diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignModuleTool.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignModuleTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..68bcab3d14a969d111239ee17ccdc8b042bb586b
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignModuleTool.h
@@ -0,0 +1,167 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRKALIGNGENTOOLS_ALIGNMODULETOOL_H
+#define TRKALIGNGENTOOLS_ALIGNMODULETOOL_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "DataModel/DataVector.h"
+
+#include "TrkAlignInterfaces/IAlignModuleTool.h"
+#include "TrkAlignEvent/AlignModule.h"
+
+/**
+   @file AlignModuleTool.h
+   @class AlignModuleTool
+
+   @brief Tool for managing list of AlignModules, detector elements in 
+   AlignModules, and AlignPar for both.  Can be used as is or inherited by
+   subdetector. (dual_use library exists for this class.)
+
+   @author Robert Harrington <roberth@bu.edu>
+   @author Daniel Kollar <daniel.kollar@cern.ch>
+   @date 3/17/2009
+*/
+
+class AtlasDetectorID;
+class TRT_ID;
+
+namespace Trk {
+
+  class TrkDetElementBase;
+  class RIO_OnTrack;
+
+  class AlignModuleTool :  public AthAlgTool, virtual public IAlignModuleTool {
+ 
+  public:
+    typedef DataVector<AlignPar>    AlignParVec;
+    typedef DataVector<AlignParVec> AlignPar2DVec;
+
+    AlignModuleTool(const std::string& type, const std::string& name,
+		    const IInterface* parent);
+    virtual ~AlignModuleTool();
+    
+    virtual StatusCode initialize();
+    virtual StatusCode finalize();
+
+
+    //
+    // GeometryManagerTool methods
+    //
+
+    /** sets alignModuleLists and idHash maps for a set of AlignModules.  AlignModuleList should be of type Combined, containing detector elements of different types. */
+    void setAlignModules(AlignModuleList* alignmods,
+			 std::vector<AlignModuleList*>* idHashMaps);
+    
+    /** Sets the AlignParLists using boost::multi_array.  Lists are owned by GeometryManagerTool. */
+    void setAlignParLists(AlignPar2DVec* fullAlignParList, 
+			  AlignPar2DVec* alignParList=0);
+
+    /** set and retrieve flag whether or not the sub-TrkDetElementBase structures are aligned for a given detector type */
+    void setSubDetElement(AlignModule::DetectorType detType, bool status) { m_subDetElement[detType]=status; }
+    bool subDetElement(AlignModule::DetectorType detType) const { return m_subDetElement[detType]; }
+
+    //
+    // AlignTrackCreator methods
+    //
+
+    /** Returns pointer to AlignModule containing RIO.  Returns 0 if not found. */
+    virtual AlignModule * findAlignModule(const RIO_OnTrack * rio,
+                                          AlignModule::DetectorType detType) const;
+
+    /** Returns pointer to AlignModule containing RIO.  Returns 0 if not found. */
+    virtual AlignModule * findAlignModule(const TrkDetElementBase* det,
+                                          AlignModule::DetectorType detType) const;
+
+    //
+    // MatrixTool methods
+    //
+
+    /** Returns total number of alignment parameters. */
+    int nAlignParameters() const { return m_alignParList1D.size(); }
+    
+    /** Returns 1-D vector of all AlignModules containing all detector types. */
+    const AlignModuleList* alignModules1D() { return &m_alignModules1D; }
+    
+    /** Returns 1-D vector of all AlignPars for all detector types. */
+    AlignParVec* alignParList1D() { return &m_alignParList1D; }
+    
+    
+    //
+    // DerivCalcTool methods
+    //
+
+    /** returns vector of AlignPars for an AlignModule */
+    AlignParVec* getAlignPars(const AlignModule* alignModule) const;
+    
+    /** methods used for numerical derivative to shift module before 
+	refitting track and restore to normal position, to be inherited by 
+	detector-specific align modules */
+    virtual void shiftModule(const AlignModule*, const Track*, 
+			     AlignModule::TransformParameters, double) const {}
+    virtual void restoreModule(const AlignModule*) const {}
+    
+    
+    //
+    // AlignDBTool methods
+    // 
+    
+    /** fills values for alignment parameters for a detector element, applying AlignModule 
+        transforms if necessary */ 
+    virtual void fillDetAlignmentParameters(const TrkDetElementBase* det,
+					    DataVector<AlignPar>* apVec,
+					    AlignModule::DetectorType detType) const;
+
+    /** Returns collection of AlignModules for a particular detector type.*/    
+    virtual const AlignModuleList* getAlignModuleCollection() const 
+    { return m_alignModules; }
+
+    //
+    // FillNtuple methods
+    //
+
+    /** returns vector of full AlignPars for an AlignModule */
+    AlignParVec* getFullAlignPars(const AlignModule* alignModule) const;
+
+
+    //
+    // miscellaneous methods
+    //
+
+    /** Returns detector type (AlignModule enum) for a detector element. */
+    AlignModule::DetectorType getDetectorType(const TrkDetElementBase* det) const;
+
+    /** Returns identifier hash for sub-TrkDetElementBase structure based on detector type.
+        It needs detector specific implementation in a derived class */
+    virtual int subDetElementIDHash(Identifier ) const { return 0; }
+
+    /** returns complete AlignParList (active parameters only) */
+    AlignPar2DVec* alignParList() const { return m_alignParList; }
+
+    /** returns complete AlignParList */
+    AlignPar2DVec* fullAlignParList() const { return m_fullAlignParList; }
+
+  protected:
+    const AtlasDetectorID* m_idHelper;          //!< Used to identify type of detector
+
+  private:
+
+    AlignModuleList*                    m_alignModules;    //!< list of AlignModules
+    std::vector<const AlignModuleList*> m_alignModuleMaps; //!< maps detector element idHash to AlignModule
+
+    AlignPar2DVec*            m_alignParList;     //!< contains active parameters
+    AlignPar2DVec*            m_fullAlignParList; //!< contains all parameters
+
+    std::vector<AlignModule*> m_alignModules1D;    //!< 1-D vector of AlignModules
+    AlignParVec               m_alignParList1D;    //!< 1-D vector of AlignPars
+
+    std::vector<bool>         m_subDetElement;     //!< identify detectors aligning structures smaller than TrkDetElementBase
+  };
+
+ MsgStream& operator << ( MsgStream& sl, AlignModuleTool& alignModTool);
+  
+}
+
+#endif // TRKALIGNGENTOOLS_ALIGNMODULETOOL_H
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignResidualCalculator.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignResidualCalculator.h
new file mode 100644
index 0000000000000000000000000000000000000000..dd04bd10f318741bf996d550c76cdb325f21e30a
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignResidualCalculator.h
@@ -0,0 +1,89 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRKALIGNGENTOOLS_ALIGNRESIDUALCALCULATOR_H
+#define TRKALIGNGENTOOLS_ALIGNRESIDUALCALCULATOR_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "DataModel/DataVector.h"
+
+#include "TrkAlignInterfaces/IAlignResidualCalculator.h"
+
+/**
+   @file AlignResidualCalculator.h
+   @class AlignResidualCalculator
+
+   @brief Tool for calculating residuals for measurements and scattering 
+   centers and storing on AlignTSOS.
+
+   @author Robert Harrington <roberth@bu.edu>
+   @date 8/28/09
+*/
+
+class AtlasDetectorID;
+
+namespace Trk {
+
+  class AlignTrack;
+  class IUpdator;
+  class IResidualPullCalculator;
+  class ResidualPull;
+  class Track;
+  class AlignTSOS;
+  class TrackStateOnSurface;
+
+  class AlignResidualCalculator :  public AthAlgTool, virtual public IAlignResidualCalculator {
+ 
+  public:
+
+    AlignResidualCalculator(const std::string& type, const std::string& name,
+		    const IInterface* parent);
+    virtual ~AlignResidualCalculator();
+    
+    virtual StatusCode initialize();
+    virtual StatusCode finalize();
+
+    /** sets residuals for AlignTSOS on AlignTrack and returns total chi2 */
+    double setResiduals(DataVector<AlignTSOS>* alignTSOSColl, 
+			const Track* track);
+    
+    /** sets residuals for AlignTSOS on AlignTrack and returns total chi2 */
+    double setResiduals(const AlignTrack* alignTrack, const Track* track);
+    
+    /** sets residuals for AlignTSOS on AlignTrack and returns total chi2 */
+    double setResiduals(DataVector<AlignTSOS>::const_iterator firstAtsos,
+			DataVector<AlignTSOS>::const_iterator lastAtsos,
+			const Track* track, bool newTrack);
+
+    /** returns chi2 summed over hits of a particular MeasurementType */
+    double chi2ForMeasType(int measType) const { return m_chi2ForMeasType[measType]; }
+
+  private:
+
+    double setResidualsOnATSOS(AlignTSOS* atsos, const TrackStateOnSurface* tsos);
+    void   accumulateScattering(const TrackStateOnSurface* tsos);
+    const TrackStateOnSurface* getMatchingTSOS(const AlignTSOS* atsos, const Track* track) const;
+
+    ToolHandle <IResidualPullCalculator> m_pullCalculator;
+    ToolHandle <IUpdator>                m_updator;
+
+    int m_resType; //<! residual type as defined in the Trk::AlignResidualType enum
+
+    bool   m_includeScatterers;
+    double m_qOverP;
+    double m_previousQOverP;
+   
+    int    m_nDoF;
+
+    double* m_chi2ForMeasType; 
+
+    mutable std::vector<const TrackStateOnSurface*> m_matchedTSOS;
+
+  };
+
+  
+}
+
+#endif // TRKALIGNGENTOOLS_ALIGNRESIDUALCALCULATOR_H
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignTrackCreator.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignTrackCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..1832727e39c4d91b2023543dab3177b4c0facb21
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignTrackCreator.h
@@ -0,0 +1,69 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRKALIGNGENTOOLS_ALIGN_TRACK_CREATOR_H
+#define TRKALIGNGENTOOLS_ALIGN_TRACK_CREATOR_H
+
+#include "GaudiKernel/ToolHandle.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+
+#include "TrkAlignInterfaces/IAlignTrackCreator.h"
+
+#include <vector>
+
+/**
+   @file AlignTrackCreator.h
+   @class AlignTrackCreator
+   
+   @brief Tool used to create an AlignTrack containing all TSOS on a track, including scatterers.
+
+   @author Robert Harrington <roberth@bu.edu>
+   @date 1/5/08
+*/
+
+class AtlasDetectorID;
+
+namespace Trk {
+
+  class AlignTrack;
+  class AlignTSOS;
+  class MeasurementTypeID;
+  class IAlignModuleTool;
+  class IAlignResidualCalculator;
+  
+  class AlignTrackCreator : virtual public IAlignTrackCreator, public AthAlgTool {
+
+  public:
+    AlignTrackCreator(const std::string& type, const std::string& name,
+		     const IInterface* parent);
+    virtual ~AlignTrackCreator();
+
+    StatusCode initialize();
+    StatusCode finalize();
+
+    /** creates AlignTrack containing all TSOS on track */
+    bool processAlignTrack(AlignTrack* track) const;
+   
+  private:
+
+    // private variables
+    ToolHandle<IAlignModuleTool>                  m_alignModuleTool;
+    ToolHandle<IAlignResidualCalculator>          m_residualCalculator;
+
+    const AtlasDetectorID*   m_idHelper;
+    MeasurementTypeID* m_measTypeIdHelper;
+
+    mutable std::vector< std::pair<int,int> > m_goodEventList; //!> good events read in from ASCII file
+
+    std::string m_eventListName;             //!> name of event list ASCII file    
+    bool m_writeEventList;                   //!> write selected events to event list ASCII file
+    bool m_requireOverlap;                   //!> keep only tracks that pass through 2 or more AlignModules
+    bool m_removeATSOSNotInAlignModule;      //!> remove AlignTSOS not in AlignModules
+    bool m_includeScatterers;                //!> includes scatterers on track
+
+  }; // end class
+
+} // end namespace
+
+#endif // TRKALIGNGENTOOLS_ALIGN_TRACK_CREATOR_H
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignTrackDresser.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignTrackDresser.h
new file mode 100644
index 0000000000000000000000000000000000000000..ba9089dd821998bd62f0db60261f118a96f45b0d
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignTrackDresser.h
@@ -0,0 +1,62 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRKALIGNGENDRESSERS_ALIGN_TRACK_DRESSER_H
+#define TRKALIGNGENDRESSERS_ALIGN_TRACK_DRESSER_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include "TrkAlignInterfaces/IAlignTrackDresser.h"
+
+/**
+   @file AlignTrackDresser.h
+   @class AlignTrackDresser
+   
+   @brief Tool used to dress AlignTrack with residuals and other information needed for alignment.
+
+   @author Robert Harrington <roberth@bu.edu>
+   @date 1/5/08
+
+   @author Daniel Kollar <daniel.kollar@cern.ch>
+*/
+
+namespace CLHEP {
+  class HepSymMatrix;
+}
+
+namespace Trk {
+  class IDerivCalcTool;
+  class AlignTrack;
+
+  class AlignTrackDresser : virtual public IAlignTrackDresser, public AthAlgTool {
+
+  public:
+    AlignTrackDresser(const std::string & type, const std::string & name, const IInterface * parent);
+    virtual ~AlignTrackDresser();
+
+    StatusCode initialize();
+    StatusCode finalize();
+    
+    /** dresses alignTrack with derivatives and other information */
+    bool dressAlignTrack(AlignTrack * alignTrack) const;
+
+    /** sets residuals for TSOS on alignTrack */
+    void setResiduals(AlignTrack * alignTrack) const;
+
+    /** sets the output stream for the logfile */
+    virtual void setLogStream(std::ostream * os);
+
+  private:
+
+    // private variables
+    ToolHandle <IDerivCalcTool>  m_derivCalcTool; //!< tool for calculating derivatives of residuals wrt. alignment parameters
+
+    mutable unsigned int m_numBadCovWMatrix; //!< number of tracks with invalid weight matrix from the deriv.calc.tool
+
+  }; // end class
+
+} // end namespace
+
+#endif // TRKALIGNGENDRESSERS_ALIGN_TRACK_DRESSER_H
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignTrackPreProcessor.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignTrackPreProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..ba592041328425e57b1a41c1ffbfa2aad63afc7d
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AlignTrackPreProcessor.h
@@ -0,0 +1,71 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRKALIGNGENTOOLS_ALIGNTRACKPREPROCESSOR_H
+#define TRKALIGNGENTOOLS_ALIGNTRACKPREPROCESSOR_H
+
+
+#include "GaudiKernel/ToolHandle.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+
+#include "TrkAlignInterfaces/IAlignTrackPreProcessor.h"
+
+#include <vector>
+
+/**
+   @file AlignTrackPreProcessor.h
+   @class AlignTrackPreProcessor
+   
+   @brief Tool used to create AlignTracks from an input collection of tracks.
+   At a minimum, the track is refit and the full covariance matrix and derivative
+   matrix are stored on the AlignTrack.
+   The AlignTracks are filled into a collection of Tracks.
+
+   @author Robert Harrington <roberth@bu.edu>, Daniel Kollar <daniel.kollar@cern.ch>
+   @date 10/1/09
+*/
+
+
+namespace Trk {
+
+  class Track;
+  class IGlobalTrackFitter;
+  class ITrackSelectorTool;
+
+  class AlignTrackPreProcessor : virtual public IAlignTrackPreProcessor, public AthAlgTool
+  {
+
+  public:
+    AlignTrackPreProcessor(const std::string & type, const std::string & name, const IInterface * parent);
+    virtual ~AlignTrackPreProcessor();
+    
+    StatusCode initialize();
+    StatusCode finalize();
+    
+    /** creates AlignTrack containing all TSOS on track */
+    DataVector<Track> * processTrackCollection(const DataVector<Track>* trks);
+   
+  private:
+    ToolHandle<IGlobalTrackFitter> m_trackFitterTool;
+    ToolHandle<IGlobalTrackFitter> m_SLTrackFitterTool;
+
+    ToolHandle<ITrackSelectorTool> m_trackSelectorTool;
+
+    bool m_refitTracks; //!> flag to refit tracks
+    bool m_storeFitMatricesAfterRefit; //!> flag to store derivative and covariance matrices after refit
+
+    bool m_runOutlierRemoval;  //!> run outlier removal in track refit
+    int  m_particleHypothesis; //!> particle hypothesis in track refit
+
+    bool m_useSingleFitter;    //!< only use 1 fitter for refitting track
+
+    bool m_selectTracks;       //!< do the track selection
+
+  }; // end class
+
+} // end namespace
+
+#endif // TRKALIGNGENTOOLS_ALIGNTRACKPREPROCESSOR_H
+
+
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AnalyticalDerivCalcTool.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AnalyticalDerivCalcTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..51975562ca76bd2d74652198641cdcfc628a168b
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/AnalyticalDerivCalcTool.h
@@ -0,0 +1,93 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRK_ANALYTICALDERIVCALCTOOL_H
+#define TRK_ANALYTICALDERIVCALCTOOL_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "EventPrimitives/EventPrimitives.h"
+#include "GeoPrimitives/GeoPrimitives.h"
+
+#include "TrkAlignInterfaces/IDerivCalcTool.h"
+
+#include <vector>
+
+
+/**
+   @file AnalyticalDerivCalcTool.h 
+   @class AnalyticalDerivCalcTool
+
+   @brief This class is the tool used with global chi2 aligment to calculate analytical 
+   derivatives based on the track covariance matrix.
+
+   @author Robert Harrington <roberth@bu.edu>
+   @author Daniel Kollar <daniel.kollar@cern.ch>
+   @author Shih-Chieh Hsu <Shih-Chieh.Hsu@cern.ch>
+*/
+
+class AtlasDetectorID;
+
+namespace Trk
+{
+  class AlignModule;
+  class AlignTrack;
+  class IAlignModuleTool;
+  class MeasurementTypeID;
+
+  class AnalyticalDerivCalcTool : virtual public IDerivCalcTool, public AthAlgTool
+  {
+
+  public:
+    AnalyticalDerivCalcTool(const std::string & type, const std::string & name, const IInterface * parent);
+    virtual ~AnalyticalDerivCalcTool();
+
+    StatusCode initialize();
+    StatusCode finalize();
+
+    /** sets analytical partial derivatives of residuals w.r.t alignment parameters for TSOS on alignTrack. */ 
+    bool setDerivatives(AlignTrack * alignTrack);
+
+    /** not used yet */
+    void showStatistics() {}
+
+    /** sets residual covariance matrix */
+    bool setResidualCovMatrix(AlignTrack * alignTrack) const;
+
+  private:
+
+    ToolHandle<IAlignModuleTool>   m_alignModuleTool;
+
+    const AtlasDetectorID * m_idHelper;
+    MeasurementTypeID * m_measTypeIdHelper;
+
+    bool getMeasErrorMatrix(const AlignTrack * alignTrack, Amg::MatrixX & V) const;
+
+    bool getTrkParamCovMatrix(const AlignTrack * alignTrack, Amg::MatrixX & HCH) const;
+
+    bool checkValidity(const Amg::MatrixX & R) const;
+
+    std::vector<Amg::VectorX> getDerivatives(AlignTrack * alignTrack,  const AlignModule * module);
+
+    void checkResidualType(const AlignTrack * alignTrack);
+
+    std::vector<std::pair<const AlignModule *, std::vector<Amg::VectorX> > > m_derivatives;
+
+    bool m_useLocalSetting;         //!< use local setup for the covariance matrix of the track
+    bool m_useIntrinsicPixelErrors; //!< use intrinsic errors for Pixel
+    bool m_useIntrinsicSCTErrors;   //!< use intrinsic errors for SCT
+    bool m_useIntrinsicTRTErrors;   //!< use intrinsic errors for TRT
+
+    mutable bool m_firstEvent; //!< recognise the first call to setResidualCovMatrix()
+
+    int m_residualType; //!< residual type to be used in the calculations
+    mutable bool m_residualTypeSet;   //!< do we have the residual type set?
+
+    bool m_storeDerivatives; //!< store derivatives on AlignTSOS to be filled into ntuple
+
+  }; // end class
+
+} // end namespace
+
+#endif // TRK_ANALYTICALDERIVCALCTOOL_H
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/BeamspotVertexPreProcessor.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/BeamspotVertexPreProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..71436a36cc5262a52fda9689557cb31950855661
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/BeamspotVertexPreProcessor.h
@@ -0,0 +1,169 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef  TRKALIGNGENTOOLS_BEAMSPOTVERTEXPREPROCESSOR_H
+#define  TRKALIGNGENTOOLS_BEAMSPOTVERTEXPREPROCESSOR_H
+
+#include "GaudiKernel/ToolHandle.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "TrkAlignInterfaces/IAlignTrackPreProcessor.h"
+#include "TrkEventPrimitives/ParticleHypothesis.h"
+#include <limits>
+#include "VxVertex/VxContainer.h"
+#include <functional>
+
+
+/**
+   @brief Tool used to create a collection of AlignTracks from Tracks
+   while the tracks are being refitted with a vertex/beam-spot constraint.
+   The AlignTracks are filled into a collection of Tracks.
+   The default control flow is like this:
+   firstly do vertex constraint, if can't, then do beamspot again;
+   if can't again, then do normal refit.
+   if want to do vertex constraint only, set:
+   doVertexConstraint = True and doBeamspotConstraint = False 
+   if want to do beamspot constraint only, set:
+   doVertexConstraint = False and doBeamspotConstraint = True 
+   @author Jike Wang <jwang@cern.ch>
+   @author Daniel Kollar <daniel.kollar@cern.ch>
+*/
+ 
+class IBeamCondSvc;
+
+namespace Trk {
+  class IGlobalTrackFitter;
+  class IExtrapolator;
+  class ITrackSelectorTool;
+  class Track;
+  class AlignTrack;
+  class AlignVertex;
+  class VxCandidate;
+  class VertexOnTrack;
+  class VxTrackAtVertex;
+  class IVertexUpdator;
+  class IVertexLinearizedTrackFactory;
+  class IAlignModuleTool;
+
+  class BeamspotVertexPreProcessor : virtual public Trk::IAlignTrackPreProcessor, public AthAlgTool
+  {
+
+  public:
+
+    BeamspotVertexPreProcessor(const std::string & type, const std::string & name, const IInterface * parent);
+    virtual ~BeamspotVertexPreProcessor();
+
+    virtual StatusCode initialize();
+    virtual StatusCode finalize();
+
+    virtual DataVector<Track> * processTrackCollection(const DataVector<Track> * trks);
+
+    void accumulateVTX(const AlignTrack* alignTrack);
+
+    void solveVTX();
+
+
+    /** Print processing summary to logfile. */
+    virtual void printSummary();
+
+
+
+  private:
+
+    void  prepareAllTracksVector();
+
+    bool  isAssociatedToPV(const Track * track, const VxContainer * vertices);
+    bool  isAssociatedToVertex(const Track * track, const VxCandidate * vertex);
+
+    bool  selectVertices(const VxCandidate* vtx) const;
+    bool  selectUpdatedVertices(const VxCandidate* updatedVtx) const;
+    const std::pair<const VxCandidate*, VxTrackAtVertex*> findVertexCandidate(const Track* track) const; 
+    const VertexOnTrack* provideVotFromVertex(const Track* track, const VxCandidate* &vtx) const;
+    const VertexOnTrack* provideVotFromBeamspot(const Track* track) const;
+    void provideVtxBeamspot(const AlignVertex* b, AmgSymMatrix(3)* q, Amg::Vector3D* v) const;
+
+
+    const Track* doConstraintRefit(ToolHandle<IGlobalTrackFitter>& fitter, const Track* track,  const VertexOnTrack* vot, const ParticleHypothesis& particleHypothesis) const;
+    bool  doBeamspotConstraintTrackSelection(const Track* track);
+    AlignTrack* doTrackRefit(const Track* track);
+
+
+
+
+    ToolHandle<IGlobalTrackFitter>    m_trackFitter;     //!< normal track fitter
+    ToolHandle<IGlobalTrackFitter>    m_SLTrackFitter;   //! straight line track fitter
+
+    ToolHandle<IExtrapolator>         m_extrapolator;    //!< track extrapolator
+    ToolHandle<ITrackSelectorTool>    m_trkSelector;     //!< track selector tool
+    ToolHandle<ITrackSelectorTool>    m_BSTrackSelector; //!< track selector tool for tracks to be used with beam-spot constraint
+    ToolHandle<IVertexUpdator>        m_IVertexUpdator;  //!< vertex updating tool, such as reomving one track from vertex
+    
+    //Comment out to make it compile in rel5  --  correct in the future 
+    ToolHandle<IVertexLinearizedTrackFactory> m_linFactory;
+
+    /** Pointer to AlignModuleTool*/
+    ToolHandle <Trk::IAlignModuleTool> m_alignModuleTool;
+    
+
+    ServiceHandle<IBeamCondSvc>       m_beamCondSvc;     //!< condition service for beam-spot retrieval
+
+    std::string m_PVContainerName;                       //!< the name of the primary vertex container
+    bool m_runOutlierRemoval;                            //!< switch whether to run outlier logics or not
+    bool m_selectVertices;                 	         //!< do vertex selection  
+    int  m_particleNumber;             		         //!< type of material interaction in extrapolation
+    bool m_doBSTrackSelection;                           //!< the selection mechanism which is based on cutting the perigee parameters, pt, etc.
+    bool m_doAssociatedToPVSelection;        		 //!< the selection mechanism that only use the tracks associated to PV
+
+    unsigned int m_constraintMode;
+
+    std::string m_compareMethod;			 //!< the method used to judge whether two tracks are the same track
+    std::vector<std::string> m_interestedVertexContainers;
+    std::vector< std::pair< VxCandidate*, std::vector<VxTrackAtVertex*>* > >  m_allTracksVector;
+
+    bool m_doBeamspotConstraint;    			 //!< do beamspot constraint 
+    bool m_doPrimaryVertexConstraint;      		 //!< do vertex constraint 
+    bool m_doFullVertexConstraint;                       //!< do GX full vertex constraint 
+ 
+    bool m_refitTracks;             			 //!< flag to refit tracks
+    bool m_storeFitMatrices;  			         //!< flag to store derivative and covariance matrices after refit
+    bool m_useSingleFitter;   	    			 //!< only use 1 fitter for refitting track
+    bool m_selectTracks;            			 //!< do the track selection
+    double m_BSScalingFactor;				 //!< scaling factor on beasmpot width
+    double m_PVScalingFactor;				 //!< scaling factor on primary vertex position error
+
+    int m_minTrksInVtx;					 //!< requirement to the minimal number of tracks in the vertex 
+    int m_nTracks;
+    std::vector<int> m_trackTypeCounter;
+    int m_nFailedNormalRefits;
+    int m_nFailedBSRefits;
+    int m_nFailedPVRefits;
+
+    DataVector<AlignVertex> AlignVertices;	         //!< collection of AlignVertices used in FullVertex constraint option
+
+
+  };
+
+
+
+class CompareTwoTracks : public std::unary_function<VxTrackAtVertex*, bool>{
+
+    public:
+         CompareTwoTracks(const Track* track, std::string compareMethod)
+         :m_method(compareMethod)
+         ,m_track(track)
+         { //std::cout <<"compareMethod: "<< m_method <<std::endl; 
+         }
+
+         bool operator()(VxTrackAtVertex* vtxTrk);
+
+    private:
+         std::string m_method;
+         const Track* m_track;
+  };
+
+
+
+} 
+
+#endif // TRKALIGNGENTOOLS_BEAMSPOTVERTEXPREPROCESSOR_H
+
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/ConstrainedTrackProvider.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/ConstrainedTrackProvider.h
new file mode 100644
index 0000000000000000000000000000000000000000..6198d2b1ccdec581dbc1b28412725674ce8482d9
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/ConstrainedTrackProvider.h
@@ -0,0 +1,102 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRKALIGNGENTOOLS_CONSTRAINEDTRACKPROVIDER_H
+#define TRKALIGNGENTOOLS_CONSTRAINEDTRACKPROVIDER_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "muonEvent/Muon.h"
+#include "TrkAlignInterfaces/ITrackCollectionProvider.h"
+#include "TrkFitterUtils/FitterTypes.h"  
+
+
+
+class TFile;
+class TH2F;
+/**
+  ConstrainedTrackProvider
+  
+  Will provide  a track coolection with momentum conatraint applied.  A 2d histogram read  and 
+  corrections (delta) are extracted as function of eta and phi.
+  The momentum is scaled as 
+  corrected QoverP = original QoverP * (1.+ charge *pt *delta );
+
+  The strength of eth constraint can be varied as well.
+*/
+namespace Trk {
+  class IGlobalTrackFitter;
+
+  class ConstrainedTrackProvider : virtual public ITrackCollectionProvider, public AthAlgTool {
+
+  public:
+    ConstrainedTrackProvider(const std::string & type, const std::string & name, const IInterface * parent);
+    virtual ~ConstrainedTrackProvider();
+    
+    virtual StatusCode initialize();
+    virtual StatusCode finalize();
+    
+    virtual StatusCode trackCollection(const TrackCollection*& tracks);
+
+    virtual void printSummary();
+
+  private :
+
+    void  getCorrectedValues_P(const Trk::Perigee* mp, double& correctedQoverP,double& correctedQoverPError);
+    void  getCorrectedValues_d0(const Trk::Perigee* mp, double& corrected_d0,double& corrected_d0Error);
+    void  getCorrectedValues_z0(const Trk::Perigee* mp, double& corrected_z0,double& corrected_z0Error);
+    bool  passTrackSelection(const Trk::Track *track);
+
+    ToolHandle<IGlobalTrackFitter>        m_trackFitter;     //!< normal track fitter 
+ 
+    RunOutlierRemoval     m_runOutlierRemoval;         //!< run outlier removal in the GX2 fitter 
+    int           m_nRetrievalErrors;          //!< number of retrieval errors at the beginning of the job
+    int           m_maxRetrievalErrors;        //!< maximum allowed number of retrieval errors at the beginning of the job (-1 for infinite)
+    bool          m_useConstrainedTrkOnly;
+    int           m_constrainedTracks;
+    int           m_passconstrainedRequirements;
+    int           m_unconstrainedTracks;
+
+    bool          m_useConstraintError;
+    double        m_reduceConstraintUncertainty;
+    double        m_deltaScaling;
+
+    int           m_minPIXHits;
+    int           m_minSCTHits;
+    int           m_minTRTHits;
+    double        m_maxd0;
+    double        m_maxz0;
+    double        m_minPt;
+    double        m_maxPt;
+    
+
+    std::string     m_inputTrackCollection;
+
+
+    bool            m_CorrectMomentum;
+    std::string     m_constraintFileName_P; 
+    TFile*          m_constraintInputFile_P;
+    std::string     m_constraintHistName_P; 
+    TH2F*           m_etaphiMap_P;
+      // Corrections expected to be in GeV-1
+
+    bool            m_CorrectD0;
+    std::string     m_constraintFileName_d0; 
+    TFile*          m_constraintInputFile_d0;
+    std::string     m_constraintHistName_d0; 
+    TH2F*           m_etaphiMap_d0;
+      // Corrections expected to be in mm
+
+    bool            m_CorrectZ0;
+    std::string     m_constraintFileName_z0; 
+    TFile*          m_constraintInputFile_z0;
+    std::string     m_constraintHistName_z0; 
+    TH2F*           m_etaphiMap_z0;
+      // Corrections expected to be in mm
+    
+  }; // end class
+
+} // end namespace
+
+#endif // TRKALIGNGENTOOLS_CONSTRAINEDTRACKPROVIDER_H
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/IPCMatrixTool.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/IPCMatrixTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..0286c2ae0c0f3415a26e922c97cbf8f8a4610ae5
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/IPCMatrixTool.h
@@ -0,0 +1,101 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRKALIGNGENTOOLS_IPCMATRIXTOOL_H
+#define TRKALIGNGENTOOLS_IPCMATRIXTOOL_H
+
+/** @file IPCMatrixTool.h
+    @class IPCMatrixTool
+
+    @brief Based on SiGlobalChi2Algs.  
+    AlgTool used with 64-big parallel processing to create IPC matrix and 
+    vector for storing first- and second-derivative terms needed to solve 
+    for alignment parameters.  Also provides for methods to add terms to 
+    existing matrix entries, and to solve for alignment parameters by 
+    inverting matrix and multiplying by vector. 
+
+    @author Robert Harrington <roberth@bu.edu>
+    @date 1/5/08
+*/
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "TrkAlignInterfaces/IMatrixTool.h"
+
+namespace Trk {
+
+  class AlVec;
+  class AlSymMatBase;
+  class IPCMat;
+
+  class IPCMatrixTool : public AthAlgTool, virtual public IMatrixTool {      
+  public:
+
+    /** Constructor */
+    IPCMatrixTool(const std::string& type, const std::string& name,
+		  const IInterface* parent);
+    
+    /** Virtual destructor */
+    virtual ~IPCMatrixTool();
+    
+    /** initialize */
+    StatusCode initialize();
+    
+    /** initialize */
+    StatusCode finalize();
+    
+    /** allocates memory for IPC matrix and vector */
+    StatusCode allocateMatrix(int nDoF); 
+    
+    /** reads/writes matrix entries from/to binary files as necessary*/
+    void prepareBinaryFiles(int solveOption);
+
+    /** adds first derivative to vector */
+    void addFirstDerivatives(AlVec* vector);
+
+    /** adds first derivative to vector for only some entries */
+    void addFirstDerivatives(std::list<int,double>& derivatives);
+
+    /** adds second derivatives to matrix */
+    void addSecondDerivatives(AlSymMatBase* matrix);
+
+    /** adds first derivative to vector for only some entries */
+    void addSecondDerivatives(std::list<std::pair<int,int>,double >& derivatives);
+
+    /** accumulates from  files */
+    bool accumulateFromFiles();
+
+    /** solves for alignment parameters */
+    int solve();
+
+    void addFirstDerivative(int irow, double firstderiv);    
+    void addSecondDerivative(int irow, int icol, double secondderiv);
+
+    //void setAlignModule(int, const AlignModule*, int) {}
+
+  private:
+    
+    /** Pointer to IPCMat, used for parallel processing */
+    IPCMat* m_ipcmat; 
+    
+    std::string m_ipcmatMatName;      //!< IPC binary matrix filename
+    std::string m_ipcmatVecName;      //!< IPC binary vector filename
+
+    /** remove spurious + align. pars from IPC matrix before writing */
+    bool m_IPCremoval;
+
+  }; // end of class
+
+  inline void IPCMatrixTool::addFirstDerivative(int, double) { /*m_bigvector[i]+=firstderiv;*/ }
+  
+  inline void IPCMatrixTool::addSecondDerivative(int, int, double) { /*m_bigmatrix[irow][icol]+=secondderiv;*/ }
+
+
+} // end of namespace
+
+#endif // TRKALIGNGENTOOLS_IPCMATRIXTOOL_H
+
+
+
+
+
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/MSConstraintTracksProvider.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/MSConstraintTracksProvider.h
new file mode 100644
index 0000000000000000000000000000000000000000..88047f23f5d805668146e8a5957d770d338ffcc9
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/MSConstraintTracksProvider.h
@@ -0,0 +1,131 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRKALIGNGENTOOLS_MSCONSTRAINTTRACKSPROVIDER_H
+#define TRKALIGNGENTOOLS_MSCONSTRAINTTRACKSPROVIDER_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "muonEvent/Muon.h"
+#include "TrkAlignInterfaces/ITrackCollectionProvider.h"
+#include "TrkFitterUtils/FitterTypes.h"  
+
+
+
+
+
+class TFile;
+class TTree;
+
+
+namespace Muon{
+  class IMuonHitSummaryTool;
+}
+
+
+namespace Trk {
+  class IGlobalTrackFitter;
+
+  class MSConstraintTracksProvider : virtual public ITrackCollectionProvider, public AthAlgTool {
+
+  public:
+    MSConstraintTracksProvider(const std::string & type, const std::string & name, const IInterface * parent);
+    virtual ~MSConstraintTracksProvider();
+    
+    virtual StatusCode initialize();
+    virtual StatusCode finalize();
+    
+    virtual StatusCode trackCollection(const TrackCollection*& tracks);
+
+    virtual void printSummary();
+
+  private :
+
+    bool combinedMuonSelection(const Analysis::Muon*);
+    bool bookNtuple();  
+    void initializeNtuple();
+    void setNtuple(TFile* ntuple);
+    StatusCode fillNtuple();
+
+    ToolHandle<IGlobalTrackFitter>        m_trackFitter;     //!< normal track fitter 
+    ToolHandle<Muon::IMuonHitSummaryTool> m_muonHitSummaryTool;
+ 
+    std::string 	  m_inputMuonCollection;       //!< Name of input combined muons collection
+    std::string		  m_inputTracksCollection;     //!< Name of input tracks collection
+    RunOutlierRemoval     m_runOutlierRemoval;         //!< run outlier removal in the GX2 fitter 
+    int      		  m_nRetrievalErrors;          //!< number of retrieval errors at the beginning of the job
+    int      		  m_maxRetrievalErrors;        //!< maximum allowed number of retrieval errors at the beginning of the job (-1 for infinite)
+    bool		  m_useMSConstraintTrkOnly;
+    bool 		  m_doTree;
+
+    double   		  m_minPt;
+    int     		  m_minPIXHits;
+    int    		  m_minSCTHits;
+    int    		  m_minTRTHits;
+    double 		  m_maxIDd0;
+    double 		  m_maxIDz0;
+    double 		  m_minIDPt;
+    int     	 	  m_minMDTHits;
+    int    		  m_minRPCPhiHits;
+    int    		  m_minTGCPhiHits;
+    double 		  m_maxMSd0;
+    double 		  m_maxMSz0;
+    double 		  m_minMSPt;
+    double 		  m_maxNumberOfSectors;
+    double 		  m_minNumberOfPhiLayers;
+    double 		  m_minStationLayers;
+    int 		  m_nCBMuonsFromSG;
+    int			  m_nCBMuonsHasEXandID;
+    int 		  m_nCBMuonsPassSelection;
+    int 		  m_nCBMuonsFailedRefit;	
+    int   		  m_nCBMuonsSucRefit;
+
+    // ntuple variables
+    TFile*   		  m_ntuple;
+    TTree*   		  m_tree;
+    int			  m_run;
+    int			  m_event;
+    double 		  m_pID;
+    double 		  m_pMS;
+    double 		  m_ptID;
+    double 		  m_ptMS;
+    int 		  m_charge;
+
+    double 	 	  m_combinedEta;
+    double 		  m_IDEta;
+    double 		  m_combinedPhi;
+    double 		  m_IDPhi;
+
+    double 		  m_pID_constrained;
+    double 		  m_ptID_constrained;
+    double 		  m_IDEta_constrained;
+    double 		  m_IDPhi_constrained;
+    int 		  m_charge_constrained;
+
+    int 		  m_eBLhits;
+    int			  m_nBLhits;
+
+    int			  m_nPIXDS;
+    int 		  m_nSCTDS;
+
+    int		   	  m_nPIXH;
+    int 		  m_nSCTH;
+
+    int 		  m_nPIXHits;
+    int 		  m_nSCTHits;
+    int 		  m_nTRTHits;
+
+    int 		  m_sectors;
+    int 		  m_phiLayers;
+    int 		  m_stationLayers;
+
+    int 		  m_sectorNum;
+    int 		  m_phiLayerNum;
+    int 		  m_stationLayerNum;
+
+  }; // end class
+
+} // end namespace
+
+#endif // TRKALIGNGENTOOLS_MSCONSTRAINTTRACKSPROVIDER_H
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/MatrixTool.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/MatrixTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..79d30cbc750f07639e68fca3b5bb29a6e739ac04
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/MatrixTool.h
@@ -0,0 +1,229 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRKALIGNGENTOOLS_MATRIXTOOL_H
+#define TRKALIGNGENTOOLS_MATRIXTOOL_H
+
+/** @file MatrixTool.h
+    @class MatrixTool
+
+    @brief Based on SiGlobalChi2Algs.  
+    AlgTool used to create a large matrix and vector for storing first- and 
+    second-derivative terms needed to solve for alignment parameters.  Also 
+    provides for methods to add terms to existing matrix entries, and to 
+    solve for alignment parameters by inverting matrix and multiplying by 
+    vector.
+    
+    @author Robert Harrington <roberth@bu.edu>, Daniel Kollar <daniel.kollar@cern.ch>
+    @date 1/5/08
+*/
+
+#include "GaudiKernel/ToolHandle.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+
+#include "TrkAlignInterfaces/IMatrixTool.h"
+
+#include <TMatrixDSym.h>
+#include "CLHEP/Matrix/SymMatrix.h"
+
+#include <string>
+
+class TString;
+
+/** @class MatrixTool
+    
+    @brief AlgTool used to create a large matrix and vector for storing first- 
+    and second-derivative terms needed to solve for alignment parameters.  
+    Also provides for methods to add terms to existing matrix entries, and to 
+    solve for alignment parameters by inverting matrix and multiplying by 
+    vector.
+    
+    Uses the double inheritance structure; concrete tools should inherit from 
+    this class and AlgTool with virtual public inheritance.   
+*/
+
+namespace Trk {
+
+  class AlSymMatBase;
+  class AlSymMat;
+  class AlMat;
+  class AlVec;
+
+  class IAlignModuleTool;
+
+  class MatrixTool : public AthAlgTool, virtual public IMatrixTool {    
+  public:
+
+    enum SolveOption { 
+      NONE                 = 0, //!< not solve in any case (to be used when ipc)
+      SOLVE                = 1, //!< solving after data accumulation (LAPACK)
+      SOLVE_FAST           = 2, //!< Fast (***REMOVED*** method) solving after data accumulation
+      DIRECT_SOLVE         = 3, //!< direct solving (LAPACK), already available matrix & vector
+      DIRECT_SOLVE_FAST    = 4, //!< direct Fast (***REMOVED*** method) solving, already available matrix & vector
+      DIRECT_SOLVE_CLUSTER = 5, //!< computation of alignment parameters from SCALAPAK already solved matrix
+      SOLVE_ROOT           = 6, //!< computation using ROOT
+      SOLVE_CLHEP          = 7  //!< computation using CLHEP
+    };
+
+    /** Constructor */
+    MatrixTool(const std::string& type, const std::string& name,
+	       const IInterface* parent);
+
+    /** Virtual destructor */
+    virtual ~MatrixTool();
+    
+    /** initialize */
+    StatusCode initialize();
+    
+    /** initialize */
+    StatusCode finalize();
+    
+    /** allocates memory for big matrix and big vector */
+    StatusCode allocateMatrix(int nDoF=0); 
+    
+    /** reads/writes matrix entries from/to binary files as necessary*/
+    void prepareBinaryFiles(int solveOption);
+
+    /** adds first derivative to vector */
+    void addFirstDerivatives(AlVec* vector);
+
+    /** adds first derivative to vector for only some entries */
+    void addFirstDerivatives(std::list<int,double>& derivatives);
+
+    void addFirstDerivative(int irow, double firstderiv);  
+
+    /** adds second derivatives to matrix */
+    void addSecondDerivatives(AlSymMatBase* matrix);
+
+    /** adds first derivative to vector for only some entries */
+    void addSecondDerivatives(std::list<std::pair<int,int>,double >& derivatives);
+
+    void addSecondDerivative(int irow, int icol, double secondderiv);
+
+
+    /** accumulates derivates from files.  Flag decides if it is binary or TFiles */
+    bool accumulateFromFiles();
+    
+    /** accumulates derivates from binary files */
+    bool accumulateFromBinaries();
+
+    /** solves for alignment parameters */
+    int solve();
+
+    
+    /** Store Files in a tfile */
+    void storeInTFile(TString filename);
+
+    /** Store Files in a tfile */
+    bool accumulateFromTFiles();
+
+    void printModuleSolution(std::ostream & os, const AlignModule * module, const CLHEP::HepSymMatrix * cov) const;
+    void printGlobalSolution(std::ostream & os, const CLHEP::HepSymMatrix * cov) const;
+    void printGlobalSolution(std::ostream & os, const TMatrixDSym * cov) const;
+
+  private:
+
+    // private methods
+    int solveROOT();
+    int solveCLHEP();
+    int solveLapack();
+    int solve***REMOVED***();
+    int solveLocal();
+
+    StatusCode spuriousRemoval();
+    int        fillVecMods();
+    void       postSolvingLapack(AlVec * dChi2, AlSymMat * d2Chi2, AlVec &w, AlMat &z, int size);
+
+    void writeHitmap();
+    void readHitmaps();
+
+    // private variables
+    ToolHandle<IAlignModuleTool> m_alignModuleTool;
+
+    /** matrix to contain second derivative terms to be used for alignment */
+    AlSymMatBase* m_bigmatrix;     
+    
+    /** vector to contain first derivative terms to be used for alignment */
+    AlVec* m_bigvector; 
+    
+    /** flag to use AlSpaMat for the big matrix (default is AlSymMat) */
+    bool m_useSparse;    
+
+    bool m_diagonalize;           //!< run diagonalization instead of inversion
+    double m_eigenvaluethreshold; //!< cut on the minimum eigenvalue
+
+    int   m_nDoF;
+    int   m_solveOption;     //!< solving option
+    int   m_modcut;          //!< cut on the weak modes which number is <par_modcut
+    int   m_minNumHits;      //!< cut on the minimum number of hits per module
+    int   m_minNumTrks;      //!< cut on the minimum number of tracks per module
+    float m_pullcut;         //!< pull cut for the automatic weak mode removal method
+    float m_eigenvalueStep;  //!< eigenvalue step for the second pass in the automatic weak mode removal method
+    float m_Align_db_step;   //!< corr in the diagonal basis step for the third pass in the auto weak mode removal method
+    
+    bool m_calDet;         //!< Compute bigmatrix's determinant ?
+    bool m_wSqMatrix;      //!< write a triangular matrix by default (true: square format) ?
+    bool m_writeMat;       //!< write big matrix and vector into files ?
+    bool m_writeMatTxt;    //!< also write big matrix and vector into txt files ?
+    bool m_writeEigenMat;    //!< write eigenvalues and eigenvectors into files ?
+    bool m_writeEigenMatTxt; //!< also write eigenvalues and eigenvectors into txt files ?
+    bool m_writeModuleNames; //!< write module name instead of Identifier to vector file
+
+    bool m_writeHitmap;    //!< write hitmap into file
+    bool m_writeHitmapTxt; //!< write hitmap into text file
+    bool m_readHitmaps;    //!< accumulate hitymap from files
+
+    bool m_writeTFile;    //!< write out files to a root file
+    bool m_readTFiles;    //!< write out files to a root file
+
+    bool m_runLocal;       //!< Run solving using Local method
+
+    double m_scale;        //!< scale for big matrix and vector normalization
+    bool m_scaleMatrix;    //!< scale matrix by number of hits before solving
+    
+    float m_matVersion;    //!< version of matrix format (based on m_stdUnits and m_angleUnit)
+    float m_vecVersion;    //!< version of vector format (based on m_stdUnits and m_angleUnit)
+
+    double  m_softEigenmodeCut; //!< add constant to diagonal to effectively cut on weak eigenmodes
+
+    bool m_removeSpurious; //!< run spurious removal
+
+    bool m_calculateFullCovariance; //?< calculate full covariance matrix for Lapack
+
+    std::string m_pathbin;      //!< path binary files (in/out)
+    std::string m_pathtxt;      //!< path ascii files (in/out)
+    std::string m_prefixName;   //!< prefix string to filenames
+
+    std::string m_tfileName;   //!< prefix string to filenames
+
+
+    std::string m_scalaMatName;       //!< Scalapack matrix name
+    std::string m_scalaVecName;       //!< Scalapack vector name
+
+
+
+    std::vector<std::string> m_inputMatrixFiles; //!< input binary files containing matrix terms
+    std::vector<std::string> m_inputVectorFiles; //!< input binary files containing vector terms
+
+    std::vector<std::string> m_inputHitmapFiles; //!< input binary files containing the hitmaps
+
+    std::vector<std::string> m_inputTFiles; //!< input binary files containing matrix terms
+
+    std::vector<int> m_activeIndices; //!< vector of indices which pass the min-hits cut
+    int m_aNDoF;                      //!< number of active DoF (size of m_activeIndices)
+
+    int m_maxReadErrors;	//!< maximum number of reading TFile errors 
+
+  }; // end of class
+  
+  
+
+} // End of namespace 
+
+
+
+#endif // TRKALIGNGENTOOLS_MATRIXTOOL_H
+
+
+
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/ShiftingDerivCalcTool.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/ShiftingDerivCalcTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..f53021f0f7bb9797cca055aa73521ad5a85d2ce5
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/ShiftingDerivCalcTool.h
@@ -0,0 +1,173 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRK_SHIFTINGDERIVCALCTOOL_H
+#define TRK_SHIFTINGDERIVCALCTOOL_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include "TrkEventPrimitives/ParamDefs.h"
+#include "TrkEventPrimitives/ParticleHypothesis.h"
+
+#include "TrkAlignInterfaces/IDerivCalcTool.h"
+
+
+#include <vector>
+#include <map>
+
+/** @file ShiftingDerivCalcTool.h
+    @class ShiftingDerivCalcTool
+
+    @brief Tool used to calculate total derivatives of residuals w.r.t. 
+    alignment parameters by shifting chambers in various directions, 
+    refitting tracks, and determining chi2 vs. chamber positions.  This 
+    is used to calculate first derivatives.
+    
+    @author Robert Harrington <roberth@bu.edu>
+    @date 1/5/08
+*/
+
+class TGraph;
+
+namespace Trk {
+
+  class TrackStateOnSurface;
+  class Track;
+  class IGlobalTrackFitter;
+  //class ITrackFitter;
+  class IAlignResidualCalculator;
+  class AlignModule;
+  class AlignTSOS;
+  class AlignTrack;
+  class AlignPar;
+  class IAlignModuleTool;
+
+  class ShiftingDerivCalcTool : virtual public IDerivCalcTool, public AthAlgTool {
+
+  public:
+    ShiftingDerivCalcTool(const std::string& type, const std::string& name,
+                           const IInterface* parent);
+    virtual ~ShiftingDerivCalcTool();
+
+    StatusCode initialize();
+    StatusCode finalize();
+
+    /** sets derivatives of residuals w.r.t. alignment parameters for hits on track.*/
+    bool setDerivatives(AlignTrack* track);
+
+    void showStatistics() {}
+
+    /** sets residual covariance matrix */
+    bool setResidualCovMatrix(AlignTrack* alignTrack) const;
+
+  protected:
+
+    // protected typedefs
+    typedef std::vector<Amg::VectorX> HitDerivative;
+    typedef std::map<const TrackStateOnSurface*,HitDerivative*> DerivativeMap;
+    typedef DerivativeMap::value_type DerivativePair;
+    
+    // protected methods
+    Amg::VectorX getDerivatives(AlignTrack* alignTrack, 
+                                int ipar, const AlignPar* alignPar,
+                                Amg::VectorX& derivativeErr, bool& resetIPar,
+                                double& actualSecondDerivative);
+
+    void   setChi2VAlignParam(const AlignTrack* alignTrack, 
+                              const AlignModule* module,
+                              int nshifts=0);
+    void   deleteChi2VAlignParam();
+
+    double shiftSize(const AlignPar* alignPar) const;
+    bool   setUnshiftedResiduals(AlignTrack* alignTrack);
+
+  private:
+    // private methods
+    const Trk::Track* bestPerigeeTrack(const Track* track) const;
+    bool scanShifts(const AlignTrack* alignTrack, 
+    const std::vector<const AlignModule*>& alignModules);
+
+    bool getAllDerivatives(AlignTrack* alignTrack, const AlignModule* alignModule,
+                           std::vector<Amg::VectorX>& deriv_vec,
+                           std::vector<Amg::VectorX>& derivErr_vec,
+                           std::vector<double>& actualsecderiv_vec,
+                           bool& resetIPar);
+
+    // private variables
+    ToolHandle<IGlobalTrackFitter> m_trackFitterTool;
+    ToolHandle<IGlobalTrackFitter> m_SLTrackFitterTool;
+    ToolHandle<IGlobalTrackFitter> m_fitter;
+    //ToolHandle<ITrackFitter> m_trackFitterTool;
+    //ToolHandle<ITrackFitter> m_SLTrackFitterTool;
+    //ToolHandle<ITrackFitter> m_fitter;
+    
+    ToolHandle<IAlignResidualCalculator> m_residualCalculator;
+    ToolHandle<IAlignModuleTool> m_alignModuleTool;
+
+    double m_traSize;
+    double m_rotSize;
+
+    bool m_runOutlierRemoval; 
+    ParticleHypothesis m_particleHypothesis;
+
+    int m_particleNumber;
+
+    DerivativeMap m_derivative_map;
+  
+    bool   m_doFits;
+    int    m_nFits;
+    bool   m_doChi2VAlignParamMeasType;
+    int    m_nChamberShifts;
+    bool   m_doResidualPlots;
+    int    m_nIterations;
+
+    Amg::VectorX* m_unshiftedResiduals;
+    Amg::VectorX* m_unshiftedResErrors;
+
+    // stores double** for each module that track passes through
+    std::vector<double**> m_chi2VAlignParamVec;  //!< track chi2[idof][ichambershift]
+    std::vector<double**> m_chi2VAlignParamXVec; //!< chamber shift[idof][ichambershift]
+
+    double** m_tmpChi2VAlignParam;           
+    double** m_tmpChi2VAlignParamX;
+    double*** m_tmpChi2VAlignParamMeasType;
+
+    // stores double*** for each module that track passes through 
+    // (one double** for each TrackState::MeasurementType)
+    std::vector<double***> m_chi2VAlignParamVecMeasType;  //!< track chi2[idof][imeastype][ichambershift]
+
+    double  m_unshiftedTrackChi2; 
+    double* m_unshiftedTrackChi2MeasType;
+
+    double m_trackAlignParamCut; //!< cut on value of track alignment parameter, determined from fit of chi2 vs. align parameters to a quadratic
+
+    bool m_setMinIterations; //!< fit track with AlignModules shifted up and down in each extreme, find the number of iterations fitter uses to converge.  Set this number for all subsequent track refits. 
+
+    int m_maxIter; //!< reject track if exceed maximum number of iterations
+
+    int m_minIter; //!< set minimum number of iterations for first track fits
+
+    bool m_removeScatteringBeforeRefit; //!< flag to remove scattering before refitting track
+
+    int m_ntracksProcessed;           //!< number tracks processed
+    int m_ntracksPassInitScan;        //!< number tracks pass initial scan
+    int m_ntracksPassSetUnshiftedRes; //!< number tracks pass setting unshifted residuals
+    int m_ntracksPassDerivatives;     //!< number tracks pass setting derivatives
+    int m_ntracksPassGetDeriv;        //!< number tracks pass getting derivatives
+    int m_ntracksPassGetDerivSecPass; //!< number tracks pass 2nd pass of getting derivatives
+    int m_ntracksPassGetDerivLastPass; //!< number tracks pass 2nd pass of getting derivatives
+    int m_ntracksFailMaxIter;
+    int m_ntracksFailTrackRefit;
+    int m_ntracksFailAlignParamCut;
+    int m_ntracksFailFinalAttempt;
+
+    bool m_secPass;
+
+  }; // end class
+
+
+} // end namespace
+
+#endif // TRK_SHIFTINGDERIVCALCTOOL_H
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/TrackCollectionProvider.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/TrackCollectionProvider.h
new file mode 100644
index 0000000000000000000000000000000000000000..0d504f5fb218ccae33bf712651d82298956de195
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/TrackCollectionProvider.h
@@ -0,0 +1,46 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRKALIGNGENTOOLS_TRACKCOLLECTIONPROVIDER_H
+#define TRKALIGNGENTOOLS_TRACKCOLLECTIONPROVIDER_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include "TrkAlignInterfaces/ITrackCollectionProvider.h"
+
+/**
+   @file TrackCollectionProvider.h
+   @class TrackCollectionProvider
+   
+   @brief Tool used to get track collection from StoreGate
+
+   @author Robert Harrington <roberth@bu.edu>
+   @date 7/29/2010
+*/
+
+namespace Trk {
+
+  class TrackCollectionProvider : virtual public ITrackCollectionProvider, public AthAlgTool {
+
+  public:
+    TrackCollectionProvider(const std::string & type, const std::string & name, const IInterface * parent);
+    virtual ~TrackCollectionProvider();
+    
+    StatusCode initialize();
+    StatusCode finalize();
+    
+    StatusCode trackCollection(const TrackCollection*& tracks);
+
+  private:
+    std::string m_inputCol;    //!< Name of input track collection
+    
+    int m_nRetrievalErrors;    //!< number of retrieval errors at the beginning of the job
+    int m_maxRetrievalErrors;  //!< maximum allowed number of retrieval errors at the beginning of the job (-1 for infinite)
+    
+  }; // end class
+
+} // end namespace
+
+#endif // TRKALIGNGENTOOLS_TRACKCOLLECTIONPROVIDER_H
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/TrkAlignDBTool.h b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/TrkAlignDBTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..005e052fefd826d097c463f2a1f99bb46b151910
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/TrkAlignGenTools/TrkAlignDBTool.h
@@ -0,0 +1,50 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRKALIGNGENTOOLS_TRKALIGNDBTOOL_H
+#define TRKALIGNGENTOOLS_TRKALIGNDBTOOL_H
+
+/** @file TrkAlignDBTool.h
+    @class TrkAlignDBTool
+
+    @brief AlgTool used to read in from alignment database and to write 
+    parameters to database.
+    
+    @author Robert Harrington <roberth@bu.edu>
+    @date 1/5/08
+*/
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "TrkAlignInterfaces/ITrkAlignDBTool.h"
+
+namespace Trk {
+  
+  class TrkAlignDBTool : virtual ITrkAlignDBTool, public AthAlgTool {
+    
+  public:
+
+    /** Constructor */
+    TrkAlignDBTool(const std::string& type, const std::string& name,
+	       const IInterface* parent);
+    
+    /** Virtual destructor */
+    virtual ~TrkAlignDBTool();
+    
+    /** initialize */
+    StatusCode initialize();
+    
+    /** initialize */
+    StatusCode finalize();
+
+    /** writes alignment paramters to ASCII file */
+    void writeAlignParToAsciiFile() const {}
+    
+  private:
+       
+  }; // end of class
+
+} // end of namespace
+
+
+#endif // TRKALIGNGENTOOLS_TRKALIGNDBTOOL_H
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/cmt/requirements b/Tracking/TrkAlignment/TrkAlignGenTools/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..2acf5a7744c828f74b54a96074a87405cfe83c99
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/cmt/requirements
@@ -0,0 +1,73 @@
+package TrkAlignGenTools
+
+author Robert Harrington <roberth@bu.edu>
+
+public
+use  AtlasPolicy                AtlasPolicy-*                   
+use  AthenaBaseComps            AthenaBaseComps-*               Control
+use  AtlasCLHEP                 AtlasCLHEP-*                    External
+use  AtlasROOT                  AtlasROOT-*                     External
+use  DataModel                  DataModel-*                     Control
+use  GaudiInterface             GaudiInterface-*                External
+use  TrkAlignEvent              TrkAlignEvent-*                 Tracking/TrkAlignment
+use  TrkAlignInterfaces         TrkAlignInterfaces-*            Tracking/TrkAlignment
+use  TrkEventPrimitives         TrkEventPrimitives-*            Tracking/TrkEvent
+use  VxVertex                   VxVertex-*                      Tracking/TrkEvent
+use  TrkFitterUtils             TrkFitterUtils-*                Tracking/TrkFitter
+use  muonEvent                  muonEvent-*                     Reconstruction/MuonIdentification
+use EventPrimitives             EventPrimitives-*               Event
+use GeoPrimitives	              GeoPrimitives-*	                DetectorDescription
+
+private
+use StoreGate                   StoreGate-*                     Control
+use  AtlasDetDescr              AtlasDetDescr-*                 DetectorDescription
+use  EventInfo                  EventInfo-*                     Event
+use  StoreGate                  StoreGate-*                     Control
+use  TrkAlgebraUtils            TrkAlgebraUtils-*               Tracking/TrkAlignment
+use  TrkDetElementBase          TrkDetElementBase-*             Tracking/TrkDetDescr
+use  TrkSurfaces                TrkSurfaces-*                   Tracking/TrkDetDescr
+use  TrkFitterInterfaces        TrkFitterInterfaces-*           Tracking/TrkFitter
+use  TrkExInterfaces            TrkExInterfaces-*               Tracking/TrkExtrapolation
+use  TrkCompetingRIOsOnTrack    TrkCompetingRIOsOnTrack-*       Tracking/TrkEvent
+use  TrkEventUtils              TrkEventUtils-*                 Tracking/TrkEvent
+use  TrkMaterialOnTrack         TrkMaterialOnTrack-*            Tracking/TrkEvent
+use  TrkMeasurementBase         TrkMeasurementBase-*            Tracking/TrkEvent
+use  TrkParameters              TrkParameters-*                 Tracking/TrkEvent
+use  TrkRIO_OnTrack             TrkRIO_OnTrack-*                Tracking/TrkEvent
+use  TrkToolInterfaces          TrkToolInterfaces-*             Tracking/TrkTools
+use  TrkTrack                   TrkTrack-*                      Tracking/TrkEvent
+use  TrkVertexOnTrack           TrkVertexOnTrack-*              Tracking/TrkEvent
+use  TrkVertexFitterInterfaces  TrkVertexFitterInterfaces-*     Tracking/TrkVertexFitter
+use  TrkParticleBase		TrkParticleBase-*		Tracking/TrkEvent	
+use  TrkPseudoMeasurementOnTrack TrkPseudoMeasurementOnTrack-*  Tracking/TrkEvent  
+
+use  InDetBeamSpotService       InDetBeamSpotService-*          InnerDetector/InDetConditions
+
+use Particle                    Particle-*                      Reconstruction
+use StoreGate                   StoreGate-*                     Control
+use MuonRecToolInterfaces       MuonRecToolInterfaces-*         MuonSpectrometer/MuonReconstruction/MuonRecTools
+use MuonSegment                 MuonSegment-*                   MuonSpectrometer/MuonReconstruction/MuonRecEvent
+
+
+apply_tag ROOTGraphicsLibs
+
+#private
+#macro cppdebugflags '$(cppdebugflags_s)'
+#macro_remove componentshr_linkopts "-Wl,-s"
+
+private
+macro_append ROOT_linkopts " -lMinuit -lMatrix"
+
+public
+#library TrkAlignGenTools *.cxx -s=components *.cxx
+#apply_pattern component_library
+apply_pattern dual_use_library files="*.cxx"
+
+apply_pattern declare_python_modules files="*.py"
+
+
+#################################################
+# debug
+# private
+##macro cppdebugflags '$(cppdebugflags_s)'
+##macro_remove componentshr_linkopts "-Wl,-s"
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/doc/mainpage.h b/Tracking/TrkAlignment/TrkAlignGenTools/doc/mainpage.h
new file mode 100644
index 0000000000000000000000000000000000000000..a9a087757d67407aa3a99ca87b85f8c2d88bbf65
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/doc/mainpage.h
@@ -0,0 +1,61 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+@mainpage TrkAlignGenTools
+@author roberth@bu.edu
+@author Daniel Kollar <daniel.kollar@cern.ch>
+
+@section TrkAlignGenToolsIntro Introduction
+
+This package was copied directly from tools in InDetAlignTools and 
+SiGlobalChi2AlignTools.  It contains some tools used to perform alignment 
+of generic detector modules, and virtual interfaces to be inherited by 
+detector-specific tools.
+
+@section TrkAlignGenToolsOverview Class Overview
+  The package contains the following classes:
+  - AlignModuleTool: inherits from IAlignModuleTool, used to handle the
+    list of AlignModules (the alignment geometry) and provide functionality
+    for basic operations/relations between AlignModules, AlignPars, etc. 
+  - AlignTrackPreProcessor: inherits from IAlignTrackPreProcessor, used
+    to create a collection of AlignTracks from a collection of Tracks,
+    performs track selection and allows to refit the tracks
+  - AlignTrackCreator: inherits from IAlignTrackCreator, used to process
+    the Track and add hit information to AlignTrack (residuals, etc.)
+  - AlignTrackDresser: inherits from IAlignTrackDresser, used to add extra
+    information to AlignTrack, needed by the alignment global/local chi2
+    algorithm, calls derivative calculator tool
+  - AnalyticalDerivCalcTool: inherits from IDerivCalcTool, used to calculate
+    derivatives of residuals wrt. alignment parameters needed for global/local
+    chi2 algorithm in analytical way by using information from the track
+    fitter
+  - ShiftingDerivCalcTool: inherits from IDerivCalcTool, used to calculate
+    derivatives of residuals wrt. alignment parameters needed for global/local
+    chi2 algorithm by "shifting" the hit along the DoF and refitting the track
+  - MatrixTool:  inherits from IMatrixTool, used to manipulate matrix and 
+    vector entries and to solve for alignment parameters.
+  - IPCMatrixTool:  inherits from IMatrixTool, used to manipulate matrix and 
+    vector entries in binary format for parallel processing, and to solve for 
+    alignment parameters.
+  - TrkAlignDBTool:  contains tools for reading information needed for 
+    performing alignment and for writing final alignment parameters to the 
+    database 
+
+@ref used_TrkAlignGenTools
+
+@ref requirements_TrkAlignGenTools
+
+*/
+
+/**
+@page used_TrkAlignGenTools Used Packages
+@htmlinclude used_packages.html
+*/
+
+/**
+@page requirements_TrkAlignGenTools Requirements
+@include requirements
+*/
+
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignResidualCalculatorGetter.py b/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignResidualCalculatorGetter.py
new file mode 100644
index 0000000000000000000000000000000000000000..4551aea3ac42fa29801430e8adad455d1c2503a6
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignResidualCalculatorGetter.py
@@ -0,0 +1,73 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+
+## @file:   AlignResidualCalculatorGetter.py
+## @brief:  to instantiate the AlignResidualCalculatorTool 
+## 	      with the default configuration
+## @author: Robert Harrington <roberth@bu.edu>
+## @date:   10/19/2009
+  
+
+from AthenaCommon.Logging import logging
+from RecExConfig.Configured import Configured
+from TrkAlignGenTools.AlignmentFlags import AlignmentFlags
+
+
+## AlignResidualCalculatorGetter creates a public 
+#  AlignResidualCalculator with default options
+#  and adds tool to ToolSvc
+
+class AlignResidualCalculatorGetter ( Configured ) :
+
+    _name = 'AlignResidualCalculatorGetter'
+
+    def configure(self):
+        mlog = logging.getLogger( self._name+'::configure :' )
+        outputLevel = AlignmentFlags.OutputLevel()
+
+        # create tool instance
+        from AthenaCommon.AppMgr import ToolSvc
+        
+        from MuonResidualPullCalculators.MuonResidualPullCalculatorsConf import Muon__TGC_ResidualPullCalculator
+        tgc_respullcalc=Muon__TGC_ResidualPullCalculator("TGC_ResidualPullCalculator")
+                                                         #OutputLevel=outputLevel)
+        ToolSvc += tgc_respullcalc
+        
+        from InDetTrackValidation.InDetTrackValidationConf import InDet__SCT_ResidualPullCalculator
+        sct_respullcalc=InDet__SCT_ResidualPullCalculator()
+        ToolSvc+=sct_respullcalc
+        
+        #from TrkValTools.TrkValToolsConf import Trk__ResidualPullCalculator
+        from TrkResidualPullCalculator.TrkResidualPullCalculatorConf import \
+            Trk__ResidualPullCalculator 
+        resPullCalc = Trk__ResidualPullCalculator("ResidualPullCalculator",
+                                                  #OutputLevel=outputLevel,
+                                                  ResidualPullCalculatorForTGC=tgc_respullcalc,
+                                                  ResidualPullCalculatorForSCT=sct_respullcalc)
+        ToolSvc += resPullCalc
+
+        self._ResidualPullCalculatorHandle = ToolSvc.ResidualPullCalculator
+
+        from TrkAlignGenTools.TrkAlignGenToolsConf import Trk__AlignResidualCalculator
+        resCalc = Trk__AlignResidualCalculator("AlignResidualCalculator",
+                                               OutputLevel = outputLevel,
+                                               ResidualType=0,
+                                               ResidualPullCalculator = resPullCalc,
+                                               IncludeScatterers = AlignmentFlags.includeScatteringResiduals())
+
+        self._AlignResidualCalculatorHandle = resCalc
+
+        mlog.info(" now adding to ToolSvc")
+        ToolSvc += self.AlignResidualCalculatorHandle()
+
+        mlog.info(" leaving configure")
+
+        return True
+
+    ## returns AlignResidualCalculator tool
+    def AlignResidualCalculatorHandle(self):
+        return self._AlignResidualCalculatorHandle
+
+    ## returns ResidualPullCalculator
+    def ResidualPullCalculatorHandle(self):
+        return self._ResidualPullCalculatorHandle
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignTrackCreatorGetter.py b/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignTrackCreatorGetter.py
new file mode 100644
index 0000000000000000000000000000000000000000..7128e085bbc386dc6b6142c4003d21aafb29943d
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignTrackCreatorGetter.py
@@ -0,0 +1,55 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+
+## @file:   AlignTrackCreatorGetter.py
+## @brief:  to instantiate the AlignTrackCreator 
+## 	    with the default configuration
+## @author: Robert Harrington <roberth@bu.edu>
+## @date:   10/19/2009
+
+from AthenaCommon.Logging import logging
+from RecExConfig.Configured import Configured
+from TrkAlignGenTools.AlignmentFlags import AlignmentFlags as align
+
+## AlignTrackCreatorGetter creates AlignTrackCreator but 
+#  but does not add to ToolSvc, so it must be used as a 
+#  private tool or added to the ToolSvc by the user
+class AlignTrackCreatorGetter ( Configured ) :
+  
+  _name = 'AlignTrackCreatorGetter'
+
+  def configure(self):
+    mlog = logging.getLogger( self._name+'::configure :' )
+            
+    # create tool instance
+    from TrkAlignGenTools.AlignResidualCalculatorGetter import AlignResidualCalculatorGetter
+    resCalc = AlignResidualCalculatorGetter().AlignResidualCalculatorHandle()
+
+    from TrkAlignGenTools.TrkAlignGenToolsConf import Trk__AlignTrackCreator
+    alignTrackCreator=Trk__AlignTrackCreator("AlignTrackCreator",
+                                             OutputLevel = align.OutputLevel(),
+                                             ResidualCalculator = resCalc,
+                                             IncludeScatterers = align.includeScatterers(),
+                                             RemoveATSOSNotInAlignModule = align.removeATSOSNotInAlignModule(),
+                                             RequireOverlap = align.requireOverlap())                
+
+    # options for good event list
+    if align.writeEventList() : 
+        from TrkAlignGenTools.AlignmentIOFiles import AlignmentIOFiles
+        alignIO = AlignmentIOFiles()
+        alignTrackCreator.EventList = "goodEvts.txt" 
+        alignTrackCreator.WriteEventList = True
+
+    self._AlignTrackCreatorHandle = alignTrackCreator
+
+    #mlog.info(" now adding to ToolSvc")
+    #from __main__ import ToolSvc 
+    #ToolSvc += self.AlignTrackCreatorHandle()
+    
+    mlog.info(" leaving configure")
+    
+    return True
+  
+  ## returns AlignTrackCreator tool 
+  def AlignTrackCreatorHandle(self):
+    return self._AlignTrackCreatorHandle
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignTrackDresserGetter.py b/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignTrackDresserGetter.py
new file mode 100644
index 0000000000000000000000000000000000000000..a3d0e0df00e82875a4c1ec892e6b5c133a380a63
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignTrackDresserGetter.py
@@ -0,0 +1,64 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+
+## @file:   AlignTrackDresserGetter.py
+## @brief:  to instantiate the AlignTrackDresser
+## 	    with the default configuration
+## @author: Robert Harrington <roberth@bu.edu>
+## @date:   10/19/2009
+
+from AthenaCommon.Logging import logging
+from RecExConfig.Configured import Configured
+from TrkAlignGenTools.AlignmentFlags import AlignmentFlags
+
+## AlignTrackDresserGetter creates an AlignTrackDresser
+#  but does not add to ToolSvc, so user has to use as a
+#  private or add to ToolSvc as public tool
+class AlignTrackDresserGetter ( Configured ) :
+  
+  _name = 'AlignTrackDresserGetter'
+
+  def configure(self):
+    mlog = logging.getLogger( self._name+'::configure :' )
+            
+    # create tool instance
+    from TrkAlignGenTools.TrkAlignGenToolsConf import Trk__AlignTrackDresser
+    alignTrackDresser=Trk__AlignTrackDresser("AlignTrackDresser",
+                                             OutputLevel = AlignmentFlags.OutputLevel(),
+                                             DerivCalcTool = self.derivativeCalcTool())
+
+    self._AlignTrackDresserHandle = alignTrackDresser
+    
+    #mlog.info(" now adding to ToolSvc")
+    #from __main__ import ToolSvc 
+    #ToolSvc += self.AlignTrackDresserHandle()
+    
+    mlog.info(" leaving configure")
+    
+    return True
+  
+  ## returns AlignTrackDresser
+  def AlignTrackDresserHandle(self):
+    return self._AlignTrackDresserHandle
+
+  ## returns derivative calculator owned by AlignTrackDresser.  If it does
+  #  exist, creates new one based on AlignmentFlags.
+  def derivativeCalcTool(self):
+    try: 
+      self._derivCalcTool
+    except:
+      derivativeType = AlignmentFlags.derivativeType()
+      if derivativeType == 'Analytical' :      
+        from TrkAlignGenTools.TrkAlignGenToolsConf import Trk__AnalyticalDerivCalcTool
+        self._derivCalcTool = Trk__AnalyticalDerivCalcTool("AnalyticalDerivCalcTool",
+                                                           OutputLevel=AlignmentFlags.OutputLevel())
+      elif derivativeType == 'Numerical' :
+        from TrkAlignGenTools.ShiftingDerivCalcToolGetter import ShiftingDerivCalcToolGetter
+        self._derivCalcTool = ShiftingDerivCalcToolGetter().ShiftingDerivCalcToolHandle()
+      else:
+        print "bad option!"
+    print "have derivCalcTool"
+    return self._derivCalcTool
+
+
+
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignmentFlags.py b/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignmentFlags.py
new file mode 100644
index 0000000000000000000000000000000000000000..468b2cfe55003a3b9d0d3a85d0bf88497b8aa1bd
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignmentFlags.py
@@ -0,0 +1,402 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+## @file:   AlignmentFlags.py
+## @brief:  Flags specific to alignment, inherit from 
+## 	    JobProperty
+## @author: Robert Harrington <roberth@bu.edu>
+## @date:   10/19/2009
+
+__author__ = 'Robert Harrington'
+__version__ = ""
+__doc__ = "Alignment specific flags"
+
+from AthenaCommon.JobProperties import JobProperty, JobPropertyContainer, jobproperties
+from AthenaCommon.Logging import logging
+from AthenaCommon.Constants import *
+
+mlog = logging.getLogger( 'AlignmentFlags.py' )
+
+_flags = []
+
+# Define default flags
+class derivativeType(JobProperty):
+    """ a flag to determine type of derivatives """
+    statusOn = True
+    allowedType=['string']
+    StoredValue='Analytical'
+    allowedValues = [ 'Analytical', 'Numerical' ]
+_flags.append(derivativeType)
+
+class alignMS(JobProperty):
+    """ flag to determine whether to align MS or not """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = True 
+_flags.append(alignMS)
+
+class alignID(JobProperty):
+    """ flag to determine whether to align ID  or not """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = True 
+_flags.append(alignID)
+
+class alignmentType(JobProperty):
+    """ flag to determine type of alignment """
+    statusOn = True
+    allowedType = ['string']
+    StoredValue = 'GlobalChi2'
+    allowedValues = [ 'GlobalChi2' , 'LocalChi2' ]
+_flags.append(alignmentType)
+
+class alignmentLevel(JobProperty):
+    """ a flag to determine alignment level """
+    statusOn=True
+    allowedType=['int']
+    StoredValue = 3
+    allowedValues = [ 0, 1, 2, 3, 23 ]
+_flags.append(alignmentLevel)
+
+class dataType(JobProperty):
+    """ type of data (if changed, don't forget to change isMC() below"""
+    statusOn = True
+    allowedType = ['string']
+    StoredValue = 'MC'
+    allowedValues = [ 'MC', 'data', 'cosmic', 'simCosmic' ]
+
+_flags.append(dataType)
+    
+class inputTrkCol(JobProperty):
+    """ input track collection name """
+    statusOn = True
+    allowedType = ['string']
+    StoredValue = 'MooreTracks'
+_flags.append(inputTrkCol)
+
+class iteration(JobProperty):
+    """ flag to indicate the iteration number """
+    statusOn = True
+    allowedType = ['int']
+    StoredValue = 0
+_flags.append(iteration)
+
+class jobIndex(JobProperty):
+    """ flag to indicate the index of the job (e.g. when running in batch) """
+    statusOn = True
+    allowedType = ['int']
+    StoredValue = -1
+_flags.append(jobIndex)
+
+class useSLFitter(JobProperty):
+    """ flag to determine whether to use SL fitter to fit straight tracks """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = False
+_flags.append(useSLFitter)
+
+class includeScatterers(JobProperty):
+    """ flag to determine whether to include scatterers as AlignTSOS on AlignTrack """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = False
+_flags.append(includeScatterers)
+
+class includeScatteringResiduals(JobProperty):
+    """ flag to determine whether to include contributions to chi2 from 
+    scattering centers """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = False
+_flags.append(includeScatteringResiduals)
+
+class runOutlierRemoval(JobProperty):
+    """ flag to run outlier removal in track refitting """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = False
+_flags.append(runOutlierRemoval)
+
+class refitTracks(JobProperty):
+    """ flag to refit tracks """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = True
+_flags.append(refitTracks)
+
+class particleNumber(JobProperty):
+    """ flag to indicate particle number (see TrkEventPrimitives::ParticleHypothesis) """
+    statusOn = True
+    allowedType = ['int']
+    StoredValue = 0
+    allowedValues = [ 0, # non-interacting or geantino
+                      2, # muon
+                      99 # undefined
+                      ]
+_flags.append(particleNumber)
+
+class OutputLevel(JobProperty):
+    """ General msg output level VERBOSE DEBUG INFO """ 
+    statusOn=True
+    allowedTypes=['int']
+    allowedValues=[ ALL,VERBOSE,DEBUG,INFO,WARNING,ERROR,FATAL ]
+    StoredValue=INFO
+_flags.append(OutputLevel)
+    
+class fitterType(JobProperty) :
+    """ type of track fitter used to refit tracks for alignment """
+    statusOn = True
+    allowedType=['string']
+    allowedValues = [ 'GlobalChi2', 'MCTB', 'iPat', 'CombMuonTrackFitter' ]
+    StoredValue = 'GlobalChi2'
+_flags.append(fitterType)
+
+class fileRootName(JobProperty) :
+    """ root name used for file names """
+    statusOn = True
+    allowedType = ['string']
+    StoredValue = ""
+_flags.append(fileRootName)
+
+class outputPath(JobProperty) :
+    """ output path """
+    statusOn = True
+    allowedType = ['string']
+    StoredValue = ""
+_flags.append(outputPath)
+
+class readEventList(JobProperty) :
+    """ flag to read run and event numbers from ASCII file for event selection """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = False
+_flags.append(readEventList)
+
+class writeEventList(JobProperty) :
+    """ flag to write run and event numbers to ASCII file after event selection """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = True
+_flags.append(writeEventList)
+
+class eventList(JobProperty) :
+    """ name of file containing run/event numbers of good events """
+    statusOn = True
+    allowedType = ['string']
+    StoredValue = ""
+_flags.append(eventList)
+
+class writeNtuple(JobProperty) :
+    """ flag to require writing ntuple"""
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = True
+_flags.append(writeNtuple)
+
+class ntupleFileName(JobProperty) :
+    """ name of ntuple file """
+    statusOn = True
+    allowedType = ['string']
+    StoredValue = "Align.root"
+_flags.append(ntupleFileName)
+
+class ntupleFilePath(JobProperty) :
+    """ name of ntuple file path """
+    statusOn = True
+    allowedType = ['string']
+    StoredValue = "./"
+_flags.append(ntupleFilePath)
+
+class requireOverlap(JobProperty) :
+    """ flag to require tracks passing through more than one AlignModule (used in AlignTrackCreator) """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = False
+_flags.append(requireOverlap)
+
+class removeATSOSNotInAlignModule(JobProperty) :
+    """ flag to remove ATSOS not in AlignModule in AlignTrackCreator """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = True
+_flags.append(removeATSOSNotInAlignModule)
+
+# flags for MatrixTool
+class useSparseMatrix(JobProperty) :
+    """ flag to use sparse matrix in MatrixTool """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = False
+_flags.append(useSparseMatrix)
+
+class matrixToolSolveOption(JobProperty) :
+    """ flag to determine solving option in MatrixTool """
+    statusOn = True
+    allowedType = ['int']
+    StoredValue = 3
+    allowedValues = [ 0, # NONE (for batch jobs)
+                      3, # DIRECT_SOLVE
+                      4, # DIRECT_SOLVE_FAST
+                      6] # SOLVE_ROOT
+_flags.append(matrixToolSolveOption) 
+
+class writeMatrix(JobProperty) :
+    """ flag to write matrix and vector to binary and text files """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = True
+_flags.append(writeMatrix)
+
+class writeEigenMatrices(JobProperty) :
+    """ flag eigenvalue matrices to files """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = False
+_flags.append(writeEigenMatrices)
+
+class writeModuleNames(JobProperty) :
+    """ write module names to vector files """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = False
+_flags.append(writeModuleNames)
+
+class weakModeToRemove(JobProperty) :
+    """used for weak mode removal in matrix solving """
+    statusOn = True
+    allowedType = ['int']
+    StoredValue = -1 # default does nothing
+_flags.append(weakModeToRemove)
+
+class softEigenmodeCut(JobProperty) :
+    """ flag used to cut on soft eigenmodes """
+    statusOn = True
+    allowedType = ['Double']
+    StoredValue = 0.0
+_flags.append(softEigenmodeCut)
+
+class secondDerivativeCut(JobProperty) :
+    """ cut on second derivative (used in GlobalChi2AlignTool) """
+    statusOn = True
+    allowedType = ['Double']
+    StoredValue = 0.0
+_flags.append(secondDerivativeCut)
+
+class trackAlignParamCut(JobProperty) :
+    """ cut used on track alignment parameter quality variable (algorithm-specific) """
+    statusOn = True
+    allowedType = ['Double']
+    StoredValue = 1e6
+_flags.append(trackAlignParamCut)
+
+class setMinIterations(JobProperty) :
+    """ used for numerical derivatives.  Track fitter required to perform a minimum number of iterations."""
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = False
+_flags.append(setMinIterations)
+
+class runLocalMethod(JobProperty) :
+    """ flag to run local solving before global """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = True
+_flags.append(runLocalMethod)
+
+class runCLHEPDiagonalize(JobProperty) :
+    """ flag to run diagonalization when using CLHEP solving """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = True
+_flags.append(runCLHEPDiagonalize)
+
+class minNumHitsPerModule(JobProperty) :
+    """ flag to set minimum number of hits per align module """
+    statusOn = True
+    allowedType = ['int']
+    StoredValue = 0
+_flags.append(minNumHitsPerModule)
+
+class minNumTrksPerModule(JobProperty) :
+    """ flag to set minimum number of tracks per align module """
+    statusOn = True
+    allowedType = ['int']
+    StoredValue = 0
+_flags.append(minNumTrksPerModule)
+
+class writeHitmap(JobProperty) :
+    """ flag to write a binary file containing number of hits in each module """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = True
+_flags.append(writeHitmap)
+
+class writeHitmapTxt(JobProperty) :
+    """ flag to write a text file containing number of hits in each module """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = True
+_flags.append(writeHitmapTxt)
+
+class readHitmaps(JobProperty) :
+    """ flag to read binary file containing number of hits in each module """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = True
+_flags.append(readHitmaps)
+
+class inputHitmapFiles(JobProperty) :
+    """ list of input hitmap files """
+    statusOn = True
+    allowedType = ['list']
+    StoredValue = []
+_flags.append(inputHitmapFiles)
+
+class inputMatrixFiles(JobProperty) :
+    """ list of input matrix files """
+    statusOn = True
+    allowedType = ['list']
+    StoredValue = []
+_flags.append(inputMatrixFiles)
+
+class inputVectorFiles(JobProperty) :
+    """ list of input vector files """
+    statusOn = True
+    allowedType = ['list']
+    StoredValue = []
+_flags.append(inputVectorFiles)
+
+class solveOnly(JobProperty) :
+    """ flag to do solving only """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = False
+_flags.append(solveOnly)
+
+class scaleMatrix(JobProperty) :
+    """ flag to scale matrix and vector before solving """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = False
+_flags.append(scaleMatrix)
+
+class doVP1(JobProperty) :
+    """ flag to run VP1 algorithm """
+    statusOn = True
+    allowedType = ['bool']
+    StoredValue = False
+_flags.append(doVP1)
+
+class Align(JobPropertyContainer):
+    """ The alignment flag/job property container """
+
+    def isMC(self):
+        val=self.dataType()
+        return val=='MC' or val=='simCosmic'
+
+jobproperties.add_Container(Align)
+
+for flag in _flags:
+    jobproperties.Align.add_JobProperty(flag)
+del _flags
+
+AlignmentFlags = jobproperties.Align
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignmentIOFiles.py b/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignmentIOFiles.py
new file mode 100644
index 0000000000000000000000000000000000000000..1a596f42cfd6bfabaf98664dc98988f9db612745
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignmentIOFiles.py
@@ -0,0 +1,57 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+
+## @file:   AlignmentIOFiles.py
+## @brief:  Used inside Athena for alignment to get various 
+## 	    files for input and output.
+## @author: Robert Harrington <roberth@bu.edu>
+## @date:   10/19/2009
+
+from AthenaCommon.Logging import logging
+from TrkAlignGenTools.AlignmentFlags import AlignmentFlags as align
+
+## AlignmentIOFiles provides methods for getting file names used 
+#  for alignment.
+class AlignmentIOFiles () :
+
+    _rootNameBase = ""
+    _rootName = ""
+    _evtList = ""
+    _matrixPath = ""
+
+    ## constructor
+    def __init__(self):
+        mlog = logging.getLogger( 'AlignmentIOFiles::__init__' )
+
+    ## filename containing list of good events 
+    #  (each line is run and event number)
+    def eventList(self, append="") :
+        if self._evtList == "" :            
+            self._evtList = "goodEvts_" + self.rootName() + ".txt"
+        return self._evtList
+
+    ## binary version of matrix files
+    def matrixPathBin(self, append="") : 
+        if self._matrixPath == "" :
+            self._matrixPath = "matrix_" + self.rootName()
+        return self._matrixPath + ".bin"
+
+    ## text version of matrix files
+    def matrixPathTxt(self, append="") : 
+        if self._matrixPath == "" :
+            self._matrixPath = "matrix_" + self.rootName()
+        return self._matrixPath + ".txt"
+
+    ## root name used in creating all file names
+    def rootName(self,append="") :
+        if self._rootName == "" :
+            self._rootName = self.rootNameBase()+"_iter"+str(align.iteration())
+        return self._rootName
+
+    ## root name without iteration
+    def rootNameBase(self,append="") :
+        if self._rootNameBase == "" :
+            self._rootNameBase = align.fileRootName()
+            if append != "":
+                self._rootNameBase = self._rootNameBase + "_" + append
+        return self._rootNameBase
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignmentTrackFitter.py b/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignmentTrackFitter.py
new file mode 100644
index 0000000000000000000000000000000000000000..1fc9065b4e0fe39ee0ca88bb40fb3f7b05f23ba2
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/python/AlignmentTrackFitter.py
@@ -0,0 +1,193 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+
+## @file:   AlignTrackFitter.py
+## @brief:  Used to create and configure the track fitter for alignment.
+## @author: Robert Harrington <roberth@bu.edu>
+## @date:   10/19/2009
+
+from AthenaCommon.Logging import logging
+from TrkAlignGenTools.AlignmentFlags import AlignmentFlags as align
+from GaudiKernel.Constants import *
+
+## AlignmentTrackFitter determines which type of fitter and configuration to 
+#  use based on AlignmentFlags and creates the fitter 
+class AlignmentTrackFitter () :
+
+    _nInitialized = 0
+
+    ## constructor
+    def __init__(self):
+        mlog = logging.getLogger( 'AlignmentTrackFitter::__init__' )
+        self._nInitialized += 1
+        if self._nInitialized == 1:
+            mlog.debug(" : First instance->configure()" )
+        else:
+            mlog.debug("already initialized" )
+            return
+        
+        fitterType = align.fitterType()
+        if fitterType == 'iPat' :
+            self.set_iPatFitter()
+        elif fitterType == 'GlobalChi2' :
+            self.setGlobalChi2Fitter()
+        elif fitterType == 'MCTB' :
+            self.setMCTBFitter()
+        elif fitterType == 'CombMuonTrackFitter' :
+            self.setCombMuonTrackFitter()
+        else: 
+            mlog.warning("no fitter!")
+            return
+        
+    ## set CombMuonTrackFitter
+    def setCombMuonTrackFitter(self) :
+        mlog = logging.getLogger( 'AlignmentTrackFitter::setCombMuonTrackFitter' )
+        from AthenaCommon.Include import include
+        include('MuonCombinedRecExample/CombinedMuonFitTools.py') 
+        
+        from AthenaCommon.AppMgr import ToolSvc
+        ToolSvc.MuonCombinedTrackFitter.FillDerivativeMatrix=True 
+
+        self._fitter = ToolSvc.MuonCombinedTrackFitter
+        self._fitter.OutputLevel = align.OutputLevel()
+
+        if align.useSLFitter() :
+            mlog.warning("SL Fitter set to default (curved) fitter!")
+            self._slfitter = ToolSvc.MuonCombinedTrackFitter
+
+        #self._fitter.OutputLevel = VERBOSE
+
+        #self._fitter.GetMaterialFromTrack = True
+        #self._fitter.MboyMat = False
+        #self._fitter.FillDerivativeMatrix = True
+        #self._fitter.MaxIterations = 50
+
+    ## set global chi2 fitter
+    def setGlobalChi2Fitter(self) :
+        mlog = logging.getLogger( 'AlignmentTrackFitter::setGlobalChi2Fitter' )
+        from AthenaCommon.AppMgr import ToolSvc
+        from TrkGlobalChi2Fitter.TrkGlobalChi2FitterConf import Trk__GlobalChi2Fitter
+        Fitter = Trk__GlobalChi2Fitter()
+        ToolSvc += Fitter
+        self._fitter = Fitter
+        if align.useSLFitter() :
+            mlog.warning("SL Fitter set to default (curved) fitter!")
+            self._slfitter = Fitter
+
+    ## set iPatFitter
+    def set_iPatFitter(self) :
+        from AthenaCommon.AppMgr import ToolSvc        
+        from MuonRecExample import MuonRecTools
+        MuonExtrapolator  = MuonRecTools.getPublicTool('MuonExtrapolator')
+        
+        from AthenaCommon.Include import include
+        include('TrkDetDescrSvc/AtlasTrackingGeometrySvc.py')
+        
+        # set up the extrapolator and fitter as used by Muid
+        from TrkExRungeKuttaIntersector.TrkExRungeKuttaIntersectorConf import \
+            Trk__IntersectorWrapper as Propagator
+        MuidPropagator = Propagator(name = 'MuidPropagator')
+        ToolSvc += MuidPropagator
+        
+        from TrkExTools.TrkExToolsConf import Trk__MaterialEffectsUpdator
+        MuidMaterialUpdator = Trk__MaterialEffectsUpdator(name = "MuidMaterialEffectsUpdator")
+        ToolSvc += MuidMaterialUpdator
+        
+        from AthenaCommon.AppMgr import ServiceMgr as svcMgr
+        from TrkExTools.TrkExToolsConf import Trk__Navigator
+        MuidNavigator = Trk__Navigator(name                = 'MuidNavigator',
+                                       TrackingGeometrySvc = svcMgr.AtlasTrackingGeometrySvc)
+        ToolSvc += MuidNavigator
+        
+        
+        from TrkExTools.TrkExToolsConf import Trk__Extrapolator
+        MuidExtrapolator = Trk__Extrapolator( 
+            name = 'MuidExtrapolator', 
+            Propagators = [ MuidPropagator ],
+            MaterialEffectsUpdators = [ MuidMaterialUpdator ],
+            Navigator=MuidNavigator)
+        ToolSvc += MuidExtrapolator
+        
+        # material allocation
+        from TrkiPatFitter.TrkiPatFitterConf import Trk__MaterialAllocator
+        MuidMaterialAllocator = Trk__MaterialAllocator(
+            name                      = 'MuidMaterialAllocator',
+            AggregateMaterial         = True,
+            Extrapolator              = MuidExtrapolator,
+            SpectrometerExtrapolator  = MuonExtrapolator,
+            TrackingGeometrySvc       = svcMgr.AtlasTrackingGeometrySvc)
+        ToolSvc += MuidMaterialAllocator
+        
+        
+        from TrkiPatFitter.TrkiPatFitterConf import Trk__iPatGlobalFitter
+        Fitter = Trk__iPatGlobalFitter(
+            name='iPatGlobalFitter',
+        #from TrkiPatFitter.TrkiPatFitterConf import Trk__iPatFitter
+        #Fitter = Trk__iPatFitter(
+        #    name='iPatFitter',
+            AggregateMaterial       = True,
+            AsymmetricCaloEnergy    = False,
+            FullCombinedFit         = True,
+            MaterialAllocator       = MuidMaterialAllocator,         
+            OutputLevel = align.OutputLevel())
+            #OutputLevel = VERBOSE)
+        
+        ToolSvc += Fitter    
+        self._fitter = ToolSvc.iPatGlobalFitter
+        #self._fitter = ToolSvc.iPatFitter
+        
+        if align.useSLFitter() :
+            SLFitter = Trk__iPatGlobalFitter(
+                name                    = 'iPatGlobalSLFitter',
+            #SLFitter = Trk__iPatFitter(
+            #    name                    = 'iPatSLFitter',
+                AggregateMaterial       = True,
+                FullCombinedFit         = True,
+                LineFit                 = True,
+                MaterialAllocator       = MuidMaterialAllocator,
+                OutputLevel = align.OutputLevel())
+            ToolSvc += SLFitter
+            self._slfitter = ToolSvc.iPatGlobalSLFitter
+            #self._slfitter = ToolSvc.iPatSLFitter
+        
+    ## creates MCTBFitter (for standalone muon tracks)
+    def setMCTBFitter (self) :
+
+        from AthenaCommon.AppMgr import ToolSvc
+
+        # this assumes that MCTBFitter has already been set
+        from MuonRecExample import MuonRecTools
+        #ToolSvc.MCTBFitter.OutputLevel = align.OutputLevel()
+        #ToolSvc.MCTBSLFitter.OutputLevel = align.OutputLevel()
+
+        MCTBFitter = MuonRecTools.getPublicToolClone("myMCTBFitter","MCTBFitterMaterialFromTrack")
+        MCTBFitter.FillDerivativeMatrix = True
+        MCTBFitter.OutputLevel = align.OutputLevel()
+        #MCTBFitter.OutputLevel = VERBOSE
+        #MCTBFitter.GetMaterialFromTrack = True
+        #MCTBFitter.PrintDerivatives = True
+        ToolSvc += MCTBFitter
+        self._fitter = ToolSvc.myMCTBFitter
+        
+        if align.useSLFitter() :
+            MCTBSLFitter = MuonRecTools.getPublicToolClone("myMCTBSLFitter","MCTBSLFitterMaterialFromTrack")
+            MCTBSLFitter.FillDerivativeMatrix = True
+            MCTBSLFitter.OutputLevel = align.OutputLevel()
+            #MCTBSLFitter.OutputLevel = VERBOSE
+            #MCTBSLFitter.GetMaterialFromTrack = True
+            ##rdh MCTBSLFitter.Momentum = 0
+            #MCTBSLFitter.PrintDerivatives = True
+            ToolSvc += MCTBSLFitter
+            self._slfitter = ToolSvc.myMCTBSLFitter
+
+    ## returns fitter
+    def fitter (self) :
+              return self._fitter
+          
+    ## returns straight-line version of fitter
+    def slfitter (self) :
+        if align.useSLFitter() :
+            return self._slfitter
+        else:
+            return
+        
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/python/MatrixToolGetter.py b/Tracking/TrkAlignment/TrkAlignGenTools/python/MatrixToolGetter.py
new file mode 100644
index 0000000000000000000000000000000000000000..966f83e8304714616054a56b7070d37e7fb34657
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/python/MatrixToolGetter.py
@@ -0,0 +1,63 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+
+## @file:   MatrixToolGetter.py
+## @brief:  to instantiate the MatrixTool
+## 	    with the default configuration
+## @author: Robert Harrington <roberth@bu.edu>
+## @date:   10/19/2009
+
+from AthenaCommon.Logging import logging
+from RecExConfig.Configured import Configured
+from TrkAlignGenTools.AlignmentFlags import AlignmentFlags as align
+
+## MatrixToolGetter configures the MatrixTool with the default
+#  configuration but does not add to ToolSvc.  User must add as a 
+#  private tool or add to ToolSvc.
+class MatrixToolGetter ( Configured ) :
+  
+  _name = 'MatrixToolGetter'
+
+  ## create and configure MatrixTool
+  def configure(self):
+    mlog = logging.getLogger( self._name+'::configure :' )
+
+    # create tool instance
+    from TrkAlignGenTools.TrkAlignGenToolsConf import Trk__MatrixTool
+    matrixTool = Trk__MatrixTool("MatrixTool",
+                                 OutputLevel = align.OutputLevel())
+    matrixTool.UseSparse          = align.useSparseMatrix()
+    matrixTool.SolveOption        = align.matrixToolSolveOption()
+    matrixTool.WriteMat           = align.writeMatrix()
+    matrixTool.WriteEigenMat      = align.writeEigenMatrices()
+    matrixTool.WriteModuleNames   = align.writeModuleNames()
+    matrixTool.ModCut             = align.weakModeToRemove()
+    matrixTool.SoftEigenmodeCut   = align.softEigenmodeCut()
+    matrixTool.ScaleMatrix        = align.scaleMatrix()
+    matrixTool.RunLocalMethod     = align.runLocalMethod()
+    matrixTool.Diagonalize        = align.runCLHEPDiagonalize()
+    matrixTool.MinNumHitsPerModule = align.minNumHitsPerModule()
+    matrixTool.MinNumTrksPerModule = align.minNumTrksPerModule()
+    matrixTool.WriteHitmap        = align.writeHitmap()
+    matrixTool.WriteHitmapTxt     = align.writeHitmapTxt()
+    matrixTool.ReadHitmaps        = align.readHitmaps()
+    if align.inputHitmapFiles()!=[]:
+      matrixTool.InputHitmapFiles   = align.inputHitmapFiles()
+    if align.inputMatrixFiles()!=[]:
+      matrixTool.InputMatrixFiles   = align.inputMatrixFiles()
+    if align.inputHitmapFiles()!=[]:
+      matrixTool.InputVectorFiles   = align.inputVectorFiles()
+
+    self._matrixToolHandle = matrixTool
+    
+    #mlog.info(" now adding to ToolSvc" )
+    #from __main__ import ToolSvc
+    #ToolSvc += self.MatrixToolHandle()
+
+    mlog.info(" leaving configure")
+
+    return True
+
+  ## return handle to MatrixTool
+  def MatrixToolHandle(self):
+      return self._matrixToolHandle
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/python/ShiftingDerivCalcToolGetter.py b/Tracking/TrkAlignment/TrkAlignGenTools/python/ShiftingDerivCalcToolGetter.py
new file mode 100644
index 0000000000000000000000000000000000000000..7403dfe4e6fcbaad376674b95f531bd4da9a5cb5
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/python/ShiftingDerivCalcToolGetter.py
@@ -0,0 +1,62 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+
+## @file:   ShiftingDerivCalcToolGetter.py
+## @brief:  to instantiate the ShiftingDerivCalcToolDresser
+## 	    with the default configuration
+## @author: Robert Harrington <roberth@bu.edu>
+## @date:   10/19/2009
+
+from AthenaCommon.Logging import logging
+from RecExConfig.Configured import Configured
+from TrkAlignGenTools.AlignmentFlags import AlignmentFlags
+from MuonAlignGenTools.MuonAlignmentFlags import MuonAlignmentFlags as mualign
+
+## ShiftingDerivCalcToolGetter creates and configures the 
+#  ShiftingDerivCalcTool with default parameters.  The tool 
+#  is not added to ToolSvc so user must use it as a private 
+#  tool or add to ToolSvc as a public tool.
+class ShiftingDerivCalcToolGetter ( Configured ) :
+
+    _name = 'ShiftingDerivCalcToolGetter'
+
+    ## creates and configures tool
+    def configure(self):
+        mlog = logging.getLogger( self._name+'::configure :' )
+    
+        # create tool instance
+        from TrkAlignGenTools.AlignResidualCalculatorGetter import AlignResidualCalculatorGetter
+        resCalc = AlignResidualCalculatorGetter().AlignResidualCalculatorHandle()
+
+        from TrkAlignGenTools.AlignmentTrackFitter import AlignmentTrackFitter
+        from TrkAlignGenTools.TrkAlignGenToolsConf import Trk__ShiftingDerivCalcTool
+        shiftingDerivCalcTool=Trk__ShiftingDerivCalcTool("ShiftingDerivCalcTool",
+                                                         OutputLevel=AlignmentFlags.OutputLevel(),
+                                                         TrackFitterTool = AlignmentTrackFitter().fitter(),
+                                                         ResidualCalculator = resCalc,
+                                                         TranslationSize = mualign.shiftSizeTranslations(),
+                                                         RotationSize = mualign.shiftSizeRotations(),
+                                                         NumberOfShifts = mualign.numberOfShifts(),
+                                                         doChi2VChamberShiftsMeasType = mualign.doChi2VChamberShiftsMeasType())
+        if AlignmentFlags.useSLFitter() :
+            shiftingDerivCalcTool.SLTrackFitterTool = AlignmentTrackFitter().slfitter()
+
+        # configure other jobOptions
+        shiftingDerivCalcTool.RunOutlierRemoval    = AlignmentFlags.runOutlierRemoval()
+        shiftingDerivCalcTool.ParticleNumber       = AlignmentFlags.particleNumber()
+        shiftingDerivCalcTool.TrackAlignParamCut   = AlignmentFlags.trackAlignParamCut()
+        shiftingDerivCalcTool.SetMinIterations     = AlignmentFlags.setMinIterations()
+
+        self._ShiftingDerivCalcToolHandle = shiftingDerivCalcTool
+        
+        mlog.info(" now adding to ToolSvc")
+        from __main__ import ToolSvc 
+        ToolSvc += self.ShiftingDerivCalcToolHandle()
+        
+        mlog.info(" leaving configure")
+
+        return True
+
+    ## returns handle to ShiftingDerivCalcTool
+    def ShiftingDerivCalcToolHandle(self):
+        return self._ShiftingDerivCalcToolHandle
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/python/TrackCollectionProviderGetter.py b/Tracking/TrkAlignment/TrkAlignGenTools/python/TrackCollectionProviderGetter.py
new file mode 100644
index 0000000000000000000000000000000000000000..df319bd5071eab2d3eeb3909d51fc9fd492d6ef9
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/python/TrackCollectionProviderGetter.py
@@ -0,0 +1,35 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+
+## @file:   TrackCollectionProviderGetter.py
+## @brief:  to instantiate the TrackCollectionProvider
+## 	    with the default configuration
+## @author: Robert Harrington <roberth@bu.edu>
+## @date:   7/29/2010
+
+from AthenaCommon.Logging import logging
+from RecExConfig.Configured import Configured
+from TrkAlignGenTools.AlignmentFlags import AlignmentFlags as align
+
+class TrackCollectionProviderGetter ( Configured ) :
+    
+    _name = 'TrackCollectionProviderGetter'
+
+    def configure(self):
+        mlog = logging.getLogger( self._name+'::configure :' )
+
+        # create tool instance
+        from TrkAlignGenTools.TrkAlignGenToolsConf import Trk__TrackCollectionProvider
+        trackCollectionProvider=Trk__TrackCollectionProvider("TrackCollectionProvider",
+                                                             OutputLevel = align.OutputLevel(),
+                                                             InputTrkCol = align.inputTrkCol())
+                                                             
+        self._trackCollectionProviderHandle = trackCollectionProvider
+
+        mlog.info(" leaving configure")
+
+        return True
+
+    def TrackCollectionProviderGetterHandle(self):
+        return self._trackCollectionProviderHandle
+        
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignModuleTool.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignModuleTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..7d1a1c25c539c34c11a9604e99ac3d7dee060485
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignModuleTool.cxx
@@ -0,0 +1,343 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "AtlasDetDescr/AtlasDetectorID.h"
+
+#include "TrkDetElementBase/TrkDetElementBase.h"
+#include "TrkRIO_OnTrack/RIO_OnTrack.h"
+#include "TrkTrack/Track.h"
+
+#include "TrkAlignEvent/AlignPar.h"
+#include "TrkAlignEvent/AlignModule.h"
+#include "TrkAlignEvent/AlignModuleList.h"
+
+#include "TrkAlignGenTools/AlignModuleTool.h"
+
+namespace Trk {
+
+  //______________________________________________________________
+  AlignModuleTool::AlignModuleTool(const std::string& type, const std::string& name,
+           const IInterface* parent)
+    
+    : AthAlgTool(type,name,parent)
+    , m_idHelper         (0)
+    , m_alignModules     (0)
+    , m_alignModuleMaps  (AlignModule::NDetectorTypes,(const AlignModuleList*)0)
+    , m_alignParList     (0)
+    , m_fullAlignParList (0)
+    , m_alignParList1D   (SG::VIEW_ELEMENTS)
+    , m_subDetElement    (AlignModule::NDetectorTypes,false)
+  {
+    declareInterface<IAlignModuleTool>(this);
+    
+    declareProperty("AlignModuleListType", m_alignModuleListType = Trk::L3);
+
+    std::cout<<"m_alignModuleMaps size: "<<m_alignModuleMaps.size()
+       <<std::endl;
+
+    m_logStream = 0;
+  }
+
+  //________________________________________________________________________
+  AlignModuleTool::~AlignModuleTool()
+  {
+
+  }
+
+  //________________________________________________________________________
+  StatusCode AlignModuleTool::initialize()
+  {
+    // Number of layers in the superstructures
+    if (m_alignModuleListType>Trk::L3 || m_alignModuleListType<Trk::L0) {
+      msg(MSG::FATAL)<<"AlignModuleListType can be 0, 1, 2, or 3" << endreq;
+      return StatusCode::FAILURE;
+    }
+
+    msg(MSG::INFO).setColor(MSG::GREEN);
+    ATH_MSG_INFO("AlignModuleListType set to " << m_alignModuleListType);
+
+    // Set up ATLAS ID helper 
+    if (detStore()->retrieve(m_idHelper, "AtlasID").isFailure()) {
+      msg(MSG::FATAL)<<"Could not get Atlas ID helper"<<endreq;
+      return StatusCode::FAILURE;
+    }
+
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  StatusCode AlignModuleTool::finalize()
+  {
+
+    return StatusCode::SUCCESS;
+  }
+  
+  //________________________________________________________________________
+  void AlignModuleTool::setAlignModules(AlignModuleList* alignmods,
+          std::vector<AlignModuleList*>* idHashMaps)
+  {
+    ATH_MSG_DEBUG("in setAlignModules");
+
+    m_alignModules=alignmods;
+
+    for (int i=0;i<(int)idHashMaps->size();i++) {
+      if ((*idHashMaps)[i]) m_alignModuleMaps[i]=(*idHashMaps)[i];
+    } 
+
+    // reset 1-D collection
+    ATH_MSG_DEBUG("clearing alignModules1D");
+    int nmods(0);
+    for (int imod=0;imod<(int)m_alignModules->size();imod++) {
+      m_alignModules1D.push_back((*m_alignModules)[imod]);
+      (*m_alignModules)[imod]->setIdHash(nmods++); // this overwrites what's set in geometry manager tool... should we do this?
+    }
+    
+    ATH_MSG_DEBUG("done setting AlignModules");
+    return;
+  }
+
+
+  //________________________________________________________________________
+  void AlignModuleTool::setAlignParLists(AlignPar2DVec* fullAlignParList, 
+           AlignPar2DVec* alignParList) 
+  { 
+    ATH_MSG_DEBUG("setting fullAlignParList="<<fullAlignParList
+      <<", alignParList="<<alignParList);
+
+    m_fullAlignParList = fullAlignParList;
+    m_alignParList     = (alignParList) ? alignParList : fullAlignParList;
+
+    // recalculate 1-D collection of alignment parameters
+    ATH_MSG_DEBUG("getting AlignParList1D");
+    m_alignParList1D.clear();
+    int index(0);
+    
+    AlignPar2DVec* aplist=m_alignParList;
+    
+    for (AlignPar2DVec::iterator apVec=aplist->begin(); apVec!=aplist->end();++apVec) {
+      for (AlignParVec::iterator ap=(*apVec)->begin(); ap!=(*apVec)->end();++ap) {
+        m_alignParList1D.push_back(*ap);
+        (*ap)->setIndex(index++);
+      }
+      
+    }
+    return;
+  }
+
+  //________________________________________________________________________  
+  AlignModule* AlignModuleTool::findAlignModule(const TrkDetElementBase* det,
+            AlignModule::DetectorType detType) const
+  {
+    ATH_MSG_DEBUG("in AlignModuleTool::findAlignModule(det,detType)");
+
+    if (!det) {
+      ATH_MSG_VERBOSE("no det!");
+      return 0;
+    }
+
+    if (m_subDetElement[detType]) {
+      ATH_MSG_ERROR("please use findAlignModule method passing RIO_OnTrack");
+      return 0;
+    }
+    
+    ATH_MSG_VERBOSE("in findAlignModule, detType="<<detType);
+    
+    if (detType==AlignModule::NDetectorTypes)
+      detType=getDetectorType(det);
+    if (detType==AlignModule::NDetectorTypes || !m_alignModuleMaps[detType]) {
+      ATH_MSG_VERBOSE("bad detector type or no map for detType "<<detType);
+      return 0;
+    }
+    
+    // find align module
+    int idHash = det->identifyHash();    
+    return (*m_alignModuleMaps[detType])[idHash];
+    
+  }  
+
+  //________________________________________________________________________  
+  AlignModule * AlignModuleTool::findAlignModule(const RIO_OnTrack * rio,
+                                                 AlignModule::DetectorType detType) const
+  {
+
+    ATH_MSG_DEBUG("in AlignModuleTool::findAlignModule(rio,detType)");
+
+    if (!rio) {
+      ATH_MSG_VERBOSE("no rio!");
+      return 0;
+    }
+
+    // find detector type using TrkDetElementBase
+    const TrkDetElementBase * detelement = rio->detectorElement();
+    if (detelement) {
+      ATH_MSG_DEBUG("have detelement");
+
+      if (detType==AlignModule::NDetectorTypes)
+        detType=getDetectorType(detelement);
+      if (detType==AlignModule::NDetectorTypes || !m_alignModuleMaps[detType]) {
+        ATH_MSG_VERBOSE("bad detector type or no map for detType "<<detType);
+        return 0;
+      }
+    
+      // find align module
+      int idHash(0);
+      if (m_subDetElement[detType]) {
+        idHash = subDetElementIDHash(rio->identify());      
+        ATH_MSG_DEBUG("idHash (from subDetElement): "<<idHash);      
+      }
+      else {
+        idHash = detelement->identifyHash();
+        ATH_MSG_DEBUG("idHash: "<<idHash);            
+      }
+
+      return (*m_alignModuleMaps[detType])[idHash];
+      
+    }
+
+    ATH_MSG_VERBOSE("no detector element!");
+    return 0;
+  }
+  
+  
+  //________________________________________________________________________
+  DataVector<AlignPar>* AlignModuleTool::getAlignPars(const AlignModule* alignModule) const
+  {
+    if (!alignModule) return 0;
+    
+    int idHash =alignModule->identifyHash();
+    ATH_MSG_DEBUG("getting alignPars for idHash "<<idHash);
+
+    return (*m_alignParList)[idHash];
+  }
+
+  //________________________________________________________________________
+  void AlignModuleTool::fillDetAlignmentParameters(const TrkDetElementBase* det,
+               DataVector<AlignPar>* detAPVec,
+               AlignModule::DetectorType detType) const
+  {
+    if (detType==AlignModule::NDetectorTypes)
+      detType=getDetectorType(det);
+    if (detType==AlignModule::NDetectorTypes || !m_alignModuleMaps[detType]) return;
+    
+    // get AlignModule
+    int idHash=det->identifyHash();
+    AlignModule* alignModule=(*(m_alignModuleMaps[detType]))[idHash];
+    
+    ATH_MSG_DEBUG("have alignModule "<<alignModule->identify());
+    // get alignment parameters
+    AlignParVec* modAlignPar = getFullAlignPars(alignModule);
+    ATH_MSG_DEBUG("modAlignPar size: "<<modAlignPar->size());
+    
+    double alignModPar[AlignModule::NTransformPar];
+    double alignModErr[AlignModule::NTransformPar];      
+    for (int i=0;i<AlignModule::NTransformPar;i++) {
+      if ((*modAlignPar)[i]) {
+        alignModPar[i]=(*modAlignPar)[i]->par();
+        alignModErr[i]=(*modAlignPar)[i]->err();
+      }
+      else {
+        alignModPar[i]=alignModErr[i]=0.;
+        ATH_MSG_DEBUG("no alignModPar!");
+      }
+    }
+  
+    ATH_MSG_DEBUG("getting transforms");  
+  
+    Amg::Translation3D alignModXTranslation(alignModPar[AlignModule::TransX],
+                                            alignModPar[AlignModule::TransY],
+                                            alignModPar[AlignModule::TransZ]);
+                                      
+    Amg::Transform3D alignModXform = alignModXTranslation * Amg::RotationMatrix3D::Identity();
+    alignModXform *= Amg::AngleAxis3D(alignModPar[AlignModule::RotZ], Amg::Vector3D(0.,0.,1.));
+    alignModXform *= Amg::AngleAxis3D(alignModPar[AlignModule::RotY], Amg::Vector3D(0.,1.,0.));
+    alignModXform *= Amg::AngleAxis3D(alignModPar[AlignModule::RotX], Amg::Vector3D(1.,0.,0.));
+
+
+    Amg::Translation3D alignModXTranslationErr(alignModErr[AlignModule::TransX],
+                                               alignModErr[AlignModule::TransY],
+                                               alignModErr[AlignModule::TransZ]);
+                                      
+    Amg::Transform3D alignModXformErr = alignModXTranslationErr * Amg::RotationMatrix3D::Identity();
+    alignModXformErr *= Amg::AngleAxis3D(alignModErr[AlignModule::RotZ], Amg::Vector3D(0.,0.,1.));
+    alignModXformErr *= Amg::AngleAxis3D(alignModErr[AlignModule::RotY], Amg::Vector3D(0.,1.,0.));
+    alignModXformErr *= Amg::AngleAxis3D(alignModErr[AlignModule::RotX], Amg::Vector3D(1.,0.,0.));
+  
+    ATH_MSG_DEBUG("getting AlignPars for detector element "<<det->identify());
+
+    // get the transform for this detector element
+    const Amg::Transform3D* transform = alignModule->alignModuleToDetElementTransform(detType,det);
+    
+    // get the alignment parameters for this detector element
+    ATH_MSG_WARNING("Check that order is correct: AlignModuleTool:271,284");
+    Amg::Transform3D xformPar( (*transform) * alignModXform );
+    double* detpars = new double[AlignModule::NTransformPar];
+    double* deterrs = new double[AlignModule::NTransformPar];
+    decomposeTransform(xformPar,detpars);
+    
+    ATH_MSG_DEBUG("transx="<<detpars[0]);
+    ATH_MSG_DEBUG("transy="<<detpars[1]);
+    ATH_MSG_DEBUG("transz="<<detpars[2]);
+    ATH_MSG_DEBUG("rotx="  <<detpars[3]);
+    ATH_MSG_DEBUG("roty="  <<detpars[4]);
+    ATH_MSG_DEBUG("rotz="  <<detpars[5]);
+    
+    Amg::Transform3D xformErr( (*transform) * alignModXformErr);
+    decomposeTransform(xformErr,deterrs);
+    
+    // set in AlignParList for this detector element
+    ATH_MSG_DEBUG("setting AlignPar for detector element ");
+    for (int ipar=0;ipar<AlignModule::NTransformPar;ipar++) {
+      AlignPar* ap=(*detAPVec)[ipar];
+      ap->setPar(detpars[ipar],deterrs[ipar]);
+      ap->setFinalPar(ap->initPar()+detpars[ipar], 
+                      std::sqrt(ap->initErr()*ap->initErr() + deterrs[ipar]*deterrs[ipar]) );
+    }
+
+    ATH_MSG_DEBUG("set");
+    return;
+  
+  }
+
+  //________________________________________________________________________
+  AlignModule::DetectorType 
+  AlignModuleTool::getDetectorType(const TrkDetElementBase* det) const
+  {
+    Identifier id = det->identify();
+    
+    // get dector type
+    if ( id.is_valid()) {
+      if    (m_idHelper->is_pixel(id)) return AlignModule::Pixel;
+      else if (m_idHelper->is_sct(id)) return AlignModule::SCT;
+      else if (m_idHelper->is_trt(id)) return AlignModule::TRT;
+      else if (m_idHelper->is_mdt(id)) return AlignModule::MDT;
+      else if (m_idHelper->is_csc(id)) return AlignModule::CSC;
+      else if (m_idHelper->is_rpc(id)) return AlignModule::RPC;
+      else if (m_idHelper->is_tgc(id)) return AlignModule::TGC;      
+    }
+    
+    return AlignModule::NDetectorTypes;    
+  }
+ 
+  //________________________________________________________________________
+  DataVector<AlignPar>* AlignModuleTool::getFullAlignPars(const AlignModule* alignModule) const
+  {
+    int idHash =alignModule->identifyHash();
+    return (*m_fullAlignParList)[idHash];
+  }
+
+  //________________________________________________________________________
+  MsgStream& operator << ( MsgStream& sl, AlignModuleTool& alignModTool)
+  {
+    const AlignModuleList* modules=alignModTool.alignModules1D();
+    for (int imod=0;imod<(int)modules->size(); imod++) {
+      sl << "AML: "<<*((*modules)[imod]);
+    }
+    
+    DataVector<AlignPar>* alignParList=alignModTool.alignParList1D();
+    for (int iap=0;iap<(int)alignParList->size();iap++) {
+      sl << *((*alignParList)[iap]);
+    } 
+    return sl;
+  }
+}
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignResidualCalculator.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignResidualCalculator.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c130ebe15ab1b104d62b7c103ebbff3e1f69f726
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignResidualCalculator.cxx
@@ -0,0 +1,391 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "TrkAlignEvent/AlignTrack.h"
+#include "TrkToolInterfaces/IResidualPullCalculator.h"
+#include "TrkToolInterfaces/IUpdator.h"
+#include "TrkAlignGenTools/AlignResidualCalculator.h"
+
+#include "TrkMeasurementBase/MeasurementBase.h"
+#include "TrkMaterialOnTrack/MaterialEffectsOnTrack.h"
+#include "TrkMaterialOnTrack/ScatteringAngles.h"
+#include "TrkMaterialOnTrack/EnergyLoss.h"
+#include "TrkRIO_OnTrack/RIO_OnTrack.h"
+#include "TrkCompetingRIOsOnTrack/CompetingRIOsOnTrack.h"
+#include "TrkParameters/TrackParameters.h"
+
+#include "muonEvent/CaloEnergy.h"
+
+#include <vector>
+
+namespace Trk {
+
+  //______________________________________________________________
+  AlignResidualCalculator::AlignResidualCalculator(const std::string& type, const std::string& name,
+           const IInterface* parent)
+    
+    : AthAlgTool(type,name,parent)    
+    , m_pullCalculator("Trk::ResidualPullCalculator/ResidualPullCalculator")
+    , m_updator("Trk::KalmanUpdator/TrkKalmanUpdator")
+    , m_chi2ForMeasType(0)
+  {
+    declareInterface<IAlignResidualCalculator>(this);
+    
+    declareProperty("ResidualPullCalculator",   m_pullCalculator);
+    declareProperty("ResidualType",             m_resType = HitOnly);
+    declareProperty("IncludeScatterers",        m_includeScatterers = false );
+
+    declareProperty("UpdatorTool",              m_updator);
+  }
+
+  //________________________________________________________________________
+  AlignResidualCalculator::~AlignResidualCalculator()
+  {
+    delete [] m_chi2ForMeasType;
+  }
+
+  //________________________________________________________________________
+  StatusCode AlignResidualCalculator::initialize()
+  {  
+    // get residual pull calculator
+    if (m_pullCalculator.retrieve().isFailure()) {
+      msg(MSG::FATAL) << "Could not get " << m_pullCalculator << endreq; 
+      return StatusCode::FAILURE;
+    }
+    ATH_MSG_INFO("Retrieved " << m_pullCalculator);
+
+    // get updator
+    if(m_resType==Unbiased) {
+      if (m_updator.retrieve().isFailure()) {
+        msg(MSG::FATAL) << "Could not get " << m_updator << endreq; 
+        return StatusCode::FAILURE;
+      }
+      ATH_MSG_INFO("Retrieved " << m_pullCalculator);
+    }
+
+    ATH_MSG_INFO("Using"<<AlignResidualType(m_resType)<<"residuals.");
+
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  StatusCode AlignResidualCalculator::finalize()
+  {
+    return StatusCode::SUCCESS;
+  }
+  
+  //________________________________________________________________________
+  double AlignResidualCalculator::setResiduals(AlignTSOSCollection* atsosColl,const Track* track)
+  {
+    bool useNewTrack = (track!=0);
+    return setResiduals(atsosColl->begin(), atsosColl->end(), track, useNewTrack);
+  }
+  
+  //________________________________________________________________________
+  double AlignResidualCalculator::setResiduals(const AlignTrack* alignTrack,const Track* track)
+  {
+    bool useNewTrack = (track!=0);
+    const Track* newTrack = (useNewTrack) ? track : alignTrack;
+    return setResiduals(alignTrack->firstAtsos(), alignTrack->lastAtsos(), newTrack, useNewTrack);
+  }
+  
+  //________________________________________________________________________
+  double AlignResidualCalculator::setResiduals(AlignTSOSCollection::const_iterator firstAtsos,
+                                               AlignTSOSCollection::const_iterator lastAtsos,
+                                               const Track* track, bool newTrack) 
+  {
+    m_nDoF=0;
+    m_matchedTSOS.clear();
+
+    delete [] m_chi2ForMeasType;
+    m_chi2ForMeasType = new double[TrackState::NumberOfMeasurementTypes];
+    for (int i=0;i<TrackState::NumberOfMeasurementTypes;i++)
+      m_chi2ForMeasType[i]=0.;
+
+    //ATH_MSG_DEBUG("in setResiduals with newTrack="<<newTrack);
+    
+    if (!track&&newTrack) { ATH_MSG_ERROR("no track!"); return 0.; }
+
+    int    ntsos(0);
+    double chi2(0.);
+    for (AlignTSOSCollection::const_iterator atsos=firstAtsos; atsos != lastAtsos; ++atsos,ntsos++) {
+
+      // get TSOS from AlignTSOS or closest TSOS if track given
+      const TrackStateOnSurface* tsos =
+          (newTrack) ? getMatchingTSOS(*atsos,track) : dynamic_cast<const TrackStateOnSurface*>(*atsos);
+
+      ATH_MSG_DEBUG("ntsos "<<ntsos);
+
+      const MaterialEffectsBase*         meb        = tsos->materialEffectsOnTrack();
+      const Trk::MaterialEffectsOnTrack* meot       = dynamic_cast<const MaterialEffectsOnTrack*>(meb);
+      //const ScatteringAngles*            scatterer = (meot) ? meot->scatteringAngles() : 0;
+      
+      // if scatterer, add scattering parameters
+      //int nScattererDim=0;
+      if (m_includeScatterers && meb && meot) { 
+        //nScattererDim = (scatterer) ? 2 : 1;      
+        accumulateScattering(tsos);
+      }
+      //ATH_MSG_DEBUG("scattererDim="<<nScattererDim);
+      //(**atsos).setScatteringAngle(scatteringAngle);
+
+      // set residuals for alignTSOS
+      double dchi2 = setResidualsOnATSOS(*atsos,tsos);
+      chi2 += dchi2;
+      int imeasType=(**atsos).measType();
+      m_chi2ForMeasType[imeasType] += dchi2;
+      ATH_MSG_DEBUG("adding "<<dchi2<<", m_chi2ForMeasType["<<imeasType<<"]="<<m_chi2ForMeasType[imeasType]);
+    }
+    
+    return chi2;///(double)m_nDoF;  
+  }
+  
+  //_______________________________________________________________________
+  double
+  AlignResidualCalculator::setResidualsOnATSOS(AlignTSOS * atsos, const TrackStateOnSurface * tsos)
+  {
+    // this method does the following:
+    // 1. gets residuals (measurement and scattering dimensions), 
+    // 2. adds to AlignTSOS, and 
+    // 3. returns contribution to chi2 from this ATSOS 
+ 
+    ATH_MSG_DEBUG("in setResidualsOnATSOS");
+
+    atsos->clearResiduals();
+ 
+    double dchi2(0.);
+
+    // scattering residual(s) and/or energy loss first
+    if (m_includeScatterers) {
+      ATH_MSG_DEBUG("scatterer");
+
+      // when using unbiased residuals including scatterers doesn't make sense
+      if(m_resType == Unbiased)
+        ATH_MSG_WARNING("When using unbiased residuals including scatterers doesn't make sense!");
+      
+      const MaterialEffectsBase*         meb        = tsos->materialEffectsOnTrack();
+      const Trk::MaterialEffectsOnTrack* meot       = dynamic_cast<const MaterialEffectsOnTrack*>(meb);
+      const ScatteringAngles*            scatterer  = (meot) ? meot->scatteringAngles() : 0;
+      
+      int nscatparam=0;
+      if (meb && meot) 
+        nscatparam = (scatterer) ? 2 : 1;
+
+      for (int iparam=0;iparam<nscatparam;iparam++) {
+
+        double errSq=0.;
+        double residual(-999.);
+
+        if (nscatparam==2) {
+
+          const Trk::TrackParameters * tparp = tsos->trackParameters();
+          if (tparp) {
+            if (iparam==0) {
+              residual=-scatterer->deltaPhi()* sin (tparp->parameters()[Trk::theta]);
+              errSq   = scatterer->sigmaDeltaTheta();
+              ATH_MSG_DEBUG("sigmaDeltaTheta="<<scatterer->sigmaDeltaTheta());
+              ATH_MSG_DEBUG("sigmaDeltaPhi  ="<<scatterer->sigmaDeltaPhi());
+              ATH_MSG_DEBUG("residual:"<<residual<<", errSq: "<<errSq<<", err="<<std::sqrt(errSq));
+              errSq  *= errSq;
+            }
+            else{
+              residual=-scatterer->deltaTheta();
+              errSq   = scatterer->sigmaDeltaTheta();
+              errSq  *= errSq;
+            }
+          }
+          else{ 
+            ATH_MSG_WARNING("scatterer has no TrackParameters!"); 
+          }
+
+          Residual res(HitOnly,Scatterer,ParamDefs(iparam),residual,errSq);
+          atsos->addResidual(res); 
+    
+          dchi2 += res.residualNorm()*res.residualNorm();
+          m_nDoF++;
+        }
+        else if (!atsos->rio() && !atsos->crio()) {
+          ATH_MSG_DEBUG("energy deposit");
+
+          // energy deposit
+          double E0        = 1./std::fabs(m_previousQOverP);
+          double E1        = 1./std::fabs(m_qOverP);
+          double energyLoss= std::fabs(meot->energyLoss()->deltaE());
+
+          double residual = .001*(E0-E1-energyLoss);
+          double errSq    = .001*meot->energyLoss()->sigmaDeltaE();
+
+          ATH_MSG_DEBUG("E0/E1/energyLoss: "<<E0<<"/"<<E1<<"/"<<energyLoss);
+          ATH_MSG_DEBUG("calorimeter residual: "<<residual/errSq);
+
+          errSq*=errSq;
+
+          Residual res(HitOnly,EnergyDeposit,ParamDefs(0),residual,errSq);
+          atsos->addResidual(res);  
+          dchi2 += res.residualNorm()*res.residualNorm();
+          m_nDoF++;
+        }
+      }
+    }
+
+    // residuals from measurement
+    if (atsos->rio() || atsos->crio()) {
+      
+      int nparams = (atsos->measType()==TrackState::Pixel) ? 2 : 1;
+      for (int iparam=0;iparam<nparams;iparam++) {
+
+        double errSq=0.;
+        double residual(-999.);
+
+        if ( atsos->measType()!=TrackState::unidentified &&
+            (atsos->rio()!=0 || atsos->crio()!=0) ) {
+
+          const MeasurementBase* mesb = tsos->measurementOnTrack();
+
+          const TrackParameters * trackPars = tsos->trackParameters();
+          const ResidualPull * resPull = 0;
+
+          if ( trackPars ) {
+
+            if (m_resType == Unbiased) {
+              // Get unbiased state
+              const Trk::TrackParameters * unbiasedTrackPars = 
+                  m_updator->removeFromState(*trackPars,
+                                             mesb->localParameters(),
+                                             mesb->localCovariance());
+              if (unbiasedTrackPars) {
+                trackPars = unbiasedTrackPars;
+                // AlignTSOS desctructor takes care of deleting unbiasedTrackPars
+                atsos->setUnbiasedTrackPars(unbiasedTrackPars);
+              }
+              else
+                ATH_MSG_WARNING("Could not get unbiased track parameters, use normal parameters");
+            }
+
+            ATH_MSG_DEBUG("Calling ResidualPullCalculator for residual type "
+                          <<ResidualPullType(AlignResidualType(m_resType))
+                          <<" (AlignResidualType "<<AlignResidualType(m_resType)
+                          <<" "<<m_resType<<")");
+            ATH_MSG_DEBUG("mesb->localErrorMatrix().covValue(Trk::loc1): "<<mesb->localCovariance()(Trk::loc1,Trk::loc1));
+            resPull = m_pullCalculator->residualPull(mesb, trackPars,
+                                                     ResidualPullType(AlignResidualType(m_resType)),
+                                                     atsos->measType());
+            if ( resPull ) {
+              residual = (resPull->residual())[iparam];
+              double pull=(resPull->pull())[iparam];
+              if (pull!=0.) {
+                errSq  = residual/pull;
+                errSq *= errSq;
+              }
+              ATH_MSG_DEBUG("residual="<<residual<<", pull="<<pull);
+                    ATH_MSG_DEBUG("pos: ("<<mesb->globalPosition().x()<<", "
+                <<mesb->globalPosition().y()<<", "
+                <<mesb->globalPosition().z()<<")");
+              ATH_MSG_DEBUG("residual:"<<residual<<", errSq: "<<errSq<<", err="<<std::sqrt(errSq));
+            }
+          }
+          delete resPull;
+        }
+        else {
+          ATH_MSG_WARNING("Expected measurement for atsos of type "
+                          << atsos->dumpType()<<", meas type "<<atsos->measType() );
+        }
+
+        Residual res(AlignResidualType(m_resType),Measurement,(ParamDefs)iparam,residual,errSq);
+        atsos->addResidual(res);
+        dchi2 += res.residualNorm()*res.residualNorm();
+        m_nDoF++;
+      }
+    }
+    return dchi2; 
+  }
+
+  //________________________________________________________________________
+  void AlignResidualCalculator::accumulateScattering(const TrackStateOnSurface* tsos) 
+  {
+
+    const MaterialEffectsOnTrack* meot       = dynamic_cast<const MaterialEffectsOnTrack*>(tsos->materialEffectsOnTrack());
+    const TrackParameters*        tpar       = tsos->trackParameters();
+
+    m_qOverP      = tpar->charge()/tpar->pT()*sin( tpar->parameters()[Trk::theta]);
+
+    if(!meot) return;
+    const EnergyLoss*             energyLoss = meot->energyLoss();
+
+
+    if (!dynamic_cast<const CaloEnergy*>(energyLoss)) {
+      m_previousQOverP     = m_qOverP;
+    }
+    
+    return;
+  }
+  
+  //________________________________________________________________________
+  const TrackStateOnSurface* 
+  AlignResidualCalculator::getMatchingTSOS(const AlignTSOS* atsos, const Track* track) const
+  {
+    const TrackStateOnSurface* tsos(0);
+
+    if (atsos->rio() || atsos->crio()) {
+
+      for (std::vector<const TrackStateOnSurface*>::const_iterator itTsos=
+           track->trackStateOnSurfaces()->begin();
+           itTsos!=track->trackStateOnSurfaces()->end(); ++itTsos) {
+        if ((*itTsos)->type(TrackStateOnSurface::Outlier))
+          continue;
+
+        const MeasurementBase* mesb = (*itTsos)->measurementOnTrack();
+        const RIO_OnTrack* rio = dynamic_cast<const RIO_OnTrack*>(mesb);
+        const CompetingRIOsOnTrack* crio = dynamic_cast<const CompetingRIOsOnTrack*>(mesb);
+        
+        if (!rio && crio) {
+          rio = &(crio->rioOnTrack(0));
+        }
+        if (!rio) continue;
+        if (rio->identify() == atsos->rio()->identify()) {
+          ATH_MSG_DEBUG("matched TSOS with identifier: "<<rio->identify());
+          tsos=*itTsos;
+          break;
+        } 
+      }
+      ATH_MSG_DEBUG("done with measurement");
+    }
+    else {
+
+      const Amg::Vector3D origPosition=atsos->trackParameters()->position();
+      double distance2(1.e27);
+      
+      // loop over track and get closest TSOS   
+      for (std::vector<const TrackStateOnSurface*>::const_iterator itTsos=
+           track->trackStateOnSurfaces()->begin();
+           itTsos!=track->trackStateOnSurfaces()->end(); ++itTsos) {
+        if ((*itTsos)->type(TrackStateOnSurface::Outlier))
+          continue;
+        if (!dynamic_cast<const MaterialEffectsOnTrack*>((*itTsos)->materialEffectsOnTrack())) continue;
+        if (!(*itTsos)->trackParameters()) { ATH_MSG_WARNING("no track parameters!"); continue; }
+        const Amg::Vector3D newPosition=(*itTsos)->trackParameters()->position();
+        ATH_MSG_DEBUG("origPos: "<<origPosition<<", newPos: "<<newPosition);
+        double newdist2=(newPosition - origPosition).mag2();
+        if (newdist2<distance2) {
+          distance2=newdist2;
+          tsos=*itTsos;
+        }
+      }      
+      ATH_MSG_DEBUG("done with scatterer");
+    } 
+    if (!tsos) return 0;   
+    const Amg::Vector3D addPosition=tsos->trackParameters()->position();    
+    if (std::find(m_matchedTSOS.begin(),m_matchedTSOS.end(),tsos)==m_matchedTSOS.end()) {
+      m_matchedTSOS.push_back(tsos);       
+      ATH_MSG_DEBUG("added tsos with pos: "<<addPosition);
+    }
+    else {
+      ATH_MSG_WARNING("TSOS already found with position "<<addPosition<<"!");
+      //return 0;
+    }
+    return tsos;
+  }
+    
+} // end namespace
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignTrackCreator.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignTrackCreator.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..3649178fc2bea5036f6768b688f7b9a89dbeab05
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignTrackCreator.cxx
@@ -0,0 +1,258 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "StoreGate/StoreGateSvc.h"
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/PropertyMgr.h"
+
+#include "AtlasDetDescr/AtlasDetectorID.h"
+#include "EventInfo/EventInfo.h"
+#include "EventInfo/EventID.h"
+
+#include "TrkEventUtils/MeasurementTypeID.h"
+
+#include "TrkTrack/TrackStateOnSurface.h"
+#include "TrkTrack/Track.h"
+#include "TrkMeasurementBase/MeasurementBase.h"
+#include "TrkRIO_OnTrack/RIO_OnTrack.h"
+#include "TrkCompetingRIOsOnTrack/CompetingRIOsOnTrack.h"
+#include "TrkMaterialOnTrack/MaterialEffectsOnTrack.h"
+
+#include "TrkAlignEvent/AlignTSOS.h"
+#include "TrkAlignEvent/AlignModule.h"
+#include "TrkAlignEvent/AlignModuleList.h"
+#include "TrkAlignEvent/AlignTrack.h"
+
+#include "TrkAlignGenTools/AlignTrackCreator.h"
+#include "TrkAlignGenTools/AlignModuleTool.h"
+#include "TrkAlignInterfaces/IAlignResidualCalculator.h"
+
+#include <fstream>
+
+namespace Trk {
+
+  //________________________________________________________________________
+  AlignTrackCreator::AlignTrackCreator(const std::string& type, const std::string& name,
+                                     const IInterface* parent)
+    : IAlignTrackCreator()
+    , AthAlgTool(type,name,parent)
+    , m_residualCalculator("Trk::AlignResidualCalculator/ResidualCalculator")
+  {
+    declareInterface<IAlignTrackCreator>(this);
+
+    declareProperty("ResidualCalculator",          m_residualCalculator);
+    declareProperty("AlignModuleTool",             m_alignModuleTool);
+
+    declareProperty("EventList",                   m_eventListName  = "goodEvents.txt");
+    declareProperty("WriteEventList",              m_writeEventList = false );
+    declareProperty("RequireOverlap",              m_requireOverlap = false);
+    declareProperty("RemoveATSOSNotInAlignModule", m_removeATSOSNotInAlignModule=true);
+    declareProperty("IncludeScatterers",           m_includeScatterers = true );
+
+    m_logStream = 0;
+  }
+
+  //________________________________________________________________________
+  AlignTrackCreator::~AlignTrackCreator()
+  {
+    ATH_MSG_DEBUG("in AlignTrackCreator d'tor");
+  }
+
+  //________________________________________________________________________
+  StatusCode AlignTrackCreator::initialize()
+  {
+    // Set up ATLAS ID helper
+    if (detStore()->retrieve(m_idHelper, "AtlasID").isFailure()) {
+      ATH_MSG_ERROR ("Could not get AtlasDetectorID helper" );
+      return StatusCode::FAILURE;
+    }
+    m_measTypeIdHelper=new MeasurementTypeID(m_idHelper);
+
+    if (m_residualCalculator.retrieve().isFailure()) {
+      msg(MSG::FATAL) << "Could not get " << m_residualCalculator << endreq;
+      return StatusCode::FAILURE;
+    }
+    ATH_MSG_INFO("Retrieved " << m_residualCalculator);
+
+    // get AlignModuleTool
+    if (m_alignModuleTool.retrieve().isFailure()) {
+      msg(MSG::FATAL) << "Could not get " << m_alignModuleTool << endreq;
+      return StatusCode::FAILURE;
+    }
+    ATH_MSG_INFO("Retrieved " << m_alignModuleTool);
+
+    ATH_MSG_INFO("initialize() successful in " << name());
+
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  StatusCode AlignTrackCreator::finalize()
+  {
+    ATH_MSG_DEBUG("finalize() in AlignTrackCreator");
+
+    // write run/evt to ASCII file
+    if (m_writeEventList) {
+      std::ofstream output(m_eventListName.c_str());
+      for (std::vector<std::pair<int,int> >::iterator it=
+             m_goodEventList.begin(); it!=m_goodEventList.end(); ++it) {
+        int run=(*it).first;
+        int evt=(*it).second;
+        output << run << "  " << evt << std::endl;
+      }
+      
+      // if no events, output dummy run and event number so file isn't empty
+      if (m_goodEventList.size()<1) output<<"0  0"<<std::endl;
+      output.close();
+    }
+    
+    delete m_measTypeIdHelper;
+
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  bool AlignTrackCreator::processAlignTrack(AlignTrack * at) const
+  {
+    DataVector<AlignTSOS>* alignTSOSCollection=new DataVector<AlignTSOS>;
+
+    bool goodtrack = false;
+    int ntsos(0);
+    double chi2(0.);
+
+    AlignModule * lastModule(0);
+    bool overlapTrack(false);
+
+    ATH_MSG_DEBUG("nDoF: "<<at->fitQuality()->numberDoF()<<", tsos size: "<<at->trackStateOnSurfaces()->size());
+
+    std::vector<const TrackStateOnSurface *>::const_iterator tsos     = at->trackStateOnSurfaces()->begin();
+    std::vector<const TrackStateOnSurface *>::const_iterator tsos_end = at->trackStateOnSurfaces()->end();
+    for ( ; tsos!=tsos_end; ++tsos,ntsos++) {
+
+      AlignTSOS * atsos(0);
+      AlignModule * module(0);
+
+      if ((*tsos)->type(TrackStateOnSurface::Outlier) ||
+          (*tsos)->type(TrackStateOnSurface::Perigee) ||
+          (*tsos)->type(TrackStateOnSurface::Hole))
+        continue;
+      else if ((*tsos)->type(TrackStateOnSurface::Measurement)) {
+
+	ATH_MSG_DEBUG("checking ntsos: "<<ntsos);
+
+        const MeasurementBase      * mesb  = (*tsos)->measurementOnTrack();
+        const TrackParameters      * tparp = (*tsos)->trackParameters();
+        const RIO_OnTrack          * rio   = dynamic_cast<const RIO_OnTrack *>(mesb);
+        const CompetingRIOsOnTrack * crio  = dynamic_cast<const CompetingRIOsOnTrack *>(mesb);
+
+        if (!rio && crio) rio=&crio->rioOnTrack(0);
+
+        if (rio && tparp) {
+
+          //AlignModule::DetectorType detType=AlignModule::NDetectorTypes;
+          //if (measType!=TrackState::unidentified && measType<=TrackState::TGC)
+          //detType=(AlignModule::DetectorType)(measType-1);
+
+          //get detector type
+          AlignModule::DetectorType detType = m_alignModuleTool->getDetectorType(rio->detectorElement());
+	  ATH_MSG_DEBUG("detType: "<<detType);
+
+          // see if track is good track
+	  if (detType!=AlignModule::NDetectorTypes) {
+	    ATH_MSG_DEBUG("calling findAlignModule");
+	    module=m_alignModuleTool->findAlignModule(rio,detType);
+	  }
+	  if (module) {
+	    ATH_MSG_DEBUG("found module");
+	    goodtrack=true;
+	    if (lastModule && module!=lastModule) {
+	      overlapTrack=true;
+	      ATH_MSG_DEBUG("have overlap track");
+	    }
+	    else
+	      lastModule=module;
+	  }	
+	  ATH_MSG_DEBUG("module not found");
+
+          // see what kind of TSOS
+          TrackState::MeasurementType measType = m_measTypeIdHelper->defineType(mesb);
+	  
+          // create AlignTSOS using CompetingRIOsOnTrack or RIO_OnTrack
+          if (crio) 
+            atsos = new AlignTSOS(**tsos,module,crio,measType);	  
+          else 
+            atsos = new AlignTSOS(**tsos,module,rio,measType);
+
+          if (module)
+            ATH_MSG_DEBUG("module id "<<module->identify());
+          else
+            ATH_MSG_VERBOSE("no module");
+
+          atsos->setValid(true);
+        }
+      }
+
+      // scatterer with no associated measurement
+      else if ((*tsos)->type(TrackStateOnSurface::Scatterer) && m_includeScatterers) {
+        atsos=new AlignTSOS(**tsos,TrackState::unidentified);
+        atsos->setValid(true);
+      }
+
+      if (!atsos) {
+        continue;
+      }
+
+      if (m_removeATSOSNotInAlignModule && !module) {
+        delete atsos;
+        continue;
+      }
+
+      // set detector specific properties (if needed)
+      m_alignModuleTool->setMeasurementProperties(atsos);
+
+      alignTSOSCollection->push_back(atsos);
+    }
+
+    ATH_MSG_DEBUG("goodtrack="<<goodtrack<<", alignTSOSCollection size: "<<alignTSOSCollection->size());
+
+    if (goodtrack && (!m_requireOverlap||overlapTrack)) {
+      
+      // store run/evt number in vector
+      if (m_writeEventList) {
+        const EventInfo * eventInfo;
+        StatusCode sc=evtStore()->retrieve(eventInfo);
+        if (sc.isFailure())
+          ATH_MSG_ERROR("Couldn't retrieve event info");
+
+        int run=eventInfo->event_ID()->run_number();
+        int evt=eventInfo->event_ID()->event_number();
+        m_goodEventList.push_back(std::make_pair(run,evt));
+      }
+
+      // set residuals on ATSOS and get local chi2
+      ATH_MSG_DEBUG("calling setResiduals");
+      chi2=m_residualCalculator->setResiduals(alignTSOSCollection);
+      ATH_MSG_DEBUG("done with setResiduals");
+
+      // check that chi2 from fitter matches local chi2
+      if (std::fabs(chi2-at->fitQuality()->chiSquared())>.01) {
+        ATH_MSG_DEBUG("local chi2: "<<chi2<<", from fit: "<<at->fitQuality()->chiSquared());
+      }
+
+      ATH_MSG_DEBUG("setting alignTrack");
+      at->setAlignTSOSCollection(alignTSOSCollection);
+      at->setChi2(chi2);
+
+      if (msgLvl(MSG::DEBUG)) at->dump(msg());
+
+      return true;
+    }
+
+    ATH_MSG_DEBUG("failed to make AlignTrack");
+    delete alignTSOSCollection;
+    return false;
+  }
+
+} // end namespace
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignTrackDresser.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignTrackDresser.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..42c717484a73b1921391fcaa6a4b61f2a248c6fc
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignTrackDresser.cxx
@@ -0,0 +1,135 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GaudiKernel/MsgStream.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "CLHEP/Matrix/SymMatrix.h"
+
+#include "TrkTrack/TrackStateOnSurface.h"
+#include "TrkMeasurementBase/MeasurementBase.h"
+#include "TrkRIO_OnTrack/RIO_OnTrack.h"
+#include "TrkCompetingRIOsOnTrack/CompetingRIOsOnTrack.h"
+
+#include "TrkTrack/Track.h"
+
+#include "TrkAlignInterfaces/IDerivCalcTool.h"
+#include "TrkAlignInterfaces/IFillNtupleTool.h"
+#include "TrkAlignEvent/AlignTSOS.h"
+#include "TrkAlignEvent/AlignModule.h"
+#include "TrkAlignEvent/AlignTrack.h"
+
+#include "TrkAlignGenTools/AlignTrackDresser.h"
+
+namespace Trk {
+
+  //________________________________________________________________________
+  AlignTrackDresser::AlignTrackDresser(const std::string & type, const std::string & name, const IInterface * parent)
+    : AthAlgTool(type,name,parent)
+    , m_derivCalcTool("Trk::AnalyticalDerivCalcTool", this)
+    , m_numBadCovWMatrix(0)
+  {
+    declareInterface<IAlignTrackDresser>(this);
+
+    declareProperty("DerivCalcTool",   m_derivCalcTool,   "tool for calculating derivatives");
+
+    m_logStream = 0;
+  }
+
+  //________________________________________________________________________
+  AlignTrackDresser::~AlignTrackDresser()
+  {
+  }
+
+  //________________________________________________________________________
+  StatusCode AlignTrackDresser::initialize()
+  {
+    ATH_MSG_DEBUG("in AlignTrackDresser initialize()");
+
+    // Get DerivCalcTool (will have to be moved to AlignTool)
+    if ( m_derivCalcTool.retrieve().isFailure() ) {
+      msg(MSG::FATAL)<< "Failed to retrieve tool " << m_derivCalcTool << endreq;
+      return StatusCode::FAILURE;
+    } 
+    ATH_MSG_INFO("Retrieved tool " << m_derivCalcTool);
+
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  void AlignTrackDresser::setLogStream(std::ostream * os)
+  {
+    m_logStream = os;
+    m_derivCalcTool->setLogStream(m_logStream);
+  } 
+
+  //________________________________________________________________________
+  StatusCode AlignTrackDresser::finalize()
+  {
+    if(m_numBadCovWMatrix>0)
+      ATH_MSG_INFO("Total of "<<m_numBadCovWMatrix<<" tracks had invalid weight matrix.");
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  bool AlignTrackDresser::dressAlignTrack(AlignTrack* alignTrack) const
+  {
+    // set hit residuals
+    setResiduals(alignTrack);
+
+    ATH_MSG_DEBUG("residuals set, getting partial derivatives from m_derivCalcTool="<<m_derivCalcTool);
+
+    // set partial derivatives of hit residuals w.r.t. alignment parameters
+    if (!m_derivCalcTool->setDerivatives(alignTrack))
+      return false;
+
+    // for global method we let the deriv.calc.tool calculate the weight matrix
+    // get W = V^{-1} R V^{-1} (simply V^{-1} for numerical derivatives)
+    bool Wisvalid = m_derivCalcTool->setResidualCovMatrix(alignTrack);
+
+    if (!Wisvalid) {
+      ATH_MSG_INFO("something is wrong with the cov matrix for the residuals.");
+      ++m_numBadCovWMatrix;
+    }
+
+    return Wisvalid;
+  }
+
+  //________________________________________________________________________
+  void AlignTrackDresser::setResiduals(AlignTrack* alignTrack) const
+  {
+    if (alignTrack->residualVector()) 
+      ATH_MSG_ERROR("alignTrack already has residuals!");
+    
+    const int NMEAS = alignTrack->nAlignTSOSMeas();
+    Amg::VectorX * residuals = new Amg::VectorX(NMEAS);
+    
+    int imeas = 0;
+    AlignTSOSCollection::const_iterator atsosItr = alignTrack->firstAtsos();
+    for ( ; atsosItr != alignTrack->lastAtsos(); ++atsosItr) {		
+
+      if (!(*atsosItr)->isValid())
+        continue;
+
+      std::vector<Residual>::const_iterator itRes = (**atsosItr).firstResidual();
+      for ( ; itRes != (**atsosItr).lastResidual() ; ++itRes, ++imeas) {
+        (*residuals)[imeas] = itRes->residual();
+        if (msgLvl(MSG::DEBUG)) {
+          double z=(**atsosItr).measurementOnTrack()->globalPosition().z();	
+          ATH_MSG_DEBUG("pos.z: "<<z<<", res["<<imeas<<"]="<<itRes->residual()<<"  res/sq["<<imeas<<"]="<<itRes->residualNorm());
+        }
+      }
+    }
+
+    if (imeas!=NMEAS) {
+      msg(MSG::ERROR)<<"problem with nmeas.  imeas="<<imeas<<", NMEAS="<<NMEAS<<endreq;
+      exit(3);
+    }
+
+    alignTrack->setResidualVector(residuals); // residuals owned by alignTrack
+    ATH_MSG_DEBUG("residuals set for AlignTrack");
+    return;
+  }
+   
+} // end namespace
+  
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignTrackPreProcessor.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignTrackPreProcessor.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..1af3b971d2fed0253583f541570532260c60766a
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/AlignTrackPreProcessor.cxx
@@ -0,0 +1,175 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrkAlignGenTools/AlignTrackPreProcessor.h"
+
+#include "TrkTrack/Track.h"
+#include "TrkTrack/TrackCollection.h"
+#include "TrkEventPrimitives/ParticleHypothesis.h"
+#include "TrkFitterInterfaces/IGlobalTrackFitter.h"
+#include "TrkToolInterfaces/ITrackSelectorTool.h"
+
+#include "TrkAlignEvent/AlignTrack.h"
+
+namespace Trk {
+
+  //________________________________________________________________________
+  AlignTrackPreProcessor::AlignTrackPreProcessor(const std::string & type,
+                                                 const std::string & name,
+                                                 const IInterface  * parent)
+    : AthAlgTool(type,name,parent)
+    , m_trackFitterTool("Trk::GlobalChi2Fitter/MCTBFitter")
+    , m_SLTrackFitterTool("")
+    , m_trackSelectorTool("")
+    , m_runOutlierRemoval(false)
+    , m_particleHypothesis(Trk::nonInteracting)
+    , m_useSingleFitter(false)
+  {
+    declareInterface<IAlignTrackPreProcessor>(this);
+
+    declareProperty("RefitTracks", m_refitTracks = true);
+
+    declareProperty("TrackFitterTool",   m_trackFitterTool);
+    declareProperty("SLTrackFitterTool", m_SLTrackFitterTool);
+    declareProperty("UseSingleFitter",   m_useSingleFitter);
+
+    declareProperty("StoreFitMatricesAfterRefit", m_storeFitMatricesAfterRefit = true);
+
+    declareProperty("TrackSelectorTool", m_trackSelectorTool);
+    declareProperty("SelectTracks", m_selectTracks = false);
+
+    declareProperty("ParticleHypothesis", m_particleHypothesis);
+    declareProperty("RunOutlierRemoval",  m_runOutlierRemoval = false);
+
+    m_logStream = 0;
+  }
+
+  //________________________________________________________________________
+  AlignTrackPreProcessor::~AlignTrackPreProcessor()
+  {
+
+  }
+
+  //________________________________________________________________________
+  StatusCode AlignTrackPreProcessor::initialize()
+  {
+    // get track fitter tools
+    if (m_trackFitterTool.retrieve().isSuccess())
+      ATH_MSG_INFO("Retrieved " << m_trackFitterTool);
+    else{
+      msg(MSG::FATAL) << "Could not get " << m_trackFitterTool << endreq;
+      return StatusCode::FAILURE;
+    }
+
+    if (!m_useSingleFitter) {
+      if (m_SLTrackFitterTool.retrieve().isSuccess())
+        ATH_MSG_INFO("Retrieved " << m_SLTrackFitterTool);
+      else {
+        msg(MSG::FATAL) << "Could not get " << m_SLTrackFitterTool << endreq;
+        return StatusCode::FAILURE;
+      }
+    }
+
+    if(m_selectTracks) {
+      if(m_trackSelectorTool.empty()) {
+        msg(MSG::FATAL) << "TrackSelectorTool not specified : " << m_trackSelectorTool << endreq;
+        return StatusCode::FAILURE;
+      }
+      else if(m_trackSelectorTool.retrieve().isFailure())
+      {
+        msg(MSG::FATAL) << "Could not get " << m_trackSelectorTool << endreq;
+        return StatusCode::FAILURE;
+      }
+      ATH_MSG_INFO("Retrieved " << m_trackSelectorTool);
+    }
+
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  StatusCode AlignTrackPreProcessor::finalize()
+  {
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  DataVector<Track>* AlignTrackPreProcessor::processTrackCollection(const DataVector<Track>* tracks) 
+  {
+    ATH_MSG_DEBUG("AlignTrackPreProcessor::processTrackCollection()");
+
+    if (!tracks || tracks->size()==0)
+      return 0;
+
+    // the output collection of AlignTracks
+    // we define it as collection of Tracks but fill AlignTracks inside
+    DataVector<Track> * newTracks = new DataVector<Track>;
+
+    int itrk(0);
+    // loop over tracks and create AlignTracks
+    TrackCollection::const_iterator it     = tracks->begin();
+    TrackCollection::const_iterator it_end = tracks->end();
+
+    for ( ; it != it_end ; ++it, ++itrk) {
+
+      ATH_MSG_DEBUG("Processing track "<<itrk);
+      Track * origTrack = *it;
+      Track * newTrack = *it;
+      AlignTrack* at;
+
+      // check whether the track passes selection
+      if (m_selectTracks)
+        if(!m_trackSelectorTool->decision(*origTrack)) {
+          ATH_MSG_DEBUG("Track did not pass the selection.");
+          continue;
+        }
+
+      // refit track
+      if (m_refitTracks) {
+
+        ToolHandle<Trk::IGlobalTrackFitter> fitter=m_trackFitterTool;
+        if (!m_useSingleFitter && AlignTrack::isSLTrack(origTrack) )
+          fitter = m_SLTrackFitterTool;
+
+        newTrack=fitter->fit(*origTrack,m_runOutlierRemoval,ParticleHypothesis(m_particleHypothesis));
+        if (!newTrack) {
+          ATH_MSG_DEBUG("Track refit yielded no track. Skipping the track.");
+          continue;
+        }
+
+        at = new AlignTrack(*newTrack);
+
+        if (msgLvl(MSG::DEBUG) && !msgLvl(MSG::VERBOSE)) {
+          msg(MSG::DEBUG)<<"before refit: "<<endreq;
+          AlignTrack::dumpLessTrackInfo(*origTrack,msg(MSG::DEBUG));
+          msg(MSG::DEBUG)<<"after refit: "<<endreq;
+          AlignTrack::dumpLessTrackInfo(*newTrack,msg(MSG::DEBUG));
+          msg(MSG::DEBUG)<<endreq;
+        }
+
+        // store fit matrices
+        if (m_storeFitMatricesAfterRefit) {
+          at->setFullCovarianceMatrix(fitter->FullCovarianceMatrix());
+          at->setDerivativeMatrix(fitter->DerivMatrix());
+        }
+
+        // delete newTrack since it's copied in AlignTrack
+        delete newTrack;
+      }
+
+      else
+        at=new AlignTrack(*newTrack);
+
+      newTracks->push_back(at);
+
+    }
+
+    if (newTracks->size()==0) {
+      delete newTracks;
+      return 0;
+    }
+
+    return newTracks;
+  }
+
+}
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/AnalyticalDerivCalcTool.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/AnalyticalDerivCalcTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..eee0d87e4b32b0bfe7579bb7c6c5de4684f6c18f
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/AnalyticalDerivCalcTool.cxx
@@ -0,0 +1,825 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrkTrack/Track.h"
+#include "TrkMeasurementBase/MeasurementBase.h"
+#include "TrkEventUtils/MeasurementTypeID.h"
+#include "TrkParameters/TrackParameters.h"
+#include "TrkAlignInterfaces/IAlignModuleTool.h"
+
+#include "AtlasDetDescr/AtlasDetectorID.h"
+#include "TrkEventPrimitives/TrackStateDefs.h"
+
+#include "TrkRIO_OnTrack/RIO_OnTrack.h"
+#include "TrkCompetingRIOsOnTrack/CompetingRIOsOnTrack.h"
+
+#include "TrkAlignEvent/AlignModule.h"
+#include "TrkAlignEvent/AlignModuleList.h"
+#include "TrkAlignEvent/AlignTSOS.h"
+#include "TrkAlignEvent/AlignTrack.h"
+#include "TrkAlignEvent/AlignPar.h"
+#include "TrkAlignEvent/AlignResidualType.h"
+
+#include "TrkAlignGenTools/AnalyticalDerivCalcTool.h"
+
+#include "TrkAlgebraUtils/AlSymMat.h"
+
+#include <string>
+
+namespace Trk {
+
+  //________________________________________________________________________
+  AnalyticalDerivCalcTool::AnalyticalDerivCalcTool(const std::string & type,
+                                                   const std::string & name,
+                                                   const IInterface  * parent)
+    : AthAlgTool(type,name,parent)
+    , m_alignModuleTool("Trk::AlignModuleTool/AlignModuleTool")
+    , m_idHelper(0)
+    , m_firstEvent(true)
+    , m_residualType(HitOnly)
+    , m_residualTypeSet(false)
+    , m_storeDerivatives(false)
+  {
+    declareInterface<IDerivCalcTool>(this);
+
+    declareProperty("AlignModuleTool",   m_alignModuleTool);
+
+    declareProperty("UseLocalSetting", m_useLocalSetting=false, "use local setup for the covariance matrix of the track");
+
+    // Use constant errors for each sub-detector such that it's equivalent
+    // to minimize residual distance instead of minizing residual pull.
+    // This is only applied if m_useLocalSetting==true
+    declareProperty("UseIntrinsicPixelError", m_useIntrinsicPixelErrors, "use intrinsic errors for Pixel");
+    declareProperty("UseIntrinsicSCTError",   m_useIntrinsicSCTErrors,   "use intrinsic errors for SCT");
+    declareProperty("UseIntrinsicTRTError",   m_useIntrinsicTRTErrors,   "use intrinsic errors for TRT");
+
+    declareProperty("StoreDerivatives", m_storeDerivatives, "store derivatives dr/da on AlignTSOS to be filled into ntuple");
+
+    m_logStream = 0;
+  }
+
+  //________________________________________________________________________
+  AnalyticalDerivCalcTool::~AnalyticalDerivCalcTool()
+  {}
+
+  //________________________________________________________________________
+  StatusCode AnalyticalDerivCalcTool::initialize()
+  {
+    if (m_alignModuleTool.retrieve().isFailure()) {
+      msg(MSG::FATAL) << "Could not get " << m_alignModuleTool << endreq;
+      return StatusCode::FAILURE;
+    }
+    ATH_MSG_INFO("Retrieved " << m_alignModuleTool);
+
+    if (detStore()->retrieve(m_idHelper, "AtlasID").isFailure()) {
+      msg(MSG::FATAL) << "Could not get AtlasDetectorID helper" << endreq;
+      return StatusCode::FAILURE;
+    }
+    m_measTypeIdHelper = new MeasurementTypeID(m_idHelper);
+
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  StatusCode AnalyticalDerivCalcTool::finalize()
+  {
+    ATH_MSG_DEBUG("in AnalyticalDerivCalcTool::finalize()");
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  bool AnalyticalDerivCalcTool::setDerivatives(AlignTrack * alignTrack)
+  {
+    if(!m_residualTypeSet)
+      checkResidualType(alignTrack);
+
+    // create table of modules for checking whether the module
+    // is hit by the track or not
+    int nModules = m_alignModuleTool->alignModules1D()->size();
+    std::vector<bool> hitModules(nModules,false);
+
+    // loop over AlignTSOSCollection, 
+    // find modules that are in the AlignModuleList,
+    std::vector<const AlignModule *> alignModules;    
+    AlignTSOSCollection::const_iterator atsosItr = alignTrack->firstAtsos();
+    for (; atsosItr != alignTrack->lastAtsos(); ++atsosItr) {      
+      const AlignModule * module=(*atsosItr)->module();
+      if (module)
+        ATH_MSG_DEBUG("have ATSOS for module "<<module->identify());
+      else
+        ATH_MSG_DEBUG("no module!");
+
+      if (!(*atsosItr)->isValid() || !module)
+        continue;
+
+      // if the module is not yet in the list for this track, add it
+      if(hitModules[module->identifyHash()] == false) {
+        hitModules[module->identifyHash()] = true;
+        alignModules.push_back(module);
+      }
+    }
+
+    // Determine derivatives from shifting these modules
+    std::vector<AlignModuleDerivatives> * derivatives = new std::vector<AlignModuleDerivatives>;
+    std::vector<const AlignModule *>::const_iterator moduleIt = alignModules.begin();
+    for ( ; moduleIt!=alignModules.end(); ++moduleIt) {
+      std::vector<Amg::VectorX> deriv_vec = getDerivatives(alignTrack,*moduleIt);
+      derivatives->push_back(make_pair(*moduleIt,deriv_vec));
+    }
+
+    // alignTrack takes care of deleting the derivatives
+    ATH_MSG_DEBUG("setting matrix derivatives");
+    alignTrack->setDerivatives(derivatives);
+
+    ATH_MSG_DEBUG("returning from setDerivatives");
+
+    return true;
+  }
+    
+  //________________________________________________________________________
+  bool AnalyticalDerivCalcTool::setResidualCovMatrix(AlignTrack * alignTrack) const
+  {
+    if (m_firstEvent) {
+      if(m_logStream) {
+        *m_logStream<<"*************************************************************"<<std::endl;
+        *m_logStream<<"*************************************************************"<<std::endl;
+        *m_logStream<<"***                                                     *****"<<std::endl;
+
+        if(m_useLocalSetting)
+          *m_logStream<<"***           Running full LOCAL Chi2 method            *****"<<std::endl;
+        else
+          *m_logStream<<"***           Running full GLOBAL Chi2 method           *****"<<std::endl;
+
+        *m_logStream<<"***            using analytical derivatives             *****"<<std::endl;
+
+        if(m_useLocalSetting) {
+          std::string resType = "HitOnly ";
+          if(m_residualType==Unbiased)
+            resType = "Unbiased";
+          *m_logStream<<"***            with residual type: "<<resType<<"             *****"<<std::endl;
+        }
+
+        *m_logStream<<"***                                                     *****"<<std::endl;
+        *m_logStream<<"*************************************************************"<<std::endl;
+      }
+      m_firstEvent = false;
+    }
+
+    // get inverse local error matrix of the track
+    const Amg::MatrixX * Vinv = alignTrack->localErrorMatrixInv();
+    if(!checkValidity(*Vinv)) {
+      ATH_MSG_WARNING("Inverse local error matrix is invalid, skipping the track");
+      return false;
+    }
+    ATH_MSG_DEBUG("V inverse (diagonal only):");
+    if (msgLvl(MSG::DEBUG)) {
+      for (int i=0;i<Vinv->rows();i++) msg()<<(*Vinv)(i,i)<<" ";
+      msg()<<endreq;
+    } 
+
+    // ========================
+    // setup local chi2 method
+    // ========================
+    if (m_useLocalSetting) {
+      ATH_MSG_DEBUG("setting Residual covariance matrix for local method");
+
+      // for local method we only need the Vinv
+      const Amg::MatrixX * Vinv = alignTrack->localErrorMatrixInv();
+      Amg::MatrixX * W = new Amg::MatrixX(*Vinv);
+
+      // if we want to ignore the real errors of measurements for a particular subretector
+      // (we should add something similar for Muon detectors)
+      if(m_useIntrinsicPixelErrors || m_useIntrinsicSCTErrors || m_useIntrinsicTRTErrors) {
+
+        if(m_useIntrinsicPixelErrors)
+          ATH_MSG_DEBUG("Ignoring measured errors for Pixel clusters, using intrinsic errors");
+        if(m_useIntrinsicSCTErrors)
+          ATH_MSG_DEBUG("Ignoring measured errors for SCT clusters, using intrinsic errors");
+        if(m_useIntrinsicTRTErrors)
+          ATH_MSG_DEBUG("Ignoring measured errors for TRT clusters, using intrinsic errors");
+
+        int index(0);
+        AlignTSOSCollection::const_iterator itAtsos     = alignTrack->firstAtsos();
+        AlignTSOSCollection::const_iterator itAtsos_end = alignTrack->lastAtsos();
+        for ( ; itAtsos != itAtsos_end; ++itAtsos) {
+          const AlignTSOS * atsos = *itAtsos;
+          if (!atsos->isValid())
+            continue;
+
+          if(m_useIntrinsicPixelErrors && atsos->measType() == Trk::TrackState::Pixel) {
+            (*W)(index,index) = 1./(0.05*0.05/12);
+            (*W)(index+1,index+1) = 1./(0.4*0.4/12);
+          }
+          else if(m_useIntrinsicSCTErrors && atsos->measType() == Trk::TrackState::SCT)
+            (*W)(index,index) = 1./(0.1*0.1/12);
+          else if(m_useIntrinsicTRTErrors && atsos->measType() == Trk::TrackState::TRT)
+            (*W)(index,index) = 1./(0.5*0.5/12);
+
+          index += atsos->nResDim();
+        }
+      }
+
+      ATH_MSG_DEBUG("setting local weight matrix W ( "<<W->rows()<<" x "<<W->cols()<<" ) (diagonal only):");
+      if (msgLvl(MSG::DEBUG)) {
+        for (int i=0;i<W->rows();i++) msg()<<(*W)(i,i)<<" ";
+        msg()<<endreq;
+      } 
+      alignTrack->setWeightMatrix(W);
+
+      Amg::MatrixX * W1st = new Amg::MatrixX(*W);
+      alignTrack->setWeightMatrixFirstDeriv(W1st);
+
+      return true;
+    }
+
+    // ========================
+    // setup global chi2 method
+    // ========================
+
+    // get the ingredients for calculating R = V - Q    
+    const Amg::MatrixX * V = alignTrack->localErrorMatrix();
+    ATH_MSG_DEBUG("V ( "<<V->rows()<<" x "<<V->cols()<<" ) (diagonal only):");
+    if (msgLvl(MSG::DEBUG)) {
+      for (int i=0;i<V->rows();i++) msg()<<(*V)(i,i)<<" ";
+      msg()<<endreq;
+    } 
+
+    const int outputdim = alignTrack->nAlignTSOSMeas();
+
+    Amg::MatrixX Q(outputdim, outputdim); //symmetric matrix
+    if (!getTrkParamCovMatrix(alignTrack, Q))
+      return false;
+    ATH_MSG_DEBUG("Q ( "<<Q.rows()<<" x "<<Q.cols()<<" )");
+    ATH_MSG_DEBUG("Q: "<<Q);
+
+    // calculate R
+    const Amg::MatrixX R = (*V) - Q;
+    if (!checkValidity(R)) {
+      ATH_MSG_WARNING("Matrix R = V - HCH is invalid, skipping the track");
+      return false;
+    }
+    ATH_MSG_DEBUG("R ( "<<R.rows()<<" x "<<R.cols()<<" )");
+    ATH_MSG_DEBUG("R: "<<R);
+
+    // calculate weight matrix and set it
+    Amg::MatrixX * W = new Amg::MatrixX(outputdim,outputdim); //symmetric matrix
+    *W = ((*Vinv) * R * (*Vinv));
+    
+    if (!checkValidity(*W)) {
+      ATH_MSG_DEBUG("Weight matrix is invalid, skipping the track");
+      return false;
+    }
+    ATH_MSG_DEBUG("setting weight: "<<(*W));
+    alignTrack->setWeightMatrix(W);
+
+    // for 1st derivatives the weight matrix is just the V^-1
+    // it has been chacked above so no need to do it again
+    Amg::MatrixX * W1st = new Amg::MatrixX(*Vinv); //symmetric matrix
+    ATH_MSG_DEBUG("setting weight for 1st derivatives (diagonal only): ");
+    if (msgLvl(MSG::DEBUG)) {
+      for (int i=0;i<W1st->rows();i++) msg()<<(*W1st)(i,i)<<" ";
+      msg()<<endreq;
+    }
+    alignTrack->setWeightMatrixFirstDeriv(W1st);
+
+    return true;
+  }
+
+  //________________________________________________________________________
+  bool AnalyticalDerivCalcTool::getTrkParamCovMatrix(const AlignTrack * alignTrack, Amg::MatrixX & Q /*symmetric matrix*/) const
+  {
+       
+    // get derivative matrices from fitter
+    const Amg::MatrixX * H0 = alignTrack->derivativeMatrix(); 
+    const Amg::MatrixX * C  = alignTrack->fullCovarianceMatrix(); //symmetric matrix
+
+    // H0 is a q0 x p matrix, 
+    // C is a p x p matrix,
+    // q0 = number of tsos measurements
+    // p = number perigee params+2*nscat+nbrem
+
+    if( H0==0 || C==0) {
+      ATH_MSG_ERROR("no derivative matrix or cov matrix stored on AlignTrack!"
+                    << "This should have been done in AlignTrackPreProcessor!"
+                    << H0 << " " << C );
+      return false;
+    }
+
+    ATH_MSG_DEBUG("H0 ( "<<H0->rows()<<" x "<<H0->cols()<<" )");
+    ATH_MSG_DEBUG("H0: "<<(*H0));
+    ATH_MSG_DEBUG("C ( "<<C->rows()<<" x "<<C->cols()<<" )");
+    ATH_MSG_DEBUG("C: "<<(*C));
+
+
+    int    Csize(C->rows());
+    Amg::MatrixX CC(*C);         // take a copy of C //symmetric matrix
+    int    ierr(0);
+    bool   amendC( !(alignTrack->refitD0() && alignTrack->refitZ0() &&
+                     alignTrack->refitPhi() && alignTrack->refitTheta() &&
+                     alignTrack->refitQovP()) );
+
+    // amendC = true;       // FUDGE!
+
+    if( amendC ) {
+      // test with AlSymMat:
+      // build AlSymMat instance from 
+      AlSymMat*     CA = new AlSymMat(Csize);
+
+      // take a copy of C:
+      for( int ii=0; ii<Csize; ++ii ) {
+        for( int jj=ii; jj<Csize; ++jj ) {
+          CA->elemr(ii,jj) = (*C)(ii,jj);
+        }
+      }
+
+      // first inversion:
+      ierr = CA->invert();
+      if( ierr ) {
+        ATH_MSG_ERROR("First inversion of matrix CA failed with LAPACK status flag " << ierr);
+        return false;
+      } else {
+        // disable selected track parametrs (remove from refit).
+        // It is your duty to assure that corresponding constraints have been imposed!
+        if( !(alignTrack->refitD0()) )    {
+          for(int ii=0; ii<(Csize); ++ii) CA->elemr(0,ii)=0.0;   // should do the trick. It is a CLHEP::HepSymMatrix! 
+          CA->elemr(0,0)=1.0;
+        }
+        if( !(alignTrack->refitZ0()) )    {
+          for(int ii=0; ii<(Csize); ++ii) CA->elemr(1,ii)=0.0;   // should do the trick. It is a CLHEP::HepSymMatrix! 
+          CA->elemr(1,1)=1.0;
+        }
+        if( !(alignTrack->refitPhi()) )   {
+          for(int ii=0; ii<(Csize); ++ii) CA->elemr(2,ii)=0.0;   // should do the trick. It is a CLHEP::HepSymMatrix! 
+          CA->elemr(2,2)=1.0;
+        }
+        if( !(alignTrack->refitTheta()) ) {
+          for(int ii=0; ii<(Csize); ++ii) CA->elemr(3,ii)=0.0;   // should do the trick. It is a CLHEP::HepSymMatrix!
+          CA->elemr(3,3)=1.0;
+        } 
+        if( !(alignTrack->refitQovP()) )  {
+          for(int ii=0; ii<(Csize); ++ii) CA->elemr(4,ii)=0.0;   // should do the trick. It is a CLHEP::HepSymMatrix! 
+          CA->elemr(4,4)=1.0;
+        }
+
+
+  // invert back:
+        ierr = CA->invert();
+        if( ierr ) {
+          ATH_MSG_ERROR("Second inversion of matrix CA failed with LAPACK status flag " << ierr);
+          return false;
+        }
+
+        // copy back to CC:
+        for( int ii=0; ii<Csize; ++ii ) {
+          for( int jj=ii; jj<Csize; ++jj ) {
+            CC(ii,jj) = CA->elemc(ii,jj);
+          }
+        }
+
+        // clear the disabled rows/collumns
+        if( !(alignTrack->refitD0()) )    for(int ii=0; ii<(Csize); ++ii){ CC(0,ii)=0.0; CC(ii,0)=0.0;  };   // should do the trick. 
+        if( !(alignTrack->refitZ0()) )    for(int ii=0; ii<(Csize); ++ii){ CC(1,ii)=0.0; CC(ii,1)=0.0;  };   // should do the trick. 
+        if( !(alignTrack->refitPhi()) )   for(int ii=0; ii<(Csize); ++ii){ CC(2,ii)=0.0; CC(ii,2)=0.0;  };   // should do the trick.  
+        if( !(alignTrack->refitTheta()) ) for(int ii=0; ii<(Csize); ++ii){ CC(3,ii)=0.0; CC(ii,3)=0.0;  };   // should do the trick. 
+        if( !(alignTrack->refitQovP()) )  for(int ii=0; ii<(Csize); ++ii){ CC(4,ii)=0.0; CC(ii,4)=0.0;  };   // should do the trick.  
+
+
+      }
+
+      //garbage collection:
+      delete CA;
+    }
+
+
+
+    int nMeas  = H0->rows();
+    int nAtsos = alignTrack->nAlignTSOSMeas();
+    ATH_MSG_DEBUG("nMeas: "<<nMeas);
+
+    //CLHEP::HepSymMatrix HCH(nMeas,0);
+    Amg::MatrixX HCH(nAtsos,nAtsos);
+    HCH = CC.similarity( *H0 );
+
+
+    ATH_MSG_WARNING("CHECK the resulst of this similarity transform");
+
+    ATH_MSG_DEBUG("HCH ( "<<HCH.rows()<<" x "<<HCH.cols()<<" )");
+    ATH_MSG_DEBUG("HCH: "<<HCH);
+
+    //
+    // get indices of HCH matrix corresponding to alignTSOSs in alignTrack
+    const AlignTSOSCollection * alignTSOSCollection = alignTrack->alignTSOSCollection();
+
+    std::vector<int> matrixIndices(nMeas);
+
+    int imeas(-1);
+    std::vector<const TrackStateOnSurface *>::const_iterator tsos     = alignTrack->trackStateOnSurfaces()->begin();
+    std::vector<const TrackStateOnSurface *>::const_iterator tsos_end = alignTrack->trackStateOnSurfaces()->end();
+    for (; tsos!=tsos_end; ++tsos) {
+
+      ATH_MSG_DEBUG("tsos:  "<<(*tsos)->dumpType());
+
+      // get tsos and make sure it is a RIO_OnTrack
+      if ((*tsos)->type(TrackStateOnSurface::Outlier))
+        continue;
+
+      // RIO
+      if (!(*tsos)->type(TrackStateOnSurface::Scatterer)) {
+        ATH_MSG_DEBUG("not scatterer, trying rio");
+
+        const MeasurementBase      * mesb = (*tsos)->measurementOnTrack();
+        const RIO_OnTrack          * rio  = dynamic_cast<const RIO_OnTrack *>(mesb);
+        const CompetingRIOsOnTrack * crio = dynamic_cast<const CompetingRIOsOnTrack *>(mesb);
+        if (!rio && crio)
+          rio=&crio->rioOnTrack(0);
+
+        if (rio==0)
+          continue;
+
+        ++imeas;
+        matrixIndices[imeas]=-1;
+
+        Identifier tsosId = rio->identify();
+        ATH_MSG_DEBUG("have tsos with Id "<<tsosId);
+
+        // get matching alignTSOS and store track index in goodMatrixIndices      
+        int iameas(0);
+        std::vector<AlignTSOS *>::const_iterator atsos=alignTSOSCollection->begin();
+        for (; atsos != alignTSOSCollection->end(); ++atsos) {
+
+          if (!(*atsos)->isValid())
+            continue;
+
+          if ((*atsos)->type(TrackStateOnSurface::Scatterer))
+            ATH_MSG_ERROR("can't use scatterers on AlignTrack yet for analytical derivatives!");
+
+          const RIO_OnTrack * atsos_rio = (*atsos)->rio();
+          if (atsos_rio) {
+//            ATH_MSG_DEBUG("tsosId / atsosId  :  "<<tsosId<<" / "<<atsos_rio->identify());
+
+            if (atsos_rio->identify()==tsosId) {
+              matrixIndices[imeas]=iameas;
+              ATH_MSG_DEBUG("matrixIndices["<<imeas<<"]="<<iameas);
+
+              // for Pixel we have two measurements
+              if ((*atsos)->nResDim()>1)
+              {
+                imeas++;
+                iameas++;
+                matrixIndices[imeas]=iameas;
+                ATH_MSG_DEBUG("matrixIndices["<<imeas<<"]="<<iameas);
+              }
+              break;
+            }
+            // for Pixel we have two measurements
+            else if((*atsos)->nResDim()>1)
+              iameas++;
+          }
+          iameas++;
+        }
+
+        // even when the Pixel is not aligned we have to take into account
+        // that it has two measurements
+        if(matrixIndices[imeas]==-1 && m_measTypeIdHelper->defineType(mesb) == TrackState::Pixel) {
+          imeas++;
+          matrixIndices[imeas]=-1;
+          ATH_MSG_DEBUG("matrixIndices["<<imeas<<"]="<<matrixIndices[imeas]);
+        }
+
+      } // end tsos==rio
+
+    } // end loop over track tsos
+
+    // strip elements in the HCH matrix which don't correspond
+    // to AlignTSOS on alignTrack
+    ATH_MSG_DEBUG("Filling the Q matrix:");
+    for (int k=0;k<nMeas;k++) {
+
+      int iameas=matrixIndices[k];
+      if (iameas==-1)
+        continue;
+
+      for (int l=0;l<nMeas;l++) {
+        int jameas=matrixIndices[l];
+        if (jameas==-1)
+          continue;
+
+        Q(iameas,jameas) = HCH(k,l);
+
+      }
+    }
+
+    ATH_MSG_DEBUG("before check Q ( "<<Q.rows()<<" x "<<Q.cols()<<" )");
+    ATH_MSG_DEBUG("before check Q: "<<Q);
+
+    if(!checkValidity(Q)) {
+      ATH_MSG_DEBUG("Matrix Q = HCH is invalid, skipping the track");
+      return false;
+    }
+
+    return true;
+  }
+
+  //________________________________________________________________________
+  // is this method used used anywhere? maybe we should remove it
+  bool AnalyticalDerivCalcTool::getMeasErrorMatrix(const AlignTrack* alignTrack, Amg::MatrixX& V /*Symmetric Matrix*/) const
+  {
+    int index(0);
+    AlignTSOSCollection::const_iterator itAtsos=alignTrack->firstAtsos();
+    for (; itAtsos != alignTrack->lastAtsos(); ++itAtsos) {      
+
+      std::vector<Residual>::const_iterator itRes=(**itAtsos).firstResidual();
+      for (; itRes!=(**itAtsos).lastResidual(); itRes++,index++) {
+        
+        V(index,index) = itRes->errSq();
+      }
+    }
+    return checkValidity(V);
+  }
+  
+  //________________________________________________________________________
+  bool AnalyticalDerivCalcTool::checkValidity(const Amg::MatrixX& R /*symmetric matrix*/) const
+  {
+    // perform some sort of sanity check. depending on how many hits
+    // on the track we use, R can have zero determinant, but it
+    // should definitely not be negative. for now, we'll just check
+    // that all diagonal elements are positive and that all correlation
+    // coefficients are within bounds
+
+    bool Risvalid(true);
+    const double epsilon=1e-10;
+    for( int irow=0; irow<R.rows(); ++irow) {
+
+      Risvalid = Risvalid && R(irow,irow)>0;
+      if ( msgLvl(MSG::DEBUG) ) {
+        if( !(R(irow,irow)>0) )
+          msg(MSG::DEBUG) << "matrix invalid: (" << irow << "," << irow<<") = " << R(irow,irow) << endreq;
+      }
+      else if (!Risvalid)
+        break;
+
+      for(int icol=0; icol<=irow; ++icol) {
+        // this one must be true if everything else succeeded
+        double Rcorr = R(irow,icol)/sqrt(R(irow,irow)*R(icol,icol));
+        if( Rcorr+epsilon<-1 || Rcorr-epsilon>1 )
+        {
+          Risvalid = false;
+          if (msgLvl(MSG::DEBUG))
+            ATH_MSG_DEBUG("matrix corr invalid for (" << irow << "," << icol << ") Rcorr = " << Rcorr);
+          else
+            break;
+        }
+      }
+    }
+
+    if( !Risvalid ) {
+      ATH_MSG_WARNING("Checked matrix is invalid.");
+      ATH_MSG_WARNING("R: "<<endreq<<R);
+    }
+    return Risvalid;
+  }
+
+  //________________________________________________________________________
+  std::vector<Amg::VectorX> AnalyticalDerivCalcTool::getDerivatives(AlignTrack * alignTrack, const AlignModule * module)
+  {
+    // module-specific transforms
+    Amg::Transform3D globalFrameToAlignFrame = module->globalFrameToAlignFrame();
+    ATH_MSG_DEBUG("globalFrameToAlignFrame: ");
+    ATH_MSG_DEBUG(globalFrameToAlignFrame(0,0)<<" "<<
+                  globalFrameToAlignFrame(0,1)<<" "<<
+                  globalFrameToAlignFrame(0,2));
+    ATH_MSG_DEBUG(globalFrameToAlignFrame(1,0)<<" "<<
+                  globalFrameToAlignFrame(1,1)<<" "<<
+                  globalFrameToAlignFrame(1,2));
+    ATH_MSG_DEBUG(globalFrameToAlignFrame(2,0)<<" "<<
+                  globalFrameToAlignFrame(2,1)<<" "<<
+                  globalFrameToAlignFrame(2,2));
+
+    Amg::RotationMatrix3D globalToAlignFrameRotation = module->globalToAlignFrameRotation();
+    ATH_MSG_DEBUG("globalToAlignFrameRotation: ");
+    ATH_MSG_DEBUG(globalToAlignFrameRotation(0,0)<<" "<<
+                  globalToAlignFrameRotation(0,1)<<" "<<
+                  globalToAlignFrameRotation(0,2));
+    ATH_MSG_DEBUG(globalToAlignFrameRotation(1,0)<<" "<<
+                  globalToAlignFrameRotation(1,1)<<" "<<
+                  globalToAlignFrameRotation(1,2));
+    ATH_MSG_DEBUG(globalToAlignFrameRotation(2,0)<<" "<<
+                  globalToAlignFrameRotation(2,1)<<" "<<
+                  globalToAlignFrameRotation(2,2));
+
+    DataVector<AlignPar> * alignPars = m_alignModuleTool->getAlignPars(module);
+    const int nAlignPar = alignPars->size();
+
+    //Create derivatives storage vector and initialise them ro zero     
+    std::vector<Amg::VectorX> derivatives( nAlignPar+3 , Amg::VectorX(alignTrack->nAlignTSOSMeas()));
+    for(int i(0); i<nAlignPar+3; ++i) derivatives[i].setZero();
+
+    int imeas(0);
+    AlignTSOSCollection::const_iterator iatsos = alignTrack->firstAtsos();
+    for (; iatsos != alignTrack->lastAtsos(); ++iatsos) {
+      
+      AlignTSOS * alignTSOS = *iatsos;
+      if (!alignTSOS->isValid() || 0==alignTSOS->module()) 
+        continue;
+
+      // we only calculate the derivatives if the AlignTSOS belongs to the align module
+      int nResDim = alignTSOS->nResDim();
+      if (alignTSOS->module() != module) {
+        imeas += nResDim;
+        continue;
+      }
+
+      // derivatives to be stored on the AlignTSOS
+      std::vector<Amg::VectorX> * atsosDerivs = 0;
+      std::vector<Amg::VectorX> * atsosDerVtx = 0;
+      if (m_storeDerivatives) {
+        atsosDerivs = new std::vector<Amg::VectorX>(nResDim,Amg::VectorX(nAlignPar));
+        atsosDerVtx = new std::vector<Amg::VectorX>(nResDim,Amg::VectorX(3));
+        ATH_MSG_DEBUG("nResDim = "<<nResDim<<"       vector size is    "<<atsosDerivs->size());
+        ATH_MSG_DEBUG("nAlignPar = "<<nAlignPar<<"   CLHEP::HepVector size is "<<atsosDerivs->at(0).rows());
+      }
+
+      // Get the rotation to the frame in which the residual is
+      // defined. In this frame the trkdistance is the x-coordinate.    
+      
+      const TrackParameters * mtp  = alignTSOS->trackParameters();
+      if (!mtp || !(mtp->covariance()) ) continue;
+      Amg::RotationMatrix3D localToGlobalRotation =    mtp->associatedSurface().transform().rotation();
+       
+
+      ATH_MSG_DEBUG( "localToGlobalRotation:");
+      ATH_MSG_DEBUG(localToGlobalRotation(0,0) << " " <<
+                    localToGlobalRotation(0,1) << " " <<
+                    localToGlobalRotation(0,2));
+      ATH_MSG_DEBUG(localToGlobalRotation(1,0) << " " <<
+                    localToGlobalRotation(1,1) << " " <<
+                    localToGlobalRotation(1,2));
+      ATH_MSG_DEBUG(localToGlobalRotation(2,0) << " " <<
+                    localToGlobalRotation(2,1) << " " <<
+                    localToGlobalRotation(2,2));
+
+      if(double alphastrip=alignTSOS->alphaStrip()) {
+        ATH_MSG_DEBUG( "applying fanout rotation : " << alphastrip );
+        ATH_MSG_ERROR( "CHECK order of rotations"  );
+        localToGlobalRotation = localToGlobalRotation * Amg::AngleAxis3D(alphastrip, Amg::Vector3D(0.,0.,1.));
+        ATH_MSG_DEBUG( "localToGlobalRotation * fanout_rotation:");
+        ATH_MSG_DEBUG(localToGlobalRotation(0,0) << " " <<
+                      localToGlobalRotation(0,1) << " " <<
+                      localToGlobalRotation(0,2));
+        ATH_MSG_DEBUG(localToGlobalRotation(1,0) << " " <<
+                      localToGlobalRotation(1,1) << " " <<
+                      localToGlobalRotation(1,2));
+        ATH_MSG_DEBUG(localToGlobalRotation(2,0) << " " <<
+                      localToGlobalRotation(2,1) << " " <<
+                      localToGlobalRotation(2,2));
+      }
+
+      // get the position of the track in the alignmentframe.
+      Amg::Vector3D refPos = globalFrameToAlignFrame * alignTSOS->trackParameters()->position();
+      ATH_MSG_DEBUG("refPos: "<<refPos);
+
+          
+      const Amg::RotationMatrix3D R = globalToAlignFrameRotation * localToGlobalRotation;
+      ATH_MSG_DEBUG("R:");
+      ATH_MSG_DEBUG(R(0,0) << " " << R(0,1) << " " << R(0,2));
+      ATH_MSG_DEBUG(R(1,0) << " " << R(1,1) << " " << R(1,2));
+      ATH_MSG_DEBUG(R(2,0) << " " << R(2,1) << " " << R(2,2));
+
+      // In the SCT measurement frame:
+      // x --> perpendicular to strips in wafer plane
+      // y --> along strips in wafer plane
+      // z --> perpendicular to wafer plane
+
+      // In the TRT measurement frame:
+      // x --> perpendicular to track and straw
+      // y --> along straw wire
+      // z --> perpendicular to x and y (but not parallel to track!)
+
+      // now 'correct' for the track angle in the measurement frame.
+      const TrackParameters * trkpars = 0;
+      if(m_residualType == HitOnly) {
+        ATH_MSG_DEBUG("using BIASED track parameters");
+        trkpars = alignTSOS->trackParameters();
+      }
+      else {
+        ATH_MSG_DEBUG("using UNBIASED track parameters");
+        trkpars = alignTSOS->unbiasedTrackPars();
+      }
+      
+      
+      Amg::Vector3D trackdir = localToGlobalRotation.inverse()  *  trkpars->momentum();
+      ATH_MSG_DEBUG( "trackdir " << trackdir[0] << " " << trackdir[1] << " " << trackdir[2]);
+
+      // for 1-dimensional measurements and Pixel-x
+      ATH_MSG_DEBUG( "trackdir.z(): " << trackdir.z() );
+      double cotphi_x = trackdir.x() / trackdir.z();
+
+      // some 1D measurements are in Y direction (e.g. in CSC)
+      // so we need the other angle
+      if (alignTSOS->measDir() == Trk::y) 
+        cotphi_x = trackdir.y() / trackdir.z();
+      
+
+      double Rxx = R(0,0) - cotphi_x * R(0,2);
+      double Ryx = R(1,0) - cotphi_x * R(1,2);
+      double Rzx = R(2,0) - cotphi_x * R(2,2);
+      ATH_MSG_DEBUG("Rxx/Ryx/Rzx: " << Rxx << "/" << Ryx << "/" << Rzx);
+
+      double projR[AlignModule::NTransformPar];
+      projR[AlignModule::TransX] = Rxx;
+      projR[AlignModule::TransY] = Ryx;
+      projR[AlignModule::TransZ] = Rzx;
+      projR[AlignModule::RotX] = -Ryx * refPos.z() + Rzx * refPos.y();
+      projR[AlignModule::RotY] = -Rzx * refPos.x() + Rxx * refPos.z();
+      projR[AlignModule::RotZ] = -Rxx * refPos.y() + Ryx * refPos.x();
+
+      // prepare derivatives w.r.t. the vertex position:
+      Amg::Vector3D RxLoc(Rxx, Ryx, Rzx);
+      Amg::Vector3D RxGlob=-1.0 * (globalToAlignFrameRotation.inverse() * RxLoc);        // to be double checked!!!
+   
+      for (int ipar=0; ipar<nAlignPar; ipar++) {
+        const AlignPar * alignPar = (*alignPars)[ipar];
+        int paramType = alignPar->paramType();
+        //double sigma  = alignPar->sigma();
+        ATH_MSG_DEBUG("ipar="<<ipar<<", paramType="<<paramType);
+        derivatives[ipar][imeas] = projR[paramType];//*sigma;
+        if (m_storeDerivatives)
+          (*atsosDerivs)[0][ipar] = projR[paramType];//*sigma;
+      }
+      // the dr/db bit:
+      for (int ipar=0; ipar<3; ipar++) {
+        derivatives[nAlignPar+ipar][imeas] = RxGlob[ipar];
+        if (m_storeDerivatives)   (*atsosDerVtx)[0][ipar] = RxGlob[ipar];
+      }
+
+      for (int i=0;i<nAlignPar+3;i++)
+        ATH_MSG_DEBUG("derivatives["<<i<<"]["<<imeas<<"]="<<derivatives[i][imeas]);
+
+      imeas++;
+
+      if (nResDim>1) {
+        // for Pixel the second measurement has to be corrected
+        // for the second angle
+        double cotphi_y = trackdir.y() / trackdir.z() ;
+        double Rxy = R(0,1) - cotphi_y * R(0,2) ;
+        double Ryy = R(1,1) - cotphi_y * R(1,2) ;
+        double Rzy = R(2,1) - cotphi_y * R(2,2) ;
+        ATH_MSG_DEBUG("Rxy/Ryy/Rzy: " << Rxy << "/" << Ryy << "/" << Rzy);
+
+        projR[AlignModule::TransX] = Rxy;
+        projR[AlignModule::TransY] = Ryy;
+        projR[AlignModule::TransZ] = Rzy;
+        projR[AlignModule::RotX] = -Ryy * refPos.z() + Rzy * refPos.y();
+        projR[AlignModule::RotY] = -Rzy * refPos.x() + Rxy * refPos.z();
+        projR[AlignModule::RotZ] = -Rxy * refPos.y() + Ryy * refPos.x();
+
+        // prepare derivatives w.r.t. the vertex position:
+        Amg::Vector3D RyLoc(Rxy, Ryy, Rzy);
+        Amg::Vector3D RyGlob=-1.0 * (globalToAlignFrameRotation.inverse() * RyLoc);        // to be double checked!!!
+
+        for (int ipar=0; ipar<nAlignPar; ipar++) {
+          const AlignPar * alignPar = (*alignPars)[ipar];
+          int paramType = alignPar->paramType();
+          ATH_MSG_DEBUG("2nd dim, ipar="<<ipar<<", paramType="<<paramType);
+          //double sigma=alignPar->sigma();
+          derivatives[ipar][imeas] = projR[paramType];//*sigma;
+          if (m_storeDerivatives)
+            (*atsosDerivs)[1][ipar] = projR[paramType];//*sigma;
+        }
+        
+        // the dr/db bit:
+        for (int ipar=0; ipar<3; ipar++) {
+          derivatives[nAlignPar+ipar][imeas] = RyGlob[ipar];
+          if (m_storeDerivatives)   (*atsosDerVtx)[1][ipar] = RyGlob[ipar];
+        }
+
+        for (int i=0;i<nAlignPar+3;i++)
+          ATH_MSG_DEBUG("2nd dim: derivatives["<<i<<"]["<<imeas<<"]="<<derivatives[i][imeas]);
+
+        imeas++;
+      }
+
+      alignTSOS->setDerivatives(atsosDerivs);
+      alignTSOS->setDerivativesVtx(atsosDerVtx);
+    }
+    ATH_MSG_DEBUG("returning derivatives");
+    return derivatives;
+  }
+
+  //________________________________________________________________________
+  void AnalyticalDerivCalcTool::checkResidualType(const AlignTrack * alignTrack)
+  {
+    // get first AlignTSOS of the AlignTrack
+    // this assumes that for unbiased or DCA residuals the scatterers
+    // and energy deposits are not included in the AlignTSOSSollection
+    AlignTSOS * atsos = *(alignTrack->firstAtsos());
+
+    // get residual type of the first residual
+    m_residualType = atsos->firstResidual()->residualType();
+    ATH_MSG_DEBUG("setting residualType to "<<m_residualType);
+
+    m_residualTypeSet = true;
+  }
+
+} // end namespace
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/BeamspotVertexPreProcessor.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/BeamspotVertexPreProcessor.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6fcf7d6e0def6429cdf852089a7d908cc0ea4679
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/BeamspotVertexPreProcessor.cxx
@@ -0,0 +1,1140 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "TrkAlignGenTools/BeamspotVertexPreProcessor.h"
+//#include "TrkAlignGenTools/CompareTwoTracks.h"
+#include "TrkFitterInterfaces/IGlobalTrackFitter.h"
+#include "TrkFitterInterfaces/ITrackFitter.h"
+#include "TrkExInterfaces/IExtrapolator.h"
+#include "TrkToolInterfaces/ITrackSelectorTool.h"
+#include "InDetBeamSpotService/IBeamCondSvc.h"
+#include "TrkAlignEvent/AlignTrack.h"
+#include "TrkAlignEvent/AlignVertex.h"
+#include "TrkVertexOnTrack/VertexOnTrack.h"
+
+#include "TrkEventPrimitives/ParticleHypothesis.h"
+
+#include "DataModel/DataVector.h"
+#include "GaudiKernel/SmartDataPtr.h"
+
+#include "VxVertex/VxContainer.h"
+#include "VxVertex/VxCandidate.h"
+#include "VxVertex/VxTrackAtVertex.h"
+#include "TrkVertexFitterInterfaces/IVertexLinearizedTrackFactory.h"
+#include "TrkVertexFitterInterfaces/IVertexUpdator.h"
+
+#include "TrkTrack/TrackCollection.h"
+#include "TrkTrack/Track.h"
+#include "TrkTrack/LinkToTrack.h"
+#include "TrkParticleBase/LinkToTrackParticleBase.h"
+#include "TrkParticleBase/TrackParticleBase.h"
+
+#include "TrkSurfaces/PerigeeSurface.h"
+#include "TrkParameters/TrackParameters.h"
+
+#include "TrkAlignInterfaces/IAlignModuleTool.h"
+
+#include "TrkMeasurementBase/MeasurementBase.h"
+
+#include <ext/algorithm>
+#include <functional>
+
+
+namespace Trk {
+
+//________________________________________________________________________
+BeamspotVertexPreProcessor::BeamspotVertexPreProcessor(const std::string & type,
+                                                       const std::string & name,
+                                                       const IInterface  * parent)
+  : AthAlgTool(type,name,parent)
+  , m_trackFitter("Trk::GlobalChi2Fitter/InDetTrackFitter")
+  , m_SLTrackFitter("")
+  , m_extrapolator("Trk::Extrapolator/AtlasExtrapolator")
+  , m_trkSelector("")
+  , m_BSTrackSelector("")
+  , m_IVertexUpdator("Trk::KalmanVertexUpdator")
+  , m_linFactory("Trk::FullLinearizedTrackFactory")
+  , m_alignModuleTool("Trk::AlignModuleTool/AlignModuleTool")
+  , m_beamCondSvc("BeamCondSvc",name)
+  , m_PVContainerName("VxPrimaryCandidate")
+  , m_runOutlierRemoval(false)
+  , m_selectVertices(true)
+  , m_particleNumber(3)                          // 3=pion, 0=non-interacting
+  , m_doBSTrackSelection(false)
+  , m_doAssociatedToPVSelection(true)
+  , m_constraintMode(0)
+  , m_compareMethod("compareAddress") 
+  , m_doBeamspotConstraint(true)
+  , m_doPrimaryVertexConstraint(false) 
+  , m_doFullVertexConstraint(false)
+  , m_refitTracks(true)
+  , m_storeFitMatrices(true)
+  , m_useSingleFitter(false)
+  , m_selectTracks(true)
+  , m_BSScalingFactor(1.)
+  , m_PVScalingFactor(1.)
+  , m_minTrksInVtx(3)
+  , m_nTracks(0)
+  , m_trackTypeCounter(AlignTrack::NTrackTypes,0)
+  , m_nFailedNormalRefits(0)
+  , m_nFailedBSRefits(0)
+  , m_nFailedPVRefits(0)
+{
+  declareInterface<IAlignTrackPreProcessor>(this);
+  declareProperty("RefitTracks",               m_refitTracks      );
+  declareProperty("PVContainerName",           m_PVContainerName    );
+  declareProperty("TrackFitter",               m_trackFitter      );
+  declareProperty("SLTrackFitter",             m_SLTrackFitter      );
+  declareProperty("UseSingleFitter",           m_useSingleFitter    );
+  declareProperty("Extrapolator",              m_extrapolator             );
+  declareProperty("RunOutlierRemoval",         m_runOutlierRemoval        );
+  declareProperty("AlignModuleTool",           m_alignModuleTool          );
+  declareProperty("ParticleNumber",            m_particleNumber           );
+  declareProperty("TrackSelector",             m_trkSelector              );
+  declareProperty("BSConstraintTrackSelector", m_BSTrackSelector          );
+  declareProperty("DoBSTrackSelection",        m_doBSTrackSelection       );
+  declareProperty("DoAssociatedToPVSelection", m_doAssociatedToPVSelection);
+  declareProperty("DoBSConstraint",            m_doBeamspotConstraint     ,"Constrain tracks to the beamspot (x,y) position");
+  declareProperty("DoPVConstraint",            m_doPrimaryVertexConstraint,"Constrain tracks to the associated primary vertex (x,y,z) position");
+  declareProperty("DoFullVertex",              m_doFullVertexConstraint   ,"Full 3D vertex constraint.  Note DoPVConstraint needs to be set to true to use this option. If DoBSConstraint vertex position will be constrained to the BS" );
+  declareProperty("ConstraintMode",            m_constraintMode           );
+  declareProperty("StoreFitMatrices",          m_storeFitMatrices         );
+  declareProperty("BeamspotScalingFactor",     m_BSScalingFactor          );
+  declareProperty("PrimaryVertexScalingFactor",m_PVScalingFactor          );
+  declareProperty("MinTrksInVtx",              m_minTrksInVtx             );
+
+  std::vector<std::string> defaultInterestedVertexContainers;
+  defaultInterestedVertexContainers.push_back("VxPrimaryCandidate");
+  defaultInterestedVertexContainers.push_back("V0Candidates");
+  m_interestedVertexContainers = defaultInterestedVertexContainers;
+
+
+  m_logStream = 0;
+}
+
+//________________________________________________________________________
+BeamspotVertexPreProcessor::~BeamspotVertexPreProcessor()
+{
+}
+
+//________________________________________________________________________
+StatusCode BeamspotVertexPreProcessor::initialize()
+{
+  ATH_MSG_INFO("BeamspotVertexPreProcessor::initialize()");
+
+  // configure main track selector if requested
+  if (!m_trkSelector.empty()) {
+    if (m_trkSelector.retrieve().isFailure())
+      msg(MSG::ERROR)<<"Failed to retrieve tool "<<m_trkSelector<<". No Track Selection will be done."<<endreq;
+    else
+      ATH_MSG_INFO("Retrieved " << m_trkSelector);
+  }
+  
+  if (m_refitTracks) {
+    // configure main track fitter
+    if(m_trackFitter.retrieve().isFailure()) {
+       msg(MSG::FATAL) << "Could not get " << m_trackFitter << endreq;
+       return StatusCode::FAILURE;
+    }
+    ATH_MSG_INFO("Retrieved " << m_trackFitter);
+    
+    // configure straight-line track fitter if requested
+    if (!m_useSingleFitter) {
+      if (m_SLTrackFitter.retrieve().isFailure()) {
+        msg(MSG::FATAL) << "Could not get " << m_SLTrackFitter << endreq;
+        return StatusCode::FAILURE;
+      }
+      ATH_MSG_INFO("Retrieved " << m_SLTrackFitter);
+    }
+    
+    //linearized track factory
+    msg(MSG::FATAL) << "Correct code to use the folowing tool " << endreq;
+    return StatusCode::FAILURE;
+       
+
+    if (m_linFactory.retrieve().isFailure()){
+      msg(MSG::FATAL) << "Failed to retrieve tool " << m_linFactory << endreq;
+      return StatusCode::FAILURE;
+    } else {
+      msg(MSG::INFO) << "Retrieved VertexLinearizedTrackFactory tool " << m_linFactory << endreq;
+    }
+
+     // KalmanVertexUpdator
+    if (m_IVertexUpdator.retrieve().isFailure()) {
+      if(msgLvl(MSG::FATAL)) msg(MSG::FATAL) << "Can not retrieve VertexUpdator of type " << m_IVertexUpdator.typeAndName() << endreq;
+        return StatusCode::FAILURE;
+    } else { 
+      ATH_MSG_INFO ( "Retrieved VertexUpdator Tool " << m_IVertexUpdator.typeAndName() );
+    }
+    
+    
+    // configure Atlas extrapolator
+    if (m_extrapolator.retrieve().isFailure()) {
+      msg(MSG::FATAL) << "Failed to retrieve tool "<<m_extrapolator<<endreq;
+      return StatusCode::FAILURE;
+    }
+    ATH_MSG_INFO("Retrieved " << m_extrapolator);
+    
+    // configure beam-spot conditions service
+    if (m_beamCondSvc.retrieve().isFailure()) {
+      msg(MSG::FATAL)<<"Failed to retrieve beamspot service "<<m_beamCondSvc<<endreq;
+      return StatusCode::FAILURE;
+    }
+    ATH_MSG_INFO("Retrieved " << m_beamCondSvc);
+    
+    // configure beam-spot track selector if requested
+    if(m_doBSTrackSelection) {
+      if(m_BSTrackSelector.empty()) {
+        msg(MSG::FATAL) << "Requested BeamSpot track selection but Track Selector not configured"<< endreq;
+        return StatusCode::FAILURE;
+      }
+      if (m_BSTrackSelector.retrieve().isFailure()) {
+         msg(MSG::FATAL) << "Could not get " << m_BSTrackSelector<< endreq;
+         return StatusCode::FAILURE;
+      }
+      ATH_MSG_INFO("Retrieved " << m_BSTrackSelector);
+    }
+
+  }  // end of 'if (m_refitTracks)'
+
+  else if (m_doBeamspotConstraint) {
+    msg(MSG::FATAL)<<"Requested beam-spot constraint but RefitTracks is False."<<endreq;
+    return StatusCode::FAILURE;
+  }
+
+  if( m_doFullVertexConstraint && m_doPrimaryVertexConstraint ) {
+    if ( m_alignModuleTool.retrieve().isFailure() ) {
+      ATH_MSG_FATAL("Failed to retrieve tool " << m_alignModuleTool);
+      return StatusCode::FAILURE;
+    } 
+    else {
+      ATH_MSG_INFO("Retrieved tool " << m_alignModuleTool);
+
+      ATH_MSG_INFO("************************************************************************");
+      ATH_MSG_INFO("*                                                                      *");
+      ATH_MSG_INFO("* You have requested the Full Vertex Constraint option.                *");
+      ATH_MSG_INFO("* It is your duty to assure that all detector elements                 *");
+      ATH_MSG_INFO("* used for track fitting are also loaded in the alignment framework!!! *");
+      ATH_MSG_INFO("*                                                                      *");
+      ATH_MSG_INFO("* Also make sure the accurate track covariance matrix                  *");
+      ATH_MSG_INFO("* is returned by the GlobalChi2Fitter!                                 *");
+      ATH_MSG_INFO("*                                                                      *");
+      ATH_MSG_INFO("************************************************************************");
+    }
+
+  }
+
+    
+  return StatusCode::SUCCESS;
+}
+
+
+
+bool CompareTwoTracks::operator()(VxTrackAtVertex* vtxTrk){
+
+  ITrackLink* trkLink = vtxTrk->trackOrParticleLink();
+  LinkToTrackParticleBase* linkToTrackParticle = dynamic_cast<Trk::LinkToTrackParticleBase*>(trkLink);
+  if(!linkToTrackParticle) return false;
+    const TrackParticleBase* tpb = *(linkToTrackParticle->cptr());
+ 
+  const Track* originalTrk = tpb->originalTrack();         
+
+
+  bool equal = false;
+  // compare the addresses of these two tracks directly 
+  if(m_method.find("compareAddress") != std::string::npos){
+     if (m_track == originalTrk) equal = true;
+     //std::cout << " comparing two Tracks' addresses directly, the address of the comparing track : "<< m_track <<" the address of the compared track : "<< originalTrk << " compare result : " << equal << std::endl;
+  }
+
+  // compare the perigee parameters of these two tracks, should safer
+  if(m_method.find("comparePerigee") != std::string::npos){
+    const Trk::Perigee * measPer1 = m_track->perigeeParameters();
+    const Trk::Perigee * measPer2 = originalTrk->perigeeParameters();
+    if(! (measPer1 && measPer2 )) equal = false;
+    else{
+      float diff = fabs(std::numeric_limits<float>::epsilon());
+      if( ! (( fabs(measPer1->parameters()[Trk::d0]     - measPer2->parameters()[Trk::d0])     <= diff)
+         && ( fabs(measPer1->parameters()[Trk::z0]     - measPer2->parameters()[Trk::z0])     <= diff)
+         && ( fabs(measPer1->parameters()[Trk::phi]    - measPer2->parameters()[Trk::phi])    <= diff)
+         && ( fabs(measPer1->parameters()[Trk::theta]  - measPer2->parameters()[Trk::theta])  <= diff)
+         && ( fabs(measPer1->parameters()[Trk::qOverP] - measPer2->parameters()[Trk::qOverP]) <= diff)))
+              equal = false;
+    }
+     //std::cout << " comparing two Tracks' perigee parameter, the perigee of the comparing track is: "<< *measPer1 <<" the perigee of the compared track is: "<< *measPer2 << " compare result is: " << equal << std::endl;
+  }
+  return equal;
+}
+
+
+
+bool BeamspotVertexPreProcessor::selectVertices(const Trk::VxCandidate* vtx) const {
+
+  if(0 == vtx->vertexType()) {
+     ATH_MSG_DEBUG("this primary vertex has been rejected as type dummy");
+     return false;
+  }
+  if (vtx->recVertex().fitQuality().numberDoF() <= 0){
+      ATH_MSG_WARNING(" VERY STRANGE!!!, this primary vertex has been rejected as non-positive DoF "<< vtx->recVertex().fitQuality().numberDoF() <<" the type of this vertex: "<<  vtx->vertexType() );  
+      return false;
+  }
+  if (int(vtx->vxTrackAtVertex()->size()) < m_minTrksInVtx){
+      ATH_MSG_DEBUG(" this primary vertex vxTrackAtVertex size:  "<< vtx->vxTrackAtVertex()->size() );
+      return false;
+  }
+  return true;
+}
+
+
+
+bool BeamspotVertexPreProcessor::selectUpdatedVertices(const Trk::VxCandidate* vtx) const {
+
+  if (vtx->recVertex().fitQuality().numberDoF() <= 0){
+      ATH_MSG_WARNING(" VERY STRANGE!!! , the updated vertex has been rejected as non-positive DoF: "<< vtx->recVertex().fitQuality().numberDoF() <<" the type of this vertex:"<<  vtx->vertexType() );
+      return false;
+  }
+
+  if (int(vtx->vxTrackAtVertex()->size()) < m_minTrksInVtx){
+      ATH_MSG_DEBUG(" the updated vertex has been rejected as vxTrackAtVertex size:  "<< vtx->vxTrackAtVertex()->size() );
+      return false;
+  }
+
+  if ((vtx->recVertex().covariancePosition())(0,0)<=0  ||
+      (vtx->recVertex().covariancePosition())(1,1)<=0  ||
+      (vtx->recVertex().covariancePosition())(2,2)<=0){
+      ATH_MSG_WARNING(" VERY STRANGE!!! , this updated vertex has been rejected as negative diagonal error matrix "); 
+      return false;
+  }
+  return true;
+}
+
+
+
+bool BeamspotVertexPreProcessor::isAssociatedToPV(const Trk::Track * track, const VxContainer * vertices)
+{
+  if(!vertices)
+      return false;
+
+  VxContainer::const_iterator vtxEnd   = vertices->end();
+  VxContainer::const_iterator vtxIter  = vertices->begin();
+ 
+  for ( ; vtxIter != vtxEnd  && (*vtxIter)->vertexType() == 1; ++vtxIter ){
+        if (isAssociatedToVertex(track, *vtxIter)) return true;  
+  } 
+  return false;
+}
+
+
+
+
+//____________________________________________________________________________
+bool BeamspotVertexPreProcessor::isAssociatedToVertex(const Trk::Track * track, const VxCandidate * vertex)
+{
+  if(!vertex)
+    return false;
+
+  const std::vector<VxTrackAtVertex *> * vertexTracks = vertex->vxTrackAtVertex();
+  Trk::CompareTwoTracks thisCompare(track, m_compareMethod);
+
+  std::vector<VxTrackAtVertex* >::const_iterator iVxTrackBegin = vertexTracks->begin();
+  std::vector<VxTrackAtVertex* >::const_iterator iVxTrackEnd   = vertexTracks->end();
+
+  std::vector<VxTrackAtVertex*>::const_iterator findResult = std::find_if(iVxTrackBegin, iVxTrackEnd, thisCompare);
+
+  if(findResult != iVxTrackEnd)
+     return true;
+
+  return false;
+}
+
+
+
+void BeamspotVertexPreProcessor::prepareAllTracksVector(){
+
+  // do clean up firstly
+  m_allTracksVector.clear();
+  const VxContainer* thisContainer = 0;
+
+  std::vector<std::string>::const_iterator strs_iter = m_interestedVertexContainers.begin();
+  std::vector<std::string>::const_iterator strs_end  = m_interestedVertexContainers.end();
+
+  for(; strs_iter != strs_end; ++strs_iter){
+
+    StatusCode sc = evtStore()->retrieve( thisContainer, *strs_iter);
+    if( sc.isFailure()  ||  !thisContainer ) {
+        ATH_MSG_WARNING("No VxContainer "<< *strs_iter <<" found in TDS tried ");
+        continue;
+    } else {
+      
+      VxContainer::const_iterator vtxEnd   = thisContainer->end();
+      VxContainer::const_iterator vtxIter  = thisContainer->begin();
+    
+      for(; vtxIter != vtxEnd; ++vtxIter){
+        if(m_selectVertices && !selectVertices(*vtxIter)) {
+          ATH_MSG_DEBUG("this vertex did not pass the primary vertex selection...");
+          continue;
+        }             
+        
+        std::vector<VxTrackAtVertex*>*  vtxTracks = (*vtxIter)->vxTrackAtVertex();
+        m_allTracksVector.push_back(std::make_pair(*vtxIter,vtxTracks));
+      }
+    } 
+  }       
+  ATH_MSG_DEBUG("m_allTracksVector size: "<<m_allTracksVector.size());
+}
+
+
+
+const std::pair<const VxCandidate*, VxTrackAtVertex*> BeamspotVertexPreProcessor::findVertexCandidate(const Track* track) const {
+
+  const VxCandidate*     findVxCandidate = 0;
+  VxTrackAtVertex* findVxTrack = 0;
+
+  std::vector< std::pair< VxCandidate*, std::vector<VxTrackAtVertex*>* > >::const_iterator iter    = m_allTracksVector.begin();
+  std::vector< std::pair< VxCandidate*, std::vector<VxTrackAtVertex*>* > >::const_iterator iterEnd = m_allTracksVector.end();
+  
+  for(; iter != iterEnd; ++iter){
+    std::pair< VxCandidate*, std::vector<VxTrackAtVertex*>* > thisPair = *iter;
+    //ATH_MSG_DEBUG(" this VxCandidate* and vector<VxTrackAtVertex*>* Pair: "<< *(thisPair.first));
+    
+    std::vector<VxTrackAtVertex*>::iterator iVxTrackBegin  = (thisPair.second)->begin();
+    std::vector<VxTrackAtVertex*>::iterator iVxTrackEnd    = (thisPair.second)->end();
+    Trk::CompareTwoTracks thisCompare(track, m_compareMethod);
+    
+    std::vector<VxTrackAtVertex*>::iterator findResult = std::find_if(iVxTrackBegin, iVxTrackEnd, thisCompare);
+    
+    if(findResult != iVxTrackEnd){
+      ATH_MSG_DEBUG("the found VxTrackAtVertex: "<<**findResult);
+      findVxCandidate      = thisPair.first;
+      findVxTrack          = *findResult;
+      break;
+    }
+  }
+
+  if  ( !(findVxCandidate && findVxTrack) ) 
+    ATH_MSG_DEBUG("the track don't not belongs to any interested Vertex! ");
+
+  return std::make_pair(findVxCandidate, findVxTrack); 
+}
+
+
+
+const VertexOnTrack* BeamspotVertexPreProcessor::provideVotFromVertex(const Track* track, const VxCandidate* &vtx) const {
+
+  VxTrackAtVertex* vtxTrk       = 0;
+  const VertexOnTrack * vot     = 0;
+  VxCandidate* tmpVtx           = 0;
+  VxCandidate* updatedVtx       = 0;
+
+  const std::pair<const VxCandidate*, VxTrackAtVertex*> findPair = findVertexCandidate(track);  
+ 
+  ATH_MSG_DEBUG("findPair in provideVotFromVertex: "<<findPair);
+ 
+  if (!( 0==findPair.first || 0==findPair.second )) {
+    vtx    = findPair.first;
+    vtxTrk = findPair.second;
+    const RecVertex & rvtx = vtx->recVertex();
+    ATH_MSG_DEBUG("the vertex position in provideVotFromVertex:  "<< rvtx);
+    
+    //////////////////////////////////////////////////////////////////////////     
+    
+    
+    ATH_MSG_WARNING("Commented out line to make code compile  --- correct when vertex classes are updated");
+    // if(!vtxTrk->linState()) m_linFactory->linearize(*vtxTrk, rvtx);
+    
+    if( m_doFullVertexConstraint ) {
+      updatedVtx = vtx->clone();
+    } else {
+      tmpVtx = vtx->clone();
+      updatedVtx = m_IVertexUpdator->remove(*tmpVtx, *vtxTrk);
+    }
+    
+      
+    if(updatedVtx){
+      
+      if(!selectUpdatedVertices(updatedVtx))
+        return vot;
+      
+      if( !m_doFullVertexConstraint ) 
+        ATH_MSG_DEBUG(" updated Vertex by KalmanVertexUpdator: "<<*updatedVtx);
+      
+      
+      ///vertex as perigeeSurface
+      Amg::Vector3D  globPos(updatedVtx->recVertex().position());
+      const PerigeeSurface* surface = new PerigeeSurface(globPos);
+      
+      
+      const Perigee *  perigee = dynamic_cast<const Perigee*>(m_extrapolator->extrapolate(*track, *surface));
+      if (!perigee) {
+        const Perigee * trackPerigee = track->perigeeParameters();
+        if ( trackPerigee && trackPerigee->associatedSurface() == *surface )
+          perigee = trackPerigee->clone();
+      }
+      
+      // create the Jacobian matrix from Cartisian to Perigee
+      AmgMatrix(2,3) Jacobian;
+      Jacobian.setZero();
+      double ptInv                               =  1./perigee->momentum().perp();
+      Jacobian(0,0)                              = -ptInv*perigee->momentum().y();
+      Jacobian(0,1)                              =  ptInv*perigee->momentum().x();
+      Jacobian(1,2)                              =  1.0;
+      
+      ATH_MSG_DEBUG(" Jacobian matrix from Cartesian to Perigee: "<< Jacobian);
+      
+      AmgSymMatrix(3) vtxCov;//= updatedVtx->recVertex().errorPosition().covariance();
+      
+      //std::cout  << " before PV scaling : "<< vtxCov << std::endl;
+      
+      vtxCov *= m_PVScalingFactor * m_PVScalingFactor; 
+      
+      //std::cout  << " after PV scaling : "<< vtxCov << std::endl;
+
+      Amg::MatrixX errorMatrix;
+      if( m_doFullVertexConstraint ) {
+        AmgSymMatrix(3)  tmpCov;
+	tmpCov.setZero();
+        tmpCov(0,0) = 1.e-10 ; 
+        tmpCov(1,1) = 1.e-10; 
+        tmpCov(2,2) = 1.e-10;       
+        errorMatrix = Amg::MatrixX( tmpCov.similarity(Jacobian) );
+      } else {
+        errorMatrix = Amg::MatrixX( vtxCov.similarity(Jacobian) );
+      }  
+      delete perigee;
+      
+      // in fact, in most of the normal situation, pointer tmpVtx and updatedVtx are the same. You can check the source code
+      // But for safety, I would like to delete them seperately 
+      if( tmpVtx )     delete tmpVtx;
+
+      if( updatedVtx ) delete updatedVtx;
+
+      LocalParameters localParams = Trk::LocalParameters(Amg::Vector2D(0,0));
+            
+      // VertexOnTrack Object
+      vot = new VertexOnTrack(localParams, errorMatrix, *surface);
+      ATH_MSG_DEBUG("the VertexOnTrack created from vertex: "<<*vot);
+      // garbage collection:
+      delete surface;
+    }
+  }
+
+  return vot;
+
+}
+
+
+const VertexOnTrack* BeamspotVertexPreProcessor::provideVotFromBeamspot(const Track* track) const{
+
+  const VertexOnTrack * vot = 0;
+
+  Amg::Vector3D  bpos = m_beamCondSvc->beamPos();
+  ATH_MSG_DEBUG("beam spot: "<<bpos);
+  float beamSpotX = bpos.x();
+  float beamSpotY = bpos.y();
+  float beamSpotZ = bpos.z();
+  float beamTiltX = m_beamCondSvc->beamTilt(0);
+  float beamTiltY = m_beamCondSvc->beamTilt(1);
+  float beamSigmaX = m_BSScalingFactor * m_beamCondSvc->beamSigma(0);
+  float beamSigmaY = m_BSScalingFactor * m_beamCondSvc->beamSigma(1);
+  //float beamSigmaZ = m_scalingFactor * m_beamCondSvc->beamSigma(2);
+
+  ATH_MSG_DEBUG("running refit with beam-spot");
+
+  
+  float z0 = track->perigeeParameters()->parameters()[Trk::z0];
+  float beamX = beamSpotX + tan(beamTiltX) * (z0-beamSpotZ);
+  float beamY = beamSpotY + tan(beamTiltY) * (z0-beamSpotZ);
+  Amg::Vector3D  BSC(beamX, beamY, z0);
+  ATH_MSG_DEBUG("constructing beam point (x,y,z) = ( "<<beamX<<" , "<<beamY<<" , "<<z0<<" )");
+
+  const PerigeeSurface * surface = 0;
+  Amg::MatrixX  errorMatrix;
+  LocalParameters beamSpotParameters;
+  
+  // covariance matrix of the beam-spot
+  AmgSymMatrix(2) beamSpotCov;
+  beamSpotCov.setZero();
+  beamSpotCov(0,0) = beamSigmaX * beamSigmaX;
+  beamSpotCov(1,1) = beamSigmaY * beamSigmaY;
+
+  if(m_constraintMode == 0) {
+
+    Amg::Vector3D  globPos(BSC);
+    surface = new PerigeeSurface(globPos);
+
+    // create a measurement for the beamspot
+    DefinedParameter Par0(0.,Trk::d0);
+    beamSpotParameters = LocalParameters(Par0);
+  
+    // calculate perigee parameters wrt. beam-spot
+    const Perigee * perigee = dynamic_cast<const Perigee*>(m_extrapolator->extrapolate(*track, *surface));
+    if (!perigee) {
+      const Perigee * trackPerigee = track->perigeeParameters();
+      if ( trackPerigee && trackPerigee->associatedSurface() == *surface )
+        perigee = trackPerigee->clone();
+    }
+  
+    Amg::MatrixX jacobian(1,2);
+    jacobian.setZero();
+    double ptInv   =  1./perigee->momentum().perp();
+    jacobian(0,0) = -ptInv * perigee->momentum().y();
+    jacobian(0,1) =  ptInv * perigee->momentum().x();
+  
+    // HACKED
+    errorMatrix = Amg::MatrixX( jacobian.transpose() * beamSpotCov * jacobian );   // similarity transform by hand
+    if( errorMatrix.cols() != 1  )
+         ATH_MSG_FATAL("Similarity transpose done incorrectly");
+    delete perigee;
+  }
+
+  vot = new VertexOnTrack(beamSpotParameters, errorMatrix, *surface);
+  ATH_MSG_DEBUG(" the VertexOnTrack objects created from BeamSpot are " << *vot);
+  // garbage collection:
+  delete surface;
+
+  return vot;
+}
+
+
+void BeamspotVertexPreProcessor::provideVtxBeamspot(const AlignVertex* b, AmgSymMatrix(3)* q, Amg::Vector3D* v) const {
+
+
+  Amg::Vector3D bpos = m_beamCondSvc->beamPos();
+  ATH_MSG_DEBUG("beam spot: "<<bpos);
+  float beamSpotX = bpos.x();
+  float beamSpotY = bpos.y();
+  float beamSpotZ = bpos.z();
+  float beamTiltX = m_beamCondSvc->beamTilt(0);
+  float beamTiltY = m_beamCondSvc->beamTilt(1);
+  float beamSigmaX = m_BSScalingFactor * m_beamCondSvc->beamSigma(0);
+  float beamSigmaY = m_BSScalingFactor * m_beamCondSvc->beamSigma(1);
+  float beamSigmaZ = m_BSScalingFactor * m_beamCondSvc->beamSigma(2);
+
+  
+  float z0 = b->originalPosition()->z();
+  (*v)(0) = beamSpotX + tan(beamTiltX) * (z0-beamSpotZ);
+  (*v)(1) = beamSpotY + tan(beamTiltY) * (z0-beamSpotZ);
+  (*v)(2) = beamSpotZ;
+  (*q)(0,0) = beamSigmaX*beamSigmaX;
+  (*q)(1,1) = beamSigmaY*beamSigmaY;
+  (*q)(2,2) = beamSigmaZ*beamSigmaZ;
+
+  ATH_MSG_DEBUG("VTX constraint point (x,y,z) = ( "<< (*v)[0] <<" , "<< (*v)[1] <<" , "<< (*v)[2] <<" )");
+  ATH_MSG_DEBUG("VTX constraint size  (x,y,z) = ( "<< beamSigmaX <<" , "<< beamSigmaY <<" , "<< beamSigmaZ <<" )");
+
+  return;
+}
+
+
+
+const Track* BeamspotVertexPreProcessor::doConstraintRefit(ToolHandle<Trk::IGlobalTrackFitter>& fitter, const Track* track,  const VertexOnTrack* vot, const ParticleHypothesis& particleHypothesis) const{
+
+  const Track* newTrack = 0;
+
+  if(vot){ 
+
+    std::vector<const MeasurementBase *> measurementCollection;
+    measurementCollection.push_back(vot);
+    // add all other measurements
+    DataVector<const MeasurementBase>::const_iterator imeas     = track->measurementsOnTrack()->begin();
+    DataVector<const MeasurementBase>::const_iterator imeas_end = track->measurementsOnTrack()->end();
+    for ( ; imeas != imeas_end ; ++imeas)  measurementCollection.push_back(*imeas);
+    
+    if( m_doFullVertexConstraint ) {
+      // get track parameters at the vertex:
+      PerigeeSurface         surface=vot->associatedSurface();
+      ATH_MSG_DEBUG(" Track reference surface will be:  " << surface);
+      const TrackParameters* parsATvertex=m_extrapolator->extrapolate(*track, surface);
+      
+      ATH_MSG_DEBUG(" Track will be refitted at this surface  ");
+      newTrack = fitter->fit(measurementCollection, *parsATvertex, m_runOutlierRemoval, particleHypothesis);
+      delete parsATvertex;
+    } else {   
+      newTrack = fitter->fit(measurementCollection, *(track->trackParameters()->front()), m_runOutlierRemoval, particleHypothesis);
+    }
+     //     delete vot;
+  }
+
+  return newTrack;
+}
+
+
+bool BeamspotVertexPreProcessor::doBeamspotConstraintTrackSelection(const Track* track) {
+ 
+  const VxContainer * vertices = 0;
+  const VxCandidate * vertex = 0;
+  bool haveVertex = false;
+ 
+  // retrieve the primary vertex if needed
+  if(m_doAssociatedToPVSelection) {
+
+    if(evtStore()->retrieve( vertices, m_PVContainerName ).isFailure()) {
+      msg(MSG::ERROR)<<"Cannot retrieve the \'"<<m_PVContainerName<<"\' vertex collection from StoreGate"<<endreq;
+      m_doAssociatedToPVSelection = false;
+    } else {
+      // if there is no vertex, we can't associate the tracks to it
+      if(vertices) {
+        ATH_MSG_DEBUG("Primary vertex collection for this event has "<<vertices->size()<<" vertices");
+        if (vertices->size()<2){
+          ATH_MSG_DEBUG("Only Dummy vertex present, no Primary vertices.");
+        } else {
+          vertex = (*vertices)[0];
+          haveVertex = true;
+        }
+      }
+      else
+        ATH_MSG_DEBUG("Could not retrieve primary vertex collection from the StoreGate");
+    }
+  }
+
+
+  if( ( m_doAssociatedToPVSelection && haveVertex && vertex && isAssociatedToPV(track,vertices) ) ||
+      ( m_doBSTrackSelection        && m_BSTrackSelector->decision(*track) ) ){
+        ATH_MSG_DEBUG("this track passes the beamspot track selection, will do beamspot constraint on it ");
+        return true; 
+  } 
+  else return false;
+}
+
+
+
+AlignTrack* BeamspotVertexPreProcessor::doTrackRefit(const Track* track) {
+
+  AlignTrack * alignTrack = 0;
+  const Track* newTrack = 0;
+  const VertexOnTrack* vot = 0;
+  const VxCandidate*    vtx = 0;
+  AlignTrack::AlignTrackType type = AlignTrack::Unknown;
+  // configuration of the material effects needed for track fitter
+  ParticleSwitcher particleSwitch;
+  ParticleHypothesis particleHypothesis = particleSwitch.particle[m_particleNumber];
+
+
+  // initialization the GX2 track fitter
+  ToolHandle<Trk::IGlobalTrackFitter> fitter = m_trackFitter;
+  if (!m_useSingleFitter && AlignTrack::isSLTrack(track) )
+      fitter = m_SLTrackFitter;
+       
+  // 
+  if(m_doPrimaryVertexConstraint){
+    vot = provideVotFromVertex(track, vtx);
+    if( !vot )  ATH_MSG_DEBUG( "VoT not found for this track! ");
+    if( !vtx )  ATH_MSG_DEBUG( "VTX pointer not found for this track! ");
+    if(vot){
+      newTrack = doConstraintRefit(fitter, track, vot, particleHypothesis);       
+      type = AlignTrack::VertexConstrained;
+      // this track failed the PV constraint reift
+      if (!newTrack)  {
+        ++m_nFailedPVRefits;
+        msg(MSG::ERROR)<<"VertexConstraint track refit failed! "<<endreq;
+      }
+    }
+  }
+
+  if( !newTrack && m_doBeamspotConstraint && doBeamspotConstraintTrackSelection(track) ){
+      vot = provideVotFromBeamspot(track);
+      if(vot){
+        newTrack = doConstraintRefit(fitter, track, vot, particleHypothesis);
+        type = AlignTrack::BeamspotConstrained;
+        // this track failed the BS constraint reift
+        if (!newTrack)  {
+          ++m_nFailedBSRefits;
+          msg(MSG::ERROR)<<"BSConstraint track refit failed! "<<endreq;
+        }
+      }
+  }
+
+  if(!newTrack){
+      newTrack = fitter->fit(*track,m_runOutlierRemoval,particleHypothesis);
+      type = AlignTrack::NormalRefitted;
+      // this track failed the normal reift
+      if (!newTrack)   {
+        ++m_nFailedNormalRefits;
+        msg(MSG::ERROR)<<"Normal track refit failed! "<<endreq;
+      }
+  }
+
+ 
+  if(newTrack) {
+    alignTrack = new AlignTrack(*newTrack);
+    // set original track pointer
+    alignTrack->setOriginalTrack(track);
+    // set the refit type
+    alignTrack->setType(type);
+
+ 
+    if (msgLvl(MSG::DEBUG) || msgLvl(MSG::VERBOSE)) {
+      msg(MSG::DEBUG)<<"before refit: "<<endreq;
+      msg(MSG::DEBUG)<< *track <<endreq;
+      if (msgLvl(MSG::VERBOSE))   AlignTrack::dumpLessTrackInfo(*track,msg(MSG::DEBUG));
+      
+      msg(MSG::DEBUG)<<"after refit: "<<endreq;
+      msg(MSG::DEBUG)<< *newTrack <<endreq;
+      if (msgLvl(MSG::VERBOSE))   AlignTrack::dumpLessTrackInfo(*newTrack,msg(MSG::DEBUG));
+    }
+  
+    if(AlignTrack::VertexConstrained == type || AlignTrack::BeamspotConstrained == type) alignTrack->doFindPerigee();
+    
+    if (m_storeFitMatrices) {
+      alignTrack->setFullCovarianceMatrix(fitter->FullCovarianceMatrix());
+      alignTrack->setDerivativeMatrix(fitter->DerivMatrix());
+    }
+    delete newTrack;
+
+    if( m_doFullVertexConstraint && vtx!=0 && type == AlignTrack::VertexConstrained ){
+    // try to log the track-vertex association in the AlignVertex object:
+      bool ifound=false;
+      std::vector<AlignVertex*>::const_iterator ivtx=AlignVertices.begin();
+      std::vector<AlignVertex*>::const_iterator evtx=AlignVertices.end();
+      for ( ; ivtx != evtx ; ++ivtx)  if( ((*ivtx)->originalVertex())==vtx ) {
+        ifound = true;
+        (*ivtx)->addAlignTrack(alignTrack);
+      }
+      if( !ifound ) {
+        AlignVertex*  avtx=new AlignVertex(vtx);
+        ATH_MSG_DEBUG(" New AlignVertex has ben created.");
+      
+        // Beam Spot constraint on the vertex:
+        if( m_doBeamspotConstraint && (Trk::PriVtx == vtx->vertexType() || Trk::PileUp == vtx->vertexType()) && vtx->vxTrackAtVertex()->size()>4 ) {     // a beam line verex 
+          ATH_MSG_DEBUG(" The Beam Spot constraint will be added to the vertex.." );  
+          AmgSymMatrix(3)     qtemp;
+          AmgVector(3)        vtemp;
+          provideVtxBeamspot(avtx, &qtemp, &vtemp);
+          (qtemp)(2,2) = 1000000.0;                  // disable Z constraint
+          avtx->setConstraint( &qtemp, &vtemp);
+        }
+      
+        avtx->addAlignTrack(alignTrack);
+        AlignVertices.push_back(avtx);
+      }
+      
+    }
+
+
+
+
+     // increment counters
+     ++m_trackTypeCounter[type];
+     ++m_nTracks;
+
+  }
+
+  // garbage collection:
+  if(vot)  delete vot;
+
+  return alignTrack; 
+} 
+
+
+
+
+//____________________________________________________________________________
+DataVector<Track> * BeamspotVertexPreProcessor::processTrackCollection(const DataVector<Track> * tracks) 
+{
+  ATH_MSG_DEBUG("BeamspotVertexPreProcessor::processTrackCollection()");
+
+  if( !tracks || (tracks->size()==0) )
+    return 0;
+
+  // Clear the AlignVertex container (will destruct the objects it owns as well!)
+  AlignVertices.clear();
+
+
+  if(m_doPrimaryVertexConstraint) 
+    prepareAllTracksVector();
+
+  // the output collection of AlignTracks
+  // we define it as collection of Tracks but fill AlignTracks inside
+  DataVector<Track> * newTrks = new DataVector<Track>;
+
+  int index(0);
+  // loop over tracks
+  TrackCollection::const_iterator itr     = tracks->begin();
+  TrackCollection::const_iterator itr_end = tracks->end();
+  for ( ; itr != itr_end; ++itr, ++index) {
+    ATH_MSG_DEBUG("Processing track "<<index);
+    const Track* track = *itr;
+    AlignTrack * alignTrack = 0;
+    
+    
+    // check whether the track passes the basic selection
+    if (track && !m_trkSelector.empty()) {
+      if(!m_trkSelector->decision(*track))
+        continue;
+    }
+  
+  
+    if(m_refitTracks && track){
+      alignTrack = doTrackRefit(track); 
+ 
+      // 2nd track check after refit
+      if(alignTrack && !m_trkSelector.empty()) {
+        // do not check for FullVertex tracks:
+        if( !(alignTrack->getVtx()) ) {
+          if(!m_trkSelector->decision(*alignTrack))
+             continue;
+        }
+      }  
+    } else{
+      alignTrack = new AlignTrack(*track);
+      alignTrack->setOriginalTrack(track);
+      alignTrack->setType(AlignTrack::Original);
+    }
+    // add the new align track to the collection
+    if (alignTrack)  newTrks->push_back(alignTrack);
+  } // end of loop over tracks
+
+  // delete the collection if it's empty
+  if (newTrks->size()==0) {
+    delete newTrks;
+    return 0;
+  }
+
+  return newTrks;
+}
+
+//____________________________________________________________________________
+void BeamspotVertexPreProcessor::accumulateVTX(const AlignTrack* alignTrack) {
+
+  if( !m_doFullVertexConstraint ) return;
+
+  AlignVertex*  alignVertex = alignTrack->getVtx();
+
+  ATH_MSG_DEBUG( " In accumulateVTX ");
+  if( !alignVertex ) {
+    ATH_MSG_DEBUG( "This alignTrack is not associated to any vertex -> return. ");
+    return;
+  }
+
+  // get pointers so we can reuse them if they're valid
+  Amg::MatrixX                 * ptrWeights   = alignTrack->weightMatrix();
+  Amg::MatrixX                 * ptrWeightsFD = alignTrack->weightMatrixFirstDeriv();
+  Amg::VectorX                 * ptrResiduals = alignTrack->residualVector();
+  std::vector<AlignModuleDerivatives> * ptrDerivs    = alignTrack->derivatives();
+
+  // check if pointers are valid
+  if (!ptrWeights || !ptrWeightsFD || !ptrResiduals || !ptrDerivs) {
+    msg(MSG::ERROR)<<"something missing from alignTrack!"<<endreq;
+    if (!ptrWeights)   msg(MSG::ERROR)<<"no weights!"<<endreq;
+    if (!ptrWeightsFD) msg(MSG::ERROR)<<"no weights for first deriv!"<<endreq;
+    if (!ptrResiduals) msg(MSG::ERROR)<<"no residuals!"<<endreq;
+    if (!ptrDerivs)    msg(MSG::ERROR)<<"no derivatives!"<<endreq;
+    return;
+  }
+
+  // get vectors
+  Amg::VectorX&                    residuals     = *ptrResiduals;
+  std::vector<AlignModuleDerivatives>  derivatives   = *ptrDerivs;
+
+  // get weight matrices
+  Amg::MatrixX&                weights           = *ptrWeights;
+  Amg::MatrixX&                weightsFirstDeriv = *ptrWeightsFD;
+  ATH_MSG_VERBOSE("weights="<<weights);
+  ATH_MSG_VERBOSE("weightsFirstDeriv="<<weightsFirstDeriv);
+
+  // get all alignPars and all derivatives
+  ATH_MSG_DEBUG("accumulateVTX: The derivative vector size is  " << derivatives.size() );
+  std::vector<AlignModuleDerivatives>::iterator derivIt     = derivatives.begin();
+  std::vector<AlignModuleDerivatives>::iterator derivIt_end = derivatives.end();
+
+  std::vector<Amg::VectorX*> allDerivatives[3];
+  //    CLHEP::HepVector*  VTXDerivatives[3];
+  Amg::VectorX  VTXDerivatives[3];
+  const int    WSize(weights.cols());
+  Amg::MatrixX*  WF = new Amg::MatrixX(3,WSize);
+  std::vector<AlignModuleVertexDerivatives>* derivX = new std::vector<AlignModuleVertexDerivatives>(0);
+
+  for ( ; derivIt!=derivIt_end ; ++derivIt) {
+
+    // get AlignModule
+    const AlignModule* module=derivIt->first;
+
+
+    // get alignment parameters
+    if( module ) {
+      Amg::MatrixX*   F = new Amg::MatrixX(3,WSize);
+      std::vector<Amg::VectorX>& deriv_vec = derivIt->second;
+      ATH_MSG_VERBOSE( "accumulateVTX: The deriv_vec size is  " << deriv_vec.size() );
+      DataVector<AlignPar>* alignPars = m_alignModuleTool->getAlignPars(module);
+      int nModPars = alignPars->size();
+      if ((nModPars+3) != (int)deriv_vec.size() ) {
+        ATH_MSG_ERROR("accumulateVTX: Derivatives w.r.t. the vertex seem to be missing");
+        delete derivX;
+        delete WF;
+        delete F;
+        return;
+      }
+      for (int i=0;i<3;i++) {
+        allDerivatives[i].push_back(&deriv_vec[nModPars+i]);
+        for (int j=0;j<WSize;j++) {
+          (*F)(i,j) = deriv_vec[nModPars+i][j];
+        }
+      }
+
+      // prepare the X object in the AlignVertex:
+      (*WF) += (*F) * weights;
+      delete F;
+
+    } else {
+      ATH_MSG_ERROR("accumulateVTX: Derivatives do not have a valid pointer to the module.");
+      delete derivX; 
+      delete WF;
+      return;
+    }
+  }
+
+
+  // second loop to fill the X object:
+  derivIt     = derivatives.begin();
+  for ( ; derivIt!=derivIt_end ; ++derivIt) {
+
+    // get AlignModule
+    const AlignModule* module=derivIt->first;
+
+
+    // get alignment parameters
+    if( module ) {
+      std::vector<Amg::VectorX>& deriv_vec = derivIt->second;
+      std::vector<Amg::VectorX>* drdaWF = new std::vector<Amg::VectorX>(0);
+      ATH_MSG_DEBUG( "accumulateVTX: The deriv_vec size is  " << deriv_vec.size() );
+      DataVector<AlignPar>* alignPars = m_alignModuleTool->getAlignPars(module);
+      int nModPars = alignPars->size();
+      if ((nModPars+3) != (int)deriv_vec.size() ) {
+        ATH_MSG_ERROR("accumulateVTX: Derivatives w.r.t. the vertex seem to be missing");
+        delete derivX;
+        delete WF;
+        delete drdaWF;
+        return;
+      }
+      for (int i=0;i<nModPars;i++) {
+        drdaWF->push_back(2.0 * (*WF) * deriv_vec[i]);
+      }
+
+      // now add contribution from this track to the X object:
+      derivX->push_back(make_pair(module,*drdaWF));
+      ATH_MSG_DEBUG("accumulateVTX: derivX incremented by:  " << (*drdaWF) );
+      delete drdaWF;
+
+    } else {
+      ATH_MSG_ERROR("accumulateVTX: Derivatives do not have a valid pointer to the module.");
+      delete derivX;
+      delete WF;
+      return;
+    }
+  }
+
+
+
+  // prepare derivatives w.r.t. the vertex position:
+  int nmodules = allDerivatives[0].size();
+  msg(MSG::DEBUG) << "accumulateVTX: allDerivatives size is  " << nmodules << endreq;
+  for( int ii=0; ii<3; ++ii ) {
+    VTXDerivatives[ii] = (*(allDerivatives[ii])[0]);
+    for( int jj=1; jj<nmodules; ++jj ) {
+      VTXDerivatives[ii] += (*(allDerivatives[ii])[jj]);
+    }
+  }
+
+
+  AmgVector(3)     vtxV;
+  AmgSymMatrix(3)  vtxM;
+
+  Amg::VectorX RHM= weightsFirstDeriv * residuals;
+  ATH_MSG_DEBUG("RHM: "<<RHM);
+
+  for (int ipar=0;ipar<3;ipar++) {
+
+    // calculate first derivative
+    //  CLHEP::HepMatrix derivativesT = (*(VTXDerivatives[ipar])).T();
+    Amg::MatrixX derivativesT = (VTXDerivatives[ipar]).transpose();
+    ATH_MSG_DEBUG("derivativesT (size "<<derivativesT.cols()<<"): "<<derivativesT);
+
+    Amg::MatrixX  tempV = (2.* derivativesT * RHM);
+    vtxV[ipar] = tempV(0,0);
+
+    for (int jpar=ipar;jpar<3;jpar++) {
+
+      // calculate second derivatives
+      Amg::MatrixX RHM2 = weights * (VTXDerivatives[jpar]);
+
+      Amg::MatrixX  tempM = (2.* derivativesT * RHM2);
+      vtxM(ipar,jpar) = tempM(0,0);
+
+    }
+
+  }
+
+  // increment the vtx algebra objects:
+
+  alignVertex->incrementVector(vtxV);
+  alignVertex->incrementMatrix(vtxM);
+  //   ATH_MSG_DEBUG("accumulateVTX: derivX size = "<< derivX->size());
+  alignVertex->addDerivatives(derivX);
+
+  // garbage collection:
+
+  delete    WF;
+  delete    derivX;
+  //    delete [] VTXDerivatives;
+
+  return; 
+} 
+
+
+//____________________________________________________________________________
+void BeamspotVertexPreProcessor::solveVTX() {
+
+  if( m_doFullVertexConstraint ){
+    ATH_MSG_DEBUG("In solveVTX. Number of vertices = " << AlignVertices.size() );
+    std::vector<AlignVertex*>::const_iterator ivtx=AlignVertices.begin();
+    std::vector<AlignVertex*>::const_iterator evtx=AlignVertices.end();
+
+    for ( ; ivtx != evtx ; ++ivtx)  {
+      if( (*ivtx)->Ntracks()>1 ) {
+        (*ivtx)->fitVertex();
+       } else {
+         msg(MSG::WARNING) << "This vertex contains " << (*ivtx)->Ntracks() << " tracks. No solution possible." <<endreq;
+       }
+
+       ATH_MSG_DEBUG( "This vertex contains " << (*ivtx)->Ntracks() << " tracks.");
+       if( msgLvl(MSG::DEBUG) )  (*ivtx)->dump(msg(MSG::DEBUG));
+    }
+  }
+}
+
+//____________________________________________________________________________
+void BeamspotVertexPreProcessor::printSummary()
+{
+  if(m_logStream) {
+
+    *m_logStream<<"*************************************************************"<<std::endl;
+    *m_logStream<<"******        BeamspotVertexPreProcessor summary       ******"<<std::endl;
+    *m_logStream<<"*"<<std::endl;
+    *m_logStream<<"* number of created AlignTracks :  "<<m_nTracks<<std::endl;
+    if(m_nTracks>0) {
+      *m_logStream<<"* --------------------------------------------"<<std::endl;
+      for(int i=0; i<AlignTrack::NTrackTypes; ++i) {
+        if(m_trackTypeCounter[i]>0)
+          *m_logStream<<"*           "<<(AlignTrack::AlignTrackType)i<<":  "<<m_trackTypeCounter[i]<<std::endl;
+        }
+    }
+    *m_logStream<<"*"<<std::endl;
+    *m_logStream<<"* number of failed normal refits :              " << m_nFailedNormalRefits << std::endl;
+    *m_logStream<<"* number of failed refits with primary vertex : " << m_nFailedPVRefits     << std::endl;
+    *m_logStream<<"* number of failed refits with beam-spot :      " << m_nFailedBSRefits     << std::endl;
+    *m_logStream<<"*"<<std::endl;
+  }
+}
+
+//____________________________________________________________________________
+StatusCode BeamspotVertexPreProcessor::finalize() 
+{
+  ATH_MSG_INFO("BeamspotVertexPreProcessor::finalize()");
+
+  return StatusCode::SUCCESS;
+}
+
+//____________________________________________________________________________
+}
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/ConstrainedTrackProvider.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/ConstrainedTrackProvider.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..9a760275e967506f8a6aa762a5b764680d3b3daf
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/ConstrainedTrackProvider.cxx
@@ -0,0 +1,496 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "TrkFitterInterfaces/IGlobalTrackFitter.h"
+#include "TrkFitterInterfaces/ITrackFitter.h"
+#include "TrkAlignGenTools/ConstrainedTrackProvider.h"
+#include "TrkPseudoMeasurementOnTrack/PseudoMeasurementOnTrack.h"  
+#include "TrkSurfaces/PerigeeSurface.h"
+#include "TrkParameters/TrackParameters.h"
+#include "TrkMeasurementBase/MeasurementBase.h"
+
+
+#include "TFile.h"
+#include "TH2F.h"
+
+
+namespace Trk {
+  
+  //________________________________________________________________________
+  ConstrainedTrackProvider::ConstrainedTrackProvider(const std::string& type, 
+               const std::string& name,
+               const IInterface* parent)
+    
+    : AthAlgTool(type,name,parent)
+    , m_trackFitter("Trk::GlobalChi2Fitter/InDetTrackFitter")
+    , m_inputTrackCollection("Tracks")
+    , m_constraintInputFile_P(0)
+    , m_etaphiMap_P(0)
+    , m_constraintInputFile_d0(0)
+    , m_etaphiMap_d0(0)
+    , m_constraintInputFile_z0(0)
+    , m_etaphiMap_z0(0)
+   {
+    declareInterface<ITrackCollectionProvider>(this);
+    declareProperty("TrackFitter",              m_trackFitter                      );
+    declareProperty("InputTracksCollection",    m_inputTrackCollection             );
+    declareProperty("RunOutlierRemoval",        m_runOutlierRemoval      = true    ); 
+    declareProperty("MaxRetrievalErrors",       m_maxRetrievalErrors     = 10      );
+    declareProperty("UseConstrainedTrkOnly",    m_useConstrainedTrkOnly  = false   );
+    declareProperty("MinPt",                    m_minPt         = 15.0             );        
+    declareProperty("MaxPt",                    m_maxPt         = 100.0            );        
+    declareProperty("MinPIXHits",               m_minPIXHits    = 1                );
+    declareProperty("MinSCTHits",               m_minSCTHits    = 6                );
+    declareProperty("MinTRTHits",               m_minTRTHits    = 0                );
+    declareProperty("Maxd0",                    m_maxd0         = 500.             );
+    declareProperty("Maxz0",                    m_maxz0         = 500.             );
+    declareProperty("CorrectMomentum",          m_CorrectMomentum         = true              );
+    declareProperty("MomentumConstraintFileName", m_constraintFileName_P  = "Constraint.root" ); 
+    declareProperty("MomentumConstraintHistName", m_constraintHistName_P  = "EtaPhiMap"       ); 
+    declareProperty("CorrectD0",                  m_CorrectD0             = false             );
+    declareProperty("d0ConstraintFileName",       m_constraintFileName_d0 = "Constraint.root" ); 
+    declareProperty("d0ConstraintHistName",       m_constraintHistName_d0 = "EtaPhiMap"       ); 
+    declareProperty("CorrectZ0",                  m_CorrectZ0             = false             );
+    declareProperty("z0ConstraintFileName",       m_constraintFileName_z0 = "Constraint.root" ); 
+    declareProperty("z0ConstraintHistName",       m_constraintHistName_z0 = "EtaPhiMap"       ); 
+    declareProperty("UseConstraintError",         m_useConstraintError = true   ,"Bla bla "   ); 
+    declareProperty("ReduceConstraintUncertainty",m_reduceConstraintUncertainty = 1., "Reduce the uncertainty on teh track parmater constraint by this amount"  ); 
+    declareProperty("DeltaScaling",               m_deltaScaling = 1.);
+   
+  }
+
+  //________________________________________________________________________
+  ConstrainedTrackProvider::~ConstrainedTrackProvider()
+  {
+
+  }
+
+  //________________________________________________________________________
+  StatusCode ConstrainedTrackProvider::initialize()
+  {
+    // configure main track fitter
+    if(m_trackFitter.retrieve().isFailure()) {
+       msg(MSG::FATAL) << "Could not get " << m_trackFitter << endreq;
+       return StatusCode::FAILURE;
+    }
+    ATH_MSG_INFO("Retrieved " << m_trackFitter);
+
+
+    std::cout << "init m_useConstraintError " <<m_useConstraintError <<std::endl;
+
+    std::cout << "Init m_reduceConstraintUncertainty " << m_reduceConstraintUncertainty <<  std::endl;
+
+
+    if(m_CorrectMomentum){
+ 
+      m_constraintInputFile_P = new TFile(m_constraintFileName_P.c_str() ,"read");
+      if ( m_constraintInputFile_P->IsZombie() || !(m_constraintInputFile_P->IsOpen()) ) {
+        ATH_MSG_FATAL( " Problem reading TFile " << m_constraintFileName_P );
+        return StatusCode::FAILURE;
+      }
+      ATH_MSG_INFO("Opened  file containing the contraints" << m_constraintFileName_P);
+      m_etaphiMap_P = (TH2F*)m_constraintInputFile_P->Get(m_constraintHistName_P.c_str());
+      if(!m_etaphiMap_P){
+        ATH_MSG_FATAL( " Problem getting constraints Hist.  Name " << m_constraintHistName_P );
+        m_constraintInputFile_P->Close();
+        delete m_constraintInputFile_P;
+        return StatusCode::FAILURE;
+      }
+      ATH_MSG_INFO("Opened contraints histogram " << m_constraintHistName_P);
+    
+    }
+    
+    if(m_CorrectD0){
+ 
+      m_constraintInputFile_d0 = new TFile(m_constraintFileName_d0.c_str() ,"read");
+      if ( m_constraintInputFile_d0->IsZombie() || !(m_constraintInputFile_d0->IsOpen()) ) {
+        ATH_MSG_FATAL( " Problem reading TFile " << m_constraintFileName_d0 );
+        return StatusCode::FAILURE;
+      }
+      ATH_MSG_INFO("Opened  file containing the contraints" << m_constraintFileName_d0);
+      m_etaphiMap_d0 = (TH2F*)m_constraintInputFile_d0->Get(m_constraintHistName_d0.c_str());
+      if(!m_etaphiMap_d0){
+        ATH_MSG_FATAL( " Problem getting constraints Hist.  Name " << m_constraintHistName_d0 );
+        m_constraintInputFile_d0->Close();
+        delete m_constraintInputFile_d0;
+        return StatusCode::FAILURE;
+      }
+      ATH_MSG_INFO("Opened contraints histogram " << m_constraintHistName_d0);
+    
+    }
+    
+    if(m_CorrectZ0){
+ 
+      m_constraintInputFile_z0 = new TFile(m_constraintFileName_z0.c_str() ,"read");
+      if ( m_constraintInputFile_z0->IsZombie() || !(m_constraintInputFile_z0->IsOpen()) ) {
+        ATH_MSG_FATAL( " Problem reading TFile " << m_constraintFileName_z0 );
+        return StatusCode::FAILURE;
+      }
+      ATH_MSG_INFO("Opened  file containing the contraints" << m_constraintFileName_z0);
+      m_etaphiMap_z0 = (TH2F*)m_constraintInputFile_z0->Get(m_constraintHistName_z0.c_str());
+      if(!m_etaphiMap_z0){
+        ATH_MSG_FATAL( " Problem getting constraints Hist.  Name " << m_constraintHistName_z0 );
+        m_constraintInputFile_z0->Close();
+        delete m_constraintInputFile_z0;
+        return StatusCode::FAILURE;
+      }
+      ATH_MSG_INFO("Opened contraints histogram " << m_constraintHistName_z0);
+    
+    }
+    
+    
+    if(m_reduceConstraintUncertainty<=0){
+      ATH_MSG_FATAL( " reduceConstraintUncertainty  is  <= 0 it must be >0 . Currently  " << m_reduceConstraintUncertainty );
+      return StatusCode::FAILURE;
+    }
+    
+    return StatusCode::SUCCESS;
+  }
+
+
+
+
+
+  //________________________________________________________________________
+  StatusCode ConstrainedTrackProvider::finalize()
+  {
+    if(m_constraintInputFile_P){
+      m_constraintInputFile_P->Close();
+      delete m_constraintInputFile_P;
+    }
+    
+    if(m_constraintInputFile_d0){
+      m_constraintInputFile_d0->Close();
+      delete m_constraintInputFile_d0;
+    }
+    
+    if(m_constraintInputFile_z0){
+      m_constraintInputFile_z0->Close();
+      delete m_constraintInputFile_z0;
+    }
+        
+    return StatusCode::SUCCESS;
+  }
+
+ 
+  StatusCode ConstrainedTrackProvider::trackCollection(const TrackCollection*& finalTracks)
+  {
+   
+
+    const TrackCollection* originalTracks = 0;
+    
+    if ( StatusCode::SUCCESS != evtStore()->retrieve(originalTracks, m_inputTrackCollection) ){
+      ATH_MSG_WARNING(" Can't retrieve " << m_inputTrackCollection << " from the StoreGate ");
+      return StatusCode::FAILURE;
+    } 
+    
+    TrackCollection* trackCollection = new TrackCollection;
+    
+    ATH_MSG_DEBUG("Have tracks in the event:  " << originalTracks->size());
+
+    TrackCollection::const_iterator trackIt   = originalTracks->begin();
+    TrackCollection::const_iterator trackItE  = originalTracks->end();
+    
+    for ( ; trackIt != trackItE; ++trackIt ) {
+      
+      if( passTrackSelection( *trackIt ) ){
+        const Trk::Perigee* measuredPerigee =  (*trackIt)->perigeeParameters();
+        if(!measuredPerigee){
+          ATH_MSG_DEBUG(" no measuredPerigee");
+          continue;
+        } 
+        
+        if(!(measuredPerigee->covariance()) ){
+          ATH_MSG_DEBUG(" no measuredPerigee");
+          continue;
+        }      
+  
+        const Trk::Surface* surf = dynamic_cast<const Trk::Surface*>( &(measuredPerigee->associatedSurface()) ) ;
+        if( !surf ) {
+          ATH_MSG_DEBUG("NO surface of the measuredPerigee");
+          continue;
+        }
+
+        // Get corrections from histograms if they are requested
+  
+        double correctedQoverP(0), correctedQoverPError(0);
+        if(m_CorrectMomentum){
+          getCorrectedValues_P( measuredPerigee, correctedQoverP, correctedQoverPError);
+        } else {
+          correctedQoverP = measuredPerigee->parameters()[Trk::qOverP];
+          correctedQoverPError = 1e6;
+        }
+
+        double correctedD0(0), correctedD0Error(0);
+        if(m_CorrectD0){
+          getCorrectedValues_d0( measuredPerigee, correctedD0, correctedD0Error);
+        } else {
+          correctedD0 = measuredPerigee->parameters()[Trk::d0];
+          correctedD0Error = 1e6;
+        }
+        
+        double correctedZ0(0), correctedZ0Error(0);
+        if(m_CorrectZ0){
+          getCorrectedValues_d0( measuredPerigee, correctedZ0, correctedZ0Error);
+        } else {
+          correctedZ0 = measuredPerigee->parameters()[Trk::z0];
+          correctedZ0Error = 1e6;
+        }
+        
+        // Construct pseudomeasurement 
+        Trk::DefinedParameter constrainedD0( correctedD0     , Trk::d0) ;
+        Trk::DefinedParameter constrainedZ0( correctedZ0     , Trk::z0) ;
+        Trk::DefinedParameter constrainedqOverP( correctedQoverP , Trk::qOverP) ;
+  
+        std::vector<Trk::DefinedParameter> constrainedPars;
+        constrainedPars.push_back( constrainedD0 ) ;
+        constrainedPars.push_back( constrainedZ0 ) ;
+        constrainedPars.push_back( constrainedqOverP ) ;
+        
+        Amg::MatrixX constrainedCov( 3,3 ) ;
+	constrainedCov.setZero();
+        constrainedCov( 0, 0 )   =  correctedD0Error;
+        constrainedCov( 1, 1 )   =  correctedZ0Error;
+        constrainedCov( 2, 2 )   =  correctedQoverPError;
+        // constrainedCov( 1, 0 )   =  0;  //initially we will assume the constraints are independant
+        // constrainedCov( 2, 0 )   =  0;
+        // constrainedCov( 2, 1 )   =  0;
+  
+        Trk::PseudoMeasurementOnTrack *pmot = new Trk::PseudoMeasurementOnTrack( Trk::LocalParameters( constrainedPars ), constrainedCov, *surf) ;
+  
+  
+        // Add pseusdo measurement to a list of hits to be fit;
+        std::vector<const Trk::MeasurementBase*> vecOfMB;
+        if (pmot) vecOfMB.push_back(pmot);
+        
+        // Add the remaining hits;
+        DataVector<const Trk::MeasurementBase>::const_iterator it    = (*trackIt)->measurementsOnTrack()->begin();
+        DataVector<const Trk::MeasurementBase>::const_iterator itend = (*trackIt)->measurementsOnTrack()->end();
+        for (;it!=itend;++it) 
+          vecOfMB.push_back(*it);
+        
+        if(m_runOutlierRemoval){
+          it    = (*trackIt)->outliersOnTrack()->begin();
+          itend = (*trackIt)->outliersOnTrack()->end();
+          // Add the remaining hits;
+          for (;it!=itend;++it) 
+            vecOfMB.push_back(*it);
+        }
+      
+        Trk::Track* constrainedFittedTrack = m_trackFitter->fit( vecOfMB, *measuredPerigee, m_runOutlierRemoval, Trk::pion);
+        delete pmot;
+        
+        if (constrainedFittedTrack){
+          ATH_MSG_DEBUG("Fit was successful");
+          const Trk::Perigee* constrainedPerigee =  constrainedFittedTrack->perigeeParameters();
+          if(!constrainedPerigee){
+            ATH_MSG_DEBUG(" no constrainedmeasuredPerigee");          
+          } else {
+            ATH_MSG_DEBUG("Constrained fit was momentum : " << 1/constrainedPerigee->parameters()[Trk::qOverP] * 1e-3 );          
+            ATH_MSG_DEBUG("Initial fit was momentum     : " << 1/measuredPerigee->parameters()[Trk::qOverP] * 1e-3 );          
+            ATH_MSG_DEBUG("corrected  was momentum      : " << 1/correctedQoverP * 1e-3 );          
+          }
+  
+          trackCollection->push_back(constrainedFittedTrack);
+          ++m_constrainedTracks;
+        } else{
+          ATH_MSG_DEBUG("Constrained fit was unsuccessful");          
+        }
+      } else {
+      
+        if(m_useConstrainedTrkOnly) continue;
+        
+        //Prob could just copy the track?
+        Trk::Track* unconstrainedFittedTrack = m_trackFitter->fit( **trackIt,m_runOutlierRemoval, Trk::pion);
+        
+        if(unconstrainedFittedTrack) {
+          ATH_MSG_DEBUG("Unconstrained fit was successful");
+          trackCollection->push_back(unconstrainedFittedTrack);
+          ++m_unconstrainedTracks;
+        } else {
+          ATH_MSG_DEBUG("Unconstrained fit was unsuccessful");                  
+        }
+      }
+    }      
+
+
+
+    if (StatusCode::SUCCESS != evtStore()->record(trackCollection, "AlignmentConstrainedTracks")){
+      ATH_MSG_WARNING("Problem with recording AlignmentConstrainedTracks to StoreGate!");
+      delete trackCollection;
+      return StatusCode::SUCCESS;
+    }    
+
+    ATH_MSG_DEBUG(" The final trackCollection size : " << trackCollection->size() );
+    if ( trackCollection ){
+      finalTracks = trackCollection;
+    }
+
+    return StatusCode::SUCCESS;
+
+  }
+
+
+
+  
+  bool  ConstrainedTrackProvider::passTrackSelection(const Trk::Track *track)
+  {
+    
+    const Trk::Perigee* perigee = track->perigeeParameters();
+    if(!perigee){
+      ATH_MSG_DEBUG("NO perigee on this track");
+      return false;
+    }
+       
+    const Trk::TrackSummary* summary = track->trackSummary();   
+    
+    if(!summary){
+      ATH_MSG_DEBUG("No summary on this track");
+      return false;
+    }
+    
+    const int nPixHits        = summary->get(Trk::numberOfPixelHits);
+    const int nSCTHits        = summary->get(Trk::numberOfSCTHits);
+    const int nTRTHits        = summary->get(Trk::numberOfTRTHits);       
+    
+    const double qoverP = perigee->parameters()[Trk::qOverP] * 1000.; 
+    const double z0     = perigee->parameters()[Trk::z0];
+    const double d0     = perigee->parameters()[Trk::d0];
+    double pt          = 0.;
+    if ( qoverP != 0 ) pt = fabs(1.0/qoverP)*sin(perigee->parameters()[Trk::theta]);
+    
+    ATH_MSG_DEBUG( " pt  : "<< pt );
+    
+    if(pt < m_minPt ||  pt > m_maxPt   ){
+      ATH_MSG_VERBOSE("Track fails pt cut [ "<<m_minPt<<", "<< m_maxPt << "] " << pt );      
+      return false;
+    }
+    
+    if( nPixHits < m_minPIXHits ||
+        nSCTHits < m_minSCTHits ||
+        nTRTHits < m_minTRTHits ||
+        d0 > m_maxd0    ||
+        z0 > m_maxz0    ) {          
+      ATH_MSG_VERBOSE("This track did not pass cuts --- nPixHits: " << nPixHits << " nSCTHits: " << nSCTHits << 
+                   "nTRTHits: " << nTRTHits << " idd0atIP: " << d0 << " idz0atIP: " << z0  );
+     return false;
+    }
+
+    return true;
+  }
+  
+  void  ConstrainedTrackProvider::getCorrectedValues_P(const Trk::Perigee* measuredPerigee, double& correctedQoverP,double& correctedQoverPError)
+  {
+  
+    // scale q/p not p
+  
+    double charge(0);
+    if( measuredPerigee->parameters()[Trk::qOverP] > 0)
+      charge = 1.;
+    else 
+      charge = -1.;
+    
+    double pt   = fabs(1./(measuredPerigee->parameters()[Trk::qOverP]))* sin(measuredPerigee->parameters()[Trk::theta]) *1e-3;
+    double eta = -log(tan(measuredPerigee->parameters()[Trk::theta]/2.));
+    double phi = measuredPerigee->parameters()[Trk::phi];
+    double perr =  (*measuredPerigee->covariance())( Trk::qOverP, Trk::qOverP );
+   
+   
+    int binNumber = m_etaphiMap_P->FindBin(eta, phi);
+    double constraintErr = m_etaphiMap_P->GetBinError(binNumber);
+
+    double delta = m_etaphiMap_P->GetBinContent(binNumber) * m_deltaScaling;
+       
+    correctedQoverP = measuredPerigee->parameters()[Trk::qOverP] * (1.+ charge *pt *delta );
+    correctedQoverPError = perr;
+   
+    if(m_useConstraintError){
+      double qoverpFracError =  perr/pow(measuredPerigee->parameters()[Trk::qOverP], 2);
+      qoverpFracError += pow(constraintErr,2);    
+      correctedQoverPError = qoverpFracError*correctedQoverP*correctedQoverP;
+    }
+    ATH_MSG_DEBUG("Scaling by 1/m_reduceConstraintUncertainty  " << m_reduceConstraintUncertainty << '\t'<< pow( m_reduceConstraintUncertainty,-2)) ;    
+    correctedQoverPError = correctedQoverPError * pow( m_reduceConstraintUncertainty,-2); 
+    return;
+  }
+
+
+  void  ConstrainedTrackProvider::getCorrectedValues_d0(const Trk::Perigee* measuredPerigee, double& correctedD0,double& correctedD0Error)
+  {
+  
+    // scale d0
+  
+    
+    double d0  = measuredPerigee->parameters()[Trk::d0];
+    double eta = -log(tan(measuredPerigee->parameters()[Trk::theta]/2.));
+    double phi = measuredPerigee->parameters()[Trk::phi]; 
+    double d0err =  (*measuredPerigee->covariance())( Trk::d0, Trk::d0 );
+   
+   
+    int binNumber = m_etaphiMap_d0->FindBin(eta, phi);
+    double constraintErr = m_etaphiMap_d0->GetBinError(binNumber);
+    double delta = m_etaphiMap_d0->GetBinContent(binNumber) * m_deltaScaling;
+       
+    correctedD0 = d0 + delta;
+    correctedD0Error = d0err;
+    
+    if(m_useConstraintError){
+      correctedD0Error = d0err + pow( constraintErr, 2 );
+    }
+    ATH_MSG_DEBUG("Scaling by 1/m_reduceConstraintUncertainty  " << m_reduceConstraintUncertainty << '\t'<< pow( m_reduceConstraintUncertainty,-2)) ;    
+    correctedD0Error = correctedD0Error * pow( m_reduceConstraintUncertainty,-2); 
+    return;
+  }
+
+  void  ConstrainedTrackProvider::getCorrectedValues_z0(const Trk::Perigee* measuredPerigee, double& correctedZ0,double& correctedZ0Error)
+  {
+  
+    // scale z0
+    
+    double z0  = measuredPerigee->parameters()[Trk::z0];
+    double eta = -log(tan(measuredPerigee->parameters()[Trk::theta]/2.));
+    double phi = measuredPerigee->parameters()[Trk::phi];
+    double z0err =  (*measuredPerigee->covariance())( Trk::z0, Trk::z0 );
+   
+    int binNumber = m_etaphiMap_z0->FindBin(eta, phi);
+    double constraintErr = m_etaphiMap_z0->GetBinError(binNumber);
+    double delta = m_etaphiMap_z0->GetBinContent(binNumber) * m_deltaScaling;
+       
+    correctedZ0 = z0 + delta;
+    correctedZ0Error = z0err;
+
+    if(m_useConstraintError){
+      correctedZ0Error = z0err + pow( constraintErr, 2 );
+    }
+    ATH_MSG_DEBUG("Scaling by 1/m_reduceConstraintUncertainty  " << m_reduceConstraintUncertainty << '\t'<< pow( m_reduceConstraintUncertainty,-2)) ;    
+    correctedZ0Error = correctedZ0Error * pow( m_reduceConstraintUncertainty,-2); 
+    return;
+  }
+
+
+
+
+ 
+  void ConstrainedTrackProvider::printSummary(){
+
+    if(m_logStream) {
+  
+      *m_logStream<<"*************************************************************"<<std::endl;
+      *m_logStream<<"******        ConstrainedTrackProvider Summary       ******"<<std::endl;
+      *m_logStream<<"*"<<std::endl;
+      *m_logStream<<"* number of combined muons failed in refit:                           " << m_passconstrainedRequirements   << std::endl;
+      *m_logStream<<"* number of combined muons failed in refit:                           " << m_constrainedTracks   << std::endl;
+      *m_logStream<<"* number of combined muons succeeded in refit:                        " << m_unconstrainedTracks      << std::endl;
+
+      *m_logStream<<"*"<<std::endl;
+    }
+  }
+
+
+
+
+
+
+} // end namespace
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/IPCMatrixTool.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/IPCMatrixTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..90ed8c382f2a9664ae36ca7c62da41014687bcc7
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/IPCMatrixTool.cxx
@@ -0,0 +1,129 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// IPCMatrixTool.cxx
+
+// AlgTool for creating big matrix and vector, manipulation of entries, and 
+// solving for alignment parameters 
+// Robert Harrington, started 1/5/08 based on SiGlobalChi2Align
+
+#include "GaudiKernel/StatusCode.h"
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/AlgTool.h"
+
+#include "TrkAlignGenTools/IPCMatrixTool.h"
+
+#include "TrkAlgebraUtils/IPCMat.h"
+
+#include <string>
+
+namespace Trk {
+
+  //_______________________________________________________________________
+  IPCMatrixTool::IPCMatrixTool(const std::string& type, const std::string& name,
+			       const IInterface* parent)
+    : AthAlgTool(type,name,parent)
+    , m_ipcmat(0)
+  {
+    declareInterface<IMatrixTool>(this);
+    
+    declareProperty("IPCRemoval",    m_IPCremoval    = false); 
+    declareProperty("IPCMatrixName", m_ipcmatMatName = "/tmp/ipcmat.dat"); 
+    declareProperty("IPCVectorName", m_ipcmatVecName = "/tmp/ipcvec.dat"); 
+
+    m_logStream = 0;
+  }
+
+  //_______________________________________________________________________
+  IPCMatrixTool::~IPCMatrixTool()
+  {
+    if (0!=m_ipcmat) delete m_ipcmat;
+    m_ipcmat = NULL;
+
+  }
+  
+  //_______________________________________________________________________
+  StatusCode IPCMatrixTool::initialize()
+  {
+    msg(MSG::DEBUG) << "initialize() of IPCMatrixTool" << endreq;  
+    
+    return StatusCode::SUCCESS;
+  }
+  
+  //_______________________________________________________________________
+  StatusCode IPCMatrixTool::finalize()
+  {
+    msg(MSG::DEBUG) << "finalize() of IPCMatrixTool" << endreq;  
+    
+    return StatusCode::SUCCESS;    
+  }
+  
+  //_______________________________________________________________________
+  StatusCode IPCMatrixTool::allocateMatrix(int nDoF) 
+  {
+    
+    if (0!=m_ipcmat) ATH_MSG_ERROR("IPCMat already exists!");
+    m_ipcmat = new IPCMat(msgSvc());
+    
+    if (m_ipcmat->init()!=StatusCode::SUCCESS) {
+      ATH_MSG_ERROR("Failed to initialize ipcmat ");
+      return StatusCode::FAILURE;
+    } else
+      ATH_MSG_INFO("Success allocating ipcmatrix");
+
+    if (m_ipcmat->allocate(nDoF)!=StatusCode::SUCCESS) {
+      ATH_MSG_ERROR("Failed to allocate matrix of size " << nDoF);
+      return StatusCode::FAILURE;
+    } else
+      ATH_MSG_INFO("Success allocating ipcvector");
+    
+    return StatusCode::SUCCESS;
+  }
+  
+  //_______________________________________________________________________
+  void IPCMatrixTool::prepareBinaryFiles(int) 
+  {
+    
+    return;
+  }
+  
+  //_______________________________________________________________________
+  bool IPCMatrixTool::accumulateFromFiles() 
+  {  
+     
+    return false;
+  }
+  
+  //_______________________________________________________________________
+  int IPCMatrixTool::solve() 
+  {  
+     
+     return -1;
+  }
+  
+  //_______________________________________________________________________
+  void IPCMatrixTool::addFirstDerivatives(AlVec* )
+  {
+    return;
+  }
+
+  //________________________________________________________________________
+  void IPCMatrixTool::addSecondDerivatives(AlSymMatBase* )
+  {
+    return;
+  }
+
+  //________________________________________________________________________
+  void IPCMatrixTool::addFirstDerivatives(std::list<int,double>& )
+  {
+    return;
+  }
+
+  //________________________________________________________________________
+  void IPCMatrixTool::addSecondDerivatives(std::list<std::pair<int,int>,double> & )
+  {
+    return;
+  }
+
+} // end of namespace
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/MSConstraintTracksProvider.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/MSConstraintTracksProvider.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6273b36778dadbbd542e5430a33cd081890a6f3e
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/MSConstraintTracksProvider.cxx
@@ -0,0 +1,568 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "TrkFitterInterfaces/IGlobalTrackFitter.h"
+#include "TrkFitterInterfaces/ITrackFitter.h"
+#include "TrkAlignGenTools/MSConstraintTracksProvider.h"
+#include "TrkPseudoMeasurementOnTrack/PseudoMeasurementOnTrack.h"  
+#include "TrkSurfaces/PerigeeSurface.h"
+#include "TrkParameters/TrackParameters.h"
+#include "TrkMeasurementBase/MeasurementBase.h"
+
+#include "muonEvent/Muon.h"
+#include "muonEvent/MuonContainer.h"
+#include "muonEvent/MuonParamDefs.h"
+#include "MuonSegment/MuonSegment.h"
+#include "Particle/TrackParticle.h"
+
+#include "MuonRecToolInterfaces/IMuonHitSummaryTool.h"
+
+#include "TTree.h"
+#include "TFile.h"
+
+
+namespace Trk {
+  
+  //________________________________________________________________________
+  MSConstraintTracksProvider::MSConstraintTracksProvider(const std::string& type, 
+               const std::string& name,
+               const IInterface* parent)
+    
+    : AthAlgTool(type,name,parent)
+    , m_trackFitter("Trk::GlobalChi2Fitter/InDetTrackFitter")
+    , m_muonHitSummaryTool("Muon::MuonHitSummaryTool/MuonHitSummaryTool")
+    , m_inputMuonCollection("MuidMuonCollection")
+    , m_inputTracksCollection("Tracks")
+    , m_nCBMuonsFromSG(0)
+    , m_nCBMuonsHasEXandID(0)
+    , m_nCBMuonsPassSelection(0)
+    , m_nCBMuonsFailedRefit(0)
+    , m_nCBMuonsSucRefit(0)
+    , m_ntuple(0)
+    , m_tree(0)
+
+  {
+
+    declareInterface<ITrackCollectionProvider>(this);
+
+    declareProperty("TrackFitter",              m_trackFitter                       );
+    declareProperty("InputMuonCollection",      m_inputMuonCollection               );   
+    declareProperty("InputTracksCollection",    m_inputTracksCollection             );
+    declareProperty("RunOutlierRemoval",        m_runOutlierRemoval      = true     ); 
+    declareProperty("MaxRetrievalErrors",       m_maxRetrievalErrors     = 10       );
+    declareProperty("UseMSConstraintTrkOnly",   m_useMSConstraintTrkOnly = true     );
+    declareProperty("DoTree",                   m_doTree                 = true     );
+    declareProperty("MinPt",                    m_minPt                  = 15.0     );        
+    declareProperty("MinPIXHits",               m_minPIXHits             = 1        );
+    declareProperty("MinSCTHits",               m_minSCTHits             = 6        );
+    declareProperty("MinTRTHits",               m_minTRTHits             = 0        );
+    declareProperty("MaxIDd0",                  m_maxIDd0                = 500.     );
+    declareProperty("MaxIDz0",                  m_maxIDz0                = 500.     ); 
+    declareProperty("MinIDPt",                  m_minIDPt                = 10       );
+    declareProperty("MDTHits",                  m_minMDTHits             = 15       );
+    declareProperty("MinRPCPhiHits",            m_minRPCPhiHits          = 0        );
+    declareProperty("MinTGCPhiHits",            m_minTGCPhiHits          = 0        );
+    declareProperty("MaxMSd0",                  m_maxMSd0                = 500.     );
+    declareProperty("MaxMSz0",                  m_maxMSz0                = 500.     );     
+    declareProperty("MinMSPt",                  m_minMSPt                = 0        );
+    declareProperty("MaxNumberOfSectors",       m_maxNumberOfSectors     = 1        );
+    declareProperty("MinNumberOfPhiLayers",     m_minNumberOfPhiLayers   = 2        );
+    declareProperty("MinStationLayers",         m_minStationLayers       = 3        );
+ 
+  }
+
+  //________________________________________________________________________
+  MSConstraintTracksProvider::~MSConstraintTracksProvider()
+  {
+
+  }
+
+  //________________________________________________________________________
+  StatusCode MSConstraintTracksProvider::initialize()
+  {
+    // configure main track fitter
+    if(m_trackFitter.retrieve().isFailure()) {
+       msg(MSG::FATAL) << "Could not get " << m_trackFitter << endreq;
+       return StatusCode::FAILURE;
+    }
+    ATH_MSG_INFO("Retrieved " << m_trackFitter);
+
+    if (m_muonHitSummaryTool.retrieve().isFailure()){
+        ATH_MSG_ERROR("could no initialize " << m_muonHitSummaryTool);
+        return StatusCode::FAILURE;
+    }
+
+    // 
+    bookNtuple();
+
+
+    return StatusCode::SUCCESS;
+  }
+
+
+
+
+  void MSConstraintTracksProvider::setNtuple(TFile* ntuple) { 
+    m_ntuple = ntuple; 
+    bookNtuple();
+  }
+  
+
+
+
+  bool MSConstraintTracksProvider::bookNtuple(){
+
+    ATH_MSG_DEBUG("in  MSConstraintTracksProvider::bookNtuple");     
+  
+    if (m_doTree && !m_tree && m_ntuple) {
+        m_ntuple->cd();
+        m_tree = new TTree("MSMomentumConstraint","MSMomentumConstraint");
+
+        ATH_MSG_DEBUG(" Start book Ntuple");
+
+        m_tree->Branch("run",               &m_run,                 "run/I"     );
+        m_tree->Branch("event",             &m_event,               "event/I"   );
+        m_tree->Branch("pID",               &m_pID,                 "pID/D"     );
+        m_tree->Branch("pMS",               &m_pMS,                 "pMS/D"     );
+        m_tree->Branch("ptID",              &m_ptID,                "ptID/D"    );
+        m_tree->Branch("ptMS",              &m_ptMS,                "ptMS/D"    );
+        m_tree->Branch("charge",            &m_charge,              "charge/D"    );
+
+        m_tree->Branch("combinedEta",       &m_combinedEta,         "combinedEta/D"   );
+        m_tree->Branch("IDEta",             &m_IDEta,         "IDEta/D"   );
+        m_tree->Branch("combinedPhi",       &m_combinedPhi,         "combinedPhi/D"   );
+        m_tree->Branch("IDPhi",             &m_IDPhi,               "IDPhi/D"   );
+
+        m_tree->Branch("pID_constrained",   &m_pID_constrained,     "pID_constrained/D" );
+        m_tree->Branch("ptID_constrained",    &m_ptID_constrained,    "ptID_constrained/D"  );
+        m_tree->Branch("IDEta_constrained",   &m_IDEta_constrained,   "IDEta_constrained/D"   );
+        m_tree->Branch("IDPhi_constrained",   &m_IDPhi_constrained,   "IDPhi_constrained/D"   );
+        m_tree->Branch("charge_constrained",    &m_charge_constrained,  "charge_constrained/D"  );
+
+   
+        m_tree->Branch("eBLhits",           &m_eBLhits,             "eBLhits/I"   );
+        m_tree->Branch("nBLhits",           &m_nBLhits,             "nBLhits/I"   );
+
+        m_tree->Branch("nPIXDS",            &m_nPIXDS,              "nPIXDS/I"    );
+        m_tree->Branch("nSCTDS",            &m_nSCTDS,              "nSCTDS/I"    );
+
+        m_tree->Branch("nPIXH",             &m_nPIXH,               "nPIXH/I"   );
+        m_tree->Branch("nSCTH",             &m_nSCTH,               "nSCTH/I"   );
+
+        m_tree->Branch("nPIXHits",            &m_nPIXHits,            "nPIXHits/I"    );
+        m_tree->Branch("nSCTHits",            &m_nSCTHits,            "nSCTHits/I"    );
+        m_tree->Branch("nTRTHits",            &m_nTRTHits,            "nTRTHits/I"    );
+
+        m_tree->Branch("sectors",             &m_sectors,             "sectors/I"   );
+        m_tree->Branch("phiLayers",           &m_phiLayers,           "phiLayers/I"   );
+        m_tree->Branch("stationLayers",       &m_stationLayers,       "stationLayers/I" );
+
+        m_tree->Branch("sectorNum",           &m_sectorNum,           "sectorNum/I"   );
+        m_tree->Branch("phiLayerNum",           &m_phiLayerNum,         "phiLayerNum/I"   );
+        m_tree->Branch("stationLayerNum",       &m_stationLayerNum,     "stationLayerNum/I" );
+
+    }
+
+    ATH_MSG_DEBUG("done with bookNtuple");
+     
+    return StatusCode::SUCCESS;
+  
+}   
+
+
+
+  void MSConstraintTracksProvider::initializeNtuple(){
+  
+    m_run      = -999;
+    m_event      = -999; 
+    m_pID      = -999.;
+    m_pMS      = -999.;
+    m_ptID     = -999.;
+    m_ptMS     = -999.;
+    m_charge     = -999.;
+
+    m_combinedEta    = -999.;
+    m_IDEta      = -999.;
+    m_combinedPhi    = -999.;
+    m_IDPhi      = -999.;             
+
+    m_pID_constrained    = -999.;
+    m_ptID_constrained   = -999.;
+    m_IDEta_constrained  = -999.;
+    m_IDPhi_constrained  = -999.;
+    m_charge_constrained = -999.;
+
+
+    m_eBLhits    = -999;
+    m_nBLhits    = -999;
+    m_nPIXDS     = -999,
+    m_nSCTDS     = -999,
+
+    m_nPIXH    = -999;
+    m_nSCTH    = -999;
+
+
+    m_nPIXHits     = -999;
+    m_nSCTHits     = -999;
+    m_nTRTHits     = -999;
+
+    m_sectors    =  -999;
+    m_phiLayers    = -999;
+    m_stationLayers  = -999;
+
+    m_sectorNum    = -999;
+    m_phiLayerNum  = -999;
+    m_stationLayerNum  = -999;
+
+  }
+
+
+
+  StatusCode MSConstraintTracksProvider::fillNtuple()
+  {
+    ATH_MSG_DEBUG("writing tree");
+    int success=1;
+    if (m_tree) {
+        m_ntuple->cd();
+       success = m_tree->Write();
+    }
+    return success>0 ? StatusCode::SUCCESS : StatusCode::FAILURE;
+  }
+
+
+
+  //________________________________________________________________________
+  StatusCode MSConstraintTracksProvider::finalize()
+  {
+    return StatusCode::SUCCESS;
+  }
+
+ 
+  bool MSConstraintTracksProvider::combinedMuonSelection(const Analysis::Muon* it) {
+
+       const Trk::Perigee* IDTrkMeasuredPerigee = dynamic_cast<const Trk::Perigee*>(& (it->inDetTrackParticle()->definingParameters()));
+       if(!IDTrkMeasuredPerigee){
+           ATH_MSG_DEBUG("NO inDetTrackParticle or no IDTrkMeasuredPerigee");
+           return false;
+       }
+
+       const Trk::Perigee* METrkMeasuredPerigee = dynamic_cast<const Trk::Perigee*>(&(it->muonExtrapolatedTrackParticle()->definingParameters()));
+       if(!METrkMeasuredPerigee){
+           ATH_MSG_DEBUG("NO muonExtrapolatedTrackParticle or no METrkMeasuredPerigee");
+           return false;
+       }
+
+       const double pt  = fabs(it->pt())/1000.;
+       const double eta = fabs(it->eta()); 
+       ATH_MSG_DEBUG(" the combined pt : "<< pt );  
+
+       if (  pt   < m_minPt     ||
+             eta  > 2.7         || 
+            (eta > 0.8 && eta < 1.2) ){ 
+             ATH_MSG_DEBUG(" this combinedMuon not pass basic pt and eta cuts --- pt: "<< pt << " eta: " << eta);
+           return false;
+       }
+
+       const int nPixHits        = it->numberOfPixelHits();
+       const int nSCTHits        = it->numberOfSCTHits();
+       const int nTRTHits        = it->numberOfTRTHits();  
+
+       //  Do you need fit quality cuts???
+       // const Trk::FitQuality* idfq = idtrk->fitQuality(); 
+       // const double chisqID        = idfq->chiSquared();
+       // const int    ndofID         = idfq->numberDoF();
+    
+
+       const double idQoverPatIP = IDTrkMeasuredPerigee->parameters()[Trk::qOverP] * 1000.; 
+       const double idz0atIP     = IDTrkMeasuredPerigee->parameters()[Trk::z0];
+       const double idd0atIP     = IDTrkMeasuredPerigee->parameters()[Trk::d0];
+       double ptIDatIP           = 0.;
+       if ( idQoverPatIP != 0 ) ptIDatIP = fabs(1.0/idQoverPatIP)*sin(IDTrkMeasuredPerigee->parameters()[Trk::theta]);
+  
+       ATH_MSG_DEBUG( " ID pt  : "<< ptIDatIP );
+
+
+       if( nPixHits < m_minPIXHits ||
+           nSCTHits < m_minSCTHits ||
+           nTRTHits < m_minTRTHits ||
+           idd0atIP > m_maxIDd0    ||
+           idz0atIP > m_maxIDz0    ||
+           ptIDatIP < m_minIDPt     ) {          
+         ATH_MSG_DEBUG("this combined muon not pass ID cuts --- nPixHits: " << nPixHits << " nSCTHits: " << nSCTHits << 
+                         "nTRTHits: " << nTRTHits << " idd0atIP: " << idd0atIP << " idz0atIP: " << idz0atIP <<" ptIDatIP: " << ptIDatIP );
+         return false;
+       }
+
+
+
+       const int nMDTHits        = it->numberOfMDTHits();
+       const int nRPCPhiHits     = it->numberOfRPCPhiHits();
+       const int nTGCPhiHits     = it->numberOfTGCPhiHits();    
+
+       const double msQoverPatIP = METrkMeasuredPerigee->parameters()[Trk::qOverP] * 1000.; 
+       const double msz0atIP     = METrkMeasuredPerigee->parameters()[Trk::z0];
+       const double msd0atIP     = METrkMeasuredPerigee->parameters()[Trk::d0];
+  
+       double ptMSatIP = 0.;
+       if ( msQoverPatIP != 0 ) ptMSatIP = fabs(1.0/msQoverPatIP)*sin(METrkMeasuredPerigee->parameters()[Trk::theta]);
+
+       ATH_MSG_DEBUG( " ME pt  : "<< ptMSatIP);
+
+
+
+       if( nMDTHits    < m_minMDTHits    ||
+           nRPCPhiHits < m_minRPCPhiHits ||
+           nTGCPhiHits < m_minTGCPhiHits ||
+           msd0atIP    > m_maxMSd0       ||
+           msz0atIP    > m_maxMSz0       ||
+           ptMSatIP    < m_minMSPt        ){
+
+           ATH_MSG_DEBUG("this combined muon not pass MS cuts --- nMDTHits: " << nMDTHits << " nRPCPhiHits: " << nRPCPhiHits << 
+                         " nTGCPhiHits: " << nTGCPhiHits << " msd0atIP: " << msd0atIP << 
+                         " msz0atIP: "    << msz0atIP    << " pMSatIP:"   << ptMSatIP);
+           return false;
+       }
+
+
+       Muon::IMuonHitSummaryTool::CompactSummary summary;
+       const Rec::TrackParticle* aTrackParticle = it->track();
+    
+       const Trk::Track* aTrack = 0;
+       if (aTrackParticle) aTrack = aTrackParticle->originalTrack();
+
+       if (aTrack && aTrack != it->inDetTrkTrack()) {
+           summary = m_muonHitSummaryTool->summary(*aTrack);  
+       } 
+       else {
+         ATH_MSG_WARNING("aTrack possible null !");
+         std::vector<const Muon::MuonSegment*> segments;
+         unsigned int nSeg = it->numberOfSegments();
+         segments.reserve(nSeg); // avoid death by push back
+         for( unsigned int si=0; si<nSeg; ++si ){
+              const Muon::MuonSegment* seg = dynamic_cast<const Muon::MuonSegment*>(it->muonSegment(si));
+              if( seg ) segments.push_back(seg);  
+         }
+         summary = m_muonHitSummaryTool->summary(segments);  
+       }
+
+       // it is possible to avoid the verbose summary construction in the above, 
+       const int sectors       = summary.sectors.size();
+       const int phiLayers     = summary.phiLayers.size();
+       const int stationLayers = summary.stationLayers.size(); 
+
+
+       if ( sectors       > m_maxNumberOfSectors   ||
+            phiLayers     < m_minNumberOfPhiLayers ||
+            stationLayers < m_minStationLayers      ){
+
+            ATH_MSG_DEBUG("this combined muon not pass muonHitSummary cuts ---  sectors: "<< sectors << " phiLayers:  "<< phiLayers << " stationLayers: " << stationLayers);   
+
+            return false;
+       }
+
+       m_pID       = it->inDetTrackParticle()->p();
+       m_pMS       = it->muonExtrapolatedTrackParticle()->p();
+       m_ptID      = it->inDetTrackParticle()->pt();
+       m_ptMS      = it->muonExtrapolatedTrackParticle()->pt();
+       m_charge    = it->inDetTrackParticle()->charge();
+
+       m_combinedEta   = it->eta();
+       m_IDEta     = it->inDetTrackParticle()->eta();
+       m_combinedPhi   = it->phi();
+       m_IDPhi     = it->inDetTrackParticle()->phi();
+
+       m_nPIXHits        = it->numberOfPixelHits();
+       m_nSCTHits        = it->numberOfSCTHits();
+       m_nTRTHits        = it->numberOfTRTHits();
+
+       m_sectors         = sectors;
+       m_phiLayers       = phiLayers;
+       m_stationLayers   = stationLayers;
+
+       m_sectorNum       = *(summary.sectors.begin());
+       //m_phiLayerNum     = (summary.phiLayers)[0];
+       //m_stationLayerNum = (summary.stationLayers)[0];
+
+
+
+    return true;
+  }
+ 
+
+  
+StatusCode MSConstraintTracksProvider::trackCollection(const TrackCollection*& originalTracks){
+  initializeNtuple();
+
+  originalTracks = 0;
+
+  const Analysis::MuonContainer* muonContainer = 0;
+  if ( StatusCode::SUCCESS != evtStore()->retrieve( muonContainer , m_inputMuonCollection) ){
+    ATH_MSG_WARNING(" Can't retrieve " << m_inputMuonCollection << " from the StoreGate ");
+    ATH_MSG_WARNING("One probability is that you are not running on ESD/DESD ");
+
+    // Can't do MS constraint refit, resort to retrieve tracks directly 
+    if ( StatusCode::SUCCESS != evtStore()->retrieve(originalTracks, m_inputTracksCollection) ){
+      originalTracks = 0;
+      ATH_MSG_WARNING(" Can't retrieve " << m_inputTracksCollection << " from the StoreGate ");
+    } else {
+      ATH_MSG_DEBUG(" have tracks of this event: " << originalTracks->size());
+    }
+
+    return StatusCode::SUCCESS;
+  } else {
+
+    TrackCollection* trackCollection = new TrackCollection;
+    ATH_MSG_DEBUG("have combined Muons of the event:  " << muonContainer->size());
+
+    Analysis::MuonContainer::const_iterator combinedTrackIt   = muonContainer->begin();
+    Analysis::MuonContainer::const_iterator combinedTrackItE  = muonContainer->end();
+    int goodQualityCombinedMuon = 0;
+
+    for ( ; combinedTrackIt != combinedTrackItE; ++combinedTrackIt ) {
+      ++m_nCBMuonsFromSG;
+      const Analysis::Muon* muon = *combinedTrackIt;  
+      if ( muon->isCombinedMuon() && muon->hasMuonExtrapolatedTrackParticle() && muon->hasInDetTrackParticle() ){
+        ++m_nCBMuonsHasEXandID;
+        if(combinedMuonSelection(muon)) {
+          ATH_MSG_DEBUG("have good quality combined Muons of the event:  " << ++goodQualityCombinedMuon); 
+          ++m_nCBMuonsPassSelection;
+          const Trk::Perigee* METrkMeasuredPerigee = dynamic_cast<const Trk::Perigee*>(&(muon->muonExtrapolatedTrackParticle()->definingParameters()));
+          if(!METrkMeasuredPerigee){
+            ATH_MSG_DEBUG("NO muonExtrapolatedTrackParticle or no METrkMeasuredPerigee");
+            continue;
+          }
+ 
+          const Trk::Surface* surf =  &(METrkMeasuredPerigee->associatedSurface()) ;
+          if( !surf ) {
+            ATH_MSG_DEBUG("NO surface of the METrkMeasuredPerigee");
+            continue;
+          }
+
+          const Trk::Perigee* IDTrkMeasuredPerigee = dynamic_cast<const Trk::Perigee*>(&(muon->inDetTrackParticle()->definingParameters()));
+          if(!IDTrkMeasuredPerigee){
+            ATH_MSG_DEBUG("NO inDetTrackParticle or no IDTrkMeasuredPerigee");
+            continue;
+          } 
+
+          Trk::DefinedParameter qOverPFromMS(METrkMeasuredPerigee->parameters()[Trk::qOverP], Trk::qOverP) ;
+
+          std::vector<Trk::DefinedParameter> parFromMSVec;
+          parFromMSVec.push_back( qOverPFromMS) ;
+
+          Amg::MatrixX covFromMS( 1,1 ) ;
+          covFromMS( 1, 1 )   = (*METrkMeasuredPerigee->covariance())( Trk::qOverP, Trk::qOverP ) ;
+
+          Trk::PseudoMeasurementOnTrack *pmot = new Trk::PseudoMeasurementOnTrack( Trk::LocalParameters( parFromMSVec ), 
+										   covFromMS, *surf) ;
+
+
+          DataVector<const Trk::TrackStateOnSurface>* trackStateOnSurfaces = new DataVector<const Trk::TrackStateOnSurface>;
+          trackStateOnSurfaces->reserve(muon->inDetTrackParticle()->originalTrack()->trackStateOnSurfaces()->size() + 1);
+          DataVector<const Trk::TrackStateOnSurface>::const_iterator sb = muon->inDetTrackParticle()->originalTrack()->trackStateOnSurfaces()->begin();
+
+          std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> type;
+          type.set(Trk::TrackStateOnSurface::Measurement);
+
+          const Perigee* IDPerigeeParameters  = muon->inDetTrackParticle()->originalTrack()->perigeeParameters(); 
+          const Perigee* IDPerigeeParametersClone(0);
+          if (IDPerigeeParameters) IDPerigeeParametersClone  = IDPerigeeParameters->clone(); 
+
+
+          // std::cout << "muon->inDetTrackParticle()->originalTrack()->perigeeParameters(): " << IDPerigeeParameters << std::endl;
+          // std::cout << "muon->inDetTrackParticle()->originalTrack()->perigeeParameters()->clone(): "<< IDPerigeeParametersClone << std::endl;
+
+          if(IDPerigeeParameters && IDPerigeeParametersClone ){
+            trackStateOnSurfaces->push_back(new const Trk::TrackStateOnSurface(pmot, IDPerigeeParametersClone, 0, 0, type));
+
+            for ( ; sb != muon->inDetTrackParticle()->originalTrack()->trackStateOnSurfaces()->end(); ++sb)  trackStateOnSurfaces->push_back((**sb).clone());
+
+            Trk::Track* tmpTrack = new Trk::Track(muon->inDetTrackParticle()->originalTrack()->info(), trackStateOnSurfaces, 0);
+
+            Trk::Track* MSConstraintFittedTrack = m_trackFitter->fit(*tmpTrack, m_runOutlierRemoval, Trk::muon);
+
+            if(!MSConstraintFittedTrack){
+              ++m_nCBMuonsFailedRefit;    
+              ATH_MSG_WARNING("MSConstraintFittedTrack refit failed!");
+
+              if(!m_useMSConstraintTrkOnly){  
+                ATH_MSG_WARNING("Try to push the originalIDTrack into the trackCollection");
+                Trk::Track* IDOriginalTrackClone = new Trk::Track(*(muon->inDetTrackParticle()->originalTrack()));
+                if(IDOriginalTrackClone){
+                  const Trk::Perigee * aMeasPerClone = IDOriginalTrackClone->perigeeParameters();
+                  if( aMeasPerClone ){
+                    ATH_MSG_DEBUG("IDOriginalTrackClone parameters --- pt: " << fabs(1./(aMeasPerClone->parameters()[Trk::qOverP]))*sin(aMeasPerClone->parameters()[Trk::theta]) << " d0: "<< aMeasPerClone->parameters()[Trk::d0] );   
+                  }
+                }     
+                if(!IDOriginalTrackClone){
+                  ATH_MSG_WARNING("Exception when IDOriginalTrackClone!");
+                } else 
+                  trackCollection->push_back(IDOriginalTrackClone);  
+              }
+            } else {
+              ++m_nCBMuonsSucRefit;
+              ATH_MSG_DEBUG("Got 1 successful MSConstraintFittedTrack ");
+
+              Trk::Track* MSConstraintFittedTrackClone = new Trk::Track(*MSConstraintFittedTrack);
+              const Trk::Perigee * MSConstraintFittedTrackMPClone = (MSConstraintFittedTrackClone->perigeeParameters());
+              m_pID_constrained    = fabs(1./(MSConstraintFittedTrackMPClone->parameters()[Trk::qOverP]));
+              m_IDEta_constrained  = -log(tan(MSConstraintFittedTrackMPClone->parameters()[Trk::theta]/2.));
+              m_IDPhi_constrained  = MSConstraintFittedTrackMPClone->parameters()[Trk::phi];
+              m_ptID_constrained   = fabs( m_pID_constrained*sin(MSConstraintFittedTrackMPClone->parameters()[Trk::theta]) );
+              m_charge_constrained = MSConstraintFittedTrackMPClone->parameters()[Trk::qOverP]/fabs(MSConstraintFittedTrackMPClone->parameters()[Trk::qOverP]);
+
+              delete MSConstraintFittedTrackClone;          
+              // only fill the tracks used in the alignment 
+              m_ntuple->cd();
+              m_tree->Fill();
+
+              trackCollection->push_back(MSConstraintFittedTrack);
+            } 
+
+          // clean up
+          delete tmpTrack;
+          } else{
+            ATH_MSG_WARNING("failed in IDPerigeeParameters or IDPerigeeParametersClone  !");
+            delete pmot;
+            delete trackStateOnSurfaces;
+          }
+
+        }
+      }
+    }// end loop over tracks 
+
+    if (StatusCode::SUCCESS != evtStore()->record(trackCollection, "MSMomentumConstraintTracks")){
+    ATH_MSG_WARNING("problem with recording MSMomentumConstraintTracks to StoreGate!");
+    return StatusCode::SUCCESS;
+    }    
+
+    ATH_MSG_DEBUG(" The final trackCollection size : " << trackCollection->size() );
+    if ( trackCollection && (trackCollection->size() != 0)){
+           originalTracks = trackCollection;
+    }
+
+  }
+  return StatusCode::SUCCESS;
+}
+
+ 
+  void MSConstraintTracksProvider::printSummary(){
+
+    if(m_logStream) {
+  
+      *m_logStream<<"*************************************************************"<<std::endl;
+      *m_logStream<<"******        MSConstraintTracksProvider Summary       ******"<<std::endl;
+      *m_logStream<<"*"<<std::endl;
+      *m_logStream<<"* number of combined muons From SG :                                  " << m_nCBMuonsFromSG        << std::endl;
+      *m_logStream<<"* number of combined muons have Extrapolated && InDet TrackParticle : " << m_nCBMuonsHasEXandID    << std::endl;
+      *m_logStream<<"* number of combined muons pass selection:                            " << m_nCBMuonsPassSelection << std::endl;
+      *m_logStream<<"* number of combined muons failed in refit:                           " << m_nCBMuonsFailedRefit   << std::endl;
+      *m_logStream<<"* number of combined muons succeeded in refit:                        " << m_nCBMuonsSucRefit      << std::endl;
+
+      *m_logStream<<"*"<<std::endl;
+    }
+  }
+
+
+} // end namespace
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/MatrixTool.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/MatrixTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..73d91445260ee9a430594a47abd64d64c3b5feb5
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/MatrixTool.cxx
@@ -0,0 +1,2317 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// MatrixTool.cxx
+
+// AlgTool for creating big matrix and vector, manipulation of entries, and
+// solving for alignment parameters
+// Robert Harrington, started 1/5/08 based on SiGlobalChi2Align
+
+#include "GaudiKernel/StatusCode.h"
+#include "GaudiKernel/MsgStream.h"
+
+#include "GaudiKernel/AlgTool.h"
+
+#include "TrkAlgebraUtils/AlVec.h"
+#include "TrkAlgebraUtils/AlSymMatBase.h"
+#include "TrkAlgebraUtils/AlMat.h"
+#include "TrkAlgebraUtils/AlSymMat.h"
+#include "TrkAlgebraUtils/AlSpaMat.h"
+
+#include "TrkAlignEvent/AlignModule.h"
+#include "TrkAlignEvent/AlignModuleList.h"
+#include "TrkAlignEvent/AlignPar.h"
+#include "TrkAlignGenTools/MatrixTool.h"
+#include "TrkAlignInterfaces/IAlignModuleTool.h"
+
+#include "CLHEP/Matrix/Matrix.h"
+#include "CLHEP/Matrix/SymMatrix.h"
+#include "CLHEP/Matrix/Vector.h"
+
+#include <TMatrixT.h>
+#include <TMatrixDSym.h>
+#include <TMatrixDSparse.h>
+#include <TVectorD.h>
+#include <TVectorT.h>
+#include <TString.h>
+#include <TFile.h>
+
+
+#include <TDecompBK.h>
+
+#include <cmath>
+#include <ctime>
+#include <algorithm>
+#include <iterator>
+
+
+#include <sys/resource.h>
+
+namespace Trk {
+
+  //_______________________________________________________________________
+  MatrixTool::MatrixTool(const std::string& type, const std::string& name,
+                         const IInterface* parent)
+    : IMatrixTool()
+    , AthAlgTool(type,name,parent)
+    , m_alignModuleTool("Trk::AlignModuleTool/AlignModuleTool")
+    , m_bigmatrix(0)
+    , m_bigvector(0)
+    , m_scale(-1.)
+    , m_aNDoF(0)
+  {
+    declareInterface<IMatrixTool>(this);
+
+    declareProperty("UseSparse",          m_useSparse       = false);
+    declareProperty("SolveOption",        m_solveOption     = NONE);
+
+    declareProperty("Diagonalize",          m_diagonalize     = true);
+    declareProperty("EigenvalueThreshold",  m_eigenvaluethreshold   = 0.);
+
+    declareProperty("ModCut",             m_modcut        = 0);
+    declareProperty("PullCut",            m_pullcut       = 1.0);
+    declareProperty("EigenvalueStep",     m_eigenvalueStep    = 1e3);
+    declareProperty("AlignCorrDBStep",    m_Align_db_step     = 10);
+    declareProperty("MinNumHitsPerModule",  m_minNumHits      = 0);
+    declareProperty("MinNumTrksPerModule",  m_minNumTrks      = 0);
+    declareProperty("RunLocalMethod",     m_runLocal      = true);
+
+    declareProperty("MatrixDet",          m_calDet          = false);
+    declareProperty("WriteSquareMatrix",  m_wSqMatrix       = false);
+    declareProperty("WriteMat",           m_writeMat        = true);
+    declareProperty("WriteMatTxt",        m_writeMatTxt       = true);
+    declareProperty("WriteEigenMat",      m_writeEigenMat     = true);
+    declareProperty("WriteEigenMatTxt",   m_writeEigenMatTxt    = true);
+    declareProperty("WriteModuleNames",   m_writeModuleNames    = false);
+    
+    declareProperty("WriteTFile",     m_writeTFile      = false);
+    // if True then files will be read from TFiles instead of Binary files
+    declareProperty("ReadTFile",    m_readTFiles      = false);
+      
+
+    std::vector<std::string> defaultMatInput,defaultVecInput,defaultTFile;
+    defaultMatInput.push_back("matrix.bin");
+    defaultVecInput.push_back("vector.bin");
+    defaultTFile.push_back("AlignmentTFile.root");
+
+    declareProperty("InputMatrixFiles",   m_inputMatrixFiles    = defaultMatInput);
+    declareProperty("InputVectorFiles",   m_inputVectorFiles    = defaultVecInput);
+    declareProperty("InputTFiles",        m_inputTFiles     = defaultTFile);
+
+    declareProperty("AlignModuleTool",    m_alignModuleTool);
+
+    declareProperty("PathBinName",        m_pathbin               = "./");
+    declareProperty("PathTxtName",        m_pathtxt               = "./");
+    declareProperty("PrefixName",         m_prefixName            = "");
+    
+    declareProperty("TFileName",          m_tfileName       = "AlignmentTFile.root");
+
+    declareProperty("SoftEigenmodeCut",   m_softEigenmodeCut    = 0.);
+    declareProperty("RemoveSpurious",     m_removeSpurious    = false);
+    declareProperty("CalculateFullCovariance",  m_calculateFullCovariance = true);
+
+    // ScaLapack
+    declareProperty("ScalapackMatrixName",  m_scalaMatName      = "eigenvectors.bin");
+    declareProperty("ScalapackVectorName",  m_scalaVecName      = "eigenvalues.bin");
+
+    declareProperty("ScaleMatrix",        m_scaleMatrix       = false);
+
+    // Hitmap
+    declareProperty("WriteHitmap",        m_writeHitmap       = false);
+    declareProperty("WriteHitmapTxt",     m_writeHitmapTxt    = false);
+    declareProperty("ReadHitmaps",        m_readHitmaps       = false);
+    std::vector<std::string> defaultHitmapInput;
+    defaultMatInput.push_back("hitmap.bin");
+    declareProperty("InputHitmapFiles",   m_inputHitmapFiles    = defaultHitmapInput);
+  
+    declareProperty("MaxReadErrors",    m_maxReadErrors     = 10);
+
+  }
+
+  //_______________________________________________________________________
+  MatrixTool::~MatrixTool()
+  {
+    delete m_bigmatrix;
+    delete m_bigvector;
+  }
+
+  //_______________________________________________________________________
+  StatusCode MatrixTool::initialize()
+  {
+    ATH_MSG_DEBUG("initialize() of MatrixTool");
+
+    // get AlignModuleTool
+    if (m_alignModuleTool.retrieve().isSuccess())
+      ATH_MSG_INFO("Retrieved " << m_alignModuleTool);
+    else{
+      msg(MSG::FATAL) << "Could not get " << m_alignModuleTool << endreq;
+      return StatusCode::FAILURE;
+    }
+
+    ATH_MSG_INFO("Retrieving data from the following files: ");
+    for (int i=0;i<(int)m_inputVectorFiles.size();i++) {
+      ATH_MSG_INFO(m_pathbin+m_inputVectorFiles[i]);
+    }    
+
+    return StatusCode::SUCCESS;
+  }
+
+  //_______________________________________________________________________
+  StatusCode MatrixTool::finalize()
+  {
+    ATH_MSG_DEBUG("finalize() of MatrixTool");
+
+    return StatusCode::SUCCESS;
+  }
+
+
+  //_______________________________________________________________________
+  StatusCode MatrixTool::allocateMatrix(int nDoF)
+  {
+    ATH_MSG_INFO("allocating matrix and vector with nDoF = "<<nDoF);
+
+    if (0!=m_bigmatrix || 0!=m_bigvector)
+      ATH_MSG_ERROR("big matrix already allocated!");
+
+    // Decide upon the big matrix representation:
+    if( m_useSparse )
+      m_bigmatrix = new AlSpaMat(nDoF);
+    else
+      m_bigmatrix = new AlSymMat(nDoF);
+
+    m_bigvector       = new AlVec(nDoF);
+
+    ATH_MSG_INFO(" After Matrix and Vector allocation");
+
+    // set paths for matrix and vector output
+    m_bigmatrix->SetPathBin(m_pathbin+m_prefixName);
+    m_bigmatrix->SetPathTxt(m_pathtxt+m_prefixName);
+    m_bigvector->SetPathBin(m_pathbin+m_prefixName);
+    m_bigvector->SetPathTxt(m_pathtxt+m_prefixName);
+
+    ATH_MSG_INFO("set path to "<<m_pathbin+m_prefixName);
+    return StatusCode::SUCCESS;
+  }
+
+  //_______________________________________________________________________
+  void MatrixTool::prepareBinaryFiles(int)
+  {
+    return;
+  }
+
+  //_______________________________________________________________________
+  int MatrixTool::solveROOT()
+  {
+    ATH_MSG_INFO("solving Global using ROOT");
+    if(m_logStream) {
+      *m_logStream<<"*************************************************************"<<std::endl;
+      *m_logStream<<"**************  solving using Global method  ****************"<<std::endl;
+      *m_logStream<<"**************          using ROOT           ****************"<<std::endl;
+      *m_logStream<<"*************************************************************"<<std::endl;
+    }
+
+    // start measuring time
+    clock_t starttime = clock();
+
+    DataVector<AlignPar>*  alignParList = m_alignModuleTool->alignParList1D();
+    //const AlignModuleList* alignModules = m_alignModuleTool->alignModules1D();
+
+    int nDoF=m_alignModuleTool->nAlignParameters();
+
+    // some debugging output
+    if (msgLvl(MSG::VERBOSE)) {
+      msg(MSG::VERBOSE)<<"dumping matrix and vector to screen"<<endreq;
+      for (int i=0;i<nDoF;i++)
+        for (int j=0;j<nDoF;j++)
+        //if (std::fabs((*m_bigmatrix)[i][j])>.0001)
+          msg(MSG::VERBOSE)<<i<<", "<<j<<" : "<<(*m_bigmatrix)[i][j] <<endreq;
+
+      for (int i=0;i<nDoF;i++)
+        msg(MSG::VERBOSE)<<i <<" : "<<(*m_bigvector)[i]<<endreq;
+    }
+
+    // get rescaled first and second derivatives
+    double * secderiv   = new double[m_aNDoF*m_aNDoF];
+    double * firstderiv = new double[m_aNDoF];
+    for (int iActive=0;iActive<m_aNDoF;iActive++) {
+      int i = m_activeIndices[iActive];
+      firstderiv[iActive] = (*m_bigvector)[i];
+      for (int jActive=0;jActive<m_aNDoF;jActive++) {
+        int j = m_activeIndices[jActive];
+        secderiv[iActive*m_aNDoF+jActive] = (*m_bigmatrix)[i][j];
+      }
+    }
+
+    // attention, the dimension of matrix a and b is m_aNDoF not nDoF,
+    // this means some alignment parameters have not been calculated
+    // if the corresponding modules did not satify the select cut
+
+    TMatrixDSym a(m_aNDoF,secderiv);
+    TVectorD    b(m_aNDoF,firstderiv);
+
+    if(msgLvl(MSG::DEBUG)) {
+      msg(MSG::DEBUG)<<"First derivatives:"<<endreq;
+      b.Print();
+      msg(MSG::DEBUG)<<"Second derivatives:"<<endreq;
+      a.Print();
+    }
+
+    TDecompBK c(a);
+    Bool_t status;
+    TMatrixDSym ainv(c.Invert(status));
+
+    TVectorD r(b.GetNrows());
+    if(status)
+      r = c.Solve(b,status);
+
+    // stop measuring time
+    clock_t stoptime = clock();
+    double totaltime = (stoptime-starttime)/double(CLOCKS_PER_SEC);
+    ATH_MSG_INFO("Time spent in solveROOT: "<<totaltime<<" s");
+
+    if(!status) {
+      msg(MSG::ERROR)<<"ROOT inversion failed"<<endreq;
+      if(m_logStream) {
+        *m_logStream<<"ROOT inversion failed"<<std::endl;
+        *m_logStream<<std::endl;
+      }
+    }
+    else {
+      ATH_MSG_INFO("ROOT inversion ok");
+
+      ATH_MSG_DEBUG("Alignment constants:");
+      for (int iAdof=0;iAdof<m_aNDoF;iAdof++) {
+
+        int idof = m_activeIndices[iAdof];
+        AlignPar * alignPar=(*alignParList)[idof];
+
+        double sigma = alignPar->sigma();
+        double param = -r[iAdof] * sigma;
+        double err = std::sqrt(2.*std::fabs(ainv(iAdof,iAdof))) * sigma;
+
+        ATH_MSG_DEBUG(iAdof <<" : "<< param << " +/- "<< err);
+        ATH_MSG_DEBUG("ainv("<<iAdof<<")="<<ainv(iAdof,iAdof)<<", sigma: "<<sigma);
+        ATH_MSG_DEBUG("init par: "<<alignPar->initPar());
+        alignPar->setPar(param,err);
+        ATH_MSG_DEBUG("set param to "<<param<<" for alignPar "<<alignPar);
+        ATH_MSG_DEBUG(*(*alignParList)[idof]);
+      }
+
+      if(m_logStream)
+      {
+        *m_logStream<<"ROOT inversion ok"<<std::endl;
+
+        printGlobalSolution(*m_logStream,&ainv);
+
+        // norm of first derivative
+        *m_logStream<<"norm of first derivative :            "<<sqrt(b.Norm2Sqr())<<std::endl;
+
+        // distance to solution
+        double dist = sqrt( ( b - (a * r) ).Norm2Sqr() );
+        *m_logStream<<"distance to solution :                "<<dist<<std::endl;
+
+        // calculate chi2 of the alignment change
+        double chi2 = a.Similarity(r) * .5;
+        *m_logStream<<"delta(chi2) of the alignment change : "<<chi2<<" / "<<m_aNDoF<<std::endl;
+
+        // time spent here
+        *m_logStream<<"time spent in solve :                 "<<totaltime<<" s"<<std::endl;
+      }
+    }
+
+    delete [] secderiv;
+    delete [] firstderiv;
+
+    return 1;
+  }
+
+  //_______________________________________________________________________
+  int MatrixTool::solveCLHEP()
+  {
+    ATH_MSG_INFO("solving Global using CLHEP");
+    if(m_logStream) {
+      *m_logStream<<"*************************************************************"<<std::endl;
+      *m_logStream<<"**************  solving using Global method  ****************"<<std::endl;
+      *m_logStream<<"**************          using CLHEP          ****************"<<std::endl;
+      *m_logStream<<"*************************************************************"<<std::endl;
+    }
+
+    // start measuring time
+    clock_t starttime = clock();
+
+    DataVector<AlignPar> * alignParList = m_alignModuleTool->alignParList1D();
+    //const AlignModuleList* alignModules = m_alignModuleTool->alignModules1D();
+    for (int i=0;i<(int)alignParList->size();i++)
+      ATH_MSG_DEBUG("ap["<<i<<"]="<<(*alignParList)[i]);
+
+    int nDoF = m_alignModuleTool->nAlignParameters();
+
+    // some debugging output
+    if (msgLvl(MSG::DEBUG)) {
+      msg(MSG::DEBUG)<<"dumping matrix and vector to screen"<<endreq;
+      for (int i=0;i<nDoF;i++)
+        for (int j=0;j<nDoF;j++)
+        //if (std::fabs((*m_bigmatrix)[i][j])>.0001)
+          msg(MSG::DEBUG)<<i<<", "<<j<<" : "<<(*m_bigmatrix)[i][j] <<endreq;
+
+      for (int i=0;i<nDoF;i++)
+        msg(MSG::DEBUG)<<i <<" : "<<(*m_bigvector)[i]<<endreq;
+    }
+
+    // get rescaled first and second derivatives
+    CLHEP::HepSymMatrix * d2Chi2 = new CLHEP::HepSymMatrix(m_aNDoF,0);
+    CLHEP::HepVector    * dChi2  = new CLHEP::HepVector(m_aNDoF,0);
+    for (int iActive=0;iActive<m_aNDoF;iActive++) {
+      int i = m_activeIndices[iActive];
+      (*dChi2)[iActive] = (*m_bigvector)[i];
+      for (int jActive=0;jActive<m_aNDoF;jActive++) {
+        int j = m_activeIndices[jActive];
+        (*d2Chi2)[iActive][jActive] = (*m_bigmatrix)[i][j];
+      }
+    }
+
+    ATH_MSG_DEBUG("First derivatives:" << (*dChi2));
+    ATH_MSG_DEBUG("Second derivatives:" << (*d2Chi2));
+
+    CLHEP::HepSymMatrix cov(m_aNDoF,0);
+    CLHEP::HepVector delta(m_aNDoF,0);
+    CLHEP::HepVector deltafull(m_aNDoF,0);
+
+    bool status=true;
+    int ierr(0);
+    if(!m_diagonalize) {
+      // ==========================================================
+      //  Run Matrix Inversion
+      ATH_MSG_INFO("Running matrix inversion");
+      if(m_logStream)
+        *m_logStream<<"Running matrix inversion"<<std::endl;
+
+      cov = *d2Chi2;
+      cov.invert(ierr);
+      if(ierr>0)
+        msg(MSG::ERROR)<<"CLHEP inversion status flag = "<<ierr<<endreq;
+      else
+        ATH_MSG_INFO("CLHEP inversion OK");
+      if(m_logStream)
+        *m_logStream<<"CLHEP inversion status flag = "<<ierr<<std::endl;
+
+      // calculate corrections
+      delta = cov * (*dChi2);
+
+      // the covariance matrix is actually defined as 2 * d2Chi2^-1
+      ATH_MSG_DEBUG("Result: "<<delta);
+      ATH_MSG_DEBUG("cov: "<<cov*2);
+
+      // -----------------------
+      // calculate also for matrix and vector multiplied by factor 0.5
+      // this should make no difference if everything is correct but
+      // it can go wrong if insensitive DoF is included
+      CLHEP::HepSymMatrix cov2 = *d2Chi2 * .5;
+      // invert the matrix
+      int ierr2 = 0;
+      cov2.invert(ierr2);
+      if(ierr2>0)
+        msg(MSG::WARNING)<<"Second CLHEP inversion status flag = "<<ierr2<<endreq;
+
+      CLHEP::HepVector delta2 = cov2 * (*dChi2) * .5;
+      for (int i=0;i<delta.num_row(); ++i)
+        if ( fabs((delta[i] - delta2[i])/delta[i]) > 1e-5 ) {
+          msg(MSG::WARNING)<<"Something's wrong with the matrix inversion: delta["<<i<<"] = "<<delta[i]<<"    delta2["<<i<<"] = "<<delta2[i]<<endreq;
+          status=false;
+          break;
+        }
+
+      if(m_logStream && (ierr2>0 || !status)) {
+        *m_logStream<<"CLHEP inversion status flag for halfed matrix = "<<ierr2<<std::endl;
+        *m_logStream<<"Matrix inversion check failed"<<std::endl;
+        *m_logStream<<std::endl;
+      }
+      // -- end of check of matrix inversion
+    }
+    else {
+      // ==========================================================
+      // Run Diagonalization
+      ATH_MSG_INFO("Running diagonalization");
+      if(m_logStream)
+        *m_logStream<<"Running diagonalization"<<std::endl;
+
+      CLHEP::HepSymMatrix D = *d2Chi2;
+      CLHEP::HepMatrix U = CLHEP::diagonalize( &D );
+
+      ATH_MSG_INFO("Diagonalization done");
+      //sold = U*sdiag*U.T.
+
+      // reorder eigenvalues ascending
+      // eigenvectors need to be reordered consistently
+      ATH_MSG_DEBUG(" Reordering eigenvalues ascending ");
+      for (int i=0; i<m_aNDoF-1; i++)
+        for (int j=i+1; j<m_aNDoF; j++)
+          if(D[j][j] < D[i][i]) {
+            // swap eigenvalues
+            double ei = D[i][i];
+            D[i][i] = D[j][j];
+            D[j][j] = ei;
+            // swap eigenvectors
+            for(int k=0;k<m_aNDoF; k++) {
+              double ev = U[k][i];
+              U[k][i] = U[k][j];
+              U[k][j] = ev;
+            }
+          }
+
+      // how do I now get the eigenvalues? this cannot be the most
+      // efficient way ...  CLHEP::HepSymMatrix D = d2Chi2->similarityT( U );
+      CLHEP::HepVector eigenvector(m_aNDoF);
+
+      if(m_logStream)
+        *m_logStream<<"/------ The Eigenvalue Spectrum -------"<<std::endl;
+
+      ATH_MSG_DEBUG("Calculating eigenvalues");
+      for(int imode=0; imode<m_aNDoF; ++imode) {
+
+        // get the relevant eigenvector
+        for(int irow=0; irow<m_aNDoF; ++irow)
+          eigenvector[irow] = U[irow][imode];
+
+        // calculate the eigenvalue
+        //double eigenvalue = d2Chi2->similarity( eigenvector );
+        double eigenvalue = D[imode][imode];
+        ATH_MSG_DEBUG("eigenvalue "<<eigenvalue);
+
+        double evdotb = dot(*dChi2,eigenvector);
+        CLHEP::HepVector thisdelta = evdotb/eigenvalue * eigenvector;
+        deltafull += thisdelta;
+
+        if(imode<m_modcut) {
+          ATH_MSG_INFO("skipping eigenvalue "<<imode<<" : "<<eigenvalue<<" , modcut is "<<m_modcut);
+          if(m_logStream)
+             *m_logStream<<"| skipping eigenvalue "<<eigenvalue<<std::endl;
+        }
+        else if( eigenvalue < m_eigenvaluethreshold ) {
+          ATH_MSG_INFO("skipping eigenvalue "<<eigenvalue<<" , cut is "<<m_eigenvaluethreshold);
+          if(m_logStream)
+             *m_logStream<<"| skipping eigenvalue "<<eigenvalue<<std::endl;
+        }
+        else {
+          if(m_logStream)
+            *m_logStream<<"| "<<eigenvalue<<std::endl;
+
+          delta += thisdelta;
+
+          // this is the time consuming part
+          for(int irow=0; irow<m_aNDoF; ++irow)
+            for(int icol=0; icol<=irow; ++icol)
+              cov[irow][icol] += eigenvector[irow] * eigenvector[icol] / eigenvalue;
+        }
+      }
+
+      // the covariance matrix is actually defined as 2 * d2Chi2^-1
+
+      ATH_MSG_DEBUG("Result: "<<delta);
+      ATH_MSG_DEBUG("cov: "<<cov);
+
+      if(m_logStream)
+        *m_logStream<<"\\----- End of Eigenvalue Spectrum -----"<<std::endl;
+
+      // end of diagonalization
+      // ==========================================================
+    }
+
+    // stop measuring time
+    clock_t stoptime = clock();
+    double totaltime = (stoptime-starttime)/double(CLOCKS_PER_SEC);
+    ATH_MSG_INFO("Time spent in solveCLHEP: "<<totaltime<<" s");
+
+    if(ierr==0 && status)
+    {
+      ATH_MSG_DEBUG("Alignment constants:");
+      for (int iAdof=0;iAdof<m_aNDoF;iAdof++) {
+
+        int idof = m_activeIndices[iAdof];
+        AlignPar * alignPar=(*alignParList)[idof];
+
+        double sigma = alignPar->sigma();
+        double param = -delta[iAdof] * sigma;
+        double err = std::sqrt(2.*std::fabs(cov[iAdof][iAdof])) * sigma;
+
+        ATH_MSG_DEBUG(iAdof <<" : "<< param << " +/- "<< err);
+        ATH_MSG_DEBUG("cov("<<iAdof<<")="<<cov[iAdof][iAdof]<<", sigma: "<<sigma);
+        ATH_MSG_DEBUG("init par: "<<alignPar->initPar());
+        alignPar->setPar(param,err);
+        ATH_MSG_DEBUG("set param to "<<param<<" for alignPar "<<alignPar);
+        ATH_MSG_DEBUG(*(*alignParList)[idof]);
+      }
+
+      if(m_logStream) {
+        printGlobalSolution(*m_logStream,&cov);
+
+        // norm of first derivative
+        *m_logStream<<"norm of first derivative :            "<<dChi2->norm()<<std::endl;
+
+        // distance to solution
+        double dist = ( - (*d2Chi2) * deltafull + (*dChi2) ).norm();
+        *m_logStream<<"distance to solution :                "<<dist<<std::endl;
+
+        // calculate chi2 of the alignment change
+        double chi2 = d2Chi2->similarity(delta) * .5;
+        *m_logStream<<"delta(chi2) of the alignment change : "<<chi2<<" / "<<m_aNDoF<<std::endl;
+
+        // time spent here
+        *m_logStream<<"time spent in solve :                 "<<totaltime<<" s"<<std::endl;
+      }
+    }
+
+    delete d2Chi2;
+    delete dChi2;
+
+    return 1;
+  }
+
+  //_______________________________________________________________________
+  int MatrixTool::solveLocal()
+  {
+    ATH_MSG_INFO("solving using Local method");
+    if(m_logStream) {
+      *m_logStream<<"*************************************************************"<<std::endl;
+      *m_logStream<<"**************  solving using Local method  *****************"<<std::endl;
+      *m_logStream<<"*************************************************************"<<std::endl;
+    }
+
+    int    totalNDoF(0);
+    double totalChi2(0.);
+
+    const AlignModuleList * alignModules = m_alignModuleTool->alignModules1D();
+
+    AlignModuleList::const_iterator imod     = alignModules->begin();
+    AlignModuleList::const_iterator imod_end = alignModules->end();
+    for( ; imod!=imod_end; ++imod) {
+
+      AlignModule * module = *imod;
+
+      ATH_MSG_INFO("Solving for module: "<<module->name());
+
+      DataVector<AlignPar> * alignPars = m_alignModuleTool->getAlignPars(module);
+
+      int thisNDoF = alignPars->size();
+
+      CLHEP::HepSymMatrix d2Chi2(thisNDoF,0);
+      CLHEP::HepVector dChi2(thisNDoF,0);
+      for (int i=0;i<thisNDoF;++i) {
+        int ipar = alignPars->at(i)->index();
+        dChi2[i] = (*m_bigvector)[ipar];
+        for (int j=0;j<thisNDoF;++j) {
+          int jpar = alignPars->at(j)->index();
+          d2Chi2[i][j] = (*m_bigmatrix)[ipar][jpar];
+        }
+      }
+
+//      ATH_MSG_INFO("First derivatives:" << dChi2);
+//      ATH_MSG_INFO("Second derivatives:" << d2Chi2);
+
+      if(module->nHits() < m_minNumHits || module->nTracks() < m_minNumTrks) {
+        ATH_MSG_INFO("Not enough hits in module \'"<<module->name()<<"\':  "
+         <<module->nHits()<<" < "<<m_minNumHits<<" or "
+         <<module->nTracks()<<" <  "<<m_minNumTrks
+         <<". Skipping...");
+
+        // print module summary even when solving is not done
+        if(m_logStream)
+          printModuleSolution(*m_logStream,module,0);
+
+        continue;
+      }
+
+      ATH_MSG_DEBUG("First derivatives:" << dChi2);
+      ATH_MSG_DEBUG("Second derivatives:" << d2Chi2);
+
+
+      totalNDoF += thisNDoF;
+
+      CLHEP::HepSymMatrix cov(d2Chi2);
+
+      // invert the matrix
+      int ierr = 0;
+      cov.invert(ierr);
+      if(ierr>0)
+        ATH_MSG_WARNING("CLHEP inversion status flag = "<<ierr);
+      else
+        ATH_MSG_DEBUG("CLHEP inversion status flag = "<<ierr);
+
+      // calculate corrections
+      CLHEP::HepVector delta = cov * dChi2;
+      //ATH_MSG_DEBUG("d2Chi2: "<<d2Chi2);
+      //ATH_MSG_DEBUG("cov: "<<cov);
+      //ATH_MSG_DEBUG("d2Chi2*cov: "<<d2Chi2*cov);
+      //ATH_MSG_DEBUG("dChi2: "<<dChi2);
+      ATH_MSG_DEBUG("Result: "<<delta);
+
+      ATH_MSG_DEBUG("Alignment constants:");
+      for (int idof=0;idof<thisNDoF;++idof) {
+        AlignPar * alignPar = alignPars->at(idof);
+
+        double sigma = alignPar->sigma();
+        double param = -delta[idof] * sigma;
+        double err = std::sqrt(2.*std::fabs(cov[idof][idof])) * sigma;
+
+        ATH_MSG_DEBUG(idof <<" : "<< param << " +/- "<< err);
+        ATH_MSG_DEBUG("cov("<<idof<<")="<<cov[idof][idof]<<", sigma: "<<sigma);
+        ATH_MSG_DEBUG("init par: "<<alignPar->initPar());
+
+        ATH_MSG_DEBUG("Filling constants obtained using Local method");
+        alignPar->setPar(param,err);
+        ATH_MSG_DEBUG("set param to "<<param<<" for alignPar "<<alignPar);
+        ATH_MSG_DEBUG(*alignPar);
+      }
+
+      if(m_logStream) {
+        printModuleSolution(*m_logStream,module,&cov);
+
+        *m_logStream<<"CLHEP inversion status flag = "<<ierr<<std::endl;
+
+        // calculate chi2 of the alignment change
+        double chi2 = d2Chi2.similarity(delta) * .5;
+        totalChi2 += chi2;
+        *m_logStream<<"delta(chi2) of the alignment change : "<<chi2<<" / "<<thisNDoF<<std::endl;
+      }
+    }
+
+    if(m_logStream) {
+      *m_logStream<<"--------------------------------------------------------------------------------"<<std::endl;
+      *m_logStream<<"Total delta(chi2) of the alignment change from the local method : "<<totalChi2<<" / "<<totalNDoF<<std::endl;
+      *m_logStream<<std::endl;
+    }
+
+    return 1;
+  }
+  
+   //________________________________________________________________________
+  bool MatrixTool::accumulateFromFiles()
+  {
+    
+    if(m_readTFiles){ 
+      ATH_MSG_INFO("Info to obtained from from TFiles");
+      return accumulateFromTFiles();
+    }else{ 
+      ATH_MSG_INFO("Info to obtained from from Binary files");
+      return accumulateFromBinaries();
+    }
+  }
+
+  //________________________________________________________________________
+  bool MatrixTool::accumulateFromBinaries()
+  {
+    
+    
+    DataVector<AlignPar>* alignParList = m_alignModuleTool->alignParList1D();
+    int nDoF=alignParList->size();
+
+    std::map<int,unsigned long long> modIndexMap;
+    float dummyVersion(0.);
+    double totalscale=0.;
+    for (int ivec=0;ivec<(int)m_inputVectorFiles.size();ivec++) {
+
+      ATH_MSG_INFO("Reading vector "<<ivec<<" from file "<<m_inputVectorFiles[ivec]);
+
+      AlVec newVector(nDoF);
+      std::map<int,unsigned long long> newModIndexMap;
+      newVector.SetPathBin(m_pathbin+m_prefixName);
+      newVector.SetPathTxt(m_pathtxt+m_prefixName);
+      double scale=0;
+      StatusCode sc = newVector.ReadPartial(m_inputVectorFiles[ivec],scale,newModIndexMap,dummyVersion);
+      totalscale += scale;
+      if (sc==StatusCode::FAILURE) {
+        msg(MSG::FATAL)<<"Problem reading vector from "<<m_inputVectorFiles[ivec]<<endreq;
+        return false;
+      }
+      if (newVector.size()!=m_bigvector->size()) {
+        msg(MSG::FATAL) <<"vector wrong size!  newVector size "<<newVector.size()
+                        <<", bigvector size "<<m_bigvector->size()<<endreq;
+        return false;
+      }
+
+      // check modIndexMaps to make sure they are the same
+      if (ivec==0)
+        modIndexMap = newModIndexMap;
+      else if (modIndexMap!=newModIndexMap) {
+        msg(MSG::FATAL)<<"module index maps don't agree!"<<endreq;
+        return false;
+      }
+      if (ivec>0)
+        *m_bigvector += newVector;
+      else
+        *m_bigvector  = newVector;
+    }
+
+    m_scale = totalscale;
+
+    AlSymMat * symBigMatrix=dynamic_cast<AlSymMat*>(m_bigmatrix);
+    AlSpaMat * spaBigMatrix=dynamic_cast<AlSpaMat*>(m_bigmatrix);
+
+
+    for (int imat=0;imat<(int)m_inputMatrixFiles.size();imat++) {
+      ATH_MSG_INFO("Reading matrix "<<imat<<" from file "<<m_inputMatrixFiles[imat]);
+
+      // create new matrix to read data from current file
+      int nDoF=modIndexMap.size();
+      bool triang;
+      StatusCode sc;
+      if (symBigMatrix) {
+        AlSymMat newMatrix(nDoF);
+        sc = newMatrix.Read(m_inputMatrixFiles[imat],nDoF,triang,dummyVersion);
+        if (sc==StatusCode::SUCCESS)
+          *symBigMatrix += newMatrix;
+      }
+      else {
+        AlSpaMat newMatrix(nDoF);
+        sc = newMatrix.Read(m_inputMatrixFiles[imat],nDoF,triang,dummyVersion);
+
+        if (sc==StatusCode::SUCCESS) {
+          if (imat>0)
+            *spaBigMatrix += newMatrix;
+          else
+            *spaBigMatrix  = newMatrix;
+        }
+      }
+
+      if (sc==StatusCode::FAILURE) {
+        msg(MSG::FATAL)<<"problem reading matrix from "<<m_inputMatrixFiles[imat]<<endreq;
+        return false;
+      }
+
+      if (!m_useSparse && triang==m_wSqMatrix) {
+        ATH_MSG_WARNING("matrix not expected format!  Changing m_wSqMatrix to "<<!triang);
+        m_wSqMatrix=!triang;
+      }
+
+    }
+
+    // accumulate hitmap from hitmap files
+    if(m_readHitmaps)
+      readHitmaps();
+
+    return true;
+  }
+
+  //_______________________________________________________________________
+  void MatrixTool::storeInTFile(TString filename)
+  {
+    //Store reults in a single TFile....
+    //Including Matrix Vector Hitmap.. Soluton EV’s etc.
+    
+    ATH_MSG_INFO("Writing Results to a TFile");
+    
+    DataVector<AlignPar> * alignParList = m_alignModuleTool->alignParList1D();
+    int nDoF = alignParList->size();
+  
+    TMatrixDSparse* myTMatrix = m_bigmatrix->makeTMatrix();
+
+    ATH_MSG_INFO( "Created TMatrixDSparse" );
+
+  
+    double *val = new double[nDoF];
+    for (int i=0;i<nDoF;i++) {
+      val[i] = (*m_bigvector)[i];
+    }
+  
+    TVectorD myTVector(nDoF, val);
+    delete [] val;
+  
+    ATH_MSG_INFO( "Created TVectorD" );
+
+  
+    const AlignModuleList * moduleList = m_alignModuleTool->alignModules1D();
+    int nModules = moduleList->size();
+  
+    double *hitmapA = new double[nModules];
+    double *hitmapB = new double[nModules];
+    AlignModuleList::const_iterator imod     = moduleList->begin();
+    AlignModuleList::const_iterator imod_end = moduleList->end();
+    int index(0);
+    for(; imod != imod_end; ++imod) {
+      AlignModule * module = *imod;
+      hitmapA[index] = (double)module->nHits();
+      hitmapB[index] = (double)module->nTracks();
+      index++;
+    }
+  
+    TVectorD hitmapHits(nModules, hitmapA); 
+    TVectorD hitmapTracks(nModules, hitmapB);
+    
+    delete [] hitmapA;
+    delete [] hitmapB;
+    
+
+
+    TFile myFile(filename,"recreate");
+    hitmapHits.Write("Hits");
+    hitmapTracks.Write("Tracks");
+    myTMatrix->Write("Matrix");
+    myTVector.Write("Vector");
+    
+    TVectorD scale(1, &m_scale) ;
+    scale.Write("Scale");
+    
+   
+    double *moduleInfoA = new double[nDoF];//unsigned long long 
+    double *dofInfoA = new double[nDoF];//int 
+  
+    if (sizeof(unsigned long long) != sizeof(double))      
+      ATH_MSG_ERROR("Module Identifiers will not be saved.  sizeof(double)!=sizeof(ulonglong)");
+    else{      
+      
+      DataVector<AlignPar>* alignPars = m_alignModuleTool->alignParList1D();
+      for (int i=0;i<(int)alignPars->size();i++) {
+        //Do a direct memory copy to store unsigned long long in the momory of a double
+        double target;
+        uint64_t  id = (*alignPars)[i]->alignModule()->identify().get_compact();
+        memcpy(&target, &id, sizeof(target));
+        moduleInfoA[i]=target;
+        //moduleInfoB[i]=(*alignPars)[i]->alignModule()->name();
+        uint64_t dof = (*alignPars)[i]->paramType();
+        memcpy(&target, &dof, sizeof(target));
+        dofInfoA[i]=target;
+      }
+  
+      TVectorD moduleIDs(nDoF, moduleInfoA) ;
+      TVectorD moduleDoFs(nDoF,dofInfoA);
+      delete [] moduleInfoA;
+      moduleIDs.Write("ModuleID");
+      moduleDoFs.Write("dof");
+    }
+    
+    myFile.Write();
+    myFile.Close();
+    
+    delete myTMatrix;
+    ATH_MSG_INFO("Finshed writing TFILE");
+
+  }
+
+//________________________________________________________________________
+  bool MatrixTool::accumulateFromTFiles()
+  {
+    DataVector<AlignPar>* alignParList = m_alignModuleTool->alignParList1D();
+    int nDoF=alignParList->size();
+    ATH_MSG_INFO("OPENING TFILES");
+
+    std::map<int,unsigned long long> modIndexMap;
+    std::map<int,unsigned long long> DoFMap;
+    double totalscale=0.;
+
+    AlSymMat * symBigMatrix=dynamic_cast<AlSymMat*>(m_bigmatrix);
+    AlSpaMat * spaBigMatrix=dynamic_cast<AlSpaMat*>(m_bigmatrix);
+    //TMatrixDSparse *accumMatrix(0);
+    AlSpaMat *accumMatrix = 0;
+    
+    const AlignModuleList * moduleList = m_alignModuleTool->alignModules1D();
+    int nModules = moduleList->size();
+    
+    TVectorD TotalHits(nModules);
+    TVectorD TotalTracks(nModules);
+   
+    int numberOfReadErrors = 0; 
+   
+    struct rusage myusage;
+    int itworked =  getrusage(RUSAGE_SELF,&myusage);
+    if(itworked)
+		  ATH_MSG_DEBUG("ItWorked");
+
+		long intialMemUse = myusage.ru_maxrss;
+
+    for (int ifile = 0; ifile < (int)m_inputTFiles.size(); ifile++) {
+      if (numberOfReadErrors > m_maxReadErrors){
+        msg(MSG::FATAL) << " number of errors when reading the TFiles already exceed " << m_maxReadErrors << endreq;
+        return false;
+      }
+   
+      ATH_MSG_INFO("Reading File number " << ifile << ",  " << m_inputTFiles[ifile]);
+      
+      itworked =  getrusage(RUSAGE_SELF,&myusage);
+      ATH_MSG_INFO("Memory usage [MB], total " << myusage.ru_maxrss/1024 << ", increase  " << (myusage.ru_maxrss-intialMemUse)/1024);
+       
+      TFile* myFile = TFile::Open(m_inputTFiles[ifile].c_str()); 
+      
+      if ( myFile->IsZombie() || !(myFile->IsOpen()) ) {
+        ++numberOfReadErrors;
+        ATH_MSG_ERROR( " Problem reading TFile " << m_inputTFiles[ifile] );
+        continue;
+      }
+      
+      std::map<int,unsigned long long> newModIndexMap;
+      
+      TVectorD* myModuleIDs;
+      myModuleIDs = (TVectorD*)myFile->Get("ModuleID");
+      if( !myModuleIDs ){
+        ++numberOfReadErrors;
+        ATH_MSG_ERROR("Modules ID not read!!!");
+        continue;
+      }
+      
+      for (int i(0); i<myModuleIDs->GetNrows(); ++i){
+        //Coverting back from a double to a unvi signed long long
+        double source = (*myModuleIDs)(i);
+        uint64_t target;
+        memcpy(&target, &source, sizeof(target));
+        newModIndexMap[i]=target;
+        //std::cout << i<< " " <<target <<std::endl; 
+      }
+      
+      delete myModuleIDs;
+      
+      std::map<int,unsigned long long> newDoFMap;
+      
+      TVectorD* myDoFs;
+      myDoFs = (TVectorD*)myFile->Get("dof");
+      if( !myDoFs ){
+        ++numberOfReadErrors;
+        ATH_MSG_ERROR("DoFs not read!!!");
+        continue;
+      }
+      
+      for (int i(0); i<myDoFs->GetNrows(); ++i){
+        //Coverting back from a double to a unsigned long long
+        double source = (*myDoFs)(i);
+        uint64_t target;
+        memcpy(&target, &source, sizeof(target));
+        newDoFMap[i]=target;
+      }
+      delete myDoFs;
+      
+      
+      TVectorD* Scale;
+      Scale = (TVectorD*)myFile->Get("Scale");
+      if( !Scale ){
+        ++numberOfReadErrors;
+        ATH_MSG_ERROR("Scale not read!!!");
+        continue;
+      }
+      
+      double scale=(*Scale)(0);
+      totalscale += scale;
+      delete Scale;
+      
+            
+      ATH_MSG_INFO("Reading Vector");
+      TVectorD* vector = (TVectorD*)myFile->Get("Vector");
+      if( !vector ){
+        ++numberOfReadErrors;
+        ATH_MSG_ERROR("Vector not read!!!");
+        continue;
+      }
+      
+      AlVec* newVector = new AlVec(nDoF);
+      newVector->SetPathBin(m_pathbin+m_prefixName);
+      newVector->SetPathTxt(m_pathtxt+m_prefixName);
+      
+      if (newVector->size()  != m_bigvector->size() ) {
+         msg(MSG::FATAL) << "vector wrong size!  newVector size " << newVector->size()
+                         << ", bigvector size " << m_bigvector->size()<<endreq;
+         delete newVector;
+         delete vector;
+         return false;
+      }
+      
+      if (m_bigvector->size() != vector->GetNrows() ) {
+         msg(MSG::FATAL) << "File vector wrong size!  File Vector size " << vector->GetNrows()
+                         << ", bigvector size " << m_bigvector->size()<<endreq;
+         delete newVector;
+         delete vector;
+         return false;
+      }
+      
+        
+      for (int i=0;i<nDoF;i++) {
+        (*newVector)[i] = (*vector)(i);
+      }
+      delete vector;
+      
+      // check modIndexMaps to make sure they are the same
+      if (ifile == 0){
+        DoFMap = newDoFMap;
+      } else if (DoFMap!=newDoFMap) {
+        msg(MSG::FATAL) << "module dofs don't agree!" << endreq;
+        return false;
+      }
+      
+      if (ifile == 0){
+         modIndexMap = newModIndexMap;
+      } else if (modIndexMap!=newModIndexMap) {
+         msg(MSG::FATAL) << "module index maps don't agree!" << endreq;
+         return false;
+      }
+      
+      if (ifile>0){
+        *m_bigvector += *newVector;
+        delete newVector;  
+      } else {
+        delete m_bigvector;
+        m_bigvector  = newVector;
+      }
+      
+      
+      ATH_MSG_INFO("Reading matrix ");
+      TMatrixDSparse* matrix = (TMatrixDSparse*)myFile->Get("Matrix");
+      
+      if( !matrix ){
+        ++numberOfReadErrors;
+        ATH_MSG_ERROR("Matrix not read!!!");
+        continue;
+      }
+      
+      
+      if (ifile == 0 ){ 
+      
+        accumMatrix = new AlSpaMat(nDoF);
+        ATH_MSG_INFO("Matrix size b4 "<< accumMatrix->ptrMap()->size()  );
+        
+        //This method is ok for large matrix files... really only access the non zero elements
+        for (int ii=0;ii<nDoF;ii++) {
+          const TMatrixTSparseRow_const<double> myRow = (*matrix)[ii];
+          int i =  myRow.GetRowIndex();
+          for (int jj=0;jj<myRow.GetNindex();jj++) {
+            int j = (myRow.GetColPtr())[jj];
+            const double  myElement= (myRow.GetDataPtr())[jj];
+            if (i<j){
+              ATH_MSG_INFO("i < j " );
+              j = i;
+              i = (myRow.GetColPtr())[jj];
+            }
+            (*accumMatrix)[i][j] = myElement;
+          }
+        }         
+        ATH_MSG_INFO("Matrix size AF "<< accumMatrix->ptrMap()->size()  );
+  
+      } else if ( accumMatrix) {        
+        ATH_MSG_INFO("Matrix size b4 "<< accumMatrix->ptrMap()->size()  );
+  
+        for (int ii=0;ii<nDoF;ii++) {
+          const TMatrixTSparseRow_const<double> myRow = (*matrix)[ii];
+          int i =  myRow.GetRowIndex();
+          for (int jj=0;jj<myRow.GetNindex();jj++) {
+            int j = (myRow.GetColPtr())[jj];
+            const double  myElement= (myRow.GetDataPtr())[jj];
+            if (i<j){
+              ATH_MSG_INFO("i < j " );
+              j = i;
+              i = (myRow.GetColPtr())[jj];
+            }
+            (*accumMatrix)[i][j] += myElement;
+          }
+        }
+        ATH_MSG_INFO("Matrix size AF "<< accumMatrix->ptrMap()->size()  );
+ 
+      } else {
+        delete matrix;
+        ++numberOfReadErrors;
+        ATH_MSG_ERROR("Matrix allocation error!!!");
+        continue;
+      }
+            
+      delete matrix;
+      
+      TVectorD* hits;
+      TVectorD* tracks;
+      
+      ATH_MSG_INFO("Reading hitmap ");
+      hits = (TVectorD*)myFile->Get("Hits");
+      if( !hits ){
+        ++numberOfReadErrors;
+        ATH_MSG_ERROR("Hitmap 1 not read!!!");
+        continue;
+      }
+      
+      tracks = (TVectorD*)myFile->Get("Tracks");
+      if( !tracks ){
+        delete hits;
+        ++numberOfReadErrors;
+        ATH_MSG_ERROR("Hitmap 2 not read!!!");
+        continue;
+      }
+      
+      if(hits->GetNrows() != TotalHits.GetNrows() ){
+        delete hits;
+        delete tracks; 
+        ++numberOfReadErrors;
+        ATH_MSG_ERROR("Hitmap size incorrect!!!");
+        continue;
+      }
+      
+      TotalHits   += (*hits);    
+      TotalTracks += (*tracks);
+      
+      delete hits;
+      delete tracks;
+      
+      myFile->Close("R");
+      delete myFile;
+
+      itworked =  getrusage(RUSAGE_SELF,&myusage);
+      ATH_MSG_INFO("Memory usage [MB], total " << myusage.ru_maxrss/1024 << ", increase  " << (myusage.ru_maxrss-intialMemUse)/1024);
+
+    }
+
+
+
+    // create new matrix to read data from current file
+    if(accumMatrix){
+      if (symBigMatrix) {
+        AlSymMat newMatrix(nDoF);
+        //This method is ok for small matrix files
+        for (int i=0;i<nDoF;i++) {
+          for (int j=0;j<=i;j++) {
+            newMatrix[i][j] = (*accumMatrix)[i][j];
+          }
+        }       
+
+        *symBigMatrix += newMatrix;
+        delete accumMatrix;
+      } else if (spaBigMatrix) { 
+        std::cout << "should reassign matrix "<< spaBigMatrix->ptrMap()->size() << std::endl;        
+        *spaBigMatrix  += *accumMatrix;     
+        std::cout << "??????  "<< spaBigMatrix->ptrMap()->size() << std::endl;
+        delete accumMatrix;
+      }
+    }
+
+        std::cout << "??????  "<< m_bigmatrix->ptrMap()->size() << std::endl;
+
+    AlignModuleList::const_iterator imod     = moduleList->begin();
+    AlignModuleList::const_iterator imod_end = moduleList->end();
+    int index = 0;
+    int totalhits = 0;
+    for(; imod != imod_end; ++imod, ++index ) {
+          AlignModule * module = *imod;
+          module->setNHits((int)TotalHits(index));
+          module->setNTracks((int)TotalTracks(index));
+          totalhits += (int)TotalHits(index);
+    }
+
+
+    m_nHits = totalhits;
+    m_nTracks = 0;
+    m_nMeasurements = 0;
+    m_scale = totalscale;
+
+    return true;
+  }
+
+
+
+
+  //_______________________________________________________________________
+  int MatrixTool::solve()
+  {
+    // ============
+    // solve
+    // ============
+    ATH_MSG_DEBUG("in MatrixTool::solve()");    
+
+    // set normalization scale to number of hits for now
+    if(m_scale<0)
+      m_scale = m_nHits;
+
+    //-------------------------------------------------------
+    // write matrix and vector to file
+    if (m_writeMat) {
+      // version has to be 2 to for reading matrices and vectors back in to work properly
+      double dummyVersion(2.);
+
+      // make map of matrix entry to module index (set by geometry manager tool)
+      std::map<int,unsigned long long> modIndexMap;
+      std::map<int,std::string>        modNameMap;
+      DataVector<AlignPar>* alignPars = m_alignModuleTool->alignParList1D();
+      for (int i=0;i<(int)alignPars->size();i++) {
+        modIndexMap[i]=(*alignPars)[i]->alignModule()->identify().get_compact();
+        modNameMap [i]=(*alignPars)[i]->alignModule()->name();
+      }
+
+      // binary files
+      ATH_MSG_DEBUG("writing binary files");
+      StatusCode sc1 = m_bigmatrix->Write("matrix.bin",true,m_wSqMatrix,m_scale,dummyVersion);
+      StatusCode sc2 = m_bigvector->WritePartial("vector.bin",true,m_scale,modIndexMap,dummyVersion);
+      if (!sc1.isSuccess() || !sc2.isSuccess()) {
+        msg(MSG::ERROR)<<"problem writing matrix or vector"<<endreq;
+        return -1;
+      }
+
+      if (m_writeMatTxt) {
+
+        // text files
+        ATH_MSG_DEBUG("writing text files");
+        sc1 = m_bigmatrix->Write("matrix.txt",false,m_wSqMatrix,m_scale,dummyVersion);
+        sc2 = m_writeModuleNames ? 
+          m_bigvector->WritePartial("vector.txt",false,m_scale,modNameMap,dummyVersion) :
+          m_bigvector->WritePartial("vector.txt",false,m_scale,modIndexMap,dummyVersion);
+  
+        if (!sc1.isSuccess() || !sc2.isSuccess()) {
+          msg(MSG::ERROR)<<"problem writing matrix or vector"<<endreq;
+          return -1;
+        }
+      }
+
+      ATH_MSG_DEBUG("matrix and vector written to: "<<m_pathbin+m_prefixName<<"matrix.bin (.txt) and "<<m_pathbin+m_prefixName<<"vector.bin (.txt)");
+    }
+
+    //-------------------------------------------------------
+    // write hitmap to file
+    if (m_writeHitmap)
+      writeHitmap();
+
+    if(m_writeTFile)
+      storeInTFile(m_pathbin+m_prefixName+m_tfileName);
+
+
+    if(!m_runLocal && m_solveOption==0) {
+      ATH_MSG_INFO("No solving requested.");
+      return 1;
+    }
+
+    //-------------------------------------------------------
+    // rescale the vector and the matrix according to sigmas
+    // and apply soft mode cut
+
+    ATH_MSG_INFO("rescaling the matrix/vector and applying the soft-mode-cut");
+
+    DataVector<AlignPar>* alignParList = m_alignModuleTool->alignParList1D();
+    int nDoF = alignParList->size();
+
+
+    const AlSymMat * chkMatrix = dynamic_cast<const AlSymMat*>(m_bigmatrix);
+    if(chkMatrix){
+      // Method when using the dense matrix
+      for (int i=0;i<nDoF;i++) {
+        // scale the vector
+        double sigma_i = (*alignParList)[i]->sigma();
+        double softCut = 2 * pow( (*alignParList)[i]->softCut() , -2 );
+        (*m_bigvector)[i] *= sigma_i;
+  
+        for (int j=0;j<=i;j++) {
+          // scale the matrix
+          if ((*chkMatrix)[i][j] != 0.) {
+            double sigma_j = (*alignParList)[j]->sigma();
+            (*m_bigmatrix)[i][j] *= sigma_i * sigma_j;
+          }
+          // apply soft-mode-cut
+          if (i==j && m_softEigenmodeCut>0.){
+            (*m_bigmatrix)[i][j] += m_softEigenmodeCut * softCut;
+         
+          }
+  
+          // set first and second derivatives on AlignPar
+          if (i==j) {
+            (*alignParList)[i]->setFirstDeriv((*m_bigvector)[i]/sigma_i);
+            (*alignParList)[i]->setSecndDeriv((*m_bigmatrix)[i][i]/sigma_i/sigma_i);
+          }
+        }
+      }    
+    } else {
+      // Method when using the sparse matrix
+      const_mapiterator pos = m_bigmatrix->ptrMap()->begin();
+      for( ; pos!=m_bigmatrix->ptrMap()->end(); pos++){
+        int i = pos->first.first;
+        int j = pos->first.second;
+  
+        // Scale matrix
+        double sigma_i = (*alignParList)[i]->sigma();
+        double sigma_j = (*alignParList)[j]->sigma();
+        
+        (*m_bigmatrix)[i][j] *= sigma_i * sigma_j;
+  
+      }
+  
+  
+      for (int i=0;i<nDoF;i++) {
+        // scale the vector
+        double sigma_i = (*alignParList)[i]->sigma();
+        (*m_bigvector)[i] *= sigma_i;
+        if (m_softEigenmodeCut >0. ){
+          double softCut = 2 * pow( (*alignParList)[i]->softCut() , -2 );
+          (*m_bigmatrix)[i][i] += m_softEigenmodeCut * softCut;
+          ATH_MSG_INFO( "DOF "<< i <<" Nhits "<< (*alignParList)[i]->alignModule()->nHits() << " soft-mode-cut "<< (*alignParList)[i]->softCut() <<" -> " << m_softEigenmodeCut * softCut  << " sigma_i "<< sigma_i << " Matrix: " << (*m_bigmatrix)[i][i] << " Vector: " << (*m_bigvector)[i]);
+        }
+        (*alignParList)[i]->setFirstDeriv((*m_bigvector)[i]/sigma_i);
+        (*alignParList)[i]->setSecndDeriv((*m_bigmatrix)[i][i]/sigma_i/sigma_i);
+      }
+    }
+   
+    ATH_MSG_INFO("rescaling done");
+
+    // select modules with non-zero tracks
+    for(int i=0;i<nDoF;i++)
+      if((*alignParList)[i]->alignModule()->nHits() >= m_minNumHits && (*alignParList)[i]->alignModule()->nTracks() >= m_minNumTrks)
+        m_activeIndices.push_back(i);
+    m_aNDoF = m_activeIndices.size();
+    ATH_MSG_DEBUG("aNDoF/nDoF: "<<m_aNDoF<<"/"<<nDoF);
+
+    // --------------------
+    // now do the SOLVING
+    // --------------------
+
+    int info = 0;
+
+    // first Local solving
+    if (m_runLocal)
+      info = solveLocal();
+
+    // remove spurious modules and resize
+    if (m_removeSpurious) {
+
+      ATH_MSG_INFO("Spurious removal not implemented at the moment.");
+/*      if (StatusCode::SUCCESS != spuriousRemoval()) {
+        ATH_MSG_ERROR("Problem while trying to remove spurious. Stopping solving");
+        return -1;
+      }
+
+      // if nDoF=0, bad job...
+      int NDoF = m_alignModuleTool->nAlignParameters();
+      if(NDoF==0) {
+        ATH_MSG_WARNING("Removal removed everything: NDoF=" << NDoF << " !!!");
+        return 1;
+      }
+      ATH_MSG_DEBUG("NDoF: " << NDoF);
+*/
+    }
+
+    // --------------------
+    // now Global solving
+    switch(m_solveOption) {
+
+      case NONE:
+        ATH_MSG_INFO("No global solving requested.");
+        break;
+
+      case SOLVE_ROOT:
+        info = solveROOT();
+        break;
+
+      case SOLVE_CLHEP:
+        info = solveCLHEP();
+        break;
+
+      case SOLVE:
+      case DIRECT_SOLVE:
+      case DIRECT_SOLVE_CLUSTER:
+        info = solveLapack();
+        break;
+
+      case SOLVE_FAST:
+      case DIRECT_SOLVE_FAST:
+        info = solve***REMOVED***();
+        break;
+
+      default:
+        ATH_MSG_INFO("Unknown solving option.");
+        info = 0;
+        break;
+    }
+
+    ATH_MSG_INFO("Return value from solving: "<<info);
+
+    return info;
+  }
+
+
+  //_______________________________________________________________________
+  void MatrixTool::addFirstDerivatives(AlVec* )
+  {
+    return;
+  }
+
+  //_______________________________________________________________________
+  void MatrixTool::addSecondDerivatives(AlSymMatBase* )
+  {
+    return;
+  }
+
+  //________________________________________________________________________
+  void MatrixTool::addFirstDerivatives(std::list<int,double>& )
+  {
+    return;
+  }
+
+  //________________________________________________________________________
+  void MatrixTool::addSecondDerivatives(std::list<std::pair<int,int>,double >&)
+  {
+    return;
+  }
+
+  //________________________________________________________________________
+  void MatrixTool::addFirstDerivative(int irow, double firstderiv)
+  {
+    (*m_bigvector)[irow] += firstderiv;
+  }
+
+  //________________________________________________________________________
+  void MatrixTool::addSecondDerivative(int irow, int icol, double secondderiv)
+  {
+    (*m_bigmatrix)[irow][icol] += secondderiv;
+  }
+
+  //________________________________________________________________________
+  void MatrixTool::printGlobalSolution(std::ostream & os, const CLHEP::HepSymMatrix * cov) const
+  {
+    const AlignModuleList * alignModules = m_alignModuleTool->alignModules1D();
+
+    std::vector<int>::iterator it;
+
+    AlignModuleList::const_iterator imod     = alignModules->begin();
+    AlignModuleList::const_iterator imod_end = alignModules->end();
+    for( ; imod!=imod_end; ++imod) {
+      AlignModule * module = *imod;
+
+      DataVector<AlignPar> * alignPars = m_alignModuleTool->getAlignPars(module);
+      int thisNDoF = alignPars->size();
+
+      // fill local covariance matrix
+      CLHEP::HepSymMatrix * covsub = 0;
+      if(cov && module->nHits() >= m_minNumHits && module->nTracks() >= m_minNumTrks) {
+        covsub = new CLHEP::HepSymMatrix(thisNDoF,0);
+        for (int i=0;i<thisNDoF;++i) {
+          int ipar = alignPars->at(i)->index();
+          double sigma_i = alignPars->at(i)->sigma();
+
+          std::vector<int>::const_iterator itActive = std::find(m_activeIndices.begin(),m_activeIndices.end(),ipar);
+          if( itActive == m_activeIndices.end() )
+            continue;
+          int iActive = std::distance(m_activeIndices.begin(),itActive);
+
+          for (int j=0;j<=i;++j) {
+            int jpar = alignPars->at(j)->index();
+            double sigma_j = alignPars->at(j)->sigma();
+
+            std::vector<int>::const_iterator jtActive = std::find(m_activeIndices.begin(),m_activeIndices.end(),jpar);
+            if( jtActive == m_activeIndices.end() )
+              continue;
+            int jActive = std::distance(m_activeIndices.begin(),jtActive);
+
+            (*covsub)[i][j] = (*cov)[iActive][jActive] * sigma_i * sigma_j;
+          }
+        }
+      }
+
+      printModuleSolution(os,module,covsub);
+
+      delete covsub;
+    }
+    os << "--------------------------------------------------------------------------------" << std::endl;
+  }
+
+  //________________________________________________________________________
+  void MatrixTool::printGlobalSolution(std::ostream & os, const TMatrixDSym * cov0) const
+  {
+    CLHEP::HepSymMatrix * cov = 0;
+    if(cov0) {
+      int nsize = cov0->GetNrows();
+      cov = new CLHEP::HepSymMatrix(nsize,0);
+
+      for(int i=0; i<nsize; i++)
+        for(int j=0; j<=i; j++)
+          (*cov)[i][j] = (*cov0)[i][j];
+    }
+
+    printGlobalSolution(os,cov);
+
+    delete cov;
+  }
+
+  //________________________________________________________________________
+  void MatrixTool::printModuleSolution(std::ostream & os, const AlignModule * module, const CLHEP::HepSymMatrix * cov) const
+  {
+    os << "--------------------------------------------------------------------------------" << std::endl;
+    os << "Alignment parameters for module: " << module->name() << std::endl;
+    os << "Number of tracks passing: " << module->nTracks() << std::endl;
+    if(m_minNumHits>0 && module->nHits()<m_minNumHits) {
+      os << "Number of hits too small: "<<module->nHits()<<" < "<<m_minNumHits<<"  Skipping the module"<<std::endl;
+      return;
+    }
+    if(m_minNumTrks>0 && module->nTracks()<m_minNumTrks) {
+      os << "Number of tracks too small: "<<module->nTracks()<<" < "<<m_minNumTrks<<"  Skipping the module"<<std::endl;
+      return;
+    }
+    os << "Number of hits seen:      " << module->nHits() << std::endl;
+    os << "Number of tracks seen:    " << module->nTracks() << std::endl;
+
+    DataVector<AlignPar> * alignPars = m_alignModuleTool->getAlignPars(module);
+    int thisNDoF = alignPars->size();
+
+    if(alignPars->size()==0)
+      os << "No active parameters" << std::endl;
+    else
+    {
+      os.unsetf(std::ios_base::floatfield);
+      os << std::setiosflags(std::ios_base::left) << std::setprecision(5);
+
+      // output alignment parameters and errors
+      DataVector<AlignPar>::const_iterator ipar     = alignPars->begin();
+      DataVector<AlignPar>::const_iterator ipar_end = alignPars->end();
+      for ( ; ipar != ipar_end; ++ipar) {
+        AlignPar * par = *ipar;
+        os << std::setw(10) << par->dumpType()
+           << std::setw(12) << par->par() << " +/- " << std::setw(12) << par->err()
+           << std::endl;
+      }
+
+      if(cov) {
+        // calculate local correlation matrix
+        CLHEP::HepSymMatrix corrsub(thisNDoF,0);
+        for(int irow=0; irow<thisNDoF; ++irow)
+          for(int icol=0; icol<=irow; ++icol)
+            corrsub[irow][icol] = (*cov)[irow][icol] / sqrt((*cov)[irow][irow] * (*cov)[icol][icol]);
+        os << "Local correlation matrix: " << corrsub << std::flush;
+      }
+    }
+  }
+
+  //________________________________________________________________________
+  int MatrixTool::fillVecMods()
+  {
+    return 0;
+  }
+
+  //________________________________________________________________________
+  int MatrixTool::solveLapack( )
+  {
+    ATH_MSG_INFO("solving Global using Lapack");
+    if(m_logStream) {
+      *m_logStream<<"*************************************************************"<<std::endl;
+      *m_logStream<<"**************  solving using Global method  ****************"<<std::endl;
+      *m_logStream<<"**************         using LAPACK          ****************"<<std::endl;
+      *m_logStream<<"*************************************************************"<<std::endl;
+    }
+
+    // get rescaled first and second derivatives
+    AlSymMat* aBetterMat = new AlSymMat(m_aNDoF);
+    AlVec*    aBetterVec = new AlVec(m_aNDoF);
+    for (int iActive=0;iActive<m_aNDoF;iActive++) {
+      int i = m_activeIndices[iActive];
+      (*aBetterVec)[iActive] = (*m_bigvector)[i];
+      for (int jActive=0;jActive<m_aNDoF;jActive++) {
+        int j = m_activeIndices[jActive];
+        (*aBetterMat)[iActive][jActive] = (*m_bigmatrix)[i][j];
+      }
+    }
+
+    // normalize bigmatrix and bigvector
+    if(m_scaleMatrix) {
+      if(m_scale<=0.)
+        ATH_MSG_WARNING("Scaling requested but scale not set. Not scaling matrix and vector.");
+      else {
+        (*aBetterVec) *= 1./m_scale;
+        (*aBetterMat) *= 1./m_scale;
+      }
+    }
+
+    // Print() method is not yet implemented for AlVec and AlSymMat
+//    ATH_MSG_DEBUG("First derivatives: "<<aBetterVec->Print());
+//    ATH_MSG_DEBUG("Second derivatives: "<<aBetterMat->Print());
+
+    ATH_MSG_DEBUG("Now Solving alignment using lapack diagonalization routine dspev...");
+
+    if (m_calDet) {
+      const double tol = 1.e-20;
+      // compute final determinant
+      double determ = (*aBetterMat).determinant();
+      ATH_MSG_INFO("Determinant: " << determ);
+      if (fabs(determ) < tol)
+        ATH_MSG_WARNING("Matrix is singular!");
+    }
+
+    // store the original matrix for checks
+    AlSymMat * d2Chi2 = 0;
+    if (m_calculateFullCovariance)
+      d2Chi2 = new AlSymMat(*aBetterMat);
+
+    clock_t starttime = clock();
+
+    // declare transition matrix + vector to store eigenvalues
+    AlMat z(m_aNDoF,m_aNDoF);
+    AlVec w(m_aNDoF); // vector to store the eigenvalues
+    ATH_MSG_DEBUG("MatrixTool::after z/w allocation");
+
+    char jobz = 'V';
+    int info = (*aBetterMat).diagonalize(jobz,w,z);
+    ATH_MSG_DEBUG(" info: " << info);
+    ATH_MSG_INFO("MatrixTool::after diagonalization");
+
+    // stop time calculation
+    clock_t stoptime = clock();
+    double time_diag = (stoptime-starttime)/double(CLOCKS_PER_SEC);
+    ATH_MSG_INFO(" - time spent diagonalizing the matrix: "<<time_diag<<" s");
+
+    double time_solve = 0.;
+    if (info==0) {
+      starttime = clock();
+      postSolvingLapack(aBetterVec,d2Chi2,w,z,m_aNDoF);
+      stoptime = clock();
+      time_solve = (stoptime-starttime)/double(CLOCKS_PER_SEC);
+      ATH_MSG_INFO(" - time spent solving the system: "<<time_solve<<" s");
+      if(m_logStream) {
+        *m_logStream<<"time spent for diagonalization: "<<time_diag<<" s"<<std::endl;
+        *m_logStream<<"time spent for post-solving: "<<time_solve<<" s"<<std::endl;
+      }
+    }
+    else {
+      ATH_MSG_ERROR("Problem in diagonalization. Solving skipped.");
+      if(m_logStream)
+        *m_logStream<<"time spent for diagonalization: "<<time_diag<<" s"<<std::endl;
+    }
+
+    if(m_logStream) {
+      *m_logStream<<"total time spent in solve: "<<time_diag+time_solve<<" s"<<std::endl;
+      *m_logStream<<std::endl;
+    }
+
+    delete d2Chi2;
+    delete aBetterMat;
+    delete aBetterVec;
+
+    // need to do this since success return value from Lapack is 0
+    // and from solveLapack() it is 1
+    if (info==0)
+      info = 1;
+
+    return info;
+  }
+
+  //________________________________________________________________________
+  StatusCode MatrixTool::spuriousRemoval()
+  {
+
+    // copied from SiGlobalChi2Algs
+    ATH_MSG_DEBUG("in spuriousRemoval");
+
+    // compute determinant before resizing
+    if (m_calDet) {
+      const double tol = 1.e-20;
+      double determ = m_bigmatrix->determinant();
+      ATH_MSG_INFO("Determinant: " << determ);
+      if (std::fabs(determ) < tol)
+        ATH_MSG_WARNING("Matrix is singular!");
+    }
+
+    // fill vector with modules that need to be removed
+    int fillvecmods=fillVecMods();
+    if (fillvecmods==0) {
+
+      //ATH_MSG_INFO(" No resize needed (NhitsCut = "
+      //     << m_hitscut << ")");
+
+      if (msgLvl(MSG::DEBUG)) {
+        //m_bigmatrix->Write("bigmatrix.txt", false, m_wSqMatrix, m_scale,
+        //           MatVersion);
+        //m_bigvector->Write("bigvector.txt", false, m_scale, m_modcodemap,
+        //           VecVersion, m_alignProcessLevel, m_fitParam);
+      }
+
+      return StatusCode::SUCCESS;
+    }
+    else if (fillvecmods==2)
+      return StatusCode::FAILURE;
+
+    /* this is a bit difficult to implement for now....
+
+    // remove matrix/vector elements
+    int cont=0;
+    ModuleIndexMap::iterator itcode;
+    ATH_MSG_INFO("Eliminating module...");
+
+
+
+    for (std::vector<int>::const_iterator it=m_dropmods.begin();
+    it!= m_dropmods.end(); ++it) {
+
+    itcode = m_modcodemap.find((*it));
+
+    if (itcode == m_modcodemap.end()) {
+    ATH_MSG_WARNING("Could not find module " << *it << " in map.");
+    return StatusCode::FAILURE;
+    }
+
+    ATH_MSG_INFO(" - Removing mcode: " << (itcode->second)
+    << " (old index: " << (*it) << " -> new index: " << (*it)-cont << ")");
+
+    m_bigmatrix->RemoveModule((*it)-cont);
+    m_bigvector->RemoveModule((*it)-cont);
+    cont++;
+    }
+    ATH_MSG_INFO("Modules removed from the Matrix and from the Vector Successfully!");
+    ATH_MSG_DEBUG("(DoF: " << nDoF << ")");
+
+    // resizing...
+    ATH_MSG_INFO("Resizing the bigvector in memory...");
+    m_bigvector->reSize(nDoF-6*m_dropmods.size());
+    ATH_MSG_INFO("Resizing the bigmatrix in memory...");
+    m_bigmatrix->reSize(nDoF-6*m_dropmods.size());
+
+    ATH_MSG_INFO(m_dropmods.size() << " modules eliminated from the matrix, i.e, "
+    << 6*m_dropmods.size() << " DoFs");
+    ATH_MSG_INFO(nDoF/6 - m_dropmods.size() << " modules to align (" << nDoF-6*m_dropmods.size() << " DoFs)");
+    ATH_MSG_INFO("New bigmatrix size is: " << m_bigmatrix->size());
+    ATH_MSG_INFO("New bigvector size is: " << (*m_bigvector).size());
+
+    NDoF = nDoF-6*(m_dropmods.size());
+
+    // resize (update) nDoF variable
+    nDoF = NDoF;
+
+    // Resizing vectors to store results
+    m_alignPar->reSize(nDoF);
+    m_alignSqErr->reSize(nDoF);
+
+    // Fill the mapping module map and updating m_modcodemap
+    UpdateModMap();
+    */
+
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  void MatrixTool::postSolvingLapack(AlVec * dChi2, AlSymMat * d2Chi2, AlVec &w, AlMat &z, int size)
+  {
+    ATH_MSG_DEBUG("in postSolvinglapack()");
+
+    if( z.ncol() != size) {
+      msg(MSG::ERROR)<<"Eigenvector matrix has incorrect size : "<<z.ncol()<<" != "<<size<<endreq;
+      return;
+    }
+
+    if( (int)m_activeIndices.size() != size) {
+      msg(MSG::ERROR)<<"Number of active parameters is incorrect : "<<m_activeIndices.size()<<" != "<<size<<endreq;
+      return;
+    }
+
+    // Compute bigvector in diagonal basis (Vb = Ut * bigvector)
+    AlVec D(size);
+    D = z*(*dChi2);
+
+    if (m_writeEigenMat) {
+
+      ATH_MSG_INFO("writing the eigenvectors in a matrix: "<< z.nrow() << "x" << z.ncol());
+
+      // Set Path for the z matrix (eigenvector matrix)
+      z.SetPathBin(m_pathbin+m_prefixName);
+      z.SetPathTxt(m_pathtxt+m_prefixName);
+
+      ATH_MSG_INFO("writing the eigenvector matrix: "<< m_scalaMatName);
+      ATH_MSG_DEBUG("matrix will be in: "<< m_pathbin+m_prefixName+m_scalaMatName);
+
+      StatusCode sc = z.Write("eigenvectors.bin",true); // write the eigenvector matrix
+
+      if (sc!=StatusCode::SUCCESS)
+        msg(MSG::ERROR)<<"Problem writing eigenvector matrix"<<endreq;
+
+      // Set Path for the w matrix (eigenvalues matrix - diagonal bigmatrix)
+      w.SetPathBin(m_pathbin+m_prefixName);
+      w.SetPathTxt(m_pathtxt+m_prefixName);
+
+      ATH_MSG_INFO("writing the eigenvectors in a vector: "<< w.size());
+      ATH_MSG_INFO("writing the eigenvalues vector (diagonal bigmatrix): "<< m_scalaVecName);
+      ATH_MSG_DEBUG("vector will be in: "<< m_pathbin+m_prefixName+m_scalaVecName);
+
+      sc = w.WriteEigenvalueVec("eigenvalues.bin",true); // write the eigenvalues vecor
+
+      if (sc!=StatusCode::SUCCESS)
+        msg(MSG::ERROR)<<"Problem writing eigenvector matrix"<<endreq;
+
+      if (m_writeEigenMatTxt) {
+        sc = z.Write("eigenvectors.txt", false);
+        if (sc!=StatusCode::SUCCESS)
+          msg(MSG::ERROR)<<"Problem writing eigenvector matrix to text file"<<endreq;
+        sc = w.WriteEigenvalueVec("eigenvalues.txt", false);
+        if (sc!=StatusCode::SUCCESS)
+          msg(MSG::ERROR)<<"Problem writing eigenvalue vector to text file"<<endreq;
+      }
+
+    }
+
+    // Set eigenvalue thresholds
+    const double eigenvalue_threshold = 1e-19;
+
+    // weak mode removal
+    if (m_modcut == -1) {
+
+      ATH_MSG_INFO(" Starting the automatic Weak Mode Removal method");
+
+      // create a pull vector for the alignment corrections in diagonal basis (db_pulls)
+      //int nDoF=m_alignModuleTool->nAlignParameters();
+      AlVec* m_Align_db = new AlVec(size);
+      AlVec* m_Align_error_db = new AlVec(size);
+      AlVec* m_AlignPull = new AlVec(size);
+      ATH_MSG_DEBUG("AlignPull vector size is: "<< (*m_AlignPull).size());
+
+      m_modcut = 0;
+      bool wm_stop = false;
+
+      // -----------------------------------------------------------------------
+      // First pass: removing weak modes because of large pull
+      // compute alignment pulls for corrections in diagonal basis (db)
+      for(int i=0; i<size; i++) {
+
+        (*m_Align_db)[i] = (-D[i]/w[i]);
+        (*m_Align_error_db)[i] = sqrt(1.0/w[i]/m_scale);
+
+        if (w[i]<eigenvalue_threshold) {
+          ATH_MSG_INFO("  + EigenMode " << i
+                         << " removed as eigenvalue lower than the threshold " << eigenvalue_threshold
+                         << ": " << w[i]);
+          (*m_AlignPull)[i] = 0.0;
+          m_modcut++;
+        }
+        else
+          (*m_AlignPull)[i] = (*m_Align_db)[i] / (*m_Align_error_db)[i];
+
+        ATH_MSG_DEBUG(i << ". AlignPar: " << (*m_Align_db)[i] << " +- " << (*m_Align_error_db)[i]
+                        << " (pull: " << (*m_AlignPull)[i]  << ") ; w[i]: " << w[i]);
+      }
+      ATH_MSG_INFO(" +++ Weak Mode removal ++ stop after mode "<< m_modcut << " (First pass)");
+      // -----------------------------------------------------------------------
+
+      // -----------------------------------------------------------------------
+      // Second pass
+      // if the error is greater than the correction -> cut this mode
+      for(int i=m_modcut; (i<size && !wm_stop); i++) {
+
+        // if the error is greater than the correction -> cut this mode
+        if (fabs((*m_AlignPull)[i])<m_pullcut) {
+          ATH_MSG_INFO("  + EigenMode " << i
+                         << " removed as pull is lower than " << m_pullcut << ": "
+                         << (*m_AlignPull)[i]);
+          m_modcut++;
+        }
+        else
+          wm_stop = true;
+
+      }
+      ATH_MSG_INFO(" +++ Weak Mode removal ++ stop after mode "<< m_modcut << " (Second pass)");
+      // -----------------------------------------------------------------------
+
+      wm_stop = false;
+
+      // ----------------------------------------------------------------------
+      // Third pass
+      // Check if the next eigenvalues is far away. If it is two orders of
+      // magnitude bigger remove also this mode and allow the search
+      for(int i=m_modcut; (i<size && !wm_stop); i++) {
+
+        // if the next eigenvalues is far away -> cut this mode
+        if (m_eigenvalueStep*w[i]<w[i+1]) {
+          ATH_MSG_INFO("  + EigenMode " << i
+                         << " removed as diff between eigenvalues, " << w[i] << " and " << w[i+1]
+                         << ", is greater than " << m_eigenvalueStep);
+          m_modcut++;
+        }
+        else
+          wm_stop = true;
+
+      }
+      ATH_MSG_INFO(" +++ Weak Mode removal ++ stop after mode "<< m_modcut << " (Third pass)");
+      // -----------------------------------------------------------------------
+
+      wm_stop = false;
+
+      // -----------------------------------------------------------------------
+      // Fourth pass
+      // Check if the next eigenvalues is far away. If it is two orders of
+      // magnitude bigger remove also this mode and allow the search
+      for(int i=m_modcut; (i<size && !wm_stop); i++) {
+
+        // if the next eigenvalues is far away -> cut this mode
+        if ( fabs((*m_Align_db)[i]) > m_Align_db_step*fabs((*m_Align_db)[i+1]) ) {
+          ATH_MSG_INFO("  + EigenMode " << i
+                         << " removed as diff between corrections, " << w[i] << " and " << w[i+1]
+                         << ", is greater than "
+                         << m_Align_db_step);
+          m_modcut++;
+        }
+        else
+          wm_stop = true;
+
+      }
+      ATH_MSG_INFO(" +++ Weak Mode removal ++ stop after mode "<< m_modcut << " (Fourth pass)");
+      // -----------------------------------------------------------------------------------------------------
+
+      // Free memory and clear the pointer to
+      // prevent using invalid memory reference
+      delete m_Align_db;
+      delete m_Align_error_db;
+      delete m_AlignPull;
+      m_Align_db = 0;
+      m_Align_error_db = 0;
+      m_AlignPull = 0;
+
+    } // end of if(m_modcut == -1)
+
+    // Save some stuff to debug purposes
+    /*
+      if (m_storeDia) {
+      std::string path = m_pathtxt+m_prefixName+"align_dia";
+      std::fstream orthogon(path.c_str(), std::ios::out);
+      orthogon.setf(std::ios::fixed);
+      orthogon.setf(std::ios::showpoint);
+      orthogon.precision(6);
+
+      orthogon << std::setw(10)
+      << "--------------------------------------------------------------------------------"
+      << std::endl;
+      orthogon << std::setw(10) << " ModeCut = " << m_modcut << std::endl;
+      orthogon << std::setw(10)
+      << "--------------------------------------------------------------------------------"
+      << std::endl;
+
+      orthogon << std::setw(10) << "mode"
+      << std::setw(20) << "eigenmode"
+      << std::setw(20) << "eigenmode error"
+      << std::setw(25) << "eigenvalue"
+      << std::endl;
+
+      for( int m=0; m<size; m++) {
+
+      // mode
+      orthogon << std::setw(10) << m;
+
+      // eigenmode (db)
+      if( w[m]>1.0e-15) orthogon << std::setw(20) << -D[m]/w[m];
+      else orthogon << std::setw(20) << 0.0;
+
+      // error eigenmode (error_db)
+      if( w[m]>1.0e-15) orthogon << std::setw(20) << sqrt(1.0/w[m]/m_scale);
+      else orthogon << std::setw(20) << 0.0;
+
+      // eigenvalues
+      orthogon << std::setw(25) << w[m] << std::endl;
+      }
+      orthogon.close();
+      } // end store align_dia.txt
+    */
+
+    AlVec delta(size);
+    AlVec deltafull(size);
+    AlVec errSq(size);
+
+    // full covariance matrix
+    CLHEP::HepSymMatrix * cov = 0;
+    if(m_calculateFullCovariance)
+      // Warning ! The matrix can be huge!
+      // This can lead to memory problems
+      cov = new CLHEP::HepSymMatrix(size,0);
+
+    if(m_logStream)
+      *m_logStream<<"/------ The Eigenvalue Spectrum -------"<<std::endl;
+
+    for (int i=0;i<size;i++) {
+      AlVec thisdelta(size);
+      for(int j=0;j<size;j++)
+        thisdelta[j] = z[i][j] * (-D[i]/w[i]);
+      deltafull += thisdelta;
+
+      ATH_MSG_DEBUG("eigenvalue "<<w[i]);
+      if( i<m_modcut ) {
+        ATH_MSG_INFO("skipping eigenvalue "<<w[i]<<" , modcut is "<<m_modcut);
+        if(m_logStream)
+           *m_logStream<<"| skipping eigenvalue "<<w[i]<<std::endl;
+      }
+      else if( w[i] < m_eigenvaluethreshold ) {
+        ATH_MSG_INFO("skipping eigenvalue "<<w[i]<<" , cut is "<<m_eigenvaluethreshold);
+        if(m_logStream)
+           *m_logStream<<"| skipping eigenvalue "<<w[i]<<std::endl;
+      }
+      else {
+        if(m_logStream)
+          *m_logStream<<"| "<<w[i]<<std::endl;
+
+        delta += thisdelta;
+        for(int j=0;j<size;j++) {
+          errSq[j] += z[i][j] * z[i][j] / w[i];
+          if(m_calculateFullCovariance) {
+            for(int k=0;k<=j;k++)
+              (*cov)[j][k] += z[i][j] * z[i][k] / w[i];
+          }
+        }
+      }
+    }
+
+    if(m_logStream)
+      *m_logStream<<"\\----- End of Eigenvalue Spectrum -----"<<std::endl;
+
+    ATH_MSG_DEBUG("Alignment constants:");
+
+    DataVector<AlignPar> * alignParList = m_alignModuleTool->alignParList1D();
+
+    // compute alignment corrections (translations in mm and rotations in rad) and their variances
+    for(int i=0; i<size; i++) {
+
+      double param = delta[i];
+      double err = sqrt(2.*std::fabs(errSq[i]));
+
+      int idof = m_activeIndices[i];
+      AlignPar * alignPar=(*alignParList)[idof];
+
+      // undo the sigma scaling
+      double sigma = alignPar->sigma();
+
+      param *= sigma;
+      err *= sigma;
+
+      // undo normalization scaling of error
+      if(m_scaleMatrix && m_scale>0.)
+        err /= sqrt(m_scale);
+
+      ATH_MSG_DEBUG(i <<" : "<< param << " +/- "<< err);
+      ATH_MSG_DEBUG("cov("<<i<<")="<<errSq[i]<<", sigma: "<<sigma);
+      ATH_MSG_DEBUG("init par: "<<alignPar->initPar());
+      alignPar->setPar(param, err);
+      ATH_MSG_DEBUG("set param to "<<param<<" for alignPar "<<alignPar);
+      ATH_MSG_DEBUG(*(*alignParList)[idof]);
+    }
+
+    if(m_logStream) {
+      printGlobalSolution(*m_logStream, cov);
+
+      // norm of first derivative
+      double norm1st = dChi2->norm();
+      if(m_scaleMatrix && m_scale>0.) // undo normalization scaling
+        norm1st *= m_scale;
+      *m_logStream<<"norm of first derivative :            "<<norm1st<<std::endl;
+
+      if(d2Chi2) {
+        // distance to solution
+        double dist = ( (*d2Chi2) * deltafull + (*dChi2) ).norm();
+        if(m_scaleMatrix && m_scale>0.) // undo normalization scaling
+          dist *= m_scale;
+        *m_logStream<<"distance to solution :                "<<dist<<std::endl;
+
+        // calculate chi2 of the alignment change
+        double chi2 = delta * (*d2Chi2) * delta * .5;
+        if(m_scaleMatrix && m_scale>0.) // undo normalization scaling
+          chi2 *= m_scale;
+        *m_logStream<<"delta(chi2) of the alignment change : "<<chi2<<" / "<<size<<std::endl;
+      }
+    }
+
+    delete cov;
+  }
+
+  //________________________________________________________________________
+  int MatrixTool::solve***REMOVED***()
+  {
+    ATH_MSG_INFO("solving Global using ***REMOVED***");
+    if(m_logStream) {
+      *m_logStream<<"*************************************************************"<<std::endl;
+      *m_logStream<<"**************  solving using Global method  ****************"<<std::endl;
+      *m_logStream<<"**************          using ***REMOVED***           ****************"<<std::endl;
+      *m_logStream<<"*************************************************************"<<std::endl;
+    }
+
+    // start measuring time
+    clock_t starttime = clock();
+
+    DataVector<AlignPar> * alignParList = m_alignModuleTool->alignParList1D();
+
+    AlSpaMat * ABetterMat = 0;
+    bool isCopy = false;
+    if ( dynamic_cast<AlSymMat*>(m_bigmatrix) ) {
+      ATH_MSG_INFO("Converting Matrix Format for fast solving");
+      ABetterMat = new AlSpaMat(*(dynamic_cast<AlSymMat*>(m_bigmatrix)));
+      isCopy = true;
+    }
+    else if ( dynamic_cast<AlSpaMat*>(m_bigmatrix) ) {
+      ATH_MSG_INFO("Matrix format native to the fast solving");
+      ABetterMat = (dynamic_cast<AlSpaMat*>(m_bigmatrix));
+    }
+    else {
+      ATH_MSG_ERROR("Cannot cast to neither AlSymMat nor AlSpaMat");
+      return 0;
+    }
+
+    ATH_MSG_DEBUG("checking active indices");
+
+    // use const matrix when checking for non-zero elements to avoid
+    // filling of the whole matrix
+    const AlSpaMat * chkMatrix = ABetterMat;
+
+    AlSpaMat * aBetterMat = new AlSpaMat(m_aNDoF);
+    AlVec    * aBetterVec = new AlVec(m_aNDoF);
+
+      
+    for (int iActive=0;iActive<m_aNDoF;iActive++) {
+      int i = m_activeIndices[iActive];
+      (*aBetterVec)[iActive] = (*m_bigvector)[i];
+      for (int jActive=0;jActive<m_aNDoF;jActive++) {
+        int j = m_activeIndices[jActive];
+        // only fill if non-zero !!!
+        if ( (*chkMatrix)[iActive][jActive] != 0. )
+          (*aBetterMat)[iActive][jActive]=(*ABetterMat)[i][j];
+      }
+    }
+
+    // store original vector for cross-checks
+    AlVec origVec(*aBetterVec);
+
+    ATH_MSG_DEBUG("running the solving");
+
+    // solve
+    int info = (*aBetterMat).***REMOVED***Solve(*aBetterVec);
+
+    if(info == 0) {
+      ATH_MSG_INFO("***REMOVED*** solving OK");
+      if(m_logStream)
+        *m_logStream<<"***REMOVED*** solving OK."<<std::endl;
+    }
+    else {
+      msg(MSG::ERROR)<<"***REMOVED*** error code (0 if OK) = "<<info<<endreq;
+      if(m_logStream)
+        *m_logStream<<"***REMOVED*** error code (0 if OK) = "<<info<<std::endl;
+    }
+
+    if( isCopy )
+      delete ABetterMat;
+    ABetterMat = 0;
+
+    // stop measuring time
+    clock_t stoptime = clock();
+    double totaltime = (stoptime-starttime)/double(CLOCKS_PER_SEC);
+    ATH_MSG_INFO("Time spent in solve***REMOVED***: "<<totaltime<<" s");
+
+    ATH_MSG_DEBUG("Alignment constants:");
+    // compute alignment corrections (translations in mm and rotations in rad)
+    // for ***REMOVED*** variances are not calculated
+    for(int i=0; i<m_aNDoF; i++) {
+
+      double param = -(*aBetterVec)[i];
+      double err = 0.;
+
+      int idof = m_activeIndices[i];
+      AlignPar * alignPar=(*alignParList)[idof];
+
+      // undo the sigma scaling
+      double sigma = alignPar->sigma();
+      param *= sigma;
+
+      ATH_MSG_DEBUG(i <<" : "<< param << " +/- "<< err);
+      ATH_MSG_DEBUG("sigma: "<<sigma);
+      ATH_MSG_DEBUG("init par: "<<alignPar->initPar());
+      alignPar->setPar(param, err);
+      ATH_MSG_DEBUG("set param to "<<param<<" for alignPar "<<alignPar);
+      ATH_MSG_DEBUG(*(*alignParList)[idof]);
+    }
+
+    if(m_logStream) {
+      CLHEP::HepSymMatrix * cov = 0;
+      printGlobalSolution(*m_logStream, cov);
+
+      // norm of first derivative
+      *m_logStream<<"norm of first derivative :            "<<origVec.norm()<<std::endl;
+
+      // distance to solution
+      double dist = ( (*aBetterMat) * (*aBetterVec) - origVec ).norm();
+      *m_logStream<<"distance to solution :                "<<dist<<std::endl;
+
+      // calculate chi2 of the alignment change
+      double chi2 = (*aBetterVec) * (*aBetterMat) * (*aBetterVec) * .5;
+      *m_logStream<<"delta(chi2) of the alignment change : "<<chi2<<" / "<<m_aNDoF<<std::endl;
+
+      // time spent here
+      *m_logStream<<"time spent in solve :                 "<<totaltime<<" s"<<std::endl;
+    }
+
+    delete aBetterMat;
+    delete aBetterVec;
+
+    // need to do this since success return value from Lapack is 0
+    // and from solve***REMOVED***() it is 1
+    if (info==0)
+      info = 1;
+
+    return info;
+  }
+
+  //________________________________________________________________________
+  void MatrixTool::writeHitmap()
+  {
+    ATH_MSG_INFO("writing the hitmap to file");
+
+    const AlignModuleList * moduleList = m_alignModuleTool->alignModules1D();
+    int nModules = moduleList->size();
+
+    AlMat hitmap(nModules,2);
+    AlignModuleList::const_iterator imod     = moduleList->begin();
+    AlignModuleList::const_iterator imod_end = moduleList->end();
+    int index(0);
+    for(; imod != imod_end; ++imod) {
+      AlignModule * module = *imod;
+      hitmap[index][0] = module->nHits();
+      hitmap[index][1] = module->nTracks();
+      index++;
+    }
+
+    // Set Path for the hitmap matrix
+    hitmap.SetPathBin(m_pathbin+m_prefixName);
+    hitmap.SetPathTxt(m_pathtxt+m_prefixName);
+
+    StatusCode sc = hitmap.Write("hitmap.bin",true); // write the hitmap matrix
+
+    if (sc!=StatusCode::SUCCESS)
+      ATH_MSG_ERROR("Problem writing hitmap matrix");
+
+    if (m_writeHitmapTxt) {
+      sc = hitmap.Write("hitmap.txt", false, 0);
+      if (sc!=StatusCode::SUCCESS)
+        ATH_MSG_ERROR("Problem writing hitmap matrix to text file");
+    }
+
+    ATH_MSG_DEBUG("hitmap written to: "<< m_pathbin+m_prefixName <<"hitmap.bin (.txt)");
+  }
+
+  //________________________________________________________________________
+  void MatrixTool::readHitmaps()
+  {
+    ATH_MSG_INFO("read hitmaps from files");
+
+    const AlignModuleList * moduleList = m_alignModuleTool->alignModules1D();
+    int nModules = moduleList->size();
+
+    AlMat hitmap(nModules,2);
+    int nFiles = (int)m_inputHitmapFiles.size();
+    for(int imap=0;imap<nFiles; imap++) {
+      AlMat nextmap(nModules,2);
+
+      ATH_MSG_INFO("Reading hitmap "<<imap<<" from file "<<m_inputHitmapFiles[imap]);
+
+      if(nextmap.ReadScalaPack(m_inputHitmapFiles[imap]).isFailure()) {
+        ATH_MSG_WARNING("Problem reading hitmap from \'"<<m_inputHitmapFiles[imap]<<"\'. Skipping.");
+        continue;
+      }
+
+      if(nextmap.nrow()!=nModules || nextmap.ncol()!=2) {
+        ATH_MSG_WARNING("Matrix in file \'"<<m_inputHitmapFiles[imap]<<"\' has wrong size ("
+            <<nextmap.nrow()<<" x "<<nextmap.ncol()<<"), should be ("<<nModules<<" x 2). Skipping.");
+        continue;
+      }
+
+      hitmap += nextmap;
+    }
+
+    AlignModuleList::const_iterator imod     = moduleList->begin();
+    AlignModuleList::const_iterator imod_end = moduleList->end();
+    int index = 0;
+    int totalhits = 0;
+    for(; imod != imod_end; ++imod) {
+      AlignModule * module = *imod;
+      //if ((int)hitmap[index][0]!=(int)module->identify().get_identifier32().get_compact()) ATH_MSG_ERROR("bad module identifier");
+      //module->setIdentifier((Identifier)hitmap[index][0]);
+      module->setNHits((int)hitmap[index][0]);
+      module->setNTracks((int)hitmap[index][1]);
+      totalhits += (int)hitmap[index][0];
+      index++;
+    }
+
+    m_nHits = totalhits;
+    m_nTracks = 0;
+    m_nMeasurements = 0;
+
+    ATH_MSG_INFO("Hitmap accumulated from "<<nFiles<<" files with total of "<<totalhits<<" hits.");
+  }
+
+} // end of namespace
+
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/ShiftingDerivCalcTool.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/ShiftingDerivCalcTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2025a0bab46039368bab5707dea28c2543a75992
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/ShiftingDerivCalcTool.cxx
@@ -0,0 +1,989 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "StoreGate/StoreGateSvc.h"
+
+#include "TrkTrack/Track.h"
+#include "TrkMeasurementBase/MeasurementBase.h"
+#include "TrkParameters/TrackParameters.h"
+#include "TrkRIO_OnTrack/RIO_OnTrack.h"
+#include "TrkCompetingRIOsOnTrack/CompetingRIOsOnTrack.h"
+#include "TrkMaterialOnTrack/MaterialEffectsOnTrack.h"
+#include "TrkFitterUtils/FitterTypes.h"
+#include "TrkEventPrimitives/TrackStateDefs.h"
+
+#include "TrkFitterInterfaces/IGlobalTrackFitter.h"
+#include "TrkAlignInterfaces/IAlignResidualCalculator.h"
+#include "TrkAlignInterfaces/IAlignModuleTool.h"
+
+#include "TrkAlignEvent/AlignTSOS.h"
+#include "TrkAlignEvent/AlignModule.h"
+#include "TrkAlignEvent/AlignTrack.h"
+#include "TrkAlignEvent/AlignPar.h"
+#include "TrkAlignEvent/AlignModuleList.h"
+
+#include "TrkAlignGenTools/ShiftingDerivCalcTool.h"
+#include "TrkAlignGenTools/AlignTrackCreator.h"
+
+#include "EventInfo/EventInfo.h"
+#include "EventInfo/EventID.h"
+
+#include "TGraph.h"
+#include "TF1.h"
+#include "TCanvas.h"
+#include "TPaveText.h"
+#include "TAxis.h"
+
+using namespace std;
+
+namespace Trk {
+  
+  //________________________________________________________________________
+  ShiftingDerivCalcTool::ShiftingDerivCalcTool(const std::string& type, 
+                                               const std::string& name,
+                                               const IInterface* parent)
+    
+    : AthAlgTool(type,name,parent)
+    , m_trackFitterTool("Trk::GlobalChi2Fitter/MCTBFitter")
+    , m_SLTrackFitterTool("Trk::GlobalChi2Fitter/MCTBSLFitter")
+    , m_residualCalculator("Trk::AlignResidualCalculator/ResidualCalculator")
+    , m_alignModuleTool("Trk::AlignModuleTool/AlignModuleTool")
+    , m_traSize(.1)
+    , m_rotSize(.1)
+    , m_runOutlierRemoval(false)
+    , m_particleHypothesis(Trk::muon)
+    , m_particleNumber(2)
+    , m_nIterations(0)
+    , m_unshiftedResiduals(0)
+    , m_unshiftedResErrors(0)
+    , m_tmpChi2VAlignParam(0)
+    , m_tmpChi2VAlignParamX(0)
+    , m_tmpChi2VAlignParamMeasType(0)
+    , m_unshiftedTrackChi2MeasType(new double  [TrackState::NumberOfMeasurementTypes])
+    , m_ntracksProcessed(0)
+    , m_ntracksPassInitScan(0)
+    , m_ntracksPassSetUnshiftedRes(0)
+    , m_ntracksPassDerivatives(0)
+    , m_ntracksPassGetDeriv(0)
+    , m_ntracksPassGetDerivSecPass(0)
+    , m_ntracksPassGetDerivLastPass(0)
+    , m_ntracksFailMaxIter(0)
+    , m_ntracksFailTrackRefit(0)
+    , m_ntracksFailAlignParamCut(0)
+    , m_ntracksFailFinalAttempt(0)
+  {
+    declareInterface<IDerivCalcTool>(this);
+
+    declareProperty("TrackFitterTool",               m_trackFitterTool);
+    declareProperty("SLTrackFitterTool",             m_SLTrackFitterTool);
+    declareProperty("TranslationSize",               m_traSize);
+    declareProperty("RotationSize",                  m_rotSize);
+    declareProperty("RunOutlierRemoval",             m_runOutlierRemoval);
+    declareProperty("ParticleNumber",                m_particleNumber);
+    declareProperty("doChi2VChamberShiftsMeasType",  m_doChi2VAlignParamMeasType = false);
+    declareProperty("doResidualFits",                m_doFits = true);
+    declareProperty("NumberOfShifts",                m_nFits=5);
+    declareProperty("ResidualCalculator",            m_residualCalculator);
+    declareProperty("AlignModuleTool",               m_alignModuleTool);
+    declareProperty("doResidualPlots",               m_doResidualPlots=false);
+    declareProperty("TrackAlignParamCut",            m_trackAlignParamCut=1e6);//.001
+    declareProperty("SetMinIterations",              m_setMinIterations=false);
+    declareProperty("MaxIterations",                 m_maxIter=50);
+    declareProperty("MinIterations",                 m_minIter=10);
+
+    declareProperty("RemoveScatteringBeforeRefit",   m_removeScatteringBeforeRefit=false);
+
+    m_logStream = 0;
+
+  }
+
+  //________________________________________________________________________
+  ShiftingDerivCalcTool::~ShiftingDerivCalcTool() 
+  {
+    deleteChi2VAlignParam();
+    delete [] m_unshiftedTrackChi2MeasType;
+  }
+  
+  //________________________________________________________________________
+  StatusCode ShiftingDerivCalcTool::initialize()
+  {
+     
+    msg(MSG::DEBUG)  << "in ShiftingDerivCalcTool initialize()"<<endreq;
+
+    if (m_trackFitterTool.retrieve().isSuccess()) {
+      msg(MSG::INFO) << "Retrieved " << m_trackFitterTool << endreq;  
+    }
+    else{
+      msg(MSG::FATAL) << "Could not get " << m_trackFitterTool << endreq; 
+      return StatusCode::FAILURE;
+    }
+
+    if (m_SLTrackFitterTool.retrieve().isSuccess()) {
+      msg(MSG::INFO) << "Retrieved " << m_SLTrackFitterTool << endreq;  
+    }
+    else{
+      msg(MSG::FATAL) << "Could not get " << m_SLTrackFitterTool << endreq; 
+      return StatusCode::FAILURE;
+    }
+    
+    if (m_residualCalculator.retrieve().isSuccess())
+      msg(MSG::INFO) << "Retrieved " << m_residualCalculator << endreq;  
+    else{
+      msg(MSG::FATAL) << "Could not get " << m_residualCalculator << endreq; 
+      return StatusCode::FAILURE;
+    }
+        
+    if (m_alignModuleTool.retrieve().isSuccess())
+      msg(MSG::INFO) << "Retrieved " << m_alignModuleTool << endreq;  
+    else{
+      msg(MSG::FATAL) << "Could not get " << m_alignModuleTool << endreq; 
+      return StatusCode::FAILURE;
+    }
+    
+    ParticleSwitcher particleSwitch;
+    m_particleHypothesis = particleSwitch.particle[m_particleNumber];
+    msg(MSG::INFO) << "ParticleNumber: "     << m_particleNumber     << endreq;
+    msg(MSG::INFO) << "ParticleHypothesis: " << m_particleHypothesis << endreq;
+  
+   
+    if(!m_doFits){
+      m_nFits = 2;
+    }
+   
+    m_nChamberShifts = m_nFits;
+    m_traSize = 5.*m_traSize/(double)m_nFits;
+    m_rotSize = 5.*m_rotSize/(double)m_nFits;
+
+    msg(MSG::INFO) << "doFits: "   << m_doFits  << endreq;
+    msg(MSG::INFO) << "nFits:  "   << m_nFits  << endreq;
+
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  StatusCode ShiftingDerivCalcTool::finalize()
+  {
+    ATH_MSG_INFO("number tracks processed:                           "<<m_ntracksProcessed<<endreq<<
+     "number tracks passing initial scan:                "<<m_ntracksPassInitScan<<endreq<<
+     "number tracks passing setting unshifted residuals: "<< m_ntracksPassSetUnshiftedRes<<endreq<<
+     "number tracks pass getting derivatives (1st pass): "<<m_ntracksPassGetDeriv<<endreq<<
+     "number tracks pass getting derivatives (2nd pass): "<<m_ntracksPassGetDerivSecPass<<endreq<<
+     "number tracks pass getting derivatives (3rd pass): "<<m_ntracksPassGetDerivLastPass<<endreq<<
+     "number tracks pass setting derivatives:            "<<m_ntracksPassDerivatives);
+    ATH_MSG_INFO("number tracks fail max iterations:                 "<<m_ntracksFailMaxIter<<endreq<<
+     "number tracks fail track refit:                    "<<m_ntracksFailTrackRefit<<endreq<<
+     "number tracks fail align param cut:                "<<m_ntracksFailAlignParamCut<<endreq<<
+     "number tracks fail final attempt:                  "<<m_ntracksFailFinalAttempt);   
+
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  bool ShiftingDerivCalcTool::scanShifts(const AlignTrack* alignTrack, 
+           const std::vector<const AlignModule*>& alignModules)
+  {
+    ATH_MSG_DEBUG("in scanShifts");
+
+    const Trk::Track* trackForRefit = 
+      (m_removeScatteringBeforeRefit) ? alignTrack->trackWithoutScattering():
+      dynamic_cast<const Trk::Track*>(alignTrack);
+        
+    // see whether straight track or not
+    m_fitter = alignTrack->isSLTrack() ? 
+      m_SLTrackFitterTool : m_trackFitterTool;
+    ATH_MSG_DEBUG("refitting unshifted track with "<<m_fitter<<" (isSLTrack="
+      <<alignTrack->isSLTrack()<<")");   
+    
+    ATH_MSG_DEBUG("setting minNIterations to "<<m_nIterations);
+    m_fitter->setMinIterations(m_nIterations);
+
+    // refit track
+    const Track* refittedTrack = m_fitter->fit( *trackForRefit,
+            m_runOutlierRemoval,
+            m_particleHypothesis);  
+    if (!refittedTrack) { 
+      msg(MSG::WARNING)  << "initial track refit failed" << endreq;     
+      return false;
+    } 
+    else 
+      ATH_MSG_DEBUG("initial track refit successful");
+
+    m_nIterations = m_fitter->iterationsOfLastFit();
+    if (m_nIterations>m_maxIter) {
+      ATH_MSG_DEBUG("exceeded maximum number of iterations"); 
+      return false;
+    }
+    ATH_MSG_DEBUG("initial nIterations: "<<m_nIterations);
+
+    // loop over AlignModules
+    int imod(0);
+    for (std::vector<const AlignModule*>::const_iterator moduleIt=alignModules.begin();
+   moduleIt!=alignModules.end(); ++moduleIt,imod++) {
+      
+      // loop over AlignPar
+      int ipar(0);
+      DataVector<AlignPar>* alignPars=m_alignModuleTool->getAlignPars(*moduleIt);
+      for (DataVector<AlignPar>::iterator alignParIt=alignPars->begin();
+     alignParIt!=alignPars->end(); ++alignParIt,ipar++) {
+
+  for (int ishift=0;ishift<2;ishift++) {
+
+    double shiftsize = shiftSize(*alignParIt);
+    if (ishift>0) shiftsize*=-1.;
+    m_alignModuleTool->shiftModule(*moduleIt,alignTrack,(**alignParIt).paramType(),shiftsize);
+    refittedTrack = m_fitter->fit(*trackForRefit,m_runOutlierRemoval,m_particleHypothesis);
+    m_alignModuleTool->restoreModule(*moduleIt);
+    if (!refittedTrack) {
+      msg(MSG::WARNING) << "track refit failed!"<<endreq;
+      m_nIterations=0;
+      return false;
+    }
+
+    int nIter=m_fitter->iterationsOfLastFit();
+    ATH_MSG_DEBUG("nIter: "<<nIter);
+    if (nIter>m_maxIter) {
+      ATH_MSG_DEBUG("exceeded maximum number of iterations"); 
+      m_nIterations=0;
+      return false;
+    }
+
+    if (nIter>m_nIterations) m_nIterations=nIter;
+  }
+      } // loop over AlignPar
+    } // loop over AlignModules
+
+    ATH_MSG_DEBUG("done with scanShifts, m_nIterations="<<m_nIterations);
+    return true;
+  }
+  
+  //________________________________________________________________________
+  bool ShiftingDerivCalcTool::setUnshiftedResiduals(AlignTrack* alignTrack)
+  {
+    
+    // see whether straight track or not
+    m_fitter = alignTrack->isSLTrack() ? 
+      m_SLTrackFitterTool : m_trackFitterTool;
+    ATH_MSG_DEBUG("refitting unshifted track with "<<m_fitter<<" (isSLTrack="
+      <<alignTrack->isSLTrack()<<")");   
+    
+    // refit track
+    ATH_MSG_DEBUG(endreq<<"setting min number iterations to "<<m_nIterations);
+    m_fitter->setMinIterations(m_nIterations);
+
+    const Trk::Track* trackForRefit = 
+      (m_removeScatteringBeforeRefit) ? alignTrack->trackWithoutScattering():
+      dynamic_cast<const Trk::Track*>(alignTrack);
+    if (!trackForRefit) ATH_MSG_ERROR("no track for refit!");
+
+    const Track* refittedTrack = m_fitter->fit( *trackForRefit,
+            m_runOutlierRemoval,
+            m_particleHypothesis);
+    
+    if (!refittedTrack) { 
+      msg(MSG::WARNING)  << "initial track refit failed" << endreq;     
+      return false;
+    } 
+    else 
+      ATH_MSG_DEBUG("initial track refit successful");
+
+    // dump local track chi2 for debugging
+    double localChi2=m_residualCalculator->setResiduals(alignTrack,refittedTrack);
+    msg()<<MSG::DEBUG<<"local Chi2(unshifted) in setChi2VAlignParam="<<localChi2<<endreq;    
+    m_unshiftedTrackChi2 = localChi2;
+    for (int i=0;i<TrackState::NumberOfMeasurementTypes;i++) {
+      ATH_MSG_DEBUG("getting chi2 for measType "<<i);
+      m_unshiftedTrackChi2MeasType[i]=m_residualCalculator->chi2ForMeasType(i);
+    }
+    ATH_MSG_DEBUG("done");
+
+    // create vector containing unshifted residuals and matrices containing errors
+    const int NMEAS=alignTrack->nAlignTSOSMeas();
+
+    // unshiftedResiduals owned by AlignTrack
+    m_unshiftedResiduals=new Amg::VectorX(NMEAS); 
+
+    // unshiftedResErrors owned by ShiftingDerivCalcTool
+    if (m_unshiftedResErrors) delete m_unshiftedResErrors;
+      m_unshiftedResErrors=new Amg::VectorX(NMEAS); 
+
+    // loop over atsos and determine residuals and errors
+    int imeas=0;
+    AlignTSOSCollection::const_iterator atsosItr=alignTrack->firstAtsos();
+    for (; atsosItr != alignTrack->lastAtsos(); ++atsosItr) {
+      if (!(**atsosItr).isValid()) continue;
+      for (std::vector<Residual>::const_iterator itRes=(**atsosItr).firstResidual();
+        itRes!=(**atsosItr).lastResidual();itRes++,imeas++) {
+          double residual = itRes->residual();
+          double errSq    = itRes->errSq();
+          (*m_unshiftedResiduals)[imeas]=residual;
+          (*m_unshiftedResErrors)[imeas]=std::sqrt(errSq);
+          //ATH_MSG_DEBUG("weight: "<<1./errSq<<", unshiftedRes["<<imeas<<"]="
+          //      <<(*m_unshiftedResiduals)[imeas]
+          //      <<", resNorm="<<itRes->residualNorm());       
+      }
+    }
+    if (imeas!=NMEAS) {
+      msg(MSG::ERROR)<<"problem with nmeas, imeas="<<imeas<<", NMEAS="<<NMEAS<<endreq;
+      exit(3);
+    }
+    alignTrack->setResidualVector(m_unshiftedResiduals); 
+
+    delete refittedTrack; refittedTrack=0;
+
+    return true;
+  }
+  
+//________________________________________________________________________
+bool ShiftingDerivCalcTool::setDerivatives(AlignTrack* alignTrack)
+{         
+  ATH_MSG_DEBUG("in ShiftingDerivCalcTool setDerivatives");
+  m_ntracksProcessed++;
+
+  // loop over AlignTSOSCollection, 
+  // find modules that are in the AlignModuleList,
+  std::vector<const AlignModule*> alignModules;    
+  for (AlignTSOSCollection::const_iterator atsosItr=alignTrack->firstAtsos(); 
+      atsosItr != alignTrack->lastAtsos(); ++atsosItr) { 
+
+    ATH_MSG_VERBOSE("getting module");
+    const AlignModule* module=(*atsosItr)->module();
+    if (module)
+      ATH_MSG_VERBOSE("have ATSOS for module "<<module->identify());
+    else 
+      ATH_MSG_VERBOSE("no module!");
+
+    if (!(*atsosItr)->isValid() || !module) continue;      
+    if (find(alignModules.begin(),alignModules.end(),module) == alignModules.end())   
+    alignModules.push_back(module);      
+  }
+    
+  // find perigee of best track fit and use as starting perigee for all fits
+  m_nIterations=m_minIter;
+  if (m_setMinIterations && !scanShifts(alignTrack, alignModules)) {
+    return false;
+  };    
+  
+  m_ntracksPassInitScan++;
+
+  // set unshifted residuals (this is done in AlignTrackDresser but redone here with track refit)    
+  if (!setUnshiftedResiduals(alignTrack)) {
+    ATH_MSG_WARNING("problem with refitting track!");
+    return false;
+  };    
+
+  m_ntracksPassSetUnshiftedRes++;
+
+  // Determine derivatives from shifting these modules
+  std::vector<AlignModuleDerivatives> * derivatives = new std::vector<AlignModuleDerivatives>;
+  std::vector<AlignModuleDerivatives> * derivativeErr = new std::vector<AlignModuleDerivatives>;
+  std::vector<std::pair<const AlignModule*, std::vector<double> > > * actualSecondDerivatives =
+      new std::vector<std::pair<const AlignModule*, std::vector<double> > >;
+  deleteChi2VAlignParam();
+  for (std::vector<const AlignModule*>::const_iterator moduleIt=alignModules.begin();
+    moduleIt!=alignModules.end(); ++moduleIt) {
+    
+    ATH_MSG_DEBUG("finding derivatives for module "<<(**moduleIt).identify());      
+    
+    std::vector<Amg::VectorX> deriv_vec;
+    std::vector<Amg::VectorX> derivErr_vec;
+    std::vector<double> actualsecderiv_vec;
+
+    // get alignPars and create arrays to store chi2 vs. align pars
+    DataVector<AlignPar>* alignPars=m_alignModuleTool->getAlignPars(*moduleIt);
+    const int nAlignPar = alignPars->size();
+    m_tmpChi2VAlignParam  = new double*[nAlignPar];
+    m_tmpChi2VAlignParamX = new double*[nAlignPar];
+    if (m_doChi2VAlignParamMeasType) {
+      m_tmpChi2VAlignParamMeasType = new double**[TrackState::NumberOfMeasurementTypes];
+      for (int i=0;i<TrackState::NumberOfMeasurementTypes;i++)
+        m_tmpChi2VAlignParamMeasType[i] = new double*[nAlignPar];
+    }
+    
+    
+    // get derivatives and arrays of chi2 vs. align params
+    bool resetIPar=false;
+    std::vector<Amg::VectorX> tmpderiv_vec;
+    std::vector<Amg::VectorX> tmpderivErr_vec;
+    std::vector<double> tmpactualsecderiv_vec;
+    m_secPass=false;
+
+    // first attempt with normal number of fitter iterations
+    bool success=getAllDerivatives(alignTrack, *moduleIt,
+           tmpderiv_vec,tmpderivErr_vec,tmpactualsecderiv_vec,
+           resetIPar);
+    if (!success){
+      delete derivatives;
+      delete derivativeErr;
+      delete actualSecondDerivatives;
+      return false;
+    }
+
+    m_ntracksPassGetDeriv++;
+
+    if (resetIPar) {    
+      // second attempt with increased number of fitter iterations
+      m_secPass=true;
+      success=getAllDerivatives(alignTrack,*moduleIt,
+              tmpderiv_vec,tmpderivErr_vec,tmpactualsecderiv_vec,
+              resetIPar); 
+    }
+
+    if (!success){ 
+      delete derivatives;
+      delete derivativeErr;
+      delete actualSecondDerivatives;
+      return false;
+    }
+
+    m_ntracksPassGetDerivSecPass++;
+
+    if (resetIPar) {  
+      // third and last attempt with number of fitter iterations set to maximum
+      m_nIterations=m_maxIter;
+      success=getAllDerivatives(alignTrack,*moduleIt,
+              tmpderiv_vec,tmpderivErr_vec,tmpactualsecderiv_vec,
+              resetIPar); 
+    }
+
+    if (!success){ 
+      delete derivatives;
+      delete derivativeErr;
+      delete actualSecondDerivatives;
+      return false;
+    }
+
+
+    m_ntracksPassGetDerivLastPass++;
+
+    if (success && !resetIPar) {
+      for (int i=0;i<(int)tmpderiv_vec.size();i++) {
+        deriv_vec.push_back(tmpderiv_vec[i]);
+        derivErr_vec.push_back(tmpderivErr_vec[i]);
+        actualsecderiv_vec.push_back(tmpactualsecderiv_vec[i]);
+      }
+    }
+    else{
+      delete derivatives;
+      delete derivativeErr;
+      delete actualSecondDerivatives;
+      return false;
+    }
+    // set the chi2 vs. align param arrays
+    ATH_MSG_DEBUG("setting chi2 vs. align param arrays");
+    m_chi2VAlignParamVec.push_back(m_tmpChi2VAlignParam);
+    m_chi2VAlignParamXVec.push_back(m_tmpChi2VAlignParamX);   
+    (**moduleIt).setChi2VAlignParamArray (m_tmpChi2VAlignParam);
+    (**moduleIt).setChi2VAlignParamXArray(m_tmpChi2VAlignParamX);
+    
+    // arrays for measurement types
+    if (m_doChi2VAlignParamMeasType) {
+      ATH_MSG_DEBUG("pushing back for measType");
+      m_chi2VAlignParamVecMeasType.push_back(m_tmpChi2VAlignParamMeasType);
+      for (int i=0;i<TrackState::NumberOfMeasurementTypes;i++) 
+        (**moduleIt).setChi2VAlignParamArrayMeasType(i,m_tmpChi2VAlignParamMeasType[i]);
+    }
+    ATH_MSG_DEBUG("done setting arrays");
+
+    derivatives->push_back(make_pair(*moduleIt,deriv_vec));      
+    derivativeErr->push_back(make_pair(*moduleIt,derivErr_vec));
+    actualSecondDerivatives->push_back(make_pair(*moduleIt,actualsecderiv_vec));
+  }
+  
+  m_ntracksPassDerivatives++;
+
+  alignTrack->setDerivatives(derivatives);
+  alignTrack->setDerivativeErr(derivativeErr);
+  alignTrack->setActualSecondDerivatives(actualSecondDerivatives);
+
+  // restore unshifted residuals in AlignTSOS
+  setUnshiftedResiduals(alignTrack);
+  ATH_MSG_DEBUG("setting min iterations to 0");
+  m_fitter->setMinIterations(0);
+
+  return true;    
+}
+  
+//________________________________________________________________________
+Amg::VectorX ShiftingDerivCalcTool::getDerivatives(AlignTrack* alignTrack, 
+              int ipar, const AlignPar* alignPar, 
+              Amg::VectorX& derivativeErr,
+              bool& resetIPar,
+              double& actualSecondDeriv)
+{
+  const Trk::Track* trackForRefit = 
+    (m_removeScatteringBeforeRefit) ? alignTrack->trackWithoutScattering():
+    dynamic_cast<const Trk::Track*>(alignTrack);        
+
+  ATH_MSG_DEBUG("m_nIterations: "<<m_nIterations);
+  
+  // gets derivatives of residuals w.r.t. a specific alignment parameter given by alignPar
+  if (!m_fitter) 
+    ATH_MSG_ERROR("set m_fitter before calling getDerivatives (by calling setUnshiftedResiduals)");
+  
+  const AlignModule* module=alignPar->alignModule();    
+  
+  // set derivatives for 2 shifts up and 2 shifts down
+  const int NFITS = m_nFits;
+  const int NMEAS = alignTrack->nAlignTSOSMeas();
+  module->setNChamberShifts(m_nFits);
+  
+  ATH_MSG_DEBUG("NMEAS="<<NMEAS);
+  double** residuals=new double*[NFITS];
+  double** resErrors=new double*[NFITS];
+  double* chi2Array =new double[NFITS];
+  double* chi2ArrayX=new double[NFITS];   
+
+  if (m_doChi2VAlignParamMeasType) {
+    for (int i=0;i<TrackState::NumberOfMeasurementTypes;i++)
+      m_tmpChi2VAlignParamMeasType[i][ipar] =new double[NFITS];
+  }
+
+  for (int ifit=0;ifit<NFITS;ifit++) {
+    residuals[ifit]=new double[NMEAS];
+    resErrors[ifit]=new double[NMEAS];
+  }
+  
+  // set the values for the unshifted track
+  const int unshiftedTrackIndex = m_doFits ? (m_nFits-1)/2 : 1;    
+  chi2Array [unshiftedTrackIndex] = m_unshiftedTrackChi2;
+  ATH_MSG_DEBUG("chi2Array["<<unshiftedTrackIndex<<"]="<<chi2Array[unshiftedTrackIndex]);
+  chi2ArrayX[unshiftedTrackIndex] = 0.;
+  if (m_doChi2VAlignParamMeasType) {
+    for (int i=0;i<TrackState::NumberOfMeasurementTypes;i++) {
+      m_tmpChi2VAlignParamMeasType[i][ipar][unshiftedTrackIndex]=
+      m_unshiftedTrackChi2MeasType[i];
+      ATH_MSG_DEBUG("chi2ArrayMeasType["<<i<<"]["<<unshiftedTrackIndex<<"]="<<m_unshiftedTrackChi2MeasType[i]);
+    }
+  }
+  
+  
+  // get shift size
+  double shiftsize=shiftSize(alignPar);
+  
+  ATH_MSG_VERBOSE("doing refits");
+  for (int ifit=0;ifit<NFITS;ifit++) {
+    
+    ATH_MSG_VERBOSE("ifit="<<ifit);
+    int jfit=ifit;  
+    if (ifit>unshiftedTrackIndex) {
+      jfit=NFITS-ifit+unshiftedTrackIndex;
+    }
+    if (m_doFits && ifit==unshiftedTrackIndex) {
+      for (int i=0;i<(int)m_unshiftedResiduals->rows();i++) {
+        residuals[ifit][i]=(*m_unshiftedResiduals)[i];
+        resErrors[ifit][i]=(*m_unshiftedResErrors)[i];
+      }
+      // change back in case it got changed on the other side of zero
+      shiftsize=shiftSize(alignPar); 
+      continue; 
+    }
+    
+    // shift module and fit track
+    double currentshift = 0.;
+    if(m_doFits)
+      currentshift = shiftsize * (double)(jfit-unshiftedTrackIndex);      
+    else
+      currentshift = (ifit==0) ? -1.*shiftsize : shiftsize;
+    
+    ATH_MSG_DEBUG("current shift="<<currentshift<<" in getDerivatives");
+    
+    m_alignModuleTool->shiftModule(module,alignTrack,
+    alignPar->paramType(),currentshift);
+
+    ATH_MSG_VERBOSE("fitting after shift");
+    const Track* refittedTrack=m_fitter->fit(*trackForRefit,
+               m_runOutlierRemoval,m_particleHypothesis);
+    if (m_setMinIterations && m_fitter->iterationsOfLastFit()>m_nIterations) {
+      m_nIterations=m_fitter->iterationsOfLastFit();
+      if (m_nIterations>m_maxIter) {
+        ATH_MSG_DEBUG("exceeded max number of iterations");
+        m_alignModuleTool->restoreModule(module);
+        resetIPar=false;
+        ATH_MSG_DEBUG("resetIPar set to false");
+        delete [] residuals; delete [] resErrors;
+        delete [] chi2Array; delete [] chi2ArrayX;
+        ATH_MSG_DEBUG("fail max iter");
+        m_ntracksFailMaxIter++;
+        Amg::VectorX derivatives(1);
+        return derivatives;
+      }
+      ATH_MSG_DEBUG("increasing m_nIterations to "<<m_nIterations<<" (not changing in fit yet)");
+      resetIPar=true;
+      ATH_MSG_DEBUG("resetIPar set to true");
+    }
+
+    // if resetIPar refit the rest of the tracks, but don't do anything with them until next pass
+    if (resetIPar) {
+      m_alignModuleTool->restoreModule(module);
+      continue;
+    }
+    
+    if (!refittedTrack) {
+      msg(MSG::WARNING) << "track refit failed for jfit "<<jfit <<endreq;
+      delete [] residuals; delete [] resErrors;
+      delete [] chi2Array; delete [] chi2ArrayX;
+      m_alignModuleTool->restoreModule(module);
+      if (!resetIPar || m_secPass) {
+        m_ntracksFailTrackRefit++;
+      }
+      ATH_MSG_DEBUG("fail track refit, resetIPar "<<resetIPar<<", secPass "<<m_secPass);
+      Amg::VectorX derivatives(1);
+      return derivatives;
+    }
+    else
+      ATH_MSG_VERBOSE("track refit successful");
+
+    double chi2=refittedTrack->fitQuality()->chiSquared();
+    
+    ATH_MSG_VERBOSE("jfit = "<<jfit);
+    double localChi2=m_residualCalculator->setResiduals(alignTrack,refittedTrack);
+    ATH_MSG_DEBUG("localChi2/fittedChi2="<<localChi2<<"/"<<chi2);
+
+    chi2ArrayX[jfit]= shiftsize * (double)(jfit-unshiftedTrackIndex);// / module->sigma(idof);
+    chi2Array[jfit]=localChi2;
+    ATH_MSG_DEBUG("chi2Array["<<jfit<<"]="<<chi2Array[jfit]);
+    if (m_doChi2VAlignParamMeasType) {
+      for (int i=0;i<TrackState::NumberOfMeasurementTypes;i++) {
+        m_tmpChi2VAlignParamMeasType[i][ipar][jfit]=  m_residualCalculator->chi2ForMeasType(i);
+        ATH_MSG_DEBUG("chi2ArrayMeasType["<<i<<"]["<<jfit<<"]="
+                      <<m_tmpChi2VAlignParamMeasType[i][ipar][jfit]);
+      }
+    }
+    
+    ATH_MSG_DEBUG("positions["<<jfit<<"]="<<chi2ArrayX[jfit]);
+
+    int imeas(0);
+    AlignTSOSCollection::const_iterator atsosItr=alignTrack->firstAtsos();
+    for (; atsosItr != alignTrack->lastAtsos(); ++atsosItr) { 
+      if (!(*atsosItr)->isValid()) continue;
+      for (vector<Residual>::const_iterator itRes=(**atsosItr).firstResidual();
+           itRes!=(**atsosItr).lastResidual();itRes++,imeas++) {
+  
+        if (refittedTrack) {
+          residuals[jfit][imeas]=itRes->residual();
+          resErrors[jfit][imeas]=std::sqrt(itRes->errSq());
+        } 
+        else {
+          residuals[jfit][imeas]=resErrors[jfit][imeas]=0.;
+        }
+        ATH_MSG_DEBUG("residuals["<<jfit<<"]["<<imeas<<"]="<<residuals[jfit][imeas]);
+        ATH_MSG_DEBUG("resErrors["<<jfit<<"]["<<imeas<<"]="<<resErrors[jfit][imeas]);
+      }
+    }
+    
+    delete refittedTrack; refittedTrack=0;
+    ATH_MSG_VERBOSE("calling restoreModule");
+    m_alignModuleTool->restoreModule(module);
+  } // NFITS
+
+  int iimeas(0);
+  AlignTSOSCollection::const_iterator aatsosItr=alignTrack->firstAtsos();
+  for (; aatsosItr != alignTrack->lastAtsos(); ++aatsosItr) { 
+    if (!(*aatsosItr)->isValid()) continue;
+    for (vector<Residual>::const_iterator itRes=(**aatsosItr).firstResidual();
+         itRes!=(**aatsosItr).lastResidual();itRes++,iimeas++) {
+      for (int ifit=0;ifit<NFITS;ifit++) {    
+        ATH_MSG_DEBUG("["<<ifit<<"]["<<iimeas<<"]   res="<<residuals[ifit][iimeas]<<
+          ",   resErr="<<resErrors[ifit][iimeas]);
+      }
+    }
+  }
+
+  if (resetIPar) {
+    //resetIPar=false;
+    delete [] residuals; delete [] resErrors;
+    delete [] chi2Array; delete [] chi2ArrayX;      
+    if (m_secPass) ATH_MSG_WARNING("failed second pass!");
+    ATH_MSG_DEBUG("returning to reset IPar");
+    Amg::VectorX derivatives;
+    return derivatives;
+  }
+
+  // check chi2 vs. chamber pos to see if discontinuous
+  TGraph* gr = new TGraph(m_nFits,chi2ArrayX,chi2Array);
+  gr->Fit("pol2","QF");
+  TF1* fit=gr->GetFunction("pol2");
+  double chi2 =fit->GetChisquare()/double(m_nFits-3);
+  double slope=fit->GetParameter(1);
+  actualSecondDeriv=fit->GetParameter(2);
+  delete gr;
+  
+  ATH_MSG_DEBUG("discontinuity check: chi2="<<chi2);
+  alignTrack->setTrackAlignParamQuality(alignPar->paramType(),chi2);  
+
+  // EventInfo
+  if (chi2>1.e-6 || std::fabs(slope)<1.e-10) {
+    const EventInfo* eventInfo;
+    StatusCode sc=evtStore()->retrieve(eventInfo);
+    if (sc.isFailure())
+    ATH_MSG_ERROR("Couldn't retrieve event info");    
+    int run=eventInfo->event_ID()->run_number();
+    int evt=eventInfo->event_ID()->event_number();
+    ATH_MSG_DEBUG("discontinuity check: chi2="<<chi2<<", run/evt "<<run<<"/"<<evt);
+  }
+
+  //reset in case it got changed somewhere
+  shiftsize = shiftSize(alignPar); 
+
+  //-----------------------------------------//
+  //--   get derivatives from residuals    --//
+  //-----------------------------------------//
+  ATH_MSG_VERBOSE("calculating residuals");
+  Amg::VectorX derivatives(alignTrack->nAlignTSOSMeas(),0);
+  ATH_MSG_DEBUG("created derivatives with "<<derivatives.rows()<<" rows");
+
+  // if bad fit or first derivative close to zero, replace derivatives with zeros
+  if (chi2>m_trackAlignParamCut) {// || std::fabs(slope)<1.e-10 ) {
+    ATH_MSG_DEBUG("chi2/"<<m_nFits-3<<"="<<chi2);
+    delete [] residuals; delete [] resErrors;
+    delete [] chi2Array; delete [] chi2ArrayX;
+
+    m_nIterations=m_fitter->iterationsOfLastFit()+5;
+    if (m_nIterations>m_maxIter) {
+      ATH_MSG_DEBUG("exceeded max number of iterations");
+      resetIPar=false;
+    }
+    ATH_MSG_DEBUG("increasing m_nIterations to "<<m_nIterations<<" (not changing in fit yet)");
+    resetIPar=true;      
+    ATH_MSG_INFO("fail align param cut, secPass "<<m_secPass);
+    if (m_secPass) {
+      m_ntracksFailAlignParamCut++;
+    }
+    Amg::VectorX emptyDerivatives;
+    return emptyDerivatives;
+  }
+
+  int imeas(0);
+  TCanvas* canv(0);
+  std::vector<TGraph*> vecGraphs;
+  AlignTSOSCollection::const_iterator atsosItr=alignTrack->firstAtsos();
+  for (; atsosItr != alignTrack->lastAtsos(); ++atsosItr) {   
+    if (!(*atsosItr)->isValid()) continue;
+    for (int idim=0;idim<(*atsosItr)->nResDim();idim++) {
+    
+      double* gr_x    = new double[NFITS];
+      double* gr_y    = new double[NFITS]; // residuals only have float precision if determined from ESD
+      int ngoodfits=0;
+      for (int ifit=0;ifit<NFITS;ifit++) {
+        double residual=residuals[ifit][imeas];
+        double resError=resErrors[ifit][imeas];
+        if (residual>-999.) {
+          gr_x[ngoodfits]   =chi2ArrayX[ifit];
+          gr_y[ngoodfits]   =residual/resError;
+          ngoodfits++;
+        }
+      }
+
+      if (!m_doFits && ngoodfits==2) {
+        derivatives[imeas]=(residuals[1][imeas]-residuals[0][imeas])/(2.*shiftsize)*
+        resErrors[unshiftedTrackIndex][imeas];
+      }
+      else if (m_doFits && ngoodfits>3) {
+        TGraph* gr=new TGraph(ngoodfits,gr_x,gr_y);
+  
+      if (m_doResidualPlots)
+        gr->Fit("pol2","VF");
+      else
+        gr->Fit("pol2","QF");
+      TF1* fit=gr->GetFunction("pol2");
+
+      //double derivRatio=fit->GetParameter(2)/fit->GetParameter(1);
+      ATH_MSG_DEBUG("deriv["<<imeas<<"]="<<fit->GetParameter(1)<<" +/- "<<fit->GetParError(1)
+        <<", chi2="<<fit->GetChisquare());
+      derivatives[imeas]=fit->GetParameter(1)*resErrors[unshiftedTrackIndex][imeas]; // first derivative at x=0
+      derivativeErr[imeas]=fit->GetParError(1)*resErrors[unshiftedTrackIndex][imeas];
+  
+
+      // plot residuals vs. chamber position
+      if (m_doResidualPlots) {
+        if (!canv) canv=new TCanvas("resPlots","resPlots");
+        canv->cd();
+        gr->SetMarkerStyle(20);
+              gr->Draw("AP");
+
+        gr->GetXaxis()->SetTitle("shift in chamber pos. from nominal (CLHEP::mm)");
+        gr->GetYaxis()->SetTitle("residual (CLHEP::mm)");
+    
+        TPaveText* pave=new TPaveText(.4,.65,.97,.92,"NDC");
+        pave->SetFillColor(0);
+        pave->SetBorderSize(1);
+        std::stringstream measType; measType<<"meas type: ";
+        if      ((*atsosItr)->measType()==TrackState::MDT) measType<<" MDT";
+        else if ((*atsosItr)->measType()==TrackState::TGC) measType<<" TGC";
+        else if ((*atsosItr)->measType()==TrackState::RPC) measType<<" RPC";
+        else measType<<" undefined";
+
+        pave->AddText(measType.str().c_str());
+
+        stringstream firstderivtxt,secndderivtxt,aptxt,chi2txt;
+        firstderivtxt<<fit->GetParameter(1)<<" +/- "<<fit->GetParError(1);
+        secndderivtxt<<fit->GetParameter(2)<<" +/- "<<fit->GetParError(2);
+        aptxt  <<"alignPar "<<alignPar->paramType()<<", RIO in "<<(*atsosItr)->identify();
+        chi2txt<<"chi2="<<fit->GetChisquare();
+
+        pave->AddText(firstderivtxt.str().c_str());     
+        pave->AddText(secndderivtxt.str().c_str());
+        pave->AddText(aptxt.str().c_str());
+        pave->AddText(chi2txt.str().c_str());
+        pave->Draw();
+
+        std::stringstream canvName; 
+        canvName<<"resPlots_ap"<<alignPar->paramType()<<"_measType"
+        <<(*atsosItr)->measType()<<"_"<<imeas<<".eps";
+        canv->Print(canvName.str().c_str());
+        canv->Clear();
+
+        delete pave;      
+      }
+      vecGraphs.push_back(gr);
+    }
+    else {
+      derivatives[imeas]=-999.;
+      derivativeErr[imeas]=-999.;
+    }
+
+    delete [] gr_y;
+    delete [] gr_x;
+
+    ++imeas;
+    }   
+  }
+
+  // delete TGraphs and TCanvas 
+  for (int i=0;i<(int)vecGraphs.size();i++) 
+    delete vecGraphs[i];
+  delete canv;
+  
+  delete [] residuals;
+  delete [] resErrors;
+  
+  // set chi2 v alignparam
+  for (int ifit=0;ifit<NFITS;ifit++) {
+    m_tmpChi2VAlignParamX[ipar]=chi2ArrayX;
+    m_tmpChi2VAlignParam [ipar]=chi2Array;
+  }
+
+  ATH_MSG_DEBUG("derivativeErr: "<<derivativeErr);
+  return derivatives;
+}
+  
+//________________________________________________________________________
+double ShiftingDerivCalcTool::shiftSize(const AlignPar* alignPar) const {
+  bool rotation = 
+    alignPar->paramType() == AlignModule::RotX || 
+    alignPar->paramType() == AlignModule::RotY || 
+    alignPar->paramType() == AlignModule::RotZ; 
+  
+  double shift = rotation ? m_rotSize : m_traSize;
+  
+  //ok... this is kind of ugly.
+  double sigma=alignPar->sigma();
+  return shift * sigma;
+}
+
+//________________________________________________________________________
+bool ShiftingDerivCalcTool::setResidualCovMatrix(AlignTrack* alignTrack) const
+{
+  Amg::MatrixX* pW = new Amg::MatrixX(alignTrack->nAlignTSOSMeas(),alignTrack->nAlignTSOSMeas());
+  //AmgSymMatrix* pW = new AmgSymMatrix(alignTrack->nAlignTSOSMeas());
+  Amg::MatrixX& W = *pW;
+  
+  if (alignTrack->localErrorMatrixInv()) {
+    ATH_MSG_ERROR("Need to assign this matrix correctly: ShiftingDerivCalcTool.cxx:893");
+    W = *(alignTrack->localErrorMatrixInv());
+    //W.assign(*(alignTrack->localErrorMatrixInv()));
+  } else 
+    return false;
+  
+  ATH_MSG_DEBUG("W: "<<W);
+
+  bool Wisvalid(true);
+  const double epsilon=1e-10;
+  for( int irow=0; irow<W.rows(); ++irow) {
+    Wisvalid = Wisvalid && W(irow,irow)>0;
+    if( !(W(irow,irow)>0) ) 
+      msg(MSG::WARNING) << "matrix invalid: " << W(irow,irow) << endreq;
+    
+    for(int icol=0; icol<=irow; ++icol) {
+
+    // this one must be true if everything else succeeded
+    double Wcorr = W(irow,icol)/sqrt(W(irow,irow)*W(icol,icol));
+    bool Wcorrisvalid = Wcorr+epsilon>=-1 && Wcorr-epsilon<=1;
+    Wisvalid = Wisvalid && Wcorrisvalid;
+    if( !Wcorrisvalid )
+      msg(MSG::WARNING) << "matrix corr invalid: " << Wcorr-1 << " " << Wcorr+1 << endreq;
+    }
+  }
+
+  if (Wisvalid) 
+  
+  alignTrack->setWeightMatrix(pW);
+  Amg::MatrixX* pWfirst=new Amg::MatrixX(*pW);
+  alignTrack->setWeightMatrixFirstDeriv(pWfirst);
+  
+  return true;
+}
+    
+//________________________________________________________________________
+void ShiftingDerivCalcTool::deleteChi2VAlignParam() 
+{    
+  for (int i=0;i<(int)m_chi2VAlignParamVec.size();i++) {
+    delete [] m_chi2VAlignParamVec[i];  m_chi2VAlignParamVec[i]=0;
+    delete [] m_chi2VAlignParamXVec[i]; m_chi2VAlignParamXVec[i]=0;
+  }
+  m_chi2VAlignParamVec.clear();
+  m_chi2VAlignParamXVec.clear();
+
+  for (int i=0;i<(int)m_chi2VAlignParamVecMeasType.size();i++) {
+    delete [] m_chi2VAlignParamVecMeasType[i];  m_chi2VAlignParamVecMeasType[i]=0;
+  }
+  m_chi2VAlignParamVecMeasType.clear();
+
+  return;
+}
+
+//________________________________________________________________________
+bool ShiftingDerivCalcTool::getAllDerivatives(AlignTrack* alignTrack,
+          const AlignModule* alignModule,
+          std::vector<Amg::VectorX>& deriv_vec,
+          std::vector<Amg::VectorX>& derivErr_vec,
+          std::vector<double>& actualsecderiv_vec,
+          bool& resetIPar)
+{
+  resetIPar=false;
+
+  deriv_vec.clear();
+  derivErr_vec.clear();
+  actualsecderiv_vec.clear();
+
+  setUnshiftedResiduals(alignTrack); // this will set the min number of iterations to the new value
+
+  int ipar(0);
+  DataVector<AlignPar>* alignPars=m_alignModuleTool->getAlignPars(alignModule);
+  for (DataVector<AlignPar>::iterator it=alignPars->begin(); it!=alignPars->end(); ++it,ipar++) {
+    ATH_MSG_DEBUG("ipar: "<<ipar);
+    Amg::VectorX derivErr(alignTrack->nAlignTSOSMeas());
+    double actualSecondDeriv(0.);
+    const Amg::VectorX vec=getDerivatives(alignTrack,ipar,*it,derivErr,resetIPar,actualSecondDeriv);
+    ATH_MSG_DEBUG("vec size: "<<vec.rows());
+
+    ATH_MSG_DEBUG("resetIPar="<<resetIPar);
+    if (resetIPar) continue; // continue with derivatives to find max iteration
+
+    if (vec.rows()<1) return false; // derivatives won't be set for alignTrack because it's a bad track
+
+    deriv_vec.push_back(vec);
+    derivErr_vec.push_back(derivErr);
+    actualsecderiv_vec.push_back(actualSecondDeriv);
+      
+    for (int i=0;i<m_nFits;i++) {
+      ATH_MSG_DEBUG("m_tmpChi2VAlignParam["<<ipar<<"]["
+                <<i<<"]="<<m_tmpChi2VAlignParam[ipar][i]);
+    }
+  }
+
+  return true;
+}
+
+} // end namespace
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/TrackCollectionProvider.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/TrackCollectionProvider.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ff6bc905cde3b87f08a343f12cd78a88e5545134
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/TrackCollectionProvider.cxx
@@ -0,0 +1,85 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrkAlignGenTools/TrackCollectionProvider.h"
+
+namespace Trk {
+  
+  //________________________________________________________________________
+  TrackCollectionProvider::TrackCollectionProvider(const std::string& type, 
+						   const std::string& name,
+						   const IInterface* parent)
+    
+    : AthAlgTool(type,name,parent)
+    , m_nRetrievalErrors(0)
+  {
+
+    declareInterface<ITrackCollectionProvider>(this);
+
+    declareProperty("InputTrkCol",        m_inputCol="MooreTracks");
+    
+    declareProperty("MaxRetrievalErrors", m_maxRetrievalErrors = 10);
+
+  }
+
+  //________________________________________________________________________
+  TrackCollectionProvider::~TrackCollectionProvider()
+  {
+
+  }
+
+  //________________________________________________________________________
+  StatusCode TrackCollectionProvider::initialize()
+  {
+    return StatusCode::SUCCESS;
+  }
+
+  //________________________________________________________________________
+  StatusCode TrackCollectionProvider::finalize()
+  {
+    return StatusCode::SUCCESS;
+  }
+
+  
+  //________________________________________________________________________
+  StatusCode TrackCollectionProvider::trackCollection(const TrackCollection*& originalTracks)
+  {
+    ATH_MSG_DEBUG("in TrackCollectionProvider::trackCollection");
+
+    originalTracks=0;
+    
+    // check if m_inputCol is a TrackCollection and exists for this event
+    // perhaps this can be done in a much nicer way on the python side ala PyUtils/checkFile.py
+    // do it here for now
+    if( !evtStore()->contains<TrackCollection>(m_inputCol) ||
+	evtStore()->retrieve(originalTracks,m_inputCol).isFailure() ) {
+      
+      originalTracks=0;
+      
+      ATH_MSG_DEBUG("input track collection \'"<<m_inputCol<<"\' not found for this event");
+      
+      if(m_maxRetrievalErrors>=0) {
+	++m_nRetrievalErrors;
+	if(m_nRetrievalErrors>=m_maxRetrievalErrors) {
+	  msg(MSG::FATAL)<<"Input track collection \'"<<m_inputCol<<"\' not found in first "
+			 <<m_nRetrievalErrors<<" events. Aborting."<<endreq;
+	  msg(MSG::FATAL)<<"Maximum allowed number of events without the track collection "
+			 <<"can be changed using the \'MaxRetrievalErrors\' option (-1 for infinite)."
+			 <<endreq;
+	  return StatusCode::FAILURE;
+	}
+      }
+      return StatusCode::SUCCESS;
+    }
+    ATH_MSG_DEBUG("found "<<originalTracks->size()<<" tracks");
+
+    // if we're here it means that the track collection m_inputCol exists in the file
+    // (it can be empty) so we change the error cutoff to process the whole file
+    if(m_maxRetrievalErrors>=0)
+      m_maxRetrievalErrors=-1;
+    
+    return StatusCode::SUCCESS;
+  }
+
+} // end namespace
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/TrkAlignDBTool.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/TrkAlignDBTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..7a02b3ceb492fb8b3f0bad92a62164b3b7db3924
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/TrkAlignDBTool.cxx
@@ -0,0 +1,46 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// TrkAlignDBTool.cxx
+
+#include "GaudiKernel/StatusCode.h"
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/AlgTool.h"
+
+#include "TrkAlignGenTools/TrkAlignDBTool.h"
+
+namespace Trk {
+  
+    //_______________________________________________________________________
+  TrkAlignDBTool::TrkAlignDBTool(const std::string& type, const std::string& name,
+			       const IInterface* parent)
+    : AthAlgTool(type,name,parent)
+  {
+    declareInterface<ITrkAlignDBTool>(this);
+
+    m_logStream = 0;
+  }
+
+   //_______________________________________________________________________
+  TrkAlignDBTool::~TrkAlignDBTool()
+  {
+  }
+  //_______________________________________________________________________
+  StatusCode TrkAlignDBTool::initialize()
+  {
+    msg(MSG::DEBUG) << "initialize() of TrkAlignDBTool" << endreq;  
+
+    return StatusCode::SUCCESS;
+  }
+  
+  //_______________________________________________________________________
+  StatusCode TrkAlignDBTool::finalize()
+  {
+    msg(MSG::DEBUG) << "finalize() of TrkAlignDBTool" << endreq;  
+    
+    return StatusCode::SUCCESS;    
+  }
+
+
+}
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/components/TrkAlignGenTools_entries.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/components/TrkAlignGenTools_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..3deaad01c5423dcd626ce41a1d6f370831d85334
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/components/TrkAlignGenTools_entries.cxx
@@ -0,0 +1,49 @@
+#include "GaudiKernel/DeclareFactoryEntries.h"
+#include "TrkAlignGenTools/MatrixTool.h"
+#include "TrkAlignGenTools/IPCMatrixTool.h"
+#include "TrkAlignGenTools/TrkAlignDBTool.h"
+#include "TrkAlignGenTools/AnalyticalDerivCalcTool.h"
+#include "TrkAlignGenTools/ShiftingDerivCalcTool.h"
+#include "TrkAlignGenTools/AlignTrackPreProcessor.h"
+#include "TrkAlignGenTools/TrackCollectionProvider.h"
+#include "TrkAlignGenTools/MSConstraintTracksProvider.h"
+#include "TrkAlignGenTools/AlignTrackCreator.h"
+#include "TrkAlignGenTools/AlignTrackDresser.h"
+#include "TrkAlignGenTools/AlignModuleTool.h"
+#include "TrkAlignGenTools/AlignResidualCalculator.h"
+#include "TrkAlignGenTools/BeamspotVertexPreProcessor.h"
+#include "TrkAlignGenTools/ConstrainedTrackProvider.h"
+
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, MatrixTool )
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, IPCMatrixTool )
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, TrkAlignDBTool )
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, AnalyticalDerivCalcTool )
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, ShiftingDerivCalcTool )
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, AlignTrackPreProcessor )
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, TrackCollectionProvider )
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, MSConstraintTracksProvider )
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, AlignTrackCreator )
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, AlignTrackDresser )
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, AlignModuleTool )
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, AlignResidualCalculator )
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, BeamspotVertexPreProcessor )
+DECLARE_NAMESPACE_TOOL_FACTORY( Trk, ConstrainedTrackProvider )
+
+
+DECLARE_FACTORY_ENTRIES( TrkAlignGenTools )
+{
+  DECLARE_NAMESPACE_TOOL( Trk, MatrixTool )
+  DECLARE_NAMESPACE_TOOL( Trk, IPCMatrixTool )
+  DECLARE_NAMESPACE_TOOL( Trk, TrkAlignDBTool )
+  DECLARE_NAMESPACE_TOOL( Trk, AnalyticalDerivCalcTool )
+  DECLARE_NAMESPACE_TOOL( Trk, ShiftingDerivCalcTool )
+  DECLARE_NAMESPACE_TOOL( Trk, TrackCollectionProvider )
+  DECLARE_NAMESPACE_TOOL( Trk, MSConstraintTracksProvider )
+  DECLARE_NAMESPACE_TOOL( Trk, AlignTrackPreProcessor )
+  DECLARE_NAMESPACE_TOOL( Trk, AlignTrackCreator )
+  DECLARE_NAMESPACE_TOOL( Trk, AlignTrackDresser )
+  DECLARE_NAMESPACE_TOOL( Trk, AlignModuleTool )
+  DECLARE_NAMESPACE_TOOL( Trk, AlignResidualCalculator )
+  DECLARE_NAMESPACE_TOOL( Trk, BeamspotVertexPreProcessor )
+  DECLARE_NAMESPACE_TOOL( Trk, ConstrainedTrackProvider )
+}
diff --git a/Tracking/TrkAlignment/TrkAlignGenTools/src/components/TrkAlignGenTools_load.cxx b/Tracking/TrkAlignment/TrkAlignGenTools/src/components/TrkAlignGenTools_load.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..9c288b58c92374f402b1e436763ae4b766558d8d
--- /dev/null
+++ b/Tracking/TrkAlignment/TrkAlignGenTools/src/components/TrkAlignGenTools_load.cxx
@@ -0,0 +1,4 @@
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+LOAD_FACTORY_ENTRIES( TrkAlignGenTools )
+