Adding new version of AliTPCCalibTracksGain
authormarian <marian@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 14 Nov 2007 14:58:32 +0000 (14:58 +0000)
committermarian <marian@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 14 Nov 2007 14:58:32 +0000 (14:58 +0000)
+ helper classes
(Stefan)

TPC/TPCcalib/AliTPCCalPadRegion.cxx
TPC/TPCcalib/AliTPCCalPadRegion.h
TPC/TPCcalib/AliTPCFitPad.cxx [new file with mode: 0644]
TPC/TPCcalib/AliTPCFitPad.h [new file with mode: 0644]
TPC/TPCcalib/AliTPCSelectorTracks.cxx
TPC/TPCcalib/AliTPCcalibTracksGain.cxx
TPC/TPCcalib/AliTPCcalibTracksGain.h
TPC/TPCcalib/TPCcalibLinkDef.h
TPC/TPCcalib/libTPCcalib.pkg2

index 4857ab1..280c67c 100644 (file)
@@ -33,6 +33,7 @@
 ////////////////////////////////////////////////////////////////////////////
 
 #include "AliTPCCalPadRegion.h"
+#include "AliTPCROC.h"
 
 ClassImp(AliTPCCalPadRegion);
 
@@ -83,5 +84,34 @@ void AliTPCCalPadRegion::GetPadRegionCenterLocal(UInt_t padType, Double_t* xy) {
    // Return the center of the pad size region in local
    // coordinates as an Double_t array xy of length 2.
    //
-   Error("GetPadRegionCenterLocal", "Not yet implemented.");
+   
+   Float_t centerPad[3] = {0};
+   AliTPCROC* tpcROC = AliTPCROC::Instance();
+
+   Int_t IOROC = (padType == 0) ? 0 : tpcROC->GetNInnerSector();
+   //tpcROC->GetPositionLocal(IOROC, tpcROC->GetNRows(IOROC)/2, tpcROC->GetNPads(IOROC, tpcROC->GetNRows(IOROC)/2)/2, centerPad);  // use this instead of the switch statement if you want to calculate the center of the ROC and not the center of the regions with the same pad size
+   switch (padType) {
+      case 0:  // short pads
+         tpcROC->GetPositionLocal(IOROC, tpcROC->GetNRows(IOROC)/2, tpcROC->GetNPads(IOROC, tpcROC->GetNRows(IOROC)/2)/2, centerPad);
+         break;
+      case 1:  // medium pads
+         tpcROC->GetPositionLocal(IOROC, 64/2, tpcROC->GetNPads(IOROC, 64/2)/2, centerPad);
+         break;
+      case 2:  // long pads
+         tpcROC->GetPositionLocal(IOROC, 64+32/2, tpcROC->GetNPads(IOROC, 64+32/2)/2, centerPad);
+         break;
+   }
+
+   xy[0] = centerPad[0];
+   xy[1] = centerPad[1];
 }
+
+/*UInt_t AliTPCCalPadRegion::GetStartRow(UInt_t padType) {
+   //
+   // Returns the index of the 
+   //
+}
+
+UInt_t AliTPCCalPadRegion::GetEndRow(UInt_t padType) {
+
+}*/
index ca7410e..25a6f03 100644 (file)
@@ -14,9 +14,9 @@ public:
    AliTPCCalPadRegion();
    AliTPCCalPadRegion(const AliTPCCalPadRegion& obj);
    AliTPCCalPadRegion(const char *name, const char *title);
-   AliTPCCalPadRegion(const TString &name, const TString &title) : TNamed(name, title) { AliTPCCalPadRegion(name.Data(), title.Data()); }
+   //AliTPCCalPadRegion(const TString &name, const TString &title) : TNamed(name, title) { }
    virtual ~AliTPCCalPadRegion() { delete fObjects; }
-   AliTPCCalPadRegion& operator=(const AliTPCCalPadRegion& obj);
+   AliTPCCalPadRegion& operator=(const AliTPCCalPadRegion& rhs);
    
    virtual TObject*   GetObject(UInt_t segment, UInt_t padType)
       { return BoundsOk("GetObject", segment, padType) ? fObjects->At(segment+fgkNSegments*padType) : 0x0; }
@@ -26,7 +26,9 @@ public:
    virtual TIterator* MakeIterator(Bool_t direction = kIterForward) const { return fObjects->MakeIterator(direction); }
    static  UInt_t     GetNSegments() { return fgkNSegments; }
    static  UInt_t     GetNPadTypes() { return fgkNPadTypes; }
-   void       GetPadRegionCenterLocal(UInt_t padType, Double_t* xy);
+   static  void       GetPadRegionCenterLocal(UInt_t padType, Double_t* xy);
+//   static  UInt_t     GetStartRow(UInt_t padType);
+//   static  UInt_t     GetEndRow(UInt_t padType);
     
 protected:
    virtual Bool_t BoundsOk(const char* where, UInt_t segment, UInt_t padType) const
diff --git a/TPC/TPCcalib/AliTPCFitPad.cxx b/TPC/TPCcalib/AliTPCFitPad.cxx
new file mode 100644 (file)
index 0000000..5094414
--- /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-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.                  *
+ **************************************************************************/
+
+////////////////////////////////////////////////////////////////////////////
+//                                                                        
+//       === Class for fitting properties specific to pad regions ===
+//
+//    For each pad size region a separate TLinearFitter object is assigned.
+//    Commonly used functions such as getting the center of a pad size
+//    region or visualization functions are provided. Also, choosing the
+//    segment and pad type is made easy due to different methods that
+//    can calculate these informations from other coordinates.
+//
+////////////////////////////////////////////////////////////////////////////
+
+#include "AliTPCFitPad.h"
+
+ClassImp(AliTPCFitPad);
+
+AliTPCFitPad::~AliTPCFitPad() {
+   //
+   // Destructor.
+   //
+
+   Delete();
+}
+
+AliTPCFitPad::AliTPCFitPad(Int_t ndim, const char* formula, Option_t* opt) :
+   AliTPCCalPadRegion("", ""),
+   fNdim(ndim),
+   fFormula(formula),
+   fOpt(opt)
+{
+   //
+   // Constructor. The parameters are used for generating new TLinearFitter
+   // objects and are described in its documentation.
+   //
+}
+
+AliTPCFitPad& AliTPCFitPad::operator=(const AliTPCFitPad& rhs) {
+   //
+   // Assignment operator.
+   //
+
+   if (this != &rhs) {
+      AliTPCCalPadRegion::operator=(rhs);
+      fNdim = rhs.fNdim;
+      fFormula = rhs.fFormula;
+      fOpt = rhs.fOpt;
+   }
+   return *this;
+}
+
+void AliTPCFitPad::Add(AliTPCFitPad* fit) {
+   //
+   // Adds another AliTPCFitPad object to this object. The formula should be the
+   // same, though it won't be checked!
+   //
+
+   for (UInt_t iSegment = 0; iSegment < GetNSegments(); iSegment++) {
+      for (UInt_t iPadType = 0; iPadType < GetNPadTypes(); iPadType++) {
+         TLinearFitter* fitter = fit->GetFitterSimple(iSegment, iPadType);
+         // parameter workaround == kTRUE because it is not possible to add another
+         // TLinearFitter object to a "virgin" one. Thus a dummy data point is added
+         // and cleared again immediately afterwards. Due to a broken TLinearFitter
+         // copy constructor this is a necessary workaround.
+         if (fitter) {
+            cout << "TLinearFitter::Add called for " << iSegment << ", " << iPadType << endl;
+            GetFitter(iSegment, iPadType, kTRUE)->Add(fitter);
+         }
+      }
+   }
+}
+
+TLinearFitter* AliTPCFitPad::GetFitterSimple(UInt_t segment, UInt_t padType) {
+   //
+   // This method returns the fitter corresponding to segment and pad type.
+   // In contrast to GetFitter() no fitter will be created, if it does
+   // not exist, but a null pointer is returned.
+   //
+   
+   return (TLinearFitter*)(GetObject(segment, padType));
+}
+
+TLinearFitter* AliTPCFitPad::GetFitter(UInt_t segment, UInt_t padType, Bool_t workaround) {
+   //
+   // This method returns the fitter corresponding
+   // to segment and pad type.
+   // If the fitter doesn't exist yet, it will be created on the fly
+   // according to the parameters passed to the constructor.
+   //
+   // The workaround parameter should always be kFALSE. (It is only used by the Add method.)
+   //
+
+   TLinearFitter* fitter = GetFitterSimple(segment, padType);
+   if (fitter == 0) {
+      SetObject(new TLinearFitter(fNdim, fFormula, fOpt), segment, padType);
+      fitter = (TLinearFitter*)(GetObject(segment, padType));
+      if (workaround) {
+         Double_t x[fNdim];
+         for (Int_t i = 0; i < fNdim; i++) x[i] = 3.141592;
+         fitter->AddPoint(x, 31.41592);
+         fitter->ClearPoints();
+         //cout << "workaround called for " << segment << ", " << padType << endl;
+      }
+   }
+   return fitter;
+}
+
+Int_t AliTPCFitPad::Evaluate(Bool_t robust, Double_t frac) {
+   //
+   // Evaluates all fitters. Returns 0 if successful, 1 in case of an error.
+   // If the robust option is set to kTRUE a robust fit is performed with frac as
+   // the minimal fraction of good points (see TLinearFitter::EvalRobust for details).
+   // Beware: Robust fitting is much slower!
+   //
+
+   Int_t returnCode = 0;
+   for (UInt_t iSegment = 0; iSegment < GetNSegments(); iSegment++) {
+      for (UInt_t iPadType = 0; iPadType < GetNPadTypes(); iPadType++) {
+         if (TLinearFitter* fitter = GetFitterSimple(iSegment, iPadType)) {
+            Int_t status = robust ? fitter->EvalRobust(frac) : fitter->Eval();
+            if (status != 0) {
+               returnCode = 1;
+               Error("Evaluate", "Error in evaluation of fitter in segment %d, pad region %d", iSegment, iPadType);
+            }
+         }
+      }
+   }
+   return returnCode;
+}
diff --git a/TPC/TPCcalib/AliTPCFitPad.h b/TPC/TPCcalib/AliTPCFitPad.h
new file mode 100644 (file)
index 0000000..06d51e3
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef ALITPCFITPAD_H
+#define ALITPCFITPAD_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+#include <iostream>
+#include "AliTPCCalPadRegion.h"
+#include <TLinearFitter.h>
+#include <TIterator.h>
+
+using namespace std;
+
+class TString;
+
+class AliTPCFitPad: public AliTPCCalPadRegion {
+public:
+   AliTPCFitPad() : AliTPCCalPadRegion() { }
+   AliTPCFitPad(const AliTPCFitPad& obj) : AliTPCCalPadRegion(obj), fNdim(obj.fNdim), fFormula(obj.fFormula), fOpt(obj.fOpt) { }
+   AliTPCFitPad(Int_t ndim, const char* formula, Option_t* opt = "D");
+   AliTPCFitPad& operator=(const AliTPCFitPad& rhs);
+   //AliTPCFitPad(const char *name, const char *title) : AliTPCCalPadRegion(name, title) { }
+   //AliTPCFitPad(const TString &name, const TString &title) : AliTPCCalPadRegion(name, title) { }
+   virtual ~AliTPCFitPad();
+
+   void           Add(AliTPCFitPad* fit);
+   TLinearFitter* GetFitter(UInt_t segment, UInt_t padType, Bool_t workaround = kFALSE);
+   TLinearFitter* GetFitterSimple(UInt_t segment, UInt_t padType);
+   Int_t          Evaluate(Bool_t robust = kFALSE, Double_t frac = -1.);
+
+protected:
+   Int_t   fNdim;         // used for generating new TLinearFitter objects
+   TString fFormula;      // used for generating new TLinearFitter objects
+   TString fOpt;          // used for generating new TLinearFitter objects
+   
+   ClassDef(AliTPCFitPad, 1)
+};
+
+
+#endif
index 5e006d6..abdd0b7 100644 (file)
@@ -119,8 +119,8 @@ void AliTPCSelectorTracks::InitComponent(){
   fCalibTracks = new AliTPCcalibTracks("calibTracks", "Resolution calibration object for tracks", clusterParam, cuts);
   fOutput->AddLast(fCalibTracks);
    
-   //fCalibTracksGain = new AliTPCcalibTracksGain("calibTracksGain", "Gain calibration object for tracks");
-   //fOutput->AddLast(fCalibTracksGain);
+  fCalibTracksGain = new AliTPCcalibTracksGain("calibTracksGain", "Gain calibration object for tracks", cuts);
+   fOutput->AddLast(fCalibTracksGain);
    fInit=kTRUE;
 }
 
@@ -168,8 +168,7 @@ Int_t AliTPCSelectorTracks::ProcessIn(Long64_t entry)
       fNClusters->Fill(seed->GetNumberOfClusters());
       //
       fCalibTracks->Process(seed, esdTrack);   // analysis is done in fCalibTracks
