Adding scripts and macros for EMCAL automatic QA and trending
authorshabetai <alexandre.shabetai@cern.ch>
Tue, 22 Jul 2014 09:21:04 +0000 (11:21 +0200)
committermgermain <marie.germain@subatech.in2p3.fr>
Tue, 22 Jul 2014 13:46:40 +0000 (15:46 +0200)
PWGPP/EMCAL/QA/macros/CopyQAFile.C [new file with mode: 0644]
PWGPP/EMCAL/QA/macros/CreateEMCALRunQA.C [new file with mode: 0644]
PWGPP/EMCAL/QA/macros/MakeQAPdf.C [new file with mode: 0644]
PWGPP/EMCAL/QA/macros/PlotEMCALQATrendingTree.C [new file with mode: 0644]
PWGPP/EMCAL/QA/macros/runEMCALQA.pl [new file with mode: 0755]
PWGPP/QA/detectorQAscripts/EMC.sh [new file with mode: 0755]

diff --git a/PWGPP/EMCAL/QA/macros/CopyQAFile.C b/PWGPP/EMCAL/QA/macros/CopyQAFile.C
new file mode 100644 (file)
index 0000000..85cb33a
--- /dev/null
@@ -0,0 +1,106 @@
+#if !defined(__CINT__) || defined(__MAKECINT__)
+#include "TSystem.h"
+#include "Riostream.h"
+#include "TEnv.h"
+#include "TROOT.h"
+#include "TGrid.h"
+#include "TSystem.h"
+#include "TFile.h"
+#include "TError.h"
+#endif
+
+// copy a QAresult.root file from alien to a local directory and check it. 
+
+//_____________________________________________________________________________
+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.Length() == 9 && auxString.IsDigit() ) {
+      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;
+}
+
+//_____________________________________________________________________________
+
+Int_t CopyQAFile(TString inFilename, TString baseOutDir=".", Bool_t makeRunDir=kTRUE, TString changeFilename="", Int_t timeOut = 10)
+{
+
+  gSystem->Setenv("XRDCLIENTMAXWAIT",Form("%d",timeOut));
+  gEnv->SetValue("XNet.RequestTimeout", timeOut);
+  gEnv->SetValue("XNet.ConnectTimeout", timeOut);
+  gEnv->SetValue("XNet.TransactionTimeout", timeOut);
+  TFile::SetOpenTimeout(timeOut);
+
+
+  if ( inFilename.Contains("alien://") && ! gGrid )
+
+    if (! TGrid::Connect("alien://")) {
+      Error(__FUNCTION__,"Error connecting to alien");
+      return -1;
+    }
+
+  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 Warning(__FUNCTION__,"run number not found!");
+  }
+  outFilename.Prepend(Form("%s/", baseOutDir.Data()));
+  Bool_t showProgressBar = ! gROOT->IsBatch();
+  if ( gSystem->AccessPathName(outFilename.Data())) {
+    if (! TFile::Cp(inFilename.Data(), outFilename.Data(), showProgressBar)) {
+      Error(__FUNCTION__,"Error copying the file from alien");
+      return -2;
+    }
+  }
+
+  printf("file: %s\n", inFilename.Data());
+  printf("outDir: %s\n", baseOutDir.Data());
+  printf("outFile: %s\n", outFilename.Data());
+
+  gErrorIgnoreLevel = kWarning +1; 
+  TFile f(outFilename.Data());
+  gErrorIgnoreLevel = -1;
+   
+  if (f.IsZombie()) {
+    Error(__FUNCTION__,"Error opening outFile");
+    return -3;
+  }
+
+  if (f.TestBit(TFile::kRecovered)) {
+    Info(__FUNCTION__,"The file is likely to be corrupted");
+    return -4;
+  }
+
+  return 0; 
+}
+
diff --git a/PWGPP/EMCAL/QA/macros/CreateEMCALRunQA.C b/PWGPP/EMCAL/QA/macros/CreateEMCALRunQA.C
new file mode 100644 (file)
index 0000000..a44f26a
--- /dev/null
@@ -0,0 +1,986 @@
+#if !defined(__CINT__) || defined(__MAKECINT__) 
+#include <Riostream.h>
+#include "AliEMCALGeometry.h"
+#include <TColor.h>
+#include <TStyle.h>
+#include <TSystem.h>
+#include <TDirectory.h>
+#include <TF1.h>
+#include <TFile.h>
+#include <TH2F.h>
+#include <TCanvas.h>
+#include <TGraphErrors.h>
+#include <TLegend.h>
+#include <TTree.h>
+#include <TPRegexp.h>
+#include <TList.h>
+#include <TObjString.h>
+#include <TDatime.h>
+#include <TError.h>
+#include <AliLog.h>
+#endif
+
+// This macro produces runLevelQA for EMCAL from a QAresults.root file
+// Authors: Y. Mao, A. Mas, M. Germain & A.Shabetai  SUBATECH
+// re-factored for automatic QA processing A.SHABETAI
+
+Int_t DrawOccupancy(Long_t run, TString period, TString pass, TString fTrigger, TString system, TFile* f, TFile* fout, AliEMCALGeometry* geom, Int_t SavePlots);
+Int_t DrawRun(Long_t run, TString period, TString pass, TString fTrigger, TFile *f, TFile* fout, Int_t SavePlots, Int_t nSM , Bool_t kFilter);
+Int_t TrendingEMCALTree(Long_t RunId,TString fCalorimeter,TString system,TString period , TString pass,const int n ,TList* TriggersList,TFile* f,TFile *fout, Int_t SavePlots);
+
+TH2F* FormatRunHisto(TH2F* aHisto,const char* title,const char* YTitle="");
+TH2F* HistoPerMod(TH2F* name,const char* title);
+TH2F* AutoZoom(TH2F* H,Option_t* aType="all", Int_t EntryMin=0);
+int FindNumberOfSM(TFile* f, TString fTrigger,TString period);
+
+TString QAPATH;
+TString QAPATHF = "./";
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+void set_plot_style()
+{
+  const Int_t NRGBs = 5;
+  const Int_t NCont = 255;
+
+  Double_t stops[NRGBs] = { 0.00, 0.34, 0.61, 0.84, 1.00 };
+  Double_t red[NRGBs]   = { 0.00, 0.00, 0.87, 1.00, 0.51 };
+  Double_t green[NRGBs] = { 0.00, 0.81, 1.00, 0.20, 0.00 };
+  Double_t blue[NRGBs]  = { 0.51, 1.00, 0.12, 0.00, 0.00 };
+  TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont);
+  gStyle->SetNumberContours(NCont);
+
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+Double_t pi0massP2(Double_t *x, Double_t *par)
+{
+  Double_t gaus;
+
+  if (par[2] != 0.) gaus = par[0] * TMath::Exp( -(x[0]-par[1])*(x[0]-par[1]) / (2*par[2]*par[2]) );
+
+  else gaus = 99999999.;
+
+  Double_t back = par[3] + par[4]*x[0] + par[5]*x[0]*x[0];
+
+  return gaus+back;
+
+}
+
+//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+Double_t pi0massP1(Double_t *x, Double_t *par)
+{
+  Double_t gaus = par[0] * TMath::Exp( -(x[0]-par[1])*(x[0]-par[1]) / (2*par[2]*par[2]) );
+
+  Double_t back = par[3] + par[4]*x[0];
+
+  return gaus+back;
+
+}
+
+//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+Double_t fitE(Double_t *x, Double_t *par)
+{
+
+  Double_t levy;
+
+  levy = par[0] * TMath::Exp( -par[1]/x[0]) * TMath::Power(x[0], -par[2]) ;
+
+  return levy;
+} 
+
+//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+int CreateEMCALRunQA(const char* filename, TString RunId, TString period, TString pass, Int_t SavePlots = 0, Bool_t filter=0 , TString fTrigger = "", TString system = "", TString fCalorimeter = "EMCAL")
+{   
+
+  QAPATH = TString(gSystem->Getenv("QAPATH"));
+  if(QAPATH.IsNull()) QAPATH = QAPATHF;
+  if(! QAPATH.BeginsWith("./")) { QAPATH = QAPATH + RunId + "/";} 
+
+  AliLog::SetGlobalLogLevel(AliLog::kError);
+  TFile *f = new TFile(filename);
+  AliLog::SetGlobalLogLevel(AliLog::kInfo);
+
+  if (f->IsZombie()) {Error(__FUNCTION__,Form("Error openning the input file %s",filename)); return -1;}
+  TList* TriggersList = new TList(); 
+
+  if (fTrigger=="") 
+    {
+      TPMERegexp name_re("CaloQA_\\w+");
+      TObjLink* link = f->GetListOfKeys()->FirstLink();
+
+      while (link)
+        {
+         TString name = link->GetObject()->GetName();
+          if (name_re.Match(name))
+            {
+             TriggersList->Add(link->GetObject());
+             if(TString(filename).Contains("barrel") && ! name.Contains("default"))  TriggersList->Remove(link->GetObject());
+             if(TString(filename).Contains("outer")  && ! name.Contains("EMC"))      TriggersList->Remove(link->GetObject());
+           } 
+          link = link->Next();
+       }
+    } else {TriggersList->Add(new TObjString(fTrigger.Data()));}
+  if(!TriggersList->GetEntries()) {Error(__FUNCTION__,"No trigger found!"); return -2;}
+
+  int nSM = FindNumberOfSM(f,((TObjString*)TriggersList->Last())->GetString(),period);
+  if (nSM<0) {Error(__FUNCTION__,"Could not find the number of super modules!"); return -3;}
+  Info(__FUNCTION__,Form("%i super modules were discuvered",nSM));
+  TString GeomName;
+  if (nSM <= 6)         { nSM=6;  GeomName = "EMCAL_FIRSTYEARv1";}
+  else if (nSM <= 10)   { nSM=10; GeomName = "EMCAL_COMPLETEv1";}
+  else if (nSM <= 12)   { nSM=12; GeomName = "EMCAL_COMPLETE12SMv1";}
+  else    {nSM = 20;              GeomName = "EMCAL_COMPLETE12SMv1_DCAL_8SM";}
+
+  AliEMCALGeometry *geom = new AliEMCALGeometry(GeomName.Data(),"EMCAL");
+  Info(__FUNCTION__,Form("Using %i super modules and the Geometry %s",nSM,GeomName.Data()));
+
+  TFile *fout = new TFile(TString( QAPATH + period+"_"+pass + fTrigger+"_"+ (Long_t)RunId.Atoi() +"_QAplots.root").Data(),"RECREATE");
+
+  if((system.IsNull()) && (period.EndsWith("h"))) {system = "PbPb";}
+  
+  Int_t ret=0;
+  TIter next(TriggersList);
+  while (TObject *obj = next())
+    {
+      fTrigger= TString(obj->GetName());     
+      ret -= DrawOccupancy(RunId.Atoi(),period,pass,fTrigger,system,f,fout,geom,SavePlots);
+      ret -= DrawRun(RunId.Atoi(),period,pass,fTrigger,f,fout,SavePlots,nSM,filter);
+    }
+  ret-= TrendingEMCALTree(RunId.Atoi(),fCalorimeter,system,period,pass,nSM,TriggersList,f,fout,SavePlots);
+  f->Close();
+  fout->Close();
+  delete f;
+  delete geom;
+
+  return ret;
+}
+
+//----------------------------------------------------------------------------------------------------------------------------------------------------------
+Int_t DrawOccupancy(Long_t  run , TString period, TString pass, TString fTrigger,TString system, TFile* f,TFile* fout, AliEMCALGeometry* geom, Int_t SavePlots)
+{
+
+  set_plot_style();
+  gStyle->SetOptStat(0);
+  TH1::AddDirectory(kFALSE);
+  TH2D *hEnergyMapReal = new TH2D("hEnergyMapReal","",96,-48,48,120,-0,120);
+  TH2D *hOccupancyMapReal = new TH2D("hOccupancyMapReal","",96,-48,48,120,-0,120);
+  hEnergyMapReal->SetXTitle("eta (bin)");
+  hEnergyMapReal->SetYTitle("phi (bin)");
+  hEnergyMapReal->SetZTitle("E(GeV)/event");
+  hEnergyMapReal->GetYaxis()->SetTitleOffset(1.2);
+  hEnergyMapReal->GetZaxis()->SetLabelSize(0.02);
+  hEnergyMapReal->GetZaxis()->SetTitleOffset(1.36);
+  hOccupancyMapReal->SetXTitle("eta (bin)");
+  hOccupancyMapReal->SetYTitle("phi (bin)"); 
+  hOccupancyMapReal->GetYaxis()->SetTitleOffset(1.2);
+  hOccupancyMapReal->GetZaxis()->SetLabelSize(0.02);
+
+  Int_t nSupMod, nModule, nIphi, nIeta;
+  Int_t iphi, ieta;
+  Int_t realbineta=0;
+  Int_t realbinphi=0;
+  
+  //NO MASK
+  Int_t mask[1] = {2222222};
+
+  TH2F *hCellAmplitude;
+  TH1F *hNEvents;
+  Int_t Events;
+  Int_t n=0;
+  
+  TString direct;
+  if(!fTrigger.Contains("QA")) {
+    direct = "CaloQA_";
+  }
+  direct += fTrigger;
+  Bool_t dirok = f->cd(direct);
+  if (!dirok) { Error(__FUNCTION__,Form("No input drectory %s",direct.Data())); return -1;}
+  TList *outputList = (TList*)gDirectory->Get(direct); 
+  if(!outputList){ Error(__FUNCTION__,"No input list! "); return -1;}
+  outputList->SetOwner();
+  
+  fout->mkdir(Form("%s/%s/%ld/%s/%s",period.Data(),pass.Data(),run,"RunLevelQA",fTrigger.Data()));
+  fout->cd();
+  fout->Cd(Form("%s/%s/%ld/%s/%s",period.Data(),pass.Data(),run,"RunLevelQA",fTrigger.Data()));
+  
+  hNEvents =(TH1F *)outputList->FindObject("hNEvents");
+  if(!hNEvents){ Error(__FUNCTION__,Form("hNEvent histogram not found for trigger %s ",fTrigger.Data())); return -2;}
+  Events = (Int_t)hNEvents->GetEntries();
+  if(Events==0){ Error(__FUNCTION__,Form("No event in trigger %s",fTrigger.Data())); return -3;}
+  Double_t Eth=1;
+  if(system=="PbPb"){
+    Eth = 5.;
+    if (fTrigger.Contains("EMC")) Eth=20.;
+  }
+  if(system=="pp"){
+    Eth = 1.;
+    if (fTrigger.Contains("EMC")) Eth=5.;
+  }
+
+  hCellAmplitude =(TH2F *)outputList->FindObject("EMCAL_hAmpId");
+  for(Int_t i = 0; i < geom->GetNCells() ; i++){ 
+    Double_t Esum = 0;
+    Double_t Nsum = 0;  
+
+    for (Int_t j = 1; j <= hCellAmplitude->GetNbinsX(); j++) 
+      {
+       Double_t E = hCellAmplitude->GetXaxis()->GetBinCenter(j);
+       Double_t N = hCellAmplitude->GetBinContent(j, i+1);
+       
+       if (E < 0.3) continue; 
+       
+       if (E <= Eth) {
+         Esum += E*N;
+         Nsum += N;
+       }
+      }
+
+    Int_t absId = i;
+    if(n!=0) {if(mask[n]<=mask[n-1]) Warning(__FUNCTION__,"The list of bad cells is not sorted !!");}
+    if(i==mask[n]){n++ ; continue; } // skip bad cells
+
+    geom->GetCellIndex(absId,  nSupMod, nModule, nIphi, nIeta);
+    geom->GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi,ieta);
+
+    realbinphi = 120-(nSupMod/2)*24 -iphi -1; //
+    if (nSupMod%2==0) realbineta= 48-ieta -1;  
+    if (nSupMod%2==1) realbineta= -ieta -1;
+
+    hEnergyMapReal->Fill(realbineta,realbinphi,Esum/(Double_t)Events);
+    hOccupancyMapReal->Fill(realbineta,realbinphi,Nsum/(Double_t)Events);
+  }
+
+  cout <<" Run: " << run << " trigger: " << fTrigger << " N_events: "<<Events<<endl;
+
+  TPMERegexp r("_\\w+");
+  TString Energy;   Energy   = QAPATH + "MapEnergy"  + fTrigger(r) + ".pdf";
+  TString Energy2;  Energy2  = QAPATH + "MapEnergy"  + fTrigger(r) + ".png";
+  TString Entries;  Entries  = QAPATH + "MapEntries" + fTrigger(r) + ".pdf";
+  TString Entries2; Entries2 = QAPATH + "MapEntries" + fTrigger(r) + ".png";
+
+  TCanvas *c1 = new TCanvas("Energymap","Energy Map",600,600); 
+  c1->SetFillColor(0);
+  c1->SetGrid();
+  c1->SetRightMargin(0.14); 
+  TString title = "run ";
+  title += run ;
+  if(fTrigger.Contains("EMC")) { title += " EMC ";} else {title += " MB ";}
+  title += " Summed energy map";
+  hEnergyMapReal->SetTitle(title);
+  hEnergyMapReal->DrawCopy("colz");  
+  if(SavePlots==2) c1->SaveAs(Energy);
+  if(SavePlots) c1->SaveAs(Energy2);
+  c1->Write();
+  delete c1; 
+
+
+  TCanvas *c2 = new TCanvas("Occupancy","Occupancy Map",600,600); 
+  c2->SetFillColor(0);
+  c2->SetGrid();
+  c2->SetRightMargin(0.14);  
+  TString title2 = "run ";
+  title2 += run ;
+  if(fTrigger.Contains("EMC")) { title2 += " EMC ";} else { title2 += " MB ";}
+  title2 += " Occupancy map";
+  hOccupancyMapReal->SetTitle(title2);
+  hOccupancyMapReal->DrawCopy("colz");  
+  if(SavePlots==2) c2->SaveAs(Entries);
+  if(SavePlots) c2->SaveAs(Entries2);
+  c2->Write();
+  delete c2; 
+
+  if (outputList) {outputList->Delete();} 
+
+  delete hEnergyMapReal;
+  delete hOccupancyMapReal;
+
+  return 0; 
+}
+
+//-----------------------------------------------------------------------------------------------------------------------
+Int_t DrawRun(const Long_t  run, TString period, TString pass, TString fTrigger, TFile *f,TFile *fout, Int_t SavePlots, Int_t nSM, Bool_t kFilter)
+{
+  TString direct;
+  if(!fTrigger.Contains("QA")) {
+    direct = "CaloQA_";
+  }
+  direct += fTrigger;
+
+  f->cd(direct);
+  if(!direct) { Error(__FUNCTION__,Form("No input directory %s",direct.Data())); return -1;}
+  TList *outputList = (TList*)gDirectory->Get(direct);
+  if(!outputList){ Error(__FUNCTION__,Form("No input list! %s",direct.Data())); return -2;}
+  outputList->SetOwner();
+  if (kFilter)
+  {
+     fout->mkdir(Form("%s/%s/%ld/%s",period.Data(),pass.Data(),run,fTrigger.Data()));
+     fout->cd();
+     fout->Cd(Form("%s/%s/%ld/%s",period.Data(),pass.Data(),run,fTrigger.Data()));
+     outputList->Write();
+  }
+  fout->cd();
+  fout->Cd(Form("%s/%s/%ld/%s/%s",period.Data(),pass.Data(),run,"RunLevelQA",fTrigger.Data()));
+
+  set_plot_style();
+  gStyle->SetPalette(1);
+  TH1::AddDirectory(kFALSE);
+  TString outfilename;
+  TString outfilename2;
+  const char* legend="";
+  TPMERegexp r("_\\w+");
+
+  if (fTrigger.Contains("EMC")){ legend = Form(" Run %d EMC ",(int)run);} 
+  else legend = Form(" Run %d MB ",(int)run);
+  TH1F* hNEvents =(TH1F *)outputList->FindObject("hNEvents");
+  if(!hNEvents){ Error(__FUNCTION__,Form("hNEvent histogram not found for trigger %s ",fTrigger.Data())); return -3;}
+  Int_t Events = (Int_t)hNEvents->GetEntries();
+  if(Events==0){ Error(__FUNCTION__,Form("No event in trigger %s",fTrigger.Data())); return -4 ;}
+
+  TCanvas* c1 = new TCanvas("TimeVsE", "Cluster Time Vs Energy", 600, 600);
+  c1->SetLogz();
+  c1->SetFillColor(0);
+  c1->SetBorderSize(0);
+  c1->SetFrameBorderMode(0);     
+
+  TH2F*  hClusterTimeEnergy =(TH2F *)outputList->FindObject("EMCAL_hClusterTimeEnergy");
+  if(!hClusterTimeEnergy) { Error(__FUNCTION__,Form("EMCAL_hClusterTimeEnergy: Histogram for trigger %s not found!",fTrigger.Data())); return -5;}
+  FormatRunHisto(hClusterTimeEnergy,Form("Time Vs Energy%s",legend),"EMCAL ToF(ns)");
+
+  AutoZoom(hClusterTimeEnergy,"maxx")->DrawCopy("colz");
+  outfilename =  QAPATH + "TimeRun" + fTrigger(r) + ".pdf" ;
+  outfilename2 = QAPATH + "TimeRun" + fTrigger(r) + ".png" ;
+
+  if(SavePlots==2) c1->SaveAs(outfilename);
+  if(SavePlots) c1->SaveAs(outfilename2);
+  c1->Write();
+  delete c1; 
+
+  TCanvas  * c2 = new TCanvas("ClusterVsTrack ","Correlation calo Mult Vs Track Multiplicity", 600, 600);
+  c2->SetLogz();
+  c2->SetFillColor(0);
+  c2->SetBorderSize(0);
+  c2->SetFrameBorderMode(0);     
+
+  TH2F* hClusterVsTrack =(TH2F *)outputList->FindObject("EMCAL_hCaloTrackMNClusters");
+  FormatRunHisto(hClusterVsTrack,Form("N cluster Vs N track%s",legend));
+
+  AutoZoom(hClusterVsTrack,"maxx,maxy",1)->DrawCopy("colz");
+  outfilename = QAPATH + "CaloTrackMult" + fTrigger(r) + ".pdf";
+  outfilename2 = QAPATH + "CaloTrackMult" + fTrigger(r) + ".png";
+  if(SavePlots==2) c2->SaveAs(outfilename);
+  if(SavePlots) c2->SaveAs(outfilename2);
+  c2->Write();
+  delete c2; 
+
+  TCanvas* c3 = new TCanvas("ClusterEVsTrack ","Correlation E calo Vs Track Multiplicity", 600, 600);
+  c3->SetLogz();
+  c3->SetFillColor(0);
+  c3->SetBorderSize(0);
+  c3->SetFrameBorderMode(0);     
+
+  TH2F* hClusterEVsTrack =(TH2F*)outputList->FindObject("EMCAL_hCaloTrackMEClusters");
+  FormatRunHisto(hClusterEVsTrack,Form("Sum E cluster Vs N track%s",legend));
+
+  AutoZoom(hClusterEVsTrack,"maxx,maxy",1)->DrawCopy("colz");
+  outfilename =  QAPATH + "ETrackMult" + fTrigger(r) + ".pdf";
+  outfilename2 = QAPATH + "ETrackMult" + fTrigger(r) + ".png";
+  if(SavePlots==2) c3->SaveAs(outfilename);
+  if(SavePlots) c3->SaveAs(outfilename2);
+  c3->Write();
+  delete c3; 
+  TCanvas* c4 = new TCanvas("ClusterEVsV0 ","Correlation E calo Vs V0 signal", 600, 600);
+  c4->SetLogz();
+  c4->SetFillColor(0);
+  c4->SetBorderSize(0);
+  c4->SetFrameBorderMode(0);     
+
+  TH2F* hClusterEVsV0S =(TH2F*)outputList->FindObject("EMCAL_hCaloV0SEClusters");
+  FormatRunHisto(hClusterEVsV0S,Form("Sum E cluster Vs V0 signal%s",legend));
+
+  AutoZoom(hClusterEVsV0S,"maxx,maxy",1)->DrawCopy("colz");
+  outfilename = QAPATH +"EVsV0s" + fTrigger(r) + ".pdf";
+  outfilename2 = QAPATH +"EVsV0s" + fTrigger(r) + ".png";
+  if(SavePlots==2) c4->SaveAs(outfilename);
+  if(SavePlots) c4->SaveAs(outfilename2);
+  c4->Write();
+  delete c4;
+
+  TCanvas* c5 = new TCanvas("CellsperCluster","Nb of cells per cluster for each SM", 600, 600);
+  c5->SetLogz();
+  c5->SetFillColor(0);
+  c5->SetBorderSize(0);
+  c5->SetFrameBorderMode(0);
+  Bool_t mod3=0; if (nSM%3) mod3=1;  
+  c5->Divide(3,(nSM/3)+mod3);
+
+  for (int ism = 0; ism < nSM; ism++)
+    {
+      c5->cd(ism+1);
+      gPad->SetLogz();
+      if(TString(Form("Nb of cells per cluster%s Mod %d",legend,ism)).Length() > 60) { Error(__FUNCTION__,"Title too long!"); return -6;}
+      AutoZoom(HistoPerMod((TH2F*)outputList->FindObject(Form("EMCAL_hNCellsPerCluster_Mod%i",ism)),Form("Nb of cells per cluster%s Mod %d",legend,ism)),"all",1)->DrawCopy("colz");
+    }
+  
+  outfilename =  QAPATH + "CellsperClusterSM" + fTrigger(r) + ".pdf";
+  outfilename2 = QAPATH + "CellsperClusterSM" + fTrigger(r) + ".png";
+  if(SavePlots==2) c5->SaveAs(outfilename);
+  if(SavePlots) c5->SaveAs(outfilename2);
+  c5->Write();
+  delete c5;
+
+  if (outputList) outputList->Delete();
+
+  return 0;
+}
+
+//----------------------------------------------------------------------------------------------------------------------------------
+Int_t TrendingEMCALTree(Long_t RunId,TString fCalorimeter,TString system,TString period , TString pass,int n ,TList* TriggersList,TFile* f,TFile *fout, Int_t SavePlots)
+{
+  
+  TString fTrigger="";
+  TString aCalorimeter; 
+  if (n<=12) {aCalorimeter = fCalorimeter;} else  {aCalorimeter = TString("EMCAL_and_DCAL");}
+  TDatime now;
+
+  Double_t Nevent=0 ;
+  Double_t xe=0.5;
+
+  Double_t CellMean=0;
+  Double_t CellRMS=0;
+  Double_t ClusterMean=0;
+  Double_t ClusterRMS=0;
+  Double_t EtotalMean=0;
+  Double_t EtotalRMS=0;
+
+  Double_t CellPerClusterMean=0; //
+  Double_t CellPerClusterRMS=0; //
+
+  Double_t mPDG = 134.9766;
+  Double_t Npi0=0;
+  Double_t Npi0Err=0;
+  Double_t MeanPos=0;
+  Double_t MeanPosErr=0;
+  Double_t Width=0;
+  Double_t WidthErr=0;
+  Double_t Chi2NdfPi0=0;
+  Double_t Ngg=0;
+  Double_t NggErr=0;
+  Double_t Signif=0; // !S/(S+B)
+  Double_t SignifErr=0; // !S/(S+B)
+
+  TFile* ftree = new TFile(Form("%s/trending.root",QAPATH.Data()),"RECREATE");
+    
+  TTree *tree = new TTree("trending","Trending QA Tree");
+  tree->Branch("fDate",&now);
+  tree->Branch("fCalorimeter",&aCalorimeter); 
+  tree->Branch("system",&system); 
+  tree->Branch("period",&period);
+  tree->Branch("pass",&pass); 
+  tree->Branch("fTrigger",&fTrigger);
+  tree->Branch("run",&RunId,"run/I");
+  tree->Branch("xe",&xe,"xe/D");
+
+  tree->Branch("Nevent",&Nevent,"Nevent/D");
+  tree->Branch("CellMean",&CellMean,"CellMean/D");
+  tree->Branch("CellRMS",&CellRMS,"CellRMS/D");        
+  tree->Branch("ClusterMean",&ClusterMean,"ClusterMean/D");
+  tree->Branch("ClusterRMS",&ClusterRMS,"ClusterRMS/D");
+  tree->Branch("EtotalMean",&EtotalMean,"EtotalMean/D");
+  tree->Branch("EtotalRMS",&EtotalRMS,"EtotalRMS/D");
+
+  tree->Branch("CellPerClusterMean",&CellPerClusterMean,"CellPerClusterMean/D"); //
+  tree->Branch("CellPerClusterRMS",&CellPerClusterRMS,"CellPerClusterRMS/D");  //
+  
+  tree->Branch("Npi0",&Npi0,"Npi0/D");
+  tree->Branch("Npi0Err",&Npi0Err,"Npi0Err/D");
+  tree->Branch("MeanPos",&MeanPos,"MeanPos/D");
+  tree->Branch("MeanPosErr",&MeanPosErr,"MeanPosErr/D");
+  tree->Branch("Width",&Width,"Width/D");
+  tree->Branch("WidthErr",&WidthErr,"WidthErr/D");
+  tree->Branch("Chi2NdfPi0",&Chi2NdfPi0,"Chi2NdfPi0/D");
+  tree->Branch("Ngg",&Ngg,"Ngg/D");
+  tree->Branch("NggErr",&NggErr,"NggErr/D");
+  tree->Branch("Signif",&Signif,"Signif/D");
+  tree->Branch("SignifErr",&SignifErr,"SignifErr/D");
+  
+  tree->Branch("nSM",&n,"nSM/I");
+
+  int nMax = 22;   
+  Double_t CellMeanSM[nMax];
+  Double_t CellRMSSM[nMax];
+  Double_t ClusterMeanSM[nMax];
+  Double_t ClusterRMSSM[nMax];
+  Double_t EtotalMeanSM[nMax]; //mean total energy deposited per event
+  Double_t EtotalRMSSM[nMax];
+  Double_t CellPerClusterMeanSM[nMax];
+  Double_t CellPerClusterRMSSM[nMax];
+  Double_t ECell1MeanSM[nMax]; //total energy deposited per event without 1 cell clusters
+  Double_t ECell1RMSSM[nMax];
+
+  Double_t MeanPosSM[nMax];
+  Double_t MeanPosErrSM[nMax];
+  Double_t WidthSM[nMax];
+  Double_t WidthErrSM[nMax]; 
+  Double_t Npi0SM[nMax];
+  Double_t Npi0ErrSM[nMax];
+
+  tree->Branch("CellMeanSM",CellMeanSM,TString::Format("CellMeanSM[%i]/D",nMax));
+  tree->Branch("CellRMSSM",CellRMSSM,TString::Format("CellRMSSM[%i]/D",nMax));
+  tree->Branch("ClusterMeanSM",ClusterMeanSM,TString::Format("ClusterMeanSM[%i]/D",nMax));
+  tree->Branch("ClusterRMSSM",ClusterRMSSM,TString::Format("ClusterRMSSM[%i]/D",nMax));
+  tree->Branch("EtotalMeanSM",EtotalMeanSM,TString::Format("EtotalMeanSM[%i]/D",nMax));
+  tree->Branch("EtotalRMSSM",EtotalRMSSM,TString::Format("EtotalRMSSM[%i]/D",nMax));
+  tree->Branch("CellPerClusterMeanSM",CellPerClusterMeanSM,TString::Format("CellPerClusterMeanSM[%i]/D",nMax));
+  tree->Branch("CellPerClusterRMSSM",CellPerClusterRMSSM,TString::Format("CellPerClusterRMSSM[%i]/D",nMax));
+  tree->Branch("ECell1MeanSM",ECell1MeanSM,TString::Format("ECell1MeanSM[%i]/D",nMax));
+  tree->Branch("ECell1RMSSM",ECell1RMSSM,TString::Format("ECell1RMSSM[%i]/D",nMax));
+
+  tree->Branch("MeanPosSM",MeanPosSM,TString::Format("MeanPosSM[%i]/D",nMax));
+  tree->Branch("MeanPosErrSM",MeanPosErrSM,TString::Format("MeanPosErrSM[%i]/D",nMax));
+  tree->Branch("WidthSM",WidthSM,TString::Format("WidthSM[%i]/D",nMax));
+  tree->Branch("WidthErrSM",WidthErrSM,TString::Format("WidthErrSM[%i]/D",nMax));
+  tree->Branch("Npi0SM",Npi0SM,TString::Format("Npi0SM[%i]/D",nMax));
+  tree->Branch("Npi0ErrSM",Npi0ErrSM,TString::Format("Npi0ErrSM[%i]/D",nMax));
+
+  TF1* fitMass = new TF1("fitMass",pi0massP2,100,250,6);
+  fitMass->SetParName(0,"A");
+  fitMass->SetParName(1,"m_{0}");
+  fitMass->SetParName(2,"sigma");
+  fitMass->SetParName(3,"a_{0}");
+  fitMass->SetParName(4,"a_{1}");
+  fitMass->SetParName(5,"a_{2}");
+  fitMass->SetParLimits(0,  1.e-5,1.e5);
+  fitMass->SetParLimits(1, 0.11, 0.16); //
+  fitMass->SetParLimits(2,  0.001,0.06);
+  
+  TList* outputList;
+
+  TH1F* fhNEvents;
+  TH1F* fhE;
+  TH1F* fhNClusters = 0x0;
+  TH1F* fhNCells = 0x0;
+  
+  TH1F* NCells[n];
+  TH1F* NClusters[n];
+  TH2F* NCellsPerCluster[n];
+  TH1F* E[n];
+
+  TH2F* fhIM ;
+  TH1F* fhMgg;
+  TH2F* IM[n];
+  TH1F* MggSM[n];
+
+  TPMERegexp r("_\\w+");
+  TIter next(TriggersList);
+  int ret = 0; 
+  while (TObject *obj = next())
+    {
+      fTrigger= TString(obj->GetName());
+      TString namefile = QAPATH + period + "_" +  pass + fTrigger(r).Data() + "_" + RunId + "_data.txt";
+      ofstream QAData(namefile, ios::app); // write checks at the end
+  
+      Npi0=0;
+      Npi0Err=0;
+      MeanPos=0;
+      MeanPosErr=0;
+      Width=0;
+      WidthErr=0;
+      Chi2NdfPi0=0;
+      Ngg=0;
+      NggErr=0;
+      Signif=0; 
+      SignifErr=0; 
+
+      memset (CellMeanSM, 0, sizeof (Double_t) * nMax);
+      memset (CellRMSSM, 0, sizeof (Double_t) *  nMax);
+      memset (ClusterMeanSM, 0, sizeof (Double_t) * nMax);
+      memset (ClusterRMSSM, 0, sizeof (Double_t) * nMax);
+      memset (EtotalMeanSM, 0, sizeof (Double_t) * nMax);
+      memset (EtotalRMSSM, 0, sizeof (Double_t) * nMax);
+      memset (CellPerClusterMeanSM, 0, sizeof (Double_t) * nMax);
+      memset (CellPerClusterRMSSM, 0, sizeof (Double_t) * nMax);
+      memset (ECell1MeanSM, 0, sizeof (Double_t) * nMax);
+      memset (ECell1RMSSM, 0, sizeof (Double_t) * nMax);
+
+      memset (MeanPosSM, 0, sizeof (Double_t) * nMax);
+      memset (MeanPosErrSM, 0, sizeof (Double_t) * nMax);
+      memset (WidthSM, 0, sizeof (Double_t) * nMax);
+      memset (WidthErrSM, 0, sizeof (Double_t) * nMax);
+      memset (Npi0SM, 0, sizeof (Double_t) * nMax);
+      memset (Npi0ErrSM, 0, sizeof (Double_t) * nMax);
+      TString dirname;
+      if(!fTrigger.Contains("QA")) {
+       dirname = "CaloQA_";
+      }  
+      dirname += fTrigger;
+  
+      Bool_t dirok = f->cd(dirname);
+      if(!dirok) { Error(__FUNCTION__,Form("No input directory %s",dirname.Data())); tree->Fill(); ftree->cd(); tree->Write(); ret= -1; continue;}
+      outputList = (TList*)gDirectory->Get(dirname);
+      if(!outputList){ Error(__FUNCTION__,Form("No input list! %s",dirname.Data())); tree->Fill();  ftree->cd(); tree->Write(); ret=-2; continue;;} 
+      outputList->SetOwner();
+
+      // number of events
+      fhNEvents =(TH1F *)outputList->FindObject("hNEvents");
+      if(!fhNEvents){ Error(__FUNCTION__,Form("NEvent histogram not found for trigger %s",fTrigger.Data())); tree->Fill();  ftree->cd(); tree->Write();  ret=-3; continue;}
+      Nevent=fhNEvents->GetEntries();
+      if(Nevent==0) {Error(__FUNCTION__,Form("No event in trigger %s",fTrigger.Data())); tree->Fill();  ftree->cd(); tree->Write(); ret=-4; continue;} 
+      if(Nevent<20) {Error(__FUNCTION__,Form("Less than 20 events in trigger %s",fTrigger.Data())); tree->Fill();  ftree->cd(); tree->Write(); ret=-5; continue;}
+    
+      // first do clusters trending
+      fhE = (TH1F *)outputList->FindObject(fCalorimeter+"_hE");
+      Double_t energy = 0. ;
+   
+      for(Int_t ibin = fhE->FindBin(0.6) ; ibin <fhE->FindBin(50.) ; ibin++){ 
+       energy+=fhE->GetBinCenter(ibin)*fhE->GetBinContent(ibin);
+      }
+      if(fhE->Integral(fhE->FindBin(0.6), fhE->FindBin(50.))==0){Error(__FUNCTION__,Form("Not enough events")); tree->Fill(); ftree->cd(); tree->Write(); ret=-6; continue;}
+      EtotalMean=energy/fhE->Integral(fhE->FindBin(0.6), fhE->FindBin(50.)) ;
+      EtotalRMS=fhE->GetMeanError();
+  
+      TString nameNCell = Form("%s_hNCells_Mod",fCalorimeter.Data());
+      TString nameNCluster = Form("%s_hNClusters_Mod",fCalorimeter.Data());
+      TString nameE = Form("%s_hE_Mod",fCalorimeter.Data());
+      TH2F* hNCellsMod= (TH2F*)outputList->FindObject(nameNCell.Data()); 
+      TH2F* hNClusterMod=(TH2F*)outputList->FindObject(nameNCluster.Data());
+      TH2F* hEMod=(TH2F*)outputList->FindObject(nameE.Data());
+
+      if (!hNCellsMod || !hNClusterMod || !hEMod) {Error(__FUNCTION__,"A requiered histogram was not found (the imput QAresult.root might be too old)!"); tree->Fill(); ftree->cd(); tree->Write(); ret=-7; continue;}
+    
+      TCanvas* c1 = new TCanvas("Pi0InvMassSM","Pi0 Invariant Mass for each SM", 600, 600);
+      c1->SetFillColor(0);
+      c1->SetBorderSize(0);
+      c1->SetFrameBorderMode(0);
+      Bool_t mod3=0; if (n%3) mod3=1;  
+      c1->Divide(3,n/3+mod3);
+
+      //per sm trending 
+      TString nameNCellPerCluster;
+      for(Int_t ism = 0 ; ism < n ; ism++){
+       cout << "#########################"<< endl;
+       cout      << " Super Module " << ism << " Run " << RunId << endl;
+        // first do clusters trending
+        nameNCellPerCluster = Form("%s_hNCellsPerCluster_Mod%d",fCalorimeter.Data(),ism);
+        NCellsPerCluster[ism] = (TH2F*)outputList->FindObject(nameNCellPerCluster.Data());
+ if(!  (TH2F*)outputList->FindObject(nameNCellPerCluster.Data()) ) { Error(__FUNCTION__,Form("NCellsPerCluster histogram not found for super module %i",ism));ret=-8; continue;}
+   NCellsPerCluster[ism] = (TH2F*)outputList->FindObject(nameNCellPerCluster.Data());
+
+       NCells[ism] = (TH1F*)hNCellsMod->ProjectionX(Form("NCells%d",ism),ism+1,ism+2,"");
+       NClusters[ism] = (TH1F*)hNClusterMod->ProjectionX(Form("NClusters%d",ism),ism+1,ism+2,"");
+       E[ism] = (TH1F*)hEMod->ProjectionX(Form("E%d",ism),ism+1,ism+2,"");
+       CellMeanSM[ism]=NCells[ism]->GetMean();
+       CellRMSSM[ism]=NCells[ism]->GetMeanError();
+       ClusterMeanSM[ism]=NClusters[ism]->GetMean();
+       ClusterRMSSM[ism]=NClusters[ism]->GetMeanError();
+       CellPerClusterMeanSM[ism]=NCellsPerCluster[ism]->GetMean(2);
+       CellPerClusterRMSSM[ism]=NCellsPerCluster[ism]->GetMeanError(2);
+
+       ECell1MeanSM[ism] =NCellsPerCluster[ism]->ProjectionX("",2,50,"")->Integral(5,50)/(Nevent);
+       ECell1RMSSM[ism] =NCellsPerCluster[ism]->ProjectionX("",2,50,"")->GetMeanError();
+       Double_t energySM = 0. ;
+       for(Int_t ibin = E[ism]->FindBin(0.6) ; ibin <E[ism]->FindBin(50.) ; ibin++){ 
+         energySM+=E[ism]->GetBinCenter(ibin)*(E[ism]->GetBinContent(ibin));
+       }
+       if(E[ism]->Integral(E[ism]->FindBin(0.6),E[ism]->FindBin(50.))==0){Error(__FUNCTION__,Form("Energy: Not enough events/SM")); continue;}
+       EtotalMeanSM[ism]=energySM/(E[ism]->Integral(E[ism]->FindBin(0.6),E[ism]->FindBin(50.)));
+      
+       EtotalRMSSM[ism]=E[ism]->GetMeanError();
+
+       if(ism==0) {
+         fhNCells = (TH1F*)NCells[ism]->Clone("NCells");
+         fhNClusters = (TH1F*)NClusters[ism]->Clone("NClusters");  
+       }
+       else {
+         fhNCells->Add(NCells[ism],1);
+         fhNClusters->Add(NClusters[ism],1);
+       }
+
+       //Pi0
+       c1->cd(ism+1);
+       TString namePair = Form("%s_hIM_Mod%d",fCalorimeter.Data(),ism);
+       IM[ism] = (TH2F*)outputList->FindObject(namePair.Data());
+       IM[ism]->Sumw2();
+
+       TString projname = Form("SM_%d",ism);
+       MggSM[ism] = (TH1F *)IM[ism]->ProjectionY(projname.Data(), 2, 150, "") ;
+
+
+       if(MggSM[ism]->GetEntries()>100) {
+         fitMass->SetParameter(0, MggSM[ism]->GetBinContent(MggSM[ism]->GetMaximumBin()));
+          fitMass->SetParameter(1, mPDG); //
+         fitMass->SetParameter(2, 15.);  //
+         fitMass->SetParameter(3,0.); 
+         fitMass->SetParameter(4,MggSM[ism]->GetBinContent(MggSM[ism]->FindBin(0.11)));
+         fitMass->SetParameter(5,MggSM[ism]->GetBinContent(MggSM[ism]->FindBin(0.20)));
+
+         if(MggSM[ism]->GetEntries()<1000){ MggSM[ism]->Rebin(4);} else {MggSM[ism]->Rebin();}
+         MggSM[ism]->Fit("fitMass", "WL R +","",0.05, 0.30);
+         MggSM[ism]->SetTitle(Form("Pi0 Mass for super module %i",ism));
+         MggSM[ism]->SetTitleSize(0.1);
+         MggSM[ism]->SetXTitle("Pi0 Mass");
+         MggSM[ism]->SetYTitle("Nb of entries");
+         MggSM[ism]->GetXaxis()->SetLabelSize(0.05);
+         MggSM[ism]->GetXaxis()->SetTitleSize(0.07);
+         MggSM[ism]->GetXaxis()->SetTitleOffset(0.68);
+         MggSM[ism]->GetYaxis()->SetLabelSize(0.05);
+         MggSM[ism]->GetYaxis()->SetTitleSize(0.06);
+         MggSM[ism]->GetYaxis()->SetTitleOffset(0.78);
+        
+         MeanPosSM[ism] = MggSM[ism]->GetFunction("fitMass")->GetParameter(1)*1000;
+         MeanPosErrSM[ism] = MggSM[ism]->GetFunction("fitMass")->GetParError(1)*1000;
+         WidthSM[ism] = MggSM[ism]->GetFunction("fitMass")->GetParameter(2)*1000;
+         WidthErrSM[ism] = MggSM[ism]->GetFunction("fitMass")->GetParError(2)*1000;
+         Npi0SM[ism] = MggSM[ism]->GetFunction("fitMass")->GetParameter(0)*(MggSM[ism]->GetFunction("fitMass")->GetParameter(2))*TMath::Sqrt(2*TMath::Pi())/(Nevent*MggSM[ism]->GetBinWidth(1));
+         Npi0ErrSM[ism] = TMath::Sqrt((MggSM[ism]->GetFunction("fitMass")->GetParError(0)/MggSM[ism]->GetFunction("fitMass")->GetParameter(0))*(MggSM[ism]->GetFunction("fitMass")->GetParError(0)/MggSM[ism]->GetFunction("fitMass")->GetParameter(0))
+                                      +(MggSM[ism]->GetFunction("fitMass")->GetParError(2)/MggSM[ism]->GetFunction("fitMass")->GetParameter(2))*(MggSM[ism]->GetFunction("fitMass")->GetParError(2)/MggSM[ism]->GetFunction("fitMass")->GetParameter(2)));
+         Npi0ErrSM[ism] = 0.; //
+
+       }// end if enough events for Pi0 fit and trending
+       else { Info(__FUNCTION__,Form("Not enough events for Pi0 fit and trending for super module %i",ism));} ;   
+      } //per SM loop
+
+      // Now Pi0 global trending
+      TCanvas* c2 = new TCanvas("Pi0InvMass","Pi0 Invariant Mass", 600, 600);
+      c2->SetFillColor(0);
+      c2->SetBorderSize(0);
+      c2->SetFrameBorderMode(0);
+    
+      fhIM = (TH2F *)outputList->FindObject(fCalorimeter+"_hIM");
+      fhIM->Sumw2();
+      fhMgg = (TH1F *)fhIM->ProjectionY("Mgg", 2, 150, "") ;
+      if(fhMgg->GetEntries()==0) {Error(__FUNCTION__,"The Pi0 histogram is empty !");  tree->Fill(); ret=-8; continue;} 
+      fitMass->SetParameter(0, 4500);
+      fitMass->SetParameter(1, mPDG);
+      fitMass->SetParameter(2, 0.01);
+      fitMass->SetParameter(3,0.);
+      fitMass->SetParameter(4,fhMgg->GetBinContent(fhMgg->FindBin(0.11)));
+      fitMass->SetParameter(5,fhMgg->GetBinContent(fhMgg->FindBin(0.20)));
+   
+      if(fhMgg->GetEntries()<5000){
+       fhMgg->Rebin(4);}
+      else   fhMgg->Rebin();
+
+      fhMgg->Fit("fitMass", "L R +", "", 0.05, 0.20);
+  
+      fhMgg->SetTitle("Pi0 Mass");
+      fhMgg->SetTitleSize(0.1);
+      fhMgg->SetXTitle("Pi0 Mass");
+      fhMgg->SetYTitle("Nb of entries");      
+      fhMgg->GetXaxis()->SetLabelSize(0.03);
+      fhMgg->GetXaxis()->SetTitleSize(0.03);
+      fhMgg->GetXaxis()->SetTitleOffset(1.3);
+      fhMgg->GetYaxis()->SetLabelSize(0.03);
+      fhMgg->GetYaxis()->SetTitleSize(0.03);
+      fhMgg->GetYaxis()->SetTitleOffset(1.3);
+    
+      MeanPos = fhMgg->GetFunction("fitMass")->GetParameter(1)*1000;
+      MeanPosErr = fhMgg->GetFunction("fitMass")->GetParError(1)*1000;
+      Width = fhMgg->GetFunction("fitMass")->GetParameter(2)*1000;
+      WidthErr = fhMgg->GetFunction("fitMass")->GetParError(2)*1000;
+      Chi2NdfPi0 = fhMgg->GetFunction("fitMass")->GetChisquare()/fhMgg->GetFunction("fitMass")->GetNDF(); 
+      Npi0 = fhMgg->GetFunction("fitMass")->GetParameter(0)*fhMgg->GetFunction("fitMass")->GetParameter(2)*TMath::Sqrt(2*TMath::Pi())/(Nevent*fhMgg->GetBinWidth(10));
+      Npi0Err = TMath::Sqrt((fhMgg->GetFunction("fitMass")->GetParError(0)/fhMgg->GetFunction("fitMass")->GetParameter(0))*(fhMgg->GetFunction("fitMass")->GetParError(0)/fhMgg->GetFunction("fitMass")->GetParameter(0))+(WidthErr/Width)*(WidthErr/Width));
+      Npi0Err = 0.; //
+      Ngg = fhMgg->GetFunction("fitMass")->Integral(0.11, 0.16)/(Nevent*fhMgg->GetBinWidth(10));
+      NggErr = fhMgg->GetFunction("fitMass")->IntegralError(0.11, 0.16)/(fhMgg->Integral()*fhMgg->GetBinWidth(10));
+      Signif = Npi0/Ngg;
+      SignifErr = TMath::Sqrt((Npi0Err/Npi0*(Npi0Err/Npi0)+(NggErr/Ngg*(NggErr/Ngg))));
+      SignifErr = Signif*SignifErr;
+    
+      cout<<"******************"<<endl;
+      //end of global trending
+
+      ClusterMean=fhNClusters->GetMean();
+      ClusterRMS=fhNClusters->GetMeanError();  
+      CellMean=fhNCells->GetMean();
+      CellRMS=fhNCells->GetMeanError();
+      tree->Fill();
+
+      TString outfilename = QAPATH +  "Pi0InvMass" + fTrigger(r) + ".pdf";
+      TString outfilename2 = QAPATH + "Pi0InvMass" + fTrigger(r) + ".png";
+      if(SavePlots==2) c2->SaveAs(outfilename);
+      if(SavePlots) c2->SaveAs(outfilename2);
+
+      outfilename = QAPATH + "Pi0InvMassSM" + fTrigger(r) + ".pdf";
+      outfilename2 = QAPATH + "Pi0InvMassSM" + fTrigger(r) + ".png";
+      if(SavePlots==2) c1->SaveAs(outfilename);
+      if(SavePlots) c1->SaveAs(outfilename2);
+
+      fout->cd();
+      fout->Cd(Form("%s/%s/%ld/%s/%s",period.Data(),pass.Data(),RunId,"RunLevelQA",fTrigger.Data()));
+      c2->Write();
+      c1->Write();
+      delete c1;
+      delete c2;
+      if (outputList) outputList->Delete() ;
+    
+      QAData  << RunId<<"    "<< Nevent        
+             <<"\n"; 
+    
+      QAData.close();
+
+    }    
+  
+  ftree->cd(); 
+  tree->Write();
+  ftree->Close();
+
+  return ret;
+
+}
+
+//-------------------------------------------------------------------------
+TH2F* FormatRunHisto(TH2F* aHisto,const char* title,const char* YTitle)
+{
+
+  if(!aHisto) {Error(__FUNCTION__,Form("The histogram with title \"%s\" was not found!",title)); return new TH2F();}
+  aHisto->SetStats(kFALSE);
+  aHisto->SetTitle(title);
+  aHisto->SetStats(kFALSE);
+  aHisto->SetYTitle(YTitle);
+  aHisto->GetYaxis()->SetTitleOffset(1.2);
+  aHisto->GetYaxis()->SetLabelSize(0.03);
+  aHisto->GetZaxis()->SetLabelSize(0.02);
+
+  return aHisto;
+
+}
+
+//--------------------------------------------------------------------------------------------------------------
+TH2F* HistoPerMod(TH2F* hTmpPerMod,const char* title)
+{
+
+  if(!hTmpPerMod) {Error(__FUNCTION__,Form("The histogram with title \"%s\" was not found!",title)); return new TH2F();}
+  hTmpPerMod->SetStats(kFALSE);
+  hTmpPerMod->SetTitle(title);
+  hTmpPerMod->SetTitleSize(0.1);
+  hTmpPerMod->GetXaxis()->SetTitleOffset(1.1);
+  hTmpPerMod->GetXaxis()->SetTitleSize(0.05);
+  hTmpPerMod->GetXaxis()->SetLabelSize(0.06);
+  hTmpPerMod->GetYaxis()->SetTitleOffset(1.1);
+  hTmpPerMod->GetYaxis()->SetTitleSize(0.05);
+  hTmpPerMod->GetYaxis()->SetLabelSize(0.06);
+  hTmpPerMod->GetZaxis()->SetLabelSize(0.04);
+
+  return hTmpPerMod;
+
+}
+
+//---------------------------------------------------------------------------------------------------
+TH2F* AutoZoom(TH2F* H,Option_t* aType, Int_t EntryMin)
+{
+
+  Int_t shiftX = (Int_t)(H->GetNbinsX()/30.);
+  Int_t shiftY = (Int_t)(H->GetNbinsY()/30.);
+
+  TString opt = aType;
+  opt.ToLower();
+
+  int minX = 0;
+  int maxX = H->GetNbinsX();
+  int New_minX = minX;
+  int New_maxX = maxX;
+
+  int minY = 0;
+  int maxY = H->GetNbinsY();
+  int New_minY = minY;
+  int New_maxY = maxY;
+
+  if (opt.Contains("all")) opt = TString("minx,maxx,miny,maxy");
+
+  if (opt.Contains("maxx"))
+    {
+
+      for  (New_maxX = maxX;New_maxX >=minX; New_maxX--)
+        {  Stat_t c = 0;
+         for  (int i_y = maxY; i_y >= minY;i_y--)
+           { c = H->GetBinContent(New_maxX,i_y);  if (c>EntryMin) break;}
+         if (c>EntryMin) break;
+        }
+    }
+  
+  if (opt.Contains("maxy"))
+    {
+
+      for  (New_maxY = maxY;New_maxY >=minY;New_maxY--)
+        {  Stat_t c = 0;
+         for  (int i_x=maxX; i_x>=minX;i_x--)
+           { c = H->GetBinContent(i_x, New_maxY );  if (c>EntryMin) break;}
+         if (c>EntryMin) break;
+        }
+
+    }
+
+  if (opt.Contains("minx"))
+    {
+
+      for  (New_minX = minX;New_minX <=maxX; New_minX++)
+        {  Stat_t c = 0;
+         for  (int i_y = minY; i_y <= maxY;i_y++)
+           { c = H->GetBinContent(New_minX,i_y);  if (c>EntryMin) break;}
+         if (c>EntryMin) break;
+        }
+    }
+
+  if (opt.Contains("miny"))
+    {
+      for  (New_minY = minY;New_minY <=maxY;New_minY++)
+        {  Stat_t c = 0;
+         for  (int i_x=minX; i_x<=maxX;i_x++)
+           { c = H->GetBinContent(i_x, New_minY );  if (c>EntryMin) break;}
+         if (c>EntryMin) break;
+        }
+    }
+ if (New_maxX!=-1 && New_maxY!=-1) H->GetXaxis()->SetRange(New_minX - shiftX  , New_maxX + shiftX);
+ if (New_maxX!=-1 && New_maxY!=-1) H->GetYaxis()->SetRange(New_minY - shiftY  , New_maxY + shiftY);
+
+  return H;
+
+}
+
+//----------------------------------------------------------------------------------------------------
+int FindNumberOfSM(TFile* f, TString fTrigger, TString period) 
+{
+
+  TString direct;
+  if(!fTrigger.Contains("QA")) {
+    direct = "CaloQA_";
+  }
+  direct += fTrigger; 
+
+  Int_t nSMt=-1;
+  Int_t year = 2000 + TString(period(3,2)).Atoi();
+  if ( year == 2010 ) { nSMt=6; }
+  else if ( year == 2011 || year == 2012 ) { nSMt=10; }
+  else if ( year == 2013 || year == 2014 ) { nSMt=12; }
+  else { nSMt=20; }
+
+  TList *outputList;   
+  Bool_t dirok = f->cd(direct);
+  if (!dirok) { Error(__FUNCTION__,Form("No input directory %s, the number SMs will be returned based on the year!",direct.Data()));} 
+  else { outputList = (TList*)gDirectory->Get(direct);}
+  if(!outputList) { Error(__FUNCTION__,"No input list, the number SMs will be returned based on the year! ");}
+  else {
+    outputList->SetOwner();
+    TH2F* hNSM =(TH2F *)outputList->FindObject("EMCAL_hE_Mod"); 
+    if (!hNSM || (!hNSM->GetEntries())) { Error(__FUNCTION__,"hNSM Histogram not found or it is empty, the number SMs will be returned based on the year!");}
+    else {
+      nSMt = hNSM->GetYaxis()->GetBinUpEdge(hNSM->FindLastBinAbove(0,2)); 
+    }
+  }
+  if (outputList) {outputList->Delete();} 
+
+  return nSMt;
+
+}
diff --git a/PWGPP/EMCAL/QA/macros/MakeQAPdf.C b/PWGPP/EMCAL/QA/macros/MakeQAPdf.C
new file mode 100644 (file)
index 0000000..f9dcbb4
--- /dev/null
@@ -0,0 +1,89 @@
+#if !defined(__CINT__) || defined(__MAKECINT__)
+#include <string.h>
+#include "TFile.h"
+#include "TTree.h"
+#include "TKey.h"
+#include "Riostream.h"
+#include "TCanvas.h"
+#include "TPad.h"
+#include "TText.h"
+#include "TError.h"
+#endif
+
+// Make a pdf with all QA plots 
+// A. SHABETAI
+
+TFile* sourceFile;
+TObject* Myobj;
+TCanvas* canvasDefault;
+TString Mypath;
+const char* title;
+
+void recurseOverKeys( TDirectory *target, TString f);
+
+//---------------------------------------------------------------------------------------
+void MakeQAPdf(const char* fileName, int outputWidth  = 600,  int outputHeight = 600) 
+{
+
+  sourceFile = TFile::Open(fileName);
+
+  canvasDefault = new TCanvas("canvasDefault","testCanvas",outputWidth,outputHeight);
+  TString f = TString(fileName).ReplaceAll(".root","");
+  
+  canvasDefault->Print(Form("%s%s",f.Data(),".pdf["));
+  gErrorIgnoreLevel = kInfo + 1;
+
+  // Now actually find all the directories, canvas, and make a pdf..
+  recurseOverKeys(sourceFile,f);  
+
+  gPad->Print(Form("%s%s",f.Data(),".pdf]"),Form("Title:%s/%s",Mypath.Data(),title));
+  gErrorIgnoreLevel = -1;
+  sourceFile->Close(); 
+
+}
+
+//---------------------------------------------------------------------------------------
+void recurseOverKeys( TDirectory *target,TString f ) 
+{
+  TString path = TString((char*)strstr( target->GetPath(), ":" ));
+  path.Remove(0, 2);
+  gErrorIgnoreLevel = kInfo + 1; 
+
+  sourceFile->cd(path.Data());
+
+  Mypath = path;
+  Mypath.ReplaceAll("CaloQA_","");
+  Mypath.ReplaceAll("default","trigMB");
+  Mypath.ReplaceAll("trig","");
+
+  TDirectory *current_sourcedir = gDirectory;
+
+  TKey *key;
+  TIter nextkey(current_sourcedir->GetListOfKeys());
+
+  while ((key = (TKey*)nextkey())) 
+  {
+
+    Myobj = key->ReadObj();
+
+    if (TString(Myobj->IsA()->GetName()).Contains("TCanvas")) 
+      {
+       title = Myobj->GetTitle();
+
+       ((TCanvas*)Myobj)->Print(Form("%s%s",f.Data(),".pdf"),Form("Title:%s/%s",Mypath.Data(),title));
+      }
+    else if ( Myobj->IsA()->InheritsFrom( "TDirectory" ) ) 
+     {
+
+      // Myobj is now the starting point of another iteration
+      // obj still knows its depth within the target file via
+      // GetPath(), so we can still figure out where we are in the recursion
+      recurseOverKeys( (TDirectory*)Myobj, f );
+
+    } // end of IF a TDriectory
+
+  } // end of LOOP over keys
+
+}
diff --git a/PWGPP/EMCAL/QA/macros/PlotEMCALQATrendingTree.C b/PWGPP/EMCAL/QA/macros/PlotEMCALQATrendingTree.C
new file mode 100644 (file)
index 0000000..a765036
--- /dev/null
@@ -0,0 +1,606 @@
+#if !defined(__CINT__) || defined(__MAKECINT__)
+#include <TSystem.h>
+#include <TStyle.h>
+#include <TROOT.h>
+#include <Riostream.h>
+#include <TFile.h>
+#include <TH1F.h>
+#include <TCanvas.h>
+#include <TGraphErrors.h>
+#include <TLegend.h>
+#include <TTree.h>
+#include <TTreeFormula.h>
+#include <TEventList.h>
+#include <TObjString.h>
+#include <TList.h>
+#include <TCut.h>
+#include <TError.h>
+#include <TDatime.h>
+#include <TPRegexp.h>
+#include <TInterpreter.h>
+#include <TGaxis.h>
+#endif
+
+// This macro produces periodLevelQA for EMCAL from a trending tree
+// Authors: A. Mas, M. Germain & A.Shabetai SUBATECH
+// re-factored for automatic QA processing and trending A. A.SHABETAI
+
+int PlotEMCALQATrendingTree(TTree* tree, const char* trig,TFile* fout,Bool_t SavePlots,TString expr);
+TH1F* ZoomFromTree(TH1F* h, TTree* atree, Int_t n, const char* aVar, UShort_t aScaleFactor=1);
+Double_t GetTreeMinimum(TTree* aTree, Int_t n, const char* columname);
+Double_t GetTreeMaximum(TTree* aTree, Int_t n, const char* columname);
+
+TString QAPATH;
+TString QAPATHF= "./";
+
+//--------------------------------------------------------------------------------------------------------------------
+int NextInt(int newMax=0) 
+{
+
+  static int N=0; 
+  static int nMax=1;
+
+  if(newMax)  {nMax = newMax; N=0; return 0;}
+  if (N == nMax) N=0;
+  N = N +1;
+  return N;
+
+}
+
+//--------------------------------------------------------------------------------------------------------------------
+int PlotEMCALQATrendingTree(const char* filename="trending.root",Bool_t SavePlots=0, TString expr ="", TString fTrigger="")
+{
+
+  QAPATH = TString(gSystem->Getenv("QAPATH"));
+  if(QAPATH.IsNull()) QAPATH = QAPATHF;
+  Int_t ret=0;
+  TFile* f = TFile::Open(filename);
+  if(!f) { return -1;}
+  TTree* tree = (TTree*)f->Get("trending");
+  if (! tree) {Error("PlotEMCALQATrendingTree","No Tree found!"); return -1;}
+  TFile* fout = new TFile(Form("%s/trendingPlots.root",QAPATH.Data()),"RECREATE");
+
+  TList* TriggersList = new TList(); 
+  if (fTrigger=="")
+    {
+      tree->Draw("fTrigger","","goff");
+      const char* obj;
+      for(Int_t i = 0 ; i < tree->GetSelectedRows() ; i++){
+       tree->GetEntry(i);
+       obj = tree->GetVar1()->PrintValue(0);
+       if(! TriggersList->FindObject(obj)) {TriggersList->Add(new TObjString(obj));}
+      }
+    }
+  else 
+    { 
+      if(!fTrigger.Contains("QA")) {fTrigger = "CaloQA_" + fTrigger;}
+      TriggersList->Add(new TObjString(fTrigger.Data()));
+    }
+  TIter next(TriggersList);
+  TObject* obj1;
+  while ((obj1 = next()))
+    { 
+      ret = PlotEMCALQATrendingTree(tree,obj1->GetName(),fout,SavePlots,expr);
+    }
+  
+  f->Close(); 
+  return ret;
+
+}
+
+//--------------------------------------------------------------------------------------------------------------------
+int PlotEMCALQATrendingTree(TTree* tree, const char* Trig, TFile* fout, Bool_t SavePlots,TString Expr) 
+{
+
+  TCut trig = Form("fTrigger==\"%s\"",Trig);
+  TCut NotZero = TCut("Nevent>0.");
+  TCut select = trig;
+  if (Expr.Contains(".C"))
+    {
+      Info("PlotEMCALQATrendingTree",Form("Additional selections from %s: ", Expr.Data()));
+      gInterpreter->ExecuteMacro(Expr.Data());
+      select = trig + expr;
+   }
+
+  if (! tree) {Error("PlotEMCALQATrendingTree","No Tree found!"); return -1;}
+  select.Print();
+  int CurN=0;  
+  TString* fCalorimeter; 
+  TString* period;
+  TString* pass; 
+  TString* fTrigger; 
+  TString* system;
+  TDatime* dtime; 
+  tree->SetBranchAddress("fDate",&dtime);
+  tree->SetBranchAddress("nSM",&CurN);
+  tree->SetBranchAddress("fCalorimeter",&fCalorimeter);
+  tree->SetBranchAddress("system",&system);
+  tree->SetBranchAddress("period",&period);
+  tree->SetBranchAddress("pass",&pass);
+  tree->SetBranchAddress("fTrigger",&fTrigger);
+
+
+  tree->SetEventList(0);
+  tree->Draw(">>elist",select);
+  tree->Draw(">>listNotZero",select+NotZero);
+  TEventList* listNotZero = (TEventList*)gDirectory->Get("listNotZero");
+  TEventList* elist = (TEventList*)gDirectory->Get("elist");
+  tree->SetEventList(elist);
+  if(! elist->GetN()) { Error("PlotEMCALQATrendingTree","The current selection doess not match any entry!"); return -2; } 
+  CurN = tree->GetMinimum("nSM"); 
+  const Int_t n = CurN;
+  tree->GetEntry(elist->GetEntry(0));
+
+  TGraphErrors* AverNclustersSM[n];
+  TGraphErrors* AverNcellsPerClusterSM[n];
+  TGraphErrors* AverESM[n];
+  TGraphErrors* AverMeanSM[n];
+  TGraphErrors* AverWidthSM[n];
+  TGraphErrors* AverNpi0SM[n];
+
+  // --------------------------------- plots ------------------------------
+
+  TString base = QAPATH + period->Data() + "_" + pass->Data() + "_";
+  TPRegexp r("_\\w+");
+
+  TString ClusterAverages ;        ClusterAverages         = base + "ClAvNew"     + (*fTrigger)(r) + ".png";
+  TString Entries;                 Entries                 = base + "Nentries"    + (*fTrigger)(r) + ".png";
+  TString ClusterAveragesEnergy;   ClusterAveragesEnergy   = base + "ClAvEne"     + (*fTrigger)(r) + ".png";
+  TString ClusterAveragesEnergy2;  ClusterAveragesEnergy2  = base + "ClAvEne"     + (*fTrigger)(r) + ".pdf";
+  TString ClusterAveragesEntries;  ClusterAveragesEntries  = base + "ClAvEnt"     + (*fTrigger)(r) + ".png";
+  TString ClusterAveragesEntries2; ClusterAveragesEntries2 = base + "ClAvEnt"     + (*fTrigger)(r) + ".pdf";
+  TString ClusterAveragesCells;    ClusterAveragesCells    = base + "ClAvCells"   + (*fTrigger)(r) + ".png";
+  TString ClusterAveragesCells2;   ClusterAveragesCells2   = base + "ClAvCells"   + (*fTrigger)(r) + ".pdf";
+  TString Pi0Entries;              Pi0Entries              = base + "Pi0Entries"  + (*fTrigger)(r) + ".png";
+  TString Pi0Entries2;             Pi0Entries2             = base + "Pi0Entries"  + (*fTrigger)(r) + ".pdf";
+  TString Pi0Mass;                 Pi0Mass                 = base + "Pi0Mass"     + (*fTrigger)(r) + ".png";
+  TString Pi0Mass2;                Pi0Mass2                = base + "Pi0Mass"     + (*fTrigger)(r) + ".pdf";
+  TString Pi0Width;                Pi0Width                = base + "Pi0Width"    + (*fTrigger)(r) + ".png";
+  TString Pi0Width2;               Pi0Width2               = base + "Pi0Width"    + (*fTrigger)(r) + ".pdf";
+
+  
+  int nEmptyRuns = tree->Draw("run","Nevent==0","goff");
+  if (nEmptyRuns && (nEmptyRuns != -1)) { 
+   Info("PlotEMCALQATrendingTree",Form("The following %i runs are empty for trigger %s:",nEmptyRuns,Trig));
+   for(Int_t i = 0 ; i < nEmptyRuns ; i++){
+     cout<<tree->GetV1()[i]<<endl;
+   }  
+  }
+  int nRun =  tree->Draw("run","","goff");
+  NextInt(nRun); 
+  TH1F* h1 = new TH1F("h1", "dummy", nRun, 0., nRun+0.5); 
+  TGaxis::SetMaxDigits(3);
+  h1->SetTitle("") ;
+  h1->SetStats(kFALSE) ;
+  h1->SetAxisRange(0, nRun, "X") ;
+  h1->GetXaxis()->SetTitle("RUN Index");    
+  h1->GetXaxis()->SetTitleOffset(1.86);
+  h1->GetXaxis()->SetTitleSize(0.03);
+
+  for(Int_t i = 0 ; i < nRun ; i++){
+    TString label = " ";
+    label+=tree->GetV1()[i];
+    h1->GetXaxis()->SetBinLabel(i+1,label.Data());
+    h1->GetXaxis()->LabelsOption("v");
+  }
+  
+  //number of events 
+  TCanvas* c1 = new TCanvas("Nevents","Nb of events", 1000, 500);
+  c1->SetFillColor(0);
+  c1->SetBorderSize(0);
+  c1->SetFrameBorderMode(0); 
+  gStyle->SetOptStat(0);  
+  gPad->SetLeftMargin(0.08);
+  gPad->SetRightMargin(0.02);
+  c1->SetGrid();
+  tree->Draw("NextInt():Nevent","","goff");
+  h1->GetYaxis()->SetTitle("N_{events}"); 
+  ZoomFromTree(h1,tree,n,"Nevent",2);
+  if (h1->GetMinimum() > 0.) {c1->SetLogy();}
+  h1->Draw();
+
+  TGraph* Nevents = new TGraph(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2());
+  Nevents->SetMarkerStyle(20);
+  Nevents->SetMarkerColor(1);
+  Nevents->SetLineColor(2);
+  Nevents->Draw("same lp") ;
+
+  c1->Update();
+  if(SavePlots) c1->SaveAs(Entries);
+
+  TCanvas* c2 = new TCanvas("ClusterAveragesEvents", "Mean Nb of Cluster per Event", 1000, 500);
+  c2->SetFillColor(0);
+  c2->SetBorderSize(0);
+  c2->SetFrameBorderMode(0); 
+  c2->SetGrid();
+    
+  gPad->SetLeftMargin(0.08);
+  gPad->SetRightMargin(0.02);
+  gPad->SetGrid();
+
+  TH1F* h2 = (TH1F*)h1->Clone("");
+  h2->GetYaxis()->SetTitle("<N_{clusters}>/event");  
+  ZoomFromTree(h2,tree,n,"ClusterMeanSM");
+  h2->GetXaxis()->SetTitle("RUN Index");    
+  h2->GetXaxis()->SetTitleOffset(1.86);
+  h2->GetXaxis()->SetTitleSize(0.03);
+  h2->Draw();
+
+  tree->Draw("NextInt():ClusterMean:xe:ClusterRMS","","goff");
+  TGraphErrors * AverNclusters = new TGraphErrors(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2(),tree->GetV3(), tree->GetV4());
+  AverNclusters->SetMarkerStyle(20);
+  AverNclusters->SetMarkerColor(1);
+  AverNclusters->Draw("same P") ;  
+   
+  for(Int_t ism = 0 ; ism < n ; ism++){
+    tree->Draw(Form("NextInt():ClusterMeanSM[%i]:xe:ClusterRMSSM[%i]",ism,ism),"","goff");
+    AverNclustersSM[ism] = new  TGraphErrors(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2(),tree->GetV3(),tree->GetV4());
+    if (ism !=8)AverNclustersSM[ism]->SetMarkerColor(ism<10?ism+2:ism+1);else AverNclustersSM[ism]->SetMarkerColor(7);
+    AverNclustersSM[ism]->SetMarkerStyle(21+(ism<10 ? ism: ism-10));
+   
+    AverNclustersSM[ism]->Draw("same P");  
+  }
+
+  TLegend* l2 = new TLegend(0.123, 0.744, 0.933, 0.894);
+  l2->SetNColumns((n+1)/2.);
+  l2->SetFillColor(0);
+  l2->SetBorderSize(0);
+  l2->SetTextSize(0.04);
+  l2->SetHeader(Form("<# of clusters> in %s (period %s trigger %s)",fCalorimeter->Data(),period->Data(),((*fTrigger)(r)).Data()));
+  l2->AddEntry(AverNclusters,"average", "p");
+  for(Int_t ism = 0 ; ism < n ; ism++){
+    TString projname = Form("SM %d",ism);
+    l2->AddEntry(AverNclustersSM[ism],projname.Data(), "p");
+  }
+  l2->Draw("same");
+  c2->Update();
+  if(SavePlots)     c2->SaveAs(ClusterAveragesEntries);
+  if(SavePlots==2)  c2->SaveAs(ClusterAveragesEntries2);
+
+  TCanvas* c3 = new TCanvas("ClusterAveragesEnergy", "Mean Cluster Energy", 1000, 500);
+  c3->SetFillColor(0);
+  c3->SetBorderSize(0);
+  c3->SetFrameBorderMode(0); 
+  c3->SetGrid();
+
+  gPad->SetLeftMargin(0.08);
+  gPad->SetRightMargin(0.02);
+  gPad->SetGrid();
+
+  TH1F* h3 = (TH1F*)h1->Clone("");
+  h3->GetYaxis()->SetTitle("<E> (GeV)"); 
+  ZoomFromTree(h3,tree,n,"EtotalMeanSM"); 
+  h3->GetXaxis()->SetTitle("RUN Index");    
+  h3->GetXaxis()->SetTitleOffset(1.86);
+  h3->GetXaxis()->SetTitleSize(0.03);
+  h3->Draw();
+
+  tree->Draw("NextInt():EtotalMean:xe:EtotalRMS","","goff");
+  TGraphErrors * AverE = new TGraphErrors(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2(),tree->GetV3(),tree->GetV4());
+  AverE->SetMarkerStyle(20);
+  AverE->SetMarkerColor(1);
+  AverE->Draw("same P");
+  for(Int_t ism = 0 ; ism < n ; ism++){
+    
+    tree->Draw(Form("NextInt():EtotalMeanSM[%i]:xe:EtotalRMSSM[%i]",ism,ism),"","goff");
+    AverESM[ism] = new  TGraphErrors(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2(),tree->GetV3(),tree->GetV4());
+    if (ism !=8)AverESM[ism]->SetMarkerColor(ism<10?ism+2:ism+1);else AverESM[ism]->SetMarkerColor(7);
+    AverESM[ism]->SetMarkerStyle(21+(ism<10 ? ism: ism-10));
+    AverESM[ism]->Draw("same P");
+
+  }
+
+  TLegend* l3 = new TLegend(0.123, 0.744, 0.933, 0.894);
+  l3->SetNColumns((n+1)/2.);
+  l3->SetFillColor(0);
+  l3->SetBorderSize(0);
+  l3->SetTextSize(0.04);
+  l3->SetHeader(Form("<E> in %s (period %s trigger %s)",fCalorimeter->Data(),period->Data(),((*fTrigger)(r)).Data()));
+  l3->AddEntry(AverE,"average", "p");
+  for(Int_t ism = 0 ; ism < n ; ism++){
+    TString projname = Form("SM %d",ism);
+    l3->AddEntry(AverESM[ism],projname.Data(), "p");
+  }
+  l3->Draw("same");
+  
+  if(SavePlots) c3->SaveAs(ClusterAveragesEnergy);
+  if(SavePlots==2) c3->SaveAs(ClusterAveragesEnergy2);
+
+  TCanvas* c4 = new TCanvas("ClusterAveragesCells", "Mean Nb of Cells per Cluster", 1000, 500);
+  c4->SetFillColor(0);
+  c4->SetBorderSize(0);
+  c4->SetFrameBorderMode(0); 
+  c4->SetGrid();
+
+  gPad->SetLeftMargin(0.08);
+  gPad->SetRightMargin(0.02); 
+  gPad->SetGrid();
+
+  TH1F* h4 = (TH1F*)h1->Clone("");
+  h4->GetYaxis()->SetTitle("<N_{CellsPerCluster}>");  
+  ZoomFromTree(h4,tree,n,"CellPerClusterMeanSM");
+  h4->GetXaxis()->SetTitle("RUN Index");    
+  h4->GetXaxis()->SetTitleOffset(1.86);
+  h4->GetXaxis()->SetTitleSize(0.03);
+  h4->Draw();
+
+  // 
+  tree->Draw("NextInt():CellPerClusterMean:xe:CellPerClusterRMS","","goff");
+  TGraphErrors * AverCellPerCluster = new TGraphErrors(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2(),tree->GetV3(),tree->GetV4());
+  AverCellPerCluster->SetMarkerStyle(20);
+  AverCellPerCluster->SetMarkerColor(1);
+
+  for(Int_t ism = 0 ; ism < n ; ism++){
+    tree->Draw(Form("NextInt():CellPerClusterMeanSM[%i]:xe:CellPerClusterRMSSM[%i]",ism,ism),"","goff");
+    AverNcellsPerClusterSM[ism] =  new TGraphErrors(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2(),tree->GetV3(),tree->GetV4());
+    if (ism !=8)AverNcellsPerClusterSM[ism]->SetMarkerColor(ism<10?ism+2:ism+1);else AverNcellsPerClusterSM[ism]->SetMarkerColor(7);
+    AverNcellsPerClusterSM[ism]->SetMarkerStyle(21+(ism<10 ? ism: ism-10));
+    AverNcellsPerClusterSM[ism]->Draw("same P");
+  }
+
+  TLegend* l4 = new TLegend(0.123, 0.744, 0.933, 0.894);
+  l4->SetNColumns((n+1)/2.);
+  l4->SetFillColor(0);
+  l4->SetBorderSize(0);
+  l4->SetTextSize(0.04);
+  l4->SetHeader(Form("<# of cells per cluster> in %s (period %s trigger %s)",fCalorimeter->Data(),period->Data(),((*fTrigger)(r)).Data()));
+  l4->AddEntry(AverCellPerCluster,"average", "p");
+  for(Int_t ism = 0 ; ism < n ; ism++){
+    TString projname = Form("SM %d",ism);
+    l4->AddEntry(AverNcellsPerClusterSM[ism],projname.Data(), "p");
+  }
+  l4->Draw("same");
+  if(SavePlots) c4->SaveAs(ClusterAveragesCells);
+
+  TCanvas* c5 = new TCanvas("Pi0Position", "Mean Pi0 Mass", 1000, 500);
+  c5->SetFillColor(0);
+  c5->SetBorderSize(0);
+  c5->SetFrameBorderMode(0); 
+  c5->SetGrid();
+
+  gStyle->SetOptStat(0); 
+
+  gPad->SetLeftMargin(0.08);
+  gPad->SetRightMargin(0.02);
+  gPad->SetGrid();
+
+  TH1F * h5 = (TH1F*)h1->Clone("");
+  ZoomFromTree(h5,tree,n,"MeanPosSM");
+  h5->GetXaxis()->SetTitle("RUN Index");    
+  h5->GetXaxis()->SetTitleOffset(1.86);
+  h5->GetXaxis()->SetTitleSize(0.03);
+  h5->GetYaxis()->SetTitle("Mean_{#pi^{0}}");
+  h5->Draw();
+  
+  tree->Draw("NextInt():MeanPos:xe:MeanPosErr","","goff");
+  TGraphErrors * AverMean = new TGraphErrors(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2(),tree->GetV3(),tree->GetV4());
+  AverMean->SetMarkerStyle(20);
+  AverMean->SetMarkerColor(1);
+  AverMean->Draw("same P");
+  
+  for(Int_t ism = 0 ; ism < n ; ism++){
+
+    tree->Draw(Form("NextInt():MeanPosSM[%i]:xe:MeanPosErrSM[%i]",ism,ism),"","goff");
+    AverMeanSM[ism] = new TGraphErrors(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2(),tree->GetV3(),tree->GetV4());
+    if (ism !=8)AverMeanSM[ism]->SetMarkerColor(ism<10?ism+2:ism+1);else AverMeanSM[ism]->SetMarkerColor(7); 
+    AverMeanSM[ism]->SetMarkerStyle(21+(ism<10 ? ism: ism-10));
+    AverMeanSM[ism]->Draw("same P");
+  }
+  
+  TLegend* l5 = new TLegend(0.123, 0.744, 0.933, 0.894);
+  l5->SetNColumns((n+1)/2.);
+  l5->SetFillColor(0);
+  l5->SetBorderSize(0);
+  l5->SetTextSize(0.04);
+  l5->SetHeader(Form("<M_{#pi^{0}}> (MeV) in %s (period %s trigger %s)",fCalorimeter->Data(),period->Data(),((*fTrigger)(r)).Data()));
+  l5->AddEntry(AverMean,"average", "p");
+  for(Int_t ism = 0 ; ism < n ; ism++){
+    TString projname = Form("SM %d",ism);
+    l5->AddEntry(AverMeanSM[ism],projname.Data(), "p");         
+  }
+  l5->Draw("same");
+  
+  c5->Update();
+  if(SavePlots) c5->SaveAs(Pi0Mass);
+
+
+  TCanvas* c6 = new TCanvas("Pi0Width", "Mean Pi0 Width", 1000, 500);
+  c6->SetFillColor(0);
+  c6->SetBorderSize(0);
+  c6->SetFrameBorderMode(0); 
+  c6->SetGrid();
+
+  gPad->SetLeftMargin(0.08);
+  gPad->SetRightMargin(0.02);
+  gPad->SetGrid();
+
+  TH1F* h6 = (TH1F*)h1->Clone("");
+  ZoomFromTree(h6,tree,n,"WidthSM");
+  h6->GetXaxis()->SetTitle("RUN Index");   
+  h6->GetXaxis()->SetTitleOffset(1.86);
+  h6->GetXaxis()->SetTitleSize(0.03); 
+  h6->GetYaxis()->SetTitle("#sigma_{#pi^{0}}");  
+  h6->Draw();
+  
+  tree->Draw("NextInt():Width:xe:WidthErr","","goff");
+  TGraphErrors * AverWidth = new TGraphErrors(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2(),tree->GetV3(),tree->GetV4());
+  AverWidth->SetMarkerStyle(20);
+  AverWidth->SetMarkerColor(1);
+  AverWidth->Draw("same P");
+
+  for(Int_t ism = 0 ; ism < n ; ism++){
+    tree->Draw(Form("NextInt():WidthSM[%i]:xe:WidthErrSM[%i]",ism,ism),"","goff");
+    AverWidthSM[ism] = new TGraphErrors(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2(),tree->GetV3(),tree->GetV4());
+    if (ism !=8)AverWidthSM[ism]->SetMarkerColor(ism<10?ism+2:ism+1);else AverWidthSM[ism]->SetMarkerColor(7);
+    AverWidthSM[ism]->SetMarkerStyle(21+(ism<10 ? ism: ism-10));
+    AverWidthSM[ism]->Draw("same P");
+  }
+  
+  
+  TLegend* l6 = new TLegend(0.123, 0.744, 0.933, 0.894);
+  l6->SetNColumns((n+1)/2.);
+  l6->SetFillColor(0);
+  l6->SetBorderSize(0);
+  l6->SetTextSize(0.04);
+  l6->SetHeader(Form("#sigma_{#pi^{0}} in %s (period %s trigger %s)",fCalorimeter->Data(),period->Data(),((*fTrigger)(r)).Data()));
+  l6->AddEntry(AverWidth,"total", "p");
+  for(Int_t ism = 0 ; ism < n ; ism++){
+    TString projname = Form("SM %d",ism);
+    l6->AddEntry(AverWidthSM[ism],projname.Data(), "p");
+  }
+  l6->Draw("same");
+  c6->Update();
+  if(SavePlots) c6->SaveAs(Pi0Width);
+  TCanvas* c7 = new TCanvas("Npi0", "Mean Nb of Pi0", 1000, 500);
+  c7->SetFillColor(0);
+  c7->SetBorderSize(0);
+  c7->SetFrameBorderMode(0); 
+  c7->SetGrid();
+
+  gPad->SetLeftMargin(0.08);
+  gPad->SetRightMargin(0.02);
+  gPad->SetGrid();
+
+  TH1F* h7 = (TH1F*)h1->Clone("");
+  ZoomFromTree(h7,tree,n,"Npi0SM");
+  if (h7->GetMinimum() > 0.) {c7->SetLogy();} 
+  h7->GetXaxis()->SetTitle("RUN Index");    
+  h7->GetXaxis()->SetTitleOffset(1.86);
+  h7->GetXaxis()->SetTitleSize(0.03);
+  h7->GetYaxis()->SetTitle("<N_{#pi^{0}}>/event");  
+  h7->Draw();
+   
+  tree->Draw("NextInt():Npi0:xe:Npi0Err","","goff");
+  if (tree->GetMinimum("Npi0") > 1) c4->SetLogy();
+  TGraphErrors * AverNpi0 = new TGraphErrors(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2(),tree->GetV3(),tree->GetV4());
+  AverNpi0->SetMarkerStyle(20);
+  AverNpi0->SetMarkerColor(1);
+  AverNpi0->Draw("same P");
+  
+  for(Int_t ism = 0 ; ism < n ; ism++){
+    tree->Draw(Form("NextInt():Npi0SM[%i]:xe:Npi0ErrSM[%i]",ism,ism),"","goff");
+    AverNpi0SM[ism] = new  TGraphErrors(tree->GetSelectedRows(), tree->GetV1(), tree->GetV2(),tree->GetV3(),tree->GetV4());
+    if (ism !=8)AverNpi0SM[ism]->SetMarkerColor(ism<10?ism+2:ism+1);else AverNpi0SM[ism]->SetMarkerColor(7);
+    AverNpi0SM[ism]->SetMarkerStyle(21+(ism<10 ? ism: ism-10));
+    AverNpi0SM[ism]->Draw("same P");
+  }
+  
+  TLegend* l7 = new TLegend(0.123, 0.744, 0.933, 0.894);
+  l7->SetNColumns((n+1)/2.);
+  l7->SetFillColor(0);
+  l7->SetBorderSize(0);
+  l7->SetTextSize(0.04);
+  l7->SetHeader(Form("<N_{#pi^{0}}>/event in %s (period %s trigger %s)",fCalorimeter->Data(),period->Data(),((*fTrigger)(r)).Data()));
+  l7->AddEntry(AverNpi0,"total", "p");
+  for(Int_t ism = 0 ; ism < n ; ism++){
+    TString projname = Form("SM %d",ism);
+    l7->AddEntry(AverNpi0SM[ism],projname.Data(), "p");
+  }
+  l7->Draw("same");
+  c7->Update();
+  if(SavePlots)  c7->SaveAs(Pi0Entries);
+  if(SavePlots==2) c7->SaveAs(Pi0Entries2);
+
+  fout->mkdir(Form("%s/%s/%s/%s",period->Data(),pass->Data(),"TrendingQA",fTrigger->Data()));
+  fout->cd();
+  fout->Cd(Form("%s/%s/%s/%s",period->Data(),pass->Data(),"TrendingQA",fTrigger->Data()));
+
+  gROOT->GetListOfCanvases()->Write(); 
+  gROOT->GetListOfCanvases()->Delete();
+
+  if((!Expr.IsNull()) && (!Expr.EndsWith(".root"))) elist->Write();
+  if(listNotZero) {listNotZero->Reset();}
+  if(elist) {elist->Reset();}
+  delete h1; 
+
+  return 0; 
+
+}
+
+//---------------------------------------------------------------------------------------------
+TH1F* ZoomFromTree(TH1F* h, TTree* atree, Int_t n, const char* aVar, UShort_t  aScaleFactor)
+{
+
+  atree->SetEventList(0);
+  TEventList *listNotZero = (TEventList*)gDirectory->Get("listNotZero");
+  atree->SetEventList(listNotZero);
+
+  double treeMin = GetTreeMinimum(atree,n,aVar);
+  double treeMax = GetTreeMaximum(atree,n,aVar);
+  double offset =  30*((treeMax - treeMin)/(100.*aScaleFactor));
+
+  if(treeMin != -treeMax){
+   h->SetMinimum(TMath::Max(0.,treeMin-offset));
+   h->SetMaximum(treeMax+2*offset);
+  }
+  atree->SetEventList(0);
+  TEventList *elist = (TEventList*)gDirectory->Get("elist");
+  atree->SetEventList(elist);
+
+  return h; 
+
+}
+
+//--------------------------------------------------------------------------------------------
+Double_t GetTreeMinimum(TTree* aTree,Int_t n, const char* columname)
+{      
+
+  TLeaf* leaf = aTree->GetLeaf(columname);
+  if (!leaf) {
+    return 0;
+  }
+  TBranch* branch = leaf->GetBranch();
+  Double_t cmin = 3.40282e+38; 
+  for (Long64_t i = 0; i < aTree->GetEntries(); ++i) {
+    Long64_t entryNumber = aTree->GetEntryNumber(i);
+    if (entryNumber < 0) break;
+    branch->GetEntry(entryNumber);
+    for (Int_t j = 0;j < TMath::Min(leaf->GetLen(),n); ++j) {
+      Double_t val = leaf->GetValue(j);
+      if (val < cmin) {
+       cmin = val;
+      }
+    }
+  }
+  
+  return cmin;
+
+}
+
+//______________________________________________________________________________
+Double_t GetTreeMaximum(TTree* aTree,Int_t n,const char* columname)
+{
+
+  TLeaf* leaf = aTree->GetLeaf(columname);
+  if (!leaf) {
+    return 0;
+  }
+  TBranch* branch = leaf->GetBranch();
+  Double_t cmax = - 3.40282e+38;
+  for (Long64_t i = 0; i < aTree->GetEntries(); ++i) {
+    Long64_t entryNumber = aTree->GetEntryNumber(i);
+    if (entryNumber < 0) break;
+    branch->GetEntry(entryNumber);
+    for (Int_t j = 0; j <  TMath::Min(leaf->GetLen(),n); ++j) {
+      Double_t val = leaf->GetValue(j);
+      if (val > cmax) {
+       cmax = val;
+      }
+    }
+  }
+
+  return cmax;
+
+}
+
diff --git a/PWGPP/EMCAL/QA/macros/runEMCALQA.pl b/PWGPP/EMCAL/QA/macros/runEMCALQA.pl
new file mode 100755 (executable)
index 0000000..c89da1d
--- /dev/null
@@ -0,0 +1,275 @@
+#!/usr/bin/perl -w
+# runEMCALQA.pl v.0.5 A.SHABETAI alexandre.shabetai@cern.ch
+
+use Cwd 'abs_path';
+use File::Basename;
+use File::Path qw(mkpath );
+use File::Copy;
+use Getopt::Long;
+
+use strict;
+use warnings;
+
+##########################################################
+# What this script is doing and how to use it
+
+sub usage()
+{
+ print STDERR << "EOF";
+ This script runs the EMCAL QA macros on selected runs.
+
+ usage: $0 --period <PERIOD> --pass <PASS> [ --gridprefix <GRIDPREFIX> ] [--extraGridPath <EXTRAGRIDPATH> ] [ --runlist <runlist.txt> ] [ --col <pp||PbPb> ] 
+
+ -h --help       : shows this (help) messag
+The following parameters are mendatory: 
+ --period        : the running period to consider                                                                                                        (ex: LHC1XX                  )
+ --pass          : the production pass to use (use "simu" for simulated data)                                                                            (ex: pass1                   )    
+
+ You may specify the following options if you want to change their default values: 
+ --runlist       : a text file with the list of runs to consider - one run by line   (default: <period>-<pass>-runlist.txt                              ) (ex: MyLHC13arunlist.txt     )
+ --extraGridPath : extra grid path to use                                            (default: none                                                     ) (ex: ESDs/QA68               )
+ --localpath     : path where the existing local QAresults files are stored          (default: <period>/<pass>                                          ) (ex: <a_prefix>              )
+ --savePlots     : save the plots as image files (0: no ; 1:png ; 2: png + pdf)      (default: 1 (png)                                                  ) (ex: 0                       )   
+ --debug         : debug flag (0 or 1)                                               (default; 0                                                        ) (ex: 1                       )
+ --gridQAname    : basename QA filename on the grid (without the .root suffix)      (default: QAresults                                                ) (ex: QAresults               )    
+ --gridTimeOut   : timeOut for grid acces                                           (default: 10 s                                                     ) (ex: 10                      )
+ --gridprefix    : the begining of the grid path to use                              (default: /alice/data/<year>/<period> - or .../sim/... if pass=simu) (ex: /alice/data/201X/LHC1XX )
+ --filter        : filter the input file                                             (default: 0 (no)                                                   ) (ex: 1                      )
+ --treeSelections: filename of file containing additional cuts on the trending tree  (default: none                                                     ) (ex: MySelection.C           )
+ --trigger       : force to use the specified trigger name                           (default: trigger names are automaticly read from the input files  ) (ex: trigEMC                 )
+ --col          : force the type of colisions pp or PbPb                            (default: pp - or PbPb if period ends with "h"                     ) (ex: PbPb                    )      
+                         
+ NB: all switches can be abreviated ex: --period is valid as well as -pe
+
+  example: $0  --period LHC13a --pass pass1 
+EOF
+
+exit;
+
+}
+
+#############################################################################
+# the values above should not be changed (please use the command lune options instead)
+
+my $help;
+my $period;
+my $pass;
+my $gridprefix;
+my $localpath;
+my $runlist;
+my $col;
+my $extragridPath;
+my $savePlots = 0;
+my $debug = 0;
+my $filter = 0;
+my $trigger = ""; 
+my $GridTimeOut = 10;
+my $gridQAname = "QAresults";
+my $treeSelections = ""; 
+
+#############################################################################
+# get options 
+
+GetOptions ( 
+ "help!" => \$help,
+ "period=s"  => \$period, # string
+ "pass=s" => \$pass, # string
+ "gridprefix=s" => \$gridprefix, #string
+ "localpath=s" => \$localpath, #string
+ "runlist=s" => \$runlist, #string
+ "col=s" => \$col, #string
+ "extraGridPath=s" => \$extragridPath, #string
+ "savePlots=i" => \$savePlots, #int
+ "debug=i" => \$debug, #int
+ "filter=i" => \$filter, #bool
+ "triggerForced=s" => \$trigger,
+ "gridTimeOut=i" => \$GridTimeOut, #int
+ "gridQAname=s" => \$gridQAname, #string
+ "treeSelections=s" => \$treeSelections) #string
+ or die("Error in command line arguments\n");
+ usage() if ($help);
+ die "Missing --period! (you can get help with $0 -h)" unless $period;
+ die "Missing --pass! (you can get help with $0 -h)" unless $pass;
+
+if ($pass eq "sim") {$pass= "simu";}
+if (!(defined($runlist))) {$runlist = "$period-$pass-runlist.txt";}
+if (!(defined($col)) && index($period, 'h') != -1) {$col = "PbPb";}
+if (!(defined($col))) {$col = "pp";}
+
+if (!(defined($gridprefix))) {
+ my $year=sprintf("20%s",substr($period, 3, 2));
+ if ($pass ne "simu") {$gridprefix = "/alice/data/$year/$period";} else {$gridprefix = "/alice/sim/$year/$period";}
+}
+if (!(defined($extragridPath))) {
+  if    (($pass ne "simu") && (index($pass, 'c') != -1)) { $extragridPath = $pass;}
+  elsif ($pass ne "simu") { $extragridPath = "ESDs/$pass";}
+  else  {$extragridPath = "";}
+ }
+
+##############################################################################
+# the values above should not be changed
+
+my $macroDir = abs_path(dirname($0));
+my $locDir = "$period/$pass";
+$ENV{QAPATH} = "$locDir/";
+my $processedrunlist = "$locDir/processed.txt";
+my $notprocessedrunlist = "$locDir/notprocessed.txt";
+my $exit_code = 0;
+
+my $calo = "EMCAL";
+my @gridsuffixes = qw(.root);
+if (index($pass, 'c') != -1) {@gridsuffixes = qw(_barrel.root _outer.root);}
+if (!(defined($localpath))) {$localpath = $locDir;} else {$localpath = $localpath."/";}
+
+###############################################################################
+# sanity checks
+
+if (! -e $locDir) {mkpath($locDir);}
+if ((defined(glob("$locDir/*data.txt")))) {unlink(glob("$locDir/*data.txt"));}
+my $includePath = qx{aliroot -b -l << EOF
+.include
+EOF 
+};
+if (index($includePath,"$ENV{ALICE_ROOT}/include") == -1) 
+  {print "Please add \$ALICE_ROOT/include to your include path using a rootlogon.C of .rootrc "; exit;}
+
+my $ALIEN_ROOT = $ENV{'ALIEN_ROOT'};
+if (!(defined($ALIEN_ROOT))) {die "ALIEN_ROOT not defined!";}
+my $proxyValidity = qx{$ALIEN_ROOT/api/bin/xrdgsiproxy info 2>&1 | grep "time left" | cut -d " " -f 6 | cut -d: -f1}; chomp($proxyValidity);
+if (!(defined($proxyValidity)) || $proxyValidity eq "0h") {  die "No valid proxy found (or proxy valid for less that one hour). Nothing done!"};
+my $isValidToken = qx{$ALIEN_ROOT/api/bin/alien-token-info | grep -c "Token is still valid"};
+if ($isValidToken==0) { die "No valid token found. Nothing done!";}
+#############################################################################t
+# start working
+
+open(STDOUT, "| tee -i \"$locDir/$period\_$pass\_EMCALQA.log\"");
+open(STDERR, '>&STDOUT');
+open(FIN, $runlist) or die "Could not open $runlist: $! please specify --runlist of create $runlist";
+open(FOUT, ">$processedrunlist") or die "Could not open $processedrunlist: $!";
+open(FOUT2, ">$notprocessedrunlist") or die "Could not open $notprocessedrunlist: $!";
+
+print "\n Executing $0";
+ foreach (@ARGV)  { print " $_";} 
+print " ...\n";
+
+# read the run list
+my @runs;
+while( my $line = <FIN>)  {
+    chomp($line);  
+    my @fields = split(/,/, $line);
+    push @runs, @fields
+}
+    @runs = sort { $a <=> $b } @runs;
+
+# create the directory structure and copy the output of the QA train from the grid
+    foreach my $run (@runs) {   
+    $run =~ tr/ //ds;
+    if($pass ne "simu") {$run = sprintf("%09d", $run);}
+    print "\nProcessing run $run...\n";
+    foreach my $suffix (@gridsuffixes) {
+     my $gridFile = "alien://$gridprefix/$run/$extragridPath/$gridQAname$suffix"; 
+     my $shortrun = $run; $shortrun =~ s/^0+//; $shortrun =~ s/ +$//; 
+     my $locFileName = "$shortrun$suffix"; 
+    
+     print "\n Processing file $locFileName...\n";
+    
+     if (! -e "$locDir/$run") {mkdir("$locDir/$run");} #
+
+if ($localpath eq $locDir) {
+     for (my $trial = 1; $trial <= 2; $trial++)  
+     {  
+      system("root -b -l -q \'$macroDir/CopyQAFile.C+g\(\"$gridFile\",\"$localpath\",kFALSE,\"$locFileName\",$GridTimeOut\)\'");  
+      $exit_code = $?>>8;
+    
+     if (! $exit_code) { print "\nFile $gridQAname$suffix processed succesfully (run $shortrun, try $trial)\n";last} else { print "\nThe processing of file $gridQAname$suffix (run $shortrun) failed! (try $trial)\n";};
+     if ($exit_code eq 252 || $exit_code eq 253) {unlink("$localpath/$locFileName"); }
+    }  
+ }
+# run the run level QA for the runs that were selected (i.e in the runlist and that do have a valid local QA output filie).
+
+ if (!$exit_code) {
+
+  if (-e "$localpath/$locFileName" )  { 
+
+   system("aliroot -b -q \'$macroDir/CreateEMCALRunQA.C+g\(\"$localpath/$locFileName\",\"$run\",\"$period\",\"$pass\",$savePlots,$filter,\"$trigger\",\"$col\",\"$calo\"\)\'"); 
+   $exit_code = $?>>8;
+   
+   if (! $exit_code) {  print FOUT "$shortrun\n"; print "\nCreateEMCALRunQA() for file $gridQAname$suffix processed succesfully (run $shortrun)\n";} else { print FOUT2 "$shortrun\n" ; print "\nThe processing of CreateEMCALRunQA() for file $gridQAname$suffix failed! (run $shortrun)\n";};
+  
+ if ($suffix ne ".root") { move("$locDir/$run/trending.root", "$locDir/$run/trending$suffix"); move("$locDir/$run/${period}_${pass}_${shortrun}_QAplots.root","$locDir/$run/${period}_${pass}_${shortrun}_QAplots$suffix");}
+
+   } else { print " File not found: $localpath/$locFileName";} }
+  } 
+}
+close FIN;
+close FOUT;
+close FOUT2;
+$exit_code = 0;
+
+#################################################################################
+# merge the QA trees
+
+if ((! $exit_code) && defined(glob("$locDir/*/trendin*.root")) && (-e glob("$locDir/*/trendin*.root")))
+{
+
+ print "\nMerging....\n";      
+ system("hadd -v 1 -f $locDir/trending.root $locDir/*/trendin*.root");
+ $exit_code = $?>>8;
+
+ if (! $debug) { system("rm $locDir/*/trendin*.root"); }
+
+} 
+################################################################################
+# process and plot the period level QA 
+
+print "\n";
+
+if ((! $exit_code) && (-e "$locDir/trending.root")) { system("root -b -l -q \'$macroDir/PlotEMCALQATrendingTree.C(\"$locDir/trending.root\",$savePlots,\"$treeSelections\",\"$trigger\"\)\'"); }
+
+$exit_code = $?>>8;
+if (! $exit_code) { print "\nPlotEMCALQATrendingTree() processed succesfully\n";} else { print "\nThe processing of PlotEMCALQATrendingTree() failed!\n";};
+   
+################################################################################
+# cleanup
+
+move($processedrunlist,"$locDir/runlist.txt")  or die "Cannot move the runlist to the correct local directory : $!";
+move("$locDir/trendingPlots.root","$locDir/$period"."_$pass"."_trendingPlots.root");
+
+################################################################################
+# final merging
+
+if ((! $exit_code) && defined(glob("$locDir/*/${period}_${pass}_*_QAplot*.root $locDir/${period}_${pass}_trendingPlots.root $locDir/trending.root")) && (-e glob("$locDir/*/${period}_${pass}_*_QAplot*.root $locDir/${period}_${pass}_trendingPlots.root $locDir/trending.root")))
+{
+
+ print "\n Final Merging....\n";
+
+ system("hadd -v 1 -f $locDir/${period}_${pass}_EMCALQA.root  $locDir/*/${period}_${pass}_*_QAplot*.root $locDir/${period}_${pass}_trendingPlots.root $locDir/trending.root");
+
+ if (! $debug) {system("rm -f  $locDir/*/${period}_${pass}_*_QAplot*.root $locDir/${period}_${pass}_trendingPlots.root"); }
+
+}
+
+###############################################################################
+# cleanup some files used for debugging
+
+if (! $debug && (defined(glob("$locDir/*/*.txt")))) {unlink(glob("$locDir/*/*.txt"));}
+if (! $debug && (defined(glob("$locDir/*.txt")))) {unlink(glob("$locDir/*.txt"));}
+if (! $debug && ! $savePlots && (defined(glob("$locDir/*/"))))  {system("rmdir --ignore-fail-on-non-empty  $locDir/*/");}
+
+
+##############################################################################
+#| make final pdf
+
+if ((! $exit_code) && -e "$locDir/${period}_${pass}_EMCALQA.root") { system("root -b -l -q \'$macroDir/MakeQAPdf.C+g(\"$locDir/${period}_${pass}_EMCALQA.root\"\)\'"); }
+
+
+##############################################################################
+#┬áthat's all falks 
+
+print "\n Done! \n";
+
+
diff --git a/PWGPP/QA/detectorQAscripts/EMC.sh b/PWGPP/QA/detectorQAscripts/EMC.sh
new file mode 100755 (executable)
index 0000000..e38558a
--- /dev/null
@@ -0,0 +1,113 @@
+#available variables:
+#  $dataType     e.g. data or sim
+#  $year         e.g. 2011
+#  $period       e.g. LHC13g
+#  $runNumber    e.g. 169123
+#  $pass         e.g. cpass1,pass1,passMC
+
+runLevelQA()
+{
+qaFile=$1
+MACRODIR=$ALICE_ROOT/PWGPP/EMCAL/QA/macros
+SaveImages=0
+
+suffix=".root"
+new_suffix=".root"
+
+echo "processing $qaFile" 
+echo 
+
+aliroot -b  << EOF
+gSystem->AddIncludePath("-I${ALICE_ROOT}/include")
+gSystem->SetBuildDir("./",kTRUE)
+.L $MACRODIR/CreateEMCALRunQA.C+g
+CreateEMCALRunQA("$qaFile","$runNumber","$period","$pass",$SaveImages)
+.q
+EOF
+
+if [[ $qaFile == *outer* ]] 
+then
+suffix=_outer.root
+new_suffix=_barrel.root
+fi
+
+if [[ $qaFile == *barrel* ]]
+then
+suffix=_barrel.root
+new_suffix=_outer.root
+fi
+
+if [[ "$suffix" != ".root" ]]
+then
+
+mv trending.root trending$suffix
+mv ${period}_${pass}_${runNumber}_QAplots.root ${period}_${pass}_${runNumber}_QAplots$suffix
+
+qaFile=${qaFile/$suffix/$new_suffix}
+
+echo
+echo "processing $qaFile" 
+echo
+
+aliroot -b  << EOF
+gSystem->AddIncludePath("-I${ALICE_ROOT}/include")
+gSystem->SetBuildDir("./",kTRUE)
+.L $MACRODIR/CreateEMCALRunQA.C+g
+CreateEMCALRunQA("$qaFile","$runNumber","$period","$pass",$SaveImages)
+.q
+EOF
+
+mv trending.root trending$new_suffix
+mv ${period}_${pass}_${runNumber}_QAplots.root ${period}_${pass}_${runNumber}_QAplots$new_suffix
+
+echo
+
+hadd -v 1 -f trending.root trending_*.root
+rm -f trending_*.root
+
+fi
+
+rm -f *.d *.so *.txt
+
+}
+
+periodLevelQA()
+{
+
+trendingFile=$1
+MACRODIR=$ALICE_ROOT/PWGPP/EMCAL/QA/macros
+SaveImages=0
+
+echo
+echo "Producing PeriodLevel QA plots" 
+echo
+
+root -b  << EOF
+gSystem->AddIncludePath("-I${ALICE_ROOT}/include");
+gSystem->SetBuildDir("./",kTRUE)
+.L $MACRODIR/PlotEMCALQATrendingTree.C
+PlotEMCALQATrendingTree("$trendingFile",$SaveImages)
+.q
+EOF
+
+mv trendingPlots.root ${period}_${pass}_trendingPlots.root
+
+echo 
+
+hadd -v 1 -f ${period}_${pass}_EMCALQA.root */*QAplot*.root ${period}_${pass}_trendingPlots.root $trendingFile
+
+echo
+echo "Producing QA PDF file" 
+echo
+
+root -b -l  << EOF
+gSystem->AddIncludePath("-I${ALICE_ROOT}/include")
+gSystem->SetBuildDir("./",kTRUE)
+.L $MACRODIR/MakeQAPdf.C+g
+MakeQAPdf("${period}_${pass}_EMCALQA.root")
+.q
+EOF
+
+rm -f *.d *.C *.so ${period}_${pass}_trendingPlots.root
+
+}