From 794cfaf225db8e53cfe013b92b5b7cfae063eaf7 Mon Sep 17 00:00:00 2001
From: Jochen Meyer <Jochen.Meyer@cern.ch>
Date: Mon, 15 Sep 2014 16:54:45 +0200
Subject: [PATCH] fixing compiler warning (MdtCalibRt-02-00-01)

---
 .../MdtCalibRt/AdaptiveResidualSmoothing.h    |  103 +
 .../MdtCalib/MdtCalibRt/MdtCalibRt/MeanRMS.h  |   43 +
 .../MdtCalibRt/RtCalibrationAnalytic.h        |  398 ++++
 .../MdtCalibRt/RtCalibrationCurved.h          |  352 ++++
 .../MdtCalibRt/RtCalibrationIntegration.h     |  127 ++
 .../MdtCalibRt/RtCalibrationOutput.h          |   36 +
 .../MdtCalibRt/RtParabolicExtrapolation.h     |   86 +
 .../MdtCalib/MdtCalibRt/cmt/requirements      |   31 +
 .../MdtCalib/MdtCalibRt/doc/mainpage.h        |   40 +
 .../src/AdaptiveResidualSmoothing.cxx         |  484 +++++
 .../MdtCalibRt/src/MultilayerRtDifference.cxx |  220 +++
 .../MdtCalibRt/src/MultilayerRtDifference.h   |   47 +
 .../MdtCalibRt/src/RtCalibrationAnalytic.cxx  | 1641 ++++++++++++++++
 .../MdtCalibRt/src/RtCalibrationCurved.cxx    | 1699 +++++++++++++++++
 .../src/RtCalibrationIntegration.cxx          |  416 ++++
 .../src/RtParabolicExtrapolation.cxx          |  248 +++
 16 files changed, 5971 insertions(+)
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/AdaptiveResidualSmoothing.h
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/MeanRMS.h
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationAnalytic.h
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationCurved.h
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationIntegration.h
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationOutput.h
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtParabolicExtrapolation.h
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/cmt/requirements
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/doc/mainpage.h
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/AdaptiveResidualSmoothing.cxx
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/MultilayerRtDifference.cxx
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/MultilayerRtDifference.h
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtCalibrationAnalytic.cxx
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtCalibrationCurved.cxx
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtCalibrationIntegration.cxx
 create mode 100644 MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtParabolicExtrapolation.cxx

diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/AdaptiveResidualSmoothing.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/AdaptiveResidualSmoothing.h
new file mode 100644
index 0000000000000..23d4ea0abc2a0
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/AdaptiveResidualSmoothing.h
@@ -0,0 +1,103 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 29.07.2008, AUTHOR: OLIVER KORTNER
+// Modified: 20.03.2009 by O. Kortner, additional method ,,performSmoothing''
+//                      with better performance than the old method added;
+//                      softer chi^2 cuts in addResidualsFromSegment.
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#ifndef MuonCalib_AdaptiveResidualSmoothingH
+#define MuonCalib_AdaptiveResidualSmoothingH
+
+//:::::::::::::::::::::::::::::::::::::
+//:: CLASS AdaptiveResidualSmoothing ::
+//:::::::::::::::::::::::::::::::::::::
+
+/// \class AdaptiveResidualSmoothing
+///
+/// This class is used to modify the r-t relationship to give smooth residuals
+/// centred at 0. The binning of the residual distribution is adapted to the
+/// statistics. The user can set the number of entries per bin. The user can
+/// decide whether the track fits should be performed with a straight or
+/// parabolic curve.
+///
+/// \author Oliver.Kortner@CERN.CH
+///
+/// \date 28.07.2008
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+// STL //
+#include <vector>
+
+// MuonCalib //
+#include "MdtCalibData/RtRelationLookUp.h"
+#include "MdtCalibFitters/StraightPatRec.h"
+#include "MdtCalibFitters/CurvedPatRec.h"
+#include "MuonCalibMath/DataPoint.h"
+
+namespace MuonCalib {
+
+class IRtRelation;
+
+class AdaptiveResidualSmoothing {
+
+public:
+// Constructor //
+    AdaptiveResidualSmoothing(void);
+    ///< Default constructor.
+
+// Methods //
+    void clear(void);
+                                    ///< clear the memory of the class
+    void addResidual(const double & radius, const double & residual);
+                                    ///< add the residual at the given radius
+    bool addResidualsFromSegment(MuonCalibSegment & seg, bool curved,
+                                                        double road_width);
+                                    ///< reconstruct the given segment and
+                                    ///< store the residuals; if curved is true
+                                    ///< a curved segment fit is performed,
+                                    ///< otherwise a straight segment is fitted
+                                    ///< to the drift radii; the user must
+                                    ///< set the road width used in the pattern
+                                    ///< recognition;
+									///< returns true in case of success
+    RtRelationLookUp performSmoothing(const IRtRelation & rt_rel,
+                                      unsigned int nb_entries_per_bin,
+									  bool fix_t_min, bool fix_t_max);
+                                    ///< use the stored residuals to improve
+                                    ///< the given r-t relationship to give
+                                    ///< smoother residuals; the user has to
+                                    ///< set the number of entries per radial
+                                    ///< bin; the user can request that the
+									///< radii for the minimum and maximum
+									///< drift time are untouched
+    RtRelationLookUp performSmoothing(const IRtRelation & rt_rel,
+									const bool & fix_t_min,
+                                    const bool & fix_t_max);
+                                    ///< use the stored residuals to improve
+                                    ///< the given r-t relationship to give
+                                    ///< smoother residuals; the user can
+                                    ///< request that the radii for the minimum
+                                    ///< and maximum drift time are untouched
+
+private:
+    std::vector<DataPoint> m_residual_point; // vector of residual points
+    StraightPatRec m_sfitter; // straight-line fitter
+    CurvedPatRec m_cfitter; // curved-line fitter
+	double t_from_r(const IRtRelation & rt_rel, const double & r);
+							// get t(r) for the given r-t relationship,
+							// the method is auxiliary and not optimized;
+							// it will disappear when the t(r) will be
+							// available in the MuonCalib framework
+
+};
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/MeanRMS.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/MeanRMS.h
new file mode 100644
index 0000000000000..2f76af94d6fbe
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/MeanRMS.h
@@ -0,0 +1,43 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "cmath"
+
+
+namespace MuonCalib {
+
+
+
+class MeanRMS
+	{
+	public:
+		inline MeanRMS() : m_sum_x(0.), m_sum_x_sq(0.), n_ent(0) {}
+		inline void Insert(double x)
+			{
+			m_sum_x += x;
+			m_sum_x_sq += x*x;
+			n_ent++;
+			}
+		inline double GetMean() const
+			{
+			if(n_ent==0) return 0;
+			return m_sum_x/static_cast<double>(n_ent);
+			}
+		inline double GetRMS() const
+			{
+			if(n_ent==0) return 0;
+			double mean=GetMean();
+			return std::sqrt(m_sum_x_sq/static_cast<double>(n_ent) - mean*mean);
+			}
+		inline int GetN() const
+			{
+			return n_ent;
+			}
+	private:
+		double m_sum_x;
+		double m_sum_x_sq;
+		int n_ent;	
+		
+	};
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationAnalytic.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationAnalytic.h
new file mode 100644
index 0000000000000..83d4ac66fa308
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationAnalytic.h
@@ -0,0 +1,398 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 06.04.2006, AUTHOR: OLIVER KORTNER
+// Modified: 02.07.2006 by O. Kortner, redesign to simplified optimization.
+//           16.07.2006 by O. Kortner, optimized quality cuts.
+//           17.07.2006 by O. Kortner, compatibility with old event loop.
+//           13.12.2006 by O. Kortner and J. von Loeben, new convergence
+//                                                       criterion.
+//           27.03.2007 by O. Kortner, control histograms are written to file
+//                                     when they are switched off again.
+//           06.08.2007 by O. Kortner, option to force r(t) to be monotonically
+//                                     increasing
+//           29.10.2007 by O. Kortner, avoid double analysis in case of full
+//                                     chamber track fits.
+//           30.06.2008 by O. Kortner, m_r_max settings corrected, better hit
+//                                     selection.
+//           03.08.2008 by O. Kortner, r-t smoothing using the conventional
+//                                     autocalibration method is implemented.
+//           28.02.2009 by O. Kortner, parabolic extrapolation added.
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#ifndef RtCalibrationAnalyticH
+#define RtCalibrationAnalyticH
+
+//:::::::::::::::::::::::::::::::::
+//:: CLASS RtCalibrationAnalytic ::
+//:::::::::::::::::::::::::::::::::
+
+namespace MuonCalib {
+/// \class RtCalibrationAnalytic
+/// This class performs the analytic autocalibration whose basic ideas were
+/// developed by Mario Deile (see ATL-MUON-2004-021).
+///
+/// \author Oliver.Kortner@CERN.CH
+///
+/// \date 06.04.2006
+/**
+@class RtCalibrationAnalytic
+This class performs the analytic autocalibration whose basic ideas were
+developed by Mario Deile (see ATL-MUON-2004-021).
+
+@author Oliver.Kortner@CERN.CH
+
+*/
+
+}
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+// STL //
+#include <vector>
+#include <string>
+
+// CLHEP //
+#include "CLHEP/Units/SystemOfUnits.h"
+#include "CLHEP/Units/PhysicalConstants.h"
+#include "CLHEP/Matrix/SymMatrix.h"
+#include "CLHEP/Matrix/Vector.h"
+
+// ROOT //
+#include "TFile.h"
+#include "TH1F.h"
+#include "TH2F.h"
+
+// MuonCalib //
+#include "MdtCalibInterfaces/IMdtCalibration.h"
+#include "MdtCalibFitters/QuasianalyticLineReconstruction.h"
+#include "MdtCalibRt/MeanRMS.h"
+
+namespace MuonCalib {
+
+class IRtRelation;
+class RtRelationLookUp;
+class RtCalibrationOutput;
+class IMdtCalibrationOutput;
+class  MuonCalibSegment;
+class BaseFunction;
+
+class RtCalibrationAnalytic : public IMdtCalibration {
+
+public:
+// Constructors //
+	RtCalibrationAnalytic(std::string name) : IMdtCalibration(name) {
+	        init(0.5*CLHEP::mm, 1, 5, true, true, true, true, 100, false, false);
+	        }
+	///< Default constructor: r-t accuracy is set to 0.5 mm.
+	///< The r-t accuracy is used internally to distinguish between good
+	///< and bad segments.
+	///< By default Legendre polynomials are used to parametrize the
+	///< r-t correction.
+	///< The order of the r-t correction polynomial is set to 5.
+	///< Segments are restricted to single multilayers. The full matrix
+	///< relating the errors in r(t) to the residuals is used.
+	///< By default no smoothing is applied after convergence.
+
+	RtCalibrationAnalytic(std::string name,
+		const double & rt_accuracy,
+		const unsigned int & func_type,
+		const unsigned int & ord,
+		const bool & split,
+		const bool & full_matrix,
+		const bool & fix_min,
+		const bool & fix_max,
+		const int & max_it,
+		bool do_smoothing=false,
+        bool do_parabolic_extrapolation=false);
+	///< Constructor: r-t accuracy is set to rt_accuracy (unit: CLHEP::mm).
+	///< The r-t accuracy is used internally to distinguish between good
+	///< and bad segments.
+	///< \param func_type: type of function to be used for the r-t correction;
+	///<    = 1: Legendre polynomial,
+	///<    = 2: Chebyshev polynomial,
+	///<    = 3: polygon equidistant in r.
+	///< \param ord The order of the r-t correction polynomial is set to ord.
+	///< \param split = true forces the algorithm to restrict segments to
+	///< multilayers. Otherwise, segments may contain hits from different
+	///< multilayers.
+	///< \param full_matrix = true lets the algorithm use the full matrix
+	///< relating the errors in r(t) to the residuals is used. Otherwise
+	///< the unit matrix is used, making the code equivalent to the
+	///< conventional/classical method.
+	///< \param fix_min,fix_max =true fix r(t_min), r(t_max) (this is default).
+	///< \param max_it maximum number of iterations.
+	///< \param do_smoothing Smoothen the r-t relations after convergence.
+    ///> \param do_parabolic_extrapolation Use parabolic extrapolations for
+    ///< small and larged drift radii.
+
+// Desctructor //
+	~RtCalibrationAnalytic(void);
+
+// Methods //
+// get-methods //
+	double reliability(void) const;
+	                                ///< get the reliability of the r-t:
+	                                ///< 0: no convergence yet
+	                                ///< 1: convergence, r-t is reliable
+	                                ///< 2: convergence, r-t is unreliable
+	double estimatedRtAccuracy(void) const;
+	                                ///< get the estimated r-t quality (CLHEP::mm),
+	                                ///< the accuracy of the input r-t is
+	                                ///< computed at the end of the
+	                                ///< iteration; in order to get the
+	                                ///< accuracy of the final r-t, the
+	                                ///< algorithm has to be rerun with the
+	                                ///< final r-t as an input
+	int numberOfSegments(void) const;
+	                                ///< get the number of segments which
+	                                ///< were passed to the algorithm
+	int numberOfSegmentsUsed(void) const;
+	                                ///< get the number of segments which
+	                                ///< are used in the autocalibration
+	int iteration(void) const;
+	                                ///< get the number of the current
+	                                ///< iteration
+	bool splitIntoMultilayers(void) const;
+	                                ///< returns true, if segments are
+	                                ///< internally restricted to single
+	                                ///< multilayers;
+	                                ///< returns false, if segments may
+	                                ///< contain hits from both multilayers
+	bool fullMatrix(void) const;
+	                                ///< returns true, if the full matrix 
+	                                ///< relating the errors in the r-t
+	                                ///< relationship to the residuals
+	                                ///< should be used;
+	                                ///< returns false, if the unit matrix
+	                                ///< is used
+	bool smoothing(void) const;
+									///< returns true, if the r-t relationship
+									///< will be smoothened using the
+									///< conventional autocalibration after
+									///< convergence;
+									///< returns false otherwise
+
+// set-method //
+	void setEstimateRtAccuracy(const double & acc);
+	                                ///< set the estimated r-t accuracy =acc
+	void splitIntoMultilayers(const bool & yes_or_no);
+	                                ///< yes_or_no=true: segments are
+	                                ///< internally restriced to single
+	                                ///< multilayers;
+					///< yes_or_no=false: segments over
+	                                ///< two multilayers of a chamber are
+	                                ///< allowed
+	void fullMatrix(const bool & yes_or_no);
+	                                ///< yes_or_no=true: the full matrix
+	                                ///< relating the errors in the r-t
+	                                ///< relationship to the residuals
+	                                ///< is used
+					///< yes_or_no=false: unit matrix is
+	                                ///< used (algorithm is equivalent to
+	                                ///< to the conventional/classical
+	                                ///< method
+	void switch_on_control_histograms(const std::string & file_name);
+	                                ///< this methods requests control
+	                                ///< histograms from the algorithms;
+	                                ///< the algorithm will write them to
+	                                ///< ROOT file called "file_name"
+	void switch_off_control_histograms(void);
+	                                ///< the algorithm does not produce
+					///< controll histograms (this is the
+					///< default)
+	void forceMonotony(void);
+					///< force r(t) to be monotonically
+					///< increasing
+	void doNotForceMonotony(void);
+					///< do not force r(t) to be
+					///< monotonically increasing
+	void doSmoothing(void);
+									///< requires that the r-t relationship
+									///< will be smoothened using the
+									///< conventional autocalibration after
+									///< convergence
+	void noSmoothing(void);
+									///< do not smoothen the r-t relationship
+									///< after convergence
+	void doParabolicExtrapolation(void);
+									///< requires that parabolic extrapolation
+                                    ///< will be used for small and large radii
+	void noParabolicExtrapolation(void);
+									///< no parabolic extrapolation is done
+
+// methods required by the base class "IMdtCalibration" //
+	const IMdtCalibrationOutput * analyseSegments(
+				const std::vector<MuonCalibSegment*> & seg);
+	                                ///< perform the full autocalibration
+	                                ///< including iterations
+	                                ///< (required since
+	                                ///< MdtCalibInterfaces-00-01-06)
+	bool handleSegment(MuonCalibSegment & seg);
+	                                ///< analyse the segment "seg"
+	                                ///< (this method was required before
+	                                ///< MdtCalibInterfaces-00-01-06)
+	void setInput(const IMdtCalibrationOutput * rt_input);
+	                                ///< set the r-t relationship,
+					///< the internal autocalibration
+					///< objects are reset
+	bool analyse(void);
+	                                ///< perform the autocalibration with
+					///< the segments acquired so far
+	bool converged(void) const;
+	                                ///< returns true, if the
+	                                ///< autocalibration has converged
+	const IMdtCalibrationOutput * getResults(void) const;
+	                                ///< returns the final r-t relationship
+
+private:
+// options //
+	bool m_control_histograms; // = true, if control histograms should be
+	                           //         produces
+	bool m_split_into_ml; // = true, if segments should be restricted to the
+	                      //         multilayers;
+	                      // = false, if segments over both multilayers are
+	                      //         allowed
+	bool m_full_matrix; // = true, if the full matrix relating the errors in
+	                    //         the r-t relationship to the residuals
+	                    //         should be used;
+			    // = false, if a diagonal matrix should be used;
+	                    //          in this case the algorithm is equivalent
+	                    //          to conventional method
+	bool m_fix_min; // = true: fix r(t_min)
+	bool m_fix_max; // = true: fix r(t_max)
+	int m_max_it; // maximum number of iterations
+	bool m_force_monotony; // = true if r(t) is forced to monotonically
+			       //        increasing, false otherwise
+
+// bookkeeping //
+	int m_nb_segments; // number of segments passed to the algorithm
+	int m_nb_segments_used; // number of segments used by the algorithm
+	int m_iteration; // current iteration
+	bool m_multilayer[2]; // m_multilayer[k] = true, if there was a segment
+	                      //                   extending to multilayer k+1
+
+// r-t quality //
+	int m_status; // m_status: 0: no covergence yet,
+	                 //           1: convergence, r-t is reliable,
+		         //           2: convergence, r-t is unreliable
+	double m_rt_accuracy; // r-t accuracy (CLHEP::mm) of the input r-t
+	double m_rt_accuracy_previous; // r-t accuracy of the previous iteration
+	                               // (used in the convergence criterion)
+	double m_chi2_previous; 
+	                  // average chi^2 per degrees of freedom from the
+			  // previous iteration (set to a large initial value
+	                  // to force at least two iterations);
+	                  // if an iteration gives a larger average than the
+	                  // pervious iteration, the algorithm has converged
+	double m_chi2; // average chi^2 per degrees of freedom,
+	               // if an iteration gives a larger average than the
+	               // pervious iteration, the algorithm has converged
+
+// r-t relationship //
+	const IRtRelation * m_rt; // pointer to the input r-t relationship
+	double m_t_length; // size of the drift time interval
+	double m_t_mean; // mean value of the drift time interval
+
+// r-t output //
+	IRtRelation * m_rt_new; // r-t as determined by the autocalibration
+	RtCalibrationOutput * m_output; // class holding the results of the
+	                                // autocalibration
+
+// straight-segment fitting //
+	double m_r_max; // maximum value for accepted drift radii
+	QuasianalyticLineReconstruction m_tracker; // quasianalytic
+	                                           // straight-line segment
+	                                           // finder, used because it
+	                                           // performs a pattern
+	                                           // recognition
+
+// autocalibration objects //
+	bool m_do_smoothing; // = true: the r-t relationship is smoothened after
+						 //         convergence, no smoothing is done
+						 //         otherwise
+	bool m_do_parabolic_extrapolation; // = true: parabolic extrapolation is
+                                       //         done for small and large radii
+                                       // = false: no parabolic extrapolation is
+                                       //          done
+	unsigned int m_order; // order of the polynomial describing the
+	                      // correction to the r-t relationship
+	std::vector<CLHEP::HepVector> m_U; // vector of base function values
+	CLHEP::HepSymMatrix m_A; // coefficient matrix of the final autocalibration
+	                  // equation
+	CLHEP::HepVector m_alpha; // vector of fit parameters, i.e. the coefficients
+	                   // of the correction polynomial
+	CLHEP::HepVector m_b; // m_A*m_alpha = m_b (final autocalibration equation)
+
+// Legendre polynomial //
+	BaseFunction *m_base_function; // pointer to the base function u
+
+// control histograms //
+	TFile *m_tfile; // ROOT file
+	TH1F *m_cut_evolution; // cut evolution histogram
+	TH1F *m_nb_segment_hits; // number of hits on the segments
+	TH1F *m_CL; // confidence level distribution of the selected segments
+	TH2F *m_residuals; // residual distribution
+
+// private methods //
+	void init(const double & rt_accuracy, const unsigned int & func_type,
+		const unsigned int & ord,
+		const bool & split, const bool & full_matrix,
+		const bool & fix_min, const bool & fix_max,
+		const int & max_it,
+		bool do_smoothing,
+        bool do_parabolic_extrapolation);
+	                        // initialization method:
+							// rt_accuracy = estimated r-t accuracy,
+	                        // func_type: type of function to be used for
+	                        //            the r-t correction;
+	                        //     = 1: Legendre polynomial,
+	                        //     = 2: Chebyshev polynomial,
+	                        //     = 3: polygon
+	                        // ord = "order" ot the r-t correction function
+	                        // split = true forces the algorithm to restrict
+	                        // segments to multilayers;
+	                        // full_matrix = true forces the algorithm ti
+	                        // use the full matrix relating the errors in
+	                        // in r(t) to the residuals; otherwise a unit
+	                        // matrix is used;
+	                        // fix_min, fix_max=true: fix r(t_min), r(t_max);
+							// do_smoothing: smoothen the r-t relationship
+							// after convergence if do_smoothing = true;
+                            // do_parabolic_extrapolation: do or not do
+                            // parabolic extrapolation for small and large
+                            // radii;
+                            // max_it: maximum number of iterations
+	double t_from_r(const double & r);
+	                        // get t(r) for the input r-t relationship,
+				// the method is auxiliary and not optimized;
+				// it will disappear when the t(r) will be
+				// available in the MuonCalib framework
+
+	void display_segment(MuonCalibSegment * segment,
+						std::ofstream & outfile);
+
+    RtRelationLookUp * performParabolicExtrapolation(const bool & min,
+                            const bool & max,
+                            const IRtRelation & in_rt);
+                            // use parabolic extrapolations on the given r-t
+                            // relationship in_rt;
+                            // min: if true, use parabolic extrapolation towards
+                            //      r=0;
+                            // max: if true, use parabolic extrapolation towards
+                            //      r=r_max;
+	
+	MeanRMS m_track_slope;
+	MeanRMS m_track_position; //mean and rms of track slope and position
+	
+	
+
+};
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationCurved.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationCurved.h
new file mode 100644
index 0000000000000..adc89c73aa378
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationCurved.h
@@ -0,0 +1,352 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 10.05.2008, AUTHOR: OLIVER KORTNER
+// Modified: 01.03.2009 by O. Kortner, parabolic extrapolation added.
+//           15.03.2009 by O. Kortner, smoothing added.
+//           18.03.2009 by O. Kortner, method performParabolicExtrapolation
+//                                     added.
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#ifndef MuonCalib_RtCalibrationCurvedH
+#define MuonCalib_RtCalibrationCurvedH
+
+//:::::::::::::::::::::::::::::::
+//:: CLASS RtCalibrationCurved ::
+//:::::::::::::::::::::::::::::::
+
+/// \class RtCalibrationCurved
+///
+/// This class performs the autocalibration of MDT chambers from the residuals
+/// of curved (parabolic) segments. The method used is a generalization of the
+/// analytic autocalibration developed by Deile, Hessey, and Staude (see
+/// ATL-MUON-2004-021).
+///
+/// \author Oliver.Kortner@CERN.CH
+///
+/// \date 10.05.2008
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+// STL //
+#include <vector>
+#include <string>
+#include <list>
+
+// CLHEP //
+#include "CLHEP/Matrix/SymMatrix.h"
+#include "CLHEP/Matrix/Vector.h"
+
+// ROOT //
+#include "TFile.h"
+#include "TH1F.h"
+#include "TH2F.h"
+
+// MuonCalib //
+#include "MdtCalibInterfaces/IMdtCalibration.h"
+
+#include "GeoPrimitives/GeoPrimitives.h"
+
+namespace MuonCalib {
+
+class IMdtCalibrationOutput;
+class IRtRelation;
+class RtRelationLookUp;
+class RtCalibrationOutput;
+class CurvedPatRec;
+class MuonCalibSegment;
+class BaseFunction;
+class Legendre_polynomial;
+class CurvedLine;
+class MultilayerRtDifference;
+
+class RtCalibrationCurved : public IMdtCalibration {
+
+public:
+// Constructors //
+    RtCalibrationCurved(std::string name);
+    ///< Default constructor: r-t accuracy is set to 0.5 mm.
+    ///< The r-t accuracy is used internally to distinguish between good
+    ///< and bad segments.
+    ///< By default Legendre polynomials are used to parametrize the
+    ///< r-t correction.
+    ///< The order of the r-t correction polynomial is set to 15.
+    ///< Segments are not restricted to single multilayers. The full matrix
+    ///< relating the errors in r(t) to the residuals is used.
+    ///< No parabolic extrapolations are used.
+	///< By default no smoothing is applied after convergence.
+
+    RtCalibrationCurved(std::string name,
+                        const double & rt_accuracy,
+                        const unsigned int & func_type,
+                        const unsigned int & ord,
+                        const bool & fix_min,
+                        const bool & fix_max,
+                        const int & max_it,
+                        bool do_parabolic_extrapolation=false,
+                        bool do_smoothing=false,
+			bool do_multilayer_rt_scale=false);
+    ///< Constructor.
+    ///< \param rt_accuracy r-t accuracy in mm. The r-t accuracy is used
+    ///<        internally to distinguish between good and bad segments.
+    ///< \param func_type  Type of function to be used for the r-t correction;
+    ///<        = 1: Legendre polynomial (default),
+    ///<        = 2: Chebyshev polynomial,
+    ///<        = 3: polygon equidistant in r.
+    ///< \param ord Order of the r-t correction function (15 is default).
+    ///< \param fix_min =true: r(t0) is fixed in the autocalibration procedure
+    ///<        (this is default).
+    ///< \param fix_max =true: r(tmax) is fixed in the autocalibration procedure
+    ///<        (false is default).
+    ///< \param max_it Maximum number of iterations (20 by default).
+    ///< \param do_parabolic_extrapolation Use parabolic extrapolations for
+    ///<        small and larged drift radii.
+	///< \param do_smoothing Smoothing of the r-t relations after convergence.
+
+// Destructor //
+    ~RtCalibrationCurved(void);
+    ///< Destructor.
+
+// Methods //
+// get-methods //
+    double reliability(void) const;
+                                    ///< get the reliability of the final r-t
+                                    ///< relationship:
+                                    ///< 0: no convergence yet
+                                    ///< 1: convergence, r(t) is reliable
+                                    ///< 2: convergence, r(t) is unreliable
+    double estimatedRtAccuracy(void) const;
+                                    ///< get the estimated r-t quality (CLHEP::mm),
+                                    ///< the accuracy of the input r-t is
+                                    ///< computed at the end of the
+                                    ///< iteration; in order to get the
+                                    ///< accuracy of the final r-t, the
+                                    ///< algorithm has to be rerun with the
+                                    ///< final r-t as an input
+    int numberOfSegments(void) const;
+                                    ///< get the number of segments which
+                                    ///< were passed to the algorithm
+    int numberOfSegmentsUsed(void) const;
+                                    ///< get the number of segments which
+                                    ///< are used in the autocalibration
+    int iteration(void) const;
+                                    ///< get the number of the current
+                                    ///< iteration
+	bool smoothing(void) const;
+									///< returns true, if the r-t relationship
+									///< will be smoothened using the
+									///< conventional autocalibration after
+									///< convergence;
+									///< returns false otherwise
+
+// set-method //
+    void setEstimateRtAccuracy(const double & acc);
+                                    ///< set the estimated r-t accuracy =acc
+    void fullMatrix(const bool & yes_or_no);
+                                    ///< yes_or_no=true: the full matrix
+                                    ///< relating the errors in the r-t
+                                    ///< relationship to the residuals
+                                    ///< is used
+                                    ///< yes_or_no=false: unit matrix is
+                                    ///< used (algorithm is equivalent to
+                                    ///< to the conventional/classical
+                                    ///< method
+    void switch_on_control_histograms(const std::string & file_name);
+                                    ///< this methods requests control
+                                    ///< histograms from the algorithms;
+                                    ///< the algorithm will write them to
+                                    ///< ROOT file called "file_name"
+    void switch_off_control_histograms(void);
+                                    ///< the algorithm does not produce
+                                    ///< controll histograms (this is the
+                                    ///< default)
+    void forceMonotony(void);
+                                    ///< force r(t) to be monotonically
+                                    ///< increasing (this is default)
+    void doNotForceMonotony(void);
+                                    ///< do not force r(t) to be
+                                    ///< monotonically increasing
+	void doParabolicExtrapolation(void);
+									///< requires that parabolic extrapolation
+                                    ///< will be used for small and large radii
+	void noParabolicExtrapolation(void);
+									///< no parabolic extrapolation is done
+	void doSmoothing(void);
+									///< requires that the r-t relationship
+									///< will be smoothened using the
+									///< conventional autocalibration after
+									///< convergence
+	void noSmoothing(void);
+									///< do not smoothen the r-t relationship
+									///< after convergence
+
+// methods required by the base class "IMdtCalibration" //
+    const IMdtCalibrationOutput * analyseSegments(
+                                const std::vector<MuonCalibSegment*> & seg);
+                                    ///< perform the full autocalibration
+                                    ///< including iterations
+                                    ///< (required since
+                                    ///< MdtCalibInterfaces-00-01-06)
+    bool handleSegment(MuonCalibSegment & seg);
+                                    ///< analyse the segment "seg"
+                                    ///< (this method was required before
+                                    ///< MdtCalibInterfaces-00-01-06)
+    void setInput(const IMdtCalibrationOutput * rt_input);
+                                    ///< set the r-t relationship,
+                                    ///< the internal autocalibration
+                                    ///< objects are reset
+    bool analyse(const std::vector<MuonCalibSegment*> & seg);
+                                    ///< perform the autocalibration with
+                                    ///< the segments acquired so far
+    bool converged(void) const;
+                                    ///< returns true, if the
+                                    ///< autocalibration has converged
+    const IMdtCalibrationOutput * getResults(void) const;
+                                    ///< returns the final r-t relationship
+
+private:
+// options //
+    bool m_control_histograms; // = true, if control histograms should be
+                               //         produces
+    bool m_fix_min; // = true: fix r(t_min)
+    bool m_fix_max; // = true: fix r(t_max)
+    int m_max_it; // maximum number of iterations
+    bool m_force_monotony; // = true if r(t) is forced to monotonically
+                           //   increasing, false otherwise
+    bool m_do_multilayer_rt_scale; // determine multilayer rt scaling
+
+// bookkeeping //
+    int m_nb_segments; // number of segments passed to the algorithm
+    int m_nb_segments_used; // number of segments used by the algorithm
+    int m_iteration; // current iteration
+    bool m_multilayer[2]; // m_multilayer[k] = true, if there was a segment
+                          //                   extending to multilayer k+1
+
+// r-t quality //
+    int m_status; // m_status: 0: no covergence yet,
+                  //           1: convergence, r-t is reliable,
+                  //           2: convergence, r-t is unreliable
+    double m_rt_accuracy; // r-t accuracy (CLHEP::mm) of the input r-t
+    double m_rt_accuracy_previous; // r-t accuracy of the previous iteration
+                                   // (used in the convergence criterion)
+    double m_chi2_previous; 
+                      // average chi^2 per degrees of freedom from the
+                      // previous iteration (set to a large initial value
+                      // to force at least two iterations);
+                      // if an iteration gives a larger average than the
+                      // pervious iteration, the algorithm has converged
+    double m_chi2; // average chi^2 per degrees of freedom,
+                   // if an iteration gives a larger average than the
+                   // pervious iteration, the algorithm has converged
+
+// r-t relationship //
+    const IRtRelation * m_rt; // pointer to the input r-t relationship
+    double m_t_length; // size of the drift time interval
+    double m_t_mean; // mean value of the drift time interval
+
+// r-t output //
+    IRtRelation * m_rt_new; // r-t as determined by the autocalibration
+    RtCalibrationOutput * m_output; // class holding the results of the
+                                    // autocalibration
+    MultilayerRtDifference * m_multilayer_rt_difference;
+// curved-segment fitting //
+    double m_r_max; // maximum value for accepted drift radii
+    CurvedPatRec *m_tracker; // curved segment finder (used for track fitting)
+  // The following three objects are needed for autocalibration formulae.
+  
+  
+  
+    CLHEP::HepSymMatrix m_M_track; // segment parameters = m_M_track^-1*m_b_track
+    CLHEP::HepSymMatrix m_M_track_inverse; // inverse of m_M_track
+
+// autocalibration objects //
+	bool m_do_parabolic_extrapolation; // = true: parabolic extrapolation is
+                                       //         done for small and large radii
+                                       // = false: no parabolic extrapolation is
+                                       //          done
+	bool m_do_smoothing; // = true: the r-t relationship is smoothened after
+						 //         convergence, no smoothing is done
+						 //         otherwise
+    unsigned int m_order; // order of the polynomial describing the
+                          // correction to the r-t relationship
+    std::vector<CLHEP::HepVector> m_U; // vector of base correction function values
+    std::vector<CLHEP::HepVector> m_U_weighted; // vector of base correction function
+                                         // values weighted by the inverse
+                                         // standard deviation of the radius
+                                         // measurements
+    CLHEP::HepSymMatrix m_A; // coefficient matrix of the final autocalibration
+                      // equation
+    CLHEP::HepVector m_alpha; // vector of fit parameters, i.e. the coefficients
+                       // of the correction polynomial
+    CLHEP::HepVector m_b; // m_A*m_alpha = m_b (final autocalibration equation)
+
+// correction functions //
+    BaseFunction *m_base_function; // pointer to the base function u
+    Legendre_polynomial *m_Legendre; // pointer to the Legendre polynomial
+                                     // describing the curved line
+
+// control histograms //
+    TFile *m_tfile; // ROOT file
+    TH1F *m_cut_evolution; // cut evolution histogram
+    TH1F *m_nb_segment_hits; // number of hits on the segments
+	TH1F *m_pull_initial; // initial pull distribution
+	TH1F *m_pull_final; // final pull distribution after convergence
+    TH2F *m_residuals_initial; // initial residual distribution
+    TH2F *m_residuals_final; // final residual distribution after convergence
+    
+
+// private methods //
+    void init(const double & rt_accuracy, const unsigned int & func_type,
+                const unsigned int & ord,
+                const bool & fix_min, const bool & fix_max,
+                const int & max_it,
+                bool do_parabolic_extrapolation,
+		        bool do_smoothing,
+			bool do_multilayer_rt_scale);
+                            // initialization method:
+                            // rt_accuracy = estimated r-t accuracy,
+                            // func_type: type of function to be used for
+                            //            the r-t correction;
+                            //     = 1: Legendre polynomial,
+                            //     = 2: Chebyshev polynomial,
+                            //     = 3: polygon
+                            // ord = "order" ot the r-t correction function
+                            // split = true forces the algorithm to restrict
+                            // segments to multilayers;
+                            // fix_min, fix_max=true: fix r(t_min), r(t_max)
+                            // max_it: maximum number of iterations
+                            // do_parabolic_extrapolation: do or do not use
+                            //    parabolic extrapolations for small and large
+                            //    radii;
+							// do_smoothing: smoothen the r-t relationship
+							//    after convergence if do_smoothing = true
+     double t_from_r(const double & r);
+                            // get t(r) for the input r-t relationship,
+                            // the method is auxiliary and not optimized;
+                            // it will disappear when the t(r) will be
+                            // available in the MuonCalib framework
+    void display_segment(MuonCalibSegment * segment,
+                        std::ofstream & outfile,
+						const CurvedLine * curved_segment);
+                            // write out a simple PAW macro displaying the
+                            // segment; if the pointer "curved_segment" equals
+                            // 0, a straight line as stored in segment is drawn;
+                            // the curved line is used otherwise
+    RtRelationLookUp * performParabolicExtrapolation(const bool & min,
+                            const bool & max,
+                            const IRtRelation & in_rt);
+                            // use parabolic extrapolations on the given r-t
+                            // relationship in_rt;
+                            // min: if true, use parabolic extrapolation towards
+                            //      r=0;
+                            // max: if true, use parabolic extrapolation towards
+                            //      r=r_max;
+};
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationIntegration.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationIntegration.h
new file mode 100644
index 0000000000000..26cfcaaa1a5a9
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationIntegration.h
@@ -0,0 +1,127 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 02.02.2007, AUTHOR: OLIVER KORTNER
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#ifndef MuonCalib_RtCalibrationIntegrationH
+#define MuonCalib_RtCalibrationIntegrationH
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+// STL //
+#include <string>
+#include <vector>
+
+// MuonCalib //
+#include "MdtCalibInterfaces/IMdtCalibration.h"
+#include "MdtCalibInterfaces/IMdtCalibrationOutput.h"
+#include "MdtCalibData/IRtRelation.h"
+#include "MdtCalibRt/RtCalibrationOutput.h"
+#include "MdtCalibInterfaces/IMdtSegmentFitter.h"
+#include "MuonCalibEventBase/MuonCalibSegment.h"
+
+namespace MuonCalib {
+
+//::::::::::::::::::::::::::::::::::::
+//:: CLASS RtCalibrationIntegration ::
+//::::::::::::::::::::::::::::::::::::
+
+/// \class RtCalibrationIntegration
+///
+/// This class allows the user to obtain an r-t relationship from the drift
+/// time spectrum in a given calibration region. The user can ask the class
+/// to restrict the r-t determination on hit on the segments or to use close
+/// hits too. The algorithms performs a t0 and tmax fit in order to get t(r=0)
+/// and t(r=rmax) right.
+///
+/// \author Oliver.Kortner@CERN.CH
+///
+/// \date 02.02.2007
+
+class RtCalibrationIntegration : public IMdtCalibration {
+
+public:
+// Constructors //
+	RtCalibrationIntegration(std::string name) : IMdtCalibration(name) {
+		init(false, 14.6,13.0,14.0, false);
+		}
+	///< Default constructor. Only hits on the segment are used by the
+	///< algorithm by default. The maximum drift radius is set to  14.6 mm.
+
+	RtCalibrationIntegration(std::string name,
+				 bool close_hits,
+				 double r_max,
+				 double lower_extrapolation_radius,
+				 double upper_extrapolation_radius, 
+				 bool  add_tmax_difference
+				 ) : IMdtCalibration(name) {
+		init(close_hits, r_max, lower_extrapolation_radius, upper_extrapolation_radius,  add_tmax_difference);
+		}
+	///< Constructor. If close_hits is set to true, also close hits are
+	///< used. The maximum drift radius is set to r_max [mm].
+
+// Methods //
+// get-methods //
+	unsigned int number_of_hits_used(void) const;
+					///< get the number of hits used in the
+					///< r-t determination
+
+// methods required by the base class "IMdtCalibration" //
+	const IMdtCalibrationOutput * analyseSegments(
+				const std::vector<MuonCalibSegment*> & seg);
+	                                ///< determine r(t)
+	bool handleSegment(MuonCalibSegment & seg);
+					///< analyse the segment "seg"
+	void setInput(const IMdtCalibrationOutput * rt_input);
+					///< the method is empty as no initial
+					///< r-t relationship is required by
+					///< the algorithm
+	bool analyse(void);
+	                                ///< perform the integration method
+	bool converged(void) const;
+	                                ///< returns true, if the integration
+					///< method has been performed
+	const IMdtCalibrationOutput * getResults(void) const;
+	                                ///< returns the final r-t relationship
+
+private:
+// options //
+	bool m_close_hits; // = true, if close hits should be used,
+			   // = false, if only hits on segments should be used
+        double m_lower_extrapolation_radius;///< sets the lower radius to perform the
+        double m_upper_extrapolation_radius;///< parabolic extrapolation. the parabolic fit will be 
+                                            ///< performet between the lower extrapolation radius 
+                                            ///< and the upper extrapolation value and be extrapolated
+                                            ///< till r_max
+        bool  m_add_tmax_difference;
+// drift-time spectrum //
+        
+	std::vector<std::pair<double, bool> > m_t_drift; // measured drift times
+// r(t) //
+	IRtRelation * m_rt; // pointer to the final r-t relationship
+	unsigned int m_nb_hits_used; // number of hits used in the algorithm
+	unsigned int m_nb_segments_used; // number of segments used
+	double m_r_max; // maximum drift radius
+	RtCalibrationOutput * m_output; // class holding the results of the
+	                                // autocalibration
+
+// private methods //
+	void init(bool close_hits,
+		  double r_max,
+		  double lower_extrapolation_radius,
+		  double higher_extrapolation_radius, 
+		  bool  add_tmax_difference );
+				// initialize the class, close hits are used, 
+				// if close_hits is set to true; the maximum
+				// drift radius is set to r_max
+
+};
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationOutput.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationOutput.h
new file mode 100644
index 0000000000000..5f1b089b6f16e
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtCalibrationOutput.h
@@ -0,0 +1,36 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef RTCALIBRATIONOUTPUT_H
+#define RTCALIBRATIONOUTPUT_H
+
+#include "MdtCalibInterfaces/IMdtCalibrationOutput.h"
+#include "MdtCalibData/RtFullInfo.h"
+#include "MdtCalibData/IRtRelation.h"
+
+namespace MuonCalib{
+/** 
+@class RtCalibrationOutput
+Class for communication between event loop and rt calibration algorithm
+contains only a rt relation for now.
+    
+*/
+
+class RtCalibrationOutput : public IMdtCalibrationOutput {
+ public:
+  RtCalibrationOutput( const IRtRelation* rt_rel, const RtFullInfo* fi ) : 
+  IMdtCalibrationOutput("RtCalibrationOutput"), m_rtRelation(rt_rel), m_fullInfo(fi) {}
+
+  /** access to private attributes */
+  const IRtRelation* rt() const { return m_rtRelation; }  
+  const RtFullInfo* fullInfo() const { return m_fullInfo; } 	 
+
+ private:
+  // pointer to a IRtRelation instance
+  const IRtRelation* m_rtRelation;
+  /** additonal info for validation */ 	 
+  const RtFullInfo* m_fullInfo;  
+};
+}
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtParabolicExtrapolation.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtParabolicExtrapolation.h
new file mode 100644
index 0000000000000..d367733080e89
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/MdtCalibRt/RtParabolicExtrapolation.h
@@ -0,0 +1,86 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 10.11.2008, AUTHOR: OLIVER KORTNER
+// Modified: 28.02.2009 by O. Kortner and J. von Loeben, extend extrapolation
+//                      features
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//::::::::::::::::::::::::::::::::::::
+//:: CLASS RtParabolicExtrapolation ::
+//::::::::::::::::::::::::::::::::::::
+
+/// \class RtParabolicExtrapolation
+///
+/// This class is used to fit a parabola to the r(t) curve for in 
+/// $[r_{min}, r_{max}]$ and to set r(t) according to this parabola for
+/// $r_{ext}>r>r_{max}$, if $r_{ext}>r_{max}$, and $r_{ext}<r<r_{min}$,
+/// if $r_{ext}<r_{min}$. The boundaries of the fit interval can be changed by 
+/// the user.
+///
+/// \author Oliver.Kortner@CERN.CH
+///
+/// \date 28.02.2009
+
+#ifndef MuonCalib_RtParabolicExtrapolationH
+#define MuonCalib_RtParabolicExtrapolationH
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+
+namespace MuonCalib {
+class IRtRelation;
+class RtRelationLookUp;
+
+class RtParabolicExtrapolation {
+
+public:
+// Constructors //
+    RtParabolicExtrapolation(void);
+    ///< Default constructor.
+
+// Methods //
+    RtRelationLookUp getRtWithParabolicExtrapolation(
+                                    const IRtRelation & in_rt,
+                                    const double & r_min=13.0,
+                                    const double & r_max=14.0) const;
+	                                ///< get an r-t relationship which is
+                                    ///< equivalent to the input relationship
+                                    ///< in_rt for r<r_min and has r(t) for
+                                    ///< r>r_max according to a parabola fitted
+                                    ///< in [r_min, r_max];
+                                    ///< this method is there for backward
+                                    ///< compatibility
+    RtRelationLookUp getRtWithParabolicExtrapolation(
+                        const IRtRelation & in_rt,
+                        const double & r_min,
+                        const double & r_max,
+                        const double & r_ext,
+                        const std::vector<SamplePoint> & add_fit_points) const;
+                                    ///< The method fits a parabola to the r-t
+                                    ///< points in $[r_{min}, r_{max}]$ and the
+                                    ///< additional user points add_fit_points.
+                                    ///< The input r-t relationship in_rt is
+                                    ///< replaced by the parabola in
+                                    ///< $[r_{ext}, r_{min}]$ is
+                                    ///< $r_{ext}<r_{min}$ and in 
+                                    ///< $[r_{max}, r_{ext}]$ if
+                                    ///< $r_{ext}>r_{max}$.
+
+private:
+    double t_from_r(const double & r, const IRtRelation & in_rt) const;
+                                    // get t(r) as defined in in_rt
+    double get_max_t_at_r(const double & r, const IRtRelation & in_rt) const;
+                                    // get the largest time of the r-t
+                                    //  relationship in_rt corresponding to
+                                    // the given radius r
+
+};
+
+}
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/cmt/requirements b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/cmt/requirements
new file mode 100644
index 0000000000000..e2044bc0f304b
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/cmt/requirements
@@ -0,0 +1,31 @@
+package MdtCalibRt
+
+author Fabrizio Petrucci 
+
+use AtlasPolicy           AtlasPolicy-*
+private
+apply_tag ROOTMathLibs
+apply_tag ROOTGraphicsLibs 
+apply_tag ROOTRooFitLibs
+end_private
+
+use AtlasROOT           AtlasROOT-*   External
+use AtlasCLHEP          AtlasCLHEP-*   External
+
+use MuonCalibEventBase    *       MuonSpectrometer/MuonCalib 
+use MuonCalibMath         *       MuonSpectrometer/MuonCalib/MuonCalibUtils
+use MdtCalibInterfaces    *       MuonSpectrometer/MuonCalib/MdtCalib    
+use MdtCalibData          *       MuonSpectrometer/MuonCalib/MdtCalib    
+use MdtCalibFitters       *       MuonSpectrometer/MuonCalib/MdtCalib    
+use GeoPrimitives	  *	  DetectorDescription
+
+include_dirs "$(MdtCalibRt_root)"
+
+library MdtCalibRt  ../src/*.cxx
+apply_pattern installed_library
+
+private
+use MdtCalibT0            *       MuonSpectrometer/MuonCalib/MdtCalib
+#use MuonCalibStl          *       MuonSpectrometer/MuonCalib/MuonCalibUtils
+#use MdtCalibUtils         *       MuonSpectrometer/MuonCalib/MdtCalib
+
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/doc/mainpage.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/doc/mainpage.h
new file mode 100644
index 0000000000000..013387dc5accd
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/doc/mainpage.h
@@ -0,0 +1,40 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+@mainpage MdtCalibRt Package
+@author Fabrizio.Petrucci@cern.ch 
+                                                                                
+@section MdtCalibRtIntro Introduction
+This package is foreseen to collect the various implementations of Mdt Rt calibration. 
+                                                                                
+@section MdtCalibRtOverview Class Overview
+The MdtCalibRt package contains at the moment the following classes:
+
+- MuonCalib::RtCalibrationAnalytic: This class performs the analytic autocalibration whose basic ideas were developed by Mario Deile (see ATL-MUON-2004-021)
+
+- MuonCalib::RtCalibrationIntegration: This class allows the user to obtain an r-t relationship from the drift time spectrum in a given calibration region. 
+
+- MuonCalib::RtCalibrationClassic: Implementation of a rt calibration using the classical approach (iterative residuals minimization)
+- MuonCalib::ClassicSettings: Parameters needed by the Rt classic calibrations which should be provided to the RtCalibrationClassic constructor
+
+- MuonCalib::RtCalibrationOutput: Class for communication between event loop and rt calibration algorithm contains only a rt relation for now
+
+- MuonCalib::RtHistos: Set of histograms used in an iteration of RtCalibrationClassic
+                                                                                
+@ref used_MdtCalibRt
+                                                                                
+@ref requirements_MdtCalibRt
+*/
+                                                                                
+/**
+@page used_MdtCalibRt Used Packages
+@htmlinclude used_packages.html
+*/
+                                                                                
+/**
+@page requirements_MdtCalibRt Requirements
+@include requirements
+*/
+
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/AdaptiveResidualSmoothing.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/AdaptiveResidualSmoothing.cxx
new file mode 100644
index 0000000000000..5427fb0c89711
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/AdaptiveResidualSmoothing.cxx
@@ -0,0 +1,484 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 29.07.2008, AUTHOR: OLIVER KORTNER
+// 05.02.2010, JOERG v.LOEBEN
+//      - tuning the method on cosmics
+//      - new way to determine the binning according to satatistics
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+// standard C++ //
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+
+// ROOT //
+#include "TSpline.h"
+
+// MuonCalib //
+#include "MuonCalibMath/BaseFunctionFitter.h"
+#include "MuonCalibMath/PolygonBase.h"
+#include "MuonCalibMath/ConstantContentBinMaker.h"
+#include "MdtCalibRt/AdaptiveResidualSmoothing.h"
+#include "MdtCalibData/IRtRelation.h"
+#include "MuonCalibMath/DataPoint.h"
+#include "CLHEP/Matrix/Vector.h"
+
+//::::::::::::::::::::::::
+//:: NAMESPACE SETTINGS ::
+//::::::::::::::::::::::::
+
+using namespace std;
+using namespace CLHEP;
+using namespace MuonCalib;
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: IMPLEMENTATION OF METHODS DEFINED IN THE CLASS ::
+//::           AdaptiveResidualSmoothing            ::
+//::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: CONSTRUCTOR ::
+//:::::::::::::::::
+
+AdaptiveResidualSmoothing::AdaptiveResidualSmoothing(void) {
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::
+//:: METHOD clear ::
+//::::::::::::::::::
+
+void AdaptiveResidualSmoothing::clear(void) {
+
+	m_residual_point.clear();
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::
+//:: METHOD addResidual ::
+//::::::::::::::::::::::::
+
+void AdaptiveResidualSmoothing::addResidual(const double & radius,
+													const double & residual) {
+
+// make the data point //
+	CLHEP::HepVector point(2);
+	point[0] = radius;
+	point[1] = residual;
+	DataPoint residual_point(point, 0);
+
+// store the data point //
+	m_residual_point.push_back(residual_point);
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::::::
+//:: METHOD addResidualsFromSegment ::
+//::::::::::::::::::::::::::::::::::::
+
+bool AdaptiveResidualSmoothing::addResidualsFromSegment(
+					MuonCalibSegment & seg, bool curved, double road_width) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	CLHEP::HepVector point(2); // auxiliary point
+	IMdtPatRecFitter *fitter(0);
+
+////////////////////////////////////////
+// RESIDUAL DETERMINATION AND STORAGE //
+////////////////////////////////////////
+
+// perform fit //
+	if (curved) {
+
+  // set road width /
+  		m_cfitter.setRoadWidth(road_width);
+
+  // set fitter pointer //
+  		fitter = &m_cfitter;
+		
+	} else {
+
+  // set road width /
+  		m_sfitter.setRoadWidth(road_width);
+
+  // set fitter pointer //
+  		fitter = &m_sfitter;
+		
+	}
+
+	fitter->SetRefineSegmentFlag(false);
+
+  // prepare hit selection to exclude the first hit from the fit //
+//     vector<unsigned int> hit_selection(seg.mdtHitsOnTrack(), 0);
+//     hit_selection[0] = 1;
+
+  // perform the track fit; return in case of failure //
+	if (!fitter->fit(seg)) {
+//		cout << seg.mdtHitsOnTrack() << endl;
+		return false;
+	}
+
+  // reject bad fits //
+  	if (curved) {
+		if (m_cfitter.chi2PerDegreesOfFreedom()>50) {
+			return false;
+		}
+	} else {
+		if (m_sfitter.chi2PerDegreesOfFreedom()>50) {
+			return false;
+		}
+	}
+
+  // store the residuals //
+// 	static ofstream resfile("res.txt");
+	for (unsigned int k=0; k<fitter->trackHits().size(); k++) {
+		point[0] = fitter->trackHits()[k]->driftRadius();
+		point[1] = fitter->trackHits()[k]->driftRadius()-
+				  fabs(fitter->trackHits()[k]->signedDistanceToTrack());
+// 		resfile << point[0] << "\t" << point[1] << endl;
+		DataPoint residual_point(point, 0);
+		m_residual_point.push_back(residual_point);
+	}
+
+	return true;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::::::::::
+//:: METHOD performSmoothing(., ., ., .) ::
+//:::::::::::::::::::::::::::::::::::::::::
+
+RtRelationLookUp AdaptiveResidualSmoothing::performSmoothing(
+								const IRtRelation & rt_rel,
+								unsigned int nb_entries_per_bin,
+								bool fix_t_min, bool fix_t_max) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	ConstantContentBinMaker bin_maker(m_residual_point, 0.001);
+	vector<unsigned int> ref_coord(1);
+
+////////////
+// CHECKS //
+////////////
+
+	if (m_residual_point.size()==0) {
+		cerr << endl
+			 << "Class AdaptiveResidualSmoothing, method performSmoothing: "
+			 << "ERROR!\n"
+			 << "No residuals stored.\n";
+		exit(1);
+	}
+
+	if (m_residual_point.size()<nb_entries_per_bin) {
+		cerr << endl
+			 << "Class AdaptiveResidualSmoothing, method performSmoothing: "
+			 << "ERROR!\n"
+			 << "Not enough residuals stored.\n";
+		exit(1);
+	}
+
+/////////////////////
+// PERFORM BINNING //
+/////////////////////
+
+	ref_coord[0] = 0;
+	bin_maker.binDataPoints(nb_entries_per_bin, ref_coord);
+
+//////////////////////////////
+// DETERMINE r-t COORECTION //
+//////////////////////////////
+
+// get a polygon through the bin centres //
+// 	cout << "bin_maker.getBins().size()="
+// 		 << bin_maker.getBins().size() << endl;
+	vector<double> rad(bin_maker.getBins().size());
+	vector<SamplePoint> corr(bin_maker.getBins().size()); 
+	for (unsigned int k=0; k<bin_maker.getBins().size(); k++) {
+		rad[k] = (bin_maker.getBins()[k])->centreOfGravity()[0];
+// 		cout << "rad[" << k << "] = " << rad[k] << endl;
+		corr[k].set_x1(rad[k]);
+		corr[k].set_x2((bin_maker.getBins()[k])->centreOfGravity()[1]);
+		corr[k].set_error(1.0);
+	}
+	sort(rad.begin(), rad.end());
+	
+	vector<double> radi;
+	radi.push_back(rad[0]);
+	unsigned int counter(0);
+	for (unsigned int k=1; k<rad.size(); k++) {
+		if (rad[counter]<rad[k]) {
+			radi.push_back(rad[k]);
+			counter++;
+		}
+	}
+
+	PolygonBase polygon(radi);
+	BaseFunctionFitter fitter(bin_maker.getBins().size());
+	fitter.fit_parameters(corr, 1, corr.size(), &polygon);
+
+// create an improved r-t relationship //
+// 	vector<double> rt_point;
+// 	unsigned int nb_rt_points(60);
+// 	double step_size((rt_rel.radius(rt_rel.tUpper())-
+// 										rt_rel.radius(rt_rel.tLower()))/
+// 										static_cast<double>(nb_rt_points));
+// 	for (double r=rt_rel.radius(rt_rel.tLower());
+// 						r<=rt_rel.radius(rt_rel.tUpper()); r=r+step_size) {
+// 		double t(t_from_r(rt_rel, r));
+// 		rt_point.push_back(t);
+// 		double delta_r(0.0);
+// 		for (unsigned int l=0; l<radi.size(); l++) {
+// 			delta_r = delta_r+fitter.coefficients()[l]*polygon.value(l, 
+// 															rt_rel.radius(t));
+// 		}
+// 		rt_point.push_back(rt_rel.radius(t)-delta_r);
+// 
+// 	}
+// 	RtSpline improved_rt(rt_point);
+	vector<double> rt_params;
+	rt_params.push_back(rt_rel.tLower());
+	rt_params.push_back(0.01*(rt_rel.tUpper()-rt_rel.tLower()));
+//	ofstream outfile("out2.txt");
+	for (double t=rt_rel.tLower(); t<=rt_rel.tUpper(); t=t+rt_params[1]) {
+		double delta_r(0.0);
+		for (unsigned int l=0; l<radi.size(); l++) {
+			delta_r = delta_r+fitter.coefficients()[l]*polygon.value(l, 
+															rt_rel.radius(t));
+		}
+		if (fix_t_min && (rt_rel.radius(t)<0.5)) {
+			delta_r = 0.0;
+		}
+		if (fix_t_max && (rt_rel.radius(t)>14.1)) {
+			delta_r = 0.0;
+		}
+		rt_params.push_back(rt_rel.radius(t)-delta_r);
+	}
+
+	RtRelationLookUp improved_rt(rt_params);
+// 	for (double t=rt_rel.tLower(); t<=rt_rel.tUpper(); t=t+rt_params[1]) {
+// 		outfile << rt_rel.radius(t) << "\t" << improved_rt.radius(t)
+// 				<< "\t" << endl;
+// 	}
+
+	return improved_rt;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::::::::
+//:: METHOD performSmoothing(., ., .) ::
+//::::::::::::::::::::::::::::::::::::::
+
+RtRelationLookUp AdaptiveResidualSmoothing::performSmoothing(
+                                                const IRtRelation & rt_rel,
+                                                const bool & fix_t_min,
+                                                const bool & fix_t_max) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+    unsigned int nb_bins; // number of bins in r
+    unsigned int min_nb_entries_per_bin(20); // minimum number of
+                                             // entries per bin
+    double step_size; // real step size [mm]
+    double r_max(16.0); // maximum drift radius
+    double aux_rad; // auxiliary radius
+    double aux_corr; // auxiliary correction value
+    unsigned int bin_index;
+
+//////////////////////////////////
+// DETERMINE THE NUMBER OF BINS //
+//////////////////////////////////
+
+
+    // take the sqrt from the number of residuals to determine the binsize.
+    // for low stat, a larger statistical error on the bins is allowed
+    // for example:
+    // 1000 segments -> 7.6% and 35 bins
+    // 5000 segments -> 5.1% and 64 bins
+    // 10000 segments-> 4.1% and 91 bins
+    nb_bins =static_cast<unsigned int>( sqrt(m_residual_point.size()/6.) );
+    
+    //calculate min_nb_per_bin
+    min_nb_entries_per_bin = m_residual_point.size() / nb_bins;
+    //cout << "min number of entries/bin: " << min_nb_entries_per_bin << endl;
+
+//////////////////////////////////////
+// RETURN IF THERE ARE NO RESIDUALS //
+//////////////////////////////////////
+
+    if (m_residual_point.size()==0) {
+        cerr << endl
+             << "Class AdaptiveResidualSmoothing, "
+             << "performSmoothing(., ., .): WARNING!\n"
+             << "No residuals are stored. no correction applied to r(t)!\n"
+             << endl;
+    }
+
+    if (nb_bins==0) {
+        nb_bins = 1;
+    }
+    step_size = r_max/static_cast<double>(nb_bins);
+
+//////////////////////////////////////////////////////////////
+// DETERMINE THE AVERAGE RESIDUAL VALUES IN THE RADIAL BINS //
+//////////////////////////////////////////////////////////////
+
+// vector for the correction function //
+	vector<SamplePoint> corr(nb_bins);
+    vector<double> radii(nb_bins); 
+
+// sort the residuals point in the residual value for a simple outlyer //
+// rejection performed later                                           //
+    for (unsigned int k=0; k<m_residual_point.size(); k++) {
+        m_residual_point[k].setReferenceComponent(1);        
+    }
+    sort(m_residual_point.begin(), m_residual_point.end());
+
+// auxiliary data point arrays //
+    vector< vector<const DataPoint *> > sample_points_per_r_bin(nb_bins);
+
+// group data points in r bins //
+    for (unsigned int k=0; k<m_residual_point.size(); k++) {
+        if (fabs(m_residual_point[k].dataVector()[0])>=r_max) {
+            continue;
+        }
+        bin_index = static_cast<unsigned int>(fabs(
+                            m_residual_point[k].dataVector()[0])/step_size);
+        sample_points_per_r_bin[bin_index].push_back(&(m_residual_point[k]));
+    }
+
+// loop over the r bins and determine the r-t corrections //
+//     static ofstream outfile("tmp.txt");
+//     outfile << endl;
+    for (unsigned int bin=0; bin<nb_bins; bin++) {
+
+        aux_rad = 0.0;
+        aux_corr = 0.0;
+
+  // remove the first and last 1% of the residuals as simple outlyer removal //
+        unsigned int k_min(static_cast<unsigned int>(
+                                    0.01*sample_points_per_r_bin[bin].size()));
+        unsigned int k_max(static_cast<unsigned int>(
+                                    0.99*sample_points_per_r_bin[bin].size()));
+//         outfile << bin << "\t" << (0.5+bin)*step_size << "\t"
+//                 << k_min << "\t" << k_max << endl;
+
+	// loop over residuals in a bin
+        for (unsigned int k=k_min; k<k_max; k++) {
+            aux_rad = aux_rad+
+                            sample_points_per_r_bin[bin][k]->dataVector()[0];
+            aux_corr = aux_corr+
+                            sample_points_per_r_bin[bin][k]->dataVector()[1];
+        }
+        if (k_max-k_min<0.25*min_nb_entries_per_bin) {
+            radii[bin] = (0.5+bin)*step_size;
+            corr[bin] = SamplePoint(radii[bin], 0.0, 1.0);
+        } else {
+            radii[bin] = aux_rad/static_cast<double>(k_max-k_min);
+            corr[bin] = SamplePoint(radii[bin],
+                               aux_corr/static_cast<double>(k_max-k_min), 1.0);
+        }
+
+    }
+
+// correction polygon //
+	PolygonBase polygon(radii);
+	BaseFunctionFitter fitter(nb_bins);
+	fitter.fit_parameters(corr, 1, corr.size(), &polygon);
+
+// create output r-t relationship //
+	vector<double> rt_params;
+	rt_params.push_back(rt_rel.tLower());
+	rt_params.push_back(0.01*(rt_rel.tUpper()-rt_rel.tLower()));
+//	ofstream outfile("out2.txt");
+	for (double t=rt_rel.tLower(); t<=rt_rel.tUpper(); t=t+rt_params[1]) {
+		double delta_r(0.0);
+		for (unsigned int l=0; l<radii.size(); l++) {
+			delta_r = delta_r+fitter.coefficients()[l]*polygon.value(l, 
+															rt_rel.radius(t));
+		}
+        if (rt_rel.radius(t)>r_max) {
+            delta_r = 0.0;
+        }
+		if (fix_t_min && (rt_rel.radius(t)<0.5)) {
+			delta_r = 0.0;
+		}
+		if (fix_t_max && (rt_rel.radius(t)>14.1)) {
+			delta_r = 0.0;
+		}
+		rt_params.push_back(rt_rel.radius(t)-delta_r);
+	}
+
+	RtRelationLookUp improved_rt(rt_params);
+// 	for (double t=rt_rel.tLower(); t<=rt_rel.tUpper(); t=t+rt_params[1]) {
+// 		outfile << rt_rel.radius(t) << "\t" << improved_rt.radius(t)
+// 				<< "\t" << endl;
+// 	}
+
+	return improved_rt;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::
+//:: METHOD t_from_r ::
+//:::::::::::::::::::::
+
+double AdaptiveResidualSmoothing::t_from_r(const IRtRelation & rt_rel,
+															const double & r) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	double precision(0.001); // spatial precision of the inversion 
+	double t_max(rt_rel.tUpper()); // upper time search limit
+	double t_min(rt_rel.tLower()); // lower time search limit
+
+/////////////////////////////////////////////
+// SEARCH FOR THE CORRESPONDING DRIFT TIME //
+/////////////////////////////////////////////
+
+	while (t_max-t_min>0.1 &&
+						fabs(rt_rel.radius(0.5*(t_min+t_max))-r)>precision) {
+
+		if (rt_rel.radius(0.5*(t_min+t_max))>r) {
+			t_max = 0.5*(t_min+t_max);
+		} else {
+			t_min = 0.5*(t_min+t_max);
+		}
+
+	}
+
+	return 0.5*(t_min+t_max);
+
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/MultilayerRtDifference.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/MultilayerRtDifference.cxx
new file mode 100644
index 0000000000000..9dac19300b028
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/MultilayerRtDifference.cxx
@@ -0,0 +1,220 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "MultilayerRtDifference.h"
+
+//MuonCalibEventBase
+#include "MuonCalibEventBase/MuonCalibSegment.h"
+
+//MdtCalibFitters
+#include "MdtCalibFitters/CurvedPatRec.h"
+#include "MdtCalibFitters/QuasianalyticLineReconstruction.h"
+
+//MdtCalibData
+#include "MdtCalibData/RtScaleFunction.h"
+#include "MdtCalibData/IRtRelation.h"
+
+
+//root
+#include "TH2F.h"
+#include "TProfile.h"
+#include "TF2.h"
+#include "TF1.h"
+#include "TDirectory.h"
+
+//std
+#include "cmath"
+#include "sstream"
+#include "iostream"
+
+namespace MuonCalib {
+
+Double_t MultilayerRtDifference_ScaleFunction(Double_t *x, Double_t *par)
+	{
+	return par[0] * RtScalePolynomial(x[0]);
+	}
+
+
+class MultilayerRtDifference_Histograms
+	{
+	public:
+		inline MultilayerRtDifference_Histograms(TDirectory *control_histogram_dir);
+		inline ~MultilayerRtDifference_Histograms();
+		inline TH2F * GetResHist(const int &ml);
+		inline TProfile * GetProfileDiff(const int & min_number_of_entries);
+	private:
+		std::list<TH2F *> m_residuals[2];
+		TH2F * m_current_residuals[2];
+		std::list<TProfile *> m_res_prov[2];
+		std::list<TProfile *> m_res_prov_diff;
+		TDirectory *m_control_histogram_dir;
+	};
+
+
+inline MultilayerRtDifference_Histograms::MultilayerRtDifference_Histograms(TDirectory *control_histogram_dir): m_control_histogram_dir(control_histogram_dir)
+	{
+	for(unsigned int i=0; i<2; i++)
+		{
+		m_current_residuals[i]=NULL;
+		}
+	}
+
+
+template<typename T> inline void clearall(T & container)
+	{
+	typename T::iterator it=container.begin();
+	for(; it!=container.end(); it++)
+		{
+		delete *it;
+		*it=NULL;
+		}
+	}
+
+inline MultilayerRtDifference_Histograms::~MultilayerRtDifference_Histograms()
+	{
+	for(unsigned int i=0; i<2; i++)
+		{
+		clearall(m_residuals[i]);
+		clearall(m_res_prov[i]);
+		}
+	clearall(m_res_prov_diff);
+	}
+
+
+inline TH2F * MultilayerRtDifference_Histograms::GetResHist(const int &ml)
+	{
+	if(!m_current_residuals[ml])
+		{
+		for(int i=0; i<2; i++)
+			{
+			TDirectory *prevdir=gDirectory;
+			if (m_control_histogram_dir)
+				m_control_histogram_dir->cd();
+			std::ostringstream nm;
+			nm << "temporal_residual_ml" << i << "_iteration" << m_residuals[i].size();
+			m_current_residuals[i]=new TH2F(nm.str().c_str(), "", 15, 0., 15., 200, -100, 100);
+			if (m_control_histogram_dir)
+				prevdir->cd();
+			else
+				m_current_residuals[i]->SetDirectory(0);
+			m_residuals[i].push_back(m_current_residuals[i]);
+			}
+		}
+	return m_current_residuals[ml];
+	}
+
+inline TProfile * MultilayerRtDifference_Histograms::GetProfileDiff(const int & min_number_of_entries)	
+	{
+	TDirectory *prev=gDirectory;
+	if(m_control_histogram_dir)
+		{
+		m_control_histogram_dir->cd();
+		}
+	bool ok(true);
+	TProfile *prof[2];
+	for(unsigned int i=0; i<2; i++)
+		{
+		if(m_current_residuals[i] && m_current_residuals[i]->GetEntries()>=min_number_of_entries)
+			{
+			prof[i]=m_current_residuals[i]->ProfileX();
+			if(!m_control_histogram_dir)
+				{
+				prof[i]->SetDirectory(0);
+				}
+			}
+		else
+			{
+			prof[i]=NULL;
+			ok=false;
+			}
+		m_res_prov[i].push_back(prof[i]);
+		m_current_residuals[i]=NULL;
+		}
+	if(!ok)
+		{
+		prev->cd();
+		m_res_prov_diff.push_back(NULL);
+		return NULL;
+		}
+	std::ostringstream nm;
+	nm<<"res_prov_diff_step"<<m_res_prov_diff.size();
+	TProfile *prov_diff=new TProfile(nm.str().c_str(), "", 15, 0., 15.);
+	prov_diff->Add(prof[0], prof[1], 1., -1);
+	m_res_prov_diff.push_back(prov_diff);
+	if(!m_control_histogram_dir)
+		{
+		prov_diff->SetDirectory(0);
+		}
+	return prov_diff;
+	}
+
+MultilayerRtDifference :: MultilayerRtDifference(int min_hits, TDirectory *control_histogram_dir): m_histograms(new MultilayerRtDifference_Histograms(control_histogram_dir)), m_min_number_of_hits(min_hits)
+	{
+	m_polfun = new TF1("polfun", MultilayerRtDifference_ScaleFunction, 4.0, 15.0, 1);
+	}
+
+
+MultilayerRtDifference :: ~MultilayerRtDifference()
+	{
+	delete m_histograms;
+	delete m_polfun;
+	}
+
+void MultilayerRtDifference :: Fill(const MdtCalibHitBase &hit, const IRtRelation &rt_relation)
+	{
+	int ml=hit.identify().mdtMultilayer() -1;
+	double r_track=std::fabs(hit.signedDistanceToTrack());
+	double res=std::fabs(hit.driftRadius()) - r_track;
+	double v=rt_relation.driftvelocity(hit.driftTime());
+	m_histograms->GetResHist(ml)->Fill(r_track, res/v);
+	}
+
+bool MultilayerRtDifference :: DoFit(IRtRelation * rt_relation, const std::vector<MuonCalibSegment *>  *seg)
+	{
+	TProfile *prov_diff=m_histograms->GetProfileDiff(m_min_number_of_hits);
+	if(!prov_diff)
+		{
+		std::cout<<"MultilayerRtDifference :: DoFit: Not enough hits!";
+		return false;
+		}
+	if(prov_diff->Fit("polfun", "Q", "", 4., 15.)!=0)
+		{
+		std::cerr<<"MultilayerRtDifference: Fit of polinomial failed! Not updating scale!"<<std::endl;
+		return false;
+		}
+	if(std::fabs(m_polfun->GetParameter(0)) < m_polfun->GetParError(0))
+		{
+		std::cout<<"MultilayerRtDifference: No Scale update needed!"<<std::endl;
+		std::cout<<"Scale correction: "<<m_polfun->GetParameter(0)<<" +- "<< m_polfun->GetParError(0) <<std::endl;
+		return true;
+		}
+	if(!rt_relation) return true;
+	float scale=m_polfun->GetParameter(0);
+//	std::cout<<"Scale correction: "<<m_polfun->GetParameter(0)<<" +- " <<m_polfun->GetParError(0)*std::sqrt(m_polfun->GetChisquare()/m_polfun->GetNDF())<<std::endl;
+	if(std::fabs(scale)>2) scale*=4;
+	if(rt_relation->HasTmaxDiff())
+		{
+		scale+=rt_relation->GetTmaxDiff();
+		}
+	rt_relation->SetTmaxDiff(scale);
+	if(!seg)
+		return true;
+//update input segments
+	for(std::vector<MuonCalibSegment *>::const_iterator it=seg->begin(); it!=seg->end(); it++)
+		{
+		MuonCalibSegment *seg=*it;
+		for (MuonCalibSegment::MdtHitVec::iterator h_it=seg->mdtHOTBegin (); h_it!=seg->mdtHOTEnd(); h_it++)
+			{
+			MdtCalibHitBase *hit=*h_it;
+			float old_corr=hit->TemperatureTime();
+			float corr=RtScaleFunction(hit->driftTime(), hit->identify().mdtMultilayer()==2, *rt_relation);
+			hit->setTemperatureTime(corr);
+			hit->setDriftTime(hit->driftTime() - corr + old_corr);
+			hit->setDriftRadius( rt_relation->radius(hit->driftTime()), hit->sigmaDriftRadius());
+			}
+		}
+	return true;
+	}
+
+}//namespace MuonCalib
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/MultilayerRtDifference.h b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/MultilayerRtDifference.h
new file mode 100644
index 0000000000000..955b568819bb0
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/MultilayerRtDifference.h
@@ -0,0 +1,47 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef MdtCalibRt_MultilayerRtDifference_h
+#define MdtCalibRt_MultilayerRtDifference_h
+
+class TF1;
+class TDirectory;
+
+#include <cstddef>
+#include "vector"
+#include "list"
+
+namespace MuonCalib {
+
+class MuonCalibSegment;
+class IRtRelation;
+class MdtCalibHitBase;
+class MultilayerRtDifference_Histograms;
+
+class MultilayerRtDifference {
+
+	public:
+		MultilayerRtDifference(int min_hits, TDirectory *control_histogram_dir=NULL);
+		virtual ~MultilayerRtDifference();
+		
+		void Fill(const MdtCalibHitBase &hit, const IRtRelation &rt_relation);
+				
+		bool DoFit(IRtRelation * rt_relation=NULL, const std::vector<MuonCalibSegment *>  *seg=NULL);
+		
+		inline const TF1 * GetFunction() const
+			{
+			return m_polfun;
+			}
+		
+	private:
+		
+		TF1 *m_polfun;
+		MultilayerRtDifference_Histograms *m_histograms;
+		int m_min_number_of_hits;
+};
+
+
+}//namespace MuonCalib 
+
+#endif
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtCalibrationAnalytic.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtCalibrationAnalytic.cxx
new file mode 100644
index 0000000000000..e161c97058182
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtCalibrationAnalytic.cxx
@@ -0,0 +1,1641 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 06.04.2006, AUTHOR: OLIVER KORTNER
+// Modified: 02.07.2006 by O. Kortner, redesign to simplified optimization.
+//           16.07.2006 by O. Kortner, optimized quality cuts.
+//           17.07.2006 by O. Kortner, compatibility with old event loop.
+//           13.12.2006 by O. Kortner and J. von Loeben, new convergence
+//                                                       criterion.
+//           27.03.2007 by O. Kortner, control histograms are written to file
+//                                     when they are switched off again.
+//           06.08.2007 by O. Kortner, option to force r(t) to be monotonically
+//                                     increasing.
+//           29.10.2007 by O. Kortner, avoid double analysis in case of full
+//                                     chamber track fits.
+//           30.06.2008 by O. Kortner, m_r_max settings corrected, better hit
+//                                     selection.
+//           03.08.2008 by O. Kortner, r-t smoothing using the conventional
+//                                     autocalibration method is implemented. 
+//           28.02.2009 by O. Kortner, parabolic extrapolation added.
+//           08.02.2010 by J.v.Loeben, parabolic extrapolation to end-point
+//                                     is now done after convergence/smoothing
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+#include "cmath"
+
+#include "MdtCalibRt/RtCalibrationAnalytic.h"
+#include "CLHEP/GenericFunctions/CumulativeChiSquare.hh"
+#include "MdtCalibRt/RtCalibrationOutput.h" 
+#include "MdtCalibData/RtChebyshev.h"
+#include "MdtCalibData/RtRelationLookUp.h"
+#include "MuonCalibMath/BaseFunctionFitter.h"
+#include "MuonCalibMath/ChebyshevPolynomial.h"
+#include "MuonCalibMath/LegendrePolynomial.h"
+#include "MuonCalibMath/PolygonBase.h"
+#include "MdtCalibRt/AdaptiveResidualSmoothing.h"
+#include "MdtCalibRt/RtParabolicExtrapolation.h"
+#include "MdtCalibData/RtFromPoints.h"
+
+#include "MdtCalibData/IRtRelation.h"
+#include "MdtCalibData/RtRelationLookUp.h"
+#include "MdtCalibRt/RtCalibrationOutput.h"
+#include "MdtCalibInterfaces/IMdtCalibrationOutput.h"
+#include "MuonCalibEventBase/MuonCalibSegment.h"
+#include "MuonCalibMath/BaseFunction.h"
+
+
+//root
+#include "TGraphErrors.h"
+
+//std
+#include "sstream"
+#include "cmath"
+
+//:::::::::::::::::::::::
+//:: NAMESPACE SETTING ::
+//:::::::::::::::::::::::
+
+using namespace MuonCalib;
+using namespace std;
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: IMPLEMENTATION OF METHODS DEFINED IN THE CLASS RtCalibrationAnalytic ::
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+//*****************************************************************************
+
+
+
+RtCalibrationAnalytic :: RtCalibrationAnalytic(std::string name,
+		const double & rt_accuracy,
+		const unsigned int & func_type,
+		const unsigned int & ord,
+		const bool & split,
+		const bool & full_matrix,
+		const bool & fix_min,
+		const bool & fix_max,
+		const int & max_it,
+		bool do_smoothing,
+        bool do_parabolic_extrapolation) : IMdtCalibration(name), m_rt(NULL) {
+	        init(rt_accuracy, func_type, ord, split, full_matrix,
+			fix_min, fix_max, max_it, do_smoothing, do_parabolic_extrapolation);
+	        }
+
+
+
+
+
+
+
+RtCalibrationAnalytic :: ~RtCalibrationAnalytic(void)
+ {
+		if (m_base_function!=0) {
+			delete m_base_function;
+		}
+		if (m_tfile!=0) {
+			m_tfile->Write();
+		}
+		}
+
+
+//:::::::::::::::::
+//:: METHOD init ::
+//:::::::::::::::::
+
+void RtCalibrationAnalytic::init(const double & rt_accuracy,
+									const unsigned int & func_type,
+									const unsigned int & ord,
+									const bool & split,
+									const bool & full_matrix,
+									const bool & fix_min,
+									const bool & fix_max,
+									const int & max_it,
+									bool do_smoothing,
+                                    bool do_parabolic_extrapolation) {
+
+/////////////////////////////
+// RESET PRIVATE VARIABLES //
+/////////////////////////////
+
+	m_r_max = 15.0*CLHEP::mm;
+	m_control_histograms = false;
+		m_tfile = 0;
+		m_cut_evolution = 0;
+		m_nb_segment_hits = 0;
+		m_CL = 0;
+		m_residuals = 0;
+	m_split_into_ml = split;
+	m_full_matrix = full_matrix;
+	m_nb_segments = 0;
+	m_nb_segments_used = 0;
+	m_iteration = 0;
+	m_multilayer[0] = false;
+	m_multilayer[1] = false;
+	m_status = 0;
+	m_rt_accuracy = fabs(rt_accuracy);
+	m_chi2_previous = 1.0e99; // large value to force at least two rounds
+	m_chi2 = 0.0;
+	m_order = ord;
+	m_fix_min = fix_min;
+	m_fix_max = fix_max;
+	m_max_it = abs(max_it);
+
+	if (m_order==0) {
+		cerr << "\n"
+		        << "Class RtCalibrationAnalytic, method init: ERROR!"
+			<< "\nOrder of the correction polynomial must be >0!\n";
+		exit(1);
+	}
+	
+	m_t_length = 1000.0;
+	m_t_mean = 500.0;
+		// default values, correct values will be set when the input r-t
+		// has been given
+
+	m_rt_new = 0;
+	m_output = 0;
+
+	m_U = vector<CLHEP::HepVector>(m_order);
+	m_A = CLHEP::HepSymMatrix(m_order, 0);
+	m_b = CLHEP::HepVector(m_order, 0);
+	m_alpha = CLHEP::HepVector(m_order, 0);
+
+// correction function
+	if (func_type<1 || func_type>3) {
+		m_base_function = 0;
+		cerr << "\n"
+			<< "Class RtCalibrationAnalytic, method init: "
+			<< "ERROR!\n"
+			<< "Illegal correction function type!\n";
+		exit(1);
+	}
+	switch(func_type) {
+		case 1:
+			m_base_function = new LegendrePolynomial;
+			break;
+		case 2:
+			m_base_function = new ChebyshevPolynomial;
+			break;
+		case 3:
+			if (m_order<2) {
+				cerr << "\n"
+					<< "Class RtCalibrationAnalytic, "
+					<< "method init: ERROR!\n"
+					<< "Order must be >2 for polygons! "
+					<< "It is set to " << m_order
+					<< "by the user.\n";
+				exit(1);
+			}
+			vector<double> x(m_order);
+			double bin_width=2.0/static_cast<double>(m_order-1);
+			for (unsigned int k=0; k<m_order; k++) {
+				x[k] = -1+k*bin_width;
+			}
+			m_base_function = new PolygonBase(x);
+			break;
+	}
+
+// request a chi^2 refit after the quasianalytic pattern recognition //
+	m_tracker.switchOnRefit();
+
+// monotony of r(t) //
+	m_force_monotony = false;
+
+// smoothing //
+	m_do_smoothing = do_smoothing;
+
+// parabolic extrapolation //
+    m_do_parabolic_extrapolation = do_parabolic_extrapolation;
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::
+//:: METHOD t_from_r ::
+//:::::::::::::::::::::
+
+double RtCalibrationAnalytic::t_from_r(const double & r) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	double precision(0.001); // spatial precision of the inversion 
+	double t_max(0.5*(m_t_length+2.0*m_t_mean)); // upper time search limit
+	double t_min(t_max-m_t_length); // lower time search limit
+
+/////////////////////////////////////////////
+// SEARCH FOR THE CORRESPONDING DRIFT TIME //
+/////////////////////////////////////////////
+
+	while (t_max-t_min>0.1 &&
+			fabs(m_rt->radius(0.5*(t_min+t_max))-r)>precision) {
+
+		if (m_rt->radius(0.5*(t_min+t_max))>r) {
+			t_max = 0.5*(t_min+t_max);
+		} else {
+			t_min = 0.5*(t_min+t_max);
+		}
+
+	}
+
+	return 0.5*(t_min+t_max);
+
+}
+
+//*****************************************************************************
+
+////////////////////////////
+// METHOD display_segment //
+////////////////////////////
+
+void RtCalibrationAnalytic::display_segment(MuonCalibSegment * segment,
+							ofstream & outfile) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	double y_min, y_max, z_min, z_max; // minimum and maximum y and z
+					   // coordinates
+	Amg::Vector3D null(0.0, 0.0, 0.0); // auxiliary null vector
+
+/////////////////////////
+// DISPLAY THE SEGMENT //
+/////////////////////////
+
+// minimum and maximum coordinates //
+	y_min = (segment->mdtHOT()[0])->localPosition().y();
+	y_max = y_min;
+	z_min = (segment->mdtHOT()[0])->localPosition().z();
+	z_max = z_min;
+	for (unsigned int k=1; k<segment->mdtHitsOnTrack(); k++) {
+		if ((segment->mdtHOT()[k])->localPosition().y()<y_min) {
+			y_min = (segment->mdtHOT()[k])->localPosition().y();
+		}
+		if ((segment->mdtHOT()[k])->localPosition().y()>y_max) {
+			y_max = (segment->mdtHOT()[k])->localPosition().y();
+		}
+		if ((segment->mdtHOT()[k])->localPosition().z()<z_min) {
+			z_min = (segment->mdtHOT()[k])->localPosition().z();
+		}
+		if ((segment->mdtHOT()[k])->localPosition().z()>z_max) {
+			z_max = (segment->mdtHOT()[k])->localPosition().z();
+		}
+	}
+	for (unsigned int k=0; k<segment->mdtCloseHits(); k++) {
+		if ((segment->mdtClose()[k])->localPosition().y()<y_min) {
+			y_min = (segment->mdtClose()[k])->localPosition().y();
+		}
+		if ((segment->mdtClose()[k])->localPosition().y()>y_max) {
+			y_max = (segment->mdtClose()[k])->localPosition().y();
+		}
+		if ((segment->mdtClose()[k])->localPosition().z()<z_min) {
+			z_min = (segment->mdtClose()[k])->localPosition().z();
+		}
+		if ((segment->mdtClose()[k])->localPosition().z()>z_max) {
+			z_max = (segment->mdtClose()[k])->localPosition().z();
+		}
+	}
+
+// write out the coordinate system //
+	if (y_max-y_min>z_max-z_min) {
+		outfile << "NULL " << y_min-30.0 << " " << y_max+30.0 << " "
+			<< 0.5*(z_min+z_max)-0.5*(y_max-y_min)-30.0 << " " 
+			<< 0.5*(z_min+z_max)+0.5*(y_max-y_min)+30.0 << "\n";
+	} else {
+		outfile << "NULL " << 0.5*(y_min+y_max)-0.5*(z_max-z_min)-30.0 
+			<< " " << 0.5*(y_min+y_max)+0.5*(z_max-z_min)+30.0 << " "
+			<< z_min-30.0 << " " 
+			<< z_max+30.0 << "\n";
+	}
+
+// write out the hits on track //
+	for (unsigned int k=0; k<segment->mdtHitsOnTrack(); k++) {
+
+   // draw a circle for the tube //
+		outfile << "SET PLCI 1\n"
+			<< "ARC " << (segment->mdtHOT()[k])->localPosition().y()
+			<< " " << (segment->mdtHOT()[k])->localPosition().z()
+			<< " 15.0\n";
+
+   // draw a drift circle //
+		outfile << "SET PLCI 3\n"
+			<< "ARC " << (segment->mdtHOT()[k])->localPosition().y()
+			<< " " << (segment->mdtHOT()[k])->localPosition().z()
+			<< " " << (segment->mdtHOT()[k])->driftRadius()
+			<< "\n";
+
+	}
+
+// write out the close hits //
+	for (unsigned int k=0; k<segment->mdtCloseHits(); k++) {
+
+   // draw a circle for the tube //
+		outfile << "SET PLCI 1\n"
+			<< "ARC " << (segment->mdtClose()[k])->localPosition().y()
+			<< " " << (segment->mdtClose()[k])->localPosition().z()
+			<< " 15.0\n";
+
+   // draw a drift circle //
+		outfile << "SET PLCI 2\n"
+			<< "ARC " << (segment->mdtClose()[k])->localPosition().y()
+			<< " " << (segment->mdtClose()[k])->localPosition().z()
+			<< " " << (segment->mdtClose()[k])->driftRadius()
+			<< "\n";
+
+	}
+
+// write out the reconstructed track //
+	MTStraightLine aux_track(segment->position(), segment->direction(),
+								null, null);
+	outfile << "SET PLCI 4\n"
+		<< "LINE " << aux_track.m_x2()*(z_min-30.0)+aux_track.b_x2() 
+		<< " " << z_min-30.0
+		<< " " << aux_track.m_x2()*(z_max+30.0)+aux_track.b_x2() 
+		<< " " << z_max+30.0 << "\n";
+
+// add a wait statement //
+	outfile << "WAIT\n";
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::
+//:: METHOD reliability ::
+//::::::::::::::::::::::::
+
+double RtCalibrationAnalytic::reliability(void) const {
+
+	return m_status;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::
+//:: METHOD estimatedRtAccuracy ::
+//::::::::::::::::::::::::::::::::
+
+double RtCalibrationAnalytic::estimatedRtAccuracy(void) const {
+
+	return m_rt_accuracy;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::
+//:: METHOD numberOfSegments ::
+//:::::::::::::::::::::::::::::
+
+int RtCalibrationAnalytic::numberOfSegments(void) const {
+
+	return m_nb_segments;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::
+//:: METHOD numberOfSegmentsUsed ::
+//:::::::::::::::::::::::::::::::::
+
+int RtCalibrationAnalytic::numberOfSegmentsUsed(void) const {
+
+	return m_nb_segments_used;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::
+//:: METHOD iteration ::
+//::::::::::::::::::::::
+
+int RtCalibrationAnalytic::iteration(void) const {
+
+	return m_iteration;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::
+//:: METHOD splitIntoMultilayers ::
+//:::::::::::::::::::::::::::::::::
+
+bool RtCalibrationAnalytic::splitIntoMultilayers(void) const {
+
+	return m_split_into_ml;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD fullMatrix ::
+//:::::::::::::::::::::::
+
+bool RtCalibrationAnalytic::fullMatrix(void) const {
+
+	return m_full_matrix;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD smoothing ::
+//:::::::::::::::::::::::
+
+bool RtCalibrationAnalytic::smoothing(void) const {
+
+	return m_do_smoothing;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::::::::::
+//:: METHOD switch_on_control_histograms ::
+//:::::::::::::::::::::::::::::::::::::::::
+
+void RtCalibrationAnalytic::switch_on_control_histograms(
+						const string & file_name) {
+
+/////////////////////////////////////////////
+// CREATE THE ROOT FILE AND THE HISTOGRAMS //
+/////////////////////////////////////////////
+
+	m_control_histograms = true;
+
+	m_tfile = new TFile(file_name.c_str(), "RECREATE");
+
+	m_cut_evolution = new TH1F("m_cut_evolution",
+				"CUT EVOLUTION",
+				11, -0.5, 10.5);
+
+	m_nb_segment_hits = new TH1F("m_nb_segment_hits",
+				"NUMBER OF HITS ON THE REFITTED SEGMENTS",
+				11, -0.5, 10.5);
+
+	m_CL = new TH1F("m_CL",
+				"CONFIDENCE LEVELS OF THE REFITTED SEGMENTS",
+				100, 0.0, 1.0);
+
+	m_residuals = new TH2F("m_residuals",
+				"RESIDUALS OF THE REFITTED SEGMENTS",
+				100, -0.5, 15.0, 300, -1.5, 1.5);
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::::::::::::
+//:: METHOD switch_off_control_histograms ::
+//::::::::::::::::::::::::::::::::::::::::::
+
+void RtCalibrationAnalytic::switch_off_control_histograms(void) {
+
+	m_control_histograms = false;
+	if (m_tfile!=0) {
+		m_tfile->Write();
+	}
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::
+//:: METHOD forceMonotony ::
+//::::::::::::::::::::::::::
+
+void RtCalibrationAnalytic::forceMonotony(void) {
+
+	m_force_monotony = true;
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::
+//:: METHOD doNotForceMonotony ::
+//:::::::::::::::::::::::::::::::
+
+void RtCalibrationAnalytic::doNotForceMonotony(void) {
+
+	m_force_monotony = false;
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::
+//:: METHOD doSmoothing ::
+//::::::::::::::::::::::::::
+
+void RtCalibrationAnalytic::doSmoothing(void) {
+
+	m_do_smoothing = true;
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::
+//:: METHOD noSmoothing ::
+//::::::::::::::::::::::::::
+
+void RtCalibrationAnalytic::noSmoothing(void) {
+
+	m_do_smoothing = false;
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::::::
+//:: METHOD doParabolicExtrapolation ::
+//:::::::::::::::::::::::::::::::::::::
+
+void RtCalibrationAnalytic::doParabolicExtrapolation(void) {
+
+    m_do_parabolic_extrapolation = true;
+    return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::::::
+//:: METHOD noParabolicExtrapolation ::
+//:::::::::::::::::::::::::::::::::::::
+
+void RtCalibrationAnalytic::noParabolicExtrapolation(void) {
+
+    m_do_parabolic_extrapolation = false;
+    return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::::
+//:: METHOD setEstimateRtAccuracy ::
+//::::::::::::::::::::::::::::::::::
+
+void RtCalibrationAnalytic::setEstimateRtAccuracy(const double & acc) {
+
+	m_rt_accuracy = fabs(acc);
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::
+//:: METHOD splitIntoMultilayers ::
+//:::::::::::::::::::::::::::::::::
+
+void RtCalibrationAnalytic::splitIntoMultilayers(const bool & yes_or_no) {
+
+	m_split_into_ml = yes_or_no;
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD fullMatrix ::
+//:::::::::::::::::::::::
+
+void RtCalibrationAnalytic::fullMatrix(const bool & yes_or_no) {
+
+	m_full_matrix = yes_or_no;
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::
+//:: METHOD analyseSegments ::
+//::::::::::::::::::::::::::::
+
+const IMdtCalibrationOutput * RtCalibrationAnalytic::analyseSegments(
+				const std::vector<MuonCalibSegment*> & seg) {
+
+	const IRtRelation *tmp_rt(0);
+	const IRtRelation *conv_rt(0);
+
+//////////////////////////
+// AUTOCALIBRATION LOOP //
+//////////////////////////
+
+	while (!converged()) {
+
+		for (unsigned int k=0; k<seg.size(); k++) {
+			handleSegment(*seg[k]);
+		}
+		if(!analyse()) 
+			{
+			for(unsigned int i=0; i<seg.size(); i++)
+				{
+				std::cout<<i<<" "<<seg[i]->direction()<<" "<<seg[i]->position()<<std::endl;
+				}
+			if(conv_rt) delete conv_rt;
+			return NULL;
+			}
+
+		const RtCalibrationOutput* rtOut = m_output;
+
+		if (!converged()) {
+			setInput(rtOut);
+		}
+		tmp_rt = rtOut->rt();
+
+		vector<double> params;
+		params.push_back(tmp_rt->tLower());
+		params.push_back(0.01*(tmp_rt->tUpper()-tmp_rt->tLower()));
+		for (double t=tmp_rt->tLower(); t<=tmp_rt->tUpper(); t=t+params[1]) {
+			params.push_back(tmp_rt->radius(t));
+		}
+		if (conv_rt) delete conv_rt;
+		conv_rt = new RtRelationLookUp(params);
+
+	}
+	if (conv_rt) delete conv_rt;
+// parabolic extrapolations for small radii //
+    if (m_do_parabolic_extrapolation) {
+	    RtRelationLookUp *tmprt = 
+                        performParabolicExtrapolation(true, true, *tmp_rt);
+	    delete m_output;
+	    m_output = new RtCalibrationOutput(tmprt, 
+				new RtFullInfo("RtCalibrationAnalyticExt", m_iteration,
+				m_nb_segments_used, 0.0, 0.0, 0.0, 0.0));
+        delete tmp_rt;
+        tmp_rt = tmprt;
+    }
+
+//////////////////////////////////////////////
+// SMOOTHING AFTER CONVERGENCE IF REQUESTED //
+//////////////////////////////////////////////
+	if (!m_do_smoothing) {
+		return getResults();
+	}
+
+// maximum number of iterations //
+	int max_smoothing_iterations(static_cast<int>(m_max_it));
+	if (max_smoothing_iterations==0) {
+		max_smoothing_iterations = 1;
+	}
+
+// convergence RMS //
+	double convergence_RMS(0.002);
+
+// variables //
+	int it(0); // iteration
+	double RMS(1.0); // RMS change of r(t)
+
+// smoothing //
+//---------------------------------------------------------------------------//
+//---------------------------------------------------------------------------//
+	while (it<max_smoothing_iterations && RMS>convergence_RMS) {
+//---------------------------------------------------------------------------//
+
+ 	AdaptiveResidualSmoothing smoothing;
+
+  // counter //
+	unsigned int counter(0);
+	unsigned int counter2(0);
+
+  // overwrite drift radii and calculate the average resolution //
+	for (unsigned int k=0; k<seg.size(); k++) {
+		if (seg[k]->mdtHitsOnTrack()<3) {
+			continue;
+		}
+		counter2++;
+		double avres(0.0);
+		for (unsigned int h=0; h<seg[k]->mdtHitsOnTrack(); h++) {
+			seg[k]->mdtHOT()[h]->setDriftRadius(tmp_rt->radius(
+					seg[k]->mdtHOT()[h]->driftTime()),
+					seg[k]->mdtHOT()[h]->sigmaDriftRadius());
+			if (seg[k]->mdtHOT()[h]->sigmaDriftRadius()<0.5*m_r_max) {
+                avres = avres+seg[k]->mdtHOT()[h]->sigma2DriftRadius();
+            } else {
+                avres = avres+0.1;
+            }
+		}
+		avres = avres/static_cast<double>(seg[k]->mdtHitsOnTrack());
+		avres = sqrt(avres);
+ 		if (seg[k]->mdtHitsOnTrack()>3) {
+			  
+		  if (smoothing.addResidualsFromSegment(
+							*seg[k], true, 7.0*avres)) {
+		    counter++;
+		  }
+
+		}
+		else {
+		  if (smoothing.addResidualsFromSegment(*seg[k], false, 7.0*avres)) {
+		    counter++;
+		  }
+		}
+		
+	}
+
+ // break, do no smoothing if there are not enough segments //
+	if (counter<1000) {
+		cerr << "Class RtCalibrationAnalytic, no smoothing applied due to "
+		     << "too small number of reconstructed segments!\n";
+		return getResults();
+	}
+
+//  // break, do no smoothing if there are not enough segments //
+// 	if (counter<250) {
+// 		cerr << "Class RtCalibrationAnalytic, no smoothing applied due to "
+// 		     << "too small number of reconstructed segments!\n";
+// 		return getResults();
+// 	}
+// 
+//  // set bin content for residual bins //
+// 	unsigned int bin_content(100);
+// 	if (counter<500) {
+// 		bin_content = 50;
+// 	}
+// 	if (counter>3000) {
+// 		bin_content = 200;
+// 	}
+// 	if (counter>6000) {
+// 		bin_content = 400;
+// 	}
+// 	if (counter>12000) {
+// 		bin_content = 800;
+// 	}
+// 	if (counter>24000) {
+// 		bin_content = seg.size()/60;
+// 	}
+// 
+//   // smoothing //
+// 	RtRelationLookUp smooth_rt(smoothing.performSmoothing(*tmp_rt, bin_content,
+// 													m_fix_min, m_fix_max));
+
+  // smoothing //
+	RtRelationLookUp smooth_rt(smoothing.performSmoothing(*tmp_rt,
+													m_fix_min, m_fix_max));
+
+  // calculate RMS change //
+	RMS = 0.0;
+	double bin_width(0.01*(smooth_rt.tUpper()-smooth_rt.tLower()));
+	for (double t=smooth_rt.tLower(); t<=smooth_rt.tUpper(); t=t+bin_width) {
+		RMS = RMS+std::pow(smooth_rt.radius(t)-tmp_rt->radius(t), 2);
+	}
+	RMS = sqrt(0.01*RMS);
+
+  // increase the iterations counter //
+	it++;
+
+  // delete tmp_rt and update it //
+// 	if (it>1) {
+// 		delete tmp_rt;
+// 	}
+	delete tmp_rt;
+	tmp_rt = new RtRelationLookUp(smooth_rt);
+// 	cout << "1: " << tmp_rt << endl;
+
+//---------------------------------------------------------------------------//
+	}
+//---------------------------------------------------------------------------//
+//---------------------------------------------------------------------------//
+
+// // r-t format conversion //
+// 	vector<double> rt_params;
+// 	rt_params.push_back(tmp_rt->tLower());
+// 	rt_params.push_back(0.01*(tmp_rt->tUpper()-tmp_rt->tLower()));
+// 	for (double t=tmp_rt->tLower(); t<=tmp_rt->tUpper(); t=t+rt_params[1]) {
+// 		rt_params.push_back(tmp_rt->radius(t));
+// 	}
+// 	RtRelationLookUp *improved_rt = new RtRelationLookUp(rt_params);
+
+// 	ofstream out1("out1.txt");
+// 	for (double t=conv_rt->tLower(); t<=conv_rt->tUpper(); t=t+5.0) {
+// 		out1 << t << "\t" << tmp_rt->radius(t) << "\t"
+// 			 << conv_rt->radius(t)
+// 			 << endl;
+// 	}
+
+// 
+// // 	m_output = new RtCalibrationOutput(smooth_rt, 
+// // 				new RtFullInfo("RtCalibrationAnalytic", m_iteration,
+// // 				m_nb_segments_used, 0.0, 0.0, 0.0, 0.0));
+	delete m_output;
+	m_output = new RtCalibrationOutput(tmp_rt, 
+				new RtFullInfo("RtCalibrationAnalytic", m_iteration,
+				m_nb_segments_used, 0.0, 0.0, 0.0, 0.0));
+
+/////////////////////////////////////////
+// RETURN THE RESULT AFTER CONVERGENCE //
+/////////////////////////////////////////
+
+	return getResults();
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::
+//:: METHOD handleSegment ::
+//::::::::::::::::::::::::::
+
+bool RtCalibrationAnalytic::handleSegment(MuonCalibSegment & seg) {
+
+/////////////////////////////////////////////////
+// RETURN, IF THE SEGMENT HAD LESS THAN 3 HITS //
+/////////////////////////////////////////////////
+
+	if (m_control_histograms) {
+		m_cut_evolution->Fill(0.0, 1.0);
+	}
+
+	m_nb_segments = m_nb_segments+1;
+	if (seg.mdtHitsOnTrack()<3) {
+		return true;
+	}
+
+	if (m_control_histograms) {
+		m_cut_evolution->Fill(1.0, 1.0);
+	}
+
+	if(std::isnan(seg.direction().x()) || std::isnan(seg.direction().y()) || std::isnan(seg.direction().z()) || std::isnan(seg.position().x()) || std::isnan(seg.position().y()) || std::isnan(seg.position().z()))
+		return true;
+	if(fabs(seg.direction().y())>100) return true;
+
+///////////////
+// VARIABLES //
+///////////////
+
+// segment reconstruction and segment selection //
+	double aux_res; // auxiliary resolution
+    double av_res(0.0); // average spatial resolution of the tube hits
+	double chi2_scale_factor; // chi^2 scale factor used to take into
+	                          // account bad r-t accuracy in the segment
+	                          // selection
+	IMdtSegmentFitter::HitSelection hit_selection[2];
+		hit_selection[0] = IMdtSegmentFitter::HitSelection(
+							seg.mdtHitsOnTrack());
+		hit_selection[1] = IMdtSegmentFitter::HitSelection(
+							seg.mdtHitsOnTrack());
+						// hit selection vectors for
+						// refits in the first and
+						// second multilayer
+	unsigned int nb_hits_in_ml[2]; // number of hits in the multilayers
+	double x; // reduced time = (r(t)-0.5*m_r_max)/(0.5*m_r_max)
+	MTStraightLine track; // refitted straight line
+	vector<double> d_track; // signed distances of the track from the anode 
+	                        // wires of the tubes
+	vector<double> residual_value; // residuals
+	vector<MTStraightLine> w; // anode wires
+	Amg::Vector3D null(0.0, 0.0, 0.0); // auxiliary 0 vector
+	Amg::Vector3D xhat(1.0, 0.0, 0.0); // auxiliary unit vector
+
+// objects needed to calculate the autocalibration matrix and vector //
+	CLHEP::HepVector G; // vector used in the calculation of the
+	             // autocalibration matrix
+	vector<double> zeta; // vector used in the calculation of G
+
+///////////////////////////////////////
+// PREPARATION FOR THE SEGMENT REFIT //
+///////////////////////////////////////
+
+// debug display //
+// 	display_segment(&seg, display);
+
+// overwrite the drift radii according to the input r-t relationship, //
+// calculate the average spatial resolution to define a road width,   //
+// select the hits in the multilayer, if requested                    //
+	nb_hits_in_ml[0] = 0;
+	nb_hits_in_ml[1] = 0;
+	for (unsigned int k=0; k<seg.mdtHitsOnTrack(); k++) {
+
+   // make the resolution at small radii large enough //
+        aux_res = seg.mdtHOT()[k]->sigmaDriftRadius();
+        if (m_rt->radius(seg.mdtHOT()[k]->driftTime())<0.5) {
+            if (aux_res<0.5-m_rt->radius(seg.mdtHOT()[k]->driftTime())) {
+                aux_res = 0.5-m_rt->radius(seg.mdtHOT()[k]->driftTime());
+            }
+        }
+
+   // overwrite radius //
+		seg.mdtHOT()[k]->setDriftRadius(m_rt->radius(
+					seg.mdtHOT()[k]->driftTime()),
+					aux_res);
+// 		seg.mdtHOT()[k]->setDriftRadius(m_rt->radius(
+// 					seg.mdtHOT()[k]->driftTime()),
+// 					seg.mdtHOT()[k]->sigmaDriftRadius());
+
+   // average resolution in the segment //
+		if (seg.mdtHOT()[k]->sigmaDriftRadius()<0.5*m_r_max) {
+            av_res = av_res+std::pow(seg.mdtHOT()[k]->sigmaDriftRadius(), 2);
+        } else {
+            av_res = av_res+0.01;
+        }
+
+   // hit selection //
+		(hit_selection[0])[k] = 0;
+
+	// 1st multilayer, if splitting is requested //
+		if (m_split_into_ml) {
+			(hit_selection[0])[k] = seg.mdtHOT()[k]->identify(
+							).mdtMultilayer()==2;
+		}
+
+	// 2nd multilayer, if splitting is requested //
+		if (m_split_into_ml) {
+			(hit_selection[1])[k] = seg.mdtHOT()[k]->identify(
+						).mdtMultilayer()==1;
+		}
+
+	// reject hits with bad radii or bad resolution //
+		if (seg.mdtHOT()[k]->driftRadius()<0.0 ||
+				seg.mdtHOT()[k]->driftRadius()>m_r_max ||
+                seg.mdtHOT()[k]->sigmaDriftRadius()>10.0*m_r_max) {
+			(hit_selection[0])[k] = 1;
+			(hit_selection[1])[k] = 1;
+		}
+
+   // counting of selected segments //
+		nb_hits_in_ml[0] = nb_hits_in_ml[0]+(1-(hit_selection[0])[k]);
+		nb_hits_in_ml[1] = nb_hits_in_ml[1]+(1-(hit_selection[1])[k]);
+
+   // check for hits in both multilayers (needed if splitting is requested) //
+		if (m_multilayer[0]==false && seg.mdtHOT()[k]->identify(
+							).mdtMultilayer()==1) {
+			m_multilayer[0] = true;
+		}
+		if (m_multilayer[1]==false && seg.mdtHOT()[k]->identify(
+							).mdtMultilayer()==2) {
+			m_multilayer[1] = true;
+		}
+	}
+
+// average resolution and chi^2 scale factor // 
+	av_res = sqrt(av_res/static_cast<double>(seg.mdtHitsOnTrack()));
+	chi2_scale_factor = sqrt(av_res*av_res+m_rt_accuracy*m_rt_accuracy)/
+									av_res;
+
+///////////////////////////////////////
+// FILL THE AUTOCALIBRATION MATRICES //
+///////////////////////////////////////
+
+// set the road width for the track reconstruction //
+	m_tracker.setRoadWidth(7.0*sqrt(av_res*av_res+
+						m_rt_accuracy*m_rt_accuracy));
+
+// loop over the multilayers //
+
+//-----------------------------------------------------------------------------
+	for (unsigned k=0; k<1+static_cast<unsigned int>(m_split_into_ml);
+									k++) {
+//-----------------------------------------------------------------------------
+
+	if (nb_hits_in_ml[k]<3) {
+		continue;
+	}
+
+// refit the segments within the multilayers //          
+	if (!m_tracker.fit(seg, hit_selection[k])) {
+		continue;
+	}
+	
+	MTStraightLine track(m_tracker.track());
+	if(std::isnan(track.m_x1()) || std::isnan(track.m_x2()) || std::isnan(track.b_x1()) || std::isnan(track.b_x2()))
+		continue;
+
+
+// check the quality of the fit //
+	if (m_tracker.chi2PerDegreesOfFreedom()>5*chi2_scale_factor) {
+		continue;
+	}
+
+// check whether there are at least three track hits //
+	if (m_control_histograms) {
+		m_nb_segment_hits->Fill(
+			static_cast<double>(m_tracker.numberOfTrackHits()),
+									1.0);
+	}
+	if (m_tracker.numberOfTrackHits()<3) {
+		continue;
+	}
+
+//reject tracks with silly parameters
+	if (fabs(m_tracker.track().m_x2()) > 8e8) continue;
+
+//for filling into data class
+	if(m_iteration==0)
+		{
+		m_track_slope.Insert(m_tracker.track().m_x2());
+		m_track_position.Insert(m_tracker.track().b_x2());
+		}
+
+// bookkeeping for convergence decision and reliability estimation //
+	m_chi2 = m_chi2+m_tracker.chi2PerDegreesOfFreedom();
+	m_nb_segments_used = m_nb_segments_used+1;
+
+// debug display //
+// 	display_segment(&seg, display);
+// 	display << "MESSAGE CONTINUE\n";
+
+// fill the autocalibration objects //
+   // auxiliary variables //
+	track = m_tracker.track(); // refitted track
+	d_track = vector<double>(m_tracker.numberOfTrackHits());
+	residual_value = vector<double>(m_tracker.numberOfTrackHits());
+	w = vector<MTStraightLine>(m_tracker.numberOfTrackHits());
+	G = CLHEP::HepVector(m_tracker.numberOfTrackHits());
+	zeta = vector<double>(m_tracker.numberOfTrackHits());
+
+   // base function values //
+	for (unsigned int l=0; l<m_order; l++) {
+		m_U[l] = CLHEP::HepVector(m_tracker.numberOfTrackHits());
+		for (unsigned int m=0; m<m_tracker.numberOfTrackHits(); m++) {
+			x = (m_tracker.trackHits()[m]->driftRadius()
+						-0.5*m_r_max)/(0.5*m_r_max);
+			(m_U[l])[m] = m_base_function->value(l, x);
+		}
+	}
+
+   // get the wire coordinates, track distances, and residuals //
+	for (unsigned int l=0; l<m_tracker.numberOfTrackHits(); l++) {
+		w[l] = MTStraightLine(Amg::Vector3D(0.0, (m_tracker.trackHits(
+						)[l]->localPosition()).y(),
+						(m_tracker.trackHits(
+						)[l]->localPosition()).z()),
+					xhat, null, null);
+		d_track[l] = track.signDistFrom(w[l]);
+		residual_value[l] = m_tracker.trackHits()[l]->driftRadius()-
+							fabs(d_track[l]);
+		if (m_control_histograms) {
+			m_residuals->Fill(fabs(d_track[l]), residual_value[l],
+									1.0);
+		}
+	}
+
+   // loop over all track hits //
+	for (unsigned int l=0; l<m_tracker.numberOfTrackHits(); l++) {
+
+	// analytic calculation of G //
+		for (unsigned int m=0; m<m_tracker.numberOfTrackHits(); m++) {
+			zeta[m] = sqrt(1.0+std::pow(track.m_x2(), 2))*
+						(w[m].positionVector()).z()
+						-track.m_x2()*d_track[m];
+		}
+		for (unsigned int m=0; m<m_tracker.numberOfTrackHits(); m++) {
+		 double sum1(0.0), sum2(0.0), sum3(0.0), sum4(0.0);
+		 for (unsigned int ll=0; ll <m_tracker.numberOfTrackHits();
+		 							ll++) {
+		 	sum1 = sum1+
+				(zeta[l]-zeta[ll])*(zeta[ll]-zeta[m])/
+				(m_tracker.trackHits()[m]->sigma2DriftRadius()
+				 *m_tracker.trackHits()[ll]->sigma2DriftRadius()
+				);
+			sum2 = sum2+zeta[ll]/
+				m_tracker.trackHits()[ll]->sigma2DriftRadius();
+			sum3 = sum3+1.0/
+				m_tracker.trackHits()[ll]->sigma2DriftRadius();
+			sum4 = sum4+std::pow(zeta[ll]/
+				m_tracker.trackHits()[ll]->sigmaDriftRadius(),
+				2);
+		 }
+		 if (d_track[m]*d_track[l]>=0.0) {
+		 	G[m] = (l==m)-m_full_matrix*sum1/(sum2*sum2-sum3*sum4);
+		 }
+		 else {
+		 	G[m] = (l==m)+m_full_matrix*sum1/(sum2*sum2-sum3*sum4);
+		 }
+		}
+	CLHEP::HepSymMatrix m_A_tmp(m_A);
+	// autocalibration objects //
+		for (unsigned int p=0; p<m_order; p++) {
+		for (unsigned int pp=p; pp<m_order; pp++) {
+			m_A_tmp[p][pp] = m_A[p][pp]+
+				(dot(G, m_U[p])*dot(G, m_U[pp]))/
+				m_tracker.trackHits(
+						)[l]->sigma2DriftRadius();
+			if(std::isnan(m_A_tmp[p][pp])) return true;
+		}
+		}
+	m_A = m_A_tmp;
+	CLHEP::HepVector m_b_tmp(m_b);
+		for (unsigned int p=0; p<m_order; p++) {
+			m_b_tmp[p] = m_b[p]-residual_value[l]*dot(G, m_U[p])/
+					m_tracker.trackHits(
+						)[l]->sigma2DriftRadius();
+			if(std::isnan(m_b_tmp[p])) return true;
+		}
+	m_b=m_b_tmp;
+	}
+
+//-----------------------------------------------------------------------------
+	}
+//-----------------------------------------------------------------------------
+
+	return true;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::
+//:: METHOD setInput ::
+//:::::::::::::::::::::
+
+void RtCalibrationAnalytic::setInput(const IMdtCalibrationOutput * rt_input) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	const RtCalibrationOutput *input(
+				dynamic_cast<const RtCalibrationOutput *>
+								(rt_input));
+
+////////////////////////////////////////////
+// CHECK IF THE OUTPUT CLASS IS SUPPORTED //
+////////////////////////////////////////////
+
+	if (input==0) {
+		cerr << endl
+			<< "Class RtCalibrationAnalytic, "
+			<< "method setInput: ERROR!\n" 
+			<< "Calibration input class not supported.\n";
+		exit(1);
+	}
+
+/////////////////////////////////////////////////////////////////
+// GET THE INITIAL r-t RELATIONSHIP AND RESET STATUS VARIABLES //
+/////////////////////////////////////////////////////////////////
+
+// get the r-t relationship //
+	m_rt = input->rt();
+	m_r_max = m_rt->radius(m_rt->tUpper());
+
+// status variables //
+	m_nb_segments = 0;
+	m_nb_segments_used = 0;
+	m_chi2 = 0.0;
+	m_A = CLHEP::HepSymMatrix(m_order, 0);
+	m_b = CLHEP::HepVector(m_order, 0);
+	m_alpha = CLHEP::HepVector(m_order, 0);
+
+// drift-time interval //
+	const RtChebyshev *rt_Chebyshev(
+				dynamic_cast<const RtChebyshev *>(m_rt));
+	const RtRelationLookUp *rt_LookUp(
+				dynamic_cast<const RtRelationLookUp *>(m_rt));
+
+	if (rt_Chebyshev==0 && rt_LookUp==0) {
+		cerr << endl
+			<< "Class RtCalibrationAnalytic, "
+			<< "method setInput: ERROR!\n" 
+			<< "r-t class not supported.\n";
+		exit(1);
+	}
+
+   // RtChebyshev //
+	if (rt_Chebyshev!=0) {
+		m_t_length = rt_Chebyshev->tUpper()-rt_Chebyshev->tLower();
+		m_t_mean = 0.5*(rt_Chebyshev->tLower()+rt_Chebyshev->tUpper());
+	}
+
+   // RtRelationLookUp, dangerous implementation, but the only way right now //
+	if (rt_LookUp!=0) {
+		m_t_length = rt_LookUp->par(1)*(rt_LookUp->nPar()-2) -
+							rt_LookUp->par(0);
+		m_t_mean = 0.5*(rt_LookUp->par(1)*(rt_LookUp->nPar()-2) +
+							rt_LookUp->par(0));
+	}
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::
+//:: METHOD analyse ::
+//::::::::::::::::::::
+
+bool RtCalibrationAnalytic::analyse(void) {
+
+	if(m_tfile!=NULL)
+		m_tfile->cd();
+
+///////////////
+// VARIABLES //
+///////////////
+
+	int ifail; // flag indicating a failure of the matrix inversion
+	unsigned int nb_points(30); // number of points used to set the new
+	                            // r-t relationship
+	double step; // r step size
+	const RtChebyshev *rt_Chebyshev(
+				dynamic_cast<const RtChebyshev *>(m_rt));
+	const RtRelationLookUp *rt_LookUp(
+				dynamic_cast<const RtRelationLookUp *>(m_rt));
+	double r_corr; // radial correction
+	vector<double> rt_param(m_rt->nPar()); // parameters for the new r-t
+	double x; // reduced time
+    RtParabolicExtrapolation rt_extrapolator; // r-t extrapolator
+    RtFromPoints rt_from_points; // r-t from points
+
+////////////////////////////////////////
+// SOLVE THE AUTOCALIBRATION EQUATION //
+////////////////////////////////////////
+
+	m_alpha = m_A.inverse(ifail)*m_b;
+	if (ifail!=0) {
+		cerr << endl
+			<< "Class RtCalibrationAnalytic, method analyse: ERROR!"
+			<< endl
+			<< "Could not solve the autocalibration equation!"
+			<< endl;
+		return false;
+	}
+
+
+
+////////////////////////////////////////
+// CALCULATE THE NEW r-t RELATIONSHIP //
+////////////////////////////////////////
+
+// input r-t is of type RtChebyshev //
+	if (rt_Chebyshev!=0) {
+
+	// set the number of points //
+		if (rt_Chebyshev->numberOfRtParameters()>30) {
+			nb_points = rt_Chebyshev->numberOfRtParameters();
+		}
+
+	// r step size //
+		step = m_r_max/static_cast<double>(nb_points);
+
+	// sample points and Chebyshev fitter //
+		vector<SamplePoint> x_r(nb_points+1);
+		BaseFunctionFitter fitter(rt_Chebyshev->numberOfRtParameters());
+		ChebyshevPolynomial chebyshev;
+
+	// calculate the sample points //
+		for (unsigned int k=0; k<nb_points+1; k++) {
+		
+			x_r[k].set_x1(t_from_r(k*step));
+			x_r[k].set_x2(rt_Chebyshev->radius(x_r[k].x1()));
+			x_r[k].set_x1(rt_Chebyshev->get_reduced_time(
+								x_r[k].x1()));
+			x_r[k].set_error(1.0);
+
+			r_corr = 0.0;
+			for (unsigned int l=0; l<m_order; l++) {
+// 				r_corr = r_corr+m_alpha[l]*
+// 					m_base_function->value(l, x_r[k].x1());
+				r_corr = r_corr+m_alpha[l]*
+					m_base_function->value(l, 
+					   (x_r[k].x2()-0.5*m_r_max)/(0.5*m_r_max));
+			}
+
+
+	   // do not change the r-t and the endpoints //
+			if (((k==0 || x_r[k].x2()<0.5) && m_fix_min) || 
+				((k==nb_points || x_r[k].x2()>14.1) 
+							&& m_fix_max)) {
+				r_corr = 0.0;
+				x_r[k].set_error(0.01);
+			}
+			x_r[k].set_x2(x_r[k].x2()+r_corr);
+
+		}
+
+	// force monotony //
+		if (m_force_monotony) {
+			for (unsigned int k=0; k<nb_points; k++) {
+				if (x_r[k].x2()>x_r[k+1].x2()) {
+					x_r[k+1].set_x2(x_r[k].x2());
+				}
+			}
+		}
+
+	    if(m_control_histograms) {
+		    TGraphErrors *gre= new TGraphErrors(x_r.size());
+		    for(unsigned int i=0; i<1; i++) {
+			    gre->SetPoint(i, x_r[i].x1(), x_r[i].x2());
+			    gre->SetPointError(i, 0, x_r[i].error());
+			}
+		    std::ostringstream str_str;
+		    str_str<<"CorrectionPoints_"<<m_iteration;	
+		    gre->Write(str_str.str().c_str());
+		}
+
+	// create the new r-t relationship //
+		fitter.fit_parameters(x_r, 1, nb_points+1, &chebyshev);
+		rt_param[0] = rt_Chebyshev->tLower();
+		rt_param[1] = rt_Chebyshev->tUpper();
+		for (unsigned int k=0; k<rt_Chebyshev->numberOfRtParameters(); 
+									k++) {
+			rt_param[k+2] = fitter.coefficients()[k];
+		}
+
+		if (m_rt_new==0) {
+			delete m_rt_new;
+		}
+		m_rt_new = new RtChebyshev(rt_param);
+
+    // parabolic extrapolation // commented, as extr. to end-point is done after convergence
+/*       if (m_do_parabolic_extrapolation) {
+	    RtRelationLookUp tmprt(performParabolicExtrapolation(false, true,
+                                                                *m_rt_new));
+        if (m_rt_new!=0) {
+			delete m_rt_new;
+		}
+
+		vector<SamplePoint> t_r(nb_points+1);
+		for (unsigned int k=0; k<nb_points+1; k++) {
+			t_r[k].set_x1(t_from_r(k*step));
+			t_r[k].set_x2(tmprt.radius(k*step));
+			t_r[k].set_error(1.0);
+        }
+        m_rt_new = new RtChebyshev(rt_from_points.getRtChebyshev(t_r,
+                                        rt_Chebyshev->numberOfRtParameters()));
+       }*/
+}
+
+// input-rt is of type RtRelationLookUp //
+	if (rt_LookUp!=0) {
+		
+		rt_param=rt_LookUp->parameters();
+		unsigned int min_k(2), max_k(rt_param.size());
+		if(m_fix_min)
+			{
+			min_k=3;
+			}
+		if(m_fix_max)
+			{
+			max_k = rt_param.size()-1;
+			}
+		
+		TGraph *gr(NULL);
+		if(m_control_histograms)
+			gr=new TGraph(max_k - min_k);	
+			
+		for (unsigned int k=min_k; k<max_k; k++) {
+			x = (rt_param[k] - 0.5*m_r_max)/(0.5*m_r_max);
+			r_corr = m_alpha[0];
+			for (unsigned int l=1; l<m_order; l++) {
+				r_corr = r_corr+m_alpha[l]*
+						m_base_function->value(l, x);
+			}
+			rt_param[k] = rt_param[k]+r_corr;
+			if(m_control_histograms)
+				gr->SetPoint(k-min_k, x, r_corr);
+			if (m_force_monotony && k>2) {
+				if (rt_param[k]<rt_param[k-1]) {
+					rt_param[k]=rt_param[k-1];
+				}
+			}
+		}
+
+		if (m_rt_new==0) {
+			delete m_rt_new;
+		}
+		m_rt_new = new RtRelationLookUp(rt_param);
+        if(m_control_histograms)    
+            {
+            std::ostringstream str_str;
+            str_str<<"CorrectionPoints_"<<m_iteration;  
+            gr->Write(str_str.str().c_str());
+            }
+        m_r_max = m_rt_new->radius(m_rt_new->tUpper());
+
+    // parabolic extrapolation //
+//       if (m_do_parabolic_extrapolation) {
+//	    RtRelationLookUp tmprt(performParabolicExtrapolation(false, true,
+//                                                              *m_rt_new));
+//        if (m_rt_new!=0) {
+//			delete m_rt_new;
+//		}
+//       m_rt_new = new RtRelationLookUp(tmprt);
+//       }
+//
+	}
+
+/////////////////////////////////////////////////////////
+// DETERMINE THE r-t QUALITY AND CHECK FOR CONVERGENCE //
+/////////////////////////////////////////////////////////
+
+// estimate r-t accuracy //
+	m_rt_accuracy = 0.0;
+	// double m_rt_accuracy_diff = 0.0; 
+	double r_corr_max =0.0;
+	
+	for (unsigned int k=0; k<100; k++) {
+		r_corr = m_alpha[0];
+		for (unsigned int l=1; l<m_order; l++) {
+			r_corr = r_corr+m_alpha[l]*
+					m_base_function->value(l, -1.0+0.01*k);
+		}
+		if (fabs(r_corr) > r_corr_max){
+				r_corr_max = fabs(r_corr);
+		}
+		m_rt_accuracy = m_rt_accuracy+r_corr*r_corr;
+	}
+	m_rt_accuracy = sqrt(0.01*m_rt_accuracy);
+	// m_rt_accuracy_diff = m_rt_accuracy_previous - m_rt_accuracy;
+	m_rt_accuracy_previous = m_rt_accuracy;
+	
+// convergence? //
+
+	m_chi2 = m_chi2/static_cast<double>(m_nb_segments_used);
+	//	cout << "------------------ ITERATION: "<< m_iteration <<" ---------------------- " << endl;
+	//	cout << " CHI2:\t" << m_chi2 <<endl;
+	//	cout << " CORDUNC.DIFF:\t" << fabs(m_rt_accuracy_diff) << endl;
+	//	cout << " Accuracy Guess:\t" << fabs(m_rt_accuracy) << endl;
+	//	if ((m_chi2<=m_chi2_previous || fabs(m_rt_accuracy_diff)>0.001) &&
+	//							m_iteration<m_max_it) {
+	if ( ((m_chi2<m_chi2_previous && fabs(m_chi2-m_chi2_previous)>0.01) 
+	      || fabs(m_rt_accuracy)>0.001) 
+	     &&	m_iteration<m_max_it) {
+
+		m_status = 0; // no convergence yet
+	} 
+	else {
+		m_status = 1;
+	}
+	m_chi2_previous = m_chi2;
+
+// reliabilty of convergence //
+	if (m_status!=0) {
+		if (m_split_into_ml && m_nb_segments_used<
+				0.5*(m_multilayer[0]+m_multilayer[1])*
+								m_nb_segments) {
+			m_status = 2;
+		}
+		if (!m_split_into_ml && m_nb_segments_used<0.5*m_nb_segments) {
+			m_status = 2;
+		}
+	}
+
+//////////////////////////////////////////////////
+// STORE THE RESULTS IN THE RtCalibrationOutput //
+//////////////////////////////////////////////////
+
+	m_iteration = m_iteration+1;
+
+	if (m_output!=0) {
+		delete m_output;
+	}
+	m_output = new RtCalibrationOutput(m_rt_new, 
+			new RtFullInfo("RtCalibrationAnalytic", m_iteration,
+				m_nb_segments_used, 0.0, 0.0, 0.0, 0.0));
+
+	return true;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::
+//:: METHOD converged ::
+//::::::::::::::::::::::
+
+bool RtCalibrationAnalytic::converged(void) const {
+
+	return (m_status>0);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD getResults ::
+//:::::::::::::::::::::::
+
+const IMdtCalibrationOutput * RtCalibrationAnalytic::getResults(void) const {
+
+	return static_cast<const IMdtCalibrationOutput *>(m_output);
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::::::::::::
+//:: METHOD performParabolicExtrapolation ::
+//::::::::::::::::::::::::::::::::::::::::::
+
+RtRelationLookUp * RtCalibrationAnalytic::performParabolicExtrapolation(
+                                                const bool & min,
+                                                const bool & max,
+                                                const IRtRelation & in_rt) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+    RtParabolicExtrapolation rt_extrapolator; // r-t extrapolator
+    RtRelationLookUp *rt_low(0), *rt_high(0); // pointers to the r-t
+                                              // relationships after
+                                              // extrapolation
+	vector<SamplePoint> add_fit_point; // additional r-t points used if r(0) or
+                                       // r(t_max) is fixed.
+
+////////////////////////////////
+// EXTRAPOLATE TO LARGE RADII //
+////////////////////////////////
+
+    if (max) {
+        add_fit_point.clear();
+        if (m_fix_max) {
+            add_fit_point.push_back(SamplePoint(in_rt.tUpper(),
+                                        in_rt.radius(in_rt.tUpper()), 1.0));
+        }
+	if ( in_rt.radius(in_rt.tUpper()) < 16.0 ){
+	  rt_high = new RtRelationLookUp(
+                    rt_extrapolator.getRtWithParabolicExtrapolation(in_rt,
+                        in_rt.radius(in_rt.tUpper())-3.0,
+                        in_rt.radius(in_rt.tUpper())-1.0,
+                        in_rt.radius(in_rt.tUpper()),
+                        add_fit_point));
+	}
+	else {
+	  rt_high = new RtRelationLookUp(
+		    rt_extrapolator.getRtWithParabolicExtrapolation(in_rt,
+		        m_r_max-3.0,
+                        m_r_max-1.0,
+                        m_r_max,
+                        add_fit_point));
+	}
+    }
+
+////////////////////////////////
+// EXTRAPOLATE TO SMALL RADII //
+////////////////////////////////
+
+    if (min) {
+        add_fit_point.clear();
+        if (m_fix_min) {
+            add_fit_point.push_back(
+                                SamplePoint(m_rt_new->tLower(), 0.0, 1.0));
+        }
+        if (m_fix_max) {
+            rt_low = new RtRelationLookUp(
+                    rt_extrapolator.getRtWithParabolicExtrapolation(*rt_high,
+                        1.0,
+                        3.0,
+                        0.0,
+                        add_fit_point));
+        } else {
+            rt_low = new RtRelationLookUp(
+                    rt_extrapolator.getRtWithParabolicExtrapolation(in_rt,
+                        1.0,
+                        3.0,
+                        0.0,
+                        add_fit_point));
+        }
+    }
+
+////////////////////
+// RETURN RESULTS //
+////////////////////
+
+    if (min && max) {
+    	if(rt_high) delete rt_high;
+        return rt_low;
+    }
+    if (min) {
+    	if(rt_high) delete rt_high;
+        return rt_low;
+    }
+    if (rt_low) delete rt_low;
+    return rt_high;
+
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtCalibrationCurved.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtCalibrationCurved.cxx
new file mode 100644
index 0000000000000..9a2b92d5868f2
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtCalibrationCurved.cxx
@@ -0,0 +1,1699 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 10.05.2008, AUTHOR: OLIVER KORTNER
+// Modified: 01.03.2009 by O. Kortner, parabolic extrapolation added.
+//           15.03.2009 by O. Kortner, smoothing added.
+// 05.02.2010, JOERG v. LOEBEN
+//    major changes: - parabolic extrapolation to r(t_max) now done after the 
+//                     after the method converged and - if turned on - after the
+//                     the residual smoothing.
+//                   - prevent extrapolation to r_max to become too large.  
+//                   - changed convergence criterion of the residual smoothing
+//                     from 1 mum to 2 mum (tuned on cosmics) 
+//                   - reduced the roadwidth of the curved segment refit for
+//                     smoothing from 7->5 times the average 
+//                     (tuned on cosmics) tube resolution
+//                   - change in convergence criterion to prevent 
+//                     iterating with only minor changes (tuned on cosmics)
+//                   - increase of spacial precision in method t_from_r to 1mum
+//                     (important to reduce oscillations in r(t) relationship)
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: IMPLEMENTATION OF METHODS DEFINED IN THE CLASS RtCalibrationCurved ::
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+#include "MdtCalibRt/RtCalibrationCurved.h"
+#include "CLHEP/GenericFunctions/CumulativeChiSquare.hh"
+#include "MdtCalibRt/RtCalibrationOutput.h"
+#include "MdtCalibData/RtChebyshev.h"
+#include "MdtCalibData/RtRelationLookUp.h"
+#include "MuonCalibMath/BaseFunctionFitter.h"
+#include "MuonCalibMath/ChebyshevPolynomial.h"
+#include "MuonCalibMath/LegendrePolynomial.h"
+#include "MuonCalibMath/PolygonBase.h"
+#include "CLHEP/Matrix/Matrix.h"
+#include "MdtCalibRt/RtParabolicExtrapolation.h"
+#include "MdtCalibData/RtFromPoints.h"
+#include "MdtCalibRt/AdaptiveResidualSmoothing.h"
+
+#include "MdtCalibInterfaces/IMdtCalibrationOutput.h"
+#include "MdtCalibData/IRtRelation.h"
+#include "MdtCalibData/RtRelationLookUp.h"
+#include "MdtCalibData/RtScaleFunction.h"
+#include "MdtCalibRt/RtCalibrationOutput.h"
+#include "MdtCalibFitters/CurvedPatRec.h"
+#include "MuonCalibEventBase/MuonCalibSegment.h"
+#include "MuonCalibMath/BaseFunction.h"
+
+#include "MultilayerRtDifference.h"
+
+
+#include "sstream"
+#include "TF1.h"
+#include "TProfile.h"
+
+//::::::::::::::::::::::::
+//:: NAMESPACE SETTINGS ::
+//::::::::::::::::::::::::
+
+using namespace MuonCalib;
+using namespace std;
+
+inline Double_t RtCalibrationCurved_polfun(Double_t *x, Double_t *par)
+	{
+	return par[0] * RtScalePolynomial(x[0]);
+	}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::
+//:: DEFAULT CONSTRUCTOR ::
+//:::::::::::::::::::::::::
+
+RtCalibrationCurved::RtCalibrationCurved(std::string name) :
+													IMdtCalibration(name), m_rt_accuracy_previous(0.0){
+
+	init(0.5*CLHEP::mm, 1, 15, true, false, 15, false, false, false);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: CONSTRUCTOR ::
+//:::::::::::::::::
+
+RtCalibrationCurved::RtCalibrationCurved(std::string name,
+                        const double & rt_accuracy,
+                        const unsigned int & func_type,
+                        const unsigned int & ord,
+                        const bool & fix_min,
+                        const bool & fix_max,
+                        const int & max_it,
+                        bool do_parabolic_extrapolation,
+                        bool do_smoothing,
+			bool do_multilayer_rt_scale) 
+			: IMdtCalibration(name), m_rt_accuracy_previous(0.0){
+
+	init(rt_accuracy, func_type, ord, fix_min, fix_max, max_it,
+                                     do_parabolic_extrapolation, do_smoothing, 
+				     do_multilayer_rt_scale);
+
+}
+
+
+//*****************************************************************************
+
+//::::::::::::::::
+//:: DESTRUCTOR ::
+//::::::::::::::::
+
+RtCalibrationCurved::~RtCalibrationCurved(void) {
+
+    if (m_tracker!=0) {
+        delete m_tracker;
+    }
+
+	if (m_base_function!=0) {
+		delete m_base_function;
+	}
+	delete m_multilayer_rt_difference;
+	if (m_tfile!=0) {
+		m_tfile->Write();
+		delete m_cut_evolution;
+		delete m_nb_segment_hits;
+		delete m_pull_initial;
+		delete m_pull_final;
+		delete m_residuals_initial;
+		delete m_residuals_final;
+		delete m_tfile;
+	}
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::
+//:: METHOD reliability ::
+//::::::::::::::::::::::::
+
+double RtCalibrationCurved::reliability(void) const {
+
+	return m_status;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::
+//:: METHOD estimatedRtAccuracy ::
+//::::::::::::::::::::::::::::::::
+
+double RtCalibrationCurved::estimatedRtAccuracy(void) const {
+
+	return m_rt_accuracy;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::
+//:: METHOD numberOfSegments ::
+//:::::::::::::::::::::::::::::
+
+int RtCalibrationCurved::numberOfSegments(void) const {
+
+	return m_nb_segments;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::
+//:: METHOD numberOfSegmentsUsed ::
+//:::::::::::::::::::::::::::::::::
+
+int RtCalibrationCurved::numberOfSegmentsUsed(void) const {
+
+	return m_nb_segments_used;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::
+//:: METHOD iteration ::
+//::::::::::::::::::::::
+
+int RtCalibrationCurved::iteration(void) const {
+
+	return m_iteration;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::
+//:: METHOD smoothing ::
+//::::::::::::::::::::::
+
+bool RtCalibrationCurved::smoothing(void) const {
+
+    return m_do_smoothing;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::::
+//:: METHOD setEstimateRtAccuracy ::
+//::::::::::::::::::::::::::::::::::
+
+void RtCalibrationCurved::setEstimateRtAccuracy(const double & acc) {
+
+	m_rt_accuracy = fabs(acc);
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::::::::::
+//:: METHOD switch_on_control_histograms ::
+//:::::::::::::::::::::::::::::::::::::::::
+
+void RtCalibrationCurved::switch_on_control_histograms(
+											const std::string & file_name) {
+
+/////////////////////////////////////////////
+// CREATE THE ROOT FILE AND THE HISTOGRAMS //
+/////////////////////////////////////////////
+
+	m_control_histograms = true;
+
+	m_tfile = new TFile(file_name.c_str(), "RECREATE");
+
+	m_cut_evolution = new TH1F("m_cut_evolution",
+				"CUT EVOLUTION",
+				11, -0.5, 10.5);
+
+	m_nb_segment_hits = new TH1F("m_nb_segment_hits",
+				"NUMBER OF HITS ON THE REFITTED SEGMENTS",
+				11, -0.5, 10.5);
+
+	m_pull_initial = new TH1F("m_pull_initial",
+				"INITIAL PULL DISTRIBUTION",
+				200, -5.05, 5.05); 
+// 	m_pull_final = new TH1F("m_pull_final",
+// 				"FINAL PULL DISTRIBUTION",
+// 				200, -5.05, 5.05); 
+
+	m_residuals_initial = new TH2F("m_residuals_initial",
+				"INITIAL OF THE REFITTED SEGMENTS",
+				100, -0.5, 15.0, 300, -1.5, 1.5);
+	m_residuals_final = new TH2F("m_residuals_final",
+				"FINAL OF THE REFITTED SEGMENTS",
+				100, -0.5, 15.0, 300, -1.5, 1.5);
+
+	delete m_multilayer_rt_difference;
+	m_multilayer_rt_difference=new MultilayerRtDifference(10000, m_tfile);
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::::::::::::
+//:: METHOD switch_off_control_histograms ::
+//::::::::::::::::::::::::::::::::::::::::::
+
+void RtCalibrationCurved::switch_off_control_histograms(void) {
+
+	m_control_histograms = false;
+	if (m_tfile!=0) {
+		m_tfile->Write();
+		delete m_multilayer_rt_difference;
+		m_multilayer_rt_difference=new MultilayerRtDifference(10000);
+	}
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::
+//:: METHOD forceMonotony ::
+//::::::::::::::::::::::::::
+
+void RtCalibrationCurved::forceMonotony(void) {
+
+	m_force_monotony = true;
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::
+//:: METHOD doNotForceMonotony ::
+//:::::::::::::::::::::::::::::::
+
+void RtCalibrationCurved::doNotForceMonotony(void) {
+
+	m_force_monotony = false;
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::::::
+//:: METHOD doParabolicExtrapolation ::
+//:::::::::::::::::::::::::::::::::::::
+
+void RtCalibrationCurved::doParabolicExtrapolation(void) {
+
+    m_do_parabolic_extrapolation = true;
+    return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::
+//:: METHOD doSmoothing ::
+//::::::::::::::::::::::::::
+
+void RtCalibrationCurved::doSmoothing(void) {
+
+	m_do_smoothing = true;
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::
+//:: METHOD noSmoothing ::
+//::::::::::::::::::::::::::
+
+void RtCalibrationCurved::noSmoothing(void) {
+
+	m_do_smoothing = false;
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::
+//:: METHOD analyseSegments ::
+//::::::::::::::::::::::::::::
+
+const IMdtCalibrationOutput * RtCalibrationCurved::analyseSegments(
+                                const std::vector<MuonCalibSegment*> & seg) {
+
+	const IRtRelation *tmp_rt(0);
+
+//////////////////////////
+// AUTOCALIBRATION LOOP //
+//////////////////////////
+
+	while (!converged()) {
+				
+		for (unsigned int k=0; k<seg.size(); k++) {
+			handleSegment(*seg[k]);
+		}
+		if(!analyse(seg)) {
+			for(unsigned int i=0; i<seg.size(); i++) {
+				std::cout << i << " " << seg[i]->direction() <<" "
+										<< seg[i]->position() << std::endl;
+			}
+			return NULL;
+		}
+
+		const RtCalibrationOutput* rtOut =m_output;
+
+		if (!converged()) {
+			setInput(rtOut);
+		}
+		tmp_rt = rtOut->rt();
+	}
+
+// parabolic extrapolations for small radii //
+    if (m_do_parabolic_extrapolation) {
+	    RtRelationLookUp *tmprt = 
+                        performParabolicExtrapolation(true, true, *tmp_rt);
+	    delete m_output;
+	    m_output = new RtCalibrationOutput(tmprt, 
+				new RtFullInfo("RtCalibrationCurved", m_iteration,
+				m_nb_segments_used, 0.0, 0.0, 0.0, 0.0));
+        delete tmp_rt;
+        tmp_rt = tmprt;
+    }
+
+//////////////////////////////////////////////
+// SMOOTHING AFTER CONVERGENCE IF REQUESTED //
+//////////////////////////////////////////////
+
+	if (!m_do_smoothing) {
+// final residuals //
+        double r, d;
+        for (unsigned int k=0; k<seg.size(); k++) {
+            for (unsigned int l=0; l<seg[k]->hitsOnTrack(); l++) {
+                r = fabs((seg[k]->mdtHOT())[l]->driftRadius());
+                d = fabs((seg[k]->mdtHOT())[l]->signedDistanceToTrack());
+		if(m_residuals_final != NULL)
+                m_residuals_final->Fill(d, r-d, 1.0);
+            }
+        }
+		return getResults();
+	}
+
+// maximum number of iterations //
+	int max_smoothing_iterations(static_cast<int>(m_max_it));
+	if (max_smoothing_iterations==0) {
+		max_smoothing_iterations = 1;
+	}
+
+// convergence RMS //
+	double convergence_RMS(0.002);
+
+// variables //
+	int it(0); // iteration
+	double RMS(1.0); // RMS change of r(t)
+
+// smoothing //
+//---------------------------------------------------------------------------//
+//---------------------------------------------------------------------------//
+	while (it<max_smoothing_iterations && RMS>convergence_RMS) {
+//---------------------------------------------------------------------------//
+
+ 	AdaptiveResidualSmoothing smoothing;
+
+  // counter //
+	unsigned int counter(0);
+	unsigned int counter2(0);
+
+  // overwrite drift radii and calculate the average resolution //
+	for (unsigned int k=0; k<seg.size(); k++) {
+		if (seg[k]->mdtHitsOnTrack()<4) {
+			continue;
+		}
+ 		counter2++;
+		double avres(0.0);
+		for (unsigned int h=0; h<seg[k]->mdtHitsOnTrack(); h++) {
+            seg[k]->mdtHOT()[h]->setDriftRadius(tmp_rt->radius(
+					seg[k]->mdtHOT()[h]->driftTime()),
+					seg[k]->mdtHOT()[h]->sigmaDriftRadius());
+			if (seg[k]->mdtHOT()[h]->sigmaDriftRadius()<0.5*m_r_max) {
+                avres = avres+seg[k]->mdtHOT()[h]->sigma2DriftRadius();
+            } else {
+                avres = avres+0.01;
+            }
+		}
+		avres = avres/static_cast<double>(seg[k]->mdtHitsOnTrack());
+		avres = sqrt(avres);
+        if (smoothing.addResidualsFromSegment(*seg[k], true, 5.0*avres)) {
+		    counter++;
+		}
+	}
+
+ // break, do no smoothing if there are not enough segments //
+	if (counter<1000) {
+		cerr << "Class RtCalibrationCurved, no smoothing applied due to "
+		     << "too small number of reconstructed segments!\n";
+// final residuals //
+        double r, d;
+        for (unsigned int k=0; k<seg.size(); k++) {
+            for (unsigned int l=0; l<seg[k]->hitsOnTrack(); l++) {
+                r = fabs((seg[k]->mdtHOT())[l]->driftRadius());
+                d = fabs((seg[k]->mdtHOT())[l]->signedDistanceToTrack());
+		if(m_residuals_final != NULL)
+                m_residuals_final->Fill(d, r-d, 1.0);
+            }
+        }
+		return getResults();
+	}
+
+  // smoothing //
+	RtRelationLookUp smooth_rt(smoothing.performSmoothing(*tmp_rt,
+													m_fix_min, m_fix_max));
+
+  // calculate RMS change //
+	RMS = 0.0;
+	double bin_width(0.01*(smooth_rt.tUpper()-smooth_rt.tLower()));
+	for (double t=smooth_rt.tLower(); t<=smooth_rt.tUpper(); t=t+bin_width) {
+		RMS = RMS+std::pow(smooth_rt.radius(t)-tmp_rt->radius(t), 2);
+	}
+	RMS = sqrt(0.01*RMS);
+
+  // increase the iterations counter //
+	it++;
+
+  // delete tmp_rt and update it //
+	delete tmp_rt;
+	tmp_rt = new RtRelationLookUp(smooth_rt);
+
+//---------------------------------------------------------------------------//
+	}
+//---------------------------------------------------------------------------//
+//---------------------------------------------------------------------------//
+
+	delete m_output;
+	m_output = new RtCalibrationOutput(tmp_rt, 
+				new RtFullInfo("RtCalibrationCurved", m_iteration,
+				m_nb_segments_used, 0.0, 0.0, 0.0, 0.0));
+
+/////////////////////
+// FINAL RESIDUALS //
+/////////////////////
+
+    double r, d;
+    for (unsigned int k=0; k<seg.size(); k++) {
+        for (unsigned int l=0; l<seg[k]->hitsOnTrack(); l++) {
+            r = fabs((seg[k]->mdtHOT())[l]->driftRadius());
+            d = fabs((seg[k]->mdtHOT())[l]->signedDistanceToTrack());
+	    if(m_residuals_final != NULL)
+            m_residuals_final->Fill(d, r-d, 1.0);
+        }
+    }
+
+/////////////////////////////////////////
+// RETURN THE RESULT AFTER CONVERGENCE //
+/////////////////////////////////////////
+
+	return getResults();
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::
+//:: METHOD handleSegment ::
+//::::::::::::::::::::::::::
+
+bool RtCalibrationCurved::handleSegment(MuonCalibSegment & seg) {
+
+/////////////////////////////////////////////////
+// RETURN, IF THE SEGMENT HAD LESS THAN 4 HITS //
+/////////////////////////////////////////////////
+
+	if (m_control_histograms) {
+		m_cut_evolution->Fill(0.0, 1.0);
+	}
+
+	m_nb_segments = m_nb_segments+1;
+	if (seg.mdtHitsOnTrack()<4) {
+		return true;
+	}
+
+	if (m_control_histograms) {
+		m_cut_evolution->Fill(1.0, 1.0);
+	}
+
+	if (std::isnan(seg.direction().x()) || std::isnan(seg.direction().y())||
+        std::isnan(seg.direction().z()) || std::isnan(seg.position().x()) ||
+        std::isnan(seg.position().y()) || std::isnan(seg.position().z())) {
+		return true;
+    }
+	if (fabs(seg.direction().y())>100) {
+        return true;
+    }
+
+///////////////
+// VARIABLES //
+///////////////
+
+// segment reconstruction and segment selection //
+	double aux_res; // auxiliary resolution
+	double av_res(0.0); // average spatial resolution of the tube hits
+	double chi2_scale_factor; // chi^2 scale factor used to take into
+	                          // account bad r-t accuracy in the segment
+	                          // selection
+	IMdtSegmentFitter::HitSelection hit_selection(seg.mdtHitsOnTrack());
+						// hit selection vectors for refits
+	unsigned int nb_hits_in_ml; // number of hits in the multilayers
+	double x; // reduced time = (r(t)-0.5*m_r_max)/(0.5*m_r_max)
+	vector<double> d_track; // signed distances of the track from the anode 
+	                        // wires of the tubes
+	vector<MTStraightLine> w; // anode wires
+	Amg::Vector3D null(0.0, 0.0, 0.0); // auxiliary 0 vector
+	Amg::Vector3D xhat(1.0, 0.0, 0.0); // auxiliary unit vector
+
+// objects needed to calculate the autocalibration matrix and vector //
+    vector<CLHEP::HepVector> F; // auxiliary vectors for the calculation of the
+                         // track cooeffients matrix
+	CLHEP::HepVector residual_value; // residuals values
+    CLHEP::HepVector weighted_residual; // residual values weighted by the inverse
+                                 // variance of the radius measurements
+    CLHEP::HepMatrix D; // Jacobian of the residuals (dresiduals/dr)
+//     static ofstream display("display.kumac");
+
+///////////////////////////////////////
+// PREPARATION FOR THE SEGMENT REFIT //
+///////////////////////////////////////
+
+// debug display //
+// 	display_segment(&seg, display);
+
+// overwrite the drift radii according to the input r-t relationship, //
+// calculate the average spatial resolution to define a road width,   //
+// select the hits in the chamber                                     //
+	nb_hits_in_ml = 0;
+	for (unsigned int k=0; k<seg.mdtHitsOnTrack(); k++) {
+	
+
+   // make the resolution at small radii large enough //
+        aux_res = seg.mdtHOT()[k]->sigmaDriftRadius();
+        if (m_rt->radius(seg.mdtHOT()[k]->driftTime())<0.75) {
+            if (aux_res<0.5-m_rt->radius(seg.mdtHOT()[k]->driftTime())) {
+                aux_res = 0.5-m_rt->radius(seg.mdtHOT()[k]->driftTime());
+            }
+        }
+
+   // overwrite radius //
+//   		std::cout<<"XXxxXX "<<m_rt->GetTmaxDiff()<<std::endl;
+		seg.mdtHOT()[k]->setDriftRadius(m_rt->radius(
+					seg.mdtHOT()[k]->driftTime()),
+					aux_res);
+
+   // hit selection //
+		hit_selection[k] = 0;
+
+	// reject hits with bad radii //
+		if (seg.mdtHOT()[k]->driftRadius()<0.0 ||
+				seg.mdtHOT()[k]->driftRadius()>m_r_max ||
+                seg.mdtHOT()[k]->sigmaDriftRadius()>10.0*m_r_max) {
+			hit_selection[k] = 1;
+		}
+
+   // average resolution in the segment //
+		if (hit_selection[k]==0) {
+		    if (seg.mdtHOT()[k]->sigmaDriftRadius()<0.5*m_r_max) {
+                av_res = av_res+std::pow(seg.mdtHOT()[k]->sigmaDriftRadius(), 2);
+            } else {
+                av_res = av_res+0.01;
+            }
+        }
+
+   // counting of selected segments //
+		nb_hits_in_ml = nb_hits_in_ml+(1-hit_selection[k]);
+
+	}
+
+
+// average resolution and chi^2 scale factor // 
+	av_res = sqrt(av_res/static_cast<double>(seg.mdtHitsOnTrack()));
+	chi2_scale_factor = sqrt(av_res*av_res+m_rt_accuracy*m_rt_accuracy)/
+									av_res;
+
+///////////////////////////////////////
+// FILL THE AUTOCALIBRATION MATRICES //
+///////////////////////////////////////
+
+// set the road width for the track reconstruction //
+	m_tracker->setRoadWidth(
+						7.0*sqrt(av_res*av_res+m_rt_accuracy*m_rt_accuracy));
+
+// check whether there are enough hits in the chambers //
+	if (nb_hits_in_ml<4) {
+		return true;
+	}
+
+// refit the segments //          
+	if (!m_tracker->fit(seg, hit_selection)) {
+		return true;
+	}
+
+	CurvedLine track(m_tracker->curvedTrack());
+	if(std::isnan(m_tracker->chi2())) {
+        return true;
+    }
+
+// check the quality of the fit //
+	if (m_tracker->chi2PerDegreesOfFreedom()>5*chi2_scale_factor) {
+		return true;
+	}
+
+// check whether there are at least three track hits //
+	if (m_control_histograms) {
+		m_nb_segment_hits->Fill(
+			static_cast<double>(m_tracker->numberOfTrackHits()), 1.0);
+	}
+	if (m_tracker->numberOfTrackHits()<4) {
+		return true;
+	}
+    
+// 	display_segment(&seg, display&(m_tracker->curvedTrack()));
+
+//reject tracks with silly parameters
+	if (fabs(m_tracker->curvedTrack().getTangent(
+                        seg.mdtHOT()[0]->localPosition().z()).m_x2())>8.0e8) {
+        return true;
+    }
+
+// bookkeeping for convergence decision and reliability estimation //
+	m_chi2 = m_chi2+m_tracker->chi2PerDegreesOfFreedom();
+	m_nb_segments_used = m_nb_segments_used+1;
+
+// debug display //
+// 	display_segment(&seg, display);
+// 	display << "MESSAGE CONTINUE\n";
+
+// fill the autocalibration objects //
+   
+   
+   // track coeffient matrix and its inverse //
+    F = vector<CLHEP::HepVector>(m_tracker->numberOfTrackHits());
+    for (unsigned int h=0; h<m_tracker->numberOfTrackHits(); h++) {
+       
+        const MdtCalibHitBase &hb=*(m_tracker->trackHits()[h]);
+	m_multilayer_rt_difference->Fill(hb, *m_rt);
+    
+        F[h] = CLHEP::HepVector(m_M_track.num_row());
+        for (int p=0; p<F[h].num_row(); p++) {
+            (F[h])[p] = m_Legendre->value(p, (m_tracker->trackHits(
+                                            )[h]->localPosition()).z())
+                      /sqrt(1.0+std::pow(track.getTangent(
+                                       (m_tracker->trackHits(
+                                       )[h]->localPosition()).z()).m_x2(), 2));
+        }
+    }
+    for (int p=0; p<m_M_track.num_row(); p++) {
+    for (int q=p; q<m_M_track.num_row(); q++) {
+        m_M_track[p][q] = 0.0;
+        for (unsigned int h=0; h<m_tracker->numberOfTrackHits(); h++) {
+            m_M_track[p][q] = m_M_track[p][q]+(F[h])[p]*(F[h])[q]/
+                               (m_tracker->trackHits()[h])->sigma2DriftRadius();
+        }
+        m_M_track[q][p] = m_M_track[p][q];
+        
+    }
+    }
+    int ifail;
+    m_M_track_inverse = m_M_track.inverse(ifail);
+    if (ifail!=0) {
+        cerr << endl
+                << "Class RtCalibrationCurved, method handleSegment: WARNING!"
+                << endl
+                << "Could not invert track matrix!\n";
+        return true;
+    }
+
+// Jacobian matrix for the residuals //
+   // track distances, residuals, corrections //
+    d_track = vector<double>(m_tracker->numberOfTrackHits());
+	w = vector<MTStraightLine>(m_tracker->numberOfTrackHits());
+    residual_value = CLHEP::HepVector(m_tracker->numberOfTrackHits());
+    weighted_residual = CLHEP::HepVector(m_tracker->numberOfTrackHits());
+    for (unsigned int l=0; l<m_order; l++) {
+		m_U[l] = CLHEP::HepVector(m_tracker->numberOfTrackHits());
+		m_U_weighted[l] = CLHEP::HepVector(m_tracker->numberOfTrackHits());
+	}
+    for (unsigned int h=0; h<m_tracker->numberOfTrackHits(); h++) {
+        w[h] = MTStraightLine(Amg::Vector3D(0.0, (m_tracker->trackHits(
+						)[h]->localPosition()).y(),
+						(m_tracker->trackHits(
+						)[h]->localPosition()).z()), xhat, null, null);
+        d_track[h] = track.getTangent((m_tracker->trackHits(
+						)[h]->localPosition()).z()).signDistFrom(w[h]);
+        residual_value[h] = (m_tracker->trackHits()[h])->driftRadius()-
+                                                            fabs(d_track[h]);
+		if (m_control_histograms) {
+			if (m_iteration==0) {
+				m_residuals_initial->Fill(fabs(d_track[h]), residual_value[h],
+																		1.0);
+			}
+		}
+        for (unsigned int l=0; l<m_order; l++) {
+			x = (m_tracker->trackHits()[h]->driftRadius()
+						                        -0.5*m_r_max)/(0.5*m_r_max);
+			(m_U[l])[h] = m_base_function->value(l, x);
+        }
+    }
+
+
+// test track matrix //
+//     static ofstream outfile("tmp.txt");
+//     CLHEP::HepVector my_b(3);
+//     for (int p=0; p<my_b.num_row(); p++) {
+//         my_b[p] = 0.0;
+//         for (unsigned int h=0; h<m_tracker->numberOfTrackHits(); h++) {
+// //             my_b[p] = my_b[p]+m_Legendre->value(p, (m_tracker->trackHits(
+// //                                             )[h]->localPosition()).z())*
+// //                      (
+// //                       +(2*d_track[h]>=0-1)*m_tracker->trackHits()[h]->driftRadius()
+// //                       +(m_tracker->trackHits()[h]->localPosition()).y()
+// //                        /sqrt(1.0+std::pow((track.getTangent(
+// //                                        (m_tracker->trackHits(
+// //                                        )[h]->localPosition()).z())).m_x2(), 2))
+// //                      )
+// //                      /(
+// //                        (m_tracker->trackHits()[h])->sigma2DriftRadius()
+// //                        *sqrt(1.0+std::pow((track.getTangent(
+// //                                        (m_tracker->trackHits(
+// //                                        )[h]->localPosition()).z())).m_x2(), 2))
+// //                        );
+//             my_b[p] = my_b[p]+((m_tracker->trackHits()[h]->localPosition()).y()
+//                             +(2*(d_track[h]>=0)-1)
+//                              *sqrt(1.0+std::pow((track.getTangent(
+//                                        (m_tracker->trackHits(
+//                                        )[h]->localPosition()).z())).m_x2() ,2))
+//                              *m_tracker->trackHits()[h]->driftRadius())
+//                              *m_Legendre->value(p, (m_tracker->trackHits(
+//                                             )[h]->localPosition()).z())
+//                              /((m_tracker->trackHits()[h])->sigma2DriftRadius()
+//                                 *(1.0+std::pow((track.getTangent(
+//                                        (m_tracker->trackHits(
+//                                        )[h]->localPosition()).z())).m_x2() ,2)));
+//         }
+//     }
+//     CLHEP::HepVector my_alpha(3);
+//     my_alpha = m_M_track_inverse*my_b;
+//     for (unsigned int h=0; h<m_tracker->numberOfTrackHits(); h++) {
+//         double ypos(0.0);
+//         for (unsigned int p=0; p<3; p++) {
+//             ypos = ypos+my_alpha[p]*m_Legendre->value(p, (m_tracker->trackHits(
+//                                             )[h]->localPosition()).z());
+//         }
+//         outfile << (m_tracker->trackHits()[h]->localPosition()).z() << "\t"
+//                     << m_tracker->curvedTrack().getPointOnLine(
+//                         (m_tracker->trackHits()[h]->localPosition()).z()).y()
+//                     << "\t" << ypos << endl;
+//     }
+
+   // Jacobian //
+	D = CLHEP::HepMatrix(m_tracker->numberOfTrackHits(), m_tracker->numberOfTrackHits());
+	for (unsigned int h=0; h<m_tracker->numberOfTrackHits(); h++) {
+	for (unsigned int hp=0; hp<m_tracker->numberOfTrackHits(); hp++) {
+		D[h][hp] = (h==hp)-(2*(d_track[h]>=0)-1)*(2*(d_track[hp]>=0)-1)
+							*dot(F[h], m_M_track_inverse*F[hp])/
+							(m_tracker->trackHits()[hp])->sigma2DriftRadius();
+	}
+	}
+
+// autocalibration objects //
+   // errors of the residuals //
+	vector<double> sigma_residual(m_tracker->numberOfTrackHits(), 0.0);
+	for (unsigned int h=0; h<m_tracker->numberOfTrackHits(); h++) {
+		for (unsigned int hp=0; hp<m_tracker->numberOfTrackHits(); hp++) {
+			sigma_residual[h] = sigma_residual[h]+
+									std::pow(D[h][hp]*(m_tracker->trackHits()[hp]
+													)->sigmaDriftRadius(), 2);
+		}
+		sigma_residual[h] = sqrt(sigma_residual[h]);
+	    if (sigma_residual[h]<av_res/
+                        static_cast<double>(m_tracker->numberOfTrackHits())) {
+            sigma_residual[h] = av_res/sqrt(m_tracker->numberOfTrackHits());
+        }
+    }
+
+
+   // weight residuals and correction functions //
+	for (unsigned int h=0; h<m_tracker->numberOfTrackHits(); h++) {
+		weighted_residual[h] = residual_value[h]/sigma_residual[h];
+        if (m_control_histograms) {
+			if (m_iteration==0) {
+				m_pull_initial->Fill(weighted_residual[h], 1.0);
+			}
+		}
+		for (unsigned int l=0; l<m_order; l++) {
+			(m_U_weighted[l])[h] = (m_U[l])[h]/sigma_residual[h];
+		}
+	}
+
+   // autocalibration matrix and autocalibration vector //
+	CLHEP::HepSymMatrix m_A_tmp(m_A);
+
+   // autocalibration objects //
+	for (unsigned int p=0; p<m_order; p++) {
+	for (unsigned int pp=p; pp<m_order; pp++) {
+	    m_A_tmp[p][pp] = m_A[p][pp]+dot(D*m_U_weighted[p], D*m_U_weighted[pp]);
+	if (std::isnan(m_A_tmp[p][pp])) {
+            return true;
+        }
+	}
+	}
+
+	CLHEP::HepVector m_b_tmp(m_b);
+	for (unsigned int p=0; p<m_order; p++) {
+		m_b_tmp[p] = m_b[p]+dot(D*m_U_weighted[p], weighted_residual);
+		if (std::isnan(m_b_tmp[p])) { 
+            return true;
+        }
+	}
+
+	m_A = m_A_tmp;
+	m_b=m_b_tmp;
+
+	return true;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::
+//:: METHOD setInput ::
+//:::::::::::::::::::::
+
+void RtCalibrationCurved::setInput(const IMdtCalibrationOutput * rt_input) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	const RtCalibrationOutput *input(
+				dynamic_cast<const RtCalibrationOutput *>
+								(rt_input));
+
+////////////////////////////////////////////
+// CHECK IF THE OUTPUT CLASS IS SUPPORTED //
+////////////////////////////////////////////
+
+	if (input==0) {
+		cerr << endl
+			<< "Class RtCalibrationCurved, "
+			<< "method setInput: ERROR!\n" 
+			<< "Calibration input class not supported.\n";
+		exit(1);
+	}
+
+/////////////////////////////////////////////////////////////////
+// GET THE INITIAL r-t RELATIONSHIP AND RESET STATUS VARIABLES //
+/////////////////////////////////////////////////////////////////
+
+// get the r-t relationship //
+	m_rt = input->rt();
+
+// status variables //
+	m_nb_segments = 0;
+	m_nb_segments_used = 0;
+	m_chi2 = 0.0;
+	m_A = CLHEP::HepSymMatrix(m_order, 0);
+	m_b = CLHEP::HepVector(m_order, 0);
+	m_alpha = CLHEP::HepVector(m_order, 0);
+
+// drift-time interval //
+	const RtChebyshev *rt_Chebyshev(
+				dynamic_cast<const RtChebyshev *>(m_rt));
+	const RtRelationLookUp *rt_LookUp(
+				dynamic_cast<const RtRelationLookUp *>(m_rt));
+
+	if (rt_Chebyshev==0 && rt_LookUp==0) {
+		cerr << endl
+			<< "Class RtCalibrationCurved, "
+			<< "method setInput: ERROR!\n" 
+			<< "r-t class not supported.\n";
+		exit(1);
+	}
+
+   // RtChebyshev //
+	if (rt_Chebyshev!=0) {
+		m_t_length = rt_Chebyshev->tUpper()-rt_Chebyshev->tLower();
+		m_t_mean = 0.5*(rt_Chebyshev->tLower()+rt_Chebyshev->tUpper());
+	}
+
+   // RtRelationLookUp, dangerous implementation, but the only way right now //
+	if (rt_LookUp!=0) {
+		m_t_length = rt_LookUp->par(1)*(rt_LookUp->nPar()-2) -
+							rt_LookUp->par(0);
+		m_t_mean = 0.5*(rt_LookUp->par(1)*(rt_LookUp->nPar()-2) +
+							rt_LookUp->par(0));
+	}
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::
+//:: METHOD analyse ::
+//::::::::::::::::::::
+
+bool RtCalibrationCurved::analyse(const std::vector<MuonCalibSegment*> & seg) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	int ifail; // flag indicating a failure of the matrix inversion
+	unsigned int nb_points(30); // number of points used to set the new
+	                            // r-t relationship
+	double step; // r step size
+	const RtChebyshev *rt_Chebyshev(
+				dynamic_cast<const RtChebyshev *>(m_rt));
+	const RtRelationLookUp *rt_LookUp(
+				dynamic_cast<const RtRelationLookUp *>(m_rt));
+	double r_corr; // radial correction
+	vector<double> rt_param(m_rt->nPar()); // parameters for the new r-t
+	double x; // reduced time
+    RtFromPoints rt_from_points; // r-t from points
+
+////////////////////////////////////////
+// SOLVE THE AUTOCALIBRATION EQUATION //
+////////////////////////////////////////
+
+	m_alpha = m_A.inverse(ifail)*m_b;
+	if (ifail!=0) {
+		cerr << endl
+			<< "Class RtCalibrationCurved, method analyse: ERROR!"
+			<< endl
+			<< "Could not solve the autocalibration equation!"
+			<< endl;
+		return false;
+	}
+
+////////////////////////////////////////
+// CALCULATE THE NEW r-t RELATIONSHIP //
+////////////////////////////////////////
+
+// input r-t is of type RtChebyshev //
+	if (rt_Chebyshev!=0) {
+
+	// set the number of points //
+		if (rt_Chebyshev->numberOfRtParameters()>30) {
+			nb_points = rt_Chebyshev->numberOfRtParameters();
+		}
+
+	// r step size //
+		step = m_r_max/static_cast<double>(nb_points);
+
+	// sample points and Chebyshev fitter //
+		vector<SamplePoint> x_r(nb_points+1);
+		BaseFunctionFitter fitter(rt_Chebyshev->numberOfRtParameters());
+		ChebyshevPolynomial chebyshev;
+
+	// calculate the sample points //
+		for (unsigned int k=0; k<nb_points+1; k++) {
+		
+			x_r[k].set_x1(t_from_r(k*step));
+			x_r[k].set_x2(rt_Chebyshev->radius(x_r[k].x1()));
+			x_r[k].set_x1(rt_Chebyshev->get_reduced_time(
+								x_r[k].x1()));
+			x_r[k].set_error(1.0);
+
+			r_corr = 0.0;
+			for (unsigned int l=0; l<m_order; l++) {
+// 				r_corr = r_corr+m_alpha[l]*
+// 					m_base_function->value(l, x_r[k].x1());
+				r_corr = r_corr+m_alpha[l]*
+					m_base_function->value(l, 
+					   (x_r[k].x2()-0.5*m_r_max)/(0.5*m_r_max));
+			}
+
+
+	   // do not change the r-t and the endpoints //
+			if (((k==0 || x_r[k].x2()<0.5) && m_fix_min) || 
+				((k==nb_points || x_r[k].x2()>14.1) 
+							&& m_fix_max)) {
+				r_corr = 0.0;
+				x_r[k].set_error(0.01);
+			}
+			x_r[k].set_x2(x_r[k].x2()-r_corr);
+
+		}
+
+	// force monotony //
+		if (m_force_monotony) {
+			for (unsigned int k=0; k<nb_points; k++) {
+				if (x_r[k].x2()>x_r[k+1].x2()) {
+					x_r[k+1].set_x2(x_r[k].x2());
+				}
+			}
+		}
+
+	// create the new r-t relationship //
+		fitter.fit_parameters(x_r, 1, nb_points+1, &chebyshev);
+		rt_param[0] = rt_Chebyshev->tLower();
+		rt_param[1] = rt_Chebyshev->tUpper();
+		for (unsigned int k=0; k<rt_Chebyshev->numberOfRtParameters(); 
+									k++) {
+			rt_param[k+2] = fitter.coefficients()[k];
+		}
+
+		if (m_rt_new==0) {
+			delete m_rt_new;
+		}
+		m_rt_new = new RtChebyshev(rt_param);
+		m_rt_new->SetTmaxDiff(m_rt->GetTmaxDiff());
+
+    // parabolic extrapolation //
+		/*
+       if (m_do_parabolic_extrapolation) {
+	    RtRelationLookUp tmprt(performParabolicExtrapolation(false, true,
+                                                                *m_rt_new));
+//         vector<SamplePoint> add_fit_point;
+//         if (m_fix_min) {
+//             add_fit_point.push_back(
+//                                 SamplePoint(m_rt_new->tLower(), 0.0, 1.0));
+//         }
+//         RtRelationLookUp tmp_rt(rt_extrapolator.getRtWithParabolicExtrapolation(
+//                                 *m_rt_new,
+//                                 m_rt_new->radius(m_rt_new->tLower())+1.0,
+//                                 m_rt_new->radius(m_rt_new->tLower())+3.0,
+//                                 m_rt_new->radius(m_rt_new->tLower()),
+//                                 add_fit_point));
+//         add_fit_point.clear();
+//         if (m_fix_max) {
+//             add_fit_point.push_back(
+//                                 SamplePoint(m_rt_new->tUpper(), m_r_max, 1.0));
+//         }
+//         RtRelationLookUp tmprt(rt_extrapolator.getRtWithParabolicExtrapolation(
+//                                 tmp_rt,
+//                                 m_rt_new->radius(m_rt_new->tUpper())-1.0,
+//                                 m_rt_new->radius(m_rt_new->tUpper())-3.0,
+//                                 m_rt_new->radius(m_rt_new->tUpper()),
+//                                 add_fit_point));
+
+        if (m_rt_new!=0) {
+			delete m_rt_new;
+		}
+
+		vector<SamplePoint> t_r(nb_points+1);
+		for (unsigned int k=0; k<nb_points+1; k++) {
+			t_r[k].set_x1(t_from_r(k*step));
+			t_r[k].set_x2(tmprt.radius(k*step));
+			t_r[k].set_error(1.0);
+        }
+        m_rt_new = new RtChebyshev(rt_from_points.getRtChebyshev(t_r,
+                                        rt_Chebyshev->numberOfRtParameters()));
+       }
+*/
+	}
+
+// input-rt is of type RtRelationLookUp //
+	if (rt_LookUp!=0) {
+
+		rt_param=rt_LookUp->parameters();
+		unsigned int min_k(2), max_k(rt_param.size());
+		if(m_fix_min)
+			{
+			min_k=3;
+			}
+		if(m_fix_max)
+			{
+			max_k = rt_param.size()-1;
+			}
+		for (unsigned int k=min_k; k<max_k; k++) {
+			x = (rt_param[k] - 7.6)/7.6;
+			r_corr = m_alpha[0];
+			for (unsigned int l=1; l<m_order; l++) {
+				r_corr = r_corr+m_alpha[l]*
+						m_base_function->value(l, x);
+			}
+			rt_param[k] = rt_param[k]-r_corr;
+			if (m_force_monotony && k>2) {
+				if (rt_param[k]<rt_param[k-1]) {
+					rt_param[k]=rt_param[k-1];
+				}
+			}
+		}
+
+		if (m_rt_new==0) {
+			delete m_rt_new;
+		}
+		m_rt_new = new RtRelationLookUp(rt_param);
+		m_rt_new->SetTmaxDiff(m_rt->GetTmaxDiff());
+    // parabolic extrapolation //
+/*
+       if (m_do_parabolic_extrapolation) {
+	    RtRelationLookUp tmprt(performParabolicExtrapolation(false, true,
+                                                                *m_rt_new));
+// 	    vector<SamplePoint> add_fit_point;
+// //         if (m_fix_min) {
+// //             add_fit_point.push_back(
+// //                                 SamplePoint(m_rt_new->tLower(), 0.0, 1.0));
+// //         }
+// // //         RtRelationLookUp tmp_rt(rt_extrapolator.getRtWithParabolicExtrapolation(
+// // //                                 *m_rt_new,
+// // //                                 m_rt_new->radius(m_rt_new->tLower())+1.0,
+// // //                                 m_rt_new->radius(m_rt_new->tLower())+3.0,
+// // //                                 m_rt_new->radius(m_rt_new->tLower()),
+// // //                                 add_fit_point));
+// //         RtRelationLookUp tmp_rt(rt_extrapolator.getRtWithParabolicExtrapolation(
+// //                                 *m_rt_new,
+// //                                 1.2,
+// //                                 3.0,
+// //                                 0.0,
+// //                                 add_fit_point));
+// //         add_fit_point.clear();
+//         if (m_fix_max) {
+//             add_fit_point.push_back(
+//                                 SamplePoint(m_rt_new->tUpper(), m_r_max, 1.0));
+//         }
+//         RtRelationLookUp tmprt(rt_extrapolator.getRtWithParabolicExtrapolation(
+//                                 *m_rt_new,
+//                                 m_r_max-1.0,
+//                                 m_r_max-3.0,
+//                                 m_r_max,
+//                                 add_fit_point));
+
+        if (m_rt_new!=0) {
+			delete m_rt_new;
+		}
+        m_rt_new = new RtRelationLookUp(tmprt);
+       }
+*/
+	}
+
+/////////////////////////////////////////////////////////
+// DETERMINE THE r-t QUALITY AND CHECK FOR CONVERGENCE //
+/////////////////////////////////////////////////////////
+
+// estimate r-t accuracy //
+	m_rt_accuracy = 0.0;
+//	double m_rt_accuracy_diff = 0.0; 
+	double r_corr_max =0.0;
+	
+	for (unsigned int k=0; k<100; k++) {
+		r_corr = m_alpha[0];
+		for (unsigned int l=1; l<m_order; l++) {
+			r_corr = r_corr+m_alpha[l]*
+					m_base_function->value(l, -1.0+0.01*k);
+		}
+		if (fabs(r_corr) > r_corr_max){
+				r_corr_max = fabs(r_corr);
+		}
+		m_rt_accuracy = m_rt_accuracy+r_corr*r_corr;
+	}
+	m_rt_accuracy = sqrt(0.01*m_rt_accuracy);
+//	m_rt_accuracy_diff = m_rt_accuracy_previous - m_rt_accuracy;
+	m_rt_accuracy_previous = m_rt_accuracy;
+	
+// convergence? //
+	m_chi2 = m_chi2/static_cast<double>(m_nb_segments_used);
+	if ( (m_chi2<=m_chi2_previous || fabs(m_chi2-m_chi2_previous)>0.01) 
+	     || (fabs(m_rt_accuracy)>0.001
+	     &&	m_iteration<m_max_it)) {
+		m_status = 0; // no convergence yet
+	} else {
+		m_status = 1;
+	}
+	m_chi2_previous = m_chi2;
+
+// reliabilty of convergence //
+	if (m_status!=0) {
+		if (m_nb_segments_used<0.5*m_nb_segments) {
+			m_status = 2;
+		}
+	}
+	
+//////////////////////////////////////
+// Set new multilayer rt-difference //
+//////////////////////////////////////
+	if(m_iteration>0 && m_do_multilayer_rt_scale)
+		m_multilayer_rt_difference->DoFit(m_rt_new, &seg);
+	else
+		{
+//		std::cout<<"No update in first iteration!"<<std::endl;
+		m_multilayer_rt_difference->DoFit();
+		}
+		
+//////////////////////////////////////////////////
+// STORE THE RESULTS IN THE RtCalibrationOutput //
+//////////////////////////////////////////////////
+
+	m_iteration = m_iteration+1;
+
+	if (m_output!=0) {
+		delete m_output;
+	}
+	m_output = new RtCalibrationOutput(m_rt_new, 
+			new RtFullInfo("RtCalibrationCurved", m_iteration,
+				m_nb_segments_used, 0.0, 0.0, 0.0, 0.0));
+	
+
+
+	return true;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::
+//:: METHOD converged ::
+//::::::::::::::::::::::
+
+bool RtCalibrationCurved::converged(void) const {
+
+	return (m_status>0);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD getResults ::
+//:::::::::::::::::::::::
+
+const IMdtCalibrationOutput * RtCalibrationCurved::getResults(void) const {
+
+	return static_cast<const IMdtCalibrationOutput *>(m_output);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: METHOD init ::
+//:::::::::::::::::
+
+void RtCalibrationCurved::init(const double & rt_accuracy,
+				const unsigned int & func_type,
+                const unsigned int & ord,
+                const bool & fix_min, const bool & fix_max,
+                const int & max_it,
+                bool do_parabolic_extrapolation,
+		        bool do_smoothing,
+			bool do_multilayer_rt_scale) {
+
+/////////////////////////////
+// RESET PRIVATE VARIABLES //
+/////////////////////////////
+        m_rt=NULL;
+	m_r_max = 15.0*CLHEP::mm;
+	m_control_histograms = false;
+		m_tfile = 0;
+		m_cut_evolution = 0;
+		m_nb_segment_hits = 0;
+		m_pull_initial = 0;
+		m_pull_final = 0;
+    	m_residuals_initial = 0;
+    	m_residuals_final = 0;
+	m_nb_segments = 0;
+	m_nb_segments_used = 0;
+	m_iteration = 0;
+	m_multilayer[0] = false;
+	m_multilayer[1] = false;
+	m_status = 0;
+	m_rt_accuracy = fabs(rt_accuracy);
+	m_chi2_previous = 1.0e99; // large value to force at least two rounds
+	m_chi2 = 0.0;
+	m_order = ord;
+	m_fix_min = fix_min;
+	m_fix_max = fix_max;
+	m_max_it = abs(max_it);
+	m_do_multilayer_rt_scale=do_multilayer_rt_scale;
+	m_multilayer_rt_difference = new MultilayerRtDifference(10000);
+    
+    m_tracker = new CurvedPatRec;
+
+	if (m_order==0) {
+		cerr << "\n"
+		        << "Class RtCalibrationCurved, method init: ERROR!"
+			<< "\nOrder of the correction polynomial must be >0!\n";
+		exit(1);
+	}
+	
+	m_t_length = 1000.0;
+	m_t_mean = 500.0;
+		// default values, correct values will be set when the input r-t
+		// has been given
+
+	m_rt_new = 0;
+	m_output = 0;
+
+	m_U = vector<CLHEP::HepVector>(m_order);
+	m_U_weighted = vector<CLHEP::HepVector>(m_order);
+    m_A = CLHEP::HepSymMatrix(m_order, 0);
+	m_b = CLHEP::HepVector(m_order, 0);
+	m_alpha = CLHEP::HepVector(m_order, 0);
+
+// correction function
+	if (func_type<1 || func_type>3) {
+		m_base_function = 0;
+		cerr << "\n"
+			<< "Class RtCalibrationCurved, method init: "
+			<< "ERROR!\n"
+			<< "Illegal correction function type!\n";
+		exit(1);
+	}
+	switch(func_type) {
+		case 1:
+			m_base_function = new LegendrePolynomial;
+			break;
+		case 2:
+			m_base_function = new ChebyshevPolynomial;
+			break;
+		case 3:
+			if (m_order<2) {
+				cerr << "\n"
+					<< "Class RtCalibrationCurved, "
+					<< "method init: ERROR!\n"
+					<< "Order must be >2 for polygons! "
+					<< "It is set to " << m_order
+					<< "by the user.\n";
+				exit(1);
+			}
+			vector<double> x(m_order);
+			double bin_width=2.0/static_cast<double>(m_order-1);
+			for (unsigned int k=0; k<m_order; k++) {
+				x[k] = -1+k*bin_width;
+			}
+			m_base_function = new PolygonBase(x);
+			break;
+	}
+
+// monotony of r(t) //
+	m_force_monotony = false;
+
+// parabolic extrapolations //
+    m_do_parabolic_extrapolation = do_parabolic_extrapolation;
+
+// smoothing //
+	m_do_smoothing = do_smoothing;
+
+// Legendre polynomials and tracking objects //
+    m_Legendre = Legendre_polynomial::get_Legendre_polynomial();
+    m_M_track = CLHEP::HepSymMatrix(3);
+    m_M_track_inverse = CLHEP::HepSymMatrix(3);
+
+
+   
+	return;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::
+//:: METHOD t_from_r ::
+//:::::::::::::::::::::
+
+double RtCalibrationCurved::t_from_r(const double & r) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	double precision(0.001); // spatial precision of the inversion 
+	double t_max(0.5*(m_t_length+2.0*m_t_mean)); // upper time search limit
+	double t_min(t_max-m_t_length); // lower time search limit
+
+/////////////////////////////////////////////
+// SEARCH FOR THE CORRESPONDING DRIFT TIME //
+/////////////////////////////////////////////
+
+	while (t_max-t_min>0.1 &&
+			fabs(m_rt->radius(0.5*(t_min+t_max))-r)>precision) {
+
+		if (m_rt->radius(0.5*(t_min+t_max))>r) {
+			t_max = 0.5*(t_min+t_max);
+		} else {
+			t_min = 0.5*(t_min+t_max);
+		}
+
+	}
+
+	return 0.5*(t_min+t_max);
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::
+//:: METHOD display_segment ::
+//::::::::::::::::::::::::::::
+
+void RtCalibrationCurved::display_segment(MuonCalibSegment * segment,
+                 std::ofstream & outfile, const CurvedLine * curved_segment) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	double y_min, y_max, z_min, z_max; // minimum and maximum y and z
+					   // coordinates
+	Amg::Vector3D null(0.0, 0.0, 0.0); // auxiliary null vector
+
+/////////////////////////
+// DISPLAY THE SEGMENT //
+/////////////////////////
+
+// minimum and maximum coordinates //
+	y_min = (segment->mdtHOT()[0])->localPosition().y();
+	y_max = y_min;
+	z_min = (segment->mdtHOT()[0])->localPosition().z();
+	z_max = z_min;
+	for (unsigned int k=1; k<segment->mdtHitsOnTrack(); k++) {
+		if ((segment->mdtHOT()[k])->localPosition().y()<y_min) {
+			y_min = (segment->mdtHOT()[k])->localPosition().y();
+		}
+		if ((segment->mdtHOT()[k])->localPosition().y()>y_max) {
+			y_max = (segment->mdtHOT()[k])->localPosition().y();
+		}
+		if ((segment->mdtHOT()[k])->localPosition().z()<z_min) {
+			z_min = (segment->mdtHOT()[k])->localPosition().z();
+		}
+		if ((segment->mdtHOT()[k])->localPosition().z()>z_max) {
+			z_max = (segment->mdtHOT()[k])->localPosition().z();
+		}
+	}
+	for (unsigned int k=0; k<segment->mdtCloseHits(); k++) {
+		if ((segment->mdtClose()[k])->localPosition().y()<y_min) {
+			y_min = (segment->mdtClose()[k])->localPosition().y();
+		}
+		if ((segment->mdtClose()[k])->localPosition().y()>y_max) {
+			y_max = (segment->mdtClose()[k])->localPosition().y();
+		}
+		if ((segment->mdtClose()[k])->localPosition().z()<z_min) {
+			z_min = (segment->mdtClose()[k])->localPosition().z();
+		}
+		if ((segment->mdtClose()[k])->localPosition().z()>z_max) {
+			z_max = (segment->mdtClose()[k])->localPosition().z();
+		}
+	}
+
+// write out the coordinate system //
+	if (y_max-y_min>z_max-z_min) {
+		outfile << "NULL " << y_min-30.0 << " " << y_max+30.0 << " "
+			<< 0.5*(z_min+z_max)-0.5*(y_max-y_min)-30.0 << " " 
+			<< 0.5*(z_min+z_max)+0.5*(y_max-y_min)+30.0 << "\n";
+	} else {
+		outfile << "NULL " << 0.5*(y_min+y_max)-0.5*(z_max-z_min)-30.0 
+			<< " " << 0.5*(y_min+y_max)+0.5*(z_max-z_min)+30.0 << " "
+			<< z_min-30.0 << " " 
+			<< z_max+30.0 << "\n";
+	}
+
+// write out the hits on track //
+	for (unsigned int k=0; k<segment->mdtHitsOnTrack(); k++) {
+
+   // draw a circle for the tube //
+		outfile << "SET PLCI 1\n"
+			<< "ARC " << (segment->mdtHOT()[k])->localPosition().y()
+			<< " " << (segment->mdtHOT()[k])->localPosition().z()
+			<< " 15.0\n";
+
+   // draw a drift circle //
+		outfile << "SET PLCI 3\n"
+			<< "ARC " << (segment->mdtHOT()[k])->localPosition().y()
+			<< " " << (segment->mdtHOT()[k])->localPosition().z()
+			<< " " << (segment->mdtHOT()[k])->driftRadius()
+			<< "\n";
+
+	}
+
+// write out the close hits //
+	for (unsigned int k=0; k<segment->mdtCloseHits(); k++) {
+
+   // draw a circle for the tube //
+		outfile << "SET PLCI 1\n"
+			<< "ARC " << (segment->mdtClose()[k])->localPosition().y()
+			<< " " << (segment->mdtClose()[k])->localPosition().z()
+			<< " 15.0\n";
+
+   // draw a drift circle //
+		outfile << "SET PLCI 2\n"
+			<< "ARC " << (segment->mdtClose()[k])->localPosition().y()
+			<< " " << (segment->mdtClose()[k])->localPosition().z()
+			<< " " << (segment->mdtClose()[k])->driftRadius()
+			<< "\n";
+
+	}
+
+// write out the reconstructed track //
+// a straight line is drawn by default //
+	if (curved_segment==0) {
+        MTStraightLine aux_track(segment->position(), segment->direction(),
+								null, null);
+	    outfile << "SET PLCI 4\n"
+		    << "LINE " << aux_track.m_x2()*(z_min-30.0)+aux_track.b_x2() 
+		    << " " << z_min-30.0
+		    << " " << aux_track.m_x2()*(z_max+30.0)+aux_track.b_x2() 
+		    << " " << z_max+30.0 << "\n";
+    }
+
+// a curved segment is drawn on demand //
+    if (curved_segment!=0) {
+        double step_size((60.0+z_max-z_min)/50.0);
+        for (double aux_z=z_min; aux_z<=z_max; aux_z=aux_z+step_size) {
+	        outfile << "SET PLCI 4\n"
+		        << "LINE " <<  curved_segment->getPointOnLine(aux_z).y()
+		        << " " << aux_z
+		        << " " << curved_segment->getPointOnLine(aux_z+step_size).y()
+		        << " " << aux_z+step_size << "\n";
+        }
+    }
+
+// add a wait statement //
+	outfile << "WAIT\n";
+
+	return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::::::::::::
+//:: METHOD performParabolicExtrapolation ::
+//::::::::::::::::::::::::::::::::::::::::::
+
+RtRelationLookUp * RtCalibrationCurved::performParabolicExtrapolation(
+                                                const bool & min,
+                                                const bool & max,
+                                                const IRtRelation & in_rt) {
+
+///////////////
+// VARIABLES //
+///////////////
+
+    RtParabolicExtrapolation rt_extrapolator; // r-t extrapolator
+    RtRelationLookUp *rt_low(0), *rt_high(0); // pointers to the r-t
+                                              // relationships after
+                                              // extrapolation
+	vector<SamplePoint> add_fit_point; // additional r-t points used if r(0) or
+                                       // r(t_max) is fixed.
+
+////////////////////////////////
+// EXTRAPOLATE TO LARGE RADII //
+////////////////////////////////
+
+    if (max) {
+        add_fit_point.clear();
+        if (m_fix_max) {
+            add_fit_point.push_back(SamplePoint(in_rt.tUpper(),
+                                        in_rt.radius(in_rt.tUpper()), 1.0));
+        }
+	if ( in_rt.radius(in_rt.tUpper()) < 16.0 ){
+	  rt_high = new RtRelationLookUp(
+                    rt_extrapolator.getRtWithParabolicExtrapolation(in_rt,
+                        in_rt.radius(in_rt.tUpper())-3.0,
+                        in_rt.radius(in_rt.tUpper())-1.0,
+                        in_rt.radius(in_rt.tUpper()),
+                        add_fit_point));
+	}
+	else{
+	  rt_high = new RtRelationLookUp(
+                    rt_extrapolator.getRtWithParabolicExtrapolation(in_rt,
+			13.,15.,16.,
+                        add_fit_point));
+ 	}
+    }
+
+////////////////////////////////
+// EXTRAPOLATE TO SMALL RADII //
+////////////////////////////////
+
+    if (min) {
+        add_fit_point.clear();
+        if (m_fix_min) {
+            add_fit_point.push_back(
+                                SamplePoint(m_rt_new->tLower(), 0.0, 1.0));
+        }
+        if (m_fix_max) {
+            rt_low = new RtRelationLookUp(
+                    rt_extrapolator.getRtWithParabolicExtrapolation(*rt_high,
+                        1.0,
+                        3.0,
+                        0.0,
+                        add_fit_point));
+        } else {
+            rt_low = new RtRelationLookUp(
+                    rt_extrapolator.getRtWithParabolicExtrapolation(in_rt,
+                        1.0,
+                        3.0,
+                        0.0,
+                        add_fit_point));
+        }
+    }
+
+////////////////////
+// RETURN RESULTS //
+////////////////////
+
+    if (min && max) {
+        if(rt_high) delete rt_high;
+	if(in_rt.HasTmaxDiff())
+		{
+		rt_low->SetTmaxDiff(in_rt.GetTmaxDiff());
+		}
+        return rt_low;
+    }
+    if (min) {
+        if(rt_high) delete rt_high;
+	if(in_rt.HasTmaxDiff())
+		{
+		rt_low->SetTmaxDiff(in_rt.GetTmaxDiff());
+		}
+        return rt_low;
+    }
+    if(rt_low) delete rt_low;
+	if(in_rt.HasTmaxDiff())
+		{
+		rt_high->SetTmaxDiff(in_rt.GetTmaxDiff());
+		}
+    return rt_high;
+
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtCalibrationIntegration.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtCalibrationIntegration.cxx
new file mode 100644
index 0000000000000..7955289a61546
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtCalibrationIntegration.cxx
@@ -0,0 +1,416 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 02.02.2007, AUTHOR: OLIVER KORTNER
+// 12.11.2008, JOERG v. LOEBEN: 
+//               line 100: add missing if statement for close hits
+//               line 140-240: change bining and adjust start/end points
+//               line 252: change to r-t chebychev. this method does interpolating 
+//                         the samplepoints better. the autocalibration methods are
+//                         working more accurate.
+//               line 256: implement parabolic extrapolation for large driftradii.
+// 11.02.2010,   include r(t_max)=r_max as addtional fit-point in extrapolation
+//                         
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: IMPLEMENTATION OF METHODS DEFINED IN THE CLASS RtCalibrationIntegration ::
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+// standard C++ //
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+
+// MuonCalib //
+#include "MdtCalibRt/RtCalibrationIntegration.h"
+#include "MdtCalibT0/T0MTHistos.h"
+#include "MdtCalibData/RtFromPoints.h"
+#include "MdtCalibRt/RtParabolicExtrapolation.h"
+
+//root//
+#include "TF1.h"
+#include "TList.h"
+//::::::::::::::::::::::::
+//:: NAMESPACE SETTINGS ::
+//::::::::::::::::::::::::
+
+using namespace std;
+using namespace MuonCalib;
+
+inline Double_t slope_function_C(Double_t *x, Double_t *par)
+	{
+	Double_t &t(x[0]);
+	Double_t &a(par[0]),
+	         &b(par[1]),
+		 &t_0(par[2]),
+		 &back(par[3]);
+	return back + exp(a+b*(t-t_0));
+	}
+
+inline void update_parameter_on_mttmax(TH1 * h, TF1 *f, const float &b, const float & T, const T0MTSettingsTMax &tmax_settings)
+	{
+	Double_t rmin, rmax;
+	f->GetRange(rmin, rmax);
+	TF1 *slope_function=new TF1("slope_function", slope_function_C, rmin, rmin+tmax_settings.WidthAB(), 4);
+	slope_function->SetParameter(0, f->GetParameter(T0MTHistos::TMAX_PAR_NR_A));
+	slope_function->FixParameter(1, b);
+	slope_function->FixParameter(2, f->GetParameter(T0MTHistos::TMAX_PAR_NR_T0));
+	slope_function->FixParameter(3, f->GetParameter(T0MTHistos::TMAX_PAR_NR_BACK));
+	h->Fit("slope_function", "R+", "");
+	f->FixParameter(T0MTHistos::TMAX_PAR_NR_A, slope_function->GetParameter(0));
+	f->FixParameter(T0MTHistos::TMAX_PAR_NR_B, b);
+	f->FixParameter(T0MTHistos::TMAX_PAR_NR_T, T);
+//	std::cout<<"LLllLL "<<slope_function->GetParameter(0)<<" "<<b<<std::endl;
+//	std::cout<<"LLllLL "<<f->GetParameter(T0MTHistos::TMAX_PAR_NR_A)<<" "<<f->GetParameter(T0MTHistos::TMAX_PAR_NR_B)<<std::endl;
+	
+	}
+
+//*****************************************************************************
+
+//:::::::::::::::::
+//:: METHOD init ::
+//:::::::::::::::::
+
+void RtCalibrationIntegration::init(bool close_hits,
+				    double r_max,
+				    double lower_extrapolation_radius,
+				    double upper_extrapolation_radius,
+				    bool add_tmax_difference){
+
+  m_close_hits = close_hits;
+  m_rt = 0;
+  m_r_max = r_max;
+  m_lower_extrapolation_radius = lower_extrapolation_radius;
+  m_upper_extrapolation_radius = upper_extrapolation_radius;
+  m_output = 0;
+  m_nb_hits_used = 0;
+  m_nb_segments_used = 0;
+  m_add_tmax_difference = add_tmax_difference;
+  return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::::::
+//:: METHOD number_of_hits_used ::
+//::::::::::::::::::::::::::::::::
+
+unsigned int RtCalibrationIntegration::number_of_hits_used(void) const {
+
+  return m_nb_hits_used;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::::
+//:: METHOD analyseSegments ::
+//::::::::::::::::::::::::::::
+
+const IMdtCalibrationOutput 
+*RtCalibrationIntegration::analyseSegments(const std::vector<MuonCalibSegment*> & seg) {
+
+  for (unsigned int k=0; k<seg.size(); k++) {
+    handleSegment(*seg[k]);
+  }
+  m_nb_segments_used = seg.size();
+  analyse();
+
+  return getResults();
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::::::
+//:: METHOD handleSegment ::
+//::::::::::::::::::::::::::
+
+bool RtCalibrationIntegration::handleSegment(MuonCalibSegment & seg) {
+
+  ///////////////////////////////////////////////////////
+  // LOOP OVER THE HITS OF THE SEGMENTS AND STORE THEM //
+  ///////////////////////////////////////////////////////
+
+  // start with hits on the segment //
+  for (unsigned int k=0; k<seg.mdtHitsOnTrack(); k++) {
+    if(seg.mdtHOT()[k]->driftTime() <-8e8) continue;
+    m_t_drift.push_back(std::pair<double, bool>(seg.mdtHOT()[k]->driftTime(), seg.mdtHOT()[k]->identify().mdtMultilayer()==2));
+  }
+
+
+  // continue with close hits if requested //
+  if (m_close_hits==true){
+    for (unsigned int k=0; k<seg.mdtCloseHits(); k++) {
+    m_t_drift.push_back(std::pair<double, bool>(seg.mdtHOT()[k]->driftTime(), seg.mdtHOT()[k]->identify().mdtMultilayer()==2));
+   }
+  }
+	
+  return true;
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::
+//:: METHOD setInput ::
+//:::::::::::::::::::::
+
+void 
+RtCalibrationIntegration::setInput(const IMdtCalibrationOutput * /*rt_input*/) {
+
+  return;
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::
+//:: METHOD analyse ::
+//::::::::::::::::::::
+
+bool RtCalibrationIntegration::analyse(void) {
+
+  ///////////////
+  // VARIABLES //
+  ///////////////
+
+  T0MTSettings t0_setting; // settings of the MT t0 fitter
+  t0_setting.AddFitfun()=true;
+//  t0_setting.DrawDebugGraphs()=true;
+  t0_setting.T0Settings()->ScrambleThreshold()=2;
+  t0_setting.T0Settings()->SlicingThreshold()=3;
+  t0_setting.TMaxSettings()->DistAB()+=50;
+  T0MTHistos drift_time_spec; // drift time spectrum used in the t0 and
+  // the tmax fit
+  T0MTHistos drift_time_spec_ml[2];
+  
+  
+  double t0, tmax; // t0 and tmax	
+  int k_min(-1);//, k_max(-1); // first and last drift-time entry to be
+  // used in the integration procedure
+  unsigned int nb_bins(100); // number of integration bins
+  double bin_content; // number of entries per bin
+  vector<SamplePoint> point(nb_bins+1); // (t, r) points
+  double radius(0.0); // r(t)
+  double scf; // scale factor (r_max/number of used hits)
+  RtFromPoints rt_from_points; // r-t converter
+
+  ///////////////////////////////////////////////////////////////////////////
+  // STOP HERE, IF THERE ARE NOT ENOUGH ENTRIES IN THE DRIFT-TIME SPECTRUM //
+  ///////////////////////////////////////////////////////////////////////////
+
+  if (m_t_drift.size()<2000) {
+    cerr << endl
+	 << "Class RtCalibrationIntegration, method analyse: "
+	 << "FAILURE!\n"
+	 << "Less than 2000 drift-time entries! No r-t "
+	 << "relationship will be determined!\n";
+    return false;
+  }
+
+  ////////////////////////
+  // INTEGRATION METHOD //
+  ////////////////////////
+
+  // sort the hits in ascending order of their drift times //
+  sort(m_t_drift.begin(), m_t_drift.end());
+
+  // perform a t0 and tmax fit //
+  // fill the histogram with the drift-time spectrum //
+  int n_bins=static_cast<int>(32 * (200.0 + m_t_drift[m_t_drift.size() - 1].first - m_t_drift[0].first) / 25.0);
+  float min_t=m_t_drift[0].first - 100.0;
+  float max_t=m_t_drift[m_t_drift.size() - 1].first + 100.0;
+  TH1F *tspec= new TH1F("tspec", "DRIFT-TIME SPECTRUM", n_bins, min_t, max_t);
+  TH1F *tspec_ml[2];
+  tspec_ml[0]=new TH1F("tspec_ml0", "DRIFT-TIME SPECTRUM ML 0",  n_bins, min_t, max_t);
+  tspec_ml[1]=new TH1F("tspec_ml1", "DRIFT-TIME SPECTRUM ML 1",  n_bins, min_t, max_t);
+  
+			
+  for (unsigned int k=0; k<m_t_drift.size(); k++) {
+    tspec->Fill(m_t_drift[k].first, 1.0);
+    tspec_ml[static_cast<unsigned int>(m_t_drift[k].second)]->Fill(m_t_drift[k].first, 1.0);
+  }
+  drift_time_spec.SetTSpec(1, tspec, &t0_setting, false);
+  drift_time_spec_ml[0].SetTSpec(2, tspec_ml[0], &t0_setting, false);
+  drift_time_spec_ml[1].SetTSpec(3, tspec_ml[1], &t0_setting, false);
+
+  // t0 and tmax fits //
+ 
+  if (!drift_time_spec.FitT0() || !drift_time_spec.T0Ok()) {
+    cerr << endl
+	 << "Class RtCalibrationIntegration, method analyse: "
+	 << "FAILURE!\n"
+	 << "t0 fit not successful, no r-t relationship will be "
+	 << "calculated!\n";
+    return false;
+  }
+  t0 = drift_time_spec.GetT0Function()->GetParameter(
+						     T0MTHistos::T0_PAR_NR_T0);
+ 
+  if (!drift_time_spec.FitTmax() || !drift_time_spec.TmaxOk()) {
+    cerr << endl
+	 << "Class RtCalibrationIntegration, method analyse: "
+	 << "FAILURE!\n"
+	 << "tmax fit not successful, no r-t relationship will "
+	 << "be calculated!\n";
+    return false;
+  }
+  tmax = drift_time_spec.GetTMaxFunction()->GetParameter(
+							 T0MTHistos::TMAX_PAR_NR_TMAX)
+    +2.0*drift_time_spec.GetTMaxFunction()->GetParameter(
+							 T0MTHistos::TMAX_PAR_NR_T);
+
+  // determine (t,r) points by integration //
+  m_nb_hits_used = 0;
+  for (unsigned int k=0; k<m_t_drift.size(); k++) {
+    if (m_t_drift[k].first>=t0 && m_t_drift[k].first<=tmax) {
+      m_nb_hits_used++;
+    }
+    if (k_min<0 && m_t_drift[k].first>=t0) {
+      k_min = k;
+    }
+  }
+  //k_max = k_min+m_nb_hits_used-1;
+
+  bin_content = static_cast<double>(m_nb_hits_used)/static_cast<double>(nb_bins);
+
+  scf = m_r_max/static_cast<double>(m_nb_hits_used);
+
+  point[0].set_x1(t0);
+  point[0].set_x2(0.0);
+  point[0].set_error(0.1); // give a higher weight to the end point in
+  
+  // the final fit
+  for (unsigned int k=1; k<nb_bins; k++) {
+    radius = radius+scf*bin_content;
+    point[k].set_x1(m_t_drift[k_min+static_cast<int>(bin_content)*(k)].first );
+    point[k].set_x2(radius);
+    point[k].set_error(1.0);
+  }
+	
+  point[nb_bins].set_x1(tmax);
+  point[nb_bins].set_x2(m_r_max);
+  point[nb_bins].set_error(1.);
+
+
+  /*//dump points
+    for(unsigned int i=0; i<point.size(); i++)
+    {
+    std::cout<<i<<" "<<point[i].x1()<<" "<<point[i].x2()<<" "<<point[i].error()<<std::endl;
+    }*/
+
+  // get the r-t relationship //
+  m_rt = new RtChebyshev(rt_from_points.getRtChebyshev(point, 15));
+  //	m_rt = new RtRelationLookUp(rt_from_points.getRtRelationLookUp(point));
+
+  ///////////////////////////////////////////////////
+  // PARABOLIC EXTRAPOLATION FOR LARGE DRIFT RADII //
+  ///////////////////////////////////////////////////
+  vector<SamplePoint> add_fit_point; // additional r-t points for r(t_max)
+  add_fit_point.push_back(SamplePoint(tmax,m_r_max, 1.0));
+  RtParabolicExtrapolation rt_extrapolated;
+  RtRelationLookUp tmp_rt( rt_extrapolated.getRtWithParabolicExtrapolation(
+						  *m_rt,
+						  m_lower_extrapolation_radius,
+						  m_upper_extrapolation_radius,
+						  m_r_max,
+						  add_fit_point));
+  IRtRelation *rt_new(0);
+  rt_new = new RtRelationLookUp(tmp_rt);
+
+
+  //////////////////////////////////////////////////
+  // Get length difference between multilayers    //
+  //////////////////////////////////////////////////
+  
+  if(tspec_ml[0]->GetEntries()>=10000 && tspec_ml[0]->GetEntries()>10000)
+  	{
+	bool fit_ok(true);
+	float b[2];
+	float tmax[2];
+	float T[2];
+	for(unsigned int i=0; i<2; i++)
+		{
+		if(!drift_time_spec_ml[i].FitT0())
+			{
+			fit_ok=false;
+			break;
+			}
+		if(!drift_time_spec_ml[i].FitTmax())
+			{
+			fit_ok=false;
+			break;
+			}
+			b[i] = drift_time_spec_ml[i].GetTMaxFunction()->GetParameter(T0MTHistos::TMAX_PAR_NR_B);
+			tmax[i] = drift_time_spec_ml[i].GetTMaxFunction()->GetParameter(T0MTHistos::TMAX_PAR_NR_TMAX) - drift_time_spec_ml[i].GetT0Function()->GetParameter(T0MTHistos::T0_PAR_NR_T0);
+			T[i] = drift_time_spec_ml[i].GetTMaxFunction()->GetParameter(T0MTHistos::TMAX_PAR_NR_T);
+		}
+	if(fit_ok)
+		{
+		int refit=static_cast<int>((b[1] + 1.33717e-03)>(b[0] + 1.33717e-03));
+		int norefit=static_cast<bool>(refit)?0:1;
+//		std::cout<<"HHhhHH "<<refit<<" "<<norefit<<std::endl;
+//		std::cout<<"HHhhHH "<<b[norefit]<<std::endl;
+		TF1 *fixfun=drift_time_spec_ml[refit].GetTMaxFunctionNC();
+		fixfun->FixParameter(T0MTHistos::TMAX_PAR_NR_B, b[norefit]);
+		update_parameter_on_mttmax(drift_time_spec_ml[refit].GetTSpec(), fixfun, b[norefit], T[norefit],*t0_setting.TMaxSettings());
+		TList *l=drift_time_spec_ml[refit].GetTSpec()->GetListOfFunctions();
+		l->Remove(l->FindObject("mt_tmax_fermi"));
+		fit_ok=drift_time_spec_ml[refit].FitTmax();
+		tmax[refit] = drift_time_spec_ml[refit].GetTMaxFunction()->GetParameter(T0MTHistos::TMAX_PAR_NR_TMAX) - drift_time_spec_ml[refit].GetT0Function()->GetParameter(T0MTHistos::T0_PAR_NR_T0);
+		}
+		
+	if(fit_ok && m_add_tmax_difference)
+		rt_new->SetTmaxDiff(tmax[0] - tmax[1]);
+	}
+
+
+  //////////////////////////////////////////////////
+  // STORE THE RESULTS IN THE RtCalibrationOutput //
+  //////////////////////////////////////////////////
+
+  if (m_output!=0) {
+    delete m_output;
+  }
+  m_output = new RtCalibrationOutput(rt_new, 
+				     new RtFullInfo("RtCalibrationIntegration", 1,
+						    m_nb_segments_used, 0.0, 0.0, 0.0, 0.0));
+
+
+  return true;
+
+
+}
+
+//*****************************************************************************
+
+//::::::::::::::::::::::
+//:: METHOD converged ::
+//::::::::::::::::::::::
+
+bool RtCalibrationIntegration::converged(void) const {
+
+  return (m_output!=0);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::
+//:: METHOD getResults ::
+//:::::::::::::::::::::::
+
+const IMdtCalibrationOutput * RtCalibrationIntegration::getResults(void) const {
+
+  return static_cast<const IMdtCalibrationOutput *>(m_output);
+
+}
diff --git a/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtParabolicExtrapolation.cxx b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtParabolicExtrapolation.cxx
new file mode 100644
index 0000000000000..90ab4b98359f3
--- /dev/null
+++ b/MuonSpectrometer/MuonCalib/MdtCalib/MdtCalibRt/src/RtParabolicExtrapolation.cxx
@@ -0,0 +1,248 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// 10.11.2008, AUTHOR: OLIVER KORTNER
+// Modified: 28.02.2009 by O. Kortner and J. von Loeben, extend extrapolation
+//                      features
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//::::::::::::::::::
+//:: HEADER FILES ::
+//::::::::::::::::::
+
+#include "MuonCalibMath/BaseFunctionFitter.h"
+#include "MuonCalibMath/LegendrePolynomial.h"
+#include "MdtCalibRt/RtParabolicExtrapolation.h"
+#include "MdtCalibData/IRtRelation.h"
+#include "MdtCalibData/RtRelationLookUp.h"
+
+//::::::::::::::::::::::::
+//:: NAMESPACE SETTINGS ::
+//::::::::::::::::::::::::
+
+using namespace MuonCalib;
+using namespace std;
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: IMPLEMENTATION OF METHODS DEFINED IN THE CLASS RtCalibrationAnalytic ::
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::
+//:: DEFAULT CONSTRUCTOR ::
+//:::::::::::::::::::::::::
+
+RtParabolicExtrapolation::RtParabolicExtrapolation(void) {
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: METHOD getRtWithParabolicExtrapolation(.,.,.) ::
+//:::::::::::::::::::::::::::::::::::::::::::::::::::
+
+RtRelationLookUp RtParabolicExtrapolation::getRtWithParabolicExtrapolation(
+                                            const IRtRelation & in_rt,
+                                            const double & r_min,
+                                            const double & r_max) const {
+
+///////////////
+// VARIABLES //
+///////////////
+
+    double t_min(t_from_r(r_min, in_rt));
+    double t_max(t_from_r(r_max, in_rt));
+    vector<SamplePoint> t_r(10);
+    BaseFunctionFitter fitter(3);
+    LegendrePolynomial pol;
+    vector<double> rt_param(102); // parameters of the output r-t relationship
+    double r, t; // drift radius
+
+////////////////////////
+// FILL SAMPLE POINTS //
+////////////////////////
+
+    double step_size((t_max-t_min)/static_cast<double>(t_r.size()-1));
+    for (unsigned int k=0; k<t_r.size(); k++) {
+        t_r[k].set_x1(t_min+k*step_size);
+        t_r[k].set_x2(in_rt.radius(t_min+k*step_size));
+        t_r[k].set_error(1.0);
+    }
+    fitter.fit_parameters(t_r, 1, t_r.size(), &pol);
+
+    rt_param[0] = in_rt.tLower();
+    rt_param[1] = (in_rt.tUpper()-in_rt.tLower())/99.0;
+    for (unsigned int k=0; k<100; k++) {
+        t = rt_param[0]+rt_param[1]*k;
+        r = in_rt.radius(t);
+        if (r<r_min) {
+            rt_param[k+2] = r;
+        } else {
+            rt_param[k+2] = 0.0;
+            for (unsigned int l=0; l<3; l++) {
+                rt_param[k+2] = rt_param[k+2]+
+                                fitter.coefficients()[l]*pol.value(l, t);
+            }
+        }
+    }
+
+    return RtRelationLookUp(rt_param);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::::
+//:: METHOD getRtWithParabolicExtrapolation(.,.,.,.,.) ::
+//:::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+RtRelationLookUp RtParabolicExtrapolation::getRtWithParabolicExtrapolation( 
+				      const IRtRelation & in_rt,
+				      const double & r_min,
+				      const double & r_max,
+				      const double & r_ext,
+				      const vector<SamplePoint> & add_fit_points
+				      ) const {
+
+///////////////
+// VARIABLES //
+///////////////
+
+//    double t_min(t_from_r(r_min, in_rt));
+    double t_min(get_max_t_at_r(r_min, in_rt));
+    double t_max(t_from_r(r_max, in_rt));
+    vector<SamplePoint> t_r(10);
+    BaseFunctionFitter fitter(3);
+    LegendrePolynomial pol;
+    vector<double> rt_param(102); // parameters of the output r-t relationship
+    double r, t; // drift radius, drift time
+
+////////////////////////
+// FILL SAMPLE POINTS //
+////////////////////////
+
+    double step_size((t_max-t_min)/static_cast<double>(t_r.size()-1));
+   
+// r-t-points in fit region
+    for (unsigned int k=0; k<t_r.size(); k++) {
+        t_r[k].set_x1(t_min+k*step_size);
+        t_r[k].set_x2(in_rt.radius(t_min+k*step_size));
+        t_r[k].set_error(1.0);
+    }
+
+// addtional points for the fit
+    for (unsigned int k=0; k<add_fit_points.size(); k++){
+    t_r.push_back(add_fit_points[k]);
+    }
+
+// perform fit //
+    fitter.fit_parameters(t_r, 1, t_r.size(), &pol);
+
+// bring r-t-points in the right format for RtRelationLookUp and fill non 
+// modified and extrapolated points in the r-t
+    rt_param[0] = in_rt.tLower();
+    rt_param[1] = (in_rt.tUpper()-in_rt.tLower())/99.0;
+//     cerr <<"r_ext:\t"<< r_ext << "\tr_min\t" << r_min << "\tr_max\t" << r_max << endl;
+    for (unsigned int k=0; k<100; k++) {
+        t = rt_param[0]+rt_param[1]*k;
+        r = in_rt.radius(t);
+
+// distinguish if extrapolation area is right or left from fit region
+        if (r_ext<r_min) {
+            if (r>r_min && t>t_min) { 
+                rt_param[k+2] = r; //fill original values
+            } else {
+            rt_param[k+2] = 0.0;
+            for (unsigned int l=0; l<3; l++) { // fill extrapolated values
+                rt_param[k+2] = rt_param[k+2]+  
+                                fitter.coefficients()[l]*pol.value(l, t);
+            }
+            if (rt_param[k+2]<0.0) {
+                rt_param[k+2] = 0.0;
+            }
+            }
+        }
+        else if (r_ext>r_max) {
+            if (r<r_max) {
+                rt_param[k+2] = r;//fill original values
+            } else {
+                rt_param[k+2] = 0.0;
+            for (unsigned int l=0; l<3; l++) { // fill extrapolated values
+                rt_param[k+2] = rt_param[k+2]+
+                fitter.coefficients()[l]*pol.value(l, t);
+            }
+            }
+        }
+// fill only original values if the radius where we want to extrapolate to is 
+// within the fit region
+        else if (r_ext <= r_max && r_ext >=r_min) {
+            rt_param[k+2] = r;
+            cerr << "Class RtParabolicExtrapolation," 
+                 << "WARNING: \n\t  Extrapolated radius withing fit region" 
+                 << " - Nothing to be done."
+                 << endl; 
+
+        }
+    }
+
+    return RtRelationLookUp(rt_param);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::
+//:: METHOD t_from_r ::
+//:::::::::::::::::::::
+
+double RtParabolicExtrapolation::t_from_r(const double & r,
+                                            const IRtRelation & in_rt) const {
+
+///////////////
+// VARIABLES //
+///////////////
+
+	double precision(0.010); // spatial precision of the inversion 
+	double t_max(in_rt.tUpper()); // upper time search limit
+	double t_min(in_rt.tLower()); // lower time search limit
+
+/////////////////////////////////////////////
+// SEARCH FOR THE CORRESPONDING DRIFT TIME //
+/////////////////////////////////////////////
+
+	while (t_max-t_min>0.1 &&
+			fabs(in_rt.radius(0.5*(t_min+t_max))-r)>precision) {
+
+		if (in_rt.radius(0.5*(t_min+t_max))>r) {
+			t_max = 0.5*(t_min+t_max);
+		} else {
+			t_min = 0.5*(t_min+t_max);
+		}
+
+	}
+
+	return 0.5*(t_min+t_max);
+
+}
+
+//*****************************************************************************
+
+//:::::::::::::::::::::::::::
+//:: METHOD get_max_t_at_r ::
+//:::::::::::::::::::::::::::
+
+double RtParabolicExtrapolation::get_max_t_at_r(const double & r,
+                                            const IRtRelation & in_rt) const {
+
+    for (double t=in_rt.tUpper(); t>=in_rt.tLower(); t=t-1.0) {
+        if (in_rt.radius(t)<r) {
+            return t+1.0;
+        }
+    }
+
+    return in_rt.tLower();
+
+}
-- 
GitLab