-      //if (!AliTPCcalibTracksGain::AcceptTrack(seed)) {/*cerr << "not accepted" << endl;*/ continue; }
-      //fCalibTracksGain->AddTrack(seed);
+      fCalibTracksGain->Process(seed);
     }
   }
   CleanESD();
@@ -196,13 +195,14 @@ void AliTPCSelectorTracks::Terminate()
 //       }
 //    }   
    TFile file(fgkOutputFileName, "recreate");
+   fCalibTracksGain->Evaluate();
    fOutput->Write();
    file.Close();
    printf("Successfully written file to '%s'.", fgkOutputFileName);
 
 
    Info("Destructor","Destuctor");
-   //delete fCalibTracksGain;
+   delete fCalibTracksGain;
    delete fCalibTracks;
 //   printf ("Terminate... \n");
 //   if (!fOutput) return;
index f219692..e09f5a2 100644 (file)
@@ -1,3 +1,82 @@
+/**************************************************************************
+ * 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.                  *
+ **************************************************************************/
+
+////////////////////////////////////////////////////////////////////////////
+//                                                                        
+//       === Calibration class for gain calibration using tracks ===
+//
+//    1) Genereal idea
+//    ================
+//       A 6-parametric parabolic function
+//
+//          G(x, y) = p0 + p1*x + p2*y + p3*x^2 + p4*y^2 + p5 * x*y
+//
+//       is fitted to the maximum charge values or total charge values of
+//       all the clusters contained in the tracks that are added to this
+//       object. This fit is performed for each read out chamber, in fact even
+//       for each type of pad sizes (thus for one segment, which consists of
+//       an IROC and an OROC, there are three fitters used, corresponding to
+//       the three pad sizes). The coordinate origin is at the center of the
+//       particular pad size region on each ROC.
+//
+//       Because of the Landau nature of the charge deposition we use
+//       different "types" of fitters instead of one to minimize the effect
+//       of the long Landau tail. The difference between the fitters is only
+//       the charge value, that is put into them, i.e. the charge is subject
+//       to a transformation. At this point we use three different fit types:
+//
+//          a) simple: the charge is put in as it is
+//          b) sqrt:   the square root of the charge is put into the fitter
+//          c) log:    fgkM * Log(1+q/fgkM) is put into the fitter, with
+//                     q being the untransformed charge and fgkM=25
+//
+//       The results of the fits may be visualized and further used by
+//       creating an AliTPCCalROC or AliTPCCalPad. You may specify to undo
+//       the transformation and/or to normalize to the pad size.
+//
+//       Not every track you add to this object is actually used for
+//       calibration. There are some cuts and conditions to exclude bad
+//       tracks, e.g. a pt cut to cut out tracks with too much charge
+//       deposition or a cut on edge clusters which are not fully
+//       registered and don't give a usable signal.
+//
+//    2) Interface / usage
+//    ====================
+//       For each track to be added you need to call Process().
+//       This method expects an AliTPCseed, which contains the necessary
+//       cluster information. At the moment of writing this information
+//       is stored in an AliESDfriend corresponding to an AliESD.
+//       You may also call AddTrack() if you don't want the cuts and
+//       other quality conditions to kick in (thus forcing the object to
+//       accept the track) or AddCluster() for adding single clusters.
+//       Call one of the Evaluate functions to evaluate the fitter(s) and
+//       to retrieve the fit parameters, erros and so on. You can also
+//       do this later on by using the different Getters.
+//
+//       The visualization methods CreateFitCalPad() and CreateFitCalROC()
+//       are straight forward to use.
+//
+//       Note: If you plan to write this object to a ROOT file, make sure
+//             you evaluate all the fitters *before* writing, because due
+//             to a bug in the fitter component writing fitters doesn't
+//             work properly (yet). Be aware that you cannot re-evaluate
+//             the fitters after loading this object from file.
+//             (This will be gone for a new ROOT version > v5-17-05)
+//                                                                        
+////////////////////////////////////////////////////////////////////////////
+
 #include <TPDGCode.h>
 #include <TStyle.h>
 #include "TMatrixD.h"
@@ -13,6 +92,8 @@
 #include <TLinearFitter.h>
 #include <TTreeStream.h>
 #include <TFile.h>
+#include <TCollection.h>
+#include <TIterator.h>
 
 //
 // AliRoot includes
 #include "AliTPCROC.h"
 #include "AliTPCParamSR.h"
 #include "AliTPCCalROC.h"
+#include "AliTPCCalPad.h"
 //
 #include "AliTracker.h"
 #include "AliESD.h"
 #include "AliESDfriendTrack.h" 
 #include "AliTPCseed.h"
 #include "AliTPCclusterMI.h"
+#include "AliTPCcalibTracksCuts.h"
+#include "AliTPCFitPad.h"
 
+// REMOVE ALL OF THIS
+#include <TTree.h>
+#include "AliESDEvent.h"
 
 /*
   
@@ -45,134 +132,287 @@ TVectorD vec(3)
 TMatrixD mat(3,3)
 TString * str = comp.FitPlane("Cl.fQ/dedxQ.fElements[0]","Cl.fY++Cl.fX","Cl.fDetector<36",chi2,vec,mat)
 
-
 */
 
+ClassImp(AliTPCcalibTracksGain)
 
-ClassImp(AliTPCcalibTracksGain);
-
+const Bool_t   AliTPCcalibTracksGain::fgkUseTotalCharge = kTRUE;
 const Double_t AliTPCcalibTracksGain::fgkM = 25.;
+const char*    AliTPCcalibTracksGain::fgkDebugStreamFileName = "TPCCalibTracksGain.root";
+AliTPCParamSR* AliTPCcalibTracksGain::fgTPCparam = new AliTPCParamSR();
 
-AliTPCcalibTracksGain::AliTPCcalibTracksGain(const char* name, const char* title) :
+AliTPCcalibTracksGain::AliTPCcalibTracksGain() :
+   TNamed(),
+   fDebugCalPadRaw(0),
+   fDebugCalPadCorr(0),
+   fDebugStream(0),
+   fSimpleFitter(0),
+   fSqrtFitter(0),
+   fLogFitter(0),
+   fZFitter(0),
+   fPrevIter(0),
+   fCuts(0)
+{
+   //
+   // Default constructor.
+   //
+}
+
+AliTPCcalibTracksGain::AliTPCcalibTracksGain(const AliTPCcalibTracksGain& obj) :
+   TNamed(obj)
+{
+   //
+   // Copy constructor.
+   //
+
+   fDebugCalPadRaw = new AliTPCCalPad(*(obj.fDebugCalPadRaw));
+   fDebugCalPadCorr = new AliTPCCalPad(*(obj.fDebugCalPadCorr));
+   fSimpleFitter = new AliTPCFitPad(*(obj.fSimpleFitter));
+   fSqrtFitter = new AliTPCFitPad(*(obj.fSqrtFitter));
+   fLogFitter = new AliTPCFitPad(*(obj.fLogFitter));
+   fZFitter = new TLinearFitter(*(obj.fZFitter));
+   fPrevIter = new AliTPCcalibTracksGain(*(obj.fPrevIter));
+   fCuts = new AliTPCcalibTracksCuts(*(obj.fCuts));
+}
+
+AliTPCcalibTracksGain& AliTPCcalibTracksGain::operator=(const AliTPCcalibTracksGain& rhs) {
+   //
+   // Assignment operator.
+   //
+
+   if (this != &rhs) {
+      TNamed::operator=(rhs);
+      fDebugCalPadRaw = new AliTPCCalPad(*(rhs.fDebugCalPadRaw));
+      fDebugCalPadCorr = new AliTPCCalPad(*(rhs.fDebugCalPadCorr));
+      fSimpleFitter = new AliTPCFitPad(*(rhs.fSimpleFitter));
+      fSqrtFitter = new AliTPCFitPad(*(rhs.fSqrtFitter));
+      fLogFitter = new AliTPCFitPad(*(rhs.fLogFitter));
+      fZFitter = new TLinearFitter(*(rhs.fZFitter));
+      fPrevIter = new AliTPCcalibTracksGain(*(rhs.fPrevIter));
+      fCuts = new AliTPCcalibTracksCuts(*(rhs.fCuts));
+   }
+   return *this;
+}
+
+AliTPCcalibTracksGain::AliTPCcalibTracksGain(const char* name, const char* title, AliTPCcalibTracksCuts* cuts, AliTPCcalibTracksGain* prevIter) :
    TNamed(name, title),
+   fDebugCalPadRaw(0),
+   fDebugCalPadCorr(0),
    fDebugStream(0),
