diff --git a/core/data/tof/CbmTofHit.h b/core/data/tof/CbmTofHit.h
index bcb32c9b609aef17fbc47211b2335963fc84ca1a..d74dcc4277b89c0e0b43fa54fdc33db7c37d470f 100644
--- a/core/data/tof/CbmTofHit.h
+++ b/core/data/tof/CbmTofHit.h
@@ -82,6 +82,12 @@ public:
   double GetCosPhi() const { return GetX() / GetRt(); }
   double GetSinPhi() const { return GetY() / GetRt(); }
 
+  inline double Dist3D(CbmTofHit* pHit)
+  {
+    return sqrt((GetX() - pHit->GetX()) * (GetX() - pHit->GetX()) + (GetY() - pHit->GetY()) * (GetY() - pHit->GetY())
+                + (GetZ() - pHit->GetZ()) * (GetZ() - pHit->GetZ()));
+  }
+
   /** Modifiers **/
   void SetFlag(int32_t flag) { fFlag = flag; };
 
diff --git a/reco/detectors/tof/CbmTofCalibrator.cxx b/reco/detectors/tof/CbmTofCalibrator.cxx
index e38c4d3a677ebee0f626c39652bf0e1beeef1d65..6ffed6831f2bfb060209af7235c70ab775336705 100644
--- a/reco/detectors/tof/CbmTofCalibrator.cxx
+++ b/reco/detectors/tof/CbmTofCalibrator.cxx
@@ -16,8 +16,7 @@
 #include "CbmTofAddress.h"  // in cbmdata/tof
 #include "CbmTofCell.h"     // in tof/TofData
 #include "CbmTofClusterizersDef.h"
-#include "CbmTofDetectorId_v12b.h"  // in cbmdata/tof
-#include "CbmTofDetectorId_v14a.h"  // in cbmdata/tof
+#include "CbmTofDetectorId_v21a.h"  // in cbmdata/tof
 #include "CbmTofDigiBdfPar.h"       // in tof/TofParam
 #include "CbmTofDigiPar.h"          // in tof/TofParam
 #include "CbmTofGeoHandler.h"       // in tof/TofTools
@@ -30,6 +29,7 @@
 #include <Logger.h>
 
 // ROOT Classes and includes
+#include "TF1.h"
 #include <TClonesArray.h>
 #include <TDirectory.h>
 #include <TFile.h>
@@ -37,10 +37,18 @@
 #include <TGeoManager.h>
 #include <TH1.h>
 #include <TH2.h>
+#include <TH3.h>
 #include <TMinuit.h>
 #include <TProfile.h>
 #include <TROOT.h>
 
+const int MaxShift            = 10;       // number of 50ps bins
+const double cLight           = 29.9792;  // in cm/ns
+const TString cBadChannelFile = "TofBadChannels.txt";
+const double dValidEdge       = 1.0;  // FIXME: constants in code
+
+std::vector<TH1*> hSvel;
+
 CbmTofCalibrator::CbmTofCalibrator()
   : fDigiMan(NULL)
   , fTofClusterizer(NULL)
@@ -52,12 +60,21 @@ CbmTofCalibrator::CbmTofCalibrator()
   , fhCalR0(NULL)
   , fhCalDX0(NULL)
   , fhCalDY0(NULL)
+  , fhCalCounterDt(NULL)
+  , fhCalCounterDy(NULL)
+  , fhCalChannelDt(NULL)
+  , fhCalChannelDy(NULL)
   , fhCalTot()
   , fhCalPosition()
   , fhCalPos()
   , fhCalTOff()
   , fhCalTofOff()
+  , fhCalDelPos()
+  , fhCalDelTOff()
+  , fhCalCluTrms()
+  , fhCalCluSize()
   , fhCalWalk()
+  , fhCalDtWalk()
   , fhCorPos()
   , fhCorTOff()
   , fhCorTot()
@@ -128,8 +145,16 @@ InitStatus CbmTofCalibrator::Init()
     return kFATAL;
   }
 
+  fTofId = new CbmTofDetectorId_v21a();
+
   fTrackletTools = new CbmTofTrackletTools();  // initialize tools
 
+  TString shcmd = Form("rm %s  ", cBadChannelFile.Data());
+  gSystem->Exec(shcmd.Data());
+
+  shcmd = Form("touch %s  ", cBadChannelFile.Data());
+  gSystem->Exec(shcmd.Data());
+
   LOG(info) << "TofCalibrator initialized successfully";
   return kSUCCESS;
 }
@@ -164,12 +189,28 @@ Bool_t CbmTofCalibrator::CreateCalHist()
   fhCalDX0 = new TH1D("hCalDX0", "Tracklet distance to nominal vertex; #DeltaX_0 [cm]", 100, -1.5, 1.5);
   fhCalDY0 = new TH1D("hCalDY0", "Tracklet distance to nominal vertex; #DeltaY_0 [cm]", 100, -1.5, 1.5);
 
+  fhCalCounterDt = new TH1D("hCalCounterDt", "CalibCounterDt ; #Deltat [ns]", 100, -0.2, 0.2);
+  fhCalCounterDy = new TH1D("hCalCounterDy", "CalibCounterDy ; #Deltay [cm]", 100, -0.8, 0.8);
+  fhCalChannelDt = new TH1D("hCalChannelDt", "CalibChannelDt ; #Deltat [ns]", 100, -0.25, 0.25);
+  fhCalChannelDy = new TH1D("hCalChannelDy", "CalibChannelDy ; #Deltat [ns]", 100, -1.8, 1.8);
+
   fhCalTot.resize(iNbDet);
   fhCalPosition.resize(iNbDet);
   fhCalPos.resize(iNbDet);
   fhCalTOff.resize(iNbDet);
   fhCalTofOff.resize(iNbDet);
+  fhCalDelPos.resize(iNbDet);
+  fhCalDelTOff.resize(iNbDet);
+  fhCalCluTrms.resize(iNbDet);
+  fhCalCluSize.resize(iNbDet);
   fhCalWalk.resize(iNbDet);
+  fhCalDtWalk.resize(iNbDet);
+  fhCalWalkAv.resize(iNbDet);
+
+  fhCalXYTOff.resize(iNbDet);
+  fhCalXYTot.resize(iNbDet);
+  fhCalTotYWalk.resize(iNbDet);
+  fhCalTotYTOff.resize(iNbDet);
 
   fDetIdIndexMap.clear();
 
@@ -186,6 +227,7 @@ Bool_t CbmTofCalibrator::CreateCalHist()
       LOG(warning) << "No DigiPar for Det " << Form("0x%08x", iUCellId);
       continue;
     }
+    Double_t YMAX = TMath::Max(2., fChannelInfo->GetSizey()) * 0.75;
 
     Double_t TotMax    = 20.;
     fhCalTot[iDetIndx] = new TH2F(
@@ -193,13 +235,18 @@ Bool_t CbmTofCalibrator::CreateCalHist()
       Form("Clu Tot of Rpc #%03d in Sm %03d of type %d; Strip []; Tot [a.u.]", iRpcId, iSmId, iSmType),
       2 * fDigiBdfPar->GetNbChan(iSmType, iRpcId), 0, 2 * fDigiBdfPar->GetNbChan(iSmType, iRpcId), 100, 0., TotMax);
 
-    Double_t YDMAX = TMath::Max(2., fChannelInfo->GetSizey()) * 1.;
+    fhCalXYTot[iDetIndx] =
+      new TH3F(Form("calXY_SmT%01d_sm%03d_rpc%03d_Tot", iSmType, iSmId, iRpcId),
+               Form("Clu Tot of Rpc #%03d in Sm %03d of type %d; Strip []; y [cm]; Tot [a.u.]", iRpcId, iSmId, iSmType),
+               2 * fDigiBdfPar->GetNbChan(iSmType, iRpcId), 0, 2 * fDigiBdfPar->GetNbChan(iSmType, iRpcId), 20, -YMAX,
+               YMAX, 100, 0., TotMax);
+
     fhCalPosition[iDetIndx] =
       new TH2F(Form("cal_SmT%01d_sm%03d_rpc%03d_Position", iSmType, iSmId, iRpcId),
                Form("Clu position of Rpc #%03d in Sm %03d of type %d; Strip []; ypos [cm]", iRpcId, iSmId, iSmType),
-               fDigiBdfPar->GetNbChan(iSmType, iRpcId), 0, fDigiBdfPar->GetNbChan(iSmType, iRpcId), 100, -YDMAX, YDMAX);
+               fDigiBdfPar->GetNbChan(iSmType, iRpcId), 0, fDigiBdfPar->GetNbChan(iSmType, iRpcId), 100, -YMAX, YMAX);
 
-    YDMAX = 5;
+    Double_t YDMAX = 5;
     fhCalPos[iDetIndx] =
       new TH2F(Form("cal_SmT%01d_sm%03d_rpc%03d_Pos", iSmType, iSmId, iRpcId),
                Form("Clu pos deviation of Rpc #%03d in Sm %03d of type %d; "
@@ -209,31 +256,88 @@ Bool_t CbmTofCalibrator::CreateCalHist()
 
     Double_t TSumMax = 2.;
     //if(iSmType == 5) TSumMax *= 2.; // enlarge for diamond / beamcounter
-    fhCalTOff[iDetIndx] = new TH2F(Form("cal_SmT%01d_sm%03d_rpc%03d_TOff", iSmType, iSmId, iRpcId),
-                                   Form("Clu T0 deviation of Rpc #%03d in Sm %03d of type %d; "
-                                        "Strip []; TOff [ns]",
-                                        iRpcId, iSmId, iSmType),
-                                   fDigiBdfPar->GetNbChan(iSmType, iRpcId), 0, fDigiBdfPar->GetNbChan(iSmType, iRpcId),
-                                   99, -TSumMax, TSumMax);
-    TSumMax               = 50.;
+    fhCalTOff[iDetIndx] = new TH2F(
+      Form("cal_SmT%01d_sm%03d_rpc%03d_TOff", iSmType, iSmId, iRpcId),
+      Form("Clu T0 deviation of Rpc #%03d in Sm %03d of type %d; Strip []; TOff [ns]", iRpcId, iSmId, iSmType),
+      fDigiBdfPar->GetNbChan(iSmType, iRpcId), 0, fDigiBdfPar->GetNbChan(iSmType, iRpcId), 200, -TSumMax, TSumMax);
+
+    fhCalXYTOff[iDetIndx] = new TH3F(
+      Form("calXY_SmT%01d_sm%03d_rpc%03d_TOff", iSmType, iSmId, iRpcId),
+      Form("XY T0 deviation of Rpc #%03d in Sm %03d of type %d; Strip []; y[cm]; TOff [ns]", iRpcId, iSmId, iSmType),
+      fDigiBdfPar->GetNbChan(iSmType, iRpcId), 0, fDigiBdfPar->GetNbChan(iSmType, iRpcId), 100, -YMAX, YMAX, 100,
+      -TSumMax * 0.5, TSumMax * 0.5);
+
+    TSumMax               = 20.;
     fhCalTofOff[iDetIndx] = new TH2F(Form("cal_SmT%01d_sm%03d_rpc%03d_TofOff", iSmType, iSmId, iRpcId),
                                      Form("Clu T0 deviation of Rpc #%03d in Sm %03d of type %d; "
                                           "Strip []; TofOff [ns]",
                                           iRpcId, iSmId, iSmType),
                                      fDigiBdfPar->GetNbChan(iSmType, iRpcId), 0,
-                                     fDigiBdfPar->GetNbChan(iSmType, iRpcId), 99, -TSumMax, TSumMax);
+                                     fDigiBdfPar->GetNbChan(iSmType, iRpcId), 199, -TSumMax, TSumMax);
+
+    fhCalDelPos[iDetIndx] =
+      new TH2F(Form("cal_SmT%01d_sm%03d_rpc%03d_DelPos", iSmType, iSmId, iRpcId),
+               Form("Clu position difference of Rpc #%03d in Sm %03d of type "
+                    "%d; Strip []; #Deltaypos(clu) [cm]",
+                    iRpcId, iSmId, iSmType),
+               fDigiBdfPar->GetNbChan(iSmType, iRpcId), 0, fDigiBdfPar->GetNbChan(iSmType, iRpcId), 99, -10., 10.);
+
+    fhCalDelTOff[iDetIndx] =
+      new TH2F(Form("cal_SmT%01d_sm%03d_rpc%03d_DelTOff", iSmType, iSmId, iRpcId),
+               Form("Clu TimeZero Difference of Rpc #%03d in Sm %03d of type %d; Strip "
+                    "[]; #DeltaTOff(clu) [ns]",
+                    iRpcId, iSmId, iSmType),
+               fDigiBdfPar->GetNbChan(iSmType, iRpcId), 0, fDigiBdfPar->GetNbChan(iSmType, iRpcId), 99, -0.6, 0.6);
+
+    fhCalCluTrms[iDetIndx] =
+      new TH2D(Form("cal_SmT%01d_sm%03d_rpc%03d_Trms", iSmType, iSmId, iRpcId),
+               Form("Clu Time RMS of Rpc #%03d in Sm %03d of type %d; Strip []; Trms [ns]", iRpcId, iSmId, iSmType),
+               fDigiBdfPar->GetNbChan(iSmType, iRpcId), 0, fDigiBdfPar->GetNbChan(iSmType, iRpcId), 99, 0., 0.5);
+
+    fhCalCluSize[iDetIndx] =
+      new TH2D(Form("cal_SmT%01d_sm%03d_rpc%03d_Size", iSmType, iSmId, iRpcId),
+               Form("Clu size of Rpc #%03d in Sm %03d of type %d; Strip []; size [strips]", iRpcId, iSmId, iSmType),
+               fDigiBdfPar->GetNbChan(iSmType, iRpcId), 0, fDigiBdfPar->GetNbChan(iSmType, iRpcId), 16, 0.5, 16.5);
 
     TSumMax = 0.8;
+    fhCalWalkAv[iDetIndx] =
+      new TH2D(Form("cal_SmT%01d_sm%03d_rpc%03d_WalkAv", iSmType, iSmId, iRpcId),
+               Form("Walk in SmT%01d_sm%03d_rpc%03d_WalkAv; Tot [a.u.];  #DeltaT [ns]", iSmType, iSmId, iRpcId),
+               nbClWalkBinX, 0., TotMax, nbClWalkBinY, -TSumMax, TSumMax);
+
     fhCalWalk[iDetIndx].resize(fDigiBdfPar->GetNbChan(iSmType, iRpcId));
+    fhCalDtWalk[iDetIndx].resize(fDigiBdfPar->GetNbChan(iSmType, iRpcId));
+    fhCalTotYWalk[iDetIndx].resize(fDigiBdfPar->GetNbChan(iSmType, iRpcId));
+    fhCalTotYTOff[iDetIndx].resize(fDigiBdfPar->GetNbChan(iSmType, iRpcId));
+
     for (Int_t iCh = 0; iCh < fDigiBdfPar->GetNbChan(iSmType, iRpcId); iCh++) {
       fhCalWalk[iDetIndx][iCh].resize(2);
+      fhCalDtWalk[iDetIndx][iCh].resize(2);
+      fhCalTotYWalk[iDetIndx][iCh].resize(2);
+      fhCalTotYTOff[iDetIndx][iCh].resize(2);
       for (Int_t iSide = 0; iSide < 2; iSide++) {
         fhCalWalk[iDetIndx][iCh][iSide] =
           new TH2D(Form("cal_SmT%01d_sm%03d_rpc%03d_Ch%03d_S%01d_Walk", iSmType, iSmId, iRpcId, iCh, iSide),
-                   Form("Walk in SmT%01d_sm%03d_rpc%03d_Ch%03d_S%01d_Walk; Tot "
-                        "[a.u.];  #DeltaT [ns]",
-                        iSmType, iSmId, iRpcId, iCh, iSide),
+                   Form("Walk in SmT%01d_sm%03d_rpc%03d_Ch%03d_S%01d_Walk; Tot [a.u.];  #DeltaT [ns]", iSmType, iSmId,
+                        iRpcId, iCh, iSide),
+                   nbClWalkBinX, 0., TotMax, nbClWalkBinY, -TSumMax, TSumMax);
+        fhCalDtWalk[iDetIndx][iCh][iSide] =
+          new TH2D(Form("cal_SmT%01d_sm%03d_rpc%03d_Ch%03d_S%01d_DtWalk", iSmType, iSmId, iRpcId, iCh, iSide),
+                   Form("SmT%01d_sm%03d_rpc%03d_Ch%03d_S%01d_DtWalk; Tot [a.u.];  #DeltaT [ns]", iSmType, iSmId, iRpcId,
+                        iCh, iSide),
                    nbClWalkBinX, 0., TotMax, nbClWalkBinY, -TSumMax, TSumMax);
+
+        fhCalTotYWalk[iDetIndx][iCh][iSide] =
+          new TH3D(Form("calTotY_SmT%01d_sm%03d_rpc%03d_Ch%03d_S%01d_Walk", iSmType, iSmId, iRpcId, iCh, iSide),
+                   Form("YWalk in SmT%01d_sm%03d_rpc%03d_Ch%03d_S%01d_Walk; Tot [a.u.]; y [cm];  #DeltaT [ns]", iSmType,
+                        iSmId, iRpcId, iCh, iSide),
+                   nbClWalkBinX, 0., TotMax, 20, -YMAX, YMAX, nbClWalkBinY, -0.4, 0.4);
+
+        fhCalTotYTOff[iDetIndx][iCh][iSide] =
+          new TH3D(Form("calTotY_SmT%01d_sm%03d_rpc%03d_Ch%03d_S%01d_TOff", iSmType, iSmId, iRpcId, iCh, iSide),
+                   Form("YTot in SmT%01d_sm%03d_rpc%03d_Ch%03d_S%01d_TOff; Tot [a.u.]; y [cm];  #DeltaT [ns]", iSmType,
+                        iSmId, iRpcId, iCh, iSide),
+                   nbClWalkBinX, 0., TotMax, 20, -YMAX, YMAX, nbClWalkBinY, -TSumMax * 0.5, TSumMax * 0.5);
       }
     }
   }
@@ -242,11 +346,13 @@ Bool_t CbmTofCalibrator::CreateCalHist()
 }
 
 static Int_t NevtH = 0;
