diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/CurvedCandidateFinder.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/CurvedCandidateFinder.h
new file mode 100644
index 0000000000000000000000000000000000000000..150b8d574891986b20df89644ed373d969d25792
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/CurvedCandidateFinder.h
@@ -0,0 +1,73 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 13.07.2008, AUTHOR: OLIVER KORTNER
+// Modified: 04.08.2008 by O. Kortner, estimated direction of incidence can be
+//                                     set.
+//           07.08.2008 by O. Kortner, bug fig in the pattern recognition.
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#ifndef MuonCalib_CurvedCandidateFinderH
+#define MuonCalib_CurvedCandidateFinderH
+
+//:::::::::::::::::::::::::::::::::
+//:: CLASS CurvedCandidateFinder ::
+//:::::::::::::::::::::::::::::::::
+
+/// \class CurvedCandidateFinder
+///
+/// This class searches for candidates of curved parabolic lines connecting
+/// all hits given to the class within a user defined search road.
+///
+/// \author Oliver.Kortner@CERN.CH
+///
+/// \date 13.07.2008
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+// STL //
+#include <vector>
+
+// MuonCalib //
+#include "MuonCalibEventBase/MdtCalibHitBase.h"
+#include "MdtCalibFitters/CurvedLine.h"
+
+
+namespace MuonCalib {
+
+class CurvedCandidateFinder {
+
+public:
+// Constructors //
+    CurvedCandidateFinder(const std::vector<const MdtCalibHitBase *> & hits);
+    ///< Constructor
+    ///< @param hits Vector of hits used in the candidate finding.
+
+// Methods //
+    const std::vector<CurvedLine> & getCandidates(const double & road_width);
+                                    ///< get all candidates connecting all hits
+                                    ///< within the given road width (mm)
+    const std::vector<CurvedLine> & getCandidates(const double & road_width,
+									const Amg::Vector3D & est_dir);
+                                    ///< get all candidates connecting all hits
+                                    ///< within the given road width (mm);
+									///< est_dir is the estimated direction of
+									///< incidence
+
+private:
+// hits //
+    std::vector<const MdtCalibHitBase *> m_hits; // vector hits used in the
+                                                 // candidate search
+
+// candidates //
+    std::vector<CurvedLine> m_candidates; // vector of candidate lines
+
+};
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/CurvedLine.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/CurvedLine.h
new file mode 100644
index 0000000000000000000000000000000000000000..9177eead1449407bdef97465d35ee16fb437d4c0
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/CurvedLine.h
@@ -0,0 +1,93 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 05.04.2008, AUTHOR: OLIVER KORTNER
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#ifndef MuonCalib_CurvedLineH
+#define MuonCalib_CurvedLineH
+
+//::::::::::::::::::::::
+//:: CLASS CurvedLine ::
+//::::::::::::::::::::::
+
+/// \class CurvedLine
+///
+/// This class describes a curved line in an MDT chamber. Let x,y,z denote the
+/// local coordinate frame of an MDT chamber. Then the class assumes a
+/// straight line in the xz and a parabolicly curved line in the yz plane.
+///
+/// \author Oliver.Kortner@CERN.CH
+///
+/// \date 05.04.2008
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+// STL //
+#include <vector>
+
+// CLHEP //
+#include "MdtCalibFitters/MTStraightLine.h"
+
+// MuonCalib //
+#include "MuonCalibMath/Legendre_polynomial.h"
+#include "GeoPrimitives/GeoPrimitives.h"
+#include "EventPrimitives/EventPrimitives.h"
+
+namespace MuonCalib {
+
+class CurvedLine {
+
+public:
+// Constructors //
+    CurvedLine(void);
+    ///< Default constructor: a straight line through (0,0,0) pointing in
+    ///< in the local x direction of the chambers is created.
+
+    CurvedLine(std::vector<Amg::Vector3D> & points);
+    ///< Constructor.
+    ///< \param points A straight line in the xz and a parabolic line in the
+    ///<               yz plane is fitter through the given points.
+    ///<  All points get equal weight.
+
+    CurvedLine(std::vector<Amg::Vector3D> & points,
+                                std::vector<Amg::Vector3D> & x_and_y_errors);
+    ///< Constructor.
+    ///< \param points A straight line in the xz and a parabolic line in the
+    ///<               yz plane is fitter through the given points.
+    ///< \param x_and_y_errors Errors of the x and y coordinates of the given
+    ///<               points
+
+// Methods //
+// get-methods //
+    Amg::Vector3D getPointOnLine(const double & loc_z) const;
+                                    ///< get the point on the line a the local
+                                    ///< z coordinate "loc_z"
+
+    MTStraightLine getTangent(const double & loc_z) const;
+                                    ///< get the tangent to the line a the local
+                                    ///< z coordinate "loc_z"
+
+private:
+// parameters of the curved line //
+    Legendre_polynomial *m_Legendre; // pointer to the Legendre polynomial
+                                     // describing the curved line
+    Amg::VectorX m_coeff_xz; // coefficients of the straight line in the local
+                          // xz plane
+    Amg::VectorX m_coeff_yz; // coefficients of the curved line in the local
+                          // yz plane
+
+// private methods //
+    void init(std::vector<Amg::Vector3D> & points,
+                                std::vector<Amg::Vector3D> & x_and_y_errors);
+                                // initialization routine
+
+};
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/CurvedPatRec.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/CurvedPatRec.h
new file mode 100644
index 0000000000000000000000000000000000000000..3f0b056d6db78445d6cbbe8e68270025b14444b3
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/CurvedPatRec.h
@@ -0,0 +1,172 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 05.04.2008, AUTHOR: OLIVER KORTNER
+// Modified: 25.07.2008 by O. Kortner, improved pattern recognition by using
+//                                     the class "CurvedCandidateFinder".
+//           04.08.2008 by O. Kortner, further improvements of the pattern
+//                                     recognition for large incidence angles.
+//           07.08.2008 by O. Kortner, bug fig in the pattern recognition.
+//           18.08.2008 by O. Kortner, update of chi^2 and segment position
+//                                     and direction added.
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#ifndef MuonCalib_CurvedPatRecH
+#define MuonCalib_CurvedPatRecH
+
+//::::::::::::::::::::::::
+//:: CLASS CurvedPatRec ::
+//::::::::::::::::::::::::
+
+/// \class CurvedPatRec
+///
+/// This class searches for the best hit combination for a parabolic curved
+/// segment fit and fits a parabola in the precision plane to the hits found 
+/// before. The algorithm overwrites the segment position nor the
+/// segment direction as well as the chi^2 in the latest versions.
+///
+/// \author Oliver.Kortner@CERN.CH
+///
+/// \date 18.08.2008
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+#include "GeoPrimitives/GeoPrimitives.h"
+
+// STL //
+#include <vector>
+
+// MuonCalib //
+#include "MdtCalibInterfaces/IMdtPatRecFitter.h"
+#include "MuonCalibEventBase/MuonCalibSegment.h"
+#include "MdtCalibFitters/MTStraightLine.h"
+#include "MdtCalibFitters/StraightPatRec.h"
+#include "MdtCalibFitters/CurvedLine.h"
+
+
+namespace MuonCalib {
+
+class CurvedPatRec : public IMdtPatRecFitter {
+
+public:
+// Constructors //
+    CurvedPatRec(void);
+    ///< Default constructor: road width of 0.5 mm is used.
+
+    CurvedPatRec(const double & road_width);
+    ///< Constructor: user defined road width [mm] for pattern recognition.
+
+// Methods //
+    double roadWidth(void) const;
+                                    ///< get the road width used in the 
+	                                ///< pattern recognition [mm]
+    unsigned int numberOfTrackHits(void) const;
+	                                ///< get the number of track hits in the
+	                                ///< final track,
+	                                ///< the method returns 0, if no track 
+	                                ///< has been reconstructed
+	const std::vector<const MdtCalibHitBase*> & trackHits(void) const;
+	                                ///< get a vector with a pointer to the
+	                                ///< hits used in the track
+	                                ///< reconstruction
+	double chi2(void) const;
+	                                ///< get the chi^2 of the final track,
+	                                ///< the method returns -1, if no track
+	                                ///< has been reconstructed
+	double chi2PerDegreesOfFreedom(void) const;
+	                                ///< get the chi^2 per degrees of
+	                                ///< freedom for the final track,
+	                                ///< the method returns -1, if no track
+	                                ///< has been reconstructed
+    const CurvedLine & curvedTrack(void) const;
+                                    ///< get the reconstructed curved track
+
+// set-method //
+	void setRoadWidth(const double & r_road_width);
+	                                ///< set the road width [mm] for the pattern
+	                                ///< recognition = r_road_width
+	void setTimeOut(const double & time_out);
+					///< set the time-out for the track
+					///< finding to time_out (in seconds)
+
+// methods required by the base class "IMdtSegmentFitter" //
+	bool fit(MuonCalibSegment & r_segment) const;
+	                                ///< reconstruction of the track using
+	                                ///< all hits in the segment
+	                                ///< "r_segment", returns true in case
+	                                ///< of success;
+	                                ///< the algorithm overwrites
+	                                ///< the track radii, the track
+	                                ///< position, track direction, and
+	                                ///< chi^2 per degrees of freedom;
+	                                ///< warning: the errors of the track
+	                                ///< radii are only approximate
+	bool fit(MuonCalibSegment & r_segment, HitSelection r_selection) const;
+	                                ///< reconstruction of the track using 
+                                    ///< only those hits in r_segment for
+	                                ///< which the r_selection[.] is 0,
+	                                ///< return true in case of success;
+	                                ///< the algorithm overwrites
+	                                ///< the track position, direction,
+                                    ///< and the chi^2 in r_segment; it
+	                                ///< updates the distances of all hits
+	                                ///< from the track, i.e. also of those
+	                                ///< hits which were rejected from the
+	                                ///< track reconstruction;
+	                                ///< warning: the errors of the track
+	                                ///< radii are only approximate
+	void printLevel(int level);
+	                                ///< set the print level, this call
+	                                ///< has no effect
+
+private:
+// internal co-ordinate definition //
+//	                    x3 
+//	                    ^
+//	   o o o o o o      |
+//	... o o o o o ...   o--> x2
+//	   o o o o o o     x1
+//
+
+// settings //
+    double m_road_width; // road width to be used in pattern finding
+    double m_time_out; // time out for pattern recognition.
+
+// straight pattern recognition to get the approximate incidence angle //
+	mutable StraightPatRec m_sfitter;
+
+// final track parameters //
+	mutable std::vector<const MdtCalibHitBase*> m_track_hits;
+	                                // pointer to hits used by the final
+	                                // track
+    mutable double m_chi2; // chi^2 of the final track
+    mutable CurvedLine m_curved_track; // curved trajectory
+
+// auxiliary methods //
+    Amg::Vector3D getHitPoint(const MdtCalibHitBase * hit,
+                                const MTStraightLine & straight_track) const;
+                                // transform the given hit into a hit point in
+                                // 3 dimensions using the given straight line
+                                // as helper
+    std::vector<Amg::Vector3D> getHitPoints(
+                                std::vector<const MdtCalibHitBase*> track_hits,
+                                const MTStraightLine & straight_track) const;
+                                // transform the track hits into hit points in
+                                // 3 dimensions using the given straight line
+                                // as helper
+    std::vector<Amg::Vector3D> getHitPoints(
+                                std::vector<const MdtCalibHitBase*> track_hits,
+                                const CurvedLine & curved_track) const;
+                                // transform the track hits into hit points in
+                                // 3 dimensions using the given curved line
+                                // as helper
+
+};
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/DCSLFitter.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/DCSLFitter.h
new file mode 100644
index 0000000000000000000000000000000000000000..fc38a64e70c786a6fbfe800507e7da62c3950fbf
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/DCSLFitter.h
@@ -0,0 +1,63 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// DCSLFitter.h
+//   Header file for class DCSLFitter
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// nveldik@nikhef.nl
+///////////////////////////////////////////////////////////////////
+
+#ifndef MUONCALIB_DCSLFITTER_H
+#define MUONCALIB_DCSLFITTER_H
+
+#include "MdtCalibInterfaces/IMdtSegmentFitter.h"
+
+#include "MuonCalibEventBase/MuonCalibSegment.h"
+#include "GeoPrimitives/GeoPrimitives.h"
+
+namespace MuonCalib {
+/**@class DCSLFitter
+   Straight line fitter for drift circles
+   
+   @author Niels.Van.Eldik@cern.ch
+*/
+    
+
+  class DCSLFitter : public IMdtSegmentFitter {
+  public:
+    DCSLFitter() : m_debug(false), m_error_dy0(0.0), m_error_dtheta(0.0) {}
+  
+    /** fit using all hits */
+    bool fit( MuonCalibSegment& seg ) const;
+
+    /** fit subset of the hits.
+	If the HitSelection vector contains a 0 for a given hit the hit is used
+	else the hit is not included in the fit.
+	The size of the HitSelection vector should be equal to the number of hits on track else
+	no fit is performed.
+    */
+    bool fit( MuonCalibSegment& seg, HitSelection selection ) const;
+//    double error_dy0() { return m_error_dy0;} 
+//    double error_dtheta() { return m_error_dtheta;} 
+
+    /** set print level */
+    void printLevel(int level);
+  private:
+  
+    bool m_debug;
+    
+    mutable double m_error_dy0;
+    mutable double m_error_dtheta;
+
+    double getY( const Amg::Vector3D& p ) const { return p.z(); }
+    double getZ( const Amg::Vector3D& p ) const { return p.y(); }
+    Amg::Vector3D getVec( double x, double y, double z) const { return Amg::Vector3D( x, z, y ); }
+  };
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/IndexSet.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/IndexSet.h
new file mode 100644
index 0000000000000000000000000000000000000000..4c4bf6f7aed19ae776a05068355f69d8ae57eb26
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/IndexSet.h
@@ -0,0 +1,104 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 09.05.2005, AUTHOR: OLIVER KORTNER
+// Modified: 16.07.2006 by O. Kortner, vector size check in initialization
+//                      added,
+//                      != operator corrected.
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#ifndef IndexSetHXX
+#define IndexSetHXX
+
+//::::::::::::::::::::
+//:: CLASS IndexSet ::
+//::::::::::::::::::::
+
+/// \class IndexSet
+/// This class allows the user to save a set of indices and to compare two sets
+/// of indices. IndexSet is an auxiliary class for 
+/// QuasianalyticLineReconstruction.
+///
+/// \author Oliver.Kortner@CERN.CH
+///
+/// \date 09.05.2005
+
+//////////////////
+// HEADER FILES //
+//////////////////
+
+// standard C++ libraries //
+#include <iostream>
+
+// STEL //
+#include <vector>
+
+namespace MuonCalib {
+
+class IndexSet {
+
+private:
+// internal index memory //
+	unsigned int m_nb_indices; // number of indices
+	std::vector<int> m_index; // indices
+
+// initialization methods //
+	void m_init(void);
+	  // default initiailization method; the number of indices is set to 0
+	void m_init(const unsigned int & r_nb_indices);
+	  // initialization method; the number of indices is set to r_nb_indices
+	void m_init(const unsigned int & r_nb_indices,
+					const std::vector<int> r_index);
+	  // initialization method; the number of indices is set to 
+	  // r_nb_indices, the vector r_index contains the indices
+
+public:
+// Constructors //
+	IndexSet(void) {
+		m_init();
+		}
+	///< default constructor: the number of indices is set to 0
+
+	IndexSet(const unsigned int & r_nb_indices) {
+		m_init(r_nb_indices);
+		}
+	///< constructor: the number of indices is set to r_nb_indices
+
+	IndexSet(const unsigned int & r_nb_indices,
+					const std::vector<int> r_index) {
+		m_init(r_nb_indices, r_index);
+		}
+	///< constructor: the number of indices is set to r_nb_indices,
+	///<              the vector r_index contains the indices
+
+// Methods //
+	unsigned int size(void) const;
+	                                ///< get the number of indices
+	void resize(const unsigned int & r_size);
+	                                ///< resize the index set to r_size; 
+	                                ///< the index store is preserved as
+	                                ///< far as possible
+	int operator [] (const unsigned int & r_k);
+	int operator [] (const unsigned int & r_k) const;
+	                                ///< access to the indices stored in 
+	                                ///< the class,
+	                                ///< 0 <= r_k < size();
+	                                ///< WARNING: no test on the index is 
+	                                ///< performed
+	void sort(void);
+	                                ///< sort the indices in ascending order
+	bool operator == (const IndexSet & r_index_set) const;
+	bool operator != (const IndexSet & r_index_set) const;
+	                                ///< comparison of two index sets;
+	                                ///< two index sets are considered 
+	                                ///< equal if they are of the same size
+	                                ///< and their indices are the same at 
+	                                ///< the same position [.]
+
+};
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/LocalSegmentResolver.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/LocalSegmentResolver.h
new file mode 100644
index 0000000000000000000000000000000000000000..cff59fbf4a584f91f583d2353cd45e2a4b58d7b4
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/LocalSegmentResolver.h
@@ -0,0 +1,59 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// LocalSegmentResolver.h
+//   Header file for class MdtSegment
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// nveldik@nikhef.nl
+///////////////////////////////////////////////////////////////////
+
+#ifndef MUONCALIB_LOCALSEGMENTRESOLVER_H
+#define MUONCALIB_LOCALSEGMENTRESOLVER_H
+
+
+// stl includes
+#include <vector>
+
+#include "MuonCalibEventBase/MuonCalibSegment.h"
+#include "GeoPrimitives/GeoPrimitives.h"
+
+class MdtCalibHitBase;
+
+namespace MuonCalib {
+
+/**@class LocalSegmentResolver
+   Class calculates the local position and direction of the segment using the hits on track.
+
+   @author Niels.Van.Eldik@cern.ch
+*/
+
+  class LocalSegmentResolver {
+  public:
+    /** constructor */
+    LocalSegmentResolver();
+
+    /** resolve local position and direction of the track segment */
+    bool resolve(MuonCalibSegment* seg) const;
+
+    /** set print level */
+    void setPrintLevel(int level) { m_printLevel = level; }
+
+  private:
+    typedef MuonCalibSegment::MdtHitVec HitVec;
+    typedef std::pair<Amg::Vector3D,Amg::Vector3D > Line;
+    typedef std::vector<Line>                 LineVec;
+  private:
+    LineVec getLines( const MdtCalibHitBase& firstHit, const MdtCalibHitBase& lastHit ) const;
+
+    int bestLine( const HitVec& hits, const LineVec& localTracks ) const;
+  
+    /** print level */
+    int m_printLevel;
+  };
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/LocalToPrecision.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/LocalToPrecision.h
new file mode 100644
index 0000000000000000000000000000000000000000..f64660c461bc7ff9e19bffcf24682ade10e31100
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/LocalToPrecision.h
@@ -0,0 +1,22 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef MUONCALIB_LOCALTOPRECISION_H
+#define MUONCALIB_LOCALTOPRECISION_H
+
+#include "GeoPrimitives/GeoPrimitives.h"
+
+namespace MuonCalib {
+
+  /** Provides transformation between local and presicion reference frames*/
+  class LocalToPrecision {
+  public:
+    static Amg::Vector3D precision( const Amg::Vector3D& p ) { return Amg::Vector3D( p.y(), p.z(), p.x() ); }
+    static Amg::Vector3D local( const Amg::Vector3D& p ) { return Amg::Vector3D( p.z(), p.x(), p.y() ); }
+    
+  };
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/MTStraightLine.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/MTStraightLine.h
new file mode 100644
index 0000000000000000000000000000000000000000..ec2b3dc00518e8046183ecf3666d634e4cac05dc
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/MTStraightLine.h
@@ -0,0 +1,168 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 01.03.2006, AUTHORS: OLIVER KORTNER, FELIX RAUSCHER
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//::::::::::::::::::::::::::
+//:: CLASS MtStraightLine ::
+//::::::::::::::::::::::::::
+#include "GeoPrimitives/GeoPrimitives.h"
+
+namespace MuonCalib {
+/// \class MtStraightLine
+/// This class contains a simple implementation of a straifht line with errors
+/// on the slope and the intercept of the straight line.
+///
+/// \author Oliver.Kortner@CERN.CH \author Felix.Rauscher@CERN.CH
+///
+/// \date 01.03.2006
+}
+
+#ifndef MTStraightLineH
+#define MTStraightLineH
+
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+// CLHEP //
+//#include "CLHEP/config/CLHEP.h"
+//#include "CLHEP/Units/SystemOfUnits.h"
+//#include "CLHEP/Units/PhysicalConstants.h"
+
+namespace MuonCalib {
+
+class MTStraightLine {
+
+public:
+// Constructors //
+	MTStraightLine(void) {
+		m_init();
+		}	
+	///< Default constructor: all internal parameters of the straight line
+	///< are set to 0.
+
+	MTStraightLine(const Amg::Vector3D & r_position,
+                                const Amg::Vector3D & r_direction,
+                                const Amg::Vector3D & r_position_error,
+                                const Amg::Vector3D & r_direction_error) {
+		m_init(r_position, r_direction,
+                                r_position_error, r_direction_error);
+		}
+	///< Constructor:
+	///< r_position: position vector of the straight line;
+	///< r_direction: direction vector of the straight line;
+	///< r_position_error: error on the position vector;
+ 	///< r_direction_error: error on the direction vector.
+
+	MTStraightLine(const double & r_m_x1, const double & r_b_x1,
+		const double & r_m_x2, const double & r_b_x2,
+		const double & r_m_x1_err, const double & r_b_x1_err,
+		const double & r_m_x2_err, const double & r_b_x2_err) {
+		m_init(r_m_x1, r_b_x1, r_m_x2, r_b_x2,
+			r_m_x1_err, r_b_x1_err, r_m_x2_err, r_b_x2_err);
+		}
+	///< Coordinates: x1, x2, x3.
+	///< Parametrization of the straight line: x1 = r_m_x1*x3 + r_b_x1;
+	///<                                       x2 = r_m_x2*x3 + r_b_x2;
+	///<                                       x3 arbitrary.
+	///< r_m_x1_err: error on r_m_x1.
+	///< r_b_x1_err: error on r_b_x1.
+	///< r_m_x2_err: error on r_m_x2.
+	///< r_b_x2_err: error on r_b_x2.
+
+// Methods //
+// get-methods //
+	Amg::Vector3D positionVector(void) const;
+	                                ///< get the position vector of the
+                                        ///< straight line
+	Amg::Vector3D directionVector(void) const;
+	                                ///< get the direction vector of the
+	                                ///< straight line
+	Amg::Vector3D positionError(void) const;
+	                                ///< get the error on the position 
+                                        ///< vector of the straight line
+	Amg::Vector3D directionError(void) const;
+	                                ///< get the error on the direction 
+	                                ///< vector of the straight line
+ 	double m_x1(void) const;
+	                                ///< get the slope of the straight line 
+                                        ///< in the x1-x3 plane
+	double m_x1_error(void) const;
+	                                ///< get the error on the slope of the 
+	                                ///< straight line in the x1-x3 plane
+	double b_x1(void) const;
+	                                ///< get the intercept of the straight 
+	                                ///< line in the x1-x3 plane
+	double b_x1_error(void) const;
+	                                ///< get the error on the intercept of 
+	                                ///< the straight line in the x1-x3
+                                        ///< plane
+	double m_x2(void) const;
+	                                ///< get the slope of the straight line
+	                                ///< in the x2-x3 plane
+	double m_x2_error(void) const;
+	                                ///< get the error on the slope of the 
+	                                ///< straight line in the x2-x3 plane
+	double b_x2(void) const;
+	                                ///< get the intercept of the straight 
+	                                ///< line in the x2-x3 plane
+	double b_x2_error(void) const;
+	                                ///< get the slope of the intercept of
+                                        ///< the straight line in the x2-x3
+                                        ///< plane
+	Amg::Vector3D pointOnLine(const double & lambda) const;
+	                                ///< get the point on the line for the 
+                                        ///< given scale factor lambda,
+	                                ///< point=position_vector+lambda*direction_vector
+	double signDistFrom(const MTStraightLine & h) const;
+	                                ///< get the signed distance of two
+                                        ///< lines
+                                        ///< (if both are parallel, dist>0)
+	double distFromLine(const Amg::Vector3D & point) const;
+	                                ///< get the distance of point point
+                                        ///< from straight line
+
+private:
+// internal representation of the straight line //
+	Amg::Vector3D m_position; //position vector of the straight line
+	Amg::Vector3D m_direction; //direction vector of the straight line
+
+// errors on the position and direction vector //
+	Amg::Vector3D m_position_error; //error on the position vector
+	Amg::Vector3D m_direction_error; //error on the direction vector
+
+// initializtion methods //
+	void m_init(void); //default initialization method
+
+	void m_init(const Amg::Vector3D & r_position,
+				const Amg::Vector3D & r_direction,
+				const Amg::Vector3D & r_position_error,
+				const Amg::Vector3D & r_direction_error);
+	                  // r_position: position vector of the straight line;
+	                  // r_direction: direction vector of the straight line;
+	                  // r_position_error: error on the position vector;
+ 	                  // r_direction_error: error on the direction vector
+
+	void m_init(const double & r_m_x1, const double & r_b_x1,
+		const double & r_m_x2, const double & r_b_x2,
+		const double & r_m_x1_err, const double & r_b_x1_err,
+		const double & r_m_x2_err, const double & r_b_x2_err);
+	       // Coordinates: x1, x2, x3.
+	       // Parametrization of the straight line: x1 = r_m_x1*x3 + r_b_x1;
+	       //                                       x2 = r_m_x2*x3 + r_b_x2;
+	       //                                       x3 arbitrary.
+	       // r_m_x1_err: error on r_m_x1.
+	       // r_b_x1_err: error on r_b_x1.
+	       // r_m_x2_err: error on r_m_x2.
+	       // r_b_x2_err: error on r_b_x2.
+
+};
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/MuCCaFitter.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/MuCCaFitter.h
new file mode 100644
index 0000000000000000000000000000000000000000..67431848c8e988baf7a8f745608f8bab3d20426c
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/MuCCaFitter.h
@@ -0,0 +1,112 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// MuCCaFitter.h
+//   Header file for class MuCCaFitter
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// 
+///////////////////////////////////////////////////////////////////
+
+#ifndef MuCCaFITTER_H
+#define MuCCaFITTER_H
+
+#include "MdtCalibInterfaces/IMdtSegmentFitter.h"
+
+#include "MuonCalibEventBase/MuonCalibSegment.h"
+
+#include <vector>
+
+    
+namespace MuonCalib {
+
+/**@class MuCCaFitter
+   Interface to the straight line fitter for drift circles used by Calib 
+   
+   @author Fabrizio.Petrucci@cern.ch
+*/
+class MuCCaFitter : public IMdtSegmentFitter {
+ public:
+  /** fit using all hits */
+  bool fit( MuonCalibSegment& seg ) const;
+
+  /** fit subset of the hits.
+      If the HitSelection vector contains a 0 for a given hit the hit is used
+      else the hit is not included in the fit.
+      The size of the HitSelection vector should be equal to the number of hits on track else
+      no fit is performed.
+  */
+  bool fit( MuonCalibSegment& seg, HitSelection selection ) const;
+
+  /** set print level */
+  void printLevel(int level);
+
+ private:
+
+ bool m_debug;
+
+ /** these methods are needed to change the reference frame between the
+     local one of the hit and one used by the fitter: apparently the 2 frames 
+     are the same ... TO BE CHECKED!!!
+ */   
+ //  double getY( const Amg::Vector3D& p ) const { return p.y(); }
+ //  double getX( const Amg::Vector3D& p ) const { return p.x(); }
+ //  double getZ( const Amg::Vector3D& p ) const { return p.z(); }
+ //  Amg::Vector3D getVec( double x, double y, double z) const { return Amg::Vector3D( x, y, z ); }
+ double getY( const Amg::Vector3D& p ) const { return p.z(); }
+ double getX( const Amg::Vector3D& p ) const { return p.x(); }
+ double getZ( const Amg::Vector3D& p ) const { return p.y(); }
+  Amg::Vector3D getVec( double x, double y, double z) const { return Amg::Vector3D( x, z, y ); }
+};
+
+/**@class MuCCaFitterImplementation
+   The straight line fitter for drift circles used by Calib 
+   
+   @author Fabrizio.Petrucci@cern.ch, Paolo.Branchini@cern.ch 
+*/
+class MuCCaFitterImplementation{
+ public:
+  void Computelin(double x1, double y1, double r1,  
+                  double x2, double y2, double r2);
+  void Computelinparnew(double x1, double y1, double r1, 
+                        double x2, double y2, double r2);
+  void computehitsfromcircles(double x0,double y0,double r0,
+                              double x1,double y1,double r1,double a,double b);
+  //  void Computehitpsemes(int nhit,double *xcirc, double *ycirc,
+  //                        double *rcirc, double a, double b);
+  void Computehitpsemes(int nhit,std::vector<double> xcirc, std::vector<double> ycirc, std::vector<double>rcirc, double a, double b);
+  //  void Computeparam3(int number_of_hits,double x[100],double y[100],
+  //                     double r[100],double sr[100]);
+  void Computeparam3(int number_of_hits,std::vector<double> x,std::vector<double> y,std::vector<double> r,std::vector<double> sr);
+  double get_a();
+  double get_b();
+  double get_da();
+  double get_db();
+  double get_corrab();
+  double get_chi2f();
+ private:
+  /** parameters of the 4 tangent lines from first and last hit */
+  double m_angularcoefficient[4];  
+  double m_bfpar[4]; 
+  /** track points from 2 circles */
+  double m_xout0; 
+  double m_yout0;
+  double m_xout1;
+  double m_yout1;
+  /** track points */
+  double m_xpoint[100]; 
+  double m_ypoint[100]; 
+  /** results */
+  double m_aoutn; //!< track slope 
+  double m_sig2a; //!< track slope's variance 
+  double m_bout;  //!< track constant term 
+  double m_sig2b; //!< error on track constant term 
+  double m_corrab;//!< correlation term
+  double m_chi2f; //!< chisquared
+};
+
+}
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/QuasianalyticLineReconstruction.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/QuasianalyticLineReconstruction.h
new file mode 100644
index 0000000000000000000000000000000000000000..02e1841ccca53cbf40b1b3576f8c8cdbf9ac6b15
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/QuasianalyticLineReconstruction.h
@@ -0,0 +1,233 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 01.03.2006, AUTHOR: OLIVER KORTNER
+// Modified: 15.07.2006 by O. Kortner, error calculation corrected,
+//                                     chi^2 refit functionality added.
+//           13.01.2007 by O. Kortner, bug fix in candidate treatment, some
+//                                     candidates were considered to be
+//                                     identical although different;
+//                                     modifications to improve the
+//                                     reconstruction efficiency at very high
+//                                     background count rates.
+//           27.03.2007 by O. Kortner, distances with signs filled into
+//                                     MuonCalibSegment.
+//           23.03.2007 by O. Kortner, isnan check for chi^2.
+//           08.06.2007 by O. Kortner, final track segment has rphi position and
+//                                     direction of the initial segment.
+//           23.06.2006 by O. Kortner, add convention for rphi track if the
+//                                     pattern recognition has failed to
+//                                     provide it.
+//           26.11.2007 by O. Kortner, fix for segment refinement.
+//           13.12.2007 by O. Kortner, time-out added.
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#ifndef QuasianalyticLineReconstructionH
+#define QuasianalyticLineReconstructionH
+
+//:::::::::::::::::::::::::::::::::::::::::::
+//:: CLASS QuasianalyticLineReconstruction ::
+//:::::::::::::::::::::::::::::::::::::::::::
+
+/// \class QuasianalyticLineReconstruction
+/// This class performs the reconstruction of straight line in MDT chambers by
+/// calculating tangents to all pairs of two tubes on a straight-line track and
+/// averaging over the calculated tangents to get the parameters of the
+/// straight-line track. The class redoes the pattern recognition using the
+/// hits provided to it. The hits which were used in the track fit can be
+/// retrieved from the class. A refit of the result of the quasianalytic
+/// reconstruction with the DCSLFitter can requested.
+/// The user can set a time-out for the track finding. It is set to 10 seconds
+/// by default.
+///
+/// \author Oliver.Kortner@CERN.CH
+///
+/// \date 01.03.2006, 16.07.2006, 13.12.2007
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+// CLHEP //
+//#include "CLHEP/config/CLHEP.h"
+
+// STL //
+#include <vector>
+
+// MuonCalib //
+#include "MdtCalibInterfaces/IMdtPatRecFitter.h"
+#include "MuonCalibEventBase/MuonCalibSegment.h"
+#include "MdtCalibFitters/MTStraightLine.h"
+#include "MdtCalibFitters/IndexSet.h"
+#include "MdtCalibFitters/DCSLFitter.h"
+
+
+namespace MuonCalib {
+
+class QuasianalyticLineReconstruction : public IMdtPatRecFitter {
+
+public:
+// Constructors //
+	QuasianalyticLineReconstruction(void) {
+		m_init();
+		}
+	///< Default constructor: road width for pattern recognition = 0.5 mm.
+
+	QuasianalyticLineReconstruction(const double & r_road_width) {
+		m_init(r_road_width);
+		}
+	///< Constructor: user-defined road width for pattern recognition.
+
+// Methods //
+// get-methods //
+	double roadWidth(void) const;
+	                                ///< get the road width used in the 
+	                                ///< pattern recognition
+	unsigned int numberOfTrackHits(void) const;
+	                                ///< get the number of track hits in the
+	                                ///< final track,
+	                                ///< the method returns 0, if no track 
+	                                ///< has been reconstructed
+	const std::vector<const MdtCalibHitBase*> & trackHits(void) const;
+	                                ///< get a vector with a pointer to the
+	                                ///< hits used in the track
+	                                ///< reconstruction
+	double chi2(void) const;
+	                                ///< get the chi^2 of the final track,
+	                                ///< the method returns -1, if no track
+	                                ///< has been reconstructed
+	double chi2PerDegreesOfFreedom(void) const;
+	                                ///< get the chi^2 per degrees of
+	                                ///< freedom for the final track,
+	                                ///< the method returns -1, if no track
+	                                ///< has been reconstructed
+	MTStraightLine track(void) const;
+	                                ///< get the final track in the local
+					///< co-ordinate frame, i.e.
+					///<                      z 
+					///<                      ^
+					///<     o o o o o o      |
+					///<  ... o o o o o ...   o--> y
+					///<     o o o o o o     x
+
+// set-method //
+	void setRoadWidth(const double & r_road_width);
+	                                ///< set the road width for the pattern
+	                                ///< recognition = r_road_width
+	void setTimeOut(const double & time_out);
+					///< set the time-out for the track
+					///< finding to time_out (in seconds)
+// methods required by the base class "IMdtSegmentFitter" //
+	bool fit(MuonCalibSegment & r_segment) const;
+	                                ///< reconstruction of the track using
+	                                ///< all hits in the segment
+	                                ///< "r_segment", returns true in case
+	                                ///< of success;
+	                                ///< the algorithm overwrites
+	                                ///< the track radii, the track
+	                                ///< position, track direction, and
+	                                ///< chi^2 per degrees of freedom;
+	                                ///< warning: the errors of the track
+	                                ///< radii are only approximate
+	bool fit(MuonCalibSegment & r_segment, HitSelection r_selection) const;
+	                                ///< reconstruction of the track using 
+					///< only those hits in r_segment for
+	                                ///< which the r_selection[.] is 0,
+	                                ///< return true in case of success;
+	                                ///< the algorithm overwrites
+	                                ///< the track position, direction,
+					///< and the chi^2 in r_segment; it
+	                                ///< updates the distances of all hits
+	                                ///< from the track, i.e. also of those
+	                                ///< hits which were rejected from the
+	                                ///< track reconstruction;
+	                                ///< warning : the errors of the track
+	                                ///< radii are only approximate
+	void printLevel(int level);
+	                                ///< set the print level, this call
+					///< has no effect
+
+private:
+// internal co-ordinate definition //
+//	                    x3 
+//	                    ^
+//	   o o o o o o      |
+//	... o o o o o ...   o--> x2
+//	   o o o o o o     x1
+//
+
+// final track parameters //
+	mutable std::vector<const MdtCalibHitBase*> m_track_hits;
+	                                // pointer to hits used by the final
+	                                // track
+	mutable int m_nb_track_hits; // number of track hits in the final 
+	                                // track
+	mutable double m_chi2; // chi^2 of the final track
+	double m_m_x1, m_b_x1; // slope and intercept in the x1-x3 plane
+	double m_m_x2, m_b_x2; // slope and intercept in the x2-x3 plane
+	double m_m_x1_err, m_b_x1_err; // errors on m_x1 and b_x1
+	double m_m_x2_err, m_b_x2_err; // errors on m_x2 and b_x2
+	mutable MTStraightLine m_track; // final track
+
+// parameters for the adjustment of the track reconstruction //
+	double m_r_max; // maximum radius
+	double m_road_width; // road width for pattern recognition
+	double m_time_out; // time-out for track finding
+
+// chi^2 refitter //
+	DCSLFitter m_nfitter; // NIKHEF straight line reconstruction
+
+// internal storage vectors //
+	std::vector<MTStraightLine> m_tangent;
+	                                    // vector of tangents (for 1 track)
+	std::vector<int> m_nb_cand_hits; // number of hits on track candidate
+	std::vector<MTStraightLine> m_candidate; // track candidates
+
+// initialization methods //
+	void m_init(void);
+	                        // default initialization:  road width = 0.5 CLHEP::mm
+	void m_init(const double & r_road_width);
+	                        // initialization with user-defined road width
+
+// auxiliary methods //
+	MTStraightLine tangent(const Amg::Vector3D & r_w1,
+	        const double & r_r1, const double & r_sigma12,
+	        const Amg::Vector3D & r_w2, const double & r_r2,
+	        const double & r_sigma22, const int & r_case) const;
+	      // method for the calculation of tangents with errors;
+	      // r_w1: wire position for the first hit,
+	      // r_r1: drift radius of the first hit,
+	      // r_sigma12: sigma(r_r1)^2,
+	      // r_w2: wire position for the second hit,
+	      // r_r2: drift radius of the second hit,
+	      // r_sigma22: sigma(r_r2)^2,
+	      // r_case = 1, 2, 3, 4: select one of the four cases of a tangent
+
+	MTStraightLine m_track_candidate(
+				const IndexSet & r_index_set,
+				const int & r_k_cand,
+				const int & r_l_cand,
+				const int & r_cand_case,
+				std::vector<Amg::Vector3D> r_w,
+				std::vector<double> r_r,
+				std::vector<double> r_sigma2,
+				double & r_chi2) const;
+	 // method for the calculatation of a straight line from tangents;
+	 // r_nb_selected_hits: number of selected hits,
+	 // r_k_cand: index of the 1st wire of the candidate tangent
+	 //           (starting from 0),
+	 // r_l_cand: index of the 2nd wire of the candidate tangent
+	 //           (starting from 0),
+	 // r_cand_case: configuration of the tangent to be used (1, 2, 3, or 4)
+	 // r_w: wire positions,
+	 // r_r: drift radii,
+	 // r_sigma2: sigma(r)^2,
+	 // r_chi2: chi^2 for the reconstructed track
+
+};
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/StraightPatRec.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/StraightPatRec.h
new file mode 100644
index 0000000000000000000000000000000000000000..9309b2460d4a1fc239628f55c1378ec7c8d55dec
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/MdtCalibFitters/StraightPatRec.h
@@ -0,0 +1,207 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 27.10.2007, AUTHOR: OLIVER KORTNER
+// Modified: 26.11.2007 by O. Kortner, fix for segment refinement.
+//           13.12.2007 by O. Kortner, time-out added.
+//           07.08.2008 by O. Kortner, bug fix when hits are disabled.
+//				 19.11.2008 by I. Potrap: 1) several bugs have been fixed;
+//												  2) external fitter(DCLS) replaced by
+//													  internal code of linear-least-chi2-fit
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#ifndef StraightPatRecH
+#define StraightPatRecH
+
+//::::::::::::::::::::::::::
+//:: CLASS StraightPatRec ::
+//::::::::::::::::::::::::::
+
+/// \class StraightPatRec
+/// This class searches for the best hit pattern to be fitted with the
+/// DCSLFitter.
+/// The user can set a time-out for the track finding. It is set to 10 seconds
+/// by default.
+///
+/// \author Oliver.Kortner@CERN.CH
+///
+/// \date 27.10.2007, 13.12.2007
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+// CLHEP //
+//#include "CLHEP/config/CLHEP.h"
+//#include "CLHEP/Units/SystemOfUnits.h"
+//#include "CLHEP/Units/PhysicalConstants.h"
+#include "GeoPrimitives/GeoPrimitives.h"
+
+// STL //
+#include <vector>
+
+// MuonCalib //
+#include "MdtCalibInterfaces/IMdtPatRecFitter.h"
+#include "MuonCalibEventBase/MuonCalibSegment.h"
+#include "MdtCalibFitters/MTStraightLine.h"
+#include "MdtCalibFitters/DCSLFitter.h"
+//#include "MdtCalibFitters/FourCasesFitter.h"
+
+
+namespace MuonCalib {
+
+class StraightPatRec : public IMdtPatRecFitter {
+
+public:
+// Constructors //
+	StraightPatRec(void) {
+		m_init();
+		}
+	///< Default constructor: road width for pattern recognition = 0.5 mm.
+
+	StraightPatRec(const double & r_road_width) {
+		m_init(r_road_width);
+		}
+	///< Constructor: user-defined road width for pattern recognition.
+
+// Methods //
+// get-methods //
+	double roadWidth(void) const;
+	                                ///< get the road width used in the 
+	                                ///< pattern recognition
+	unsigned int numberOfTrackHits(void) const;
+	                                ///< get the number of track hits in the
+	                                ///< final track,
+	                                ///< the method returns 0, if no track 
+	                                ///< has been reconstructed
+	const std::vector<const MdtCalibHitBase*> & trackHits(void) const;
+	                                ///< get a vector with a pointer to the
+	                                ///< hits used in the track
+	                                ///< reconstruction
+	double chi2(void) const;
+	                                ///< get the chi^2 of the final track,
+	                                ///< the method returns -1, if no track
+	                                ///< has been reconstructed
+	double chi2PerDegreesOfFreedom(void) const;
+	                                ///< get the chi^2 per degrees of
+	                                ///< freedom for the final track,
+	                                ///< the method returns -1, if no track
+	                                ///< has been reconstructed
+	MTStraightLine track(void) const;
+	                                ///< get the final track in the local
+					///< co-ordinate frame, i.e.
+					///<                      z 
+					///<                      ^
+					///<     o o o o o o      |
+					///<  ... o o o o o ...   o--> y
+					///<     o o o o o o     x
+
+// set-method //
+	void setRoadWidth(const double & r_road_width);
+	                                ///< set the road width for the pattern
+	                                ///< recognition = r_road_width
+	void setTimeOut(const double & time_out);
+					///< set the time-out for the track
+					///< finding to time_out (in seconds)
+
+	void setFixSelection(bool fix_sel);
+
+// methods required by the base class "IMdtSegmentFitter" //
+	bool fit(MuonCalibSegment & r_segment) const;
+	                                ///< reconstruction of the track using
+	                                ///< all hits in the segment
+	                                ///< "r_segment", returns true in case
+	                                ///< of success;
+	                                ///< the algorithm overwrites
+	                                ///< the track radii, the track
+	                                ///< position, track direction, and
+	                                ///< chi^2 per degrees of freedom;
+	                                ///< warning: the errors of the track
+	                                ///< radii are only approximate
+	bool fit(MuonCalibSegment & r_segment, HitSelection r_selection) const;
+	                                ///< reconstruction of the track using 
+					///< only those hits in r_segment for
+	                                ///< which the r_selection[.] is 0,
+	                                ///< return true in case of success;
+	                                ///< the algorithm overwrites
+	                                ///< the track position, direction,
+					///< and the chi^2 in r_segment; it
+	                                ///< updates the distances of all hits
+	                                ///< from the track, i.e. also of those
+	                                ///< hits which were rejected from the
+	                                ///< track reconstruction;
+	                                ///< warning : the errors of the track
+	                                ///< CLHEP::radii are only approximate
+
+bool fitCallByReference(MuonCalibSegment & r_segment, HitSelection &r_selection) const;
+
+	void printLevel(int level);
+	                                ///< set the print level, this call
+					///< has no effect
+
+private:
+// internal co-ordinate definition //
+//	                    x3 
+//	                    ^
+//	   o o o o o o      |
+//	... o o o o o ...   o--> x2
+//	   o o o o o o     x1
+//
+
+// final track parameters //
+	mutable std::vector<const MdtCalibHitBase*> m_track_hits;
+	                                // pointer to hits used by the final
+	                                // track
+	mutable int m_nb_track_hits; // number of track hits in the final 
+	                                // track
+	mutable double m_chi2; // chi^2 of the final track
+	double m_m_x1, m_b_x1; // slope and intercept in the x1-x3 plane
+	double m_m_x2, m_b_x2; // slope and intercept in the x2-x3 plane
+	double m_m_x1_err, m_b_x1_err; // errors on m_x1 and b_x1
+	double m_m_x2_err, m_b_x2_err; // errors on m_x2 and b_x2
+	mutable MTStraightLine m_track; // final track
+
+	bool m_fix_selection;
+
+// parameters for the adjustment of the track reconstruction //
+	double m_r_max; // maximum radius
+	double m_road_width; // road width for pattern recognition
+	double m_time_out; // time-out for track finding
+
+// chi^2 refitter //
+//	DCSLFitter m_nfitter; // NIKHEF straight line reconstruction
+//	FourCasesFitter m_nfitter;
+
+// initialization methods //
+	void m_init(void);
+	                        // default initialization:  road width = 0.5 CLHEP::mm
+	void m_init(const double & r_road_width);
+	                        // initialization with user-defined road width
+
+// auxiliary methods //
+	MTStraightLine tangent(const Amg::Vector3D & r_w1,
+	        const double & r_r1, const double & r_sigma12,
+	        const Amg::Vector3D & r_w2, const double & r_r2,
+	        const double & r_sigma22, const int & r_case) const;
+	      // method for the calculation of tangents with errors;
+	      // r_w1: wire position for the first hit,
+	      // r_r1: drift radius of the first hit,
+	      // r_sigma12: sigma(r_r1)^2,
+	      // r_w2: wire position for the second hit,
+	      // r_r2: drift radius of the second hit,
+	      // r_sigma22: sigma(r_r2)^2,
+	      // r_case = 1, 2, 3, 4: select one of the four cases of a tangent
+	MTStraightLine fitCandidate(MuonCalibSegment & r_segment,
+				const std::vector<unsigned int> & r_selection,
+				const MTStraightLine & cand_line) const;
+//				const std::vector<unsigned int> & index) const;
+		// refit the candidate "cand_line" using the hits specified by
+		// the r_selection and index vectors
+
+};
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/cmt/requirements b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..5d7be1e3ea044bdb63e6922fed6a291d8b648ffb
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/cmt/requirements
@@ -0,0 +1,27 @@
+package MdtCalibFitters
+
+author Niels van Eldik
+
+use AtlasPolicy		AtlasPolicy-*
+
+use GeoPrimitives  GeoPrimitives-*   DetectorDescription
+use EventPrimitives  EventPrimitives-*  Event
+
+use MuonCalibEventBase   MuonCalibEventBase-*   MuonSpectrometer/MuonCalib
+use MdtCalibInterfaces   MdtCalibInterfaces-*   MuonSpectrometer/MuonCalib/MdtCalib
+use MuonCalibMath        MuonCalibMath-*   MuonSpectrometer/MuonCalib/MuonCalibUtils
+
+include_dirs "$(MdtCalibFitters_root)"
+
+macro MdtCalibFitters_linkopts "-L$(MdtCalibFitters_root)/lib -lMdtCalibFitters"
+
+library  MdtCalibFitters ../src/*.cxx
+
+apply_pattern installed_library 
+
+private
+
+use AtlasCLHEP		AtlasCLHEP-* External
+
+#macro cppdebugflags ''
+#macro_remove componentshr_linkopts "-Wl,-s"
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/doc/Doxyfile b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/doc/Doxyfile
new file mode 100644
index 0000000000000000000000000000000000000000..6d20c82d4f36ae64b076aa75a3e43cf1c5b6a284
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/doc/Doxyfile
@@ -0,0 +1,160 @@
+# Doxyfile 1.2.10
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = MdtCalibFitters
+PROJECT_NUMBER         = MdtCalibFitters-00-00-03
+OUTPUT_DIRECTORY       = /afs/cern.ch/user/d/domizia/calibration4/InstallArea/doc/MdtCalibFitters
+OUTPUT_LANGUAGE        = English
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = YES
+EXTRACT_STATIC         = YES
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ALWAYS_DETAILED_SEC    = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+INTERNAL_DOCS          = NO
+CLASS_DIAGRAMS         = YES
+SOURCE_BROWSER         = YES
+INLINE_SOURCES         = YES
+STRIP_CODE_COMMENTS    = YES
+CASE_SENSE_NAMES       = YES
+SHORT_NAMES            = NO
+HIDE_SCOPE_NAMES       = NO
+VERBATIM_HEADERS       = YES
+SHOW_INCLUDE_FILES     = YES
+JAVADOC_AUTOBRIEF      = YES
+INHERIT_DOCS           = YES
+INLINE_INHERITED_MEMB  = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = NO
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 8
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+ALIASES                = 
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+OPTIMIZE_OUTPUT_FOR_C  = NO
+SHOW_USED_FILES        = YES
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_FORMAT            = 
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT =  ../src ../MdtCalibFitters ../doc
+FILE_PATTERNS          = *.cxx *.h *.py *.xml *.mk
+RECURSIVE              = YES
+EXCLUDE                = 
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = ../doc ../cmt ../share
+EXAMPLE_PATTERNS       = *.cxx *.html requirements *.py
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = 
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = 
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = 
+MAN_EXTENSION          = 
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = 
+EXPAND_AS_DEFINED      = 
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES =  /afs/cern.ch/atlas/software/dist/10.2.0/InstallArea/doc/AtlasPolicy.tag /afs/cern.ch/user/d/domizia/calibration4//InstallArea/doc/MuonCalibEvent.tag /afs/cern.ch/user/d/domizia/calibration4//InstallArea/doc/MuonCalibEventBase.tag
+GENERATE_TAGFILE = /afs/cern.ch/user/d/domizia/calibration4/InstallArea/doc/MdtCalibFitters.tag
+ALLEXTERNALS           = NO
+PERL_PATH              = 
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+HAVE_DOT               = YES
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+TEMPLATE_RELATIONS     = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+GRAPHICAL_HIERARCHY    = YES
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 1024
+MAX_DOT_GRAPH_HEIGHT   = 1024
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+DOT_IMAGE_FORMAT       = gif
+UML_LOOK               = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/doc/mainpage.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/doc/mainpage.h
new file mode 100644
index 0000000000000000000000000000000000000000..874015e5d5b5c1eaefccdded6bd45a2e855227e7
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/doc/mainpage.h
@@ -0,0 +1,35 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+@mainpage MdtCalibFitters Package
+@author Niels.Van.Eldik@cern.ch, Fabrizio.Petrucci@cern.ch
+                                                                                
+@section MdtCalibFittersIntro Introduction
+Package containing local pattern recognition algorithms and fitters that 
+work on segment level.
+                                                                                
+@section MdtCalibFittersOverview Class Overview
+
+- MuonCalib::DCSLFitter: straight line fitter for drift circles
+- MuonCalib::LocalSegmentResolver: calculates the local position and direction of the segment using the hits on track
+- MuonCalib::LocalToPrecision: provides transformation between local and precision reference frames
+- MuonCalib::MuCCaFitter: interface to the straight line fitter for drift circles used by Calib
+- MuonCalib::MuCCaFitterImplementation: the straight line fitter for drift circles used by Calib
+                                                                                
+@ref used_MdtCalibFitters
+                                                                                
+@ref requirements_MdtCalibFitters
+*/
+                                                                                
+/**
+@page used_MdtCalibFitters Used Packages
+@htmlinclude used_packages.html
+*/
+                                                                                
+/**
+@page requirements_MdtCalibFitters Requirements
+@include requirements
+*/
+
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/doc/used_packages.html b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/doc/used_packages.html
new file mode 100644
index 0000000000000000000000000000000000000000..9c7000d00b1dbf1f73bc890c2aedf5274e834762
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/doc/used_packages.html
@@ -0,0 +1,7 @@
+<center><table border='1'><tr><td><center><i>Used packages</i></center></td></tr>
+<tr><td><a href='../../AtlasCLHEP/html'>External/AtlasCLHEP</a></td></tr>
+<tr><td><a href='../../AtlasPolicy/html'>AtlasPolicy</a></td></tr>
+<tr><td><a href='../../MdtCalibInterfaces/html'>MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibInterfaces</a></td></tr>
+<tr><td><a href='../../MuonCalibEvent/html'>MuonSpectrometer/MuonCalib/MuonCalibEvent</a></td></tr>
+<tr><td><a href='../../MuonCalibEventBase/html'>MuonSpectrometer/MuonCalib/MuonCalibEventBase</a></td></tr>
+</table></center>
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/CurvedCandidateFinder.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/CurvedCandidateFinder.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d1102d8809f8535684bee60c5a1353fd8d3924e0
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/CurvedCandidateFinder.cxx
@@ -0,0 +1,193 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 13.07.2008, AUTHOR: OLIVER KORTNER
+// Modified: 04.08.2008 by O. Kortner, estimated direction of incidence can be
+//                                     set.
+//           07.08.2008 by O. Kortner, bug fig in the pattern recognition.
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: IMPLEMENTATION OF METHODS DEFINED IN THE CLASS CurvedCandidateFinder ::
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+#include "MdtCalibFitters/CurvedCandidateFinder.h"
+
+//::::::::::::::::::::::::
+//:: NAMESPACE SETTINGS ::
+//::::::::::::::::::::::::
+
+using namespace MuonCalib;
+using namespace std;
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: CONSTRUCTOR ::
+//:::::::::::::::::
+
+CurvedCandidateFinder::CurvedCandidateFinder(
+                           const std::vector<const MdtCalibHitBase *> & hits) {
+
+    m_hits = hits;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::
+//:: METHOD getCandidates ::
+//::::::::::::::::::::::::::
+
+const std::vector<CurvedLine> & CurvedCandidateFinder::getCandidates(
+                                                const double & road_width) {
+
+	Amg::Vector3D est_dir(0.0, 0.0, 1.0);
+	return getCandidates(road_width, est_dir);
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::
+//:: METHOD getCandidates ::
+//::::::::::::::::::::::::::
+
+const std::vector<CurvedLine> & CurvedCandidateFinder::getCandidates(
+                                                const double & road_width,
+												const Amg::Vector3D & est_dir) {
+
+/////////////////////////////////////////
+// RETURN IF THERE ARE NOT ENOUGH HITS //
+/////////////////////////////////////////
+
+    if (m_hits.size()<3) {
+        cerr << endl
+                << "Class CurvedCandidateFinder, method getCandidates: "
+                << "WARNING!\n"
+                << "Not enough hits to determine a parabola!\n";
+    }
+
+///////////////
+// VARIABLES //
+///////////////
+
+    const MdtCalibHitBase *hit[3]; // three hits defining the candidate line
+    double min_z, max_z, dist(0.0); // auxialiary variables to define the points
+    vector<Amg::Vector3D> points(3); // points defining the curved candidate line
+    int sign[3]; // auxiliary sign array
+	Amg::Vector3D null(0.0, 0.0, 0.0); // auxiliary 0 vector
+	Amg::Vector3D xhat(1.0, 0.0, 0.0); // auxiliary unit vector
+	Amg::Vector3D shift_vec(0.0, est_dir.z(), -est_dir.y());
+	shift_vec = shift_vec.unit();
+
+/////////////////////////////////////////////
+// FIND THREE HITS WITH LARGEST SEPARATION //
+/////////////////////////////////////////////
+
+    hit[0] = m_hits[0];
+    hit[1] = 0;
+    hit[2] = m_hits[0];
+
+    min_z = hit[0]->localPosition().z();
+    max_z = hit[2]->localPosition().z();
+
+// get the points with the smallest and largest local z coordinate //
+    for (unsigned int k=1; k<m_hits.size(); k++) {
+        if (m_hits[k]->localPosition().z()<min_z) {
+            min_z = m_hits[k]->localPosition().z();
+            hit[0] = m_hits[k];
+        }
+        if (m_hits[k]->localPosition().z()>max_z) {
+            max_z = m_hits[k]->localPosition().z();
+            hit[2] = m_hits[k];
+        }
+    }
+
+// find a third hit with large separation from these two points //
+    for (unsigned int k=0; k<m_hits.size(); k++) {
+        if (m_hits[k]!=hit[0] && m_hits[k]!=hit[2]) {
+            if (hit[1]==0) {
+                hit[1] = m_hits[k];
+                dist = (hit[2]->localPosition().z()-hit[1]->localPosition().z())
+                     -(hit[1]->localPosition().z()-hit[0]->localPosition().z());
+            } else {
+                if (dist<(hit[2]->localPosition().z()-
+                                                m_hits[k]->localPosition().z())
+                            -(m_hits[k]->localPosition().z()-
+                                                hit[0]->localPosition().z())) {
+                    dist = (hit[2]->localPosition().z()-
+                                                m_hits[k]->localPosition().z())
+                            -(m_hits[k]->localPosition().z()-
+                                                hit[0]->localPosition().z());
+                    hit[1] = m_hits[k];
+                }
+            }
+        }
+    }
+
+////////////////////////////////////////////////////////////////////
+// CALCULATE CANDIDATE LINES AND COUNT THE NUMBER OF HITS ON THEM //
+////////////////////////////////////////////////////////////////////
+
+// clear candidate vector //
+    m_candidates.clear();
+
+// search for the candidates //
+    for (sign[0]=-1; sign[0]<2; sign[0]=sign[0]+2) {
+    for (sign[1]=-1; sign[1]<2; sign[1]=sign[1]+2) {
+    for (sign[2]=-1; sign[2]<2; sign[2]=sign[2]+2) {
+
+// get a candidate //
+        unsigned int nb_hits(0);
+        for (unsigned int l=0; l<3; l++) {
+//             points[l] = Amg::Vector3D(hit[l]->localPosition().x(),
+//                             hit[l]->localPosition().y()+
+//                                                 sign[l]*hit[l]->driftRadius(),
+//                             hit[l]->localPosition().z());
+			points[l] = hit[l]->localPosition()+
+						sign[l]*hit[l]->driftRadius()*shift_vec;
+        }
+        CurvedLine cand_line(points);
+
+// refine the candidate //
+        for (unsigned int l=0; l<3; l++) {
+            MTStraightLine tangent(
+                            cand_line.getTangent(hit[l]->localPosition().z()));
+            Amg::Vector3D delta(tangent.positionVector()-hit[l]->localPosition());
+            Amg::Vector3D aux_dir(delta+(delta.dot(tangent.directionVector().unit())*tangent.directionVector().unit()));
+            aux_dir = hit[l]->driftRadius()*aux_dir.unit();
+            Amg::Vector3D mem(points[l]);
+            points[l][1] = (hit[l]->localPosition().y()+aux_dir.y());
+            points[l][2] = (hit[l]->localPosition().z()+aux_dir.z());
+        }
+
+// count the number of hits on the line within the given road width //
+        for (unsigned int k=0; k<m_hits.size(); k++) {
+            MTStraightLine w(Amg::Vector3D(0.0, m_hits[k]->localPosition().y(),
+						m_hits[k]->localPosition().z()), xhat, null, null);
+            double d(fabs((cand_line.getTangent(m_hits[k]->localPosition().z()
+                                                    )).signDistFrom(w)));
+            if (fabs(m_hits[k]->driftRadius()-d)<road_width) {
+                nb_hits++;
+            }
+        }
+
+// add the candidate line to list of candidates if there are enough hits //
+        if (nb_hits==m_hits.size()) {
+            m_candidates.push_back(cand_line);
+        }
+
+    }
+    }
+    }
+
+    return m_candidates;
+
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/CurvedLine.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/CurvedLine.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..915f33c6f4cd538964dd7b169b47036e014c8e6a
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/CurvedLine.cxx
@@ -0,0 +1,223 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 05.04.2008, AUTHOR: OLIVER KORTNER
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: IMPLEMENTATION OF METHODS DEFINED IN THE CLASS CurvedLine ::
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+#include "MdtCalibFitters/CurvedLine.h"
+#include "MuonCalibMath/BaseFunctionFitter.h"
+#include "MuonCalibMath/LegendrePolynomial.h"
+
+//::::::::::::::::::::::::
+//:: NAMESPACE SETTINGS ::
+//::::::::::::::::::::::::
+
+using namespace MuonCalib;
+using namespace std;
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::
+//:: DEFAULT CONSTRUCTOR ::
+//:::::::::::::::::::::::::
+
+CurvedLine::CurvedLine(void) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+    vector<Amg::Vector3D> points(3);
+    vector<Amg::Vector3D> errors(3);
+
+////////////////////
+// FILL VARIABLES //
+////////////////////
+
+    points[0] = Amg::Vector3D(0.0, 0.0, 0.0); errors[0] = Amg::Vector3D(1.0, 1.0, 0.0);
+    points[1] = Amg::Vector3D(0.0, 0.0, 1.0); errors[1] = Amg::Vector3D(1.0, 1.0, 0.0);
+    points[2] = Amg::Vector3D(0.0, 0.0, 2.0); errors[2] = Amg::Vector3D(1.0, 1.0, 0.0);
+
+////////////////////
+// INITIALIZATION //
+////////////////////
+
+    init(points, errors);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: CONSTRUCTOR ::
+//:::::::::::::::::
+
+CurvedLine::CurvedLine(std::vector<Amg::Vector3D> & points) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+    vector<Amg::Vector3D> errors(points.size());
+
+////////////////////
+// FILL VARIABLES //
+////////////////////
+
+    for (unsigned int k=0; k<errors.size(); k++) {
+        errors[k] = Amg::Vector3D(1.0, 1.0, 0.0);
+    }
+
+////////////////////
+// INITIALIZATION //
+////////////////////
+
+    init(points, errors);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: CONSTRUCTOR ::
+//:::::::::::::::::
+
+CurvedLine::CurvedLine(std::vector<Amg::Vector3D> & points,
+                                std::vector<Amg::Vector3D> & x_and_y_errors) {
+
+    init(points, x_and_y_errors);
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::
+//:: METHOD getPointOnLine ::
+//::::::::::::::::::::::::::::::
+
+Amg::Vector3D CurvedLine::getPointOnLine(const double & loc_z) const {
+
+///////////////
+// VARIABLES //
+///////////////
+
+    double loc_x(0.0), loc_y(0.0);
+
+///////////////////////////////
+// CALCULATE THE COORDINATES //
+///////////////////////////////
+
+    for (int k=0; k<m_coeff_xz.rows(); k++) {
+        loc_x = loc_x+m_coeff_xz[k]*m_Legendre->value(k, loc_z);
+    }
+
+    for (int k=0; k< m_coeff_yz.rows(); k++) {
+        loc_y = loc_y+m_coeff_yz[k]*m_Legendre->value(k, loc_z);
+    }
+
+////////////////////////////////
+// RETURN THE REQUESTED POINT //
+////////////////////////////////
+
+    return Amg::Vector3D(loc_x, loc_y, loc_z);
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::
+//:: METHOD getTangent ::
+//::::::::::::::::::::::::
+
+MTStraightLine CurvedLine::getTangent(const double & loc_z) const {
+
+///////////////
+// VARIABLES //
+///////////////
+
+    Amg::Vector3D null_vec(0.0, 0.0, 0.0); // auxiliary 0 vector
+    Amg::Vector3D point_1(getPointOnLine(loc_z)); // first point on the curved
+                                                  // line
+    Amg::Vector3D point_2(getPointOnLine(loc_z+1.0)); // second point on the
+                                                      // curved line
+
+////////////////////////
+// RETURN THE TANGENT //
+////////////////////////
+
+    return MTStraightLine(point_1, point_2-point_1, null_vec, null_vec);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: METHOD init ::
+//:::::::::::::::::
+
+void CurvedLine::init(std::vector<Amg::Vector3D> & points,
+                                std::vector<Amg::Vector3D> & x_and_y_errors) {
+
+////////////////////////////////
+// CHECK THE NUMBER OF POINTS //
+////////////////////////////////
+
+	if (points.size()<3) {
+		cerr << endl
+				<< "Class CurvedLine, method init: ERROR!\n"
+				<< "Not enough points given, must be at least 3 points!\n";
+	}
+
+///////////////
+// VARIABLES //
+///////////////
+
+    BaseFunctionFitter fitter;
+    LegendrePolynomial legendre; // Legendre polynomial needed by the base
+                                 // function fitter
+    vector<SamplePoint> sample_points(points.size()); // sample points needed
+                                                      // by the base function
+                                                      // fitter
+/////////////////////////////////////////////
+// FILL THE VARIABLES AND PERFORM THE FITS //
+/////////////////////////////////////////////
+
+// xz plane //
+    for (unsigned int k=0; k<points.size(); k++) {
+        sample_points[k].set_x1(points[k].z());
+        sample_points[k].set_x2(points[k].x());
+        sample_points[k].set_error(x_and_y_errors[k].x());
+    }
+    fitter.set_number_of_coefficients(2);
+    fitter.fit_parameters(sample_points, 1, sample_points.size(), &legendre);
+    m_coeff_xz = fitter.coefficients();
+
+// yz plane //
+    for (unsigned int k=0; k<points.size(); k++) {
+        sample_points[k].set_x1(points[k].z());
+        sample_points[k].set_x2(points[k].y());
+        sample_points[k].set_error(x_and_y_errors[k].y());
+    }
+    fitter.set_number_of_coefficients(3);
+    fitter.fit_parameters(sample_points, 1, sample_points.size(), &legendre);
+    m_coeff_yz = fitter.coefficients();
+
+//////////////////////////////////////////////
+// GET A POINTER TO THE LEGENDRE POLYNOMIAL //
+//////////////////////////////////////////////
+
+    m_Legendre = Legendre_polynomial::get_Legendre_polynomial();
+
+    return;
+
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/CurvedPatRec.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/CurvedPatRec.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0d8cf9eed85f80d74f567883008f86619ed51497
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/CurvedPatRec.cxx
@@ -0,0 +1,573 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 05.04.2008, AUTHOR: OLIVER KORTNER
+// Modified: 25.07.2008 by O. Kortner, improved pattern recognition by using
+//                                     the class "CurvedCandidateFinder"
+//           04.08.2008 by O. Kortner, further improvements of the pattern
+//                                     recognition for large incidence angles.
+//           07.08.2008 by O. Kortner, bug fig in the pattern recognition.
+//           18.08.2008 by O. Kortner, update of chi^2 and segment position
+//                                     and direction added.
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: IMPLEMENTATION OF METHODS DEFINED IN THE CLASS CurvedPatRec ::
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+#include "MdtCalibFitters/CurvedPatRec.h"
+#include "MdtCalibFitters/CurvedCandidateFinder.h"
+#include "MuonCalibMath/Combination.h"
+#include "time.h"
+#include "cmath"
+
+//::::::::::::::::::::::::
+//:: NAMESPACE SETTINGS ::
+//::::::::::::::::::::::::
+
+using namespace MuonCalib;
+using namespace std;
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::
+//:: DEFAULT CONSTRUCTOR ::
+//:::::::::::::::::::::::::
+
+CurvedPatRec::CurvedPatRec(void) {
+
+	m_chi2 = -1.0;
+    m_road_width = 0.5;
+    m_track_hits.clear();
+    m_time_out = 10;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: CONSTRUCTOR ::
+//:::::::::::::::::
+
+CurvedPatRec::CurvedPatRec(const double & road_width) {
+
+	m_chi2 = -1.0;
+    m_road_width = road_width;
+    m_track_hits.clear();
+    m_time_out = 10;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::
+//:: METHOD roadWidth ::
+//::::::::::::::::::::::
+
+double CurvedPatRec::roadWidth(void) const {
+
+	return m_road_width;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::
+//:: METHOD numberOfTrackHits ::
+//::::::::::::::::::::::::::::::
+
+unsigned int CurvedPatRec::numberOfTrackHits(void) const {
+
+	return m_track_hits.size();
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::
+//:: METHOD trackHits ::
+//::::::::::::::::::::::
+
+const std::vector<const MdtCalibHitBase*> & CurvedPatRec::trackHits(
+																void) const {
+
+	return m_track_hits;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: METHOD chi2 ::
+//:::::::::::::::::
+
+double CurvedPatRec::chi2(void) const {
+
+	return m_chi2;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::::::
+//:: METHOD chi2PerDegreesOfFreedom ::
+//::::::::::::::::::::::::::::::::::::
+
+double CurvedPatRec::chi2PerDegreesOfFreedom(void) const {
+
+	return m_chi2/static_cast<double>(m_track_hits.size()-3);
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::
+//:: METHOD curvedTrack ::
+//::::::::::::::::::::::::
+
+const CurvedLine & CurvedPatRec::curvedTrack(void) const {
+
+	return m_curved_track;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::
+//:: METHOD setRoadWidth ::
+//:::::::::::::::::::::::::
+
+void CurvedPatRec::setRoadWidth(const double & r_road_width) {
+
+	m_road_width = r_road_width;
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD setTimeOut ::
+//:::::::::::::::::::::::
+
+void CurvedPatRec::setTimeOut(const double & time_out) {
+
+	m_time_out = time_out;
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::
+//:: METHOD fit(.) ::
+//:::::::::::::::::::
+
+bool CurvedPatRec::fit(MuonCalibSegment & r_segment) const {
+
+// select all hits //
+	HitSelection selection(r_segment.mdtHitsOnTrack(), 0);
+// call the other fit function //
+	return fit(r_segment, selection);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::
+//:: METHOD fit(.,.) ::
+//:::::::::::::::::::::
+
+bool CurvedPatRec::fit(MuonCalibSegment & r_segment,
+											HitSelection r_selection) const {
+///////////////
+// VARIABLES //
+///////////////
+
+    time_t start, end; // start and end times (needed for time-out)
+	double diff; // difference of start and end time (needed for time-out)
+    Combination combination;
+    vector<unsigned int> hit_index; // hit indices for a given combination
+    unsigned int try_nb_hits; // try to find a segment with try_nb_hits hits
+    bool segment_found(false); // flag indicating the a segment has been found
+    vector<const MdtCalibHitBase *> cand_track_hits; // vector of the track hits
+                                                     // found so far
+    CurvedLine aux_line; // memory for reconstructed curved lines
+	Amg::Vector3D null(0.0, 0.0, 0.0);
+	Amg::Vector3D xhat(1.0, 0.0, 0.0);
+    vector<Amg::Vector3D> points; // hit points for the track fit
+	vector<const MdtCalibHitBase*> loc_track_hits; // track hit store
+
+////////////
+// RESETS //
+////////////
+
+	m_chi2 = -1.0;
+    m_track_hits.clear();
+	time(&start);
+
+////////////////////////////////////////
+// CHECK SIZE OF THE SELECTION VECTOR //
+////////////////////////////////////////
+
+    if (r_selection.size()!=r_segment.mdtHitsOnTrack()) {
+        cerr << endl
+             << "Class CurvedPatRec, method fit: ERROR!\n"
+             << "Size of selection vector does not match the number of hits on"
+             << "track!\n";
+        exit(1);
+    }
+
+//////////////////////
+// PREPARATORY WORK //
+//////////////////////
+
+// perform a straight track fit to get an estimate of the incidence angle //
+	Amg::Vector3D est_dir(0.0, 0.0, 1.0);
+	m_sfitter.setRoadWidth(2.0*m_road_width);
+	m_sfitter.setTimeOut(0.5*m_time_out);
+	if (m_sfitter.fit(r_segment, r_selection)) {
+		est_dir = m_sfitter.track().directionVector();
+	}
+	
+// store track hits //
+	for (unsigned int k=0; k<r_segment.mdtHitsOnTrack(); k++) {
+        if (r_selection[k]==0 && r_segment.mdtHOT()[k]->sigmaDriftRadius()<100) {
+            m_track_hits.push_back(r_segment.mdtHOT()[k]);
+        	loc_track_hits.push_back(r_segment.mdtHOT()[k]);
+		}
+    }
+
+// return, if there are too few hits //
+	if (m_track_hits.size()<4) {
+		return false;
+	}
+/////////////////////////
+// PATTERN RECOGNITION //
+/////////////////////////
+
+// try to find a segment with as many hits on it as possible //
+    try_nb_hits = loc_track_hits.size();
+	while (!segment_found && try_nb_hits>3) {
+
+   // reset //
+        m_chi2 = -1.0;
+
+   // loop over the combinations //
+        combination.setNewParameters(loc_track_hits.size(), try_nb_hits);
+        for (unsigned int cb=0; cb<combination.numberOfCombinations(); cb++) {
+
+   // time-out //
+            time (&end);
+            diff = difftime (end,start);
+            if (diff>m_time_out) {
+                cerr << endl
+	   		         << "Class CurvedPatRec: "
+	   		         << "time-out for track finding after "
+			         << m_time_out
+			         << " seconds!\n";
+                return false;
+            }
+
+    // analyse the hit combination //
+            if (cb==0) {
+                combination.currentCombination(hit_index);
+            } else {
+                combination.nextCombination(hit_index);
+            }
+            vector<const MdtCalibHitBase *> track_hits;
+            for (unsigned int k=0; k<try_nb_hits; k++) {
+                track_hits.push_back(loc_track_hits[hit_index[k]-1]);
+            }
+
+        // find candidates //
+            CurvedCandidateFinder finder(track_hits);
+            const vector<CurvedLine> &candidates(finder.getCandidates(
+                                                       m_road_width, est_dir));
+			if (candidates.size()==0) {
+                continue;
+            }
+
+            segment_found = true; 
+
+        // store the track hits //
+ //           m_track_hits = track_hits;
+
+            for (unsigned int cand=0; cand<candidates.size(); cand++) {
+                vector<Amg::Vector3D> errors(track_hits.size());
+                for (unsigned int k=0; k<errors.size(); k++) {
+                    if (track_hits[k]->sigmaDriftRadius()>0.0) {
+ 			            errors[k] = Amg::Vector3D(1.0,
+									track_hits[k]->sigmaDriftRadius(), 0.0);
+		            } else {
+			            errors[k] = Amg::Vector3D(1.0, 1.0, 0.0);
+		            }
+	            }
+
+        // get hit points //
+                points = getHitPoints(track_hits, candidates[cand]);
+
+        // fit a curved line through the points //
+                aux_line = CurvedLine(points, errors);
+
+        // calculate chi^2 //
+                double tmp_chi2(0.0);
+	            for (unsigned int k=0; k<track_hits.size(); k++) {
+		            MTStraightLine tang(m_curved_track.getTangent(
+										(track_hits[k]->localPosition()).z()));
+                    MTStraightLine wire(Amg::Vector3D(0.0, 
+									track_hits[k]->localPosition().y(),
+									track_hits[k]->localPosition().z()),
+									xhat, null, null);
+                    double d(fabs(tang.signDistFrom(wire)));
+                    if (track_hits[k]->sigma2DriftRadius()!=0) {
+                        tmp_chi2 = tmp_chi2+
+                                    std::pow(d-track_hits[k]->driftRadius(), 2)/
+									track_hits[k]->sigma2DriftRadius();
+                    } else {
+                        tmp_chi2 = tmp_chi2+
+                                    std::pow(d-track_hits[k]->driftRadius(), 2)/0.01;
+                    }
+	            }
+
+        // compare chi^2 with chi^2 values found so far //
+                if (m_chi2<0) {
+                    m_chi2 = tmp_chi2;
+                    m_curved_track = aux_line;
+        // store the track hits //
+					m_track_hits = track_hits;
+               } else {
+ 					if (tmp_chi2<m_chi2) {
+                        m_chi2 = tmp_chi2;
+                        m_curved_track = aux_line;
+ 						m_track_hits = track_hits;
+					}
+                }
+
+            }
+
+        }
+
+        try_nb_hits = try_nb_hits-1;
+
+    }
+
+    if (segment_found==false) {
+        return false;
+    }
+
+///////////////////////////////
+// SECOND REFINED CURVED FIT //
+///////////////////////////////
+
+// get hit points //
+    points = getHitPoints(m_track_hits, m_curved_track);
+    vector<Amg::Vector3D> errors(m_track_hits.size());
+    for (unsigned int k=0; k<errors.size(); k++) {
+        if (m_track_hits[k]->sigmaDriftRadius()>0.0) {
+ 		    errors[k] = Amg::Vector3D(1.0,
+									m_track_hits[k]->sigmaDriftRadius(), 0.0);
+		} else {
+		    errors[k] = Amg::Vector3D(1.0, 1.0, 0.0);
+		}
+	}
+
+// fit a curved line through the points //
+	m_curved_track = CurvedLine(points, errors);
+
+/////////////////////
+// CALCULATE CHI^2 //
+/////////////////////
+
+	m_chi2 = 0.0;
+	for (unsigned int k=0; k<m_track_hits.size(); k++) {
+		MTStraightLine tang(m_curved_track.getTangent(
+									(m_track_hits[k]->localPosition()).z()));
+		MTStraightLine wire(Amg::Vector3D(0.0, 
+									m_track_hits[k]->localPosition().y(),
+									m_track_hits[k]->localPosition().z()),
+									xhat, null, null);
+		double d(fabs(tang.signDistFrom(wire)));
+		if (m_track_hits[k]->sigma2DriftRadius()!=0) {
+            m_chi2 = m_chi2+ std::pow(d-m_track_hits[k]->driftRadius(), 2)/
+									m_track_hits[k]->sigma2DriftRadius();
+        } else {
+            m_chi2 = m_chi2+ std::pow(d-m_track_hits[k]->driftRadius(), 2)/0.01;
+        }
+	}
+
+//////////////////////////
+// UPDATE HIT RESIDUALS //
+//////////////////////////
+
+	MuonCalibSegment::MdtHitIt it = r_segment.mdtHOTBegin();
+	while(it!=r_segment.mdtHOTEnd()){
+
+		MdtCalibHitBase& hit = const_cast< MdtCalibHitBase& >( **it );
+
+		Amg::Vector3D pos(0.0, (hit.localPosition()).y(),
+					(hit.localPosition()).z());
+		MTStraightLine aux_line(pos, xhat, null, null);
+
+		MTStraightLine tang(m_curved_track.getTangent(pos.z()));
+
+		double dist(tang.signDistFrom(aux_line)); // track distance
+		double dist_err(1.0); // unknown error of the track distance
+		hit.setDistanceToTrack(dist, dist_err);
+    
+		++it;
+
+	}
+
+	if (std::isnan(m_chi2)) {
+		m_chi2=1.0e6;
+	}
+
+///////////////////////////////////////////////
+// UPDATE SEGMENT POSITION, DIRECTION, CHI^2 //
+///////////////////////////////////////////////
+
+	MTStraightLine tangent(m_curved_track.getTangent(
+												(r_segment.position()).z()));
+	r_segment.set(m_chi2/static_cast<double>(m_track_hits.size()-3),
+												tangent.positionVector(),
+												tangent.directionVector());
+
+	return true;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD printLevel ::
+//:::::::::::::::::::::::
+
+void CurvedPatRec::printLevel(int level) {
+
+	cerr << "Class CurvedPatRec: method printLevel: " << level
+			<< " has no effect!\n";
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::
+//:: METHOD getHitPoint ::
+//:::::::::::::::::::::::::
+
+Amg::Vector3D CurvedPatRec::getHitPoint(const MdtCalibHitBase * hit,
+                                const MTStraightLine & straight_track) const {
+
+///////////////
+// VARIABLES //
+///////////////
+
+// 	double dy, dz; // wire coordinates in the yz (precision) plane
+// 	double my, by; // slope and intercept of the given line in the yz
+				   // (precision) plane
+// 	double d0; // distance of the track from the wire
+
+////////////////////
+// FILL VARIABLES //
+////////////////////
+
+// 	dy = (hit->localPosition()).y();
+// 	dz = (hit->localPosition()).z();
+// 	my = straight_track.m_x2();
+// 	by = straight_track.b_x2();
+
+///////////////////////////////////////////
+// CALCULATE THE POINT OF CLOSE APPROACH //
+///////////////////////////////////////////
+
+// 	double z0((dz-(by-dy)*my)/(1+my*my));
+// 	double y0(my*z0+by);
+
+/////////////////////////
+// CALCULATE HIT POINT //
+/////////////////////////
+
+// 	d0 = sqrt((y0-dy)*(y0-dy)+(z0-dz)*(z0-dz));
+
+
+
+  Amg::Vector3D point = straight_track.positionVector() + (straight_track.directionVector().unit().dot(hit->localPosition() - straight_track.positionVector() ) ) * straight_track.directionVector().unit();
+  Amg::Vector3D point_2 = hit->localPosition() + hit->driftRadius() * (point - hit->localPosition()).unit() ;
+
+  return point_2;
+	
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::
+//:: METHOD getHitPoints ::
+//:::::::::::::::::::::::::
+
+std::vector<Amg::Vector3D> CurvedPatRec::getHitPoints(
+                                std::vector<const MdtCalibHitBase*> track_hits,
+                                const MTStraightLine & straight_track) const {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	vector<Amg::Vector3D> hit_vec;
+
+/////////////////////
+// FILL HIT VECTOR //
+/////////////////////
+
+	for (unsigned int k=0; k<track_hits.size(); k++) {
+		hit_vec.push_back(getHitPoint(track_hits[k], straight_track));
+	}
+
+///////////////////////////
+// RETURN THE HIT VECTOR //
+///////////////////////////
+
+	return hit_vec;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::
+//:: METHOD getHitPoints ::
+//:::::::::::::::::::::::::
+
+std::vector<Amg::Vector3D> CurvedPatRec::getHitPoints(
+                                std::vector<const MdtCalibHitBase*> track_hits,
+                                const CurvedLine & curved_track) const {
+///////////////
+// VARIABLES //
+///////////////
+
+	vector<Amg::Vector3D> hit_vec;
+
+/////////////////////
+// FILL HIT VECTOR //
+/////////////////////
+
+	for (unsigned int k=0; k<track_hits.size(); k++) {
+		hit_vec.push_back(getHitPoint(track_hits[k],
+							curved_track.getTangent(
+									(track_hits[k]->localPosition()).z())));
+	}
+
+///////////////////////////
+// RETURN THE HIT VECTOR //
+///////////////////////////
+
+	return hit_vec;
+
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/DCSLFitter.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/DCSLFitter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..35e6c621045ded14b6f83103442d24ec8c1807a6
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/DCSLFitter.cxx
@@ -0,0 +1,277 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "MdtCalibFitters/DCSLFitter.h"
+#include "cmath"
+
+namespace MuonCalib {
+
+  void DCSLFitter::printLevel(int level) {
+    if(level > 0 ) m_debug = true;
+  }
+
+  bool DCSLFitter::fit( MuonCalibSegment& seg ) const
+  {
+    // select all hits
+    HitSelection selection(seg.mdtHitsOnTrack(),0);
+
+    // call fit function
+    return fit(seg,selection);
+  }
+  
+
+  bool DCSLFitter::fit( MuonCalibSegment& seg, HitSelection selection ) const
+  {
+    if(m_debug) std::cout << "New seg: " << std::endl; //<< seg;
+
+
+    int N = seg.mdtHitsOnTrack();
+
+    if(N<2) {
+      return false;
+    }
+
+    if((int)selection.size() != N){
+      selection.clear();
+      selection.assign(N,0);
+    }else{
+      int used(0);
+      for(int i=0;i<N;++i){
+	if(selection[i] == 0) ++used;
+      }
+      if(used < 2){
+	std::cout << "TO FEW HITS SELECTED" << std::endl;
+	return false;
+      }
+    }
+
+    Amg::Vector3D pos = seg.position(); 
+    Amg::Vector3D dir = seg.direction(); 
+
+    double S(0),Sz(0),Sy(0);
+    double Zc(0),Yc(0);
+
+    std::vector<double> y(N);
+    std::vector<double> z(N);
+    std::vector<double> r(N);
+    std::vector<double> w(N);
+    {
+      MuonCalibSegment::MdtHitIt hit = seg.mdtHOTBegin();
+
+      int ii(0);
+      while(hit != seg.mdtHOTEnd()){
+	const MdtCalibHitBase& h = **hit;
+      
+	y[ii] = getY( h.localPosition() );
+	z[ii] = getZ( h.localPosition() );
+	r[ii] = std::abs( h.driftRadius() );
+	if(h.sigma2DriftRadius() > 0)
+	  w[ii] = 1./( h.sigma2DriftRadius() );
+	else
+	  w[ii] = 0.;
+	if(r[ii]<0){
+	  r[ii] = 0.;
+	  std::cout << "DCSLFitter ERROR: <Negative r> " << r[ii] << std::endl;
+	}
+	if(m_debug)
+	  std::cout << "DC:  (" << y[ii] << "," << z[ii] << ")  R = " << r[ii]
+		    << " W " << w[ii] << std::endl;
+
+	if(selection[ii]){
+	  ++hit;++ii;
+	  continue;
+	}
+	S+=w[ii];
+	Sz+= w[ii]*z[ii];
+	Sy+= w[ii]*y[ii];
+	++hit;++ii;
+      }
+    }
+    Zc = Sz/S;
+    Yc = Sy/S;
+  
+    if(m_debug)
+      std::cout << "Yc " << Yc << " Zc " << Zc << std::endl;
+    //
+    //    shift hits
+    //
+    //std::cout << "Shifted d " << d << std::endl;
+    Sy = 0;
+    Sz = 0;
+    double Szz(0),Syy(0),Szy(0),Syyzz(0);
+    std::vector<double> rw(N);
+    std::vector<double> ryw(N);
+    std::vector<double> rzw(N);
+  
+    for(int i=0;i<N;++i){
+
+      y[i]  -= Yc;
+      z[i]  -= Zc;
+
+      if(selection[i]) continue;
+
+      rw[i]  = r[i]*w[i];
+      ryw[i] = rw[i]*y[i];
+      rzw[i] = rw[i]*z[i];
+
+      Szz   += z[i]*z[i]*w[i];
+      Syy   += y[i]*y[i]*w[i];
+      Szy   += y[i]*z[i]*w[i];
+      Syyzz += (y[i]-z[i])*(y[i]+z[i])*w[i];
+    }
+
+    if(m_debug)
+      std::cout << " Szz " << Szz << " Syy " << Syy 
+		<< " Szy " << Szy << " Syyzz " << Syyzz << std::endl; 
+  
+    int count(0);
+    double R(0),Ry(0),Rz(0);
+    double Att(0);
+    double Add = S;
+    double Bt(0);
+    double Bd(0);
+    double Stt(0);
+    double Sd(0);
+  
+    double cosin = getZ( dir )/dir.mag();
+    double sinus = getY( dir )/dir.mag();
+
+    if(m_debug) 
+      std::cout << "cos " << cosin << " sin " << sinus << std::endl;
+
+    // make sure 0 <= theta < PI
+    if ( sinus < 0.0 ) {
+      if(m_debug) {
+	std::cout << "sinus < 0.0 " << std::endl;
+      }     
+      sinus = -sinus;
+      cosin = -cosin;
+    } else if ( sinus == 0.0 && cosin < 0.0 ) {
+      if(m_debug) {
+	std::cout << "sinus == 0.0 && cosin < 0.0" << std::endl;
+      }     
+      cosin = -cosin;
+    }
+    //
+    // calculate shift
+    //
+    double d = -( getZ( pos )-Zc)*sinus+( getY( pos )-Yc)*cosin;
+    double theta = acos(cosin);
+    if(m_debug) {
+      std::cout << "____________INITIAL VALUES________________" << count << std::endl;
+      std::cout << "Theta " << theta << " d " << d << std::endl;
+    }
+
+    while(count<100){
+      if(m_debug) std::cout << "____________NEW ITERATION________________" << count << std::endl;
+      R=0;Ry=0;Rz=0;
+      for(int i=0;i<N;++i){
+	if(selection[i]) continue;
+
+	double dist = y[i]*cosin-z[i]*sinus;
+	if(dist>d){
+	  R  -= rw[i];
+	  Ry -= ryw[i];
+	  Rz -= rzw[i];
+	  if(m_debug) std::cout << " < - > " << dist - d << " r " << r[i];
+	}else{
+	  R  += rw[i];
+	  Ry += ryw[i];
+	  Rz += rzw[i];
+	  if(m_debug) std::cout << " < + > " << dist - d << " r " << r[i];
+	}
+      }
+      if(m_debug) std::cout << std::endl;
+      Att = Syy + cosin*(2*sinus*Szy - cosin*Syyzz);
+      Bt = -Szy + cosin*(sinus*Syyzz + 2*cosin*Szy + Rz) + sinus*Ry;
+      Bd = -S*d + R;
+      if(Att==0){
+	std::cerr << "===> Error NewtonSLDCFitter ZERO Determinant" << std::endl;
+	return false;
+      }
+      theta += Bt/Att;
+      if ( theta < 0.0   ) theta += M_PI;
+      if ( theta >= M_PI ) theta -= M_PI;
+      cosin = cos(theta);
+      sinus = sqrt(1-cosin*cosin);
+      d = R/S;
+      if(m_debug) std::cout << "R " << R << " Ry " << Ry << " Rz " << Rz << std::endl;
+      if(m_debug) std::cout << "Att " << Att << " Add " << Add << " Bt " << Bt << " Bd " << Bd << std::endl;
+      if(m_debug) std::cout << "dTheta " << Bt/Att << " dD " << Bd/Add << std::endl;
+      if(fabs(Bt/Att) < 0.001 && fabs(Bd/Add) < 0.001){
+	Stt = sqrt(1/Att);
+	Sd = sqrt(1/Add);
+	if(m_debug) std::cout << "Fit converged after " << count << " iterations " << std::endl;
+
+	if(m_debug) std::cout << "Theta " << theta << "d " << d << std::endl;
+	if(m_debug) std::cout << "Errors: theta " << Stt << " d " << Sd << std::endl;
+
+//        error_dy0 = Sd;
+//        error_dtheta = Stt;
+        seg.setErrors(Sd,Stt);
+
+	break;
+      }
+      ++count;
+    }
+    if(m_debug) std::cout << "Calculating chi2" << std::endl;
+
+    std::vector< double > yl(N);
+    std::vector< double > dyl(N);
+    std::vector< double > res(N);
+    double chi2(0);
+    if(m_debug) std::cout << "contributions to chi2: " << std::endl;
+
+    // calculate predicted hit positions from track parameters
+    for(int i=0;i<N;++i){
+      yl[i] = cosin*y[i] - sinus*z[i] - d;
+      double dth = -(sinus*y[i] + cosin*z[i])*Stt;
+      dyl[i] = sqrt( dth*dth + Sd*Sd );
+      res[i] = fabs(yl[i]) - r[i];
+      if(m_debug) std::cout << " r_track " << yl[i] << " dr " << dyl[i]
+			    << " r_rt " << r[i] << " res " << res[i]
+			    << " pull " << res[i]*res[i]*w[i] << std::endl;
+      //skip hits that are not used in fit
+      if(selection[i]) continue;
+
+      chi2 += res[i]*res[i]*w[i];
+
+    }
+  
+    // std::cout << " Chi2 = " << chi2 << " chi2 per dof " << chi2/(N-2) << std::endl;
+
+    if(m_debug) std::cout << "Fit complete: Chi2 tof " << chi2/(N-2)
+			  << " " << !(chi2/(N-2) > 5) << std::endl;
+    if(chi2/(N-2) > 5) {
+      if(m_debug) {
+	std::cout << "_______NOT GOOD " << std::endl;
+      }
+    }
+
+    if(m_debug) std::cout << "Transforming back to real world" << std::endl;
+
+    Amg::Vector3D ndir = getVec( dir.x() , sinus, cosin );
+    Amg::Vector3D npos = getVec( pos.x() , Yc + cosin*d, Zc - sinus*d );
+
+    if(m_debug) std::cout << "New line: position " << npos << " direction " << ndir << std::endl;
+
+    seg.set( chi2/(N-2), npos, ndir );
+
+    MuonCalibSegment::MdtHitIt it = seg.mdtHOTBegin();
+  
+    int i(0);
+    while(it!=seg.mdtHOTEnd()){
+      MdtCalibHitBase& hit = const_cast< MdtCalibHitBase& >( **it );
+
+      hit.setDistanceToTrack( yl[i], dyl[i] );
+    
+      ++it;++i;
+    }
+
+    if(m_debug) std::cout << "fit done" << std::endl;
+ //tracking failed if position and directins are not real numbers
+    return (std::isfinite(ndir.y()) && std::isfinite(ndir.z()) && std::isfinite(npos.y()) && std::isfinite(npos.z()));
+  }
+
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/IndexSet.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/IndexSet.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..1f088ecfa42baafcd945f69385cf2dd8f3350d42
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/IndexSet.cxx
@@ -0,0 +1,211 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 09.05.2005, AUTHOR: OLIVER KORTNER
+// Modified: 16.07.2006 by O. Kortner, vector size check in initialization
+//                      added,
+//                      != operator corrected.
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: IMPLEMENTATIONS OF METHODS DEFINED IN THE CLASS IndexSet ::
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+#include "MdtCalibFitters/IndexSet.h"
+#include <algorithm>
+#include <cstdlib>
+
+//:::::::::::::::::::::::
+//:: NAMESPACE SETTING ::
+//:::::::::::::::::::::::
+
+using namespace MuonCalib;
+using namespace std;
+
+//*****************************************************************************
+
+//:::::::::::::::::::
+//:: METHOD m_init ::
+//:::::::::::::::::::
+
+void IndexSet::m_init(void) {
+
+	m_nb_indices = 0;
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::
+//:: METHOD m_init(.) ::
+//::::::::::::::::::::::
+
+void IndexSet::m_init(const unsigned int & r_nb_indices) {
+
+	m_nb_indices = r_nb_indices;
+	m_index = vector<int>(m_nb_indices);
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::
+//:: METHOD m_init(.,.) ::
+//::::::::::::::::::::::::
+
+void IndexSet::m_init(const unsigned int & r_nb_indices,
+					const vector<int> r_index) {
+
+///////////////////////
+// CHECK VECTOR SIZE //
+///////////////////////
+
+	if (r_index.size()<r_nb_indices) {
+		cerr << endl
+			<< "Class IndexSet, method m_init: ERROR!\n"
+			<< "Index vector too short!\n";
+		exit(1);
+	}
+
+////////////////////
+// INITIALIZATION //
+////////////////////
+
+	m_nb_indices = r_nb_indices;
+	m_index = vector<int>(m_nb_indices);
+	for (unsigned int k=0; k<m_nb_indices; k++) {
+		if (k<r_index.size()) {
+			m_index[k] = r_index[k];
+		} else {
+			m_index[k] = 0;
+		}
+	}
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: METHOD size ::
+//:::::::::::::::::
+
+unsigned int IndexSet::size(void) const {
+
+	return m_nb_indices;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::
+//:: METHOD resize ::
+//:::::::::::::::::::
+
+void IndexSet::resize(const unsigned int & r_size) {
+
+//:::::::::::::::
+//:: VARIABLES ::
+//:::::::::::::::
+
+	vector<int> aux_index = m_index; // vector for temporary storage of
+	                                 // the indices
+
+//:::::::::::::::::::::::::::::::::::::
+//:: RESIZE AND COPY THE OLD INDICES ::
+//:::::::::::::::::::::::::::::::::::::
+
+	m_index = vector<int>(r_size);
+	for (unsigned int k=0; k<r_size; k++) {
+		if (k<m_nb_indices) {
+			m_index[k] = aux_index[k];
+		} else {
+			m_index[k] = 0;
+		}
+	}
+	m_nb_indices = r_size;
+
+	return;
+
+}
+
+//*****************************************************************************
+
+///:::::::::::::::::::::::
+//:: METHOD operator [] ::
+//::::::::::::::::::::::::
+
+int IndexSet::operator [] (const unsigned int & r_k) {
+
+	return m_index[r_k];
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::
+//:: METHOD operator [] ::
+//::::::::::::::::::::::::
+
+int IndexSet::operator [] (const unsigned int & r_k) const {
+
+	return m_index[r_k];
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: METHOD sort ::
+//:::::::::::::::::
+
+void IndexSet::sort(void) {
+
+	std::sort(m_index.begin(), m_index.end());
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::
+//:: METHOD operator == ::
+//::::::::::::::::::::::::
+
+bool IndexSet::operator == (const IndexSet & r_index_set) const {
+
+	if (r_index_set.size()!=m_nb_indices) {
+		return false;
+	}
+
+	for (unsigned int k=0; k<m_nb_indices; k++) {
+		if (m_index[k]!=r_index_set[k]) {
+			return false;
+		}
+	}
+
+	return true;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::
+//:: METHOD != ::
+//:::::::::::::::
+
+bool IndexSet::operator != (const IndexSet & r_index_set) const {
+
+	return !(*this==r_index_set);
+
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/LocalSegmentResolver.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/LocalSegmentResolver.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0c713c694b453f4e0c8c8f6af2514fcfefe5a75a
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/LocalSegmentResolver.cxx
@@ -0,0 +1,238 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "MdtCalibFitters/LocalSegmentResolver.h"
+
+#include "MuonCalibEventBase/MdtCalibHitBase.h"
+
+#include "MdtCalibFitters/LocalToPrecision.h"
+
+#include <iostream>
+
+namespace MuonCalib {
+
+  LocalSegmentResolver::LocalSegmentResolver() : m_printLevel(0) {}
+
+  bool LocalSegmentResolver::resolve(MuonCalibSegment* seg) const{
+    if( !seg ){
+      if( m_printLevel >= 0 )
+	std::cout << "LocalSegmentResolver::resolve  ERROR <got null pointer> " << std::endl;
+      return false;
+    }
+    if( seg->mdtHitsOnTrack() < 2 ) {
+      if( m_printLevel >= 1 )
+	std::cout << "LocalSegmentResolver::resolve  ERROR <to few hits, cannot resolve direction> " << std::endl;
+      return false;
+    }
+
+    // get tangent lines
+    LineVec lines = getLines( *seg->mdtHOT().front(), *seg->mdtHOT().back() );
+
+    // find line which yields smallest residuals
+    int lineIndex = bestLine( seg->mdtHOT(), lines );
+
+    // check if everything went right
+    if( lineIndex < 0 ) return false;
+
+    // reset local position and direction of segment
+    seg->set( seg->chi2(), MuonCalib::LocalToPrecision::local(lines[lineIndex].first), 
+	      MuonCalib::LocalToPrecision::local(lines[lineIndex].second) );
+
+    return true;
+  }
+
+  LocalSegmentResolver::LineVec LocalSegmentResolver::getLines( const MdtCalibHitBase& firstHit,
+								const MdtCalibHitBase& lastHit ) const
+  {
+  
+    Amg::Vector3D hpos1 = MuonCalib::LocalToPrecision::precision(firstHit.localPosition());
+    double  x1             = hpos1.x();
+    double  y1             = hpos1.y();
+    double  r1             = std::abs(firstHit.driftRadius());
+    Amg::Vector3D hpos2 = MuonCalib::LocalToPrecision::precision(lastHit.localPosition());
+    double  x2             = hpos2.x();
+    double  y2             = hpos2.y();
+    double  r2             = std::abs(lastHit.driftRadius());
+
+    double  DeltaX       		=	x2 - x1;
+    double  DeltaY       		=	y2 - y1;
+    double  DistanceOfCenters	=	sqrt(DeltaX*DeltaX + DeltaY*DeltaY);
+    double  Alpha0       		=	atan2(DeltaY,DeltaX);
+
+    LineVec list_of_lines;
+    
+    if( m_printLevel >= 3 ){
+      std::cout << "      calculating Lines (" << x1 << "," << y1 << ")  " << r1 
+		<< "       (" << x2 << "," << y2 << ")  " << r2 << std::endl;
+      std::cout << "      general dir " << (hpos2-hpos1).unit() 
+		<< " calculated : " << Amg::Vector3D( cos(Alpha0), sin(Alpha0), 0. ) << std::endl;
+    }
+
+    // Case of 0 drift distances, only 1 line
+    if ( r1 == 0. && r2 == 0.) {
+      Amg::Vector3D  pos = hpos1;
+      Amg::Vector3D dir( cos(Alpha0) ,sin(Alpha0), 0 );
+      if( m_printLevel >= 5 ) std::cout << " line pos " << pos << " dir " << dir << std::endl;
+      list_of_lines.push_back( std::make_pair(pos, dir) );
+      return list_of_lines;
+    }
+
+
+    // Here are the first 2 "inner" lines ....
+    double	RSum	=	r1 + r2;
+    double	Alpha1	=	asin(RSum/DistanceOfCenters);
+
+    double	line_phi	=	Alpha0 + Alpha1;
+
+    Amg::Vector3D  pos1( x1 + r1*sin(line_phi), y1 - r1*cos(line_phi), 0. ) ;
+    Amg::Vector3D dir1( cos(line_phi), sin(line_phi), 0. );
+
+    if( m_printLevel >= 5 )  
+      std::cout << " line pos " << pos1 << " dir " << dir1 << std::endl;
+
+    list_of_lines.push_back( std::make_pair(pos1, dir1) );
+    
+    line_phi	=	Alpha0 - Alpha1;
+  
+    Amg::Vector3D  pos2( x1 - r1*sin(line_phi), y1 + r1*cos(line_phi), 0. );
+    Amg::Vector3D dir2( cos(line_phi), sin(line_phi), 0. );
+			  
+    if( m_printLevel >= 5 ) 
+      std::cout << " line pos " << pos2 << " dir " << dir2 << std::endl;
+
+    list_of_lines.push_back( std::make_pair(pos2, dir2) );
+
+    // Case where one of the drifts is 0 ==> Only two lines
+    if (r1 == 0. || r2 == 0.)	return list_of_lines;
+  
+    // ... and here are the other 2 "outer" lines
+    double	DeltaR	=	fabs(r2 - r1);
+    double	Alpha2	=	asin(DeltaR/DistanceOfCenters);
+
+    if ( r1 < r2 ) {
+      if( m_printLevel >= 5 )
+	std::cout << "   r1 < r2 " << std::endl;
+
+
+      line_phi	=	Alpha0 + Alpha2;
+
+      Amg::Vector3D  pos3( x1 - r1*sin(line_phi), y1 + r1*cos(line_phi), 0. );
+      Amg::Vector3D dir3( cos(line_phi),sin(line_phi), 0. );
+
+      if( m_printLevel >= 5 )
+	std::cout << " line pos " << pos3 << " dir " << dir3 << std::endl;
+
+      list_of_lines.push_back( std::make_pair(pos3, dir3) );
+
+      line_phi	=	Alpha0 - Alpha2;
+
+      Amg::Vector3D  pos4( x1 + r1*sin(line_phi), y1 - r1*cos(line_phi), 0. );
+      Amg::Vector3D dir4( cos(line_phi),sin(line_phi), 0. );
+
+      if( m_printLevel >= 5 )
+	std::cout << " line pos " << pos4 << " dir " << dir4 << std::endl;
+
+      list_of_lines.push_back( std::make_pair(pos4, dir4) );
+
+    } else {
+      if( m_printLevel >= 5 )
+	std::cout << "   r1 > r2 " << std::endl;
+
+      line_phi	=	Alpha0 + Alpha2;
+
+      Amg::Vector3D  pos3( x1 + r1*sin(line_phi), y1 - r1*cos(line_phi), 0. );
+      Amg::Vector3D dir3( cos(line_phi),sin(line_phi), 0. );
+
+      if( m_printLevel >= 5 )
+	std::cout << " line pos " << pos3 << " dir " << dir3 << std::endl;
+
+      list_of_lines.push_back( std::make_pair(pos3, dir3) );
+
+      line_phi	=	Alpha0 - Alpha2;
+    
+      Amg::Vector3D  pos4( x1 - r1*sin(line_phi), y1 + r1*cos(line_phi), 0. );
+      Amg::Vector3D dir4( cos(line_phi),sin(line_phi), 0. );
+
+      if( m_printLevel >= 5 )
+	std::cout << " line pos " << pos4 << " dir " << dir4 << std::endl;
+
+      list_of_lines.push_back( std::make_pair(pos4, dir4) );
+    }
+
+    return list_of_lines;
+  }
+
+  int LocalSegmentResolver::bestLine( const LocalSegmentResolver::HitVec& hits,
+				      const LocalSegmentResolver::LineVec& localTracks ) const
+  {
+    // loop over tangent lines
+    LineVec::const_iterator lit     = localTracks.begin(); 
+    LineVec::const_iterator lit_end = localTracks.end(); 
+
+    // look for line with smallest residual sum
+    double ressummin = 1e20;
+    unsigned int resnum = 0;
+
+    for( ; lit!=lit_end;++lit ){
+
+      double ressum=0;
+
+      // calculate angle between line and z precision plane
+      double alpha = atan2(lit->second.y(),lit->second.x());
+
+      // get rotations in track frame
+      Amg::AngleAxis3D rotationAroundZ(-alpha,Amg::Vector3D::UnitZ());
+      //Amg::AngleAxis3D rotationAroundZ_inv(alpha,Amg::Vector3D::UnitZ());
+
+      // rotate position on track into track frame
+      Amg::Vector3D avePosTrk = rotationAroundZ*lit->first;
+    
+      if( m_printLevel >= 5 ){
+	Amg::Vector3D lTrkDir = rotationAroundZ*lit->second;
+	std::cout << "   angle " << alpha*57.32 << " trk dir in trk frame " << lTrkDir 
+		  << " pos " << avePosTrk << std::endl;
+      }
+      // loop over local hits
+      LocalSegmentResolver::HitVec::const_iterator it = hits.begin();
+      LocalSegmentResolver::HitVec::const_iterator it_end = hits.end();
+      for( ; it!=it_end; ++it ){
+      
+	// rotate into track system
+	Amg::Vector3D spos = MuonCalib::LocalToPrecision::precision((*it)->localPosition());
+	Amg::Vector3D sposAve = rotationAroundZ*spos - avePosTrk;
+      
+	// get drift radius (unsigned)
+	double r = std::abs( (*it)->driftRadius() );
+      
+	// calculate residual and pull
+	double res  = r - std::abs( sposAve.y() );
+
+	if( m_printLevel >= 5 )
+	  std::cout << " r " << r << " r_trk " << std::abs( sposAve.y() ) << " residual " << res << std::endl;
+      
+	ressum += res*res;
+      }  
+
+      if( m_printLevel >= 3 )
+	std::cout << "     line " << lit-localTracks.begin() << " residual sum " << ressum << std::endl;
+      if( ressum < ressummin ) {
+	ressummin = ressum;
+	resnum    = lit-localTracks.begin();
+      }
+    }
+
+    if( m_printLevel >= 3 ){
+      std::cout << "        Done selected line: ressum " <<  ressummin << " ## " << resnum << std::endl;
+      std::cout << "        Position " << localTracks[resnum].first 
+		<< "   direction " << localTracks[resnum].second << std::endl;
+    }
+    if( resnum >= localTracks.size() ) {
+      std::cout << " ERROR wrong line index " << std::endl;
+      return -1;
+    }
+    
+    return resnum;
+  }
+
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/MTStraightLine.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/MTStraightLine.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a6a75483f943484aac6466af29cafa0a71ea478b
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/MTStraightLine.cxx
@@ -0,0 +1,333 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 01.03.2006, AUTHORS: OLIVER KORTNER, FELIX RAUSCHER
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+#include "MdtCalibFitters/MTStraightLine.h"
+#include "cmath"
+#include <iostream>
+//:::::::::::::::::::::::
+//:: NAMESPACE SETTING ::
+//:::::::::::::::::::::::
+
+using namespace MuonCalib;
+
+//using namespace std;
+
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: IMPLEMENTATION OF METHODS DEFINED IN THE CLASS MTStraightLine ::
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+//*****************************************************************************
+
+//:::::::::::::::::::
+//:: METHOD m_init ::
+//:::::::::::::::::::
+
+void MTStraightLine::m_init(void) {
+
+	m_position = Amg::Vector3D(0.0, 0.0, 0.0);
+	m_direction = Amg::Vector3D(0.0, 0.0, 0.0);
+	m_position_error = Amg::Vector3D(0.0, 0.0, 0.0);
+	m_direction_error = Amg::Vector3D(0.0, 0.0, 0.0);
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::::::::::::::
+//:: METHOD m_init(const Amg::Vector3D &, ...) ::
+//::::::::::::::::::::::::::::::::::::::::::::
+
+void MTStraightLine::m_init(const Amg::Vector3D & r_position,
+				const Amg::Vector3D & r_direction,
+				const Amg::Vector3D & r_position_error,
+				const Amg::Vector3D & r_direction_error) {
+
+	m_position = r_position;
+	m_direction = r_direction;
+	m_position_error = r_position_error;
+	m_direction_error = r_direction_error;
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::
+//:: METHOD m_init ::
+//:::::::::::::::::::
+
+void MTStraightLine::m_init(const double & r_m_x1,
+		const double & r_b_x1,
+		const double & r_m_x2, const double & r_b_x2,
+		const double & r_m_x1_err, const double & r_b_x1_err,
+		const double & r_m_x2_err, const double & r_b_x2_err) {
+
+	m_position = Amg::Vector3D(r_b_x1, r_b_x2, 0.0);
+	m_direction = Amg::Vector3D(r_m_x1, r_m_x2, 1.0);
+	m_position_error = Amg::Vector3D(r_b_x1_err, r_b_x2_err, 0.0);
+	m_direction_error = Amg::Vector3D(r_m_x1_err, r_m_x2_err, 1.0);
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::
+//:: METHOD positionVector ::
+//:::::::::::::::::::::::::::
+
+Amg::Vector3D MTStraightLine::positionVector(void) const {
+
+	return m_position;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::
+//:: METHOD directionVector ::
+//::::::::::::::::::::::::::::
+
+Amg::Vector3D MTStraightLine::directionVector(void) const {
+
+	return m_direction;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::
+//:: METHOD positionError ::
+//::::::::::::::::::::::::::
+
+Amg::Vector3D MTStraightLine::positionError(void) const {
+
+	return m_position_error;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::
+//:: METHOD directionError ::
+//:::::::::::::::::::::::::::
+
+Amg::Vector3D MTStraightLine::directionError(void) const {
+
+	return m_direction_error;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: METHOD m_x1 ::
+//:::::::::::::::::
+
+double MTStraightLine::m_x1(void) const {
+
+	if (m_direction.z() == 0.0) {
+		return 0.0;
+	}
+	return m_direction.x()/m_direction.z();
+
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD m_x1_error ::
+//:::::::::::::::::::::::
+
+double MTStraightLine::m_x1_error(void) const {
+
+	if (m_direction.z()==0) {
+		return 0.0;
+	}
+
+	return sqrt(std::pow(m_direction_error.x()/m_direction_error.z(), 2)
+		+std::pow(m_direction_error.y()*m_x1()/m_direction_error.z(), 2));
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: METHOD b_x1 ::
+//:::::::::::::::::
+
+double MTStraightLine::b_x1(void) const {
+
+	if (m_direction.z() == 0.0) {
+		std::cerr << "Class MTStraightLine, method b_x1: WARNING!\n"
+			  << "b_x1 not uniquely defined." << std::endl;
+		return m_position.x();
+	}
+	return (m_position.x()-m_position.z()*m_x1());
+					
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD b_x1_error ::
+//:::::::::::::::::::::::
+
+double MTStraightLine::b_x1_error(void) const {
+
+	return sqrt(std::pow(m_position_error.x(), 2)+
+			std::pow(m_x1()*m_position_error.z(), 2)+
+			std::pow(m_position.z()*m_x1_error(),2));
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: METHOD m_x2 ::
+//:::::::::::::::::
+
+double MTStraightLine::m_x2(void) const {
+
+	if (m_direction.z() == 0.0) {
+		return 0.0;
+	}
+	return m_direction.y()/m_direction.z();
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD m_x2_error ::
+//:::::::::::::::::::::::
+
+double MTStraightLine::m_x2_error(void) const {
+
+	if (m_direction.z()==0) {
+		return 0.0;
+	}
+
+	return sqrt(std::pow(m_direction_error.y()/m_direction_error.z(), 2)
+		+std::pow(m_direction_error.y()*m_x2()/m_direction_error.z(), 2));
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: METHOD b_x2 ::
+//:::::::::::::::::
+
+double MTStraightLine::b_x2(void) const {
+
+	if (m_direction.z() == 0.0) {
+		std::cerr << "Class MTStraightLine, method b_x2: WARNING!\n"
+			  << "b_x2 not uniquely defined." << std::endl;
+		return m_position.x();
+	}
+	return (m_position.y()-m_position.z()*m_x2());
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD b_x2_error ::
+//:::::::::::::::::::::::
+
+double MTStraightLine::b_x2_error(void) const {
+
+	return sqrt(std::pow(m_position_error.y(), 2)+
+			std::pow(m_x2()*m_position_error.z(), 2)+
+			std::pow(m_position.z()*m_x2_error(),2));
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::
+//:: METHOD pointOnLine ::
+//::::::::::::::::::::::::
+
+Amg::Vector3D MTStraightLine::pointOnLine(const double & lambda) const {
+
+	return m_position+lambda*m_direction;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::
+//:: METHOD signDistFrom ::
+//:::::::::::::::::::::::::
+
+double MTStraightLine::signDistFrom(const MTStraightLine & h) const {
+
+//:::::::::::::::::::::::::
+//:: AUXILIARY VARIABLES ::
+//:::::::::::::::::::::::::
+
+	Amg::Vector3D a = m_position, u = m_direction;
+					// position and direction vectors of g
+	Amg::Vector3D b = h.positionVector(), v = h.directionVector();
+					// position and direction vectors of h
+	Amg::Vector3D n; // normal vector of plane spanned by g and h
+	Amg::Vector3D d; // distance vector
+
+//:::::::::::::
+//:: PROGRAM ::
+//:::::::::::::
+
+//::::::::::::::::::::::::
+//:: collinearity check ::
+//::::::::::::::::::::::::
+
+	n = u.cross(v);
+	d = a-b;
+	if (n.dot(n) == 0.0) {
+		// straight lines are parallel
+		// no sign given
+	  return sqrt(d.dot(d)-(u.unit().dot(d))*(u.unit().dot(d)));
+	}
+	
+	return (d.dot(n.unit()));
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::
+//:: METHOD distFromLine ::
+//:::::::::::::::::::::::::
+
+double MTStraightLine::distFromLine(const Amg::Vector3D & point) const {
+
+//:::::::::::::::::::::::::
+//:: AUXILIARY VARIABLES ::
+//:::::::::::::::::::::::::
+
+	Amg::Vector3D u = m_direction;
+
+//::::::::::::::::::::::::
+//:: CALCULATE DISTANCE ::
+//::::::::::::::::::::::::
+
+	return sqrt((point-m_position).dot(point-m_position) -
+		    ((point-m_position).dot(u.unit()))*((point-m_position).dot(u.unit())));
+
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/MuCCaFitter.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/MuCCaFitter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..57a2b9b9721ebc995d150a1ed744a9a6b38a829c
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/MuCCaFitter.cxx
@@ -0,0 +1,653 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//#include <iostream.h>
+//#include <math.h>
+#include "MdtCalibFitters/MuCCaFitter.h"
+
+//class MuCCaFitterImplementation;
+
+namespace MuonCalib {
+
+void MuCCaFitter::printLevel(int level) {
+  if(level > 0 ) m_debug = true;
+}
+
+bool MuCCaFitter::fit( MuonCalibSegment& seg ) const
+{
+
+  // select all hits
+  HitSelection selection(seg.mdtHitsOnTrack(),0);
+
+  // call fit function
+  return fit(seg,selection);
+}
+  
+
+bool MuCCaFitter::fit( MuonCalibSegment& seg, HitSelection selection ) const
+{
+  bool m_debug = false;
+  if(m_debug) std::cout << "New seg: " << std::endl; //<< seg;
+
+
+  int N = seg.mdtHitsOnTrack();
+
+  if(N<2) {
+    return false;
+  }
+
+  if((int)selection.size() != N){
+    selection.clear();
+    selection.assign(N,0);
+  }else{
+    int used(0);
+    for(int i=0;i<N;++i){
+      if(selection[i] == 0) ++used;
+    }
+    if(used < 2){
+      std::cout << "TO FEW HITS SELECTED" << std::endl;
+      return false;
+    }
+  }
+
+  Amg::Vector3D pos = seg.position(); 
+//  Amg::Vector3D dir = seg.direction(); 
+
+  double S(0),Sy(0),Sz(0);
+  double Zc,Yc;
+  std::vector<double> y(N);
+  std::vector<double> x(N);
+  std::vector<double> z(N);
+  std::vector<double> r(N);
+  std::vector<double> sr(N);
+  std::vector<double> w(N);
+  std::vector<double> rw(N);
+  int ii;
+  int jj;
+  {
+    MuonCalibSegment::MdtHitIt hit = seg.mdtHOTBegin();
+
+    ii=0;
+    jj=0;
+    while(hit != seg.mdtHOTEnd()){
+      const MdtCalibHitBase& h = **hit;
+      y[ii] = getY( h.localPosition() );
+      z[ii] = getZ( h.localPosition() );
+      r[ii] = std::abs( h.driftRadius() );
+      
+      if(h.sigma2DriftRadius() > 0){
+	w[ii] = 1./( h.sigma2DriftRadius() );
+	sr[ii] =sqrt( h.sigma2DriftRadius() );
+      } else {
+	w[ii] = 0.;
+	sr[ii]=0.;
+      }
+      if(m_debug)
+	std::cout << "MuCCaFitter:  (" << x[ii] << "," << y[ii] << ")  R = " << r[ii]
+		  << " W " << w[ii] << std::endl;
+      rw[ii]  = r[ii]*w[ii];
+      if(selection[jj]){
+	++hit;++jj;
+	continue;
+      }
+      S+=w[ii];
+      Sz+= w[ii]*z[ii];
+      Sy+= w[ii]*y[ii];
+      ++hit;++ii;++jj;
+    }
+  }
+  Zc = Sz/S;
+  Yc = Sy/S;
+
+  MuCCaFitterImplementation *Fitter=new MuCCaFitterImplementation();
+  if(m_debug){
+  for (int i = 0; i != ii; i++)  
+    {  
+     std::cout<<"      MuCCaFitter hits passed to computepam Z=" 
+              <<x[i]<<" phi="<<y[i]<<" zzz="<<z[i]<<" drift="<<r[i]<<" error="<<w[i]<<std::endl;  
+    } 
+  }
+  Fitter->Computeparam3(ii,z,y,r,sr);
+  if(m_debug){
+    std::cout<<"      MuCCaFitter computed track a= "<<Fitter->get_a()
+	     <<" da= "<<Fitter->get_da()
+	     <<" b= "<<Fitter->get_b()
+	     <<" db= "<<Fitter->get_db()
+	     <<" corrab= "<<Fitter->get_corrab()
+	     <<" chi2f= "<<Fitter->get_chi2f()
+	     <<std::endl;  
+  }
+
+  double afit=Fitter->get_a();
+  //double dafit=Fitter->get_da();
+  //double bfit=Fitter->get_b();
+  //double dbfit=Fitter->get_db();
+  double chi2f=Fitter->get_chi2f();
+
+  std::vector<double> dist(N);
+  std::vector<double> ddist(N);
+  double R,dis;
+  double theta = atan(afit);
+  if(theta<0.) theta= M_PI+theta;
+  double sinus = sin(theta);
+  double cosin = cos(theta);
+  double d = -( getZ( pos )-Zc)*sinus+( getY( pos )-Yc)*cosin;
+  if(m_debug){
+    std::cout << "MuCCaFitter>>> theta= " << theta << " sinus= " << sinus << " cosin= " << cosin << std::endl;
+    std::cout << "MuCCaFitter>>> getZ( pos )= " << getZ( pos ) << " getY( pos )= " << getY( pos ) << " Zc= " << Zc << " Yc= " << Yc<< std::endl;
+  }
+  double Szz(0),Syy(0),Szy(0),Syyzz(0),Att(0);
+  R=0;
+  for(int i=0;i<N;++i){
+    if(selection[i]) continue;
+    Szz   += (z[i]-Zc)*(z[i]-Zc)*w[i];
+    Syy   += (y[i]-Yc)*(y[i]-Yc)*w[i];
+    Szy   += (y[i]-Yc)*(z[i]-Zc)*w[i];
+    Syyzz += ((y[i]-Yc)-(z[i]-Zc))*((y[i]-Yc)+(z[i]-Zc))*w[i];    
+    dis = (y[i]-Yc)*cosin-(z[i]-Zc)*sinus;
+    if(dis>d){
+      R  -= rw[i];
+    }else{
+      R  += rw[i];
+    }
+    //    std::cout << "MuCCaFitter>>> d= " << d <<" z[i]= "<<z[i] <<" y[i]= "<<y[i]<< " dis= " << dis << " R= " << R << " rw[i]= " << rw[i]<< std::endl;
+  }
+  Att = Syy + cosin*(2*sinus*Szy - cosin*Syyzz);
+  d = R/S;
+  if(m_debug)
+      std::cout << "MuCCaFitter>>> d= " << d << " R= " 
+                << R << " S= " << S << " Att= " << Att << std::endl;
+  for(int i=0;i<N;++i){
+    if(selection[i]) continue;
+    dist[i] = cosin*(y[i]-Yc) - sinus*(z[i]-Zc) - d;
+    double dth = -(sinus*(y[i]-Yc) + cosin*(z[i]-Zc))*(sqrt(1./Att));
+    ddist[i] = sqrt( dth*dth + (1./S) );  
+  }
+  if(m_debug) std::cout << "Transforming back to real world" << std::endl;
+  Amg::Vector3D ndir = getVec( 0., sinus, cosin );
+  Amg::Vector3D npos = getVec( 0., Yc + cosin*d, Zc - sinus*d );
+  
+  if(m_debug) std::cout << "New line: position " << npos << " direction " << ndir << " chi2f " << chi2f << std::endl;
+   
+   seg.set( chi2f/(N-2), npos, ndir );
+   
+   MuonCalibSegment::MdtHitIt it = seg.mdtHOTBegin();
+   
+   int i(0);
+   while(it!=seg.mdtHOTEnd()){
+     MdtCalibHitBase& hit = const_cast< MdtCalibHitBase& >( **it );
+     
+     hit.setDistanceToTrack( dist[i], ddist[i] );
+     //     std::cout << "MuCCaFitter>>> dist[i] " << dist[i] <<" dis= "<<dis<<" ddist= "<< ddist[i] << std::endl;
+     ++it;++i;
+   }
+   
+   delete Fitter;
+   if(m_debug) std::cout << "fit done" << std::endl;
+   return true;
+}
+void MuCCaFitterImplementation::Computeparam3(int number_of_hits,std::vector<double> x,std::vector<double> y,std::vector<double> r,std::vector<double> sr)
+{
+/***************************************/
+/* Fit a line to n=number_of_hits hits */
+/***************************************/ 
+  double xout[100],yout[100];
+  //  double grada[4],gradb[4];
+  double dist[100],rsub[100];
+  double chi2outn[4],chi2min;
+  //  double chip[4];
+  double aref[4],bref[4];
+  //  double sigmaa[4],sigmab[4];
+  int fhit,i,j,icouple=0,lhit;
+  //  int segnobf[4];
+  //  double da,db,hesseb,hessea,hesseab,chi2fin; 
+    //  for (int i = 0; i != number_of_hits; i++)  
+    //    {  
+    //     std::cout<<"      MuCCaFitterImplementation hits passed to computepam Z=" 
+    //              <<x[i]<<" phi="<<y[i]<<" drift="<<r[i]<<" error="<<sr[i]<<std::endl;  
+    //    } 
+/* compute 4 tanget lines from first and last hit */  
+  fhit = 0;
+  lhit = number_of_hits-1;
+  //  Computelinparnew(x[fhit],y[fhit],r[fhit],sr[fhit],x[lhit],y[lhit],r[lhit],sr[lhit]);
+  Computelinparnew(x[fhit],y[fhit],r[fhit],x[lhit],y[lhit],r[lhit]);
+  for(int ii=0;ii<4;ii++){
+    bref[ii]=m_bfpar[ii];
+    aref[ii]=m_angularcoefficient[ii];
+  }
+/* choose the REFERENCE LINE (aref[icouple],bref[icouple])*/
+  for(i=0;i<4;i++){
+     for(j=0;j<number_of_hits;j++){
+        double d;
+        d = fabs(aref[i]*x[j]+bref[i]-y[j]); 
+        dist[j] = d/sqrt(1.+aref[i]*aref[i]);
+        rsub[j] = r[j]-dist[j];
+     }
+     double chi2out = 0;
+     for(int ii=1;ii<number_of_hits-1;ii++){
+       chi2out += rsub[ii]*rsub[ii]/(sr[ii]*sr[ii]);
+     } 
+     chi2outn[i]=chi2out;
+  }
+  chi2min = 999999999.;
+  for(i=0;i<4;i++){
+     if(chi2outn[i]<chi2min){
+         chi2min = chi2outn[i];
+         icouple = i;
+     }
+  } 
+/* Compute TRACK POINTS */
+  Computehitpsemes(number_of_hits,x,y,r,aref[icouple],bref[icouple]);
+  for(i=0;i<number_of_hits;i++){
+   xout[i]=m_xpoint[i];
+   yout[i]=m_ypoint[i];
+  }
+/* Compute a & b parameters of the track from TRACK POINTS */
+  // int idim;
+  //  ifail;
+  double aoutn, bout, sig2a, sig2b, corrab;
+  double temp,det; 
+  double hesse[2][2];
+  double W,WX,WX2,WY,WY2,WXY;
+  //  double errormatrix[2][2];
+  W=0.;
+  WX=0.;
+  WX2=0.;
+  WY=0.;
+  WY2=0.;
+  WXY=0;
+  for(int i=0;i<number_of_hits;i++){
+    temp = 1./(sr[i]*sr[i]);
+    W  += temp;
+    WX += xout[i]*temp;
+    WX2+= xout[i]*xout[i]*temp;
+    WY += yout[i]*temp;
+    WY2+= yout[i]*yout[i]*temp;
+    WXY+= xout[i]*yout[i]*temp;
+  }
+  det = W*WX2-WX*WX;
+  aoutn       = (W*WXY-WY*WX)/det;
+  bout        = (WY*WX2-WX*WXY)/det;
+  hesse[1][1] = W;
+  hesse[0][0] = WX2;
+  hesse[1][0] = WX;
+  hesse[0][1] = WX;
+  // idim        = 2;
+/* invert hessian matrix */
+  hesse[1][1] = hesse[0][0]/det;
+  hesse[0][0] = hesse[1][1]/det;
+  hesse[1][0] = -1.*(hesse[0][1]/det);
+  hesse[0][1] = -1.*(hesse[0][1]/det);
+  sig2a = hesse[0][0];
+  sig2b = hesse[1][1];
+  corrab = hesse[1][0];
+  double deno,btest,bs1,bs2,db1,db2;
+  btest = bout;
+  bout   = 0;
+  deno = 0;
+  for(int i=0;i<number_of_hits;i++){
+     bs1 = (y[i]-aoutn*x[i]-r[i]*sqrt(1+aoutn*aoutn));
+     bs2 = (y[i]-aoutn*x[i]+r[i]*sqrt(1+aoutn*aoutn));
+     db1 = fabs(bs1-btest);
+     db2 = fabs(bs2-btest);
+     if(db1<db2){
+       bout  += bs1/(sr[i]*sr[i]); 
+     }else{
+       bout  +=bs2/(sr[i]*sr[i]);
+     } 
+     deno+= 1/(sr[i]*sr[i]);
+  }
+  bout /=deno;
+/* compute chi2 from residuals*/
+  double resd;
+  double chi2f = 0;
+  for(int i=0;i<number_of_hits;i++){ 
+     double xi,yi;
+     xi = (aoutn*y[i]-aoutn*bout+x[i])/(1.+aoutn*aoutn);
+     yi = aoutn*xi+bout;
+     resd = (sqrt((xi-x[i])*(xi-x[i])+(yi-y[i])*(yi-y[i]))-r[i])/sr[i];
+     chi2f += resd*resd;
+ }
+/* set global variables (method output)*/
+  m_aoutn=aoutn;
+  m_sig2a=sig2a;
+  m_bout=bout;
+  m_sig2b=sig2b;
+  m_corrab=corrab;
+  //  if(fabs(atan(aoutn))>1.5) chi2f=100000000;
+  m_chi2f=chi2f;
+  //  std::cout<<"      MuCCaFitter::Computeparam3 computed track a= "<<m_aoutn
+  //	   <<" da= "<<m_sig2a
+  //	   <<" b= "<<m_bout
+  //	   <<" db= "<<m_sig2b
+  //	   <<" corrab= "<<m_corrab
+  //	   <<" chi2f= "<<m_chi2f
+  //	   <<std::endl;  
+}
+
+double MuCCaFitterImplementation::get_a() 
+{
+  return m_aoutn;
+}
+double MuCCaFitterImplementation::get_b() {return m_bout;}
+double MuCCaFitterImplementation::get_da() {return m_sig2a;}
+double MuCCaFitterImplementation::get_db() {return m_sig2b;}
+double MuCCaFitterImplementation::get_corrab() {return m_corrab;}
+double MuCCaFitterImplementation::get_chi2f() {return m_chi2f;}
+
+void MuCCaFitterImplementation::Computelinparnew(double x1, double y1, double r1, double x2, double y2, double r2)
+{
+/********************************************/
+/* Compute the 4 lines tangent to 2 circles */
+/********************************************/
+   double delta;
+   double averagephi,dist,dphiin,dphiex;
+   double bpar[4],phi;
+   double bfparn[2];
+   // int segnobfn[2];
+   // int segnoc[2][4],ncandid[4],ncand;
+   int ncandid[4],ncand;
+   double bcand[2][4];
+   int segnob[]={1,-1,1,-1};
+   int firsttime,i;
+   double angularcoefficient[4];
+   double bfpar[4];
+   // int segnobf[4];
+   double dy, dx;
+
+/* compute a parameters */
+   dx = x2-x1;
+   dy = y2-y1;
+   averagephi = atan2(dy,dx);
+   dist = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); 
+   delta = r2+r1;
+
+   dphiin = asin(delta/dist);
+
+   delta = r2-r1;
+   dphiex = asin(delta/dist);
+
+   int f=1;
+   phi = averagephi+f*dphiex;
+   if(phi < 0){phi = 6.2831853+(phi);}
+   angularcoefficient[0] = tan(phi);
+
+   f=-1;
+   phi = averagephi+f*dphiex;
+   if(phi < 0){phi = 6.2831853+(phi);}
+   angularcoefficient[1] = tan(phi);
+
+   f=1;
+   phi = averagephi+f*dphiin;
+   if(phi < 0){phi = 6.2831853+(phi);}
+   angularcoefficient[2] = tan(phi);
+
+   f=-1;
+   phi = averagephi+f*dphiin;
+   if(phi < 0){phi = 6.2831853+(phi);}
+   angularcoefficient[3] = tan(phi);
+
+/* Compute b parameters */
+   for(i=0;i<4;i++){
+     bpar[0] = y1-angularcoefficient[i]*x1+segnob[0]*r1*
+               sqrt(1+angularcoefficient[i]*angularcoefficient[i]);
+     bpar[1] = y1-angularcoefficient[i]*x1+segnob[1]*r1*
+               sqrt(1+angularcoefficient[i]*angularcoefficient[i]);
+     bpar[2] = y2-angularcoefficient[i]*x2+segnob[2]*r2*
+               sqrt(1+angularcoefficient[i]*angularcoefficient[i]);
+     bpar[3] = y2-angularcoefficient[i]*x2+segnob[3]*r2*
+               sqrt(1+angularcoefficient[i]*angularcoefficient[i]);
+     double delta = 0.00001;
+     ncand = 0;
+     if(fabs(bpar[0]-bpar[2])<delta){
+       bfparn[ncand]= bpar[0];
+       // segnobfn[ncand] = segnob[0];
+       ncand           = ncand+1;     
+     }
+     if(fabs(bpar[0]-bpar[3])<delta){
+       bfparn[ncand]   = bpar[0];
+       // segnobfn[ncand] = segnob[0];
+       ncand           = ncand+1;     
+     }
+     if(fabs(bpar[1]-bpar[2])<delta){
+       bfparn[ncand]   = bpar[1];
+       // segnobfn[ncand] = segnob[1];
+       ncand           = ncand+1;     
+     }
+     if(fabs(bpar[1]-bpar[3])<delta){
+       bfparn[ncand]   = bpar[1];
+       //  segnobfn[ncand] = segnob[1];
+       ncand           = ncand+1;
+     }
+       bcand[0][i]  = bfparn[0];
+       bcand[1][i]  = bfparn[1];
+       // segnoc[0][i] = segnobfn[0];
+       // segnoc[1][i] = segnobfn[1];
+       ncandid[i]   = ncand;
+     }
+     firsttime = 0;
+     for(i=0;i<4;i++){
+       if(ncandid[i]==1){
+         bfpar[i] = bcand[0][i];
+         // segnobf[i] = segnoc[0][i];
+       }else{
+         bfpar[i] = bcand[firsttime][i];
+         // segnobf[i] = segnoc[firsttime][i];
+         firsttime++;
+       }
+     }
+/* set global variables (method output)*/
+   for(i=0;i<4;i++){
+     m_bfpar[i]=bfpar[i];
+     m_angularcoefficient[i]=angularcoefficient[i];
+   }
+}
+
+void MuCCaFitterImplementation::Computelin(double x1, double y1, double r1, double x2, double y2, double r2)
+{
+/********************************************/
+/* Compute the 4 lines tangent to 2 circles */
+/********************************************/
+   double delta;
+   double averagephi,dist,dphiin,dphiex;
+   double bpar[4],phi;
+   //   double distfp[4];
+   double bfparn[2];
+   double bcand[2][4];
+   // int segnobf[4],segnobfn[2];
+   //   double sol[4];
+   int segnob[]={1,-1,1,-1};
+   // int segnoc[2][4],ncandid[4],ncand;
+   int ncandid[4],ncand;
+   int i,firsttime; 
+   double angularcoefficient[4];
+   double bfpar[4];
+   double dy, dx;
+
+/* compute a parameters */
+   dx = x2-x1;
+   dy = y2-y1;
+   averagephi = atan2(dy,dx);
+   dist = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); 
+
+   delta = r2+r1;
+   dphiin = asin(delta/dist);
+
+   delta = r2-r1;
+   dphiex = asin(delta/dist);
+
+   int f=1;
+   phi = averagephi+f*dphiex;
+   if(phi < 0){phi = 6.2831853+(phi);}
+   angularcoefficient[0] = tan(phi);
+
+   f=-1;
+   phi = averagephi+f*dphiex;
+   if(phi < 0){phi = 6.2831853+(phi);}
+   angularcoefficient[1] = tan(phi);
+
+   f=1;
+   phi = averagephi+f*dphiin;
+   if(phi < 0){phi = 6.2831853+(phi);}
+   angularcoefficient[2] = tan(phi);
+
+   f=-1;
+   phi = averagephi+f*dphiin;
+   if(phi < 0){phi = 6.2831853+(phi);}
+   angularcoefficient[3] = tan(phi);
+
+/* Compute b parameters */
+   for(i=0;i<4;i++){
+     bpar[0] = y1-angularcoefficient[i]*x1+segnob[0]*r1*
+               sqrt(1+angularcoefficient[i]*angularcoefficient[i]);  
+     bpar[1] = y1-angularcoefficient[i]*x1+segnob[1]*r1*
+               sqrt(1+angularcoefficient[i]*angularcoefficient[i]);
+     bpar[2] = y2-angularcoefficient[i]*x2+segnob[2]*r2*
+               sqrt(1+angularcoefficient[i]*angularcoefficient[i]);
+     bpar[3] = y2-angularcoefficient[i]*x2+segnob[3]*r2*
+               sqrt(1+angularcoefficient[i]*angularcoefficient[i]);
+     double delta = 0.00001;
+     ncand = 0;
+     if(fabs(bpar[0]-bpar[2])<delta){
+       bfparn[ncand]  = bpar[0];
+       // segnobf[ncand] = segnob[0];
+       ncand          = ncand+1;     
+     }
+     if(fabs(bpar[0]-bpar[3])<delta){
+       bfparn[ncand]  = bpar[0];
+       // segnobf[ncand] = segnob[0];
+       ncand          = ncand+1;     
+     }
+     if(fabs(bpar[1]-bpar[2])<delta){
+       bfparn[ncand]  = bpar[1];
+       // segnobf[ncand] = segnob[1];
+       ncand          = ncand+1;     
+     }
+     if(fabs(bpar[1]-bpar[3])<delta){
+       bfparn[ncand]  = bpar[1];
+       // segnobf[ncand] = segnob[1];
+       ncand          = ncand+1;
+     }
+     bcand[0][i]  = bfparn[0];
+     bcand[1][i]  = bfparn[1];
+     // segnoc[0][i] = segnobfn[0];
+     // segnoc[1][i] = segnobfn[1];
+     ncandid[i]   = ncand;
+   }
+   firsttime = 0;
+   for(i=0;i<4;i++){
+     if(ncandid[i]==1){
+       bfpar[i]   = bcand[0][i];
+       // segnobf[i] = segnoc[0][i];
+     }else{
+       bfpar[i]   = bcand[firsttime][i];
+       // segnobf[i] = segnoc[firsttime][i];
+       firsttime++;
+     }
+   }
+/* set global variables (method output)*/
+   for(int i=0; i<4; i++){
+     m_bfpar[i]=bfpar[i];
+     m_angularcoefficient[i]=angularcoefficient[i];
+   }
+}
+void MuCCaFitterImplementation::Computehitpsemes(int nhit,std::vector<double> xcirc, std::vector<double> ycirc, std::vector<double>rcirc, double a, double b)
+{
+/************************/
+/* Compute TRACK POINTS */
+/************************/
+    int i,nhitc;
+    //    double xpoint[nhit],ypoint[nhit];
+/* loop over hit couples */
+    nhitc = nhit/2;
+    for(i=0;i<nhitc;i++){
+/* Compute TRACK POINTS for 2 circles */
+       computehitsfromcircles(xcirc[2*i],ycirc[2*i],rcirc[2*i],xcirc[2*i+1],ycirc[2*i+1],rcirc[2*i+1],a,b);
+       m_xpoint[2*i]=m_xout0;
+       m_ypoint[2*i]=m_yout0;
+       m_xpoint[2*i+1]=m_xout1;
+       m_ypoint[2*i+1]=m_yout1;
+    }
+    if(2*nhitc!=nhit){
+/* Compute TRACK POINTS for 2 circles */
+       computehitsfromcircles(xcirc[nhit-2],ycirc[nhit-2],rcirc[nhit-2],xcirc[nhit-1],ycirc[nhit-1],rcirc[nhit-1],a,b);
+       m_xpoint[nhit-2]=m_xout0;
+       m_ypoint[nhit-2]=m_yout0;
+       m_xpoint[nhit-1]=m_xout1;
+       m_ypoint[nhit-1]=m_yout1;
+    }
+}
+
+void MuCCaFitterImplementation::computehitsfromcircles(double x0,double y0,double r0,double x1,double y1,double r1,double a,double b)
+{
+/**************************************/
+/* Compute TRACK POINTS for 2 circles */
+/**************************************/
+  double ang[4],bpar[4];
+  int i;
+  double xout0=0,yout0=0;
+  double xout1=0,yout1=0;
+  double dist,dist1,xint,yint,xref,yref;
+
+/* Compute the 4 lines tangent to 2 circles */
+  Computelin(x0,y0,r0,x1,y1,r1);
+  for(i=0;i<4;i++){
+    bpar[i]=m_bfpar[i];
+    ang[i]=m_angularcoefficient[i];
+  }
+
+  dist = 9999999;
+/* for each of the 4 tangents : */
+  for(i=0;i<4;i++){
+/* compute tangent point */
+     xint = (x0+ang[i]*y0-ang[i]*bpar[i])/(1+ang[i]*ang[i]);
+     yint = ang[i]*(xint)+bpar[i];
+/* compute point from reference line */
+   double bprime;
+   if(a!=0){
+     bprime = y0+x0/a;
+     xref = (bprime-b)*a/(a*a+1);
+     yref = (b+bprime*a*a)/(a*a+1);
+   }else{
+     xref = x0;
+     yref = b; 
+   }
+/* choose tangent point closest to that of the reference lines (TRACK POINT)*/
+   dist1 = sqrt((xint-xref)*(xint-xref)+(yint-yref)*(yint-yref));
+   if(dist1<dist){
+     dist   = dist1;
+     xout0 = xint;
+     yout0 = yint; 
+   }
+  }
+  dist = 9999999;
+  for(i=0;i<4;i++){
+/* compute tangent point */
+     xint = (x1+ang[i]*y1-ang[i]*bpar[i])/(1+ang[i]*ang[i]);
+     yint = ang[i]*(xint)+bpar[i];
+/* compute point from reference line */
+   double bprime;
+   if(a!=0){
+     bprime = y1+x1/a;
+     xref = (bprime-b)*a/(a*a+1);
+     yref = (b+bprime*a*a)/(a*a+1);
+   }else{
+     xref = x1;
+     yref = b; 
+   }
+/* choose tangent point closest to that of the reference line (TRACK POINT)*/
+   dist1 = sqrt((xint-xref)*(xint-xref)+(yint-yref)*(yint-yref));
+   if(dist1<dist){
+     dist   = dist1;
+     xout1 = xint;
+     yout1 = yint; 
+   }
+  }
+/* set global variables (method output)*/
+  m_xout0=xout0;
+  m_yout0=yout0;
+  m_xout1=xout1;
+  m_yout1=yout1;  
+}
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/QuasianalyticLineReconstruction.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/QuasianalyticLineReconstruction.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..8de996c1286f3d73c7406a9fce58249c227b20e0
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/QuasianalyticLineReconstruction.cxx
@@ -0,0 +1,947 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 01.03.2006, AUTHOR: OLIVER KORTNER
+// Modified: 15.07.2006 by O. Kortner, error calculation corrected,
+//                                     chi^2 refit functionality added.
+//           13.01.2007 by O. Kortner, bug fix in candidate treatment, some
+//                                     candidates were considered to be
+//                                     identical although different;
+//                                     modifications to improve the
+//                                     reconstruction efficiency at very high
+//                                     background count rates.
+//           27.03.2007 by O. Kortner, distances with signs filled into
+//                                     MuonCalibSegment.
+//           23.03.2007 by O. Kortner, isnan check for chi^2.
+//           08.06.2007 by O. Kortner, final track segment has rphi position and
+//                                     direction of the initial segment.
+//           23.06.2006 by O. Kortner, add convention for rphi track if the
+//                                     pattern recognition has failed to
+//                                     provide it.
+//           26.11.2007 by O. Kortner, fix for segment refinement.
+//           13.12.2007 by O. Kortner, time-out added.
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+#include "MdtCalibFitters/QuasianalyticLineReconstruction.h"
+#include <iostream>
+#include <fstream>
+#include "CLHEP/GenericFunctions/CumulativeChiSquare.hh"
+#include "CLHEP/Units/SystemOfUnits.h"
+#include "CLHEP/Units/PhysicalConstants.h"
+#include "time.h"
+#include <cmath>
+
+//:::::::::::::::::::::::
+//:: NAMESPACE SETTING ::
+//:::::::::::::::::::::::
+
+using namespace MuonCalib;
+using namespace std;
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: IMPLEMENTATION OF METHODS DEFINED IN THE CLASS ::
+//::         QuasianalyticLineReconstruction        ::
+//::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+//*****************************************************************************
+
+//:::::::::::::::::::
+//:: METHOD m_init ::
+//:::::::::::::::::::
+
+void QuasianalyticLineReconstruction::m_init(void) {
+
+	m_init(0.5*CLHEP::mm); // default road width = 0.5 CLHEP::mm
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: METHOD m_init(const double & r_road_width) ::
+//:::::::::::::::::::::::::::::::::::::::::::::::::::
+
+void QuasianalyticLineReconstruction::m_init(const double & r_road_width) {
+
+//:::::::::::::::
+//:: VARIABLES ::
+//:::::::::::::::
+
+	Amg::Vector3D null_vec(0.0, 0.0, 0.0); // auxiliary 0 vector
+
+//::::::::::::::::::
+//:: SET TIME-OUT ::
+//::::::::::::::::::
+
+	m_time_out = 10.0;
+
+//::::::::::::::::::::::::::::
+//:: SET THE MAXIMUM RADIUS ::
+//::::::::::::::::::::::::::::
+
+	m_r_max = 15.0;
+
+//::::::::::::::::::::::::
+//:: SET THE ROAD WIDTH ::
+//::::::::::::::::::::::::
+
+	m_road_width = r_road_width;
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: INITIALIZE PRIVATE VARIABLES WHICH ARE ACCESSIBLE BY METHODS ::
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+	m_nb_track_hits = 0;
+	m_chi2 = 0.0;
+	m_track = MTStraightLine(null_vec, null_vec, null_vec, null_vec);
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: SET THE TRACK IN THE x1-x3 PLANE (LATER VERSION MAY ALLOW TO SET ::
+//:: USER-DEFINED VALUES)                                             ::
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+	m_m_x1 = 1.0; m_b_x1 = 0.0;
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::
+//:: METHOD tangent ::
+//::::::::::::::::::::
+
+MTStraightLine QuasianalyticLineReconstruction::tangent(
+		const Amg::Vector3D & r_w1,
+		const double & r_r1, const double & r_sigma12,
+		const Amg::Vector3D & r_w2, const double & r_r2,
+		const double & r_sigma22, const int & r_case) const {
+
+//:::::::::::::::
+//:: VARIABLES ::
+//:::::::::::::::
+
+	double sinalpha; // auxiliary sinus of an angle
+	double cosalpha; // auxiliary sinus of an angle
+	Amg::Vector3D e2prime(0.,0.,0.), e3prime(0.,0.,0.); // auxiliary direction vectors
+	MTStraightLine tang; // tangent to drift circles of a hit pair
+	Amg::Vector3D p1(0.,0.,0.), p2(0.,0.,0.); // hit points defining a tangent
+	Amg::Vector3D null_vec(0.0, 0.0, 0.0); // auxiliary 0 vector
+	double mx1, bx1, mx2, bx2; // auxiliary track parameters
+
+//::::::::::::::::::::::::::::::::::::::::::::
+//:: CHECK WHETHER THE SELECTED CASE EXISTS ::
+//::::::::::::::::::::::::::::::::::::::::::::
+
+	if (r_case<1 || r_case>4) {
+		cerr << endl
+			<< "Class QuasianalyticLineReconstruction, "
+			<< "method tangent: ERROR!\n"
+			<< "Illegal case " << r_case << ", must be 1,2,3, or 4."
+			<< endl;
+		exit(1);
+	}
+
+//:::::::::::::::::::::::::::::::::::::
+//:: CALCULATE THE REQUESTED TANGENT ::
+//:::::::::::::::::::::::::::::::::::::
+
+// local coordinate axis vectors //
+	e3prime = (r_w2-r_w1).unit();
+	e2prime = Amg::Vector3D(0.0, e3prime.z(), -e3prime.y());
+
+// case 1 and 2 //
+	if (r_case==1 || r_case==2) {
+
+		sinalpha = fabs(r_r2-r_r1)/(r_w2-r_w1).mag();
+		cosalpha = sqrt(1.0-sinalpha*sinalpha);
+
+   // case 1 //
+		if (r_case==1) {
+			p1 = r_w1+((1 && r_r2>=r_r1)-(1 && r_r2<r_r1))*r_r1*
+					(cosalpha*e2prime-sinalpha*e3prime);
+			p2 = r_w2+((1 && r_r2>=r_r1)-(1 && r_r2<r_r1))*r_r2*
+					(cosalpha*e2prime-sinalpha*e3prime);
+		}
+
+   // case 2 //
+		if (r_case==2) {
+			p1 = r_w1-((1 && r_r2>=r_r1)-(1 && r_r2<r_r1))*r_r1*
+					(cosalpha*e2prime+sinalpha*e3prime);
+			p2 = r_w2-((1 && r_r2>=r_r1)-(1 && r_r2<r_r1))*r_r2*
+					(cosalpha*e2prime+sinalpha*e3prime);
+		}
+
+
+	}
+
+// case 3 and 4 //
+	if (r_case==3  || r_case==4) {
+
+		sinalpha = (r_r1+r_r2)/(r_w2-r_w1).mag();
+		cosalpha = sqrt(1.0-sinalpha*sinalpha);
+
+   // case 3 //
+		if (r_case==3) {
+// 			p1 = r_w1+r_r1*(cosalpha*e2prime-sinalpha*e3prime);
+// 			p2 = r_w2-r_r2*(cosalpha*e2prime-sinalpha*e3prime);
+			p1 = r_w1+r_r1*(cosalpha*e2prime+sinalpha*e3prime);
+			p2 = r_w2-r_r2*(cosalpha*e2prime+sinalpha*e3prime);
+		}
+
+   // case 4 //
+		if (r_case==4) {
+			p1 = r_w1-r_r1*(cosalpha*e2prime-sinalpha*e3prime);
+			p2 = r_w2+r_r2*(cosalpha*e2prime-sinalpha*e3prime);
+		}
+
+	}
+
+// calculation of the tangent and estimation of its errors //
+	if ((p2-p1).z()!=0.0) {
+		tang = MTStraightLine(p1, p2-p1, null_vec, null_vec);
+	} else {
+		Amg::Vector3D direction(p2-p1);
+		direction[2] = 1.0e-99;
+		tang = MTStraightLine(p1, direction, null_vec, null_vec);	
+	}
+	mx1 = tang.m_x1(); bx2 = tang.b_x1();
+	mx2 = tang.m_x2(); bx2 = tang.b_x2();
+	tang = MTStraightLine(mx1, bx1, mx2, bx2,1.0, 1.0, 
+			sqrt(r_sigma12+r_sigma22)/fabs(p2.z()-p1.z()),
+			sqrt(r_sigma12+p1.z()*p1.z()*(r_sigma12+r_sigma22)/
+						std::pow(p2.z()-p1.z(), 2)));
+			// errors in mx1 and bx1 are arbitrary since they are
+			// not used at a later stage.
+
+
+	return tang;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::
+//:: METHOD m_track_candidate ::
+//::::::::::::::::::::::::::::::
+
+MTStraightLine QuasianalyticLineReconstruction::m_track_candidate(
+				const IndexSet & r_index_set,
+				const int & r_k_cand,
+				const int & r_l_cand,
+				const int & r_cand_case,
+				vector<Amg::Vector3D> r_w,
+				vector<double> r_r,
+				vector<double> r_sigma2,
+				double & r_chi2) const {
+
+//:::::::::::::::
+//:: VARIABLES ::
+//:::::::::::::::
+
+	int nb_hits(r_index_set.size()); // number of hits used in the track
+					    // reconstruction
+	int nb_tangents(0); // number of tangents used in the track
+			       // reconstruction
+	vector<double> mx1, bx1, mx2, bx2; // slopes and intercepts of the
+					      // tangents building the track
+	vector<double> mx1_err, bx1_err, mx2_err, bx2_err; // their errors
+	MTStraightLine aux_track; // auxiliary straight line
+	MTStraightLine tang; // tangent to drift circles of a hit pair
+	Amg::Vector3D d1(0.0, 0.0, 0.0), d2(0.0, 0.0, 0.0); // auxiliary distance vectors
+	Amg::Vector3D e2prime(0.0, 0.0, 0.0), e3prime(0.0, 0.0, 0.0); // auxiliary basis vectors
+	Amg::Vector3D a(0.0, 0.0, 0.0), u(0.0, 0.0, 0.0); // position and direction vector of the candidate
+			 // tangent
+	double sinalpha; // auxiliary sinus of an angle
+	double cosalpha; // auxiliary sinus of an angle
+	Amg::Vector3D p1(0.0, 0.0, 0.0), p2(0.0, 0.0, 0.0); // hit points defining a tangent
+	Amg::Vector3D null_vec(0.0, 0.0, 0.0); // auxiliary 0 vector
+	double sum[4]; // auxiliary summation variables
+
+//:::::::::::::::::::::
+//:: GET THE TANGENT ::
+//:::::::::::::::::::::
+
+// calculate the tangent //
+	aux_track = tangent(r_w[r_k_cand], r_r[r_k_cand], r_sigma2[r_k_cand],
+			r_w[r_l_cand], r_r[r_l_cand], r_sigma2[r_l_cand],
+			r_cand_case);
+	a = aux_track.positionVector();
+	u = (aux_track.directionVector()).unit();
+
+// store the parameters of this tangent //
+	mx1.push_back(aux_track.m_x1());
+	mx1_err.push_back(aux_track.m_x1_error());
+	bx1.push_back(aux_track.b_x1());
+	bx1_err.push_back(aux_track.b_x1_error());
+	mx2.push_back(aux_track.m_x2());
+	mx2_err.push_back(aux_track.m_x2_error());
+	bx2.push_back(aux_track.b_x2());
+	bx2_err.push_back(aux_track.b_x2_error());
+
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: LOOP OVER THE OTHER HITS AND CALCULATE TANGENTS ::                                                            //
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+	for (int kk=0; kk<nb_hits-1; kk++) {
+	for (int ll=kk+1; ll<nb_hits; ll++) {
+
+		int k(r_index_set[kk]);
+		int l(r_index_set[ll]);
+
+		if (k==r_k_cand && l==r_l_cand) {
+			continue;
+		}
+
+// local coordinate axis vectors //
+		e3prime = (r_w[l]-r_w[k]).unit();
+		e2prime = Amg::Vector3D(0.0, e3prime.z(), -e3prime.y());
+
+// distance vectors //
+		d1 = (r_w[k]-a).dot(u)*u-(r_w[k]-a); d1[0] = (0.0);
+		d2 = (r_w[l]-a).dot(u)*u-(r_w[l]-a); d2[0] = (0.0);
+
+// one must distinguish 2 cases //
+
+   // case 1: candidate tangent passes both wires on the same side //
+		if (d1.dot(d2)>=0) {
+
+			sinalpha = fabs(r_r[l]-r_r[k])/(r_w[l]-r_w[k]).mag();
+			cosalpha = sqrt(1.0-sinalpha*sinalpha);
+
+			if (d1.dot(e2prime)>=0) {
+				if (r_r[k]<=r_r[l]) {
+					p1 = r_w[k]+r_r[k]*(cosalpha*e2prime-
+						sinalpha*e3prime);
+				} else {
+					p1 = r_w[k]+r_r[k]*(cosalpha*e2prime+
+						sinalpha*e3prime);
+				}
+			}
+			else {
+				if (r_r[k]>=r_r[l]) {
+					p1 = r_w[k]-r_r[k]*(cosalpha*e2prime-
+						sinalpha*e3prime);
+				} else {
+					p1 = r_w[k]-r_r[k]*(cosalpha*e2prime+
+						sinalpha*e3prime);
+				}
+			}
+
+			if (d2.dot(e2prime)>=0) {
+				if (r_r[k]<=r_r[l]) {
+					p2 = r_w[l]+r_r[l]*(cosalpha*e2prime-
+						sinalpha*e3prime);
+				} else {
+					p2 = r_w[l]+r_r[l]*(cosalpha*e2prime+
+						sinalpha*e3prime);
+				}
+			}
+			else {
+				if (r_r[k]>=r_r[l]) {
+					p2 = r_w[l]-r_r[l]*(cosalpha*e2prime-
+						sinalpha*e3prime);
+				} else {
+					p2 = r_w[l]-r_r[l]*(cosalpha*e2prime+
+						sinalpha*e3prime);
+				}
+			}
+
+		}
+
+   // case 2: candidate tangent passes both wires on opposite sides //
+		if (d1.dot(d2)<0) {
+
+			sinalpha = (r_r[l]+r_r[k])/(r_w[l]-r_w[k]).mag();
+			cosalpha = sqrt(1.0-sinalpha*sinalpha);
+
+	// case 2(a) //
+			if (d1.dot(e2prime)>=0 && d2.dot(e2prime)<=0) {
+				p1 = r_w[k]+r_r[k]*(cosalpha*e2prime+
+							sinalpha*e3prime);
+				p2 = r_w[l]-r_r[l]*(cosalpha*e2prime+
+							sinalpha*e3prime);
+			}
+
+	// case 2(b) //
+			if (d1.dot(e2prime)<0 && d2.dot(e2prime)>=0) {
+				p1 = r_w[k]-r_r[k]*(cosalpha*e2prime-
+							sinalpha*e3prime);
+				p2 = r_w[l]+r_r[l]*(cosalpha*e2prime-
+							sinalpha*e3prime);
+			}
+
+		}
+
+// get the slope and intercept of the new tangents and error estimates //
+		if ((p2-p1).z()!=0.0) {
+			tang = MTStraightLine(p1, p2-p1, null_vec, null_vec);
+		} else {
+			Amg::Vector3D direction(p2-p1);
+			direction[2] = (1.0e-99);
+			tang = MTStraightLine(p1, direction,
+							null_vec, null_vec);
+		}
+		mx1.push_back(tang.m_x1());
+		bx1.push_back(tang.b_x1());
+		mx2.push_back(tang.m_x2());
+		bx2.push_back(tang.b_x2());
+
+		mx1_err.push_back(1.0);
+		bx1_err.push_back(1.0);
+		
+		mx2_err.push_back((r_sigma2[k]+r_sigma2[l])/
+							std::pow(p2.z()-p1.z(), 2));
+		bx2_err.push_back(r_sigma2[k]+
+				p1.z()*p1.z()*(r_sigma2[k]+r_sigma2[l])/
+						std::pow(p2.z()-p1.z(),2));
+			// errors in x1 and x2 are arbitrary since they are not
+			// used at a later stage.
+
+// increase the number of tangents //
+		nb_tangents = nb_tangents+1;
+
+	}
+	}
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: CALCULATE A WEIGHTED AVERAGE OVER THE TANGENTS AND THE chi^2 FOR ::
+//:: THE RECONSTRUCTED TRAJECTORY                                     ::
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+	sum[0] = 0.0; sum[1] = 0.0; sum[2] = 0.0; sum[3] = 0.0;
+	for (int k=0; k<nb_tangents; k++) {
+
+		if (mx2_err[k]>0) {
+			sum[0] = sum[0] + mx2[k]/mx2_err[k];
+			sum[1] = sum[1] + 1.0/mx2_err[k];
+		} else {
+			sum[0] = sum[0] + mx2[k];
+			sum[1] = sum[1] + 1.0;
+		}
+		if (bx2_err[k]>0) {
+			sum[2] = sum[2] + bx2[k]/bx2_err[k];
+			sum[3] = sum[3] + 1.0/bx2_err[k];
+		} else {
+			sum[2] = sum[2] + bx2[k];
+			sum[3] = sum[3] + 1.0;
+		}
+
+	}
+
+	aux_track = MTStraightLine(0.0, 0.0, sum[0]/sum[1], sum[2]/sum[3],
+				0.0, 1.0, sqrt(1.0/sum[1]), sqrt(1.0/sum[3]));
+
+	r_chi2 = 0.0;
+	for (int k=0; k<nb_hits; k++) {
+		r_chi2 = r_chi2+std::pow(aux_track.distFromLine(
+					r_w[r_index_set[k]])
+					-r_r[r_index_set[k]], 2)/
+								r_sigma2[k];
+	}
+
+	return aux_track;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::
+//:: METHOD roadWidth ::
+//::::::::::::::::::::::
+
+double QuasianalyticLineReconstruction::roadWidth(void) const {
+
+	return m_road_width;
+
+}
+
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::
+//:: METHOD numberOfTrackHits ::
+//::::::::::::::::::::::::::::::
+
+unsigned int QuasianalyticLineReconstruction::numberOfTrackHits(void) const {
+
+	return m_nb_track_hits;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::
+//:: METHOD trackHits ::
+//::::::::::::::::::::::
+
+const vector<const MdtCalibHitBase*> & QuasianalyticLineReconstruction::trackHits(void) const {
+
+	return m_track_hits;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: METHOD chi2 ::
+//:::::::::::::::::
+
+double QuasianalyticLineReconstruction::chi2(void) const {
+
+	if (m_nb_track_hits == 0) {
+		return -1;
+	}
+	return m_chi2;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::::::
+//:: METHOD chi2PerDegreesOfFreedom ::
+//::::::::::::::::::::::::::::::::::::
+
+double QuasianalyticLineReconstruction::chi2PerDegreesOfFreedom(
+								void) const{
+
+	if (m_nb_track_hits<3) {
+		return -1;
+	}
+	return chi2()/static_cast<double>(numberOfTrackHits()-2);
+
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::
+//:: METHOD track ::
+//::::::::::::::::::
+
+MTStraightLine QuasianalyticLineReconstruction::track(void) const {
+
+	return m_track;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::
+//:: METHOD setRoadWidth ::
+//:::::::::::::::::::::::::
+
+void QuasianalyticLineReconstruction::setRoadWidth(
+					const double & r_road_width) {
+
+	m_road_width = fabs(r_road_width);
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD setTimeOut ::
+//:::::::::::::::::::::::
+
+void QuasianalyticLineReconstruction::setTimeOut(const double & time_out) {
+
+	m_time_out = time_out;
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD setTimeOut ::
+//:::::::::::::::::::::::
+
+void setTimeOut(const double & /*time_out*/) {
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::
+//:: METHOD fit(.) ::
+//:::::::::::::::::::
+
+bool QuasianalyticLineReconstruction::fit(MuonCalibSegment & r_segment) const {
+
+// select all hits //
+	HitSelection selection(r_segment.mdtHitsOnTrack(), 0);
+
+// call the other fit function //
+	return fit(r_segment, selection);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::
+//:: METHOD fit(.,.) ::
+//:::::::::::::::::::::
+
+bool QuasianalyticLineReconstruction::fit(MuonCalibSegment & r_segment,
+					HitSelection r_selection) const {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	time_t start,end; // start and end time (needed for time-out)
+	time(&start);
+	double diff; // difference of start and end time (needed for time-out)
+	unsigned int nb_selected_hits(0); // number of selected hits
+	vector<const MdtCalibHitBase*> selected_hits; // vector of pointers to the
+	                                        // selected hits
+	vector<unsigned> selected_hits_index(r_selection.size());
+	                                      // vector containing the indices
+	                                      // of the selected hits (needed
+	                                      // a requested refit)
+	vector<Amg::Vector3D> w; // wire coordinates
+	vector<double> r; // drift CLHEP::radii of the selected hits
+	vector<double> sigma2; // sigma(r)^2 (spatial resolution in r)
+	int counter1, counter2, counter3; // auxiliary counters
+	int max_cand_hits; // the maximum number of hits on a track candidate
+	                      // found so far
+	int max_cand_HOTs; // the maximum number of hit tubes on a track
+			      // candidate found so far
+	int nb_candidates; // number of candidate tracks
+	vector<int> k_cand, l_cand; // candidate track index
+	vector<int> cand_case; // tangent case for the candidate
+	vector<int> nb_HOTs; // number of hits on a candidate
+	int candidate; // index of the candidate which becomes the track
+	IndexSet aux_set; // auxiliary index set
+	vector<IndexSet> index_set; // index set for the storage of the hits
+	                            // forming a track
+	vector<double> intercept; // intercepts of track candidates
+	MTStraightLine tangents[4]; // the four tangents to the drift circles of a
+	                            // hit pair
+	MTStraightLine aux_track; // auxiliary track
+	double aux_chi2; // auxiliary chi^2 variable
+	Amg::Vector3D null(0.0, 0.0, 0.0);
+	Amg::Vector3D xhat(1.0, 0.0, 0.0);
+	MTStraightLine initial_track(r_segment.position(),
+					r_segment.direction(), null, null);
+					// initial track stored in the segment
+	Amg::Vector3D aux_pos, aux_dir; // auxiliary position and direction vectors					
+
+/////////////////////////////////////
+// GET THE NUMBER OF SELECTED HITS //
+/////////////////////////////////////
+	if (r_segment.mdtHitsOnTrack() != r_selection.size()) {
+		cerr << "\n"
+			<< "Class QuasianalyticLineReconstruction, "
+			<< "METHOD fit(., .): WARNING!\n"
+			<< "Vector with selected hits unequal to the number "
+			<< "of hits on the segment!\n"
+			<< "The user selection will be ignored!\n";
+		r_selection.clear();
+		r_selection.assign(r_segment.hitsOnTrack(), 0);
+	} else {
+		for (unsigned int k=0; k<r_selection.size(); k++) {
+			if (r_selection[k] == 0) {
+				nb_selected_hits = nb_selected_hits+1;
+			}
+		}
+	}
+
+//////////////////////////////////////////////////////////////////////////
+// FIX POTENTIAL SECOND-COORDINATE PROBLEM OF THE INITIAL TRACK SEGMENT //
+//////////////////////////////////////////////////////////////////////////
+
+	if (r_segment.direction().z()==0.0) {
+		Amg::Vector3D dir(r_segment.direction().x(),
+				r_segment.direction().y(),
+				1.0);
+		initial_track = MTStraightLine(r_segment.position(), dir,
+								null, null);
+	}
+
+///////////////////////////////////////////////////////////////////////////
+// RETURN, IF THERE ARE LESS THAN 3 HITS, I.E. THE TRACK IS NOT UNIQUELY //
+// DEFINED BY THE HITS.                                                  //
+///////////////////////////////////////////////////////////////////////////
+
+	if (nb_selected_hits<3) {
+		cerr << "\n"
+			<< "Class QuasianalyticLineReconstruction, "
+			<< "METHOD fit(., .): WARNING!\n"
+			<< "Too few hits for the track reconstructions!\n";
+		return false;
+	}
+
+/////////////////////////////////////////////////
+// COPY THE WIRE COORDINATES TO A LOCAL VECTOR //
+/////////////////////////////////////////////////
+
+// vector assignments //
+	selected_hits.clear();// = vector<const MdtCalibHitBase*>(nb_selected_hits);
+	w.clear();// = vector<Amg::Vector3D>(nb_selected_hits);
+	r.clear();// = vector<double>(nb_selected_hits);
+	sigma2.clear();// = vector<double>(nb_selected_hits);
+	selected_hits_index.clear();//
+// vector filling //
+	counter2 = 0;
+	for (unsigned int k=0; k<r_segment.mdtHitsOnTrack(); k++) {
+
+   // skip the hit, if it has not been selected //
+		const MdtCalibHitBase *hit = (r_segment.mdtHOT())[k];
+		if (r_selection[k]==1 || hit->sigmaDriftRadius()>100.0) {
+			continue;
+		}
+
+   // copy the hit information into local vectors //
+		selected_hits.push_back(hit);//[counter2] = hit;
+		selected_hits_index.push_back(k);//[counter2] = k;
+		w.push_back(Amg::Vector3D(0.0, (hit->localPosition()).y(), (hit->localPosition()).z()));//[counter2] = Amg::Vector3D(0.0, (hit->localPosition()).y(), (hit->localPosition()).z());
+		r.push_back(fabs(hit->driftRadius()));//[counter2] = fabs(hit->driftRadius());
+		sigma2.push_back(hit->sigma2DriftRadius());//[counter2] = hit->sigma2DriftRadius();
+   // if the spatial resolution has not been set, set it to 0.1 CLHEP::mm //
+		if (sigma2[counter2] == 0) {
+			sigma2[counter2] = std::pow(0.1*CLHEP::mm, 2);
+		}
+
+		counter2 = counter2+1;
+
+	}
+	nb_selected_hits=selected_hits.size();
+	if(nb_selected_hits<3)
+		return false;
+//////////////////////////
+// TRACK RECONSTRUCTION //
+//////////////////////////
+
+// reset counters //
+	max_cand_hits = 0;
+	max_cand_HOTs = 0;
+	nb_candidates = 0;
+// 1st step: loop over all hit pairs and determine a track candidate //
+	for (unsigned int k=0; k<nb_selected_hits; k++) {
+	for (unsigned int l=k+1; l<nb_selected_hits; l++) {
+
+// time-out //
+		time (&end);
+  		diff = difftime (end,start);
+		if (diff>m_time_out) {
+			cerr << endl
+				<< "Class QuasianalyticLineReconstruction: "
+				<< "time-out for track finding after "
+				<< m_time_out
+				<< " seconds!\n";
+			return false;
+		}
+
+// 2nd step: determine all four tangents to the drift circles of the hit pair //
+		for (unsigned int r_case=1; r_case<5; r_case++) {
+			tangents[r_case-1] = tangent(w[l], r[l], sigma2[l],
+						w[k], r[k], sigma2[k], r_case);
+		}
+
+// 3rd step: determine additional track points within the road width around //
+//           the four tangents                                              //
+		for (unsigned int r_case=1; r_case<5; r_case++) {
+			bool same(false);
+			counter1 = 0;
+			counter3 = 0;
+			vector<int> indices; // indices of the hits forming a
+					     // track
+			for (unsigned int n=0; n<nb_selected_hits; n++) {
+				MTStraightLine aux_line(w[n], xhat, null, null);
+				if (fabs(fabs(tangents[r_case-1].signDistFrom(
+						aux_line))-r[n])<m_r_max) {
+					counter3++;
+				}
+				if (fabs(fabs(tangents[r_case-1].signDistFrom(
+						aux_line))-
+					r[n])<=m_road_width) {
+					counter1 = counter1+1;
+					indices.push_back(n);
+				}
+			}
+			if (counter1>2) {
+				aux_set = IndexSet(counter1, indices);
+				aux_set.sort();
+				for (int ca=0; ca<nb_candidates; ca++) {
+					if (aux_set==index_set[ca] &&
+						fabs(intercept[ca]-
+						tangents[r_case-1].b_x2())
+						<m_road_width) {
+						same = true;
+						break;
+					}
+				}
+				if (same) {
+					continue;
+				}
+				nb_candidates = nb_candidates+1;
+				k_cand.push_back(k);
+				l_cand.push_back(l);
+				cand_case.push_back(r_case);
+				index_set.push_back(aux_set);
+				intercept.push_back(tangents[r_case-1].b_x2());
+				nb_HOTs.push_back(counter3);
+				if (counter1>max_cand_hits) {
+					max_cand_hits = counter1;
+				}
+			}
+		}
+
+	}
+	}
+
+// 4th step: reconstruct a straight-line trajectory for all candidates with   //
+//           the maximum number of hits, keep the one with the smallest chi^2 //
+	m_nb_track_hits = max_cand_hits;
+	m_chi2 = -1.0;
+	if (m_nb_track_hits<3) {
+		return false;
+	}
+	
+	candidate = 0;
+	for (int ca=0; ca<nb_candidates; ca++) {
+		if (index_set[ca].size()<static_cast<unsigned int>(
+							m_nb_track_hits)) {
+			continue;
+		}
+
+		aux_track = m_track_candidate(index_set[ca],
+					k_cand[ca], l_cand[ca], 
+					cand_case[ca], w, r, sigma2, aux_chi2);
+		if (nb_HOTs[ca]>=max_cand_HOTs) {
+			max_cand_HOTs = nb_HOTs[ca];
+			if (m_chi2==-1.0 || m_chi2>aux_chi2) {
+				m_chi2 = aux_chi2;
+				m_track = aux_track;
+				candidate = ca;
+			}
+		}
+	}
+
+	m_track_hits.resize(m_nb_track_hits);
+	for (int k=0; k<m_nb_track_hits; k++) {
+		m_track_hits[k] = selected_hits[index_set[candidate][k]];
+	}
+
+   // make the segment in rphi as the initial segment //
+	aux_pos = Amg::Vector3D(initial_track.b_x1(), m_track.b_x2(), 0);
+	aux_dir = Amg::Vector3D(initial_track.m_x1(), m_track.m_x2(), 1.0);
+	m_track = MTStraightLine(aux_pos, aux_dir, null, null);
+
+// 5th step: update the segment//
+	if (std::isnan(m_chi2)) {
+		m_chi2=1.0e6;
+	}
+	r_segment.set(m_chi2/static_cast<double>(m_nb_track_hits-2),
+			m_track.positionVector(), m_track.directionVector());
+
+
+	vector<unsigned int> refit_hit_selection(r_selection.size(), 1);
+	for (int k=0; k<m_nb_track_hits; k++) {
+		refit_hit_selection[selected_hits_index[
+					index_set[candidate][k]]] = 0;
+	}
+	if(!m_refit && m_refine_segment) {
+		r_segment.refineMdtSelection(refit_hit_selection);
+	}
+	
+   // chi^2 refit, if requested //
+	if (m_refit) {
+		if (m_nfitter.fit(r_segment, refit_hit_selection)) {
+// 			m_chi2 = r_segment.chi2()*(m_nb_track_hits-2);
+			Amg::Vector3D dir(r_segment.direction());
+			if (dir.z()==0.0) {
+				dir[2] = (1.0e-99);
+			}
+			MTStraightLine aux_line(r_segment.position(),
+					dir,
+					Amg::Vector3D(0.0, 0.0, 0.0),
+					Amg::Vector3D(0.0, 0.0, 0.0));
+			double m_err(m_track.m_x2_error());
+			double b_err(m_track.b_x2_error());
+			m_track = MTStraightLine(0.0, 0.0,
+						aux_line.m_x2(),
+						aux_line.b_x2(),
+						0.0, 0.0,
+						m_err, b_err);
+			aux_pos = Amg::Vector3D(initial_track.b_x1(),
+							m_track.b_x2(), 0);
+			aux_dir = Amg::Vector3D(initial_track.m_x1(),
+							m_track.m_x2(), 1.0);
+			m_track = MTStraightLine(aux_pos, aux_dir, null, null);
+	// recompute chi^2 because of different convention in DCSLFitter //
+			m_chi2 = 0.0;
+			for (int k=0; k<m_nb_track_hits; k++) {
+				MTStraightLine wire(Amg::Vector3D(0.0, 
+					m_track_hits[k]->localPosition().y(),
+					m_track_hits[k]->localPosition().z()),
+					xhat, null, null);
+				double d(fabs(m_track.signDistFrom(wire)));
+				m_chi2 = m_chi2+
+					std::pow(d-m_track_hits[k]->driftRadius(),
+						2)/
+					m_track_hits[k]->sigma2DriftRadius();
+			}
+			r_segment.set(
+			m_chi2/static_cast<double>(m_nb_track_hits-2),
+			m_track.positionVector(), m_track.directionVector());
+			if (std::isnan(m_chi2)) {
+				m_chi2=1.0e6;
+			}
+			if (m_refine_segment) {
+				r_segment.refineMdtSelection(
+							refit_hit_selection);
+			}
+			return true;
+		}
+		return false;
+	}
+
+   // finish the update (necessary, if no refit has been performed) //
+	MuonCalibSegment::MdtHitIt it = r_segment.mdtHOTBegin();
+	while(it!=r_segment.mdtHOTEnd()){
+		MdtCalibHitBase& hit = const_cast< MdtCalibHitBase& >( **it );
+
+		Amg::Vector3D pos(0.0, (hit.localPosition()).y(),
+					(hit.localPosition()).z());
+					// wire position
+		MTStraightLine aux_line(pos, xhat, null, null);
+// 		double dist(fabs(m_track.signDistFrom(aux_line))); // track distance
+		double dist(m_track.signDistFrom(aux_line)); // track distance
+		double dist_err(sqrt(std::pow(pos.z()*m_track.m_x2_error(), 2)+
+				std::pow(m_track.b_x2_error(), 2)));
+				// approximate error of the track distance
+		hit.setDistanceToTrack(dist, dist_err);
+    
+		++it;
+	}
+
+	return true;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD printLevel ::
+//:::::::::::::::::::::::
+
+void QuasianalyticLineReconstruction::printLevel(int level) {
+
+	cerr << "\n"
+		<< "Class QuasianalyticLineReconstruction, "
+		<< "method printLevel: WARNING!\n"
+		<< "Print level " << level << " is ignored.\n";
+	return;
+
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/StraightPatRec.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/StraightPatRec.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..23c19e83a5b7ea2ba7b3ea4b054440df02d8cf2a
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibFitters/src/StraightPatRec.cxx
@@ -0,0 +1,797 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 27.10.2007, AUTHOR: OLIVER KORTNER
+// Modified: 26.11.2007 by O. Kortner, fix for segment refinement.
+//           13.12.2007 by O. Kortner, time-out added.
+//           07.08.2008 by O. Kortner, bug fix when hits are disabled.
+//				 19.11.2008 by I. Potrap: 1) several bugs have been fixed;
+//												  2) external fitter(DCLS) replaced by
+//													  internal code of linear-least-chi2-fit
+//				 01.12.2008 by I. Potrap, track() method and segment position are fixed
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: IMPLEMENTATION OF METHODS DEFINED IN THE CLASS ::
+//::                 StraightPatRec                 ::
+//::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+#include "MdtCalibFitters/StraightPatRec.h"
+#include <iostream>
+#include <fstream>
+#include "CLHEP/GenericFunctions/CumulativeChiSquare.hh"
+#include "CLHEP/Units/SystemOfUnits.h"
+#include "CLHEP/Units/PhysicalConstants.h"
+
+#include "MuonCalibMath/Combination.h"
+#include "time.h"
+
+#include "EventPrimitives/EventPrimitives.h"
+#include "GeoPrimitives/GeoPrimitivesHelpers.h"
+
+//:::::::::::::::::::::::
+//:: NAMESPACE SETTING ::
+//:::::::::::::::::::::::
+
+using namespace MuonCalib;
+using namespace std;
+
+//*****************************************************************************
+
+//:::::::::::::::::::
+//:: METHOD m_init ::
+//:::::::::::::::::::
+
+void StraightPatRec::m_init(void) {
+
+	m_init(0.5*CLHEP::mm); // default road width = 0.5 CLHEP::mm
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: METHOD m_init(const double & r_road_width) ::
+//:::::::::::::::::::::::::::::::::::::::::::::::::::
+
+void StraightPatRec::m_init(const double & r_road_width) {
+
+
+//coverity
+	m_b_x1_err=0.0;
+	m_b_x2_err=0.0;
+	m_b_x2=0.0;
+	m_m_x1_err=0.0;
+	m_m_x2_err=0.0;
+	m_m_x2=0.0;
+
+
+//:::::::::::::::
+//:: VARIABLES ::
+//:::::::::::::::
+
+	Amg::Vector3D null_vec(0.0, 0.0, 0.0); // auxiliary 0 vector
+
+//::::::::::::::::::
+//:: SET TIME-OUT ::
+//::::::::::::::::::
+
+	m_time_out = 10.0;
+
+//::::::::::::::::::::::::::::
+//:: SET THE MAXIMUM RADIUS ::
+//::::::::::::::::::::::::::::
+
+	m_r_max = 15.0;
+
+//::::::::::::::::::::::::
+//:: SET THE ROAD WIDTH ::
+//::::::::::::::::::::::::
+
+	m_road_width = r_road_width;
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: INITIALIZE PRIVATE VARIABLES WHICH ARE ACCESSIBLE BY METHODS ::
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+	m_nb_track_hits = 0;
+	m_chi2 = 0.0;
+	m_track = MTStraightLine(null_vec, null_vec, null_vec, null_vec);
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: SET THE TRACK IN THE x1-x3 PLANE (LATER VERSION MAY ALLOW TO SET ::
+//:: USER-DEFINED VALUES)                                             ::
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+	m_m_x1 = 1.0; m_b_x1 = 0.0;
+
+	m_fix_selection = false;
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::
+//:: METHOD tangent ::
+//::::::::::::::::::::
+
+MTStraightLine StraightPatRec::tangent(
+		const Amg::Vector3D & r_w1,
+		const double & r_r1, const double & r_sigma12,
+		const Amg::Vector3D & r_w2, const double & r_r2,
+		const double & r_sigma22, const int & r_case) const {
+
+//:::::::::::::::
+//:: VARIABLES ::
+//:::::::::::::::
+
+	double sinalpha; // auxiliary sinus of an angle
+	double cosalpha; // auxiliary sinus of an angle
+	Amg::Vector3D e2prime, e3prime; // auxiliary direction vectors
+	MTStraightLine tang; // tangent to drift circles of a hit pair
+	Amg::Vector3D p1(0.0, 0.0, 0.0), p2(0.0, 0.0, 0.0); // hit points defining a tangent
+	Amg::Vector3D null_vec(0.0, 0.0, 0.0); // auxiliary 0 vector
+	double mx1, bx1, mx2, bx2; // auxiliary track parameters
+
+//::::::::::::::::::::::::::::::::::::::::::::
+//:: CHECK WHETHER THE SELECTED CASE EXISTS ::
+//::::::::::::::::::::::::::::::::::::::::::::
+
+	if (r_case<1 || r_case>4) {
+		cerr << endl
+			<< "Class StraightPatRec, "
+			<< "method tangent: ERROR!\n"
+			<< "Illegal case " << r_case << ", must be 1,2,3, or 4."
+			<< endl;
+		exit(1);
+	}
+
+//:::::::::::::::::::::::::::::::::::::
+//:: CALCULATE THE REQUESTED TANGENT ::
+//:::::::::::::::::::::::::::::::::::::
+
+// local coordinate axis vectors //
+	e3prime = (r_w2-r_w1).unit();
+	e2prime = Amg::Vector3D(0.0, e3prime.z(), -e3prime.y());
+
+// case 1 and 2 //
+	if (r_case==1 || r_case==2) {
+
+		sinalpha = fabs(r_r2-r_r1)/(r_w2-r_w1).mag();
+		cosalpha = sqrt(1.0-sinalpha*sinalpha);
+
+   // case 1 //
+		if (r_case==1) {
+			p1 = r_w1+((1 && r_r2>=r_r1)-(1 && r_r2<r_r1))*r_r1*
+					(cosalpha*e2prime-sinalpha*e3prime);
+			p2 = r_w2+((1 && r_r2>=r_r1)-(1 && r_r2<r_r1))*r_r2*
+					(cosalpha*e2prime-sinalpha*e3prime);
+		}
+
+   // case 2 //
+		if (r_case==2) {
+			p1 = r_w1-((1 && r_r2>=r_r1)-(1 && r_r2<r_r1))*r_r1*
+					(cosalpha*e2prime+sinalpha*e3prime);
+			p2 = r_w2-((1 && r_r2>=r_r1)-(1 && r_r2<r_r1))*r_r2*
+					(cosalpha*e2prime+sinalpha*e3prime);
+		}
+
+
+	}
+
+// case 3 and 4 //
+	if (r_case==3  || r_case==4) {
+
+		sinalpha = (r_r1+r_r2)/(r_w2-r_w1).mag();
+		cosalpha = sqrt(1.0-sinalpha*sinalpha);
+
+   // case 3 //
+		if (r_case==3) {
+// 			p1 = r_w1+r_r1*(cosalpha*e2prime-sinalpha*e3prime);
+// 			p2 = r_w2-r_r2*(cosalpha*e2prime-sinalpha*e3prime);
+			p1 = r_w1+r_r1*(cosalpha*e2prime+sinalpha*e3prime);
+			p2 = r_w2-r_r2*(cosalpha*e2prime+sinalpha*e3prime);
+		}
+
+   // case 4 //
+		if (r_case==4) {
+			p1 = r_w1-r_r1*(cosalpha*e2prime-sinalpha*e3prime);
+			p2 = r_w2+r_r2*(cosalpha*e2prime-sinalpha*e3prime);
+		}
+
+	}
+
+// calculation of the tangent and estimation of its errors //
+	if ((p2-p1).z()!=0.0) {
+		tang = MTStraightLine(p1, p2-p1, null_vec, null_vec);
+	} else {
+		Amg::Vector3D direction(p2-p1);
+		direction[2] = (1.0e-99);
+		tang = MTStraightLine(p1, direction, null_vec, null_vec);	
+	}
+	mx1 = tang.m_x1(); bx2 = tang.b_x1();
+	mx2 = tang.m_x2(); bx2 = tang.b_x2();
+	tang = MTStraightLine(mx1, bx1, mx2, bx2,1.0, 1.0, 
+			sqrt(r_sigma12+r_sigma22)/fabs(p2.z()-p1.z()),
+			sqrt(r_sigma12+p1.z()*p1.z()*(r_sigma12+r_sigma22)/
+						pow(p2.z()-p1.z(), 2)));
+			// errors in mx1 and bx1 are arbitrary since they are
+			// not used at a later stage.
+
+
+	return tang;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::
+//:: METHOD fitCandidate ::
+//:::::::::::::::::::::::::
+//
+
+
+MTStraightLine StraightPatRec::fitCandidate(MuonCalibSegment & r_segment,
+				const std::vector<unsigned int> & r_selection,
+				const MTStraightLine & cand_line) const {
+
+///////////////
+// VARIABLES //
+///////////////
+	Amg::Vector3D null(0.0, 0.0, 0.0);
+	Amg::Vector3D xhat(1.0, 0.0, 0.0);
+
+	int num_selected_hits(0);
+	for (unsigned int k=0; k<r_selection.size(); k++) {
+		if(!r_selection[k]) {
+			num_selected_hits++;
+		}
+	}
+	if(num_selected_hits<3) return cand_line;
+
+	Amg::Vector3D init_dir(r_segment.direction());
+	Amg::Vector3D init_pos(r_segment.position());
+////////////////////////////////////////////
+// SET THE CORRECT SIGNED TRACK DISTANCES //
+////////////////////////////////////////////
+
+	r_segment.set(r_segment.chi2(), cand_line.positionVector(), cand_line.directionVector());
+
+	for (unsigned int k=0; k<r_segment.mdtHitsOnTrack(); k++) {
+		MTStraightLine aux_line(r_segment.mdtHOT()[k]->localPosition(),
+							xhat, null, null);
+		r_segment.mdtHOT()[k]->setDistanceToTrack(
+				cand_line.signDistFrom(aux_line),
+				r_segment.mdtHOT()[k]->sigmaDriftRadius());
+	}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//Analitical fit of linearized measurements (transformation to reference frame is used) //
+//////////////////////////////////////////////////////////////////////////////////////////
+	unsigned int NLC=2; //number of fit parameters
+
+//Normalization on z-direction
+	Amg::Vector3D dir_norm(r_segment.direction().x()/r_segment.direction().z(),
+	r_segment.direction().y()/r_segment.direction().z(), 1.0);
+
+	Amg::Vector3D refTransl(r_segment.position());
+	refTransl[0] = 0;
+	Amg::Vector3D refDir(dir_norm);
+	refDir[0] = 0;
+	refDir = refDir.unit();
+
+// Rotation Matrix for Toewr_to_track transformation
+	
+	double rotAngle = Amg::angle(Amg::Vector3D::UnitZ(),refDir)*(refDir.y())/fabs(refDir.y());
+	Amg::AngleAxis3D RotMatr(rotAngle, Amg::Vector3D::UnitX() ); // Matrix for Track reference transformation
+	Amg::AngleAxis3D RotMatr_inv(-rotAngle, Amg::Vector3D::UnitX() ); // inverse
+
+	Amg::VectorX alpha = Amg::VectorX(NLC);
+	alpha.setZero();
+	Amg::VectorX betha = Amg::VectorX(NLC);
+	betha.setZero();
+	Amg::MatrixX Gamma = Amg::MatrixX(NLC,NLC);
+	Gamma.setZero();
+// vector to store hit positions
+	vector<Amg::Vector3D > hit_position_track;
+
+	for(unsigned int l=0;l<r_segment.mdtHitsOnTrack();l++) {
+// Transformation to track reference frame
+		Amg::Vector3D WirPosLocal = r_segment.mdtHOT()[l]->localPosition();
+		Amg::Vector3D WirPosTrack = WirPosLocal-refTransl;
+		WirPosTrack = RotMatr*WirPosTrack;
+		double signedDrifRadius = fabs(r_segment.mdtHOT()[l]->driftRadius())*
+			(r_segment.mdtHOT()[l]->signedDistanceToTrack()/
+			fabs(r_segment.mdtHOT()[l]->signedDistanceToTrack()));
+		Amg::Vector3D HitPosTrack = WirPosTrack;
+		HitPosTrack[0] = HitPosTrack.y() + signedDrifRadius;
+		HitPosTrack[1] = r_segment.mdtHOT()[l]->sigma2DriftRadius(); //trick to store hit resolution
+
+		hit_position_track.push_back(HitPosTrack);
+
+		Amg::VectorX delta = Amg::VectorX(NLC);
+		delta.setZero();
+		delta[0] = 1.0;
+		delta[1] = HitPosTrack.z();
+
+		if(!r_selection[l]) {
+			double weight=1.0/(r_segment.mdtHOT()[l]->sigma2DriftRadius());
+			Gamma += weight*delta*delta.transpose();
+			betha += weight*HitPosTrack.y()*delta;
+		}
+	}
+
+// solution of linear system of equations
+	Gamma = Gamma.inverse();
+	alpha = Gamma*betha;
+
+	double refit_chi2(0.0);
+	for(unsigned int j=0;j<hit_position_track.size();j++) {
+		double res = (alpha[0] + alpha[1]*hit_position_track[j].z()
+			- hit_position_track[j].y());
+		if(!r_selection[j]) refit_chi2 += res*res/hit_position_track[j].x();
+	}
+
+// Backward transformation
+	Amg::Vector3D seg_dir(0.0,alpha[1],1.0);
+	seg_dir = RotMatr_inv*seg_dir;
+	seg_dir[1] = seg_dir.y()/seg_dir.z();
+	seg_dir[0] = init_dir.x()/init_dir.z();
+	seg_dir[2] = 1.0;
+
+	Amg::Vector3D seg_pos(0.0,alpha[0],0.0);
+	seg_pos = RotMatr_inv*seg_pos;
+	seg_pos = seg_pos + refTransl;
+
+	seg_pos[1] = seg_pos.y()+seg_dir.y()*(init_pos.z()-seg_pos.z());
+	seg_pos[0] = init_pos.x();
+	seg_pos[2] = init_pos.z();
+
+
+// Rewriting segment
+	r_segment.set(refit_chi2/static_cast<double>(num_selected_hits-2), seg_pos, seg_dir);
+
+	MTStraightLine aux_line(seg_pos, seg_dir,
+			Amg::Vector3D(0.0, 0.0, 0.0), Amg::Vector3D(0.0, 0.0, 0.0));
+	
+	for (unsigned int k=0; k<r_segment.mdtHitsOnTrack(); k++) {
+		MTStraightLine aux_t(r_segment.mdtHOT()[k]->localPosition(), xhat, null, null);
+		r_segment.mdtHOT()[k]->setDistanceToTrack(aux_line.signDistFrom(aux_t),
+				r_segment.mdtHOT()[k]->sigmaDriftRadius());
+	}
+
+	return aux_line;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::
+//:: METHOD roadWidth ::
+//::::::::::::::::::::::
+
+double StraightPatRec::roadWidth(void) const {
+
+	return m_road_width;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::
+//:: METHOD numberOfTrackHits ::
+//::::::::::::::::::::::::::::::
+
+unsigned int StraightPatRec::numberOfTrackHits(void) const {
+
+	return m_nb_track_hits;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::
+//:: METHOD trackHits ::
+//::::::::::::::::::::::
+
+const vector<const MdtCalibHitBase*> & StraightPatRec::trackHits(
+								void) const {
+
+	return m_track_hits;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: METHOD chi2 ::
+//:::::::::::::::::
+
+double StraightPatRec::chi2(void) const {
+
+	if (m_nb_track_hits == 0) {
+		return -1;
+	}
+	return m_chi2;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::::::
+//:: METHOD chi2PerDegreesOfFreedom ::
+//::::::::::::::::::::::::::::::::::::
+
+double StraightPatRec::chi2PerDegreesOfFreedom(void) const{
+
+	if (m_nb_track_hits<3) {
+		return -1;
+	}
+	return chi2()/static_cast<double>(numberOfTrackHits()-2);
+
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::
+//:: METHOD track ::
+//::::::::::::::::::
+
+MTStraightLine StraightPatRec::track(void) const {
+
+	return m_track;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::
+//:: METHOD setRoadWidth ::
+//:::::::::::::::::::::::::
+
+void StraightPatRec::setRoadWidth(
+					const double & r_road_width) {
+
+	m_road_width = fabs(r_road_width);
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD setTimeOut ::
+//:::::::::::::::::::::::
+
+void StraightPatRec::setTimeOut(const double & time_out) {
+
+	m_time_out = time_out;
+	return;
+
+}
+
+void StraightPatRec::setFixSelection(bool fix_sel) {
+	m_fix_selection = fix_sel;
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::
+//:: METHOD fit(.) ::
+//:::::::::::::::::::
+
+bool StraightPatRec::fit(MuonCalibSegment & r_segment) const {
+
+// select all hits //
+	HitSelection selection(r_segment.mdtHitsOnTrack(), 0);
+
+// call the other fit function //
+	return fit(r_segment, selection);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::
+//:: METHOD fit(.,.) ::
+//:::::::::::::::::::::
+bool StraightPatRec::fit(MuonCalibSegment & r_segment,
+
+					HitSelection r_selection) const {
+
+	return fitCallByReference(r_segment, r_selection);
+
+}
+
+//*****************************************************************************
+
+bool StraightPatRec::fitCallByReference(MuonCalibSegment & r_segment,
+
+					HitSelection &r_selection) const {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	time_t start,end; // start and end time (needed for time-out)
+	time(&start);
+	double diff; // difference of start and end time (needed for time-out)
+	Combination combination;
+
+	vector<unsigned int> hit_index; // hit indices for given selection
+	unsigned int try_nb_hits; // try this given number of hits for the
+				  // segment reconstruction
+
+	vector<const MdtCalibHitBase*> selected_hits;
+	vector<unsigned int> selected_hits_index;
+
+	Amg::Vector3D w_min, w_max; // wire with the minimum local z coordinate,
+	                         // wire with the maximum local z coordinate
+	double r_min, r_max; // corresponding drift CLHEP::radii
+	double sigma2_min, sigma2_max; // corresponding spatial resolution
+
+	unsigned int counter1; // auxiliary counter
+
+	unsigned int nb_candidates(0); // number of straight-track candidates
+
+	MTStraightLine tangents[4]; // the four tangents to the drift circles of a
+	                            // hit pair
+	MTStraightLine aux_track; // auxiliary track
+	Amg::Vector3D null(0.0, 0.0, 0.0);
+	Amg::Vector3D xhat(1.0, 0.0, 0.0);
+
+	MTStraightLine initial_track(r_segment.position(),
+					r_segment.direction(), null, null);
+					// initial track stored in the segment
+	Amg::Vector3D aux_pos, aux_dir; // auxiliary position and direction vectors					
+
+///////////
+// RESET //
+///////////
+
+	m_chi2 = -1.0;
+
+	if (r_segment.mdtHitsOnTrack() != r_selection.size()) {
+		cerr << "\n"
+			<< "Class StraightPatRec, "
+			<< "METHOD fit(., .): WARNING!\n"
+			<< "Vector with selected hits unequal to the number "
+			<< "of hits on the segment!\n"
+			<< "The user selection will be ignored!\n";
+		r_selection.clear();
+		r_selection.assign(r_segment.hitsOnTrack(), 0);
+	}
+
+// Filling selected_hits vector
+	for (unsigned int k=0; k<r_segment.mdtHitsOnTrack(); k++) {
+		if(!r_selection[k]) {
+			selected_hits.push_back(r_segment.mdtHOT()[k]);
+			selected_hits_index.push_back(k);
+		}
+	}
+
+///////////////////////////////////////////////////////////////////////////
+// RETURN, IF THERE ARE LESS THAN 3 HITS, I.E. THE TRACK IS NOT UNIQUELY //
+// DEFINED BY THE HITS.                                                  //
+///////////////////////////////////////////////////////////////////////////
+
+	if (selected_hits.size()<3) {
+//		cerr << "\n"
+//			<< "Class StraightPatRec, "
+//			<< "METHOD fit(., .): WARNING!\n"
+//			<< "Too few hits for the track reconstructions!\n";
+		return false;
+	}
+
+//////////////////////////////////////////////////////////////////////////
+// FIX POTENTIAL SECOND-COORDINATE PROBLEM OF THE INITIAL TRACK SEGMENT //
+//////////////////////////////////////////////////////////////////////////
+
+	if (r_segment.direction().z()==0.0) {
+		Amg::Vector3D dir(r_segment.direction().x(),
+				r_segment.direction().y(),
+				1.0);
+		initial_track = MTStraightLine(r_segment.position(), dir,
+								null, null);
+	}
+
+//////////////////////////
+// TRACK RECONSTRUCTION //
+//////////////////////////
+// try to find a segment with as many hits as selected initially //
+
+	HitSelection final_selection(r_selection);
+
+	try_nb_hits = selected_hits.size();
+//=============================================================================
+	while(nb_candidates==0) {
+//-----------------------------------------------------------------------------
+// Return in case of large amount of fake hits
+if(try_nb_hits<5 && (selected_hits.size()-try_nb_hits)>2) return false;
+// reset //
+	double best_chi2ndf = -1.0;
+	MTStraightLine	best_aux_line(initial_track);
+
+// loop over all combinations //
+	combination.setNewParameters(selected_hits.size(), try_nb_hits);
+
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+	for (unsigned int cb=0; cb<combination.numberOfCombinations(); cb++) {
+//.............................................................................
+
+   // time-out //
+	   time (&end);
+	   diff = difftime (end,start);
+	   if (diff>m_time_out) {
+//	   	cerr << endl
+//	   		<< "Class StraightPatRec: "
+//	   		<< "time-out for track finding after "
+//			<< m_time_out
+//			<< " seconds!\n";
+	   	return false;
+	   }
+
+   // get the present hit combination //
+	   if (cb==0) {
+		combination.currentCombination(hit_index);
+	   } else {
+		combination.nextCombination(hit_index);
+	   }
+
+// Current selection of hits
+	HitSelection tmp_selection(r_selection);
+	tmp_selection.assign(tmp_selection.size(), 1);
+	for (unsigned int k=0; k<try_nb_hits; k++) {
+		tmp_selection[selected_hits_index[hit_index[k]-1]]=0;
+	}
+
+   // investigate the current combination //
+	// find the wires with minimum and maximum local z //
+	   w_min = selected_hits[hit_index[0]-1]->localPosition();
+	   w_max = selected_hits[hit_index[0]-1]->localPosition();
+	   r_min = selected_hits[hit_index[0]-1]->driftRadius();
+	   r_max = selected_hits[hit_index[0]-1]->driftRadius();
+	   sigma2_min = selected_hits[hit_index[0]-1]->sigma2DriftRadius();
+	   sigma2_max = selected_hits[hit_index[0]-1]->sigma2DriftRadius();
+	   for (unsigned int k=1; k<try_nb_hits; k++) {
+		if (selected_hits[hit_index[k]-1]->localPosition().z()<
+								w_min.z()) {
+			w_min = selected_hits[hit_index[k]-1]->localPosition();
+			r_min = selected_hits[hit_index[k]-1]->driftRadius();
+			sigma2_min = selected_hits[hit_index[k]-1
+							]->sigma2DriftRadius();
+		}
+	   	if (selected_hits[hit_index[k]-1]->localPosition().z()>
+								w_max.z()) {
+			w_max = selected_hits[hit_index[k]-1]->localPosition();
+			r_max = selected_hits[hit_index[k]-1]->driftRadius();
+			sigma2_max = selected_hits[hit_index[k]-1
+							]->sigma2DriftRadius();
+		}
+	   }
+
+	// set the spatial resolution to 0.1 CLHEP::mm if it is 0 //
+	   if (sigma2_min==0) {
+	   	sigma2_min=0.1;
+	   }
+	   if (sigma2_max==0) {
+	   	sigma2_max=0.1;
+	   }
+
+	// get the four segment candidates tangential to the outermost hits //
+	   for (unsigned int r_case=1; r_case<5; r_case++) {
+		tangents[r_case-1] = tangent(w_min, r_min, sigma2_min,
+					     w_max, r_max, sigma2_max, r_case);
+	   }
+
+	// determine additional track points within the road width around //
+	// the four tangents and determine a segment                      //
+	   for (unsigned int r_case=1; r_case<5; r_case++) {
+		counter1 = 0;
+		for (unsigned int n=0; n<try_nb_hits; n++) {
+			MTStraightLine aux_line(
+ 				selected_hits[hit_index[n]-1]->localPosition(),
+				xhat, null, null);
+			if (fabs(fabs(tangents[r_case-1].signDistFrom(
+						aux_line))-
+				selected_hits[hit_index[n]-1]->driftRadius())
+								<=m_road_width) {
+				counter1 = counter1+1;
+			}
+		}
+
+// Used to fix initial configuration of hits
+		if(m_fix_selection) counter1=try_nb_hits;
+// perform a straight line fit for the candidate //
+		if (counter1==try_nb_hits) {
+			nb_candidates++;
+			aux_track = fitCandidate(r_segment, tmp_selection,
+						tangents[r_case-1]);
+
+			if ((best_chi2ndf==-1) || (best_chi2ndf>r_segment.chi2())) {
+				best_chi2ndf = r_segment.chi2();
+				best_aux_line = aux_track;
+				final_selection.assign(final_selection.size(),1);
+				for (unsigned int j=0; j<try_nb_hits; j++) {
+					final_selection[selected_hits_index[hit_index[j]-1]]=0;
+				}
+
+			}
+		}
+	   }
+//.............................................................................
+	}
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+
+//////////////////////////////////////////////////
+// MAKE THE FINAL STRAIGHT SEGMENT, IF POSSIBLE //
+//////////////////////////////////////////////////
+
+	if (nb_candidates>0) {
+
+   // store track hits, rewrite hit selection //
+		m_track_hits.clear();
+		for (unsigned int k=0; k<r_selection.size(); k++) {
+			r_selection[k] = final_selection[k];
+			if(!final_selection[k]) {
+				m_track_hits.push_back(r_segment.mdtHOT()[k]);
+			}
+		}
+
+// Final refit //
+		m_track = fitCandidate(r_segment, final_selection,
+						best_aux_line);
+
+		m_nb_track_hits = m_track_hits.size();
+		m_chi2 = r_segment.chi2()*(static_cast<double>(m_nb_track_hits-2));
+
+		if(m_refine_segment) {
+			r_segment.refineMdtSelection(r_selection);
+		}
+
+	} else {
+		try_nb_hits = try_nb_hits-1;
+		if (try_nb_hits<3) {
+			return false;
+		}
+	}
+	
+//-----------------------------------------------------------------------------
+	}
+//=============================================================================
+
+	if (std::isnan(m_chi2)) {
+		m_chi2 = -1.0;
+		return false;
+	}
+
+	return true;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD printLevel ::
+//:::::::::::::::::::::::
+
+void StraightPatRec::printLevel(int level) {
+
+	cerr << "\n"
+		<< "Class StraightPatRec, "
+		<< "method printLevel: WARNING!\n"
+		<< "Print level " << level << " is ignored.\n";
+	return;
+
+}