diff --git a/core/detectors/tof/CbmTofCreateDigiPar.cxx b/core/detectors/tof/CbmTofCreateDigiPar.cxx
index 983b5796febddc0bcb96cb12a65161f2e6b7f652..57d4186efc790ae1275ff006f9a042687bdc473a 100644
--- a/core/detectors/tof/CbmTofCreateDigiPar.cxx
+++ b/core/detectors/tof/CbmTofCreateDigiPar.cxx
@@ -139,7 +139,9 @@ InitStatus CbmTofCreateDigiPar::Init() {
     TGeoNode* tGeoNode = gGeoManager->GetCurrentNode();
     nodemap.insert(std::pair<Int_t, TGeoNode*>(iAddr, tGeoNode));
     LOG(debug) << Form(
-      "Digipar for %d, addr 0x%08x: Node=%p", iCell, iAddr, tGeoNode);
+      "Digipar for %d, addr 0x%08x: Node=%p, x %6.2f, y %6.2f, z %6.2f ",
+	  iCell, iAddr, tGeoNode,
+	  fChannelInfo->GetX(), fChannelInfo->GetY(), fChannelInfo->GetZ());
   }
   fDigiPar->SetNodeMap(nodemap);
 
diff --git a/reco/detectors/tof/CMakeLists.txt b/reco/detectors/tof/CMakeLists.txt
index 2e5b31354b569c543407c732a538f7420f2378a8..ff4c8ea2cdb610ed847400521c4c029de16c9004 100644
--- a/reco/detectors/tof/CMakeLists.txt
+++ b/reco/detectors/tof/CMakeLists.txt
@@ -34,6 +34,7 @@ link_directories(${LINK_DIRECTORIES})
 
 set(SRCS
   CbmTofBuildDigiEvents.cxx
+  CbmTofHitMaker.cxx
   CbmTofCosmicClusterizer.cxx
   CbmTofEventClusterizer.cxx
   CbmTofFindTracks.cxx 
diff --git a/reco/detectors/tof/CbmTofHitMaker.cxx b/reco/detectors/tof/CbmTofHitMaker.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..96d2fdb76f18499f79e7179f92b2407bba32f169
--- /dev/null
+++ b/reco/detectors/tof/CbmTofHitMaker.cxx
@@ -0,0 +1,3185 @@
+/** @file CbmTofHitMaker.cxx 
+ ** @author nh  
+ ** @date01.12.2018
+ ** adopted from
+ ** @file CbmTofEventClusterizer.cxx 
+ ** @file CbmTofTestBeamClusterizer.cxx 
+ ** @file CbmTofSimpClusterizer.cxx 
+ ** @author Pierre-Alain Loizeau <loizeau@physi.uni-heidelberg.de>
+ ** @date 23.08.2013
+ **/
+
+#include "CbmTofHitMaker.h"
+
+// TOF Classes and includes
+#include "CbmDigiManager.h"
+#include "CbmEvent.h"
+#include "CbmMatch.h"
+#include "CbmTofAddress.h"          // in cbmdata/tof
+#include "CbmTofCell.h"             // in tof/TofData
+#include "CbmTofCreateDigiPar.h"    // in tof/TofTools
+#include "CbmTofDetectorId_v12b.h"  // in cbmdata/tof
+#include "CbmTofDetectorId_v14a.h"  // in cbmdata/tof
+#include "CbmTofDetectorId_v21a.h"  // in cbmdata/tof
+#include "CbmTofDigi.h"             // in cbmdata/tof
+#include "CbmTofDigiBdfPar.h"       // in tof/TofParam
+#include "CbmTofDigiPar.h"          // in tof/TofParam
+#include "CbmTofGeoHandler.h"       // in tof/TofTools
+#include "CbmTofHit.h"              // in cbmdata/tof
+#include "CbmTofPoint.h"            // in cbmdata/tof
+#include "CbmVertex.h"
+
+#include "TTrbHeader.h"
+
+// CBMroot classes and includes
+#include "CbmMCTrack.h"
+
+// FAIR classes and includes
+#include "FairEventHeader.h"
+#include "FairLogger.h"
+#include "FairRootFileSink.h"
+#include "FairRootManager.h"
+#include "FairRunAna.h"
+#include "FairRuntimeDb.h"
+
+// ROOT Classes and includes
+#include "TClonesArray.h"
+#include "TDirectory.h"
+#include "TF1.h"
+#include "TF2.h"
+#include "TFitResult.h"
+#include "TGeoManager.h"
+#include "TH1.h"
+#include "TH2.h"
+#include "TH3.h"
+#include "TLine.h"
+#include "TMath.h"
+#include "TMinuit.h"
+#include "TProfile.h"
+#include "TROOT.h"
+#include "TRandom.h"
+#include "TRandom3.h"
+#include "TVector3.h"
+
+// Constants definitions
+#include "CbmTofClusterizersDef.h"
+
+// C++ Classes and includes
+// Globals
+#include <vector>
+
+static Int_t iNbTs            = 0;
+
+static Bool_t bAddBeamCounterSideDigi = kTRUE;
+static TRandom3* fRndm                = new TRandom3();
+
+//   std::vector< CbmTofPoint* > vPtsRef;
+
+CbmTofHitMaker* CbmTofHitMaker::fInstance = 0;
+
+/************************************************************************************/
+CbmTofHitMaker::CbmTofHitMaker()
+  : CbmTofHitMaker("TofHitMaker", 0, 0) {
+  // if ( !fInstance ) fInstance = this;
+}
+
+CbmTofHitMaker::CbmTofHitMaker(const char* name,
+                                               Int_t verbose,
+                                               Bool_t writeDataInOut)
+  : FairTask(TString(name), verbose)
+  , fGeoHandler(new CbmTofGeoHandler())
+  , fTofId(NULL)
+  , fDigiPar(NULL)
+  , fChannelInfo(NULL)
+  , fDigiBdfPar(NULL)
+  , fTrbHeader(NULL)
+  , fTofPointsColl(NULL)
+  , fMcTracksColl(NULL)
+  , fDigiMan(nullptr)
+  , fEventsColl(nullptr)
+  , fbWriteHitsInOut(writeDataInOut)
+  , fbWriteDigisInOut(writeDataInOut)
+  , fTofHitsColl(NULL)
+  , fTofDigiMatchColl(NULL)
+  , fTofHitsCollOut(NULL)
+  , fTofDigiMatchCollOut(NULL)
+  , fiNbHits(0)
+  , fVerbose(verbose)
+  , fStorDigi()
+  , fStorDigiInd()
+  , vDigiIndRef()
+  , fviClusterMul()
+  , fviClusterSize()
+  , fviTrkMul()
+  , fvdX()
+  , fvdY()
+  , fvdDifX()
+  , fvdDifY()
+  , fvdDifCh()
+  , fhClustBuildTime(NULL)
+  , fhHitsPerTracks(NULL)
+  , fhPtsPerHit(NULL)
+  , fhTimeResSingHits(NULL)
+  , fhTimeResSingHitsB(NULL)
+  , fhTimePtVsHits(NULL)
+  , fhClusterSize(NULL)
+  , fhClusterSizeType(NULL)
+  , fhTrackMul(NULL)
+  , fhClusterSizeMulti(NULL)
+  , fhTrk1MulPos(NULL)
+  , fhHiTrkMulPos(NULL)
+  , fhAllTrkMulPos(NULL)
+  , fhMultiTrkProbPos(NULL)
+  , fhDigSpacDifClust(NULL)
+  , fhDigTimeDifClust(NULL)
+  , fhDigDistClust(NULL)
+  , fhClustSizeDifX(NULL)
+  , fhClustSizeDifY(NULL)
+  , fhChDifDifX(NULL)
+  , fhChDifDifY(NULL)
+  , fhCluMulCorDutSel(NULL)
+  , fhEvCluMul(NULL)
+  , fhRpcDigiCor()
+  , fhRpcDigiMul()
+  , fhRpcDigiStatus()
+  , fhRpcDigiDTLD()
+  , fhRpcDigiDTFD()
+  , fhRpcDigiDTMul()
+  , fhRpcCluMul()
+  , fhRpcCluRate()
+  , fhRpcCluRate10s()
+  , fhRpcCluPosition()
+  , fhRpcCluPositionEvol()
+  , fhRpcCluTimeEvol()
+  , fhRpcCluDelPos()
+  , fhRpcCluDelMatPos()
+  , fhRpcCluTOff()
+  , fhRpcCluDelTOff()
+  , fhRpcCluDelMatTOff()
+  , fhRpcCluTrms()
+  , fhRpcCluTot()
+  , fhRpcCluSize()
+  , fhRpcCluAvWalk()
+  , fhRpcCluAvLnWalk()
+  , fhRpcCluWalk()
+  , fhSmCluPosition()
+  , fhSmCluTOff()
+  , fhSmCluSvel()
+  , fhSmCluFpar()
+  , fhRpcDTLastHits()
+  , fhRpcDTLastHits_Tot()
+  , fhRpcDTLastHits_CluSize()
+  , fhTRpcCluMul()
+  , fhTRpcCluPosition()
+  , fhTRpcCluTOff()
+  , fhTRpcCluTofOff()
+  , fhTRpcCluTot()
+  , fhTRpcCluSize()
+  , fhTRpcCluAvWalk()
+  , fhTRpcCluDelTof()
+  , fhTRpcCludXdY()
+  , fhTRpcCluWalk()
+  , fhTRpcCluWalk2()
+  , fhTSmCluPosition()
+  , fhTSmCluTOff()
+  , fhTSmCluTRun()
+  , fhTRpcCluTOffDTLastHits()
+  , fhTRpcCluTotDTLastHits()
+  , fhTRpcCluSizeDTLastHits()
+  , fhTRpcCluMemMulDTLastHits()
+  , fhSeldT()
+  , fvCPDelTof()
+  , fvCPTOff()
+  , fvCPTotGain()
+  , fvCPTotOff()
+  , fvCPWalk()
+  , fvLastHits()
+  , fvDeadStrips()
+  , fvTimeLastDigi()
+  , fiNbSameSide(0)
+  , fhNbSameSide(NULL)
+  , fhNbDigiPerChan(NULL)
+  , fStart()
+  , fStop()
+  , dTRef(0.)
+  , fdTRefMax(0.)
+  , fCalMode(0)
+  , fCalSel(0)
+  , fCalSmAddr(0)
+  , fdCaldXdYMax(0.)
+  , fiCluMulMax(0)
+  , fTRefMode(0)
+  , fTRefHits(0)
+  , fIdMode(0)
+  , fDutId(0)
+  , fDutSm(0)
+  , fDutRpc(0)
+  , fDutAddr(0)
+  , fSelId(0)
+  , fSelSm(0)
+  , fSelRpc(0)
+  , fSelAddr(0)
+  , fiBeamRefType(0)
+  , fiBeamRefSm(0)
+  , fiBeamRefDet(0)
+  , fiBeamRefAddr(0)
+  , fiBeamRefMulMax(1)
+  , fiBeamAddRefMul(0)
+  , fSel2Id(-1)
+  , fSel2Sm(0)
+  , fSel2Rpc(0)
+  , fSel2Addr(0)
+  , fSel2MulMax(1)
+  , fDetIdIndexMap()
+  , fviDetId()
+  , fPosYMaxScal(0.)
+  , fTRefDifMax(0.)
+  , fTotMax(0.)
+  , fTotMin(0.)
+  , fTotOff(0.)
+  , fTotMean(0.)
+  , fdDelTofMax(60.)
+  , fTotPreRange(0.)
+  , fMaxTimeDist(0.)
+  , fdChannelDeadtime(0.)
+  , fdMemoryTime(0.)
+  , fdYFitMin(1.E6)
+  , fdToDAv(0.033)  // in ns/cm
+  , fEnableMatchPosScaling(kTRUE)
+  , fEnableAvWalk(kFALSE)
+  , fbPs2Ns(kFALSE)
+  , fCalParFileName("")
+  , fOutHstFileName("")
+  , fCalParFile(NULL)
+  , fiNevtBuild(0)
+  , fiMsgCnt(100)
+  , fdTOTMax(50.)
+  , fdTOTMin(0.)
+  , fdTTotMean(2.)
+  , fdMaxTimeDist(0.)
+  , fdMaxSpaceDist(0.)
+  , fdEvent(0)
+  , fbSwapChannelSides(kFALSE)
+  , fiOutputTreeEntry(0)
+  , fiFileIndex(0)
+  , fbAlternativeBranchNames(kFALSE) {
+  if (!fInstance) fInstance = this;
+}
+
+CbmTofHitMaker::~CbmTofHitMaker() {
+  if (fGeoHandler) delete fGeoHandler;
+  if (fInstance == this) fInstance = 0;
+  //   DeleteHistos(); // <-- if needed  ?
+}
+
+/************************************************************************************/
+// FairTasks inherited functions
+InitStatus CbmTofHitMaker::Init() {
+  LOG(info)
+    << "CbmTofHitMaker initializing... expect Digis in ns units! ";
+
+  if (kFALSE == RegisterInputs()) return kFATAL;
+
+  if (kFALSE == RegisterOutputs()) return kFATAL;
+
+  if (kFALSE == InitParameters()) return kFATAL;
+
+  if (kFALSE == LoadGeometry()) return kFATAL;
+
+  if (kFALSE == InitCalibParameter()) return kFATAL;
+
+  if (kFALSE == CreateHistos()) return kFATAL;
+  return kSUCCESS;
+}
+
+void CbmTofHitMaker::SetParContainers() {
+  LOG(info) << "=> Get the digi parameters for tof";
+  //LOG(warning)<<"Return without action";
+  //return;
+  // Get Base Container
+  FairRunAna* ana     = FairRunAna::Instance();
+  FairRuntimeDb* rtdb = ana->GetRuntimeDb();
+
+  fDigiPar = (CbmTofDigiPar*) (rtdb->getContainer("CbmTofDigiPar"));
+
+  LOG(info) << "found " << fDigiPar->GetNrOfModules() << " cells ";
+  fDigiBdfPar = (CbmTofDigiBdfPar*) (rtdb->getContainer("CbmTofDigiBdfPar"));
+}
+
+void CbmTofHitMaker::Exec(Option_t* option) {
+
+  if (fTofCalDigiVecOut) fTofCalDigiVecOut->clear();
+  if (fEventsColl) {
+    LOG(info) << "CbmTofHitMaker::Exec => New timeslice " << iNbTs
+              << " with " << fEventsColl->GetEntriesFast() << " events, "
+              << fDigiMan->GetNofDigis(ECbmModuleId::kTof) << " TOF digis + "
+              << fDigiMan->GetNofDigis(ECbmModuleId::kT0) << " T0 digis ";
+    iNbTs++;
+
+    Int_t iNbHits     = 0;
+    Int_t iNbCalDigis = 0;
+    fTofDigiMatchCollOut->Delete();  // costly, FIXME
+    fTofHitsCollOut->Delete();       // costly, FIXME
+    //fTofDigiMatchCollOut->Clear("C"); // not sufficient, memory leak
+    for (Int_t iEvent = 0; iEvent < fEventsColl->GetEntriesFast(); iEvent++) {
+      CbmEvent* tEvent = dynamic_cast<CbmEvent*>(fEventsColl->At(iEvent));
+      fTofDigiVec.clear();
+      //if (fTofDigisColl) fTofDigisColl->Clear("C");
+      //Int_t iNbDigis=0;  (VF) not used
+      LOG(debug) << "TS event " << iEvent << " with "
+                 << tEvent->GetNofData(ECbmDataType::kT0Digi) << " T0 and "
+                 << tEvent->GetNofData(ECbmDataType::kTofDigi) << " Tof digis ";
+
+      for (Int_t iDigi = 0; iDigi < tEvent->GetNofData(ECbmDataType::kT0Digi);
+           iDigi++) {
+        Int_t iDigiIndex =
+          static_cast<Int_t>(tEvent->GetIndex(ECbmDataType::kT0Digi, iDigi));
+        const CbmTofDigi tDigi = fT0DigiVec->at(iDigiIndex);
+        if (tDigi.GetType() != 5)
+          LOG(fatal) << "Wrong T0 type " << tDigi.GetType() << ", Addr 0x"
+                     << std::hex << tDigi.GetAddress();
+        fTofDigiVec.push_back(CbmTofDigi(tDigi));
+      }
+      for (Int_t iDigi = 0; iDigi < tEvent->GetNofData(ECbmDataType::kTofDigi);
+           iDigi++) {
+        Int_t iDigiIndex =
+          static_cast<Int_t>(tEvent->GetIndex(ECbmDataType::kTofDigi, iDigi));
+        const CbmTofDigi* tDigi = fDigiMan->Get<CbmTofDigi>(iDigiIndex);
+        fTofDigiVec.push_back(CbmTofDigi(*tDigi));
+        //new((*fTofDigisColl)[iNbDigis++]) CbmTofDigi(*tDigi);
+      }
+
+      ExecEvent(option);
+
+      // --- In event-by-event mode: copy caldigis, hits and matches to output array and register them to event
+
+      // Int_t iDigi0=iNbCalDigis; //starting index of current event  (VF) not used
+      for (UInt_t index = 0; index < fTofCalDigiVec->size(); index++) {
+        //      for (Int_t index = 0; index < fTofCalDigisColl->GetEntriesFast(); index++){
+        CbmTofDigi* tDigi = &(fTofCalDigiVec->at(index));
+        //CbmTofDigi* tDigi = dynamic_cast<CbmTofDigi*>(fTofCalDigisColl->At(index));
+        tEvent->AddData(ECbmDataType::kTofCalDigi, iNbCalDigis);
+        fTofCalDigiVecOut->push_back(CbmTofDigi(*tDigi));
+        iNbCalDigis++;
+        //new((*fTofCalDigisCollOut)[iNbCalDigis++]) CbmTofDigi(*tDigi);
+      }
+
+      for (Int_t index = 0; index < fTofHitsColl->GetEntriesFast(); index++) {
+        CbmTofHit* pHit = (CbmTofHit*) fTofHitsColl->At(index);
+        new ((*fTofHitsCollOut)[iNbHits]) CbmTofHit(*pHit);
+        tEvent->AddData(ECbmDataType::kTofHit, iNbHits);
+
+        CbmMatch* pDigiMatch = (CbmMatch*) fTofDigiMatchColl->At(index);
+        // update content of match object, not necessary if event definition  is kept !
+        /*
+				 for (Int_t iLink=0; iLink<pDigiMatch->GetNofLinks(); iLink++) {  // loop over digis
+				 CbmLink Link = pDigiMatch->GetLink(iLink);
+				 Link.SetIndex(Link.GetIndex()+iDigi0);
+				 }
+				 */
+        new ((*fTofDigiMatchCollOut)[iNbHits]) CbmMatch(*pDigiMatch);
+
+        iNbHits++;
+      }
+      //fTofDigisColl->Delete();
+      fTofDigiVec.clear();
+      //fTofCalDigi->Delete();//Clear("C"); //otherwise memoryleak! FIXME
+      fTofCalDigiVec->clear();
+      fTofHitsColl->Clear("C");
+      fTofDigiMatchColl->Delete();  //Clear("C");
+    }
+  } else {
+    // fTofDigisColl=fTofRawDigisColl;
+    // (VF) This does not work here. The digi manager does not foresee to add
+    // new data to the input array. So, I here copy the input digis into
+    // the array fTofDigisColl. Not very efficient, but temporary only, until
+    // also the internal data representations are changed to std::vectors.
+
+    fTofDigiVec.clear();
+    //if (fTofDigisColl) fTofDigisColl->Clear("C");
+    // Int_t iNbDigis=0; (VF) not used
+    for (Int_t iDigi = 0; iDigi < fDigiMan->GetNofDigis(ECbmModuleId::kTof);
+         iDigi++) {
+      const CbmTofDigi* tDigi = fDigiMan->Get<CbmTofDigi>(iDigi);
+      fTofDigiVec.push_back(CbmTofDigi(*tDigi));
+      //new((*fTofDigisColl)[iNbDigis++]) CbmTofDigi(*tDigi);
+    }
+    ExecEvent(option);
+  }
+}
+
+void CbmTofHitMaker::ExecEvent(Option_t* /*option*/) {
+  // 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
+  //for (Int_t i=0; i<fTofDigiMatchColl->GetEntries(); 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();
+  FairRootFileSink* bla =
+    (FairRootFileSink*) FairRootManager::Instance()->GetSink();
+  if (bla)
+    fiOutputTreeEntry =
+      ((FairRootFileSink*) FairRootManager::Instance()->GetSink())
+        ->GetOutTree()
+        ->GetEntries();
+
+  fiNbHits = 0;
+
+  fStart.Set();
+
+  BuildClusters();
+
+  MergeClusters();
+
+  fStop.Set();
+
+  fdEvent++;
+  FillHistos();
+
+  //   fTofDigisColl->RemoveAll();
+}
+
+/************************************************************************************/
+void CbmTofHitMaker::Finish() {
+  if (fdEvent < 100) return;  // don't save histos with insufficient statistics
+  WriteHistos();
+  // Prevent them from being sucked in by the CbmHadronAnalysis WriteHistograms method
+  // DeleteHistos();
+  if (fdMemoryTime > 0.) CleanLHMemory();
+}
+
+void CbmTofHitMaker::Finish(Double_t calMode) {
+  if (fdEvent < 100) return;  // don't save histos with insufficient statistics
+  SetCalMode(calMode);
+  WriteHistos();
+}
+
+/************************************************************************************/
+// Functions common for all clusters approximations
+Bool_t CbmTofHitMaker::RegisterInputs() {
+  FairRootManager* fManager = FairRootManager::Instance();
+
+  if (NULL == fManager) {
+    LOG(error) << "CbmTofHitMaker::RegisterInputs => Could not find "
+                  "FairRootManager!!!";
+    return kFALSE;
+  }  // if( NULL == fTofDigisColl)
+
+  fEventsColl = dynamic_cast<TClonesArray*>(fManager->GetObject("Event"));
+  if (NULL == fEventsColl)
+    fEventsColl = dynamic_cast<TClonesArray*>(fManager->GetObject("CbmEvent"));
+
+  if (NULL == fEventsColl)
+    LOG(info) << "CbmEvent not found in input file, assume eventwise input";
+
+  fDigiMan = CbmDigiManager::Instance();
+  fDigiMan->Init();
+  if (!fDigiMan->IsPresent(ECbmModuleId::kTof)) {
+    LOG(error) << GetName() << ": No Tof digi input!";
+    return kFALSE;
+  }
+  if (fDigiMan->IsPresent(ECbmModuleId::kT0)) {
+    LOG(info) << GetName() << ": separate T0 digi input!";
+  } else {
+    fT0DigiVec =
+      fManager->InitObjectAs<std::vector<CbmTofDigi> const*>("T0Digi");
+    if (!fT0DigiVec) { LOG(info) << "No T0 digi input vector found."; }
+  }  // if( ! fT0DigiVec )
+
+  fTrbHeader = (TTrbHeader*) fManager->GetObject("TofTrbHeader.");
+  if (NULL == fTrbHeader) {
+    LOG(info) << "CbmTofHitMaker::RegisterInputs => Could not get "
+                 "TofTrbHeader Object";
+  }
+
+  if (NULL == fEventsColl) {
+    //fTofDigisColl = new TClonesArray("CbmTofDigi");
+  } else {
+    // time based input
+    LOG(info) << "CbmEvent found in input file, assume time based input";
+    //fTofDigisColl = new TClonesArray("CbmTofDigi");
+  }
+
+  return kTRUE;
+}
+Bool_t CbmTofHitMaker::RegisterOutputs() {
+  FairRootManager* rootMgr = FairRootManager::Instance();
+  // FairRunAna* ana = FairRunAna::Instance();  (VF) not used
+
+  rootMgr->InitSink();
+
+  //fTofCalDigisColl = new TClonesArray("CbmTofDigi");
+  fTofCalDigiVec = new std::vector<CbmTofDigi>();
+
+  fTofHitsColl = new TClonesArray("CbmTofHit");
+
+  fTofDigiMatchColl = new TClonesArray("CbmMatch", 100);
+
+  TString tHitBranchName;
+  TString tHitDigiMatchBranchName;
+
+  if (fbAlternativeBranchNames) {
+    tHitBranchName          = "ATofHit";
+    tHitDigiMatchBranchName = "ATofDigiMatch";
+  } else {
+    tHitBranchName          = "TofHit";
+    tHitDigiMatchBranchName = "TofCalDigiMatch";
+  }
+
+  if (NULL == fEventsColl) {
+    // Flag check to control whether digis are written in output root file
+    //rootMgr->Register( "TofCalDigi","Tof", fTofCalDigisColl, fbWriteDigisInOut);
+    rootMgr->RegisterAny("TofCalDigi", fTofCalDigiVec, fbWriteDigisInOut);
+
+    // Flag check to control whether digis are written in output root file
+    rootMgr->Register(tHitBranchName, "Tof", fTofHitsColl, fbWriteHitsInOut);
+
+    rootMgr->Register(
+      tHitDigiMatchBranchName, "Tof", fTofDigiMatchColl, fbWriteHitsInOut);
+  } else {  // CbmEvent - mode
+    //fTofCalDigisCollOut  = new TClonesArray("CbmTofDigi");
+    fTofCalDigiVecOut    = new std::vector<CbmTofDigi>();
+    fTofHitsCollOut      = new TClonesArray("CbmTofHit");
+    fTofDigiMatchCollOut = new TClonesArray("CbmMatch", 100);
+    //rootMgr->Register( "TofCalDigi","Tof", fTofCalDigisCollOut, fbWriteDigisInOut);
+    rootMgr->RegisterAny("TofCalDigi", fTofCalDigiVecOut, fbWriteDigisInOut);
+    rootMgr->Register(tHitBranchName, "Tof", fTofHitsCollOut, fbWriteHitsInOut);
+    rootMgr->Register(
+      tHitDigiMatchBranchName, "Tof", fTofDigiMatchCollOut, fbWriteHitsInOut);
+  }
+  LOG(info) << "out branches: " << tHitBranchName << ", "
+            << tHitDigiMatchBranchName;
+  return kTRUE;
+}
+Bool_t CbmTofHitMaker::InitParameters() {
+
+  // Initialize the TOF GeoHandler
+  Bool_t isSimulation = kFALSE;
+  LOG(info)
+    << "CbmTofHitMaker::InitParameters - Geometry, Mapping, ...  ??";
+
+  // Get Base Container
+  FairRun* ana        = FairRun::Instance();
+  FairRuntimeDb* rtdb = ana->GetRuntimeDb();
+
+  Int_t iGeoVersion = fGeoHandler->Init(isSimulation);
+  if (k14a > iGeoVersion) {
+    LOG(error) << "CbmTofHitMaker::InitParameters => Only compatible "
+                  "with geometries after v14a !!!";
+    return kFALSE;
+  }
+  if (iGeoVersion == k14a)
+    fTofId = new CbmTofDetectorId_v14a();
+  else
+    fTofId = new CbmTofDetectorId_v21a();
+
+  // create digitization parameters from geometry file
+  CbmTofCreateDigiPar* tofDigiPar =
+    new CbmTofCreateDigiPar("TOF Digi Producer", "TOF task");
+  LOG(info) << "Create DigiPar ";
+  tofDigiPar->Init();
+
+  fDigiPar = (CbmTofDigiPar*) (rtdb->getContainer("CbmTofDigiPar"));
+  if (0 == fDigiPar) {
+    LOG(error) << "CbmTofHitMaker::InitParameters => Could not obtain "
+                  "the CbmTofDigiPar ";
+    return kFALSE;
+  }
+
+  fDigiBdfPar = (CbmTofDigiBdfPar*) (rtdb->getContainer("CbmTofDigiBdfPar"));
+  if (0 == fDigiBdfPar) {
+    LOG(error) << "CbmTofHitMaker::InitParameters => Could not obtain "
+                  "the CbmTofDigiBdfPar ";
+    return kFALSE;
+  }
+
+  rtdb->initContainers(ana->GetRunId());
+
+  LOG(info) << "CbmTofHitMaker::InitParameter: currently "
+            << fDigiPar->GetNrOfModules() << " digi cells ";
+
+  fdMaxTimeDist  = fDigiBdfPar->GetMaxTimeDist();     // in ns
+  fdMaxSpaceDist = fDigiBdfPar->GetMaxDistAlongCh();  // in cm
+
+  if (fMaxTimeDist != fdMaxTimeDist) {
+    fdMaxTimeDist = fMaxTimeDist;  // modify default
+    fdMaxSpaceDist =
+      fdMaxTimeDist * fDigiBdfPar->GetSignalSpeed()
+      * 0.5;  // cut consistently on positions (with default signal velocity)
+  }
+
+  LOG(info) << " BuildCluster with MaxTimeDist " << fdMaxTimeDist
+            << ", MaxSpaceDist " << fdMaxSpaceDist;
+
+  if (fiCluMulMax == 0) fiCluMulMax = 100;
+  if (fOutHstFileName == "") { fOutHstFileName = "./tofEventClust.hst.root"; }
+
+  LOG(info) << " Hst Output filename = " << fOutHstFileName;
+
+  LOG(info) << "<I>  BeamRefType = " << fiBeamRefType << ", Sm " << fiBeamRefSm
+            << ", Det " << fiBeamRefDet << ", MulMax " << fiBeamRefMulMax;
+
+  return kTRUE;
+}
+/************************************************************************************/
+Bool_t CbmTofHitMaker::InitCalibParameter() {
+  // dimension and initialize calib parameter
+  // Int_t iNbDet     = fDigiBdfPar->GetNbDet();  (VF) not used
+  Int_t iNbSmTypes = fDigiBdfPar->GetNbSmTypes();
+
+  if (fTotMean != 0.) fdTTotMean = fTotMean;  // adjust target mean for TOT
+
+  fvCPTOff.resize(iNbSmTypes);
+  fvCPTotGain.resize(iNbSmTypes);
+  fvCPTotOff.resize(iNbSmTypes);
+  fvCPWalk.resize(iNbSmTypes);
+  fvCPDelTof.resize(iNbSmTypes);
+  for (Int_t iSmType = 0; iSmType < iNbSmTypes; iSmType++) {
+    Int_t iNbSm  = fDigiBdfPar->GetNbSm(iSmType);
+    Int_t iNbRpc = fDigiBdfPar->GetNbRpc(iSmType);
+    fvCPTOff[iSmType].resize(iNbSm * iNbRpc);
+    fvCPTotGain[iSmType].resize(iNbSm * iNbRpc);
+    fvCPTotOff[iSmType].resize(iNbSm * iNbRpc);
+    fvCPWalk[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++) {
+        //          LOG(info)<<Form(" fvCPDelTof resize for SmT %d, R %d, B %d ",iSmType,iNbSm*iNbRpc,nbClDelTofBinX)
+        //           ;
+        fvCPDelTof[iSmType][iSm * iNbRpc + iRpc].resize(nbClDelTofBinX);
+        for (Int_t iBx = 0; iBx < nbClDelTofBinX; iBx++) {
+          // LOG(info)<<Form(" fvCPDelTof for SmT %d, R %d, B %d",iSmType,iSm*iNbRpc+iRpc,iBx);
+          fvCPDelTof[iSmType][iSm * iNbRpc + iRpc][iBx].resize(iNSel);
+          for (Int_t iSel = 0; iSel < iNSel; iSel++)
+            fvCPDelTof[iSmType][iSm * iNbRpc + iRpc][iBx][iSel] =
+              0.;  // initialize
+        }
+
+        Int_t iNbChan = fDigiBdfPar->GetNbChan(iSmType, iRpc);
+        fvCPTOff[iSmType][iSm * iNbRpc + iRpc].resize(iNbChan);
+        fvCPTotGain[iSmType][iSm * iNbRpc + iRpc].resize(iNbChan);
+        fvCPTotOff[iSmType][iSm * iNbRpc + iRpc].resize(iNbChan);
+        fvCPWalk[iSmType][iSm * iNbRpc + iRpc].resize(iNbChan);
+        Int_t nbSide = 2 - fDigiBdfPar->GetChanType(iSmType, iRpc);
+        for (Int_t iCh = 0; iCh < iNbChan; iCh++) {
+          fvCPTOff[iSmType][iSm * iNbRpc + iRpc][iCh].resize(nbSide);
+          fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh].resize(nbSide);
+          fvCPTotOff[iSmType][iSm * iNbRpc + iRpc][iCh].resize(nbSide);
+          fvCPWalk[iSmType][iSm * iNbRpc + iRpc][iCh].resize(nbSide);
+          for (Int_t iSide = 0; iSide < nbSide; iSide++) {
+            fvCPTOff[iSmType][iSm * iNbRpc + iRpc][iCh][iSide] =
+              0.;  //initialize
+            fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][iSide] =
+              1.;  //initialize
+            fvCPTotOff[iSmType][iSm * iNbRpc + iRpc][iCh][iSide] =
+              0.;  //initialize
+            fvCPWalk[iSmType][iSm * iNbRpc + iRpc][iCh][iSide].resize(
+              nbClWalkBinX);
+            for (Int_t iWx = 0; iWx < nbClWalkBinX; iWx++) {
+              fvCPWalk[iSmType][iSm * iNbRpc + iRpc][iCh][iSide][iWx] = 0.;
+            }
+          }
+        }
+      }
+    }
+  }
+  LOG(info) << "CbmTofHitMaker::InitCalibParameter: defaults set";
+
+  TDirectory* oldir =
+    gDirectory;  // <= To prevent histos from being sucked in by the param file of the TRootManager!
+  /*
+	 gROOT->cd(); // <= To prevent histos from being sucked in by the param file of the TRootManager !
+	 */
+
+  if (0 < fCalMode) {
+    LOG(info) << "CbmTofHitMaker::InitCalibParameter: read histos from "
+              << "file " << fCalParFileName;
+
+    // read parameter from histos
+    if (fCalParFileName.IsNull()) return kTRUE;
+
+    fCalParFile = new TFile(fCalParFileName, "");
+    if (NULL == fCalParFile) {
+      LOG(fatal) << "CbmTofHitMaker::InitCalibParameter: "
+                 << "file " << fCalParFileName << " does not exist!";
+      return kTRUE;
+    }
+    /*
+		 gDirectory->Print();
+		 fCalParFile->cd();
+		 fCalParFile->ls();
+		 */
+    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(oldir->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(oldir->GetPath());
+          // TProfile *hFparmem = (TProfile *)hFparcur->Clone();  (VF) not used
+          gDirectory->cd(curdir->GetPath());
+        }
+      }
+
+      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 (Vscal == 0.) Vscal = 1.;
+            fDigiBdfPar->SetSigVel(iSmType,
+                                   iSm,
+                                   iRpc,
+                                   fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc)
+                                     * Vscal);
+            LOG(info) << "Modify " << iSmType << iSm << iRpc << " Svel by "
+                      << Vscal << " to "
+                      << fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc);
+          }
+          TH2F* htempPos_pfx = (TH2F*) gDirectory->FindObjectAny(
+            Form("cl_CorSmT%01d_sm%03d_rpc%03d_Pos_pfx", iSmType, iSm, iRpc));
+          TH2F* htempTOff_pfx = (TH2F*) gDirectory->FindObjectAny(
+            Form("cl_CorSmT%01d_sm%03d_rpc%03d_TOff_pfx", iSmType, iSm, iRpc));
+          TH1D* htempTot_Mean = (TH1D*) gDirectory->FindObjectAny(
+            Form("cl_CorSmT%01d_sm%03d_rpc%03d_Tot_Mean", iSmType, iSm, iRpc));
+          TH1D* htempTot_Off = (TH1D*) gDirectory->FindObjectAny(
+            Form("cl_CorSmT%01d_sm%03d_rpc%03d_Tot_Off", iSmType, iSm, iRpc));
+          if (NULL != htempPos_pfx && NULL != htempTOff_pfx
+              && NULL != htempTot_Mean && NULL != htempTot_Off) {
+            Int_t iNbCh    = fDigiBdfPar->GetNbChan(iSmType, iRpc);
+            Int_t iNbinTot = htempTot_Mean->GetNbinsX();
+            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);  
+              Double_t TMean =
+                ((TProfile*) htempTOff_pfx)->GetBinContent(iCh + 1);
+              //Double_t dTYOff=YMean/fDigiBdfPar->GetSignalSpeed() ;
+              Double_t dTYOff =
+                YMean / fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc);
+              fvCPTOff[iSmType][iSm * iNbRpc + iRpc][iCh][0] += -dTYOff + TMean;
+              fvCPTOff[iSmType][iSm * iNbRpc + iRpc][iCh][1] += +dTYOff + TMean;
+
+              if (5 == iSmType || 8 == iSmType) {  // for PAD counters
+                fvCPTOff[iSmType][iSm * iNbRpc + iRpc][iCh][1] =
+                  fvCPTOff[iSmType][iSm * iNbRpc + iRpc][iCh][0];
+                fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][1] =
+                  fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][0];
+                fvCPTotOff[iSmType][iSm * iNbRpc + iRpc][iCh][1] =
+                  fvCPTotOff[iSmType][iSm * iNbRpc + iRpc][iCh][0];
+              }
+
+              LOG(debug) << "CbmTofHitMaker::InitCalibParameter:"
+                         << " SmT " << iSmType << " Sm " << iSm << " Rpc "
+                         << iRpc << " Ch " << iCh
+                         << Form(": YMean %f, TMean %f", YMean, TMean) << " -> "
+                         << Form(
+                              " %f, %f, %f, %f ",
+                              fvCPTOff[iSmType][iSm * iNbRpc + iRpc][iCh][0],
+                              fvCPTOff[iSmType][iSm * iNbRpc + iRpc][iCh][1],
+                              fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][0],
+                              fvCPTotGain[iSmType][iSm * iNbRpc + iRpc][iCh][1])
+                         << ", NbinTot " << iNbinTot;
+
+              TH1D* htempWalk0 = (TH1D*) gDirectory->FindObjectAny(
+                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) {  // reinitialize Walk array
+                LOG(debug) << "Initialize Walk correction for "
+                           << Form(" SmT%01d_sm%03d_rpc%03d_Ch%03d",
+                                   iSmType,
+                                   iSm,
+                                   iRpc,
+                                   iCh);
+                if (htempWalk0->GetNbinsX() != nbClWalkBinX)
+                  LOG(error) << "CbmTofHitMaker::InitCalibParameter: "
+                                "Inconsistent Walk histograms";
+                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 (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 (5 == iSmType || 8 == iSmType) {  // Pad structure
+                    fvCPWalk[iSmType][iSm * iNbRpc + iRpc][iCh][1][iBin] =
+                      fvCPWalk[iSmType][iSm * iNbRpc + iRpc][iCh][0][iBin];
+                  }
+                }
+              } else {
+                LOG(info) << "No Walk histograms for TSRC " << iSmType << iSm
+                          << iRpc << iCh;
+              }
+            }
+          } else {
+            LOG(warning) << " Calibration histos "
+                         << Form("cl_SmT%01d_sm%03d_rpc%03d_XXX",
+                                 iSmType,
+                                 iSm,
+                                 iRpc)
+                         << " not found. ";
+          }
+          for (Int_t iSel = 0; iSel < iNSel; iSel++) {
+            TH1D* htmpDelTof = (TH1D*) gDirectory->FindObjectAny(
+              Form("cl_CorSmT%01d_sm%03d_rpc%03d_Sel%02d_DelTof",
+                   iSmType,
+                   iSm,
+                   iRpc,
+                   iSel));
+            if (NULL == htmpDelTof) {
+              LOG(debug) << " Histos "
+                         << Form("cl_CorSmT%01d_sm%03d_rpc%03d_Sel%02d_DelTof",
+                                 iSmType,
+                                 iSm,
+                                 iRpc,
+                                 iSel)
+                         << " not found. ";
+              continue;
+            }
+            LOG(debug) << " Load DelTof from histos "
+                       << Form("cl_CorSmT%01d_sm%03d_rpc%03d_Sel%02d_DelTof",
+                               iSmType,
+                               iSm,
+                               iRpc,
+                               iSel)
+                       << ".";
+            for (Int_t iBx = 0; iBx < nbClDelTofBinX; iBx++) {
+              fvCPDelTof[iSmType][iSm * iNbRpc + iRpc][iBx][iSel] +=
+                htmpDelTof->GetBinContent(iBx + 1);
+            }
+
+            // copy Histo to memory
+            // TDirectory * curdir = gDirectory;
+            gDirectory->cd(oldir->GetPath());
+            TH1D* h1DelTof = (TH1D*) htmpDelTof->Clone(
+              Form("cl_CorSmT%01d_sm%03d_rpc%03d_Sel%02d_DelTof",
+                   iSmType,
+                   iSm,
+                   iRpc,
+                   iSel));
+
+            LOG(debug) << " copy histo " << h1DelTof->GetName()
+                       << " to directory " << oldir->GetName();
+
+            gDirectory->cd(curdir->GetPath());
+          }
+        }
+    }
+  }
+  //   fCalParFile->Delete();
+  gDirectory->cd(
+    oldir
+      ->GetPath());  // <= To prevent histos from being sucked in by the param file of the TRootManager!
+  LOG(info)
+    << "CbmTofHitMaker::InitCalibParameter: initialization done";
+  return kTRUE;
+}
+/************************************************************************************/
+Bool_t CbmTofHitMaker::LoadGeometry() {
+  LOG(info) << "CbmTofHitMaker::LoadGeometry starting for  "
+            << fDigiBdfPar->GetNbDet() << " described detectors, "
+            << fDigiPar->GetNrOfModules() << " geometrically known cells ";
+
+  Int_t iNrOfCells = fDigiPar->GetNrOfModules();
+  LOG(info) << "Digi Parameter container contains " << iNrOfCells << " cells.";
+  for (Int_t icell = 0; icell < iNrOfCells; ++icell) {
+
+    Int_t cellId =
+      fDigiPar->GetCellId(icell);  // cellId is assigned in CbmTofCreateDigiPar
+    fChannelInfo = fDigiPar->GetCell(cellId);
+
+    Int_t smtype  = fGeoHandler->GetSMType(cellId);
+    Int_t smodule = fGeoHandler->GetSModule(cellId);
+    Int_t module  = fGeoHandler->GetCounter(cellId);
+    Int_t cell    = fGeoHandler->GetCell(cellId);
+
+    Double_t x  = fChannelInfo->GetX();
+    Double_t y  = fChannelInfo->GetY();
+    Double_t z  = fChannelInfo->GetZ();
+    Double_t dx = fChannelInfo->GetSizex();
+    Double_t dy = fChannelInfo->GetSizey();
+    LOG(debug) << "-I- InitPar " << icell << " Id: " << Form("0x%08x", cellId)
+               << " " << cell << " tmcs: " << smtype << " " << smodule << " "
+               << module << " " << cell << " x=" << Form("%6.2f", x)
+               << " y=" << Form("%6.2f", y) << " z=" << Form("%6.2f", z)
+               << " dx=" << dx << " dy=" << dy;
+
+    TGeoNode* fNode =  // prepare local->global trafo
+      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);
+    if (icell == 0) {
+      TGeoHMatrix* cMatrix = gGeoManager->GetCurrentMatrix();
+      fNode->Print();
+      fDigiPar->GetNode(cellId)->Print();
+      cMatrix->Print();
+    }
+  }
+
+  Int_t iNbDet = fDigiBdfPar->GetNbDet();
+  fvDeadStrips.resize(iNbDet);
+  fvTimeLastDigi.resize(iNbDet);
+  fvTimeFirstDigi.resize(iNbDet);
+  fvMulDigi.resize(iNbDet);
+
+  for (Int_t iDetIndx = 0; iDetIndx < iNbDet; iDetIndx++) {
+    Int_t iUniqueId = fDigiBdfPar->GetDetUId(iDetIndx);
+    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)
+              << Form(" Svel %6.6f, DeadStrips 0x%08x ",
+                      fDigiBdfPar->GetSigVel(iSmType, iSmId, iRpcId),
+                      fvDeadStrips[iDetIndx]);
+    Int_t iNbChan = fDigiBdfPar->GetNbChan(iSmType, iRpcId);
+    fvTimeLastDigi[iDetIndx].resize(iNbChan * 2);
+    for (Int_t iCh = 0; iCh < iNbChan * 2; iCh++)
+      fvTimeLastDigi[iDetIndx][iCh] = 0.;
+    fvTimeFirstDigi[iDetIndx].resize(iNbChan * 2);
+    fvMulDigi[iDetIndx].resize(iNbChan * 2);
+    for (Int_t iCh = 0; iCh < iNbChan * 2; iCh++) {
+      fvTimeFirstDigi[iDetIndx][iCh] = 0.;
+      fvMulDigi[iDetIndx][iCh]       = 0.;
+    }
+
+    Int_t iCell = -1;
+    while (kTRUE) {
+      Int_t iUCellId =
+        CbmTofAddress::GetUniqueAddress(iSmId, iRpcId, ++iCell, 0, iSmType);
+      fChannelInfo = fDigiPar->GetCell(iUCellId);
+      if (NULL == fChannelInfo) break;
+      LOG(debug3) << " Cell " << iCell << Form(" 0x%08x ", iUCellId)
+                  << Form(", fCh 0x%p ", fChannelInfo)
+                  << ", x: " << fChannelInfo->GetX()
+                  << ", y: " << fChannelInfo->GetY()
+                  << ", z: " << fChannelInfo->GetZ();
+    }
+  }
+
+  //   return kTRUE;
+
+  Int_t iNbSmTypes = fDigiBdfPar->GetNbSmTypes();
+
+  if (kTRUE == fDigiBdfPar->UseExpandedDigi()) {
+    fStorDigi.resize(iNbSmTypes);
+    fStorDigiInd.resize(iNbSmTypes);
+    fviClusterSize.resize(iNbSmTypes);
+    fviTrkMul.resize(iNbSmTypes);
+    fvdX.resize(iNbSmTypes);
+    fvdY.resize(iNbSmTypes);
+    fvdDifX.resize(iNbSmTypes);
+    fvdDifY.resize(iNbSmTypes);
+    fvdDifCh.resize(iNbSmTypes);
+    fviClusterMul.resize(iNbSmTypes);
+    fvLastHits.resize(iNbSmTypes);
+
+    for (Int_t iSmType = 0; iSmType < iNbSmTypes; iSmType++) {
+      Int_t iNbSm  = fDigiBdfPar->GetNbSm(iSmType);
+      Int_t iNbRpc = fDigiBdfPar->GetNbRpc(iSmType);
+      fStorDigi[iSmType].resize(iNbSm * iNbRpc);
+      fStorDigiInd[iSmType].resize(iNbSm * iNbRpc);
+      fviClusterSize[iSmType].resize(iNbRpc);
+      fviTrkMul[iSmType].resize(iNbRpc);
+      fvdX[iSmType].resize(iNbRpc);
+      fvdY[iSmType].resize(iNbRpc);
+      fvdDifX[iSmType].resize(iNbRpc);
+      fvdDifY[iSmType].resize(iNbRpc);
+      fvdDifCh[iSmType].resize(iNbRpc);
+      for (Int_t iSm = 0; iSm < iNbSm; iSm++) {
+        fviClusterMul[iSmType].resize(iNbSm);
+        fvLastHits[iSmType].resize(iNbSm);
+        for (Int_t iRpc = 0; iRpc < iNbRpc; iRpc++) {
+          fviClusterMul[iSmType][iSm].resize(iNbRpc);
+          fvLastHits[iSmType][iSm].resize(iNbRpc);
+          Int_t iNbChan = fDigiBdfPar->GetNbChan(iSmType, iRpc);
+          if (iNbChan == 0) {
+            LOG(warning) << "CbmTofHitMaker::LoadGeometry: StoreDigi "
+                            "without channels "
+                         << Form("SmTy %3d, Sm %3d, NbRpc %3d, Rpc, %3d ",
+                                 iSmType,
+                                 iSm,
+                                 iNbRpc,
+                                 iRpc);
+          }
+          LOG(debug1)
+            << "CbmTofHitMaker::LoadGeometry: StoreDigi with "
+            << Form(
+                 " %3d %3d %3d %3d %5d ", iSmType, iSm, iNbRpc, iRpc, iNbChan);
+          fStorDigi[iSmType][iSm * iNbRpc + iRpc].resize(iNbChan);
+          fStorDigiInd[iSmType][iSm * iNbRpc + iRpc].resize(iNbChan);
+          fvLastHits[iSmType][iSm][iRpc].resize(iNbChan);
+        }  // for( Int_t iRpc = 0; iRpc < iNbRpc; iRpc++ )
+      }    // for( Int_t iSm = 0; iSm < iNbSm; iSm++ )
+    }      // for( Int_t iSmType = 0; iSmType < iNbSmTypes; iSmType++ )
+  }        // if( kTRUE == fDigiBdfPar->UseExpandedDigi() )
+
+  return kTRUE;
+}
+Bool_t CbmTofHitMaker::DeleteGeometry() {
+  LOG(info) << "CbmTofHitMaker::DeleteGeometry starting";
+  return kTRUE;
+  Int_t iNbSmTypes = fDigiBdfPar->GetNbSmTypes();
+  if (kTRUE == fDigiBdfPar->UseExpandedDigi()) {
+    for (Int_t iSmType = 0; iSmType < iNbSmTypes; iSmType++) {
+      Int_t iNbSm  = fDigiBdfPar->GetNbSm(iSmType);
+      Int_t iNbRpc = fDigiBdfPar->GetNbRpc(iSmType);
+      for (Int_t iSm = 0; iSm < iNbSm; iSm++) {
+        for (Int_t iRpc = 0; iRpc < iNbRpc; iRpc++) {
+          fStorDigi[iSmType][iSm * iNbRpc + iRpc].clear();
+          fStorDigiInd[iSmType][iSm * iNbRpc + iRpc].clear();
+        }
+      }  // for( Int_t iSm = 0; iSm < iNbSm; iSm++ )
+      fStorDigi[iSmType].clear();
+      fStorDigiInd[iSmType].clear();
+    }  // for( Int_t iSmType = 0; iSmType < iNbSmTypes; iSmType++ )
+    fStorDigi.clear();
+    fStorDigiInd.clear();
+  }  // if( kTRUE == fDigiBdfPar->UseExpandedDigi() )
+  return kTRUE;
+}
+/************************************************************************************/
+// Histogramming functions
+Bool_t CbmTofHitMaker::CreateHistos() {
+  // <= To prevent histos from being sucked in by the param file of the TRootManager!
+  TDirectory* oldir = gDirectory;  
+  gROOT->cd();  
+  fhClustBuildTime =
+    new TH1I("TofClustBuildTime",
+             "Time needed to build clusters in each event; Time [s]",
+             100, 0.0, 4.0);
+  gDirectory->cd(oldir->GetPath());  
+  // <= To prevent histos from being sucked in by the param file of the TRootManager!
+
+  return kTRUE;
+}
+
+Bool_t CbmTofHitMaker::FillHistos() {
+  fhClustBuildTime->Fill(fStop.GetSec() - fStart.GetSec()
+                         + (fStop.GetNanoSec() - fStart.GetNanoSec()) / 1e9);
+  return kTRUE;
+}
+
+Bool_t CbmTofHitMaker::WriteHistos() {
+  TDirectory* oldir = gDirectory;
+  TFile* fHist;
+  fHist = new TFile(fOutHstFileName, "RECREATE");
+  fHist->cd();
+  fhClustBuildTime->Write();
+  gDirectory->cd(oldir->GetPath());
+  fHist->Close();
+
+  return kTRUE;
+}
+Bool_t CbmTofHitMaker::DeleteHistos() {
+  delete fhClustBuildTime;
+  return kTRUE;
+}
+/************************************************************************************/
+Bool_t CbmTofHitMaker::BuildClusters() {
+  //gGeoManager->SetTopVolume( gGeoManager->FindVolumeFast("tof_v14a") );
+  gGeoManager->CdTop();
+
+  //  if(NULL == fTofDigisColl) {
+  if (fTofDigiVec.empty()) {
+    LOG(info) << " No RawDigis defined ! Check! ";
+    return kFALSE;
+  }
+  fiNevtBuild++;
+  LOG(debug)
+    << "Build clusters from "
+    //            <<fTofDigisColl->GetEntries()<<" digis in event "<<fiNevtBuild;
+    << fTofDigiVec.size() << " digis in event " << fiNevtBuild;
+
+  fTRefHits = 0.;
+
+  Int_t iNbTofDigi = fTofDigiVec.size();
+  //Int_t iNbTofDigi = fTofDigisColl->GetEntries();
+  if (iNbTofDigi > 100000) {
+    LOG(warning) << "Too many digis in event " << fiNevtBuild;
+    return kFALSE;
+  }
+  if (bAddBeamCounterSideDigi) {
+    // Duplicate type "5" - digis
+    // Int_t iNbDigi=iNbTofDigi;
+    for (Int_t iDigInd = 0; iDigInd < iNbTofDigi; iDigInd++) {
+      CbmTofDigi* pDigi = &(fTofDigiVec.at(iDigInd));
+      //CbmTofDigi *pDigi = (CbmTofDigi*) fTofDigisColl->At( iDigInd );
+      if (pDigi->GetType() == 5) {
+        if (pDigi->GetSide() == 1) {
+          bAddBeamCounterSideDigi = kFALSE;  // disable for current data set
+          LOG(info) << "Start counter digi duplication disabled";
+          break;
+        }
+        fTofDigiVec.push_back(CbmTofDigi(*pDigi));
+        CbmTofDigi* pDigiN = &(fTofDigiVec.back());
+        //	 CbmTofDigi *pDigiN  = new((*fTofDigisColl)[iNbDigi++]) CbmTofDigi( *pDigi );
+        pDigiN->SetAddress(pDigi->GetSm(),
+                           pDigi->GetRpc(),
+                           pDigi->GetChannel(),
+                           (0 == pDigi->GetSide()) ? 1 : 0,
+                           pDigi->GetType());
+        LOG(debug) << "Duplicated digi " << fTofDigiVec.size()
+                   << " with address 0x" << std::hex << pDigiN->GetAddress();
+      }
+    }
+    iNbTofDigi = fTofDigiVec.size();
+    //iNbTofDigi = fTofDigisColl->GetEntries(); // Update
+  }
+
+  if (kTRUE) {
+    for (UInt_t iDetIndx = 0; iDetIndx < fvTimeFirstDigi.size(); iDetIndx++)
+      for (UInt_t iCh = 0; iCh < fvTimeFirstDigi[iDetIndx].size(); iCh++) {
+        fvTimeFirstDigi[iDetIndx][iCh] = 0.;
+        fvMulDigi[iDetIndx][iCh]       = 0.;
+      }
+
+    for (Int_t iDigInd = 0; iDigInd < iNbTofDigi; iDigInd++) {
+      //CbmTofDigi *pDigi = (CbmTofDigi*) fTofDigisColl->At( iDigInd );
+      CbmTofDigi* pDigi = &(fTofDigiVec.at(iDigInd));
+      Int_t iDetIndx    = fDigiBdfPar->GetDetInd(pDigi->GetAddress());
+
+      LOG(debug) << iDigInd << " " << pDigi
+                 << Form(" Address : 0x%08x ", pDigi->GetAddress()) << " SmT "
+                 << pDigi->GetType() << " Sm " << pDigi->GetSm() << " Rpc "
+                 << pDigi->GetRpc() << " Ch " << pDigi->GetChannel() << " S "
+                 << pDigi->GetSide() << ", DetIndx " << iDetIndx << " : "
+                 << pDigi->ToString()
+        //         <<" Time "<<pDigi->GetTime()
+        //         <<" Tot " <<pDigi->GetTot()
+        ;
+
+      if (fDigiBdfPar->GetNbDet() - 1 < iDetIndx || iDetIndx < 0) {
+        LOG(debug) << Form(
+          " Wrong DetIndx %d >< %d ", iDetIndx, fDigiBdfPar->GetNbDet());
+        break;
+      }
+
+      size_t iDigiCh = pDigi->GetChannel() * 2 + pDigi->GetSide();
+      if (iDigiCh < fvTimeLastDigi[iDetIndx].size()) {
+        fvTimeLastDigi[iDetIndx][iDigiCh] = pDigi->GetTime();
+
+        if (fvTimeFirstDigi[iDetIndx][iDigiCh] != 0.) {
+          fvMulDigi[iDetIndx][iDigiCh]++;
+        } else {
+          fvTimeFirstDigi[iDetIndx][iDigiCh] = pDigi->GetTime();
+          fvMulDigi[iDetIndx][iDigiCh]++;
+        }
+      }
+    }
+    for (UInt_t iDetIndx = 0; iDetIndx < fvTimeFirstDigi.size(); iDetIndx++)
+      for (UInt_t iCh = 0; iCh < fvTimeFirstDigi[iDetIndx].size(); iCh++) {
+        if (fvTimeFirstDigi[iDetIndx][iCh] != 0.)
+          fhRpcDigiDTMul[iDetIndx]->Fill(iCh, fvMulDigi[iDetIndx][iCh]);
+      }
+  }  // kTRUE end
+
+  // Calibrate RawDigis
+  if (kTRUE == fDigiBdfPar->UseExpandedDigi()) {
+    CbmTofDigi* pDigi;
+    // CbmTofDigi *pCalDigi=NULL;  (VF) not used
+    CalibRawDigis();
+
+    // Then loop over the digis array and store the Digis in separate vectors for
+    // each RPC modules
+
+    //      iNbTofDigi = fTofCalDigisColl->GetEntries();
+    iNbTofDigi = fTofCalDigiVec->size();
+    for (Int_t iDigInd = 0; iDigInd < iNbTofDigi; iDigInd++) {
+      //         pDigi = (CbmTofDigi*) fTofCalDigisColl->At( iDigInd );
+      pDigi = &(fTofCalDigiVec->at(iDigInd));
+      LOG(debug1) << "AC "  // After Calibration
+                  << Form("0x%08x", pDigi->GetAddress()) << " TSRC "
+                  << pDigi->GetType() << pDigi->GetSm() << pDigi->GetRpc()
+                  << Form("%2d", (Int_t) pDigi->GetChannel()) << " "
+                  << pDigi->GetSide() << " " << Form("%f", pDigi->GetTime())
+                  << " " << pDigi->GetTot();
+
+      if (fDigiBdfPar->GetNbSmTypes()
+            > pDigi->GetType()  // prevent crash due to misconfiguration
+          && fDigiBdfPar->GetNbSm(pDigi->GetType()) > pDigi->GetSm()
+          && fDigiBdfPar->GetNbRpc(pDigi->GetType()) > pDigi->GetRpc()
+          && fDigiBdfPar->GetNbChan(pDigi->GetType(), pDigi->GetRpc())
+               > pDigi->GetChannel()) {
+        fStorDigi[pDigi->GetType()]
+                 [pDigi->GetSm() * fDigiBdfPar->GetNbRpc(pDigi->GetType())
+                  + pDigi->GetRpc()][pDigi->GetChannel()]
+                   .push_back(pDigi);
+        fStorDigiInd[pDigi->GetType()]
+                    [pDigi->GetSm() * fDigiBdfPar->GetNbRpc(pDigi->GetType())
+                     + pDigi->GetRpc()][pDigi->GetChannel()]
+                      .push_back(iDigInd);
+      } else {
+        LOG(info) << "Skip2 Digi "
+                  << " Type " << pDigi->GetType() << " "
+                  << fDigiBdfPar->GetNbSmTypes() << " Sm " << pDigi->GetSm()
+                  << " " << fDigiBdfPar->GetNbSm(pDigi->GetType()) << " Rpc "
+                  << pDigi->GetRpc() << " "
+                  << fDigiBdfPar->GetNbRpc(pDigi->GetType()) << " Ch "
+                  << pDigi->GetChannel() << " "
+                  << fDigiBdfPar->GetNbChan(pDigi->GetType(), 0);
+      }
+    }  // for( Int_t iDigInd = 0; iDigInd < nTofDigi; iDigInd++ )
+
+    // inspect digi array
+    Int_t iNbDet = fDigiBdfPar->GetNbDet();
+    for (Int_t iDetIndx = 0; iDetIndx < iNbDet; iDetIndx++) {
+      Int_t iDetId    = fviDetId[iDetIndx];
+      Int_t iSmType   = CbmTofAddress::GetSmType(iDetId);
+      Int_t iSm       = CbmTofAddress::GetSmId(iDetId);
+      Int_t iRpc      = CbmTofAddress::GetRpcId(iDetId);
+      Int_t iNbStrips = fDigiBdfPar->GetNbChan(iSmType, iRpc);
+      for (Int_t iStrip = 0; iStrip < iNbStrips; iStrip++) {
+        Int_t iDigiMul = fStorDigi[iSmType][iSm * fDigiBdfPar->GetNbRpc(iSmType)
+                                            + iRpc][iStrip]
+                           .size();
+        //LOG(info)<<"Inspect TSRC "<<iSmType<<iSm<<iRpc<<iStrip<<" with "<<iNbStrips<<" strips: Mul "<<iDigiMul;
+        if (iDigiMul > 0) {
+          fhRpcDigiMul[iDetIndx]->Fill(iStrip, iDigiMul);
+          if (iDigiMul == 1) {
+            fhRpcDigiStatus[iDetIndx]->Fill(iStrip, 0);
+            if (iStrip > 0)
+              if (fStorDigi[iSmType][iSm * fDigiBdfPar->GetNbRpc(iSmType)
+                                     + iRpc][iStrip - 1]
+                    .size()
+                  > 1) {
+                fhRpcDigiStatus[iDetIndx]->Fill(iStrip, 1);
+                if (TMath::Abs(
+                      fStorDigi[iSmType][iSm * fDigiBdfPar->GetNbRpc(iSmType)
+                                         + iRpc][iStrip][0]
+                        ->GetTime()
+                      - fStorDigi[iSmType][iSm * fDigiBdfPar->GetNbRpc(iSmType)
+                                           + iRpc][iStrip - 1][0]
+                          ->GetTime())
+                    < fMaxTimeDist)
+                  fhRpcDigiStatus[iDetIndx]->Fill(iStrip, 3);
+              }
+            if (iStrip < iNbStrips - 2) {
+              if (fStorDigi[iSmType][iSm * fDigiBdfPar->GetNbRpc(iSmType)
+                                     + iRpc][iStrip + 1]
+                    .size()
+                  > 1) {
+                fhRpcDigiStatus[iDetIndx]->Fill(iStrip, 2);
+                if (TMath::Abs(
+                      fStorDigi[iSmType][iSm * fDigiBdfPar->GetNbRpc(iSmType)
+                                         + iRpc][iStrip][0]
+                        ->GetTime()
+                      - fStorDigi[iSmType][iSm * fDigiBdfPar->GetNbRpc(iSmType)
+                                           + iRpc][iStrip + 1][0]
+                          ->GetTime())
+                    < fMaxTimeDist)
+                  fhRpcDigiStatus[iDetIndx]->Fill(iStrip, 4);
+              }
+            }
+          }
+        }
+      }
+    }
+
+    BuildHits();
+
+  }  // if( kTRUE == fDigiBdfPar->UseExpandedDigi() )
+  else {
+    LOG(error) << " Compressed Digis not implemented ... ";
+    return kFALSE;  // not implemented properly yet
+  }
+  return kTRUE;
+}
+
+Bool_t CbmTofHitMaker::MergeClusters() {
+  // Merge clusters from neigbouring Rpc within a (Super)Module
+  if (NULL == fTofHitsColl) {
+    LOG(info) << " No Hits defined ! Check! ";
+    return kFALSE;
+  }
+  // inspect hits
+  for (Int_t iHitInd = 0; iHitInd < fTofHitsColl->GetEntries(); iHitInd++) {
+    CbmTofHit* pHit = (CbmTofHit*) fTofHitsColl->At(iHitInd);
+    if (NULL == pHit) continue;
+
+    Int_t iDetId  = (pHit->GetAddress() & DetMask);
+    Int_t iSmType = CbmTofAddress::GetSmType(iDetId);
+    Int_t iNbRpc  = fDigiBdfPar->GetNbRpc(iSmType);
+    if (iSmType != 5 && iSmType != 8) continue;  // only merge diamonds and Pad
+    LOG(debug) << "MergeClusters: in SmT " << iSmType << " for " << iNbRpc
+               << " Rpcs";
+
+    if (iNbRpc > 1) {  // check for possible mergers
+      Int_t iSm    = CbmTofAddress::GetSmId(iDetId);
+      Int_t iRpc   = CbmTofAddress::GetRpcId(iDetId);
+      Int_t iChId  = pHit->GetAddress();
+      fChannelInfo = fDigiPar->GetCell(iChId);
+      Int_t iCh    = CbmTofAddress::GetChannelId(iChId);
+      LOG(debug) << "MergeClusters: Check for mergers in "
+                 << Form(" SmT %d, Sm %d, Rpc %d, Ch %d - hit %d",
+                         iSmType,
+                         iSm,
+                         iRpc,
+                         iCh,
+                         iHitInd);
+      for (Int_t iHitInd2 = iHitInd + 1; iHitInd2 < fTofHitsColl->GetEntries();
+           iHitInd2++) {
+        CbmTofHit* pHit2 = (CbmTofHit*) fTofHitsColl->At(iHitInd2);
+        if (NULL == pHit2) continue;
+        Int_t iDetId2  = (pHit2->GetAddress() & DetMask);
+        Int_t iSmType2 = CbmTofAddress::GetSmType(iDetId2);
+        if (iSmType2 == iSmType) {
+          Int_t iSm2 = CbmTofAddress::GetSmId(iDetId2);
+          if (iSm2 == iSm || iSmType == 5) {
+            Int_t iRpc2 = CbmTofAddress::GetRpcId(iDetId2);
+            if (TMath::Abs(iRpc - iRpc2) == 1
+                || iSm2 != iSm) {  // Found neighbour
+              Int_t iChId2 = pHit2->GetAddress();
+              // CbmTofCell  *fChannelInfo2 = fDigiPar->GetCell( iChId2 );  (VF) not used
+              Int_t iCh2     = CbmTofAddress::GetChannelId(iChId2);
+              Double_t xPos  = pHit->GetX();
+              Double_t yPos  = pHit->GetY();
+              Double_t tof   = pHit->GetTime();
+              Double_t xPos2 = pHit2->GetX();
+              Double_t yPos2 = pHit2->GetY();
+              Double_t tof2  = pHit2->GetTime();
+              LOG(debug) << "MergeClusters: Found hit in neighbour "
+                         << Form(" SmT %d, Sm %d, Rpc %d, Ch %d - hit %d",
+                                 iSmType2,
+                                 iSm2,
+                                 iRpc2,
+                                 iCh2,
+                                 iHitInd2)
+                         << Form(" DX %6.1f, DY %6.1f, DT %6.1f",
+                                 xPos - xPos2,
+                                 yPos - yPos2,
+                                 tof - tof2);
+
+              if (TMath::Abs(xPos - xPos2) < fdCaldXdYMax * 2.
+                  && TMath::Abs(yPos - yPos2) < fdCaldXdYMax * 2.
+                  && TMath::Abs(tof - tof2) < fMaxTimeDist) {
+
+                CbmMatch* digiMatch =
+                  (CbmMatch*) fTofDigiMatchColl->At(iHitInd);
+                Double_t dTot = 0;
+                for (Int_t iLink = 0; iLink < digiMatch->GetNofLinks();
+                     iLink += 2) {  // loop over digis
+                  CbmLink L0      = digiMatch->GetLink(iLink);
+                  UInt_t iDigInd0 = L0.GetIndex();
+                  UInt_t iDigInd1 = (digiMatch->GetLink(iLink + 1)).GetIndex();
+                  //                    if (iDigInd0 < fTofCalDigisColl->GetEntries() && iDigInd1 < fTofCalDigisColl->GetEntries()){
+                  if (iDigInd0 < fTofCalDigiVec->size()
+                      && iDigInd1 < fTofCalDigiVec->size()) {
+                    //                      CbmTofDigi *pDig0 = (CbmTofDigi*) (fTofCalDigisColl->At(iDigInd0));
+                    //                      CbmTofDigi *pDig1 = (CbmTofDigi*) (fTofCalDigisColl->At(iDigInd1));
+                    CbmTofDigi* pDig0 = &(fTofCalDigiVec->at(iDigInd0));
+                    CbmTofDigi* pDig1 = &(fTofCalDigiVec->at(iDigInd1));
+                    dTot += pDig0->GetTot();
+                    dTot += pDig1->GetTot();
+                  }
+                }
+
+                CbmMatch* digiMatch2 =
+                  (CbmMatch*) fTofDigiMatchColl->At(iHitInd2);
+                Double_t dTot2 = 0;
+                for (Int_t iLink = 0; iLink < digiMatch2->GetNofLinks();
+                     iLink += 2) {  // loop over digis
+                  CbmLink L0      = digiMatch2->GetLink(iLink);
+                  UInt_t iDigInd0 = L0.GetIndex();
+                  UInt_t iDigInd1 = (digiMatch2->GetLink(iLink + 1)).GetIndex();
+                  //                    if (iDigInd0 < fTofCalDigisColl->GetEntries() && iDigInd1 < fTofCalDigisColl->GetEntries()){
+                  if (iDigInd0 < fTofCalDigiVec->size()
+                      && iDigInd1 < fTofCalDigiVec->size()) {
+                    //                      CbmTofDigi *pDig0 = (CbmTofDigi*) (fTofCalDigisColl->At(iDigInd0));
+                    //                      CbmTofDigi *pDig1 = (CbmTofDigi*) (fTofCalDigisColl->At(iDigInd1));
+                    CbmTofDigi* pDig0 = &(fTofCalDigiVec->at(iDigInd0));
+                    CbmTofDigi* pDig1 = &(fTofCalDigiVec->at(iDigInd1));
+                    dTot2 += pDig0->GetTot();
+                    dTot2 += pDig1->GetTot();
+                    digiMatch->AddLink(CbmLink(pDig0->GetTot(),
+                                               iDigInd0,
+                                               fiOutputTreeEntry,
+                                               fiFileIndex));
+                    digiMatch->AddLink(CbmLink(pDig1->GetTot(),
+                                               iDigInd1,
+                                               fiOutputTreeEntry,
+                                               fiFileIndex));
+                  }
+                }
+                LOG(debug) << "MergeClusters: Found merger in neighbour "
+                           << Form(" SmT %d, Sm %d, Rpc %d, Ch %d - hit %d(%d)",
+                                   iSmType2,
+                                   iSm2,
+                                   iRpc2,
+                                   iCh2,
+                                   iHitInd2,
+                                   fTofHitsColl->GetEntries())
+                           << Form(" DX %6.1f, DY %6.1f, DT %6.1f",
+                                   xPos - xPos2,
+                                   yPos - yPos2,
+                                   tof - tof2)
+                           << Form(" Tots %6.1f - %6.1f", dTot, dTot2);
+                Double_t dTotSum = dTot + dTot2;
+                Double_t dxPosM  = (xPos * dTot + xPos2 * dTot2) / dTotSum;
+                Double_t dyPosM  = (yPos * dTot + yPos2 * dTot2) / dTotSum;
+                Double_t dtofM   = (tof * dTot + tof2 * dTot2) / dTotSum;
+                pHit->SetX(dxPosM);
+                pHit->SetY(dyPosM);
+                pHit->SetTime(dtofM);
+
+                // remove merged hit at iHitInd2 and update digiMatch
+
+                fTofHitsColl->RemoveAt(iHitInd2);
+                fTofDigiMatchColl->RemoveAt(iHitInd2);
+                fTofDigiMatchColl->Compress();
+                fTofHitsColl->Compress();
+                LOG(debug) << "MergeClusters: Compress TClonesArrays to "
+                           << fTofHitsColl->GetEntries() << ", "
+                           << fTofDigiMatchColl->GetEntries();
+                /*
+								 for(Int_t i=iHitInd2; i<fTofHitsColl->GetEntries(); i++){ // update RefLinks
+								 CbmTofHit *pHiti = (CbmTofHit*) fTofHitsColl->At( i );
+								 pHiti->SetRefId(i);
+								 }
+								 */
+                //check merged hit (cluster)
+                //pHit->Print();
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return kTRUE;
+}
+
+static Double_t f1_xboxe(double* x, double* par) {
+  double xx    = x[0];
+  double wx    = 1. - par[4] * TMath::Power(xx + par[5], 2);
+  double xboxe = par[0] * 0.25
+                 * (1. + TMath::Erf((xx + par[1] - par[3]) / par[2]))
+                 * (1. + TMath::Erf((-xx + par[1] + par[3]) / par[2]));
+  return xboxe * wx;
+}
+
+void CbmTofHitMaker::fit_ybox(const char* hname) {
+  TH1* h1;
+  h1 = (TH1*) gROOT->FindObjectAny(hname);
+  if (NULL != h1) { fit_ybox(h1, 0.); }
+}
+
+void CbmTofHitMaker::fit_ybox(TH1* h1, Double_t ysize) {
+  Double_t* fpar = NULL;
+  fit_ybox(h1, ysize, fpar);
+}
+
+void CbmTofHitMaker::fit_ybox(TH1* h1,
+                                      Double_t ysize,
+                                      Double_t* fpar = NULL) {
+  TAxis* xaxis  = h1->GetXaxis();
+  Double_t Ymin = xaxis->GetXmin();
+  Double_t Ymax = xaxis->GetXmax();
+  TF1* f1       = new TF1("YBox", f1_xboxe, Ymin, Ymax, 6);
+  Double_t yini = (h1->GetMaximum() + h1->GetMinimum()) * 0.5;
+  if (ysize == 0.) ysize = Ymax * 0.8;
+  f1->SetParameters(yini, ysize * 0.5, 1., 0., 0., 0.);
+  //  f1->SetParLimits(1,ysize*0.8,ysize*1.2);
+  f1->SetParLimits(2, 0.2, 3.);
+  f1->SetParLimits(3, -4., 4.);
+  if (fpar != NULL) {
+    Double_t fp[4];
+    for (Int_t i = 0; i < 4; i++)
+      fp[i] = *fpar++;
+    for (Int_t i = 0; i < 4; i++)
+      f1->SetParameter(2 + i, fp[i]);
+    LOG(debug) << "Ini Fpar for " << h1->GetName() << " with "
+               << Form(" %6.3f %6.3f %6.3f %6.3f ", fp[0], fp[1], fp[2], fp[3]);
+  }
+
+  h1->Fit("YBox", "QM0");
+
+  double res[10];
+  double err[10];
+  res[9] = f1->GetChisquare();
+
+  for (int i = 0; i < 6; i++) {
+    res[i] = f1->GetParameter(i);
+    err[i] = f1->GetParError(i);
+    //cout << " FPar "<< i << ": " << res[i] << ", " << err[i] << endl;
+  }
+  LOG(debug) << "YBox Fit of " << h1->GetName()
+             << " ended with chi2 = " << res[9]
+             << Form(", strip length %7.2f +/- %5.2f, position resolution "
+                     "%7.2f +/- %5.2f at y_cen = %7.2f +/- %5.2f",
+                     2. * res[1],
+                     2. * err[1],
+                     res[2],
+                     err[2],
+                     res[3],
+                     err[3]);
+}
+
+void CbmTofHitMaker::CheckLHMemory() {
+  if (fvLastHits.size() != static_cast<size_t>(fDigiBdfPar->GetNbSmTypes()))
+    LOG(fatal) << Form("Inconsistent LH Smtype size %lu, %d ",
+                       fvLastHits.size(),
+                       fDigiBdfPar->GetNbSmTypes());
+
+  for (Int_t iSmType = 0; iSmType < fDigiBdfPar->GetNbSmTypes(); iSmType++) {
+    if (fvLastHits[iSmType].size()
+        != static_cast<size_t>(fDigiBdfPar->GetNbSm(iSmType)))
+      LOG(fatal) << Form("Inconsistent LH Sm size %lu, %d T %d",
+                         fvLastHits[iSmType].size(),
+                         fDigiBdfPar->GetNbSm(iSmType),
+                         iSmType);
+    for (Int_t iSm = 0; iSm < fDigiBdfPar->GetNbSm(iSmType); iSm++) {
+      if (fvLastHits[iSmType][iSm].size()
+          != static_cast<size_t>(fDigiBdfPar->GetNbRpc(iSmType)))
+        LOG(fatal) << Form("Inconsistent LH Rpc size %lu, %d TS %d%d ",
+                           fvLastHits[iSmType][iSm].size(),
+                           fDigiBdfPar->GetNbRpc(iSmType),
+                           iSmType,
+                           iSm);
+      for (Int_t iRpc = 0; iRpc < fDigiBdfPar->GetNbRpc(iSmType); iRpc++) {
+        if (fvLastHits[iSmType][iSm][iRpc].size()
+            != static_cast<size_t>(fDigiBdfPar->GetNbChan(iSmType, iRpc)))
+          LOG(fatal) << Form(
+            "Inconsistent LH RpcChannel size %lu, %d TSR %d%d%d ",
+            fvLastHits[iSmType][iSm][iRpc].size(),
+            fDigiBdfPar->GetNbChan(iSmType, iRpc),
+            iSmType,
+            iSm,
+            iRpc);
+        for (Int_t iCh = 0; iCh < fDigiBdfPar->GetNbChan(iSmType, iRpc); iCh++)
+          if (fvLastHits[iSmType][iSm][iRpc][iCh].size() > 0) {
+            CbmTofDetectorInfo xDetInfo(
+              ECbmModuleId::kTof, iSmType, iSm, iRpc, 0, iCh);
+            Int_t iAddr = fTofId->SetDetectorInfo(xDetInfo);
+            if (fvLastHits[iSmType][iSm][iRpc][iCh].front()->GetAddress()
+                != iAddr)
+              LOG(fatal) << Form(
+                "Inconsistent address for Ev %8.0f in list of size %lu for "
+                "TSRC %d%d%d%d: 0x%08x, time  %f",
+                fdEvent,
+                fvLastHits[iSmType][iSm][iRpc][iCh].size(),
+                iSmType,
+                iSm,
+                iRpc,
+                iCh,
+                fvLastHits[iSmType][iSm][iRpc][iCh].front()->GetAddress(),
+                fvLastHits[iSmType][iSm][iRpc][iCh].front()->GetTime());
+          }
+      }
+    }
+  }
+  LOG(debug) << Form("LH check passed for event %8.0f", fdEvent);
+}
+
+void CbmTofHitMaker::CleanLHMemory() {
+  if (fvLastHits.size() != static_cast<size_t>(fDigiBdfPar->GetNbSmTypes()))
+    LOG(fatal) << Form("Inconsistent LH Smtype size %lu, %d ",
+                       fvLastHits.size(),
+                       fDigiBdfPar->GetNbSmTypes());
+  for (Int_t iSmType = 0; iSmType < fDigiBdfPar->GetNbSmTypes(); iSmType++) {
+    if (fvLastHits[iSmType].size()
+        != static_cast<size_t>(fDigiBdfPar->GetNbSm(iSmType)))
+      LOG(fatal) << Form("Inconsistent LH Sm size %lu, %d T %d",
+                         fvLastHits[iSmType].size(),
+                         fDigiBdfPar->GetNbSm(iSmType),
+                         iSmType);
+    for (Int_t iSm = 0; iSm < fDigiBdfPar->GetNbSm(iSmType); iSm++) {
+      if (fvLastHits[iSmType][iSm].size()
+          != static_cast<size_t>(fDigiBdfPar->GetNbRpc(iSmType)))
+        LOG(fatal) << Form("Inconsistent LH Rpc size %lu, %d TS %d%d ",
+                           fvLastHits[iSmType][iSm].size(),
+                           fDigiBdfPar->GetNbRpc(iSmType),
+                           iSmType,
+                           iSm);
+      for (Int_t iRpc = 0; iRpc < fDigiBdfPar->GetNbRpc(iSmType); iRpc++) {
+        if (fvLastHits[iSmType][iSm][iRpc].size()
+            != static_cast<size_t>(fDigiBdfPar->GetNbChan(iSmType, iRpc)))
+          LOG(fatal) << Form(
+            "Inconsistent LH RpcChannel size %lu, %d TSR %d%d%d ",
+            fvLastHits[iSmType][iSm][iRpc].size(),
+            fDigiBdfPar->GetNbChan(iSmType, iRpc),
+            iSmType,
+            iSm,
+            iRpc);
+        for (Int_t iCh = 0; iCh < fDigiBdfPar->GetNbChan(iSmType, iRpc); iCh++)
+          while (fvLastHits[iSmType][iSm][iRpc][iCh].size() > 0) {
+            CbmTofDetectorInfo xDetInfo(
+              ECbmModuleId::kTof, iSmType, iSm, iRpc, 0, iCh);
+            Int_t iAddr = fTofId->SetDetectorInfo(xDetInfo);
+            if (fvLastHits[iSmType][iSm][iRpc][iCh].front()->GetAddress()
+                != iAddr)
+              LOG(fatal) << Form(
+                "Inconsistent address for Ev %8.0f in list of size %lu for "
+                "TSRC %d%d%d%d: 0x%08x, time  %f",
+                fdEvent,
+                fvLastHits[iSmType][iSm][iRpc][iCh].size(),
+                iSmType,
+                iSm,
+                iRpc,
+                iCh,
+                fvLastHits[iSmType][iSm][iRpc][iCh].front()->GetAddress(),
+                fvLastHits[iSmType][iSm][iRpc][iCh].front()->GetTime());
+            fvLastHits[iSmType][iSm][iRpc][iCh].front()->Delete();
+            fvLastHits[iSmType][iSm][iRpc][iCh].pop_front();
+          }
+      }
+    }
+  }
+  LOG(info) << Form("LH cleaning done after %8.0f events", fdEvent);
+}
+
+Bool_t CbmTofHitMaker::AddNextChan(Int_t iSmType,
+                                           Int_t iSm,
+                                           Int_t iRpc,
+                                           Int_t iLastChan,
+                                           Double_t dLastPosX,
+                                           Double_t dLastPosY,
+                                           Double_t dLastTime,
+                                           Double_t dLastTotS) {
+  // Int_t iNbSm  = fDigiBdfPar->GetNbSm(  iSmType);  (VF) not used
+  Int_t iNbRpc = fDigiBdfPar->GetNbRpc(iSmType);
+  Int_t iNbCh  = fDigiBdfPar->GetNbChan(iSmType, iRpc);
+  // Int_t iChType = fDigiBdfPar->GetChanType( iSmType, iRpc );  (VF) not used
+  Int_t iDetId   = CbmTofAddress::GetUniqueAddress(iSm, iRpc, 0, 0, iSmType);
+  Int_t iDetIndx = fDetIdIndexMap[iDetId];  // Detector Index
+
+  Int_t iCh   = iLastChan + 1;
+  Int_t iChId = CbmTofAddress::GetUniqueAddress(iSm, iRpc, iCh, 0, iSmType);
+
+  while (fvDeadStrips[iDetIndx] & (1 << iCh)) {
+    LOG(debug) << "Skip channel " << iCh << " of detector "
+               << Form("0x%08x", iDetId);
+    iCh++;
+    iLastChan++;
+    if (iCh >= iNbCh) return kFALSE;
+  }
+  LOG(debug1) << Form("Inspect channel TSRC %d%d%d%d at time %f, pos %f, size ",
+                      iSmType,
+                      iSm,
+                      iRpc,
+                      iCh,
+                      dLastTime,
+                      dLastPosY)
+              << fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size();
+  if (iCh == iNbCh) return kFALSE;
+  if (0 == fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size()) return kFALSE;
+  if (0 < fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size())
+    fhNbDigiPerChan->Fill(fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size());
+  if (1 < fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size()) {
+    Bool_t AddedHit = kFALSE;
+    for (size_t i1 = 0;
+         i1 < fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size() - 1;
+         i1++) {
+      if (AddedHit) break;
+      size_t i2 = i1 + 1;
+      while (!AddedHit
+             && i2 < fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size()) {
+        LOG(debug1) << "check digi pair " << i1 << "," << i2 << " with size "
+                    << fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size();
+
+        if ((fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][i1])->GetSide()
+            == (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][i2])->GetSide()) {
+          i2++;
+          continue;
+        }  // endif same side
+           // 2 Digis, both sides present
+        CbmTofDigi* xDigiA = fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][i1];
+        CbmTofDigi* xDigiB = fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][i2];
+        Double_t dTime     = 0.5 * (xDigiA->GetTime() + xDigiB->GetTime());
+        if (TMath::Abs(dTime - dLastTime) < fdMaxTimeDist) {
+          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());
+
+          Double_t dTimeDif = xDigiA->GetTime() - xDigiB->GetTime();
+          Double_t dPosY    = 0.;
+          if (1 == xDigiA->GetSide())
+            dPosY = fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc) * dTimeDif * 0.5;
+          else
+            dPosY =
+              -fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc) * dTimeDif * 0.5;
+
+          if (TMath::Abs(dPosY - dLastPosY)
+              < fdMaxSpaceDist) {  // append digi pair to current cluster
+
+            Double_t dNClHits = (Double_t)(vDigiIndRef.size() / 2);
+            Double_t dPosX =
+              ((Double_t)(-iNbCh / 2 + iCh) + 0.5) * fChannelInfo->GetSizex();
+            Double_t dTotS    = xDigiA->GetTot() + xDigiB->GetTot();
+            Double_t dNewTotS = (dLastTotS + dTotS);
+            dLastPosX = (dLastPosX * dLastTotS + dPosX * dTotS) / dNewTotS;
+            dLastPosY = (dLastPosY * dLastTotS + dPosY * dTotS) / dNewTotS;
+            dLastTime = (dLastTime * dLastTotS + dTime * dTotS) / dNewTotS;
+            dLastTotS = dNewTotS;
+            // attach selected digis from pool
+            Int_t Ind1 = fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh][i1];
+            Int_t Ind2 = fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh][i2];
+            vDigiIndRef.push_back(Ind1);
+            vDigiIndRef.push_back(Ind2);
+            // remove selected digis from pool
+            fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+              fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin() + i1);
+            fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+              fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].begin() + i1);
+
+            std::vector<int>::iterator it;
+            it = find(fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].begin(),
+                      fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].end(),
+                      Ind2);
+            if (it != fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].end()) {
+              auto ipos =
+                it - fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].begin();
+              LOG(debug1) << "Found i2 " << i2 << " with Ind2 " << Ind2
+                          << " at position " << ipos;
+              fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin() + ipos);
+              fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].begin() + ipos);
+            } else {
+              LOG(fatal) << " Did not find  i2 " << i2 << " with Ind2 " << Ind2;
+            }
+
+            //if(iCh == iNbCh-1) break;  //Last strip reached
+            if (iCh != (iNbCh - 1)
+                && AddNextChan(iSmType,
+                               iSm,
+                               iRpc,
+                               iCh,
+                               dLastPosX,
+                               dLastPosY,
+                               dLastTime,
+                               dLastTotS)) {
+              LOG(debug1) << "Added Strip " << iCh << " to cluster of size "
+                          << dNClHits;
+              return kTRUE;  // signal hit was already added
+            }
+            AddedHit = kTRUE;
+          }  //TMath::Abs(dPosY - dLastPosY) < fdMaxSpaceDist
+        }    //TMath::Abs(dTime-dLastTime)<fdMaxTimeDist)
+        i2++;
+      }  //  while(i2 < fStorDigi[iSmType][iSm*iNbRpc+iRpc][iCh].size()-1 )
+    }    // end for i1
+  }      // end if size
+  Double_t hitpos_local[3] = {3 * 0.};
+  hitpos_local[0]          = dLastPosX;
+  hitpos_local[1]          = dLastPosY;
+  hitpos_local[2]          = 0.;
+  /*
+	 if( 5 == iSmType || 8 == iSmType) { // for PAD counters
+	 hitpos_local[0] = (gRandom->Rndm()-0.5)*fChannelInfo->GetSizex()*0.5;
+	 hitpos_local[1] = (gRandom->Rndm()-0.5)*fChannelInfo->GetSizey()*0.5;
+	 }
+	 */
+  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);
+
+  Int_t iNbChanInHit = vDigiIndRef.size() / 2;
+
+  TString cstr = "Save A-Hit ";
+  cstr += Form(" %3d %3d 0x%08x %3d 0x%08x %8.2f %6.2f",  // %3d %3d
+               fiNbHits,
+               iNbChanInHit,
+               iDetId,
+               iLastChan,
+               0,  //vPtsRef.size(),vPtsRef[0])
+               dLastTime,
+               dLastPosY);
+  cstr += Form(", DigiSize: %lu ", vDigiIndRef.size());
+  cstr += ", DigiInds: ";
+
+  fviClusterMul[iSmType][iSm][iRpc]++;
+
+  for (UInt_t i = 0; i < vDigiIndRef.size(); i++) {
+    cstr +=
+      Form(" %d (M,%d)", vDigiIndRef.at(i), fviClusterMul[iSmType][iSm][iRpc]);
+  }
+  LOG(debug) << cstr;
+
+  CbmTofHit* pHit = new CbmTofHit(
+    iDetId,
+    hitPos,
+    hitPosErr,  //local detector coordinates
+    fiNbHits,   // this number is used as reference!!
+    dLastTime,
+    vDigiIndRef.size(),  // number of linked digis =  2*CluSize
+    //vPtsRef.size(), // flag  = number of TofPoints generating the cluster
+    Int_t(dLastTotS * 10.));  //channel -> Tot
+  // output hit
+  new ((*fTofHitsColl)[fiNbHits]) CbmTofHit(*pHit);
+  if (fdMemoryTime > 0.) {  // memorize hit
+    LH_store(iSmType, iSm, iRpc, iChm, pHit);
+  } else {
+    pHit->Delete();
+  }
+  CbmMatch* digiMatch = new ((*fTofDigiMatchColl)[fiNbHits]) CbmMatch();
+  for (size_t i = 0; i < vDigiIndRef.size(); i++) {
+    Double_t dTot = (fTofCalDigiVec->at(vDigiIndRef.at(i))).GetTot();
+    digiMatch->AddLink(
+      CbmLink(dTot, vDigiIndRef.at(i), fiOutputTreeEntry, fiFileIndex));
+  }
+  fiNbHits++;
+  vDigiIndRef.clear();
+
+  return kTRUE;
+}
+
+void CbmTofHitMaker::LH_store(Int_t iSmType,
+                                      Int_t iSm,
+                                      Int_t iRpc,
+                                      Int_t iChm,
+                                      CbmTofHit* pHit) {
+
+  if (fvLastHits[iSmType][iSm][iRpc][iChm].size() == 0)
+    fvLastHits[iSmType][iSm][iRpc][iChm].push_back(pHit);
+  else {
+    Double_t dLastTime = pHit->GetTime();
+    if (dLastTime >= fvLastHits[iSmType][iSm][iRpc][iChm].back()->GetTime()) {
+      fvLastHits[iSmType][iSm][iRpc][iChm].push_back(pHit);
+      LOG(debug) << Form(
+        " Store LH from Ev  %8.0f for TSRC %d%d%d%d, size %lu, addr 0x%08x, "
+        "time %f, dt %f",
+        fdEvent,
+        iSmType,
+        iSm,
+        iRpc,
+        iChm,
+        fvLastHits[iSmType][iSm][iRpc][iChm].size(),
+        pHit->GetAddress(),
+        dLastTime,
+        dLastTime - fvLastHits[iSmType][iSm][iRpc][iChm].front()->GetTime());
+    } else {
+      if (dLastTime
+          >= fvLastHits[iSmType][iSm][iRpc][iChm]
+               .front()
+               ->GetTime()) {  // hit has to be inserted in the proper place
+        std::list<CbmTofHit*>::iterator it;
+        for (it = fvLastHits[iSmType][iSm][iRpc][iChm].begin();
+             it != fvLastHits[iSmType][iSm][iRpc][iChm].end();
+             ++it)
+          if ((*it)->GetTime() > dLastTime) break;
+        fvLastHits[iSmType][iSm][iRpc][iChm].insert(--it, pHit);
+        Double_t deltaTime = dLastTime - (*it)->GetTime();
+        LOG(debug) << Form("Hit inserted into LH from Ev  %8.0f for TSRC "
+                           "%d%d%d%d, size %lu, addr 0x%08x, delta time %f  ",
+                           fdEvent,
+                           iSmType,
+                           iSm,
+                           iRpc,
+                           iChm,
+                           fvLastHits[iSmType][iSm][iRpc][iChm].size(),
+                           pHit->GetAddress(),
+                           deltaTime);
+      } else {  // this hit is first
+        Double_t deltaTime =
+          dLastTime - fvLastHits[iSmType][iSm][iRpc][iChm].front()->GetTime();
+        LOG(debug) << Form("first LH from Ev  %8.0f for TSRC %d%d%d%d, size "
+                           "%lu, addr 0x%08x, delta time %f ",
+                           fdEvent,
+                           iSmType,
+                           iSm,
+                           iRpc,
+                           iChm,
+                           fvLastHits[iSmType][iSm][iRpc][iChm].size(),
+                           pHit->GetAddress(),
+                           deltaTime);
+        if (deltaTime == 0.) {
+          // remove hit, otherwise double entry?
+          pHit->Delete();
+        } else {
+          fvLastHits[iSmType][iSm][iRpc][iChm].push_front(pHit);
+        }
+      }
+    }
+  }
+}
+
+Bool_t CbmTofHitMaker::BuildHits() {
+  // Then build clusters inside each RPC module
+  // Assume only 0 or 1 Digi per channel/side in each event
+  // Use simplest method possible, scan direction independent:
+  // a) Loop over channels in the RPC starting from 0
+  //   * If strips
+  //     i) Loop over Digis to check if both ends of the channel have a Digi
+  //    ii) Reconstruct a mean channel time and a mean position
+  //     + If a Hit is currently filled & the mean position (space, time) is less than XXX from last channel position
+  //   iii) Add the mean channel time and the mean position to the ones of the hit
+  //     + else
+  //   iii) Use nb of strips in cluster to cal. the hit mean time and pos (charge/tot weighting)
+  //    iv) Save the hit
+  //     v) Start a new hit with current channel
+  //   * else (pads)
+  //     i) Loop over Digis to find if this channel fired
+  //    ii) FIXME: either scan all other channels to check for matching Digis or have more than 1 hit open
+  Int_t iNbSmTypes = fDigiBdfPar->GetNbSmTypes();
+  // Hit variables
+  Double_t dWeightedTime = 0.0;
+  Double_t dWeightedPosX = 0.0;
+  Double_t dWeightedPosY = 0.0;
+  Double_t dWeightedPosZ = 0.0;
+  Double_t dWeightsSum   = 0.0;
+  //vPtsRef.clear();
+  vDigiIndRef.clear();
+  // CbmTofCell *fTrafoCell=NULL;  (VF) not used
+  // Int_t iTrafoCell=-1;  (VF) not used
+  Int_t iNbChanInHit = 0;
+  // Last Channel Temp variables
+  Int_t iLastChan = -1;
+  Double_t dLastPosX =
+    0.0;  // -> Comment to remove warning because set but never used
+  Double_t dLastPosY = 0.0;
+  Double_t dLastTime = 0.0;
+  // Channel Temp variables
+  Double_t dPosX    = 0.0;
+  Double_t dPosY    = 0.0;
+  Double_t dPosZ    = 0.0;
+  Double_t dTime    = 0.0;
+  Double_t dTimeDif = 0.0;
+  Double_t dTotS    = 0.0;
+  fiNbSameSide      = 0;
+  if (kTRUE == fDigiBdfPar->UseExpandedDigi()) {
+    for (Int_t iSmType = 0; iSmType < iNbSmTypes; iSmType++) {
+      Int_t iNbSm  = fDigiBdfPar->GetNbSm(iSmType);
+      Int_t iNbRpc = fDigiBdfPar->GetNbRpc(iSmType);
+      for (Int_t iSm = 0; iSm < iNbSm; iSm++)
+        for (Int_t iRpc = 0; iRpc < iNbRpc; iRpc++) {
+          Int_t iNbCh   = fDigiBdfPar->GetNbChan(iSmType, iRpc);
+          Int_t iChType = fDigiBdfPar->GetChanType(iSmType, iRpc);
+          LOG(debug2) << "RPC - Loop  "
+                      << Form(" %3d %3d %3d %3d ", iSmType, iSm, iRpc, iChType);
+          fviClusterMul[iSmType][iSm][iRpc] = 0;
+          Int_t iChId                       = 0;
+          Int_t iDetId =
+            CbmTofAddress::GetUniqueAddress(iSm, iRpc, 0, 0, iSmType);
+          ;
+          Int_t iDetIndx = fDetIdIndexMap[iDetId];  // Detector Index
+          if (0 == iChType) {
+            // Don't spread clusters over RPCs!!!
+            dWeightedTime = 0.0;
+            dWeightedPosX = 0.0;
+            dWeightedPosY = 0.0;
+            dWeightedPosZ = 0.0;
+            dWeightsSum   = 0.0;
+            iNbChanInHit  = 0;
+            //vPtsRef.clear();
+            // For safety reinitialize everything
+            iLastChan = -1;
+            //                  dLastPosX = 0.0; // -> Comment to remove warning because set but never used
+            dLastPosY = 0.0;
+            dLastTime = 0.0;
+            LOG(debug2) << "ChanOrient "
+                        << Form(" %3d %3d %3d %3d %3d ",
+                                iSmType,
+                                iSm,
+                                iRpc,
+                                fDigiBdfPar->GetChanOrient(iSmType, iRpc),
+                                iNbCh);
+
+            if (1 == fDigiBdfPar->GetChanOrient(iSmType, iRpc)) {
+              // 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
+              for (Int_t iCh = 0; iCh < iNbCh; iCh++) {
+                LOG(debug3)
+                  << "VDigisize "
+                  << Form(" T %3d Sm %3d R %3d Ch %3d Size %3lu ",
+                          iSmType,
+                          iSm,
+                          iRpc,
+                          iCh,
+                          fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size());
+                if (0 == fStorDigi[iSmType][iSm * iNbRpc + iRpc].size())
+                  continue;
+                if (fvDeadStrips[iDetIndx] & (1 << iCh))
+                  continue;  // skip over dead channels
+                if (0 < fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size())
+                  fhNbDigiPerChan->Fill(
+                    fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size());
+
+                while (1
+                       < fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size()) {
+
+                  while (
+                    (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][0])->GetSide()
+                    == (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][1])
+                         ->GetSide()) {
+                    // Not one Digi of each end!
+                    fiNbSameSide++;
+                    if (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size()
+                        > 2) {
+                      LOG(debug)
+                        << "SameSide Digis! on TSRC " << iSmType << iSm << iRpc
+                        << iCh << ", Times: "
+                        << Form(
+                             "%f",
+                             (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][0])
+                               ->GetTime())
+                        << ", "
+                        << Form(
+                             "%f",
+                             (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][1])
+                               ->GetTime())
+                        << ", DeltaT "
+                        << (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][1])
+                               ->GetTime()
+                             - (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][0])
+                                 ->GetTime()
+                        << ", array size: "
+                        << fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size();
+                      if (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][2]
+                            ->GetSide()
+                          == fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][0]
+                               ->GetSide()) {
+                        LOG(debug)
+                          << "3 consecutive SameSide Digis! on TSRC " << iSmType
+                          << iSm << iRpc << iCh << ", Times: "
+                          << (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][0])
+                               ->GetTime()
+                          << ", "
+                          << (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][1])
+                               ->GetTime()
+                          << ", DeltaT "
+                          << (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][1])
+                                 ->GetTime()
+                               - (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh]
+                                           [0])
+                                   ->GetTime()
+                          << ", array size: "
+                          << fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh]
+                               .size();
+                        fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                          fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin());
+                        fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                          fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh]
+                            .begin());
+                      } else {
+                        if (fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][2]
+                                ->GetTime()
+                              - fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][0]
+                                  ->GetTime()
+                            > fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][2]
+                                  ->GetTime()
+                                - fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh]
+                                           [1]
+                                             ->GetTime()) {
+                          fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                            fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh]
+                              .begin());
+                          fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                            fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh]
+                              .begin());
+                        } else {
+                          LOG(debug) << Form(
+                            "Ev %8.0f, digis not properly time ordered, TSRCS "
+                            "%d%d%d%d%d ",
+                            fdEvent,
+                            iSmType,
+                            iSm,
+                            iRpc,
+                            iCh,
+                            (Int_t)
+                              fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][0]
+                                ->GetSide());
+                          fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                            fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin()
+                            + 1);
+                          fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                            fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh]
+                              .begin()
+                            + 1);
+                        }
+                      }
+                    } else {
+                      LOG(debug2)
+                        << "SameSide Erase fStor entries(d) " << iSmType
+                        << ", SR " << iSm * iNbRpc + iRpc << ", Ch" << iCh;
+                      fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                        fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin());
+                      fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                        fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh]
+                          .begin());
+                    }
+                    if (2 > fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size())
+                      break;
+                    continue;
+                  }  // same condition side end
+
+                  LOG(debug2)
+                    << "digis processing for "
+                    << Form(
+                         " SmT %3d Sm %3d Rpc %3d Ch %3d # %3lu ",
+                         iSmType,
+                         iSm,
+                         iRpc,
+                         iCh,
+                         fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size());
+                  if (2 > fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size()) {
+                    LOG(debug) << Form(
+                      "Leaving digi processing for TSRC %d%d%d%d, size  %3lu",
+                      iSmType,
+                      iSm,
+                      iRpc,
+                      iCh,
+                      fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size());
+                    break;
+                  }
+                  /* 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);
+                  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) << "CbmTofHitMaker::BuildClusters: no "
+                                  "geometry info! "
+                               << Form(" %3d %3d %3d %3d 0x%08x 0x%08x ",
+                                       iSmType,
+                                       iSm,
+                                       iRpc,
+                                       iCh,
+                                       iChId,
+                                       iUCellId);
+                    break;
+                  }
+
+                  TGeoNode* fNode =  // prepare local->global trafo
+                    gGeoManager->FindNode(fChannelInfo->GetX(),
+                                          fChannelInfo->GetY(),
+                                          fChannelInfo->GetZ());
+                  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];
+
+                  LOG(debug2) << "    " << xDigiA->ToString();
+                  LOG(debug2) << "    " << xDigiB->ToString();
+
+                  dTimeDif = (xDigiA->GetTime() - xDigiB->GetTime());
+                  if (5 == iSmType && dTimeDif != 0.) {
+                    // FIXME -> Overflow treatment in calib/tdc/TMbsCalibTdcTof.cxx
+                    LOG(debug) << "CbmTofHitMaker::BuildClusters: "
+                                  "Diamond hit in "
+                               << iSm << " with inconsistent digits "
+                               << xDigiA->GetTime() << ", " << xDigiB->GetTime()
+                               << " -> " << dTimeDif;
+                    LOG(debug) << "    " << xDigiA->ToString();
+                    LOG(debug) << "    " << xDigiB->ToString();
+                  }
+                  if (1 == xDigiA->GetSide())
+                    // 0 is the top side, 1 is the bottom side
+                    dPosY = fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc)
+                            * dTimeDif * 0.5;
+                  else
+                    // 0 is the bottom side, 1 is the top side
+                    dPosY = -fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc)
+                            * dTimeDif * 0.5;
+
+                  while (TMath::Abs(dPosY)
+                           > fChannelInfo->GetSizey() * fPosYMaxScal
+                         && fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size()
+                              > 2) {
+                    LOG(debug)
+                      << "Hit candidate outside correlation window, check for "
+                         "better possible digis, "
+                      << " mul "
+                      << fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].size();
+
+                    CbmTofDigi* xDigiC =
+                      fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh][2];
+                    Double_t dPosYN    = 0.;
+                    Double_t dTimeDifN = 0;
+                    if (xDigiC->GetSide() == xDigiA->GetSide())
+                      dTimeDifN = xDigiC->GetTime() - xDigiB->GetTime();
+                    else
+                      dTimeDifN = xDigiA->GetTime() - xDigiC->GetTime();
+
+                    if (1 == xDigiA->GetSide())
+                      dPosYN = fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc)
+                               * dTimeDifN * 0.5;
+                    else
+                      dPosYN = -fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc)
+                               * dTimeDifN * 0.5;
+
+                    if (TMath::Abs(dPosYN) < TMath::Abs(dPosY)) {
+                      LOG(debug)
+                        << "Replace digi on side " << xDigiC->GetSide()
+                        << ", yPosNext " << dPosYN << " old: " << dPosY;
+                      dTimeDif = dTimeDifN;
+                      dPosY    = dPosYN;
+                      if (xDigiC->GetSide() == xDigiA->GetSide()) {
+                        xDigiA = xDigiC;
+                        fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                          fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin());
+                        fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                          fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh]
+                            .begin());
+                      } else {
+                        xDigiB = xDigiC;
+                        fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(++(
+                          fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin()
+                          + 1));
+                        fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                          ++(fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh]
+                               .begin()
+                             + 1));
+                      }
+                    } else
+                      break;
+                  }  //while loop end
+
+                  if (xDigiA->GetSide() == xDigiB->GetSide()) {
+                    LOG(fatal)
+                      << "Wrong combinations of digis "
+                      << fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh][0]
+                      << ","
+                      << fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh][1];
+                  }
+
+                  if (TMath::Abs(dPosY)
+                      > fChannelInfo->GetSizey()
+                          * fPosYMaxScal) {  // remove both digis
+                    fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                      fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin());
+                    fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                      fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].begin());
+                    continue;
+                  }
+                  // The "Strip" time is the mean time between each end
+                  dTime = 0.5 * (xDigiA->GetTime() + xDigiB->GetTime());
+
+                  // Weight is the total charge => sum of both ends ToT
+                  dTotS = xDigiA->GetTot() + xDigiB->GetTot();
+
+                  // use local coordinates, (0,0,0) is in the center of counter  ?
+                  dPosX = ((Double_t)(-iNbCh / 2 + iCh) + 0.5)
+                          * fChannelInfo->GetSizex();
+                  dPosZ = 0.;
+
+                  LOG(debug1)
+                    << "NbChanInHit  "
+                    << Form(" %3d %3d %3d %3d %3d 0x%p %1.0f Time %f PosX %f "
+                            "PosY %f Svel %f ",
+                            iNbChanInHit,
+                            iSmType,
+                            iRpc,
+                            iCh,
+                            iLastChan,
+                            xDigiA,
+                            xDigiA->GetSide(),
+                            dTime,
+                            dPosX,
+                            dPosY,
+                            fDigiBdfPar->GetSigVel(iSmType, iSm, iRpc))
+                    //  << Form( ", Offs %f, %f ",fvCPTOff[iSmType][iSm*iNbRpc+iRpc][iCh][0],
+                    //                            fvCPTOff[iSmType][iSm*iNbRpc+iRpc][iCh][1])
+                    ;
+
+                  // Now check if a hit/cluster is already started
+                  if (0 < iNbChanInHit) {
+                    if (iLastChan == iCh - 1) {
+                      fhDigTimeDifClust->Fill(dTime - dLastTime);
+                      fhDigSpacDifClust->Fill(dPosY - dLastPosY);
+                      fhDigDistClust->Fill(dPosY - dLastPosY,
+                                           dTime - dLastTime);
+                    }
+                    // if( iLastChan == iCh - 1 )
+                    // a cluster is already started => check distance in space/time
+                    // For simplicity, just check along strip direction for now
+                    // and break cluster when a not fired strip is found
+                    if (TMath::Abs(dTime - dLastTime) < fdMaxTimeDist
+                        && iLastChan == iCh - 1
+                        && TMath::Abs(dPosY - dLastPosY) < fdMaxSpaceDist) {
+                      // Add to cluster/hit
+                      dWeightedTime += dTime * dTotS;
+                      dWeightedPosX += dPosX * dTotS;
+                      dWeightedPosY += dPosY * dTotS;
+                      dWeightedPosZ += dPosZ * dTotS;
+                      dWeightsSum += dTotS;
+                      iNbChanInHit += 1;
+
+                      vDigiIndRef.push_back((Int_t)(
+                        fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh][0]));
+                      vDigiIndRef.push_back((Int_t)(
+                        fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh][1]));
+
+                      LOG(debug1)
+                        << " Add Digi and erase fStor entries(a): NbChanInHit "
+                        << iNbChanInHit << ", " << iSmType << ", SR "
+                        << iSm * iNbRpc + iRpc << ", Ch" << iCh;
+
+                      fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                        fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin());
+                      fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                        fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin());
+                      fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                        fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh]
+                          .begin());
+                      fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                        fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh]
+                          .begin());
+
+                    }  // if current Digis compatible with last fired chan
+                    else {
+                      // Save Hit
+                      dWeightedTime /= dWeightsSum;
+                      dWeightedPosX /= dWeightsSum;
+                      dWeightedPosY /= dWeightsSum;
+                      dWeightedPosZ /= dWeightsSum;
+                      //  TVector3 hitPosLocal(dWeightedPosX, dWeightedPosY, dWeightedPosZ);
+                      //TVector3 hitPos;
+                      Double_t hitpos_local[3];
+                      hitpos_local[0] = dWeightedPosX;
+                      hitpos_local[1] = dWeightedPosY;
+                      hitpos_local[2] = dWeightedPosZ;
+                      /*
+											 if( 5 == iSmType || 8 == iSmType) { // for PAD counters
+											 hitpos_local[0] = (gRandom->Rndm()-0.5)*fChannelInfo->GetSizex();
+											 hitpos_local[1] = (gRandom->Rndm()-0.5)*fChannelInfo->GetSizey();
+											 }
+											 */
+                      Double_t hitpos[3] = {3 * 0.};
+                      if (5 != iSmType) {
+                        /*TGeoNode*    cNode   =*/gGeoManager->GetCurrentNode();
+                        /*TGeoHMatrix* cMatrix =*/gGeoManager
+                          ->GetCurrentMatrix();
+                        //cNode->Print();
+                        //cMatrix->Print();
+
+                        gGeoManager->LocalToMaster(hitpos_local, hitpos);
+                      }
+                      LOG(debug1) << Form(" LocalToMaster: (%6.1f,%6.1f,%6.1f) "
+                                          "->(%6.1f,%6.1f,%6.1f)",
+                                          hitpos_local[0],
+                                          hitpos_local[1],
+                                          hitpos_local[2],
+                                          hitpos[0],
+                                          hitpos[1],
+                                          hitpos[2]);
+
+                      TVector3 hitPos(hitpos[0], hitpos[1], hitpos[2]);
+
+                      // Simple errors, not properly done at all for now
+                      // Right way of doing it should take into account the weight distribution
+                      // and real system time resolution
+                      TVector3 hitPosErr(
+                        0.5, 0.5, 0.5);  // including positioning uncertainty
+                      /*
+											 TVector3 hitPosErr( fChannelInfo->GetSizex()/TMath::Sqrt(12.0),   // Single strips approximation
+											 0.5, // Use generic value
+											 1.);
+
+											 */
+                      //fDigiBdfPar->GetFeeTimeRes() * fDigiBdfPar->GetSigVel(iSmType,iRpc), // Use the electronics resolution
+                      //fDigiBdfPar->GetNbGaps( iSmType, iRpc)*
+                      //fDigiBdfPar->GetGapSize( iSmType, iRpc)/ //10.0 / // Change gap size in cm
+                      //TMath::Sqrt(12.0) ); // Use full RPC thickness as "Channel" Z size
+                      // Int_t iDetId = vPtsRef[0]->GetDetectorID();// detID = pt->GetDetectorID() <= from TofPoint
+                      // calc mean ch from dPosX=((Double_t)(-iNbCh/2 + iCh)+0.5)*fChannelInfo->GetSizex();
+                      Int_t iChm =
+                        floor(dWeightedPosX / fChannelInfo->GetSizex())
+                        + iNbCh / 2;
+                      if (iChm < 0) iChm = 0;
+                      if (iChm > iNbCh - 1) iChm = iNbCh - 1;
+                      iDetId = CbmTofAddress::GetUniqueAddress(
+                        iSm, iRpc, iChm, 0, iSmType);
+                      Int_t iRefId = 0;  // Index of the correspondng TofPoint
+                      //		       if(NULL != fTofPointsColl) {
+                      //iRefId = fTofPointsColl->IndexOf( vPtsRef[0] );
+                      //}
+                      TString sRef = "";
+                      for (UInt_t i = 0; i < vDigiIndRef.size(); i++) {
+                        sRef += Form(" %d, (M%d)",
+                                     vDigiIndRef.at(i),
+                                     fviClusterMul[iSmType][iSm][iRpc]);
+                      }
+                      LOG(debug) << "Save Hit  "
+                                 << Form(" %3d %3d 0x%08x %3d %3d %3d %f %f",
+                                         fiNbHits,
+                                         iNbChanInHit,
+                                         iDetId,
+                                         iChm,
+                                         iLastChan,
+                                         iRefId,
+                                         dWeightedTime,
+                                         dWeightedPosY)
+                                 << ", DigiSize: " << vDigiIndRef.size()
+                                 << ", DigiInds: " << sRef;
+
+                      fviClusterMul[iSmType][iSm][iRpc]++;
+
+                      if (vDigiIndRef.size() < 2) {
+                        LOG(warning) << "Digi refs for Hit " << fiNbHits
+                                     << ":        vDigiIndRef.size()";
+                      }
+                      if (fiNbHits > 0) {
+                        CbmTofHit* pHitL =
+                          (CbmTofHit*) fTofHitsColl->At(fiNbHits - 1);
+                        if (iDetId == pHitL->GetAddress()
+                            && dWeightedTime == pHitL->GetTime()) {
+                          LOG(debug)
+                            << "Store Hit twice? "
+                            << " fiNbHits " << fiNbHits << ", "
+                            << Form("0x%08x, MatchCollSize %d, IndRefSize %lu ",
+                                    iDetId,
+                                    fTofDigiMatchColl->GetEntriesFast(),
+                                    vDigiIndRef.size());
+
+                          for (UInt_t i = 0; i < vDigiIndRef.size(); i++) {
+                            if (vDigiIndRef.at(i)
+                                < (Int_t) fTofCalDigiVec->size()) {
+                              CbmTofDigi* pDigiC =
+                                &(fTofCalDigiVec->at(vDigiIndRef.at(i)));
+                              LOG(debug)
+                                << " Digi " << i << " " << pDigiC->ToString();
+                            } else {
+                              LOG(fatal)
+                                << "Insufficient CalDigiVec size for i " << i
+                                << ", Ind " << vDigiIndRef.at(i);
+                            }
+                          }
+
+                          if (NULL == fTofDigiMatchColl)
+                            assert("No DigiMatchColl");
+                          CbmMatch* digiMatchL = NULL;
+                          if (fTofDigiMatchColl->GetEntriesFast()
+                              >= fiNbHits - 1) {
+                            digiMatchL =
+                              (CbmMatch*) fTofDigiMatchColl->At(fiNbHits - 1);
+                          } else {
+                            LOG(fatal) << "DigiMatchColl has insufficient size "
+                                       << fTofDigiMatchColl->GetEntriesFast();
+                          }
+
+                          if (NULL != digiMatchL)
+                            for (Int_t i = 0; i < digiMatchL->GetNofLinks();
+                                 i++) {
+                              CbmLink L0 = digiMatchL->GetLink(i);
+                              LOG(debug) << "report link " << i << "("
+                                         << digiMatchL->GetNofLinks()
+                                         << "), ind " << L0.GetIndex();
+                              Int_t iDigIndL = L0.GetIndex();
+                              if (iDigIndL >= (Int_t) vDigiIndRef.size()) {
+                                if (iDetId != fiBeamRefAddr) {
+                                  LOG(warn)
+                                    << Form("Invalid DigiRefInd for det 0x%08x",
+                                            iDetId);
+                                  continue;
+                                }
+                              }
+                              if (vDigiIndRef.at(iDigIndL)
+                                  >= (Int_t) fTofCalDigiVec->size()) {
+                                LOG(warn) << "Invalid CalDigiInd";
+                                continue;
+                              }
+                              CbmTofDigi* pDigiC =
+                                &(fTofCalDigiVec->at(vDigiIndRef.at(iDigIndL)));
+                              LOG(debug) << " DigiL " << pDigiC->ToString();
+                            }
+                          else {
+                            LOG(warn) << "Invalid digMatch Link at Index "
+                                      << fiNbHits - 1;
+                          }
+                        }
+                        LOG(debug) << "Current HitsColl length "
+                                   << fTofHitsColl->GetEntriesFast();
+                      }
+                      CbmTofHit* pHit = new CbmTofHit(
+                        iDetId,
+                        hitPos,
+                        hitPosErr,  //local detector coordinates
+                        fiNbHits,   // this number is used as reference!!
+                        dWeightedTime,
+                        vDigiIndRef
+                          .size(),  // number of linked digis =  2*CluSize
+                        //vPtsRef.size(), // flag  = number of TofPoints generating the cluster
+                        Int_t(dWeightsSum * 10.));  //channel -> Tot
+                      //0) ; //channel
+                      // output hit
+                      new ((*fTofHitsColl)[fiNbHits]) CbmTofHit(*pHit);
+                      // memorize hit
+                      if (fdMemoryTime > 0.) {
+                        LH_store(iSmType, iSm, iRpc, iChm, pHit);
+                      } else {
+                        pHit->Delete();
+                      }
+                      /*
+											 new((*fTofDigiMatchColl)[fiNbHits]) CbmMatch();
+											 CbmMatch* digiMatch = (CbmMatch *)fTofDigiMatchColl->At(fiNbHits);
+											 */
+                      CbmMatch* digiMatch =
+                        new ((*fTofDigiMatchColl)[fiNbHits]) CbmMatch();
+                      for (size_t i = 0; i < vDigiIndRef.size(); i++) {
+                        Double_t dTot =
+                          (fTofCalDigiVec->at(vDigiIndRef.at(i))).GetTot();
+                        digiMatch->AddLink(CbmLink(dTot,
+                                                   vDigiIndRef.at(i),
+                                                   fiOutputTreeEntry,
+                                                   fiFileIndex));
+                      }
+
+                      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);
+                      /*  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 );
+											 */
+                      //vPtsRef.clear();
+                      vDigiIndRef.clear();
+
+                      // Start a new hit
+                      dWeightedTime = dTime * dTotS;
+                      dWeightedPosX = dPosX * dTotS;
+                      dWeightedPosY = dPosY * dTotS;
+                      dWeightedPosZ = dPosZ * dTotS;
+                      dWeightsSum   = dTotS;
+                      iNbChanInHit  = 1;
+                      // Save pointer on CbmTofPoint
+                      // vPtsRef.push_back( (CbmTofPoint*)(xDigiA->GetLinks()) );
+                      // Save next digi address
+                      LOG(debug2)
+                        << " Next fStor Digi " << iSmType << ", SR "
+                        << iSm * iNbRpc + iRpc << ", Ch" << iCh << ", Dig0 "
+                        << (fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh][0])
+                        << ", Dig1 "
+                        << (fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh][1]);
+
+                      vDigiIndRef.push_back((Int_t)(
+                        fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh][0]));
+                      vDigiIndRef.push_back((Int_t)(
+                        fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh][1]));
+                      LOG(debug2)
+                        << " Erase fStor entries(b) " << iSmType << ", SR "
+                        << iSm * iNbRpc + iRpc << ", Ch" << iCh;
+                      fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                        fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin());
+                      fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                        fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin());
+                      fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                        fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh]
+                          .begin());
+                      fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                        fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh]
+                          .begin());
+
+                      if (kTRUE == fDigiBdfPar->ClustUseTrackId()) {
+                        //    if( ((CbmTofPoint*)(xDigiA->GetLinks()))->GetTrackID() !=
+                        //        ((CbmTofPoint*)(xDigiB->GetLinks()))->GetTrackID() )
+                        // if other side come from a different Track,
+                        // also save the pointer on CbmTofPoint
+                        //  vPtsRef.push_back( (CbmTofPoint*)(xDigiB->GetLinks()) );
+                      }  // if( kTRUE == fDigiBdfPar->ClustUseTrackId() )
+                         //else if( xDigiA->GetLinks() != xDigiB->GetLinks() )
+                         // if other side come from a different TofPoint,
+                         // also save the pointer on CbmTofPoint
+                      //    vPtsRef.push_back( (CbmTofPoint*)(xDigiB->GetLinks()) );
+                    }  // else of if current Digis compatible with last fired chan
+                  }    // if( 0 < iNbChanInHit)
+                  else {
+                    LOG(debug) << Form(
+                      "1.Hit on TSRC %d%d%d%d, time: %f, PosY %f, Tdif %f ",
+                      iSmType,
+                      iSm,
+                      iRpc,
+                      iCh,
+                      dTime,
+                      dPosY,
+                      dTimeDif);
+
+                    // first fired strip in this RPC
+                    dWeightedTime = dTime * dTotS;
+                    dWeightedPosX = dPosX * dTotS;
+                    dWeightedPosY = dPosY * dTotS;
+                    dWeightedPosZ = dPosZ * dTotS;
+                    dWeightsSum   = dTotS;
+                    iNbChanInHit  = 1;
+                    // Save pointer on CbmTofPoint
+                    //if(NULL != fTofPointsColl)
+                    //                                    vPtsRef.push_back( (CbmTofPoint*)(xDigiA->GetLinks()) );
+                    vDigiIndRef.push_back((Int_t)(
+                      fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh][0]));
+                    vDigiIndRef.push_back((Int_t)(
+                      fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh][1]));
+
+                    LOG(debug2)
+                      << " Erase fStor entries(c) " << iSmType << ", SR "
+                      << iSm * iNbRpc + iRpc << ", Ch" << iCh;
+                    fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                      fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin());
+                    fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                      fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].begin());
+                    fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                      fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].begin());
+                    fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].erase(
+                      fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].begin());
+
+                    if (kTRUE == fDigiBdfPar->ClustUseTrackId()) {
+                      // if( ((CbmTofPoint*)(xDigiA->GetLinks()))->GetTrackID() !=
+                      //     ((CbmTofPoint*)(xDigiB->GetLinks()))->GetTrackID() )
+                      // if other side come from a different Track,
+                      // also save the pointer on CbmTofPoint
+                      // vPtsRef.push_back( (CbmTofPoint*)(xDigiB->GetLinks()) );
+                    }  // if( kTRUE == fDigiBdfPar->ClustUseTrackId() )
+                       // else if( xDigiA->GetLinks() != xDigiB->GetLinks() )
+                       // if other side come from a different TofPoint,
+                       // also save the pointer on CbmTofPoint
+                    //   vPtsRef.push_back( (CbmTofPoint*)(xDigiB->GetLinks()) );
+                  }  // else of if( 0 < iNbChanInHit)
+                  iLastChan = iCh;
+                  dLastPosX = dPosX;
+                  dLastPosY = dPosY;
+                  dLastTime = dTime;
+                  if (AddNextChan(iSmType,
+                                  iSm,
+                                  iRpc,
+                                  iLastChan,
+                                  dLastPosX,
+                                  dLastPosY,
+                                  dLastTime,
+                                  dWeightsSum)) {
+                    iNbChanInHit = 0;  // cluster already stored
+                  }
+                }  // while( 1 < fStorDigi[iSmType][iSm*iNbRpc+iRpc][iCh].size() )
+                fStorDigi[iSmType][iSm * iNbRpc + iRpc][iCh].clear();
+                fStorDigiInd[iSmType][iSm * iNbRpc + iRpc][iCh].clear();
+              }  // for( Int_t iCh = 0; iCh < iNbCh; iCh++ )
+              LOG(debug2) << "finished V-RPC"
+                          << Form(" %3d %3d %3d %d %f %fx",
+                                  iSmType,
+                                  iSm,
+                                  iRpc,
+                                  fTofHitsColl->GetEntries(),
+                                  dLastPosX,
+                                  dLastPosY);
+            }  // else of if( 1 == fDigiBdfPar->GetChanOrient( iSmType, iRpc ) )
+          }    // if( 0 == iChType)
+          else {
+            LOG(error)
+              << "=> Cluster building "
+              << "from digis to hits not implemented for pads, Sm type "
+              << iSmType << " Rpc " << iRpc;
+            return kFALSE;
+          }  // else of if( 0 == iChType)
+
+          // Now check if another hit/cluster is started
+          // and save it if it's the case
+          if (0 < iNbChanInHit) {
+            LOG(debug1) << "Process cluster " << iNbChanInHit;
+
+            // Check orientation to properly assign errors
+            if (1 == fDigiBdfPar->GetChanOrient(iSmType, iRpc)) {
+              LOG(debug1) << "H-Hit ";
+            }  // if( 1 == fDigiBdfPar->GetChanOrient( iSmType, iRpc ) )
+            else {
+              LOG(debug2) << "V-Hit ";
+              // Save Hit
+              dWeightedTime /= dWeightsSum;
+              dWeightedPosX /= dWeightsSum;
+              dWeightedPosY /= dWeightsSum;
+              dWeightedPosZ /= dWeightsSum;
+              //TVector3 hitPos(dWeightedPosX, dWeightedPosY, dWeightedPosZ);
+
+              Double_t hitpos_local[3] = {3 * 0.};
+              hitpos_local[0]          = dWeightedPosX;
+              hitpos_local[1]          = dWeightedPosY;
+              hitpos_local[2]          = dWeightedPosZ;
+              /*
+							 if( 5 == iSmType || 8 == iSmType) { // for PAD counters
+							 hitpos_local[0] = (gRandom->Rndm()-0.5)*fChannelInfo->GetSizex();
+							 hitpos_local[1] = (gRandom->Rndm()-0.5)*fChannelInfo->GetSizey();
+							 }
+							 */
+              Double_t hitpos[3] = {3 * 0.};
+              if (5 != iSmType) {
+                /*TGeoNode*       cNode=*/gGeoManager->GetCurrentNode();
+                /*TGeoHMatrix* cMatrix =*/gGeoManager->GetCurrentMatrix();
+                //cNode->Print();
+                //cMatrix->Print();
+                gGeoManager->LocalToMaster(hitpos_local, hitpos);
+              }
+              LOG(debug1) << Form(" LocalToMaster for V-node: "
+                                  "(%6.1f,%6.1f,%6.1f) ->(%6.1f,%6.1f,%6.1f)",
+                                  hitpos_local[0],
+                                  hitpos_local[1],
+                                  hitpos_local[2],
+                                  hitpos[0],
+                                  hitpos[1],
+                                  hitpos[2]);
+
+              TVector3 hitPos(hitpos[0], hitpos[1], hitpos[2]);
+              // Event errors, not properly done at all for now
+              // Right way of doing it should take into account the weight distribution
+              // and real system time resolution
+              TVector3 hitPosErr(
+                0.5, 0.5, 0.5);  // including positioning uncertainty
+              /*
+							 TVector3 hitPosErr( fChannelInfo->GetSizex()/TMath::Sqrt(12.0),   // Single strips approximation
+							 0.5, // Use generic value
+							 1.);
+							 */
+              //                fDigiBdfPar->GetFeeTimeRes() * fDigiBdfPar->GetSigVel(iSmType,iRpc), // Use the electronics resolution
+              //                fDigiBdfPar->GetNbGaps( iSmType, iRpc)*
+              //                fDigiBdfPar->GetGapSize( iSmType, iRpc)/10.0 / // Change gap size in cm
+              //                TMath::Sqrt(12.0) ); // Use full RPC thickness as "Channel" Z size
+              //                     cout<<"a "<<vPtsRef.size()<<endl;
+              //                     cout<<"b "<<vPtsRef[0]<<endl;
+              //                     cout<<"c "<<vPtsRef[0]->GetDetectorID()<<endl;
+              //                     Int_t iDetId = vPtsRef[0]->GetDetectorID();// detID = pt->GetDetectorID() <= from TofPoint
+              //                     Int_t iDetId = iChId;
+              Int_t iChm =
+                floor(dWeightedPosX / fChannelInfo->GetSizex()) + iNbCh / 2;
+              if (iChm < 0) iChm = 0;
+              if (iChm > iNbCh - 1) iChm = iNbCh - 1;
+              iDetId =
+                CbmTofAddress::GetUniqueAddress(iSm, iRpc, iChm, 0, iSmType);
+              Int_t iRefId = 0;  // Index of the correspondng TofPoint
+              //if(NULL != fTofPointsColl) iRefId = fTofPointsColl->IndexOf( vPtsRef[0] );
+              TString cstr = "Save V-Hit  ";
+              cstr += Form(" %3d %3d 0x%08x %3d 0x%08x %8.2f %6.2f",  // %3d %3d
+                           fiNbHits,
+                           iNbChanInHit,
+                           iDetId,
+                           iLastChan,
+                           iRefId,  //vPtsRef.size(),vPtsRef[0])
+                           dWeightedTime,
+                           dWeightedPosY);
+
+              cstr += Form(", DigiSize: %lu ", vDigiIndRef.size());
+              cstr += ", DigiInds: ";
+
+              fviClusterMul[iSmType][iSm][iRpc]++;
+
+              for (UInt_t i = 0; i < vDigiIndRef.size(); i++) {
+                cstr += Form(" %d (M,%d)",
+                             vDigiIndRef.at(i),
+                             fviClusterMul[iSmType][iSm][iRpc]);
+              }
+              LOG(debug) << cstr;
+
+              if (vDigiIndRef.size() < 2) {
+                LOG(warning) << "Digi refs for Hit " << fiNbHits
+                             << ":        vDigiIndRef.size()";
+              }
+              if (fiNbHits > 0) {
+                CbmTofHit* pHitL = (CbmTofHit*) fTofHitsColl->At(fiNbHits - 1);
+                if (iDetId == pHitL->GetAddress()
+                    && dWeightedTime == pHitL->GetTime())
+                  LOG(debug) << "Store Hit twice? "
+                             << " fiNbHits " << fiNbHits << ", "
+                             << Form("0x%08x", iDetId);
+              }
+
+              CbmTofHit* pHit = new CbmTofHit(
+                iDetId,
+                hitPos,
+                hitPosErr,  //local detector coordinates
+                fiNbHits,   // this number is used as reference!!
+                dWeightedTime,
+                vDigiIndRef.size(),  // number of linked digis =  2*CluSize
+                //vPtsRef.size(), // flag  = number of TofPoints generating the cluster
+                Int_t(dWeightsSum * 10.));  //channel -> Tot
+              //                0) ; //channel
+              //                vDigiIndRef);
+              // output hit
+              new ((*fTofHitsColl)[fiNbHits]) CbmTofHit(*pHit);
+              // memorize hit
+              if (fdMemoryTime > 0.) {
+                LH_store(iSmType, iSm, iRpc, iChm, pHit);
+              } else {
+                pHit->Delete();
+              }
+              /*
+							 new((*fTofDigiMatchColl)[fiNbHits]) CbmMatch();
+							 CbmMatch* digiMatch = (CbmMatch *)fTofDigiMatchColl->At(fiNbHits);
+							 */
+              CbmMatch* digiMatch =
+                new ((*fTofDigiMatchColl)[fiNbHits]) CbmMatch();
+
+              for (size_t i = 0; i < vDigiIndRef.size(); i++) {
+                Double_t dTot = fTofCalDigiVec->at(vDigiIndRef.at(i)).GetTot();
+                digiMatch->AddLink(CbmLink(
+                  dTot, vDigiIndRef.at(i), fiOutputTreeEntry, fiFileIndex));
+              }
+
+              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 );
+							 */
+              //vPtsRef.clear();
+              vDigiIndRef.clear();
+            }  // else of if( 1 == fDigiBdfPar->GetChanOrient( iSmType, iRpc ) )
+          }    // if( 0 < iNbChanInHit)
+          LOG(debug2) << " Fini-A "
+                      << Form(" %3d %3d %3d M%3d",
+                              iSmType,
+                              iSm,
+                              iRpc,
+                              fviClusterMul[iSmType][iSm][iRpc]);
+        }  // for each sm/rpc pair
+      LOG(debug2) << " Fini-B " << Form(" %3d ", iSmType);
+    }  // for( Int_t iSmType = 0; iSmType < iNbSmTypes; iSmType++ )
+  }
+  return kTRUE;
+}
+
+Bool_t CbmTofHitMaker::CalibRawDigis() {
+  CbmTofDigi* pDigi;
+  CbmTofDigi* pCalDigi = NULL;
+  Int_t iDigIndCal     = -1;
+  // channel deadtime map
+  std::map<Int_t, Double_t> mChannelDeadTime;
+
+  Int_t iNbTofDigi = fTofDigiVec.size();
+  //Int_t iNbTofDigi = fTofDigisColl->GetEntriesFast();
+  for (Int_t iDigInd = 0; iDigInd < iNbTofDigi; iDigInd++) {
+    pDigi = &(fTofDigiVec.at(iDigInd));
+    //pDigi = (CbmTofDigi*) fTofDigisColl->At( iDigInd );
+
+    if (fbSwapChannelSides && 5 != pDigi->GetType() && 8 != pDigi->GetType()) {
+      pDigi->SetAddress(pDigi->GetSm(),
+                        pDigi->GetRpc(),
+                        pDigi->GetChannel(),
+                        (0 == pDigi->GetSide()) ? 1 : 0,
+                        pDigi->GetType());
+    }
+
+    Int_t iAddr = pDigi->GetAddress();
+
+    LOG(debug1) << "BC "  // Before Calibration
+                << Form("0x%08x", pDigi->GetAddress()) << " TSRC "
+                << pDigi->GetType() << pDigi->GetSm() << pDigi->GetRpc()
+                << Form("%2d", (Int_t) pDigi->GetChannel()) << " "
+                << pDigi->GetSide() << " " << Form("%f", pDigi->GetTime())
+                << " " << pDigi->GetTot();
+    /*
+		 if (pDigi->GetType() == 5
+		 || pDigi->GetType()
+		 == 8)  // for Pad counters generate fake digi to mockup a strip
+		 if (pDigi->GetSide() == 1)
+		 continue;  // skip one side to avoid double entries
+		 */
+    Bool_t bValid = kTRUE;
+    std::map<Int_t, Double_t>::iterator it;
+    it = mChannelDeadTime.find(iAddr);
+    if (it != mChannelDeadTime.end()) {
+      LOG(debug1) << "CCT found valid ChannelDeadtime entry "
+                  << mChannelDeadTime[iAddr] << ", DeltaT "
+                  << pDigi->GetTime() - mChannelDeadTime[iAddr];
+      if ((bValid = (pDigi->GetTime()
+                     > mChannelDeadTime[iAddr] + fdChannelDeadtime))) {
+
+        //       pCalDigi = new((*fTofCalDigisColl)[++iDigIndCal]) CbmTofDigi( *pDigi );
+        fTofCalDigiVec->push_back(CbmTofDigi(*pDigi));
+        pCalDigi = &(fTofCalDigiVec->back());
+        iDigIndCal++;
+      }
+    } else {
+      fTofCalDigiVec->push_back(CbmTofDigi(*pDigi));
+      pCalDigi = &(fTofCalDigiVec->back());
+      iDigIndCal++;
+      // pCalDigi = new((*fTofCalDigisColl)[++iDigIndCal]) CbmTofDigi( *pDigi );
+    }
+    mChannelDeadTime[iAddr] = pDigi->GetTime();
+    if (!bValid) continue;
+
+    LOG(debug1) << "DC "  // After deadtime check. before Calibration
+                << Form("0x%08x", pDigi->GetAddress()) << " TSRC "
+                << pDigi->GetType() << pDigi->GetSm() << pDigi->GetRpc()
+                << Form("%2d", (Int_t) pDigi->GetChannel()) << " "
+                << pDigi->GetSide() << " " << Form("%f", pDigi->GetTime())
+                << " " << pDigi->GetTot();
+
+    if (fbPs2Ns) {
+      pCalDigi->SetTime(pCalDigi->GetTime()
+                        / 1000.);  // for backward compatibility
+      pCalDigi->SetTot(pCalDigi->GetTot()
+                       / 1000.);  // for backward compatibility
+    }
+
+    if (fDigiBdfPar->GetNbSmTypes()
+          > pDigi->GetType()  // prevent crash due to misconfiguration
+        && fDigiBdfPar->GetNbSm(pDigi->GetType()) > pDigi->GetSm()
+        && fDigiBdfPar->GetNbRpc(pDigi->GetType()) > pDigi->GetRpc()
+        && fDigiBdfPar->GetNbChan(pDigi->GetType(), pDigi->GetRpc())
+             > pDigi->GetChannel()) {
+
+      LOG(debug2) << " CluCal-Init: " << pDigi->ToString();
+      // apply calibration vectors
+      pCalDigi->SetTime(
+        pCalDigi->GetTime() -  // calibrate Digi Time
+        fvCPTOff[pDigi->GetType()]
+                [pDigi->GetSm() * fDigiBdfPar->GetNbRpc(pDigi->GetType())
+                 + pDigi->GetRpc()][pDigi->GetChannel()][pDigi->GetSide()]);
+      LOG(debug2) << " CluCal-TOff: " << pCalDigi->ToString();
+
+      Double_t dTot =
+        pCalDigi->GetTot() + fRndm->Uniform(0, 1) -  // subtract Offset
+        fvCPTotOff[pDigi->GetType()]
+                  [pDigi->GetSm() * fDigiBdfPar->GetNbRpc(pDigi->GetType())
+                   + pDigi->GetRpc()][pDigi->GetChannel()][pDigi->GetSide()];
+      if (dTot < 0.001) dTot = 0.001;
+      pCalDigi->SetTot(
+        dTot *  // calibrate Digi ToT
+        fvCPTotGain[pDigi->GetType()]
+                   [pDigi->GetSm() * fDigiBdfPar->GetNbRpc(pDigi->GetType())
+                    + pDigi->GetRpc()][pDigi->GetChannel()][pDigi->GetSide()]);
+
+      // walk correction
+      Double_t dTotBinSize = (fdTOTMax - fdTOTMin) / nbClWalkBinX;
+      Int_t iWx = (Int_t)((pCalDigi->GetTot() - fdTOTMin) / dTotBinSize);
+      if (0 > iWx) iWx = 0;
+      if (iWx >= nbClWalkBinX) iWx = nbClWalkBinX - 1;
+      Double_t dDTot =
+        (pCalDigi->GetTot() - fdTOTMin) / dTotBinSize - (Double_t) iWx - 0.5;
+      Double_t dWT =
+        fvCPWalk[pCalDigi->GetType()]
+                [pCalDigi->GetSm() * fDigiBdfPar->GetNbRpc(pCalDigi->GetType())
+                 + pCalDigi->GetRpc()][pCalDigi->GetChannel()]
+                [pCalDigi->GetSide()][iWx];
+      if (dDTot > 0) {                 // linear interpolation to next bin
+        if (iWx < nbClWalkBinX - 1) {  // linear interpolation to next bin
+
+          dWT += dDTot
+                 * (fvCPWalk[pCalDigi->GetType()]
+                            [pCalDigi->GetSm()
+                               * fDigiBdfPar->GetNbRpc(pCalDigi->GetType())
+                             + pCalDigi->GetRpc()][pCalDigi->GetChannel()]
+                            [pCalDigi->GetSide()][iWx + 1]
+                    - fvCPWalk[pCalDigi->GetType()]
+                              [pCalDigi->GetSm()
+                                 * fDigiBdfPar->GetNbRpc(pCalDigi->GetType())
+                               + pCalDigi->GetRpc()][pCalDigi->GetChannel()]
+                              [pCalDigi->GetSide()][iWx]);  //memory leak???
+        }
+      } else  // dDTot < 0,  linear interpolation to next bin
+      {
+        if (0 < iWx) {  // linear interpolation to next bin
+          dWT -= dDTot
+                 * (fvCPWalk[pCalDigi->GetType()]
+                            [pCalDigi->GetSm()
+                               * fDigiBdfPar->GetNbRpc(pCalDigi->GetType())
+                             + pCalDigi->GetRpc()][pCalDigi->GetChannel()]
+                            [pCalDigi->GetSide()][iWx - 1]
+                    - fvCPWalk[pCalDigi->GetType()]
+                              [pCalDigi->GetSm()
+                                 * fDigiBdfPar->GetNbRpc(pCalDigi->GetType())
+                               + pCalDigi->GetRpc()][pCalDigi->GetChannel()]
+                              [pCalDigi->GetSide()][iWx]);  //memory leak???
+        }
+      }
+
+      pCalDigi->SetTime(pCalDigi->GetTime() - dWT);  // calibrate Digi Time
+      LOG(debug2) << " CluCal-Walk: " << pCalDigi->ToString();
+
+      if (1) {  //pDigi->GetType()==7 && pDigi->GetSm()==0){
+        LOG(debug) << "BuildClusters: 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())
+                                  + pCalDigi->GetRpc()][pCalDigi->GetChannel()]
+                                 [pCalDigi->GetSide()]
+                   << ", TotOff "
+                   << fvCPTotOff[pCalDigi->GetType()]
+                                [pCalDigi->GetSm()
+                                   * fDigiBdfPar->GetNbRpc(pCalDigi->GetType())
+                                 + pCalDigi->GetRpc()][pCalDigi->GetChannel()]
+                                [pCalDigi->GetSide()]
+                   << ", Walk " << iWx << ": "
+                   << fvCPWalk[pCalDigi->GetType()]
+                              [pCalDigi->GetSm()
+                                 * fDigiBdfPar->GetNbRpc(pCalDigi->GetType())
+                               + pCalDigi->GetRpc()][pCalDigi->GetChannel()]
+                              [pCalDigi->GetSide()][iWx];
+
+        LOG(debug1) << " dDTot " << dDTot << " BinSize: " << dTotBinSize
+                    << ", CPWalk "
+                    << fvCPWalk[pCalDigi->GetType()]
+                               [pCalDigi->GetSm()
+                                  * fDigiBdfPar->GetNbRpc(pCalDigi->GetType())
+                                + pCalDigi->GetRpc()][pCalDigi->GetChannel()]
+                               [pCalDigi->GetSide()][iWx - 1]
+                    << ", "
+                    << fvCPWalk[pCalDigi->GetType()]
+                               [pCalDigi->GetSm()
+                                  * fDigiBdfPar->GetNbRpc(pCalDigi->GetType())
+                                + pCalDigi->GetRpc()][pCalDigi->GetChannel()]
+                               [pCalDigi->GetSide()][iWx]
+                    << ", "
+                    << fvCPWalk[pCalDigi->GetType()]
+                               [pCalDigi->GetSm()
+                                  * fDigiBdfPar->GetNbRpc(pCalDigi->GetType())
+                                + pCalDigi->GetRpc()][pCalDigi->GetChannel()]
+                               [pCalDigi->GetSide()][iWx + 1]
+                    << " -> dWT = " << dWT;
+      }
+    } else {
+      LOG(info) << "Skip1 Digi "
+                << " Type " << pDigi->GetType() << " "
+                << fDigiBdfPar->GetNbSmTypes() << " Sm " << pDigi->GetSm()
+                << " " << fDigiBdfPar->GetNbSm(pDigi->GetType()) << " Rpc "
+                << pDigi->GetRpc() << " "
+                << fDigiBdfPar->GetNbRpc(pDigi->GetType()) << " Ch "
+                << pDigi->GetChannel() << " "
+                << fDigiBdfPar->GetNbChan(pDigi->GetType(), 0);
+    }
+
+    if (0)  // (bAddBeamCounterSideDigi)
+      if (pCalDigi->GetType() == 5
+          || pCalDigi->GetType()
+               == 8) {  // for Pad counters generate fake digi to mockup a strip
+        LOG(debug) << "add Pad counter 2. Side digi for 0x" << std::hex
+                   << pCalDigi->GetAddress();
+        fTofCalDigiVec->push_back(CbmTofDigi(*pCalDigi));
+        CbmTofDigi* pCalDigi2 = &(fTofCalDigiVec->back());
+        iDigIndCal++;
+        //      CbmTofDigi *pCalDigi2 = new((*fTofCalDigisColl)[++iDigIndCal]) CbmTofDigi( *pCalDigi );
+        if (pCalDigi->GetSide() == 0)
+          pCalDigi2->SetAddress(pCalDigi->GetSm(),
+                                pCalDigi->GetRpc(),
+                                pCalDigi->GetChannel(),
+                                1,
+                                pCalDigi->GetType());
+        else
+          pCalDigi2->SetAddress(pCalDigi->GetSm(),
+                                pCalDigi->GetRpc(),
+                                pCalDigi->GetChannel(),
+                                0,
+                                pCalDigi->GetType());
+      }
+
+  }  // for( Int_t iDigInd = 0; iDigInd < nTofDigi; iDigInd++ )
+
+  //  iNbTofDigi = fTofCalDigisColl->GetEntries();  // update because of added duplicted digis
+  iNbTofDigi =
+    fTofCalDigiVec->size();  // update because of added duplicted digis
+  //if(fTofCalDigisColl->IsSortable())
+  //    LOG(debug)<<"CbmTofHitMaker::BuildClusters: Sort "<<fTofCalDigisColl->GetEntries()<<" calibrated digis ";
+  LOG(debug) << "CbmTofHitMaker::BuildClusters: Sort "
+             << fTofCalDigiVec->size() << " calibrated digis ";
+  if (iNbTofDigi > 1) {
+    //    fTofCalDigisColl->Sort(iNbTofDigi); // Time order again, in case modified by the calibration
+    /// Sort the buffers of hits due to the time offsets applied
+    std::sort(fTofCalDigiVec->begin(),
+              fTofCalDigiVec->end(),
+              [](const CbmTofDigi& a, const CbmTofDigi& b) -> bool {
+                return a.GetTime() < b.GetTime();
+              });
+    //    std::sort(fTofCalDigiVec->begin(), fTofCalDigiVec->end());
+    //    if(!fTofCalDigisColl->IsSorted()){
+    //    if ( ! std::is_sorted(fTofCalDigiVec->begin(), fTofCalDigiVec->end()))
+    if (!std::is_sorted(fTofCalDigiVec->begin(),
+                        fTofCalDigiVec->end(),
+                        [](const CbmTofDigi& a, const CbmTofDigi& b) -> bool {
+                          return a.GetTime() < b.GetTime();
+                        }))
+      LOG(warning)
+        << "CbmTofHitMaker::BuildClusters: Sorting not successful ";
+  }
+  //  }
+
+  return kTRUE;
+}
+
+void CbmTofHitMaker::SetDeadStrips(Int_t iDet, Int_t ival) {
+  if (fvDeadStrips.size() < static_cast<size_t>(iDet + 1))
+    fvDeadStrips.resize(iDet + 1);
+  fvDeadStrips[iDet] = ival;
+}
diff --git a/reco/detectors/tof/CbmTofHitMaker.h b/reco/detectors/tof/CbmTofHitMaker.h
new file mode 100644
index 0000000000000000000000000000000000000000..0c8d0edb5bad6510334c967c57876c1f3e326452
--- /dev/null
+++ b/reco/detectors/tof/CbmTofHitMaker.h
@@ -0,0 +1,493 @@
+/** @file CbmTofHitMaker.h
+ ** @author nh adopted from
+ ** @author Pierre-Alain Loizeau <loizeau@physi.uni-heidelberg.de>
+ ** @date 01.12.2020
+ **/
+/** @class CbmTofSimpClusterizer
+ ** @brief Simple Cluster building and hit producing for CBM ToF using Digis as input
+ ** @author Pierre-Alain Loizeau <loizeau@physi.uni-heidelberg.de>
+ ** @version 1.0
+ **/
+#ifndef CBMTOFHITMAKER_H
+#define CBMTOFHITMAKER_H 1
+
+// TOF Classes and includes
+// Input/Output
+//class CbmTofPoint;
+class CbmTofHit;
+class CbmMatch;
+class CbmEvent;
+class CbmVertex;
+// Geometry
+class CbmTofGeoHandler;
+class CbmTofDetectorId;
+class CbmTofDigiPar;
+class CbmTofDigiBdfPar;
+class CbmTofCell;
+class CbmTofFindTracks;
+class CbmDigiManager;
+
+class TTofCalibData;
+class TTrbHeader;
+
+// FAIR classes and includes
+#include "CbmTofAddress.h"  // in cbmdata/tof
+#include "CbmTofDigi.h"
+#include "FairTask.h"
+
+// ROOT Classes and includes
+class TClonesArray;
+class TF1;
+class TH1;
+class TH2;
+class TH3;
+class TProfile;
+class TString;
+#include "TTimeStamp.h"
+
+// C++ Classes and includes
+#include <list>
+#include <map>
+#include <vector>
+
+class CbmTofHitMaker : public FairTask {
+
+  friend class CbmTofAnaTestbeam;
+
+public:
+  inline static CbmTofHitMaker* Instance() { return fInstance; }
+
+  /**
+       ** @brief Constructor.
+       **/
+  CbmTofHitMaker();
+
+  /**
+       ** @brief Constructor.
+       **/
+  CbmTofHitMaker(const char* name,
+                         Int_t verbose         = 1,
+                         Bool_t writeDataInOut = kTRUE);
+  /**
+       ** @brief Destructor.
+       **/
+  virtual ~CbmTofHitMaker();
+
+  /**
+       ** @brief Inherited from FairTask.
+       **/
+  virtual InitStatus Init();
+
+  /**
+       ** @brief Inherited from FairTask.
+       **/
+  virtual void SetParContainers();
+
+  /**
+       ** @brief Inherited from FairTask.
+       **/
+  virtual void Exec(Option_t* option);
+  virtual void ExecEvent(Option_t* option);
+
+  /**
+       ** @brief Inherited from FairTask.
+       **/
+  virtual void Finish();
+  virtual void Finish(Double_t calMode);
+
+  inline void SetCalMode(Int_t iMode) { fCalMode = iMode; }
+  inline void SetCalSel(Int_t iSel) { fCalSel = iSel; }
+  inline void SetCalSmType(Int_t iCalSmType) {
+    fCalSmAddr = CbmTofAddress::GetUniqueAddress(0, 0, 0, 0, iCalSmType);
+  }
+  inline void SetCalSmAddr(Int_t iCalSmAddr) { fCalSmAddr = iCalSmAddr; }
+  inline void SetCalRpc(Int_t iCalRpc) {
+    if (iCalRpc != 0) {
+      Int_t iSign = iCalRpc / TMath::Abs(iCalRpc);
+      iCalRpc *= iSign;  // always a positive number
+      Int_t iRpc = iCalRpc % 10;
+      iCalRpc    = (iCalRpc - iRpc) / 10;
+      Int_t iSm  = iCalRpc % 10;
+      iCalRpc    = (iCalRpc - iSm) / 10;
+      if (fIdMode == 1) iRpc = 0;  // ignore RPC number
+      fCalSmAddr =
+        iSign * CbmTofAddress::GetUniqueAddress(iSm, iRpc, 0, 0, iCalRpc);
+    } else {
+      fCalSmAddr = 0;
+    }
+  }
+  inline void SetCaldXdYMax(Double_t dCaldXdYMax) {
+    fdCaldXdYMax = dCaldXdYMax;
+  }
+  inline void SetCalCluMulMax(Int_t ival) { fiCluMulMax = ival; }
+  inline void SetTRefId(Int_t Id) { fTRefMode = Id; }
+  inline void SetIdMode(Int_t Id) { fIdMode = Id; }
+  inline void SetDutId(Int_t Id) { fDutId = Id; }
+  inline void SetDutSm(Int_t Id) { fDutSm = Id; }
+  inline void SetDutRpc(Int_t Id) { fDutRpc = Id; }
+  inline void SetSelId(Int_t Id) { fSelId = Id; }
+  inline void SetSelSm(Int_t Id) { fSelSm = Id; }
+  inline void SetSelRpc(Int_t Id) { fSelRpc = Id; }
+  inline void SetBeamRefId(Int_t Id) { fiBeamRefType = Id; }
+  inline void SetBeamRefSm(Int_t Id) { fiBeamRefSm = Id; }
+  inline void SetBeamRefDet(Int_t Id) { fiBeamRefDet = Id; }
+  inline void SetBeamRefMulMax(Int_t Id) { fiBeamRefMulMax = Id; }
+  inline void SetBeamAddRefMul(Int_t ival) { fiBeamAddRefMul = ival; }
+  inline void SetTRefDifMax(Double_t val) { fTRefDifMax = val; }
+  inline void SetdTRefMax(Double_t val) { fdTRefMax = val; }
+  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 void SetTotMean(Double_t val) { fTotMean = val; }
+  inline void SetDelTofMax(Double_t val) { fdDelTofMax = val; }
+  inline void SetTotPreRange(Double_t val) { fTotPreRange = val; }
+  inline void SetMaxTimeDist(Double_t val) { fMaxTimeDist = val; }
+  inline void SetChannelDeadtime(Double_t val) { fdChannelDeadtime = val; }
+  inline void SetMemoryTime(Double_t val) { fdMemoryTime = val; }
+  inline void SetYFitMin(Double_t val) { fdYFitMin = val; }
+  inline void SetToDAv(Double_t val) { fdToDAv = val; }
+  inline void SetSel2Id(Int_t ival) { fSel2Id = ival; }
+  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 SetOutHstFileName(TString OutHstFileName) {
+    fOutHstFileName = OutHstFileName;
+  }
+  inline void SetCalParFileName(TString CalParFileName) {
+    fCalParFileName = CalParFileName;
+  }
+  inline TString GetCalParFileName() { return fCalParFileName; }
+
+  inline void SetEnableMatchPosScaling(Bool_t bval) {
+    fEnableMatchPosScaling = bval;
+  }
+  inline void SetEnableAvWalk(Bool_t bval) { fEnableAvWalk = bval; }
+  inline void SetPs2Ns(Bool_t bval) { fbPs2Ns = bval; }
+
+  //static Double_t  f1_xboxe(double *x, double *par); // Fit function
+  virtual void fit_ybox(const char* hname);                    // Fit
+  virtual void fit_ybox(TH1* h, Double_t dy);                  // Fit
+  virtual void fit_ybox(TH1* h, Double_t dy, Double_t* fpar);  // Fit
+  virtual void CheckLHMemory();  // Check consistency of stored last hits
+  virtual void CleanLHMemory();  // Cleanup
+  virtual Bool_t AddNextChan(Int_t iSmType,
+                             Int_t iSm,
+                             Int_t iRpc,
+                             Int_t iLastChan,
+                             Double_t dLastPosX,
+                             Double_t dLastPosY,
+                             Double_t dLastTime,
+                             Double_t dLastTot);  // needed for time based data
+  virtual void
+  LH_store(Int_t iSmType, Int_t iSm, Int_t iRpc, Int_t iChm, CbmTofHit* pHit);
+
+  void SwapChannelSides(Bool_t bSwap) { fbSwapChannelSides = bSwap; }
+  void SetFileIndex(Int_t iIndex) { fiFileIndex = iIndex; }
+  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);
+
+protected:
+private:
+  static CbmTofHitMaker* fInstance;
+  /**
+       ** @brief Copy constructor.
+       **/
+  CbmTofHitMaker(const CbmTofHitMaker&);
+  /**
+       ** @brief Copy operator.
+       **/
+  CbmTofHitMaker& operator=(const CbmTofHitMaker&);
+
+  // Functions common for all clusters approximations
+  /**
+       ** @brief Recover pointer on input TClonesArray: TofPoints, TofDigis...
+       **/
+  Bool_t RegisterInputs();
+  /**
+       ** @brief Create and register output TClonesArray of Tof Hits.
+       **/
+  Bool_t RegisterOutputs();
+  /**
+       ** @brief Initialize other parameters not included in parameter classes.
+       **/
+  Bool_t InitParameters();
+  /**
+       ** @brief Initialize other parameters not included in parameter classes.
+       **/
+  Bool_t InitCalibParameter();
+  /**
+       ** @brief Load the geometry: for now just resizing the Digis temporary vectors
+       **/
+  Bool_t LoadGeometry();
+  /**
+       ** @brief Delete the geometry related arrays: for now just clearing the Digis temporary vectors
+       **/
+  Bool_t DeleteGeometry();
+
+  // Histogramming functions
+  Bool_t CreateHistos();
+  Bool_t FillHistos();
+  Bool_t WriteHistos();
+  Bool_t DeleteHistos();
+
+  /**
+       ** @brief Build clusters out of ToF Digis and store the resulting info in a TofHit.
+       **/
+  Bool_t BuildClusters();
+  Bool_t MergeClusters();
+  Bool_t BuildHits();
+  Bool_t CalibRawDigis();
+  Bool_t InspectRawDigis();
+
+  // ToF geometry variables
+  CbmTofGeoHandler* fGeoHandler;
+  CbmTofDetectorId* fTofId;
+  CbmTofDigiPar* fDigiPar;
+  CbmTofCell* fChannelInfo;
+  CbmTofDigiBdfPar* fDigiBdfPar;
+
+  TTrbHeader* fTrbHeader;
+
+  // Input variables
+  TClonesArray* fTofPointsColl;  // TOF MC points
+  TClonesArray* fMcTracksColl;   // MC tracks
+  //TClonesArray          * fTofDigisColl;     // TOF Digis
+  std::vector<CbmTofDigi> fTofDigiVec {};               //! TOF Digis
+  const std::vector<CbmTofDigi>* fT0DigiVec = nullptr;  //! T0 Digis
+  CbmDigiManager* fDigiMan;                             // TOF Input Digis
+  TClonesArray* fEventsColl;  // CBMEvents (time based)
+
+  // Output variables
+  Bool_t fbWriteHitsInOut;
+  Bool_t fbWriteDigisInOut;
+  std::vector<CbmTofDigi>* fTofCalDigiVec =
+    nullptr;                        //! // Calibrated TOF Digis
+  TClonesArray* fTofHitsColl;       // TOF hits
+  TClonesArray* fTofDigiMatchColl;  // TOF Digi Links
+  //TClonesArray          * fTofCalDigisCollOut;   // Calibrated TOF Digis
+  std::vector<CbmTofDigi>* fTofCalDigiVecOut =
+    nullptr;                           //! // Calibrated TOF Digis
+  TClonesArray* fTofHitsCollOut;       // TOF hits
+  TClonesArray* fTofDigiMatchCollOut;  // TOF Digi Links
+  Int_t fiNbHits;                      // Index of the CbmTofHit TClonesArray
+
+  // Generic
+  Int_t fVerbose;
+
+  // Intermediate storage variables
+  std::vector<std::vector<std::vector<std::vector<CbmTofDigi*>>>>
+    fStorDigi;  //[nbType][nbSm*nbRpc][nbCh][nDigis]
+  std::vector<std::vector<std::vector<std::vector<Int_t>>>>
+    fStorDigiInd;  //[nbType][nbSm*nbRpc][nbCh][nDigis]
+  std::vector<Int_t> vDigiIndRef;
+
+  std::vector<std::vector<std::vector<Int_t>>>
+    fviClusterMul;  //[nbType][nbSm][nbRpc]
+  std::vector<std::vector<std::vector<Int_t>>>
+    fviClusterSize;  //[nbType][nbRpc][nClusters]
+  std::vector<std::vector<std::vector<Int_t>>>
+    fviTrkMul;  //[nbType][nbRpc][nClusters]
+  std::vector<std::vector<std::vector<Double_t>>>
+    fvdX;  //[nbType][nbRpc][nClusters]
+  std::vector<std::vector<std::vector<Double_t>>>
+    fvdY;  //[nbType][nbRpc][nClusters]
+  std::vector<std::vector<std::vector<Double_t>>>
+    fvdDifX;  //[nbType][nbRpc][nClusters]
+  std::vector<std::vector<std::vector<Double_t>>>
+    fvdDifY;  //[nbType][nbRpc][nClusters]
+  std::vector<std::vector<std::vector<Double_t>>>
+    fvdDifCh;  //[nbType][nbRpc][nClusters]
+
+  // Histograms
+  TH1* fhClustBuildTime;
+  TH1* fhHitsPerTracks;
+  TH1* fhPtsPerHit;
+  TH1* fhTimeResSingHits;
+  TH2* fhTimeResSingHitsB;
+  TH2* fhTimePtVsHits;
+  TH1* fhClusterSize;
+  TH2* fhClusterSizeType;
+  TH1* fhTrackMul;
+  TH2* fhClusterSizeMulti;
+  TH2* fhTrk1MulPos;
+  TH2* fhHiTrkMulPos;
+  TH2* fhAllTrkMulPos;
+  TH2* fhMultiTrkProbPos;
+  TH1* fhDigSpacDifClust;
+  TH1* fhDigTimeDifClust;
+  TH2* fhDigDistClust;
+  TH2* fhClustSizeDifX;
+  TH2* fhClustSizeDifY;
+  TH2* fhChDifDifX;
+  TH2* fhChDifDifY;
+  TH2* fhCluMulCorDutSel;
+  TH2* fhEvCluMul;
+
+  std::vector<TH2*> fhRpcDigiCor;               //[nbDet]
+  std::vector<TH2*> fhRpcDigiMul;               //[nbDet]
+  std::vector<TH2*> fhRpcDigiStatus;            //[nbDet]
+  std::vector<TH2*> fhRpcDigiDTLD;              //[nbDet]
+  std::vector<TH2*> fhRpcDigiDTFD;              //[nbDet]
+  std::vector<TH2*> fhRpcDigiDTMul;             //[nbDet]
+  std::vector<TH1*> fhRpcCluMul;                //[nbDet]
+  std::vector<TH1*> fhRpcCluRate;               //[nbDet]
+  std::vector<TH1*> fhRpcCluRate10s;            //[nbDet]
+  std::vector<TH2*> fhRpcCluPosition;           //[nbDet]
+  std::vector<TProfile*> fhRpcCluPositionEvol;  //[nbDet]
+  std::vector<TProfile*> fhRpcCluTimeEvol;      //[nbDet]
+  std::vector<TH2*> fhRpcCluDelPos;             //[nbDet]
+  std::vector<TH2*> fhRpcCluDelMatPos;          //[nbDet]
+  std::vector<TH2*> fhRpcCluTOff;               //[nbDet]
+  std::vector<TH2*> fhRpcCluDelTOff;            //[nbDet]
+  std::vector<TH2*> fhRpcCluDelMatTOff;         //[nbDet]
+  std::vector<TH2*> fhRpcCluTrms;               //[nbDet]
+  std::vector<TH2*> fhRpcCluTot;                //[nbDet]
+  std::vector<TH2*> fhRpcCluSize;               //[nbDet]
+  std::vector<TH2*> fhRpcCluAvWalk;             //[nbDet]
+  std::vector<TH2*> fhRpcCluAvLnWalk;           //[nbDet]
+  std::vector<std::vector<std::vector<TH2*>>>
+    fhRpcCluWalk;                     // [nbDet][nbCh][nSide]
+  std::vector<TH2*> fhSmCluPosition;  //[nbSmTypes]
+  std::vector<TH2*> fhSmCluTOff;
+  std::vector<TProfile*> fhSmCluSvel;
+  std::vector<std::vector<TProfile*>> fhSmCluFpar;
+  std::vector<TH1*> fhRpcDTLastHits;          //[nbDet]
+  std::vector<TH1*> fhRpcDTLastHits_Tot;      //[nbDet]
+  std::vector<TH1*> fhRpcDTLastHits_CluSize;  //[nbDet]
+
+  std::vector<std::vector<TH1*>> fhTRpcCluMul;       //[nbDet][nbSel]
+  std::vector<std::vector<TH2*>> fhTRpcCluPosition;  //[nbDet][nbSel]
+  std::vector<std::vector<TH2*>> fhTRpcCluTOff;      //[nbDet] [nbSel]
+  std::vector<std::vector<TH2*>> fhTRpcCluTofOff;    //[nbDet] [nbSel]
+  std::vector<std::vector<TH2*>> fhTRpcCluTot;       // [nbDet][nbSel]
+  std::vector<std::vector<TH2*>> fhTRpcCluSize;      // [nbDet][nbSel]
+  std::vector<std::vector<TH2*>> fhTRpcCluAvWalk;    // [nbDet][nbSel]
+  std::vector<std::vector<TH2*>> fhTRpcCluDelTof;    // [nbDet][nbSel]
+  std::vector<std::vector<TH2*>> fhTRpcCludXdY;      // [nbDet][nbSel]
+  std::vector<std::vector<std::vector<std::vector<TH2*>>>>
+    fhTRpcCluWalk;                                // [nbDet][nbSel][nbCh][nSide]
+  std::vector<std::vector<TH3*>> fhTRpcCluWalk2;  // [nbDet][nbSel]
+
+  std::vector<std::vector<TH2*>> fhTSmCluPosition;  //[nbSmTypes][nbSel]
+  std::vector<std::vector<TH2*>> fhTSmCluTOff;      //[nbSmTypes][nbSel]
+  std::vector<std::vector<TH2*>> fhTSmCluTRun;      //[nbSmTypes][nbSel]
+  std::vector<std::vector<TH2*>> fhTRpcCluTOffDTLastHits;
+  std::vector<std::vector<TH2*>> fhTRpcCluTotDTLastHits;
+  std::vector<std::vector<TH2*>> fhTRpcCluSizeDTLastHits;
+  std::vector<std::vector<TH2*>> fhTRpcCluMemMulDTLastHits;
+
+  std::vector<TH1*> fhSeldT;  //[nbSel]
+
+  std::vector<std::vector<std::vector<std::vector<Double_t>>>>
+    fvCPDelTof;  //[nSMT][nRpc][nbClDelTofBinX][nbSel]
+  std::vector<std::vector<std::vector<std::vector<Double_t>>>>
+    fvCPTOff;  //[nSMT][nRpc][nCh][nbSide]
+  std::vector<std::vector<std::vector<std::vector<Double_t>>>>
+    fvCPTotGain;  //[nSMT][nRpc][nCh][nbSide]
+  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<std::vector<std::list<CbmTofHit*>>>>>
+    fvLastHits;                     //[nSMT[nSm][nRpc][nCh][NHits]
+  std::vector<Int_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]
+
+  // Digis quality
+  Int_t fiNbSameSide;
+  TH1* fhNbSameSide;
+  TH1* fhNbDigiPerChan;
+
+  // Control
+  TTimeStamp fStart;
+  TTimeStamp fStop;
+
+  // Calib
+  Double_t dTRef;
+  Double_t fdTRefMax;
+  Int_t fCalMode;
+  Int_t fCalSel;
+  Int_t fCalSmAddr;
+  Double_t fdCaldXdYMax;
+  Int_t fiCluMulMax;
+  Int_t fTRefMode;
+  Int_t fTRefHits;
+  Int_t fIdMode;
+  Int_t fDutId;
+  Int_t fDutSm;
+  Int_t fDutRpc;
+  Int_t fDutAddr;
+  Int_t fSelId;
+  Int_t fSelSm;
+  Int_t fSelRpc;
+  Int_t fSelAddr;
+  Int_t fiBeamRefType;
+  Int_t fiBeamRefSm;
+  Int_t fiBeamRefDet;
+  Int_t fiBeamRefAddr;
+  Int_t fiBeamRefMulMax;
+  Int_t fiBeamAddRefMul;
+  Int_t fSel2Id;
+  Int_t fSel2Sm;
+  Int_t fSel2Rpc;
+  Int_t fSel2Addr;
+  Int_t fSel2MulMax;
+
+  std::map<UInt_t, UInt_t> fDetIdIndexMap;
+  std::vector<Int_t> fviDetId;
+
+  Double_t fPosYMaxScal;
+  Double_t fTRefDifMax;
+  Double_t fTotMax;
+  Double_t fTotMin;
+  Double_t fTotOff;
+  Double_t fTotMean;
+  Double_t fdDelTofMax;
+  Double_t fTotPreRange;
+  Double_t fMaxTimeDist;
+  Double_t fdChannelDeadtime;
+  Double_t fdMemoryTime;
+  Double_t fdYFitMin;
+  Double_t fdToDAv;
+
+  Bool_t fEnableMatchPosScaling;
+  Bool_t fEnableAvWalk;
+  Bool_t fbPs2Ns;  // convert input raw digis from ps to ns
+
+  TString fCalParFileName;  // name of the file name with Calibration Parameters
+  TString
+    fOutHstFileName;  // name of the histogram output file name with Calibration Parameters
+  TFile* fCalParFile;  // pointer to Calibration Parameter file
+
+  // Constants or setting parameters
+  Int_t fiNevtBuild;
+  Int_t fiMsgCnt;
+
+  Double_t fdTOTMax;
+  Double_t fdTOTMin;
+  Double_t fdTTotMean;
+
+  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 fdEvent;
+
+  Bool_t fbSwapChannelSides;
+  Int_t fiOutputTreeEntry;
+  Int_t fiFileIndex;
+  Bool_t fbAlternativeBranchNames;
+
+  ClassDef(CbmTofHitMaker, 1);
+};
+
+#endif  // CBMTOFHITMAKER
diff --git a/reco/detectors/tof/CbmTofRecoLinkDef.h b/reco/detectors/tof/CbmTofRecoLinkDef.h
index 5ceddb22ca0071accb7bb8cf74ceac9ec4503cfa..93244528d3d05fb0a26ffddad1455e69bcc1622d 100644
--- a/reco/detectors/tof/CbmTofRecoLinkDef.h
+++ b/reco/detectors/tof/CbmTofRecoLinkDef.h
@@ -5,6 +5,7 @@
 #pragma link off all functions;
 
 #pragma link C++ class CbmTofBuildDigiEvents + ;
+#pragma link C++ class CbmTofHitMaker + ;
 #pragma link C++ class CbmTofCosmicClusterizer + ;
 #pragma link C++ class CbmTofEventClusterizer + ;
 #pragma link C++ class CbmTofFindTracks + ;