-void CbmTofCalibrator::FillCalHist(CbmTofHit* pRef, Int_t /*iOpt*/, CbmEvent* /*tEvent*/)
+void CbmTofCalibrator::FillCalHist(CbmTofHit* pRef, Int_t iOpt, CbmEvent* tEvent)
 {
-  if (NULL == fTofCalDigiVec) LOG(fatal) << "No access to TofCalDigis!";
+  if (NULL == fTofCalDigiVec) LOG(fatal) << "No access to TofCalDigis! for Event " << tEvent;
 
   NevtH++;
+  if (NevtH == 1) LOG(info) << "FillCalHist: look for beam counter at " << pRef;
+
   double dTAv = 0.;
   if (pRef != NULL) dTAv = pRef->GetTime();
   else {
@@ -347,18 +453,20 @@ void CbmTofCalibrator::FillCalHist(CbmTofHit* pRef, Int_t /*iOpt*/, CbmEvent* /*
       LOG(error) << "Invalid Channel Pointer for ChId " << Form(" 0x%08x ", iChId) << ", Ch " << iCh;
       continue;
     }
-    gGeoManager->FindNode(fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ());
+    //gGeoManager->FindNode(fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ());
     Double_t hitpos[3];
     hitpos[0] = pHit->GetX();
     hitpos[1] = pHit->GetY();
     hitpos[2] = pHit->GetZ();
     Double_t hlocal_p[3];
     //TGeoNode* cNode=
-    gGeoManager->GetCurrentNode();
-    gGeoManager->MasterToLocal(hitpos, hlocal_p);
+    //gGeoManager->GetCurrentNode();
+    //gGeoManager->MasterToLocal(hitpos, hlocal_p);
+    fTofClusterizer->MasterToLocal(iChId, hitpos, hlocal_p);
+
     /*
-    LOG(info)<<Form(" Ev %d: TSRC %d%d%d%2d, y %6.2f, tof %6.2f ",
-    		   NevtH,iSmType,iSm,iRpc,iCh,hlocal_p[1],pHit->GetTime() - pRef->GetTime());
+    LOG(info)<<Form(" Ev %d: TSRC %d%d%d%2d, y %6.2f, tof %6.2f, Tref %12.1f ",
+    		   NevtH,iSmType,iSm,iRpc,iCh,hlocal_p[1],pHit->GetTime() - dTAv, pRef->GetTime());
     */
     fhCalPosition[iDetIndx]->Fill((Double_t) iCh, hlocal_p[1]);  // transformed into LRF
     /*
@@ -366,19 +474,293 @@ void CbmTofCalibrator::FillCalHist(CbmTofHit* pRef, Int_t /*iOpt*/, CbmEvent* /*
       fhCalTofOff[iDetIndx]->Fill((Double_t) iCh,
                               pHit->GetTime() - pRef->GetTime());  // ignore any dependence
                               */
-    fhCalTofOff[iDetIndx]->Fill((Double_t) iCh, pHit->GetTime() - dTAv);
+    if (iOpt < 100) {
+      fhCalTOff[iDetIndx]->Fill((Double_t) iCh, pHit->GetTime() - dTAv);
+      fhCalXYTOff[iDetIndx]->Fill((Double_t) iCh, hlocal_p[1], pHit->GetTime() - dTAv);
+      fhCalTofOff[iDetIndx]->Fill((Double_t) iCh, pHit->GetTime() - dTAv);
+    }
+    else {
+      double dTexp = pHit->GetR() * fTofFindTracks->GetTtTarg();
+      fhCalTOff[iDetIndx]->Fill((Double_t) iCh, pHit->GetTime() - dTAv);
+      fhCalXYTOff[iDetIndx]->Fill((Double_t) iCh, hlocal_p[1], pHit->GetTime() - dTAv);
+      fhCalTofOff[iDetIndx]->Fill((Double_t) iCh, pHit->GetTime() - dTAv - dTexp);
+    }
   }
 
   return;
 }
 
+void CbmTofCalibrator::FillHitCalHist(CbmTofHit* pRef, const Int_t iOpt, CbmEvent* tEvent, TClonesArray* tTofHitsColl)
+{
+  if (NULL == fTofCalDigiVec) LOG(fatal) << "No access to TofCalDigis! for Event " << tEvent;
+  if (NULL == tTofHitsColl) LOG(fatal) << "No access to TofHits! for Event " << tEvent;
+
+  NevtH++;
+  if (NevtH == 1)
+    LOG(warn) << "HitCalHist at " << NevtH << ", Opt = " << iOpt << ", pRef " << pRef << ", "
+              << Form("0x%08x", fTofClusterizer->GetBeamAddr());
+
+  double dTAv = 0.;
+  if (pRef != NULL) {
+    dTAv = pRef->GetTime();
+    //LOG(debug) << "HitCalHist got Tbeam " << dTAv << ", Opt = " << iOpt;
+  }
+  else {
+    if (-1 < fTofClusterizer->GetBeamAddr()) {  // look for beam counter
+      if (NevtH == 1) LOG(warn) << Form("FillHitCalHist: look for beam counter 0x%08x", fTofClusterizer->GetBeamAddr());
+      Int_t iHit = 0;
+      //for (; iHit < (int) fTofFindTracks->GetNbHits(); iHit++) {
+      for (; iHit < tEvent->GetNofData(ECbmDataType::kTofHit); iHit++) {
+        //CbmTofHit* pHit = fTofFindTracks->GetHitPointer(iHit);
+        Int_t iHitIndex = static_cast<Int_t>(tEvent->GetIndex(ECbmDataType::kTofHit, iHit));
+        CbmTofHit* pHit = (CbmTofHit*) tTofHitsColl->At(iHitIndex);
+        if (NULL == pHit) continue;
+        if ((pHit->GetAddress() & DetMask) == (fTofClusterizer->GetBeamAddr() & DetMask)) {
+          if (pRef != NULL) {
+            if (pHit->GetTime() < dTAv) pRef = pHit;
+          }
+          else {
+            pRef = pHit;
+          }
+          dTAv = pRef->GetTime();
+          if (NevtH == 1) LOG(warn) << "FillHitCalHist: found beam counter";
+          break;
+        }
+      }
+      if (iHit == tEvent->GetNofData(ECbmDataType::kTofHit)) return;  // beam counter not present
+    }
+    else {
+      double dNAv = 0.;
+      for (Int_t iHit = 0; iHit < tEvent->GetNofData(ECbmDataType::kTofHit); iHit++) {
+        Int_t iHitIndex = static_cast<Int_t>(tEvent->GetIndex(ECbmDataType::kTofHit, iHit));
+        CbmTofHit* pHit = (CbmTofHit*) tTofHitsColl->At(iHitIndex);
+        if (NULL == pHit) continue;
+        dTAv += pHit->GetTime();
+        dNAv++;
+      }
+      if (dNAv == 0) return;
+      dTAv /= dNAv;
+    }
+  }
+
+  for (Int_t iHit = 0; iHit < tEvent->GetNofData(ECbmDataType::kTofHit); iHit++) {
+    Int_t iHitIndex = static_cast<Int_t>(tEvent->GetIndex(ECbmDataType::kTofHit, iHit));
+    CbmTofHit* pHit = (CbmTofHit*) tTofHitsColl->At(iHitIndex);
+    if (NULL == pHit) continue;
+
+    Int_t iDetId  = (pHit->GetAddress() & DetMask);
+    Int_t iSmType = CbmTofAddress::GetSmType(iDetId);
+    Int_t iSm     = CbmTofAddress::GetSmId(iDetId);
+    Int_t iRpc    = CbmTofAddress::GetRpcId(iDetId);
+
+    std::map<UInt_t, UInt_t>::iterator it = fDetIdIndexMap.find(iDetId);
+    if (it == fDetIdIndexMap.end()) {
+      LOG(info) << "detector TSR " << iSmType << iSm << iRpc << " not found in detector map";
+      continue;  // continue for invalid detector index
+    }
+    Int_t iDetIndx = it->second;  //fDetIdIndexMap[iDetId];
+
+    Int_t iChId  = pHit->GetAddress();
+    Int_t iCh    = CbmTofAddress::GetChannelId(iChId);
+    double dTexp = 0.;
+
+    /*
+    CbmTofCell* fChannelInfo = fDigiPar->GetCell(iChId);
+    if (NULL == fChannelInfo) {
+      LOG(error) << "Invalid Channel Pointer for ChId " << Form(" 0x%08x ", iChId) << ", Ch " << iCh;
+      continue;
+    }
+    */
+
+    Double_t hitpos[3];
+    hitpos[0] = pHit->GetX();
+    hitpos[1] = pHit->GetY();
+    hitpos[2] = pHit->GetZ();
+    Double_t hlocal_p[3];
+
+    fTofClusterizer->MasterToLocal(iChId, hitpos, hlocal_p);
+
+    LOG(debug) << Form(" Ev %d: TSRC %d%d%d%2d, y %6.2f, tof %6.2f, Tref %12.1f ", NevtH, iSmType, iSm, iRpc, iCh,
+                       hlocal_p[1], pHit->GetTime() - dTAv, pRef->GetTime());
+
+    fhCalPosition[iDetIndx]->Fill((Double_t) iCh, hlocal_p[1]);  // transformed into LRF
+
+    if (iOpt < 100) {
+      LOG(debug) << "Fill " << fhCalTofOff[iDetIndx]->GetName();
+      if (pHit != pRef) {
+        fhCalTOff[iDetIndx]->Fill((Double_t) iCh, pHit->GetTime() - dTAv);
+        fhCalXYTOff[iDetIndx]->Fill((Double_t) iCh, hlocal_p[1], pHit->GetTime() - dTAv);
+        fhCalTofOff[iDetIndx]->Fill((Double_t) iCh, pHit->GetTime() - dTAv);
+      }
+    }
+    else {
+      if (iSmType != 5) {
+        if (NULL != pRef) {
+          if ((pHit->GetAddress() & DetMask) != (pRef->GetAddress() & DetMask)) {
+            dTexp = pHit->Dist3D(pRef) / cLight;  // Edge expected for speed of light,
+            if (pHit->GetZ() < pRef->GetZ()) dTexp *= -1;
+
+            LOG(debug) << Form(" Ev %d: TSRC %d%d%d%2d, y %6.2f, tof %6.2f, Tref %12.1f, Texp %12.1f ", NevtH, iSmType,
+                               iSm, iRpc, iCh, hlocal_p[1], pHit->GetTime() - dTAv, pRef->GetTime(), dTexp);
+          }
+        }
+        else {
+          dTexp = pHit->GetR() / cLight;  // Edge expected for speed of light, fTofFindTracks->GetTtTarg();
+        }
+        /*
+          LOG(debug)<<"Fill " << fhCalTofOff[iDetIndx]->GetName()<<" " << iHit <<": " << iCh << ", "
+                  << pHit->GetTime() - dTAv <<" - " << dTexp;
+        */
+        if (dTexp != 0.) {
+          fhCalTOff[iDetIndx]->Fill((Double_t) iCh, pHit->GetTime() - dTAv - dTexp);
+          fhCalXYTOff[iDetIndx]->Fill((Double_t) iCh, hlocal_p[1], pHit->GetTime() - dTAv - dTexp);
+          fhCalTofOff[iDetIndx]->Fill((Double_t) iCh, pHit->GetTime() - dTAv - dTexp);
+        }
+      }
+    }
+
+    // fill CalDigi Tots and internal walks
+    if (dTexp != 0.) {
+      CbmMatch* digiMatch = fTofClusterizer->GetMatchIndexPointer(iHitIndex);
+      if (NULL == digiMatch) LOG(fatal) << "No digiMatch for Hit " << iHit << ", TSR " << iSmType << iSm << iRpc;
+      if (digiMatch->GetNofLinks() < fTofClusterizer->GetCluSizeMin()) continue;
+      double dMeanTimeSquared = 0.;
+      double dTotSum          = 0.;
+      double dYSum            = 0.;
+      for (Int_t iLink = 0; iLink < digiMatch->GetNofLinks(); iLink += 2) {  // first loop over digis
+        CbmLink L0      = digiMatch->GetLink(iLink);
+        UInt_t iDigInd0 = L0.GetIndex();
+        UInt_t iDigInd1 = (digiMatch->GetLink(iLink + 1)).GetIndex();
+        //LOG(debug1)<<" " << iDigInd0<<", "<<iDigInd1;
+        if (iDigInd0 < fTofCalDigiVec->size() && iDigInd1 < fTofCalDigiVec->size()) {
+          const CbmTofDigi* pDig0 = &(fTofCalDigiVec->at(iDigInd0));
+          const CbmTofDigi* pDig1 = &(fTofCalDigiVec->at(iDigInd1));
+          if ((Int_t) pDig0->GetType() != iSmType) {
+            LOG(error) << Form(" Wrong Digi SmType %d - %d for Tofhit %d in iDetIndx "
+                               "%d, Ch %d with %d strips at Indx %d, %d",
+                               iSmType, (Int_t) pDig0->GetType(), iHit, iDetIndx, iCh,
+                               fDigiBdfPar->GetNbChan(iSmType, iRpc), iDigInd0, iDigInd1);
+
+            for (Int_t iL = 0; iL < digiMatch->GetNofLinks(); iL++) {  // loop over digis
+              int idx               = (digiMatch->GetLink(iL)).GetIndex();
+              const CbmTofDigi* pDx = &(fTofCalDigiVec->at(idx));
+              LOG(info) << Form(" Digi %d, idx %d, TSRCS %d%d%d%02d%d ", iL, idx, (int) pDx->GetType(),
+                                (int) pDx->GetSm(), (int) pDx->GetRpc(), (int) pDx->GetChannel(), (int) pDx->GetSide());
+            }
+
+            for (Int_t idx = 0; idx < (int) fTofCalDigiVec->size(); idx++) {  // loop over digis
+              const CbmTofDigi* pDx = &(fTofCalDigiVec->at(idx));
+              LOG(info) << Form(" AllDigi %d, TSRCS %d%d%d%02d%d ", idx, (int) pDx->GetType(), (int) pDx->GetSm(),
+                                (int) pDx->GetRpc(), (int) pDx->GetChannel(), (int) pDx->GetSide());
+            }
+
+            LOG(fatal) << " fhRpcCluTot:  Digi 0 " << iDigInd0 << ": Ch " << pDig0->GetChannel() << ", Side "
+                       << pDig0->GetSide() << ", StripSide " << (Double_t) iCh * 2. + pDig0->GetSide() << " Digi 1 "
+                       << iDigInd1 << ": Ch " << pDig1->GetChannel() << ", Side " << pDig1->GetSide() << ", StripSide "
+                       << (Double_t) iCh * 2. + pDig1->GetSide() << ", Tot0 " << pDig0->GetTot() << ", Tot1 "
+                       << pDig1->GetTot();
+          }  // end of type mismatch condition
+          fhCalTot[iDetIndx]->Fill(pDig0->GetChannel() * 2. + pDig0->GetSide(), pDig0->GetTot());
+          fhCalTot[iDetIndx]->Fill(pDig1->GetChannel() * 2. + pDig1->GetSide(), pDig1->GetTot());
+          if (digiMatch->GetNofLinks() > 2) {
+            double dTotStrip = pDig0->GetTot() + pDig1->GetTot();
+            dTotSum += dTotStrip;
+            double dYdigi = 0.5 * (pDig0->GetTime() - pDig1->GetTime()) * fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc);
+            if (pDig0->GetSide() == 1) {
+              dYSum += (pDig0->GetTime() - pDig1->GetTime()) * dTotStrip;  // weighted mean
+            }
+            else {
+              dYSum += (pDig1->GetTime() - pDig0->GetTime()) * dTotStrip;
+              dYdigi *= -1;
+            }
+            fhCalXYTot[iDetIndx]->Fill(pDig0->GetChannel() * 2. + pDig0->GetSide(), dYdigi, pDig0->GetTot());
+            fhCalXYTot[iDetIndx]->Fill(pDig1->GetChannel() * 2. + pDig1->GetSide(), dYdigi, pDig1->GetTot());
+          }
+        }
+      }  // first loop over digis
+      if (digiMatch->GetNofLinks() > 2) {
+        double dYAv  = dYSum / dTotSum;
+        double dYLoc = 0.;
+        for (Int_t iLink = 0; iLink < digiMatch->GetNofLinks(); iLink += 2) {  // second loop over digis
+          CbmLink L0      = digiMatch->GetLink(iLink);
+          UInt_t iDigInd0 = L0.GetIndex();
+          UInt_t iDigInd1 = (digiMatch->GetLink(iLink + 1)).GetIndex();
+          if (iDigInd0 < fTofCalDigiVec->size() && iDigInd1 < fTofCalDigiVec->size()) {
+            const CbmTofDigi* pDig0 = &(fTofCalDigiVec->at(iDigInd0));
+            const CbmTofDigi* pDig1 = &(fTofCalDigiVec->at(iDigInd1));
+            double dTotStrip        = pDig0->GetTot() + pDig1->GetTot();
+            double dTotWeight       = 1 - dTotStrip / dTotSum;
+            //dTotWeight    *= 0.5;
+            dTotWeight     = 1.;
+            double dDeltaT = 0.5 * (pDig0->GetTime() + pDig1->GetTime()) - pHit->GetTime();
+            //if(NULL != fTofFindTracks) dDeltaT += fTofFindTracks->GetTOff(iDetId); //obsolete ??
+            fhCalDelTOff[iDetIndx]->Fill(pDig0->GetChannel(), dDeltaT * dTotWeight);
+            //  TBD: position deviation in counter reference frame
+            Double_t dDelPos = 0.5 * (pDig0->GetTime() - pDig1->GetTime()) * fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc);
+            if (0 == pDig0->GetSide()) dDelPos *= -1.;
+            fhCalDelPos[iDetIndx]->Fill(pDig0->GetChannel(), (dDelPos - fTofClusterizer->GetLocalY(pHit)));
+
+            int iCh0   = pDig0->GetChannel();
+            int iSide0 = pDig0->GetSide();
+            int iCh1   = pDig1->GetChannel();
+            int iSide1 = pDig1->GetSide();
+            if (iCh0 != iCh1) LOG(fatal) << "Inconsistent TofHit - FixIt";
+            fhCalWalk[iDetIndx][iCh0][iSide0]->Fill(pDig0->GetTot(), dDeltaT * dTotWeight);
+            fhCalWalk[iDetIndx][iCh1][iSide1]->Fill(pDig1->GetTot(), dDeltaT * dTotWeight);
+            dMeanTimeSquared += dDeltaT * dDeltaT;
+            if (pDig0->GetSide() == 1) { dYLoc = pDig0->GetTime() - pDig1->GetTime(); }
+            else {
+              dYLoc = pDig1->GetTime() - pDig0->GetTime();
+            }
+            dYLoc *= 0.5;
+            fhCalTotYWalk[iDetIndx][iCh0][iSide0]->Fill(pDig0->GetTot(),
+                                                        dYLoc * fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc), dDeltaT);
+            fhCalTotYWalk[iDetIndx][iCh1][iSide1]->Fill(pDig1->GetTot(),
+                                                        dYLoc * fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc), dDeltaT);
+
+            fhCalTotYTOff[iDetIndx][iCh0][iSide0]->Fill(
+              pDig0->GetTot(), dYLoc * fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc), pHit->GetTime() - dTAv - dTexp);
+            fhCalTotYTOff[iDetIndx][iCh1][iSide1]->Fill(
+              pDig1->GetTot(), dYLoc * fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc), pHit->GetTime() - dTAv - dTexp);
+
+            Double_t dDeltaDT = dYLoc - dYAv;
+            fhCalPos[iDetIndx]->Fill(iCh0, dDeltaDT * fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc));
+
+            fhCalDtWalk[iDetIndx][iCh0][iSide0]->Fill(pDig0->GetTot(), (2. * pDig0->GetSide() - 1) * dDeltaDT);
+            fhCalDtWalk[iDetIndx][iCh1][iSide1]->Fill(pDig1->GetTot(), (2. * pDig1->GetSide() - 1) * dDeltaDT);
+          }
+        }  // second loop over digis
+      }    // if (digiMatch->GetNofLinks()>2)
+
+      fhCalCluSize[iDetIndx]->Fill((Double_t) iCh, digiMatch->GetNofLinks() / 2);
+      if (digiMatch->GetNofLinks() > 2) {
+        double dVar  = dMeanTimeSquared / (digiMatch->GetNofLinks() / 2 - 1);
+        double dTrms = TMath::Sqrt(dVar);
+        fhCalCluTrms[iDetIndx]->Fill((Double_t) iCh, dTrms);
+      }
+    }  // iOpt<100
+  }
+  return;
+}  // -- FillHitCalHist
+
+
 static Int_t NevtT = 0;
 void CbmTofCalibrator::FillCalHist(CbmTofTracklet* pTrk, Int_t iOpt, CbmEvent* tEvent)
 {
   NevtT++;
-  if (NULL == fTofCalDigiVec) LOG(fatal) << "No access to TofCalDigis!";
+  if (NULL == fTofCalDigiVec) LOG(fatal) << "No access to TofCalDigis! Opt " << iOpt << ", Event" << tEvent;
   // fill deviation histograms on walk level
+  /*
+  LOG(info)<<"Calibrator " << NevtT <<": Tt " << pTrk->GetTt() 
+           <<", R0: " << pTrk->GetR0() <<", bB " 
+           <<  pTrk->ContainsAddr(CbmTofAddress::GetUniqueAddress(0, 0, 0, 0, 5));
+  */
   if (pTrk->GetTt() < 0) return;  // take tracks with positive velocity only
+  if (pTrk->GetNofHits() < fTofFindTracks->GetNReqStations()) return;
+
+  fhCalDX0->Fill(pTrk->GetFitX(0.));
+  fhCalDY0->Fill(pTrk->GetFitY(0.));
+
   if (fbBeam && !pTrk->ContainsAddr(CbmTofAddress::GetUniqueAddress(0, 0, 0, 0, 5)))
     return;  // request beam counter hit for calibration
 
@@ -387,9 +769,8 @@ void CbmTofCalibrator::FillCalHist(CbmTofTracklet* pTrk, Int_t iOpt, CbmEvent* t
     fhCalR0->Fill(pTrk->GetR0());
     if (pTrk->GetR0() > fdR0Lim) return;
   }
-  fhCalDX0->Fill(pTrk->GetFitX(0.));
-  fhCalDY0->Fill(pTrk->GetFitY(0.));
-  if (iOpt > 70) HstDoublets(pTrk);  // Fill Doublets histograms
+
+  //if (iOpt > 70) HstDoublets(pTrk);  // Fill Doublets histograms
 
   //double dEvtStart=fEvtHeader->GetEventTime();
   for (Int_t iHit = 0; iHit < pTrk->GetNofHits(); iHit++) {
@@ -410,24 +791,37 @@ void CbmTofCalibrator::FillCalHist(CbmTofTracklet* pTrk, Int_t iOpt, CbmEvent* t
       LOG(error) << "Invalid Channel Pointer for ChId " << Form(" 0x%08x ", iChId) << ", Ch " << iCh;
       continue;
     }
-    gGeoManager->FindNode(fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ());
+    //gGeoManager->FindNode(fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ());
     Double_t hitpos[3];
     hitpos[0] = pHit->GetX();
     hitpos[1] = pHit->GetY();
     hitpos[2] = pHit->GetZ();
     Double_t hlocal_p[3];
     //TGeoNode* cNode=
-    gGeoManager->GetCurrentNode();
-    gGeoManager->MasterToLocal(hitpos, hlocal_p);
+    //gGeoManager->GetCurrentNode();
+    //gGeoManager->MasterToLocal(hitpos, hlocal_p);
+    fTofClusterizer->MasterToLocal(iChId, hitpos, hlocal_p);
+
     hitpos[0] = pTrk->GetFitX(pHit->GetZ());
     hitpos[1] = pTrk->GetFitY(pHit->GetZ());
     Double_t hlocal_f[3];
-    gGeoManager->MasterToLocal(hitpos, hlocal_f);
-    fhCalPosition[iDetIndx]->Fill((Double_t) iCh,
-                                  hlocal_p[1]);                           // transformed into LRF
-    fhCalPos[iDetIndx]->Fill((Double_t) iCh, hlocal_p[1] - hlocal_f[1]);  // transformed into LRF
-    fhCalTOff[iDetIndx]->Fill((Double_t) iCh,
-                              pHit->GetTime() - pTrk->GetFitT(pHit->GetZ()));  // residuals transformed into LRF
+    //gGeoManager->MasterToLocal(hitpos, hlocal_f);
+    fTofClusterizer->MasterToLocal(iChId, hitpos, hlocal_f);
+    if (true) {  //0==fDigiBdfPar->GetChanOrient(iSmType, iRpc)) { // default
+      fhCalPosition[iDetIndx]->Fill((Double_t) iCh, hlocal_p[1]);           // transformed into LRF
+      fhCalPos[iDetIndx]->Fill((Double_t) iCh, hlocal_p[1] - hlocal_f[1]);  // transformed into LRF
+    }
+    else {  // Counters rotated with respect to module axis, strips along x-axis
+      fhCalPosition[iDetIndx]->Fill((Double_t) iCh, hlocal_p[0]);           // transformed into LRF
+      fhCalPos[iDetIndx]->Fill((Double_t) iCh, hlocal_p[0] - hlocal_f[0]);  // transformed into LRF
+    }
+    //if(fTofFindTracks->GetTtTarg()==0.033) pTrk->SetTt(fTofFindTracks->GetTtTarg()); //for calibration mode 1,2,31
+    //double dTexp = pTrk->GetFitT(pHit->GetZ());  // residuals transformed into LRF
+    //double dTexp = fTrackletTools->GetTexpected(pTrk, pHit->GetAddress()&DetMask, pHit, fTofFindTracks->GetTtLight());
+    double dTexp = fTrackletTools->GetTexpected(pTrk, -1, pHit, fTofFindTracks->GetTtLight());
+    fhCalTOff[iDetIndx]->Fill((Double_t) iCh, pHit->GetTime() - dTexp);
+    fhCalXYTOff[iDetIndx]->Fill((Double_t) iCh, hlocal_p[1],
+                                pHit->GetTime() - dTexp);  // residuals transformed into LRF
     //fhCalTOff[iDetIndx]->Fill((Double_t)iCh,fTrackletTools->GetTdif(pTrk, iDetId, pHit));
 
     Int_t iEA  = pTrk->GetTofHitIndex(iHit);
@@ -486,22 +880,25 @@ void CbmTofCalibrator::FillCalHist(CbmTofTracklet* pTrk, Int_t iOpt, CbmEvent* t
         continue;
       }
       if (iCh0 > (Int_t) fhCalWalk[iDetIndx].size()) {
-        LOG(error) << "Invalid Ch0 " << iCh0;
+        LOG(error) << "Invalid Ch0 " << iCh0 << " for detIndx" << iDetIndx << ", size " << fhCalWalk[iDetIndx].size();
         continue;
       }
       if (iSide0 > (Int_t) fhCalWalk[iDetIndx][iCh0].size()) {
-        LOG(error) << "Invalid Side0 " << iSide0;
+        LOG(error) << "Invalid Side0 " << iSide0 << " for "
+                   << " for detIndx" << iDetIndx << ", size " << fhCalWalk[iDetIndx][iCh0].size();
         continue;
       }
 
       Int_t iCh1   = tDigi1->GetChannel();
       Int_t iSide1 = tDigi1->GetSide();
       if (iCh1 > (Int_t) fhCalWalk[iDetIndx].size()) {
-        LOG(error) << "Invalid Ch1 " << iCh1;
+        LOG(error) << "Invalid Ch1 " << iCh1 << " for "
+                   << " for detIndx" << iDetIndx;
         continue;
       }
       if (iSide1 > (Int_t) fhCalWalk[iDetIndx][iCh1].size()) {
-        LOG(error) << "Invalid Side1 " << iSide1;
+        LOG(error) << "Invalid Side1 " << iSide1 << " for "
+                   << " for detIndx" << iDetIndx;
         continue;
       }
 
@@ -519,7 +916,7 @@ void CbmTofCalibrator::FillCalHist(CbmTofTracklet* pTrk, Int_t iOpt, CbmEvent* t
         LOG(warn) << "CMPY for TSRC " << iSmType << iSm << iRpc << iCh0 << ": " << hlocal_f[1] << ", " << hlocal_p[1]
                   << ", " << hlocal_d[1] << ", TOT: " << tDigi0->GetTot() << " " << tDigi1->GetTot();
       }
-      Int_t iWalkMode = (iOpt - iOpt % 100) / 100;
+      Int_t iWalkMode = 0;  //(iOpt - iOpt % 100) / 100;
       switch (iWalkMode) {
         case 1:
           fhCalWalk[iDetIndx][iCh0][iSide0]->Fill(
@@ -549,14 +946,20 @@ void CbmTofCalibrator::FillCalHist(CbmTofTracklet* pTrk, Int_t iOpt, CbmEvent* t
           break;
 
         case 0: {
-          Double_t dDeltaT = 0.5 * (tDigi0->GetTime() + tDigi1->GetTime()) + fTofFindTracks->GetTOff(iDetId)
-                             - pTrk->GetFitT(pHit->GetZ());
+          Double_t dDeltaT =
+            0.5 * (tDigi0->GetTime() + tDigi1->GetTime()) + fTofFindTracks->GetTOff(iDetId) - pHit->GetTime();
+
+          fhCalWalkAv[iDetIndx]->Fill(tDigi0->GetTot(), dDeltaT);
+          fhCalWalkAv[iDetIndx]->Fill(tDigi1->GetTot(), dDeltaT);
           fhCalWalk[iDetIndx][iCh0][iSide0]->Fill(tDigi0->GetTot(), dDeltaT);
           fhCalWalk[iDetIndx][iCh1][iSide1]->Fill(tDigi1->GetTot(), dDeltaT);
           if (iSmType == 5 || iSmType == 8) {  // symmetrize for Pad counters
             fhCalWalk[iDetIndx][iCh0][iSide0]->Fill(tDigi1->GetTot(), dDeltaT);
             fhCalWalk[iDetIndx][iCh1][iSide1]->Fill(tDigi0->GetTot(), dDeltaT);
           }
+          Double_t dDeltaDT = (hlocal_d[1] - hlocal_p[1]) / fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc);
+          fhCalDtWalk[iDetIndx][iCh0][iSide0]->Fill(tDigi0->GetTot(), (2. * tDigi0->GetSide() - 1) * dDeltaDT);
+          fhCalDtWalk[iDetIndx][iCh1][iSide1]->Fill(tDigi1->GetTot(), (2. * tDigi1->GetSide() - 1) * dDeltaDT);
         } break;
       }
     }
@@ -630,126 +1033,779 @@ Bool_t CbmTofCalibrator::UpdateCalHist(Int_t iOpt)
 
       switch (iOpt0) {
         case 0:  // none
-          break;
-        case 1:  // update channel mean
         {
-          LOG(info) << "Update Offsets for TSR " << iSmType << iSm << iRpc;
+          double* dRes;
+          switch (iOpt1) {
+            case 10: {
+              LOG(info) << "Equalize velocities with const threshold counterwise for " << fhCorTOff[iDetIndx]->GetName()
+                        << ", MeanTOff " << fhCorTOff[iDetIndx]->GetMean();
+              TString hname2 = Form("cal_SmT%d_sm%03d_rpc%03d_TOff", iSmType, iSm, iRpc);
+              //TH2* h2 = (TH2*) gROOT->FindObjectAny(hname2);
+              TH2* h2  = fhCalTOff[iDetIndx];
+              TH2* h2W = fhCalTofOff[iDetIndx];
+              if (NULL == h2) {
+                LOG(warn) << "Calibration data not available from " << hname2;
+                continue;
+              }
+
+              double dResIni[1] = {0.};
+              dRes              = &dResIni[0];
+              Int_t NStrips     = h2->GetNbinsX();
+              TH1* h2Wy         = h2W->ProjectionY(Form("%s_py", h2W->GetName()), 1, NStrips);
+              TH1* h2y          = h2->ProjectionY(Form("%s_py", h2->GetName()), 1, NStrips);
+              double dEdge      = 0.;
+              if (iSmType != 5) {
+                dRes  = find_tofedge((const char*) (h2Wy->GetName()), fTofClusterizer->GetEdgeThr(),
+                                    fTofClusterizer->GetEdgeLen());
+                dEdge = dRes[0];
+              }
+              else {
+                dEdge = h2Wy->GetBinCenter(h2Wy->GetMaximumBin());
+              }
+
+              /*
+              LOG(info) << h2Wy->GetName() << ": Coarse Max at " << h2Wy->GetMaximumBin()
+                        << ", " << dEdge << ", " << h2y->GetBinCenter(1)
+                        << ", " << h2y->GetBinCenter(h2y->GetNbinsX());
+              */
+              if (dEdge < h2y->GetBinCenter(1) || dEdge > h2y->GetBinCenter(h2y->GetNbinsX())) {
+                dRes[0] = dEdge;  // - fTofClusterizer->GetEdgeTbias();
+                LOG(info) << h2Wy->GetName() << ": Coarse TOff shift by " << dRes[0];
+              }
+              else {
+                if (iSmType != 5) {
+                  dRes = find_tofedge((const char*) (h2y->GetName()), fTofClusterizer->GetEdgeThr(),
+                                      fTofClusterizer->GetEdgeLen());
+                  if (TMath::Abs(dRes[0]) < 0.5) {
+                    //LOG(info) << "Now fit edge above noise, dT " << dRes[0] <<", T "<< iSmType;
+                    double dTfind = dRes[0];
+                    double dTmax  = dTfind + fTofClusterizer->GetEdgeFrange();
+                    dRes          = fit_tofedge((const char*) (h2y->GetName()), dTmax, fTofClusterizer->GetEdgeThr());
+                    if (isnan(dRes[0])) dRes[0] = dTfind;
+                  }
+                }
+              }
+              //LOG(info) << h2y->GetName() << ": shift TOff by " << dRes[0];
+              fhCalChannelDt->Fill(dRes[0]);
+              for (Int_t i = 0; i < NStrips; i++) {
+                fhCorTOff[iDetIndx]->SetBinContent(i + 1, fhCorTOff[iDetIndx]->GetBinContent(i + 1) + dRes[0]);
+              }
+            } break;
+
+            case 15:
+            case 12:
+            case 11: {
+              LOG(info) << "Equalize velocities with chi2 deviations for " << fhCorTOff[iDetIndx]->GetName();
+              TString hname2 = Form("cal_SmT%d_sm%03d_rpc%03d_TOff", iSmType, iSm, iRpc);
+
+              double dTRefSum    = 0.;
+              double dRefNormSum = 0.;
+              double dNorm       = 0.;
+
+              TH2* h2W = fhCalTofOff[iDetIndx];
+
+              if (h2W->GetEntries() < MINCTS) continue;
+
+              TH2* h2       = fhCalTOff[iDetIndx];
+              Int_t NStrips = h2->GetNbinsX();
+              TH1* h2yAv;
+              double dResIni[1] = {0.};
+              dRes              = &dResIni[0];
+
+              TH1* h2Wy    = h2W->ProjectionY(Form("%s_py", h2W->GetName()), 1, NStrips);
+              h2yAv        = h2->ProjectionY(Form("%s_py", h2->GetName()), 1, NStrips);
+              double dEdge = 0.;
+
+              double dMean = TruncatedMeanY(h2W);  //h2Wy->GetMean();
+              if (iSmType == 5) {
+                dEdge = h2Wy->GetBinCenter(h2Wy->GetMaximumBin());
+                dNorm = h2Wy->GetBinContent(h2Wy->GetMaximumBin());
+              }
+              else {
+                dRes  = find_tofedge((const char*) (h2Wy->GetName()), fTofClusterizer->GetEdgeThr(),
+                                    fTofClusterizer->GetEdgeLen());
+                dEdge = dRes[0];
+                if ((dMean - dEdge) > 10.) {  //FIXME: constant in code
+                  LOG(warn) << h2Wy->GetName() << ": wrong edge detected " << dEdge << ", Mean " << dMean;
+                  dEdge = dMean;
+                }
+              }
+              /*
+              LOG(info) << h2Wy->GetName() << ": Coarse shift at " << h2Wy->GetMaximumBin() 
+                        << ", Edge " << dEdge   
+                        << ", " << h2yAv->GetBinCenter(1)
+                        << ", " << h2yAv->GetBinCenter(h2yAv->GetNbinsX());
+              */
+              if (dEdge < h2yAv->GetBinCenter(1) || dEdge > h2yAv->GetBinCenter(h2yAv->GetNbinsX())) {
+                dRes[0] = dEdge;  // - fTofClusterizer->GetEdgeTbias();
+                //LOG(info) << h2Wy->GetName() << ": Coarse TOff shift by " << dRes[0];
+              }
+              else {
+                if (iSmType != 5) {
+                  dRes = find_tofedge((const char*) (h2yAv->GetName()), fTofClusterizer->GetEdgeThr(),
+                                      fTofClusterizer->GetEdgeLen());
+                  if (TMath::Abs(dRes[0]) < dValidEdge) {
+                    double dTfind = dRes[0];
+                    double dTmax  = dTfind + fTofClusterizer->GetEdgeFrange();
+                    dRes          = fit_tofedge((const char*) (h2yAv->GetName()), dTmax, fTofClusterizer->GetEdgeThr());
+                    if (isnan(dRes[0])) dRes[0] = dTfind;
+                    LOG(info) << h2yAv->GetName() << ": fitted AvEdge up to " << dTmax << ", Res " << dRes[0]
+                              << ", FindE " << dTfind;
+                  }
+                }
+              }
+
+              if (iSmType != 5) {
+                fhCalCounterDt->Fill(dRes[0] - fTofClusterizer->GetEdgeTbias());
+                if (TMath::Abs(dRes[0] - fTofClusterizer->GetEdgeTbias()) > -fhCalCounterDt->GetBinCenter(1)) {
+                  LOG(warn) << "Channel ooCR: " << fhCorTOff[iDetIndx]->GetName() << ", " << dRes[0] << ", "
+                            << fTofClusterizer->GetEdgeTbias() << ", " << -fhCalCounterDt->GetBinCenter(1);
+                }
+              }
+              else {
+                fhCalCounterDt->Fill(dEdge);
+              }
+
+              const double dResAv    = dRes[0];
+              const int nValues      = MaxShift * 2 + 1;
+              const double dRangeFac = 1.;
+              double chi2Shift[NStrips][nValues];
+              double chi2Minimum[NStrips];
+              double chi2MinShift[NStrips];
+              double chi2LowMinNeighbor[NStrips];
+              double chi2LowMinNeighborShift[NStrips];
+              for (Int_t i = 0; i < NStrips; i++) {
+                double dTminShift = 0.;
+                double dEdgei     = 0.;
+                double dMeani     = 0.;
+                TH1* h2y          = h2->ProjectionY(Form("%s_py%d", h2->GetName(), i), i + 1, i + 1);
+                if (h2y->GetEntries() < MINCTS) continue;
+                LOG(info) << h2y->GetName() << ": inspect with iOpt1 = " << iOpt1;
+                if (kTRUE) {
+                  if (iOpt1 == 11 || iOpt1 == 15) {
+                    //check peak position
+                    TH1* h2Wyi = h2W->ProjectionY(Form("%s_py%d", h2W->GetName(), i), i + 1, i + 1);
+                    if (iSmType == 5) {
+                      dEdgei = h2Wy->GetBinCenter(h2Wy->GetMaximumBin());
+                      dNorm  = h2Wy->GetBinContent(h2Wy->GetMaximumBin());
+                    }
+                    else {
+                      dRes   = find_tofedge((const char*) (h2Wyi->GetName()), fTofClusterizer->GetEdgeThr(),
+                                          fTofClusterizer->GetEdgeLen());
+                      dEdgei = dRes[0];
+                    }
+
+                    if (dEdgei < dRangeFac * h2y->GetBinCenter(1)
+                        || dEdgei > dRangeFac * h2y->GetBinCenter(h2y->GetNbinsX())) {
+                      dMeani = h2Wyi->GetMean();
+                      LOG(info) << h2Wyi->GetName() << " ooR: " << dRes[0] << ", E " << dEdgei << ", Av " << dResAv
+                                << ", Meani " << dMeani << ", MeanY " << dMean;
+                      if ((dMeani - dEdgei) > 10.) {  //FIXME: constant in code
+                        LOG(warn) << h2Wyi->GetName() << ": invalid edge detected " << dEdgei << ", Mean " << dMeani;
+                        dRes[0] = dMeani - dMean;
+                      }
+                      //dRes[0]=dEdgei
+                    }
+                    else {
+                      if (iSmType != 5) {
+                        dRes = find_tofedge((const char*) (h2y->GetName()), fTofClusterizer->GetEdgeThr(),
+                                            fTofClusterizer->GetEdgeLen());
+                        LOG(info) << h2y->GetName() << " CheckValidEdge: " << dRes[0] << ", " << dValidEdge;
+                        if (TMath::Abs(dRes[0]) < dValidEdge) {
+                          switch (iOpt1) {
+                            case 11: {
+                              double dTfind = dRes[0];
+                              double dTmax  = dTfind + fTofClusterizer->GetEdgeFrange();
+                              dRes = fit_tofedge((const char*) (h2y->GetName()), dTmax, fTofClusterizer->GetEdgeThr());
+                              if (isnan(dRes[0])) dRes[0] = dTfind;
+                              LOG(info) << h2y->GetName() << ": fit edge up to " << dTmax << ", Res " << dRes[0]
+                                        << ", FindE " << dTfind;
+                            } break;
+                            case 15:
+                              chi2Minimum[i]        = 1.E6;
+                              chi2LowMinNeighbor[i] = 1.E6;
+                              int idx               = 0;
+                              for (int j = -MaxShift; j < MaxShift + 1; j++) {
+                                chi2Shift[i][idx] = CalcChi2(h2yAv, h2y, j);
+                                if (chi2Shift[i][idx] < chi2Minimum[i]) {
+                                  chi2LowMinNeighbor[i]      = chi2Minimum[i];
+                                  chi2LowMinNeighborShift[i] = chi2MinShift[i];
+                                  chi2Minimum[i]             = chi2Shift[i][idx];
+                                  chi2MinShift[i]            = j * h2y->GetBinWidth(1);
+                                }
+                                else {
+                                  if (chi2Shift[i][idx] < chi2LowMinNeighbor[i]) {
+                                    chi2LowMinNeighbor[i]      = chi2Shift[i][idx];
+                                    chi2LowMinNeighborShift[i] = j * h2y->GetBinWidth(1);
+                                  }
+                                }
+                                idx++;
+                              }
+                              double chi2sum = chi2Minimum[i] + chi2LowMinNeighbor[i];
+                              dTminShift     = (chi2MinShift[i] * (chi2sum - chi2Minimum[i])
+                                            + chi2LowMinNeighborShift[i] * (chi2sum - chi2LowMinNeighbor[i]))
+                                           / chi2sum;
+                              //dTminShift=chi2MinShift[i];   // take Min only, for debugging
+                              LOG(info) << h2y->GetName() << ": Chi2 shift " << dTminShift << ", Res " << dRes[0]
+                                        << ", ResAv " << dResAv;
+                              dRes[0] = dResAv;
+                              break;
+                          }
+                        }
+                        else {
+                          LOG(info) << h2y->GetName() << ": stick to coarse offset " << dEdgei << ", Res " << dRes[0];
+                          dRes[0] = dEdgei;  // use offset from wide histo
+                        }
+                      }
+                      else {  // beam counter
+                        dEdgei = h2y->GetBinCenter(h2y->GetMaximumBin());
+                        dNorm  = h2y->GetBinContent(h2y->GetMaximumBin());
+                      }
+
+                      //LOG(info) << h2Wyi->GetName() << " TminShift: " << dTminShift;
+                    }
+                  }
+                }
+                if (iSmType == 5) {
+                  LOG(info) << "Update StartCounterCalib " << i << ": " << dRes[0] << ", " << dBeamTOff << ", "
+                            << dTminShift << ", " << dEdgei << ", N " << dNorm;
+                  dRes[0] = -dEdgei;
+                }
+                else {
+                  dTminShift -= fTofClusterizer->GetEdgeTbias();  // shift to physical scale
+                }
+                fhCalChannelDt->Fill(dRes[0] + dTminShift);
+                if (TMath::Abs(dRes[0] + dTminShift) > -fhCalChannelDt->GetBinCenter(1)) {
+                  LOG(warn) << "Channel ooHR: " << h2Wy->GetName() << i << ", " << dRes[0] << ", " << dTminShift;
+                }
+                double dVal = fhCorTOff[iDetIndx]->GetBinContent(i + 1);
+                if (isnan(dVal)) fhCorTOff[iDetIndx]->SetBinContent(i + 1, 0.);  // fix NANs
+
+                LOG(info) << h2Wy->GetName() << i << " CorTOff: " << dRes[0] << ", " << dResAv << ", " << dTminShift
+                          << ", " << fhCorTOff[iDetIndx]->GetBinContent(i + 1) << " -> "
+                          << fhCorTOff[iDetIndx]->GetBinContent(i + 1) + dRes[0] + dTminShift;
+
+                fhCorTOff[iDetIndx]->SetBinContent(i + 1,
+                                                   (fhCorTOff[iDetIndx]->GetBinContent(i + 1) + dRes[0] + dTminShift));
+                if (iSmType == 5) {
+                  dTRefSum += fhCorTOff[iDetIndx]->GetBinContent(i + 1) * dNorm;
+                  dRefNormSum += dNorm;
+                }
+                //LOG(info)<<fhCorTOff[iDetIndx]->GetName() << ": new TOff " << fhCorTOff[iDetIndx]->GetBinContent(i + 1);
+              }                    //for (Int_t i = 0; i < NStrips; i++)
+              if (iSmType == 5) {  // avoid runaway
+                double dTRefAv = dTRefSum / dRefNormSum;
+                LOG(info) << "Shift average ref time to 0: " << dTRefAv;
+                for (Int_t i = 0; i < NStrips; i++) {
+                  fhCorTOff[iDetIndx]->SetBinContent(i + 1, (fhCorTOff[iDetIndx]->GetBinContent(i + 1) - dTRefAv));
+                }
+              }
+            } break;
+
+            case 14:
+            case 13: {
+              LOG(info) << "TofCalibrator: skip TOff, calibrate hit positions, check YBox, Opt = " << iOpt;
+            } break;
+            case 16: {
+              LOG(info) << "TofCalibrator: determine counter time offsets with cosmics, Opt = " << iOpt;
+              TH2* h2  = fhCalTOff[iDetIndx];
+              TH2* h2W = fhCalTofOff[iDetIndx];
+              if (NULL == h2) {
+                LOG(warn) << "Calibration data not available for detx " << iDetIndx;
+                continue;
+              }
+              Int_t NStrips = h2->GetNbinsX();
+              TH1* h2Wy     = h2W->ProjectionY(Form("%s_py", h2W->GetName()), 1, NStrips);
+              TH1* h2y      = h2->ProjectionY(Form("%s_py", h2->GetName()), 1, NStrips);
+
+              Double_t dCtsWy = h2Wy->GetEntries();
+              Double_t dDt    = 0;
+              if (dCtsWy > MINCTS) {
+                double dFMean      = h2Wy->GetBinCenter(h2Wy->GetMaximumBin());
+                double dFLim       = 0.5;  // CAUTION, fixed numeric value
+                double dBinSize    = h2Wy->GetBinWidth(1);
+                dFLim              = TMath::Max(dFLim, 5. * dBinSize);
+                TFitResultPtr fRes = h2Wy->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
+                if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
+                  dDt = fRes->Parameter(1);
+                  if (TMath::Abs(dDt) < 0.9 * h2y->GetXaxis()->GetXmax()) {
+                    dFMean   = h2y->GetBinCenter(h2y->GetMaximumBin());
+                    dFLim    = 0.5;  // CAUTION, fixed numeric value
+                    dBinSize = h2y->GetBinWidth(1);
+                    dFLim    = TMath::Max(dFLim, 5. * dBinSize);
+                    fRes     = h2y->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
+                    if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
+                      dDt = fRes->Parameter(1);
+                    }
+                  }
+                  fhCalCounterDt->Fill(dDt);
+                }
+                LOG(info) << "Update cor hist " << fhCorTOff[iDetIndx]->GetName() << " by " << dDt << ", " << dBeamTOff;
+                for (int iCh = 0; iCh < fhCorTOff[iDetIndx]->GetNbinsX(); iCh++) {
+                  fhCalChannelDt->Fill(dDt);
+                  fhCorTOff[iDetIndx]->SetBinContent(iCh + 1, fhCorTOff[iDetIndx]->GetBinContent(iCh + 1) + dDt);
+                }
+              }
+            } break;
+
+            case 17: {
+              LOG(info) << "TofCalibrator: determine channel time offsets with cosmics, Opt = " << iOpt;
+              TH2* h2  = fhCalTOff[iDetIndx];
+              TH2* h2W = fhCalTofOff[iDetIndx];
+              if (NULL == h2) {
+                LOG(warn) << "Calibration data not available for detx " << iDetIndx;
+                continue;
+              }
+              Int_t NStrips = h2->GetNbinsX();
+              for (int i = 0; i < NStrips; i++) {
+                TH1* h2Wy = h2W->ProjectionY(Form("%s_py_%02d", h2W->GetName(), i), i + 1, i + 1);
+                TH1* h2y  = h2->ProjectionY(Form("%s_py_%02d", h2->GetName(), i), i + 1, i + 1);
+
+                Double_t dCtsWy = h2Wy->GetEntries();
+                Double_t dDt    = 0;
+                if (dCtsWy > MINCTS) {
+                  double dFMean      = h2Wy->GetBinCenter(h2Wy->GetMaximumBin());
+                  double dFLim       = 0.5;  // CAUTION, fixed numeric value
+                  double dBinSize    = h2Wy->GetBinWidth(1);
+                  dFLim              = TMath::Max(dFLim, 5. * dBinSize);
+                  TFitResultPtr fRes = h2Wy->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
+                  Int_t iFitStatus   = fRes;
+                  //LOG(warn)<<h2Wy->GetName() << ":  "<< iFitStatus << " " <<fRes;
+                  if (iFitStatus != -1)
+                    if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
+                      dDt = fRes->Parameter(1);
+                      //LOG(warn)<<h2Wy->GetName() << " Dt "<< dDt;
+                      if (h2y->GetEntries() > MINCTS)
+                        if (TMath::Abs(dDt) < 0.9 * h2y->GetXaxis()->GetXmax()) {
+                          dFMean   = h2y->GetBinCenter(h2y->GetMaximumBin());
+                          dFLim    = 0.5;  // CAUTION, fixed numeric value
+                          dBinSize = h2y->GetBinWidth(1);
+                          dFLim    = TMath::Max(dFLim, 5. * dBinSize);
+                          fRes     = h2y->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
+                          if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
+                            dDt = fRes->Parameter(1);
+                          }
+                        }
+                      fhCalChannelDt->Fill(dDt);
+                      fhCorTOff[iDetIndx]->SetBinContent(i + 1, fhCorTOff[iDetIndx]->GetBinContent(i + 1) + dDt);
+                    }
+                }
+                else {
+                  LOG(warn) << "Too few counts in " << h2Wy->GetName() << ": " << dCtsWy;
+                }
+              }
+            } break;
+
+            case 18: {
+              LOG(info) << "TofCalibrator: determine channel walks with cosmics, Opt = " << iOpt << " for TSR "
+                        << iSmType << iSm << iRpc;
+              //if (iSmType == 5) continue;  // no walk correction for beam counter up to now
+              const Double_t MinCounts = 10.;
+              Int_t iNbCh              = fDigiBdfPar->GetNbChan(iSmType, iRpc);
+              for (Int_t iCh = 0; iCh < iNbCh; iCh++) {
+                TH1* hCY = fhCalPos[iDetIndx]->ProjectionY(Form("%s_py_%d", fhCalPos[iDetIndx]->GetName(), iCh),
+                                                           iCh + 1, iCh + 1);
+                if (hCY->GetEntries() > 1)
+                  fhCalChannelDy->Fill(hCY->GetRMS() / fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc));
+                //LOG(info) << "Get walk histo pointer for TSRCS " << iSmType<<iSm<<iRpc<<iCh<<iSide;
+                TProfile* hpW0 = fhCalWalk[iDetIndx][iCh][0]->ProfileX();     // mean deviation
+                TH1* hCW0      = fhCalWalk[iDetIndx][iCh][0]->ProjectionX();  // contributing counts
+                TProfile* hpW1 = fhCalWalk[iDetIndx][iCh][1]->ProfileX();     // mean deviation
+                TH1* hCW1      = fhCalWalk[iDetIndx][iCh][1]->ProjectionX();  // contributing counts
+                if (hCW0->GetEntries() == 0 || hCW1->GetEntries() == 0) {
+                  //LOG(info) << "No entries in " << hCW0->GetName();
+                  continue;
+                }
+                Double_t dCorT = 0;
+                for (Int_t iBin = 0; iBin < fhCorWalk[iDetIndx][iCh][0]->GetNbinsX(); iBin++) {
+                  Double_t dCts0  = hCW0->GetBinContent(iBin + 1);
+                  Double_t dCts1  = hCW1->GetBinContent(iBin + 1);
+                  Double_t dWOff0 = fhCorWalk[iDetIndx][iCh][0]->GetBinContent(iBin + 1);  // current value
+                  Double_t dWOff1 = fhCorWalk[iDetIndx][iCh][1]->GetBinContent(iBin + 1);  // current value
+                  if (iBin > 0 && dCts0 == 0 && dCts1 == 0) {
+                    fhCorWalk[iDetIndx][iCh][0]->SetBinContent(iBin + 1,
+                                                               fhCorWalk[iDetIndx][iCh][0]->GetBinContent(iBin));
+                    fhCorWalk[iDetIndx][iCh][1]->SetBinContent(iBin + 1,
+                                                               fhCorWalk[iDetIndx][iCh][1]->GetBinContent(iBin));
+                  }
+                  dCorT = 0.;
+                  if (dCts0 > MinCounts && dCts1 > MinCounts) {
+                    dCorT = 0.5 * (hpW0->GetBinContent(iBin + 1) + hpW1->GetBinContent(iBin + 1));
+                    fhCalChannelDt->Fill(dCorT);
+                  }
+                  fhCorWalk[iDetIndx][iCh][0]->SetBinContent(iBin + 1, dWOff0 + dCorT);  //set new value
+                  fhCorWalk[iDetIndx][iCh][1]->SetBinContent(iBin + 1, dWOff1 + dCorT);  //set new value
+                }
+              }
+            } break;
+
+            default:
+              LOG(info) << "TofCalibrator: unknown option " << iOpt;
+              return kTRUE;
+              break;
+          }  // switch iOpt1 end
+
+          // re-adjust positions
+          if (fhCalPosition[iDetIndx]->GetEntries() == 0) continue;
+          double dYShift           = 0;
+          TH1* hCalP               = fhCalPosition[iDetIndx]->ProjectionX();
+          TH1* hCalPos_py          = fhCalPosition[iDetIndx]->ProjectionY();  // full counter
+          dYShift                  = hCalPos_py->GetMean();
+          int iChId                = CbmTofAddress::GetUniqueAddress(iSm, iRpc, 0, 0, iSmType);
+          CbmTofCell* fChannelInfo = fDigiPar->GetCell(iChId);
+          if (NULL == fChannelInfo) LOG(fatal) << Form("invalid ChannelInfo for 0x%08x", iChId);
+          double dLen = fChannelInfo->GetSizey() * fTofClusterizer->GetModifySigvel();
+          fTofClusterizer->fit_ybox(hCalPos_py, dLen);
+          TF1* ff = hCalPos_py->GetFunction("YBox");  // box fit for monitoring signal velocity
+          if (NULL != ff) {
+            LOG(info) << "FRes YBox " << hCalPos_py->GetEntries() << " entries in TSR " << iSmType << iSm << iRpc
+                      << ", chi2 " << ff->GetChisquare() / ff->GetNDF()
+                      << Form(", striplen (%5.2f): %7.2f +/- %5.2f, pos "
+                              "res %5.2f +/- %5.2f at y_cen = %5.2f +/- %5.2f",
+                              dLen * fTofClusterizer->GetModifySigvel(), 2. * ff->GetParameter(1),
+                              2. * ff->GetParError(1), ff->GetParameter(2), ff->GetParError(2), ff->GetParameter(3),
+                              ff->GetParError(3));
+            //dYShift = ff->GetParameter(3); // update common shift by box fit
+            if (iOpt1 == 14) {  // Update signal velocity
+              if (hSvel[iSmType] != NULL) {
+                int iNbRpc    = fDigiBdfPar->GetNbRpc(iSmType);
+                double dSscal = hSvel[iSmType]->GetBinContent(iSm * iNbRpc + iRpc + 1);
+                double dRatio = dLen * fTofClusterizer->GetModifySigvel() / 2. / ff->GetParameter(1);
+                LOG(info) << "Modify SigVel modifier for TSR " << iSmType << iSm << iRpc << ": " << dSscal << ", "
+                          << dRatio << " -> " << dSscal * dRatio;
+                dSscal = dSscal * dRatio;
+                if (dSscal < 0.8) dSscal = 0.8;
+                if (dSscal > 1.2) dSscal = 1.2;
+                hSvel[iSmType]->SetBinContent(iSm * iNbRpc + iRpc + 1,
+                                              dSscal);  // does not work in input file directory
+              }
+            }
+          }
+
+          double dThr = hCalPos_py->GetBinContent(hCalPos_py->GetMaximumBin()) / 10;
+          if (dThr < 3.) dThr = 3.;
+          dRes = fTofClusterizer->find_yedges((const char*) (hCalPos_py->GetName()), dThr, fChannelInfo->GetSizey());
+          if (TMath::Abs(dRes[0] - fChannelInfo->GetSizey()) / fChannelInfo->GetSizey() < 0.1) { dYShift = dRes[1]; }
+
+          if (iOpt1 != 16 && iOpt1 != 12) {
+            for (Int_t iBin = 0; iBin < fhCorPos[iDetIndx]->GetNbinsX(); iBin++) {
+              Double_t dCorP = fhCorPos[iDetIndx]->GetBinContent(iBin + 1);
+              Double_t dCtsP = hCalP->GetBinContent(iBin + 1);
+              if (dCtsP > MINCTS) {
+                TH1* hPos_py = fhCalPosition[iDetIndx]->ProjectionY(
+                  Form("%s_py_%d", fhCalPosition[iDetIndx]->GetName(), iBin), iBin + 1, iBin + 1);
+                dYShift = hPos_py->GetMean();
+                dThr    = hPos_py->GetBinContent(hPos_py->GetMaximumBin()) / 10;
+                if (dThr < 3.) dThr = 3.;
+                dRes = fTofClusterizer->find_yedges((const char*) (hPos_py->GetName()), dThr, fChannelInfo->GetSizey());
+
+                LOG(info) << Form("EdgeY for %s, TSR %d%d%d: DY %5.2f, Len %5.2f, Size %5.2f ", hPos_py->GetName(),
+                                  iSmType, iSm, iRpc, dRes[1], dRes[0],
+                                  fChannelInfo->GetSizey() * fTofClusterizer->GetModifySigvel());
+
+                if (TMath::Abs(dRes[0] - fChannelInfo->GetSizey()) / fChannelInfo->GetSizey() < 0.1) {
+                  dYShift = dRes[1];
+                }
+                else {
+                  dYShift = hPos_py->GetMean();
+                }
+                // apply correction
+                //LOG(info)<<Form("UpdateCalPos TSRC %d%d%d%2d: %6.2f -> %6.2f ",iSmType,iSm,iRpc,iBin,dCorP,dCorP+dYShift);
+                fhCorPos[iDetIndx]->SetBinContent(iBin + 1, dCorP + dYShift);
+                fhCalChannelDy->Fill(dYShift);
+              }
+            }
+          }
+          else {  // no individuak y-corrections
+            for (Int_t iBin = 0; iBin < fhCorPos[iDetIndx]->GetNbinsX(); iBin++) {
+              Double_t dCorP = fhCorPos[iDetIndx]->GetBinContent(iBin + 1);
+              fhCorPos[iDetIndx]->SetBinContent(iBin + 1, dCorP + dYShift);
+              fhCalChannelDy->Fill(dYShift);
+            }
+          }
+        } break;  // case iOpt0=0
 
