From fa91431dd9f338337b03742f4961c8736a8b927a Mon Sep 17 00:00:00 2001
From: Jochen Meyer <Jochen.Meyer@cern.ch>
Date: Mon, 15 Sep 2014 14:53:56 +0200
Subject: [PATCH] fixing compiler warning (MdtSegmentT0Fitter-00-00-29)

---
 .../MdtSegmentT0Fitter/MdtSegmentT0Fitter.h   |  81 ++
 .../MdtSegmentT0Fitter/cmt/requirements       |  31 +
 .../MdtSegmentT0Fitter/doc/mainpage.h         |   7 +
 .../src/MdtSegmentT0Fitter.cxx                | 997 ++++++++++++++++++
 .../components/MdtSegmentT0Fitter_entries.cxx |  11 +
 .../components/MdtSegmentT0Fitter_load.cxx    |   3 +
 6 files changed, 1130 insertions(+)
 create mode 100755 MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/MdtSegmentT0Fitter/MdtSegmentT0Fitter.h
 create mode 100755 MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/cmt/requirements
 create mode 100755 MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/doc/mainpage.h
 create mode 100755 MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/src/MdtSegmentT0Fitter.cxx
 create mode 100755 MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/src/components/MdtSegmentT0Fitter_entries.cxx
 create mode 100755 MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/src/components/MdtSegmentT0Fitter_load.cxx

diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/MdtSegmentT0Fitter/MdtSegmentT0Fitter.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/MdtSegmentT0Fitter/MdtSegmentT0Fitter.h
new file mode 100755
index 0000000000000..cdcd22262ba7d
--- /dev/null
+++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/MdtSegmentT0Fitter/MdtSegmentT0Fitter.h
@@ -0,0 +1,81 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// Fitting for in situ calibration of segments
+#ifndef MUON_MDTSEGMENTT0FITTER_H
+#define MUON_MDTSEGMENTT0FITTER_H
+
+#include "GaudiKernel/AlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "GaudiKernel/ServiceHandle.h"
+
+#include "TrkDriftCircleMath/DCSLFitter.h"
+#include "MuonSegmentMakerInterfaces/IDCSLFitProvider.h"
+
+#include "MdtCalibSvc/MdtCalibrationDbSvc.h"
+
+#include <vector>
+
+class MsgStream;
+class IIdToFixedIdTool;
+class MdtCalibrationDbSvc;
+class TMinuit;
+
+namespace TrkDriftCircleMath {
+
+  class MdtSegmentT0Fitter : public AlgTool, public DCSLFitter, virtual public Muon::IDCSLFitProvider {
+    public:
+
+      MdtSegmentT0Fitter(const std::string&,const std::string&,const IInterface*);
+      virtual ~MdtSegmentT0Fitter ();
+      virtual StatusCode initialize();
+      virtual StatusCode finalize  ();
+      
+      bool fit( const Line& line, const DCOnTrackVec& dcs, double t0Seed ) const;
+      bool fit( const Line& line, const DCOnTrackVec& dcs, const HitSelection& selection, double t0Seed ) const;
+
+ 
+      DCSLFitter* getFitter() { return this; }
+
+    private:
+      mutable MsgStream* m_log;
+      bool m_verbose;
+
+		  bool m_trace; // debug - traces operation
+      bool m_dumpToFile; // debug - dumps some performance info
+		  bool m_dumpNoFit; // debug - print hit info where fit doesn't run		
+
+      bool m_useInternalRT; // whether to use an internal RT function or the one from Calibration Service
+		  ServiceHandle<MdtCalibrationDbSvc> m_calibDbSvc;
+      // MdtCalibrationDbSvc* m_calibDbSvc;
+      
+      int m_minHits; // minimum number of selected hits for t0 fit. Otherwise use default
+
+      bool m_constrainShifts; // whether to constrain t0 shifts to a 50 ns window
+      double m_constrainT0Error; // t0 error that is used in the constraint
+      bool   m_rejectWeakTopologies; // Reject topolgies that do not have at least one +- combination in one Multilayer
+      bool m_scaleErrors; //!< rescale errors in fit
+
+      bool m_propagateErrors; //!< propagate errors
+
+      TMinuit* m_minuit;
+
+      // counters
+      mutable unsigned int m_ntotalCalls;
+      mutable unsigned int m_npassedNHits;
+      mutable unsigned int m_npassedSelectionConsistency;
+      mutable unsigned int m_npassedNSelectedHits;
+      mutable unsigned int m_npassedMinHits;
+      mutable unsigned int m_npassedMinuitFit;
+    };
+    
+  inline bool MdtSegmentT0Fitter::fit( const Line& line, const DCOnTrackVec& dcs, double t0Seed ) const { 
+    HitSelection selection(dcs.size(),0);
+    return fit( line, dcs, selection, t0Seed ); 
+  }
+}
+
+
+
+#endif
diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/cmt/requirements b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/cmt/requirements
new file mode 100755
index 0000000000000..2e77a0860bd88
--- /dev/null
+++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/cmt/requirements
@@ -0,0 +1,31 @@
+package MdtSegmentT0Fitter
+
+author Srivas Prasad <srivas.prasad@cern.ch>
+
+use AtlasPolicy           AtlasPolicy-*
+use GaudiInterface        GaudiInterface-*        External 
+use TrkDriftCircleMath    TrkDriftCircleMath-*    Tracking/TrkUtilityPackages
+use MdtCalibSvc           MdtCalibSvc-*           MuonSpectrometer/MuonCalib/MdtCalib
+use MuonSegmentMakerInterfaces    MuonSegmentMakerInterfaces-*       MuonSpectrometer/MuonReconstruction/MuonSegmentMakers
+
+private
+use  MuonReadoutGeometry        MuonReadoutGeometry-*           MuonSpectrometer/MuonDetDescr
+use  AtlasROOT                  AtlasROOT-*                     External
+use  MdtCalibData               MdtCalibData-*                  MuonSpectrometer/MuonCalib/MdtCalib
+use  MuonCalibTools             MuonCalibTools-*                MuonSpectrometer/MuonCalib
+use  MuonIdHelpers              MuonIdHelpers-*                 MuonSpectrometer
+use  MuonPrepRawData            MuonPrepRawData-*               MuonSpectrometer/MuonReconstruction/MuonRecEvent
+use  MuonRIO_OnTrack            MuonRIO_OnTrack-*               MuonSpectrometer/MuonReconstruction/MuonRecEvent
+
+
+apply_tag ROOTMathLibs
+end_private
+
+library MdtSegmentT0Fitter *.cxx components/*.cxx
+
+apply_pattern component_library
+apply_pattern declare_joboptions files="*.py"
+
+private
+#macro cppdebugflags '$(cppdebugflags_s)'
+#macro_remove componentshr_linkopts "-Wl,-s"
diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/doc/mainpage.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/doc/mainpage.h
new file mode 100755
index 0000000000000..4c53564b72eaa
--- /dev/null
+++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/doc/mainpage.h
@@ -0,0 +1,7 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+
+*/
diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/src/MdtSegmentT0Fitter.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/src/MdtSegmentT0Fitter.cxx
new file mode 100755
index 0000000000000..ed3051bfaf0cb
--- /dev/null
+++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/src/MdtSegmentT0Fitter.cxx
@@ -0,0 +1,997 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GaudiKernel/MsgStream.h"
+//#include "GaudiKernel/ListItem.h"
+#include "MdtSegmentT0Fitter/MdtSegmentT0Fitter.h"
+
+#include "MuonIdHelpers/MdtIdHelper.h"
+#include "MdtCalibSvc/MdtCalibrationSvc.h"
+#include "MdtCalibSvc/MdtCalibrationSvcSettings.h"
+//#include "MdtCalibSvc/MdtCalibrationSvcInput.h"
+#include "MuonReadoutGeometry/MdtReadoutElement.h"
+#include "MuonReadoutGeometry/MuonDetectorManager.h"
+
+#include "MdtCalibSvc/MdtCalibrationDbSvc.h"
+#include "MuonCalibTools/IdToFixedIdTool.h"
+#include "MdtCalibData/IRtRelation.h"
+#include "MdtCalibData/IRtResolution.h"
+#include "MdtCalibData/MdtRtRelation.h"
+
+
+
+#include "MuonRIO_OnTrack/MdtDriftCircleOnTrack.h"
+#include "MuonPrepRawData/MdtPrepData.h"
+
+#include <iostream>
+#include <fstream>
+
+#include "TTree.h"
+#include "TROOT.h"
+#include "TMath.h"
+#include "TVirtualFitter.h"
+#include "TMinuit.h"
+
+// tdc count bin size
+#define TDCBINSIZE 0.78125
+
+// number of fit parameters
+#define NUMPAR 3
+
+// prints a message if a radius is bigger than this
+#define MAX_RAD 16
+
+// time corresponding to r=15 mm for internal rt
+#define TUBE_TIME 757.22
+
+#define MAX_DRIFT 855
+
+// garbage time value to return when radius isn't wihin rt range
+#define R2TSPURIOUS 50000
+
+#define WEAK_TOPO_T0ERROR 10
+#define STRONG_TOPO_T0ERROR 50
+
+
+namespace TrkDriftCircleMath {
+  
+  bool use_hardcoded;
+  bool use_shift_constraint;
+  double constrainT0Error;
+	
+//	int count;
+    
+  MdtSegmentT0Fitter::MdtSegmentT0Fitter(const std::string& ty,const std::string& na,const IInterface* pa)
+  : AlgTool(ty,na,pa),
+    DCSLFitter(), 
+    m_calibDbSvc("MdtCalibrationDbSvc", na),
+    m_ntotalCalls(0),
+    m_npassedNHits(0),
+    m_npassedSelectionConsistency(0),
+    m_npassedNSelectedHits(0),
+    m_npassedMinHits(0),
+    m_npassedMinuitFit(0)
+  {
+    declareInterface <IDCSLFitProvider> (this);
+    declareProperty("MinimumHits", m_minHits = 4);
+    declareProperty("DumpToFile", m_dumpToFile = false);
+    declareProperty("UseInternalRT", m_useInternalRT = false);
+    declareProperty("TraceOperation", m_trace = false);
+    declareProperty("DumpNoFit", m_dumpNoFit = false);
+    declareProperty("ConstrainShifts", m_constrainShifts = false);
+    declareProperty("ConstrainT0Error", m_constrainT0Error = 10.);
+    declareProperty("RejectWeakTopologies",  m_rejectWeakTopologies = true);
+    declareProperty("RescaleErrors",m_scaleErrors = true );
+    declareProperty("PropagateErrors",m_propagateErrors = true );
+  }
+  
+  
+  MdtSegmentT0Fitter::~MdtSegmentT0Fitter(){}
+  
+  StatusCode MdtSegmentT0Fitter::initialize() {
+    StatusCode sc = AlgTool::initialize(); 
+    m_log = new MsgStream(msgSvc(), name());
+    m_verbose = m_log->level() <= MSG::VERBOSE;
+
+    // only print in debug output level
+    m_trace = m_log->level() <= MSG::DEBUG && m_trace;
+    
+    use_hardcoded = m_useInternalRT;
+    use_shift_constraint = m_constrainShifts;
+    constrainT0Error = m_constrainT0Error;
+//		count = 0;
+    
+        
+    // Get pointer to MdtCalibrationDbSvc and cache it :
+    if ( !m_calibDbSvc.retrieve().isSuccess() ) {
+      *m_log << MSG::FATAL << "Unable to retrieve pointer to MdtCalibrationDbSvc" << endreq;
+      return StatusCode::FAILURE;
+    }
+
+    TMinuit* oldMinuit = gMinuit;
+    m_minuit = new TMinuit(3);
+    m_minuit->SetPrintLevel(-1); // -1: no output, 1: std output
+    if( m_verbose ) m_minuit->SetPrintLevel(1);
+    gMinuit = oldMinuit;
+
+    return sc;
+  }
+  
+  StatusCode MdtSegmentT0Fitter::finalize() {
+    
+    double scaleFactor = m_ntotalCalls != 0 ? 1./(double)m_ntotalCalls : 1.;
+
+    *m_log << MSG::INFO << "Summarizing fitter statistics " << endreq
+	   << " Total fits       " << std::setw(10) << m_ntotalCalls << "   " << scaleFactor*m_ntotalCalls << endreq
+	   << " hits > 2         " << std::setw(10) << m_npassedNHits << "   " << scaleFactor*m_npassedNHits << endreq
+	   << " hit consis.      " << std::setw(10) << m_npassedSelectionConsistency << "   " << scaleFactor*m_npassedSelectionConsistency << endreq
+	   << " sel. hits > 2    " << std::setw(10) << m_npassedNSelectedHits << "   " << scaleFactor*m_npassedNSelectedHits << endreq
+	   << " Hits > min hits  " << std::setw(10) << m_npassedMinHits << "   " << scaleFactor*m_npassedMinHits << endreq
+	   << " Passed Fit       " << std::setw(10) << m_npassedMinuitFit << "   " << scaleFactor*m_npassedMinuitFit << endreq;
+    delete m_log;
+    if( gMinuit == m_minuit ) gMinuit = 0;
+    delete m_minuit;
+    return AlgTool::finalize(); 
+  }
+  
+  
+  /***********************************************************************************/
+  /// RT function from Craig Blocker
+  /// ok for now, possibly replace with actual RT function used to calibrate run
+  
+  static double t2r_a[10] = {1.184169e-1, 3.32382e-2, 4.179808e-4, -5.012896e-6, 2.61497e-8, -7.800677e-11, 1.407393e-13, -1.516193e-16, 8.967997e-20, -2.238627e-23};
+  static double rcorr_a[] = {234.3413, -5.803375, 5.061677e-2, -1.994959e-4, 4.017433e-7, -3.975037e-10, 1.522393e-13};
+  
+  double rcorr(double tin) {
+    double rc;
+    if(tin < 16.) {
+      rc = -50.;
+    } else {
+      double tpow = 1.;
+      rc = 0.;
+      for(int j = 0; j < 7; j++) {
+        rc += rcorr_a[j]*tpow;
+        tpow *= tin;
+      }
+    }
+    rc = rc/1000.;
+    
+    return rc;
+  }
+  
+  double t2r(double tin) {
+    if(tin < 0.) return 0.;
+    if(tin > MAX_DRIFT) return 20.;
+    
+    double tpow = 1.;
+    double rc = 0.;
+    for(int j = 0; j < 10; j++) {
+      rc += t2r_a[j]*tpow;
+      tpow *= tin;
+    }
+    
+    rc -= rcorr(tin);
+    return rc;
+  }
+  
+  /// derivatives of RT function, use to get errors
+  double rcorrprime(double tin) {
+    double rc;
+    if(tin < 16.) {
+      rc = 0.;
+    } else {
+      double tpow = 1.;
+      rc = 0.;
+      for(int j = 1; j < 7; j++) {
+        rc += j*rcorr_a[j]*tpow;
+        tpow *= tin;
+      }
+    }
+    rc = rc/1000.;
+    
+    return rc;
+  }
+  
+  double t2rprime(double tin) {
+    if(tin < 0.) return 0.;
+    if(tin > MAX_DRIFT) return 20.;
+    
+    double tpow = 1.;
+    double rc = 0.;
+    for(int j = 1; j < 10; j++) {
+      rc += j*t2r_a[j]*tpow;
+      tpow *= tin;
+    }
+    
+    rc -= rcorrprime(tin);
+    return rc;
+  }
+  
+  
+  /// use a binary search to get rt-inverse from rt
+  /// assumes the function is monotonic, obviously not true for these polynomial parametrizations for all t
+  double r2t(double r) {
+    double ta = 0;
+    double tb = MAX_DRIFT;
+    if(r<t2r(ta) ) {
+      return -1*R2TSPURIOUS;
+    } else if(r>t2r(tb)) {
+      return R2TSPURIOUS;
+    }
+    
+    int itr = 0;
+    while (ta <= tb) {
+      double tm  = (ta + tb) / 2;  // compute mid point.
+      double rtm = t2r(tm);
+      if(fabs(rtm - r) < 0.001 ) {
+        return tm;
+      }
+      else if (r > rtm) {
+        ta = tm;  // repeat search in top half.
+      }
+      else if (r < rtm ) {
+        tb = tm; // repeat search in bottom half.
+      }
+      
+      itr++;
+      if(itr>50) return -1;
+    }
+    return -1;    // failed to find key
+  }
+  
+  double r2t_ext(   std::vector<const MuonCalib::IRtRelation*> *rtpointers, double r, int i) {
+    const MuonCalib::IRtRelation* rtrel = rtpointers->at(i);
+    //  double ta = 0;
+    // double tb = 
+    
+    double ta = rtrel->tLower();
+    double tb = rtrel->tUpper();
+    if(r<rtrel->radius(ta) ) {
+      return -1*R2TSPURIOUS;
+    } else if(r>rtrel->radius(tb)) {
+      return R2TSPURIOUS;
+    }
+    
+    int itr = 0;
+    while (ta <= tb) {
+      double tm  = (ta + tb) / 2;  // compute mid point.
+      double rtm = rtrel->radius(tm);
+      if(fabs(rtm - r) < 0.001 ) {
+        return tm;
+      }
+      else if (r > rtm) {
+        ta = tm;  // repeat search in top half.
+      }
+      else if (r < rtm ) {
+        tb = tm; // repeat search in bottom half.
+      }
+      
+      itr++;
+      if(itr>50) return -1;
+    }
+    return -1;    // failed to find key
+  }
+  
+  
+  /// data to pass to fcn
+  typedef struct {
+    double z;
+    double t;
+    double y;
+    double w;
+    double r;
+    const MuonCalib::IRtRelation *rt;
+  } hitcoords;
+  
+  std::vector<hitcoords> data;
+  double t_lo, t_hi;
+  int used;
+  int t0Error;
+  /// the fit function
+  /// gets distance between the line and the hit (in the frame whose direction is given by the line segment
+  /// and position is given by the weighted average of all the hits), subtracts off the radius from the rt relation etc 
+  void mdtSegmentT0Fcn(Int_t &/*npar*/, Double_t* grad, Double_t &fval, Double_t* par, Int_t jflag) {
+    if(jflag < 0) grad[0] = 0.;
+    
+    double ang = par[0];  
+    double b = par[1];
+    double t0 = par[2];
+    
+    double cosin = cos(ang);
+    double sinus = sin(ang);
+//    if ( sinus < 0.0 ) {
+//      sinus = -sinus;
+//      cosin = -cosin;
+//    } else if ( sinus == 0.0 && cosin < 0.0 ) {
+//      cosin = -cosin;
+//    }
+    
+    fval = 0.;
+    // Add t0 constraint 
+    if(use_shift_constraint) {
+     fval += par[2]*par[2]/(constrainT0Error*constrainT0Error);
+    } else if (t0Error == WEAK_TOPO_T0ERROR ) {
+     fval += par[2]*par[2]/(1.0 *t0Error*t0Error);
+    }
+    double t, r, z, y, w, dist;
+    for(int i = 0; i < used ; i++) {
+      t = data[i].t - t0;
+      z = data[i].z;
+      y = data[i].y;
+      w = data[i].w;
+      dist = fabs(b*cosin + z*sinus - y*cosin); // same thing as fabs(a*z - y + b)/sqrt(1. + a*a);
+      double uppercut = use_hardcoded ? TUBE_TIME : data[i].rt->tUpper();
+      double lowercut = use_hardcoded ? 0 : data[i].rt->tLower();
+// Penalty for t<lowercut and t >uppercut
+      if (t> uppercut ) { // too large 
+	fval += (t-uppercut)* (t-uppercut)/10.;
+      }else if (t < 0 ) {// too small
+	fval += (t-lowercut)*(t-lowercut)/10.;
+      }
+      if(use_hardcoded) {
+	  if(t<0) r=0;
+	  else r = t2r(t);
+      } else {
+	  if(t<lowercut) r =  data[i].rt->radius(lowercut);
+          else if(t>uppercut)  r =  data[i].rt->radius(uppercut);
+	  else r = data[i].rt->radius(t);
+      }
+      fval += (dist - r)*(dist - r)*w;
+      
+    }
+    
+    return;
+  }
+  /***********************************************************************************/
+  
+  
+  int sign(double a) {
+    if(a>0) return 1;
+    if(a<0) return -1;
+    return 0;
+  }
+  bool MdtSegmentT0Fitter::fit( const Line& line, const DCOnTrackVec& dcs, const HitSelection& selection, double t0Seed ) const {
+
+    ++m_ntotalCalls;
+
+    if(m_trace) *m_log << MSG::DEBUG << "New seg: " << "\n"; //<< seg;
+ 
+    const DCOnTrackVec& dcs_keep = dcs;
+
+    unsigned int N = dcs_keep.size();
+    used=0;
+    m_result.setT0Shift(-99999,-99999);
+    
+    if(N<2) {
+      return false;
+    }
+    ++m_npassedNHits;
+    if( selection.size() != N ) {
+      *m_log << MSG::ERROR << "MdtSegmentT0Fitter.cxx:fit with t0 <bad HitSelection>" <<endreq;
+      return false;
+    }  
+    ++m_npassedSelectionConsistency;
+    for(unsigned int i=0;i<N;++i){
+      if( selection[i] == 0 ) ++used;
+      //      if(m_trace) *m_log << MSG::DEBUG << " selection flag " <<  selection[i] << endreq;
+    }
+    if(used < 2){
+      if(m_trace) *m_log << MSG::DEBUG << "TOO FEW HITS SELECTED" <<endreq;
+      return false;
+    }
+    ++m_npassedNSelectedHits;
+    if(used < m_minHits) {
+      if(m_trace) *m_log << MSG::DEBUG << "FEWER THAN Minimum HITS N " << m_minHits << " total hits " <<N<<" used " << used <<"\n";
+
+      //
+      //     Copy driftcircles and reset the drift radii as they might have been overwritten
+      //     after a succesfull t0 fit 
+      // 
+
+      DCOnTrackVec::const_iterator it = dcs.begin();
+      DCOnTrackVec::const_iterator it_end = dcs.end();
+      
+      DCOnTrackVec dcs_new;
+      dcs_new.reserve(dcs.size());
+      double chi2p = 0.;
+      for(int i=0; it!=it_end; ++it, ++i ){
+	const DriftCircle* ds  = & dcs[i];
+        if(fabs(ds->r()-ds->rot()->driftRadius())>0.1&&m_trace) std::cout << " Different radii on dc " << ds->r() << " rot " << ds->rot()->driftRadius() << std::endl;  
+	DriftCircle dc_keep(ds->position(), ds->rot()->driftRadius(), ds->dr(), ds->drPrecise(), ds->state(), ds->id(), ds->index(),ds->rot() );
+	DCOnTrack dc_new(dc_keep, 0., 0.);
+	dc_new.state(dcs[i].state());
+	dcs_new.push_back( dc_new );
+        if( selection[i] == 0 ){
+          double t = ds->rot()->driftTime();
+          const MuonCalib::MdtRtRelation *rtInfo = m_calibDbSvc->getRtCalibration(ds->rot()->identify());
+          double tUp = rtInfo->rt()->tUpper();
+          double tLow = rtInfo->rt()->tLower();
+          if(t<tLow) chi2p += (t-tLow)*(t-tLow)/10.;
+          if(t>tUp) chi2p += (t-tUp)*(t-tUp)/10.;
+        }
+      }
+      if(m_trace&&chi2p>0) std::cout << " NO Minuit Fit TOO few hits Chi2 penalty " << chi2p << std::endl;
+      bool oldrefit = DCSLFitter::fit( line, dcs_new, selection ); 
+      chi2p += m_result.chi2();
+// add chi2 penalty for too large or too small driftTimes  t < 0 or t> t upper
+      m_result.set( chi2p, m_result.ndof(),  m_result.dtheta(),  m_result.dy0() );
+      int iok = 0;
+      if(oldrefit) iok = 1;
+      if(m_trace) std::cout << " chi2 total " << m_result.chi2() << " angle " << m_result.line().phi() << " y0 " << m_result.line().y0()  << " nhits "<< selection.size() << " refit ok " << iok << std::endl;
+      return oldrefit;
+    } else {
+      if(m_trace) *m_log << MSG::DEBUG << "FITTING FOR T0 N "<<N<<" used " << used << endreq;
+    } 
+
+    ++m_npassedMinHits;
+
+    
+    if (m_trace) *m_log << MSG::DEBUG <<" in  MdtSegmentT0Fitter::fit with N dcs "<< N << " hit selection size " <<  selection.size() << endreq;
+    if(m_trace) *m_log << MSG::DEBUG <<"in fit "<<m_result.hasT0Shift()<< " " <<m_result.t0Shift()<<"\n";
+
+    
+    
+    double Zc=0, Yc=0, S=0, Sz=0, Sy=0;
+    std::vector<double> y(N);
+    std::vector<double> z(N);
+    std::vector<double> w(N); 
+    std::vector<double> r(N);
+    std::vector<double> dr(N);
+    std::vector<double> t(N);
+    //   std::vector<double> driftt(N);
+    std::vector<const MuonCalib::IRtRelation*> rtpointers(N);
+    
+    // allocate memory for data
+    // allocate memory for data
+    if( data.capacity() != 50 ) data.reserve(50);
+    data.resize(used);
+    {
+      DCOnTrackVec::const_iterator it = dcs_keep.begin();
+      DCOnTrackVec::const_iterator it_end = dcs_keep.end();
+      for(int ii=0 ;it!=it_end; ++it, ++ii ){
+        const Muon::MdtDriftCircleOnTrack *roto = it->rot();
+        if (!roto) {
+          *m_log << MSG::ERROR <<" MdtSegmentT0Fitter: NO DC ROT pointer found " << endreq;;
+          return false;
+        }
+        if(m_trace) *m_log << MSG::DEBUG << "hit # "<<ii<<" ";
+        y[ii] = it->y();
+        z[ii] = it->x();
+        r[ii] = std::abs( roto->driftRadius() );
+        dr[ii] = it->dr(); 
+        const Muon::MdtPrepData *peerd;
+        peerd = dynamic_cast<const Muon::MdtPrepData*>( roto->prepRawData() );
+        if(!peerd) {
+          *m_log << MSG::ERROR <<"MdtSegmentT0Fitter: Can't convert to MdtPrepData* !! Not fitting for t0\n";
+          return false;
+        }
+        Identifier id = roto->identify();
+        const MuonCalib::MdtRtRelation *rtInfo = m_calibDbSvc->getRtCalibration(id);
+        rtpointers[ii] = rtInfo->rt();
+        t[ii] = roto->driftTime();
+
+	double newerror = m_scaleErrors ? it->drPrecise() : it->dr();        
+
+        if( newerror > 0.) w[ii] = 1./(newerror);
+        else w[ii] = 0.;
+        w[ii]*=w[ii];
+        if(r[ii]<0){
+          r[ii] = 0.;
+          if(m_trace) *m_log << MSG::DEBUG << "MdtSegmentT0Fitter (using times) ERROR: <Negative r> " << r[ii] <<endreq;
+        }
+
+        if(m_trace) *m_log << MSG::DEBUG << "DC:  (" << y[ii] << "," << z[ii] << ") R = " << r[ii] << " W " << w[ii] <<" t " <<t[ii]<< " id: "<<it->id()<<" sel " << selection[ii] <<endreq;
+        
+        if( selection[ii] == 0 ){
+          S+=w[ii];
+          Sz+= w[ii]*z[ii];
+          Sy+= w[ii]*y[ii];
+          if(r[ii] > MAX_RAD ) {
+            if(m_trace) *m_log << MSG::DEBUG <<"Radius is too big" << endreq;
+          }
+        }
+      }
+    }
+    Zc = Sz/S;
+    Yc = Sy/S;
+    
+    if(m_trace) *m_log << MSG::DEBUG << "Yc " << Yc << " Zc " << Zc <<endreq;
+    
+    /// go to coordinates centered at the average of the hits
+    for(unsigned int i=0;i<N;++i) {
+      y[i]  -= Yc;
+      z[i]  -= Zc;
+    }
+    
+    int selcount(0);
+    DCOnTrackVec::const_iterator it = dcs_keep.begin();
+    DCOnTrackVec::const_iterator it_end = dcs_keep.end();
+    
+    t_lo = 1e10;
+    t_hi = -1e10;
+    // replicate for the case where the external rt is used...
+    // each hit has an rt function with some range...we want to fit such that
+    // tlower_i < ti - t0 < tupper_i
+    double min_tlower=1e10;
+    double max_tupper=-1e10;
+    
+    double t0seed=0; // the average t0 of the hit
+    double st0 = 0; // the std deviation of the hit t0s
+    double min_t0 = 1e10; // the smallest t0 seen
+    double tee0, tl, th;
+    
+    
+    for(int ii=0 ;it!=it_end; ++it, ++ii ){
+      if( selection[ii] == 0 ) {
+        data[selcount].z = z[ii];
+        data[selcount].y = y[ii];
+        data[selcount].r = r[ii];
+        data[selcount].w = w[ii];
+        data[selcount].rt = rtpointers[ii];
+        double r2tval;
+        if(use_hardcoded) {
+          r2tval = r2t(r[ii]);
+        } else {
+          r2tval = r2t_ext(&rtpointers,  r[ii], ii) ;
+          tl = rtpointers[ii]->tLower();
+          th = rtpointers[ii]->tUpper();
+          if(t[ii] - tl < min_tlower) min_tlower = t[ii] - tl;
+          if(t[ii] - th > max_tupper) max_tupper = t[ii] - th;
+        }
+        tee0 = t[ii] - r2tval;
+
+        if(m_trace) {
+          *m_log << MSG::DEBUG <<" z "<<z[ii];
+          *m_log << MSG::DEBUG <<" y "<<y[ii];
+          *m_log << MSG::DEBUG <<" r "<<r[ii];
+          *m_log << MSG::DEBUG <<" t "<<t[ii];
+          *m_log << MSG::DEBUG <<" t0 "<<tee0;
+          if(!use_hardcoded) {
+            *m_log << MSG::DEBUG <<" tLower "<<tl;
+            *m_log << MSG::DEBUG <<" tUpper "<<th;
+          }
+          *m_log << MSG::DEBUG << endreq;
+        }
+        t0seed += tee0;
+        st0 += tee0*tee0;
+        if(tee0 < min_t0 && fabs(r2tval) < R2TSPURIOUS) min_t0 = tee0;
+        
+        data[selcount].t = t[ii];
+        if(t[ii]< t_lo) t_lo = t[ii];
+        if(t[ii] > t_hi) t_hi = t[ii];
+        selcount++;
+      } 
+    }
+    t0seed /= selcount;
+    st0 = st0/selcount - t0seed*t0seed;
+    st0 = st0 > 0. ? sqrt(st0) : 0.;
+    t_hi -= MAX_DRIFT;
+    
+    if(!use_hardcoded) {
+      t_hi = max_tupper;
+      t_lo = min_tlower;
+    }
+    
+    if(m_trace) *m_log << MSG::DEBUG <<"t_hi "<<t_hi<<" t_lo "<<t_lo<<" t0seed "<<t0seed<<" sigma "<<st0<< " min_t0 "<<min_t0<< endreq;
+    if(t_hi > t_lo ) {
+      if(m_dumpNoFit) {
+        std::ofstream gg;
+        gg.open("fitnotdone.txt", std::ios::out | std::ios::app);
+        DCOnTrackVec::const_iterator it = dcs_keep.begin();
+        DCOnTrackVec::const_iterator it_end = dcs_keep.end();
+        for(int ii=0 ;it!=it_end; ++it, ++ii ){
+          const Muon::MdtDriftCircleOnTrack *roto = it->rot();
+          const Muon::MdtPrepData *peerd;
+          if(!roto) continue; 
+          peerd = dynamic_cast<const Muon::MdtPrepData*>( roto->prepRawData() );
+          if(!peerd) continue; 
+          Identifier id = roto->identify();
+          gg<<id;
+          gg<<" z "<<z[ii];
+          gg<<" y "<<y[ii];
+          gg<<" r "<<r[ii];
+          gg<<" t "<<t[ii];
+          gg<<" t0 "<<t[ii] - r2t_ext(&rtpointers,  r[ii], ii);
+          gg<<" adc "<<peerd->adc();
+          gg<<" tdc "<<peerd->tdc();
+          gg<<*it;
+          gg<<" sel "<<selection[ii];
+          gg<< endreq;
+        }
+        gg<<"--------------\n";
+      }
+    }
+    
+    
+    // ************************* seed the parameters
+    double theta = line.phi();
+    double cosin = cos(theta);
+    double sinus = sin(theta);
+    
+    if ( sinus < 0.0 ) {
+      sinus = -sinus;
+      cosin = -cosin;
+    } else if ( sinus == 0.0 && cosin < 0.0 ) {
+      cosin = -cosin;
+    }
+    if(m_trace) *m_log << MSG::DEBUG <<"before fit theta "<<theta<<" sinus "<<sinus<< " cosin "<< cosin << endreq; 
+    
+    double d = line.y0() + Zc*sinus-Yc*cosin;
+    
+    if(m_trace) {
+      *m_log << MSG::DEBUG <<" line x y "<<line.position().x()<<" "<<line.position().y()<< endreq;
+      *m_log << MSG::DEBUG <<" Zc Yc "<< Zc <<" "<<Yc<< endreq;
+      *m_log << MSG::DEBUG <<" line x0 y0 "<<line.x0()<<" "<<line.y0()<< endreq;
+      *m_log << MSG::DEBUG <<" hit shift " << -Zc*sinus+Yc*cosin;
+    } 
+
+// Calculate signed radii 
+
+    int nml1p = 0;
+    int nml2p = 0;
+    int nml1n = 0;
+    int nml2n = 0;
+    double sdist;
+    it = dcs_keep.begin();
+    for(int ii=0 ;it!=it_end; ++it, ++ii ){
+      if( selection[ii] != 0 ) continue;
+      sdist = d*cosin + z[ii]*sinus - y[ii]*cosin; // same thing as fabs(a*z - y + b)/sqrt(1. + a*a);
+//      if (r[ii] < 1) continue;
+      if(it->id().ml()==0&&sdist > 0) nml1p++;
+      if(it->id().ml()==0&&sdist < 0) nml1n++;
+      if(it->id().ml()==1&&sdist > 0) nml2p++;
+      if(it->id().ml()==1&&sdist < 0) nml2n++;
+    }
+
+// Define t0 constraint in Minuit 
+    t0Error = STRONG_TOPO_T0ERROR;
+    if (nml1p+nml2p < 2 || nml1n+nml2n < 2) t0Error = WEAK_TOPO_T0ERROR;
+
+// Reject topologies where in one of the Multilayers no +- combination is present
+    if((nml1p<1||nml1n<1)&&(nml2p<1||nml2n<1)&&m_rejectWeakTopologies) {
+      if(m_trace) *m_log << MSG::DEBUG <<" Combination rejected for positive radii ML1 " <<  nml1p << " ML2 " <<  nml2p << " negative radii ML1 " << nml1n << " ML " << nml2n << " used hits " << used << " t0 Error " << t0Error  << endreq;
+      it = dcs.begin();
+      it_end = dcs.end();
+      double chi2p = 0.; 
+      DCOnTrackVec dcs_new;
+      dcs_new.reserve(dcs.size());
+      for(int i=0; it!=it_end; ++it, ++i ){
+	const DriftCircle* ds  = & dcs[i];
+        if(fabs(ds->r()-ds->rot()->driftRadius())>0.1&&m_trace) std::cout << " Different radii on dc " << ds->r() << " rot " << ds->rot()->driftRadius() << std::endl;  
+	DriftCircle dc_keep(ds->position(), ds->rot()->driftRadius(), ds->dr(), ds->drPrecise(), ds->state(), ds->id(), ds->index(),ds->rot() );
+	DCOnTrack dc_new(dc_keep, 0., 0.);
+	dc_new.state(dcs[i].state());
+	dcs_new.push_back( dc_new );
+        if( selection[i] == 0 ){
+          double t = ds->rot()->driftTime();
+          const MuonCalib::MdtRtRelation *rtInfo = m_calibDbSvc->getRtCalibration(ds->rot()->identify());
+          double tUp = rtInfo->rt()->tUpper();
+          double tLow = rtInfo->rt()->tLower();
+          if(t<tLow) chi2p += (t-tLow)*(t-tLow)/10.;
+          if(t>tUp) chi2p += (t-tUp)*(t-tUp)/10.;
+        } 
+      }
+      if(m_trace&&chi2p>0) *m_log << MSG::DEBUG  << " Rejected weak topology Chi2 penalty " << chi2p << std::endl;
+      bool oldrefit = DCSLFitter::fit( line, dcs_new, selection ); 
+      chi2p += m_result.chi2();
+// add chi2 penalty for too large or too small driftTimes  t < 0 or t> t upper
+      m_result.set( chi2p, m_result.ndof(),  m_result.dtheta(),  m_result.dy0() );
+      return oldrefit;
+    }  // end rejection of weak topologies  
+
+    if(m_trace) *m_log << MSG::DEBUG <<" positive radii ML1 " <<  nml1p << " ML2 " <<  nml2p << " negative radii ML1 " << nml1n << " ML " << nml2n << " used hits " << used << " t0 Error " << t0Error  << endreq;
+    
+//    m_minuit->BuildArrays(3);
+    m_minuit->SetFCN(mdtSegmentT0Fcn);
+    Double_t arglist[3];
+    
+    // Set printout level
+    arglist[0] = -1;
+    // Clear previous fit
+    m_minuit->mncler();
+    arglist[0] = -1;
+    
+    Double_t vstart[3];
+    vstart[0] = theta;
+    // x' = x - xc, y' = y - yc => y' = m x' + b + m xc - yc
+    // and b = yc - m xc
+    vstart[1] = d ; 
+    vstart[2] = 0 ;
+
+    // if t0Seed value from outside use this
+    if(t0Seed > -999.)  vstart[2] = t0Seed; 
+
+    Double_t step[3] = {0.01 , 0.01 , 0.1 };
+    
+    if(m_trace) {
+      *m_log << MSG::DEBUG <<"\n____________INITIAL VALUES________________\n";
+      *m_log << MSG::DEBUG <<"Theta " << theta << "("<<tan(theta)<<") d " << vstart[1] <<endreq;
+    }
+    
+    int errFlag = 0;
+    int errFlag1 = 0;
+    int errFlag2 = 0;
+    int errFlag3 = 0;
+    int errFlag4 = 0;
+    int errFlag5 = 0;
+    m_minuit->mnparm(0, "a", vstart[0], step[0], -0.5, 3.5,errFlag);
+    m_minuit->mnparm(1, "b", vstart[1], step[1], 0., 0.,errFlag);
+    // m_minuit->SetParameter(2, "t0", vstart[2], step[2], t_hi, t_lo,errFlag);
+    m_minuit->mnparm(2, "t0", vstart[2], step[2], 0., 0.,errFlag);
+
+    if (errFlag !=0 &&m_trace)  {
+      *m_log << MSG::DEBUG  <<  " ALARM with steering of Minuit variable " << errFlag << endreq;
+    }
+   
+    m_minuit->FixParameter(0);
+    m_minuit->FixParameter(1);
+    m_minuit->mnexcm("MINIMIZE", arglist, 0,errFlag1);
+
+    m_minuit->Release(0);
+    m_minuit->Release(1);
+    m_minuit->FixParameter(2);
+    m_minuit->mnexcm("MINIMIZE", arglist, 0,errFlag2);
+    m_minuit->mnexcm("MIGRAD", arglist, 0,errFlag3);
+    m_minuit->Release(2);
+    m_minuit->mnexcm("MINIMIZE", arglist, 0,errFlag4);
+    m_minuit->mnexcm("MIGRAD", arglist, 0,errFlag5);
+    if(errFlag5!=0&&errFlag4==0) {
+      m_minuit->mnexcm("MINIMIZE", arglist, 0,errFlag4); 
+      if (errFlag4 == 0 &&m_trace)  {
+        *m_log << MSG::DEBUG  <<  " ALARM Fall back to MINIMIZE " << errFlag4 << endreq;
+      }
+    } 
+    
+    // Get the chisquare and errors
+    double chisq;
+    double edm;
+    double errdef;
+    int npari, nparx, icstat;
+    m_minuit->mnstat(chisq, edm, errdef, npari, nparx, icstat);
+   
+    int fitretval = errFlag5;
+    if (npari<0 || nparx < 0 || chisq < 0) *m_log << MSG::ERROR  <<  " MdtSegmentT0Fitter MINUIT problem " << " chisq "<<chisq<<" npari "<<npari<<" nparx "<< nparx <<" fitretval "<< fitretval<< endreq;
+
+    if (fitretval !=0 &&m_trace)  {
+     *m_log << MSG::DEBUG  <<  " ALARM return value " << fitretval << endreq;
+    }
+    if(m_dumpToFile) {
+      std::ofstream ff;
+      ff.open("fitres.txt", std::ios::out | std::ios::app);
+//      ff << fitretval<<" 0 "<<chisq<<" "<<t_hi<<" "<<t_lo<<" "<<t0seed<<" "<<st0<<" "<<min_t0<<" "<<m_minuit->GetParameter(2)<<" "<<m_minuit->GetParError(2)<< endreq;
+//			TMinut * tm = (TMinuit*) minuit->GetObjectFit();
+			ff<<npari<<" "<<nparx<<" "<<fitretval<<" "<<chisq<< " "<< endreq;
+      ff.close();
+    }
+    if(m_trace) *m_log << MSG::DEBUG <<"chisq "<<chisq<<" npari "<<npari<<" nparx "<<nparx<<" fitretval "<<fitretval<< endreq;
+
+    // Do standard DCSL fit if minuit is bad 
+    // Do standard DCSL fit if all fits from minuit are bad 
+    if (errFlag5!=0&&errFlag4!=0&&errFlag3!=0&&errFlag2!=0&&errFlag1!=0)  {
+      if(m_trace)*m_log << MSG::DEBUG << " ALARM Minimize fix " << errFlag1 << " ALARM minimize release " << errFlag2 
+			<< " ALARM migrad fix 1 " << errFlag3 << " ALARM minimize all free" << errFlag4 << " ALARM migrad all free " 
+			<< errFlag5 << endreq;
+
+      DCOnTrackVec dcs_new;
+      dcs_new.reserve(dcs.size());
+      DCOnTrackVec::const_iterator it = dcs.begin();
+      DCOnTrackVec::const_iterator it_end = dcs.end();
+    
+      for(int i=0; it!=it_end; ++it, ++i ){
+	const DriftCircle* ds  = & dcs[i];
+	DriftCircle dc_keep(ds->position(), ds->rot()->driftRadius(), ds->dr(), ds->drPrecise(), ds->state(), ds->id(), ds->index(),ds->rot() );
+	DCOnTrack dc_new(dc_keep, 0., 0.);
+	dc_new.state(dcs[i].state());
+	dcs_new.push_back( dc_new );
+      }
+
+      bool oldrefit =  DCSLFitter::fit( line , dcs_new, selection );
+      //int iok = 0;
+      //if(oldrefit) iok = 1;
+      return  oldrefit;
+    } 
+    ++m_npassedMinuitFit;
+
+    // Get the fit values
+    double aret(0),aErr(0);
+    m_minuit->GetParameter(0,aret,aErr); // theta returned
+    double dtheta = aErr;
+    
+    double tana = tan(aret); // tangent of angle
+    
+    double ang = aret;  // between zero and pi
+    cosin = cos(ang);
+    sinus = sin(ang);
+    if ( sinus < 0.0 ) {
+      sinus = -sinus;
+      cosin = -cosin;
+    } else if ( sinus == 0.0 && cosin < 0.0 ) {
+      cosin = -cosin;
+    }
+    ang = atan2(sinus, cosin);
+    
+    
+    double b(0),bErr(0);
+    m_minuit->GetParameter(1,b,bErr); // intercept
+
+    
+    double t0(0),t0Err(0);
+    m_minuit->GetParameter(2,t0,t0Err);
+    
+    
+    //    double y0 = b * cosin ; // parallel distance
+    double dy0 = cosin * bErr - b * sinus * aErr;
+    
+    double del_t;
+    if(use_hardcoded) del_t = fabs(t2r((t0+t0Err)) - t2r(t0));
+    else del_t = fabs(rtpointers[0]->radius((t0+t0Err)) - rtpointers[0]->radius(t0)) ;
+    
+    if(m_trace) {
+      *m_log << MSG::DEBUG <<"____________FINAL VALUES________________\n";
+      *m_log << MSG::DEBUG <<"Values: a "<<tana<<" d "<<b * cosin <<" t0 "<<t0<< endreq; 
+      *m_log << MSG::DEBUG <<"Errors: a "<<aErr<<" b "<<dy0 <<" t0 "<<t0Err<< endreq; 
+    }
+    
+    
+    d = b * cosin;
+    
+    
+    double covar[3][3];
+    m_minuit->mnemat(&covar[0][0],3);  // 3x3
+    if(m_trace) {
+      *m_log << MSG::DEBUG <<"COVAR  ";
+      for(int it1=0; it1<3; it1++) {
+        for(int it2=0; it2<3; it2++) {
+          *m_log << MSG::DEBUG <<covar[it1][it2]<<" ";
+        }
+  	 *m_log << MSG::DEBUG << endreq;
+      }
+    }
+    
+    m_result.dcs().clear();
+    m_result.clusters().clear();
+    m_result.emptyTubes().clear();
+
+    if(m_trace) *m_log << MSG::DEBUG <<"after fit theta "<<ang<<" sinus "<<sinus<< " cosin "<< cosin << endreq; 
+    
+    double chi2 = 0;
+    unsigned int nhits(0);
+    double yl;
+    
+    
+    // calculate predicted hit positions from track parameters
+    it = dcs_keep.begin();
+    it_end = dcs_keep.end();
+    if(m_trace) *m_log << MSG::DEBUG <<"------NEW HITS------\n";
+    
+    for(int i=0; it!=it_end; ++it, ++i ){
+      double rad, drad;
+      
+      double uppercut = use_hardcoded ? TUBE_TIME :  rtpointers[i]->tUpper();
+      double lowercut = use_hardcoded ? 0 :  rtpointers[i]->tLower();
+      if(use_hardcoded) { 
+        rad = t2r(t[i]-t0);
+        if(t[i]-t0<lowercut) rad = t2r(lowercut);
+        if(t[i]-t0>uppercut) rad = t2r(uppercut);
+      } else {
+        rad = rtpointers[i]->radius(t[i]-t0);
+        if(t[i]-t0<lowercut) rad = rtpointers[i]->radius(lowercut);     
+        if(t[i]-t0>uppercut) rad = rtpointers[i]->radius(uppercut);     
+      } 
+  
+      drad = 1.0/sqrt(w[i]) ; 
+      
+      yl = (y[i] -  tana*z[i] - b);
+      if(m_trace) {
+        *m_log << MSG::DEBUG <<"i "<<i<<" "; // ": yi "<<y[i]<<" line y "<<tana*z[i] + b<<" perp "<<yl/sqrt((1+tana*tana))<<" ";
+      }
+      
+      
+      double dth = -(sinus*y[i] + cosin*z[i])*dtheta;
+      double residuals = fabs(yl)/sqrt((1+tana*tana)) - rad;
+      if(m_trace) {
+        *m_log << MSG::DEBUG <<" dth "<<dth<<" dy0 "<<dy0<<" del_t "<<del_t<<" ";
+      }
+      
+      double errorResiduals = sqrt( dth*dth + dy0*dy0 + del_t*del_t);
+      
+      // derivatives of the residual 'R'
+      double deriv[3];
+      // del R/del theta
+      double dd = z[i] * sinus + b *cosin - y[i] * cosin;
+      deriv[0] = sign(dd) * (z[i] * cosin - b * sinus + y[i] * sinus);
+      // del R / del b
+      deriv[1] = sign(dd) * cosin ;
+      // del R / del t0
+      
+      if(use_hardcoded) deriv[2] = -1* t2rprime(t[i]-t0);
+      else deriv[2] = -1* rtpointers[i]->driftvelocity(t[i]-t0);
+      
+      double covsq=0;
+      for(int rr=0; rr<3; rr++) {
+        for(int cc=0; cc<3; cc++) {
+          covsq += deriv[rr]*covar[rr][cc]* deriv[cc];
+        }
+      }
+      if(m_trace) {
+	*m_log << MSG::DEBUG << " covsquared " << covsq << endreq;
+	if( covsq < 0. ){
+	  for(int rr=0; rr<3; rr++) {
+	    for(int cc=0; cc<3; cc++) {
+	      double dot = deriv[rr]*covar[rr][cc]* deriv[cc];
+	      *m_log << MSG::DEBUG << " adding term " << dot << " dev1 " << deriv[rr] << " cov " << covar[rr][cc]
+		     << " dev2 " << deriv[cc] << endreq;
+	    }
+	  }
+	}
+      }
+      covsq = covsq > 0. ? sqrt(covsq) : 0.;
+      const DriftCircle* ds  = & dcs_keep[i];
+      if (m_propagateErrors) drad = dr[i]; 
+      DriftCircle dc_newrad(dcs_keep[i].position(), rad, drad, ds->state(), dcs_keep[i].id(), dcs_keep[i].index(),ds->rot() );
+      DCOnTrack dc_new(dc_newrad, residuals, covsq);
+      dc_new.state(dcs_keep[i].state());
+      
+      if(m_trace) *m_log << MSG::DEBUG  <<"T0 Segment hit res "<<residuals<<" eres "<<errorResiduals<<" covsq "<<covsq<<" ri " << r[i]<<" ro "<<rad<<" drad "<<drad << " sel "<<selection[i]<< " inv error " << w[i] << endreq;
+      
+      if( selection[i] == 0 ) {
+        ++nhits;
+//        chi2 += residuals*residuals*hitwt;
+        if (!m_propagateErrors) {
+          chi2 += residuals*residuals*w[i];
+        } else {
+          chi2 += residuals*residuals/(drad*drad);
+        }
+        if(m_trace) std::cout <<" T0 Segment hit res "<<residuals<<" eres "<<errorResiduals<<" covsq "<<covsq<<" ri " << r[i]<<" radius after t0 "<<rad<<" radius error "<< drad <<  " original error " << dr[i] << std::endl;
+// Put chi2 penalty for drift times outside window
+        if (t[i]-t0> uppercut ) { // too large 
+	  chi2  += (t[i]-t0-uppercut)* (t[i]-t0-uppercut)/10.;
+        }else if (t[i]-t0 < lowercut ) {// too small
+	  chi2 += ((t[i]-t0-lowercut)*(t[i]-t0-lowercut))/10.;
+        }
+      } 
+      m_result.dcs().push_back( dc_new );
+    }
+    
+    double oldshift;
+    oldshift = m_result.t0Shift();
+    if(m_trace) *m_log << MSG::DEBUG <<"end fit old "<<oldshift<< " new " <<t0<< endreq;
+    // Final Minuit Fit result
+    if(nhits==NUMPAR) {
+      nhits++;
+      chi2 += 1.;
+    }
+    m_result.set( chi2, nhits-NUMPAR, dtheta, -1.*dy0 );
+    m_result.line().set( LocPos( Zc - sinus*d, Yc + cosin*d ), ang );
+    if(t0==0.) t0=0.00001;
+    m_result.setT0Shift(t0,t0Err);
+    if(m_trace) std::cout << "Minuit Fit complete: Chi2 " << chi2 << " angle " << m_result.line().phi() << " nhits "<< nhits  << " t0result " << t0 << std::endl;
+    
+    if(m_trace) {
+      *m_log << MSG::DEBUG << "Minuit Fit complete: Chi2 " << chi2 << " angle " << m_result.line().phi() << " nhits "<<nhits<<" numpar "<<NUMPAR << " per dof " << chi2/(nhits-NUMPAR)  << endreq;
+
+      *m_log << MSG::DEBUG << "Fit complete: Chi2 " << chi2 <<" nhits "<<nhits<<" numpar "<<NUMPAR << " per dof " << chi2/(nhits-NUMPAR)  <<endreq;
+      if(chi2/(nhits-NUMPAR) > 5) {
+        *m_log << MSG::DEBUG << "_______NOT GOOD " <<endreq;
+      }
+      *m_log << MSG::DEBUG <<"chi2 "<<chi2<<" per dof "<<chi2/(nhits-NUMPAR)<<" root chisq "<<chisq<< endreq;
+    }
+
+    // Do standard DCSL fit using the t0 updated results 
+    // if minuit MIGRAD failed to converge (and t0 fit converged) 
+//    if (errFlag5!=0&&errFlag4!=0)  {
+//      bool oldrefit =  DCSLFitter::fit( m_result.line() , m_result.dcs(), selection );
+//      int iok = 0;
+//      if(oldrefit) iok = 1;
+//      if(m_trace)*m_log << MSG::DEBUG << " ALARM Minimize fix " << errFlag1 << " ALARM minimize release " << errFlag2 << " ALARM migrad fix 1 " << errFlag3 << " ALARM minimize all free " << errFlag4 << " ALARM migrad all free " << errFlag5 << endreq;
+//      if(m_trace) std::cout << " ALARM Migrad and Minimize failed DCSL Fit Chi2 " << m_result.chi2() << " angle " << m_result.line().phi() << " y0 " << m_result.line().y0() << " nhits "<< selection.size() << " fitretval " << fitretval << " refit ok " << iok  << std::endl;
+//      return  oldrefit;
+//    } 
+    
+      
+    return true;
+  }
+  
+  
+}
diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/src/components/MdtSegmentT0Fitter_entries.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/src/components/MdtSegmentT0Fitter_entries.cxx
new file mode 100755
index 0000000000000..053f166afb717
--- /dev/null
+++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/src/components/MdtSegmentT0Fitter_entries.cxx
@@ -0,0 +1,11 @@
+#include "GaudiKernel/DeclareFactoryEntries.h"
+#include "MdtSegmentT0Fitter/MdtSegmentT0Fitter.h"
+
+using namespace TrkDriftCircleMath;
+
+DECLARE_TOOL_FACTORY(MdtSegmentT0Fitter)
+
+DECLARE_FACTORY_ENTRIES(MdtSegmentT0Fitter) {
+  DECLARE_TOOL(MdtSegmentT0Fitter)
+}
+
diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/src/components/MdtSegmentT0Fitter_load.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/src/components/MdtSegmentT0Fitter_load.cxx
new file mode 100755
index 0000000000000..20f3676db4f80
--- /dev/null
+++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MdtSegmentT0Fitter/src/components/MdtSegmentT0Fitter_load.cxx
@@ -0,0 +1,3 @@
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+LOAD_FACTORY_ENTRIES(MdtSegmentT0Fitter)
-- 
GitLab