end-of-line normalization
[u/mrichter/AliRoot.git] / PWGPP / TRD / AliTRDrecoTask.cxx
index 67198bc..1cc07f0 100644 (file)
-///////////////////////////////////////////////////////\r
-//\r
-// Basic class for Performance/Calibration TRD tasks\r
-// \r
-// It performs generic tasks like :\r
-//   - data file manegment\r
-//   - reference container management\r
-//   - debug container management\r
-//   - interaction with AliAnalysisManager\r
-//   - Plot functor loop\r
-//\r
-// Author: Alexandru Bercuci <A.Bercuci@gsi.de>, 10/09/2008\r
-//\r
-/////////////////////////////////////////////////////////\r
-\r
-#include "TClass.h"\r
-#include "TMethod.h"\r
-#include "TMethodCall.h"\r
-#include "TMethodArg.h"\r
-#include "TFile.h"\r
-#include "TChain.h"\r
-#include "TList.h"\r
-#include "TMap.h"\r
-#include "TH1.h"\r
-#include "TH2.h"\r
-#include "TH3.h"\r
-#include "TF1.h"\r
-#include "TObjArray.h"\r
-#include "TDirectory.h"\r
-#include "TTreeStream.h"\r
-#include "TBox.h"\r
-#include "TLatex.h"\r
-#include "TVectorT.h"\r
-\r
-#include "AliLog.h"\r
-#include "AliAnalysisTask.h"\r
-#include "AliAnalysisManager.h"\r
-#include "AliExternalTrackParam.h"\r
-\r
-#include "info/AliTRDchmbInfo.h"\r
-#include "info/AliTRDeventInfo.h"\r
-#include "info/AliTRDtrendingManager.h"\r
-#include "AliTRDrecoTask.h"\r
-#include "AliTRDtrackV1.h"\r
-#include "AliTRDpidUtil.h"\r
-\r
-ClassImp(AliTRDrecoTask)\r
-\r
-Float_t AliTRDrecoTask::fgPt[AliTRDrecoTask::fgNPt+1] = {0.};\r
-TTreeSRedirector* AliTRDrecoTask::fgDebugStream(NULL);\r
-TH1* AliTRDrecoTask::fgProjector(NULL);\r
-//_______________________________________________________\r
-AliTRDrecoTask::AliTRDrecoTask()\r
-  : AliAnalysisTaskSE()\r
-  ,fNRefFigures(0)\r
-  ,fDets(NULL)\r
-  ,fDetsV(NULL)\r
-  ,fContainer(NULL)\r
-  ,fEvent(NULL)\r
-  ,fTracks(NULL)\r
-  ,fClusters(NULL)\r
-  ,fkClusters(NULL)\r
-  ,fkTrack(NULL)\r
-  ,fkMC(NULL)\r
-  ,fkESD(NULL)\r
-  ,fSpecies(-6)\r
-  ,fTriggerSlot(0)\r
-  ,fPt(-1.)\r
-  ,fPhi(0.)\r
-  ,fEta(0.)\r
-  ,fNpt(0)\r
-  ,fTriggerList(NULL)\r
-  ,fPlotFuncList(NULL)\r
-  ,fDetFuncList(NULL)\r
-  ,fRunTerminate(kFALSE)\r
-{\r
-// Default constructor\r
-  snprintf(fNameId, 10, "no name");\r
-}\r
-\r
-//_______________________________________________________\r
-AliTRDrecoTask::AliTRDrecoTask(const char *name, const char *title)\r
-  : AliAnalysisTaskSE(name)\r
-  ,fNRefFigures(0)\r
-  ,fDets(NULL)\r
-  ,fDetsV(NULL)\r
-  ,fContainer(NULL)\r
-  ,fEvent(NULL)\r
-  ,fTracks(NULL)\r
-  ,fClusters(NULL)\r
-  ,fkClusters(NULL)\r
-  ,fkTrack(NULL)\r
-  ,fkMC(NULL)\r
-  ,fkESD(NULL)\r
-  ,fSpecies(-6)\r
-  ,fTriggerSlot(0)\r
-  ,fPt(-1.)\r
-  ,fPhi(0.)\r
-  ,fEta(0.)\r
-  ,fNpt(0)\r
-  ,fTriggerList(NULL)\r
-  ,fPlotFuncList(NULL)\r
-  ,fDetFuncList(NULL)\r
-  ,fRunTerminate(kFALSE)\r
-{\r
-// Constructor for all derived performance tasks\r
-\r
-  SetTitle(title);\r
-  snprintf(fNameId, 10, "no name");\r
-  DefineInput (1, TObjArray::Class()); // track list\r
-  DefineInput (2, AliTRDeventInfo::Class()); // event info object\r
-  DefineInput (3, TObjArray::Class()); // cluster list object\r
-  DefineOutput(1, TObjArray::Class()); // histogram list\r
-}\r
-\r
-//_______________________________________________________\r
-AliTRDrecoTask::~AliTRDrecoTask() \r
-{\r
-\r
-  // Generic task destructor\r
-\r
-  AliDebug(2, Form(" Ending task %s[%s]", GetName(), GetTitle()));\r
- if(fgDebugStream){\r
-    delete fgDebugStream;\r
-    fgDebugStream = NULL;\r
-  }\r
-\r
-  if(fgProjector){\r
-    delete fgProjector;\r
-    fgProjector = NULL;\r
-  }\r
-\r
-  if(fPlotFuncList){\r
-    fPlotFuncList->Delete();\r
-    delete fPlotFuncList;\r
-    fPlotFuncList = NULL;\r
-  }\r
-  if(fDetFuncList){\r
-    fDetFuncList->Delete();\r
-    delete fDetFuncList;\r
-    fDetFuncList = NULL;\r
-  }\r
-  \r
-  if(fDets){\r
-    if(fDets->IsOwner()) fDets->Delete();\r
-    delete fDets;\r
-    fDets = NULL;\r
-  }\r
-  if(fDetsV) delete fDetsV; fDetsV=NULL;\r
-  if(fTriggerList){fTriggerList->Delete(); delete fTriggerList;}\r
-\r
-  if(fContainer && !(AliAnalysisManager::GetAnalysisManager() && AliAnalysisManager::GetAnalysisManager()->IsProofMode())){\r
-    if(fContainer->IsOwner()) fContainer->Delete();\r
-    delete fContainer;\r
-    fContainer = NULL;\r
-  }\r
-\r
-/*  if(fgTrendPoint){\r
-    TFile::Open("TRD.PerformanceTrend.root", "UPDATE");\r
-    fgTrendPoint->Write();\r
-    delete fgTrendPoint;\r
-    fgTrendPoint=NULL;\r
-    gFile->Close();\r
-  }*/\r
-}\r
-\r
-//_______________________________________________________\r
-Int_t AliTRDrecoTask::GetNRefFigures() const  \r
-{ \r
-  if(!fNRefFigures) AliWarning("No reference plots available.");\r
-  return fNRefFigures; \r
-} \r
-\r
-//____________________________________________________________________\r
-Int_t AliTRDrecoTask::GetPtBin(Float_t pt)\r
-{\r
-// Get significant (very low, low, medium, high, very high) pt bin\r
-\r
-  Int_t ipt(0);\r
-  while(ipt<fNpt){\r
-    if(pt<fgPt[ipt]) break;\r
-    ipt++;\r
-  }\r
-  return ipt-1;\r
-}\r
-\r
-//_______________________________________________________\r
-Bool_t AliTRDrecoTask::MakeMomSegmentation()\r
-{\r
-  switch(fNpt){\r
-  case fgNPt:\r
-    fgPt[0]=0.3;\r
-    for(Int_t j(1); j<=fgNPt; j++) fgPt[j]=fgPt[j-1]+(TMath::Exp(j*j*2.e-3)-1.);\r
-    AliDebug(2, "Using debug momentum segmentation");\r
-    break;\r
-  case 4:\r
-    fgPt[0]=0.5; fgPt[1]=0.8; fgPt[2]=1.5; fgPt[3]=5.;\r
-    AliDebug(2, "Using default momentum segmentation");\r
-    break;\r
-  default:\r
-    AliError(Form("Momentum segmentation %d not supported.", fNpt));\r
-    fNpt=0;\r
-    return kFALSE;\r
-  }\r
-  return kTRUE;\r
-}\r
-\r
-//_______________________________________________________\r
-void AliTRDrecoTask::UserCreateOutputObjects()\r
-{\r
-  if(!HasFunctorList()) InitFunctorList();\r
-  if(DebugLevel()) fNpt = fgNPt;\r
-  else fNpt = 4;\r
-  MakeMomSegmentation();\r
-\r
-  fContainer = Histos();\r
-  PostData(1, fContainer);\r
-}\r
-\r
-//_______________________________________________________\r
-void AliTRDrecoTask::UserExec(Option_t *)\r
-{\r
-// Loop over Plot functors published by particular tasks\r
-\r
-  fTracks   = dynamic_cast<TObjArray *>(GetInputData(1));\r
-  fEvent    = dynamic_cast<AliTRDeventInfo *>(GetInputData(2));\r
-  fTriggerSlot=0;\r
-  if(fTriggerList && fEvent){\r
-    for(Int_t itrig(0); itrig<fTriggerList->GetEntries(); itrig++){\r
-      if(!fEvent->GetFiredTriggerClasses().Contains(((TObjString*)(*fTriggerList)[itrig])->GetName())) continue;\r
-      //printf("\"%s\" selected\n", ((TObjString*)(*fTriggerList)[itrig])->GetName());\r
-      SETBIT(fTriggerSlot,itrig);\r
-    }\r
-    if(!fTriggerSlot){\r
-      AliDebug(2, Form("Triggers[%s] not used for %s", fEvent->GetFiredTriggerClasses().Data(),  GetName()));\r
-      return;\r
-    }\r
-  }\r
-  fClusters = dynamic_cast<TObjArray*>(GetInputData(3));\r
-\r
-  if(!fPlotFuncList){\r
-    AliWarning("No track functor list defined for the task");\r
-    return;\r
-  }\r
-  if(!fEvent || !fTracks) return;\r
-  if(!fTracks->GetEntriesFast()) return;\r
-  else AliDebug(2, Form("Tracks[%d] for %s", fTracks->GetEntriesFast(), GetName()));\r
-\r
-  Int_t itrk(-1);\r
-  AliTRDtrackInfo *trackInfo(NULL);\r
-  TIter plotIter(fPlotFuncList);\r
-  TObjArrayIter trackIter(fTracks);\r
-  while((trackInfo = dynamic_cast<AliTRDtrackInfo*>(trackIter()))){\r
-    itrk++; fPt=-1; fEta=0.; fPhi=0.; fSpecies=-6;\r
-    fkMC    = trackInfo->GetMCinfo();\r
-    fkESD   = trackInfo->GetESDinfo();\r
-    if((fkTrack = trackInfo->GetTrack())){\r
-      // cache properties of the track at TRD entrance\r
-      // check input track status\r
-      AliExternalTrackParam *tin(NULL);\r
-      if(!(tin = fkTrack->GetTrackIn())) AliDebug(2, Form("Missing TRD track[%d] :: entry point.", itrk));\r
-      else {\r
-        fPt   = tin->Pt();\r
-        fEta  = tin->Eta();\r
-        Double_t xyz[3];\r
-        if(!tin->GetXYZ(xyz)) AliDebug(2, Form("Failed TRD track[%d] :: global track postion", itrk));\r
-        else fPhi  = TMath::ATan2(xyz[1], xyz[0]);\r
-        fSpecies= fkTrack->Charge()*(AliTRDpidUtil::Mass2Pid(fkTrack->GetMass())+1);\r
-      }\r
-    } else AliDebug(2, Form("Missing TRD track[%d].", itrk));\r
-\r
-    TMethodCall *plot(NULL);\r
-    plotIter.Reset();\r
-    while((plot=dynamic_cast<TMethodCall*>(plotIter()))) plot->Execute(this);\r
-  }\r
-  if(!fClusters) return;\r
-  if(!fDetFuncList){\r
-    AliDebug(1, "No detector functor list defined for task");\r
-    return;\r
-  }\r
-  TIter detIter(fDetFuncList);\r
-  for(Int_t idet(0); idet<AliTRDgeometry::kNdet; idet++){\r
-    if(!(fkClusters = (TObjArray*)fClusters->At(idet))) continue;\r
-    TMethodCall *det(NULL);\r
-    detIter.Reset();\r
-    while((det=dynamic_cast<TMethodCall*>(detIter()))) det->Execute(this);\r
-  }\r
-}\r
-\r
-//_______________________________________________________\r
-Bool_t AliTRDrecoTask::GetRefFigure(Int_t /*ifig*/)\r
-{\r
-  AliWarning("Retrieving reference figures not implemented.");\r
-  return kFALSE;\r
-}\r
-\r
-//_______________________________________________________\r
-Bool_t AliTRDrecoTask::PutTrendValue(const Char_t *name, Double_t val, Double_t err)\r
-{\r
-// Generic publisher for trend values\r
-\r
-  AliTRDtrendingManager *tm = AliTRDtrendingManager::Instance();\r
-  if(!tm){\r
-    AliError("Wrong usage of the trending functionality. Could not instantiate AliTRDtrendingManager singleton.");\r
-    return kFALSE;\r
-  }\r
-  tm->AddValue(Form("%s_%s", GetName(), name), val, err);\r
-  return kTRUE;\r
-}\r
-\r
-//_______________________________________________________\r
-void AliTRDrecoTask::InitFunctorList()\r
-{\r
-// Initialize list of functors\r
-\r
-  TClass *c = this->IsA();\r
-  if(fPlotFuncList) fPlotFuncList->Clear();\r
-  if(fDetFuncList) fDetFuncList->Clear();\r
-\r
-  TMethod *m(NULL);\r
-  TIter methIter(c->GetListOfMethods());\r
-  while((m=dynamic_cast<TMethod*>(methIter()))){\r
-    TString name(m->GetName());\r
-    if(name.BeginsWith("Plot")){\r
-      if(!fPlotFuncList) fPlotFuncList = new TList();\r
-      fPlotFuncList->AddLast(new TMethodCall(c, (const char*)name, ""));\r
-    } else if(name.BeginsWith("Det")){\r
-      if(!fDetFuncList) fDetFuncList = new TList();\r
-      fDetFuncList->AddLast(new TMethodCall(c, (const char*)name, ""));\r
-    }\r
-  }\r
-}\r
-\r
-//_______________________________________________________\r
-Bool_t AliTRDrecoTask::Load(const Char_t *file, const Char_t *dir)\r
-{\r
-// Generic container loader\r
-\r
-  if(!TFile::Open(file)){\r
-    AliWarning(Form("Couldn't open file %s.", file));\r
-    return kFALSE;\r
-  }\r
-  if(!gFile->cd(dir)){\r
-    AliWarning(Form("Couldn't cd to %s in %s.", dir, file));\r
-    gFile->Close();\r
-    return kFALSE;\r
-  }\r
-  if(!(fContainer = (TObjArray*)gDirectory->Get(GetName()))){\r
-    AliWarning("Missing histogram container.");\r
-    gFile->Close();\r
-    return kFALSE;\r
-  }\r
-  gFile->Close();\r
-  return kTRUE;\r
-}\r
-\r
-//________________________________________________________\r
-Bool_t AliTRDrecoTask::LoadDetectorMap(const Char_t *file, const Char_t *dir)\r
-{\r
-// Load detector map.\r
-\r
-  if(!TFile::Open(file)){\r
-    AliWarning(Form("Couldn't open file %s.", file));\r
-    return kFALSE;\r
-  }\r
-  if(!gFile->cd(dir)){\r
-    AliWarning(Form("Couldn't cd to %s in %s.", dir, file));\r
-    gFile->Close();\r
-    return kFALSE;\r
-  }\r
-  TObjArray *info = NULL;\r
-  if(!(info = (TObjArray*)gDirectory->Get("TRDinfoGen"))){\r
-    AliWarning("Missing TRDinfoGen container.");\r
-    gFile->Close();\r
-    return kFALSE;\r
-  }\r
-\r
-  if(info->FindObject("Chambers Status"))\r
-    fDets = (TObjArray*)((TObjArray*)info->FindObject("Chambers Status"))->Clone();\r
-\r
-  if(!fDets){\r
-    if(!info->At(4) || strcmp("TObjArray", info->At(4)->IsA()->GetName())) AliError("Looking for old style chamber status map. Failed.");\r
-    else {\r
-      AliWarning("Looking for old style chamber status map.");\r
-      fDetsV = (TObjArray*)((TObjArray*)info->At(4))->Clone();\r
-    }\r
-  }\r
-  gFile->Close();\r
-  info->Delete(); delete info;\r
-  return kTRUE;\r
-}\r
-\r
-\r
-//________________________________________________________\r
-Bool_t AliTRDrecoTask::Save(TObjArray * const results){\r
-  //\r
-  // Store the output graphs in a ROOT file\r
-  // Input TObject array will not be written as Key to the file,\r
-  // only content itself\r
-  //\r
-\r
-  TDirectory *cwd = gDirectory;\r
-  if(!TFile::Open(Form("TRD.Result%s.root", GetName()), "RECREATE")) return kFALSE;\r
-\r
-  TIterator *iter = results->MakeIterator();\r
-  TObject *inObject = NULL, *outObject = NULL;\r
-  while((inObject = iter->Next())){\r
-    outObject = inObject->Clone();\r
-    outObject->Write(NULL, TObject::kSingleKey);\r
-  }\r
-  delete iter;\r
-  gFile->Close(); delete gFile;\r
-  cwd->cd(); \r
-  return kTRUE;\r
-}\r
-\r
-//_______________________________________________________\r
-Bool_t AliTRDrecoTask::PostProcess()\r
-{\r
-// To be implemented by particular tasks\r
-\r
-  AliWarning("Post processing of reference histograms not implemented.");\r
-  return kTRUE;\r
-}\r
-\r
-//_______________________________________________________\r
-void AliTRDrecoTask::MakeDetectorPlot(Int_t ly, const Option_t *opt)\r
-{\r
-// Draw chamber boundaries in eta/phi plots with misalignments\r
-// based on info collected by AliTRDinfoGen\r
-\r
-  if(!fDets){\r
-    AliWarning("NEW Detector map and status not available. Try OLD");\r
-    MakeDetectorPlotOLD(ly, opt);\r
-    return;\r
-  }\r
-  AliTRDchmbInfo *ci(NULL);\r
-  for(Int_t idet(0); idet<fDets->GetEntriesFast(); idet++){\r
-    if(!(ci = (AliTRDchmbInfo*)fDets->At(idet))) continue;\r
-    if(AliTRDgeometry::GetLayer(ci->GetDetector()) != ly) continue;\r
-    ci->Draw(opt);\r
-  }\r
-}\r
-\r
-//_______________________________________________________\r
-void AliTRDrecoTask::MakeDetectorPlotOLD(Int_t ly, const Option_t *opt)\r
-{\r
-// Draw chamber boundaries in eta/phi plots with misalignments\r
-// based on info collected by AliTRDinfoGen OLD data storage\r
-\r
-  if(!fDetsV){\r
-    AliError("OLD Detector map and status not available.");\r
-    return;\r
-  }\r
-  if(!fDetsV->GetEntries()){\r
-    AliError("OLD Detector map and status not filled.");\r
-    return;\r
-  }\r
-\r
-  Float_t xmin(0.), xmax(0.);\r
-  TBox *gdet = new TBox();\r
-  gdet->SetLineColor(kBlack);gdet->SetFillColor(kBlack);\r
-  Int_t style[] = {0, 3003};\r
-  for(Int_t idet(0); idet<540; idet++){\r
-    if(idet%6 != ly) continue;\r
-    TVectorF *det((TVectorF*)fDetsV->At(idet));\r
-    if(!det) continue;\r
-    Int_t iopt = Int_t((*det)[4]);\r
-    if(strcmp(opt, "eta")==0){\r
-      xmin=(*det)[0]; xmax=(*det)[2];\r
-    } else if(strcmp(opt, "pad")==0){\r
-      Int_t stk(AliTRDgeometry::GetStack(idet));\r
-      xmin=-0.6+16*(4-stk)-(stk<2?4:0); xmax=xmin+(stk==2?12:16)-0.2;\r
-    } else continue;\r
-    AliDebug(2, Form("det[%03d] 0[%+4.1f(%+4.1f) %+4.1f] 1[%+4.1f(%+4.1f) %+4.1f] opt[%d]", idet, xmin, (*det)[0], (*det)[1], xmax, (*det)[2], (*det)[3], iopt));\r
-    if(iopt==1){\r
-      gdet->SetFillStyle(style[1]);gdet->SetFillColor(kBlack);\r
-      gdet->DrawBox(xmin, (*det)[1], xmax, (*det)[3]);\r
-    } else {\r
-      gdet->SetFillStyle(style[0]);\r
-      gdet->DrawBox(xmin, (*det)[1], xmax, (*det)[3]);\r
-      if(iopt==2){\r
-        gdet->SetFillStyle(style[1]);gdet->SetFillColor(kGreen);\r
-        gdet->DrawBox(xmin, (*det)[1], xmax, 0.5*((*det)[3]+(*det)[1]));\r
-      } else if(iopt==3){\r
-        gdet->SetFillStyle(style[1]);gdet->SetFillColor(kRed);\r
-        gdet->DrawBox(xmin, 0.5*((*det)[3]+(*det)[1]), xmax, (*det)[3]);\r
-      } else if(iopt!=0) AliError(Form("Wrong chmb. status[%d] for det[%03d]", iopt, idet));\r
-    }\r
-  }\r
-  Float_t dsm = TMath::TwoPi()/AliTRDgeometry::kNsector;\r
-  xmin=0.;\r
-  if(strcmp(opt, "pad")==0) xmin=38.;\r
-  TLatex *sm = new TLatex(); sm->SetTextAlign(22);sm->SetTextColor(kBlack); sm->SetTextFont(32);sm->SetTextSize(0.03);\r
-  for(Int_t is(0); is<AliTRDgeometry::kNsector; is++) sm->DrawLatex(xmin, -TMath::Pi()+(is+0.5)*dsm, Form("%02d", is>=9?(is-9):(is+9)));\r
-}\r
-\r
-\r
-//_______________________________________________________\r
-void AliTRDrecoTask::MakeSummary()\r
-{\r
-// To be implemented by particular tasks\r
-  AliWarning("Summary not available");\r
-}\r
-\r
-//_______________________________________________________\r
-void AliTRDrecoTask::SetDebugLevel(Int_t level)\r
-{\r
-// Generic debug handler\r
-\r
-  AliAnalysisTaskSE::SetDebugLevel(level);\r
-  if(DebugLevel()>=1 && !fgDebugStream){\r
-    AliInfo(Form("Debug Level for Task %s set to %d", GetName(), level));\r
-    TDirectory *savedir = gDirectory;\r
-    fgDebugStream = new TTreeSRedirector("TRD.DebugPerformance.root", "RECREATE");\r
-    savedir->cd();\r
-  }\r
-}\r
-\r
-//____________________________________________________________________\r
-void AliTRDrecoTask::Terminate(Option_t *)\r
-{\r
-  //\r
-  // Terminate\r
-  //\r
-\r
-  if(fgDebugStream){ \r
-    delete fgDebugStream;\r
-    fgDebugStream = NULL;\r
-  }\r
-  fContainer = dynamic_cast<TObjArray *>(GetOutputData(1));\r
-  if(fContainer && fRunTerminate){\r
-    PostProcess();\r
-    MakeSummary();\r
-  }\r
-}\r
-\r
-//________________________________________________________\r
-Float_t AliTRDrecoTask::SetNormZ(TH2 *h2, Int_t bxmin, Int_t bxmax, Int_t bymin, Int_t bymax, Float_t thr)\r
-{\r
-// Normalize histo content to the mean value in the range specified by bin ranges\r
-// [bxmin, bxmax] on the x axis and [bymin, bymax] on the y axis.\r
-// Optionally a threshold "thr" can be specified to disregard entries with no meaning\r
-\r
-  Float_t s = 0., c=0.; Int_t is(0);\r
-  for(Int_t ix(bxmin); ix<=(bxmax>0?bxmax:(h2->GetXaxis()->GetNbins())); ix++){\r
-    for(Int_t iy(bymin); iy<=(bymax>0?bymax:(h2->GetYaxis()->GetNbins())); iy++){\r
-      if((c = h2->GetBinContent(ix, iy))<thr) continue;\r
-      s += c; is++;\r
-    }\r
-  }\r
-  s/= (is?is:1);\r
-  for(Int_t ix(1); ix<=h2->GetXaxis()->GetNbins(); ix++){\r
-    for(Int_t iy(1); iy<=h2->GetYaxis()->GetNbins(); iy++){\r
-      if((c = h2->GetBinContent(ix, iy))<thr) h2->SetBinContent(ix, iy, thr-1000);\r
-      else h2->SetBinContent(ix, iy, 100.*(c/s-1.));\r
-    }\r
-  }\r
-  return s;\r
-}\r
-\r
-//________________________________________________________\r
-void AliTRDrecoTask::SetRangeZ(TH2 *h2, Float_t min, Float_t max, Float_t thr)\r
-{\r
-// Set range on Z axis such to avoid outliers\r
-\r
-  Float_t c(0.), dz(1.e-3*(max-min));\r
-  for(Int_t ix(1); ix<=h2->GetXaxis()->GetNbins(); ix++){\r
-    for(Int_t iy(1); iy<=h2->GetYaxis()->GetNbins(); iy++){\r
-      if((c = h2->GetBinContent(ix, iy))<thr) continue;\r
-      if(c<=min) h2->SetBinContent(ix, iy, min+dz);\r
-    }\r
-  }\r
-  h2->GetZaxis()->SetRangeUser(min, max);\r
-}\r
-\r
-//________________________________________________________\r
-Float_t AliTRDrecoTask::GetMeanStat(TH1 *h, Float_t cut, Int_t opt, Float_t *sigma)\r
-{\r
-// Return mean number of entries/bin of histogram "h".\r
-// If optionally sigma is allocated than it is also filled with sigma paramter of the gauss fit \r
-//\r
-// Option "opt" is given the following values are accepted:\r
-//   -1 : consider only entries less than "cut"\r
-//   1  : consider only entries greater than "cut"\r
-//   0  : no "cut" [dafault]\r
-// Error codes\r
-//   -999. : statistics too low [20]\r
-//   -998. : fit failed\r
-\r
-  const Int_t kvd(100000);\r
-  Float_t v[kvd];\r
-  Int_t nbx(h->GetNbinsX()), nby(h->GetNbinsY()), nbz(h->GetNbinsZ());\r
-  Int_t nv(0); Float_t xmin(1.e5), xmax(-xmin);\r
-  for(Int_t ix(1); ix<=nbx; ix++){\r
-    for(Int_t iy(1); iy<=nby; iy++){\r
-      for(Int_t iz(1); iz<=nbz; iz++){\r
-        Float_t c = h->GetBinContent(ix, iy, iz);\r
-        if(opt*(c-cut)<0.) continue;\r
-        v[nv++] = c;\r
-        if(c<xmin) xmin = c;\r
-        if(c>xmax) xmax = c;\r
-        if(nv==kvd){\r
-          printf("W - AliTRDrecoTask::GetMeanStat() :: Unreliable results for %s[%s]. Statical allocation exceeded.\n", h->GetName(), h->GetTitle());\r
-          break;\r
-        }\r
-      }\r
-      if(nv==kvd) break;\r
-    }\r
-    if(nv==kvd) break;\r
-  }\r
-  if(nv<10){\r
-    //printf("W - AliTRDrecoTask::GetMeanStat() :: Failed for %s[%s]. Statical undefined [%d].\n", h->GetName(), h->GetTitle(), nv);\r
-    return -999.;\r
-  }\r
-  if(fgProjector) delete fgProjector;\r
-  fgProjector = new TH1F("hProjector", "", 20, 0.5*(3*xmin-xmax), 0.5*(3*xmax - xmin));\r
-  for(Int_t iv(0); iv<nv; iv++) fgProjector->Fill(v[iv]);\r
-  TF1 f("f", "gaus", xmin, xmax);\r
-  f.SetParameter(0, fgProjector->Integral());\r
-  f.SetParameter(1, fgProjector->GetMean()); f.SetParLimits(1, xmin, xmax);\r
-  f.SetParameter(2, fgProjector->GetRMS());\r
-  if(fgProjector->Fit(&f, "WQ0", "goff")) return -998.;\r
-  if(sigma) *sigma = f.GetParameter(2);\r
-  return f.GetParameter(1);\r
-}\r
-\r
-//________________________________________________________\r
-Int_t AliTRDrecoTask::Rebin(TH2 *h, Int_t n, Int_t rebinX[], Int_t rebinY[], Int_t nstat)\r
-{\r
-// Rebin histo "h" according to "rebinning" strategy "n" steps such to obtain mean statistics per bin over "nstat"\r
-\r
-  Int_t irebin(0);\r
-  while(irebin<n && GetMeanStat(h, .5, 1)<nstat){\r
-    h->Rebin2D(rebinX[irebin], rebinY[irebin]);\r
-    irebin++;\r
-  }\r
-  return irebin;\r
-}\r
-\r
-//________________________________________________________\r
-AliTRDrecoTask::AliTRDrecoProjection::AliTRDrecoProjection()\r
-  :TNamed()\r
-  ,fH(NULL)\r
-  ,fNrebin(0)\r
-{\r
-  // constructor\r
-  fRebin[0] = NULL;fRebin[1] = NULL;\r
-  memset(fAx, 0, 3*sizeof(Int_t));\r
-  memset(fRange, 0, 4*sizeof(Float_t));\r
-}\r
-\r
-//________________________________________________________\r
-AliTRDrecoTask::AliTRDrecoProjection::~AliTRDrecoProjection()\r
-{\r
-  // destructor\r
-  if(fH) delete fH;\r
-  if(fRebin[0]) delete [] fRebin[0];\r
-  if(fRebin[1]) delete [] fRebin[1];\r
-}\r
-\r
-//________________________________________________________\r
-void AliTRDrecoTask::AliTRDrecoProjection::Build(const Char_t *n, const Char_t *t, Int_t ix, Int_t iy, Int_t iz, TAxis *aa[])\r
-{\r
-// check and build (if neccessary) projection determined by axis "ix", "iy" and "iz"\r
-  if(!aa[ix] || !aa[iy] || !aa[iz]) return;\r
-  TAxis *ax(aa[ix]), *ay(aa[iy]), *az(aa[iz]);\r
-  // check ax definiton to protect against older versions of the data\r
-  if(ax->GetNbins()<=0 || (ax->GetXmax()-ax->GetXmin())<=0.){\r
-    AliWarning(Form("Wrong definition of axis[%d] \"%s\"[%d](%f %f).", ix, ax->GetTitle(), ax->GetNbins(), ax->GetXmin(), ax->GetXmax()));\r
-    return;\r
-  }\r
-  if(ay->GetNbins()<=0 || (ay->GetXmax()-ay->GetXmin())<=0.){\r
-    AliWarning(Form("Wrong definition of axis[%d] \"%s\"[%d](%f %f).", ix, ay->GetTitle(), ay->GetNbins(), ay->GetXmin(), ay->GetXmax()));\r
-    return;\r
-  }\r
-  if(az->GetNbins()<=0 || (az->GetXmax()-az->GetXmin())<=0.){\r
-    AliWarning(Form("Wrong definition of axis[%d] \"%s\"[%d](%f %f).", ix, az->GetTitle(), az->GetNbins(), az->GetXmin(), az->GetXmax()));\r
-    return;\r
-  }\r
-  SetNameTitle(n,t);\r
-  fH = new TH3I(n, Form("%s;%s;%s;%s", t, ax->GetTitle(), ay->GetTitle(), az->GetTitle()),\r
-    ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),\r
-    ay->GetNbins(), ay->GetXmin(), ay->GetXmax(),\r
-    az->GetNbins(), az->GetXmin(), az->GetXmax());\r
-  fAx[0] = ix; fAx[1] = iy; fAx[2] = iz;\r
-  fRange[0] = az->GetXmin()/3.; fRange[1] = az->GetXmax()/3.;\r
-  AliDebug(2, Form("H3(%s, %s) :: %s[%3d %4.2f %4.2f]%s[%3d %4.2f %4.2f]%s[%3d %4.2f %4.2f]", n, t,\r
-    ax->GetTitle(), ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),\r
-    ay->GetTitle(), ay->GetNbins(), ay->GetXmin(), ay->GetXmax(),\r
-    az->GetTitle(), az->GetNbins(), az->GetXmin(), az->GetXmax()));\r
-}\r
-\r
-//________________________________________________________\r
-AliTRDrecoTask::AliTRDrecoProjection& AliTRDrecoTask::AliTRDrecoProjection::operator=(const AliTRDrecoProjection& rhs)\r
-{\r
-// copy projections\r
-  if(this == &rhs) return *this;\r
-\r
-  TNamed::operator=(rhs);\r
-  if(fNrebin){fNrebin=0; delete [] fRebin[0]; delete [] fRebin[1];}\r
-  if(rhs.fNrebin) SetRebinStrategy(rhs.fNrebin, rhs.fRebin[0], rhs.fRebin[1]);\r
-  memcpy(fAx, rhs.fAx, 3*sizeof(Int_t));\r
-  memcpy(fRange, rhs.fRange, 4*sizeof(Float_t));\r
-  if(fH) delete fH;\r
-  if(rhs.fH) fH=(TH3I*)rhs.fH->Clone(Form("%s_CLONE", rhs.fH->GetName()));\r
-  return *this;\r
-}\r
-\r
-//________________________________________________________\r
-AliTRDrecoTask::AliTRDrecoProjection& AliTRDrecoTask::AliTRDrecoProjection::operator+=(const AliTRDrecoProjection& other)\r
-{\r
-// increment projections\r
-  if(!fH || !other.fH) return *this;\r
-  AliDebug(2, Form("%s+=%s [%s+=%s]", GetName(), other.GetName(), fH->GetName(), (other.fH)->GetName()));\r
-  fH->Add(other.fH);\r
-  return *this;\r
-}\r
-\r
-//________________________________________________________\r
-void AliTRDrecoTask::AliTRDrecoProjection::Increment(Int_t bin[], Double_t v)\r
-{\r
-// increment bin with value "v" pointed by general coord in "bin"\r
-  if(!fH) return;\r
-  AliDebug(4, Form("  %s[%2d]", fH->GetName(), Int_t(v)));\r
-  fH->AddBinContent(fH->GetBin(bin[fAx[0]],bin[fAx[1]],bin[fAx[2]]), Int_t(v));\r
-}\r
-\r
-//________________________________________________________\r
-Double_t AliTRDrecoTask::AliTRDrecoProjection::GetTrendValue(const Int_t mid, Double_t *e, Double_t *s, Double_t *se) const\r
-{\r
-//   Return result of fitting the main distribution (represented on the z axis) with the function selected\r
-// "mid". Optionally return the Mean and RMS of the distribution pointing to "m" and "s"\r
-\r
-  if(!fH){\r
-    AliDebug(1, Form("Missing 3D in %s", GetName()));\r
-    return -999.;\r
-  }\r
-  TH1 *h1s(NULL);\r
-  if(!(h1s = (TH1D*)fH->Project3D("z"))){\r
-    AliDebug(1, Form("Failed Project3D(\"z\") in %s", GetName()));\r
-    return -999.;\r
-  }\r
-  Int_t ne((Int_t)h1s->Integral());\r
-  if(ne<30){\r
-    AliDebug(1, Form("Statistics too low[%2d] in %s", ne, GetName()));\r
-    delete h1s;\r
-    return -999.;\r
-  }\r
-  TAxis *az(h1s->GetXaxis());\r
-  Float_t mn(h1s->GetMean()), rms(h1s->GetRMS()),\r
-          v(mn),  // main trending value (mean, mu, MPV)\r
-          ve(rms),// dispersion (RMS, sigma, landau 2nd param)\r
-          ev(h1s->GetMeanError()), // error on v\r
-          eve(h1s->GetRMSError());// error on ve\r
-  if(mid==1){\r
-    TF1 fg("fg", "gaus", az->GetXmin(), az->GetXmax());\r
-    fg.SetParameter(0, Float_t(ne)); fg.SetParameter(1, mn); fg.SetParameter(2, rms);\r
-    h1s->Fit(&fg, "WQ0");\r
-    v = fg.GetParameter(1); ev = fg.GetParError(1);\r
-    ve= fg.GetParameter(2); eve= fg.GetParError(2);\r
-  } else if (mid==2) {\r
-    TF1 fl("fl", "landau", az->GetXmin(), az->GetXmax());\r
-    fl.SetParameter(0, Float_t(ne)); fl.SetParameter(1, mn); fl.SetParameter(2, rms);\r
-    h1s->Fit(&fl, "WQ0");\r
-    v = fl.GetMaximumX(); ev = fl.GetParError(1);\r
-    ve= fl.GetParameter(2);eve= fl.GetParError(2);\r
-  }\r
-  if(e)  *e  = ev;\r
-  if(s)  *s  = ve;\r
-  if(se) *se = eve;\r
-  AliDebug(2, Form("[%d] %s(%4d) = M{%f+-%f} S{%f+-%f}", mid, fH->GetName(), (Int_t)h1s->Integral(), v, ev, ve, eve));\r
-\r
-  delete h1s;\r
-  return v;\r
-}\r
-\r
-//________________________________________________________\r
-TH2* AliTRDrecoTask::AliTRDrecoProjection::Projection2Dbin(Int_t bin, Bool_t mc)\r
-{\r
-// dumb 2D projection for bin including under/over flow. Default all [bin==-1]\r
-\r
-  TAxis *ax(fH->GetXaxis()), *ay(fH->GetYaxis()), *az(fH->GetZaxis());\r
-  Int_t nbins(az->GetNbins());\r
-  TH2F *h2(NULL);\r
-  if(bin<0) h2 = new TH2F(Form("%s_2D", fH->GetName()),\r
-                Form("%s;%s;%s;Entries", fH->GetTitle(), ax->GetTitle(), ay->GetTitle()),\r
-                ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),\r
-                ay->GetNbins(), ay->GetXmin(), ay->GetXmax());\r
-  else h2 = new TH2F(Form("%s%d_2D", fH->GetName(), bin),\r
-                Form("%s | #it{%4.2f<=p_{t}^{%s}[GeV/c]<%4.2f};%s;%s;Entries", fH->GetTitle(),\r
-                bin?fgPt[bin-1]:0., mc?"MC":"", bin>nbins?99.99:fgPt[bin], ax->GetTitle(), ay->GetTitle()),\r
-                ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),\r
-                ay->GetNbins(), ay->GetXmin(), ay->GetXmax());\r
-  for(Int_t ix(1); ix<=ax->GetNbins(); ix++){\r
-    for(Int_t iy(1); iy<=ay->GetNbins(); iy++){\r
-      Int_t ibin = h2->GetBin(ix, iy);\r
-      for(Int_t iz(0); iz<=az->GetNbins()+1; iz++){\r
-        if(bin<0) h2->AddBinContent(ibin, fH->GetBinContent(ix, iy, iz));\r
-        else if(bin==iz){\r
-          h2->AddBinContent(ibin, fH->GetBinContent(ix, iy, iz));\r
-          break;\r
-        }\r
-      }\r
-    }\r
-  }\r
-  return h2;\r
-}\r
-\r
-//________________________________________________________\r
-TH2* AliTRDrecoTask::AliTRDrecoProjection::Projection2D(const Int_t nstat, const Int_t ncol, const Int_t mid, Bool_t del)\r
-{\r
-// build the 2D projection and adjust binning\r
-\r
-  const Char_t *title[] = {"Mean", "#mu", "MPV"};\r
-  if(!fH){\r
-    AliDebug(1, Form("Missing 3D in %s", GetName()));\r
-    return NULL;\r
-  }\r
-  TAxis *ax(fH->GetXaxis()), *ay(fH->GetYaxis()), *az(fH->GetZaxis());\r
-  TH2D *h2s(NULL), *hyx(NULL);\r
-  if(!(h2s = (TH2D*)fH->Project3D("yx"))){\r
-    AliDebug(1, Form("Failed Project3D(\"yx\") in %s", GetName()));\r
-    return NULL;\r
-  }\r
-  // save a copy of the original distribution\r
-  if(!del){\r
-    hyx = (TH2D*)h2s->Clone();\r
-    hyx->SetName(Form("%sEn", fH->GetName()));\r
-  }\r
-  Int_t irebin(Rebin(h2s, fNrebin, fRebin[0], fRebin[1], nstat)), dxBin(1), dyBin(1);\r
-  for(Int_t ir(0); ir<irebin; ir++){dxBin*=fRebin[0][ir]; dyBin*=fRebin[1][ir];}\r
-  Int_t nx(h2s->GetNbinsX()), ny(h2s->GetNbinsY());\r
-  delete h2s;\r
-  if(mid<0) return NULL;\r
-\r
-  // start projection\r
-  TH1 *h(NULL); Int_t n(0);\r
-  Float_t dz=(fRange[1]-fRange[1])/ncol;\r
-  TString titlez(az->GetTitle()); TObjArray *tokenTitle(titlez.Tokenize(" "));\r
-  Int_t nt(tokenTitle->GetEntriesFast());\r
-  TH2 *h2(NULL);\r
-  if((h2 = (TH2*)gDirectory->Get(Form("%s_2D", fH->GetName())))) delete h2; // avoid ROOT warning messages\r
-  h2 = new TH2F(Form("%s_2D", fH->GetName()),\r
-            Form("%s;%s;%s;%s(%s) %s", fH->GetTitle(), ax->GetTitle(), ay->GetTitle(), title[mid], nt>0?(*tokenTitle)[0]->GetName():"", nt>1?(*tokenTitle)[1]->GetName():""),\r
-            nx, ax->GetXmin(), ax->GetXmax(), ny, ay->GetXmin(), ay->GetXmax());\r
-  tokenTitle->Delete(); delete tokenTitle;\r
-  h2->SetContour(ncol);\r
-  h2->GetZaxis()->CenterTitle();\r
-  h2->GetZaxis()->SetTitleOffset(1.4);\r
-  h2->GetZaxis()->SetRangeUser(fRange[0], fRange[1]);\r
-  AliDebug(2, Form("%s[%s] nx[%d] ny[%d]", h2->GetName(), h2->GetTitle(), nx, ny));\r
-  for(Int_t iy(0); iy<ny; iy++){\r
-    for(Int_t ix(0); ix<nx; ix++){\r
-      h = fH->ProjectionZ(Form("%s_z", h2->GetName()), ix*dxBin+1, (ix+1)*dxBin, iy*dyBin+1, (iy+1)*dyBin);\r
-      Int_t ne((Int_t)h->Integral());\r
-      //printf("  x[%2d %2d] y[%2d %2d] ne[%4d]\n", ix*dxBin+1, (ix+1)*dxBin, iy*dyBin+1, (iy+1)*dyBin, ne);\r
-      if(ne<nstat/2){\r
-        h2->SetBinContent(ix+1, iy+1, -999);\r
-        h2->SetBinError(ix+1, iy+1, 1.);\r
-        n++;\r
-      }else{\r
-        // redo the projection by adding 1 bin @ left and 1 bin @ right for smoothing\r
-        h = fH->ProjectionZ(Form("%s_z", h2->GetName()), ix*dxBin, (ix+1)*dxBin+1, iy*dyBin, (iy+1)*dyBin+1);\r
-        Float_t v(h->GetMean()), ve(h->GetRMS());\r
-        if(mid==1){\r
-          TF1 fg("fg", "gaus", az->GetXmin(), az->GetXmax());\r
-          fg.SetParameter(0, Float_t(ne)); fg.SetParameter(1, v); fg.SetParameter(2, ve);\r
-          h->Fit(&fg, "WQ0");\r
-          v = fg.GetParameter(1); ve = fg.GetParameter(2);\r
-        } else if (mid==2) {\r
-          TF1 fl("fl", "landau", az->GetXmin(), az->GetXmax());\r
-          fl.SetParameter(0, Float_t(ne)); fl.SetParameter(1, v); fl.SetParameter(2, ve);\r
-          h->Fit(&fl, "WQ0");\r
-          v = fl.GetMaximumX(); ve = fl.GetParameter(2);\r
-/*          TF1 fgle("gle", "[0]*TMath::Landau(x, [1], [2], 1)*TMath::Exp(-[3]*x/[1])", az->GetXmin(), az->GetXmax());\r
-          fgle.SetParameter(0, fl.GetParameter(0));\r
-          fgle.SetParameter(1, fl.GetParameter(1));\r
-          fgle.SetParameter(2, fl.GetParameter(2));\r
-          fgle.SetParameter(3, 1.);fgle.SetParLimits(3, 0., 5.);\r
-          h->Fit(&fgle, "WQ");\r
-          v = fgle.GetMaximumX(); ve = fgle.GetParameter(2);*/\r
-        }\r
-        if(v<fRange[0]) h2->SetBinContent(ix+1, iy+1, fRange[0]+0.1*dz);\r
-        else h2->SetBinContent(ix+1, iy+1, v);\r
-        h2->SetBinError(ix+1, iy+1, ve);\r
-      }\r
-    }\r
-  }\r
-  if(h) delete h;\r
-  if(n==nx*ny){  // clean empty projections\r
-    AliDebug(1, Form("Empty projection in %s", GetName()));\r
-    delete h2; h2=NULL;\r
-  }\r
-  return h2;\r
-}\r
-\r
-//________________________________________________________\r
-void AliTRDrecoTask::AliTRDrecoProjection::SetRebinStrategy(Int_t n, Int_t rebx[], Int_t reby[])\r
-{\r
-// define rebinning strategy for this projection\r
-  fNrebin = n;\r
-  fRebin[0] = new Int_t[n]; memcpy(fRebin[0], rebx, n*sizeof(Int_t));\r
-  fRebin[1] = new Int_t[n]; memcpy(fRebin[1], reby, n*sizeof(Int_t));\r
-}\r
-\r
-//________________________________________________________\r
-void AliTRDrecoTask::SetTriggerList(const Char_t *tl)\r
-{\r
-// Store list of triggers to be monitored\r
-  TString stl(tl);\r
-  if(fTriggerList){ fTriggerList->Delete(); delete fTriggerList;}\r
-  TObjArray *atl = stl.Tokenize(" ");\r
-  fTriggerList = (TObjArray*)atl->Clone("");\r
-  atl->Delete(); delete atl;\r
-  AliInfo("Running only for triggers::");\r
-  fTriggerList->Print();\r
-}\r
-\r
-\r
+///////////////////////////////////////////////////////
+//
+// Basic class for Performance/Calibration TRD tasks
+// 
+// It performs generic tasks like :
+//   - data file manegment
+//   - reference container management
+//   - debug container management
+//   - interaction with AliAnalysisManager
+//   - Plot functor loop
+//
+// Author: Alexandru Bercuci <A.Bercuci@gsi.de>, 10/09/2008
+//
+/////////////////////////////////////////////////////////
+
+#include "TClass.h"
+#include "TMethod.h"
+#include "TMethodCall.h"
+#include "TMethodArg.h"
+#include "TFile.h"
+#include "TChain.h"
+#include "TList.h"
+#include "TMap.h"
+#include "TH1.h"
+#include "TH2.h"
+#include "TH3.h"
+#include "TF1.h"
+#include "TObjArray.h"
+#include "TDirectory.h"
+#include "TTreeStream.h"
+#include "TBox.h"
+#include "TLatex.h"
+#include "TVectorT.h"
+
+#include "AliLog.h"
+#include "AliAnalysisTask.h"
+#include "AliAnalysisManager.h"
+#include "AliExternalTrackParam.h"
+
+#include "info/AliTRDchmbInfo.h"
+#include "info/AliTRDeventInfo.h"
+#include "info/AliTRDtrendingManager.h"
+#include "AliTRDrecoTask.h"
+#include "AliTRDtrackV1.h"
+#include "AliTRDpidUtil.h"
+
+ClassImp(AliTRDrecoTask)
+
+Float_t AliTRDrecoTask::fgPt[AliTRDrecoTask::fgNPt+1] = {0.};
+TTreeSRedirector* AliTRDrecoTask::fgDebugStream(NULL);
+TH1* AliTRDrecoTask::fgProjector(NULL);
+//_______________________________________________________
+AliTRDrecoTask::AliTRDrecoTask()
+  : AliAnalysisTaskSE()
+  ,fNRefFigures(0)
+  ,fDets(NULL)
+  ,fDetsV(NULL)
+  ,fContainer(NULL)
+  ,fEvent(NULL)
+  ,fTracks(NULL)
+  ,fClusters(NULL)
+  ,fkClusters(NULL)
+  ,fkTrack(NULL)
+  ,fkMC(NULL)
+  ,fkESD(NULL)
+  ,fSpecies(-6)
+  ,fTriggerSlot(0)
+  ,fPt(-1.)
+  ,fPhi(0.)
+  ,fEta(0.)
+  ,fNpt(0)
+  ,fTriggerList(NULL)
+  ,fPlotFuncList(NULL)
+  ,fDetFuncList(NULL)
+  ,fRunTerminate(kFALSE)
+{
+// Default constructor
+  snprintf(fNameId, 10, "no name");
+}
+
+//_______________________________________________________
+AliTRDrecoTask::AliTRDrecoTask(const char *name, const char *title)
+  : AliAnalysisTaskSE(name)
+  ,fNRefFigures(0)
+  ,fDets(NULL)
+  ,fDetsV(NULL)
+  ,fContainer(NULL)
+  ,fEvent(NULL)
+  ,fTracks(NULL)
+  ,fClusters(NULL)
+  ,fkClusters(NULL)
+  ,fkTrack(NULL)
+  ,fkMC(NULL)
+  ,fkESD(NULL)
+  ,fSpecies(-6)
+  ,fTriggerSlot(0)
+  ,fPt(-1.)
+  ,fPhi(0.)
+  ,fEta(0.)
+  ,fNpt(0)
+  ,fTriggerList(NULL)
+  ,fPlotFuncList(NULL)
+  ,fDetFuncList(NULL)
+  ,fRunTerminate(kFALSE)
+{
+// Constructor for all derived performance tasks
+
+  SetTitle(title);
+  snprintf(fNameId, 10, "no name");
+  DefineInput (1, TObjArray::Class()); // track list
+  DefineInput (2, AliTRDeventInfo::Class()); // event info object
+  DefineInput (3, TObjArray::Class()); // cluster list object
+  DefineOutput(1, TObjArray::Class()); // histogram list
+}
+
+//_______________________________________________________
+AliTRDrecoTask::~AliTRDrecoTask() 
+{
+
+  // Generic task destructor
+
+  AliDebug(2, Form(" Ending task %s[%s]", GetName(), GetTitle()));
+ if(fgDebugStream){
+    delete fgDebugStream;
+    fgDebugStream = NULL;
+  }
+
+  if(fgProjector){
+    delete fgProjector;
+    fgProjector = NULL;
+  }
+
+  if(fPlotFuncList){
+    fPlotFuncList->Delete();
+    delete fPlotFuncList;
+    fPlotFuncList = NULL;
+  }
+  if(fDetFuncList){
+    fDetFuncList->Delete();
+    delete fDetFuncList;
+    fDetFuncList = NULL;
+  }
+  
+  if(fDets){
+    if(fDets->IsOwner()) fDets->Delete();
+    delete fDets;
+    fDets = NULL;
+  }
+  if(fDetsV) delete fDetsV; fDetsV=NULL;
+  if(fTriggerList){fTriggerList->Delete(); delete fTriggerList;}
+
+  if(fContainer && !(AliAnalysisManager::GetAnalysisManager() && AliAnalysisManager::GetAnalysisManager()->IsProofMode())){
+    if(fContainer->IsOwner()) fContainer->Delete();
+    delete fContainer;
+    fContainer = NULL;
+  }
+
+/*  if(fgTrendPoint){
+    TFile::Open("TRD.PerformanceTrend.root", "UPDATE");
+    fgTrendPoint->Write();
+    delete fgTrendPoint;
+    fgTrendPoint=NULL;
+    gFile->Close();
+  }*/
+}
+
+//_______________________________________________________
+Int_t AliTRDrecoTask::GetNRefFigures() const  
+{ 
+  if(!fNRefFigures) AliWarning("No reference plots available.");
+  return fNRefFigures; 
+} 
+
+//____________________________________________________________________
+Int_t AliTRDrecoTask::GetPtBin(Float_t pt)
+{
+// Get significant (very low, low, medium, high, very high) pt bin
+
+  Int_t ipt(0);
+  while(ipt<fNpt){
+    if(pt<fgPt[ipt]) break;
+    ipt++;
+  }
+  return ipt-1;
+}
+
+//_______________________________________________________
+Bool_t AliTRDrecoTask::MakeMomSegmentation()
+{
+  switch(fNpt){
+  case fgNPt:
+    fgPt[0]=0.3;
+    for(Int_t j(1); j<=fgNPt; j++) fgPt[j]=fgPt[j-1]+(TMath::Exp(j*j*2.e-3)-1.);
+    AliDebug(2, "Using debug momentum segmentation");
+    break;
+  case 4:
+    fgPt[0]=0.5; fgPt[1]=0.8; fgPt[2]=1.5; fgPt[3]=5.;
+    AliDebug(2, "Using default momentum segmentation");
+    break;
+  default:
+    AliError(Form("Momentum segmentation %d not supported.", fNpt));
+    fNpt=0;
+    return kFALSE;
+  }
+  return kTRUE;
+}
+
+//_______________________________________________________
+void AliTRDrecoTask::UserCreateOutputObjects()
+{
+  if(!HasFunctorList()) InitFunctorList();
+  if(DebugLevel()) fNpt = fgNPt;
+  else fNpt = 4;
+  MakeMomSegmentation();
+
+  fContainer = Histos();
+  PostData(1, fContainer);
+}
+
+//_______________________________________________________
+void AliTRDrecoTask::UserExec(Option_t *)
+{
+// Loop over Plot functors published by particular tasks
+
+  fTracks   = dynamic_cast<TObjArray *>(GetInputData(1));
+  fEvent    = dynamic_cast<AliTRDeventInfo *>(GetInputData(2));
+  fTriggerSlot=0;
+  if(fTriggerList && fEvent){
+    for(Int_t itrig(0); itrig<fTriggerList->GetEntries(); itrig++){
+      if(!fEvent->GetFiredTriggerClasses().Contains(((TObjString*)(*fTriggerList)[itrig])->GetName())) continue;
+      //printf("\"%s\" selected\n", ((TObjString*)(*fTriggerList)[itrig])->GetName());
+      SETBIT(fTriggerSlot,itrig);
+    }
+    if(!fTriggerSlot){
+      AliDebug(2, Form("Triggers[%s] not used for %s", fEvent->GetFiredTriggerClasses().Data(),  GetName()));
+      return;
+    }
+  }
+  fClusters = dynamic_cast<TObjArray*>(GetInputData(3));
+
+  if(!fPlotFuncList){
+    AliWarning("No track functor list defined for the task");
+    return;
+  }
+  if(!fEvent || !fTracks) return;
+  if(!fTracks->GetEntriesFast()) return;
+  else AliDebug(2, Form("Tracks[%d] for %s", fTracks->GetEntriesFast(), GetName()));
+
+  Int_t itrk(-1);
+  AliTRDtrackInfo *trackInfo(NULL);
+  TIter plotIter(fPlotFuncList);
+  TObjArrayIter trackIter(fTracks);
+  while((trackInfo = dynamic_cast<AliTRDtrackInfo*>(trackIter()))){
+    itrk++; fPt=-1; fEta=0.; fPhi=0.; fSpecies=-6;
+    fkMC    = trackInfo->GetMCinfo();
+    fkESD   = trackInfo->GetESDinfo();
+    if((fkTrack = trackInfo->GetTrack())){
+      // cache properties of the track at TRD entrance
+      // check input track status
+      AliExternalTrackParam *tin(NULL);
+      if(!(tin = fkTrack->GetTrackIn())) AliDebug(2, Form("Missing TRD track[%d] :: entry point.", itrk));
+      else {
+        fPt   = tin->Pt();
+        fEta  = tin->Eta();
+        Double_t xyz[3];
+        if(!tin->GetXYZ(xyz)) AliDebug(2, Form("Failed TRD track[%d] :: global track postion", itrk));
+        else fPhi  = TMath::ATan2(xyz[1], xyz[0]);
+        fSpecies= fkTrack->Charge()*(AliTRDpidUtil::Mass2Pid(fkTrack->GetMass())+1);
+      }
+    } else AliDebug(2, Form("Missing TRD track[%d].", itrk));
+
+    TMethodCall *plot(NULL);
+    plotIter.Reset();
+    while((plot=dynamic_cast<TMethodCall*>(plotIter()))) plot->Execute(this);
+  }
+  if(!fClusters) return;
+  if(!fDetFuncList){
+    AliDebug(1, "No detector functor list defined for task");
+    return;
+  }
+  TIter detIter(fDetFuncList);
+  for(Int_t idet(0); idet<AliTRDgeometry::kNdet; idet++){
+    if(!(fkClusters = (TObjArray*)fClusters->At(idet))) continue;
+    TMethodCall *det(NULL);
+    detIter.Reset();
+    while((det=dynamic_cast<TMethodCall*>(detIter()))) det->Execute(this);
+  }
+}
+
+//_______________________________________________________
+Bool_t AliTRDrecoTask::GetRefFigure(Int_t /*ifig*/)
+{
+  AliWarning("Retrieving reference figures not implemented.");
+  return kFALSE;
+}
+
+//_______________________________________________________
+Bool_t AliTRDrecoTask::PutTrendValue(const Char_t *name, Double_t val, Double_t err)
+{
+// Generic publisher for trend values
+
+  AliTRDtrendingManager *tm = AliTRDtrendingManager::Instance();
+  if(!tm){
+    AliError("Wrong usage of the trending functionality. Could not instantiate AliTRDtrendingManager singleton.");
+    return kFALSE;
+  }
+  tm->AddValue(Form("%s_%s", GetName(), name), val, err);
+  return kTRUE;
+}
+
+//_______________________________________________________
+void AliTRDrecoTask::InitFunctorList()
+{
+// Initialize list of functors
+
+  TClass *c = this->IsA();
+  if(fPlotFuncList) fPlotFuncList->Clear();
+  if(fDetFuncList) fDetFuncList->Clear();
+
+  TMethod *m(NULL);
+  TIter methIter(c->GetListOfMethods());
+  while((m=dynamic_cast<TMethod*>(methIter()))){
+    TString name(m->GetName());
+    if(name.BeginsWith("Plot")){
+      if(!fPlotFuncList) fPlotFuncList = new TList();
+      fPlotFuncList->AddLast(new TMethodCall(c, (const char*)name, ""));
+    } else if(name.BeginsWith("Det")){
+      if(!fDetFuncList) fDetFuncList = new TList();
+      fDetFuncList->AddLast(new TMethodCall(c, (const char*)name, ""));
+    }
+  }
+}
+
+//_______________________________________________________
+Bool_t AliTRDrecoTask::Load(const Char_t *file, const Char_t *dir)
+{
+// Generic container loader
+
+  if(!TFile::Open(file)){
+    AliWarning(Form("Couldn't open file %s.", file));
+    return kFALSE;
+  }
+  if(!gFile->cd(dir)){
+    AliWarning(Form("Couldn't cd to %s in %s.", dir, file));
+    gFile->Close();
+    return kFALSE;
+  }
+  if(!(fContainer = (TObjArray*)gDirectory->Get(GetName()))){
+    AliWarning("Missing histogram container.");
+    gFile->Close();
+    return kFALSE;
+  }
+  gFile->Close();
+  return kTRUE;
+}
+
+//________________________________________________________
+Bool_t AliTRDrecoTask::LoadDetectorMap(const Char_t *file, const Char_t *dir)
+{
+// Load detector map.
+
+  if(!TFile::Open(file)){
+    AliWarning(Form("Couldn't open file %s.", file));
+    return kFALSE;
+  }
+  if(!gFile->cd(dir)){
+    AliWarning(Form("Couldn't cd to %s in %s.", dir, file));
+    gFile->Close();
+    return kFALSE;
+  }
+  TObjArray *info = NULL;
+  if(!(info = (TObjArray*)gDirectory->Get("TRDinfoGen"))){
+    AliWarning("Missing TRDinfoGen container.");
+    gFile->Close();
+    return kFALSE;
+  }
+
+  if(info->FindObject("Chambers Status"))
+    fDets = (TObjArray*)((TObjArray*)info->FindObject("Chambers Status"))->Clone();
+
+  if(!fDets){
+    if(!info->At(4) || strcmp("TObjArray", info->At(4)->IsA()->GetName())) AliError("Looking for old style chamber status map. Failed.");
+    else {
+      AliWarning("Looking for old style chamber status map.");
+      fDetsV = (TObjArray*)((TObjArray*)info->At(4))->Clone();
+    }
+  }
+  gFile->Close();
+  info->Delete(); delete info;
+  return kTRUE;
+}
+
+
+//________________________________________________________
+Bool_t AliTRDrecoTask::Save(TObjArray * const results){
+  //
+  // Store the output graphs in a ROOT file
+  // Input TObject array will not be written as Key to the file,
+  // only content itself
+  //
+
+  TDirectory *cwd = gDirectory;
+  if(!TFile::Open(Form("TRD.Result%s.root", GetName()), "RECREATE")) return kFALSE;
+
+  TIterator *iter = results->MakeIterator();
+  TObject *inObject = NULL, *outObject = NULL;
+  while((inObject = iter->Next())){
+    outObject = inObject->Clone();
+    outObject->Write(NULL, TObject::kSingleKey);
+  }
+  delete iter;
+  gFile->Close(); delete gFile;
+  cwd->cd(); 
+  return kTRUE;
+}
+
+//_______________________________________________________
+Bool_t AliTRDrecoTask::PostProcess()
+{
+// To be implemented by particular tasks
+
+  AliWarning("Post processing of reference histograms not implemented.");
+  return kTRUE;
+}
+
+//_______________________________________________________
+void AliTRDrecoTask::MakeDetectorPlot(Int_t ly, const Option_t *opt)
+{
+// Draw chamber boundaries in eta/phi plots with misalignments
+// based on info collected by AliTRDinfoGen
+
+  if(!fDets){
+    AliWarning("NEW Detector map and status not available. Try OLD");
+    MakeDetectorPlotOLD(ly, opt);
+    return;
+  }
+  AliTRDchmbInfo *ci(NULL);
+  for(Int_t idet(0); idet<fDets->GetEntriesFast(); idet++){
+    if(!(ci = (AliTRDchmbInfo*)fDets->At(idet))) continue;
+    if(AliTRDgeometry::GetLayer(ci->GetDetector()) != ly) continue;
+    ci->Draw(opt);
+  }
+}
+
+//_______________________________________________________
+void AliTRDrecoTask::MakeDetectorPlotOLD(Int_t ly, const Option_t *opt)
+{
+// Draw chamber boundaries in eta/phi plots with misalignments
+// based on info collected by AliTRDinfoGen OLD data storage
+
+  if(!fDetsV){
+    AliError("OLD Detector map and status not available.");
+    return;
+  }
+  if(!fDetsV->GetEntries()){
+    AliError("OLD Detector map and status not filled.");
+    return;
+  }
+
+  Float_t xmin(0.), xmax(0.);
+  TBox *gdet = new TBox();
+  gdet->SetLineColor(kBlack);gdet->SetFillColor(kBlack);
+  Int_t style[] = {0, 3003};
+  for(Int_t idet(0); idet<540; idet++){
+    if(idet%6 != ly) continue;
+    TVectorF *det((TVectorF*)fDetsV->At(idet));
+    if(!det) continue;
+    Int_t iopt = Int_t((*det)[4]);
+    if(strcmp(opt, "eta")==0){
+      xmin=(*det)[0]; xmax=(*det)[2];
+    } else if(strcmp(opt, "pad")==0){
+      Int_t stk(AliTRDgeometry::GetStack(idet));
+      xmin=-0.6+16*(4-stk)-(stk<2?4:0); xmax=xmin+(stk==2?12:16)-0.2;
+    } else continue;
+    AliDebug(2, Form("det[%03d] 0[%+4.1f(%+4.1f) %+4.1f] 1[%+4.1f(%+4.1f) %+4.1f] opt[%d]", idet, xmin, (*det)[0], (*det)[1], xmax, (*det)[2], (*det)[3], iopt));
+    if(iopt==1){
+      gdet->SetFillStyle(style[1]);gdet->SetFillColor(kBlack);
+      gdet->DrawBox(xmin, (*det)[1], xmax, (*det)[3]);
+    } else {
+      gdet->SetFillStyle(style[0]);
+      gdet->DrawBox(xmin, (*det)[1], xmax, (*det)[3]);
+      if(iopt==2){
+        gdet->SetFillStyle(style[1]);gdet->SetFillColor(kGreen);
+        gdet->DrawBox(xmin, (*det)[1], xmax, 0.5*((*det)[3]+(*det)[1]));
+      } else if(iopt==3){
+        gdet->SetFillStyle(style[1]);gdet->SetFillColor(kRed);
+        gdet->DrawBox(xmin, 0.5*((*det)[3]+(*det)[1]), xmax, (*det)[3]);
+      } else if(iopt!=0) AliError(Form("Wrong chmb. status[%d] for det[%03d]", iopt, idet));
+    }
+  }
+  Float_t dsm = TMath::TwoPi()/AliTRDgeometry::kNsector;
+  xmin=0.;
+  if(strcmp(opt, "pad")==0) xmin=38.;
+  TLatex *sm = new TLatex(); sm->SetTextAlign(22);sm->SetTextColor(kBlack); sm->SetTextFont(32);sm->SetTextSize(0.03);
+  for(Int_t is(0); is<AliTRDgeometry::kNsector; is++) sm->DrawLatex(xmin, -TMath::Pi()+(is+0.5)*dsm, Form("%02d", is>=9?(is-9):(is+9)));
+}
+
+
+//_______________________________________________________
+void AliTRDrecoTask::MakeSummary()
+{
+// To be implemented by particular tasks
+  AliWarning("Summary not available");
+}
+
+//_______________________________________________________
+void AliTRDrecoTask::SetDebugLevel(Int_t level)
+{
+// Generic debug handler
+
+  AliAnalysisTaskSE::SetDebugLevel(level);
+  if(DebugLevel()>=1 && !fgDebugStream){
+    AliInfo(Form("Debug Level for Task %s set to %d", GetName(), level));
+    TDirectory *savedir = gDirectory;
+    fgDebugStream = new TTreeSRedirector("TRD.DebugPerformance.root", "RECREATE");
+    savedir->cd();
+  }
+}
+
+//____________________________________________________________________
+void AliTRDrecoTask::Terminate(Option_t *)
+{
+  //
+  // Terminate
+  //
+
+  if(fgDebugStream){ 
+    delete fgDebugStream;
+    fgDebugStream = NULL;
+  }
+  fContainer = dynamic_cast<TObjArray *>(GetOutputData(1));
+  if(fContainer && fRunTerminate){
+    PostProcess();
+    MakeSummary();
+  }
+}
+
+//________________________________________________________
+Float_t AliTRDrecoTask::SetNormZ(TH2 *h2, Int_t bxmin, Int_t bxmax, Int_t bymin, Int_t bymax, Float_t thr)
+{
+// Normalize histo content to the mean value in the range specified by bin ranges
+// [bxmin, bxmax] on the x axis and [bymin, bymax] on the y axis.
+// Optionally a threshold "thr" can be specified to disregard entries with no meaning
+
+  Float_t s = 0., c=0.; Int_t is(0);
+  for(Int_t ix(bxmin); ix<=(bxmax>0?bxmax:(h2->GetXaxis()->GetNbins())); ix++){
+    for(Int_t iy(bymin); iy<=(bymax>0?bymax:(h2->GetYaxis()->GetNbins())); iy++){
+      if((c = h2->GetBinContent(ix, iy))<thr) continue;
+      s += c; is++;
+    }
+  }
+  s/= (is?is:1);
+  for(Int_t ix(1); ix<=h2->GetXaxis()->GetNbins(); ix++){
+    for(Int_t iy(1); iy<=h2->GetYaxis()->GetNbins(); iy++){
+      if((c = h2->GetBinContent(ix, iy))<thr) h2->SetBinContent(ix, iy, thr-1000);
+      else h2->SetBinContent(ix, iy, 100.*(c/s-1.));
+    }
+  }
+  return s;
+}
+
+//________________________________________________________
+void AliTRDrecoTask::SetRangeZ(TH2 *h2, Float_t min, Float_t max, Float_t thr)
+{
+// Set range on Z axis such to avoid outliers
+
+  Float_t c(0.), dz(1.e-3*(max-min));
+  for(Int_t ix(1); ix<=h2->GetXaxis()->GetNbins(); ix++){
+    for(Int_t iy(1); iy<=h2->GetYaxis()->GetNbins(); iy++){
+      if((c = h2->GetBinContent(ix, iy))<thr) continue;
+      if(c<=min) h2->SetBinContent(ix, iy, min+dz);
+    }
+  }
+  h2->GetZaxis()->SetRangeUser(min, max);
+}
+
+//________________________________________________________
+Float_t AliTRDrecoTask::GetMeanStat(TH1 *h, Float_t cut, Int_t opt, Float_t *sigma)
+{
+// Return mean number of entries/bin of histogram "h".
+// If optionally sigma is allocated than it is also filled with sigma paramter of the gauss fit 
+//
+// Option "opt" is given the following values are accepted:
+//   -1 : consider only entries less than "cut"
+//   1  : consider only entries greater than "cut"
+//   0  : no "cut" [dafault]
+// Error codes
+//   -999. : statistics too low [20]
+//   -998. : fit failed
+
+  const Int_t kvd(100000);
+  Float_t v[kvd];
+  Int_t nbx(h->GetNbinsX()), nby(h->GetNbinsY()), nbz(h->GetNbinsZ());
+  Int_t nv(0); Float_t xmin(1.e5), xmax(-xmin);
+  for(Int_t ix(1); ix<=nbx; ix++){
+    for(Int_t iy(1); iy<=nby; iy++){
+      for(Int_t iz(1); iz<=nbz; iz++){
+        Float_t c = h->GetBinContent(ix, iy, iz);
+        if(opt*(c-cut)<0.) continue;
+        v[nv++] = c;
+        if(c<xmin) xmin = c;
+        if(c>xmax) xmax = c;
+        if(nv==kvd){
+          printf("W - AliTRDrecoTask::GetMeanStat() :: Unreliable results for %s[%s]. Statical allocation exceeded.\n", h->GetName(), h->GetTitle());
+          break;
+        }
+      }
+      if(nv==kvd) break;
+    }
+    if(nv==kvd) break;
+  }
+  if(nv<10){
+    //printf("W - AliTRDrecoTask::GetMeanStat() :: Failed for %s[%s]. Statical undefined [%d].\n", h->GetName(), h->GetTitle(), nv);
+    return -999.;
+  }
+  if(fgProjector) delete fgProjector;
+  fgProjector = new TH1F("hProjector", "", 20, 0.5*(3*xmin-xmax), 0.5*(3*xmax - xmin));
+  for(Int_t iv(0); iv<nv; iv++) fgProjector->Fill(v[iv]);
+  TF1 f("f", "gaus", xmin, xmax);
+  f.SetParameter(0, fgProjector->Integral());
+  f.SetParameter(1, fgProjector->GetMean()); f.SetParLimits(1, xmin, xmax);
+  f.SetParameter(2, fgProjector->GetRMS());
+  if(fgProjector->Fit(&f, "WQ0", "goff")) return -998.;
+  if(sigma) *sigma = f.GetParameter(2);
+  return f.GetParameter(1);
+}
+
+//________________________________________________________
+Int_t AliTRDrecoTask::Rebin(TH2 *h, Int_t n, Int_t rebinX[], Int_t rebinY[], Int_t nstat)
+{
+// Rebin histo "h" according to "rebinning" strategy "n" steps such to obtain mean statistics per bin over "nstat"
+
+  Int_t irebin(0);
+  while(irebin<n && GetMeanStat(h, .5, 1)<nstat){
+    h->Rebin2D(rebinX[irebin], rebinY[irebin]);
+    irebin++;
+  }
+  return irebin;
+}
+
+//________________________________________________________
+AliTRDrecoTask::AliTRDrecoProjection::AliTRDrecoProjection()
+  :TNamed()
+  ,fH(NULL)
+  ,fNrebin(0)
+{
+  // constructor
+  fRebin[0] = NULL;fRebin[1] = NULL;
+  memset(fAx, 0, 3*sizeof(Int_t));
+  memset(fRange, 0, 4*sizeof(Float_t));
+}
+
+//________________________________________________________
+AliTRDrecoTask::AliTRDrecoProjection::~AliTRDrecoProjection()
+{
+  // destructor
+  if(fH) delete fH;
+  if(fRebin[0]) delete [] fRebin[0];
+  if(fRebin[1]) delete [] fRebin[1];
+}
+
+//________________________________________________________
+void AliTRDrecoTask::AliTRDrecoProjection::Build(const Char_t *n, const Char_t *t, Int_t ix, Int_t iy, Int_t iz, TAxis *aa[])
+{
+// check and build (if neccessary) projection determined by axis "ix", "iy" and "iz"
+  if(!aa[ix] || !aa[iy] || !aa[iz]) return;
+  TAxis *ax(aa[ix]), *ay(aa[iy]), *az(aa[iz]);
+  // check ax definiton to protect against older versions of the data
+  if(ax->GetNbins()<=0 || (ax->GetXmax()-ax->GetXmin())<=0.){
+    AliWarning(Form("Wrong definition of axis[%d] \"%s\"[%d](%f %f).", ix, ax->GetTitle(), ax->GetNbins(), ax->GetXmin(), ax->GetXmax()));
+    return;
+  }
+  if(ay->GetNbins()<=0 || (ay->GetXmax()-ay->GetXmin())<=0.){
+    AliWarning(Form("Wrong definition of axis[%d] \"%s\"[%d](%f %f).", ix, ay->GetTitle(), ay->GetNbins(), ay->GetXmin(), ay->GetXmax()));
+    return;
+  }
+  if(az->GetNbins()<=0 || (az->GetXmax()-az->GetXmin())<=0.){
+    AliWarning(Form("Wrong definition of axis[%d] \"%s\"[%d](%f %f).", ix, az->GetTitle(), az->GetNbins(), az->GetXmin(), az->GetXmax()));
+    return;
+  }
+  SetNameTitle(n,t);
+  fH = new TH3I(n, Form("%s;%s;%s;%s", t, ax->GetTitle(), ay->GetTitle(), az->GetTitle()),
+    ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),
+    ay->GetNbins(), ay->GetXmin(), ay->GetXmax(),
+    az->GetNbins(), az->GetXmin(), az->GetXmax());
+  fAx[0] = ix; fAx[1] = iy; fAx[2] = iz;
+  fRange[0] = az->GetXmin()/3.; fRange[1] = az->GetXmax()/3.;
+  AliDebug(2, Form("H3(%s, %s) :: %s[%3d %4.2f %4.2f]%s[%3d %4.2f %4.2f]%s[%3d %4.2f %4.2f]", n, t,
+    ax->GetTitle(), ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),
+    ay->GetTitle(), ay->GetNbins(), ay->GetXmin(), ay->GetXmax(),
+    az->GetTitle(), az->GetNbins(), az->GetXmin(), az->GetXmax()));
+}
+
+//________________________________________________________
+AliTRDrecoTask::AliTRDrecoProjection& AliTRDrecoTask::AliTRDrecoProjection::operator=(const AliTRDrecoProjection& rhs)
+{
+// copy projections
+  if(this == &rhs) return *this;
+
+  TNamed::operator=(rhs);
+  if(fNrebin){fNrebin=0; delete [] fRebin[0]; delete [] fRebin[1];}
+  if(rhs.fNrebin) SetRebinStrategy(rhs.fNrebin, rhs.fRebin[0], rhs.fRebin[1]);
+  memcpy(fAx, rhs.fAx, 3*sizeof(Int_t));
+  memcpy(fRange, rhs.fRange, 4*sizeof(Float_t));
+  if(fH) delete fH;
+  if(rhs.fH) fH=(TH3I*)rhs.fH->Clone(Form("%s_CLONE", rhs.fH->GetName()));
+  return *this;
+}
+
+//________________________________________________________
+AliTRDrecoTask::AliTRDrecoProjection& AliTRDrecoTask::AliTRDrecoProjection::operator+=(const AliTRDrecoProjection& other)
+{
+// increment projections
+  if(!fH || !other.fH) return *this;
+  AliDebug(2, Form("%s+=%s [%s+=%s]", GetName(), other.GetName(), fH->GetName(), (other.fH)->GetName()));
+  fH->Add(other.fH);
+  return *this;
+}
+
+//________________________________________________________
+void AliTRDrecoTask::AliTRDrecoProjection::Increment(Int_t bin[], Double_t v)
+{
+// increment bin with value "v" pointed by general coord in "bin"
+  if(!fH) return;
+  AliDebug(4, Form("  %s[%2d]", fH->GetName(), Int_t(v)));
+  fH->AddBinContent(fH->GetBin(bin[fAx[0]],bin[fAx[1]],bin[fAx[2]]), Int_t(v));
+}
+
+//________________________________________________________
+Double_t AliTRDrecoTask::AliTRDrecoProjection::GetTrendValue(const Int_t mid, Double_t *e, Double_t *s, Double_t *se) const
+{
+//   Return result of fitting the main distribution (represented on the z axis) with the function selected
+// "mid". Optionally return the Mean and RMS of the distribution pointing to "m" and "s"
+
+  if(!fH){
+    AliDebug(1, Form("Missing 3D in %s", GetName()));
+    return -999.;
+  }
+  TH1 *h1s(NULL);
+  if(!(h1s = (TH1D*)fH->Project3D("z"))){
+    AliDebug(1, Form("Failed Project3D(\"z\") in %s", GetName()));
+    return -999.;
+  }
+  Int_t ne((Int_t)h1s->Integral());
+  if(ne<30){
+    AliDebug(1, Form("Statistics too low[%2d] in %s", ne, GetName()));
+    delete h1s;
+    return -999.;
+  }
+  TAxis *az(h1s->GetXaxis());
+  Float_t mn(h1s->GetMean()), rms(h1s->GetRMS()),
+          v(mn),  // main trending value (mean, mu, MPV)
+          ve(rms),// dispersion (RMS, sigma, landau 2nd param)
+          ev(h1s->GetMeanError()), // error on v
+          eve(h1s->GetRMSError());// error on ve
+  if(mid==1){
+    TF1 fg("fg", "gaus", az->GetXmin(), az->GetXmax());
+    fg.SetParameter(0, Float_t(ne)); fg.SetParameter(1, mn); fg.SetParameter(2, rms);
+    h1s->Fit(&fg, "WQ0");
+    v = fg.GetParameter(1); ev = fg.GetParError(1);
+    ve= fg.GetParameter(2); eve= fg.GetParError(2);
+  } else if (mid==2) {
+    TF1 fl("fl", "landau", az->GetXmin(), az->GetXmax());
+    fl.SetParameter(0, Float_t(ne)); fl.SetParameter(1, mn); fl.SetParameter(2, rms);
+    h1s->Fit(&fl, "WQ0");
+    v = fl.GetMaximumX(); ev = fl.GetParError(1);
+    ve= fl.GetParameter(2);eve= fl.GetParError(2);
+  }
+  if(e)  *e  = ev;
+  if(s)  *s  = ve;
+  if(se) *se = eve;
+  AliDebug(2, Form("[%d] %s(%4d) = M{%f+-%f} S{%f+-%f}", mid, fH->GetName(), (Int_t)h1s->Integral(), v, ev, ve, eve));
+
+  delete h1s;
+  return v;
+}
+
+//________________________________________________________
+TH2* AliTRDrecoTask::AliTRDrecoProjection::Projection2Dbin(Int_t bin, Bool_t mc)
+{
+// dumb 2D projection for bin including under/over flow. Default all [bin==-1]
+
+  TAxis *ax(fH->GetXaxis()), *ay(fH->GetYaxis()), *az(fH->GetZaxis());
+  Int_t nbins(az->GetNbins());
+  TH2F *h2(NULL);
+  if(bin<0) h2 = new TH2F(Form("%s_2D", fH->GetName()),
+                Form("%s;%s;%s;Entries", fH->GetTitle(), ax->GetTitle(), ay->GetTitle()),
+                ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),
+                ay->GetNbins(), ay->GetXmin(), ay->GetXmax());
+  else h2 = new TH2F(Form("%s%d_2D", fH->GetName(), bin),
+                Form("%s | #it{%4.2f<=p_{t}^{%s}[GeV/c]<%4.2f};%s;%s;Entries", fH->GetTitle(),
+                bin?fgPt[bin-1]:0., mc?"MC":"", bin>nbins?99.99:fgPt[bin], ax->GetTitle(), ay->GetTitle()),
+                ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),
+                ay->GetNbins(), ay->GetXmin(), ay->GetXmax());
+  for(Int_t ix(1); ix<=ax->GetNbins(); ix++){
+    for(Int_t iy(1); iy<=ay->GetNbins(); iy++){
+      Int_t ibin = h2->GetBin(ix, iy);
+      for(Int_t iz(0); iz<=az->GetNbins()+1; iz++){
+        if(bin<0) h2->AddBinContent(ibin, fH->GetBinContent(ix, iy, iz));
+        else if(bin==iz){
+          h2->AddBinContent(ibin, fH->GetBinContent(ix, iy, iz));
+          break;
+        }
+      }
+    }
+  }
+  return h2;
+}
+
+//________________________________________________________
+TH2* AliTRDrecoTask::AliTRDrecoProjection::Projection2D(const Int_t nstat, const Int_t ncol, const Int_t mid, Bool_t del)
+{
+// build the 2D projection and adjust binning
+
+  const Char_t *title[] = {"Mean", "#mu", "MPV"};
+  if(!fH){
+    AliDebug(1, Form("Missing 3D in %s", GetName()));
+    return NULL;
+  }
+  TAxis *ax(fH->GetXaxis()), *ay(fH->GetYaxis()), *az(fH->GetZaxis());
+  TH2D *h2s(NULL), *hyx(NULL);
+  if(!(h2s = (TH2D*)fH->Project3D("yx"))){
+    AliDebug(1, Form("Failed Project3D(\"yx\") in %s", GetName()));
+    return NULL;
+  }
+  // save a copy of the original distribution
+  if(!del){
+    hyx = (TH2D*)h2s->Clone();
+    hyx->SetName(Form("%sEn", fH->GetName()));
+  }
+  Int_t irebin(Rebin(h2s, fNrebin, fRebin[0], fRebin[1], nstat)), dxBin(1), dyBin(1);
+  for(Int_t ir(0); ir<irebin; ir++){dxBin*=fRebin[0][ir]; dyBin*=fRebin[1][ir];}
+  Int_t nx(h2s->GetNbinsX()), ny(h2s->GetNbinsY());
+  delete h2s;
+  if(mid<0) return NULL;
+
+  // start projection
+  TH1 *h(NULL); Int_t n(0);
+  Float_t dz=(fRange[1]-fRange[1])/ncol;
+  TString titlez(az->GetTitle()); TObjArray *tokenTitle(titlez.Tokenize(" "));
+  Int_t nt(tokenTitle->GetEntriesFast());
+  TH2 *h2(NULL);
+  if((h2 = (TH2*)gDirectory->Get(Form("%s_2D", fH->GetName())))) delete h2; // avoid ROOT warning messages
+  h2 = new TH2F(Form("%s_2D", fH->GetName()),
+            Form("%s;%s;%s;%s(%s) %s", fH->GetTitle(), ax->GetTitle(), ay->GetTitle(), title[mid], nt>0?(*tokenTitle)[0]->GetName():"", nt>1?(*tokenTitle)[1]->GetName():""),
+            nx, ax->GetXmin(), ax->GetXmax(), ny, ay->GetXmin(), ay->GetXmax());
+  tokenTitle->Delete(); delete tokenTitle;
+  h2->SetContour(ncol);
+  h2->GetZaxis()->CenterTitle();
+  h2->GetZaxis()->SetTitleOffset(1.4);
+  h2->GetZaxis()->SetRangeUser(fRange[0], fRange[1]);
+  AliDebug(2, Form("%s[%s] nx[%d] ny[%d]", h2->GetName(), h2->GetTitle(), nx, ny));
+  for(Int_t iy(0); iy<ny; iy++){
+    for(Int_t ix(0); ix<nx; ix++){
+      h = fH->ProjectionZ(Form("%s_z", h2->GetName()), ix*dxBin+1, (ix+1)*dxBin, iy*dyBin+1, (iy+1)*dyBin);
+      Int_t ne((Int_t)h->Integral());
+      //printf("  x[%2d %2d] y[%2d %2d] ne[%4d]\n", ix*dxBin+1, (ix+1)*dxBin, iy*dyBin+1, (iy+1)*dyBin, ne);
+      if(ne<nstat/2){
+        h2->SetBinContent(ix+1, iy+1, -999);
+        h2->SetBinError(ix+1, iy+1, 1.);
+        n++;
+      }else{
+        // redo the projection by adding 1 bin @ left and 1 bin @ right for smoothing
+        h = fH->ProjectionZ(Form("%s_z", h2->GetName()), ix*dxBin, (ix+1)*dxBin+1, iy*dyBin, (iy+1)*dyBin+1);
+        Float_t v(h->GetMean()), ve(h->GetRMS());
+        if(mid==1){
+          TF1 fg("fg", "gaus", az->GetXmin(), az->GetXmax());
+          fg.SetParameter(0, Float_t(ne)); fg.SetParameter(1, v); fg.SetParameter(2, ve);
+          h->Fit(&fg, "WQ0");
+          v = fg.GetParameter(1); ve = fg.GetParameter(2);
+        } else if (mid==2) {
+          TF1 fl("fl", "landau", az->GetXmin(), az->GetXmax());
+          fl.SetParameter(0, Float_t(ne)); fl.SetParameter(1, v); fl.SetParameter(2, ve);
+          h->Fit(&fl, "WQ0");
+          v = fl.GetMaximumX(); ve = fl.GetParameter(2);
+/*          TF1 fgle("gle", "[0]*TMath::Landau(x, [1], [2], 1)*TMath::Exp(-[3]*x/[1])", az->GetXmin(), az->GetXmax());
+          fgle.SetParameter(0, fl.GetParameter(0));
+          fgle.SetParameter(1, fl.GetParameter(1));
+          fgle.SetParameter(2, fl.GetParameter(2));
+          fgle.SetParameter(3, 1.);fgle.SetParLimits(3, 0., 5.);
+          h->Fit(&fgle, "WQ");
+          v = fgle.GetMaximumX(); ve = fgle.GetParameter(2);*/
+        }
+        if(v<fRange[0]) h2->SetBinContent(ix+1, iy+1, fRange[0]+0.1*dz);
+        else h2->SetBinContent(ix+1, iy+1, v);
+        h2->SetBinError(ix+1, iy+1, ve);
+      }
+    }
+  }
+  if(h) delete h;
+  if(n==nx*ny){  // clean empty projections
+    AliDebug(1, Form("Empty projection in %s", GetName()));
+    delete h2; h2=NULL;
+  }
+  return h2;
+}
+
+//________________________________________________________
+void AliTRDrecoTask::AliTRDrecoProjection::SetRebinStrategy(Int_t n, Int_t rebx[], Int_t reby[])
+{
+// define rebinning strategy for this projection
+  fNrebin = n;
+  fRebin[0] = new Int_t[n]; memcpy(fRebin[0], rebx, n*sizeof(Int_t));
+  fRebin[1] = new Int_t[n]; memcpy(fRebin[1], reby, n*sizeof(Int_t));
+}
+
+//________________________________________________________
+void AliTRDrecoTask::SetTriggerList(const Char_t *tl)
+{
+// Store list of triggers to be monitored
+  TString stl(tl);
+  if(fTriggerList){ fTriggerList->Delete(); delete fTriggerList;}
+  TObjArray *atl = stl.Tokenize(" ");
+  fTriggerList = (TObjArray*)atl->Clone("");
+  atl->Delete(); delete atl;
+  AliInfo("Running only for triggers::");
+  fTriggerList->Print();
+}
+
+