+        case 1:  // update channel mean
+        {
+          LOG(info) << "Update time offsets for TSR " << iSmType << iSm << iRpc << " with opt1 " << iOpt1;
           TProfile* hpP = fhCalPos[iDetIndx]->ProfileX();
           TProfile* hpT = fhCalTOff[iDetIndx]->ProfileX();
           TH1* hCalP    = fhCalPos[iDetIndx]->ProjectionX();
           TH1* hCalT    = fhCalTOff[iDetIndx]->ProjectionX();
           //fhCorPos[iDetIndx]->Add((TH1 *)hpP,-1.);
           //fhCorTOff[iDetIndx]->Add((TH1*)hpT,-1.);
-          double dTOffMeanShift = 0.;
-          double dNCh           = 0.;
-          for (Int_t iBin = 0; iBin < fhCorTOff[iDetIndx]->GetNbinsX(); iBin++) {
-            Double_t dDt   = hpT->GetBinContent(iBin + 1);
-            Double_t dCorT = fhCorTOff[iDetIndx]->GetBinContent(iBin + 1);
-            Double_t dCtsT = hCalT->GetBinContent(iBin + 1);
-            Double_t dCtsP = hCalP->GetBinContent(iBin + 1);
-            Double_t dDp   = hpP->GetBinContent(iBin + 1);
-            Double_t dCorP = fhCorPos[iDetIndx]->GetBinContent(iBin + 1);
-            LOG(info) << "Cts check for " << fhCalTOff[iDetIndx]->GetName() << ", bin " << iBin << ": " << dCtsT << ", "
-                      << dCtsP << ", " << MINCTS;
-            if (dCtsT > MINCTS && dCtsP > MINCTS) {
-              // Fit Gaussian around peak
-              TH1* hpPy =
-                (TH1*) fhCalPos[iDetIndx]->ProjectionY(Form("PosPy_%d_%d", iDetIndx, iBin), iBin + 1, iBin + 1);
-              Double_t dFMean    = hpPy->GetBinCenter(hpPy->GetMaximumBin());
-              Double_t dFLim     = 0.5;  // CAUTION, fixed numeric value
-              Double_t dBinSize  = hpPy->GetBinWidth(1);
-              dFLim              = TMath::Max(dFLim, 5. * dBinSize);
-              TFitResultPtr fRes = hpPy->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
-              if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
-                dDp = fRes->Parameter(1);  //overwrite mean
-              }
-              TH1* hpTy =
-                (TH1*) fhCalTOff[iDetIndx]->ProjectionY(Form("TOffPy_%d_%d", iDetIndx, iBin), iBin + 1, iBin + 1);
-              dFMean   = hpTy->GetBinCenter(hpTy->GetMaximumBin());
-              dFLim    = 0.5;  // CAUTION, fixed numeric value
-              dBinSize = hpTy->GetBinWidth(1);
+          if (iOpt1 == 3) {  // update counter times from track pulls
+            TH1* hCalTpy     = fhCalTOff[iDetIndx]->ProjectionY();
+            Double_t dCtsTpy = hCalTpy->GetEntries();
+            Double_t dDt     = 0;
+            if (dCtsTpy > MINCTS) {
+              double dFMean      = hCalTpy->GetBinCenter(hCalTpy->GetMaximumBin());
+              double dFLim       = 0.5;  // CAUTION, fixed numeric value
+              double dBinSize    = hCalTpy->GetBinWidth(1);
               dFLim    = TMath::Max(dFLim, 5. * dBinSize);
-              fRes     = hpTy->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
+              TFitResultPtr fRes = hCalTpy->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
               if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
-                dDt = fRes->Parameter(1);  //overwrite mean
-              }
-              // Double_t dDpRes = fRes->Parameter(2);
-              if (iSmType == 5) {  // do not shift beam counter in time
-                fhCorTOff[iDetIndx]->SetBinContent(iBin + 1, dCorT + dDt - dBeamTOff);
-                dTOffMeanShift += dDt - dBeamTOff;
-              }
-              else {
-                fhCorTOff[iDetIndx]->SetBinContent(iBin + 1, dCorT + dDt + dBeamTOff);
-                dTOffMeanShift += dDt + dBeamTOff;
-              }
-              dNCh += 1.;
-              if (iOpt1 > 0) {  // active  y-position correction
-                fhCorPos[iDetIndx]->SetBinContent(iBin + 1, dCorP + dDp);
-              }
-              if (iDetIndx > -1) {
-                LOG(info) << Form("Update %s: bin %02d, Cts: %d, Old %6.3f, dev %6.3f, beam %6.3f, new %6.3f",
-                                  fhCorTOff[iDetIndx]->GetName(), iBin, (Int_t) dCtsT, dCorT, dDt, dBeamTOff,
-                                  dCorT + dDt + dBeamTOff);
+                dDt = fRes->Parameter(1);
+                LOG(info) << "Update cor hist " << fhCorTOff[iDetIndx]->GetName() << " by " << dDt << ", " << dBeamTOff;
+                if (iSmType == 5) {  // do not shift beam counter in time
+                  dDt -= dBeamTOff;
+                }
+                else {
+                  dDt += dBeamTOff;
+                }
+                fhCalCounterDt->Fill(dDt);
+                for (int iCh = 0; iCh < fhCorTOff[iDetIndx]->GetNbinsX(); iCh++) {
+                  fhCalChannelDt->Fill(dDt);
+                  fhCorTOff[iDetIndx]->SetBinContent(iCh + 1, fhCorTOff[iDetIndx]->GetBinContent(iCh + 1) + dDt);
+                }
               }
             }
           }
-          if (dNCh > 0) dTOffMeanShift /= dNCh;
-          LOG(info) << "Apply dTOffMeanShift " << dTOffMeanShift << " to " << fhCorTOff[iDetIndx]->GetName();
-          for (Int_t iBin = 0; iBin < fhCorTOff[iDetIndx]->GetNbinsX(); iBin++) {  //preserve mean offset
-            fhCorTOff[iDetIndx]->SetBinContent(iBin + 1, fhCorTOff[iDetIndx]->GetBinContent(iBin + 1) - dTOffMeanShift);
+          else {
+            double dTOffMeanShift = 0.;
+            double dNCh           = 0.;
+            for (Int_t iBin = 0; iBin < fhCorTOff[iDetIndx]->GetNbinsX(); iBin++) {
+              Double_t dDt   = hpT->GetBinContent(iBin + 1);
+              Double_t dCorT = fhCorTOff[iDetIndx]->GetBinContent(iBin + 1);
+              Double_t dCtsT = hCalT->GetBinContent(iBin + 1);
+              Double_t dCtsP = hCalP->GetBinContent(iBin + 1);
+              Double_t dDp   = hpP->GetBinContent(iBin + 1);
+              Double_t dCorP = fhCorPos[iDetIndx]->GetBinContent(iBin + 1);
+              LOG(debug) << "Cts check for " << fhCalTOff[iDetIndx]->GetName() << ", bin " << iBin << ": " << dCtsT
+                         << ", " << dCtsP << ", " << MINCTS;
+              if (dCtsT > MINCTS && dCtsP > MINCTS) {
+                // Fit Gaussian around peak
+                TH1* hpPy =
+                  (TH1*) fhCalPos[iDetIndx]->ProjectionY(Form("PosPy_%d_%d", iDetIndx, iBin), iBin + 1, iBin + 1);
+                if (hpPy->Integral() > MINCTS) {
+                  Double_t dFMean    = hpPy->GetBinCenter(hpPy->GetMaximumBin());
+                  Double_t dFLim     = 0.5;  // CAUTION, fixed numeric value
+                  Double_t dBinSize  = hpPy->GetBinWidth(1);
+                  dFLim              = TMath::Max(dFLim, 5. * dBinSize);
+                  TFitResultPtr fRes = hpPy->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
+                  if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
+                    dDp = fRes->Parameter(1);  //overwrite mean
+                    fhCalChannelDy->Fill(dDt);
+                  }
+                }
+                TH1* hpTy =
+                  (TH1*) fhCalTOff[iDetIndx]->ProjectionY(Form("TOffPy_%d_%d", iDetIndx, iBin), iBin + 1, iBin + 1);
+                if (hpTy->Integral() > MINCTS) {
+                  Double_t dFMean    = hpTy->GetBinCenter(hpTy->GetMaximumBin());
+                  Double_t dFLim     = 0.5;  // CAUTION, fixed numeric value
+                  Double_t dBinSize  = hpTy->GetBinWidth(1);
+                  dFLim              = TMath::Max(dFLim, 5. * dBinSize);
+                  TFitResultPtr fRes = hpTy->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
+                  if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
+                    dDt = fRes->Parameter(1);  //overwrite mean
+                    fhCalChannelDt->Fill(dDt);
+                  }
+                }
+                // Double_t dDpRes = fRes->Parameter(2);
+                if (iSmType == 5) {  // do not shift beam counter in time
+                  fhCorTOff[iDetIndx]->SetBinContent(iBin + 1, dCorT + dDt - dBeamTOff);
+                  dTOffMeanShift += dDt - dBeamTOff;
+                }
+                else {
+                  fhCorTOff[iDetIndx]->SetBinContent(iBin + 1, dCorT + dDt + dBeamTOff);
+                  dTOffMeanShift += dDt + dBeamTOff;
+                }
+                dNCh += 1.;
+                if (iOpt1 > 0) {  // active  y-position correction
+                  fhCorPos[iDetIndx]->SetBinContent(iBin + 1, dCorP + dDp);
+                }
+                if (iDetIndx > -1) {
+                  LOG(debug) << Form("Update %s: bin %02d, Cts: %d, Old %6.3f, dev %6.3f, beam %6.3f, new %6.3f",
+                                     fhCorTOff[iDetIndx]->GetName(), iBin, (Int_t) dCtsT, dCorT, dDt, dBeamTOff,
+                                     dCorT + dDt + dBeamTOff);
+                }
+              }
+            }
+            if (dNCh > 0) dTOffMeanShift /= dNCh;
+            //LOG(info) << "Apply dTOffMeanShift " << dTOffMeanShift << " to " << fhCorTOff[iDetIndx]->GetName();
+            for (Int_t iBin = 0; iBin < fhCorTOff[iDetIndx]->GetNbinsX(); iBin++) {  //preserve mean offset
+              fhCorTOff[iDetIndx]->SetBinContent(iBin + 1,
+                                                 fhCorTOff[iDetIndx]->GetBinContent(iBin + 1) - dTOffMeanShift);
+            }
           }
         } break;
-        case 2: {  // update individual channel walks
-          LOG(info) << "Update Walks for TSR " << iSmType << iSm << iRpc;
-          if (iSmType == 5) continue;  // no walk correction for beam counter up to now
-          const Double_t MinCounts = 10.;
-          Int_t iNbCh              = fDigiBdfPar->GetNbChan(iSmType, iRpc);
-          for (Int_t iCh = 0; iCh < iNbCh; iCh++) {
-            for (Int_t iSide = 0; iSide < 2; iSide++) {
-              //LOG(info) << "Get walk histo pointer for TSRCS " << iSmType<<iSm<<iRpc<<iCh<<iSide;
-              TProfile* hpW = fhCalWalk[iDetIndx][iCh][iSide]->ProfileX();     // mean deviation
-              TH1* hCW      = fhCalWalk[iDetIndx][iCh][iSide]->ProjectionX();  // contributing counts
-              if (hCW->GetEntries() == 0) {
-                LOG(info) << "No entries in " << hCW->GetName();
-                continue;
-              }
-              Double_t dCorT = 0;
-              for (Int_t iBin = 0; iBin < fhCorWalk[iDetIndx][iCh][iSide]->GetNbinsX(); iBin++) {
-                Double_t dCts  = hCW->GetBinContent(iBin + 1);
-                Double_t dWOff = fhCorWalk[iDetIndx][iCh][iSide]->GetBinContent(iBin + 1);  // current value
-                if (iBin > 0 && dCts == 0)
-                  fhCorWalk[iDetIndx][iCh][iSide]->SetBinContent(iBin + 1,
-                                                                 fhCorWalk[iDetIndx][iCh][iSide]->GetBinContent(iBin));
-                if (dCts > MinCounts) { dCorT = hpW->GetBinContent(iBin + 1); }
-                fhCorWalk[iDetIndx][iCh][iSide]->SetBinContent(iBin + 1, dWOff + dCorT);  //set new value
+        case 2: {  // iopt1==11: update individual channel walks from inside Cluster deviations
+          switch (iOpt1) {
+            case 10: {
+              LOG(debug) << "Update Cluster Offsets for TSR " << iSmType << iSm << iRpc;
+              if (iSmType == 5) continue;  // do not shift beam counter in time
+              //TProfile* hpP = fhCalDelPos[iDetIndx]->ProfileX();
+              TProfile* hpT = fhCalDelTOff[iDetIndx]->ProfileX();
+              TH1* hCalP    = fhCalDelPos[iDetIndx]->ProjectionX();
+              TH1* hCalT    = fhCalDelTOff[iDetIndx]->ProjectionX();
+              //double dTOffMeanShift = 0.;
+              //double dNCh           = 0.;
+              for (Int_t iBin = 0; iBin < fhCorTOff[iDetIndx]->GetNbinsX(); iBin++) {
+                Double_t dDt   = hpT->GetBinContent(iBin + 1);
+                Double_t dCorT = fhCorTOff[iDetIndx]->GetBinContent(iBin + 1);
+                Double_t dCtsT = hCalT->GetBinContent(iBin + 1);
+                Double_t dCtsP = hCalP->GetBinContent(iBin + 1);
+                //Double_t dDp   = hpP->GetBinContent(iBin + 1);
+                //Double_t dCorP = fhCorPos[iDetIndx]->GetBinContent(iBin + 1);
+                LOG(debug) << "Cts check for " << fhCalDelTOff[iDetIndx]->GetName() << ", bin " << iBin << ": " << dCtsT
+                           << ", " << dCtsP << ", " << MINCTS;
+                if (dCtsT > MINCTS) {  //&& dCtsP > MINCTS) {
+                                       // Fit Gaussian around peak
+                  TH1* hpTy       = (TH1*) fhCalDelTOff[iDetIndx]->ProjectionY(Form("DelTOffPy_%d_%d", iDetIndx, iBin),
+                                                                         iBin + 1, iBin + 1);
+                  double dFMean   = hpTy->GetBinCenter(hpTy->GetMaximumBin());
+                  double dFLim    = 0.5;  // CAUTION, fixed numeric value
+                  double dBinSize = hpTy->GetBinWidth(1);
+                  dFLim           = TMath::Max(dFLim, 5. * dBinSize);
+                  TFitResultPtr fRes = hpTy->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
+                  if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
+                    dDt = fRes->Parameter(1);  //overwrite mean
+                  }
+                  fhCorTOff[iDetIndx]->SetBinContent(iBin + 1, dCorT + dDt);
+                  fhCalChannelDt->Fill(dDt);
+                }
+                if (iDetIndx > -1) {
+                  LOG(debug) << Form("Update %s: bin %02d, Cts: %d, Old %6.3f, dev %6.3f, new %6.3f",
+                                     fhCorTOff[iDetIndx]->GetName(), iBin, (Int_t) dCtsT, dCorT, dDt, dCorT + dDt);
+                }
               }
-              // determine effective/count rate weighted mean
-              Double_t dMean   = 0;
-              Double_t dCtsAll = 0.;
-              for (Int_t iBin = 0; iBin < fhCorWalk[iDetIndx][iCh][iSide]->GetNbinsX(); iBin++) {
-                Double_t dCts  = hCW->GetBinContent(iBin + 1);
-                Double_t dWOff = fhCorWalk[iDetIndx][iCh][iSide]->GetBinContent(iBin + 1);
-                if (dCts > MinCounts) {
-                  dCtsAll += dCts;
-                  dMean += dCts * dWOff;
+            } break;
+            case 12: {
+              LOG(debug) << "Update Cluster Position for TSR " << iSmType << iSm << iRpc;
+              if (iSmType == 5) continue;  // do not shift beam counter in time
+              TProfile* hpP = fhCalDelPos[iDetIndx]->ProfileX();
+              TProfile* hpT = fhCalDelTOff[iDetIndx]->ProfileX();
+              TH1* hCalP    = fhCalDelPos[iDetIndx]->ProjectionX();
+              TH1* hCalT    = fhCalDelTOff[iDetIndx]->ProjectionX();
+              //double dTOffMeanShift = 0.;
+              //double dNCh           = 0.;
+              for (Int_t iBin = 0; iBin < fhCorTOff[iDetIndx]->GetNbinsX(); iBin++) {
+                Double_t dDt   = hpT->GetBinContent(iBin + 1);
+                Double_t dCorT = fhCorTOff[iDetIndx]->GetBinContent(iBin + 1);
+                Double_t dCtsT = hCalT->GetBinContent(iBin + 1);
+                Double_t dCtsP = hCalP->GetBinContent(iBin + 1);
+                Double_t dDp   = hpP->GetBinContent(iBin + 1);
+                Double_t dCorP = fhCorPos[iDetIndx]->GetBinContent(iBin + 1);
+                LOG(debug) << "Cts check for " << fhCalDelTOff[iDetIndx]->GetName() << ", bin " << iBin << ": " << dCtsT
+                           << ", " << dCtsP << ", " << MINCTS;
+                if (dCtsT > MINCTS && dCtsP > MINCTS) {
+                  // Fit Gaussian around peak
+                  TH1* hpTy       = (TH1*) fhCalDelTOff[iDetIndx]->ProjectionY(Form("DelTOffPy_%d_%d", iDetIndx, iBin),
+                                                                         iBin + 1, iBin + 1);
+                  double dFMean   = hpTy->GetBinCenter(hpTy->GetMaximumBin());
+                  double dFLim    = 0.5;  // CAUTION, fixed numeric value
+                  double dBinSize = hpTy->GetBinWidth(1);
+                  dFLim           = TMath::Max(dFLim, 5. * dBinSize);
+                  TFitResultPtr fRes = hpTy->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
+                  if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
+                    dDt = fRes->Parameter(1);  //overwrite mean
+                  }
+                  fhCorTOff[iDetIndx]->SetBinContent(iBin + 1, dCorT + dDt);
+                  fhCalChannelDt->Fill(dDt);
+
+                  TH1* hpPy = (TH1*) fhCalDelPos[iDetIndx]->ProjectionY(Form("DelPosPy_%d_%d", iDetIndx, iBin),
+                                                                        iBin + 1, iBin + 1);
+                  dFMean    = hpPy->GetBinCenter(hpTy->GetMaximumBin());
+                  dFLim     = 0.5;  // CAUTION, fixed numeric value
+                  dBinSize  = hpPy->GetBinWidth(1);
+                  dFLim     = TMath::Max(dFLim, 5. * dBinSize);
+                  fRes      = hpPy->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
+                  if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
+                    dDp = fRes->Parameter(1);  //overwrite mean
+                  }
+                  fhCorPos[iDetIndx]->SetBinContent(iBin + 1, dCorP + dDp);
+                  fhCalChannelDy->Fill(dDp);
+                }
+                if (iDetIndx > -1) {
+                  LOG(debug) << Form("Update %s: bin %02d, Cts: %d, Old %6.3f, dev %6.3f, new %6.3f",
+                                     fhCorTOff[iDetIndx]->GetName(), iBin, (Int_t) dCtsT, dCorT, dDt, dCorT + dDt);
                 }
               }
-              if (dCtsAll > 0.) dMean /= dCtsAll;
-
-              LOG(info) << "Mean shift for TSRCS " << iSmType << iSm << iRpc << iCh << iSide << ": " << dMean;
-
-              // keep mean value at 0
-              for (Int_t iBin = 0; iBin < fhCorWalk[iDetIndx][iCh][iSide]->GetNbinsX(); iBin++) {
-                Double_t dWOff = fhCorWalk[iDetIndx][iCh][iSide]->GetBinContent(iBin + 1);  // current value
-                fhCorWalk[iDetIndx][iCh][iSide]->SetBinContent(iBin + 1, dWOff - dMean);    //set new value
-                if (iCh == 0 && iSmType == 8 && iBin == 10)                                 // debugging
-                  LOG(info) << "New Walk for " << fhCorWalk[iDetIndx][iCh][iSide]->GetName() << " bin " << iBin << ": "
-                            << fhCorWalk[iDetIndx][iCh][iSide]->GetBinContent(iBin + 1) << ", Mean " << dMean
-                            << ", WOff " << dWOff;
+            } break;
+            case 0:
+            case 11: {
+              LOG(debug) << "Update Walks for TSR " << iSmType << iSm << iRpc;
+              //if (iSmType == 5) continue;  // no walk correction for beam counter up to now
+              const Double_t MinCounts = 10.;
+              Int_t iNbCh              = fDigiBdfPar->GetNbChan(iSmType, iRpc);
+              for (Int_t iCh = 0; iCh < iNbCh; iCh++) {
+                TH1* hCY = fhCalPos[iDetIndx]->ProjectionY(Form("%s_py_%d", fhCalPos[iDetIndx]->GetName(), iCh),
+                                                           iCh + 1, iCh + 1);
+                if (hCY->GetEntries() > 1) fhCalChannelDy->Fill(hCY->GetRMS());
+                //LOG(info) << "Get walk histo pointer for TSRCS " << iSmType<<iSm<<iRpc<<iCh<<iSide;
+                TProfile* hpW0 = fhCalWalk[iDetIndx][iCh][0]->ProfileX();     // mean deviation
+                TH1* hCW0      = fhCalWalk[iDetIndx][iCh][0]->ProjectionX();  // contributing counts
+                TProfile* hpW1 = fhCalWalk[iDetIndx][iCh][1]->ProfileX();     // mean deviation
+                TH1* hCW1      = fhCalWalk[iDetIndx][iCh][1]->ProjectionX();  // contributing counts
+                if (iOpt0 == 3) {                                             // use average distributions
+                  hpW0 = fhCalWalkAv[iDetIndx]->ProfileX();                   // mean deviation
+                  hCW0 = fhCalWalkAv[iDetIndx]->ProjectionX();                // contributing counts
+                  hpW1 = fhCalWalkAv[iDetIndx]->ProfileX();                   // mean deviation
+                  hCW1 = fhCalWalkAv[iDetIndx]->ProjectionX();                // contributing counts
+                }
+                if (hCW0->GetEntries() == 0 || hCW1->GetEntries() == 0) {
+                  //LOG(info) << "No entries in " << hCW0->GetName();
+                  continue;
+                }
+                Double_t dCorT = 0;
+                for (Int_t iBin = 0; iBin < fhCorWalk[iDetIndx][iCh][0]->GetNbinsX(); iBin++) {
+                  Double_t dCts0  = hCW0->GetBinContent(iBin + 1);
+                  Double_t dCts1  = hCW1->GetBinContent(iBin + 1);
+                  Double_t dWOff0 = fhCorWalk[iDetIndx][iCh][0]->GetBinContent(iBin + 1);  // current value
+                  Double_t dWOff1 = fhCorWalk[iDetIndx][iCh][1]->GetBinContent(iBin + 1);  // current value
+                  if (iBin > 0 && dCts0 == 0 && dCts1 == 0) {
+                    fhCorWalk[iDetIndx][iCh][0]->SetBinContent(iBin + 1,
+                                                               fhCorWalk[iDetIndx][iCh][0]->GetBinContent(iBin));
+                    fhCorWalk[iDetIndx][iCh][1]->SetBinContent(iBin + 1,
+                                                               fhCorWalk[iDetIndx][iCh][1]->GetBinContent(iBin));
+                  }
+                  dCorT = 0.;
+                  if (dCts0 > MinCounts && dCts1 > MinCounts) {
+                    dCorT = 0.5 * (hpW0->GetBinContent(iBin + 1) + hpW1->GetBinContent(iBin + 1));
+                    fhCalChannelDt->Fill(dCorT);
+                  }
+                  fhCorWalk[iDetIndx][iCh][0]->SetBinContent(iBin + 1, dWOff0 + dCorT);  //set new value
+                  fhCorWalk[iDetIndx][iCh][1]->SetBinContent(iBin + 1, dWOff1 + dCorT);  //set new value
+                  if (iSmType == 0 && iSm == 0 && iRpc == 2)                             // debugging
+                    LOG(info) << "UpdWalk " << fhCorWalk[iDetIndx][iCh][0]->GetName() << " bin " << iBin << " Tot "
+                              << hCW0->GetBinCenter(iBin + 1) << ", " << hCW1->GetBinCenter(iBin + 1) << ": curVal "
+                              << dWOff0 << ", " << dWOff1 << ", Cts " << dCts0 << ", " << dCts1 << ", dCorT " << dCorT
+                              << ", newVal " << dWOff0 + dCorT << ", " << dWOff1 + dCorT;
+                }
+                // determine effective/count rate weighted mean
+                /*
+                  Double_t dMean   = 0;
+                  Double_t dCtsAll = 0.;
+                  for (Int_t iBin = 0; iBin < fhCorWalk[iDetIndx][iCh][iSide]->GetNbinsX(); iBin++) {
+                    Double_t dCts  = hCW->GetBinContent(iBin + 1);
+                    Double_t dWOff = fhCorWalk[iDetIndx][iCh][iSide]->GetBinContent(iBin + 1);
+                    if (dCts > MinCounts) {
+                      dCtsAll += dCts;
+                      dMean += dCts * dWOff;
+                    }
+                  }
+                  if (dCtsAll > 0.) dMean /= dCtsAll;
+
+                  //LOG(info) << "Mean shift for TSRCS " << iSmType << iSm << iRpc << iCh << iSide << ": " << dMean;
+                  // keep mean value at 0
+                  for (Int_t iBin = 0; iBin < fhCorWalk[iDetIndx][iCh][iSide]->GetNbinsX(); iBin++) {
+                    Double_t dWOff = fhCorWalk[iDetIndx][iCh][iSide]->GetBinContent(iBin + 1);  // current value
+                    if (iSmType == 0 && iSm == 0 && iRpc == 2)                                  // debugging
+                    LOG(info) << "UpdWalk " << fhCorWalk[iDetIndx][iCh][iSide]->GetName() 
+                              << " bin " << iBin << " Tot " << hCW->GetBinCenter(iBin + 1)
+                              << ": curDev " << hpW->GetBinContent(iBin + 1)
+                              << ", Cts "    << hCW->GetBinContent(iBin + 1)
+                              << ", all "    << dCtsAll
+                              << ", oldWOff " << dWOff - hpW->GetBinContent(iBin + 1) 
+                              << ", Mean " << dMean
+                              << ", newWOff " << dWOff - dMean;
+                    fhCorWalk[iDetIndx][iCh][iSide]->SetBinContent(iBin + 1, dWOff + dMean);    //set new value                            
+                  }
+                */
               }
-            }
-          }
+            } break;  //iopt1=11 end
+            default:; LOG(info) << "Calibrator option " << iOpt << " not implemented ";
+          }  // switch iOpt1 end
         } break;
 
         case 9:  // update channel means on cluster level
@@ -772,7 +1828,8 @@ Bool_t CbmTofCalibrator::UpdateCalHist(Int_t iOpt)
               CbmTofCell* fChannelInfo = fDigiPar->GetCell(iChId);
               if (NULL == fChannelInfo) LOG(fatal) << Form("invalid ChannelInfo for 0x%08x", iChId);
 
-              double dThr = 10.;
+              double dThr = dCtsP / 100;
+              if (dThr < 3.) dThr = 3.;
               double* dRes =
                 fTofClusterizer->find_yedges((const char*) (hPos_py->GetName()), dThr, fChannelInfo->GetSizey());
               /*
@@ -791,9 +1848,11 @@ Bool_t CbmTofCalibrator::UpdateCalHist(Int_t iOpt)
             }
           }
 
-          //TofOff
-          TProfile* hpT = fhCalTofOff[iDetIndx]->ProfileX();
-          TH1* hCalT    = fhCalTofOff[iDetIndx]->ProjectionX();
+          //TofOff or TOff as input ?
+          //TProfile* hpT = fhCalTofOff[iDetIndx]->ProfileX();
+          //TH1* hCalT    = fhCalTofOff[iDetIndx]->ProjectionX();
+          TProfile* hpT = fhCalTOff[iDetIndx]->ProfileX();
+          TH1* hCalT    = fhCalTOff[iDetIndx]->ProjectionX();
           for (Int_t iBin = 0; iBin < fhCorTOff[iDetIndx]->GetNbinsX(); iBin++) {
             //Double_t dDt   = hpT->GetBinContent(iBin + 1);
             Double_t dCorT = fhCorTOff[iDetIndx]->GetBinContent(iBin + 1);
@@ -812,16 +1871,20 @@ Bool_t CbmTofCalibrator::UpdateCalHist(Int_t iOpt)
                 //if (fRes == 0 )
                 if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
                   //if (TMath::Abs(TMean - fRes->Parameter(1)) > 1.)
+                  /*
                   LOG(info) << "CalTOff  "
                             << Form("TSRC %d%d%d%d, %s gaus %8.2f %8.2f %8.2f for "
                                     "TM %8.2f, TBeam %6.2f",
                                     iSmType, iSm, iRpc, iBin, hTy->GetName(), fRes->Parameter(0), fRes->Parameter(1),
                                     fRes->Parameter(2), dTmean, dBeamTOff);
+                  */
                   dTmean = fRes->Parameter(1);  //overwrite mean
                 }
               }
