]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - TPC/AliTPCcalibLaser.cxx
Fixes for cmake
[u/mrichter/AliRoot.git] / TPC / AliTPCcalibLaser.cxx
index 8d8536fc206f949d1d2762f90ccedf5f713dcb88..a13bb7b6544df8e6bf249640df59f031e51f1696 100644 (file)
   AliXRDPROOFtoolkit tool;
   TChain * chainDrift = tool.MakeChain("laser.txt","driftv",0,10200);
   chainDrift->Lookup();
+  TChain * chainDriftN = tool.MakeChain("laser.txt","driftvN",0,10200);
+  chainDriftN->Lookup();
+
+
 
   TChain * chain = tool.MakeChain("laser.txt","Residuals",0,10200);
   chain->Lookup();
 #include "AliTPCLaserTrack.h"
 #include "AliTPCcalibDB.h"
 #include "AliTPCParam.h"
+#include "AliTPCParamSR.h"
 #include "TTimeStamp.h"
 #include "AliDCSSensorArray.h"
 #include "AliDCSSensor.h"
@@ -143,6 +148,7 @@ AliTPCcalibLaser::AliTPCcalibLaser():
   fDeltaPhiP(336),
   fSignals(336),
   //
+  fHisLaser(0),      //  N dim histogram of laser
   fHisNclIn(0),      //->Number of clusters inner
   fHisNclOut(0),     //->Number of clusters outer
   fHisNclIO(0),      //->Number of cluster inner outer
@@ -190,6 +196,8 @@ AliTPCcalibLaser::AliTPCcalibLaser():
   fDeltaZres(336),   //->2D histo fo residuals
   fDeltaYres2(336),   //->2D histo of residuals
   fDeltaZres2(336),   //->2D histo fo residuals
+  fDeltaYresAbs(336),   //->2D histo of residuals
+  fDeltaZresAbs(336),   //->2D histo of residuals
   //fDeltaYres3(336),   //->2D histo of residuals
   //fDeltaZres3(336),   //->2D histo fo residuals
   fFitAside(new TVectorD(5)),
@@ -198,7 +206,18 @@ AliTPCcalibLaser::AliTPCcalibLaser():
   fEdgeXcuts(3),    
   fEdgeYcuts(3),    
   fNClCuts(5),      
