copy TRD performance train to PWG1
authorabercuci <abercuci@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 30 Oct 2009 08:12:25 +0000 (08:12 +0000)
committerabercuci <abercuci@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 30 Oct 2009 08:12:25 +0000 (08:12 +0000)
60 files changed:
PWG1/TRD/AliTRDalignmentTask.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDalignmentTask.h [new file with mode: 0644]
PWG1/TRD/AliTRDcalibration.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDcalibration.h [new file with mode: 0644]
PWG1/TRD/AliTRDcheckDET.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDcheckDET.h [new file with mode: 0644]
PWG1/TRD/AliTRDcheckESD.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDcheckESD.h [new file with mode: 0644]
PWG1/TRD/AliTRDcheckPID.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDcheckPID.h [new file with mode: 0644]
PWG1/TRD/AliTRDclusterResolution.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDclusterResolution.h [new file with mode: 0644]
PWG1/TRD/AliTRDefficiency.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDefficiency.h [new file with mode: 0644]
PWG1/TRD/AliTRDefficiencyMC.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDefficiencyMC.h [new file with mode: 0644]
PWG1/TRD/AliTRDinfoGen.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDinfoGen.h [new file with mode: 0644]
PWG1/TRD/AliTRDmultiplicity.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDmultiplicity.h [new file with mode: 0644]
PWG1/TRD/AliTRDpidRefMaker.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDpidRefMaker.h [new file with mode: 0644]
PWG1/TRD/AliTRDpidRefMakerLQ.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDpidRefMakerLQ.h [new file with mode: 0644]
PWG1/TRD/AliTRDpidRefMakerNN.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDpidRefMakerNN.h [new file with mode: 0644]
PWG1/TRD/AliTRDrecoTask.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDrecoTask.h [new file with mode: 0644]
PWG1/TRD/AliTRDresolution.cxx [new file with mode: 0644]
PWG1/TRD/AliTRDresolution.h [new file with mode: 0644]
PWG1/TRD/info/AliTRDclusterInfo.cxx [new file with mode: 0644]
PWG1/TRD/info/AliTRDclusterInfo.h [new file with mode: 0644]
PWG1/TRD/info/AliTRDeventInfo.cxx [new file with mode: 0644]
PWG1/TRD/info/AliTRDeventInfo.h [new file with mode: 0644]
PWG1/TRD/info/AliTRDtrackInfo.cxx [new file with mode: 0644]
PWG1/TRD/info/AliTRDtrackInfo.h [new file with mode: 0644]
PWG1/TRD/info/AliTRDv0Info.cxx [new file with mode: 0644]
PWG1/TRD/info/AliTRDv0Info.h [new file with mode: 0644]
PWG1/TRD/info/Makefile [new file with mode: 0644]
PWG1/TRD/info/trdTrackInfoLinkDef.h [new file with mode: 0644]
PWG1/TRD/macros/AddTRDcheckDET.C [new file with mode: 0644]
PWG1/TRD/macros/AddTRDcheckESD.C [new file with mode: 0644]
PWG1/TRD/macros/AddTRDcheckPID.C [new file with mode: 0644]
PWG1/TRD/macros/AddTRDefficiency.C [new file with mode: 0644]
PWG1/TRD/macros/AddTRDinfoGen.C [new file with mode: 0644]
PWG1/TRD/macros/AddTRDresolution.C [new file with mode: 0644]
PWG1/TRD/macros/AliTRDperformanceTrain.h [new file with mode: 0644]
PWG1/TRD/macros/AliTrackletsinTRD.C [new file with mode: 0644]
PWG1/TRD/macros/AliTrackletsinTRD.h [new file with mode: 0644]
PWG1/TRD/macros/EVE/PH.C [new file with mode: 0644]
PWG1/TRD/macros/EVE/nclusters.C [new file with mode: 0644]
PWG1/TRD/macros/PID/ConvertMLPs.C [new file with mode: 0644]
PWG1/TRD/macros/PID/MonitorTraining.C [new file with mode: 0644]
PWG1/TRD/macros/PID/makeTrainingData.C [new file with mode: 0644]
PWG1/TRD/macros/PID/runTraining.C [new file with mode: 0644]
PWG1/TRD/macros/helper.C [new file with mode: 0644]
PWG1/TRD/macros/makeCalibResults.C [new file with mode: 0644]
PWG1/TRD/macros/makeResults.C [new file with mode: 0644]
PWG1/TRD/run.C [new file with mode: 0644]
PWG1/TRD/run.jdl [new file with mode: 0644]

diff --git a/PWG1/TRD/AliTRDalignmentTask.cxx b/PWG1/TRD/AliTRDalignmentTask.cxx
new file mode 100644 (file)
index 0000000..37681fa
--- /dev/null
@@ -0,0 +1,143 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercialf purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+///////////////////////////////////////////////
+// TRD alignment task
+//
+// Some documentation
+//
+// Authors :
+//
+////////////////////////////////////////////////
+
+#include "TTreeStream.h"
+#include "TROOT.h"
+#include "TH1.h"
+#include "TH2.h"
+
+#include "AliTrackPointArray.h"
+#include "AliLog.h"
+
+#include "AliTRDgeometry.h"
+#include "AliTRDcluster.h"
+#include "AliTRDseedV1.h"
+#include "AliTRDtrackV1.h"
+
+#include "AliTRDalignmentTask.h"
+
+ClassImp(AliTRDalignmentTask)
+
+//________________________________________________________
+AliTRDalignmentTask::AliTRDalignmentTask()
+  :AliTRDrecoTask("Alignment", "TRD alignment")
+  ,fTree(0x0)
+  ,fArray(0x0)
+{
+  InitFunctorList();
+  DefineOutput(1, TTree::Class());
+
+}
+
+//________________________________________________________
+AliTRDalignmentTask::~AliTRDalignmentTask()
+{
+  if (fArray) delete fArray;
+}
+
+
+//________________________________________________________
+void AliTRDalignmentTask::CreateOutputObjects()
+{
+  // spatial resolution
+  OpenFile(1, "RECREATE");
+
+  fTree = new TTree("spTree", "Tree with track space point arrays");
+  fTree->Branch("SP","AliTrackPointArray", &fArray);
+}
+
+
+//________________________________________________________
+void AliTRDalignmentTask::Exec(Option_t *opt)
+{
+// Documentation to come
+
+  AliTRDrecoTask::Exec(opt);
+  PostData(1, fTree);
+}
+
+
+//________________________________________________________
+TH1* AliTRDalignmentTask::PlotTrackPoints(const AliTRDtrackV1 *track)
+{
+// Documentation to come 
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+
+  if (fArray) delete fArray;
+  fArray = new AliTrackPointArray(fkTrack->GetNumberOfTracklets());
+
+  // Filling the track points array
+  Float_t x, y, z;
+  AliTrackPoint p; Int_t ip = 0;
+  AliTRDseedV1 *tracklet = 0x0;
+  for(Int_t il=0; il<AliTRDgeometry::kNlayer; il++){
+    if(!(tracklet = fkTrack->GetTracklet(il))) continue;
+    if(!tracklet->IsOK()) continue;
+    tracklet->Fit(kTRUE);
+
+    x = tracklet->GetX0();
+    y = tracklet->GetYfit(0)-tracklet->GetYfit(1)*(tracklet->GetX0()-x);
+    z = tracklet->GetZfit(0);
+    p.SetXYZ(x,y,z);
+    fArray->AddPoint(ip++, &p);
+  }
+  fTree->Fill();
+
+/*  if(fDebugLevel>=1){
+    Float_t yt = fRim.GetYat(x[il]);
+    (*fDebugStream) << "TrkltResiduals"
+      << "layer="  << il
+      << "x="      <<x[il]
+      << "y="      <<y[il]
+      << "yt="     <<yt
+      << "dydx="   << dydx[il]
+      << "dy="     << dy
+      << "\n";
+  }*/
+  return 0x0;
+}
+
+
+
+//________________________________________________________
+Bool_t AliTRDalignmentTask::IsIdenticalWithOneOf(AliTrackPoint * const p, AliTrackPointArray *parray, int nmax) {
+
+  // Is the point p identical with one of the points on the list parray?
+  // This is a fix for aliroot 4-16-Rev-01 (and before) writing some 
+  // spurious unitialized points. 
+  for (int i=0; i<parray->GetNPoints() && i<nmax; i++) {
+    AliTrackPoint pa;
+    parray->GetPoint(pa,i);
+    //printf("comparing %7.3f with %7.3f\n",p->GetY(),pa.GetY());
+    if (p->GetResidual(pa,0)<1e-8) return kTRUE;
+    //printf("different\n");
+  }
+  return kFALSE;
+}
diff --git a/PWG1/TRD/AliTRDalignmentTask.h b/PWG1/TRD/AliTRDalignmentTask.h
new file mode 100644 (file)
index 0000000..568894a
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef ALITRDALIGNMENTTASK_H
+#define ALITRDALIGNMENTTASK_H
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+
+////////////////////////////////////////////////////////////////////////////
+//                                                                        //
+//  TRD Alignment QA                                                     //
+//                                                                        //
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef ALITRDRECOTASK_H
+#include "AliTRDrecoTask.h"
+#endif
+
+class TH1;
+class TTree;
+class AliTrackPoint;
+class AliTrackPointArray;
+class AliTRDtrackV1;
+class AliTRDalignmentTask : public AliTRDrecoTask
+{
+public:
+
+  AliTRDalignmentTask();
+  virtual ~AliTRDalignmentTask();
+  
+  void    CreateOutputObjects();
+  void    Exec(Option_t *opt);
+  TH1*    PlotTrackPoints(const AliTRDtrackV1 *track=0x0);
+  Bool_t  PostProcess() { return kTRUE;}
+  
+private:
+  Bool_t IsIdenticalWithOneOf(AliTrackPoint * const p, AliTrackPointArray *parray, int nmax);
+  AliTRDalignmentTask(const AliTRDalignmentTask&);
+  AliTRDalignmentTask& operator=(const AliTRDalignmentTask&);
+
+private:
+  TTree          *fTree;    //! pointer to the output TTree 
+  AliTrackPointArray *fArray; // pointer to the track points
+  ClassDef(AliTRDalignmentTask, 1) // tracking resolution task
+};
+#endif
diff --git a/PWG1/TRD/AliTRDcalibration.cxx b/PWG1/TRD/AliTRDcalibration.cxx
new file mode 100644 (file)
index 0000000..82a7907
--- /dev/null
@@ -0,0 +1,1373 @@
+
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+/////////////////////////////////////////////////////////////////////////////////
+//                                                                             
+// AliTRDcalibration                                                            
+//                                                                             
+// Task to run the calibration offline.
+// Author:
+//   R. Bailhache (rbailhache@ikf.uni-frankfurt.de, R.Bailhache@gsi.de)
+//           
+//////////////////////////////////////////////////////////////////////////////////
+
+
+#include "Riostream.h"
+#include "TChain.h"
+#include "TTree.h"
+#include "TProfile2D.h"
+#include "TH2I.h"
+#include "TH1F.h"
+#include "TList.h"
+#include "TMath.h"
+#include "TCanvas.h"
+#include "TObject.h"
+#include "TFile.h"
+#include "TObjArray.h"
+#include "TGraph.h"
+#include "TStyle.h"
+#include "TLegend.h"
+#include "TGraphErrors.h"
+
+#include "AliTRDrecoTask.h"
+#include "AliAnalysisManager.h"
+
+#include "AliESDInputHandler.h"
+#include "AliTRDtrackV1.h"
+#include "AliTRDseedV1.h"
+#include "AliTRDcluster.h"
+#include "info/AliTRDtrackInfo.h"
+#include "AliTRDcalibDB.h"
+
+#include "AliTRDCalibraFillHisto.h"
+#include "AliTRDCalibraFit.h"
+#include "AliTRDCalibraVdriftLinearFit.h"
+#include "AliTRDCalibraMode.h"
+#include "AliTRDCalibraVector.h"
+#include "./Cal/AliTRDCalPad.h"
+#include "./Cal/AliTRDCalDet.h"
+#include "AliCDBMetaData.h"
+#include "AliCDBManager.h"
+#include "AliCDBStorage.h"
+
+#include "AliLog.h"
+
+#include "AliTRDcalibration.h"
+
+
+ClassImp(AliTRDcalibration)
+
+//________________________________________________________________________
+AliTRDcalibration::AliTRDcalibration() 
+  :AliTRDrecoTask("Calibration", "Calibration on tracks")
+  ,fTrackInfo(0)
+  ,ftrdTrack(0)
+  ,fcl(0)
+  ,fTRDCalibraFillHisto(0)
+  ,fNbTRDTrack(0)
+  ,fNbTRDTrackOffline(0)
+  ,fNbTRDTrackStandalone(0)
+  ,fNbTRDTracklet(0)
+  ,fNbTRDTrackletOffline(0)
+  ,fNbTRDTrackletStandalone(0)
+  ,fNbTimeBin(0x0)
+  ,fNbTimeBinOffline(0x0)
+  ,fNbTimeBinStandalone(0x0)
+  ,fNbClusters(0)
+  ,fNbClustersOffline(0)
+  ,fNbClustersStandalone(0)
+  ,fPHSum(0)
+  ,fCHSum(0)
+  ,fDetSum(0)
+  ,fDetSumVector(0)
+  ,fHisto2d(kTRUE)
+  ,fVector2d(kFALSE)
+  ,fVdriftLinear(kTRUE)
+  ,flow(0)
+  ,fhigh(30)
+  ,fNbTimeBins(30)
+  ,ffillZero(kFALSE)
+  ,fnormalizeNbOfCluster(kFALSE)
+  ,fmaxCluster(0)
+  ,fOfflineTracks(kFALSE)
+  ,fStandaloneTracks(kFALSE)
+  ,fCompressPerDetector(kFALSE)
+  ,fRunNumber(0)
+  ,fkNameDirectory("local://.")
+  ,fGraph(0x0)
+  ,fPostProcess(kFALSE)
+{
+  // Constructor
+  
+  fNRefFigures = 17;
+
+  for(Int_t k = 0; k < 3; k++)
+    {
+      fNz[k]=0;
+      fNrphi[k]=0;
+    }
+
+}  
+//________________________________________________________________________
+AliTRDcalibration::~AliTRDcalibration() 
+{
+  // Default destructor
+
+  if(fNbTRDTrack) delete fNbTRDTrack;
+  if(fNbTRDTrackOffline) delete fNbTRDTrackOffline;
+  if(fNbTRDTrackStandalone) delete fNbTRDTrackStandalone;
+  if(fNbTRDTracklet) delete fNbTRDTracklet;
+  if(fNbTRDTrackletOffline) delete fNbTRDTrackletOffline;
+  if(fNbTRDTrackletStandalone) delete fNbTRDTrackletStandalone;
+  if(fNbTimeBin) delete fNbTimeBin;
+  if(fNbTimeBinOffline) delete fNbTimeBinOffline;
+  if(fNbTimeBinStandalone) delete fNbTimeBinStandalone;
+  if(fNbClusters) delete fNbClusters;
+  if(fNbClustersOffline) delete fNbClustersOffline;
+  if(fNbClustersStandalone) delete fNbClustersStandalone;
+  if(fPHSum) delete fPHSum;
+  if(fCHSum) delete fCHSum;
+  if(fDetSum) delete fDetSum;
+  if(fDetSumVector) delete fDetSumVector;
+  if(fkNameDirectory) delete fkNameDirectory;
+  if(fGraph){fGraph->Delete(); delete fGraph;}
+
+}
+//________________________________________________________________________
+void AliTRDcalibration::CreateOutputObjects() 
+{
+  // Create output objects
+
+  OpenFile(0, "RECREATE");
+  
+  // Number of time bins
+  AliTRDcalibDB *cal = AliTRDcalibDB::Instance();
+  fNbTimeBins = cal->GetNumberOfTimeBins();
+  
+  // instance calibration: what to calibrate
+  fTRDCalibraFillHisto = AliTRDCalibraFillHisto::Instance();
+  fTRDCalibraFillHisto->SetHisto2d(fHisto2d); // choose to use histograms
+  fTRDCalibraFillHisto->SetVector2d(fVector2d); // choose to use vectors
+  fTRDCalibraFillHisto->SetCH2dOn();  // choose to calibrate the gain
+  fTRDCalibraFillHisto->SetPH2dOn();  // choose to calibrate the drift velocity
+  fTRDCalibraFillHisto->SetPRF2dOn(); // choose to look at the PRF
+  fTRDCalibraFillHisto->SetLinearFitterOn(fVdriftLinear); // Other possibility vdrift VDRIFT
+  fTRDCalibraFillHisto->SetLinearFitterDebugOn(fVdriftLinear); // Other possibility vdrift
+
+  // segmentation (should be per default the max and add at the end)
+  for(Int_t k = 0; k < 3; k++){
+    if(((fNz[k] != 10) && (fNrphi[k] != 10)) && ((fNz[k] != 100) && (fNrphi[k] != 100))) {
+      fTRDCalibraFillHisto->SetNz(k,fNz[k]);                                    // Mode calibration
+      fTRDCalibraFillHisto->SetNrphi(k,fNrphi[k]);                             // Mode calibration
+    }
+    else {
+      if((fNz[k] == 100) && (fNrphi[k] == 100))  {
+       if(fVector2d) AliInfo("The mode all together is not supported by the vector method");
+       fTRDCalibraFillHisto->SetAllTogether(k);
+      }
+      if((fNz[k] == 10) && (fNrphi[k] == 10))  {
+       if(fVector2d) AliInfo("The mode per supermodule is not supported by the vector method");
+       fTRDCalibraFillHisto->SetPerSuperModule(k);
+      }
+    }
+  }
+
+  // Debug level
+  fTRDCalibraFillHisto->SetDebugLevel(DebugLevel()); //debug stuff
+
+  // Init the stuff
+  fTRDCalibraFillHisto->Init2Dhistos(); // initialise the histos
+
+  // cuts
+  fTRDCalibraFillHisto->SetNumberClusters(flow); // At least flow clusters
+  fTRDCalibraFillHisto->SetNumberClustersf(fhigh); // The more fhigh clusters
+  fTRDCalibraFillHisto->SetFillWithZero(ffillZero); // Fill zeros
+  fTRDCalibraFillHisto->SetNormalizeNbOfCluster(fnormalizeNbOfCluster); // For iterations
+
+  // Add them to the container
+  fContainer = new TObjArray();
+  if(fHisto2d) {
+    fContainer->Add(fTRDCalibraFillHisto->GetCH2d()); //TH2I
+    fContainer->Add(fTRDCalibraFillHisto->GetPH2d()); //TProfile2D
+    fContainer->Add(fTRDCalibraFillHisto->GetPRF2d()); //TProfile2D
+  }
+  if(fVdriftLinear) fContainer->Add(fTRDCalibraFillHisto->GetVdriftLinearFit()); // Other drift velocity 
+  if(fVector2d) fContainer->Add(fTRDCalibraFillHisto->GetCalibraVector()); //calibra vector
+      
+  if(DebugLevel()) {
+    
+    // Init the debug histos
+    fNbTRDTrack = new TH1F("TRDTrack","TRDTrack",500,0,500);
+    fNbTRDTrack->Sumw2();
+    fNbTRDTrackOffline = new TH1F("TRDTrackOffline","TRDTrackOffline",500,0,500);
+    fNbTRDTrackOffline->Sumw2();
+    fNbTRDTrackStandalone = new TH1F("TRDTrackStandalone","TRDTrackStandalone",500,0,500);
+    fNbTRDTrackStandalone->Sumw2();
+    //
+    fNbTRDTracklet = new TH1F("TRDTracklet","TRDTracklet",540,0.,540.);
+    fNbTRDTracklet->Sumw2();
+    fNbTRDTrackletOffline = new TH1F("TRDTrackletOffline","TRDTrackletOffline",540,0.,540.);
+    fNbTRDTrackletOffline->Sumw2();
+    fNbTRDTrackletStandalone = new TH1F("TRDTrackletStandalone","TRDTrackletStandalone",540,0.,540.);
+    fNbTRDTrackletStandalone->Sumw2();
+    //
+    fNbTimeBin = new TH1F("TimeBin","TimeBin",35,0,35);
+    fNbTimeBin->Sumw2();
+    fNbTimeBinOffline = new TH1F("TimeBinOffline","TimeBinOffline",35,0,35);
+    fNbTimeBinOffline->Sumw2();
+    fNbTimeBinStandalone = new TH1F("TimeBinStandalone","TimeBinStandalone",35,0,35);
+    fNbTimeBinStandalone->Sumw2();
+    //
+    fNbClusters = new TH1F("NbClusters","",35,0,35);
+    fNbClusters->Sumw2();
+    fNbClustersOffline = new TH1F("NbClustersOffline","",35,0,35);
+    fNbClustersOffline->Sumw2();
+    fNbClustersStandalone = new TH1F("NbClustersStandalone","",35,0,35);
+    fNbClustersStandalone->Sumw2();
+    //
+    fPHSum = new TProfile2D("PH2dSum","Nz0Nrphi0"
+                           ,fNbTimeBins,-0.05,(Double_t)(fNbTimeBins/10.0)-0.05
+                           ,540,0,540);
+    fPHSum->SetYTitle("Det/pad groups");
+    fPHSum->SetXTitle("time [#mus]");
+    fPHSum->SetZTitle("<PH> [a.u.]");
+    fPHSum->SetStats(0);
+    //
+    fCHSum = new TH2I("CH2dSum","Nz0Nrphi0",100,0,300,540,0,540);
+    fCHSum->SetYTitle("Det/pad groups");
+    fCHSum->SetXTitle("charge deposit [a.u]");
+    fCHSum->SetZTitle("counts");
+    fCHSum->SetStats(0);
+    fCHSum->Sumw2();
+    
+    // Add them
+    fContainer->Add(fNbTRDTrack);
+    fContainer->Add(fNbTRDTrackOffline);
+    fContainer->Add(fNbTRDTrackStandalone);
+    fContainer->Add(fNbTRDTracklet);
+    fContainer->Add(fNbTRDTrackletOffline);
+    fContainer->Add(fNbTRDTrackletStandalone);
+    fContainer->Add(fNbTimeBin);
+    fContainer->Add(fNbTimeBinOffline);
+    fContainer->Add(fNbTimeBinStandalone);
+    fContainer->Add(fNbClusters);
+    fContainer->Add(fNbClustersOffline);
+    fContainer->Add(fNbClustersStandalone);
+    fContainer->Add(fPHSum);
+    fContainer->Add(fCHSum);
+
+  }
+
+}
+
+//________________________________________________________________________
+void AliTRDcalibration::Exec(Option_t *) 
+{
+  //
+  // Execute function where the reference data are filled
+  //
+
+  if(!fTracks) return;
+  
+  // In total
+  Int_t nbTrdTracks = 0;
+  // standalone
+  Int_t nbTrdTracksStandalone = 0;
+  // offline
+  Int_t nbTrdTracksOffline = 0;
+  
+
+  //
+  // Loop on track in the event
+  //
+  //printf("Total of %d\n",fTracks->GetEntriesFast());
+  for(Int_t itrk=0; itrk < fTracks->GetEntriesFast(); itrk++){
+    
+    //printf("itrk %d\n",itrk);
+
+    fTrackInfo = (AliTRDtrackInfo*)fTracks->UncheckedAt(itrk);
+    ftrdTrack = fTrackInfo->GetTrack();
+    if(!ftrdTrack) continue;
+
+    nbTrdTracks++;
+  
+    fTRDCalibraFillHisto->UpdateHistogramsV1(ftrdTrack);
+
+    if(DebugLevel()) {
+      
+      Bool_t standalonetracklet = kFALSE;  
+      const AliTRDseedV1 *tracklet = 0x0;
+      //
+      // Loop on tracklet in the event
+      //
+      for(Int_t itr = 0; itr < 6; itr++){
+       //printf("itr %d\n",itr);
+       if(!(tracklet = ftrdTrack->GetTracklet(itr))) continue;
+       if(!tracklet->IsOK()) continue;
+       // standalone
+       if(tracklet->IsStandAlone()) standalonetracklet = kTRUE;
+       Int_t nbclusters = 0;
+       // For PH
+       Double_t phtb[AliTRDseedV1::kNtb];
+       memset(phtb, 0, AliTRDseedV1::kNtb*sizeof(Double_t));
+       // For CH
+       Double_t sum = 0.0;
+       // normalisation
+       Float_t normalisation = 6.67;
+       Int_t detector = 0;
+       Int_t crossrow = 0;
+       for(int ic=0; ic<AliTRDseedV1::kNtb; ic++){
+         // Check no shared clusters
+         for(int icc=AliTRDseedV1::kNtb; icc<AliTRDseedV1::kNclusters; icc++){
+           if((fcl = tracklet->GetClusters(icc)))  crossrow = 1;
+         }
+         if(!(fcl = tracklet->GetClusters(ic))) continue;
+         nbclusters++;
+         Int_t time = fcl->GetPadTime();
+         Float_t ch =  tracklet->GetdQdl(ic);
+         Float_t qcl = TMath::Abs(fcl->GetQ());
+         detector = fcl->GetDetector();          
+         if((time>-1) && (time<fNbTimeBins)) phtb[time]=qcl;
+         sum += ch/normalisation;
+         fNbTimeBin->Fill(time);
+         if(tracklet->IsStandAlone()) fNbTimeBinStandalone->Fill(time);
+         else fNbTimeBinOffline->Fill(time);
+       }
+
+       fNbTRDTracklet->Fill(detector);
+       if(tracklet->IsStandAlone()) fNbTRDTrackletStandalone->Fill(detector);
+       else fNbTRDTrackletOffline->Fill(detector);
+       
+       fNbClusters->Fill(nbclusters);
+       if(tracklet->IsStandAlone())  fNbClustersStandalone->Fill(nbclusters);
+       else  fNbClustersOffline->Fill(nbclusters);
+       
+       if((nbclusters > flow) && (nbclusters < fhigh)){
+         fCHSum->Fill(sum/20.0,0.0);
+         for(int ic=0; ic<fNbTimeBins; ic++){
+           //printf("ic %d and time %f and cluster %f \n",ic,(Double_t)(ic/10.0),(Double_t)phtb[ic]);
+           if(ffillZero) fPHSum->Fill((Double_t)(ic/10.0),0.0,(Double_t)phtb[ic]);
+           else {
+             if(phtb[ic] > 0.0) fPHSum->Fill((Double_t)(ic/10.0),0.0,(Double_t)phtb[ic]);
+           }
+         }
+       }
+      }
+    
+    if(standalonetracklet) nbTrdTracksStandalone++;
+    else nbTrdTracksOffline++;
+    
+    }
+    
+  }
+  
+  if(DebugLevel()) {
+    
+    //Fill Histos
+    fNbTRDTrack->Fill(nbTrdTracks);
+    fNbTRDTrackStandalone->Fill(nbTrdTracksStandalone);
+    fNbTRDTrackOffline->Fill(nbTrdTracksOffline);
+    
+  }
+
+  //printf("Nbof tracks %d\n",nbTrdTracks);
+  
+  TFile *file = TFile::Open("test.root","RECREATE");
+  fContainer->Write();
+  file->Close();
+
+  // Post output data
+  PostData(0, fContainer);
+
+  //printf("post container\n");
+  
+}      
+//________________________________________________________________________
+void AliTRDcalibration::Terminate(Option_t *) 
+{
+  // Draw result to the screen
+  // Called once at the end of the query
+
+  //printf("terminate\n");
+
+  if(fTRDCalibraFillHisto) fTRDCalibraFillHisto->DestroyDebugStreamer();
+}
+//________________________________________________________
+Bool_t AliTRDcalibration::GetRefFigure(Int_t ifig)
+{
+  //
+  // Draw filled histos
+  //
+  
+  gStyle->SetPalette(1);
+  gStyle->SetOptStat(1111);
+  gStyle->SetPadBorderMode(0);
+  gStyle->SetCanvasColor(10);
+  gStyle->SetPadLeftMargin(0.13);
+  gStyle->SetPadRightMargin(0.13);
+
+  if(!fContainer) return kFALSE;
+  
+  switch(ifig){
+  case kNbTrack:{
+    TCanvas *c0 = new TCanvas("c0","c0",10,10,510,510);
+    TLegend *legNbTrack = new TLegend(.7, .7, .98, .98);
+    legNbTrack->SetBorderSize(1);
+    TH1F *h  = 0x0;
+    TH1F *ho = 0x0;
+    TH1F *hs = 0x0;
+    if(!(h = (TH1F *)fContainer->FindObject("TRDTrack"))) break;
+    if(!(ho = (TH1F *)fContainer->FindObject("TRDTrackOffline"))) break;
+    if(!(hs = (TH1F *)fContainer->FindObject("TRDTrackStandalone"))) break;
+    c0->cd();
+    //gPad->SetLogy();
+    gPad->SetGridy();
+    gPad->SetGridx();
+    h->Draw();
+    ho->Draw("same");
+    hs->Draw("same");
+    legNbTrack->AddEntry(h, "all", "p");
+    legNbTrack->AddEntry(ho, "offline", "p");
+    legNbTrack->AddEntry(hs, "standalone", "p");
+    legNbTrack->Draw("same");
+    return kTRUE;
+  }
+  case kNbTracklet:{
+    TLegend *legNbTracklet = new TLegend(.7, .7, .98, .98);
+    legNbTracklet->SetBorderSize(1);
+    TH1F *h = 0x0;
+    TH1F *ho = 0x0;
+    TH1F *hs = 0x0;
+    if(!(h = (TH1F *)fContainer->FindObject("TRDTracklet"))) break;
+    if(!(ho = (TH1F *)fContainer->FindObject("TRDTrackletOffline"))) break;
+    if(!(hs = (TH1F *)fContainer->FindObject("TRDTrackletStandalone"))) break;
+    h->Draw();
+    ho->Draw("same");
+    hs->Draw("same");
+    legNbTracklet->AddEntry(h, "all", "p");
+    legNbTracklet->AddEntry(ho, "offline", "p");
+    legNbTracklet->AddEntry(hs, "standalone", "p");
+    legNbTracklet->Draw("same");
+    gPad->SetLogy();
+    gPad->SetGridy();
+    gPad->SetGridx();
+    return kTRUE;
+  }
+  case kNbTimeBin:{
+    TLegend *legNbTimeBin = new TLegend(.7, .7, .98, .98);
+    legNbTimeBin->SetBorderSize(1);
+    TH1F *h = 0x0;
+    TH1F *ho = 0x0;
+    TH1F *hs = 0x0;
+    if(!(h = (TH1F *)fContainer->FindObject("TimeBin"))) break;
+    if(!(ho = (TH1F *)fContainer->FindObject("TimeBinOffline"))) break;
+    if(!(hs = (TH1F *)fContainer->FindObject("TimeBinStandalone"))) break;
+    h->Draw();
+    ho->Draw("same");
+    hs->Draw("same");
+    legNbTimeBin->AddEntry(h, "all", "p");
+    legNbTimeBin->AddEntry(ho, "offline", "p");
+    legNbTimeBin->AddEntry(hs, "standalone", "p");
+    legNbTimeBin->Draw("same");
+    //gPad->SetLogy();
+    gPad->SetGridy();
+    gPad->SetGridx();
+    return kTRUE;
+  }
+  case kNbClusters:{
+    TLegend *legNbClusters = new TLegend(.7, .7, .98, .98);
+    legNbClusters->SetBorderSize(1);
+    TH1F *h = 0x0;
+    TH1F *ho = 0x0;
+    TH1F *hs = 0x0;
+    if(!(h = (TH1F *)fContainer->FindObject("NbClusters"))) break;
+    if(!(ho = (TH1F *)fContainer->FindObject("NbClustersOffline"))) break;
+    if(!(hs = (TH1F *)fContainer->FindObject("NbClustersStandalone"))) break;
+    h->Draw();
+    ho->Draw("same");
+    hs->Draw("same");
+    legNbClusters->AddEntry(h, "all", "p");
+    legNbClusters->AddEntry(ho, "offline", "p");
+    legNbClusters->AddEntry(hs, "standalone", "p");
+    legNbClusters->Draw("same");
+    gPad->SetLogy();
+    gPad->SetGridy();
+    gPad->SetGridx();
+    return kTRUE;
+  }
+  case kPHSum:{
+    TProfile2D *h = 0x0;
+    if(!(h = (TProfile2D *)fContainer->FindObject("PH2dSum"))) break;
+    TH1D *projh = h->ProjectionX("projh",1,1,"e");
+    projh->Draw();
+    gPad->SetGridy();
+    gPad->SetGridx();
+    return kTRUE;
+  }
+  case kCHSum:{
+    TH2I *h = 0x0;
+    if(!(h = (TH2I *)fContainer->FindObject("CH2dSum"))) break;
+    TH1D *projh = h->ProjectionX("projhh",1,1,"e");
+    projh->Draw();
+    gPad->SetGridy();
+    gPad->SetGridx();
+    return kTRUE;
+  }
+  case kPH2D:{
+    if(!fHisto2d) {
+      AliInfo("Histo was not filled!");
+      break;
+    }
+    TProfile2D *h = 0x0;
+    if(!(h = (TProfile2D *)fContainer->FindObject("PH2d"))) break;
+    h->Draw("lego");
+    return kTRUE;
+  }
+  case kCH2D:{
+    if(!fHisto2d) {
+      AliInfo("Histo was not filled!");
+      break;
+    }
+    TH2I *h = 0x0;
+    if(!(h = (TH2I *)fContainer->FindObject("CH2d"))) break;
+    h->Draw("lego");
+    return kTRUE;
+  }
+  case kPRF2D:{
+    if(!fHisto2d) {
+      AliInfo("Histo was not filled!");
+      break;
+    }
+    TProfile2D *h = 0x0;
+    if(!(h = (TProfile2D *)fContainer->FindObject("PRF2d"))) break;
+    h->Draw("lego");
+    return kTRUE;
+  }
+  case kPH2DVector:{
+    if(!fVector2d) {
+      AliInfo("vector was not filled!");
+      break;
+    }
+    AliTRDCalibraVector *v = 0x0;
+    TGraphErrors *vdet = 0x0; 
+    if(!(v = (AliTRDCalibraVector *)fContainer->FindObject("AliTRDCalibraVector"))) break;
+    Int_t detectormax = -1;
+    Int_t groupmax    = -1;
+    if(!v->FindTheMaxEntries(1,detectormax,groupmax)) break;
+    if(!(vdet = v->ConvertVectorPHTGraphErrors((Int_t)detectormax,groupmax,"plotPH2dVector"))) break;
+    Int_t nbeentries = 0;
+    TH1F *ko = v->CorrectTheError(vdet,nbeentries);
+    ko->Draw();
+    AliInfo(Form("There are %d entries in the detector %d and group %d",nbeentries,detectormax,groupmax));
+    return kTRUE;
+  }
+case kCH2DVector:{
+    if(!fVector2d) {
+      AliInfo("vector was not filled!");
+      break;
+    }
+    AliTRDCalibraVector *v = 0x0;
+    TH1F *vdet = 0x0; 
+    if(!(v = (AliTRDCalibraVector *)fContainer->FindObject("AliTRDCalibraVector"))) break;
+    Int_t detectormax = -1;
+    Int_t groupmax    = -1;
+    if(!v->FindTheMaxEntries(0,detectormax,groupmax)) break;
+    if(!(vdet = v->ConvertVectorCHHisto((Int_t)detectormax,groupmax,"plotCH2dVector"))) break;
+    vdet->Draw();
+    AliInfo(Form("The detectormax and groupmax are %d and %d",detectormax,groupmax));
+    return kTRUE;
+  }
+  case kPRF2DVector:{
+    if(!fVector2d) {
+      AliInfo("vector was not filled!");
+      break;
+    }
+    AliTRDCalibraVector *v = 0x0;
+    TGraphErrors *vdet = 0x0; 
+    if(!(v = (AliTRDCalibraVector *)fContainer->FindObject("AliTRDCalibraVector"))) break;
+    Int_t detectormax  = -1;
+    Int_t groupmax     = -1;
+    Int_t nbeentries   = 0;
+    if(!v->FindTheMaxEntries(2,detectormax,groupmax)) break;
+    if(!(vdet = v->ConvertVectorPRFTGraphErrors((Int_t)detectormax,groupmax,"plotPRF2dVector"))) break;
+    TH1F *ko = v->CorrectTheError(vdet,nbeentries);
+    ko->Draw();
+    AliInfo(Form("The detectormax and groupmax are %d and %d",detectormax,groupmax));
+    return kTRUE;
+  }
+  case kLinearFitter:{
+    if(!fVdriftLinear) {
+      AliInfo("vdrift linear was not filled!");
+      break;
+    }
+    AliTRDCalibraVdriftLinearFit *h = 0x0;
+    TH2S *hdetector = 0x0; 
+    if(!(h = (AliTRDCalibraVdriftLinearFit *)fContainer->FindObject("AliTRDCalibraVdriftLinearFit"))) break;
+    Double_t entries[540];
+    for(Int_t k = 0; k < 540; k++){
+      entries[k] = 0.0;
+      hdetector = 0x0;
+      if(!(hdetector = (TH2S *)h->GetLinearFitterHisto(k,kFALSE))) continue;
+      entries[k] = hdetector->GetEntries();
+    }
+    Double_t max = -10.0;
+    Double_t detectormax = -1;
+    for(Int_t k = 0; k < 540; k++){
+      if(entries[k] > max) {
+       max = entries[k];
+       detectormax = k;
+      }
+    }
+    hdetector = 0x0;
+    if((TMath::Abs(max) <= 0.001) || (detectormax <0.0) || (detectormax >=540.0)) break;
+    if(!(hdetector = (TH2S *)h->GetLinearFitterHisto((Int_t)detectormax,kFALSE))) break;
+    AliInfo(Form("The detector with the maximum of entries is %d",detectormax));
+    hdetector->Draw();
+    return kTRUE;
+  }
+  case kGainFactor:{
+    if(!fPostProcess){
+      if(!PostProcess()) break;
+    }
+    TGraph *fgain = (TGraph *) fGraph->At(0);
+    if(!fgain) break;
+    fgain->Draw("ALP");
+    return kTRUE;
+  }
+  case kVdriftT0Factor:{
+    if(!fPostProcess){
+      if(!PostProcess()) break;
+    }
+    TCanvas *c = new TCanvas("c","c",10,10,510,510);
+    c->Divide(2,1);
+    TGraph *fvd = (TGraph *) fGraph->At(1);
+    if(fvd){
+      c->cd(1);
+      fvd->Draw("ALP");
+    } 
+    TGraph *ft0 = (TGraph *) fGraph->At(2);
+    if(ft0){
+      c->cd(2);
+      ft0->Draw("ALP");
+    } 
+    return kTRUE;
+  }
+  case kVdriftLorentzAngleFactor:{
+    if(!fVdriftLinear) {
+      AliInfo("vdrift linear was not filled!");
+      break;
+    }
+    if(!fPostProcess){
+      if(!PostProcess()) break;
+    }
+    TCanvas *c = new TCanvas("c","c",10,10,510,510);
+    c->Divide(2,1);
+    TGraph *fvdl = (TGraph *) fGraph->At(3);
+    if(fvdl){
+      c->cd(1);
+      fvdl->Draw("ALP");
+    } 
+    TGraph *flal = (TGraph *) fGraph->At(4);
+    if(flal){
+      c->cd(2);
+      flal->Draw("ALP");
+    } 
+    return kTRUE;
+  }
+  case kPRFFactor:{
+    if(!fPostProcess){
+      if(!PostProcess()) break;
+    }
+    TGraph *fprf = (TGraph *) fGraph->At(5);
+    if(!fprf) break;
+    fprf->Draw("ALP");
+    return kTRUE;
+  }
+  }
+  
+  return kFALSE;
+  
+}
+//________________________________________________________________________
+Bool_t AliTRDcalibration::PostProcess()
+{
+  // 
+  // Fit the filled histos
+  //
+
+  if(!fGraph){
+    fGraph = new TObjArray(6);
+    fGraph->SetOwner();
+  }
+  else {
+    delete fGraph;
+    PostProcess();
+  }
+
+  Bool_t storage[3] = {kFALSE,kFALSE,kFALSE};
+
+  // storage element
+  AliCDBManager *man = AliCDBManager::Instance();
+  man->SetDefaultStorage("local://$ALICE_ROOT");
+  AliCDBStorage* storLoc = man->GetStorage(fkNameDirectory);
+  if (!storLoc)
+    return kFALSE;
+  man->SetRun(fRunNumber);
+
+  // MetaData
+  AliCDBMetaData mdDet; 
+  mdDet.SetObjectClassName("AliTRDCalDet");
+  AliCDBMetaData mdPad; 
+  mdPad.SetObjectClassName("AliTRDCalPad");
+  
+  // Objects for fitting
+  AliTRDCalibraFit *calibra = AliTRDCalibraFit::Instance();
+  calibra->SetDebugLevel(2); // 0 rien, 1 fitvoir, 2 debug files, 3 one detector  
+  
+  // Take the stuff
+  if (!fContainer) {
+    Printf("ERROR: list not available");
+    return kFALSE;
+  }
+
+  if(fHisto2d && fVector2d) AliInfo("We will only look at histos. Set fHisto2d off if you don't want");
+  AliTRDCalibraVector *calibraVector = 0x0;
+  if(fVector2d) calibraVector = (AliTRDCalibraVector *) fContainer->FindObject("CalibraVector");
+  //
+  // GAIN TH2I
+  //
+  Bool_t pass = kFALSE; 
+  AliTRDCalibraVector *vvect = 0x0;
+  if(fHisto2d) {
+    TH2I *histogain = (TH2I *) fContainer->FindObject("CH2d");  
+    if(histogain) {
+      histogain->SetDirectory(0);
+      calibra->SetMinEntries(20); 
+      if(fCompressPerDetector){
+       if(AddStatsPerDetector(histogain)) pass = calibra->AnalyseCH(fCHSum);
+      }
+      else pass = calibra->AnalyseCH(histogain);
+    }
+  }
+  else {
+    if(fVector2d && calibraVector) {
+      calibra->SetMinEntries(20); 
+      if(fCompressPerDetector){
+       if(!(vvect = calibraVector->AddStatsPerDetectorCH())) return kFALSE;
+               pass = calibra->AnalyseCH(vvect);
+      }
+      else pass = calibra->AnalyseCH(calibraVector);
+    }
+  }
+  
+  if(pass)
+    {
+      Int_t nbtg = 6*4*18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb0(0))
+       + 6*  18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb2(0));
+      Int_t nbfit = calibra->GetNumberFit();  //Number of fits
+      Int_t nbE   = calibra->GetNumberEnt();  //Number of detector mit entries
+      // enough statistics
+      if ((nbtg >                  0) && 
+         (nbfit        >= 0.001*nbE))
+       {
+         // create the cal objects
+         calibra->PutMeanValueOtherVectorFit(1,kTRUE); 
+         TObjArray object           = calibra->GetVectorFit();
+         AliTRDCalDet *objgaindet   = calibra->CreateDetObjectGain(&object);
+         TObject *objgainpad        = calibra->CreatePadObjectGain();
+         // store
+         AliCDBId id1("TRD/Calib/ChamberGainFactor",fRunNumber, AliCDBRunRange::Infinity()); 
+         storLoc->Put((TObject *)objgaindet, id1, &mdDet); 
+         AliCDBId id2("TRD/Calib/LocalGainFactor",fRunNumber, AliCDBRunRange::Infinity()); 
+         storLoc->Put((TObject *)objgainpad, id2, &mdPad);
+         storage[0] = kTRUE;
+         // Make graph
+         TGraph *graph = 0x0;
+         if(FillGraphIndex(&object,graph)){ 
+           fGraph->AddAt(graph,0);
+         }
+       }//if(enough statistics?)
+      calibra->ResetVectorFit();
+    }
+  else return kFALSE;
+  
+  //
+  // VDRIFT average pulse height
+  //
+  pass = kFALSE; 
+  if(fHisto2d) {
+    TProfile2D *histodriftvelocity = (TProfile2D *) fContainer->FindObject("PH2d");  
+    if(histodriftvelocity) {
+      histodriftvelocity->SetDirectory(0);  
+      calibra->SetMinEntries(20*20);  
+      if(fCompressPerDetector){
+       if(AddStatsPerDetector(histodriftvelocity,1)) {
+         pass = calibra->AnalysePH(fDetSumVector);
+       }
+      }
+      else pass = calibra->AnalysePH(histodriftvelocity);
+    }
+  }
+  else {
+    if(fVector2d && calibraVector) {
+      calibra->SetMinEntries(20*20);  
+      if(fCompressPerDetector){
+       if(!(vvect = calibraVector->AddStatsPerDetectorPH())) return kFALSE;
+               pass = calibra->AnalysePH(vvect);
+      }
+      else pass = calibra->AnalysePH(calibraVector);  
+    }
+  }
+
+  if(pass) {
+    Int_t nbtg = 6*4*18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb0(1))
+      + 6*  18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb2(1));
+    Int_t nbfit  = calibra->GetNumberFit();
+    Int_t nbE    = calibra->GetNumberEnt();
+    // enough statistics
+    if ((nbtg >                  0) && 
+       (nbfit        >= 0.001*nbE))
+      {
+       // create the cal objects
+       calibra->PutMeanValueOtherVectorFit(1,kTRUE);
+       calibra->PutMeanValueOtherVectorFit2(1,kTRUE); 
+       TObjArray object  = calibra->GetVectorFit();
+       AliTRDCalDet *objdriftvelocitydet = calibra->CreateDetObjectVdrift(&object,kTRUE);
+       TObject *objdriftvelocitypad      = calibra->CreatePadObjectVdrift();
+       TObjArray objectt          = calibra->GetVectorFit2();
+       AliTRDCalDet *objtime0det  = calibra->CreateDetObjectT0(&object,kTRUE);
+       TObject *objtime0pad       = calibra->CreatePadObjectT0();
+       // store
+       AliCDBId id1("TRD/Calib/ChamberVdrift",fRunNumber, AliCDBRunRange::Infinity()); 
+       storLoc->Put((TObject *)objdriftvelocitydet, id1, &mdDet); 
+       AliCDBId id2("TRD/Calib/LocalVdrift",fRunNumber, AliCDBRunRange::Infinity()); 
+       storLoc->Put((TObject *)objdriftvelocitypad, id2, &mdPad); 
+       //
+       AliCDBId idd1("TRD/Calib/ChamberT0",fRunNumber, AliCDBRunRange::Infinity()); 
+       storLoc->Put((TObject *)objtime0det, idd1, &mdDet); 
+       AliCDBId idd2("TRD/Calib/LocalT0",fRunNumber, AliCDBRunRange::Infinity()); 
+       storLoc->Put((TObject *)objtime0pad, idd2, &mdPad); 
+       // Make graph
+       TGraph *graph = 0x0;
+       if(FillGraphIndex(&object,graph)){ 
+         fGraph->AddAt(graph,1);
+       }
+       TGraph *graphh = 0x0;
+       if(FillGraphIndex(&objectt,graphh)){ 
+         fGraph->AddAt(graphh,2);
+       }
+      }//if(enough statistics)
+    calibra->ResetVectorFit();
+  }
+  else return kFALSE;
+  
+  //
+  // PRF
+  //
+  pass = kFALSE; 
+  if(fHisto2d) {
+    TProfile2D *histoprf = (TProfile2D *) fContainer->FindObject("PRF2d");
+    if (histoprf) {
+      histoprf->SetDirectory(0);  
+      calibra->SetMinEntries(600); 
+      if(fCompressPerDetector){
+       if(AddStatsPerDetector(histoprf,2)) pass = calibra->AnalysePRFMarianFit(fDetSumVector);
+      }
+      else pass = calibra->AnalysePRFMarianFit(histoprf);
+    }
+  }
+  else {
+    if(fVector2d && calibraVector) {
+      calibra->SetMinEntries(600);  
+      if(fCompressPerDetector){
+       if(!(vvect =calibraVector->AddStatsPerDetectorPRF())) return kFALSE;
+       pass = calibra->AnalysePRFMarianFit(vvect);
+      }
+      else pass = calibra->AnalysePRFMarianFit(calibraVector);  
+    }
+  }
+  
+  if(pass){
+    Int_t nbtg = 6*4*18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb0(2))
+      + 6*  18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb2(2));
+    Int_t nbfit        = calibra->GetNumberFit();
+    Int_t nbE          = calibra->GetNumberEnt();
+    // enough statistics
+    if ((nbtg >                  0) && 
+       (nbfit        >= 0.001*nbE)) {
+      TObjArray object            = calibra->GetVectorFit();
+      TObject *objPRFpad          = calibra->CreatePadObjectPRF(&object);
+      // store
+      AliCDBId id2("TRD/Calib/PRFWidth",fRunNumber, AliCDBRunRange::Infinity()); 
+      storLoc->Put((TObject *)objPRFpad, id2, &mdPad); 
+      // Make graph
+      TGraph *graph = 0x0;
+      if(FillGraphIndex(&object,graph)){ 
+       fGraph->AddAt(graph,5);
+      }
+    }
+    calibra->ResetVectorFit();
+  }
+  else return kFALSE;
+  
+  //
+  // VDRIFT linear fit 
+  //
+  AliTRDCalibraVdriftLinearFit *vlinearfit = (AliTRDCalibraVdriftLinearFit *) fContainer->FindObject("LinearVdriftFit"); 
+  if (vlinearfit) {
+    calibra->SetMinEntries(20*20);     
+    if(calibra->AnalyseLinearFitters(vlinearfit)) {
+      
+      Int_t nbtg = 6*4*18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb0(2))
+       + 6*  18*((Int_t) ((AliTRDCalibraMode *)calibra->GetCalibraMode())->GetDetChamb2(2));
+      Int_t nbfit  = calibra->GetNumberFit();
+      Int_t nbE    = calibra->GetNumberEnt();
+      // enough statistics
+      if ((nbtg >                  0) && 
+         (nbfit        >= 0.001*nbE))
+       {
+         // create the cal objects
+         calibra->PutMeanValueOtherVectorFit(1,kTRUE);
+         calibra->PutMeanValueOtherVectorFit2(1,kTRUE); 
+         TObjArray object  = calibra->GetVectorFit();
+         AliTRDCalDet *objdriftvelocitydet = calibra->CreateDetObjectVdrift(&object,kTRUE);
+         TObject *objdriftvelocitypad      = calibra->CreatePadObjectVdrift();
+         TObjArray objectt          = calibra->GetVectorFit2();
+         AliTRDCalDet *objtime0det  = calibra->CreateDetObjectT0(&object,kTRUE);
+         TObject *objtime0pad       = calibra->CreatePadObjectT0();
+         // store dummy
+         AliCDBId id1("TRD/Calib/ChamberVdriftLinear",fRunNumber, AliCDBRunRange::Infinity()); 
+         storLoc->Put((TObject *)objdriftvelocitydet, id1, &mdDet); 
+         AliCDBId id2("TRD/Calib/LocalVdriftLinear",fRunNumber, AliCDBRunRange::Infinity()); 
+         storLoc->Put((TObject *)objdriftvelocitypad, id2, &mdPad); 
+         //
+         AliCDBId idd1("TRD/Calib/ChamberLorentzAngle",fRunNumber, AliCDBRunRange::Infinity()); 
+         storLoc->Put((TObject *)objtime0det, idd1, &mdDet); 
+         AliCDBId idd2("TRD/Calib/LocalLorentzAngle",fRunNumber, AliCDBRunRange::Infinity()); 
+         storLoc->Put((TObject *)objtime0pad, idd2, &mdPad); 
+         // Make graph
+         TGraph *graph = 0x0;
+         if(FillGraphIndex(&object,graph)){ 
+           fGraph->AddAt(graph,3);
+         }
+         TGraph *graphh = 0x0;
+         if(FillGraphIndex(&objectt,graphh)){ 
+           fGraph->AddAt(graphh,4);
+         }
+       }//if(enough statistics)
+    }// if fit
+    calibra->ResetVectorFit();
+  }
+  else return kFALSE;
+  
+  fPostProcess = kTRUE;
+  
+  return kTRUE;
+  
+}
+
+//________________________________________________________________________
+Bool_t AliTRDcalibration::FillGraphIndex(const TObjArray *vectora,TGraph *graph) const
+{
+  //
+  // Fill one value (the first one) per detector
+  //
+
+  Int_t loop = (Int_t) vectora->GetEntriesFast();
+  if(loop != 540) {
+    AliInfo("The Vector Fit is not complete!");
+    return kFALSE;
+  }
+  
+  Double_t x[540];
+  Double_t y[540];
+  for (Int_t k = 0; k < loop; k++) {
+    if(!vectora->At(k)){
+      x[k] = -1.0;
+      y[k] = -1.0;
+      continue;
+    }
+    x[k]  = ((AliTRDCalibraFit::AliTRDFitInfo *) vectora->At(k))->GetDetector();
+    y[k]  = ((Float_t *)((AliTRDCalibraFit::AliTRDFitInfo *) vectora->At(k))->GetCoef())[0];
+  }
+
+  if(!graph) graph = new TGraph(540,&x[0],&y[0]);
+  else{ 
+    graph->~TGraph();
+    new(graph) TGraph(540,&x[0],&y[0]);
+  }
+
+  return kTRUE;
+
+}
+//________________________________________________________________________
+Bool_t AliTRDcalibration::AddStatsPerDetector(const TH2I *ch) 
+{
+  //
+  // Add statistic per detector
+  //
+  
+  AliTRDCalibraMode calibMode = AliTRDCalibraMode();
+  const char *name = ch->GetTitle();
+  if(!SetNzFromTObject(name,0,&calibMode)) return 0x0;
+  if(!SetNrphiFromTObject(name,0,&calibMode)) return 0x0;
+  if(((calibMode.GetNz(0) == 100) && (calibMode.GetNrphi(0) == 100)) || ((calibMode.GetNz(0) == 10) && (calibMode.GetNrphi(0) == 10))) return kFALSE;
+
+  Int_t    nybins  = ch->GetNbinsY();// groups number
+  Int_t    nxbins  = ch->GetNbinsX();// number of bins X
+  TAxis   *xaxis   = ch->GetXaxis();
+  Double_t lowedge  = xaxis->GetBinLowEdge(1);
+  Double_t upedge   = xaxis->GetBinUpEdge(nxbins);
+
+  // number per chamber 2
+  calibMode.ModePadCalibration(2,0);
+  calibMode.ModePadFragmentation(0,2,0,0);
+  calibMode.SetDetChamb2(0);
+  Int_t perChamber2 = (Int_t) calibMode.GetDetChamb2(0);
+
+  // number per other chamber
+  calibMode.ModePadCalibration(0,0);
+  calibMode.ModePadFragmentation(0,0,0,0);
+  calibMode.SetDetChamb0(0);
+  Int_t perChamber0 = (Int_t) calibMode.GetDetChamb0(0);
+
+  if(nybins != (6*18*perChamber2+6*4*18*perChamber0)) return kFALSE;
+
+  // Create Histo
+  TString nname((const char *)ch->GetName());
+  nname  += "PerDetector";
+  TString title("Nz");
+  title += 0;
+  title += "Nrphi";
+  title += 0;
+  if(!fCHSum) fCHSum = new TH2I((const char *)nname,(const char *)title
+                               ,nxbins,lowedge,upedge,540,0,540);
+  else{ 
+    fCHSum->~TH2I();
+    new(fCHSum) TH2I((const Char_t *) nname,(const char *)title
+                    ,nxbins,lowedge,upedge,540,0,540);
+  }
+  fCHSum->SetYTitle("Detector number");
+  fCHSum->SetXTitle("charge deposit [a.u]");
+  fCHSum->SetZTitle("counts");
+  fCHSum->SetStats(0);
+  fCHSum->Sumw2();
+
+  Int_t counter = 0;
+  
+  for(Int_t det = 0; det < 540; det++){
+
+    Int_t numberofgroup = 0;
+    if(AliTRDgeometry::GetStack(det) == 2) numberofgroup = perChamber2;
+    else numberofgroup = perChamber0;
+    TH1I *projch = (TH1I *) ch->ProjectionX("projch",counter+1,counter+numberofgroup,(Option_t *)"e");
+    projch->SetDirectory(0);
+       
+    for(Int_t nx = 0; nx <= nxbins; nx++) {
+      fCHSum->SetBinContent(nx,det+1,projch->GetBinContent(nx));
+      fCHSum->SetBinError(nx,det+1,projch->GetBinError(nx));
+    }
+
+    counter += numberofgroup;
+    
+    delete projch;
+
+  }
+
+  return kTRUE;
+
+}
+//_____________________________________________________________________________________________________________________
+Bool_t AliTRDcalibration::AddStatsPerDetector(const TProfile2D *ph,Int_t i)
+{
+  //
+  // Add statistic per detector
+  //
+
+  AliTRDCalibraMode calibMode = AliTRDCalibraMode();
+  const char *name = ph->GetTitle();
+  //printf("name %s\n",name);
+  if(!SetNzFromTObject(name,0,&calibMode)) return kFALSE;
+  if(!SetNrphiFromTObject(name,0,&calibMode)) return kFALSE;
+  if(((calibMode.GetNz(0) == 100) && (calibMode.GetNrphi(0) == 100)) || ((calibMode.GetNz(0) == 10) && (calibMode.GetNrphi(0) == 10))) return kFALSE;
+  //printf("Found mode Mz %d, Nrphi %d\n",calibMode.GetNz(0),calibMode.GetNrphi(0));  
+
+
+  Int_t    nybins  = ph->GetNbinsY();// groups number
+  Int_t    nxbins  = ph->GetNbinsX();// number of bins X
+  TAxis   *xaxis = ph->GetXaxis();
+  Double_t lowedge  = xaxis->GetBinLowEdge(1);
+  Double_t upedge   = xaxis->GetBinUpEdge(nxbins);
+
+  // number per chamber 2
+  calibMode.ModePadCalibration(2,0);
+  calibMode.ModePadFragmentation(0,2,0,0);
+  calibMode.SetDetChamb2(0);
+  Int_t perChamber2 = (Int_t) calibMode.GetDetChamb2(0);
+
+  // number per other chamber
+  calibMode.ModePadCalibration(0,0);
+  calibMode.ModePadFragmentation(0,0,0,0);
+  calibMode.SetDetChamb0(0);
+  Int_t perChamber0 = (Int_t) calibMode.GetDetChamb0(0);
+
+  if(nybins != (6*18*perChamber2+6*4*18*perChamber0)) return kFALSE;
+  
+  // Create calvector 
+  TString nbname((const char *)ph->GetName());
+  nbname  += "PerDetectorVector";
+  if(!fDetSumVector) fDetSumVector = new AliTRDCalibraVector();
+  else{ 
+    fDetSumVector->~AliTRDCalibraVector();
+    new(fDetSumVector) AliTRDCalibraVector();
+  }
+  if(i==1){
+    fDetSumVector->SetTimeMax(nxbins);
+  }
+  if(i==2){
+    fDetSumVector->SetNumberBinPRF(nxbins);
+    fDetSumVector->SetPRFRange(TMath::Abs(lowedge));
+  }
+  fDetSumVector->SetDetCha0(i,1);
+  fDetSumVector->SetDetCha2(i,1);
+  fDetSumVector->SetNzNrphi(i,0,0);
+  if(i==2) {
+    Int_t nbg = GetNumberOfGroupsPRF((const char *)name);
+    fDetSumVector->SetNbGroupPRF(nbg);
+  }
+
+  // Create Histo
+  TString nname((const char *)ph->GetName());
+  nname  += "PerDetector";
+  TString title("Nz");
+  title += 0;
+  title += "Nrphi";
+  title += 0;
+  if(!fDetSum) fDetSum = new TH2D((const char *)nname,(const Char_t *) title
+                               ,nxbins,lowedge,upedge,540,0,540);
+  else{ 
+    fDetSum->~TH2D();
+    new(fDetSum) TH2D((const Char_t *) nname,(const Char_t *) title
+                    ,nxbins,lowedge,upedge,540,0,540);
+  }
+  fDetSum->SetYTitle("Detector number");
+  fDetSum->SetXTitle(xaxis->GetTitle());
+  fDetSum->SetStats(0);
+  
+  Int_t counter = 0;
+
+  for(Int_t det = 0; det < 540; det++){
+
+    Int_t numberofgroup = 0;
+    if(AliTRDgeometry::GetStack(det) == 2) numberofgroup = perChamber2;
+    else numberofgroup = perChamber0;
+    
+    for(Int_t nx = 1; nx <= nxbins; nx++) {
+      
+      Double_t entries = 0.0;
+      Double_t sumw2 = 0.0;
+      Double_t sumw = 0.0;
+
+      for(Int_t k = counter+1; k <= (counter+numberofgroup); k++){
+       Int_t  binnumber = ph->GetBin(nx,k);
+       entries += ph->GetBinEntries(binnumber);
+       sumw2 += (ph->GetBinError(binnumber)*ph->GetBinError(binnumber)+ph->GetBinContent(binnumber)*ph->GetBinContent(binnumber))*ph->GetBinEntries(binnumber);
+       sumw += ph->GetBinContent(binnumber)*ph->GetBinEntries(binnumber);
+      }
+
+      Double_t mean = 0.0;
+      if(entries > 0.0) mean = sumw/entries;
+      Double_t squaremean = 0.0;
+      if(entries > 0.0) squaremean = sumw2/entries;
+      Double_t errorf = squaremean - mean*mean;
+      Double_t error = 0.0;
+      if(entries > 0.0) error = TMath::Sqrt(TMath::Abs(errorf)/entries);
+      
+      fDetSum->SetBinContent(nx,det+1,mean);
+      fDetSum->SetBinError(nx,det+1,error);
+
+      if(i==1) fDetSumVector->FillVectorPH(det,0,nx-1,(Int_t)entries,(Float_t)mean,(Float_t)squaremean);
+      if(i==2) fDetSumVector->FillVectorPRF(det,0,nx-1,(Int_t)entries,(Float_t)mean,(Float_t)squaremean);
+      
+    }
+    
+    counter += numberofgroup;
+
+  }
+
+  return kTRUE;
+
+  
+}
+//_____________________________________________________________________________
+Bool_t AliTRDcalibration::SetNrphiFromTObject(const char *name, Int_t i, AliTRDCalibraMode *calibMode) const
+{
+  //
+  // Set the granularity from object
+  //  
+  
+  const Char_t *patternrphi0 = "Nrphi0";
+  const Char_t *patternrphi1 = "Nrphi1";
+  const Char_t *patternrphi2 = "Nrphi2";
+  const Char_t *patternrphi3 = "Nrphi3";
+  const Char_t *patternrphi4 = "Nrphi4";
+  const Char_t *patternrphi5 = "Nrphi5";
+  const Char_t *patternrphi6 = "Nrphi6";
+
+  
+  const Char_t *patternrphi10 = "Nrphi10";
+  const Char_t *patternrphi100 = "Nrphi100";
+  const Char_t *patternz10 = "Nz10";
+  const Char_t *patternz100 = "Nz100";
+
+  // Nrphi mode
+  if ((strstr(name,patternrphi100)) && (strstr(name,patternz100))) {
+    calibMode->SetAllTogether(i);
+    return kTRUE;
+  }
+  if ((strstr(name,patternrphi10)) && (strstr(name,patternz10))) {
+    calibMode->SetPerSuperModule(i);
+    return kTRUE;
+  }
+  
+  if (strstr(name,patternrphi0)) {
+    calibMode->SetNrphi(i ,0);
+    return kTRUE;
+  }
+  if (strstr(name,patternrphi1)) {
+    calibMode->SetNrphi(i, 1);
+    return kTRUE;
+  }
+  if (strstr(name,patternrphi2)) {
+    calibMode->SetNrphi(i, 2);
+    return kTRUE;
+  }
+  if (strstr(name,patternrphi3)) {
+    calibMode->SetNrphi(i, 3);
+    return kTRUE;
+  }
+  if (strstr(name,patternrphi4)) {
+    calibMode->SetNrphi(i, 4);
+    return kTRUE;
+  }
+  if (strstr(name,patternrphi5)) {
+    calibMode->SetNrphi(i, 5);
+    return kTRUE;
+  }
+  if (strstr(name,patternrphi6)) {
+    calibMode->SetNrphi(i, 6);
+    return kTRUE;
+  }
+  
+  calibMode->SetNrphi(i ,0);
+  return kFALSE;
+  
+}
+//_____________________________________________________________________________
+Bool_t AliTRDcalibration::SetNzFromTObject(const char *name, Int_t i, AliTRDCalibraMode *calibMode) const
+{
+  //
+  // Set fNz[i] of the AliTRDCalibraFit::Instance()
+  // corresponding to the given TObject
+  //
+
+  // Some patterns
+  const Char_t *patternz0    = "Nz0";
+  const Char_t *patternz1    = "Nz1";
+  const Char_t *patternz2    = "Nz2";
+  const Char_t *patternz3    = "Nz3";
+  const Char_t *patternz4    = "Nz4";
+
+  const Char_t *patternrphi10 = "Nrphi10";
+  const Char_t *patternrphi100 = "Nrphi100";
+  const Char_t *patternz10 = "Nz10";
+  const Char_t *patternz100 = "Nz100";
+
+  if ((strstr(name,patternrphi100)) && (strstr(name,patternz100))) {
+    calibMode->SetAllTogether(i);
+    return kTRUE;
+  }
+  if ((strstr(name,patternrphi10)) && (strstr(name,patternz10))) {
+    calibMode->SetPerSuperModule(i);
+    return kTRUE;
+  }
+  if (strstr(name,patternz0)) {
+    calibMode->SetNz(i, 0);
+    return kTRUE;
+  }
+  if (strstr(name,patternz1)) {
+    calibMode->SetNz(i ,1);
+    return kTRUE;
+  }
+  if (strstr(name,patternz2)) {
+    calibMode->SetNz(i ,2);
+    return kTRUE;
+  }
+  if (strstr(name,patternz3)) {
+    calibMode->SetNz(i ,3);
+    return kTRUE;  
+  }
+  if (strstr(name,patternz4)) {
+    calibMode->SetNz(i ,4);
+    return kTRUE;
+  }
+  calibMode->SetNz(i ,0);
+  return kFALSE;
+}
+//____________________________________________________________________________________________________
+Int_t AliTRDcalibration::GetNumberOfGroupsPRF(const char* nametitle) const
+{
+  //
+  // Get numberofgroupsprf
+  //
+  
+  // Some patterns
+  const Char_t *pattern0 = "Ngp0";
+  const Char_t *pattern1 = "Ngp1";
+  const Char_t *pattern2 = "Ngp2";
+  const Char_t *pattern3 = "Ngp3";
+  const Char_t *pattern4 = "Ngp4";
+  const Char_t *pattern5 = "Ngp5";
+  const Char_t *pattern6 = "Ngp6";
+
+  // Nrphi mode
+  if (strstr(nametitle,pattern0)) {
+    return 0;
+  }
+  if (strstr(nametitle,pattern1)) {
+    return 1;
+  }
+  if (strstr(nametitle,pattern2)) {
+    return 2;
+  }
+  if (strstr(nametitle,pattern3)) {
+    return 3;
+  }
+  if (strstr(nametitle,pattern4)) {
+    return 4;
+  }
+  if (strstr(nametitle,pattern5)) {
+    return 5;
+  }
+  if (strstr(nametitle,pattern6)){
+    return 6;
+  }
+  else return -1;
+
+}
diff --git a/PWG1/TRD/AliTRDcalibration.h b/PWG1/TRD/AliTRDcalibration.h
new file mode 100644 (file)
index 0000000..0c24a2c
--- /dev/null
@@ -0,0 +1,151 @@
+#ifndef ALITRDCALIBRATION_H
+#define ALITRDCALIBRATION_H
+
+// macro for extremely simple analysis
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+//  TRD calibration class                                                    //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+#include "AliTRDrecoTask.h"
+
+class TList;
+class TObject;
+class TH1F;
+class TProfile2D;
+class TGraph;
+class TH2I;
+class TH2D;
+class TTree;
+class TObjArray;
+class AliTRDtrackV1;
+class AliTRDCalibraFillHisto;
+class AliTRDCalibraVector;
+class AliTRDCalibraMode;
+class AliTRDcluster;
+class AliTRDtrackInfo;
+
+class AliTRDcalibration : public AliTRDrecoTask 
+{
+public:
+
+  // Plots registered for this task
+  enum{
+    kNbTrack        =  0     // Nb tracks per event
+      ,kNbTracklet     =  1     // Nb of traklets per detector
+      ,kNbTimeBin      =  2     // Nb of clusters per timebin
+      ,kNbClusters     =  3     // Nb of clusters per tracklet
+      ,kPHSum          =  4     // All integrated PH
+      ,kCHSum          =  5     // All integrated CH
+      ,kPH2D           =  6     // PH2D
+      ,kCH2D           =  7     // CH2D
+      ,kPRF2D          =  8     // PRF2D 
+      ,kPH2DVector     =  9     // PH2D
+      ,kCH2DVector     =  10     // CH2D
+      ,kPRF2DVector    =  11     // PRF2D 
+      ,kLinearFitter   =  12    // For the one with the most stats 
+      ,kGainFactor     =  13    // Gain factor
+      ,kVdriftT0Factor   = 14   // VdriftT0 average pulse height
+      ,kVdriftLorentzAngleFactor = 15  // VdriftLorentzAngle
+      ,kPRFFactor = 16                 //PRF Factor
+      };
+  
+
+  AliTRDcalibration();
+  virtual ~AliTRDcalibration();
+  
+  virtual void    CreateOutputObjects();
+  virtual void    Exec(Option_t *option);
+  virtual void    Terminate(Option_t *);
+  virtual Bool_t  GetRefFigure(Int_t ifig);
+  virtual Bool_t  PostProcess();
+
+  Bool_t FillGraphIndex(const TObjArray *vectora, TGraph *graph) const;
+  Bool_t AddStatsPerDetector(const TH2I *ch);
+  Bool_t AddStatsPerDetector(const TProfile2D *ph, Int_t i);
+
+  Bool_t SetNrphiFromTObject(const char *name, Int_t i, AliTRDCalibraMode *calibMode) const;
+  Bool_t SetNzFromTObject(const char *name, Int_t i, AliTRDCalibraMode *calibMode) const;
+
+  Int_t  GetNumberOfGroupsPRF(const char* nametitle) const;
+  TH2I  *GetSumCH() const                                           { return fCHSum; };
+  TH2D  *GetSumDet() const                                          { return fDetSum;};
+  AliTRDCalibraVector  *GetSumDetVector() const                     { return fDetSumVector;};
+
+  
+
+  void SetHisto2d(Bool_t histo2d)                                   {fHisto2d=histo2d;};
+  void SetVector2d(Bool_t vector2d)                                 {fVector2d=vector2d;};
+  void SetVdriftLinear(Bool_t vdriftLinear)                         {fVdriftLinear = vdriftLinear;};
+  void SetLow(Int_t low)                                            {flow=low;};
+  void SetHigh(Int_t high)                                          {fhigh=high;};
+  void SetNz(Short_t nz, Int_t i)                                   {fNz[i]=nz;};
+  void SetNrphi(Short_t nrphi, Int_t i)                             {fNrphi[i]=nrphi;};
+  void SetFillZero(Bool_t fillZero)                                 {ffillZero =  fillZero;};
+  void SetNormalizeNbOfCluster(Bool_t normalizeNbOfCluster)         {fnormalizeNbOfCluster = normalizeNbOfCluster;};
+  void SetMaxCluster(Float_t maxcluster)                            {fmaxCluster =  maxcluster; }; 
+  void SetOfflineTracks()                                           {fOfflineTracks=kTRUE; fStandaloneTracks=kFALSE; };
+  void SetStandaloneTracks()                                        {fStandaloneTracks=kTRUE; fOfflineTracks=kFALSE; };
+  void SetCompressPerDetector(Bool_t compressPerDetector=kTRUE)     {fCompressPerDetector=compressPerDetector; };
+  void SetRunNumber(Int_t runNumber)                                {fRunNumber=runNumber; };
+  void SetNameDirectoryOutput(const char *nameDirectory)            {fkNameDirectory=nameDirectory; };
+  
+private:
+  AliTRDtrackInfo  *fTrackInfo;                  //track info
+
+  AliTRDtrackV1 *ftrdTrack;                      //trdtrack
+  AliTRDcluster *fcl;                            //cluster
+  
+  AliTRDCalibraFillHisto *fTRDCalibraFillHisto;  //! calibration analyse object
+  TH1F        *fNbTRDTrack;                      //! nb ESD tracks used
+  TH1F        *fNbTRDTrackOffline;               //! nb ESD tracks offline used
+  TH1F        *fNbTRDTrackStandalone;            //! nb ESD tracks standalone used
+  TH1F        *fNbTRDTracklet;                   //! nb tracklets used
+  TH1F        *fNbTRDTrackletOffline;            //! nb tracklets offline used
+  TH1F        *fNbTRDTrackletStandalone;         //! nb tracklets standalone used
+  TH1F        *fNbTimeBin;                       //! nb Time Bin
+  TH1F        *fNbTimeBinOffline;                //! nb Time Bin offline
+  TH1F        *fNbTimeBinStandalone;             //! nb Time Bin standalone
+  TH1F        *fNbClusters;                      //! nb Clusters
+  TH1F        *fNbClustersOffline;               //! nb Clusters offline
+  TH1F        *fNbClustersStandalone;            //! nb Clusters standalone
+
+
+  TProfile2D  *fPHSum;                           //! sum PH
+  TH2I        *fCHSum;                           //! sum CH
+  TH2D        *fDetSum;                          //! sum Det
+  AliTRDCalibraVector *fDetSumVector;            //! sum Det Vect
+  
+  Bool_t      fHisto2d;                          //! histo
+  Bool_t      fVector2d;                         //! vector
+  Bool_t      fVdriftLinear;                     //! vdrift Linear
+
+  Int_t       flow;                              //! lower limit nb of clusters
+  Int_t       fhigh;                             //! higher limit nb of clusters
+  Int_t       fNbTimeBins;                       //! number of timebins 
+  Bool_t      ffillZero;                         //! fill zero
+  Short_t     fNz[3];                            //! Nz mode 
+  Short_t     fNrphi[3];                         //! Nrphi mode
+  Bool_t      fnormalizeNbOfCluster;             //! normalize with number of clusters
+  Float_t     fmaxCluster;                       //! maxcluster (noise at the end)
+  Bool_t      fOfflineTracks;                    //! Offline refited tracks
+  Bool_t      fStandaloneTracks;                 //! Take only standalone tracks
+
+  Bool_t      fCompressPerDetector;              //! Compress per detector 
+
+  Int_t       fRunNumber;                        //! Run number
+  const char *fkNameDirectory;                   //! Name output directory fit parameters
+
+  TObjArray  *fGraph;                            //! array of graphs filled in PostProcess
+  Bool_t      fPostProcess;                      //Post process 
+
+  AliTRDcalibration(const AliTRDcalibration&); 
+  AliTRDcalibration& operator=(const AliTRDcalibration&); 
+
+  ClassDef(AliTRDcalibration, 1) // calibration task
+};
+#endif
+
diff --git a/PWG1/TRD/AliTRDcheckDET.cxx b/PWG1/TRD/AliTRDcheckDET.cxx
new file mode 100644 (file)
index 0000000..3b34d5d
--- /dev/null
@@ -0,0 +1,1210 @@
+////////////////////////////////////////////////////////////////////////////
+//                                                                        //
+//                                                                        //
+//  Basic checks for tracking and detector performance                    //
+//  
+//     For the moment (15.10.2009) the following checks are implemented    //
+//       - Number of clusters/track
+//       - Number of clusters/tracklet
+//       - Number of tracklets/track from different sources (Barrel, StandAlone)
+//       - Number of findable tracklets
+//       - Number of tracks per event and TRD sector
+//       - <PH>
+//       - Chi2 distribution for tracks
+//       - Charge distribution per cluster and tracklet
+//       - Number of events and tracks per trigger source 
+//       - Trigger purity
+//       - Track and Tracklet propagation status
+//
+//  Authors:                                                              //
+//    Anton Andronic <A.Andronic@gsi.de>                                  //
+//    Alexandru Bercuci <A.Bercuci@gsi.de>                                //
+//    Markus Fasel <M.Fasel@gsi.de>                                       //
+//                                                                        //
+////////////////////////////////////////////////////////////////////////////
+
+#include <TAxis.h>
+#include <TCanvas.h>
+#include <TFile.h>
+#include <TH1F.h>
+#include <TH1I.h>
+#include <TF1.h>
+#include <TGaxis.h>
+#include <TGraph.h>
+#include <TLegend.h>
+#include <TMath.h>
+#include <TMap.h>
+#include <TObjArray.h>
+#include <TObject.h>
+#include <TObjString.h>
+
+#include <TPad.h>
+#include <TProfile.h>
+#include <TProfile2D.h>
+#include <TROOT.h>
+
+#include "AliLog.h"
+#include "AliTRDcluster.h"
+#include "AliESDHeader.h"
+#include "AliESDRun.h"
+#include "AliESDtrack.h"
+#include "AliTRDgeometry.h"
+#include "AliTRDpadPlane.h"
+#include "AliTRDSimParam.h"
+#include "AliTRDseedV1.h"
+#include "AliTRDtrackV1.h"
+#include "AliTRDtrackerV1.h"
+#include "AliTRDReconstructor.h"
+#include "AliTrackReference.h"
+#include "AliTrackPointArray.h"
+#include "AliTracker.h"
+#include "TTreeStream.h"
+
+#include "info/AliTRDtrackInfo.h"
+#include "info/AliTRDeventInfo.h"
+#include "AliTRDcheckDET.h"
+
+#include <cstdio>
+#include <iostream>
+
+ClassImp(AliTRDcheckDET)
+
+//_______________________________________________________
+AliTRDcheckDET::AliTRDcheckDET():
+  AliTRDrecoTask("checkDET", "Basic TRD data checker")
+  ,fEventInfo(0x0)
+  ,fTriggerNames(0x0)
+  ,fReconstructor(0x0)
+  ,fGeo(0x0)
+{
+  //
+  // Default constructor
+  //
+  DefineInput(1,AliTRDeventInfo::Class());
+  fReconstructor = new AliTRDReconstructor;
+  fReconstructor->SetRecoParam(AliTRDrecoParam::GetLowFluxParam());
+  fGeo = new AliTRDgeometry;
+  InitFunctorList();
+}
+
+//_______________________________________________________
+AliTRDcheckDET::~AliTRDcheckDET(){
+  //
+  // Destructor
+  // 
+  if(fTriggerNames) delete fTriggerNames;
+  delete fReconstructor;
+  delete fGeo;
+}
+
+//_______________________________________________________
+void AliTRDcheckDET::ConnectInputData(Option_t *opt){
+  //
+  // Connect the Input data with the task
+  //
+  AliTRDrecoTask::ConnectInputData(opt);
+  fEventInfo = dynamic_cast<AliTRDeventInfo *>(GetInputData(1));
+}
+
+//_______________________________________________________
+void AliTRDcheckDET::CreateOutputObjects(){
+  //
+  // Create Output Objects
+  //
+  OpenFile(0,"RECREATE");
+  fContainer = Histos();
+  if(!fTriggerNames) fTriggerNames = new TMap();
+}
+
+//_______________________________________________________
+void AliTRDcheckDET::Exec(Option_t *opt){
+  //
+  // Execution function
+  // Filling TRD quality histos
+  //
+  if(!HasMCdata() && fEventInfo->GetEventHeader()->GetEventType() != 7) return;        // For real data we select only physical events
+  AliTRDrecoTask::Exec(opt);  
+  Int_t nTracks = 0;           // Count the number of tracks per event
+  Int_t triggermask = fEventInfo->GetEventHeader()->GetTriggerMask();
+  TString triggername =  fEventInfo->GetRunInfo()->GetFiredTriggerClasses(triggermask);
+  AliDebug(6, Form("Trigger cluster: %d, Trigger class: %s\n", triggermask, triggername.Data()));
+  dynamic_cast<TH1F *>(fContainer->UncheckedAt(kNeventsTrigger))->Fill(triggermask);
+  for(Int_t iti = 0; iti < fTracks->GetEntriesFast(); iti++){
+    if(!fTracks->UncheckedAt(iti)) continue;
+    AliTRDtrackInfo *fTrackInfo = dynamic_cast<AliTRDtrackInfo *>(fTracks->UncheckedAt(iti));
+    if(!fTrackInfo->GetTrack()) continue;
+    nTracks++;
+  }
+  if(nTracks){
+    dynamic_cast<TH1F *>(fContainer->UncheckedAt(kNeventsTriggerTracks))->Fill(triggermask);
+    dynamic_cast<TH1F *>(fContainer->UncheckedAt(kNtracksEvent))->Fill(nTracks);
+  }
+  if(triggermask <= 20 && !fTriggerNames->FindObject(Form("%d", triggermask))){
+    fTriggerNames->Add(new TObjString(Form("%d", triggermask)), new TObjString(triggername));
+    // also set the label for both histograms
+    TH1 *histo = dynamic_cast<TH1F *>(fContainer->UncheckedAt(kNeventsTriggerTracks));
+    histo->GetXaxis()->SetBinLabel(histo->FindBin(triggermask), triggername);
+    histo = dynamic_cast<TH1F *>(fContainer->UncheckedAt(kNeventsTrigger));
+    histo->GetXaxis()->SetBinLabel(histo->FindBin(triggermask), triggername);
+  }
+  PostData(0, fContainer);
+}
+
+
+//_______________________________________________________
+Bool_t AliTRDcheckDET::PostProcess(){
+  //
+  // Do Postprocessing (for the moment set the number of Reference histograms)
+  //
+  
+  TH1 * h = 0x0;
+  
+  // Calculate of the trigger clusters purity
+  h = dynamic_cast<TH1F *>(fContainer->FindObject("hEventsTrigger"));
+  TH1F *h1 = dynamic_cast<TH1F *>(fContainer->FindObject("hEventsTriggerTracks"));
+  h1->Divide(h);
+  Float_t purities[20], val = 0;
+  TString triggernames[20];
+  Int_t nTriggerClasses = 0;
+  for(Int_t ibin = 1; ibin <= h->GetNbinsX(); ibin++){
+    if((val = h1->GetBinContent(ibin))){
+      purities[nTriggerClasses] = val;
+      triggernames[nTriggerClasses] = h1->GetXaxis()->GetBinLabel(ibin);
+      nTriggerClasses++;
+    }
+  }
+  h = dynamic_cast<TH1F *>(fContainer->UncheckedAt(kTriggerPurity));
+  TAxis *ax = h->GetXaxis();
+  for(Int_t itrg = 0; itrg < nTriggerClasses; itrg++){
+    h->Fill(itrg, purities[itrg]);
+    ax->SetBinLabel(itrg+1, triggernames[itrg].Data());
+  }
+  ax->SetRangeUser(-0.5, nTriggerClasses+.5);
+  h->GetYaxis()->SetRangeUser(0,1);
+
+  // track status
+  h=dynamic_cast<TH1F*>(fContainer->At(kTrackStatus));
+  Float_t ok = h->GetBinContent(1);
+  Int_t nerr = h->GetNbinsX();
+  for(Int_t ierr=nerr; ierr--;){
+    h->SetBinContent(ierr+1, 1.e2*h->GetBinContent(ierr+1)/ok);
+  }
+  h->SetBinContent(1, 0.);
+
+  // tracklet status
+  TObjArray *arr = dynamic_cast<TObjArray*>(fContainer->UncheckedAt(kTrackletStatus));
+  for(Int_t ily = AliTRDgeometry::kNlayer; ily--;){
+    h=dynamic_cast<TH1F*>(arr->At(ily));
+    Float_t okB = h->GetBinContent(1);
+    Int_t nerrB = h->GetNbinsX();
+    for(Int_t ierr=nerrB; ierr--;){
+      h->SetBinContent(ierr+1, 1.e2*h->GetBinContent(ierr+1)/okB);
+    }
+    h->SetBinContent(1, 0.);
+  }
+
+  fNRefFigures = 18;
+
+  return kTRUE;
+}
+
+//_______________________________________________________
+Bool_t AliTRDcheckDET::GetRefFigure(Int_t ifig){
+  //
+  // Setting Reference Figures
+  //
+  gPad->SetLogy(0);
+  gPad->SetLogx(0);
+  TH1 *h = 0x0; TObjArray *arr=0x0;
+  TLegend *leg = 0x0;
+  Bool_t kFIRST(1);
+  switch(ifig){
+  case kNclustersTrack:
+    (h=(TH1F*)fContainer->FindObject("hNcls"))->Draw("pl");
+    PutTrendValue("NClustersTrack", h->GetMean());
+    PutTrendValue("NClustersTrackRMS", h->GetRMS());
+    return kTRUE;
+  case kNclustersTracklet:
+    (h =(TH1F*)fContainer->FindObject("hNclTls"))->Draw("pc");
+    PutTrendValue("NClustersTracklet", h->GetMean());
+    PutTrendValue("NClustersTrackletRMS", h->GetRMS());
+    return kTRUE;
+  case kNtrackletsTrack:
+    h=MakePlotNTracklets();
+    PutTrendValue("NTrackletsTrack", h->GetMean());
+    PutTrendValue("NTrackletsTrackRMS", h->GetRMS());
+    return kTRUE;
+  case kNtrackletsCross:
+    h = (TH1F*)fContainer->FindObject("hNtlsCross");
+    if(!MakeBarPlot(h, kRed)) break;
+    PutTrendValue("NTrackletsCross", h->GetMean());
+    PutTrendValue("NTrackletsCrossRMS", h->GetRMS());
+    return kTRUE;
+  case kNtrackletsFindable:
+    h = (TH1F*)fContainer->FindObject("hNtlsFindable");
+    if(!MakeBarPlot(h, kGreen)) break;
+    PutTrendValue("NTrackletsFindable", h->GetMean());
+    PutTrendValue("NTrackletsFindableRMS", h->GetRMS());
+    return kTRUE;
+  case kNtracksEvent:
+    (h = (TH1F*)fContainer->FindObject("hNtrks"))->Draw("pl");
+    PutTrendValue("NTracksEvent", h->GetMean());
+    PutTrendValue("NTracksEventRMS", h->GetRMS());
+    return kTRUE;
+  case kNtracksSector:
+    h = (TH1F*)fContainer->FindObject("hNtrksSector");
+    if(!MakeBarPlot(h, kGreen)) break;
+    PutTrendValue("NTracksSector", h->Integral()/h->GetNbinsX());
+    return kTRUE;
+  case kTrackStatus:
+    if(!(h=(TH1F *)fContainer->FindObject("hTrackStatus"))) break;
+    h->GetXaxis()->SetRangeUser(0.5, -1);
+    h->GetYaxis()->CenterTitle();
+    h->Draw("c");
+    PutTrendValue("TrackStatus", h->Integral());
+    gPad->SetLogy(0);
+    return kTRUE;
+  case kTrackletStatus:
+    if(!(arr = dynamic_cast<TObjArray*>(fContainer->At(kTrackletStatus)))) break;
+    leg = new TLegend(.68, .7, .98, .98);
+    leg->SetBorderSize(1);leg->SetFillColor(0);
+    leg->SetHeader("TRD layer");
+    for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
+      if(!(h=dynamic_cast<TH1F*>(arr->At(ily)))) continue;
+      if(kFIRST){
+        h->Draw("c");
+        h->GetXaxis()->SetRangeUser(0.5, -1);
+        h->GetYaxis()->CenterTitle();
+        kFIRST = kFALSE;
+      } else h->Draw("samec");
+      leg->AddEntry(h, Form("%d", ily), "l");
+      PutTrendValue(Form("TrackletStatus%d", ily), h->Integral());
+    }
+    leg->Draw();
+    gPad->SetLogy(0);
+    return kTRUE;
+  case kChi2:
+    MakePlotChi2();
+    return kTRUE;
+  case kPH:
+    MakePlotPulseHeight();
+    gPad->SetLogy(0);
+    return kTRUE;
+  case kChargeCluster:
+    (h = (TH1F*)fContainer->FindObject("hQcl"))->Draw("c");
+    gPad->SetLogy(1);
+    PutTrendValue("ChargeCluster", h->GetMaximumBin());
+    PutTrendValue("ChargeClusterRMS", h->GetRMS());
+    return kTRUE;
+  case kChargeTracklet:
+    (h=(TH1F*)fContainer->FindObject("hQtrklt"))->Draw("c");
+    PutTrendValue("ChargeTracklet", h->GetMaximumBin());
+    PutTrendValue("ChargeTrackletRMS", h->GetRMS());
+    return kTRUE;
+  case kNeventsTrigger:
+    ((TH1F*)fContainer->FindObject("hEventsTrigger"))->Draw("");
+    return kTRUE;
+  case kNeventsTriggerTracks:
+    ((TH1F*)fContainer->FindObject("hEventsTriggerTracks"))->Draw("");
+    return kTRUE;
+  case kTriggerPurity: 
+    if(!MakeBarPlot((TH1F*)fContainer->FindObject("hTriggerPurity"), kGreen)) break;
+    break;
+  default:
+    break;
+  }
+  AliInfo(Form("Reference plot [%d] missing result", ifig));
+  return kFALSE;
+}
+
+//_______________________________________________________
+TObjArray *AliTRDcheckDET::Histos(){
+  //
+  // Create QA histograms
+  //
+  if(fContainer) return fContainer;
+  
+  fContainer = new TObjArray(20);
+  //fContainer->SetOwner(kTRUE);
+
+  // Register Histograms
+  TH1 * h = NULL;
+  TAxis *ax = NULL;
+  if(!(h = (TH1F *)gROOT->FindObject("hNcls"))){
+    h = new TH1F("hNcls", "N_{clusters} / track", 181, -0.5, 180.5);
+    h->GetXaxis()->SetTitle("N_{clusters}");
+    h->GetYaxis()->SetTitle("Entries");
+  } else h->Reset();
+  fContainer->AddAt(h, kNclustersTrack);
+
+  if(!(h = (TH1F *)gROOT->FindObject("hNclTls"))){
+    h = new TH1F("hNclTls","N_{clusters} / tracklet", 51, -0.5, 50.5);
+    h->GetXaxis()->SetTitle("N_{clusters}");
+    h->GetYaxis()->SetTitle("Entries");
+  } else h->Reset();
+  fContainer->AddAt(h, kNclustersTracklet);
+
+  if(!(h = (TH1F *)gROOT->FindObject("hNtls"))){
+    h = new TH1F("hNtls", "N_{tracklets} / track", AliTRDgeometry::kNlayer, 0.5, 6.5);
+    h->GetXaxis()->SetTitle("N^{tracklet}");
+    h->GetYaxis()->SetTitle("freq. [%]");
+  } else h->Reset();
+  fContainer->AddAt(h, kNtrackletsTrack);
+
+  if(!(h = (TH1F *)gROOT->FindObject("htlsSTA"))){
+    h = new TH1F("hNtlsSTA", "N_{tracklets} / track (Stand Alone)", AliTRDgeometry::kNlayer, 0.5, 6.5);
+    h->GetXaxis()->SetTitle("N^{tracklet}");
+    h->GetYaxis()->SetTitle("freq. [%]");
+  }
+  fContainer->AddAt(h, kNtrackletsSTA);
+
+  if(!(h = (TH1F *)gROOT->FindObject("htlsBAR"))){
+    h = new TH1F("hNtlsBAR", "N_{tracklets} / track (Barrel)", AliTRDgeometry::kNlayer, 0.5, 6.5);
+    h->GetXaxis()->SetTitle("N^{tracklet}");
+    h->GetYaxis()->SetTitle("freq. [%]");
+  }
+  fContainer->AddAt(h, kNtrackletsBAR);
+
+  // 
+  if(!(h = (TH1F *)gROOT->FindObject("hNtlsCross"))){
+    h = new TH1F("hNtlsCross", "N_{tracklets}^{cross} / track", 7, -0.5, 6.5);
+    h->GetXaxis()->SetTitle("n_{row cross}");
+    h->GetYaxis()->SetTitle("freq. [%]");
+  } else h->Reset();
+  fContainer->AddAt(h, kNtrackletsCross);
+
+  if(!(h = (TH1F *)gROOT->FindObject("hNtlsFindable"))){
+    h = new TH1F("hNtlsFindable", "Found/Findable Tracklets" , 101, -0.005, 1.005);
+    h->GetXaxis()->SetTitle("r [a.u]");
+    h->GetYaxis()->SetTitle("Entries");
+  } else h->Reset();
+  fContainer->AddAt(h, kNtrackletsFindable);
+
+  if(!(h = (TH1F *)gROOT->FindObject("hNtrks"))){
+    h = new TH1F("hNtrks", "N_{tracks} / event", 100, 0, 100);
+    h->GetXaxis()->SetTitle("N_{tracks}");
+    h->GetYaxis()->SetTitle("Entries");
+  } else h->Reset();
+  fContainer->AddAt(h, kNtracksEvent);
+
+  if(!(h = (TH1F *)gROOT->FindObject("hNtrksSector"))){
+    h = new TH1F("hNtrksSector", "N_{tracks} / sector", AliTRDgeometry::kNsector, -0.5, 17.5);
+    h->GetXaxis()->SetTitle("sector");
+    h->GetYaxis()->SetTitle("freq. [%]");
+  } else h->Reset();
+  fContainer->AddAt(h, kNtracksSector);
+
+  if(!(h = (TH1F*)gROOT->FindObject("hTrackStatus"))){
+    const Int_t nerr = 7;
+    h = new TH1F("hTrackStatus", "Track Status", nerr, -0.5, nerr-0.5);
+    const Char_t *label[nerr] = {"OK", "PROL", "PROP", "AJST", "SNP", "TINI", "UPDT"};
+    ax = h->GetXaxis();
+    for(Int_t ierr=nerr; ierr--;) ax->SetBinLabel(ierr+1, label[ierr]);
+    h->SetYTitle("Relative Error to Good [%]");
+  }
+  fContainer->AddAt(h, kTrackStatus);
+
+  TObjArray *arr = new TObjArray(AliTRDgeometry::kNlayer);
+  arr->SetOwner(kTRUE);  arr->SetName("TrackletStatus");
+  fContainer->AddAt(arr, kTrackletStatus);
+  for(Int_t ily=AliTRDgeometry::kNlayer; ily--;){
+    if(!(h = (TH1F *)gROOT->FindObject(Form("hTrackletStatus%d", ily)))){
+      const Int_t nerr = 8;
+      h = new TH1F(Form("hTrackletStatus%d", ily), "Tracklet status", nerr, -0.5, nerr-0.5);
+      h->SetLineColor(ily+1);
+      const Char_t *label[nerr] = {"OK", "Geom", "Bound", "NoCl", "NoAttach", "NoClTr", "NoFit", "Chi2"};
+      ax = h->GetXaxis();
+      for(Int_t ierr=nerr; ierr--;) ax->SetBinLabel(ierr+1, label[ierr]);
+      h->SetYTitle("Relative Error to Good [%]");
+    } else h->Reset();
+    arr->AddAt(h, ily);
+  }
+
+  // <PH> histos
+  arr = new TObjArray(2);
+  arr->SetOwner(kTRUE);  arr->SetName("<PH>");
+  fContainer->AddAt(arr, kPH);
+  if(!(h = (TH1F *)gROOT->FindObject("hPHt"))){
+    h = new TProfile("hPHt", "<PH>", 31, -0.5, 30.5);
+    h->GetXaxis()->SetTitle("Time / 100ns");
+    h->GetYaxis()->SetTitle("<PH> [a.u]");
+  } else h->Reset();
+  arr->AddAt(h, 0);
+  if(!(h = (TH1F *)gROOT->FindObject("hPHx")))
+    h = new TProfile("hPHx", "<PH>", 31, -0.08, 4.88);
+  else h->Reset();
+  arr->AddAt(h, 1);
+
+  // Chi2 histos
+  if(!(h = (TH2S*)gROOT->FindObject("hChi2"))){
+    h = new TH2S("hChi2", "#chi^{2} per track", AliTRDgeometry::kNlayer, .5, AliTRDgeometry::kNlayer+.5, 100, 0, 50);
+    h->SetXTitle("ndf");
+    h->SetYTitle("#chi^{2}/ndf");
+    h->SetZTitle("entries");
+  } else h->Reset();
+  fContainer->AddAt(h, kChi2);
+
+  if(!(h = (TH1F *)gROOT->FindObject("hQcl"))){
+    h = new TH1F("hQcl", "Q_{cluster}", 200, 0, 1200);
+    h->GetXaxis()->SetTitle("Q_{cluster} [a.u.]");
+    h->GetYaxis()->SetTitle("Entries");
+  }else h->Reset();
+  fContainer->AddAt(h, kChargeCluster);
+
+  if(!(h = (TH1F *)gROOT->FindObject("hQtrklt"))){
+    h = new TH1F("hQtrklt", "Q_{tracklet}", 6000, 0, 6000);
+    h->GetXaxis()->SetTitle("Q_{tracklet} [a.u.]");
+    h->GetYaxis()->SetTitle("Entries");
+  }else h->Reset();
+  fContainer->AddAt(h, kChargeTracklet);
+
+
+  if(!(h = (TH1F *)gROOT->FindObject("hEventsTrigger")))
+    h = new TH1F("hEventsTrigger", "Trigger Class", 100, 0, 100);
+  else h->Reset();
+  fContainer->AddAt(h, kNeventsTrigger);
+
+  if(!(h = (TH1F *)gROOT->FindObject("hEventsTriggerTracks")))
+    h = new TH1F("hEventsTriggerTracks", "Trigger Class (Tracks)", 100, 0, 100);
+  else h->Reset();
+  fContainer->AddAt(h, kNeventsTriggerTracks);
+
+  if(!(h = (TH1F *)gROOT->FindObject("hTriggerPurity"))){
+    h = new TH1F("hTriggerPurity", "Trigger Purity", 10, -0.5, 9.5);
+    h->GetXaxis()->SetTitle("Trigger Cluster");
+    h->GetYaxis()->SetTitle("freq.");
+  } else h->Reset();
+  fContainer->AddAt(h, kTriggerPurity);
+
+  return fContainer;
+}
+
+/*
+* Plotting Functions
+*/
+
+//_______________________________________________________
+TH1 *AliTRDcheckDET::PlotTrackStatus(const AliTRDtrackV1 *track)
+{
+//
+// Plot the track propagation status. The following errors are defined (see AliTRDtrackV1::ETRDtrackError)
+//   PROL - track prolongation failure
+//   PROP - track propagation failure
+//   AJST - crossing sectors failure
+//   SNP  - too large bending
+//   TINI - tracklet initialization failure
+//   UPDT - track position/covariance update failure 
+//
+// Performance plot looks as below:
+//Begin_Html
+//<img src="TRD/trackStatus.gif">
+//End_Html
+//
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TH1 *h = 0x0;
+  if(!(h = dynamic_cast<TH1F *>(fContainer->At(kTrackStatus)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  h->Fill(fkTrack->GetStatusTRD());
+  return h;
+}
+
+//_______________________________________________________
+TH1 *AliTRDcheckDET::PlotTrackletStatus(const AliTRDtrackV1 *track)
+{
+//
+// Plot the tracklet propagation status. The following errors are defined for tracklet (see AliTRDtrackV1::ETRDlayerError)
+//   Geom   - 
+//   Bound  - tracklet too close to chamber walls
+//   NoCl   - no clusters in the track roads
+//   NoAttach - fail to attach clusters
+//   NoClTr - fail to use clusters for fit
+//   NoFit  - tracklet fit failled
+//   Chi2   - chi2 tracklet-track over threshold
+//
+// Performance plot looks as below:
+//Begin_Html
+//<img src="TRD/trackletStatus.gif">
+//End_Html
+//
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TObjArray *arr =0x0;
+  if(!(arr = dynamic_cast<TObjArray*>(fContainer->At(kTrackletStatus)))){
+    AliWarning("Histograms not defined.");
+    return 0x0;
+  }
+
+  TH1 *h = 0x0;
+  for(Int_t ily=AliTRDgeometry::kNlayer; ily--;){
+    if(!(h = dynamic_cast<TH1F*>(arr->At(ily)))){
+      AliWarning(Form("Missing histo for layer %d.", ily));
+      continue;
+    }
+    h->Fill(fkTrack->GetStatusTRD(ily));
+  }
+  return h;
+}
+
+//_______________________________________________________
+TH1 *AliTRDcheckDET::PlotNClustersTracklet(const AliTRDtrackV1 *track){
+  //
+  // Plot the mean number of clusters per tracklet
+  //
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TH1 *h = 0x0;
+  if(!(h = dynamic_cast<TH1F *>(fContainer->At(kNclustersTracklet)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  AliTRDseedV1 *tracklet = 0x0;
+  for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){
+    if(!(tracklet = fkTrack->GetTracklet(itl)) || !tracklet->IsOK()) continue;
+    h->Fill(tracklet->GetN2());
+  }
+  return h;
+}
+
+//_______________________________________________________
+TH1 *AliTRDcheckDET::PlotNClustersTrack(const AliTRDtrackV1 *track){
+  //
+  // Plot the number of clusters in one track
+  //
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TH1 *h = 0x0;
+  if(!(h = dynamic_cast<TH1F *>(fContainer->At(kNclustersTrack)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  
+  Int_t nclusters = 0;
+  AliTRDseedV1 *tracklet = 0x0;
+  for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){
+    if(!(tracklet = fkTrack->GetTracklet(itl)) || !tracklet->IsOK()) continue;
+    nclusters += tracklet->GetN();
+    if(DebugLevel() > 2){
+      Int_t crossing = Int_t(tracklet->IsRowCross());
+      Int_t detector = tracklet->GetDetector();
+      Float_t theta = TMath::ATan(tracklet->GetZref(1));
+      Float_t phi = TMath::ATan(tracklet->GetYref(1));
+      Float_t momentum = 0.;
+      Int_t pdg = 0;
+      Int_t kinkIndex = fkESD ? fkESD->GetKinkIndex() : 0;
+      UShort_t nclsTPC = fkESD ? fkESD->GetTPCncls() : 0;
+      if(fkMC){
+        if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P();
+        pdg = fkMC->GetPDG();
+      }
+      (*DebugStream()) << "NClustersTrack"
+        << "Detector="  << detector
+        << "crossing="  << crossing
+        << "momentum=" << momentum
+        << "pdg="                              << pdg
+        << "theta="                    << theta
+        << "phi="                              << phi
+        << "kinkIndex="        << kinkIndex
+        << "TPCncls="          << nclsTPC
+        << "nclusters=" << nclusters
+        << "\n";
+    }
+  }
+  h->Fill(nclusters);
+  return h;
+}
+
+
+//_______________________________________________________
+TH1 *AliTRDcheckDET::PlotNTrackletsTrack(const AliTRDtrackV1 *track){
+  //
+  // Plot the number of tracklets
+  //
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TH1 *h = 0x0, *hMethod = 0x0;
+  if(!(h = dynamic_cast<TH1F *>(fContainer->At(kNtrackletsTrack)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  Int_t nTracklets = fkTrack->GetNumberOfTracklets();
+  h->Fill(nTracklets);
+  if(!fkESD) return h;
+  Int_t status = fkESD->GetStatus();
+/*  printf("in/out/refit/pid: TRD[%d|%d|%d|%d]\n", status &AliESDtrack::kTRDin ? 1 : 0, status &AliESDtrack::kTRDout ? 1 : 0, status &AliESDtrack::kTRDrefit ? 1 : 0, status &AliESDtrack::kTRDpid ? 1 : 0);*/
+  if((status & AliESDtrack::kTRDin) != 0){
+    // Full BarrelTrack
+    if(!(hMethod = dynamic_cast<TH1F *>(fContainer->At(kNtrackletsBAR))))
+      AliWarning("Method: Barrel.  Histogram not processed!");
+  } else {
+    // Stand alone Track
+    if(!(hMethod = dynamic_cast<TH1F *>(fContainer->At(kNtrackletsSTA))))
+      AliWarning("Method: StandAlone.  Histogram not processed!");
+  }
+  hMethod->Fill(nTracklets);
+
+  if(DebugLevel() > 3){
+    if(nTracklets == 1){
+      // If we have one Tracklet, check in which layer this happens
+      Int_t layer = -1;
+      AliTRDseedV1 *tracklet = 0x0;
+      for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){
+        if((tracklet = fkTrack->GetTracklet(il)) && tracklet->IsOK()){layer =  il; break;}
+      }
+      (*DebugStream()) << "NTrackletsTrack"
+        << "Layer=" << layer
+        << "\n";
+    }
+  }
+  return h;
+}
+
+
+//_______________________________________________________
+TH1 *AliTRDcheckDET::PlotNTrackletsRowCross(const AliTRDtrackV1 *track){
+  //
+  // Plot the number of tracklets
+  //
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TH1 *h = 0x0;
+  if(!(h = dynamic_cast<TH1F *>(fContainer->At(kNtrackletsCross)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+
+  Int_t ncross = 0;
+  AliTRDseedV1 *tracklet = 0x0;
+  for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){
+    if(!(tracklet = fkTrack->GetTracklet(il)) || !tracklet->IsOK()) continue;
+
+    if(tracklet->IsRowCross()) ncross++;
+  }
+  h->Fill(ncross);
+  return h;
+}
+
+//_______________________________________________________
+TH1 *AliTRDcheckDET::PlotFindableTracklets(const AliTRDtrackV1 *track){
+  //
+  // Plots the ratio of number of tracklets vs.
+  // number of findable tracklets
+  //
+  // Findable tracklets are defined as track prolongation
+  // to layer i does not hit the dead area +- epsilon
+  //
+  // In order to check whether tracklet hist active area in Layer i, 
+  // the track is refitted and the fitted position + an uncertainty 
+  // range is compared to the chamber border (also with a different
+  // uncertainty)
+  //
+  // For the track fit two cases are distinguished:
+  // If the track is a stand alone track (defined by the status bit 
+  // encoding, then the track is fitted with the tilted Rieman model
+  // Otherwise the track is fitted with the Kalman fitter in two steps:
+  // Since the track parameters are give at the outer point, we first 
+  // fit in direction inwards. Afterwards we fit again in direction outwards
+  // to extrapolate the track to layers which are not reached by the track
+  // For the Kalman model, the radial track points have to be shifted by
+  // a distance epsilon in the direction that we want to fit
+  //
+  const Float_t epsilon = 0.01;   // dead area tolerance
+  const Float_t epsilonR = 1;    // shift in radial direction of the anode wire position (Kalman filter only)
+  const Float_t deltaY = 0.7;    // Tolerance in the track position in y-direction
+  const Float_t deltaZ = 7.0;    // Tolerance in the track position in z-direction (Padlength)
+  Double_t xAnode[AliTRDgeometry::kNlayer] = {300.2, 312.8, 325.4, 338.0, 350.6, 363.2}; // Take the default X0
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TH1 *h = 0x0;
+  if(!(h = dynamic_cast<TH1F *>(fContainer->At(kNtrackletsFindable)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  Int_t nFound = 0, nFindable = 0;
+  Int_t stack = -1;
+  Double_t ymin = 0., ymax = 0., zmin = 0., zmax = 0.;
+  Double_t y = 0., z = 0.;
+  AliTRDseedV1 *tracklet = 0x0;
+  AliTRDpadPlane *pp;  
+  for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){
+    if((tracklet = fkTrack->GetTracklet(il)) && tracklet->IsOK()){
+      tracklet->SetReconstructor(fReconstructor);
+      nFound++;
+    }
+  }
+  // 2 Different cases:
+  // 1st stand alone: here we cannot propagate, but be can do a Tilted Rieman Fit
+  // 2nd barrel track: here we propagate the track to the layers
+  AliTrackPoint points[6];
+  Float_t xyz[3];
+  memset(xyz, 0, sizeof(Float_t) * 3);
+  if(((fkESD->GetStatus() & AliESDtrack::kTRDout) > 0) && !((fkESD->GetStatus() & AliESDtrack::kTRDin) > 0)){
+    // stand alone track
+    for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){
+      xyz[0] = xAnode[il];
+      points[il].SetXYZ(xyz);
+    }
+    AliTRDtrackerV1::FitRiemanTilt(const_cast<AliTRDtrackV1 *>(fkTrack), 0x0, kTRUE, 6, points);
+  } else {
+    // barrel track
+    //
+    // 2 Steps:
+    // -> Kalman inwards
+    // -> Kalman outwards
+    AliTRDtrackV1 copyTrack(*fkTrack);  // Do Kalman on a (non-constant) copy of the track
+    AliTrackPoint pointsInward[6], pointsOutward[6];
+    for(Int_t il = AliTRDgeometry::kNlayer; il--;){
+      // In order to avoid complications in the Kalman filter if the track points have the same radial
+      // position like the tracklets, we have to shift the radial postion of the anode wire by epsilon
+      // in the direction we want to go
+      // The track points have to be in reverse order for the Kalman Filter inwards
+      xyz[0] = xAnode[AliTRDgeometry::kNlayer - il - 1] - epsilonR;
+      pointsInward[il].SetXYZ(xyz);
+      xyz[0] = xAnode[il] + epsilonR;
+      pointsOutward[il].SetXYZ(xyz);
+    }
+    /*for(Int_t ipt = 0; ipt < AliTRDgeometry::kNlayer; ipt++)
+      printf("%d. X = %f\n", ipt, points[ipt].GetX());*/
+    // Kalman inwards
+    AliTRDtrackerV1::FitKalman(&copyTrack, 0x0, kFALSE, 6, pointsInward);
+    memcpy(points, pointsInward, sizeof(AliTrackPoint) * 6); // Preliminary store the inward results in the Array points
+    // Kalman outwards
+    AliTRDtrackerV1::FitKalman(&copyTrack, 0x0, kTRUE, 6, pointsInward);
+    memcpy(points, pointsOutward, sizeof(AliTrackPoint) * AliTRDgeometry::kNlayer);
+  }
+  for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){
+    y = points[il].GetY();
+    z = points[il].GetZ();
+    if((stack = fGeo->GetStack(z, il)) < 0) continue; // Not findable
+    pp = fGeo->GetPadPlane(il, stack);
+    ymin = pp->GetCol0() + epsilon;
+    ymax = pp->GetColEnd() - epsilon; 
+    zmin = pp->GetRowEnd() + epsilon; 
+    zmax = pp->GetRow0() - epsilon;
+    // ignore y-crossing (material)
+    if((z + deltaZ > zmin && z - deltaZ < zmax) && (y + deltaY > ymin && y - deltaY < ymax)) nFindable++;
+      if(DebugLevel() > 3){
+        Double_t posTracklet[2] = {tracklet ? tracklet->GetYfit(0) : 0, tracklet ? tracklet->GetZfit(0) : 0};
+        Int_t hasTracklet = tracklet ? 1 : 0;
+        (*DebugStream())   << "FindableTracklets"
+          << "layer="     << il
+          << "ytracklet=" << posTracklet[0]
+          << "ytrack="    << y
+          << "ztracklet=" << posTracklet[1]
+          << "ztrack="    << z
+          << "tracklet="  << hasTracklet
+          << "\n";
+      }
+  }
+  
+  h->Fill(nFindable > 0 ? TMath::Min(nFound/static_cast<Double_t>(nFindable), 1.) : 1);
+  AliDebug(2, Form("Findable[Found]: %d[%d|%f]", nFindable, nFound, nFound/static_cast<Float_t>(nFindable > 0 ? nFindable : 1)));
+  return h;
+}
+
+
+//_______________________________________________________
+TH1 *AliTRDcheckDET::PlotChi2(const AliTRDtrackV1 *track){
+  //
+  // Plot the chi2 of the track
+  //
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TH1 *h = 0x0;
+  if(!(h = dynamic_cast<TH2S*>(fContainer->At(kChi2)))) {
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  Int_t n = fkTrack->GetNumberOfTracklets();
+  if(!n) return 0x0;
+
+  h->Fill(n, fkTrack->GetChi2()/n);
+  return h;
+}
+
+
+//_______________________________________________________
+TH1 *AliTRDcheckDET::PlotPHt(const AliTRDtrackV1 *track){
+  //
+  // Plot the average pulse height
+  //
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TProfile *h = 0x0;
+  if(!(h = dynamic_cast<TProfile *>(((TObjArray*)(fContainer->At(kPH)))->At(0)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  AliTRDseedV1 *tracklet = 0x0;
+  AliTRDcluster *c = 0x0;
+  for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){
+    if(!(tracklet = fkTrack->GetTracklet(itl)) || !tracklet->IsOK())continue;
+    Int_t crossing = Int_t(tracklet->IsRowCross());
+    Int_t detector = tracklet->GetDetector();
+    tracklet->ResetClusterIter();
+    while((c = tracklet->NextCluster())){
+      if(!c->IsInChamber()) continue;
+      Int_t localtime        = c->GetLocalTimeBin();
+      Double_t absoluteCharge = TMath::Abs(c->GetQ());
+      h->Fill(localtime, absoluteCharge);
+      if(DebugLevel() > 3){
+        Double_t distance[2];
+        GetDistanceToTracklet(distance, tracklet, c);
+        Float_t theta = TMath::ATan(tracklet->GetZref(1));
+        Float_t phi = TMath::ATan(tracklet->GetYref(1));
+        Float_t momentum = 0.;
+        Int_t pdg = 0;
+        Int_t kinkIndex = fkESD ? fkESD->GetKinkIndex() : 0;
+        UShort_t TPCncls = fkESD ? fkESD->GetTPCncls() : 0;
+        if(fkMC){
+          if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P();
+          pdg = fkMC->GetPDG();
+        }
+        (*DebugStream()) << "PHt"
+          << "Detector="       << detector
+          << "crossing="       << crossing
+          << "Timebin="                << localtime
+          << "Charge="         << absoluteCharge
+          << "momentum="       << momentum
+          << "pdg="                            << pdg
+          << "theta="                  << theta
+          << "phi="                            << phi
+          << "kinkIndex="      << kinkIndex
+          << "TPCncls="                << TPCncls
+          << "dy="        << distance[0]
+          << "dz="        << distance[1]
+          << "c.="        << c
+          << "\n";
+      }
+    }
+  }
+  return h;
+}
+
+//_______________________________________________________
+TH1 *AliTRDcheckDET::PlotPHx(const AliTRDtrackV1 *track){
+  //
+  // Plots the average pulse height vs the distance from the anode wire
+  // (plus const anode wire offset)
+  //
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TProfile *h = 0x0;
+  if(!(h = dynamic_cast<TProfile *>(((TObjArray*)(fContainer->At(kPH)))->At(1)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  Float_t offset = .5*AliTRDgeometry::CamHght();
+  AliTRDseedV1 *tracklet = 0x0;
+  AliTRDcluster *c = 0x0;
+  Double_t distance = 0;
+  Double_t x, y;
+  for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){
+    if(!(tracklet = fkTrack->GetTracklet(itl)) || !(tracklet->IsOK())) continue;
+    tracklet->ResetClusterIter();
+    while((c = tracklet->NextCluster())){
+      if(!c->IsInChamber()) continue;
+      x = c->GetX()-AliTRDcluster::GetXcorr(c->GetLocalTimeBin());
+      y = c->GetY()-AliTRDcluster::GetYcorr(AliTRDgeometry::GetLayer(c->GetDetector()), c->GetCenter());
+
+      distance = tracklet->GetX0() - (c->GetX() + 0.3) + offset;
+      h->Fill(distance, TMath::Abs(c->GetQ()));
+    }
+  }  
+  return h;
+}
+
+//_______________________________________________________
+TH1 *AliTRDcheckDET::PlotChargeCluster(const AliTRDtrackV1 *track){
+  //
+  // Plot the cluster charge
+  //
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TH1 *h = 0x0;
+  if(!(h = dynamic_cast<TH1F *>(fContainer->At(kChargeCluster)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  AliTRDseedV1 *tracklet = 0x0;
+  AliTRDcluster *c = 0x0;
+  for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){
+    if(!(tracklet = fkTrack->GetTracklet(itl)) || !tracklet->IsOK())continue;
+    for(Int_t itime = 0; itime < AliTRDtrackerV1::GetNTimeBins(); itime++){
+      if(!(c = tracklet->GetClusters(itime))) continue;
+      h->Fill(c->GetQ());
+    }
+  }
+  return h;
+}
+
+//_______________________________________________________
+TH1 *AliTRDcheckDET::PlotChargeTracklet(const AliTRDtrackV1 *track){
+  //
+  // Plot the charge deposit per chamber
+  //
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TH1 *h = 0x0;
+  if(!(h = dynamic_cast<TH1F *>(fContainer->At(kChargeTracklet)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  AliTRDseedV1 *tracklet = 0x0;
+  AliTRDcluster *c = 0x0;
+  Double_t qTot = 0;
+  Int_t nTracklets =fkTrack->GetNumberOfTracklets();
+  for(Int_t itl = 0x0; itl < AliTRDgeometry::kNlayer; itl++){
+    if(!(tracklet = fkTrack->GetTracklet(itl)) || !tracklet->IsOK()) continue;
+    qTot = 0.;
+    for(Int_t ic = AliTRDseedV1::kNclusters; ic--;){
+      if(!(c = tracklet->GetClusters(ic))) continue;
+      qTot += TMath::Abs(c->GetQ());
+    }
+    h->Fill(qTot);
+    if(DebugLevel() > 3){
+      Int_t crossing = (Int_t)tracklet->IsRowCross();
+      Int_t detector = tracklet->GetDetector();
+      Float_t theta = TMath::ATan(tracklet->GetZfit(1));
+      Float_t phi = TMath::ATan(tracklet->GetYfit(1));
+      Float_t momentum = 0.;
+      Int_t pdg = 0;
+      Int_t kinkIndex = fkESD ? fkESD->GetKinkIndex() : 0;
+      UShort_t nclsTPC = fkESD ? fkESD->GetTPCncls() : 0;
+      if(fkMC){
+             if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P();
+        pdg = fkMC->GetPDG();
+      }
+      (*DebugStream()) << "ChargeTracklet"
+        << "Detector="  << detector
+        << "crossing="  << crossing
+        << "momentum=" << momentum
+        << "nTracklets="<< nTracklets
+        << "pdg="                              << pdg
+        << "theta="                    << theta
+        << "phi="                              << phi
+        << "kinkIndex="        << kinkIndex
+        << "TPCncls="          << nclsTPC
+        << "QT="        << qTot
+        << "\n";
+    }
+  }
+  return h;
+}
+
+//_______________________________________________________
+TH1 *AliTRDcheckDET::PlotNTracksSector(const AliTRDtrackV1 *track){
+  //
+  // Plot the number of tracks per Sector
+  //
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TH1 *h = 0x0;
+  if(!(h = dynamic_cast<TH1F *>(fContainer->At(kNtracksSector)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+
+  // TODO we should compare with
+  // sector = Int_t(track->GetAlpha() / AliTRDgeometry::GetAlpha());
+
+  AliTRDseedV1 *tracklet = 0x0;
+  Int_t sector = -1;
+  for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){
+    if(!(tracklet = fkTrack->GetTracklet(itl)) || !tracklet->IsOK()) continue;
+    sector = static_cast<Int_t>(tracklet->GetDetector()/AliTRDgeometry::kNdets);
+    break;
+  }
+  h->Fill(sector);
+  return h;
+}
+
+
+//________________________________________________________
+void AliTRDcheckDET::SetRecoParam(AliTRDrecoParam *r)
+{
+
+  fReconstructor->SetRecoParam(r);
+}
+
+//________________________________________________________
+void AliTRDcheckDET::GetDistanceToTracklet(Double_t *dist, AliTRDseedV1 * const tracklet, AliTRDcluster * const c)
+{
+  Float_t x = c->GetX();
+  dist[0] = c->GetY() - tracklet->GetYat(x);
+  dist[1] = c->GetZ() - tracklet->GetZat(x);
+}
+
+
+//_______________________________________________________
+TH1* AliTRDcheckDET::MakePlotChi2()
+{
+// Plot chi2/track normalized to number of degree of freedom 
+// (tracklets) and compare with the theoretical distribution.
+// 
+// Alex Bercuci <A.Bercuci@gsi.de>
+
+  TH2S *h2 = (TH2S*)fContainer->At(kChi2);
+  TF1 f("fChi2", "[0]*pow(x, [1]-1)*exp(-0.5*x)", 0., 50.);
+  TLegend *leg = new TLegend(.7,.7,.95,.95);
+  leg->SetBorderSize(1); leg->SetHeader("Tracklets per Track");
+  TH1D *h1 = 0x0;
+  Bool_t kFIRST = kTRUE;
+  for(Int_t il=1; il<=h2->GetNbinsX(); il++){
+    h1 = h2->ProjectionY(Form("pyChi2%d", il), il, il);
+    if(h1->Integral()<50) continue;
+    h1->Scale(1./h1->Integral());
+    h1->SetMarkerStyle(7);h1->SetMarkerColor(il);
+    h1->SetLineColor(il);h1->SetLineStyle(2);
+    f.SetParameter(1, .5*il);f.SetLineColor(il);
+    h1->Fit(&f, "QW+", kFIRST ? "pc": "pcsame");
+    leg->AddEntry(h1, Form("%d", il), "l");
+    if(kFIRST){
+      h1->GetXaxis()->SetRangeUser(0., 25.);
+    }
+    kFIRST = kFALSE;
+  }
+  leg->Draw();
+  gPad->SetLogy();
+  return h1;
+}
+
+
+//________________________________________________________
+TH1* AliTRDcheckDET::MakePlotNTracklets(){
+  //
+  // Make nice bar plot of the number of tracklets in each method
+  //
+  TH1F *hBAR = (TH1F *)fContainer->FindObject("hNtlsBAR");
+  TH1F *hSTA = (TH1F *)fContainer->FindObject("hNtlsSTA");
+  TH1F *hCON = (TH1F *)fContainer->FindObject("hNtls");
+  TLegend *leg = new TLegend(0.13, 0.75, 0.39, 0.89);
+  leg->SetBorderSize(1);
+  leg->SetFillColor(0);
+
+  Float_t scale = hCON->Integral();
+  hCON->Scale(100./scale);
+  hCON->SetFillColor(kRed);hCON->SetLineColor(kRed);
+  hCON->SetBarWidth(0.2);
+  hCON->SetBarOffset(0.6);
+  hCON->SetStats(kFALSE);
+  hCON->GetYaxis()->SetRangeUser(0.,40.);
+  hCON->GetYaxis()->SetTitleOffset(1.2);
+  hCON->Draw("bar1"); leg->AddEntry(hCON, "Total", "f");
+  hCON->SetMaximum(55.);
+
+  hBAR->Scale(100./scale);
+  hBAR->SetFillColor(kGreen);hBAR->SetLineColor(kGreen);
+  hBAR->SetBarWidth(0.2);
+  hBAR->SetBarOffset(0.2);
+  hBAR->SetTitle("");
+  hBAR->SetStats(kFALSE);
+  hBAR->GetYaxis()->SetRangeUser(0.,40.);
+  hBAR->GetYaxis()->SetTitleOffset(1.2);
+  hBAR->Draw("bar1same"); leg->AddEntry(hBAR, "Barrel", "f");
+
+  hSTA->Scale(100./scale);
+  hSTA->SetFillColor(kBlue);hSTA->SetLineColor(kBlue);
+  hSTA->SetBarWidth(0.2);
+  hSTA->SetBarOffset(0.4);
+  hSTA->SetTitle("");
+  hSTA->SetStats(kFALSE);
+  hSTA->GetYaxis()->SetRangeUser(0.,40.);
+  hSTA->GetYaxis()->SetTitleOffset(1.2);
+  hSTA->Draw("bar1same"); leg->AddEntry(hSTA, "Stand Alone", "f");
+  leg->Draw();
+  gPad->Update();
+  return hCON;
+}
+
+//________________________________________________________
+TH1* AliTRDcheckDET::MakePlotPulseHeight(){
+  //
+  // Create Plot of the Pluse Height Spectrum
+  //
+  TH1 *h, *h1, *h2;
+  TObjArray *arr = (TObjArray*)fContainer->FindObject("<PH>");
+  h = (TH1F*)arr->At(0);
+  h->SetMarkerStyle(24);
+  h->SetMarkerColor(kBlack);
+  h->SetLineColor(kBlack);
+  h->Draw("e1");
+//   copy the second histogram in a new one with the same x-dimension as the phs with respect to time
+  h1 = (TH1F *)arr->At(1);
+  h2 = new TH1F("hphs1","Average PH", 31, -0.5, 30.5);
+  for(Int_t ibin = h1->GetXaxis()->GetFirst(); ibin < h1->GetNbinsX(); ibin++) 
+    h2->SetBinContent(ibin, h1->GetBinContent(ibin));
+  h2->SetMarkerStyle(22);
+  h2->SetMarkerColor(kBlue);
+  h2->SetLineColor(kBlue);
+  h2->Draw("e1same");
+  gPad->Update();
+//   create axis according to the histogram dimensions of the original second histogram
+  TGaxis *axis = new TGaxis(gPad->GetUxmin(),
+                    gPad->GetUymax(),
+                    gPad->GetUxmax(),
+                    gPad->GetUymax(),
+                    -0.08, 4.88, 510,"-L");
+  axis->SetLineColor(kBlue);
+  axis->SetLabelColor(kBlue);
+  axis->SetTextColor(kBlue);
+  axis->SetTitle("x_{0}-x_{c} [cm]");
+  axis->Draw();
+  return h1;
+}
+
+//________________________________________________________
+Bool_t AliTRDcheckDET::MakeBarPlot(TH1 *histo, Int_t color){
+  //
+  // Draw nice bar plots
+  //
+  if(!histo->GetEntries()) return kFALSE;
+  histo->Scale(100./histo->Integral());
+  histo->SetFillColor(color);
+  histo->SetBarOffset(.2);
+  histo->SetBarWidth(.6);
+  histo->Draw("bar1");
+  return kTRUE;
+}
diff --git a/PWG1/TRD/AliTRDcheckDET.h b/PWG1/TRD/AliTRDcheckDET.h
new file mode 100644 (file)
index 0000000..04fef04
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef ALITRDCHECKDET_H
+#define ALITRDCHECKDET_H
+
+#ifndef ALITRDRECOTASK_H
+#include "AliTRDrecoTask.h"
+#endif
+////////////////////////////////////////////////////////////////////////////
+//  Basic checks for tracking and detector performance                    //
+//                                                                        //
+//  Authors:                                                              //
+//    Anton Andronic <A.Andronic@gsi.de>                                  //
+//    Alexandru Bercuci <A.Bercuci@gsi.de>                                //
+//    Markus Fasel <M.Fasel@gsi.de>                                       //
+////////////////////////////////////////////////////////////////////////////
+
+
+class TObjArray;
+class TH1;
+class TMap;
+class AliESDHeader;
+class AliTRDcluster;
+class AliTRDseedV1;
+class AliTRDgeometry;
+class AliTRDReconstructor;
+class AliTRDrecoParam;
+class AliTRDeventInfo;
+class AliTRDcheckDET : public AliTRDrecoTask{
+public:
+  // The Histogram number
+  enum  HistType_t {
+    kNclustersTrack     = 0,
+    kNclustersTracklet  = 1,
+    kNtrackletsTrack    = 2,
+    kNtrackletsSTA      = 3,
+    kNtrackletsBAR      = 4,
+    kNtrackletsCross    = 5,
+    kNtrackletsFindable = 6,
+    kNtracksEvent       = 7,
+    kNtracksSector      = 8,
+    kPH                 = 9,
+    kChi2               = 10,
+    kChargeCluster      = 11,
+    kChargeTracklet     = 12,
+    kNeventsTrigger     = 13,
+    kNeventsTriggerTracks=14,
+    kTriggerPurity      = 15,
+    kTrackStatus        = 16,
+    kTrackletStatus     = 17
+  };
+
+  AliTRDcheckDET();
+  virtual ~AliTRDcheckDET();
+
+  virtual void ConnectInputData(const Option_t *);
+  virtual void CreateOutputObjects();
+  virtual void Exec(Option_t *opt);
+
+  virtual TObjArray *Histos();
+
+  // Plotting Functions:
+  TH1 *PlotTrackStatus(const AliTRDtrackV1 *track = 0x0);
+  TH1 *PlotTrackletStatus(const AliTRDtrackV1 *track = 0x0);
+  TH1 *PlotNClustersTracklet(const AliTRDtrackV1 *t = 0x0);
+  TH1 *PlotNClustersTrack(const AliTRDtrackV1 *t = 0x0);
+  TH1 *PlotNTrackletsTrack(const AliTRDtrackV1 *t = 0x0);
+  TH1 *PlotNTrackletsRowCross(const AliTRDtrackV1 *t = 0x0);
+  TH1 *PlotFindableTracklets(const AliTRDtrackV1 *track = 0x0);
+  TH1 *PlotNTracksSector(const AliTRDtrackV1 *t = 0x0);
+  TH1 *PlotPHt(const AliTRDtrackV1 *t = 0x0);
+  TH1 *PlotPHx(const AliTRDtrackV1 *track = 0x0);
+  TH1 *PlotChi2(const AliTRDtrackV1 *t = 0x0);
+  TH1 *PlotChargeCluster(const AliTRDtrackV1 *t = 0x0);
+  TH1 *PlotChargeTracklet(const AliTRDtrackV1 *t = 0x0);
+
+  virtual Bool_t PostProcess();
+  virtual Bool_t GetRefFigure(Int_t ifig);
+  
+  void SetRecoParam(AliTRDrecoParam *r);
+
+private:
+  AliTRDcheckDET(const AliTRDcheckDET &);
+  AliTRDcheckDET& operator=(const AliTRDcheckDET &);
+  void GetDistanceToTracklet(Double_t *dist, AliTRDseedV1 * const tracklet, AliTRDcluster * const c);
+  TH1* MakePlotChi2();
+  TH1* MakePlotNTracklets();
+  TH1* MakePlotPulseHeight();
+  Bool_t MakeBarPlot(TH1 *histo, Int_t Color);
+
+  AliTRDeventInfo *fEventInfo;         //! ESD Header
+  TMap *fTriggerNames;                 //! Containing trigger class names
+  AliTRDReconstructor *fReconstructor; // TRD Reconstructor
+  AliTRDgeometry *fGeo;                // TRD Geometry object
+    
+  ClassDef(AliTRDcheckDET, 1)
+};
+#endif
+
diff --git a/PWG1/TRD/AliTRDcheckESD.cxx b/PWG1/TRD/AliTRDcheckESD.cxx
new file mode 100644 (file)
index 0000000..0a07060
--- /dev/null
@@ -0,0 +1,486 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+/////////////////////////////////////////////////////
+//
+// Check basic detector results at ESD level
+//   - Geometrical efficiency  
+//   - Tracking efficiency  
+//   - PID efficiency  
+//   - Refit efficiency  
+//
+// Author
+//   Alex Bercuci <A.Bercuci@gsi.de>
+//
+//////////////////////////////////////////////////////
+
+#include <TClonesArray.h>
+#include <TObjArray.h>
+#include <TObject.h>
+#include <TH2I.h>
+#include <TGraphErrors.h>
+#include <TGraphAsymmErrors.h>
+#include <TFile.h>
+#include <TTree.h>
+#include <TROOT.h>
+#include <TChain.h>
+#include <TParticle.h>
+
+#include "AliLog.h"
+#include "AliAnalysisManager.h"
+#include "AliESDEvent.h"
+#include "AliESDkink.h"
+#include "AliMCEvent.h"
+#include "AliESDInputHandler.h"
+#include "AliMCEventHandler.h"
+
+#include "AliESDtrack.h"
+#include "AliMCParticle.h"
+#include "AliPID.h"
+#include "AliStack.h"
+#include "AliTrackReference.h"
+
+#include "AliTRDcheckESD.h"
+
+ClassImp(AliTRDcheckESD)
+
+const Float_t AliTRDcheckESD::fgkxTPC = 290.;
+const Float_t AliTRDcheckESD::fgkxTOF = 365.;
+FILE* AliTRDcheckESD::fgFile = 0x0;
+
+//____________________________________________________________________
+AliTRDcheckESD::AliTRDcheckESD():
+  AliAnalysisTask("checkESD", "ESD checker for TRD info")
+  ,fStatus(0)
+  ,fESD(0x0)
+  ,fMC(0x0)
+  ,fHistos(0x0)
+  ,fResults(0x0)
+{
+  //
+  // Default constructor
+  //
+  SetMC(kTRUE);
+  DefineInput(0, TChain::Class());
+  DefineOutput(0, TObjArray::Class());
+}
+
+//____________________________________________________________________
+AliTRDcheckESD::~AliTRDcheckESD()
+{
+// Destructor
+  if(fHistos){
+    //fHistos->Delete();
+    delete fHistos;
+  }
+  if(fResults){
+    fResults->Delete();
+    delete fResults;
+  }
+}
+
+//____________________________________________________________________
+void AliTRDcheckESD::ConnectInputData(Option_t *)
+{
+  //
+  // Link the Input Data
+  //
+  TTree *tree = dynamic_cast<TChain*>(GetInputData(0));
+  if(tree) tree->SetBranchStatus("Tracks", 1);
+
+  AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*>(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
+  fESD = esdH ? esdH->GetEvent() : 0x0;
+
+  if(!HasMC()) return;
+  AliMCEventHandler *mcH = dynamic_cast<AliMCEventHandler*>(AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
+  fMC = mcH ? mcH->MCEvent() : 0x0;
+}
+
+//____________________________________________________________________
+void AliTRDcheckESD::CreateOutputObjects()
+{      
+  //
+  // Create Output Containers (TObjectArray containing 1D histograms)
+  //
+  OpenFile(0, "RECREATE");  
+  Histos();
+}
+
+//____________________________________________________________________
+TGraph* AliTRDcheckESD::GetGraph(Int_t id, Option_t *opt)
+{
+// Retrieve graph with "id"
+// Possible options are :
+//   "b" - build graph if none found
+//   "c" - clear existing graph
+
+  Bool_t kBUILD = strstr(opt, "b"), // build graph if none found
+         kCLEAR = strstr(opt, "c"); // clear existing graph
+
+  const Char_t *name[] = {
+    "Geo", "Trk", "Pid", "Ref", "Max06", "Mean09"
+  };
+  const Char_t *title[] = {
+    "TRD geometrical efficiency (TRDin/TPCout)"
+    ,"TRD tracking efficiency (TRDout/TRDin)"
+    ,"TRD PID efficiency (TRDpid/TRDin)"
+    ,"TRD refit efficiency (TRDrefit/TRDin)"
+    ,"TRD Eloss (Max/90% quantile)"
+    ,"TRD Eloss (Mean/60% quantile)"
+  };
+  const Int_t ngr = sizeof(name)/sizeof(Char_t*);
+  if(ngr != kNgraphs){
+    AliWarning("No of graphs defined different from definition");
+    return 0x0;
+  }
+
+  if(!fResults){
+    fResults = new TObjArray(kNgraphs);
+    fResults->SetOwner();
+    fResults->SetName("results");
+  }
+
+  TGraph *g = 0x0;
+  if((g = dynamic_cast<TGraph*>(fResults->At(id)))){
+    if(kCLEAR){ 
+      for(Int_t ip=g->GetN(); ip--;) g->RemovePoint(ip);
+    } else {
+      PutTrendValue(name[id], g->GetMean(2));
+      PutTrendValue(Form("%sRMS", name[id]), g->GetRMS(2));
+    }
+  } else {
+    if(kBUILD){
+      switch(id){
+      case 0:
+        g = new TGraphErrors();
+        break;
+      case 1:
+        g = new TGraphErrors();
+        break;
+      case 2:
+        g = new TGraphErrors();
+        break;
+      case 3:
+        g = new TGraphErrors();
+        break;
+      case 4:
+        g = new TGraphAsymmErrors(6);
+        g->SetMarkerStyle(22);g->SetMarkerColor(kRed);
+        g->SetLineColor(kBlack);g->SetLineWidth(2);
+        break;
+      case 5:
+        g = new TGraphAsymmErrors(6);
+        g->SetMarkerStyle(21);
+        g->SetLineColor(kRed);g->SetLineWidth(2);
+        break;
+      default:
+        AliWarning(Form("Graph index[%d] missing/not defined.", id));
+        return 0x0;
+      }
+      g->SetNameTitle(name[id], title[id]);
+      fResults->AddAt(g, id);
+    }
+  }
+  return g;
+}
+
+//____________________________________________________________________
+void AliTRDcheckESD::Exec(Option_t *){
+  //
+  // Run the Analysis
+  //
+  if(!fESD){
+    AliError("ESD event missing.");
+    return;
+  }
+
+  // Get MC information if available
+  AliStack * fStack = 0x0;
+  if(HasMC()){
+    if(!fMC){ 
+      AliWarning("MC event missing");
+      SetMC(kFALSE);
+    } else {
+      if(!(fStack = fMC->Stack())){
+        AliWarning("MC stack missing");
+        SetMC(kFALSE);
+      }
+    }
+  }
+  Bool_t bTRDin(0), bTRDout(0), bTRDpid(0);
+
+  AliESDtrack *esdTrack = 0x0;
+  for(Int_t itrk = 0; itrk < fESD->GetNumberOfTracks(); itrk++){
+    bTRDin=0;bTRDout=0;bTRDpid=0;
+    esdTrack = fESD->GetTrack(itrk);
+
+//     if(esdTrack->GetNcls(1)) nTPC++;
+//     if(esdTrack->GetNcls(2)) nTRD++;
+
+    // track status
+    ULong_t status = esdTrack->GetStatus();
+    //PrintStatus(status);
+
+    // define TPC out tracks
+    if(!Bool_t(status & AliESDtrack::kTPCout)) continue;
+    if(esdTrack->GetKinkIndex(0) > 0) continue;
+
+    // TRD PID
+    Double_t p[AliPID::kSPECIES]; esdTrack->GetTRDpid(p);
+    // pid quality
+    //esdTrack->GetTRDntrackletsPID();
+
+    // look at external track param
+    const AliExternalTrackParam *op = esdTrack->GetOuterParam();
+    const AliExternalTrackParam *ip = esdTrack->GetInnerParam();
+    Double_t xyz[3];
+    if(op){
+      op->GetXYZ(xyz);
+      op->Global2LocalPosition(xyz, op->GetAlpha());
+      //printf("op @ X[%7.3f]\n", xyz[0]);
+    }
+
+    // read MC info
+    if(!HasMC()) continue;
+
+    Int_t fLabel = esdTrack->GetLabel();
+    if(TMath::Abs(fLabel) > fStack->GetNtrack()) continue; 
+    
+    // read MC particle
+    AliMCParticle *mcParticle = 0x0; 
+    if(!(mcParticle = (AliMCParticle*) fMC->GetTrack(TMath::Abs(fLabel)))){
+      AliWarning(Form("MC particle missing. Label[ %d].", fLabel));
+      continue;
+    }
+
+    AliTrackReference *ref = 0x0; 
+    Int_t nRefs = mcParticle->GetNumberOfTrackReferences();
+    if(!nRefs){
+      AliWarning(Form("Track refs missing. Label[%d].", fLabel));
+      continue;
+    }
+    Int_t iref = 0;
+    while(iref<nRefs){
+      ref = mcParticle->GetTrackReference(iref);
+      if(ref->LocalX() > fgkxTPC) break;
+      ref=0x0; iref++;
+    }
+
+    // read TParticle
+    //TParticle *tParticle = mcParticle->Particle(); 
+    //Int_t fPdg = tParticle->GetPdgCode();
+    // reject secondaries
+    //if(!tParticle->IsPrimary()) continue;
+
+    if(ref){ 
+      if(ref->LocalX() > fgkxTOF){ // track skipping TRD fiducial volume
+        ref = mcParticle->GetTrackReference(TMath::Max(iref-1, 0));
+      } else {
+        bTRDin=1;
+        if(esdTrack->GetNcls(2)) bTRDout=1;
+        if(esdTrack->GetTRDntrackletsPID()>=4) bTRDpid=1;
+      }
+    } else { // track stopped in TPC 
+      ref = mcParticle->GetTrackReference(TMath::Max(iref-1, 0));
+    }
+    // get the MC pt !!
+    Float_t pt = ref->Pt();
+
+    TH2 *h = (TH2I*)fHistos->At(kTRDstat);
+    if(status & AliESDtrack::kTPCout) h->Fill(pt, kTPCout);
+    if(/*status & AliESDtrack::k*/bTRDin) h->Fill(pt, kTRDin);
+    if(/*status & AliESDtrack::k*/bTRDout){ 
+      ((TH1*)fHistos->At(kNCl))->Fill(esdTrack->GetNcls(2));
+      h->Fill(pt, kTRDout);
+    }
+    if(/*status & AliESDtrack::k*/bTRDpid) h->Fill(pt, kTRDpid);
+    if(status & AliESDtrack::kTRDrefit) h->Fill(pt, kTRDref);
+
+    if(ip){
+      h = (TH2I*)fHistos->At(kTRDmom);
+      Float_t p(0.);
+      for(Int_t ily=6; ily--;){
+        if((p=esdTrack->GetTRDmomentum(ily))<0.) continue;
+        h->Fill(ip->GetP()-p, ily);
+      }
+    }
+  }  
+  PostData(0, fHistos);
+}
+
+//____________________________________________________________________
+TObjArray* AliTRDcheckESD::Histos()
+{
+// Retrieve histograms array if already build or build it
+
+  if(fHistos) return fHistos;
+
+  fHistos = new TObjArray(kNhistos);
+  //fHistos->SetOwner(kTRUE);
+  
+  TH1 *h = 0x0;
+
+  // clusters per tracklet
+  if(!(h = (TH1I*)gROOT->FindObject("hNCl"))){
+    h = new TH1I("hNCl", "Clusters per TRD track", 100, 0., 200.);
+    h->GetXaxis()->SetTitle("N_{cl}^{TRD}");
+    h->GetYaxis()->SetTitle("entries");
+  } else h->Reset();
+  fHistos->AddAt(h, kNCl);
+
+  // status bits histogram
+  if(!(h = (TH2I*)gROOT->FindObject("hTRDstat"))){
+    h = new TH2I("hTRDstat", "TRD status bits", 100, 0., 20., kNbits, .5, kNbits+.5);
+    h->GetXaxis()->SetTitle("p_{T} [GeV/c]");
+    h->GetYaxis()->SetTitle("status bits");
+    h->GetZaxis()->SetTitle("entries");
+  } else h->Reset();
+  fHistos->AddAt(h, kTRDstat);
+
+  // energy loss
+  if(!(h = (TH2I*)gROOT->FindObject("hTRDmom"))){
+    h = new TH2I("hTRDmom", "TRD energy loss", 100, -1., 2., 6, -0.5, 5.5);
+    h->GetXaxis()->SetTitle("p_{inner} - p_{ly} [GeV/c]");
+    h->GetYaxis()->SetTitle("layer");
+    h->GetZaxis()->SetTitle("entries");
+  } else h->Reset();
+  fHistos->AddAt(h, kTRDmom);
+
+  return fHistos;
+}
+
+//____________________________________________________________________
+Bool_t AliTRDcheckESD::Load(const Char_t *filename, const Char_t *name)
+{
+// Load data from performance file
+
+  if(!TFile::Open(filename)){
+    AliWarning(Form("Couldn't open file %s.", filename));
+    return kFALSE;
+  }
+  TObjArray *o = 0x0;
+  if(!(o = (TObjArray*)gFile->Get(name ? name : GetName()))){
+    AliWarning("Missing histogram container.");
+    return kFALSE;
+  }
+  fHistos = (TObjArray*)o->Clone(GetName());
+  gFile->Close();
+  return kTRUE;
+}
+
+//_______________________________________________________
+Bool_t AliTRDcheckESD::PutTrendValue(const Char_t *name, Double_t val)
+{
+// Dump trending value to default file
+
+  if(!fgFile){
+    fgFile = fopen("TRD.Performance.txt", "at");
+  }
+  fprintf(fgFile, "%s_%s %f\n", GetName(), name, val);
+  return kTRUE;
+}
+
+//____________________________________________________________________
+void AliTRDcheckESD::Terminate(Option_t *)
+{
+// Steer post-processing 
+
+
+  // geometrical efficiency
+  TH2I *h2 = (TH2I*)fHistos->At(kTRDstat);
+  TH1 *h1[2] = {0x0, 0x0};
+  h1[0] = h2->ProjectionX("checkESDx0", kTPCout, kTPCout);
+  h1[1] = h2->ProjectionX("checkESDx1", kTRDin, kTRDin);
+  Process(h1, (TGraphErrors*)GetGraph(0));
+  delete h1[0];delete h1[1];
+
+  // tracking efficiency
+  h1[0] = h2->ProjectionX("checkESDx0", kTRDin, kTRDin);
+  h1[1] = h2->ProjectionX("checkESDx1", kTRDout, kTRDout);
+  Process(h1, (TGraphErrors*)GetGraph(1));
+  delete h1[1];
+
+  // PID efficiency
+  h1[1] = h2->ProjectionX("checkESDx1", kTRDpid, kTRDpid);
+  Process(h1, (TGraphErrors*)GetGraph(2));
+  delete h1[1];
+
+  // Refit efficiency
+  h1[1] = h2->ProjectionX("checkESDx1", kTRDref, kTRDref);
+  Process(h1, (TGraphErrors*)GetGraph(3));
+  delete h1[1];
+  if(!(h2 = dynamic_cast<TH2I*>(fHistos->At(kTRDmom)))) return;
+  TGraphAsymmErrors *g06 = (TGraphAsymmErrors*)GetGraph(4), *g09 = (TGraphAsymmErrors*)GetGraph(5);
+  TAxis *ax=h2->GetXaxis();
+  const Int_t nq(4);
+  const Double_t xq[nq] = {0.05, 0.2, 0.8, 0.95};
+  Double_t yq[nq];
+  for(Int_t ily=6; ily--;){
+    h1[0] = h2->ProjectionX("checkESDp0", ily+1, ily+1);
+    h1[0]->GetQuantiles(nq,yq,xq);
+    g06->SetPoint(ily, Float_t(ily), ax->GetBinCenter(h1[0]->GetMaximumBin()));
+    g06->SetPointError(ily, 0., 0., TMath::Abs(yq[0]), yq[3]);
+    g09->SetPoint(ily, Float_t(ily), h1[0]->GetMean());
+    g09->SetPointError(ily, 0., 0., TMath::Abs(yq[1]), yq[2]);
+
+    //printf(" max[%f] mean[%f] q[%f %f %f %f]\n", ax->GetBinCenter(h1[0]->GetMaximumBin()), h1[0]->GetMean(), yq[0], yq[1], yq[2], yq[3]);
+    delete h1[0];
+  }
+}
+
+//____________________________________________________________________
+void AliTRDcheckESD::Process(TH1 **h1, TGraphErrors *g)
+{
+// Generic function to process one reference plot
+
+  Int_t n1 = 0, n2 = 0, ip=0;
+  Double_t eff = 0.;
+
+  TAxis *ax = h1[0]->GetXaxis();
+  for(Int_t ib=1; ib<=ax->GetNbins(); ib++){
+    if(!(n1 = (Int_t)h1[0]->GetBinContent(ib))) continue;
+    n2 = (Int_t)h1[1]->GetBinContent(ib);
+    eff = n2/Float_t(n1);
+
+    ip=g->GetN();
+    g->SetPoint(ip, ax->GetBinCenter(ib), eff);
+    g->SetPointError(ip, 0., n2 ? eff*TMath::Sqrt(1./n1+1./n2) : 0.);
+  }
+}  
+
+//____________________________________________________________________
+void AliTRDcheckESD::PrintStatus(ULong_t status)
+{
+// Dump track status to stdout
+
+  printf("ITS[i(%d) o(%d) r(%d)] TPC[i(%d) o(%d) r(%d) p(%d)] TRD[i(%d) o(%d) r(%d) p(%d) s(%d)] HMPID[o(%d) p(%d)]\n"
+    ,Bool_t(status & AliESDtrack::kITSin)
+    ,Bool_t(status & AliESDtrack::kITSout)
+    ,Bool_t(status & AliESDtrack::kITSrefit)
+    ,Bool_t(status & AliESDtrack::kTPCin)
+    ,Bool_t(status & AliESDtrack::kTPCout)
+    ,Bool_t(status & AliESDtrack::kTPCrefit)
+    ,Bool_t(status & AliESDtrack::kTPCpid)
+    ,Bool_t(status & AliESDtrack::kTRDin)
+    ,Bool_t(status & AliESDtrack::kTRDout)
+    ,Bool_t(status & AliESDtrack::kTRDrefit)
+    ,Bool_t(status & AliESDtrack::kTRDpid)
+    ,Bool_t(status & AliESDtrack::kTRDStop)
+    ,Bool_t(status & AliESDtrack::kHMPIDout)
+    ,Bool_t(status & AliESDtrack::kHMPIDpid)
+  );
+}
+
diff --git a/PWG1/TRD/AliTRDcheckESD.h b/PWG1/TRD/AliTRDcheckESD.h
new file mode 100644 (file)
index 0000000..6dd999b
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef ALITRDCHECKESD_H
+#define ALITRDCHECKESD_H
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+/* $Id: AliTRDcheckESD.h 27496 2008-07-22 08:35:45Z cblume $ */
+
+/////////////////////////////////////////////////////
+//
+// Check basic detector results at ESD level
+//
+// Author
+//   Alex Bercuci <A.Bercuci@gsi.de>
+//
+//////////////////////////////////////////////////////
+
+#ifndef ALIANALYSISTASK_H
+#include "AliAnalysisTask.h"
+#endif
+
+class AliESDEvent;
+class AliMCEvent;
+class TH1;
+class TObjArray;
+class TGraph;
+class TGraphErrors;
+class AliTRDcheckESD : public AliAnalysisTask {
+public:
+  enum ETRDcheckESDstatus {
+    kMC = BIT(0)
+  };
+  enum ETRDcheckESDhistos {
+    kNCl  = 0    // number of clusters per track
+   ,kTRDstat     // TRD tracks status
+   ,kTRDmom      // TRD track momentum
+   ,kNhistos = 3 // number of histograms
+   ,kNgraphs = 6 // number of graphs
+  };
+  enum ETRDcheckESDbits {
+    kTPCout = 1 // track left TPC
+   ,kTRDin      // track reach TRD fiducial volume
+   ,kTRDout     // track reconstructed in TRD
+   ,kTRDpid     // PID calculated in TRD
+   ,kTRDref     // track refitted in TRD
+   ,kNbits  = 5 // number of check bits
+  };
+  AliTRDcheckESD();
+  virtual ~AliTRDcheckESD();
+  
+  void          ConnectInputData(Option_t *);
+  void          CreateOutputObjects();
+  TGraph*       GetGraph(Int_t id, Option_t *opt="bc");
+  void          Exec(Option_t *);
+
+  Bool_t        HasMC() const { return TESTBIT(fStatus, kMC);}
+  TObjArray*    Histos();
+  Bool_t        Load(const Char_t *fn, const Char_t *name=0x0);
+  void          SetMC(Bool_t mc = kTRUE) { mc ? SETBIT(fStatus, kMC) : CLRBIT(fStatus, kMC);}
+  Bool_t        PutTrendValue(const Char_t *name, Double_t val);
+  void          Terminate(Option_t *);
+
+private:
+  static const Float_t fgkxTPC; // end radial position of TPC
+  static const Float_t fgkxTOF; // start radial position of TOF
+
+  AliTRDcheckESD(const AliTRDcheckESD&);
+  AliTRDcheckESD& operator=(const AliTRDcheckESD&);
+  void          Process(TH1 **h, TGraphErrors *g);
+  void          PrintStatus(ULong_t s);
+
+  Int_t            fStatus;            // bit mask for controlling the task
+  AliESDEvent      *fESD;              // ESD event
+  AliMCEvent       *fMC;               // MC event
+  TObjArray        *fHistos;           // QA histos
+  TObjArray        *fResults;          // QA graphs
+  static FILE *fgFile;                 //! trend file streamer
+  ClassDef(AliTRDcheckESD, 3)          // user oriented TRD analysis based on ESD-MC data
+};
+#endif
diff --git a/PWG1/TRD/AliTRDcheckPID.cxx b/PWG1/TRD/AliTRDcheckPID.cxx
new file mode 100644 (file)
index 0000000..389954e
--- /dev/null
@@ -0,0 +1,1075 @@
+//////////////////////////////////////////////////////
+//
+// PID performance checker of the TRD
+//
+// Performs checks of ESD information for TRD-PID and recalculate PID based on OCDB information
+// Also provides performance plots on detector based on the PID information - for the moment only 
+// MC source is used but V0 is also possible. Here is a list of detector performance checks
+//   - Integrated dE/dx per chamber
+//   - <PH> as function of time bin and local radial position
+//   - number of clusters/tracklet 
+//   - number of tracklets/track 
+//
+// Author : Alex Wilk <wilka@uni-muenster.de>
+//          Alex Bercuci <A.Bercuci@gsi.de>
+//          Markus Fasel <M.Fasel@gsi.de>
+//
+///////////////////////////////////////////////////////
+
+#include "TAxis.h"
+#include "TROOT.h"
+#include "TPDGCode.h"
+#include "TCanvas.h"
+#include "TF1.h"
+#include "TH1F.h"
+#include "TH1D.h"
+#include "TH2F.h"
+#include "TProfile.h"
+#include "TProfile2D.h"
+#include "TGraph.h"
+#include "TGraphErrors.h"
+#include "TLegend.h"
+
+#include <TClonesArray.h>
+#include <TObjArray.h>
+#include <TList.h>
+
+#include "AliESDEvent.h"
+#include "AliESDInputHandler.h"
+#include "AliTrackReference.h"
+
+#include "AliAnalysisTask.h"
+
+#include "AliTRDtrackerV1.h"
+#include "AliTRDtrackV1.h"
+#include "AliTRDcluster.h"
+#include "AliTRDReconstructor.h"
+#include "AliCDBManager.h"
+#include "AliTRDpidUtil.h"
+
+#include "AliTRDcheckPID.h"
+#include "info/AliTRDtrackInfo.h"
+
+ClassImp(AliTRDcheckPID)
+
+//________________________________________________________________________
+AliTRDcheckPID::AliTRDcheckPID() 
+  :AliTRDrecoTask("checkPID", "TRD PID checker")
+  ,fReconstructor(0x0)
+  ,fUtil(0x0)
+  ,fGraph(0x0)
+  ,fEfficiency(0x0)
+  ,fMomentumAxis(0x0)
+  ,fMinNTracklets(AliTRDgeometry::kNlayer)
+  ,fMaxNTracklets(AliTRDgeometry::kNlayer)
+ {
+  //
+  // Default constructor
+  //
+
+  fReconstructor = new AliTRDReconstructor();
+  fReconstructor->SetRecoParam(AliTRDrecoParam::GetLowFluxParam());
+
+  // Initialize momentum axis with default values
+  Double_t defaultMomenta[AliTRDCalPID::kNMom+1];
+  for(Int_t imom = 0; imom < AliTRDCalPID::kNMom+1; imom++)
+    defaultMomenta[imom] = AliTRDCalPID::GetMomentumBinning(imom);
+  SetMomentumBinning(AliTRDCalPID::kNMom, defaultMomenta);
+
+  fUtil = new AliTRDpidUtil();
+  InitFunctorList();
+}
+
+
+//________________________________________________________________________
+AliTRDcheckPID::~AliTRDcheckPID() 
+{
+ if(fGraph){fGraph->Delete(); delete fGraph;}
+ if(fReconstructor) delete fReconstructor;
+ if(fUtil) delete fUtil;
+}
+
+
+//________________________________________________________________________
+void AliTRDcheckPID::CreateOutputObjects()
+{
+  // Create histograms
+  // Called once
+
+  OpenFile(0, "RECREATE");
+  fContainer = Histos();
+}
+
+
+//_______________________________________________________
+TObjArray * AliTRDcheckPID::Histos(){
+
+  //
+  // Create QA histograms
+  //
+  if(fContainer) return fContainer;
+
+  Int_t xBins = AliPID::kSPECIES*fMomentumAxis->GetNbins(); 
+  fContainer = new TObjArray(); fContainer->Expand(kNPlots);
+
+  const Float_t epsilon = 1./(2*(AliTRDpidUtil::kBins-1));     // get nice histos with bin center at 0 and 1
+
+  // histos of the electron probability of all 5 particle species and 11 momenta for the 2-dim LQ method 
+  fEfficiency = new TObjArray(3);
+  fEfficiency->SetOwner(); fEfficiency->SetName("Efficiency");
+  fContainer->AddAt(fEfficiency, kEfficiency);
+  
+  TH1 *h = 0x0;
+  if(!(h = (TH2F*)gROOT->FindObject("PID_LQ"))){
+    h = new TH2F("PID_LQ", "", xBins, -0.5, xBins - 0.5,
+      AliTRDpidUtil::kBins, 0.-epsilon, 1.+epsilon);
+  } else h->Reset();
+  fEfficiency->AddAt(h, AliTRDpidUtil::kLQ);
+
+  // histos of the electron probability of all 5 particle species and 11 momenta for the neural network method
+  if(!(h = (TH2F*)gROOT->FindObject("PID_NN"))){
+    h = new TH2F("PID_NN", "", 
+      xBins, -0.5, xBins - 0.5,
+      AliTRDpidUtil::kBins, 0.-epsilon, 1.+epsilon);
+  } else h->Reset();
+  fEfficiency->AddAt(h, AliTRDpidUtil::kNN);
+
+  // histos of the electron probability of all 5 particle species and 11 momenta for the ESD output
+  if(!(h = (TH2F*)gROOT->FindObject("PID_ESD"))){
+    h = new TH2F("PID_ESD", "", 
+      xBins, -0.5, xBins - 0.5,
+      AliTRDpidUtil::kBins, 0.-epsilon, 1.+epsilon);
+  } else h->Reset();
+  fEfficiency->AddAt(h, AliTRDpidUtil::kESD);
+
+  // histos of the dE/dx distribution for all 5 particle species and 11 momenta 
+  if(!(h = (TH2F*)gROOT->FindObject("dEdx"))){
+    h = new TH2F("dEdx", "", 
+      xBins, -0.5, xBins - 0.5,
+      200, 0, 10000);
+  } else h->Reset();
+  fContainer->AddAt(h, kdEdx);
+
+  // histos of the dE/dx slices for all 5 particle species and 11 momenta 
+  if(!(h = (TH2F*)gROOT->FindObject("dEdxSlice"))){
+    h = new TH2F("dEdxSlice", "", 
+      xBins*AliTRDpidUtil::kLQslices, -0.5, xBins*AliTRDpidUtil::kLQslices - 0.5,
+      200, 0, 5000);
+  } else h->Reset();
+  fContainer->AddAt(h, kdEdxSlice);
+
+  // histos of the pulse height distribution for all 5 particle species and 11 momenta 
+  TObjArray *fPH = new TObjArray(2);
+  fPH->SetOwner(); fPH->SetName("PH");
+  fContainer->AddAt(fPH, kPH);
+  if(!(h = (TProfile2D*)gROOT->FindObject("PHT"))){
+    h = new TProfile2D("PHT", "", 
+      xBins, -0.5, xBins - 0.5,
+      AliTRDtrackerV1::GetNTimeBins(), -0.5, AliTRDtrackerV1::GetNTimeBins() - 0.5);
+  } else h->Reset();
+  fPH->AddAt(h, 0);
+  if(!(h = (TProfile2D*)gROOT->FindObject("PHX"))){
+    h = new TProfile2D("PHX", "", 
+      xBins, -0.5, xBins - 0.5,
+      AliTRDtrackerV1::GetNTimeBins(), 0., .5*AliTRDgeometry::CamHght()+AliTRDgeometry::CdrHght());
+  } else h->Reset();
+  fPH->AddAt(h, 1);
+
+  // histos of the number of clusters distribution for all 5 particle species and 11 momenta 
+  if(!(h = (TH2F*)gROOT->FindObject("NClus"))){
+    h = new TH2F("NClus", "", 
+      xBins, -0.5, xBins - 0.5,
+      50, -0.5, 49.5);
+  } else h->Reset();
+  fContainer->AddAt(h, kNClus);
+
+
+  // momentum distributions - absolute and in momentum bins
+  if(!(h = (TH1F*)gROOT->FindObject("hMom"))){
+    h = new TH1F("hMom", "momentum distribution", fMomentumAxis->GetNbins(), fMomentumAxis->GetXmin(), fMomentumAxis->GetXmax());
+  } else h->Reset();
+  fContainer->AddAt(h, kMomentum);
+  
+  if(!(h = (TH1F*)gROOT->FindObject("hMomBin"))){
+    h = new TH1F("hMomBin", "momentum distribution in momentum bins", fMomentumAxis->GetNbins(), fMomentumAxis->GetXmin(), fMomentumAxis->GetXmax());
+  } else h->Reset();
+  fContainer->AddAt(h, kMomentumBin);
+
+  // Number of tracklets per track
+  if(!(h = (TH2F*)gROOT->FindObject("nTracklets"))){
+    h = new TH2F("nTracklets", "", 
+      xBins, -0.5, xBins - 0.5,
+      AliTRDgeometry::kNlayer, 0.5, AliTRDgeometry::kNlayer+.5);
+  } else h->Reset();
+  fContainer->AddAt(h, kNTracklets);
+
+  return fContainer;
+}
+
+
+//________________________________________________________________________
+Bool_t AliTRDcheckPID::CheckTrackQuality(const AliTRDtrackV1* track) const
+{
+  //
+  // Check if the track is ok for PID
+  //
+  
+  Int_t ntracklets = track->GetNumberOfTracklets();
+  if(ntracklets >= fMinNTracklets && ntracklets <= fMaxNTracklets) return 1;
+//   if(!fESD)
+//     return 0;
+
+  return 0;
+}
+
+//________________________________________________________________________
+Int_t AliTRDcheckPID::CalcPDG(AliTRDtrackV1* track) 
+{
+// Documentation to come
+
+  track -> SetReconstructor(fReconstructor);
+  (const_cast<AliTRDrecoParam*>(fReconstructor->GetRecoParam()))->SetPIDNeuralNetwork();
+  track -> CookPID();
+
+  if(track -> GetPID(AliPID::kElectron) > track -> GetPID(AliPID::kMuon) + track -> GetPID(AliPID::kPion)  + track -> GetPID(AliPID::kKaon) + track -> GetPID(AliPID::kProton)){
+    return kElectron;
+  }
+  else if(track -> GetPID(kProton) > track -> GetPID(AliPID::kPion)  && track -> GetPID(AliPID::kProton) > track -> GetPID(AliPID::kKaon)  && track -> GetPID(AliPID::kProton) > track -> GetPID(AliPID::kMuon)){
+    return kProton;
+  }
+  else if(track -> GetPID(AliPID::kKaon) > track -> GetPID(AliPID::kMuon)  && track -> GetPID(AliPID::kKaon) > track -> GetPID(AliPID::kPion)){
+    return kKPlus;
+  }
+  else if(track -> GetPID(AliPID::kMuon) > track -> GetPID(AliPID::kPion)){
+    return kMuonPlus;
+  }
+  else{
+    return kPiPlus;
+  }
+}
+
+
+//_______________________________________________________
+TH1 *AliTRDcheckPID::PlotLQ(const AliTRDtrackV1 *track)
+{
+  //
+  // Plot the probabilities for electrons using 2-dim LQ
+  //
+
+  if(!fkESD){
+    AliWarning("No ESD info available.");
+    return 0x0;
+  }
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+
+  ULong_t status;
+  status = fkESD -> GetStatus();
+  if(!(status&AliESDtrack::kTRDin)) return 0x0;
+
+  if(!CheckTrackQuality(fkTrack)) return 0x0;
+  
+  if(!(fEfficiency = dynamic_cast<TObjArray *>(fContainer->At(kEfficiency)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  TH2F *hPIDLQ = 0x0;
+  if(!(hPIDLQ = dynamic_cast<TH2F *>(fEfficiency->At(AliTRDpidUtil::kLQ)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+
+  AliTRDtrackV1 cTrack(*fkTrack);
+  cTrack.SetReconstructor(fReconstructor);
+
+  Int_t pdg = 0;
+  Float_t momentum = 0.;
+
+  if(fkMC){
+    if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P();
+    pdg = fkMC->GetPDG();
+  } else{
+    //AliWarning("No MC info available!");
+    momentum = cTrack.GetMomentum(0);
+    pdg = CalcPDG(&cTrack);
+  }
+  if(!IsInRange(momentum)) return 0x0;
+
+  (const_cast<AliTRDrecoParam*>(fReconstructor->GetRecoParam()))->SetPIDNeuralNetwork(kFALSE);
+  cTrack.CookPID();
+  if(cTrack.GetNumberOfTrackletsPID() < fMinNTracklets) return 0x0;
+
+  Int_t species = AliTRDpidUtil::Pdg2Pid(pdg);
+  hPIDLQ -> Fill(FindBin(species, momentum), cTrack.GetPID(AliPID::kElectron));
+  return hPIDLQ;
+}
+
+
+//_______________________________________________________
+TH1 *AliTRDcheckPID::PlotNN(const AliTRDtrackV1 *track)
+{
+  //
+  // Plot the probabilities for electrons using 2-dim LQ
+  //
+
+  if(!fkESD){
+    AliWarning("No ESD info available.");
+    return 0x0;
+  }
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  
+  ULong_t status;
+  status = fkESD -> GetStatus();
+  if(!(status&AliESDtrack::kTRDin)) return 0x0;
+
+  if(!CheckTrackQuality(fkTrack)) return 0x0;
+  
+  if(!(fEfficiency = dynamic_cast<TObjArray *>(fContainer->At(kEfficiency)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  TH2F *hPIDNN;
+  if(!(hPIDNN = dynamic_cast<TH2F *>(fEfficiency->At(AliTRDpidUtil::kNN)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+
+  AliTRDtrackV1 cTrack(*fkTrack);
+  cTrack.SetReconstructor(fReconstructor);
+
+  Int_t pdg = 0;
+  Float_t momentum = 0.;
+  if(fkMC){
+    if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P();
+    pdg = fkMC->GetPDG();
+  } else {
+    //AliWarning("No MC info available!");
+    momentum = cTrack.GetMomentum(0);
+    pdg = CalcPDG(&cTrack);
+  }
+  if(!IsInRange(momentum)) return 0x0;
+
+  (const_cast<AliTRDrecoParam*>(fReconstructor->GetRecoParam()))->SetPIDNeuralNetwork();
+  cTrack.CookPID();
+  if(cTrack.GetNumberOfTrackletsPID() < fMinNTracklets) return 0x0;
+
+  Int_t species = AliTRDpidUtil::Pdg2Pid(pdg);
+  hPIDNN -> Fill(FindBin(species, momentum), cTrack.GetPID(AliPID::kElectron));
+  return hPIDNN;
+}
+
+
+//_______________________________________________________
+TH1 *AliTRDcheckPID::PlotESD(const AliTRDtrackV1 *track)
+{
+  //
+  // Plot the probabilities for electrons using 2-dim LQ
+  //
+
+  if(!fkESD){
+    AliWarning("No ESD info available.");
+    return 0x0;
+  }
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  
+  ULong_t status;
+  status = fkESD -> GetStatus();
+  if(!(status&AliESDtrack::kTRDin)) return 0x0;
+
+  if(!CheckTrackQuality(fkTrack)) return 0x0;
+  if(fkTrack->GetNumberOfTrackletsPID() < fMinNTracklets) return 0x0;
+  
+  if(!(fEfficiency = dynamic_cast<TObjArray *>(fContainer->At(kEfficiency)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  TH2F *hPIDESD = 0x0;
+  if(!(hPIDESD = dynamic_cast<TH2F *>(fEfficiency->At(AliTRDpidUtil::kESD)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+
+
+  Int_t pdg = 0;
+  Float_t momentum = 0.;
+  if(fkMC){
+    if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P();
+    pdg = fkMC->GetPDG();
+  } else {
+    //AliWarning("No MC info available!");
+    AliTRDtrackV1 cTrack(*fkTrack);
+    cTrack.SetReconstructor(fReconstructor);
+    momentum = cTrack.GetMomentum(0);
+    pdg = CalcPDG(&cTrack);
+  }
+  if(!IsInRange(momentum)) return 0x0;
+
+//   Double32_t pidESD[AliPID::kSPECIES];
+  const Double32_t *pidESD = fkESD->GetResponseIter();
+  Int_t species = AliTRDpidUtil::Pdg2Pid(pdg);
+  hPIDESD -> Fill(FindBin(species, momentum), pidESD[0]);
+  return hPIDESD;
+}
+
+
+//_______________________________________________________
+TH1 *AliTRDcheckPID::PlotdEdx(const AliTRDtrackV1 *track)
+{
+  //
+  // Plot the probabilities for electrons using 2-dim LQ
+  //
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  
+  if(!CheckTrackQuality(fkTrack)) return 0x0;
+  
+  TH2F *hdEdx;
+  if(!(hdEdx = dynamic_cast<TH2F *>(fContainer->At(kdEdx)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+
+  AliTRDtrackV1 cTrack(*fkTrack);
+  cTrack.SetReconstructor(fReconstructor);
+  Int_t pdg = 0;
+  Float_t momentum = 0.;
+  if(fkMC){
+    if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P();
+    pdg = fkMC->GetPDG();
+  } else {
+    //AliWarning("No MC info available!");
+    momentum = cTrack.GetMomentum(0);
+    pdg = CalcPDG(&cTrack);
+  }
+  Int_t species = AliTRDpidUtil::Pdg2Pid(pdg);
+  if(!IsInRange(momentum)) return 0x0;
+
+  (const_cast<AliTRDrecoParam*>(fReconstructor->GetRecoParam()))->SetPIDNeuralNetwork(kFALSE);
+  Float_t sumdEdx = 0;
+  Int_t iBin = FindBin(species, momentum);
+  AliTRDseedV1 *tracklet = 0x0;
+  for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){
+    sumdEdx = 0;
+    tracklet = cTrack.GetTracklet(iChamb);
+    if(!tracklet) continue;
+    tracklet -> CookdEdx(AliTRDpidUtil::kLQslices);
+    for(Int_t i = 3; i--;) sumdEdx += tracklet->GetdEdx()[i];
+    hdEdx -> Fill(iBin, sumdEdx);
+  }
+  return hdEdx;
+}
+
+
+//_______________________________________________________
+TH1 *AliTRDcheckPID::PlotdEdxSlice(const AliTRDtrackV1 *track)
+{
+  //
+  // Plot the probabilities for electrons using 2-dim LQ
+  //
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  
+  if(!CheckTrackQuality(fkTrack)) return 0x0;
+  
+  TH2F *hdEdxSlice;
+  if(!(hdEdxSlice = dynamic_cast<TH2F *>(fContainer->At(kdEdxSlice)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+
+  AliTRDtrackV1 cTrack(*fkTrack);
+  cTrack.SetReconstructor(fReconstructor);
+  Int_t pdg = 0;
+  Float_t momentum = 0.;
+  if(fkMC){
+    if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P();
+    pdg = fkMC->GetPDG();
+  } else {
+    //AliWarning("No MC info available!");
+    momentum = cTrack.GetMomentum(0);
+    pdg = CalcPDG(&cTrack);
+  }
+  if(!IsInRange(momentum)) return 0x0;
+
+  (const_cast<AliTRDrecoParam*>(fReconstructor->GetRecoParam()))->SetPIDNeuralNetwork(kFALSE);
+  Int_t iMomBin = fMomentumAxis->FindBin(momentum);
+  Int_t species = AliTRDpidUtil::Pdg2Pid(pdg);
+  Float_t *fdEdx;
+  AliTRDseedV1 *tracklet = 0x0;
+  for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){
+    tracklet = cTrack.GetTracklet(iChamb);
+    if(!tracklet) continue;
+    tracklet -> CookdEdx(AliTRDpidUtil::kLQslices);
+    fdEdx = const_cast<Float_t *>(tracklet->GetdEdx());
+    for(Int_t iSlice = 0; iSlice < AliTRDpidUtil::kLQslices; iSlice++){
+      hdEdxSlice -> Fill(species * fMomentumAxis->GetNbins() * AliTRDpidUtil::kLQslices + (iMomBin-1) * AliTRDpidUtil::kLQslices + iSlice, fdEdx[iSlice]);
+    }
+  }  
+
+  return hdEdxSlice;
+}
+
+
+//_______________________________________________________
+TH1 *AliTRDcheckPID::PlotPH(const AliTRDtrackV1 *track)
+{
+  //
+  // Plot the probabilities for electrons using 2-dim LQ
+  //
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  
+  if(!CheckTrackQuality(fkTrack)) return 0x0;
+  
+  TObjArray *arr = 0x0;
+  TProfile2D *hPHX, *hPHT;
+  if(!(arr = dynamic_cast<TObjArray *>(fContainer->At(kPH)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+  hPHT = (TProfile2D*)arr->At(0);
+  hPHX = (TProfile2D*)arr->At(1);
+
+  Int_t pdg = 0;
+  Float_t momentum = 0.;
+  if(fkMC){
+    if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P();
+    pdg = fkMC->GetPDG();
+  } else {
+    //AliWarning("No MC info available!");
+    AliTRDtrackV1 cTrack(*fkTrack);
+    cTrack.SetReconstructor(fReconstructor);
+    momentum = cTrack.GetMomentum(0);
+    pdg = CalcPDG(&cTrack);
+  }
+  if(!IsInRange(momentum)) return 0x0;;
+
+  AliTRDseedV1 *tracklet = 0x0;
+  AliTRDcluster *cluster = 0x0;
+  Int_t species = AliTRDpidUtil::Pdg2Pid(pdg);
+  Int_t iBin = FindBin(species, momentum);
+  for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){
+    tracklet = fkTrack->GetTracklet(iChamb);
+    if(!tracklet) continue;
+    Float_t x0 = tracklet->GetX0(); 
+    for(Int_t ic = 0; ic < AliTRDtrackerV1::GetNTimeBins(); ic++){
+      if(!(cluster = tracklet->GetClusters(ic))) continue;
+      hPHT -> Fill(iBin, cluster->GetLocalTimeBin(), TMath::Abs(cluster->GetQ()));
+      hPHX -> Fill(iBin, x0 - cluster->GetX(), tracklet->GetdQdl(ic));
+    }
+  }
+  return hPHT;
+}
+
+
+//_______________________________________________________
+TH1 *AliTRDcheckPID::PlotNClus(const AliTRDtrackV1 *track)
+{
+  //
+  // Plot the probabilities for electrons using 2-dim LQ
+  //
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  
+  if(!CheckTrackQuality(fkTrack)) return 0x0;
+  
+  TH2F *hNClus;
+  if(!(hNClus = dynamic_cast<TH2F *>(fContainer->At(kNClus)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+
+
+  Int_t pdg = 0;
+  Float_t momentum = 0.;
+  if(fkMC){
+    if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P();
+    pdg = fkMC->GetPDG();
+  } else {
+    //AliWarning("No MC info available!");
+    AliTRDtrackV1 cTrack(*fkTrack);
+    cTrack.SetReconstructor(fReconstructor);
+    momentum = cTrack.GetMomentum(0);
+    pdg = CalcPDG(&cTrack);
+  }
+  if(!IsInRange(momentum)) return 0x0;
+
+  Int_t species = AliTRDpidUtil::AliTRDpidUtil::Pdg2Pid(pdg);
+  Int_t iBin = FindBin(species, momentum); 
+  AliTRDseedV1 *tracklet = 0x0;
+  for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){
+    tracklet = fkTrack->GetTracklet(iChamb);
+    if(!tracklet) continue;
+    hNClus -> Fill(iBin, tracklet->GetN());
+  }
+
+  return hNClus;
+}
+
+//_______________________________________________________
+TH1 *AliTRDcheckPID::PlotNTracklets(const AliTRDtrackV1 *track)
+{
+  //
+  // Plot the probabilities for electrons using 2-dim LQ
+  //
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  
+  TH2F *hTracklets;
+  if(!(hTracklets = dynamic_cast<TH2F *>(fContainer->At(kNTracklets)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+
+  AliTRDtrackV1 cTrack(*fkTrack);
+  cTrack.SetReconstructor(fReconstructor);
+  Int_t pdg = 0;
+  Float_t momentum = 0.;
+  if(fkMC){
+    if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P();
+    pdg = fkMC->GetPDG();
+  } else {
+    //AliWarning("No MC info available!");
+    momentum = cTrack.GetMomentum(0);
+    pdg = CalcPDG(&cTrack);
+  }
+  Int_t species = AliTRDpidUtil::Pdg2Pid(pdg);
+  if(!IsInRange(momentum)) return 0x0;
+
+  Int_t iBin = FindBin(species, momentum);
+  hTracklets -> Fill(iBin, cTrack.GetNumberOfTracklets());
+  return hTracklets;
+}
+
+//_______________________________________________________
+TH1 *AliTRDcheckPID::PlotMom(const AliTRDtrackV1 *track)
+{
+  //
+  // Plot the probabilities for electrons using 2-dim LQ
+  //
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  
+  if(!CheckTrackQuality(fkTrack)) return 0x0;
+  
+  TH1F *hMom;
+  if(!(hMom = dynamic_cast<TH1F *>(fContainer->At(kMomentum)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+
+
+  Int_t pdg = 0;
+  Float_t momentum = 0.;
+  if(fkMC){
+    if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P();
+    pdg = fkMC->GetPDG();
+  } else {
+    //AliWarning("No MC info available!");
+    AliTRDtrackV1 cTrack(*fkTrack);
+    cTrack.SetReconstructor(fReconstructor);
+    momentum = cTrack.GetMomentum(0);
+    pdg = CalcPDG(&cTrack);
+  }
+  if(IsInRange(momentum)) hMom -> Fill(momentum);
+  return hMom;
+}
+
+
+//_______________________________________________________
+TH1 *AliTRDcheckPID::PlotMomBin(const AliTRDtrackV1 *track)
+{
+  //
+  // Plot the probabilities for electrons using 2-dim LQ
+  //
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  
+  if(!CheckTrackQuality(fkTrack)) return 0x0;
+  
+  TH1F *hMomBin;
+  if(!(hMomBin = dynamic_cast<TH1F *>(fContainer->At(kMomentumBin)))){
+    AliWarning("No Histogram defined.");
+    return 0x0;
+  }
+
+
+  Int_t pdg = 0;
+  Float_t momentum = 0.;
+
+  if(fkMC){
+    if(fkMC->GetTrackRef()) momentum = fkMC->GetTrackRef()->P();
+    pdg = fkMC->GetPDG();
+  } else {
+    //AliWarning("No MC info available!");
+    AliTRDtrackV1 cTrack(*fkTrack);
+    cTrack.SetReconstructor(fReconstructor);
+    momentum = cTrack.GetMomentum(0);
+  }
+  if(IsInRange(momentum)) hMomBin -> Fill(fMomentumAxis->FindBin(momentum));
+  return hMomBin;
+}
+
+
+//________________________________________________________
+Bool_t AliTRDcheckPID::GetRefFigure(Int_t ifig)
+{
+// Steering function to retrieve performance plots
+
+  Bool_t kFIRST = kTRUE;
+  TGraphErrors *g = 0x0;
+  TAxis *ax = 0x0;
+  TObjArray *arr = 0x0;
+  TH1 *h1 = 0x0, *h=0x0;
+  TH2 *h2 = 0x0;
+  TList *content = 0x0;
+  switch(ifig){
+  case kEfficiency:{
+    gPad->Divide(2, 1, 1.e-5, 1.e-5);
+    TList *l=gPad->GetListOfPrimitives();
+    TVirtualPad *pad = ((TVirtualPad*)l->At(0));pad->cd();
+    pad->SetMargin(0.1, 0.01, 0.1, 0.01);
+
+    TLegend *legEff = new TLegend(.65, .75, .98, .98);
+    legEff->SetBorderSize(1);
+    legEff->SetFillColor(0);
+    h=new TH1S("hEff", "", 1, .5, 11.);
+    h->SetLineColor(1);h->SetLineWidth(1);
+    ax = h->GetXaxis();
+    ax->SetTitle("p [GeV/c]");
+    ax->SetRangeUser(.5, 11.);
+    ax->SetMoreLogLabels();
+    ax = h->GetYaxis();
+    ax->SetTitle("#epsilon_{#pi} [%]");
+    ax->CenterTitle();
+    ax->SetRangeUser(1.e-2, 10.);
+    h->Draw();
+    content = (TList *)fGraph->FindObject("Efficiencies");
+    if(!(g = (TGraphErrors*)content->At(AliTRDpidUtil::kLQ))) break;
+    if(!g->GetN()) break;
+    legEff->SetHeader("PID Source");
+    g->Draw("pc"); legEff->AddEntry(g, "LQ 2D", "pl");
+    if(! (g = (TGraphErrors*)content->At(AliTRDpidUtil::kNN))) break;
+    g->Draw("pc"); legEff->AddEntry(g, "NN", "pl");
+    if(! (g = (TGraphErrors*)content->At(AliTRDpidUtil::kESD))) break;
+    g->Draw("p"); legEff->AddEntry(g, "ESD", "pl");
+    legEff->Draw();
+    gPad->SetLogy();
+    gPad->SetLogx();
+    gPad->SetGridy();
+    gPad->SetGridx();
+
+    pad = ((TVirtualPad*)l->At(1));pad->cd();
+    pad->SetMargin(0.1, 0.01, 0.1, 0.01);
+    h=new TH1S("hThr", "", 1, .5, 11.);
+    h->SetLineColor(1);h->SetLineWidth(1);
+    ax = h->GetXaxis();
+    ax->SetTitle("p [GeV/c]");
+    ax->SetMoreLogLabels();
+    ax = h->GetYaxis();
+    ax->SetTitle("Threshold [%]");
+    ax->SetRangeUser(5.e-2, 1.);
+    h->Draw();
+    content = (TList *)fGraph->FindObject("Thresholds");
+    if(!(g = (TGraphErrors*)content->At(AliTRDpidUtil::kLQ))) break;
+    if(!g->GetN()) break;
+    g->Draw("pc");
+    if(!(g = (TGraphErrors*)content->At(AliTRDpidUtil::kNN))) break;
+    g->Draw("pc");
+    if(!(g = (TGraphErrors*)content->At(AliTRDpidUtil::kESD))) break;
+    g->Draw("p");
+    gPad->SetLogx();
+    gPad->SetGridy();
+    gPad->SetGridx();
+    return kTRUE;
+  }
+  case kdEdx:{
+    // save 2.0 GeV projection as reference
+    TLegend *legdEdx = new TLegend(.7, .7, .98, .98);
+    legdEdx->SetBorderSize(1);
+    kFIRST = kTRUE;
+    if(!(h2 = (TH2F*)(fContainer->At(kdEdx)))) break;
+    legdEdx->SetHeader("Particle Species");
+    gPad->SetMargin(0.1, 0.01, 0.1, 0.01);
+    for(Int_t is = AliPID::kSPECIES-1; is>=0; is--){
+      Int_t bin = FindBin(is, 2.);
+      h1 = h2->ProjectionY(Form("px%d", is), bin, bin);
+      if(!h1->GetEntries()) continue;
+      h1->Scale(1./h1->Integral());
+      h1->SetLineColor(AliTRDCalPID::GetPartColor(is));
+      if(kFIRST){
+        h1->GetXaxis()->SetTitle("dE/dx (a.u.)");
+        h1->GetYaxis()->SetTitle("<Entries>");
+      }
+      h = (TH1F*)h1->DrawClone(kFIRST ? "c" : "samec");
+      legdEdx->AddEntry(h, Form("%s", AliTRDCalPID::GetPartName(is)), "l");
+      kFIRST = kFALSE;
+    }
+    if(kFIRST) break;
+    legdEdx->Draw();
+    gPad->SetLogy();
+    gPad->SetLogx(0);
+    gPad->SetGridy();
+    gPad->SetGridx();
+    return kTRUE;
+  }
+  case kdEdxSlice:
+    break;
+  case kPH:{
+    gPad->Divide(2, 1, 1.e-5, 1.e-5);
+    TList *l=gPad->GetListOfPrimitives();
+
+    // save 2.0 GeV projection as reference
+    TLegend *legPH = new TLegend(.4, .7, .68, .98);
+    legPH->SetBorderSize(1);legPH->SetFillColor(0);
+    legPH->SetHeader("Particle Species");
+    if(!(arr = (TObjArray*)(fContainer->At(kPH)))) break;
+    if(!(h2 = (TProfile2D*)(arr->At(0)))) break;
+
+    TVirtualPad *pad = ((TVirtualPad*)l->At(0));pad->cd();
+    pad->SetMargin(0.1, 0.01, 0.1, 0.01);
+    kFIRST = kTRUE;
+    for(Int_t is=0; is<AliPID::kSPECIES; is++){
+      Int_t bin = FindBin(is, 2.);
+      h1 = h2->ProjectionY(Form("pyt%d", is), bin, bin);
+      if(!h1->GetEntries()) continue;
+      h1->SetMarkerStyle(24);
+      h1->SetMarkerColor(AliTRDCalPID::GetPartColor(is));
+      h1->SetLineColor(AliTRDCalPID::GetPartColor(is));
+      if(kFIRST){
+        h1->GetXaxis()->SetTitle("t_{drift} [100*ns]");
+        h1->GetYaxis()->SetTitle("<dQ/dt> [a.u.]");
+      }
+      h = (TH1F*)h1->DrawClone(kFIRST ? "c" : "samec");
+      legPH->AddEntry(h, Form("%s", AliTRDCalPID::GetPartName(is)), "pl");
+      kFIRST = kFALSE;
+    }
+
+    pad = ((TVirtualPad*)l->At(1));pad->cd();
+    pad->SetMargin(0.1, 0.01, 0.1, 0.01);
+    if(!(h2 = (TProfile2D*)(arr->At(1)))) break;
+    kFIRST = kTRUE;
+    for(Int_t is=0; is<AliPID::kSPECIES; is++){
+      Int_t bin = FindBin(is, 2.);
+      h1 = h2->ProjectionY(Form("pyx%d", is), bin, bin);
+      if(!h1->GetEntries()) continue;
+      h1->SetMarkerStyle(24);
+      h1->SetMarkerColor(AliTRDCalPID::GetPartColor(is));
+      h1->SetLineColor(AliTRDCalPID::GetPartColor(is));
+      if(kFIRST){
+        h1->GetXaxis()->SetTitle("x_{drift} [cm]");
+        h1->GetYaxis()->SetTitle("<dQ/dl> [a.u./cm]");
+      }
+      h = (TH1F*)h1->DrawClone(kFIRST ? "c" : "samec");
+      kFIRST = kFALSE;
+    }
+
+    if(kFIRST) break;
+    legPH->Draw();
+    gPad->SetLogy(0);
+    gPad->SetLogx(0);
+    gPad->SetGridy();
+    gPad->SetGridx();
+    return kTRUE;
+  }
+  case kNClus:{
+    // save 2.0 GeV projection as reference
+    TLegend *legNClus = new TLegend(.13, .7, .4, .98);
+    legNClus->SetBorderSize(1);
+    legNClus->SetFillColor(0);
+
+    kFIRST = kTRUE;
+    if(!(h2 = (TH2F*)(fContainer->At(kNClus)))) break;
+    legNClus->SetHeader("Particle Species");
+    for(Int_t is=0; is<AliPID::kSPECIES; is++){
+      Int_t bin = FindBin(is, 2.);
+      h1 = h2->ProjectionY(Form("pyNClus%d", is), bin, bin);
+      if(!h1->GetEntries()) continue;
+      h1->Scale(100./h1->Integral());
+      //h1->SetMarkerStyle(24);
+      //h1->SetMarkerColor(AliTRDCalPID::GetPartColor(is));
+      h1->SetLineColor(AliTRDCalPID::GetPartColor(is));
+      if(kFIRST){ 
+        h1->GetXaxis()->SetTitle("N^{cl}/tracklet");
+        h1->GetYaxis()->SetTitle("Prob. [%]");
+        h = (TH1F*)h1->DrawClone("c");
+        h->SetMaximum(55.);
+        h->GetXaxis()->SetRangeUser(0., 35.);
+        kFIRST = kFALSE;
+      } else h = (TH1F*)h1->DrawClone("samec");
+
+      legNClus->AddEntry(h, Form("%s", AliTRDCalPID::GetPartName(is)), "l");
+    }
+    if(kFIRST) break;
+    legNClus->Draw();
+    gPad->SetLogy(0);
+    gPad->SetLogx(0);
+    gPad->SetGridy();
+    gPad->SetGridx();
+    return kTRUE;
+  }
+  case kMomentum:
+  case kMomentumBin:
+    break; 
+  case kNTracklets:{
+    TLegend *legNClus = new TLegend(.4, .7, .68, .98);
+    legNClus->SetBorderSize(1);
+    kFIRST = kTRUE;
+    if(!(h2 = (TH2F*)(fContainer->At(kNTracklets)))) break;
+    legNClus->SetHeader("Particle Species");
+    for(Int_t is=0; is<AliPID::kSPECIES; is++){
+      Int_t bin = FindBin(is, 2.);
+      h1 = h2->ProjectionY(Form("pyNTracklets%d", is), bin, bin);
+      if(!h1->GetEntries()) continue;
+      h1->Scale(100./h1->Integral());
+      //h1->SetMarkerStyle(24);
+      //h1->SetMarkerColor(AliTRDCalPID::GetPartColor(is));
+      h1->SetLineColor(AliTRDCalPID::GetPartColor(is));
+      if(kFIRST){ 
+        h1->GetXaxis()->SetTitle("N^{trklt}/track");
+        h1->GetXaxis()->SetRangeUser(1.,6.);
+        h1->GetYaxis()->SetTitle("Prob. [%]");
+      }
+      h = (TH1F*)h1->DrawClone(kFIRST ? "c" : "samec");
+      legNClus->AddEntry(h, Form("%s", AliTRDCalPID::GetPartName(is)), "l");
+      kFIRST = kFALSE;
+    }
+    if(kFIRST) break;
+    legNClus->Draw();
+    gPad->SetLogy(0);
+    gPad->SetLogx(0);
+    gPad->SetGridy();
+    gPad->SetGridx();
+    return kTRUE;
+  }
+  }
+  AliInfo(Form("Reference plot [%d] missing result", ifig));
+  return kFALSE;
+}
+
+//________________________________________________________________________
+Bool_t AliTRDcheckPID::PostProcess()
+{
+  // Draw result to the screen
+  // Called once at the end of the query
+
+  if (!fContainer) {
+    Printf("ERROR: list not available");
+    return kFALSE;
+  }
+  if(!(fEfficiency = dynamic_cast<TObjArray *>(fContainer->At(kEfficiency)))){
+    AliError("Efficiency container missing.");
+    return 0x0;
+  }
+  if(!fGraph){ 
+    fGraph = new TObjArray(6);
+    fGraph->SetOwner();
+    EvaluatePionEfficiency(fEfficiency, fGraph, 0.9);
+  }
+  fNRefFigures = 9;
+  return kTRUE;
+}
+
+//________________________________________________________________________
+void AliTRDcheckPID::EvaluatePionEfficiency(TObjArray * const histoContainer, TObjArray *results, Float_t electronEfficiency){
+// Process PID information for pion efficiency
+
+  fUtil->SetElectronEfficiency(electronEfficiency);
+
+  Color_t colors[3] = {kBlue, kGreen+2, kRed};
+  Int_t markerStyle[3] = {7, 7, 24};
+  TString methodName[3] = {"LQ", "NN", "ESD"};
+  // efficiency graphs
+  TGraphErrors *g, *gPtrEff[3], *gPtrThres[3];
+  TObjArray *eff = new TObjArray(3); eff->SetOwner(); eff->SetName("Efficiencies");
+  results->AddAt(eff, 0);
+  for(Int_t iMethod = 0; iMethod < 3; iMethod++){
+    eff->AddAt(g = gPtrEff[iMethod] = new TGraphErrors(), iMethod);
+    g->SetName(Form("efficiency_%s", methodName[iMethod].Data()));
+    g->SetLineColor(colors[iMethod]);
+    g->SetMarkerColor(colors[iMethod]);
+    g->SetMarkerStyle(markerStyle[iMethod]);
+  }
+
+  // Threshold graphs
+  TObjArray *thres = new TObjArray(3); thres->SetOwner(); thres->SetName("Thresholds");
+  results->AddAt(thres, 1);
+  for(Int_t iMethod = 0; iMethod < 3; iMethod++){
+    thres->AddAt(g = gPtrThres[iMethod] = new TGraphErrors(), iMethod);
+    g->SetName(Form("threshold_%s", methodName[iMethod].Data()));
+    g->SetLineColor(colors[iMethod]);
+    g->SetMarkerColor(colors[iMethod]);
+    g->SetMarkerStyle(markerStyle[iMethod]);
+  }
+  
+  Float_t mom = 0.;
+  TH1D *histo1=0x0, *histo2=0x0;
+
+  TH2F *hPtr[3];
+  hPtr[0] = (TH2F*)histoContainer->At(AliTRDpidUtil::kLQ);
+  hPtr[1] = (TH2F*)histoContainer->At(AliTRDpidUtil::kNN);
+  hPtr[2] = (TH2F*)histoContainer->At(AliTRDpidUtil::kESD);
+  
+  for(Int_t iMom = 0; iMom < fMomentumAxis->GetNbins(); iMom++){
+    mom = fMomentumAxis->GetBinCenter(iMom+1);
+
+    Int_t binEl = fMomentumAxis->GetNbins() * AliPID::kElectron + iMom + 1, 
+         binPi = fMomentumAxis->GetNbins() * AliPID::kPion + iMom + 1;
+    for(Int_t iMethod = 0; iMethod < 3; iMethod++){
+      // Calculate the Pion Efficiency at 90% electron efficiency for each Method
+      histo1 = hPtr[iMethod] -> ProjectionY(Form("%s_ele", methodName[iMethod].Data()), binEl, binEl);
+      histo2 = hPtr[iMethod] -> ProjectionY(Form("%s_pio", methodName[iMethod].Data()), binPi, binPi);
+
+      if(!fUtil->CalculatePionEffi(histo1, histo2)) continue;
+     
+      gPtrEff[iMethod]->SetPoint(iMom, mom, 1.e2*fUtil->GetPionEfficiency());
+      gPtrEff[iMethod]->SetPointError(iMom, 0., 1.e2*fUtil->GetError());
+      gPtrThres[iMethod]->SetPoint(iMom, mom, fUtil->GetThreshold());
+      gPtrThres[iMethod]->SetPointError(iMom, 0., 0.);
+
+      AliDebug(2, Form("Pion Efficiency for %s is : %f +/- %f", methodName[iMethod].Data(), fUtil->GetPionEfficiency(), fUtil->GetError()));
+    }
+  }
+}
diff --git a/PWG1/TRD/AliTRDcheckPID.h b/PWG1/TRD/AliTRDcheckPID.h
new file mode 100644 (file)
index 0000000..d1f9eb3
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef ALITRDCHECKPID_H
+#define ALITRDCHECKPID_H
+
+//////////////////////////////////////////////////////
+//
+// PID performance checker of the TRD
+//
+// Author : Alex Wilk <wilka@uni-muenster.de>
+//          Alex Bercuci <A.Bercuci@gsi.de>
+//          Markus Fasel <M.Fasel@gsi.de>
+//
+///////////////////////////////////////////////////////
+
+#ifndef ROOT_TAxis
+#include "TAxis.h"
+#endif
+
+#ifndef ALITRDRECOTASK_H
+#include "AliTRDrecoTask.h"
+#endif
+
+class AliTRDReconstructor;
+class AliTRDpidUtil;
+class AliTRDcheckPID : public AliTRDrecoTask 
+{
+public:
+  // Plots registered for this task
+  enum{
+     kEfficiency     =  0     // pi Efficiency plot
+    ,kdEdx           =  1     // dE/dx spectra
+    ,kdEdxSlice      =  2     // dE/dx spectra
+    ,kPH             =  3     // pulse height spectra
+    ,kNClus          =  4     //  number of clusters per track
+    ,kMomentum       =  5     // momentum distribution
+    ,kMomentumBin    =  6     // momentum distribution
+    ,kNTracklets     =  7     // Number of tracklets per track
+    ,kNPlots         =  8     // Number of plots for this tasks 
+  };
+  AliTRDcheckPID();
+  virtual ~AliTRDcheckPID();
+  
+  virtual void    CreateOutputObjects();
+  virtual Bool_t  GetRefFigure(Int_t ifig);
+  virtual Bool_t  PostProcess();
+
+  TH1 *PlotLQ(const AliTRDtrackV1 *track = 0x0);
+  TH1 *PlotNN(const AliTRDtrackV1 *track = 0x0);
+  TH1 *PlotESD(const AliTRDtrackV1 *track = 0x0);
+  TH1 *PlotdEdx(const AliTRDtrackV1 *track = 0x0);
+  TH1 *PlotdEdxSlice(const AliTRDtrackV1 *track = 0x0);
+  TH1 *PlotPH(const AliTRDtrackV1 *track = 0x0);
+  TH1 *PlotNClus(const AliTRDtrackV1 *track = 0x0);
+  TH1 *PlotNTracklets(const AliTRDtrackV1 *track = 0x0);
+  TH1 *PlotMom(const AliTRDtrackV1 *track = 0x0);
+  TH1 *PlotMomBin(const AliTRDtrackV1 *track = 0x0);
+
+  void SetRequireMinNTracklets(Int_t mintracklets) { fMinNTracklets = mintracklets; }
+  void SetRequireMaxNTracklets(Int_t maxtracklets) { fMaxNTracklets = maxtracklets; }
+
+  TObjArray *GetGraphs() const { return fGraph; };
+  //TObjArray *GetHistos() { return fContainer; };
+  virtual TObjArray *Histos();
+  void EvaluatePionEfficiency(TObjArray * const histoContainer, TObjArray *results, Float_t electronEfficiency);
+  inline void SetMomentumBinning(Int_t nBins, Double_t *bins);
+  inline Int_t FindBin(Int_t species, Double_t momentum);
+  inline Bool_t IsInRange(Double_t momentum);
+
+private:
+  AliTRDcheckPID(const AliTRDcheckPID&);               // not implemented
+  AliTRDcheckPID& operator=(const AliTRDcheckPID&);    // not implemented
+
+  Int_t  CalcPDG(AliTRDtrackV1* track = 0x0);
+  Bool_t CheckTrackQuality(const AliTRDtrackV1* track = 0x0) const;
+  
+  AliTRDReconstructor *fReconstructor;     //! reconstructor needed for recalculation the PID
+  AliTRDpidUtil       *fUtil;              //! utility class for PID calculations
+  TObjArray           *fGraph;             //! array of graphs filled in PostProcess
+  TObjArray           *fEfficiency;        //! array of histograms with efficiency
+  TAxis               *fMomentumAxis;      //! helper mementum binning
+  Int_t                fMinNTracklets;     // minimum number of required Tracklets (for systematic studies)
+  Int_t                fMaxNTracklets;     // maximum number of required Tracklets (for systematic studies) 
+  ClassDef(AliTRDcheckPID, 1); // TRD PID checker
+};
+
+//________________________________________________________________________
+inline void AliTRDcheckPID::SetMomentumBinning(Int_t nBins, Double_t *bins){
+  //
+  // Set the Momentum Bins
+  //
+  if(fMomentumAxis) delete fMomentumAxis;
+  fMomentumAxis = new TAxis(nBins, bins);
+}
+
+//________________________________________________________________________
+inline Int_t AliTRDcheckPID::FindBin(Int_t species, Double_t momentum){
+  //
+  // Find the Bin in the 2D Histogram
+  //
+  return species * fMomentumAxis->GetNbins() + (fMomentumAxis->FindBin(momentum) -1);
+}
+
+//________________________________________________________________________
+inline Bool_t AliTRDcheckPID::IsInRange(Double_t momentum){
+  //
+  // Check Whether momentum is in the defined Range
+  //
+  return (momentum >= fMomentumAxis->GetXmin() && momentum <= fMomentumAxis->GetXmax());
+}
+
+#endif
diff --git a/PWG1/TRD/AliTRDclusterResolution.cxx b/PWG1/TRD/AliTRDclusterResolution.cxx
new file mode 100644 (file)
index 0000000..fc8d264
--- /dev/null
@@ -0,0 +1,1225 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercialf purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+/* $Id: AliTRDclusterResolution.cxx */
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+//  TRD cluster error parameterization                                        //
+//                                                                           //
+// This class is designed to produce the reference plots for a detailed study//
+// and parameterization of TRD cluster errors. The following effects are taken//
+// into account :                                                            //
+//   - dependence with the total charge of the cluster                       //
+//   - dependence with the distance from the center pad. This is monitored 
+// for each layer individually since the pad size varies with layer
+//   - dependence with the drift length - here the influence of anisochronity 
+// and diffusion are searched
+//   - dependence with the distance to the anode wire - anisochronity effects
+//   - dependence with track angle (for y resolution)
+// The correlation between effects is taken into account. 
+// 
+// Since magnetic field plays a very important role in the TRD measurement 
+// the ExB correction is forced by the setter function SetExB(Int_t). The 
+// argument is the detector index, if none is specified all will be 
+// considered.
+// 
+// Two cases are of big importance.
+//   - comparison with MC
+//   - comparison with Kalman fit. In this case the covariance matrix of the
+// Kalman fit are needed.
+// 
+// The functionalities implemented in this class are based on the storage 
+// class AliTRDclusterInfo.
+// 
+// The Method
+// ----------
+// 
+// The method to disentangle s_y and s_x is based on the relation (see also fig.)
+// BEGIN_LATEX
+// #sigma^{2} = #sigma^{2}_{y} + tg^{2}(#alpha_{L})*#sigma^{2}_{x_{d}} + tg^{2}(#phi-#alpha_{L})*(#sigma^{2}_{x_{d}}+#sigma^{2}_{x_{c}})
+// END_LATEX
+// with
+// BEGIN_LATEX
+// #sigma^{2}_{x_{c}} #approx 0 
+// END_LATEX
+// we suppose the chamber is well calibrated for t_{0} and aligned in
+// radial direction. 
+//
+// Clusters can be radially shifted due to three causes:
+//   - globally shifted - due to residual misalignment/miscalibration(t0)
+//   - locally shifted - due to different local drift velocity from the mean
+//   - randomly shifted - due to neighboring (radial direction) clusters 
+// charge induced by asymmetry of the TRF.
+//
+// We estimate this effects by the relations:
+// BEGIN_LATEX
+// #mu_{y} = tg(#alpha_{L})*#Delta x_{d}(...) + tg(#phi-#alpha_{L})*(#Delta x_{c}(...) + #Delta x_{d}(...))
+// END_LATEX
+// where
+// BEGIN_LATEX
+// #Delta x_{d}(...) = (<v_{d}> + #delta v_{d}(x_{d}, d)) * (t + t^{*}(Q))
+// END_LATEX
+// and we specified explicitely the variation of drift velocity parallel 
+// with the track (x_{d}) and perpendicular to it due to anisochronity (d).
+// 
+// For estimating the contribution from asymmetry of TRF the following
+// parameterization is being used
+// BEGIN_LATEX
+// t^{*}(Q) = #delta_{0} * #frac{Q_{t+1} - Q_{t-1}}{Q_{t-1} + Q_{t} + Q_{t+1}}
+// END_LATEX
+//
+//
+// Clusters can also be r-phi shifted due to:
+//   - wrong PRF or wrong cuts at digits level
+//The following correction is applied :
+// BEGIN_LATEX
+// <#Delta y> = a + b * sin(c*y_{pw})
+// END_LATEX
+
+// The Models
+//
+//   Parameterization against total charge
+//
+// Obtained for B=0T at phi=0. All other effects integrated out.
+// BEGIN_LATEX
+// #sigma^{2}_{y}(Q) = #sigma^{2}_{y}(...) + b(#frac{1}{Q} - #frac{1}{Q_{0}}) 
+// END_LATEX
+// For B diff 0T the error of the average ExB correction error has to be subtracted !! 
+//
+//   Parameterization Sx
+//
+// The parameterization of the error in the x direction can be written as
+// BEGIN_LATEX
+// #sigma_{x} = #sigma_{x}^{||} + #sigma_{x}^{#perp}
+// END_LATEX
+//
+// where the parallel component is given mainly by the TRF width while 
+// the perpendicular component by the anisochronity. The model employed for 
+// the parallel is gaus(0)+expo(3) with the following parameters
+// 1  C   5.49018e-01   1.23854e+00   3.84540e-04  -8.21084e-06
+// 2  M   7.82999e-01   6.22531e-01   2.71272e-04  -6.88485e-05
+// 3  S   2.74451e-01   1.13815e+00   2.90667e-04   1.13493e-05
+// 4  E1  2.53596e-01   1.08646e+00   9.95591e-05  -2.11625e-05
+// 5  E2 -2.40078e-02   4.26520e-01   4.67153e-05  -2.35392e-04
+//
+// and perpendicular to the track is pol2 with the parameters
+//
+// Par_0 = 0.190676 +/- 0.41785
+// Par_1 = -3.9269  +/- 7.49862
+// Par_2 = 14.7851  +/- 27.8012
+//
+//   Parameterization Sy
+//
+// The parameterization of the error in the y direction along track uses
+// BEGIN_LATEX
+// #sigma_{y}^{||} = #sigma_{y}^{0} -a*exp(1/(x-b))
+// END_LATEX
+//
+// with following values for the parameters:
+// 1  sy0 2.60967e-01   2.99652e-03   7.82902e-06  -1.89636e-04
+// 2  a  -7.68941e+00   1.87883e+00   3.84539e-04   9.38268e-07
+// 3  b  -3.41160e-01   7.72850e-02   1.63231e-05   2.51602e-05
+//
+//==========================================================================
+// Example how to retrive reference plots from the task
+// void steerClErrParam(Int_t fig=0)
+// {
+//   gSystem->Load("libANALYSIS.so");
+//   gSystem->Load("libTRDqaRec.so");
+// 
+//   // initialize DB manager
+//   AliCDBManager *cdb = AliCDBManager::Instance();
+//   cdb->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
+//   cdb->SetRun(0);
+//   // initialize magnetic field.
+//   AliMagFCheb *field=new AliMagFCheb("Maps","Maps", 2, 1., 10., AliMagFCheb::k5kG);
+//   AliTracker::SetFieldMap(field, kTRUE);
+// 
+//   AliTRDclusterResolution *res = new AliTRDclusterResolution();
+//   res->SetMCdata();
+//   res->Load("TRD.TaskClErrParam.root");
+//   res->SetExB();  
+//   res->SetVisual(); 
+//   //res->SetSaveAs();
+//   res->SetProcessCharge(kFALSE);
+//   res->SetProcessCenterPad(kFALSE);
+//   //res->SetProcessMean(kFALSE);
+//   res->SetProcessSigma(kFALSE);
+//   if(!res->PostProcess()) return;
+//   new TCanvas;
+//   res->GetRefFigure(fig);
+// }
+//
+//  Authors:                                                              //
+//    Alexandru Bercuci <A.Bercuci@gsi.de>                                //
+////////////////////////////////////////////////////////////////////////////
+
+#include "AliTRDclusterResolution.h"
+#include "info/AliTRDclusterInfo.h"
+#include "AliTRDgeometry.h"
+#include "AliTRDcluster.h"
+#include "AliTRDcalibDB.h"
+#include "AliTRDCommonParam.h"
+#include "Cal/AliTRDCalROC.h"
+#include "Cal/AliTRDCalDet.h"
+
+#include "AliLog.h"
+#include "AliTracker.h"
+#include "AliCDBManager.h"
+
+#include "TROOT.h"
+#include "TObjArray.h"
+#include "TAxis.h"
+#include "TF1.h"
+#include "TLegend.h"
+#include "TGraphErrors.h"
+#include "TLine.h"
+#include "TH2I.h"
+#include "TH3S.h"
+#include "TTree.h"
+#include "TMath.h"
+#include "TLinearFitter.h"
+
+#include "TCanvas.h"
+#include "TSystem.h"
+
+ClassImp(AliTRDclusterResolution)
+
+const Float_t AliTRDclusterResolution::fgkTimeBinLength = 1./ AliTRDCommonParam::Instance()->GetSamplingFrequency();
+//_______________________________________________________
+AliTRDclusterResolution::AliTRDclusterResolution(const char *name, const char *title)
+  : AliTRDrecoTask(name, title)
+  ,fCanvas(0x0)
+  ,fInfo(0x0)
+  ,fResults(0x0)
+  ,fAt(0x0)
+  ,fStatus(0)
+  ,fDet(-1)
+  ,fExB(0.)
+  ,fVdrift(0.)
+  ,fLy(0)
+  ,fX(0.)
+  ,fY(0.)
+  ,fZ(0.)
+{
+// Constructor
+
+  memset(fR, 0, 4*sizeof(Float_t));
+  memset(fP, 0, 4*sizeof(Float_t));
+  // time drift axis
+  fAt = new TAxis(kNTB, 0., kNTB*fgkTimeBinLength);
+
+  // By default register all analysis
+  // The user can switch them off in his steering macro
+  SetProcess(kQRes);
+  SetProcess(kCenter);
+  SetProcess(kMean);
+  SetProcess(kSigm);
+}
+
+//_______________________________________________________
+AliTRDclusterResolution::~AliTRDclusterResolution()
+{
+// Destructor
+
+  if(fCanvas) delete fCanvas;
+  if(fAt) delete fAt;
+  if(fResults){
+    fResults->Delete();
+    delete fResults;
+  }
+}
+
+//_______________________________________________________
+void AliTRDclusterResolution::ConnectInputData(Option_t *)
+{
+  fInfo = dynamic_cast<TObjArray *>(GetInputData(0));
+}
+
+//_______________________________________________________
+void AliTRDclusterResolution::CreateOutputObjects()
+{
+  OpenFile(0, "RECREATE");
+  fContainer = Histos();
+}
+
+//_______________________________________________________
+Bool_t AliTRDclusterResolution::GetRefFigure(Int_t ifig)
+{
+// Steering function to retrieve performance plots
+
+  if(!fResults) return kFALSE;
+  TLegend *leg = 0x0;
+  TList *l = 0x0;
+  TObjArray *arr = 0x0;
+  TTree *t = 0x0;
+  TH2 *h2 = 0x0;TH1 *h1 = 0x0;
+  TGraphErrors *gm(0x0), *gs(0x0), *gp(0x0);
+  switch(ifig){
+  case kQRes:
+    if(!(arr = (TObjArray*)fResults->At(kQRes))) break;
+    if(!(gm = (TGraphErrors*)arr->At(0))) break;
+    if(!(gs = (TGraphErrors*)arr->At(1))) break;
+    if(!(gp = (TGraphErrors*)arr->At(2))) break;
+    gs->Draw("apl");
+    gs->GetHistogram()->GetYaxis()->SetRangeUser(-50., 700.);
+    gs->GetHistogram()->SetXTitle("Q [a.u.]");
+    gs->GetHistogram()->SetYTitle("#sigma_{y} / #mu_{y} [#mum] / freq");
+    gm->Draw("pl");
+    gp->Draw("pl");
+    return kTRUE;
+  case kCenter:
+    if(!(arr = (TObjArray*)fResults->At(kCenter))) break;
+    gPad->Divide(2, 1); l = gPad->GetListOfPrimitives();
+    ((TVirtualPad*)l->At(0))->cd();
+    ((TTree*)arr->At(0))->Draw("y:x>>h(23, 0.1, 2.4, 51, -.51, .51)",
+            "m[0]*(ly==0&&abs(m[0])<1.e-1)", "colz");
+    ((TVirtualPad*)l->At(1))->cd();
+    leg= new TLegend(.7, .7, .9, .95);
+    leg->SetBorderSize(0); leg->SetFillColor(0); leg->SetFillStyle(0);
+    leg->SetHeader("TRD Plane"); 
+    for(Int_t il = 1; il<=AliTRDgeometry::kNlayer; il++){
+      if(!(gm = (TGraphErrors*)arr->At(il))) return kFALSE;
+      gm->Draw(il>1?"pc":"apc"); leg->AddEntry(gm, Form("%d", il-1), "pl");
+      if(il>1) continue;
+      gm->GetHistogram()->SetXTitle("t_{drift} [#mus]");
+      gm->GetHistogram()->SetYTitle("#sigma_{y}(x|cen=0) [#mum]");
+      gm->GetHistogram()->GetYaxis()->SetRangeUser(150., 500.);
+    }
+    leg->Draw();
+    return kTRUE;
+  case kSigm:
+    if(!(t = (TTree*)fResults->At(kSigm))) break;
+    t->Draw("z:t>>h2x(23, 0.1, 2.4, 25, 0., 2.5)","sx*(1)", "lego2fb");
+    h2 = (TH2F*)gROOT->FindObject("h2x");
+    printf("  const Double_t sx[24][25]={\n");
+    for(Int_t ix=1; ix<=h2->GetNbinsX(); ix++){
+      printf("    {");
+      for(Int_t iy=1; iy<h2->GetNbinsY(); iy++){
+        printf("%6.4f ", h2->GetBinContent(ix, iy));
+      }
+      printf("%6.4f},\n", h2->GetBinContent(ix, h2->GetNbinsY()));
+    }
+    printf("  };\n");
+    gPad->Divide(2, 1, 1.e-5, 1.e-5); l = gPad->GetListOfPrimitives();
+    ((TVirtualPad*)l->At(0))->cd();
+    h1 = h2->ProjectionX("hsx_pxx"); h1->Scale(1.e4/kND); h1->SetMarkerStyle(24);
+    h1->SetYTitle("<#sigma_{x}> [#mum]");
+    h1->SetXTitle("t_{drift} [#mus]");
+    h1->GetXaxis()->SetRange(2, kNTB-1); h1->Draw("pc");
+
+    t->Draw("z:t>>h2y(23, 0.1, 2.4, 25, 0., 2.5)","sy*(1)", "lego2fb");
+    h2 = (TH2F*)gROOT->FindObject("h2y");
+    printf("  const Double_t sy[24][25]={\n");
+    for(Int_t ix=1; ix<=h2->GetNbinsX(); ix++){
+      printf("    {");
+      for(Int_t iy=1; iy<h2->GetNbinsY(); iy++){
+        printf("%6.4f ", h2->GetBinContent(ix, iy));
+      }
+      printf("%6.4f},\n", h2->GetBinContent(ix, h2->GetNbinsY()));
+    }
+    printf("  };\n");
+    ((TVirtualPad*)l->At(1))->cd();
+    h1 = h2->ProjectionX("hsy_pxx"); h1->Scale(1.e4/kND); h1->SetMarkerStyle(24);
+    h1->SetYTitle("<#sigma_{y}> [#mum]");
+    h1->SetXTitle("t_{drift} [#mus]");
+    h1->GetXaxis()->SetRange(2, kNTB-1); h1->Draw("pc");
+    return kTRUE;
+  case kMean:
+    if(!(t = (TTree*)fResults->At(kMean))) break;
+    t->Draw("z:t>>h2x(23, 0.1, 2.4, 25, 0., 2.5)","dx*(1)", "goff");
+    h2 = (TH2F*)gROOT->FindObject("h2x");
+    printf("  const Double_t dx[24][25]={\n");
+    for(Int_t ix=1; ix<=h2->GetNbinsX(); ix++){
+      printf("    {");
+      for(Int_t iy=1; iy<h2->GetNbinsY(); iy++){
+        printf("%6.4f ", h2->GetBinContent(ix, iy));
+      }
+      printf("%6.4f},\n", h2->GetBinContent(ix, h2->GetNbinsY()));
+    }
+    printf("  };\n");
+    gPad->Divide(2, 1, 1.e-5, 1.e-5); l = gPad->GetListOfPrimitives();
+    ((TVirtualPad*)l->At(0))->cd();
+    h1 = h2->ProjectionX("hdx_pxx"); h1->Scale(1.e4/kND); h1->SetMarkerStyle(24);
+    h1->SetYTitle("<dx> [#mum]");
+    h1->SetXTitle("t_{drift} [#mus]");
+    h1->GetXaxis()->SetRange(2, kNTB-1); h1->Draw("pc");
+
+    t->Draw("z:t>>h2y(23, 0.1, 2.4, 25, 0., 2.5)","dy*(1)", "goff");
+    h2 = (TH2F*)gROOT->FindObject("h2y");
+    printf("  const Double_t dy[24][25]={\n");
+    for(Int_t ix=1; ix<=h2->GetNbinsX(); ix++){
+      printf("    {");
+      for(Int_t iy=1; iy<h2->GetNbinsY(); iy++){
+        printf("%6.4f ", h2->GetBinContent(ix, iy));
+      }
+      printf("%6.4f},\n", h2->GetBinContent(ix, h2->GetNbinsY()));
+    }
+    printf("  };\n");
+    ((TVirtualPad*)l->At(1))->cd();
+    h1 = h2->ProjectionX("hdy_pxx"); h1->Scale(1.e4/kND); h1->SetMarkerStyle(24);
+    h1->SetYTitle("<dy> [#mum]");
+    h1->SetXTitle("t_{drift} [#mus]");
+    h1->GetXaxis()->SetRange(2, kNTB-1); h1->Draw("pc");
+
+    return kTRUE;
+  default:
+    break;
+  }
+  AliWarning("No container/data found.");
+  return kFALSE;
+}
+
+//_______________________________________________________
+TObjArray* AliTRDclusterResolution::Histos()
+{
+// Retrieve histograms array if already build or build it
+
+  if(fContainer) return fContainer;
+  fContainer = new TObjArray(kNtasks);
+  //fContainer->SetOwner(kTRUE);
+
+  TH3S *h3 = 0x0;
+  TObjArray *arr = 0x0;
+
+  fContainer->AddAt(arr = new TObjArray(2*AliTRDgeometry::kNlayer), kCenter);
+  arr->SetName("Center");
+  for(Int_t il=0; il<AliTRDgeometry::kNlayer; il++){
+    // add resolution plot for each layer
+    if(!(h3=(TH3S*)gROOT->FindObject(Form("hCenResLy%d", il)))){ 
+      h3 = new TH3S(
+        Form("hCenResLy%d", il), 
+        Form(" ly [%d]", il), 
+        kNTB, fAt->GetBinLowEdge(1), fAt->GetBinUpEdge(kNTB),   // x
+        51, -.51, .51, // y 
+        60, -.3, .3); // dy
+      h3->SetXTitle("x [#mus]");
+      h3->SetYTitle("y [pw]");
+      h3->SetZTitle("#Delta y[cm]");
+    } h3->Reset();
+    arr->AddAt(h3, il);
+    // add Pull plot for each layer
+    if(!(h3=(TH3S*)gROOT->FindObject(Form("hCenPullLy%d", il)))){ 
+      h3 = new TH3S(
+        Form("hCenPullLy%d", il), 
+        Form(" ly [%d]", il), 
+        kNTB, fAt->GetBinLowEdge(1), fAt->GetBinUpEdge(kNTB),   // x
+        51, -.51, .51, // y 
+        60, -4., 4.); // dy
+      h3->SetXTitle("x [#mus]");
+      h3->SetYTitle("y [pw]");
+      h3->SetZTitle("#Delta y/#sigma_{y}");
+    } h3->Reset();
+    arr->AddAt(h3, AliTRDgeometry::kNlayer+il);
+  }
+
+  if(!(h3 = (TH3S*)gROOT->FindObject("Charge"))){
+    h3 = new TH3S("Charge", "dy=f(q)", 50, 2.2, 7.5, 60, -.3, .3, 60, -4., 4.);
+    h3->SetXTitle("log(q) [a.u.]");
+    h3->SetYTitle("#Delta y[cm]");
+    h3->SetZTitle("#Delta y/#sigma_{y}");
+  }
+  fContainer->AddAt(h3, kQRes);
+
+  fContainer->AddAt(arr = new TObjArray(kNTB), kSigm);
+  arr->SetName("Resolution");
+  for(Int_t ix=0; ix<kNTB; ix++){
+    if(!(h3=(TH3S*)gROOT->FindObject(Form("hr_x%02d", ix)))){
+      h3 = new TH3S(
+        Form("hr_x%02d", ix), 
+        Form(" t_{drift}(%3.1f-%3.1f)[#mus]", fAt->GetBinLowEdge(ix+1), fAt->GetBinUpEdge(ix+1)), 
+        kND, 0., 2.5,   // z 
+        35, -.35, .35, // tgp 
+        60, -.3, .3); // dy
+      h3->SetXTitle("z [mm]");
+      h3->SetYTitle("tg#phi");
+      h3->SetZTitle("#Delta y[cm]");
+    }
+    arr->AddAt(h3, ix);
+  }
+
+  fContainer->AddAt(arr = new TObjArray(kNTB), kMean);
+  arr->SetName("Systematics");
+  for(Int_t ix=0; ix<kNTB; ix++){
+    if(!(h3=(TH3S*)gROOT->FindObject(Form("hs_x%02d", ix)))){
+      h3 = new TH3S(
+        Form("hs_x%02d", ix), 
+        Form(" t_{drift}(%3.1f-%3.1f)[#mus]", fAt->GetBinLowEdge(ix+1), fAt->GetBinUpEdge(ix+1)), 
+        kND, 0., 2.5,   // z 
+        35, -.35, .35, // tgp-h tgt 
+        60, -.3, .3); // dy
+      h3->SetXTitle("z [mm]");
+      h3->SetYTitle("tg(#phi) - h*tg(#theta)");
+      h3->SetZTitle("#Delta y[cm]");
+    }
+    arr->AddAt(h3, ix);
+  }
+
+  return fContainer;
+}
+
+//_______________________________________________________
+void AliTRDclusterResolution::Exec(Option_t *)
+{
+// Fill container histograms
+
+  if(!HasExB()) AliWarning("ExB was not set. Call SetExB() before running the task.");
+
+  Int_t det, t;
+  Float_t x, y, z, q, dy, dydx, dzdx, cov[3], covcl[3];
+  TH3S *h3 = 0x0;
+
+  // define limits around ExB for which x contribution is negligible
+  const Float_t kDtgPhi = 3.5e-2; //(+- 2 deg)
+
+  TObjArray *arr0 = (TObjArray*)fContainer->At(kCenter);
+  TObjArray *arr1 = (TObjArray*)fContainer->At(kSigm);
+  TObjArray *arr2 = (TObjArray*)fContainer->At(kMean);
+
+  const AliTRDclusterInfo *cli = 0x0;
+  TIterator *iter=fInfo->MakeIterator();
+  while((cli=dynamic_cast<AliTRDclusterInfo*>((*iter)()))){
+    cli->GetCluster(det, x, y, z, q, t, covcl);
+    if(fDet>=0 && fDet!=det) continue;
+    
+    dy = cli->GetResolution();
+    cli->GetGlobalPosition(y, z, dydx, dzdx, &cov[0]);
+
+    // resolution as a function of cluster charge
+    // only for phi equal exB 
+    if(TMath::Abs(dydx-fExB) < kDtgPhi){
+      h3 = (TH3S*)fContainer->At(kQRes);
+      h3->Fill(TMath::Log(q), dy, dy/TMath::Sqrt(covcl[0]));
+
+      printf("q=%f Log(q)=%f dy=%f pull=%f\n",q, TMath::Log(q), dy, dy/TMath::Sqrt(covcl[0]));
+    }
+
+    // do not use problematic clusters in resolution analysis
+    // TODO define limits as calibration aware (gain) !!
+    if(q<20. || q>250.) continue;
+
+    x = (t+.5)*fgkTimeBinLength; // conservative approach !!
+
+    // resolution as a function of y displacement from pad center
+    // only for phi equal exB
+    if(TMath::Abs(dydx-fExB) < kDtgPhi/* &&
+       TMath::Abs(x-0.675)<0.225*/){
+      Int_t ly(AliTRDgeometry::GetLayer(det));
+      h3 = (TH3S*)arr0->At(ly);
+      h3->Fill(x, cli->GetYDisplacement(), dy);
+      h3 = (TH3S*)arr0->At(AliTRDgeometry::kNlayer+ly);
+      h3->Fill(x, cli->GetYDisplacement(), dy/TMath::Sqrt(covcl[0]));
+    }
+
+    Int_t ix = fAt->FindBin(x);
+    if(ix==0 || ix == fAt->GetNbins()+1){
+      AliWarning(Form("Drift time %3.1f outside allowed range", x));
+      continue;
+    }
+
+    // fill histo for resolution (sigma)
+    ((TH3S*)arr1->At(ix-1))->Fill(10.*cli->GetAnisochronity(), dydx, dy);
+
+    // fill histo for systematic (mean)
+    ((TH3S*)arr2->At(ix-1))->Fill(10.*cli->GetAnisochronity(), dydx-cli->GetTilt()*dzdx, dy);  
+  }
+  PostData(0, fContainer);
+}
+
+
+//_______________________________________________________
+Bool_t AliTRDclusterResolution::PostProcess()
+{
+  if(!fContainer) return kFALSE;
+  if(!HasExB()) AliWarning("ExB was not set. Call SetExB() before running the post processing.");
+  
+  TObjArray *arr = 0x0;
+  TTree *t=0x0;
+  if(!fResults){
+    TGraphErrors *g = 0x0;
+    fResults = new TObjArray(kNtasks);
+    fResults->SetOwner();
+    fResults->AddAt(arr = new TObjArray(3), kQRes);
+    arr->SetOwner();
+    arr->AddAt(g = new TGraphErrors(), 0);
+    g->SetLineColor(kBlue); g->SetMarkerColor(kBlue);
+    g->SetMarkerStyle(7); 
+    arr->AddAt(g = new TGraphErrors(), 1);
+    g->SetLineColor(kRed); g->SetMarkerColor(kRed);
+    g->SetMarkerStyle(23); 
+    arr->AddAt(g = new TGraphErrors(), 2);
+    g->SetLineColor(kGreen); g->SetMarkerColor(kGreen);
+    g->SetMarkerStyle(7); 
+
+    // pad center dependence
+    fResults->AddAt(arr = new TObjArray(AliTRDgeometry::kNlayer+1), kCenter);
+    arr->SetOwner();
+    arr->AddAt(
+    t = new TTree("cent", "dy=f(y,x,ly)"), 0);
+    t->Branch("ly", &fLy, "ly/B");
+    t->Branch("x", &fX, "x/F");
+    t->Branch("y", &fY, "y/F");
+    t->Branch("m", &fR[0], "m[2]/F");
+    t->Branch("s", &fR[2], "s[2]/F");
+    t->Branch("pm", &fP[0], "pm[2]/F");
+    t->Branch("ps", &fP[2], "ps[2]/F");
+    for(Int_t il=1; il<=AliTRDgeometry::kNlayer; il++){
+      arr->AddAt(g = new TGraphErrors(), il);
+      g->SetLineColor(il); g->SetLineStyle(il);
+      g->SetMarkerColor(il);g->SetMarkerStyle(4); 
+    }
+
+
+    fResults->AddAt(t = new TTree("sigm", "dy=f(dw,x,dydx)"), kSigm);
+    t->Branch("t", &fX, "t/F");
+    t->Branch("z", &fZ, "z/F");
+    t->Branch("sx", &fR[0], "sx[2]/F");
+    t->Branch("sy", &fR[2], "sy[2]/F");
+
+
+    fResults->AddAt(t = new TTree("mean", "dy=f(dw,x,dydx - h dzdx)"), kMean);
+    t->Branch("t", &fX, "t/F");
+    t->Branch("z", &fZ, "z/F");
+    t->Branch("dx", &fR[0], "dx[2]/F");
+    t->Branch("dy", &fR[2], "dy[2]/F");
+  } else {
+    TObject *o = 0x0;
+    TIterator *iter=fResults->MakeIterator();
+    while((o=((*iter)()))) o->Clear(); // maybe it is wrong but we should never reach this point
+  }
+  
+  // precalculated value of tg^2(alpha_L)
+  Double_t exb2 = fExB*fExB;
+  // square of the mean value of sigma drift length.
+  // has to come from previous calibration 
+  //Double_t sxd2 = 1.;// [mm^2]
+
+  printf("ExB[%e] ExB2[%e]\n", fExB, exb2);
+
+  // process resolution dependency on charge
+  if(HasProcess(kQRes)) ProcessCharge();
+  
+  // process resolution dependency on y displacement
+  if(HasProcess(kCenter)) ProcessCenterPad();
+
+  // process resolution dependency on drift legth and drift cell width
+  if(HasProcess(kSigm)) ProcessSigma();
+
+  // process systematic shift on drift legth and drift cell width
+  if(HasProcess(kMean)) ProcessMean();
+
+  return kTRUE;
+}
+
+//_______________________________________________________
+Bool_t AliTRDclusterResolution::SetExB(Int_t det, Int_t col, Int_t row)
+{
+  // check OCDB
+  AliCDBManager *cdb = AliCDBManager::Instance();
+  if(cdb->GetRun() < 0){
+    AliError("OCDB manager not properly initialized");
+    return kFALSE;
+  }
+
+  // check magnetic field
+  if(TMath::Abs(AliTracker::GetBz()) < 1.e-10){
+    AliWarning("B=0. Magnetic field may not be initialized. Continue if you know what you are doing !");
+  }
+
+  // set reference detector if any
+  if(det>=0 && det<AliTRDgeometry::kNdet) fDet = det;
+  else det = 0;
+
+  AliTRDcalibDB *fCalibration  = AliTRDcalibDB::Instance();
+  AliTRDCalROC  *fCalVdriftROC = fCalibration->GetVdriftROC(det);
+  const AliTRDCalDet  *fCalVdriftDet = fCalibration->GetVdriftDet();
+
+  fVdrift = fCalVdriftDet->GetValue(det) * fCalVdriftROC->GetValue(col, row);
+  fExB   = AliTRDCommonParam::Instance()->GetOmegaTau(fVdrift);
+  SetBit(kExB);
+  return kTRUE;
+}
+
+//_______________________________________________________
+void AliTRDclusterResolution::SetVisual()
+{
+  if(fCanvas) return;
+  fCanvas = new TCanvas("clResCanvas", "Cluster Resolution Visualization", 10, 10, 600, 600);
+}
+
+//_______________________________________________________
+void AliTRDclusterResolution::ProcessCharge()
+{
+// Resolution as a function of cluster charge.
+//
+// As described in the function ProcessCenterPad() the error parameterization for clusters for phi = a_L can be 
+// written as:
+// BEGIN_LATEX
+// #sigma_{y}^{2} = #sigma_{y}^{2}|_{B=0} + tg^{2}(#alpha_{L})*#sigma_{x}^{2}
+// END_LATEX
+// with the contribution in case of B=0 given by:
+// BEGIN_LATEX
+// #sigma_{y}|_{B=0} = #sigma_{diff}*Gauss(0, s_{ly}) + #delta_{#sigma}(q)
+// END_LATEX
+// which further can be simplified to:
+// BEGIN_LATEX
+// <#sigma_{y}|_{B=0}>(q) = <#sigma_{y}> + #delta_{#sigma}(q)
+// <#sigma_{y}> = #int{f(q)#sigma_{y}dq}
+// END_LATEX
+// The results for s_y and f(q) are displayed below:
+//Begin_Html
+//<img src="TRD/clusterQerror.gif">
+//End_Html
+// The function has to extended to accomodate gain calibration scalling and errors.
+//
+// Author
+// Alexandru Bercuci <A.Bercuci@gsi.de>
+
+  TH2I *h2 = 0x0;
+  if(!(h2 = (TH2I*)fContainer->At(kQRes))) {
+    AliWarning("Missing dy=f(Q) histo");
+    return;
+  }
+  TF1 f("f", "gaus", -.5, .5);
+  TAxis *ax = 0x0;
+  TH1D *h1 = 0x0;
+
+  // compute mean error on x
+  Double_t s2x = 0.; 
+  for(Int_t ix=5; ix<kNTB; ix++){
+    // retrieve error on the drift length
+    s2x += AliTRDcluster::GetSX(ix);
+  }
+  s2x /= (kNTB-5); s2x *= s2x;
+  Double_t exb2 = fExB*fExB;
+
+  TObjArray *arr = (TObjArray*)fResults->At(kQRes);
+  TGraphErrors *gqm = (TGraphErrors*)arr->At(0);
+  TGraphErrors *gqs = (TGraphErrors*)arr->At(1);
+  TGraphErrors *gqp = (TGraphErrors*)arr->At(2);
+  Double_t q, n = 0., entries;
+  ax = h2->GetXaxis();
+  for(Int_t ix=1; ix<=ax->GetNbins(); ix++){
+    q = TMath::Exp(ax->GetBinCenter(ix));
+    if(q<20. || q>250.) continue; // ?!
+
+    h1 = h2->ProjectionY("py", ix, ix);
+    entries = h1->GetEntries();
+    if(entries < 50) continue;
+    Adjust(&f, h1);
+    h1->Fit(&f, "Q");
+
+    // Fill sy^2 = f(q)
+    Int_t ip = gqm->GetN();
+    gqm->SetPoint(ip, q, 1.e4*f.GetParameter(1));
+    gqm->SetPointError(ip, 0., 1.e4*f.GetParError(1));
+
+    // correct sigma for ExB effect
+    gqs->SetPoint(ip, q, 1.e4*(f.GetParameter(2)*f.GetParameter(2)-exb2*s2x));
+    gqs->SetPointError(ip, 0., 1.e4*f.GetParError(2)*f.GetParameter(2));
+
+    // save probability
+    n += entries;
+    gqp->SetPoint(ip, q, entries);
+    gqp->SetPointError(ip, 0., 0./*TMath::Sqrt(entries)*/);
+  } 
+
+  // normalize probability and get mean sy
+  Double_t sm = 0., sy;
+  for(Int_t ip=gqp->GetN(); ip--;){
+    gqp->GetPoint(ip, q, entries);
+    entries/=n;
+    gqp->SetPoint(ip, q, 1.e3*entries);
+    gqs->GetPoint(ip, q, sy);
+    sm += entries*sy;
+  }
+
+  // error parametrization s(q) = <sy> + b(1/q-1/q0)
+  TF1 fq("fq", "[0] + [1]/x", 20., 250.);
+  gqs->Fit(&fq/*, "W"*/);
+  printf("sm=%f [0]=%f [1]=%f\n", 1.e-4*sm, fq.GetParameter(0), fq.GetParameter(1));
+  printf("  const Float_t sq0inv = %f; // [1/q0]\n", (sm-fq.GetParameter(0))/fq.GetParameter(1));
+  printf("  const Float_t sqb    = %f; // [cm]\n", 1.e-4*fq.GetParameter(1));
+}
+
+//_______________________________________________________
+void AliTRDclusterResolution::ProcessCenterPad()
+{
+// Resolution as a function of y displacement from pad center and drift length.
+//
+// Since the error parameterization of cluster r-phi position can be written as (see AliTRDcluster::SetSigmaY2()):
+// BEGIN_LATEX
+// #sigma_{y}^{2} = (#sigma_{diff}*Gauss(0, s_{ly}) + #delta_{#sigma}(q))^{2} + tg^{2}(#alpha_{L})*#sigma_{x}^{2} + tg^{2}(#phi-#alpha_{L})*#sigma_{x}^{2}+[tg(#phi-#alpha_{L})*tg(#alpha_{L})*x]^{2}/12
+// END_LATEX
+// one can see that for phi = a_L one gets the following expression:
+// BEGIN_LATEX
+// #sigma_{y}^{2} = #sigma_{y}^{2}|_{B=0} + tg^{2}(#alpha_{L})*#sigma_{x}^{2}
+// END_LATEX
+// where we have explicitely marked the remaining term in case of absence of magnetic field. Thus one can use the 
+// previous equation to estimate s_y for B=0 and than by comparing in magnetic field conditions one can get the s_x.
+// This is a simplified method to determine the error parameterization for s_x and s_y as compared to the one 
+// implemented in ProcessSigma(). For more details on cluster error parameterization please see also 
+// AliTRDcluster::SetSigmaY2()
+// 
+// The representation of dy=f(y_cen, x_drift| layer) can be also used to estimate the systematic shift in the r-phi 
+// coordinate resulting from imperfection in the cluster shape parameterization. From the expresion of the shift derived 
+// in ProcessMean() with phi=exb one gets: 
+// BEGIN_LATEX
+// <#Delta y>= <#delta x> * (tg(#alpha_{L})-h*dz/dx) + <#delta y - #delta x * tg(#alpha_{L})>
+// <#Delta y>(y_{cen})= -h*<#delta x>(x_{drift}, q_{cl}) * dz/dx + #delta y(y_{cen}, ...)
+// END_LATEX
+// where all dependences are made explicit. This last expression can be used in two ways:
+//   - by average on the dz/dx we can determine directly dy (the method implemented here) 
+//   - by plotting as a function of dzdx one can determine both dx and dy components in an independent method.
+//Begin_Html
+//<img src="TRD/clusterYcorr.gif">
+//End_Html
+// Author
+// Alexandru Bercuci <A.Bercuci@gsi.de>
+
+  TObjArray *arr = (TObjArray*)fContainer->At(kCenter);
+  if(!arr) {
+    AliWarning("Missing dy=f(y | x, ly) container");
+    return;
+  }
+  Double_t exb2 = fExB*fExB;
+  Float_t s[AliTRDgeometry::kNlayer];
+  TF1 f("f", "gaus", -.5, .5);
+  TF1 fp("fp", "gaus", -3.5, 3.5);
+
+  TH1D *h1 = 0x0; TH2F *h2 = 0x0; TH3S *h3r=0x0, *h3p=0x0;
+  TObjArray *arrRes = (TObjArray*)fResults->At(kCenter);
+  TTree *t = (TTree*)arrRes->At(0);
+  TGraphErrors *gs = 0x0;
+  TAxis *ax = 0x0;
+
+  printf("  const Float_t lSy[6][24] = {\n      {");
+  const Int_t nl = AliTRDgeometry::kNlayer;
+  for(Int_t il=0; il<nl; il++){
+    if(!(h3r = (TH3S*)arr->At(il))) continue;
+    if(!(h3p = (TH3S*)arr->At(nl+il))) continue;
+    gs = (TGraphErrors*)arrRes->At(il+1);
+    fLy = il;
+//    printf("Ly[%d]\n", il);
+    for(Int_t ix=1; ix<=h3r->GetXaxis()->GetNbins(); ix++){
+      ax = h3r->GetXaxis(); ax->SetRange(ix, ix);
+      ax = h3p->GetXaxis(); ax->SetRange(ix, ix);
+      fX  = ax->GetBinCenter(ix);
+//      printf("  x[%2d]=%4.2f\n", ix, fX);
+      for(Int_t iy=1; iy<=h3r->GetYaxis()->GetNbins(); iy++){
+        ax = h3r->GetYaxis(); ax->SetRange(iy, iy);
+        ax = h3p->GetYaxis(); ax->SetRange(iy, iy);
+        fY  = ax->GetBinCenter(iy);
+//        printf("    y[%2d]=%5.2f\n", iy, fY);
+        // finish navigation in the HnSparse
+
+        h1 = (TH1D*)h3r->Project3D("z");
+        Int_t entries = (Int_t)h1->Integral();
+        if(entries < 50) continue;
+        //Adjust(&f, h1);
+        h1->Fit(&f, "QN");
+    
+        // Fill sy,my=f(y_w,x,ly)
+        fR[0] = f.GetParameter(1); fR[1] = f.GetParError(1);
+        fR[2] = f.GetParameter(2); fR[3] = f.GetParError(2);
+
+        h1 = (TH1D*)h3p->Project3D("z");
+        h1->Fit(&fp, "QN");
+        fP[0] = fp.GetParameter(1); fP[1] = fp.GetParError(1);
+        fP[2] = fp.GetParameter(2); fP[3] = fp.GetParError(2);
+
+        //printf("ly[%d] x[%3.1f] y[%+5.2f] m[%5.3f] s[%5.3f] \n", fLy, fX, fY, fR[0], fR[2]);
+        t->Fill();
+
+
+      }
+    }
+    t->Draw("y:x>>h(24, 0., 2.4, 51, -.51, .51)",
+            Form("s[0]*(ly==%d&&abs(m[0])<1.e-1)", fLy),
+            "goff");
+    h2=(TH2F*)gROOT->FindObject("h");
+    f.FixParameter(1, 0.);
+    Int_t n = h2->GetXaxis()->GetNbins(), nn(0); s[il]=0.;
+    printf("    {");
+    for(Int_t ix=1; ix<=n; ix++){
+      ax = h2->GetXaxis();
+      fX  = ax->GetBinCenter(ix);
+      h1 = h2->ProjectionY("hCenPy", ix, ix);
+      //if((Int_t)h1->Integral() < 1.e-10) continue; 
+
+      // Apply lorentz angle correction
+      // retrieve error on the drift length
+      Double_t s2x = AliTRDcluster::GetSX(ix-1); s2x *= s2x;
+      Int_t nnn = 0;
+      for(Int_t iy=1; iy<=h1->GetNbinsX(); iy++){
+        Double_t s2 = h1->GetBinContent(iy); s2*= s2;
+        // sigma square corrected for Lorentz angle
+        // s2 = s2_y(y_w,x)+exb2*s2_x
+        Double_t sy = TMath::Sqrt(TMath::Max(s2 - exb2*s2x, Double_t(0.)));
+        if(sy<1.e-20) continue;
+        h1->SetBinContent(iy, sy); nnn++;
+        printf("s[%6.2f] sx[%6.2f] sy[%6.2f]\n",
+        1.e4*TMath::Sqrt(s2), 1.e4*TMath::Abs(fExB*AliTRDcluster::GetSX(ix-1)), 
+        1.e4*h1->GetBinContent(iy));
+      }
+      // do fit only if enough data
+      Double_t sPRF = 0.;
+      if(nnn>5){
+        h1->Fit(&f, "QN");
+        sPRF = f.GetParameter(2);
+        nn++;
+      }
+      s[il]+=sPRF;
+      printf("%6.4f,%s", sPRF, ix%6?" ":"\n     ");
+      Int_t jx = gs->GetN();
+      gs->SetPoint(jx, fX, 1.e4*sPRF);
+      gs->SetPointError(jx, 0., 0./*f.GetParError(0)*/);
+    }
+    printf("\b},\n");
+    s[il]/=nn;
+
+    f.ReleaseParameter(2);
+
+
+    if(!fCanvas) continue;
+    h2->Draw("lego2fb");
+    fCanvas->Modified(); fCanvas->Update();
+    if(IsSaveAs()) fCanvas->SaveAs(Form("Figures/ProcessCenter_ly[%d].gif", fLy));
+    else gSystem->Sleep(100);
+  }
+  printf("  };\n");
+  printf("  const Float_t lPRF[] = {"
+    "%5.3f, %5.3f, %5.3f, %5.3f, %5.3f, %5.3f};\n",
+    s[0], s[1], s[2], s[3], s[4], s[5]);
+}
+
+//_______________________________________________________
+void AliTRDclusterResolution::ProcessSigma()
+{
+// As the r-phi coordinate is the only one which is measured by the TRD detector we have to rely on it to
+// estimate both the radial (x) and r-phi (y) errors. This method is based on the following assumptions. 
+// The measured error in the y direction is the sum of the intrinsic contribution of the r-phi measurement
+// with the contribution of the radial measurement - because x is not a parameter of Alice track model (Kalman).
+// BEGIN_LATEX
+// #sigma^{2}|_{y} = #sigma^{2}_{y*} + #sigma^{2}_{x*}   
+// END_LATEX
+// In the general case 
+// BEGIN_LATEX
+// #sigma^{2}_{y*} = #sigma^{2}_{y} + tg^{2}(#alpha_{L})#sigma^{2}_{x_{drift}}   
+// #sigma^{2}_{x*} = tg^{2}(#phi - #alpha_{L})*(#sigma^{2}_{x_{drift}} + #sigma^{2}_{x_{0}} + tg^{2}(#alpha_{L})*x^{2}/12)
+// END_LATEX
+// where we have explicitely show the lorentz angle correction on y and the projection of radial component on the y
+// direction through the track angle in the bending plane (phi). Also we have shown that the radial component in the
+// last equation has twp terms, the drift and the misalignment (x_0). For ideal geometry or known misalignment one 
+// can solve the equation
+// BEGIN_LATEX
+// #sigma^{2}|_{y} = tg^{2}(#phi - #alpha_{L})*(#sigma^{2}_{x} + tg^{2}(#alpha_{L})*x^{2}/12)+ [#sigma^{2}_{y} + tg^{2}(#alpha_{L})#sigma^{2}_{x}]
+// END_LATEX
+// by fitting a straight line:
+// BEGIN_LATEX
+// #sigma^{2}|_{y} = a(x_{cl}, z_{cl}) * tg^{2}(#phi - #alpha_{L}) + b(x_{cl}, z_{cl})
+// END_LATEX
+// the error parameterization will be given by:
+// BEGIN_LATEX
+// #sigma_{x} (x_{cl}, z_{cl}) = #sqrt{a(x_{cl}, z_{cl}) - tg^{2}(#alpha_{L})*x^{2}/12}
+// #sigma_{y} (x_{cl}, z_{cl}) = #sqrt{b(x_{cl}, z_{cl}) - #sigma^{2}_{x} (x_{cl}, z_{cl}) * tg^{2}(#alpha_{L})}
+// END_LATEX
+// Below there is an example of such dependency. 
+//Begin_Html
+//<img src="TRD/clusterSigmaMethod.gif">
+//End_Html
+//
+// The error parameterization obtained by this method are implemented in the functions AliTRDcluster::GetSX() and
+// AliTRDcluster::GetSYdrift(). For an independent method to determine s_y as a function of drift length check the 
+// function ProcessCenterPad(). One has to keep in mind that while this method return the mean s_y over the distance
+// to pad center distribution the other method returns the *STANDARD* value at center=0 (maximum). To recover the 
+// standard value one has to solve the obvious equation:
+// BEGIN_LATEX
+// #sigma_{y}^{STANDARD} = #frac{<#sigma_{y}>}{#int{s exp(s^{2}/#sigma) ds}}
+// END_LATEX
+// with "<s_y>" being the value calculated here and "sigma" the width of the s_y distribution calculated in 
+// ProcessCenterPad().
+//  
+// Author
+// Alexandru Bercuci <A.Bercuci@gsi.de>
+
+  TObjArray *arr = (TObjArray*)fContainer->At(kSigm);
+  if(!arr){
+    AliWarning("Missing dy=f(x_d, d_w) container");
+    return;
+  }
+
+  // init visualization
+  TGraphErrors *ggs = 0x0;
+  TGraph *line = 0x0;
+  if(fCanvas){
+    ggs = new TGraphErrors();
+    line = new TGraph();
+    line->SetLineColor(kRed);line->SetLineWidth(2);
+  }
+
+  // init logistic support
+  TF1 f("f", "gaus", -.5, .5);
+  TLinearFitter gs(1,"pol1");
+  TH1 *hFrame=0x0;
+  TH1D *h1 = 0x0; TH3S *h3=0x0;
+  TAxis *ax = 0x0;
+  Double_t exb2 = fExB*fExB, x;
+  AliTRDcluster c;
+  TTree *t = (TTree*)fResults->At(kSigm);
+  for(Int_t ix=0; ix<kNTB; ix++){
+    if(!(h3=(TH3S*)arr->At(ix))) continue;
+    c.SetPadTime(ix);
+    x = c.GetXloc(0., 1.5);
+    fX= fAt->GetBinCenter(ix+1);
+    for(Int_t iz=1; iz<=h3->GetXaxis()->GetNbins(); iz++){
+      ax = h3->GetXaxis();
+      ax->SetRange(iz, iz);
+      fZ = ax->GetBinCenter(iz);
+
+      // reset visualization
+      if(fCanvas){ 
+        new(ggs) TGraphErrors();
+        ggs->SetMarkerStyle(7);
+      }
+      gs.ClearPoints();
+
+      for(Int_t ip=1; ip<=h3->GetYaxis()->GetNbins(); ip++){
+        ax = h3->GetYaxis();
+        ax->SetRange(ip, ip); 
+        Double_t tgl = ax->GetBinCenter(ip);
+        // finish navigation in the HnSparse
+
+        //if(TMath::Abs(dydx)>0.18) continue;
+        Double_t tgg = (tgl-fExB)/(1.+tgl*fExB);
+        Double_t tgg2 = tgg*tgg;
+
+        h1 = (TH1D*)h3->Project3D("z");
+        Int_t entries = (Int_t)h1->Integral();
+        if(entries < 50) continue;
+        //Adjust(&f, h1);
+        h1->Fit(&f, "QN");
+
+        Double_t s2  = f.GetParameter(2)*f.GetParameter(2);
+        Double_t s2e = 2.*f.GetParameter(2)*f.GetParError(2);
+        // Fill sy^2 = f(tg^2(phi-a_L))
+        gs.AddPoint(&tgg2, s2, s2e);
+
+        if(!ggs) continue;
+        Int_t jp = ggs->GetN();
+        ggs->SetPoint(jp, tgg2, s2);
+        ggs->SetPointError(jp, 0., s2e);
+      }
+      // TODO here a more robust fit method has to be provided
+      // for which lower boundaries on the parameters have to 
+      // be imposed. Unfortunately the Minuit fit does not work 
+      // for the TGraph in the case of B not 0.
+      if(gs.Eval()) continue;
+
+      fR[0] = gs.GetParameter(1) - x*x*exb2/12.;
+      printf("s2x+x2=%f ang=%f s2x=%f\n", gs.GetParameter(1), x*x*exb2/12., fR[0]);
+      fR[0] = TMath::Max(fR[0], Float_t(4.e-4)); 
+
+      // s^2_y  = s0^2_y + tg^2(a_L) * s^2_x
+      // s0^2_y = f(D_L)*x + s_PRF^2 
+      fR[2]= gs.GetParameter(0)-exb2*fR[0];
+      printf("s2y+s2x=%f s2y=%f\n", fR[0], fR[2]);
+      fR[2] = TMath::Max(fR[2], Float_t(2.5e-5)); 
+      fR[0] = TMath::Sqrt(fR[0]);
+      fR[1] = .5*gs.GetParError(1)/fR[0];
+      fR[2] = TMath::Sqrt(fR[2]);
+      fR[3] = gs.GetParError(0)+exb2*exb2*gs.GetParError(1);
+      t->Fill();
+      printf("    xd=%4.2f[cm] sx=%6.1f[um] sy=%5.1f[um]\n", x, 1.e4*fR[0], 1.e4*fR[2]);
+
+      if(!fCanvas) continue;
+      fCanvas->cd(); fCanvas->SetLogx(); //fCanvas->SetLogy();
+      if(!hFrame){ 
+        fCanvas->SetMargin(0.15, 0.01, 0.1, 0.01);
+        hFrame=new TH1I("hFrame", "", 100, 0., .3);
+        hFrame->SetMinimum(0.);hFrame->SetMaximum(.005);
+        hFrame->SetXTitle("tg^{2}(#phi-#alpha_{L})");
+        hFrame->SetYTitle("#sigma^{2}y[cm^{2}]");
+        hFrame->GetYaxis()->SetTitleOffset(2.);
+        hFrame->SetLineColor(1);hFrame->SetLineWidth(1);
+        hFrame->Draw();
+      } else hFrame->Reset();
+      Double_t xx = 0., dxx=.2/50;
+      for(Int_t ip=0;ip<50;ip++){ 
+        line->SetPoint(ip, xx,  gs.GetParameter(0)+xx*gs.GetParameter(1)); 
+        xx+=dxx;
+      }
+      ggs->Draw("pl"); line->Draw("l");
+      fCanvas->Modified(); fCanvas->Update();
+      if(IsSaveAs()) fCanvas->SaveAs(Form("Figures/ProcessSigma_z[%5.3f]_x[%5.3f].gif", fZ, fX));
+      else gSystem->Sleep(100);
+    }
+  }
+  return;
+}
+
+//_______________________________________________________
+void AliTRDclusterResolution::ProcessMean()
+{
+// By this method the cluster shift in r-phi and radial directions can be estimated by comparing with the MC.
+// The resolution of the cluster corrected for pad tilt with respect to MC in the r-phi (measuring) plane can be 
+// expressed by:
+// BEGIN_LATEX
+// #Delta y=w - y_{MC}(x_{cl})
+// w = y_{cl}^{'} + h*(z_{MC}(x_{cl})-z_{cl})
+// y_{MC}(x_{cl}) = y_{0} - dy/dx*x_{cl}
+// z_{MC}(x_{cl}) = z_{0} - dz/dx*x_{cl}
+// y_{cl}^{'} = y_{cl}-x_{cl}*tg(#alpha_{L})
+// END_LATEX
+// where x_cl is the drift length attached to a cluster, y_cl is the r-phi coordinate of the cluster measured by
+// charge sharing on adjacent pads and y_0 and z_0 are MC reference points (as example the track references at 
+// entrance/exit of a chamber). If we suppose that both r-phi (y) and radial (x) coordinate of the clusters are 
+// affected by errors we can write
+// BEGIN_LATEX
+// x_{cl} = x_{cl}^{*} + #delta x 
+// y_{cl} = y_{cl}^{*} + #delta y 
+// END_LATEX 
+// where the starred components are the corrected values. Thus by definition the following quantity
+// BEGIN_LATEX
+// #Delta y^{*}= w^{*} - y_{MC}(x_{cl}^{*})
+// END_LATEX
+// has 0 average over all dependency. Using this decomposition we can write:
+// BEGIN_LATEX
+// <#Delta y>=<#Delta y^{*}> + <#delta x * (dy/dx-h*dz/dx) + #delta y - #delta x * tg(#alpha_{L})>
+// END_LATEX
+// which can be transformed to the following linear dependence:
+// BEGIN_LATEX
+// <#Delta y>= <#delta x> * (dy/dx-h*dz/dx) + <#delta y - #delta x * tg(#alpha_{L})>
+// END_LATEX
+// if expressed as function of dy/dx-h*dz/dx. Furtheremore this expression can be plotted for various clusters
+// i.e. we can explicitely introduce the diffusion (x_cl) and drift cell - anisochronity (z_cl) dependences. From 
+// plotting this dependence and linear fitting it with:
+// BEGIN_LATEX
+// <#Delta y>= a(x_{cl}, z_{cl}) * (dy/dx-h*dz/dx) + b(x_{cl}, z_{cl})
+// END_LATEX
+// the systematic shifts will be given by:
+// BEGIN_LATEX
+// #delta x (x_{cl}, z_{cl}) = a(x_{cl}, z_{cl})
+// #delta y (x_{cl}, z_{cl}) = b(x_{cl}, z_{cl}) + a(x_{cl}, z_{cl}) * tg(#alpha_{L})
+// END_LATEX
+// Below there is an example of such dependency. 
+//Begin_Html
+//<img src="TRD/clusterShiftMethod.gif">
+//End_Html
+//
+// The occurance of the radial shift is due to the following conditions 
+//   - the approximation of a constant drift velocity over the drift length (larger drift velocities close to 
+//     cathode wire plane)
+//   - the superposition of charge tails in the amplification region (first clusters appear to be located at the 
+//     anode wire)
+//   - the superposition of charge tails in the drift region (shift towards anode wire)
+//   - diffusion effects which convolute with the TRF thus enlarging it
+//   - approximate knowledge of the TRF (approximate measuring in test beam conditions) 
+// 
+// The occurance of the r-phi shift is due to the following conditions 
+//   - approximate model for cluster shape (LUT)
+//   - rounding-up problems
+//
+// The numerical results for ideal simulations for the radial and r-phi shifts are displayed below and used 
+// for the cluster reconstruction (see the functions AliTRDcluster::GetXcorr() and AliTRDcluster::GetYcorr()). 
+//Begin_Html
+//<img src="TRD/clusterShiftX.gif">
+//<img src="TRD/clusterShiftY.gif">
+//End_Html
+// More details can be found in the presentation given during the TRD
+// software meeting at the end of 2008 and beginning of year 2009, published on indico.cern.ch.
+// 
+// Author 
+// Alexandru Bercuci <A.Bercuci@gsi.de>
+
+
+  TObjArray *arr = (TObjArray*)fContainer->At(kMean);
+  if(!arr){
+    AliWarning("Missing dy=f(x_d, d_w) container");
+    return;
+  }
+
+  // init logistic support
+  TF1 f("f", "gaus", -.5, .5);
+  TF1 line("l", "[0]+[1]*x", -.15, .15);
+  TGraphErrors *gm = new TGraphErrors();
+  TH1 *hFrame=0x0;
+  TH1D *h1 = 0x0; TH3S *h3 =0x0;
+  TAxis *ax = 0x0;
+  Double_t x;
+
+  AliTRDcluster c;
+  TTree *t = (TTree*)fResults->At(kMean);
+  for(Int_t ix=0; ix<kNTB; ix++){
+    if(!(h3=(TH3S*)arr->At(ix))) continue;
+    c.SetPadTime(ix);
+    x = c.GetXloc(0., 1.5);
+    fX= fAt->GetBinCenter(ix+1);
+    for(Int_t iz=1; iz<=h3->GetXaxis()->GetNbins(); iz++){
+      ax = h3->GetXaxis();
+      ax->SetRange(iz, iz);
+      fZ = ax->GetBinCenter(iz);
+
+      // reset fitter
+      new(gm) TGraphErrors();
+      gm->SetMarkerStyle(7);
+
+      for(Int_t ip=1; ip<=h3->GetYaxis()->GetNbins(); ip++){
+        ax = h3->GetYaxis();
+        ax->SetRange(ip, ip); 
+        Double_t tgl = ax->GetBinCenter(ip);
+        // finish navigation in the HnSparse
+
+        h1 = (TH1D*)h3->Project3D("z");
+        Int_t entries = (Int_t)h1->Integral();
+        if(entries < 50) continue;
+        //Adjust(&f, h1);
+        h1->Fit(&f, "QN");
+
+        // Fill <Dy> = f(dydx - h*dzdx)
+        Int_t jp = gm->GetN();
+        gm->SetPoint(jp, tgl, f.GetParameter(1));
+        gm->SetPointError(jp, 0., f.GetParError(1));
+      }
+      if(gm->GetN()<4) continue;
+
+      gm->Fit(&line, "QN");
+      fR[0] = line.GetParameter(1); // dx
+      fR[1] = line.GetParError(1);
+      fR[2] = line.GetParameter(0) + fExB*fR[0]; // xs = dy - tg(a_L)*dx
+      t->Fill();
+      printf("    xd=%4.2f[cm] dx=%6.2f[um] dy=%6.2f[um]\n", x, 1.e4*fR[0], 1.e4*fR[2]);
+
+      if(!fCanvas) continue;
+      fCanvas->cd();
+      if(!hFrame){ 
+        fCanvas->SetMargin(0.1, 0.02, 0.1, 0.01);
+        hFrame=new TH1I("hFrame", "", 100, -.3, .3);
+        hFrame->SetMinimum(-.1);hFrame->SetMaximum(.1);
+        hFrame->SetXTitle("tg#phi-htg#theta");
+        hFrame->SetYTitle("#Delta y[cm]");
+        hFrame->GetYaxis()->SetTitleOffset(1.5);
+        hFrame->SetLineColor(1);hFrame->SetLineWidth(1);
+        hFrame->Draw();
+      } else hFrame->Reset();
+      gm->Draw("pl"); line.Draw("same");
+      fCanvas->Modified(); fCanvas->Update();
+      if(IsSaveAs()) fCanvas->SaveAs(Form("Figures/ProcessMean_Z[%5.3f]_X[%5.3f].gif", fZ, fX));
+      else gSystem->Sleep(100);
+    }
+  }
+}
diff --git a/PWG1/TRD/AliTRDclusterResolution.h b/PWG1/TRD/AliTRDclusterResolution.h
new file mode 100644 (file)
index 0000000..7bdc891
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef ALITRDCLUSTERRESOLUTION_H
+#define ALITRDCLUSTERRESOLUTION_H
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+//  TRD cluster error parameterization                  
+//  Authors:                                                              //
+//    Alexandru Bercuci <A.Bercuci@gsi.de>                                //
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef ALITRDRECOTASK_H
+#include "AliTRDrecoTask.h"
+#endif
+
+class TCanvas;
+class TObjArray;
+class TAxis;
+class AliTRDclusterResolution : public AliTRDrecoTask
+{
+public:
+  enum EAxisBinning { // bins in z and x direction
+    kNTB = 24
+   ,kND  = 25
+   ,kN   = kND*kNTB
+  };
+  enum EResultContainer { // results container type
+    kCenter = 0   // cluster2center pad calibration
+   ,kQRes   = 1   // resolution on charge dependence
+   ,kSigm   = 2   // sigma cluster as func of x and z
+   ,kMean   = 3   // shift cluster as func of x and z
+   ,kNtasks = 4   // total number os sub tasks
+  };
+  enum ECheckBits { // force setting the ExB
+    kSaveAs    = BIT(22)
+   ,kExB       = BIT(23)
+  };
+  AliTRDclusterResolution(const char *name="ClErrParam", const char *title="Cluster error monitor");
+  virtual ~AliTRDclusterResolution();
+
+  void          ConnectInputData(Option_t *);
+  void          CreateOutputObjects();
+  void          Exec(Option_t *);
+  Int_t         GetDetector() const { return fDet; }
+  inline Float_t GetExB() const;
+  inline Float_t GetVdrift() const;
+  Bool_t        GetRefFigure(Int_t ifig);
+  Bool_t        HasProcess(EResultContainer bit) const {return TESTBIT(fStatus, bit);}
+  Bool_t        HasExB() const { return TestBit(kExB);}
+
+  TObjArray*    Histos(); 
+  TObjArray*    Results() const {return fResults;}; 
+
+  Bool_t        IsVisual() const {return Bool_t(fCanvas);}
+  Bool_t        IsSaveAs() const {return TestBit(kSaveAs);}
+
+  Bool_t        PostProcess();
+  Bool_t        SetExB(Int_t det=-1, Int_t c = 70, Int_t r = 7);
+  void          SetVisual();
+  void          SetProcess(EResultContainer bit, Bool_t v = kTRUE) {v ? SETBIT(fStatus, bit) : CLRBIT(fStatus, bit);}
+  void          SetSaveAs(Bool_t v = kTRUE) {SetBit(kSaveAs, v);}
+  inline void   ResetProcess();
+
+protected:
+  void    ProcessCharge();
+  void    ProcessCenterPad();
+  void    ProcessSigma();
+  void    ProcessMean();
+
+private:
+  AliTRDclusterResolution(const AliTRDclusterResolution&);  
+  AliTRDclusterResolution& operator=(const AliTRDclusterResolution&);
+
+  TCanvas    *fCanvas; //! visualization canvas 
+  TObjArray  *fInfo;   //! list of cluster info
+  TObjArray  *fResults;// list of result graphs/histos
+  TAxis      *fAt;     //! binning in the x(radial) direction (time)
+  UChar_t    fStatus;  // steer parameter of the task
+  Short_t    fDet;     // detector (-1 for all)
+  Float_t    fExB;     // tg of the Lorentz angle
+  Float_t    fVdrift;  // mean drift velocity
+  static const Float_t fgkTimeBinLength;// time bin length (invers of sampling frequency)
+
+  // working named variables
+  UChar_t    fLy;      //! TRD plane 
+  Float_t    fX;       //! local drift length 
+  Float_t    fY;       //! local rphi offset 
+  Float_t    fZ;       //! local anode wire offset 
+  Float_t    fR[4];    //! mean/sgm resolution
+  Float_t    fP[4];    //! mean/sgm pulls
+  
+  ClassDef(AliTRDclusterResolution, 3)  // cluster resolution
+};
+
+//___________________________________________________
+inline Float_t AliTRDclusterResolution::GetExB() const
+{ 
+  if(!HasExB()){
+    printf("WARNING :: ExB was not set. Use B=0.\n");
+  }
+  return fExB;
+}
+
+//___________________________________________________
+inline Float_t AliTRDclusterResolution::GetVdrift() const
+{ 
+  if(!HasExB()){
+    printf("WARNING :: ExB was not set. Use B=0.\n");
+  }
+  return fVdrift;
+}
+
+//___________________________________________________
+inline void AliTRDclusterResolution::ResetProcess()
+{
+  CLRBIT(fStatus, kQRes);
+  CLRBIT(fStatus, kCenter);
+  CLRBIT(fStatus, kSigm);
+  CLRBIT(fStatus, kMean);
+}
+
+#endif
+
diff --git a/PWG1/TRD/AliTRDefficiency.cxx b/PWG1/TRD/AliTRDefficiency.cxx
new file mode 100644 (file)
index 0000000..1d4440e
--- /dev/null
@@ -0,0 +1,295 @@
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id: AliTRDefficiency.cxx 27496 2008-07-22 08:35:45Z cblume $ */
+
+////////////////////////////////////////////////////////////////////////////
+//                                                                        //
+//  Reconstruction QA                                                     //
+//                                                                        //
+//  Authors:                                                              //
+//    Markus Fasel <M.Fasel@gsi.de>                                       //
+//                                                                        //
+////////////////////////////////////////////////////////////////////////////
+
+#include <TClonesArray.h>
+#include <TObjArray.h>
+#include <TProfile.h>
+#include "TTreeStream.h"
+
+#include "AliPID.h"
+#include "AliESDtrack.h"
+#include "AliTrackReference.h"
+#include "AliExternalTrackParam.h"
+#include "AliTracker.h"
+#include "AliAnalysisManager.h"
+
+#include "Cal/AliTRDCalPID.h"
+#include "AliTRDefficiency.h"
+#include "info/AliTRDtrackInfo.h"
+
+ClassImp(AliTRDefficiency)
+
+//____________________________________________________________________
+AliTRDefficiency::AliTRDefficiency()
+  :AliTRDrecoTask("efficiency", "TRD barrel tracking efficiency checker")
+  ,fMissed(0x0)
+{
+  //
+  // Default constructor
+  //
+}
+
+//____________________________________________________________________
+AliTRDefficiency::~AliTRDefficiency()
+{
+  // Destructor
+  if(fMissed){
+    fMissed->Delete();
+    delete fMissed;
+  }
+}
+
+//____________________________________________________________________
+void  AliTRDefficiency::CreateOutputObjects()
+{
+  //
+  // Create output objects
+  //
+
+  OpenFile(0, "RECREATE");
+  const Int_t nbins = AliTRDCalPID::kNMom;
+  Float_t xbins[nbins+1] = {.5, .7, .9, 1.3, 1.7, 2.4, 3.5, 4.5, 5.5, 7., 9., 11.};
+
+  TH1 *h = 0x0;
+  fContainer = new TObjArray();
+  for(Int_t is=0; is<AliPID::kSPECIES; is++){
+    fContainer->Add(h = new TProfile(Form("h%s", AliTRDCalPID::GetPartSymb(is)), "", nbins, xbins));
+    h->SetLineColor(AliTRDCalPID::GetPartColor(is));
+    h->SetMarkerColor(AliTRDCalPID::GetPartColor(is));
+    h->SetMarkerStyle(7);
+  }
+  fContainer->Add(h = new TProfile("h", "", nbins, xbins));
+  h->SetMarkerStyle(7);
+} 
+
+//____________________________________________________________________
+void AliTRDefficiency::Exec(Option_t *)
+{
+  //
+  // Do it
+  //
+
+  Int_t labelsacc[10000]; 
+  memset(labelsacc, 0, sizeof(Int_t) * 10000);
+       
+  if(!fMissed){ 
+    fMissed = new TClonesArray("AliTRDtrackInfo", 10);
+    fMissed->SetOwner();
+  }
+
+  Float_t mom;
+  Int_t selection[10000], nselect = 0;
+  ULong_t status; Int_t pidx;
+  Int_t nTRD = 0, nTPC = 0, nMiss = 0;
+  AliTRDtrackInfo     *track = 0x0;
+  AliTrackReference     *ref = 0x0;
+  AliExternalTrackParam *esd = 0x0;
+  for(Int_t itrk=0; itrk<fTracks->GetEntriesFast(); itrk++){
+    track = (AliTRDtrackInfo*)fTracks->UncheckedAt(itrk);
+
+               if(!track->HasESDtrack()) continue;
+    status = track->GetStatus();
+
+    // missing TPC propagation - interesting for SA
+    if(!(status&AliESDtrack::kTPCout)) continue;
+
+    // missing MC info.
+    if(HasMCdata() && track->GetNTrackRefs() <= 1) continue;
+   
+    nTPC++;
+    selection[nselect++]=itrk;
+    ref  = track->GetTrackRef(0);
+    esd  = track->GetESDinfo()->GetOuterParam();
+    mom  = ref ? ref->P(): esd->P();
+    pidx = AliTRDCalPID::GetPartIndex(track->GetPDG());
+    pidx = TMath::Max(pidx, 0);
+
+    //Int_t n = track->GetNumberOfClusters(); 
+    // where are this tracklets ???
+    //if(ncls0 > ncls1) printf("%3d ESD[%3d] TRD[%3d|%3d]\n", itrk, ncls0, ncls1, n);
+    if(track->GetNumberOfClustersRefit()){ 
+      ((TProfile*)fContainer->At(pidx))->Fill(mom, 1.);
+                       labelsacc[nTRD] = track->GetLabel();
+      nTRD++;
+      continue;
+    }
+
+
+
+    Float_t xmed, xleng;
+    Int_t iref = 1; Bool_t found = kFALSE;
+    while((ref = track->GetTrackRef(iref))){
+      xmed = .5*(ref->LocalX() + track->GetTrackRef(iref-1)->LocalX());
+      xleng= (ref->LocalX() - track->GetTrackRef(iref-1)->LocalX());
+      if(TMath::Abs(xmed - 298.5) < .5 &&
+        TMath::Abs(xleng - 3.7) < .1){ 
+        found = kTRUE;
+        break;
+      }
+      iref++;
+    }
+    if(!found){ 
+      nTPC--;
+      // track missing first layer. Maybe interesting for SA.
+      continue;
+    }
+    nselect--;
+    new ((*fMissed)[nMiss]) AliTRDtrackInfo(*track);
+    nMiss++;
+  }
+  AliDebug(2, Form("%3d Tracks: ESD[%3d] TPC[%3d] TRD[%3d | %5.2f%%] Off[%d]", (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), fTracks->GetEntriesFast(), nTPC, nTRD, nTPC ? 1.E2*nTRD/float(nTPC) : 0., fMissed->GetEntriesFast()));
+
+
+  // Find double tracks
+  Float_t threshold = 10.;
+  AliTrackReference *refMiss = 0x0;
+  AliExternalTrackParam *op = 0x0;
+  AliTRDtrackInfo       *tt = 0x0;
+  for(Int_t imiss=0; imiss<nMiss; imiss++){
+    //printf("Searching missing %d ...\n", imiss);
+
+    // get outer param of missed
+    tt = (AliTRDtrackInfo*)fMissed->UncheckedAt(imiss);
+    op = tt->GetESDinfo()->GetOuterParam();
+    Double_t alpha = op->GetAlpha(), cosa = TMath::Cos(alpha), sina = TMath::Sin(alpha);
+
+    Double_t xyz[3], x0, y0, z0, x, y, z, dx, dy, dz, d;
+
+    Bool_t bFOUND = kFALSE;
+    for(Int_t iselect=0; iselect<nselect; iselect++){
+      track = (AliTRDtrackInfo*)fTracks->UncheckedAt(selection[iselect]);
+
+      // check first MC ... if available
+      d = 0;
+      for(Int_t iref=0; iref<track->GetNTrackRefs(); iref++){
+        if(!(ref = track->GetTrackRef(iref))) continue;
+        if((refMiss = tt->GetTrackRef(iref))){
+          dy = ref->LocalY() - refMiss->LocalY();
+          dz = ref->Z() - refMiss->Z();
+        } else {
+          // compare missOP with refTrackRef in LTC
+          x0 = ref->LocalX();
+          op->GetYAt(x0, AliTracker::GetBz(), y0);
+          op->GetZAt(x0, AliTracker::GetBz(), z0);
+          dy = y0 - ref->LocalY();
+          dz = z0 - ref->Z();
+        }
+        d += (dy*dy + dz*dz);
+      }
+      //printf("\td[%d] = %f N[%d]\n", selection[iselect], d, track->GetNTrackRefs());
+      if((track->GetNTrackRefs())){ 
+        d /= track->GetNTrackRefs();
+        if(d < threshold){
+          //printf("\t\tFound %2d in ref[%3d] : d[%f]\n", imiss, selection[iselect], d/track->GetNTrackRefs());
+          bFOUND = kTRUE; break;
+        }
+      }
+
+      // process outer param ... always available
+      // compare missOP with OP in GTC
+      esd = track->GetESDinfo()->GetOuterParam();
+      esd->GetXYZ(xyz);
+      x0 = esd->GetX();
+      op->GetYAt(x0, AliTracker::GetBz(), y0);
+      op->GetZAt(x0, AliTracker::GetBz(), z0);
+      x = x0*cosa - y0*sina;
+      y = x0*sina + y0*cosa;
+      z = z0;
+      dx=xyz[0]-x;
+      dy=xyz[1]-y;
+      dz=xyz[2]-z;
+      d = dx*dx+dy*dy+dz*dz;
+      //printf("\td[%d] = %f op\n", selection[iselect], d);
+      if(d < threshold){
+        //printf("\t\tFound %2d in op[%3d]  : d[%f] dx[%5.2f] dy[%5.2f] dz[%5.2f]\n", imiss, selection[iselect], d, dx, dy, dz);
+        bFOUND = kTRUE; break;
+      }
+    }
+    if(bFOUND) nTPC--;
+    else{ 
+      ref = tt->GetTrackRef(0);
+      mom = ref ? ref->P(): op->P();
+      pidx = AliTRDCalPID::GetPartIndex(tt->GetPDG());
+      pidx = TMath::Max(pidx, 0);
+      ((TProfile*)fContainer->At(pidx))->Fill(mom, 0.);
+      AliDebug(2, Form("  NOT bFOUND Id[%d] Mom[%f]\n", tt->GetTrackId(), mom));
+    }
+  }
+
+  AliDebug(2, Form("%3d Tracks: ESD[%3d] TPC[%3d] TRD[%3d | %5.2f%%] Off[%d]", (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), fTracks->GetEntriesFast(), nTPC, nTRD, nTPC ? 1.E2*nTRD/float(nTPC) : 0., fMissed->GetEntriesFast()));
+
+  //fMissed->Delete();
+       // check for double countings
+       Int_t indices[10000]; memset(indices, 0, sizeof(Int_t) * 10000);
+       TMath::Sort(nTRD, labelsacc, indices);
+       if(DebugLevel() > 2){
+       for(Int_t itk = 0; itk < nTRD - 1; itk++)
+               if(labelsacc[indices[itk]] ==labelsacc[indices[itk + 1]]) printf("Double counted MC track: %d\n", labelsacc[indices[itk]]);
+       }
+  PostData(0, fContainer);
+}
+
+
+//____________________________________________________________________
+Bool_t AliTRDefficiency::GetRefFigure(Int_t ifig)
+{
+// Steer reference figures
+
+  Bool_t bFIRST = kTRUE;
+  TProfile *h = 0x0;
+  switch(ifig){
+  case 0:
+    h = (TProfile*)fContainer->At(AliPID::kSPECIES);
+    for(Int_t is=0; is<AliPID::kSPECIES; is++){
+      h->Add((TProfile*)fContainer->At(is));
+    }
+    h->SetMarkerColor(kBlack);
+    h->SetLineColor(kBlack);
+    h->GetXaxis()->SetTitle("p [GeV/c]");
+    h->Draw("e1");
+    break;
+  case 1:
+    bFIRST = kTRUE;
+    for(Int_t is=0; is<AliPID::kSPECIES; is++){
+      if(!(h = (TProfile*)fContainer->At(is))) continue;
+      if(bFIRST){
+        h->Draw("e1");
+        h->GetXaxis()->SetTitle("p [GeV/c]");
+      } else h->Draw("same e1");
+      bFIRST = kFALSE;
+    }
+    break;
+  }
+  return kTRUE;
+}
+
+
+//____________________________________________________________________
+Bool_t AliTRDefficiency::PostProcess()
+{
+  fNRefFigures = HasMCdata() ? 2 : 1; 
+  return kTRUE;
+}
diff --git a/PWG1/TRD/AliTRDefficiency.h b/PWG1/TRD/AliTRDefficiency.h
new file mode 100644 (file)
index 0000000..ea27399
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef ALITRDEFFICIENCY_H
+#define ALITRDEFFICIENCY_H
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+/* $Id: AliTRDefficiency.h 27496 2008-07-22 08:35:45Z cblume $ */
+
+////////////////////////////////////////////////////////////////////////////
+//                                                                        //
+//  Reconstruction QA                                                     //
+//                                                                        //
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef ALITRDRECOTASK_H
+#include "AliTRDrecoTask.h"
+#endif
+
+class TObjArray;
+class TList;
+class TClonesArray;
+class TTreeSRedirector;
+class AliTRDefficiency : public AliTRDrecoTask
+{
+public:
+  AliTRDefficiency();
+  virtual ~AliTRDefficiency();
+  void    CreateOutputObjects();
+  void    Exec(Option_t *);
+  Bool_t  GetRefFigure(Int_t ifig);
+  Bool_t  PostProcess();
+
+private:
+  AliTRDefficiency(const AliTRDefficiency&);
+  AliTRDefficiency& operator=(const AliTRDefficiency&);
+
+private:
+  TClonesArray     *fMissed;            // Missed ?
+
+  ClassDef(AliTRDefficiency, 1) // TRD tracking efficiency
+};
+
+#endif
+
diff --git a/PWG1/TRD/AliTRDefficiencyMC.cxx b/PWG1/TRD/AliTRDefficiencyMC.cxx
new file mode 100644 (file)
index 0000000..1297757
--- /dev/null
@@ -0,0 +1,493 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+/* $Id: AliTRDefficiencyMC.cxx 27496 2008-07-22 08:35:45Z cblume $ */
+
+////////////////////////////////////////////////////////////////////////////
+//                                                                        //
+//  Reconstruction QA                                                     //
+//                                                                        //
+//  Authors:                                                              //
+//    Markus Fasel <M.Fasel@gsi.de>                                       //
+//                                                                        //
+////////////////////////////////////////////////////////////////////////////
+
+#include <TObjArray.h>
+#include <TClonesArray.h>
+#include <TProfile.h>
+#include <TMath.h>
+#include "TTreeStream.h"
+
+#include "AliMagF.h"
+#include "AliPID.h"
+#include "AliMathBase.h"
+#include "AliTrackReference.h"
+#include "AliAnalysisManager.h"
+
+#include "AliTRDcluster.h"
+#include "AliTRDseedV1.h"
+#include "AliTRDtrackV1.h"
+#include "Cal/AliTRDCalPID.h"
+#include "info/AliTRDtrackInfo.h"
+#include "AliTRDinfoGen.h"
+#include "AliTRDefficiencyMC.h"
+
+ClassImp(AliTRDefficiencyMC)
+
+//_____________________________________________________________________________
+AliTRDefficiencyMC::AliTRDefficiencyMC()
+  :AliTRDrecoTask("EfficiencyMC", "Combined Tracking Efficiency")
+{
+  //
+  // Default constructor
+  //
+}
+
+
+//_____________________________________________________________________________
+void AliTRDefficiencyMC::CreateOutputObjects(){
+  //
+  // Create output objects
+  //
+
+  OpenFile(0, "RECREATE");
+  fContainer = Histos();
+
+}
+
+//_____________________________________________________________________________
+void AliTRDefficiencyMC::Exec(Option_t *){
+  //
+  // Execute the task:
+  //
+  // Loop over TrackInfos
+  // 1st: check if there is a trackTRD
+  // 2nd: put conditions on the track:
+  //      - check if we did not register it before
+  //      - check if we have Track References for the track 
+  // 3rd: Register track:
+  //      - accepted if both conditions are fulfilled
+  //      - contamination if at least one condition is not fulfilled
+  // 4th: check Monte-Carlo Track wheter findable or not if there is no TRD track in this track info
+  // 5th: register MC track as rejected if findable and not jet registered
+  // Match the registers accepted and rejected and clean register rejected
+  // Fill the histograms
+  //
+  const Int_t kArraySize = 10000;     // Store indices of track references in an array
+  Int_t indexAccepted[kArraySize], indexRejected[kArraySize], indexContamination[kArraySize];
+  memset(indexAccepted, 0, sizeof(Int_t) * kArraySize);
+  memset(indexRejected, 0, sizeof(Int_t) * kArraySize);
+  memset(indexContamination, 0, sizeof(Int_t) * kArraySize);
+  Int_t naccepted = 0, nrejected = 0, ncontamination = 0;
+  Bool_t isContamination = kFALSE;
+  
+  Int_t nTrackInfos = fTracks->GetEntriesFast();
+  AliTRDtrackV1 *trackTRD = 0x0;
+  AliTRDtrackInfo *trkInf = 0x0;
+  for(Int_t itinf = 0; itinf < nTrackInfos; itinf++){
+    trkInf = dynamic_cast<AliTRDtrackInfo *>(fTracks->UncheckedAt(itinf));
+    if(!trkInf) continue;
+    if(trkInf->GetTrack() || trkInf->GetNumberOfClustersRefit()){
+      isContamination = IsRegistered(trkInf,indexAccepted,naccepted);
+      if(!trkInf->GetNTrackRefs()){
+        // We reject the track since the Monte Carlo Information is missing
+        AliDebug(1, Form("Error: Track Reference missing for Track %d", trkInf->GetLabel()));
+        isContamination = kTRUE;
+        // Debugging
+        if(trackTRD && DebugLevel() > 5) FillStreamTrackWOMC(trkInf);
+      }        
+      if(isContamination){
+        // reject kink (we count these only once)
+        if(trkInf->GetKinkIndex()) continue;
+        // Register track as contamination
+        indexContamination[ncontamination++]=itinf;
+        continue;
+      }
+      // Accept track
+      AliDebug(4, "Accept track");
+      // Register track as accepted
+      indexAccepted[naccepted++] = itinf;
+    }else{
+      if(IsFindable(trkInf)){
+        // register track as rejected if not already registered there
+        // Attention:
+        // These track infos are not!!! registered as contamination
+        if(!IsRegistered(trkInf, indexRejected, nrejected)) indexRejected[nrejected++] = itinf;
+      }
+    }
+  }
+  // we have to check if the rejected tracks are registered as found
+  // a possible source for this:
+  // first the track is not found by the barrel tracking but it is later found
+  // by the stand alone tracking, then two track info objects with the same 
+  // label would be created
+  // Attention:
+  // these tracks are not! registered as contamination
+  Int_t tmprejected[kArraySize]; Int_t nrej = nrejected;
+  memcpy(tmprejected, indexRejected, sizeof(Int_t) * nrejected);
+  nrejected = 0;
+  for(Int_t irej = 0; irej < nrej; irej++){
+    trkInf = dynamic_cast<AliTRDtrackInfo *>(fTracks->At(tmprejected[irej]));
+    if(!IsRegistered(trkInf,indexAccepted,naccepted)) indexRejected[nrejected++] = tmprejected[irej];
+  }
+  // Fill Histograms
+  FillHistograms(naccepted, &indexAccepted[0], kAccepted);
+  FillHistograms(nrejected, &indexRejected[0], kRejected);
+  FillHistograms(ncontamination, &indexContamination[0], kContamination);
+  Int_t nall = naccepted + nrejected;
+  //if(DebugLevel()>=1)
+  AliInfo(Form("%3d Tracks: MC[%3d] TRD[%3d | %5.2f%%] \n", (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), nall, naccepted, nall ? 1.E2*Float_t(naccepted)/Float_t(nall) : 0.));
+  AliInfo(Form("%3d Tracks: ALL[%3d] Contamination[%3d | %5.2f%%] \n", (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), nall + ncontamination, ncontamination, nall ? 1.E2*Float_t(ncontamination)/Float_t(nall + ncontamination) : 0.));
+
+  PostData(0, fContainer);
+}
+
+
+//_____________________________________________________________________________
+Bool_t AliTRDefficiencyMC::PostProcess()
+{
+  //
+  // Post Process 
+  //
+  // Change the histogram style
+  // For species histograms apply the colors connected with the given particle species
+  //
+  TH1 *histo = dynamic_cast<TH1 *>(fContainer->At(kEfficiencyHistogram));
+  histo->SetMarkerStyle(22);
+  histo->SetMarkerColor(kBlue);
+  histo->GetXaxis()->SetTitle("p [GeV/c]");
+  histo->GetXaxis()->SetMoreLogLabels();
+  histo->GetYaxis()->SetTitle("Efficiency [%]");
+  histo->GetYaxis()->SetRangeUser(0.99, 1.005);
+
+  histo = dynamic_cast<TH1 *>(fContainer->At(kContaminationHistogram));
+  histo->SetMarkerStyle(22);
+  histo->SetMarkerColor(kBlue);
+  histo->GetXaxis()->SetTitle("p [GeV/c]");
+  histo->GetXaxis()->SetMoreLogLabels();
+  histo->GetYaxis()->SetTitle("Contamination [%]");
+  
+  // Species Efficiency Histograms
+  for(Int_t ispec = 0; ispec < AliPID::kSPECIES; ispec++){
+    histo = dynamic_cast<TH1 *>(fContainer->At(kEfficiencySpeciesHistogram  + ispec));
+    histo->SetMarkerStyle(22);
+    histo->SetLineColor(AliTRDCalPID::GetPartColor(ispec));
+    histo->SetMarkerColor(AliTRDCalPID::GetPartColor(ispec));
+    histo->GetXaxis()->SetTitle("p [GeV/c]");
+    histo->GetXaxis()->SetMoreLogLabels();
+    histo->GetYaxis()->SetTitle("Efficiency [%]");
+    histo->GetYaxis()->SetRangeUser(0.99, 1.005);
+  }
+  
+  // Species Contamination Histograms
+  for(Int_t ispec = 0; ispec < AliPID::kSPECIES; ispec++){
+    histo = dynamic_cast<TH1 *>(fContainer->At(kContaminationSpeciesHistogram  + ispec));
+    histo->SetMarkerStyle(22);
+    histo->SetLineColor(AliTRDCalPID::GetPartColor(ispec));
+    histo->SetMarkerColor(AliTRDCalPID::GetPartColor(ispec));
+    histo->GetXaxis()->SetTitle("p [GeV/c]");
+    histo->GetXaxis()->SetMoreLogLabels();
+    histo->GetYaxis()->SetTitle("Contamination [%]");
+  }
+  
+  fNRefFigures = 6;
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
+Bool_t AliTRDefficiencyMC::GetRefFigure(Int_t ifig){
+  //
+  // Plot the histograms
+  //
+  if(ifig >= fNRefFigures) return kFALSE;
+  if(ifig < 2){
+    (dynamic_cast<TH1 *>(fContainer->At(ifig)))->Draw("e1");
+    return kTRUE;
+  }
+  switch(ifig){
+  case 2:
+    (dynamic_cast<TH1 *>(fContainer->At(kEfficiencySpeciesHistogram)))->Draw("e1");
+    for(Int_t ispec = 1; ispec < AliPID::kSPECIES; ispec++)
+      (dynamic_cast<TH1 *>(fContainer->At(kEfficiencySpeciesHistogram + ispec)))->Draw("e1same");
+    break;
+  case 3:
+    (dynamic_cast<TH1 *>(fContainer->At(kContaminationSpeciesHistogram)))->Draw("e1");
+    for(Int_t ispec = 1; ispec < AliPID::kSPECIES; ispec++)
+      (dynamic_cast<TH1 *>(fContainer->At(kContaminationSpeciesHistogram + ispec)))->Draw("e1same");
+    break;
+  case 4:
+    (dynamic_cast<TH1 *>(fContainer->At(kEfficiencyNoPID)))->Draw("e1");
+    break;
+  case 5:
+    (dynamic_cast<TH1 *>(fContainer->At(kContaminationNoPID)))->Draw("e1");
+    break;
+  }
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
+TObjArray *AliTRDefficiencyMC::Histos(){
+  //
+  // Create the histograms
+  //
+  const Int_t nbins = 11;
+
+  if(fContainer) return fContainer;
+  Float_t xbins[nbins+1] = {.5, .7, .9, 1.3, 1.7, 2.4, 3.5, 4.5, 5.5, 7., 9., 11.};
+  
+  TString species[AliPID::kSPECIES] = {"Pions", "Muons", "Electrons", "Kaons", "Protons"};
+  TString species_short[AliPID::kSPECIES] = {"Pi", "Mu", "El", "Ka", "Pr"};
+  
+  fContainer = new TObjArray();
+  fContainer->AddAt(new TProfile("trEffComb", "Combined Tracking Efficiency", nbins, xbins), kEfficiencyHistogram);
+  fContainer->AddAt(new TProfile("trContComb", "Combined Tracking Contamination", nbins, xbins), kContaminationHistogram);
+  for(Int_t ispec = 0; ispec < AliPID::kSPECIES; ispec++)
+    fContainer->AddAt(new TProfile(Form("trEffComb%s", species_short[ispec].Data()), Form("Combined Tracking Efficiency %s", species[ispec].Data()), nbins, xbins), kEfficiencySpeciesHistogram + ispec);
+  for(Int_t ispec = 0; ispec < AliPID::kSPECIES; ispec++)
+    fContainer->AddAt(new TProfile(Form("trContComb%s", species_short[ispec].Data()), Form("Combined Tracking Contamination %s", species[ispec].Data()), nbins, xbins), kContaminationSpeciesHistogram + ispec);
+  fContainer->AddAt(new TProfile("trEffCombNoPID", "Combined Tracking Efficiency", nbins, xbins), kEfficiencyNoPID);
+  fContainer->AddAt(new TProfile("trContCombNoPID", "Combined Tracking Contamination", nbins, xbins), kContaminationNoPID);
+  return fContainer;
+}
+
+//_____________________________________________________________________________
+Bool_t AliTRDefficiencyMC::IsFindable(AliTRDtrackInfo * const trkInf){
+  //
+  // Apply Cuts on the Monte Carlo track references
+  // return whether track is findable or not
+  //
+  const Float_t kAlpha = 0.349065850;
+  
+  AliDebug(10, "Analysing Track References\n");
+  // Check if track is findable
+  Double_t mom = 0.;
+  Float_t xmin = 10000.0, xmax = 0.0; 
+  Float_t ymin = 0.0, ymax = 0.0;
+  Float_t zmin = 0.0, zmax = 0.0;
+  Float_t lastx = 0.0, x = 0.0;
+  Int_t nLayers = 0;
+  Int_t sector[20];
+  AliTrackReference *trackRef = 0x0;
+  for(Int_t itr = 0; itr < trkInf->GetNTrackRefs(); itr++){
+    trackRef = trkInf->GetTrackRef(itr);
+    AliDebug(10, Form("%d. x[%f], y[%f], z[%f]\n", itr, trackRef->LocalX(), trackRef->LocalY(), trackRef->Z()));
+    x = trackRef->LocalX(); 
+        
+    // Be Sure that we are inside TRD
+    if(x < AliTRDinfoGen::GetTPCx() || x > AliTRDinfoGen::GetTOFx()) continue; 
+    sector[itr] = Int_t(trackRef->Alpha()/kAlpha);
+    if(x < xmin){
+      xmin = trackRef->LocalX();
+      ymin = trackRef->LocalY();
+      zmin = trackRef->Z();
+      mom = trackRef->P();
+    } else if(x > xmax){
+      xmax = trackRef->LocalX();
+      ymax = trackRef->LocalY();
+      zmax = trackRef->Z();
+    }
+    if(itr > 0){
+      Float_t dist = TMath::Abs(x - lastx);
+      AliDebug(10, Form("x = %f, lastx = %f, dist = %f\n", x, lastx, dist));
+      if(TMath::Abs(dist - 3.7) < 0.1) nLayers++;      // ref(i+1) has to be larger than ref(i)
+    }
+    lastx = x;
+  }
+
+  // Apply cuts
+  Bool_t findable = kTRUE;
+  if(trkInf->GetNTrackRefs() > 2 && xmax > xmin){
+    if(mom < 0.55) findable = kFALSE;                                                                  // momentum cut at 0.6
+    Double_t yangle = (ymax -ymin)/(xmax - xmin);
+    Double_t zangle = (zmax -zmin)/(xmax - xmin);
+    AliDebug(10, Form("\ntrack: y-Angle = %f, z-Angle = %f\nnLayers = %d", yangle, zangle, nLayers));
+    if(TMath::ATan(TMath::Abs(yangle)) > 45.) findable = kFALSE;
+    if(TMath::ATan(TMath::Abs(zangle)) > 45.) findable = kFALSE;
+    if(nLayers < 4) findable = kFALSE;
+    if(!trkInf->IsPrimary()) findable = kFALSE;
+    Bool_t samesec = kTRUE;
+    for(Int_t iref = 1; iref < trkInf->GetNTrackRefs(); iref++)
+      if(sector[iref] != sector[0]) samesec = kFALSE;
+    if(!samesec) findable = kFALSE;            // Discard all tracks which are passing more than one sector
+    if(DebugLevel()){
+      Double_t trackAngle = TMath::ATan(yangle);
+      Bool_t primary = trkInf->IsPrimary();
+      (*DebugStream()) << "NotFoundTrack"
+        << "Momentum="         << mom
+        << "trackAngle="<< trackAngle
+        << "NLayers="  << nLayers
+        << "Primary="  << primary
+        << "\n";
+    }
+  }
+  else
+    findable = kFALSE;
+  return findable;
+}
+
+//_____________________________________________________________________________
+void AliTRDefficiencyMC::FillHistograms(Int_t nTracks, Int_t *indices, FillingMode_t mode){
+  //
+  // Fill Histograms in three different modes:
+  // 1st tracks which are found and accepted
+  // 2nd tracks which are not found and not already counted
+  // 3rd contaminating tracks: either double counts (kinks!) or tracks with no MC hit inside TRD
+  //
+  const Int_t pid[AliPID::kSPECIES] = {211,13,11,321,2212};
+  Double_t trkmom = 0.;   // the track momentum
+  Int_t trkpid = -1;      // particle species
+  AliTRDtrackInfo *trkInf = 0x0;
+  for(Int_t itk = 0; itk < nTracks; itk++){
+    trkInf = dynamic_cast<AliTRDtrackInfo *>(fTracks->At(indices[itk]));
+    AliDebug(3, Form("Accepted MC track: %d\n", trkInf->GetLabel()));
+    if(trkInf->GetNTrackRefs()){
+      // use Monte-Carlo Information for Momentum and PID
+      trkmom = trkInf->GetTrackRef(0)->P();
+      trkpid = trkInf->GetPDG();
+    }else{
+      // Use TPC Momentum
+      trkmom = trkInf->GetTrack()->P();
+    }
+    switch(mode){
+      case kAccepted:
+        (dynamic_cast<TProfile *>(fContainer->At(kEfficiencyHistogram)))->Fill(trkmom, 1);
+        (dynamic_cast<TProfile *>(fContainer->At(kContaminationHistogram)))->Fill(trkmom, 0);
+        break;
+      case kRejected:
+        (dynamic_cast<TProfile *>(fContainer->At(kEfficiencyHistogram)))->Fill(trkmom, 0);
+        (dynamic_cast<TProfile *>(fContainer->At(kContaminationHistogram)))->Fill(trkmom, 0);
+        break;
+      case kContamination:
+        (dynamic_cast<TProfile *>(fContainer->At(kContaminationHistogram)))->Fill(trkmom, 1);
+        break;
+    }
+    // Fill species histogram
+    Int_t partSpec = -1;
+    for(Int_t ispec = 0; ispec < AliPID::kSPECIES; ispec++){
+      if(trkpid == pid[ispec]) partSpec = ispec;
+    }
+    if(partSpec >= 0){
+      switch(mode){
+        case kAccepted:
+          (dynamic_cast<TProfile *>(fContainer->At(kEfficiencySpeciesHistogram + partSpec)))->Fill(trkmom, 1);
+          (dynamic_cast<TProfile *>(fContainer->At(kContaminationSpeciesHistogram + partSpec)))->Fill(trkmom, 0);
+          break;
+        case kRejected:
+          (dynamic_cast<TProfile *>(fContainer->At(kEfficiencySpeciesHistogram + partSpec)))->Fill(trkmom, 0);          (dynamic_cast<TProfile *>(fContainer->At(kContaminationSpeciesHistogram + partSpec)))->Fill(trkmom, 0);
+          break;
+        case kContamination:
+          (dynamic_cast<TProfile *>(fContainer->At(kContaminationSpeciesHistogram + partSpec)))->Fill(trkmom, 1);
+          break;
+      }
+    } else {
+      // The particle Type is not registered
+      (dynamic_cast<TProfile *>(fContainer->At(kEfficiencyNoPID)))->Fill(trkmom, 1);
+      (dynamic_cast<TProfile *>(fContainer->At(kContaminationNoPID)))->Fill(trkmom, 1);
+    }
+  }
+}
+
+//_____________________________________________________________________________
+void AliTRDefficiencyMC::FillStreamTrackWOMC(AliTRDtrackInfo * const trkInf){
+  // fill debug stream
+  // we want to know:
+  //  1. The event number
+  //  2. The track label
+  //  3. The TRD track label
+  //  4. The frequency of the TRD Label
+  //  5. Momentum from TPC (NO STAND ALONE TRACK)
+  //  6. TPC Phi angle
+  //  7. the TRD track
+  //  8. Monte Carlo PID
+  //  9. We check the Labels of the TRD track according to them we search the maching Monte-Carlo track.
+  //     From the matching Monte-Carlo track we store trackRefs, phi and momentum
+  // 10. We may also want to keep the kink index
+  Double_t mom = trkInf->GetESDinfo()->GetOuterParam()->P();
+  Int_t event = (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry();
+  Int_t label = trkInf->GetLabel();
+  Int_t kinkIndex = trkInf->GetKinkIndex();
+  Int_t pdg = trkInf->GetPDG();
+  Double_t phiTPC = trkInf->GetESDinfo()->GetOuterParam()->Phi();
+  Int_t labelsTRD[180];        // Container for the cluster labels
+  Int_t sortlabels[360];       // Cluster Labels sorted according their occurancy
+  AliTRDseedV1 *tracklet = 0x0;
+  AliTRDcluster *c = 0x0;
+  Int_t nclusters = 0x0;
+  AliTRDtrackV1 *trackTRD = trkInf->GetTrack();
+  for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){
+    tracklet = trackTRD->GetTracklet(il);
+    if(!tracklet) continue;
+    tracklet->ResetClusterIter();
+    c = 0x0;
+    while((c = tracklet->NextCluster())) labelsTRD[nclusters++] = c->GetLabel(0);
+  }
+  // Determine Label and Frequency
+  AliMathBase::Freq(nclusters, const_cast<const Int_t *>(&labelsTRD[0]), &sortlabels[0], kTRUE);
+  Int_t labelTRD = sortlabels[0];
+  Int_t freqTRD = sortlabels[1];
+  // find the track info object matching to the TRD track
+  AliTRDtrackInfo *realtrack = 0;
+  TObjArrayIter rtiter(fTracks);
+  while((realtrack = (AliTRDtrackInfo *)rtiter())){
+    if(realtrack->GetLabel() != labelTRD) continue;
+    break;
+  }
+  TClonesArray trackRefs("AliTrackReference");
+  Int_t realPdg = -1;
+  Double_t realP = 0.;
+  Double_t realPhi = 0.;
+  if(realtrack){
+    // pack the track references into the trackRefsContainer
+    for(Int_t iref = 0; iref < realtrack->GetNTrackRefs(); iref++){
+    new(trackRefs[iref])AliTrackReference(*(realtrack->GetTrackRef(iref)));
+    }
+    realPdg = realtrack->GetPDG();
+    if(realtrack->GetNTrackRefs()){
+      realP = realtrack->GetTrackRef(0)->P();
+      realPhi = realtrack->GetTrackRef(0)->Phi();
+    }
+  }
+  (*DebugStream()) << "TrackingEffMCfake"
+    << "Event="        << event
+    << "Label=" << label
+    << "labelTRD=" << labelTRD
+    << "FreqTRDlabel=" << freqTRD
+    << "TPCp=" << mom
+    << "phiTPC=" << phiTPC
+    << "trackTRD=" << trackTRD
+    << "PDG="  << pdg
+    << "TrackRefs=" << &trackRefs
+    << "RealPDG=" << realPdg
+    << "RealP="        << realP
+    << "RealPhi" << realPhi
+    << "KinkIndex=" << kinkIndex
+    << "\n";
+}
+
+//_____________________________________________________________________________
+Bool_t AliTRDefficiencyMC::IsRegistered(AliTRDtrackInfo * const trkInf, Int_t *indices, Int_t nTracks){
+  //
+  // Checks if track is registered in a given mode
+  //
+  Bool_t isRegistered = kFALSE;
+  for(Int_t il = 0; il < nTracks; il++){
+    if((dynamic_cast<AliTRDtrackInfo *>(fTracks->At(indices[il])))->GetLabel() == trkInf->GetLabel()){
+      isRegistered = kTRUE;        
+      break;
+    }
+  }
+  return isRegistered;
+}
+
diff --git a/PWG1/TRD/AliTRDefficiencyMC.h b/PWG1/TRD/AliTRDefficiencyMC.h
new file mode 100644 (file)
index 0000000..b0890ac
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef ALITRDEFFICIENCYMC_H
+#define ALITRDEFFICIENCYMC_H
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+/* $Id: AliTRDefficiencyMC.h 27496 2008-07-22 08:35:45Z cblume $ */
+
+////////////////////////////////////////////////////////////////////////////
+//                                                                        //
+//  Reconstruction QA                                                     //
+//                                                                        //
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef ALITRDRECOTASK_H
+#include "AliTRDrecoTask.h"
+#endif
+
+class AliTRDefficiencyMC : public AliTRDrecoTask{
+public:
+  AliTRDefficiencyMC();
+  virtual ~AliTRDefficiencyMC(){;}
+  
+  void        CreateOutputObjects();
+  void        Exec(Option_t *);
+  
+  Bool_t      PostProcess();
+  TObjArray*  Histos();
+  Bool_t      GetRefFigure(Int_t ifig);
+    
+private:
+  enum{
+    kEfficiencyHistogram = 0,
+    kContaminationHistogram = 1,
+    kEfficiencySpeciesHistogram = 2,
+    kContaminationSpeciesHistogram = 7,
+    kEfficiencyNoPID = 12,
+    kContaminationNoPID = 13
+  };
+  typedef enum{
+    kAccepted = 0,
+    kRejected = 1,
+    kContamination = 2
+  } FillingMode_t;
+  AliTRDefficiencyMC(const AliTRDefficiencyMC &);
+  AliTRDefficiencyMC& operator=(const AliTRDefficiencyMC &);
+  
+  void    FillHistograms(Int_t ntracks, Int_t *indices, FillingMode_t mode);
+  void    FillStreamTrackWOMC(AliTRDtrackInfo * const trkInf);
+
+  Bool_t  IsFindable(AliTRDtrackInfo * const trkInf);
+  Bool_t  IsRegistered(AliTRDtrackInfo * const trkInf, Int_t *indices, Int_t nTracks);
+    
+  ClassDef(AliTRDefficiencyMC, 1); // Combined tracking efficiency
+};
+    
+#endif
diff --git a/PWG1/TRD/AliTRDinfoGen.cxx b/PWG1/TRD/AliTRDinfoGen.cxx
new file mode 100644 (file)
index 0000000..4dc3f59
--- /dev/null
@@ -0,0 +1,377 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+/* $Id: AliTRDinfoGen.cxx 27496 2008-07-22 08:35:45Z cblume $ */
+
+////////////////////////////////////////////////////////////////////////////
+//
+//  Tender wagon for TRD performance/calibration train
+//
+// In this wagon the information from
+//   - ESD
+//   - Friends [if available]
+//   - MC [if available]
+// are grouped into AliTRDtrackInfo objects and fed to worker tasks
+//
+//  Authors:
+//    Markus Fasel <M.Fasel@gsi.de>
+//    Alexandru Bercuci <A.Bercuci@gsi.de>
+//
+////////////////////////////////////////////////////////////////////////////
+
+#include <TClonesArray.h>
+#include <TObjArray.h>
+#include <TObject.h>
+#include <TH1F.h>
+#include <TFile.h>
+#include <TTree.h>
+#include <TROOT.h>
+#include <TChain.h>
+#include <TParticle.h>
+
+#include "AliLog.h"
+#include "AliAnalysisManager.h"
+#include "AliESDEvent.h"
+#include "AliMCEvent.h"
+#include "AliESDInputHandler.h"
+#include "AliMCEventHandler.h"
+
+#include "AliESDfriend.h"
+#include "AliESDfriendTrack.h"
+#include "AliESDHeader.h"
+#include "AliESDtrack.h"
+#include "AliMCParticle.h"
+#include "AliPID.h"
+#include "AliStack.h"
+#include "AliTRDtrackV1.h"
+#include "AliTrackReference.h"
+#include "AliTRDgeometry.h"
+#include "AliTRDcluster.h"
+#include "AliTRDseedV1.h"
+#include "TTreeStream.h"
+
+#include <cstdio>
+#include <climits>
+#include <cstring>
+#include <iostream>
+
+#include "AliTRDinfoGen.h"
+#include "info/AliTRDtrackInfo.h"
+#include "info/AliTRDeventInfo.h"
+#include "info/AliTRDv0Info.h"
+
+ClassImp(AliTRDinfoGen)
+
+const Float_t AliTRDinfoGen::fgkTPC = 290.;
+const Float_t AliTRDinfoGen::fgkTOF = 365.;
+
+//____________________________________________________________________
+AliTRDinfoGen::AliTRDinfoGen():
+  AliTRDrecoTask("infoGen", "MC-REC TRD-track list generator")
+  ,fESDev(0x0)
+  ,fMCev(0x0)
+  ,fESDfriend(0x0)
+  ,fTrackInfo(0x0)
+  ,fEventInfo(0x0)
+  ,fV0container(0x0)
+  ,fV0Info(0x0)
+{
+  //
+  // Default constructor
+  //
+
+  DefineInput(0, TChain::Class());
+  DefineOutput(0, TObjArray::Class());
+  DefineOutput(1, AliTRDeventInfo::Class());
+  DefineOutput(2, TObjArray::Class());
+}
+
+//____________________________________________________________________
+AliTRDinfoGen::~AliTRDinfoGen()
+{
+// Destructor
+  if(fTrackInfo) delete fTrackInfo; fTrackInfo = 0x0;
+  if(fEventInfo) delete fEventInfo; fEventInfo = 0x0;
+  if(fV0Info) delete fV0Info; fV0Info = 0x0;
+  if(fContainer){ 
+    fContainer->Delete(); delete fContainer;
+    fContainer = 0x0;
+  }
+  if(fV0container){ 
+    fV0container->Delete(); delete fV0container;
+    fV0container = 0x0;
+  }
+}
+
+//____________________________________________________________________
+void AliTRDinfoGen::ConnectInputData(Option_t *)
+{
+  //
+  // Link the Input Data
+  //
+  TTree *tree = dynamic_cast<TChain*>(GetInputData(0));
+  if(!tree){
+    printf("ERROR - ESD event not found");
+  } else {
+    tree->SetBranchStatus("Tracks", 1);
+    tree->SetBranchStatus("ESDfriend*",1);
+  }
+
+  AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*>(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
+  if(!esdH){
+    printf("ERROR - ESD input handler not found");
+  } else {
+    fESDev = esdH->GetEvent();
+    if(!fESDev){
+      printf("ERROR - ESD event not found");
+    } else {
+      esdH->SetActiveBranches("ESDfriend*");
+      fESDfriend = (AliESDfriend *)fESDev->FindListObject("AliESDfriend");
+    }
+  }
+  if(HasMCdata()){
+    AliMCEventHandler *mcH = dynamic_cast<AliMCEventHandler*>(AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
+    if(!mcH){ 
+      AliError("MC input handler not found");
+    } else {
+      fMCev = mcH->MCEvent();
+    }
+  }
+}
+
+//____________________________________________________________________
+void AliTRDinfoGen::CreateOutputObjects()
+{      
+  //
+  // Create Output Containers (TObjectArray containing 1D histograms)
+  //
+  fTrackInfo = new AliTRDtrackInfo();
+  fEventInfo = new AliTRDeventInfo();
+  fV0Info    = new AliTRDv0Info();
+  fContainer = new TObjArray(1000);
+  fContainer->SetOwner(kTRUE);
+  fV0container = new TObjArray(50);
+  fV0container->SetOwner(kTRUE);
+
+}
+
+//____________________________________________________________________
+void AliTRDinfoGen::Exec(Option_t *){
+  //
+  // Run the Analysis
+  //
+  if(!fESDev){
+    AliError("Failed retrieving ESD event");
+    return;
+  }
+  if(!fESDfriend){
+    AliError("Failed retrieving ESD friend event");
+    return;
+  }
+  if(HasMCdata() && !fMCev){
+    AliError("Failed retrieving MC event");
+    return;
+  }
+  fContainer->Delete();
+  fV0container->Delete();
+  fEventInfo->Delete("");
+  fESDev->SetESDfriend(fESDfriend);
+  new(fEventInfo)AliTRDeventInfo(fESDev->GetHeader(), const_cast<AliESDRun *>(fESDev->GetESDRun()));
+  
+  Bool_t *trackMap = 0x0;
+  AliStack * mStack = 0x0;
+  Int_t nTracksMC = HasMCdata() ? fMCev->GetNumberOfTracks() : 0, nTracksESD = fESDev->GetNumberOfTracks();
+  if(HasMCdata()){
+    mStack = fMCev->Stack();
+    if(!mStack){
+      AliError("Failed retrieving MC Stack");
+      return;
+    }
+    trackMap = new Bool_t[nTracksMC];
+    memset(trackMap, 0, sizeof(Bool_t) * nTracksMC);
+  }
+  
+  Int_t nTRD = 0, nTPC = 0, nclsTrklt;
+  AliDebug(2, Form("Entry[%3d] Tracks: ESD[%d] MC[%d]\n", (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), nTracksESD, nTracksMC));
+  AliESDtrack *esdTrack = 0x0;
+  AliESDfriendTrack *esdFriendTrack = 0x0;
+  TObject *calObject = 0x0;
+  AliTRDtrackV1 *track = 0x0;
+  AliTRDseedV1 *tracklet = 0x0;
+  AliTRDcluster *cl = 0x0;
+  for(Int_t itrk = 0; itrk < nTracksESD; itrk++){
+    esdTrack = fESDev->GetTrack(itrk);
+    AliDebug(3, Form("\n%3d ITS[%d] TPC[%d] TRD[%d]\n", itrk, esdTrack->GetNcls(0), esdTrack->GetNcls(1), esdTrack->GetNcls(2)));
+    if(esdTrack->GetNcls(1)) nTPC++;
+    if(esdTrack->GetNcls(2)) nTRD++;
+
+    // look at external track param
+    const AliExternalTrackParam *op = esdTrack->GetOuterParam();
+    Double_t xyz[3];
+    if(op){
+      op->GetXYZ(xyz);
+      op->Global2LocalPosition(xyz, op->GetAlpha());
+      AliDebug(3, Form("op @ X[%7.3f]\n", xyz[0]));
+    }
+
+    // read MC info
+    Int_t fPdg = -1;
+    Int_t label = -1; UInt_t alab=UINT_MAX;
+    if(HasMCdata()){
+      label = esdTrack->GetLabel(); 
+      alab = TMath::Abs(label);
+      // register the track
+      if(alab < UInt_t(nTracksMC)){ 
+        trackMap[alab] = kTRUE; 
+      } else { 
+        AliError(Form("MC label[%d] outside scope for Ev[%d] Trk[%d].", label, (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), itrk));
+        continue; 
+      }
+      AliMCParticle *mcParticle = 0x0; 
+      if(!(mcParticle = (AliMCParticle*) fMCev->GetTrack(alab))){
+        AliError(Form("MC particle label[%d] missing for Ev[%d] Trk[%d].", label, (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), itrk));
+        continue;
+      }
+      fPdg = mcParticle->Particle()->GetPdgCode();
+      Int_t nRefs = mcParticle->GetNumberOfTrackReferences();
+      Int_t iref = 0; AliTrackReference *ref = 0x0; 
+      while(iref<nRefs){
+        ref = mcParticle->GetTrackReference(iref);
+        if(ref->LocalX() > fgkTPC) break;
+        iref++;
+      }
+
+      new(fTrackInfo) AliTRDtrackInfo();
+      fTrackInfo->SetPDG(fPdg);
+      fTrackInfo->SetPrimary(mcParticle->Particle()->IsPrimary());
+      Int_t jref = iref;//, kref = 0;
+      while(jref<nRefs){
+        ref = mcParticle->GetTrackReference(jref);
+        if(ref->LocalX() > fgkTOF) break;
+        AliDebug(4, Form("  trackRef[%2d (%2d)] @ %7.3f OK", jref-iref, jref, ref->LocalX()));
+        fTrackInfo->AddTrackRef(ref);
+        jref++;
+      }
+      AliDebug(3, Form("NtrackRefs[%d(%d)]", fTrackInfo->GetNTrackRefs(), nRefs));
+    } else {
+      new (fTrackInfo) AliTRDtrackInfo();
+      fTrackInfo->SetPDG(fPdg);
+    }
+
+    // copy some relevant info to TRD track info
+    fTrackInfo->SetStatus(esdTrack->GetStatus());
+    fTrackInfo->SetTrackId(esdTrack->GetID());
+    Double_t p[AliPID::kSPECIES]; esdTrack->GetTRDpid(p);
+    fTrackInfo->SetESDpid(p);
+    fTrackInfo->SetESDpidQuality(esdTrack->GetTRDntrackletsPID());
+    fTrackInfo->SetLabel(label);
+    fTrackInfo->SetNumberOfClustersRefit(esdTrack->GetNcls(2));
+    // some other Informations which we may wish to store in order to find problematic cases
+    fTrackInfo->SetKinkIndex(esdTrack->GetKinkIndex(0));
+    fTrackInfo->SetTPCncls(static_cast<UShort_t>(esdTrack->GetNcls(1)));
+    nclsTrklt = 0;
+  
+
+    // read REC info
+    esdFriendTrack = fESDfriend->GetTrack(itrk);
+    if(esdFriendTrack){
+      Int_t icalib = 0;
+      while((calObject = esdFriendTrack->GetCalibObject(icalib++))){
+        if(strcmp(calObject->IsA()->GetName(),"AliTRDtrackV1") != 0) continue; // Look for the TRDtrack
+        if(!(track = dynamic_cast<AliTRDtrackV1*>(calObject))) break;
+        nTRD++;
+        AliDebug(4, Form("TRD track OK"));
+        // Set the clusters to unused
+        for(Int_t ipl = 0; ipl < AliTRDgeometry::kNlayer; ipl++){
+          if(!(tracklet = track->GetTracklet(ipl))) continue;
+          tracklet->ResetClusterIter();
+          while((cl = tracklet->NextCluster())) cl->Use(0);
+        }
+        fTrackInfo->SetTrack(track);
+        break;
+      }
+      AliDebug(3, Form("Ntracklets[%d]\n", fTrackInfo->GetNTracklets()));
+    } else AliDebug(3, "No ESD friends");
+    if(op) fTrackInfo->SetOuterParam(op);
+
+    if(DebugLevel() >= 1){
+      AliTRDtrackInfo info(*fTrackInfo);
+      (*DebugStream()) << "trackInfo"
+      << "TrackInfo.=" << &info
+      << "\n";
+      info.Delete("");
+    }
+  
+    fContainer->Add(new AliTRDtrackInfo(*fTrackInfo));
+    fTrackInfo->Delete("");
+  }
+  AliDebug(3, Form("%3d Tracks: TPC[%d] TRD[%d]\n", (Int_t)AliAnalysisManager::GetAnalysisManager()->GetCurrentEntry(), nTPC, nTRD));
+
+//   AliESDv0 *v0 = 0x0;
+//   for(Int_t iv0=0; iv0<fESD->GetNumberOfV0s(); iv0++){
+//     if(!(v0 = fESD->GetV0(iv0))) continue;
+//     fV0container->Add(new AliTRDv0Info(v0));
+//   }
+
+  // Insert also MC tracks which are passing TRD where the track is not reconstructed
+  if(HasMCdata()){
+    AliDebug(10, "Output of the MC track map:");
+    for(Int_t itk = 0; itk < nTracksMC;  itk++) AliDebug(10, Form("trackMap[%d] = %s", itk, trackMap[itk] == kTRUE ? "TRUE" : "kFALSE"));
+  
+    for(Int_t itk = 0; itk < nTracksMC; itk++){
+      if(trackMap[itk]) continue;
+      AliMCParticle *mcParticle =  (AliMCParticle*) fMCev->GetTrack(TMath::Abs(itk));
+      Int_t fPdg = mcParticle->Particle()->GetPdgCode();
+      Int_t nRefs = mcParticle->GetNumberOfTrackReferences();
+      Int_t iref = 0; AliTrackReference *ref = 0x0; 
+      Int_t nRefsTRD = 0;
+      new(fTrackInfo) AliTRDtrackInfo();
+      fTrackInfo->SetPDG(fPdg);
+      while(iref<nRefs){
+        ref = mcParticle->GetTrackReference(iref);
+        if(ref->LocalX() > 250. && ref->LocalX() < 370.){
+          AliDebug(4, Form("  trackRef[%2d] @ %7.3f IN", iref, ref->LocalX()));
+          fTrackInfo->AddTrackRef(ref);
+          nRefsTRD++;
+        }
+        else AliDebug(4, Form("  trackRef[%2d] @ %7.3f OUT", iref, ref->LocalX()));
+        iref++;
+      }
+      if(!nRefsTRD){
+        // In this stage we at least require 1 hit inside TRD. What will be done with this tracks is a task for the 
+        // analysis job
+        fTrackInfo->Delete("");
+        continue;
+      }
+      fTrackInfo->SetPrimary(mcParticle->Particle()->IsPrimary());
+      fTrackInfo->SetLabel(itk);
+      if(DebugLevel() >= 1){
+        AliTRDtrackInfo info(*fTrackInfo);
+        (*DebugStream()) << "trackInfo"
+        << "TrackInfo.=" << &info
+        << "\n";
+        info.Delete("");
+      }
+      AliDebug(3, Form("Registering rejected MC track with label %d", itk));
+      fContainer->Add(new AliTRDtrackInfo(*fTrackInfo));
+      fTrackInfo->Delete("");
+    }
+    delete[] trackMap;
+  }
+  PostData(0, fContainer);
+  PostData(1, fEventInfo);
+  PostData(2, fV0container);
+}
+
diff --git a/PWG1/TRD/AliTRDinfoGen.h b/PWG1/TRD/AliTRDinfoGen.h
new file mode 100644 (file)
index 0000000..61dafcc
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef ALITRDINFOGEN_H
+#define ALITRDINFOGEN_H
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+/* $Id: AliTRDinfoGen.h 27496 2008-07-22 08:35:45Z cblume $ */
+
+////////////////////////////////////////////////////////////////////////////
+//                                                                        //
+//  Reconstruction QA                                                     //
+//                                                                        //
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef ALITRDRECOTASK_H
+#include "AliTRDrecoTask.h"
+#endif
+
+class AliESDEvent;
+class AliMCEvent;
+class AliESDfriend;
+class AliTRDtrackInfo;
+class AliTRDeventInfo;
+class AliTRDv0Info;
+class TObjArray;
+class TTreeSRedirector;
+class AliTRDinfoGen : public AliTRDrecoTask{
+public:
+
+  AliTRDinfoGen();
+  virtual ~AliTRDinfoGen();
+  
+  void  ConnectInputData(Option_t *);
+  void  CreateOutputObjects();
+  void  Exec(Option_t *);
+  static Float_t GetTPCx() { return fgkTPC;}
+  static Float_t GetTOFx() { return fgkTOF;}
+
+private:
+  static const Float_t fgkTPC; // end TPC radial position
+  static const Float_t fgkTOF; // begin TOF radial position
+
+  AliTRDinfoGen(const AliTRDinfoGen&);
+  AliTRDinfoGen& operator=(const AliTRDinfoGen&);
+
+  AliESDEvent      *fESDev;          //! ESD event
+  AliMCEvent       *fMCev;           //! MC event
+  AliESDfriend     *fESDfriend;      //! ESD friends
+  AliTRDtrackInfo  *fTrackInfo;      //! Track info
+  AliTRDeventInfo  *fEventInfo;                   //! Event info
+  TObjArray        *fV0container;    //! V0 container
+  AliTRDv0Info     *fV0Info;                //! V0 info
+
+  ClassDef(AliTRDinfoGen, 2)         // entry to TRD analysis train
+};
+#endif
diff --git a/PWG1/TRD/AliTRDmultiplicity.cxx b/PWG1/TRD/AliTRDmultiplicity.cxx
new file mode 100644 (file)
index 0000000..619c89d
--- /dev/null
@@ -0,0 +1,288 @@
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////////
+//                                                                        //
+//  TRD multiplicity                                                      //
+//                                                                        //
+// Task to select true single tracks
+// 
+// Program flow:
+// Part A - task AliTRDmultiplicity (within the framework qaRec):
+//   For TRD standalone or TRD&TOF tracks I make a FitRiemanTilt
+//   The resulting parameterization is dumped into a DebugStreamer written to a file
+// 
+// Part B – $ALICE_ROOT/TRD/qaRec/macros/TrackletsinTRD.C[h] (analysis macro):
+//   The clusters are read in
+//   The above produced file is read in
+//   I make a fit through the parameterization of the  FitRiemanTilt -> in order to get a straight line (representing the track)
+//   the distance of each cluster with respect to the straight line is calculated
+//   If there is no cluster at a distance of 0.6  to 2 with respect to the track, the track is defined as a good track, i.e. clean single track
+//                                                                        //
+//  Authors: Yvonne C. Pachmayer <pachmay@physi.uni-heidelberg.de>        //
+//                                                                        //
+////////////////////////////////////////////////////////////////////////////
+
+#include <TObjArray.h>
+#include <TH1F.h>
+#include <TTreeStream.h>
+
+#include "AliESDtrack.h"
+#include "AliExternalTrackParam.h"
+#include "AliTRDseedV1.h"
+#include "AliTRDtrackV1.h"
+#include "AliTRDtrackerV1.h"
+#include "AliTrackPointArray.h"
+
+#include "AliTRDmultiplicity.h"
+#include "AliTRDgeometry.h"
+#include "info/AliTRDtrackInfo.h"
+
+ClassImp(AliTRDmultiplicity)
+
+//____________________________________________________________________
+AliTRDmultiplicity::AliTRDmultiplicity()
+    :AliTRDrecoTask("Multiplicity", "Barrel Tracking Multiplicity")
+  ,fEventCounter(0)
+{
+  //
+  // Default constructor
+    //
+}
+
+//____________________________________________________________________
+AliTRDmultiplicity::~AliTRDmultiplicity()
+{
+}
+
+//____________________________________________________________________
+void  AliTRDmultiplicity::CreateOutputObjects()
+{
+  //
+  // Create output objects
+  //
+
+  OpenFile(0, "RECREATE");
+
+  TH1 *h = 0x0;
+  fContainer = new TObjArray();
+  for(Int_t is=0; is<AliTRDgeometry::kNsector; is++){
+  fContainer->Add(h = new TH1F(Form("h_sector_%i", is), " ", 100,-10,10));
+  }
+} 
+
+//____________________________________________________________________
+void AliTRDmultiplicity::Exec(Option_t *)
+{
+  //
+  // Do it
+  //
+
+
+
+  ULong_t status;
+  AliTRDtrackInfo     *track = 0x0;
+  AliExternalTrackParam *esd = 0x0;
+  AliTRDtrackV1 *trackTRD = 0x0;
+  Double_t x_anode[AliTRDgeometry::kNlayer] = {300.2, 312.8, 325.4, 338.0, 350.6, 363.2}; // Take the default X0
+  Int_t standAlone=1;
+  fEventCounter++;
+
+
+  for(Int_t itrk=0; itrk<fTracks->GetEntriesFast(); itrk++){
+    track = (AliTRDtrackInfo*)fTracks->UncheckedAt(itrk);
+    if(!track->HasESDtrack()) continue;
+    status = track->GetStatus();
+
+    AliTrackPoint points[6];
+    Float_t xyz[3];
+    memset(xyz, 0, sizeof(Float_t) * 3);
+    Float_t trackletX[6];
+    Float_t trackletY[6];
+    Float_t trackletZ[6];
+    for(Int_t a=0;a<6;a++)
+    {
+        xyz[0] = x_anode[a];
+        points[a].SetXYZ(xyz);
+        trackletX[a]=-1000;
+        trackletY[a]=-1000;
+        trackletZ[a]=-1000;
+    }
+    Int_t detTracklet=600;
+
+
+
+    // TRD standalone
+    if(((status&AliESDtrack::kTRDout)>0) && !((status&AliESDtrack::kTRDin)>0))
+    {
+        trackTRD = track->GetTrack();
+
+        if(trackTRD)
+        {
+            AliTRDseedV1 *tracklet = 0x0;
+            Int_t counterTracklet=0;
+            for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++)
+            {
+                tracklet = trackTRD->GetTracklet(itl);
+                if(tracklet)
+                {
+                    if(tracklet->IsOK())
+                    {
+                        counterTracklet++;
+                        detTracklet=tracklet->GetDetector();
+                        //printf("%i %f %f \n",itl,tracklet->GetYfit(0),tracklet->GetZfit(0));
+                        trackletX[itl]=tracklet->GetX0();
+                        trackletY[itl]=tracklet->GetYfit(0);
+                        trackletZ[itl]=tracklet->GetZfit(0);
+                    }
+                }
+            }
+            // this cut is needed otherwise the order of tracklets in the fit function is not correct
+            if(counterTracklet==AliTRDgeometry::kNlayer) AliTRDtrackerV1::FitRiemanTilt(const_cast<AliTRDtrackV1 *>(trackTRD), 0x0, kTRUE, counterTracklet, points);
+            else continue;
+
+            if(DebugLevel()>=1){
+              for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){
+                //printf("---------------------------------------- %i %i %f %f %f \n",counterTracklet,il,points[il].GetX(),points[il].GetY(),points[il].GetZ());
+                Double_t pointX=points[il].GetX();
+                Double_t pointY=points[il].GetY();
+                Double_t pointZ=points[il].GetZ();
+
+
+                (*DebugStream())   << "TrackletsinTRD"
+                    << "standalone=" << standAlone
+                    << "eventcounter=" << fEventCounter
+                    << "layer="     << il
+                    << "dettracklet=" << detTracklet
+                    << "xtracklet=" << trackletX[il]
+                    << "xtrack="    << pointX
+                    << "ytracklet=" << trackletY[il]
+                    << "ytrack="    << pointY
+                    << "ztracklet=" << trackletZ[il]
+                    << "ztrack="    << pointZ
+                    << "num_tracklets=" << counterTracklet
+                    << "\n";
+
+              }
+            }
+        }
+    } // end TRD standalone
+
+
+
+    // TPC cluster selection for cosmic data
+    if((track->GetTPCncls())<40) continue;
+    // missing TPC propagation
+    if(!(status&AliESDtrack::kTPCout)) continue;
+    standAlone=0;
+
+    esd = track->GetESDinfo()->GetOuterParam();
+    // calculate sector - does not matter if track ends in TPC or TRD - sector number independent
+    Double_t alpha;
+    alpha=-100;
+    Int_t fSector=100;
+    if(esd){
+        alpha=esd->GetAlpha();
+        fSector = (Int_t)((alpha+ TMath::Pi())/(20*TMath::Pi()/180));
+        if((fSector>-1) && (fSector<18))
+        {
+        }
+        else
+        {
+            continue;
+        }
+    }
+
+
+
+    // only these sectors have a TRD detector at the moment
+   if(fSector==0||fSector==8||fSector==9||fSector==17)
+    {
+        trackTRD = track->GetTrack();
+        if(!trackTRD) continue;
+        AliTRDseedV1 *tracklet = 0x0;
+        Int_t counterTracklet=0;
+
+
+        for(Int_t itl = 0; itl < AliTRDgeometry::kNlayer; itl++){
+            tracklet = trackTRD->GetTracklet(itl);
+            if(!tracklet || !tracklet->IsOK()) continue;
+            counterTracklet++;
+            detTracklet=tracklet->GetDetector();
+            trackletX[itl]=tracklet->GetX0();
+            trackletY[itl]=tracklet->GetYfit(0);
+            trackletZ[itl]=tracklet->GetZfit(0);
+
+            /*
+            AliTRDcluster *c = 0x0;
+            for(Int_t itime = 0; itime < AliTRDseedV1::kNtb; itime++){
+                c = tracklet->GetClusters(itime);
+                if(!c) continue;
+//                Float_t cluster_x = c->GetX();
+//                Bool_t isprop;
+//                isprop=kFALSE;
+//                isprop=AliTracker::PropagateTrackTo(esd,(Double_t)cluster_x,0.105,5,kFALSE);
+//                if(isprop)
+//                {
+//                    Int_t detector = c->GetDetector();
+//                    ((TH1F*)fContainer->At(fSector))->Fill((c->GetY())-(esd->GetY()));
+//                    if(c->GetY()-esd->GetY()>);
+//                    printf("diff: %f\n",c->GetY()-(esd->GetY()));
+//                }
+            }
+            */
+
+        } // loop over tracklets ends
+
+        if(counterTracklet==AliTRDgeometry::kNlayer)
+        {
+            AliTRDtrackerV1::FitRiemanTilt(const_cast<AliTRDtrackV1 *>(trackTRD), 0x0, kTRUE, counterTracklet, points);
+        }
+        else continue;
+
+       
+
+        if(DebugLevel()>=1){
+          for(Int_t il = 0; il < AliTRDgeometry::kNlayer; il++){
+            //printf("---------------------------------------- %i %i %f %f %f \n",counterTracklet,il,points[il].GetX(),points[il].GetY(),points[il].GetZ());
+            Double_t pointX=points[il].GetX();
+            Double_t pointY=points[il].GetY();
+            Double_t pointZ=points[il].GetZ();
+            
+            (*DebugStream())   << "TrackletsinTRD"
+                << "standalone=" << standAlone
+                << "eventcounter=" << fEventCounter
+                << "layer="     << il
+                << "dettracklet=" << detTracklet
+                << "xtracklet=" << trackletX[il]
+                << "xtrack="    << pointX
+                << "ytracklet=" << trackletY[il]
+                << "ytrack="    << pointY
+                << "ztracklet=" << trackletZ[il]
+                << "ztrack="    << pointZ
+                << "num_tracklets=" << counterTracklet
+                << "\n";
+          }
+        }
+
+    }
+  }
+
+  
+  PostData(0, fContainer);
+}
+
+
diff --git a/PWG1/TRD/AliTRDmultiplicity.h b/PWG1/TRD/AliTRDmultiplicity.h
new file mode 100644 (file)
index 0000000..f544424
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef ALITRDMULTIPLICITY_H
+#define ALITRDMULTIPLICITY_H
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+
+////////////////////////////////////////////////////////////////////////////
+//                                                                        //
+//  TRD multiplicity                                                     //
+//                                                                        //
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef ALITRDRECOTASK_H
+#include "AliTRDrecoTask.h"
+#endif
+
+class AliTRDmultiplicity : public AliTRDrecoTask
+{
+public:
+  AliTRDmultiplicity();
+  virtual ~AliTRDmultiplicity();
+  void    CreateOutputObjects();
+  void    Exec(Option_t *);
+
+private:
+  AliTRDmultiplicity(const AliTRDmultiplicity&);
+  AliTRDmultiplicity& operator=(const AliTRDmultiplicity&);
+
+private:
+  Int_t fEventCounter;            // Event counter
+
+
+  ClassDef(AliTRDmultiplicity, 1) // TRD tracking multiplicity
+};
+
+#endif
+
diff --git a/PWG1/TRD/AliTRDpidRefMaker.cxx b/PWG1/TRD/AliTRDpidRefMaker.cxx
new file mode 100644 (file)
index 0000000..be8d4e6
--- /dev/null
@@ -0,0 +1,364 @@
+#include "TPDGCode.h"
+#include "TFile.h"
+#include "TTree.h"
+#include "TEventList.h"
+#include "TObjArray.h"
+#include "TH2.h"
+
+#include "AliLog.h"
+#include "AliESDtrack.h"
+#include "AliTrackReference.h"
+
+#include "AliTRDReconstructor.h"
+#include "AliTRDtrackV1.h"
+#include "AliTRDseedV1.h"
+#include "AliTRDpidRefMaker.h"
+#include "info/AliTRDv0Info.h"
+
+
+// Defines and implements basic functionality for building reference data for TRD PID. 
+// 
+// Here is the list of functionality provided by this class
+// 1.
+// 2.
+// 
+// Authors:
+//   Alex Bercuci <A.Bercuci@gsi.de>
+//   Alex Wilk    <wilka@uni-muenster.de>
+//   Markus Fasel <mfasel@gsi.de>
+//   Markus Heide <mheide@uni-muenster.de>
+// 
+
+ClassImp(AliTRDpidRefMaker)
+ClassImp(AliTRDpidRefMaker::AliTRDpidRefData)
+ClassImp(AliTRDpidRefMaker::AliTRDpidRefDataArray)
+
+//________________________________________________________________________
+AliTRDpidRefMaker::AliTRDpidRefDataArray::AliTRDpidRefDataArray() :
+  fNtracklets(0)
+  ,fData(0x0)
+{
+  // Constructor of data array
+  fData = new AliTRDpidRefData[AliTRDgeometry::kNlayer];
+}
+
+//________________________________________________________________________
+AliTRDpidRefMaker::AliTRDpidRefDataArray::~AliTRDpidRefDataArray()
+{
+  // Destructor
+  delete [] fData;
+}
+
+//________________________________________________________________________
+void AliTRDpidRefMaker::AliTRDpidRefDataArray::PushBack(Int_t ly, Int_t p, Float_t *dedx)
+{
+// Add PID data to the end of the array 
+  fData[fNtracklets].fPLbin= (ly<<4) | (p&0xf);
+  memcpy(fData[fNtracklets].fdEdx, dedx, 8*sizeof(Float_t));
+  fNtracklets++;
+}
+
+//________________________________________________________________________
+void AliTRDpidRefMaker::AliTRDpidRefDataArray::Reset()
+{
+// Reset content
+
+  if(!fNtracklets) return;
+  while(fNtracklets--){
+    fData[fNtracklets].fPLbin = 0xff;
+    memset(fData[fNtracklets].fdEdx, 0, 8*sizeof(Float_t));
+  }
+  fNtracklets=0;
+}
+
+//________________________________________________________________________
+AliTRDpidRefMaker::AliTRDpidRefMaker(const char *name, const char *title) 
+  :AliTRDrecoTask(name, title)
+  ,fReconstructor(0x0)
+  ,fV0s(0x0)
+  ,fData(0x0)
+  ,fPIDdataArray(0x0)
+  ,fRefPID(kMC)
+  ,fRefP(kMC)
+  ,fPIDbin(0xff)
+  ,fFreq(1.)
+  ,fP(-1.)
+  ,fPthreshold(0.5)
+{
+  //
+  // Default constructor
+  //
+
+  fReconstructor = new AliTRDReconstructor();
+  fReconstructor->SetRecoParam(AliTRDrecoParam::GetLowFluxParam());
+  memset(fdEdx, 0, 10*sizeof(Float_t));
+  memset(fPID, 0, AliPID::kSPECIES*sizeof(Float_t));
+
+  DefineInput(1, TObjArray::Class());
+  DefineOutput(1, TTree::Class());
+}
+
+
+//________________________________________________________________________
+AliTRDpidRefMaker::~AliTRDpidRefMaker() 
+{
+  if(fPIDdataArray) delete fPIDdataArray;
+  if(fReconstructor) delete fReconstructor;
+}
+
+//________________________________________________________________________
+Bool_t AliTRDpidRefMaker::CheckQuality(AliTRDseedV1* /*trklt*/)
+{
+// Place holder for checking tracklet quality for PID.
+  return kTRUE;  
+}
+
+
+//________________________________________________________________________
+Float_t* AliTRDpidRefMaker::CookdEdx(AliTRDseedV1 *trklt)
+{
+  trklt->CookdEdx(AliTRDpidUtil::kNNslices);
+  memcpy(fdEdx, trklt->GetdEdx(), AliTRDpidUtil::kNNslices*sizeof(Float_t));
+  return fdEdx;
+}
+
+
+//________________________________________________________________________
+void AliTRDpidRefMaker::ConnectInputData(Option_t *opt)
+{
+  AliTRDrecoTask::ConnectInputData(opt);
+  fV0s = dynamic_cast<TObjArray*>(GetInputData(1));
+}
+
+//________________________________________________________________________
+void AliTRDpidRefMaker::CreateOutputObjects()
+{
+  // Create histograms
+  // Called once
+
+  OpenFile(0, "RECREATE");
+  fContainer = new TObjArray();
+  fContainer->SetName(Form("Moni%s", GetName()));
+
+  TH2 *h2 = new TH2I("hPDG","Particle abundance", AliPID::kSPECIES, -0.5, 4.5, AliTRDCalPID::kNMom, -0.5, AliTRDCalPID::kNMom-0.5);
+  TAxis *ax = h2->GetXaxis();
+  ax->SetNdivisions(505);
+  ax->SetTitle("Particle species");
+  for(Int_t is=AliPID::kSPECIES; is--;) ax->SetBinLabel(is+1, AliPID::ParticleShortName(is));
+  h2->GetYaxis()->SetTitle("P bins");
+  h2->GetYaxis()->SetNdivisions(511);
+
+  fContainer->AddAt(h2, 0);
+
+  fData = new TTree(GetName(), Form("Reference data for %s", GetName()));
+  fData->Branch("s", &fPIDbin, "s/b");
+  fData->Branch("data", &fPIDdataArray);
+}
+
+//________________________________________________________________________
+void AliTRDpidRefMaker::Exec(Option_t *) 
+{
+  // Main loop
+  // Called for each event
+
+  AliTRDtrackInfo     *track = 0x0;
+  AliTRDtrackV1    *trackTRD = 0x0;
+  AliTrackReference     *ref = 0x0;
+  const AliTRDtrackInfo::AliESDinfo *infoESD = 0x0;
+  for(Int_t itrk=0; itrk<fTracks->GetEntriesFast(); itrk++){
+    track = (AliTRDtrackInfo*)fTracks->UncheckedAt(itrk);
+    if(!track->HasESDtrack()) continue;
+    trackTRD = track->GetTrack();
+    infoESD  = track->GetESDinfo();
+    Double32_t *infoPID = infoESD->GetSliceIter();
+    Int_t n = infoESD->GetNSlices() - AliTRDgeometry::kNlayer;
+    Double32_t *p = &infoPID[n];
+
+
+    ULong_t status = track->GetStatus();
+    if(!(status&AliESDtrack::kTPCout)) continue;
+
+    // fill the pid information
+    SetRefPID(fRefPID, track, fPID);
+
+    // prepare PID data array
+    if(!fPIDdataArray){ 
+      fPIDdataArray = new AliTRDpidRefDataArray();
+    } else fPIDdataArray->Reset();
+
+    // fill PID information
+    for(Int_t ily = 0; ily < AliTRDgeometry::kNlayer; ily++){
+
+      // fill P & dE/dx information
+      if(HasFriends()){ // from TRD track
+        if(!trackTRD) continue;
+        AliTRDseedV1 *trackletTRD(0x0);
+        trackTRD -> SetReconstructor(fReconstructor);
+        if(!(trackletTRD = trackTRD -> GetTracklet(ily))) continue;
+        if(!CheckQuality(trackletTRD)) continue;
+        if(!CookdEdx(trackletTRD)) continue;
+
+        // fill momentum information
+        fP = 0.;
+        switch(fRefP){
+        case kMC:
+          if(!(ref = track->GetTrackRef(trackletTRD))) continue;
+          fP = ref->P();
+          break;
+        case kRec:
+          fP = trackletTRD->GetMomentum();
+          break;
+        default: continue;
+        }
+      } else { // from ESD track
+        // fill momentum information
+        switch(fRefP){
+        case kMC:
+          if(!(ref = track->GetTrackRef(ily))) continue;
+          fP = ref->P();
+          break;
+        case kRec:
+          fP = p[ily];
+          break;
+        default: continue;
+        } 
+        Double32_t *it = &infoPID[ily*AliTRDCalPID::kNSlicesNN];
+        for(Int_t is=AliTRDCalPID::kNSlicesNN; is--; it++) fdEdx[is] = (*it);
+      }
+
+      // momentum threshold
+      if(fP < fPthreshold) continue;
+
+      // store information
+      fPIDdataArray->PushBack(ily, AliTRDpidUtil::GetMomentumBin(fP), fdEdx);
+    }
+
+    Fill();
+  }
+
+  PostData(0, fContainer);
+  PostData(1, fData);
+}
+
+
+//________________________________________________________________________
+void AliTRDpidRefMaker::Fill() 
+{
+// Fill data tree
+
+  if(!fPIDdataArray->fNtracklets) return;
+  fPIDbin = TMath::LocMax(AliPID::kSPECIES, fPID); // get particle type
+// Fill data tree
+  fData->Fill();
+
+  
+  // fill monitor
+  for(Int_t ily=fPIDdataArray->fNtracklets; ily--;){
+    Int_t pBin = fPIDdataArray->fData[ily].fPLbin & 0xf;
+    ((TH2*)fContainer->At(0))->Fill(fPIDbin, pBin);
+  }
+}
+
+//________________________________________________________________________
+void AliTRDpidRefMaker::LinkPIDdata() 
+{
+// Link data tree to data members
+  fData->SetBranchAddress("s", &fPIDbin);
+  fData->SetBranchAddress("data", &fPIDdataArray);
+}
+
+//________________________________________________________________________
+void AliTRDpidRefMaker::SetRefPID(ETRDpidRefMakerSource select, void *source, Float_t *pid) 
+{
+// Fill the reference PID values "pid" from "source" object
+// according to the option "select". Possible options are
+// - kV0  - v0 based PID
+// - kMC  - MC truth [default]
+// - kRec - outside detectors
+
+
+  memset(fPID, 0, AliPID::kSPECIES*sizeof(Float_t));
+  switch(select){ 
+  case kV0:
+    {
+      AliTRDtrackInfo *track = static_cast<AliTRDtrackInfo*>(source);
+      if(!track){
+        AliError("No trackInfo found");
+        return;
+      }
+
+      //Get V0 PID decisions from the AliTRDv0Info for all particle species (implemented so far : electrons from conversions, pions from K0s and protons from Lambdas) :
+      AliTRDv0Info v0;
+      for(Int_t is=AliPID::kSPECIES; is--;) fPID[is] = v0.GetV0PID(is, track);
+    }
+    break;
+  case kMC:
+    if(!HasMCdata()){
+      AliError("Could not retrive reference PID from MC");
+      return;
+    }
+    {
+      AliTRDtrackInfo *track = static_cast<AliTRDtrackInfo*>(source);
+      switch(track->GetPDG()){
+      case kElectron:
+      case kPositron:
+        fPID[AliPID::kElectron] = 1.;
+        break;
+      case kMuonPlus:
+      case kMuonMinus:
+        fPID[AliPID::kMuon] = 1.;
+        break;
+      case kPiPlus:
+      case kPiMinus:
+        fPID[AliPID::kPion] = 1.;
+        break;
+      case kKPlus:
+      case kKMinus:
+        fPID[AliPID::kKaon] = 1.;
+        break;
+      case kProton:
+      case kProtonBar:
+        fPID[AliPID::kProton] = 1.;
+        break;
+      }
+    }
+    break;
+  case kRec:
+    { 
+      AliTRDtrackInfo *track = static_cast<AliTRDtrackInfo*>(source);
+      AliTRDtrackV1 *trackTRD = track->GetTrack();
+      trackTRD -> SetReconstructor(fReconstructor);
+      //fReconstructor -> SetOption("nn");
+      trackTRD -> CookPID();
+      for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){
+        pid[iPart] = trackTRD -> GetPID(iPart);
+        AliDebug(4, Form("PDG is (in V0info) %d %f", iPart, pid[iPart]));
+      }
+    }
+    break;
+  default:
+    AliWarning("PID reference source not implemented");
+    return;
+  }
+  AliDebug(4, Form("Ref PID [%] : %s[%5.2f] %s[%5.2f] %s[%5.2f] %s[%5.2f] %s[%5.2f]"
+    ,AliPID::ParticleShortName(0), 1.e2*fPID[0]
+    ,AliPID::ParticleShortName(1), 1.e2*fPID[1]
+    ,AliPID::ParticleShortName(2), 1.e2*fPID[2]
+    ,AliPID::ParticleShortName(3), 1.e2*fPID[3]
+    ,AliPID::ParticleShortName(4), 1.e2*fPID[4]
+  ));
+}
+
+//________________________________________________________________________
+void AliTRDpidRefMaker::SetAbundance(Float_t train) 
+{
+// Split data sample between trainning and testing
+
+  if(train<0. || train >1.){
+    AliWarning("The input data should be in the interval [0, 1]");
+    return;
+  }
+
+  fFreq = train; 
+}
+
diff --git a/PWG1/TRD/AliTRDpidRefMaker.h b/PWG1/TRD/AliTRDpidRefMaker.h
new file mode 100644 (file)
index 0000000..dfd8bb6
--- /dev/null
@@ -0,0 +1,121 @@
+#ifndef ALITRDPIDREFMAKER_H
+#define ALITRDPIDREFMAKER_H
+
+////////////////////////////////////////////////////////////
+//
+// Base class for the Task to build TRD-PID reference data
+// For the actual implementation please check the classes
+//   - AliTRDpidRefMakerNN (Neural Networks)
+//   - AliTRDpidRefMakerLQ (Multidimensional Likelihood)
+//
+// Authors: Alex Bercuci <A.Bercuci@gsi.de>
+//          Alex Wilk    <wilka@uni-muenster.de>
+//
+/////////////////////////////////////////////////////////////
+
+#ifndef ALITRDRECOTASK_H
+#include "AliTRDrecoTask.h"
+#endif
+#ifndef ALIPID_H
+#include "AliPID.h"
+#endif
+#ifndef ALITRDCALPID_H
+#include "../Cal/AliTRDCalPID.h"
+#endif
+#ifndef ALITRDGEOMETRY_H
+#include "../AliTRDgeometry.h"
+#endif
+
+class TTree;
+class TObjArray;
+class AliTRDReconstructor;
+class AliTRDseedV1;
+class AliTRDpidRefMaker : public AliTRDrecoTask
+{
+public:
+  enum ETRDpidRefMakerPBins {
+    k006  =  0
+    ,k008 =  1
+    ,k010 =  2
+    ,k015 =  3
+    ,k020 =  4
+    ,k030 =  5
+    ,k040 =  6
+    ,k050 =  7
+    ,k060 =  8
+    ,k080 =  9
+    ,k100 = 10
+    ,kAll = 11
+  };
+  enum ETRDpidRefMakerSource {
+    kV0 = 0 // use V0 as reference
+   ,kMC = 1 // use MC as reference
+   ,kRec= 2 // use Reconstructed PID as reference
+  };
+
+  struct AliTRDpidRefData {
+    AliTRDpidRefData() : fPLbin(0xff) {
+      memset(fdEdx, 0, 8*sizeof(Float_t));
+    }
+    virtual ~AliTRDpidRefData(){}
+    UChar_t fPLbin;   // momentum / layer bin
+    Float_t fdEdx[8]; // dEdx array
+    ClassDef(AliTRDpidRefData, 1)  // PID data representation
+  };
+  struct AliTRDpidRefDataArray {
+    AliTRDpidRefDataArray();
+    virtual ~AliTRDpidRefDataArray();
+    void    PushBack(Int_t ly, Int_t p, Float_t *dedx);
+    void    Reset();
+
+    Int_t   fNtracklets;     // number of tracklets
+    AliTRDpidRefData *fData; //[fNtracklets] PID data array
+  private:
+    AliTRDpidRefDataArray(const AliTRDpidRefMaker::AliTRDpidRefDataArray& ref);
+    AliTRDpidRefDataArray& operator=(const AliTRDpidRefMaker::AliTRDpidRefDataArray& ref);
+    ClassDef(AliTRDpidRefDataArray, 1)  // track PID data representation
+  };
+
+  AliTRDpidRefMaker(const char *name="PIDrefMaker", const char *title="PID Reference Maker");
+
+  virtual ~AliTRDpidRefMaker();
+  
+  void    ConnectInputData(Option_t *opt);
+  void    CreateOutputObjects();
+  void    Exec(Option_t *option);
+  Float_t GetPthreshold() const { return fPthreshold;}
+
+  void    SetAbundance(Float_t train);
+  void    SetPthreshold(Float_t t) { fPthreshold = t;}
+  void    SetRefPID(ETRDpidRefMakerSource select, void *source, Float_t *pid);
+  void    SetSource(ETRDpidRefMakerSource pid, ETRDpidRefMakerSource momentum) {fRefPID = pid; fRefP = momentum;}
+
+
+protected:
+  virtual Bool_t   CheckQuality(AliTRDseedV1* trklt);
+  virtual Float_t* CookdEdx(AliTRDseedV1* trklt);
+  virtual void     LinkPIDdata();
+  virtual void     Fill();
+
+  AliTRDReconstructor *fReconstructor;  //! reconstructor needed for recalculation the PID
+  TObjArray     *fV0s;                  //! v0 array
+  TTree         *fData;                 //! dEdx-P data
+  AliTRDpidRefDataArray *fPIDdataArray; //! pid data array
+  ETRDpidRefMakerSource  fRefPID;       // reference PID source
+  ETRDpidRefMakerSource  fRefP;         // reference momentum source
+  UChar_t       fPIDbin;                //! species bin
+  Float_t       fFreq;                  //! training sample relative abundance
+  Float_t       fP;                     //! momentum
+  Float_t       fdEdx[8];               //! dEdx array
+  Float_t       fPID[AliPID::kSPECIES]; //! pid from v0s
+
+private:
+  AliTRDpidRefMaker(const AliTRDpidRefMaker&);              // not implemented
+  AliTRDpidRefMaker& operator=(const AliTRDpidRefMaker&);   // not implemented
+
+  Float_t        fPthreshold;            // momentum threshold [GeV/c]
+
+  ClassDef(AliTRDpidRefMaker, 3); // TRD PID reference  maker base class
+};
+
+#endif
diff --git a/PWG1/TRD/AliTRDpidRefMakerLQ.cxx b/PWG1/TRD/AliTRDpidRefMakerLQ.cxx
new file mode 100644 (file)
index 0000000..fc0b63d
--- /dev/null
@@ -0,0 +1,272 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+/* $Id: AliTRDpidRefMakerLQ.cxx 34163 2009-08-07 11:28:51Z cblume $ */
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//
+//  TRD calibration class for building reference data for PID
+//  - 2D reference histograms (responsible A.Bercuci) 
+//  - 3D reference histograms (not yet implemented) (responsible A.Bercuci)
+//  - Neural Network (responsible A.Wilk)
+//
+//   Origin
+//   Alex Bercuci  (A.Bercuci@gsi.de)
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <TFile.h>
+#include <TROOT.h>
+#include <TTree.h>
+#include <TMath.h>
+#include <TEventList.h>
+#include <TH2D.h>
+#include <TH2I.h>
+#include <TPrincipal.h>
+//#include <TVector3.h>
+//#include <TLinearFitter.h>
+#include <TCanvas.h>
+//#include <TEllipse.h>
+//#include <TMarker.h>
+
+#include "AliLog.h"
+#include "../../STAT/TKDPDF.h"
+#include "AliTRDpidRefMakerLQ.h"
+#include "../Cal/AliTRDCalPID.h"
+#include "../Cal/AliTRDCalPIDLQ.h"
+#include "AliTRDseedV1.h"
+#include "AliTRDcalibDB.h"
+#include "AliTRDgeometry.h"
+
+ClassImp(AliTRDpidRefMakerLQ)
+
+//__________________________________________________________________
+AliTRDpidRefMakerLQ::AliTRDpidRefMakerLQ()
+  :AliTRDpidRefMaker("PIDrefMakerLQ", "PID(LQ) Reference Maker")
+{
+  //
+  // AliTRDpidRefMakerLQ default constructor
+  //
+}
+
+//__________________________________________________________________
+AliTRDpidRefMakerLQ::~AliTRDpidRefMakerLQ()
+{
+  //
+  // AliTRDCalPIDQRef destructor
+  //
+}
+
+//________________________________________________________________________
+void AliTRDpidRefMakerLQ::CreateOutputObjects()
+{
+  // Create histograms
+  // Called once
+
+  AliTRDpidRefMaker::CreateOutputObjects();
+
+  // save dE/dx references
+  TH2 *h2 = 0x0;
+  for(Int_t ip=AliTRDCalPID::kNMom; ip--;){ 
+    TObjArray *arr = new TObjArray(AliPID::kSPECIES);
+    arr->SetName(Form("Pbin%02d", ip));
+    for(Int_t is=AliPID::kSPECIES; is--;) {
+      h2 = new TH2D(Form("h%s%d", AliPID::ParticleShortName(is), ip), Form("%s ref. dEdx @ Pbin[%d]", AliPID::ParticleName(is), ip), 50, 5., 10., 50, 5., 10.);
+      h2->GetXaxis()->SetTitle("log(dE/dx_{am}) [au]");
+      h2->GetYaxis()->SetTitle("log(dE/dx_{dr}) [au]");
+      h2->GetZaxis()->SetTitle("#");
+      arr->AddAt(h2, is);
+    }
+    fContainer->AddAt(arr, 1+ip);
+  }
+}
+
+/*
+//________________________________________________________________________
+Float_t* AliTRDpidRefMakerLQ::CookdEdx(AliTRDseedV1 *trklt)
+{
+// Fill dEdx array for multidim LQ PID
+
+  trklt->CookdEdx(AliTRDpidUtil::kLQslices);
+  const Float_t *dedx = trklt->GetdEdx();
+  if(dedx[0]+dedx[1] <= 0.) return 0x0;
+  if(dedx[2] <= 0.) return 0x0;
+
+  fdEdx[0] = TMath::Log(dedx[0]+dedx[1]);
+  fdEdx[1] = TMath::Log(dedx[2]);
+  return fdEdx;
+}*/
+
+//__________________________________________________________________
+TObject* AliTRDpidRefMakerLQ::GetOCDBEntry(Option_t *opt)
+{
+// Steer loading of OCDB LQ PID
+
+  TDirectoryFile *d = 0x0;
+  if(!TFile::Open(Form("TRD.Calib%s.root", GetName()))) return 0x0;
+  if(!(d=(TDirectoryFile*)gFile->Get(Form("PDF_%s", opt)))) return 0x0;
+  AliTRDCalPIDLQ *cal = new AliTRDCalPIDLQ("pidLQ", "LQ TRD PID object");
+  cal->LoadPDF(d);
+  return cal;
+}
+
+//__________________________________________________________________
+Bool_t AliTRDpidRefMakerLQ::GetRefFigure(Int_t ifig)
+{
+// Steering reference picture
+
+  if(ifig<0 || ifig>AliTRDCalPID::kNMom-1){ 
+    AliError("Ref fig requested outside definition.");
+    return kFALSE;
+  }
+  if(!gPad){
+    AliWarning("Please provide a canvas to draw results.");
+    return kFALSE;
+  }
+
+  TObjArray *arr = (TObjArray*)fContainer->At(ifig);
+  gPad->Divide(3, 2, 1.e-5, 1.e-5); 
+  TList *l=gPad->GetListOfPrimitives(); 
+  for(Int_t is=0; is<AliPID::kSPECIES; is++){
+    ((TVirtualPad*)l->At(is))->cd();
+    ((TH2*)arr->At(is))->Draw("cont4z");
+  }
+
+  return kTRUE;
+}
+
+//________________________________________________________________________
+Bool_t AliTRDpidRefMakerLQ::PostProcess()
+{
+// Analyse merged dedx = f(p) distributions.
+//   - select momentum - species bins
+//   - rotate to principal components
+//   - locally interpolate with TKDPDF
+//   - save interpolation to monitoring histograms
+//   - write pdf to file for loading to OCDB
+// 
+
+
+  TFile *fCalib = TFile::Open(Form("TRD.Calib%s.root", GetName()), "update");
+  fData = dynamic_cast<TTree*>(gFile->Get(GetName()));
+  if (!fData) {
+    AliError("Calibration data not available");
+    return kFALSE;
+  }
+  TObjArray *o = 0x0;
+  if(!(o = (TObjArray*)gFile->Get(Form("Moni%s", GetName())))){
+    AliWarning("Missing monitoring container.");
+    return kFALSE;
+  }
+  fContainer = (TObjArray*)o->Clone("monitor");
+
+  TDatime d;
+  TDirectoryFile *pdfs = new TDirectoryFile(Form("PDF_%d", d.GetDate()), "PDFs for LQ TRD-PID", "", gFile);
+  pdfs->Write();
+  AliDebug(2, Form("Data[%d]", fData->GetEntries()));
+  pdfs->cd();
+
+  //TCanvas *cc = new TCanvas("cc", "", 500, 500);
+  LinkPIDdata();
+  Float_t *data[] = {0x0, 0x0};
+  // allocate storage
+  data[0] = new Float_t[kMaxStat];data[1] = new Float_t[kMaxStat];
+  for(Int_t ip=AliTRDCalPID::kNMom; ip--; ){ 
+    for(Int_t is=AliPID::kSPECIES; is--;) {
+      Int_t n(0); // index of data
+      for(Int_t itrk=0; (itrk < fData->GetEntries()) && (n<kMaxStat); itrk++){
+        if(!(fData->GetEntry(itrk))) continue;
+        if(fPIDbin!=is) continue;
+        for(Int_t ily=fPIDdataArray->fNtracklets; ily--;){
+          if((fPIDdataArray->fData[ily].fPLbin & 0xf)!= ip) continue;
+          
+          Float_t dedx[] = {0., 0.};
+          for(Int_t islice=AliTRDCalPID::kNSlicesNN; islice--;){
+            Int_t jslice = islice>kNN2LQtransition;
+            dedx[jslice]+=fPIDdataArray->fData[ily].fdEdx[islice];
+          }
+          
+          // check data integrity
+          if(dedx[0]<1.e-30) continue;
+          if(dedx[1]<1.e-30) continue;
+
+          // store data
+          data[0][n] = TMath::Log(dedx[0]);
+          data[1][n] = TMath::Log(dedx[1]);
+          n++; if(n==kMaxStat) break;
+        }
+      }
+
+      // estimate bucket statistics
+      Int_t nb(kMinBuckets), // number of buckets
+            ns(Int_t(Float_t(n)/nb));    //statistics/bucket
+            
+// if(Float_t(n)/nb < 220.) ns = 200; // 7% stat error
+//       else if(Float_t(n)/nb < 420.) ns = 400; // 5% stat error
+
+      AliDebug(2, Form("pBin[%d] sBin[%d] n[%d] ns[%d] nb[%d]", ip, is, n, ns, nb));
+      if(ns<Int_t(kMinStat)){
+        AliWarning(Form("Not enough entries [%d] for %s[%d].", n, AliPID::ParticleShortName(is), ip));
+        continue;
+      }
+
+      // build PDF
+      TKDPDF pdf(n, 2, ns, data);
+      pdf.SetCOG(kFALSE);
+      pdf.SetWeights();
+      pdf.SetStore();
+      pdf.SetAlpha(5.);
+      pdf.GetStatus();
+      Float_t *c, v, ve; Double_t r, e, rxy[2];
+      for(Int_t in=pdf.GetNTNodes(); in--;){
+        pdf.GetCOGPoint(in, c, v, ve);
+        rxy[0] = (Double_t)c[0];rxy[1] = (Double_t)c[1];
+        pdf.Eval(rxy, r, e, kTRUE);
+      }
+//       // visual on-line monitoring
+//       pdf.DrawProjection();cc->Modified(); cc->Update(); cc->SaveAs(Form("pdf_%s%02d.gif", AliPID::ParticleShortName(is), ip));
+//       cc->SaveAs(Form("%s_%s%02d.gif", GetName(), AliPID::ParticleShortName(is), ip));
+
+      // save a discretization of the PDF for result monitoring
+      TH2 *h2s = (TH2D*)((TObjArray*)fContainer->At(ip))->At(is);
+      TAxis *ax = h2s->GetXaxis(), *ay = h2s->GetYaxis();
+      h2s->Clear();
+      for(int ix=1; ix<=ax->GetNbins(); ix++){
+        rxy[0] = ax->GetBinCenter(ix);
+        for(int iy=1; iy<=ay->GetNbins(); iy++){
+          rxy[1] = ay->GetBinCenter(iy);
+      
+          Double_t rr,ee;
+          pdf.Eval(rxy, rr, ee, kFALSE);
+          if(rr<0. || ee/rr>.15) continue; // 15% relative error
+          //printf("x[%2d] x[%2d] r[%f] e[%f]\n", ix, iy, rr, ee);
+          h2s->SetBinContent(ix, iy, rr);
+        }
+      }
+
+      // write results to output array
+      //pdf.GetStatus();
+      pdf.Write(Form("%s[%d]", AliPID::ParticleShortName(is), ip));
+    }
+  }
+  delete [] data[0]; delete [] data[1];
+  pdfs->Write();
+  fCalib->Close(); delete fCalib;
+
+  return kTRUE; // testing protection
+}
+
+
diff --git a/PWG1/TRD/AliTRDpidRefMakerLQ.h b/PWG1/TRD/AliTRDpidRefMakerLQ.h
new file mode 100644 (file)
index 0000000..a791a2c
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef ALITRDPIDREFMAKERLQ_H
+#define ALITRDPIDREFMAKERLQ_H
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+/* $Id: AliTRDpidRefMakerLQ.h 34125 2009-08-06 09:35:40Z cblume $ */
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+//  TRD calibration class for building reference data for PID                //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef ALIPID_H
+#include "AliPID.h"
+#endif
+
+#ifndef ALITRDPIDREFMAKER_H
+#include "AliTRDpidRefMaker.h"
+#endif
+
+#ifndef ALITRDPIDUTIL_H
+#include "AliTRDpidUtil.h"
+#endif
+
+class TObjArray;
+class AliTRDpidRefMakerLQ : public AliTRDpidRefMaker {
+public:
+  enum ETRDpidRefMakerLQsteer{
+    kMaxStat    = 180000 // maximum statistics/PID bin
+   ,kMinStat    = 50     // minimum statistics/bucket 14%
+   ,kMinBuckets = 450    // minimum number of buckets [lambda(6)*alpha(1.5)*regions(50)]
+   ,kNN2LQtransition = 4 // index of NN slices where first LQ slice ends 
+  };
+  AliTRDpidRefMakerLQ();
+  ~AliTRDpidRefMakerLQ();
+  void      CreateOutputObjects();
+  TObject*  GetOCDBEntry(Option_t *opt);
+  Bool_t    GetRefFigure(Int_t ifig);
+  Bool_t    PostProcess();
+
+private:
+  AliTRDpidRefMakerLQ(const AliTRDpidRefMakerLQ &ref);
+  AliTRDpidRefMakerLQ& operator=(const AliTRDpidRefMakerLQ &ref);
+private:
+  ClassDef(AliTRDpidRefMakerLQ, 5)  // Reference builder for Multidim-LQ TRD-PID
+
+};
+
+#endif
+
diff --git a/PWG1/TRD/AliTRDpidRefMakerNN.cxx b/PWG1/TRD/AliTRDpidRefMakerNN.cxx
new file mode 100644 (file)
index 0000000..e6e7870
--- /dev/null
@@ -0,0 +1,536 @@
+/*************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercialf purposes is hereby granted  *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+/* $Id: AliTRDpidRefMakerNN.cxx 27496 2008-07-22 08:35:45Z cblume $ */
+
+////////////////////////////////////////////////////////////////////////////
+//                                                                        //
+//  Builds the reference tree for the training of neural networks         //
+//                                                                        //
+////////////////////////////////////////////////////////////////////////////
+
+#include "TSystem.h"
+#include "TDatime.h"
+#include "TPDGCode.h"
+#include "TH1F.h"
+#include "TH2F.h"
+#include "TFile.h"
+#include "TGraphErrors.h"
+#include "TTree.h"
+#include "TEventList.h"
+#include "TMultiLayerPerceptron.h"
+
+#include "AliPID.h"
+#include "AliESDtrack.h"
+#include "AliTrackReference.h"
+
+#include "AliTRDtrackV1.h"
+#include "AliTRDReconstructor.h"
+#include "AliTRDpidUtil.h"
+#include "AliTRDpidRefMakerNN.h"
+#include "AliTRDpidUtil.h"
+
+#include "../Cal/AliTRDCalPID.h"
+#include "../Cal/AliTRDCalPIDNN.h"
+#include "info/AliTRDtrackInfo.h"
+#include "info/AliTRDv0Info.h"
+
+ClassImp(AliTRDpidRefMakerNN)
+
+//________________________________________________________________________
+AliTRDpidRefMakerNN::AliTRDpidRefMakerNN() 
+  :AliTRDpidRefMaker("PidRefMakerNN", "PID(NN) Reference Maker")
+//   :AliTRDrecoTask("PidRefMakerNN", "PID(NN) Reference Maker")
+  ,fTrainMomBin(kAll)
+  ,fEpochs(1000)
+  ,fMinTrain(100)
+  ,fDate(0)
+  ,fDoTraining(0)
+  ,fContinueTraining(0)
+  ,fTrainPath(0x0)
+  ,fScale(0)
+{
+  //
+  // Default constructor
+  //
+
+  memset(fTrain, 0, AliTRDCalPID::kNMom*AliTRDgeometry::kNlayer*sizeof(TEventList*));
+  memset(fTest, 0, AliTRDCalPID::kNMom*AliTRDgeometry::kNlayer*sizeof(TEventList*));
+  memset(fNet, 0, AliTRDgeometry::kNlayer*sizeof(TMultiLayerPerceptron*));
+
+  SetAbundance(.67);
+  SetScaledEdx(Float_t(AliTRDCalPIDNN::kMLPscale));
+  TDatime datime;
+  fDate = datime.GetDate();
+
+  DefineInput(1, TObjArray::Class());
+  DefineOutput(1, TTree::Class());
+}
+
+
+//________________________________________________________________________
+AliTRDpidRefMakerNN::~AliTRDpidRefMakerNN() 
+{
+}
+
+
+//________________________________________________________________________
+void AliTRDpidRefMakerNN::CreateOutputObjects()
+{
+  // Create histograms
+  // Called once
+
+  AliTRDpidRefMaker::CreateOutputObjects();
+  TGraphErrors *gEffisTrain = new TGraphErrors(kMoniTrain);
+  gEffisTrain -> SetLineColor(4);
+  gEffisTrain -> SetMarkerColor(4);
+  gEffisTrain -> SetMarkerStyle(29);
+  gEffisTrain -> SetMarkerSize(1);
+
+  TGraphErrors *gEffisTest = new TGraphErrors(kMoniTrain);
+  gEffisTest -> SetLineColor(2);
+  gEffisTest -> SetMarkerColor(2);
+  gEffisTest -> SetMarkerStyle(29);
+  gEffisTest -> SetMarkerSize(1);
+
+  fContainer -> AddAt(gEffisTrain,kGraphTrain);
+  fContainer -> AddAt(gEffisTest,kGraphTest);
+}
+
+
+
+//________________________________________________________________________
+Bool_t AliTRDpidRefMakerNN::PostProcess()
+{
+  // Draw result to the screen
+  // Called once at the end of the query
+
+  // build the training andthe test list for the neural networks
+  MakeTrainingLists();        
+  if(!fDoTraining) return kTRUE;
+
+  // train the neural networks and build the refrence histos for 2-dim LQ
+  gSystem->Exec(Form("mkdir ./Networks_%d/",fDate));
+  AliDebug(2, Form("TrainMomBin [%d] [%d]", fTrainMomBin, kAll));
+
+  // train single network for a single momentum (recommended)
+  if(!(fTrainMomBin == kAll)){
+    if(fTrain[fTrainMomBin][0] -> GetN() < fMinTrain){
+      AliDebug(2, Form("Warning in AliTRDpidRefMakerNN::PostProcess : Not enough events for training available! Please check Data sample!"));
+      return kFALSE;
+    }
+    MakeRefs(fTrainMomBin);
+//     TrainNetworks(fTrainMomBin);
+    MonitorTraining(fTrainMomBin);
+  }
+  // train all momenta
+  else{
+    for(Int_t iMomBin = 0; iMomBin < AliTRDCalPID::kNMom; iMomBin++){
+      if(fTrain[iMomBin][0] -> GetN() < fMinTrain){
+        AliDebug(2, Form("Warning in AliTRDpidRefMakerNN::PostProcess : Not enough events for training available for momentum bin [%d]! Please check Data sample!", iMomBin));
+  continue;
+      }
+      MakeRefs(fTrainMomBin);
+//       TrainNetworks(iMomBin);
+      MonitorTraining(iMomBin);
+    }
+  }
+
+  return kTRUE; // testing protection
+}
+
+
+//________________________________________________________________________
+void AliTRDpidRefMakerNN::MakeTrainingLists() 
+{
+  //
+  // build the training lists for the neural networks
+  //
+
+  if (!fData) {
+    LoadFile("TRD.CalibPidRefMakerNN.root");
+  }
+
+  if (!fData) {
+    Printf("ERROR tree for training list not available");
+    return;
+  }
+
+  AliDebug(2, "  Making training lists! \n");
+
+  Int_t nPart[AliPID::kSPECIES][AliTRDCalPID::kNMom];
+  memset(nPart, 0, AliPID::kSPECIES*AliTRDCalPID::kNMom*sizeof(Int_t));
+
+  // set needed branches
+  LinkPIDdata();
+
+  // start first loop to check total number of each particle type
+  for(Int_t iEv=0; iEv < fData -> GetEntries(); iEv++){
+    fData -> GetEntry(iEv);
+
+    // use only events with goes through 6 layers TRD
+    if(fPIDdataArray->fNtracklets != AliTRDgeometry::kNlayer) continue;
+
+    for(Int_t ily=AliTRDgeometry::kNlayer; ily--;) nPart[fPIDbin][fPIDdataArray->fData[ily].fPLbin & 0xf]++;
+  }
+
+  AliDebug(2, "Particle multiplicities:");
+  for(Int_t iMomBin = 0; iMomBin <AliTRDCalPID::kNMom; iMomBin++)
+    AliDebug(2, Form("Momentum[%d]  Elecs[%d] Muons[%d] Pions[%d] Kaons[%d] Protons[%d]", iMomBin, nPart[AliPID::kElectron][iMomBin], nPart[AliPID::kMuon][iMomBin], nPart[AliPID::kPion][iMomBin], nPart[AliPID::kKaon][iMomBin], nPart[AliPID::kProton][iMomBin]));
+
+  // implement counter of training and test sample size
+  Int_t iTrain[AliTRDCalPID::kNMom], iTest[AliTRDCalPID::kNMom];
+  memset(iTrain, 0, AliTRDCalPID::kNMom*sizeof(Int_t));
+  memset(iTest, 0, AliTRDCalPID::kNMom*sizeof(Int_t));
+
+  // set training sample size per momentum interval to 2/3 
+  // of smallest particle counter and test sample to 1/3
+  for(Int_t iMomBin = 0; iMomBin < AliTRDCalPID::kNMom; iMomBin++){
+    iTrain[iMomBin] = nPart[0][iMomBin];
+    for(Int_t iPart = 1; iPart < AliPID::kSPECIES; iPart++){
+      if(iTrain[iMomBin] > nPart[iPart][iMomBin])
+  iTrain[iMomBin] = nPart[iPart][iMomBin];
+    } 
+    iTrain[iMomBin] = Int_t(iTrain[iMomBin] * .66);
+    iTest[iMomBin] = Int_t( iTrain[iMomBin] * .5);
+    AliDebug(2, Form("Momentum[%d]  Train[%d] Test[%d]", iMomBin, iTrain[iMomBin], iTest[iMomBin]));
+  }
+
+
+  // reset couters
+  memset(nPart, 0, AliPID::kSPECIES*AliTRDCalPID::kNMom*sizeof(Int_t));
+
+  // start second loop to set the event lists
+  for(Int_t iEv = 0; iEv < fData -> GetEntries(); iEv++){
+    fData -> GetEntry(iEv);
+
+    // use only events with goes through 6 layers TRD
+    if(fPIDdataArray->fNtracklets != AliTRDgeometry::kNlayer) continue;
+
+    for(Int_t ily=AliTRDgeometry::kNlayer; ily--;){ 
+      Int_t iMomBin = fPIDdataArray->fData[ily].fPLbin & 0xf;
+    
+      // set event list
+      if(nPart[fPIDbin][iMomBin] < iTrain[iMomBin]){
+        fTrain[iMomBin][ily] -> Enter(iEv + ily);
+        nPart[fPIDbin][iMomBin]++;
+      } else if(nPart[fPIDbin][iMomBin] < iTest[iMomBin]+iTrain[iMomBin]){
+        fTest[iMomBin][ily] -> Enter(iEv + ily);
+        nPart[fPIDbin][iMomBin]++;
+      } else continue;
+    }
+  }
+  
+  AliDebug(2, "Particle multiplicities in both lists:");
+  for(Int_t iMomBin = 0; iMomBin <AliTRDCalPID::kNMom; iMomBin++)
+    AliDebug(2, Form("Momentum[%d]  Elecs[%d] Muons[%d] Pions[%d] Kaons[%d] Protons[%d]", iMomBin, nPart[AliPID::kElectron][iMomBin], nPart[AliPID::kMuon][iMomBin], nPart[AliPID::kPion][iMomBin], nPart[AliPID::kKaon][iMomBin], nPart[AliPID::kProton][iMomBin]));
+}
+
+
+//________________________________________________________________________
+void AliTRDpidRefMakerNN::MakeRefs(Int_t mombin) 
+{
+  //
+  // train the neural networks
+  //
+  
+  
+  if (!fData) LoadFile(Form("TRD.Calib%s.root", GetName()));
+
+  if (!fData) {
+    AliError("Tree for training list not available");
+    return;
+  }
+
+  TDatime datime;
+  fDate = datime.GetDate();
+
+  AliDebug(2, Form("Training momentum bin %d", mombin));
+
+  // set variable to monitor the training and to save the development of the networks
+  Int_t nEpochs = fEpochs/kMoniTrain;       
+  AliDebug(2, Form("Training %d times %d epochs", kMoniTrain, nEpochs));
+
+  // make directories to save the networks 
+  gSystem->Exec(Form("rm -r ./Networks_%d/MomBin_%d",fDate, mombin));
+  gSystem->Exec(Form("mkdir ./Networks_%d/MomBin_%d",fDate, mombin));
+
+  // variable to check if network can load weights from previous training
+  Bool_t bFirstLoop[AliTRDgeometry::kNlayer];
+  memset(bFirstLoop, kTRUE, AliTRDgeometry::kNlayer*sizeof(Bool_t));
+
+  // train networks over several loops and save them after each loop
+  for(Int_t iLoop = 0; iLoop < kMoniTrain; iLoop++){
+    // loop over chambers
+    for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){
+      // set the event lists
+      fData -> SetEventList(fTrain[mombin][iChamb]);
+      fData -> SetEventList(fTest[mombin][iChamb]);
+      
+      AliDebug(2, Form("Trainingloop[%d] Chamber[%d]", iLoop, iChamb));
+      
+      // check if network is already implemented
+      if(bFirstLoop[iChamb] == kTRUE){
+  fNet[iChamb] = new TMultiLayerPerceptron("fdEdx[0],fdEdx[1],fdEdx[2],fdEdx[3],fdEdx[4],fdEdx[5],fdEdx[6],fdEdx[7]:15:7:fPID[0],fPID[1],fPID[2],fPID[3],fPID[4]!",fData,fTrain[mombin][iChamb],fTest[mombin][iChamb]);
+  fNet[iChamb] -> SetLearningMethod(TMultiLayerPerceptron::kStochastic);       // set learning method
+  fNet[iChamb] -> TMultiLayerPerceptron::SetEta(0.001);                        // set learning speed
+  if(!fContinueTraining){
+    if(DebugLevel()>=2) fNet[iChamb] -> Train(nEpochs,"text update=10, graph");
+    else fNet[iChamb] -> Train(nEpochs,"");
+  }
+  else{
+    fNet[iChamb] -> LoadWeights(Form("./Networks_%d/MomBin_%d/Net%d_%d",fTrainPath, mombin, iChamb, kMoniTrain - 1));
+    if(DebugLevel()>=2) fNet[iChamb] -> Train(nEpochs,"text update=10, graph+");      
+    else fNet[iChamb] -> Train(nEpochs,"+");                   
+  }
+  bFirstLoop[iChamb] = kFALSE;
+      }
+      else{    
+  if(DebugLevel()>=2) fNet[iChamb] -> Train(nEpochs,"text update=10, graph+");      
+  else fNet[iChamb] -> Train(nEpochs,"+");                   
+      }
+      
+      // save weights for monitoring of the training
+      fNet[iChamb] -> DumpWeights(Form("./Networks_%d/MomBin_%d/Net%d_%d",fDate, mombin, iChamb, iLoop));
+    } // end chamber loop
+  }   // end training loop
+}
+
+
+
+//________________________________________________________________________
+void AliTRDpidRefMakerNN::MonitorTraining(Int_t mombin) 
+{
+  //
+  // train the neural networks
+  //
+  
+  if (!fData) LoadFile(Form("TRD.Calib%s.root", GetName()));
+  if (!fData) {
+    AliError("Tree for training list not available");
+    return;
+  }
+
+  // init networks and set event list
+  for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){
+  fNet[iChamb] = new TMultiLayerPerceptron("fdEdx[0],fdEdx[1],fdEdx[2],fdEdx[3],fdEdx[4],fdEdx[5],fdEdx[6],fdEdx[7]:15:7:fPID[0],fPID[1],fPID[2],fPID[3],fPID[4]!",fData,fTrain[mombin][iChamb],fTest[mombin][iChamb]);   
+  fData -> SetEventList(fTrain[mombin][iChamb]);
+  fData -> SetEventList(fTest[mombin][iChamb]);
+  }
+
+  // implement variables for likelihoods
+  Float_t like[AliPID::kSPECIES][AliTRDgeometry::kNlayer];
+  memset(like, 0, AliPID::kSPECIES*AliTRDgeometry::kNlayer*sizeof(Float_t));
+  Float_t likeAll[AliPID::kSPECIES], totProb;
+
+  Double_t pionEffiTrain[kMoniTrain], pionEffiErrTrain[kMoniTrain];
+  Double_t pionEffiTest[kMoniTrain], pionEffiErrTest[kMoniTrain];
+  memset(pionEffiTrain, 0, kMoniTrain*sizeof(Double_t));
+  memset(pionEffiErrTrain, 0, kMoniTrain*sizeof(Double_t));
+  memset(pionEffiTest, 0, kMoniTrain*sizeof(Double_t));
+  memset(pionEffiErrTest, 0, kMoniTrain*sizeof(Double_t));
+
+  // init histos
+  const Float_t epsilon = 1/(2*(AliTRDpidUtil::kBins-1));     // get nice histos with bin center at 0 and 1
+  TH1F *hElecs, *hPions;
+  hElecs = new TH1F("hElecs","Likelihood for electrons", AliTRDpidUtil::kBins, 0.-epsilon, 1.+epsilon);
+  hPions = new TH1F("hPions","Likelihood for pions", AliTRDpidUtil::kBins, 0.-epsilon, 1.+epsilon);
+
+  TGraphErrors *gEffisTrain=0x0, *gEffisTest=0x0;
+  gEffisTrain = (TGraphErrors*)fContainer->At(kGraphTrain);
+  gEffisTest = (TGraphErrors*)fContainer->At(kGraphTest);
+
+  AliTRDpidUtil *util = new AliTRDpidUtil();
+  
+  // monitor training progress
+  for(Int_t iLoop = 0; iLoop < kMoniTrain; iLoop++){
+
+    // load weights
+    for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){
+      fNet[iChamb] -> LoadWeights(Form("./Networks_%d/MomBin_%d/Net%d_%d",fDate, mombin, iChamb, iLoop));
+    }
+
+    // event loop training list
+    for(Int_t iEvent = 0; iEvent < fTrain[mombin][0] -> GetN(); iEvent++ ){
+
+      // reset particle probabilities
+      for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){
+  likeAll[iPart] = 1./AliPID::kSPECIES;
+      }
+      totProb = 0.;
+
+      fData -> GetEntry(fTrain[mombin][0] -> GetEntry(iEvent));
+      // use event only if it is electron or pion
+      if(!((fPID[AliPID::kElectron] == 1.0) || (fPID[AliPID::kPion] == 1.0))) continue;
+
+      // get the probabilities for each particle type in each chamber
+      for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){
+  for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){
+    like[iPart][iChamb] = fNet[iChamb] -> Result(fTrain[mombin][iChamb] -> GetEntry(iEvent), iPart);
+    likeAll[iPart] *=  like[iPart][iChamb];
+  }
+      }
+
+      // get total probability and normalize it
+      for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){
+  totProb += likeAll[iPart];
+      }
+      for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){
+  likeAll[iPart] /= totProb;
+      }
+
+      // fill likelihood distributions
+      if(fPID[AliPID::kElectron] == 1)      
+  hElecs -> Fill(likeAll[AliPID::kElectron]);
+      if(fPID[AliPID::kPion] == 1)      
+  hPions -> Fill(likeAll[AliPID::kElectron]);
+    } // end event loop
+
+
+    // calculate the pion efficiency and fill the graph
+    util -> CalculatePionEffi(hElecs, hPions);
+    pionEffiTrain[iLoop] = util -> GetPionEfficiency();
+    pionEffiErrTrain[iLoop] = util -> GetError();
+
+    gEffisTrain -> SetPoint(iLoop, iLoop+1, pionEffiTrain[iLoop]);
+    gEffisTrain -> SetPointError(iLoop, 0, pionEffiErrTrain[iLoop]);
+    hElecs -> Reset();
+    hPions -> Reset();
+    AliDebug(2, Form("TrainingLoop[%d] PionEfficiency[%f +/- %f]", iLoop, pionEffiTrain[iLoop], pionEffiErrTrain[iLoop]));
+    // end training loop
+    
+
+
+    // event loop test list
+    for(Int_t iEvent = 0; iEvent < fTest[mombin][0] -> GetN(); iEvent++ ){
+
+      // reset particle probabilities
+      for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){
+  likeAll[iPart] = 1./AliTRDgeometry::kNlayer;
+      }
+      totProb = 0.;
+
+      fData -> GetEntry(fTest[mombin][0] -> GetEntry(iEvent));
+      // use event only if it is electron or pion
+      if(!((fPID[AliPID::kElectron] == 1.0) || (fPID[AliPID::kPion] == 1.0))) continue;
+
+      // get the probabilities for each particle type in each chamber
+      for(Int_t iChamb = 0; iChamb < AliTRDgeometry::kNlayer; iChamb++){
+  for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){
+    like[iPart][iChamb] = fNet[iChamb] -> Result(fTest[mombin][iChamb] -> GetEntry(iEvent), iPart);
+    likeAll[iPart] *=  like[iPart][iChamb];
+  }
+      }
+
+      // get total probability and normalize it
+      for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){
+  totProb += likeAll[iPart];
+      }
+      for(Int_t iPart = 0; iPart < AliPID::kSPECIES; iPart++){
+  likeAll[iPart] /= totProb;
+      }
+
+      // fill likelihood distributions
+      if(fPID[AliPID::kElectron] == 1)      
+  hElecs -> Fill(likeAll[AliPID::kElectron]);
+      if(fPID[AliPID::kPion] == 1)      
+  hPions -> Fill(likeAll[AliPID::kElectron]);
+    } // end event loop
+
+    // calculate the pion efficiency and fill the graph
+    util -> CalculatePionEffi(hElecs, hPions);
+    pionEffiTest[iLoop] = util -> GetPionEfficiency();
+    pionEffiErrTest[iLoop] = util -> GetError();
+
+    gEffisTest -> SetPoint(iLoop, iLoop+1, pionEffiTest[iLoop]);
+    gEffisTest -> SetPointError(iLoop, 0, pionEffiErrTest[iLoop]);
+    hElecs -> Reset();
+    hPions -> Reset();
+    AliDebug(2, Form("TestLoop[%d] PionEfficiency[%f +/- %f] \n", iLoop, pionEffiTest[iLoop], pionEffiErrTest[iLoop]));
+    
+  } //   end training loop
+
+  util -> Delete();
+
+  gEffisTest -> Draw("PAL");
+  gEffisTrain -> Draw("PL");
+
+}
+
+
+//________________________________________________________________________
+void AliTRDpidRefMakerNN::LoadFile(const Char_t *InFileNN) 
+{
+  //
+  // Loads the files and sets the event list
+  // for neural network training and 
+  // building of the 2-dim reference histograms.
+  // Useable for training outside of the makeResults.C macro
+  //
+
+  TFile *fInFileNN;
+  fInFileNN = new TFile(InFileNN, "READ");
+  fData = (TTree*)fInFileNN -> Get("NN");
+
+  for(Int_t iMom = 0; iMom < AliTRDCalPID::kNMom; iMom++){
+    for(Int_t ily = 0; ily < AliTRDgeometry::kNlayer; ily++){
+      fTrain[iMom][ily] = new TEventList(Form("fTrainMom%d_%d", iMom, ily), Form("Training list for momentum intervall %d and plane %d", iMom, ily));
+      fTest[iMom][ily] = new TEventList(Form("fTestMom%d_%d", iMom, ily), Form("Test list for momentum intervall %d and plane %d", iMom, ily));
+    }
+  }
+}
+
+
+// //________________________________________________________________________
+// void AliTRDpidRefMakerNN::LoadContainer(const Char_t *InFileCont) 
+// {
+
+//   //
+//   // Loads the container if no container is there.
+//   // Useable for training outside of the makeResults.C macro
+//   //
+
+//   TFile *fInFileCont;
+//   fInFileCont = new TFile(InFileCont, "READ");
+//   fContainer = (TObjArray*)fInFileCont -> Get("PidRefMaker");
+
+// }
+
+
+// //________________________________________________________________________
+// void AliTRDpidRefMakerNN::CreateGraphs()
+// {
+//   // Create histograms
+//   // Called once
+
+//   OpenFile(0, "RECREATE");
+//   fContainer = new TObjArray();
+//   fContainer->AddAt(new TH1F("hPDG","hPDG",AliPID::kSPECIES,-0.5,5.5),0);
+
+//   TGraphErrors *gEffisTrain = new TGraphErrors(kMoniTrain);
+//   gEffisTrain -> SetLineColor(4);
+//   gEffisTrain -> SetMarkerColor(4);
+//   gEffisTrain -> SetMarkerStyle(29);
+//   gEffisTrain -> SetMarkerSize(2);
+
+//   TGraphErrors *gEffisTest = new TGraphErrors(kMoniTrain);
+//   gEffisTest -> SetLineColor(2);
+//   gEffisTest -> SetMarkerColor(2);
+//   gEffisTest -> SetMarkerSize(2);
+
+//   fContainer -> AddAt(gEffisTrain,kGraphTrain);
+//   fContainer -> AddAt(gEffisTest,kGraphTest);
+// }
+
diff --git a/PWG1/TRD/AliTRDpidRefMakerNN.h b/PWG1/TRD/AliTRDpidRefMakerNN.h
new file mode 100644 (file)
index 0000000..78b5960
--- /dev/null
@@ -0,0 +1,111 @@
+#ifndef ALITRDPIDREFMAKERNN_H
+#define ALITRDPIDREFMAKERNN_H
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+/* $Id: AliTRDpidRefMakerNN.h 27496 2008-07-22 08:35:45Z cblume $ */
+
+//////////////////////////////////////////////////////
+//
+// Task to build PID reference tree for the training
+// of neural networs for the TRD PID
+//
+// Authors: Alex Wilk    <wilka@uni-muenster.de>
+//          Markus Heide <mheide@uni-muenster.de>
+//
+///////////////////////////////////////////////////////
+
+/* #ifndef ALITRDRECOTASK_H */
+/* #include "AliTRDrecoTask.h" */
+/* #endif */
+
+/* #ifndef ALIPID_H */
+/* #include "AliPID.h" */
+/* #endif */
+
+/* #ifndef ALITRDCALPID_H */
+/* #include "../Cal/AliTRDCalPID.h" */
+/* #endif */
+
+/* #ifndef ALITRDGEOMETRY_H */
+/* #include "../AliTRDgeometry.h" */
+/* #endif */
+
+#ifndef ALITRDPIDREFMAKER_H
+#include "AliTRDpidRefMaker.h"
+#endif
+
+/* class TTree; */
+/* class TObjArray; */
+/* class TEventList; */
+/* class TMultiLayerPerceptron; */
+/* class AliPID; */
+/* class AliTRDtrackV1; */
+/* class AliTRDReconstructor; */
+
+/* class AliTRDpidRefMakerNN : public AliTRDrecoTask */
+
+class TEventList;
+class TMultiLayerPerceptron;
+class AliTRDpidRefMakerNN : public AliTRDpidRefMaker
+{
+
+public:
+  enum ETRDpidRefMakerNNgraph {
+    kGraphTrain = 0
+    ,kGraphTest = 1
+  };
+
+  enum ETRDpidRefMakerNNmoni {
+    kMoniTrain = 50
+  };
+
+  AliTRDpidRefMakerNN();
+
+  virtual ~AliTRDpidRefMakerNN();
+  
+  void    CreateOutputObjects();
+  Int_t   GetEpochs() const {return fEpochs;};
+  Int_t   GetMinTrain() const {return fMinTrain;};
+  Int_t   GetTrainMomBin() const {return fTrainMomBin;};
+
+  Bool_t  PostProcess();
+
+  void    SetEpochs(Int_t epochs) {fEpochs = epochs;};
+  void    SetMinTrain(Int_t mintrain) {fMinTrain = mintrain;};
+  void    SetTrainMomBin(Int_t trainmombin) {fTrainMomBin = trainmombin;};
+  void    SetDate(Int_t date) {fDate = date;};
+  void    SetDoTraining(Bool_t train) {fDoTraining = train;};
+  void    SetContinueTraining(Bool_t continTrain) {fContinueTraining = continTrain;};
+  void    SetTrainPath(Int_t path) {fTrainPath = path;};
+  void    LoadFile(const Char_t *InFileNN);
+  void    SetScaledEdx(Float_t s) {fScale = s;};
+
+  void    MakeTrainingLists();                                 // build the training and the test list
+  void    MonitorTraining(Int_t mombin);                       // monitor training process
+
+protected:
+  void MakeRefs(Int_t mombin);                         // train the neural networks for a given momentum bin
+
+private:
+  AliTRDpidRefMakerNN(const AliTRDpidRefMakerNN&);              // not implemented
+  AliTRDpidRefMakerNN& operator=(const AliTRDpidRefMakerNN&);   // not implemented
+
+  TEventList *fTrain[AliTRDCalPID::kNMom][AliTRDgeometry::kNlayer];          // Training list for each momentum 
+  TEventList *fTest[AliTRDCalPID::kNMom][AliTRDgeometry::kNlayer];           // Test list for each momentum 
+  TMultiLayerPerceptron *fNet[AliTRDgeometry::kNlayer]; // artificial neural network
+
+  Int_t         fTrainMomBin;              // momentum bin for the training
+  Int_t         fEpochs;                   // Number of epochs for the training of the NNs
+  Int_t         fMinTrain;                 // minimum of events needed for training
+  Int_t         fDate;                     // date stamp for training of the NNs
+  Bool_t        fDoTraining;               // checks if training will be done
+  Bool_t        fContinueTraining;         // checks if training from an older run should be continued
+  Int_t         fTrainPath;                // sets the path for continuing the training
+
+  Float_t fScale;
+
+  ClassDef(AliTRDpidRefMakerNN, 2); // TRD reference  maker for NN
+};
+
+#endif
diff --git a/PWG1/TRD/AliTRDrecoTask.cxx b/PWG1/TRD/AliTRDrecoTask.cxx
new file mode 100644 (file)
index 0000000..4937f5f
--- /dev/null
@@ -0,0 +1,270 @@
+///////////////////////////////////////////////////////
+//
+// 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 "TList.h"
+#include "TMap.h"
+#include "TH1.h"
+#include "TF1.h"
+#include "TObjArray.h"
+#include "TDirectory.h"
+#include "TTreeStream.h"
+
+#include "AliLog.h"
+#include "AliAnalysisTask.h"
+
+#include "AliTRDrecoTask.h"
+
+ClassImp(AliTRDrecoTask)
+
+TList* AliTRDrecoTask::fgTrendPoint(0x0);
+TTreeSRedirector* AliTRDrecoTask::fgDebugStream(0x0);
+//_______________________________________________________
+AliTRDrecoTask::AliTRDrecoTask(const char *name, const char *title)
+  : AliAnalysisTask(name, title)
+  ,fNRefFigures(0)
+  ,fContainer(0x0)
+  ,fTracks(0x0)
+  ,fkTrack(0x0)
+  ,fkMC(0x0)
+  ,fkESD(0x0)
+  ,fDebugLevel(0)
+  ,fPlotFuncList(0x0)
+{
+  DefineInput(0, TObjArray::Class());
+  DefineOutput(0, TObjArray::Class());
+}
+
+//_______________________________________________________
+AliTRDrecoTask::~AliTRDrecoTask() 
+{
+
+  // Generic task destructor
+
+  AliDebug(1, Form(" Ending %s (%s)\n", GetName(), GetTitle()));
+  if(fgDebugStream){ 
+    delete fgDebugStream;
+    fgDebugStream = 0x0;
+  }
+
+  if(fPlotFuncList){
+    fPlotFuncList->Delete();
+    delete fPlotFuncList;
+    fPlotFuncList = 0x0;
+  }
+  
+  if(fContainer){
+    if(fContainer->IsOwner()) fContainer->Delete();
+    delete fContainer;
+    fContainer = 0x0;
+  }
+
+  if(fgTrendPoint){
+    TFile::Open("TRD.PerformanceTrend.root", "UPDATE");
+    fgTrendPoint->Write();
+    delete fgTrendPoint;
+    fgTrendPoint=0x0;
+    gFile->Close();
+  }
+}
+
+//_______________________________________________________
+void AliTRDrecoTask::ConnectInputData(Option_t *)
+{
+  //
+  // Connect input data
+  //
+
+  fTracks = dynamic_cast<TObjArray *>(GetInputData(0));
+}
+
+//_______________________________________________________
+void AliTRDrecoTask::Exec(Option_t *)
+{
+// Loop over Plot functors published by particular tasks
+
+  if(!fPlotFuncList){
+    AliWarning("No functor list defined for the reference plots");
+    return;
+  }
+  if(!fTracks) return;
+  if(!fTracks->GetEntriesFast()) return;
+  
+  AliTRDtrackInfo *trackInfo = 0x0;
+  TIter plotIter(fPlotFuncList);
+  TObjArrayIter trackIter(fTracks);
+  while((trackInfo = dynamic_cast<AliTRDtrackInfo*>(trackIter()))){
+    fkTrack = trackInfo->GetTrack();
+    fkMC    = trackInfo->GetMCinfo();
+    fkESD   = trackInfo->GetESDinfo();
+
+    TMethodCall *plot = 0x0;
+    plotIter.Reset();
+    while((plot=dynamic_cast<TMethodCall*>(plotIter()))){
+      plot->Execute(this);
+    }
+  }
+  PostData(0, fContainer);
+}
+
+//_______________________________________________________
+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)
+{
+// Generic publisher for trend values
+
+  if(!fgTrendPoint){
+    fgTrendPoint = new TList();
+    fgTrendPoint->SetOwner();
+  }
+  fgTrendPoint->AddLast(new TNamed(Form("%s_%s", GetName(), name), Form("%f", val)));
+  return kTRUE;
+}
+
+//_______________________________________________________
+void AliTRDrecoTask::InitFunctorList()
+{
+// Initialize list of functors
+
+  TClass *c = this->IsA();
+
+  TMethod *m = 0x0;
+  TIter methIter(c->GetListOfMethods());
+  while((m=dynamic_cast<TMethod*>(methIter()))){
+    TString name(m->GetName());
+    if(!name.BeginsWith("Plot")) continue;
+    if(!fPlotFuncList) fPlotFuncList = new TList();
+    fPlotFuncList->AddLast(new TMethodCall(c, (const char*)name, ""));
+  }
+}
+
+//_______________________________________________________
+Bool_t AliTRDrecoTask::Load(const Char_t *filename)
+{
+// Generic container loader
+
+  if(!TFile::Open(filename)){
+    AliWarning(Form("Couldn't open file %s.", filename));
+    return kFALSE;
+  }
+  TObjArray *o = 0x0;
+  if(!(o = (TObjArray*)gFile->Get(GetName()))){
+    AliWarning("Missing histogram container.");
+    return kFALSE;
+  }
+  fContainer = (TObjArray*)o->Clone(GetName());
+  gFile->Close();
+  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 = 0x0, *outObject = 0x0;
+  while((inObject = iter->Next())){
+    outObject = inObject->Clone();
+    outObject->Write(0x0, 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 kFALSE;
+}
+
+//_______________________________________________________
+void AliTRDrecoTask::SetDebugLevel(Int_t level)
+{
+// Generic debug handler
+
+  fDebugLevel = level;
+  if(fDebugLevel>=1){
+    TDirectory *savedir = gDirectory;
+    fgDebugStream = new TTreeSRedirector("TRD.DebugPerformance.root");
+    savedir->cd();
+  }
+}
+
+//____________________________________________________________________
+void AliTRDrecoTask::Terminate(Option_t *)
+{
+  //
+  // Terminate
+  //
+
+  if(fgDebugStream){ 
+    delete fgDebugStream;
+    fgDebugStream = 0x0;
+    fDebugLevel = 0;
+  }
+  if(HasPostProcess()) PostProcess();
+}
+
+//________________________________________________________
+void AliTRDrecoTask::Adjust(TF1 *f, TH1 * const h)
+{
+// Helper function to avoid duplication of code
+// Make first guesses on the fit parameters
+
+  // find the intial parameters of the fit !! (thanks George)
+  Int_t nbinsy = Int_t(.5*h->GetNbinsX());
+  Double_t sum = 0.;
+  for(Int_t jbin=nbinsy-4; jbin<=nbinsy+4; jbin++) sum+=h->GetBinContent(jbin); sum/=9.;
+  f->SetParLimits(0, 0., 3.*sum);
+  f->SetParameter(0, .9*sum);
+
+  f->SetParLimits(1, -.2, .2);
+  f->SetParameter(1, -0.1);
+
+  f->SetParLimits(2, 0., 4.e-1);
+  f->SetParameter(2, 2.e-2);
+  if(f->GetNpar() <= 4) return;
+
+  f->SetParLimits(3, 0., sum);
+  f->SetParameter(3, .1*sum);
+
+  f->SetParLimits(4, -.3, .3);
+  f->SetParameter(4, 0.);
+
+  f->SetParLimits(5, 0., 1.e2);
+  f->SetParameter(5, 2.e-1);
+}
diff --git a/PWG1/TRD/AliTRDrecoTask.h b/PWG1/TRD/AliTRDrecoTask.h
new file mode 100644 (file)
index 0000000..66d2805
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef ALITRDRECOTASK_H
+#define ALITRDRECOTASK_H
+
+///////////////////////////////////////////////////////
+//
+// Basic class for Performance/Calibration TRD tasks
+//
+// Author: Alexandru Bercuci, 10/09/2008
+//
+//////////////////////////////////////////////////
+
+#ifndef ALIANALYSISTASK_H
+#include "AliAnalysisTask.h"
+#endif
+
+#ifndef ALITRDTRACKINFO_H
+#include "info/AliTRDtrackInfo.h"
+#endif
+
+class TH1;
+class TF1;
+class TList;
+class TObjArray;
+class TTreeSRedirector;
+class AliTRDtrackV1;
+class AliTRDtrackInfo;
+class AliTRDrecoTask : public AliAnalysisTask 
+{
+public:
+  enum AliTRDrecoSteeringBits{
+    kMCdata       = BIT(20)
+    ,kFriends     = BIT(21)
+    ,kPostProcess = BIT(22)
+  };
+  AliTRDrecoTask(const char *name, const char *title);
+  virtual ~AliTRDrecoTask();
+  
+  
+  void           ConnectInputData(Option_t *);
+  virtual void   CreateOutputObjects() = 0;
+  virtual void   Exec(Option_t *);
+
+  Int_t          GetNRefFigures() const  { return fNRefFigures; } 
+  TList*         GetPlotFunctors() const { return fPlotFuncList;}
+  virtual Bool_t GetRefFigure(Int_t ifig);
+
+  Bool_t         HasFriends() const      { return TestBit(kFriends);};
+  Bool_t         HasMCdata() const       { return TestBit(kMCdata);};
+  Bool_t         HasPostProcess() const  { return TestBit(kPostProcess);};
+  virtual TObjArray* Histos()            { return fContainer;}
+
+  virtual Bool_t Load(const Char_t *filename = "TRD.Performance.root");
+  virtual Bool_t Save(TObjArray * const res);
+  virtual Bool_t PostProcess();
+  virtual Bool_t PutTrendValue(const Char_t *name, Double_t val);
+  virtual void   SetDebugLevel(Int_t level);
+  virtual void   SetFriends(Bool_t fr = kTRUE) {SetBit(kFriends, fr);}
+  virtual void   SetMCdata(Bool_t mc = kTRUE) {SetBit(kMCdata, mc);}
+  virtual void   SetPostProcess(Bool_t pp = kTRUE) {SetBit(kPostProcess, pp);}
+  virtual void   Terminate(Option_t *);
+
+protected:
+  Int_t          DebugLevel() const      { return fDebugLevel;}
+  static TTreeSRedirector* DebugStream() { return fgDebugStream;}
+  void           InitFunctorList();
+  void           Adjust(TF1 *f, TH1 * const h);
+
+  UChar_t   fNRefFigures;  //! no of reference figures reported by task
+  TObjArray *fContainer;   //! container to store results
+  TObjArray *fTracks;      //! Array of tracks
+  const AliTRDtrackV1    *fkTrack;         //! current track
+  const AliTRDtrackInfo::AliMCinfo  *fkMC; //! MC info
+  const AliTRDtrackInfo::AliESDinfo *fkESD;//! ESD info
+
+private:
+  AliTRDrecoTask(const AliTRDrecoTask&);
+  AliTRDrecoTask& operator=(const AliTRDrecoTask&);
+
+  UChar_t   fDebugLevel;   //! Debug level 
+  TList     *fPlotFuncList;//! plot functors list
+  static TList     *fgTrendPoint;          //! trend point
+  static TTreeSRedirector *fgDebugStream;  //! Debug stream 
+
+  ClassDef(AliTRDrecoTask, 1) // base TRD reconstruction task
+};
+
+#endif
+
diff --git a/PWG1/TRD/AliTRDresolution.cxx b/PWG1/TRD/AliTRDresolution.cxx
new file mode 100644 (file)
index 0000000..3f346e3
--- /dev/null
@@ -0,0 +1,2048 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercialf purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+/* $Id: AliTRDresolution.cxx 27496 2008-07-22 08:35:45Z cblume $ */
+
+////////////////////////////////////////////////////////////////////////////
+//                                                                        //
+//  TRD tracking resolution                                               //
+//
+// The class performs resolution and residual studies 
+// of the TRD tracks for the following quantities :
+//   - spatial position (y, [z])
+//   - angular (phi) tracklet
+//   - momentum at the track level
+// 
+// The class has to be used for regular detector performance checks using the official macros:
+//   - $ALICE_ROOT/TRD/qaRec/run.C
+//   - $ALICE_ROOT/TRD/qaRec/makeResults.C
+// 
+// For stand alone usage please refer to the following example: 
+// {  
+//   gSystem->Load("libANALYSIS.so");
+//   gSystem->Load("libTRDqaRec.so");
+//   AliTRDresolution *res = new AliTRDresolution();
+//   //res->SetMCdata();
+//   //res->SetVerbose();
+//   //res->SetVisual();
+//   res->Load();
+//   if(!res->PostProcess()) return;
+//   res->GetRefFigure(0);
+// }  
+//
+//  Authors:                                                              //
+//    Alexandru Bercuci <A.Bercuci@gsi.de>                                //
+//    Markus Fasel <M.Fasel@gsi.de>                                       //
+//                                                                        //
+////////////////////////////////////////////////////////////////////////////
+
+#include <TROOT.h>
+#include <TObjArray.h>
+#include <TH3.h>
+#include <TH2.h>
+#include <TH1.h>
+#include <TF1.h>
+#include <TCanvas.h>
+#include <TGaxis.h>
+#include <TBox.h>
+#include <TGraphErrors.h>
+#include <TGraphAsymmErrors.h>
+#include <TMath.h>
+#include <TMatrixT.h>
+#include <TVectorT.h>
+#include <TTreeStream.h>
+#include <TGeoManager.h>
+
+#include "AliPID.h"
+
+#include "AliTRDresolution.h"
+#include "AliTRDgeometry.h"
+#include "AliTRDpadPlane.h"
+#include "AliTRDcluster.h"
+#include "AliTRDseedV1.h"
+#include "AliTRDtrackV1.h"
+#include "AliTRDReconstructor.h"
+#include "AliTRDrecoParam.h"
+
+#include "info/AliTRDclusterInfo.h"
+
+ClassImp(AliTRDresolution)
+
+UChar_t const AliTRDresolution::fgNElements[kNhistos] = {
+  2, 2, 5, 5,
+  2, 5, 12, 2, 11
+};
+Char_t const * AliTRDresolution::fgPerformanceName[kNhistos] = {
+     "Charge"
+    ,"Cluster2Track"
+    ,"Tracklet2Track"
+    ,"Tracklet2TPC" 
+    ,"Cluster2MC"
+    ,"Tracklet2MC"
+    ,"TPC2MC"
+    ,"TOF/HMPID2MC"
+    ,"TRD2MC"
+};
+Char_t const *AliTRDresolution::fgAxTitle[46][4] = {
+  // Charge
+  {"Impv", "x [cm]", "I_{mpv}", "x/x_{0}"}
+ ,{"dI/Impv", "x/x_{0}", "#delta I/I_{mpv}", "x[cm]"}
+  // Clusters to Kalman
+ ,{"Pos", "tg(#phi)", "#mu_{y}^{cl} [#mum]", "#sigma_{y}^{cl} [#mum]"}
+ ,{"Pulls", "tg(#phi)", "PULL: #mu_{y}^{cl}", "PULL: #sigma_{y}^{cl}"}
+  // TRD tracklet to Kalman fit
+ ,{"PosY", "tg(#phi)", "#mu_{y}^{trklt} [#mum]", "#sigma_{y}^{trklt} [#mum]"}
+ ,{"PullsY", "tg(#phi)", "PULL: #mu_{y}^{trklt}", "PULL: #sigma_{y}^{trklt}"}
+ ,{"PosZ", "tg(#theta)", "#mu_{z}^{trklt} [#mum]", "#sigma_{z}^{trklt} [#mum]"}
+ ,{"PullsZ", "tg(#theta)", "PULL: #mu_{z}^{trklt}", "PULL: #sigma_{z}^{trklt}"}
+ ,{"Phi", "tg(#phi)", "#mu_{#phi}^{trklt} [mrad]", "#sigma_{#phi}^{trklt} [mrad]"}
+  // TPC track 2 first TRD tracklet
+ ,{"PosY", "tg(#phi)", "#mu_{y}^{TPC trklt} [#mum]", "#sigma_{y}^{TPC trklt} [#mum]"}
+ ,{"PullsY", "tg(#phi)", "PULL: #mu_{y}^{TPC trklt}", "PULL: #sigma_{y}^{TPC trklt}"}
+ ,{"PosZ", "tg(#theta)", "#mu_{z}^{TPC trklt} [#mum]", "#sigma_{z}^{TPC trklt} [#mum]"}
+ ,{"PullsZ", "tg(#theta)", "PULL: #mu_{z}^{TPC trklt}", "PULL: #sigma_{z}^{TPC trklt}"}
+ ,{"Phi", "tg(#phi)", "#mu_{#phi}^{TPC trklt} [mrad]", "#sigma_{#phi}^{TPC trklt} [mrad]"}
+  // MC cluster
+ ,{"Pos", "tg(#phi)", "MC: #mu_{y}^{cl} [#mum]", "MC: #sigma_{y}^{cl} [#mum]"}
+ ,{"Pulls", "tg(#phi)", "MC PULL: #mu_{y}^{cl}", "MC PULL: #sigma_{y}^{cl}"}
+  // MC tracklet
+ ,{"PosY", "tg(#phi)", "MC: #mu_{y}^{trklt} [#mum]", "MC: #sigma_{y}^{trklt} [#mum]"}
+ ,{"PullsY", "tg(#phi)", "MC PULL: #mu_{y}^{trklt}", "MC PULL: #sigma_{y}^{trklt}"}
+ ,{"PosZ", "tg(#theta)", "MC: #mu_{z}^{trklt} [#mum]", "MC: #sigma_{z}^{trklt} [#mum]"}
+ ,{"PullsZ", "tg(#theta)", "MC PULL: #mu_{z}^{trklt}", "MC PULL: #sigma_{z}^{trklt}"}
+ ,{"Phi", "tg(#phi)", "MC: #mu_{#phi}^{trklt} [mrad]", "MC: #sigma_{#phi}^{trklt} [mrad]"}
+  // MC track TPC
+ ,{"PosY", "tg(#phi)", "MC: #mu_{y}^{TPC} [#mum]", "MC: #sigma_{y}^{TPC} [#mum]"}
+ ,{"PullsY", "tg(#phi)", "MC PULL: #mu_{y}^{TPC}", "MC PULL: #sigma_{y}^{TPC}"}
+ ,{"PosZ", "tg(#theta)", "MC: #mu_{z}^{TPC} [#mum]", "MC: #sigma_{z}^{TPC} [#mum]"}
+ ,{"PullsZ", "tg(#theta)", "MC PULL: #mu_{z}^{TPC}", "MC PULL: #sigma_{z}^{TPC}"}
+ ,{"Phi", "tg(#phi)", "MC: #mu_{#phi}^{TPC} [mrad]", "MC: #sigma_{#phi}^{TPC} [mrad]"}
+ ,{"PullsSNP", "tg(#phi)", "MC PULL: #mu_{snp}^{TPC}", "MC PULL: #sigma_{snp}^{TPC}"}
+ ,{"Theta", "tg(#theta)", "MC: #mu_{#theta}^{TPC} [mrad]", "MC: #sigma_{#theta}^{TPC} [mrad]"}
+ ,{"PullsTGL", "tg(#theta)", "MC PULL: #mu_{tgl}^{TPC}", "MC PULL: #sigma_{tgl}^{TPC}"}
+ ,{"Pt", "p_{t}^{MC} [GeV/c]", "MC: #mu^{TPC}(#Deltap_{t}/p_{t}^{MC}) [%]", "MC: #sigma^{TPC}(#Deltap_{t}/p_{t}^{MC}) [%]"}
+ ,{"Pulls1Pt", "1/p_{t}^{MC} [c/GeV]", "MC PULL: #mu_{1/p_{t}}^{TPC}", "MC PULL: #sigma_{1/p_{t}}^{TPC}"}
+ ,{"P", "p^{MC} [GeV/c]", "MC: #mu^{TPC}(#Deltap/p^{MC}) [%]", "MC: #sigma^{TPC}(#Deltap/p^{MC}) [%]"}
+ ,{"PullsP", "p^{MC} [GeV/c]", "MC PULL: #mu^{TPC}(#Deltap/#sigma_{p})", "MC PULL: #sigma^{TPC}(#Deltap/#sigma_{p})"}
+  // MC track TOF
+ ,{"PosZ", "tg(#theta)", "MC: #mu_{z}^{TOF} [#mum]", "MC: #sigma_{z}^{TOF} [#mum]"}
+ ,{"PullsZ", "tg(#theta)", "MC PULL: #mu_{z}^{TOF}", "MC PULL: #sigma_{z}^{TOF}"}
+  // MC track in TRD
+ ,{"PosY", "tg(#phi)", "MC: #mu_{y}^{Trk} [#mum]", "MC: #sigma_{y}^{Trk} [#mum]"}
+ ,{"PullsY", "tg(#phi)", "MC PULL: #mu_{y}^{Trk}", "MC PULL: #sigma_{y}^{Trk}"}
+ ,{"PosZ", "tg(#theta)", "MC: #mu_{z}^{Trk} [#mum]", "MC: #sigma_{z}^{Trk} [#mum]"}
+ ,{"PullsZ", "tg(#theta)", "MC PULL: #mu_{z}^{Trk}", "MC PULL: #sigma_{z}^{Trk}"}
+ ,{"Phi", "tg(#phi)", "MC: #mu_{#phi}^{Trk} [mrad]", "MC: #sigma_{#phi}^{Trk} [mrad]"}
+ ,{"PullsSNP", "tg(#phi)", "MC PULL: #mu_{snp}^{Trk}", "MC PULL: #sigma_{snp}^{Trk}"}
+ ,{"Theta", "tg(#theta)", "MC: #mu_{#theta}^{Trk} [mrad]", "MC: #sigma_{#theta}^{Trk} [mrad]"}
+ ,{"PullsTGL", "tg(#theta)", "MC PULL: #mu_{tgl}^{Trk}", "MC PULL: #sigma_{tgl}^{Trk}"}
+ ,{"Pt", "p_{t}^{MC} [GeV/c]", "MC: #mu^{Trk}(#Deltap_{t}/p_{t}^{MC}) [%]", "MC: #sigma^{Trk}(#Deltap_{t}/p_{t}^{MC}) [%]"}
+ ,{"Pulls1Pt", "1/p_{t}^{MC} [c/GeV]", "MC PULL: #mu_{1/p_{t}}^{Trk}", "MC PULL: #sigma_{1/p_{t}}^{Trk}"}
+ ,{"P", "p^{MC} [GeV/c]", "MC: #mu^{Trk}(#Deltap/p^{MC}) [%]", "MC: #sigma^{Trk}(#Deltap/p^{MC}) [%]"}
+};
+
+//________________________________________________________
+AliTRDresolution::AliTRDresolution()
+  :AliTRDrecoTask("resolution", "Spatial and momentum TRD resolution checker")
+  ,fStatus(0)
+  ,fIdxPlot(0)
+  ,fReconstructor(0x0)
+  ,fGeo(0x0)
+  ,fGraphS(0x0)
+  ,fGraphM(0x0)
+  ,fCl(0x0)
+  ,fTrklt(0x0)
+  ,fMCcl(0x0)
+  ,fMCtrklt(0x0)
+{
+  //
+  // Default constructor
+  //
+
+  fReconstructor = new AliTRDReconstructor();
+  fReconstructor->SetRecoParam(AliTRDrecoParam::GetLowFluxParam());
+  fGeo = new AliTRDgeometry();
+
+  InitFunctorList();
+
+  DefineOutput(1, TObjArray::Class()); // cluster2track
+  DefineOutput(2, TObjArray::Class()); // tracklet2track
+  DefineOutput(3, TObjArray::Class()); // cluster2mc
+  DefineOutput(4, TObjArray::Class()); // tracklet2mc
+}
+
+//________________________________________________________
+AliTRDresolution::~AliTRDresolution()
+{
+  //
+  // Destructor
+  //
+
+  if(fGraphS){fGraphS->Delete(); delete fGraphS;}
+  if(fGraphM){fGraphM->Delete(); delete fGraphM;}
+  delete fGeo;
+  delete fReconstructor;
+  if(gGeoManager) delete gGeoManager;
+  if(fCl){fCl->Delete(); delete fCl;}
+  if(fTrklt){fTrklt->Delete(); delete fTrklt;}
+  if(fMCcl){fMCcl->Delete(); delete fMCcl;}
+  if(fMCtrklt){fMCtrklt->Delete(); delete fMCtrklt;}
+}
+
+
+//________________________________________________________
+void AliTRDresolution::CreateOutputObjects()
+{
+  // spatial resolution
+  OpenFile(0, "RECREATE");
+
+  fContainer = Histos();
+
+  fCl = new TObjArray();
+  fCl->SetOwner(kTRUE);
+  fTrklt = new TObjArray();
+  fTrklt->SetOwner(kTRUE);
+  fMCcl = new TObjArray();
+  fMCcl->SetOwner(kTRUE);
+  fMCtrklt = new TObjArray();
+  fMCtrklt->SetOwner(kTRUE);
+}
+
+//________________________________________________________
+void AliTRDresolution::Exec(Option_t *opt)
+{
+  //
+  // Execution part
+  //
+
+  fCl->Delete();
+  fTrklt->Delete();
+  fMCcl->Delete();
+  fMCtrklt->Delete();
+
+  AliTRDrecoTask::Exec(opt);
+
+  PostData(1, fCl);
+  PostData(2, fTrklt);
+  PostData(3, fMCcl);
+  PostData(4, fMCtrklt);
+}
+
+//________________________________________________________
+TH1* AliTRDresolution::PlotCharge(const AliTRDtrackV1 *track)
+{
+  //
+  // Plots the charge distribution
+  //
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TObjArray *arr = 0x0;
+  if(!(arr = ((TObjArray*)fContainer->At(kCharge)))){
+    AliWarning("No output container defined.");
+    return 0x0;
+  }
+  TH3S* h = 0x0;
+
+  AliTRDseedV1 *fTracklet = 0x0;  
+  AliTRDcluster *c = 0x0;
+  for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
+    if(!(fTracklet = fkTrack->GetTracklet(ily))) continue;
+    if(!fTracklet->IsOK()) continue;
+    Float_t x0 = fTracklet->GetX0();
+    Float_t dq, dl;
+    for(Int_t itb=AliTRDseedV1::kNtb; itb--;){
+      if(!(c = fTracklet->GetClusters(itb))){ 
+        if(!(c = fTracklet->GetClusters(AliTRDseedV1::kNtb+itb))) continue;
+      }
+      dq = fTracklet->GetdQdl(itb, &dl);
+      dl /= 0.15; // dl/dl0, dl0 = 1.5 mm for nominal vd
+      (h = (TH3S*)arr->At(0))->Fill(dl, x0-c->GetX(), dq);
+    }
+
+//     if(!HasMCdata()) continue;
+//     UChar_t s;
+//     Float_t pt0, y0, z0, dydx0, dzdx0;
+//     if(!fMC->GetDirections(x0, y0, z0, dydx0, dzdx0, pt0, s)) continue;
+
+  }
+  return h;
+}
+
+
+//________________________________________________________
+TH1* AliTRDresolution::PlotCluster(const AliTRDtrackV1 *track)
+{
+  //
+  // Plot the cluster distributions
+  //
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TObjArray *arr = 0x0;
+  if(!(arr = ((TObjArray*)fContainer->At(kCluster)))){
+    AliWarning("No output container defined.");
+    return 0x0;
+  }
+
+  Double_t cov[7];
+  Float_t x0, y0, z0, dy, dydx, dzdx;
+  AliTRDseedV1 *fTracklet = 0x0;  
+  for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
+    if(!(fTracklet = fkTrack->GetTracklet(ily))) continue;
+    if(!fTracklet->IsOK()) continue;
+    x0 = fTracklet->GetX0();
+
+    // retrive the track angle with the chamber
+    y0   = fTracklet->GetYref(0);
+    z0   = fTracklet->GetZref(0);
+    dydx = fTracklet->GetYref(1);
+    dzdx = fTracklet->GetZref(1);
+    fTracklet->GetCovRef(cov);
+    Float_t tilt = fTracklet->GetTilt();
+    AliTRDcluster *c = 0x0;
+    fTracklet->ResetClusterIter(kFALSE);
+    while((c = fTracklet->PrevCluster())){
+      Float_t xc = c->GetX();
+      Float_t yc = c->GetY();
+      Float_t zc = c->GetZ();
+      Float_t dx = x0 - xc; 
+      Float_t yt = y0 - dx*dydx;
+      Float_t zt = z0 - dx*dzdx; 
+      yc -= tilt*(zc-zt); // tilt correction
+      dy = yt - yc;
+
+      //Float_t sx2 = dydx*c->GetSX(c->GetLocalTimeBin()); sx2*=sx2;
+      Float_t sy2 = c->GetSigmaY2();
+      if(sy2<=0.) continue;
+      ((TH2I*)arr->At(0))->Fill(dydx, dy);
+      ((TH2I*)arr->At(1))->Fill(dydx, dy/TMath::Sqrt(cov[0] /*+ sx2*/ + sy2));
+  
+/*      if(DebugLevel()>=3){
+        // Get z-position with respect to anode wire
+        //AliTRDSimParam    *simParam    = AliTRDSimParam::Instance();
+        Int_t istk = fGeo->GetStack(c->GetDetector());
+        AliTRDpadPlane *pp = fGeo->GetPadPlane(ily, istk);
+        Float_t row0 = pp->GetRow0();
+        Float_t d  =  row0 - zt + pp->GetAnodeWireOffset();
+        d -= ((Int_t)(2 * d)) / 2.0;
+        if (d > 0.25) d  = 0.5 - d;
+
+        AliTRDclusterInfo *clInfo = new AliTRDclusterInfo;
+        fCl->Add(clInfo);
+        clInfo->SetCluster(c);
+        clInfo->SetGlobalPosition(yt, zt, dydx, dzdx);
+        clInfo->SetResolution(dy);
+        clInfo->SetAnisochronity(d);
+        clInfo->SetDriftLength(dx);
+        (*DebugStream()) << "ClusterResiduals"
+          <<"clInfo.=" << clInfo
+          << "\n";
+      }*/
+    }
+  }
+  return (TH2I*)arr->At(0);
+}
+
+
+//________________________________________________________
+TH1* AliTRDresolution::PlotTracklet(const AliTRDtrackV1 *track)
+{
+// Plot normalized residuals for tracklets to track. 
+// 
+// We start from the result that if X=N(|m|, |Cov|)
+// BEGIN_LATEX
+// (Cov^{-1})^{1/2}X = N((Cov^{-1})^{1/2}*|m|, |1|)
+// END_LATEX
+// in our case X=(y_trklt - y_trk z_trklt - z_trk) and |Cov| = |Cov_trklt| + |Cov_trk| at the radial 
+// reference position. 
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  TObjArray *arr = 0x0;
+  if(!(arr = (TObjArray*)fContainer->At(kTrackTRD ))){
+    AliWarning("No output container defined.");
+    return 0x0;
+  }
+
+  Double_t cov[3], covR[7]/*, sqr[3], inv[3]*/;
+  Float_t x, dx, dy, dz;
+  AliTRDseedV1 *fTracklet = 0x0;  
+  for(Int_t il=AliTRDgeometry::kNlayer; il--;){
+    if(!(fTracklet = fkTrack->GetTracklet(il))) continue;
+    if(!fTracklet->IsOK()) continue;
+    x    = fTracklet->GetX();
+    dx   = fTracklet->GetX0() - x;
+    // compute dy^2 and dz^2
+    dy   = fTracklet->GetYref(0)-dx*fTracklet->GetYref(1) - fTracklet->GetY();
+    dz   = fTracklet->GetZref(0)-dx*fTracklet->GetZref(1) - fTracklet->GetZ();
+    // compute covariance matrix
+    fTracklet->GetCovAt(x, cov);
+    fTracklet->GetCovRef(covR);
+    cov[0] += covR[0]; cov[1] += covR[1]; cov[2] += covR[2]; 
+/*  // Correct PULL calculation by considering off  
+    // diagonal elements in the covariance matrix
+    // compute square root matrix
+    if(AliTRDseedV1::GetCovInv(cov, inv)==0.) continue;
+    if(AliTRDseedV1::GetCovSqrt(inv, sqr)<0.) continue;
+    Double_t y = sqr[0]*dy+sqr[1]*dz;
+    Double_t z = sqr[1]*dy+sqr[2]*dz;
+    ((TH3*)h)->Fill(y, z, fTracklet->GetYref(1));*/
+
+    ((TH2I*)arr->At(0))->Fill(fTracklet->GetYref(1), dy);
+    ((TH2I*)arr->At(1))->Fill(fTracklet->GetYref(1), dy/TMath::Sqrt(cov[0]));
+    ((TH2I*)arr->At(4))->Fill(fTracklet->GetYref(1), TMath::ATan((fTracklet->GetYref(1)-fTracklet->GetYfit(1))/(1-fTracklet->GetYref(1)*fTracklet->GetYfit(1))));
+    if(!fTracklet->IsRowCross()) continue;
+    ((TH2I*)arr->At(2))->Fill(fTracklet->GetZref(1), dz);
+    ((TH2I*)arr->At(3))->Fill(fTracklet->GetZref(1), dz/TMath::Sqrt(cov[2]));
+  }
+
+
+  return (TH2I*)arr->At(0);
+}
+
+
+//________________________________________________________
+TH1* AliTRDresolution::PlotTrackTPC(const AliTRDtrackV1 *track)
+{
+// Store resolution/pulls of Kalman before updating with the TRD information 
+// at the radial position of the first tracklet. The following points are used 
+// for comparison  
+//  - the (y,z,snp) of the first TRD tracklet
+//  - the (y, z, snp, tgl, pt) of the MC track reference
+// 
+// Additionally the momentum resolution/pulls are calculated for usage in the 
+// PID calculation. 
+
+  if(track) fkTrack = track;
+  if(!fkTrack){
+    AliWarning("No Track defined.");
+    return 0x0;
+  }
+  AliExternalTrackParam *tin = 0x0;
+  if(!(tin = fkTrack->GetTrackLow())){
+    AliWarning("Track did not entered TRD fiducial volume.");
+    return 0x0;
+  }
+  TH1 *h = 0x0;
+  
+  Double_t x = tin->GetX();
+  AliTRDseedV1 *tracklet = 0x0;  
+  for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
+    if(!(tracklet = fkTrack->GetTracklet(ily))) continue;
+    break;
+  }
+  if(!tracklet || TMath::Abs(x-tracklet->GetX())>1.e-3){
+    AliWarning("Tracklet did not match TRD entrance.");
+    return 0x0;
+  }
+  const Int_t kNPAR(5);
+  Double_t parR[kNPAR]; memcpy(parR, tin->GetParameter(), kNPAR*sizeof(Double_t));
+  Double_t covR[3*kNPAR]; memcpy(covR, tin->GetCovariance(), 3*kNPAR*sizeof(Double_t));
+  Double_t cov[3]; tracklet->GetCovAt(x, cov);
+
+  // define sum covariances
+  TMatrixDSym COV(kNPAR); TVectorD PAR(kNPAR);
+  Double_t *pc = &covR[0], *pp = &parR[0];
+  for(Int_t ir=0; ir<kNPAR; ir++, pp++){
+    PAR(ir) = (*pp);
+    for(Int_t ic = 0; ic<=ir; ic++,pc++){ 
+      COV(ir,ic) = (*pc); COV(ic,ir) = (*pc);
+    }
+  }
+  PAR[4] = TMath::Abs(PAR[4]); // remove sign of pt !!
+  //COV.Print(); PAR.Print();
+
+  //TODO Double_t dydx =  TMath::Sqrt(1.-parR[2]*parR[2])/parR[2]; 
+  Double_t dy = parR[0] - tracklet->GetY(); 
+  TObjArray *arr = (TObjArray*)fContainer->At(kTrackTPC);
+  ((TH2I*)arr->At(0))->Fill(tracklet->GetYref(1), dy);
+  ((TH2I*)arr->At(1))->Fill(tracklet->GetYref(1), dy/TMath::Sqrt(COV(0,0)+cov[0]));
+  if(tracklet->IsRowCross()){
+    Double_t dz = parR[1] - tracklet->GetZ(); 
+    ((TH2I*)arr->At(2))->Fill(tracklet->GetZref(1), dz);
+    ((TH2I*)arr->At(3))->Fill(tracklet->GetZref(1), dz/TMath::Sqrt(COV(1,1)+cov[2]));
+  }
+  Double_t dphi = TMath::ASin(PAR[2])-TMath::ATan(tracklet->GetYfit(1));  ((TH2I*)arr->At(4))->Fill(tracklet->GetYref(1), dphi);
+
+
+  // register reference histo for mini-task
+  h = (TH2I*)arr->At(0);
+
+  if(DebugLevel()>=1){
+    (*DebugStream()) << "trackIn"
+      << "x="       << x
+      << "P="       << &PAR
+      << "C="       << &COV
+      << "\n";
+
+    Double_t y = tracklet->GetY(); 
+    Double_t z = tracklet->GetZ(); 
+    (*DebugStream()) << "trackletIn"
+      << "y="       << y
+      << "z="       << z
+      << "Vy="      << cov[0]
+      << "Cyz="     << cov[1]
+      << "Vz="      << cov[2]
+      << "\n";
+  }
+
+
+  if(!HasMCdata()) return h;
+  UChar_t s;
+  Float_t dx, pt0, x0=tracklet->GetX0(), y0, z0, dydx0, dzdx0;
+  if(!fkMC->GetDirections(x0, y0, z0, dydx0, dzdx0, pt0, s)) return h;
+  // translate to reference radial position
+  dx = x0 - x; y0 -= dx*dydx0; z0 -= dx*dzdx0;
+  Float_t norm = 1./TMath::Sqrt(1.+dydx0*dydx0); // 1/sqrt(1+tg^2(phi))
+  //Fill MC info
+  TVectorD PARMC(kNPAR);
+  PARMC[0]=y0; PARMC[1]=z0;
+  PARMC[2]=dydx0*norm; PARMC[3]=dzdx0*norm;
+  PARMC[4]=1./pt0;
+
+//   TMatrixDSymEigen eigen(COV);
+//   TVectorD evals = eigen.GetEigenValues();
+//   TMatrixDSym evalsm(kNPAR);
+//   for(Int_t ir=0; ir<kNPAR; ir++) for(Int_t ic=0; ic<kNPAR; ic++) evalsm(ir,ic) = (ir==ic ? evals(ir): 0.);
+//   TMatrixD evecs = eigen.GetEigenVectors();
+//   TMatrixD sqrcov(evecs, TMatrixD::kMult, TMatrixD(evalsm, TMatrixD::kMult, evecs.T()));
+  
+  // fill histos
+  arr = (TObjArray*)fContainer->At(kMCtrackTPC);
+  // y resolution/pulls
+  ((TH2I*)arr->At(0))->Fill(dydx0, PARMC[0]-PAR[0]);
+  ((TH2I*)arr->At(1))->Fill(dydx0, (PARMC[0]-PAR[0])/TMath::Sqrt(COV(0,0)));
+  // z resolution/pulls
+  ((TH2I*)arr->At(2))->Fill(dzdx0, PARMC[1]-PAR[1]);
+  ((TH2I*)arr->At(3))->Fill(dzdx0, (PARMC[1]-PAR[1])/TMath::Sqrt(COV(1,1)));
+  // phi resolution/snp pulls
+  ((TH2I*)arr->At(4))->Fill(dydx0, TMath::ASin(PARMC[2])-TMath::ASin(PAR[2]));
+  ((TH2I*)arr->At(5))->Fill(dydx0, (PARMC[2]-PAR[2])/TMath::Sqrt(COV(2,2)));
+  // theta resolution/tgl pulls
+  ((TH2I*)arr->At(6))->Fill(dzdx0, TMath::ATan((PARMC[3]-PAR[3])/(1-PARMC[3]*PAR[3])));
+  ((TH2I*)arr->At(7))->Fill(dzdx0, (PARMC[3]-PAR[3])/TMath::Sqrt(COV(3,3)));
+  // pt resolution\\1/pt pulls\\p resolution/pull
+  for(Int_t is=AliPID::kSPECIES; is--;){
+    if(TMath::Abs(fkMC->GetPDG())!=AliPID::ParticleCode(is)) continue;
+    ((TH3S*)arr->At(8))->Fill(pt0, PARMC[4]/PAR[4]-1., is);
+    ((TH3S*)arr->At(9))->Fill(PARMC[4], (PARMC[4]-PAR[4])/TMath::Sqrt(COV(4,4)), is);
+
+    Double_t p0 = TMath::Sqrt(1.+ PARMC[3]*PARMC[3])*pt0, p;
+    Float_t sp;
+    p = tracklet->GetMomentum(&sp);
+    ((TH3S*)arr->At(10))->Fill(p0, p/p0-1., is);
+    ((TH3S*)arr->At(11))->Fill(p0, (p0-p)/sp, is);
+    break;
+  }
+
+  // fill debug for MC 
+  if(DebugLevel()&g