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 ) +