+              /*
               LOG(info) << Form("UpdateCalTOff TSRC %d%d%d%2d, cts %d: %6.2f -> %6.2f, %6.2f ", iSmType, iSm, iRpc,
                                 iBin, (int) dCtsT, dCorT, dCorT + dTmean, dCorT + hpT->GetBinContent(iBin + 1));
+              */
               fhCorTOff[iDetIndx]->SetBinContent(iBin + 1, dCorT + dTmean);
             }
           }
@@ -834,31 +1897,41 @@ Bool_t CbmTofCalibrator::UpdateCalHist(Int_t iOpt)
             double dTotMean = hbin->GetMean();
             // Do gaus fit around maximum
             Double_t dCtsTot = hbin->GetEntries();
-            if (kFALSE && dCtsTot > MINCTS) {
+            if (dCtsTot > MINCTS) {
               double dFMean = hbin->GetBinCenter(hbin->GetMaximumBin());
-              double dFLim  = dFMean;  // CAUTION,
+              double dFLim  = dFMean * 0.5;  // CAUTION,
               //LOG(info)<<Form("FitTot TSRC %d%d%d%2d:  Mean %6.2f, Width %6.2f ",iSmType,iSm,iRpc,iBin,dFMean,dFLim);
               if (dFMean > 2.) {
                 TFitResultPtr fRes = hbin->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
                 if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
                   dTotMean = fRes->Parameter(1);  //overwrite mean
                 }
+                else {
+                  LOG(warn) << "FitFail " << hbin->GetName();
+                }
               }
             }
+            else {  //append to broken channel list
+              int iCh   = iBin % 2;
+              int iSide = iBin - iCh * 2;
+              CbmTofDetectorInfo xDetInfo(ECbmModuleId::kTof, iSmType, iSm, iRpc, iCh, iSide);
+              Int_t iChId   = fTofId->SetDetectorInfo(xDetInfo);
+              TString shcmd = Form("echo %d >> %s  ", iChId, cBadChannelFile.Data());
+              gSystem->Exec(shcmd.Data());
+            }
             if (dTotMean > 0.) {  // prevent zero-divide
               double dCorTot = fhCorTot[iDetIndx]->GetBinContent(ib);
               /*
           	  LOG(info)<<Form("UpdateCalTot TSRC %d%d%d%2d: %6.2f, %6.2f, %6.2f -> %6.2f ",iSmType,iSm,iRpc,iBin,
           			  dCorTot,dCalTotMean,dTotMean,dCorTot*dTotMean/dCalTotMean);
-          			  */
+          		*/
               fhCorTot[iDetIndx]->SetBinContent(ib, dCorTot * dTotMean / dCalTotMean);
             }
           }
 
         } break;
-
-        default: LOG(warning) << "No valid calibration mode " << iOpt0;
-      }  //switch( iOpt) end
+        default: LOG(fatal) << "No valid calibration mode " << iOpt0;
+      }  //switch( iOpt0) end
     }
   }
   else {
@@ -870,6 +1943,9 @@ Bool_t CbmTofCalibrator::UpdateCalHist(Int_t iOpt)
     WriteHist(fCalParFileNew);
     fCalParFileNew->Close();
   }
+  else {
+    WriteHist(fCalParFile);
+  }
   fCalParFile->Close();
 
   /// Restore old global file and folder pointer to avoid messing with FairRoot
@@ -921,11 +1997,19 @@ void CbmTofCalibrator::ReadHist(TFile* fHist)
       fhCorWalk[iDetIndx][iCh].resize(2);
       for (Int_t iSide = 0; iSide < 2; iSide++) {
         //LOG(info) << "Get walk histo pointer for TSRCS " << iSmType<<iSm<<iRpc<<iCh<<iSide;
-        fhCorWalk[iDetIndx][iCh][iSide] = (TH1*) gDirectory->FindObjectAny(
-          Form("Cor_SmT%01d_sm%03d_rpc%03d_Ch%03d_S%d_Walk_px", iSmType, iSm, iRpc, iCh, iSide));
+        TString hname = Form("Cor_SmT%01d_sm%03d_rpc%03d_Ch%03d_S%d_Walk_px", iSmType, iSm, iRpc, iCh, iSide);
+        fhCorWalk[iDetIndx][iCh][iSide] = (TH1*) gDirectory->FindObjectAny(hname);
         if (NULL == fhCorWalk[iDetIndx][iCh][iSide]) {
           LOG(warn) << "No Walk histo for TSRCS " << iSmType << iSm << iRpc << iCh << iSide;
-          continue;
+          if (NULL != fhCalWalk[iDetIndx][iCh][iSide]) {
+            LOG(info) << "Create walk correction histo " << hname;
+            fhCorWalk[iDetIndx][iCh][iSide] =
+              new TH1D(hname,
+                       Form("Walk in SmT%01d_sm%03d_rpc%03d_Ch%03d_S%01d_Walk; Tot [a.u.];  #DeltaT [ns]", iSmType, iSm,
+                            iRpc, iCh, iSide),
+                       nbClWalkBinX, fTofClusterizer->GetTotMin(), fTofClusterizer->GetTotMax());
+          }
+          //continue;
         }
 
         if (iSmType == 8 && iSide == 1) {  //pad special treatment
@@ -938,6 +2022,35 @@ void CbmTofCalibrator::ReadHist(TFile* fHist)
       }
     }
   }
+
+  int iNbTypes = fDigiBdfPar->GetNbSmTypes();
+  hSvel.resize(iNbTypes);
+  for (int iSmType = 0; iSmType < iNbTypes; iSmType++) {
+    int iNbRpc = fDigiBdfPar->GetNbRpc(iSmType);
+    if (iNbRpc > 0 && fDigiBdfPar->GetNbSm(iSmType) > 0) {
+      TH1* hTmp = (TH1*) gDirectory->FindObjectAny(Form("cl_SmT%01d_Svel", iSmType));
+      if (hTmp == NULL) {
+        TDirectory* oldir = gDirectory;
+        gROOT->cd();
+        LOG(warn) << Form("cl_SmT%01d_Svel not found, creating ... in %s ", iSmType, gDirectory->GetName());
+        hSvel[iSmType] =
+          new TH1F(Form("cl_SmT%01d_Svel", iSmType), Form("Clu Svel in SmType %d; Sm+Rpc# []; v/v_{nominal} ", iSmType),
+                   fDigiBdfPar->GetNbSm(iSmType) * iNbRpc, 0, fDigiBdfPar->GetNbSm(iSmType) * iNbRpc);
+
+        for (int i = 0; i < hSvel[iSmType]->GetNbinsX(); i++)
+          hSvel[iSmType]->SetBinContent(i + 1, 1.);  // set default
+        oldir->cd();
+      }
+      else {
+        //LOG(info) << "hSvel "<< hTmp->GetName() << " located in " <<  gDirectory->GetName();
+        TDirectory* oldir = gDirectory;
+        gROOT->cd();
+        hSvel[iSmType] = (TProfile*) hTmp->Clone();
+        //LOG(info) << "hSvel "<< hSvel[iSmType]->GetName() << " cloned in " <<  gDirectory->GetName();
+        oldir->cd();
+      }
+    }
+  }
 }
 
 void CbmTofCalibrator::WriteHist(TFile* fHist)
@@ -955,10 +2068,23 @@ void CbmTofCalibrator::WriteHist(TFile* fHist)
     Int_t iNbCh = (Int_t) fhCorWalk[iDetIndx].size();
     for (Int_t iCh = 0; iCh < iNbCh; iCh++) {
       for (Int_t iSide = 0; iSide < 2; iSide++) {
-        fhCorWalk[iDetIndx][iCh][iSide]->Write();
+        //LOG(info)<<"Write " << fhCorWalk[iDetIndx][iCh][iSide]->GetName();
+        if (NULL != fhCorWalk[iDetIndx][iCh][iSide]) fhCorWalk[iDetIndx][iCh][iSide]->Write();
+        else
+          LOG(warn) << "Walk correction histo for DetIndx " << iDetIndx << ", Ch " << iCh << ", S " << iSide
+                    << " not found";
       }
     }
   }
+  for (Int_t iS = 0; iS < fDigiBdfPar->GetNbSmTypes(); iS++) {
+    if (NULL != hSvel[iS]) {
+      hSvel[iS]->Write();
+      LOG(warn) << "Wrote " << hSvel[iS]->GetName() << " to " << gDirectory->GetName();
+    }
+    else {
+      LOG(warn) << Form("cl_SmT%01d_Svel not found ", iS);
+    }
+  }
   oldir->cd();
 }
 
@@ -1013,5 +2139,269 @@ void CbmTofCalibrator::HstDoublets(CbmTofTracklet* pTrk)
   }
 }
 