-   fShortFitter(0),
-   fMediumFitter(0),
-   fLongFitter(0),
-   fSqrtShortFitter(0),
-   fSqrtMediumFitter(0),
-   fSqrtLongFitter(0),
-   fLogShortFitter(0),
-   fLogMediumFitter(0),
-   fLogLongFitter(0),
-   fTPCparam(0)
- {
+   fSimpleFitter(0),
+   fSqrtFitter(0),
+   fLogFitter(0),
+   fZFitter(0),
+   fPrevIter(0),
+   fCuts(0)
+{
    //
-   // constructor
+   // Constructor.
    //
    
    //TH1::AddDirectory(kFALSE);
    G__SetCatchException(0);
 
-   for (UInt_t iSegment = 0; iSegment < 36; iSegment++) {
-      fNShortClusters[iSegment] = 0;
-      fNMediumClusters[iSegment] = 0;
-      fNLongClusters[iSegment] = 0;
-   }
+   fCuts = cuts;
+   fPrevIter = prevIter;
 
-   fShortFitter = new TObjArray(36);
-   fMediumFitter = new TObjArray(36);
-   fLongFitter = new TObjArray(36);
+   fSimpleFitter = new AliTPCFitPad(6, "hyp5", "");
+   fSqrtFitter   = new AliTPCFitPad(6, "hyp5", "");
+   fLogFitter    = new AliTPCFitPad(6, "hyp5", "");
+
+   fZFitter      = new TLinearFitter(2, "hyp1", "");
+   // workaround for TLinearFitter
+   Double_t workaround = 3.141592;
+   fZFitter->AddPoint(&workaround, 31.41592);
+   fZFitter->ClearPoints();
+
+   // just for debugging
+   fTotalTracks     = 0;
+   fAcceptedTracks  = 0;
+   fDebugCalPadRaw  = new AliTPCCalPad("DebugCalPadRaw", "All clusters simply added up before correction");
+   fDebugCalPadCorr = new AliTPCCalPad("DebugCalPadCorr", "All clusters simply added up after correction");
    
-   fSqrtShortFitter = new TObjArray(36);
-   fSqrtMediumFitter = new TObjArray(36);
-   fSqrtLongFitter = new TObjArray(36);
+   // this will be gone for the a new ROOT version > v5-17-05
+   for (UInt_t i = 0; i < 36; i++) {
+      fNShortClusters[i]  = 0;
+      fNMediumClusters[i] = 0;
+      fNLongClusters[i]   = 0;
+   }
+ }
+
+AliTPCcalibTracksGain::~AliTPCcalibTracksGain() {
+   //
+   // Destructor.
+   //
    
-   fLogShortFitter = new TObjArray(36);
-   fLogMediumFitter = new TObjArray(36);
-   fLogLongFitter = new TObjArray(36);
+   if (fSimpleFitter) delete fSimpleFitter;
+   if (fSqrtFitter) delete fSqrtFitter;
+   if (fLogFitter) delete fLogFitter;
 
-   for (UInt_t iSegment = 0; iSegment < 36; iSegment++) {   
-      fShortFitter->Add(new TLinearFitter(6, "hyp5"));
-      fMediumFitter->Add(new TLinearFitter(6, "hyp5"));
-      fLongFitter->Add(new TLinearFitter(6, "hyp5"));
-      
-      fSqrtShortFitter->Add(new TLinearFitter(6, "hyp5"));
-      fSqrtMediumFitter->Add(new TLinearFitter(6, "hyp5"));
-      fSqrtLongFitter->Add(new TLinearFitter(6, "hyp5"));
-      
-      fLogShortFitter->Add(new TLinearFitter(6, "hyp5"));
-      fLogMediumFitter->Add(new TLinearFitter(6, "hyp5"));
-      fLogLongFitter->Add(new TLinearFitter(6, "hyp5"));
+   if (fZFitter) delete fZFitter;
+
+   if (fDebugStream) {
+      //fDebugStream->GetFile()->Close();
+      printf("Deleting debug stream object\n");
+      delete fDebugStream;
+   }
+
+   if (fDebugCalPadRaw) delete fDebugCalPadRaw;
+   if (fDebugCalPadCorr) delete fDebugCalPadCorr;
+}
+
+void AliTPCcalibTracksGain::AddInfo(TChain* chain, char* fileName) {
+   // 
+   // Add some parameters from a previous run (AliTPCcalibTracksGain object contained
+   // in root file fileName) to the chain.
+   // Note: The parameters are *not* added to this class, you need to do it later by retrieving
+   // the parameters from the chain and passing them to the constructor!
+   //
    
-      ((TLinearFitter*)(fShortFitter->At(iSegment)))->StoreData(kFALSE);
-      ((TLinearFitter*)(fMediumFitter->At(iSegment)))->StoreData(kFALSE);
-      ((TLinearFitter*)(fLongFitter->At(iSegment)))->StoreData(kFALSE);
-      ((TLinearFitter*)(fSqrtShortFitter->At(iSegment)))->StoreData(kFALSE);
-      ((TLinearFitter*)(fSqrtMediumFitter->At(iSegment)))->StoreData(kFALSE);
-      ((TLinearFitter*)(fSqrtLongFitter->At(iSegment)))->StoreData(kFALSE);
-      ((TLinearFitter*)(fLogShortFitter->At(iSegment)))->StoreData(kFALSE);
-      ((TLinearFitter*)(fLogMediumFitter->At(iSegment)))->StoreData(kFALSE);
-      ((TLinearFitter*)(fLogLongFitter->At(iSegment)))->StoreData(kFALSE);
+   TFile paramFile(fileName);
+   if (paramFile.IsZombie()) {
+      printf("File %s not found. Continuing without z dependence parametrisation.\n", fileName);
+      return;
    }
    
-   fTPCparam = new AliTPCParamSR();
- }   
+   AliTPCcalibTracksGain *prevIter = (AliTPCcalibTracksGain*)paramFile.Get("calibTracksGain");
+   if (prevIter) {
+      //TVectorD* param = new TVectorD(2);
+      //prevIter->fZFitter->GetParameters(*param);
+      //chain->GetUserInfo()->AddLast((TObject*)param);
+      chain->GetUserInfo()->AddLast((TObject*)prevIter);
+   } else
+      printf("No calibTracksGain object found. Continuing without z dependence parametrisation.\n");
+}
 
-AliTPCcalibTracksGain::~AliTPCcalibTracksGain() {
+Int_t AliTPCcalibTracksGain::AcceptTrack(AliTPCseed* track) {
    //
-   // destructor
+   // Decides whether to accept a track or not.
+   // Tracks are discarded, if due to edge effects, the number of clusters
+   // is too low, the ratio of the number of clusters and the findable clusters is too low
+   // or the transverse momentum is too low.
+   // The corresponding cut values are specified in the fCuts member.
    //
    
-   //if (fDebugStream) delete fDebugStream;
+   if (track->GetNumberOfClusters() < fCuts->GetMinClusters()) return 1;
+   if ((TMath::Abs(track->GetY() / track->GetX()) > fCuts->GetEdgeYXCutNoise())
+      && (TMath::Abs(track->GetTgl()) < fCuts->GetEdgeThetaCutNoise())) return 2;
+   if (track->GetNumberOfClusters() / (track->GetNFoundable()+1.) < fCuts->GetMinRatio()) return 3;
+   if (TMath::Abs(track->GetSigned1Pt()) > fCuts->GetMax1pt()) return 4;
    
-   if (fShortFitter) { fShortFitter->Delete(); delete fShortFitter; }
-   if (fMediumFitter) { fMediumFitter->Delete(); delete fMediumFitter; }
-   if (fLongFitter) { fLongFitter->Delete(); delete fLongFitter; }
+   //if (track->GetPt() < 50.) return kFALSE;
+   return 0;
+}
+
+/*Bool_t AliTPCcalibTracksGain::AcceptCluster(AliTPCclusterMI* cluster) {
+   //
+   // Decides whether to accept a cluster or not.
+   //
 
-   if (fSqrtShortFitter) { fSqrtShortFitter->Delete(); delete fSqrtShortFitter; }
-   if (fSqrtMediumFitter) { fSqrtMediumFitter->Delete(); delete fSqrtMediumFitter; }
-   if (fSqrtLongFitter) { fSqrtLongFitter->Delete(); delete fSqrtLongFitter; }
+   // cluster type < 0: edge cluster
+   // cluster type = 0: "golden" (i.e. good) cluster
+   // cluster type > 0: overlapping cluster
+   if (cluster->GetType() != 0) { Info("AcceptCluster", "Cluster not accepted (type %d)", cluster->GetType()); return kFALSE;}
+
+   // remove edge clusters
+   
+   
+   return kTRUE;
+}*/
 
-   if (fLogShortFitter) { fLogShortFitter->Delete(); delete fLogShortFitter; }
-   if (fLogMediumFitter) { fLogMediumFitter->Delete(); delete fLogMediumFitter; }
-   if (fLogLongFitter) { fLogLongFitter->Delete(); delete fLogLongFitter; }
-   //fDebugStream->GetFile()->Close();
-   printf("Deleting debug stream\n");
-   delete fDebugStream;
-   if (fTPCparam) delete fTPCparam;
+void AliTPCcalibTracksGain::Process(AliTPCseed* seed) {
+   //
+   // Main method to be called when a new seed is supposed to be processed
+   // and be used for gain calibration. Its quality is checked before it
+   // is added.
+   //
+   
+   fTotalTracks++;
+   //fTrackPt->Fill(seed->GetSignedPt());
+   Int_t status = AcceptTrack(seed);
+   if (status != 0) { /*cout << "Track not accepted (reason " << status << ")" << endl;*/ return; }
+   fAcceptedTracks++;
+   AddTrack(seed);
 }
 
+Long64_t AliTPCcalibTracksGain::Merge(TCollection *list) {
+   //
+   // Merge() merges the results of all AliTPCcalibTracksGain objects contained in
+   // list, thus allowing a distributed computation of several files, e.g. on PROOF.
+   // The merged results are stored in the data members of the AliTPCcalibTracksGain
+   // object used for calling the Merge method.
+   // The return value is 0 /*the total number of tracks used for calibration*/ if the merge
+   // is successful, otherwise it is -1.
+   //
 
-Bool_t AliTPCcalibTracksGain::AcceptTrack(AliTPCseed * track){
-  //
-  // Decides whether to accept a track or not.
-  // Tracks are discarded, if due to edge effects, the number of clusters
-  // is too low, the ratio of the number of clusters and the findable clusters is too low,
-  // ...
-  //
-  
-  const Int_t   kMinClusters  = 20;
-  const Float_t kMinRatio     = 0.4;
-  const Float_t kMax1pt       = 0.5;
-  const Float_t kEdgeYXCutNoise    = 0.13;
-  const Float_t kEdgeThetaCutNoise = 0.018;
-  //
-  // edge induced noise tracks - NEXT RELEASE will be removed during tracking
-  if (TMath::Abs(track->GetY()/track->GetX())> kEdgeYXCutNoise)
-    if (TMath::Abs(track->GetTgl())<kEdgeThetaCutNoise) { /*cerr << "[edge induced] " << flush;*/ return kFALSE; }
-  
-  //
-  if (track->GetNumberOfClusters()<kMinClusters) { /*cerr << "[only " << track->GetNumberOfClusters() << " clusters] " << flush;*/ return kFALSE; }
-  Float_t ratio = track->GetNumberOfClusters()/(track->GetNFoundable()+1.);
-  if (ratio<kMinRatio) {/*cerr << "[ratio " << ratio << "] " << flush;*/ return kFALSE; }
-  Float_t mpt = track->GetSigned1Pt();
-  if (TMath::Abs(mpt)>kMax1pt) { /*cerr << "[mpt " << mpt << "] " << flush;*/ return kFALSE; }
-  //if (TMath::Abs(track->GetZ())>240.) return kFALSE;
-  //if (TMath::Abs(track->GetZ())<10.) return kFALSE;
-  //if (TMath::Abs(track->GetTgl())>0.03) return kFALSE;
-  
-  return kTRUE;
+   if (!list || list->IsEmpty()) return -1;
+   
+   // reset the data members first
+   if (fSimpleFitter) delete fSimpleFitter;
+   if (fSqrtFitter)   delete fSqrtFitter;
+   if (fLogFitter)    delete fLogFitter;
+   if (fZFitter)      delete fZFitter;
+   fSimpleFitter = new AliTPCFitPad(6, "hyp5", "");
+   fSqrtFitter   = new AliTPCFitPad(6, "hyp5", "");
+   fLogFitter    = new AliTPCFitPad(6, "hyp5", "");
+   fZFitter      = new TLinearFitter(2, "hyp1", "");
+   // workaround for TLinearFitter
+   Double_t workaround = 3.141592;
+   fZFitter->AddPoint(&workaround, 31.41592);
+   fZFitter->ClearPoints();
+
+   // this will be gone for the a new ROOT version > v5-17-05
+   for (UInt_t i = 0; i < 36; i++) {
+      fNShortClusters[i]  = 0;
+      fNMediumClusters[i] = 0;
+      fNLongClusters[i]   = 0;
+   }
+
+   // just for debugging
+   if (fDebugCalPadRaw)  delete fDebugCalPadRaw;
+   if (fDebugCalPadCorr) delete fDebugCalPadCorr;
+   fDebugCalPadRaw  = new AliTPCCalPad("DebugCalPadRaw", "All clusters simply added up before correction");
+   fDebugCalPadCorr = new AliTPCCalPad("DebugCalPadCorr", "All clusters simply added up after correction");
+   fTotalTracks     = 0;
+   fAcceptedTracks  = 0;
+   
+   TIterator* iter = list->MakeIterator();
+   AliTPCcalibTracksGain* cal = 0;
+   
+   while ((cal = (AliTPCcalibTracksGain*)iter->Next())) {
+      if (!cal->InheritsFrom(AliTPCcalibTracksGain::Class())) {
+         Error("Merge","Attempt to add object of class %s to a %s", cal->ClassName(), this->ClassName());
+         return -1;
+      }
+      Add(cal);
+   }
+   return 0;
+}
+
+void AliTPCcalibTracksGain::Add(AliTPCcalibTracksGain* cal) {
+   //
+   // Adds another AliTPCcalibTracksGain object to this object.
+   //
+   
+   fSimpleFitter->Add(cal->fSimpleFitter);
+   fSqrtFitter->Add(cal->fSqrtFitter);
+   fLogFitter->Add(cal->fLogFitter);
+   fZFitter->Add(cal->fZFitter);
+
+   // this will be gone for the a new ROOT version > v5-17-05
+   for (UInt_t iSegment = 0; iSegment < 36; iSegment++) {
+      fNShortClusters[iSegment] += cal->fNShortClusters[iSegment];
+      fNMediumClusters[iSegment] += cal->fNMediumClusters[iSegment];
+      fNLongClusters[iSegment] += cal->fNLongClusters[iSegment];
+   }
+   
+   // just for debugging, remove me
+   fTotalTracks += cal->fTotalTracks;
+   fAcceptedTracks += cal->fAcceptedTracks;
+   fDebugCalPadRaw->Add(cal->fDebugCalPadRaw);
+   fDebugCalPadCorr->Add(cal->fDebugCalPadCorr);
+
+   // Let's see later what to do with fCuts and fDebugStream
 }
 
 void AliTPCcalibTracksGain::AddTrack(AliTPCseed* seed) {
@@ -180,26 +420,31 @@ void AliTPCcalibTracksGain::AddTrack(AliTPCseed* seed) {
    // The clusters making up the track (seed) are added to various fit functions.
    // See AddCluster(...) for more detail.
    //
-  if (!fDebugStream) fDebugStream = new TTreeSRedirector("TPCCalibTracksGain.root");
+   
+   if (!fDebugStream) fDebugStream = new TTreeSRedirector(fgkDebugStreamFileName);
+   DumpTrack(seed);
 
+   AliTPCcalibTracksGain::PreProcess preProc(seed);
    for (Int_t iCluster = 0; iCluster < 159; iCluster++) {
       AliTPCclusterMI* cluster = seed->GetClusterPointer(iCluster);
-      if (cluster) AddCluster(cluster);
+      if (cluster && preProc.IsClusterAccepted(iCluster)) AddCluster(cluster, preProc);
    }
-   DumpTrack(seed);
 }
 
-void AliTPCcalibTracksGain::AddCluster(AliTPCclusterMI* cluster) {
+void AliTPCcalibTracksGain::AddCluster(AliTPCclusterMI* cluster, AliTPCcalibTracksGain::PreProcess& preProc) {
    //
    // Adds cluster to the appropriate fitter for later analysis.
-   // The charge used for the fit is the maximum charge for this specific cluster.
-   // It is planned to add a switch to use the accumulated charge per cluster instead.
+   // The charge used for the fit is the maximum charge for this specific cluster or the
+   // accumulated charge per cluster, depending on the value of fgkUseTotalCharge.
    // Depending on the pad size where the cluster is registered, the value will be put in
    // the appropriate fitter. Furthermore, for each pad size three different types of fitters
    // are used. The fit functions are the same for all fitters (parabolic functions), but the value
    // added to each fitter is different. The simple fitter gets the charge plugged in as is, the sqrt fitter
    // gets the square root of the charge, and the log fitter gets fgkM*(1+q/fgkM), where q is the original charge
    // and fgkM==25.
+   // The preProc object is used for passing information which was gained by preprocessing the seed to which the
+   // cluster belongs. It is used for correcting the charge due to various effects, e.g. its dependence
+   // on the track length over each pad.
    //
 
    if (!cluster) {
@@ -209,24 +454,13 @@ void AliTPCcalibTracksGain::AddCluster(AliTPCclusterMI* cluster) {
    
    Double_t xx[5];
    
-   // this block is for using the center of the region with the same pad size as origin for the fit function,
-   // comment it out if you want the origin at lx=ly=0.
-   Float_t centerPad[3] = {0};
-   AliTPCROC* tpcROC = AliTPCROC::Instance();
    Int_t padType = GetPadType(cluster->GetX());
-   Int_t IOROC = (padType == 0) ? 0 : tpcROC->GetNInnerSector();
-   //tpcROC->GetPositionLocal(IOROC, tpcROC->GetNRows(IOROC)/2, tpcROC->GetNPads(IOROC, tpcROC->GetNRows(IOROC)/2)/2, centerPad);  // use this instead of the switch statement if you want to calculate the center of the ROC and not the center of the regions with the same pad size
-   switch (padType) {
-      case kShortPads:
-         tpcROC->GetPositionLocal(IOROC, tpcROC->GetNRows(IOROC)/2, tpcROC->GetNPads(IOROC, tpcROC->GetNRows(IOROC)/2)/2, centerPad);
-         break;
-      case kMediumPads:
-         tpcROC->GetPositionLocal(IOROC, 64/2, tpcROC->GetNPads(IOROC, 64/2)/2, centerPad);
-         break;
-      case kLongPads:
-         tpcROC->GetPositionLocal(IOROC, 64+32/2, tpcROC->GetNPads(IOROC, 64+32/2)/2, centerPad);
-         break;
-   }
+   Double_t centerPad[2] = {0};
+   // this line is for using the center of the region with the same pad size as origin for the fit function,
+   // comment out the appropriate lines in AliTPCCalPadRegion::GetPadRegionCenterLocal() and here if you
+   // want the origin at lx=ly=0.
+   AliTPCFitPad::GetPadRegionCenterLocal(padType, centerPad);
+   
    xx[0] = cluster->GetX() - centerPad[0];
    xx[1] = cluster->GetY() - centerPad[1];
    
@@ -237,28 +471,67 @@ void AliTPCcalibTracksGain::AddCluster(AliTPCclusterMI* cluster) {
    xx[4] = xx[0] * xx[1];
 
    Int_t segment = cluster->GetDetector() % 36;
-   Double_t q = ((Double_t)(cluster->GetMax()));  // note: no normalization to pad size!
+   Double_t q = fgkUseTotalCharge ? ((Double_t)(cluster->GetQ())) : ((Double_t)(cluster->GetMax()));  // note: no normalization to pad size!
+   //cerr << "AngleTrackPadrow(" << segment << ", " << padType << ") == " << preProc.GetAngleTrackPadrow(segment, padType) * TMath::RadToDeg() << endl;
+   //cerr << "AngleTrackBeam  (" << segment << ", " << padType << ") == " << preProc.GetAngleTrackBeam(segment, padType) * TMath:: RadToDeg() << endl;
+   //cerr << "Correction factor == " << TMath::Abs(TMath::Sin(preProc.GetAngleTrackPadrow(segment, padType))*TMath::Sin(preProc.GetAngleTrackBeam(segment, padType)))/GetPadLength(cluster->GetX()) << endl;
+
+   // just for debugging
+   Int_t row = 0;
+   Int_t pad = 0;
+   GetRowPad(cluster->GetX(), cluster->GetY(), row, pad);
+   fDebugCalPadRaw->GetCalROC(cluster->GetDetector())->SetValue(row, pad, q + fDebugCalPadRaw->GetCalROC(cluster->GetDetector())->GetValue(row, pad));
+   
+   // correct charge by normalising to mean charge per track
+   //q = TMath::Abs(TMath::Sin(preProc.GetAngleTrackPadrow(segment, padType))*TMath::Sin(preProc.GetAngleTrackBeam(segment, padType)))*q/(GetPadLength(cluster->GetX()) /* * preProc.GetMeanCharge(segment, padType) */);
+   //q *= TMath::Abs(TMath::Sin(preProc.GetAngleTrackPadrow(segment, padType))) / (/*GetPadLength(cluster->GetX()) * */preProc.GetMeanCharge(segment, padType));
+   q /= preProc.GetMeanCharge(segment, padType);
+   //q /= (1 + 0.36 * TMath::Abs(1/TMath::Tan(preProc.GetAngleTrackPadrow(segment, padType))));
+
+   // correct charge for dependency on z distance using previous iteration
+   if (fPrevIter) {
+      TVectorD param(2);
+      fPrevIter->fZFitter->GetParameters(param);
+      q /= param[0] + param[1] * (TMath::Abs(cluster->GetZ()) - TMath::Abs(preProc.GetMeanZ(segment, padType)));
+   }
+   
+   // just for debugging
+   fDebugCalPadCorr->GetCalROC(cluster->GetDetector())->SetValue(row, pad, q + fDebugCalPadCorr->GetCalROC(cluster->GetDetector())->GetValue(row, pad));
+
    Double_t sqrtQ = TMath::Sqrt(q);
    Double_t logQ = fgkM * TMath::Log(1 + q / fgkM);
-   if (padType == kShortPads) {
-      ((TLinearFitter*)(fShortFitter->At(segment)))->AddPoint(xx, q);
-      ((TLinearFitter*)(fSqrtShortFitter->At(segment)))->AddPoint(xx, sqrtQ);
-      ((TLinearFitter*)(fLogShortFitter->At(segment)))->AddPoint(xx, logQ);
+   fSimpleFitter->GetFitter(segment, padType)->AddPoint(xx, q);
+   fSqrtFitter->GetFitter(segment, padType)->AddPoint(xx, sqrtQ);
+   fLogFitter->GetFitter(segment, padType)->AddPoint(xx, logQ);
+
+   Double_t zz = TMath::Abs(cluster->GetZ()) - TMath::Abs(preProc.GetMeanZ(segment, padType));
+   fZFitter->AddPoint(&zz, q);
+   
+   // this will be gone for the a new ROOT version > v5-17-05
+   if (padType == kShortPads)
       fNShortClusters[segment]++;
-   } else if (padType == kMediumPads) {
-      ((TLinearFitter*)(fMediumFitter->At(segment)))->AddPoint(xx, q);
-      ((TLinearFitter*)(fSqrtMediumFitter->At(segment)))->AddPoint(xx, sqrtQ);
-      ((TLinearFitter*)(fLogMediumFitter->At(segment)))->AddPoint(xx, logQ);
+   else if (padType == kMediumPads)
       fNMediumClusters[segment]++;
-   } else if (padType == kLongPads) {
-      ((TLinearFitter*)(fLongFitter->At(segment)))->AddPoint(xx, q);
-      ((TLinearFitter*)(fSqrtLongFitter->At(segment)))->AddPoint(xx, sqrtQ);
-      ((TLinearFitter*)(fLogLongFitter->At(segment)))->AddPoint(xx, logQ);
+   else if (padType == kLongPads)
       fNLongClusters[segment]++;
-   }
 }
 
-Int_t AliTPCcalibTracksGain::Evaluate(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD* fitParam, TVectorD* fitError, Double_t* redChi2, Bool_t robust) {
+void AliTPCcalibTracksGain::Evaluate(Bool_t robust, Double_t frac) {
+   //
+   // Evaluates all fitters contained in this object.
+   // If the robust option is set to kTRUE a robust fit is performed with frac as
+   // the minimal fraction of good points (see TLinearFitter::EvalRobust for details).
+   // Beware: Robust fitting is much slower!
+   //
+   
+   fSimpleFitter->Evaluate(robust, frac);
+   fSqrtFitter->Evaluate(robust, frac);
+   fLogFitter->Evaluate(robust, frac);
+   if (robust) fZFitter->EvalRobust(frac);
+   else        fZFitter->Eval();
+}
+
+Int_t AliTPCcalibTracksGain::Evaluate(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD* fitParam, TVectorD* fitError, Double_t* redChi2, Bool_t robust, Double_t frac) {
    //
    // Evaluate the tracks for obtaining the calibration information.
    // segment specifies the segment (IROC & OROC) for which the fitter shall be evaluated (it can take values from
@@ -269,11 +542,17 @@ Int_t AliTPCcalibTracksGain::Evaluate(UInt_t segment, UInt_t padType, UInt_t fit
    // the same is valid for fitError, which will contain the errors of course.
    // redChi2 is a pointer to an Int_t value which will contain the reduced chi^2 of the fit.
    // If fitParam, fitError or redChi2 is a null pointer, the corresponding value is not calculated.
-   // robust specifies wether the fitter's robust fitting mode shall be used (use with caution, it takes looooong!)
+   // If the robust option is set to kTRUE a robust fit is performed with frac as
+   // the minimal fraction of good points (see TLinearFitter::EvalRobust for details).
+   // Beware: Robust fitting is much slower!
+   // Evaluate() returns the number of clusters in the specified padType.
    //
 
    TLinearFitter* fitter = GetFitter(segment, padType, fitType);
    Int_t NClusters = 0;
+   // this will be gone for a new ROOT version > v5-17-05
+   // and replaced by
+   // UInt_t NClusters = fSimpleFitter->GetFitter(segment, padType)->GetNpoints();
    switch (padType) {
       case kShortPads:
          NClusters = fNShortClusters[segment];
@@ -286,7 +565,7 @@ Int_t AliTPCcalibTracksGain::Evaluate(UInt_t segment, UInt_t padType, UInt_t fit
          break;
    }
 
-   if (robust) fitter->EvalRobust();
+   if (robust) fitter->EvalRobust(frac);
    else fitter->Eval();
    
    if (redChi2) *redChi2 = fitter->GetChisquare()/(NClusters - 6);
@@ -299,50 +578,75 @@ Int_t AliTPCcalibTracksGain::Evaluate(UInt_t segment, UInt_t padType, UInt_t fit
    return NClusters;
 }
 
-AliTPCCalROC* AliTPCcalibTracksGain::CreateFitCalROC(UInt_t sector, UInt_t padType, TVectorD &fitParam, Int_t undoTransformation, Bool_t normalizeToPadSize) {
+AliTPCCalPad* AliTPCcalibTracksGain::CreateFitCalPad(UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) {
+   TObjArray tpc(72);
+   for (UInt_t iSector = 0; iSector < 72; iSector++)
+      tpc.Add(CreateFitCalROC(iSector, fitType, undoTransformation, normalizeToPadSize));
+   return new AliTPCCalPad(&tpc);
+}
+
+AliTPCCalROC* AliTPCcalibTracksGain::CreateFitCalROC(UInt_t sector, UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) {
+   TVectorD par(6);
+   if (sector < 36) {
+      GetParameters(sector % 36, 0, fitType, par);
+      return CreateFitCalROC(sector, 0, par, fitType, undoTransformation, normalizeToPadSize);
+   }
+   else {
+      GetParameters(sector % 36, 1, fitType, par);
+      AliTPCCalROC* roc1 = CreateFitCalROC(sector, 1, par, fitType, undoTransformation, normalizeToPadSize);
+      GetParameters(sector % 36, 2, fitType, par);
+      AliTPCCalROC* roc2 = CreateFitCalROC(sector, 2, par, fitType, undoTransformation, normalizeToPadSize);
+      AliTPCCalROC* roc3 = CreateCombinedCalROC(roc1, roc2);
+      delete roc1;
+      delete roc2;
+      return roc3;
+   }
+}
+
+AliTPCCalROC* AliTPCcalibTracksGain::CreateFitCalROC(UInt_t sector, UInt_t padType, TVectorD &fitParam, UInt_t fitType, Bool_t undoTransformation, Bool_t normalizeToPadSize) {
    //
    // This function is essentially a copy of AliTPCCalROC::CreateGlobalFitCalROC(...), with the
    // modifications, that the center of the region of same pad size is used as the origin
    // of the fit function instead of the center of the ROC.
    // The possibility of a linear fit is removed as well because it is not needed.
    // Only values for pads with the given pad size are calculated, the rest is 0.
-   // Set undoTransformation to 0, 1 or 2 for undoing the transformation that was applied to the
+   // Set undoTransformation for undoing the transformation that was applied to the
    // charge values before they were put into the fitter (thus allowing comparison to the original
-   // charge values). Use 0 for the simple fitter, 1 for the sqrt fitter, 2 for the log fitter.
-   // Set it to -1 (or any other value) if you don't want any transformations undone (at the moment this is equivalent
-   // with the transformation for the simple fitter (because no transformation is applied to the simple
-   // fitter)).
+   // charge values). For fitType use 0 for the simple fitter, 1 for the sqrt fitter, 2 for the log fitter.
    // If normalizeToPadSize is true, the values are normalized to the pad size.
+   // Please be aware, that you even need to specify the fitType if you want to normalize to the pad size without
+   // undoing the transformation (because normalizing involves undoing the trafo first, then normalizing, then
+   // applying the trafo again).
+   // Please note: The normalization to the pad size is a simple linear scaling with the pad length, which
+   //              actually doesn't describe reality!
    //
    
    Float_t dlx, dly;
-   Float_t centerPad[3] = {0};
+   Double_t centerPad[2] = {0};
    Float_t localXY[3] = {0};
    AliTPCROC* tpcROC = AliTPCROC::Instance();
    if ((padType == 0 && sector >= tpcROC->GetNInnerSector()) || (padType > 0 && sector < tpcROC->GetNInnerSector()) || sector >= tpcROC->GetNSector())
       return 0;
    AliTPCCalROC* ROCfitted = new AliTPCCalROC(sector);
    //tpcROC->GetPositionLocal(sector, ROCfitted->GetNrows()/2, ROCfitted->GetNPads(ROCfitted->GetNrows()/2)/2, centerPad);  // use this instead of the switch statement if you want to calculate the center of the ROC and not the center of the regions with the same pad size
-   UInt_t startRow;
-   UInt_t endRow;
+   UInt_t startRow = 0;
+   UInt_t endRow = 0;
    switch (padType) {
       case kShortPads:
          startRow = 0;
          endRow = ROCfitted->GetNrows();
-         tpcROC->GetPositionLocal(sector, endRow/2, ROCfitted->GetNPads(endRow/2)/2, centerPad);
          break;
       case kMediumPads:
          startRow = 0;
          endRow = 64;
-         tpcROC->GetPositionLocal(sector, endRow/2, ROCfitted->GetNPads(endRow/2)/2, centerPad);
          break;
       case kLongPads:
          startRow = 64;
          endRow = ROCfitted->GetNrows();
-         tpcROC->GetPositionLocal(sector, (endRow+startRow)/2, ROCfitted->GetNPads((endRow+startRow)/2)/2, centerPad);
          break;
    }
-   
+
+   AliTPCFitPad::GetPadRegionCenterLocal(padType, centerPad);   
    Double_t value = 0;
    for (UInt_t irow = startRow; irow < endRow; irow++) {
       for (UInt_t ipad = 0; ipad < ROCfitted->GetNPads(irow); ipad++) {
@@ -350,12 +654,33 @@ AliTPCCalROC* AliTPCcalibTracksGain::CreateFitCalROC(UInt_t sector, UInt_t padTy
          dlx = localXY[0] - centerPad[0];
          dly = localXY[1] - centerPad[1];
          value = fitParam[0] + fitParam[1]*dlx + fitParam[2]*dly + fitParam[3]*dlx*dlx + fitParam[4]*dly*dly + fitParam[5]*dlx*dly;
-         switch (undoTransformation) {
-            case  1: value = value * value; break;
-            case  2: value = (TMath::Exp(value / fgkM) - 1) * fgkM; break;
-            default: break;
+
+         // Let q' = value be the transformed value without any pad size corrections,
+         // let T be the transformation and let l be the pad size
+         //    1) don't undo transformation, don't normalize: return q'
+         //    2) undo transformation,       don't normalize: return T^{-1} q'
+         //    3) undo transformation,       normalize:       return (T^{-1} q') / l
+         //    4) don't undo transformation, normalize:       return T((T^{-1} q') / l)
+         if (!undoTransformation && !normalizeToPadSize) {/* value remains unchanged */}  // (1)
+         else {                                                                           // (2), (3), (4)
+            //calculate T^{-1}
+            switch (fitType) {
+               case  0: /* value remains unchanged */ break;
+               case  1: value = value * value; break;
+               case  2: value = (TMath::Exp(value / fgkM) - 1) * fgkM; break;
+               default: Error("CreateFitCalROC", "Wrong fit type."); break;
+            }
+            if (normalizeToPadSize) value /= GetPadLength(localXY[0]);                    // (3)
+         }
+         if (!undoTransformation && normalizeToPadSize) {                                 // (4)
+            // calculate T
+            switch (fitType) {
+               case  0: /* value remains unchanged */ break;
+               case  1: value = TMath::Sqrt(value); break;
+               case  2: value = fgkM * TMath::Log(1 + value / fgkM); break;
+               default: Error("CreateFitCalROC", "Wrong fit type."); break;
+            }
          }
-         if (normalizeToPadSize) value /= GetPadLength(localXY[0]);
          ROCfitted->SetValue(irow, ipad, value);
       }
    }
@@ -371,8 +696,8 @@ AliTPCCalROC* AliTPCcalibTracksGain::CreateCombinedCalROC(const AliTPCCalROC* ro
    //
 
    if (!roc1 || !roc2) return 0;
-   if ((Int_t)(roc1->GetSector()) < fTPCparam->GetNInnerSector()) return 0;
-   if ((Int_t)(roc2->GetSector()) < fTPCparam->GetNInnerSector()) return 0;
+   if ((Int_t)(roc1->GetSector()) < fgTPCparam->GetNInnerSector()) return 0;
+   if ((Int_t)(roc2->GetSector()) < fgTPCparam->GetNInnerSector()) return 0;
    if (roc1->GetSector() != roc2->GetSector()) Warning("CreateCombinedCalROC", "Sector number mismatch.");
    AliTPCCalROC* roc = new AliTPCCalROC(roc1->GetSector());
    
@@ -447,33 +772,29 @@ TLinearFitter* AliTPCcalibTracksGain::GetFitter(UInt_t segment, UInt_t padType,
    // padType is one of kShortPads, kMediumPads, kLongPads. fitType is one of kSimpleFitter, kSqrtFitter, kLogFitter.
    //
    
-   if (segment >= 36 || padType > 2 || fitType > 2) {
-      Error("GetFitter", "Index out of bounds.");
-      return 0;
-   }
-   switch (padType) {
-      case kShortPads:
-         return (TLinearFitter*)((fitType == kSimpleFitter) ? fShortFitter->At(segment) : ((fitType == kSqrtFitter) ? fSqrtShortFitter->At(segment) : fLogShortFitter->At(segment)));
-      case kMediumPads:
-         return (TLinearFitter*)((fitType == kSimpleFitter) ? fMediumFitter->At(segment) : ((fitType == kSqrtFitter) ? fSqrtMediumFitter->At(segment) : fLogMediumFitter->At(segment)));
-      case kLongPads:
-         return (TLinearFitter*)((fitType == kSimpleFitter) ? fLongFitter->At(segment) : ((fitType == kSqrtFitter) ? fSqrtLongFitter->At(segment) : fLogLongFitter->At(segment)));
+   switch (fitType) {
+      case kSimpleFitter:
+         return fSimpleFitter->GetFitter(segment, padType);
+      case kSqrtFitter:
+         return fSqrtFitter->GetFitter(segment, padType);
+      case kLogFitter:
+         return fLogFitter->GetFitter(segment, padType);
    }
    return 0;
 }
 
 Double_t AliTPCcalibTracksGain::GetPadLength(Double_t lx) {
    //
-   // The function returns 0 for an IROC, 1 for an OROC at medium pad size position,
-   // 2 for an OROC at long pad size position, -1 if out of bounds.
+   // The function returns 0.75 for an IROC, 1. for an OROC at medium pad size position,
+   // 1.5 for an OROC at long pad size position, -1 if out of bounds.
    //
 
-   Double_t irocLow = fTPCparam->GetPadRowRadiiLow(0) - fTPCparam->GetInnerPadPitchLength()/2;
-   Double_t irocUp = fTPCparam->GetPadRowRadiiLow(fTPCparam->GetNRowLow()-1) + fTPCparam->GetInnerPadPitchLength()/2;
-   Double_t orocLow1 = fTPCparam->GetPadRowRadiiUp(0) - fTPCparam->GetOuter1PadPitchLength()/2;
-   Double_t orocUp1 = fTPCparam->GetPadRowRadiiUp(fTPCparam->GetNRowUp1()-1) + fTPCparam->GetOuter1PadPitchLength()/2;
-   Double_t orocLow2 = fTPCparam->GetPadRowRadiiUp(fTPCparam->GetNRowUp1()) - fTPCparam->GetOuter2PadPitchLength()/2;
-   Double_t orocUp2 = fTPCparam->GetPadRowRadiiUp(fTPCparam->GetNRowUp()-1) + fTPCparam->GetOuter2PadPitchLength()/2;
+   Double_t irocLow = fgTPCparam->GetPadRowRadiiLow(0) - fgTPCparam->GetInnerPadPitchLength()/2;
+   Double_t irocUp = fgTPCparam->GetPadRowRadiiLow(fgTPCparam->GetNRowLow()-1) + fgTPCparam->GetInnerPadPitchLength()/2;
+   Double_t orocLow1 = fgTPCparam->GetPadRowRadiiUp(0) - fgTPCparam->GetOuter1PadPitchLength()/2;
+   Double_t orocUp1 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()-1) + fgTPCparam->GetOuter1PadPitchLength()/2;
+   Double_t orocLow2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()) - fgTPCparam->GetOuter2PadPitchLength()/2;
+   Double_t orocUp2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp()-1) + fgTPCparam->GetOuter2PadPitchLength()/2;
    
    // if IROC
    if (lx >= irocLow && lx <= irocUp) return 0.75;
@@ -497,237 +818,388 @@ Int_t AliTPCcalibTracksGain::GetPadType(Double_t lx) {
    return -1;
 }
 
-
-
-void  AliTPCcalibTracksGain::DumpTrack(AliTPCseed * track){
-  //
-  //  Dump track information to the  stream
-  //   
+// ONLY FOR DEBUGGING PURPOSES - REMOVE ME WHEN NOT NEEDED ANYMORE
+Bool_t AliTPCcalibTracksGain::GetRowPad(Double_t lx, Double_t ly, Int_t& row, Int_t& pad) {
+   //
+   // Calculate the row and pad number when the local coordinates are given.
+   // Returns kFALSE if the position is out of range, otherwise return kTRUE.
+   // WARNING: This function is preliminary and probably isn't very accurate!!
+   //
    
-  
-  (*fDebugStream)<<"Track"<<
-    "Track.="<<track<<       // track information
-    "\n";
-  Int_t rows[200];
-  for (Int_t ipad=0; ipad<3; ipad++){
-    GetDedx(track,ipad, rows);
-  }
-  
+   Double_t irocLow = fgTPCparam->GetPadRowRadiiLow(0) - fgTPCparam->GetInnerPadPitchLength()/2;
+   //Double_t irocUp = fgTPCparam->GetPadRowRadiiLow(fgTPCparam->GetNRowLow()-1) + fgTPCparam->GetInnerPadPitchLength()/2;
+   Double_t orocLow1 = fgTPCparam->GetPadRowRadiiUp(0) - fgTPCparam->GetOuter1PadPitchLength()/2;
+   //Double_t orocUp1 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()-1) + fgTPCparam->GetOuter1PadPitchLength()/2;
+   Double_t orocLow2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp1()) - fgTPCparam->GetOuter2PadPitchLength()/2;
+   //Double_t orocUp2 = fgTPCparam->GetPadRowRadiiUp(fgTPCparam->GetNRowUp()-1) + fgTPCparam->GetOuter2PadPitchLength()/2;
+
+   if (GetPadType(lx) == 0) {
+      row = (Int_t)((lx - irocLow) / fgTPCparam->GetInnerPadPitchLength());
+      pad = (Int_t)((ly + fgTPCparam->GetYInner(row)) / fgTPCparam->GetInnerPadPitchWidth());
+   } else if (GetPadType(lx) == 1) {
+      row = (Int_t)((lx - orocLow1) / fgTPCparam->GetOuter1PadPitchLength());
+      pad = (Int_t)((ly + fgTPCparam->GetYOuter(row)) / fgTPCparam->GetOuterPadPitchWidth());
+   } else if (GetPadType(lx) == 2) {
+      row = fgTPCparam->GetNRowUp1() + (Int_t)((lx - orocLow2) / fgTPCparam->GetOuter2PadPitchLength());
+      pad = (Int_t)((ly + fgTPCparam->GetYOuter(row)) / fgTPCparam->GetOuterPadPitchWidth());
+   }
+   else return kFALSE;
+   return kTRUE;
 }
 
+void AliTPCcalibTracksGain::DumpTrack(AliTPCseed* track) {
+   //
+   //  Dump track information to the debug stream
+   //
+   
+   (*fDebugStream) << "Track" <<
+      "Track.=" << track <<        // track information
+      "\n";
+   Int_t rows[200];
+   for (Int_t ipad = 0; ipad < 3; ipad++) {
+      GetDedx(track, ipad, rows);
+   }
+}
 
+Bool_t AliTPCcalibTracksGain::GetDedx(AliTPCseed* track, Int_t padType, Int_t* rows) {
+   //
+   // GetDedx for given sector for given track
+   // padType - type of pads
+   //
+   
+   Int_t firstRow = 0, lastRow = 0;
+   Int_t minRow = 100;
+   Float_t xcenter = 0;
+   const Float_t ktany = TMath::Tan(TMath::DegToRad() * 10);
+   const Float_t kedgey = 4.;
+   if (padType == 0) {
+      firstRow = 0;
+      lastRow = fgTPCparam->GetNRowLow();
+      xcenter = 108.47;
+   }
+   if (padType == 1) {
+      firstRow = fgTPCparam->GetNRowLow();
+      lastRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp1();
+      xcenter = 166.60;
+   }
+   if (padType == 2) {
+      firstRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp1();
+      lastRow = fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp();
+      xcenter = 222.6;
+   }
+   minRow = (lastRow - firstRow) / 2;
+   //
+   //
+   Int_t nclusters = 0;
+   Int_t nclustersNE = 0; // number of not edge clusters
+   Int_t lastSector = -1;
+   Float_t amplitudeQ[100];
+   Float_t amplitudeM[100];
+   Int_t rowIn[100];
+   Int_t index[100];
+   //
+   static TLinearFitter fitY(2, "pol1");
+   static TLinearFitter fitZ(2, "pol1");
+   static TVectorD parY(2);
+   static TVectorD parZ(2);
+   fitY.ClearPoints();
+   fitZ.ClearPoints();
+   TVectorD meanPos(6);
+   
+   for (Int_t iCluster = firstRow; iCluster < lastRow; iCluster++) {
+      AliTPCclusterMI* cluster = track->GetClusterPointer(iCluster);
+      if (cluster) {
+         Int_t detector = cluster->GetDetector() ;
+         if (lastSector == -1) lastSector = detector;
+         if (lastSector != detector) continue;
+         amplitudeQ[nclusters] = cluster->GetQ();
+         amplitudeM[nclusters] = cluster->GetMax();
+         rowIn[nclusters] = iCluster;
+         nclusters++;
+         Double_t dx = cluster->GetX() - xcenter;
+         Double_t y = cluster->GetY();
+         Double_t z = cluster->GetZ();
+         fitY.AddPoint(&dx, y);
+         fitZ.AddPoint(&dx, z);
+         meanPos[0] += dx;
+         meanPos[1] += dx;
+         meanPos[2] += y;
+         meanPos[3] += y*y;
+         meanPos[4] += z;
+         meanPos[5] += z*z;
+         if (TMath::Abs(cluster->GetY()) < cluster->GetX()*ktany - kedgey) nclustersNE++;
+      }
+   }
+   
+   if (nclusters < minRow / 2) return kFALSE;
+   if (nclustersNE < minRow / 2) return kFALSE;
+   for (Int_t i = 0; i < 6; i++) meanPos[i] /= Double_t(nclusters);
+   fitY.Eval();
+   fitZ.Eval();
+   fitY.GetParameters(parY);
+   fitZ.GetParameters(parZ);
+   //
+   // calculate truncated mean
+   //
+   TMath::Sort(nclusters, amplitudeQ, index, kFALSE);
+   
+   TVectorD dedxQ(5);
+   TVectorD dedxM(5);
+   Float_t ndedx[5];
+   for (Int_t i = 0; i < 5; i++) {
+      dedxQ[i] = 0;
+      dedxM[i] = 0;
+      ndedx[i] = 0;
+   }
+   //
+   // dedx calculation
+   //
+   Int_t inonEdge = 0;
+   for (Int_t i = 0; i < nclusters; i++) {
+      Int_t rowSorted = rowIn[index[i]];
+      AliTPCclusterMI* cluster = track->GetClusterPointer(rowSorted);
+      
+      if (TMath::Abs(cluster->GetY()) > cluster->GetX()*ktany - kedgey) continue;  //don't take edge clusters
+      inonEdge++;
+      if (inonEdge < nclustersNE * 0.5) {
+         ndedx[0]++;
+         dedxQ[0] += amplitudeQ[index[i]];
+         dedxM[0] += amplitudeM[index[i]];
+      }
+      if (inonEdge < nclustersNE * 0.6) {
+         ndedx[1]++;
+         dedxQ[1] += amplitudeQ[index[i]];
+         dedxM[1] += amplitudeM[index[i]];
+      }
+      if (inonEdge < nclustersNE * 0.7) {
+         ndedx[2]++;
+         dedxQ[2] += amplitudeQ[index[i]];
+         dedxM[2] += amplitudeM[index[i]];
+      }
+      if (inonEdge < nclustersNE * 0.8) {
+         ndedx[3]++;
+         dedxQ[3] += amplitudeQ[index[i]];
+         dedxM[3] += amplitudeM[index[i]];
+      }
+      if (inonEdge < nclustersNE * 0.9) {
+         ndedx[4]++;
+         dedxQ[4] += amplitudeQ[index[i]];
+         dedxM[4] += amplitudeM[index[i]];
+      }
+   }
+   for (Int_t i = 0; i < 5; i++) {
+      dedxQ[i] /= ndedx[i];
+      dedxM[i] /= ndedx[i];
+   }
+   
+   inonEdge = 0;
+   for (Int_t i = 0; i < nclusters; i++) {
+      Int_t rowSorted = rowIn[index[i]];
+      AliTPCclusterMI* cluster = track->GetClusterPointer(rowSorted);
+      if (!cluster) {
+         printf("Problem\n");
+         continue;
+      }
+      if (TMath::Abs(cluster->GetY()) < cluster->GetX()*ktany - kedgey) inonEdge++;
+      Float_t dedge = cluster->GetX()*ktany - TMath::Abs(cluster->GetY());
+      Float_t fraction = Float_t(i) / Float_t(nclusters);
+      Float_t fraction2 = Float_t(inonEdge) / Float_t(nclustersNE);
+      Float_t momenta = track->GetP();
+      Float_t mdedx = track->GetdEdx();
+
+      (*fDebugStream) << "dEdx" <<
+         "Cl.=" << cluster <<           // cluster of interest
+         "P=" << momenta <<             // track momenta
+         "dedx=" << mdedx <<            // mean dedx - corrected for angle
+         "IPad=" << padType <<          // pad type 0..2
+         "xc=" << xcenter <<            // x center of chamber
+         "dedxQ.=" << &dedxQ <<         // dedxQ  - total charge
+         "dedxM.=" << &dedxM <<         // dedxM  - maximal charge
+         "fraction=" << fraction <<     // fraction - order in statistic (0,1)
+         "fraction2=" << fraction2 <<   // fraction - order in statistic (0,1)
+         "dedge=" << dedge <<           // distance to the edge
+         "parY.=" << &parY <<           // line fit
+         "parZ.=" << &parZ <<           // line fit
+         "meanPos.=" << &meanPos <<     // mean position (dx, dx^2, y,y^2, z, z^2)
+         "\n";
+   }
+   return kTRUE;
+}
 
-//_____________________________________________________________________________
-Float_t AliTPCcalibTracksGain::TPCBetheBloch(Float_t p, Float_t mass)
+AliTPCcalibTracksGain::PreProcess::PreProcess(AliTPCseed* seed) :
+   fSeed(seed)
 {
-  //
-  // Bethe-Bloch energy loss formula
-  //   
-  Float_t bg = p /mass;
-  const Double_t kp1=0.76176e-1;
-  const Double_t kp2=10.632;
-  const Double_t kp3=0.13279e-4;
-  const Double_t kp4=1.8631;
-  const Double_t kp5=1.9479;
-
-  Double_t dbg = (Double_t) bg;
+   //
+   // Constructor. Preprocesses the track contained in seed. After that
+   // all relevant values gained from preprocessing can be accessed using
+   // the getter methods.
+   // For each pad region a line fit using the clusters of this region is made
+   // for obtaining the angle between track and padrow.
+   // The mean charge for the clusters of each pad region is calculated.
+   // For all these calculations inappropriate clusters are not used
+   // and are accordingly marked (which can be found out with IsClusterAccepted).
+   //
 
-  Double_t beta = dbg/TMath::Sqrt(1.+dbg*dbg);
+   // initialize data members and constants
+   fAngleTrackPadrow = new Double_t[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
+   fAngleTrackBeam   = new Double_t[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
+   fMeanCharge       = new Double_t[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
+   fMeanZ            = new Double_t[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
+   for (UInt_t i = 0; i < AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes(); i++) {
+      fMeanCharge[i] = 0;
+      fMeanZ[i] = 0;
+   }
+   for (UInt_t i = 0; i < 159; i++) fAcceptedClusters[i] = kFALSE;
+   const Double_t kSmallNumber = 1E-20;
+   const Double_t kTan10 = TMath::Tan(10*TMath::DegToRad());
+   const Double_t kCos10 = TMath::Cos(10*TMath::DegToRad());
+      
+   Int_t nClusters[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];                              // this will be gone for a new ROOT version > v5-17-05
+   for (UInt_t i = 0; i < AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes(); i++) nClusters[i] = 0; // this will be gone for a new ROOT version > v5-17-05
+   Int_t nAllClusters[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()];
+   for (UInt_t i = 0; i < AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes(); i++) nAllClusters[i] = 0;
+   
+   Double_t clusterCharges[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()][100];
+   Int_t    clusterIndices[AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()][100];
+   Int_t    clusterRows   [AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes()][100];
+   for (Int_t iCluster = 0; iCluster < 159; iCluster++) {
+      AliTPCclusterMI* cluster = fSeed->GetClusterPointer(iCluster);
+      // check if cluster is good cluster
+      if (cluster) {
+         Int_t segment = cluster->GetDetector() % 36;
+         Int_t padType = (iCluster < AliTPCcalibTracksGain::fgTPCparam->GetNRowLow()) ? 0 : ((iCluster < fgTPCparam->GetNRowLow() + fgTPCparam->GetNRowUp1()) ? 1 : 2);
+         Int_t index = segment + AliTPCFitPad::GetNSegments() * padType;
+         nAllClusters[index]++;
+
+         // cluster type < 0: edge cluster
+         // cluster type = 0: "golden" (i.e. good) cluster
+         // cluster type > 0: overlapping cluster
+         // if (cluster->GetType() != 0) continue;
+         
+         // add up z positions for later calculation of mean z position
+         fMeanZ[index] += cluster->GetZ();
+         
+         // remove edge clusters (only keep those farther away than 3 cm from the edge)
+         Double_t edgeDistance = (cluster->GetX() * kTan10 - TMath::Abs(cluster->GetY())); //* kCos10; // the cos is for the shortest distance
+         if (edgeDistance < 3.) continue;
+         
+         // put cluster charges and their row position in arrays for each pad region and count them
+         clusterCharges[index][nClusters[index]] = AliTPCcalibTracksGain::fgkUseTotalCharge ? cluster->GetQ() : cluster->GetMax();
+         clusterRows[index][nClusters[index]] = iCluster;
+         nClusters[index]++;
+      }
+   }
 
-  Double_t aa = TMath::Power(beta,kp4);
-  Double_t bb = TMath::Power(1./dbg,kp5);
+   // order clusters according to their charge (in each pad region)
+   //for (UInt_t index = 0; index < AliTPCFitPad::GetNSegments() * AliTPCFitPad::GetNPadTypes(); index++)
+   //   TMath::Sort(nClusters[index], clusterCharges[index], clusterIndices[index], kFALSE);
 
-  bb=TMath::Log(kp3+bb);
-  
-  return ((Float_t)((kp2-aa-bb)*kp1/aa));
+   AliTPCFitPad localXYfitters(2, "pol1", ""); // used for determining the angle between XY projection of track and Y axis (padrow) - local c.s.
+   AliTPCFitPad localXZfitters(2, "pol1", ""); // used for determining the angle between XZ projection of track and Z axis (beam) - local c.s.
+   
+   Int_t minRows[3] = {0};
+   minRows[0] = AliTPCcalibTracksGain::fgTPCparam->GetNRowLow();
+   minRows[1] = AliTPCcalibTracksGain::fgTPCparam->GetNRowUp1();
+   minRows[2] = AliTPCcalibTracksGain::fgTPCparam->GetNRowUp() - AliTPCcalibTracksGain::fgTPCparam->GetNRowUp1();
+   // the minimum number of rows occupied by clusters in a pad region should be a quarter of the available rows
+   for (Int_t i = 0; i < 3; minRows[i++] /= 4);
+   
+   for (UInt_t iSegment = 0; iSegment < AliTPCFitPad::GetNSegments(); iSegment++) {
+      for (UInt_t iPadType = 0; iPadType < AliTPCFitPad::GetNPadTypes(); iPadType++) {
+         Int_t index = iSegment + AliTPCFitPad::GetNSegments() * iPadType;
+         
+         // remove pad regions with too few rows occupied by clusters
+         if (nAllClusters[index] < minRows[iPadType]) continue;
+         // calculate mean z position
+         fMeanZ[index] /= nAllClusters[index];
+         // order clusters according to their charge (in each pad region)
+         TMath::Sort(nClusters[index], clusterCharges[index], clusterIndices[index], kFALSE);
+         
+         for (Int_t i = 0; i < nClusters[index]; i++) {
+            Int_t iCluster = clusterRows[index][clusterIndices[index][i]];
+            AliTPCclusterMI* cluster = fSeed->GetClusterPointer(iCluster);
+            // keep only the lower 70% of the clusters ordered according to their charge
+            Double_t fraction = (Double_t)i / (Double_t)(nClusters[index]);
+            if (fraction > 0.7) break;
+                        
+            fAcceptedClusters[iCluster] = kTRUE;
+            // put cluster data into fitters (I should move this before the fraction cut, because the charge values don't matter - the problem is the number of points -> additional counter)
+            Double_t x = cluster->GetX();             // maybe it's better for fitter stability to use difference from pad region center instead
+            localXYfitters.GetFitter(iSegment, iPadType)->AddPoint(&x, cluster->GetY());
+            localXZfitters.GetFitter(iSegment, iPadType)->AddPoint(&x, cluster->GetZ());
+            // add up charges for later calculation of mean charges
+            fMeanCharge[index] += AliTPCcalibTracksGain::fgkUseTotalCharge ? cluster->GetQ() : cluster->GetMax();
+         }
+         // calculate mean charges
+         if (nClusters[index] != 0) fMeanCharge[index] /= (Double_t)(nClusters[index]);
+      }
+   }
+      
+   // evaluate fitters and set corresponding angles or default values, respectively
+   for (UInt_t iSegment = 0; iSegment < AliTPCFitPad::GetNSegments(); iSegment++) {
+      for (UInt_t iPadType = 0; iPadType < AliTPCFitPad::GetNPadTypes(); iPadType++) {
+         UInt_t index = iSegment + AliTPCFitPad::GetNSegments() * iPadType;
+         // evaluate XY fitters
+         TLinearFitter* fitter = localXYfitters.GetFitterSimple(iSegment, iPadType);
+         if (fitter && nClusters[index] >= 2 && fitter->Eval() == 0) {                                    // this will be gone for a new ROOT version > v5-17-05 and replaced by (fitter && fitter->GetNPoints() >= 2 && fitter->Eval() == 0)
+            Double_t slope = fitter->GetParameter(1);
+            if (TMath::Abs(slope) < kSmallNumber)
+               fAngleTrackPadrow[index] = TMath::Sign(TMath::Pi()/2, slope); // default value for small slopes
+            else
+               fAngleTrackPadrow[index] = TMath::ATan(1/slope);
+         }
+         else  fAngleTrackPadrow[index] = TMath::Pi()/2; // default value if not enough data points in fitter
+         // evaluate XZ fitters
+         fitter = localXZfitters.GetFitterSimple(iSegment, iPadType);
+         if (fitter && nClusters[index] >= 2 && fitter->Eval() == 0) {                                   // this will be gone for a new ROOT version > v5-17-05 and replaced by (fitter && fitter->GetNPoints() >= 2 && fitter->Eval() == 0)
+            Double_t slope = fitter->GetParameter(1);
+            if (TMath::Abs(slope) < kSmallNumber)
+               fAngleTrackBeam[index] = TMath::Sign(TMath::Pi()/2, slope); // default value for small slopes
+            else
+               fAngleTrackBeam[index] = TMath::ATan(1/slope);
+         }
+         else  fAngleTrackBeam[index] = TMath::Pi()/2; // default value if not enough data points in fitter, should be pi/2 for cosmics, something like pi/4 for pp
+      }
+   }
 }
 
-
-
-
-
-Bool_t   AliTPCcalibTracksGain::GetDedx(AliTPCseed * track, Int_t padType, Int_t *rows){
-  //
-  // GetDedx for given sector for given track
-  // padType - type of pads
-  //
-  Int_t firstRow=0, lastRow=0;
-  Int_t minRow=100;
-  Float_t xcenter=0;
-  const Float_t ktany = TMath::Tan(TMath::DegToRad()*10);
-  const Float_t kedgey =4.;
-  if (padType==0){
-    firstRow=0;
-    lastRow= fTPCparam->GetNRowLow();
-    xcenter= 108.47;
-  }
-  if (padType==1){
-    firstRow= fTPCparam->GetNRowLow();
-    lastRow= fTPCparam->GetNRowLow()+fTPCparam->GetNRowUp1();
-    xcenter= 166.60;
-  }
-  if (padType==2){
-    firstRow= fTPCparam->GetNRowLow()+fTPCparam->GetNRowUp1();
-    lastRow= fTPCparam->GetNRowLow()+fTPCparam->GetNRowUp();
-    xcenter =222.6;
-  }
-  minRow= (lastRow-firstRow)/2;
-  //
-  //
-  Int_t nclusters=0;
-  Int_t nclustersNE=0; // number of not edge clusters
-  Int_t lastSector=-1;
-  Float_t amplitudeQ[100];
-  Float_t amplitudeM[100];
-  Int_t   rowIn[100];
-  Int_t   index[100];
-  //
-  static TLinearFitter fitY(2,"pol1");
-  static TLinearFitter fitZ(2,"pol1");
-  static TVectorD      parY(2);
-  static TVectorD      parZ(2);
-  fitY.ClearPoints();
-  fitZ.ClearPoints();
-  TVectorD meanPos(6);
-  
-
-  for (Int_t iCluster = firstRow; iCluster < lastRow; iCluster++) {
-    AliTPCclusterMI* cluster = track->GetClusterPointer(iCluster);
-    if (cluster) {
-      Int_t detector = cluster->GetDetector() ;
-      if (lastSector==-1) lastSector= detector;
-      if (lastSector!=detector) continue;
-      amplitudeQ[nclusters]=cluster->GetQ();
-      amplitudeM[nclusters]=cluster->GetMax();
-      rowIn[nclusters]=iCluster;
-      nclusters++;
-      Double_t dx=cluster->GetX()-xcenter;
-      Double_t y=cluster->GetY();
-      Double_t z=cluster->GetZ();      
-      fitY.AddPoint(&dx, y);
-      fitZ.AddPoint(&dx, z);
-      meanPos[0]+=dx;
-      meanPos[1]+=dx;
-      meanPos[2]+=y;
-      meanPos[3]+=y*y;
-      meanPos[4]+=z;
-      meanPos[5]+=z*z;
-      if (TMath::Abs(cluster->GetY())<cluster->GetX()*ktany-kedgey) nclustersNE++;
-    }
-  }
-
-  if (nclusters<minRow/2) return kFALSE;
-  if (nclustersNE<minRow/2) return kFALSE;
-  for (Int_t i=0;i<6;i++) meanPos[i]/=Double_t(nclusters);
-  fitY.Eval();
-  fitZ.Eval();
-  fitY.GetParameters(parY);
-  fitZ.GetParameters(parZ);
-  //
-  // calculate truncated mean
-  //
-  TMath::Sort(nclusters,amplitudeQ,index, kFALSE);
-
-  TVectorD dedxQ(5);
-  TVectorD dedxM(5);
-  Float_t ndedx[5];
-  for (Int_t i=0; i<5; i++){
-    dedxQ[i]=0;
-    dedxM[i]=0;                                        
-    ndedx[i]=0;
-  }
-  //
-  // dedx calculation
-  //
-  Int_t inonEdge=0;
-  for (Int_t i=0; i<nclusters; i++){
-    Int_t rowSorted = rowIn[index[i]]; 
-    AliTPCclusterMI* cluster = track->GetClusterPointer(rowSorted);
-    
-    if (TMath::Abs(cluster->GetY())> cluster->GetX()*ktany-kedgey) continue;  //don't take edge clusters
-    inonEdge++;
-    if (inonEdge<nclustersNE*0.5) { 
-      ndedx[0]++; 
-      dedxQ[0]+=amplitudeQ[index[i]];
-      dedxM[0]+=amplitudeM[index[i]];
-    }
-    if (inonEdge<nclustersNE*0.6) { 
-      ndedx[1]++; 
-      dedxQ[1]+=amplitudeQ[index[i]];
-      dedxM[1]+=amplitudeM[index[i]];
-    }
-    if (inonEdge<nclustersNE*0.7) { 
-      ndedx[2]++; 
-      dedxQ[2]+=amplitudeQ[index[i]];
-      dedxM[2]+=amplitudeM[index[i]];
-    }
-    if (inonEdge<nclustersNE*0.8) { 
-      ndedx[3]++; 
-      dedxQ[3]+=amplitudeQ[index[i]];
-      dedxM[3]+=amplitudeM[index[i]];
-    }
-    if (inonEdge<nclustersNE*0.9) { 
-      ndedx[4]++; 
-      dedxQ[4]+=amplitudeQ[index[i]];
-      dedxM[4]+=amplitudeM[index[i]];
-    }
-  }
-  for (Int_t i=0; i<5; i++){
-    dedxQ[i]/=ndedx[i];
-    dedxM[i]/=ndedx[i];
-  }
-
-  inonEdge=0;
-  Float_t momenta = track->GetP();
-  Float_t mdedx   = track->GetdEdx();
-
-  for (Int_t i=0; i<nclusters; i++){
-    Int_t rowSorted = rowIn[index[i]]; 
-    AliTPCclusterMI* cluster = track->GetClusterPointer(rowSorted);
-    if (!cluster) {
-      printf("Problem\n");
-      continue;
-    }
-    if (TMath::Abs(cluster->GetY())< cluster->GetX()*ktany-kedgey) inonEdge++;
-    Float_t dedge    = cluster->GetX()*ktany-TMath::Abs(cluster->GetY());
-    Float_t fraction = Float_t(i)/Float_t(nclusters);
-    Float_t fraction2= Float_t(inonEdge)/Float_t(nclustersNE);
-    (*fDebugStream)<<"dEdxCl"<<
-      "Cl.="<<cluster<<    //cluster of interest
-      "P="<<momenta<<     // track momenta
-      "dedx="<<mdedx<<    // mean dedx - corrected for angle
-      "IPad="<<padType<<   // pad type 0..2
-      "xc="<<xcenter<<     // x center of chamber
-      "dedxQ.="<<&dedxQ<<  // dedxQ  - total charge
-      "dedxM.="<<&dedxM<<  // dedxM  - maximal charge
-      "fraction="<<fraction<<  // fraction - order in statistic (0,1)
-      "fraction2="<<fraction2<<  // fraction - order in statistic (0,1)
-      "dedge="<<dedge<<      // distance to thhe edge
-      "parY.="<<&parY<<      // line fit
-      "parZ.="<<&parZ<<      // line fit
-      "meanPos.="<<&meanPos<< // mean position (dx, dx^2, y,y^2, z, z^2)
-      "\n";
-
-  }
-
-  Float_t prim =  TPCBetheBloch(momenta, 0.1057);   //dedx under muon assumption
-  (*fDebugStream)<<"dEdxTr"<<
-    "P="<<momenta<<     // track momenta
-    "sector="<<lastSector<<// sector to investigate
-    "ncl0="<<nclusters<<    // number of clusters
-    "ncl="<<inonEdge<<      // number of clusters used for dEdx
-    "dedx="<<mdedx<<    // mean dedx - corrected for angle
-    "prim="<<prim<<     // primary ionization parameters
-    "IPad="<<padType<<   // pad type 0..2
-    "xc="<<xcenter<<     // x center of chamber
-    "dedxQ.="<<&dedxQ<<  // dedxQ  - total charge
-    "dedxM.="<<&dedxM<<  // dedxM  - maximal charge
-    "parY.="<<&parY<<      // line fit
-    "parZ.="<<&parZ<<      // line fit
-    "meanPos.="<<&meanPos<< // mean position (dx, dx^2, y,y^2, z, z^2)
-    "\n";
-
-  return 0;
-
+AliTPCcalibTracksGain::PreProcess::~PreProcess() {
+   //
+   // Destructor.
+   //
+   
+   delete[] fAngleTrackPadrow;
+   delete[] fAngleTrackBeam;
+   delete[] fMeanCharge;
+   delete[] fMeanZ;
 }
 
+// REMOVE ME, just for debugging
+void AliTPCcalibTracksGain::testSeed(char* file, Int_t entry, Int_t tr) {
+   // read a single AliTPCseed from AliESDs.root and AliESDfriends.root (with new AliRoot)
+   TFile f(file);
+   TTree* tree = (TTree*)(f.Get("esdTree"));
+   tree->SetBranchStatus("*",1);
+   AliESDEvent* fESDevent = new AliESDEvent();
+   fESDevent->ReadFromTree(tree);
+   tree->GetEntry(entry);
+   AliESDfriend* fESDfriend = (AliESDfriend*)fESDevent->FindListObject("AliESDfriend");
+   tree->SetBranchAddress("ESDfriend.",&fESDfriend);
+   fESDevent->SetESDfriend(fESDfriend);
+   AliESDtrack *esdTrack = (AliESDtrack*) fESDevent->GetTrack(tr);
+   AliESDfriendTrack *friendtrack = (AliESDfriendTrack*) esdTrack->GetFriendTrack();
+   AliTPCseed *seed = 0; TObject *cobject = 0;
+   for (Int_t i = 0; ; i++){ cobject = friendtrack->GetCalibObject(i); if (!cobject) break; seed = dynamic_cast<AliTPCseed*>(cobject); if (seed) break;}
+
+   AliTPCcalibTracksGain::PreProcess preProc(seed);
+   for (Int_t iCluster = 0; iCluster < 159; iCluster++) {
+      AliTPCclusterMI* cluster = seed->GetClusterPointer(iCluster);
+      if (cluster) {
+         Int_t padType = AliTPCcalibTracksGain::GetPadType(cluster->GetX());
+         Int_t segment = cluster->GetDetector() % 36;
+         cout << "AngleTrackPadrow(" << segment << ", " << padType << ") == " << preProc.GetAngleTrackPadrow(segment, padType) * TMath::RadToDeg() << endl;
+         cout << "AngleTrackBeam  (" << segment << ", " << padType << ") == " << preProc.GetAngleTrackBeam(segment, padType) * TMath:: RadToDeg() << endl;
+         cout << "Correction factor == " << TMath::Abs(TMath::Sin(preProc.GetAngleTrackPadrow(segment, padType))*TMath::Sin(preProc.GetAngleTrackBeam(segment, padType)))/AliTPCcalibTracksGain::GetPadLength(cluster->GetX()) << endl;
+      }
+   }
+}
index aa6f992..e2f1ff6 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef AliTPCCALIBTRACKSGAIN_H
 #define AliTPCCALIBTRACKSGAIN_H
 
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
 #include <TChain.h>
 #include <TNamed.h>
 
@@ -11,6 +14,8 @@
 #include <TMatrixD.h>
 
 #include <iostream>
+#include <TH1F.h>
+
 using namespace std;
 
 class TTreeSRedirector;
@@ -19,14 +24,39 @@ class TLinearFitter;
 
 class AliTPCClusterParam; 
 class AliTPCParamSR; 
-class AliTPCCalROC; 
+class AliTPCCalROC;
+class AliTPCCalPad;
 class AliTPCseed; 
 class AliTPCclusterMI; 
 class AliTrackPointArray;
 class TTreeStream;
+class AliTPCcalibTracksCuts;
+class AliTPCFitPad;
 
 class AliTPCcalibTracksGain : public TNamed {
-public :
+private:
+   class PreProcess {
+   public:
+      PreProcess(AliTPCseed* seed);
+      virtual ~PreProcess();
+
+      AliTPCseed* GetSeed() { return fSeed; }
+      Double_t    GetAngleTrackPadrow(UInt_t segment, UInt_t padType) { return fAngleTrackPadrow[segment + 36*padType]; }
+      Double_t    GetAngleTrackBeam(UInt_t segment, UInt_t padType) { return fAngleTrackBeam[segment + 36*padType]; }
+      Double_t    GetMeanCharge(UInt_t segment, UInt_t padType) { return fMeanCharge[segment + 36*padType]; }
+      Double_t    GetMeanZ(UInt_t segment, UInt_t padType) { return fMeanZ[segment + 36*padType]; }
+      Bool_t      IsClusterAccepted(UInt_t clusterIndex) { return fAcceptedClusters[clusterIndex]; }
+      
+   private:
+      AliTPCseed*  fSeed;                   // the seed used for preprocessing
+      Double_t*    fAngleTrackPadrow;       // angle between the track and the padrows of one TPC pad region, calculated using a line fit through the appropriate clusters
+      Double_t*    fAngleTrackBeam;         // angle between the track and the beam axis, calculated using a line fit through the appropriate clusters
+      Double_t*    fMeanCharge;             // the mean charges for this seed (for each pad region)
+      Double_t*    fMeanZ;                  // the mean z position for this seed (for each pad region)
+      Bool_t       fAcceptedClusters[159];  // contains kFALSE for not accepted clusters, kTRUE for accepted ones (index is padrow)
+   };
+   
+public:
    enum {
       kShortPads = 0,
       kMediumPads = 1,
@@ -38,51 +68,63 @@ public :
       kLogFitter = 2
    };
    
-   AliTPCcalibTracksGain(const char* name = 0, const char* title = 0);
+   AliTPCcalibTracksGain();
+   AliTPCcalibTracksGain(const AliTPCcalibTracksGain& obj);
+   AliTPCcalibTracksGain(const char* name, const char* title, AliTPCcalibTracksCuts* cuts, AliTPCcalibTracksGain* prevIter = 0);
    virtual ~AliTPCcalibTracksGain();
-   static Bool_t   AcceptTrack(AliTPCseed * track);
-   void            DumpTrack(AliTPCseed * track);
-  Bool_t GetDedx(AliTPCseed * track, Int_t padType, Int_t *rows);
+   AliTPCcalibTracksGain& operator=(const AliTPCcalibTracksGain& rhs);
+   
+   static void testSeed(char* file = "/d/alice07/sma/v4-06-Rev-03/pp/0201/AliESDs.root", Int_t entry = 87, Int_t track = 0); // LOESCH MICH ODER DU WIRST UNTERGEHEN
+   static void     AddInfo(TChain * chain, char* fileName);
+   Int_t          AcceptTrack(AliTPCseed* track);
+   //Bool_t          AcceptCluster(AliTPCclusterMI* cluster);
+   void            Add(AliTPCcalibTracksGain* cal);
    void            AddTrack(AliTPCseed* seed);
-   void            AddCluster(AliTPCclusterMI* cluster);
-   Int_t           Evaluate(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD* fitParam = 0, TVectorD* fitError = 0, Double_t* redChi2 = 0, Bool_t robust = kFALSE);
+   void            AddCluster(AliTPCclusterMI* cluster, AliTPCcalibTracksGain::PreProcess& preProc);
+   void            Process(AliTPCseed* seed);
+   Long64_t        Merge(TCollection *list);
+   void            Evaluate(Bool_t robust = kFALSE, Double_t frac = -1.);
+   Int_t           Evaluate(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD* fitParam = 0, TVectorD* fitError = 0, Double_t* redChi2 = 0, Bool_t robust = kFALSE, Double_t frac = -1.);
    void            GetParameters(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD &fitParam);
    void            GetErrors(UInt_t segment, UInt_t padType, UInt_t fitType, TVectorD &fitError);
    Double_t        GetRedChi2(UInt_t segment, UInt_t padType, UInt_t fitType);
    void            GetCovarianceMatrix(UInt_t segment, UInt_t padType, UInt_t fitType, TMatrixD& covMatrix);
-   AliTPCCalROC*   CreateFitCalROC(UInt_t sector, UInt_t padType, TVectorD &fitParam, Int_t undoTransformation = -1, Bool_t normalizeToPadSize = kFALSE);
+   AliTPCCalPad*   CreateFitCalPad(UInt_t fitType, Bool_t undoTransformation = kFALSE, Bool_t normalizeToPadSize = kFALSE);
+   AliTPCCalROC*   CreateFitCalROC(UInt_t sector, UInt_t fitType, Bool_t undoTransformation = kFALSE, Bool_t normalizeToPadSize = kFALSE);
+   AliTPCCalROC*   CreateFitCalROC(UInt_t sector, UInt_t padType, TVectorD &fitParam, UInt_t fitType, Bool_t undoTransformation = kFALSE, Bool_t normalizeToPadSize = kFALSE);
    AliTPCCalROC*   CreateCombinedCalROC(const AliTPCCalROC* roc1, const AliTPCCalROC* roc2);
    TLinearFitter*  GetFitter(UInt_t segment, UInt_t padType, UInt_t fitType);
-   Double_t        GetPadLength(Double_t lx);
-   Int_t           GetPadType(Double_t lx);
-  //
-  //
-  static Float_t   TPCBetheBloch(Float_t p, Float_t mass=0.1057);
-
-
-
-private:
-  TTreeSRedirector   *fDebugStream;       //! debug stream for
-
-   TObjArray*      fShortFitter;          // simple fitter for short pads
-   TObjArray*      fMediumFitter;         // simple fitter for medium pads
-   TObjArray*      fLongFitter;           // simple fitter for long pads
+   static Double_t GetPadLength(Double_t lx);
+   static Int_t    GetPadType(Double_t lx);
+   void            DumpTrack(AliTPCseed* track);
+   Bool_t          GetDedx(AliTPCseed* track, Int_t padType, Int_t* rows);
    
-   TObjArray*      fSqrtShortFitter;      // sqrt fitter for short pads
-   TObjArray*      fSqrtMediumFitter;     // sqrt fitter for medium pads
-   TObjArray*      fSqrtLongFitter;       // sqrt fitter for long pads
+   static Bool_t   GetRowPad(Double_t lx, Double_t ly, Int_t& row, Int_t& pad); // just for debugging, remove me
+   UInt_t          fTotalTracks;         // just for debugging, remove me
+   UInt_t          fAcceptedTracks;      // just for debugging, remove me
+   AliTPCCalPad*   fDebugCalPadRaw;      // just for debugging, remove me
+   AliTPCCalPad*   fDebugCalPadCorr;     // just for debugging, remove me
+
+public:
+   TTreeSRedirector* fDebugStream;          //! debug stream for debugging
    
-   TObjArray*      fLogShortFitter;       // log fitter for short pads
-   TObjArray*      fLogMediumFitter;      // log fitter for medium pads
-   TObjArray*      fLogLongFitter;        // log fitter for long pads
+   AliTPCFitPad*     fSimpleFitter;         // simple fitter for short pads
+   AliTPCFitPad*     fSqrtFitter;           // sqrt fitter for medium pads
+   AliTPCFitPad*     fLogFitter;            // log fitter for long pads
+
+   TLinearFitter*    fZFitter;              // fitter for getting the parametrisation for the z dependence of the charges
+   AliTPCcalibTracksGain* fPrevIter;        // the calibration object in its previous iteration (will not be owned by the new object, don't forget to delete it!)
    
-   UInt_t          fNShortClusters[36];   // number of clusters registered on short pads
-   UInt_t          fNMediumClusters[36];  // number of clusters registered on medium pads
-   UInt_t          fNLongClusters[36];    // number of clusters registered on medium pads
-   AliTPCParamSR*  fTPCparam;             //! helper object for geometry related operations
+   UInt_t            fNShortClusters[36];   // number of clusters registered on short pads
+   UInt_t            fNMediumClusters[36];  // number of clusters registered on medium pads
+   UInt_t            fNLongClusters[36];    // number of clusters registered on long pads
+   AliTPCcalibTracksCuts* fCuts;            // cuts that are used for sieving the tracks used for calibration
+
+   static       AliTPCParamSR* fgTPCparam;              //! helper object for geometry related operations
+   static const Double_t       fgkM;                    // value used in the transformation of the charge values for the logarithmic fitter
+   static const char*          fgkDebugStreamFileName;  // filename of the debug stream file
+   static const Bool_t         fgkUseTotalCharge;       // whether to use the cluster's total or maximum charge
 
-   static const Double_t fgkM;            // value used in the transformation of the charge values for the logarithmic fitter
-       
    ClassDef(AliTPCcalibTracksGain, 1);
 };
 
index 6979997..f78fcfe 100644 (file)
@@ -13,6 +13,7 @@
 #pragma link C++ class  AliTPCcalibTracks+;
 #pragma link C++ class  AliTPCcalibTracksCuts+;
 #pragma link C++ class  AliTPCcalibTracksGain+;
+#pragma link C++ class  AliTPCFitPad+;
 #pragma link C++ class  AliTPCCalPadRegion+;
 
 #pragma link C++ class  AliTPCSelectorESD+;
index 081ea07..ac2d42b 100644 (file)
@@ -1,6 +1,6 @@
 
 SRCS = AliTPCcalibTracksCuts.cxx   AliTPCcalibTracks.cxx   AliTPCcalibTracksGain.cxx  \
-        AliTPCSelectorESD.cxx   AliTPCSelectorTracks.cxx   AliTPCCalPadRegion.cxx
+        AliTPCSelectorESD.cxx   AliTPCSelectorTracks.cxx   AliTPCCalPadRegion.cxx AliTPCFitPad.cxx
        
 
 HDRS:= $(SRCS:.cxx=.h)