-  fNcuts(0)        
+  fNcuts(0),
+  fBeamSectorOuter(336),
+  fBeamSectorInner(336),
+  fBeamOffsetYOuter(336),
+  fBeamSlopeYOuter(336),
+  fBeamOffsetYInner(336),
+  fBeamSlopeYInner(336),
+  fBeamOffsetZOuter(336),
+  fBeamSlopeZOuter(336),
+  fBeamOffsetZInner(336),
+  fBeamSlopeZInner(336),
+  fInverseSlopeZ(kTRUE)
 {
   //
   // Constructor
@@ -225,6 +244,7 @@ AliTPCcalibLaser::AliTPCcalibLaser(const Text_t *name, const Text_t *title, Bool
   fSignals(336),           // array of dedx signals
   //
   //
+  fHisLaser(0),      //  N dim histogram of laser
   fHisNclIn(0),      //->Number of clusters inner
   fHisNclOut(0),     //->Number of clusters outer
   fHisNclIO(0),      //->Number of cluster inner outer
@@ -274,6 +294,8 @@ AliTPCcalibLaser::AliTPCcalibLaser(const Text_t *name, const Text_t *title, Bool
   fDeltaZres(336),  
   fDeltaYres2(336),
   fDeltaZres2(336),  
+  fDeltaYresAbs(336),
+  fDeltaZresAbs(336),
   //  fDeltaYres3(336),
   //fDeltaZres3(336),  
   fFitAside(new TVectorD(5)),        // drift fit - A side
@@ -282,7 +304,18 @@ AliTPCcalibLaser::AliTPCcalibLaser(const Text_t *name, const Text_t *title, Bool
   fEdgeXcuts(3),       // cuts in local x direction; used in the refit of the laser tracks
   fEdgeYcuts(3),       // cuts in local y direction; used in the refit of the laser tracks
   fNClCuts(5),         // cuts on the number of clusters per tracklet; used in the refit of the laser tracks
-  fNcuts(0)           // number of cuts
+  fNcuts(0),           // number of cuts
+  fBeamSectorOuter(336),
+  fBeamSectorInner(336),
+  fBeamOffsetYOuter(336),
+  fBeamSlopeYOuter(336),
+  fBeamOffsetYInner(336),
+  fBeamSlopeYInner(336),
+  fBeamOffsetZOuter(336),
+  fBeamSlopeZOuter(336),
+  fBeamOffsetZInner(336),
+  fBeamSlopeZInner(336),
+  fInverseSlopeZ(kTRUE)
 {
   SetName(name);
   SetTitle(title);
@@ -311,6 +344,7 @@ AliTPCcalibLaser::AliTPCcalibLaser(const AliTPCcalibLaser& calibLaser):
   fSignals(((calibLaser.fSignals))),           // array of dedx signals
   //
   //
+  fHisLaser(0),      //  N dim histogram of laser
   fHisNclIn(new TH2F(*(calibLaser.fHisNclIn))),      //->Number of clusters inner
   fHisNclOut(new TH2F(*(calibLaser.fHisNclOut))),     //->Number of clusters outer
   fHisNclIO(new TH2F(*(calibLaser.fHisNclIO))),      //->Number of cluster inner outer
@@ -359,6 +393,8 @@ AliTPCcalibLaser::AliTPCcalibLaser(const AliTPCcalibLaser& calibLaser):
   fDeltaZres(((calibLaser.fDeltaZres))),  
   fDeltaYres2(((calibLaser.fDeltaYres))),
   fDeltaZres2(((calibLaser.fDeltaZres))),  
+  fDeltaYresAbs(((calibLaser.fDeltaYresAbs))),
+  fDeltaZresAbs(((calibLaser.fDeltaZresAbs))),
   //  fDeltaYres3(((calibLaser.fDeltaYres))),
   //fDeltaZres3(((calibLaser.fDeltaZres))),  
   fFitAside(new TVectorD(5)),        // drift fit - A side
@@ -367,7 +403,19 @@ AliTPCcalibLaser::AliTPCcalibLaser(const AliTPCcalibLaser& calibLaser):
   fEdgeXcuts(3),       // cuts in local x direction; used in the refit of the laser tracks
   fEdgeYcuts(3),       // cuts in local y direction; used in the refit of the laser tracks
   fNClCuts(5),         // cuts on the number of clusters per tracklet; used in the refit of the laser tracks
-  fNcuts(0)           // number of cuts
+  fNcuts(0),           // number of cuts
+  fBeamSectorOuter(336),
+  fBeamSectorInner(336),
+  fBeamOffsetYOuter(336),
+  fBeamSlopeYOuter(336),
+  fBeamOffsetYInner(336),
+  fBeamSlopeYInner(336),
+  fBeamOffsetZOuter(336),
+  fBeamSlopeZOuter(336),
+  fBeamOffsetZInner(336),
+  fBeamSlopeZInner(336),
+  fInverseSlopeZ(calibLaser.fInverseSlopeZ)
+
 {
   //
   // copy constructor
@@ -395,6 +443,7 @@ AliTPCcalibLaser::~AliTPCcalibLaser() {
   // destructor
   //
   if ( fHisNclIn){
+    delete fHisLaser;      //->
     delete fHisNclIn;      //->Number of clusters inner
     delete fHisNclOut;     //->Number of clusters outer
     delete fHisNclIO;      //->Number of cluster inner outer
@@ -464,7 +513,10 @@ AliTPCcalibLaser::~AliTPCcalibLaser() {
   fDeltaZres2.SetOwner();
   fDeltaZres2.Delete();
   
-
+  fDeltaYresAbs.SetOwner();
+  fDeltaYresAbs.Delete();
+  fDeltaZresAbs.SetOwner();
+  fDeltaZresAbs.Delete();
 }
 
 
@@ -516,6 +568,7 @@ void AliTPCcalibLaser::Process(AliESDEvent * event) {
   if (counter<kMinTracks) return;
 
   FitDriftV();
+  FitDriftV(0.5);
   if (!fFullCalib) return;
   static Bool_t init=kFALSE;
   if (!init){
@@ -545,6 +598,7 @@ void AliTPCcalibLaser::MakeDistHisto(Int_t id){
     //
     if (!fTracksEsdParam.At(id)) return;
     if (!AcceptLaser(id)) return;
+    Double_t xhis[12]={0,0,0,0,0,0,0,0,0,0,0,0};
     //
     //
     TH1F * hisdz = (TH1F*)fDeltaZ.At(id);
@@ -581,7 +635,21 @@ void AliTPCcalibLaser::MakeDistHisto(Int_t id){
     if (hisdphi) hisdphi->Fill(dphi);
     if (hisdphiP) hisdphiP->Fill(dphiP);
     if (hisSignal) hisSignal->Fill(TMath::Sqrt(TMath::Abs(track->GetTPCsignal())));
+    // fill HisLaser
+    xhis[0] = ltrp->GetId();
+    xhis[1] = ltrp->GetSide();
+    xhis[2] = ltrp->GetRod();
+    xhis[3] = ltrp->GetBundle();
+    xhis[4] = ltrp->GetBeam();
+    xhis[5] = dphi;
+    xhis[6] = fFitZ[id];
+    xhis[7] = param->GetParameter()[2]-ltrp->GetParameter()[2]; //dp2
+    xhis[8] = param->GetParameter()[3]-ltrp->GetParameter()[3]; //dp3
+    xhis[9] = param->GetParameter()[4];
+    xhis[10]= track->GetTPCNcls();
+    xhis[11]= TMath::Sqrt(TMath::Abs(track->GetTPCsignal()));
     // }
+    fHisLaser->Fill(xhis);
 }
 
 void AliTPCcalibLaser::FitDriftV(){
@@ -628,8 +696,7 @@ void AliTPCcalibLaser::FitDriftV(){
   TVectorD fitA(3),fitC(3),fitAC(4);
   
   AliTPCcalibDB*  calib=AliTPCcalibDB::Instance();
-  AliTPCParam  * tpcparam    = calib->GetParameters(); 
-   
+  AliTPCParam  * tpcparam    = calib->GetParameters();    
   //
   for (Int_t id=0; id<336; id++) fFitZ[id]=0;
 
@@ -807,6 +874,273 @@ void AliTPCcalibLaser::FitDriftV(){
     }
   }
 }
+Bool_t  AliTPCcalibLaser::FitDriftV(Float_t minFraction){
+  //
+  // Fit corrections to the drift velocity - linear approximation in the z and global y
+  //The transfromatiom from the drift time to the z position done in AliTPCTracnsform class
+  // 
+  /*
+    Formulas:
+    
+    z  = s* (z0 - vd*(t-t0))
+    
+    s  - side -1 and +1 
+    t0 - time 0
+    vd - nominal drift velocity
+    zs - miscalibrated position
+    
+    zs = s*(z0 - vd*(1+vr)*(t-(t0+dt))
+    vr  - relative change of the drift velocity
+    dzt - vd*dt
+    dr  = zz0-s*z
+    ..
+    ==>
+    zs ~ z - s*vr*(z0-s*z)+s*dzt
+    --------------------------------
+    1. Correction function vr constant:
+    
+    
+    dz = zs-z = -s*vr *(z0-s*z)+s*dzt         
+    dzs/dl = dz/dl +s*s*vr*dz/dl 
+    d(dz/dl) = vr*dz/dl     
+  */
+  const Int_t   knLaser      = 336;    //n laser tracks
+  const Float_t kFraction    = 0.9;   // robust fit fraction
+  const Float_t kSaturCut    = 0.05;   // remove saturated lasers - cut on fraction of saturated 
+  const Float_t kDistCut     = 6;      // distance sigma cut
+  const Float_t kDistCutAbs  = 0.25;  
+  const Float_t kMinClusters = 60;     // minimal amount of the clusters
+  const Float_t kMinSignal   = 16;     // minimal mean height of the signal
+  const Float_t kChi2Cut     = 0.1;    // chi2 cut to accept drift fit
+  //
+  static TLinearFitter fdriftA(3,"hyp2");
+  static TLinearFitter fdriftC(3,"hyp2");
+  static TLinearFitter fdriftAC(4,"hyp3");
+  TVectorD fitA(3),fitC(3),fitAC(4);
+  
+  AliTPCcalibDB*  calib=AliTPCcalibDB::Instance();
+  AliTPCParam  * tpcparam    = calib->GetParameters();    
+  //
+  // reset old data
+  //
+  for (Int_t id=0; id<336; id++) fFitZ[id]=0;
+  if (fFitAside->GetNoElements()<5) fFitAside->ResizeTo(5);
+  if (fFitCside->GetNoElements()<5) fFitCside->ResizeTo(5);
+  for (Int_t i=0;i<5; i++){
+    (*fFitCside)[i]=0;
+    (*fFitAside)[i]=0;
+  }
+  //
+  //
+  Float_t chi2A = 10;
+  Float_t chi2C = 10;
+  Float_t chi2AC = 10;
+  Int_t npointsA=0;
+  Int_t npointsC=0;
+  Int_t npointsAC=0;
+  Int_t nbA[4]={0,0,0,0};
+  Int_t nbC[4]={0,0,0,0};
+  //
+  for (Int_t id=0; id<336; id++){
+    if (!fTracksEsdParam.At(id)) continue;
+    if (!AcceptLaser(id)) continue;
+    if ( fClusterSatur[id]>kSaturCut)  continue;
+    if ( fClusterCounter[id]<kMinClusters)  continue;
+    AliTPCLaserTrack *ltrp = ( AliTPCLaserTrack*)fTracksMirror.At(id);
+    if (ltrp->GetSide()==0){
+      npointsA++;
+      nbA[ltrp->GetBundle()]++;
+    }
+    if (ltrp->GetSide()==1){
+      npointsA++;
+      nbC[ltrp->GetBundle()]++;
+    }
+  }
+  //
+  // reject  "bad events"
+  //
+  Bool_t isOK=kTRUE;
+  Int_t  naA=0;
+  Int_t  naC=0;
+  if (npointsA<minFraction*0.5*knLaser && npointsC<minFraction*0.5*knLaser)
+    isOK=kFALSE;
+  for (Int_t i=0;i<4;i++){
+    //count accepted for all layers
+    if (nbA[i]>minFraction*0.5*0.25*knLaser) naA++;
+    if (nbC[i]>minFraction*0.5*0.25*knLaser) naC++;
+  }
+  if (naA<3 &&naC<3) isOK=kFALSE;
+  if (isOK==kFALSE) return kFALSE;
+  
+  //
+  //
+  //
+  for (Int_t iter=0; iter<2; iter++){
+    fdriftA.ClearPoints();
+    fdriftC.ClearPoints();
+    fdriftAC.ClearPoints();
+    //
+    for (Int_t id=0; id<336; id++){
+      if (!fTracksEsdParam.At(id)) continue;
+      if (!AcceptLaser(id)) continue;
+      if ( fClusterSatur[id]>kSaturCut)  continue;
+      if ( fClusterCounter[id]<kMinClusters)  continue;
+      AliESDtrack   *track    = (AliESDtrack*)fTracksEsd.At(id);
+      if (track->GetTPCsignal()<kMinSignal) continue;
+      AliExternalTrackParam *param=(AliExternalTrackParam*)fTracksEsdParam.At(id);
+      AliTPCLaserTrack *ltrp = ( AliTPCLaserTrack*)fTracksMirror.At(id);
+
+      Double_t xyz[3];
+      Double_t pxyz[3];
+      Double_t lxyz[3];
+      Double_t lpxyz[3];
+      param->GetXYZ(xyz);
+      param->GetPxPyPz(pxyz);
+      ltrp->GetXYZ(lxyz);
+      ltrp->GetPxPyPz(lpxyz);
+      Float_t sz = (ltrp->GetSide()==0) ? TMath::Sqrt(chi2A): TMath::Sqrt(chi2C);
+      if (npointsAC>0) sz =TMath::Sqrt(chi2AC); 
+      if (TMath::Abs(fFitZ[id])>sz*kDistCut) continue;
+      if (iter>0 && TMath::Abs(fFitZ[id])>kDistCutAbs) continue;
+
+      // drift distance
+      Double_t zlength =  tpcparam->GetZLength(0);
+      Double_t ldrift = zlength-TMath::Abs(lxyz[2]);
+      Double_t mdrift = zlength-TMath::Abs(xyz[2]);
+      Double_t xxx[2] = {ldrift,lxyz[1]*ldrift/(zlength*250.)};
+      if (ltrp->GetSide()==0){
+       fdriftA.AddPoint(xxx,mdrift,1);
+      }else{
+       fdriftC.AddPoint(xxx,mdrift,1);
+      }
+      Double_t xxx2[3] = {ltrp->GetSide(), ldrift,lxyz[1]*ldrift/(zlength*250.)};
+      fdriftAC.AddPoint(xxx2,mdrift,1);
+    }
+    //
+    if (fdriftA.GetNpoints()>minFraction*0.5*knLaser){
+      //
+      fdriftA.Eval();
+      npointsA= fdriftA.GetNpoints();
+      chi2A = fdriftA.GetChisquare()/fdriftA.GetNpoints();
+      fdriftA.EvalRobust(kFraction);
+      fdriftA.GetParameters(fitA);
+      if (chi2A<kChi2Cut ||(*fFitAside)[0]==0 ) {
+       if (fFitAside->GetNoElements()<5) fFitAside->ResizeTo(5);
+       (*fFitAside)[0] = fitA[0];
+       (*fFitAside)[1] = fitA[1];
+       (*fFitAside)[2] = fitA[2];
+       (*fFitAside)[3] = fdriftA.GetNpoints();
+       (*fFitAside)[4] = chi2A;        
+      }
+    }
+    if (fdriftC.GetNpoints()>minFraction*0.5*knLaser){
+      fdriftC.Eval();
+      npointsC= fdriftC.GetNpoints();
+      chi2C = fdriftC.GetChisquare()/fdriftC.GetNpoints();
+      fdriftC.EvalRobust(kFraction);
+      fdriftC.GetParameters(fitC);
+      if (chi2C<kChi2Cut||(*fFitCside)[0]==0) {        
+       if (fFitCside->GetNoElements()<5) fFitCside->ResizeTo(5);
+       (*fFitCside)[0] = fitC[0];
+       (*fFitCside)[1] = fitC[1];
+       (*fFitCside)[2] = fitC[2];
+       (*fFitCside)[3] = fdriftC.GetNpoints();
+       (*fFitCside)[4] = chi2C;        
+      }
+    }
+
+    if (fdriftAC.GetNpoints()>minFraction*knLaser){
+      fdriftAC.Eval();
+      npointsAC= fdriftAC.GetNpoints();
+      chi2AC = fdriftAC.GetChisquare()/fdriftAC.GetNpoints();
+      fdriftAC.EvalRobust(kFraction);
+      fdriftAC.GetParameters(fitAC);
+      if (chi2AC<kChi2Cut||(*fFitACside)[0]==0) (*fFitACside) = fitAC;
+      (*fFitACside)[0] = fitAC[0];
+      (*fFitACside)[1] = fitAC[1];
+      (*fFitACside)[2] = fitAC[2];
+      (*fFitACside)[3] = fdriftAC.GetNpoints();
+      (*fFitACside)[4] = chi2AC;
+    }
+    
+    for (Int_t id=0; id<336; id++){
+      if (!fTracksEsdParam.At(id)) continue;
+      //
+      AliExternalTrackParam *param=(AliExternalTrackParam*)fTracksEsdParam.At(id);
+      AliTPCLaserTrack *ltrp = ( AliTPCLaserTrack*)fTracksMirror.At(id);
+      Double_t xyz[3];
+      Double_t pxyz[3];
+      Double_t lxyz[3];
+      Double_t lpxyz[3];
+      param->GetXYZ(xyz);
+      param->GetPxPyPz(pxyz);
+      ltrp->GetXYZ(lxyz);
+      ltrp->GetPxPyPz(lpxyz); 
+      Double_t zlength =  tpcparam->GetZLength(0);
+      Double_t ldrift = zlength-TMath::Abs(lxyz[2]);
+      Double_t mdrift = zlength-TMath::Abs(xyz[2]);
+
+      Float_t fz =0;
+      if (ltrp->GetSide()==0){
+       fz = (fitA)[0]+(fitA)[1]*ldrift+(fitA)[2]*lxyz[1]*ldrift/(zlength*250.);
+      }else{
+       fz = (fitC)[0]+(fitC)[1]*ldrift+(fitC)[2]*lxyz[1]*ldrift/(zlength*250.);        
+      }
+      if (npointsAC>10){
+       fz = (fitAC)[0]+(fitAC)[1]*ltrp->GetSide()+(fitAC)[2]*ldrift+(fitAC)[3]*lxyz[1]*ldrift/(zlength*250.);
+      }
+      fFitZ[id]=mdrift-fz;
+    }
+    if (fStreamLevel>0){
+      TTreeSRedirector *cstream = GetDebugStreamer();
+      TTimeStamp tstamp(fTime);
+      Float_t valuePressure0  = AliTPCcalibDB::GetPressure(tstamp,fRun,0);
+      Float_t valuePressure1 = AliTPCcalibDB::GetPressure(tstamp,fRun,1);
+      Double_t ptrelative0   = AliTPCcalibDB::GetPTRelative(tstamp,fRun,0);
+      Double_t ptrelative1   = AliTPCcalibDB::GetPTRelative(tstamp,fRun,1);
+      Double_t temp0         = AliTPCcalibDB::GetTemperature(tstamp,fRun,0);
+      Double_t temp1         = AliTPCcalibDB::GetTemperature(tstamp,fRun,1);
+      TVectorD vecGoofie(20);
+      AliDCSSensorArray* goofieArray = AliTPCcalibDB::Instance()->GetGoofieSensors(fRun);
+      if (goofieArray) 
+       for (Int_t isensor=0; isensor<goofieArray->NumSensors();isensor++){
+         AliDCSSensor *gsensor = goofieArray->GetSensor(isensor);
+         if (gsensor) vecGoofie[isensor]=gsensor->GetValue(tstamp);
+       }
+
+      if (cstream){
+       (*cstream)<<"driftvN"<<
+         "run="<<fRun<<              //  run number
+         "event="<<fEvent<<          //  event number
+         "time="<<fTime<<            //  time stamp of event
+         "trigger="<<fTrigger<<      //  trigger
+         "mag="<<fMagF<<             //  magnetic field
+         // Environment values
+         "press0="<<valuePressure0<<
+         "press1="<<valuePressure1<<
+         "pt0="<<ptrelative0<<
+         "pt1="<<ptrelative1<<
+         "temp0="<<temp0<<
+         "temp1="<<temp1<<
+         "vecGoofie.="<<&vecGoofie<<
+         //
+         //
+         "iter="<<iter<<
+         "driftA.="<<fFitAside<<
+         "driftC.="<<fFitCside<<
+         "driftAC.="<<fFitACside<<
+         "chi2A="<<chi2A<<
+         "chi2C="<<chi2C<<
+         "chi2AC="<<chi2AC<<
+         "nA="<<npointsA<<
+         "nC="<<npointsC<<
+         "nAC="<<npointsAC<<
+         "\n";
+      }
+    }
+  }
+  return kTRUE;
+}
 
 Float_t AliTPCcalibLaser::GetDistance(AliExternalTrackParam *param, AliTPCLaserTrack *ltrp){
   //
@@ -906,6 +1240,8 @@ Int_t  AliTPCcalibLaser::FindMirror(AliESDtrack *track, AliTPCseed *seed){
   //
   Int_t countercl=0;
   Float_t counterSatur=0;
+  Int_t csideA =0;
+  Int_t csideC =0;
   for (Int_t irow=158;irow>-1;--irow) {
     AliTPCclusterMI *c=seed->GetClusterPointer(irow);
     if (!c) continue;
@@ -914,10 +1250,17 @@ Int_t  AliTPCcalibLaser::FindMirror(AliESDtrack *track, AliTPCseed *seed){
     if (pedgeY<3) continue;
     if (pedgeX<3) continue;
     countercl++;
+    if (c->GetDetector()%36<18) csideA++;
+    if (c->GetDetector()%36>=18) csideC++;
     if (c->GetMax()>900) counterSatur++;
   }
   counterSatur/=(countercl+1);
   //
+  //
+  //
+  if (csideA>0.1*seed->GetNumberOfClusters() && ltrp->GetSide()==1) return -1;
+  if (csideC>0.1*seed->GetNumberOfClusters() && ltrp->GetSide()==0) return -1;
+  //
   if (counterSatur>fClusterSatur[id]) fClusterSatur[id]=counterSatur;
   //
   //
@@ -1612,32 +1955,87 @@ void AliTPCcalibLaser::RefitLaserJW(Int_t id){
       TH2F *profz = (TH2F*)fDeltaZres.UncheckedAt(id);
       TH2F *profy2 = (TH2F*)fDeltaYres2.UncheckedAt(id);
       TH2F *profz2 = (TH2F*)fDeltaZres2.UncheckedAt(id);
+      TH2F *profyabs = (TH2F*)fDeltaYresAbs.UncheckedAt(id);
+      TH2F *profzabs = (TH2F*)fDeltaZresAbs.UncheckedAt(id);
       //      TH2F *profy3 = (TH2F*)fDeltaYres3.UncheckedAt(id);
       //TH2F *profz3 = (TH2F*)fDeltaZres3.UncheckedAt(id);
       //
       for (Int_t irow=158;irow>-1;--irow) {
        if (vecSec[irow]==-1)continue; // no cluster info
        if (isReject[irow]>0.5) continue;  // 
-       //Double_t x    = vecX[irow];
        Double_t ycl  = vecClY[irow];
        Double_t yfit = vecY1[irow];
        Double_t yfit2 = vecY2[irow];
+       Double_t x    = vecX[irow];
+       Double_t yabsbeam = -1000;
+       if(vecSec[irow]==outerSector && outerSector==fBeamSectorOuter[id])
+         yabsbeam = fBeamSlopeYOuter[id]*x + fBeamOffsetYOuter[id];
+       else if(innerSector==fBeamSectorInner[id])
+         yabsbeam = fBeamSlopeYInner[id]*x + fBeamOffsetYInner[id];
+
        //      Double_t yfit3 = vecY2[irow];
        Double_t zcl  = vecClZ[irow];
        Double_t zfit = vecZ1[irow];
        Double_t zfit2 = vecZ2[irow];
        //Double_t zfit3 = vecZ2[irow];
 
+       // dz abs 
+       // The expressions for zcorrected has been obtained by
+       // inverting the fits in the FitDriftV() method (ignoring the
+       // global y dependence for now):
+       // A side:
+       // 250 - zmeasured = [0] + [1]*(250 - zreal) + .... (yglobal)
+       // =>
+       // zreal = (zmeasured + [0] - (1-[1])*250.0)/[1]
+       // 
+       // C side:
+       // 250 + zmeasured  = [0] + [1]*(250+zreal) + .... (yglobal)
+       // =>
+       // zreal = (zmeasured - [0] + (1 - [1])*250.0)/[1]
+
+       Double_t dzabs = -1000;
+       if (ltrp->GetSide()==0){
+         if ((*fFitAside)[1]>0.) { 
+           // ignore global y dependence for now
+           Double_t zcorrected = (zcl + (*fFitAside)[0] - 
+                                  (1.0-(*fFitAside)[1])*250.0)/(*fFitAside)[1];
+           //      zcorrected = zcl;
+           if(vecSec[irow]==outerSector && (outerSector%36)==fBeamSectorOuter[id])
+             dzabs = zcorrected -fBeamSlopeZOuter[id]*x -fBeamOffsetZOuter[id];
+           else if((innerSector%36)==fBeamSectorInner[id])
+             dzabs = zcorrected -fBeamSlopeZInner[id]*x -fBeamOffsetZInner[id];
+         }
+       } else {
+         if ((*fFitCside)[1]>0.) {
+           Double_t zcorrected = (zcl - (*fFitCside)[0] + 
+                                  (1.0-(*fFitCside)[1])*250.0)/(*fFitCside)[1];
+           //      zcorrected = zcl;
+           if(vecSec[irow]==outerSector && (outerSector%36)==fBeamSectorOuter[id])
+             dzabs = zcorrected -fBeamSlopeZOuter[id]*x -fBeamOffsetZOuter[id];
+           else if((innerSector%36)==fBeamSectorInner[id])
+             dzabs = zcorrected -fBeamSlopeZInner[id]*x -fBeamOffsetZInner[id];
+         }
+       }
+       
        if (TMath::Abs(yfit-ycl)<2&&TMath::Abs(zfit-zcl)<2){
          if (profy){       
              profy->Fill(irow,ycl-yfit);
              profy2->Fill(irow,ycl-yfit2);
+             if(yabsbeam<-100)
+               profyabs->Fill(irow,-0.99);
+             else
+               profyabs->Fill(irow,ycl-yabsbeam);
+
              //              profy3->Fill(irow,ycl-yfit3);
          }
          if (profz) {
              profz->Fill(irow,zcl-zfit);
              profz2->Fill(irow,zcl-zfit2);
              //profz3->Fill(irow,zcl-zfit3);
+             if(dzabs<-100)
+               profzabs->Fill(irow,-0.99);
+             else
+               profzabs->Fill(irow,dzabs);
          }
        }
       }
@@ -1725,6 +2123,26 @@ void AliTPCcalibLaser::DumpMeanInfo(Float_t bfield, Int_t run){
   AliTPCcalibLaser *laser = this;
   TTreeSRedirector *pcstream = new TTreeSRedirector("laserMean.root");
   TF1 fg("fg","gaus");
+
+  // start set up for absolute residuals analysis
+  //AliTPCcalibDB*  calib=AliTPCcalibDB::Instance();
+  //  AliTPCParam  * tpcparam    = calib->GetParameters(); 
+  AliTPCParam  * tpcparam    = 0; 
+  if (!tpcparam) tpcparam    = new AliTPCParamSR;
+  tpcparam->Update();
+  SetBeamParameters(fBeamOffsetYOuter, fBeamSlopeYOuter, fBeamSectorOuter,0);
+  SetBeamParameters(fBeamOffsetYInner, fBeamSlopeYInner, fBeamSectorInner,1);
+  TLinearFitter lfabsyInner(2);
+  lfabsyInner.SetFormula("1 ++ x");
+  TLinearFitter lfabszInner(2);
+  lfabszInner.SetFormula("1 ++ x");
+
+  TLinearFitter lfabsyOuter(2);
+  lfabsyOuter.SetFormula("1 ++ x");
+  TLinearFitter lfabszOuter(2);
+  lfabszOuter.SetFormula("1 ++ x");
+  // end set up for absolute residuals analysis
+
   //
   //
   for (Int_t id=0; id<336; id++){
@@ -1758,7 +2176,7 @@ void AliTPCcalibLaser::DumpMeanInfo(Float_t bfield, Int_t run){
     Float_t rmsphiP = hisphiP->GetRMS();
     Float_t meanZ = hisZ->GetMean();
     Float_t rmsZ = hisZ->GetRMS();
-    if (hisphi->GetRMS()>0)
+    if (hisphi->GetRMS()>hisphi->GetBinWidth(1))
       hisphi->Fit(&fg,"","",hisphi->GetMean()-4*hisphi->GetRMS(),hisphi->GetMean()+4*hisphi->GetRMS());
     Double_t gphi1 = fg.GetParameter(1);
     Double_t gphi2 = fg.GetParameter(2);
@@ -1767,17 +2185,17 @@ void AliTPCcalibLaser::DumpMeanInfo(Float_t bfield, Int_t run){
     Double_t gphiP1 = fg.GetParameter(1);
     Double_t gphiP2 = fg.GetParameter(2);
     //
-    if (hisZ->GetRMS()>0)
-      hisZ->Fit(&fg,"","",hisZ->GetMean()-4*hisZ->GetRMS()-0.1,hisZ->GetMean()+4*hisZ->GetRMS()+0.1);
+    if (hisZ->GetRMS()>hisZ->GetBinWidth(1))
+      hisZ->Fit(&fg,"","");
     Double_t gz1 = fg.GetParameter(1);
     Double_t gz2 = fg.GetParameter(2);
     //
-    if (hisP3->GetRMS()>0)
+    if (hisP3->GetRMS()>hisP3->GetBinWidth(1))
       hisP3->Fit(&fg,"","",hisP3->GetMean()-4*hisP3->GetRMS(),hisP3->GetMean()+4*hisP3->GetRMS());
     Double_t gp31 = fg.GetParameter(1);
     Double_t gp32 = fg.GetParameter(2);
     //
-    if (hisP4->GetRMS()>0)
+    if (hisP4->GetRMS()>hisP4->GetBinWidth(1))
       hisP4->Fit(&fg,"","",hisP4->GetMean()-4*hisP4->GetRMS(),hisP4->GetMean()+4*hisP4->GetRMS());
     Double_t gp41 = fg.GetParameter(1);
     Double_t gp42 = fg.GetParameter(2);
@@ -1972,10 +2390,238 @@ void AliTPCcalibLaser::DumpMeanInfo(Float_t bfield, Int_t run){
     Float_t  mPz3vP2IO  = his->GetMean();
     Float_t  rPz3vP2IO  = his->GetRMS();
     delete his;
+
+    // Fit absolute laser residuals
+    TH2F* histAbsY = (TH2F*)laser->fDeltaYresAbs[id];
+    TH2F* histAbsZ = (TH2F*)laser->fDeltaZresAbs[id];
+
+    Int_t secInner = TMath::Nint(fBeamSectorInner[id]); 
+    Int_t secOuter = TMath::Nint(fBeamSectorOuter[id]); 
+
+    TVectorD vecX(159);        // X
+    TVectorD vecY(159);        // Y
+    TVectorD vecR(159);        // R
+    TVectorD vecDY(159);       // absolute residuals in Y
+    TVectorD vecDZ(159);       // absolute residuals in Z
+    TVectorD vecN(159);        // number of clusters
+    TVectorD vecEy(159);       //error y
+    TVectorD vecEz(159);       //error z
+    TVectorD vecPhi(159);      // local tangent
+    TVectorD vecPhiR(159);     // local tangent
+
+    lfabsyInner.ClearPoints();    
+    lfabszInner.ClearPoints();    
+    lfabsyOuter.ClearPoints();    
+    lfabszOuter.ClearPoints();    
+    // dummy fit values
+    Int_t    nClInY         = 0;
+    Float_t  yAbsInOffset  = -100;
+    Float_t  yAbsInSlope   = -100;
+    Float_t  yAbsInDeltay  = -100;
+    Int_t    nClInZ         = 0;
+    Float_t  zAbsInOffset  = -100;
+    Float_t  zAbsInSlope   = -100;
+    Float_t  zAbsInDeltaz  = -100;
+    Int_t    nClOutY         = 0;
+    Float_t  yAbsOutOffset  = -100;
+    Float_t  yAbsOutSlope   = -100;
+    Float_t  yAbsOutDeltay  = -100;
+    Int_t    nClOutZ         = 0;
+    Float_t  zAbsOutOffset  = -100;
+    Float_t  zAbsOutSlope   = -100;
+    Float_t  zAbsOutDeltaz  = -100;
+
+    Float_t  lasTanPhiLocIn = -100;
+    Float_t  lasTanPhiLocOut = -100;
+
+    if(histAbsY->GetEntries()>0) {
+      
+      Double_t rotAngOut = 10;
+      Double_t rotAngIn = 10;
+      if((secInner%36)!=(secOuter%36))
+       rotAngIn += 20; // 30 degrees
+      
+      // Calculate laser mirror X position in local frame
+      Double_t laserposOut = 
+       TMath::Abs(ltrp->GetX()*TMath::Cos(rotAngOut*TMath::DegToRad()));
+      Double_t laserposIn = 
+       TMath::Abs(ltrp->GetX()*TMath::Cos(rotAngIn*TMath::DegToRad()));
+      
+      // Calculate laser tan phi in local frame
+      lasTanPhiLocOut  = TMath::ASin(ltrp->GetSnp());
+      if(lasTanPhiLocOut<0) {
+       lasTanPhiLocIn  = lasTanPhiLocOut - rotAngIn*TMath::DegToRad();
+       lasTanPhiLocOut -= rotAngOut*TMath::DegToRad();
+      } else {
+       
+       lasTanPhiLocIn  = lasTanPhiLocOut + rotAngIn*TMath::DegToRad();
+       lasTanPhiLocOut += rotAngOut*TMath::DegToRad();
+      }
+      
+      lasTanPhiLocIn = TMath::Tan(lasTanPhiLocIn);
+      lasTanPhiLocOut = TMath::Tan(lasTanPhiLocOut);
+      
+      TProfile* yprof  = histAbsY->ProfileX("yprof");
+      TProfile* zprof  = histAbsZ->ProfileX("zprof");
+      
+      for(Int_t bin = 1; bin<=159; bin++) {
+       
+       if(yprof->GetBinEntries(bin)<10&&
+          zprof->GetBinEntries(bin)<10) {
+         continue;     
+       }
+       
+       // There is a problem in defining inner and outer sectors for
+       // the outer beams (0 and 6) where both sectors are OROCs. To
+       // make sure there is no overlap row 94 to 99 are cutted.
+       if(((ltrp->GetBeam()==0)||(ltrp->GetBeam()==6))&&bin>=95&&bin<=100)
+         continue;
+       
+       Int_t row = (bin-1);
+       if(row>62)
+         row -= 63;
+
+       Bool_t isOuter = kTRUE;
+       Int_t sector = TMath::Nint(fBeamSectorOuter[id]);
+       
+       if(bin<=62 ||                                        
+          (((ltrp->GetBeam()==0)||(ltrp->GetBeam()==6))&&bin<=95)) {
+
+         isOuter = kFALSE;
+         sector = TMath::Nint(fBeamSectorInner[id]);
+       }
+
+
+       Double_t x = tpcparam->GetPadRowRadii(sector, row); // slope
+       vecN[bin-1] =yprof->GetBinEntries(bin);
+       vecEy[bin-1]=yprof->GetBinError(bin);
+       vecEz[bin-1]=zprof->GetBinError(bin);
+       vecX[bin-1] = x;
+       vecDY[bin-1] = yprof->GetBinContent(bin);
+       vecDZ[bin-1] = zprof->GetBinContent(bin);
+       if(!isOuter) { // inner   
+         vecPhi[bin-1]=lasTanPhiLocIn;
+         // Calculate local y from residual and database
+         Double_t y  = fBeamSlopeYInner[id]*x + fBeamOffsetYInner[id]
+           + vecDY[bin-1];
+         vecY[bin-1] = y;
+         Double_t r  = TMath::Sqrt(x*x + y*y);
+         vecR[bin-1] = r;
+         // Find angle between laser vector and R vector
+         // cos angle = (x,y).(1,fBeamSlopeYInner)/R/sqrt(1+fBeamSlopeYInner**2)
+         Double_t cosPhi = x + y*fBeamSlopeYInner[id];
+         cosPhi /= r*TMath::Sqrt(1+fBeamSlopeYInner[id]*fBeamSlopeYInner[id]);
+         vecPhiR[bin-1] = TMath::Tan(TMath::ACos(cosPhi));
+         if(lasTanPhiLocIn<0)
+           vecPhiR[bin-1]*=-1; // to have the same sign
+         
+         if(yprof->GetBinEntries(bin)>=10) {
+           lfabsyInner.AddPoint(&x, yprof->GetBinContent(bin), 
+                                 TMath::Max(yprof->GetBinError(bin), 0.001));
+         } 
+         if(zprof->GetBinEntries(bin)>=10) {
+           lfabszInner.AddPoint(&x, zprof->GetBinContent(bin), 
+                                 TMath::Max(zprof->GetBinError(bin), 0.001));
+         }
+       } else { // outer
+         vecPhi[bin-1]=lasTanPhiLocOut;          
+         // Calculate local y from residual and database
+         Double_t y  = fBeamSlopeYOuter[id]*x + fBeamOffsetYOuter[id]
+           + vecDY[bin-1];
+         vecY[bin-1] = y;
+         Double_t r  = TMath::Sqrt(x*x + y*y);
+         vecR[bin-1] = r;
+
+         Double_t cosPhi = x + y*fBeamSlopeYOuter[id];
+         cosPhi /= r*TMath::Sqrt(1+fBeamSlopeYOuter[id]*fBeamSlopeYOuter[id]);
+         vecPhiR[bin-1] = TMath::Tan(TMath::ACos(cosPhi));
+         if(lasTanPhiLocOut<0)
+           vecPhiR[bin-1]*=-1; // to have the same sign
+
+         if(yprof->GetBinEntries(bin)>=10) {
+           lfabsyOuter.AddPoint(&x, yprof->GetBinContent(bin), 
+                                 TMath::Max(yprof->GetBinError(bin), 0.001));
+         }
+         if(zprof->GetBinEntries(bin)>=10) {
+           lfabszOuter.AddPoint(&x, zprof->GetBinContent(bin), 
+                                 TMath::Max(zprof->GetBinError(bin), 0.001));
+         }
+       }
+
+      }
+       
+      delete yprof; delete zprof;
+
+      
+      // Fit laser abs residuals with linear robust fit (exclude 5% outliers)
+      nClInY = lfabsyInner.GetNpoints();
+      if(lfabsyInner.GetNpoints()>10) {
+       lfabsyInner.EvalRobust(0.95);
+       
+       TVectorD result(2);
+       lfabsyInner.GetParameters(result);
+       yAbsInOffset = result[0];
+       yAbsInSlope  = result[1];
+       yAbsInDeltay = yAbsInSlope*laserposIn + yAbsInOffset;
+      }
+      nClInZ = lfabszInner.GetNpoints();
+      if(lfabszInner.GetNpoints()>10) {
+       lfabszInner.EvalRobust(0.95);
+       
+       TVectorD result(2);
+       lfabszInner.GetParameters(result);
+       zAbsInOffset = result[0];
+       zAbsInSlope  = result[1];
+       zAbsInDeltaz = zAbsInSlope*laserposIn + zAbsInOffset;
+      } 
+      nClOutY = lfabsyOuter.GetNpoints();
+      if(lfabsyOuter.GetNpoints()>10) {
+       lfabsyOuter.EvalRobust(0.95);
+       
+       TVectorD result(2);
+       lfabsyOuter.GetParameters(result);
+       yAbsOutOffset = result[0];
+       yAbsOutSlope  = result[1];
+       yAbsOutDeltay = yAbsOutSlope*laserposOut + yAbsOutOffset;
+      }
+      nClOutZ = lfabszOuter.GetNpoints();
+      if(lfabszOuter.GetNpoints()>10) {
+       lfabszOuter.EvalRobust(0.95);
+       
+       TVectorD result(2);
+       lfabszOuter.GetParameters(result);
+       zAbsOutOffset = result[0];
+       zAbsOutSlope  = result[1];
+       zAbsOutDeltaz = zAbsOutSlope*laserposOut + zAbsOutOffset;
+      }
+    }
+
     
+    Int_t itime=-1;
+    Float_t  coverIA=AliTPCcalibDB::GetCoverVoltage(run,0,itime);
+    Float_t  coverIC=AliTPCcalibDB::GetCoverVoltage(run,18,itime);
+    Float_t  coverOA=AliTPCcalibDB::GetCoverVoltage(run,36,itime);
+    Float_t  coverOC=AliTPCcalibDB::GetCoverVoltage(run,54,itime);
+    //
+    Float_t  skirtA=AliTPCcalibDB::GetSkirtVoltage(run,0,itime);
+    Float_t  skirtC=AliTPCcalibDB::GetSkirtVoltage(run,18,itime);
+    //
+    Float_t  ggOffA=AliTPCcalibDB::GetGGoffsetVoltage(run,0,itime);
+    Float_t  ggOffC=AliTPCcalibDB::GetGGoffsetVoltage(run,18,itime);
+
     //
     (*pcstream)<<"Mean"<<
       "run="<<run<<               //
+      //voltages
+      "UcIA="<<coverIA<<
+      "UcIC="<<coverIC<<
+      "UcOA="<<coverOA<<
+      "UcOC="<<coverOC<<
+      "UsA="<<skirtA<<
+      "UsC="<<skirtC<<
+      "UggA="<<ggOffA<<
+      "UggC="<<ggOffC<<
+      //
       "isOK="<<isOK<<             //
       "id="<<id<<                 // track id
       "entries="<<entries<<       // number of entries
@@ -2093,7 +2739,40 @@ void AliTPCcalibLaser::DumpMeanInfo(Float_t bfield, Int_t run){
       "gp32="<<gp32<<            //gaus rms  -tgl
       "gp41="<<gp41<<            //gaus mean - P4
       "gp42="<<gp42<<            //gaus rms  - P4
-
+      // Parameters from abs res analysis
+      "SecIn="<<secInner<<              // inner sector
+      "SecOut="<<secOuter<<             // outer sector
+      "lasTanPhiLocIn="<<lasTanPhiLocIn<< // laser tan phi in local frame (inner)
+      "lasTanPhiLocOut="<<lasTanPhiLocOut<<// laser tan phi in local frame (outer)
+      "X.="<<&vecX<<       // local x 
+      "Y.="<<&vecY<<       // local y 
+      "R.="<<&vecR<<       // radius 
+      "dY.="<<&vecDY<<     // abs y residuals
+      "dZ.="<<&vecDZ<<     // abs z residuals
+      "eY.="<<&vecEy<<     // error of y residuals
+      "eZ.="<<&vecEz<<     // error of z residuals
+      "kY.="<<&vecPhi<<    // local tangent y (fixed for sector)
+      "kYR.="<<&vecPhiR<<  // tangent between laser and R vector (varies inside sector) 
+      "nCl.="<<&vecN<<     // number of clusters
+      //
+      "nClInY="<<nClInY<<               // Number of clusters for inner y
+      "yAbsInOffset="<<yAbsInOffset<< // fitted offset absres (inner y)
+      "yAbsInSlope="<<yAbsInSlope <<  // fitted slope absres (inner y)
+      "yAbsInDeltay="<<yAbsInDeltay<< // fitted laser offset absres (inner y)
+      "nClInZ="<<nClInZ<<               // Number of clusters for inner z
+      "zAbsInOffset="<<zAbsInOffset<< // fitted offset absres (inner z)
+      "zAbsInSlope="<<zAbsInSlope <<  // fitted slope absres (inner z)
+      "zAbsInDeltaz="<<zAbsInDeltaz<< // fitted laser offset absres (inner z)
+      //
+      "nClOutY="<<nClOutY<<               // Number of clusters for outer y
+      "yAbsOutOffset="<<yAbsOutOffset<< // fitted offset absres (outer y)
+      "yAbsOutSlope="<<yAbsOutSlope <<  // fitted slope absres (outer y)
+      "yAbsOutDeltay="<<yAbsOutDeltay<< // fitted laser offset absres (outer y)
+      "nClOutZ="<<nClOutZ<<               // Number of clusters for outer z
+      "zAbsOutOffset="<<zAbsOutOffset<< // fitted offset absres (outer z)
+      "zAbsOutSlope="<<zAbsOutSlope <<  // fitted slope absres (outer z)
+      "zAbsOutDeltaz="<<zAbsOutDeltaz<< // fitted laser offset absres (outer z)
+      //
       "\n";
   }
   delete pcstream;
@@ -2137,7 +2816,7 @@ void AliTPCcalibLaser::DumpScanInfo(TTree * chain, const char * cutUser){
   Double_t pphi[3];
   Double_t pphiP[3];
   Double_t pmZ[3];
-  Double_t pmP4[3];
+  
   //
   for (Int_t id=0; id<336; id++){
     // id =205;
@@ -2384,6 +3063,15 @@ Long64_t AliTPCcalibLaser::Merge(TCollection *li) {
       h2m = (TH2F*)cal->fDeltaZres2.At(id);
       h2  = (TH2F*)fDeltaZres2.At(id);
       if (h2m&&h2) h2->Add(h2m);
+
+      // merge ProfileY histograms - abs
+      h2m = (TH2F*)cal->fDeltaYresAbs.At(id);
+      h2  = (TH2F*)fDeltaYresAbs.At(id);
+      if (h2m&&h2) h2->Add(h2m);
+
+      h2m = (TH2F*)cal->fDeltaZresAbs.At(id);
+      h2  = (TH2F*)fDeltaZresAbs.At(id);
+      if (h2m&&h2) h2->Add(h2m);
       // merge ProfileY histograms - 3
       //h2m = (TH2F*)cal->fDeltaYres3.At(id);
       //h2  = (TH2F*)fDeltaYres3.At(id);
@@ -2538,6 +3226,8 @@ void   AliTPCcalibLaser::MakeFitHistos(){
     TH2F *profz = (TH2F*)fDeltaZres.UncheckedAt(id);
     TH2F *profy2 = (TH2F*)fDeltaYres2.UncheckedAt(id);
     TH2F *profz2 = (TH2F*)fDeltaZres2.UncheckedAt(id);
+    TH2F *profyabs = (TH2F*)fDeltaYresAbs.UncheckedAt(id);
+    TH2F *profzabs = (TH2F*)fDeltaYresAbs.UncheckedAt(id);
     //    TH2F *profy3 = (TH2F*)fDeltaYres3.UncheckedAt(id);
     //TH2F *profz3 = (TH2F*)fDeltaZres3.UncheckedAt(id);
     if (!profy){
@@ -2547,6 +3237,9 @@ void   AliTPCcalibLaser::MakeFitHistos(){
       profy2=new TH2F(Form("pry%03d",id),Form("Y Residuals for Laser Beam %03d -Parabolic",id),160,0,160,50,-0.5,0.5);
       profy2->SetDirectory(0);
       fDeltaYres2.AddAt(profy2,id);
+      profyabs=new TH2F(Form("pryabs%03d",id),Form("Y Residuals for Laser Beam %03d -Absolute",id),160,0,160,100,-1.0,1.0); // has to be bigger based on earlier studies
+      profyabs->SetDirectory(0);
+      fDeltaYresAbs.AddAt(profyabs,id);
       //profy3=new TH2F(Form("pry%03d",id),Form("Y Residuals for Laser Beam %03d- Parabolic2",id),160,0,160,100,-0.5,0.5);
       //profy3->SetDirectory(0);
       //fDeltaYres3.AddAt(profy3,id);
@@ -2558,6 +3251,9 @@ void   AliTPCcalibLaser::MakeFitHistos(){
       profz2=new TH2F(Form("prz%03d",id),Form("Z Residuals for Laser Beam %03d - Parabolic",id),160,0,160,50,-0.5,0.5);
       profz2->SetDirectory(0);
       fDeltaZres2.AddAt(profz2,id);
+      profzabs=new TH2F(Form("przabs%03d",id),Form("Z Residuals for Laser Beam %03d -Absolute",id),160,0,160,100,-1.0,1.0); // has to be bigger based on earlier studies
+      profzabs->SetDirectory(0);
+      fDeltaZresAbs.AddAt(profzabs,id);
       //profz3=new TH2F(Form("prz%03d",id),Form("Z Residuals for Laser Beam %03d- Parabolic2",id),160,0,160,100,-0.5,0.5);
       //profz3->SetDirectory(0);
       //fDeltaZres3.AddAt(profz3,id);
@@ -2600,6 +3296,81 @@ void   AliTPCcalibLaser::MakeFitHistos(){
       fSignals.AddAt(hisSignal,id);
     }
   }
+
+  SetBeamParameters(fBeamOffsetZOuter, fBeamSlopeZOuter, fBeamSectorOuter,2);
+  SetBeamParameters(fBeamOffsetZInner, fBeamSlopeZInner, fBeamSectorInner,3);
+  SetBeamParameters(fBeamOffsetYOuter, fBeamSlopeYOuter, fBeamSectorOuter,0);
+  SetBeamParameters(fBeamOffsetYInner, fBeamSlopeYInner, fBeamSectorInner,1);
+  //
+  // Make THnSparse
+  //
+  //                   id   side   rod  bundle  beam  dP0  dP1  dP2  dP3  dP4 ncl dEdx 
+  Int_t binsLaser[12]= {336,  //id
+                       2,    //side
+                       6,    //rod
+                       4,    //bundle
+                       7,    //beam
+                       300,  //dP0
+                       300,  //dP1
+                       300,  //dP2
+                       300,  //dP3
+                       300,  //dP4
+                       80,   //ncl
+                       50};   //dEdx
+  Double_t xminLaser[12]= {0,  //id
+                       0,     //side
+                       0,     //rod
+                       0,     //bundle
+                       0,     //beam
+                       -1,    //dP0
+                       -1,    //dP1
+                       -0.01,   //dP2
+                       -0.01,  //dP3
+                       -0.1,  //dP4
+                       0,   //ncl
+                       0};   //sqrt dEdx
+  Double_t xmaxLaser[12]= {336,  //id
+                       2,    //side
+                       6,    //rod
+                       4,    //bundle
+                       7,    //beam
+                       1,  //dP0
+                       1,  //dP1
+                       0.01,  //dP2
+                       0.01,  //dP3
+                       0.1,  //dP4
+                       160,   //ncl
+                       40};   //sqrt dEdx
+  
+  TString nameLaser[12]= {"id",
+                         "side",
+                         "rod",
+                         "bundle",
+                         "beam",
+                         "dP0",
+                         "dP1",
+                         "dP2",
+                         "dP3",
+                         "dP4",
+                         "ncl",
+                         "sqrt dEdx"};
+  TString titleLaser[12]= {"id",
+                         "side",
+                         "rod",
+                         "bundle",
+                         "beam",
+                         "#Delta_{P0}",
+                         "#Delta_{P1}",
+                         "#Delta_{P2}",
+                         "#Delta_{P3}",
+                         "#Delta_{P4}",
+                         "N_{cl}",
+                         "#sqrt{dEdx}"};
+  fHisLaser = new THnSparseS("dLaser","#Delta_{Laser}", 12, binsLaser,xminLaser, xmaxLaser);
+  for (Int_t iaxis=1; iaxis<12; iaxis++){
+    fHisLaser->GetAxis(iaxis)->SetName(nameLaser[iaxis]);
+    fHisLaser->GetAxis(iaxis)->SetTitle(titleLaser[iaxis]);
+  }
 }
 
 void AliTPCcalibLaser::MergeFitHistos(AliTPCcalibLaser * laser){
@@ -2607,10 +3378,11 @@ void AliTPCcalibLaser::MergeFitHistos(AliTPCcalibLaser * laser){
   // Merge content of histograms 
   //
   // Only first histogram is checked - all other should be the same
+  if (fHisLaser &&laser->fHisLaser) fHisLaser->Add(laser->fHisLaser);
+
   if (!laser->fHisNclIn) return;  // empty histograms
   if (!fHisNclIn) MakeFitHistos();
   //
-  
   fHisNclIn->Add(laser->fHisNclIn  );      //->Number of clusters inner
   fHisNclOut->Add(laser->fHisNclOut  );     //->Number of clusters outer
   fHisNclIO->Add(laser->fHisNclIO  );      //->Number of cluster inner outer
@@ -2932,6 +3704,88 @@ void AliTPCcalibLaser::DumpFitInfo(TTree * chainFit,Int_t id){
     
     delete pcstream;
   }
+}
+
+void AliTPCcalibLaser::SetBeamParameters(TVectorD& meanOffset,
+                                        TVectorD& meanSlope,
+                                        TVectorD& sectorArray,
+                                        Int_t option)
+{
+  // This method should ideally go in AliTPCLaser
+  // option == 0 (pads outer - closest to beam)
+  // option == 1 (pads inner)
+  // option == 2 (time outer)
+  // option == 3 (time inner)
+  Int_t nFailures = 0;
+
+  for(Int_t id = 0; id < 336; id++) {
+    
+    if (!AliTPCLaserTrack::GetTracks()) 
+      AliTPCLaserTrack::LoadTracks();
+    AliTPCLaserTrack *ltrp =
+      (AliTPCLaserTrack*)AliTPCLaserTrack::GetTracks()->UncheckedAt(id);
+    
+    AliExternalTrackParam trackParam(*ltrp);
+    
+    Double_t deltaangle = 10.0; // sector is 1/2 a sector away from mirror
+    if((option==1 || option==3)&& (ltrp->GetBeam()<=1 || ltrp->GetBeam()>=5))
+      deltaangle = 30.0; // inner sector is 1 sector further away from mirror
+    
+    Double_t angle = trackParam.GetAlpha();
+    if(angle<0)
+      angle += 2*TMath::Pi();
+    if(trackParam.GetSnp()>0) // track points to sector "before"
+      angle -= deltaangle*TMath::DegToRad();
+    else // track points to sector "after"
+      angle += deltaangle*TMath::DegToRad();
+    
+    Bool_t success = trackParam.Rotate(angle);
+    
+    if(!success) {
+      //      cout << "WARNING: Rotate failed for ID: " << id << endl;
+      nFailures++;
+    }
+    
+    angle *= TMath::RadToDeg();
+    
+    Int_t sector = TMath::Nint((angle-10.0)/20.0);
+    if(sector<0)
+      sector += 18;
+    else if(sector>=18)
+      sector -= 18;
+    if(ltrp->GetSide()==1) // C side
+      sector += 18;
+    if(option==0 || option==2)
+      sector += 36;
+    if((option==1||option==3)&&(ltrp->GetBeam()==0||ltrp->GetBeam()==6)) 
+      sector += 36;
+
+    sectorArray[id] = sector;
+
+    const Double_t x0 = 0;
+    
+    Double_t slopey  = TMath::Tan(TMath::ASin(trackParam.GetSnp()));
+    Double_t slopez  = trackParam.GetTgl();
+    //  One needs a factor sqrt(1+slopey**2) to take into account the
+    //  longer path length
+    slopez *= TMath::Sqrt(1.0 + slopey*slopey);    
+    if(fInverseSlopeZ) // wrong sign in database, should be fixed there
+      slopez *= -1;
+    //    Double_t offsetz = trackParam.GetZ();
+    Double_t offsety = trackParam.GetY() + slopey*(x0-trackParam.GetX());
+    Double_t offsetz = trackParam.GetZ() + slopez*(x0-trackParam.GetX());
+    if(option==2 || option==3) {
+      meanOffset[id] = offsetz; meanSlope[id] = slopez;
+    } else {
+      meanOffset[id] = offsety; meanSlope[id] = slopey;
+    }
+  }
+
+  if(nFailures>0)
+    AliWarning(Form("Rotate method failed %d times", nFailures));
+}
+
+
   /*
     TFile f("vscan.root");
    */  
@@ -3020,8 +3874,6 @@ TH2 * phisPy2In = (TH2*) gROOT->FindObject("hisPy2In0")
 
 */
 
-}  
-