Scripts and macros for the production of tracker/trigger QA trending plots, from...
authormartinez <martinez@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 21 Jun 2011 15:27:57 +0000 (15:27 +0000)
committermartinez <martinez@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 21 Jun 2011 15:27:57 +0000 (15:27 +0000)
PWG3/muon/mergeGridFiles.C [new file with mode: 0644]
PWG3/muon/runQA.sh [new file with mode: 0755]
PWG3/muon/terminateQA.C [new file with mode: 0644]
PWG3/muon/trigEffQA.C [new file with mode: 0644]

diff --git a/PWG3/muon/mergeGridFiles.C b/PWG3/muon/mergeGridFiles.C
new file mode 100644 (file)
index 0000000..942b4cf
--- /dev/null
@@ -0,0 +1,320 @@
+#if !defined(__CINT__) || defined(__MAKECINT__)
+
+#include <Riostream.h>
+
+// ROOT includes
+#include "TString.h"
+#include "TObjArray.h"
+#include "TObjString.h"
+#include "TFileMerger.h"
+#include "TGrid.h"
+#include "TList.h"
+#include "TSystem.h"
+#include "TGridResult.h"
+#include "TMap.h"
+#include "TFile.h"
+#include "TROOT.h"
+#endif
+
+Bool_t AddFileList(TString, TString&, TString);
+void ReadListFromFile(TString, TString&, TString);
+Int_t GetLastStage(TGridResult*);
+
+void mergeGridFiles(TString outFilename, TString inFileList, TString addPrefix = "alien://", Int_t nFilesPerStep = 100, Bool_t copyLocal = kTRUE, TString dirsToMerge = "")
+{
+  TString fileList = "";
+  ReadListFromFile(inFileList, fileList, addPrefix);
+
+  if ( fileList.IsNull() ) {
+    printf("List of merging files is null: Nothing done!\n");
+    return;
+  }
+
+  TString logFilename = "toBeMerged.txt";
+
+  if ( ! gGrid ) copyLocal = kFALSE;
+
+  TString currList = fileList;
+  TString currOutput = "", mergedFiles = "";
+  TFileMerger* fileMerger = 0x0;
+  TObjArray* dirsToMergeArray = 0x0;
+  TList* sourceList = new TList();
+  if ( ! dirsToMerge.IsNull() ) {
+    dirsToMergeArray = dirsToMerge.Tokenize(" ");
+    dirsToMergeArray->SetOwner();
+  }
+
+  Bool_t showProgressBar = ! gROOT->IsBatch();
+
+  for ( Int_t istep = 0; istep < 100; istep++ ) {
+    TObjArray* array = currList.Tokenize(" ");
+    array->SetOwner();
+    currList = "";
+    Int_t nFiles = array->GetEntries();
+    Int_t subStep = -1;
+    for (Int_t ifile = 0; ifile < nFiles; ifile++ ) {
+      if ( ! fileMerger ) fileMerger = new TFileMerger(copyLocal);
+      TString currFilename = array->At(ifile)->GetName();
+      Bool_t isFileAdded = fileMerger->AddFile(currFilename.Data(), showProgressBar);
+      if ( ! isFileAdded ) continue;
+      //printf("New file %s\n", gROOT->GetListOfFiles()->Last()->GetName()); // REMEMBER TO CUT
+      if ( dirsToMergeArray ) {
+        if ( ! sourceList ) sourceList = new TList();
+        sourceList->Add(gROOT->GetListOfFiles()->Last());
+      }
+      
+      Int_t nFilesToMerge = fileMerger->GetMergeList()->GetEntries();
+      if ( nFilesToMerge % nFilesPerStep != 0 && ifile < nFiles - 1 ) 
+       continue;
+      // The following part is executed only at the end of each step
+      currOutput = outFilename;
+      if ( nFiles > nFilesPerStep ) {
+       subStep++;
+       currOutput.ReplaceAll(".root",Form("_%i_%i.root", istep, subStep));
+       AddFileList(currOutput, currList, "");
+      }
+      if ( dirsToMergeArray ) {
+        TFile* outFile = new TFile(currOutput.Data(), "recreate");
+        for ( Int_t idir=0; idir<dirsToMergeArray->GetEntries(); idir++ ) {
+          outFile->cd();
+          TDirectory* currDir = outFile->mkdir(dirsToMergeArray->At(idir)->GetName());
+          fileMerger->MergeRecursive(currDir, sourceList);
+        }
+        outFile->Close();
+      }
+      else {
+        fileMerger->OutputFile(currOutput.Data());
+        fileMerger->Merge();
+      }
+      printf("\nMerged in %s:\n", currOutput.Data());
+      mergedFiles = "";
+      for ( Int_t ientry=0; ientry<nFilesToMerge; ientry++ )
+       mergedFiles += Form("%s ", fileMerger->GetMergeList()->At(ientry)->GetName());
+      printf("%s\n\n", mergedFiles.Data());
+
+      // remove merged files
+      if ( istep > 0 )
+       gSystem->Exec(Form("rm %s", mergedFiles.Data()));
+
+      delete fileMerger;
+      fileMerger = 0x0;
+      if ( dirsToMergeArray ) {
+        delete sourceList;
+        sourceList = 0x0;
+      }
+
+      // Write log file to keep trace of files to be merged
+      ofstream logFile(logFilename.Data());
+      TString logString = "";
+      for ( Int_t jfile = ifile + 1; jfile < nFiles; jfile++ ) {
+       logString += Form("%s ", array->At(jfile)->GetName());
+      }
+      logString.Append(currList.Data());
+      logString.ReplaceAll(" ", "\n");
+      logFile << logString.Data() << endl;;
+      logFile.close();
+    } // loop on files
+
+
+    delete array;
+    printf("Step %i completed!\n", istep);
+
+    if ( nFiles <= nFilesPerStep ) break;
+  } // loop on steps
+
+  gSystem->Exec(Form("rm %s", logFilename.Data()));
+}
+
+
+//___________________________________________________
+Bool_t AddFileList(TString filename, TString& fileList, TString addPrefix)
+{
+  if ( filename.IsNull() || ! filename.Contains(".root") ) return kFALSE;
+
+  if ( ! addPrefix.IsNull() && ! filename.Contains(addPrefix.Data()) )
+    filename.Prepend(addPrefix.Data());
+
+  if ( filename.Contains("alien://") && ! gGrid )
+    TGrid::Connect("alien://");
+  
+  if ( ! fileList.IsNull() )
+    fileList.Append(" ");
+  fileList.Append(filename.Data());
+
+  return kTRUE;
+}
+
+//___________________________________________________
+void ReadListFromFile(TString filename, TString& fileList, TString addPrefix)
+{
+  ifstream inFile(filename.Data());
+  TString currLine = "";
+  if ( inFile.is_open() ) {
+    while ( ! inFile.eof() ) {
+      currLine.ReadLine(inFile,kTRUE); // Read line
+      AddFileList(currLine, fileList, addPrefix);
+    }
+    inFile.close();
+  }
+}
+
+
+//___________________________________________________
+void completeProd(TString runListName="runList.txt", TString prodDir = "", TString baseDir="/alice/data/2010/LHC10h", TString outTaskFilename="QAresults.root", Int_t nFilesPerStep = 50, TString dirsToMerge = "MUON_QA MUON.TriggerEfficiencyMap", Bool_t overwriteExisting = kFALSE)
+{
+  TString outFilename = "completeFileList.txt";
+
+  // Get run list from file
+  ifstream inFile(runListName.Data());
+  TObjArray runList;
+  runList.SetOwner();
+  TString currRun;
+  Int_t minRun = 99999999;
+  Int_t maxRun = -1;
+  if (inFile.is_open()) {
+    while (! inFile.eof() ) {
+      currRun.ReadLine(inFile,kTRUE); // Read line
+      if ( currRun.IsNull() || ! currRun.IsDigit() ) continue;
+      Int_t currRunInt = currRun.Atoi();
+      minRun = TMath::Min(currRunInt, minRun);
+      maxRun = TMath::Max(currRunInt, maxRun);
+      runList.Add(new TObjString(Form("%d", currRunInt)));
+    }
+    inFile.close();
+  }
+
+  outFilename.ReplaceAll(".txt", Form("_%i_%i.txt", minRun, maxRun));
+
+  //TString filePattern[3] = {"", "Stage*/","*/"};
+  TString filePattern[2] = {"","*/"};
+
+  ofstream outFile(outFilename.Data());
+
+  if ( outTaskFilename.Contains("QAresults.root") ) {
+    const Int_t kNlibs = 5; // 1
+    //TString loadLibs[kNlibs] = {"libPWG3base.so"};
+    //TString loadLibs[kNlibs] = {"libANALYSIS.so", "libANALYSISalice.so", "libTENDER.so", "libPWG1.so", "libPWG3base.so"};
+    TString loadLibs[kNlibs] = {"libANALYSIS.so", "libOADB.so", "libANALYSISalice.so", "libCORRFW.so", "libPWG3base.so"};
+    for ( Int_t ilib=0; ilib<kNlibs; ilib++ ) {
+      Int_t exitVal = gSystem->Load(loadLibs[ilib].Data());
+      if ( exitVal < 0 ) {
+        printf("Please run with aliroot if you're merging QA objects!\n");
+        return;
+      }
+    }
+  }
+
+  if ( ! gGrid )
+    TGrid::Connect("alien://");
+
+  baseDir.ReplaceAll("alien://","");
+
+  TMap* map = 0x0;
+  TString stageName = "";
+  TString runsWithoutOut = "";
+  for ( Int_t irun=0; irun<runList.GetEntries(); irun++ ) {
+    TString currRunString = ((TObjString*)runList.At(irun))->GetString();
+
+    TString localOut = outTaskFilename;
+    localOut.ReplaceAll(".root", Form("_%s.root", currRunString.Data()));
+    printf("Searching for %s\n", localOut.Data()); // REMEMBER TO CUT
+    if ( ! gSystem->AccessPathName(localOut.Data()) ) {
+      if ( overwriteExisting )
+        printf("Overwriting existing file %s\n", localOut.Data());
+      else {
+        printf("Warning: merged file %s already exist: do not overwrite\n", localOut.Data());
+        continue;
+      }
+    }
+
+    TString tmpFilename = Form("/tmp/mergeListRun%s.txt", currRunString.Data());
+    ofstream tmpFile(tmpFilename.Data());
+    TString mergeFilename = "";
+
+    for ( Int_t ipattern=0; ipattern<2; ipattern++ ) {
+      TString command = Form("find %s/*%s %s/%s%s", baseDir.Data(), currRunString.Data(), prodDir.Data(), filePattern[ipattern].Data(), outTaskFilename.Data());
+
+      printf("%s\n", command.Data());
+
+      TGridResult* res = gGrid->Command(command);
+
+      if ( ! res || res->GetEntries() == 0 ) continue;
+
+      Int_t mergeStage = ( ipattern == 1 ) ? GetLastStage(res)  : -1;
+      stageName = Form("Stage_%i", mergeStage);
+
+      TIter nextmap(res);
+      while ( ( map = (TMap*)nextmap() ) ) {
+        // Loop 'find' results and get next LFN
+        TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
+        if (!objs || !objs->GetString().Length()) 
+          continue;
+
+        mergeFilename = objs->GetString();
+
+        if ( mergeStage > 0 && ! mergeFilename.Contains(stageName.Data()) ) continue;
+
+        tmpFile << mergeFilename.Data() << endl;
+      } // loop on grid lfns
+
+      delete res;
+
+      tmpFile.close();
+
+      // If the merging of specific directories is required
+      // run merging also if there is 1 file
+      // so that we get rid of other sub-directories
+      if ( ipattern == 1 || ! dirsToMerge.IsNull() ) {
+        mergeFilename = outTaskFilename;
+        mergeFilename.ReplaceAll(".root", Form("_%s.root", currRunString.Data()));
+        mergeGridFiles(mergeFilename, tmpFilename, "alien://", nFilesPerStep, kTRUE, dirsToMerge);
+      }
+
+      if ( ! mergeFilename.Contains("alien://") )
+        outFile << gSystem->pwd() << "/";
+      outFile << mergeFilename.Data() << endl;
+      gSystem->Exec(Form("rm %s", tmpFilename.Data()));
+      break;
+    } // loop on pattern
+    if ( mergeFilename.IsNull() ) runsWithoutOut += currRunString + " ";
+  } // loop on runs
+  if ( ! runsWithoutOut.IsNull() )
+    printf("\nNo output found in runs\n%s\n",runsWithoutOut.Data());
+  printf("\nOutput written in:\n%s\n", outFilename.Data());
+}
+
+
+//___________________________________________________
+Int_t GetLastStage(TGridResult* res)
+{
+  Int_t lastStage = 0;
+
+  TMap* map = 0x0;
+  TIter nextmap(res);
+  TString filename = "", currToken = "";
+  while ( ( map = (TMap*)nextmap() ) ) {
+    // Loop 'find' results and get next LFN
+    TObjString *objs = dynamic_cast<TObjString*>(map->GetValue("turl"));
+    if (!objs || !objs->GetString().Length()) 
+      continue;
+
+    filename = objs->GetString();
+    
+    if ( ! filename.Contains("Stage_") ) continue;
+
+    TObjArray* array = filename.Tokenize("/");
+    array->SetOwner();
+    for ( Int_t ientry=0; ientry<array->GetEntries(); ientry++ ) {
+      currToken = array->At(ientry)->GetName();
+      if ( currToken.Contains("Stage_") ) {
+        currToken.Remove(0,6);
+        Int_t currStage = currToken.Atoi();
+        lastStage = TMath::Max(currStage, lastStage);
+        break;
+      }
+    }
+    delete array;
+  } // loop on grid lfns
+
+  return lastStage;
+}
diff --git a/PWG3/muon/runQA.sh b/PWG3/muon/runQA.sh
new file mode 100755 (executable)
index 0000000..443cbd6
--- /dev/null
@@ -0,0 +1,172 @@
+#!/bin/bash
+
+qaMacroDir="$ALICE_ROOT/PWG3/muon"
+
+baseOutDir=`pwd`
+
+
+mergeLog="logMerge.txt"
+mergeOut=""
+terminateDir="${baseOutDir}/terminateRuns"
+outTaskName="QAresults.root"
+
+execMerge=1
+execMergeAll=1
+execTerminate=1
+execTrigQA=1
+execTrackQA=1
+while getopts "matek" option
+do
+  case $option in
+    m ) execMerge=0;;
+    a ) execMergeAll=0;;
+    t ) execTerminate=0;;
+    e ) execTrigQA=0;;
+    k ) execTrackQA=0;;
+    * ) echo "Unimplemented option chosen."
+    EXIT=1
+    ;;
+  esac
+done
+
+shift $(($OPTIND - 1))
+
+# needs 3 arguments
+if [[ $# -ne 3 || "$EXIT" -eq 1 ]]; then
+    echo "Usage: `basename $0` (-matek) <runList.txt> <QAx> <alien:///alice/data/20XX>/LHCXXy>"
+    echo "       -m skip merging (default: run)"
+    echo "       -a skip final merging (default: run)"
+    echo "       -t skip terminate (default: run)"
+    echo "       -e skip run trigger efficiency QA (defult: run)"
+    echo "       -k skip run muon QA (defult: run)"
+    exit 4
+fi
+
+loadLibs="gSystem->Load(\"libANALYSIS.so\");gSystem->Load(\"libOADB.so\");gSystem->Load(\"libANALYSISalice.so\");gSystem->Load(\"libCORRFW.so\");gSystem->Load(\"libPWG3base.so\");"
+
+function mergePerRun()
+{
+    echo "Merging each run..."
+    cd $baseOutDir
+    runListName="$1"
+    prodDir="$2"
+    alienBaseDir="$3"
+    aliroot -b <<EOF &> $mergeLog
+.L $qaMacroDir/mergeGridFiles.C+
+completeProd("${runListName}","${prodDir}","${alienBaseDir}","${outTaskName}",50,"MUON_QA MUON.TriggerEfficiencyMap");
+.q
+EOF
+}
+
+function mergeRuns()
+{
+    echo "Merge all runs"
+    cd $baseOutDir
+    fileListName=$1
+    outFilename=$2
+    aliroot -b <<EOF &> logMergeAll.txt
+${loadLibs}
+gSystem->Load("libANALYSIS.so");gSystem->Load("libOADB.so");gSystem->Load("libANALYSISalice.so");gSystem->Load("libCORRFW.so");gSystem->Load("libPWG3base.so");
+.x $qaMacroDir/mergeGridFiles.C+("${outFilename}","${fileListName}","");
+.q
+EOF
+    
+}
+
+function terminateRuns()
+{
+    echo "Terminating runs..."
+    cd $baseOutDir
+    currList=`cat $1 | xargs`
+    if [ ! -d $terminateDir ]; then
+       mkdir $terminateDir
+    fi
+    for file in $currList; do
+       cd $terminateDir
+       aliroot -b <<EOF &> logCopy.txt
+.L $qaMacroDir/terminateQA.C+
+CopyFile("$file","$terminateDir",1,"${outTaskName}")
+.q 
+EOF
+       outDir=`grep outDir logCopy.txt | cut -d ":" -f 2`
+       #outFile=`grep outFile logCopy.txt | cut -d ":" -f 2`
+       forceTerminate=`grep -c "run number not found" logCopy.txt`
+
+       rm logCopy.txt
+
+       cd $outDir
+       #ln -s $qaMacroDir/SetAlienHandler.C
+
+
+       aliroot -b <<EOF &> logTerminate.txt
+.x $qaMacroDir/terminateQA.C("${outTaskName}",$forceTerminate)
+.q
+EOF
+       rm logTerminate.txt
+       #.x $qaMacroDir/runAnalysisTask.C("terminate","grid terminate","",kFALSE,"${outTaskName}");
+
+       #if [ -L "SetAlienHandler.C" ]; then
+       #rm SetAlienHandler.C
+       #fi
+       if [ -e "outputs_valid" ]; then
+           rm outputs_valid
+       fi
+       cd $baseOutDir
+    done
+}
+
+function runTrigQA() {
+    echo "Running trigger QA"
+    cd $baseOutDir
+    runListName="$1"
+    outFileName="$2"
+    aliroot -b <<EOF &> logTrigEffQA.txt
+.x $qaMacroDir/trigEffQA.C+("${runListName}","${outFileName}");
+.q
+EOF
+}
+
+function runTrackQA() {
+    echo "Running tracker QA"
+    cd $terminateDir
+    physSel="$1"
+    alienBaseDir="$2"
+    lhcPeriod=`echo ${alienBaseDir%"/"} | awk -F "/" ' { print $NF } '`
+    aliroot -b <<EOF &> logTrackQA.txt
+${loadLibs}
+.x $qaMacroDir/PlotMuonQA.C+("${terminateDir}",0x0,$physSel,"$lhcPeriod","${outTaskName}");
+.q
+EOF
+    cd $baseOutDir
+}
+
+if [ $execMerge -eq 1 ]; then
+    mergePerRun $1 $2 $3
+fi
+mergeOut=`grep -A 1 "Output written" ${mergeLog} | grep -v written`
+mergeOutAll=${mergeOut//".txt"/"_merged.txt"}
+
+if [ $execMergeAll -eq 1 ]; then
+    mergeRuns $mergeOut "QAresults_Merged.root"
+    cp -p $mergeOut $mergeOutAll
+    echo "${baseOutDir}/QAresults_Merged.root" >> $mergeOutAll
+fi
+
+if [ ! -e $mergeOutAll ]; then
+    mergeOutAll=$mergeOut
+fi
+
+if [ $execTerminate -eq 1 ]; then
+    terminateRuns $mergeOutAll
+fi
+
+if [ $execTrigQA -eq 1 ]; then
+    minRun=`echo ${mergeOut} | cut -d "_" -f 2`
+    maxRun=`echo ${mergeOut} | cut -d "_" -f 3 | cut -d "." -f 1`
+    outName="trigEffQA_${minRun}_${maxRun}_$2.root"
+    runTrigQA "${mergeOut}" "${outName}"
+fi
+
+if [ $execTrackQA -eq 1 ]; then
+    runTrackQA 1 $3
+fi
diff --git a/PWG3/muon/terminateQA.C b/PWG3/muon/terminateQA.C
new file mode 100644 (file)
index 0000000..6a565cd
--- /dev/null
@@ -0,0 +1,164 @@
+#if !defined(__CINT__) || defined(__MAKECINT__)
+// ROOT includes
+#include "TFile.h"
+#include "TGrid.h"
+#include "TString.h"
+#include "TObjArray.h"
+#include "TObjString.h"
+#include "TSystem.h"
+#include "TROOT.h"
+
+// Aliroot includes
+#include "AliAnalysisManager.h"
+#include "AliAnalysisAlien.h"
+#include "AliESDInputHandler.h"
+
+#define COMPILEMACRO
+
+#endif
+
+
+//_____________________________________________________________________________
+Int_t GetRunNumber(TString filePath)
+{
+  TObjArray* array = filePath.Tokenize("/");
+  array->SetOwner();
+  TString auxString = "";
+  Int_t runNum = -1;
+  for ( Int_t ientry=0; ientry<array->GetEntries(); ientry++ ) {
+    auxString = array->At(ientry)->GetName();
+    if ( auxString.Contains("000") ) {
+      runNum = auxString.Atoi();
+      break;
+    }
+  }
+  delete array;
+
+  if ( runNum < 0 ) {
+    array = auxString.Tokenize("_");
+    array->SetOwner();
+    auxString = array->Last()->GetName();
+    auxString.ReplaceAll(".root","");
+    if ( auxString.IsDigit() )
+      runNum = auxString.Atoi();
+    delete array;
+  }
+
+  return runNum;
+}
+
+//_____________________________________________________________________________
+void CopyFile(TString inFilename, TString baseOutDir=".", Bool_t makeRunDir=kTRUE, TString changeFilename="")
+{
+  if ( inFilename.Contains("alien://") && ! gGrid )
+    TGrid::Connect("alien://");
+
+  TObjArray* array = inFilename.Tokenize("/");
+  array->SetOwner();
+  TString outFilename = changeFilename.IsNull() ? array->Last()->GetName() : changeFilename.Data();
+  delete array;
+
+  if ( makeRunDir ) {
+    Int_t runNumber = GetRunNumber(inFilename);
+    if ( runNumber >= 0 ) {
+      baseOutDir = Form("%s/%i", baseOutDir.Data(), runNumber);
+      if ( gSystem->AccessPathName(baseOutDir.Data()) )
+        gSystem->mkdir(baseOutDir.Data());
+    }
+    else printf("Warning: run number not found!\n");
+  }
+  //outFilename.ReplaceAll(".root", Form("_%i.root", runNumber));
+  outFilename.Prepend(Form("%s/", baseOutDir.Data()));
+  Bool_t showProgressBar = ! gROOT->IsBatch();
+  TFile::Cp(inFilename.Data(), outFilename.Data(), showProgressBar);
+  printf("outDir: %s\n", baseOutDir.Data());
+  printf("outFile: %s\n", outFilename.Data());
+}
+
+
+
+//_____________________________________________________________________________
+AliAnalysisAlien* CreateAlienHandler()
+{
+  AliAnalysisAlien *plugin = new AliAnalysisAlien();
+  
+  // Set the run mode
+  plugin->SetRunMode("terminate");
+
+  // Declare all libraries
+  plugin->SetAdditionalLibs("libCORRFW.so libPWG3base.so libPWG3muon.so");
+
+  plugin->SetAdditionalRootLibs("libXMLParser.so libGui.so libProofPlayer.so");
+
+  plugin->AddIncludePath("-I.");
+  plugin->AddIncludePath("-I$ALICE_ROOT/PWG3/base");
+  plugin->AddIncludePath("-I$ALICE_ROOT/PWG3/muon");
+  
+  return plugin;
+}
+
+
+//_____________________________________________________________________________
+void terminateQA(TString outfilename = "QAresults.root", Bool_t force = kFALSE)
+{
+  //
+  // Load common libraries
+  //
+  gSystem->Load("libTree");
+  gSystem->Load("libGeom");
+  gSystem->Load("libVMC");
+  gSystem->Load("libPhysics");
+  gSystem->Load("libProof");
+
+  TString libsList = "libANALYSIS.so libOADB.so libANALYSISalice.so libCORRFW.so libPWG3base.so libPWG3muon.so";
+
+  TObjArray* libsArray = libsList.Tokenize(" ");
+  libsArray->SetOwner();
+  TString currLib = "";
+  for ( Int_t ilib=0; ilib<libsArray->GetEntries(); ilib++ ) {
+    currLib = libsArray->At(ilib)->GetName();
+    gSystem->Load(currLib.Data());
+  }
+
+  AliAnalysisAlien* alienHandler = CreateAlienHandler();
+
+  AliAnalysisManager* mgr = new AliAnalysisManager("testAnalysis");
+  mgr->SetCommonFileName(outfilename.Data());
+  mgr->SetGridHandler(alienHandler);
+
+  // Needed to the manager (but not used in terminate mode)
+  AliESDInputHandler* esdH = new AliESDInputHandler();
+  esdH->SetReadFriends(kFALSE);
+  mgr->SetInputEventHandler(esdH); 
+
+ #ifndef COMPILEMACRO
+  gROOT->LoadMacro("$ALICE_ROOT/PWG3/muon/AddTaskMuonQA.C");
+  AliAnalysisTaskMuonQA* muonQATask = AddTaskMuonQA();
+
+  gROOT->LoadMacro("$ALICE_ROOT/PWG1/macros/AddTaskMTRchamberEfficiency.C");
+  AliAnalysisTaskTrigChEff* trigChEffTask = AddTaskMTRchamberEfficiency();
+#endif
+
+  // Check if terminate was already performed
+  if  ( ! force ) {
+    TObject* paramContainer = mgr->GetParamOutputs()->At(0);
+    if ( paramContainer ) {
+      TFile* file = TFile::Open(outfilename);
+      if ( file->FindObjectAny(paramContainer->GetName() ) ) {
+        printf("\nTerminate was already executed!\n");
+        printf("Nothing to be done\n");
+        file->Close();
+        return;
+      }
+      file->Close();
+    }
+  }
+
+
+  if ( ! mgr->InitAnalysis()) {
+    printf("Fatal: Cannot initialize analysis\n");
+    return;
+  }
+  mgr->PrintStatus();
+  mgr->StartAnalysis("grid terminate");
+}
diff --git a/PWG3/muon/trigEffQA.C b/PWG3/muon/trigEffQA.C
new file mode 100644 (file)
index 0000000..fa0d52a
--- /dev/null
@@ -0,0 +1,410 @@
+#if !defined(__CINT__) || defined(__MAKECINT__)
+// ROOT includes
+#include "TFile.h"
+#include "TH1.h"
+#include "TH2.h"
+#include "TGraphAsymmErrors.h"
+#include "TSystem.h"
+#include "Riostream.h"
+#include "TCanvas.h"
+#include "TStyle.h"
+#include "TROOT.h"
+#include "TLine.h"
+#include "TLegend.h"
+#include "TPaveLabel.h"
+#include "TMath.h"
+#include "TObjArray.h"
+#include "TObjString.h"
+#include "TString.h"
+#include "TGrid.h"
+
+#include "AliCDBManager.h"
+#include "AliCDBEntry.h"
+#include "AliCDBPath.h"
+#include "AliMUONTriggerEfficiencyCells.h"
+#include "AliMUONTriggerChamberEfficiency.h"
+#endif
+
+const Int_t kNch = 4;
+void SetMyStyle();
+Int_t GetRunNumber(TString);
+//Double_t GetBinomial(Double_t*, Double_t* eff2 = 0x0, Double_t* effBoth = 0x0);
+Double_t* GetBinomial(Double_t*, Double_t* effErr2 = 0x0, Double_t* effErrBoth = 0x0);
+Double_t* GetProdErr(Double_t*, Int_t, Int_t nFactors=kNch);
+Double_t* GetConditionalEffErr(Double_t*, Double_t*, Double_t*, Int_t exclude=-1);
+TH1* GetHisto(TString, TFile*, TList*);
+
+void trigEffQA(TString fileListName, TString outFilename = "")
+{
+  ifstream inFile(fileListName.Data());
+  TObjArray fileNameArray, runNumArray;
+  fileNameArray.SetOwner();
+  runNumArray.SetOwner();
+  TString currString = "";
+  if (inFile.is_open()) {
+    while (! inFile.eof() ) {
+      currString.ReadLine(inFile,kTRUE); // Read line
+      if ( currString.IsNull() || ! currString.Contains(".root") || 
+           currString.BeginsWith("#") ) continue;
+      fileNameArray.AddLast(new TObjString(currString.Data()));
+      Int_t runNum = GetRunNumber(currString);
+      runNumArray.AddLast(new TObjString(Form("%i",runNum)));
+    }
+    inFile.close();
+  }
+  else {
+    printf("Fatal: cannot open input file\n");
+    return;
+  }
+
+  runNumArray.Sort();
+
+  //TString elementName[2] = {"Board", "RPC"};
+  TString countTypeName[3] = {"bendPlane", "nonBendPlane","bothPlanes"};
+
+  TObjArray chEffList(13);
+
+  TCanvas* can = 0x0;
+  TString filename = "", histoName = "", histoTitle = "";
+
+  histoName = "totalEffEvolution";
+  histoTitle = "Multinomial probability of firing at least 3/4 chambers";
+  TH1* totalEff = new TH1D(histoName.Data(), histoTitle.Data(), 0, 0., 1.);
+  chEffList.AddAtAndExpand(totalEff, 12);
+
+  SetMyStyle();
+  Double_t effValues[3][2*kNch];
+
+  TString runNumString = "";
+  for ( Int_t irun=0; irun<runNumArray.GetEntries(); irun++ ) {
+    runNumString = runNumArray.At(irun)->GetName();
+
+    // Search corresponding file (for sorting)
+    for ( Int_t ifile=0; ifile<fileNameArray.GetEntries(); ifile++ ) {
+      filename = fileNameArray.At(ifile)->GetName();
+      if ( filename.Contains(runNumString.Data()) ) break;
+    }
+
+    if ( filename.Contains("alien://") && ! gGrid )
+      gGrid->Connect("alien://");
+
+    TFile* file = TFile::Open(filename.Data());
+    if ( ! file ) {
+      printf("Warning: cannot find %s\n", filename.Data());
+      continue;
+    }
+    TList* trigEffList = (TList*)file->FindObjectAny("triggerChamberEff");
+    if ( ! trigEffList )
+      printf("Warning: histo list not found in %s. Check directly in file\n", filename.Data());
+
+    TH1* histoDen = GetHisto("allTracksCountChamber", file, trigEffList);
+    if ( ! histoDen ) {
+      printf("Error: cannot find histograms in file %s. Skip to next\n", filename.Data());
+      continue;
+    }
+    for(Int_t icount=0; icount<AliMUONTriggerEfficiencyCells::kNcounts-1; icount++) {
+      histoName = countTypeName[icount] + "CountChamber";
+      TH1* histoNum = GetHisto(histoName, file, trigEffList);
+      TGraphAsymmErrors* graph = new TGraphAsymmErrors(histoNum, histoDen);
+      Double_t xpt, ypt;
+      for ( Int_t ich=0; ich<kNch; ich++ ) {
+        graph->GetPoint(ich, xpt, ypt);
+        effValues[icount][ich] = ypt;
+        Int_t ihisto = kNch*icount+ich;
+        TH1* chEff = (TH1*)chEffList.At(ihisto);
+        if ( ! chEff ) {
+          histoName = Form("effEvolution%sCh%i", countTypeName[icount].Data(), 11+ich);
+          histoTitle = Form("Efficiency of trigger chamber %i", 11+ich);
+          chEff = new TH1D(histoName.Data(), histoTitle.Data(), 0, 0., 1.);
+          chEffList.AddAtAndExpand(chEff, ihisto);
+        }
+        Int_t currBin = chEff->Fill(runNumString.Data(), ypt);
+        Double_t err = 0.5*(graph->GetErrorYlow(ich) + graph->GetErrorYhigh(ich));
+        chEff->SetBinError(currBin, err);
+        effValues[icount][ich+kNch] = err;
+      } // loop on chambers
+    } // loop on counts
+    Double_t* binomialEff = GetBinomial(effValues[0], effValues[1], effValues[2]);
+    Int_t currBin = totalEff->Fill(runNumString, binomialEff[0]);
+    // CAVEAT!!!!
+    // Well, error calculation of the binomial efficiency is a mess...
+    // Sometimes it happens that efficiency + error > 1.
+    // In that case reduce the error.
+    totalEff->SetBinError(currBin, TMath::Min(binomialEff[1], 1.-binomialEff[0]));
+    delete binomialEff;
+  } // loop on runs
+
+  TString outCanName = outFilename;
+  outCanName.ReplaceAll(".root",".pdf");
+  TString canName = "";
+  canName = "totalEff";
+  can = new TCanvas(canName.Data(), canName.Data(), 200, 10, 600, 600);
+  if ( ! outCanName.IsNull() )
+    can->Print(Form("%s[", outCanName.Data())); // Open pdf file
+
+  // Set correct range (do not show last empty bins)
+  for ( Int_t ihisto=0; ihisto<chEffList.GetEntries(); ihisto++ ) {
+    TH1* histo = (TH1*)chEffList.At(ihisto);
+    histo->GetXaxis()->SetRange(1,fileNameArray.GetEntries());
+  }
+
+  TH1* totEff = (TH1*)chEffList.At(12);
+  totEff->GetYaxis()->SetRangeUser(0.,1.1);
+  totEff->GetYaxis()->SetTitle("Probability to satisfy trigger conditions (3/4)");
+  totEff->SetStats(kFALSE);
+  totEff->DrawCopy();
+  if ( ! outCanName.IsNull() )
+    can->Print(outCanName.Data());
+
+  Int_t color[3] = {kBlack, kRed, kBlue};
+  Int_t markStyle[3] = {20, 24, 26};
+  TLegend* leg = 0x0;
+
+  for ( Int_t ich=0; ich<kNch; ich++ ) {
+    canName = Form("trigEffCh%i", 11+ich);
+    can = new TCanvas(canName.Data(), canName.Data(), 200, 10, 600, 600);
+    can->SetGridy();
+    leg = new TLegend(0.6, 0.2, 0.9, 0.4);
+    leg->SetBorderSize(1);
+    //can->Divide(2,2);
+    TString drawOpt = "e";
+    for(Int_t icount=0; icount<AliMUONTriggerEfficiencyCells::kNcounts-1; icount++) {
+      //can->cd(icount+1);
+      TH1* chEff = (TH1*)chEffList.At(4*icount+ich);
+      chEff->GetYaxis()->SetRangeUser(0.48,1.05);
+      chEff->SetStats(kFALSE);
+      chEff->GetYaxis()->SetTitle("Trigger chamber efficiency");
+      TH1* copyEff = chEff->DrawCopy(drawOpt.Data());
+      copyEff->SetLineColor(color[icount]);
+      copyEff->SetMarkerColor(color[icount]);
+      copyEff->SetMarkerStyle(markStyle[icount]);
+      leg->AddEntry(copyEff, countTypeName[icount].Data(), "lp");
+      drawOpt = "esame";
+    } // loop on counts
+    leg->Draw("same");
+    if ( ! outCanName.IsNull() )
+      can->Print(outCanName.Data());
+  } // loop on chambers
+  if ( ! outCanName.IsNull() ) {
+    can->Print(Form("%s]", outCanName.Data())); // close pdf file
+    // There is a bug when creating a pdf
+    // So create a ps and then convert via epstopdf
+    if ( outCanName.Contains(".ps") || outCanName.Contains(".eps") ) {
+      gSystem->Exec(Form("epstopdf %s", outCanName.Data()));
+      gSystem->Exec(Form("rm %s", outCanName.Data()));
+    }
+  }
+
+  TFile* outFile = 0x0;
+  if ( ! outFilename.IsNull() ) {
+    outFile = new TFile(outFilename.Data(), "recreate");
+    chEffList.Write();
+    outFile->Close();
+  }
+}
+
+
+//_____________________________________________________________________________
+void SetMyStyle()
+{
+    gStyle->SetCanvasColor(10);
+    gStyle->SetFrameFillColor(10);
+    gStyle->SetStatColor(10);
+    gStyle->SetFillColor(10);
+    gStyle->SetTitleFillColor(10);
+
+    gStyle->SetTitleXSize(0.03);
+    gStyle->SetTitleXOffset(1.1);
+    gStyle->SetTitleYSize(0.03);
+    gStyle->SetTitleYOffset(1.9);
+
+    gStyle->SetMarkerSize(0.7);
+    gStyle->SetHistLineWidth(2);
+
+    gStyle->SetPadLeftMargin(0.12);
+    gStyle->SetPadRightMargin(0.04);
+    gStyle->SetPadBottomMargin(0.08);
+    gStyle->SetPadTopMargin(0.08);
+
+    gROOT->ForceStyle();    
+}
+
+//_____________________________________________________________________________
+Int_t GetRunNumber(TString filePath)
+{
+  TObjArray* array = filePath.Tokenize("/");
+  array->SetOwner();
+  TString auxString = "";
+  Int_t runNum = -1;
+  for ( Int_t ientry=0; ientry<array->GetEntries(); ientry++ ) {
+    auxString = array->At(ientry)->GetName();
+    if ( auxString.Contains("000") ) {
+      runNum = auxString.Atoi();
+      break;
+    }
+  }
+  delete array;
+
+  if ( runNum < 0 ) {
+    array = auxString.Tokenize("_");
+    array->SetOwner();
+    auxString = array->Last()->GetName();
+    auxString.ReplaceAll(".root","");
+    runNum = auxString.Atoi();
+    delete array;
+  }
+
+  return runNum;
+}
+
+
+// //_____________________________________________________________________________
+// Double_t GetBinomial(Double_t* eff1, Double_t* eff2, Double_t* effBoth)
+// {
+//   Double_t binomialEff = 0.;
+//   Double_t eff44 = 1.;
+//   Double_t auxEff[4];
+//   Double_t auxBinomial = 1.;
+
+//   // All chamber efficient
+//   for ( Int_t ich=0; ich<4; ich++ ) {
+//     eff44 *= eff1[ich];
+//   }
+//   if ( eff2 ) {
+//     for ( Int_t ich=0; ich<4; ich++ ) {
+//       auxEff[ich] = ( eff1[ich] > 0. ) ? effBoth[ich]/eff1[ich] : 0.;
+//     }
+//     auxBinomial = GetBinomial(auxEff);
+//     eff44 *= auxBinomial;
+//   }
+
+//   binomialEff += eff44;
+
+//   // 1 chamber inefficient
+//   for ( Int_t ich=0; ich<4; ich++ ) {
+//     Double_t eff34 = 1.;
+//     for ( Int_t jch=0; jch<4; jch++ ) {
+//       eff34 *= ( ich == jch ) ? ( 1. - eff1[jch] ) : eff1[jch];
+//     }
+//     if ( eff2 ) {
+//       for ( Int_t jch=0; jch<4; jch++ ) {
+//         if ( ich == jch ) {
+//           auxEff[jch] = ( eff1[jch] < 1. ) ? ( eff2[jch] - effBoth[jch] ) / ( 1. - eff1[jch]) : 0.;
+//         }
+//         else {
+//           auxEff[jch] = ( eff1[ich] > 0. ) ? effBoth[ich]/eff1[ich] : 0.;
+//         }
+//         auxBinomial = GetBinomial(auxEff);
+//         eff34 *= auxBinomial;
+//       }
+//     }
+
+//     binomialEff += eff34;
+//   }
+
+//   return binomialEff;
+// }
+
+
+//_____________________________________________________________________________
+Double_t* GetBinomial(Double_t* effErr1, Double_t* effErr2, Double_t* effErrBoth)
+{
+  Double_t effProd[4];
+  Double_t defaultEffErr[2] = {1.,0.};
+  Double_t* auxBinomial = 0x0;
+  Double_t* currEffErr44 = 0x0;
+  Double_t* effErrBinomial = new Double_t[2];
+  effErrBinomial[0] = 0.;
+  effErrBinomial[1] = 0.;
+
+  for ( Int_t ich = -1; ich<kNch; ich++ ) {
+    Double_t* currEffErr = GetProdErr(effErr1, ich);
+    if ( ich >= 0 ) {
+      currEffErr[0] = currEffErr[0] - currEffErr44[0];
+      currEffErr[1] = TMath::Sqrt(currEffErr[1]*currEffErr[1] + currEffErr44[1]*currEffErr44[1]);
+    }
+    if ( effErr2 ) {
+      Double_t* auxEffErr = GetConditionalEffErr(effErr1, effErr2, effErrBoth, ich);
+      auxBinomial = GetBinomial(auxEffErr);
+      delete auxEffErr;
+    }
+    for ( Int_t ival=0; ival<2; ival++ ) {
+      effProd[2*ival] = currEffErr[ival];
+      effProd[2*ival+1] = ( effErr2 ) ? auxBinomial[ival] : defaultEffErr[ival];
+    }
+    if ( ich < 0 ) currEffErr44 = currEffErr;
+    else delete currEffErr;
+    delete auxBinomial;
+
+    Double_t* effErr = GetProdErr(effProd, -1, 2);
+    //printf("%f * %f = %f\n", effProd[0], effProd[1], effErr[0]); // REMEMBER TO CUT
+    effErrBinomial[0] += effErr[0];
+    effErrBinomial[1] += effErr[1]*effErr[1];
+    delete effErr;
+  } // loop on chambers
+
+  delete currEffErr44;
+
+  effErrBinomial[1] = TMath::Sqrt(effErrBinomial[1]);
+
+  return effErrBinomial;
+}
+
+//_____________________________________________________________________________
+Double_t* GetProdErr(Double_t* effErr, Int_t exclude, Int_t nFactors)
+{
+  Double_t prod = 1.;
+  Double_t relErr = 0., relProdErrSquare = 0.;
+  for ( Int_t iprod=0; iprod<nFactors; iprod++ ) {
+    if ( iprod == exclude ) continue;
+    prod *= effErr[iprod];
+    relErr = ( effErr[iprod] > 0. ) ? effErr[iprod+nFactors]/effErr[iprod] : 0.;
+    relProdErrSquare += relErr*relErr;
+    //printf("%f +- %f  ", effErr[iprod], effErr[iprod+nFactors]); // REMEMBER TO CUT
+  }
+  Double_t* prodErr = new Double_t[2];
+  prodErr[0] = prod;
+  prodErr[1] = prod*TMath::Sqrt(relProdErrSquare);
+  //printf("-> %f %f\n", prodErr[0], prodErr[1]); // REMEMBER TO CUT
+  return prodErr;
+}
+
+
+//_____________________________________________________________________________
+Double_t* GetConditionalEffErr(Double_t* effErr1, Double_t* effErr2, Double_t* effErrBoth, Int_t exclude)
+{
+  Double_t* effErr = new Double_t[2*kNch];
+  for ( Int_t ich=0; ich<kNch; ich++ ) {
+    if ( ich == exclude ) {
+      effErr[ich] = ( effErr1[ich] < 1. ) ? ( effErr2[ich] - effErrBoth[ich] ) / ( 1. - effErr1[ich] ) : 0.;
+      effErr[ich+kNch] = 0;
+      if ( effErr1[ich] < 1. ) {
+        Double_t err2 = effErr2[ich+kNch] / ( 1. - effErr1[ich] );
+        Double_t errBoth = effErrBoth[ich+kNch] / ( 1. - effErr1[ich] );
+        Double_t err1 = effErr1[ich+kNch] * effErr[ich] / ( 1. - effErr1[ich] );
+        effErr[ich+kNch] = TMath::Sqrt(err2*err2 + errBoth*errBoth + err1*err1);
+      }
+    }
+    else {
+      effErr[ich] = ( effErr1[ich] > 0. ) ? effErrBoth[ich]/effErr1[ich] : 0.;
+      Double_t relErr1 = ( effErr1[ich] > 0. ) ? effErr1[ich+kNch]/effErr1[ich] : 0.;
+      Double_t relErrBoth = ( effErrBoth[ich] > 0. ) ? effErrBoth[ich+kNch]/effErrBoth[ich] : 0.;
+      effErr[ich+kNch] = effErr[ich] * TMath::Sqrt(relErr1*relErr1 + relErrBoth*relErrBoth);
+    }
+    //printf("%f  %f  %f -> %f\n", effErr1[ich], effErr2[ich], effErrBoth[ich], effErr[ich]); // REMEMBER TO CUT
+  } // loop on chambers
+  return effErr;
+}
+
+
+//_____________________________________________________________________________
+TH1* GetHisto(TString histoName, TFile* file, TList* histoList)
+{
+  TH1* histo = 0x0;
+  if ( histoList )
+    histo = (TH1*)histoList->FindObject(histoName.Data());
+  else 
+    histo = (TH1*)file->FindObjectAny(histoName.Data());
+  
+  return histo;
+}