+double* CbmTofCalibrator::find_tofedge(const char* hname, double dThr, double dLen)
+{
+  TH1* h1               = (TH1*) gROOT->FindObjectAny(hname);
+  static double dRes[2] = {2 * 0};
+  dRes[0]               = 0.;
+  if (NULL != h1) {
+    /*
+	LOG(debug) << "Inspect " << h1->GetName() << ", entries " << h1->GetNbinsX() 
+	     << ", Thr " << dThr << ", Len " << dLen << endl;
+	     */
+
+    const int iMaxInt = 3;
+    int iMax          = h1->GetMaximumBin();
+    int iLow          = TMath::Max(iMax - iMaxInt, 1);
+    int iHigh         = TMath::Min(iMax + iMaxInt, h1->GetNbinsX());
+    double dMax       = 0.;
+    int nMax          = 0;
+    for (int i = iLow; i < iHigh; i++) {
+      dMax += h1->GetBinContent(i);
+      nMax++;
+    }
+    dMax /= nMax;
+
+    // determine average noise and RMS per bin
+    double dNoise  = 0;
+    double dNoise2 = 0;
+    double dRMS    = 0;
+    int iNbins     = 0;
+    for (int iBin = 0; iBin < h1->GetNbinsX() / 4; iBin++) {
+      if (h1->GetBinContent(iBin + 1) > 0 || iNbins > 0) {  // start counting from first bin with entries
+        dNoise += h1->GetBinContent(iBin + 1);
+        dNoise2 += h1->GetBinContent(iBin + 1) * h1->GetBinContent(iBin + 1);
+        iNbins++;
+      }
+    }
+    if (iNbins > 0) {
+      dNoise /= iNbins;
+      dNoise2 /= iNbins;
+      dRMS = TMath::Sqrt(dNoise2 - dNoise * dNoise);
+    }
+    else {
+      dNoise = h1->GetMaximum() * 0.1;
+      LOG(warn) << h1->GetName() << ": Noise level could not be determined, init to " << dNoise;
+    }
+    double dLev = dNoise + (dMax - dNoise) * dThr;
+    dLev        = TMath::Max(dNoise + 3. * dRMS, dLev);
+    if (dLev == 0) {
+      LOG(warn) << "Invalid threshold level " << dLev;
+      return dRes;
+    }
+    int iBl     = -1;
+    double xLow = h1->GetBinCenter(1);
+
+    for (int iBin = 1; iBin < h1->GetNbinsX() - dLen; iBin++) {
+      int iLen = 0;
+      for (; iLen < dLen; iLen++) {
+        LOG(debug) << h1->GetName() << ": Lev " << dLev << ",  Bin " << iBin << ", Len " << iLen << ", cont "
+                   << h1->GetBinContent(iBin + iLen);
+        if (h1->GetBinContent(iBin + iLen) < dLev) break;
+      }
+      if (iLen == dLen) {
+        if (iBin == 1) {
+          LOG(warn) << "find_tofedge: " << h1->GetName() << ",  Lvl1 " << dLev;
+          iBin--;
+          dLev *= 2;
+          continue;
+        }
+        iBl  = iBin;
+        xLow = h1->GetBinCenter(iBin);
+        if (iBin == 1) {  // not active since did not work, case already caught above
+          LOG(warn) << GetName() << ": " << h1->GetName() << " Lvl1 " << dLev;
+          xLow *= 2;
+        }
+        break;
+      }
+    }
+    dRes[0] = xLow;
+    LOG(info) << h1->GetName() << " with Thr " << dLev << ", Noise " << dNoise << ", RMS " << dRMS << " at iBl " << iBl
+              << ", TOff " << dRes[0];
+  }
+  return dRes;
+}
+
+double* CbmTofCalibrator::find_tofedge(const char* hname)
+{
+  double dThr = 0.1;
+  double dLen = 3.;
+  return find_tofedge(hname, dThr, dLen);
+}
+
+double CbmTofCalibrator::CalcChi2(TH1* h1, TH1* h2, int i)
+{
+  double chi2         = 0.;
+  double nBin         = 0.;
+  double nEntries1    = h1->GetEntries();
+  double nEntries2    = h2->GetEntries();
+  const int CompRange = (int) h1->GetNbinsX() / 4;
+  for (int iBin1 = CompRange; iBin1 < h1->GetNbinsX() - CompRange; iBin1++) {
+    double diff = h1->GetBinContent(iBin1) / nEntries1 - h2->GetBinContent(iBin1 + i) / nEntries2;
+    chi2 += diff * diff;
+    nBin++;
+  }
+  chi2 /= nBin;
+  return chi2;
+}
+
+
+Double_t CbmTofCalibrator::f1_tedge(double* x, double* par)
+{
+  double xx = x[0];
+  //double wx    = par[0] + par[1] * TMath::Exp(xx*par[2]);
+  double wx = par[0] + par[1] * (1. + TMath::Erf((xx - par[2]) / par[3]));
+
+  return wx;
+}
+
+double* CbmTofCalibrator::fit_tofedge(const char* hname, Double_t TMax, Double_t dThr)
+{
+  TH1* h1;
+  static double res[10] = {10 * 0.};
+  double err[10];
+  h1 = (TH1*) gROOT->FindObjectAny(hname);
+  if (NULL != h1) {
+    const double MinCts = 1000.;
+    res[2]              = 0.;
+    if (h1->GetEntries() < MinCts) {
+      LOG(warn) << h1->GetName() << ": too few entries for edgefit " << h1->GetEntries();
+      return &res[2];
+    }
+
+    TAxis* xaxis   = h1->GetXaxis();
+    Double_t Tmin  = xaxis->GetXmin();
+    Double_t Tmax  = xaxis->GetXmax();
+    Double_t dXmax = Tmax;
+    if (TMax == 0.) TMax = Tmax;
+    else
+      Tmax = TMax - 1.;
+    Tmax               = TMath::Max(Tmax, Tmin + 0.3);
+    TFitResultPtr fRes = h1->Fit("pol0", "SQM", "", Tmin, Tmax);
+    TF1* f0            = h1->GetFunction("pol0");
+    if (fRes != 0 && f0 != NULL && (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED"))) {
+      //double dBackground=fRes->Parameter(0) ;
+      double dBackground = f0->GetParameter(0);
+      //cout << h1->GetName() << ":  av background rate \t" <<  dBackground<< endl;
+      TF1* f1 = new TF1("TEdge", f1_tedge, Tmin, dXmax, 4);
+      if (TMax != 0.) {
+        f1->SetParameters(dBackground, 1000., 0., 0.1);
+        f1->SetParLimits(0, dBackground, dBackground);  //fix background
+      }
+      f1->SetParLimits(2, -0.5, 0.5);
+      f1->SetParLimits(3, 0.05, 0.5);
+
+      h1->Fit("TEdge", "SQM", "", Tmin, TMax);
+      res[9] = f1->GetChisquare();
+
+      for (int i = 0; i < 4; i++) {
+        res[i] = f1->GetParameter(i);
+        err[i] = f1->GetParError(i);
+      }
+
+      if (res[1] < 0.) {
+        LOG(warn) << h1->GetName() << "fitted wrong sign of step function ";
+        res[0] = h1->GetBinCenter(h1->GetNbinsX());
+        return &res[0];
+      }
+      // determine toff at 10*background
+      /*
+      double dToff=0.;
+      if (res[1] !=0. && res[2] != 0.) dToff=TMath::Log(10*dBackground/res[1])/res[2];
+      LOG(info) << "TEdge Fit of " << hname 
+                << " in [" << Tmin <<","<< TMax <<"]"
+		            << " ended with chi2 = " << res[9]
+		            << ", Toff " << dToff
+                << Form(", noise level %7.2f +/- %5.2f, e0 %7.2f "
+                   "+/- %5.2f, exp = %7.2f +/- %5.2f",
+                   res[0], err[0], res[1], err[1], res[2], err[2]);
+      res[0]=dToff;
+      */
+      // FIXME: code duplication from find_tofedge
+      const int iMaxInt = 3;
+      int iMax          = h1->GetMaximumBin();
+      int iLow          = TMath::Max(iMax - iMaxInt, 1);
+      int iHigh         = TMath::Min(iMax + iMaxInt, h1->GetNbinsX());
+      double dMax       = 0.;
+      int nMax          = 0;
+      for (int i = iLow; i < iHigh; i++) {
+        dMax += h1->GetBinContent(i);
+        nMax++;
+      }
+      dMax /= nMax;
+      double dLev = dThr * dMax;
+      dLev        = dBackground + (dMax - dBackground) * 0.1;
+
+      double dToff = f1->GetX(dLev, Tmin, dXmax);
+
+      LOG(info) << "TEdge Fit of " << hname << " in [" << Tmin << "," << TMax << "/" << dXmax << "]"
+                << ": chi2 " << res[9]
+                << Form(
+                     ", noise %6.2f +/-%4.2f, norm %6.2f +/-%4.2f, mean %6.2f +/-%5.3f, wid %6.2f +/-%5.3f -> %6.3f ",
+                     res[0], err[0], res[1], err[1], res[2], err[2], res[3], err[3], dToff);
+      res[2] = dToff;
+    }
+    else {
+      LOG(warn) << "pol0 fit failed, Minuit " << gMinuit->fCstatu << ", fRes " << fRes << ", "
+                << ", f0 " << f0;
+    }
+  }
+  return &res[2];
+}
+
+double* CbmTofCalibrator::fit_tofedge(const char* hname)
+{
+  Double_t Tmax = 0.3;
+  return fit_tofedge(hname, Tmax, fTofClusterizer->GetEdgeThr());
+}
+
+double CbmTofCalibrator::TruncatedMeanY(TH2* h2, double dRmsLim)
+{
+  double dMeanIn = h2->ProjectionY()->GetMean();
+  double dRmsIn  = h2->ProjectionY()->GetRMS();
+  const int Nx   = h2->GetNbinsX();
+
+  int Ntru = 0;
+  TH1* h1[Nx];
+  double dMean  = 0.;
+  double dMean2 = 0.;
+  double dNorm  = 0.;
+  double dRms   = 0.;
+  for (int i = 0; i < Nx; i++) {
+    h1[i] = h2->ProjectionY(Form("%s_py%d", h2->GetName(), i), i + 1, i + 1);
+    if (TMath::Abs(dMeanIn - h1[i]->GetMean()) < dRmsLim * dRmsIn) {
+      dMean += h1[i]->GetMean() * h1[i]->GetEntries();
+      dMean2 += h1[i]->GetMean() * h1[i]->GetMean() * h1[i]->GetEntries();
+      dNorm += h1[i]->GetEntries();
+      Ntru++;
+    }
+  }
+  if (Ntru > 0) {
+    dMean /= dNorm;
+    dMean2 /= dNorm;
+    if (dMean2 > dMean * dMean) { dRms = TMath::Sqrt(dMean2 - dMean * dMean); }
+    else {
+      LOG(error) << h2->GetName() << " Invalid Rms calculation: " << dMean2 << ", " << dMean * dMean;
+      return dMean;
+    }
+    double dMean1 = dMean;
+    dMean         = 0.;
+    dMean2        = 0.;
+    dNorm         = 0.;
+    Ntru          = 0;
+    for (int j = 0; j < Nx; j++) {
+      if (TMath::Abs(dMean1 - h1[j]->GetMean()) < dRmsLim * dRms) {
+        dMean += h1[j]->GetMean() * h1[j]->GetEntries();
+        dMean2 += h1[j]->GetMean() * h1[j]->GetMean() * h1[j]->GetEntries();
+        dNorm += h1[j]->GetEntries();
+        Ntru++;
+      }
+    }
+    if (Ntru > 0) { dMean /= dNorm; }
+  }
+  LOG(info) << h2->GetName() << ": TruncY " << dMean << "( " << Ntru << ")"
+            << ", full " << dMeanIn << ", RMS " << dRms;
+  return dMean;
+}
 
 ClassImp(CbmTofCalibrator)
diff --git a/reco/detectors/tof/CbmTofCalibrator.h b/reco/detectors/tof/CbmTofCalibrator.h
index f89430cbac6e5f1ead5523e88630b8861b4ce409..c90c5aa5f1ce382d59ac9fc43c119c2d6fde1d7a 100644
--- a/reco/detectors/tof/CbmTofCalibrator.h
+++ b/reco/detectors/tof/CbmTofCalibrator.h
@@ -63,11 +63,19 @@ public:
   Bool_t InitParameters();
   Bool_t CreateCalHist();
   void FillCalHist(CbmTofHit* pHit, Int_t iOpt, CbmEvent* pEvent = NULL);
+  void FillHitCalHist(CbmTofHit* pHit, Int_t iOpt, CbmEvent* pEvent = NULL, TClonesArray* tHitColl = NULL);
   void FillCalHist(CbmTofTracklet* pTrk, Int_t iOpt, CbmEvent* pEvent = NULL);
   Bool_t UpdateCalHist(Int_t iOpt);
   void ReadHist(TFile* fhFile);
   void WriteHist(TFile* fhFile);
   void HstDoublets(CbmTofTracklet* pTrk);
+  double* find_tofedge(const char* hname, Double_t dThr, Double_t dLen);
+  double* find_tofedge(const char* hname);
+  double CalcChi2(TH1* h1, TH1* h2, int iShift);
+  double* fit_tofedge(const char* hname, Double_t dTmax, Double_t dThr);
+  double* fit_tofedge(const char* hname);
+  static double f1_tedge(double* x, double* par);
+  double TruncatedMeanY(TH2* pHst, double RmsLim = 1.);
 
   inline void SetR0Lim(Double_t dVal) { fdR0Lim = dVal; }
   inline void SetBeam(Bool_t bVal) { fbBeam = bVal; }
@@ -82,6 +90,8 @@ private:
 
   CbmTofDigiPar* fDigiPar;
   CbmTofDigiBdfPar* fDigiBdfPar;
+  CbmTofGeoHandler* fGeoHandler;
+  CbmTofDetectorId* fTofId;
   TClonesArray* fTofDigiMatchColl;  // TOF Digi Links
 
   FairEventHeader* fEvtHeader;
@@ -90,12 +100,27 @@ private:
   TH1* fhCalDX0;
   TH1* fhCalDY0;
 
+  TH1* fhCalCounterDt;
+  TH1* fhCalCounterDy;
+  TH1* fhCalChannelDt;
+  TH1* fhCalChannelDy;
+
   std::vector<TH2*> fhCalTot;                             // [nbDet]
   std::vector<TH2*> fhCalPosition;                        // [nbDet]
   std::vector<TH2*> fhCalPos;                             // [nbDet]
   std::vector<TH2*> fhCalTOff;                            // [nbDet]
   std::vector<TH2*> fhCalTofOff;                          // [nbDet]
+  std::vector<TH2*> fhCalDelPos;                          // [nbDet]
+  std::vector<TH2*> fhCalDelTOff;                         // [nbDet]
+  std::vector<TH2*> fhCalCluTrms;                         // [nbDet]
+  std::vector<TH2*> fhCalCluSize;                         // [nbDet]
+  std::vector<TH2*> fhCalWalkAv;                          // [nbDet]
   std::vector<std::vector<std::vector<TH2*>>> fhCalWalk;  // [nbDet][nbCh][nSide]
+  std::vector<std::vector<std::vector<TH2*>>> fhCalDtWalk;    // [nbDet][nbCh][nSide]
+  std::vector<TH3*> fhCalXYTOff;                              // [nbDet]
+  std::vector<TH3*> fhCalXYTot;                               // [nbDet]
+  std::vector<std::vector<std::vector<TH3*>>> fhCalTotYWalk;  // [nbDet][nbCh][nSide]
+  std::vector<std::vector<std::vector<TH3*>>> fhCalTotYTOff;  // [nbDet][nbCh][nSide]
 
   std::vector<TH1*> fhCorPos;                             // [nbDet]
   std::vector<TH1*> fhCorTOff;                            // [nbDet]
diff --git a/reco/detectors/tof/CbmTofEventClusterizer.cxx b/reco/detectors/tof/CbmTofEventClusterizer.cxx
index 9d9398357cfd3942e802e025368d5f23096e5d26..911f6ccf8c791ee820dfdf5ff164e533d888415c 100644
--- a/reco/detectors/tof/CbmTofEventClusterizer.cxx
+++ b/reco/detectors/tof/CbmTofEventClusterizer.cxx
@@ -19,7 +19,8 @@
 #include "CbmDigiManager.h"
 #include "CbmEvent.h"
 #include "CbmMatch.h"
-#include "CbmTofAddress.h"          // in cbmdata/tof
+#include "CbmTimeSlice.h"
+#include "CbmTofAddress.h"  // in cbmdata/tof
 #include "CbmTofCalibrator.h"
 #include "CbmTofCell.h"             // in tof/TofData
 #include "CbmTofCreateDigiPar.h"    // in tof/TofTools
@@ -32,8 +33,11 @@
 #include "CbmTofGeoHandler.h"       // in tof/TofTools
 #include "CbmTofHit.h"              // in cbmdata/tof
 #include "CbmTofPoint.h"            // in cbmdata/tof
+#include "CbmTsEventHeader.h"
 #include "CbmVertex.h"
 
+#include "TimesliceMetaData.h"
+
 #include "TTrbHeader.h"
 
 // CBMroot classes and includes
@@ -55,6 +59,7 @@
 #include "TFitResult.h"
 #include "TFitter.h"
 #include "TGeoManager.h"
+#include "TGeoPhysicalNode.h"
 #include "TH1.h"
 #include "TH2.h"
 #include "TH3.h"
@@ -85,13 +90,14 @@ static Int_t iNSpill          = 0;
 static Int_t iNbTs            = 0;
 static int fiHitStart          = 0;
 static double dTsStartTime     = 0.;
+static double dTsStartTimeLast = -1.;
 const Double_t fdSpillDuration = 2.;    // in seconds
 const Double_t fdSpillBreak    = 0.9;   // in seconds
 const Double_t dTimeRes        = 0.08;  // in ns
 
 static Bool_t bAddBeamCounterSideDigi = kTRUE;
 static TRandom3* fRndm                = new TRandom3();
-
+std::vector<CbmTofDigi>* fT0DigiVec;  //! T0 Digis
 //   std::vector< CbmTofPoint* > vPtsRef;
 
 CbmTofEventClusterizer* CbmTofEventClusterizer::fInstance = 0;
@@ -111,6 +117,8 @@ CbmTofEventClusterizer::CbmTofEventClusterizer(const char* name, Int_t verbose,
   , fDigiBdfPar(NULL)
   , fTrbHeader(NULL)
   , fEvtHeader(NULL)
+  , fTsHeader(NULL)
+  , fTimeSlice(NULL)
   , fTofDigiPointMatches(NULL)
   , fDigiMan(nullptr)
   , fEventsColl(nullptr)
@@ -136,6 +144,7 @@ CbmTofEventClusterizer::CbmTofEventClusterizer(const char* name, Int_t verbose,
   , fvdDifCh()
   , fTofCalibrator(NULL)
   , fhClustBuildTime(NULL)
+  , fhClustHitsDigi(NULL)
   , fhHitsPerTracks(NULL)
   , fhPtsPerHit(NULL)
   , fhTimeResSingHits(NULL)
@@ -165,6 +174,10 @@ CbmTofEventClusterizer::CbmTofEventClusterizer(const char* name, Int_t verbose,
   , fhRpcDigiDTFD()
   , fhRpcDigiDTMul()
   , fhRpcDigiRate()
+  , fhRpcDigiTotLeft()
+  , fhRpcDigiTotRight()
+  , fhRpcDigiTotDiff()
+  , fhRpcDigiTotMap()
   , fhRpcCluMul()
   , fhRpcCluRate()
   , fhRpcCluRate10s()
@@ -216,6 +229,9 @@ CbmTofEventClusterizer::CbmTofEventClusterizer(const char* name, Int_t verbose,
   , fvCPTotGain()
   , fvCPTotOff()
   , fvCPWalk()
+  , fvCPTOffY()
+  , fvCPTOffYBinWidth()
+  , fvCPTOffYRange()
   , fvLastHits()
   , fvDeadStrips()
   , fvTimeLastDigi()
@@ -253,7 +269,10 @@ CbmTofEventClusterizer::CbmTofEventClusterizer(const char* name, Int_t verbose,
   , fSel2Rpc(0)
   , fSel2Addr(0)
   , fSel2MulMax(1)
+  , fiCluSizeMin(0)
+  , fNbCalHitMin(0)
   , fDetIdIndexMap()
+  , fCellIdGeoMap()
   , fviDetId()
   , fPosYMaxScal(1.)
   , fTRefDifMax(10.)
@@ -281,6 +300,11 @@ CbmTofEventClusterizer::CbmTofEventClusterizer(const char* name, Int_t verbose,
   , fdTTotMean(2.)
   , fdMaxTimeDist(0.)
   , fdMaxSpaceDist(0.)
+  , fdEdgeThr(0.1)
+  , fdEdgeLen(3.)
+  , fdEdgeTbias(-0.3)
+  , fdEdgeFrange(0.4)
+  , fdModifySigvel(1.0)
   , fdEvent(0)
   , fdStartAnalysisTime(0.)
   , fbSwapChannelSides(kFALSE)
@@ -316,7 +340,10 @@ InitStatus CbmTofEventClusterizer::Init()
 
   if (kFALSE == CreateHistos()) return kFATAL;
 
-  if (fCalMode % 10 > 7 && fDutId > -1) {
+  if ((fCalMode % 10 > 7 && fDutId > -1) || (fCalMode > 99 && fDutId < 0)) {
+    if (fiBeamRefType > -1)
+      fiBeamRefAddr = CbmTofAddress::GetUniqueAddress(fiBeamRefSm, fiBeamRefDet, 0, 0, fiBeamRefType);
+    LOG(info) << "Initialize Calibrator for Clusterizer ";
     fTofCalibrator = new CbmTofCalibrator();
     if (fTofCalibrator->Init() != kSUCCESS) return kFATAL;
     return kSUCCESS;
@@ -373,9 +400,10 @@ void CbmTofEventClusterizer::Exec(Option_t* option)
 
   if (fTofCalDigiVecOut) fTofCalDigiVecOut->clear();
   if (fEventsColl) {
-    LOG(info) << "New timeslice " << iNbTs << " with " << fEventsColl->GetEntriesFast() << " events, "
-              << fDigiMan->GetNofDigis(ECbmModuleId::kTof) << " TOF digis + "
-              << fDigiMan->GetNofDigis(ECbmModuleId::kT0) << " T0 digis ";
+    if (NULL != fTsHeader)
+      LOG(info) << "New Ts " << iNbTs << ", size " << fEventsColl->GetSize() << " at " << fTsHeader->GetTsStartTime()
+                << " with " << fEventsColl->GetEntriesFast() << " events, " << fDigiMan->GetNofDigis(ECbmModuleId::kTof)
+                << " TOF digis + " << fDigiMan->GetNofDigis(ECbmModuleId::kT0) << " T0 digis ";
 
     TStopwatch timerTs;
     timerTs.Start();
@@ -387,6 +415,7 @@ void CbmTofEventClusterizer::Exec(Option_t* option)
     Int_t iNbHits     = 0;
     Int_t iNbCalDigis = 0;
     fTofDigiMatchCollOut->Delete();  // costly, FIXME
+    //for(int i=0; i<fTofHitsCollOut->GetEntriesFast(); i++) delete fTofHitsCollOut->At(i);
     fTofHitsCollOut->Delete();       // costly, FIXME
     //fTofDigiMatchCollOut->Clear("C"); // not sufficient, memory leak
     for (Int_t iEvent = 0; iEvent < fEventsColl->GetEntriesFast(); iEvent++) {
@@ -400,8 +429,10 @@ void CbmTofEventClusterizer::Exec(Option_t* option)
       for (Int_t iDigi = 0; iDigi < tEvent->GetNofData(ECbmDataType::kT0Digi); iDigi++) {
         Int_t iDigiIndex       = static_cast<Int_t>(tEvent->GetIndex(ECbmDataType::kT0Digi, iDigi));
         CbmTofDigi tDigi(fDigiMan->Get<CbmBmonDigi>(iDigiIndex));
-        if (tDigi.GetType() != 5)
-          LOG(fatal) << "Wrong T0 type " << tDigi.GetType() << ", Addr 0x" << std::hex << tDigi.GetAddress();
+        if (tDigi.GetType() != 5) {
+          //LOG(fatal) << "Wrong T0 type " << tDigi.GetType() << ", Addr 0x" << std::hex << tDigi.GetAddress();
+          tDigi.SetAddress(0, 0, 0, 0, 5);  // convert to Tof Address
+        }
         if (tDigi.GetSide() == 1) {  // HACK for May22 setup
           tDigi.SetAddress(tDigi.GetSm(), tDigi.GetRpc(), tDigi.GetChannel() + 6, 0, tDigi.GetType());
         }
@@ -459,12 +490,19 @@ void CbmTofEventClusterizer::Exec(Option_t* option)
         //tEvent->SetMatch( (CbmMatch*)((*fTofDigiMatchCollOut)[iNbHits]) );
         iNbHits++;
       }
-      if (fCalMode % 10 == 9 && fDutId > -1) {
-        if (iNbHits - iHit0 > 0) {  // outsource all calibration actions
+
+      if ((fCalMode % 10 == 9 && fDutId > -1) || (fCalMode > 99 && fDutId < 0)) {
+        if (iNbHits - iHit0 > fNbCalHitMin) {  // outsource all calibration actions
           LOG(debug) << "Call Calibrator with fiHitStart = " << fiHitStart << ", entries "
                      << fTofHitsCollOut->GetEntriesFast();
           CbmTofHit* pHit = (CbmTofHit*) fTofHitsCollOut->At(fiHitStart);  // use most early hit as reference
-          fTofCalibrator->FillCalHist(pHit, fCalMode, tEvent);
+          if (fCalMode < 100) fTofCalibrator->FillCalHist(pHit, fCalMode, tEvent);
+          else {
+            if (fCalMode < 1000) {
+              CbmTofHit* pRef = NULL;
+              fTofCalibrator->FillHitCalHist(pRef, fCalMode, tEvent, fTofHitsCollOut);
+            }
+          }
         }
       }
 
@@ -473,7 +511,7 @@ void CbmTofEventClusterizer::Exec(Option_t* option)
       fTofDigiVec.clear();
       //fTofCalDigi->Delete();//Clear("C"); //otherwise memoryleak! FIXME
       fTofCalDigiVec->clear();
-      fTofHitsColl->Clear("C");
+      fTofHitsColl->Delete();       //Clear("C");
       fTofDigiMatchColl->Delete();  //Clear("C");
     }
     if (0 < fiNbSkip1) {
@@ -512,6 +550,23 @@ void CbmTofEventClusterizer::Exec(Option_t* option)
     fTofDigiVec.clear();
     //if (fTofDigisColl) fTofDigisColl->Clear("C");
     // Int_t iNbDigis=0; (VF) not used
+    if (NULL != fT0DigiVec)  // 2022 data
+      for (Int_t iDigi = 0; iDigi < (int) (fT0DigiVec->size()); iDigi++) {
+        CbmTofDigi tDigi = fT0DigiVec->at(iDigi);
+        if (tDigi.GetType() != 5)
+          LOG(fatal) << "Wrong T0 type " << tDigi.GetType() << ", Addr 0x" << std::hex << tDigi.GetAddress();
+        if (tDigi.GetSide() == 1) {  // HACK for May22 setup
+          tDigi.SetAddress(tDigi.GetSm(), tDigi.GetRpc(), tDigi.GetChannel() + 6, 0, tDigi.GetType());
+        }
+        fTofDigiVec.push_back(CbmTofDigi(tDigi));
+      }
+    else {  // MC
+      /*
+      for (Int_t iDigi = 0; iDigi < fDigiMan->GetNofDigis(ECbmModuleId::kT0); iDigi++) {
+        const CbmTofDigi* tDigi = fDigiMan->Get<CbmTofDigi>(iDigi);
+      }
+      */
+    }
     for (Int_t iDigi = 0; iDigi < fDigiMan->GetNofDigis(ECbmModuleId::kTof); iDigi++) {
       const CbmTofDigi* tDigi = fDigiMan->Get<CbmTofDigi>(iDigi);
       fTofDigiVec.push_back(CbmTofDigi(*tDigi));
@@ -526,8 +581,8 @@ void CbmTofEventClusterizer::ExecEvent(Option_t* /*option*/, CbmEvent* tEvent)
   // Clear output arrays
   //fTofCalDigisColl->Delete(); //otherwise memoryleak if 'CbmDigi::fMatch' points to valid MC match objects (simulation)! FIXME
   fTofCalDigiVec->clear();
-  fTofHitsColl->Clear("C");
-  //fTofHitsColl->Delete();  // Computationally costly!, but hopefully safe
+  //fTofHitsColl->Clear("C");
+  fTofHitsColl->Delete();  // Computationally costly!, but hopefully safe
   //for (Int_t i=0; i<fTofDigiMatchColl->GetEntriesFast(); i++) ((CbmMatch *)(fTofDigiMatchColl->At(i)))->ClearLinks();  // FIXME, try to tamper memory leak (did not help)
   //fTofDigiMatchColl->Clear("C+L");  // leads to memory leak
   fTofDigiMatchColl->Delete();
@@ -535,11 +590,21 @@ void CbmTofEventClusterizer::ExecEvent(Option_t* /*option*/, CbmEvent* tEvent)
   if (bla) fiOutputTreeEntry = ((FairRootFileSink*) FairRootManager::Instance()->GetSink())->GetOutTree()->GetEntries();
 
   // Check for corruption
-  if (fTofDigiVec.size() > 10. * fDigiBdfPar->GetNbDet()) return;  // FIXME constant in code, skip this event
-
+  if (fTofDigiVec.size() > 20. * fDigiBdfPar->GetNbDet()) {  // FIXME constant in code, skip this event
+    LOG(warn) << "Skip processing of Tof DigiEvent with " << fTofDigiVec.size() << " digis ";
+    return;
+  }
   fiNbHits = 0;
-  if (fEvtHeader != NULL) dTsStartTime = fEvtHeader->GetEventTime();
-  LOG(debug) << Form("BuildClu for event %d at tTS = %f ", (int) fdEvent, dTsStartTime);
+  if (fEvtHeader != NULL) {
+    dTsStartTime = fEvtHeader->GetEventTime();
+    if (fTsHeader != NULL) dTsStartTime = static_cast<double>(fTsHeader->GetTsStartTime());
+    if (dTsStartTime != dTsStartTimeLast) {
+      LOG(debug) << Form("BuildClu for event %d at tTS = %f ", (int) fdEvent, dTsStartTime);
+      dTsStartTimeLast = dTsStartTime;
+    }
+  }
+  else
+    LOG(fatal) << "No EvtHeader found!";
 
   fStart.Set();
 
@@ -551,13 +616,12 @@ void CbmTofEventClusterizer::ExecEvent(Option_t* /*option*/, CbmEvent* tEvent)
 
   fdEvent++;
   FillHistos(tEvent);
-
-  //   fTofDigisColl->RemoveAll();
 }
 
 /************************************************************************************/
 void CbmTofEventClusterizer::Finish()
 {
+  FairLogger::GetLogger()->SetLogScreenLevel("info");
   LOG(info) << "Finish with " << fdEvent << " processed events";
 
   /// PAL: add run statistics for monitoring and perf evaluation
@@ -575,12 +639,14 @@ void CbmTofEventClusterizer::Finish()
   LOG(info) << "=====================================";
 
   if (fdEvent < 100) return;  // don't save histos with insufficient statistics
-  if (fDutId < 0) return;     // no histograms were produced
 
-  if (fCalMode % 10 < 8) { WriteHistos(); }
+  if (fCalMode % 10 < 8 && fDutId > -1) { WriteHistos(); }
   else {
-    fTofCalibrator->UpdateCalHist(fCalMode);
+    if ((fCalMode % 10 > 7 && fDutId > -1) || (fCalMode > 99 && fDutId < 0)) {
+      fTofCalibrator->UpdateCalHist(fCalMode);
+    }
   }
+
   // Prevent them from being sucked in by the CbmHadronAnalysis WriteHistograms method
   // DeleteHistos();
   if (fdMemoryTime > 0.) CleanLHMemory();
@@ -621,7 +687,10 @@ Bool_t CbmTofEventClusterizer::RegisterInputs()
     LOG(error) << GetName() << ": No Tof digi input!";
     return kFALSE;
   }
-  if (fDigiMan->IsPresent(ECbmModuleId::kT0)) { LOG(info) << GetName() << ": found separate T0 digi input!"; }
+  if (fDigiMan->IsPresent(ECbmModuleId::kT0)) {
+    LOG(info) << GetName() << ": separate T0 digi input!";
+    //fT0DigiVec = fManager->InitObjectAs<std::vector<CbmTofDigi> const*>("TzdDigi");
+  }
   else {
     LOG(info) << "No separate T0 digi input found.";
   }  // if( ! fT0DigiVec )
@@ -632,10 +701,13 @@ Bool_t CbmTofEventClusterizer::RegisterInputs()
                  "TofTrbHeader Object";
   }
 
-  fEvtHeader = (FairEventHeader*) fManager->GetObject("EventHeader.");
-  if (NULL == fEvtHeader) {
-    LOG(info) << "CbmTofEventClusterizer::RegisterInputs => Could not get "
-                 "EvtHeader Object";
+  fEvtHeader = dynamic_cast<FairEventHeader*>(fManager->GetObject("EventHeader."));
+  if (NULL == fEvtHeader) { LOG(fatal) << "CbmTofEventClusterizer::RegisterInputs => Could not get EvtHeader Object"; }
+  fTsHeader = fManager->InitObjectAs<CbmTsEventHeader const*>("EventHeader.");  //for data
+  if (NULL == fTsHeader) {
+    LOG(info) << "CbmTofEventClusterizer::RegisterInputs => Could not get TsHeader Object";
+    fTimeSlice = fManager->InitObjectAs<CbmTimeSlice const*>("TimeSlice.");  // MC
+    if (NULL == fTimeSlice) { LOG(info) << "CbmTofEventClusterizer::RegisterInputs => Could not get TimeSlice Object"; }
   }
 
   if (NULL == fEventsColl) {
@@ -659,7 +731,7 @@ Bool_t CbmTofEventClusterizer::RegisterOutputs()
   //fTofCalDigisColl = new TClonesArray("CbmTofDigi");
   fTofCalDigiVec = new std::vector<CbmTofDigi>();
 
-  fTofHitsColl = new TClonesArray("CbmTofHit");
+  fTofHitsColl = new TClonesArray("CbmTofHit", 100);
 
   fTofDigiMatchColl = new TClonesArray("CbmMatch", 100);
 
@@ -685,7 +757,7 @@ Bool_t CbmTofEventClusterizer::RegisterOutputs()
     fTofHitsCollOut = fTofHitsColl;
 
     rootMgr->Register(tHitDigiMatchBranchName, "Tof", fTofDigiMatchColl, fbWriteHitsInOut);
-    LOG(info) << Form("Register DigiMatch in TS mode at %p", fTofDigiMatchColl);
+    LOG(info) << Form("Register DigiMatch in TS mode at %p with %d", fTofDigiMatchColl, (int) fbWriteHitsInOut);
     fTofDigiMatchCollOut = fTofDigiMatchColl;
 
     if (NULL != fTofDigiPointMatches) {
@@ -703,7 +775,7 @@ Bool_t CbmTofEventClusterizer::RegisterOutputs()
     rootMgr->RegisterAny("TofCalDigi", fTofCalDigiVecOut, fbWriteDigisInOut);
     rootMgr->Register(tHitBranchName, "Tof", fTofHitsCollOut, fbWriteHitsInOut);
     rootMgr->Register(tHitDigiMatchBranchName, "Tof", fTofDigiMatchCollOut, fbWriteHitsInOut);
-    LOG(info) << Form("Register DigiMatch in event mode at %p", fTofDigiMatchCollOut);
+    LOG(info) << Form("Register DigiMatch in event mode at %p with %d ", fTofDigiMatchCollOut, (int) fbWriteHitsInOut);
 
     if (NULL != fTofDigiPointMatches) {
       fTofDigiPointMatchesOut = new std::vector<CbmMatch>();
@@ -794,6 +866,9 @@ Bool_t CbmTofEventClusterizer::InitCalibParameter()
   fvCPTotOff.resize(iNbSmTypes);
   fvCPWalk.resize(iNbSmTypes);
   fvCPDelTof.resize(iNbSmTypes);
+  fvCPTOffY.resize(iNbSmTypes);
+  fvCPTOffYBinWidth.resize(iNbSmTypes);
+  fvCPTOffYRange.resize(iNbSmTypes);
   for (Int_t iSmType = 0; iSmType < iNbSmTypes; iSmType++) {
     Int_t iNbSm  = fDigiBdfPar->GetNbSm(iSmType);
     Int_t iNbRpc = fDigiBdfPar->GetNbRpc(iSmType);
@@ -801,6 +876,9 @@ Bool_t CbmTofEventClusterizer::InitCalibParameter()
     fvCPTotGain[iSmType].resize(iNbSm * iNbRpc);
     fvCPTotOff[iSmType].resize(iNbSm * iNbRpc);
     fvCPWalk[iSmType].resize(iNbSm * iNbRpc);
+    fvCPTOffY[iSmType].resize(iNbSm * iNbRpc);
+    fvCPTOffYBinWidth[iSmType].resize(iNbSm * iNbRpc);
+    fvCPTOffYRange[iSmType].resize(iNbSm * iNbRpc);
     fvCPDelTof[iSmType].resize(iNbSm * iNbRpc);
     for (Int_t iSm = 0; iSm < iNbSm; iSm++) {
       for (Int_t iRpc = 0; iRpc < iNbRpc; iRpc++) {
@@ -813,6 +891,8 @@ Bool_t CbmTofEventClusterizer::InitCalibParameter()
           for (Int_t iSel = 0; iSel < iNSel; iSel++)
             fvCPDelTof[iSmType][iSm * iNbRpc + iRpc][iBx][iSel] = 0.;  // initialize
         }
+        fvCPTOffYBinWidth[iSmType][iSm * iNbRpc + iRpc] = 0.;  // initialize
+        fvCPTOffYRange[iSmType][iSm * iNbRpc + iRpc]    = 0.;  // initialize
 
         Int_t iNbChan = fDigiBdfPar->GetNbChan(iSmType, iRpc);
         fvCPTOff[iSmType][iSm * iNbRpc + iRpc].resize(iNbChan);
@@ -853,7 +933,7 @@ Bool_t CbmTofEventClusterizer::InitCalibParameter()
     // read parameter from histos
     if (fCalParFileName.IsNull()) return kTRUE;
 
-    fCalParFile = new TFile(fCalParFileName, "");
+    fCalParFile = new TFile(fCalParFileName, "READ");
     if (NULL == fCalParFile) {
       if (fCalMode % 10 == 9) {  //modify reference file name
         int iCalMode              = fCalParFileName.Index("tofClust") - 3;
@@ -863,49 +943,45 @@ Bool_t CbmTofEventClusterizer::InitCalibParameter()
         if (NULL == fCalParFile)
           LOG(fatal) << "CbmTofEventClusterizer::InitCalibParameter: "
                      << "file " << fCalParFileName << " does not exist!";
+
         return kTRUE;
       }
+      LOG(fatal) << "Calibration parameter file not existing!";
     }
-    /*
-		 gDirectory->Print();
-		 fCalParFile->cd();
-		 fCalParFile->ls();
-		 */
+    fhSmCluSvel.resize(iNbSmTypes);
     for (Int_t iSmType = 0; iSmType < iNbSmTypes; iSmType++) {
       Int_t iNbSm     = fDigiBdfPar->GetNbSm(iSmType);
       Int_t iNbRpc    = fDigiBdfPar->GetNbRpc(iSmType);
-      TProfile* hSvel = (TProfile*) gDirectory->FindObjectAny(Form("cl_SmT%01d_Svel", iSmType));
-
-      // copy Histo to memory
-      TDirectory* curdir = gDirectory;
-      if (NULL != hSvel) {
-        gDirectory->cd(oldDir->GetPath());
-        // TProfile *hSvelmem = (TProfile *)hSvel->Clone();  (VF) not used
-        gDirectory->cd(curdir->GetPath());
-      }
-      else {
-        LOG(info) << "Svel histogram not found for module type " << iSmType;
-      }
-
-      for (Int_t iPar = 0; iPar < 4; iPar++) {
-        TProfile* hFparcur = (TProfile*) gDirectory->FindObjectAny(Form("cl_SmT%01d_Fpar%1d", iSmType, iPar));
-        if (NULL != hFparcur) {
-          gDirectory->cd(oldDir->GetPath());
-          // TProfile *hFparmem = (TProfile *)hFparcur->Clone();  (VF) not used
-          gDirectory->cd(curdir->GetPath());
+      if (iNbSm > 0 && NULL == fhSmCluSvel[iSmType]) {
+        TProfile* hSvel = (TProfile*) gDirectory->FindObjectAny(Form("cl_SmT%01d_Svel", iSmType));
+        if (NULL == hSvel) LOG(warn) << "hSvel not found in " << gDirectory->GetName();
+        else {
+          fhSmCluSvel[iSmType] = (TProfile*) hSvel->Clone();
+          LOG(info) << fhSmCluSvel[iSmType]->GetName() << " cloned from " << gDirectory->GetName();
         }
       }
-
+      TDirectory* curdir = gDirectory;
       for (Int_t iSm = 0; iSm < iNbSm; iSm++)
         for (Int_t iRpc = 0; iRpc < iNbRpc; iRpc++) {
-
           // update default parameter
-          if (NULL != hSvel) {
-            Double_t Vscal = 1.;  //hSvel->GetBinContent(iSm*iNbRpc+iRpc+1);
+          if (NULL != fhSmCluSvel[iSmType]) {
+            Double_t Vscal = fhSmCluSvel[iSmType]->GetBinContent(iSm * iNbRpc + iRpc + 1);
             if (Vscal == 0.) Vscal = 1.;
+            if (Vscal < 0.8) {
+              LOG(warn) << "Fix parameter value of signal velocity TSR " << iSmType << iSm << iRpc << ": " << Vscal;
+              Vscal = 0.8;
+            }
+            if (Vscal > 1.2) {
+              LOG(warn) << "Fix parameter value of signal velocity TSR " << iSmType << iSm << iRpc << ": " << Vscal;
+              Vscal = 1.2;
+            }
+            Vscal *= fdModifySigvel;  //1.03; // testing the effect of wrong signal velocity, FIXME
             fDigiBdfPar->SetSigVel(iSmType, iSm, iRpc, fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc) * Vscal);
-            LOG(debug) << "Modify " << iSmType << iSm << iRpc << " Svel by " << Vscal << " to "
-                       << fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc);
+            LOG(info) << "Modify " << iSmType << iSm << iRpc << " Svel by " << Vscal << " to "
+                      << fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc);
+          }
+          else {
+            LOG(warn) << "Svel modifier histo not found in " << curdir->GetName();
           }
           TH2D* htempPos_pfx =
             (TH2D*) gDirectory->FindObjectAny(Form("cl_CorSmT%01d_sm%03d_rpc%03d_Pos_pfx", iSmType, iSm, iRpc));
@@ -919,13 +995,11 @@ Bool_t CbmTofEventClusterizer::InitCalibParameter()
             Int_t iNbCh    = fDigiBdfPar->GetNbChan(iSmType, iRpc);
             //Int_t iNbinTot = htempTot_Mean->GetNbinsX();//not used any more
             for (Int_t iCh = 0; iCh < iNbCh; iCh++) {
-
               for (Int_t iSide = 0; iSide < 2; iSide++) {
                 Double_t TotMean = htempTot_Mean->GetBinContent(iCh * 2 + 1 + iSide);  //nh +1 empirical(?)
                 if (0.001 < TotMean) { fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][iSide] *= fdTTotMean / TotMean; }
                 fvCPTotOff[iSmType][iSm * iNbRpc + iRpc][iCh][iSide] = htempTot_Off->GetBinContent(iCh * 2 + 1 + iSide);
               }
-
               Double_t YMean = ((TProfile*) htempPos_pfx)->GetBinContent(iCh + 1);  //nh +1 empirical(?)
               Double_t TMean = ((TProfile*) htempTOff_pfx)->GetBinContent(iCh + 1);
               if (std::isnan(YMean) || std::isnan(TMean)) {
@@ -950,8 +1024,8 @@ Bool_t CbmTofEventClusterizer::InitCalibParameter()
                 fvCPTotOff[iSmType][iSm * iNbRpc + iRpc][iCh][1]  = fvCPTotOff[iSmType][iSm * iNbRpc + iRpc][iCh][0];
               }
               //if(iSmType==0 && iSm==4 && iRpc==2 && iCh==26)
-              //if (iSmType==0 && iSm==1 && iRpc == 1)
-              if (iSmType == 9 && iSm == 0 && iRpc == 0 && iCh == 10)  // select specific channel
+              if (iSmType == 0 && iSm == 2 && iRpc == 0)
+                //if (iSmType == 9 && iSm == 0 && iRpc == 0 && iCh == 10)  // select specific channel
                 LOG(info) << "InitCalibParameter:"
                           << " TSRC " << iSmType << iSm << iRpc << iCh
                           << Form(": YMean %6.3f, TYOff %6.3f, TMean %6.3f", YMean, dTYOff, TMean) << " -> "
@@ -965,6 +1039,20 @@ Bool_t CbmTofEventClusterizer::InitCalibParameter()
                 Form("Cor_SmT%01d_sm%03d_rpc%03d_Ch%03d_S0_Walk_px", iSmType, iSm, iRpc, iCh));
               TH1D* htempWalk1 = (TH1D*) gDirectory->FindObjectAny(
                 Form("Cor_SmT%01d_sm%03d_rpc%03d_Ch%03d_S1_Walk_px", iSmType, iSm, iRpc, iCh));
+              if (NULL == htempWalk0 && NULL == htempWalk1) {  // regenerate Walk histos
+                int iSide = 0;
+                htempWalk0 =
+                  new TH1D(Form("Cor_SmT%01d_sm%03d_rpc%03d_Ch%03d_S0_Walk_px", iSmType, iSm, iRpc, iCh),
+                           Form("Walk in SmT%01d_sm%03d_rpc%03d_Ch%03d_S%01d_Walk; Tot [a.u.];  #DeltaT [ns]", iSmType,
+                                iSm, iRpc, iCh, iSide),
+                           nbClWalkBinX, fdTOTMin, fdTOTMax);
+                iSide = 1;
+                htempWalk1 =
+                  new TH1D(Form("Cor_SmT%01d_sm%03d_rpc%03d_Ch%03d_S0_Walk_px", iSmType, iSm, iRpc, iCh),
+                           Form("Walk in SmT%01d_sm%03d_rpc%03d_Ch%03d_S%01d_Walk; Tot [a.u.];  #DeltaT [ns]", iSmType,
+                                iSm, iRpc, iCh, iSide),
+                           nbClWalkBinX, fdTOTMin, fdTOTMax);
+              }
               if (NULL != htempWalk0 && NULL != htempWalk1) {  // reinitialize Walk array
                 LOG(debug) << "Initialize Walk correction for "
                            << Form(" SmT%01d_sm%03d_rpc%03d_Ch%03d", iSmType, iSm, iRpc, iCh);
@@ -974,9 +1062,11 @@ Bool_t CbmTofEventClusterizer::InitCalibParameter()
                 for (Int_t iBin = 0; iBin < nbClWalkBinX; iBin++) {
                   fvCPWalk[iSmType][iSm * iNbRpc + iRpc][iCh][0][iBin] = htempWalk0->GetBinContent(iBin + 1);
                   fvCPWalk[iSmType][iSm * iNbRpc + iRpc][iCh][1][iBin] = htempWalk1->GetBinContent(iBin + 1);
-                  if (0)  // iCh == 5 && iBin == 10)  // debugging
-                    LOG(info) << Form("Read New SmT%01d_sm%03d_rpc%03d_Ch%03d bin %d walk %f ", iSmType, iSm, iRpc, iCh,
-                                      iBin, fvCPWalk[iSmType][iSm * iNbRpc + iRpc][iCh][0][iBin]);
+                  if (iSmType == 0 && iSm == 0 && iRpc == 2 && iCh == 15)  // debugging
+                    LOG(info) << Form("Read new SmT%01d_sm%03d_rpc%03d_Ch%03d bin %d cen %f walk %f %f", iSmType, iSm,
+                                      iRpc, iCh, iBin, htempWalk0->GetBinCenter(iBin + 1),
+                                      fvCPWalk[iSmType][iSm * iNbRpc + iRpc][iCh][0][iBin],
+                                      fvCPWalk[iSmType][iSm * iNbRpc + iRpc][iCh][1][iBin]);
                   if (5 == iSmType || 8 == iSmType) {  // Pad structure, enforce consistency
                     if (fvCPWalk[iSmType][iSm * iNbRpc + iRpc][iCh][1][iBin]
                         != fvCPWalk[iSmType][iSm * iNbRpc + iRpc][iCh][0][iBin]) {
@@ -994,6 +1084,22 @@ Bool_t CbmTofEventClusterizer::InitCalibParameter()
                 LOG(info) << "No Walk histograms for TSRC " << iSmType << iSm << iRpc << iCh;
               }
             }
+            // look for TcorY corrections
+            LOG(info) << "Check for TCorY in " << gDirectory->GetName();
+            TH1* hTCorY =
+              (TH1*) gDirectory->FindObjectAny(Form("calXY_SmT%d_sm%03d_rpc%03d_TOff_z_all_TcorY", iSmType, iSm, iRpc));
+            if (NULL != hTCorY) {
+              fvCPTOffYBinWidth[iSmType][iSm * iNbRpc + iRpc] = hTCorY->GetBinWidth(0);
+              fvCPTOffYRange[iSmType][iSm * iNbRpc + iRpc]    = hTCorY->GetXaxis()->GetXmax();
+              LOG(info) << "Initialize TCorY: TSR " << iSmType << iSm << iRpc << ", Bwid "
+                        << fvCPTOffYBinWidth[iSmType][iSm * iNbRpc + iRpc] << ", Range "
+                        << fvCPTOffYRange[iSmType][iSm * iNbRpc + iRpc];
+              fvCPTOffY[iSmType][iSm * iNbRpc + iRpc].resize(hTCorY->GetNbinsX());
+              for (int iB = 0; iB < hTCorY->GetNbinsX(); iB++) {
+                //LOG(info) << "iB " << iB <<": " << hTCorY->GetBinContent(iB+1);
+                fvCPTOffY[iSmType][iSm * iNbRpc + iRpc][iB] = hTCorY->GetBinContent(iB + 1);
+              }
+            }
           }
           else {
             LOG(warning) << " Calibration histos " << Form("cl_SmT%01d_sm%03d_rpc%03d_XXX", iSmType, iSm, iRpc)
@@ -1038,7 +1144,7 @@ Bool_t CbmTofEventClusterizer::LoadGeometry()
 {
   LOG(info) << "CbmTofEventClusterizer::LoadGeometry starting for  " << fDigiBdfPar->GetNbDet()
             << " described detectors, " << fDigiPar->GetNrOfModules() << " geometrically known cells ";
-
+  fCellIdGeoMap.clear();
   Int_t iNrOfCells = fDigiPar->GetNrOfModules();
   LOG(info) << "Digi Parameter container contains " << iNrOfCells << " cells.";
   for (Int_t icell = 0; icell < iNrOfCells; ++icell) {
@@ -1064,6 +1170,8 @@ Bool_t CbmTofEventClusterizer::LoadGeometry()
       gGeoManager->FindNode(fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ());
     LOG(debug2) << Form(" Node at (%6.1f,%6.1f,%6.1f) : 0x%p", fChannelInfo->GetX(), fChannelInfo->GetY(),
                         fChannelInfo->GetZ(), fNode);
+    fCellIdGeoMap[cellId] = gGeoManager->MakePhysicalNode();
+
     if (icell == 0) {
       TGeoHMatrix* cMatrix = gGeoManager->GetCurrentMatrix();
       fNode->Print();
@@ -1083,8 +1191,8 @@ Bool_t CbmTofEventClusterizer::LoadGeometry()
     Int_t iSmType   = CbmTofAddress::GetSmType(iUniqueId);
     Int_t iSmId     = CbmTofAddress::GetSmId(iUniqueId);
     Int_t iRpcId    = CbmTofAddress::GetRpcId(iUniqueId);
-    LOG(info) << " DetIndx " << iDetIndx << "(" << iNbDet << "), SmType " << iSmType << ", SmId " << iSmId << ", RpcId "
-              << iRpcId << " => UniqueId " << Form("0x%08x ", iUniqueId)
+    LOG(info) << " DetIndx " << iDetIndx << "(" << iNbDet << "), TSR " << iSmType << iSmId << iRpcId << " => UniqueId "
+              << Form("0x%08x ", iUniqueId)
               << Form(" Svel %6.6f, DeadStrips 0x%08x ", fDigiBdfPar->GetSigVel(iSmType, iSmId, iRpcId),
                       fvDeadStrips[iDetIndx]);
     Int_t iNbChan = fDigiBdfPar->GetNbChan(iSmType, iRpcId);
@@ -1195,6 +1303,10 @@ Bool_t CbmTofEventClusterizer::CreateHistos()
   gROOT->cd();                     // <= To prevent histos from being sucked in by the param file of the TRootManager !
   fhClustBuildTime =
     new TH1I("TofEventClus_ClustBuildTime", "Time needed to build clusters in each event; Time [s]", 4000, 0.0, 4.0);
+
+  fhClustHitsDigi =
+    new TH2D(Form("hClustHitsDigi"), Form("Hits vs. CalDigis; Mul_{Digi}; Mul_{Hits}"), 100, 0, 500, 100, 0, 200);
+
   // RPC related distributions
   Int_t iNbDet = fDigiBdfPar->GetNbDet();
   fviDetId.resize(iNbDet);
@@ -1206,7 +1318,14 @@ Bool_t CbmTofEventClusterizer::CreateHistos()
     fviDetId[iDetIndx]        = iUniqueId;
   }
 
-  if (fDutId < 0) return kTRUE;
+  if (fTotMax != 0.) fdTOTMax = fTotMax;
+  if (fTotMin != 0.) fdTOTMin = fTotMin;
+  LOG(info) << "ToT init to Min " << fdTOTMin << " Max " << fdTOTMax;
+
+  if (fDutId < 0) {
+    LOG(info) << GetName() << ": Skip booking of calibration histograms ";
+    return kTRUE;
+  }
 
   // Sm related distributions
   fhSmCluPosition.resize(fDigiBdfPar->GetNbSmTypes());
@@ -1258,16 +1377,21 @@ Bool_t CbmTofEventClusterizer::CreateHistos()
                fDigiBdfPar->GetNbSm(iS) * fDigiBdfPar->GetNbRpc(iS), 0,
                fDigiBdfPar->GetNbSm(iS) * fDigiBdfPar->GetNbRpc(iS), 99, -TSumMax * 2., TSumMax * 2.);
 
-    TProfile* hSvelcur = (TProfile*) gDirectory->FindObjectAny(Form("cl_SmT%01d_Svel", iS));
-    if (NULL == hSvelcur) {
-      fhSmCluSvel[iS] =
-        new TProfile(Form("cl_SmT%01d_Svel", iS), Form("Clu Svel in SmType %d; Sm+Rpc# []; v/v_{nominal} ", iS),
-                     fDigiBdfPar->GetNbSm(iS) * fDigiBdfPar->GetNbRpc(iS), 0,
-                     fDigiBdfPar->GetNbSm(iS) * fDigiBdfPar->GetNbRpc(iS), 0.8, 1.2);
-      fhSmCluSvel[iS]->Sumw2();
+    if (NULL == fhSmCluSvel[iS]) {
+      TProfile* hSvelcur = (TProfile*) gDirectory->FindObjectAny(Form("cl_SmT%01d_Svel", iS));
+      if (NULL == hSvelcur) {
+        LOG(info) << "Histo " << Form("cl_SmT%01d_Svel", iS) << " not found, recreate ...";
+        fhSmCluSvel[iS] =
+          new TProfile(Form("cl_SmT%01d_Svel", iS), Form("Clu Svel in SmType %d; Sm+Rpc# []; v/v_{nominal} ", iS),
+                       fDigiBdfPar->GetNbSm(iS) * fDigiBdfPar->GetNbRpc(iS), 0,
+                       fDigiBdfPar->GetNbSm(iS) * fDigiBdfPar->GetNbRpc(iS), 0.8, 1.2);
+        fhSmCluSvel[iS]->Sumw2();
+      }
+      else {
+        fhSmCluSvel[iS] = (TProfile*) hSvelcur->Clone();
+        LOG(info) << fhSmCluSvel[iS]->GetName() << " cloned from " << gDirectory->GetName();
+      }
     }
-    else
-      fhSmCluSvel[iS] = (TProfile*) hSvelcur->Clone();
 
     fhSmCluFpar[iS].resize(4);
     for (Int_t iPar = 0; iPar < 4; iPar++) {
@@ -1316,6 +1440,10 @@ Bool_t CbmTofEventClusterizer::CreateHistos()
   fhRpcDigiDTFD.resize(iNbDet);
   fhRpcDigiDTMul.resize(iNbDet);
   fhRpcDigiRate.resize(iNbDet);
+  fhRpcDigiTotLeft.resize(iNbDet);
+  fhRpcDigiTotRight.resize(iNbDet);
+  fhRpcDigiTotDiff.resize(iNbDet);
+  fhRpcDigiTotMap.resize(iNbDet);
   fhRpcCluMul.resize(iNbDet);
   fhRpcCluRate.resize(iNbDet);
   fhRpcCluRate10s.resize(iNbDet);
@@ -1338,9 +1466,6 @@ Bool_t CbmTofEventClusterizer::CreateHistos()
   fhRpcDTLastHits_Tot.resize(iNbDet);
   fhRpcDTLastHits_CluSize.resize(iNbDet);
 
-  if (fTotMax != 0.) fdTOTMax = fTotMax;
-  if (fTotMin != 0.) fdTOTMin = fTotMin;
-
   for (Int_t iDetIndx = 0; iDetIndx < iNbDet; iDetIndx++) {
     Int_t iUniqueId = fDigiBdfPar->GetDetUId(iDetIndx);
 
@@ -1459,6 +1584,25 @@ Bool_t CbmTofEventClusterizer::CreateHistos()
       Form("cl_SmT%01d_sm%03d_rpc%03d_GloPos", iSmType, iSmId, iRpcId),
       Form("Clu global position of Rpc #%03d in Sm %03d of type %d; xpos [cm]; ypos [cm]", iRpcId, iSmId, iSmType), 200,
       -100, 100, 200, -100, 100);
+    fhRpcDigiTotLeft[iDetIndx] =
+      new TH2D(Form("cl_SmT%01d_sm%03d_rpc%03d_Tot_Left", iSmType, iSmId, iRpcId),
+               Form("Digi Tot of Rpc #%03d in Sm %03d of type %d; Tot; ypos [cm]", iRpcId, iSmId, iSmType), 100,
+               fdTOTMin, fdTOTMax, 99, -YDMAX, YDMAX);
+
+    fhRpcDigiTotRight[iDetIndx] =
+      new TH2D(Form("cl_SmT%01d_sm%03d_rpc%03d_Tot_Right", iSmType, iSmId, iRpcId),
+               Form("Digi Tot of Rpc #%03d in Sm %03d of type %d; Tot; ypos [cm]", iRpcId, iSmId, iSmType), 100,
+               fdTOTMin, fdTOTMax, 99, -YDMAX, YDMAX);
+
+    fhRpcDigiTotDiff[iDetIndx] =
+      new TH2D(Form("cl_SmT%01d_sm%03d_rpc%03d_Tot_Diff", iSmType, iSmId, iRpcId),
+               Form("Digi Tot of Rpc #%03d in Sm %03d of type %d; Tot; ypos [cm]", iRpcId, iSmId, iSmType), 200,
+               fdTOTMax, fdTOTMax, 99, -YDMAX, YDMAX);
+
+    fhRpcDigiTotMap[iDetIndx] = new TH2D(
+      Form("cl_SmT%01d_sm%03d_rpc%03d_Tot_Map", iSmType, iSmId, iRpcId),
+      Form("Digi Tot left vs Tot right of Rpc #%03d in Sm %03d of type %d; Tot; ypos [cm]", iRpcId, iSmId, iSmType),
+      100, 0, fdTOTMax, 100, 0, fdTOTMax);
 
     fhRpcCluPositionEvol[iDetIndx] = new TProfile(Form("cl_SmT%01d_sm%03d_rpc%03d_PosEvol", iSmType, iSmId, iRpcId),
                                                   Form("Clu position of Rpc #%03d in Sm %03d of type %d; Analysis Time "
@@ -1830,6 +1974,7 @@ Bool_t CbmTofEventClusterizer::CreateHistos()
                               "from a single TofPoint; tMcPoint -tTofHit [ps]",
                               2000, 0.0, 50.0, 2000, 0.0, 50.0);
   }  // else of if( kTRUE == fDigiBdfPar->ClustUseTrackId() )
+  /*
   fhClusterSize = new TH1I("Clus_ClusterSize", "Cluster Size distribution; Cluster Size [Strips]", 100, 0.5, 100.5);
   fhClusterSizeType =
     new TH2I("Clus_ClusterSizeType",
@@ -1856,9 +2001,9 @@ Bool_t CbmTofEventClusterizer::CreateHistos()
     fhMultiTrkProbPos = new TH2D("Clus_MultiTrkProbPos",
                                  "Probability of having a cluster with multiple tracks as "
                                  "function of position; X [cm]; Y [cm]; Prob. [%]",
-                                 1500, -750, 750, 1000, -500, 500);
+                                 1500, -750, 750, 1000, -500, 500); 
   }  // if( kTRUE == fDigiBdfPar->ClustUseTrackId() )
-
+  */
   gDirectory->cd(oldir->GetPath());  // <= To prevent histos from being sucked in by the param file of the TRootManager!
 
   return kTRUE;
@@ -1867,6 +2012,7 @@ Bool_t CbmTofEventClusterizer::CreateHistos()
 Bool_t CbmTofEventClusterizer::FillHistos(CbmEvent* tEvent)
 {
   fhClustBuildTime->Fill(fStop.GetSec() - fStart.GetSec() + (fStop.GetNanoSec() - fStart.GetNanoSec()) / 1e9);
+  fhClustHitsDigi->Fill(fTofCalDigiVec->size(), fTofHitsColl->GetEntriesFast());
 
   if (fDutId < 0) return kTRUE;
 
@@ -1980,7 +2126,8 @@ Bool_t CbmTofEventClusterizer::FillHistos(CbmEvent* tEvent)
         //LOG(debug)<<"TimeAna "<<StartAnalysisTime<<", "<< pHit->GetTime()<<", "<<dTimeAna;
         fhRpcCluRate[iDetIndx]->Fill(dTimeAna, 1. / fhRpcCluRate[iDetIndx]->GetBinWidth(1));
 
-        // deal with spill structure
+        // deal with spill structures
+
         Double_t dTimeAna10s = pHit->GetTime() + dTsStartTime - fdStartAna10s;
         if (iHitInd == 0) {
           fhEvCluMul->Fill(dTimeAna, dCluMul);
@@ -2337,7 +2484,6 @@ Bool_t CbmTofEventClusterizer::FillHistos(CbmEvent* tEvent)
             uTriggerPattern |= (0x1 << (iSel * 3 + CbmTofAddress::GetRpcId(pTrig[iSel]->GetAddress() & DetMask)));
           }
       }
-
       LOG(debug1) << "Inspect trigger pattern";
       for (Int_t iSel = 0; iSel < iNSel; iSel++) {
         if (BSel[iSel]) {
@@ -2389,7 +2535,7 @@ Bool_t CbmTofEventClusterizer::FillHistos(CbmEvent* tEvent)
         continue;
       }
       /*TGeoNode *fNode=*/  // prepare global->local trafo
-      gGeoManager->FindNode(fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ());
+      //gGeoManager->FindNode(fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ());
 
       LOG(debug1) << "Hit info: "
                   << Form(" 0x%08x %d %f %f %f %f %f %d", iChId, iCh, pHit->GetX(), pHit->GetY(), pHit->GetTime(),
@@ -2400,12 +2546,14 @@ Bool_t CbmTofEventClusterizer::FillHistos(CbmEvent* tEvent)
       hitpos[1] = pHit->GetY();
       hitpos[2] = pHit->GetZ();
       Double_t hitpos_local[3];
-      TGeoNode* cNode = gGeoManager->GetCurrentNode();
-      gGeoManager->MasterToLocal(hitpos, hitpos_local);
+      //TGeoNode* cNode = gGeoManager->GetCurrentNode();
+      fCellIdGeoMap[iChId]->GetMatrix()->MasterToLocal(hitpos, hitpos_local);
+      /*
       LOG(debug1) << Form(" MasterToLocal for %d, %d%d%d, node %p: "
                           "(%6.1f,%6.1f,%6.1f) ->(%6.1f,%6.1f,%6.1f)",
                           iDetIndx, iSmType, iSm, iRpc, cNode, hitpos[0], hitpos[1], hitpos[2], hitpos_local[0],
                           hitpos_local[1], hitpos_local[2]);
+      */
       Bool_t bFillPos = kTRUE;
       //if( fCalMode/10 > 4 && pHit->GetClusterSize() < 3 ) bFillPos=kFALSE;
       if (bFillPos) {
@@ -2511,6 +2659,11 @@ Bool_t CbmTofEventClusterizer::FillHistos(CbmEvent* tEvent)
           CbmTofDigi* pDigS1 = pDig1;
           if (iS1 == 0) pDigS1 = pDig0;
 
+          fhRpcDigiTotLeft[iDetIndx]->Fill(pDigS0->GetTot(), hitpos_local[1]);
+          fhRpcDigiTotRight[iDetIndx]->Fill(pDigS1->GetTot(), hitpos_local[1]);
+          fhRpcDigiTotDiff[iDetIndx]->Fill(pDigS0->GetTot() - pDigS1->GetTot(), hitpos_local[1]);
+          fhRpcDigiTotMap[iDetIndx]->Fill(pDigS0->GetTot(), pDigS1->GetTot());
+
           if (iCh0 != iCh1 || iS0 == iS1) {
             LOG(error) << Form(" MT2 for Tofhit %d in iDetIndx %d, Ch %d from "
                                "in event %d, ",
@@ -2834,46 +2987,47 @@ Bool_t CbmTofEventClusterizer::FillHistos(CbmEvent* tEvent)
       }
     }  // iHitInd hit loop end
 
-    for (Int_t iSmType = 0; iSmType < fDigiBdfPar->GetNbSmTypes(); iSmType++) {
-      for (Int_t iRpc = 0; iRpc < fDigiBdfPar->GetNbRpc(iSmType); iRpc++) {
-        LOG(debug1) << "CbmTofEventClusterizer::FillHistos:  "
-                    << Form(" %3d %3d %3lu ", iSmType, iRpc, fviClusterSize[iSmType][iRpc].size());
+    if (false)
+      for (Int_t iSmType = 0; iSmType < fDigiBdfPar->GetNbSmTypes(); iSmType++) {
+        for (Int_t iRpc = 0; iRpc < fDigiBdfPar->GetNbRpc(iSmType); iRpc++) {
+          LOG(debug1) << "CbmTofEventClusterizer::FillHistos:  "
+                      << Form(" %3d %3d %3lu ", iSmType, iRpc, fviClusterSize[iSmType][iRpc].size());
 
-        for (UInt_t uCluster = 0; uCluster < fviClusterSize[iSmType][iRpc].size(); uCluster++) {
-          LOG(debug2) << "CbmTofEventClusterizer::FillHistos:  " << Form(" %3d %3d %3d ", iSmType, iRpc, uCluster);
+          for (UInt_t uCluster = 0; uCluster < fviClusterSize[iSmType][iRpc].size(); uCluster++) {
+            LOG(debug2) << "CbmTofEventClusterizer::FillHistos:  " << Form(" %3d %3d %3d ", iSmType, iRpc, uCluster);
 
-          fhClusterSize->Fill(fviClusterSize[iSmType][iRpc][uCluster]);
-          fhClusterSizeType->Fill(fviClusterSize[iSmType][iRpc][uCluster],
-                                  40 * iSmType + iRpc);  //FIXME - hardwired constant
-          if (kFALSE)                                    // kTRUE == fDigiBdfPar->ClustUseTrackId() )
-          {
-            fhTrackMul->Fill(fviTrkMul[iSmType][iRpc][uCluster]);
-            fhClusterSizeMulti->Fill(fviClusterSize[iSmType][iRpc][uCluster], fviTrkMul[iSmType][iRpc][uCluster]);
-            if (1 == fviTrkMul[iSmType][iRpc][uCluster])
-              fhTrk1MulPos->Fill(fvdX[iSmType][iRpc][uCluster], fvdY[iSmType][iRpc][uCluster]);
-            if (1 < fviTrkMul[iSmType][iRpc][uCluster])
-              fhHiTrkMulPos->Fill(fvdX[iSmType][iRpc][uCluster], fvdY[iSmType][iRpc][uCluster]);
-            fhAllTrkMulPos->Fill(fvdX[iSmType][iRpc][uCluster], fvdY[iSmType][iRpc][uCluster]);
-          }            // if( kTRUE == fDigiBdfPar->ClustUseTrackId() )
-          if (kFALSE)  //  1 == fviTrkMul[iSmType][iRpc][uCluster] )
-          {
-            fhClustSizeDifX->Fill(fviClusterSize[iSmType][iRpc][uCluster], fvdDifX[iSmType][iRpc][uCluster]);
-            fhClustSizeDifY->Fill(fviClusterSize[iSmType][iRpc][uCluster], fvdDifY[iSmType][iRpc][uCluster]);
-            if (1 == fviClusterSize[iSmType][iRpc][uCluster]) {
-              fhChDifDifX->Fill(fvdDifCh[iSmType][iRpc][uCluster], fvdDifX[iSmType][iRpc][uCluster]);
-              fhChDifDifY->Fill(fvdDifCh[iSmType][iRpc][uCluster], fvdDifY[iSmType][iRpc][uCluster]);
+            fhClusterSize->Fill(fviClusterSize[iSmType][iRpc][uCluster]);
+            fhClusterSizeType->Fill(fviClusterSize[iSmType][iRpc][uCluster],
+                                    40 * iSmType + iRpc);  //FIXME - hardwired constant
+            if (kFALSE)                                    // kTRUE == fDigiBdfPar->ClustUseTrackId() )
+            {
+              fhTrackMul->Fill(fviTrkMul[iSmType][iRpc][uCluster]);
+              fhClusterSizeMulti->Fill(fviClusterSize[iSmType][iRpc][uCluster], fviTrkMul[iSmType][iRpc][uCluster]);
+              if (1 == fviTrkMul[iSmType][iRpc][uCluster])
+                fhTrk1MulPos->Fill(fvdX[iSmType][iRpc][uCluster], fvdY[iSmType][iRpc][uCluster]);
+              if (1 < fviTrkMul[iSmType][iRpc][uCluster])
+                fhHiTrkMulPos->Fill(fvdX[iSmType][iRpc][uCluster], fvdY[iSmType][iRpc][uCluster]);
+              fhAllTrkMulPos->Fill(fvdX[iSmType][iRpc][uCluster], fvdY[iSmType][iRpc][uCluster]);
+            }            // if( kTRUE == fDigiBdfPar->ClustUseTrackId() )
+            if (kFALSE)  //  1 == fviTrkMul[iSmType][iRpc][uCluster] )
+            {
+              fhClustSizeDifX->Fill(fviClusterSize[iSmType][iRpc][uCluster], fvdDifX[iSmType][iRpc][uCluster]);
+              fhClustSizeDifY->Fill(fviClusterSize[iSmType][iRpc][uCluster], fvdDifY[iSmType][iRpc][uCluster]);
+              if (1 == fviClusterSize[iSmType][iRpc][uCluster]) {
+                fhChDifDifX->Fill(fvdDifCh[iSmType][iRpc][uCluster], fvdDifX[iSmType][iRpc][uCluster]);
+                fhChDifDifY->Fill(fvdDifCh[iSmType][iRpc][uCluster], fvdDifY[iSmType][iRpc][uCluster]);
+              }
             }
-          }
-        }  // for( UInt_t uCluster = 0; uCluster < fviClusterSize[iSmType][iRpc].size(); uCluster++ )
-        fviClusterSize[iSmType][iRpc].clear();
-        fviTrkMul[iSmType][iRpc].clear();
-        fvdX[iSmType][iRpc].clear();
-        fvdY[iSmType][iRpc].clear();
-        fvdDifX[iSmType][iRpc].clear();
-        fvdDifY[iSmType][iRpc].clear();
-        fvdDifCh[iSmType][iRpc].clear();
-      }  // for( Int_t iRpc = 0; iRpc < fDigiBdfPar->GetNbRpc( iSmType); iRpc++ )
-    }
+          }  // for( UInt_t uCluster = 0; uCluster < fviClusterSize[iSmType][iRpc].size(); uCluster++ )
+          fviClusterSize[iSmType][iRpc].clear();
+          fviTrkMul[iSmType][iRpc].clear();
+          fvdX[iSmType][iRpc].clear();
+          fvdY[iSmType][iRpc].clear();
+          fvdDifX[iSmType][iRpc].clear();
+          fvdDifY[iSmType][iRpc].clear();
+          fvdDifCh[iSmType][iRpc].clear();
+        }  // for( Int_t iRpc = 0; iRpc < fDigiBdfPar->GetNbRpc( iSmType); iRpc++ )
+      }
     fhNbSameSide->Fill(fiNbSameSide);
   }  // if(0<iNbTofHits) end
 
@@ -3777,16 +3931,16 @@ Bool_t CbmTofEventClusterizer::WriteHistos()
                                     fvCPTOff[iSmType][iSm * iNbRpc + iRpc][iCh][1]);
               }
               /*
-					 Double_t TotMean=((TProfile *)htempTot_pfx)->GetBinContent(iCh+1);
-					 if(0.001 < TotMean){
-					 fvCPTotGain[iSmType][iSm*iNbRpc+iRpc][iCh][0] *= fdTTotMean / TotMean;
-					 fvCPTotGain[iSmType][iSm*iNbRpc+iRpc][iCh][1] *= fdTTotMean / TotMean;
-					 }
-					 */
+					    Double_t TotMean=((TProfile *)htempTot_pfx)->GetBinContent(iCh+1);
+					    if(0.001 < TotMean){
+					    fvCPTotGain[iSmType][iSm*iNbRpc+iRpc][iCh][0] *= fdTTotMean / TotMean;
+					    fvCPTotGain[iSmType][iSm*iNbRpc+iRpc][iCh][1] *= fdTTotMean / TotMean;
+					    }
+					    */
               if (fCalMode < 90)  // keep digi TOT calibration in last step
                 for (Int_t iSide = 0; iSide < 2; iSide++) {
                   Int_t ib  = iCh * 2 + 1 + iSide;
-                  TH1* hbin = htempTot->ProjectionY(Form("bin%d", ib), ib, ib);
+                  TH1* hbin = htempTot->ProjectionY(Form("%s_bin%d", htempTot->GetName(), ib), ib, ib);
                   if (100 > hbin->GetEntries()) continue;  //request min number of entries
                   /*            Double_t Ymax=hbin->GetMaximum();*/
                   Int_t iBmax   = hbin->GetMaximumBin();
@@ -3800,6 +3954,38 @@ Bool_t CbmTofEventClusterizer::WriteHistos()
                   }
                   //            Double_t TotMean=htempTot_Mean->GetBinContent(ib);
                   Double_t TotMean = hbin->GetMean();
+                  Double_t dCtsTot = hbin->GetEntries();
+                  if (dCtsTot > WalkNHmin) {
+                    if (iBmax == 0) {
+                      if (hbin->GetBinContent(hbin->GetNbinsX() > 0))
+                        TotMean = xaxis->GetBinCenter(hbin->GetNbinsX() - 1);
+                      LOG(info) << "TotInvalid " << hbin->GetName() << ": " << TotMean;
+                    }
+                    double dFMean = hbin->GetBinCenter(iBmax);
+                    double dFLim  = dFMean * 0.5;  // CAUTION, hardcoded parameter
+                    LOG(info) << Form("FitTot TSRC %d%d%d%2d:  Mean %6.2f, Width %6.2f ", iSmType, iSm, iRpc, ib,
+                                      dFMean, dFLim);
+                    if (dFMean > 2.) {
+                      TFitResultPtr fRes = hbin->Fit("gaus", "SQM", "", dFMean - dFLim, dFMean + dFLim);
+                      if (gMinuit->fCstatu.Contains("OK") || gMinuit->fCstatu.Contains("CONVERGED")) {
+                        TotMean = fRes->Parameter(1);  //overwrite mean
+                      }
+                      else {
+                        TotMean = dFMean;
+                        LOG(warn) << "TotFitFail " << hbin->GetName() << ": " << TotMean << ", wid " << dFLim << ", "
+                                  << gMinuit->fCstatu;
+                      }
+                    }
+                    else {
+                      TotMean = dFMean;
+                      if (TotMean < 0.2)
+                        //if(hbin->GetBinContent(hbin->GetNbinsX()) > 0 )
+                        TotMean = xaxis->GetBinCenter(hbin->GetNbinsX() - 1);
+                      LOG(warn) << "TotooR " << hbin->GetName() << ": " << TotMean << ", gain "
+                                << fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][iSide] << ", ovfl "
+                                << hbin->GetBinContent(hbin->GetNbinsX());
+                    }
+                  }
                   if (15 == iSmType) {
                     LOG(warning) << "Gain for "
                                  << Form("SmT%01d_sm%03d_rpc%03d_Side%d: TotMean %f, prof %f, "
@@ -3824,13 +4010,17 @@ Bool_t CbmTofEventClusterizer::WriteHistos()
                 Double_t dTOff =
                   0.5
                   * (fvCPTOff[iSmType][iSm * iNbRpc + iRpc][iCh][0] + fvCPTOff[iSmType][iSm * iNbRpc + iRpc][iCh][1]);
+                /*  
                 Double_t dGain = 0.5
                                  * (fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][0]
                                     + fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][1]);
+                */
+                Double_t dGain0                                   = fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][0];
+                Double_t dGain1                                   = fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][1];
                 fvCPTOff[iSmType][iSm * iNbRpc + iRpc][iCh][0]    = dTOff;
                 fvCPTOff[iSmType][iSm * iNbRpc + iRpc][iCh][1]    = dTOff;
-                fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][0] = dGain;
-                fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][1] = dGain;
+                fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][0] = dGain0;
+                fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][1] = dGain1;
               }  // diamond warning end
             }    // for( Int_t iCh = 0; iCh < iNbCh; iCh++ )
           }      // iSmType selection condition
@@ -4080,7 +4270,7 @@ Bool_t CbmTofEventClusterizer::WriteHistos()
         {
           Int_t iNbRpc = fDigiBdfPar->GetNbRpc(iSmType);
           Int_t iNbCh  = fDigiBdfPar->GetNbChan(iSmType, iRpc);
-          Int_t iYCalMode = 1;
+          Int_t iYCalMode = 0;                                // FIXME hardcoded option
           if ((fCalSmAddr < 0) || (fCalSmAddr != iSmAddr)) {  // select detectors for updating offsets
             LOG(debug) << "WriteHistos (calMode==5): update Offsets and Gains, "
                           "keep Walk and DelTof for "
@@ -4543,7 +4733,7 @@ Bool_t CbmTofEventClusterizer::WriteHistos()
       //       fhTSmCluTOff[iS][iSel]->Write();
       //       fhTSmCluTRun[iS][iSel]->Write();
     }
-  }  // iFindT0 loop end
+  }
 
   /// Restore old global file and folder pointer to avoid messing with FairRoot
   gFile      = oldFile;
@@ -4600,6 +4790,7 @@ Bool_t CbmTofEventClusterizer::BuildClusters()
     return kFALSE;
   }
   fiNevtBuild++;
+
   LOG(debug) << "Build clusters from "
              //            <<fTofDigisColl->GetEntriesFast()<<" digis in event "<<fiNevtBuild;
              << fTofDigiVec.size() << " digis in event " << fiNevtBuild;
@@ -4841,8 +5032,7 @@ Bool_t CbmTofEventClusterizer::BuildClusters()
     // Then loop over the digis array and store the Digis in separate vectors for
     // each RPC modules
 
-
-    //      iNbTofDigi = fTofCalDigisColl->GetEntriesFast();
+    // iNbTofDigi = fTofCalDigisColl->GetEntriesFast();
     iNbTofDigi = fTofCalDigiVec->size();
     for (Int_t iDigInd = 0; iDigInd < iNbTofDigi; iDigInd++) {
       //         pDigi = (CbmTofDigi*) fTofCalDigisColl->At( iDigInd );
@@ -4915,8 +5105,9 @@ Bool_t CbmTofEventClusterizer::BuildClusters()
         }
       }
     }
-    BuildHits();
 
+    BuildHits();
+    CalibHits();
   }  // if( kTRUE ) obsolete )
 
   return kTRUE;
@@ -5234,8 +5425,21 @@ Bool_t CbmTofEventClusterizer::AddNextChan(Int_t iSmType, Int_t iSm, Int_t iRpc,
           CbmTofDetectorInfo xDetInfo(ECbmModuleId::kTof, iSmType, iSm, iRpc, 0, iCh);
           iChId        = fTofId->SetDetectorInfo(xDetInfo);
           fChannelInfo = fDigiPar->GetCell(iChId);
-          gGeoManager->FindNode(fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ());
-
+          if (iChId == 0x13800036) {
+            const double local[3] = {3 * 0};
+            double global[3];
+            fCellIdGeoMap[iChId]->GetMatrix()->LocalToMaster(local, global);
+            LOG(info) << "GeoTest1: " << global[0] << ", " << global[1] << ", " << global[2];
+          }
+          //gGeoManager->FindNode(fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ()); //needed, why?
+          if (iChId == 0x13800036) {
+            TGeoHMatrix* pMatrix  = gGeoManager->GetCurrentMatrix();
+            const double local[3] = {3 * 0};
+            double global[3];
+            pMatrix->LocalToMaster(local, global);
+            LOG(info) << "GeoTest2: " << global[0] << ", " << global[1] << ", " << global[2];
+            if (fiNbHits == 10) LOG(fatal) << " for inspection";
+          }
           Double_t dTimeDif = xDigiA->GetTime() - xDigiB->GetTime();
           Double_t dPosY    = 0.;
           if (1 == xDigiA->GetSide()) dPosY = fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc) * dTimeDif * 0.5;
@@ -5302,18 +5506,21 @@ Bool_t CbmTofEventClusterizer::AddNextChan(Int_t iSmType, Int_t iSm, Int_t iRpc,
 	 }
 	 */
   Double_t hitpos[3] = {3 * 0.};
-  if (5 != iSmType) {  // Diamond beam counter always at (0,0,0)
-    /*TGeoNode*    cNode   = */ gGeoManager->GetCurrentNode();
-    /*TGeoHMatrix* cMatrix = */ gGeoManager->GetCurrentMatrix();
-    gGeoManager->LocalToMaster(hitpos_local, hitpos);
-  }
-  TVector3 hitPos(hitpos[0], hitpos[1], hitpos[2]);
-  TVector3 hitPosErr(0.5, 0.5, 0.5);  // FIXME including positioning uncertainty
   Int_t iChm = floor(dLastPosX / fChannelInfo->GetSizex()) + iNbCh / 2;
   if (iChm < 0) iChm = 0;
   if (iChm > iNbCh - 1) iChm = iNbCh - 1;
   iDetId = CbmTofAddress::GetUniqueAddress(iSm, iRpc, iChm, 0, iSmType);
 
+  if (5 != iSmType) {  // Diamond beam counter always at (0,0,0)
+    fCellIdGeoMap[iDetId]->GetMatrix()->LocalToMaster(hitpos_local, hitpos);
+    /*TGeoNode*    cNode   = */  // gGeoManager->GetCurrentNode();
+    /*TGeoHMatrix* cMatrix = */  // gGeoManager->GetCurrentMatrix();
+    //gGeoManager->LocalToMaster(hitpos_local, hitpos);
+  }
+  TVector3 hitPos(hitpos[0], hitpos[1], hitpos[2]);
+  TVector3 hitPosErr(0.5, 0.5, 0.5);  // FIXME including positioning uncertainty
+
+
   Int_t iNbChanInHit = vDigiIndRef.size() / 2;
 
   TString cstr = "Save A-Hit ";
@@ -5483,7 +5690,7 @@ Bool_t CbmTofEventClusterizer::BuildHits()
                         << Form(" %3d %3d %3d %3d %3d ", iSmType, iSm, iRpc, fDigiBdfPar->GetChanOrient(iSmType, iRpc),
                                 iNbCh);
 
-            if (1 == fDigiBdfPar->GetChanOrient(iSmType, iRpc)) {
+            if (0) {  //1 == fDigiBdfPar->GetChanOrient(iSmType, iRpc)) { // option disabled, used in Calibrator
               // Horizontal strips => X comes from left right time difference
             }       // if( 1 == fDigiBdfPar->GetChanOrient( iSmType, iRpc ) )
             else {  // Vertical strips => Y comes from bottom top time difference
@@ -5569,27 +5776,34 @@ Bool_t CbmTofEventClusterizer::BuildHits()
                   /* Int_t iLastChId = iChId; // Save Last hit channel*/
 
                   // 2 Digis = both sides present
-                  CbmTofDetectorInfo xDetInfo(ECbmModuleId::kTof, iSmType, iSm, iRpc, 0, iCh);
-                  iChId          = fTofId->SetDetectorInfo(xDetInfo);
-                  Int_t iUCellId = CbmTofAddress::GetUniqueAddress(iSm, iRpc, iCh, 0, iSmType);
+                  //CbmTofDetectorInfo xDetInfo(ECbmModuleId::kTof, iSmType, iSm, iRpc, 0, iCh);
+                  //iChId          = fTofId->SetDetectorInfo(xDetInfo);
+                  iChId = CbmTofAddress::GetUniqueAddress(iSm, iRpc, iCh, 0, iSmType);
+                  /*
                   LOG(debug1) << Form(" TSRC %d%d%d%d size %3lu ", iSmType, iSm, iRpc, iCh,
                                       fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size())
                               << Form(" ChId: 0x%08x 0x%08x ", iChId, iUCellId);
+                  */
                   fChannelInfo = fDigiPar->GetCell(iChId);
 
                   if (NULL == fChannelInfo) {
-                    LOG(error) << "CbmTofEventClusterizer::BuildClusters: no "
-                                  "geometry info! "
-                               << Form(" %3d %3d %3d %3d 0x%08x 0x%08x ", iSmType, iSm, iRpc, iCh, iChId, iUCellId);
+                    LOG(error) << "CbmTofEventClusterizer::BuildClusters: no geometry info! "
+                               << Form(" %3d %3d %3d %3d 0x%08x", iSmType, iSm, iRpc, iCh, iChId);
                     break;
                   }
 
-                  TGeoNode* fNode =  // prepare local->global trafo
-                    gGeoManager->FindNode(fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ());
+                  //TGeoNode* fNode =  // prepare local->global trafo
+                  //gGeoManager->FindNode(fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ()); //needed for position spectra, why?
+                  if (iChId == 0x13800036) {
+                    const double local[3] = {3 * 0};
+                    double global[3];
+                    fCellIdGeoMap[iChId]->GetMatrix()->LocalToMaster(local, global);
+                    LOG(info) << "GeoTest3: " << global[0] << ", " << global[1] << ", " << global[2];
+                  } /*
                   LOG(debug2) << Form(" Node at (%6.1f,%6.1f,%6.1f) : %p", fChannelInfo->GetX(), fChannelInfo->GetY(),
                                       fChannelInfo->GetZ(), fNode);
                   //          fNode->Print();
-
+                  */
                   CbmTofDigi* xDigiA = fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][0];
                   CbmTofDigi* xDigiB = fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][1];
 
@@ -5746,12 +5960,12 @@ Bool_t CbmTofEventClusterizer::BuildHits()
 											 */
                       Double_t hitpos[3] = {3 * 0.};
                       if (5 != iSmType) {
-                        /*TGeoNode*    cNode   =*/gGeoManager->GetCurrentNode();
-                        /*TGeoHMatrix* cMatrix =*/gGeoManager->GetCurrentMatrix();
+                        fCellIdGeoMap[iChId]->GetMatrix()->LocalToMaster(hitpos_local, hitpos);
+                        /*TGeoNode*    cNode   =*/  //gGeoManager->GetCurrentNode();
+                        /*TGeoHMatrix* cMatrix =*/  //gGeoManager->GetCurrentMatrix();
                         //cNode->Print();
                         //cMatrix->Print();
-
-                        gGeoManager->LocalToMaster(hitpos_local, hitpos);
+                        //gGeoManager->LocalToMaster(hitpos_local, hitpos);
                       }
                       LOG(debug1) << Form(" LocalToMaster: (%6.1f,%6.1f,%6.1f) "
                                           "->(%6.1f,%6.1f,%6.1f)",
@@ -5879,12 +6093,13 @@ Bool_t CbmTofEventClusterizer::BuildHits()
                       }
 
                       fiNbHits++;
-                      // For Histogramming
+                      // For Histogramming, vectors are cleared in FillHistos!
+                      /*
                       fviClusterSize[iSmType][iRpc].push_back(iNbChanInHit);
                       //fviTrkMul[iSmType][iRpc].push_back( vPtsRef.size() );
                       fvdX[iSmType][iRpc].push_back(dWeightedPosX);
                       fvdY[iSmType][iRpc].push_back(dWeightedPosY);
-                      /*  no TofPoint available for data!
+                      //  no TofPoint available for data!
 											 fvdDifX[iSmType][iRpc].push_back( vPtsRef[0]->GetX() - dWeightedPosX);
 											 fvdDifY[iSmType][iRpc].push_back( vPtsRef[0]->GetY() - dWeightedPosY);
 											 fvdDifCh[iSmType][iRpc].push_back( fGeoHandler->GetCell( vPtsRef[0]->GetDetectorID() ) -1 -iLastChan );
@@ -6000,7 +6215,7 @@ Bool_t CbmTofEventClusterizer::BuildHits()
             LOG(debug1) << "Process cluster " << iNbChanInHit;
 
             // Check orientation to properly assign errors
-            if (1 == fDigiBdfPar->GetChanOrient(iSmType, iRpc)) {
+            if (0) {  // 1 == fDigiBdfPar->GetChanOrient(iSmType, iRpc)) {  //option disabled, LRF fixed
               LOG(debug1) << "H-Hit ";
             }  // if( 1 == fDigiBdfPar->GetChanOrient( iSmType, iRpc ) )
             else {
@@ -6024,11 +6239,12 @@ Bool_t CbmTofEventClusterizer::BuildHits()
 							 */
               Double_t hitpos[3] = {3 * 0.};
               if (5 != iSmType) {
-                /*TGeoNode*       cNode=*/gGeoManager->GetCurrentNode();
-                /*TGeoHMatrix* cMatrix =*/gGeoManager->GetCurrentMatrix();
+                fCellIdGeoMap[iChId]->GetMatrix()->LocalToMaster(hitpos_local, hitpos);
+                /*TGeoNode*       cNode=*/  //gGeoManager->GetCurrentNode();
+                /*TGeoHMatrix* cMatrix =*/  //gGeoManager->GetCurrentMatrix();
                 //cNode->Print();
                 //cMatrix->Print();
-                gGeoManager->LocalToMaster(hitpos_local, hitpos);
+                //gGeoManager->LocalToMaster(hitpos_local, hitpos);
               }
               LOG(debug1) << Form(" LocalToMaster for V-node: "
                                   "(%6.1f,%6.1f,%6.1f) ->(%6.1f,%6.1f,%6.1f)",
@@ -6111,11 +6327,11 @@ Bool_t CbmTofEventClusterizer::BuildHits()
 
               fiNbHits++;
               // For Histogramming
+              /*
               fviClusterSize[iSmType][iRpc].push_back(iNbChanInHit);
               //fviTrkMul[iSmType][iRpc].push_back( vPtsRef.size() );
               fvdX[iSmType][iRpc].push_back(dWeightedPosX);
               fvdY[iSmType][iRpc].push_back(dWeightedPosY);
-              /*
 							 fvdDifX[iSmType][iRpc].push_back( vPtsRef[0]->GetX() - dWeightedPosX);
 							 fvdDifY[iSmType][iRpc].push_back( vPtsRef[0]->GetY() - dWeightedPosY);
 							 fvdDifCh[iSmType][iRpc].push_back( fGeoHandler->GetCell( vPtsRef[0]->GetDetectorID() ) -1 -iLastChan );
@@ -6220,6 +6436,7 @@ Bool_t CbmTofEventClusterizer::CalibRawDigis()
       // walk correction
       Double_t dTotBinSize = (fdTOTMax - fdTOTMin) / nbClWalkBinX;
       Int_t iWx            = (Int_t)((pCalDigi->GetTot() - fdTOTMin) / dTotBinSize);
+      // LOG(info)<<"Wx: "<<pCalDigi->GetTot()<<" "<<fdTOTMin<<" "<<fdTOTMax<<" "<<dTotBinSize<<" "<<iWx;
       if (0 > iWx) iWx = 0;
       if (iWx >= nbClWalkBinX) iWx = nbClWalkBinX - 1;
       Double_t dDTot = (pCalDigi->GetTot() - fdTOTMin) / dTotBinSize - (Double_t) iWx - 0.5;
@@ -6254,9 +6471,10 @@ Bool_t CbmTofEventClusterizer::CalibRawDigis()
       pCalDigi->SetTime(pCalDigi->GetTime() - dWT);  // calibrate Digi Time
       LOG(debug2) << " CluCal-Walk: " << pCalDigi->ToString();
 
-      if (0) {  //pDigi->GetType()==8) { // && pDigi->GetSm()==0){
+      if (
+        0) {  //pCalDigi->GetType()==0 && pCalDigi->GetSm()==0 && pCalDigi->GetRpc()==2 && pCalDigi->GetChannel()==15 ){
         LOG(info)
-          << "BuildClusters: CalDigi " << Form("%02d TSRCS  ", iDigIndCal) << pCalDigi->GetType() << pCalDigi->GetSm()
+          << "CalDigi " << Form("%02d TSRCS  ", iDigIndCal) << pCalDigi->GetType() << pCalDigi->GetSm()
           << pCalDigi->GetRpc() << Form("%02d", Int_t(pCalDigi->GetChannel())) << pCalDigi->GetSide()
           << Form(", T %15.3f", pCalDigi->GetTime()) << ", Tot " << pCalDigi->GetTot() << ", TotGain "
           << fvCPTotGain[pCalDigi->GetType()][pCalDigi->GetSm() * fDigiBdfPar->GetNbRpc(pCalDigi->GetType())
@@ -6368,7 +6586,7 @@ Bool_t CbmTofEventClusterizer::CalibRawDigis()
   return kTRUE;
 }
 
-void CbmTofEventClusterizer::SetDeadStrips(Int_t iDet, Int_t ival)
+void CbmTofEventClusterizer::SetDeadStrips(Int_t iDet, UInt_t ival)
 {
   if (fvDeadStrips.size() < static_cast<size_t>(iDet + 1)) fvDeadStrips.resize(iDet + 1);
   fvDeadStrips[iDet] = ival;
@@ -6395,10 +6613,13 @@ double* CbmTofEventClusterizer::find_yedges(const char* hname, double dThr, doub
             && h1->GetBinContent(iBin + 2) > dLev) {
           iBl  = iBin;
           xLow = h1->GetBinCenter(iBin);
+          break;
         }
-        if (iBl > -1) {
-          if (iBh < 0 && h1->GetBinContent(iBin) < dLev && h1->GetBinContent(iBin + 1) < dLev
-              && h1->GetBinContent(iBin + 2) < dLev) {
+      }
+      if (iBl > -1) {
+        for (int iBin = h1->GetNbinsX() - 1; iBin > 3; iBin--) {
+          if (iBh < 0 && h1->GetBinContent(iBin) > dLev && h1->GetBinContent(iBin - 1) > dLev
+              && h1->GetBinContent(iBin - 2) > dLev) {
             iBh   = iBin;
             xHigh = h1->GetBinCenter(iBin);
             break;
@@ -6413,6 +6634,7 @@ double* CbmTofEventClusterizer::find_yedges(const char* hname, double dThr, doub
         dValid++;
       }
     }  // for loop end
+    if (dValid == 0) { LOG(warn) << " No valid yEdge  with thr " << dThr << " for " << h1->GetName(); }
     dRes[0] = dLength;
     dRes[1] = dMean;
   }
@@ -6433,5 +6655,104 @@ CbmTofHit* CbmTofEventClusterizer::GetHitPointer(int iHitInd)
 
 CbmMatch* CbmTofEventClusterizer::GetMatchPointer(int iHitInd)
 {
+  if (fiHitStart + iHitInd > fTofDigiMatchCollOut->GetEntriesFast()) {
+    LOG(fatal) << "Invalid Hit index " << iHitInd << ", " << fiHitStart << ", "
+               << fTofDigiMatchCollOut->GetEntriesFast();
+  }
   return (CbmMatch*) fTofDigiMatchCollOut->At(fiHitStart + iHitInd);
 }
+
+CbmMatch* CbmTofEventClusterizer::GetMatchIndexPointer(int idx)
+{
+  if (idx > fTofDigiMatchCollOut->GetEntriesFast()) {
+    LOG(fatal) << "Invalid Hit index " << idx << ", " << fTofDigiMatchCollOut->GetEntriesFast();
+  }
+  return (CbmMatch*) fTofDigiMatchCollOut->At(idx);
+}
+
+double CbmTofEventClusterizer::GetLocalX(CbmTofHit* pHit)
+{
+  Int_t iChId = pHit->GetAddress();
+  Double_t hitpos[3];
+  Double_t hitpos_local[3] = {3 * 0.};
+  hitpos[0]                = pHit->GetX();
+  hitpos[1]                = pHit->GetY();
+  hitpos[2]                = pHit->GetZ();
+  fChannelInfo             = fDigiPar->GetCell(iChId);
+  Int_t iCh                = CbmTofAddress::GetChannelId(iChId);
+  if (NULL == fChannelInfo) {
+    LOG(fatal) << "Invalid Channel Pointer for ChId " << Form(" 0x%08x ", iChId) << ", Ch " << iCh;
+  }
+  //gGeoManager->FindNode(fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ());
+  /*
+  gGeoManager->MasterToLocal(hitpos,hitpos_local);  //  transform into local frame 
+  */
+  fCellIdGeoMap[iChId]->GetMatrix()->MasterToLocal(hitpos, hitpos_local);
+  return hitpos_local[0];
+}
+
+double CbmTofEventClusterizer::GetLocalY(CbmTofHit* pHit)
+{
+  Int_t iChId = pHit->GetAddress();
+  Double_t hitpos[3];
+  Double_t hitpos_local[3] = {3 * 0.};
+  hitpos[0]                = pHit->GetX();
+  hitpos[1]                = pHit->GetY();
+  hitpos[2]                = pHit->GetZ();
+  fChannelInfo             = fDigiPar->GetCell(iChId);
+  Int_t iCh                = CbmTofAddress::GetChannelId(iChId);
+  if (NULL == fChannelInfo) {
+    LOG(fatal) << "Invalid Channel Pointer for ChId " << Form(" 0x%08x ", iChId) << ", Ch " << iCh;
+  }
+  //gGeoManager->FindNode(fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ());
+  /*
+  gGeoManager->MasterToLocal(hitpos,hitpos_local);  //  transform into local frame 
+  */
+  fCellIdGeoMap[iChId]->GetMatrix()->MasterToLocal(hitpos, hitpos_local);
+  return hitpos_local[1];
+}
+
+void CbmTofEventClusterizer::MasterToLocal(const int iChId, const double* global, double* local)
+{
+  fCellIdGeoMap[iChId]->GetMatrix()->MasterToLocal(global, local);
+}
+
+static int iLogCal = 0;
+Bool_t CbmTofEventClusterizer::CalibHits()
+{
+  // correct Y position dependence of arrival time
+  for (Int_t iHitInd = 0; iHitInd < fTofHitsColl->GetEntriesFast(); iHitInd++) {
+    CbmTofHit* pHit = (CbmTofHit*) fTofHitsColl->At(iHitInd);
+    if (NULL == pHit) continue;
+
+    Int_t iDetId  = (pHit->GetAddress() & DetMask);
+    Int_t iSmType = CbmTofAddress::GetSmType(iDetId);
+    if (iSmType == 5 || iSmType == 8) continue;  //Diamond or Pads
+    Int_t iNbRpc = fDigiBdfPar->GetNbRpc(iSmType);
+    Int_t iSm    = CbmTofAddress::GetSmId(iDetId);
+    Int_t iRpc   = CbmTofAddress::GetRpcId(iDetId);
+    int iRpcInd  = iSm * iNbRpc + iRpc;
+
+    double dY       = GetLocalY(pHit);
+    double fdYRange = fvCPTOffYRange[iSmType][iRpcInd];
+    LOG(debug) << "TSR " << iSmType << iSm << iRpc << ": Y " << dY << ", " << fdYRange;
+    if (fdYRange == 0) continue;
+
+    double fdBinDy = fvCPTOffYBinWidth[iSmType][iRpcInd];
+    double dBin    = (dY + fdYRange) / fdBinDy;
+    int iBin       = floor(dBin);
+    int iBin1      = ceil(dBin);
+    double dRes    = dBin - iBin;
+    //interpolate
+    double dTcor = fvCPTOffY[iSmType][iSm * iNbRpc + iRpc][iBin];
+    dTcor += dRes * (fvCPTOffY[iSmType][iSm * iNbRpc + iRpc][iBin1] - fvCPTOffY[iSmType][iSm * iNbRpc + iRpc][iBin]);
+    if (iLogCal < 10) {
+      iLogCal++;
+      LOG(info) << "TSR " << iSmType << iSm << iRpc << ": Y " << dY << ", B " << dBin << ", " << iBin << ", " << iBin1
+                << ", " << dRes << ", TcorY " << dTcor;
+    }
+
+    pHit->SetTime(pHit->GetTime() - dTcor);
+  }
+  return kTRUE;
+}
diff --git a/reco/detectors/tof/CbmTofEventClusterizer.h b/reco/detectors/tof/CbmTofEventClusterizer.h
index b53f4d8aa2798e20db53d00f0c86c5147a9e07c1..ffa54badcf084bc854fa557bde9435a611f4925f 100644
--- a/reco/detectors/tof/CbmTofEventClusterizer.h
+++ b/reco/detectors/tof/CbmTofEventClusterizer.h
@@ -30,10 +30,15 @@ class CbmTofCell;
 class CbmTofFindTracks;
 class CbmDigiManager;
 class CbmTofCalibrator;
+class CbmTsEventHeader;
+class CbmTimeSlice;
+
 #include "CbmMatch.h"
 #include "CbmTofAddress.h"  // in cbmdata/tof
 #include "CbmTofDigi.h"
 
+#include "TGeoManager.h"
+class TimesliceMetaData;
 class TTofCalibData;
 class TTrbHeader;
 class FairEventHeader;
@@ -140,6 +145,8 @@ public:
   inline void PosYMaxScal(Double_t val) { fPosYMaxScal = val; }
   inline void SetTotMax(Double_t val) { fTotMax = val; }
   inline void SetTotMin(Double_t val) { fTotMin = val; }
+  inline double GetTotMax() { return fTotMax; }
+  inline double GetTotMin() { return fTotMin; }
   inline void SetTotMean(Double_t val) { fTotMean = val; }
   inline void SetDelTofMax(Double_t val) { fdDelTofMax = val; }
   inline void SetTotPreRange(Double_t val) { fTotPreRange = val; }
@@ -152,6 +159,10 @@ public:
   inline void SetSel2Sm(Int_t ival) { fSel2Sm = ival; }
   inline void SetSel2Rpc(Int_t ival) { fSel2Rpc = ival; }
   inline void SetSel2MulMax(Int_t Id) { fSel2MulMax = Id; }
+  inline void SetCluSizeMin(Int_t iVal) { fiCluSizeMin = iVal; }
+  inline int GetCluSizeMin() { return fiCluSizeMin; }
+  inline void SetNbCalHitMin(Int_t iVal) { fNbCalHitMin = iVal; }
+  inline int GetNbCalHitMin() { return fNbCalHitMin; }
 
   inline void SetOutHstFileName(TString OutHstFileName) { fOutHstFileName = OutHstFileName; }
   inline void SetCalParFileName(TString CalParFileName) { fCalParFileName = CalParFileName; }
@@ -164,8 +175,12 @@ public:
   inline int GetNbHits() { return fiNbHits; }
   CbmTofHit* GetHitPointer(int iHit);
   CbmMatch* GetMatchPointer(int iHit);
+  CbmMatch* GetMatchIndexPointer(int idx);
   inline double GetTotMean() { return fTotMean; }
   inline int GetBeamAddr() { return fiBeamRefAddr; }
+  double GetLocalX(CbmTofHit* pHit);
+  double GetLocalY(CbmTofHit* pHit);
+  void MasterToLocal(const Int_t CellId, const Double_t* master, Double_t* local);
 
   //static Double_t  f1_xboxe(double *x, double *par); // Fit function
   virtual void fit_ybox(const char* hname);                    // Fit
@@ -184,7 +199,18 @@ public:
   void SetWriteDigisInOut(Bool_t bDigis) { fbWriteDigisInOut = bDigis; }
   void SetWriteHitsInOut(Bool_t bHits) { fbWriteHitsInOut = bHits; }
   void SetAlternativeBranchNames(Bool_t bNames) { fbAlternativeBranchNames = bNames; }
-  void SetDeadStrips(Int_t iDet, Int_t ival);
+  void SetDeadStrips(Int_t iDet, UInt_t ival);
+
+  inline void SetEdgeThr(double val) { fdEdgeThr = val; }
+  inline void SetEdgeLen(double val) { fdEdgeLen = val; }
+  inline void SetEdgeTbias(double val) { fdEdgeTbias = val; }
+  inline void SetEdgeFrange(double val) { fdEdgeFrange = val; }
+  inline double GetEdgeThr() { return fdEdgeThr; }
+  inline double GetEdgeLen() { return fdEdgeLen; }
+  inline double GetEdgeTbias() { return fdEdgeTbias; }
+  inline double GetEdgeFrange() { return fdEdgeFrange; }
+  inline void SetModifySigvel(Double_t val) { fdModifySigvel = val; }
+  inline double GetModifySigvel() { return fdModifySigvel; }
 
 protected:
 private:
@@ -238,6 +264,7 @@ private:
   Bool_t BuildHits();
   Bool_t CalibRawDigis();
   Bool_t InspectRawDigis();
+  Bool_t CalibHits();
 
   // ToF geometry variables
   CbmTofGeoHandler* fGeoHandler;
@@ -248,6 +275,8 @@ private:
 
   TTrbHeader* fTrbHeader;
   FairEventHeader* fEvtHeader;
+  const CbmTsEventHeader* fTsHeader;
+  const CbmTimeSlice* fTimeSlice;
 
   // Input variables
   const std::vector<CbmMatch>* fTofDigiPointMatches = nullptr;  // TOF MC point matches
@@ -293,6 +322,7 @@ private:
 
   // Histograms
   TH1* fhClustBuildTime;
+  TH2* fhClustHitsDigi;
   TH1* fhHitsPerTracks;
   TH1* fhPtsPerHit;
   TH1* fhTimeResSingHits;
@@ -323,6 +353,10 @@ private:
   std::vector<TH2*> fhRpcDigiDTFD;                           //[nbDet]
   std::vector<TH2*> fhRpcDigiDTMul;                          //[nbDet]
   std::vector<TH1*> fhRpcDigiRate;                           //[nbDet]
+  std::vector<TH2*> fhRpcDigiTotLeft;                        //[nbDet]
+  std::vector<TH2*> fhRpcDigiTotRight;                       //[nbDet]
+  std::vector<TH2*> fhRpcDigiTotDiff;                        //[nbDet]
+  std::vector<TH2*> fhRpcDigiTotMap;                         //[nbDet]
   std::vector<TH1*> fhRpcCluMul;                             //[nbDet]
   std::vector<TH1*> fhRpcCluRate;                            //[nbDet]
   std::vector<TH1*> fhRpcCluRate10s;                         //[nbDet]
@@ -379,9 +413,12 @@ private:
   std::vector<std::vector<std::vector<std::vector<Double_t>>>> fvCPTotOff;   //[nSMT][nRpc][nCh][nbSide]
   std::vector<std::vector<std::vector<std::vector<std::vector<Double_t>>>>>
     fvCPWalk;  //[nSMT][nRpc][nCh][nbSide][nbWalkBins]
+  std::vector<std::vector<std::vector<Double_t>>> fvCPTOffY;  //[nSMT][nRpc][nBin]
+  std::vector<std::vector<Double_t>> fvCPTOffYBinWidth;       //[nSMT][nRpc]
+  std::vector<std::vector<Double_t>> fvCPTOffYRange;          //[nSMT][nRpc]
 
   std::vector<std::vector<std::vector<std::vector<std::list<CbmTofHit*>>>>> fvLastHits;  //[nSMT[nSm][nRpc][nCh][NHits]
-  std::vector<Int_t> fvDeadStrips;                                                       //[nbDet]
+  std::vector<UInt_t> fvDeadStrips;                                                      //[nbDet]
   std::vector<std::vector<Double_t>> fvTimeLastDigi;                                     //[nbDet][nChannel*2]
   std::vector<std::vector<Double_t>> fvTimeFirstDigi;                                    //[nbDet][nChannel*2]
   std::vector<std::vector<Double_t>> fvMulDigi;                                          //[nbDet][nChannel*2]
@@ -425,8 +462,10 @@ private:
   Int_t fSel2Rpc;
   Int_t fSel2Addr;
   Int_t fSel2MulMax;
-
+  Int_t fiCluSizeMin;
+  Int_t fNbCalHitMin;
   std::map<UInt_t, UInt_t> fDetIdIndexMap;
+  std::map<UInt_t, TGeoPhysicalNode*> fCellIdGeoMap;
   std::vector<Int_t> fviDetId;
 
   Double_t fPosYMaxScal;
@@ -461,6 +500,11 @@ private:
 
   Double_t fdMaxTimeDist;   // Isn't this just a local variable? Why make it global and preset?!?
   Double_t fdMaxSpaceDist;  // Isn't this just a local variable? Why make it global and preset?!?
+  Double_t fdEdgeThr;       // for Calibrator
+  Double_t fdEdgeLen;       // for Calibrator
+  Double_t fdEdgeTbias;
+  Double_t fdEdgeFrange;
+  Double_t fdModifySigvel;
 
   Double_t fdEvent;
   Double_t fdStartAnalysisTime;
diff --git a/reco/detectors/tof/CbmTofFindTracks.cxx b/reco/detectors/tof/CbmTofFindTracks.cxx
index e3d66dfb33ee08122d47712f382c3e0349fd032b..cb9e7158bc661a3d8c33bbad0253a11e7bb7474e 100644
--- a/reco/detectors/tof/CbmTofFindTracks.cxx
+++ b/reco/detectors/tof/CbmTofFindTracks.cxx
@@ -132,12 +132,22 @@ CbmTofFindTracks::CbmTofFindTracks(const char* name, const char* /*title*/, CbmT
   , fhTrklXY0_0(NULL)
   , fhTrklXY0_1(NULL)
   , fhTrklXY0_2(NULL)
+  , fhTrklX0_TX(NULL)
+  , fhTrklY0_TX(NULL)
+  , fhTrklX0_TY(NULL)
+  , fhTrklY0_TY(NULL)
   , vhPullX()
   , vhPullY()
   , vhPullZ()
   , vhPullT()
   , vhPullTB()
   , vhTrefRms()
+  , vhFitDT0()
+  , vhFitT0Err()
+  , vhFitTt()
+  , vhFitTtErr()
+  , vhFitDTMean()
+  , vhFitDTMeanErr()
   , vhResidualTBWalk()
   , vhResidualYWalk()
   , vhXY_AllTracks()
@@ -154,7 +164,7 @@ CbmTofFindTracks::CbmTofFindTracks(const char* name, const char* /*title*/, CbmT
   , fhVTXNorm(NULL)
   , fhVTX_XY0(NULL)
   , fhVTX_DT0_Norm(NULL)
-  , fiStationStatus()
+  , fiStationStatus(0)
   , fOutHstFileName("")
   , fCalParFileName("")
   , fCalOutFileName("./tofFindTracks.hst.root")
@@ -174,11 +184,13 @@ CbmTofFindTracks::CbmTofFindTracks(const char* name, const char* /*title*/, CbmT
   , fhTOff_Smt(NULL)
   , fhTOff_Smt_Off(NULL)
   , fhDeltaTt_Smt(NULL)
+  , fhDeltaTc_Smt(NULL)
   , fhTOff_HMul2(NULL)
   , fiCorMode(0)
   , fiBeamCounter(-1)
   , fiStationMaxHMul(1000)
   , fTtTarg(30.)
+  , fTtLight(0.)
   , fdTOffScal(1.)
   , fVTXNorm(0.)
   , fVTX_T(0.)
@@ -254,9 +266,9 @@ InitStatus CbmTofFindTracks::Init()
   fEventsColl = dynamic_cast<TClonesArray*>(ioman->GetObject("Event"));
   if (!fEventsColl) fEventsColl = dynamic_cast<TClonesArray*>(ioman->GetObject("CbmEvent"));
   if (!fEventsColl) { LOG(info) << "CbmEvent not found in input file, assume eventwise input"; }
-  else {
-    fTofHitArray = new TClonesArray("CbmTofHit");
-  }
+
+  fTofHitArray = new TClonesArray("CbmTofHit");
+
 
   // Get TOF hit Array
   fTofHitArrayIn = (TClonesArray*) ioman->GetObject("TofHit");
@@ -280,14 +292,14 @@ InitStatus CbmTofFindTracks::Init()
   if (fEventsColl) {
     fTrackArrayOut  = new TClonesArray("CbmTofTracklet", 100);
     fTofHitArrayOut = new TClonesArray("CbmTofHit", 100);
-    ioman->Register("TofTracks", "TOF", fTrackArrayOut, kTRUE);
-    ioman->Register("TofCalHit", "TOF", fTofHitArrayOut, kTRUE);
+    ioman->Register("TofTracks", "TOF", fTrackArrayOut, IsOutputBranchPersistent("TofTracks"));
+    ioman->Register("TofCalHit", "TOF", fTofHitArrayOut, IsOutputBranchPersistent("TofCalHit"));
   }
   else {
-    ioman->Register("TofTracks", "TOF", fTrackArray, kTRUE);
+    ioman->Register("TofTracks", "TOF", fTrackArray, IsOutputBranchPersistent("TofTracks"));
     cout << "-I- CbmTofFindTracks::Init:TofTrack array registered" << endl;
-
-    ioman->Register("TofCalHit", "TOF", fTofHitArray, kFALSE);
+    LOG(info) << "Register TofCalHit at " << fTofHitArray;
+    ioman->Register("TofCalHit", "TOF", fTofHitArray, IsOutputBranchPersistent("TofCalHit"));
 
     // Create and register TofUHit array for unused Hits
     ioman->Register("TofUHit", "TOF", fTofUHitArray, kFALSE);
@@ -488,7 +500,7 @@ Bool_t CbmTofFindTracks::LoadCalParameter()
       new TH1F(Form("hPullT_Smt_Off"), Form("Tracklet PullT vs RpcInd ; RpcInd ; #DeltaT (ns)"), nSmt, 0, nSmt);
   }
   // Initialize Parameter
-  if (fiCorMode <= 3) {  // hidden option, FIXME
+  if (fiCorMode <= -3) {  // hidden option, FIXME, disabled
     for (Int_t iDet = 0; iDet < nSmt; iDet++) {
       std::map<Int_t, Int_t>::iterator it;
       //it = fMapRpcIdParInd.find(iDet)
@@ -506,11 +518,13 @@ Bool_t CbmTofFindTracks::LoadCalParameter()
         if (dVal == 0) {
           if (fiBeamCounter != iUniqueId) dVal = fChannelInfo->GetZ() * fTtTarg;  //  use calibration target value
           fhPullT_Smt_Off->SetBinContent(iDet + 1, dVal);
+          LOG(info) << Form("PrimInit det 0x%08x at %d, GloInd %d, z=%f to Tt %6.4f, %6.4f with TOff %6.2f", iUniqueId,
+                            iDet, iMap, fChannelInfo->GetZ(), fTtTarg, fdTOffScal, dVal);
         }
         else {
           if (fdTOffScal != 0.) fhPullT_Smt_Off->SetBinContent(iDet + 1, dVal * fdTOffScal);
         }
-        LOG(info) << Form("Initialize det 0x%08x at %d, GloInd %d, z=%f to Tt %6.4f, %6.4f with TOff %6.2f", iUniqueId,
+        LOG(info) << Form("ReInit det 0x%08x at %d, GloInd %d, z=%f to Tt %6.4f, %6.4f with TOff %6.2f", iUniqueId,
                           iDet, iMap, fChannelInfo->GetZ(), fTtTarg, fdTOffScal, dVal);
       }
     }
@@ -835,10 +849,12 @@ Bool_t CbmTofFindTracks::WriteHistos()
             if (dRMS > fSIGX * 3.0) dRMS = fSIGX * 3.;
 
             // limit maximal shift in X, for larger values, change geometry file
-            if (dVal < -3.) dVal = -3.;
-            if (dVal > 3.) dVal = 3.;
+            const double dMaxShift = 4.;
+            if (dVal < -dMaxShift) dVal = -dMaxShift;
+            if (dVal > dMaxShift) dVal = dMaxShift;
             LOG(info) << "Update hPullX_Smt_Off " << ix << ": " << fhPullX_Smt_Off->GetBinContent(ix + 1) << " + "
-                      << htmp1D->GetBinContent(ix + 1) << " -> " << dVal << ", Width " << dRMS;
+                      << htmp1D->GetBinContent(ix + 1) << ", " << fRes->Parameter(1) << " -> " << dVal << ", Width "
+                      << dRMS;
             if (fRpcAddr[ix] != fiBeamCounter)  // don't correct beam counter position
               fhPullX_Smt_Off->SetBinContent(ix + 1, dVal);
             fhPullX_Smt_Width->SetBinContent(ix + 1, dRMS);
@@ -1145,7 +1161,7 @@ void CbmTofFindTracks::Exec(Option_t* opt)
       if (fTofHitArray) fTofHitArray->Clear("C");
       Int_t iNbHits = 0;
       fTofHitIndexArray.resize(tEvent->GetNofData(ECbmDataType::kTofHit));
-      for (Int_t iHit = 0; iHit < tEvent->GetNofData(ECbmDataType::kTofHit); iHit++) {
+      for (Int_t iHit = 0; iHit < (int) tEvent->GetNofData(ECbmDataType::kTofHit); iHit++) {
         Int_t iHitIndex            = static_cast<Int_t>(tEvent->GetIndex(ECbmDataType::kTofHit, iHit));
         CbmTofHit* tHit            = dynamic_cast<CbmTofHit*>(fTofHitArrayIn->At(iHitIndex));
         fTofHitIndexArray[iNbHits] = iHitIndex;
@@ -1184,6 +1200,7 @@ void CbmTofFindTracks::ExecFind(Option_t* /*opt*/, CbmEvent* tEvent)
   if (NULL != fTofUHitArray) fTofUHitArray->Clear("C");
   if (NULL != fTrackArray) fTrackArray->Delete();  // reset
   //if (NULL != fTrackArray) fTrackArray->Clear();  // reset
+  CbmTofHit* pBeamHit = NULL;
 
   // recalibrate hits and count trackable hits
   for (Int_t iHit = 0; iHit < fTofHitArray->GetEntriesFast(); iHit++) {
@@ -1220,6 +1237,11 @@ void CbmTofFindTracks::ExecFind(Option_t* /*opt*/, CbmEvent* tEvent)
         pHit->SetPosition(hitPos);
         TVector3 hitPosErr0(1., 1., 1.);     // including positioning uncertainty
         pHit->SetPositionError(hitPosErr0);  //
+        if (NULL != pBeamHit) {
+          if (pHit->GetTime() < pBeamHit->GetTime()) pBeamHit = pHit;
+        }
+        else
+          pBeamHit = pHit;
       }
     }
 
@@ -1260,16 +1282,24 @@ void CbmTofFindTracks::ExecFind(Option_t* /*opt*/, CbmEvent* tEvent)
       LOG(fatal) << "Invalid NTofStations " << fNTofStations << ", " << fMapStationRpcId.size();
     }
 
-    LOG(debug) << Form("Exec found Hit %02d, addr 0x%08x, TSR %d%d%d, sta %02d, %02d, HM "
+    LOG(debug) << Form("ExecFind Hit %02d, addr 0x%08x, TSR %d%d%d, sta %02d, %02d, HM "
                        "%02d, X %6.2f(%3.2f) Y "
-                       "%6.2f(%3.2f)  Z %6.2f(%3.2f)  T %6.2f(%3.2f)",
+                       "%6.2f(%3.2f)  Z %6.2f(%3.2f)  T %12.2f(%3.2f)",
                        iHit, pHit->GetAddress(), CbmTofAddress::GetSmType(iDetId), CbmTofAddress::GetSmId(iDetId),
                        CbmTofAddress::GetRpcId(iDetId), GetStationOfAddr(iDetId), fDigiBdfPar->GetTrackingStation(pHit),
                        fStationHMul[GetStationOfAddr(iDetId)], pHit->GetX(), pHit->GetDx(), pHit->GetY(), pHit->GetDy(),
                        pHit->GetZ(), pHit->GetDz(), pHit->GetTime(), pHit->GetTimeError());
+
     MarkStationFired(iSt);
   }
 
+  /* call moved to Clusterizer
+  if (fiCalOpt > 99) {
+    //LOG(info) << "Call TofCalibrator with pBeam  "<<pBeamHit;
+    if (NULL != pBeamHit) fTofCalibrator->FillHitCalHist(pBeamHit, fiCalOpt, tEvent, fTofHitArrayIn); 
+  }
+  */
+
   LOG(debug) << Form("CbmTofFindTracks::Exec NStationsFired %d >= %d Min ?, NbStations %d", GetNStationsFired(),
                      GetMinNofHits(), fDigiBdfPar->GetNbTrackingStations());
 
@@ -1308,10 +1338,11 @@ void CbmTofFindTracks::ExecFind(Option_t* /*opt*/, CbmEvent* tEvent)
 void CbmTofFindTracks::Finish()
 {
   if (fiEvent < 1000) return;  // preserve calibration histos in event display
+  FairLogger::GetLogger()->SetLogScreenLevel("info");
   if (fiCalOpt > 0) fTofCalibrator->UpdateCalHist(fiCalOpt);
   if (fbDoHistos) WriteHistos();
 
-  LOG(info) << Form(" CbmTofFindTracks::Finished  ");
+  LOG(info) << Form(" CbmTofFindTracks::Finished for opt %d", fiCalOpt);
 }
 // -------------------------------------------------------------------------
 
@@ -1393,10 +1424,19 @@ void CbmTofFindTracks::CreateHistograms()
   Double_t X0MAX = 40.;
   fhTrklXY0_0    = new TH2F(Form("hTrklXY0_0"), Form("Tracklet XY at z=0 for hmulmax ; x (cm); y (cm)"), 100, -X0MAX,
                          X0MAX, 100, -X0MAX, X0MAX);
-  fhTrklXY0_1    = new TH2F(Form("hTrklXY0_1"), Form("Tracklet XY at z=0 for hmulmax-1 ; x (cm); y (cm)"), 100,
-                         -X0MAX * 2., X0MAX * 2., 100, -X0MAX * 2., X0MAX * 2.);
-  fhTrklXY0_2    = new TH2F(Form("hTrklXY0_2"), Form("Tracklet XY at z=0 for hmulmax-2 ; x (cm); y (cm)"), 100,
-                         -X0MAX * 3., X0MAX * 3., 100, -X0MAX * 3., X0MAX * 3.);
+  fhTrklXY0_1    = new TH2F(Form("hTrklXY0_1"), Form("Tracklet XY at z=0 for hmulmax-1 ; x (cm); y (cm)"), 100, -X0MAX,
+                         X0MAX, 100, -X0MAX, X0MAX);
+  fhTrklXY0_2    = new TH2F(Form("hTrklXY0_2"), Form("Tracklet XY at z=0 for hmulmax-2 ; x (cm); y (cm)"), 100, -X0MAX,
+                         X0MAX, 100, -X0MAX, X0MAX);
+
+  fhTrklX0_TX = new TH2F(Form("hTrklX0_TX"), Form("Tracklet X0 vs TX at z=0 for hmulmax ; tx (); x0 (cm)"), 100, 0.,
+                         0.4, 100, -X0MAX, X0MAX);
+  fhTrklY0_TX = new TH2F(Form("hTrklY0_TX"), Form("Tracklet Y0 vs TX at z=0 for hmulmax ; tx (); y0 (cm)"), 100, 0.,
+                         0.4, 100, -X0MAX, X0MAX);
+  fhTrklX0_TY = new TH2F(Form("hTrklX0_TY"), Form("Tracklet X0 vs TY at z=0 for hmulmax ; ty (); x0 (cm)"), 100, 0.,
+                         0.4, 100, -X0MAX, X0MAX);
+  fhTrklY0_TY = new TH2F(Form("hTrklY0_TY"), Form("Tracklet Y0 vs TY at z=0 for hmulmax ; ty (); y0 (cm)"), 100, 0.,
+                         0.4, 100, -X0MAX, X0MAX);
 
   Double_t DT0MAX = 5.;
   if (fT0MAX == 0) fT0MAX = DT0MAX;
@@ -1421,12 +1461,21 @@ void CbmTofFindTracks::CreateHistograms()
   fhDeltaTt_Smt   = new TH2F(Form("hDeltaTt_Smt"), Form("Tracklet DeltaTt; RpcInd ; #DeltaTt (ns/cm)"), nSmt, 0, nSmt,
                            100, -DTTMAX, DTTMAX);
 
+  fhDeltaTc_Smt =
+    new TH2F(Form("hDeltaTc_Smt"), Form("Tracklet DeltaTc; RpcInd ; #DeltaTc (ns)"), nSmt, 0, nSmt, 160, -2., 2.);
+
   vhPullX.resize(fNTofStations);
   vhPullY.resize(fNTofStations);
   vhPullZ.resize(fNTofStations);
   vhPullT.resize(fNTofStations);
   vhPullTB.resize(fNTofStations);
   vhTrefRms.resize(fNTofStations);
+  vhFitDT0.resize(fNTofStations);
+  vhFitT0Err.resize(fNTofStations);
+  vhFitTt.resize(fNTofStations);
+  vhFitTtErr.resize(fNTofStations);
+  vhFitDTMean.resize(fNTofStations);
+  vhFitDTMeanErr.resize(fNTofStations);
   vhResidualTBWalk.resize(fNTofStations);
   vhResidualYWalk.resize(fNTofStations);
   vhXY_AllTracks.resize(fNTofStations);
@@ -1453,6 +1502,19 @@ void CbmTofFindTracks::CreateHistograms()
     vhPullTB[iSt] = new TH1F(Form("hPullTB_Station_%d", iSt), Form("hResiTB_Station_%d;  #DeltaT (ns)", iSt), 59,
                              -1.25 * fT0MAX, 1.25 * fT0MAX);
     vhTrefRms[iSt] = new TH1F(Form("hTrefRms_Station_%d", iSt), Form("hTrefRms_Station_%d;  RMS (ns)", iSt), 40, 0, 2.);
+    vhFitDT0[iSt] =
+      new TH1F(Form("hFitDT0_Station_%d", iSt), Form("hFitDT0_Station_%d;  #Deltat (ns)", iSt), 40, -5, 5.);
+    vhFitT0Err[iSt] =
+      new TH1F(Form("hFitT0Err_Station_%d", iSt), Form("hFitT0Err_Station_%d;  rel. error ()", iSt), 40, 0, 0.1);
+    vhFitTt[iSt] =
+      new TH1F(Form("hFitTt_Station_%d", iSt), Form("hFitTt_Station_%d;  inverse velocity (ns/cm)", iSt), 40, 0, 0.1);
+    vhFitTtErr[iSt]     = new TH1F(Form("hFitTtErr_Station_%d", iSt),
+                               Form("hFitTtErr_Station_%d;  inverse velocity error()", iSt), 40, 0, 0.4);
+    vhFitDTMean[iSt]    = new TH1F(Form("hFitDTMean_Station_%d", iSt),
+                                Form("hFitDTMean_Station_%d;  extrapolation distance (ns)", iSt), 40, -5, 5.);
+    vhFitDTMeanErr[iSt] = new TH1F(Form("hFitDTMeanErr_Station_%d", iSt),
+                                   Form("hFitDTMeanErr_Station_%d;  extrapolation error (ns)", iSt), 40, 0, 0.4);
+
     const Double_t TOTmax = 50.;
     vhResidualTBWalk[iSt] =
       new TH2F(Form("hResidualTBWalk_Station_%d", iSt), Form("hResidualTBWalk_Station_%d;  #DeltaT (ns)", iSt), TOTmax,
@@ -1464,7 +1526,7 @@ void CbmTofFindTracks::CreateHistograms()
     Int_t Nbins              = 32.;
     CbmTofCell* fChannelInfo = fDigiPar->GetCell(fMapStationRpcId[iSt]);
     if (NULL == fChannelInfo) {
-      LOG(fatal) << "Geometry for station " << iSt << Form(", Rpc %0x08x ", fMapStationRpcId[iSt]) << " not defined ";
+      LOG(fatal) << "Geometry for station " << iSt << Form(", Rpc 0x%08x ", fMapStationRpcId[iSt]) << " not defined ";
       return;
     }
     Int_t NbinsX        = 2 * XSIZ / fChannelInfo->GetSizex();
@@ -1485,7 +1547,7 @@ void CbmTofFindTracks::CreateHistograms()
     vhXY_DT[iSt] = new TH3F(Form("hXY_DT_%d", iSt), Form("hXY_DT_%d;  x(cm); y (cm); #DeltaT (ns)", iSt), NbinsX, -XSIZ,
                             XSIZ, Nbins, -XSIZ, XSIZ, Nbins, -0.5, 0.5);
     vhXY_TOT[iSt]    = new TH3F(Form("hXY_TOT_%d", iSt), Form("hXY_TOT_%d;  x(cm); y (cm); TOT (a.u.)", iSt), NbinsX,
-                             -XSIZ, XSIZ, Nbins, -XSIZ, XSIZ, Nbins, 0., 10.);
+                             -XSIZ, XSIZ, Nbins, -XSIZ, XSIZ, Nbins, 0., 20.);
     vhXY_CSZ[iSt]    = new TH3F(Form("hXY_CSZ_%d", iSt), Form("hXY_CSZ_%d;  x(cm); y (cm); CSZ ()", iSt), NbinsX, -XSIZ,
                              XSIZ, Nbins, -XSIZ, XSIZ, 6, 1., 7.);
     vhUDXDY_DT[iSt]  = new TH3F(Form("hUDXDY_DT_%d", iSt),
@@ -1618,7 +1680,9 @@ void CbmTofFindTracks::FillHistograms(CbmEvent* tEvent)
       iTMul++;
       fhTrklChi2->Fill(pTrk->GetNofHits(), pTrk->GetChiSq());
 
-      if (fiCalOpt > 0)
+      fhTrklChi2->Fill(pTrk->GetNofHits(), pTrk->GetChiSq());
+
+      if (fiCalOpt > 0)  // && fiCalOpt < 10 )
         if (pTrk->GetTt() > fdTtMin) fTofCalibrator->FillCalHist(pTrk, fiCalOpt, tEvent);
 
       CbmTofTrackletParam* tPar = pTrk->GetTrackParameter();
@@ -1648,6 +1712,10 @@ void CbmTofFindTracks::FillHistograms(CbmEvent* tEvent)
       switch (GetNReqStations() - pTrk->GetNofHits()) {
         case 0:  // max hit number
           fhTrklXY0_0->Fill(pTrk->GetFitX(0.), pTrk->GetFitY(0.));
+          fhTrklX0_TX->Fill(tPar->GetTx(), pTrk->GetFitX(0.));
+          fhTrklY0_TX->Fill(tPar->GetTx(), pTrk->GetFitY(0.));
+          fhTrklX0_TY->Fill(tPar->GetTy(), pTrk->GetFitX(0.));
+          fhTrklY0_TY->Fill(tPar->GetTy(), pTrk->GetFitY(0.));
           break;
         case 1: fhTrklXY0_1->Fill(pTrk->GetFitX(0.), pTrk->GetFitY(0.)); break;
         case 2: fhTrklXY0_2->Fill(pTrk->GetFitX(0.), pTrk->GetFitY(0.)); break;
@@ -1676,9 +1744,9 @@ void CbmTofFindTracks::FillHistograms(CbmEvent* tEvent)
           Double_t dDX  = pHit->GetX() - pTrk->GetFitX(pHit->GetZ());     // - tPar->GetX() - tPar->GetTx()*dDZ;
           Double_t dDY  = pHit->GetY() - pTrk->GetFitY(pHit->GetZ());     // - tPar->GetTy()*dDZ;
           Double_t dDT  = pHit->GetTime() - pTrk->GetFitT(pHit->GetZ());  // pTrk->GetTdif(fMapStationRpcId[iSt]);
-          Double_t dTexp = fTrackletTools->GetTexpected(pTrk, fMapStationRpcId[iSt], pHit);
-          Double_t dDTB  = pHit->GetTime() - dTexp;
+          Double_t dTexp = fTrackletTools->GetTexpected(pTrk, fMapStationRpcId[iSt], pHit, fTtLight);
           //        	fTrackletTools->GetTdif(pTrk, fMapStationRpcId[iSt],pHit);  // ignore pHit in calc of reference
+          Double_t dDTB     = pHit->GetTime() - dTexp;
           Double_t dTexpErr = fTrackletTools->GetTexpectedError(pTrk, fMapStationRpcId[iSt], pHit, dTexp);
           Double_t dTOT = pHit->GetCh() / 10.;            // misuse of channel field
 
@@ -1694,12 +1762,33 @@ void CbmTofFindTracks::FillHistograms(CbmEvent* tEvent)
           vhPullT[iSt]->Fill(dDT);
           vhPullTB[iSt]->Fill(dDTB);
           vhTrefRms[iSt]->Fill(dTexpErr);
+          vhFitDT0[iSt]->Fill(pHit->GetTime() - pTrk->GetT0());
+          vhFitT0Err[iSt]->Fill(pTrk->GetT0Err());
+          vhFitTt[iSt]->Fill(pTrk->GetTt());
+          vhFitTtErr[iSt]->Fill(pTrk->GetTtErr() / pTrk->GetTt());
+          vhFitDTMean[iSt]->Fill(fTrackletTools->GetDTMean(pTrk, pHit));
+          vhFitDTMeanErr[iSt]->Fill(fTrackletTools->GetDTMeanError(pTrk, pHit));
           vhResidualTBWalk[iSt]->Fill(dTOT, dDTB);
           vhResidualYWalk[iSt]->Fill(dTOT, dDY);
 
           fhPullT_Smt->Fill((Double_t) fMapRpcIdParInd[fMapStationRpcId[iSt]], dDT);
           fhPullX_Smt->Fill((Double_t) fMapRpcIdParInd[fMapStationRpcId[iSt]], dDX);
           fhPullY_Smt->Fill((Double_t) fMapRpcIdParInd[fMapStationRpcId[iSt]], dDY);
+          bool bCalModule = kTRUE;
+          if (bCalModule) { /* fill all counters of module*/
+            int iModType = CbmTofAddress::GetSmType(fMapStationRpcId[iSt]);
+            if (iModType < 3) {
+              int iSm  = CbmTofAddress::GetSmId(fMapStationRpcId[iSt]);
+              int iRpc = CbmTofAddress::GetRpcId(fMapStationRpcId[iSt]);
+              for (int i = 0; i < fDigiBdfPar->GetNbDet(); i++) {
+                if (i != iRpc) {
+                  int iRpcId = CbmTofAddress::GetUniqueAddress(iSm, iRpc, 0, 0, iModType);
+                  fhPullX_Smt->Fill((Double_t) fMapRpcIdParInd[iRpcId], dDX);
+                  fhPullY_Smt->Fill((Double_t) fMapRpcIdParInd[iRpcId], dDY);
+                }
+              }
+            }
+          }
           /*
           fhPullT_Smt->Fill((Double_t)fMapRpcIdParInd[fMapStationRpcId[iSt]], fTrackletTools->GetTdif(pTrk,fMapStationRpcId[iSt], pHit) );
           fhPullX_Smt->Fill((Double_t)fMapRpcIdParInd[fMapStationRpcId[iSt]], fTrackletTools->GetXdif(pTrk,fMapStationRpcId[iSt], pHit) );
@@ -1709,6 +1798,10 @@ void CbmTofFindTracks::FillHistograms(CbmEvent* tEvent)
 
           Double_t dDeltaTt = dTt - fTtTarg;
           fhDeltaTt_Smt->Fill((Double_t) fMapRpcIdParInd[fMapStationRpcId[iSt]], dDeltaTt);
+          if (fiBeamCounter != -1) {
+            Double_t dDeltaTc = pHit->GetTime() - pRefHit->GetTime() - pHit->GetR() / 29.979;
+            fhDeltaTc_Smt->Fill((Double_t) fMapRpcIdParInd[fMapStationRpcId[iSt]], dDeltaTc);
+          }
           //XXX use BRef as Referenz!!!
           if (pRefHit != NULL) {
             if (pHit != pRefHit) {
@@ -1776,7 +1869,7 @@ void CbmTofFindTracks::FillHistograms(CbmEvent* tEvent)
             hitpos[0]     = pHit->GetX() - (Double_t) fhPullX_Smt_Off->GetBinContent(iRpcInd + 1);
             hitpos[1]     = pHit->GetY() - (Double_t) fhPullY_Smt_Off->GetBinContent(iRpcInd + 1);
             hitpos[2]     = pHit->GetZ() - (Double_t) fhPullZ_Smt_Off->GetBinContent(iRpcInd + 1);
-            /*	 TGeoNode* cNode= gGeoManager->GetCurrentNode();*/
+            /* TGeoNode* cNode= */ gGeoManager->GetCurrentNode();
             gGeoManager->MasterToLocal(hitpos, hitpos_local);
           }
           vhXY_AllStations[iSt]->Fill(hitpos_local[0], hitpos_local[1]);
@@ -2286,3 +2379,17 @@ int CbmTofFindTracks::GetStationStatus(int iStation)
   else
     return 0;
 }
+
+int CbmTofFindTracks::GetNbHits() { return fTofHitArray->GetEntriesFast(); }  // for internal use by Calibrator
+
+CbmTofHit* CbmTofFindTracks::GetHitPointer(int iHit) { return (CbmTofHit*) fTofHitArray->At(iHit); }
+
+int CbmTofFindTracks::GetHitIndex(int iHit)
+{
+  if ((int) fTofHitIndexArray.size() > iHit) {
+    //LOG(debug) << "Hit " << iHit << ", index " << fTofHitIndexArray[iHit];
+    return fTofHitIndexArray[iHit];
+  }
+  else
+    return iHit;
+}
diff --git a/reco/detectors/tof/CbmTofFindTracks.h b/reco/detectors/tof/CbmTofFindTracks.h
index 7a6d799fbc0e005bbd227158f34fd9fbd0147653..6633f84380f37e50944ae065fa76de1080713510 100644
--- a/reco/detectors/tof/CbmTofFindTracks.h
+++ b/reco/detectors/tof/CbmTofFindTracks.h
@@ -56,7 +56,7 @@ public:
   CbmTofFindTracks();
 
 
-  /** Standard constructor
+  /** Standard constructor 
    **
    *@param name   Name of class
    *@param title  Task title
@@ -132,6 +132,7 @@ public:
   inline Int_t GetBeamCounter() const { return fiBeamCounter; }
   inline Int_t GetEventNumber() const { return fiEvent; }
   inline Double_t GetTtTarg() const { return fTtTarg; }
+  inline Double_t GetTtLight() const { return fTtLight; }
   inline Double_t GetTOffScal() const { return fdTOffScal; }
 
   inline Double_t GetSigT() const { return fSIGT; }
@@ -163,6 +164,8 @@ public:
   inline void SetCalParFileName(TString CalParFileName) { fCalParFileName = CalParFileName; }
   inline void SetCalOutFileName(TString CalOutFileName) { fCalOutFileName = CalOutFileName; }
   inline void SetTtTarg(Double_t val) { fTtTarg = val; }
+  inline void SetTtLight(Double_t val) { fTtLight = val; }
+
   inline void SetTOffScal(Double_t val) { fdTOffScal = val; }
   inline void SetT0MAX(Double_t val) { fT0MAX = val; }
 
@@ -190,6 +193,12 @@ public:
     else
       return fTofHitIndexArray[iHit];
   }
+
+  int GetNbHits();
+  CbmTofHit* GetHitPointer(int iHit);
+  int GetHitIndex(int iHit);
+
+
   bool EvalDoublets(int iI0, int iI1, int iI2, double* dTshift);
 
 private:
@@ -261,6 +270,10 @@ private:
   TH2* fhTrklXY0_0;
   TH2* fhTrklXY0_1;
   TH2* fhTrklXY0_2;
+  TH2* fhTrklX0_TX;
+  TH2* fhTrklY0_TX;
+  TH2* fhTrklX0_TY;
+  TH2* fhTrklY0_TY;
 
   std::vector<TH1*> vhPullX;
   std::vector<TH1*> vhPullY;
@@ -268,6 +281,12 @@ private:
   std::vector<TH1*> vhPullT;
   std::vector<TH1*> vhPullTB;
   std::vector<TH1*> vhTrefRms;
+  std::vector<TH1*> vhFitDT0;
+  std::vector<TH1*> vhFitT0Err;
+  std::vector<TH1*> vhFitTt;
+  std::vector<TH1*> vhFitTtErr;
+  std::vector<TH1*> vhFitDTMean;
+  std::vector<TH1*> vhFitDTMeanErr;
   std::vector<TH2*> vhResidualTBWalk;
   std::vector<TH2*> vhResidualYWalk;
   std::vector<TH2*> vhXY_AllTracks;      // for monitoring
@@ -311,11 +330,13 @@ private:
   TH2* fhTOff_Smt;         // Time calibration histo
   TH1* fhTOff_Smt_Off;     // Time calibration histo
   TH2* fhDeltaTt_Smt;      // Time calibration histo
+  TH2* fhDeltaTc_Smt;      // Time calibration histo
   TH2* fhTOff_HMul2;       // Time calibration histo
   Int_t fiCorMode;
   Int_t fiBeamCounter;
   Int_t fiStationMaxHMul;
   Double_t fTtTarg;     // expected average slope in ns/cm
+  Double_t fTtLight;    // slope of Light in ns/cm
   Double_t fdTOffScal;  // modifier to tune average velocity
   Double_t fVTXNorm;  // Number of Hits contributing to Vertex determination
   Double_t fVTX_T;    // measured event wise t0
diff --git a/reco/detectors/tof/CbmTofTrackletTools.cxx b/reco/detectors/tof/CbmTofTrackletTools.cxx
index 43978e982214eeabb9a22bdae821b4d5419410b2..c6aab26d3336823a10f4ab9959f0f9ef72c99c7c 100644
--- a/reco/detectors/tof/CbmTofTrackletTools.cxx
+++ b/reco/detectors/tof/CbmTofTrackletTools.cxx
@@ -69,7 +69,7 @@ Double_t CbmTofTrackletTools::FitTt(CbmTofTracklet* pTrk, Int_t iDetId)
   // Call with iDetId=-1 for full Tracklet fit
   Int_t nValidHits = 0;
   Int_t iHit1      = 0;
-  Double_t dDist1  = 100.;
+  Double_t dDist1  = 0.;
   //LOG(info) << "FitTt: " << pTrk->GetNofHits() << " hits, exclude " << Form("0x%08x",iDetId);
   Double_t aR[pTrk->GetNofHits()];
   Double_t at[pTrk->GetNofHits()];
@@ -79,7 +79,7 @@ Double_t CbmTofTrackletTools::FitTt(CbmTofTracklet* pTrk, Int_t iDetId)
     if (nValidHits == 0) {
       iHit1 = iHit;
       //LOG(info) << "Init Dist1 with " << iHit1;
-      Double_t* dPar = Line3DFit(pTrk, iDetId);  // spatial fit without iDetId
+      Double_t* dPar = Line3DFit(pTrk, iDetId);  // spatial fit without iDetId, dPar[1] = slope dx/dz, dPar[3]=dy/dz
       dDist1         = pTrk->GetTofHitPointer(iHit1)->GetZ() * TMath::Sqrt(1. + dPar[1] * dPar[1] + dPar[3] * dPar[3]);
       //LOG(info) << "Dist1 = " << dDist1;
     }
@@ -116,6 +116,7 @@ Double_t CbmTofTrackletTools::FitTt(CbmTofTracklet* pTrk, Int_t iDetId)
   Double_t dT0      = (RRsum * tsum - Rsum * Rtsum) / det_cov_mat;  // Best Guess for time at origin
   Double_t dTt      = (-Rsum * tsum + esum * Rtsum) / det_cov_mat;  // Best guess for inverted velocity
   Double_t dT0Err   = TMath::Sqrt(RRsum / det_cov_mat);  // sqrt of (0,0) in Covariance matrix -> error on fT0
+  dT0Err /= dT0;                                         // relative error
   Double_t dTtErr   = TMath::Sqrt(esum / det_cov_mat);   // sqrt of (1,1) in Covariance Matrix -> error on fTt
   Double_t dT0TtCov = -Rsum / det_cov_mat;               // (0,1)=(1,0) in Covariance Matrix -> cov(fT0,fTt)
   dT0 += yoffset;                                        // Adding yoffset again
@@ -263,13 +264,14 @@ Double_t CbmTofTrackletTools::GetTdif(CbmTofTracklet* pTrk, Int_t iDetId, CbmTof
   return dTdif;
 }
 
-Double_t CbmTofTrackletTools::GetTexpected(CbmTofTracklet* pTrk, Int_t iDetId, CbmTofHit* pHit)
+Double_t CbmTofTrackletTools::GetTexpected(CbmTofTracklet* pTrk, Int_t iDetId, CbmTofHit* pHit, double TtLight)
 {
   Double_t dTref = 0.;
   Double_t Nref  = 0;
   Double_t dTt   = 0.;
-
-  dTt = FitTt(pTrk, iDetId);
+  if (TtLight == 0.) dTt = FitTt(pTrk, iDetId);
+  else
+    dTt = TtLight;  // fix slope to speed of light
 
   for (Int_t iHit = 0; iHit < pTrk->GetNofHits(); iHit++) {
     if (iDetId == pTrk->GetTofDetIndex(iHit) || 0 == pTrk->GetTofDetIndex(iHit)) continue;
@@ -283,6 +285,7 @@ Double_t CbmTofTrackletTools::GetTexpected(CbmTofTracklet* pTrk, Int_t iDetId, C
     return 1.E20;
   }
   dTref /= (Double_t) Nref;
+
   return dTref;
 }
 
@@ -319,4 +322,21 @@ Double_t CbmTofTrackletTools::GetTexpectedError(CbmTofTracklet* pTrk, Int_t iDet
   return dTrms;
 }
 
+Double_t CbmTofTrackletTools::GetDTMean(CbmTofTracklet* pTrk, CbmTofHit* pHit)
+{
+  double dTmean = 0.;
+  int nHits     = 0;
+  for (Int_t iHit = 0; iHit < pTrk->GetNofHits(); iHit++) {
+    if (pTrk->GetTofHitPointer(iHit) == pHit) continue;
+    dTmean += pTrk->GetTofHitPointer(iHit)->GetTime();
+    nHits++;
+  }
+  dTmean /= nHits;
+  return pHit->GetTime() - dTmean;
+}
+
+Double_t CbmTofTrackletTools::GetDTMeanError(CbmTofTracklet* pTrk, CbmTofHit* pHit)
+{
+  return pTrk->GetTtErr() / pTrk->GetTt() * TMath::Abs(GetDTMean(pTrk, pHit));
+}
 ClassImp(CbmTofTrackletTools)
diff --git a/reco/detectors/tof/CbmTofTrackletTools.h b/reco/detectors/tof/CbmTofTrackletTools.h
index 46c35558287d8d70205f4b93d2a1de6a559fd523..3936a2d8ee998bcd0cc4a072f7159e158e944756 100644
--- a/reco/detectors/tof/CbmTofTrackletTools.h
+++ b/reco/detectors/tof/CbmTofTrackletTools.h
@@ -39,8 +39,10 @@ public:
   virtual Double_t GetXdif(CbmTofTracklet* pTrk, Int_t iDetId, CbmTofHit* pHit);
   virtual Double_t GetYdif(CbmTofTracklet* pTrk, Int_t iDetId, CbmTofHit* pHit);
   virtual Double_t GetTdif(CbmTofTracklet* pTrk, Int_t iDetId, CbmTofHit* pHit);
-  virtual Double_t GetTexpected(CbmTofTracklet* pTrk, Int_t iDetId, CbmTofHit* pHit);
+  virtual Double_t GetTexpected(CbmTofTracklet* pTrk, Int_t iDetId, CbmTofHit* pHit, double TtLight = 0.);
   virtual Double_t GetTexpectedError(CbmTofTracklet* pTrk, Int_t iDetId, CbmTofHit* pHit, Double_t dTexp);
+  virtual Double_t GetDTMean(CbmTofTracklet* pTrk, CbmTofHit* pHit);
+  virtual Double_t GetDTMeanError(CbmTofTracklet* pTrk, CbmTofHit* pHit);
 
 private:
   ClassDef(CbmTofTrackletTools, 1);