diff --git a/MuonSpectrometer/MuonReconstruction/MuonRecExample/python/MuonRecExampleConfigDb.py b/MuonSpectrometer/MuonReconstruction/MuonRecExample/python/MuonRecExampleConfigDb.py index 2d616e4f89023e1c0f953cc1675deaa7349f7113..10482c797a4214109e2ead74025908a71932a5fc 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonRecExample/python/MuonRecExampleConfigDb.py +++ b/MuonSpectrometer/MuonReconstruction/MuonRecExample/python/MuonRecExampleConfigDb.py @@ -43,7 +43,7 @@ addTool( "MuonRecExample.MuonRecTools.MuonRotCreator", "MuonRotCreator" ) addTool( "MuonRecExample.MuonRecTools.MuonCombinePatternTool", "MuonCombinePatternTool" ) addTool( "MuonRecExample.MuonRecTools.MuonHoughPatternTool", "MuonHoughPatternTool" ) -addTool( "MuonRecExample.MuonRecTools.MuonHoughPatternFinderTool", "MuonHoughPatternFinderTool" ) +addTool( "MuonRecExample.MuonRecTools.MuonHoughPatternFinderTool", "MuonHoughPatternFinderTool" ) addService("MuonRecExample.MuonRecTools.AtlasTrackingGeometrySvc","AtlasTrackingGeometrySvc") @@ -54,7 +54,7 @@ addTool( "Trk::MaterialEffectsUpdator", "MuonMaterialEffectsUpdator" ) addTool("MuonRecExample.MuonRecTools.MuonRK_Propagator","MuonRK_Propagator") addTool("MuonRecExample.MuonRecTools.MuonSTEP_Propagator","MuonSTEP_Propagator") addTool("MuonRecExample.MuonRecTools.MuonSTEP_Propagator","MuonPropagator") -addTool("MuonRecExample.MuonRecTools.MuonSTEP_Propagator","MCTBPropagator") +addTool("MuonRecExample.MuonRecTools.MuonSTEP_Propagator","MCTBPropagator") addTool("Trk::STEP_Propagator", "MuonStraightLinePropagator") addTool("MuonRecExample.MuonRecTools.MuonExtrapolator", "MuonExtrapolator") @@ -85,7 +85,7 @@ addTool( "MuonRecExample.MuonRecTools.MuonChi2TrackFitter", "MuonChi2SLTrackFitt addTool( "MuonRecExample.MuonRecTools.MuonSegmentMomentum", "MuonSegmentMomentum" ) addTool( "MuonRecExample.MuonRecTools.MuonSegmentMomentumFromField", "MuonSegmentMomentumFromField") - + addTool( "MuonRecExample.MuonRecTools.MuonPhiHitSelector", "MuonPhiHitSelector" ) addTool( "MuonRecExample.MuonRecTools.MdtSegmentT0Fitter", "MdtSegmentT0Fitter" ) @@ -96,7 +96,7 @@ addTool( "MuonRecExample.MuonRecTools.MdtMathT0FitSegmentFinder", "MdtMathT0FitS addTool( "MuonRecExample.MuonRecTools.DCMathSegmentMaker", "DCMathSegmentMaker" ) addTool( "MuonRecExample.MuonRecTools.DCMathT0FitSegmentMaker", "DCMathT0FitSegmentMaker" ) -addTool( "MuonRecExample.MuonRecTools.MuonClusterSegmentFinder", "MuonClusterSegmentFinder") +addTool( "MuonRecExample.MuonRecTools.MuonClusterSegmentFinder", "MuonClusterSegmentFinder") addTool( "MuonRecExample.MuonRecTools.MuonClusterSegmentFinderTool", "MuonClusterSegmentFinderTool" ) #N.B. Both of these are tools. They do slightly different things, but the naming is unfortunate. @@ -174,7 +174,7 @@ addTool( "MuonRecExample.MooreTools.MuonTrackScoringTool", "MuonTrackScoringTool addTool( "Muon::MuonAmbiTrackSelectionTool", "MuonAmbiSelectionTool" ) -addTool( "MuonRecExample.MooreTools.MuonAmbiProcessor", "MuonAmbiProcessor" ) +addTool( "MuonRecExample.MooreTools.MuonAmbiProcessor", "MuonAmbiProcessor" ) addTool( "MuonRecExample.MooreTools.MuonTrackSelectorTool", "MuonTrackSelectorTool" ) @@ -217,7 +217,7 @@ if MuonGeometryFlags.hasCSC(): addTool("MuonRecExample.CscTools.CalibCscStripFitter","CalibCscStripFitter") addTool("MuonRecExample.CscTools.SimpleCscClusterFitter","SimpleCscClusterFitter") addTool("MuonRecExample.CscTools.CscSplitClusterFitter","CscSplitClusterFitter") - + addTool("MuonRecExample.CscTools.Csc2dSegmentMaker","Csc2dSegmentMaker") addTool("MuonRecExample.CscTools.Csc4dSegmentMaker","Csc4dSegmentMaker") addTool("MuonRecExample.CscTools.CscSegmentUtilTool","CscSegmentUtilTool") @@ -260,6 +260,7 @@ addTool("Muon::MuonSegmentCombinationCleanerTool","MuonSegmentCombinationCleaner addTool( "MuonRecExample.MuonStandalone.MuonTrackSteering", "MuonTrackSteering" ) addTool("MuonRecExample.MuonRecTools.MuonSegmentFittingTool", "MuonSegmentFittingTool") +addTool("MuonRecExample.MuonRecTools.MuonLayerSegmentFinderTool", "MuonLayerSegmentFinderTool") ################################################################################ # MS vertex diff --git a/MuonSpectrometer/MuonReconstruction/MuonRecExample/python/MuonRecTools.py b/MuonSpectrometer/MuonReconstruction/MuonRecExample/python/MuonRecTools.py index 7887d30fc9649590fe0aba20629bf1dcb5c768ec..0b9461b6491d850ba721329548824b594bf02816 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonRecExample/python/MuonRecTools.py +++ b/MuonSpectrometer/MuonReconstruction/MuonRecExample/python/MuonRecTools.py @@ -65,7 +65,7 @@ def CscClusterOnTrackCreator(name="CscClusterOnTrackCreator",**kwargs): kwargs.setdefault("CSCErrorScalingKey","/MUON/TrkErrorScalingCSC") if globalflags.DataSource() == 'data': # collisions real data or simulated first data - # scale CSC and hit errors + # scale CSC and hit errors kwargs.setdefault("ErrorScalerBeta", 0.070 ) return CfgMgr.Muon__CscClusterOnTrackCreator(name,**kwargs) @@ -101,7 +101,7 @@ def MdtDriftCircleOnTrackCreator(name="MdtDriftCircleOnTrackCreator",**kwargs): if globalflags.DataSource() == 'data': # collisions real data or simulated first data kwargs.setdefault("CreateTubeHit", True) # BroadErrors - kwargs.setdefault("UseLooseErrors", muonRecFlags.useLooseErrorTuning()) # LooseErrors on data + kwargs.setdefault("UseLooseErrors", muonRecFlags.useLooseErrorTuning()) # LooseErrors on data if globalflags.DataSource() == 'data': kwargs.setdefault("IsMC", False) @@ -110,11 +110,11 @@ def MdtDriftCircleOnTrackCreator(name="MdtDriftCircleOnTrackCreator",**kwargs): if TriggerFlags.MuonSlice.doTrigMuonConfig: kwargs.setdefault("doMDT", True) - + return CfgMgr.Muon__MdtDriftCircleOnTrackCreator(name,**kwargs) # end of factory function MdtDriftCircleOnTrackCreator - + def MdtTubeHitOnTrackCreator(name="MdtTubeHitOnTrackCreator",**kwargs): kwargs["CreateTubeHit"] = True return MdtDriftCircleOnTrackCreator(name,**kwargs) @@ -133,7 +133,7 @@ def AdjustableT0Tool(name="AdjustableT0Tool",**kwargs): kwargs.setdefault("DoTof", 0) else: # collisions simulation final precise cuts kwargs.setdefault("DoTof", 1) - + from MdtDriftCircleOnTrackCreator.MdtDriftCircleOnTrackCreatorConf import AdjT0__AdjustableT0Tool return AdjT0__AdjustableT0Tool(name,**kwargs) # end of factory function AdjustableT0ToolMboy @@ -169,20 +169,20 @@ def MuonCombinePatternTool(name="MuonCombinePatternTool",**kwargs): # end of factory function MuonCombinePatternTool def MuonHoughPatternTool(name="MuonHoughPatternTool",**kwargs): - if muonStandaloneFlags.reconstructionMode() == 'collisions': + if muonStandaloneFlags.reconstructionMode() == 'collisions': kwargs.setdefault("UseCosmics", True) kwargs.setdefault("NumberOfMaximaPerIterations", 1) return CfgMgr.MuonHoughPatternTool(name,**kwargs) # end of factory function MuonHoughPatternTool -def MuonHoughPatternFinderTool(name="MuonHoughPatternFinderTool",**kwargs): - getPublicTool("MuonCombinePatternTool") - getPublicTool("MuonHoughPatternTool") - if muonStandaloneFlags.reconstructionMode() == 'collisions': +def MuonHoughPatternFinderTool(name="MuonHoughPatternFinderTool",**kwargs): + getPublicTool("MuonCombinePatternTool") + getPublicTool("MuonHoughPatternTool") + if muonStandaloneFlags.reconstructionMode() == 'collisions': kwargs.setdefault("MDT_TDC_cut", False) - if muonStandaloneFlags.reconstructionMode() == 'collisions' or TriggerFlags.MuonSlice.doTrigMuonConfig: + if muonStandaloneFlags.reconstructionMode() == 'collisions' or TriggerFlags.MuonSlice.doTrigMuonConfig: kwargs.setdefault("RecordAll",False) - return CfgMgr.Muon__MuonHoughPatternFinderTool(name,**kwargs) + return CfgMgr.Muon__MuonHoughPatternFinderTool(name,**kwargs) #-------------------------------------------------------------------------------- # Tracking geometry @@ -380,11 +380,12 @@ def MdtMathSegmentFinder(name="MdtMathSegmentFinder",extraFlags=None,**kwargs): return CfgMgr.Muon__MdtMathSegmentFinder(name,**kwargs) def MdtMathT0FitSegmentFinder(name="MdtMathT0FitSegmentFinder",extraFlags=None,**kwargs): - if extraFlags is None: extraFlags = ExtraFlags() + if extraFlags is None: extraFlags = ExtraFlags() extraFlags.setFlagDefault('doSegmentT0Fit',True) return MdtMathSegmentFinder(name,extraFlags,**kwargs) def MuonClusterSegmentFinder(name="MuonClusterSegmentFinder", extraFlags=None,**kwargs): + kwargs.setdefault("AmbiguityProcessor",getPublicTool("MuonAmbiProcessor")) return CfgMgr.Muon__MuonClusterSegmentFinder(name,**kwargs) def MuonClusterSegmentFinderTool(name="MuonClusterSegmentFinderTool", extraFlags=None,**kwargs): @@ -402,7 +403,7 @@ def DCMathSegmentMaker(name='DCMathSegmentMaker',extraFlags=None,**kwargs): doSegmentT0Fit = getattr(extraFlags,"doSegmentT0Fit", muonRecFlags.doSegmentT0Fit()) updateSegmentSecondCoordinate = getattr(extraFlags,"updateSegmentSecondCoordinate", muonStandaloneFlags.updateSegmentSecondCoordinate()) enableCurvedSegmentFinding = getattr(extraFlags,"enableCurvedSegmentFinding", muonStandaloneFlags.enableCurvedSegmentFinding()) - + kwargs.setdefault("RefitSegment", True) kwargs.setdefault("AssumePointingPhi", beamType != 'cosmics') kwargs.setdefault("OutputFittedT0", True) @@ -417,8 +418,8 @@ def DCMathSegmentMaker(name='DCMathSegmentMaker',extraFlags=None,**kwargs): # MuonCompetingClustersCreator apparently just takes default kwargs.setdefault("MuonClusterCreator", getPrivateTool("MuonClusterOnTrackCreator") ) - - if (beamType == 'singlebeam' or beamType == 'cosmics'): + + if (beamType == 'singlebeam' or beamType == 'cosmics'): kwargs.setdefault("SinAngleCut", 0.9) kwargs.setdefault("AddUnassociatedPhiHits", True) kwargs.setdefault("RecoverBadRpcCabling", True) @@ -447,7 +448,7 @@ def DCMathSegmentMaker(name='DCMathSegmentMaker',extraFlags=None,**kwargs): def DCMathT0FitSegmentMaker(name='DCMathT0FitSegmentMaker',extraFlags=None,**kwargs): - if extraFlags is None: extraFlags = ExtraFlags() + if extraFlags is None: extraFlags = ExtraFlags() extraFlags.setFlagDefault('doSegmentT0Fit',True) return DCMathSegmentMaker(name,extraFlags,**kwargs) @@ -461,7 +462,7 @@ def MuonLayerHoughTool(name='MuonLayerHoughTool',extraFlags=None,**kwargs): return CfgMgr.Muon__MuonLayerHoughTool(name,**kwargs) def MuonSegmentFittingTool(name='MuonSegmentFittingTool',extraFlags=None,**kwargs): - prop = getPublicTool('AtlasRungeKuttaPropagator') + prop = getPublicTool('AtlasRungeKuttaPropagator') kwargs.setdefault("SLPropagator", getPrivateToolClone('SLPropagator',prop) ) # Think I need to do it this way because AtlasRungeKuttaPropagator isn't known to ConfigurableFactory. # If I directly call getPrivateTool('AtlasRungeKuttaPropagator') then it fails with: @@ -485,8 +486,15 @@ if DetFlags.detdescr.Muon_on() and rec.doMuon(): getPrivateTool("CscBroadClusterOnTrackCreator") getPublicTool("MdtDriftCircleOnTrackCreator") getPublicTool("MdtTubeHitOnTrackCreator") - + #getService("SomeService") else: # not (DetFlags.Muon_on() and rec.doMuon()) logMuon.warning("Muon reconstruction tools only loaded on-demand because Muons") + +def MuonLayerSegmentFinderTool(name='MuonLayerSegmentFinderTool',extraFlags=None,**kwargs): + kwargs.setdefault("Csc2DSegmentMaker", getPublicTool("Csc2dSegmentMaker") if MuonGeometryFlags.hasCSC() else "") + kwargs.setdefault("Csc4DSegmentMaker", getPublicTool("Csc4dSegmentMaker") if MuonGeometryFlags.hasCSC() else "") + kwargs.setdefault("MuonClusterSegmentFinder",getPublicTool("MuonClusterSegmentFinder")) + + return CfgMgr.Muon__MuonLayerSegmentFinderTool(name,**kwargs) \ No newline at end of file diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/Csc4dSegmentMaker.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/Csc4dSegmentMaker.cxx index 20060cefeb6aa96374b32fcea12a0cf70df0ec32..877fb763a9d77946e67b28cf8a8814c1de530153 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/Csc4dSegmentMaker.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/Csc4dSegmentMaker.cxx @@ -3,30 +3,27 @@ */ #include "Csc4dSegmentMaker.h" + #include <sstream> + +#include "CscClusterization/ICscClusterFitter.h" +#include "CscClusterization/ICscStripFitter.h" #include "CscSegmentMakers/ICscSegmentUtilTool.h" -#include "MuonReadoutGeometry/MuonDetectorManager.h" -#include "MuonReadoutGeometry/CscReadoutElement.h" +#include "EventPrimitives/EventPrimitivesHelpers.h" #include "MuonPrepRawData/CscPrepDataContainer.h" -#include "TrkEventPrimitives/LocalDirection.h" -#include "TrkSurfaces/PlaneSurface.h" -#include "TrkSurfaces/TrapezoidBounds.h" - #include "MuonRIO_OnTrack/CscClusterOnTrack.h" #include "MuonRIO_OnTrack/MdtDriftCircleOnTrack.h" - -#include "TrkEventPrimitives/FitQuality.h" -#include "EventPrimitives/EventPrimitivesHelpers.h" +#include "MuonReadoutGeometry/CscReadoutElement.h" +#include "MuonReadoutGeometry/MuonDetectorManager.h" +#include "MuonRecHelperTools/MuonEDMPrinterTool.h" #include "MuonSegment/MuonSegment.h" - #include "MuonSegment/MuonSegmentCombinationCollection.h" -#include "CscClusterization/ICscStripFitter.h" -#include "CscClusterization/ICscClusterFitter.h" - -#include "TrkSegment/Segment.h" +#include "TrkEventPrimitives/FitQuality.h" +#include "TrkEventPrimitives/LocalDirection.h" #include "TrkRoad/TrackRoad.h" - -#include "MuonRecHelperTools/MuonEDMPrinterTool.h" +#include "TrkSegment/Segment.h" +#include "TrkSurfaces/PlaneSurface.h" +#include "TrkSurfaces/TrapezoidBounds.h" using Muon::CscPrepData; using Muon::CscPrepDataCollection; @@ -38,8 +35,8 @@ using Muon::CscClusterOnTrack; using Muon::MuonSegment; using Muon::MuonSegmentCombination; -using Muon::MuonClusterOnTrack; using Muon::MdtDriftCircleOnTrack; +using Muon::MuonClusterOnTrack; /*namespace { std::string station_name(int station) { @@ -55,109 +52,98 @@ using Muon::MdtDriftCircleOnTrack; //****************************************************************************** -Csc4dSegmentMaker:: -Csc4dSegmentMaker(const std::string& type, const std::string& aname, const IInterface* parent) -: AthAlgTool(type, aname, parent), - m_dumped(0), m_dump(false), - m_segmentTool("CscSegmentUtilTool/CscSegmentUtilTool"), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool") +Csc4dSegmentMaker::Csc4dSegmentMaker(const std::string& type, const std::string& aname, const IInterface* parent) + : AthAlgTool(type, aname, parent), m_dumped(0), m_dump(false) { - declareInterface<ICscSegmentFinder>(this); - declareProperty("dump_count", m_dumpcount =-1); - declareProperty("max_chisquare", m_max_chisquare = 25); - declareProperty("max_slope_r", m_max_slope_r = 0.2); - declareProperty("max_slope_phi", m_max_slope_phi = 0.2); - declareProperty("max_seg_per_chamber", m_max_seg_per_chamber = 50); - declareProperty("segmentTool", m_segmentTool); + declareInterface<ICscSegmentFinder>(this); + declareProperty("dump_count", m_dumpcount = -1); + declareProperty("max_chisquare", m_max_chisquare = 25); + declareProperty("max_slope_r", m_max_slope_r = 0.2); + declareProperty("max_slope_phi", m_max_slope_phi = 0.2); + declareProperty("max_seg_per_chamber", m_max_seg_per_chamber = 50); } //****************************************************************************** // Destructor. -Csc4dSegmentMaker::~Csc4dSegmentMaker() { -} +Csc4dSegmentMaker::~Csc4dSegmentMaker() {} //****************************************************************************** -StatusCode Csc4dSegmentMaker::initialize(){ - - ATH_MSG_DEBUG ( "Initializing" ); - - // Show keys. - ATH_MSG_DEBUG ( " Dump count: " << m_dumpcount ); - ATH_MSG_DEBUG ( " Max chi-square: " << m_max_chisquare ); - ATH_MSG_DEBUG ( " Max r slope: " << m_max_slope_r ); - ATH_MSG_DEBUG ( " Max phi slope: " << m_max_slope_phi ); - ATH_MSG_DEBUG ( " Max segments/chamber: " << m_max_seg_per_chamber ); - ATH_MSG_DEBUG ( " SegmentTool: " << m_segmentTool.typeAndName() ); +StatusCode +Csc4dSegmentMaker::initialize() +{ + ATH_MSG_DEBUG("Initializing"); - if ( m_segmentTool.retrieve().isFailure() ) { - ATH_MSG_ERROR ( "Unable to retrieve CscSegmentUtilTool " << m_segmentTool ); - return StatusCode::FAILURE; - } + // Show keys. + ATH_MSG_DEBUG(" Dump count: " << m_dumpcount); + ATH_MSG_DEBUG(" Max chi-square: " << m_max_chisquare); + ATH_MSG_DEBUG(" Max r slope: " << m_max_slope_r); + ATH_MSG_DEBUG(" Max phi slope: " << m_max_slope_phi); + ATH_MSG_DEBUG(" Max segments/chamber: " << m_max_seg_per_chamber); + ATH_MSG_DEBUG(" SegmentTool: " << m_segmentTool.typeAndName()); - if (m_printer.retrieve().isFailure()){ - ATH_MSG_ERROR("Failed to initialize " << m_printer ); - return StatusCode::FAILURE; - } + ATH_CHECK(m_segmentTool.retrieve()); + ATH_CHECK(m_printer.retrieve()); - - return StatusCode::SUCCESS; + return StatusCode::SUCCESS; } //****************************************************************************** std::unique_ptr<MuonSegmentCombinationCollection> -Csc4dSegmentMaker::find( const MuonSegmentCombinationCollection& segcols) const +Csc4dSegmentMaker::find(const MuonSegmentCombinationCollection& segcols) const { - // Set dump flag. - m_dump = m_dumped < m_dumpcount || m_dumpcount < 0; - if ( m_dump ) ++m_dumped; - - std::unique_ptr<MuonSegmentCombinationCollection> pcols(new MuonSegmentCombinationCollection); - if ( segcols.empty() ){ - pcols.reset(); - return pcols; - } - - for ( MuonSegmentCombinationCollection::const_iterator icom=segcols.begin(); - icom!=segcols.end(); ++icom ) { - const MuonSegmentCombination& insegs = **icom; + // Set dump flag. + m_dump = m_dumped < m_dumpcount || m_dumpcount < 0; + if (m_dump) ++m_dumped; - int nsta = insegs.numberOfStations(); - if ( nsta != 2 ) { // This can be happened if segment is not made at all in case of two hit layers !! - // NOW, 2d segment is not made.... - // ATH_MSG_FATAL ( " Combination has " << nsta << " stations where 2 are expected" ); - return pcols; + std::unique_ptr<MuonSegmentCombinationCollection> pcols(new MuonSegmentCombinationCollection); + if (segcols.empty()) { + pcols.reset(); + return pcols; } - ATH_MSG_DEBUG ( "Csc4dSegmentMaker called get4dMuonSegmentCombination"); - - MuonSegmentCombination* pcol = m_segmentTool->get4dMuonSegmentCombination( &insegs ); - if (pcol) { - pcols->push_back(pcol); - ATH_MSG_DEBUG("Found 4d CSC segment " << std::endl << m_printer->print( *pcol )); - } - } + for (MuonSegmentCombinationCollection::const_iterator icom = segcols.begin(); icom != segcols.end(); ++icom) { + const MuonSegmentCombination& insegs = **icom; + + int nsta = insegs.numberOfStations(); + if (nsta != 2) { // This can be happened if segment is not made at all in case of two hit layers !! + // NOW, 2d segment is not made.... + // ATH_MSG_FATAL ( " Combination has " << nsta << " stations where 2 are expected" ); + return pcols; + } - ATH_MSG_DEBUG ( " Created " << pcols->size() << " 4D segments." ); - return pcols; + ATH_MSG_DEBUG("Csc4dSegmentMaker called get4dMuonSegmentCombination"); + MuonSegmentCombination* pcol = m_segmentTool->get4dMuonSegmentCombination(&insegs); + if (pcol) { + pcols->push_back(pcol); + ATH_MSG_DEBUG("Found 4d CSC segment " << std::endl << m_printer->print(*pcol)); + } + } + + ATH_MSG_DEBUG(" Created " << pcols->size() << " 4D segments."); + return pcols; } //****************************************************************************** -StatusCode Csc4dSegmentMaker::finalize() { - ATH_MSG_DEBUG ( "Goodbye" ); - return StatusCode::SUCCESS; +StatusCode +Csc4dSegmentMaker::finalize() +{ + ATH_MSG_DEBUG("Goodbye"); + return StatusCode::SUCCESS; } //****************************************************************************** -//dummy ICscSegmentFinder interface -std::unique_ptr<MuonSegmentCombinationCollection> Csc4dSegmentMaker::find(const std::vector<const Muon::CscPrepDataCollection*>& ) const { - return 0; +// dummy ICscSegmentFinder interface +std::unique_ptr<MuonSegmentCombinationCollection> +Csc4dSegmentMaker::find(const std::vector<const Muon::CscPrepDataCollection*>&) const +{ + return 0; } diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/Csc4dSegmentMaker.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/Csc4dSegmentMaker.h index 7e2602a938ed9f948196b5d923495cb961c9ff92..d4059a03d8efd545860905ef35dd602d97194f77 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/Csc4dSegmentMaker.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/Csc4dSegmentMaker.h @@ -12,63 +12,69 @@ // each chamber (with segments) and separate r and phi collections // for each combination. +#include <atomic> + #include "AthenaBaseComps/AthAlgTool.h" +#include "CscSegmentMakers/ICscSegmentFinder.h" //including MuonSegmentCombination(Collection).h CscPrepDataContainer.h" #include "GaudiKernel/ToolHandle.h" -#include "MuonIdHelpers/IMuonIdHelperSvc.h" #include "Identifier/Identifier.h" -#include "CscSegmentMakers/ICscSegmentFinder.h" //including MuonSegmentCombination(Collection).h CscPrepDataContainer.h" - -#include <atomic> +#include "MuonIdHelpers/IMuonIdHelperSvc.h" class ICscSegmentUtilTool; namespace Track { - class TrackRaod; - class RIO_OnTrack; -} +class TrackRaod; +class RIO_OnTrack; +} // namespace Track namespace Muon { - class MdtDriftCircleOnTrack; - class MuonClusterOnTrack; - class MuonEDMPrinterTool; - class MuonSegment; -} +class MdtDriftCircleOnTrack; +class MuonClusterOnTrack; +class MuonEDMPrinterTool; +class MuonSegment; +} // namespace Muon class Csc4dSegmentMaker : virtual public ICscSegmentFinder, public AthAlgTool { -public: // methods - - // Constructor. - Csc4dSegmentMaker(const std::string&, const std::string&, const IInterface*); - - // Destructor. - ~Csc4dSegmentMaker(); - - // Initialization. - StatusCode initialize(); - - // Finalization. - StatusCode finalize(); - - std::unique_ptr<MuonSegmentCombinationCollection> find( const MuonSegmentCombinationCollection& ) const ; - std::unique_ptr<MuonSegmentCombinationCollection> find( const std::vector<const Muon::CscPrepDataCollection*>& pcols) const; //not used here - -private: // data - - // Properties. - // Number of events dumped. - int m_dumpcount; - mutable std::atomic_int m_dumped; - // Debug flags. - mutable std::atomic_bool m_dump; - double m_max_chisquare; - double m_max_slope_r; - double m_max_slope_phi; - double m_max_seg_per_chamber; - - ToolHandle<ICscSegmentUtilTool> m_segmentTool; - ToolHandle<Muon::MuonEDMPrinterTool> m_printer; - + public: // methods + // Constructor. + Csc4dSegmentMaker(const std::string&, const std::string&, const IInterface*); + + // Destructor. + ~Csc4dSegmentMaker(); + + // Initialization. + StatusCode initialize(); + + // Finalization. + StatusCode finalize(); + + std::unique_ptr<MuonSegmentCombinationCollection> find(const MuonSegmentCombinationCollection&) const; + std::unique_ptr<MuonSegmentCombinationCollection> find( + const std::vector<const Muon::CscPrepDataCollection*>& pcols) const; // not used here + + private: // data + // Properties. + // Number of events dumped. + int m_dumpcount; + mutable std::atomic_int m_dumped; + // Debug flags. + mutable std::atomic_bool m_dump; + double m_max_chisquare; + double m_max_slope_r; + double m_max_slope_phi; + double m_max_seg_per_chamber; + + ToolHandle<ICscSegmentUtilTool> m_segmentTool{ + this, + "segmentTool", + "CscSegmentUtilTool/CscSegmentUtilTool", + }; + ToolHandle<Muon::MuonEDMPrinterTool> m_printer{ + this, + "Printer", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; }; #endif diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/CscSegmentMaker.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/CscSegmentMaker.cxx index db5c08227a1e7c55f756c5d96e38de2b0424ecf6..5bdc89e2e8b37b6722286bdb15b79e492885a134 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/CscSegmentMaker.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/CscSegmentMaker.cxx @@ -1,13 +1,15 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ #include "CscSegmentMaker.h" + #include <sstream> -#include "xAODEventInfo/EventInfo.h" + #include "MuonPrepRawData/CscPrepDataContainer.h" #include "MuonSegment/MuonSegment.h" #include "MuonSegment/MuonSegmentCombinationCollection.h" +#include "xAODEventInfo/EventInfo.h" using Muon::CscPrepData; using Muon::CscPrepDataCollection; @@ -20,12 +22,12 @@ using Muon::CscPrepDataContainer; if ( station == 2 ) return "CSL"; return "UNKNOWN_STATION"; } - + std::string measphi_name(bool measphi) { if ( measphi ) return "phi"; return "eta"; } - + // Convert chamber identifier to string. std::string chamber(int istation, int zsec, int phi) { std::ostringstream ssout; @@ -38,154 +40,136 @@ using Muon::CscPrepDataContainer; ssout << phi; return ssout.str(); } - + }*/ //****************************************************************************** -CscSegmentMaker:: -CscSegmentMaker(const std::string& aname, ISvcLocator* pSvcLocator) - : AthAlgorithm(aname, pSvcLocator), - m_dumped(0), m_dump(false), - m_2dseg_finder(""), - m_4dseg_finder(""), - m_psegs(std::unique_ptr<MuonSegmentCombinationCollection>()), - m_psegs4d(std::unique_ptr<MuonSegmentCombinationCollection>()) +CscSegmentMaker::CscSegmentMaker(const std::string& aname, ISvcLocator* pSvcLocator) + : AthAlgorithm(aname, pSvcLocator), + m_dumped(0), + m_dump(false), + m_psegs(std::unique_ptr<MuonSegmentCombinationCollection>()), + m_psegs4d(std::unique_ptr<MuonSegmentCombinationCollection>()) { - declareProperty("dump_count", m_dumpcount =5); - declareProperty("sg_inkey", m_sg_inkey = ""); - declareProperty("sg_2d_outkey", m_sg_outkey = ""); - declareProperty("sg_4d_outkey", m_sg_4d_outkey = ""); - declareProperty("segfinder_2d", m_2dseg_finder); - declareProperty("segfinder_4d", m_4dseg_finder); + declareProperty("dump_count", m_dumpcount = 5); + declareProperty("sg_inkey", m_sg_inkey = ""); + declareProperty("sg_2d_outkey", m_sg_outkey = ""); + declareProperty("sg_4d_outkey", m_sg_4d_outkey = ""); } //****************************************************************************** // Destructor. -CscSegmentMaker::~CscSegmentMaker() { -} +CscSegmentMaker::~CscSegmentMaker() {} //****************************************************************************** -StatusCode CscSegmentMaker::initialize(){ - - ATH_MSG_INFO ( "Initializing " << name() ); - - ATH_MSG_INFO ( " Dump count: " << m_dumpcount ); - // Show keys. - ATH_MSG_INFO ( " Input SG key: " << m_sg_inkey ); - ATH_MSG_INFO ( " Output SG key for 2D Segment: " << m_sg_outkey ); - ATH_MSG_INFO ( " Output SG key for 4D Segment: " << m_sg_4d_outkey ); - - ATH_MSG_INFO ( " 2D Segment Finder is " << m_2dseg_finder.typeAndName() ); - ATH_MSG_INFO ( " 4D Segment Finder is " << m_4dseg_finder.typeAndName() ); - - - // Retrieve the Segment Finder tool. - if ( m_2dseg_finder.retrieve().isFailure() ) { - ATH_MSG_FATAL ( "Unable to retrieve 2dseg_finder tool " - << m_2dseg_finder ); - return StatusCode::FAILURE; - } else { - ATH_MSG_DEBUG ( "Retrieved 2dseg finder tool " - << m_2dseg_finder ); - } - - // Retrieve the Segment Finder tool. - if ( m_4dseg_finder.retrieve().isFailure() ) { - ATH_MSG_FATAL ( "Unable to retrieve 4dseg_finder tool " - << m_4dseg_finder ); - return StatusCode::FAILURE; - } else { - ATH_MSG_DEBUG ( "Retrieved 4dseg finder tool " - << m_4dseg_finder ); - } - - - return StatusCode::SUCCESS; +StatusCode +CscSegmentMaker::initialize() +{ + + ATH_MSG_INFO("Initializing " << name()); + + ATH_MSG_INFO(" Dump count: " << m_dumpcount); + // Show keys. + ATH_MSG_INFO(" Input SG key: " << m_sg_inkey); + ATH_MSG_INFO(" Output SG key for 2D Segment: " << m_sg_outkey); + ATH_MSG_INFO(" Output SG key for 4D Segment: " << m_sg_4d_outkey); + + ATH_MSG_INFO(" 2D Segment Finder is " << m_2dseg_finder.typeAndName()); + ATH_MSG_INFO(" 4D Segment Finder is " << m_4dseg_finder.typeAndName()); + + + // Retrieve the Segment Finder tool. + ATH_CHECK(m_2dseg_finder.retrieve()); + ATH_MSG_DEBUG("Retrieved 2dseg finder tool " << m_2dseg_finder); + + // Retrieve the Segment Finder tool. + ATH_CHECK(m_4dseg_finder.retrieve()); + ATH_MSG_DEBUG("Retrieved 4dseg finder tool " << m_4dseg_finder); + + return StatusCode::SUCCESS; } //****************************************************************************** -StatusCode CscSegmentMaker::execute(){ - - m_dump = m_dumped < m_dumpcount || m_dumpcount < 0; - if ( m_dump ) ++m_dumped; - - StatusCode sc = StatusCode::SUCCESS; - // Get event info. - const xAOD::EventInfo* pevt = 0; - StatusCode sc_ev = evtStore()->retrieve(pevt, ""); - int evt = pevt->eventNumber(); - int run = pevt->runNumber(); - if ( m_dump ) - ATH_MSG_DEBUG ( "Processing run " << run - << ", event " << evt ); - - /////////// - // Build Segment - sc = build_segments(); - if (sc.isFailure()) { - ATH_MSG_ERROR ( " Failed to build segments " ); - } +StatusCode +CscSegmentMaker::execute() +{ - sc = evtStore()->record(m_psegs.release(), m_sg_outkey); - if (sc.isFailure()) { - ATH_MSG_ERROR ( " Cannot record CSC segment collection " << m_sg_outkey ); - } else { - if ( m_dump ) - ATH_MSG_DEBUG ( " Created " << m_psegs->size() << " 2D segments and " ); - } - - sc = evtStore()->record(m_psegs4d.release(), m_sg_4d_outkey); - if (sc.isFailure()) { - ATH_MSG_ERROR ( " Cannot record CSC segment collection " << m_sg_4d_outkey ); - } else { - if ( m_dump ) - ATH_MSG_DEBUG ( m_psegs4d->size() << " 4D segments." ); - } - - return StatusCode::SUCCESS; + m_dump = m_dumped < m_dumpcount || m_dumpcount < 0; + if (m_dump) ++m_dumped; + + StatusCode sc = StatusCode::SUCCESS; + // Get event info. + const xAOD::EventInfo* pevt = 0; + StatusCode sc_ev = evtStore()->retrieve(pevt, ""); + int evt = pevt->eventNumber(); + int run = pevt->runNumber(); + if (m_dump) ATH_MSG_DEBUG("Processing run " << run << ", event " << evt); + + /////////// + // Build Segment + sc = build_segments(); + if (sc.isFailure()) { + ATH_MSG_ERROR(" Failed to build segments "); + } + sc = evtStore()->record(m_psegs.release(), m_sg_outkey); + if (sc.isFailure()) { + ATH_MSG_ERROR(" Cannot record CSC segment collection " << m_sg_outkey); + } else { + if (m_dump) ATH_MSG_DEBUG(" Created " << m_psegs->size() << " 2D segments and "); + } + + sc = evtStore()->record(m_psegs4d.release(), m_sg_4d_outkey); + if (sc.isFailure()) { + ATH_MSG_ERROR(" Cannot record CSC segment collection " << m_sg_4d_outkey); + } else { + if (m_dump) ATH_MSG_DEBUG(m_psegs4d->size() << " 4D segments."); + } + + return StatusCode::SUCCESS; } //****************************************************************************** -StatusCode CscSegmentMaker::build_segments() { - // Retrieve the container. - const CscPrepDataContainer* pcols = nullptr; - StatusCode status = evtStore()->retrieve(pcols, m_sg_inkey); - - if ( m_dump ) - ATH_MSG_DEBUG ( "Retrieved " << pcols->size() - << " CSC cluster collections."); - - // Chambers incols; - if ( status.isSuccess() ) { - std::vector<const CscPrepDataCollection*> myclus; - for ( CscPrepDataContainer::const_iterator icol=pcols->begin(); - icol!=pcols->end(); ++icol ) - myclus.push_back(*icol); - - ATH_MSG_DEBUG ("CscSegmentMaker called find!!"); - m_psegs = m_2dseg_finder->find(myclus); - // Construct output segment collection. - ATH_MSG_DEBUG ("CscSegmentMaker called find!!"); - if (m_psegs) { - if (m_psegs->size() > 1) { - m_psegs4d = m_4dseg_finder->find(*m_psegs); - } +StatusCode +CscSegmentMaker::build_segments() +{ + // Retrieve the container. + const CscPrepDataContainer* pcols = nullptr; + StatusCode status = evtStore()->retrieve(pcols, m_sg_inkey); + + if (m_dump) ATH_MSG_DEBUG("Retrieved " << pcols->size() << " CSC cluster collections."); + + // Chambers incols; + if (status.isSuccess()) { + std::vector<const CscPrepDataCollection*> myclus; + for (CscPrepDataContainer::const_iterator icol = pcols->begin(); icol != pcols->end(); ++icol) + myclus.push_back(*icol); + + ATH_MSG_DEBUG("CscSegmentMaker called find!!"); + m_psegs = m_2dseg_finder->find(myclus); + // Construct output segment collection. + ATH_MSG_DEBUG("CscSegmentMaker called find!!"); + if (m_psegs) { + if (m_psegs->size() > 1) { + m_psegs4d = m_4dseg_finder->find(*m_psegs); + } + } } - } - return StatusCode::SUCCESS; + return StatusCode::SUCCESS; } //****************************************************************************** -StatusCode CscSegmentMaker::finalize() { - ATH_MSG_DEBUG ( "Goodbye" ); - return StatusCode::SUCCESS; +StatusCode +CscSegmentMaker::finalize() +{ + ATH_MSG_DEBUG("Goodbye"); + return StatusCode::SUCCESS; } - + //****************************************************************************** diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/CscSegmentMaker.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/CscSegmentMaker.h index 639661ada01dbc714a0417f84baa7565ade6e2b8..eb3cb85f28ef90d27ae16c48b37d7874eb12560a 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/CscSegmentMaker.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerAlgs/CscSegmentMakers/src/CscSegmentMaker.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ // Csc2dSegmentMaker.h @@ -14,58 +14,62 @@ // for each combination. #include "AthenaBaseComps/AthAlgorithm.h" +#include "CscSegmentMakers/ICscSegmentFinder.h" // MuonSegmentCombinationCollection.h MuonSegmentCombination.h included #include "GaudiKernel/ToolHandle.h" #include "Identifier/Identifier.h" -#include "CscSegmentMakers/ICscSegmentFinder.h" // MuonSegmentCombinationCollection.h MuonSegmentCombination.h included namespace Muon { - class CscPrepData; +class CscPrepData; } class CscSegmentMaker : public AthAlgorithm { - -public: // methods - // Constructor. - CscSegmentMaker(const std::string& name, ISvcLocator* pSvcLocator); + public: // methods + // Constructor. + CscSegmentMaker(const std::string& name, ISvcLocator* pSvcLocator); - // Destructor. - ~CscSegmentMaker(); + // Destructor. + ~CscSegmentMaker(); - // Initialization. - StatusCode initialize(); + // Initialization. + StatusCode initialize(); - // Event processing. - StatusCode execute(); + // Event processing. + StatusCode execute(); - // Finalization. - StatusCode finalize(); + // Finalization. + StatusCode finalize(); - -private: // methods - StatusCode build_segments(); - -private: // data + private: // methods + StatusCode build_segments(); - // Number of events dumped. - int m_dumped; - // Debug flags. - bool m_dump; - int m_dumpcount; + private: // data + // Number of events dumped. + int m_dumped; + // Debug flags. + bool m_dump; + int m_dumpcount; - // Properties. - std::string m_sg_inkey; - std::string m_sg_outkey; - std::string m_sg_4d_outkey; + // Properties. + std::string m_sg_inkey; + std::string m_sg_outkey; + std::string m_sg_4d_outkey; - ToolHandle<ICscSegmentFinder> m_2dseg_finder; - ToolHandle<ICscSegmentFinder> m_4dseg_finder; - - // Output container. - std::unique_ptr<MuonSegmentCombinationCollection> m_psegs; - std::unique_ptr<MuonSegmentCombinationCollection> m_psegs4d; + ToolHandle<ICscSegmentFinder> m_2dseg_finder{ + this, + "segfinder_2d", + "", + }; + ToolHandle<ICscSegmentFinder> m_4dseg_finder{ + this, + "segfinder_4d", + "", + }; + // Output container. + std::unique_ptr<MuonSegmentCombinationCollection> m_psegs; + std::unique_ptr<MuonSegmentCombinationCollection> m_psegs4d; }; #endif diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/DCMathSegmentMaker.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/DCMathSegmentMaker.cxx index d1af1e1313340fa2b5d76430f6bc4154431c9558..37f2995317c4807a0938169251f1e4ce8ebdeddb 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/DCMathSegmentMaker.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/DCMathSegmentMaker.cxx @@ -4,148 +4,137 @@ #include "DCMathSegmentMaker.h" +#include <cassert> +#include <functional> +#include <iostream> + #include "AthenaKernel/Timeout.h" -#include "TrkRIO_OnTrack/RIO_OnTrack.h" -#include "MuonSegment/MuonSegmentQuality.h" -#include "TrkEventPrimitives/LocalDirection.h" -#include "TrkEventPrimitives/DefinedParameter.h" -#include "TrkEventPrimitives/LocalParameters.h" -#include "TrkEventPrimitives/JacobianCotThetaPtToThetaP.h" -#include "TrkEventPrimitives/ParamDefs.h" -#include "TrkEventPrimitives/FitQuality.h" -#include "TrkRoad/TrackRoad.h" -#include "TrkTrack/Track.h" -#include "TrkParameters/TrackParameters.h" -#include "TrkSurfaces/StraightLineSurface.h" -#include "TrkSurfaces/PlaneSurface.h" -#include "TrkDriftCircleMath/SegmentFinder.h" -#include "TrkDriftCircleMath/Road.h" -#include "TrkDriftCircleMath/Segment.h" -#include "TrkDriftCircleMath/DriftCircle.h" -#include "TrkDriftCircleMath/ClusterId.h" -#include "TrkDriftCircleMath/ResidualWithSegment.h" -#include "TrkDriftCircleMath/MdtStationId.h" -#include "TrkDriftCircleMath/MdtMultiChamberGeometry.h" +#include "EventPrimitives/EventPrimitivesHelpers.h" +#include "EventPrimitives/EventPrimitivesToStringConverter.h" +#include "GeoPrimitives/GeoPrimitivesToStringConverter.h" +#include "MuonCompetingRIOsOnTrack/CompetingMuonClustersOnTrack.h" #include "MuonPrepRawData/MdtPrepData.h" #include "MuonPrepRawData/RpcPrepData.h" #include "MuonPrepRawData/TgcPrepData.h" #include "MuonRIO_OnTrack/MdtDriftCircleOnTrack.h" #include "MuonRIO_OnTrack/RpcClusterOnTrack.h" #include "MuonRIO_OnTrack/TgcClusterOnTrack.h" -#include "MuonCompetingRIOsOnTrack/CompetingMuonClustersOnTrack.h" #include "MuonReadoutGeometry/MdtReadoutElement.h" -#include "MuonReadoutGeometry/RpcReadoutElement.h" #include "MuonReadoutGeometry/MuonDetectorManager.h" -#include "EventPrimitives/EventPrimitivesHelpers.h" -#include "EventPrimitives/EventPrimitivesToStringConverter.h" -#include "GeoPrimitives/GeoPrimitivesToStringConverter.h" - -#include <cassert> -#include <iostream> -#include <functional> +#include "MuonReadoutGeometry/RpcReadoutElement.h" +#include "MuonSegment/MuonSegmentQuality.h" +#include "TrkDriftCircleMath/ClusterId.h" +#include "TrkDriftCircleMath/DriftCircle.h" +#include "TrkDriftCircleMath/MdtMultiChamberGeometry.h" +#include "TrkDriftCircleMath/MdtStationId.h" +#include "TrkDriftCircleMath/ResidualWithSegment.h" +#include "TrkDriftCircleMath/Road.h" +#include "TrkDriftCircleMath/Segment.h" +#include "TrkDriftCircleMath/SegmentFinder.h" +#include "TrkEventPrimitives/DefinedParameter.h" +#include "TrkEventPrimitives/FitQuality.h" +#include "TrkEventPrimitives/JacobianCotThetaPtToThetaP.h" +#include "TrkEventPrimitives/LocalDirection.h" +#include "TrkEventPrimitives/LocalParameters.h" +#include "TrkEventPrimitives/ParamDefs.h" +#include "TrkParameters/TrackParameters.h" +#include "TrkRIO_OnTrack/RIO_OnTrack.h" +#include "TrkRoad/TrackRoad.h" +#include "TrkSurfaces/PlaneSurface.h" +#include "TrkSurfaces/StraightLineSurface.h" +#include "TrkTrack/Track.h" namespace Muon { - DCMathSegmentMaker::DCMathSegmentMaker( const std::string& t, const std::string& n, const IInterface* p ) : - AthAlgTool(t,n,p), - m_intersectSvc("MuonStationIntersectSvc", name()), - m_mdtCreator("Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator", this), - m_mdtCreatorT0("Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator", this), - m_clusterCreator("Muon::MuonClusterOnTrackCreator/MuonClusterOnTrackCreator", this), - m_compClusterCreator("Muon::TriggerChamberClusterOnTrackCreator/TriggerChamberClusterOnTrackCreator", this), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"), - m_segmentFinder("Muon::MdtMathSegmentFinder/MdtMathSegmentFinder", this), - m_segmentFitter("Muon::MuonSegmentFittingTool/MuonSegmentFittingTool", this), - m_segmentSelectionTool("Muon::MuonSegmentSelectionTool/MuonSegmentSelectionTool", this), - m_dcslFitProvider("", this), - m_rpcKey("RPC_Measurements"), - m_tgcKey("TGC_Measurements"), - m_mdtKey("MDT_DriftCircles") - { +DCMathSegmentMaker::DCMathSegmentMaker(const std::string& t, const std::string& n, const IInterface* p) + : AthAlgTool(t, n, p), + m_intersectSvc("MuonStationIntersectSvc", name()), + m_rpcKey("RPC_Measurements"), + m_tgcKey("TGC_Measurements"), + m_mdtKey("MDT_DriftCircles") +{ declareInterface<IMuonSegmentMaker>(this); declareInterface<IMuonSegmentTriggerHitAssociator>(this); declareProperty("MuonStationIntersectSvc", m_intersectSvc); - declareProperty("MdtCreator", m_mdtCreator); - declareProperty("MdtCreatorT0", m_mdtCreatorT0); - declareProperty("MuonClusterCreator", m_clusterCreator); - declareProperty("MuonCompetingClustersCreator", m_compClusterCreator); - declareProperty("EDMPrinter", m_printer); - declareProperty("MdtSegmentFinder", m_segmentFinder); - declareProperty("SegmentFitter", m_segmentFitter); - declareProperty("SegmentSelector", m_segmentSelectionTool); - declareProperty("DCFitProvider", m_dcslFitProvider ); - declareProperty("SinAngleCut",m_sinAngleCut = 0.2); - declareProperty("DoGeometry",m_doGeometry = true); - declareProperty("DoDebugSpacePoints",m_debugSpacePoints = false); - declareProperty("CurvedErrorScaling",m_curvedErrorScaling = true); - declareProperty("UseTriggerSpacePoints",m_doSpacePoints = true); - declareProperty("CreateCompetingROTsPhi",m_createCompetingROTsPhi = true); - declareProperty("CreateCompetingROTsEta",m_createCompetingROTsEta = true); - declareProperty("RefitSegment",m_refitParameters = false); - declareProperty("AddUnassociatedPhiHits",m_addUnassociatedPhiHits = false); - declareProperty("StrictRoadDirectionConsistencyCheck",m_strictRoadDirectionConsistencyCheck = true); - declareProperty("MaxAssociateClusterDistance",m_maxAssociateClusterDistance=3000); - declareProperty("AllMdtHoles",m_allMdtHoles = false, "flag to decide whether to apply bound checks during the hole search"); - declareProperty("RemoveDeltasFromSegmentQuality",m_removeDeltas = true, "flag to decide whether add deltas to SegmentSummary"); - declareProperty("Reject1DTgcSpacePoints",m_reject1DTgcSpacePoints = true ,"reject TGC eta hits that are not associated with a phi hit in the same gas gap" ); - declareProperty("UsePreciseError",m_usePreciseError = false ); - declareProperty("PreciseErrorScale",m_preciseErrorScale = 2. ); - declareProperty("OutputFittedT0",m_outputFittedT0 = false ); - declareProperty("UseTimeOutGard",m_doTimeOutChecks = true ); - declareProperty("RecoverBadRpcCabling",m_recoverBadRpcCabling = false ); - declareProperty("UpdatePhiUsingPhiHits",m_updatePhiUsingPhiHits = false ); - declareProperty("AssumePointingPhi",m_assumePointingPhi = false ); - declareProperty("Redo2DFit", m_redo2DFit = true ); + declareProperty("SinAngleCut", m_sinAngleCut = 0.2); + declareProperty("DoGeometry", m_doGeometry = true); + declareProperty("DoDebugSpacePoints", m_debugSpacePoints = false); + declareProperty("CurvedErrorScaling", m_curvedErrorScaling = true); + declareProperty("UseTriggerSpacePoints", m_doSpacePoints = true); + declareProperty("CreateCompetingROTsPhi", m_createCompetingROTsPhi = true); + declareProperty("CreateCompetingROTsEta", m_createCompetingROTsEta = true); + declareProperty("RefitSegment", m_refitParameters = false); + declareProperty("AddUnassociatedPhiHits", m_addUnassociatedPhiHits = false); + declareProperty("StrictRoadDirectionConsistencyCheck", m_strictRoadDirectionConsistencyCheck = true); + declareProperty("MaxAssociateClusterDistance", m_maxAssociateClusterDistance = 3000); + declareProperty("AllMdtHoles", m_allMdtHoles = false, + "flag to decide whether to apply bound checks during the hole search"); + declareProperty("RemoveDeltasFromSegmentQuality", m_removeDeltas = true, + "flag to decide whether add deltas to SegmentSummary"); + declareProperty("Reject1DTgcSpacePoints", m_reject1DTgcSpacePoints = true, + "reject TGC eta hits that are not associated with a phi hit in the same gas gap"); + declareProperty("UsePreciseError", m_usePreciseError = false); + declareProperty("PreciseErrorScale", m_preciseErrorScale = 2.); + declareProperty("OutputFittedT0", m_outputFittedT0 = false); + declareProperty("UseTimeOutGard", m_doTimeOutChecks = true); + declareProperty("RecoverBadRpcCabling", m_recoverBadRpcCabling = false); + declareProperty("UpdatePhiUsingPhiHits", m_updatePhiUsingPhiHits = false); + declareProperty("AssumePointingPhi", m_assumePointingPhi = false); + declareProperty("Redo2DFit", m_redo2DFit = true); declareProperty("RpcPrepDataContainer", m_rpcKey); declareProperty("TgcPrepDataContainer", m_tgcKey); declareProperty("MdtPrepDataContainer", m_mdtKey); - } +} - StatusCode DCMathSegmentMaker::initialize() - { +StatusCode +DCMathSegmentMaker::initialize() +{ // retrieve MuonDetectorManager ATH_CHECK(m_DetectorManagerKey.initialize()); - ATH_CHECK( m_intersectSvc.retrieve() ); - ATH_CHECK( m_mdtCreator.retrieve() ); - ATH_CHECK( m_mdtCreatorT0.retrieve() ); - ATH_CHECK( m_compClusterCreator.retrieve() ); - ATH_CHECK( m_idHelperSvc.retrieve() ); - ATH_CHECK( m_printer.retrieve() ); - ATH_CHECK( m_edmHelperSvc.retrieve() ); - ATH_CHECK( m_segmentFinder.retrieve() ); - ATH_CHECK( m_segmentSelectionTool.retrieve() ); - - if( m_refitParameters ){ - ATH_CHECK( m_segmentFitter.retrieve() ); - } - - if( !m_dcslFitProvider.empty() ){ - ATH_CHECK( m_dcslFitProvider.retrieve() ); - ATH_MSG_INFO(" Using " << m_dcslFitProvider); - } - - //initialise for data handles + ATH_CHECK(m_intersectSvc.retrieve()); + ATH_CHECK(m_mdtCreator.retrieve()); + ATH_CHECK(m_mdtCreatorT0.retrieve()); + ATH_CHECK(m_clusterCreator.retrieve()); + ATH_CHECK(m_compClusterCreator.retrieve()); + ATH_CHECK(m_idHelperSvc.retrieve()); + ATH_CHECK(m_printer.retrieve()); + ATH_CHECK(m_edmHelperSvc.retrieve()); + ATH_CHECK(m_segmentFinder.retrieve()); + ATH_CHECK(m_segmentSelectionTool.retrieve()); + + if (m_refitParameters) { + ATH_CHECK(m_segmentFitter.retrieve()); + } + + if (!m_dcslFitProvider.empty()) { + ATH_CHECK(m_dcslFitProvider.retrieve()); + ATH_MSG_INFO(" Using " << m_dcslFitProvider); + } + + // initialise for data handles ATH_CHECK(m_rpcKey.initialize()); ATH_CHECK(m_tgcKey.initialize()); ATH_CHECK(m_mdtKey.initialize()); - if(!m_condKey.empty()) ATH_CHECK(m_condKey.initialize()); + if (!m_condKey.empty()) ATH_CHECK(m_condKey.initialize()); return StatusCode::SUCCESS; - } +} + +const MuonSegment* +DCMathSegmentMaker::associateTriggerHits(const MuonSegment& seg, const std::vector<const MuonClusterOnTrack*>& clus, + bool includeEtaHits) const +{ - const MuonSegment* DCMathSegmentMaker::associateTriggerHits( const MuonSegment& seg, const std::vector<const MuonClusterOnTrack*>& clus, - bool includeEtaHits ) const { - - ATH_MSG_DEBUG("associateTriggerHits: clusters " << clus.size() ); + ATH_MSG_DEBUG("associateTriggerHits: clusters " << clus.size()); // extract hits - std::vector<const MdtDriftCircleOnTrack*> mdts; - std::vector<const Trk::MeasurementBase*>::const_iterator hit = seg.containedMeasurements().begin(); + std::vector<const MdtDriftCircleOnTrack*> mdts; + std::vector<const Trk::MeasurementBase*>::const_iterator hit = seg.containedMeasurements().begin(); std::vector<const Trk::MeasurementBase*>::const_iterator hit_end = seg.containedMeasurements().end(); - for( ;hit!=hit_end;++hit ){ - const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(*hit); - if( mdt ) mdts.push_back(mdt); + for (; hit != hit_end; ++hit) { + const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(*hit); + if (mdt) mdts.push_back(mdt); } // global to local transformation for chamber @@ -153,41 +142,42 @@ namespace Muon { // set to get Identifiers of chambers with hits std::set<Identifier> chamberSet; - for( std::vector<const MdtDriftCircleOnTrack*>::const_iterator it=mdts.begin();it!=mdts.end();++it){ - Identifier dcid = (*it)->identify(); - Identifier elId = m_idHelperSvc->mdtIdHelper().elementID( dcid ); - chamberSet.insert(elId); + for (std::vector<const MdtDriftCircleOnTrack*>::const_iterator it = mdts.begin(); it != mdts.end(); ++it) { + Identifier dcid = (*it)->identify(); + Identifier elId = m_idHelperSvc->mdtIdHelper().elementID(dcid); + chamberSet.insert(elId); } std::unique_ptr<TrkDriftCircleMath::MdtMultiChamberGeometry> multiGeo; - if( m_doGeometry ) { - // vector to store chamber geometries - std::vector<TrkDriftCircleMath::MdtChamberGeometry> geos; + if (m_doGeometry) { + // vector to store chamber geometries + std::vector<TrkDriftCircleMath::MdtChamberGeometry> geos; - // loop over chambers - std::set<Identifier>::iterator it = chamberSet.begin(); - std::set<Identifier>::iterator it_end = chamberSet.end(); - for( ;it!=it_end;++it ){ - geos.push_back( createChamberGeometry( *it, gToStation ) ); - } + // loop over chambers + std::set<Identifier>::iterator it = chamberSet.begin(); + std::set<Identifier>::iterator it_end = chamberSet.end(); + for (; it != it_end; ++it) { + geos.push_back(createChamberGeometry(*it, gToStation)); + } - // create new geometry - multiGeo = std::unique_ptr<TrkDriftCircleMath::MdtMultiChamberGeometry>(new TrkDriftCircleMath::MdtMultiChamberGeometry(geos)); + // create new geometry + multiGeo = std::unique_ptr<TrkDriftCircleMath::MdtMultiChamberGeometry>( + new TrkDriftCircleMath::MdtMultiChamberGeometry(geos)); } - if( mdts.size() < 2 )return 0; + if (mdts.size() < 2) return 0; const MdtDriftCircleOnTrack* firstRot = findFirstRotInChamberWithMostHits(mdts); - if( !firstRot ) { - return 0; + if (!firstRot) { + return 0; } const MuonGM::MdtReadoutElement* detEl = firstRot->detectorElement(); - if( !detEl ) { - ATH_MSG_WARNING(" no MdtReadoutElement found, returning 0 "); - return 0; + if (!detEl) { + ATH_MSG_WARNING(" no MdtReadoutElement found, returning 0 "); + return 0; } - + // identifier Identifier chid = firstRot->identify(); @@ -197,213 +187,219 @@ namespace Muon { // define axis of chamber in global coordinates Amg::Transform3D amdbToGlobal = seg.associatedSurface().transform(); - std::vector<const MuonClusterOnTrack*> clusters = clus; + std::vector<const MuonClusterOnTrack*> clusters = clus; std::vector<const Trk::MeasurementBase*> measToBeDeleted; // if requested, retrieve trigger eta hits - if( includeEtaHits ) { - measToBeDeleted=addEtaHits(clusters,isEndcap); - ATH_MSG_DEBUG("adding eta hits: original clusters " << clus.size() << " extended " << clusters.size() ); + if (includeEtaHits) { + measToBeDeleted = addEtaHits(clusters, isEndcap); + ATH_MSG_DEBUG("adding eta hits: original clusters " << clus.size() << " extended " << clusters.size()); } /* ***** create cluster hits ******** */ ClusterVecPair spVecs; - if( m_doSpacePoints ) spVecs = create2DClusters( clusters ); - else spVecs = create1DClusters( clusters ); - TrkDriftCircleMath::CLVec cls = createClusterVec( chid, spVecs.first, gToStation ); - + if (m_doSpacePoints) + spVecs = create2DClusters(clusters); + else + spVecs = create1DClusters(clusters); + TrkDriftCircleMath::CLVec cls = createClusterVec(chid, spVecs.first, gToStation); + /* ***** create MDT hits ************ */ ATH_MSG_DEBUG(" adding mdts " << mdts.size()); TrkDriftCircleMath::DCOnTrackVec dcs; // reset chamber statistics - bool firstMdt = true; - double phimin = 9999.; - double phimax = -9999.; - unsigned index = 0; - std::vector<const Trk::MeasurementBase*>::const_iterator it = seg.containedMeasurements().begin(); - std::vector<const Trk::MeasurementBase*>::const_iterator it_end = seg.containedMeasurements().end(); - for( ;it!=it_end;++it){ - - const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(*it); - - if( !mdt ){ - continue; - } - Identifier id = mdt->identify(); - - // calculate local AMDB position - Amg::Vector3D locPos = gToStation*mdt->prepRawData()->globalPosition(); - TrkDriftCircleMath::LocPos lpos(locPos.y(),locPos.z()); - - double r = mdt->localParameters()[Trk::locR]; - double dr = Amg::error(mdt->localCovariance(),Trk::locR); - - // create identifier - TrkDriftCircleMath::MdtId mdtid( m_idHelperSvc->mdtIdHelper().isBarrel(id),m_idHelperSvc->mdtIdHelper().multilayer(id)-1, - m_idHelperSvc->mdtIdHelper().tubeLayer(id)-1, m_idHelperSvc->mdtIdHelper().tube(id)-1 ); - - // create new DriftCircle - TrkDriftCircleMath::DriftCircle dc( lpos, r, dr, TrkDriftCircleMath::DriftCircle::InTime, mdtid, index, mdt ); - TrkDriftCircleMath::DCOnTrack dcOnTrack(dc,1.,1.); - ATH_MSG_VERBOSE(" new MDT hit " << m_idHelperSvc->toString( id ) << " x " << lpos.x() << " y " << lpos.y() ); - - TubeEnds tubeEnds = localTubeEnds(*mdt,gToStation,amdbToGlobal); - if( firstMdt ){ - phimin = tubeEnds.phimin; - phimax = tubeEnds.phimax; - firstMdt = false; - }else{ - updatePhiRanges(tubeEnds.phimin,tubeEnds.phimax,phimin,phimax); - } - - dcs.push_back( dcOnTrack ); - - ++index; - } - + bool firstMdt = true; + double phimin = 9999.; + double phimax = -9999.; + unsigned index = 0; + std::vector<const Trk::MeasurementBase*>::const_iterator it = seg.containedMeasurements().begin(); + std::vector<const Trk::MeasurementBase*>::const_iterator it_end = seg.containedMeasurements().end(); + for (; it != it_end; ++it) { + + const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(*it); + + if (!mdt) { + continue; + } + Identifier id = mdt->identify(); + + // calculate local AMDB position + Amg::Vector3D locPos = gToStation * mdt->prepRawData()->globalPosition(); + TrkDriftCircleMath::LocPos lpos(locPos.y(), locPos.z()); + + double r = mdt->localParameters()[Trk::locR]; + double dr = Amg::error(mdt->localCovariance(), Trk::locR); + + // create identifier + TrkDriftCircleMath::MdtId mdtid( + m_idHelperSvc->mdtIdHelper().isBarrel(id), m_idHelperSvc->mdtIdHelper().multilayer(id) - 1, + m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1, m_idHelperSvc->mdtIdHelper().tube(id) - 1); + + // create new DriftCircle + TrkDriftCircleMath::DriftCircle dc(lpos, r, dr, TrkDriftCircleMath::DriftCircle::InTime, mdtid, index, mdt); + TrkDriftCircleMath::DCOnTrack dcOnTrack(dc, 1., 1.); + ATH_MSG_VERBOSE(" new MDT hit " << m_idHelperSvc->toString(id) << " x " << lpos.x() << " y " << lpos.y()); + + TubeEnds tubeEnds = localTubeEnds(*mdt, gToStation, amdbToGlobal); + if (firstMdt) { + phimin = tubeEnds.phimin; + phimax = tubeEnds.phimax; + firstMdt = false; + } else { + updatePhiRanges(tubeEnds.phimin, tubeEnds.phimax, phimin, phimax); + } + + dcs.push_back(dcOnTrack); + + ++index; + } + // create line - double angleYZ = seg.localDirection().angleYZ(); - const Amg::Vector3D lpos = gToStation*seg.globalPosition(); - TrkDriftCircleMath::LocPos segPos(lpos.y(),lpos.z()); - TrkDriftCircleMath::Line segPars(segPos,angleYZ); + double angleYZ = seg.localDirection().angleYZ(); + const Amg::Vector3D lpos = gToStation * seg.globalPosition(); + TrkDriftCircleMath::LocPos segPos(lpos.y(), lpos.z()); + TrkDriftCircleMath::Line segPars(segPos, angleYZ); - const Trk::FitQuality* fq = seg.fitQuality(); - double chi2 = fq ? fq->chiSquared() : 0.; - int ndof = fq ? fq->numberDoF() : 1; + const Trk::FitQuality* fq = seg.fitQuality(); + double chi2 = fq ? fq->chiSquared() : 0.; + int ndof = fq ? fq->numberDoF() : 1; - TrkDriftCircleMath::Segment segment(segPars,dcs,chi2,ndof,Amg::error(seg.localCovariance(),Trk::locY), - Amg::error(seg.localCovariance(),Trk::theta)); + TrkDriftCircleMath::Segment segment(segPars, dcs, chi2, ndof, Amg::error(seg.localCovariance(), Trk::locY), + Amg::error(seg.localCovariance(), Trk::theta)); segment.clusters(cls); - segment.hitsOnTrack(6); // hack just putting a number above the cut of at least 2 + segment.hitsOnTrack(6); // hack just putting a number above the cut of at least 2 - segmentCreationInfo sInfo(spVecs,multiGeo.get(),gToStation,amdbToGlobal,phimin,phimax); - MuonSegment* newSeg = createSegment(segment,chid,seg.globalPosition(),seg.globalDirection(),mdts,true,sInfo); - for(std::vector<const Trk::MeasurementBase*>::iterator it=measToBeDeleted.begin(); it!=measToBeDeleted.end(); it++) - delete (*it); + segmentCreationInfo sInfo(spVecs, multiGeo.get(), gToStation, amdbToGlobal, phimin, phimax); + MuonSegment* newSeg = createSegment(segment, chid, seg.globalPosition(), seg.globalDirection(), mdts, true, sInfo); + for (std::vector<const Trk::MeasurementBase*>::iterator it = measToBeDeleted.begin(); it != measToBeDeleted.end(); + it++) + delete (*it); measToBeDeleted.clear(); - + return newSeg; - } - - std::vector<const Trk::MeasurementBase*> DCMathSegmentMaker::addEtaHits( std::vector<const MuonClusterOnTrack*>& clusters, bool isEndcap ) const { - - std::set<IdentifierHash> chIdHs; - std::vector<const Trk::MeasurementBase*> measurementsToBeDeleted; - std::vector<const MuonClusterOnTrack*>::iterator cit = clusters.begin(); +} + +std::vector<const Trk::MeasurementBase*> +DCMathSegmentMaker::addEtaHits(std::vector<const MuonClusterOnTrack*>& clusters, bool isEndcap) const +{ + + std::set<IdentifierHash> chIdHs; + std::vector<const Trk::MeasurementBase*> measurementsToBeDeleted; + std::vector<const MuonClusterOnTrack*>::iterator cit = clusters.begin(); std::vector<const MuonClusterOnTrack*>::iterator cit_end = clusters.end(); - for( ;cit!=cit_end;++cit ) chIdHs.insert((*cit)->collectionHash()); - ATH_MSG_VERBOSE("Number of collections " << chIdHs.size() ); - - if( isEndcap ){ - const Muon::TgcPrepDataContainer* prdContainer = 0; - SG::ReadHandle<Muon::TgcPrepDataContainer> TgcCont(m_tgcKey); - if( !TgcCont.isValid() ) { - ATH_MSG_WARNING("Cannot retrieve TgcPrepDataContainer "); - return measurementsToBeDeleted; - } - else { - prdContainer = TgcCont.cptr(); - } - if(!prdContainer){ - ATH_MSG_WARNING("No TGC prd container retrieved"); - return measurementsToBeDeleted; - } - - // loop over chambers and get collections - std::set<IdentifierHash>::const_iterator chit = chIdHs.begin(); - std::set<IdentifierHash>::const_iterator chit_end = chIdHs.end(); - for( ;chit!=chit_end;++chit ){ - auto collptr = prdContainer->indexFindPtr(*chit); - if( collptr == nullptr ) { - ATH_MSG_VERBOSE("Could not find collection "); - continue; - } - const TgcPrepDataCollection& col = *collptr; - ATH_MSG_VERBOSE("Found collection: " << m_idHelperSvc->toStringChamber(col.identify()) << " size " << col.size() ); - TgcPrepDataCollection::const_iterator hit = col.begin(); - TgcPrepDataCollection::const_iterator hit_end = col.end(); - for( ;hit!=hit_end;++hit ){ - // skip phi hits - if( m_idHelperSvc->measuresPhi((*hit)->identify()) ) continue; - - const MuonClusterOnTrack* clus = m_clusterCreator->createRIO_OnTrack(**hit,(*hit)->globalPosition()); - if( clus ) { - ATH_MSG_VERBOSE(" adding hit: " << m_idHelperSvc->toString(clus->identify()) ); - clusters.push_back(clus); - measurementsToBeDeleted.push_back(clus); - } - } - } - - }else{ - const Muon::RpcPrepDataContainer* prdContainer = 0; - SG::ReadHandle<Muon::RpcPrepDataContainer> RpcCont(m_rpcKey); - if(!RpcCont.isValid()){ - ATH_MSG_WARNING("Cannot retrieve RpcPrepDataContainer "); - return measurementsToBeDeleted; - } - else{ - prdContainer = RpcCont.cptr(); - } - if(!prdContainer){ - ATH_MSG_WARNING("No RPC prd container retrieved"); - return measurementsToBeDeleted; - } - - // loop over chambers and get collections - std::set<IdentifierHash>::const_iterator chit = chIdHs.begin(); - std::set<IdentifierHash>::const_iterator chit_end = chIdHs.end(); - for( ;chit!=chit_end;++chit ){ - auto collptr = prdContainer->indexFindPtr(*chit); - if( collptr == nullptr ) continue; - - const RpcPrepDataCollection& col = *collptr; - RpcPrepDataCollection::const_iterator hit = col.begin(); - RpcPrepDataCollection::const_iterator hit_end = col.end(); - for( ;hit!=hit_end;++hit ){ - // skip phi hits - if( m_idHelperSvc->measuresPhi((*hit)->identify()) ) continue; - const MuonClusterOnTrack* clus = m_clusterCreator->createRIO_OnTrack(**hit,(*hit)->globalPosition()); - if( clus ) { - clusters.push_back(clus); - measurementsToBeDeleted.push_back(clus); - } - } - } + for (; cit != cit_end; ++cit) chIdHs.insert((*cit)->collectionHash()); + ATH_MSG_VERBOSE("Number of collections " << chIdHs.size()); + + if (isEndcap) { + const Muon::TgcPrepDataContainer* prdContainer = 0; + SG::ReadHandle<Muon::TgcPrepDataContainer> TgcCont(m_tgcKey); + if (!TgcCont.isValid()) { + ATH_MSG_WARNING("Cannot retrieve TgcPrepDataContainer "); + return measurementsToBeDeleted; + } else { + prdContainer = TgcCont.cptr(); + } + if (!prdContainer) { + ATH_MSG_WARNING("No TGC prd container retrieved"); + return measurementsToBeDeleted; + } + + // loop over chambers and get collections + std::set<IdentifierHash>::const_iterator chit = chIdHs.begin(); + std::set<IdentifierHash>::const_iterator chit_end = chIdHs.end(); + for (; chit != chit_end; ++chit) { + auto collptr = prdContainer->indexFindPtr(*chit); + if (collptr == nullptr) { + ATH_MSG_VERBOSE("Could not find collection "); + continue; + } + const TgcPrepDataCollection& col = *collptr; + ATH_MSG_VERBOSE("Found collection: " << m_idHelperSvc->toStringChamber(col.identify()) << " size " + << col.size()); + TgcPrepDataCollection::const_iterator hit = col.begin(); + TgcPrepDataCollection::const_iterator hit_end = col.end(); + for (; hit != hit_end; ++hit) { + // skip phi hits + if (m_idHelperSvc->measuresPhi((*hit)->identify())) continue; + + const MuonClusterOnTrack* clus = m_clusterCreator->createRIO_OnTrack(**hit, (*hit)->globalPosition()); + if (clus) { + ATH_MSG_VERBOSE(" adding hit: " << m_idHelperSvc->toString(clus->identify())); + clusters.push_back(clus); + measurementsToBeDeleted.push_back(clus); + } + } + } + + } else { + const Muon::RpcPrepDataContainer* prdContainer = 0; + SG::ReadHandle<Muon::RpcPrepDataContainer> RpcCont(m_rpcKey); + if (!RpcCont.isValid()) { + ATH_MSG_WARNING("Cannot retrieve RpcPrepDataContainer "); + return measurementsToBeDeleted; + } else { + prdContainer = RpcCont.cptr(); + } + if (!prdContainer) { + ATH_MSG_WARNING("No RPC prd container retrieved"); + return measurementsToBeDeleted; + } + + // loop over chambers and get collections + std::set<IdentifierHash>::const_iterator chit = chIdHs.begin(); + std::set<IdentifierHash>::const_iterator chit_end = chIdHs.end(); + for (; chit != chit_end; ++chit) { + auto collptr = prdContainer->indexFindPtr(*chit); + if (collptr == nullptr) continue; + + const RpcPrepDataCollection& col = *collptr; + RpcPrepDataCollection::const_iterator hit = col.begin(); + RpcPrepDataCollection::const_iterator hit_end = col.end(); + for (; hit != hit_end; ++hit) { + // skip phi hits + if (m_idHelperSvc->measuresPhi((*hit)->identify())) continue; + const MuonClusterOnTrack* clus = m_clusterCreator->createRIO_OnTrack(**hit, (*hit)->globalPosition()); + if (clus) { + clusters.push_back(clus); + measurementsToBeDeleted.push_back(clus); + } + } + } } return measurementsToBeDeleted; - } +} - void DCMathSegmentMaker::find( const Amg::Vector3D& roadpos, const Amg::Vector3D& roaddir, - const std::vector<const MdtDriftCircleOnTrack*>& mdts, - const std::vector<const MuonClusterOnTrack*>& clusters, - bool hasPhiMeasurements, Trk::SegmentCollection* segColl, double momentum, double sinAngleCut) const - { +void +DCMathSegmentMaker::find(const Amg::Vector3D& roadpos, const Amg::Vector3D& roaddir, + const std::vector<const MdtDriftCircleOnTrack*>& mdts, + const std::vector<const MuonClusterOnTrack*>& clusters, bool hasPhiMeasurements, + Trk::SegmentCollection* segColl, double momentum, double sinAngleCut) const +{ - if (m_doTimeOutChecks && Athena::Timeout::instance().reached() ) { - ATH_MSG_DEBUG("Timeout reached. Aborting sequence."); - return; - } - - ATH_MSG_DEBUG("In find, passed "<<mdts.size() <<" RIO_OnTracks"); + if (m_doTimeOutChecks && Athena::Timeout::instance().reached()) { + ATH_MSG_DEBUG("Timeout reached. Aborting sequence."); + return; + } + + ATH_MSG_DEBUG("In find, passed " << mdts.size() << " RIO_OnTracks"); - if( mdts.size() < 3 ) return; + if (mdts.size() < 3) return; const MdtDriftCircleOnTrack* firstRot = findFirstRotInChamberWithMostHits(mdts); - if( !firstRot ) { - return; + if (!firstRot) { + return; } const MuonGM::MdtReadoutElement* detEl = firstRot->detectorElement(); - if( !detEl ) { - ATH_MSG_WARNING(" no MdtReadoutElement found, returning 0 "); - return; + if (!detEl) { + ATH_MSG_WARNING(" no MdtReadoutElement found, returning 0 "); + return; } - + // identifier Identifier chid = firstRot->identify(); @@ -418,926 +414,959 @@ namespace Muon { // transform nominal pointing chamber position into surface frame - Amg::Vector3D globalDirCh = Amg::Vector3D(detEl->center().x(),detEl->center().y(),detEl->center().z()); - Amg::Vector3D dirCh(gToStation.linear()*globalDirCh); - double chamber_angleYZ = atan2(dirCh.z(),dirCh.y()); + Amg::Vector3D globalDirCh = Amg::Vector3D(detEl->center().x(), detEl->center().y(), detEl->center().z()); + Amg::Vector3D dirCh(gToStation.linear() * globalDirCh); + double chamber_angleYZ = atan2(dirCh.z(), dirCh.y()); - Amg::Vector3D roaddir2=roaddir; - double dotprod= globalDirCh.perp()*sin(roaddir2.theta()) +globalDirCh.z()*cos(roaddir2.theta()); - if (dotprod<0) roaddir2=-roaddir2; + Amg::Vector3D roaddir2 = roaddir; + double dotprod = globalDirCh.perp() * sin(roaddir2.theta()) + globalDirCh.z() * cos(roaddir2.theta()); + if (dotprod < 0) roaddir2 = -roaddir2; // transform the global direction into the surface frame - Amg::Vector3D d(gToStation.linear()*roaddir2); + Amg::Vector3D d(gToStation.linear() * roaddir2); // calculate the local road angles in the surface frame - double road_angleXZ = atan2(d.z(),d.x()); - double road_angleYZ = atan2(d.z(),d.y()); + double road_angleXZ = atan2(d.z(), d.x()); + double road_angleYZ = atan2(d.z(), d.y()); - if( !hasPhiMeasurements ) road_angleXZ = acos(0.); // if no phi, take phi perpendicular to plane - ATH_MSG_VERBOSE("global road dir " << Amg::toString(roaddir2) << " XZ " << road_angleXZ << " YZ " << road_angleYZ << " isEndcap " << isEndcap - << " central phi " << detEl->center().phi() << " r " << detEl->center().perp() << " z " << detEl->center().z() ); + if (!hasPhiMeasurements) road_angleXZ = acos(0.); // if no phi, take phi perpendicular to plane + ATH_MSG_VERBOSE("global road dir " << Amg::toString(roaddir2) << " XZ " << road_angleXZ << " YZ " << road_angleYZ + << " isEndcap " << isEndcap << " central phi " << detEl->center().phi() << " r " + << detEl->center().perp() << " z " << detEl->center().z()); // rescale errors for low momentum - double errorScale = errorScaleFactor( chid, momentum, hasPhiMeasurements ); + double errorScale = errorScaleFactor(chid, momentum, hasPhiMeasurements); /* ***** create cluster hits ******** */ ATH_MSG_DEBUG(" adding clusters " << clusters.size()); ClusterVecPair spVecs; - if( m_doSpacePoints ) spVecs = create2DClusters( clusters ); - else spVecs = create1DClusters( clusters ); - TrkDriftCircleMath::CLVec cls = createClusterVec( chid, spVecs.first, gToStation ); - + if (m_doSpacePoints) + spVecs = create2DClusters(clusters); + else + spVecs = create1DClusters(clusters); + TrkDriftCircleMath::CLVec cls = createClusterVec(chid, spVecs.first, gToStation); + /* ***** create MDT hits ************ */ ATH_MSG_DEBUG(" adding mdts " << mdts.size()); - for (auto it : mdts) - ATH_MSG_DEBUG(*it); - + for (auto it : mdts) ATH_MSG_DEBUG(*it); + // set to get Identifiers of chambers with hits - std::set<Identifier> chamberSet; - double phimin=-9999,phimax=9999; - TrkDriftCircleMath::DCStatistics dcStatistics; // statistics on chamber occupancy - TrkDriftCircleMath::DCVec dcs = createDCVec( mdts, errorScale, chamberSet, phimin, phimax, dcStatistics, gToStation, amdbToGlobal ); - - //create geometry + std::set<Identifier> chamberSet; + double phimin = -9999, phimax = 9999; + TrkDriftCircleMath::DCStatistics dcStatistics; // statistics on chamber occupancy + TrkDriftCircleMath::DCVec dcs = + createDCVec(mdts, errorScale, chamberSet, phimin, phimax, dcStatistics, gToStation, amdbToGlobal); + + // create geometry std::unique_ptr<TrkDriftCircleMath::MdtMultiChamberGeometry> multiGeo; - if( m_doGeometry ) { - - ATH_MSG_VERBOSE(" using chamber geometry with #chambers " << chamberSet.size()); - - // vector to store chamber geometries - std::vector<TrkDriftCircleMath::MdtChamberGeometry> geos; - - // loop over chambers - std::set<Identifier>::iterator it = chamberSet.begin(); - std::set<Identifier>::iterator it_end = chamberSet.end(); - for( ;it!=it_end;++it ){ - geos.push_back( createChamberGeometry( *it, gToStation ) ); - } - - // create new geometry - multiGeo = std::unique_ptr<TrkDriftCircleMath::MdtMultiChamberGeometry>( new TrkDriftCircleMath::MdtMultiChamberGeometry(geos) ); - } - - double angle=m_sinAngleCut; - if(sinAngleCut>0) angle=sinAngleCut; - TrkDriftCircleMath::Road road(TrkDriftCircleMath::LocPos(0.,0.),road_angleYZ,chamber_angleYZ,angle); - + if (m_doGeometry) { + + ATH_MSG_VERBOSE(" using chamber geometry with #chambers " << chamberSet.size()); + + // vector to store chamber geometries + std::vector<TrkDriftCircleMath::MdtChamberGeometry> geos; + + // loop over chambers + std::set<Identifier>::iterator it = chamberSet.begin(); + std::set<Identifier>::iterator it_end = chamberSet.end(); + for (; it != it_end; ++it) { + geos.push_back(createChamberGeometry(*it, gToStation)); + } + + // create new geometry + multiGeo = std::unique_ptr<TrkDriftCircleMath::MdtMultiChamberGeometry>( + new TrkDriftCircleMath::MdtMultiChamberGeometry(geos)); + } + + double angle = m_sinAngleCut; + if (sinAngleCut > 0) angle = sinAngleCut; + TrkDriftCircleMath::Road road(TrkDriftCircleMath::LocPos(0., 0.), road_angleYZ, chamber_angleYZ, angle); + // call segment finder - TrkDriftCircleMath::SegVec segs = m_segmentFinder->findSegments(dcs,cls,road,dcStatistics,multiGeo.get()); + TrkDriftCircleMath::SegVec segs = m_segmentFinder->findSegments(dcs, cls, road, dcStatistics, multiGeo.get()); - ATH_MSG_DEBUG("Found " << segs.size() <<" segments"); + ATH_MSG_DEBUG("Found " << segs.size() << " segments"); // return - if( segs.empty() ) { - return; + if (segs.empty()) { + return; } - // loop over segments - TrkDriftCircleMath::SegIt sit = segs.begin(); + // loop over segments + TrkDriftCircleMath::SegIt sit = segs.begin(); TrkDriftCircleMath::SegIt sit_end = segs.end(); - segmentCreationInfo sInfo(spVecs,multiGeo.get(),gToStation,amdbToGlobal,phimin,phimax); - for( ;sit!=sit_end;++sit ){ + segmentCreationInfo sInfo(spVecs, multiGeo.get(), gToStation, amdbToGlobal, phimin, phimax); + for (; sit != sit_end; ++sit) { - MuonSegment* segment = createSegment(*sit,chid,roadpos,roaddir2,mdts,hasPhiMeasurements,sInfo); - if( segment ) segColl->push_back(segment); + MuonSegment* segment = createSegment(*sit, chid, roadpos, roaddir2, mdts, hasPhiMeasurements, sInfo); + if (segment) segColl->push_back(segment); } ATH_MSG_DEBUG(" Done "); +} - } +MuonSegment* +DCMathSegmentMaker::createSegment(TrkDriftCircleMath::Segment& segment, const Identifier& chid, + const Amg::Vector3D& roadpos, const Amg::Vector3D& roaddir2, + const std::vector<const MdtDriftCircleOnTrack*>& mdts, bool hasPhiMeasurements, + segmentCreationInfo& sInfo) const +{ - MuonSegment* DCMathSegmentMaker::createSegment( TrkDriftCircleMath::Segment& segment, const Identifier& chid, - const Amg::Vector3D& roadpos, const Amg::Vector3D& roaddir2, - const std::vector<const MdtDriftCircleOnTrack*>& mdts, - bool hasPhiMeasurements, segmentCreationInfo& sInfo) const { - bool isEndcap = m_idHelperSvc->isEndcap(chid); - //find all curved segments - bool isCurvedSegment(false); - MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chid); + // find all curved segments + bool isCurvedSegment(false); + MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chid); - //MuonStationIndex::ChIndex chIndex; - if(segment.hasCurvatureParameters()) { - if(chIndex == Muon::MuonStationIndex::BIL || chIndex == MuonStationIndex::BML || chIndex == MuonStationIndex::BMS || chIndex == MuonStationIndex::BOL) - isCurvedSegment = true; + // MuonStationIndex::ChIndex chIndex; + if (segment.hasCurvatureParameters()) { + if (chIndex == Muon::MuonStationIndex::BIL || chIndex == MuonStationIndex::BML + || chIndex == MuonStationIndex::BMS || chIndex == MuonStationIndex::BOL) + isCurvedSegment = true; } // remove segments with too few hits - if( segment.hitsOnTrack() < 3 ) return 0; + if (segment.hitsOnTrack() < 3) return 0; // convert segment parameters + x position from road - const TrkDriftCircleMath::Line& line = segment.line(); + const TrkDriftCircleMath::Line& line = segment.line(); - ATH_MSG_DEBUG("New segment: chi2 " << segment.chi2() << " ndof " << segment.ndof() - << " line " << line.position().x() << "," << line.position().y() << " phi " << line.phi() - << " associated clusters " << segment.clusters().size()); - + ATH_MSG_DEBUG("New segment: chi2 " << segment.chi2() << " ndof " << segment.ndof() << " line " + << line.position().x() << "," << line.position().y() << " phi " << line.phi() + << " associated clusters " << segment.clusters().size()); + // local position along x from road - Amg::Vector3D lroadpos = sInfo.globalTrans*roadpos; - Amg::Vector3D lroaddir = sInfo.globalTrans.linear()*roaddir2; + Amg::Vector3D lroadpos = sInfo.globalTrans * roadpos; + Amg::Vector3D lroaddir = sInfo.globalTrans.linear() * roaddir2; // local x position of first tube used if no phi measurement is present double lxroad = 0.; - - if( hasPhiMeasurements ){ - - // calculate local position of segment along tube using the road - // calculate intersect pattern measurement plane - double sphi = 0.; - double cphi = lroaddir.x(); - // swap local y and z in the endcaps - if ( isEndcap ) { - sphi = lroaddir.y(); - lxroad = lroadpos.x()+(-lroadpos.y()+line.position().x())*cphi/sphi; - }else{ - sphi = lroaddir.z(); - lxroad = lroadpos.x()+(-lroadpos.z()+line.position().y())*cphi/sphi; - } - - double shortestTubeLen = 1e9; - // loop over hits and get the shortest tube on the segment - for( TrkDriftCircleMath::DCOnTrackCit dcit = segment.dcs().begin();dcit!=segment.dcs().end();++dcit ){ - - if( dcit->state() != TrkDriftCircleMath::DCOnTrack::OnTrack ) continue; - - const MdtDriftCircleOnTrack* riodc = mdts[dcit->index()]; - if( !riodc ) continue; - int lay = m_idHelperSvc->mdtIdHelper().tubeLayer(riodc->identify()); - int tube = m_idHelperSvc->mdtIdHelper().tube(riodc->identify()); - double tubelen = 0.5*riodc->prepRawData()->detectorElement()->getActiveTubeLength(lay,tube); - if( tubelen < shortestTubeLen ) shortestTubeLen = tubelen; - } - // if the predicted position lies outside the chamber move it back inside - if ( std::abs(lxroad) > shortestTubeLen) { - ATH_MSG_DEBUG("coordinates far outside chamber! using global position of first hit "); - if( lxroad < 0. ) shortestTubeLen *= -1.; - lxroad = shortestTubeLen; - } - }else{ - lxroad = (sInfo.globalTrans*mdts[0]->prepRawData()->detectorElement()->surface(mdts[0]->identify()).center()).x(); + + if (hasPhiMeasurements) { + + // calculate local position of segment along tube using the road + // calculate intersect pattern measurement plane + double sphi = 0.; + double cphi = lroaddir.x(); + // swap local y and z in the endcaps + if (isEndcap) { + sphi = lroaddir.y(); + lxroad = lroadpos.x() + (-lroadpos.y() + line.position().x()) * cphi / sphi; + } else { + sphi = lroaddir.z(); + lxroad = lroadpos.x() + (-lroadpos.z() + line.position().y()) * cphi / sphi; + } + + double shortestTubeLen = 1e9; + // loop over hits and get the shortest tube on the segment + for (TrkDriftCircleMath::DCOnTrackCit dcit = segment.dcs().begin(); dcit != segment.dcs().end(); ++dcit) { + + if (dcit->state() != TrkDriftCircleMath::DCOnTrack::OnTrack) continue; + + const MdtDriftCircleOnTrack* riodc = mdts[dcit->index()]; + if (!riodc) continue; + int lay = m_idHelperSvc->mdtIdHelper().tubeLayer(riodc->identify()); + int tube = m_idHelperSvc->mdtIdHelper().tube(riodc->identify()); + double tubelen = 0.5 * riodc->prepRawData()->detectorElement()->getActiveTubeLength(lay, tube); + if (tubelen < shortestTubeLen) shortestTubeLen = tubelen; + } + // if the predicted position lies outside the chamber move it back inside + if (std::abs(lxroad) > shortestTubeLen) { + ATH_MSG_DEBUG("coordinates far outside chamber! using global position of first hit "); + if (lxroad < 0.) shortestTubeLen *= -1.; + lxroad = shortestTubeLen; + } + } else { + lxroad = + (sInfo.globalTrans * mdts[0]->prepRawData()->detectorElement()->surface(mdts[0]->identify()).center()).x(); } // calculate local direction vector - Amg::Vector3D lpos( lxroad,line.position().x(),line.position().y() ); - + Amg::Vector3D lpos(lxroad, line.position().x(), line.position().y()); + // global position segment - Amg::Vector3D gpos = sInfo.amdbTrans*lpos; + Amg::Vector3D gpos = sInfo.amdbTrans * lpos; - // create new surface + // create new surface Amg::Transform3D* surfaceTransform = new Amg::Transform3D(sInfo.amdbTrans.rotation()); surfaceTransform->pretranslate(gpos); - double surfDim = 500.; - Trk::PlaneSurface* surf = new Trk::PlaneSurface( surfaceTransform, surfDim, surfDim ); - + double surfDim = 500.; + Trk::PlaneSurface* surf = new Trk::PlaneSurface(surfaceTransform, surfDim, surfDim); + // measurements - Amg::Vector2D segLocPos(0.,0.); - double linephi = line.phi(); + Amg::Vector2D segLocPos(0., 0.); + double linephi = line.phi(); - // now update the global direction using the local precision angle of the segment and the global phi angle of the road. - Amg::Vector3D gdir = updateDirection( linephi, *surf, roaddir2, isCurvedSegment ); + // now update the global direction using the local precision angle of the segment and the global phi angle of the + // road. + Amg::Vector3D gdir = updateDirection(linephi, *surf, roaddir2, isCurvedSegment); // extract RIO_OnTracks - std::vector<std::pair<double,const Trk::MeasurementBase*> > rioDistVec; //vector to store the distance of a ROT to the segment + std::vector<std::pair<double, const Trk::MeasurementBase*> > + rioDistVec; // vector to store the distance of a ROT to the segment // associate MDT hits to segment - std::set<Identifier> deltaVec; - std::set<Identifier> outoftimeVec; - std::vector<const Trk::MeasurementBase*> measToBeDeleted=associateMDTsToSegment( gdir, segment, mdts, sInfo.geom, sInfo.globalTrans, sInfo.amdbTrans, deltaVec, outoftimeVec, rioDistVec ); - - TrkDriftCircleMath::DCSLHitSelector hitSelector; - - if( m_redo2DFit && !isCurvedSegment ){ - - // refit segment after recalibration - TrkDriftCircleMath::DCSLFitter defaultFitter; - TrkDriftCircleMath::Segment result(TrkDriftCircleMath::Line(0.,0.,0.), TrkDriftCircleMath::DCOnTrackVec()); - bool goodFit = defaultFitter.fit( result, line, segment.dcs(), hitSelector.selectHitsOnTrack(segment.dcs()) ); - if( goodFit ){ - if( std::abs(segment.line().phi() - result.line().phi()) > 0.01 || - std::abs(segment.line().x0() - result.line().x0()) > 0.01 || - std::abs(segment.line().y0() - result.line().y0()) > 0.01 ) { - - // update local position and global - linephi = result.line().phi(); - lpos[1] = result.line().position().x() ; - lpos[2] = result.line().position().y() ; - gpos = sInfo.amdbTrans*lpos; - - // recreate surface - delete surf; - surfaceTransform = new Amg::Transform3D(sInfo.amdbTrans.rotation()); - surfaceTransform->pretranslate(gpos); - surf = new Trk::PlaneSurface( surfaceTransform, surfDim, surfDim ); - - // finally update global direction - gdir = updateDirection( linephi, *surf, roaddir2, isCurvedSegment ); - } - } - } - + std::set<Identifier> deltaVec; + std::set<Identifier> outoftimeVec; + std::vector<const Trk::MeasurementBase*> measToBeDeleted = associateMDTsToSegment( + gdir, segment, mdts, sInfo.geom, sInfo.globalTrans, sInfo.amdbTrans, deltaVec, outoftimeVec, rioDistVec); + + TrkDriftCircleMath::DCSLHitSelector hitSelector; + + if (m_redo2DFit && !isCurvedSegment) { + + // refit segment after recalibration + TrkDriftCircleMath::DCSLFitter defaultFitter; + TrkDriftCircleMath::Segment result(TrkDriftCircleMath::Line(0., 0., 0.), TrkDriftCircleMath::DCOnTrackVec()); + bool goodFit = defaultFitter.fit(result, line, segment.dcs(), hitSelector.selectHitsOnTrack(segment.dcs())); + if (goodFit) { + if (std::abs(segment.line().phi() - result.line().phi()) > 0.01 + || std::abs(segment.line().x0() - result.line().x0()) > 0.01 + || std::abs(segment.line().y0() - result.line().y0()) > 0.01) + { + + // update local position and global + linephi = result.line().phi(); + lpos[1] = result.line().position().x(); + lpos[2] = result.line().position().y(); + gpos = sInfo.amdbTrans * lpos; + + // recreate surface + delete surf; + surfaceTransform = new Amg::Transform3D(sInfo.amdbTrans.rotation()); + surfaceTransform->pretranslate(gpos); + surf = new Trk::PlaneSurface(surfaceTransform, surfDim, surfDim); + + // finally update global direction + gdir = updateDirection(linephi, *surf, roaddir2, isCurvedSegment); + } + } + } + // create local segment direction Trk::LocalDirection segLocDir; - surf->globalToLocalDirection(gdir,segLocDir); - + surf->globalToLocalDirection(gdir, segLocDir); + // sanity checks - double diff_phi = roaddir2.phi() - gdir.phi(); - double diff_prec = linephi - segLocDir.angleYZ(); - if (std::abs(sin(diff_phi)) > 1.e-3 || std::abs(sin(diff_prec)) > 1.e-3 ) { - ATH_MSG_WARNING(" ALARM updated angles wrong: diff phi " << diff_phi << " prec " << diff_prec << " phi rdir " << roaddir2.phi() - << " gdir " << gdir.phi() << " lphi " << linephi << " seg " << segLocDir.angleYZ() ); + double diff_phi = roaddir2.phi() - gdir.phi(); + double diff_prec = linephi - segLocDir.angleYZ(); + if (std::abs(sin(diff_phi)) > 1.e-3 || std::abs(sin(diff_prec)) > 1.e-3) { + ATH_MSG_WARNING(" ALARM updated angles wrong: diff phi " << diff_phi << " prec " << diff_prec << " phi rdir " + << roaddir2.phi() << " gdir " << gdir.phi() << " lphi " + << linephi << " seg " << segLocDir.angleYZ()); } - + // associate Clusters to segment, uses spVecs to get clusters - std::pair<std::pair<int,int>,bool> netaPhiHits = associateClustersToSegment( segment, chid, sInfo.globalTrans, sInfo.clusters, sInfo.phimin, sInfo.phimax, rioDistVec ); - + std::pair<std::pair<int, int>, bool> netaPhiHits = associateClustersToSegment( + segment, chid, sInfo.globalTrans, sInfo.clusters, sInfo.phimin, sInfo.phimax, rioDistVec); + // copy hits into vector DataVector<const Trk::MeasurementBase>* rioVec = createROTVec(rioDistVec); - double dlocx = 1000.; - double dangleXZ = 1000.; - double qoverp = -99999.; - double dqoverp = -99999.; - bool hasMeasuredCoordinate = false; - if( m_refitParameters && netaPhiHits.second ){ - ATH_MSG_DEBUG(" distance between first and last phi hit sufficient to perform 4D fit: phi " - << gdir.phi() << " theta " << gdir.theta()); - - Trk::Track* track = m_segmentFitter->fit( gpos, gdir, *surf, rioVec->stdcont() ); - - if( track ) { - if( isCurvedSegment && track->perigeeParameters() && track->perigeeParameters()->covariance() ) { - qoverp = track->perigeeParameters()->parameters()[Trk::qOverP]; - dqoverp = Amg::error(*track->perigeeParameters()->covariance(),Trk::qOverP); - } - hasMeasuredCoordinate = true; - // hack to update the second coordinate errors - Amg::MatrixX updatedCov(5,5); - updatedCov.setZero(); - m_segmentFitter->updateSegmentParameters( *track, *surf, segLocPos, segLocDir, updatedCov ); - if( Amg::error(updatedCov,Trk::locX) > 0 && Amg::error(updatedCov,Trk::phi) > 0. ){ - dlocx = Amg::error(updatedCov,Trk::locX); - dangleXZ = Amg::error(updatedCov,Trk::phi); // hack (2): phi not always angleXZ - }else{ - ATH_MSG_WARNING(" Corrupt error matrix returned from fitter " << Amg::toString(updatedCov)); - } - - /// recalculate global direction and position - surf->localToGlobal(segLocPos,gdir,gpos); - surf->localToGlobalDirection(segLocDir,gdir); - - if( track->measurementsOnTrack() && rioVec->size() != track->measurementsOnTrack()->size() ){ - ATH_MSG_DEBUG(" ROT vector size changed after fit, updating "); - delete rioVec; - rioDistVec.clear(); - rioVec = new DataVector<const Trk::MeasurementBase>(); - rioVec->reserve(track->measurementsOnTrack()->size()); - DataVector<const Trk::TrackStateOnSurface>::const_iterator tsit = track->trackStateOnSurfaces()->begin(); - DataVector<const Trk::TrackStateOnSurface>::const_iterator tsit_end = track->trackStateOnSurfaces()->end(); - const Trk::TrackParameters* firstPars = 0; - for( ;tsit!=tsit_end;++tsit ) { - - const Trk::TrackParameters* pars = (*tsit)->trackParameters(); - if( !pars ) continue; - if( !firstPars ) firstPars = pars; - - // check whether state is a measurement, skip outliers if they are not MDT - const Trk::MeasurementBase* meas = (*tsit)->measurementOnTrack(); - if( !meas ) continue; - if( (*tsit)->type(Trk::TrackStateOnSurface::Outlier) && !dynamic_cast<const MdtDriftCircleOnTrack*>(meas) ) continue; - - const Trk::MeasurementBase* measNew = meas->clone(); - rioVec->push_back( measNew ); - double dist = (pars->position()-firstPars->position()).dot(firstPars->momentum().unit()); - rioDistVec.push_back( std::make_pair(dist,measNew) ); - } - } - - delete track; - }else { - ATH_MSG_DEBUG(" refit of segment failed!! "); - netaPhiHits.second = false; - } - } - - // optional update of phi position and direction, only performed if the segment was not refitted and there are phi hits - if( m_updatePhiUsingPhiHits && !netaPhiHits.second ){ - if( updateSegmentPhi( gpos, gdir, segLocPos, segLocDir, *surf, rioVec->stdcont(), sInfo.phimin, sInfo.phimax ) ){ - surf->localToGlobal(segLocPos,gpos,gpos); - surf->localToGlobalDirection(segLocDir,gdir); - hasMeasuredCoordinate = true; - dlocx = 100.; - dangleXZ = 0.1; - } - } - - - if( msgLvl(MSG::DEBUG) ){ - ATH_MSG_DEBUG(" number of hits " << rioVec->size() << " of which trigger " << netaPhiHits.first.first - << " eta and " << netaPhiHits.first.second << " phi "); - DataVector<const Trk::MeasurementBase>::const_iterator mit = rioVec->begin(); - DataVector<const Trk::MeasurementBase>::const_iterator mit_end = rioVec->end(); - for( ;mit!=mit_end;++mit ){ - const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(*mit); - if( rot ){ - ATH_MSG_DEBUG(m_idHelperSvc->toString( rot->identify() )); - const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(rot); - if( mdt ) ATH_MSG_DEBUG(std::setprecision(4) << " radius " << std::setw(6) << mdt->driftRadius() << " time " << std::setw(6) << mdt->driftTime()); - continue; - } - const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*mit); - if( crot ){ - ATH_MSG_DEBUG(m_idHelperSvc->toString( crot->rioOnTrack(0).identify() ) - << " comp rot with hits " << crot->containedROTs().size()); - continue; - } - ATH_MSG_WARNING("failed to dynamic_cast to ROT "); - - } - } + double dlocx = 1000.; + double dangleXZ = 1000.; + double qoverp = -99999.; + double dqoverp = -99999.; + bool hasMeasuredCoordinate = false; + if (m_refitParameters && netaPhiHits.second) { + ATH_MSG_DEBUG(" distance between first and last phi hit sufficient to perform 4D fit: phi " + << gdir.phi() << " theta " << gdir.theta()); + + Trk::Track* track = m_segmentFitter->fit(gpos, gdir, *surf, rioVec->stdcont()); + + if (track) { + if (isCurvedSegment && track->perigeeParameters() && track->perigeeParameters()->covariance()) { + qoverp = track->perigeeParameters()->parameters()[Trk::qOverP]; + dqoverp = Amg::error(*track->perigeeParameters()->covariance(), Trk::qOverP); + } + hasMeasuredCoordinate = true; + // hack to update the second coordinate errors + Amg::MatrixX updatedCov(5, 5); + updatedCov.setZero(); + m_segmentFitter->updateSegmentParameters(*track, *surf, segLocPos, segLocDir, updatedCov); + if (Amg::error(updatedCov, Trk::locX) > 0 && Amg::error(updatedCov, Trk::phi) > 0.) { + dlocx = Amg::error(updatedCov, Trk::locX); + dangleXZ = Amg::error(updatedCov, Trk::phi); // hack (2): phi not always angleXZ + } else { + ATH_MSG_WARNING(" Corrupt error matrix returned from fitter " << Amg::toString(updatedCov)); + } + + /// recalculate global direction and position + surf->localToGlobal(segLocPos, gdir, gpos); + surf->localToGlobalDirection(segLocDir, gdir); + + if (track->measurementsOnTrack() && rioVec->size() != track->measurementsOnTrack()->size()) { + ATH_MSG_DEBUG(" ROT vector size changed after fit, updating "); + delete rioVec; + rioDistVec.clear(); + rioVec = new DataVector<const Trk::MeasurementBase>(); + rioVec->reserve(track->measurementsOnTrack()->size()); + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsit = + track->trackStateOnSurfaces()->begin(); + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsit_end = + track->trackStateOnSurfaces()->end(); + const Trk::TrackParameters* firstPars = 0; + for (; tsit != tsit_end; ++tsit) { + + const Trk::TrackParameters* pars = (*tsit)->trackParameters(); + if (!pars) continue; + if (!firstPars) firstPars = pars; + + // check whether state is a measurement, skip outliers if they are not MDT + const Trk::MeasurementBase* meas = (*tsit)->measurementOnTrack(); + if (!meas) continue; + if ((*tsit)->type(Trk::TrackStateOnSurface::Outlier) + && !dynamic_cast<const MdtDriftCircleOnTrack*>(meas)) + continue; + + const Trk::MeasurementBase* measNew = meas->clone(); + rioVec->push_back(measNew); + double dist = (pars->position() - firstPars->position()).dot(firstPars->momentum().unit()); + rioDistVec.push_back(std::make_pair(dist, measNew)); + } + } + + delete track; + } else { + ATH_MSG_DEBUG(" refit of segment failed!! "); + netaPhiHits.second = false; + } + } + + // optional update of phi position and direction, only performed if the segment was not refitted and there are phi + // hits + if (m_updatePhiUsingPhiHits && !netaPhiHits.second) { + if (updateSegmentPhi(gpos, gdir, segLocPos, segLocDir, *surf, rioVec->stdcont(), sInfo.phimin, sInfo.phimax)) { + surf->localToGlobal(segLocPos, gpos, gpos); + surf->localToGlobalDirection(segLocDir, gdir); + hasMeasuredCoordinate = true; + dlocx = 100.; + dangleXZ = 0.1; + } + } + + + if (msgLvl(MSG::DEBUG)) { + ATH_MSG_DEBUG(" number of hits " << rioVec->size() << " of which trigger " << netaPhiHits.first.first + << " eta and " << netaPhiHits.first.second << " phi "); + DataVector<const Trk::MeasurementBase>::const_iterator mit = rioVec->begin(); + DataVector<const Trk::MeasurementBase>::const_iterator mit_end = rioVec->end(); + for (; mit != mit_end; ++mit) { + const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(*mit); + if (rot) { + ATH_MSG_DEBUG(m_idHelperSvc->toString(rot->identify())); + const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(rot); + if (mdt) + ATH_MSG_DEBUG(std::setprecision(4) << " radius " << std::setw(6) << mdt->driftRadius() << " time " + << std::setw(6) << mdt->driftTime()); + continue; + } + const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*mit); + if (crot) { + ATH_MSG_DEBUG(m_idHelperSvc->toString(crot->rioOnTrack(0).identify()) + << " comp rot with hits " << crot->containedROTs().size()); + continue; + } + ATH_MSG_WARNING("failed to dynamic_cast to ROT "); + } + } // recalculate holes - std::vector<Identifier> holeVec=calculateHoles( chid, gpos, gdir, hasMeasuredCoordinate, deltaVec, outoftimeVec, rioDistVec ); + std::vector<Identifier> holeVec = + calculateHoles(chid, gpos, gdir, hasMeasuredCoordinate, deltaVec, outoftimeVec, rioDistVec); // currently not taking into account masked channels - if(!outoftimeVec.empty()) holeVec.insert(holeVec.end(),outoftimeVec.begin(),outoftimeVec.end()); - MuonSegmentQuality* quality = new MuonSegmentQuality( segment.chi2(), segment.ndof(), holeVec ); + if (!outoftimeVec.empty()) holeVec.insert(holeVec.end(), outoftimeVec.begin(), outoftimeVec.end()); + MuonSegmentQuality* quality = new MuonSegmentQuality(segment.chi2(), segment.ndof(), holeVec); const TrkDriftCircleMath::DCSLFitter* dcslFitter = m_dcslFitProvider->getFitter(); - TrkDriftCircleMath::Segment result(TrkDriftCircleMath::Line(0.,0.,0.), TrkDriftCircleMath::DCOnTrackVec()); - if( dcslFitter && !segment.hasT0Shift() && m_outputFittedT0 ){ - if( !dcslFitter->fit( result, segment.line(), segment.dcs(), hitSelector.selectHitsOnTrack( segment.dcs() ) ) ) { - ATH_MSG_DEBUG( " T0 refit failed "); - }else{ - if( msgLvl(MSG::DEBUG) ) { - if( result.hasT0Shift() ) ATH_MSG_DEBUG(" Fitted T0 " << result.t0Shift()); - else ATH_MSG_DEBUG(" No fitted T0 "); - } - } - } - bool hasFittedT0 = false; - double fittedT0 = 0; - double errorFittedT0 = 1.; - if( m_outputFittedT0 && ( segment.hasT0Shift() || ( dcslFitter && result.hasT0Shift() ) ) ){ - hasFittedT0 = true; - if( segment.hasT0Shift() ){ - fittedT0 = segment.t0Shift(); - errorFittedT0 = segment.t0Error(); - }else if( dcslFitter && result.hasT0Shift() ) { - fittedT0 = result.t0Shift(); - errorFittedT0 = result.t0Error(); - }else{ - ATH_MSG_WARNING(" Failed to access fitted t0 "); - hasFittedT0 = false; - } - } - // create new segment + TrkDriftCircleMath::Segment result(TrkDriftCircleMath::Line(0., 0., 0.), TrkDriftCircleMath::DCOnTrackVec()); + if (dcslFitter && !segment.hasT0Shift() && m_outputFittedT0) { + if (!dcslFitter->fit(result, segment.line(), segment.dcs(), hitSelector.selectHitsOnTrack(segment.dcs()))) { + ATH_MSG_DEBUG(" T0 refit failed "); + } else { + if (msgLvl(MSG::DEBUG)) { + if (result.hasT0Shift()) + ATH_MSG_DEBUG(" Fitted T0 " << result.t0Shift()); + else + ATH_MSG_DEBUG(" No fitted T0 "); + } + } + } + bool hasFittedT0 = false; + double fittedT0 = 0; + double errorFittedT0 = 1.; + if (m_outputFittedT0 && (segment.hasT0Shift() || (dcslFitter && result.hasT0Shift()))) { + hasFittedT0 = true; + if (segment.hasT0Shift()) { + fittedT0 = segment.t0Shift(); + errorFittedT0 = segment.t0Error(); + } else if (dcslFitter && result.hasT0Shift()) { + fittedT0 = result.t0Shift(); + errorFittedT0 = result.t0Error(); + } else { + ATH_MSG_WARNING(" Failed to access fitted t0 "); + hasFittedT0 = false; + } + } + // create new segment MuonSegment* msegment = 0; - if(isCurvedSegment) {//curved segments - if(qoverp == -99999.) { - double charge = gpos.z()*tan(gdir.theta()); - charge = charge/std::abs(charge); - //if the curved segment was not refit, then use a momentum estimate - double BILALPHA(28.4366),BMLALPHA(62.8267),BMSALPHA(53.1259),BOLALPHA(29.7554); - if(chIndex == MuonStationIndex::BIL) { - qoverp = (charge*segment.deltaAlpha())/BILALPHA; - dqoverp = sqrt(2)*segment.dtheta()/BILALPHA; - } - else if(chIndex == MuonStationIndex::BML) { - qoverp = (charge*segment.deltaAlpha())/BMLALPHA; - dqoverp = sqrt(2)*segment.dtheta()/BMLALPHA; - } - else if(chIndex == MuonStationIndex::BMS) { - qoverp = (charge*segment.deltaAlpha())/BMSALPHA; - dqoverp = sqrt(2)*segment.dtheta()/BMSALPHA; - } - else if(chIndex == MuonStationIndex::BOL) { - qoverp = (charge*segment.deltaAlpha())/BOLALPHA; - dqoverp = sqrt(2)*segment.dtheta()/BOLALPHA; - } - } - Amg::MatrixX covMatrix(5,5); - covMatrix.setIdentity(); - covMatrix(0,0) = dlocx*dlocx; - covMatrix(1,1) = segment.dy0()*segment.dy0(); - covMatrix(2,2) = dangleXZ*dangleXZ; - covMatrix(3,3) = segment.dtheta()*segment.dtheta(); - covMatrix(4,4) = dqoverp*dqoverp; - - std::vector<Trk::DefinedParameter> defPars; - defPars.push_back( Trk::DefinedParameter(segLocPos[Trk::loc1],Trk::loc1) ); - defPars.push_back( Trk::DefinedParameter(segLocPos[Trk::loc2],Trk::loc2) ); - defPars.push_back( Trk::DefinedParameter(gdir.phi(), Trk::phi) ); - defPars.push_back( Trk::DefinedParameter(gdir.theta(), Trk::theta) ); - defPars.push_back( Trk::DefinedParameter(qoverp,Trk::qOverP) ); - Trk::LocalParameters segLocPar( defPars ); - msegment = new MuonSegment( segLocPar, covMatrix, surf, rioVec, quality, Trk::Segment::DCMathSegmentMakerCurved ); - } - else {//straight segments - // errors (for now no correlations) - Amg::MatrixX covMatrix(4,4); - covMatrix.setIdentity(); - covMatrix(0,0) = dlocx*dlocx; - covMatrix(1,1) = segment.dy0()*segment.dy0(); - covMatrix(2,2) = dangleXZ*dangleXZ; - covMatrix(3,3) = segment.dtheta()*segment.dtheta(); - msegment = new MuonSegment( segLocPos, segLocDir, covMatrix, surf, rioVec, quality, Trk::Segment::DCMathSegmentMaker ); - } - - if( hasFittedT0 ) msegment->setT0Error(fittedT0,errorFittedT0); + if (isCurvedSegment) { // curved segments + if (qoverp == -99999.) { + double charge = gpos.z() * tan(gdir.theta()); + charge = charge / std::abs(charge); + // if the curved segment was not refit, then use a momentum estimate + double BILALPHA(28.4366), BMLALPHA(62.8267), BMSALPHA(53.1259), BOLALPHA(29.7554); + if (chIndex == MuonStationIndex::BIL) { + qoverp = (charge * segment.deltaAlpha()) / BILALPHA; + dqoverp = sqrt(2) * segment.dtheta() / BILALPHA; + } else if (chIndex == MuonStationIndex::BML) { + qoverp = (charge * segment.deltaAlpha()) / BMLALPHA; + dqoverp = sqrt(2) * segment.dtheta() / BMLALPHA; + } else if (chIndex == MuonStationIndex::BMS) { + qoverp = (charge * segment.deltaAlpha()) / BMSALPHA; + dqoverp = sqrt(2) * segment.dtheta() / BMSALPHA; + } else if (chIndex == MuonStationIndex::BOL) { + qoverp = (charge * segment.deltaAlpha()) / BOLALPHA; + dqoverp = sqrt(2) * segment.dtheta() / BOLALPHA; + } + } + Amg::MatrixX covMatrix(5, 5); + covMatrix.setIdentity(); + covMatrix(0, 0) = dlocx * dlocx; + covMatrix(1, 1) = segment.dy0() * segment.dy0(); + covMatrix(2, 2) = dangleXZ * dangleXZ; + covMatrix(3, 3) = segment.dtheta() * segment.dtheta(); + covMatrix(4, 4) = dqoverp * dqoverp; + + std::vector<Trk::DefinedParameter> defPars; + defPars.push_back(Trk::DefinedParameter(segLocPos[Trk::loc1], Trk::loc1)); + defPars.push_back(Trk::DefinedParameter(segLocPos[Trk::loc2], Trk::loc2)); + defPars.push_back(Trk::DefinedParameter(gdir.phi(), Trk::phi)); + defPars.push_back(Trk::DefinedParameter(gdir.theta(), Trk::theta)); + defPars.push_back(Trk::DefinedParameter(qoverp, Trk::qOverP)); + Trk::LocalParameters segLocPar(defPars); + msegment = new MuonSegment(segLocPar, covMatrix, surf, rioVec, quality, Trk::Segment::DCMathSegmentMakerCurved); + } else { // straight segments + // errors (for now no correlations) + Amg::MatrixX covMatrix(4, 4); + covMatrix.setIdentity(); + covMatrix(0, 0) = dlocx * dlocx; + covMatrix(1, 1) = segment.dy0() * segment.dy0(); + covMatrix(2, 2) = dangleXZ * dangleXZ; + covMatrix(3, 3) = segment.dtheta() * segment.dtheta(); + msegment = + new MuonSegment(segLocPos, segLocDir, covMatrix, surf, rioVec, quality, Trk::Segment::DCMathSegmentMaker); + } + + if (hasFittedT0) msegment->setT0Error(fittedT0, errorFittedT0); // check whether segment satisfies minimum quality criteria int segmentQuality = m_segmentSelectionTool->quality(*msegment); - - if( msgLvl(MSG::DEBUG) ) { - ATH_MSG_DEBUG(m_printer->print(*msegment) << " quality " << segmentQuality); - if( segmentQuality < 0 ) ATH_MSG_DEBUG(" BAD segment "); - if( hasFittedT0 ) ATH_MSG_DEBUG(" T0 " << fittedT0); - if( isCurvedSegment ) ATH_MSG_DEBUG(" Curved " << fittedT0); - } - if( segmentQuality < 0 ){ - delete msegment; - msegment = 0; - } - for(std::vector<const Trk::MeasurementBase*>::iterator it=measToBeDeleted.begin(); it!=measToBeDeleted.end(); it++) - delete (*it); + + if (msgLvl(MSG::DEBUG)) { + ATH_MSG_DEBUG(m_printer->print(*msegment) << " quality " << segmentQuality); + if (segmentQuality < 0) ATH_MSG_DEBUG(" BAD segment "); + if (hasFittedT0) ATH_MSG_DEBUG(" T0 " << fittedT0); + if (isCurvedSegment) ATH_MSG_DEBUG(" Curved " << fittedT0); + } + if (segmentQuality < 0) { + delete msegment; + msegment = 0; + } + for (std::vector<const Trk::MeasurementBase*>::iterator it = measToBeDeleted.begin(); it != measToBeDeleted.end(); + it++) + delete (*it); measToBeDeleted.clear(); return msegment; - } +} - void DCMathSegmentMaker::find( const std::vector<const Trk::RIO_OnTrack*>& rios, Trk::SegmentCollection* segColl) const - { +void +DCMathSegmentMaker::find(const std::vector<const Trk::RIO_OnTrack*>& rios, Trk::SegmentCollection* segColl) const +{ std::vector<const MdtDriftCircleOnTrack*> mdts; std::vector<const MuonClusterOnTrack*> clusters; - std::vector<const Trk::RIO_OnTrack*>::const_iterator it = rios.begin(); + std::vector<const Trk::RIO_OnTrack*>::const_iterator it = rios.begin(); std::vector<const Trk::RIO_OnTrack*>::const_iterator it_end = rios.end(); - for( ; it!=it_end;++it ){ - - Identifier id = (*it)->identify(); - if( m_idHelperSvc->isMdt(id) ){ - const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(*it); - if( !mdt ){ - ATH_MSG_WARNING("failed dynamic_cast, not a MDT but hit has MDT id!!!"); - } - mdts.push_back(mdt); - }else if( m_idHelperSvc->isTrigger(id) ){ - const MuonClusterOnTrack* clus = dynamic_cast<const MuonClusterOnTrack*>(*it); - if( !clus ){ - ATH_MSG_WARNING("failed dynamic_cast, not a cluster but hit has RPC/TGC id!!!"); - } - clusters.push_back(clus); - } - } - find(mdts,clusters,segColl); - } - - void DCMathSegmentMaker::find( const std::vector<const MdtDriftCircleOnTrack*>& mdts, - const std::vector<const MuonClusterOnTrack*>& clusters, - Trk::SegmentCollection* segColl) const - { - if( mdts.empty() ) return; + for (; it != it_end; ++it) { + + Identifier id = (*it)->identify(); + if (m_idHelperSvc->isMdt(id)) { + const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(*it); + if (!mdt) { + ATH_MSG_WARNING("failed dynamic_cast, not a MDT but hit has MDT id!!!"); + } + mdts.push_back(mdt); + } else if (m_idHelperSvc->isTrigger(id)) { + const MuonClusterOnTrack* clus = dynamic_cast<const MuonClusterOnTrack*>(*it); + if (!clus) { + ATH_MSG_WARNING("failed dynamic_cast, not a cluster but hit has RPC/TGC id!!!"); + } + clusters.push_back(clus); + } + } + find(mdts, clusters, segColl); +} + +void +DCMathSegmentMaker::find(const std::vector<const MdtDriftCircleOnTrack*>& mdts, + const std::vector<const MuonClusterOnTrack*>& clusters, Trk::SegmentCollection* segColl) const +{ + if (mdts.empty()) return; const MdtDriftCircleOnTrack* mdt = mdts.front(); - if( !mdt ) return; - - bool hasPhiMeasurements = false; - Amg::Vector3D gpos = mdt->globalPosition(); - Amg::Vector3D gdir = Amg::Vector3D(gpos.x(),gpos.y(),gpos.z()).unit(); - find( gpos, - gdir, - mdts, - clusters, - hasPhiMeasurements, - segColl); - } - - - void DCMathSegmentMaker::find( const std::vector<const Trk::RIO_OnTrack*>& rios1, - const std::vector<const Trk::RIO_OnTrack*>& rios2 ) const - { + if (!mdt) return; + + bool hasPhiMeasurements = false; + Amg::Vector3D gpos = mdt->globalPosition(); + Amg::Vector3D gdir = Amg::Vector3D(gpos.x(), gpos.y(), gpos.z()).unit(); + find(gpos, gdir, mdts, clusters, hasPhiMeasurements, segColl); +} + + +void +DCMathSegmentMaker::find(const std::vector<const Trk::RIO_OnTrack*>& rios1, + const std::vector<const Trk::RIO_OnTrack*>& rios2) const +{ std::vector<const Trk::RIO_OnTrack*> rios = rios1; - rios.insert( rios.end(), rios2.begin(), rios2.end() ); + rios.insert(rios.end(), rios2.begin(), rios2.end()); find(rios); - } - - void DCMathSegmentMaker::find( const Trk::TrackRoad& road, - const std::vector< std::vector< const MdtDriftCircleOnTrack* > >& mdts, - const std::vector< std::vector< const MuonClusterOnTrack* > >& clusters, - Trk::SegmentCollection* segColl, - bool hasPhiMeasurements, double momentum ) const - { +} + +void +DCMathSegmentMaker::find(const Trk::TrackRoad& road, + const std::vector<std::vector<const MdtDriftCircleOnTrack*> >& mdts, + const std::vector<std::vector<const MuonClusterOnTrack*> >& clusters, + Trk::SegmentCollection* segColl, bool hasPhiMeasurements, double momentum) const +{ // copy all mdt hits into one vector - std::vector< const MdtDriftCircleOnTrack* > all_mdts; - std::vector< std::vector< const MdtDriftCircleOnTrack* > >::const_iterator mit = mdts.begin(); - std::vector< std::vector< const MdtDriftCircleOnTrack* > >::const_iterator mit_end = mdts.end(); - for(; mit!=mit_end;++mit ){ - std::copy( mit->begin(), mit->end(), std::back_inserter(all_mdts) ); + std::vector<const MdtDriftCircleOnTrack*> all_mdts; + std::vector<std::vector<const MdtDriftCircleOnTrack*> >::const_iterator mit = mdts.begin(); + std::vector<std::vector<const MdtDriftCircleOnTrack*> >::const_iterator mit_end = mdts.end(); + for (; mit != mit_end; ++mit) { + std::copy(mit->begin(), mit->end(), std::back_inserter(all_mdts)); } // copy all clusters into one vector - std::vector< const MuonClusterOnTrack* > all_clus; - std::vector< std::vector< const MuonClusterOnTrack* > >::const_iterator cit = clusters.begin(); - std::vector< std::vector< const MuonClusterOnTrack* > >::const_iterator cit_end = clusters.end(); - for(; cit!=cit_end;++cit ){ - std::copy( cit->begin(), cit->end(), std::back_inserter(all_clus) ); + std::vector<const MuonClusterOnTrack*> all_clus; + std::vector<std::vector<const MuonClusterOnTrack*> >::const_iterator cit = clusters.begin(); + std::vector<std::vector<const MuonClusterOnTrack*> >::const_iterator cit_end = clusters.end(); + for (; cit != cit_end; ++cit) { + std::copy(cit->begin(), cit->end(), std::back_inserter(all_clus)); } - + const Amg::Vector3D& gpos = road.globalPosition(); const Amg::Vector3D& gdir = road.globalDirection(); - find( gpos, - gdir, - all_mdts, - all_clus, - hasPhiMeasurements, - segColl, - momentum, - road.deltaEta()); - - } + find(gpos, gdir, all_mdts, all_clus, hasPhiMeasurements, segColl, momentum, road.deltaEta()); +} - double DCMathSegmentMaker::errorScaleFactor( const Identifier& id, double curvature, bool hasPhiMeasurements ) const - { +double +DCMathSegmentMaker::errorScaleFactor(const Identifier& id, double curvature, bool hasPhiMeasurements) const +{ double scale = 1.; - if( !m_curvedErrorScaling ) return scale; + if (!m_curvedErrorScaling) return scale; - if( !errorScalingRegion( id ) ) return scale; + if (!errorScalingRegion(id)) return scale; double scaleMax = 5.; - if( m_curvedErrorScaling && curvature > 2 ){ - scale = 1. + curvature/10000; // 3*(curvature/30000) - if( scale > scaleMax ) scale = scaleMax; - ATH_MSG_DEBUG(" rescaled errors " << scale << " curvature " << curvature); - + if (m_curvedErrorScaling && curvature > 2) { + scale = 1. + curvature / 10000; // 3*(curvature/30000) + if (scale > scaleMax) scale = scaleMax; + ATH_MSG_DEBUG(" rescaled errors " << scale << " curvature " << curvature); } scale *= 2; - // rescale errors is no phi measurement was found - if( !hasPhiMeasurements ){ + // rescale errors is no phi measurement was found + if (!hasPhiMeasurements) { - double phiScale = 1.; - // rescale errors - int stRegion = m_idHelperSvc->mdtIdHelper().stationRegion(id); - if( stRegion == 0 ) phiScale = 2.; // inner - else if( stRegion == 1 ) phiScale = 2.5; // extended - else if( stRegion == 2 ) phiScale = 2.5; // middle - else phiScale = 3.; // outer - scale = sqrt( scale*scale + phiScale*phiScale ); - ATH_MSG_DEBUG(" rescaled error for missing phi road " << scale); + double phiScale = 1.; + // rescale errors + int stRegion = m_idHelperSvc->mdtIdHelper().stationRegion(id); + if (stRegion == 0) + phiScale = 2.; // inner + else if (stRegion == 1) + phiScale = 2.5; // extended + else if (stRegion == 2) + phiScale = 2.5; // middle + else + phiScale = 3.; // outer + scale = sqrt(scale * scale + phiScale * phiScale); + ATH_MSG_DEBUG(" rescaled error for missing phi road " << scale); } return scale; - } +} - bool DCMathSegmentMaker::errorScalingRegion( const Identifier& id ) const +bool +DCMathSegmentMaker::errorScalingRegion(const Identifier& id) const - { +{ // simple division of MuonSpectrometer in regions using barrel/endcap seperation plus // inner/middle/outer seperation bool isEndcap = m_idHelperSvc->isEndcap(id); - if( isEndcap ){ + if (isEndcap) { - std::string stName = m_idHelperSvc->mdtIdHelper().stationNameString(m_idHelperSvc->mdtIdHelper().stationName(id) ); - if( stName[1] == 'I' ) return true; + std::string stName = + m_idHelperSvc->mdtIdHelper().stationNameString(m_idHelperSvc->mdtIdHelper().stationName(id)); + if (stName[1] == 'I') return true; - }else{ - - return true; + } else { + return true; } return false; - } +} - DCMathSegmentMaker::ClusterVecPair DCMathSegmentMaker::create1DClusters( const std::vector<const MuonClusterOnTrack*>& clusters ) const - { +DCMathSegmentMaker::ClusterVecPair +DCMathSegmentMaker::create1DClusters(const std::vector<const MuonClusterOnTrack*>& clusters) const +{ // if empty return - if( clusters.empty() ) return ClusterVecPair(); + if (clusters.empty()) return ClusterVecPair(); // some useful typedefs... typedef std::vector<const MuonClusterOnTrack*>::const_iterator ROTCit; - + // create a vector to hold the clusters ClusterVec clVec; ClusterVec phiVec; clVec.reserve(clusters.size()); - ROTCit cit = clusters.begin(); + ROTCit cit = clusters.begin(); ROTCit cit_end = clusters.end(); - for( ;cit!=cit_end;++cit ){ - Identifier id = (*cit)->identify(); - Identifier gasGapId = m_idHelperSvc->gasGapId(id); - int measuresPhi = m_idHelperSvc->measuresPhi(id); - - if( measuresPhi ) { - phiVec.push_back( createSpacePoint( gasGapId, 0, *cit ) ); - if( phiVec.back().corrupt() ) phiVec.pop_back(); - }else{ - clVec.push_back( createSpacePoint( gasGapId, *cit, 0 ) ); - if( clVec.back().corrupt() ) clVec.pop_back(); - } - } - - return ClusterVecPair(clVec,phiVec); - } - - - DCMathSegmentMaker::ClusterVecPair DCMathSegmentMaker::create2DClusters( const std::vector<const MuonClusterOnTrack*>& clusters ) const - { + for (; cit != cit_end; ++cit) { + Identifier id = (*cit)->identify(); + Identifier gasGapId = m_idHelperSvc->gasGapId(id); + int measuresPhi = m_idHelperSvc->measuresPhi(id); + + if (measuresPhi) { + phiVec.push_back(createSpacePoint(gasGapId, 0, *cit)); + if (phiVec.back().corrupt()) phiVec.pop_back(); + } else { + clVec.push_back(createSpacePoint(gasGapId, *cit, 0)); + if (clVec.back().corrupt()) clVec.pop_back(); + } + } + + return ClusterVecPair(clVec, phiVec); +} + + +DCMathSegmentMaker::ClusterVecPair +DCMathSegmentMaker::create2DClusters(const std::vector<const MuonClusterOnTrack*>& clusters) const +{ // if empty return - if( clusters.empty() ) return ClusterVecPair(); - + if (clusters.empty()) return ClusterVecPair(); + ChIdHitMap gasGapHitMap; - ROTCit cit = clusters.begin(); + ROTCit cit = clusters.begin(); ROTCit cit_end = clusters.end(); - for( ;cit!=cit_end;++cit ){ - Identifier id = (*cit)->identify(); - ATH_MSG_VERBOSE(" new trigger hit " << m_idHelperSvc->toString( id )); - - Identifier chId = m_idHelperSvc->chamberId(id); - Identifier gasGapId = m_idHelperSvc->gasGapId(id); - int measuresPhi = m_idHelperSvc->measuresPhi(id); - - // eta hits first than phi hits - if( !measuresPhi ) gasGapHitMap[chId][gasGapId].first.push_back(*cit); - else gasGapHitMap[chId][gasGapId].second.push_back(*cit); - } - - return createSpacePoints( gasGapHitMap ); - } - - void DCMathSegmentMaker::handleChamber( DCMathSegmentMaker::IdHitMap& gasGapHitMap ) const { - - if( m_debugSpacePoints ) std::cout << " new chamber " << m_idHelperSvc->toString( gasGapHitMap.begin()->first ) << std::endl; + for (; cit != cit_end; ++cit) { + Identifier id = (*cit)->identify(); + ATH_MSG_VERBOSE(" new trigger hit " << m_idHelperSvc->toString(id)); + + Identifier chId = m_idHelperSvc->chamberId(id); + Identifier gasGapId = m_idHelperSvc->gasGapId(id); + int measuresPhi = m_idHelperSvc->measuresPhi(id); + + // eta hits first than phi hits + if (!measuresPhi) + gasGapHitMap[chId][gasGapId].first.push_back(*cit); + else + gasGapHitMap[chId][gasGapId].second.push_back(*cit); + } + + return createSpacePoints(gasGapHitMap); +} + +void +DCMathSegmentMaker::handleChamber(DCMathSegmentMaker::IdHitMap& gasGapHitMap) const +{ + + if (m_debugSpacePoints) + std::cout << " new chamber " << m_idHelperSvc->toString(gasGapHitMap.begin()->first) << std::endl; std::list<const Trk::PrepRawData*> prds; - - IdHitMapIt git = gasGapHitMap.begin(); + + IdHitMapIt git = gasGapHitMap.begin(); IdHitMapIt git_end = gasGapHitMap.end(); - for( ;git!=git_end;++git ){ - ROTCit hit = git->second.first.begin(); - ROTCit hit_end = git->second.first.end(); - for( ;hit!=hit_end;++hit ){ - double lpos = (*hit)->localParameters()[Trk::locX]; - if( m_debugSpacePoints ) std::cout << " new eta hit " << lpos << " " << m_idHelperSvc->toString( (*hit)->identify() ) << std::endl; - prds.push_back( (*hit)->prepRawData() ); - } - } - const CompetingMuonClustersOnTrack* rotEta = 0; - if( prds.size() > 1 ) { - rotEta = m_compClusterCreator->createBroadCluster( prds, 0. ); - if( m_debugSpacePoints ) std::cout << " --> new competing eta rot " << rotEta->localParameters()[Trk::locX] << " " - << Amg::error(rotEta->localCovariance(),Trk::locX) << std::endl; + for (; git != git_end; ++git) { + ROTCit hit = git->second.first.begin(); + ROTCit hit_end = git->second.first.end(); + for (; hit != hit_end; ++hit) { + double lpos = (*hit)->localParameters()[Trk::locX]; + if (m_debugSpacePoints) + std::cout << " new eta hit " << lpos << " " << m_idHelperSvc->toString((*hit)->identify()) + << std::endl; + prds.push_back((*hit)->prepRawData()); + } + } + const CompetingMuonClustersOnTrack* rotEta = 0; + if (prds.size() > 1) { + rotEta = m_compClusterCreator->createBroadCluster(prds, 0.); + if (m_debugSpacePoints) + std::cout << " --> new competing eta rot " << rotEta->localParameters()[Trk::locX] << " " + << Amg::error(rotEta->localCovariance(), Trk::locX) << std::endl; } prds.clear(); - git = gasGapHitMap.begin(); + git = gasGapHitMap.begin(); git_end = gasGapHitMap.end(); - for( ;git!=git_end;++git ){ - ROTCit hit = git->second.second.begin(); - ROTCit hit_end = git->second.second.end(); - for( ;hit!=hit_end;++hit ){ - double lpos = (*hit)->localParameters()[Trk::locX]; - if( m_debugSpacePoints ) std::cout << " new phi hit " << lpos << " " << m_idHelperSvc->toString( (*hit)->identify() ) << std::endl; - prds.push_back( (*hit)->prepRawData() ); - } + for (; git != git_end; ++git) { + ROTCit hit = git->second.second.begin(); + ROTCit hit_end = git->second.second.end(); + for (; hit != hit_end; ++hit) { + double lpos = (*hit)->localParameters()[Trk::locX]; + if (m_debugSpacePoints) + std::cout << " new phi hit " << lpos << " " << m_idHelperSvc->toString((*hit)->identify()) + << std::endl; + prds.push_back((*hit)->prepRawData()); + } } const CompetingMuonClustersOnTrack* rotPhi = 0; - if( prds.size() > 1 ) { - rotPhi = m_compClusterCreator->createBroadCluster( prds, 0. ); - if( m_debugSpacePoints ) std::cout << " --> new competing phi rot " << rotPhi->localParameters()[Trk::locX] - << " " << Amg::error(rotPhi->localCovariance(),Trk::locX) << std::endl; + if (prds.size() > 1) { + rotPhi = m_compClusterCreator->createBroadCluster(prds, 0.); + if (m_debugSpacePoints) + std::cout << " --> new competing phi rot " << rotPhi->localParameters()[Trk::locX] << " " + << Amg::error(rotPhi->localCovariance(), Trk::locX) << std::endl; } - } +} + +DCMathSegmentMaker::ClusterVecPair +DCMathSegmentMaker::createSpacePoints(DCMathSegmentMaker::ChIdHitMap& chIdHitMap) const +{ - DCMathSegmentMaker::ClusterVecPair DCMathSegmentMaker::createSpacePoints( DCMathSegmentMaker::ChIdHitMap& chIdHitMap ) const { - // vector to store output ClusterVecPair clusterVecs; clusterVecs.first.reserve(20); clusterVecs.second.reserve(20); - + // loop over chambers - ChIdHitMapIt cit = chIdHitMap.begin(); + ChIdHitMapIt cit = chIdHitMap.begin(); ChIdHitMapIt cit_end = chIdHitMap.end(); - for( ;cit!=cit_end;++cit ){ + for (; cit != cit_end; ++cit) { - // create clusters per chamber and copy them in to result vector - ClusterVecPair cls = createSpacePoints( cit->second ); - std::copy( cls.first.begin(), cls.first.end(), std::back_inserter(clusterVecs.first) ); - std::copy( cls.second.begin(), cls.second.end(), std::back_inserter(clusterVecs.second) ); + // create clusters per chamber and copy them in to result vector + ClusterVecPair cls = createSpacePoints(cit->second); + std::copy(cls.first.begin(), cls.first.end(), std::back_inserter(clusterVecs.first)); + std::copy(cls.second.begin(), cls.second.end(), std::back_inserter(clusterVecs.second)); - //handleChamber( cit->second ); + // handleChamber( cit->second ); } return clusterVecs; - } +} - DCMathSegmentMaker::ClusterVecPair DCMathSegmentMaker::createSpacePoints( DCMathSegmentMaker::IdHitMap& gasGapHitMap ) const { +DCMathSegmentMaker::ClusterVecPair +DCMathSegmentMaker::createSpacePoints(DCMathSegmentMaker::IdHitMap& gasGapHitMap) const +{ ClusterVec spacePoints; ClusterVec phiVec; - bool isEndcap=m_idHelperSvc->isEndcap((*(gasGapHitMap.begin())).first); - - ATH_MSG_VERBOSE(" creating Space points for " << gasGapHitMap.size() << " gas gaps "); + bool isEndcap = m_idHelperSvc->isEndcap((*(gasGapHitMap.begin())).first); - IdHitMapIt git = gasGapHitMap.begin(); + ATH_MSG_VERBOSE(" creating Space points for " << gasGapHitMap.size() << " gas gaps "); + + IdHitMapIt git = gasGapHitMap.begin(); IdHitMapIt git_end = gasGapHitMap.end(); - for( ;git!=git_end;++git ){ - - // flag whether phi hits are matched with a eta hit - std::vector<int> flagPhihit(git->second.second.size(),0); - - // store Identifier of previous hit to remove duplicates - Identifier prevEtaId; - - if( m_debugSpacePoints ) ATH_MSG_VERBOSE(" New gasgap " << m_idHelperSvc->toString(git->first) - << " neta " << git->second.first.size() - << " nphi " << git->second.second.size()); - - ROTCit etaIt = git->second.first.begin(); - ROTCit etaIt_end = git->second.first.end(); - for( ;etaIt!=etaIt_end;++etaIt ){ - - // check whether we are not dealing with a duplicate hit - if( (*etaIt)->identify() == prevEtaId ) continue; - prevEtaId = (*etaIt)->identify(); - - if( m_debugSpacePoints ) ATH_MSG_VERBOSE(" Eta hit " << m_idHelperSvc->toString((*etaIt)->identify())); - - if( isEndcap ) { - - // check whether match with phi hits was found - bool foundSP = false; - Identifier prevPhiId; - ROTCit phiIt = git->second.second.begin(); - ROTCit phiIt_begin = git->second.second.begin(); - ROTCit phiIt_end = git->second.second.end(); - for( ;phiIt!=phiIt_end;++phiIt ){ - - // check for duplicate phi hits - if( (*phiIt)->identify() == prevPhiId ) continue; - prevPhiId = (*phiIt)->identify(); - - if( m_debugSpacePoints ) ATH_MSG_VERBOSE(" Phi hit " << m_idHelperSvc->toString((*phiIt)->identify())); - - Cluster2D sp = createTgcSpacePoint( git->first, *etaIt, *phiIt ); - if( sp.corrupt() ) continue; - spacePoints.push_back( sp ); - - // mark as used - foundSP = true; - flagPhihit[ std::distance( phiIt_begin, phiIt ) ] = 1; - - } - - // add single eta hit if not matching phi hit was found - if( !foundSP ){ - Cluster2D sp = createSpacePoint( git->first, *etaIt, 0 ); - if( sp.corrupt() ) continue; - spacePoints.push_back( sp ); - } - }else{ - Cluster2D sp = createRpcSpacePoint( git->first, *etaIt, git->second.second ); - if( sp.corrupt() ) continue; - // flag all phi hits, not very elegant, but works - flagPhihit = std::vector<int>(git->second.second.size(),1); - spacePoints.push_back( sp ); - - } - } - if( isEndcap ){ - // loop over flag vector and add unmatched phi hits to phiVec; - Identifier prevPhiId; - for( unsigned int i=0;i<flagPhihit.size();++i ){ - if( flagPhihit[i] ) continue; - - // check for duplicate phi hits - if( git->second.second[i]->identify() == prevPhiId ) continue; - prevPhiId = git->second.second[i]->identify(); - - Cluster2D sp = createTgcSpacePoint( git->first, 0, git->second.second[i] ); - if( sp.corrupt() ) continue; - phiVec.push_back( sp ); - - } - }else if( git->second.first.empty() && !git->second.second.empty() ) { - // if there were no eta hits create one phi spacePoint of all phi hits in gasgap - Cluster2D sp = createRpcSpacePoint( git->first, 0, git->second.second ); - if( sp.corrupt() ) continue; - phiVec.push_back( sp ); - } - - } - - ATH_MSG_VERBOSE(" Creating space points, number of gas-gaps " << gasGapHitMap.size() - << " space points " << spacePoints.size()); - - return ClusterVecPair(spacePoints,phiVec); - } - - DCMathSegmentMaker::Cluster2D DCMathSegmentMaker::createSpacePoint( const Identifier& gasGapId, const MuonClusterOnTrack* etaHit, - const MuonClusterOnTrack* phiHit ) const - { - bool isEndcap=m_idHelperSvc->isEndcap(gasGapId); + for (; git != git_end; ++git) { + + // flag whether phi hits are matched with a eta hit + std::vector<int> flagPhihit(git->second.second.size(), 0); + + // store Identifier of previous hit to remove duplicates + Identifier prevEtaId; + + if (m_debugSpacePoints) + ATH_MSG_VERBOSE(" New gasgap " << m_idHelperSvc->toString(git->first) << " neta " + << git->second.first.size() << " nphi " << git->second.second.size()); + + ROTCit etaIt = git->second.first.begin(); + ROTCit etaIt_end = git->second.first.end(); + for (; etaIt != etaIt_end; ++etaIt) { + + // check whether we are not dealing with a duplicate hit + if ((*etaIt)->identify() == prevEtaId) continue; + prevEtaId = (*etaIt)->identify(); + + if (m_debugSpacePoints) ATH_MSG_VERBOSE(" Eta hit " << m_idHelperSvc->toString((*etaIt)->identify())); + + if (isEndcap) { + + // check whether match with phi hits was found + bool foundSP = false; + Identifier prevPhiId; + ROTCit phiIt = git->second.second.begin(); + ROTCit phiIt_begin = git->second.second.begin(); + ROTCit phiIt_end = git->second.second.end(); + for (; phiIt != phiIt_end; ++phiIt) { + + // check for duplicate phi hits + if ((*phiIt)->identify() == prevPhiId) continue; + prevPhiId = (*phiIt)->identify(); + + if (m_debugSpacePoints) + ATH_MSG_VERBOSE(" Phi hit " << m_idHelperSvc->toString((*phiIt)->identify())); + + Cluster2D sp = createTgcSpacePoint(git->first, *etaIt, *phiIt); + if (sp.corrupt()) continue; + spacePoints.push_back(sp); + + // mark as used + foundSP = true; + flagPhihit[std::distance(phiIt_begin, phiIt)] = 1; + } + + // add single eta hit if not matching phi hit was found + if (!foundSP) { + Cluster2D sp = createSpacePoint(git->first, *etaIt, 0); + if (sp.corrupt()) continue; + spacePoints.push_back(sp); + } + } else { + Cluster2D sp = createRpcSpacePoint(git->first, *etaIt, git->second.second); + if (sp.corrupt()) continue; + // flag all phi hits, not very elegant, but works + flagPhihit = std::vector<int>(git->second.second.size(), 1); + spacePoints.push_back(sp); + } + } + if (isEndcap) { + // loop over flag vector and add unmatched phi hits to phiVec; + Identifier prevPhiId; + for (unsigned int i = 0; i < flagPhihit.size(); ++i) { + if (flagPhihit[i]) continue; + + // check for duplicate phi hits + if (git->second.second[i]->identify() == prevPhiId) continue; + prevPhiId = git->second.second[i]->identify(); + + Cluster2D sp = createTgcSpacePoint(git->first, 0, git->second.second[i]); + if (sp.corrupt()) continue; + phiVec.push_back(sp); + } + } else if (git->second.first.empty() && !git->second.second.empty()) { + // if there were no eta hits create one phi spacePoint of all phi hits in gasgap + Cluster2D sp = createRpcSpacePoint(git->first, 0, git->second.second); + if (sp.corrupt()) continue; + phiVec.push_back(sp); + } + } + + ATH_MSG_VERBOSE(" Creating space points, number of gas-gaps " << gasGapHitMap.size() << " space points " + << spacePoints.size()); + + return ClusterVecPair(spacePoints, phiVec); +} + +DCMathSegmentMaker::Cluster2D +DCMathSegmentMaker::createSpacePoint(const Identifier& gasGapId, const MuonClusterOnTrack* etaHit, + const MuonClusterOnTrack* phiHit) const +{ + bool isEndcap = m_idHelperSvc->isEndcap(gasGapId); double error(1.); double lpx(0.); double lpy(0.); // case one hit missing. Take position and error of the available hit - if( !etaHit ){ - lpx = phiHit->localParameters()[Trk::locX]; - error = Amg::error(phiHit->localCovariance(),Trk::locX); - }else if( !phiHit ) { - lpx = etaHit->localParameters()[Trk::locX]; - error = Amg::error(etaHit->localCovariance(),Trk::locX); - }else if( etaHit && phiHit ) { - if( isEndcap ){ - return createTgcSpacePoint( gasGapId,etaHit,phiHit ); - }else{ - std::vector<const MuonClusterOnTrack*> phiVec; - phiVec.push_back(phiHit); - return createRpcSpacePoint( gasGapId,etaHit,phiVec ); - } + if (!etaHit) { + lpx = phiHit->localParameters()[Trk::locX]; + error = Amg::error(phiHit->localCovariance(), Trk::locX); + } else if (!phiHit) { + lpx = etaHit->localParameters()[Trk::locX]; + error = Amg::error(etaHit->localCovariance(), Trk::locX); + } else if (etaHit && phiHit) { + if (isEndcap) { + return createTgcSpacePoint(gasGapId, etaHit, phiHit); + } else { + std::vector<const MuonClusterOnTrack*> phiVec; + phiVec.push_back(phiHit); + return createRpcSpacePoint(gasGapId, etaHit, phiVec); + } } Identifier detElId = m_idHelperSvc->detElId(gasGapId); - if( std::abs(error) < 0.001 ){ - ATH_MSG_WARNING(" Unphysical error assigned for gasgap " << m_idHelperSvc->toString(gasGapId)); - error = 0.; + if (std::abs(error) < 0.001) { + ATH_MSG_WARNING(" Unphysical error assigned for gasgap " << m_idHelperSvc->toString(gasGapId)); + error = 0.; } - return Cluster2D(detElId,gasGapId,Amg::Vector2D(lpx,lpy),error,etaHit,phiHit); - } + return Cluster2D(detElId, gasGapId, Amg::Vector2D(lpx, lpy), error, etaHit, phiHit); +} - DCMathSegmentMaker::Cluster2D DCMathSegmentMaker::createTgcSpacePoint( const Identifier& gasGapId, const MuonClusterOnTrack* etaHit, - const MuonClusterOnTrack* phiHit ) const - { - double error(1.); - double lpx(0.); - double lpy(0.); +DCMathSegmentMaker::Cluster2D +DCMathSegmentMaker::createTgcSpacePoint(const Identifier& gasGapId, const MuonClusterOnTrack* etaHit, + const MuonClusterOnTrack* phiHit) const +{ + double error(1.); + double lpx(0.); + double lpy(0.); Identifier detElId = m_idHelperSvc->detElId(gasGapId); // case one hit missing. Take position and error of the available hit - if( !etaHit ){ - lpx = phiHit->localParameters()[Trk::locX]; - error = Amg::error(phiHit->localCovariance(),Trk::locX); - }else if( !phiHit ) { - lpx = etaHit->localParameters()[Trk::locX]; - error = Amg::error(etaHit->localCovariance(),Trk::locX); - }else if( etaHit && phiHit ){ - - - // get orientation angle of strip to rotate back from local frame to strip - // copy code from ROT creator - int stripNo = m_idHelperSvc->tgcIdHelper().channel(phiHit->identify()); - int gasGap = m_idHelperSvc->tgcIdHelper().gasGap(phiHit->identify()); - - const MuonGM::TgcReadoutElement* detEl = dynamic_cast<const MuonGM::TgcReadoutElement*>(etaHit->detectorElement()); - if (!detEl) { - ATH_MSG_WARNING("dynamic cast error returning"); - return Cluster2D(detElId,gasGapId,Amg::Vector2D(lpx,lpy),error,etaHit,phiHit); - } - // calculate local position of endpoint of strip - Amg::Vector3D lEtapos = detEl->localChannelPos(etaHit->identify()); - double localEtaY = detEl->stripCtrX(gasGap, stripNo, lEtapos.z() ); - if (0 < detEl->getStationEta()) { - localEtaY *= -1.; - } - Amg::Vector3D lSppos = lEtapos; - lSppos[1] = localEtaY; - - // transform to global - const Amg::Transform3D tgcTrans = detEl->absTransform(); - Amg::Vector3D gposSp = tgcTrans*lSppos; - lpx = etaHit->localParameters()[Trk::locX]; - error = Amg::error(etaHit->localCovariance(),Trk::locX); - if( error == 0. ){ - ATH_MSG_WARNING(" Unphysical error assigned for " << m_idHelperSvc->toString(etaHit->identify())); - if( etaHit->prepRawData() ) ATH_MSG_WARNING(" PRD error " << Amg::error(etaHit->prepRawData()->localCovariance(),Trk::locX)); - } - Amg::Vector2D lspPos(0.,0.); - if( etaHit->associatedSurface().globalToLocal( gposSp, gposSp,lspPos ) ){ - lpy = lspPos[Trk::locY]; - }else{ - ATH_MSG_WARNING(" globalToLocal failed "); - } - - if( m_debugSpacePoints ) std::cout << " TGC space point: error " << error << " stripWith " << error*sqrt(12) << std::endl - << " " << m_idHelperSvc->toString( etaHit->identify() ) << std::endl - << " " << m_idHelperSvc->toString( phiHit->identify() ) << std::endl; - - } - if( std::abs(error) < 0.001 ){ - ATH_MSG_WARNING(" Unphysical error assigned for gasgap " << m_idHelperSvc->toString(gasGapId)); - error = 1.; - } - return Cluster2D(detElId,gasGapId,Amg::Vector2D(lpx,lpy),error,etaHit,phiHit); - } - - - DCMathSegmentMaker::Cluster2D DCMathSegmentMaker::createRpcSpacePoint( const Identifier& gasGapId, const MuonClusterOnTrack* etaHit, - const std::vector<const MuonClusterOnTrack*>& phiHits ) const - { + if (!etaHit) { + lpx = phiHit->localParameters()[Trk::locX]; + error = Amg::error(phiHit->localCovariance(), Trk::locX); + } else if (!phiHit) { + lpx = etaHit->localParameters()[Trk::locX]; + error = Amg::error(etaHit->localCovariance(), Trk::locX); + } else if (etaHit && phiHit) { + + + // get orientation angle of strip to rotate back from local frame to strip + // copy code from ROT creator + int stripNo = m_idHelperSvc->tgcIdHelper().channel(phiHit->identify()); + int gasGap = m_idHelperSvc->tgcIdHelper().gasGap(phiHit->identify()); + + const MuonGM::TgcReadoutElement* detEl = + dynamic_cast<const MuonGM::TgcReadoutElement*>(etaHit->detectorElement()); + if (!detEl) { + ATH_MSG_WARNING("dynamic cast error returning"); + return Cluster2D(detElId, gasGapId, Amg::Vector2D(lpx, lpy), error, etaHit, phiHit); + } + // calculate local position of endpoint of strip + Amg::Vector3D lEtapos = detEl->localChannelPos(etaHit->identify()); + double localEtaY = detEl->stripCtrX(gasGap, stripNo, lEtapos.z()); + if (0 < detEl->getStationEta()) { + localEtaY *= -1.; + } + Amg::Vector3D lSppos = lEtapos; + lSppos[1] = localEtaY; + + // transform to global + const Amg::Transform3D tgcTrans = detEl->absTransform(); + Amg::Vector3D gposSp = tgcTrans * lSppos; + lpx = etaHit->localParameters()[Trk::locX]; + error = Amg::error(etaHit->localCovariance(), Trk::locX); + if (error == 0.) { + ATH_MSG_WARNING(" Unphysical error assigned for " << m_idHelperSvc->toString(etaHit->identify())); + if (etaHit->prepRawData()) + ATH_MSG_WARNING(" PRD error " << Amg::error(etaHit->prepRawData()->localCovariance(), Trk::locX)); + } + Amg::Vector2D lspPos(0., 0.); + if (etaHit->associatedSurface().globalToLocal(gposSp, gposSp, lspPos)) { + lpy = lspPos[Trk::locY]; + } else { + ATH_MSG_WARNING(" globalToLocal failed "); + } + + if (m_debugSpacePoints) + std::cout << " TGC space point: error " << error << " stripWith " << error * sqrt(12) << std::endl + << " " << m_idHelperSvc->toString(etaHit->identify()) << std::endl + << " " << m_idHelperSvc->toString(phiHit->identify()) << std::endl; + } + if (std::abs(error) < 0.001) { + ATH_MSG_WARNING(" Unphysical error assigned for gasgap " << m_idHelperSvc->toString(gasGapId)); + error = 1.; + } + return Cluster2D(detElId, gasGapId, Amg::Vector2D(lpx, lpy), error, etaHit, phiHit); +} + + +DCMathSegmentMaker::Cluster2D +DCMathSegmentMaker::createRpcSpacePoint(const Identifier& gasGapId, const MuonClusterOnTrack* etaHit, + const std::vector<const MuonClusterOnTrack*>& phiHits) const +{ // create vector to store phi hits after removal of duplicate hits std::vector<const MuonClusterOnTrack*> cleanPhihits; cleanPhihits.reserve(phiHits.size()); @@ -1346,123 +1375,131 @@ namespace Muon { double lpx(0.); double lpy(0.); // case one hit missing. Take position and error of the available hit - if( !etaHit ){ - lpx = phiHits.front()->localParameters()[Trk::locX]; - error = Amg::error(phiHits.front()->localCovariance(),Trk::locX); - // loop over phi hits, remove duplicate phi hits - Identifier prevId; - std::vector<const MuonClusterOnTrack*>::const_iterator pit = phiHits.begin(); - std::vector<const MuonClusterOnTrack*>::const_iterator pit_end = phiHits.end(); - for( ;pit!=pit_end;++pit ){ - - // remove duplicate phi hits - if( (*pit)->identify() == prevId ) continue; - prevId = (*pit)->identify(); - - cleanPhihits.push_back(*pit); - } - }else if( phiHits.empty() ) { - lpx = etaHit->localParameters()[Trk::locX]; - error = Amg::error(etaHit->localCovariance(),Trk::locX); - }else if( etaHit && !phiHits.empty() ) { - lpx = etaHit->localParameters()[Trk::locX]; - error = Amg::error(etaHit->localCovariance(),Trk::locX); - if( m_debugSpacePoints ) std::cout << " RPC space point: error " << error << " stripWith " << error*sqrt(12) << std::endl - << " " << m_idHelperSvc->toString( etaHit->identify() ) << std::endl; - - double minPos = 1e9; - double maxPos = -1e9; - Identifier prevId; - - // loop over phi hits, calculate average position + cluster width, remove duplicate phi hits - std::vector<const MuonClusterOnTrack*>::const_iterator pit = phiHits.begin(); - std::vector<const MuonClusterOnTrack*>::const_iterator pit_end = phiHits.end(); - for( ;pit!=pit_end;++pit ){ - - // remove duplicate phi hits - if( (*pit)->identify() == prevId ) continue; - prevId = (*pit)->identify(); - - // calculate phi hit position in local eta hit reference frame - Amg::Vector2D phiLocPos(0.,0.); - if( etaHit->associatedSurface().globalToLocal( (*pit)->globalPosition(),(*pit)->globalPosition(),phiLocPos ) ){ - lpy = phiLocPos[Trk::locY]; - if( lpy < minPos ) minPos = lpy; - if( lpy > maxPos ) maxPos = lpy; - if( m_debugSpacePoints ) std::cout << " " << m_idHelperSvc->toString( (*pit)->identify() ) << std::endl; - cleanPhihits.push_back(*pit); - } - } - if( m_debugSpacePoints && cleanPhihits.size() > 1 ) std::cout << " multiple phi hits: nhits " << cleanPhihits.size() - << " cl width " << maxPos - minPos << std::endl; - }else{ - ATH_MSG_DEBUG(" ARRRGGG got two empty pointers!!! "); + if (!etaHit) { + lpx = phiHits.front()->localParameters()[Trk::locX]; + error = Amg::error(phiHits.front()->localCovariance(), Trk::locX); + // loop over phi hits, remove duplicate phi hits + Identifier prevId; + std::vector<const MuonClusterOnTrack*>::const_iterator pit = phiHits.begin(); + std::vector<const MuonClusterOnTrack*>::const_iterator pit_end = phiHits.end(); + for (; pit != pit_end; ++pit) { + + // remove duplicate phi hits + if ((*pit)->identify() == prevId) continue; + prevId = (*pit)->identify(); + + cleanPhihits.push_back(*pit); + } + } else if (phiHits.empty()) { + lpx = etaHit->localParameters()[Trk::locX]; + error = Amg::error(etaHit->localCovariance(), Trk::locX); + } else if (etaHit && !phiHits.empty()) { + lpx = etaHit->localParameters()[Trk::locX]; + error = Amg::error(etaHit->localCovariance(), Trk::locX); + if (m_debugSpacePoints) + std::cout << " RPC space point: error " << error << " stripWith " << error * sqrt(12) << std::endl + << " " << m_idHelperSvc->toString(etaHit->identify()) << std::endl; + + double minPos = 1e9; + double maxPos = -1e9; + Identifier prevId; + + // loop over phi hits, calculate average position + cluster width, remove duplicate phi hits + std::vector<const MuonClusterOnTrack*>::const_iterator pit = phiHits.begin(); + std::vector<const MuonClusterOnTrack*>::const_iterator pit_end = phiHits.end(); + for (; pit != pit_end; ++pit) { + + // remove duplicate phi hits + if ((*pit)->identify() == prevId) continue; + prevId = (*pit)->identify(); + + // calculate phi hit position in local eta hit reference frame + Amg::Vector2D phiLocPos(0., 0.); + if (etaHit->associatedSurface().globalToLocal((*pit)->globalPosition(), (*pit)->globalPosition(), + phiLocPos)) { + lpy = phiLocPos[Trk::locY]; + if (lpy < minPos) minPos = lpy; + if (lpy > maxPos) maxPos = lpy; + if (m_debugSpacePoints) std::cout << " " << m_idHelperSvc->toString((*pit)->identify()) << std::endl; + cleanPhihits.push_back(*pit); + } + } + if (m_debugSpacePoints && cleanPhihits.size() > 1) + std::cout << " multiple phi hits: nhits " << cleanPhihits.size() << " cl width " << maxPos - minPos + << std::endl; + } else { + ATH_MSG_DEBUG(" ARRRGGG got two empty pointers!!! "); } Identifier detElId = m_idHelperSvc->detElId(gasGapId); - if( std::abs(error) < 0.001 ){ - ATH_MSG_WARNING(" Unphysical error assigned for gasgap " << m_idHelperSvc->toString(gasGapId)); - error = 1.; + if (std::abs(error) < 0.001) { + ATH_MSG_WARNING(" Unphysical error assigned for gasgap " << m_idHelperSvc->toString(gasGapId)); + error = 1.; } - return Cluster2D(detElId,gasGapId,Amg::Vector2D(lpx,lpy),error,etaHit, !cleanPhihits.empty() ? cleanPhihits : phiHits ); - } - + return Cluster2D(detElId, gasGapId, Amg::Vector2D(lpx, lpy), error, etaHit, + !cleanPhihits.empty() ? cleanPhihits : phiHits); +} + + +TrkDriftCircleMath::CLVec +DCMathSegmentMaker::createClusterVec(const Identifier& chid, ClusterVec& spVec, Amg::Transform3D gToStation) const +{ - TrkDriftCircleMath::CLVec DCMathSegmentMaker::createClusterVec( const Identifier& chid, ClusterVec& spVec, Amg::Transform3D gToStation ) const { - TrkDriftCircleMath::CLVec cls; - int chPhi = m_idHelperSvc->mdtIdHelper().stationPhi(chid); + int chPhi = m_idHelperSvc->mdtIdHelper().stationPhi(chid); // loop over clusters - ClusterIt cit=spVec.begin(); - ClusterIt cit_end=spVec.end(); - int index = 0; + ClusterIt cit = spVec.begin(); + ClusterIt cit_end = spVec.end(); + int index = 0; cls.reserve(spVec.size()); - for( ; cit!=cit_end;++cit ){ - - const MuonClusterOnTrack* meas = cit->etaHit ? cit->etaHit : cit->phiHit; - // construct cluster id - Identifier id = meas->identify(); - int measuresPhi = m_idHelperSvc->measuresPhi(id); - int eta = m_idHelperSvc->stationEta(id); - int phi = m_idHelperSvc->stationPhi(id); - int isTgc = m_idHelperSvc->isTgc(id); - int name = isTgc ? m_idHelperSvc->tgcIdHelper().stationName(id) : m_idHelperSvc->rpcIdHelper().stationName(id); - if( !isTgc ){ - if( chPhi != phi ){ - ATH_MSG_VERBOSE(" Discarding cluster, wrong station phi " << m_idHelperSvc->toString(id)); - ++index; - continue; - } - } - TrkDriftCircleMath::ClusterId clid( name,eta,phi,isTgc,measuresPhi ); - - // calculate local cluster position - Amg::Vector3D locPos = gToStation*cit->globalPos; - TrkDriftCircleMath::LocPos lp(locPos.y(),locPos.z()); - - if( std::abs(lp.y()) > m_maxAssociateClusterDistance ) { - ATH_MSG_VERBOSE(" Discarding cluster with large distance from chamber " << m_idHelperSvc->toString(id)); - ++index; - continue; - } - ATH_MSG_VERBOSE(" " << m_idHelperSvc->toString(id) - << " clid: " << clid.id() << " central phi " << meas->detectorElement()->center().phi() << " index " << index); - double err = cit->error; - TrkDriftCircleMath::Cluster cl( lp, err, clid, index ); - cls.push_back( cl); - - ++index; + for (; cit != cit_end; ++cit) { + + const MuonClusterOnTrack* meas = cit->etaHit ? cit->etaHit : cit->phiHit; + // construct cluster id + Identifier id = meas->identify(); + int measuresPhi = m_idHelperSvc->measuresPhi(id); + int eta = m_idHelperSvc->stationEta(id); + int phi = m_idHelperSvc->stationPhi(id); + int isTgc = m_idHelperSvc->isTgc(id); + int name = isTgc ? m_idHelperSvc->tgcIdHelper().stationName(id) : m_idHelperSvc->rpcIdHelper().stationName(id); + if (!isTgc) { + if (chPhi != phi) { + ATH_MSG_VERBOSE(" Discarding cluster, wrong station phi " << m_idHelperSvc->toString(id)); + ++index; + continue; + } + } + TrkDriftCircleMath::ClusterId clid(name, eta, phi, isTgc, measuresPhi); + + // calculate local cluster position + Amg::Vector3D locPos = gToStation * cit->globalPos; + TrkDriftCircleMath::LocPos lp(locPos.y(), locPos.z()); + + if (std::abs(lp.y()) > m_maxAssociateClusterDistance) { + ATH_MSG_VERBOSE(" Discarding cluster with large distance from chamber " << m_idHelperSvc->toString(id)); + ++index; + continue; + } + ATH_MSG_VERBOSE(" " << m_idHelperSvc->toString(id) << " clid: " << clid.id() << " central phi " + << meas->detectorElement()->center().phi() << " index " << index); + double err = cit->error; + TrkDriftCircleMath::Cluster cl(lp, err, clid, index); + cls.push_back(cl); + + ++index; } return cls; - } +} + +TrkDriftCircleMath::DCVec +DCMathSegmentMaker::createDCVec(const std::vector<const MdtDriftCircleOnTrack*>& mdts, double errorScale, + std::set<Identifier>& chamberSet, double& phimin, double& phimax, + TrkDriftCircleMath::DCStatistics& dcStatistics, Amg::Transform3D gToStation, + Amg::Transform3D amdbToGlobal) const +{ - - TrkDriftCircleMath::DCVec DCMathSegmentMaker::createDCVec( const std::vector<const MdtDriftCircleOnTrack*>& mdts, double errorScale, std::set<Identifier>& chamberSet, - double& phimin, double& phimax, TrkDriftCircleMath::DCStatistics& dcStatistics, - Amg::Transform3D gToStation, Amg::Transform3D amdbToGlobal) const { - TrkDriftCircleMath::DCVec dcs; /* ******** Mdt hits ******** */ @@ -1473,82 +1510,84 @@ namespace Muon { bool firstMdt = true; unsigned index = 0; - for( std::vector<const MdtDriftCircleOnTrack*>::const_iterator it=mdts.begin();it!=mdts.end();++it){ - - const MdtDriftCircleOnTrack* rot = *it; - - if( !rot ){ - ATH_MSG_WARNING(" rot not a MdtDriftCircleOnTrack "); - ++index; - continue; - } - const MuonGM::MdtReadoutElement* detEl = rot->prepRawData()->detectorElement(); - - if( !detEl ){ - ATH_MSG_WARNING(" aborting not detEl found "); - return TrkDriftCircleMath::DCVec(); - } - - Identifier id = (*it)->identify(); - Identifier elId = m_idHelperSvc->mdtIdHelper().elementID( id ); - - - // calculate local AMDB position - Amg::Vector3D locPos = gToStation*rot->prepRawData()->globalPosition(); - TrkDriftCircleMath::LocPos lpos(locPos.y(),locPos.z()); - - double r = rot->localParameters()[Trk::locR]; - double dr = Amg::error(rot->localCovariance(),Trk::locR)*errorScale; - - // create identifier - TrkDriftCircleMath::MdtId mdtid( m_idHelperSvc->mdtIdHelper().isBarrel(id),m_idHelperSvc->mdtIdHelper().multilayer(id)-1, - m_idHelperSvc->mdtIdHelper().tubeLayer(id)-1, m_idHelperSvc->mdtIdHelper().tube(id)-1 ); - - // - double preciseError = dr; - if( m_usePreciseError ) { - preciseError = m_preciseErrorScale*(0.23*std::exp(-std::abs(r)/6.06)+0.0362); - } - // create new DriftCircle - TrkDriftCircleMath::DriftCircle dc( lpos, r, dr, preciseError, TrkDriftCircleMath::DriftCircle::InTime, mdtid, index, rot ); - - - - TubeEnds tubeEnds = localTubeEnds(*rot,gToStation,amdbToGlobal); - if( firstMdt ){ - phimin = tubeEnds.phimin; - phimax = tubeEnds.phimax; - firstMdt = false; - }else{ - updatePhiRanges(tubeEnds.phimin,tubeEnds.phimax,phimin,phimax); - } - - if( msgLvl(MSG::VERBOSE) ) { - ATH_MSG_VERBOSE(" new MDT hit " << m_idHelperSvc->toString( id ) << " x " << lpos.x() << " y " << lpos.y() - << " time " << rot->driftTime() << " r " << r << " dr " << dr << " phi range " << tubeEnds.phimin << " " << tubeEnds.phimax); - if( m_usePreciseError ) ATH_MSG_VERBOSE(" dr(2) " << preciseError); - } - dcs.push_back( dc ); - - chamberSet.insert(elId); - - ++dcStatistics[detEl]; - - ++index; - - } - + for (std::vector<const MdtDriftCircleOnTrack*>::const_iterator it = mdts.begin(); it != mdts.end(); ++it) { + + const MdtDriftCircleOnTrack* rot = *it; + + if (!rot) { + ATH_MSG_WARNING(" rot not a MdtDriftCircleOnTrack "); + ++index; + continue; + } + const MuonGM::MdtReadoutElement* detEl = rot->prepRawData()->detectorElement(); + + if (!detEl) { + ATH_MSG_WARNING(" aborting not detEl found "); + return TrkDriftCircleMath::DCVec(); + } + + Identifier id = (*it)->identify(); + Identifier elId = m_idHelperSvc->mdtIdHelper().elementID(id); + + + // calculate local AMDB position + Amg::Vector3D locPos = gToStation * rot->prepRawData()->globalPosition(); + TrkDriftCircleMath::LocPos lpos(locPos.y(), locPos.z()); + + double r = rot->localParameters()[Trk::locR]; + double dr = Amg::error(rot->localCovariance(), Trk::locR) * errorScale; + + // create identifier + TrkDriftCircleMath::MdtId mdtid( + m_idHelperSvc->mdtIdHelper().isBarrel(id), m_idHelperSvc->mdtIdHelper().multilayer(id) - 1, + m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1, m_idHelperSvc->mdtIdHelper().tube(id) - 1); + + // + double preciseError = dr; + if (m_usePreciseError) { + preciseError = m_preciseErrorScale * (0.23 * std::exp(-std::abs(r) / 6.06) + 0.0362); + } + // create new DriftCircle + TrkDriftCircleMath::DriftCircle dc(lpos, r, dr, preciseError, TrkDriftCircleMath::DriftCircle::InTime, mdtid, + index, rot); + + + TubeEnds tubeEnds = localTubeEnds(*rot, gToStation, amdbToGlobal); + if (firstMdt) { + phimin = tubeEnds.phimin; + phimax = tubeEnds.phimax; + firstMdt = false; + } else { + updatePhiRanges(tubeEnds.phimin, tubeEnds.phimax, phimin, phimax); + } + + if (msgLvl(MSG::VERBOSE)) { + ATH_MSG_VERBOSE(" new MDT hit " << m_idHelperSvc->toString(id) << " x " << lpos.x() << " y " << lpos.y() + << " time " << rot->driftTime() << " r " << r << " dr " << dr + << " phi range " << tubeEnds.phimin << " " << tubeEnds.phimax); + if (m_usePreciseError) ATH_MSG_VERBOSE(" dr(2) " << preciseError); + } + dcs.push_back(dc); + + chamberSet.insert(elId); + + ++dcStatistics[detEl]; + + ++index; + } + return dcs; - } +} - TrkDriftCircleMath::MdtChamberGeometry DCMathSegmentMaker::createChamberGeometry( const Identifier& chid, - const Amg::Transform3D& gToStation ) const { +TrkDriftCircleMath::MdtChamberGeometry +DCMathSegmentMaker::createChamberGeometry(const Identifier& chid, const Amg::Transform3D& gToStation) const +{ /* calculate chamber geometry it takes as input: distance between the first and second tube in the chamber within a layer along the tube layer (tube distance) - distance between the first tube in the first layer and the first tube in the second layer along the tube layer (tube stagering) - distance between the first and second layer perpendicular to the tube layers (layer distance) + distance between the first tube in the first layer and the first tube in the second layer along the tube layer + (tube stagering) distance between the first and second layer perpendicular to the tube layers (layer distance) position of the first hit in ml 0 and ml 1 (2D in plane) total number of multilayers total number of layers @@ -1560,311 +1599,329 @@ namespace Muon { Amg::Vector3D firstTubeMl1(0., 0., 0.); // get id - int eta = m_idHelperSvc->mdtIdHelper().stationEta(chid); - int phi = m_idHelperSvc->mdtIdHelper().stationPhi(chid); - int name = m_idHelperSvc->mdtIdHelper().stationName(chid); - int isBarrel = m_idHelperSvc->mdtIdHelper().isBarrel(chid); - int isSmallMdt = m_idHelperSvc->issMdt(chid); - TrkDriftCircleMath::MdtStationId stationId( isSmallMdt, isBarrel, name, eta, phi ); + int eta = m_idHelperSvc->mdtIdHelper().stationEta(chid); + int phi = m_idHelperSvc->mdtIdHelper().stationPhi(chid); + int name = m_idHelperSvc->mdtIdHelper().stationName(chid); + int isBarrel = m_idHelperSvc->mdtIdHelper().isBarrel(chid); + int isSmallMdt = m_idHelperSvc->issMdt(chid); + TrkDriftCircleMath::MdtStationId stationId(isSmallMdt, isBarrel, name, eta, phi); SG::ReadCondHandle<MuonGM::MuonDetectorManager> DetectorManagerHandle{m_DetectorManagerKey}; - const MuonGM::MuonDetectorManager* MuonDetMgr{*DetectorManagerHandle}; - if(MuonDetMgr==nullptr){ - ATH_MSG_ERROR("Null pointer to the read MuonDetectorManager conditions object"); + const MuonGM::MuonDetectorManager* MuonDetMgr{*DetectorManagerHandle}; + if (MuonDetMgr == nullptr) { + ATH_MSG_ERROR("Null pointer to the read MuonDetectorManager conditions object"); } // get detEL for first ml (always there) - const MuonGM::MdtReadoutElement* detEl1 = MuonDetMgr->getMdtReadoutElement( m_idHelperSvc->mdtIdHelper().channelID( name,eta,phi,1,1,1 ) ); + const MuonGM::MdtReadoutElement* detEl1 = + MuonDetMgr->getMdtReadoutElement(m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 1, 1)); const MuonGM::MdtReadoutElement* detEl2 = nullptr; - int ntube2 = 0; + int ntube2 = 0; // number of multilayers in chamber int nml = detEl1->nMDTinStation(); - + // treament of chambers with two ml - if( nml == 2 ){ - Identifier firstIdml1 = m_idHelperSvc->mdtIdHelper().channelID( name,eta,phi,2,1,1 ); - detEl2 = MuonDetMgr->getMdtReadoutElement( firstIdml1 ); - firstTubeMl1 = gToStation*(detEl2->surface( firstIdml1 ).center()); - ntube2 = detEl2->getNtubesperlayer(); + if (nml == 2) { + Identifier firstIdml1 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 2, 1, 1); + detEl2 = MuonDetMgr->getMdtReadoutElement(firstIdml1); + firstTubeMl1 = gToStation * (detEl2->surface(firstIdml1).center()); + ntube2 = detEl2->getNtubesperlayer(); } // number of layers and tubes - int nlay = detEl1->getNLayers(); + int nlay = detEl1->getNLayers(); int ntube1 = detEl1->getNtubesperlayer(); // position first tube in ml 0 - Identifier firstIdml0 = m_idHelperSvc->mdtIdHelper().channelID( name,eta,phi,1,1,1 ); - firstTubeMl0 = gToStation*(detEl1->surface( firstIdml0 ).center()); + Identifier firstIdml0 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 1, 1); + firstTubeMl0 = gToStation * (detEl1->surface(firstIdml0).center()); // position second tube in ml 0 - Identifier secondIdml0 = m_idHelperSvc->mdtIdHelper().channelID( name,eta,phi,1,1,2 ); - Amg::Vector3D secondTubeMl0 = gToStation*(detEl1->surface( secondIdml0 ).center()); + Identifier secondIdml0 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 1, 2); + Amg::Vector3D secondTubeMl0 = gToStation * (detEl1->surface(secondIdml0).center()); - TrkDriftCircleMath::LocPos firstTube0( firstTubeMl0.y(), firstTubeMl0.z() ); - TrkDriftCircleMath::LocPos firstTube1( firstTubeMl1.y(), firstTubeMl1.z() ); + TrkDriftCircleMath::LocPos firstTube0(firstTubeMl0.y(), firstTubeMl0.z()); + TrkDriftCircleMath::LocPos firstTube1(firstTubeMl1.y(), firstTubeMl1.z()); // position first tube ml 0 and 1 - Identifier firstIdml0lay1 = m_idHelperSvc->mdtIdHelper().channelID( name,eta,phi,1,2,1 ); - Amg::Vector3D firstTubeMl0lay1 = gToStation*(detEl1->surface( firstIdml0lay1 ).center()); + Identifier firstIdml0lay1 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 2, 1); + Amg::Vector3D firstTubeMl0lay1 = gToStation * (detEl1->surface(firstIdml0lay1).center()); - double tubeDist = (secondTubeMl0 - firstTubeMl0).y(); // distance between tube in a given layer + double tubeDist = (secondTubeMl0 - firstTubeMl0).y(); // distance between tube in a given layer double tubeStage = (firstTubeMl0lay1 - firstTubeMl0).y(); // tube stagering distance - double layDist = (firstTubeMl0lay1 - firstTubeMl0).z(); // distance between layers + double layDist = (firstTubeMl0lay1 - firstTubeMl0).z(); // distance between layers - TrkDriftCircleMath::MdtChamberGeometry mdtgeo(stationId,nml,nlay,ntube1,ntube2,firstTube0,firstTube1, - tubeDist,tubeStage,layDist,detEl1->surface().center().theta()); + TrkDriftCircleMath::MdtChamberGeometry mdtgeo(stationId, nml, nlay, ntube1, ntube2, firstTube0, firstTube1, + tubeDist, tubeStage, layDist, detEl1->surface().center().theta()); - if( msgLvl(MSG::VERBOSE) ) mdtgeo.print(); + if (msgLvl(MSG::VERBOSE)) mdtgeo.print(); return mdtgeo; - } +} + +std::vector<const Trk::MeasurementBase*> +DCMathSegmentMaker::associateMDTsToSegment( + const Amg::Vector3D& gdir, TrkDriftCircleMath::Segment& segment, + const std::vector<const MdtDriftCircleOnTrack*>& mdts, TrkDriftCircleMath::MdtMultiChamberGeometry* multiGeo, + Amg::Transform3D gToStation, Amg::Transform3D amdbToGlobal, std::set<Identifier>& deltaVec, + std::set<Identifier>& outoftimeVec, std::vector<std::pair<double, const Trk::MeasurementBase*> >& rioDistVec) const +{ - std::vector<const Trk::MeasurementBase*> DCMathSegmentMaker::associateMDTsToSegment( const Amg::Vector3D& gdir, TrkDriftCircleMath::Segment& segment, - const std::vector<const MdtDriftCircleOnTrack*>& mdts, - TrkDriftCircleMath::MdtMultiChamberGeometry* multiGeo, - Amg::Transform3D gToStation, Amg::Transform3D amdbToGlobal, - std::set<Identifier>& deltaVec, std::set<Identifier>& outoftimeVec, - std::vector<std::pair<double,const Trk::MeasurementBase*> >& rioDistVec) const { - // clear result vectors std::vector<const Trk::MeasurementBase*> measurementsToBeDeleted; // convert segment parameters + x position from road - const TrkDriftCircleMath::Line& line = segment.line(); + const TrkDriftCircleMath::Line& line = segment.line(); TrkDriftCircleMath::TransformToLine toLineml1(line); TrkDriftCircleMath::TransformToLine toLineml2(line); - if(segment.hasCurvatureParameters()) { - //ml2 segment direction - double ml2phi = line.phi() - segment.deltaAlpha(); - TrkDriftCircleMath::LocDir ml2dir(cos(ml2phi),sin(ml2phi)); - //ml2 segment position - const TrkDriftCircleMath::LocPos ml1LocPos = multiGeo->tubePosition(0,multiGeo->nlay(),0); - const TrkDriftCircleMath::LocPos ml2LocPos = multiGeo->tubePosition(1,1,0); - double chamberMidPtY = (ml1LocPos.y() + ml2LocPos.y())/2.0; - TrkDriftCircleMath::LocPos ml2pos(segment.deltab(),chamberMidPtY); - //construct the new ml2 segment line & transform - const TrkDriftCircleMath::Line ml2line(ml2pos,ml2dir); - TrkDriftCircleMath::TransformToLine tmptoLine(ml2line); - //set the ml2 line - toLineml2 = tmptoLine; - } - - - for( TrkDriftCircleMath::DCOnTrackIt dcit = segment.dcs().begin();dcit!=segment.dcs().end();++dcit ){ - - if( dcit->state() == TrkDriftCircleMath::DCOnTrack::Delta ) { - deltaVec.insert( mdts[dcit->index()]->identify() ); - } - - if( dcit->state() == TrkDriftCircleMath::DCOnTrack::OutOfTime ){ - outoftimeVec.insert( mdts[dcit->index()]->identify() ); - } - - if( dcit->state() != TrkDriftCircleMath::DCOnTrack::OnTrack ) continue; - - const MdtDriftCircleOnTrack* riodc = dynamic_cast<const MdtDriftCircleOnTrack*>( mdts[dcit->index()] ); - if( !riodc ) continue; - - - //choose which line to use (ml1 or ml2) - TrkDriftCircleMath::TransformToLine toLine = toLineml1; - if(m_idHelperSvc->mdtIdHelper().multilayer(riodc->identify()) == 2) toLine = toLineml2; - // calculate position of hit in line frame - TrkDriftCircleMath::LocPos pointOnHit = toLine.toLine( dcit->position() ); - - // calculate position of hit on line in line frame - TrkDriftCircleMath::LocPos pointOnLine( pointOnHit.x(), 0. ); - - // transform back to local AMDB coordinates - TrkDriftCircleMath::LocPos pointOnLineAMDB = toLine.toLocal( pointOnLine ); - - // get position along wire from ROT - Amg::Vector3D posAlong = gToStation*riodc->globalPosition(); - - // set yz components - posAlong[1] = pointOnLineAMDB.x(); - posAlong[2] = pointOnLineAMDB.y(); - - // back to global - Amg::Vector3D mdtGP = amdbToGlobal*posAlong; - - const Trk::StraightLineSurface* surf = dynamic_cast<const Trk::StraightLineSurface*>( &riodc->associatedSurface() ); - if( ! surf ){ - ATH_MSG_WARNING(" dynamic cast to StraightLineSurface failed for mdt!!! "); - continue; - } - - // calculate Amg::Vector2D using surf to obtain sign - Amg::Vector2D locPos(0.,0.); - if( ! surf->globalToLocal(mdtGP,gdir,locPos) ) ATH_MSG_WARNING(" globalToLocal failed "); - - // calculate side - Trk::DriftCircleSide side = locPos[Trk::driftRadius] < 0 ? Trk::LEFT : Trk::RIGHT; - - MdtDriftCircleOnTrack* nonconstDC = 0; - bool hasT0 = segment.hasT0Shift(); - if( !hasT0 ){ - //ATH_MSG_VERBOSE(" recalibrate MDT hit"); - nonconstDC = m_mdtCreator->createRIO_OnTrack(*riodc->prepRawData(),mdtGP,&gdir); - }else{ - ATH_MSG_VERBOSE(" recalibrate MDT hit with shift " << segment.t0Shift()); - nonconstDC = m_mdtCreatorT0->createRIO_OnTrack(*riodc->prepRawData(),mdtGP,&gdir,segment.t0Shift()); - } - - if( !nonconstDC ){ - dcit->state( TrkDriftCircleMath::DCOnTrack::OutOfTime ); - continue; - } - - // update the drift radius after recalibration, keep error - MdtDriftCircleOnTrack *new_drift_circle=new MdtDriftCircleOnTrack(*nonconstDC); - measurementsToBeDeleted.push_back(new_drift_circle); - TrkDriftCircleMath::DriftCircle new_dc(dcit->position(), std::abs(nonconstDC->driftRadius()), dcit->dr(), dcit->drPrecise(), - static_cast<TrkDriftCircleMath::DriftCircle *>(&(*dcit))->state() - , dcit->id(), dcit->index(),new_drift_circle); - TrkDriftCircleMath::DCOnTrack new_dc_on_track(new_dc, dcit->residual(), dcit->errorTrack()); - (*dcit)=new_dc_on_track; - - if( hasT0 ) { - if( msgLvl(MSG::VERBOSE) ){ - double shift = riodc->driftTime() - nonconstDC->driftTime(); - ATH_MSG_VERBOSE(" t0 shift " << segment.t0Shift() << " from hit " << shift - << " recal " << nonconstDC->driftRadius() << " t " << nonconstDC->driftTime() << " from fit " << dcit->r() - << " old " << riodc->driftRadius() << " t " << riodc->driftTime()); - if( std::abs( std::abs(nonconstDC->driftRadius()) - std::abs(dcit->r()) ) > 0.1 && nonconstDC->driftRadius() < 19. && nonconstDC->driftRadius() > 1. ) { - ATH_MSG_WARNING("Detected invalid recalibration after T0 shift"); - } - } - } - m_mdtCreator->updateSign( *nonconstDC, side ); - double dist = pointOnHit.x(); - rioDistVec.push_back( std::make_pair(dist,nonconstDC) ); + if (segment.hasCurvatureParameters()) { + // ml2 segment direction + double ml2phi = line.phi() - segment.deltaAlpha(); + TrkDriftCircleMath::LocDir ml2dir(cos(ml2phi), sin(ml2phi)); + // ml2 segment position + const TrkDriftCircleMath::LocPos ml1LocPos = multiGeo->tubePosition(0, multiGeo->nlay(), 0); + const TrkDriftCircleMath::LocPos ml2LocPos = multiGeo->tubePosition(1, 1, 0); + double chamberMidPtY = (ml1LocPos.y() + ml2LocPos.y()) / 2.0; + TrkDriftCircleMath::LocPos ml2pos(segment.deltab(), chamberMidPtY); + // construct the new ml2 segment line & transform + const TrkDriftCircleMath::Line ml2line(ml2pos, ml2dir); + TrkDriftCircleMath::TransformToLine tmptoLine(ml2line); + // set the ml2 line + toLineml2 = tmptoLine; + } + + + for (TrkDriftCircleMath::DCOnTrackIt dcit = segment.dcs().begin(); dcit != segment.dcs().end(); ++dcit) { + + if (dcit->state() == TrkDriftCircleMath::DCOnTrack::Delta) { + deltaVec.insert(mdts[dcit->index()]->identify()); + } + + if (dcit->state() == TrkDriftCircleMath::DCOnTrack::OutOfTime) { + outoftimeVec.insert(mdts[dcit->index()]->identify()); + } + + if (dcit->state() != TrkDriftCircleMath::DCOnTrack::OnTrack) continue; + + const MdtDriftCircleOnTrack* riodc = dynamic_cast<const MdtDriftCircleOnTrack*>(mdts[dcit->index()]); + if (!riodc) continue; + + + // choose which line to use (ml1 or ml2) + TrkDriftCircleMath::TransformToLine toLine = toLineml1; + if (m_idHelperSvc->mdtIdHelper().multilayer(riodc->identify()) == 2) toLine = toLineml2; + // calculate position of hit in line frame + TrkDriftCircleMath::LocPos pointOnHit = toLine.toLine(dcit->position()); + + // calculate position of hit on line in line frame + TrkDriftCircleMath::LocPos pointOnLine(pointOnHit.x(), 0.); + + // transform back to local AMDB coordinates + TrkDriftCircleMath::LocPos pointOnLineAMDB = toLine.toLocal(pointOnLine); + + // get position along wire from ROT + Amg::Vector3D posAlong = gToStation * riodc->globalPosition(); + + // set yz components + posAlong[1] = pointOnLineAMDB.x(); + posAlong[2] = pointOnLineAMDB.y(); + + // back to global + Amg::Vector3D mdtGP = amdbToGlobal * posAlong; + + const Trk::StraightLineSurface* surf = + dynamic_cast<const Trk::StraightLineSurface*>(&riodc->associatedSurface()); + if (!surf) { + ATH_MSG_WARNING(" dynamic cast to StraightLineSurface failed for mdt!!! "); + continue; + } + + // calculate Amg::Vector2D using surf to obtain sign + Amg::Vector2D locPos(0., 0.); + if (!surf->globalToLocal(mdtGP, gdir, locPos)) ATH_MSG_WARNING(" globalToLocal failed "); + + // calculate side + Trk::DriftCircleSide side = locPos[Trk::driftRadius] < 0 ? Trk::LEFT : Trk::RIGHT; + + MdtDriftCircleOnTrack* nonconstDC = 0; + bool hasT0 = segment.hasT0Shift(); + if (!hasT0) { + // ATH_MSG_VERBOSE(" recalibrate MDT hit"); + nonconstDC = m_mdtCreator->createRIO_OnTrack(*riodc->prepRawData(), mdtGP, &gdir); + } else { + ATH_MSG_VERBOSE(" recalibrate MDT hit with shift " << segment.t0Shift()); + nonconstDC = m_mdtCreatorT0->createRIO_OnTrack(*riodc->prepRawData(), mdtGP, &gdir, segment.t0Shift()); + } + + if (!nonconstDC) { + dcit->state(TrkDriftCircleMath::DCOnTrack::OutOfTime); + continue; + } + + // update the drift radius after recalibration, keep error + MdtDriftCircleOnTrack* new_drift_circle = new MdtDriftCircleOnTrack(*nonconstDC); + measurementsToBeDeleted.push_back(new_drift_circle); + TrkDriftCircleMath::DriftCircle new_dc(dcit->position(), std::abs(nonconstDC->driftRadius()), dcit->dr(), + dcit->drPrecise(), + static_cast<TrkDriftCircleMath::DriftCircle*>(&(*dcit))->state(), + dcit->id(), dcit->index(), new_drift_circle); + TrkDriftCircleMath::DCOnTrack new_dc_on_track(new_dc, dcit->residual(), dcit->errorTrack()); + (*dcit) = new_dc_on_track; + + if (hasT0) { + if (msgLvl(MSG::VERBOSE)) { + double shift = riodc->driftTime() - nonconstDC->driftTime(); + ATH_MSG_VERBOSE(" t0 shift " << segment.t0Shift() << " from hit " << shift << " recal " + << nonconstDC->driftRadius() << " t " << nonconstDC->driftTime() + << " from fit " << dcit->r() << " old " << riodc->driftRadius() << " t " + << riodc->driftTime()); + if (std::abs(std::abs(nonconstDC->driftRadius()) - std::abs(dcit->r())) > 0.1 + && nonconstDC->driftRadius() < 19. && nonconstDC->driftRadius() > 1.) + { + ATH_MSG_WARNING("Detected invalid recalibration after T0 shift"); + } + } + } + m_mdtCreator->updateSign(*nonconstDC, side); + double dist = pointOnHit.x(); + rioDistVec.push_back(std::make_pair(dist, nonconstDC)); } return measurementsToBeDeleted; - } - - - std::string DCMathSegmentMaker::printSP( std::pair<double,double> resPull,const DCMathSegmentMaker::Cluster2D& spacePoint ) const { +} + + +std::string +DCMathSegmentMaker::printSP(std::pair<double, double> resPull, const DCMathSegmentMaker::Cluster2D& spacePoint) const +{ std::ostringstream sout; - Identifier id; - if( spacePoint.etaHit != 0 && spacePoint.phiHit != 0 ){ - sout << " space point: "; - id = spacePoint.etaHit->identify(); - }else if( spacePoint.etaHit != 0 && spacePoint.phiHit == 0 ){ - sout << " eta hit: "; - id = spacePoint.etaHit->identify(); - }else if( spacePoint.etaHit == 0 && spacePoint.phiHit != 0 ){ - sout << " phi hit: "; - id = spacePoint.phiHit->identify(); - }else sout << " UNKNOWN TYPE "; - sout << " residual " << std::setw(5) << std::setprecision(3) << resPull.first << " pull " << std::setw(6) << resPull.second - << " " << m_idHelperSvc->toString( id ); + Identifier id; + if (spacePoint.etaHit != 0 && spacePoint.phiHit != 0) { + sout << " space point: "; + id = spacePoint.etaHit->identify(); + } else if (spacePoint.etaHit != 0 && spacePoint.phiHit == 0) { + sout << " eta hit: "; + id = spacePoint.etaHit->identify(); + } else if (spacePoint.etaHit == 0 && spacePoint.phiHit != 0) { + sout << " phi hit: "; + id = spacePoint.phiHit->identify(); + } else + sout << " UNKNOWN TYPE "; + sout << " residual " << std::setw(5) << std::setprecision(3) << resPull.first << " pull " << std::setw(6) + << resPull.second << " " << m_idHelperSvc->toString(id); return sout.str(); - } +} - template<class T> - struct IdDataVec { - typedef T Entry; - typedef std::vector<Entry> EntryVec; +template <class T> +struct IdDataVec { + typedef T Entry; + typedef std::vector<Entry> EntryVec; typedef typename EntryVec::iterator EntryIt; - + IdDataVec<T>() {} - IdDataVec<T>( const Identifier& i ) : id(i) {} + IdDataVec<T>(const Identifier& i) : id(i) {} Identifier id; EntryVec data; - }; - - template<class T> - struct SortIdDataVec { - bool operator()(const IdDataVec<T>& d1, const IdDataVec<T>& d2 ){ - return d1.id < d2.id; - } - }; - - struct SortClByPull { - bool operator()(const std::pair<double,DCMathSegmentMaker::Cluster2D>& d1, const std::pair<double,DCMathSegmentMaker::Cluster2D>& d2 ){ - return std::abs(d1.first) < std::abs(d2.first); - } - }; - - std::pair<std::pair<int,int>,bool> DCMathSegmentMaker::associateClustersToSegment( const TrkDriftCircleMath::Segment& segment, const Identifier& chid, - Amg::Transform3D gToStation, ClusterVecPair& spVecs, double phimin, double phimax, - std::vector<std::pair<double,const Trk::MeasurementBase*> >& rioDistVec ) const { - - typedef IdDataVec<std::pair<double,Cluster2D> > GasGapData; - typedef IdDataVec<GasGapData> ChamberData; - typedef std::vector<ChamberData> ChamberDataVec; - typedef ChamberDataVec::iterator ChamberDataIt; - ChamberDataVec chamberDataVec; - bool isEndcap=m_idHelperSvc->isEndcap(chid); +}; + +template <class T> +struct SortIdDataVec { + bool operator()(const IdDataVec<T>& d1, const IdDataVec<T>& d2) + { + return d1.id < d2.id; + } +}; + +struct SortClByPull { + bool operator()(const std::pair<double, DCMathSegmentMaker::Cluster2D>& d1, + const std::pair<double, DCMathSegmentMaker::Cluster2D>& d2) + { + return std::abs(d1.first) < std::abs(d2.first); + } +}; + +std::pair<std::pair<int, int>, bool> +DCMathSegmentMaker::associateClustersToSegment( + const TrkDriftCircleMath::Segment& segment, const Identifier& chid, Amg::Transform3D gToStation, + ClusterVecPair& spVecs, double phimin, double phimax, + std::vector<std::pair<double, const Trk::MeasurementBase*> >& rioDistVec) const +{ + + typedef IdDataVec<std::pair<double, Cluster2D> > GasGapData; + typedef IdDataVec<GasGapData> ChamberData; + typedef std::vector<ChamberData> ChamberDataVec; + typedef ChamberDataVec::iterator ChamberDataIt; + ChamberDataVec chamberDataVec; + bool isEndcap = m_idHelperSvc->isEndcap(chid); // keep track of the number of eta/phi hits on the segment - bool refit = false; - std::pair<std::pair<int,int>,bool> netaPhiHits(std::pair<int,int>(0,0),false); - if( segment.clusters().empty() ) return netaPhiHits; + bool refit = false; + std::pair<std::pair<int, int>, bool> netaPhiHits(std::pair<int, int>(0, 0), false); + if (segment.clusters().empty()) return netaPhiHits; std::vector<const Trk::MeasurementBase*> phiHits; // only refit if there are sufficient phi hits and no multiple phi hits per surface - refit = true; + refit = true; // keep track of detector elements which space points added to the track - std::set<Identifier> detElOnSegments; + std::set<Identifier> detElOnSegments; std::set<MuonStationIndex::PhiIndex> phiIndices; - ATH_MSG_DEBUG(" Associating clusters: " << segment.clusters().size() << " number of space points " << spVecs.first.size()); + ATH_MSG_DEBUG(" Associating clusters: " << segment.clusters().size() << " number of space points " + << spVecs.first.size()); // associate space points and sort them per detector element and gas gap - for( TrkDriftCircleMath::CLCit ccit = segment.clusters().begin();ccit!=segment.clusters().end();++ccit ){ - - ATH_MSG_VERBOSE(" accessing cluster: " << ccit->index()); - const Cluster2D& spacePoint = spVecs.first[ccit->index()]; - - // skip corrupt space points - if( spacePoint.corrupt() ) { - ATH_MSG_DEBUG(" Found corrupt space point: index " << ccit->index()); - continue; - } - // reject TGC clusters that are not 2D - if( m_reject1DTgcSpacePoints && !spacePoint.is2D() && m_idHelperSvc->isTgc(spacePoint.identify()) ) { - ATH_MSG_DEBUG(" Rejecting 1D tgc space point " << m_idHelperSvc->toString(spacePoint.identify())); - continue; - } - if( m_assumePointingPhi && spacePoint.is2D() && !checkPhiConsistency(spacePoint.globalPos.phi(), phimin, phimax) ){ - ATH_MSG_DEBUG(" Inconsistent phi angle, dropping space point: phi " << spacePoint.globalPos.phi() - << " range " << phimin << " " << phimax); - continue; - } - - std::pair<double,double> resPull = residualAndPullWithSegment( segment, spacePoint, gToStation ); - - // if empty or new chamber, add chamber - if( chamberDataVec.empty() || chamberDataVec.back().id != spacePoint.detElId ){ - detElOnSegments.insert(spacePoint.detElId); - chamberDataVec.push_back( ChamberData(spacePoint.detElId) ); - MuonStationIndex::PhiIndex phiIndex = m_idHelperSvc->phiIndex(spacePoint.detElId); - phiIndices.insert(phiIndex); - } - - // reference to current chamber data - ChamberData& chamber = chamberDataVec.back(); - - // if same detector element - if( spacePoint.detElId == chamber.id ){ - // if chamber empty or new gas gap, add gasp gap - if( chamber.data.empty() || chamber.data.back().id != spacePoint.gasGapId ){ - chamber.data.push_back( GasGapData(spacePoint.gasGapId) ); - } - } - - // reference to current gas gap data - GasGapData& gasGap = chamber.data.back(); - gasGap.data.push_back( std::make_pair(resPull.second,spacePoint) ); + for (TrkDriftCircleMath::CLCit ccit = segment.clusters().begin(); ccit != segment.clusters().end(); ++ccit) { + + ATH_MSG_VERBOSE(" accessing cluster: " << ccit->index()); + const Cluster2D& spacePoint = spVecs.first[ccit->index()]; + + // skip corrupt space points + if (spacePoint.corrupt()) { + ATH_MSG_DEBUG(" Found corrupt space point: index " << ccit->index()); + continue; + } + // reject TGC clusters that are not 2D + if (m_reject1DTgcSpacePoints && !spacePoint.is2D() && m_idHelperSvc->isTgc(spacePoint.identify())) { + ATH_MSG_DEBUG(" Rejecting 1D tgc space point " << m_idHelperSvc->toString(spacePoint.identify())); + continue; + } + if (m_assumePointingPhi && spacePoint.is2D() + && !checkPhiConsistency(spacePoint.globalPos.phi(), phimin, phimax)) { + ATH_MSG_DEBUG(" Inconsistent phi angle, dropping space point: phi " + << spacePoint.globalPos.phi() << " range " << phimin << " " << phimax); + continue; + } + + std::pair<double, double> resPull = residualAndPullWithSegment(segment, spacePoint, gToStation); + + // if empty or new chamber, add chamber + if (chamberDataVec.empty() || chamberDataVec.back().id != spacePoint.detElId) { + detElOnSegments.insert(spacePoint.detElId); + chamberDataVec.push_back(ChamberData(spacePoint.detElId)); + MuonStationIndex::PhiIndex phiIndex = m_idHelperSvc->phiIndex(spacePoint.detElId); + phiIndices.insert(phiIndex); + } + + // reference to current chamber data + ChamberData& chamber = chamberDataVec.back(); + + // if same detector element + if (spacePoint.detElId == chamber.id) { + // if chamber empty or new gas gap, add gasp gap + if (chamber.data.empty() || chamber.data.back().id != spacePoint.gasGapId) { + chamber.data.push_back(GasGapData(spacePoint.gasGapId)); + } + } + + // reference to current gas gap data + GasGapData& gasGap = chamber.data.back(); + gasGap.data.push_back(std::make_pair(resPull.second, spacePoint)); } // calculate the distance between the first and last station, use r in barrel and z in endcaps @@ -1873,1014 +1930,1093 @@ namespace Muon { // loop over chambers and create competing ROTs per chamber - ChamberDataIt cit = chamberDataVec.begin(); + ChamberDataIt cit = chamberDataVec.begin(); ChamberDataIt cit_end = chamberDataVec.end(); - for( ;cit!=cit_end;++cit ){ - - // select best clusters per gas gap in chamber - std::list<const Trk::PrepRawData*> etaClusterVec; - std::list<const Trk::PrepRawData*> phiClusterVec; - std::set<Identifier> etaIds; - // loop over gas gaps - ChamberData::EntryIt git = cit->data.begin(); - ChamberData::EntryIt git_end = cit->data.end(); - for( ;git!=git_end;++git ){ - - // sort space points by their pull with the segment - std::sort(git->data.begin(),git->data.end(),SortClByPull()); - - // select all space points with a pull that is within 1 of the best pull - double bestPull = std::abs(git->data.front().first); - - // count number of associated clusters in gas gap - unsigned int nassociatedSp = 0; - GasGapData::EntryIt cl_it = git->data.begin(); - while( cl_it != git->data.end() && std::abs(cl_it->first) - bestPull < 1. ){ - - Cluster2D& sp = cl_it->second; - - // calculate distance to segment - double dist = distanceToSegment( segment, sp.globalPos, gToStation ); - ATH_MSG_VERBOSE(" selected space point: " << m_idHelperSvc->toString( sp.identify() ) - << " pull " << std::abs(cl_it->first) << " distance to segment " << dist << " phi " << sp.globalPos.phi()); - - // here keep open the option not to create CompetingMuonClustersOnTrack - if( sp.etaHit ){ - - if( !etaIds.count(sp.etaHit->identify()) ) { - etaIds.insert(sp.etaHit->identify()); - - if( m_createCompetingROTsEta ) etaClusterVec.push_back( sp.etaHit->prepRawData() ); - else{ - rioDistVec.push_back( std::make_pair(dist,sp.etaHit->clone()) ); - ++netaPhiHits.first.first; - } - } - } - if( !sp.phiHits.empty() ) { - if( m_createCompetingROTsPhi ){ - // can have multiple phi hits per cluster, loop over phi hits and add them - for( std::vector<const MuonClusterOnTrack*>::iterator pit = sp.phiHits.begin();pit!=sp.phiHits.end();++pit ){ - phiClusterVec.push_back( (*pit)->prepRawData() ); - } - }else{ - // can have multiple phi hits per cluster, loop over phi hits and add them - for( std::vector<const MuonClusterOnTrack*>::iterator pit = sp.phiHits.begin();pit!=sp.phiHits.end();++pit ){ - rioDistVec.push_back( std::make_pair(dist,(*pit)->clone()) ); - ++netaPhiHits.first.second; - phiHits.push_back(*pit); - - // calculate position - double phiPos = isEndcap ? std::abs( (*pit)->globalPosition().z() ) : std::abs( (*pit)->globalPosition().perp() ); - if( phiPos < posFirstPhiStation ) posFirstPhiStation = phiPos; - if( phiPos > posLastPhiStation ) posLastPhiStation = phiPos; - } - if( sp.phiHits.size() > 1 ) refit = false; - } - } - ++nassociatedSp; - ++cl_it; - } - // multiple clusters in same gas gap, don't refit - if( !m_createCompetingROTsPhi && nassociatedSp > 1 ) refit = false; - } - - if( m_createCompetingROTsEta ){ - // create competing ROT for eta hits - if( !etaClusterVec.empty() ){ - const CompetingMuonClustersOnTrack* etaCompCluster = m_compClusterCreator->createBroadCluster(etaClusterVec,0.); - if( !etaCompCluster ){ - ATH_MSG_DEBUG(" failed to create competing ETA ROT " << etaClusterVec.size()); - }else{ - double dist = distanceToSegment( segment, etaCompCluster->globalPosition(), gToStation ); - rioDistVec.push_back( std::make_pair(dist,etaCompCluster) ); - ++netaPhiHits.first.first; - - if( msgLvl(MSG::VERBOSE) ){ - ATH_MSG_VERBOSE(" selected cluster: " << m_idHelperSvc->toString( etaClusterVec.front()->identify() )); - for( unsigned int i=0;i<etaCompCluster->containedROTs().size();++i){ - ATH_MSG_VERBOSE(" content: " << m_idHelperSvc->toString( etaCompCluster->containedROTs()[i]->identify() )); - } - } - } - } - } - - if( m_createCompetingROTsPhi ){ - // create competing ROT for phi hits - if( !phiClusterVec.empty() ) { - const CompetingMuonClustersOnTrack* phiCompCluster = m_compClusterCreator->createBroadCluster(phiClusterVec,0.); - if( !phiCompCluster ) { - ATH_MSG_DEBUG(" failed to create competing PHI ROT " << phiClusterVec.size()); - }else{ - double dist = distanceToSegment( segment, phiCompCluster->globalPosition(), gToStation ); - rioDistVec.push_back( std::make_pair(dist,phiCompCluster) ); - phiHits.push_back(phiCompCluster); - ++netaPhiHits.first.second; - - if( msgLvl(MSG::VERBOSE) ){ - ATH_MSG_VERBOSE(" selected cluster: " << m_idHelperSvc->toString( phiClusterVec.front()->identify() )); - for( unsigned int i=0;i<phiCompCluster->containedROTs().size();++i){ - ATH_MSG_VERBOSE(" content: " << m_idHelperSvc->toString( phiCompCluster->containedROTs()[i]->identify() )); - } - } - - // calculate position - double phiPos = isEndcap ? std::abs( phiCompCluster->globalPosition().z() ) : std::abs( phiCompCluster->globalPosition().perp() ); - if( phiPos < posFirstPhiStation ) posFirstPhiStation = phiPos; - if( phiPos > posLastPhiStation ) posLastPhiStation = phiPos; - } - } - } + for (; cit != cit_end; ++cit) { + + // select best clusters per gas gap in chamber + std::list<const Trk::PrepRawData*> etaClusterVec; + std::list<const Trk::PrepRawData*> phiClusterVec; + std::set<Identifier> etaIds; + // loop over gas gaps + ChamberData::EntryIt git = cit->data.begin(); + ChamberData::EntryIt git_end = cit->data.end(); + for (; git != git_end; ++git) { + + // sort space points by their pull with the segment + std::sort(git->data.begin(), git->data.end(), SortClByPull()); + + // select all space points with a pull that is within 1 of the best pull + double bestPull = std::abs(git->data.front().first); + + // count number of associated clusters in gas gap + unsigned int nassociatedSp = 0; + GasGapData::EntryIt cl_it = git->data.begin(); + while (cl_it != git->data.end() && std::abs(cl_it->first) - bestPull < 1.) { + + Cluster2D& sp = cl_it->second; + + // calculate distance to segment + double dist = distanceToSegment(segment, sp.globalPos, gToStation); + ATH_MSG_VERBOSE(" selected space point: " << m_idHelperSvc->toString(sp.identify()) << " pull " + << std::abs(cl_it->first) << " distance to segment " + << dist << " phi " << sp.globalPos.phi()); + + // here keep open the option not to create CompetingMuonClustersOnTrack + if (sp.etaHit) { + + if (!etaIds.count(sp.etaHit->identify())) { + etaIds.insert(sp.etaHit->identify()); + + if (m_createCompetingROTsEta) + etaClusterVec.push_back(sp.etaHit->prepRawData()); + else { + rioDistVec.push_back(std::make_pair(dist, sp.etaHit->clone())); + ++netaPhiHits.first.first; + } + } + } + if (!sp.phiHits.empty()) { + if (m_createCompetingROTsPhi) { + // can have multiple phi hits per cluster, loop over phi hits and add them + for (std::vector<const MuonClusterOnTrack*>::iterator pit = sp.phiHits.begin(); + pit != sp.phiHits.end(); ++pit) { + phiClusterVec.push_back((*pit)->prepRawData()); + } + } else { + // can have multiple phi hits per cluster, loop over phi hits and add them + for (std::vector<const MuonClusterOnTrack*>::iterator pit = sp.phiHits.begin(); + pit != sp.phiHits.end(); ++pit) { + rioDistVec.push_back(std::make_pair(dist, (*pit)->clone())); + ++netaPhiHits.first.second; + phiHits.push_back(*pit); + + // calculate position + double phiPos = isEndcap ? std::abs((*pit)->globalPosition().z()) + : std::abs((*pit)->globalPosition().perp()); + if (phiPos < posFirstPhiStation) posFirstPhiStation = phiPos; + if (phiPos > posLastPhiStation) posLastPhiStation = phiPos; + } + if (sp.phiHits.size() > 1) refit = false; + } + } + ++nassociatedSp; + ++cl_it; + } + // multiple clusters in same gas gap, don't refit + if (!m_createCompetingROTsPhi && nassociatedSp > 1) refit = false; + } + + if (m_createCompetingROTsEta) { + // create competing ROT for eta hits + if (!etaClusterVec.empty()) { + const CompetingMuonClustersOnTrack* etaCompCluster = + m_compClusterCreator->createBroadCluster(etaClusterVec, 0.); + if (!etaCompCluster) { + ATH_MSG_DEBUG(" failed to create competing ETA ROT " << etaClusterVec.size()); + } else { + double dist = distanceToSegment(segment, etaCompCluster->globalPosition(), gToStation); + rioDistVec.push_back(std::make_pair(dist, etaCompCluster)); + ++netaPhiHits.first.first; + + if (msgLvl(MSG::VERBOSE)) { + ATH_MSG_VERBOSE( + " selected cluster: " << m_idHelperSvc->toString(etaClusterVec.front()->identify())); + for (unsigned int i = 0; i < etaCompCluster->containedROTs().size(); ++i) { + ATH_MSG_VERBOSE(" content: " + << m_idHelperSvc->toString(etaCompCluster->containedROTs()[i]->identify())); + } + } + } + } + } + + if (m_createCompetingROTsPhi) { + // create competing ROT for phi hits + if (!phiClusterVec.empty()) { + const CompetingMuonClustersOnTrack* phiCompCluster = + m_compClusterCreator->createBroadCluster(phiClusterVec, 0.); + if (!phiCompCluster) { + ATH_MSG_DEBUG(" failed to create competing PHI ROT " << phiClusterVec.size()); + } else { + double dist = distanceToSegment(segment, phiCompCluster->globalPosition(), gToStation); + rioDistVec.push_back(std::make_pair(dist, phiCompCluster)); + phiHits.push_back(phiCompCluster); + ++netaPhiHits.first.second; + + if (msgLvl(MSG::VERBOSE)) { + ATH_MSG_VERBOSE( + " selected cluster: " << m_idHelperSvc->toString(phiClusterVec.front()->identify())); + for (unsigned int i = 0; i < phiCompCluster->containedROTs().size(); ++i) { + ATH_MSG_VERBOSE(" content: " + << m_idHelperSvc->toString(phiCompCluster->containedROTs()[i]->identify())); + } + } + + // calculate position + double phiPos = isEndcap ? std::abs(phiCompCluster->globalPosition().z()) + : std::abs(phiCompCluster->globalPosition().perp()); + if (phiPos < posFirstPhiStation) posFirstPhiStation = phiPos; + if (phiPos > posLastPhiStation) posLastPhiStation = phiPos; + } + } + } } // add phi hits that were not associated with an eta hit (only in barrel) - if( (!spVecs.second.empty()||m_recoverBadRpcCabling) && m_addUnassociatedPhiHits && !isEndcap ) { - - TrkDriftCircleMath::ResidualWithSegment resWithSegment(segment); - - std::map<Identifier,std::list<const Trk::PrepRawData*> > phiClusterMap; - - std::set<const MuonClusterOnTrack*> selectedClusters; - std::vector<Cluster2D*> phiClusters; - phiClusters.reserve(spVecs.second.size()); - - // create lists of PrepRawData per detector element - ClusterIt pit = spVecs.second.begin(); - ClusterIt pit_end = spVecs.second.end(); - for( ;pit!=pit_end;++pit ){ - if( !pit->phiHit || pit->corrupt() ) { - ATH_MSG_WARNING(" phi clusters without phi hit!!"); - continue; - } - phiClusters.push_back( &*pit); - selectedClusters.insert(pit->phiHit); - } - - unsigned int recoveredUnassociatedPhiHits(0); - if( m_recoverBadRpcCabling ){ - // now loop over 2D space points and add the phi hits to the list if the detEl is not yet added to the segment - ClusterIt spit = spVecs.first.begin(); - ClusterIt spit_end = spVecs.first.end(); - for( ;spit!=spit_end;++spit ){ - - // skip clusters without phi hit - if( !spit->phiHit || spit->corrupt() ) continue; - - // skip clusters in detector elements that are already associated (ok as this is only done for RPC) - if( detElOnSegments.count(spit->detElId) ) continue; - - MuonStationIndex::PhiIndex phiIndex = m_idHelperSvc->phiIndex(spit->detElId); - // skip clusters in detector layer - if( phiIndices.count(phiIndex) ) continue; - - - bool wasFound = false; - for( std::vector<const MuonClusterOnTrack*>::iterator it = spit->phiHits.begin();it!=spit->phiHits.end();++it ){ - - // now to avoid duplicate also skip if the given ROT is already in the list - std::pair<std::set<const MuonClusterOnTrack*>::iterator,bool> insertResult = selectedClusters.insert(*it); - if( !insertResult.second ) { - // flag as found - wasFound = true; - - // just because I'm paranoid, remove the hits from this cluster that were already inserted up to here - for( std::vector<const MuonClusterOnTrack*>::iterator rmit = spit->phiHits.begin();rmit!=it;++rmit ) selectedClusters.erase(*rmit); - break; - } - } - if( wasFound ) continue; - - // if we get here we should add the hit - phiClusters.push_back( &*spit); - ++recoveredUnassociatedPhiHits; - } - } - - unsigned int addedPhiHits(0); - std::vector<Cluster2D*>::iterator cit = phiClusters.begin(); - std::vector<Cluster2D*>::iterator cit_end = phiClusters.end(); - for( ;cit!=cit_end;++cit ){ - - const Identifier& detElId = (*cit)->detElId; - - // check that detector element is not already added to segment - if( detElOnSegments.count(detElId) ) continue; - - MuonStationIndex::PhiIndex phiIndex = m_idHelperSvc->phiIndex(detElId); - // skip clusters in detector layer - if( phiIndices.count(phiIndex) ) continue; - - // calculate local cluster position - Amg::Vector3D locPos = gToStation*(*cit)->globalPos; - - // calculate intersect of segment with cluster - TrkDriftCircleMath::Cluster cl(TrkDriftCircleMath::LocPos(locPos.y(),locPos.z()),1.); - double residual = resWithSegment.residual(cl); - double segError = sqrt(resWithSegment.trackError2(cl)); - const MuonGM::RpcReadoutElement* detEl = dynamic_cast<const MuonGM::RpcReadoutElement*>((*cit)->phiHit->detectorElement()); - if( !detEl ){ - ATH_MSG_WARNING("found RPC prd without RpcReadoutElement"); - continue; - } - - // perform bound check - double stripLength = detEl->StripLength(1); - bool inBounds = std::abs(residual) < 0.5*stripLength + 2. + segError ? true : false; - if( msgLvl(MSG::DEBUG) ) { - ATH_MSG_DEBUG(" Unassociated " << m_idHelperSvc->toString((*cit)->phiHit->identify()) - << " pos x " << cl.position().x() << " pos y " << cl.position().y() - << " : residual " << residual << " strip half length " << 0.5*stripLength << " segment error " << segError); - if( inBounds ) ATH_MSG_DEBUG(" inBounds"); - else ATH_MSG_DEBUG(" outBounds"); - } - if( inBounds ){ - // can have multiple phi hits per cluster, loop over phi hits and add them - for( std::vector<const MuonClusterOnTrack*>::iterator pit = (*cit)->phiHits.begin();pit!=(*cit)->phiHits.end();++pit ){ - phiClusterMap[detElId].push_back( (*pit)->prepRawData() ); - } - } - } - - // loop over detector elements and created competing ROTs - - std::map<Identifier,std::list<const Trk::PrepRawData*> >::iterator chit = phiClusterMap.begin(); - std::map<Identifier,std::list<const Trk::PrepRawData*> >::iterator chit_end = phiClusterMap.end(); - for( ;chit!=chit_end;++chit ){ - - std::list<const Trk::PrepRawData*>& prds = chit->second; - if( prds.empty() ) { - ATH_MSG_WARNING(" chamber without phi hits " << m_idHelperSvc->toString(chit->first)); - continue; - } - - const CompetingMuonClustersOnTrack* phiCompCluster = m_compClusterCreator->createBroadCluster(prds,0.); - if( !phiCompCluster ) { - ATH_MSG_DEBUG(" failed to create competing PHI ROT " << prds.size()); - }else{ - double dist = distanceToSegment( segment, phiCompCluster->globalPosition(), gToStation ); - - if( std::abs(dist) > m_maxAssociateClusterDistance ){ - delete phiCompCluster; - ATH_MSG_VERBOSE(" rejected unassociated cluster: " << m_idHelperSvc->toString( prds.front()->identify() ) << " distance to segment " << dist); - continue; - } - rioDistVec.push_back( std::make_pair(dist,phiCompCluster) ); - phiHits.push_back(phiCompCluster); - ++netaPhiHits.first.second; - ++addedPhiHits; - if( msgLvl(MSG::VERBOSE) ){ - ATH_MSG_VERBOSE(" selected unassociated cluster: " << m_idHelperSvc->toString( prds.front()->identify() ) << " distance to segment " << dist); - for( unsigned int i=0;i<phiCompCluster->containedROTs().size();++i){ - ATH_MSG_VERBOSE(" content: " << m_idHelperSvc->toString( phiCompCluster->containedROTs()[i]->identify() )); - } - } - } - } - ATH_MSG_VERBOSE("Added " << addedPhiHits << " unass phi hits out of " << spVecs.second.size() << " phi hits without eta hit and " - << recoveredUnassociatedPhiHits << " with unassociated eta hit "); - } - + if ((!spVecs.second.empty() || m_recoverBadRpcCabling) && m_addUnassociatedPhiHits && !isEndcap) { + + TrkDriftCircleMath::ResidualWithSegment resWithSegment(segment); + + std::map<Identifier, std::list<const Trk::PrepRawData*> > phiClusterMap; + + std::set<const MuonClusterOnTrack*> selectedClusters; + std::vector<Cluster2D*> phiClusters; + phiClusters.reserve(spVecs.second.size()); + + // create lists of PrepRawData per detector element + ClusterIt pit = spVecs.second.begin(); + ClusterIt pit_end = spVecs.second.end(); + for (; pit != pit_end; ++pit) { + if (!pit->phiHit || pit->corrupt()) { + ATH_MSG_WARNING(" phi clusters without phi hit!!"); + continue; + } + phiClusters.push_back(&*pit); + selectedClusters.insert(pit->phiHit); + } + + unsigned int recoveredUnassociatedPhiHits(0); + if (m_recoverBadRpcCabling) { + // now loop over 2D space points and add the phi hits to the list if the detEl is not yet added to the + // segment + ClusterIt spit = spVecs.first.begin(); + ClusterIt spit_end = spVecs.first.end(); + for (; spit != spit_end; ++spit) { + + // skip clusters without phi hit + if (!spit->phiHit || spit->corrupt()) continue; + + // skip clusters in detector elements that are already associated (ok as this is only done for RPC) + if (detElOnSegments.count(spit->detElId)) continue; + + MuonStationIndex::PhiIndex phiIndex = m_idHelperSvc->phiIndex(spit->detElId); + // skip clusters in detector layer + if (phiIndices.count(phiIndex)) continue; + + + bool wasFound = false; + for (std::vector<const MuonClusterOnTrack*>::iterator it = spit->phiHits.begin(); + it != spit->phiHits.end(); ++it) { + + // now to avoid duplicate also skip if the given ROT is already in the list + std::pair<std::set<const MuonClusterOnTrack*>::iterator, bool> insertResult = + selectedClusters.insert(*it); + if (!insertResult.second) { + // flag as found + wasFound = true; + + // just because I'm paranoid, remove the hits from this cluster that were already inserted up to + // here + for (std::vector<const MuonClusterOnTrack*>::iterator rmit = spit->phiHits.begin(); rmit != it; + ++rmit) + selectedClusters.erase(*rmit); + break; + } + } + if (wasFound) continue; + + // if we get here we should add the hit + phiClusters.push_back(&*spit); + ++recoveredUnassociatedPhiHits; + } + } + + unsigned int addedPhiHits(0); + std::vector<Cluster2D*>::iterator cit = phiClusters.begin(); + std::vector<Cluster2D*>::iterator cit_end = phiClusters.end(); + for (; cit != cit_end; ++cit) { + + const Identifier& detElId = (*cit)->detElId; + + // check that detector element is not already added to segment + if (detElOnSegments.count(detElId)) continue; + + MuonStationIndex::PhiIndex phiIndex = m_idHelperSvc->phiIndex(detElId); + // skip clusters in detector layer + if (phiIndices.count(phiIndex)) continue; + + // calculate local cluster position + Amg::Vector3D locPos = gToStation * (*cit)->globalPos; + + // calculate intersect of segment with cluster + TrkDriftCircleMath::Cluster cl(TrkDriftCircleMath::LocPos(locPos.y(), locPos.z()), 1.); + double residual = resWithSegment.residual(cl); + double segError = sqrt(resWithSegment.trackError2(cl)); + const MuonGM::RpcReadoutElement* detEl = + dynamic_cast<const MuonGM::RpcReadoutElement*>((*cit)->phiHit->detectorElement()); + if (!detEl) { + ATH_MSG_WARNING("found RPC prd without RpcReadoutElement"); + continue; + } + + // perform bound check + double stripLength = detEl->StripLength(1); + bool inBounds = std::abs(residual) < 0.5 * stripLength + 2. + segError ? true : false; + if (msgLvl(MSG::DEBUG)) { + ATH_MSG_DEBUG(" Unassociated " << m_idHelperSvc->toString((*cit)->phiHit->identify()) << " pos x " + << cl.position().x() << " pos y " << cl.position().y() << " : residual " + << residual << " strip half length " << 0.5 * stripLength + << " segment error " << segError); + if (inBounds) + ATH_MSG_DEBUG(" inBounds"); + else + ATH_MSG_DEBUG(" outBounds"); + } + if (inBounds) { + // can have multiple phi hits per cluster, loop over phi hits and add them + for (std::vector<const MuonClusterOnTrack*>::iterator pit = (*cit)->phiHits.begin(); + pit != (*cit)->phiHits.end(); ++pit) + { + phiClusterMap[detElId].push_back((*pit)->prepRawData()); + } + } + } + + // loop over detector elements and created competing ROTs + + std::map<Identifier, std::list<const Trk::PrepRawData*> >::iterator chit = phiClusterMap.begin(); + std::map<Identifier, std::list<const Trk::PrepRawData*> >::iterator chit_end = phiClusterMap.end(); + for (; chit != chit_end; ++chit) { + + std::list<const Trk::PrepRawData*>& prds = chit->second; + if (prds.empty()) { + ATH_MSG_WARNING(" chamber without phi hits " << m_idHelperSvc->toString(chit->first)); + continue; + } + + const CompetingMuonClustersOnTrack* phiCompCluster = m_compClusterCreator->createBroadCluster(prds, 0.); + if (!phiCompCluster) { + ATH_MSG_DEBUG(" failed to create competing PHI ROT " << prds.size()); + } else { + double dist = distanceToSegment(segment, phiCompCluster->globalPosition(), gToStation); + + if (std::abs(dist) > m_maxAssociateClusterDistance) { + delete phiCompCluster; + ATH_MSG_VERBOSE(" rejected unassociated cluster: " + << m_idHelperSvc->toString(prds.front()->identify()) << " distance to segment " + << dist); + continue; + } + rioDistVec.push_back(std::make_pair(dist, phiCompCluster)); + phiHits.push_back(phiCompCluster); + ++netaPhiHits.first.second; + ++addedPhiHits; + if (msgLvl(MSG::VERBOSE)) { + ATH_MSG_VERBOSE(" selected unassociated cluster: " + << m_idHelperSvc->toString(prds.front()->identify()) << " distance to segment " + << dist); + for (unsigned int i = 0; i < phiCompCluster->containedROTs().size(); ++i) { + ATH_MSG_VERBOSE(" content: " + << m_idHelperSvc->toString(phiCompCluster->containedROTs()[i]->identify())); + } + } + } + } + ATH_MSG_VERBOSE("Added " << addedPhiHits << " unass phi hits out of " << spVecs.second.size() + << " phi hits without eta hit and " << recoveredUnassociatedPhiHits + << " with unassociated eta hit "); + } + // calculate distance between first and last phi trigger hit, refit if there is a good constraint on phi - double phiDistanceMax = posLastPhiStation - posFirstPhiStation; - if( isEndcap && phiDistanceMax < 1000. ) refit = false; - else if( phiDistanceMax < 400. ) refit = false; + double phiDistanceMax = posLastPhiStation - posFirstPhiStation; + if (isEndcap && phiDistanceMax < 1000.) + refit = false; + else if (phiDistanceMax < 400.) + refit = false; - netaPhiHits.second=refit; + netaPhiHits.second = refit; return netaPhiHits; - } - - double DCMathSegmentMaker::distanceToSegment( const TrkDriftCircleMath::Segment& segment, const Amg::Vector3D& hitPos, Amg::Transform3D gToStation ) const - { +} - const TrkDriftCircleMath::Line& line = segment.line(); +double +DCMathSegmentMaker::distanceToSegment(const TrkDriftCircleMath::Segment& segment, const Amg::Vector3D& hitPos, + Amg::Transform3D gToStation) const +{ + + const TrkDriftCircleMath::Line& line = segment.line(); TrkDriftCircleMath::TransformToLine toLine(line); - double cos_sinLine = cos( line.phi() )/sin( line.phi() ); + double cos_sinLine = cos(line.phi()) / sin(line.phi()); // calculate local AMDB position - Amg::Vector3D locPos = gToStation*hitPos; - - TrkDriftCircleMath::LocPos lpos(locPos.y(),locPos.z()); - + Amg::Vector3D locPos = gToStation * hitPos; + + TrkDriftCircleMath::LocPos lpos(locPos.y(), locPos.z()); + // calculate distance of segment to measurement surface double delta_y = lpos.y() - line.position().y(); - + // calculate position of hit in line frame - TrkDriftCircleMath::LocPos lineSurfaceIntersect( delta_y*cos_sinLine + line.position().x(), lpos.y() ); - + TrkDriftCircleMath::LocPos lineSurfaceIntersect(delta_y * cos_sinLine + line.position().x(), lpos.y()); + // calculate position of hit in line frame - TrkDriftCircleMath::LocPos pointOnHit = toLine.toLine( lineSurfaceIntersect ); - - return pointOnHit.x(); - } - + TrkDriftCircleMath::LocPos pointOnHit = toLine.toLine(lineSurfaceIntersect); + + return pointOnHit.x(); +} + - DataVector<const Trk::MeasurementBase>* DCMathSegmentMaker::createROTVec(std::vector<std::pair<double,const Trk::MeasurementBase*> >& rioDistVec) const { +DataVector<const Trk::MeasurementBase>* +DCMathSegmentMaker::createROTVec(std::vector<std::pair<double, const Trk::MeasurementBase*> >& rioDistVec) const +{ // sort hits according to they distance to the segment position - std::sort( rioDistVec.begin(),rioDistVec.end(),SortByDistanceToSegment() ); - + std::sort(rioDistVec.begin(), rioDistVec.end(), SortByDistanceToSegment()); + DataVector<const Trk::MeasurementBase>* rioVec = new DataVector<const Trk::MeasurementBase>(); rioVec->reserve(rioDistVec.size()); - std::vector<std::pair<double,const Trk::MeasurementBase*> >::iterator rdit = rioDistVec.begin(); - std::vector<std::pair<double,const Trk::MeasurementBase*> >::iterator rdit_end = rioDistVec.end(); - for( ;rdit!=rdit_end;++rdit ){ - rioVec->push_back( rdit->second ); + std::vector<std::pair<double, const Trk::MeasurementBase*> >::iterator rdit = rioDistVec.begin(); + std::vector<std::pair<double, const Trk::MeasurementBase*> >::iterator rdit_end = rioDistVec.end(); + for (; rdit != rdit_end; ++rdit) { + rioVec->push_back(rdit->second); } return rioVec; - } +} - std::pair<double,double> DCMathSegmentMaker::residualAndPullWithSegment( const TrkDriftCircleMath::Segment& segment, const Cluster2D& spacePoint, Amg::Transform3D gToStation ) const - { - const TrkDriftCircleMath::Line& line = segment.line(); - double phi = line.phi(); +std::pair<double, double> +DCMathSegmentMaker::residualAndPullWithSegment(const TrkDriftCircleMath::Segment& segment, const Cluster2D& spacePoint, + Amg::Transform3D gToStation) const +{ + const TrkDriftCircleMath::Line& line = segment.line(); + double phi = line.phi(); - if( std::abs(phi) < 0.0000001 ) { - ATH_MSG_WARNING("Unphysical phi angle " << phi); - phi = 0.0000001; - if( line.phi() < 0. ) phi *= -1.; + if (std::abs(phi) < 0.0000001) { + ATH_MSG_WARNING("Unphysical phi angle " << phi); + phi = 0.0000001; + if (line.phi() < 0.) phi *= -1.; } - double cos_sinLine = cos( phi )/sin( phi ); + double cos_sinLine = cos(phi) / sin(phi); // calculate sp postion in AMDB reference frame - Amg::Vector3D locPos = gToStation*spacePoint.globalPos; - TrkDriftCircleMath::LocPos lpos(locPos.y(),locPos.z()); - + Amg::Vector3D locPos = gToStation * spacePoint.globalPos; + TrkDriftCircleMath::LocPos lpos(locPos.y(), locPos.z()); + // calculate distance of segment to measurement surface double delta_y = lpos.y() - line.position().y(); // calculate position of hit in line frame - TrkDriftCircleMath::LocPos lineSurfaceIntersect( delta_y*cos_sinLine + line.position().x(), lpos.y() ); - + TrkDriftCircleMath::LocPos lineSurfaceIntersect(delta_y * cos_sinLine + line.position().x(), lpos.y()); + // calculate position of hit in line frame - double residual = lpos.x() - lineSurfaceIntersect.x(); - double pull = residual/spacePoint.error; - return std::make_pair(residual,pull); - } + double residual = lpos.x() - lineSurfaceIntersect.x(); + double pull = residual / spacePoint.error; + return std::make_pair(residual, pull); +} +std::vector<Identifier> +DCMathSegmentMaker::calculateHoles(Identifier chid, Amg::Vector3D gpos, Amg::Vector3D gdir, bool hasMeasuredCoordinate, + std::set<Identifier>& deltaVec, std::set<Identifier>& outoftimeVec, + std::vector<std::pair<double, const Trk::MeasurementBase*> >& rioDistVec) const +{ - std::vector<Identifier> DCMathSegmentMaker::calculateHoles( Identifier chid, Amg::Vector3D gpos, Amg::Vector3D gdir, bool hasMeasuredCoordinate, - std::set<Identifier>& deltaVec, std::set<Identifier>& outoftimeVec, - std::vector<std::pair<double,const Trk::MeasurementBase*> >& rioDistVec) const { - // calculate crossed tubes const MdtCondDbData* dbData; - if(!m_condKey.empty()){ - SG::ReadCondHandle<MdtCondDbData> readHandle{m_condKey}; - dbData=readHandle.cptr(); - } - else dbData=nullptr; //for online running + if (!m_condKey.empty()) { + SG::ReadCondHandle<MdtCondDbData> readHandle{m_condKey}; + dbData = readHandle.cptr(); + } else + dbData = nullptr; // for online running SG::ReadCondHandle<MuonGM::MuonDetectorManager> DetectorManagerHandle{m_DetectorManagerKey}; - const MuonGM::MuonDetectorManager* MuonDetMgr{*DetectorManagerHandle}; - if(MuonDetMgr==nullptr){ - ATH_MSG_ERROR("Null pointer to the read MuonDetectorManager conditions object"); - // return 0; - } + const MuonGM::MuonDetectorManager* MuonDetMgr{*DetectorManagerHandle}; + if (MuonDetMgr == nullptr) { + ATH_MSG_ERROR("Null pointer to the read MuonDetectorManager conditions object"); + // return 0; + } - const MuonStationIntersect intersect = m_intersectSvc->tubesCrossedByTrack(chid, gpos, gdir, dbData, MuonDetMgr ); + const MuonStationIntersect intersect = m_intersectSvc->tubesCrossedByTrack(chid, gpos, gdir, dbData, MuonDetMgr); // set to identify the hit on the segment - std::set<Identifier> hitsOnSegment; - std::set<Identifier> chambersOnSegment; - int firstLayer = -1; - int lastLayer = -1; - std::vector<std::pair<double,const Trk::MeasurementBase*> >::iterator rdit = rioDistVec.begin(); - std::vector<std::pair<double,const Trk::MeasurementBase*> >::iterator rdit_end = rioDistVec.end(); - for( ;rdit!=rdit_end;++rdit ){ - const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(rdit->second); - if( mdt ) { - const Identifier& id = mdt->identify(); - int layer = (m_idHelperSvc->mdtIdHelper().tubeLayer(id)-1) + 4*(m_idHelperSvc->mdtIdHelper().multilayer(id)-1); - if( firstLayer == -1 ) firstLayer = layer; - else lastLayer = layer; - - hitsOnSegment.insert( mdt->identify() ); - chambersOnSegment.insert(m_idHelperSvc->chamberId(mdt->identify())); - } + std::set<Identifier> hitsOnSegment; + std::set<Identifier> chambersOnSegment; + int firstLayer = -1; + int lastLayer = -1; + std::vector<std::pair<double, const Trk::MeasurementBase*> >::iterator rdit = rioDistVec.begin(); + std::vector<std::pair<double, const Trk::MeasurementBase*> >::iterator rdit_end = rioDistVec.end(); + for (; rdit != rdit_end; ++rdit) { + const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(rdit->second); + if (mdt) { + const Identifier& id = mdt->identify(); + int layer = (m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1) + + 4 * (m_idHelperSvc->mdtIdHelper().multilayer(id) - 1); + if (firstLayer == -1) + firstLayer = layer; + else + lastLayer = layer; + + hitsOnSegment.insert(mdt->identify()); + chambersOnSegment.insert(m_idHelperSvc->chamberId(mdt->identify())); + } } // cross check for cosmic case - if( firstLayer > lastLayer ){ - int tmpLayer = firstLayer; - firstLayer = lastLayer; - lastLayer = tmpLayer; - } - if( msgLvl(MSG::VERBOSE) ) ATH_MSG_VERBOSE(" Tube layer ranges: " << firstLayer << " -- " - << lastLayer << " crossed tubes " << intersect.tubeIntersects().size()); + if (firstLayer > lastLayer) { + int tmpLayer = firstLayer; + firstLayer = lastLayer; + lastLayer = tmpLayer; + } + if (msgLvl(MSG::VERBOSE)) + ATH_MSG_VERBOSE(" Tube layer ranges: " << firstLayer << " -- " << lastLayer << " crossed tubes " + << intersect.tubeIntersects().size()); // clear hole vector std::vector<Identifier> holeVec; - for( unsigned int ii=0;ii<intersect.tubeIntersects().size();++ii ){ - - const MuonTubeIntersect& tint = intersect.tubeIntersects()[ii]; - if( !chambersOnSegment.count( m_idHelperSvc->chamberId(tint.tubeId) ) ) { - if( msgLvl(MSG::VERBOSE) ) ATH_MSG_VERBOSE(" chamber not on segment, not counting tube " << tint.rIntersect << " l " << tint.xIntersect - << " " << m_idHelperSvc->toString(tint.tubeId)); - continue; - } - - const Identifier& id = tint.tubeId; - int layer = (m_idHelperSvc->mdtIdHelper().tubeLayer(id)-1) + 4*(m_idHelperSvc->mdtIdHelper().multilayer(id)-1); - - bool notBetweenHits = layer < firstLayer || layer > lastLayer; - double distanceCut = hasMeasuredCoordinate ? -20 : -200.; - double innerRadius = MuonDetMgr->getMdtReadoutElement(id)->innerTubeRadius(); - if( notBetweenHits && ( std::abs(tint.rIntersect) > innerRadius || (!m_allMdtHoles && tint.xIntersect > distanceCut) ) ) { - if( msgLvl(MSG::VERBOSE) ) ATH_MSG_VERBOSE(" not counting tube: distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect - << " " << m_idHelperSvc->toString(tint.tubeId)); - }else{ - // check whether there is a hit in this tube - if( hitsOnSegment.count( tint.tubeId ) ) { - if( msgLvl(MSG::VERBOSE) ) ATH_MSG_VERBOSE(" tube on segment: distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect - << " " << m_idHelperSvc->toString(tint.tubeId)); - continue; - } - // check whether there is a delta electron in this tube - if( m_removeDeltas ){ - if( deltaVec.count( tint.tubeId ) ) { - if( msgLvl(MSG::VERBOSE) ) ATH_MSG_VERBOSE(" removing delta, distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect - << " " << m_idHelperSvc->toString(tint.tubeId)); - continue; - } - - const MdtPrepData* prd = findMdt(id); - if( prd && std::abs(prd->localPosition()[Trk::locR]) < std::abs(tint.rIntersect) ){ - if( msgLvl(MSG::VERBOSE) ) ATH_MSG_VERBOSE(" found and removed delta, distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect - << " " << m_idHelperSvc->toString(tint.tubeId)); - continue; - } - } - if( msgLvl(MSG::VERBOSE) ) { - std::string holeType = "hole "; - if( outoftimeVec.count(tint.tubeId) ) holeType = "Out-of-time "; - ATH_MSG_VERBOSE(holeType << " distance to wire " << tint.rIntersect << " dist to tube end " << tint.xIntersect - << " " << m_idHelperSvc->toString(tint.tubeId)); - if( !notBetweenHits ) ATH_MSG_VERBOSE(" between hits"); - } - - holeVec.push_back( tint.tubeId ); - } + for (unsigned int ii = 0; ii < intersect.tubeIntersects().size(); ++ii) { + + const MuonTubeIntersect& tint = intersect.tubeIntersects()[ii]; + if (!chambersOnSegment.count(m_idHelperSvc->chamberId(tint.tubeId))) { + if (msgLvl(MSG::VERBOSE)) + ATH_MSG_VERBOSE(" chamber not on segment, not counting tube " << tint.rIntersect << " l " + << tint.xIntersect << " " + << m_idHelperSvc->toString(tint.tubeId)); + continue; + } + + const Identifier& id = tint.tubeId; + int layer = + (m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1) + 4 * (m_idHelperSvc->mdtIdHelper().multilayer(id) - 1); + + bool notBetweenHits = layer < firstLayer || layer > lastLayer; + double distanceCut = hasMeasuredCoordinate ? -20 : -200.; + double innerRadius = MuonDetMgr->getMdtReadoutElement(id)->innerTubeRadius(); + if (notBetweenHits + && (std::abs(tint.rIntersect) > innerRadius || (!m_allMdtHoles && tint.xIntersect > distanceCut))) { + if (msgLvl(MSG::VERBOSE)) + ATH_MSG_VERBOSE(" not counting tube: distance to wire " << tint.rIntersect << " dist to tube end " + << tint.xIntersect << " " + << m_idHelperSvc->toString(tint.tubeId)); + } else { + // check whether there is a hit in this tube + if (hitsOnSegment.count(tint.tubeId)) { + if (msgLvl(MSG::VERBOSE)) + ATH_MSG_VERBOSE(" tube on segment: distance to wire " << tint.rIntersect << " dist to tube end " + << tint.xIntersect << " " + << m_idHelperSvc->toString(tint.tubeId)); + continue; + } + // check whether there is a delta electron in this tube + if (m_removeDeltas) { + if (deltaVec.count(tint.tubeId)) { + if (msgLvl(MSG::VERBOSE)) + ATH_MSG_VERBOSE(" removing delta, distance to wire " << tint.rIntersect << " dist to tube end " + << tint.xIntersect << " " + << m_idHelperSvc->toString(tint.tubeId)); + continue; + } + + const MdtPrepData* prd = findMdt(id); + if (prd && std::abs(prd->localPosition()[Trk::locR]) < std::abs(tint.rIntersect)) { + if (msgLvl(MSG::VERBOSE)) + ATH_MSG_VERBOSE(" found and removed delta, distance to wire " + << tint.rIntersect << " dist to tube end " << tint.xIntersect << " " + << m_idHelperSvc->toString(tint.tubeId)); + continue; + } + } + if (msgLvl(MSG::VERBOSE)) { + std::string holeType = "hole "; + if (outoftimeVec.count(tint.tubeId)) holeType = "Out-of-time "; + ATH_MSG_VERBOSE(holeType << " distance to wire " << tint.rIntersect << " dist to tube end " + << tint.xIntersect << " " << m_idHelperSvc->toString(tint.tubeId)); + if (!notBetweenHits) ATH_MSG_VERBOSE(" between hits"); + } + + holeVec.push_back(tint.tubeId); + } } return holeVec; - } +} - const MdtPrepData* DCMathSegmentMaker::findMdt( const Identifier& id ) const { +const MdtPrepData* +DCMathSegmentMaker::findMdt(const Identifier& id) const +{ IdentifierHash colHash; - if( m_idHelperSvc->mdtIdHelper().get_module_hash(m_idHelperSvc->chamberId(id),colHash) == 0 ){ - const MdtPrepDataContainer* prdContainer = 0; - SG::ReadHandle<Muon::MdtPrepDataContainer> MdtCont(m_mdtKey); - if(!MdtCont.isValid()){ - ATH_MSG_WARNING("Cannot retrieve MdtPrepDataContainer "); - return 0; - } - else{ - prdContainer = MdtCont.cptr(); - } - if(!prdContainer){ - ATH_MSG_WARNING("No MDT prd collection retrieved"); - return 0; - } - auto collptr = prdContainer->indexFindPtr(colHash); - if( collptr == nullptr ) return 0; - const MdtPrepDataCollection& col = *collptr; - MdtPrepDataCollection::const_iterator mdtIt = col.begin(); - MdtPrepDataCollection::const_iterator mdtIt_end = col.end(); - for( ;mdtIt!=mdtIt_end;++mdtIt ){ - if( (*mdtIt)->identify() == id ) return *mdtIt; - } + if (m_idHelperSvc->mdtIdHelper().get_module_hash(m_idHelperSvc->chamberId(id), colHash) == 0) { + const MdtPrepDataContainer* prdContainer = 0; + SG::ReadHandle<Muon::MdtPrepDataContainer> MdtCont(m_mdtKey); + if (!MdtCont.isValid()) { + ATH_MSG_WARNING("Cannot retrieve MdtPrepDataContainer "); + return 0; + } else { + prdContainer = MdtCont.cptr(); + } + if (!prdContainer) { + ATH_MSG_WARNING("No MDT prd collection retrieved"); + return 0; + } + auto collptr = prdContainer->indexFindPtr(colHash); + if (collptr == nullptr) return 0; + const MdtPrepDataCollection& col = *collptr; + MdtPrepDataCollection::const_iterator mdtIt = col.begin(); + MdtPrepDataCollection::const_iterator mdtIt_end = col.end(); + for (; mdtIt != mdtIt_end; ++mdtIt) { + if ((*mdtIt)->identify() == id) return *mdtIt; + } } return 0; - } +} + +const MdtDriftCircleOnTrack* +DCMathSegmentMaker::findFirstRotInChamberWithMostHits(const std::vector<const MdtDriftCircleOnTrack*>& mdts) const +{ - const MdtDriftCircleOnTrack* DCMathSegmentMaker::findFirstRotInChamberWithMostHits( const std::vector<const MdtDriftCircleOnTrack*>& mdts ) const { - - int hitsInChamberWithMostHits = 0; - std::map<Identifier,int> hitsPerChamber; - int currentSector = -1; + int hitsInChamberWithMostHits = 0; + std::map<Identifier, int> hitsPerChamber; + int currentSector = -1; const MdtDriftCircleOnTrack* rotInChamberWithMostHits = 0; // loop over all MDTs and count number of MDTs per chamber - for( std::vector<const MdtDriftCircleOnTrack*>::const_iterator it=mdts.begin();it!=mdts.end();++it){ - - const MdtDriftCircleOnTrack* rot = *it; - - if( !rot ){ - ATH_MSG_WARNING(" rot not a MdtDriftCircleOnTrack "); - continue; - } - Identifier chId = m_idHelperSvc->chamberId((*it)->identify()); - int sector = m_idHelperSvc->sector(chId); - if( currentSector == -1 ){ - currentSector = sector; - }else if( sector != currentSector ){ - return 0; - } - int& hitsInCh = hitsPerChamber[chId]; - ++hitsInCh; - if( hitsInCh > hitsInChamberWithMostHits ){ - hitsInChamberWithMostHits = hitsInCh; - rotInChamberWithMostHits = rot; - } + for (std::vector<const MdtDriftCircleOnTrack*>::const_iterator it = mdts.begin(); it != mdts.end(); ++it) { + + const MdtDriftCircleOnTrack* rot = *it; + + if (!rot) { + ATH_MSG_WARNING(" rot not a MdtDriftCircleOnTrack "); + continue; + } + Identifier chId = m_idHelperSvc->chamberId((*it)->identify()); + int sector = m_idHelperSvc->sector(chId); + if (currentSector == -1) { + currentSector = sector; + } else if (sector != currentSector) { + return 0; + } + int& hitsInCh = hitsPerChamber[chId]; + ++hitsInCh; + if (hitsInCh > hitsInChamberWithMostHits) { + hitsInChamberWithMostHits = hitsInCh; + rotInChamberWithMostHits = rot; + } } return rotInChamberWithMostHits; - } +} - std::pair<bool,double> DCMathSegmentMaker::rotateLocalAngleXZIntoBounds( double xline, double zline, double dXdZ, std::vector<DCMathSegmentMaker::HitInXZ>& hits ) const { +std::pair<bool, double> +DCMathSegmentMaker::rotateLocalAngleXZIntoBounds(double xline, double zline, double dXdZ, + std::vector<DCMathSegmentMaker::HitInXZ>& hits) const +{ // routine checks whether hits are in bounds, if not rotates the local angle XZ until all hits are in bounds - - std::pair<bool,double> result(false,dXdZ); - if( hits.empty() ) return result; - - - double dXdZMinLeft = 1e9; - double dXdZMinRight = 1e9; - std::vector<HitInXZ>::iterator hit = hits.begin(); - std::vector<HitInXZ>::iterator hit_end = hits.end(); - if(msgLvl(MSG::VERBOSE) ) ATH_MSG_VERBOSE(" recalculating using phi measurement " << m_idHelperSvc->toString(hits.front().id) - << " pos (" << xline << "," << zline << ")"); - for( ;hit!=hit_end;++hit ){ - - // sl extrapolation - double locExX = xline + dXdZ*(hit->z-zline); - - - bool newBoundLeft = false; - bool newBoundRight = false; - - // sanity checks to avoid division + only for MDT for now - if( hit->isMdt ){ - - // now calculate, if out of bounds, for which angle the situation would be ok - double dz = (hit->z-zline); - if( std::abs(dz) > 0.01 ) { - if( locExX < hit->xmin ){ - double inBoundsdXdZ = (hit->xmin-xline)/dz; - if( std::abs(inBoundsdXdZ) < std::abs(dXdZMinLeft) ) dXdZMinLeft = inBoundsdXdZ; - newBoundLeft = true; - } - if( locExX > hit->xmax ) { - double inBoundsdXdZ = (hit->xmax-xline)/dz; - if( std::abs(inBoundsdXdZ) < std::abs(dXdZMinRight) ) dXdZMinRight = inBoundsdXdZ; - newBoundRight = true; - } - } - } - if(msgLvl(MSG::VERBOSE) ){ - ATH_MSG_VERBOSE(" " << std::setw(65) << m_idHelperSvc->toString( hit->id ) - << " pos (" << std::setw(6) << (int)hit->x << "," << std::setw(6) << (int)hit->z - << ") ex pos " << std::setw(6) << (int)locExX - << " min " << std::setw(6) << (int)hit->xmin << " max " << std::setw(6) << (int)hit->xmax - << " phimin " << std::setw(6) << hit->phimin << " phimax " << std::setw(6) << hit->phimax); - if( locExX < hit->xmin || locExX > hit->xmax ) ATH_MSG_VERBOSE(" outBounds "); - if( newBoundRight ) ATH_MSG_VERBOSE(" right " << dXdZMinRight); - if( newBoundLeft ) ATH_MSG_VERBOSE(" left " << dXdZMinLeft); - } - } - - if(msgLvl(MSG::VERBOSE) ) { - if( std::abs(dXdZMinRight) < 1e8 ) ATH_MSG_VERBOSE(" selected right bound " << dXdZMinRight); - if( std::abs(dXdZMinLeft) < 1e8 ) ATH_MSG_VERBOSE(" selected left bound " << dXdZMinLeft); - } - - if( std::abs(dXdZMinRight) < 1e8 ) { - result.first = true; - result.second = dXdZMinRight; - }else if( std::abs(dXdZMinLeft) < 1e8 ){ - result.first = true; - result.second = dXdZMinLeft; + + std::pair<bool, double> result(false, dXdZ); + if (hits.empty()) return result; + + + double dXdZMinLeft = 1e9; + double dXdZMinRight = 1e9; + std::vector<HitInXZ>::iterator hit = hits.begin(); + std::vector<HitInXZ>::iterator hit_end = hits.end(); + if (msgLvl(MSG::VERBOSE)) + ATH_MSG_VERBOSE(" recalculating using phi measurement " << m_idHelperSvc->toString(hits.front().id) << " pos (" + << xline << "," << zline << ")"); + for (; hit != hit_end; ++hit) { + + // sl extrapolation + double locExX = xline + dXdZ * (hit->z - zline); + + + bool newBoundLeft = false; + bool newBoundRight = false; + + // sanity checks to avoid division + only for MDT for now + if (hit->isMdt) { + + // now calculate, if out of bounds, for which angle the situation would be ok + double dz = (hit->z - zline); + if (std::abs(dz) > 0.01) { + if (locExX < hit->xmin) { + double inBoundsdXdZ = (hit->xmin - xline) / dz; + if (std::abs(inBoundsdXdZ) < std::abs(dXdZMinLeft)) dXdZMinLeft = inBoundsdXdZ; + newBoundLeft = true; + } + if (locExX > hit->xmax) { + double inBoundsdXdZ = (hit->xmax - xline) / dz; + if (std::abs(inBoundsdXdZ) < std::abs(dXdZMinRight)) dXdZMinRight = inBoundsdXdZ; + newBoundRight = true; + } + } + } + if (msgLvl(MSG::VERBOSE)) { + ATH_MSG_VERBOSE(" " << std::setw(65) << m_idHelperSvc->toString(hit->id) << " pos (" << std::setw(6) + << (int)hit->x << "," << std::setw(6) << (int)hit->z << ") ex pos " << std::setw(6) + << (int)locExX << " min " << std::setw(6) << (int)hit->xmin << " max " << std::setw(6) + << (int)hit->xmax << " phimin " << std::setw(6) << hit->phimin << " phimax " + << std::setw(6) << hit->phimax); + if (locExX < hit->xmin || locExX > hit->xmax) ATH_MSG_VERBOSE(" outBounds "); + if (newBoundRight) ATH_MSG_VERBOSE(" right " << dXdZMinRight); + if (newBoundLeft) ATH_MSG_VERBOSE(" left " << dXdZMinLeft); + } + } + + if (msgLvl(MSG::VERBOSE)) { + if (std::abs(dXdZMinRight) < 1e8) ATH_MSG_VERBOSE(" selected right bound " << dXdZMinRight); + if (std::abs(dXdZMinLeft) < 1e8) ATH_MSG_VERBOSE(" selected left bound " << dXdZMinLeft); + } + + if (std::abs(dXdZMinRight) < 1e8) { + result.first = true; + result.second = dXdZMinRight; + } else if (std::abs(dXdZMinLeft) < 1e8) { + result.first = true; + result.second = dXdZMinLeft; } return result; - } +} - bool DCMathSegmentMaker::checkBoundsInXZ( double xline, double zline, double dXdZ, std::vector<DCMathSegmentMaker::HitInXZ>& hits ) const { +bool +DCMathSegmentMaker::checkBoundsInXZ(double xline, double zline, double dXdZ, + std::vector<DCMathSegmentMaker::HitInXZ>& hits) const +{ bool ok = true; // look over hits and check whether all are in bounds - std::vector<HitInXZ>::iterator hit = hits.begin(); + std::vector<HitInXZ>::iterator hit = hits.begin(); std::vector<HitInXZ>::iterator hit_end = hits.end(); - for( ;hit!=hit_end;++hit ){ - - bool outBounds = false; - double locExX = xline + dXdZ*(hit->z-zline); - if( hit->isMdt && (locExX < hit->xmin - 1. || locExX > hit->xmax + 1.) ){ - ok = false; - outBounds = true; - if( !msgLvl(MSG::DEBUG) ) break; - } - - if( outBounds &&msgLvl(MSG::DEBUG) ){ - ATH_MSG_DEBUG(" " << std::setw(65) << m_idHelperSvc->toString( hit->id ) - << " pos (" << std::setw(6) << (int)hit->x << "," << std::setw(6) << (int)hit->z - << ") ex pos " << std::setw(6) << (int)locExX - << " min " << std::setw(6) << (int)hit->xmin << " max " << std::setw(6) << (int)hit->xmax - << " phimin " << std::setw(6) << hit->phimin << " phimax " << std::setw(6) << hit->phimax - << " outBounds, cross-check"); - } + for (; hit != hit_end; ++hit) { + + bool outBounds = false; + double locExX = xline + dXdZ * (hit->z - zline); + if (hit->isMdt && (locExX < hit->xmin - 1. || locExX > hit->xmax + 1.)) { + ok = false; + outBounds = true; + if (!msgLvl(MSG::DEBUG)) break; + } + + if (outBounds && msgLvl(MSG::DEBUG)) { + ATH_MSG_DEBUG(" " << std::setw(65) << m_idHelperSvc->toString(hit->id) << " pos (" << std::setw(6) + << (int)hit->x << "," << std::setw(6) << (int)hit->z << ") ex pos " << std::setw(6) + << (int)locExX << " min " << std::setw(6) << (int)hit->xmin << " max " << std::setw(6) + << (int)hit->xmax << " phimin " << std::setw(6) << hit->phimin << " phimax " + << std::setw(6) << hit->phimax << " outBounds, cross-check"); + } } return ok; - } +} - bool DCMathSegmentMaker::updateSegmentPhi( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, - Amg::Vector2D& segLocPos, Trk::LocalDirection& segLocDir, - Trk::PlaneSurface& surf, const std::vector<const Trk::MeasurementBase*>& rots, - double seg_phimin, double seg_phimax) const { +bool +DCMathSegmentMaker::updateSegmentPhi(const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, Amg::Vector2D& segLocPos, + Trk::LocalDirection& segLocDir, Trk::PlaneSurface& surf, + const std::vector<const Trk::MeasurementBase*>& rots, double seg_phimin, + double seg_phimax) const +{ bool hasUpdated = false; const Amg::Transform3D& segmentToGlobal = surf.transform(); - Amg::Transform3D gToSegment = surf.transform().inverse(); - Amg::Vector3D ldir = gToSegment*gdir; - - // ensure that we can extrapolate - if( ldir.z() < 0.0001 ) return false; - - double dXdZ = ldir.x()/ldir.z(); - double dYdZ = ldir.y()/ldir.z(); - Amg::Vector3D lsegPos = gToSegment*gpos; - double xline = lsegPos.x(); - double yline = lsegPos.y(); - double zline = lsegPos.z(); - if(msgLvl(MSG::VERBOSE) ) ATH_MSG_VERBOSE(" Associated hits " << rots.size() - << " angleXZ " << 90.*segLocDir.angleXZ()/acos(0.) - << " dXdZ " << dXdZ << " seg Pos (" << xline << " " << zline << ") " - << segLocPos); + Amg::Transform3D gToSegment = surf.transform().inverse(); + Amg::Vector3D ldir = gToSegment * gdir; + + // ensure that we can extrapolate + if (ldir.z() < 0.0001) return false; + + double dXdZ = ldir.x() / ldir.z(); + double dYdZ = ldir.y() / ldir.z(); + Amg::Vector3D lsegPos = gToSegment * gpos; + double xline = lsegPos.x(); + double yline = lsegPos.y(); + double zline = lsegPos.z(); + if (msgLvl(MSG::VERBOSE)) + ATH_MSG_VERBOSE(" Associated hits " << rots.size() << " angleXZ " << 90. * segLocDir.angleXZ() / acos(0.) + << " dXdZ " << dXdZ << " seg Pos (" << xline << " " << zline << ") " + << segLocPos); std::vector<HitInXZ> hits; hits.reserve(rots.size()); unsigned int nphiHits(0); - HitInXZ* firstPhiHit = 0; - HitInXZ* lastPhiHit = 0; - - for( std::vector<const Trk::MeasurementBase*>::const_iterator it = rots.begin();it!=rots.end();++it ){ - - Identifier id = m_edmHelperSvc->getIdentifier(**it); - if( !id.is_valid() ) continue; - Amg::Vector3D lpos; - double lxmin(0),lxmax(0),phimin(0.),phimax(0.); - bool isMdt = m_idHelperSvc->isMdt(id); - bool measuresPhi = m_idHelperSvc->measuresPhi(id); - if( isMdt ){ - - const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(*it); - if (!mdt) continue; - TubeEnds tubeEnds = localTubeEnds(*mdt,gToSegment,segmentToGlobal); - - lxmin = tubeEnds.lxmin; - lxmax = tubeEnds.lxmax; - phimin = tubeEnds.phimin; - phimax = tubeEnds.phimax; - }else{ - - lpos = gToSegment*(*it)->globalPosition(); - lxmin = lpos.x() - 5*Amg::error((*it)->localCovariance(),Trk::locX); - lxmax = lpos.x() + 5*Amg::error((*it)->localCovariance(),Trk::locX); - - const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*it); - if( !measuresPhi ){ - if( crot ){ - const MuonGM::RpcReadoutElement* detEl = dynamic_cast<const MuonGM::RpcReadoutElement*>(crot->containedROTs().front()->prepRawData()->detectorElement()); - if( detEl ){ - // perform bound check - double stripLength = detEl->StripLength(0); - - lxmin = lpos.x() - 0.5*stripLength; - lxmax = lpos.x() + 0.5*stripLength; - } - } - Amg::Vector3D locPosition = lpos; - locPosition[0] = lxmin; - Amg::Vector3D globalPos = segmentToGlobal*locPosition; - double phi1 = globalPos.phi(); - - locPosition[0] = lxmax; - globalPos = segmentToGlobal*locPosition; - double phi2 = globalPos.phi(); - phimin = phi1 < phi2 ? phi1 : phi2; - phimax = phi1 < phi2 ? phi2 : phi1; - - }else{ - if( m_idHelperSvc->isTgc(id) ){ - - // need some special tricks for TGC phi hits as their reference plane can be rotated - // with respect to the MDT frame - - // get orientation angle of strip to rotate back from local frame to strip - // copy code from ROT creator - int stripNo = m_idHelperSvc->tgcIdHelper().channel(id); - int gasGap = m_idHelperSvc->tgcIdHelper().gasGap(id); - if (!crot) { - ATH_MSG_WARNING("dynamic cast failed for CompetingMuonClustersOnTrack"); - continue; - } - const MuonGM::TgcReadoutElement* detEl = dynamic_cast<const MuonGM::TgcReadoutElement*>(crot->containedROTs().front()->prepRawData()->detectorElement()); - if (!detEl) { - ATH_MSG_WARNING("dynamic cast failed for TgcReadoutElement"); - continue; - } - // calculate two points along the tgc phi strip in the local tgc reference frame - Amg::Vector3D lposTGC = detEl->localChannelPos(id); - double z_shift = lposTGC.z()+10; - double locy_shift = detEl->stripCtrX(gasGap, stripNo, z_shift ); - if (0 < detEl->getStationEta()) { - locy_shift *= -1.; - } - Amg::Vector3D lpos_shift(lposTGC.x(),locy_shift,z_shift); - - // transform the two points to global coordinates - const Amg::Transform3D tgcTrans = detEl->absTransform(); - Amg::Vector3D gposL = tgcTrans*lposTGC; - Amg::Vector3D gposL_shift = tgcTrans*lpos_shift; - - // now transform them into the segment frame - Amg::Vector3D lposSeg = gToSegment*gposL; - Amg::Vector3D lposSeg_shift = gToSegment*gposL_shift; - - // calculate the y coordinate of the intersect of the segment with the TGC plane in the segment frame - double segYAtHit = yline + dYdZ*(lposSeg.z()-zline); - - // the TGC phi strip is a line in the xy plane, calculate the x position of the point on the line - // at the y intersect position of the segment - double tgcdX = lposSeg_shift.x() - lposSeg.x(); - double tgcdY = lposSeg_shift.y() - lposSeg.y(); - if( std::abs(tgcdY) < 0.0001 ) { - ATH_MSG_WARNING(" Bad TGC phi strip orientation "); - continue; - } - double tgcExX = tgcdX/tgcdY*(segYAtHit-lposSeg.y()) + lposSeg.x(); - lpos[0] = tgcExX; - lpos[1] = segYAtHit; - if(msgLvl(MSG::VERBOSE) ) ATH_MSG_VERBOSE(" In seg frame: phi pos " << lposSeg << " shifted pos " << lposSeg_shift - << " intersect with segment " << lpos); - - - } - Amg::Vector3D globalPos = segmentToGlobal*lpos; - phimin = globalPos.phi(); - phimax = phimin; - - // check whether phi is consistent with segment phi range - bool phiOk = checkPhiConsistency(phimin,seg_phimin,seg_phimax); - if( !phiOk ){ - if(msgLvl(MSG::DEBUG) ) ATH_MSG_DEBUG(" Inconsistent phi " << phimin << " range " << seg_phimin << " " << seg_phimax); - } - } - } - - hits.push_back( HitInXZ(id,isMdt,measuresPhi,lpos.x(),lpos.z(),lxmin,lxmax,phimin,phimax) ); - if( measuresPhi ){ - ++nphiHits; - if( !firstPhiHit ) firstPhiHit = new HitInXZ(hits.back()); - else{ - double distPhiHits = std::abs(firstPhiHit->z - hits.back().z); - if( distPhiHits > 500. ){ - if( lastPhiHit ) delete lastPhiHit; - lastPhiHit = new HitInXZ(hits.back()); - }else{ - // not count this phi hit - --nphiHits; - if(msgLvl(MSG::DEBUG) ){ - ATH_MSG_DEBUG(" close phi hits, distance " << distPhiHits); - } - } - } - } - if(msgLvl(MSG::VERBOSE) ){ - double locExX = xline + dXdZ*(lpos.z()-zline); - ATH_MSG_VERBOSE(" " << std::setw(65) << m_idHelperSvc->toString( id ) - << " pos (" << std::setw(6) << (int)lpos.x() << "," << std::setw(6) << (int)lpos.z() - << ") ex pos " << std::setw(6) << (int)locExX - << " min " << std::setw(6) << (int)lxmin << " max " << std::setw(6) << (int)lxmax - << " phimin " << std::setw(6) << phimin << " phimax " << std::setw(6) << phimax); - if( lpos.x() < lxmin || lpos.x() > lxmax ) ATH_MSG_VERBOSE(" outBounds"); - } - } - - - if( nphiHits == 1 ){ - - if( !firstPhiHit ){ - ATH_MSG_WARNING(" Pointer to first phi hit not set, this should not happen! "); - }else{ - if( xline != firstPhiHit->x ) { - hasUpdated = true; - - // use phi position of the phi hit - xline = firstPhiHit->x; - zline = firstPhiHit->z; - - if( m_assumePointingPhi ){ - Amg::Vector3D ipLocPos = gToSegment*Amg::Vector3D(0.,0.,0.); - if(msgLvl(MSG::VERBOSE) ) ATH_MSG_VERBOSE(" IP position in local frame " << ipLocPos); - - double dz = ipLocPos.z()-zline; - if( std::abs(dz) > 0.001 ){ - if(msgLvl(MSG::VERBOSE) ) ATH_MSG_VERBOSE(" hit (" << xline << "," << zline << ") IP (" << ipLocPos.x() << "," << ipLocPos.z() - << ") dXdZ " << (ipLocPos.x()-xline)/dz << " old " << dXdZ); - dXdZ = (ipLocPos.x()-xline)/dz; - } - } - } - } - }else if( nphiHits == 2 ){ - - if( !firstPhiHit || !lastPhiHit ){ - ATH_MSG_WARNING(" Pointer to one of the two phi hit not set, this should not happen! "); - }else{ - double dz = lastPhiHit->z - firstPhiHit->z; - // use phi position of the first hit - xline = firstPhiHit->x; - zline = firstPhiHit->z; - if( std::abs(dz) > 300. ){ - double dx = lastPhiHit->x - firstPhiHit->x; - hasUpdated = true; - - // if the two hits are far enough apart, also use the direction of the line connecting the two hits. - dXdZ = dx/dz; - } - } - }else{ - // in all other cases just rotate until the MDTs are ok - - } - - if( hasUpdated ){ - // move segment to position of phi hit - double segX = xline - dXdZ*zline; - - // finally check whether now everything is in bounds - bool ok = checkBoundsInXZ(segX,0.,dXdZ,hits); - if( !ok ){ - // give WARNING and give up for now - ATH_MSG_DEBUG("still several out of bounds hits after rotation: posx(" << segX << ") dXdZ " << dXdZ << " keeping old result "); - } - - // update segment parameters - double alphaYZ = segLocDir.angleYZ(); - double alphaXZ = atan2(1,dXdZ); - - segLocPos[Trk::locX] = segX; - segLocDir = Trk::LocalDirection(alphaXZ,alphaYZ); + HitInXZ* firstPhiHit = 0; + HitInXZ* lastPhiHit = 0; + + for (std::vector<const Trk::MeasurementBase*>::const_iterator it = rots.begin(); it != rots.end(); ++it) { + + Identifier id = m_edmHelperSvc->getIdentifier(**it); + if (!id.is_valid()) continue; + Amg::Vector3D lpos; + double lxmin(0), lxmax(0), phimin(0.), phimax(0.); + bool isMdt = m_idHelperSvc->isMdt(id); + bool measuresPhi = m_idHelperSvc->measuresPhi(id); + if (isMdt) { + + const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(*it); + if (!mdt) continue; + TubeEnds tubeEnds = localTubeEnds(*mdt, gToSegment, segmentToGlobal); + + lxmin = tubeEnds.lxmin; + lxmax = tubeEnds.lxmax; + phimin = tubeEnds.phimin; + phimax = tubeEnds.phimax; + } else { + + lpos = gToSegment * (*it)->globalPosition(); + lxmin = lpos.x() - 5 * Amg::error((*it)->localCovariance(), Trk::locX); + lxmax = lpos.x() + 5 * Amg::error((*it)->localCovariance(), Trk::locX); + + const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*it); + if (!measuresPhi) { + if (crot) { + const MuonGM::RpcReadoutElement* detEl = dynamic_cast<const MuonGM::RpcReadoutElement*>( + crot->containedROTs().front()->prepRawData()->detectorElement()); + if (detEl) { + // perform bound check + double stripLength = detEl->StripLength(0); + + lxmin = lpos.x() - 0.5 * stripLength; + lxmax = lpos.x() + 0.5 * stripLength; + } + } + Amg::Vector3D locPosition = lpos; + locPosition[0] = lxmin; + Amg::Vector3D globalPos = segmentToGlobal * locPosition; + double phi1 = globalPos.phi(); + + locPosition[0] = lxmax; + globalPos = segmentToGlobal * locPosition; + double phi2 = globalPos.phi(); + phimin = phi1 < phi2 ? phi1 : phi2; + phimax = phi1 < phi2 ? phi2 : phi1; + + } else { + if (m_idHelperSvc->isTgc(id)) { + + // need some special tricks for TGC phi hits as their reference plane can be rotated + // with respect to the MDT frame + + // get orientation angle of strip to rotate back from local frame to strip + // copy code from ROT creator + int stripNo = m_idHelperSvc->tgcIdHelper().channel(id); + int gasGap = m_idHelperSvc->tgcIdHelper().gasGap(id); + if (!crot) { + ATH_MSG_WARNING("dynamic cast failed for CompetingMuonClustersOnTrack"); + continue; + } + const MuonGM::TgcReadoutElement* detEl = dynamic_cast<const MuonGM::TgcReadoutElement*>( + crot->containedROTs().front()->prepRawData()->detectorElement()); + if (!detEl) { + ATH_MSG_WARNING("dynamic cast failed for TgcReadoutElement"); + continue; + } + // calculate two points along the tgc phi strip in the local tgc reference frame + Amg::Vector3D lposTGC = detEl->localChannelPos(id); + double z_shift = lposTGC.z() + 10; + double locy_shift = detEl->stripCtrX(gasGap, stripNo, z_shift); + if (0 < detEl->getStationEta()) { + locy_shift *= -1.; + } + Amg::Vector3D lpos_shift(lposTGC.x(), locy_shift, z_shift); + + // transform the two points to global coordinates + const Amg::Transform3D tgcTrans = detEl->absTransform(); + Amg::Vector3D gposL = tgcTrans * lposTGC; + Amg::Vector3D gposL_shift = tgcTrans * lpos_shift; + + // now transform them into the segment frame + Amg::Vector3D lposSeg = gToSegment * gposL; + Amg::Vector3D lposSeg_shift = gToSegment * gposL_shift; + + // calculate the y coordinate of the intersect of the segment with the TGC plane in the segment + // frame + double segYAtHit = yline + dYdZ * (lposSeg.z() - zline); + + // the TGC phi strip is a line in the xy plane, calculate the x position of the point on the line + // at the y intersect position of the segment + double tgcdX = lposSeg_shift.x() - lposSeg.x(); + double tgcdY = lposSeg_shift.y() - lposSeg.y(); + if (std::abs(tgcdY) < 0.0001) { + ATH_MSG_WARNING(" Bad TGC phi strip orientation "); + continue; + } + double tgcExX = tgcdX / tgcdY * (segYAtHit - lposSeg.y()) + lposSeg.x(); + lpos[0] = tgcExX; + lpos[1] = segYAtHit; + if (msgLvl(MSG::VERBOSE)) + ATH_MSG_VERBOSE(" In seg frame: phi pos " << lposSeg << " shifted pos " << lposSeg_shift + << " intersect with segment " << lpos); + } + Amg::Vector3D globalPos = segmentToGlobal * lpos; + phimin = globalPos.phi(); + phimax = phimin; + + // check whether phi is consistent with segment phi range + bool phiOk = checkPhiConsistency(phimin, seg_phimin, seg_phimax); + if (!phiOk) { + if (msgLvl(MSG::DEBUG)) + ATH_MSG_DEBUG(" Inconsistent phi " << phimin << " range " << seg_phimin << " " << seg_phimax); + } + } + } + + hits.push_back(HitInXZ(id, isMdt, measuresPhi, lpos.x(), lpos.z(), lxmin, lxmax, phimin, phimax)); + if (measuresPhi) { + ++nphiHits; + if (!firstPhiHit) + firstPhiHit = new HitInXZ(hits.back()); + else { + double distPhiHits = std::abs(firstPhiHit->z - hits.back().z); + if (distPhiHits > 500.) { + if (lastPhiHit) delete lastPhiHit; + lastPhiHit = new HitInXZ(hits.back()); + } else { + // not count this phi hit + --nphiHits; + if (msgLvl(MSG::DEBUG)) { + ATH_MSG_DEBUG(" close phi hits, distance " << distPhiHits); + } + } + } + } + if (msgLvl(MSG::VERBOSE)) { + double locExX = xline + dXdZ * (lpos.z() - zline); + ATH_MSG_VERBOSE(" " << std::setw(65) << m_idHelperSvc->toString(id) << " pos (" << std::setw(6) + << (int)lpos.x() << "," << std::setw(6) << (int)lpos.z() << ") ex pos " + << std::setw(6) << (int)locExX << " min " << std::setw(6) << (int)lxmin << " max " + << std::setw(6) << (int)lxmax << " phimin " << std::setw(6) << phimin << " phimax " + << std::setw(6) << phimax); + if (lpos.x() < lxmin || lpos.x() > lxmax) ATH_MSG_VERBOSE(" outBounds"); + } + } + + + if (nphiHits == 1) { + + if (!firstPhiHit) { + ATH_MSG_WARNING(" Pointer to first phi hit not set, this should not happen! "); + } else { + if (xline != firstPhiHit->x) { + hasUpdated = true; + + // use phi position of the phi hit + xline = firstPhiHit->x; + zline = firstPhiHit->z; + + if (m_assumePointingPhi) { + Amg::Vector3D ipLocPos = gToSegment * Amg::Vector3D(0., 0., 0.); + if (msgLvl(MSG::VERBOSE)) ATH_MSG_VERBOSE(" IP position in local frame " << ipLocPos); + + double dz = ipLocPos.z() - zline; + if (std::abs(dz) > 0.001) { + if (msgLvl(MSG::VERBOSE)) + ATH_MSG_VERBOSE(" hit (" << xline << "," << zline << ") IP (" << ipLocPos.x() << "," + << ipLocPos.z() << ") dXdZ " << (ipLocPos.x() - xline) / dz + << " old " << dXdZ); + dXdZ = (ipLocPos.x() - xline) / dz; + } + } + } + } + } else if (nphiHits == 2) { + + if (!firstPhiHit || !lastPhiHit) { + ATH_MSG_WARNING(" Pointer to one of the two phi hit not set, this should not happen! "); + } else { + double dz = lastPhiHit->z - firstPhiHit->z; + // use phi position of the first hit + xline = firstPhiHit->x; + zline = firstPhiHit->z; + if (std::abs(dz) > 300.) { + double dx = lastPhiHit->x - firstPhiHit->x; + hasUpdated = true; + + // if the two hits are far enough apart, also use the direction of the line connecting the two hits. + dXdZ = dx / dz; + } + } + } else { + // in all other cases just rotate until the MDTs are ok + } + + if (hasUpdated) { + // move segment to position of phi hit + double segX = xline - dXdZ * zline; + + // finally check whether now everything is in bounds + bool ok = checkBoundsInXZ(segX, 0., dXdZ, hits); + if (!ok) { + // give WARNING and give up for now + ATH_MSG_DEBUG("still several out of bounds hits after rotation: posx(" << segX << ") dXdZ " << dXdZ + << " keeping old result "); + } + + // update segment parameters + double alphaYZ = segLocDir.angleYZ(); + double alphaXZ = atan2(1, dXdZ); + + segLocPos[Trk::locX] = segX; + segLocDir = Trk::LocalDirection(alphaXZ, alphaYZ); } delete firstPhiHit; delete lastPhiHit; return hasUpdated; - } - +} - DCMathSegmentMaker::TubeEnds DCMathSegmentMaker::localTubeEnds( const MdtDriftCircleOnTrack& mdt, - const Amg::Transform3D& gToSegment, - const Amg::Transform3D& segmentToG ) const { +DCMathSegmentMaker::TubeEnds +DCMathSegmentMaker::localTubeEnds(const MdtDriftCircleOnTrack& mdt, const Amg::Transform3D& gToSegment, + const Amg::Transform3D& segmentToG) const +{ - TubeEnds tubeEnds; - const Identifier& id = mdt.identify(); - Amg::Vector3D lpos = gToSegment*mdt.prepRawData()->globalPosition(); + TubeEnds tubeEnds; + const Identifier& id = mdt.identify(); + Amg::Vector3D lpos = gToSegment * mdt.prepRawData()->globalPosition(); // use readout and hv side as the surface frame is not that of the chamber - Amg::Vector3D lropos = gToSegment*mdt.prepRawData()->detectorElement()->ROPos(id); - Amg::Vector3D lhvpos = lpos + (lpos-lropos); + Amg::Vector3D lropos = gToSegment * mdt.prepRawData()->detectorElement()->ROPos(id); + Amg::Vector3D lhvpos = lpos + (lpos - lropos); // rescale to correctly take into account active tube length - double tubeLen = (lropos-lhvpos).mag(); - double activeTubeLen = mdt.detectorElement()->getActiveTubeLength(m_idHelperSvc->mdtIdHelper().tubeLayer(id),m_idHelperSvc->mdtIdHelper().tube(id)); - double scaleFactor = activeTubeLen/tubeLen; - lropos[0] = scaleFactor*lropos.x(); - lhvpos[0] = scaleFactor*lhvpos.x(); - - if( lropos.x() < lhvpos.x() ){ - tubeEnds.lxmin = lropos.x(); - tubeEnds.lxmax = lhvpos.x(); - }else{ - tubeEnds.lxmin = lhvpos.x(); - tubeEnds.lxmax = lropos.x(); - } - - Amg::Vector3D ropos = segmentToG*lropos; - Amg::Vector3D hvpos = segmentToG*lhvpos; - double phiRO = ropos.phi(); - double phiHV = hvpos.phi(); - tubeEnds.phimin = phiRO < phiHV ? phiRO : phiHV; - tubeEnds.phimax = phiRO < phiHV ? phiHV : phiRO; + double tubeLen = (lropos - lhvpos).mag(); + double activeTubeLen = mdt.detectorElement()->getActiveTubeLength(m_idHelperSvc->mdtIdHelper().tubeLayer(id), + m_idHelperSvc->mdtIdHelper().tube(id)); + double scaleFactor = activeTubeLen / tubeLen; + lropos[0] = scaleFactor * lropos.x(); + lhvpos[0] = scaleFactor * lhvpos.x(); + + if (lropos.x() < lhvpos.x()) { + tubeEnds.lxmin = lropos.x(); + tubeEnds.lxmax = lhvpos.x(); + } else { + tubeEnds.lxmin = lhvpos.x(); + tubeEnds.lxmax = lropos.x(); + } + + Amg::Vector3D ropos = segmentToG * lropos; + Amg::Vector3D hvpos = segmentToG * lhvpos; + double phiRO = ropos.phi(); + double phiHV = hvpos.phi(); + tubeEnds.phimin = phiRO < phiHV ? phiRO : phiHV; + tubeEnds.phimax = phiRO < phiHV ? phiHV : phiRO; return tubeEnds; - } +} + +void +DCMathSegmentMaker::updatePhiRanges(double phiminNew, double phimaxNew, double& phiminRef, double& phimaxRef) const +{ - void DCMathSegmentMaker::updatePhiRanges( double phiminNew, double phimaxNew, double& phiminRef, double& phimaxRef ) const { - // check whether we are at the boundary where phi changes sign - if( phiminRef*phimaxRef < 0. ){ - if( phiminRef < -1.1 ){ - if( phiminRef > phiminNew ) phiminRef = phiminNew; - if( phimaxRef < phimaxNew ) phimaxRef = phimaxNew; - }else{ - if( phiminRef < phiminNew ) phiminRef = phiminNew; - if( phimaxRef > phimaxNew ) phimaxRef = phimaxNew; - } - }else{ - // if not life is 'easy' - if( phiminRef < 0. ){ - if( phiminRef < phiminNew ) phiminRef = phiminNew; - if( phimaxRef > phimaxNew ) phimaxRef = phimaxNew; - }else{ - if( phiminRef > phiminNew ) phiminRef = phiminNew; - if( phimaxRef < phimaxNew ) phimaxRef = phimaxNew; - } - } - } - - bool DCMathSegmentMaker::checkPhiConsistency( double phi, double phimin, double phimax ) const { + if (phiminRef * phimaxRef < 0.) { + if (phiminRef < -1.1) { + if (phiminRef > phiminNew) phiminRef = phiminNew; + if (phimaxRef < phimaxNew) phimaxRef = phimaxNew; + } else { + if (phiminRef < phiminNew) phiminRef = phiminNew; + if (phimaxRef > phimaxNew) phimaxRef = phimaxNew; + } + } else { + // if not life is 'easy' + if (phiminRef < 0.) { + if (phiminRef < phiminNew) phiminRef = phiminNew; + if (phimaxRef > phimaxNew) phimaxRef = phimaxNew; + } else { + if (phiminRef > phiminNew) phiminRef = phiminNew; + if (phimaxRef < phimaxNew) phimaxRef = phimaxNew; + } + } +} + +bool +DCMathSegmentMaker::checkPhiConsistency(double phi, double phimin, double phimax) const +{ // only if assuming pointing phi - if( !m_assumePointingPhi ) return true; + if (!m_assumePointingPhi) return true; - bool phiOk = true; + bool phiOk = true; double offset = 0.05; - if( phimin*phimax < 0. ){ - if( phi < 0. ){ - if( phi > -1.1 ){ - if( phi < phimin - offset ) phiOk = false; - }else{ - if( phi > phimin + offset ) phiOk = false; - } - }else{ - if( phi > 1.1 ){ - if( phi < phimax - offset ) phiOk = false; - }else{ - if( phi > phimax + offset ) phiOk = false; - } - } - }else{ - if( phi < phimin - offset || phi > phimax + offset ) phiOk = false; + if (phimin * phimax < 0.) { + if (phi < 0.) { + if (phi > -1.1) { + if (phi < phimin - offset) phiOk = false; + } else { + if (phi > phimin + offset) phiOk = false; + } + } else { + if (phi > 1.1) { + if (phi < phimax - offset) phiOk = false; + } else { + if (phi > phimax + offset) phiOk = false; + } + } + } else { + if (phi < phimin - offset || phi > phimax + offset) phiOk = false; } return phiOk; - } +} - Amg::Vector3D DCMathSegmentMaker::updateDirection( double linephi, const Trk::PlaneSurface& surf, - const Amg::Vector3D& roaddir, bool isCurvedSegment ) const { +Amg::Vector3D +DCMathSegmentMaker::updateDirection(double linephi, const Trk::PlaneSurface& surf, const Amg::Vector3D& roaddir, + bool isCurvedSegment) const +{ // Local direction along precision measurement (0, dy, dz) - Trk::LocalDirection segLocDirs( std::asin(1.), linephi ); - Amg::Vector3D gdirs; - surf.localToGlobalDirection(segLocDirs,gdirs); - // Local direction in plane (1,0,0) - Trk::LocalDirection segLocDiro( 0.,std::asin(1.)); - Amg::Vector3D gdiro; - surf.localToGlobalDirection(segLocDiro,gdiro); - - // recalculate the value of the local XZ angle for the give YZ angle of the segment such that the global phi direction remains unchanged - double dx = std::sin(gdirs.theta())*std::cos(gdirs.phi()); - double dy = std::sin(gdirs.theta())*std::sin(gdirs.phi()); - double dz = std::cos(gdirs.theta()); + Trk::LocalDirection segLocDirs(std::asin(1.), linephi); + Amg::Vector3D gdirs; + surf.localToGlobalDirection(segLocDirs, gdirs); + // Local direction in plane (1,0,0) + Trk::LocalDirection segLocDiro(0., std::asin(1.)); + Amg::Vector3D gdiro; + surf.localToGlobalDirection(segLocDiro, gdiro); + + // recalculate the value of the local XZ angle for the give YZ angle of the segment such that the global phi + // direction remains unchanged + double dx = std::sin(gdirs.theta()) * std::cos(gdirs.phi()); + double dy = std::sin(gdirs.theta()) * std::sin(gdirs.phi()); + double dz = std::cos(gdirs.theta()); // vector gdiro - double dxo = std::sin(gdiro.theta())*std::cos(gdiro.phi()); - double dyo = std::sin(gdiro.theta())*std::sin(gdiro.phi()); - double dzo = std::cos(gdiro.theta()); + double dxo = std::sin(gdiro.theta()) * std::cos(gdiro.phi()); + double dyo = std::sin(gdiro.theta()) * std::sin(gdiro.phi()); + double dzo = std::cos(gdiro.theta()); - // solve system real direction = A * gdir + B * gdiro + // solve system real direction = A * gdir + B * gdiro // phi global constraint: (1)*sin(phi road) - (2)*cos(phi road) = 0 // ( A * dx + B * dxo ) sin (phi ) - (A * dy + B *dyo ) cos (phi) = 0 // A ( dx sin - dy cos ) + B (dx0 sin -dy0 cos) = A * a0 + B * b0 = 0 - // psi = atan (-b0 , a0) - - double a0 = dx * std::sin (roaddir.phi()) - dy * std::cos(roaddir.phi()); - double b0 = dxo * std::sin (roaddir.phi()) - dyo * std::cos(roaddir.phi()); - if (b0 < 1e-8 && b0 > 0) b0 = 1e-8; - if (b0 > -1e-8 && b0 < 0) b0 = -1e-8; - double dxn = dx -a0*dxo/b0; - double dyn = dy -a0*dyo/b0; - double dzn = dz -a0*dzo/b0; - double norm = std::sqrt(dxn*dxn+dyn*dyn+dzn*dzn); - - // flip the sign if the direction NOT parallel to road - if( m_assumePointingPhi ){ - if (dxn*roaddir.x() + dyn*roaddir.y() + dzn*roaddir.z()< 0.) { - norm = -norm; - } - }else{ - if (dxn*roaddir.x() + dyn*roaddir.y() < 0.) { - norm = -norm; - } - } - - if(isCurvedSegment) norm = norm/2.; - - - // + // psi = atan (-b0 , a0) + + double a0 = dx * std::sin(roaddir.phi()) - dy * std::cos(roaddir.phi()); + double b0 = dxo * std::sin(roaddir.phi()) - dyo * std::cos(roaddir.phi()); + if (b0 < 1e-8 && b0 > 0) b0 = 1e-8; + if (b0 > -1e-8 && b0 < 0) b0 = -1e-8; + double dxn = dx - a0 * dxo / b0; + double dyn = dy - a0 * dyo / b0; + double dzn = dz - a0 * dzo / b0; + double norm = std::sqrt(dxn * dxn + dyn * dyn + dzn * dzn); + + // flip the sign if the direction NOT parallel to road + if (m_assumePointingPhi) { + if (dxn * roaddir.x() + dyn * roaddir.y() + dzn * roaddir.z() < 0.) { + norm = -norm; + } + } else { + if (dxn * roaddir.x() + dyn * roaddir.y() < 0.) { + norm = -norm; + } + } + + if (isCurvedSegment) norm = norm / 2.; + + + // // Follow segment fit direction // - dxn = dxn/norm; - dyn = dyn/norm; - dzn = dzn/norm; + dxn = dxn / norm; + dyn = dyn / norm; + dzn = dzn / norm; - return Amg::Vector3D(dxn,dyn,dzn); - } + return Amg::Vector3D(dxn, dyn, dzn); } - +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/DCMathSegmentMaker.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/DCMathSegmentMaker.h index 3a8a0925b13b4f37c1c0c567f46e2470662edf53..608c5b992f631d935601bd8478dfd063aa7fe50b 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/DCMathSegmentMaker.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/DCMathSegmentMaker.h @@ -5,427 +5,518 @@ #ifndef DCMATHSEGMENTMAKER_H #define DCMATHSEGMENTMAKER_H -#include "MuonRecToolInterfaces/IMuonSegmentMaker.h" -#include "MuonSegmentMakerToolInterfaces/IMuonSegmentTriggerHitAssociator.h" +#include <list> +#include <set> +#include <string> +#include <vector> + #include "AthenaBaseComps/AthAlgTool.h" +#include "EventPrimitives/EventPrimitives.h" #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" - -#include "MuonRIO_OnTrack/MuonClusterOnTrack.h" -#include "MuonSegment/MuonSegment.h" -#include "TrkDriftCircleMath/DCSLFitter.h" -#include "TrkDriftCircleMath/DCSLHitSelector.h" -#include "TrkDriftCircleMath/MdtChamberGeometry.h" -#include "TrkDriftCircleMath/DCStatistics.h" -#include "TrkDriftCircleMath/Cluster.h" -#include "TrkDriftCircleMath/DriftCircle.h" -#include "TrkSurfaces/Surface.h" -#include "MuonRecHelperTools/IMuonEDMHelperSvc.h" -#include "TrkFitterInterfaces/ITrackFitter.h" -#include "MuonCondData/MdtCondDbData.h" -#include "EventPrimitives/EventPrimitives.h" #include "GeoPrimitives/GeoPrimitives.h" +#include "MuonCondData/MdtCondDbData.h" +#include "MuonIdHelpers/IMuonIdHelperSvc.h" #include "MuonPrepRawData/RpcPrepDataContainer.h" -#include "MuonRecHelperTools/MuonEDMPrinterTool.h" +#include "MuonRIO_OnTrack/MuonClusterOnTrack.h" #include "MuonRecHelperTools/IMuonEDMHelperSvc.h" +#include "MuonRecHelperTools/MuonEDMPrinterTool.h" #include "MuonRecToolInterfaces/IMdtDriftCircleOnTrackCreator.h" +#include "MuonRecToolInterfaces/IMdtSegmentFinder.h" #include "MuonRecToolInterfaces/IMuonClusterOnTrackCreator.h" #include "MuonRecToolInterfaces/IMuonCompetingClustersOnTrackCreator.h" -#include "MuonRecToolInterfaces/IMdtSegmentFinder.h" #include "MuonRecToolInterfaces/IMuonSegmentFittingTool.h" -#include "MuonSegmentMakerToolInterfaces/IMuonSegmentSelectionTool.h" +#include "MuonRecToolInterfaces/IMuonSegmentMaker.h" +#include "MuonSegment/MuonSegment.h" #include "MuonSegmentMakerInterfaces/IDCSLFitProvider.h" -#include "MuonIdHelpers/IMuonIdHelperSvc.h" +#include "MuonSegmentMakerToolInterfaces/IMuonSegmentSelectionTool.h" +#include "MuonSegmentMakerToolInterfaces/IMuonSegmentTriggerHitAssociator.h" #include "MuonStationIntersectSvc/MuonStationIntersectSvc.h" - -#include <vector> -#include <set> -#include <string> -#include <list> +#include "TrkDriftCircleMath/Cluster.h" +#include "TrkDriftCircleMath/DCSLFitter.h" +#include "TrkDriftCircleMath/DCSLHitSelector.h" +#include "TrkDriftCircleMath/DCStatistics.h" +#include "TrkDriftCircleMath/DriftCircle.h" +#include "TrkDriftCircleMath/MdtChamberGeometry.h" +#include "TrkFitterInterfaces/ITrackFitter.h" +#include "TrkSurfaces/Surface.h" namespace Trk { - class RIO_OnTrack; - class PlaneSurface; -} +class RIO_OnTrack; +class PlaneSurface; +} // namespace Trk namespace TrkDriftCircleMath { - class MdtMultiChamberGeometry; - class Segment; -} +class MdtMultiChamberGeometry; +class Segment; +} // namespace TrkDriftCircleMath namespace MuonGM { - class MuonDetectorManager; +class MuonDetectorManager; } namespace Muon { - class MdtPrepData; +class MdtPrepData; } namespace Muon { class MdtDriftCircleOnTrack; - /** - Function object to sort MuonClusterOnTrack pointers by Identier. - Usage: - - std::vector<const MuonClusterOnTrack*> myClusters; - - ... - - std::sort( myClusters.begin(), myClusters.end(), SortClustersById() ); - */ - struct SortClustersById { - bool operator()( const MuonClusterOnTrack* cl1, const MuonClusterOnTrack* cl2 ){ - return cl1->identify() < cl2->identify(); +/** + Function object to sort MuonClusterOnTrack pointers by Identier. + Usage: + + std::vector<const MuonClusterOnTrack*> myClusters; + + ... + + std::sort( myClusters.begin(), myClusters.end(), SortClustersById() ); +*/ +struct SortClustersById { + bool operator()(const MuonClusterOnTrack* cl1, const MuonClusterOnTrack* cl2) + { + return cl1->identify() < cl2->identify(); } - }; - - - /** - Function object to sort pairs containing a double and a pointer to a MuonClusterOnTrack. - The object is used to sort MuonClusterOnTrack objects along the trajectory of a give segment. - Usage: - - std::vector<std::pair<double,const MuonClusterOnTrack*> > myDistClusters; - - ... - - std::sort( myDistClusters.begin(), myDistClusters.end(), SortByDistanceToSegment() ); - */ - struct SortByDistanceToSegment - { - bool operator()( const std::pair<double,const Trk::MeasurementBase*>& hit1, const std::pair<double,const Trk::MeasurementBase*>& hit2 ){ - return hit1.first < hit2.first; +}; + + +/** + Function object to sort pairs containing a double and a pointer to a MuonClusterOnTrack. + The object is used to sort MuonClusterOnTrack objects along the trajectory of a give segment. + Usage: + + std::vector<std::pair<double,const MuonClusterOnTrack*> > myDistClusters; + + ... + + std::sort( myDistClusters.begin(), myDistClusters.end(), SortByDistanceToSegment() ); +*/ +struct SortByDistanceToSegment { + bool operator()(const std::pair<double, const Trk::MeasurementBase*>& hit1, + const std::pair<double, const Trk::MeasurementBase*>& hit2) + { + return hit1.first < hit2.first; } - }; +}; - /** - @class DCMathSegmentMaker +/** + @class DCMathSegmentMaker - Implementation of a IMuonSegmentMaker. + Implementation of a IMuonSegmentMaker. - For more details look at the mainpage of this package. - */ - class DCMathSegmentMaker : virtual public IMuonSegmentMaker, public IMuonSegmentTriggerHitAssociator, public AthAlgTool { + For more details look at the mainpage of this package. +*/ +class DCMathSegmentMaker : virtual public IMuonSegmentMaker, + public IMuonSegmentTriggerHitAssociator, + public AthAlgTool { public: // pair of eta-phi hits in the same gasgap - typedef std::pair<std::vector<const MuonClusterOnTrack*>,std::vector<const MuonClusterOnTrack*> > EtaPhiHitsPair; + typedef std::pair<std::vector<const MuonClusterOnTrack*>, std::vector<const MuonClusterOnTrack*> > EtaPhiHitsPair; // map to sort hit per gasgap - typedef std::map<Identifier,EtaPhiHitsPair> IdHitMap; - typedef IdHitMap::iterator IdHitMapIt; - typedef std::map<Identifier,IdHitMap> ChIdHitMap; - typedef ChIdHitMap::iterator ChIdHitMapIt; + typedef std::map<Identifier, EtaPhiHitsPair> IdHitMap; + typedef IdHitMap::iterator IdHitMapIt; + typedef std::map<Identifier, IdHitMap> ChIdHitMap; + typedef ChIdHitMap::iterator ChIdHitMapIt; typedef std::vector<const MuonClusterOnTrack*>::const_iterator ROTCit; struct HitInXZ { - HitInXZ(Identifier i, bool isM, bool measP, double lx, double lz, double lxmin, double lxmax, double phmin, double phmax) : - id(i),isMdt(isM),measPhi(measP),x(lx),z(lz),xmin(lxmin),xmax(lxmax),phimin(phmin),phimax(phmax) {} - Identifier id; - bool isMdt; - bool measPhi; - double x; - double z; - double xmin; - double xmax; - double phimin; - double phimax; + HitInXZ(Identifier i, bool isM, bool measP, double lx, double lz, double lxmin, double lxmax, double phmin, + double phmax) + : id(i), isMdt(isM), measPhi(measP), x(lx), z(lz), xmin(lxmin), xmax(lxmax), phimin(phmin), phimax(phmax) + { + } + Identifier id; + bool isMdt; + bool measPhi; + double x; + double z; + double xmin; + double xmax; + double phimin; + double phimax; }; struct Cluster2D { - /** constructor taking a single phi hit */ - Cluster2D( const Identifier elId, const Identifier ggId, const Amg::Vector2D& lp, double err, - const MuonClusterOnTrack* ecl, const MuonClusterOnTrack* pcl ) : - detElId(elId),gasGapId(ggId),locPos(lp),error(err),etaHit(ecl),phiHit(pcl) { - if( ecl || pcl ) { - surface().localToGlobal(locPos,Amg::Vector3D::UnitZ(),globalPos); - } - if( pcl ) phiHits.push_back(pcl); - } - /** constructor taking a vector of phi hits */ - Cluster2D( const Identifier elId, const Identifier ggId, const Amg::Vector2D& lp, double err, - const MuonClusterOnTrack* ecl, const std::vector<const MuonClusterOnTrack*>& phs ) : - detElId(elId),gasGapId(ggId),locPos(lp),error(err),etaHit(ecl),phiHits(phs) { - // if phiHits to empty point phiHit to first hit in PhiHits - phiHit = phiHits.empty() ? 0 : phiHits.front(); - if( ecl || phiHit ) { - surface().localToGlobal(locPos,Amg::Vector3D::UnitZ(),globalPos); - } - } - Identifier detElId; - Identifier gasGapId; - Amg::Vector2D locPos; - double error; // assume same error for eta and phi - const MuonClusterOnTrack* etaHit; - const MuonClusterOnTrack* phiHit; - std::vector<const MuonClusterOnTrack*> phiHits; - const Trk::Surface& surface() const { - if( etaHit ) return etaHit->associatedSurface(); - else return phiHit->associatedSurface(); - } - Identifier identify() const { - if( etaHit ) return etaHit->identify(); - else return phiHit->identify(); - } - Amg::Vector3D globalPos; - bool is2D() const { return etaHit && phiHit; } - bool corrupt() const { return (!etaHit && !phiHit) || error < 0.01; } + /** constructor taking a single phi hit */ + Cluster2D(const Identifier elId, const Identifier ggId, const Amg::Vector2D& lp, double err, + const MuonClusterOnTrack* ecl, const MuonClusterOnTrack* pcl) + : detElId(elId), gasGapId(ggId), locPos(lp), error(err), etaHit(ecl), phiHit(pcl) + { + if (ecl || pcl) { + surface().localToGlobal(locPos, Amg::Vector3D::UnitZ(), globalPos); + } + if (pcl) phiHits.push_back(pcl); + } + /** constructor taking a vector of phi hits */ + Cluster2D(const Identifier elId, const Identifier ggId, const Amg::Vector2D& lp, double err, + const MuonClusterOnTrack* ecl, const std::vector<const MuonClusterOnTrack*>& phs) + : detElId(elId), gasGapId(ggId), locPos(lp), error(err), etaHit(ecl), phiHits(phs) + { + // if phiHits to empty point phiHit to first hit in PhiHits + phiHit = phiHits.empty() ? 0 : phiHits.front(); + if (ecl || phiHit) { + surface().localToGlobal(locPos, Amg::Vector3D::UnitZ(), globalPos); + } + } + Identifier detElId; + Identifier gasGapId; + Amg::Vector2D locPos; + double error; // assume same error for eta and phi + const MuonClusterOnTrack* etaHit; + const MuonClusterOnTrack* phiHit; + std::vector<const MuonClusterOnTrack*> phiHits; + const Trk::Surface& surface() const + { + if (etaHit) + return etaHit->associatedSurface(); + else + return phiHit->associatedSurface(); + } + Identifier identify() const + { + if (etaHit) + return etaHit->identify(); + else + return phiHit->identify(); + } + Amg::Vector3D globalPos; + bool is2D() const + { + return etaHit && phiHit; + } + bool corrupt() const + { + return (!etaHit && !phiHit) || error < 0.01; + } }; - typedef std::vector<Cluster2D> ClusterVec; - typedef ClusterVec::iterator ClusterIt; - typedef ClusterVec::const_iterator ClusterCit; - typedef std::pair<ClusterVec,ClusterVec> ClusterVecPair; + typedef std::vector<Cluster2D> ClusterVec; + typedef ClusterVec::iterator ClusterIt; + typedef ClusterVec::const_iterator ClusterCit; + typedef std::pair<ClusterVec, ClusterVec> ClusterVecPair; struct TubeEnds { - TubeEnds() : lxmin(0), lxmax(0), phimin(0), phimax(0) {} - double lxmin; - double lxmax; - double phimin; - double phimax; + TubeEnds() : lxmin(0), lxmax(0), phimin(0), phimax(0) {} + double lxmin; + double lxmax; + double phimin; + double phimax; }; - struct segmentCreationInfo {//miscellaneous objects needed for segment creation - segmentCreationInfo(ClusterVecPair& spVecs, TrkDriftCircleMath::MdtMultiChamberGeometry* multiGeo, Amg::Transform3D gToStation, Amg::Transform3D amdbToGlobal, double pmin, double pmax): - geom(multiGeo),phimin(pmin),phimax(pmax){ - ClusterVec spacePoints=spVecs.first; - ClusterVec phiHits=spVecs.second; - clusters=ClusterVecPair(spacePoints,phiHits); - globalTrans=gToStation; - amdbTrans=amdbToGlobal; - } - ClusterVecPair clusters; - TrkDriftCircleMath::MdtMultiChamberGeometry* geom; - Amg::Transform3D globalTrans; - Amg::Transform3D amdbTrans; - double phimin; - double phimax; + struct segmentCreationInfo { // miscellaneous objects needed for segment creation + segmentCreationInfo(ClusterVecPair& spVecs, TrkDriftCircleMath::MdtMultiChamberGeometry* multiGeo, + Amg::Transform3D gToStation, Amg::Transform3D amdbToGlobal, double pmin, double pmax) + : geom(multiGeo), phimin(pmin), phimax(pmax) + { + ClusterVec spacePoints = spVecs.first; + ClusterVec phiHits = spVecs.second; + clusters = ClusterVecPair(spacePoints, phiHits); + globalTrans = gToStation; + amdbTrans = amdbToGlobal; + } + ClusterVecPair clusters; + TrkDriftCircleMath::MdtMultiChamberGeometry* geom; + Amg::Transform3D globalTrans; + Amg::Transform3D amdbTrans; + double phimin; + double phimax; }; public: - DCMathSegmentMaker(const std::string&,const std::string&,const IInterface*); - - virtual ~DCMathSegmentMaker()=default; - + DCMathSegmentMaker(const std::string&, const std::string&, const IInterface*); + + virtual ~DCMathSegmentMaker() = default; + virtual StatusCode initialize(); - /** find segments starting from a list of RIO_OnTrack objects, implementation of IMuonSegmentMaker interface routine. - + /** find segments starting from a list of RIO_OnTrack objects, implementation of IMuonSegmentMaker interface + routine. + Will call: - + std::vector<const MuonSegment*>* find( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, const std::vector<const MdtDriftCircleOnTrack*>& mdts, - const std::vector<const MuonClusterOnTrack*>& clusters, bool hasPhiMeasurements); + const std::vector<const MuonClusterOnTrack*>& clusters, bool + hasPhiMeasurements); */ - void find( const std::vector<const Trk::RIO_OnTrack*>& rios, Trk::SegmentCollection* segColl=nullptr ) const ; - - /** find segments starting from a list of RIO_OnTrack objects in multiple chambers, implementation of IMuonSegmentMaker interface routine - Will call: - + void find(const std::vector<const Trk::RIO_OnTrack*>& rios, Trk::SegmentCollection* segColl = nullptr) const; + + /** find segments starting from a list of RIO_OnTrack objects in multiple chambers, implementation of + IMuonSegmentMaker interface routine Will call: + std::vector<const MuonSegment*>* find( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, const std::vector<const MdtDriftCircleOnTrack*>& mdts, - const std::vector<const MuonClusterOnTrack*>& clusters, bool hasPhiMeasurements); + const std::vector<const MuonClusterOnTrack*>& clusters, bool + hasPhiMeasurements); */ - void find( const std::vector<const Trk::RIO_OnTrack*>& rios1, - const std::vector<const Trk::RIO_OnTrack*>& rios2 ) const ; - - /** find segments starting from: - - a list of MdtDriftCircleOnTrack objects - - a list of MuonClusterOnTrack objects + void find(const std::vector<const Trk::RIO_OnTrack*>& rios1, + const std::vector<const Trk::RIO_OnTrack*>& rios2) const; + + /** find segments starting from: + - a list of MdtDriftCircleOnTrack objects + - a list of MuonClusterOnTrack objects - Implementation of IMuonSegmentMaker interface routine + Implementation of IMuonSegmentMaker interface routine - Will call: + Will call: - std::vector<const MuonSegment*>* find( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, - const std::vector<const MdtDriftCircleOnTrack*>& mdts, - const std::vector<const MuonClusterOnTrack*>& clusters, - bool hasPhiMeasurements, double momentum ); - */ + std::vector<const MuonSegment*>* find( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, + const std::vector<const MdtDriftCircleOnTrack*>& mdts, + const std::vector<const MuonClusterOnTrack*>& clusters, + bool hasPhiMeasurements, double momentum ); + */ void find(const std::vector<const MdtDriftCircleOnTrack*>& mdts, - const std::vector<const MuonClusterOnTrack*>& clusters, - Trk::SegmentCollection* segColl=nullptr) const ; + const std::vector<const MuonClusterOnTrack*>& clusters, Trk::SegmentCollection* segColl = nullptr) const; /** find segments starting from: - - an estimate of the global position and direction of the particle in the chamber - - a list of MdtDriftCircleOnTrack - - a list of MuonClusterOnTrack - - a boolean to indicate whether the external prediction should be used to set the - @f$ \phi @f$-direction of the segment + - an estimate of the global position and direction of the particle in the chamber + - a list of MdtDriftCircleOnTrack + - a list of MuonClusterOnTrack + - a boolean to indicate whether the external prediction should be used to set the + @f$ \phi @f$-direction of the segment - an estimate of the momentum of the particle - - The global direction is used to perform a seeded search for segments. + + The global direction is used to perform a seeded search for segments. */ - void find( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, - const std::vector<const MdtDriftCircleOnTrack*>& mdts, - const std::vector<const MuonClusterOnTrack*>& clusters, - bool hasPhiMeasurements = false, Trk::SegmentCollection* segColl=nullptr, double momentum = 1e9, double sinAngleCut=0 ) const; + void find(const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, + const std::vector<const MdtDriftCircleOnTrack*>& mdts, + const std::vector<const MuonClusterOnTrack*>& clusters, bool hasPhiMeasurements = false, + Trk::SegmentCollection* segColl = nullptr, double momentum = 1e9, double sinAngleCut = 0) const; /** find segments starting from: - - a track prediction - - a list of MdtDriftCircleOnTrack objects in multiple chambers, sorted by chamber - - a list of MuonClusterOnTrack objects in multiple chambers, sorted by chamber + - a track prediction + - a list of MdtDriftCircleOnTrack objects in multiple chambers, sorted by chamber + - a list of MuonClusterOnTrack objects in multiple chambers, sorted by chamber - Implementation of IMuonSegmentMaker interface routine + Implementation of IMuonSegmentMaker interface routine - Will call: + Will call: - std::vector<const MuonSegment*>* find( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, + std::vector<const MuonSegment*>* find( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, const std::vector<const MdtDriftCircleOnTrack*>& mdts, - const std::vector<const MuonClusterOnTrack*>& clusters, - bool hasPhiMeasurements, double momentum ); + const std::vector<const MuonClusterOnTrack*>& clusters, + bool hasPhiMeasurements, double momentum ); */ - void find( const Trk::TrackRoad& road, - const std::vector< std::vector< const MdtDriftCircleOnTrack* > >& mdts, - const std::vector< std::vector< const MuonClusterOnTrack* > >& clusters, - Trk::SegmentCollection* segColl, - bool hasPhiMeasurements = false, double momentum = 1e9) const; + void find(const Trk::TrackRoad& road, const std::vector<std::vector<const MdtDriftCircleOnTrack*> >& mdts, + const std::vector<std::vector<const MuonClusterOnTrack*> >& clusters, Trk::SegmentCollection* segColl, + bool hasPhiMeasurements = false, double momentum = 1e9) const; /** associate trigger hits to an existing segment - - a segment - - a list of MuonClusterOnTrack objects - - a flag indicating whether the eta hits should be added + - a segment + - a list of MuonClusterOnTrack objects + - a flag indicating whether the eta hits should be added - returns the new segment, owner ship passed to the caller. + returns the new segment, owner ship passed to the caller. - Implementation of IMuonSegmentTriggerHitAssociator interface routine + Implementation of IMuonSegmentTriggerHitAssociator interface routine */ - const MuonSegment* associateTriggerHits( const MuonSegment& seg, const std::vector<const MuonClusterOnTrack*>& clus, - bool includeEtaHits ) const; + const MuonSegment* associateTriggerHits(const MuonSegment& seg, const std::vector<const MuonClusterOnTrack*>& clus, + bool includeEtaHits) const; private: /** helper routine to print Identifers */ - std::string printSP( std::pair<double,double> resPull,const Cluster2D& spacePoint ) const; + std::string printSP(std::pair<double, double> resPull, const Cluster2D& spacePoint) const; /** apply error scaling for low mometum tracks */ - bool errorScalingRegion( const Identifier& id ) const; + bool errorScalingRegion(const Identifier& id) const; /** calculate error scaling factor */ - double errorScaleFactor( const Identifier& id, double curvature, bool hasPhiMeasurements ) const; - - std::vector<Identifier> calculateHoles( Identifier chid, Amg::Vector3D gpos, Amg::Vector3D gdir, bool hasMeasuredCoordinate, - std::set<Identifier>& deltaVec, std::set<Identifier>& outoftimeVec, std::vector<std::pair<double,const Trk::MeasurementBase*> >& rioDistVec ) const; - - TrkDriftCircleMath::DCVec createDCVec( const std::vector<const MdtDriftCircleOnTrack*>& mdts, double errorScale, std::set<Identifier>& chamberSet, - double& phimin, double& phimax, TrkDriftCircleMath::DCStatistics& dcStatistics, Amg::Transform3D gToStation, Amg::Transform3D amdbToGlobal ) const; - ClusterVecPair create1DClusters( const std::vector<const MuonClusterOnTrack*>& clusters ) const; - ClusterVecPair create2DClusters( const std::vector<const MuonClusterOnTrack*>& clusters ) const; - - void handleChamber( IdHitMap& gasGapHitMap ) const; - ClusterVecPair createSpacePoints( ChIdHitMap& chIdHitMap ) const; - ClusterVecPair createSpacePoints( IdHitMap& gasGapHitMap ) const; - Cluster2D createSpacePoint( const Identifier& gasGapId, const MuonClusterOnTrack* etaHit, const MuonClusterOnTrack* phiHit ) const; - Cluster2D createRpcSpacePoint( const Identifier& gasGapId, const MuonClusterOnTrack* etaHit, const std::vector<const MuonClusterOnTrack*>& phiHits ) const; - Cluster2D createTgcSpacePoint( const Identifier& gasGapId, const MuonClusterOnTrack* etaHit, const MuonClusterOnTrack* phiHit ) const; - TrkDriftCircleMath::CLVec createClusterVec( const Identifier& chid, ClusterVec& spVec, Amg::Transform3D gToStation ) const; - - std::vector<const Trk::MeasurementBase*> associateMDTsToSegment( const Amg::Vector3D& gdir, TrkDriftCircleMath::Segment& segment, - const std::vector<const MdtDriftCircleOnTrack*>& mdts, TrkDriftCircleMath::MdtMultiChamberGeometry* multiGeo, - Amg::Transform3D gToStation, Amg::Transform3D amdbToGlobal, - std::set<Identifier>& deltaVec, std::set<Identifier>& outoftimeVec, - std::vector<std::pair<double,const Trk::MeasurementBase*> >& rioDistVec ) const; - std::pair<std::pair<int,int>,bool> associateClustersToSegment( const TrkDriftCircleMath::Segment& segment, const Identifier& chid, Amg::Transform3D gToStation, - ClusterVecPair& spVecs, double phimin, double phimax, - std::vector<std::pair<double,const Trk::MeasurementBase*> >& rioDistVec) const; - DataVector<const Trk::MeasurementBase>* createROTVec(std::vector<std::pair<double,const Trk::MeasurementBase*> >& rioDistVec) const; - - double distanceToSegment( const TrkDriftCircleMath::Segment& segment, const Amg::Vector3D& hitPos, Amg::Transform3D gToStation ) const; - std::pair<double,double> residualAndPullWithSegment( const TrkDriftCircleMath::Segment& segment, const Cluster2D& spacePoint, Amg::Transform3D gToStation ) const; - - TrkDriftCircleMath::MdtChamberGeometry createChamberGeometry( const Identifier& chid, const Amg::Transform3D& gToStation ) const; - - const MdtDriftCircleOnTrack* findFirstRotInChamberWithMostHits( const std::vector<const MdtDriftCircleOnTrack*>& mdts ) const; - - bool updateSegmentPhi( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, - Amg::Vector2D& segLocPos, Trk::LocalDirection& segLocDir, - Trk::PlaneSurface& surf, const std::vector<const Trk::MeasurementBase*>& rots, - double phimin, double phimax) const; - - /** rotate the angle XZ until all hits are in bounds. - returns a pair of bool, double, the bool is false if the code did not update the dXdZ. the double is the updated dXdZ */ - std::pair<bool,double> rotateLocalAngleXZIntoBounds( double xline, double zline, double dXdZ, std::vector<HitInXZ>& hits ) const; + double errorScaleFactor(const Identifier& id, double curvature, bool hasPhiMeasurements) const; + + std::vector<Identifier> calculateHoles( + Identifier chid, Amg::Vector3D gpos, Amg::Vector3D gdir, bool hasMeasuredCoordinate, + std::set<Identifier>& deltaVec, std::set<Identifier>& outoftimeVec, + std::vector<std::pair<double, const Trk::MeasurementBase*> >& rioDistVec) const; + + TrkDriftCircleMath::DCVec createDCVec(const std::vector<const MdtDriftCircleOnTrack*>& mdts, double errorScale, + std::set<Identifier>& chamberSet, double& phimin, double& phimax, + TrkDriftCircleMath::DCStatistics& dcStatistics, Amg::Transform3D gToStation, + Amg::Transform3D amdbToGlobal) const; + ClusterVecPair create1DClusters(const std::vector<const MuonClusterOnTrack*>& clusters) const; + ClusterVecPair create2DClusters(const std::vector<const MuonClusterOnTrack*>& clusters) const; + + void handleChamber(IdHitMap& gasGapHitMap) const; + ClusterVecPair createSpacePoints(ChIdHitMap& chIdHitMap) const; + ClusterVecPair createSpacePoints(IdHitMap& gasGapHitMap) const; + Cluster2D createSpacePoint(const Identifier& gasGapId, const MuonClusterOnTrack* etaHit, + const MuonClusterOnTrack* phiHit) const; + Cluster2D createRpcSpacePoint(const Identifier& gasGapId, const MuonClusterOnTrack* etaHit, + const std::vector<const MuonClusterOnTrack*>& phiHits) const; + Cluster2D createTgcSpacePoint(const Identifier& gasGapId, const MuonClusterOnTrack* etaHit, + const MuonClusterOnTrack* phiHit) const; + TrkDriftCircleMath::CLVec createClusterVec(const Identifier& chid, ClusterVec& spVec, + Amg::Transform3D gToStation) const; + + std::vector<const Trk::MeasurementBase*> associateMDTsToSegment( + const Amg::Vector3D& gdir, TrkDriftCircleMath::Segment& segment, + const std::vector<const MdtDriftCircleOnTrack*>& mdts, TrkDriftCircleMath::MdtMultiChamberGeometry* multiGeo, + Amg::Transform3D gToStation, Amg::Transform3D amdbToGlobal, std::set<Identifier>& deltaVec, + std::set<Identifier>& outoftimeVec, + std::vector<std::pair<double, const Trk::MeasurementBase*> >& rioDistVec) const; + std::pair<std::pair<int, int>, bool> associateClustersToSegment( + const TrkDriftCircleMath::Segment& segment, const Identifier& chid, Amg::Transform3D gToStation, + ClusterVecPair& spVecs, double phimin, double phimax, + std::vector<std::pair<double, const Trk::MeasurementBase*> >& rioDistVec) const; + DataVector<const Trk::MeasurementBase>* createROTVec( + std::vector<std::pair<double, const Trk::MeasurementBase*> >& rioDistVec) const; + + double distanceToSegment(const TrkDriftCircleMath::Segment& segment, const Amg::Vector3D& hitPos, + Amg::Transform3D gToStation) const; + std::pair<double, double> residualAndPullWithSegment(const TrkDriftCircleMath::Segment& segment, + const Cluster2D& spacePoint, + Amg::Transform3D gToStation) const; + + TrkDriftCircleMath::MdtChamberGeometry createChamberGeometry(const Identifier& chid, + const Amg::Transform3D& gToStation) const; + + const MdtDriftCircleOnTrack* findFirstRotInChamberWithMostHits( + const std::vector<const MdtDriftCircleOnTrack*>& mdts) const; + + bool updateSegmentPhi(const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, Amg::Vector2D& segLocPos, + Trk::LocalDirection& segLocDir, Trk::PlaneSurface& surf, + const std::vector<const Trk::MeasurementBase*>& rots, double phimin, double phimax) const; + + /** rotate the angle XZ until all hits are in bounds. + returns a pair of bool, double, the bool is false if the code did not update the dXdZ. the double is the updated + dXdZ */ + std::pair<bool, double> rotateLocalAngleXZIntoBounds(double xline, double zline, double dXdZ, + std::vector<HitInXZ>& hits) const; /** check whether all hits are in bounds in the XZ plane */ - bool checkBoundsInXZ( double xline, double zline, double dXdZ, std::vector<HitInXZ>& hits ) const; + bool checkBoundsInXZ(double xline, double zline, double dXdZ, std::vector<HitInXZ>& hits) const; /** calculate positions of tube ends */ - TubeEnds localTubeEnds( const MdtDriftCircleOnTrack& mdt, const Amg::Transform3D& gToSegment, const Amg::Transform3D& segmentToG ) const; - + TubeEnds localTubeEnds(const MdtDriftCircleOnTrack& mdt, const Amg::Transform3D& gToSegment, + const Amg::Transform3D& segmentToG) const; + /** update phi ranges */ - void updatePhiRanges( double phiminNew, double phimaxNew, double& phiminRef, double& phimaxRef ) const; + void updatePhiRanges(double phiminNew, double phimaxNew, double& phiminRef, double& phimaxRef) const; /** check whether phi is consistent with segment phi */ - bool checkPhiConsistency( double phi, double phimin, double phimax ) const; + bool checkPhiConsistency(double phi, double phimin, double phimax) const; /** update the global direction, keeping the phi of the input road direction but using the local angle YZ */ - Amg::Vector3D updateDirection( double linephi, const Trk::PlaneSurface& surf, - const Amg::Vector3D& roaddir, bool isCurvedSegment ) const; + Amg::Vector3D updateDirection(double linephi, const Trk::PlaneSurface& surf, const Amg::Vector3D& roaddir, + bool isCurvedSegment) const; + + std::vector<const Trk::MeasurementBase*> addEtaHits(std::vector<const MuonClusterOnTrack*>& clusters, + bool isEndcap) const; - std::vector<const Trk::MeasurementBase*> addEtaHits( std::vector<const MuonClusterOnTrack*>& clusters, bool isEndcap ) const; + MuonSegment* createSegment(TrkDriftCircleMath::Segment& segment, const Identifier& chid, + const Amg::Vector3D& roadpos, const Amg::Vector3D& roaddir2, + const std::vector<const MdtDriftCircleOnTrack*>& mdts, bool hasPhiMeasurements, + segmentCreationInfo& sInfo) const; - MuonSegment* createSegment( TrkDriftCircleMath::Segment& segment, const Identifier& chid, - const Amg::Vector3D& roadpos, const Amg::Vector3D& roaddir2, - const std::vector<const MdtDriftCircleOnTrack*>& mdts, - bool hasPhiMeasurements, segmentCreationInfo& sInfo ) const; - - const MdtPrepData* findMdt( const Identifier& id ) const; + const MdtPrepData* findMdt(const Identifier& id) const; /** pointers to IdHelpers */ - SG::ReadCondHandleKey<MuonGM::MuonDetectorManager> m_DetectorManagerKey {this, "DetectorManagerKey", - "MuonDetectorManager", - "Key of input MuonDetectorManager condition data"}; - - ServiceHandle<MuonStationIntersectSvc> m_intersectSvc; //<! pointer to hole search service - - ToolHandle<IMdtDriftCircleOnTrackCreator> m_mdtCreator; //<! mdt rio ontrack creator - ToolHandle<IMdtDriftCircleOnTrackCreator> m_mdtCreatorT0; //<! mdt rio ontrack creator - ToolHandle<IMuonClusterOnTrackCreator> m_clusterCreator; //<! cluster rio ontrack creator - ToolHandle<IMuonCompetingClustersOnTrackCreator> m_compClusterCreator; //<! competing clusters rio ontrack creator - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - ToolHandle<MuonEDMPrinterTool> m_printer; //<! printer helper tool - ServiceHandle<IMuonEDMHelperSvc> m_edmHelperSvc {this, "edmHelper", - "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", - "Handle to the service providing the IMuonEDMHelperSvc interface" }; //<! edm helper tool - ToolHandle<IMdtSegmentFinder> m_segmentFinder; //<! segment finder tool - ToolHandle<IMuonSegmentFittingTool> m_segmentFitter; //<! segment fitting tool - ToolHandle<IMuonSegmentSelectionTool> m_segmentSelectionTool; //<! segment selection tool - ToolHandle<IDCSLFitProvider> m_dcslFitProvider; - - double m_sinAngleCut; //<! cut on the angle between the segment and the prediction - bool m_debugSpacePoints; //<! additional debug output for space point formation - bool m_doGeometry; //<! use chamber geometry in segment finding - bool m_curvedErrorScaling; //<! rescale errors for low momenta - bool m_doSpacePoints; //<! use cluster space points for association - bool m_createCompetingROTsEta; //<! create competing ROTs for the clusters - bool m_createCompetingROTsPhi; //<! create competing ROTs for the clusters - bool m_refitParameters; //<! refit segment if there are sufficient phi hits and update the segment parameters - bool m_addUnassociatedPhiHits; //<! if there are phi hits without associated eta hit add them to segment - bool m_strictRoadDirectionConsistencyCheck; //<! check if direction of road is consistent with IP (default: true), should be off for cosmics - double m_maxAssociateClusterDistance; //<! maximum distance for clusters to be associated to segment (default: 3000 (mm)) - bool m_allMdtHoles; //<! add all mdt holes without bound checks - bool m_removeDeltas; //<! do not add delta electrons to MuonSegmentQuality::holes - bool m_reject1DTgcSpacePoints; //<! remove 1D tgc space points - bool m_usePreciseError; - bool m_outputFittedT0; + SG::ReadCondHandleKey<MuonGM::MuonDetectorManager> m_DetectorManagerKey{ + this, + "DetectorManagerKey", + "MuonDetectorManager", + "Key of input MuonDetectorManager condition data", + }; + + ServiceHandle<MuonStationIntersectSvc> m_intersectSvc; //<! pointer to hole search service + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; + ServiceHandle<IMuonEDMHelperSvc> m_edmHelperSvc{ + this, + "edmHelper", + "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", + "Handle to the service providing the IMuonEDMHelperSvc interface", + }; //<! edm helper tool + + ToolHandle<IMdtDriftCircleOnTrackCreator> m_mdtCreator{ + this, + "MdtCreator", + "Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator", + }; //<! mdt rio ontrack creator + ToolHandle<IMdtDriftCircleOnTrackCreator> m_mdtCreatorT0{ + this, + "MdtCreatorT0", + "Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator", + }; //<! mdt rio ontrack creator + ToolHandle<IMuonClusterOnTrackCreator> m_clusterCreator{ + this, + "MuonClusterCreator", + "Muon::MuonClusterOnTrackCreator/MuonClusterOnTrackCreator", + }; //<! cluster rio ontrack creator + ToolHandle<IMuonCompetingClustersOnTrackCreator> m_compClusterCreator{ + this, + "MuonCompetingClustersCreator", + "Muon::TriggerChamberClusterOnTrackCreator/TriggerChamberClusterOnTrackCreator", + }; //<! competing clusters rio ontrack creator + ToolHandle<MuonEDMPrinterTool> m_printer{ + this, + "EDMPrinter", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; //<! printer helper tool + ToolHandle<IMdtSegmentFinder> m_segmentFinder{ + this, + "MdtSegmentFinder", + "Muon::MdtMathSegmentFinder/MdtMathSegmentFinder", + }; //<! segment finder tool + ToolHandle<IMuonSegmentFittingTool> m_segmentFitter{ + this, + "SegmentFitter", + "Muon::MuonSegmentFittingTool/MuonSegmentFittingTool", + }; //<! segment fitting tool + ToolHandle<IMuonSegmentSelectionTool> m_segmentSelectionTool{ + this, + "SegmentSelector", + "Muon::MuonSegmentSelectionTool/MuonSegmentSelectionTool", + }; //<! segment selection tool + ToolHandle<IDCSLFitProvider> m_dcslFitProvider{ + this, + "DCFitProvider", + "", + }; + + double m_sinAngleCut; //<! cut on the angle between the segment and the prediction + bool m_debugSpacePoints; //<! additional debug output for space point formation + bool m_doGeometry; //<! use chamber geometry in segment finding + bool m_curvedErrorScaling; //<! rescale errors for low momenta + bool m_doSpacePoints; //<! use cluster space points for association + bool m_createCompetingROTsEta; //<! create competing ROTs for the clusters + bool m_createCompetingROTsPhi; //<! create competing ROTs for the clusters + bool m_refitParameters; //<! refit segment if there are sufficient phi hits and update the segment parameters + bool m_addUnassociatedPhiHits; //<! if there are phi hits without associated eta hit add them to segment + bool m_strictRoadDirectionConsistencyCheck; //<! check if direction of road is consistent with IP (default: true), + // should be off for cosmics + double m_maxAssociateClusterDistance; //<! maximum distance for clusters to be associated to segment (default: 3000 + //(mm)) + bool m_allMdtHoles; //<! add all mdt holes without bound checks + bool m_removeDeltas; //<! do not add delta electrons to MuonSegmentQuality::holes + bool m_reject1DTgcSpacePoints; //<! remove 1D tgc space points + bool m_usePreciseError; + bool m_outputFittedT0; double m_preciseErrorScale; - bool m_doTimeOutChecks; - bool m_recoverBadRpcCabling; - bool m_updatePhiUsingPhiHits; - bool m_assumePointingPhi; - bool m_redo2DFit; - - SG::ReadHandleKey <Muon::RpcPrepDataContainer> m_rpcKey; - SG::ReadHandleKey <Muon::TgcPrepDataContainer> m_tgcKey; - SG::ReadHandleKey <Muon::MdtPrepDataContainer> m_mdtKey; - SG::ReadCondHandleKey <MdtCondDbData> m_condKey{this, "MdtCondKey", "MdtCondDbData", "Key of MdtCondDbData"}; - - }; - -} -#endif + bool m_doTimeOutChecks; + bool m_recoverBadRpcCabling; + bool m_updatePhiUsingPhiHits; + bool m_assumePointingPhi; + bool m_redo2DFit; + + SG::ReadHandleKey<Muon::RpcPrepDataContainer> m_rpcKey; + SG::ReadHandleKey<Muon::TgcPrepDataContainer> m_tgcKey; + SG::ReadHandleKey<Muon::MdtPrepDataContainer> m_mdtKey; + SG::ReadCondHandleKey<MdtCondDbData> m_condKey{ + this, + "MdtCondKey", + "MdtCondDbData", + "Key of MdtCondDbData", + }; +}; +} // namespace Muon +#endif diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MdtMathSegmentFinder.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MdtMathSegmentFinder.cxx index 9f8d20ceac38e1a0cca3890681109dc9f5cc1dfb..ba122c67977bad7af7de82bad9de0e1b312eaa77 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MdtMathSegmentFinder.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MdtMathSegmentFinder.cxx @@ -4,190 +4,193 @@ #include "MdtMathSegmentFinder.h" -#include "TrkDriftCircleMath/SegmentFinder.h" -#include "TrkDriftCircleMath/Road.h" -#include "TrkDriftCircleMath/DCStatistics.h" -#include "TrkDriftCircleMath/DCSLFitter.h" #include "MuonReadoutGeometry/MdtReadoutElement.h" +#include "TrkDriftCircleMath/DCSLFitter.h" +#include "TrkDriftCircleMath/DCStatistics.h" +#include "TrkDriftCircleMath/Road.h" +#include "TrkDriftCircleMath/SegmentFinder.h" namespace Muon { - MdtMathSegmentFinder::MdtMathSegmentFinder (const std::string& t, const std::string& n, const IInterface* p) : - AthAlgTool (t, n, p), - m_dcslFitProvider("",this) - { - declareInterface <IMdtSegmentFinder> (this); - - declareProperty("FinderDebugLevel", m_finderDebugLevel = 0, "switch on debug output of finder"); - declareProperty("DoDrop", m_doDrop = true, "Recursive outlier removal"); - declareProperty("Chi2PerDofDropping", m_chi2PerDofDrop = 10., "Chi2 cut for recursive outlier removal" ); - declareProperty("RatioEmptyTubeCut", m_ratioEmptyTubesCut = 1.1, "holes/hits cut - holes are all non-hits along the line" ); - declareProperty("EnableSeedCleaning", m_enableSeedCleaning = false, "only use dc witout neighbours as seeds" ); - declareProperty("OccupancyThreshold", m_occupancyThreshold = 0.3, "occupancy threshold before enabling seed cleaning"); - declareProperty("OccupancyCutoff", m_occupancyCutOff = 0.8, "above the occupancy threshold no segment finding"); - declareProperty("RPCAssocationPullcut", m_rpcAssociationPullCut = 5., "Association cut for RPCs" ); - declareProperty("TGCAssocationPullcut", m_tgcAssociationPullCut = 5., "Association cut for TGCs" ); - declareProperty("MDTAssocationPullcut", m_mdtAssociationPullCut = 5., "Association cut for MDTs" ); - declareProperty("UseChamberTheta", m_useChamberTheta = true, "Always look for pointing segments" ); - declareProperty("SortSegmentWithAllHits", m_doAllHitSort = true, "Including triggers in segment selection" ); - declareProperty("AssociationRoadWidth", m_roadWidth = 1.5, "Road width used during hit association with seed lines" ); - declareProperty("SearchForPointingSegments", m_useChamberTheta = true, "Always search for pointing segments" ); - declareProperty("DoRoadSeeding", m_doRoadAngleSeeding = true ); - declareProperty("DoIPSeeding", m_doIPAngleSeeding = true ); - declareProperty("TightRoadCut", m_tightRoadCut = 0.1 ); - declareProperty("MaxHitsPerFullSearch", m_maxHitsPerFullSearch = 100 ); - declareProperty("DoSingleMultiLayerScan", m_doSingleMultiLayerScan = true,"Look for segments in one multi layer"); - declareProperty("RecoverMdtOutliers", m_recoverMdtOutliers = true,"Recover MDT outliers after fit"); - declareProperty("RemoveSingleMdtOutliers",m_removeSingleOutliers = true,"Remove single MDT outliers"); - declareProperty("DoCurvedSegmentFinder", m_doCurvedSegmentFinder = false,"Use the curved segment finding routine"); - declareProperty("DeltaCutT0Segments", m_deltaCutT0Segments = 5.,"Delta cut for segments with T0 fit"); - declareProperty("ResidualCutT0Segments", m_residualCutT0Segments = 1.,"Residual cut for segments with T0 fit"); - declareProperty("UseSegmentQuality", m_useSegmentQuality = false,"Use segment quality in hit dropping"); - declareProperty("DCFitProvider", m_dcslFitProvider ); - } - - StatusCode MdtMathSegmentFinder::initialize() - { +MdtMathSegmentFinder::MdtMathSegmentFinder(const std::string& t, const std::string& n, const IInterface* p) + : AthAlgTool(t, n, p) +{ + declareInterface<IMdtSegmentFinder>(this); + + declareProperty("FinderDebugLevel", m_finderDebugLevel = 0, "switch on debug output of finder"); + declareProperty("DoDrop", m_doDrop = true, "Recursive outlier removal"); + declareProperty("Chi2PerDofDropping", m_chi2PerDofDrop = 10., "Chi2 cut for recursive outlier removal"); + declareProperty("RatioEmptyTubeCut", m_ratioEmptyTubesCut = 1.1, + "holes/hits cut - holes are all non-hits along the line"); + declareProperty("EnableSeedCleaning", m_enableSeedCleaning = false, "only use dc witout neighbours as seeds"); + declareProperty("OccupancyThreshold", m_occupancyThreshold = 0.3, + "occupancy threshold before enabling seed cleaning"); + declareProperty("OccupancyCutoff", m_occupancyCutOff = 0.8, "above the occupancy threshold no segment finding"); + declareProperty("RPCAssocationPullcut", m_rpcAssociationPullCut = 5., "Association cut for RPCs"); + declareProperty("TGCAssocationPullcut", m_tgcAssociationPullCut = 5., "Association cut for TGCs"); + declareProperty("MDTAssocationPullcut", m_mdtAssociationPullCut = 5., "Association cut for MDTs"); + declareProperty("UseChamberTheta", m_useChamberTheta = true, "Always look for pointing segments"); + declareProperty("SortSegmentWithAllHits", m_doAllHitSort = true, "Including triggers in segment selection"); + declareProperty("AssociationRoadWidth", m_roadWidth = 1.5, + "Road width used during hit association with seed lines"); + declareProperty("SearchForPointingSegments", m_useChamberTheta = true, "Always search for pointing segments"); + declareProperty("DoRoadSeeding", m_doRoadAngleSeeding = true); + declareProperty("DoIPSeeding", m_doIPAngleSeeding = true); + declareProperty("TightRoadCut", m_tightRoadCut = 0.1); + declareProperty("MaxHitsPerFullSearch", m_maxHitsPerFullSearch = 100); + declareProperty("DoSingleMultiLayerScan", m_doSingleMultiLayerScan = true, "Look for segments in one multi layer"); + declareProperty("RecoverMdtOutliers", m_recoverMdtOutliers = true, "Recover MDT outliers after fit"); + declareProperty("RemoveSingleMdtOutliers", m_removeSingleOutliers = true, "Remove single MDT outliers"); + declareProperty("DoCurvedSegmentFinder", m_doCurvedSegmentFinder = false, "Use the curved segment finding routine"); + declareProperty("DeltaCutT0Segments", m_deltaCutT0Segments = 5., "Delta cut for segments with T0 fit"); + declareProperty("ResidualCutT0Segments", m_residualCutT0Segments = 1., "Residual cut for segments with T0 fit"); + declareProperty("UseSegmentQuality", m_useSegmentQuality = false, "Use segment quality in hit dropping"); +} + +StatusCode +MdtMathSegmentFinder::initialize() +{ if (!m_dcslFitProvider.empty()) { - ATH_CHECK(m_dcslFitProvider.retrieve()); - ATH_MSG_INFO(" Using fitter from " << m_dcslFitProvider); + ATH_CHECK(m_dcslFitProvider.retrieve()); + ATH_MSG_INFO(" Using fitter from " << m_dcslFitProvider); } ATH_CHECK(m_idHelperSvc.retrieve()); return StatusCode::SUCCESS; - } +} - const TrkDriftCircleMath::SegVec MdtMathSegmentFinder::findSegments (const TrkDriftCircleMath::DCVec& dcvec, - const TrkDriftCircleMath::CLVec& clvec, - const TrkDriftCircleMath::Road& road, - const TrkDriftCircleMath::DCStatistics& dcstats, - const TrkDriftCircleMath::ChamberGeometry* multiGeo = 0 ) const - { +const TrkDriftCircleMath::SegVec +MdtMathSegmentFinder::findSegments(const TrkDriftCircleMath::DCVec& dcvec, const TrkDriftCircleMath::CLVec& clvec, + const TrkDriftCircleMath::Road& road, + const TrkDriftCircleMath::DCStatistics& dcstats, + const TrkDriftCircleMath::ChamberGeometry* multiGeo = 0) const +{ // setup finder - std::unique_ptr<TrkDriftCircleMath::SegmentFinder> segmentFinder (new TrkDriftCircleMath::SegmentFinder(m_roadWidth,m_mdtAssociationPullCut,false)); + std::unique_ptr<TrkDriftCircleMath::SegmentFinder> segmentFinder( + new TrkDriftCircleMath::SegmentFinder(m_roadWidth, m_mdtAssociationPullCut, false)); // set debug level segmentFinder->debugLevel(m_finderDebugLevel); // configure uasge of chamber position for angular seeding - segmentFinder->setUseChamberPhi( m_useChamberTheta ); + segmentFinder->setUseChamberPhi(m_useChamberTheta); // enable dropping of hits - segmentFinder->setDropHits( m_doDrop ); + segmentFinder->setDropHits(m_doDrop); // enable seed cleaing - segmentFinder->setSeedCleaning( m_enableSeedCleaning ); + segmentFinder->setSeedCleaning(m_enableSeedCleaning); // do single multilayer scan? - segmentFinder->setSingleMultiLayerScan( m_doSingleMultiLayerScan ); + segmentFinder->setSingleMultiLayerScan(m_doSingleMultiLayerScan); // set chi2/ndof threshold for cleaning of segments - segmentFinder->setChi2DropCut( m_chi2PerDofDrop ); + segmentFinder->setChi2DropCut(m_chi2PerDofDrop); // set ratio for dropping segments with many empty tubes - segmentFinder->setRatioEmptyTubesCut( m_ratioEmptyTubesCut ); + segmentFinder->setRatioEmptyTubesCut(m_ratioEmptyTubesCut); // set sort mode segment finder - segmentFinder->setSortSegmentsUsingAllHits( m_doAllHitSort ); + segmentFinder->setSortSegmentsUsingAllHits(m_doAllHitSort); // set RPC pull cut - segmentFinder->setRPCPullCut( m_rpcAssociationPullCut ); + segmentFinder->setRPCPullCut(m_rpcAssociationPullCut); // set TGC pull cut - segmentFinder->setTGCPullCut( m_tgcAssociationPullCut ); + segmentFinder->setTGCPullCut(m_tgcAssociationPullCut); // set MDT outlier recovery - segmentFinder->setRecoverMDT( m_recoverMdtOutliers ); + segmentFinder->setRecoverMDT(m_recoverMdtOutliers); // set removal of single outliers - segmentFinder->setRemoveSingleOutliers( m_removeSingleOutliers ); + segmentFinder->setRemoveSingleOutliers(m_removeSingleOutliers); // set the curved segment finder - segmentFinder->setCurvedSegmentFinder( m_doCurvedSegmentFinder ); + segmentFinder->setCurvedSegmentFinder(m_doCurvedSegmentFinder); // set removal of single outliers - segmentFinder->setDeltaCutT0( m_deltaCutT0Segments ); // reset defaults + segmentFinder->setDeltaCutT0(m_deltaCutT0Segments); // reset defaults // set removal of single outliers - segmentFinder->setResidualCutT0( m_residualCutT0Segments ); + segmentFinder->setResidualCutT0(m_residualCutT0Segments); // set use of segment quality - segmentFinder->setUseSegmentQuality( m_useSegmentQuality ); + segmentFinder->setUseSegmentQuality(m_useSegmentQuality); - std::unique_ptr<TrkDriftCircleMath::DCSLFitter> dcslFitter; - if( !m_dcslFitProvider.empty() ){ - segmentFinder->setFitter( m_dcslFitProvider->getFitter() ); - } - else{ - dcslFitter=std::make_unique<TrkDriftCircleMath::DCSLFitter>(); - segmentFinder->setFitter( dcslFitter.get() ); + std::unique_ptr<TrkDriftCircleMath::DCSLFitter> dcslFitter; + if (!m_dcslFitProvider.empty()) { + segmentFinder->setFitter(m_dcslFitProvider->getFitter()); + } else { + dcslFitter = std::make_unique<TrkDriftCircleMath::DCSLFitter>(); + segmentFinder->setFitter(dcslFitter.get()); } // set angle prediction from road - segmentFinder->setPhiRoad( road.angle(), road.chamberAngle(), road.width(), m_doRoadAngleSeeding, m_doIPAngleSeeding ); + segmentFinder->setPhiRoad(road.angle(), road.chamberAngle(), road.width(), m_doRoadAngleSeeding, + m_doIPAngleSeeding); // set pointer to geometry - segmentFinder->setMdtGeometry( multiGeo ); + segmentFinder->setMdtGeometry(multiGeo); // set seed cleaning - bool highOccupancy = false; - bool aboveOccupancyCut = false; - double occupancyMax = 0.; - unsigned int nmdtHits = 0; + bool highOccupancy = false; + bool aboveOccupancyCut = false; + double occupancyMax = 0.; + unsigned int nmdtHits = 0; // calculate multi layer occupancy - TrkDriftCircleMath::DCStatCit mit = dcstats.begin(); + TrkDriftCircleMath::DCStatCit mit = dcstats.begin(); TrkDriftCircleMath::DCStatCit mit_end = dcstats.end(); - for( ;mit!=mit_end;++mit ){ - - unsigned int channels = mit->first->getNLayers()*mit->first->getNtubesperlayer(); - double occupancy = (double)mit->second/(double)channels; + for (; mit != mit_end; ++mit) { - nmdtHits += mit->second; + unsigned int channels = mit->first->getNLayers() * mit->first->getNtubesperlayer(); + double occupancy = (double)mit->second / (double)channels; - if( occupancy > occupancyMax ) occupancyMax = occupancy; + nmdtHits += mit->second; - if( occupancy > m_occupancyThreshold ) highOccupancy = true; - - if( occupancy > m_occupancyCutOff ) aboveOccupancyCut = true; + if (occupancy > occupancyMax) occupancyMax = occupancy; - ATH_MSG_VERBOSE(" multilayer occupancy: " << occupancy - << " " << m_idHelperSvc->toStringDetEl(mit->first->identify())); + if (occupancy > m_occupancyThreshold) highOccupancy = true; + if (occupancy > m_occupancyCutOff) aboveOccupancyCut = true; + + ATH_MSG_VERBOSE(" multilayer occupancy: " << occupancy << " " + << m_idHelperSvc->toStringDetEl(mit->first->identify())); } // sanity check - if( nmdtHits != dcvec.size() ){ - ATH_MSG_WARNING(" inconsistent number of mdt hits " << nmdtHits << " from vec " << dcvec.size()); - nmdtHits = dcvec.size(); + if (nmdtHits != dcvec.size()) { + ATH_MSG_WARNING(" inconsistent number of mdt hits " << nmdtHits << " from vec " << dcvec.size()); + nmdtHits = dcvec.size(); } - if( aboveOccupancyCut ) { - ATH_MSG_DEBUG(" layer with occupancy above threshold, aborting segment finding " << occupancyMax << " cut " << m_occupancyCutOff - << " nhits " << nmdtHits << " cut " << m_maxHitsPerFullSearch); - return TrkDriftCircleMath::SegVec(); + if (aboveOccupancyCut) { + ATH_MSG_DEBUG(" layer with occupancy above threshold, aborting segment finding " + << occupancyMax << " cut " << m_occupancyCutOff << " nhits " << nmdtHits << " cut " + << m_maxHitsPerFullSearch); + return TrkDriftCircleMath::SegVec(); } // enable seed cleaning - if( highOccupancy || nmdtHits > m_maxHitsPerFullSearch ) { + if (highOccupancy || nmdtHits > m_maxHitsPerFullSearch) { + - - ATH_MSG_DEBUG(" switch to fast search: occupancy " << occupancyMax << " cut " << m_occupancyThreshold - << " nhits " << nmdtHits << " cut " << m_maxHitsPerFullSearch); + ATH_MSG_DEBUG(" switch to fast search: occupancy " << occupancyMax << " cut " << m_occupancyThreshold + << " nhits " << nmdtHits << " cut " + << m_maxHitsPerFullSearch); - // to speed up reconstruction use default fitter - if( !m_dcslFitProvider.empty() ){ - dcslFitter=std::make_unique<TrkDriftCircleMath::DCSLFitter>(); - segmentFinder->setFitter( dcslFitter.get() ); - } - - // use tight road cuts and only look for pointing segments - segmentFinder->setPhiRoad( road.chamberAngle(), road.chamberAngle(), m_tightRoadCut ); + // to speed up reconstruction use default fitter + if (!m_dcslFitProvider.empty()) { + dcslFitter = std::make_unique<TrkDriftCircleMath::DCSLFitter>(); + segmentFinder->setFitter(dcslFitter.get()); + } + // use tight road cuts and only look for pointing segments + segmentFinder->setPhiRoad(road.chamberAngle(), road.chamberAngle(), m_tightRoadCut); } - return segmentFinder->findSegments(dcvec,clvec); - } + return segmentFinder->findSegments(dcvec, clvec); +} -} +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MdtMathSegmentFinder.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MdtMathSegmentFinder.h index 2b7820310f50a432141d6dfdbbad83105883578c..53cf389ecfbeb2c8c36eac11bc778cdb28782d2f 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MdtMathSegmentFinder.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MdtMathSegmentFinder.h @@ -5,63 +5,70 @@ #ifndef DCMATHSEGMENTMAKER_MDTMATHSEGMENTFINDER_H #define DCMATHSEGMENTMAKER_MDTMATHSEGMENTFINDER_H -#include "MuonRecToolInterfaces/IMdtSegmentFinder.h" #include "AthenaBaseComps/AthAlgTool.h" #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" - #include "MuonIdHelpers/IMuonIdHelperSvc.h" +#include "MuonRecToolInterfaces/IMdtSegmentFinder.h" #include "MuonSegmentMakerInterfaces/IDCSLFitProvider.h" namespace Muon { - class MdtMathSegmentFinder : virtual public IMdtSegmentFinder::IMdtSegmentFinder, public AthAlgTool - { +class MdtMathSegmentFinder : virtual public IMdtSegmentFinder::IMdtSegmentFinder, public AthAlgTool { public: - MdtMathSegmentFinder (const std::string& t, const std::string& n, const IInterface* p); - - ~MdtMathSegmentFinder()=default; - + MdtMathSegmentFinder(const std::string& t, const std::string& n, const IInterface* p); + + ~MdtMathSegmentFinder() = default; + virtual StatusCode initialize(); - + /** IMdtMdtMathSegmentFinder interface implementation */ - virtual const TrkDriftCircleMath::SegVec findSegments ( const TrkDriftCircleMath::DCVec& dcvec, - const TrkDriftCircleMath::CLVec& clvec, - const TrkDriftCircleMath::Road& road, - const TrkDriftCircleMath::DCStatistics& dcstats, - const TrkDriftCircleMath::ChamberGeometry* multiGeo ) const; + virtual const TrkDriftCircleMath::SegVec findSegments(const TrkDriftCircleMath::DCVec& dcvec, + const TrkDriftCircleMath::CLVec& clvec, + const TrkDriftCircleMath::Road& road, + const TrkDriftCircleMath::DCStatistics& dcstats, + const TrkDriftCircleMath::ChamberGeometry* multiGeo) const; + protected: + ToolHandle<IDCSLFitProvider> m_dcslFitProvider{ + this, + "DCFitProvider", + "", + }; - ToolHandle<IDCSLFitProvider> m_dcslFitProvider; - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; - int m_finderDebugLevel; //<! additional debug output - bool m_doDrop; //<! enable dropping of hits from segment - bool m_useChamberTheta; //<! enable to usage of the angle from the chamber position to seed the finder - bool m_enableSeedCleaning; //<! enable seed cleaning for busy events - double m_occupancyThreshold; //<! threshold use when seeding is enabled - double m_occupancyCutOff; //<! threshold above which no segment finding is performed - double m_roadWidth; //<! width of road used to associate hits to seed lines - double m_chi2PerDofDrop; //<! maximum chi2 per dof used during cleaning - double m_ratioEmptyTubesCut; //<! cut on the ratio empty tubes/(hits on track + delta) - double m_mdtAssociationPullCut; //<! cut on the pull of MDT hits during association to segment - double m_rpcAssociationPullCut; //<! cut on the pull of RPC hits during association to segment - double m_tgcAssociationPullCut; //<! cut on the pull of TGC hits during association to segment - bool m_doAllHitSort; //<! configure the SegmentFinder to include trigger hits in sorting of segments - bool m_doRoadAngleSeeding; //<! use angle of road to seed segment search - bool m_doIPAngleSeeding; //<! use angle of IP to seed segment search - double m_tightRoadCut; //<! tight cut on angle with prediction, used for very busy chambers - bool m_doSingleMultiLayerScan; //<! perform single ml scan - bool m_recoverMdtOutliers; //<! recover MDT outliers - bool m_removeSingleOutliers; //<! remove single bad hits from segment - bool m_doCurvedSegmentFinder; //<! use curved segment finding routine - double m_deltaCutT0Segments; //<! delta cut for segments with T0 - double m_residualCutT0Segments; //<! residual cut for segments with T0 - bool m_useSegmentQuality; //<! use segment quality in hit dropping instead of chi2 + int m_finderDebugLevel; //<! additional debug output + bool m_doDrop; //<! enable dropping of hits from segment + bool m_useChamberTheta; //<! enable to usage of the angle from the chamber position to seed the finder + bool m_enableSeedCleaning; //<! enable seed cleaning for busy events + double m_occupancyThreshold; //<! threshold use when seeding is enabled + double m_occupancyCutOff; //<! threshold above which no segment finding is performed + double m_roadWidth; //<! width of road used to associate hits to seed lines + double m_chi2PerDofDrop; //<! maximum chi2 per dof used during cleaning + double m_ratioEmptyTubesCut; //<! cut on the ratio empty tubes/(hits on track + delta) + double m_mdtAssociationPullCut; //<! cut on the pull of MDT hits during association to segment + double m_rpcAssociationPullCut; //<! cut on the pull of RPC hits during association to segment + double m_tgcAssociationPullCut; //<! cut on the pull of TGC hits during association to segment + bool m_doAllHitSort; //<! configure the SegmentFinder to include trigger hits in sorting of segments + bool m_doRoadAngleSeeding; //<! use angle of road to seed segment search + bool m_doIPAngleSeeding; //<! use angle of IP to seed segment search + double m_tightRoadCut; //<! tight cut on angle with prediction, used for very busy chambers + bool m_doSingleMultiLayerScan; //<! perform single ml scan + bool m_recoverMdtOutliers; //<! recover MDT outliers + bool m_removeSingleOutliers; //<! remove single bad hits from segment + bool m_doCurvedSegmentFinder; //<! use curved segment finding routine + double m_deltaCutT0Segments; //<! delta cut for segments with T0 + double m_residualCutT0Segments; //<! residual cut for segments with T0 + bool m_useSegmentQuality; //<! use segment quality in hit dropping instead of chi2 - unsigned int m_maxHitsPerFullSearch; //<! maximum number of hits, above will use faster search mode - }; + unsigned int m_maxHitsPerFullSearch; //<! maximum number of hits, above will use faster search mode +}; -} +} // namespace Muon #endif diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonClusterSegmentFinderTool.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonClusterSegmentFinderTool.cxx index 40fabbd7a889ca6da9c6377e20ddf5b031ec6ccb..669d7d56507475ef2744081ff2291f3debc73e5b 100755 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonClusterSegmentFinderTool.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonClusterSegmentFinderTool.cxx @@ -3,974 +3,1054 @@ */ #include "MuonClusterSegmentFinderTool.h" + +#include "EventPrimitives/EventPrimitivesHelpers.h" +#include "MuonPrepRawData/MMPrepData.h" #include "MuonPrepRawData/MuonPrepDataCollection.h" +#include "MuonPrepRawData/sTgcPrepData.h" +#include "MuonReadoutGeometry/MuonPadDesign.h" #include "MuonReadoutGeometry/MuonReadoutElement.h" #include "MuonReadoutGeometry/sTgcReadoutElement.h" -#include "MuonReadoutGeometry/MuonPadDesign.h" -#include "MuonPrepRawData/sTgcPrepData.h" -#include "MuonPrepRawData/MMPrepData.h" -#include "TrkTrack/Track.h" -#include "TrkParameters/TrackParameters.h" +#include "MuonRecToolInterfaces/IMuonTrackCleaner.h" #include "TrkEventPrimitives/FitQuality.h" +#include "TrkParameters/TrackParameters.h" #include "TrkPseudoMeasurementOnTrack/PseudoMeasurementOnTrack.h" -#include "MuonRecToolInterfaces/IMuonTrackCleaner.h" -#include "EventPrimitives/EventPrimitivesHelpers.h" +#include "TrkTrack/Track.h" namespace Muon { - MuonClusterSegmentFinderTool::MuonClusterSegmentFinderTool (const std::string& type, const std::string& name, - const IInterface* parent) - : - AthAlgTool(type, name, parent), - m_slTrackFitter("Trk::GlobalChi2Fitter/MCTBSLFitter", this), - m_ambiTool("Trk::SimpleAmbiguityProcessorTool/MuonAmbiProcessor"), - m_trackToSegmentTool("Muon::MuonTrackToSegmentTool/MuonTrackToSegmentTool", this), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"), - m_trackCleaner("Muon::MuonTrackCleaner/MuonTrackCleaner", this), - m_trackSummary("Trk::TrackSummaryTool/MuidTrackSummaryTool", this) { - +MuonClusterSegmentFinderTool::MuonClusterSegmentFinderTool(const std::string& type, const std::string& name, + const IInterface* parent) + : AthAlgTool(type, name, parent) +{ declareInterface<IMuonClusterSegmentFinderTool>(this); - - declareProperty("SLFitter", m_slTrackFitter); - declareProperty("SegmentAmbiguityTool",m_ambiTool); - declareProperty("TrackToSegmentTool", m_trackToSegmentTool); - declareProperty("TrackCleaner", m_trackCleaner); - declareProperty("TrackSummaryTool", m_trackSummary); // declareProperty("IPConstraint", m_ipConstraint = true); - declareProperty("ClusterDistance", m_maxClustDist=5); - } - - StatusCode MuonClusterSegmentFinderTool::initialize() { - ATH_CHECK( m_slTrackFitter.retrieve() ); - ATH_CHECK( m_printer.retrieve() ); - ATH_CHECK( m_edmHelperSvc.retrieve() ); - ATH_CHECK( m_ambiTool.retrieve() ); - ATH_CHECK( m_trackToSegmentTool.retrieve() ); - ATH_CHECK( m_idHelperSvc.retrieve() ); - ATH_CHECK( m_trackCleaner.retrieve() ); - ATH_CHECK( m_trackSummary.retrieve() ); - ATH_MSG_DEBUG(" Max cut " << m_maxClustDist ); + declareProperty("ClusterDistance", m_maxClustDist = 5); +} + +StatusCode +MuonClusterSegmentFinderTool::initialize() +{ + ATH_CHECK(m_slTrackFitter.retrieve()); + ATH_CHECK(m_printer.retrieve()); + ATH_CHECK(m_edmHelperSvc.retrieve()); + ATH_CHECK(m_ambiTool.retrieve()); + ATH_CHECK(m_trackToSegmentTool.retrieve()); + ATH_CHECK(m_idHelperSvc.retrieve()); + ATH_CHECK(m_trackCleaner.retrieve()); + ATH_CHECK(m_trackSummary.retrieve()); + ATH_MSG_DEBUG(" Max cut " << m_maxClustDist); return StatusCode::SUCCESS; - } - - MuonClusterSegmentFinderTool::~MuonClusterSegmentFinderTool() { - - } - - void MuonClusterSegmentFinderTool::find(std::vector< const Muon::MuonClusterOnTrack* >& muonClusters, std::vector<Muon::MuonSegment*>& segments, Trk::SegmentCollection* segColl) const { - ATH_MSG_DEBUG("Entering MuonClusterSegmentFinderTool with " << muonClusters.size() << " clusters to be fit" ); - if(belowThreshold(muonClusters,4)) return; +} + +MuonClusterSegmentFinderTool::~MuonClusterSegmentFinderTool() {} + +void +MuonClusterSegmentFinderTool::find(std::vector<const Muon::MuonClusterOnTrack*>& muonClusters, + std::vector<Muon::MuonSegment*>& segments, Trk::SegmentCollection* segColl) const +{ + ATH_MSG_DEBUG("Entering MuonClusterSegmentFinderTool with " << muonClusters.size() << " clusters to be fit"); + if (belowThreshold(muonClusters, 4)) return; std::vector<Muon::MuonSegment*> etaSegs; - findPrecisionSegments(muonClusters,etaSegs); - if(etaSegs.size() == 0) - { - return; + findPrecisionSegments(muonClusters, etaSegs); + if (etaSegs.size() == 0) { + return; } - find3DSegments(muonClusters,etaSegs,segments,segColl); - - } + find3DSegments(muonClusters, etaSegs, segments, segColl); +} - StatusCode MuonClusterSegmentFinderTool::finalize() { +StatusCode +MuonClusterSegmentFinderTool::finalize() +{ return StatusCode::SUCCESS; - } - - //find the precision (eta) segments - void MuonClusterSegmentFinderTool::findPrecisionSegments(std::vector< const Muon::MuonClusterOnTrack* >& muonClusters, std::vector<Muon::MuonSegment*>& etaSegs) const { - - //clean the muon clusters -- select only the eta hits - bool selectPhiHits(false); - std::vector< const Muon::MuonClusterOnTrack* > clusters = cleanClusters(muonClusters,selectPhiHits); - ATH_MSG_VERBOSE("After hit cleaning, there are " << clusters.size() << " 2D clusters to be fit" ); - if(belowThreshold(clusters,4)){ - return; +} + +// find the precision (eta) segments +void +MuonClusterSegmentFinderTool::findPrecisionSegments(std::vector<const Muon::MuonClusterOnTrack*>& muonClusters, + std::vector<Muon::MuonSegment*>& etaSegs) const +{ + + // clean the muon clusters -- select only the eta hits + bool selectPhiHits(false); + std::vector<const Muon::MuonClusterOnTrack*> clusters = cleanClusters(muonClusters, selectPhiHits); + ATH_MSG_VERBOSE("After hit cleaning, there are " << clusters.size() << " 2D clusters to be fit"); + if (belowThreshold(clusters, 4)) { + return; } - + std::unique_ptr<TrackCollection> segTrkColl(new TrackCollection); - //std::vector< const Muon::MuonClusterOnTrack* > clusters = muonClusters; - //order the muon clusters by layer - std::vector< std::vector<const Muon::MuonClusterOnTrack*> > orderedClusters = orderByLayer(clusters); - - //create segment seeds - std::vector<std::pair<Amg::Vector3D,Amg::Vector3D> > seeds = segmentSeed(orderedClusters,false); - ATH_MSG_VERBOSE("Found " << seeds.size() << " 2D seeds to be fit" ); - - std::vector< const Muon::MuonClusterOnTrack* > rioVecPrevious; - //find all clusters near the seed and try to fit - for(unsigned int i=0; i<seeds.size(); ++i) { - std::vector< const Muon::MuonClusterOnTrack* > rioVec = getClustersOnSegment(orderedClusters,seeds[i],false); -// make consistent cut - if(belowThreshold(rioVec,4)) continue; - // logic to reduce combinatorics - if(rioVec.size() == rioVecPrevious.size()) { - bool sameContent = true; - for(unsigned int k=0; k<rioVec.size(); ++k) { - if(rioVec[k]!=rioVecPrevious[k]) sameContent = false; - } - if(sameContent) { - ATH_MSG_VERBOSE(" same clusters found for 2D seed " << i ); - continue; - } - } - ATH_MSG_VERBOSE(" new clusters for 2D seed " << i); - rioVecPrevious.clear(); - int nMM = 0; - for(unsigned int k=0; k<rioVec.size(); ++k) { - rioVecPrevious.push_back(rioVec[k]); - if(m_idHelperSvc->isMM(rioVec[k]->identify())) nMM++; - } - - //fit the segment!! - std::vector<const Trk::MeasurementBase*> vec2; - if(m_ipConstraint) vec2.reserve(rioVec.size()+3); - else vec2.reserve(rioVec.size()+2); - - // pseudo measurement for vtx - Trk::PseudoMeasurementOnTrack* pseudoVtx = nullptr; - if(m_ipConstraint) { - double errVtx = 100.; - Amg::MatrixX covVtx(1,1); - covVtx(0,0) = errVtx*errVtx; - Amg::Vector3D vtx(0.,0.,0.); - Trk::PerigeeSurface perVtx(vtx); - pseudoVtx = new Trk::PseudoMeasurementOnTrack(Trk::LocalParameters( Trk::DefinedParameter(0,Trk::locX) ), covVtx,perVtx); - vec2.push_back(pseudoVtx); - } - - //create a pseudo phi hit - double errPos = 0.1; - if(nMM>0) errPos = 1000.; - Amg::MatrixX cov(1,1); - cov(0,0) = errPos*errPos; - Trk::PseudoMeasurementOnTrack* pseudoSegPhi1 = new Trk::PseudoMeasurementOnTrack(Trk::LocalParameters( Trk::DefinedParameter(0,Trk::locY) ), - cov,rioVec.front()->associatedSurface()); - Trk::PseudoMeasurementOnTrack* pseudoSegPhi2 = new Trk::PseudoMeasurementOnTrack(Trk::LocalParameters( Trk::DefinedParameter(0,Trk::locY) ), - cov,rioVec.back()->associatedSurface()); - vec2.push_back(pseudoSegPhi1); - std::copy( rioVec.begin(), rioVec.end(), std::back_inserter(vec2) ); - vec2.push_back(pseudoSegPhi2); - ATH_MSG_VERBOSE("fitting 2D segment track with " << vec2.size() << " hits" ); - for(unsigned int k=0; k<rioVec.size(); ++k) { - ATH_MSG_VERBOSE( m_idHelperSvc->toString(rioVec[k]->identify()) << " " << rioVec[k]->globalPosition().perp() << ", " << rioVec[k]->globalPosition().z() - << " " << m_idHelperSvc->measuresPhi(rioVec[k]->identify()) ); - } - - Trk::TrackParameters* startpar = 0; - - const Trk::PlaneSurface* surf = dynamic_cast<const Trk::PlaneSurface*>(&rioVec.front()->associatedSurface()); - if( surf ){ - Amg::Vector3D posOnSurf = intersectPlane( *surf, seeds[i].first, seeds[i].second ); - Amg::Vector2D lpos; - surf->globalToLocal(posOnSurf,posOnSurf,lpos); - Trk::LocalDirection ldir; - surf->globalToLocalDirection(seeds[i].second,ldir); - Amg::Vector2D lp( lpos[Trk::locX], 0. ); - Trk::LocalDirection ld( ldir.angleXZ(), std::asin(1.) ); - Amg::Vector3D gd; - surf->localToGlobalDirection(ld,gd); - Amg::Vector3D gp; - surf->localToGlobal(lp,gp,gp); - - Amg::Vector3D perpos = gp + -10*gd.unit(); - if(perpos.dot(gd) < 0) gd = -1*gd; - startpar = new Trk::Perigee(perpos, gd, 0, perpos); - ATH_MSG_VERBOSE(" start parameter " << perpos << " pp " << startpar->position() << " gd " << gd.unit() << " pp " << startpar->momentum().unit() ); - } - // old method as fall back - if( !startpar ){ - double phi = seeds[i].second.phi(); - double theta = seeds[i].second.theta(); - double qoverp=0; - Trk::PerigeeSurface persurf(vec2.front()->globalPosition()); - startpar = new Trk::Perigee(0,0,phi,theta,qoverp,persurf); - } - Trk::Track* segtrack = fit(vec2,*startpar); - delete startpar; - if(segtrack) { - m_trackSummary->updateTrack(*segtrack); - segTrkColl->push_back( segtrack ); - - // Peter NEW calculate distance of segment to all muon clusters - if( msgLvl(MSG::VERBOSE) ) { - Amg::Vector3D pos = segtrack->perigeeParameters()->position(); - Amg::Vector3D dir = segtrack->perigeeParameters()->momentum(); - dir = dir / dir.mag(); - ATH_MSG_VERBOSE(" 2D eta segment found position " << pos << " direction " << dir << " hits " << vec2.size()); - for(unsigned int k=0; k<muonClusters.size(); ++k) { - const Trk::PlaneSurface* surf = dynamic_cast<const Trk::PlaneSurface*> (&(muonClusters[k]->associatedSurface())); - if(surf) { - Amg::Vector3D posOnSurf = intersectPlane( *surf, pos, dir ); - Amg::Vector2D lpos; - surf->globalToLocal(posOnSurf,posOnSurf,lpos); - double residual = muonClusters[k]->localParameters()[Trk::locX] - lpos[0]; - double error = Amg::error(muonClusters[k]->localCovariance(),Trk::locX); - double pull = residual / error; - ATH_MSG_VERBOSE(" lay " << k << " residual " << residual << " error " << error - << " pull " << pull << " " << m_idHelperSvc->toString(muonClusters[k]->identify()) ); - } - } + // std::vector< const Muon::MuonClusterOnTrack* > clusters = muonClusters; + // order the muon clusters by layer + std::vector<std::vector<const Muon::MuonClusterOnTrack*> > orderedClusters = orderByLayer(clusters); + + // create segment seeds + std::vector<std::pair<Amg::Vector3D, Amg::Vector3D> > seeds = segmentSeed(orderedClusters, false); + ATH_MSG_VERBOSE("Found " << seeds.size() << " 2D seeds to be fit"); + + std::vector<const Muon::MuonClusterOnTrack*> rioVecPrevious; + // find all clusters near the seed and try to fit + for (unsigned int i = 0; i < seeds.size(); ++i) { + std::vector<const Muon::MuonClusterOnTrack*> rioVec = getClustersOnSegment(orderedClusters, seeds[i], false); + // make consistent cut + if (belowThreshold(rioVec, 4)) continue; + // logic to reduce combinatorics + if (rioVec.size() == rioVecPrevious.size()) { + bool sameContent = true; + for (unsigned int k = 0; k < rioVec.size(); ++k) { + if (rioVec[k] != rioVecPrevious[k]) sameContent = false; + } + if (sameContent) { + ATH_MSG_VERBOSE(" same clusters found for 2D seed " << i); + continue; + } } + ATH_MSG_VERBOSE(" new clusters for 2D seed " << i); + rioVecPrevious.clear(); + int nMM = 0; + for (unsigned int k = 0; k < rioVec.size(); ++k) { + rioVecPrevious.push_back(rioVec[k]); + if (m_idHelperSvc->isMM(rioVec[k]->identify())) nMM++; + } + + // fit the segment!! + std::vector<const Trk::MeasurementBase*> vec2; + if (m_ipConstraint) + vec2.reserve(rioVec.size() + 3); + else + vec2.reserve(rioVec.size() + 2); + + // pseudo measurement for vtx + Trk::PseudoMeasurementOnTrack* pseudoVtx = nullptr; + if (m_ipConstraint) { + double errVtx = 100.; + Amg::MatrixX covVtx(1, 1); + covVtx(0, 0) = errVtx * errVtx; + Amg::Vector3D vtx(0., 0., 0.); + Trk::PerigeeSurface perVtx(vtx); + pseudoVtx = new Trk::PseudoMeasurementOnTrack(Trk::LocalParameters(Trk::DefinedParameter(0, Trk::locX)), + covVtx, perVtx); + vec2.push_back(pseudoVtx); + } + + // create a pseudo phi hit + double errPos = 0.1; + if (nMM > 0) errPos = 1000.; + Amg::MatrixX cov(1, 1); + cov(0, 0) = errPos * errPos; + Trk::PseudoMeasurementOnTrack* pseudoSegPhi1 = new Trk::PseudoMeasurementOnTrack( + Trk::LocalParameters(Trk::DefinedParameter(0, Trk::locY)), cov, rioVec.front()->associatedSurface()); + Trk::PseudoMeasurementOnTrack* pseudoSegPhi2 = new Trk::PseudoMeasurementOnTrack( + Trk::LocalParameters(Trk::DefinedParameter(0, Trk::locY)), cov, rioVec.back()->associatedSurface()); + vec2.push_back(pseudoSegPhi1); + std::copy(rioVec.begin(), rioVec.end(), std::back_inserter(vec2)); + vec2.push_back(pseudoSegPhi2); + ATH_MSG_VERBOSE("fitting 2D segment track with " << vec2.size() << " hits"); + for (unsigned int k = 0; k < rioVec.size(); ++k) { + ATH_MSG_VERBOSE(m_idHelperSvc->toString(rioVec[k]->identify()) + << " " << rioVec[k]->globalPosition().perp() << ", " << rioVec[k]->globalPosition().z() + << " " << m_idHelperSvc->measuresPhi(rioVec[k]->identify())); + } + + Trk::TrackParameters* startpar = 0; + + const Trk::PlaneSurface* surf = dynamic_cast<const Trk::PlaneSurface*>(&rioVec.front()->associatedSurface()); + if (surf) { + Amg::Vector3D posOnSurf = intersectPlane(*surf, seeds[i].first, seeds[i].second); + Amg::Vector2D lpos; + surf->globalToLocal(posOnSurf, posOnSurf, lpos); + Trk::LocalDirection ldir; + surf->globalToLocalDirection(seeds[i].second, ldir); + Amg::Vector2D lp(lpos[Trk::locX], 0.); + Trk::LocalDirection ld(ldir.angleXZ(), std::asin(1.)); + Amg::Vector3D gd; + surf->localToGlobalDirection(ld, gd); + Amg::Vector3D gp; + surf->localToGlobal(lp, gp, gp); + + Amg::Vector3D perpos = gp + -10 * gd.unit(); + if (perpos.dot(gd) < 0) gd = -1 * gd; + startpar = new Trk::Perigee(perpos, gd, 0, perpos); + ATH_MSG_VERBOSE(" start parameter " << perpos << " pp " << startpar->position() << " gd " << gd.unit() + << " pp " << startpar->momentum().unit()); + } + // old method as fall back + if (!startpar) { + double phi = seeds[i].second.phi(); + double theta = seeds[i].second.theta(); + double qoverp = 0; + Trk::PerigeeSurface persurf(vec2.front()->globalPosition()); + startpar = new Trk::Perigee(0, 0, phi, theta, qoverp, persurf); + } + Trk::Track* segtrack = fit(vec2, *startpar); + delete startpar; + if (segtrack) { + m_trackSummary->updateTrack(*segtrack); + segTrkColl->push_back(segtrack); + + // Peter NEW calculate distance of segment to all muon clusters + if (msgLvl(MSG::VERBOSE)) { + Amg::Vector3D pos = segtrack->perigeeParameters()->position(); + Amg::Vector3D dir = segtrack->perigeeParameters()->momentum(); + dir = dir / dir.mag(); + ATH_MSG_VERBOSE(" 2D eta segment found position " << pos << " direction " << dir << " hits " + << vec2.size()); + for (unsigned int k = 0; k < muonClusters.size(); ++k) { + const Trk::PlaneSurface* surf = + dynamic_cast<const Trk::PlaneSurface*>(&(muonClusters[k]->associatedSurface())); + if (surf) { + Amg::Vector3D posOnSurf = intersectPlane(*surf, pos, dir); + Amg::Vector2D lpos; + surf->globalToLocal(posOnSurf, posOnSurf, lpos); + double residual = muonClusters[k]->localParameters()[Trk::locX] - lpos[0]; + double error = Amg::error(muonClusters[k]->localCovariance(), Trk::locX); + double pull = residual / error; + ATH_MSG_VERBOSE(" lay " << k << " residual " << residual << " error " << error << " pull " + << pull << " " + << m_idHelperSvc->toString(muonClusters[k]->identify())); + } + } + } - } - else ATH_MSG_DEBUG( " 2D segment fit failed" ); - //delete the pseudo hits - delete pseudoSegPhi1; - delete pseudoSegPhi2; - if(m_ipConstraint) delete pseudoVtx; + } else + ATH_MSG_DEBUG(" 2D segment fit failed"); + // delete the pseudo hits + delete pseudoSegPhi1; + delete pseudoSegPhi2; + if (m_ipConstraint) delete pseudoVtx; } - if( msgLvl(MSG::DEBUG) ){ - ATH_MSG_DEBUG("Tracks before ambi solving "); - - for(TrackCollection::const_iterator it=segTrkColl->begin(); it!=segTrkColl->end(); ++it) { - ATH_MSG_DEBUG(m_printer->print(**it)); - const DataVector<const Trk::MeasurementBase>* measu = (*it)->measurementsOnTrack(); - if( measu ) ATH_MSG_DEBUG(m_printer->print( measu->stdcont() )); - } + if (msgLvl(MSG::DEBUG)) { + ATH_MSG_DEBUG("Tracks before ambi solving "); + + for (TrackCollection::const_iterator it = segTrkColl->begin(); it != segTrkColl->end(); ++it) { + ATH_MSG_DEBUG(m_printer->print(**it)); + const DataVector<const Trk::MeasurementBase>* measu = (*it)->measurementsOnTrack(); + if (measu) ATH_MSG_DEBUG(m_printer->print(measu->stdcont())); + } } - if( segTrkColl->empty() ){ - return; + if (segTrkColl->empty()) { + return; } TrackCollection* resolvedTracks = m_ambiTool->process(segTrkColl.get()); - ATH_MSG_DEBUG("Resolved track candidates: old size " << segTrkColl->size() << " new size " << resolvedTracks->size() ); - //store the resolved segments - - for(TrackCollection::const_iterator it=resolvedTracks->begin(); it!=resolvedTracks->end(); ++it) { - MuonSegment* seg = m_trackToSegmentTool->convert( **it ); - if( !seg ) { - ATH_MSG_VERBOSE("Segment conversion failed, no segment created. "); - } - else { - ATH_MSG_DEBUG(" adding " << m_printer->print(*seg) << std::endl << m_printer->print( seg->containedMeasurements() ) ); - etaSegs.push_back(seg); - } - } - - //memory cleanup - delete resolvedTracks; - - } - - void MuonClusterSegmentFinderTool::find3DSegments(std::vector< const Muon::MuonClusterOnTrack* >& muonClusters, - std::vector<Muon::MuonSegment*>& etaSegs, - std::vector<Muon::MuonSegment*>& segments, - Trk::SegmentCollection* segColl) const { - bool selectPhiHits(true); - std::vector< const Muon::MuonClusterOnTrack* > clusters = cleanClusters(muonClusters,selectPhiHits); - std::vector< const Muon::MuonClusterOnTrack* > etaClusters = cleanClusters(muonClusters,false); - ATH_MSG_DEBUG("After hit cleaning, there are " << clusters.size() << " 3D clusters to be fit" ); - if(belowThreshold(clusters,4)) { - ATH_MSG_DEBUG("Not enough phi hits present, cannot perform the fit!"); - - for (auto vsit : etaSegs) { - if (segColl) { - segColl->push_back(vsit); + ATH_MSG_DEBUG("Resolved track candidates: old size " << segTrkColl->size() << " new size " + << resolvedTracks->size()); + // store the resolved segments + + for (TrackCollection::const_iterator it = resolvedTracks->begin(); it != resolvedTracks->end(); ++it) { + MuonSegment* seg = m_trackToSegmentTool->convert(**it); + if (!seg) { + ATH_MSG_VERBOSE("Segment conversion failed, no segment created. "); } else { - segments.push_back(vsit); + ATH_MSG_DEBUG(" adding " << m_printer->print(*seg) << std::endl + << m_printer->print(seg->containedMeasurements())); + etaSegs.push_back(seg); } - } - - etaSegs.clear(); - return; + } + + // memory cleanup + delete resolvedTracks; +} + +void +MuonClusterSegmentFinderTool::find3DSegments(std::vector<const Muon::MuonClusterOnTrack*>& muonClusters, + std::vector<Muon::MuonSegment*>& etaSegs, + std::vector<Muon::MuonSegment*>& segments, + Trk::SegmentCollection* segColl) const +{ + bool selectPhiHits(true); + std::vector<const Muon::MuonClusterOnTrack*> clusters = cleanClusters(muonClusters, selectPhiHits); + std::vector<const Muon::MuonClusterOnTrack*> etaClusters = cleanClusters(muonClusters, false); + ATH_MSG_DEBUG("After hit cleaning, there are " << clusters.size() << " 3D clusters to be fit"); + if (belowThreshold(clusters, 4)) { + ATH_MSG_DEBUG("Not enough phi hits present, cannot perform the fit!"); + + for (auto vsit : etaSegs) { + if (segColl) { + segColl->push_back(vsit); + } else { + segments.push_back(vsit); + } + } + + etaSegs.clear(); + return; } TrackCollection* segTrkColl = new TrackCollection; - //order the clusters by layer - bool useWires(true); - std::vector< std::vector<const Muon::MuonClusterOnTrack*> > orderedClusters = orderByLayer(clusters,useWires); - std::vector< std::vector<const Muon::MuonClusterOnTrack*> > orderedEtaClusters = orderByLayer(etaClusters,false); - if(orderedClusters.size() == 0) { - ATH_MSG_DEBUG( "No phi wire hits found ... moving to pads" ); - useWires = false; - orderedClusters = orderByLayer(clusters,useWires); + // order the clusters by layer + bool useWires(true); + std::vector<std::vector<const Muon::MuonClusterOnTrack*> > orderedClusters = orderByLayer(clusters, useWires); + std::vector<std::vector<const Muon::MuonClusterOnTrack*> > orderedEtaClusters = orderByLayer(etaClusters, false); + if (orderedClusters.size() == 0) { + ATH_MSG_DEBUG("No phi wire hits found ... moving to pads"); + useWires = false; + orderedClusters = orderByLayer(clusters, useWires); } else { - ATH_MSG_DEBUG( "phi wire hits found" ); - } - //get the segment seeds - std::vector<std::pair<Amg::Vector3D,Amg::Vector3D> > seeds; - if(useWires) { - seeds = segmentSeed(orderedClusters,true); - ATH_MSG_DEBUG("Found " << seeds.size() << " 3D seeds from Wires for phi direction" ); - } - //loop on the seeds and combine with the eta segments - for(std::vector<Muon::MuonSegment*>::const_iterator sit=etaSegs.begin(); sit!=etaSegs.end(); ++sit) { - bool is3Dseg(false); - if(!useWires) seeds = segmentSeedFromPads(orderedClusters,*sit); - if(!useWires) ATH_MSG_DEBUG("Found " << seeds.size() << " 3D seeds from Pads for phi direction" ); - std::vector< const Muon::MuonClusterOnTrack* > phiHitsPrevious; - for(unsigned int i=0; i<seeds.size(); ++i) { - std::pair<Amg::Vector3D,Amg::Vector3D> seed3D; - Trk::TrackParameters* startpar = 0; - // calculate start parameters - const Trk::PlaneSurface& surf = (*sit)->associatedSurface(); - Amg::Vector3D posOnSeg = intersectPlane( surf, seeds[i].first, seeds[i].second ); - Amg::Vector2D lpos; - surf.globalToLocal(posOnSeg,posOnSeg,lpos); - Trk::LocalDirection ldir; - surf.globalToLocalDirection(seeds[i].second,ldir); - - Amg::Vector2D lp( (*sit)->localParameters()[Trk::locX], lpos[Trk::locY] ); - Trk::LocalDirection ld( (*sit)->localDirection().angleXZ(), ldir.angleYZ() ); - Amg::Vector3D gd; - surf.localToGlobalDirection(ld,gd); - Amg::Vector3D gp; - surf.localToGlobal(lp,gp,gp); - Amg::Vector3D perpos = gp + -10*(gd.unit()); - if(perpos.dot(gd) < 0) gd = -1*gd; - startpar = new Trk::Perigee(perpos, gd, 0, perpos); - seed3D = std::pair<Amg::Vector3D,Amg::Vector3D>(perpos,gd); - ATH_MSG_VERBOSE(" start parameter " << perpos << " pp " << startpar->position() << " gd " << gd.unit() << " pp " << startpar->momentum().unit() ); - - // old method as fall back - if( !startpar ){ - double phi = seeds[i].second.phi(); - double theta = (*sit)->globalDirection().theta(); - double qoverp=0; - Trk::PerigeeSurface persurf((*sit)->rioOnTrack(0)->globalPosition()); - startpar = new Trk::Perigee(0,0,phi,theta,qoverp,persurf); - seed3D = seeds[i]; - } - - std::vector< const Muon::MuonClusterOnTrack* > phiHits = getClustersOnSegment(orderedClusters,seed3D,true); - std::vector< const Muon::MuonClusterOnTrack* > etaHitsRedone = getClustersOnSegment(orderedEtaClusters,seed3D,true); - if(phiHits.size() < 2) { - delete startpar; - continue; - } - // logic to reduce combinatorics - if(phiHits.size() == phiHitsPrevious.size()) { - bool sameContent = true; - for(unsigned int k=0; k<phiHits.size(); ++k) { - if(phiHits[k]!=phiHitsPrevious[k]) sameContent = false; - } - if(sameContent) { - ATH_MSG_VERBOSE(" same clusters found for 3D seed " << i ); - delete startpar; - continue; - } - } - phiHitsPrevious.clear(); - for(unsigned int k=0; k<phiHits.size(); ++k) { - phiHitsPrevious.push_back(phiHits[k]); - } - ATH_MSG_VERBOSE(" new clusters for 3D seed " << i); - - //interleave the phi hits - std::vector<const Trk::MeasurementBase*> vec2; - std::vector<const Trk::RIO_OnTrack*> etaHits; - for(unsigned int irot=0;irot<(*sit)->numberOfContainedROTs();irot++){ - const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>((*sit)->rioOnTrack(irot)); - if( rot ) etaHits.push_back(rot); - } - unsigned int netas = etaHits.size(); - ATH_MSG_DEBUG("got "<<netas<<" eta hits and "<<etaHitsRedone.size()<<" redone eta hits"); - bool useEtaHitsRedone = false; - if(etaHitsRedone.size()>netas) { - ATH_MSG_VERBOSE(" Found additional eta hits " << etaHitsRedone.size() - netas); - useEtaHitsRedone = true; - } - if(useEtaHitsRedone) netas = etaHitsRedone.size(); - if(m_ipConstraint) vec2.reserve(phiHits.size()+netas+1); - else vec2.reserve(phiHits.size()+netas); - - // pseudo measurement for vtx - Trk::PseudoMeasurementOnTrack* pseudoVtx = nullptr; - if(m_ipConstraint) { - ATH_MSG_DEBUG("add pseudo vertex"); - double errVtx = 100.; - Amg::MatrixX covVtx(1,1); - covVtx(0,0) = errVtx*errVtx; - Amg::Vector3D vtx(0.,0.,0.); - Trk::PerigeeSurface perVtx(vtx); - pseudoVtx = new Trk::PseudoMeasurementOnTrack(Trk::LocalParameters( Trk::DefinedParameter(0,Trk::locX) ), covVtx,perVtx); - vec2.push_back(pseudoVtx); - } - unsigned int iEta(0),iPhi(0); - ATH_MSG_VERBOSE( "There are " << (*sit)->numberOfContainedROTs() << " & " << phiHits.size() << " eta and phi hits" ); - while(true) { - float phiZ(999999.),etaZ(999999.); - if(iPhi < phiHits.size()) phiZ = std::abs(phiHits[iPhi]->globalPosition().z()); - if(iEta < etaHits.size()) etaZ = std::abs(etaHits[iEta]->globalPosition().z()); - if( phiZ < etaZ ) { - vec2.push_back(phiHits[iPhi]); - iPhi++; - } - else { - if(!useEtaHitsRedone) { - vec2.push_back(etaHits[iEta]); - } else { - vec2.push_back(etaHitsRedone[iEta]); + ATH_MSG_DEBUG("phi wire hits found"); + } + // get the segment seeds + std::vector<std::pair<Amg::Vector3D, Amg::Vector3D> > seeds; + if (useWires) { + seeds = segmentSeed(orderedClusters, true); + ATH_MSG_DEBUG("Found " << seeds.size() << " 3D seeds from Wires for phi direction"); + } + // loop on the seeds and combine with the eta segments + for (std::vector<Muon::MuonSegment*>::const_iterator sit = etaSegs.begin(); sit != etaSegs.end(); ++sit) { + bool is3Dseg(false); + if (!useWires) seeds = segmentSeedFromPads(orderedClusters, *sit); + if (!useWires) ATH_MSG_DEBUG("Found " << seeds.size() << " 3D seeds from Pads for phi direction"); + std::vector<const Muon::MuonClusterOnTrack*> phiHitsPrevious; + for (unsigned int i = 0; i < seeds.size(); ++i) { + std::pair<Amg::Vector3D, Amg::Vector3D> seed3D; + Trk::TrackParameters* startpar = 0; + // calculate start parameters + const Trk::PlaneSurface& surf = (*sit)->associatedSurface(); + Amg::Vector3D posOnSeg = intersectPlane(surf, seeds[i].first, seeds[i].second); + Amg::Vector2D lpos; + surf.globalToLocal(posOnSeg, posOnSeg, lpos); + Trk::LocalDirection ldir; + surf.globalToLocalDirection(seeds[i].second, ldir); + + Amg::Vector2D lp((*sit)->localParameters()[Trk::locX], lpos[Trk::locY]); + Trk::LocalDirection ld((*sit)->localDirection().angleXZ(), ldir.angleYZ()); + Amg::Vector3D gd; + surf.localToGlobalDirection(ld, gd); + Amg::Vector3D gp; + surf.localToGlobal(lp, gp, gp); + Amg::Vector3D perpos = gp + -10 * (gd.unit()); + if (perpos.dot(gd) < 0) gd = -1 * gd; + startpar = new Trk::Perigee(perpos, gd, 0, perpos); + seed3D = std::pair<Amg::Vector3D, Amg::Vector3D>(perpos, gd); + ATH_MSG_VERBOSE(" start parameter " << perpos << " pp " << startpar->position() << " gd " << gd.unit() + << " pp " << startpar->momentum().unit()); + + // old method as fall back + if (!startpar) { + double phi = seeds[i].second.phi(); + double theta = (*sit)->globalDirection().theta(); + double qoverp = 0; + Trk::PerigeeSurface persurf((*sit)->rioOnTrack(0)->globalPosition()); + startpar = new Trk::Perigee(0, 0, phi, theta, qoverp, persurf); + seed3D = seeds[i]; + } + + std::vector<const Muon::MuonClusterOnTrack*> phiHits = getClustersOnSegment(orderedClusters, seed3D, true); + std::vector<const Muon::MuonClusterOnTrack*> etaHitsRedone = + getClustersOnSegment(orderedEtaClusters, seed3D, true); + if (phiHits.size() < 2) { + delete startpar; + continue; + } + // logic to reduce combinatorics + if (phiHits.size() == phiHitsPrevious.size()) { + bool sameContent = true; + for (unsigned int k = 0; k < phiHits.size(); ++k) { + if (phiHits[k] != phiHitsPrevious[k]) sameContent = false; + } + if (sameContent) { + ATH_MSG_VERBOSE(" same clusters found for 3D seed " << i); + delete startpar; + continue; + } + } + phiHitsPrevious.clear(); + for (unsigned int k = 0; k < phiHits.size(); ++k) { + phiHitsPrevious.push_back(phiHits[k]); } - iEta++; - } - if( iEta >= netas && iPhi >= phiHits.size() ) break; - } - - - ATH_MSG_DEBUG( "Fitting a 3D segment with " << phiHits.size() << " phi hits and " << vec2.size() << " total hits" ); - for(unsigned int k=0; k<vec2.size(); ++k) { - Identifier id = m_edmHelperSvc->getIdentifier(*vec2[k]); - ATH_MSG_VERBOSE( m_idHelperSvc->toString(id) << " " << vec2[k]->globalPosition().perp() << ", " << vec2[k]->globalPosition().z() ); - } - Trk::Track* segtrack = fit(vec2,*startpar); - delete startpar; - if(segtrack) { - m_trackSummary->updateTrack(*segtrack); - //store the track segment in track collection - segTrkColl->push_back( segtrack ); - is3Dseg = true; - - // Peter NEW calculate distance of segment to all muon clusters - if( msgLvl(MSG::VERBOSE) ) { - Amg::Vector3D pos = segtrack->perigeeParameters()->position(); - Amg::Vector3D dir = segtrack->perigeeParameters()->momentum(); - dir = dir / dir.mag(); - ATH_MSG_VERBOSE("3D eta-phi segment found position " << pos << " direction " << dir << " hits " << vec2.size()); - for(unsigned int k=0; k<muonClusters.size(); ++k) { - const Trk::PlaneSurface* surf = dynamic_cast<const Trk::PlaneSurface*> (&(muonClusters[k]->associatedSurface())); - if(surf) { - Amg::Vector3D posOnSurf = intersectPlane( *surf, pos, dir ); - Amg::Vector2D lpos; - surf->globalToLocal(posOnSurf,posOnSurf,lpos); - double residual = muonClusters[k]->localParameters()[Trk::locX] - lpos[0]; - double error = Amg::error(muonClusters[k]->localCovariance(),Trk::locX); - double pull = residual / error; - ATH_MSG_VERBOSE(" lay " << k << " residual " << residual << " error " << error - << " pull " << pull << " " << m_idHelperSvc->toString(muonClusters[k]->identify()) ); - } + ATH_MSG_VERBOSE(" new clusters for 3D seed " << i); + + // interleave the phi hits + std::vector<const Trk::MeasurementBase*> vec2; + std::vector<const Trk::RIO_OnTrack*> etaHits; + for (unsigned int irot = 0; irot < (*sit)->numberOfContainedROTs(); irot++) { + const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>((*sit)->rioOnTrack(irot)); + if (rot) etaHits.push_back(rot); } - } - - } else { - ATH_MSG_DEBUG( "3D segment fit failed" ); - } - if(m_ipConstraint) delete pseudoVtx; - }//end loop on phi seeds - if( !is3Dseg ){ - if(!segColl) segments.push_back( (*sit)->clone() ); - else segColl->push_back( (*sit)->clone() ); - } - }//end loop on precision plane segments + unsigned int netas = etaHits.size(); + ATH_MSG_DEBUG("got " << netas << " eta hits and " << etaHitsRedone.size() << " redone eta hits"); + bool useEtaHitsRedone = false; + if (etaHitsRedone.size() > netas) { + ATH_MSG_VERBOSE(" Found additional eta hits " << etaHitsRedone.size() - netas); + useEtaHitsRedone = true; + } + if (useEtaHitsRedone) netas = etaHitsRedone.size(); + if (m_ipConstraint) + vec2.reserve(phiHits.size() + netas + 1); + else + vec2.reserve(phiHits.size() + netas); + + // pseudo measurement for vtx + Trk::PseudoMeasurementOnTrack* pseudoVtx = nullptr; + if (m_ipConstraint) { + ATH_MSG_DEBUG("add pseudo vertex"); + double errVtx = 100.; + Amg::MatrixX covVtx(1, 1); + covVtx(0, 0) = errVtx * errVtx; + Amg::Vector3D vtx(0., 0., 0.); + Trk::PerigeeSurface perVtx(vtx); + pseudoVtx = new Trk::PseudoMeasurementOnTrack(Trk::LocalParameters(Trk::DefinedParameter(0, Trk::locX)), + covVtx, perVtx); + vec2.push_back(pseudoVtx); + } + unsigned int iEta(0), iPhi(0); + ATH_MSG_VERBOSE("There are " << (*sit)->numberOfContainedROTs() << " & " << phiHits.size() + << " eta and phi hits"); + while (true) { + float phiZ(999999.), etaZ(999999.); + if (iPhi < phiHits.size()) phiZ = std::abs(phiHits[iPhi]->globalPosition().z()); + if (iEta < etaHits.size()) etaZ = std::abs(etaHits[iEta]->globalPosition().z()); + if (phiZ < etaZ) { + vec2.push_back(phiHits[iPhi]); + iPhi++; + } else { + if (!useEtaHitsRedone) { + vec2.push_back(etaHits[iEta]); + } else { + vec2.push_back(etaHitsRedone[iEta]); + } + iEta++; + } + if (iEta >= netas && iPhi >= phiHits.size()) break; + } + + + ATH_MSG_DEBUG("Fitting a 3D segment with " << phiHits.size() << " phi hits and " << vec2.size() + << " total hits"); + for (unsigned int k = 0; k < vec2.size(); ++k) { + Identifier id = m_edmHelperSvc->getIdentifier(*vec2[k]); + ATH_MSG_VERBOSE(m_idHelperSvc->toString(id) + << " " << vec2[k]->globalPosition().perp() << ", " << vec2[k]->globalPosition().z()); + } + Trk::Track* segtrack = fit(vec2, *startpar); + delete startpar; + if (segtrack) { + m_trackSummary->updateTrack(*segtrack); + // store the track segment in track collection + segTrkColl->push_back(segtrack); + is3Dseg = true; + + // Peter NEW calculate distance of segment to all muon clusters + if (msgLvl(MSG::VERBOSE)) { + Amg::Vector3D pos = segtrack->perigeeParameters()->position(); + Amg::Vector3D dir = segtrack->perigeeParameters()->momentum(); + dir = dir / dir.mag(); + ATH_MSG_VERBOSE("3D eta-phi segment found position " << pos << " direction " << dir << " hits " + << vec2.size()); + for (unsigned int k = 0; k < muonClusters.size(); ++k) { + const Trk::PlaneSurface* surf = + dynamic_cast<const Trk::PlaneSurface*>(&(muonClusters[k]->associatedSurface())); + if (surf) { + Amg::Vector3D posOnSurf = intersectPlane(*surf, pos, dir); + Amg::Vector2D lpos; + surf->globalToLocal(posOnSurf, posOnSurf, lpos); + double residual = muonClusters[k]->localParameters()[Trk::locX] - lpos[0]; + double error = Amg::error(muonClusters[k]->localCovariance(), Trk::locX); + double pull = residual / error; + ATH_MSG_VERBOSE(" lay " << k << " residual " << residual << " error " << error << " pull " + << pull << " " + << m_idHelperSvc->toString(muonClusters[k]->identify())); + } + } + } + + } else { + ATH_MSG_DEBUG("3D segment fit failed"); + } + if (m_ipConstraint) delete pseudoVtx; + } // end loop on phi seeds + if (!is3Dseg) { + if (!segColl) + segments.push_back((*sit)->clone()); + else + segColl->push_back((*sit)->clone()); + } + } // end loop on precision plane segments TrackCollection* resolvedTracks = m_ambiTool->process(segTrkColl); - ATH_MSG_DEBUG("Resolved track candidates: old size " << segTrkColl->size() << " new size " << resolvedTracks->size() ); - //store the resolved segments - for(TrackCollection::const_iterator it=resolvedTracks->begin(); it!=resolvedTracks->end(); ++it) { - MuonSegment* seg = m_trackToSegmentTool->convert( **it ); - if( !seg ) { - ATH_MSG_VERBOSE("Segment conversion failed, no segment created. "); - } - else { - if(!segColl) segments.push_back(seg); - else segColl->push_back(seg); - } - } - - //memory cleanup + ATH_MSG_DEBUG("Resolved track candidates: old size " << segTrkColl->size() << " new size " + << resolvedTracks->size()); + // store the resolved segments + for (TrackCollection::const_iterator it = resolvedTracks->begin(); it != resolvedTracks->end(); ++it) { + MuonSegment* seg = m_trackToSegmentTool->convert(**it); + if (!seg) { + ATH_MSG_VERBOSE("Segment conversion failed, no segment created. "); + } else { + if (!segColl) + segments.push_back(seg); + else + segColl->push_back(seg); + } + } + + // memory cleanup delete segTrkColl; delete resolvedTracks; - for(std::vector<Muon::MuonSegment*>::iterator sit=etaSegs.begin(); sit!=etaSegs.end(); ++sit) { - delete *sit; + for (std::vector<Muon::MuonSegment*>::iterator sit = etaSegs.begin(); sit != etaSegs.end(); ++sit) { + delete *sit; } - - } - - - std::vector< const Muon::MuonClusterOnTrack* > MuonClusterSegmentFinderTool::cleanClusters(std::vector< const Muon::MuonClusterOnTrack* >& muonClusters, bool selectPhiHits) const { - std::vector< const Muon::MuonClusterOnTrack* > clusters; - //remove the phi hits - for(std::vector< const Muon::MuonClusterOnTrack* >::const_iterator cit=muonClusters.begin(); cit!=muonClusters.end(); ++cit) { - if(!(*cit)) continue; - bool measPhi = m_idHelperSvc->measuresPhi( (*cit)->identify()); - if( measPhi != selectPhiHits ) continue; - clusters.push_back(*cit); +} + + +std::vector<const Muon::MuonClusterOnTrack*> +MuonClusterSegmentFinderTool::cleanClusters(std::vector<const Muon::MuonClusterOnTrack*>& muonClusters, + bool selectPhiHits) const +{ + std::vector<const Muon::MuonClusterOnTrack*> clusters; + // remove the phi hits + for (std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit = muonClusters.begin(); + cit != muonClusters.end(); ++cit) + { + if (!(*cit)) continue; + bool measPhi = m_idHelperSvc->measuresPhi((*cit)->identify()); + if (measPhi != selectPhiHits) continue; + clusters.push_back(*cit); } return clusters; - } - - std::vector< std::vector<const Muon::MuonClusterOnTrack*> > MuonClusterSegmentFinderTool::orderByLayer(std::vector< const Muon::MuonClusterOnTrack* >& clusters, bool useWires) const{ - //loop on the input clusters and order by layer - std::vector< std::vector<const Muon::MuonClusterOnTrack*> > orderedClusters; - unsigned int nOrdered(0); - double minz(0.),maxz(9999999.); - while(nOrdered < clusters.size()) { - std::vector< const Muon::MuonClusterOnTrack* > tmpclusters; - for(std::vector< const Muon::MuonClusterOnTrack* >::const_iterator cit = clusters.begin(); cit!=clusters.end(); ++cit) { - if( useWires && m_idHelperSvc->issTgc((*cit)->identify()) && m_idHelperSvc->stgcIdHelper().channelType( (*cit)->identify() ) == 0 ) { - if(minz < 1) nOrdered++; - continue; - } - else if( !useWires && m_idHelperSvc->issTgc((*cit)->identify()) && m_idHelperSvc->stgcIdHelper().channelType( (*cit)->identify() ) == 2 ) { - if(minz < 1) nOrdered++; - continue; - } - if(std::abs((*cit)->prepRawData()->globalPosition().z()) <= minz) continue; - if(std::abs((*cit)->prepRawData()->globalPosition().z()) < maxz) { - maxz = std::abs((*cit)->prepRawData()->globalPosition().z()); - tmpclusters.clear(); - tmpclusters.push_back(*cit); - } - else if ( std::abs(std::abs((*cit)->prepRawData()->globalPosition().z()) - maxz) < 0.1) { - tmpclusters.push_back(*cit); - } - } - if(tmpclusters.size() == 0) break; - orderedClusters.push_back(tmpclusters); - nOrdered += tmpclusters.size(); - minz = maxz+0.1; - maxz = 9999999.; +} + +std::vector<std::vector<const Muon::MuonClusterOnTrack*> > +MuonClusterSegmentFinderTool::orderByLayer(std::vector<const Muon::MuonClusterOnTrack*>& clusters, bool useWires) const +{ + // loop on the input clusters and order by layer + std::vector<std::vector<const Muon::MuonClusterOnTrack*> > orderedClusters; + unsigned int nOrdered(0); + double minz(0.), maxz(9999999.); + while (nOrdered < clusters.size()) { + std::vector<const Muon::MuonClusterOnTrack*> tmpclusters; + for (std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit = clusters.begin(); cit != clusters.end(); + ++cit) { + if (useWires && m_idHelperSvc->issTgc((*cit)->identify()) + && m_idHelperSvc->stgcIdHelper().channelType((*cit)->identify()) == 0) + { + if (minz < 1) nOrdered++; + continue; + } else if (!useWires && m_idHelperSvc->issTgc((*cit)->identify()) + && m_idHelperSvc->stgcIdHelper().channelType((*cit)->identify()) == 2) + { + if (minz < 1) nOrdered++; + continue; + } + if (std::abs((*cit)->prepRawData()->globalPosition().z()) <= minz) continue; + if (std::abs((*cit)->prepRawData()->globalPosition().z()) < maxz) { + maxz = std::abs((*cit)->prepRawData()->globalPosition().z()); + tmpclusters.clear(); + tmpclusters.push_back(*cit); + } else if (std::abs(std::abs((*cit)->prepRawData()->globalPosition().z()) - maxz) < 0.1) { + tmpclusters.push_back(*cit); + } + } + if (tmpclusters.size() == 0) break; + orderedClusters.push_back(tmpclusters); + nOrdered += tmpclusters.size(); + minz = maxz + 0.1; + maxz = 9999999.; } return orderedClusters; - } +} - std::vector<std::pair<Amg::Vector3D,Amg::Vector3D> > - MuonClusterSegmentFinderTool::segmentSeed( std::vector< std::vector<const Muon::MuonClusterOnTrack*> >& orderedClusters, bool usePhi ) const { +std::vector<std::pair<Amg::Vector3D, Amg::Vector3D> > +MuonClusterSegmentFinderTool::segmentSeed(std::vector<std::vector<const Muon::MuonClusterOnTrack*> >& orderedClusters, + bool usePhi) const +{ - std::vector<std::pair<Amg::Vector3D,Amg::Vector3D> > seeds; - if(orderedClusters.size() < 2) return seeds; + std::vector<std::pair<Amg::Vector3D, Amg::Vector3D> > seeds; + if (orderedClusters.size() < 2) return seeds; - //calculate the straight line between the two furthest points + // calculate the straight line between the two furthest points int seedlayers1 = 0; - for( unsigned int i = 0; (i<orderedClusters.size() && seedlayers1 < 2); ++i ){ - - bool usedLayer1 = false; - for(std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit=orderedClusters[i].begin(); cit!=orderedClusters[i].end(); ++cit) { - - if( usePhi != m_idHelperSvc->measuresPhi((*cit)->identify() ) ) continue; - usedLayer1 = true; - const Amg::Vector3D& gp1 = (*cit)->prepRawData()->globalPosition(); - - int seedlayers2 = 0; - for(unsigned int k=orderedClusters.size()-1; (k>i && seedlayers2 < 2) ; --k) { - - bool usedLayer2 = false; - for(std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit2=orderedClusters[k].begin(); cit2!=orderedClusters[k].end(); ++cit2) { - - if( usePhi != m_idHelperSvc->measuresPhi((*cit2)->identify() ) ) continue; - - usedLayer2 = true; - const Amg::Vector3D& gp2 = (*cit2)->prepRawData()->globalPosition(); - double dx = (gp2.x()-gp1.x()); - double dy = (gp2.y()-gp1.y()); - double dz = (gp2.z()-gp1.z()); - if(std::abs(dz) < 200.) { - dx = (gp2.x()+gp1.x())/2.; - dy = (gp2.y()+gp1.y())/2.; - dz = (gp2.z()+gp1.z())/2.; - } - Amg::Vector3D segdir(dx, dy, dz); - seeds.push_back(std::pair<Amg::Vector3D,Amg::Vector3D>(gp1,segdir)); - } - if( usedLayer2 ) ++seedlayers2; - - } - } - if( usedLayer1 ) ++seedlayers1; - } - if(usePhi) return seeds; - - //use the innermost and outermost MM hits to form the seeds - unsigned int innerMM(999),outerMM(999); - for( unsigned int i = 0; i<orderedClusters.size(); ++i ) { - if(m_idHelperSvc->isMM(orderedClusters[i].front()->identify())) { - innerMM = i; - break; - } - } - for( unsigned int i=orderedClusters.size()-1; i > innerMM; --i ) { - if(m_idHelperSvc->isMM(orderedClusters[i].front()->identify())) { - outerMM = i; - break; - } - } - if(innerMM == 999 || outerMM == 999) return seeds; - //create the seeds - for(std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit=orderedClusters[innerMM].begin(); cit!=orderedClusters[innerMM].end(); ++cit) { - const Amg::Vector3D& gp1 = (*cit)->prepRawData()->globalPosition(); - for(std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit2=orderedClusters[outerMM].begin(); cit2!=orderedClusters[outerMM].end(); ++cit2) { - const Amg::Vector3D& gp2 = (*cit2)->prepRawData()->globalPosition(); - double dx = (gp2.x()-gp1.x()); - double dy = (gp2.y()-gp1.y()); - double dz = (gp2.z()-gp1.z()); - if(std::abs(dz) < 200.) { - dx = (gp2.x()+gp1.x())/2.; - dy = (gp2.y()+gp1.y())/2.; - dz = (gp2.z()+gp1.z())/2.; - } - Amg::Vector3D segdir(dx, dy, dz); - seeds.push_back(std::pair<Amg::Vector3D,Amg::Vector3D>(gp1,segdir)); - } + for (unsigned int i = 0; (i < orderedClusters.size() && seedlayers1 < 2); ++i) { + + bool usedLayer1 = false; + for (std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit = orderedClusters[i].begin(); + cit != orderedClusters[i].end(); ++cit) + { + + if (usePhi != m_idHelperSvc->measuresPhi((*cit)->identify())) continue; + usedLayer1 = true; + const Amg::Vector3D& gp1 = (*cit)->prepRawData()->globalPosition(); + + int seedlayers2 = 0; + for (unsigned int k = orderedClusters.size() - 1; (k > i && seedlayers2 < 2); --k) { + + bool usedLayer2 = false; + for (std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit2 = orderedClusters[k].begin(); + cit2 != orderedClusters[k].end(); ++cit2) + { + + if (usePhi != m_idHelperSvc->measuresPhi((*cit2)->identify())) continue; + + usedLayer2 = true; + const Amg::Vector3D& gp2 = (*cit2)->prepRawData()->globalPosition(); + double dx = (gp2.x() - gp1.x()); + double dy = (gp2.y() - gp1.y()); + double dz = (gp2.z() - gp1.z()); + if (std::abs(dz) < 200.) { + dx = (gp2.x() + gp1.x()) / 2.; + dy = (gp2.y() + gp1.y()) / 2.; + dz = (gp2.z() + gp1.z()) / 2.; + } + Amg::Vector3D segdir(dx, dy, dz); + seeds.push_back(std::pair<Amg::Vector3D, Amg::Vector3D>(gp1, segdir)); + } + if (usedLayer2) ++seedlayers2; + } + } + if (usedLayer1) ++seedlayers1; + } + if (usePhi) return seeds; + + // use the innermost and outermost MM hits to form the seeds + unsigned int innerMM(999), outerMM(999); + for (unsigned int i = 0; i < orderedClusters.size(); ++i) { + if (m_idHelperSvc->isMM(orderedClusters[i].front()->identify())) { + innerMM = i; + break; + } + } + for (unsigned int i = orderedClusters.size() - 1; i > innerMM; --i) { + if (m_idHelperSvc->isMM(orderedClusters[i].front()->identify())) { + outerMM = i; + break; + } + } + if (innerMM == 999 || outerMM == 999) return seeds; + // create the seeds + for (std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit = orderedClusters[innerMM].begin(); + cit != orderedClusters[innerMM].end(); ++cit) + { + const Amg::Vector3D& gp1 = (*cit)->prepRawData()->globalPosition(); + for (std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit2 = orderedClusters[outerMM].begin(); + cit2 != orderedClusters[outerMM].end(); ++cit2) + { + const Amg::Vector3D& gp2 = (*cit2)->prepRawData()->globalPosition(); + double dx = (gp2.x() - gp1.x()); + double dy = (gp2.y() - gp1.y()); + double dz = (gp2.z() - gp1.z()); + if (std::abs(dz) < 200.) { + dx = (gp2.x() + gp1.x()) / 2.; + dy = (gp2.y() + gp1.y()) / 2.; + dz = (gp2.z() + gp1.z()) / 2.; + } + Amg::Vector3D segdir(dx, dy, dz); + seeds.push_back(std::pair<Amg::Vector3D, Amg::Vector3D>(gp1, segdir)); + } } return seeds; - } - - std::vector< const Muon::MuonClusterOnTrack* > MuonClusterSegmentFinderTool::getClustersOnSegment(std::vector< std::vector<const Muon::MuonClusterOnTrack*> >& clusters, - std::pair<Amg::Vector3D,Amg::Vector3D>& seed, bool tight) const { - ATH_MSG_VERBOSE(" getClustersOnSegment: layers " << clusters.size() ); - std::vector< const Muon::MuonClusterOnTrack* > rios; - int layer = 0; - for(std::vector<std::vector<const Muon::MuonClusterOnTrack*> >::const_iterator cvecIt=clusters.begin(); cvecIt!=clusters.end(); ++cvecIt) { - const Muon::MuonClusterOnTrack* rio = 0; - double bestDist(9999.); - - for(std::vector< const Muon::MuonClusterOnTrack* >::const_iterator cit=(*cvecIt).begin(); cit!=(*cvecIt).end(); ++cit) { - double dist = clusterDistanceToSeed( *cit, seed); - double error = Amg::error((*cit)->localCovariance(),Trk::locX); - if (!tight && m_idHelperSvc->isMM((*cit)->identify())) error += 15.; - - ATH_MSG_VERBOSE(" lay " << layer << " dist " << dist << " pull " << dist/error - << " cut " << m_maxClustDist << " " << m_idHelperSvc->toString((*cit)->identify()) ); - if( std::abs(dist/error) < m_maxClustDist) { - if(std::abs(dist) < bestDist) { - bestDist = std::abs(dist); - rio = (*cit); - } - } - } - if(rio) { - ATH_MSG_VERBOSE(" adding " << bestDist << " " << m_idHelperSvc->toString(rio->identify()) ); - rios.push_back( rio ); - } - ++layer; - } - ATH_MSG_VERBOSE(" getClustersOnSegment: returning hits " << rios.size() ); - return rios; - } - - - Amg::Vector3D MuonClusterSegmentFinderTool::intersectPlane( const Trk::PlaneSurface& surf, const Amg::Vector3D& pos, - const Amg::Vector3D& dir ) const { +} + +std::vector<const Muon::MuonClusterOnTrack*> +MuonClusterSegmentFinderTool::getClustersOnSegment(std::vector<std::vector<const Muon::MuonClusterOnTrack*> >& clusters, + std::pair<Amg::Vector3D, Amg::Vector3D>& seed, bool tight) const +{ + ATH_MSG_VERBOSE(" getClustersOnSegment: layers " << clusters.size()); + std::vector<const Muon::MuonClusterOnTrack*> rios; + int layer = 0; + for (std::vector<std::vector<const Muon::MuonClusterOnTrack*> >::const_iterator cvecIt = clusters.begin(); + cvecIt != clusters.end(); ++cvecIt) + { + const Muon::MuonClusterOnTrack* rio = 0; + double bestDist(9999.); + + for (std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit = (*cvecIt).begin(); + cit != (*cvecIt).end(); ++cit) + { + double dist = clusterDistanceToSeed(*cit, seed); + double error = Amg::error((*cit)->localCovariance(), Trk::locX); + if (!tight && m_idHelperSvc->isMM((*cit)->identify())) error += 15.; + + ATH_MSG_VERBOSE(" lay " << layer << " dist " << dist << " pull " << dist / error << " cut " + << m_maxClustDist << " " << m_idHelperSvc->toString((*cit)->identify())); + if (std::abs(dist / error) < m_maxClustDist) { + if (std::abs(dist) < bestDist) { + bestDist = std::abs(dist); + rio = (*cit); + } + } + } + if (rio) { + ATH_MSG_VERBOSE(" adding " << bestDist << " " << m_idHelperSvc->toString(rio->identify())); + rios.push_back(rio); + } + ++layer; + } + ATH_MSG_VERBOSE(" getClustersOnSegment: returning hits " << rios.size()); + return rios; +} + + +Amg::Vector3D +MuonClusterSegmentFinderTool::intersectPlane(const Trk::PlaneSurface& surf, const Amg::Vector3D& pos, + const Amg::Vector3D& dir) const +{ const Amg::Vector3D& planepostion = surf.center(); - const Amg::Vector3D& planenormal = surf.normal(); - double denom = dir.dot(planenormal); - double u = planenormal.dot(planepostion - pos)/denom; + const Amg::Vector3D& planenormal = surf.normal(); + double denom = dir.dot(planenormal); + double u = planenormal.dot(planepostion - pos) / denom; return pos + u * dir; - } +} - double MuonClusterSegmentFinderTool::clusterDistanceToSeed(const Muon::MuonClusterOnTrack* clus, std::pair<Amg::Vector3D,Amg::Vector3D>& seed) const { +double +MuonClusterSegmentFinderTool::clusterDistanceToSeed(const Muon::MuonClusterOnTrack* clus, + std::pair<Amg::Vector3D, Amg::Vector3D>& seed) const +{ const Trk::PlaneSurface* surf = dynamic_cast<const Trk::PlaneSurface*>(&clus->associatedSurface()); - double dist(-99999); - if( !surf ) { - ATH_MSG_DEBUG(" clusterDistanceToSeed: no Trk::PlaneSurface found on cluster "); - return dist; + double dist(-99999); + if (!surf) { + ATH_MSG_DEBUG(" clusterDistanceToSeed: no Trk::PlaneSurface found on cluster "); + return dist; } - Amg::Vector3D piOnPlane = intersectPlane(*surf,seed.first,seed.second); + Amg::Vector3D piOnPlane = intersectPlane(*surf, seed.first, seed.second); // transform to local plane coordiantes Amg::Vector2D lpos; - surf->globalToLocal(piOnPlane,piOnPlane,lpos); - //check if the MuonCluster is pad hit - if(m_idHelperSvc->issTgc( clus->identify() ) && m_idHelperSvc->stgcIdHelper().channelType( clus->identify() ) == 0 ) { - const sTgcPrepData* prd = dynamic_cast<const sTgcPrepData*>(clus->prepRawData()); - if (!prd) { - ATH_MSG_DEBUG(" clusterDistanceToSeed: no sTgcPrepData found "); - return dist; - } - const MuonGM::MuonPadDesign* design = prd->detectorElement()->getPadDesign( clus->identify() ); - if(!design) { - ATH_MSG_WARNING( "MuonPadDesign not found for " << m_idHelperSvc->toString( clus->identify() ) ); - return dist; - } - //check the alignment in locX - double chWidth1 = 0.5*design->channelWidth(prd->localPosition(),false); - double chWidth2 = 0.5*design->channelWidth(prd->localPosition(),true); - chWidth1 = std::abs(chWidth1); - chWidth2 = std::abs(chWidth2); - Amg::Vector2D lp1(prd->localPosition().x()-chWidth2,prd->localPosition().y()-chWidth1); - Amg::Vector2D lp2(prd->localPosition().x()+chWidth2,prd->localPosition().y()+chWidth1); - ATH_MSG_DEBUG(" chWidth2 locX " << chWidth2 << " chWidth1 locY" << chWidth1 << " design->sPadWidth " << design->sPadWidth << " design->lPadWidth " << design->lPadWidth ); - ATH_MSG_DEBUG(" cluster locX " << prd->localPosition().x() << " lpos.x() " << lpos.x() << " cluster locY " << prd->localPosition().y() << " lpos.y() " << lpos.y()); - if(lp1.y() < lpos.y() && lp2.y() > lpos.y() && lp1.x() < lpos.x() && lp2.x() > lpos.x() ) { - dist = 0; - } - } - else { - dist = clus->localParameters()[Trk::locX] - lpos[Trk::locX]; - ATH_MSG_DEBUG(" clus [locX] " << clus->localParameters()[Trk::locX] << " clus [LocY] " << clus->localParameters()[Trk::locY] << " lpos[locX] " << lpos[Trk::locX] << " lpos[locY] " << lpos[Trk::locY] ); + surf->globalToLocal(piOnPlane, piOnPlane, lpos); + // check if the MuonCluster is pad hit + if (m_idHelperSvc->issTgc(clus->identify()) && m_idHelperSvc->stgcIdHelper().channelType(clus->identify()) == 0) { + const sTgcPrepData* prd = dynamic_cast<const sTgcPrepData*>(clus->prepRawData()); + if (!prd) { + ATH_MSG_DEBUG(" clusterDistanceToSeed: no sTgcPrepData found "); + return dist; + } + const MuonGM::MuonPadDesign* design = prd->detectorElement()->getPadDesign(clus->identify()); + if (!design) { + ATH_MSG_WARNING("MuonPadDesign not found for " << m_idHelperSvc->toString(clus->identify())); + return dist; + } + // check the alignment in locX + double chWidth1 = 0.5 * design->channelWidth(prd->localPosition(), false); + double chWidth2 = 0.5 * design->channelWidth(prd->localPosition(), true); + chWidth1 = std::abs(chWidth1); + chWidth2 = std::abs(chWidth2); + Amg::Vector2D lp1(prd->localPosition().x() - chWidth2, prd->localPosition().y() - chWidth1); + Amg::Vector2D lp2(prd->localPosition().x() + chWidth2, prd->localPosition().y() + chWidth1); + ATH_MSG_DEBUG(" chWidth2 locX " << chWidth2 << " chWidth1 locY" << chWidth1 << " design->sPadWidth " + << design->sPadWidth << " design->lPadWidth " << design->lPadWidth); + ATH_MSG_DEBUG(" cluster locX " << prd->localPosition().x() << " lpos.x() " << lpos.x() << " cluster locY " + << prd->localPosition().y() << " lpos.y() " << lpos.y()); + if (lp1.y() < lpos.y() && lp2.y() > lpos.y() && lp1.x() < lpos.x() && lp2.x() > lpos.x()) { + dist = 0; + } + } else { + dist = clus->localParameters()[Trk::locX] - lpos[Trk::locX]; + ATH_MSG_DEBUG(" clus [locX] " << clus->localParameters()[Trk::locX] << " clus [LocY] " + << clus->localParameters()[Trk::locY] << " lpos[locX] " << lpos[Trk::locX] + << " lpos[locY] " << lpos[Trk::locY]); } return dist; - } - - Trk::Track* MuonClusterSegmentFinderTool::fit( const std::vector<const Trk::MeasurementBase*>& vec2, const Trk::TrackParameters& startpar ) const { - Trk::Track* segtrack = m_slTrackFitter->fit(vec2,startpar,false,Trk::nonInteracting); - if(segtrack) { - ATH_MSG_VERBOSE( "segment fit succeeded"); - std::unique_ptr<Trk::Track> cleanedTrack = m_trackCleaner->clean(*segtrack); - if( cleanedTrack && !(cleanedTrack->perigeeParameters() == segtrack->perigeeParameters()) ){ - delete segtrack; - //using release until the entire code can be migrated to use smart pointers - segtrack = cleanedTrack.release(); - } - if( !m_edmHelperSvc->goodTrack(*segtrack,10) ) { - if(segtrack->fitQuality()) { - ATH_MSG_DEBUG( "segment fit with chi^2/nDoF = " << segtrack->fitQuality()->chiSquared() << "/" << segtrack->fitQuality()->numberDoF() ); - } - delete segtrack; - segtrack = 0; - } else { - m_trackSummary->updateTrack(*segtrack); - } +} + +Trk::Track* +MuonClusterSegmentFinderTool::fit(const std::vector<const Trk::MeasurementBase*>& vec2, + const Trk::TrackParameters& startpar) const +{ + Trk::Track* segtrack = m_slTrackFitter->fit(vec2, startpar, false, Trk::nonInteracting); + if (segtrack) { + ATH_MSG_VERBOSE("segment fit succeeded"); + std::unique_ptr<Trk::Track> cleanedTrack = m_trackCleaner->clean(*segtrack); + if (cleanedTrack && !(cleanedTrack->perigeeParameters() == segtrack->perigeeParameters())) { + delete segtrack; + // using release until the entire code can be migrated to use smart pointers + segtrack = cleanedTrack.release(); + } + if (!m_edmHelperSvc->goodTrack(*segtrack, 10)) { + if (segtrack->fitQuality()) { + ATH_MSG_DEBUG("segment fit with chi^2/nDoF = " << segtrack->fitQuality()->chiSquared() << "/" + << segtrack->fitQuality()->numberDoF()); + } + delete segtrack; + segtrack = 0; + } else { + m_trackSummary->updateTrack(*segtrack); + } } return segtrack; - } +} + +std::vector<std::pair<Amg::Vector3D, Amg::Vector3D> > +MuonClusterSegmentFinderTool::segmentSeedFromPads( + std::vector<std::vector<const Muon::MuonClusterOnTrack*> >& orderedClusters, const Muon::MuonSegment* etaSeg) const +{ + + std::vector<std::pair<Amg::Vector3D, Amg::Vector3D> > seeds; + + std::vector<std::vector<const Muon::MuonClusterOnTrack*> > sTgc1, sTgc2; + + for (int iml = 1; iml < 3; ++iml) { + // multilayer loop + unsigned int istart = 0; + unsigned int idir = 1; + if (iml == 2) istart = orderedClusters.size() - 1; + if (iml == 2) idir = -1; + for (unsigned int i = istart; i < orderedClusters.size(); i = i + idir) { + if (m_idHelperSvc->stgcIdHelper().multilayer(orderedClusters[i].front()->identify()) != iml) continue; + std::vector<const Muon::MuonClusterOnTrack*> hits; + double distance = 1000.; + for (std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit = orderedClusters[i].begin(); + cit != orderedClusters[i].end(); ++cit) + { + // check the hit is aligned with the segment + // segment position on the surface + const Trk::PlaneSurface* surf = dynamic_cast<const Trk::PlaneSurface*>(&(*cit)->associatedSurface()); + if (!surf) continue; + Amg::Vector3D piOnPlane = intersectPlane(*surf, etaSeg->globalPosition(), etaSeg->globalDirection()); + // transform to local plane coordiantes + Amg::Vector2D lpos; + surf->globalToLocal(piOnPlane, piOnPlane, lpos); + // pad width + const sTgcPrepData* prd = dynamic_cast<const sTgcPrepData*>((*cit)->prepRawData()); + if (!prd) continue; + const MuonGM::MuonPadDesign* design = prd->detectorElement()->getPadDesign((*cit)->identify()); + if (!design) continue; + double chWidth1 = 0.5 * design->channelWidth(prd->localPosition(), false); + Amg::Vector2D lp1(prd->localPosition().x(), prd->localPosition().y() - chWidth1); + Amg::Vector2D lp2(prd->localPosition().x(), prd->localPosition().y() + chWidth1); + double etaDistance = prd->localPosition().y() - lpos[1]; + ATH_MSG_DEBUG(" etaDistance " << etaDistance); + if (std::abs(etaDistance) < distance + 0.001) { + double lastDistance = distance; + distance = std::abs(etaDistance); + if (distance < 100.) { + if (lp1.y() < lpos.y() && lp2.y() > lpos.y()) { + if (hits.size() == 0) { + ATH_MSG_DEBUG(" start best etaDistance " << etaDistance); + hits.push_back(*cit); + } else if (std::abs(lastDistance - distance) < 0.001) { + hits.push_back(*cit); + ATH_MSG_DEBUG(" added etaDistance " << etaDistance << " size " << hits.size()); + } else { + ATH_MSG_DEBUG(" reset update best etaDistance " << etaDistance); + hits.clear(); + hits.push_back(*cit); + } + } + } + } + } + if (hits.size() == 0) continue; + if (m_idHelperSvc->stgcIdHelper().multilayer(hits.front()->identify()) == 1) + sTgc1.push_back(hits); + else + sTgc2.push_back(hits); + } + } - std::vector<std::pair<Amg::Vector3D,Amg::Vector3D> > - MuonClusterSegmentFinderTool::segmentSeedFromPads(std::vector< std::vector<const Muon::MuonClusterOnTrack*> >& orderedClusters, - const Muon::MuonSegment* etaSeg) const { + ATH_MSG_DEBUG(" sTgc1.size() " << sTgc1.size() << " sTgc2.size() " << sTgc2.size()); - std::vector<std::pair<Amg::Vector3D,Amg::Vector3D> > seeds; + if (sTgc1.size() == 0 || sTgc2.size() == 0) return seeds; + // store reference surfaces + const sTgcPrepData* prdL1 = dynamic_cast<const sTgcPrepData*>(sTgc1.front().front()->prepRawData()); + const sTgcPrepData* prdL2 = dynamic_cast<const sTgcPrepData*>(sTgc2.back().front()->prepRawData()); + const Trk::PlaneSurface* surf1 = + dynamic_cast<const Trk::PlaneSurface*>(&(sTgc1.front().front())->associatedSurface()); + const Trk::PlaneSurface* surf2 = + dynamic_cast<const Trk::PlaneSurface*>(&(sTgc2.back().front())->associatedSurface()); - std::vector<std::vector<const Muon::MuonClusterOnTrack*> > sTgc1,sTgc2; - for(int iml=1; iml<3; ++iml) { -// multilayer loop - unsigned int istart = 0; - unsigned int idir = 1; - if(iml==2) istart = orderedClusters.size()-1; - if(iml==2) idir = -1; - for(unsigned int i=istart; i<orderedClusters.size(); i = i+idir) { - if(m_idHelperSvc->stgcIdHelper().multilayer(orderedClusters[i].front()->identify()) != iml) continue; + // ensure there are 4 entries per sTgc chamber + while (sTgc1.size() < 4) { + ATH_MSG_DEBUG("Adding empty layer to the sTgc chlay 1"); std::vector<const Muon::MuonClusterOnTrack*> hits; - double distance = 1000.; - for(std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit=orderedClusters[i].begin(); cit!=orderedClusters[i].end(); ++cit) { - //check the hit is aligned with the segment - //segment position on the surface - const Trk::PlaneSurface* surf = dynamic_cast<const Trk::PlaneSurface*>(&(*cit)->associatedSurface()); - if( !surf ) continue; - Amg::Vector3D piOnPlane = intersectPlane(*surf,etaSeg->globalPosition(),etaSeg->globalDirection()); - // transform to local plane coordiantes - Amg::Vector2D lpos; - surf->globalToLocal(piOnPlane,piOnPlane,lpos); - //pad width - const sTgcPrepData* prd = dynamic_cast<const sTgcPrepData*>((*cit)->prepRawData()); - if (!prd) continue; - const MuonGM::MuonPadDesign* design = prd->detectorElement()->getPadDesign( (*cit)->identify() ); - if (!design) continue; - double chWidth1 = 0.5*design->channelWidth(prd->localPosition(),false); - Amg::Vector2D lp1(prd->localPosition().x(),prd->localPosition().y()-chWidth1); - Amg::Vector2D lp2(prd->localPosition().x(),prd->localPosition().y()+chWidth1); - double etaDistance = prd->localPosition().y()-lpos[1]; - ATH_MSG_DEBUG(" etaDistance " << etaDistance); - if(std::abs(etaDistance)<distance+0.001) { - double lastDistance = distance; - distance = std::abs(etaDistance); - if(distance<100.) { - if(lp1.y() < lpos.y() && lp2.y() > lpos.y()) { - if(hits.size() == 0) { - ATH_MSG_DEBUG(" start best etaDistance " << etaDistance ); - hits.push_back( *cit ); - } else if(std::abs(lastDistance-distance)<0.001) { - hits.push_back( *cit ); - ATH_MSG_DEBUG(" added etaDistance " << etaDistance << " size " << hits.size()); - } else { - ATH_MSG_DEBUG(" reset update best etaDistance " << etaDistance); - hits.clear(); - hits.push_back( *cit ); - } - } - } - } - } - if(hits.size() == 0) continue; - if(m_idHelperSvc->stgcIdHelper().multilayer(hits.front()->identify()) == 1) sTgc1.push_back(hits); - else sTgc2.push_back( hits ); - } + sTgc1.push_back(hits); + } + while (sTgc2.size() < 4) { + ATH_MSG_DEBUG("Adding empty layer to the sTgc chlay 2"); + std::vector<const Muon::MuonClusterOnTrack*> hits; + sTgc2.push_back(hits); + } + if (!prdL1 || !prdL2) { + ATH_MSG_WARNING("No prd associated to one of the sTgc pads!"); + return seeds; } - ATH_MSG_DEBUG(" sTgc1.size() " << sTgc1.size() << " sTgc2.size() " << sTgc2.size()); + if (!surf1 || !surf2) { + ATH_MSG_WARNING("No surface associated to one of the sTgc pads!"); + return seeds; + } + + if (sTgc1.size() != 4 || sTgc2.size() != 4) { + ATH_MSG_WARNING("Something is wrong with the sTgc phi pads! Found " << sTgc1.size() << "/" << sTgc2.size() + << " layers"); + } + std::vector<std::pair<double, double> > sTgc1_phi = getPadPhiOverlap(sTgc1); + std::vector<std::pair<double, double> > sTgc2_phi = getPadPhiOverlap(sTgc2); + + // make combinations of pad clusters + std::vector<Amg::Vector3D> phiPos1, phiPos2; + for (unsigned int i1 = 0; i1 < sTgc1_phi.size(); ++i1) { + double midPhi1 = 0.5 * (sTgc1_phi[i1].first + sTgc1_phi[i1].second); + // change to global position + Amg::Vector2D lp1(midPhi1, prdL1->localPosition().y()); + Amg::Vector3D gpL1; + prdL1->detectorElement()->surface().localToGlobal(lp1, gpL1, gpL1); + for (unsigned int i2 = 0; i2 < sTgc2_phi.size(); ++i2) { + // change to global position + double midPhi2 = 0.5 * (sTgc2_phi[i2].first + sTgc2_phi[i2].second); + Amg::Vector2D lp2(midPhi2, prdL2->localPosition().y()); + Amg::Vector3D gpL2; + prdL2->detectorElement()->surface().localToGlobal(lp2, gpL2, gpL2); + phiPos1.push_back(gpL1); + phiPos2.push_back(gpL2); + } + } - if(sTgc1.size() == 0 || sTgc2.size() == 0) return seeds; - //store reference surfaces - const sTgcPrepData* prdL1 = dynamic_cast<const sTgcPrepData*>(sTgc1.front().front()->prepRawData()); - const sTgcPrepData* prdL2 = dynamic_cast<const sTgcPrepData*>(sTgc2.back().front()->prepRawData()); - const Trk::PlaneSurface* surf1 = dynamic_cast<const Trk::PlaneSurface*>(&(sTgc1.front().front())->associatedSurface()); - const Trk::PlaneSurface* surf2 = dynamic_cast<const Trk::PlaneSurface*>(&(sTgc2.back().front())->associatedSurface()); - - - //ensure there are 4 entries per sTgc chamber - while(sTgc1.size() < 4) { - ATH_MSG_DEBUG("Adding empty layer to the sTgc chlay 1"); - std::vector<const Muon::MuonClusterOnTrack*> hits; - sTgc1.push_back(hits); - } - while(sTgc2.size() < 4) { - ATH_MSG_DEBUG("Adding empty layer to the sTgc chlay 2"); - std::vector<const Muon::MuonClusterOnTrack*> hits; - sTgc2.push_back(hits); - } - if( !prdL1 || !prdL2 ) { - ATH_MSG_WARNING( "No prd associated to one of the sTgc pads!" ); - return seeds; - } - - if( !surf1 || !surf2 ) { - ATH_MSG_WARNING( "No surface associated to one of the sTgc pads!" ); - return seeds; - } - - if(sTgc1.size() != 4 || sTgc2.size() != 4) { - ATH_MSG_WARNING( "Something is wrong with the sTgc phi pads! Found " << sTgc1.size() << "/" << sTgc2.size() << " layers" ); - } - std::vector<std::pair<double,double> > sTgc1_phi = getPadPhiOverlap(sTgc1); - std::vector<std::pair<double,double> > sTgc2_phi = getPadPhiOverlap(sTgc2); - - //make combinations of pad clusters - std::vector<Amg::Vector3D> phiPos1,phiPos2; - for(unsigned int i1=0; i1<sTgc1_phi.size(); ++i1) { - double midPhi1 = 0.5*(sTgc1_phi[i1].first + sTgc1_phi[i1].second); - //change to global position - Amg::Vector2D lp1(midPhi1,prdL1->localPosition().y()); - Amg::Vector3D gpL1; - prdL1->detectorElement()->surface().localToGlobal(lp1,gpL1,gpL1); - for(unsigned int i2=0; i2<sTgc2_phi.size(); ++i2) { - //change to global position - double midPhi2 = 0.5*(sTgc2_phi[i2].first + sTgc2_phi[i2].second); - Amg::Vector2D lp2(midPhi2,prdL2->localPosition().y()); - Amg::Vector3D gpL2; - prdL2->detectorElement()->surface().localToGlobal(lp2,gpL2,gpL2); - phiPos1.push_back(gpL1); - phiPos2.push_back(gpL2); - } - } - - for(unsigned int i=0; i<phiPos1.size(); ++i) { - //create the seed pair - // Peter this is badly defined -> use phi from positions - // Amg::Vector3D gdir( (phiPos2[i].x()-phiPos1[i].x()),(phiPos2[i].y()-phiPos1[i].y()),(phiPos2[i].z()-phiPos1[i].z()) ); - Amg::Vector3D gdir( (phiPos2[i].x()+phiPos1[i].x()),(phiPos2[i].y()+phiPos1[i].y()),(phiPos2[i].z()+phiPos1[i].z()) ); - gdir = gdir / gdir.mag(); - std::pair<Amg::Vector3D,Amg::Vector3D> seedPair(phiPos1[i],gdir); - seeds.push_back(seedPair); + for (unsigned int i = 0; i < phiPos1.size(); ++i) { + // create the seed pair + // Peter this is badly defined -> use phi from positions + // Amg::Vector3D gdir( + // (phiPos2[i].x()-phiPos1[i].x()),(phiPos2[i].y()-phiPos1[i].y()),(phiPos2[i].z()-phiPos1[i].z()) ); + Amg::Vector3D gdir((phiPos2[i].x() + phiPos1[i].x()), (phiPos2[i].y() + phiPos1[i].y()), + (phiPos2[i].z() + phiPos1[i].z())); + gdir = gdir / gdir.mag(); + std::pair<Amg::Vector3D, Amg::Vector3D> seedPair(phiPos1[i], gdir); + seeds.push_back(seedPair); } ATH_MSG_DEBUG(" segmentSeedFromPads: seeds.size() " << seeds.size()); return seeds; - - } - - - std::vector<std::pair<double,double> > MuonClusterSegmentFinderTool::getPadPhiOverlap(std::vector< std::vector<const Muon::MuonClusterOnTrack*> >& pads) const { - std::vector<std::pair<double,double> > phiOverlap; - - //calculate the max/min phi values for each pad - std::vector<std::vector<double> > padMax,padMin; - std::vector<double> padMean; - unsigned npadsMean = 0; - for(unsigned int i=0; i<pads.size(); ++i) { - std::vector<double> padLayerMax,padLayerMin; - for(std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit=pads[i].begin(); cit!=pads[i].end(); ++cit) { - Identifier id = (*cit)->identify(); - const sTgcPrepData* prd = dynamic_cast<const sTgcPrepData*>((*cit)->prepRawData()); - if (!prd) { - ATH_MSG_WARNING("No prd found for " << m_idHelperSvc->toString( id ) ); - continue; - } - const MuonGM::MuonPadDesign* design = prd->detectorElement()->getPadDesign( id ); - if( !design ) { - ATH_MSG_WARNING("No design found for " << m_idHelperSvc->toString( id ) ); - continue; - } - double chWidth = 0.5*design->channelWidth(prd->localPosition(),true); - Amg::Vector2D lp1(prd->localPosition().x()+chWidth,prd->localPosition().y()); - Amg::Vector2D lp2(prd->localPosition().x()-chWidth,prd->localPosition().y()); - - bool keep = true; - int jmean = -1; - for(unsigned int j = 0; j < npadsMean; j++) { - if(padMean[j]>lp2.x()&&padMean[j]<lp1.x()) { - keep = false; - jmean = (int) j; - } - } - if(keep) { -// only store phi positions that are different - padLayerMax.push_back(lp1.x()); - padLayerMin.push_back(lp2.x()); - padMean.push_back((lp1.x()+lp2.x())/2.); - ATH_MSG_DEBUG(" keep pad id " << m_idHelperSvc->toString( id ) << " lp1.x() " << lp1.x() << " lp1.y() " << lp1.y() << " index " << npadsMean << " padMean " << padMean[npadsMean]); - npadsMean++; - } else { - ATH_MSG_DEBUG(" reject pad id " << m_idHelperSvc->toString( id ) << " lp1.x() " << lp1.x() << " lp1.y() " << lp1.y() << " matched index " << jmean << " padMean " << padMean[jmean]); +} + + +std::vector<std::pair<double, double> > +MuonClusterSegmentFinderTool::getPadPhiOverlap(std::vector<std::vector<const Muon::MuonClusterOnTrack*> >& pads) const +{ + std::vector<std::pair<double, double> > phiOverlap; + + // calculate the max/min phi values for each pad + std::vector<std::vector<double> > padMax, padMin; + std::vector<double> padMean; + unsigned npadsMean = 0; + for (unsigned int i = 0; i < pads.size(); ++i) { + std::vector<double> padLayerMax, padLayerMin; + for (std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit = pads[i].begin(); cit != pads[i].end(); + ++cit) { + Identifier id = (*cit)->identify(); + const sTgcPrepData* prd = dynamic_cast<const sTgcPrepData*>((*cit)->prepRawData()); + if (!prd) { + ATH_MSG_WARNING("No prd found for " << m_idHelperSvc->toString(id)); + continue; + } + const MuonGM::MuonPadDesign* design = prd->detectorElement()->getPadDesign(id); + if (!design) { + ATH_MSG_WARNING("No design found for " << m_idHelperSvc->toString(id)); + continue; + } + double chWidth = 0.5 * design->channelWidth(prd->localPosition(), true); + Amg::Vector2D lp1(prd->localPosition().x() + chWidth, prd->localPosition().y()); + Amg::Vector2D lp2(prd->localPosition().x() - chWidth, prd->localPosition().y()); + + bool keep = true; + int jmean = -1; + for (unsigned int j = 0; j < npadsMean; j++) { + if (padMean[j] > lp2.x() && padMean[j] < lp1.x()) { + keep = false; + jmean = (int)j; + } + } + if (keep) { + // only store phi positions that are different + padLayerMax.push_back(lp1.x()); + padLayerMin.push_back(lp2.x()); + padMean.push_back((lp1.x() + lp2.x()) / 2.); + ATH_MSG_DEBUG(" keep pad id " << m_idHelperSvc->toString(id) << " lp1.x() " << lp1.x() << " lp1.y() " + << lp1.y() << " index " << npadsMean << " padMean " + << padMean[npadsMean]); + npadsMean++; + } else { + ATH_MSG_DEBUG(" reject pad id " << m_idHelperSvc->toString(id) << " lp1.x() " << lp1.x() << " lp1.y() " + << lp1.y() << " matched index " << jmean << " padMean " + << padMean[jmean]); + } } - } - padMax.push_back(padLayerMax); - padMin.push_back(padLayerMin); + padMax.push_back(padLayerMax); + padMin.push_back(padLayerMin); } - //find all combinations of pads (1 per layer) + // find all combinations of pads (1 per layer) unsigned int nCombos(1); - for(unsigned int i=1; i<padMax.size(); ++i) { - if(padMax[i].size() != 0) nCombos = nCombos*padMax[i].size(); + for (unsigned int i = 1; i < padMax.size(); ++i) { + if (padMax[i].size() != 0) nCombos = nCombos * padMax[i].size(); } bool makeCombinations = true; - if(nCombos>8) makeCombinations = false; - - if(makeCombinations) { - ATH_MSG_DEBUG("MakeCombinations for Pads " << nCombos ); - for(unsigned int l0=0; l0<padMax[0].size(); ++l0) { - std::vector<double> phiMax(nCombos,padMax[0][l0]); - std::vector<double> phiMin(nCombos,padMin[0][l0]); - for(unsigned int l1=0; l1<padMax[1].size(); ++l1) { - for(unsigned int i=0; i<nCombos; ++i) { - if(nCombos % padMax[1].size() == 0) { - if(padMax[1][l1] < phiMax[i]) phiMax[i] = padMax[1][l1]; - if(padMin[1][l1] > phiMin[i]) phiMin[i] = padMin[1][l1]; - } - } - for(unsigned int l2=0; l2<padMax[2].size(); ++l2) { - for(unsigned int i=0; i<nCombos; ++i) { - if(nCombos % padMax[2].size() == 0) { - if(padMax[2][l2] < phiMax[i]) phiMax[i] = padMax[2][l2]; - if(padMin[2][l2] > phiMin[i]) phiMin[i] = padMin[2][l2]; - } - } - for(unsigned int l3=0; l3<padMax[3].size(); ++l3) { - for(unsigned int i=0; i<nCombos; ++i) { - if(nCombos % padMax[3].size() == 0) { - if(padMax[3][l3] < phiMax[i]) phiMax[i] = padMax[3][l3]; - if(padMin[3][l3] > phiMin[i]) phiMin[i] = padMin[3][l3]; - } - } - }//end layer 3 loop - }//end layer 2 loop - }//end layer 1 loop - //store the overlaps regions - for(unsigned int i=0; i<nCombos; ++i) { - phiOverlap.push_back( std::pair<double,double>(phiMin[i],phiMax[i]) ); - } - }//end layer 0 loop + if (nCombos > 8) makeCombinations = false; + + if (makeCombinations) { + ATH_MSG_DEBUG("MakeCombinations for Pads " << nCombos); + for (unsigned int l0 = 0; l0 < padMax[0].size(); ++l0) { + std::vector<double> phiMax(nCombos, padMax[0][l0]); + std::vector<double> phiMin(nCombos, padMin[0][l0]); + for (unsigned int l1 = 0; l1 < padMax[1].size(); ++l1) { + for (unsigned int i = 0; i < nCombos; ++i) { + if (nCombos % padMax[1].size() == 0) { + if (padMax[1][l1] < phiMax[i]) phiMax[i] = padMax[1][l1]; + if (padMin[1][l1] > phiMin[i]) phiMin[i] = padMin[1][l1]; + } + } + for (unsigned int l2 = 0; l2 < padMax[2].size(); ++l2) { + for (unsigned int i = 0; i < nCombos; ++i) { + if (nCombos % padMax[2].size() == 0) { + if (padMax[2][l2] < phiMax[i]) phiMax[i] = padMax[2][l2]; + if (padMin[2][l2] > phiMin[i]) phiMin[i] = padMin[2][l2]; + } + } + for (unsigned int l3 = 0; l3 < padMax[3].size(); ++l3) { + for (unsigned int i = 0; i < nCombos; ++i) { + if (nCombos % padMax[3].size() == 0) { + if (padMax[3][l3] < phiMax[i]) phiMax[i] = padMax[3][l3]; + if (padMin[3][l3] > phiMin[i]) phiMin[i] = padMin[3][l3]; + } + } + } // end layer 3 loop + } // end layer 2 loop + } // end layer 1 loop + // store the overlaps regions + for (unsigned int i = 0; i < nCombos; ++i) { + phiOverlap.push_back(std::pair<double, double>(phiMin[i], phiMax[i])); + } + } // end layer 0 loop } else { - - for(unsigned int i0=0; i0<4; ++i0) { - for(unsigned int l0=0; l0<padMax[i0].size(); ++l0) { - phiOverlap.push_back( std::pair<double,double>(padMin[i0][l0],padMax[i0][l0]) ); - ATH_MSG_DEBUG(" layer " << i0 << " mst " << l0 << " phiMin " << padMin[i0][l0] << " phiMax " << padMax[i0][l0]); + + for (unsigned int i0 = 0; i0 < 4; ++i0) { + for (unsigned int l0 = 0; l0 < padMax[i0].size(); ++l0) { + phiOverlap.push_back(std::pair<double, double>(padMin[i0][l0], padMax[i0][l0])); + ATH_MSG_DEBUG(" layer " << i0 << " mst " << l0 << " phiMin " << padMin[i0][l0] << " phiMax " + << padMax[i0][l0]); + } } - } - ATH_MSG_DEBUG("Do not make combinations for Pads " << nCombos << " phiOverlap size " << phiOverlap.size() ); + ATH_MSG_DEBUG("Do not make combinations for Pads " << nCombos << " phiOverlap size " << phiOverlap.size()); } return phiOverlap; - } +} - bool MuonClusterSegmentFinderTool::belowThreshold(std::vector< const Muon::MuonClusterOnTrack* >& muonClusters, int threshold) const { +bool +MuonClusterSegmentFinderTool::belowThreshold(std::vector<const Muon::MuonClusterOnTrack*>& muonClusters, + int threshold) const +{ int n_surf_with_hits = 0; - if (muonClusters.size()>1) { - for(std::vector< const Muon::MuonClusterOnTrack* >::const_iterator cit=muonClusters.begin()+1; cit!=muonClusters.end(); cit++){ - if ((*cit) && (*(cit-1))) { - if ((*cit)->detectorElement()->center((*cit)->identify()) != (*(cit-1))->detectorElement()->center((*(cit-1))->identify())) { - n_surf_with_hits++; - } + if (muonClusters.size() > 1) { + for (std::vector<const Muon::MuonClusterOnTrack*>::const_iterator cit = muonClusters.begin() + 1; + cit != muonClusters.end(); cit++) + { + if ((*cit) && (*(cit - 1))) { + if ((*cit)->detectorElement()->center((*cit)->identify()) + != (*(cit - 1))->detectorElement()->center((*(cit - 1))->identify())) + { + n_surf_with_hits++; + } + } } - } - } else - n_surf_with_hits = muonClusters.size(); - if(n_surf_with_hits < threshold) return true; - else return false; - } - -}//end namespace + } else + n_surf_with_hits = muonClusters.size(); + if (n_surf_with_hits < threshold) + return true; + else + return false; +} + +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonClusterSegmentFinderTool.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonClusterSegmentFinderTool.h index dd66d6994255df5732e389ae4c178ad25f42156c..de2e5ab6e710f7adcb8a4c9f4d16117abfd359bc 100755 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonClusterSegmentFinderTool.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonClusterSegmentFinderTool.h @@ -5,90 +5,133 @@ #ifndef MUONROADFINDERTOOL_H #define MUONROADFINDERTOOL_H -#include "GaudiKernel/AlgTool.h" +#include <utility> +#include <vector> + #include "AthenaBaseComps/AthAlgTool.h" -#include "GaudiKernel/ToolHandle.h" +#include "GaudiKernel/AlgTool.h" #include "GaudiKernel/ServiceHandle.h" +#include "GaudiKernel/ToolHandle.h" +#include "MuonIdHelpers/IMuonIdHelperSvc.h" +#include "MuonRIO_OnTrack/MuonClusterOnTrack.h" +#include "MuonRecHelperTools/IMuonEDMHelperSvc.h" +#include "MuonRecHelperTools/MuonEDMPrinterTool.h" +#include "MuonRecToolInterfaces/IMuonTrackToSegmentTool.h" +#include "MuonSegment/MuonSegment.h" #include "MuonSegmentMakerToolInterfaces/IMuonClusterSegmentFinderTool.h" #include "TrkFitterInterfaces/ITrackFitter.h" +#include "TrkPseudoMeasurementOnTrack/PseudoMeasurementOnTrack.h" #include "TrkToolInterfaces/ITrackAmbiguityProcessorTool.h" #include "TrkToolInterfaces/ITrackSummaryTool.h" -#include "MuonRecToolInterfaces/IMuonTrackToSegmentTool.h" -#include "MuonSegment/MuonSegment.h" -#include "MuonRIO_OnTrack/MuonClusterOnTrack.h" -#include "MuonRecHelperTools/MuonEDMPrinterTool.h" -#include "MuonRecHelperTools/IMuonEDMHelperSvc.h" -#include "MuonIdHelpers/IMuonIdHelperSvc.h" -#include "TrkPseudoMeasurementOnTrack/PseudoMeasurementOnTrack.h" -#include <utility> -#include <vector> namespace Muon { - class IMuonTrackCleaner; +class IMuonTrackCleaner; + +class MuonClusterSegmentFinderTool : virtual public IMuonClusterSegmentFinderTool, public AthAlgTool { - class MuonClusterSegmentFinderTool : virtual public IMuonClusterSegmentFinderTool, public AthAlgTool - { - - public : + public: /** default constructor */ - MuonClusterSegmentFinderTool (const std::string& type, const std::string& name, const IInterface* parent); + MuonClusterSegmentFinderTool(const std::string& type, const std::string& name, const IInterface* parent); /** destructor */ virtual ~MuonClusterSegmentFinderTool(); - + static const InterfaceID& interfaceID(); virtual StatusCode initialize(void) override; virtual StatusCode finalize(void) override; private: - ToolHandle<Trk::ITrackFitter> m_slTrackFitter; //<! fitter, always use straightline - mutable ToolHandle<Trk::ITrackAmbiguityProcessorTool> m_ambiTool; //!< Tool for ambiguity solving - ToolHandle<IMuonTrackToSegmentTool> m_trackToSegmentTool; //<! track to segment converter - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - ToolHandle<MuonEDMPrinterTool> m_printer; - ServiceHandle<IMuonEDMHelperSvc> m_edmHelperSvc {this, "edmHelper", - "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", - "Handle to the service providing the IMuonEDMHelperSvc interface" }; //<! Id helper tool - ToolHandle<IMuonTrackCleaner> m_trackCleaner; - ToolHandle<Trk::ITrackSummaryTool> m_trackSummary; - bool m_ipConstraint; // use a ip perigee(0,0) constraint in the segment fit + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; + ServiceHandle<IMuonEDMHelperSvc> m_edmHelperSvc{ + this, + "edmHelper", + "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", + "Handle to the service providing the IMuonEDMHelperSvc interface", + }; //<! Id helper tool + + mutable ToolHandle<Trk::ITrackAmbiguityProcessorTool> m_ambiTool{ + this, + "SegmentAmbiguityTool", + "Trk::SimpleAmbiguityProcessorTool/MuonAmbiProcessor", + }; //!< Tool for ambiguity solving + ToolHandle<Trk::ITrackFitter> m_slTrackFitter{ + this, + "SLFitter", + "Trk::GlobalChi2Fitter/MCTBSLFitter", + }; //<! fitter, always use straightline + ToolHandle<IMuonTrackToSegmentTool> m_trackToSegmentTool{ + this, + "TrackToSegmentTool", + "Muon::MuonTrackToSegmentTool/MuonTrackToSegmentTool", + }; //<! track to segment converter + ToolHandle<MuonEDMPrinterTool> m_printer{ + this, + "Printer", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; + ToolHandle<IMuonTrackCleaner> m_trackCleaner{ + this, + "TrackCleaner", + "Muon::MuonTrackCleaner/MuonTrackCleaner", + }; + ToolHandle<Trk::ITrackSummaryTool> m_trackSummary{ + this, + "TrackSummaryTool", + "Trk::TrackSummaryTool/MuidTrackSummaryTool", + }; + + bool m_ipConstraint; // use a ip perigee(0,0) constraint in the segment fit double m_maxClustDist; public: - //find segments given a list of MuonCluster - //segments can be added directly to a SegmentCollection, if they are to be written to SG, or returned in a list for further processing - void find(std::vector< const Muon::MuonClusterOnTrack* >& clusters, std::vector<Muon::MuonSegment*>& segments, Trk::SegmentCollection* segColl=0) const override; - + // find segments given a list of MuonCluster + // segments can be added directly to a SegmentCollection, if they are to be written to SG, or returned in a list for + // further processing + void find(std::vector<const Muon::MuonClusterOnTrack*>& clusters, std::vector<Muon::MuonSegment*>& segments, + Trk::SegmentCollection* segColl = 0) const override; + private: - //reconstruct the segments in the precision (eta) plane - void findPrecisionSegments(std::vector< const Muon::MuonClusterOnTrack* >& MuonClusters, std::vector<Muon::MuonSegment*>& etaSegs) const; - //recontruct 3D segments - void find3DSegments(std::vector< const Muon::MuonClusterOnTrack* >& MuonClusters, - std::vector<Muon::MuonSegment*>& etaSegs, - std::vector<Muon::MuonSegment*>& segments, - Trk::SegmentCollection* segColl=0) const; - //clean the clusters - std::vector< const Muon::MuonClusterOnTrack* > cleanClusters(std::vector< const Muon::MuonClusterOnTrack* >& MuonClusters, bool selectPhiClusters=false) const ; - //order the clusters - std::vector< std::vector<const Muon::MuonClusterOnTrack*> > orderByLayer(std::vector< const Muon::MuonClusterOnTrack* >& clusters, bool usePads=false) const; - //find segment seeds - std::vector<std::pair<Amg::Vector3D,Amg::Vector3D> > segmentSeed(std::vector< std::vector<const Muon::MuonClusterOnTrack*> >& orderedClusters, bool usePhi) const; - std::vector<std::pair<Amg::Vector3D,Amg::Vector3D> > segmentSeedFromPads(std::vector< std::vector<const Muon::MuonClusterOnTrack*> >& orderedClusters, - const Muon::MuonSegment* etaSeg) const; - std::vector<std::pair<double,double> > getPadPhiOverlap(std::vector< std::vector<const Muon::MuonClusterOnTrack*> >& pads) const; - //associate clusters to the segment seeds - std::vector< const Muon::MuonClusterOnTrack* > getClustersOnSegment(std::vector< std::vector<const Muon::MuonClusterOnTrack*> >& clusters, - std::pair<Amg::Vector3D,Amg::Vector3D>& seed, bool tight) const; - //distance of cluster to segment seed - double clusterDistanceToSeed(const Muon::MuonClusterOnTrack* clust, std::pair<Amg::Vector3D,Amg::Vector3D>& seed) const; - Amg::Vector3D intersectPlane( const Trk::PlaneSurface& surf, const Amg::Vector3D& pos, const Amg::Vector3D& dir ) const; - Trk::Track* fit( const std::vector<const Trk::MeasurementBase*>& vec2, const Trk::TrackParameters& startpar ) const; - - //check if enough surfaces are hitted - bool belowThreshold(std::vector< const Muon::MuonClusterOnTrack* >& muonClusters, int threshold) const; - }; - - -} -#endif //MUONROADFINDERTOOL_H + // reconstruct the segments in the precision (eta) plane + void findPrecisionSegments(std::vector<const Muon::MuonClusterOnTrack*>& MuonClusters, + std::vector<Muon::MuonSegment*>& etaSegs) const; + // recontruct 3D segments + void find3DSegments(std::vector<const Muon::MuonClusterOnTrack*>& MuonClusters, + std::vector<Muon::MuonSegment*>& etaSegs, std::vector<Muon::MuonSegment*>& segments, + Trk::SegmentCollection* segColl = 0) const; + // clean the clusters + std::vector<const Muon::MuonClusterOnTrack*> cleanClusters( + std::vector<const Muon::MuonClusterOnTrack*>& MuonClusters, bool selectPhiClusters = false) const; + // order the clusters + std::vector<std::vector<const Muon::MuonClusterOnTrack*> > orderByLayer( + std::vector<const Muon::MuonClusterOnTrack*>& clusters, bool usePads = false) const; + // find segment seeds + std::vector<std::pair<Amg::Vector3D, Amg::Vector3D> > segmentSeed( + std::vector<std::vector<const Muon::MuonClusterOnTrack*> >& orderedClusters, bool usePhi) const; + std::vector<std::pair<Amg::Vector3D, Amg::Vector3D> > segmentSeedFromPads( + std::vector<std::vector<const Muon::MuonClusterOnTrack*> >& orderedClusters, + const Muon::MuonSegment* etaSeg) const; + std::vector<std::pair<double, double> > getPadPhiOverlap( + std::vector<std::vector<const Muon::MuonClusterOnTrack*> >& pads) const; + // associate clusters to the segment seeds + std::vector<const Muon::MuonClusterOnTrack*> getClustersOnSegment( + std::vector<std::vector<const Muon::MuonClusterOnTrack*> >& clusters, + std::pair<Amg::Vector3D, Amg::Vector3D>& seed, bool tight) const; + // distance of cluster to segment seed + double clusterDistanceToSeed(const Muon::MuonClusterOnTrack* clust, + std::pair<Amg::Vector3D, Amg::Vector3D>& seed) const; + Amg::Vector3D intersectPlane(const Trk::PlaneSurface& surf, const Amg::Vector3D& pos, + const Amg::Vector3D& dir) const; + Trk::Track* fit(const std::vector<const Trk::MeasurementBase*>& vec2, const Trk::TrackParameters& startpar) const; + + // check if enough surfaces are hitted + bool belowThreshold(std::vector<const Muon::MuonClusterOnTrack*>& muonClusters, int threshold) const; +}; + + +} // namespace Muon +#endif // MUONROADFINDERTOOL_H diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonSegmentFittingTool.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonSegmentFittingTool.cxx index c845675cdcbf519cf2aacad6225441931d2aa5b2..5bcaf0e6c495bb69dd2651b99296c746125a74d6 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonSegmentFittingTool.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonSegmentFittingTool.cxx @@ -4,186 +4,187 @@ #include "MuonSegmentFittingTool.h" -#include "TrkEventPrimitives/LocalDirection.h" +#include "MuonSegment/MuonSegment.h" #include "TrkEventPrimitives/DefinedParameter.h" +#include "TrkEventPrimitives/FitQuality.h" +#include "TrkEventPrimitives/LocalDirection.h" #include "TrkEventPrimitives/LocalParameters.h" #include "TrkEventPrimitives/ParamDefs.h" -#include "TrkEventPrimitives/FitQuality.h" -#include "TrkTrack/Track.h" #include "TrkParameters/TrackParameters.h" #include "TrkSurfaces/PlaneSurface.h" -#include "MuonSegment/MuonSegment.h" +#include "TrkTrack/Track.h" namespace Muon { - MuonSegmentFittingTool::MuonSegmentFittingTool( const std::string& t, const std::string& n, const IInterface* p ) : - AthAlgTool(t,n,p), - m_slPropagator("Trk::RungeKuttaPropagator/AtlasRungeKuttaPropagator", this), - m_magFieldProperties(Trk::NoField), - m_slTrackFitter("Trk::GlobalChi2Fitter/MCTBSLFitter", this), - m_curvedTrackFitter("Trk::GlobalChi2Fitter/MCTBFitter", this), - m_trackCleaner("Muon::MuonTrackCleaner/MuonTrackCleaner", this) - { +MuonSegmentFittingTool::MuonSegmentFittingTool(const std::string& t, const std::string& n, const IInterface* p) + : AthAlgTool(t, n, p), m_magFieldProperties(Trk::NoField) +{ declareInterface<IMuonSegmentFittingTool>(this); - declareProperty("SLPropagator", m_slPropagator); - declareProperty("SLFitter", m_slTrackFitter); - declareProperty("CurvedFitter", m_curvedTrackFitter); - declareProperty("TrackCleaner", m_trackCleaner); - declareProperty("UpdatePrecisionCoordinate", m_updatePrecisionCoordinate = false ); - } - - StatusCode MuonSegmentFittingTool::initialize() - { - ATH_CHECK( m_slPropagator.retrieve() ); - ATH_CHECK( m_slTrackFitter.retrieve() ); - ATH_CHECK( m_curvedTrackFitter.retrieve() ); - ATH_CHECK( m_trackCleaner.retrieve() ); + declareProperty("UpdatePrecisionCoordinate", m_updatePrecisionCoordinate = false); +} + +StatusCode +MuonSegmentFittingTool::initialize() +{ + ATH_CHECK(m_slPropagator.retrieve()); + ATH_CHECK(m_slTrackFitter.retrieve()); + ATH_CHECK(m_curvedTrackFitter.retrieve()); + ATH_CHECK(m_trackCleaner.retrieve()); return StatusCode::SUCCESS; - } +} + +Trk::Track* +MuonSegmentFittingTool::fit(const MuonSegment& segment) const +{ + return fit(segment.globalPosition(), segment.globalDirection(), segment.associatedSurface(), + segment.containedMeasurements()); +} + +Trk::Track* +MuonSegmentFittingTool::fit(const Amg::Vector3D& gpos, const Amg::Vector3D& gDir, const Trk::PlaneSurface& surf, + const std::vector<const Trk::MeasurementBase*>& rioVec) const +{ - Trk::Track* MuonSegmentFittingTool::fit( const MuonSegment& segment ) const { - return fit( segment.globalPosition(),segment.globalDirection(),segment.associatedSurface(),segment.containedMeasurements()); - } - Trk::Track* MuonSegmentFittingTool::fit( const Amg::Vector3D& gpos, const Amg::Vector3D& gDir, const Trk::PlaneSurface& surf, - const std::vector<const Trk::MeasurementBase*>& rioVec ) const { - - ATH_MSG_VERBOSE(" trying to fit segment "); Amg::Vector3D gdir = gDir; - double gdirNorm = gdir.mag(); - bool isCurvedSegment = ( gdirNorm > 1.5 ? true : false ); - if(isCurvedSegment) { - //re-normalize the gdir - gdir = Amg::Vector3D(gdir.x()/gdirNorm,gdir.y()/gdirNorm,gdir.z()/gdirNorm); + double gdirNorm = gdir.mag(); + bool isCurvedSegment = (gdirNorm > 1.5 ? true : false); + if (isCurvedSegment) { + // re-normalize the gdir + gdir = Amg::Vector3D(gdir.x() / gdirNorm, gdir.y() / gdirNorm, gdir.z() / gdirNorm); } - double charge = 0; - Trk::AtaPlane segPars(gpos,gdir,charge,surf); - + double charge = 0; + Trk::AtaPlane segPars(gpos, gdir, charge, surf); + // extrapolate segment parameters to first measurements - const Trk::MeasurementBase* firstMeas = rioVec.front(); - const Trk::TrackParameters* exPars = m_slPropagator->propagate(segPars,firstMeas->associatedSurface(),Trk::anyDirection,false,m_magFieldProperties); - if( !exPars ) { - ATH_MSG_DEBUG(" Propagation failed!! "); - return 0; + const Trk::MeasurementBase* firstMeas = rioVec.front(); + const Trk::TrackParameters* exPars = m_slPropagator->propagate(segPars, firstMeas->associatedSurface(), + Trk::anyDirection, false, m_magFieldProperties); + if (!exPars) { + ATH_MSG_DEBUG(" Propagation failed!! "); + return 0; } // small shift towards the ip - double sign = exPars->position().dot(exPars->momentum()) > 0 ? 1. : -1.; - Amg::Vector3D perpos = exPars->position() - sign*exPars->momentum().unit(); - delete exPars; exPars = 0; + double sign = exPars->position().dot(exPars->momentum()) > 0 ? 1. : -1.; + Amg::Vector3D perpos = exPars->position() - sign * exPars->momentum().unit(); + delete exPars; + exPars = 0; // create start parameter - double phi=gdir.phi(); - double theta=gdir.theta(); - double qoverp=0; + double phi = gdir.phi(); + double theta = gdir.theta(); + double qoverp = 0; Trk::PerigeeSurface persurf(perpos); - Trk::Perigee startpar(0,0,phi,theta,qoverp,persurf); + Trk::Perigee startpar(0, 0, phi, theta, qoverp, persurf); // copy measurements into new vector std::vector<const Trk::MeasurementBase*> vec2; vec2.reserve(rioVec.size()); - std::copy( rioVec.begin(), rioVec.end(), std::back_inserter(vec2) ); - - // fit + std::copy(rioVec.begin(), rioVec.end(), std::back_inserter(vec2)); + + // fit Trk::ParticleSwitcher particleSwitch; - Trk::Track* newtrack; - //use the full fitter if the segment is curved - if(isCurvedSegment) { - newtrack = m_curvedTrackFitter->fit(vec2,startpar,false,particleSwitch.particle[0]); + Trk::Track* newtrack; + // use the full fitter if the segment is curved + if (isCurvedSegment) { + newtrack = m_curvedTrackFitter->fit(vec2, startpar, false, particleSwitch.particle[0]); } - //else use the straight line fitter - else { - newtrack = m_slTrackFitter->fit(vec2,startpar,false,Trk::nonInteracting); + // else use the straight line fitter + else + { + newtrack = m_slTrackFitter->fit(vec2, startpar, false, Trk::nonInteracting); } - if( !newtrack ) { - ATH_MSG_VERBOSE(" fit failed "); - return 0; + if (!newtrack) { + ATH_MSG_VERBOSE(" fit failed "); + return 0; } std::unique_ptr<Trk::Track> cleanTrack = m_trackCleaner->clean(*newtrack); - if( !cleanTrack && !isCurvedSegment ) { - ATH_MSG_VERBOSE(" lost in cleaner "); - delete newtrack; - return 0; + if (!cleanTrack && !isCurvedSegment) { + ATH_MSG_VERBOSE(" lost in cleaner "); + delete newtrack; + return 0; } - if( !(*cleanTrack->perigeeParameters() == *newtrack->perigeeParameters()) && !isCurvedSegment ) { - delete newtrack; - //using release until the entire code can be migrated to use smart pointers - newtrack = cleanTrack.release(); + if (!(*cleanTrack->perigeeParameters() == *newtrack->perigeeParameters()) && !isCurvedSegment) { + delete newtrack; + // using release until the entire code can be migrated to use smart pointers + newtrack = cleanTrack.release(); } - + const Trk::FitQuality* fq = newtrack->fitQuality(); - if( !fq ) { - // no fit quality!!, discard track - ATH_MSG_WARNING(" track without fit quality!! "); - delete newtrack; - return 0; + if (!fq) { + // no fit quality!!, discard track + ATH_MSG_WARNING(" track without fit quality!! "); + delete newtrack; + return 0; } - - double reducedChi2 = fq->chiSquared()/fq->numberDoF(); - double cut = 10.; + + double reducedChi2 = fq->chiSquared() / fq->numberDoF(); + double cut = 10.; // reject fit if larger than cut - if( reducedChi2 > cut ) { - ATH_MSG_VERBOSE(" reduced chi2 to large " << reducedChi2 << " cut " << cut); - delete newtrack; - return 0; + if (reducedChi2 > cut) { + ATH_MSG_VERBOSE(" reduced chi2 to large " << reducedChi2 << " cut " << cut); + delete newtrack; + return 0; } - - if( msgLvl(MSG::DEBUG) ){ - ATH_MSG_DEBUG(std::setprecision(5) << " chi2 " << fq->chiSquared() << " ndof " << fq->numberDoF()); - const Trk::Perigee* pp = newtrack->perigeeParameters(); - if( pp ){ - ATH_MSG_DEBUG(" pos " << std::setprecision(5) << pp->position() - << " phi " << pp->momentum().phi() << " theta " << pp->momentum().theta() - << " q*mom " << pp->momentum().mag()*pp->charge() - << " pt " << pp->momentum().perp()); - }else{ - ATH_MSG_DEBUG(" no perigee "); - } + + if (msgLvl(MSG::DEBUG)) { + ATH_MSG_DEBUG(std::setprecision(5) << " chi2 " << fq->chiSquared() << " ndof " << fq->numberDoF()); + const Trk::Perigee* pp = newtrack->perigeeParameters(); + if (pp) { + ATH_MSG_DEBUG(" pos " << std::setprecision(5) << pp->position() << " phi " << pp->momentum().phi() + << " theta " << pp->momentum().theta() << " q*mom " + << pp->momentum().mag() * pp->charge() << " pt " << pp->momentum().perp()); + } else { + ATH_MSG_DEBUG(" no perigee "); + } } return newtrack; - } +} + +void +MuonSegmentFittingTool::updateSegmentParameters(const Trk::Track& track, const Trk::PlaneSurface& surf, + Amg::Vector2D& segLocPos, Trk::LocalDirection& segLocDir, + Amg::MatrixX& locerr) const +{ - void MuonSegmentFittingTool::updateSegmentParameters( const Trk::Track& track, const Trk::PlaneSurface& surf, Amg::Vector2D& segLocPos, - Trk::LocalDirection& segLocDir, Amg::MatrixX& locerr ) const - { - ATH_MSG_DEBUG(" old segment parameters: pos (" << segLocPos[Trk::locX] << "," << segLocPos[Trk::locY] << ") dir (" - << segLocDir.angleXZ() << "," << segLocDir.angleYZ() << ") "); - - + << segLocDir.angleXZ() << "," << segLocDir.angleYZ() << ") "); + + const Trk::Perigee* pp = track.perigeeParameters(); - if( !pp ){ - ATH_MSG_WARNING(" track without perigee "); - return; + if (!pp) { + ATH_MSG_WARNING(" track without perigee "); + return; } - const Trk::TrackParameters* exPars = m_slPropagator->propagate( *pp,surf,Trk::anyDirection,false,m_magFieldProperties); - if( !exPars ){ - ATH_MSG_WARNING(" extrapolation failed, this should not happen "); - return; + const Trk::TrackParameters* exPars = + m_slPropagator->propagate(*pp, surf, Trk::anyDirection, false, m_magFieldProperties); + if (!exPars) { + ATH_MSG_WARNING(" extrapolation failed, this should not happen "); + return; } Amg::Vector2D lpos; - surf.globalToLocal( exPars->position(),exPars->position(),lpos ); + surf.globalToLocal(exPars->position(), exPars->position(), lpos); Trk::LocalDirection ldir; - surf.globalToLocalDirection( exPars->momentum().unit(), ldir ); + surf.globalToLocalDirection(exPars->momentum().unit(), ldir); ATH_MSG_DEBUG(" new segment parameters: pos (" << lpos[Trk::locX] << "," << lpos[Trk::locY] << ") dir (" - << ldir.angleXZ() << "," << ldir.angleYZ() << ") "); + << ldir.angleXZ() << "," << ldir.angleYZ() << ") "); segLocPos[Trk::locX] = lpos[Trk::locX]; - if( m_updatePrecisionCoordinate ) segLocPos[Trk::locY] = lpos[Trk::locY]; + if (m_updatePrecisionCoordinate) segLocPos[Trk::locY] = lpos[Trk::locY]; segLocDir = Trk::LocalDirection(ldir.angleXZ(), m_updatePrecisionCoordinate ? ldir.angleYZ() : segLocDir.angleYZ()); - - if(exPars->covariance()) locerr = *exPars->covariance(); - delete exPars; - } + if (exPars->covariance()) locerr = *exPars->covariance(); + delete exPars; } +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonSegmentFittingTool.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonSegmentFittingTool.h index b35dc9b1e266b6143fa91d2d303c657635a65151..5dd2ad0659eae11d507e39271f8f30f1b4270ca5 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonSegmentFittingTool.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/DCMathSegmentMaker/src/MuonSegmentFittingTool.h @@ -5,65 +5,81 @@ #ifndef MUONSEGMENTFITTINGTOOL_H #define MUONSEGMENTFITTINGTOOL_H -#include "MuonRecToolInterfaces/IMuonSegmentFittingTool.h" +#include <string> +#include <vector> + #include "AthenaBaseComps/AthAlgTool.h" #include "GaudiKernel/ToolHandle.h" - #include "GeoPrimitives/GeoPrimitives.h" -#include "TrkGeometry/MagneticFieldProperties.h" -#include "TrkFitterInterfaces/ITrackFitter.h" +#include "MuonRecToolInterfaces/IMuonSegmentFittingTool.h" #include "TrkExInterfaces/IPropagator.h" +#include "TrkFitterInterfaces/ITrackFitter.h" +#include "TrkGeometry/MagneticFieldProperties.h" #include "MuonRecToolInterfaces/IMuonTrackCleaner.h" -#include <string> -#include <vector> namespace Trk { - class PlaneSurface; - class LocalDirection; - class MeasurementBase; -} +class PlaneSurface; +class LocalDirection; +class MeasurementBase; +} // namespace Trk namespace Muon { - class MuonSegment; +class MuonSegment; } namespace Muon { - /** - @class MuonSegmentFittingTool +/** + @class MuonSegmentFittingTool - Implementation of an IMuonSegmentFittingTool. + Implementation of an IMuonSegmentFittingTool. - */ - class MuonSegmentFittingTool : virtual public IMuonSegmentFittingTool, public AthAlgTool { +*/ +class MuonSegmentFittingTool : virtual public IMuonSegmentFittingTool, public AthAlgTool { public: - MuonSegmentFittingTool(const std::string&,const std::string&,const IInterface*); - - virtual ~MuonSegmentFittingTool()=default; - + MuonSegmentFittingTool(const std::string&, const std::string&, const IInterface*); + + virtual ~MuonSegmentFittingTool() = default; + virtual StatusCode initialize(); /** fit segment parameters + hits producing a track */ - Trk::Track* fit( const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, const Trk::PlaneSurface& surf, - const std::vector<const Trk::MeasurementBase*>& rioVec ) const; + Trk::Track* fit(const Amg::Vector3D& gpos, const Amg::Vector3D& gdir, const Trk::PlaneSurface& surf, + const std::vector<const Trk::MeasurementBase*>& rioVec) const; /** fit segment parameters + hits producing a track */ - Trk::Track* fit( const MuonSegment& segment ) const; + Trk::Track* fit(const MuonSegment& segment) const; /** update the parameters of the segment using the track information */ - void updateSegmentParameters( const Trk::Track& track, const Trk::PlaneSurface& surf, Amg::Vector2D& segLocPos, - Trk::LocalDirection& segLocDir, Amg::MatrixX& locerr ) const; - - - ToolHandle<Trk::IPropagator> m_slPropagator; //<! propagator, always use straightline - Trk::MagneticFieldProperties m_magFieldProperties; //<! pmagnetic field properties - ToolHandle<Trk::ITrackFitter> m_slTrackFitter; //<! fitter, always use straightline - ToolHandle<Trk::ITrackFitter> m_curvedTrackFitter; //<! fitter, curved tracks - ToolHandle<Muon::IMuonTrackCleaner> m_trackCleaner; - - bool m_updatePrecisionCoordinate; //<! flag to select update of precision coordinate in fit - }; - -} -#endif + void updateSegmentParameters(const Trk::Track& track, const Trk::PlaneSurface& surf, Amg::Vector2D& segLocPos, + Trk::LocalDirection& segLocDir, Amg::MatrixX& locerr) const; + + + Trk::MagneticFieldProperties m_magFieldProperties; //<! pmagnetic field properties + + ToolHandle<Trk::IPropagator> m_slPropagator{ + this, + "SLPropagator", + "Trk::RungeKuttaPropagator/AtlasRungeKuttaPropagator", + }; //<! propagator, always use straightline + ToolHandle<Trk::ITrackFitter> m_slTrackFitter{ + this, + "SLFitter", + "Trk::GlobalChi2Fitter/MCTBSLFitter", + }; //<! fitter, always use straightline + ToolHandle<Trk::ITrackFitter> m_curvedTrackFitter{ + this, + "CurvedFitter", + "Trk::GlobalChi2Fitter/MCTBFitter", + }; //<! fitter, curved tracks + ToolHandle<Muon::IMuonTrackCleaner> m_trackCleaner{ + this, + "TrackCleaner", + "Muon::MuonTrackCleaner/MuonTrackCleaner", + }; + + bool m_updatePrecisionCoordinate; //<! flag to select update of precision coordinate in fit +}; +} // namespace Muon +#endif diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonClusterSegmentMakerTools/src/MuonClusterSegmentFinder.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonClusterSegmentMakerTools/src/MuonClusterSegmentFinder.cxx index 6f2d38b288cf32bb154dca22439c070e040c2b8d..ed04c771097a2f51c9b31653ca714e940751ee6f 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonClusterSegmentMakerTools/src/MuonClusterSegmentFinder.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonClusterSegmentMakerTools/src/MuonClusterSegmentFinder.cxx @@ -4,61 +4,44 @@ #include "MuonClusterSegmentFinder.h" +#include "AtlasHepMC/GenEvent.h" #include "MuonLinearSegmentMakerUtilities/ClusterAnalysis.h" #include "MuonPrepRawData/MdtPrepDataCollection.h" #include "MuonRIO_OnTrack/MdtDriftCircleOnTrack.h" -#include "AtlasHepMC/GenEvent.h" #include "MuonRIO_OnTrack/MuonClusterOnTrack.h" - -#include "TTree.h" #include "TFile.h" +#include "TTree.h" namespace Muon { - MuonClusterSegmentFinder::MuonClusterSegmentFinder(const std::string& type, const std::string& name, const IInterface* parent): - AthAlgTool(type,name,parent), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"), - m_layerHashProvider("Muon::MuonLayerHashProviderTool/MuonLayerHashProviderTool", this), - m_muonPRDSelectionTool("Muon::MuonPRDSelectionTool/MuonPRDSelectionTool", this), - m_segmentMaker("Muon::DCMathSegmentMaker/DCMathSegmentMaker", this), - m_clusterTool("Muon::MuonClusterizationTool/MuonClusterizationTool", this), - m_clusterCreator("Muon::MuonClusterOnTrackCreator/MuonClusterOnTrackCreator", this), - m_trackToSegmentTool("Muon::MuonTrackToSegmentTool/MuonTrackToSegmentTool", this), - m_slTrackFitter("Trk::GlobalChi2Fitter/MCTBSLFitter", this), - m_ambiguityProcessor("Trk::TrackSelectionProcessorTool/MuonAmbiProcessor"), - m_trackCleaner("Muon::MuonTrackCleaner/MuonTrackCleaner", this), - m_segmentOverlapRemovalTool("Muon::MuonSegmentOverlapRemovalTool/MuonSegmentOverlapRemovalTool", this) - { +MuonClusterSegmentFinder::MuonClusterSegmentFinder(const std::string& type, const std::string& name, + const IInterface* parent) + : AthAlgTool(type, name, parent) +{ declareInterface<IMuonClusterSegmentFinder>(this); - - declareProperty("MuonClusterizationTool", m_clusterTool); - declareProperty("MuonEDMPrinterTool",m_printer ); - declareProperty("MuonPRDSelectionTool", m_muonPRDSelectionTool ); - declareProperty("MdtSegmentMaker",m_segmentMaker); - declareProperty("SLFitter", m_slTrackFitter); - declareProperty("TrackToSegmentTool", m_trackToSegmentTool); - declareProperty("AmbiguityProcessor",m_ambiguityProcessor); - declareProperty("DoNtuple",m_doNtuple = false); - declareProperty("TrackCleaner", m_trackCleaner); - - } - - StatusCode MuonClusterSegmentFinder::finalize() { - - if( m_doNtuple ){ - TDirectory* cdir = gDirectory; - m_file->cd(); - m_tree->Write(); - m_file->Write(); - m_file->Close(); - delete m_ntuple; - gDirectory = cdir; + declareProperty("DoNtuple", m_doNtuple = false); +} + +StatusCode +MuonClusterSegmentFinder::finalize() +{ + + if (m_doNtuple) { + TDirectory* cdir = gDirectory; + m_file->cd(); + m_tree->Write(); + m_file->Write(); + m_file->Close(); + delete m_ntuple; + gDirectory = cdir; } return StatusCode::SUCCESS; - } +} - StatusCode MuonClusterSegmentFinder::initialize() { +StatusCode +MuonClusterSegmentFinder::initialize() +{ ATH_CHECK(m_idHelperSvc.retrieve()); ATH_CHECK(m_printer.retrieve()); @@ -74,461 +57,550 @@ namespace Muon { ATH_CHECK(m_trackCleaner.retrieve()); ATH_CHECK(m_segmentOverlapRemovalTool.retrieve()); - if( m_doNtuple ){ - TDirectory* cdir = gDirectory; - m_file = new TFile("ClusterNtuple.root","RECREATE"); - m_tree = new TTree("clusters","clusters"); - m_ntuple = new ClusterSeg::ClusterNtuple(); - m_ntuple->initForWrite(*m_tree); - gDirectory = cdir; - }else{ - m_file = 0; - m_tree = 0; - m_ntuple = 0; + if (m_doNtuple) { + TDirectory* cdir = gDirectory; + m_file = new TFile("ClusterNtuple.root", "RECREATE"); + m_tree = new TTree("clusters", "clusters"); + m_ntuple = new ClusterSeg::ClusterNtuple(); + m_ntuple->initForWrite(*m_tree); + gDirectory = cdir; + } else { + m_file = 0; + m_tree = 0; + m_ntuple = 0; } return StatusCode::SUCCESS; - } - - bool sortfunctionMB (const Trk::MeasurementBase* i, const Trk::MeasurementBase* j){return (fabs(i->globalPosition().z()) < fabs(j->globalPosition().z()));} - bool sortfunctionSP (ClusterSeg::SpacePoint i, ClusterSeg::SpacePoint j){ -return (fabs(i.z()) < fabs(j.z()));} - bool sortfunctionVec (std::pair<int,int> i, std::pair<int,int> j){return (i.second < j.second);} - - bool MuonClusterSegmentFinder::matchTruth(const PRD_MultiTruthCollection& truthCol, const Identifier& id,int& bcode) const { +} + +bool +sortfunctionMB(const Trk::MeasurementBase* i, const Trk::MeasurementBase* j) +{ + return (fabs(i->globalPosition().z()) < fabs(j->globalPosition().z())); +} +bool +sortfunctionSP(ClusterSeg::SpacePoint i, ClusterSeg::SpacePoint j) +{ + return (fabs(i.z()) < fabs(j.z())); +} +bool +sortfunctionVec(std::pair<int, int> i, std::pair<int, int> j) +{ + return (i.second < j.second); +} + +bool +MuonClusterSegmentFinder::matchTruth(const PRD_MultiTruthCollection& truthCol, const Identifier& id, int& bcode) const +{ typedef PRD_MultiTruthCollection::const_iterator iprdt; - std::pair<iprdt, iprdt> range = truthCol.equal_range(id); + std::pair<iprdt, iprdt> range = truthCol.equal_range(id); // Loop over particles contributing to this cluster - for(iprdt i = range.first; i != range.second; i++) { - if(!i->second.isValid()) { - ATH_MSG_INFO( "Unexpected invalid HepMcParticleLink in PRD_MultiTruthCollection" ); - } else { - const HepMcParticleLink& link = i->second; - if( link.cptr() ){ - if (abs(link.cptr()->pdg_id()) == 13 ){ - bcode = link.barcode(); - return true; - } + for (iprdt i = range.first; i != range.second; i++) { + if (!i->second.isValid()) { + ATH_MSG_INFO("Unexpected invalid HepMcParticleLink in PRD_MultiTruthCollection"); + } else { + const HepMcParticleLink& link = i->second; + if (link.cptr()) { + if (abs(link.cptr()->pdg_id()) == 13) { + bcode = link.barcode(); + return true; + } + } } - } } return false; - } - - void MuonClusterSegmentFinder::getClusterSegments(const Muon::MdtPrepDataContainer* mdtPrdCont, - std::vector<const Muon::TgcPrepDataCollection*>* tgcCols, - std::vector<const Muon::RpcPrepDataCollection*>* rpcCols, - const PRD_MultiTruthCollection* tgcTruthColl, const PRD_MultiTruthCollection* rpcTruthColl, - Trk::SegmentCollection* segColl) const { - - if(tgcCols){ - Muon::TgcPrepDataContainer* clusterPRD=new Muon::TgcPrepDataContainer(m_idHelperSvc->tgcIdHelper().module_hash_max()); - for(const auto tgcCol : *tgcCols){ - Muon::TgcPrepDataCollection* clusteredCol = m_clusterTool->cluster(*tgcCol); - if(clusteredCol) clusterPRD->addCollection(clusteredCol, tgcCol->identifyHash() ).ignore(); - } - std::vector<const Muon::TgcPrepDataCollection*> theTGCs; - Muon::TgcPrepDataContainer::const_iterator theIt = clusterPRD->begin(); - int theEmpty(0),contInt(-1); - for (;theIt!=clusterPRD->end();theIt++){ - contInt++; - if ((*theIt)->size() == 0) { - theEmpty++; - } - theTGCs.push_back(*theIt); - } - - findSegments(theTGCs,mdtPrdCont,segColl,tgcTruthColl); - }//end if TGC - - if(rpcCols){ - Muon::RpcPrepDataContainer* clusterPRD=new Muon::RpcPrepDataContainer(m_idHelperSvc->rpcIdHelper().module_hash_max()); - for(const auto rpcCol : *rpcCols){ - Muon::RpcPrepDataCollection* clusteredCol = m_clusterTool->cluster(*rpcCol); - if(clusteredCol) clusterPRD->addCollection(clusteredCol, rpcCol->identifyHash() ).ignore(); - } - std::vector<const Muon::RpcPrepDataCollection*> theRPCs; - Muon::RpcPrepDataContainer::const_iterator theIt = clusterPRD->begin(); - int theEmpty(0),contInt(-1); - for (;theIt!=clusterPRD->end();theIt++){ - contInt++; - if ((*theIt)->size() == 0) { - theEmpty++; - } - theRPCs.push_back(*theIt); - } +} - findSegments(theRPCs,mdtPrdCont,segColl,rpcTruthColl); - }//end if RPC +void +MuonClusterSegmentFinder::getClusterSegments(const Muon::MdtPrepDataContainer* mdtPrdCont, + std::vector<const Muon::TgcPrepDataCollection*>* tgcCols, + std::vector<const Muon::RpcPrepDataCollection*>* rpcCols, + const PRD_MultiTruthCollection* tgcTruthColl, + const PRD_MultiTruthCollection* rpcTruthColl, + Trk::SegmentCollection* segColl) const +{ + + if (tgcCols) { + Muon::TgcPrepDataContainer* clusterPRD = + new Muon::TgcPrepDataContainer(m_idHelperSvc->tgcIdHelper().module_hash_max()); + for (const auto tgcCol : *tgcCols) { + Muon::TgcPrepDataCollection* clusteredCol = m_clusterTool->cluster(*tgcCol); + if (clusteredCol) clusterPRD->addCollection(clusteredCol, tgcCol->identifyHash()).ignore(); + } + std::vector<const Muon::TgcPrepDataCollection*> theTGCs; + Muon::TgcPrepDataContainer::const_iterator theIt = clusterPRD->begin(); + int theEmpty(0), contInt(-1); + for (; theIt != clusterPRD->end(); theIt++) { + contInt++; + if ((*theIt)->size() == 0) { + theEmpty++; + } + theTGCs.push_back(*theIt); + } - } + findSegments(theTGCs, mdtPrdCont, segColl, tgcTruthColl); + } // end if TGC - void MuonClusterSegmentFinder::getClusterSegments(const Muon::MdtPrepDataContainer* mdtPrdCont, - const Muon::RpcPrepDataContainer* rpcPrdCont, const Muon::TgcPrepDataContainer* tgcPrdCont, - const PRD_MultiTruthCollection* tgcTruthColl, const PRD_MultiTruthCollection* rpcTruthColl, - Trk::SegmentCollection* segColl) const { + if (rpcCols) { + Muon::RpcPrepDataContainer* clusterPRD = + new Muon::RpcPrepDataContainer(m_idHelperSvc->rpcIdHelper().module_hash_max()); + for (const auto rpcCol : *rpcCols) { + Muon::RpcPrepDataCollection* clusteredCol = m_clusterTool->cluster(*rpcCol); + if (clusteredCol) clusterPRD->addCollection(clusteredCol, rpcCol->identifyHash()).ignore(); + } + std::vector<const Muon::RpcPrepDataCollection*> theRPCs; + Muon::RpcPrepDataContainer::const_iterator theIt = clusterPRD->begin(); + int theEmpty(0), contInt(-1); + for (; theIt != clusterPRD->end(); theIt++) { + contInt++; + if ((*theIt)->size() == 0) { + theEmpty++; + } + theRPCs.push_back(*theIt); + } - if (tgcPrdCont) { + findSegments(theRPCs, mdtPrdCont, segColl, rpcTruthColl); + } // end if RPC +} - Muon::TgcPrepDataContainer* clusterPRD = m_clusterTool->cluster(*tgcPrdCont); - std::vector<const Muon::TgcPrepDataCollection*> theTGCs; - Muon::TgcPrepDataContainer::const_iterator theIt = clusterPRD->begin(); - int theEmpty(0),contInt(-1); - for (;theIt!=clusterPRD->end();theIt++){ - contInt++; - if ((*theIt)->size() == 0) { - theEmpty++; +void +MuonClusterSegmentFinder::getClusterSegments(const Muon::MdtPrepDataContainer* mdtPrdCont, + const Muon::RpcPrepDataContainer* rpcPrdCont, + const Muon::TgcPrepDataContainer* tgcPrdCont, + const PRD_MultiTruthCollection* tgcTruthColl, + const PRD_MultiTruthCollection* rpcTruthColl, + Trk::SegmentCollection* segColl) const +{ + + if (tgcPrdCont) { + + Muon::TgcPrepDataContainer* clusterPRD = m_clusterTool->cluster(*tgcPrdCont); + std::vector<const Muon::TgcPrepDataCollection*> theTGCs; + Muon::TgcPrepDataContainer::const_iterator theIt = clusterPRD->begin(); + int theEmpty(0), contInt(-1); + for (; theIt != clusterPRD->end(); theIt++) { + contInt++; + if ((*theIt)->size() == 0) { + theEmpty++; + } + theTGCs.push_back(*theIt); } - theTGCs.push_back(*theIt); - } - findSegments(theTGCs,mdtPrdCont,segColl,tgcTruthColl); - }//end if TGC + findSegments(theTGCs, mdtPrdCont, segColl, tgcTruthColl); + } // end if TGC if (rpcPrdCont) { - Muon::RpcPrepDataContainer* clusterPRD = m_clusterTool->cluster(*rpcPrdCont); - std::vector<const Muon::RpcPrepDataCollection*> theRPCs; - Muon::RpcPrepDataContainer::const_iterator theIt = clusterPRD->begin(); - int theEmpty(0),contInt(-1); - for (;theIt!=clusterPRD->end();theIt++){ - contInt++; - if ((*theIt)->size() == 0) { - theEmpty++; + Muon::RpcPrepDataContainer* clusterPRD = m_clusterTool->cluster(*rpcPrdCont); + std::vector<const Muon::RpcPrepDataCollection*> theRPCs; + Muon::RpcPrepDataContainer::const_iterator theIt = clusterPRD->begin(); + int theEmpty(0), contInt(-1); + for (; theIt != clusterPRD->end(); theIt++) { + contInt++; + if ((*theIt)->size() == 0) { + theEmpty++; + } + theRPCs.push_back(*theIt); } - theRPCs.push_back(*theIt); - } - findSegments(theRPCs,mdtPrdCont,segColl,rpcTruthColl); - }//end if rpc + findSegments(theRPCs, mdtPrdCont, segColl, rpcTruthColl); + } // end if rpc +} - } +void +MuonClusterSegmentFinder::findSegments(std::vector<const TgcPrepDataCollection*>& tgcCols, + const Muon::MdtPrepDataContainer* mdtPrdCont, Trk::SegmentCollection* segColl, + const PRD_MultiTruthCollection* tgcTruthColl) const +{ + ATH_MSG_INFO("Executing " << name() << "..."); + ATH_MSG_DEBUG("start with " << segColl->size() << " segments"); - void MuonClusterSegmentFinder::findSegments( std::vector<const TgcPrepDataCollection*>& tgcCols, const Muon::MdtPrepDataContainer* mdtPrdCont, - Trk::SegmentCollection* segColl, const PRD_MultiTruthCollection* tgcTruthColl) const { - ATH_MSG_INFO ("Executing " << name() << "..."); - ATH_MSG_DEBUG("start with "<<segColl->size()<<" segments"); + candEvent* thisEvent = new candEvent; - candEvent* thisEvent = new candEvent; + makeClusterVecs(tgcTruthColl, tgcCols, thisEvent); - makeClusterVecs(tgcTruthColl,tgcCols,thisEvent); - ClusterSeg::ClusterAnalysis theAnalysis; - ATH_MSG_DEBUG("the size of Clust is " << thisEvent->Clust().size() ); + ATH_MSG_DEBUG("the size of Clust is " << thisEvent->Clust().size()); std::vector<std::vector<ClusterSeg::SpacePoint>> sPoints = theAnalysis.analyse(thisEvent->Clust()); - - processSpacePoints(thisEvent,sPoints); - if(thisEvent->segTrkColl()->size() > 0) ATH_MSG_DEBUG( "it made at least one track " ); - else ATH_MSG_DEBUG("processSpacePoints didn't make anything"); - std::map<int,bool> themap; - findOverlap(themap,thisEvent); - resolveCollections(themap,thisEvent); + processSpacePoints(thisEvent, sPoints); + if (thisEvent->segTrkColl()->size() > 0) + ATH_MSG_DEBUG("it made at least one track "); + else + ATH_MSG_DEBUG("processSpacePoints didn't make anything"); + + std::map<int, bool> themap; + findOverlap(themap, thisEvent); + resolveCollections(themap, thisEvent); getSegments(thisEvent, mdtPrdCont, segColl); - ATH_MSG_DEBUG("now have " << segColl->size()<<" segments" ); + ATH_MSG_DEBUG("now have " << segColl->size() << " segments"); if (m_doNtuple) { - m_ntuple->fill(thisEvent->Clust()); - m_tree->Fill(); + m_ntuple->fill(thisEvent->Clust()); + m_tree->Fill(); } delete thisEvent; - } +} + +void +MuonClusterSegmentFinder::findSegments(std::vector<const RpcPrepDataCollection*>& rpcCols, + const Muon::MdtPrepDataContainer* mdtPrdCont, Trk::SegmentCollection* segColl, + const PRD_MultiTruthCollection* rpcTruthColl) const +{ + ATH_MSG_INFO("Executing " << name() << "..."); + ATH_MSG_DEBUG("start with " << segColl->size() << " segments"); - void MuonClusterSegmentFinder::findSegments(std::vector<const RpcPrepDataCollection*>& rpcCols, const Muon::MdtPrepDataContainer* mdtPrdCont, - Trk::SegmentCollection* segColl, const PRD_MultiTruthCollection* rpcTruthColl ) const { - ATH_MSG_INFO ("Executing " << name() << "..."); - ATH_MSG_DEBUG("start with "<<segColl->size()<<" segments"); + candEvent* thisEvent = new candEvent; - candEvent * thisEvent = new candEvent; + makeClusterVecs(rpcTruthColl, rpcCols, thisEvent); - makeClusterVecs(rpcTruthColl,rpcCols,thisEvent); - ClusterSeg::ClusterAnalysis theAnalysis; - ATH_MSG_DEBUG("the size of Clust is " << thisEvent->Clust().size() ); - std::vector<std::vector<ClusterSeg::SpacePoint>> sPoints = theAnalysis.analyse(thisEvent->Clust()); + ATH_MSG_DEBUG("the size of Clust is " << thisEvent->Clust().size()); + std::vector<std::vector<ClusterSeg::SpacePoint>> sPoints = theAnalysis.analyse(thisEvent->Clust()); - processSpacePoints(thisEvent,sPoints); - if(thisEvent->segTrkColl()->size() > 0) ATH_MSG_DEBUG( "it made at least one track " ); - else ATH_MSG_DEBUG("processSpacePoints didn't make anything"); + processSpacePoints(thisEvent, sPoints); + if (thisEvent->segTrkColl()->size() > 0) + ATH_MSG_DEBUG("it made at least one track "); + else + ATH_MSG_DEBUG("processSpacePoints didn't make anything"); - std::map<int,bool> themap; - findOverlap(themap,thisEvent); - resolveCollections(themap,thisEvent); + std::map<int, bool> themap; + findOverlap(themap, thisEvent); + resolveCollections(themap, thisEvent); - getSegments(thisEvent,mdtPrdCont,segColl); + getSegments(thisEvent, mdtPrdCont, segColl); - ATH_MSG_DEBUG("now have " << segColl->size()<<" segments" ); + ATH_MSG_DEBUG("now have " << segColl->size() << " segments"); if (m_doNtuple) { - m_ntuple->fill(thisEvent->Clust()); - m_tree->Fill(); + m_ntuple->fill(thisEvent->Clust()); + m_tree->Fill(); } delete thisEvent; +} - } - - void MuonClusterSegmentFinder::findOverlap(std::map<int,bool>& themap,candEvent * theEvent) const { +void +MuonClusterSegmentFinder::findOverlap(std::map<int, bool>& themap, candEvent* theEvent) const +{ CompareMuonSegmentKeys compareKeys; - if(theEvent->keyVector().size() > 1){ - for (unsigned int i=0;i<theEvent->keyVector().size();i++){themap.insert(std::pair<int,bool>(i,true));} - for(unsigned int i=0;i<theEvent->keyVector().size()-1;i++){ - for(unsigned int j=i+1;j<theEvent->keyVector().size();j++){ - CompareMuonSegmentKeys::OverlapResult overlap = compareKeys(theEvent->keyVector()[i],theEvent->keyVector()[j]); - if(overlap == 0 || overlap == 2) themap[j] = false; - if(overlap == 1) themap[i] = false; + if (theEvent->keyVector().size() > 1) { + for (unsigned int i = 0; i < theEvent->keyVector().size(); i++) { + themap.insert(std::pair<int, bool>(i, true)); + } + for (unsigned int i = 0; i < theEvent->keyVector().size() - 1; i++) { + for (unsigned int j = i + 1; j < theEvent->keyVector().size(); j++) { + CompareMuonSegmentKeys::OverlapResult overlap = + compareKeys(theEvent->keyVector()[i], theEvent->keyVector()[j]); + if (overlap == 0 || overlap == 2) themap[j] = false; + if (overlap == 1) themap[i] = false; + } } - } } - } - - Trk::Track* MuonClusterSegmentFinder::fit( const std::vector<const Trk::MeasurementBase*>& vec2, const Trk::TrackParameters& startpar ) const { - Trk::Track* segtrack = m_slTrackFitter->fit(vec2,startpar,false,Trk::nonInteracting); - - if(segtrack) { - ATH_MSG_DEBUG( "segment fit succeeded"); - - std::unique_ptr<Trk::Track> cleanedTrack = m_trackCleaner->clean(*segtrack); - if( cleanedTrack && !(*cleanedTrack->perigeeParameters() == *segtrack->perigeeParameters()) ){ - delete segtrack; - //using release until the entire code can be migrated to use smart pointers - segtrack = cleanedTrack.release(); - }else{ ATH_MSG_DEBUG("track remains unchanged");} - - - if( !m_edmHelperSvc->goodTrack(*segtrack,30) && vec2.size() > 4) { - if(msgLvl(MSG::DEBUG)) { - ATH_MSG_DEBUG("bad segment fit:"); - if (segtrack->fitQuality()) ATH_MSG_DEBUG("with chi^2/nDoF = " << segtrack->fitQuality()->chiSquared() << "/" << segtrack->fitQuality()->numberDoF()); +} + +Trk::Track* +MuonClusterSegmentFinder::fit(const std::vector<const Trk::MeasurementBase*>& vec2, + const Trk::TrackParameters& startpar) const +{ + Trk::Track* segtrack = m_slTrackFitter->fit(vec2, startpar, false, Trk::nonInteracting); + + if (segtrack) { + ATH_MSG_DEBUG("segment fit succeeded"); + + std::unique_ptr<Trk::Track> cleanedTrack = m_trackCleaner->clean(*segtrack); + if (cleanedTrack && !(*cleanedTrack->perigeeParameters() == *segtrack->perigeeParameters())) { + delete segtrack; + // using release until the entire code can be migrated to use smart pointers + segtrack = cleanedTrack.release(); + } else { + ATH_MSG_DEBUG("track remains unchanged"); + } + + + if (!m_edmHelperSvc->goodTrack(*segtrack, 30) && vec2.size() > 4) { + if (msgLvl(MSG::DEBUG)) { + ATH_MSG_DEBUG("bad segment fit:"); + if (segtrack->fitQuality()) + ATH_MSG_DEBUG("with chi^2/nDoF = " << segtrack->fitQuality()->chiSquared() << "/" + << segtrack->fitQuality()->numberDoF()); + } + delete segtrack; + segtrack = 0; } - delete segtrack; - segtrack = 0; - } } return segtrack; - } - - void MuonClusterSegmentFinder::makeClusterVecs(const std::vector<const Muon::MuonClusterOnTrack*>& clustCol,candEvent* theEvent) const { - for( std::vector<const Muon::MuonClusterOnTrack*>::const_iterator colIt = clustCol.begin(); colIt != clustCol.end(); ++ colIt ){ - const MuonClusterOnTrack* clust = *colIt; - MuonStationIndex::PhiIndex pIndex = m_idHelperSvc->phiIndex(clust->identify()); - bool tmatch(false); - int barcode(0); - if (m_idHelperSvc->measuresPhi( clust->identify())){ - theEvent->clusters().push_back(clust); - ClusterSeg::Cluster* cluster = new ClusterSeg::Cluster(clust->globalPosition().x(),clust->globalPosition().y(),clust->globalPosition().z(),true,MuonStationIndex::TechnologyIndex::TGC,pIndex,tmatch,barcode); - theEvent->Clust().push_back(cluster); - } else { - theEvent->clusters().push_back(clust); - ClusterSeg::Cluster* cluster = new ClusterSeg::Cluster(clust->globalPosition().x(),clust->globalPosition().y(),clust->globalPosition().z(),false,MuonStationIndex::TechnologyIndex::TGC,pIndex,tmatch,barcode); - theEvent->Clust().push_back(cluster); - } - } - } - - void MuonClusterSegmentFinder::makeClusterVecs(const PRD_MultiTruthCollection* truthCollectionTGC, const std::vector<const TgcPrepDataCollection*>& tgcCols,candEvent* theEvent) const { - for( std::vector<const TgcPrepDataCollection*>::const_iterator colIt = tgcCols.begin(); colIt != tgcCols.end(); ++ colIt ){ - TgcPrepDataCollection::const_iterator pit = (*colIt)->begin(); - for(; pit!=(*colIt)->end(); ++pit) { - const MuonCluster* cl = *pit; - if( !cl ) continue; - bool tmatch = false; - int barcode = 0; - if(truthCollectionTGC){ - const Identifier& id = (*pit)->identify(); - tmatch = matchTruth(*truthCollectionTGC,id,barcode); - } - const MuonClusterOnTrack* clust = m_clusterCreator->createRIO_OnTrack( *cl, cl->globalPosition() ); +} + +void +MuonClusterSegmentFinder::makeClusterVecs(const std::vector<const Muon::MuonClusterOnTrack*>& clustCol, + candEvent* theEvent) const +{ + for (std::vector<const Muon::MuonClusterOnTrack*>::const_iterator colIt = clustCol.begin(); colIt != clustCol.end(); + ++colIt) + { + const MuonClusterOnTrack* clust = *colIt; MuonStationIndex::PhiIndex pIndex = m_idHelperSvc->phiIndex(clust->identify()); - if (m_idHelperSvc->measuresPhi( clust->identify())){ - theEvent->clusters().push_back(clust); - ClusterSeg::Cluster* cluster = new ClusterSeg::Cluster(clust->globalPosition().x(),clust->globalPosition().y(),clust->globalPosition().z(),true,MuonStationIndex::TechnologyIndex::TGC,pIndex,tmatch,barcode); - theEvent->Clust().push_back(cluster); + bool tmatch(false); + int barcode(0); + if (m_idHelperSvc->measuresPhi(clust->identify())) { + theEvent->clusters().push_back(clust); + ClusterSeg::Cluster* cluster = new ClusterSeg::Cluster( + clust->globalPosition().x(), clust->globalPosition().y(), clust->globalPosition().z(), true, + MuonStationIndex::TechnologyIndex::TGC, pIndex, tmatch, barcode); + theEvent->Clust().push_back(cluster); } else { - theEvent->clusters().push_back(clust); - ClusterSeg::Cluster* cluster = new ClusterSeg::Cluster(clust->globalPosition().x(),clust->globalPosition().y(),clust->globalPosition().z(),false,MuonStationIndex::TechnologyIndex::TGC,pIndex,tmatch,barcode); - theEvent->Clust().push_back(cluster); + theEvent->clusters().push_back(clust); + ClusterSeg::Cluster* cluster = new ClusterSeg::Cluster( + clust->globalPosition().x(), clust->globalPosition().y(), clust->globalPosition().z(), false, + MuonStationIndex::TechnologyIndex::TGC, pIndex, tmatch, barcode); + theEvent->Clust().push_back(cluster); } - } - } - } - - void MuonClusterSegmentFinder::makeClusterVecs(const PRD_MultiTruthCollection* truthCollectionRPC, const std::vector<const RpcPrepDataCollection*>& rpcCols,candEvent* theEvent) const { - for( std::vector<const RpcPrepDataCollection*>::const_iterator colIt = rpcCols.begin(); colIt != rpcCols.end(); ++ colIt ){ - RpcPrepDataCollection::const_iterator pit = (*colIt)->begin(); - for(; pit!=(*colIt)->end(); ++pit) { - const MuonCluster* cl = *pit; - if( !cl ) continue; - bool tmatch = false; - int barcode = 0; - if(truthCollectionRPC){ - const Identifier& id = (*pit)->identify(); - tmatch = matchTruth(*truthCollectionRPC,id,barcode); + } +} + +void +MuonClusterSegmentFinder::makeClusterVecs(const PRD_MultiTruthCollection* truthCollectionTGC, + const std::vector<const TgcPrepDataCollection*>& tgcCols, + candEvent* theEvent) const +{ + for (std::vector<const TgcPrepDataCollection*>::const_iterator colIt = tgcCols.begin(); colIt != tgcCols.end(); + ++colIt) { + TgcPrepDataCollection::const_iterator pit = (*colIt)->begin(); + for (; pit != (*colIt)->end(); ++pit) { + const MuonCluster* cl = *pit; + if (!cl) continue; + bool tmatch = false; + int barcode = 0; + if (truthCollectionTGC) { + const Identifier& id = (*pit)->identify(); + tmatch = matchTruth(*truthCollectionTGC, id, barcode); + } + const MuonClusterOnTrack* clust = m_clusterCreator->createRIO_OnTrack(*cl, cl->globalPosition()); + MuonStationIndex::PhiIndex pIndex = m_idHelperSvc->phiIndex(clust->identify()); + if (m_idHelperSvc->measuresPhi(clust->identify())) { + theEvent->clusters().push_back(clust); + ClusterSeg::Cluster* cluster = new ClusterSeg::Cluster( + clust->globalPosition().x(), clust->globalPosition().y(), clust->globalPosition().z(), true, + MuonStationIndex::TechnologyIndex::TGC, pIndex, tmatch, barcode); + theEvent->Clust().push_back(cluster); + } else { + theEvent->clusters().push_back(clust); + ClusterSeg::Cluster* cluster = new ClusterSeg::Cluster( + clust->globalPosition().x(), clust->globalPosition().y(), clust->globalPosition().z(), false, + MuonStationIndex::TechnologyIndex::TGC, pIndex, tmatch, barcode); + theEvent->Clust().push_back(cluster); + } } - const MuonClusterOnTrack* clust = m_clusterCreator->createRIO_OnTrack( *cl, cl->globalPosition() ); - MuonStationIndex::PhiIndex pIndex = m_idHelperSvc->phiIndex(clust->identify()); - if (m_idHelperSvc->measuresPhi( clust->identify())){ - theEvent->clusters().push_back(clust); - ClusterSeg::Cluster* cluster = new ClusterSeg::Cluster(clust->globalPosition().x(),clust->globalPosition().y(),clust->globalPosition().z(),true,MuonStationIndex::TechnologyIndex::RPC,pIndex,tmatch,barcode); - theEvent->Clust().push_back(cluster); - } else { - theEvent->clusters().push_back(clust); - ClusterSeg::Cluster* cluster = new ClusterSeg::Cluster(clust->globalPosition().x(),clust->globalPosition().y(),clust->globalPosition().z(),false,MuonStationIndex::TechnologyIndex::RPC,pIndex,tmatch,barcode); - theEvent->Clust().push_back(cluster); + } +} + +void +MuonClusterSegmentFinder::makeClusterVecs(const PRD_MultiTruthCollection* truthCollectionRPC, + const std::vector<const RpcPrepDataCollection*>& rpcCols, + candEvent* theEvent) const +{ + for (std::vector<const RpcPrepDataCollection*>::const_iterator colIt = rpcCols.begin(); colIt != rpcCols.end(); + ++colIt) { + RpcPrepDataCollection::const_iterator pit = (*colIt)->begin(); + for (; pit != (*colIt)->end(); ++pit) { + const MuonCluster* cl = *pit; + if (!cl) continue; + bool tmatch = false; + int barcode = 0; + if (truthCollectionRPC) { + const Identifier& id = (*pit)->identify(); + tmatch = matchTruth(*truthCollectionRPC, id, barcode); + } + const MuonClusterOnTrack* clust = m_clusterCreator->createRIO_OnTrack(*cl, cl->globalPosition()); + MuonStationIndex::PhiIndex pIndex = m_idHelperSvc->phiIndex(clust->identify()); + if (m_idHelperSvc->measuresPhi(clust->identify())) { + theEvent->clusters().push_back(clust); + ClusterSeg::Cluster* cluster = new ClusterSeg::Cluster( + clust->globalPosition().x(), clust->globalPosition().y(), clust->globalPosition().z(), true, + MuonStationIndex::TechnologyIndex::RPC, pIndex, tmatch, barcode); + theEvent->Clust().push_back(cluster); + } else { + theEvent->clusters().push_back(clust); + ClusterSeg::Cluster* cluster = new ClusterSeg::Cluster( + clust->globalPosition().x(), clust->globalPosition().y(), clust->globalPosition().z(), false, + MuonStationIndex::TechnologyIndex::RPC, pIndex, tmatch, barcode); + theEvent->Clust().push_back(cluster); + } } - } } - } - - void MuonClusterSegmentFinder::processSpacePoints(candEvent* theEvent, std::vector<std::vector<ClusterSeg::SpacePoint>>& sPoints) const { - bool truthSeed(true); - int fakeCounter(0); +} + +void +MuonClusterSegmentFinder::processSpacePoints(candEvent* theEvent, + std::vector<std::vector<ClusterSeg::SpacePoint>>& sPoints) const +{ + bool truthSeed(true); + int fakeCounter(0); unsigned int barcodeCounter(0); - int barcodeVal(0); - - for(const std::vector<ClusterSeg::SpacePoint>& sit : sPoints){ - if (sit.size() < 2) continue; - std::vector<const MuonClusterOnTrack*> vec1; - std::vector<const Trk::MeasurementBase*> vec2; - - for(unsigned int i=0;i<sit.size();i++){ - int spEit = sit[i].eit(); - vec1.push_back(theEvent->clusters()[spEit]); - vec2.push_back(theEvent->clusters()[spEit]); - int spPit = sit[i].pit(); - vec1.push_back(theEvent->clusters()[spPit]); - vec2.push_back(theEvent->clusters()[spPit]); - if (!(sit[i].isMatch())) fakeCounter++; - else if (barcodeCounter == 0) { - barcodeVal = sit[i].barcode(); - barcodeCounter++; - } else if (barcodeVal == sit[i].barcode()) barcodeCounter++; - } - - if (fakeCounter != 0) truthSeed = false; - std::sort (vec2.begin(),vec2.end(), sortfunctionMB); - Trk::TrackParameters* startpar = 0; - Amg::Vector3D gp(sit.front().x(),sit.front().y(),sit.front().z()); - Amg::Vector3D gd(sit.back().x()-sit.front().x(),sit.back().y()-sit.front().y(),sit.back().z()-sit.front().z()); - Amg::Vector3D perpos = gp + -10*(gd.unit()); - if(perpos.dot(gd) < 0) gd = -1*gd; - startpar = new Trk::Perigee(perpos, gd, 0, perpos); - ATH_MSG_DEBUG("It is starting a fit with " << vec2.size() << "Measurement Base elements and " << startpar ); - Trk::Track* segtrack = fit(vec2,*startpar); - delete startpar; - if(segtrack) { - MuonSegmentKey keyEntry = MuonSegmentKey(vec2); - theEvent->keyVector().push_back(keyEntry); - double chi2 = segtrack->fitQuality()->chiSquared(); - double dof = segtrack->fitQuality()->doubleNumberDoF(); - if( m_ntuple ){ - if(truthSeed) m_ntuple->fill(chi2/dof,ClusterSeg::FillType::chi2T); - m_ntuple->fill(chi2/dof,ClusterSeg::FillType::chi2); + int barcodeVal(0); + + for (const std::vector<ClusterSeg::SpacePoint>& sit : sPoints) { + if (sit.size() < 2) continue; + std::vector<const MuonClusterOnTrack*> vec1; + std::vector<const Trk::MeasurementBase*> vec2; + + for (unsigned int i = 0; i < sit.size(); i++) { + int spEit = sit[i].eit(); + vec1.push_back(theEvent->clusters()[spEit]); + vec2.push_back(theEvent->clusters()[spEit]); + int spPit = sit[i].pit(); + vec1.push_back(theEvent->clusters()[spPit]); + vec2.push_back(theEvent->clusters()[spPit]); + if (!(sit[i].isMatch())) + fakeCounter++; + else if (barcodeCounter == 0) { + barcodeVal = sit[i].barcode(); + barcodeCounter++; + } else if (barcodeVal == sit[i].barcode()) + barcodeCounter++; + } + + if (fakeCounter != 0) truthSeed = false; + std::sort(vec2.begin(), vec2.end(), sortfunctionMB); + Trk::TrackParameters* startpar = 0; + Amg::Vector3D gp(sit.front().x(), sit.front().y(), sit.front().z()); + Amg::Vector3D gd(sit.back().x() - sit.front().x(), sit.back().y() - sit.front().y(), + sit.back().z() - sit.front().z()); + Amg::Vector3D perpos = gp + -10 * (gd.unit()); + if (perpos.dot(gd) < 0) gd = -1 * gd; + startpar = new Trk::Perigee(perpos, gd, 0, perpos); + ATH_MSG_DEBUG("It is starting a fit with " << vec2.size() << "Measurement Base elements and " << startpar); + Trk::Track* segtrack = fit(vec2, *startpar); + delete startpar; + if (segtrack) { + MuonSegmentKey keyEntry = MuonSegmentKey(vec2); + theEvent->keyVector().push_back(keyEntry); + double chi2 = segtrack->fitQuality()->chiSquared(); + double dof = segtrack->fitQuality()->doubleNumberDoF(); + if (m_ntuple) { + if (truthSeed) m_ntuple->fill(chi2 / dof, ClusterSeg::FillType::chi2T); + m_ntuple->fill(chi2 / dof, ClusterSeg::FillType::chi2); + } + ATH_MSG_DEBUG("the chi2 is " << chi2 << "the dof are " << dof << " and the chi2/dof is " << chi2 / dof); + theEvent->segTrkColl()->push_back(segtrack); + theEvent->trackSeeds().push_back(std::make_pair(gp, gd)); + theEvent->hits().push_back(vec1); + } else { + ATH_MSG_DEBUG("segment fit failed"); } - ATH_MSG_DEBUG( "the chi2 is " << chi2 << "the dof are " << dof << " and the chi2/dof is " << chi2/dof ); - theEvent->segTrkColl()->push_back(segtrack); - theEvent->trackSeeds().push_back(std::make_pair(gp,gd)); - theEvent->hits().push_back(vec1); - } else { - ATH_MSG_DEBUG( "segment fit failed" ); - } } - } - - void MuonClusterSegmentFinder::resolveCollections(std::map<int,bool> themap,candEvent* theEvent) const { - for(unsigned int i=0;i<theEvent->keyVector().size();i++){ - if (themap[i] == true ){ - theEvent->resolvedTrackSeeds().push_back(std::make_pair(theEvent->trackSeeds()[i].first,theEvent->trackSeeds()[i].second)); - theEvent->resolvedhits().push_back(theEvent->hits()[i]); - theEvent->resolvedTracks()->push_back(new Trk::Track(*(theEvent->segTrkColl()->at(i)))); - } +} + +void +MuonClusterSegmentFinder::resolveCollections(std::map<int, bool> themap, candEvent* theEvent) const +{ + for (unsigned int i = 0; i < theEvent->keyVector().size(); i++) { + if (themap[i] == true) { + theEvent->resolvedTrackSeeds().push_back( + std::make_pair(theEvent->trackSeeds()[i].first, theEvent->trackSeeds()[i].second)); + theEvent->resolvedhits().push_back(theEvent->hits()[i]); + theEvent->resolvedTracks()->push_back(new Trk::Track(*(theEvent->segTrkColl()->at(i)))); + } } - if(theEvent->keyVector().size() == 1) { - theEvent->resolvedTrackSeeds().push_back(std::make_pair(theEvent->trackSeeds()[0].first,theEvent->trackSeeds()[0].second)); - theEvent->resolvedhits().push_back(theEvent->hits()[0]); - theEvent->resolvedTracks()->push_back(new Trk::Track(*(theEvent->segTrkColl()->at(0)))); + if (theEvent->keyVector().size() == 1) { + theEvent->resolvedTrackSeeds().push_back( + std::make_pair(theEvent->trackSeeds()[0].first, theEvent->trackSeeds()[0].second)); + theEvent->resolvedhits().push_back(theEvent->hits()[0]); + theEvent->resolvedTracks()->push_back(new Trk::Track(*(theEvent->segTrkColl()->at(0)))); } - ATH_MSG_DEBUG("Resolved track candidates: old size " << theEvent->segTrkColl()->size() << " new size " << theEvent->resolvedTracks()->size() ); - } - - void MuonClusterSegmentFinder::getSegments(candEvent* theEvent, const Muon::MdtPrepDataContainer* mdtPrdCont, Trk::SegmentCollection* segColl) const { + ATH_MSG_DEBUG("Resolved track candidates: old size " << theEvent->segTrkColl()->size() << " new size " + << theEvent->resolvedTracks()->size()); +} + +void +MuonClusterSegmentFinder::getSegments(candEvent* theEvent, const Muon::MdtPrepDataContainer* mdtPrdCont, + Trk::SegmentCollection* segColl) const +{ + + std::vector<const Muon::MuonSegment*> appendSegments; - std::vector<const Muon::MuonSegment*> appendSegments; - const std::vector<const Muon::MuonClusterOnTrack*> MCOTs; - for(unsigned int i=0;i<theEvent->resolvedTracks()->size();i++){ - - const DataVector<const Trk::TrackParameters>* tpVec = theEvent->resolvedTracks()->at(i)->trackParameters(); - if( !tpVec || tpVec->empty() || !tpVec->front() ) continue; - const Trk::TrackParameters& startPars = *tpVec->front(); - - const std::vector<const MuonClusterOnTrack*>& MCOTs = const_cast<const std::vector<const MuonClusterOnTrack*>&>(theEvent->resolvedhits()[i]); - if( MCOTs.empty() ) continue; - - - const Identifier& id = MCOTs.front()->identify(); - MuonStationIndex::DetectorRegionIndex regionIndex = m_idHelperSvc->regionIndex(id); - MuonStationIndex::LayerIndex layerIndex = m_idHelperSvc->layerIndex(id); - - MuonLayerSurface::SurfacePtr surfacePtr(startPars.associatedSurface().clone()); - std::shared_ptr<const Trk::TrackParameters> parsPtr(startPars.clone()); - - // get sectors and loop over them - std::vector<int> sectors; - theEvent->sectorMapping().getSectors(startPars.position().phi(),sectors); - for( auto sector : sectors ){ - - MuonLayerSurface layerSurface( surfacePtr, sector, regionIndex, layerIndex ) ; - MuonSystemExtension::Intersection intersection( parsPtr, layerSurface); - - std::vector<const MdtPrepDataCollection*> mdtCols; - if( !getLayerData( sector, regionIndex, layerIndex, mdtPrdCont, mdtCols ) ){ - ATH_MSG_DEBUG("Failed to get MDT PRD collections "); - continue; - } - std::vector<const Muon::MdtDriftCircleOnTrack*> MDTs; - for( auto mdtCol : mdtCols ){ - if( !m_muonPRDSelectionTool->calibrateAndSelectMdt( intersection, *mdtCol, MDTs ) ) { - ATH_MSG_DEBUG("Failed to calibrate MDT PRD collection "); - continue; - } + for (unsigned int i = 0; i < theEvent->resolvedTracks()->size(); i++) { + + const DataVector<const Trk::TrackParameters>* tpVec = theEvent->resolvedTracks()->at(i)->trackParameters(); + if (!tpVec || tpVec->empty() || !tpVec->front()) continue; + const Trk::TrackParameters& startPars = *tpVec->front(); + + const std::vector<const MuonClusterOnTrack*>& MCOTs = + const_cast<const std::vector<const MuonClusterOnTrack*>&>(theEvent->resolvedhits()[i]); + if (MCOTs.empty()) continue; + + + const Identifier& id = MCOTs.front()->identify(); + MuonStationIndex::DetectorRegionIndex regionIndex = m_idHelperSvc->regionIndex(id); + MuonStationIndex::LayerIndex layerIndex = m_idHelperSvc->layerIndex(id); + + MuonLayerSurface::SurfacePtr surfacePtr(startPars.associatedSurface().clone()); + std::shared_ptr<const Trk::TrackParameters> parsPtr(startPars.clone()); + + // get sectors and loop over them + std::vector<int> sectors; + theEvent->sectorMapping().getSectors(startPars.position().phi(), sectors); + for (auto sector : sectors) { + + MuonLayerSurface layerSurface(surfacePtr, sector, regionIndex, layerIndex); + MuonSystemExtension::Intersection intersection(parsPtr, layerSurface); + + std::vector<const MdtPrepDataCollection*> mdtCols; + if (!getLayerData(sector, regionIndex, layerIndex, mdtPrdCont, mdtCols)) { + ATH_MSG_DEBUG("Failed to get MDT PRD collections "); + continue; + } + std::vector<const Muon::MdtDriftCircleOnTrack*> MDTs; + for (auto mdtCol : mdtCols) { + if (!m_muonPRDSelectionTool->calibrateAndSelectMdt(intersection, *mdtCol, MDTs)) { + ATH_MSG_DEBUG("Failed to calibrate MDT PRD collection "); + continue; + } + } + ATH_MSG_DEBUG("Running mdt segment finding: MDTs " << MDTs.size() << " MCOTs " << MCOTs.size()); + m_segmentMaker->find(theEvent->resolvedTrackSeeds()[i].first, theEvent->resolvedTrackSeeds()[i].second, + MDTs, MCOTs, false, segColl); + ATH_MSG_DEBUG("the size of the segment collection is " << segColl->size()); + for (unsigned int j = 0; j < segColl->size(); j++) { + Trk::Segment* tseg = segColl->at(j); + ATH_MSG_DEBUG("the " << j << "th segment contains " + << (dynamic_cast<MuonSegment*>(tseg))->numberOfContainedROTs() << " ROTs "); + } } - ATH_MSG_DEBUG("Running mdt segment finding: MDTs " << MDTs.size() << " MCOTs " << MCOTs.size()); - m_segmentMaker->find(theEvent->resolvedTrackSeeds()[i].first,theEvent->resolvedTrackSeeds()[i].second,MDTs,MCOTs,false,segColl); - ATH_MSG_DEBUG( "the size of the segment collection is " << segColl->size() ); - for(unsigned int j = 0;j< segColl->size();j++){ - Trk::Segment* tseg=segColl->at(j); - ATH_MSG_DEBUG( "the " << j << "th segment contains " << (dynamic_cast<MuonSegment*>(tseg))->numberOfContainedROTs() << " ROTs " ); - } - } } - } +} - bool MuonClusterSegmentFinder::getLayerData( int sector, MuonStationIndex::DetectorRegionIndex regionIndex,MuonStationIndex::LayerIndex layerIndex, - const Muon::MdtPrepDataContainer* input, std::vector<const MdtPrepDataCollection*>& output ) const { +bool +MuonClusterSegmentFinder::getLayerData(int sector, MuonStationIndex::DetectorRegionIndex regionIndex, + MuonStationIndex::LayerIndex layerIndex, const Muon::MdtPrepDataContainer* input, + std::vector<const MdtPrepDataCollection*>& output) const +{ // get technologies in the given layer - unsigned int sectorLayerHash = MuonStationIndex::sectorLayerHash( regionIndex, layerIndex ); + unsigned int sectorLayerHash = MuonStationIndex::sectorLayerHash(regionIndex, layerIndex); // get hashes - const MuonLayerHashProviderTool::HashVec& hashes = m_layerHashProvider->getHashes( sector, MuonStationIndex::TechnologyIndex::MDT, sectorLayerHash ); + const MuonLayerHashProviderTool::HashVec& hashes = + m_layerHashProvider->getHashes(sector, MuonStationIndex::TechnologyIndex::MDT, sectorLayerHash); // skip empty inputs - if( hashes.empty() ) return true; + if (hashes.empty()) return true; // loop over hashes - for( MuonLayerHashProviderTool::HashVec::const_iterator it=hashes.begin();it!=hashes.end();++it ){ - // skip if not found - auto col = input->indexFindPtr(*it); - if( col == nullptr ) { - //ATH_MSG_WARNING("Cannot find hash " << *it << " in container at " << location); - continue; - } - ATH_MSG_VERBOSE(" adding " << m_idHelperSvc->toStringChamber(col->identify()) << " size " << col->size()); - // else add - output.push_back(col); + for (MuonLayerHashProviderTool::HashVec::const_iterator it = hashes.begin(); it != hashes.end(); ++it) { + // skip if not found + auto col = input->indexFindPtr(*it); + if (col == nullptr) { + // ATH_MSG_WARNING("Cannot find hash " << *it << " in container at " << location); + continue; + } + ATH_MSG_VERBOSE(" adding " << m_idHelperSvc->toStringChamber(col->identify()) << " size " << col->size()); + // else add + output.push_back(col); } return true; - } } +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonClusterSegmentMakerTools/src/MuonClusterSegmentFinder.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonClusterSegmentMakerTools/src/MuonClusterSegmentFinder.h index ca3ef42404f313a8c49fd56a078cafac4e4514a0..9bf038e080477e14d63786b176106e98b650f006 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonClusterSegmentMakerTools/src/MuonClusterSegmentFinder.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonClusterSegmentMakerTools/src/MuonClusterSegmentFinder.h @@ -5,144 +5,233 @@ #ifndef MUON_MUONCLUSTERSEGMENTFINDER_H #define MUON_MUONCLUSTERSEGMENTFINDER_H -#include "MuonSegmentMakerToolInterfaces/IMuonClusterSegmentFinder.h" +#include <string> +#include <vector> + #include "AthenaBaseComps/AthAlgTool.h" #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" - +#include "MuonClusterization/IMuonClusterizationTool.h" +#include "MuonDetDescrUtils/MuonSectorMapping.h" #include "MuonIdHelpers/IMuonIdHelperSvc.h" -#include "MuonRecToolInterfaces/IMuonClusterOnTrackCreator.h" -#include "MuonRecHelperTools/MuonEDMPrinterTool.h" +#include "MuonLinearSegmentMakerUtilities/ClusterNtuple.h" +#include "MuonPrepRawData/MuonCluster.h" +#include "MuonPrepRawData/RpcPrepDataCollection.h" +#include "MuonPrepRawData/TgcPrepDataCollection.h" +#include "MuonPrepRawDataProviderTools/MuonLayerHashProviderTool.h" +#include "MuonRIO_OnTrack/MuonClusterOnTrack.h" #include "MuonRecHelperTools/IMuonEDMHelperSvc.h" -#include "TrkFitterInterfaces/ITrackFitter.h" -#include "TrkToolInterfaces/ITrackAmbiguityProcessorTool.h" +#include "MuonRecHelperTools/MuonEDMPrinterTool.h" +#include "MuonRecToolInterfaces/IMuonClusterOnTrackCreator.h" +#include "MuonRecToolInterfaces/IMuonPRDSelectionTool.h" +#include "MuonRecToolInterfaces/IMuonSegmentMaker.h" #include "MuonRecToolInterfaces/IMuonTrackCleaner.h" #include "MuonRecToolInterfaces/IMuonTrackToSegmentTool.h" -#include "MuonRecToolInterfaces/IMuonSegmentMaker.h" -#include "MuonSegmentMakerToolInterfaces/IMuonSegmentOverlapRemovalTool.h" -#include "MuonRecToolInterfaces/IMuonPRDSelectionTool.h" -#include "MuonClusterization/IMuonClusterizationTool.h" -#include "MuonPrepRawDataProviderTools/MuonLayerHashProviderTool.h" #include "MuonSegment/MuonSegment.h" -#include "MuonPrepRawData/MuonCluster.h" -#include "MuonRIO_OnTrack/MuonClusterOnTrack.h" -#include "TrkTruthData/PRD_MultiTruthCollection.h" -#include "TrkTrack/Track.h" -#include "TrkTrack/TrackCollection.h" -#include "MuonDetDescrUtils/MuonSectorMapping.h" -#include "MuonSegmentMakerUtils/MuonSegmentKey.h" +#include "MuonSegmentMakerToolInterfaces/IMuonClusterSegmentFinder.h" +#include "MuonSegmentMakerToolInterfaces/IMuonSegmentOverlapRemovalTool.h" #include "MuonSegmentMakerUtils/CompareMuonSegmentKeys.h" -#include "MuonPrepRawData/RpcPrepDataCollection.h" -#include "MuonPrepRawData/TgcPrepDataCollection.h" +#include "MuonSegmentMakerUtils/MuonSegmentKey.h" +#include "TrkFitterInterfaces/ITrackFitter.h" #include "TrkParameters/TrackParameters.h" -#include "MuonLinearSegmentMakerUtilities/ClusterNtuple.h" - -#include <string> -#include <vector> +#include "TrkToolInterfaces/ITrackAmbiguityProcessorTool.h" +#include "TrkTrack/Track.h" +#include "TrkTrack/TrackCollection.h" +#include "TrkTruthData/PRD_MultiTruthCollection.h" class TTree; class TFile; namespace Trk { - class Track; - class MeasurementBase; -} +class Track; +class MeasurementBase; +} // namespace Trk namespace Muon { - struct candEvent { +struct candEvent { + + candEvent() : m_segTrkColl(new TrackCollection), m_resolvedTracks(new TrackCollection) {} + ~candEvent() + { + delete m_segTrkColl; + delete m_resolvedTracks; + } - candEvent() : m_segTrkColl(new TrackCollection),m_resolvedTracks(new TrackCollection) {} - ~candEvent(){ - delete m_segTrkColl; - delete m_resolvedTracks; + TrackCollection* segTrkColl() + { + return m_segTrkColl; + } + std::vector<const MuonClusterOnTrack*>& clusters() + { + return m_clusters; + } + std::vector<ClusterSeg::Cluster*>& Clust() + { + return m_Clust; + } + std::vector<std::vector<const MuonClusterOnTrack*>>& hits() + { + return m_hits; + } + std::vector<std::pair<Amg::Vector3D, Amg::Vector3D>>& trackSeeds() + { + return m_trackSeeds; + } + std::vector<MuonSegmentKey>& keyVector() + { + return m_keyVector; + } + std::vector<std::vector<ClusterSeg::SpacePoint>>& SPoints() + { + return m_SPoints; + } + MuonSectorMapping& sectorMapping() + { + return m_sectorMapping; + } + TrackCollection* resolvedTracks() + { + return m_resolvedTracks; + } + std::vector<std::pair<Amg::Vector3D, Amg::Vector3D>>& resolvedTrackSeeds() + { + return m_resolvedTrackSeeds; + } + std::vector<std::vector<const MuonClusterOnTrack*>>& resolvedhits() + { + return m_resolvedhits; } - TrackCollection* segTrkColl(){return m_segTrkColl;} - std::vector<const MuonClusterOnTrack*>& clusters(){return m_clusters;} - std::vector<ClusterSeg::Cluster*>& Clust(){return m_Clust;} - std::vector<std::vector<const MuonClusterOnTrack*>>& hits(){return m_hits;} - std::vector<std::pair<Amg::Vector3D,Amg::Vector3D>>& trackSeeds(){return m_trackSeeds;} - std::vector<MuonSegmentKey>& keyVector(){return m_keyVector;} - std::vector<std::vector<ClusterSeg::SpacePoint>>& SPoints(){return m_SPoints;} - MuonSectorMapping& sectorMapping(){return m_sectorMapping;} - TrackCollection* resolvedTracks(){return m_resolvedTracks;} - std::vector<std::pair<Amg::Vector3D,Amg::Vector3D>>& resolvedTrackSeeds(){return m_resolvedTrackSeeds;} - std::vector<std::vector<const MuonClusterOnTrack*>>& resolvedhits(){return m_resolvedhits;} - - TrackCollection* m_segTrkColl; - std::vector<const MuonClusterOnTrack*> m_clusters; - std::vector<ClusterSeg::Cluster*> m_Clust; - std::vector<std::vector<const MuonClusterOnTrack*>> m_hits; - std::vector<std::pair<Amg::Vector3D,Amg::Vector3D>> m_trackSeeds; - std::vector<MuonSegmentKey> m_keyVector; - std::vector<std::vector<ClusterSeg::SpacePoint>> m_SPoints; - MuonSectorMapping m_sectorMapping; - TrackCollection* m_resolvedTracks; - std::vector<std::pair<Amg::Vector3D,Amg::Vector3D>> m_resolvedTrackSeeds; - std::vector<std::vector<const MuonClusterOnTrack*>> m_resolvedhits; - }; - - class MuonClusterSegmentFinder : virtual public IMuonClusterSegmentFinder, public AthAlgTool{ + TrackCollection* m_segTrkColl; + std::vector<const MuonClusterOnTrack*> m_clusters; + std::vector<ClusterSeg::Cluster*> m_Clust; + std::vector<std::vector<const MuonClusterOnTrack*>> m_hits; + std::vector<std::pair<Amg::Vector3D, Amg::Vector3D>> m_trackSeeds; + std::vector<MuonSegmentKey> m_keyVector; + std::vector<std::vector<ClusterSeg::SpacePoint>> m_SPoints; + MuonSectorMapping m_sectorMapping; + TrackCollection* m_resolvedTracks; + std::vector<std::pair<Amg::Vector3D, Amg::Vector3D>> m_resolvedTrackSeeds; + std::vector<std::vector<const MuonClusterOnTrack*>> m_resolvedhits; +}; + +class MuonClusterSegmentFinder : virtual public IMuonClusterSegmentFinder, public AthAlgTool { public: /** Default AlgTool functions */ MuonClusterSegmentFinder(const std::string& type, const std::string& name, const IInterface* parent); - virtual ~MuonClusterSegmentFinder()=default; + virtual ~MuonClusterSegmentFinder() = default; StatusCode initialize(); StatusCode finalize(); - void getClusterSegments(const Muon::MdtPrepDataContainer* mdtPrdCont, - const Muon::RpcPrepDataContainer* rpcPrdCont, const Muon::TgcPrepDataContainer* tgcPrdCont, - const PRD_MultiTruthCollection* tgcTruthColl, const PRD_MultiTruthCollection* rpcTruthColl, - Trk::SegmentCollection* segColl) const; + void getClusterSegments(const Muon::MdtPrepDataContainer* mdtPrdCont, const Muon::RpcPrepDataContainer* rpcPrdCont, + const Muon::TgcPrepDataContainer* tgcPrdCont, const PRD_MultiTruthCollection* tgcTruthColl, + const PRD_MultiTruthCollection* rpcTruthColl, Trk::SegmentCollection* segColl) const; - void getClusterSegments(const Muon::MdtPrepDataContainer* mdtPrdCont, - std::vector<const Muon::TgcPrepDataCollection*>* tgcCols, std::vector<const Muon::RpcPrepDataCollection*>* rpcCols, - const PRD_MultiTruthCollection* tgcTruthColl, const PRD_MultiTruthCollection* rpcTruthColl, - Trk::SegmentCollection* segColl) const; + void getClusterSegments(const Muon::MdtPrepDataContainer* mdtPrdCont, + std::vector<const Muon::TgcPrepDataCollection*>* tgcCols, + std::vector<const Muon::RpcPrepDataCollection*>* rpcCols, + const PRD_MultiTruthCollection* tgcTruthColl, const PRD_MultiTruthCollection* rpcTruthColl, + Trk::SegmentCollection* segColl) const; /** tgc segment finding */ - void findSegments(std::vector<const TgcPrepDataCollection*>& tgcCols, const Muon::MdtPrepDataContainer* mdtPrdCont, Trk::SegmentCollection* segColl, - const PRD_MultiTruthCollection* tgcTruthColl) const; + void findSegments(std::vector<const TgcPrepDataCollection*>& tgcCols, const Muon::MdtPrepDataContainer* mdtPrdCont, + Trk::SegmentCollection* segColl, const PRD_MultiTruthCollection* tgcTruthColl) const; /** rpc segment finding */ - void findSegments(std::vector<const RpcPrepDataCollection*>& rpcCols, const Muon::MdtPrepDataContainer* mdtPrdCont, Trk::SegmentCollection* segColl, - const PRD_MultiTruthCollection* tgcTruthColl) const; + void findSegments(std::vector<const RpcPrepDataCollection*>& rpcCols, const Muon::MdtPrepDataContainer* mdtPrdCont, + Trk::SegmentCollection* segColl, const PRD_MultiTruthCollection* tgcTruthColl) const; private: - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - ToolHandle<MuonEDMPrinterTool> m_printer; - ToolHandle<MuonLayerHashProviderTool> m_layerHashProvider; - ToolHandle<IMuonPRDSelectionTool> m_muonPRDSelectionTool; - ToolHandle<IMuonSegmentMaker> m_segmentMaker; - ToolHandle<Muon::IMuonClusterizationTool> m_clusterTool; //<! clustering tool - ToolHandle<IMuonClusterOnTrackCreator> m_clusterCreator; - ToolHandle<IMuonTrackToSegmentTool> m_trackToSegmentTool; //<! track to segment converter - ToolHandle<Trk::ITrackFitter> m_slTrackFitter; //<! fitter, always use straightline - ToolHandle<Trk::ITrackAmbiguityProcessorTool> m_ambiguityProcessor; //!< Tool for ambiguity solving - ServiceHandle<IMuonEDMHelperSvc> m_edmHelperSvc {this, "edmHelper", - "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", - "Handle to the service providing the IMuonEDMHelperSvc interface" }; //<! Id helper tool - ToolHandle<IMuonTrackCleaner> m_trackCleaner; - ToolHandle<IMuonSegmentOverlapRemovalTool> m_segmentOverlapRemovalTool; - - bool m_doNtuple; - TFile* m_file; - TTree* m_tree; + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; + ServiceHandle<IMuonEDMHelperSvc> m_edmHelperSvc{ + this, + "edmHelper", + "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", + "Handle to the service providing the IMuonEDMHelperSvc interface", + }; //<! Id helper tool + + ToolHandle<MuonEDMPrinterTool> m_printer{ + this, + "MuonEDMPrinterTool", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; + ToolHandle<MuonLayerHashProviderTool> m_layerHashProvider{ + this, + "MuonLayerHashProviderTool", + "Muon::MuonLayerHashProviderTool/MuonLayerHashProviderTool", + }; + ToolHandle<IMuonPRDSelectionTool> m_muonPRDSelectionTool{ + this, + "MuonPRDSelectionTool", + "Muon::MuonPRDSelectionTool/MuonPRDSelectionTool", + }; + ToolHandle<IMuonSegmentMaker> m_segmentMaker{ + this, + "MdtSegmentMaker", + "Muon::DCMathSegmentMaker/DCMathSegmentMaker", + }; + ToolHandle<Muon::IMuonClusterizationTool> m_clusterTool{ + this, + "MuonClusterizationTool", + "Muon::MuonClusterizationTool/MuonClusterizationTool", + }; //<! clustering tool + ToolHandle<IMuonClusterOnTrackCreator> m_clusterCreator{ + this, + "MuonClusterOnTrackCreator", + "Muon::MuonClusterOnTrackCreator/MuonClusterOnTrackCreator", + }; + ToolHandle<IMuonTrackToSegmentTool> m_trackToSegmentTool{ + this, + "TrackToSegmentTool", + "Muon::MuonTrackToSegmentTool/MuonTrackToSegmentTool", + }; //<! track to segment converter + ToolHandle<Trk::ITrackFitter> m_slTrackFitter{ + this, + "SLFitter", + "Trk::GlobalChi2Fitter/MCTBSLFitter", + }; //<! fitter, always use straightline + ToolHandle<Trk::ITrackAmbiguityProcessorTool> m_ambiguityProcessor{ + this, + "AmbiguityProcessor", + "Trk::TrackSelectionProcessorTool/MuonAmbiProcessor", + }; //!< Tool for ambiguity solving + ToolHandle<IMuonTrackCleaner> m_trackCleaner{ + this, + "TrackCleaner", + "Muon::MuonTrackCleaner/MuonTrackCleaner", + }; + ToolHandle<IMuonSegmentOverlapRemovalTool> m_segmentOverlapRemovalTool{ + this, + "MuonSegmentOverlapRemovalTool", + "Muon::MuonSegmentOverlapRemovalTool/MuonSegmentOverlapRemovalTool", + }; + + bool m_doNtuple; + TFile* m_file; + TTree* m_tree; ClusterSeg::ClusterNtuple* m_ntuple; - bool matchTruth(const PRD_MultiTruthCollection& truthCol, const Identifier& id, int& barcode) const; - Trk::Track* fit( const std::vector<const Trk::MeasurementBase*>& vec2, const Trk::TrackParameters& startpar ) const; + bool matchTruth(const PRD_MultiTruthCollection& truthCol, const Identifier& id, int& barcode) const; + Trk::Track* fit(const std::vector<const Trk::MeasurementBase*>& vec2, const Trk::TrackParameters& startpar) const; void makeClusterVecs(const std::vector<const Muon::MuonClusterOnTrack*>& clustCol, candEvent* theEvent) const; - void makeClusterVecs(const PRD_MultiTruthCollection* truthCollectionTGC, const std::vector<const TgcPrepDataCollection*>& tgcCols, candEvent* theEvent) const; - void makeClusterVecs(const PRD_MultiTruthCollection* truthCollectionRPC, const std::vector<const RpcPrepDataCollection*>& rpcCols, candEvent* theEvent) const; - void findOverlap(std::map<int,bool>& themap,candEvent* theEvent) const; - void processSpacePoints(candEvent* theEvent,std::vector<std::vector<ClusterSeg::SpacePoint>>& sPoints) const; - void resolveCollections(std::map<int,bool> themap,candEvent* theEvent) const; - void getSegments(candEvent* theEvent, const Muon::MdtPrepDataContainer* mdtPrdCont, Trk::SegmentCollection* segColl) const; - bool getLayerData( int sector, MuonStationIndex::DetectorRegionIndex regionIndex, MuonStationIndex::LayerIndex layerIndex, - const Muon::MdtPrepDataContainer* input, std::vector<const MdtPrepDataCollection*>& output ) const; - }; - -} + void makeClusterVecs(const PRD_MultiTruthCollection* truthCollectionTGC, + const std::vector<const TgcPrepDataCollection*>& tgcCols, candEvent* theEvent) const; + void makeClusterVecs(const PRD_MultiTruthCollection* truthCollectionRPC, + const std::vector<const RpcPrepDataCollection*>& rpcCols, candEvent* theEvent) const; + void findOverlap(std::map<int, bool>& themap, candEvent* theEvent) const; + void processSpacePoints(candEvent* theEvent, std::vector<std::vector<ClusterSeg::SpacePoint>>& sPoints) const; + void resolveCollections(std::map<int, bool> themap, candEvent* theEvent) const; + void getSegments(candEvent* theEvent, const Muon::MdtPrepDataContainer* mdtPrdCont, + Trk::SegmentCollection* segColl) const; + bool getLayerData(int sector, MuonStationIndex::DetectorRegionIndex regionIndex, + MuonStationIndex::LayerIndex layerIndex, const Muon::MdtPrepDataContainer* input, + std::vector<const MdtPrepDataCollection*>& output) const; +}; + +} // namespace Muon #endif diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonLayerSegmentMakerTools/src/MuonLayerSegmentFinderTool.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonLayerSegmentMakerTools/src/MuonLayerSegmentFinderTool.cxx index a0176cd7aa7b3807b1f597716f5340006e156d98..b04820e76eb7a3caab0c09f039a32574cf0eaf68 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonLayerSegmentMakerTools/src/MuonLayerSegmentFinderTool.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonLayerSegmentMakerTools/src/MuonLayerSegmentFinderTool.cxx @@ -4,41 +4,27 @@ #include "MuonLayerSegmentFinderTool.h" -#include "MuonPrepRawDataProviderTools/MuonPrepRawDataCollectionProviderTool.h" +#include "EventPrimitives/EventPrimitivesHelpers.h" #include "MuonLayerHough/MuonLayerHough.h" -#include "TrkSegment/SegmentCollection.h" -#include "MuonSegment/MuonSegment.h" +#include "MuonPrepRawDataProviderTools/MuonPrepRawDataCollectionProviderTool.h" #include "MuonRIO_OnTrack/MdtDriftCircleOnTrack.h" #include "MuonRIO_OnTrack/MuonClusterOnTrack.h" -#include "EventPrimitives/EventPrimitivesHelpers.h" +#include "MuonSegment/MuonSegment.h" +#include "TrkSegment/SegmentCollection.h" namespace Muon { - MuonLayerSegmentFinderTool::MuonLayerSegmentFinderTool(const std::string& type, const std::string& name, const IInterface* parent): - AthAlgTool(type,name,parent), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"), - m_muonPRDSelectionTool("Muon::MuonPRDSelectionTool/MuonPRDSelectionTool"), - m_segmentMaker("Muon::DCMathSegmentMaker/DCMathSegmentMaker"), - m_csc2dSegmentFinder("Csc2dSegmentMaker/Csc2dSegmentMaker"), - m_csc4dSegmentFinder("Csc4dSegmentMaker/Csc4dSegmentMaker"), - m_clusterSegmentFinder("Muon::MuonClusterSegmentFinder/MuonClusterSegmentFinder"), - m_clusterSegMakerNSW("Muon::MuonClusterSegmentFinderTool/MuonClusterSegmentFinderTool"), - m_recoValidationTool("") // ("Muon::MuonRecoValidationTool/MuonRecoValidationTool") - - { +MuonLayerSegmentFinderTool::MuonLayerSegmentFinderTool(const std::string& type, const std::string& name, + const IInterface* parent) + : AthAlgTool(type, name, parent) + +{ declareInterface<IMuonLayerSegmentFinderTool>(this); +} - declareProperty("MuonEDMPrinterTool",m_printer ); - declareProperty("MuonPRDSelectionTool", m_muonPRDSelectionTool ); - declareProperty("SegmentMaker",m_segmentMaker); - declareProperty("Csc2DSegmentMaker",m_csc2dSegmentFinder); - declareProperty("Csc4DSegmentMaker",m_csc4dSegmentFinder); - declareProperty("MuonClusterSegmentFinder",m_clusterSegmentFinder); - declareProperty("NSWMuonClusterSegmentFinderTool",m_clusterSegMakerNSW); - declareProperty("MuonRecoValidationTool",m_recoValidationTool); - } - - StatusCode MuonLayerSegmentFinderTool::initialize() { +StatusCode +MuonLayerSegmentFinderTool::initialize() +{ ATH_CHECK(m_idHelperSvc.retrieve()); ATH_CHECK(m_printer.retrieve()); ATH_CHECK(m_muonPRDSelectionTool.retrieve()); @@ -47,63 +33,73 @@ namespace Muon { if (m_idHelperSvc->hasCSC() && !m_csc4dSegmentFinder.empty()) ATH_CHECK(m_csc4dSegmentFinder.retrieve()); ATH_CHECK(m_clusterSegmentFinder.retrieve()); ATH_CHECK(m_clusterSegMakerNSW.retrieve()); - if( !m_recoValidationTool.empty() ) ATH_CHECK(m_recoValidationTool.retrieve()); + if (!m_recoValidationTool.empty()) ATH_CHECK(m_recoValidationTool.retrieve()); ATH_CHECK(m_houghDataPerSectorVecKey.initialize()); return StatusCode::SUCCESS; - } - - void MuonLayerSegmentFinderTool::find( const MuonSystemExtension::Intersection& intersection, std::vector< std::shared_ptr<const Muon::MuonSegment> >& segments, - MuonLayerPrepRawData& layerPrepRawData ) const { +} - ATH_MSG_VERBOSE(" Running segment finding in sector " << intersection.layerSurface.sector - << " region " << MuonStationIndex::regionName(intersection.layerSurface.regionIndex) - << " layer " << MuonStationIndex::layerName(intersection.layerSurface.layerIndex) - << " intersection position: r " << intersection.trackParameters->position().perp() << " z " << intersection.trackParameters->position().z() - << " locX " << intersection.trackParameters->parameters()[Trk::locX] << " locY " << intersection.trackParameters->parameters()[Trk::locY] - << " phi " << intersection.trackParameters->position().phi() ); +void +MuonLayerSegmentFinderTool::find(const MuonSystemExtension::Intersection& intersection, + std::vector<std::shared_ptr<const Muon::MuonSegment> >& segments, + MuonLayerPrepRawData& layerPrepRawData) const +{ + + ATH_MSG_VERBOSE(" Running segment finding in sector " + << intersection.layerSurface.sector << " region " + << MuonStationIndex::regionName(intersection.layerSurface.regionIndex) << " layer " + << MuonStationIndex::layerName(intersection.layerSurface.layerIndex) << " intersection position: r " + << intersection.trackParameters->position().perp() << " z " + << intersection.trackParameters->position().z() << " locX " + << intersection.trackParameters->parameters()[Trk::locX] << " locY " + << intersection.trackParameters->parameters()[Trk::locY] << " phi " + << intersection.trackParameters->position().phi()); // run cluster hit based segment finding on PRDs - findClusterSegments(intersection,layerPrepRawData,segments); - ATH_MSG_VERBOSE(" findClusterSegments " << segments.size() ); + findClusterSegments(intersection, layerPrepRawData, segments); + ATH_MSG_VERBOSE(" findClusterSegments " << segments.size()); // run standard MDT/Trigger hit segment finding either from Hough or hits - findMdtSegments(intersection,layerPrepRawData,segments); - } + findMdtSegments(intersection, layerPrepRawData, segments); +} - void MuonLayerSegmentFinderTool::findMdtSegmentsFromHough( const MuonSystemExtension::Intersection& intersection, - const MuonLayerPrepRawData& /*layerPrepRawData*/, - std::vector< std::shared_ptr<const Muon::MuonSegment> >& segments ) const { +void +MuonLayerSegmentFinderTool::findMdtSegmentsFromHough( + const MuonSystemExtension::Intersection& intersection, const MuonLayerPrepRawData& /*layerPrepRawData*/, + std::vector<std::shared_ptr<const Muon::MuonSegment> >& segments) const +{ - unsigned int nprevSegments = segments.size(); // keep track of what is already there - int sector = intersection.layerSurface.sector; - MuonStationIndex::DetectorRegionIndex regionIndex = intersection.layerSurface.regionIndex; - MuonStationIndex::LayerIndex layerIndex = intersection.layerSurface.layerIndex; + unsigned int nprevSegments = segments.size(); // keep track of what is already there + int sector = intersection.layerSurface.sector; + MuonStationIndex::DetectorRegionIndex regionIndex = intersection.layerSurface.regionIndex; + MuonStationIndex::LayerIndex layerIndex = intersection.layerSurface.layerIndex; // get hough data - SG::ReadHandle<MuonLayerHoughTool::HoughDataPerSectorVec> houghDataPerSectorVec {m_houghDataPerSectorVecKey}; + SG::ReadHandle<MuonLayerHoughTool::HoughDataPerSectorVec> houghDataPerSectorVec{m_houghDataPerSectorVecKey}; if (!houghDataPerSectorVec.isValid()) { - ATH_MSG_ERROR("Hough data per sector vector not found"); - return; + ATH_MSG_ERROR("Hough data per sector vector not found"); + return; } // sanity check - if( static_cast<int>(houghDataPerSectorVec->vec.size()) <= sector-1 ){ - ATH_MSG_WARNING(" MuonLayerHoughTool::HoughDataPerSectorVec smaller than sector " << houghDataPerSectorVec->vec.size() - << " sector " << sector ); - return; + if (static_cast<int>(houghDataPerSectorVec->vec.size()) <= sector - 1) { + ATH_MSG_WARNING(" MuonLayerHoughTool::HoughDataPerSectorVec smaller than sector " + << houghDataPerSectorVec->vec.size() << " sector " << sector); + return; } // get hough maxima in the layer - unsigned int sectorLayerHash = MuonStationIndex::sectorLayerHash( regionIndex,layerIndex ); - const MuonLayerHoughTool::HoughDataPerSector& houghDataPerSector = houghDataPerSectorVec->vec[sector-1]; - ATH_MSG_DEBUG(" findMdtSegmentsFromHough: sector " << sector << " " << MuonStationIndex::regionName(regionIndex) - << " " << MuonStationIndex::layerName(layerIndex) << " sector hash " << sectorLayerHash - << " houghData " << houghDataPerSectorVec->vec.size() << " " << houghDataPerSector.maxVec.size()); + unsigned int sectorLayerHash = MuonStationIndex::sectorLayerHash(regionIndex, layerIndex); + const MuonLayerHoughTool::HoughDataPerSector& houghDataPerSector = houghDataPerSectorVec->vec[sector - 1]; + ATH_MSG_DEBUG(" findMdtSegmentsFromHough: sector " + << sector << " " << MuonStationIndex::regionName(regionIndex) << " " + << MuonStationIndex::layerName(layerIndex) << " sector hash " << sectorLayerHash << " houghData " + << houghDataPerSectorVec->vec.size() << " " << houghDataPerSector.maxVec.size()); // sanity check - if( houghDataPerSector.maxVec.size() <= sectorLayerHash ){ - ATH_MSG_WARNING(" houghDataPerSector.maxVec.size() smaller than hash " << houghDataPerSector.maxVec.size() << " hash " << sectorLayerHash ); - return; + if (houghDataPerSector.maxVec.size() <= sectorLayerHash) { + ATH_MSG_WARNING(" houghDataPerSector.maxVec.size() smaller than hash " << houghDataPerSector.maxVec.size() + << " hash " << sectorLayerHash); + return; } const MuonLayerHoughTool::MaximumVec& maxVec = houghDataPerSector.maxVec[sectorLayerHash]; @@ -113,252 +109,265 @@ namespace Muon { float phi = intersection.trackParameters->position().phi(); // in the endcaps take the r in the sector frame from the local position of the extrapolation - float r = barrelLike ? - m_muonSectorMapping.transformRToSector(intersection.trackParameters->position().perp(),phi, intersection.layerSurface.sector,true) : - intersection.trackParameters->parameters()[Trk::locX]; + float r = barrelLike ? m_muonSectorMapping.transformRToSector(intersection.trackParameters->position().perp(), phi, + intersection.layerSurface.sector, true) + : intersection.trackParameters->parameters()[Trk::locX]; - float z = intersection.trackParameters->position().z(); - float errx = Amg::error(*intersection.trackParameters->covariance(),Trk::locX); - float x = barrelLike ? r : z; - float y = barrelLike ? z : r; - float theta = atan2(x,y); + float z = intersection.trackParameters->position().z(); + float errx = Amg::error(*intersection.trackParameters->covariance(), Trk::locX); + float x = barrelLike ? r : z; + float y = barrelLike ? z : r; + float theta = atan2(x, y); - ATH_MSG_DEBUG(" Got Hough maxima " << maxVec.size() << " extrapolated position in Hough space (" << x << "," << y - << ") error " << errx << " " << " angle " << theta ); + ATH_MSG_DEBUG(" Got Hough maxima " << maxVec.size() << " extrapolated position in Hough space (" << x << "," << y + << ") error " << errx << " " + << " angle " << theta); // lambda to handle calibration and selection of MDTs - auto handleMdt = [this,intersection](const MdtPrepData& prd, std::vector<const MdtDriftCircleOnTrack*>& mdts){ - const MdtDriftCircleOnTrack* mdt = m_muonPRDSelectionTool->calibrateAndSelect( intersection, prd ); - if( mdt ) mdts.push_back(mdt); + auto handleMdt = [this, intersection](const MdtPrepData& prd, std::vector<const MdtDriftCircleOnTrack*>& mdts) { + const MdtDriftCircleOnTrack* mdt = m_muonPRDSelectionTool->calibrateAndSelect(intersection, prd); + if (mdt) mdts.push_back(mdt); }; // lambda to handle calibration and selection of clusters - auto handleCluster = [this,intersection](const MuonCluster& prd, std::vector<const MuonClusterOnTrack*>& clusters){ - const MuonClusterOnTrack* cluster = m_muonPRDSelectionTool->calibrateAndSelect( intersection, prd ); - if( cluster ) clusters.push_back(cluster); + auto handleCluster = [this, intersection](const MuonCluster& prd, + std::vector<const MuonClusterOnTrack*>& clusters) { + const MuonClusterOnTrack* cluster = m_muonPRDSelectionTool->calibrateAndSelect(intersection, prd); + if (cluster) clusters.push_back(cluster); }; - // loop over maxima and associate them to the extrapolation - MuonLayerHoughTool::MaximumVec::const_iterator mit = maxVec.begin(); + MuonLayerHoughTool::MaximumVec::const_iterator mit = maxVec.begin(); MuonLayerHoughTool::MaximumVec::const_iterator mit_end = maxVec.end(); - for( ;mit!=mit_end;++mit){ - const MuonHough::MuonLayerHough::Maximum& maximum = **mit; - float residual = maximum.pos - y; - float residualTheta = maximum.theta - theta; - float refPos = (maximum.hough != nullptr) ? maximum.hough->m_descriptor.referencePosition : 0; - float maxwidth = (maximum.binposmax-maximum.binposmin); - if( maximum.hough ) maxwidth *= maximum.hough->m_binsize; - float pull = residual/sqrt(errx*errx+maxwidth*maxwidth/12.); - - // fill validation content - if( !m_recoValidationTool.empty() ) m_recoValidationTool->add( intersection, maximum ); - - ATH_MSG_DEBUG(" Hough maximum " << maximum.max << " position (" << refPos - << "," << maximum.pos << ") residual " << residual << " pull " << pull - << " angle " << maximum.theta << " residual " << residualTheta ); - - // select maximum - if( std::abs(pull) > 5 ) continue; - - // loop over hits in maximum and add them to the hit list - std::vector<const MdtDriftCircleOnTrack*> mdts; - std::vector<const MuonClusterOnTrack*> clusters; - std::vector<MuonHough::Hit*>::const_iterator hit = maximum.hits.begin(); - std::vector<MuonHough::Hit*>::const_iterator hit_end = maximum.hits.end(); - for( ;hit!=hit_end;++hit ) { - - // treat the case that the hit is a composite TGC hit - if( (*hit)->tgc ){ - for( const auto& prd : (*hit)->tgc->etaCluster.hitList ) handleCluster(*prd,clusters); - }else if( (*hit)->prd ){ - Identifier id = (*hit)->prd->identify(); - if( m_idHelperSvc->isMdt(id) ) handleMdt( static_cast<const MdtPrepData&>(*(*hit)->prd),mdts); - else handleCluster( static_cast<const MuonCluster&>(*(*hit)->prd),clusters); - } - } - - // get phi hits - const MuonLayerHoughTool::PhiMaximumVec& phiMaxVec = houghDataPerSector.phiMaxVec[intersection.layerSurface.regionIndex]; - ATH_MSG_DEBUG(" Got Phi Hough maxima " << phiMaxVec.size() << " phi " << phi ); - - // loop over maxima and associate them to the extrapolation - MuonLayerHoughTool::PhiMaximumVec::const_iterator pit = phiMaxVec.begin(); - MuonLayerHoughTool::PhiMaximumVec::const_iterator pit_end = phiMaxVec.end(); - for( ;pit!=pit_end;++pit){ - const MuonHough::MuonPhiLayerHough::Maximum& maximum = **pit; - float residual = maximum.pos - phi; - if( residual > 2*M_PI ) residual -= 2*M_PI; - if( residual < -2*M_PI ) residual += 2*M_PI; - - ATH_MSG_DEBUG(" Phi Hough maximum " << maximum.max << " phi " << maximum.pos << ") angle " << maximum.pos - << " residual " << residual ); - - std::vector<MuonHough::PhiHit*>::const_iterator hit = maximum.hits.begin(); - std::vector<MuonHough::PhiHit*>::const_iterator hit_end = maximum.hits.end(); - for( ;hit!=hit_end;++hit ) { - // treat the case that the hit is a composite TGC hit - if( (*hit)->tgc && !(*hit)->tgc->phiCluster.hitList.empty() ){ - Identifier id = (*hit)->tgc->phiCluster.hitList.front()->identify(); - if( m_idHelperSvc->layerIndex(id) != intersection.layerSurface.layerIndex ) continue; - for( const auto& prd : (*hit)->tgc->phiCluster.hitList ) handleCluster(*prd,clusters); - }else if( (*hit)->prd ){ - Identifier id = (*hit)->prd->identify(); - if( m_idHelperSvc->layerIndex(id) != intersection.layerSurface.layerIndex ) continue; - handleCluster( static_cast<const MuonCluster&>(*(*hit)->prd),clusters); - } + for (; mit != mit_end; ++mit) { + const MuonHough::MuonLayerHough::Maximum& maximum = **mit; + float residual = maximum.pos - y; + float residualTheta = maximum.theta - theta; + float refPos = (maximum.hough != nullptr) ? maximum.hough->m_descriptor.referencePosition : 0; + float maxwidth = (maximum.binposmax - maximum.binposmin); + if (maximum.hough) maxwidth *= maximum.hough->m_binsize; + float pull = residual / sqrt(errx * errx + maxwidth * maxwidth / 12.); + + // fill validation content + if (!m_recoValidationTool.empty()) m_recoValidationTool->add(intersection, maximum); + + ATH_MSG_DEBUG(" Hough maximum " << maximum.max << " position (" << refPos << "," << maximum.pos + << ") residual " << residual << " pull " << pull << " angle " << maximum.theta + << " residual " << residualTheta); + + // select maximum + if (std::abs(pull) > 5) continue; + + // loop over hits in maximum and add them to the hit list + std::vector<const MdtDriftCircleOnTrack*> mdts; + std::vector<const MuonClusterOnTrack*> clusters; + std::vector<MuonHough::Hit*>::const_iterator hit = maximum.hits.begin(); + std::vector<MuonHough::Hit*>::const_iterator hit_end = maximum.hits.end(); + for (; hit != hit_end; ++hit) { + + // treat the case that the hit is a composite TGC hit + if ((*hit)->tgc) { + for (const auto& prd : (*hit)->tgc->etaCluster.hitList) handleCluster(*prd, clusters); + } else if ((*hit)->prd) { + Identifier id = (*hit)->prd->identify(); + if (m_idHelperSvc->isMdt(id)) + handleMdt(static_cast<const MdtPrepData&>(*(*hit)->prd), mdts); + else + handleCluster(static_cast<const MuonCluster&>(*(*hit)->prd), clusters); + } } - } - // call segment finder - ATH_MSG_DEBUG(" Got hits: mdts " << mdts.size() << " clusters " << clusters.size() ); - findMdtSegments(intersection,mdts,clusters,segments); + // get phi hits + const MuonLayerHoughTool::PhiMaximumVec& phiMaxVec = + houghDataPerSector.phiMaxVec[intersection.layerSurface.regionIndex]; + ATH_MSG_DEBUG(" Got Phi Hough maxima " << phiMaxVec.size() << " phi " << phi); + + // loop over maxima and associate them to the extrapolation + MuonLayerHoughTool::PhiMaximumVec::const_iterator pit = phiMaxVec.begin(); + MuonLayerHoughTool::PhiMaximumVec::const_iterator pit_end = phiMaxVec.end(); + for (; pit != pit_end; ++pit) { + const MuonHough::MuonPhiLayerHough::Maximum& maximum = **pit; + float residual = maximum.pos - phi; + if (residual > 2 * M_PI) residual -= 2 * M_PI; + if (residual < -2 * M_PI) residual += 2 * M_PI; + + ATH_MSG_DEBUG(" Phi Hough maximum " << maximum.max << " phi " << maximum.pos << ") angle " + << maximum.pos << " residual " << residual); + + std::vector<MuonHough::PhiHit*>::const_iterator hit = maximum.hits.begin(); + std::vector<MuonHough::PhiHit*>::const_iterator hit_end = maximum.hits.end(); + for (; hit != hit_end; ++hit) { + // treat the case that the hit is a composite TGC hit + if ((*hit)->tgc && !(*hit)->tgc->phiCluster.hitList.empty()) { + Identifier id = (*hit)->tgc->phiCluster.hitList.front()->identify(); + if (m_idHelperSvc->layerIndex(id) != intersection.layerSurface.layerIndex) continue; + for (const auto& prd : (*hit)->tgc->phiCluster.hitList) handleCluster(*prd, clusters); + } else if ((*hit)->prd) { + Identifier id = (*hit)->prd->identify(); + if (m_idHelperSvc->layerIndex(id) != intersection.layerSurface.layerIndex) continue; + handleCluster(static_cast<const MuonCluster&>(*(*hit)->prd), clusters); + } + } + } - // clean-up memory - for( auto hit : mdts ) delete hit; - for( auto hit : clusters ) delete hit; - ATH_MSG_DEBUG(" Done maximum: new segments " << segments.size()-nprevSegments ); + // call segment finder + ATH_MSG_DEBUG(" Got hits: mdts " << mdts.size() << " clusters " << clusters.size()); + findMdtSegments(intersection, mdts, clusters, segments); + // clean-up memory + for (auto hit : mdts) delete hit; + for (auto hit : clusters) delete hit; + ATH_MSG_DEBUG(" Done maximum: new segments " << segments.size() - nprevSegments); } - ATH_MSG_DEBUG(" Done with layer: new segments " << segments.size()-nprevSegments ); + ATH_MSG_DEBUG(" Done with layer: new segments " << segments.size() - nprevSegments); return; - } +} - void MuonLayerSegmentFinderTool::findMdtSegments( const MuonSystemExtension::Intersection& intersection, - const MuonLayerPrepRawData& layerPrepRawData, - std::vector< std::shared_ptr<const Muon::MuonSegment> >& segments ) const { +void +MuonLayerSegmentFinderTool::findMdtSegments(const MuonSystemExtension::Intersection& intersection, + const MuonLayerPrepRawData& layerPrepRawData, + std::vector<std::shared_ptr<const Muon::MuonSegment> >& segments) const +{ // calibrate what is already there MuonLayerROTs layerROTs; - if( !m_muonPRDSelectionTool->calibrateAndSelect( intersection, layerPrepRawData, layerROTs ) ){ - ATH_MSG_WARNING("Failed to calibrate and select layer data"); - return; + if (!m_muonPRDSelectionTool->calibrateAndSelect(intersection, layerPrepRawData, layerROTs)) { + ATH_MSG_WARNING("Failed to calibrate and select layer data"); + return; } // get hits - MuonStationIndex::TechnologyIndex clusterTech = intersection.layerSurface.regionIndex == MuonStationIndex::Barrel ? MuonStationIndex::RPC : MuonStationIndex::TGC; - const std::vector<const MdtDriftCircleOnTrack*>& mdts = layerROTs.getMdts(); + MuonStationIndex::TechnologyIndex clusterTech = intersection.layerSurface.regionIndex == MuonStationIndex::Barrel + ? MuonStationIndex::RPC + : MuonStationIndex::TGC; + const std::vector<const MdtDriftCircleOnTrack*>& mdts = layerROTs.getMdts(); const std::vector<const MuonClusterOnTrack*>& clusters = layerROTs.getClusters(clusterTech); - findMdtSegments(intersection,mdts,clusters,segments); - } + findMdtSegments(intersection, mdts, clusters, segments); +} - void MuonLayerSegmentFinderTool::findMdtSegments( const MuonSystemExtension::Intersection& intersection, - const std::vector<const MdtDriftCircleOnTrack*>& mdts, - const std::vector<const MuonClusterOnTrack*>& clusters, - std::vector< std::shared_ptr<const Muon::MuonSegment> >& segments ) const { +void +MuonLayerSegmentFinderTool::findMdtSegments(const MuonSystemExtension::Intersection& intersection, + const std::vector<const MdtDriftCircleOnTrack*>& mdts, + const std::vector<const MuonClusterOnTrack*>& clusters, + std::vector<std::shared_ptr<const Muon::MuonSegment> >& segments) const +{ // require at least 2 MDT hits - if( mdts.size() > 2 ){ - - // run segment finder - std::unique_ptr<Trk::SegmentCollection> segColl(new Trk::SegmentCollection(SG::VIEW_ELEMENTS)); - m_segmentMaker->find( intersection.trackParameters->position(),intersection.trackParameters->momentum(), - mdts, clusters, - !clusters.empty(), segColl.get(), intersection.trackParameters->momentum().mag() ); - - if( segColl ){ - Trk::SegmentCollection::iterator sit = segColl->begin(); - Trk::SegmentCollection::iterator sit_end = segColl->end(); - for( ; sit!=sit_end;++sit){ - Trk::Segment* tseg=*sit; - MuonSegment* mseg=dynamic_cast<MuonSegment*>(tseg); - ATH_MSG_DEBUG( " " << m_printer->print(*mseg)); - segments.push_back( std::shared_ptr<const MuonSegment>(mseg) ); + if (mdts.size() > 2) { + + // run segment finder + std::unique_ptr<Trk::SegmentCollection> segColl(new Trk::SegmentCollection(SG::VIEW_ELEMENTS)); + m_segmentMaker->find(intersection.trackParameters->position(), intersection.trackParameters->momentum(), mdts, + clusters, !clusters.empty(), segColl.get(), + intersection.trackParameters->momentum().mag()); + + if (segColl) { + Trk::SegmentCollection::iterator sit = segColl->begin(); + Trk::SegmentCollection::iterator sit_end = segColl->end(); + for (; sit != sit_end; ++sit) { + Trk::Segment* tseg = *sit; + MuonSegment* mseg = dynamic_cast<MuonSegment*>(tseg); + ATH_MSG_DEBUG(" " << m_printer->print(*mseg)); + segments.push_back(std::shared_ptr<const MuonSegment>(mseg)); + } } - } } - } +} - void MuonLayerSegmentFinderTool::findClusterSegments( const MuonSystemExtension::Intersection& intersection, - const MuonLayerPrepRawData& layerPrepRawData, - std::vector< std::shared_ptr<const Muon::MuonSegment> >& segments ) const { +void +MuonLayerSegmentFinderTool::findClusterSegments(const MuonSystemExtension::Intersection& intersection, + const MuonLayerPrepRawData& layerPrepRawData, + std::vector<std::shared_ptr<const Muon::MuonSegment> >& segments) const +{ // if there are CSC hits run CSC segment finding - if( !layerPrepRawData.cscs.empty() ) findCscSegments(layerPrepRawData,segments); + if (!layerPrepRawData.cscs.empty()) findCscSegments(layerPrepRawData, segments); // find TGC segments - //if( !layerPrepRawData.tgcs.empty() && intersection.layerSurface.layerIndex == MuonStationIndex::Middle ) { + // if( !layerPrepRawData.tgcs.empty() && intersection.layerSurface.layerIndex == MuonStationIndex::Middle ) { // m_clusterSegmentFinder->findSegments(layerPrepRawData.tgcs,segments); //} - if( layerPrepRawData.stgcs.empty() && layerPrepRawData.mms.empty() ) return; + if (layerPrepRawData.stgcs.empty() && layerPrepRawData.mms.empty()) return; // NSW segment finding MuonLayerROTs layerROTs; - if( !m_muonPRDSelectionTool->calibrateAndSelect( intersection, layerPrepRawData, layerROTs ) ){ + if (!m_muonPRDSelectionTool->calibrateAndSelect(intersection, layerPrepRawData, layerROTs)) { ATH_MSG_WARNING("Failed to calibrate and select layer data"); - return; + return; } - ATH_MSG_DEBUG( " MM prds " << layerPrepRawData.mms.size() << " STGC prds " << layerPrepRawData.stgcs.size()); + ATH_MSG_DEBUG(" MM prds " << layerPrepRawData.mms.size() << " STGC prds " << layerPrepRawData.stgcs.size()); - // get STGC and MM clusters - const std::vector<const MuonClusterOnTrack*>& clustersSTGC = layerROTs.getClusters(MuonStationIndex::STGC); - const std::vector<const MuonClusterOnTrack*>& clustersMM = layerROTs.getClusters(MuonStationIndex::MM); + // get STGC and MM clusters + const std::vector<const MuonClusterOnTrack*>& clustersSTGC = layerROTs.getClusters(MuonStationIndex::STGC); + const std::vector<const MuonClusterOnTrack*>& clustersMM = layerROTs.getClusters(MuonStationIndex::MM); std::vector<const MuonClusterOnTrack*> clusters; - if( clustersSTGC.size()>0 ) { - ATH_MSG_DEBUG( " STGC clusters " << clustersSTGC.size()); - for( auto cl : clustersSTGC ){ - clusters.push_back(cl); - } + if (clustersSTGC.size() > 0) { + ATH_MSG_DEBUG(" STGC clusters " << clustersSTGC.size()); + for (auto cl : clustersSTGC) { + clusters.push_back(cl); + } } - if( clustersMM.size()>0 ) { - ATH_MSG_DEBUG( " MM clusters " << clustersMM.size()); - for( auto cl : clustersMM ){ - clusters.push_back(cl); - } + if (clustersMM.size() > 0) { + ATH_MSG_DEBUG(" MM clusters " << clustersMM.size()); + for (auto cl : clustersMM) { + clusters.push_back(cl); + } } std::vector<MuonSegment*> foundSegments; - m_clusterSegMakerNSW->find(clusters,foundSegments); - if( foundSegments.size()>0 ) { - for( auto seg : foundSegments ){ - ATH_MSG_DEBUG( " NSW segment " << m_printer->print(*seg) ); - segments.push_back( std::shared_ptr<const MuonSegment>(seg) ); - ATH_MSG_DEBUG( " total segments " << segments.size() ); - } - } - } - - void MuonLayerSegmentFinderTool::findCscSegments( const MuonLayerPrepRawData& layerPrepRawData, std::vector< std::shared_ptr<const Muon::MuonSegment> >& segments ) const { + m_clusterSegMakerNSW->find(clusters, foundSegments); + if (foundSegments.size() > 0) { + for (auto seg : foundSegments) { + ATH_MSG_DEBUG(" NSW segment " << m_printer->print(*seg)); + segments.push_back(std::shared_ptr<const MuonSegment>(seg)); + ATH_MSG_DEBUG(" total segments " << segments.size()); + } + } +} + +void +MuonLayerSegmentFinderTool::findCscSegments(const MuonLayerPrepRawData& layerPrepRawData, + std::vector<std::shared_ptr<const Muon::MuonSegment> >& segments) const +{ // run 2d segment finder std::unique_ptr<MuonSegmentCombinationCollection> combi2D = m_csc2dSegmentFinder->find(layerPrepRawData.cscs); - if( combi2D ){ - - // run 4d segment finder - std::unique_ptr<MuonSegmentCombinationCollection> combi4D = m_csc4dSegmentFinder->find( *combi2D ); - if( combi4D ){ - - // extract segments and clean-up memory - for( auto com : *combi4D ){ - const Muon::MuonSegmentCombination& combi = *com; - unsigned int nstations = combi.numberOfStations(); - - // loop over chambers in combi and extract segments - for(unsigned int i=0; i<nstations; ++i){ - - // loop over segments in station - const Muon::MuonSegmentCombination::SegmentVec* segs = combi.stationSegments( i ) ; - - // check if not empty - if( !segs || segs->empty() ) continue; - // loop over new segments, copy them into collection - Muon::MuonSegmentCombination::SegmentVec::const_iterator sit = segs->begin(); - Muon::MuonSegmentCombination::SegmentVec::const_iterator sit_end = segs->end(); - for( ; sit!=sit_end;++sit){ - ATH_MSG_DEBUG( " " << m_printer->print(**sit) ); - segments.push_back( std::shared_ptr<const MuonSegment>( (*sit)->clone() ) ); + if (combi2D) { + + // run 4d segment finder + std::unique_ptr<MuonSegmentCombinationCollection> combi4D = m_csc4dSegmentFinder->find(*combi2D); + if (combi4D) { + + // extract segments and clean-up memory + for (auto com : *combi4D) { + const Muon::MuonSegmentCombination& combi = *com; + unsigned int nstations = combi.numberOfStations(); + + // loop over chambers in combi and extract segments + for (unsigned int i = 0; i < nstations; ++i) { + + // loop over segments in station + const Muon::MuonSegmentCombination::SegmentVec* segs = combi.stationSegments(i); + + // check if not empty + if (!segs || segs->empty()) continue; + // loop over new segments, copy them into collection + Muon::MuonSegmentCombination::SegmentVec::const_iterator sit = segs->begin(); + Muon::MuonSegmentCombination::SegmentVec::const_iterator sit_end = segs->end(); + for (; sit != sit_end; ++sit) { + ATH_MSG_DEBUG(" " << m_printer->print(**sit)); + segments.push_back(std::shared_ptr<const MuonSegment>((*sit)->clone())); + } + } } - } } - } } - } - } +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonLayerSegmentMakerTools/src/MuonLayerSegmentFinderTool.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonLayerSegmentMakerTools/src/MuonLayerSegmentFinderTool.h index 0dc14144425613f9d879e920911f1cc6ed8c2fc3..c229d8689cfab8920ba1565b3fb1eee67114accb 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonLayerSegmentMakerTools/src/MuonLayerSegmentFinderTool.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonLayerSegmentMakerTools/src/MuonLayerSegmentFinderTool.h @@ -5,86 +5,128 @@ #ifndef MUON_MUONLAYERSEGMENTFINDERTOOL_H #define MUON_MUONLAYERSEGMENTFINDERTOOL_H -#include "MuonSegmentMakerToolInterfaces/IMuonLayerSegmentFinderTool.h" +#include <string> +#include <vector> + #include "AthenaBaseComps/AthAlgTool.h" +#include "CscSegmentMakers/ICscSegmentFinder.h" #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" - +#include "MuonDetDescrUtils/MuonSectorMapping.h" +#include "MuonHoughPatternTools/MuonLayerHoughTool.h" #include "MuonIdHelpers/IMuonIdHelperSvc.h" +#include "MuonLayerEvent/MuonSystemExtension.h" #include "MuonRecHelperTools/MuonEDMPrinterTool.h" -#include "MuonRecToolInterfaces/IMuonSegmentMaker.h" #include "MuonRecToolInterfaces/IMuonPRDSelectionTool.h" -#include "CscSegmentMakers/ICscSegmentFinder.h" +#include "MuonRecToolInterfaces/IMuonRecoValidationTool.h" +#include "MuonRecToolInterfaces/IMuonSegmentMaker.h" #include "MuonSegmentMakerToolInterfaces/IMuonClusterSegmentFinder.h" -#include "MuonHoughPatternTools/MuonLayerHoughTool.h" -#include "MuonLayerEvent/MuonSystemExtension.h" -#include "MuonDetDescrUtils/MuonSectorMapping.h" #include "MuonSegmentMakerToolInterfaces/IMuonClusterSegmentFinderTool.h" -#include "MuonRecToolInterfaces/IMuonRecoValidationTool.h" - -#include <string> -#include <vector> +#include "MuonSegmentMakerToolInterfaces/IMuonLayerSegmentFinderTool.h" namespace Muon { - - class MuonSegment; - struct MuonLayerPrepRawData; - class MuonLayerROTs; - class MdtDriftCircleOnTrack; - class MuonClusterOnTrack; - class MuonLayerSegmentFinderTool : virtual public IMuonLayerSegmentFinderTool, public AthAlgTool { - public: +class MuonSegment; +struct MuonLayerPrepRawData; +class MuonLayerROTs; +class MdtDriftCircleOnTrack; +class MuonClusterOnTrack; +class MuonLayerSegmentFinderTool : virtual public IMuonLayerSegmentFinderTool, public AthAlgTool { + public: /** Default AlgTool functions */ MuonLayerSegmentFinderTool(const std::string& type, const std::string& name, const IInterface* parent); - virtual ~MuonLayerSegmentFinderTool()=default; + virtual ~MuonLayerSegmentFinderTool() = default; StatusCode initialize(); - /**IMuonLayerSegmentFinderTool interface: find */ - void find( const MuonSystemExtension::Intersection& intersection, std::vector< std::shared_ptr<const Muon::MuonSegment> >& segments, MuonLayerPrepRawData& layerPrepRawData ) const; + /**IMuonLayerSegmentFinderTool interface: find */ + void find(const MuonSystemExtension::Intersection& intersection, + std::vector<std::shared_ptr<const Muon::MuonSegment> >& segments, + MuonLayerPrepRawData& layerPrepRawData) const; private: /** find segments from PRD clusters */ - void findClusterSegments( const MuonSystemExtension::Intersection& intersection, const MuonLayerPrepRawData& layerPrepRawData, - std::vector< std::shared_ptr<const Muon::MuonSegment> >& segments ) const; + void findClusterSegments(const MuonSystemExtension::Intersection& intersection, + const MuonLayerPrepRawData& layerPrepRawData, + std::vector<std::shared_ptr<const Muon::MuonSegment> >& segments) const; /** find csc segments */ - void findCscSegments( const MuonLayerPrepRawData& layerPrepRawData, std::vector< std::shared_ptr<const Muon::MuonSegment> >& segments ) const; + void findCscSegments(const MuonLayerPrepRawData& layerPrepRawData, + std::vector<std::shared_ptr<const Muon::MuonSegment> >& segments) const; /** find mdt segments from hits in the layer */ - void findMdtSegments( const MuonSystemExtension::Intersection& intersection, const MuonLayerPrepRawData& layerPrepRawData, - std::vector< std::shared_ptr<const Muon::MuonSegment> >& segments ) const; + void findMdtSegments(const MuonSystemExtension::Intersection& intersection, + const MuonLayerPrepRawData& layerPrepRawData, + std::vector<std::shared_ptr<const Muon::MuonSegment> >& segments) const; /** find mdt segments from Hough output */ - void findMdtSegmentsFromHough( const MuonSystemExtension::Intersection& intersection, const MuonLayerPrepRawData& layerPrepRawData, - std::vector< std::shared_ptr<const Muon::MuonSegment> >& segments ) const; + void findMdtSegmentsFromHough(const MuonSystemExtension::Intersection& intersection, + const MuonLayerPrepRawData& layerPrepRawData, + std::vector<std::shared_ptr<const Muon::MuonSegment> >& segments) const; /** find mdt segments main routine */ - void findMdtSegments( const MuonSystemExtension::Intersection& intersection, - const std::vector<const MdtDriftCircleOnTrack*>& mdts, - const std::vector<const MuonClusterOnTrack*>& clusters, - std::vector< std::shared_ptr<const Muon::MuonSegment> >& segments ) const; + void findMdtSegments(const MuonSystemExtension::Intersection& intersection, + const std::vector<const MdtDriftCircleOnTrack*>& mdts, + const std::vector<const MuonClusterOnTrack*>& clusters, + std::vector<std::shared_ptr<const Muon::MuonSegment> >& segments) const; /** storegate */ - SG::ReadHandleKey<MuonLayerHoughTool::HoughDataPerSectorVec> m_houghDataPerSectorVecKey {this, - "Key_MuonLayerHoughToolHoughDataPerSectorVec", "HoughDataPerSectorVec", "HoughDataPerSectorVec key"}; - - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - ToolHandle<MuonEDMPrinterTool> m_printer; - ToolHandle<IMuonPRDSelectionTool> m_muonPRDSelectionTool; - ToolHandle<IMuonSegmentMaker> m_segmentMaker; - ToolHandle<ICscSegmentFinder> m_csc2dSegmentFinder; - ToolHandle<ICscSegmentFinder> m_csc4dSegmentFinder; - ToolHandle<IMuonClusterSegmentFinder> m_clusterSegmentFinder; - ToolHandle<IMuonClusterSegmentFinderTool> m_clusterSegMakerNSW; - mutable ToolHandle<IMuonRecoValidationTool> m_recoValidationTool; - MuonSectorMapping m_muonSectorMapping; - }; -} - + SG::ReadHandleKey<MuonLayerHoughTool::HoughDataPerSectorVec> m_houghDataPerSectorVecKey{ + this, + "Key_MuonLayerHoughToolHoughDataPerSectorVec", + "HoughDataPerSectorVec", + "HoughDataPerSectorVec key", + }; + + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; + + ToolHandle<MuonEDMPrinterTool> m_printer{ + this, + "MuonEDMPrinterTool", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; + ToolHandle<IMuonPRDSelectionTool> m_muonPRDSelectionTool{ + this, + "MuonPRDSelectionTool", + "Muon::MuonPRDSelectionTool/MuonPRDSelectionTool", + }; + ToolHandle<IMuonSegmentMaker> m_segmentMaker{ + this, + "SegmentMaker", + "Muon::DCMathSegmentMaker/DCMathSegmentMaker", + }; + ToolHandle<ICscSegmentFinder> m_csc2dSegmentFinder{ + this, + "Csc2DSegmentMaker", + "Csc2dSegmentMaker/Csc2dSegmentMaker", + }; + ToolHandle<ICscSegmentFinder> m_csc4dSegmentFinder{ + this, + "Csc4DSegmentMaker", + "Csc4dSegmentMaker/Csc4dSegmentMaker", + }; + ToolHandle<IMuonClusterSegmentFinder> m_clusterSegmentFinder{ + this, + "MuonClusterSegmentFinder", + "Muon::MuonClusterSegmentFinder/MuonClusterSegmentFinder", + }; + ToolHandle<IMuonClusterSegmentFinderTool> m_clusterSegMakerNSW{ + this, + "NSWMuonClusterSegmentFinderTool", + "Muon::MuonClusterSegmentFinderTool/MuonClusterSegmentFinderTool", + }; + mutable ToolHandle<IMuonRecoValidationTool> m_recoValidationTool{ + this, + "MuonRecoValidationTool", + "", // "Muon::MuonRecoValidationTool/MuonRecoValidationTool" + }; + + MuonSectorMapping m_muonSectorMapping; +}; +} // namespace Muon #endif - - - diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/MuonPatternSegmentMaker/MuonPatternCalibration.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/MuonPatternSegmentMaker/MuonPatternCalibration.h index 9e2f5470f679491e7fa23e060e113d3c4ab54277..cb9fde8c1715bd458e77453e513e42f18e54e072 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/MuonPatternSegmentMaker/MuonPatternCalibration.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/MuonPatternSegmentMaker/MuonPatternCalibration.h @@ -4,128 +4,138 @@ #ifndef MUON_MUONPATTERNCALIBRATION_H #define MUON_MUONPATTERNCALIBRATION_H -#include "MuonSegmentMakerToolInterfaces/IMuonPatternCalibration.h" +#include <map> +#include <string> +#include <vector> + #include "AthenaBaseComps/AthAlgTool.h" #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" - +#include "MuonIdHelpers/IMuonIdHelperSvc.h" +#include "MuonPattern/MuonPatternCombination.h" +#include "MuonPattern/MuonPatternCombinationCollection.h" +#include "MuonPrepRawData/MuonPrepDataContainer.h" #include "MuonRecHelperTools/MuonEDMPrinterTool.h" #include "MuonRecToolInterfaces/IMdtDriftCircleOnTrackCreator.h" #include "MuonRecToolInterfaces/IMuonClusterOnTrackCreator.h" -#include "MuonPattern/MuonPatternCombinationCollection.h" -#include "MuonPattern/MuonPatternCombination.h" -#include "MuonPrepRawData/MuonPrepDataContainer.h" -#include "MuonIdHelpers/IMuonIdHelperSvc.h" - -#include <string> -#include <map> -#include <vector> +#include "MuonSegmentMakerToolInterfaces/IMuonPatternCalibration.h" class MdtPrepData; namespace Muon { - class MdtPrepData; - class MuonClusterOnTrack; - class MdtDriftCircleOnTrack; +class MdtPrepData; +class MuonClusterOnTrack; +class MdtDriftCircleOnTrack; - class MuonPatternCalibration : virtual public IMuonPatternCalibration, public AthAlgTool - { +class MuonPatternCalibration : virtual public IMuonPatternCalibration, public AthAlgTool { public: - typedef std::pair<Amg::Vector3D,const MuonCluster*> ISPrd; - typedef std::vector< ISPrd > ISPrdVec; - typedef ISPrdVec::const_iterator ISPrdIt; + typedef std::pair<Amg::Vector3D, const MuonCluster*> ISPrd; + typedef std::vector<ISPrd> ISPrdVec; + typedef ISPrdVec::const_iterator ISPrdIt; - typedef std::pair<Amg::Vector3D,const MdtPrepData*> ISPrdMdt; - typedef std::vector< ISPrdMdt > ISPrdMdtVec; - typedef ISPrdMdtVec::const_iterator ISPrdMdtIt; + typedef std::pair<Amg::Vector3D, const MdtPrepData*> ISPrdMdt; + typedef std::vector<ISPrdMdt> ISPrdMdtVec; + typedef ISPrdMdtVec::const_iterator ISPrdMdtIt; - typedef std::map< int, ISPrdMdtVec > RegionIdMap; + typedef std::map<int, ISPrdMdtVec> RegionIdMap; typedef RegionIdMap::const_iterator RegionIdMapIt; - + struct Region { - Amg::Vector3D regionPos; - Amg::Vector3D regionDir; - ISPrdVec triggerPrds; - RegionIdMap mdtPrdsPerChamber; + Amg::Vector3D regionPos; + Amg::Vector3D regionDir; + ISPrdVec triggerPrds; + RegionIdMap mdtPrdsPerChamber; }; - typedef std::map< int, Region > RegionMap; - typedef RegionMap::iterator RegionMapIt; + typedef std::map<int, Region> RegionMap; + typedef RegionMap::iterator RegionMapIt; typedef RegionMap::const_iterator RegionMapCit; - - typedef std::vector< const MuonClusterOnTrack* > ClusterVec; - typedef ClusterVec::iterator ClusterIt; - typedef ClusterVec::const_iterator ClusterCit; - typedef std::vector< const MdtDriftCircleOnTrack* > MdtVec; - typedef MdtVec::iterator MdtIt; - typedef MdtVec::iterator MdtCit; + typedef std::vector<const MuonClusterOnTrack*> ClusterVec; + typedef ClusterVec::iterator ClusterIt; + typedef ClusterVec::const_iterator ClusterCit; + + typedef std::vector<const MdtDriftCircleOnTrack*> MdtVec; + typedef MdtVec::iterator MdtIt; + typedef MdtVec::iterator MdtCit; + + typedef std::vector<MdtVec> MdtVecVec; + typedef MdtVecVec::iterator MdtVecIt; + typedef MdtVecVec::iterator MdtVecCit; - typedef std::vector< MdtVec > MdtVecVec; - typedef MdtVecVec::iterator MdtVecIt; - typedef MdtVecVec::iterator MdtVecCit; - - typedef IMuonPatternCalibration::ROTsPerRegion::iterator ROTsPerRegionIt; - typedef IMuonPatternCalibration::ROTsPerRegion::const_iterator ROTsPerRegionCit; + typedef IMuonPatternCalibration::ROTsPerRegion::iterator ROTsPerRegionIt; + typedef IMuonPatternCalibration::ROTsPerRegion::const_iterator ROTsPerRegionCit; struct EtaPhiHits { - EtaPhiHits() : neta(0), nphi(0) {} - int neta; - int nphi; + EtaPhiHits() : neta(0), nphi(0) {} + int neta; + int nphi; }; - + public: MuonPatternCalibration(const std::string&, const std::string&, const IInterface*); - virtual ~MuonPatternCalibration()=default; + virtual ~MuonPatternCalibration() = default; virtual StatusCode initialize(); - void calibrate( const MuonPatternCombination& pat, IMuonPatternCalibration::ROTsPerRegion& hitsPerRegion) const; - int getRegionId( const Identifier& id ) const ; - void clearRotsPerRegion( IMuonPatternCalibration::ROTsPerRegion& hitsPerRegion ) const; - bool checkForPhiMeasurements( const MuonPatternCombination& pat ) const; + void calibrate(const MuonPatternCombination& pat, IMuonPatternCalibration::ROTsPerRegion& hitsPerRegion) const; + int getRegionId(const Identifier& id) const; + void clearRotsPerRegion(IMuonPatternCalibration::ROTsPerRegion& hitsPerRegion) const; + bool checkForPhiMeasurements(const MuonPatternCombination& pat) const; private: - - void createRegionMap( const MuonPatternCombination& pat, RegionMap& regionMap, bool hasPhiMeasurements ) const; - void printRegionMap( const RegionMap& regionMap) const; - - void calibrateRegionMap( const RegionMap& regionMap, IMuonPatternCalibration::ROTsPerRegion& hitsPerRegion ) const; + void createRegionMap(const MuonPatternCombination& pat, RegionMap& regionMap, bool hasPhiMeasurements) const; + void printRegionMap(const RegionMap& regionMap) const; + void calibrateRegionMap(const RegionMap& regionMap, IMuonPatternCalibration::ROTsPerRegion& hitsPerRegion) const; - void insertCluster( const MuonCluster& mdt, RegionMap& regionMap, - const Amg::Vector3D& patpose, const Amg::Vector3D& patdire, - bool hasPhiMeasurements ) const; - void insertMdt( const MdtPrepData& clus, RegionMap& regionMap, - const Amg::Vector3D& patpose, const Amg::Vector3D& patdire, - bool hasPhiMeasurements ) const; + void insertCluster(const MuonCluster& mdt, RegionMap& regionMap, const Amg::Vector3D& patpose, + const Amg::Vector3D& patdire, bool hasPhiMeasurements) const; + void insertMdt(const MdtPrepData& clus, RegionMap& regionMap, const Amg::Vector3D& patpose, + const Amg::Vector3D& patdire, bool hasPhiMeasurements) const; void retrieveTriggerHitContainers() const; - ToolHandle<IMdtDriftCircleOnTrackCreator> m_mdtCreator; //<! pointer to mdt rio ontrack creator - ToolHandle<IMuonClusterOnTrackCreator> m_clusterCreator; //<! pointer to muon cluster rio ontrack creator - ToolHandle<MuonEDMPrinterTool> m_printer; //<! tool to print EDM objects - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - - bool m_doMultiAnalysis; //<! use neighbouring chambers during segment finding - bool m_doFullFinder; //<! - double m_dropDistance; //<! hits that are further away than the distance are not added to segmentmaker input - double m_phiAngleCut; //<! cut on the phi opening angle between chamber and pattern - bool m_doSummary; - bool m_recoverTriggerHits; - bool m_removeDoubleMdtHits; - - SG::ReadHandleKey <Muon::RpcPrepDataContainer> m_keyRpc; - SG::ReadHandleKey <Muon::TgcPrepDataContainer> m_keyTgc; - mutable const Muon::RpcPrepDataContainer* m_rpcPrdContainer; - mutable const Muon::TgcPrepDataContainer* m_tgcPrdContainer; - - }; - -} - -#endif //MUON_MUONPATTERNCALIBRATION_H + ToolHandle<IMdtDriftCircleOnTrackCreator> m_mdtCreator{ + this, + "MdtCreator", + "Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator", + }; //<! pointer to mdt rio ontrack creator + ToolHandle<IMuonClusterOnTrackCreator> m_clusterCreator{ + this, + "ClusterCreator", + "Muon::MuonClusterOnTrackCreator/MuonClusterOnTrackCreator", + }; //<! pointer to muon cluster rio ontrack creator + ToolHandle<MuonEDMPrinterTool> m_printer{ + this, + "Printer", + "Muon::MuonEDMPrinterTool", + }; //<! tool to print EDM objects + + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; + + bool m_doMultiAnalysis; //<! use neighbouring chambers during segment finding + bool m_doFullFinder; //<! + double m_dropDistance; //<! hits that are further away than the distance are not added to segmentmaker input + double m_phiAngleCut; //<! cut on the phi opening angle between chamber and pattern + bool m_doSummary; + bool m_recoverTriggerHits; + bool m_removeDoubleMdtHits; + + SG::ReadHandleKey<Muon::RpcPrepDataContainer> m_keyRpc; + SG::ReadHandleKey<Muon::TgcPrepDataContainer> m_keyTgc; + mutable const Muon::RpcPrepDataContainer* m_rpcPrdContainer; + mutable const Muon::TgcPrepDataContainer* m_tgcPrdContainer; +}; + +} // namespace Muon + +#endif // MUON_MUONPATTERNCALIBRATION_H diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/MuonPatternSegmentMaker/MuonPatternSegmentMaker.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/MuonPatternSegmentMaker/MuonPatternSegmentMaker.h index 824fedea065dc8882a9b92abac04b6abd6f7c61a..9e4fa370f3519493e7c1c2c35ab7f81c53ba6a38 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/MuonPatternSegmentMaker/MuonPatternSegmentMaker.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/MuonPatternSegmentMaker/MuonPatternSegmentMaker.h @@ -5,143 +5,159 @@ #ifndef MUON_MUONPATTERNSEGMENTMAKER_MUONPATTERNSEGMENTMAKER_H #define MUON_MUONPATTERNSEGMENTMAKER_MUONPATTERNSEGMENTMAKER_H -#include "MuonSegmentMakerToolInterfaces/IMuonPatternSegmentMaker.h" +#include <map> +#include <string> +#include <vector> + #include "AthenaBaseComps/AthAlgTool.h" #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" - #include "MuonIdHelpers/IMuonIdHelperSvc.h" +#include "MuonPattern/MuonPatternCombination.h" +#include "MuonPattern/MuonPatternCombinationCollection.h" #include "MuonRecHelperTools/MuonEDMPrinterTool.h" #include "MuonRecToolInterfaces/IMdtDriftCircleOnTrackCreator.h" #include "MuonRecToolInterfaces/IMuonClusterOnTrackCreator.h" #include "MuonRecToolInterfaces/IMuonSegmentMaker.h" - #include "MuonSegment/MuonSegmentCombination.h" #include "MuonSegment/MuonSegmentCombinationCollection.h" -#include "MuonPattern/MuonPatternCombinationCollection.h" -#include "MuonPattern/MuonPatternCombination.h" - -#include <string> -#include <map> -#include <vector> +#include "MuonSegmentMakerToolInterfaces/IMuonPatternSegmentMaker.h" class MdtPrepData; namespace Muon { - class MdtPrepData; - class MuonClusterOnTrack; - class MdtDriftCircleOnTrack; - class MuonSegment; +class MdtPrepData; +class MuonClusterOnTrack; +class MdtDriftCircleOnTrack; +class MuonSegment; - class MuonPatternSegmentMaker : virtual public IMuonPatternSegmentMaker, public AthAlgTool - { +class MuonPatternSegmentMaker : virtual public IMuonPatternSegmentMaker, public AthAlgTool { public: - typedef std::pair<Amg::Vector3D,const MuonCluster*> ISPrd; - typedef std::vector< ISPrd > ISPrdVec; - typedef ISPrdVec::const_iterator ISPrdIt; + typedef std::pair<Amg::Vector3D, const MuonCluster*> ISPrd; + typedef std::vector<ISPrd> ISPrdVec; + typedef ISPrdVec::const_iterator ISPrdIt; - typedef std::pair<Amg::Vector3D,const MdtPrepData*> ISPrdMdt; - typedef std::vector< ISPrdMdt > ISPrdMdtVec; - typedef ISPrdMdtVec::const_iterator ISPrdMdtIt; + typedef std::pair<Amg::Vector3D, const MdtPrepData*> ISPrdMdt; + typedef std::vector<ISPrdMdt> ISPrdMdtVec; + typedef ISPrdMdtVec::const_iterator ISPrdMdtIt; - typedef std::map< int, ISPrdMdtVec > RegionIdMap; + typedef std::map<int, ISPrdMdtVec> RegionIdMap; typedef RegionIdMap::const_iterator RegionIdMapIt; - + struct Region { - Amg::Vector3D regionPos; - Amg::Vector3D regionDir; - ISPrdVec triggerPrds; - RegionIdMap mdtPrdsPerChamber; + Amg::Vector3D regionPos; + Amg::Vector3D regionDir; + ISPrdVec triggerPrds; + RegionIdMap mdtPrdsPerChamber; }; - typedef std::map< int, Region > RegionMap; - typedef RegionMap::iterator RegionMapIt; + typedef std::map<int, Region> RegionMap; + typedef RegionMap::iterator RegionMapIt; typedef RegionMap::const_iterator RegionMapCit; - - typedef std::vector< const MuonClusterOnTrack* > ClusterVec; - typedef ClusterVec::iterator ClusterIt; - typedef ClusterVec::const_iterator ClusterCit; - - typedef std::vector< const MdtDriftCircleOnTrack* > MdtVec; - typedef MdtVec::iterator MdtIt; - typedef MdtVec::iterator MdtCit; - - typedef std::vector< MdtVec > MdtVecVec; - typedef MdtVecVec::iterator MdtVecIt; - typedef MdtVecVec::iterator MdtVecCit; - - struct ROTRegion{ - int regionId; - Amg::Vector3D regionPos; - Amg::Vector3D regionDir; - ClusterVec clusters; - MdtVecVec mdts; + + typedef std::vector<const MuonClusterOnTrack*> ClusterVec; + typedef ClusterVec::iterator ClusterIt; + typedef ClusterVec::const_iterator ClusterCit; + + typedef std::vector<const MdtDriftCircleOnTrack*> MdtVec; + typedef MdtVec::iterator MdtIt; + typedef MdtVec::iterator MdtCit; + + typedef std::vector<MdtVec> MdtVecVec; + typedef MdtVecVec::iterator MdtVecIt; + typedef MdtVecVec::iterator MdtVecCit; + + struct ROTRegion { + int regionId; + Amg::Vector3D regionPos; + Amg::Vector3D regionDir; + ClusterVec clusters; + MdtVecVec mdts; }; - typedef std::vector< ROTRegion > ROTsPerRegion; - typedef ROTsPerRegion::iterator ROTsPerRegionIt; - typedef ROTsPerRegion::const_iterator ROTsPerRegionCit; + typedef std::vector<ROTRegion> ROTsPerRegion; + typedef ROTsPerRegion::iterator ROTsPerRegionIt; + typedef ROTsPerRegion::const_iterator ROTsPerRegionCit; struct EtaPhiHits { - EtaPhiHits() : neta(0), nphi(0) {} - int neta; - int nphi; + EtaPhiHits() : neta(0), nphi(0) {} + int neta; + int nphi; }; - + public: MuonPatternSegmentMaker(const std::string&, const std::string&, const IInterface*); - virtual ~MuonPatternSegmentMaker()=default; + virtual ~MuonPatternSegmentMaker() = default; virtual StatusCode initialize(); - void find( const MuonPatternCombination& pattern, const std::vector<const RpcPrepDataCollection*>& rpcCols, const std::vector<const TgcPrepDataCollection*>& tgcCols, - Trk::SegmentCollection* segColl) const; + void find(const MuonPatternCombination& pattern, const std::vector<const RpcPrepDataCollection*>& rpcCols, + const std::vector<const TgcPrepDataCollection*>& tgcCols, Trk::SegmentCollection* segColl) const; - std::unique_ptr<MuonSegmentCombinationCollection> find( const MuonPatternCombinationCollection* patternCol, MuonSegmentCombPatternCombAssociationMap* segPattMap, - const std::vector<const RpcPrepDataCollection*>& rpcCols, const std::vector<const TgcPrepDataCollection*>& tgcCols) const; + std::unique_ptr<MuonSegmentCombinationCollection> find( + const MuonPatternCombinationCollection* patternCol, MuonSegmentCombPatternCombAssociationMap* segPattMap, + const std::vector<const RpcPrepDataCollection*>& rpcCols, + const std::vector<const TgcPrepDataCollection*>& tgcCols) const; private: - void createRegionMap( const MuonPatternCombination& pat, RegionMap& regionMap, bool hasPhiMeasurements, - const std::vector<const RpcPrepDataCollection*>& rpcCols, const std::vector<const TgcPrepDataCollection*>& tgcCols) const; - - void insertCluster( const MuonCluster& mdt, RegionMap& regionMap, - const Amg::Vector3D& patpose, const Amg::Vector3D& patdire, - bool hasPhiMeasurements ) const; - - void insertMdt( const MdtPrepData& clus, RegionMap& regionMap, - const Amg::Vector3D& patpose, const Amg::Vector3D& patdire, - bool hasPhiMeasurements ) const; - - - void printRegionMap( const RegionMap& regionMap) const; - bool checkForPhiMeasurements( const MuonPatternCombination& pat ) const; - - void calibrateRegionMap( const RegionMap& regionMap, ROTsPerRegion& hitsPerRegion ) const; - void clearRotsPerRegion( ROTsPerRegion& hitsPerRegion ) const; - - const MuonSegment* isSubSet( const MuonSegment* seg1, const MuonSegment* seg2 ) const; - int getRegionId( const Identifier& id ) const ; - - ToolHandle<IMuonSegmentMaker> m_segmentMaker; //<! pointer to muon segment maker. - - ToolHandle<IMdtDriftCircleOnTrackCreator> m_mdtCreator; //<! pointer to mdt rio ontrack creator - - ToolHandle<IMuonClusterOnTrackCreator> m_clusterCreator; //<! pointer to muon cluster rio ontrack creator - ToolHandle<MuonEDMPrinterTool> m_printer; //<! tool to print EDM objects - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - - bool m_doNtuple; //<! write ntuple for standalone pattern finding - bool m_doMultiAnalysis; //<! use neighbouring chambers during segment finding - bool m_doFullFinder; //<! - double m_dropDistance; //<! hits that are further away than the distance are not added to segmentmaker input - double m_phiAngleCut; //<! cut on the phi opening angle between chamber and pattern - bool m_doSummary; - bool m_recoverTriggerHits; - bool m_removeDoubleMdtHits; + void createRegionMap(const MuonPatternCombination& pat, RegionMap& regionMap, bool hasPhiMeasurements, + const std::vector<const RpcPrepDataCollection*>& rpcCols, + const std::vector<const TgcPrepDataCollection*>& tgcCols) const; + + void insertCluster(const MuonCluster& mdt, RegionMap& regionMap, const Amg::Vector3D& patpose, + const Amg::Vector3D& patdire, bool hasPhiMeasurements) const; + + void insertMdt(const MdtPrepData& clus, RegionMap& regionMap, const Amg::Vector3D& patpose, + const Amg::Vector3D& patdire, bool hasPhiMeasurements) const; + + + void printRegionMap(const RegionMap& regionMap) const; + bool checkForPhiMeasurements(const MuonPatternCombination& pat) const; + + void calibrateRegionMap(const RegionMap& regionMap, ROTsPerRegion& hitsPerRegion) const; + void clearRotsPerRegion(ROTsPerRegion& hitsPerRegion) const; + + const MuonSegment* isSubSet(const MuonSegment* seg1, const MuonSegment* seg2) const; + int getRegionId(const Identifier& id) const; + + ToolHandle<IMuonSegmentMaker> m_segmentMaker{ + this, + "SegmentMaker", + "Muon::DCMathSegmentMaker/DCMathSegmentMaker", + }; //<! pointer to muon segment maker. + ToolHandle<IMdtDriftCircleOnTrackCreator> m_mdtCreator{ + this, + "MdtCreator", + "Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator", + }; //<! pointer to mdt rio ontrack creator + ToolHandle<IMuonClusterOnTrackCreator> m_clusterCreator{ + this, + "ClusterCreator", + "Muon::MuonClusterOnTrackCreator/MuonClusterOnTrackCreator", + }; //<! pointer to muon cluster rio ontrack creator + ToolHandle<MuonEDMPrinterTool> m_printer{ + this, + "Printer", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; //<! tool to print EDM objects + + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; - }; + bool m_doNtuple; //<! write ntuple for standalone pattern finding + bool m_doMultiAnalysis; //<! use neighbouring chambers during segment finding + bool m_doFullFinder; //<! + double m_dropDistance; //<! hits that are further away than the distance are not added to segmentmaker input + double m_phiAngleCut; //<! cut on the phi opening angle between chamber and pattern + bool m_doSummary; + bool m_recoverTriggerHits; + bool m_removeDoubleMdtHits; +}; -} +} // namespace Muon -#endif //MUONSEGMENTMAKERALGS_MUONSEGMENTMAKERTOOL_H +#endif // MUONSEGMENTMAKERALGS_MUONSEGMENTMAKERTOOL_H diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/src/MuonPatternCalibration.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/src/MuonPatternCalibration.cxx index 8b45ee0b2011bc6d260b7fadb2677c1942d92567..893593f5489593282963761414dde86d4f46cab4 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/src/MuonPatternCalibration.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/src/MuonPatternCalibration.cxx @@ -4,45 +4,40 @@ #include "MuonPatternSegmentMaker/MuonPatternCalibration.h" +#include <iostream> +#include <set> +#include <sstream> + #include "MuonPattern/MuonPatternChamberIntersect.h" #include "MuonPrepRawData/MuonPrepDataContainer.h" +#include "MuonReadoutGeometry/CscReadoutElement.h" #include "MuonReadoutGeometry/MdtReadoutElement.h" +#include "MuonReadoutGeometry/MuonDetectorManager.h" #include "MuonReadoutGeometry/RpcReadoutElement.h" #include "MuonReadoutGeometry/TgcReadoutElement.h" -#include "MuonReadoutGeometry/CscReadoutElement.h" -#include "MuonReadoutGeometry/MuonDetectorManager.h" #include "TrkToolInterfaces/IRIO_OnTrackCreator.h" -#include <iostream> -#include <sstream> -#include <set> - namespace Muon { - MuonPatternCalibration::MuonPatternCalibration(const std::string& t,const std::string& n,const IInterface* p) : - AthAlgTool(t,n,p), - m_mdtCreator("Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator", this), - m_clusterCreator("Muon::MuonClusterOnTrackCreator/MuonClusterOnTrackCreator", this), - m_printer("Muon::MuonEDMPrinterTool"), - m_keyRpc("RPC_Measurements"), - m_keyTgc("TGC_Measurements") - { +MuonPatternCalibration::MuonPatternCalibration(const std::string& t, const std::string& n, const IInterface* p) + : AthAlgTool(t, n, p), m_keyRpc("RPC_Measurements"), m_keyTgc("TGC_Measurements") +{ declareInterface<IMuonPatternCalibration>(this); - declareProperty("MdtCreator",m_mdtCreator); - declareProperty("ClusterCreator",m_clusterCreator); - declareProperty("DoMultiChamberAnalysis",m_doMultiAnalysis = true); - declareProperty("DropDistance",m_dropDistance = 1500.); - declareProperty("AngleCutPhi",m_phiAngleCut = 1e9 ); - declareProperty("FullFinder",m_doFullFinder = true); + declareProperty("DoMultiChamberAnalysis", m_doMultiAnalysis = true); + declareProperty("DropDistance", m_dropDistance = 1500.); + declareProperty("AngleCutPhi", m_phiAngleCut = 1e9); + declareProperty("FullFinder", m_doFullFinder = true); declareProperty("RpcPrepDataContainer", m_keyRpc); declareProperty("TgcPrepDataContainer", m_keyTgc); - declareProperty("DoSummary",m_doSummary = false); - declareProperty("RecoverTriggerHits",m_recoverTriggerHits = true); - declareProperty("RemoveDoubleMdtHits",m_removeDoubleMdtHits = true); - } + declareProperty("DoSummary", m_doSummary = false); + declareProperty("RecoverTriggerHits", m_recoverTriggerHits = true); + declareProperty("RemoveDoubleMdtHits", m_removeDoubleMdtHits = true); +} - StatusCode MuonPatternCalibration::initialize() { +StatusCode +MuonPatternCalibration::initialize() +{ ATH_MSG_VERBOSE("MuonPatternCalibration::Initializing"); ATH_CHECK(m_mdtCreator.retrieve()); ATH_CHECK(m_printer.retrieve()); @@ -50,525 +45,560 @@ namespace Muon { ATH_CHECK(m_clusterCreator.retrieve()); ATH_CHECK(m_keyRpc.initialize()); ATH_CHECK(m_keyTgc.initialize()); - return StatusCode::SUCCESS; - } - + return StatusCode::SUCCESS; +} - void MuonPatternCalibration::calibrate(const MuonPatternCombination& pattern, IMuonPatternCalibration::ROTsPerRegion& hitsPerRegion) const { + +void +MuonPatternCalibration::calibrate(const MuonPatternCombination& pattern, + IMuonPatternCalibration::ROTsPerRegion& hitsPerRegion) const +{ Muon::MuonPatternCalibration::RegionMap regionMap; - bool hasPhiMeasurements = checkForPhiMeasurements( pattern ); - createRegionMap( pattern, regionMap, hasPhiMeasurements ); + bool hasPhiMeasurements = checkForPhiMeasurements(pattern); + createRegionMap(pattern, regionMap, hasPhiMeasurements); // calibrate hits - calibrateRegionMap( regionMap, hitsPerRegion ); + calibrateRegionMap(regionMap, hitsPerRegion); return; - } +} - int MuonPatternCalibration::getRegionId( const Identifier& id ) const - { - +int +MuonPatternCalibration::getRegionId(const Identifier& id) const +{ + // simple division of MuonSpectrometer in regions using barrel/endcap seperation plus // inner/middle/outer seperation int stIndex = (int)m_idHelperSvc->stationIndex(id); - int eta = m_idHelperSvc->stationEta( id ); - + int eta = m_idHelperSvc->stationEta(id); + int regionId = stIndex; - if( eta < 0 ) regionId *= -1; + if (eta < 0) regionId *= -1; return regionId; - } - - - bool MuonPatternCalibration::checkForPhiMeasurements( const MuonPatternCombination& pat ) const { - - bool hasPhiMeasurements(false); - std::vector< MuonPatternChamberIntersect >::const_iterator it = pat.chamberData().begin(); - for (; it!=pat.chamberData().end(); ++it) - { - if (hasPhiMeasurements==true) {break;} - std::vector< const Trk::PrepRawData* >::const_iterator pit = (*it).prepRawDataVec().begin(); - for (; pit!=(*it).prepRawDataVec().end(); ++pit) - { - Identifier id = (*pit)->identify(); - if( m_idHelperSvc->isRpc(id) && m_idHelperSvc->rpcIdHelper().measuresPhi(id) ) {hasPhiMeasurements = true; break;} - else if( m_idHelperSvc->isTgc(id) && m_idHelperSvc->tgcIdHelper().isStrip(id) ) {hasPhiMeasurements = true; break;} - else if( m_idHelperSvc->isCsc(id) && m_idHelperSvc->cscIdHelper().measuresPhi(id) ) {hasPhiMeasurements = true; break;} - } - } +} + + +bool +MuonPatternCalibration::checkForPhiMeasurements(const MuonPatternCombination& pat) const +{ + + bool hasPhiMeasurements(false); + std::vector<MuonPatternChamberIntersect>::const_iterator it = pat.chamberData().begin(); + for (; it != pat.chamberData().end(); ++it) { + if (hasPhiMeasurements == true) { + break; + } + std::vector<const Trk::PrepRawData*>::const_iterator pit = (*it).prepRawDataVec().begin(); + for (; pit != (*it).prepRawDataVec().end(); ++pit) { + Identifier id = (*pit)->identify(); + if (m_idHelperSvc->isRpc(id) && m_idHelperSvc->rpcIdHelper().measuresPhi(id)) { + hasPhiMeasurements = true; + break; + } else if (m_idHelperSvc->isTgc(id) && m_idHelperSvc->tgcIdHelper().isStrip(id)) { + hasPhiMeasurements = true; + break; + } else if (m_idHelperSvc->isCsc(id) && m_idHelperSvc->cscIdHelper().measuresPhi(id)) { + hasPhiMeasurements = true; + break; + } + } + } return hasPhiMeasurements; - } +} - void MuonPatternCalibration::createRegionMap( const MuonPatternCombination& pat, RegionMap& regionMap, - bool hasPhiMeasurements ) const { - if( hasPhiMeasurements ) ATH_MSG_DEBUG("pattern has phi measurements using extrapolation to determine second coordinate"); - else ATH_MSG_DEBUG("No phi measurements using center tubes"); +void +MuonPatternCalibration::createRegionMap(const MuonPatternCombination& pat, RegionMap& regionMap, + bool hasPhiMeasurements) const +{ + if (hasPhiMeasurements) + ATH_MSG_DEBUG("pattern has phi measurements using extrapolation to determine second coordinate"); + else + ATH_MSG_DEBUG("No phi measurements using center tubes"); retrieveTriggerHitContainers(); - - std::vector< MuonPatternChamberIntersect >::const_iterator it = pat.chamberData().begin(); - for (; it!=pat.chamberData().end(); ++it) { - - if( it->prepRawDataVec().empty() ) continue; - - const Amg::Vector3D& patpose = (*it).intersectPosition(); - const Amg::Vector3D patdire = (*it).intersectDirection().unit(); - - /** Try to recover missing phi clusters: - - loop over the clusters in the region and sort them by collection - - count the number of eta and phi clusters per collection - - */ - std::map<int,EtaPhiHits> etaPhiHitsPerChamber; - std::set<Identifier> clusterIds; - - - - const Trk::PrepRawData* prd = (*it).prepRawDataVec().front(); - if( !prd ) continue; - Identifier id = prd->identify(); - - // apply cut on the opening angle between pattern and chamber phi - // do some magic to avoid problems at phi = 0 and 2*pi - double phiStart = patdire.phi(); - double chPhi = prd->detectorElement()->center().phi(); - double pi = M_PI; - double phiRange = 0.75*pi; - double phiRange2 = 0.25*pi; - double phiOffset = 0.; - if( phiStart > phiRange || phiStart < -phiRange ) phiOffset = 2*pi; - else if( phiStart > -phiRange2 && phiStart < phiRange2 ) phiOffset = pi; - - if( phiOffset > 1.5*pi ){ - if( phiStart < 0 ) phiStart += phiOffset; - if( chPhi < 0 ) chPhi += phiOffset; - }else if( phiOffset > 0. ) { - phiStart += phiOffset; - chPhi += phiOffset; - } - double dphi = fabs(phiStart - chPhi); - - if( dphi > m_phiAngleCut ) { - ATH_MSG_DEBUG("Large angular phi difference between pattern and chamber, phi pattern " << patdire.phi() << " phi chamber " << prd->detectorElement()->center().phi()); - continue; - } - - // map to find duplicate hits in the chamber - std::map<Identifier,const MdtPrepData*> idMdtMap; - - std::vector< const Trk::PrepRawData* >::const_iterator pit = (*it).prepRawDataVec().begin(); - for (; pit!=(*it).prepRawDataVec().end(); ++pit) { - - if( !(*pit) ) continue; - - const MdtPrepData* mdt = dynamic_cast<const MdtPrepData*>(*pit); - if( mdt) { - - if( m_removeDoubleMdtHits ){ - const MdtPrepData*& previousMdt = idMdtMap[mdt->identify()]; - if( !previousMdt || previousMdt->tdc() > mdt->tdc() ) previousMdt = mdt; - else continue; - } - - insertMdt(*mdt,regionMap,patpose,patdire,hasPhiMeasurements); - }else{ - - const MuonCluster* clus = dynamic_cast<const MuonCluster*>(*pit); - if( !clus ) continue; - const Identifier& id = clus->identify(); - - if( clusterIds.count(id) ) continue; - clusterIds.insert(id); - - if( m_recoverTriggerHits ){ - bool measuresPhi = m_idHelperSvc->measuresPhi(id); - int colHash = clus->collectionHash(); - - EtaPhiHits& hitsPerChamber = etaPhiHitsPerChamber[colHash]; - if( measuresPhi ) ++hitsPerChamber.nphi; - else ++hitsPerChamber.neta; - } - insertCluster(*clus,regionMap,patpose,patdire,hasPhiMeasurements); - } - } - if( !etaPhiHitsPerChamber.empty() ){ - std::map<int,EtaPhiHits>::iterator chit = etaPhiHitsPerChamber.begin(); - std::map<int,EtaPhiHits>::iterator chit_end = etaPhiHitsPerChamber.end(); - for( ;chit!=chit_end;++chit ){ - EtaPhiHits& hits = chit->second; - if( (hits.neta > 0 && hits.nphi == 0) || (hits.nphi > 0 && hits.neta == 0) ){ - if( m_idHelperSvc->isRpc(id) && m_rpcPrdContainer ){ - - auto pos = m_rpcPrdContainer->indexFindPtr(chit->first); - if( pos == nullptr ) ATH_MSG_DEBUG("RpcPrepDataCollection not found in container!!"); - else{ - RpcPrepDataCollection::const_iterator rpcit = pos->begin(); - RpcPrepDataCollection::const_iterator rpcit_end = pos->end(); - for( ;rpcit!=rpcit_end;++rpcit ){ - if( clusterIds.count( (*rpcit)->identify() ) ) continue; - const MuonCluster* clus = dynamic_cast<const MuonCluster*>(*rpcit); - insertCluster(*clus,regionMap,patpose,patdire,hasPhiMeasurements); - clusterIds.insert(clus->identify()); - } - } - }else if( m_idHelperSvc->isTgc(id) && m_tgcPrdContainer ){ - auto pos = m_tgcPrdContainer->indexFindPtr(chit->first); - if( pos == nullptr ) ATH_MSG_DEBUG("TgcPrepDataCollection not found in container!!"); - else{ - TgcPrepDataCollection::const_iterator tgcit = pos->begin(); - TgcPrepDataCollection::const_iterator tgcit_end = pos->end(); - for( ;tgcit!=tgcit_end;++tgcit ){ - if( clusterIds.count( (*tgcit)->identify() ) ) continue; - const MuonCluster* clus = dynamic_cast<const MuonCluster*>(*tgcit); - insertCluster(*clus,regionMap,patpose,patdire,hasPhiMeasurements); - clusterIds.insert(clus->identify()); - } - } - } - } - } - } + + std::vector<MuonPatternChamberIntersect>::const_iterator it = pat.chamberData().begin(); + for (; it != pat.chamberData().end(); ++it) { + + if (it->prepRawDataVec().empty()) continue; + + const Amg::Vector3D& patpose = (*it).intersectPosition(); + const Amg::Vector3D patdire = (*it).intersectDirection().unit(); + + /** Try to recover missing phi clusters: + - loop over the clusters in the region and sort them by collection + - count the number of eta and phi clusters per collection + + */ + std::map<int, EtaPhiHits> etaPhiHitsPerChamber; + std::set<Identifier> clusterIds; + + + const Trk::PrepRawData* prd = (*it).prepRawDataVec().front(); + if (!prd) continue; + Identifier id = prd->identify(); + + // apply cut on the opening angle between pattern and chamber phi + // do some magic to avoid problems at phi = 0 and 2*pi + double phiStart = patdire.phi(); + double chPhi = prd->detectorElement()->center().phi(); + double pi = M_PI; + double phiRange = 0.75 * pi; + double phiRange2 = 0.25 * pi; + double phiOffset = 0.; + if (phiStart > phiRange || phiStart < -phiRange) + phiOffset = 2 * pi; + else if (phiStart > -phiRange2 && phiStart < phiRange2) + phiOffset = pi; + + if (phiOffset > 1.5 * pi) { + if (phiStart < 0) phiStart += phiOffset; + if (chPhi < 0) chPhi += phiOffset; + } else if (phiOffset > 0.) { + phiStart += phiOffset; + chPhi += phiOffset; + } + double dphi = fabs(phiStart - chPhi); + + if (dphi > m_phiAngleCut) { + ATH_MSG_DEBUG("Large angular phi difference between pattern and chamber, phi pattern " + << patdire.phi() << " phi chamber " << prd->detectorElement()->center().phi()); + continue; + } + + // map to find duplicate hits in the chamber + std::map<Identifier, const MdtPrepData*> idMdtMap; + + std::vector<const Trk::PrepRawData*>::const_iterator pit = (*it).prepRawDataVec().begin(); + for (; pit != (*it).prepRawDataVec().end(); ++pit) { + + if (!(*pit)) continue; + + const MdtPrepData* mdt = dynamic_cast<const MdtPrepData*>(*pit); + if (mdt) { + + if (m_removeDoubleMdtHits) { + const MdtPrepData*& previousMdt = idMdtMap[mdt->identify()]; + if (!previousMdt || previousMdt->tdc() > mdt->tdc()) + previousMdt = mdt; + else + continue; + } + + insertMdt(*mdt, regionMap, patpose, patdire, hasPhiMeasurements); + } else { + + const MuonCluster* clus = dynamic_cast<const MuonCluster*>(*pit); + if (!clus) continue; + const Identifier& id = clus->identify(); + + if (clusterIds.count(id)) continue; + clusterIds.insert(id); + + if (m_recoverTriggerHits) { + bool measuresPhi = m_idHelperSvc->measuresPhi(id); + int colHash = clus->collectionHash(); + + EtaPhiHits& hitsPerChamber = etaPhiHitsPerChamber[colHash]; + if (measuresPhi) + ++hitsPerChamber.nphi; + else + ++hitsPerChamber.neta; + } + insertCluster(*clus, regionMap, patpose, patdire, hasPhiMeasurements); + } + } + if (!etaPhiHitsPerChamber.empty()) { + std::map<int, EtaPhiHits>::iterator chit = etaPhiHitsPerChamber.begin(); + std::map<int, EtaPhiHits>::iterator chit_end = etaPhiHitsPerChamber.end(); + for (; chit != chit_end; ++chit) { + EtaPhiHits& hits = chit->second; + if ((hits.neta > 0 && hits.nphi == 0) || (hits.nphi > 0 && hits.neta == 0)) { + if (m_idHelperSvc->isRpc(id) && m_rpcPrdContainer) { + + auto pos = m_rpcPrdContainer->indexFindPtr(chit->first); + if (pos == nullptr) + ATH_MSG_DEBUG("RpcPrepDataCollection not found in container!!"); + else { + RpcPrepDataCollection::const_iterator rpcit = pos->begin(); + RpcPrepDataCollection::const_iterator rpcit_end = pos->end(); + for (; rpcit != rpcit_end; ++rpcit) { + if (clusterIds.count((*rpcit)->identify())) continue; + const MuonCluster* clus = dynamic_cast<const MuonCluster*>(*rpcit); + insertCluster(*clus, regionMap, patpose, patdire, hasPhiMeasurements); + clusterIds.insert(clus->identify()); + } + } + } else if (m_idHelperSvc->isTgc(id) && m_tgcPrdContainer) { + auto pos = m_tgcPrdContainer->indexFindPtr(chit->first); + if (pos == nullptr) + ATH_MSG_DEBUG("TgcPrepDataCollection not found in container!!"); + else { + TgcPrepDataCollection::const_iterator tgcit = pos->begin(); + TgcPrepDataCollection::const_iterator tgcit_end = pos->end(); + for (; tgcit != tgcit_end; ++tgcit) { + if (clusterIds.count((*tgcit)->identify())) continue; + const MuonCluster* clus = dynamic_cast<const MuonCluster*>(*tgcit); + insertCluster(*clus, regionMap, patpose, patdire, hasPhiMeasurements); + clusterIds.insert(clus->identify()); + } + } + } + } + } + } } - } +} - void MuonPatternCalibration::insertCluster( const MuonCluster& clus, RegionMap& regionMap, - const Amg::Vector3D& patpose, const Amg::Vector3D& patdire, - bool hasPhiMeasurements ) const { +void +MuonPatternCalibration::insertCluster(const MuonCluster& clus, RegionMap& regionMap, const Amg::Vector3D& patpose, + const Amg::Vector3D& patdire, bool hasPhiMeasurements) const +{ const Identifier& id = clus.identify(); - // check whether we are measuring phi or eta + // check whether we are measuring phi or eta bool measuresPhi = m_idHelperSvc->measuresPhi(id); - + Amg::Vector3D globalpos = clus.globalPosition(); Amg::Vector3D intersect; - if( hasPhiMeasurements ){ - // if there is a phi measurement in the pattern use the global direction to calculate the intersect with measurement plane - // and use the intersect to calculate the position along the strip - - // calculate intersect pattern measurement plane - const Trk::Surface& surf = clus.detectorElement()->surface(id); - Amg::Vector3D planepostion = surf.center(); - Amg::Vector3D planenormal = surf.normal(); - double denom = patdire.dot(planenormal); - double u = (planenormal.dot(planepostion - patpose))/(denom); - Amg::Vector3D piOnPlane = ( patpose + u * patdire); - - // transform to local plane coordiantes - const Amg::Transform3D gToLocal = clus.detectorElement()->surface().transform().inverse(); - Amg::Vector3D ilpos = gToLocal*piOnPlane; - Amg::Vector3D glpos = gToLocal*globalpos; - - // strip length - double striplen(0.); - - // projective strips - bool hasPointingPhiStrips= false; - - // detector specific stuff - const RpcPrepData* rpc = dynamic_cast<const RpcPrepData*>( &clus ); - if( rpc ){ - striplen = rpc->detectorElement()->StripLength(measuresPhi); - }else{ - const TgcPrepData* tgc = dynamic_cast<const TgcPrepData*>( &clus ); - if( !tgc ) return; - - int gasGap = m_idHelperSvc->tgcIdHelper().gasGap(id); - if( measuresPhi){ - hasPointingPhiStrips = true; - striplen = tgc->detectorElement()->StripLength(gasGap); - }else{ - int wire = m_idHelperSvc->tgcIdHelper().channel(id); - striplen = tgc->detectorElement()->WireLength(gasGap,wire); - } - } - - // set the position along the strip - if( !measuresPhi ) { - glpos[0] = ilpos.x(); - }else{ - if( hasPointingPhiStrips ) { - // do some special for tgcs - glpos[1] = ilpos.y(); - }else{ - glpos[1] = ilpos.y(); - } - } - - // transform back to global coordinates - intersect = gToLocal.inverse()*glpos; - Amg::Vector3D dif = globalpos - intersect; - if( (intersect - piOnPlane).mag() > m_dropDistance || dif.mag() > 0.5*striplen + m_dropDistance ){ - - ATH_MSG_VERBOSE(">>>> extrapolated position far outside volume, dropping hit " << m_idHelperSvc->toString( id ) << ". dist along strip " << dif.mag() << " 1/2 strip len " << 0.5*striplen - << " dist measurement plane " << (intersect - piOnPlane).mag()); - return; - } - if( dif.mag() > 0.5*striplen ){ - Amg::Vector3D newpos = globalpos - dif*(0.5*striplen/dif.mag()); - - ATH_MSG_VERBOSE(">>>> extrapolated position outside volume, shifting position " << m_idHelperSvc->toString( id ) << ". position along strip " << dif.mag() << " 1/2 tube len " << 0.5*striplen - << " dist To strip " << (intersect - piOnPlane).mag() << ". dist to newpos " << (newpos-globalpos).mag() << " pos " << newpos); - - intersect = newpos; - } - }else{ - // no phi measurements, use strip center - intersect = globalpos; + if (hasPhiMeasurements) { + // if there is a phi measurement in the pattern use the global direction to calculate the intersect with + // measurement plane and use the intersect to calculate the position along the strip + + // calculate intersect pattern measurement plane + const Trk::Surface& surf = clus.detectorElement()->surface(id); + Amg::Vector3D planepostion = surf.center(); + Amg::Vector3D planenormal = surf.normal(); + double denom = patdire.dot(planenormal); + double u = (planenormal.dot(planepostion - patpose)) / (denom); + Amg::Vector3D piOnPlane = (patpose + u * patdire); + + // transform to local plane coordiantes + const Amg::Transform3D gToLocal = clus.detectorElement()->surface().transform().inverse(); + Amg::Vector3D ilpos = gToLocal * piOnPlane; + Amg::Vector3D glpos = gToLocal * globalpos; + + // strip length + double striplen(0.); + + // projective strips + bool hasPointingPhiStrips = false; + + // detector specific stuff + const RpcPrepData* rpc = dynamic_cast<const RpcPrepData*>(&clus); + if (rpc) { + striplen = rpc->detectorElement()->StripLength(measuresPhi); + } else { + const TgcPrepData* tgc = dynamic_cast<const TgcPrepData*>(&clus); + if (!tgc) return; + + int gasGap = m_idHelperSvc->tgcIdHelper().gasGap(id); + if (measuresPhi) { + hasPointingPhiStrips = true; + striplen = tgc->detectorElement()->StripLength(gasGap); + } else { + int wire = m_idHelperSvc->tgcIdHelper().channel(id); + striplen = tgc->detectorElement()->WireLength(gasGap, wire); + } + } + + // set the position along the strip + if (!measuresPhi) { + glpos[0] = ilpos.x(); + } else { + if (hasPointingPhiStrips) { + // do some special for tgcs + glpos[1] = ilpos.y(); + } else { + glpos[1] = ilpos.y(); + } + } + + // transform back to global coordinates + intersect = gToLocal.inverse() * glpos; + Amg::Vector3D dif = globalpos - intersect; + if ((intersect - piOnPlane).mag() > m_dropDistance || dif.mag() > 0.5 * striplen + m_dropDistance) { + + ATH_MSG_VERBOSE(">>>> extrapolated position far outside volume, dropping hit " + << m_idHelperSvc->toString(id) << ". dist along strip " << dif.mag() << " 1/2 strip len " + << 0.5 * striplen << " dist measurement plane " << (intersect - piOnPlane).mag()); + return; + } + if (dif.mag() > 0.5 * striplen) { + Amg::Vector3D newpos = globalpos - dif * (0.5 * striplen / dif.mag()); + + ATH_MSG_VERBOSE(">>>> extrapolated position outside volume, shifting position " + << m_idHelperSvc->toString(id) << ". position along strip " << dif.mag() << " 1/2 tube len " + << 0.5 * striplen << " dist To strip " << (intersect - piOnPlane).mag() + << ". dist to newpos " << (newpos - globalpos).mag() << " pos " << newpos); + + intersect = newpos; + } + } else { + // no phi measurements, use strip center + intersect = globalpos; } - + // enter hit in map - int regionId = getRegionId( id ); + int regionId = getRegionId(id); RegionMapIt mip = regionMap.find(regionId); - if( mip == regionMap.end() ){ - Region region; - region.triggerPrds.push_back( std::make_pair( intersect, &clus ) ); - region.regionDir = patdire; - region.regionPos = patpose; - regionMap.insert( std::make_pair(regionId,region) ); - }else{ - Region& region = mip->second; - region.triggerPrds.push_back( std::make_pair( intersect, &clus ) ); + if (mip == regionMap.end()) { + Region region; + region.triggerPrds.push_back(std::make_pair(intersect, &clus)); + region.regionDir = patdire; + region.regionPos = patpose; + regionMap.insert(std::make_pair(regionId, region)); + } else { + Region& region = mip->second; + region.triggerPrds.push_back(std::make_pair(intersect, &clus)); } - } +} - void MuonPatternCalibration::insertMdt( const MdtPrepData& mdt, RegionMap& regionMap, - const Amg::Vector3D& patpose, const Amg::Vector3D& patdire, - bool hasPhiMeasurements ) const { +void +MuonPatternCalibration::insertMdt(const MdtPrepData& mdt, RegionMap& regionMap, const Amg::Vector3D& patpose, + const Amg::Vector3D& patdire, bool hasPhiMeasurements) const +{ - Amg::Vector3D intersect; + Amg::Vector3D intersect; const Identifier& id = mdt.identify(); - const MuonGM::MdtReadoutElement* detEl = mdt.detectorElement(); - const Amg::Vector3D& tubePos = mdt.globalPosition(); - - if( hasPhiMeasurements ){ - // if there is a phi measurement in the pattern use the global direction to calculate the intersect with the tube - // use the intersect to calculate the second coordinate - - const Amg::Transform3D amdbToGlobal = detEl->AmdbLRSToGlobalTransform(); - - - // calculate intersect pattern measurement plane - const Amg::Vector3D& planepostion = tubePos; - - // always project on plane with normal in radial direction - Amg::Vector3D planenormal = m_idHelperSvc->mdtIdHelper().isBarrel(id) ? - amdbToGlobal.linear()*Amg::Vector3D(0.,0.,1.) : amdbToGlobal.linear()*Amg::Vector3D(0.,1.,0.); - - double denom = patdire.dot(planenormal); - double u = (planenormal.dot(planepostion - patpose))/(denom); - Amg::Vector3D piOnPlane = ( patpose + u * patdire); - - Amg::Vector3D lpiOnPlane = amdbToGlobal.inverse()*piOnPlane; - Amg::Vector3D ltubePos = amdbToGlobal.inverse()*tubePos; - - intersect = amdbToGlobal*Amg::Vector3D( lpiOnPlane.x(), ltubePos.y(), ltubePos.z() ); - - Amg::Vector3D dif = tubePos - intersect; - double tubelen = detEl->getActiveTubeLength( m_idHelperSvc->mdtIdHelper().tubeLayer(id),m_idHelperSvc->mdtIdHelper().tube(id) ); - - if( dif.mag() > 0.5*tubelen ){ - Amg::Vector3D newpos = tubePos - dif*(0.5*tubelen/dif.mag()); - - ATH_MSG_VERBOSE(">>>> extrapolated position outside volume, shifting position " << m_idHelperSvc->toString( id ) << ". position along strip " << dif.mag() << " 1/2 tube len " << 0.5*tubelen - << " dist To Wire " << (piOnPlane-intersect).mag() << ". dist to newpos " << (newpos-tubePos).mag() << " pos " << newpos); - - intersect = newpos; - } - }else{ - // not phi measurement, use tube center - intersect = tubePos; + const MuonGM::MdtReadoutElement* detEl = mdt.detectorElement(); + const Amg::Vector3D& tubePos = mdt.globalPosition(); + + if (hasPhiMeasurements) { + // if there is a phi measurement in the pattern use the global direction to calculate the intersect with the + // tube use the intersect to calculate the second coordinate + + const Amg::Transform3D amdbToGlobal = detEl->AmdbLRSToGlobalTransform(); + + + // calculate intersect pattern measurement plane + const Amg::Vector3D& planepostion = tubePos; + + // always project on plane with normal in radial direction + Amg::Vector3D planenormal = m_idHelperSvc->mdtIdHelper().isBarrel(id) + ? amdbToGlobal.linear() * Amg::Vector3D(0., 0., 1.) + : amdbToGlobal.linear() * Amg::Vector3D(0., 1., 0.); + + double denom = patdire.dot(planenormal); + double u = (planenormal.dot(planepostion - patpose)) / (denom); + Amg::Vector3D piOnPlane = (patpose + u * patdire); + + Amg::Vector3D lpiOnPlane = amdbToGlobal.inverse() * piOnPlane; + Amg::Vector3D ltubePos = amdbToGlobal.inverse() * tubePos; + + intersect = amdbToGlobal * Amg::Vector3D(lpiOnPlane.x(), ltubePos.y(), ltubePos.z()); + + Amg::Vector3D dif = tubePos - intersect; + double tubelen = detEl->getActiveTubeLength(m_idHelperSvc->mdtIdHelper().tubeLayer(id), + m_idHelperSvc->mdtIdHelper().tube(id)); + + if (dif.mag() > 0.5 * tubelen) { + Amg::Vector3D newpos = tubePos - dif * (0.5 * tubelen / dif.mag()); + + ATH_MSG_VERBOSE(">>>> extrapolated position outside volume, shifting position " + << m_idHelperSvc->toString(id) << ". position along strip " << dif.mag() << " 1/2 tube len " + << 0.5 * tubelen << " dist To Wire " << (piOnPlane - intersect).mag() << ". dist to newpos " + << (newpos - tubePos).mag() << " pos " << newpos); + + intersect = newpos; + } + } else { + // not phi measurement, use tube center + intersect = tubePos; } - + // enter hit in map - Identifier elId = m_idHelperSvc->mdtIdHelper().elementID( id ); - + Identifier elId = m_idHelperSvc->mdtIdHelper().elementID(id); + MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(elId); - int chFlag = elId.get_identifier32().get_compact(); - if( m_doMultiAnalysis ){ - if( m_idHelperSvc->isSmallChamber(id) ){ - ATH_MSG_VERBOSE("Small chamber " << m_idHelperSvc->toString( elId )); - chFlag = 0; - if( chIndex == MuonStationIndex::BIS ){ - int eta = m_idHelperSvc->stationEta(elId); - if( abs(eta) == 8 ) { - ATH_MSG_VERBOSE("BIS8 chamber " << m_idHelperSvc->toString( elId )); - chFlag = 3; - } - } - }else{ - ATH_MSG_VERBOSE("Large chamber " << m_idHelperSvc->toString( elId )); - chFlag = 1; - if( chIndex == MuonStationIndex::BIL ){ - std::string stName = m_idHelperSvc->chamberNameString(id); - if( stName[2] == 'R' ){ - ATH_MSG_VERBOSE("BIR chamber " << m_idHelperSvc->toString( elId )); - chFlag = 2; - } - } - } - int phi = m_idHelperSvc->mdtIdHelper().stationPhi(id); - - chFlag += 10*phi; + int chFlag = elId.get_identifier32().get_compact(); + if (m_doMultiAnalysis) { + if (m_idHelperSvc->isSmallChamber(id)) { + ATH_MSG_VERBOSE("Small chamber " << m_idHelperSvc->toString(elId)); + chFlag = 0; + if (chIndex == MuonStationIndex::BIS) { + int eta = m_idHelperSvc->stationEta(elId); + if (abs(eta) == 8) { + ATH_MSG_VERBOSE("BIS8 chamber " << m_idHelperSvc->toString(elId)); + chFlag = 3; + } + } + } else { + ATH_MSG_VERBOSE("Large chamber " << m_idHelperSvc->toString(elId)); + chFlag = 1; + if (chIndex == MuonStationIndex::BIL) { + std::string stName = m_idHelperSvc->chamberNameString(id); + if (stName[2] == 'R') { + ATH_MSG_VERBOSE("BIR chamber " << m_idHelperSvc->toString(elId)); + chFlag = 2; + } + } + } + int phi = m_idHelperSvc->mdtIdHelper().stationPhi(id); + + chFlag += 10 * phi; } // use center tube for region assignment - int regionId = getRegionId( id ); + int regionId = getRegionId(id); RegionMapIt mip = regionMap.find(regionId); - if( mip == regionMap.end() ){ - Region region; - region.mdtPrdsPerChamber[chFlag].push_back( std::make_pair( intersect, &mdt ) ); - region.regionPos = patpose; - region.regionDir = patdire; - regionMap.insert( std::make_pair(regionId,region) ); - }else{ - Region& region = mip->second; - region.mdtPrdsPerChamber[chFlag].push_back( std::make_pair( intersect, &mdt ) ); + if (mip == regionMap.end()) { + Region region; + region.mdtPrdsPerChamber[chFlag].push_back(std::make_pair(intersect, &mdt)); + region.regionPos = patpose; + region.regionDir = patdire; + regionMap.insert(std::make_pair(regionId, region)); + } else { + Region& region = mip->second; + region.mdtPrdsPerChamber[chFlag].push_back(std::make_pair(intersect, &mdt)); } +} - } - - void MuonPatternCalibration::clearRotsPerRegion( IMuonPatternCalibration::ROTsPerRegion& hitsPerRegion ) const - { +void +MuonPatternCalibration::clearRotsPerRegion(IMuonPatternCalibration::ROTsPerRegion& hitsPerRegion) const +{ // loop over regions, delete all ROTS in map - ROTsPerRegionIt rit = hitsPerRegion.begin(); + ROTsPerRegionIt rit = hitsPerRegion.begin(); ROTsPerRegionIt rit_end = hitsPerRegion.end(); - for( ; rit!=rit_end;++rit ){ - - // loop over mdt hits vectors in region - MdtVecIt mdtvit = rit->mdts.begin(); - MdtVecIt mdtvit_end = rit->mdts.end(); - for( ; mdtvit!=mdtvit_end; ++mdtvit ){ - - // loop over mdt hits - MdtIt mdtit = mdtvit->begin(); - MdtIt mdtit_end = mdtvit->end(); - for( ; mdtit!=mdtit_end;++mdtit ){ - delete *mdtit; - } - - } - - // loop over clusters in region - ClusterIt clit = rit->clusters.begin(); - ClusterIt clit_end = rit->clusters.end(); - for( ;clit!=clit_end;++clit ){ - delete *clit; - } + for (; rit != rit_end; ++rit) { + + // loop over mdt hits vectors in region + MdtVecIt mdtvit = rit->mdts.begin(); + MdtVecIt mdtvit_end = rit->mdts.end(); + for (; mdtvit != mdtvit_end; ++mdtvit) { + + // loop over mdt hits + MdtIt mdtit = mdtvit->begin(); + MdtIt mdtit_end = mdtvit->end(); + for (; mdtit != mdtit_end; ++mdtit) { + delete *mdtit; + } + } + + // loop over clusters in region + ClusterIt clit = rit->clusters.begin(); + ClusterIt clit_end = rit->clusters.end(); + for (; clit != clit_end; ++clit) { + delete *clit; + } } - - } +} - void MuonPatternCalibration::printRegionMap( const RegionMap& regionMap) const { +void +MuonPatternCalibration::printRegionMap(const RegionMap& regionMap) const +{ - RegionMapCit mit = regionMap.begin(); + RegionMapCit mit = regionMap.begin(); RegionMapCit mit_end = regionMap.end(); ATH_MSG_INFO("Summarizing input"); - for( ; mit!=mit_end;++mit ){ - ATH_MSG_INFO("new region " << mit->first << " trigger " << mit->second.triggerPrds.size() - << " mdt ch " << mit->second.mdtPrdsPerChamber.size()); - - if( !mit->second.triggerPrds.empty() ) ATH_MSG_INFO("trigger hits " << mit->second.triggerPrds.size()); - - - ISPrdIt pit = mit->second.triggerPrds.begin(); - ISPrdIt pit_end = mit->second.triggerPrds.end(); - for( ;pit!=pit_end;++pit ){ - ATH_MSG_INFO(" " << m_printer->print(*(pit->second))); - } - - RegionIdMapIt idit = mit->second.mdtPrdsPerChamber.begin(); - RegionIdMapIt idit_end = mit->second.mdtPrdsPerChamber.end(); - for( ;idit!=idit_end;++idit ){ - ATH_MSG_INFO("new MDT chamber with " << idit->second.size() << " hits"); - - ISPrdMdtIt mdtit = idit->second.begin(); - ISPrdMdtIt mdtit_end = idit->second.end(); - for( ;mdtit!=mdtit_end;++mdtit ){ - const MdtPrepData* prd = mdtit->second; - ATH_MSG_INFO(" " << m_printer->print(*prd)); - } - } + for (; mit != mit_end; ++mit) { + ATH_MSG_INFO("new region " << mit->first << " trigger " << mit->second.triggerPrds.size() << " mdt ch " + << mit->second.mdtPrdsPerChamber.size()); + + if (!mit->second.triggerPrds.empty()) ATH_MSG_INFO("trigger hits " << mit->second.triggerPrds.size()); + + + ISPrdIt pit = mit->second.triggerPrds.begin(); + ISPrdIt pit_end = mit->second.triggerPrds.end(); + for (; pit != pit_end; ++pit) { + ATH_MSG_INFO(" " << m_printer->print(*(pit->second))); + } + + RegionIdMapIt idit = mit->second.mdtPrdsPerChamber.begin(); + RegionIdMapIt idit_end = mit->second.mdtPrdsPerChamber.end(); + for (; idit != idit_end; ++idit) { + ATH_MSG_INFO("new MDT chamber with " << idit->second.size() << " hits"); + + ISPrdMdtIt mdtit = idit->second.begin(); + ISPrdMdtIt mdtit_end = idit->second.end(); + for (; mdtit != mdtit_end; ++mdtit) { + const MdtPrepData* prd = mdtit->second; + ATH_MSG_INFO(" " << m_printer->print(*prd)); + } + } } - } +} - void MuonPatternCalibration::calibrateRegionMap( const RegionMap& regionMap, IMuonPatternCalibration::ROTsPerRegion& hitsPerRegion ) const - { +void +MuonPatternCalibration::calibrateRegionMap(const RegionMap& regionMap, + IMuonPatternCalibration::ROTsPerRegion& hitsPerRegion) const +{ - RegionMapCit mit = regionMap.begin(); + RegionMapCit mit = regionMap.begin(); RegionMapCit mit_end = regionMap.end(); - for( ; mit!=mit_end;++mit ){ + for (; mit != mit_end; ++mit) { - ROTRegion rotRegion; - rotRegion.regionId = mit->first; - rotRegion.regionPos = mit->second.regionPos; - rotRegion.regionDir = mit->second.regionDir; + ROTRegion rotRegion; + rotRegion.regionId = mit->first; + rotRegion.regionPos = mit->second.regionPos; + rotRegion.regionDir = mit->second.regionDir; - ISPrdIt pit = mit->second.triggerPrds.begin(); - ISPrdIt pit_end = mit->second.triggerPrds.end(); - for( ;pit!=pit_end;++pit ){ - - if( !pit->second ) continue; + ISPrdIt pit = mit->second.triggerPrds.begin(); + ISPrdIt pit_end = mit->second.triggerPrds.end(); + for (; pit != pit_end; ++pit) { - const MuonClusterOnTrack* cluster = m_clusterCreator->createRIO_OnTrack( *(pit->second), pit->first ); - if( !cluster ) continue; + if (!pit->second) continue; - rotRegion.clusters.push_back( cluster ); + const MuonClusterOnTrack* cluster = m_clusterCreator->createRIO_OnTrack(*(pit->second), pit->first); + if (!cluster) continue; - } + rotRegion.clusters.push_back(cluster); + } - RegionIdMapIt idit = mit->second.mdtPrdsPerChamber.begin(); - RegionIdMapIt idit_end = mit->second.mdtPrdsPerChamber.end(); - for( ;idit!=idit_end;++idit ){ + RegionIdMapIt idit = mit->second.mdtPrdsPerChamber.begin(); + RegionIdMapIt idit_end = mit->second.mdtPrdsPerChamber.end(); + for (; idit != idit_end; ++idit) { - ISPrdMdtIt mdtit = idit->second.begin(); - ISPrdMdtIt mdtit_end = idit->second.end(); - - MdtVec mdtROTs; - for( ;mdtit!=mdtit_end;++mdtit ){ - const MdtPrepData* prd = mdtit->second; - if( !prd ) continue; - - const MdtDriftCircleOnTrack* mdt = m_mdtCreator->createRIO_OnTrack( *prd, mdtit->first ); + ISPrdMdtIt mdtit = idit->second.begin(); + ISPrdMdtIt mdtit_end = idit->second.end(); - if( !mdt ) { - ATH_MSG_VERBOSE("Failed to calibrate " << m_idHelperSvc->toString(prd->identify())); - continue; - } - mdtROTs.push_back( mdt ); - } - if( !mdtROTs.empty() ) rotRegion.mdts.push_back( mdtROTs ); - } - hitsPerRegion.push_back( rotRegion ); - } + MdtVec mdtROTs; + for (; mdtit != mdtit_end; ++mdtit) { + const MdtPrepData* prd = mdtit->second; + if (!prd) continue; - } + const MdtDriftCircleOnTrack* mdt = m_mdtCreator->createRIO_OnTrack(*prd, mdtit->first); - void MuonPatternCalibration::retrieveTriggerHitContainers() const { + if (!mdt) { + ATH_MSG_VERBOSE("Failed to calibrate " << m_idHelperSvc->toString(prd->identify())); + continue; + } + mdtROTs.push_back(mdt); + } + if (!mdtROTs.empty()) rotRegion.mdts.push_back(mdtROTs); + } + hitsPerRegion.push_back(rotRegion); + } +} + +void +MuonPatternCalibration::retrieveTriggerHitContainers() const +{ - m_rpcPrdContainer=0; + m_rpcPrdContainer = 0; SG::ReadHandle<Muon::RpcPrepDataContainer> RpcCont(m_keyRpc); - if( !RpcCont.isValid() ) { - ATH_MSG_DEBUG(" Failed to retrieve RpcPrepDataContainer, will not recover rpc trigger hits "); - } - else m_rpcPrdContainer=RpcCont.cptr(); - - m_tgcPrdContainer=0; - SG::ReadHandle<Muon::TgcPrepDataContainer> TgcCont(m_keyTgc); - if(!TgcCont.isValid() ) { - ATH_MSG_DEBUG(" Failed to retrieve TgcPrepDataContainer, will not recover tgc trigger hits "); - } - else m_tgcPrdContainer=TgcCont.cptr(); - - } + if (!RpcCont.isValid()) { + ATH_MSG_DEBUG(" Failed to retrieve RpcPrepDataContainer, will not recover rpc trigger hits "); + } else + m_rpcPrdContainer = RpcCont.cptr(); + m_tgcPrdContainer = 0; + SG::ReadHandle<Muon::TgcPrepDataContainer> TgcCont(m_keyTgc); + if (!TgcCont.isValid()) { + ATH_MSG_DEBUG(" Failed to retrieve TgcPrepDataContainer, will not recover tgc trigger hits "); + } else + m_tgcPrdContainer = TgcCont.cptr(); } + +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/src/MuonPatternSegmentMaker.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/src/MuonPatternSegmentMaker.cxx index 7475b3128a76dfabb82f17a56a4183770cbda953..84fea49fe4581e306b8303598d5991e5527215ac 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/src/MuonPatternSegmentMaker.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonPatternSegmentMaker/src/MuonPatternSegmentMaker.cxx @@ -3,694 +3,710 @@ */ #include "MuonPatternSegmentMaker/MuonPatternSegmentMaker.h" +#include <iostream> +#include <set> +#include <sstream> +#include <utility> + #include "MuonPattern/MuonPatternChamberIntersect.h" #include "MuonPrepRawData/MuonPrepDataContainer.h" -#include "MuonSegment/MuonSegment.h" +#include "MuonReadoutGeometry/CscReadoutElement.h" #include "MuonReadoutGeometry/MdtReadoutElement.h" #include "MuonReadoutGeometry/RpcReadoutElement.h" #include "MuonReadoutGeometry/TgcReadoutElement.h" -#include "MuonReadoutGeometry/CscReadoutElement.h" -#include "TrkSegment/SegmentCollection.h" +#include "MuonSegment/MuonSegment.h" #include "TrkParameters/TrackParameters.h" +#include "TrkSegment/SegmentCollection.h" #include "TrkToolInterfaces/IRIO_OnTrackCreator.h" -#include <iostream> -#include <sstream> -#include <set> -#include <utility> - namespace Muon { - MuonPatternSegmentMaker::MuonPatternSegmentMaker(const std::string& t,const std::string& n,const IInterface* p) : - AthAlgTool(t,n,p), - m_segmentMaker("Muon::DCMathSegmentMaker/DCMathSegmentMaker", this), - m_mdtCreator("Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator", this), - m_clusterCreator("Muon::MuonClusterOnTrackCreator/MuonClusterOnTrackCreator", this), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool") - { +MuonPatternSegmentMaker::MuonPatternSegmentMaker(const std::string& t, const std::string& n, const IInterface* p) + : AthAlgTool(t, n, p) +{ declareInterface<IMuonPatternSegmentMaker>(this); - declareProperty("SegmentMaker",m_segmentMaker); - declareProperty("MdtCreator",m_mdtCreator); - declareProperty("ClusterCreator",m_clusterCreator); - declareProperty("DoNtuple",m_doNtuple = false); - declareProperty("DoMultiChamberAnalysis",m_doMultiAnalysis = true); - declareProperty("DropDistance",m_dropDistance = 1500.); - declareProperty("AngleCutPhi",m_phiAngleCut = 1e9 ); - declareProperty("FullFinder",m_doFullFinder = true); - declareProperty("DoSummary",m_doSummary = false); - declareProperty("RecoverTriggerHits",m_recoverTriggerHits = true); - declareProperty("RemoveDoubleMdtHits",m_removeDoubleMdtHits = true); - } - - StatusCode MuonPatternSegmentMaker::initialize() - { + declareProperty("DoNtuple", m_doNtuple = false); + declareProperty("DoMultiChamberAnalysis", m_doMultiAnalysis = true); + declareProperty("DropDistance", m_dropDistance = 1500.); + declareProperty("AngleCutPhi", m_phiAngleCut = 1e9); + declareProperty("FullFinder", m_doFullFinder = true); + declareProperty("DoSummary", m_doSummary = false); + declareProperty("RecoverTriggerHits", m_recoverTriggerHits = true); + declareProperty("RemoveDoubleMdtHits", m_removeDoubleMdtHits = true); +} + +StatusCode +MuonPatternSegmentMaker::initialize() +{ ATH_CHECK(m_mdtCreator.retrieve()); ATH_CHECK(m_printer.retrieve()); ATH_CHECK(m_idHelperSvc.retrieve()); ATH_CHECK(m_segmentMaker.retrieve()); ATH_CHECK(m_clusterCreator.retrieve()); - return StatusCode::SUCCESS; - } - + return StatusCode::SUCCESS; +} - std::unique_ptr<MuonSegmentCombinationCollection> MuonPatternSegmentMaker::find( const MuonPatternCombinationCollection* patterns, - MuonSegmentCombPatternCombAssociationMap* segPattMap, - const std::vector<const RpcPrepDataCollection*>& rpcCols, - const std::vector<const TgcPrepDataCollection*>& tgcCols) const { +std::unique_ptr<MuonSegmentCombinationCollection> +MuonPatternSegmentMaker::find(const MuonPatternCombinationCollection* patterns, + MuonSegmentCombPatternCombAssociationMap* segPattMap, + const std::vector<const RpcPrepDataCollection*>& rpcCols, + const std::vector<const TgcPrepDataCollection*>& tgcCols) const +{ std::unique_ptr<MuonSegmentCombinationCollection> combiCol(new MuonSegmentCombinationCollection); MuonPatternCombinationCollection::const_iterator it = patterns->begin(); - for( ; it!=patterns->end();++it ){ + for (; it != patterns->end(); ++it) { + + const MuonPatternCombination* pattern = *it; + + if (!pattern) { + continue; + } + + std::unique_ptr<Trk::SegmentCollection> segCol(new Trk::SegmentCollection(SG::VIEW_ELEMENTS)); + find(*pattern, rpcCols, tgcCols, segCol.get()); + + if (!segCol->empty()) { + MuonSegmentCombination* combi = + new MuonSegmentCombination(); // dynamically assigning memory here, but this object will be immediately + // added to the collection, which will take ownership + std::unique_ptr<std::vector<std::unique_ptr<MuonSegment> > > segVec( + new std::vector<std::unique_ptr<MuonSegment> >); + Trk::SegmentCollection::iterator sit = segCol->begin(); + Trk::SegmentCollection::iterator sit_end = segCol->end(); + for (; sit != sit_end; ++sit) { + Trk::Segment* tseg = *sit; + MuonSegment* mseg = dynamic_cast<MuonSegment*>(tseg); + segVec->push_back(std::unique_ptr<MuonSegment>(mseg)); + } + combi->addSegments(std::move(segVec)); + + // insert new combination into collection + combiCol->push_back(combi); + + // create link between pattern and segment combination + segPattMap->insert(std::make_pair(combi, pattern)); + } + + } // end loop over patterns + + if (combiCol->empty()) combiCol.reset(); + return combiCol; +} - const MuonPatternCombination* pattern = *it; - if( !pattern ) { - continue; - } +void +MuonPatternSegmentMaker::find(const MuonPatternCombination& pattern, + const std::vector<const RpcPrepDataCollection*>& rpcCols, + const std::vector<const TgcPrepDataCollection*>& tgcCols, + Trk::SegmentCollection* segColl) const +{ - std::unique_ptr<Trk::SegmentCollection> segCol(new Trk::SegmentCollection(SG::VIEW_ELEMENTS)); - find( *pattern, rpcCols, tgcCols, segCol.get() ); + if (pattern.chamberData().empty()) return; + ATH_MSG_DEBUG(" New global Pattern: pos " << pattern.chamberData().front().intersectPosition() << " dir " + << pattern.chamberData().front().intersectDirection()); - if(!segCol->empty()){ - MuonSegmentCombination* combi=new MuonSegmentCombination(); //dynamically assigning memory here, but this object will be immediately added to the collection, which will take ownership - std::unique_ptr<std::vector<std::unique_ptr<MuonSegment> > > segVec (new std::vector<std::unique_ptr< MuonSegment> >); - Trk::SegmentCollection::iterator sit = segCol->begin(); - Trk::SegmentCollection::iterator sit_end = segCol->end(); - for( ; sit!=sit_end;++sit){ - Trk::Segment* tseg=*sit; - MuonSegment* mseg=dynamic_cast<MuonSegment*>(tseg); - segVec->push_back(std::unique_ptr<MuonSegment>(mseg)); - } - combi->addSegments(std::move(segVec)); + bool hasPhiMeasurements = checkForPhiMeasurements(pattern); - // insert new combination into collection - combiCol->push_back( combi ); + // sort hits per region + RegionMap regionMap; + createRegionMap(pattern, regionMap, hasPhiMeasurements, rpcCols, tgcCols); - // create link between pattern and segment combination - segPattMap->insert(std::make_pair( combi, pattern) ); - } + // printout region Map + if (msgLvl(MSG::DEBUG) || m_doSummary) printRegionMap(regionMap); - } // end loop over patterns + // calibrate hits + ROTsPerRegion hitsPerRegion; + calibrateRegionMap(regionMap, hitsPerRegion); - if(combiCol->empty()) combiCol.reset(); - return combiCol; - } - - - void MuonPatternSegmentMaker::find( const MuonPatternCombination& pattern, const std::vector<const RpcPrepDataCollection*>& rpcCols, - const std::vector<const TgcPrepDataCollection*>& tgcCols, Trk::SegmentCollection* segColl) const { + // if( m_doNtuple ) xxx_EventNtWriter->fill( hitsPerRegion, &pattern, hasPhiMeasurements ); - if( pattern.chamberData().empty() ) return; - ATH_MSG_DEBUG(" New global Pattern: pos " << pattern.chamberData().front().intersectPosition() - << " dir " << pattern.chamberData().front().intersectDirection()); + ROTsPerRegionIt rit = hitsPerRegion.begin(); + ROTsPerRegionIt rit_end = hitsPerRegion.end(); - bool hasPhiMeasurements = checkForPhiMeasurements( pattern ); + for (; rit != rit_end; ++rit) { + // int regionId = rit->regionId; + + MdtVecIt mdtit = rit->mdts.begin(); + MdtVecIt mdtit_end = rit->mdts.end(); + for (; mdtit != mdtit_end; ++mdtit) { + if (mdtit->empty()) continue; + + if (mdtit->size() < 3) continue; + + if (m_doFullFinder) { + m_segmentMaker->find(rit->regionPos, rit->regionDir, *mdtit, rit->clusters, hasPhiMeasurements, segColl, + rit->regionDir.mag()); + } else { + std::vector<const Trk::RIO_OnTrack*> rios; + rios.insert(rios.begin(), mdtit->begin(), mdtit->end()); + m_segmentMaker->find(rios, segColl); + } + + ATH_MSG_VERBOSE(" search in " << m_idHelperSvc->toStringChamber(mdtit->front()->identify()) << " nhits " + << mdtit->size()); + if (segColl->empty()) { + ATH_MSG_VERBOSE(" no segments found "); + } else + ATH_MSG_VERBOSE("now have " << segColl->size() << " segments"); + + } // end loop over MDTs + + } // end loop over regions + + // delete pointer to ROT in region mapx + clearRotsPerRegion(hitsPerRegion); +} + +int +MuonPatternSegmentMaker::getRegionId(const Identifier& id) const +{ - // sort hits per region - RegionMap regionMap; - createRegionMap( pattern, regionMap, hasPhiMeasurements, rpcCols, tgcCols ); - - // printout region Map - if( msgLvl(MSG::DEBUG) || m_doSummary ) printRegionMap( regionMap ); - - // calibrate hits - ROTsPerRegion hitsPerRegion; - calibrateRegionMap( regionMap, hitsPerRegion ); - - //if( m_doNtuple ) xxx_EventNtWriter->fill( hitsPerRegion, &pattern, hasPhiMeasurements ); - - ROTsPerRegionIt rit = hitsPerRegion.begin(); - ROTsPerRegionIt rit_end = hitsPerRegion.end(); - - for( ;rit!=rit_end;++rit){ - //int regionId = rit->regionId; - - MdtVecIt mdtit = rit->mdts.begin(); - MdtVecIt mdtit_end = rit->mdts.end(); - for( ; mdtit!=mdtit_end; ++mdtit ){ - if( mdtit->empty() ) continue; - - if( mdtit->size() < 3 ) continue; - - if( m_doFullFinder ){ - m_segmentMaker->find( rit->regionPos, rit->regionDir, *mdtit, rit->clusters, - hasPhiMeasurements, segColl, rit->regionDir.mag() ); - }else{ - std::vector<const Trk::RIO_OnTrack*> rios; - rios.insert( rios.begin(), mdtit->begin(), mdtit->end() ); - m_segmentMaker->find(rios,segColl); - } - - ATH_MSG_VERBOSE(" search in " << m_idHelperSvc->toStringChamber(mdtit->front()->identify()) << " nhits " << mdtit->size()); - if(segColl->empty()){ - ATH_MSG_VERBOSE(" no segments found "); - } - else ATH_MSG_VERBOSE("now have "<<segColl->size()<<" segments"); - - }// end loop over MDTs - - } // end loop over regions - - // delete pointer to ROT in region mapx - clearRotsPerRegion( hitsPerRegion ); - - } - - int MuonPatternSegmentMaker::getRegionId( const Identifier& id ) const - { - // simple division of MuonSpectrometer in regions using barrel/endcap seperation plus // inner/middle/outer seperation int stIndex = (int)m_idHelperSvc->stationIndex(id); - int eta = m_idHelperSvc->stationEta( id ); - + int eta = m_idHelperSvc->stationEta(id); + int regionId = stIndex; - if( eta < 0 ) regionId *= -1; + if (eta < 0) regionId *= -1; return regionId; - } +} - bool MuonPatternSegmentMaker::checkForPhiMeasurements( const MuonPatternCombination& pat ) const { +bool +MuonPatternSegmentMaker::checkForPhiMeasurements(const MuonPatternCombination& pat) const +{ - std::vector< MuonPatternChamberIntersect >::const_iterator it = pat.chamberData().begin(); - for (; it!=pat.chamberData().end(); ++it) { - std::vector< const Trk::PrepRawData* >::const_iterator pit = (*it).prepRawDataVec().begin(); - for (; pit!=(*it).prepRawDataVec().end(); ++pit) { - if( m_idHelperSvc->measuresPhi((*pit)->identify()) ) { - return true; - } - } + std::vector<MuonPatternChamberIntersect>::const_iterator it = pat.chamberData().begin(); + for (; it != pat.chamberData().end(); ++it) { + std::vector<const Trk::PrepRawData*>::const_iterator pit = (*it).prepRawDataVec().begin(); + for (; pit != (*it).prepRawDataVec().end(); ++pit) { + if (m_idHelperSvc->measuresPhi((*pit)->identify())) { + return true; + } + } } return false; - } - - void MuonPatternSegmentMaker::createRegionMap( const MuonPatternCombination& pat, RegionMap& regionMap, bool hasPhiMeasurements, - const std::vector<const RpcPrepDataCollection*>& rpcCols, const std::vector<const TgcPrepDataCollection*>& tgcCols) const { - - if( hasPhiMeasurements ) - ATH_MSG_DEBUG(" pattern has phi measurements using extrapolation to determine second coordinate "); - else - ATH_MSG_DEBUG(" No phi measurements using center tubes "); - - - - std::vector< MuonPatternChamberIntersect >::const_iterator it = pat.chamberData().begin(); - for (; it!=pat.chamberData().end(); ++it) { - - if( it->prepRawDataVec().empty() ) continue; - - const Amg::Vector3D& patpose = (*it).intersectPosition(); - const Amg::Vector3D patdire = (*it).intersectDirection().unit(); - - /** Try to recover missing phi clusters: - - loop over the clusters in the region and sort them by collection - - count the number of eta and phi clusters per collection - - */ - std::map<unsigned int,EtaPhiHits> etaPhiHitsPerChamber; - std::set<Identifier> clusterIds; - - - - const Trk::PrepRawData* prd = (*it).prepRawDataVec().front(); - if( !prd ) continue; - Identifier id = prd->identify(); - - // apply cut on the opening angle between pattern and chamber phi - // do some magic to avoid problems at phi = 0 and 2*pi - double phiStart = patdire.phi(); - double chPhi = prd->detectorElement()->center().phi(); - double phiRange = 0.75*M_PI; - double phiRange2 = 0.25*M_PI; - double phiOffset = 0.; - if( phiStart > phiRange || phiStart < -phiRange ) phiOffset = 2*M_PI; - else if( phiStart > -phiRange2 && phiStart < phiRange2 ) phiOffset = M_PI; - - if( phiOffset > 1.5*M_PI ){ - if( phiStart < 0 ) phiStart += phiOffset; - if( chPhi < 0 ) chPhi += phiOffset; - }else if( phiOffset > 0. ) { - phiStart += phiOffset; - chPhi += phiOffset; - } - double dphi = fabs(phiStart - chPhi); - - if( dphi > m_phiAngleCut ) { - ATH_MSG_DEBUG(" Large angular phi difference between pattern and chamber " << std::endl - << " phi pattern " << patdire.phi() << " phi chamber " << prd->detectorElement()->center().phi()); - continue; - } - - // map to find duplicate hits in the chamber - std::map<Identifier,const MdtPrepData*> idMdtMap; - - std::vector< const Trk::PrepRawData* >::const_iterator pit = (*it).prepRawDataVec().begin(); - for (; pit!=(*it).prepRawDataVec().end(); ++pit) { - - if( !(*pit) ) continue; - - const MdtPrepData* mdt = dynamic_cast<const MdtPrepData*>(*pit); - if( mdt) { - - if( m_removeDoubleMdtHits ){ - const MdtPrepData*& previousMdt = idMdtMap[mdt->identify()]; - if( !previousMdt || previousMdt->tdc() > mdt->tdc() ) previousMdt = mdt; - else continue; - } - - insertMdt(*mdt,regionMap,patpose,patdire,hasPhiMeasurements); - }else{ - - const MuonCluster* clus = dynamic_cast<const MuonCluster*>(*pit); - if( !clus ) continue; - const Identifier& id = clus->identify(); - - if( clusterIds.count(id) ) continue; - clusterIds.insert(id); - - if( m_recoverTriggerHits ){ - bool measuresPhi = m_idHelperSvc->measuresPhi(id); - unsigned int colHash = clus->collectionHash(); - - EtaPhiHits& hitsPerChamber = etaPhiHitsPerChamber[colHash]; - if( measuresPhi ) ++hitsPerChamber.nphi; - else ++hitsPerChamber.neta; - } - insertCluster(*clus,regionMap,patpose,patdire,hasPhiMeasurements); - } - } - if( !etaPhiHitsPerChamber.empty() ){ - std::map<unsigned int,EtaPhiHits>::iterator chit = etaPhiHitsPerChamber.begin(); - std::map<unsigned int,EtaPhiHits>::iterator chit_end = etaPhiHitsPerChamber.end(); - for( ;chit!=chit_end;++chit ){ - EtaPhiHits& hits = chit->second; - if( (hits.neta > 0 && hits.nphi == 0) || (hits.nphi > 0 && hits.neta == 0) ){ - if( m_idHelperSvc->isRpc(id) && !rpcCols.empty() ){ - std::vector<const RpcPrepDataCollection*>::const_iterator rcvit=rpcCols.begin(); - for( ;rcvit!=rpcCols.end();++rcvit){ - if((*rcvit)->identifyHash()==chit->first){ - RpcPrepDataCollection::const_iterator rpcit = (*rcvit)->begin(); - RpcPrepDataCollection::const_iterator rpcit_end = (*rcvit)->end(); - for( ;rpcit!=rpcit_end;++rpcit ){ - if( clusterIds.count( (*rpcit)->identify() ) ) continue; - const MuonCluster* clus = dynamic_cast<const MuonCluster*>(*rpcit); - insertCluster(*clus,regionMap,patpose,patdire,hasPhiMeasurements); - clusterIds.insert(clus->identify()); - } - break; - } - } - if( rcvit == rpcCols.end() ){ - ATH_MSG_DEBUG(" RpcPrepDataCollection not found in container!! "); - } - }else if( m_idHelperSvc->isTgc(id) && !tgcCols.empty()){ - std::vector<const TgcPrepDataCollection*>::const_iterator tcvit=tgcCols.begin(); - for( ;tcvit!=tgcCols.end();++tcvit){ - if((*tcvit)->identifyHash()==chit->first){ - TgcPrepDataCollection::const_iterator tgcit = (*tcvit)->begin(); - TgcPrepDataCollection::const_iterator tgcit_end = (*tcvit)->end(); - for( ;tgcit!=tgcit_end;++tgcit ){ - if( clusterIds.count( (*tgcit)->identify() ) ) continue; - const MuonCluster* clus = dynamic_cast<const MuonCluster*>(*tgcit); - insertCluster(*clus,regionMap,patpose,patdire,hasPhiMeasurements); - clusterIds.insert(clus->identify()); - } - break; - } - } - if( tcvit == tgcCols.end() ){ - ATH_MSG_DEBUG(" RpcPrepDataCollection not found in container!! "); - } - } - } - } - } +} + +void +MuonPatternSegmentMaker::createRegionMap(const MuonPatternCombination& pat, RegionMap& regionMap, + bool hasPhiMeasurements, + const std::vector<const RpcPrepDataCollection*>& rpcCols, + const std::vector<const TgcPrepDataCollection*>& tgcCols) const +{ + + if (hasPhiMeasurements) + ATH_MSG_DEBUG(" pattern has phi measurements using extrapolation to determine second coordinate "); + else + ATH_MSG_DEBUG(" No phi measurements using center tubes "); + + + std::vector<MuonPatternChamberIntersect>::const_iterator it = pat.chamberData().begin(); + for (; it != pat.chamberData().end(); ++it) { + + if (it->prepRawDataVec().empty()) continue; + + const Amg::Vector3D& patpose = (*it).intersectPosition(); + const Amg::Vector3D patdire = (*it).intersectDirection().unit(); + + /** Try to recover missing phi clusters: + - loop over the clusters in the region and sort them by collection + - count the number of eta and phi clusters per collection + + */ + std::map<unsigned int, EtaPhiHits> etaPhiHitsPerChamber; + std::set<Identifier> clusterIds; + + + const Trk::PrepRawData* prd = (*it).prepRawDataVec().front(); + if (!prd) continue; + Identifier id = prd->identify(); + + // apply cut on the opening angle between pattern and chamber phi + // do some magic to avoid problems at phi = 0 and 2*pi + double phiStart = patdire.phi(); + double chPhi = prd->detectorElement()->center().phi(); + double phiRange = 0.75 * M_PI; + double phiRange2 = 0.25 * M_PI; + double phiOffset = 0.; + if (phiStart > phiRange || phiStart < -phiRange) + phiOffset = 2 * M_PI; + else if (phiStart > -phiRange2 && phiStart < phiRange2) + phiOffset = M_PI; + + if (phiOffset > 1.5 * M_PI) { + if (phiStart < 0) phiStart += phiOffset; + if (chPhi < 0) chPhi += phiOffset; + } else if (phiOffset > 0.) { + phiStart += phiOffset; + chPhi += phiOffset; + } + double dphi = fabs(phiStart - chPhi); + + if (dphi > m_phiAngleCut) { + ATH_MSG_DEBUG(" Large angular phi difference between pattern and chamber " + << std::endl + << " phi pattern " << patdire.phi() << " phi chamber " + << prd->detectorElement()->center().phi()); + continue; + } + + // map to find duplicate hits in the chamber + std::map<Identifier, const MdtPrepData*> idMdtMap; + + std::vector<const Trk::PrepRawData*>::const_iterator pit = (*it).prepRawDataVec().begin(); + for (; pit != (*it).prepRawDataVec().end(); ++pit) { + + if (!(*pit)) continue; + + const MdtPrepData* mdt = dynamic_cast<const MdtPrepData*>(*pit); + if (mdt) { + + if (m_removeDoubleMdtHits) { + const MdtPrepData*& previousMdt = idMdtMap[mdt->identify()]; + if (!previousMdt || previousMdt->tdc() > mdt->tdc()) + previousMdt = mdt; + else + continue; + } + + insertMdt(*mdt, regionMap, patpose, patdire, hasPhiMeasurements); + } else { + + const MuonCluster* clus = dynamic_cast<const MuonCluster*>(*pit); + if (!clus) continue; + const Identifier& id = clus->identify(); + + if (clusterIds.count(id)) continue; + clusterIds.insert(id); + + if (m_recoverTriggerHits) { + bool measuresPhi = m_idHelperSvc->measuresPhi(id); + unsigned int colHash = clus->collectionHash(); + + EtaPhiHits& hitsPerChamber = etaPhiHitsPerChamber[colHash]; + if (measuresPhi) + ++hitsPerChamber.nphi; + else + ++hitsPerChamber.neta; + } + insertCluster(*clus, regionMap, patpose, patdire, hasPhiMeasurements); + } + } + if (!etaPhiHitsPerChamber.empty()) { + std::map<unsigned int, EtaPhiHits>::iterator chit = etaPhiHitsPerChamber.begin(); + std::map<unsigned int, EtaPhiHits>::iterator chit_end = etaPhiHitsPerChamber.end(); + for (; chit != chit_end; ++chit) { + EtaPhiHits& hits = chit->second; + if ((hits.neta > 0 && hits.nphi == 0) || (hits.nphi > 0 && hits.neta == 0)) { + if (m_idHelperSvc->isRpc(id) && !rpcCols.empty()) { + std::vector<const RpcPrepDataCollection*>::const_iterator rcvit = rpcCols.begin(); + for (; rcvit != rpcCols.end(); ++rcvit) { + if ((*rcvit)->identifyHash() == chit->first) { + RpcPrepDataCollection::const_iterator rpcit = (*rcvit)->begin(); + RpcPrepDataCollection::const_iterator rpcit_end = (*rcvit)->end(); + for (; rpcit != rpcit_end; ++rpcit) { + if (clusterIds.count((*rpcit)->identify())) continue; + const MuonCluster* clus = dynamic_cast<const MuonCluster*>(*rpcit); + insertCluster(*clus, regionMap, patpose, patdire, hasPhiMeasurements); + clusterIds.insert(clus->identify()); + } + break; + } + } + if (rcvit == rpcCols.end()) { + ATH_MSG_DEBUG(" RpcPrepDataCollection not found in container!! "); + } + } else if (m_idHelperSvc->isTgc(id) && !tgcCols.empty()) { + std::vector<const TgcPrepDataCollection*>::const_iterator tcvit = tgcCols.begin(); + for (; tcvit != tgcCols.end(); ++tcvit) { + if ((*tcvit)->identifyHash() == chit->first) { + TgcPrepDataCollection::const_iterator tgcit = (*tcvit)->begin(); + TgcPrepDataCollection::const_iterator tgcit_end = (*tcvit)->end(); + for (; tgcit != tgcit_end; ++tgcit) { + if (clusterIds.count((*tgcit)->identify())) continue; + const MuonCluster* clus = dynamic_cast<const MuonCluster*>(*tgcit); + insertCluster(*clus, regionMap, patpose, patdire, hasPhiMeasurements); + clusterIds.insert(clus->identify()); + } + break; + } + } + if (tcvit == tgcCols.end()) { + ATH_MSG_DEBUG(" RpcPrepDataCollection not found in container!! "); + } + } + } + } + } } - } +} - void MuonPatternSegmentMaker::insertCluster( const MuonCluster& clus, RegionMap& regionMap, - const Amg::Vector3D& patpose, const Amg::Vector3D& patdire, - bool hasPhiMeasurements ) const { +void +MuonPatternSegmentMaker::insertCluster(const MuonCluster& clus, RegionMap& regionMap, const Amg::Vector3D& patpose, + const Amg::Vector3D& patdire, bool hasPhiMeasurements) const +{ const Identifier& id = clus.identify(); // check whether we are measuring phi or eta bool measuresPhi = m_idHelperSvc->measuresPhi(id); - + Amg::Vector3D globalpos = clus.globalPosition(); Amg::Vector3D intersect; - if( hasPhiMeasurements ){ - // if there is a phi measurement in the pattern use the global direction to calculate the intersect with measurement plane - // and use the intersect to calculate the position along the strip - - // calculate intersect pattern measurement plane - const Trk::Surface& surf = clus.detectorElement()->surface(id); - const Amg::Vector3D& planepostion = surf.center(); - const Amg::Vector3D& planenormal = surf.normal(); - double denom = patdire.dot(planenormal); - double u = (planenormal.dot(planepostion - patpose))/denom; - Amg::Vector3D piOnPlane = ( patpose + u * patdire); - - // transform to local plane coordiantes - const Amg::Transform3D gToLocal = clus.detectorElement()->surface().transform().inverse(); - Amg::Vector3D ilpos = gToLocal*piOnPlane; - Amg::Vector3D glpos = gToLocal*globalpos; - - // strip length - double striplen(0.); - - // projective strips - bool hasPointingPhiStrips= false; - - // detector specific stuff - const RpcPrepData* rpc = dynamic_cast<const RpcPrepData*>( &clus ); - if( rpc ){ - striplen = rpc->detectorElement()->StripLength(measuresPhi); - }else{ - const TgcPrepData* tgc = dynamic_cast<const TgcPrepData*>( &clus ); - if( !tgc ) return; - - int gasGap = m_idHelperSvc->tgcIdHelper().gasGap(id); - if( measuresPhi){ - hasPointingPhiStrips = true; - striplen = tgc->detectorElement()->StripLength(gasGap); - }else{ - int wire = m_idHelperSvc->tgcIdHelper().channel(id); - striplen = tgc->detectorElement()->WireLength(gasGap,wire); - } - } - - // set the position along the strip - if( !measuresPhi ) { - glpos[0] = ilpos.x() ; - }else{ - if( hasPointingPhiStrips ) { - // do some special for tgcs - glpos[1] = ilpos.y(); - }else{ - glpos[1] = ilpos.y(); - } - } - - // transform back to global coordinates - intersect = gToLocal.inverse()*glpos; - Amg::Vector3D dif = globalpos - intersect; - if( (intersect - piOnPlane).mag() > m_dropDistance || dif.mag() > 0.5*striplen + m_dropDistance ){ - - ATH_MSG_VERBOSE(" >>>> extrapolated position far outside volume, dropping hit " - << m_idHelperSvc->toString( id ) << std::endl - << " dist along strip " << dif.mag() << " 1/2 strip len " << 0.5*striplen - << " dist measurement plane " << (intersect - piOnPlane).mag()); - return; - } - if( dif.mag() > 0.5*striplen ){ - Amg::Vector3D newpos = globalpos - dif*(0.5*striplen/dif.mag()); - - ATH_MSG_VERBOSE(" >>>> extrapolated position outside volume, shifting position " - << m_idHelperSvc->toString( id ) << std::endl - << " position along strip " << dif.mag() << " 1/2 tube len " << 0.5*striplen - << " dist To strip " << (intersect - piOnPlane).mag() << std::endl - << " dist to newpos " << (newpos-globalpos).mag() << " pos " << newpos); - - intersect = newpos; - } - }else{ - // no phi measurements, use strip center - intersect = globalpos; + if (hasPhiMeasurements) { + // if there is a phi measurement in the pattern use the global direction to calculate the intersect with + // measurement plane and use the intersect to calculate the position along the strip + + // calculate intersect pattern measurement plane + const Trk::Surface& surf = clus.detectorElement()->surface(id); + const Amg::Vector3D& planepostion = surf.center(); + const Amg::Vector3D& planenormal = surf.normal(); + double denom = patdire.dot(planenormal); + double u = (planenormal.dot(planepostion - patpose)) / denom; + Amg::Vector3D piOnPlane = (patpose + u * patdire); + + // transform to local plane coordiantes + const Amg::Transform3D gToLocal = clus.detectorElement()->surface().transform().inverse(); + Amg::Vector3D ilpos = gToLocal * piOnPlane; + Amg::Vector3D glpos = gToLocal * globalpos; + + // strip length + double striplen(0.); + + // projective strips + bool hasPointingPhiStrips = false; + + // detector specific stuff + const RpcPrepData* rpc = dynamic_cast<const RpcPrepData*>(&clus); + if (rpc) { + striplen = rpc->detectorElement()->StripLength(measuresPhi); + } else { + const TgcPrepData* tgc = dynamic_cast<const TgcPrepData*>(&clus); + if (!tgc) return; + + int gasGap = m_idHelperSvc->tgcIdHelper().gasGap(id); + if (measuresPhi) { + hasPointingPhiStrips = true; + striplen = tgc->detectorElement()->StripLength(gasGap); + } else { + int wire = m_idHelperSvc->tgcIdHelper().channel(id); + striplen = tgc->detectorElement()->WireLength(gasGap, wire); + } + } + + // set the position along the strip + if (!measuresPhi) { + glpos[0] = ilpos.x(); + } else { + if (hasPointingPhiStrips) { + // do some special for tgcs + glpos[1] = ilpos.y(); + } else { + glpos[1] = ilpos.y(); + } + } + + // transform back to global coordinates + intersect = gToLocal.inverse() * glpos; + Amg::Vector3D dif = globalpos - intersect; + if ((intersect - piOnPlane).mag() > m_dropDistance || dif.mag() > 0.5 * striplen + m_dropDistance) { + + ATH_MSG_VERBOSE(" >>>> extrapolated position far outside volume, dropping hit " + << m_idHelperSvc->toString(id) << std::endl + << " dist along strip " << dif.mag() << " 1/2 strip len " << 0.5 * striplen + << " dist measurement plane " << (intersect - piOnPlane).mag()); + return; + } + if (dif.mag() > 0.5 * striplen) { + Amg::Vector3D newpos = globalpos - dif * (0.5 * striplen / dif.mag()); + + ATH_MSG_VERBOSE(" >>>> extrapolated position outside volume, shifting position " + << m_idHelperSvc->toString(id) << std::endl + << " position along strip " << dif.mag() << " 1/2 tube len " << 0.5 * striplen + << " dist To strip " << (intersect - piOnPlane).mag() << std::endl + << " dist to newpos " << (newpos - globalpos).mag() << " pos " << newpos); + + intersect = newpos; + } + } else { + // no phi measurements, use strip center + intersect = globalpos; } - + // enter hit in map - int regionId = getRegionId( id ); + int regionId = getRegionId(id); RegionMapIt mip = regionMap.find(regionId); - if( mip == regionMap.end() ){ - Region region; - region.triggerPrds.push_back( std::make_pair( intersect, &clus ) ); - region.regionDir = patdire; - region.regionPos = patpose; - regionMap.insert( std::make_pair(regionId,region) ); - }else{ - Region& region = mip->second; - region.triggerPrds.push_back( std::make_pair( intersect, &clus ) ); + if (mip == regionMap.end()) { + Region region; + region.triggerPrds.push_back(std::make_pair(intersect, &clus)); + region.regionDir = patdire; + region.regionPos = patpose; + regionMap.insert(std::make_pair(regionId, region)); + } else { + Region& region = mip->second; + region.triggerPrds.push_back(std::make_pair(intersect, &clus)); } - } +} - void MuonPatternSegmentMaker::insertMdt( const MdtPrepData& mdt, RegionMap& regionMap, - const Amg::Vector3D& patpose, const Amg::Vector3D& patdire, - bool hasPhiMeasurements ) const { +void +MuonPatternSegmentMaker::insertMdt(const MdtPrepData& mdt, RegionMap& regionMap, const Amg::Vector3D& patpose, + const Amg::Vector3D& patdire, bool hasPhiMeasurements) const +{ - Amg::Vector3D intersect; + Amg::Vector3D intersect; const Identifier& id = mdt.identify(); - const MuonGM::MdtReadoutElement* detEl = mdt.detectorElement(); - const Amg::Vector3D& tubePos = mdt.globalPosition(); - - if( hasPhiMeasurements ){ - // if there is a phi measurement in the pattern use the global direction to calculate the intersect with the tube - // use the intersect to calculate the second coordinate - - const Amg::Transform3D amdbToGlobal = detEl->AmdbLRSToGlobalTransform(); - - - // calculate intersect pattern measurement plane - const Amg::Vector3D& planepostion = tubePos; - - // always project on plane with normal in radial direction - Amg::Vector3D planenormal = !m_idHelperSvc->isEndcap(id) ? - amdbToGlobal.linear()*Amg::Vector3D(0.,0.,1.) : amdbToGlobal.linear()*Amg::Vector3D(0.,1.,0.); - - double denom = patdire.dot(planenormal); - double u = (planenormal.dot(planepostion - patpose))/denom; - Amg::Vector3D piOnPlane = ( patpose + u * patdire); - - Amg::Vector3D lpiOnPlane = amdbToGlobal.inverse()*piOnPlane; - Amg::Vector3D ltubePos = amdbToGlobal.inverse()*tubePos; - - intersect = amdbToGlobal*Amg::Vector3D( lpiOnPlane.x(), ltubePos.y(), ltubePos.z() ); - - Amg::Vector3D dif = tubePos - intersect; - double tubelen = detEl->getActiveTubeLength( m_idHelperSvc->mdtIdHelper().tubeLayer(id),m_idHelperSvc->mdtIdHelper().tube(id) ); - - if( dif.mag() > 0.5*tubelen ){ - Amg::Vector3D newpos = tubePos - dif*(0.5*tubelen/dif.mag()); - - ATH_MSG_VERBOSE(" >>>> extrapolated position outside volume, shifting position " - << m_idHelperSvc->toString( id ) << std::endl - << " position along strip " << dif.mag() << " 1/2 tube len " << 0.5*tubelen - << " dist To Wire " << (piOnPlane-intersect).mag() << std::endl - << " dist to newpos " << (newpos-tubePos).mag() << " pos " << newpos); - - intersect = newpos; - } - }else{ - // not phi measurement, use tube center - intersect = tubePos; + const MuonGM::MdtReadoutElement* detEl = mdt.detectorElement(); + const Amg::Vector3D& tubePos = mdt.globalPosition(); + + if (hasPhiMeasurements) { + // if there is a phi measurement in the pattern use the global direction to calculate the intersect with the + // tube use the intersect to calculate the second coordinate + + const Amg::Transform3D amdbToGlobal = detEl->AmdbLRSToGlobalTransform(); + + + // calculate intersect pattern measurement plane + const Amg::Vector3D& planepostion = tubePos; + + // always project on plane with normal in radial direction + Amg::Vector3D planenormal = !m_idHelperSvc->isEndcap(id) ? amdbToGlobal.linear() * Amg::Vector3D(0., 0., 1.) + : amdbToGlobal.linear() * Amg::Vector3D(0., 1., 0.); + + double denom = patdire.dot(planenormal); + double u = (planenormal.dot(planepostion - patpose)) / denom; + Amg::Vector3D piOnPlane = (patpose + u * patdire); + + Amg::Vector3D lpiOnPlane = amdbToGlobal.inverse() * piOnPlane; + Amg::Vector3D ltubePos = amdbToGlobal.inverse() * tubePos; + + intersect = amdbToGlobal * Amg::Vector3D(lpiOnPlane.x(), ltubePos.y(), ltubePos.z()); + + Amg::Vector3D dif = tubePos - intersect; + double tubelen = detEl->getActiveTubeLength(m_idHelperSvc->mdtIdHelper().tubeLayer(id), + m_idHelperSvc->mdtIdHelper().tube(id)); + + if (dif.mag() > 0.5 * tubelen) { + Amg::Vector3D newpos = tubePos - dif * (0.5 * tubelen / dif.mag()); + + ATH_MSG_VERBOSE(" >>>> extrapolated position outside volume, shifting position " + << m_idHelperSvc->toString(id) << std::endl + << " position along strip " << dif.mag() << " 1/2 tube len " << 0.5 * tubelen + << " dist To Wire " << (piOnPlane - intersect).mag() << std::endl + << " dist to newpos " << (newpos - tubePos).mag() << " pos " << newpos); + + intersect = newpos; + } + } else { + // not phi measurement, use tube center + intersect = tubePos; } - + // enter hit in map - Identifier elId = m_idHelperSvc->mdtIdHelper().elementID( id ); - + Identifier elId = m_idHelperSvc->mdtIdHelper().elementID(id); + MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(elId); - int chFlag = elId.get_identifier32().get_compact(); - if( m_doMultiAnalysis ){ - if( m_idHelperSvc->isSmallChamber(id) ){ - ATH_MSG_VERBOSE(" Small chamber " << m_idHelperSvc->toString( elId )); - chFlag = 0; - if( chIndex == MuonStationIndex::BIS ){ - int eta = m_idHelperSvc->stationEta(elId); - if( abs(eta) == 8 ) { - ATH_MSG_VERBOSE(" BIS8 chamber " << m_idHelperSvc->toString( elId )); - chFlag = 3; - } - } - }else{ - ATH_MSG_VERBOSE(" Large chamber " << m_idHelperSvc->toString( elId )); - chFlag = 1; - if( chIndex == MuonStationIndex::BIL ){ - std::string stName = m_idHelperSvc->chamberNameString(id); - if( stName[2] == 'R' ){ - ATH_MSG_VERBOSE(" BIR chamber " << m_idHelperSvc->toString( elId )); - chFlag = 2; - } - } - else if( chIndex == MuonStationIndex::BOL ){ - if( abs( m_idHelperSvc->stationEta(id) ) == 7 ){ - ATH_MSG_VERBOSE(" BOE chamber " << m_idHelperSvc->toString( elId )); - chFlag = 4; - } - } - } - - int phi = m_idHelperSvc->stationPhi(id); - - chFlag += 10*phi; + int chFlag = elId.get_identifier32().get_compact(); + if (m_doMultiAnalysis) { + if (m_idHelperSvc->isSmallChamber(id)) { + ATH_MSG_VERBOSE(" Small chamber " << m_idHelperSvc->toString(elId)); + chFlag = 0; + if (chIndex == MuonStationIndex::BIS) { + int eta = m_idHelperSvc->stationEta(elId); + if (abs(eta) == 8) { + ATH_MSG_VERBOSE(" BIS8 chamber " << m_idHelperSvc->toString(elId)); + chFlag = 3; + } + } + } else { + ATH_MSG_VERBOSE(" Large chamber " << m_idHelperSvc->toString(elId)); + chFlag = 1; + if (chIndex == MuonStationIndex::BIL) { + std::string stName = m_idHelperSvc->chamberNameString(id); + if (stName[2] == 'R') { + ATH_MSG_VERBOSE(" BIR chamber " << m_idHelperSvc->toString(elId)); + chFlag = 2; + } + } else if (chIndex == MuonStationIndex::BOL) { + if (abs(m_idHelperSvc->stationEta(id)) == 7) { + ATH_MSG_VERBOSE(" BOE chamber " << m_idHelperSvc->toString(elId)); + chFlag = 4; + } + } + } + + int phi = m_idHelperSvc->stationPhi(id); + + chFlag += 10 * phi; } // use center tube for region assignment - int regionId = getRegionId( id ); + int regionId = getRegionId(id); RegionMapIt mip = regionMap.find(regionId); - if( mip == regionMap.end() ){ - Region region; - region.mdtPrdsPerChamber[chFlag].push_back( std::make_pair( intersect, &mdt ) ); - region.regionPos = patpose; - region.regionDir = patdire; - regionMap.insert( std::make_pair(regionId,region) ); - }else{ - Region& region = mip->second; - region.mdtPrdsPerChamber[chFlag].push_back( std::make_pair( intersect, &mdt ) ); + if (mip == regionMap.end()) { + Region region; + region.mdtPrdsPerChamber[chFlag].push_back(std::make_pair(intersect, &mdt)); + region.regionPos = patpose; + region.regionDir = patdire; + regionMap.insert(std::make_pair(regionId, region)); + } else { + Region& region = mip->second; + region.mdtPrdsPerChamber[chFlag].push_back(std::make_pair(intersect, &mdt)); } +} - } - - void MuonPatternSegmentMaker::clearRotsPerRegion( MuonPatternSegmentMaker::ROTsPerRegion& hitsPerRegion ) const - { +void +MuonPatternSegmentMaker::clearRotsPerRegion(MuonPatternSegmentMaker::ROTsPerRegion& hitsPerRegion) const +{ // loop over regions, delete all ROTS in map - ROTsPerRegionIt rit = hitsPerRegion.begin(); + ROTsPerRegionIt rit = hitsPerRegion.begin(); ROTsPerRegionIt rit_end = hitsPerRegion.end(); - for( ; rit!=rit_end;++rit ){ - - // loop over mdt hits vectors in region - MdtVecIt mdtvit = rit->mdts.begin(); - MdtVecIt mdtvit_end = rit->mdts.end(); - for( ; mdtvit!=mdtvit_end; ++mdtvit ){ - - // loop over mdt hits - MdtIt mdtit = mdtvit->begin(); - MdtIt mdtit_end = mdtvit->end(); - for( ; mdtit!=mdtit_end;++mdtit ){ - delete *mdtit; - } - - } - - // loop over clusters in region - ClusterIt clit = rit->clusters.begin(); - ClusterIt clit_end = rit->clusters.end(); - for( ;clit!=clit_end;++clit ){ - delete *clit; - } + for (; rit != rit_end; ++rit) { + + // loop over mdt hits vectors in region + MdtVecIt mdtvit = rit->mdts.begin(); + MdtVecIt mdtvit_end = rit->mdts.end(); + for (; mdtvit != mdtvit_end; ++mdtvit) { + + // loop over mdt hits + MdtIt mdtit = mdtvit->begin(); + MdtIt mdtit_end = mdtvit->end(); + for (; mdtit != mdtit_end; ++mdtit) { + delete *mdtit; + } + } + + // loop over clusters in region + ClusterIt clit = rit->clusters.begin(); + ClusterIt clit_end = rit->clusters.end(); + for (; clit != clit_end; ++clit) { + delete *clit; + } } - - } +} - void MuonPatternSegmentMaker::printRegionMap( const RegionMap& regionMap) const { +void +MuonPatternSegmentMaker::printRegionMap(const RegionMap& regionMap) const +{ - RegionMapCit mit = regionMap.begin(); + RegionMapCit mit = regionMap.begin(); RegionMapCit mit_end = regionMap.end(); - ATH_MSG_INFO("Summarizing input "); - - for( ; mit!=mit_end;++mit ){ - ATH_MSG_INFO("new region " << mit->first << " trigger " << mit->second.triggerPrds.size() - << " mdt ch " << mit->second.mdtPrdsPerChamber.size()); - - if( !mit->second.triggerPrds.empty() ) ATH_MSG_INFO(" trigger hits " << mit->second.triggerPrds.size()); - - - ISPrdIt pit = mit->second.triggerPrds.begin(); - ISPrdIt pit_end = mit->second.triggerPrds.end(); - for( ;pit!=pit_end;++pit ){ - ATH_MSG_INFO(" " << m_printer->print(*(pit->second))); - } - - RegionIdMapIt idit = mit->second.mdtPrdsPerChamber.begin(); - RegionIdMapIt idit_end = mit->second.mdtPrdsPerChamber.end(); - for( ;idit!=idit_end;++idit ){ - ATH_MSG_INFO(" new MDT chamber with " << idit->second.size() << " hits"); - - ISPrdMdtIt mdtit = idit->second.begin(); - ISPrdMdtIt mdtit_end = idit->second.end(); - for( ;mdtit!=mdtit_end;++mdtit ){ - const MdtPrepData* prd = mdtit->second; - ATH_MSG_INFO(" " << m_printer->print(*prd)); - } - } + ATH_MSG_INFO("Summarizing input "); + + for (; mit != mit_end; ++mit) { + ATH_MSG_INFO("new region " << mit->first << " trigger " << mit->second.triggerPrds.size() << " mdt ch " + << mit->second.mdtPrdsPerChamber.size()); + + if (!mit->second.triggerPrds.empty()) ATH_MSG_INFO(" trigger hits " << mit->second.triggerPrds.size()); + + + ISPrdIt pit = mit->second.triggerPrds.begin(); + ISPrdIt pit_end = mit->second.triggerPrds.end(); + for (; pit != pit_end; ++pit) { + ATH_MSG_INFO(" " << m_printer->print(*(pit->second))); + } + + RegionIdMapIt idit = mit->second.mdtPrdsPerChamber.begin(); + RegionIdMapIt idit_end = mit->second.mdtPrdsPerChamber.end(); + for (; idit != idit_end; ++idit) { + ATH_MSG_INFO(" new MDT chamber with " << idit->second.size() << " hits"); + + ISPrdMdtIt mdtit = idit->second.begin(); + ISPrdMdtIt mdtit_end = idit->second.end(); + for (; mdtit != mdtit_end; ++mdtit) { + const MdtPrepData* prd = mdtit->second; + ATH_MSG_INFO(" " << m_printer->print(*prd)); + } + } } msg(MSG::INFO).doOutput(); +} - } - - void MuonPatternSegmentMaker::calibrateRegionMap( const RegionMap& regionMap, ROTsPerRegion& hitsPerRegion ) const - { +void +MuonPatternSegmentMaker::calibrateRegionMap(const RegionMap& regionMap, ROTsPerRegion& hitsPerRegion) const +{ - RegionMapCit mit = regionMap.begin(); + RegionMapCit mit = regionMap.begin(); RegionMapCit mit_end = regionMap.end(); - for( ; mit!=mit_end;++mit ){ + for (; mit != mit_end; ++mit) { - ROTRegion rotRegion; - rotRegion.regionId = mit->first; - rotRegion.regionPos = mit->second.regionPos; - rotRegion.regionDir = mit->second.regionDir; + ROTRegion rotRegion; + rotRegion.regionId = mit->first; + rotRegion.regionPos = mit->second.regionPos; + rotRegion.regionDir = mit->second.regionDir; - ISPrdIt pit = mit->second.triggerPrds.begin(); - ISPrdIt pit_end = mit->second.triggerPrds.end(); - for( ;pit!=pit_end;++pit ){ - - if( !pit->second ) continue; + ISPrdIt pit = mit->second.triggerPrds.begin(); + ISPrdIt pit_end = mit->second.triggerPrds.end(); + for (; pit != pit_end; ++pit) { - const MuonClusterOnTrack* cluster = m_clusterCreator->createRIO_OnTrack( *(pit->second), pit->first ); - if( !cluster ) continue; + if (!pit->second) continue; - rotRegion.clusters.push_back( cluster ); + const MuonClusterOnTrack* cluster = m_clusterCreator->createRIO_OnTrack(*(pit->second), pit->first); + if (!cluster) continue; - } + rotRegion.clusters.push_back(cluster); + } - RegionIdMapIt idit = mit->second.mdtPrdsPerChamber.begin(); - RegionIdMapIt idit_end = mit->second.mdtPrdsPerChamber.end(); - for( ;idit!=idit_end;++idit ){ + RegionIdMapIt idit = mit->second.mdtPrdsPerChamber.begin(); + RegionIdMapIt idit_end = mit->second.mdtPrdsPerChamber.end(); + for (; idit != idit_end; ++idit) { - ISPrdMdtIt mdtit = idit->second.begin(); - ISPrdMdtIt mdtit_end = idit->second.end(); - - MdtVec mdtROTs; - for( ;mdtit!=mdtit_end;++mdtit ){ - const MdtPrepData* prd = mdtit->second; - if( !prd ) continue; - Amg::Vector3D dr=mdtit->first; - const MdtDriftCircleOnTrack* mdt = m_mdtCreator->createRIO_OnTrack( *prd, mdtit->first, &dr ); + ISPrdMdtIt mdtit = idit->second.begin(); + ISPrdMdtIt mdtit_end = idit->second.end(); - if( !mdt ) { - ATH_MSG_VERBOSE(" Failed to calibrate " << m_idHelperSvc->toString(prd->identify())); - continue; - } - mdtROTs.push_back( mdt ); - } - if( !mdtROTs.empty() ) rotRegion.mdts.push_back( mdtROTs ); - } - hitsPerRegion.push_back( rotRegion ); - } + MdtVec mdtROTs; + for (; mdtit != mdtit_end; ++mdtit) { + const MdtPrepData* prd = mdtit->second; + if (!prd) continue; + Amg::Vector3D dr = mdtit->first; + const MdtDriftCircleOnTrack* mdt = m_mdtCreator->createRIO_OnTrack(*prd, mdtit->first, &dr); - } + if (!mdt) { + ATH_MSG_VERBOSE(" Failed to calibrate " << m_idHelperSvc->toString(prd->identify())); + continue; + } + mdtROTs.push_back(mdt); + } + if (!mdtROTs.empty()) rotRegion.mdts.push_back(mdtROTs); + } + hitsPerRegion.push_back(rotRegion); + } +} - const MuonSegment* MuonPatternSegmentMaker::isSubSet( const MuonSegment* seg1, const MuonSegment* seg2 ) const - { +const MuonSegment* +MuonPatternSegmentMaker::isSubSet(const MuonSegment* seg1, const MuonSegment* seg2) const +{ double theta1 = seg1->globalDirection().theta(); double phi1 = seg1->globalDirection().phi(); double R1 = seg1->globalPosition().perp(); double z1 = seg1->globalPosition().z(); - + double theta2 = seg2->globalDirection().theta(); double phi2 = seg2->globalDirection().phi(); double R2 = seg2->globalPosition().perp(); double z2 = seg2->globalPosition().z(); - - double dtheta = theta1-theta2; - double dphi = phi1-phi2; - double dR = R1-R2; - double dz = z1-z2; - - if( std::abs(dtheta) < 0.001 && std::abs(dphi) < 0.001 && std::abs( dR*dR + dz*dz ) < 0.01 ){ - return seg1; + + double dtheta = theta1 - theta2; + double dphi = phi1 - phi2; + double dR = R1 - R2; + double dz = z1 - z2; + + if (std::abs(dtheta) < 0.001 && std::abs(dphi) < 0.001 && std::abs(dR * dR + dz * dz) < 0.01) { + return seg1; } return 0; - } - } + +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentCleaner/MuonSegmentCleaner/MuonPhiHitSelector.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentCleaner/MuonSegmentCleaner/MuonPhiHitSelector.h index 4f0e992d93f7d6f85a0414ef777cde5b1084566e..30d1c298ab0327ecdfd4d4d1e3c45532bfb651d3 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentCleaner/MuonSegmentCleaner/MuonPhiHitSelector.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentCleaner/MuonSegmentCleaner/MuonPhiHitSelector.h @@ -5,84 +5,107 @@ #ifndef MuonSegmentCleaner_MuonPhiHitSelector_H #define MuonSegmentCleaner_MuonPhiHitSelector_H -#include "MuonRecToolInterfaces/IMuonHitSelector.h" #include "AthenaBaseComps/AthAlgTool.h" #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" - #include "MuonIdHelpers/IMuonIdHelperSvc.h" #include "MuonRecToolInterfaces/IMuonClusterOnTrackCreator.h" -#include "MuonRecToolInterfaces/IMuonCompetingClustersOnTrackCreator.h" +#include "MuonRecToolInterfaces/IMuonCompetingClustersOnTrackCreator.h" +#include "MuonRecToolInterfaces/IMuonHitSelector.h" namespace Trk { - class PrepRawData; - class RIO_OnTrack; -} - -class MuonPhiHitSelector : public AthAlgTool, virtual public Muon::IMuonHitSelector -{ - public: - MuonPhiHitSelector(const std::string&,const std::string&,const IInterface*); - virtual ~MuonPhiHitSelector()=default; - - virtual StatusCode initialize(); - - /** @brief Selects and builds a cleaned vector of RIO - fits the associatedHits and build new RIOs, if m_competingRios true then for ambiguous hits competing rios are built - */ - virtual std::vector<const Trk::MeasurementBase*>* select_rio( const double pmom, const std::vector<const Trk::RIO_OnTrack*>& associatedHits, - const std::vector<const Trk::PrepRawData*>& unassociatedHits ) const; - - private: - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - - /** Toolhandle to CompetingRIOsOnTrackTool creator */ - ToolHandle<Muon::IMuonCompetingClustersOnTrackCreator> m_competingRIOsOnTrackTool; - /** Toolhandle to ClusterOnTrackTool creator */ - ToolHandle<Muon::IMuonClusterOnTrackCreator> m_clusterCreator; - - /** flag to print out a summary of what comes in and what comes out */ - bool m_summary; - /** flag for use of cosmics, straight line model will be used, no interaction point constraint */ - bool m_cosmics; - /** flag that performs a clusterization and return clusters (default: false) */ - bool m_makeClusters; - /** flag that build competing rios on track for amibguous trigger hits (default: false) */ - bool m_competingRios; - - /** fit method curved track model */ - void fitRecPhi( const double pmom, const std::vector<Identifier> & phiId, const std::vector<double> & phiHitx, const std::vector<double> & phiHity, const std::vector<double> & phiHitz, const std::vector<double> & phiError, std::vector<int> & quality, const int nphi, std::vector<double> & phiPull, std::vector<int> & phiMult, std::vector<int> & phiSelect, double & chi2, double & r0, double & phi, std::vector<double> & errorM, int & nfit) const; - - /** fit method straight line model */ - void fitPhiSL(const double pmom, const std::vector<Identifier> & id, const std::vector<double> & hitx, const std::vector<double> & hity, const std::vector<double> & hitz, const std::vector<double> & error, std::vector<int> & select, const int n, std::vector<double> & pull, int & imax , double & chi2, double & r0, double & phi , std::vector<double> & errorM, bool fast) const; - - /** @brief clusterization method - - Use hits (select > 0) and pulls to make clusters - - Inputs - id = identifiers hits - hitx hity hitz = position in space - error = associated error (in x-y plane) - pull (from fit)= residual (hit -fit) /error - select = > 0 for selected hits - n = total number of hits - fast = true = fast fit without scattering centres and no error propagation - false = fit with scattering centres and error propagation - - Outputs - clusterX Y Z = cluster positions - clusterError = errors - clusterId = cluster identifier (smallest pull) - clusterHits = number of hits per cluster - ncl = number of clusters - chi2 = total chi2 - r0 = perigee parameter of fit (0,0) - phi = azimuthal angle of fit at perigee - */ - -void clusterPhi( const std::vector<Identifier> & id, const std::vector<double> & hitx, const std::vector<double> & hity, const std::vector<double> & hitz, const std::vector<double> & error, const std::vector<double> & pull, std::vector<int> & select, const int n, std::vector<double> & clusterX , std::vector<double> & clusterY ,std::vector<double> & clusterZ , std::vector<double> & clusterError , std::vector<Identifier> & clusterId, std::vector<int> & clusterHits, std::vector<int> & clusterSelect, std::vector<int> & clusterInt, int & ncl ) const; - +class PrepRawData; +class RIO_OnTrack; +} // namespace Trk + +class MuonPhiHitSelector : public AthAlgTool, virtual public Muon::IMuonHitSelector { + public: + MuonPhiHitSelector(const std::string&, const std::string&, const IInterface*); + virtual ~MuonPhiHitSelector() = default; + + virtual StatusCode initialize(); + + /** @brief Selects and builds a cleaned vector of RIO + fits the associatedHits and build new RIOs, if m_competingRios true then for ambiguous hits competing rios are + built + */ + virtual std::vector<const Trk::MeasurementBase*>* select_rio( + const double pmom, const std::vector<const Trk::RIO_OnTrack*>& associatedHits, + const std::vector<const Trk::PrepRawData*>& unassociatedHits) const; + + private: + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; + + /** Toolhandle to CompetingRIOsOnTrackTool creator */ + ToolHandle<Muon::IMuonCompetingClustersOnTrackCreator> m_competingRIOsOnTrackTool{ + this, + "MuonCompetingClustersOnTrackCreator", + "Muon::MuonCompetingClustersOnTrackCreator/MuonCompetingClustersOnTrackCreator", + }; + /** Toolhandle to ClusterOnTrackTool creator */ + ToolHandle<Muon::IMuonClusterOnTrackCreator> m_clusterCreator{ + this, + "MuonClusterOnTrackCreator", + "Muon::MuonClusterOnTrackCreator/MuonClusterOnTrackCreator", + }; + + /** flag to print out a summary of what comes in and what comes out */ + bool m_summary; + /** flag for use of cosmics, straight line model will be used, no interaction point constraint */ + bool m_cosmics; + /** flag that performs a clusterization and return clusters (default: false) */ + bool m_makeClusters; + /** flag that build competing rios on track for amibguous trigger hits (default: false) */ + bool m_competingRios; + + /** fit method curved track model */ + void fitRecPhi(const double pmom, const std::vector<Identifier>& phiId, const std::vector<double>& phiHitx, + const std::vector<double>& phiHity, const std::vector<double>& phiHitz, + const std::vector<double>& phiError, std::vector<int>& quality, const int nphi, + std::vector<double>& phiPull, std::vector<int>& phiMult, std::vector<int>& phiSelect, double& chi2, + double& r0, double& phi, std::vector<double>& errorM, int& nfit) const; + + /** fit method straight line model */ + void fitPhiSL(const double pmom, const std::vector<Identifier>& id, const std::vector<double>& hitx, + const std::vector<double>& hity, const std::vector<double>& hitz, const std::vector<double>& error, + std::vector<int>& select, const int n, std::vector<double>& pull, int& imax, double& chi2, double& r0, + double& phi, std::vector<double>& errorM, bool fast) const; + + /** @brief clusterization method + + Use hits (select > 0) and pulls to make clusters + + Inputs + id = identifiers hits + hitx hity hitz = position in space + error = associated error (in x-y plane) + pull (from fit)= residual (hit -fit) /error + select = > 0 for selected hits + n = total number of hits + fast = true = fast fit without scattering centres and no error propagation + false = fit with scattering centres and error propagation + + Outputs + clusterX Y Z = cluster positions + clusterError = errors + clusterId = cluster identifier (smallest pull) + clusterHits = number of hits per cluster + ncl = number of clusters + chi2 = total chi2 + r0 = perigee parameter of fit (0,0) + phi = azimuthal angle of fit at perigee + */ + + void clusterPhi(const std::vector<Identifier>& id, const std::vector<double>& hitx, const std::vector<double>& hity, + const std::vector<double>& hitz, const std::vector<double>& error, const std::vector<double>& pull, + std::vector<int>& select, const int n, std::vector<double>& clusterX, std::vector<double>& clusterY, + std::vector<double>& clusterZ, std::vector<double>& clusterError, + std::vector<Identifier>& clusterId, std::vector<int>& clusterHits, std::vector<int>& clusterSelect, + std::vector<int>& clusterInt, int& ncl) const; }; -#endif // MuonSegmentCleaner_MuonPhiHitSelector_H +#endif // MuonSegmentCleaner_MuonPhiHitSelector_H diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentCleaner/src/MuonPhiHitSelector.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentCleaner/src/MuonPhiHitSelector.cxx index 0c170f6e71415558e33d59d896d3507b35802220..820f519dc260e40d85b46a637e71c80b806a843a 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentCleaner/src/MuonPhiHitSelector.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentCleaner/src/MuonPhiHitSelector.cxx @@ -4,1081 +4,1180 @@ #include "MuonSegmentCleaner/MuonPhiHitSelector.h" -#include "MuonReadoutGeometry/MdtReadoutElement.h" -#include "MuonReadoutGeometry/RpcReadoutElement.h" -#include "MuonReadoutGeometry/TgcReadoutElement.h" -#include "MuonReadoutGeometry/CscReadoutElement.h" -#include "MuonCompetingRIOsOnTrack/CompetingMuonClustersOnTrack.h" -#include "MuonRIO_OnTrack/MuonClusterOnTrack.h" +#include <Eigen/LU> +#include <ctime> +#include <iostream> +#include <list> +#include <sstream> +#include <vector> + +#include "CxxUtils/sincos.h" +#include "MuonCompetingRIOsOnTrack/CompetingMuonClustersOnTrack.h" +#include "MuonPrepRawData/MuonCluster.h" +#include "MuonRIO_OnTrack/CscClusterOnTrack.h" #include "MuonRIO_OnTrack/MdtDriftCircleOnTrack.h" +#include "MuonRIO_OnTrack/MuonClusterOnTrack.h" #include "MuonRIO_OnTrack/RpcClusterOnTrack.h" #include "MuonRIO_OnTrack/TgcClusterOnTrack.h" -#include "MuonRIO_OnTrack/CscClusterOnTrack.h" -#include "MuonPrepRawData/MuonCluster.h" -#include "TrkSurfaces/PlaneSurface.h" -#include "TrkRIO_OnTrack/RIO_OnTrack.h" +#include "MuonReadoutGeometry/CscReadoutElement.h" +#include "MuonReadoutGeometry/MdtReadoutElement.h" +#include "MuonReadoutGeometry/RpcReadoutElement.h" +#include "MuonReadoutGeometry/TgcReadoutElement.h" #include "TrkPrepRawData/PrepRawData.h" -#include "CxxUtils/sincos.h" +#include "TrkRIO_OnTrack/RIO_OnTrack.h" +#include "TrkSurfaces/PlaneSurface.h" -#include <sstream> -#include <iostream> -#include <vector> -#include <list> -#include <ctime> -#include <Eigen/LU> +MuonPhiHitSelector::MuonPhiHitSelector(const std::string& type, const std::string& name, const IInterface* parent) + : AthAlgTool(type, name, parent) +{ + declareInterface<IMuonHitSelector>(this); -MuonPhiHitSelector::MuonPhiHitSelector(const std::string& type,const std::string& name,const IInterface* parent) : - AthAlgTool(type,name,parent), - m_competingRIOsOnTrackTool("Muon::MuonCompetingClustersOnTrackCreator/MuonCompetingClustersOnTrackCreator"), - m_clusterCreator("Muon::MuonClusterOnTrackCreator/MuonClusterOnTrackCreator") { - declareInterface<IMuonHitSelector>(this); + m_cosmics = false; + declareProperty("DoCosmics", m_cosmics); - m_cosmics = false; - declareProperty("DoCosmics",m_cosmics); + m_summary = false; + declareProperty("DoSummary", m_summary); - m_summary = false; - declareProperty("DoSummary",m_summary); + // Create and write out the phi clusters or hits - // Create and write out the phi clusters or hits + m_makeClusters = false; + declareProperty("MakeClusters", m_makeClusters); + m_competingRios = false; - m_makeClusters = false; - declareProperty("MakeClusters",m_makeClusters); - m_competingRios = false; ; - declareProperty("CompetingRios",m_competingRios); + declareProperty("CompetingRios", m_competingRios); } -StatusCode MuonPhiHitSelector::initialize() +StatusCode +MuonPhiHitSelector::initialize() { - ATH_MSG_VERBOSE("MuonPhiHitSelector::Initializing"); - ATH_CHECK(m_competingRIOsOnTrackTool.retrieve()); - ATH_CHECK(m_clusterCreator.retrieve()); - ATH_CHECK(m_idHelperSvc.retrieve()); - ATH_MSG_VERBOSE("End of Initializing"); - return StatusCode::SUCCESS; + ATH_MSG_VERBOSE("MuonPhiHitSelector::Initializing"); + ATH_CHECK(m_competingRIOsOnTrackTool.retrieve()); + ATH_CHECK(m_clusterCreator.retrieve()); + ATH_CHECK(m_idHelperSvc.retrieve()); + ATH_MSG_VERBOSE("End of Initializing"); + return StatusCode::SUCCESS; } -std::vector<const Trk::MeasurementBase*>* MuonPhiHitSelector::select_rio( const double pmom, const std::vector<const Trk::RIO_OnTrack* >& associatedHits, const std::vector<const Trk::PrepRawData*>& unassociatedHits) const +std::vector<const Trk::MeasurementBase*>* +MuonPhiHitSelector::select_rio(const double pmom, const std::vector<const Trk::RIO_OnTrack*>& associatedHits, + const std::vector<const Trk::PrepRawData*>& unassociatedHits) const { - // Make Rios on Track + // Make Rios on Track - int time_start = std::clock()/1000; + int time_start = std::clock() / 1000; - std::vector<const Trk::MeasurementBase*>* selectedHits = new std::vector<const Trk::MeasurementBase*>() ; - std::vector<const Trk::MeasurementBase*>* selectedClusters = new std::vector<const Trk::MeasurementBase*>() ; + std::vector<const Trk::MeasurementBase*>* selectedHits = new std::vector<const Trk::MeasurementBase*>(); + std::vector<const Trk::MeasurementBase*>* selectedClusters = new std::vector<const Trk::MeasurementBase*>(); - ATH_MSG_VERBOSE("Executing MuonPhiHitSelectorTool select_rio "); + ATH_MSG_VERBOSE("Executing MuonPhiHitSelectorTool select_rio "); - int nhits = associatedHits.size() + unassociatedHits.size(); + int nhits = associatedHits.size() + unassociatedHits.size(); - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Executing MuonPhiHitSelectorTool nhits select_rio " << nhits); + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Executing MuonPhiHitSelectorTool nhits select_rio " << nhits); - std::vector<double> phiHitx(nhits); - std::vector<double> phiHity(nhits); - std::vector<double> phiHitz(nhits); - std::vector<double> phiError(nhits); - std::vector<Identifier> phiId(nhits); - std::vector<double> phiPull(nhits); - std::vector<int> phiSelect(nhits); - std::vector<int> phiMult(nhits); - std::vector<int> quality(nhits); - std::vector<const Trk::PrepRawData*> phiPrep(nhits); + std::vector<double> phiHitx(nhits); + std::vector<double> phiHity(nhits); + std::vector<double> phiHitz(nhits); + std::vector<double> phiError(nhits); + std::vector<Identifier> phiId(nhits); + std::vector<double> phiPull(nhits); + std::vector<int> phiSelect(nhits); + std::vector<int> phiMult(nhits); + std::vector<int> quality(nhits); + std::vector<const Trk::PrepRawData*> phiPrep(nhits); - std::map<Identifier,int> phiMapId; - int nphi = 0; - std::vector<const Trk::RIO_OnTrack* >::const_iterator it = associatedHits.begin(); - std::vector<const Trk::RIO_OnTrack* >::const_iterator it_end = associatedHits.end(); + std::map<Identifier, int> phiMapId; + int nphi = 0; + std::vector<const Trk::RIO_OnTrack*>::const_iterator it = associatedHits.begin(); + std::vector<const Trk::RIO_OnTrack*>::const_iterator it_end = associatedHits.end(); - for(; it != it_end ; ++it ) { - const Trk::PrepRawData* prd = (*it)->prepRawData(); - if (!prd) { - ATH_MSG_WARNING("prepRawData of associatedHits is nullptr, continuing..."); - continue; - } - Identifier id = prd->identify(); - phiId[nphi] = id; - Amg::Vector3D gHitPos = (*it)->globalPosition(); - if (m_idHelperSvc->isRpc(id) ) { - phiSelect[nphi] = 1; - } - else if (m_idHelperSvc->isTgc(id)) { - phiSelect[nphi] = 2; - } - else if (m_idHelperSvc->isCsc(id)) { - phiSelect[nphi] = 3; + for (; it != it_end; ++it) { + const Trk::PrepRawData* prd = (*it)->prepRawData(); + if (!prd) { + ATH_MSG_WARNING("prepRawData of associatedHits is nullptr, continuing..."); + continue; + } + Identifier id = prd->identify(); + phiId[nphi] = id; + Amg::Vector3D gHitPos = (*it)->globalPosition(); + if (m_idHelperSvc->isRpc(id)) { + phiSelect[nphi] = 1; + } else if (m_idHelperSvc->isTgc(id)) { + phiSelect[nphi] = 2; + } else if (m_idHelperSvc->isCsc(id)) { + phiSelect[nphi] = 3; + } + phiHitx[nphi] = gHitPos.x(); + phiHity[nphi] = gHitPos.y(); + phiHitz[nphi] = gHitPos.z(); + + const Amg::MatrixX& cov = (*it)->localCovariance(); + double error = cov(0, 0); + + // for the TGCs diagonalize the error matrix and use the smallest component + if (cov.cols() > 1) { + AmgMatrix(2, 2) Er; + Er(0, 0) = cov(0, 0); + Er(0, 1) = cov(0, 1); + Er(1, 1) = cov(1, 1); + Er(1, 0) = Er(0, 1); + + double chi = Er(0, 0) != Er(1, 1) ? std::atan(-2 * Er(0, 1) / (Er(0, 0) - Er(1, 1))) / 2. : 0.; + + CxxUtils::sincos scchi(chi); + + AmgMatrix(2, 2) Rot; + Rot(0, 0) = scchi.cs; + Rot(1, 1) = Rot(0, 0); + Rot(0, 1) = scchi.sn; + Rot(1, 0) = -Rot(0, 1); + AmgMatrix(2, 2) D = Rot.transpose() * Er * Rot; + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Diagonalized error matrix " << D); + error = D(0, 0) < D(1, 1) ? D(0, 0) : D(1, 1); + } + phiError[nphi] = std::sqrt(error); + quality[nphi] = 1000; + phiMapId[id] = 1; + phiPrep[nphi] = prd; + double phipos = std::atan2(phiHity[nphi], phiHitx[nphi]); + if (msgLvl(MSG::DEBUG)) + ATH_MSG_DEBUG("phi Segment Hit " << nphi << " det " << phiSelect[nphi] << " phi " << phipos); + nphi++; } - phiHitx[nphi] = gHitPos.x(); - phiHity[nphi] = gHitPos.y(); - phiHitz[nphi] = gHitPos.z(); - - const Amg::MatrixX& cov = (*it)->localCovariance(); - double error = cov(0,0); - - // for the TGCs diagonalize the error matrix and use the smallest component - if( cov.cols() > 1 ){ - AmgMatrix(2,2) Er; - Er(0,0) = cov(0,0); - Er(0,1) = cov(0,1); - Er(1,1) = cov(1,1); - Er(1,0) = Er(0,1); - - double chi = Er(0,0) != Er(1,1) ? std::atan(-2*Er(0,1)/(Er(0,0)-Er(1,1)))/2. : 0.; - - CxxUtils::sincos scchi(chi); - - AmgMatrix(2,2) Rot; - Rot(0,0) = scchi.cs; - Rot(1,1) = Rot(0,0); - Rot(0,1) = scchi.sn; - Rot(1,0) = -Rot(0,1); - AmgMatrix(2,2) D = Rot.transpose()*Er*Rot; - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Diagonalized error matrix " << D); - error = D(0,0) < D(1,1) ? D(0,0) : D(1,1); + int nphiseg = nphi; + + std::vector<const Trk::PrepRawData*>::const_iterator itu = unassociatedHits.begin(); + std::vector<const Trk::PrepRawData*>::const_iterator itu_end = unassociatedHits.end(); + + for (; itu != itu_end; ++itu) { + Identifier id = (*itu)->identify(); + phiId[nphi] = id; + // Skip phi hits already on segment + if (phiMapId.count(id) > 0) continue; + const Muon::MuonCluster* clus = dynamic_cast<const Muon::MuonCluster*>(*itu); + if (!clus) continue; + if (m_idHelperSvc->isRpc(id)) + phiSelect[nphi] = 1; + else if (m_idHelperSvc->isTgc(id)) + phiSelect[nphi] = 2; + else if (m_idHelperSvc->isCsc(id)) + phiSelect[nphi] = 3; + Amg::Vector3D gHitPos = clus->globalPosition(); + phiHitx[nphi] = gHitPos.x(); + phiHity[nphi] = gHitPos.y(); + phiHitz[nphi] = gHitPos.z(); + phiError[nphi] = (*itu)->localCovariance()(Trk::locX); + quality[nphi] = 10; + phiPrep[nphi] = *itu; + double phipos = std::atan2(phiHity[nphi], phiHitx[nphi]); + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("phi Pattern Hit " << nphi << " phi " << phipos); + nphi++; } - phiError[nphi] = std::sqrt(error); - quality[nphi] = 1000; - phiMapId[id] = 1; - phiPrep[nphi] = prd; - double phipos = std::atan2(phiHity[nphi],phiHitx[nphi]); - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("phi Segment Hit " << nphi << " det " << phiSelect[nphi] << " phi " << phipos); - nphi++; - } - int nphiseg = nphi; - - std::vector<const Trk::PrepRawData* >::const_iterator itu = unassociatedHits.begin(); - std::vector<const Trk::PrepRawData* >::const_iterator itu_end = unassociatedHits.end(); - - for(; itu != itu_end ; ++itu ) { - Identifier id = (*itu)->identify(); - phiId[nphi] = id; - // Skip phi hits already on segment - if (phiMapId.count(id) > 0) continue; - const Muon::MuonCluster* clus = dynamic_cast<const Muon::MuonCluster*>(*itu); - if( !clus ) continue; - if (m_idHelperSvc->isRpc(id)) phiSelect[nphi] = 1; - else if (m_idHelperSvc->isTgc(id)) phiSelect[nphi] = 2; - else if (m_idHelperSvc->isCsc(id)) phiSelect[nphi] = 3; - Amg::Vector3D gHitPos = clus->globalPosition(); - phiHitx[nphi] = gHitPos.x(); - phiHity[nphi] = gHitPos.y(); - phiHitz[nphi] = gHitPos.z(); - phiError[nphi] = (*itu)->localCovariance()(Trk::locX); - quality[nphi] = 10; - phiPrep[nphi] = *itu; - double phipos = std::atan2(phiHity[nphi],phiHitx[nphi]); - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("phi Pattern Hit " << nphi << " phi " << phipos); - nphi++; - } - - double chi2(0); - double r0(0); - int nfit; - std::vector<double> errorM(4); - double phi(DBL_MAX); - fitRecPhi( pmom, phiId, phiHitx, phiHity, phiHitz, phiError, quality, nphi, phiPull, phiMult, phiSelect, chi2, r0, phi, errorM, nfit); - - // Define global track parameters (not used 27-8 JS) - - for(int i = 0; i < nphi ; ++i ) { - if (phiSelect[i]>0) { - if (phiSelect[i] == 1) { - const Muon::RpcPrepData* prd = dynamic_cast <const Muon::RpcPrepData*> (phiPrep[i]); - const Amg::Vector3D globalpos(phiHitx[i],phiHity[i],phiHitz[i]); - const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd,globalpos); - if (rio) selectedHits->push_back(rio); - } - else if (phiSelect[i] == 2) { - const Muon::TgcPrepData* prd = dynamic_cast <const Muon::TgcPrepData*> (phiPrep[i]); - const Amg::Vector3D globalpos(phiHitx[i],phiHity[i],phiHitz[i]); - const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd,globalpos); - if (rio) selectedHits->push_back(rio); - } - else if (phiSelect[i] == 3) { - const Muon::CscPrepData* prd = dynamic_cast <const Muon::CscPrepData*> (phiPrep[i]); - const Amg::Vector3D globalpos(phiHitx[i],phiHity[i],phiHitz[i]); - const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd,globalpos); - if (rio) selectedHits->push_back(rio); - } - - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Make ONE rio per PrepData"); + + double chi2(0); + double r0(0); + int nfit; + std::vector<double> errorM(4); + double phi(DBL_MAX); + fitRecPhi(pmom, phiId, phiHitx, phiHity, phiHitz, phiError, quality, nphi, phiPull, phiMult, phiSelect, chi2, r0, + phi, errorM, nfit); + + // Define global track parameters (not used 27-8 JS) + + for (int i = 0; i < nphi; ++i) { + if (phiSelect[i] > 0) { + if (phiSelect[i] == 1) { + const Muon::RpcPrepData* prd = dynamic_cast<const Muon::RpcPrepData*>(phiPrep[i]); + const Amg::Vector3D globalpos(phiHitx[i], phiHity[i], phiHitz[i]); + const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd, globalpos); + if (rio) selectedHits->push_back(rio); + } else if (phiSelect[i] == 2) { + const Muon::TgcPrepData* prd = dynamic_cast<const Muon::TgcPrepData*>(phiPrep[i]); + const Amg::Vector3D globalpos(phiHitx[i], phiHity[i], phiHitz[i]); + const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd, globalpos); + if (rio) selectedHits->push_back(rio); + } else if (phiSelect[i] == 3) { + const Muon::CscPrepData* prd = dynamic_cast<const Muon::CscPrepData*>(phiPrep[i]); + const Amg::Vector3D globalpos(phiHitx[i], phiHity[i], phiHitz[i]); + const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd, globalpos); + if (rio) selectedHits->push_back(rio); + } + + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Make ONE rio per PrepData"); + } } - } - if (msgLvl(MSG::DEBUG)||m_summary) { - ATH_MSG_DEBUG("Fit hit results phi " << phi << " chi2 " << chi2 << " segment hits " << nphiseg << " pattern hits " << nphi-nphiseg << " nfit " << nfit << " rio size " << selectedHits->size()); - } - - std::vector<double> clusterX(nphi); - std::vector<double> clusterY(nphi); - std::vector<double> clusterZ(nphi); - std::vector<double> clusterError(nphi); - std::vector<Identifier> clusterId(nphi); - std::vector<int> clusterHits(nphi); - std::vector<double> clusterPull(nphi); - std::vector<int> clusterSelect(nphi); - // Link from hit to cluster - std::vector<int> clusterInt(nphi); - - int ncl,imax; - double chi2cl,r0cl, phicl; - std::vector<double> errorMcl(4); - clusterPhi(phiId, phiHitx, phiHity, phiHitz, phiError, phiPull, phiSelect, nphi, clusterX, clusterY, clusterZ, clusterError, clusterId, clusterHits, clusterSelect, clusterInt, ncl); - - - for(int ic = 0; ic < ncl ; ++ic ) { - std::list <const Trk::PrepRawData*> prdList; - int iic = -1; - double avError = 0.; - int ip = -1; - int np = 0; - for(int i = 0; i < nphi ; ++i ) { - if (clusterInt[i] == ic) { - ip = i; - prdList.push_back(phiPrep[i]); - avError += 1./(phiError[i]*phiError[i]); - if (clusterId[ic] == phiId[i]) iic = i; - np++; - } + if (msgLvl(MSG::DEBUG) || m_summary) { + ATH_MSG_DEBUG("Fit hit results phi " << phi << " chi2 " << chi2 << " segment hits " << nphiseg + << " pattern hits " << nphi - nphiseg << " nfit " << nfit << " rio size " + << selectedHits->size()); } - if (iic > -1) { - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi cluster found np " << np << " ip " << ip); - if (np ==1) { - // Only one PrepData: create RIO on Track - const Amg::Vector3D globalpos(clusterX[ic],clusterY[ic],clusterZ[ic]); - if (phiSelect[ip] == 1) { - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi RPC rio"); - const Muon::RpcPrepData* prd = dynamic_cast <const Muon::RpcPrepData*> (phiPrep[ip]); - const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd,globalpos); - if (rio) selectedClusters->push_back(rio); - } - else if (phiSelect[ip] == 2) { - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi TGC rio"); - const Muon::TgcPrepData* prd = dynamic_cast <const Muon::TgcPrepData*> (phiPrep[ip]); - const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd,globalpos); - if (rio) selectedClusters->push_back(rio); - } - else if (phiSelect[ip] == 3) { - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi CSC rio"); - const Muon::CscPrepData* prd = dynamic_cast <const Muon::CscPrepData*> (phiPrep[ip]); - const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd,globalpos); - if (rio) selectedClusters->push_back(rio); + + std::vector<double> clusterX(nphi); + std::vector<double> clusterY(nphi); + std::vector<double> clusterZ(nphi); + std::vector<double> clusterError(nphi); + std::vector<Identifier> clusterId(nphi); + std::vector<int> clusterHits(nphi); + std::vector<double> clusterPull(nphi); + std::vector<int> clusterSelect(nphi); + // Link from hit to cluster + std::vector<int> clusterInt(nphi); + + int ncl, imax; + double chi2cl, r0cl, phicl; + std::vector<double> errorMcl(4); + clusterPhi(phiId, phiHitx, phiHity, phiHitz, phiError, phiPull, phiSelect, nphi, clusterX, clusterY, clusterZ, + clusterError, clusterId, clusterHits, clusterSelect, clusterInt, ncl); + + + for (int ic = 0; ic < ncl; ++ic) { + std::list<const Trk::PrepRawData*> prdList; + int iic = -1; + double avError = 0.; + int ip = -1; + int np = 0; + for (int i = 0; i < nphi; ++i) { + if (clusterInt[i] == ic) { + ip = i; + prdList.push_back(phiPrep[i]); + avError += 1. / (phiError[i] * phiError[i]); + if (clusterId[ic] == phiId[i]) iic = i; + np++; + } } - } else { - - if (m_competingRios) { - // More PrepData's: create Competing RIOs on Track - avError = std::sqrt(1./avError); - double scaleFactor = clusterError[ic]/avError; - const Trk::CompetingRIOsOnTrack* rio = m_competingRIOsOnTrackTool->createBroadCluster(prdList,scaleFactor); - if (rio) selectedClusters->push_back(rio); - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Make competing rio/cluster " << " scale factor " << scaleFactor << " number of rios " << prdList.size()); + if (iic > -1) { + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi cluster found np " << np << " ip " << ip); + if (np == 1) { + // Only one PrepData: create RIO on Track + const Amg::Vector3D globalpos(clusterX[ic], clusterY[ic], clusterZ[ic]); + if (phiSelect[ip] == 1) { + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi RPC rio"); + const Muon::RpcPrepData* prd = dynamic_cast<const Muon::RpcPrepData*>(phiPrep[ip]); + const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd, globalpos); + if (rio) selectedClusters->push_back(rio); + } else if (phiSelect[ip] == 2) { + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi TGC rio"); + const Muon::TgcPrepData* prd = dynamic_cast<const Muon::TgcPrepData*>(phiPrep[ip]); + const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd, globalpos); + if (rio) selectedClusters->push_back(rio); + } else if (phiSelect[ip] == 3) { + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi CSC rio"); + const Muon::CscPrepData* prd = dynamic_cast<const Muon::CscPrepData*>(phiPrep[ip]); + const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd, globalpos); + if (rio) selectedClusters->push_back(rio); + } + } else { + + if (m_competingRios) { + // More PrepData's: create Competing RIOs on Track + avError = std::sqrt(1. / avError); + double scaleFactor = clusterError[ic] / avError; + const Trk::CompetingRIOsOnTrack* rio = + m_competingRIOsOnTrackTool->createBroadCluster(prdList, scaleFactor); + if (rio) selectedClusters->push_back(rio); + if (msgLvl(MSG::DEBUG)) + ATH_MSG_DEBUG("Make competing rio/cluster " + << " scale factor " << scaleFactor << " number of rios " << prdList.size()); + } else { + // Make one Rio for central cluster + ip = iic; + const Amg::Vector3D globalpos(clusterX[ic], clusterY[ic], clusterZ[ic]); + if (phiSelect[ip] == 1) { + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi RPC rio central cluster"); + const Muon::RpcPrepData* prd = dynamic_cast<const Muon::RpcPrepData*>(phiPrep[ip]); + const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd, globalpos); + if (rio) selectedClusters->push_back(rio); + } else if (phiSelect[ip] == 2) { + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi TGC rio central cluster"); + const Muon::TgcPrepData* prd = dynamic_cast<const Muon::TgcPrepData*>(phiPrep[ip]); + const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd, globalpos); + if (rio) selectedClusters->push_back(rio); + } else if (phiSelect[ip] == 3) { + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi CSC rio central cluster"); + const Muon::CscPrepData* prd = dynamic_cast<const Muon::CscPrepData*>(phiPrep[ip]); + const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd, globalpos); + if (rio) selectedClusters->push_back(rio); + } + } + } } else { - // Make one Rio for central cluster - ip = iic; - const Amg::Vector3D globalpos(clusterX[ic],clusterY[ic],clusterZ[ic]); - if (phiSelect[ip] == 1) { - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi RPC rio central cluster"); - const Muon::RpcPrepData* prd = dynamic_cast <const Muon::RpcPrepData*> (phiPrep[ip]); - const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd,globalpos); - if (rio) selectedClusters->push_back(rio); - } - else if (phiSelect[ip] == 2) { - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi TGC rio central cluster"); - const Muon::TgcPrepData* prd = dynamic_cast <const Muon::TgcPrepData*> (phiPrep[ip]); - const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd,globalpos); - if (rio) selectedClusters->push_back(rio); - } - else if (phiSelect[ip] == 3) { - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi CSC rio central cluster"); - const Muon::CscPrepData* prd = dynamic_cast <const Muon::CscPrepData*> (phiPrep[ip]); - const Muon::MuonClusterOnTrack* rio = m_clusterCreator->createRIO_OnTrack(*prd,globalpos); - if (rio) selectedClusters->push_back(rio); - } + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi cluster NOT found "); } - } - }else { - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Phi cluster NOT found "); } - } - fitPhiSL(pmom, clusterId, clusterX, clusterY, clusterZ, clusterError, clusterSelect, ncl, clusterPull, imax, chi2cl, r0cl, phicl, errorMcl , false ); + fitPhiSL(pmom, clusterId, clusterX, clusterY, clusterZ, clusterError, clusterSelect, ncl, clusterPull, imax, chi2cl, + r0cl, phicl, errorMcl, false); + + if (msgLvl(MSG::DEBUG) || m_summary) { + ATH_MSG_DEBUG("PhiHitSelector Time spent " << std::clock() / 1000 - time_start << " nhits " << nhits + << " segment hits " << associatedHits.size() << " nfit " << nfit + << " nclusters " << ncl); + ATH_MSG_DEBUG("Fit cluster results phi " << phicl << " chi2 " << chi2cl << " number of clusters " << ncl + << " size cluster Hits " << selectedClusters->size()); + } + if (m_makeClusters) { + std::vector<const Trk::MeasurementBase*>::iterator mit = selectedHits->begin(); + for (; mit != selectedHits->end(); ++mit) { + delete *mit; + } + delete selectedHits; + return selectedClusters; + } - if (msgLvl(MSG::DEBUG)||m_summary) { - ATH_MSG_DEBUG("PhiHitSelector Time spent " << std::clock()/1000-time_start << " nhits " << nhits << " segment hits " << associatedHits.size() << " nfit " << nfit << " nclusters " << ncl); - ATH_MSG_DEBUG("Fit cluster results phi " << phicl << " chi2 " << chi2cl << " number of clusters " << ncl << " size cluster Hits " << selectedClusters->size()); - } - if (m_makeClusters) { - std::vector<const Trk::MeasurementBase*>::iterator mit = selectedHits->begin(); - for (;mit!=selectedHits->end();++mit){ - delete *mit; + std::vector<const Trk::MeasurementBase*>::iterator mit = selectedClusters->begin(); + for (; mit != selectedClusters->end(); ++mit) { + delete *mit; } - delete selectedHits; - return selectedClusters; - } - - std::vector<const Trk::MeasurementBase*>::iterator mit = selectedClusters->begin(); - for (;mit!=selectedClusters->end();++mit){ - delete *mit; - } - delete selectedClusters; - return selectedHits; + delete selectedClusters; + return selectedHits; } -void MuonPhiHitSelector::clusterPhi( const std::vector<Identifier> & id, const std::vector<double> & hitx, const std::vector<double> & hity, const std::vector<double> & hitz, const std::vector<double> & error, const std::vector<double> & pull, std::vector<int> & select, const int n, std::vector<double> & clusterX , std::vector<double> & clusterY ,std::vector<double> & clusterZ , std::vector<double> & clusterError , std::vector<Identifier> & clusterId, std::vector<int> & clusterHits, std::vector<int> & clusterSelect, std::vector<int> & clusterInt, int & ncl ) const { - - // - // Use hits (select > 0) and pulls to make clusters - // - // - // Inputs - // id = identifiers hits - // hitx hity hitz = position in space - // error = associated error (in x-y plane) - // pull (from fit)= residual (hit -fit) /error - // select = > 0 for selected hits - // n = total number of hits - - // Outputs - // clusterX Y Z = cluster positions - // clusterError = errors - // clusterId = cluster identifier (smallest pull) - // clusterHits = number of hits per cluster - // ncl = number of clusters - // chi2 = total chi2 - // r0 = perigee parameter of fit (0,0) - // phi = azimuthal angle of fit at perigee - - - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Start phi clustering"); - - ncl = 0; - if (n ==0) return; - - std::vector<int> scode(n); - - for(int i = 0; i < n ; ++i ) { - Identifier idi = id[i]; - int code = 0; - if (m_idHelperSvc->isRpc( idi )) { - int doubZ = m_idHelperSvc->rpcIdHelper().doubletZ(idi); - int doubPhi = m_idHelperSvc->rpcIdHelper().doubletPhi(idi); - code = 100000000*(m_idHelperSvc->rpcIdHelper().stationName(idi))+1000000*(m_idHelperSvc->rpcIdHelper().stationPhi(idi))+ 10000* ((m_idHelperSvc->rpcIdHelper().stationEta(idi))+1000); - code += 1000*(doubZ-1) + 100*(doubPhi-1); - code += 2*((m_idHelperSvc->rpcIdHelper().doubletR(idi))-1) + 16*((m_idHelperSvc->rpcIdHelper().gasGap(idi))-1) ; - } - else if (m_idHelperSvc->isTgc( idi )) { - code = 1000000*(m_idHelperSvc->tgcIdHelper().stationName(idi))+10000*(m_idHelperSvc->tgcIdHelper().stationPhi(idi))+ 100* ((m_idHelperSvc->tgcIdHelper().stationEta(idi))+10); - code = code + m_idHelperSvc->tgcIdHelper().gasGap(idi); +void +MuonPhiHitSelector::clusterPhi(const std::vector<Identifier>& id, const std::vector<double>& hitx, + const std::vector<double>& hity, const std::vector<double>& hitz, + const std::vector<double>& error, const std::vector<double>& pull, + std::vector<int>& select, const int n, std::vector<double>& clusterX, + std::vector<double>& clusterY, std::vector<double>& clusterZ, + std::vector<double>& clusterError, std::vector<Identifier>& clusterId, + std::vector<int>& clusterHits, std::vector<int>& clusterSelect, + std::vector<int>& clusterInt, int& ncl) const +{ + + // + // Use hits (select > 0) and pulls to make clusters + // + // + // Inputs + // id = identifiers hits + // hitx hity hitz = position in space + // error = associated error (in x-y plane) + // pull (from fit)= residual (hit -fit) /error + // select = > 0 for selected hits + // n = total number of hits + + // Outputs + // clusterX Y Z = cluster positions + // clusterError = errors + // clusterId = cluster identifier (smallest pull) + // clusterHits = number of hits per cluster + // ncl = number of clusters + // chi2 = total chi2 + // r0 = perigee parameter of fit (0,0) + // phi = azimuthal angle of fit at perigee + + + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Start phi clustering"); + + ncl = 0; + if (n == 0) return; + + std::vector<int> scode(n); + + for (int i = 0; i < n; ++i) { + Identifier idi = id[i]; + int code = 0; + if (m_idHelperSvc->isRpc(idi)) { + int doubZ = m_idHelperSvc->rpcIdHelper().doubletZ(idi); + int doubPhi = m_idHelperSvc->rpcIdHelper().doubletPhi(idi); + code = 100000000 * (m_idHelperSvc->rpcIdHelper().stationName(idi)) + + 1000000 * (m_idHelperSvc->rpcIdHelper().stationPhi(idi)) + + 10000 * ((m_idHelperSvc->rpcIdHelper().stationEta(idi)) + 1000); + code += 1000 * (doubZ - 1) + 100 * (doubPhi - 1); + code += 2 * ((m_idHelperSvc->rpcIdHelper().doubletR(idi)) - 1) + + 16 * ((m_idHelperSvc->rpcIdHelper().gasGap(idi)) - 1); + } else if (m_idHelperSvc->isTgc(idi)) { + code = 1000000 * (m_idHelperSvc->tgcIdHelper().stationName(idi)) + + 10000 * (m_idHelperSvc->tgcIdHelper().stationPhi(idi)) + + 100 * ((m_idHelperSvc->tgcIdHelper().stationEta(idi)) + 10); + code = code + m_idHelperSvc->tgcIdHelper().gasGap(idi); + } else if (m_idHelperSvc->isCsc(idi)) { + code = 1000000 * (m_idHelperSvc->cscIdHelper().stationName(idi)) + + 10000 * (m_idHelperSvc->cscIdHelper().stationPhi(idi)) + + 100 * ((m_idHelperSvc->cscIdHelper().stationEta(idi)) + 10); + code = code + m_idHelperSvc->cscIdHelper().wireLayer(idi); + } + scode[i] = code; } - else if (m_idHelperSvc->isCsc( idi )) { - code = 1000000*(m_idHelperSvc->cscIdHelper().stationName(idi))+10000*(m_idHelperSvc->cscIdHelper().stationPhi(idi))+ 100* ((m_idHelperSvc->cscIdHelper().stationEta(idi))+10); - code = code + m_idHelperSvc->cscIdHelper().wireLayer(idi); + + // std::vector<int> clusterInt(n); + + for (int i = 0; i < n; ++i) { + clusterInt[i] = -1; } - scode[i] = code; - } - - // std::vector<int> clusterInt(n); - - for(int i = 0; i < n ; ++i ) { - clusterInt[i] = -1; - } - - int icl = -1; - for (int i = 0; i < n ; ++i ) { - if ( error[i] != 0 && select[i] > 0 && clusterInt[i] == -1 ) { - icl++; - clusterInt[i] = icl; - for (int j = i+1; j < n ; ++j ) { - if (clusterInt[j] == -1 ) { - if ( error[j] != 0 && select[j] > 0 ) { - if (scode[i] == scode [j]) clusterInt[j] = icl; - } - } - } + + int icl = -1; + for (int i = 0; i < n; ++i) { + if (error[i] != 0 && select[i] > 0 && clusterInt[i] == -1) { + icl++; + clusterInt[i] = icl; + for (int j = i + 1; j < n; ++j) { + if (clusterInt[j] == -1) { + if (error[j] != 0 && select[j] > 0) { + if (scode[i] == scode[j]) clusterInt[j] = icl; + } + } + } + } } - } - - std::vector<double> clusterCommon2Error(icl+1); - std::vector<int> clusterCode(icl+1); - ncl = icl+1; - for (int ic = 0; ic < icl+1 ; ++ic ) { - clusterX[ic] = 0.; - clusterY[ic] = 0.; - clusterZ[ic] = 0.; - clusterError[ic] = 0.; - clusterCommon2Error[ic] = 0.; - clusterHits[ic] = 0; - clusterCode[ic] = 0; - clusterSelect[ic] = 0; - double pullMax = 10.; - for (int i = 0; i < n ; ++i ) { - if (select[i] > 0) { - if (ic == clusterInt[i] ) { - clusterSelect[ic] = select[i]; - double w = 1./(error[i]*error[i]); - clusterX[ic]+= hitx[i]*w; - clusterY[ic]+= hity[i]*w; - clusterZ[ic]+= hitz[i]*w; - clusterError[ic]+= w; - if ( std::abs(pull[i]) < std::abs(pullMax)) { - pullMax = pull[i]; - clusterId[ic] = id[i]; - clusterCode[ic] = scode[i]; - clusterSelect[ic] = select[i]; - } - clusterHits[ic]++; - if (clusterHits[ic] == 1) clusterCommon2Error[ic]= 0.; - } - } - } - clusterX[ic] = clusterX[ic]/clusterError[ic]; - clusterY[ic] = clusterY[ic]/clusterError[ic]; - clusterZ[ic] = clusterZ[ic]/clusterError[ic]; -// Don't assume improvement on errors due to clustering - clusterError[ic]= std::sqrt(clusterHits[ic])/std::sqrt(clusterError[ic]); - if (msgLvl(MSG::DEBUG)) { - ATH_MSG_DEBUG("cluster phi " << ic << " x " << clusterX[ic] << " y " << clusterY[ic] << " z " << clusterZ[ic] << " error " << clusterError[ic] << " hits " << clusterHits[ic] << " select " << clusterSelect[ic] << " Code " << clusterCode[ic]); + + std::vector<double> clusterCommon2Error(icl + 1); + std::vector<int> clusterCode(icl + 1); + ncl = icl + 1; + for (int ic = 0; ic < icl + 1; ++ic) { + clusterX[ic] = 0.; + clusterY[ic] = 0.; + clusterZ[ic] = 0.; + clusterError[ic] = 0.; + clusterCommon2Error[ic] = 0.; + clusterHits[ic] = 0; + clusterCode[ic] = 0; + clusterSelect[ic] = 0; + double pullMax = 10.; + for (int i = 0; i < n; ++i) { + if (select[i] > 0) { + if (ic == clusterInt[i]) { + clusterSelect[ic] = select[i]; + double w = 1. / (error[i] * error[i]); + clusterX[ic] += hitx[i] * w; + clusterY[ic] += hity[i] * w; + clusterZ[ic] += hitz[i] * w; + clusterError[ic] += w; + if (std::abs(pull[i]) < std::abs(pullMax)) { + pullMax = pull[i]; + clusterId[ic] = id[i]; + clusterCode[ic] = scode[i]; + clusterSelect[ic] = select[i]; + } + clusterHits[ic]++; + if (clusterHits[ic] == 1) clusterCommon2Error[ic] = 0.; + } + } + } + clusterX[ic] = clusterX[ic] / clusterError[ic]; + clusterY[ic] = clusterY[ic] / clusterError[ic]; + clusterZ[ic] = clusterZ[ic] / clusterError[ic]; + // Don't assume improvement on errors due to clustering + clusterError[ic] = std::sqrt(clusterHits[ic]) / std::sqrt(clusterError[ic]); + if (msgLvl(MSG::DEBUG)) { + ATH_MSG_DEBUG("cluster phi " << ic << " x " << clusterX[ic] << " y " << clusterY[ic] << " z " + << clusterZ[ic] << " error " << clusterError[ic] << " hits " << clusterHits[ic] + << " select " << clusterSelect[ic] << " Code " << clusterCode[ic]); + } } - } - } -void MuonPhiHitSelector::fitRecPhi( const double pmom, const std::vector<Identifier> & phiId, const std::vector<double> & phiHitx, const std::vector<double> & phiHity, const std::vector<double> & phiHitz, const std::vector<double> & phiError, std::vector<int> & quality, const int nphi, std::vector<double> & phiPull, std::vector<int> & phiMult, std::vector<int> & phiSelect, double & chi2, double & r0, double & phi, std::vector<double> & errorM, int & nfit) const { - - // - // Use reconstructed hits to perform fit for phi - // - - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Start phi fit reconstruction"); - - chi2 =0.; - r0 = 0.; - nfit = 0; - phi =0.; - - int ncsc = 0; - int ntgc = 0; - int nrpc = 0; - - - if (nphi ==0) return; - - std::vector<double> error0(nphi); - std::vector<double> error(nphi); - std::vector<double> errorf(nphi); - std::vector<int> scode(nphi); - std::vector<int> srcode(nphi); - std::vector<int> phiSelectKeep(nphi); - std::map<int,int> clusters; - std::map<int,int> clustersr; - std::map<int,int> clusterspat; - - for(int i = 0; i < nphi ; ++i ) { - - Identifier idi = phiId[i]; - int code = 0; - int rcode = 0; - if (m_idHelperSvc->isRpc( idi )) { - code = 1000000*(m_idHelperSvc->rpcIdHelper().stationName(idi))+10000*(m_idHelperSvc->rpcIdHelper().stationPhi(idi))+ 100* ((m_idHelperSvc->rpcIdHelper().stationEta(idi))+10); - code = code + 2*((m_idHelperSvc->rpcIdHelper().doubletR(idi))-1)+16*((m_idHelperSvc->rpcIdHelper().gasGap(idi))-1); - rcode = 1000000*(m_idHelperSvc->rpcIdHelper().stationName(idi))+10000*(m_idHelperSvc->rpcIdHelper().stationPhi(idi))+ 0* ((m_idHelperSvc->rpcIdHelper().stationEta(idi))+10); - rcode = rcode + 2*((m_idHelperSvc->rpcIdHelper().doubletR(idi))-1)+16*((m_idHelperSvc->rpcIdHelper().gasGap(idi))-1); +void +MuonPhiHitSelector::fitRecPhi(const double pmom, const std::vector<Identifier>& phiId, + const std::vector<double>& phiHitx, const std::vector<double>& phiHity, + const std::vector<double>& phiHitz, const std::vector<double>& phiError, + std::vector<int>& quality, const int nphi, std::vector<double>& phiPull, + std::vector<int>& phiMult, std::vector<int>& phiSelect, double& chi2, double& r0, + double& phi, std::vector<double>& errorM, int& nfit) const +{ + + // + // Use reconstructed hits to perform fit for phi + // + + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Start phi fit reconstruction"); + + chi2 = 0.; + r0 = 0.; + nfit = 0; + phi = 0.; + + int ncsc = 0; + int ntgc = 0; + int nrpc = 0; + + + if (nphi == 0) return; + + std::vector<double> error0(nphi); + std::vector<double> error(nphi); + std::vector<double> errorf(nphi); + std::vector<int> scode(nphi); + std::vector<int> srcode(nphi); + std::vector<int> phiSelectKeep(nphi); + std::map<int, int> clusters; + std::map<int, int> clustersr; + std::map<int, int> clusterspat; + + for (int i = 0; i < nphi; ++i) { + + Identifier idi = phiId[i]; + int code = 0; + int rcode = 0; + if (m_idHelperSvc->isRpc(idi)) { + code = 1000000 * (m_idHelperSvc->rpcIdHelper().stationName(idi)) + + 10000 * (m_idHelperSvc->rpcIdHelper().stationPhi(idi)) + + 100 * ((m_idHelperSvc->rpcIdHelper().stationEta(idi)) + 10); + code = code + 2 * ((m_idHelperSvc->rpcIdHelper().doubletR(idi)) - 1) + + 16 * ((m_idHelperSvc->rpcIdHelper().gasGap(idi)) - 1); + rcode = 1000000 * (m_idHelperSvc->rpcIdHelper().stationName(idi)) + + 10000 * (m_idHelperSvc->rpcIdHelper().stationPhi(idi)) + + 0 * ((m_idHelperSvc->rpcIdHelper().stationEta(idi)) + 10); + rcode = rcode + 2 * ((m_idHelperSvc->rpcIdHelper().doubletR(idi)) - 1) + + 16 * ((m_idHelperSvc->rpcIdHelper().gasGap(idi)) - 1); + } else if (m_idHelperSvc->isTgc(idi)) { + code = 1000000 * (m_idHelperSvc->tgcIdHelper().stationName(idi)) + + 10000 * (m_idHelperSvc->tgcIdHelper().stationPhi(idi)) + + 100 * ((m_idHelperSvc->tgcIdHelper().stationEta(idi)) + 10); + code = code + m_idHelperSvc->tgcIdHelper().gasGap(idi); + rcode = 1000000 * (m_idHelperSvc->tgcIdHelper().stationName(idi)) + + 10000 * (m_idHelperSvc->tgcIdHelper().stationPhi(idi)) + + 0 * ((m_idHelperSvc->tgcIdHelper().stationEta(idi)) + 10); + rcode = rcode + m_idHelperSvc->tgcIdHelper().gasGap(idi); + } else if (m_idHelperSvc->isCsc(idi)) { + code = 1000000 * (m_idHelperSvc->cscIdHelper().stationName(idi)) + + 10000 * (m_idHelperSvc->cscIdHelper().stationPhi(idi)) + + 100 * ((m_idHelperSvc->cscIdHelper().stationEta(idi)) + 10); + code = code + m_idHelperSvc->cscIdHelper().wireLayer(idi); + rcode = 1000000 * (m_idHelperSvc->cscIdHelper().stationName(idi)) + + 10000 * (m_idHelperSvc->cscIdHelper().stationPhi(idi)) + + 0 * ((m_idHelperSvc->cscIdHelper().stationEta(idi)) + 10); + rcode = rcode + m_idHelperSvc->cscIdHelper().wireLayer(idi); + } + + scode[i] = code; + srcode[i] = rcode; + int idet = 0; + if (m_idHelperSvc->isRpc(idi)) + idet = 1; + else if (m_idHelperSvc->isTgc(idi)) + idet = 2; + else if (m_idHelperSvc->isCsc(idi)) + idet = 3; + phiSelect[i] = idet; + phiSelectKeep[i] = idet; } - else if (m_idHelperSvc->isTgc( idi )) { - code = 1000000*(m_idHelperSvc->tgcIdHelper().stationName(idi))+10000*(m_idHelperSvc->tgcIdHelper().stationPhi(idi))+ 100* ((m_idHelperSvc->tgcIdHelper().stationEta(idi))+10); - code = code + m_idHelperSvc->tgcIdHelper().gasGap(idi); - rcode = 1000000*(m_idHelperSvc->tgcIdHelper().stationName(idi))+10000*(m_idHelperSvc->tgcIdHelper().stationPhi(idi))+ 0* ((m_idHelperSvc->tgcIdHelper().stationEta(idi))+10); - rcode = rcode + m_idHelperSvc->tgcIdHelper().gasGap(idi); + // Hits on segments + for (int i = 0; i < nphi; ++i) { + if (phiError[i] != 0 && quality[i] > 100) { + clusters[scode[i]]++; + clustersr[srcode[i]]++; + } } - else if (m_idHelperSvc->isCsc( idi )) { - code = 1000000*(m_idHelperSvc->cscIdHelper().stationName(idi))+10000*(m_idHelperSvc->cscIdHelper().stationPhi(idi))+ 100* ((m_idHelperSvc->cscIdHelper().stationEta(idi))+10); - code = code + m_idHelperSvc->cscIdHelper().wireLayer(idi); - rcode = 1000000*(m_idHelperSvc->cscIdHelper().stationName(idi))+10000*(m_idHelperSvc->cscIdHelper().stationPhi(idi))+ 0* ((m_idHelperSvc->cscIdHelper().stationEta(idi))+10); - rcode = rcode + m_idHelperSvc->cscIdHelper().wireLayer(idi); + // Drop hits on patterns that are in same station and layer as segment hit + // Avoid adding again (solved) ambiguous hits + + for (int i = 0; i < nphi; ++i) { + if (phiError[i] != 0 && quality[i] > 0 && quality[i] < 100) { + if (clustersr.count(srcode[i]) > 0) { + quality[i] = 0; + } else { + clusterspat[scode[i]]++; + } + } } - scode[i] = code; - srcode[i] = rcode; - int idet = 0; - if (m_idHelperSvc->isRpc(idi)) idet = 1; - else if (m_idHelperSvc->isTgc(idi)) idet = 2; - else if (m_idHelperSvc->isCsc(idi)) idet = 3; - phiSelect[i] = idet; - phiSelectKeep[i] = idet; - } - // Hits on segments - for(int i = 0; i < nphi ; ++i ) { - if ( phiError[i] != 0 && quality[i] > 100 ) { - clusters[scode[i]]++; - clustersr[srcode[i]]++; - } - } - // Drop hits on patterns that are in same station and layer as segment hit - // Avoid adding again (solved) ambiguous hits - - for(int i = 0; i < nphi ; ++i ) { - if (phiError[i] != 0 && quality[i]>0 && quality[i] < 100) { - if (clustersr.count(srcode[i]) > 0) { - quality[i] = 0; - } else { - clusterspat[scode[i]]++; - } - } - } - - // Assign errors according to multiplicities - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("phi hits " << nphi << " segment clusters " << clusters.size() << " pattern clusters " << clusterspat.size()); - - for(int i = 0; i < nphi ; ++i ) { - error0[i] = 0; - Identifier id = phiId[i]; - phiMult[i] = 0; - if ( phiError[i] != 0 && quality[i] > 0 ) { - int n = 0; - if (quality[i] > 100 ) { - n = clusters[scode[i]]; -// Treat phi hits from segment with high multiplicity > 10 as lying on patterm - if (n > 10) quality[i] = 10; - } else if (quality[i] < 100 ) { - n = clusterspat[scode[i]]; -// Drop phi hits patterns with high multiplicity - if (clusters.count(scode[i])==1 || n > 10) { - n = 0; - // drop phi hits from pattern if already segment hits in same layer - quality[i] = 0; - phiSelect[i] = 0; - phiSelectKeep[i] = 0; - continue; - } - } - phiMult[i] = n; - double fact = 1.; - if (m_idHelperSvc->isRpc(id)) fact = 1.2; - else if (m_idHelperSvc->isTgc(id)) n = 1; - else if (m_idHelperSvc->isCsc(id)) n = 1; - - error0[i]=phiError[i]*std::sqrt(n)*fact; - error[i]=phiError[i]*std::sqrt(n)*fact; - double phiHit = std::atan2 ( phiHity[i], phiHitx[i] ); - if (msgLvl(MSG::DEBUG)) { - ATH_MSG_DEBUG(i << " Station " << int(scode[i]/1000000) << " Hit x " << phiHitx[i] << " Hit y " << phiHity[i] << " Hit z " << phiHitz[i] << " error " << phiError[i] << " phi Hit " << phiHit); - ATH_MSG_DEBUG("station " << phiSelect[i]); - ATH_MSG_DEBUG("code " << scode[i] << " multiplicity " << n << " error " << error0[i] << " quality " << quality[i]); - if ( error0[i] < 1. ) ATH_MSG_DEBUG("TOO small error "); - } + // Assign errors according to multiplicities + if (msgLvl(MSG::DEBUG)) + ATH_MSG_DEBUG("phi hits " << nphi << " segment clusters " << clusters.size() << " pattern clusters " + << clusterspat.size()); + + for (int i = 0; i < nphi; ++i) { + error0[i] = 0; + Identifier id = phiId[i]; + phiMult[i] = 0; + if (phiError[i] != 0 && quality[i] > 0) { + int n = 0; + if (quality[i] > 100) { + n = clusters[scode[i]]; + // Treat phi hits from segment with high multiplicity > 10 as lying on patterm + if (n > 10) quality[i] = 10; + } else if (quality[i] < 100) { + n = clusterspat[scode[i]]; + // Drop phi hits patterns with high multiplicity + if (clusters.count(scode[i]) == 1 || n > 10) { + n = 0; + // drop phi hits from pattern if already segment hits in same layer + quality[i] = 0; + phiSelect[i] = 0; + phiSelectKeep[i] = 0; + continue; + } + } + phiMult[i] = n; + double fact = 1.; + if (m_idHelperSvc->isRpc(id)) + fact = 1.2; + else if (m_idHelperSvc->isTgc(id)) + n = 1; + else if (m_idHelperSvc->isCsc(id)) + n = 1; + + error0[i] = phiError[i] * std::sqrt(n) * fact; + error[i] = phiError[i] * std::sqrt(n) * fact; + double phiHit = std::atan2(phiHity[i], phiHitx[i]); + if (msgLvl(MSG::DEBUG)) { + ATH_MSG_DEBUG(i << " Station " << int(scode[i] / 1000000) << " Hit x " << phiHitx[i] << " Hit y " + << phiHity[i] << " Hit z " << phiHitz[i] << " error " << phiError[i] << " phi Hit " + << phiHit); + ATH_MSG_DEBUG("station " << phiSelect[i]); + ATH_MSG_DEBUG("code " << scode[i] << " multiplicity " << n << " error " << error0[i] << " quality " + << quality[i]); + if (error0[i] < 1.) ATH_MSG_DEBUG("TOO small error "); + } + } } - } - // Count layers hit + // Count layers hit - std::map<int,int> layersHit; - for(int i = 0; i < nphi ; ++i ) { - if ( phiError[i] != 0 && quality[i] > 0 ) { - layersHit[srcode[i]]++; - } - } - int allLayerHits = layersHit.size(); - int allLayerRecoHits = 0; - double pfit = 20000.; - - for (int iqua = 0; iqua < 3 ; ++iqua ) { - - double quacut = 10; - if (iqua == 1 ) quacut = 0; - else if (iqua == 2 ) { - quacut = 10; - pfit = pmom; - } - - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Quality loop " << iqua << " quality cut " << quacut); - int nsel = 0; - int nselseg = 0; - for(int i = 0; i < nphi ; ++i ) { - - if (iqua == 1) phiSelect[i] = phiSelectKeep[i]; - - if ( phiError[i] != 0 && quality[i] > quacut ) { - nsel++; - if (quality[i]>100) nselseg++; - if (quality[i]== 10 && iqua == 1) quality[i] = 11; - } else { - phiSelect[i] = 0; - } - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("index i " << i << " phiSelect " << phiSelect[i] << " Quality " << quality[i] << " error " << error[i]); + std::map<int, int> layersHit; + for (int i = 0; i < nphi; ++i) { + if (phiError[i] != 0 && quality[i] > 0) { + layersHit[srcode[i]]++; + } } + int allLayerHits = layersHit.size(); + int allLayerRecoHits = 0; + double pfit = 20000.; + + for (int iqua = 0; iqua < 3; ++iqua) { + + double quacut = 10; + if (iqua == 1) + quacut = 0; + else if (iqua == 2) { + quacut = 10; + pfit = pmom; + } - int imax = -1; - if (iqua ==1 && nselseg> 0) { - // Test and drop pattern Hits if far off - double errorScaleFactor = 25.; - std::vector<int> phiPatSelect(nphi,0); - for(int i = 0; i < nphi ; ++i ) { - phiPatSelect[i] = 0; - if( phiSelect[i] > 0 && quality[i] > 0 && quality[i] < 100 ) { - phiPatSelect[i] = 1; - error[i] = errorScaleFactor*error[i]; + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Quality loop " << iqua << " quality cut " << quacut); + int nsel = 0; + int nselseg = 0; + for (int i = 0; i < nphi; ++i) { + + if (iqua == 1) phiSelect[i] = phiSelectKeep[i]; + + if (phiError[i] != 0 && quality[i] > quacut) { + nsel++; + if (quality[i] > 100) nselseg++; + if (quality[i] == 10 && iqua == 1) quality[i] = 11; + } else { + phiSelect[i] = 0; + } + if (msgLvl(MSG::DEBUG)) + ATH_MSG_DEBUG("index i " << i << " phiSelect " << phiSelect[i] << " Quality " << quality[i] << " error " + << error[i]); } - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("select " << phiSelect[i] << " quality " << quality[i] << " error " << error[i]); - } - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("performing outlier removal for pattern hits "); - fitPhiSL(pfit, phiId, phiHitx, phiHity, phiHitz, error, phiSelect, nphi, phiPull, imax, chi2, r0, phi, errorM , false); - for(int i = 0; i < nphi ; ++i ) { - if(phiPatSelect[i] == 1) { - error[i] = error[i]/errorScaleFactor; - double rescaledPull = phiPull[i]*errorScaleFactor; - // 3 sigma cut - if (std::abs(rescaledPull) < 3.) { - phiSelect[i] = phiSelectKeep[i]; - } else { - phiSelect[i] = 0; - phiSelectKeep[i] = 0; - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Drop Pattern Hits with Quality == 1 " << i << " quality " << quality[i] << " Pull " << rescaledPull << " phiSelect " << phiSelect[i]); - } + + int imax = -1; + if (iqua == 1 && nselseg > 0) { + // Test and drop pattern Hits if far off + double errorScaleFactor = 25.; + std::vector<int> phiPatSelect(nphi, 0); + for (int i = 0; i < nphi; ++i) { + phiPatSelect[i] = 0; + if (phiSelect[i] > 0 && quality[i] > 0 && quality[i] < 100) { + phiPatSelect[i] = 1; + error[i] = errorScaleFactor * error[i]; + } + if (msgLvl(MSG::DEBUG)) + ATH_MSG_DEBUG("select " << phiSelect[i] << " quality " << quality[i] << " error " << error[i]); + } + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("performing outlier removal for pattern hits "); + fitPhiSL(pfit, phiId, phiHitx, phiHity, phiHitz, error, phiSelect, nphi, phiPull, imax, chi2, r0, phi, + errorM, false); + for (int i = 0; i < nphi; ++i) { + if (phiPatSelect[i] == 1) { + error[i] = error[i] / errorScaleFactor; + double rescaledPull = phiPull[i] * errorScaleFactor; + // 3 sigma cut + if (std::abs(rescaledPull) < 3.) { + phiSelect[i] = phiSelectKeep[i]; + } else { + phiSelect[i] = 0; + phiSelectKeep[i] = 0; + if (msgLvl(MSG::DEBUG)) + ATH_MSG_DEBUG("Drop Pattern Hits with Quality == 1 " + << i << " quality " << quality[i] << " Pull " << rescaledPull << " phiSelect " + << phiSelect[i]); + } + } + } + } + + const double pfitc = pfit; + imax = -1; + + if (iqua == 2) { + // low momentum fit with scaled error (factor 10) for dropped segment hits + std::vector<int> phiReSelect(nphi); + for (int i = 0; i < nphi; ++i) { + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("select " << phiSelect[i] << " quality " << quality[i]); + phiReSelect[i] = 0; + if (phiSelect[i] == 0 && quality[i] > 99) { + phiReSelect[i] = 1; + phiSelect[i] = phiSelectKeep[i]; + error[i] = 10. * error[i]; + } + } + fitPhiSL(pfitc, phiId, phiHitx, phiHity, phiHitz, error, phiSelect, nphi, phiPull, imax, chi2, r0, phi, + errorM, false); + for (int i = 0; i < nphi; ++i) { + if (phiReSelect[i] == 1) { + error[i] = error[i] / 10.; + // 10 sigma cut (error rescale = 10) + if (std::abs(phiPull[i]) < 1) { + phiSelect[i] = phiSelectKeep[i]; + } else { + phiSelect[i] = 0; + } + if (msgLvl(MSG::DEBUG)) + ATH_MSG_DEBUG("Low momentum Quality == 2 add hit nr " + << i << " quality " << quality[i] << " Pull " << phiPull[i] << " phiSelect " + << phiSelect[i]); + } + } + } + if (iqua == 1 && msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Quality loop "); + nsel = 0; + for (int i = 0; i < nphi; ++i) { + errorf[i] = error[i]; + if (iqua == 1) phiSelect[i] = phiSelectKeep[i]; + + if (phiError[i] != 0 && quality[i] > quacut) { + nsel++; + if (quality[i] == 10 && iqua == 1) quality[i] = 11; + } else { + phiSelect[i] = 0; + } + } + + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Selected PHI hits in fit " << nsel << " iqua " << iqua); + if (nsel == 0) continue; + + int niter = -1; + // do hit dropping in maximal 10 iterations by putting quality to 0 + + for (int iter = 0; iter < 100; ++iter) { + niter++; + double power = (iter - 10) / 20.; + if (power < 0.) power = 0.; + chi2 = 0.; + nfit = 0; + if (iter > 10) { + // Shower treatment inflate errors with multiplicity + for (int i = 0; i < nphi; ++i) { + errorf[i] = error[i] * std::pow(phiMult[i], power); + } + } + fitPhiSL(pfitc, phiId, phiHitx, phiHity, phiHitz, errorf, phiSelect, nphi, phiPull, imax, chi2, r0, phi, + errorM, false); + + ncsc = 0; + ntgc = 0; + nrpc = 0; + + // Count layers hit in Reconstruction + + std::map<int, int> layersRecoHit; + + for (int i = 0; i < nphi; ++i) { + Identifier id = phiId[i]; + if (error[i] == 0 || quality[i] < quacut) phiSelect[i] = 0; + if (error[i] != 0 && quality[i] > quacut) { + layersRecoHit[srcode[i]]++; + if (msgLvl(MSG::DEBUG)) { + if (m_idHelperSvc->isRpc(id)) + nrpc++; + else if (m_idHelperSvc->isTgc(id)) + ntgc++; + else if (m_idHelperSvc->isCsc(id)) + ncsc++; + } + nfit++; + } + } + allLayerRecoHits = layersRecoHit.size(); + double frac = allLayerRecoHits / (allLayerHits + 0.0001); + + if (nfit == 1) break; + + if (imax < 0 || imax > nphi) { + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Fitphi imax " << imax); + break; + } + + if (chi2 < 5 * (nfit + 1) || std::abs(phiPull[imax]) < 3.0) { + + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Final phi " << phi << " frac " << frac << " chi2 " << chi2); + break; + } + + phiSelect[imax] = 0; + + if (msgLvl(MSG::DEBUG)) { + ATH_MSG_DEBUG("Start hit dropping " << imax << " pullmax " << phiPull[imax] << " phi " << phi + << " chi2 " << chi2); + } } - } - } - const double pfitc = pfit; - imax = -1; - - if (iqua == 2) { - // low momentum fit with scaled error (factor 10) for dropped segment hits - std::vector<int> phiReSelect(nphi); - for(int i = 0; i < nphi ; ++i ) { - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("select " << phiSelect[i] << " quality " << quality[i]); - phiReSelect[i] = 0; - if(phiSelect[i] == 0 && quality[i] > 99) { - phiReSelect[i] = 1; - phiSelect[i] = phiSelectKeep[i]; - error[i] = 10.*error[i]; + if (msgLvl(MSG::DEBUG)) { + ATH_MSG_DEBUG("Fit results phi " << phi << " chi2 " << chi2 << " ndof " << nfit); + ATH_MSG_DEBUG("Reco RPC " << nrpc << " TGC " << ntgc << " CSC " << ncsc); } - } - fitPhiSL(pfitc, phiId, phiHitx, phiHity, phiHitz, error, phiSelect, nphi, phiPull, imax, chi2, r0, phi, errorM, false); - for(int i = 0; i < nphi ; ++i ) { - if(phiReSelect[i] == 1) { - error[i] = error[i]/10.; - // 10 sigma cut (error rescale = 10) - if (std::abs(phiPull[i]) < 1) { - phiSelect[i] = phiSelectKeep[i]; - } else { - phiSelect[i] = 0; - } - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Low momentum Quality == 2 add hit nr " << i << " quality " << quality[i] << " Pull " << phiPull[i] << " phiSelect " << phiSelect[i]); + + + int nacc = 0; + int nshowerdrop = 0; + for (int i = 0; i < nphi; ++i) { + double power = (niter - 10) / 20.; + if (power < 0.) power = 0.; + double pull = phiPull[i] * std::pow(phiMult[i], power); + if (niter > 10 && std::abs(pull) > 3.0 && phiSelect[i] > 0) { + phiSelect[i] = 0; + quality[i] = 0; + nshowerdrop++; + if (msgLvl(MSG::DEBUG)) + ATH_MSG_DEBUG("Drop shower hit i " << i << " with pull " << pull << " iterations " << niter + << " power " << power); + } + if (phiSelect[i] != 0) nacc++; + } + if (msgLvl(MSG::DEBUG)) + ATH_MSG_DEBUG("phi hits " << nphi << " selected for fit " << nfit << " iqua " << iqua << " iterations " + << niter << " accepted hits " << nacc << " nshower drop " << nshowerdrop); + } +} + +void +MuonPhiHitSelector::fitPhiSL(const double pmom, const std::vector<Identifier>& /*id*/, const std::vector<double>& hitx, + const std::vector<double>& hity, const std::vector<double>& hitz, + const std::vector<double>& error, std::vector<int>& select, const int n, + std::vector<double>& pull, int& imax, double& chi2, double& r0, double& phi, + std::vector<double>& errorM, bool fast) const +{ + + // Perform straight line fit to hits: good hits have select > 0 + // in the fit scattering centres are added for nfit-1 angles + // WITH beamspot constraint + // degrees of freedom = 2*nfit + + // Fit is based on matrix inversions formulae + + // Inputs pmom = estimate of momentum + // id = identifiers hits + // hitx hity hitz = position in space + // error = associated error (in x-y plane) + // select = > 0 for selected hits + // n = total number of hits + + + // Outputs pull = residual (hit -fit) /error + // imax = index for hit with maximum pull + // chi2 = total chi2 + // r0 = perigee parameter of fit (0,0) + // phi = azimuthal angle of fit at perigee + + double pest = pmom; + if (pest > 20000.) pest = 20000.; + + r0 = 0.; + phi = 0.; + chi2 = 0.; + imax = 0; + + // Calculate mean position + double xm = 0.; + double ym = 0.; + double dtot = 0.; + double em = 0.; + for (int i = 0; i < n; ++i) { + if (error[i] != 0 && select[i] > 0) { + double inver2 = 1. / (error[i] * error[i]); + xm += hitx[i] * inver2; + ym += hity[i] * inver2; + dtot += std::sqrt(hitx[i] * hitx[i] + hity[i] * hity[i] + hitz[i] * hitz[i]) * inver2; + em += inver2; } - } } - if (iqua == 1 && msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Quality loop "); - nsel = 0; - for(int i = 0; i < nphi ; ++i ) { - errorf[i] = error[i]; - if (iqua ==1) phiSelect[i] = phiSelectKeep[i]; - - if ( phiError[i] != 0 && quality[i] > quacut ) { - nsel++; - if (quality[i]== 10 && iqua == 1) quality[i] = 11; - } else { - phiSelect[i] = 0; - } - } - - if(msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Selected PHI hits in fit " << nsel << " iqua " << iqua); - if (nsel == 0) continue; - - int niter = -1; - // do hit dropping in maximal 10 iterations by putting quality to 0 - - for (int iter = 0; iter < 100 ; ++iter ) { - niter++; - double power = (iter - 10)/20.; - if (power< 0.) power = 0.; - chi2 =0.; - nfit = 0; - if (iter > 10) { -// Shower treatment inflate errors with multiplicity - for(int i = 0; i < nphi ; ++i ) { - errorf[i] = error[i]*std::pow(phiMult[i],power); + + if (em == 0) return; + + dtot = dtot / em; + + // Beamspot error 10 mm for cosmics 10000 + + double ebs = 0.1; + if (m_cosmics) ebs = 10000.; + + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("pmom " << pmom << " error beam " << ebs); + double ebs2 = ebs * ebs; + double invebs2 = 1. / ebs2; + double xmc = xm / (em + invebs2); + double ymc = ym / (em + invebs2); + xm = xm / em; + ym = ym / em; + + // Constraint on beam spot + + double len2 = xmc * xmc + ymc * ymc; + double xcc = len2 * xmc * invebs2; + double ycc = len2 * ymc * invebs2; + + for (int i = 0; i < n; ++i) { + if (error[i] != 0 && select[i] > 0) { + double inver2 = 1. / (error[i] * error[i]); + double xdiff = hitx[i] - xmc; + double ydiff = hity[i] - ymc; + double xdiff2 = xdiff * xdiff; + double ydiff2 = ydiff * ydiff; + len2 = xdiff2 + ydiff2; + double sign = 1.; + // Non Cosmics assume IP at 0 0 + if (xdiff * hitx[i] + ydiff * hity[i] < 0 && !m_cosmics) sign = -1; + // Cosmics assume down going + if (ydiff < 0 && m_cosmics) sign = -1; + xcc += len2 * sign * xdiff * inver2; + ycc += len2 * sign * ydiff * inver2; } - } - fitPhiSL(pfitc, phiId, phiHitx, phiHity, phiHitz, errorf, phiSelect, nphi, phiPull, imax, chi2, r0, phi, errorM, false ); - - ncsc = 0; - ntgc = 0; - nrpc = 0; - - // Count layers hit in Reconstruction - - std::map<int,int> layersRecoHit; - - for(int i = 0; i < nphi ; ++i ) { - Identifier id = phiId[i]; - if ( error[i] == 0 || quality[i] < quacut) phiSelect[i] = 0; - if ( error[i] != 0 && quality[i] > quacut) { - layersRecoHit[srcode[i]]++; - if (msgLvl(MSG::DEBUG)) { - if (m_idHelperSvc->isRpc(id)) nrpc++; - else if (m_idHelperSvc->isTgc(id)) ntgc++; - else if (m_idHelperSvc->isCsc(id)) ncsc++; - } - nfit++; - } - } - allLayerRecoHits = layersRecoHit.size(); - double frac = allLayerRecoHits/ ( allLayerHits + 0.0001); - - if (nfit == 1) break; - - if (imax < 0 || imax > nphi ) { - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Fitphi imax " << imax); - break; - } - - if (chi2 < 5*(nfit+1) || std::abs(phiPull[imax]) < 3.0 ) { - - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Final phi " << phi << " frac " << frac << " chi2 " << chi2); - break; - } - - phiSelect[imax] = 0; - - if (msgLvl(MSG::DEBUG)) { - ATH_MSG_DEBUG("Start hit dropping " << imax << " pullmax " << phiPull[imax] << " phi " << phi << " chi2 " << chi2); - } } - if (msgLvl(MSG::DEBUG)) { - ATH_MSG_DEBUG("Fit results phi " << phi << " chi2 " << chi2 << " ndof " << nfit); - ATH_MSG_DEBUG("Reco RPC " << nrpc << " TGC " << ntgc << " CSC " << ncsc); + if (em > 0) phi = std::atan2(ycc, xcc); + CxxUtils::sincos scphi(phi); + + r0 = xmc * scphi.sn - ymc * scphi.cs; + double x0 = r0 * scphi.sn; + double y0 = -r0 * scphi.cs; + + if (msgLvl(MSG::DEBUG)) + ATH_MSG_DEBUG("Constraint r0 " << r0 << " xpos " << xmc << " ypos " << ymc << " phi " << phi); + // assume 0,0 + std::vector<double> d(n); + std::vector<double> dist(n); + std::map<double, int> distanceSort; + double pullmax = 0.; + for (int i = 0; i < n; ++i) { + if (error[i] != 0 && select[i] > 0) { + double xdiff = hitx[i] - x0; + double ydiff = hity[i] - y0; + double xdiff2 = xdiff * xdiff; + double ydiff2 = ydiff * ydiff; + d[i] = std::sqrt(xdiff2 + ydiff2); + dist[i] = std::sqrt(xdiff2 + ydiff2 + hitz[i] * hitz[i]); + distanceSort[dist[i]] = i; + pull[i] = hitx[i] * scphi.sn - hity[i] * scphi.cs - r0; + if (std::abs(pull[i]) > std::abs(pullmax)) { + pullmax = pull[i]; + imax = i; + } + } } - - int nacc = 0; - int nshowerdrop = 0; - for(int i = 0; i < nphi ; ++i ) { - double power = (niter - 10)/20.; - if (power< 0.) power = 0.; - double pull = phiPull[i]*std::pow(phiMult[i],power); - if (niter > 10 && std::abs(pull) > 3.0 && phiSelect[i] > 0 ) { - phiSelect[i] = 0; - quality[i] = 0; - nshowerdrop++; - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Drop shower hit i " << i << " with pull " << pull << " iterations " << niter << " power " << power); - } - if( phiSelect[i] != 0) nacc++; + if (fast) return; + + std::map<double, int>::iterator it = distanceSort.begin(); + std::map<double, int>::iterator it_end = distanceSort.end(); + + int nfit = 0; + std::vector<double> xf(2 * n); + std::vector<double> lf(2 * n); + std::vector<double> yf(2 * n); + std::vector<double> ef(2 * n); + std::vector<int> indexf(n); + // + // measurements yf error ef at distance xf (0:nfit) + // scattering centra angle zero yf error ef at distance xf(nfit+1..2nfit-1) + // beamspot at yf(2 nfit) = 0 error ebs2 at distance xf(2 nfit) + + for (; it != it_end; ++it) { + int index = it->second; + xf[nfit] = d[index]; + lf[nfit] = dist[index]; + yf[nfit] = (hitx[index] - xmc) * scphi.sn - (hity[index] - ymc) * scphi.cs; + ef[nfit] = error[index]; + indexf[nfit] = index; + nfit++; } - if(msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("phi hits " << nphi << " selected for fit " << nfit << " iqua " << iqua << " iterations " << niter << " accepted hits " << nacc << " nshower drop " << nshowerdrop); - } -} -void MuonPhiHitSelector::fitPhiSL(const double pmom, const std::vector<Identifier> & /*id*/ , const std::vector<double> & hitx, const std::vector<double> & hity, const std::vector<double> & hitz, const std::vector<double> & error, std::vector<int> & select, const int n, std::vector<double> & pull, int & imax , double & chi2, double & r0, double & phi , std::vector<double> & errorM, bool fast) const { - - // Perform straight line fit to hits: good hits have select > 0 - // in the fit scattering centres are added for nfit-1 angles - // WITH beamspot constraint - // degrees of freedom = 2*nfit - - // Fit is based on matrix inversions formulae - - // Inputs pmom = estimate of momentum - // id = identifiers hits - // hitx hity hitz = position in space - // error = associated error (in x-y plane) - // select = > 0 for selected hits - // n = total number of hits - - - // Outputs pull = residual (hit -fit) /error - // imax = index for hit with maximum pull - // chi2 = total chi2 - // r0 = perigee parameter of fit (0,0) - // phi = azimuthal angle of fit at perigee - - double pest = pmom; - if (pest > 20000.) pest = 20000.; - - r0 = 0.; - phi = 0.; - chi2 = 0.; - imax = 0; - - // Calculate mean position - double xm = 0.; - double ym = 0.; - double dtot = 0.; - double em = 0.; - for(int i = 0; i < n ; ++i ) { - if ( error[i] != 0 && select[i] > 0 ) { - double inver2 = 1./(error[i]*error[i]); - xm += hitx[i]*inver2; - ym += hity[i]*inver2; - dtot += std::sqrt (hitx[i]*hitx[i] + hity[i]*hity[i] + hitz[i]*hitz[i] )*inver2 ; - em += inver2; + // NB start at 1 to add scattering centra + + double erang = 0.030 * 5000. / (pest + 1000.); + for (int i = 1; i < nfit; ++i) { + xf[nfit + i - 1] = xf[i - 1]; + yf[nfit + i - 1] = 0.; + double scale = 1.; + if (select[i] == 1) + scale = 1.; + else if (select[i] == 3) + scale = 0.5; + else if (select[i] == 2) + scale = 2.5; + ef[nfit + i - 1] = scale * erang; } - } - - if (em == 0) return; - - dtot = dtot/em; - - // Beamspot error 10 mm for cosmics 10000 - - double ebs = 0.1; - if (m_cosmics) ebs = 10000.; - - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("pmom " << pmom << " error beam " << ebs); - double ebs2 = ebs*ebs; - double invebs2 = 1./ebs2; - double xmc = xm / ( em + invebs2); - double ymc = ym / ( em + invebs2); - xm = xm/em; - ym = ym/em; - - // Constraint on beam spot - - double len2 = xmc*xmc+ymc*ymc; - double xcc = len2*xmc*invebs2; - double ycc = len2*ymc*invebs2; - - for(int i = 0; i < n ; ++i ) { - if ( error[i] != 0 && select[i] > 0) { - double inver2 = 1./(error[i]*error[i]); - double xdiff = hitx[i]-xmc; - double ydiff = hity[i]-ymc; - double xdiff2 = xdiff*xdiff; - double ydiff2 = ydiff*ydiff; - len2 =xdiff2+ydiff2; - double sign = 1.; -// Non Cosmics assume IP at 0 0 - if (xdiff*hitx[i]+ydiff*hity[i]<0&&!m_cosmics) sign =-1; -// Cosmics assume down going - if (ydiff<0&&m_cosmics) sign =-1; - xcc += len2*sign*xdiff*inver2; - ycc += len2*sign*ydiff*inver2; + // Beamspot + yf[2 * nfit - 1] = 0.; + xf[2 * nfit - 1] = 0.; + ef[2 * nfit - 1] = ebs; + + Amg::MatrixX v(nfit + 1, 1); + v.setIdentity(); + + if (msgLvl(MSG::DEBUG)) + ATH_MSG_DEBUG("fitPhiSL " + << " nfit " << nfit); + + for (int i = 0; i < nfit + 1; ++i) { + v(i, 0) = 0.; + for (int j = 0; j < nfit; ++j) { + double inver2 = 1. / (ef[j] * ef[j]); + if (i == 0) + v(i, 0) += yf[j] * inver2; + else if (i == 1) + v(i, 0) += yf[j] * xf[j] * inver2; + else if (i > 1 && j > i - 2) { + v(i, 0) += yf[j] * (lf[j] - lf[i - 2]) * inver2; + } + } } - } - - if (em>0) phi = std::atan2(ycc,xcc); - CxxUtils::sincos scphi(phi); - - r0 = xmc*scphi.sn - ymc*scphi.cs; - double x0 = r0*scphi.sn; - double y0 = -r0*scphi.cs; - - if(msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Constraint r0 " << r0 << " xpos " << xmc << " ypos " << ymc << " phi " << phi); - // assume 0,0 - std::vector<double> d(n); - std::vector<double> dist(n); - std::map < double, int > distanceSort; - double pullmax = 0.; - for(int i = 0; i < n ; ++i ) { - if ( error[i] != 0 && select[i] > 0) { - double xdiff = hitx[i]-x0; - double ydiff = hity[i]-y0; - double xdiff2 = xdiff*xdiff; - double ydiff2 = ydiff*ydiff; - d[i] = std::sqrt(xdiff2 + ydiff2); - dist[i] = std::sqrt(xdiff2 + ydiff2 + hitz[i]*hitz[i]); - distanceSort[dist[i]] = i; - pull[i] = hitx[i]*scphi.sn - hity[i]*scphi.cs - r0; - if (std::abs(pull[i])> std::abs(pullmax)) { - pullmax = pull[i]; - imax = i; - } + + // Track Model Matrix + + Amg::MatrixX model(nfit + 1, 2 * nfit); + model.setIdentity(); + // Measurements related to position and slope + + for (int i = 0; i < nfit + 1; ++i) { + for (int j = 0; j < nfit; ++j) { + model(i, j) = 0.; + if (i == 0) + model(i, j) = 1.; + else if (i == 1) + model(i, j) = xf[j]; + // scattering angle + else if (i > 1 && j > i - 2) + model(i, j) = lf[j] - lf[i - 2]; + } } - } - - if (fast) return; - - std::map< double, int >::iterator it = distanceSort.begin(); - std::map< double, int >::iterator it_end = distanceSort.end(); - - int nfit = 0; - std::vector<double> xf(2*n); - std::vector<double> lf(2*n); - std::vector<double> yf(2*n); - std::vector<double> ef(2*n); - std::vector<int> indexf(n); - // - // measurements yf error ef at distance xf (0:nfit) - // scattering centra angle zero yf error ef at distance xf(nfit+1..2nfit-1) - // beamspot at yf(2 nfit) = 0 error ebs2 at distance xf(2 nfit) - - for(; it != it_end; ++it){ - int index = it->second; - xf[nfit] = d[index]; - lf[nfit] = dist[index]; - yf[nfit] = (hitx[index]-xmc)*scphi.sn - (hity[index]-ymc)*scphi.cs; - ef[nfit] = error[index]; - indexf[nfit] = index; - nfit++; - } - - // NB start at 1 to add scattering centra - - double erang = 0.030*5000./(pest+1000.); - for(int i =1; i < nfit ; ++i ) { - xf[nfit+i-1] = xf[i-1]; - yf[nfit+i-1] = 0.; - double scale = 1.; - if (select[i] == 1) scale = 1.; - else if (select[i] == 3) scale = 0.5; - else if (select[i] == 2) scale = 2.5; - ef[nfit+i-1] = scale*erang; - } - // Beamspot - yf[2*nfit-1] = 0.; - xf[2*nfit-1] = 0.; - ef[2*nfit-1] = ebs; - - Amg::MatrixX v(nfit+1,1); - v.setIdentity(); - - if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("fitPhiSL " << " nfit " << nfit); - - for(int i = 0; i < nfit+1 ; ++i ) { - v(i,0) = 0.; - for(int j = 0; j < nfit ; ++j ) { - double inver2 = 1./(ef[j]*ef[j]); - if (i == 0) v(i,0) += yf[j]*inver2; - else if (i == 1) v(i,0) += yf[j]*xf[j]*inver2; - else if (i > 1 && j > i-2 ) { - v(i,0) += yf[j]*(lf[j]-lf[i-2])*inver2; - } - } - } - - // Track Model Matrix - - Amg::MatrixX model(nfit+1,2*nfit); - model.setIdentity(); - // Measurements related to position and slope - - for(int i = 0; i <nfit+1 ; ++i ) { - for(int j = 0; j <nfit ; ++j ) { - model(i,j) = 0.; - if ( i == 0 ) model(i,j) = 1.; - else if ( i == 1 ) model(i,j) = xf[j]; - // scattering angle - else if ( i > 1 && j > i - 2 ) model(i,j) = lf[j]-lf[i-2]; + + // Constraints on scattering angles and beamspot + + for (int i = 0; i < nfit + 1; ++i) { + for (int j = nfit; j < 2 * nfit; ++j) { + model(i, j) = 0.; + // scattering angle + if (i == j - nfit + 2) model(i, j) = 1.; + // Beam spot + if (i == 0 && j == 2 * nfit - 1) model(i, j) = 1.; + } } - } - // Constraints on scattering angles and beamspot + // Covariance Inverse of Track parameters - for(int i = 0; i <nfit+1 ; ++i ) { - for(int j = nfit; j < 2*nfit ; ++j ) { - model(i,j) = 0.; - // scattering angle - if ( i == j- nfit + 2) model(i,j) = 1.; - // Beam spot - if ( i == 0 && j == 2*nfit-1) model(i,j) = 1.; + Amg::MatrixX covT(nfit + 1, nfit + 1); + for (int i = 0; i < nfit + 1; ++i) { + for (int j = 0; j < nfit + 1; ++j) { + covT(i, j) = 0.; + for (int k = 0; k < 2 * nfit; ++k) { + double er2 = ef[k] * ef[k]; + covT(i, j) += model(i, k) * model(j, k) / er2; + } + } } - } - - // Covariance Inverse of Track parameters - - Amg::MatrixX covT(nfit+1,nfit+1); - for(int i = 0; i <nfit+1 ; ++i ) { - for(int j = 0; j <nfit+1 ; ++j ) { - covT(i,j) = 0.; - for(int k = 0; k <2*nfit ; ++k ) { - double er2 = ef[k]*ef[k]; - covT(i,j) += model(i,k)*model(j,k)/er2; - } + + // Invert covariance matrix and replace it (should be CovT) + Amg::MatrixX covTI = covT.inverse(); + + Amg::MatrixX t(nfit + 1, 1); + // Solution for Track parameters + t = covTI * v; + + if (msgLvl(MSG::DEBUG) && std::abs(t(1, 0)) > 0.2) { + ATH_MSG_DEBUG("Don't trust fit result " << t(1, 0) << " Keep Old result"); } - } - -// Invert covariance matrix and replace it (should be CovT) - Amg::MatrixX covTI = covT.inverse(); - - Amg::MatrixX t(nfit+1,1); - // Solution for Track parameters - t = covTI*v; - - if (msgLvl(MSG::DEBUG) && std::abs(t(1,0))> 0.2 ) { - ATH_MSG_DEBUG("Don't trust fit result " << t(1,0) << " Keep Old result"); - } - if (std::abs(t(1,0))> 0.2) return; - - // calculate residuals and chi2 - std::vector <double> resi(2*nfit); - std::vector <double> pulli(2*nfit); - std::vector <double> errf(2*nfit); - std::vector <double> pullf(2*nfit); - std::vector <double> resiOut(2*nfit); - std::vector <double> pullOut(2*nfit); - pullmax = 0.; - int jmax = 0; - - errorM[0] = covTI(0,0); - errorM[1] = covTI(0,1); - errorM[2] = covTI(1,1); - errorM[3] = 0.; - if (nfit>2) { - double invlt = 1./(lf[nfit-1]-lf[1]); - for(int i = 1; i < nfit-1 ; ++i ) { - double w = (lf[nfit-1]-lf[i])*invlt; - errorM[3] += covTI(i+1,i+1)*w*w; - } - } - - if(msgLvl(MSG::DEBUG)) { - if (nfit>=3) { - ATH_MSG_DEBUG("Error angle " << covTI(3,3)); - } // covTI has dim nfit+1 - ATH_MSG_DEBUG("errorM[3] " << errorM[3]); - } - - for(int i = 0; i < 2*nfit ; ++i ) { - - // Calculate prediction at each measurement i - // propagate error of track parameters to measurement i - double error2 = 0.; - double ypred = 0.; - for(int j = 0; j < nfit+1 ; ++j ) { - if(msgLvl(MSG::DEBUG) && i == 0) ATH_MSG_DEBUG("Parameter j " << j << " t(j,0) " << t(j,0)); - if(msgLvl(MSG::DEBUG) && model(j,i) != 0) ATH_MSG_DEBUG("i " << i << " model ij " << model(j,i)); - ypred += model(j,i)*t(j,0); - for(int k = 0; k < nfit+1 ; ++k ) { - error2 += model(j,i)*covTI(j,k)*model(k,i); - } + if (std::abs(t(1, 0)) > 0.2) return; + + // calculate residuals and chi2 + std::vector<double> resi(2 * nfit); + std::vector<double> pulli(2 * nfit); + std::vector<double> errf(2 * nfit); + std::vector<double> pullf(2 * nfit); + std::vector<double> resiOut(2 * nfit); + std::vector<double> pullOut(2 * nfit); + pullmax = 0.; + int jmax = 0; + + errorM[0] = covTI(0, 0); + errorM[1] = covTI(0, 1); + errorM[2] = covTI(1, 1); + errorM[3] = 0.; + if (nfit > 2) { + double invlt = 1. / (lf[nfit - 1] - lf[1]); + for (int i = 1; i < nfit - 1; ++i) { + double w = (lf[nfit - 1] - lf[i]) * invlt; + errorM[3] += covTI(i + 1, i + 1) * w * w; + } } - double ef_i2 = ef[i]*ef[i]; - double inv_ef_i2 = 1./ef_i2; - - resi[i] = ypred - yf[i]; - pulli[i] = resi[i]/ef[i]; - - // errf propagated error and pullf - errf[i] = std::sqrt(error2); - pullf[i] = resi[i]/errf[i]; - - // calculate residual without hit and error without hit - // Think of Kalmanm method to exclude hit and error - double err2invOut = 1./error2 - inv_ef_i2; - if (err2invOut > 0) { - resiOut[i] = (ypred/error2 - yf[i]*inv_ef_i2)/err2invOut - yf[i]; - pullOut[i] = resiOut[i]/std::sqrt(1./err2invOut+ef_i2); + + if (msgLvl(MSG::DEBUG)) { + if (nfit >= 3) { + ATH_MSG_DEBUG("Error angle " << covTI(3, 3)); + } // covTI has dim nfit+1 + ATH_MSG_DEBUG("errorM[3] " << errorM[3]); } - if (std::abs(pullOut[i]) > std::abs(pullmax) && i < nfit ) { - imax = indexf[i]; - jmax = i; - pullmax = pullOut[i]; - } - chi2 += resi[i]*resi[i]*inv_ef_i2; + for (int i = 0; i < 2 * nfit; ++i) { + + // Calculate prediction at each measurement i + // propagate error of track parameters to measurement i + double error2 = 0.; + double ypred = 0.; + for (int j = 0; j < nfit + 1; ++j) { + if (msgLvl(MSG::DEBUG) && i == 0) ATH_MSG_DEBUG("Parameter j " << j << " t(j,0) " << t(j, 0)); + if (msgLvl(MSG::DEBUG) && model(j, i) != 0) ATH_MSG_DEBUG("i " << i << " model ij " << model(j, i)); + ypred += model(j, i) * t(j, 0); + for (int k = 0; k < nfit + 1; ++k) { + error2 += model(j, i) * covTI(j, k) * model(k, i); + } + } + double ef_i2 = ef[i] * ef[i]; + double inv_ef_i2 = 1. / ef_i2; + + resi[i] = ypred - yf[i]; + pulli[i] = resi[i] / ef[i]; + + // errf propagated error and pullf + errf[i] = std::sqrt(error2); + pullf[i] = resi[i] / errf[i]; + + // calculate residual without hit and error without hit + // Think of Kalmanm method to exclude hit and error + double err2invOut = 1. / error2 - inv_ef_i2; + if (err2invOut > 0) { + resiOut[i] = (ypred / error2 - yf[i] * inv_ef_i2) / err2invOut - yf[i]; + pullOut[i] = resiOut[i] / std::sqrt(1. / err2invOut + ef_i2); + } + + if (std::abs(pullOut[i]) > std::abs(pullmax) && i < nfit) { + imax = indexf[i]; + jmax = i; + pullmax = pullOut[i]; + } + chi2 += resi[i] * resi[i] * inv_ef_i2; - if (i < nfit ) { - pull[indexf[i]] = pullOut[i]; + if (i < nfit) { + pull[indexf[i]] = pullOut[i]; + } + if (msgLvl(MSG::DEBUG) && i < nfit) + ATH_MSG_DEBUG("i " << i << " index " << indexf[i] << " det " << select[indexf[i]] << " ypred " << ypred + << " mst " << yf[i] << " residual " << resi[i] << " error " << ef[i] << " dist " + << dist[i] << " hitz " << hitz[i] << " Pull " << pulli[i] << " Pullf " << pullf[i] + << " resi out " << resiOut[i] << " pull out " << pullOut[i]); + if (msgLvl(MSG::DEBUG) && i > nfit) + ATH_MSG_DEBUG("i " << i << " ypred " << ypred << " mst " << yf[i] << " residual " << resi[i] << " error " + << ef[i]); } - if (msgLvl(MSG::DEBUG)&& i < nfit) ATH_MSG_DEBUG("i " << i << " index " << indexf[i] << " det " << select[indexf[i]] << " ypred " << ypred << " mst " << yf[i] << " residual " << resi[i] << " error " << ef[i] << " dist " << dist[i] << " hitz " << hitz[i] << " Pull " << pulli[i] << " Pullf " << pullf[i] << " resi out " << resiOut[i] << " pull out " << pullOut[i]); - if (msgLvl(MSG::DEBUG)&& i > nfit) ATH_MSG_DEBUG("i " << i << " ypred " << ypred << " mst " << yf[i] << " residual " << resi[i] << " error " << ef[i]); - } - r0 = r0 + t(0,0); - phi = phi + t(1,0); - - if (msgLvl(MSG::DEBUG) ) ATH_MSG_DEBUG("delta phi " << t(1,0)); - if (msgLvl(MSG::DEBUG) && std::abs(t(1,0))> 0.1 ) ATH_MSG_DEBUG("ALARM delta phi " << t(1,0)); - - if(msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("Track parameters r0 " << r0 << " phi " << phi << " chi2 " << chi2 << " jmax " << jmax << " imax " << imax << " pullmax " << pullmax); - + r0 = r0 + t(0, 0); + phi = phi + t(1, 0); + + if (msgLvl(MSG::DEBUG)) ATH_MSG_DEBUG("delta phi " << t(1, 0)); + if (msgLvl(MSG::DEBUG) && std::abs(t(1, 0)) > 0.1) ATH_MSG_DEBUG("ALARM delta phi " << t(1, 0)); + + if (msgLvl(MSG::DEBUG)) + ATH_MSG_DEBUG("Track parameters r0 " << r0 << " phi " << phi << " chi2 " << chi2 << " jmax " << jmax << " imax " + << imax << " pullmax " << pullmax); } - diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentInOverlapResolvingTool.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentInOverlapResolvingTool.cxx index a891a82cdb6fc86233f5af22a5954e22f45e2237..0ab94d7900dd607a90d1555cc144cd6b45399182 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentInOverlapResolvingTool.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentInOverlapResolvingTool.cxx @@ -3,35 +3,30 @@ */ #include "MuonSegmentInOverlapResolvingTool.h" - -#include "GaudiKernel/MsgStream.h" -#include "MuonSegment/MuonSegment.h" +#include "GaudiKernel/MsgStream.h" +#include "GeoPrimitives/GeoPrimitivesHelpers.h" +#include "GeoPrimitives/GeoPrimitivesToStringConverter.h" #include "MuonRIO_OnTrack/MdtDriftCircleOnTrack.h" -#include "TrkParameters/TrackParameters.h" -#include "TrkEventPrimitives/LocalDirection.h" -#include "TrkDetDescrUtils/Intersection.h" - #include "MuonReadoutGeometry/MdtReadoutElement.h" - +#include "MuonSegment/MuonSegment.h" +#include "TrkDetDescrUtils/Intersection.h" +#include "TrkEventPrimitives/LocalDirection.h" #include "TrkEventPrimitives/ResidualPull.h" -#include "GeoPrimitives/GeoPrimitivesHelpers.h" -#include "GeoPrimitives/GeoPrimitivesToStringConverter.h" +#include "TrkParameters/TrackParameters.h" namespace Muon { - MuonSegmentInOverlapResolvingTool::MuonSegmentInOverlapResolvingTool(const std::string& ty,const std::string& na,const IInterface* pa) - : AthAlgTool(ty,na,pa), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"), - m_propagator("Trk::RungeKuttaPropagator/AtlasRungeKuttaPropagator"), - m_magFieldProperties(Trk::NoField), - m_pullCalculator("Trk::ResidualPullCalculator/ResidualPullCalculator") - { +MuonSegmentInOverlapResolvingTool::MuonSegmentInOverlapResolvingTool(const std::string& ty, const std::string& na, + const IInterface* pa) + : AthAlgTool(ty, na, pa), m_magFieldProperties(Trk::NoField) +{ declareInterface<IMuonSegmentInOverlapResolvingTool>(this); - } +} - StatusCode MuonSegmentInOverlapResolvingTool::initialize() - { +StatusCode +MuonSegmentInOverlapResolvingTool::initialize() +{ ATH_CHECK(AthAlgTool::initialize()); ATH_CHECK(m_edmHelperSvc.retrieve()); @@ -41,67 +36,71 @@ namespace Muon { ATH_CHECK(m_pullCalculator.retrieve()); return StatusCode::SUCCESS; - } +} + +Amg::Vector3D +MuonSegmentInOverlapResolvingTool::updateSegmentDirection(const MuonSegment& seg, double phi) const +{ - Amg::Vector3D MuonSegmentInOverlapResolvingTool::updateSegmentDirection( const MuonSegment& seg, double phi ) const { - Amg::Transform3D gToStation = seg.associatedSurface().transform().inverse(); - Amg::Vector3D phiDir(1.,0.,0.); - Amg::setThetaPhi(phiDir,seg.globalDirection().theta(),phi); - Amg::Vector3D lphiDir = gToStation.linear()*phiDir; - Amg::Vector3D lsegDir = gToStation.linear()*seg.globalDirection(); - double road_dz = lphiDir.z(); - double seg_dy = lsegDir.y(); - double seg_dz = lsegDir.z(); - if( road_dz*seg_dz < 0 ) { - seg_dy *= -1.; - seg_dz *= -1.; + Amg::Vector3D phiDir(1., 0., 0.); + Amg::setThetaPhi(phiDir, seg.globalDirection().theta(), phi); + Amg::Vector3D lphiDir = gToStation.linear() * phiDir; + Amg::Vector3D lsegDir = gToStation.linear() * seg.globalDirection(); + double road_dz = lphiDir.z(); + double seg_dy = lsegDir.y(); + double seg_dz = lsegDir.z(); + if (road_dz * seg_dz < 0) { + seg_dy *= -1.; + seg_dz *= -1.; } - if( fabs(seg_dz) < 1e-6 ) { - seg_dz = 1e-6; - ATH_MSG_DEBUG(" Unexpected local direction of segment " << lsegDir); + if (fabs(seg_dz) < 1e-6) { + seg_dz = 1e-6; + ATH_MSG_DEBUG(" Unexpected local direction of segment " << lsegDir); } - double scale = road_dz/seg_dz; + double scale = road_dz / seg_dz; seg_dy *= scale; - Amg::Vector3D locDir(lphiDir.x(),seg_dy,road_dz); - Amg::Vector3D gDir = seg.associatedSurface().transform().linear()*locDir; + Amg::Vector3D locDir(lphiDir.x(), seg_dy, road_dz); + Amg::Vector3D gDir = seg.associatedSurface().transform().linear() * locDir; return gDir; - } +} - Amg::Vector3D MuonSegmentInOverlapResolvingTool::estimateSegmentDirection( const MuonSegment& seg1, const MuonSegment& seg2, - double& phi, double& stereoangle ) const { +Amg::Vector3D +MuonSegmentInOverlapResolvingTool::estimateSegmentDirection(const MuonSegment& seg1, const MuonSegment& seg2, + double& phi, double& stereoangle) const +{ // // From two segments the direction and position of the segments are determined // assuming a straight line // - // if a stereoangle is present one can determine: phi and x local for both segments + // if a stereoangle is present one can determine: phi and x local for both segments // -// bool check = false; + // bool check = false; // Confusing use of objects: - // This is needed because otherwise the Transform3D DOES NOT know + // This is needed because otherwise the Transform3D DOES NOT know // whether it transforms a position or a direction // const Amg::Transform3D& gToGlobal1 = seg1.associatedSurface().transform(); const Amg::Transform3D& gToGlobal2 = seg2.associatedSurface().transform(); - Amg::Transform3D gToLocal1 = seg1.associatedSurface().transform().inverse(); - Amg::Transform3D gToLocal2 = seg2.associatedSurface().transform().inverse(); + Amg::Transform3D gToLocal1 = seg1.associatedSurface().transform().inverse(); + Amg::Transform3D gToLocal2 = seg2.associatedSurface().transform().inverse(); // const Amg::Vector3D& gDir1 = seg1.globalDirection(); const Amg::Vector3D& gDir2 = seg2.globalDirection(); - // Confusing but Amg::Vector3D can hold a 3D local direction - Amg::Vector3D lDir1 = gToLocal1.linear()*gDir1; - //Amg::Vector3D lDir2 = gToLocal2.linear()*gDir2; + // Confusing but Amg::Vector3D can hold a 3D local direction + Amg::Vector3D lDir1 = gToLocal1.linear() * gDir1; + // Amg::Vector3D lDir2 = gToLocal2.linear()*gDir2; // segment 2 local direction in frame of segment 1 - Amg::Vector3D lDir12 = gToLocal1.linear()*gDir2; - //Amg::Vector3D lDir21 = gToLocal2.linear()*gDir1; + Amg::Vector3D lDir12 = gToLocal1.linear() * gDir2; + // Amg::Vector3D lDir21 = gToLocal2.linear()*gDir1; - Amg::Vector3D segLocDiro(1.,0.,0.); + Amg::Vector3D segLocDiro(1., 0., 0.); // orthogonal vector to segment 2 in local frame of segment 1 - Amg::Vector3D lDiro12 = gToLocal1.linear()*(gToGlobal2.linear()*segLocDiro); + Amg::Vector3D lDiro12 = gToLocal1.linear() * (gToGlobal2.linear() * segLocDiro); // orthogonal vector to segment 1in local frame of segment 2 - Amg::Vector3D lDiro21 = gToLocal2.linear()*(gToGlobal1.linear()*segLocDiro); + Amg::Vector3D lDiro21 = gToLocal2.linear() * (gToGlobal1.linear() * segLocDiro); stereoangle = acos(lDiro12.x()); @@ -110,444 +109,465 @@ namespace Muon { // dy1 = lDir1.y() = a * lDir12.y() + b * lDiro12.y() // dz1 = lDir1.z() = a * lDir12.z() + b * lDiro12.z() - double b = lDir1.y()*lDir12.z() - lDir1.z()*lDir12.y(); - double a = lDir1.y()*lDiro12.z() - lDir1.z()*lDiro12.y(); + double b = lDir1.y() * lDir12.z() - lDir1.z() * lDir12.y(); + double a = lDir1.y() * lDiro12.z() - lDir1.z() * lDiro12.y(); double dxn = lDir12.x(); double dyn = lDir12.y(); double dzn = lDir12.z(); - if (fabs(a)> 1e-2) { - dxn = lDir12.x() - b*lDiro12.x()/a; - dyn = lDir12.y() - b*lDiro12.y()/a; - dzn = lDir12.z() - b*lDiro12.z()/a; + if (fabs(a) > 1e-2) { + dxn = lDir12.x() - b * lDiro12.x() / a; + dyn = lDir12.y() - b * lDiro12.y() / a; + dzn = lDir12.z() - b * lDiro12.z() / a; } - double norm = std::sqrt(dxn*dxn+dyn*dyn+dzn*dzn); - if( norm < 1e-6 ) { - ATH_MSG_DEBUG(" Unexpected normalisation " << norm); - norm = 1e-6; + double norm = std::sqrt(dxn * dxn + dyn * dyn + dzn * dzn); + if (norm < 1e-6) { + ATH_MSG_DEBUG(" Unexpected normalisation " << norm); + norm = 1e-6; } - if (dxn*lDir1.x() + dyn*lDir1.y() + dzn*lDir1.z() < 0 ) norm = - norm; - dxn = dxn/norm; - dyn = dyn/norm; - dzn = dzn/norm; + if (dxn * lDir1.x() + dyn * lDir1.y() + dzn * lDir1.z() < 0) norm = -norm; + dxn = dxn / norm; + dyn = dyn / norm; + dzn = dzn / norm; - // The final result for the direction of the two segments + // The final result for the direction of the two segments // New Local direction of segment 1 - Amg::Vector3D lDirn1 (dxn,dyn,dzn); + Amg::Vector3D lDirn1(dxn, dyn, dzn); // Global direction of both segments - Amg::Vector3D gDirn = gToGlobal1.linear()*lDirn1; + Amg::Vector3D gDirn = gToGlobal1.linear() * lDirn1; // New Local direction of segment 2 - Amg::Vector3D lDirn2 = gToLocal2.linear()*gDirn; - phi = gDirn.phi(); - double theta = gDirn.theta(); + Amg::Vector3D lDirn2 = gToLocal2.linear() * gDirn; + phi = gDirn.phi(); + double theta = gDirn.theta(); const Amg::Vector3D& gPos1 = seg1.globalPosition(); - // Confusing but Amg::Vector3D can hold a 3D local position - Amg::Vector3D lPos1 = gToLocal1*gPos1; - Amg::Vector3D lPos21 = gToLocal2*gPos1; - Amg::Vector3D gPos2 = seg2.globalPosition(); - Amg::Vector3D lPos12 = gToLocal1*gPos2; - Amg::Vector3D lPos2 = gToLocal2*gPos2; + // Confusing but Amg::Vector3D can hold a 3D local position + Amg::Vector3D lPos1 = gToLocal1 * gPos1; + Amg::Vector3D lPos21 = gToLocal2 * gPos1; + Amg::Vector3D gPos2 = seg2.globalPosition(); + Amg::Vector3D lPos12 = gToLocal1 * gPos2; + Amg::Vector3D lPos2 = gToLocal2 * gPos2; // In local frame of segment 2 shift segment 1 to obtain zero residual - double res21 = (lPos2.y() - lPos21.y())*lDirn2.z() - (lPos2.z() - lPos21.z())*lDirn2.y(); + double res21 = (lPos2.y() - lPos21.y()) * lDirn2.z() - (lPos2.z() - lPos21.z()) * lDirn2.y(); double localx1 = 0.; - double step = (lDiro21.y()*lDirn2.z() - lDiro21.z()*lDirn2.y()); - if (fabs(step)>1e-5) { - localx1 = res21/step; + double step = (lDiro21.y() * lDirn2.z() - lDiro21.z() * lDirn2.y()); + if (fabs(step) > 1e-5) { + localx1 = res21 / step; } ATH_MSG_DEBUG(" localx1 " << localx1 << " res21 " << res21 << " step " << step); // Result: New local and global position of segment 1 - Amg::Vector3D lPosn1(lPos1.x()+localx1,lPos1.y(),lPos1.z()); - Amg::Vector3D gPosn1 = gToGlobal1*lPosn1; + Amg::Vector3D lPosn1(lPos1.x() + localx1, lPos1.y(), lPos1.z()); + Amg::Vector3D gPosn1 = gToGlobal1 * lPosn1; // In local frame of segment 1 shift segment 2 to obtain zero residual - double res12 = (lPos1.y() - lPos12.y())*lDirn1.z() - (lPos1.z() - lPos12.z())*lDirn1.y(); - step = (lDiro12.y()*lDirn1.z() - lDiro12.z()*lDirn1.y()); + double res12 = (lPos1.y() - lPos12.y()) * lDirn1.z() - (lPos1.z() - lPos12.z()) * lDirn1.y(); + step = (lDiro12.y() * lDirn1.z() - lDiro12.z() * lDirn1.y()); double localx2 = 0.; - if (fabs(step)>1e-5) { - localx2 = res12/step; + if (fabs(step) > 1e-5) { + localx2 = res12 / step; } ATH_MSG_DEBUG(" localx2 " << localx2 << " res12 " << res12 << " step " << step); // Result: New local and global position of segment 2 - Amg::Vector3D lPosn2(lPos2.x()+localx2,lPos2.y(),lPos2.z()); - Amg::Vector3D gPosn2 = gToGlobal2*lPosn2; - ATH_MSG_DEBUG(" segment 1 local position " << lPos1 << " new " << lPosn1 << std::endl - << " segment 1 global position " << gPos1 << " new " << gPosn1 << std::endl - << " segment 2 local position " << lPos2 << " new " << lPosn2 << std::endl - << " segment 2 global position " << gPos2 << " new " << gPosn2 ); + Amg::Vector3D lPosn2(lPos2.x() + localx2, lPos2.y(), lPos2.z()); + Amg::Vector3D gPosn2 = gToGlobal2 * lPosn2; + ATH_MSG_DEBUG(" segment 1 local position " + << lPos1 << " new " << lPosn1 << std::endl + << " segment 1 global position " << gPos1 << " new " << gPosn1 << std::endl + << " segment 2 local position " << lPos2 << " new " << lPosn2 << std::endl + << " segment 2 global position " << gPos2 << " new " << gPosn2); // This gives the direction from the position of the segments Amg::Vector3D gDirPos = gPosn2 - gPosn1; - if (gDir1.x()* gDirPos.x() + gDir1.y()* gDirPos.y() + gDir1.z()* gDirPos.z() < 0 ) { - gDirPos = - gPosn2 + gPosn1; - } - double dtheta = theta - gDirPos.theta(); - double dphi = phi - gDirPos.phi(); - ATH_MSG_DEBUG(" theta " << theta << " gDirPos theta " << gDirPos.theta() << " dtheta " - << dtheta << " phi " << phi << " gDirPos phi " << gDirPos.phi() << " dphi " << dphi); + if (gDir1.x() * gDirPos.x() + gDir1.y() * gDirPos.y() + gDir1.z() * gDirPos.z() < 0) { + gDirPos = -gPosn2 + gPosn1; + } + double dtheta = theta - gDirPos.theta(); + double dphi = phi - gDirPos.phi(); + ATH_MSG_DEBUG(" theta " << theta << " gDirPos theta " << gDirPos.theta() << " dtheta " << dtheta << " phi " << phi + << " gDirPos phi " << gDirPos.phi() << " dphi " << dphi); return gDirn; - } +} + - - MuonSegmentInOverlapResolvingTool::SegmentPhiMatchResult MuonSegmentInOverlapResolvingTool::bestPhiMatchAnalytic( const MuonSegment& seg1, const MuonSegment& seg2 ) const { +MuonSegmentInOverlapResolvingTool::SegmentPhiMatchResult +MuonSegmentInOverlapResolvingTool::bestPhiMatchAnalytic(const MuonSegment& seg1, const MuonSegment& seg2) const +{ // // From two segments the direction and position of the segments are determined // assuming a straight line // - // if a stereoangle is present one can determine: phi and x local for both segments + // if a stereoangle is present one can determine: phi and x local for both segments // - //bool check = false; + // bool check = false; // Confusing use of objects: - // Trk::GlobalDirection can and will hold a 3D LOCAL direction - // Trk::GlobalPositionn can and will hold a 3D LOCAL position - // This is needed because otherwise the Amg::Transform3D DOES NOT know + // Trk::GlobalDirection can and will hold a 3D LOCAL direction + // Trk::GlobalPositionn can and will hold a 3D LOCAL position + // This is needed because otherwise the Amg::Transform3D DOES NOT know // whether it transforms a position or a direction // const Amg::Transform3D& gToGlobal1 = seg1.associatedSurface().transform(); const Amg::Transform3D& gToGlobal2 = seg2.associatedSurface().transform(); - Amg::Transform3D gToLocal1 = seg1.associatedSurface().transform().inverse(); - //Amg::Transform3D gToLocal2 = seg2.associatedSurface().transform().inverse(); + Amg::Transform3D gToLocal1 = seg1.associatedSurface().transform().inverse(); + // Amg::Transform3D gToLocal2 = seg2.associatedSurface().transform().inverse(); // const Amg::Vector3D& gDir1 = seg1.globalDirection(); const Amg::Vector3D& gDir2 = seg2.globalDirection(); - // Confusing but Amg::Vector3D can hold a 3D local direction - Amg::Vector3D lDir1 = gToLocal1.linear()*gDir1; - //Amg::Vector3D lDir2 = gToLocal2.linear()*gDir2; + // Confusing but Amg::Vector3D can hold a 3D local direction + Amg::Vector3D lDir1 = gToLocal1.linear() * gDir1; + // Amg::Vector3D lDir2 = gToLocal2.linear()*gDir2; // segment 2 local direction in frame of segment 1 - Amg::Vector3D lDir12 = gToLocal1.linear()*gDir2; - //Amg::Vector3D lDir21 = gToLocal2.linear()*gDir1; + Amg::Vector3D lDir12 = gToLocal1.linear() * gDir2; + // Amg::Vector3D lDir21 = gToLocal2.linear()*gDir1; - Amg::Vector3D segLocDiro(1.,0.,0.); + Amg::Vector3D segLocDiro(1., 0., 0.); // orthogonal vector to segment 2 in local frame of segment 1 - Amg::Vector3D lDiro12 = gToLocal1.linear()*(gToGlobal2.linear()*segLocDiro); + Amg::Vector3D lDiro12 = gToLocal1.linear() * (gToGlobal2.linear() * segLocDiro); // orthogonal vector to segment 1in local frame of segment 2 - //Amg::Vector3D lDiro21 = gToLocal2.linear()*(gToGlobal1.linear()*segLocDiro); + // Amg::Vector3D lDiro21 = gToLocal2.linear()*(gToGlobal1.linear()*segLocDiro); - //stereoangle = acos(lDiro12.x()); + // stereoangle = acos(lDiro12.x()); // We have the following equations for segment 2 in local frame of segment 1 // dx1 = free // dy1 = lDir1.y() = a * lDir12.y() + b * lDiro12.y() // dz1 = lDir1.z() = a * lDir12.z() + b * lDiro12.z() - double b = lDir1.y()*lDir12.z() - lDir1.z()*lDir12.y(); - double a = lDir1.y()*lDiro12.z() - lDir1.z()*lDiro12.y(); + double b = lDir1.y() * lDir12.z() - lDir1.z() * lDir12.y(); + double a = lDir1.y() * lDiro12.z() - lDir1.z() * lDiro12.y(); double dxn = lDir12.x(); double dyn = lDir12.y(); double dzn = lDir12.z(); - if (fabs(a)> 1e-2) { - dxn = lDir12.x() - b*lDiro12.x()/a; - dyn = lDir12.y() - b*lDiro12.y()/a; - dzn = lDir12.z() - b*lDiro12.z()/a; + if (fabs(a) > 1e-2) { + dxn = lDir12.x() - b * lDiro12.x() / a; + dyn = lDir12.y() - b * lDiro12.y() / a; + dzn = lDir12.z() - b * lDiro12.z() / a; } - double norm = std::sqrt(dxn*dxn+dyn*dyn+dzn*dzn); - if( norm < 1e-6 ) { - ATH_MSG_DEBUG(" Unexpected normalisation " << norm); - norm = 1e-6; + double norm = std::sqrt(dxn * dxn + dyn * dyn + dzn * dzn); + if (norm < 1e-6) { + ATH_MSG_DEBUG(" Unexpected normalisation " << norm); + norm = 1e-6; } - if (dxn*lDir1.x() + dyn*lDir1.y() + dzn*lDir1.z() < 0 ) norm = - norm; - dxn = dxn/norm; - dyn = dyn/norm; - dzn = dzn/norm; + if (dxn * lDir1.x() + dyn * lDir1.y() + dzn * lDir1.z() < 0) norm = -norm; + dxn = dxn / norm; + dyn = dyn / norm; + dzn = dzn / norm; - // The final result for the direction of the two segments + // The final result for the direction of the two segments // New Local direction of segment 1 - Amg::Vector3D lDirn1 (dxn,dyn,dzn); + Amg::Vector3D lDirn1(dxn, dyn, dzn); // Global direction of both segments - Amg::Vector3D segDir1Min = gToGlobal1.linear()*lDirn1; - Amg::Vector3D segDir2Min = segDir1Min;//updateSegmentDirection(seg2,segDir1Min.phi()); + Amg::Vector3D segDir1Min = gToGlobal1.linear() * lDirn1; + Amg::Vector3D segDir2Min = segDir1Min; // updateSegmentDirection(seg2,segDir1Min.phi()); Trk::LocalDirection segLocDir1; - seg2.associatedSurface().globalToLocalDirection(segDir1Min,segLocDir1); + seg2.associatedSurface().globalToLocalDirection(segDir1Min, segLocDir1); Trk::LocalDirection segLocDir2; - seg2.associatedSurface().globalToLocalDirection(segDir2Min,segLocDir2); + seg2.associatedSurface().globalToLocalDirection(segDir2Min, segLocDir2); double dyz = fabs(segLocDir1.angleYZ() - segLocDir2.angleYZ()); - return SegmentPhiMatchResult(segDir1Min,segDir2Min,dyz ); - } + return SegmentPhiMatchResult(segDir1Min, segDir2Min, dyz); +} - MuonSegmentInOverlapResolvingTool::SegmentPhiMatchResult MuonSegmentInOverlapResolvingTool::bestPhiMatch( const MuonSegment& seg1, const MuonSegment& seg2 ) const { +MuonSegmentInOverlapResolvingTool::SegmentPhiMatchResult +MuonSegmentInOverlapResolvingTool::bestPhiMatch(const MuonSegment& seg1, const MuonSegment& seg2) const +{ unsigned int nbins = 11; - //unsigned int bestBin = 0; + // unsigned int bestBin = 0; double scanRange = 1.; - double scanStep = scanRange/(nbins-1); - double phiStart = seg1.globalDirection().phi() - 0.5*scanRange; + double scanStep = scanRange / (nbins - 1); + double phiStart = seg1.globalDirection().phi() - 0.5 * scanRange; - double dthetaMin = 1e9; - Amg::Vector3D segDir1Min = seg1.globalDirection(); + double dthetaMin = 1e9; + Amg::Vector3D segDir1Min = seg1.globalDirection(); Trk::LocalDirection segLocDir2; - seg2.associatedSurface().globalToLocalDirection(seg2.globalDirection(),segLocDir2); - for( unsigned int i=0;i<nbins;++i ){ - double phi = phiStart + scanStep*i; - Amg::Vector3D segDir1 = updateSegmentDirection(seg1,phi); - Trk::LocalDirection segLocDir12; - seg2.associatedSurface().globalToLocalDirection(segDir1,segLocDir12); - double dyz = fabs(segLocDir12.angleYZ() - segLocDir2.angleYZ()); - if( dyz < dthetaMin ){ - dthetaMin = dyz; - segDir1Min = segDir1; - //bestBin = i; - } + seg2.associatedSurface().globalToLocalDirection(seg2.globalDirection(), segLocDir2); + for (unsigned int i = 0; i < nbins; ++i) { + double phi = phiStart + scanStep * i; + Amg::Vector3D segDir1 = updateSegmentDirection(seg1, phi); + Trk::LocalDirection segLocDir12; + seg2.associatedSurface().globalToLocalDirection(segDir1, segLocDir12); + double dyz = fabs(segLocDir12.angleYZ() - segLocDir2.angleYZ()); + if (dyz < dthetaMin) { + dthetaMin = dyz; + segDir1Min = segDir1; + // bestBin = i; + } } - return SegmentPhiMatchResult(segDir1Min,updateSegmentDirection(seg2,segDir1Min.phi()),dthetaMin ); - } - - - MuonSegmentInOverlapResolvingTool::SegmentPositionMatchResult - MuonSegmentInOverlapResolvingTool::bestPositionAlongTubeMatch( const MuonSegment& seg1, - const MuonSegment& seg2, - const Amg::Vector3D& segDir1Min ) const { + return SegmentPhiMatchResult(segDir1Min, updateSegmentDirection(seg2, segDir1Min.phi()), dthetaMin); +} + + +MuonSegmentInOverlapResolvingTool::SegmentPositionMatchResult +MuonSegmentInOverlapResolvingTool::bestPositionAlongTubeMatch(const MuonSegment& seg1, const MuonSegment& seg2, + const Amg::Vector3D& segDir1Min) const +{ bool goodMatch = true; // get geomtry summary for segment - SegmentGeometrySummary segmentGeometry = segmentGeometrySummary( seg1 ); - SegmentGeometrySummary segmentGeometry2 = segmentGeometrySummary( seg2 ); + SegmentGeometrySummary segmentGeometry = segmentGeometrySummary(seg1); + SegmentGeometrySummary segmentGeometry2 = segmentGeometrySummary(seg2); - int nbins = 2; + int nbins = 2; double tubeStep = segmentGeometry.hvPosInSegFrame - segmentGeometry.roPosInSegFrame; - double posStep = tubeStep/(nbins-1); + double posStep = tubeStep / (nbins - 1); double resfirst = 1e9; - double reslast = 1e9; + double reslast = 1e9; double posfirst = 1e9; - double poslast = 1e9; - double locy = seg1.localParameters().contains(Trk::locY) ? seg1.localParameters()[Trk::locY] : 0.; - - for( int j=0;j<nbins;++j ){ - double distToRO = segmentGeometry.roPosInSegFrame + posStep*j; - - // create local position - Amg::Vector2D lpos(distToRO,locy); - - // segment reference surface - const Trk::PlaneSurface& segmentSurface = seg2.associatedSurface(); - - // get global position - Amg::Vector3D gpos; - seg1.associatedSurface().localToGlobal(lpos,segDir1Min,gpos); - - // calculate intersection - Trk::Intersection intersect = segmentSurface.straightLineIntersection(gpos,segDir1Min,false,false); - if( !intersect.valid || !segmentSurface.globalToLocal(intersect.position,segDir1Min,lpos) ){ -// if( !intersect.valid || !segmentSurface.globalToLocal(intersect.intersection,segDir1Min,lpos) ){ - ATH_MSG_WARNING(" Intersect with surface position " << Amg::toString(gpos) - << " direction: phi " << segDir1Min.phi() << " theta " << segDir1Min.theta() ); - }else{ - - // now we have the prediction of the track in the segment frame, lets look at residuals - double resy = lpos[Trk::locY]- seg2.localParameters()[Trk::locY]; - - if( j==0 ){ - resfirst = resy; - posfirst = distToRO; - } - if( j==nbins-1 ){ - reslast = resy; - poslast = distToRO; - } - } + double poslast = 1e9; + double locy = seg1.localParameters().contains(Trk::locY) ? seg1.localParameters()[Trk::locY] : 0.; + + for (int j = 0; j < nbins; ++j) { + double distToRO = segmentGeometry.roPosInSegFrame + posStep * j; + + // create local position + Amg::Vector2D lpos(distToRO, locy); + + // segment reference surface + const Trk::PlaneSurface& segmentSurface = seg2.associatedSurface(); + + // get global position + Amg::Vector3D gpos; + seg1.associatedSurface().localToGlobal(lpos, segDir1Min, gpos); + + // calculate intersection + Trk::Intersection intersect = segmentSurface.straightLineIntersection(gpos, segDir1Min, false, false); + if (!intersect.valid || !segmentSurface.globalToLocal(intersect.position, segDir1Min, lpos)) { + // if( !intersect.valid || !segmentSurface.globalToLocal(intersect.intersection,segDir1Min,lpos) ){ + ATH_MSG_WARNING(" Intersect with surface position " << Amg::toString(gpos) << " direction: phi " + << segDir1Min.phi() << " theta " + << segDir1Min.theta()); + } else { + + // now we have the prediction of the track in the segment frame, lets look at residuals + double resy = lpos[Trk::locY] - seg2.localParameters()[Trk::locY]; + + if (j == 0) { + resfirst = resy; + posfirst = distToRO; + } + if (j == nbins - 1) { + reslast = resy; + poslast = distToRO; + } + } } - - double distPosMin2 = 1e9; - double distPosInTube2 = 1e9; - double distPosMin = 1e9; - double distPosInTube = 1e9; - double resyMin = 1e9; - Amg::Vector3D segPos(0.,0.,0.); - double rangeCut = 1e5; - if( resfirst < rangeCut && reslast < rangeCut && posfirst < rangeCut && poslast < rangeCut ){ - double resDif = reslast-resfirst; - double posDif = poslast-posfirst; - if( fabs(resDif) < 1e-6 ){ - ATH_MSG_DEBUG(" Unexpected residual difference " << resDif); - resDif = resDif < 0. ? -1e-6 : 1e-6; - } - if( fabs(posDif) < 1e-6 ){ - ATH_MSG_DEBUG(" Unexpected position difference " << posDif); - posDif = posDif < 0. ? -1e-6 : 1e-6; - } - distPosMin = posfirst - resfirst/(resDif)*(posDif); - distPosInTube = segmentGeometry.positionInsideTube(distPosMin); - resyMin = resfirst + (resDif)*(distPosInTube - posfirst)/(posDif); - - double locx = distPosInTube; - double locy = seg1.localParameters().contains(Trk::locY) ? seg1.localParameters()[Trk::locY] : 0.; - - // create local position - Amg::Vector2D lpos(locx,locy); - - // segment reference surface - const Trk::PlaneSurface& segmentSurface = seg2.associatedSurface(); - - // get global position - Amg::Vector3D gpos; - seg1.associatedSurface().localToGlobal(lpos,segDir1Min,gpos); - segPos = gpos; - - // calculate intersection - Trk::Intersection intersect = segmentSurface.straightLineIntersection(gpos,segDir1Min,false,false); - if( !intersect.valid ){ - ATH_MSG_WARNING(" Intersect with surface position " << Amg::toString(gpos) - << " direction: phi " << segDir1Min.phi() << " theta " << segDir1Min.theta() ); - goodMatch = false; - }else{ - Amg::Vector3D locExSeg2 = segmentGeometry2.globalToSeg*intersect.position; - distPosMin2 = locExSeg2.x(); - distPosInTube2 = segmentGeometry2.positionInsideTube(distPosMin2); - } - - }else{ - goodMatch = false; + + double distPosMin2 = 1e9; + double distPosInTube2 = 1e9; + double distPosMin = 1e9; + double distPosInTube = 1e9; + double resyMin = 1e9; + Amg::Vector3D segPos(0., 0., 0.); + double rangeCut = 1e5; + if (resfirst < rangeCut && reslast < rangeCut && posfirst < rangeCut && poslast < rangeCut) { + double resDif = reslast - resfirst; + double posDif = poslast - posfirst; + if (fabs(resDif) < 1e-6) { + ATH_MSG_DEBUG(" Unexpected residual difference " << resDif); + resDif = resDif < 0. ? -1e-6 : 1e-6; + } + if (fabs(posDif) < 1e-6) { + ATH_MSG_DEBUG(" Unexpected position difference " << posDif); + posDif = posDif < 0. ? -1e-6 : 1e-6; + } + distPosMin = posfirst - resfirst / (resDif) * (posDif); + distPosInTube = segmentGeometry.positionInsideTube(distPosMin); + resyMin = resfirst + (resDif) * (distPosInTube - posfirst) / (posDif); + + double locx = distPosInTube; + double locy = seg1.localParameters().contains(Trk::locY) ? seg1.localParameters()[Trk::locY] : 0.; + + // create local position + Amg::Vector2D lpos(locx, locy); + + // segment reference surface + const Trk::PlaneSurface& segmentSurface = seg2.associatedSurface(); + + // get global position + Amg::Vector3D gpos; + seg1.associatedSurface().localToGlobal(lpos, segDir1Min, gpos); + segPos = gpos; + + // calculate intersection + Trk::Intersection intersect = segmentSurface.straightLineIntersection(gpos, segDir1Min, false, false); + if (!intersect.valid) { + ATH_MSG_WARNING(" Intersect with surface position " << Amg::toString(gpos) << " direction: phi " + << segDir1Min.phi() << " theta " + << segDir1Min.theta()); + goodMatch = false; + } else { + Amg::Vector3D locExSeg2 = segmentGeometry2.globalToSeg * intersect.position; + distPosMin2 = locExSeg2.x(); + distPosInTube2 = segmentGeometry2.positionInsideTube(distPosMin2); + } + + } else { + goodMatch = false; } - return SegmentPositionMatchResult( distPosMin, distPosInTube, segmentGeometry.shortestChannelLength, - distPosMin2, distPosInTube2, segmentGeometry2.shortestChannelLength, - resyMin, goodMatch, segPos ); - } + return SegmentPositionMatchResult(distPosMin, distPosInTube, segmentGeometry.shortestChannelLength, distPosMin2, + distPosInTube2, segmentGeometry2.shortestChannelLength, resyMin, goodMatch, + segPos); +} +MuonSegmentInOverlapResolvingTool::SegmentGeometrySummary +MuonSegmentInOverlapResolvingTool::segmentGeometrySummary(const MuonSegment& seg) const +{ - MuonSegmentInOverlapResolvingTool::SegmentGeometrySummary MuonSegmentInOverlapResolvingTool::segmentGeometrySummary( const MuonSegment& seg ) const { - SegmentGeometrySummary summary; // loop over hits - Identifier tubeId1; - const MuonGM::MdtReadoutElement* detEl = 0; - double shortestTubeLen = 1e9; - Amg::Vector3D roPos; - Amg::Vector3D tubeCenter; - MeasCit sit = seg.containedMeasurements().begin(); - MeasCit sit_end = seg.containedMeasurements().end(); - bool hasMdt = false; - for( ;sit!=sit_end;++sit ){ - - const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(*sit); - if( mdt ){ - hasMdt = true; - const Identifier& id = mdt->identify(); - int layer = m_idHelperSvc->mdtIdHelper().tubeLayer(id); - int tube = m_idHelperSvc->mdtIdHelper().tube(id); - double tubelen = mdt->prepRawData()->detectorElement()->getActiveTubeLength(layer,tube); - if( tubelen < shortestTubeLen ) { - shortestTubeLen = tubelen; - roPos = mdt->prepRawData()->detectorElement()->ROPos(id); - tubeCenter = mdt->prepRawData()->detectorElement()->surface(id).center(); - detEl = mdt->prepRawData()->detectorElement(); - tubeId1 = id; - } - } + Identifier tubeId1; + const MuonGM::MdtReadoutElement* detEl = 0; + double shortestTubeLen = 1e9; + Amg::Vector3D roPos; + Amg::Vector3D tubeCenter; + MeasCit sit = seg.containedMeasurements().begin(); + MeasCit sit_end = seg.containedMeasurements().end(); + bool hasMdt = false; + for (; sit != sit_end; ++sit) { + + const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(*sit); + if (mdt) { + hasMdt = true; + const Identifier& id = mdt->identify(); + int layer = m_idHelperSvc->mdtIdHelper().tubeLayer(id); + int tube = m_idHelperSvc->mdtIdHelper().tube(id); + double tubelen = mdt->prepRawData()->detectorElement()->getActiveTubeLength(layer, tube); + if (tubelen < shortestTubeLen) { + shortestTubeLen = tubelen; + roPos = mdt->prepRawData()->detectorElement()->ROPos(id); + tubeCenter = mdt->prepRawData()->detectorElement()->surface(id).center(); + detEl = mdt->prepRawData()->detectorElement(); + tubeId1 = id; + } + } } - summary.detEl = detEl; - summary.hasMdt = hasMdt; - summary.segToGlobal = seg.associatedSurface().transform(); - summary.globalToSeg = summary.segToGlobal.inverse(); - summary.roPosInSegFrame = (summary.globalToSeg*roPos).x(); - double distTubeCenterFromRO = (summary.globalToSeg*tubeCenter).x() - summary.roPosInSegFrame; - summary.hvPosInSegFrame = summary.roPosInSegFrame + 2*distTubeCenterFromRO; - summary.shortestChannelLength = fabs(2*distTubeCenterFromRO); + summary.detEl = detEl; + summary.hasMdt = hasMdt; + summary.segToGlobal = seg.associatedSurface().transform(); + summary.globalToSeg = summary.segToGlobal.inverse(); + summary.roPosInSegFrame = (summary.globalToSeg * roPos).x(); + double distTubeCenterFromRO = (summary.globalToSeg * tubeCenter).x() - summary.roPosInSegFrame; + summary.hvPosInSegFrame = summary.roPosInSegFrame + 2 * distTubeCenterFromRO; + summary.shortestChannelLength = fabs(2 * distTubeCenterFromRO); return summary; - } +} - MuonSegmentInOverlapResolvingTool::SegmentMatchResult MuonSegmentInOverlapResolvingTool::matchResult( const MuonSegment& seg1, const MuonSegment& seg2 ) const { +MuonSegmentInOverlapResolvingTool::SegmentMatchResult +MuonSegmentInOverlapResolvingTool::matchResult(const MuonSegment& seg1, const MuonSegment& seg2) const +{ ATH_MSG_DEBUG(" First segment " << m_printer->print(seg1) << std::endl - << " Second segment " << m_printer->print(seg2)); + << " Second segment " << m_printer->print(seg2)); SegmentMatchResult result = SegmentMatchResult(); - + // calculate the phi angle that matches the two local segment angles - result.phiResult = bestPhiMatchAnalytic(seg1,seg2); + result.phiResult = bestPhiMatchAnalytic(seg1, seg2); - // calculate the position along the tube that minimizes the position residual for both segments - result.segmentResult1 = bestPositionAlongTubeMatch( seg1, seg2, result.phiResult.segmentDirection1 ); - result.segmentResult2 = bestPositionAlongTubeMatch( seg2, seg1, result.phiResult.segmentDirection2 ); + // calculate the position along the tube that minimizes the position residual for both segments + result.segmentResult1 = bestPositionAlongTubeMatch(seg1, seg2, result.phiResult.segmentDirection1); + result.segmentResult2 = bestPositionAlongTubeMatch(seg2, seg1, result.phiResult.segmentDirection2); // calculate the average pull of the phi hits on the segments with the new parameters - result.averagePhiHitPullSegment1 = checkPhiHitConsistency( seg1, result.phiResult, result.segmentResult1 ); - result.averagePhiHitPullSegment2 = checkPhiHitConsistency( seg2, result.phiResult, result.segmentResult2 ); - - if( result.segmentResult1.goodMatch && result.segmentResult2.goodMatch ){ - - // calculate vector connecting the two new segment positions - Amg::Vector3D difPos = result.segmentResult2.segmentPosition - result.segmentResult1.segmentPosition; - - // check if vectors are pointing in the same direction, else flip - if( result.phiResult.segmentDirection1.y()*difPos.y() < 0. ){ - difPos *= -1.; - } - - // calculate difference in angle between phi from phi match and the two new segment positions - double norm = difPos.perp()*result.phiResult.segmentDirection1.perp(); - double cosdphi = (result.phiResult.segmentDirection1.x()*difPos.x() + result.phiResult.segmentDirection1.y()*difPos.y())/norm; - if( cosdphi > 0.999999 ) cosdphi = 0.999999; - else if( cosdphi < -0.999999 ) cosdphi = -0.999999; - result.angularDifferencePhi = std::acos(cosdphi); + result.averagePhiHitPullSegment1 = checkPhiHitConsistency(seg1, result.phiResult, result.segmentResult1); + result.averagePhiHitPullSegment2 = checkPhiHitConsistency(seg2, result.phiResult, result.segmentResult2); + + if (result.segmentResult1.goodMatch && result.segmentResult2.goodMatch) { + + // calculate vector connecting the two new segment positions + Amg::Vector3D difPos = result.segmentResult2.segmentPosition - result.segmentResult1.segmentPosition; + + // check if vectors are pointing in the same direction, else flip + if (result.phiResult.segmentDirection1.y() * difPos.y() < 0.) { + difPos *= -1.; + } + + // calculate difference in angle between phi from phi match and the two new segment positions + double norm = difPos.perp() * result.phiResult.segmentDirection1.perp(); + double cosdphi = + (result.phiResult.segmentDirection1.x() * difPos.x() + result.phiResult.segmentDirection1.y() * difPos.y()) + / norm; + if (cosdphi > 0.999999) + cosdphi = 0.999999; + else if (cosdphi < -0.999999) + cosdphi = -0.999999; + result.angularDifferencePhi = std::acos(cosdphi); } return result; - } +} + - - double MuonSegmentInOverlapResolvingTool::checkPhiHitConsistency( const Muon::MuonSegment& segment, SegmentPhiMatchResult& phiMatchResult, - SegmentPositionMatchResult& posMatchResult ) const { +double +MuonSegmentInOverlapResolvingTool::checkPhiHitConsistency(const Muon::MuonSegment& segment, + SegmentPhiMatchResult& phiMatchResult, + SegmentPositionMatchResult& posMatchResult) const +{ // calculate average pull of phi measurements - unsigned int nphiMeas = 0; - double averagePull = 0.; + unsigned int nphiMeas = 0; + double averagePull = 0.; // calculate segment AtaPlane - //SegmentGeometrySummary geometry = segmentGeometrySummary( segment ); - double locx = posMatchResult.positionInTube1; - double locy = segment.localParameters().contains(Trk::locY) ? segment.localParameters()[Trk::locY] : 0.; - Trk::AtaPlane segPars(locx,locy,phiMatchResult.segmentDirection1.phi(),phiMatchResult.segmentDirection1.theta(),0.,segment.associatedSurface()); + // SegmentGeometrySummary geometry = segmentGeometrySummary( segment ); + double locx = posMatchResult.positionInTube1; + double locy = segment.localParameters().contains(Trk::locY) ? segment.localParameters()[Trk::locY] : 0.; + Trk::AtaPlane segPars(locx, locy, phiMatchResult.segmentDirection1.phi(), phiMatchResult.segmentDirection1.theta(), + 0., segment.associatedSurface()); // loop over hits and calculate residuals for phi hits - MeasCit mit = segment.containedMeasurements().begin(); + MeasCit mit = segment.containedMeasurements().begin(); MeasCit mit_end = segment.containedMeasurements().end(); - for( ;mit!=mit_end;++mit ){ - - Identifier id = m_edmHelperSvc->getIdentifier(**mit); - if( !id.is_valid() || !m_idHelperSvc->measuresPhi(id) ) continue; - - // predict onto segment surface - const Trk::Surface& measSurf = (**mit).associatedSurface(); - - // propagate station parameters to segment - const Trk::TrackParameters* exPars = m_propagator->propagate(segPars,measSurf,Trk::anyDirection,false,m_magFieldProperties); - if( !exPars ) { - ATH_MSG_WARNING(" Failed to propagate parameter to segment surface" << std::endl - << " pars " << m_printer->print(segPars)); - }else{ - - const Trk::ResidualPull* resPull = m_pullCalculator->residualPull( *mit, exPars, Trk::ResidualPull::Unbiased ); - if( !resPull ) { - ATH_MSG_DEBUG(" calculation of residual/pull failed !!!!! "); - delete exPars; - continue; - } - - // sanity check - if( resPull->pull().size() != 1 ){ - ATH_MSG_WARNING(" ResidualPull with empty pull vector for channel " << m_idHelperSvc->toString(id)); - delete resPull; - delete exPars; - continue; - } - - double pull = resPull->pull().front(); - - averagePull += pull; - ++nphiMeas; - delete resPull; - delete exPars; - } + for (; mit != mit_end; ++mit) { + + Identifier id = m_edmHelperSvc->getIdentifier(**mit); + if (!id.is_valid() || !m_idHelperSvc->measuresPhi(id)) continue; + + // predict onto segment surface + const Trk::Surface& measSurf = (**mit).associatedSurface(); + + // propagate station parameters to segment + const Trk::TrackParameters* exPars = + m_propagator->propagate(segPars, measSurf, Trk::anyDirection, false, m_magFieldProperties); + if (!exPars) { + ATH_MSG_WARNING(" Failed to propagate parameter to segment surface" << std::endl + << " pars " + << m_printer->print(segPars)); + } else { + + const Trk::ResidualPull* resPull = + m_pullCalculator->residualPull(*mit, exPars, Trk::ResidualPull::Unbiased); + if (!resPull) { + ATH_MSG_DEBUG(" calculation of residual/pull failed !!!!! "); + delete exPars; + continue; + } + + // sanity check + if (resPull->pull().size() != 1) { + ATH_MSG_WARNING(" ResidualPull with empty pull vector for channel " << m_idHelperSvc->toString(id)); + delete resPull; + delete exPars; + continue; + } + + double pull = resPull->pull().front(); + + averagePull += pull; + ++nphiMeas; + delete resPull; + delete exPars; + } } - if( nphiMeas != 0 ) averagePull /= nphiMeas; + if (nphiMeas != 0) averagePull /= nphiMeas; return averagePull; - } - } + +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentInOverlapResolvingTool.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentInOverlapResolvingTool.h index e0cdc515120e1c4fba984ab012a0e6123471de37..4d505a5e9e78e8c4add557bc65ff13661ae523dc 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentInOverlapResolvingTool.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentInOverlapResolvingTool.h @@ -5,93 +5,112 @@ #ifndef MUON_MUONSEGMENTSOVERLAPRESOLVINGTOOL_H #define MUON_MUONSEGMENTSOVERLAPRESOLVINGTOOL_H -#include "MuonSegmentMakerToolInterfaces/IMuonSegmentInOverlapResolvingTool.h" +#include <string> +#include <vector> #include "AthenaBaseComps/AthAlgTool.h" -#include "GaudiKernel/ToolHandle.h" #include "GaudiKernel/ServiceHandle.h" - +#include "GaudiKernel/ToolHandle.h" #include "GeoPrimitives/GeoPrimitives.h" -#include "TrkGeometry/MagneticFieldProperties.h" -#include "MuonRecHelperTools/IMuonEDMHelperSvc.h" #include "MuonIdHelpers/IMuonIdHelperSvc.h" -#include "TrkToolInterfaces/IResidualPullCalculator.h" -#include "TrkExInterfaces/IPropagator.h" +#include "MuonRecHelperTools/IMuonEDMHelperSvc.h" #include "MuonRecHelperTools/MuonEDMPrinterTool.h" - -#include <vector> -#include <string> +#include "MuonSegmentMakerToolInterfaces/IMuonSegmentInOverlapResolvingTool.h" +#include "TrkExInterfaces/IPropagator.h" +#include "TrkGeometry/MagneticFieldProperties.h" +#include "TrkToolInterfaces/IResidualPullCalculator.h" class MsgStream; namespace Trk { - class MagneticFieldProperties; - class MeasurementBase; -} +class MagneticFieldProperties; +class MeasurementBase; +} // namespace Trk namespace MuonGM { - class MdtReadoutElement; +class MdtReadoutElement; } namespace Muon { - - class MuonSegment; - /** - @brief tool to match segments - */ - class MuonSegmentInOverlapResolvingTool : virtual public IMuonSegmentInOverlapResolvingTool, public AthAlgTool { +class MuonSegment; +/** + @brief tool to match segments + +*/ +class MuonSegmentInOverlapResolvingTool : virtual public IMuonSegmentInOverlapResolvingTool, public AthAlgTool { public: /** @brief constructor */ - MuonSegmentInOverlapResolvingTool(const std::string&,const std::string&,const IInterface*); + MuonSegmentInOverlapResolvingTool(const std::string&, const std::string&, const IInterface*); /** @brief destructor */ - virtual ~MuonSegmentInOverlapResolvingTool() {}; - + virtual ~MuonSegmentInOverlapResolvingTool(){}; + /** @brief AlgTool initilize */ StatusCode initialize(); - + /** @brief performance match and return result */ - SegmentMatchResult matchResult( const MuonSegment& seg1, const MuonSegment& seg2 ) const; + SegmentMatchResult matchResult(const MuonSegment& seg1, const MuonSegment& seg2) const; /** @brief calculate the position along a tube direction of the first segment - that results in the smallest position residual in the precision plane of the second segment given - the segment direction for segment 1 in global coordinates */ - SegmentPositionMatchResult bestPositionAlongTubeMatch( const MuonSegment& seg1, const MuonSegment& seg2, - const Amg::Vector3D& segDir1Min ) const; - - /** calculate the angle phi for which the angular residual in the precision plane of - the second segment is zero */ - SegmentPhiMatchResult bestPhiMatch( const MuonSegment& seg1, const MuonSegment& seg2 ) const; - - /** calculate the angle phi for which the angular residual in the precision plane of - the second segment is zero */ - SegmentPhiMatchResult bestPhiMatchAnalytic( const MuonSegment& seg1, const MuonSegment& seg2 ) const; + that results in the smallest position residual in the precision plane of the second segment given + the segment direction for segment 1 in global coordinates */ + SegmentPositionMatchResult bestPositionAlongTubeMatch(const MuonSegment& seg1, const MuonSegment& seg2, + const Amg::Vector3D& segDir1Min) const; + + /** calculate the angle phi for which the angular residual in the precision plane of + the second segment is zero */ + SegmentPhiMatchResult bestPhiMatch(const MuonSegment& seg1, const MuonSegment& seg2) const; + + /** calculate the angle phi for which the angular residual in the precision plane of + the second segment is zero */ + SegmentPhiMatchResult bestPhiMatchAnalytic(const MuonSegment& seg1, const MuonSegment& seg2) const; /** recalculate the segment direction give a new angle phi, keeps the angle in the precision plane fixed */ - Amg::Vector3D updateSegmentDirection( const MuonSegment& seg, double phi ) const; + Amg::Vector3D updateSegmentDirection(const MuonSegment& seg, double phi) const; /** calculate geometrical information for a segment */ - SegmentGeometrySummary segmentGeometrySummary( const MuonSegment& seg ) const; + SegmentGeometrySummary segmentGeometrySummary(const MuonSegment& seg) const; + private: - /** compare phi hits with segment parameters, return average pull of the phi hits */ - double checkPhiHitConsistency( const Muon::MuonSegment& segment, SegmentPhiMatchResult& phiMatchResult, - SegmentPositionMatchResult& matchResult ) const; - - Amg::Vector3D estimateSegmentDirection( const MuonSegment& seg1, const MuonSegment& seg2, double& phi, double& stereoangle ) const; - - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - ServiceHandle<IMuonEDMHelperSvc> m_edmHelperSvc {this, "edmHelper", - "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", - "Handle to the service providing the IMuonEDMHelperSvc interface" }; //!< EDM Helper tool - ToolHandle<MuonEDMPrinterTool> m_printer; //!< EDM printer tool - ToolHandle<Trk::IPropagator> m_propagator; - Trk::MagneticFieldProperties m_magFieldProperties; //!< magnetic field properties - ToolHandle<Trk::IResidualPullCalculator> m_pullCalculator; - - }; - -} + double checkPhiHitConsistency(const Muon::MuonSegment& segment, SegmentPhiMatchResult& phiMatchResult, + SegmentPositionMatchResult& matchResult) const; + + Amg::Vector3D estimateSegmentDirection(const MuonSegment& seg1, const MuonSegment& seg2, double& phi, + double& stereoangle) const; + + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; + ServiceHandle<IMuonEDMHelperSvc> m_edmHelperSvc{ + this, + "edmHelper", + "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", + "Handle to the service providing the IMuonEDMHelperSvc interface", + }; //!< EDM Helper tool + + ToolHandle<MuonEDMPrinterTool> m_printer{ + this, + "Printer", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; //!< EDM printer tool + ToolHandle<Trk::IPropagator> m_propagator{ + this, + "AtlasRungeKuttaPropagator", + "Trk::RungeKuttaPropagator/AtlasRungeKuttaPropagator", + }; + ToolHandle<Trk::IResidualPullCalculator> m_pullCalculator{ + this, + "ResidualPullCalculator", + "Trk::ResidualPullCalculator/ResidualPullCalculator", + }; + + Trk::MagneticFieldProperties m_magFieldProperties; //!< magnetic field properties +}; + +} // namespace Muon #endif diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentMatchingTool.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentMatchingTool.cxx index f04f66d6cf5aa46949e0b86f4beca221d24767eb..e79a8602e1f1b5a5764c12d0baaee1ff3a36545d 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentMatchingTool.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentMatchingTool.cxx @@ -4,72 +4,92 @@ #include "MuonSegmentMatchingTool.h" -#include "MuonSegment/MuonSegment.h" - #include <cmath> #include <iostream> +#include "MuonSegment/MuonSegment.h" + namespace Muon { - MuonSegmentMatchingTool::MuonSegmentMatchingTool(const std::string& ty,const std::string& na,const IInterface* pa) - : AthAlgTool(ty,na,pa), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"), - m_overlapResolvingTool("Muon::MuonSegmentInOverlapResolvingTool/MuonSegmentInOverlapResolvingTool"), - m_pairMatchingTool("Muon::MuonSegmentPairMatchingTool/MuonSegmentPairMatchingTool"), - m_straightLineMatches(0),m_straightLineMatchesGood(0), - m_overlapMatches(0),m_overlapMatchesGood(0), - m_curvedMatches(0),m_curvedMatchesGood(0) - { +MuonSegmentMatchingTool::MuonSegmentMatchingTool(const std::string& ty, const std::string& na, const IInterface* pa) + : AthAlgTool(ty, na, pa), + m_straightLineMatches(0), + m_straightLineMatchesGood(0), + m_overlapMatches(0), + m_overlapMatchesGood(0), + m_curvedMatches(0), + m_curvedMatchesGood(0) +{ declareInterface<IMuonSegmentMatchingTool>(this); - declareProperty("UseCosmicsSettings", m_isCosmics = false, "Pick up settings for cosmics"); - declareProperty("DoOverlapMatch", m_doOverlapMatch = true, "Perform matching for segments in a small/large overlap"); - declareProperty("DoStraightLineMatch", m_doStraightLineMatch = true, "Perform matching for segments in regions without field"); - declareProperty("DoCurvedMatch", m_doCurvedMatch = true, "Perform matching for segments in a field regions"); - declareProperty("doThetaMatching", m_thetaMatch = false, "Pre-matching in theta" ); - declareProperty("doPhiMatching", m_phiMatch = false, "Pre-matching in phi" ); - - declareProperty("OverlapMatchAngleDPhiCut",m_overlapMatchAngleDPhiCut = 0.15, - "Cut on the angular difference between the best phi and the one consistent with the chamber bounds"); - declareProperty("OverlapMatchAngleDYZCut",m_overlapMatchAngleDYZCut = 0.05, - "Cut on the angular difference between the best phi and the one consistent with the chamber bounds"); - declareProperty("OverlapMatchPositionCut",m_overlapMatchPositionCut = 100., - "Cut on the distance of recalculated position to the tube edge"); - declareProperty("OverlapMatchPositionResidualCut",m_overlapMatchPositionResidualCut = 30., - "Cut on the segment position residual after recalculation of the paramters"); - declareProperty("OverlapMatchAveragePhiHitPullCut",m_overlapMatchPhiHitPullCut = 20., - "Cut on the average pull of the phi hits with the new segment parameters"); - - declareProperty("StraightLineMatchAngleCut",m_straightLineMatchAngleCut = 0.1, - "Cut on the angular difference between the extrapolated segment angle and reference"); - declareProperty("StraightLineMatchPositionCut",m_straightLineMatchPositionCut = 200., - "Cut on the distance of extrapolated segment position and reference"); - declareProperty("MaxDistanceBetweenSegments",m_maxDistSegments = 5000., - "If the two segments are further apart than this distance, they are considered to not match"); - - declareProperty("OnlySameSectorIfTight",m_onlySameSectorIfTight = true, "Accept only segments that are in the same sector for tight matching"); - declareProperty("TightSegmentMatching",m_useTightCuts = false, "Use tight selection for busy event to suppress combinatorics and improve CPU"); - - declareProperty("DumpAngles", m_dumpAngles = false, "Print matching angle information to screen. WARNING: always returns True for suppressNoise"); - declareProperty("DoMatchingCutsBIBM_S", m_matchingbibm_sphisec = 0.015, "Cut on sumDeltaYZ, segments in BI and BM, small phi sec"); - declareProperty("DoMatchingCutsBIBO_S", m_matchingbibo_sphisec = 0.015, "Cut on sumDeltaYZ, segments in BI and BO, small phi sec"); - declareProperty("DoMatchingCutsBMBO_S", m_matchingbmbo_sphisec = 0.015, "Cut on sumDeltaYZ, segments in BM and BO, small phi sec"); - declareProperty("DoMatchingCutsEIEM_S", m_matchingeiem_sphisec = 0.010*2, "Cut on sumDeltaYZ, segments in EI and EM, small phi sec"); - declareProperty("DoMatchingCutsEIEO_S", m_matchingeieo_sphisec = 0.020*2, "Cut on sumDeltaYZ, segments in EI and EO, small phi sec"); - declareProperty("DoMatchingCutsEMEO_S", m_matchingemeo_sphisec = 0.002, "Cut on sumDeltaYZ, segments in EM and EO, small phi sec"); - declareProperty("DoMatchingCutsBIBM_L", m_matchingbibm_lphisec = 0.005, "Cut on sumDeltaYZ, segments in BI and BM, large phi sec"); - declareProperty("DoMatchingCutsBIBO_L", m_matchingbibo_lphisec = 0.015, "Cut on sumDeltaYZ, segments in BI and BO, large phi sec"); - declareProperty("DoMatchingCutsBMBO_L", m_matchingbmbo_lphisec = 0.010, "Cut on sumDeltaYZ, segments in BM and BO, large phi sec"); - declareProperty("DoMatchingCutsEIEM_L", m_matchingeiem_lphisec = 0.015*2, "Cut on sumDeltaYZ, segments in EI and EM, large phi sec"); - declareProperty("DoMatchingCutsEIEO_L", m_matchingeieo_lphisec = 0.025*2, "Cut on sumDeltaYZ, segments in EI and EO, large phi sec"); - declareProperty("DoMatchingCutsEMEO_L", m_matchingemeo_lphisec = 0.002, "Cut on sumDeltaYZ, segments in EM and EO, large phi sec"); - declareProperty("UseEndcapExtrapolationMatching", m_useEndcapExtrapolationMatching = true ); - declareProperty("DrExtrapolationRMS", m_drExtrapRMS = 10 ); - declareProperty("DThetaExtrapolationRMS", m_dthetaExtrapRMS = 0.01*2 ); - declareProperty("DrExtrapolationAlignementOffset", m_drExtrapAlignmentOffset = 50 ); + declareProperty("UseCosmicsSettings", m_isCosmics = false, "Pick up settings for cosmics"); + declareProperty("DoOverlapMatch", m_doOverlapMatch = true, + "Perform matching for segments in a small/large overlap"); + declareProperty("DoStraightLineMatch", m_doStraightLineMatch = true, + "Perform matching for segments in regions without field"); + declareProperty("DoCurvedMatch", m_doCurvedMatch = true, "Perform matching for segments in a field regions"); + declareProperty("doThetaMatching", m_thetaMatch = false, "Pre-matching in theta"); + declareProperty("doPhiMatching", m_phiMatch = false, "Pre-matching in phi"); + + declareProperty( + "OverlapMatchAngleDPhiCut", m_overlapMatchAngleDPhiCut = 0.15, + "Cut on the angular difference between the best phi and the one consistent with the chamber bounds"); + declareProperty( + "OverlapMatchAngleDYZCut", m_overlapMatchAngleDYZCut = 0.05, + "Cut on the angular difference between the best phi and the one consistent with the chamber bounds"); + declareProperty("OverlapMatchPositionCut", m_overlapMatchPositionCut = 100., + "Cut on the distance of recalculated position to the tube edge"); + declareProperty("OverlapMatchPositionResidualCut", m_overlapMatchPositionResidualCut = 30., + "Cut on the segment position residual after recalculation of the paramters"); + declareProperty("OverlapMatchAveragePhiHitPullCut", m_overlapMatchPhiHitPullCut = 20., + "Cut on the average pull of the phi hits with the new segment parameters"); + + declareProperty("StraightLineMatchAngleCut", m_straightLineMatchAngleCut = 0.1, + "Cut on the angular difference between the extrapolated segment angle and reference"); + declareProperty("StraightLineMatchPositionCut", m_straightLineMatchPositionCut = 200., + "Cut on the distance of extrapolated segment position and reference"); + declareProperty("MaxDistanceBetweenSegments", m_maxDistSegments = 5000., + "If the two segments are further apart than this distance, they are considered to not match"); + + declareProperty("OnlySameSectorIfTight", m_onlySameSectorIfTight = true, + "Accept only segments that are in the same sector for tight matching"); + declareProperty("TightSegmentMatching", m_useTightCuts = false, + "Use tight selection for busy event to suppress combinatorics and improve CPU"); + + declareProperty("DumpAngles", m_dumpAngles = false, + "Print matching angle information to screen. WARNING: always returns True for suppressNoise"); + declareProperty("DoMatchingCutsBIBM_S", m_matchingbibm_sphisec = 0.015, + "Cut on sumDeltaYZ, segments in BI and BM, small phi sec"); + declareProperty("DoMatchingCutsBIBO_S", m_matchingbibo_sphisec = 0.015, + "Cut on sumDeltaYZ, segments in BI and BO, small phi sec"); + declareProperty("DoMatchingCutsBMBO_S", m_matchingbmbo_sphisec = 0.015, + "Cut on sumDeltaYZ, segments in BM and BO, small phi sec"); + declareProperty("DoMatchingCutsEIEM_S", m_matchingeiem_sphisec = 0.010 * 2, + "Cut on sumDeltaYZ, segments in EI and EM, small phi sec"); + declareProperty("DoMatchingCutsEIEO_S", m_matchingeieo_sphisec = 0.020 * 2, + "Cut on sumDeltaYZ, segments in EI and EO, small phi sec"); + declareProperty("DoMatchingCutsEMEO_S", m_matchingemeo_sphisec = 0.002, + "Cut on sumDeltaYZ, segments in EM and EO, small phi sec"); + declareProperty("DoMatchingCutsBIBM_L", m_matchingbibm_lphisec = 0.005, + "Cut on sumDeltaYZ, segments in BI and BM, large phi sec"); + declareProperty("DoMatchingCutsBIBO_L", m_matchingbibo_lphisec = 0.015, + "Cut on sumDeltaYZ, segments in BI and BO, large phi sec"); + declareProperty("DoMatchingCutsBMBO_L", m_matchingbmbo_lphisec = 0.010, + "Cut on sumDeltaYZ, segments in BM and BO, large phi sec"); + declareProperty("DoMatchingCutsEIEM_L", m_matchingeiem_lphisec = 0.015 * 2, + "Cut on sumDeltaYZ, segments in EI and EM, large phi sec"); + declareProperty("DoMatchingCutsEIEO_L", m_matchingeieo_lphisec = 0.025 * 2, + "Cut on sumDeltaYZ, segments in EI and EO, large phi sec"); + declareProperty("DoMatchingCutsEMEO_L", m_matchingemeo_lphisec = 0.002, + "Cut on sumDeltaYZ, segments in EM and EO, large phi sec"); + declareProperty("UseEndcapExtrapolationMatching", m_useEndcapExtrapolationMatching = true); + declareProperty("DrExtrapolationRMS", m_drExtrapRMS = 10); + declareProperty("DThetaExtrapolationRMS", m_dthetaExtrapRMS = 0.01 * 2); + declareProperty("DrExtrapolationAlignementOffset", m_drExtrapAlignmentOffset = 50); } - StatusCode MuonSegmentMatchingTool::initialize() - { +StatusCode +MuonSegmentMatchingTool::initialize() +{ ATH_CHECK(AthAlgTool::initialize()); ATH_CHECK(m_edmHelperSvc.retrieve()); ATH_CHECK(m_printer.retrieve()); @@ -77,964 +97,959 @@ namespace Muon { ATH_CHECK(m_pairMatchingTool.retrieve()); ATH_CHECK(m_overlapResolvingTool.retrieve()); return StatusCode::SUCCESS; - } +} - StatusCode MuonSegmentMatchingTool::finalize() - { - double goodOverlapMatchFraction = m_overlapMatches != 0 ? (double)m_overlapMatchesGood/((double)m_overlapMatches) : 0.; - ATH_MSG_INFO("Overlap matches: total " << std::setw(7) << m_overlapMatches - << " good " << std::setw(7) << m_overlapMatchesGood << " fraction " << goodOverlapMatchFraction); +StatusCode +MuonSegmentMatchingTool::finalize() +{ + double goodOverlapMatchFraction = + m_overlapMatches != 0 ? (double)m_overlapMatchesGood / ((double)m_overlapMatches) : 0.; + ATH_MSG_INFO("Overlap matches: total " << std::setw(7) << m_overlapMatches << " good " << std::setw(7) + << m_overlapMatchesGood << " fraction " << goodOverlapMatchFraction); - double goodStraightLineMatchFraction = m_straightLineMatches != 0 ? (double)m_straightLineMatchesGood/((double)m_straightLineMatches) : 0.; - ATH_MSG_INFO("StraightLine matches: total " << std::setw(7) << m_straightLineMatches - << " good " << std::setw(7) << m_straightLineMatchesGood << " fraction " << goodStraightLineMatchFraction); + double goodStraightLineMatchFraction = + m_straightLineMatches != 0 ? (double)m_straightLineMatchesGood / ((double)m_straightLineMatches) : 0.; + ATH_MSG_INFO("StraightLine matches: total " << std::setw(7) << m_straightLineMatches << " good " << std::setw(7) + << m_straightLineMatchesGood << " fraction " + << goodStraightLineMatchFraction); - double goodCurvedMatchFraction = m_curvedMatches != 0 ? (double)m_curvedMatchesGood/((double)m_curvedMatches) : 0.; - ATH_MSG_INFO("Curved matches: total " << std::setw(7) << m_curvedMatches - << " good " << std::setw(7) << m_curvedMatchesGood << " fraction " << goodCurvedMatchFraction); + double goodCurvedMatchFraction = + m_curvedMatches != 0 ? (double)m_curvedMatchesGood / ((double)m_curvedMatches) : 0.; + ATH_MSG_INFO("Curved matches: total " << std::setw(7) << m_curvedMatches << " good " << std::setw(7) + << m_curvedMatchesGood << " fraction " << goodCurvedMatchFraction); - if( AthAlgTool::finalize().isFailure() ) return StatusCode::FAILURE; + if (AthAlgTool::finalize().isFailure()) return StatusCode::FAILURE; return StatusCode::SUCCESS; - } +} - bool MuonSegmentMatchingTool::match( const MuonSegment& seg1, const MuonSegment& seg2 ) const { - - ATH_MSG_VERBOSE(" match: segments " << std::endl - << m_printer->print(seg1) << std::endl << m_printer->print(seg2)); - - // get identifiers +bool +MuonSegmentMatchingTool::match(const MuonSegment& seg1, const MuonSegment& seg2) const +{ + + ATH_MSG_VERBOSE(" match: segments " << std::endl << m_printer->print(seg1) << std::endl << m_printer->print(seg2)); + + // get identifiers Identifier chid1 = m_edmHelperSvc->chamberId(seg1); Identifier chid2 = m_edmHelperSvc->chamberId(seg2); - if( chid1 == chid2 ) return false; + if (chid1 == chid2) return false; MuonStationIndex::StIndex stIndex1 = m_idHelperSvc->stationIndex(chid1); MuonStationIndex::StIndex stIndex2 = m_idHelperSvc->stationIndex(chid2); - if( isSLMatch(chid1,chid2) ){ - if( !m_idHelperSvc->isMdt(chid1) || !m_idHelperSvc->isMdt(chid2)) return false; - // if there is a stereo angle match using overlap matching tool - - if( stIndex1 == stIndex2 ){ - - if( hasStereoAngle(chid1,chid2) ){ - if( !m_doOverlapMatch ) return true; - int eta1 = m_idHelperSvc->mdtIdHelper().stationEta(chid1); - int eta2 = m_idHelperSvc->mdtIdHelper().stationEta(chid2); - int phi1 = m_idHelperSvc->sector(chid1); - int phi2 = m_idHelperSvc->sector(chid2); - - // require that the two segments are close in eta AND are in adjecent sectors - if( (eta1==eta2||eta1==eta2-1||eta1==eta2+1) && - (phi1==(phi2+1) || phi1==(phi2-1) || - (phi1==1&&phi2==16) || (phi1==16&&phi2==1) ) ) { - return overlapMatch(seg1,seg2); - }else return false; - } - } - if( !m_doStraightLineMatch ) return true; - - if( stIndex1 == stIndex2 ) return false; - - return straightLineMatch(seg1,seg2); + if (isSLMatch(chid1, chid2)) { + if (!m_idHelperSvc->isMdt(chid1) || !m_idHelperSvc->isMdt(chid2)) return false; + // if there is a stereo angle match using overlap matching tool + + if (stIndex1 == stIndex2) { + + if (hasStereoAngle(chid1, chid2)) { + if (!m_doOverlapMatch) return true; + int eta1 = m_idHelperSvc->mdtIdHelper().stationEta(chid1); + int eta2 = m_idHelperSvc->mdtIdHelper().stationEta(chid2); + int phi1 = m_idHelperSvc->sector(chid1); + int phi2 = m_idHelperSvc->sector(chid2); + + // require that the two segments are close in eta AND are in adjecent sectors + if ((eta1 == eta2 || eta1 == eta2 - 1 || eta1 == eta2 + 1) + && (phi1 == (phi2 + 1) || phi1 == (phi2 - 1) || (phi1 == 1 && phi2 == 16) + || (phi1 == 16 && phi2 == 1))) + { + return overlapMatch(seg1, seg2); + } else + return false; + } + } + if (!m_doStraightLineMatch) return true; + + if (stIndex1 == stIndex2) return false; + + return straightLineMatch(seg1, seg2); } - + // if we get here perform a curved matching - if( !m_doCurvedMatch ) return true; - if( stIndex1 == stIndex2 ) return false; - - return curvedMatch(seg1,seg2); + if (!m_doCurvedMatch) return true; + if (stIndex1 == stIndex2) return false; - } + return curvedMatch(seg1, seg2); +} - bool MuonSegmentMatchingTool::straightLineMatch( const MuonSegment& seg1, const MuonSegment& seg2 ) const { +bool +MuonSegmentMatchingTool::straightLineMatch(const MuonSegment& seg1, const MuonSegment& seg2) const +{ ++m_straightLineMatches; ATH_MSG_VERBOSE(" straight line match "); - + // Suppress cavern background noise and combinatorics using both theta and phi matching - if ( m_thetaMatch ) - if( !suppressNoise(seg1, seg2, m_useTightCuts ) ) { - return false; - } + if (m_thetaMatch) + if (!suppressNoise(seg1, seg2, m_useTightCuts)) { + return false; + } // Suppress cavern background noise and combinatorics using phi matching - if ( m_phiMatch ){ - if( !suppressNoisePhi(seg1, seg2, m_useTightCuts ) ) return false; + if (m_phiMatch) { + if (!suppressNoisePhi(seg1, seg2, m_useTightCuts)) return false; } - + ++m_straightLineMatchesGood; return true; - } +} - bool MuonSegmentMatchingTool::curvedMatch( const MuonSegment& seg1, const MuonSegment& seg2 ) const { +bool +MuonSegmentMatchingTool::curvedMatch(const MuonSegment& seg1, const MuonSegment& seg2) const +{ ++m_curvedMatches; ATH_MSG_VERBOSE(" curved match "); // Suppress cavern background noise and combinatorics using both theta and phi matching - if ( m_thetaMatch ) - if( !suppressNoise(seg1, seg2, m_useTightCuts ) ) { - return false; - } + if (m_thetaMatch) + if (!suppressNoise(seg1, seg2, m_useTightCuts)) { + return false; + } // Suppress cavern background noise and combinatorics using phi matching - if ( m_phiMatch ){ - if( !suppressNoisePhi(seg1, seg2, m_useTightCuts ) ) return false; + if (m_phiMatch) { + if (!suppressNoisePhi(seg1, seg2, m_useTightCuts)) return false; } ++m_curvedMatchesGood; return true; - } +} - bool MuonSegmentMatchingTool::overlapMatch( const MuonSegment& seg1, const MuonSegment& seg2 ) const { +bool +MuonSegmentMatchingTool::overlapMatch(const MuonSegment& seg1, const MuonSegment& seg2) const +{ ++m_overlapMatches; - + ATH_MSG_VERBOSE(" overlap match "); Identifier chid = m_edmHelperSvc->chamberId(seg1); // check the distance between the two segments float segDist = (seg1.globalPosition() - seg2.globalPosition()).mag(); - ATH_MSG_VERBOSE(" Distance between segments " << segDist ); - if(m_isCosmics && segDist > m_minDistSegmentsCosmics) { - ATH_MSG_DEBUG(" Too far appart, accepting "); - return true; + ATH_MSG_VERBOSE(" Distance between segments " << segDist); + if (m_isCosmics && segDist > m_minDistSegmentsCosmics) { + ATH_MSG_DEBUG(" Too far appart, accepting "); + return true; } if (segDist > m_maxDistSegments) return false; - if( !m_idHelperSvc->isMdt(chid) ) { - ATH_MSG_DEBUG(" not a mdt segment " << m_idHelperSvc->toString(chid)); - return true; + if (!m_idHelperSvc->isMdt(chid)) { + ATH_MSG_DEBUG(" not a mdt segment " << m_idHelperSvc->toString(chid)); + return true; } - IMuonSegmentInOverlapResolvingTool::SegmentMatchResult result = m_overlapResolvingTool->matchResult(seg1,seg2); - + IMuonSegmentInOverlapResolvingTool::SegmentMatchResult result = m_overlapResolvingTool->matchResult(seg1, seg2); + ATH_MSG_VERBOSE(result.toString()); - if( !result.goodMatch() ){ - ATH_MSG_DEBUG(" bad match "); - return false; + if (!result.goodMatch()) { + ATH_MSG_DEBUG(" bad match "); + return false; } - - result.phiResult = m_overlapResolvingTool->bestPhiMatch(seg1,seg2); - if( fabs(result.angularDifferencePhi) > m_overlapMatchAngleDPhiCut || fabs(result.phiResult.deltaYZ) > m_overlapMatchAngleDYZCut ) { - ATH_MSG_DEBUG(" failed angle cut: diff phi " << result.angularDifferencePhi - << " deltaYZ " << result.phiResult.deltaYZ); - return false; + + result.phiResult = m_overlapResolvingTool->bestPhiMatch(seg1, seg2); + if (fabs(result.angularDifferencePhi) > m_overlapMatchAngleDPhiCut + || fabs(result.phiResult.deltaYZ) > m_overlapMatchAngleDYZCut) + { + ATH_MSG_DEBUG(" failed angle cut: diff phi " << result.angularDifferencePhi << " deltaYZ " + << result.phiResult.deltaYZ); + return false; } - if( fabs(result.averagePhiHitPullSegment1) > m_overlapMatchPhiHitPullCut || fabs(result.averagePhiHitPullSegment2) > m_overlapMatchPhiHitPullCut ) { - ATH_MSG_DEBUG(" failed phi hit pull cut: seg1 " << result.averagePhiHitPullSegment1 - << " seg2 " << result.averagePhiHitPullSegment2); - return false; + if (fabs(result.averagePhiHitPullSegment1) > m_overlapMatchPhiHitPullCut + || fabs(result.averagePhiHitPullSegment2) > m_overlapMatchPhiHitPullCut) + { + ATH_MSG_DEBUG(" failed phi hit pull cut: seg1 " << result.averagePhiHitPullSegment1 << " seg2 " + << result.averagePhiHitPullSegment2); + return false; } - if( !result.segmentResult1.inBounds(m_overlapMatchPositionCut) || !result.segmentResult2.inBounds(m_overlapMatchPositionCut) ){ - ATH_MSG_DEBUG(" failed position cut "); - return false; + if (!result.segmentResult1.inBounds(m_overlapMatchPositionCut) + || !result.segmentResult2.inBounds(m_overlapMatchPositionCut)) + { + ATH_MSG_DEBUG(" failed position cut "); + return false; } - if( fabs(result.segmentResult1.positionResidual) > m_overlapMatchPositionResidualCut || - fabs(result.segmentResult2.positionResidual) > m_overlapMatchPositionResidualCut ){ - ATH_MSG_DEBUG(" failed position residual cut: seg1 " << result.segmentResult1.positionResidual - << " seg2 " << result.segmentResult2.positionResidual); - return false; + if (fabs(result.segmentResult1.positionResidual) > m_overlapMatchPositionResidualCut + || fabs(result.segmentResult2.positionResidual) > m_overlapMatchPositionResidualCut) + { + ATH_MSG_DEBUG(" failed position residual cut: seg1 " << result.segmentResult1.positionResidual << " seg2 " + << result.segmentResult2.positionResidual); + return false; } ++m_overlapMatchesGood; return true; - } +} + +bool +MuonSegmentMatchingTool::isSLMatch(const Identifier& chid1, const Identifier& chid2) const +{ - bool MuonSegmentMatchingTool::isSLMatch( const Identifier& chid1, const Identifier& chid2 ) const { - // check whether there is field - if(!m_toroidOn) return true; + if (!m_toroidOn) return true; MuonStationIndex::StIndex stIndex1 = m_idHelperSvc->stationIndex(chid1); MuonStationIndex::StIndex stIndex2 = m_idHelperSvc->stationIndex(chid2); - + // check whether segments in same station - if( stIndex1 == stIndex2 ) return true; + if (stIndex1 == stIndex2) return true; // check whether segments in endcap EM/EO region - if( (stIndex1==MuonStationIndex::EO && stIndex2==MuonStationIndex::EM) || - (stIndex1==MuonStationIndex::EM && stIndex2==MuonStationIndex::EO) ) return true; - + if ((stIndex1 == MuonStationIndex::EO && stIndex2 == MuonStationIndex::EM) + || (stIndex1 == MuonStationIndex::EM && stIndex2 == MuonStationIndex::EO)) + return true; + // all other cases should be treated with curvature return false; - } +} + +bool +MuonSegmentMatchingTool::hasStereoAngle(const Identifier& id1, const Identifier& id2) const +{ - bool MuonSegmentMatchingTool::hasStereoAngle( const Identifier& id1, const Identifier& id2 ) const { - // check whether same phi, else stereo angle (need correction for cosmic up-down tracks) int phi1 = m_idHelperSvc->mdtIdHelper().stationPhi(id1); - int phi2 = m_idHelperSvc->mdtIdHelper().stationPhi(id2); - - if( phi1!=phi2) return true; - - // check whether there is a small/large overlap + int phi2 = m_idHelperSvc->mdtIdHelper().stationPhi(id2); + + if (phi1 != phi2) return true; + + // check whether there is a small/large overlap bool isSmallChamber1 = m_idHelperSvc->isSmallChamber(id1); bool isSmallChamber2 = m_idHelperSvc->isSmallChamber(id2); return isSmallChamber1 != isSmallChamber2; - } +} - // DOMINIQUE: - // Check that segment pairs is compatible with being produce within the calorimeter volume - // Keep it loose to retain long live particles decaying in calo - bool MuonSegmentMatchingTool::suppressNoise( const MuonSegment& seg1, const MuonSegment& seg2, const bool& useTightCuts ) const { +// DOMINIQUE: +// Check that segment pairs is compatible with being produce within the calorimeter volume +// Keep it loose to retain long live particles decaying in calo +bool +MuonSegmentMatchingTool::suppressNoise(const MuonSegment& seg1, const MuonSegment& seg2, const bool& useTightCuts) const +{ // calculate matching variables - IMuonSegmentPairMatchingTool::SegmentMatchResult result = m_pairMatchingTool->matchResult(seg1,seg2); - - MuonStationIndex::StIndex station_a = m_idHelperSvc->stationIndex( result.chid_a ); - MuonStationIndex::StIndex station_b = m_idHelperSvc->stationIndex( result.chid_b ); - - bool isEndcap_a = m_idHelperSvc->isEndcap( result.chid_a ); - bool isCSC_a = m_idHelperSvc->isCsc( result.chid_a ); - bool isBEE_a = station_a == MuonStationIndex::BE; - - bool isEndcap_b = m_idHelperSvc->isEndcap( result.chid_b ); - bool isCSC_b = m_idHelperSvc->isCsc( result.chid_b ); - bool isBEE_b = station_a == MuonStationIndex::BE; - - - if ( m_dumpAngles ) { - - std::cout << "SegmentPositionChange " - << " " << m_idHelperSvc->chamberNameString(result.chid_a) - << " " << m_idHelperSvc->chamberNameString(result.chid_b) - << " " << result.phiSector_a - << " " << result.phiSector_b - << " " << result.deltaTheta_a - << " " << result.deltaTheta_b - << " " << result.deltaTheta - << " " << result.angleAC - << " " << result.angleBC - << " " << result.angleAB - << std::endl; -// return true; // to get the maximum statistics and not be hindered by current cuts - } - - ATH_MSG_VERBOSE( "matching " << m_idHelperSvc->chamberNameString(result.chid_a) - << " " << m_idHelperSvc->chamberNameString(result.chid_b) - << " phis " << result.phiSector_a - << " " << result.phiSector_b - << " thetas " << result.deltaTheta_a - << " " << result.deltaTheta_b - << " thetaSum " << result.deltaTheta - << " tight cuts " << useTightCuts ); - + IMuonSegmentPairMatchingTool::SegmentMatchResult result = m_pairMatchingTool->matchResult(seg1, seg2); + + MuonStationIndex::StIndex station_a = m_idHelperSvc->stationIndex(result.chid_a); + MuonStationIndex::StIndex station_b = m_idHelperSvc->stationIndex(result.chid_b); + + bool isEndcap_a = m_idHelperSvc->isEndcap(result.chid_a); + bool isCSC_a = m_idHelperSvc->isCsc(result.chid_a); + bool isBEE_a = station_a == MuonStationIndex::BE; + + bool isEndcap_b = m_idHelperSvc->isEndcap(result.chid_b); + bool isCSC_b = m_idHelperSvc->isCsc(result.chid_b); + bool isBEE_b = station_a == MuonStationIndex::BE; + + + if (m_dumpAngles) { + + std::cout << "SegmentPositionChange " + << " " << m_idHelperSvc->chamberNameString(result.chid_a) << " " + << m_idHelperSvc->chamberNameString(result.chid_b) << " " << result.phiSector_a << " " + << result.phiSector_b << " " << result.deltaTheta_a << " " << result.deltaTheta_b << " " + << result.deltaTheta << " " << result.angleAC << " " << result.angleBC << " " << result.angleAB + << std::endl; + // return true; // to get the maximum statistics and not be hindered by current cuts + } + + ATH_MSG_VERBOSE("matching " << m_idHelperSvc->chamberNameString(result.chid_a) << " " + << m_idHelperSvc->chamberNameString(result.chid_b) << " phis " << result.phiSector_a + << " " << result.phiSector_b << " thetas " << result.deltaTheta_a << " " + << result.deltaTheta_b << " thetaSum " << result.deltaTheta << " tight cuts " + << useTightCuts); + // The difference between the segment direction in the inner and outer stations ~< 60 degrees in all cases - if ( result.angleAB > 1.0 ) return false; + if (result.angleAB > 1.0) return false; + - // First: loose selection - if ( !useTightCuts ) { - if ( isCSC_a || isCSC_b ) { - ATH_MSG_VERBOSE( " check CSC result "); - if ( result.phiSector_a != result.phiSector_b ) { - return false; + if (!useTightCuts) { + if (isCSC_a || isCSC_b) { + ATH_MSG_VERBOSE(" check CSC result "); + if (result.phiSector_a != result.phiSector_b) { + return false; + } + if ((isCSC_a && !isEndcap_b) || (isCSC_b && !isEndcap_a)) return false; + return endcapExtrapolationMatch(seg1, seg2, useTightCuts); + } + // BEE + else if (isBEE_a || isBEE_b) + { + ATH_MSG_VERBOSE(" check BEE result "); + if (result.deltaTheta > 0.300) { + return false; + } else { + return true; + } + } + // Barrel/endcap overlap + else if (isEndcap_a != isEndcap_b) + { + ATH_MSG_VERBOSE(" check B-E result "); + if (result.deltaTheta > 0.300) { + return false; + } else { + return true; + } + } + // Phi-sector overlap + else if (result.phiSector_a != result.phiSector_b) + { + ATH_MSG_VERBOSE(" check phiSector result "); + if (result.deltaTheta > 0.300) { + ATH_MSG_VERBOSE(" check phiSector reject "); + return false; + } else { + return true; + } + } + // Barrel inner to middle station + else if (station_a == MuonStationIndex::BI && station_b == MuonStationIndex::BM) + { + ATH_MSG_VERBOSE(" check BI BM result "); + if (result.phiSector_a % 2 == 0) { + if (result.deltaTheta > 6.67 * m_matchingbibm_sphisec) { + return false; + } else { + return true; + } + } else if (result.phiSector_a % 2 == 1) { + if (result.deltaTheta > 6.67 * m_matchingbibm_lphisec) { + return false; + } else { + return true; + } + } + } + // Barrel inner to outer station + else if (station_a == MuonStationIndex::BI && station_b == MuonStationIndex::BO) + { + ATH_MSG_VERBOSE(" check BI BO result "); + if (result.phiSector_a % 2 == 0) { + if (result.deltaTheta > 6.67 * m_matchingbibo_sphisec) { + return false; + } else { + return true; + } + } else if (result.phiSector_a % 2 == 1) { + if (result.deltaTheta > 6.67 * m_matchingbibo_lphisec) { + return false; + } else { + return true; + } + } + } + + // Barrel middle to outer station + else if (station_a == MuonStationIndex::BM && station_b == MuonStationIndex::BO) + { + ATH_MSG_VERBOSE(" check BM BO result "); + if (result.phiSector_a % 2 == 0) { + if (result.deltaTheta > 6.67 * m_matchingbmbo_sphisec) { + return false; + } else { + return true; + } + } else if (result.phiSector_a % 2 == 1) { + if (result.deltaTheta > 6.67 * m_matchingbmbo_lphisec) { + return false; + } else { + return true; + } + } } - if( (isCSC_a && !isEndcap_b) || (isCSC_b && !isEndcap_a) ) return false; - return endcapExtrapolationMatch(seg1,seg2,useTightCuts); - } - // BEE - else if ( isBEE_a || isBEE_b ) { - ATH_MSG_VERBOSE( " check BEE result "); - if ( result.deltaTheta > 0.300 ) { - return false; - } else { - return true; - } - } - // Barrel/endcap overlap - else if ( isEndcap_a != isEndcap_b ) { - ATH_MSG_VERBOSE( " check B-E result "); - if ( result.deltaTheta > 0.300 ) { - return false; - } else { - return true; - } - } - // Phi-sector overlap - else if ( result.phiSector_a != result.phiSector_b ) { - ATH_MSG_VERBOSE( " check phiSector result "); - if ( result.deltaTheta > 0.300 ) { - ATH_MSG_VERBOSE( " check phiSector reject "); - return false; - } else { - return true; - } - } - // Barrel inner to middle station - else if ( station_a == MuonStationIndex::BI && - station_b == MuonStationIndex::BM ) { - ATH_MSG_VERBOSE( " check BI BM result "); - if ( result.phiSector_a%2==0) { - if ( result.deltaTheta > 6.67*m_matchingbibm_sphisec ) { - return false; - } else { - return true; - } - } - else if ( result.phiSector_a%2==1) { - if ( result.deltaTheta > 6.67*m_matchingbibm_lphisec ) { - return false; - } else { - return true; - } - } - } - // Barrel inner to outer station - else if ( station_a == MuonStationIndex::BI && - station_b == MuonStationIndex::BO ) { - ATH_MSG_VERBOSE( " check BI BO result "); - if ( result.phiSector_a%2==0) { - if ( result.deltaTheta > 6.67*m_matchingbibo_sphisec ) { - return false; - } else { - return true; - } - } - else if ( result.phiSector_a%2==1) { - if ( result.deltaTheta > 6.67*m_matchingbibo_lphisec ) { - return false; - } else { - return true; - } - } - } - - // Barrel middle to outer station - else if ( station_a == MuonStationIndex::BM && station_b == MuonStationIndex::BO ) { - ATH_MSG_VERBOSE( " check BM BO result "); - if ( result.phiSector_a%2==0) { - if ( result.deltaTheta > 6.67*m_matchingbmbo_sphisec ) { - return false; - } else { - return true; - } - } - else if ( result.phiSector_a%2==1) { - if ( result.deltaTheta > 6.67*m_matchingbmbo_lphisec ) { - return false; - } else { - return true; - } - } - } - // Endcap inner to middle station - else if ( station_a == MuonStationIndex::EI && - (station_b == MuonStationIndex::EM ) ) { - ATH_MSG_VERBOSE( " check EI EM result "); - if ( result.phiSector_a%2==0) { - if ( result.deltaTheta > 6.67*m_matchingeiem_sphisec ) { - ATH_MSG_VERBOSE( " reject EI EM S result "); - return false; - } else { - return endcapExtrapolationMatch(seg1,seg2,useTightCuts); - } - } - else if ( result.phiSector_a%2==1) { - if ( result.deltaTheta > 6.67*m_matchingeiem_lphisec ) { - ATH_MSG_VERBOSE( " reject EI EM L result "); - return false; - } else { - return endcapExtrapolationMatch(seg1,seg2,useTightCuts); - } - } - } - // Endcap inner to outer station - else if ( station_a == MuonStationIndex::EI && - (station_b == MuonStationIndex::EO) ) { - ATH_MSG_VERBOSE( " check EI EO result "); - if ( result.phiSector_a%2==0) { - if ( result.deltaTheta > 6.67*m_matchingeieo_sphisec ) { - ATH_MSG_VERBOSE( " reject EI EO S result "); - return false; - } else { - return endcapExtrapolationMatch(seg1,seg2,useTightCuts); - } - } - else if ( result.phiSector_a%2==1) { - if ( result.deltaTheta > 6.67*m_matchingeieo_lphisec ) { - ATH_MSG_VERBOSE( " reject EI EO L result "); - return false; - } else { - return endcapExtrapolationMatch(seg1,seg2,useTightCuts); - } - } - } - // Endcap middle to outer station - else if ( station_a == MuonStationIndex::EM && station_b == MuonStationIndex::EO ) { - // 5 mrad - ATH_MSG_VERBOSE( " check EM EO result "); - if ( result.phiSector_a%2==0) { - if ( result.deltaTheta > 6.67*m_matchingemeo_sphisec ) { - return false; - } else { - return true; - } - } - else if ( result.phiSector_a%2==1) { - if ( result.deltaTheta > 6.67*m_matchingemeo_lphisec ) { - return false; - } else { - return true; - } - } - } - - return true; + // Endcap inner to middle station + else if (station_a == MuonStationIndex::EI && (station_b == MuonStationIndex::EM)) + { + ATH_MSG_VERBOSE(" check EI EM result "); + if (result.phiSector_a % 2 == 0) { + if (result.deltaTheta > 6.67 * m_matchingeiem_sphisec) { + ATH_MSG_VERBOSE(" reject EI EM S result "); + return false; + } else { + return endcapExtrapolationMatch(seg1, seg2, useTightCuts); + } + } else if (result.phiSector_a % 2 == 1) { + if (result.deltaTheta > 6.67 * m_matchingeiem_lphisec) { + ATH_MSG_VERBOSE(" reject EI EM L result "); + return false; + } else { + return endcapExtrapolationMatch(seg1, seg2, useTightCuts); + } + } + } + // Endcap inner to outer station + else if (station_a == MuonStationIndex::EI && (station_b == MuonStationIndex::EO)) + { + ATH_MSG_VERBOSE(" check EI EO result "); + if (result.phiSector_a % 2 == 0) { + if (result.deltaTheta > 6.67 * m_matchingeieo_sphisec) { + ATH_MSG_VERBOSE(" reject EI EO S result "); + return false; + } else { + return endcapExtrapolationMatch(seg1, seg2, useTightCuts); + } + } else if (result.phiSector_a % 2 == 1) { + if (result.deltaTheta > 6.67 * m_matchingeieo_lphisec) { + ATH_MSG_VERBOSE(" reject EI EO L result "); + return false; + } else { + return endcapExtrapolationMatch(seg1, seg2, useTightCuts); + } + } + } + // Endcap middle to outer station + else if (station_a == MuonStationIndex::EM && station_b == MuonStationIndex::EO) + { + // 5 mrad + ATH_MSG_VERBOSE(" check EM EO result "); + if (result.phiSector_a % 2 == 0) { + if (result.deltaTheta > 6.67 * m_matchingemeo_sphisec) { + return false; + } else { + return true; + } + } else if (result.phiSector_a % 2 == 1) { + if (result.deltaTheta > 6.67 * m_matchingemeo_lphisec) { + return false; + } else { + return true; + } + } + } + + return true; } - - ATH_MSG_VERBOSE( " check further matching result "); + + ATH_MSG_VERBOSE(" check further matching result "); // Second: tight selection if only if requested - if( m_onlySameSectorIfTight && result.phiSector_a != result.phiSector_b ){ - ATH_MSG_VERBOSE(" rejection pair as in different sector and using tight cuts"); - return false; + if (m_onlySameSectorIfTight && result.phiSector_a != result.phiSector_b) { + ATH_MSG_VERBOSE(" rejection pair as in different sector and using tight cuts"); + return false; } - if ( isCSC_a || isCSC_b ) { - if ( result.phiSector_a != result.phiSector_b ) { - return false; - } else { - if ( result.deltaTheta > 0.100 ) { - return false; + if (isCSC_a || isCSC_b) { + if (result.phiSector_a != result.phiSector_b) { + return false; } else { - if( (isCSC_a && !isEndcap_b) || (isCSC_b && !isEndcap_a) ) return false; - return endcapExtrapolationMatch(seg1,seg2,useTightCuts); + if (result.deltaTheta > 0.100) { + return false; + } else { + if ((isCSC_a && !isEndcap_b) || (isCSC_b && !isEndcap_a)) return false; + return endcapExtrapolationMatch(seg1, seg2, useTightCuts); + } } - } - + } // BEE - else if ( isBEE_a || isBEE_b ) { - if ( result.deltaTheta > 0.200 ) { - return false; - } else { - return true; - } + else if (isBEE_a || isBEE_b) + { + if (result.deltaTheta > 0.200) { + return false; + } else { + return true; + } } // Looser cut for segment in two different phi sectors - else if ( result.phiSector_a != result.phiSector_b ) { - if ( result.deltaTheta > 0.150 ) { - return false; - } - return true; + else if (result.phiSector_a != result.phiSector_b) + { + if (result.deltaTheta > 0.150) { + return false; + } + return true; } - // Barrel/endcap overlap - else if ( isEndcap_a != isEndcap_b ) { - if ( result.deltaTheta > 0.150 ) { - return false; - } else { - return true; - } + // Barrel/endcap overlap + else if (isEndcap_a != isEndcap_b) + { + if (result.deltaTheta > 0.150) { + return false; + } else { + return true; + } } - // Phi-sector overlap - else if ( result.phiSector_a != result.phiSector_b ) { - unsigned nChambers_a = m_edmHelperSvc->chamberIds(seg1).size(); - unsigned nChambers_b = m_edmHelperSvc->chamberIds(seg2).size(); - if ( nChambers_a < 2 && nChambers_b < 2 ) { - return false; - } - else if ( result.deltaTheta > 0.150 ) { - return false; - } else { - return true; - } + // Phi-sector overlap + else if (result.phiSector_a != result.phiSector_b) + { + unsigned nChambers_a = m_edmHelperSvc->chamberIds(seg1).size(); + unsigned nChambers_b = m_edmHelperSvc->chamberIds(seg2).size(); + if (nChambers_a < 2 && nChambers_b < 2) { + return false; + } else if (result.deltaTheta > 0.150) { + return false; + } else { + return true; + } } - // Barrel inner to middle station - else if ( station_a == MuonStationIndex::BI && - station_b == MuonStationIndex::BM ) { - if ( result.phiSector_a%2==0 ){ - if ( result.deltaTheta > m_matchingbibm_sphisec ) { - return false; - } else { - return true; - } - } - else if ( result.phiSector_a%2==1 ){ - if ( result.deltaTheta > m_matchingbibm_lphisec ) { - return false; - } else { - return true; - } - } + // Barrel inner to middle station + else if (station_a == MuonStationIndex::BI && station_b == MuonStationIndex::BM) + { + if (result.phiSector_a % 2 == 0) { + if (result.deltaTheta > m_matchingbibm_sphisec) { + return false; + } else { + return true; + } + } else if (result.phiSector_a % 2 == 1) { + if (result.deltaTheta > m_matchingbibm_lphisec) { + return false; + } else { + return true; + } + } } - // Barrel inner to outer station - else if ( station_a == MuonStationIndex::BI && - station_b == MuonStationIndex::BO ) { - if ( result.phiSector_a%2==0 ){ - if ( result.deltaTheta > m_matchingbibo_sphisec ) { - return false; - } else { - return true; - } - } - else if ( result.phiSector_a%2==1 ){ - if ( result.deltaTheta > m_matchingbibo_lphisec ) { - return false; - } else { - return true; - } - } + // Barrel inner to outer station + else if (station_a == MuonStationIndex::BI && station_b == MuonStationIndex::BO) + { + if (result.phiSector_a % 2 == 0) { + if (result.deltaTheta > m_matchingbibo_sphisec) { + return false; + } else { + return true; + } + } else if (result.phiSector_a % 2 == 1) { + if (result.deltaTheta > m_matchingbibo_lphisec) { + return false; + } else { + return true; + } + } } - // Barrel middle to outer station - else if ( station_a == MuonStationIndex::BM && station_b == MuonStationIndex::BO ) { - if( result.phiSector_a%2==0){ - if ( result.deltaTheta > m_matchingbmbo_sphisec ) { - return false; - } else { - return true; - } - } - else if( result.phiSector_a%2==1){ - if ( result.deltaTheta > m_matchingbmbo_lphisec ) { - return false; - } else { - return true; - } - } + // Barrel middle to outer station + else if (station_a == MuonStationIndex::BM && station_b == MuonStationIndex::BO) + { + if (result.phiSector_a % 2 == 0) { + if (result.deltaTheta > m_matchingbmbo_sphisec) { + return false; + } else { + return true; + } + } else if (result.phiSector_a % 2 == 1) { + if (result.deltaTheta > m_matchingbmbo_lphisec) { + return false; + } else { + return true; + } + } } - // Endcap inner to middle station - else if ( (station_a == MuonStationIndex::EI||station_a == MuonStationIndex::BI) && station_b == MuonStationIndex::EM ) { - if( result.phiSector_a%2==0){ - if ( result.deltaTheta > m_matchingeiem_sphisec ) { - return false; - } else { - return endcapExtrapolationMatch(seg1,seg2,useTightCuts); - } - } - else if( result.phiSector_a%2==1){ - if ( result.deltaTheta > m_matchingeiem_lphisec ) { - return false; - } else { - return endcapExtrapolationMatch(seg1,seg2,useTightCuts); - } - } + // Endcap inner to middle station + else if ((station_a == MuonStationIndex::EI || station_a == MuonStationIndex::BI) + && station_b == MuonStationIndex::EM) + { + if (result.phiSector_a % 2 == 0) { + if (result.deltaTheta > m_matchingeiem_sphisec) { + return false; + } else { + return endcapExtrapolationMatch(seg1, seg2, useTightCuts); + } + } else if (result.phiSector_a % 2 == 1) { + if (result.deltaTheta > m_matchingeiem_lphisec) { + return false; + } else { + return endcapExtrapolationMatch(seg1, seg2, useTightCuts); + } + } } - // Endcap inner to outer station - else if ( station_a == MuonStationIndex::EI && - (station_b == MuonStationIndex::EO) ) { - if( result.phiSector_a%2==0){ - if ( result.deltaTheta > m_matchingeieo_sphisec ) { - return false; - } else { - return endcapExtrapolationMatch(seg1,seg2,useTightCuts); - } - } - else if( result.phiSector_a%2==1){ - if ( result.deltaTheta > m_matchingeieo_lphisec ) { - return false; - } else { - return endcapExtrapolationMatch(seg1,seg2,useTightCuts); - } - } + // Endcap inner to outer station + else if (station_a == MuonStationIndex::EI && (station_b == MuonStationIndex::EO)) + { + if (result.phiSector_a % 2 == 0) { + if (result.deltaTheta > m_matchingeieo_sphisec) { + return false; + } else { + return endcapExtrapolationMatch(seg1, seg2, useTightCuts); + } + } else if (result.phiSector_a % 2 == 1) { + if (result.deltaTheta > m_matchingeieo_lphisec) { + return false; + } else { + return endcapExtrapolationMatch(seg1, seg2, useTightCuts); + } + } } - // Endcap middle to outer station - else if ( station_a == MuonStationIndex::EM && station_b == MuonStationIndex::EO ) { - if( result.phiSector_a%2==0){ - if ( result.deltaTheta > m_matchingemeo_sphisec ) { - return false; - } else { - return true; - } - } - else if( result.phiSector_a%2==1){ - if ( result.deltaTheta > m_matchingemeo_lphisec ) { - return false; - } else { - return true; - } - } + // Endcap middle to outer station + else if (station_a == MuonStationIndex::EM && station_b == MuonStationIndex::EO) + { + if (result.phiSector_a % 2 == 0) { + if (result.deltaTheta > m_matchingemeo_sphisec) { + return false; + } else { + return true; + } + } else if (result.phiSector_a % 2 == 1) { + if (result.deltaTheta > m_matchingemeo_lphisec) { + return false; + } else { + return true; + } + } } - + return true; - } // if m_useLocalAngles +} // if m_useLocalAngles - bool MuonSegmentMatchingTool::suppressNoisePhi( const MuonSegment& seg1, const MuonSegment& seg2, const bool& useTightCuts ) const { +bool +MuonSegmentMatchingTool::suppressNoisePhi(const MuonSegment& seg1, const MuonSegment& seg2, + const bool& useTightCuts) const +{ // calculate matching variables - IMuonSegmentPairMatchingTool::SegmentMatchResult result = m_pairMatchingTool->matchResult(seg1,seg2); - - MuonStationIndex::StIndex station_a = m_idHelperSvc->stationIndex( result.chid_a ); - MuonStationIndex::StIndex station_b = m_idHelperSvc->stationIndex( result.chid_b ); - - bool isEndcap_a = m_idHelperSvc->isEndcap( result.chid_a ); - - bool isEndcap_b = m_idHelperSvc->isEndcap( result.chid_b ); - - if ( m_dumpAngles ) { - std::cout << "SegmentPositionChange Phi" - << " " << m_idHelperSvc->chamberNameString(result.chid_a) - << " " << m_idHelperSvc->chamberNameString(result.chid_b) - << " deltaPhipos " << result.deltaPhipos - << " deltaPhidir " << result.deltaPhidir - << " phiposerr_a " << result.phiposerr_a - << " phiposerr_b " << result.phiposerr_b - << " phidirerr_a " << result.phidirerr_a - << " phidirerr_b " << result.phidirerr_b - << " shorttube_a " << result.shorttube_a - << " shorttube_b " << result.shorttube_b - << std::endl; -// return true; // to get the maximum statistics and not be hindered by current cuts - } - - //Keep segments only if they are in the same or adjacent phi sectors - if (result.phiSector_a != result.phiSector_b && ((result.phiSector_a!=16 && result.phiSector_b!=1) && (result.phiSector_a!=1 && result.phiSector_b!=16)) && (result.phiSector_a != (result.phiSector_b+1) && result.phiSector_a != (result.phiSector_b-1))) return false; - + IMuonSegmentPairMatchingTool::SegmentMatchResult result = m_pairMatchingTool->matchResult(seg1, seg2); + + MuonStationIndex::StIndex station_a = m_idHelperSvc->stationIndex(result.chid_a); + MuonStationIndex::StIndex station_b = m_idHelperSvc->stationIndex(result.chid_b); + + bool isEndcap_a = m_idHelperSvc->isEndcap(result.chid_a); + + bool isEndcap_b = m_idHelperSvc->isEndcap(result.chid_b); + + if (m_dumpAngles) { + std::cout << "SegmentPositionChange Phi" + << " " << m_idHelperSvc->chamberNameString(result.chid_a) << " " + << m_idHelperSvc->chamberNameString(result.chid_b) << " deltaPhipos " << result.deltaPhipos + << " deltaPhidir " << result.deltaPhidir << " phiposerr_a " << result.phiposerr_a << " phiposerr_b " + << result.phiposerr_b << " phidirerr_a " << result.phidirerr_a << " phidirerr_b " + << result.phidirerr_b << " shorttube_a " << result.shorttube_a << " shorttube_b " + << result.shorttube_b << std::endl; + // return true; // to get the maximum statistics and not be hindered by current cuts + } + + // Keep segments only if they are in the same or adjacent phi sectors + if (result.phiSector_a != result.phiSector_b + && ((result.phiSector_a != 16 && result.phiSector_b != 1) + && (result.phiSector_a != 1 && result.phiSector_b != 16)) + && (result.phiSector_a != (result.phiSector_b + 1) && result.phiSector_a != (result.phiSector_b - 1))) + return false; + // First: loose selection - if ( !useTightCuts ) { - //cuts on second coordinate - if(result.phiSector_a==result.phiSector_b){ - if(result.phiposerr_a < 10001.000 && result.phiposerr_b < 10001.000){ - - if( !isEndcap_a && !isEndcap_b){ - if( result.deltaPhipos > 0.1 ){ - return false; - } - else { - return true; - } - } - if( isEndcap_a && isEndcap_b){ - //small sectors - if( result.phiSector_a%2==0 ) { - if( result.deltaPhipos > 0.1 ){ - return false; - } - else { - return true; - } - } - //large sectors - if (result.phiSector_a%2==1) { - if( result.deltaPhipos > 0.2 ){ - return false; - } - else { - return true; - } - } - } - } -// if(result.phidirerr_a < 10001.000 && result.phidirerr_b < 10001.000){ -// if( !isEndcap_a && !isEndcap_b){ -// if( result.deltaPhidir > 0.2 ){ -// return false; -// } -// else { -// return true; -// } -// } -// if( isEndcap_a && isEndcap_b){ -// return true; -// } -// } - } - - if(result.phiSector_a!=result.phiSector_b){ - if(result.phiposerr_a < 10001.000 && result.phiposerr_b < 10001.000){ - if( !isEndcap_a && !isEndcap_b){ - if( result.deltaPhipos > 0.1 ){ - return false; - } - else { - return true; - } - } - if( isEndcap_a && isEndcap_b){ - if( result.deltaPhipos > 0.2 ){ - return false; - } - else { - return true; - } - } - } -// if(result.phidirerr_a < 10001.000 && result.phidirerr_b < 10001.000){ -// if( !isEndcap_a && !isEndcap_b){ -// if( result.deltaPhidir > 0.2 ){ -// return false; -// } -// else { -// return true; -// } -// } -// if( isEndcap_a && isEndcap_b){ -// return true; -// } -// } - } - - //cuts on distance to tube edge - //only if in a different phi sector - if(result.phiSector_a!=result.phiSector_b){ - //measured inner segment - if(result.phiposerr_a < 10001.000){ - if ( station_a == MuonStationIndex::BM && - station_b == MuonStationIndex::BO ) { - if(result.shorttube_a > 800){ - return false; - } else { - return true; - } - } - if ( station_a == MuonStationIndex::EI && - station_b == MuonStationIndex::EM ) { -// MM or STGC have result.shorttube = 99999. - if(result.shorttube_a > 3500 && result.shorttube_a != 99999.){ - return false; - } else { - return true; - } - } - if ( station_a == MuonStationIndex::EI && - station_b == MuonStationIndex::EO ) { - if(result.shorttube_a > 3500 && result.shorttube_a != 99999.){ - return false; - } else { - return true; - } - } - if ( station_a == MuonStationIndex::EM && - station_b == MuonStationIndex::EO ) { - if(result.shorttube_a > 800){ - return false; - } else { - return true; - } - } - } - //measured outer segment - if(result.phiposerr_b < 10001.000){ - if ( station_a == MuonStationIndex::BI && - station_b == MuonStationIndex::BM ) { - if(result.shorttube_b > 800){ - return false; - } else { - return true; - } - } - if ( station_a == MuonStationIndex::BI && - station_b == MuonStationIndex::BO ) { - if(result.shorttube_b > 800){ - return false; - } else { - return true; - } - } - if ( station_a == MuonStationIndex::BM && - station_b == MuonStationIndex::BO ) { - if(result.shorttube_b > 800){ - return false; - } else { - return true; - } - } - if ( station_a == MuonStationIndex::EI && - station_b == MuonStationIndex::EM ) { - if(result.shorttube_b > 1400){ - return false; - } else { - return true; - } - } - } - } - return true; + if (!useTightCuts) { + // cuts on second coordinate + if (result.phiSector_a == result.phiSector_b) { + if (result.phiposerr_a < 10001.000 && result.phiposerr_b < 10001.000) { + + if (!isEndcap_a && !isEndcap_b) { + if (result.deltaPhipos > 0.1) { + return false; + } else { + return true; + } + } + if (isEndcap_a && isEndcap_b) { + // small sectors + if (result.phiSector_a % 2 == 0) { + if (result.deltaPhipos > 0.1) { + return false; + } else { + return true; + } + } + // large sectors + if (result.phiSector_a % 2 == 1) { + if (result.deltaPhipos > 0.2) { + return false; + } else { + return true; + } + } + } + } + // if(result.phidirerr_a < 10001.000 && result.phidirerr_b < 10001.000){ + // if( !isEndcap_a && !isEndcap_b){ + // if( result.deltaPhidir > 0.2 ){ + // return false; + // } + // else { + // return true; + // } + // } + // if( isEndcap_a && isEndcap_b){ + // return true; + // } + // } + } + + if (result.phiSector_a != result.phiSector_b) { + if (result.phiposerr_a < 10001.000 && result.phiposerr_b < 10001.000) { + if (!isEndcap_a && !isEndcap_b) { + if (result.deltaPhipos > 0.1) { + return false; + } else { + return true; + } + } + if (isEndcap_a && isEndcap_b) { + if (result.deltaPhipos > 0.2) { + return false; + } else { + return true; + } + } + } + // if(result.phidirerr_a < 10001.000 && result.phidirerr_b < 10001.000){ + // if( !isEndcap_a && !isEndcap_b){ + // if( result.deltaPhidir > 0.2 ){ + // return false; + // } + // else { + // return true; + // } + // } + // if( isEndcap_a && isEndcap_b){ + // return true; + // } + // } + } + + // cuts on distance to tube edge + // only if in a different phi sector + if (result.phiSector_a != result.phiSector_b) { + // measured inner segment + if (result.phiposerr_a < 10001.000) { + if (station_a == MuonStationIndex::BM && station_b == MuonStationIndex::BO) { + if (result.shorttube_a > 800) { + return false; + } else { + return true; + } + } + if (station_a == MuonStationIndex::EI && station_b == MuonStationIndex::EM) { + // MM or STGC have result.shorttube = 99999. + if (result.shorttube_a > 3500 && result.shorttube_a != 99999.) { + return false; + } else { + return true; + } + } + if (station_a == MuonStationIndex::EI && station_b == MuonStationIndex::EO) { + if (result.shorttube_a > 3500 && result.shorttube_a != 99999.) { + return false; + } else { + return true; + } + } + if (station_a == MuonStationIndex::EM && station_b == MuonStationIndex::EO) { + if (result.shorttube_a > 800) { + return false; + } else { + return true; + } + } + } + // measured outer segment + if (result.phiposerr_b < 10001.000) { + if (station_a == MuonStationIndex::BI && station_b == MuonStationIndex::BM) { + if (result.shorttube_b > 800) { + return false; + } else { + return true; + } + } + if (station_a == MuonStationIndex::BI && station_b == MuonStationIndex::BO) { + if (result.shorttube_b > 800) { + return false; + } else { + return true; + } + } + if (station_a == MuonStationIndex::BM && station_b == MuonStationIndex::BO) { + if (result.shorttube_b > 800) { + return false; + } else { + return true; + } + } + if (station_a == MuonStationIndex::EI && station_b == MuonStationIndex::EM) { + if (result.shorttube_b > 1400) { + return false; + } else { + return true; + } + } + } + } + return true; } - - + + // Second: tight selection if only if requested - //cuts on second coordinate - if(result.phiSector_a==result.phiSector_b){ - if(result.phiposerr_a < 10001.000 && result.phiposerr_b < 10001.000){ - if( !isEndcap_a && !isEndcap_b){ - if( result.deltaPhipos > 0.1 ){ - return false; - } - else { - return true; - } - } - if( isEndcap_a && isEndcap_b){ - //small sectors - if( result.phiSector_a%2==0 ) { - if( result.deltaPhipos > 0.08 ){ - return false; - } - else { - return true; - } - } - //large sectors - if (result.phiSector_a%2==1) { - if( result.deltaPhipos > 0.1 ){ - return false; - } - else { - return true; - } - } - } - } -// if(result.phidirerr_a < 10001.000 && result.phidirerr_b < 10001.000){ -// if( !isEndcap_a && !isEndcap_b){ -// if( result.deltaPhidir > 0.1 ){ -// return false; -// } -// else { -// return true; -// } -// } -// if( isEndcap_a && isEndcap_b){ -// return true; -// } -// } + // cuts on second coordinate + if (result.phiSector_a == result.phiSector_b) { + if (result.phiposerr_a < 10001.000 && result.phiposerr_b < 10001.000) { + if (!isEndcap_a && !isEndcap_b) { + if (result.deltaPhipos > 0.1) { + return false; + } else { + return true; + } + } + if (isEndcap_a && isEndcap_b) { + // small sectors + if (result.phiSector_a % 2 == 0) { + if (result.deltaPhipos > 0.08) { + return false; + } else { + return true; + } + } + // large sectors + if (result.phiSector_a % 2 == 1) { + if (result.deltaPhipos > 0.1) { + return false; + } else { + return true; + } + } + } + } + // if(result.phidirerr_a < 10001.000 && result.phidirerr_b < 10001.000){ + // if( !isEndcap_a && !isEndcap_b){ + // if( result.deltaPhidir > 0.1 ){ + // return false; + // } + // else { + // return true; + // } + // } + // if( isEndcap_a && isEndcap_b){ + // return true; + // } + // } } - if(result.phiSector_a!=result.phiSector_b){ - if(result.phiposerr_a < 10001.000 && result.phiposerr_b < 10001.000){ - if( !isEndcap_a && !isEndcap_b){ - if( result.deltaPhipos > 0.05 ){ - return false; - } - else { - return true; - } - } - if( isEndcap_a && isEndcap_b){ - if( result.deltaPhipos > 0.1 ){ - return false; - } - else { - return true; - } - } - } -// if(result.phidirerr_a < 10001.000 && result.phidirerr_b < 10001.000){ -// if( !isEndcap_a && !isEndcap_b){ -// if( result.deltaPhidir > 0.1 ){ -// return false; -// } -// else { -// return true; -// } -// } -// if( isEndcap_a && isEndcap_b){ -// return true; -// } -// } - //cuts on distance to tube edge - //only if in a different phi sector - if(result.phiSector_a!=result.phiSector_b){ - //measured inner segment - if(result.phiposerr_a < 10001.000){ - if ( station_a == MuonStationIndex::BM && - station_b == MuonStationIndex::BO ) { - if(result.shorttube_a > 600){ - return false; - } else { - return true; - } - } - if ( station_a == MuonStationIndex::EI && - station_b == MuonStationIndex::EM ) { - if(result.shorttube_a > 3500 && result.shorttube_a != 99999.){ - return false; - } else { - return true; - } - } - if ( station_a == MuonStationIndex::EI && - station_b == MuonStationIndex::EO ) { - if(result.shorttube_a > 3500 && result.shorttube_a != 99999.){ - return false; - } else { - return true; - } - } - if ( station_a == MuonStationIndex::EM && - station_b == MuonStationIndex::EO ) { - if(result.shorttube_a > 500){ - return false; - } else { - return true; - } - } - } - //measured outer segment - if(result.phiposerr_b < 10001.000){ - if ( station_a == MuonStationIndex::BI && - station_b == MuonStationIndex::BM ) { - if(result.shorttube_b > 600){ - return false; - } else { - return true; - } - } - if ( station_a == MuonStationIndex::BI && - station_b == MuonStationIndex::BO ) { - if(result.shorttube_b > 700){ - return false; - } else { - return true; - } - } - if ( station_a == MuonStationIndex::BM && - station_b == MuonStationIndex::BO ) { - if(result.shorttube_b > 700){ - return false; - } else { - return true; - } - } - if ( station_a == MuonStationIndex::EI && - station_b == MuonStationIndex::EM ) { - if(result.shorttube_b > 700){ - return false; - } else { - return true; - } - } - } - } - } + if (result.phiSector_a != result.phiSector_b) { + if (result.phiposerr_a < 10001.000 && result.phiposerr_b < 10001.000) { + if (!isEndcap_a && !isEndcap_b) { + if (result.deltaPhipos > 0.05) { + return false; + } else { + return true; + } + } + if (isEndcap_a && isEndcap_b) { + if (result.deltaPhipos > 0.1) { + return false; + } else { + return true; + } + } + } + // if(result.phidirerr_a < 10001.000 && result.phidirerr_b < 10001.000){ + // if( !isEndcap_a && !isEndcap_b){ + // if( result.deltaPhidir > 0.1 ){ + // return false; + // } + // else { + // return true; + // } + // } + // if( isEndcap_a && isEndcap_b){ + // return true; + // } + // } + // cuts on distance to tube edge + // only if in a different phi sector + if (result.phiSector_a != result.phiSector_b) { + // measured inner segment + if (result.phiposerr_a < 10001.000) { + if (station_a == MuonStationIndex::BM && station_b == MuonStationIndex::BO) { + if (result.shorttube_a > 600) { + return false; + } else { + return true; + } + } + if (station_a == MuonStationIndex::EI && station_b == MuonStationIndex::EM) { + if (result.shorttube_a > 3500 && result.shorttube_a != 99999.) { + return false; + } else { + return true; + } + } + if (station_a == MuonStationIndex::EI && station_b == MuonStationIndex::EO) { + if (result.shorttube_a > 3500 && result.shorttube_a != 99999.) { + return false; + } else { + return true; + } + } + if (station_a == MuonStationIndex::EM && station_b == MuonStationIndex::EO) { + if (result.shorttube_a > 500) { + return false; + } else { + return true; + } + } + } + // measured outer segment + if (result.phiposerr_b < 10001.000) { + if (station_a == MuonStationIndex::BI && station_b == MuonStationIndex::BM) { + if (result.shorttube_b > 600) { + return false; + } else { + return true; + } + } + if (station_a == MuonStationIndex::BI && station_b == MuonStationIndex::BO) { + if (result.shorttube_b > 700) { + return false; + } else { + return true; + } + } + if (station_a == MuonStationIndex::BM && station_b == MuonStationIndex::BO) { + if (result.shorttube_b > 700) { + return false; + } else { + return true; + } + } + if (station_a == MuonStationIndex::EI && station_b == MuonStationIndex::EM) { + if (result.shorttube_b > 700) { + return false; + } else { + return true; + } + } + } + } + } return true; - } // if m_useLocalAngles - +} // if m_useLocalAngles - bool MuonSegmentMatchingTool::endcapExtrapolationMatch( const MuonSegment& seg1, const MuonSegment& seg2, - bool useTightCuts ) const { +bool +MuonSegmentMatchingTool::endcapExtrapolationMatch(const MuonSegment& seg1, const MuonSegment& seg2, + bool useTightCuts) const +{ - if( !m_useEndcapExtrapolationMatching ) return true; + if (!m_useEndcapExtrapolationMatching) return true; Identifier chid1 = m_edmHelperSvc->chamberId(seg1); Identifier chid2 = m_edmHelperSvc->chamberId(seg2); - if( chid1 == chid2 ) return false; + if (chid1 == chid2) return false; MuonStationIndex::StIndex stIndex1 = m_idHelperSvc->stationIndex(chid1); MuonStationIndex::StIndex stIndex2 = m_idHelperSvc->stationIndex(chid2); - if( stIndex1 == stIndex2 ) return false; + if (stIndex1 == stIndex2) return false; const MuonSegment* segInner = 0; - if( stIndex1 == MuonStationIndex::EI ) segInner = &seg1; - if( stIndex2 == MuonStationIndex::EI ) segInner = &seg2; + if (stIndex1 == MuonStationIndex::EI) segInner = &seg1; + if (stIndex2 == MuonStationIndex::EI) segInner = &seg2; const MuonSegment* segOuter = 0; - if( stIndex1 == MuonStationIndex::EM || stIndex1 == MuonStationIndex::EO ) segOuter = &seg1; - if( stIndex2 == MuonStationIndex::EM || stIndex2 == MuonStationIndex::EO ) segOuter = &seg2; + if (stIndex1 == MuonStationIndex::EM || stIndex1 == MuonStationIndex::EO) segOuter = &seg1; + if (stIndex2 == MuonStationIndex::EM || stIndex2 == MuonStationIndex::EO) segOuter = &seg2; - if( !segInner || !segOuter ) { - return false; + if (!segInner || !segOuter) { + return false; } const Amg::Vector3D& pos1 = segOuter->globalPosition(); const Amg::Vector3D& dir1 = segOuter->globalDirection(); @@ -1042,43 +1057,51 @@ namespace Muon { const Amg::Vector3D& dir2 = segInner->globalDirection(); // extrapolate the first segment to the inner layer - double r_expected = 0; + double r_expected = 0; double theta_expected = 0; - double rhoInv = 0; - simpleEndcapExtrapolate( pos1.x(), pos1.y(), pos1.z(), dir1.theta(), pos2.z(), - r_expected, theta_expected, rhoInv ); - - if( rhoInv < 0 ) rhoInv *= -1.; - double dr = pos2.perp() - r_expected; - double dtheta = dir2.theta() - theta_expected; + double rhoInv = 0; + simpleEndcapExtrapolate(pos1.x(), pos1.y(), pos1.z(), dir1.theta(), pos2.z(), r_expected, theta_expected, rhoInv); - double drCut = m_drExtrapRMS + 5e6*rhoInv; - if( useTightCuts ) drCut *= 2; - else drCut *= 4; + if (rhoInv < 0) rhoInv *= -1.; + double dr = pos2.perp() - r_expected; + double dtheta = dir2.theta() - theta_expected; - if( (stIndex1 == MuonStationIndex::EM && stIndex2 == MuonStationIndex::BI) || (stIndex1 == MuonStationIndex::BI && stIndex2 == MuonStationIndex::EM) ){ - drCut += 3*m_drExtrapAlignmentOffset; - }else{ - drCut += m_drExtrapAlignmentOffset; + double drCut = m_drExtrapRMS + 5e6 * rhoInv; + if (useTightCuts) + drCut *= 2; + else + drCut *= 4; + + if ((stIndex1 == MuonStationIndex::EM && stIndex2 == MuonStationIndex::BI) + || (stIndex1 == MuonStationIndex::BI && stIndex2 == MuonStationIndex::EM)) + { + drCut += 3 * m_drExtrapAlignmentOffset; + } else { + drCut += m_drExtrapAlignmentOffset; } - double dthetaCut = m_dthetaExtrapRMS + 1.5e3*rhoInv; - if( useTightCuts ) dthetaCut *= 2; - else dthetaCut *= 4; + double dthetaCut = m_dthetaExtrapRMS + 1.5e3 * rhoInv; + if (useTightCuts) + dthetaCut *= 2; + else + dthetaCut *= 4; ATH_MSG_VERBOSE(" simple match " << m_printer->print(seg1) << std::endl - << " " << m_printer->print(seg2) << std::endl - << " dr " << dr << " cut " << drCut << " dtheta " << dtheta << " cut " << dthetaCut << " rhoInv " << 1e6*rhoInv); + << " " << m_printer->print(seg2) << std::endl + << " dr " << dr << " cut " << drCut << " dtheta " << dtheta << " cut " << dthetaCut + << " rhoInv " << 1e6 * rhoInv); - if( fabs(dr) > drCut ) return false; - if( fabs(dtheta) > dthetaCut ) return false; + if (fabs(dr) > drCut) return false; + if (fabs(dtheta) > dthetaCut) return false; return true; - } +} - void MuonSegmentMatchingTool::simpleEndcapExtrapolate(double x_segment, double y_segment, double z_segment, double theta_segment, - double z_extrapolated, double& r_expected, - double& theta_expected, double& rhoInv ) const { +void +MuonSegmentMatchingTool::simpleEndcapExtrapolate(double x_segment, double y_segment, double z_segment, + double theta_segment, double z_extrapolated, double& r_expected, + double& theta_expected, double& rhoInv) const +{ // // Endcap extrapolation with a parabolic track model // @@ -1086,51 +1109,49 @@ namespace Muon { // r_expected = z tan(theta) + (z - z start)*(z - z start)/ rho // // outside this region No field - // + // // here z start = 6 000 z end = 10 000 // theta = direction at the vertex rho is the effective curvature // - double z_start = 7000.; + double z_start = 7000.; double z_end = 12000.; - if(z_extrapolated<0) z_start = - z_start; - if(z_extrapolated<0) z_end = - z_end; + if (z_extrapolated < 0) z_start = -z_start; + if (z_extrapolated < 0) z_end = -z_end; - double r_segment = sqrt(x_segment*x_segment+y_segment*y_segment); + double r_segment = sqrt(x_segment * x_segment + y_segment * y_segment); - if(fabs(z_extrapolated) > fabs(z_segment)) { - ATH_MSG_WARNING(" extrapolate outwards is not implemented for z " << z_extrapolated); - r_expected = 0; - theta_expected = 0.; - return; + if (fabs(z_extrapolated) > fabs(z_segment)) { + ATH_MSG_WARNING(" extrapolate outwards is not implemented for z " << z_extrapolated); + r_expected = 0; + theta_expected = 0.; + return; } - if(fabs(z_segment) < fabs(z_end) ) { - ATH_MSG_WARNING(" segment before end of Toroid: SL extrapolation is used implemented " << z_segment); + if (fabs(z_segment) < fabs(z_end)) { + ATH_MSG_WARNING(" segment before end of Toroid: SL extrapolation is used implemented " << z_segment); } // use SL extrapolation to go to the z_end of the Toroid - double r_end = r_segment + (z_end-z_segment)*tan(theta_segment); + double r_end = r_segment + (z_end - z_segment) * tan(theta_segment); - // std::cout << "z end " << z_end << " r_end " << r_end << std::endl; - // std::cout << "r_segment " << r_segment << " z _segment " << z_segment << std::endl; + // std::cout << "z end " << z_end << " r_end " << r_end << std::endl; + // std::cout << "r_segment " << r_segment << " z _segment " << z_segment << std::endl; - double zgeo = (z_end-z_start)*(z_end-z_start) -2*z_end*(z_end-z_start); - rhoInv = (r_end - z_end*tan(theta_segment)) / zgeo; - double tantheta = tan(theta_segment) - 2*(z_end - z_start)*rhoInv; - r_expected = z_extrapolated*tantheta + (z_extrapolated-z_start)*(z_extrapolated-z_start)*rhoInv; + double zgeo = (z_end - z_start) * (z_end - z_start) - 2 * z_end * (z_end - z_start); + rhoInv = (r_end - z_end * tan(theta_segment)) / zgeo; + double tantheta = tan(theta_segment) - 2 * (z_end - z_start) * rhoInv; + r_expected = z_extrapolated * tantheta + (z_extrapolated - z_start) * (z_extrapolated - z_start) * rhoInv; // - // increase radius by 30% wrt straight line + // increase radius by 30% wrt straight line // - double r_SL = r_segment + (z_extrapolated-z_segment)*tan(theta_segment); - r_expected = r_expected + 0.3*(r_expected-r_SL); - theta_expected = atan(tantheta+2*(z_extrapolated-z_start)*rhoInv); - - if(tan(theta_segment)<0&&theta_expected<0) theta_expected += 2*acos(0.); - if(tan(theta_segment)>0&&theta_expected<0) theta_expected = - theta_expected; - } - - + double r_SL = r_segment + (z_extrapolated - z_segment) * tan(theta_segment); + r_expected = r_expected + 0.3 * (r_expected - r_SL); + theta_expected = atan(tantheta + 2 * (z_extrapolated - z_start) * rhoInv); + if (tan(theta_segment) < 0 && theta_expected < 0) theta_expected += 2 * acos(0.); + if (tan(theta_segment) > 0 && theta_expected < 0) theta_expected = -theta_expected; } + +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentMatchingTool.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentMatchingTool.h index 823994d5486487f5d60dd603e5ede15d5906a5b4..f8717fa2a486bbad26ddd71bf6597b258828ec61 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentMatchingTool.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentMatchingTool.h @@ -5,92 +5,113 @@ #ifndef MUON_MUONSEGMENTMATCHINGTOOL_H #define MUON_MUONSEGMENTMATCHINGTOOL_H -#include "MuonSegmentMakerToolInterfaces/IMuonSegmentMatchingTool.h" +#include <atomic> #include "AthenaBaseComps/AthAlgTool.h" -#include "GaudiKernel/ToolHandle.h" #include "GaudiKernel/ServiceHandle.h" - +#include "GaudiKernel/ToolHandle.h" +#include "MuonIdHelpers/IMuonIdHelperSvc.h" #include "MuonRecHelperTools/IMuonEDMHelperSvc.h" #include "MuonRecHelperTools/MuonEDMPrinterTool.h" -#include "MuonIdHelpers/IMuonIdHelperSvc.h" #include "MuonSegmentMakerToolInterfaces/IMuonSegmentInOverlapResolvingTool.h" +#include "MuonSegmentMakerToolInterfaces/IMuonSegmentMatchingTool.h" #include "MuonSegmentMakerToolInterfaces/IMuonSegmentPairMatchingTool.h" #include "TrkGeometry/MagneticFieldProperties.h" -#include <atomic> - namespace Muon { - - class MuonSegment; - - /** - @brief tool to match segments using a curved trajectory. The tool decides whether the matching should be - performed with curvature or with a straight line. - Cases in which a straight line will be used: - - no magnetic field in the muon spectrometer - - endcap middle/outer combination - - small/large overlap in one station layer - */ - class MuonSegmentMatchingTool : virtual public IMuonSegmentMatchingTool, public AthAlgTool { + +class MuonSegment; + +/** + @brief tool to match segments using a curved trajectory. The tool decides whether the matching should be + performed with curvature or with a straight line. + Cases in which a straight line will be used: + - no magnetic field in the muon spectrometer + - endcap middle/outer combination + - small/large overlap in one station layer +*/ +class MuonSegmentMatchingTool : virtual public IMuonSegmentMatchingTool, public AthAlgTool { public: /** @brief constructor */ - MuonSegmentMatchingTool(const std::string&,const std::string&,const IInterface*); + MuonSegmentMatchingTool(const std::string&, const std::string&, const IInterface*); /** @brief destructor */ - virtual ~MuonSegmentMatchingTool()=default; - + virtual ~MuonSegmentMatchingTool() = default; + /** @brief AlgTool initilize */ StatusCode initialize(); - + /** @brief AlgTool finalize */ StatusCode finalize(); - + /** @brief match two segments */ - bool match( const MuonSegment& seg1, const MuonSegment& seg2 ) const; + bool match(const MuonSegment& seg1, const MuonSegment& seg2) const; private: /** @brief perform straight line matching using SL extrapolation */ - bool straightLineMatch( const MuonSegment& seg1, const MuonSegment& seg2 ) const; + bool straightLineMatch(const MuonSegment& seg1, const MuonSegment& seg2) const; /** @brief perform curved matching */ - bool curvedMatch( const MuonSegment& seg1, const MuonSegment& seg2 ) const; + bool curvedMatch(const MuonSegment& seg1, const MuonSegment& seg2) const; /** @brief perform overlap matching */ - bool overlapMatch( const MuonSegment& seg1, const MuonSegment& seg2 ) const; + bool overlapMatch(const MuonSegment& seg1, const MuonSegment& seg2) const; /** @brief setup field */ bool initializeField() const; /** @brief check whether the two segments have a stereo angle */ - bool hasStereoAngle( const Identifier& id1, const Identifier& id2 ) const; - - /** @brief check whether we should perform a straight line match */ - bool isSLMatch( const Identifier& chid1, const Identifier& chid2 ) const; - - /** @brief Suppress noise from cavern background/pile up using basic cuts */ - bool suppressNoise( const MuonSegment& seg1, const MuonSegment& seg2, const bool& useTightCuts ) const; - - /** @brief Suppress noise from cavern background/pile up using basic cuts in phi */ - bool suppressNoisePhi( const MuonSegment& seg1, const MuonSegment& seg2, const bool& useTightCuts ) const; - - /** @brief extrapolate segment in middle or outer endcap station to inner layer assuming the particle came from the IP */ - void simpleEndcapExtrapolate(double x_segment, double y_segment, double z_segment, double theta_segment, double z_extrapolated, - double& r_expected, double& theta_expected, double& rhoInv) const; + bool hasStereoAngle(const Identifier& id1, const Identifier& id2) const; - - /** @brief match an endcap middle or outer segment with an inner segment using a simple analytic extrapolation model */ - bool endcapExtrapolationMatch( const MuonSegment& seg1, const MuonSegment& seg2, bool useTightCuts ) const; + /** @brief check whether we should perform a straight line match */ + bool isSLMatch(const Identifier& chid1, const Identifier& chid2) const; - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - ServiceHandle<Muon::IMuonEDMHelperSvc> m_edmHelperSvc {this, "edmHelper", - "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", - "Handle to the service providing the IMuonEDMHelperSvc interface" }; //!< EDM Helper tool - ToolHandle<Muon::MuonEDMPrinterTool> m_printer; //!< EDM printer tool - ToolHandle<Muon::IMuonSegmentInOverlapResolvingTool> m_overlapResolvingTool; //!< matching tool to handle the overlaps - ToolHandle<Muon::IMuonSegmentPairMatchingTool> m_pairMatchingTool; //!< matching tool to handle the pairs of segments + /** @brief Suppress noise from cavern background/pile up using basic cuts */ + bool suppressNoise(const MuonSegment& seg1, const MuonSegment& seg2, const bool& useTightCuts) const; - Gaudi::Property<bool> m_toroidOn { this, "ToroidOn", true, "Status of toroidal B-Field" }; + /** @brief Suppress noise from cavern background/pile up using basic cuts in phi */ + bool suppressNoisePhi(const MuonSegment& seg1, const MuonSegment& seg2, const bool& useTightCuts) const; + + /** @brief extrapolate segment in middle or outer endcap station to inner layer assuming the particle came from the + * IP */ + void simpleEndcapExtrapolate(double x_segment, double y_segment, double z_segment, double theta_segment, + double z_extrapolated, double& r_expected, double& theta_expected, + double& rhoInv) const; + + + /** @brief match an endcap middle or outer segment with an inner segment using a simple analytic extrapolation model + */ + bool endcapExtrapolationMatch(const MuonSegment& seg1, const MuonSegment& seg2, bool useTightCuts) const; + + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; + ServiceHandle<Muon::IMuonEDMHelperSvc> m_edmHelperSvc{ + this, + "edmHelper", + "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", + "Handle to the service providing the IMuonEDMHelperSvc interface", + }; //!< EDM Helper tool + + ToolHandle<Muon::MuonEDMPrinterTool> m_printer{ + this, + "Printer", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; //!< EDM printer tool + ToolHandle<Muon::IMuonSegmentInOverlapResolvingTool> m_overlapResolvingTool{ + this, + "MuonSegmentInOverlapResolvingTool", + "Muon::MuonSegmentInOverlapResolvingTool/MuonSegmentInOverlapResolvingTool", + }; //!< matching tool to handle the overlaps + ToolHandle<Muon::IMuonSegmentPairMatchingTool> m_pairMatchingTool{ + this, + "MuonSegmentPairMatchingTool", + "Muon::MuonSegmentPairMatchingTool/MuonSegmentPairMatchingTool", + }; //!< matching tool to handle the pairs of segments + + Gaudi::Property<bool> m_toroidOn{this, "ToroidOn", true, "Status of toroidal B-Field"}; mutable std::atomic_uint m_straightLineMatches; mutable std::atomic_uint m_straightLineMatchesGood; @@ -106,22 +127,25 @@ namespace Muon { bool m_thetaMatch; bool m_phiMatch; bool m_useLocalAngles; - + // cuts for straight line match double m_straightLineMatchAngleCut; double m_straightLineMatchPositionCut; // cuts for sl overlap match - double m_overlapMatchAngleDPhiCut; //!< cut of the angular difference between phi from phi match and phi from positions - double m_overlapMatchAngleDYZCut; //!< cut of the angular difference between phi from phi match and phi from positions - double m_overlapMatchPositionCut; //!< cut on the distance of best position from the chamber bounds - double m_overlapMatchPositionResidualCut; //!< cut on the position residual for the best position match - double m_overlapMatchPhiHitPullCut; //!< cut on the average pull of the phi hits with the new segment parameters + double m_overlapMatchAngleDPhiCut; //!< cut of the angular difference between phi from phi match and phi from + //!< positions + double + m_overlapMatchAngleDYZCut; //!< cut of the angular difference between phi from phi match and phi from positions + double m_overlapMatchPositionCut; //!< cut on the distance of best position from the chamber bounds + double m_overlapMatchPositionResidualCut; //!< cut on the position residual for the best position match + double m_overlapMatchPhiHitPullCut; //!< cut on the average pull of the phi hits with the new segment parameters // cuts for matching segments from different stations double m_angleABCut; - double m_maxDistSegments; //!< cut on the maximum distance between the segments - double m_minDistSegmentsCosmics; //!< cut on the minimum distance between the segments, if the distance is larger than the cut the segments are always matched (for cosmics) + double m_maxDistSegments; //!< cut on the maximum distance between the segments + double m_minDistSegmentsCosmics; //!< cut on the minimum distance between the segments, if the distance is larger + //!< than the cut the segments are always matched (for cosmics) double m_matchingbibm_lphisec; double m_matchingbibo_lphisec; double m_matchingbmbo_lphisec; @@ -134,19 +158,19 @@ namespace Muon { double m_matchingeiem_sphisec; double m_matchingeieo_sphisec; double m_matchingemeo_sphisec; - + double m_matchingbee_sphisec; - - bool m_onlySameSectorIfTight; //!< reject all segments in different sectors if in tight matching - bool m_useTightCuts; //!< only apply tight selection for busy combinations - bool m_dumpAngles; //!< dump matching angle info to screen + + bool m_onlySameSectorIfTight; //!< reject all segments in different sectors if in tight matching + bool m_useTightCuts; //!< only apply tight selection for busy combinations + bool m_dumpAngles; //!< dump matching angle info to screen bool m_useEndcapExtrapolationMatching; double m_drExtrapRMS; double m_drExtrapAlignmentOffset; double m_dthetaExtrapRMS; - }; +}; -} +} // namespace Muon #endif diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentPairMatchingTool.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentPairMatchingTool.cxx index 90832608493e56f36938a3cff554f176e5bee573..70a436ff5e73faa3ef42fd1ef99973b9b3b798a9 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentPairMatchingTool.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentPairMatchingTool.cxx @@ -4,92 +4,97 @@ #include "MuonSegmentPairMatchingTool.h" +#include "MuonCompetingRIOsOnTrack/CompetingMuonClustersOnTrack.h" +#include "MuonRIO_OnTrack/MdtDriftCircleOnTrack.h" +#include "MuonReadoutGeometry/MdtReadoutElement.h" #include "MuonRecHelperTools/IMuonEDMHelperSvc.h" #include "MuonRecHelperTools/MuonEDMPrinterTool.h" #include "MuonSegment/MuonSegment.h" -#include "MuonRIO_OnTrack/MdtDriftCircleOnTrack.h" -#include "MuonReadoutGeometry/MdtReadoutElement.h" -#include "MuonCompetingRIOsOnTrack/CompetingMuonClustersOnTrack.h" #include "TrkEventPrimitives/LocalDirection.h" namespace { - // limit angle difference to -pi < x <= pi - inline double limit_angle_2pi(double x) { - while ( x <= -M_PI ) x += 2.0 * M_PI; - while ( x > +M_PI ) x -= 2.0 * M_PI; +// limit angle difference to -pi < x <= pi +inline double +limit_angle_2pi(double x) +{ + while (x <= -M_PI) x += 2.0 * M_PI; + while (x > +M_PI) x -= 2.0 * M_PI; return x; - } +} - inline double robust_acos(double x) { - if ( x >= +1.0 ) return 0.0; - if ( x <= -1.0 ) return M_PI; +inline double +robust_acos(double x) +{ + if (x >= +1.0) return 0.0; + if (x <= -1.0) return M_PI; return std::acos(x); - } - -} // unnamed namespace +} + +} // unnamed namespace - namespace Muon { - MuonSegmentPairMatchingTool::MuonSegmentPairMatchingTool(const std::string& ty,const std::string& na,const IInterface* pa) - : AthAlgTool(ty,na,pa), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool") - { +MuonSegmentPairMatchingTool::MuonSegmentPairMatchingTool(const std::string& ty, const std::string& na, + const IInterface* pa) + : AthAlgTool(ty, na, pa) +{ declareInterface<IMuonSegmentPairMatchingTool>(this); - } +} - StatusCode MuonSegmentPairMatchingTool::initialize() - { +StatusCode +MuonSegmentPairMatchingTool::initialize() +{ ATH_CHECK(AthAlgTool::initialize()); - + ATH_CHECK(m_edmHelperSvc.retrieve()); ATH_CHECK(m_printer.retrieve()); ATH_CHECK(m_idHelperSvc.retrieve()); return StatusCode::SUCCESS; - } +} - IMuonSegmentPairMatchingTool::SegmentMatchResult MuonSegmentPairMatchingTool::matchResult( const MuonSegment& seg1, const MuonSegment& seg2 ) const { +IMuonSegmentPairMatchingTool::SegmentMatchResult +MuonSegmentPairMatchingTool::matchResult(const MuonSegment& seg1, const MuonSegment& seg2) const +{ IMuonSegmentPairMatchingTool::SegmentMatchResult result; // get identifiers // and the detector region from identifier - Identifier chid1 = m_edmHelperSvc->chamberId(seg1); - MuonStationIndex::StIndex station1 = m_idHelperSvc->stationIndex( chid1 ); + Identifier chid1 = m_edmHelperSvc->chamberId(seg1); + MuonStationIndex::StIndex station1 = m_idHelperSvc->stationIndex(chid1); - Identifier chid2 = m_edmHelperSvc->chamberId(seg2); - MuonStationIndex::StIndex station2 = m_idHelperSvc->stationIndex( chid2 ); + Identifier chid2 = m_edmHelperSvc->chamberId(seg2); + MuonStationIndex::StIndex station2 = m_idHelperSvc->stationIndex(chid2); // Don't deal with overlap/merge of segments here - if ( chid1 == chid2 ) return result; - if ( station1 == station2 ) return result; + if (chid1 == chid2) return result; + if (station1 == station2) return result; // Don't know how to deal with these cases yet... - if (station1 == MuonStationIndex::StUnknown ) return result; - if (station2 == MuonStationIndex::StUnknown ) return result; - if (station1 >= MuonStationIndex::StIndexMax ) return result; - if (station2 >= MuonStationIndex::StIndexMax ) return result; + if (station1 == MuonStationIndex::StUnknown) return result; + if (station2 == MuonStationIndex::StUnknown) return result; + if (station1 >= MuonStationIndex::StIndexMax) return result; + if (station2 >= MuonStationIndex::StIndexMax) return result; // Here order matters, so sort segment by order a= inner, b= outer // MuonStationIndex::StIndex station_a = station1; // MuonStationIndex::StIndex station_b = station2; - + const MuonSegment* pSeg_a = 0; const MuonSegment* pSeg_b = 0; // bool swapped = false; - if ( station1 < station2 ) { - pSeg_a = &seg1; - pSeg_b = &seg2; + if (station1 < station2) { + pSeg_a = &seg1; + pSeg_b = &seg2; - } - else { - // swapped = true; - pSeg_a = &seg2; - pSeg_b = &seg1; - // station_a = station2; - // station_b = station1; + } else { + // swapped = true; + pSeg_a = &seg2; + pSeg_b = &seg1; + // station_a = station2; + // station_b = station1; } const MuonSegment& seg_a(*pSeg_a); @@ -98,42 +103,42 @@ namespace Muon { Identifier chid_a = m_edmHelperSvc->chamberId(seg_a); Identifier chid_b = m_edmHelperSvc->chamberId(seg_b); - int phiSector_a = m_idHelperSvc->sector( chid_a ); - int phiSector_b = m_idHelperSvc->sector( chid_b ); + int phiSector_a = m_idHelperSvc->sector(chid_a); + int phiSector_b = m_idHelperSvc->sector(chid_b); result.chid_a = chid_a; result.chid_b = chid_b; result.phiSector_a = phiSector_a; result.phiSector_b = phiSector_b; - + const Amg::Vector3D& dir_a = seg_a.globalDirection(); const Amg::Vector3D& dir_b = seg_b.globalDirection(); const Amg::Vector3D& pos_a = seg_a.globalPosition(); const Amg::Vector3D& pos_b = seg_b.globalPosition(); - + // Define direction between segment position Amg::Vector3D vecAB = pos_b - pos_a; // compute angle between vector position a and b using dot product double sizeA = dir_a.mag(); double sizeB = dir_b.mag(); - double cosAB = dir_a.dot( dir_b ) / (sizeA * sizeB ); + double cosAB = dir_a.dot(dir_b) / (sizeA * sizeB); double angleAB = robust_acos(cosAB); // compute angle between vector position a and b using dot product double sizeC = vecAB.mag(); - double cosAC = dir_a.dot( vecAB ) / (sizeA * sizeC ); + double cosAC = dir_a.dot(vecAB) / (sizeA * sizeC); double angleAC = robust_acos(cosAC); // compute angle between vector position a and b using dot product - double cosBC = dir_b.dot( vecAB ) / (sizeB * sizeC ); + double cosBC = dir_b.dot(vecAB) / (sizeB * sizeC); double angleBC = robust_acos(cosBC); - if ( angleAB > M_PI /2. ) angleAB = fabs( angleAB - M_PI); - if ( angleAC > M_PI /2. ) angleAC = fabs( angleAC - M_PI); - if ( angleBC > M_PI /2. ) angleBC = fabs( angleBC - M_PI); + if (angleAB > M_PI / 2.) angleAB = fabs(angleAB - M_PI); + if (angleAC > M_PI / 2.) angleAC = fabs(angleAC - M_PI); + if (angleBC > M_PI / 2.) angleBC = fabs(angleBC - M_PI); result.angleAB = angleAB; result.angleAC = angleAC; @@ -141,182 +146,188 @@ namespace Muon { // Compute local angles // for some reason, vec12 gets the direction right far more often than vecAB - double dirTheta_a = seg_a.localDirection().angleYZ(); - double dirTheta_b = seg_b.localDirection().angleYZ(); + double dirTheta_a = seg_a.localDirection().angleYZ(); + double dirTheta_b = seg_b.localDirection().angleYZ(); Trk::LocalDirection dirPred_a; - seg_a.associatedSurface().globalToLocalDirection( vecAB, dirPred_a ); + seg_a.associatedSurface().globalToLocalDirection(vecAB, dirPred_a); Trk::LocalDirection dirPred_b; - seg_b.associatedSurface().globalToLocalDirection( vecAB, dirPred_b ); - double deltaTheta_a = limit_angle_2pi( dirTheta_a - dirPred_a.angleYZ() ); - double deltaTheta_b = limit_angle_2pi( dirTheta_b - dirPred_b.angleYZ() ); - + seg_b.associatedSurface().globalToLocalDirection(vecAB, dirPred_b); + double deltaTheta_a = limit_angle_2pi(dirTheta_a - dirPred_a.angleYZ()); + double deltaTheta_b = limit_angle_2pi(dirTheta_b - dirPred_b.angleYZ()); + // bool opposite = false; // in case both segment directions are opposite to vecAB, try opposite direction - if ( std::abs(deltaTheta_a) > 0.5 * M_PI && std::abs(deltaTheta_b) > 0.5 * M_PI ) { - // opposite = true; - seg_a.associatedSurface().globalToLocalDirection( -vecAB, dirPred_a ); - seg_b.associatedSurface().globalToLocalDirection( -vecAB, dirPred_b ); - deltaTheta_a = limit_angle_2pi( dirTheta_a - dirPred_a.angleYZ() ); - deltaTheta_b = limit_angle_2pi( dirTheta_b - dirPred_b.angleYZ() ); + if (std::abs(deltaTheta_a) > 0.5 * M_PI && std::abs(deltaTheta_b) > 0.5 * M_PI) { + // opposite = true; + seg_a.associatedSurface().globalToLocalDirection(-vecAB, dirPred_a); + seg_b.associatedSurface().globalToLocalDirection(-vecAB, dirPred_b); + deltaTheta_a = limit_angle_2pi(dirTheta_a - dirPred_a.angleYZ()); + deltaTheta_b = limit_angle_2pi(dirTheta_b - dirPred_b.angleYZ()); } - - + + // look at the relative orientation of the local X axes to determine if YZ angles are flipped - bool flipped = false; - const Amg::Transform3D& trf_a = seg_a.associatedSurface().transform(); - const Amg::Transform3D& trf_b = seg_b.associatedSurface().transform(); - double xAxisDotProduct = trf_a(0,0) * trf_b(0,0) + trf_a(1,0) * trf_b(1,0) + trf_a(2,0) * trf_b(2,0); - if ( xAxisDotProduct < 0.0 ) flipped = true; + bool flipped = false; + const Amg::Transform3D& trf_a = seg_a.associatedSurface().transform(); + const Amg::Transform3D& trf_b = seg_b.associatedSurface().transform(); + double xAxisDotProduct = trf_a(0, 0) * trf_b(0, 0) + trf_a(1, 0) * trf_b(1, 0) + trf_a(2, 0) * trf_b(2, 0); + if (xAxisDotProduct < 0.0) flipped = true; double deltaTheta = 0.0; - if ( flipped ) { - deltaTheta = std::abs( limit_angle_2pi( deltaTheta_a - deltaTheta_b ) ); + if (flipped) { + deltaTheta = std::abs(limit_angle_2pi(deltaTheta_a - deltaTheta_b)); } else { - deltaTheta = std::abs( limit_angle_2pi( deltaTheta_a + deltaTheta_b ) ); + deltaTheta = std::abs(limit_angle_2pi(deltaTheta_a + deltaTheta_b)); } - + result.deltaTheta_a = deltaTheta_a; result.deltaTheta_b = deltaTheta_b; - result.deltaTheta = deltaTheta; + result.deltaTheta = deltaTheta; // compute angular differences in second coordinate - result.deltaPhipos = fabs( seg_a.globalPosition().phi() - seg_b.globalPosition().phi() ); - result.deltaPhidir = fabs( seg_a.globalDirection().phi() - seg_b.globalDirection().phi() ); - -// check presence of phi hits on segment a - bool ContainPhiHits = false; - std::vector< const Trk::MeasurementBase* >::const_iterator hit = seg_a.containedMeasurements().begin(); - std::vector< const Trk::MeasurementBase* >::const_iterator hit_end = seg_a.containedMeasurements().end(); - for( ;hit!=hit_end;++hit ){ - Identifier id; - const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(*hit); - if( rot ) id = rot->identify(); - else{ - const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*hit); - if( crot ) id = crot->containedROTs().front()->identify(); - } - if( !id.is_valid() ) continue; - if(m_idHelperSvc->measuresPhi(id)) { - ContainPhiHits = true; - break; - } - } - - if(ContainPhiHits) { - result.phiposerr_a = seg_a.localCovariance()(Trk::locX,Trk::locX); - result.phidirerr_a = seg_a.localCovariance()(Trk::phi,Trk::phi); + result.deltaPhipos = fabs(seg_a.globalPosition().phi() - seg_b.globalPosition().phi()); + result.deltaPhidir = fabs(seg_a.globalDirection().phi() - seg_b.globalDirection().phi()); + + // check presence of phi hits on segment a + bool ContainPhiHits = false; + std::vector<const Trk::MeasurementBase*>::const_iterator hit = seg_a.containedMeasurements().begin(); + std::vector<const Trk::MeasurementBase*>::const_iterator hit_end = seg_a.containedMeasurements().end(); + for (; hit != hit_end; ++hit) { + Identifier id; + const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(*hit); + if (rot) + id = rot->identify(); + else { + const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*hit); + if (crot) id = crot->containedROTs().front()->identify(); + } + if (!id.is_valid()) continue; + if (m_idHelperSvc->measuresPhi(id)) { + ContainPhiHits = true; + break; + } + } + + if (ContainPhiHits) { + result.phiposerr_a = seg_a.localCovariance()(Trk::locX, Trk::locX); + result.phidirerr_a = seg_a.localCovariance()(Trk::phi, Trk::phi); } else { - result.phiposerr_a = 99999.; - result.phidirerr_a = 99999.; + result.phiposerr_a = 99999.; + result.phidirerr_a = 99999.; } -// check presence of phi hits on segment b + // check presence of phi hits on segment b ContainPhiHits = false; - hit = seg_b.containedMeasurements().begin(); - hit_end = seg_b.containedMeasurements().end(); - for( ;hit!=hit_end;++hit ){ - Identifier id; - const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(*hit); - if( rot ) id = rot->identify(); - else{ - const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*hit); - if( crot ) id = crot->containedROTs().front()->identify(); - } - if( !id.is_valid() ) continue; - if(m_idHelperSvc->measuresPhi(id)) { - ContainPhiHits = true; - break; - } + hit = seg_b.containedMeasurements().begin(); + hit_end = seg_b.containedMeasurements().end(); + for (; hit != hit_end; ++hit) { + Identifier id; + const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(*hit); + if (rot) + id = rot->identify(); + else { + const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*hit); + if (crot) id = crot->containedROTs().front()->identify(); + } + if (!id.is_valid()) continue; + if (m_idHelperSvc->measuresPhi(id)) { + ContainPhiHits = true; + break; + } } - if(ContainPhiHits) { - result.phiposerr_b = seg_b.localCovariance()(Trk::locX,Trk::locX); - result.phidirerr_b = seg_b.localCovariance()(Trk::phi,Trk::phi); + if (ContainPhiHits) { + result.phiposerr_b = seg_b.localCovariance()(Trk::locX, Trk::locX); + result.phidirerr_b = seg_b.localCovariance()(Trk::phi, Trk::phi); } else { - result.phiposerr_b = 99999.; - result.phidirerr_b = 99999.; + result.phiposerr_b = 99999.; + result.phidirerr_b = 99999.; } result.shorttube_a = 99999.; - if( m_idHelperSvc->isMdt(chid_a) ){ - //make shortest tube calculations - std::pair<Amg::Vector3D, Amg::Vector3D> stseg1 = getShortestTubePos(seg_a); - double shorttube_lx_a = stseg1.first.x(); - double shorttube_ly_a = stseg1.first.y(); - double shorttube_rx_a = stseg1.second.x(); - double shorttube_ry_a = stseg1.second.y(); - - double dist_x_la = seg_a.globalPosition().x() - shorttube_lx_a; - double dist_x_ra = seg_a.globalPosition().x() - shorttube_rx_a; - - double dist_y_la = seg_a.globalPosition().y() - shorttube_ly_a; - double dist_y_ra = seg_a.globalPosition().y() - shorttube_ry_a; - - double dist_la = sqrt(dist_x_la*dist_x_la + dist_y_la*dist_y_la); - double dist_ra = sqrt(dist_x_ra*dist_x_ra + dist_y_ra*dist_y_ra); - - if(dist_la>=dist_ra) result.shorttube_a = dist_ra; - else result.shorttube_a = dist_la; + if (m_idHelperSvc->isMdt(chid_a)) { + // make shortest tube calculations + std::pair<Amg::Vector3D, Amg::Vector3D> stseg1 = getShortestTubePos(seg_a); + double shorttube_lx_a = stseg1.first.x(); + double shorttube_ly_a = stseg1.first.y(); + double shorttube_rx_a = stseg1.second.x(); + double shorttube_ry_a = stseg1.second.y(); + + double dist_x_la = seg_a.globalPosition().x() - shorttube_lx_a; + double dist_x_ra = seg_a.globalPosition().x() - shorttube_rx_a; + + double dist_y_la = seg_a.globalPosition().y() - shorttube_ly_a; + double dist_y_ra = seg_a.globalPosition().y() - shorttube_ry_a; + + double dist_la = sqrt(dist_x_la * dist_x_la + dist_y_la * dist_y_la); + double dist_ra = sqrt(dist_x_ra * dist_x_ra + dist_y_ra * dist_y_ra); + + if (dist_la >= dist_ra) + result.shorttube_a = dist_ra; + else + result.shorttube_a = dist_la; } result.shorttube_b = 99999.; - if( m_idHelperSvc->isMdt(chid_b) ){ - std::pair<Amg::Vector3D, Amg::Vector3D> stseg2 = getShortestTubePos(seg_b); - double shorttube_lx_b = stseg2.first.x(); - double shorttube_ly_b = stseg2.first.y(); - double shorttube_rx_b = stseg2.second.x(); - double shorttube_ry_b = stseg2.second.y(); - - double dist_x_lb = seg_b.globalPosition().x() - shorttube_lx_b; - double dist_x_rb = seg_b.globalPosition().x() - shorttube_rx_b; - - double dist_y_lb = seg_b.globalPosition().y() - shorttube_ly_b; - double dist_y_rb = seg_b.globalPosition().y() - shorttube_ry_b; - - double dist_lb = sqrt(dist_x_lb*dist_x_lb + dist_y_lb*dist_y_lb); - double dist_rb = sqrt(dist_x_rb*dist_x_rb + dist_y_rb*dist_y_rb); - - if(dist_lb>=dist_rb) result.shorttube_b=dist_rb; - else result.shorttube_b=dist_lb; + if (m_idHelperSvc->isMdt(chid_b)) { + std::pair<Amg::Vector3D, Amg::Vector3D> stseg2 = getShortestTubePos(seg_b); + double shorttube_lx_b = stseg2.first.x(); + double shorttube_ly_b = stseg2.first.y(); + double shorttube_rx_b = stseg2.second.x(); + double shorttube_ry_b = stseg2.second.y(); + + double dist_x_lb = seg_b.globalPosition().x() - shorttube_lx_b; + double dist_x_rb = seg_b.globalPosition().x() - shorttube_rx_b; + + double dist_y_lb = seg_b.globalPosition().y() - shorttube_ly_b; + double dist_y_rb = seg_b.globalPosition().y() - shorttube_ry_b; + + double dist_lb = sqrt(dist_x_lb * dist_x_lb + dist_y_lb * dist_y_lb); + double dist_rb = sqrt(dist_x_rb * dist_x_rb + dist_y_rb * dist_y_rb); + + if (dist_lb >= dist_rb) + result.shorttube_b = dist_rb; + else + result.shorttube_b = dist_lb; } result.matchFlag = true; return result; - } - - std::pair<Amg::Vector3D, Amg::Vector3D> MuonSegmentPairMatchingTool::getShortestTubePos(const Muon::MuonSegment& seg) const - { - const Muon::MdtDriftCircleOnTrack* shortestMdt = 0; - double storedLength = 999999; - - //loop over hits, cast each hit to drift circle - - const std::vector<const Trk::MeasurementBase*>& rioVec = seg.containedMeasurements(); - std::vector<const Trk::MeasurementBase*>::const_iterator it = rioVec.begin(); +} + +std::pair<Amg::Vector3D, Amg::Vector3D> +MuonSegmentPairMatchingTool::getShortestTubePos(const Muon::MuonSegment& seg) const +{ + const Muon::MdtDriftCircleOnTrack* shortestMdt = 0; + double storedLength = 999999; + + // loop over hits, cast each hit to drift circle + + const std::vector<const Trk::MeasurementBase*>& rioVec = seg.containedMeasurements(); + std::vector<const Trk::MeasurementBase*>::const_iterator it = rioVec.begin(); std::vector<const Trk::MeasurementBase*>::const_iterator it_end = rioVec.end(); - - for( ;it!=it_end; ++it ){ - const Muon::MdtDriftCircleOnTrack* mdt = dynamic_cast<const Muon::MdtDriftCircleOnTrack*>(*it); - if( !mdt ) continue; - const MuonGM::MdtReadoutElement* roe = mdt->detectorElement(); - if( !roe) continue; - - //sanity check with getActiveTubeLength - int layer = m_idHelperSvc->mdtIdHelper().tubeLayer(mdt->identify()); - int tube = m_idHelperSvc->mdtIdHelper().tube(mdt->identify()); - double halfLength = 0.5*roe->getActiveTubeLength(layer,tube); - - if(2*halfLength > storedLength) continue; - - storedLength= halfLength; - shortestMdt = mdt; + for (; it != it_end; ++it) { + const Muon::MdtDriftCircleOnTrack* mdt = dynamic_cast<const Muon::MdtDriftCircleOnTrack*>(*it); + if (!mdt) continue; + const MuonGM::MdtReadoutElement* roe = mdt->detectorElement(); + if (!roe) continue; + + // sanity check with getActiveTubeLength + int layer = m_idHelperSvc->mdtIdHelper().tubeLayer(mdt->identify()); + int tube = m_idHelperSvc->mdtIdHelper().tube(mdt->identify()); + double halfLength = 0.5 * roe->getActiveTubeLength(layer, tube); + + if (2 * halfLength > storedLength) continue; + + storedLength = halfLength; + shortestMdt = mdt; } std::pair<Amg::Vector3D, Amg::Vector3D> shortpos; - Amg::Vector2D lp(0,storedLength); - if(shortestMdt) shortestMdt->associatedSurface().localToGlobal(lp,Amg::Vector3D::UnitZ(),shortpos.first); + Amg::Vector2D lp(0, storedLength); + if (shortestMdt) shortestMdt->associatedSurface().localToGlobal(lp, Amg::Vector3D::UnitZ(), shortpos.first); lp[1] = -storedLength; - if(shortestMdt) shortestMdt->associatedSurface().localToGlobal(lp,Amg::Vector3D::UnitZ(),shortpos.second); + if (shortestMdt) shortestMdt->associatedSurface().localToGlobal(lp, Amg::Vector3D::UnitZ(), shortpos.second); return shortpos; - } } +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentPairMatchingTool.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentPairMatchingTool.h index b24c6203a62491f9368ad579a32e129fa6c2b36f..47bf454d4b369fe20c33eacb586f1ff978dfb220 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentPairMatchingTool.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentMatchingTools/src/MuonSegmentPairMatchingTool.h @@ -5,47 +5,56 @@ #ifndef MUON_MUONSEGMENTPAIRMATCHINGTOOL_H #define MUON_MUONSEGMENTPAIRMATCHINGTOOL_H -#include "MuonSegmentMakerToolInterfaces/IMuonSegmentPairMatchingTool.h" - #include "AthenaBaseComps/AthAlgTool.h" -#include "GaudiKernel/ToolHandle.h" #include "GaudiKernel/ServiceHandle.h" - -#include "TrkTrack/TrackCollection.h" -#include "MuonRecHelperTools/IMuonEDMHelperSvc.h" +#include "GaudiKernel/ToolHandle.h" #include "MuonIdHelpers/IMuonIdHelperSvc.h" +#include "MuonRecHelperTools/IMuonEDMHelperSvc.h" +#include "MuonSegmentMakerToolInterfaces/IMuonSegmentPairMatchingTool.h" +#include "TrkTrack/TrackCollection.h" namespace Muon { - - class MuonSegment; - class MuonEDMPrinterTool; - /** - @brief tool to match segments - */ - class MuonSegmentPairMatchingTool : virtual public IMuonSegmentPairMatchingTool, public AthAlgTool { + +class MuonSegment; +class MuonEDMPrinterTool; +/** + @brief tool to match segments +*/ +class MuonSegmentPairMatchingTool : virtual public IMuonSegmentPairMatchingTool, public AthAlgTool { public: /** @brief constructor */ - MuonSegmentPairMatchingTool(const std::string&,const std::string&,const IInterface*); + MuonSegmentPairMatchingTool(const std::string&, const std::string&, const IInterface*); /** @brief destructor */ - virtual ~MuonSegmentPairMatchingTool () {}; - + virtual ~MuonSegmentPairMatchingTool(){}; + /** @brief AlgTool initilize */ StatusCode initialize(); /** @brief performance match and return result */ - SegmentMatchResult matchResult( const MuonSegment& seg1, const MuonSegment& seg2 ) const; + SegmentMatchResult matchResult(const MuonSegment& seg1, const MuonSegment& seg2) const; std::pair<Amg::Vector3D, Amg::Vector3D> getShortestTubePos(const Muon::MuonSegment& seg) const; private: - - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - ServiceHandle<IMuonEDMHelperSvc> m_edmHelperSvc {this, "edmHelper", - "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", - "Handle to the service providing the IMuonEDMHelperSvc interface" }; //!< EDM Helper tool - ToolHandle<MuonEDMPrinterTool> m_printer; //!< EDM printer tool - }; - -} + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; + ServiceHandle<IMuonEDMHelperSvc> m_edmHelperSvc{ + this, + "edmHelper", + "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", + "Handle to the service providing the IMuonEDMHelperSvc interface", + }; //!< EDM Helper tool + + ToolHandle<MuonEDMPrinterTool> m_printer{ + this, + "Printer", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; //!< EDM printer tool +}; + +} // namespace Muon #endif diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentCombinationCleanerTool.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentCombinationCleanerTool.cxx index 87184d35ce3c75708abd2ef7b84548232c02b6be..079a2338e0caec4c0da65c9cac541bd6afb68684 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentCombinationCleanerTool.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentCombinationCleanerTool.cxx @@ -3,472 +3,495 @@ */ #include "MuonSegmentCombinationCleanerTool.h" - + +#include <algorithm> #include <iostream> #include <sstream> #include <vector> -#include <algorithm> +#include "MuonPattern/MuonPatternCombination.h" #include "MuonSegment/MuonSegment.h" #include "MuonSegment/MuonSegmentCombination.h" #include "MuonSegment/MuonSegmentCombinationCollection.h" - -#include "MuonPattern/MuonPatternCombination.h" - -#include "MuonSegmentMakerUtils/MuonSegmentKey.h" #include "MuonSegmentMakerUtils/CompareMuonSegmentKeys.h" - +#include "MuonSegmentMakerUtils/MuonSegmentKey.h" #include "TrkEventPrimitives/FitQuality.h" namespace Muon { - MuonSegmentCombinationCleanerTool::MuonSegmentCombinationCleanerTool(const std::string& t,const std::string& n,const IInterface* p) : - AthAlgTool(t,n,p), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"), - m_overlapRemovalTool("Muon::MuonSegmentOverlapRemovalTool/MuonSegmentOverlapRemovalTool", this) - { +MuonSegmentCombinationCleanerTool::MuonSegmentCombinationCleanerTool(const std::string& t, const std::string& n, + const IInterface* p) + : AthAlgTool(t, n, p) +{ declareInterface<IMuonSegmentCombinationCleanerTool>(this); + declareProperty("MergeAllCombis", m_mergeAllCombis = false, "merge all combinations into one large combination"); +} - declareProperty("SegmentOverlapRemovalTool", m_overlapRemovalTool, "tool to removal overlaps in segment combinations" ); - declareProperty("MergeAllCombis", m_mergeAllCombis = false, "merge all combinations into one large combination" ); - - } - - StatusCode MuonSegmentCombinationCleanerTool::initialize() - { - ATH_CHECK(AlgTool::initialize()); +StatusCode +MuonSegmentCombinationCleanerTool::initialize() +{ + ATH_CHECK(AlgTool::initialize()); ATH_MSG_VERBOSE(" MuonSegmentCombinationCleanerTool::Initializing "); - + ATH_CHECK(m_printer.retrieve()); ATH_CHECK(m_edmHelperSvc.retrieve()); ATH_CHECK(m_idHelperSvc.retrieve()); ATH_CHECK(m_overlapRemovalTool.retrieve()); ATH_MSG_VERBOSE("End of Initializing"); - return StatusCode::SUCCESS; - } + return StatusCode::SUCCESS; +} - std::unique_ptr<MuonSegmentCombinationCollection> MuonSegmentCombinationCleanerTool::clean( const MuonSegmentCombinationCollection& combiCol, - MuonSegmentCombPatternCombAssociationMap* segPattMap ){ +std::unique_ptr<MuonSegmentCombinationCollection> +MuonSegmentCombinationCleanerTool::clean(const MuonSegmentCombinationCollection& combiCol, + MuonSegmentCombPatternCombAssociationMap* segPattMap) +{ std::unique_ptr<MuonSegmentCombinationCollection> combiCleanCol(new MuonSegmentCombinationCollection); - - cleanAndMergeCombis(combiCol,combiCleanCol.get(),segPattMap); - + + cleanAndMergeCombis(combiCol, combiCleanCol.get(), segPattMap); + return combiCleanCol; - } +} - void MuonSegmentCombinationCleanerTool::cleanAndMergeCombis( const MuonSegmentCombinationCollection& combiCol, - MuonSegmentCombinationCollection* combiCleanCol, - MuonSegmentCombPatternCombAssociationMap* segPattMap) { +void +MuonSegmentCombinationCleanerTool::cleanAndMergeCombis(const MuonSegmentCombinationCollection& combiCol, + MuonSegmentCombinationCollection* combiCleanCol, + MuonSegmentCombPatternCombAssociationMap* segPattMap) +{ - ATH_MSG_DEBUG(" cleaning combis " << combiCol.size() ); + ATH_MSG_DEBUG(" cleaning combis " << combiCol.size()); - MuonSegmentCombinationCollection::const_iterator cit = combiCol.begin(); + MuonSegmentCombinationCollection::const_iterator cit = combiCol.begin(); MuonSegmentCombinationCollection::const_iterator cit_end = combiCol.end(); std::vector<MuonSegmentCombiSummary> summaries; - for(; cit!=cit_end;++cit ){ - const Muon::MuonSegmentCombination* combi = *cit; - if( !combi ) { - ATH_MSG_INFO(" empty MuonSegmentCombination!!! "); - continue; - } - - MuonSegmentCombiSummary summary = createSummary( *combi ); - ATH_MSG_VERBOSE( print(summary) ); - - if( summary.stations.size() < 2 ){ - - // keep combination if Endcap middle - if( summary.stations.count(MuonStationIndex::EM) ){ - - ATH_MSG_VERBOSE(" Keeping single station endcap middle MuonSegmentCombination "); - - }else{ - - ATH_MSG_DEBUG(" MuonSegmentCombination has too few station layers, rejecting "); - continue; - } - } - - if( summary.stationsGood.size() == 0 ){ - ATH_MSG_DEBUG(" MuonSegmentCombination has no station layer with good segment, rejecting "); - continue; - } - - if( !subSetOfPrevious(summary,summaries) ){ - summaries.push_back(summary); - } - } - - std::vector<MuonSegmentCombiSummary>::iterator sit = summaries.begin(); - std::vector<MuonSegmentCombiSummary>::iterator sit_end = summaries.end(); - for( ;sit!=sit_end;++sit ){ - + for (; cit != cit_end; ++cit) { + const Muon::MuonSegmentCombination* combi = *cit; + if (!combi) { + ATH_MSG_INFO(" empty MuonSegmentCombination!!! "); + continue; + } - // check whether there is an original, if so pass the pointer else clone the combi as it comes from the input collection - const MuonSegmentCombination* originalCombi = 0; - MuonSegmentCombination* newCombi = 0; - if( sit->combiOriginal ){ + MuonSegmentCombiSummary summary = createSummary(*combi); + ATH_MSG_VERBOSE(print(summary)); - // HACK: cast away const as DataVector expects no-const pointer - newCombi = const_cast<MuonSegmentCombination*>(&sit->segmentCombination()); - if( !newCombi ){ - ATH_MSG_INFO(" const_cast to MuonSegmentCombination failed "); - continue; - } + if (summary.stations.size() < 2) { - originalCombi = sit->combiOriginal; + // keep combination if Endcap middle + if (summary.stations.count(MuonStationIndex::EM)) { + ATH_MSG_VERBOSE(" Keeping single station endcap middle MuonSegmentCombination "); - }else{ - originalCombi = &sit->segmentCombination(); - newCombi = new MuonSegmentCombination(sit->segmentCombination()); - } + } else { - MuonSegmentCombination* finalCombi = const_cast<MuonSegmentCombination*>(m_overlapRemovalTool->removeDuplicates( *newCombi )); - if( finalCombi != newCombi ) delete newCombi; + ATH_MSG_DEBUG(" MuonSegmentCombination has too few station layers, rejecting "); + continue; + } + } - // lookup the patterncombi and add association - unsigned int count = segPattMap->count(originalCombi); - if(count != 1 ){ - ATH_MSG_INFO(" This list should only have one entry!! "); - }else{ - std::pair<MuonSegmentCombPatternCombAssociationMap::const_iterator, MuonSegmentCombPatternCombAssociationMap::const_iterator> range = segPattMap->equal_range(originalCombi); - const Muon::MuonPatternCombination* pat = (range.first)->second; - if( pat ) segPattMap->insert(std::make_pair(finalCombi, pat)); - else ATH_MSG_INFO(" The pattern pointer should never be zero!!!! "); - } + if (summary.stationsGood.size() == 0) { + ATH_MSG_DEBUG(" MuonSegmentCombination has no station layer with good segment, rejecting "); + continue; + } - combiCleanCol->push_back( finalCombi ); - + if (!subSetOfPrevious(summary, summaries)) { + summaries.push_back(summary); + } + } + std::vector<MuonSegmentCombiSummary>::iterator sit = summaries.begin(); + std::vector<MuonSegmentCombiSummary>::iterator sit_end = summaries.end(); + for (; sit != sit_end; ++sit) { + + + // check whether there is an original, if so pass the pointer else clone the combi as it comes from the input + // collection + const MuonSegmentCombination* originalCombi = 0; + MuonSegmentCombination* newCombi = 0; + if (sit->combiOriginal) { + + // HACK: cast away const as DataVector expects no-const pointer + newCombi = const_cast<MuonSegmentCombination*>(&sit->segmentCombination()); + if (!newCombi) { + ATH_MSG_INFO(" const_cast to MuonSegmentCombination failed "); + continue; + } + + originalCombi = sit->combiOriginal; + + + } else { + originalCombi = &sit->segmentCombination(); + newCombi = new MuonSegmentCombination(sit->segmentCombination()); + } + + MuonSegmentCombination* finalCombi = + const_cast<MuonSegmentCombination*>(m_overlapRemovalTool->removeDuplicates(*newCombi)); + if (finalCombi != newCombi) delete newCombi; + + // lookup the patterncombi and add association + unsigned int count = segPattMap->count(originalCombi); + if (count != 1) { + ATH_MSG_INFO(" This list should only have one entry!! "); + } else { + std::pair<MuonSegmentCombPatternCombAssociationMap::const_iterator, + MuonSegmentCombPatternCombAssociationMap::const_iterator> + range = segPattMap->equal_range(originalCombi); + const Muon::MuonPatternCombination* pat = (range.first)->second; + if (pat) + segPattMap->insert(std::make_pair(finalCombi, pat)); + else + ATH_MSG_INFO(" The pattern pointer should never be zero!!!! "); + } + + combiCleanCol->push_back(finalCombi); } - } +} + + +bool +MuonSegmentCombinationCleanerTool::subSetOfPrevious(MuonSegmentCombiSummary& summary, + std::vector<MuonSegmentCombiSummary>& summaries) const +{ + + if (summaries.empty()) return false; - - bool MuonSegmentCombinationCleanerTool::subSetOfPrevious( MuonSegmentCombiSummary& summary, std::vector<MuonSegmentCombiSummary>& summaries) const { - - if( summaries.empty() ) return false; - ATH_MSG_DEBUG(" comparing combi with aleady handled ones "); bool hasOverlap = false; - std::vector<MuonSegmentCombiSummary>::iterator sit = summaries.begin(); + std::vector<MuonSegmentCombiSummary>::iterator sit = summaries.begin(); std::vector<MuonSegmentCombiSummary>::iterator sit_end = summaries.end(); - for( ;sit!=sit_end;++sit ){ - - MuonSegmentCombiOverlapSummary overlap = calculateOverlap( summary, *sit ); - - // simplest case: no subsets - if( overlap.subsetFirst.empty() && overlap.subsetSecond.empty() ) { - - // no overlap - if( overlap.shared.empty() ) { - if( !m_mergeAllCombis ) continue; - } - // complete overlap, keep previous - if( overlap.uniqueFirst.empty() && overlap.uniqueSecond.empty() ){ - ATH_MSG_VERBOSE(" -> complete overlap, keeping first "); - hasOverlap = true; - break; - } - } - - // second simple case, no unique segments in first and no subsets in second combi - if( overlap.uniqueFirst.empty() && overlap.subsetSecond.empty() ){ - - ATH_MSG_VERBOSE(" -> keeping selected combi "); - hasOverlap = true; - break; - }else if( overlap.uniqueSecond.empty() && overlap.subsetFirst.empty() ){ - - ATH_MSG_VERBOSE(" -> replacing selected combi "); - - if( sit->combiOriginal ) { - // copy pointer to original combi, delete combi - delete sit->m_combi; - } - *sit = summary; - hasOverlap = true; - break; - } - - // large overlap - - unsigned int overlappingSegments1 = overlap.subsetFirst.size() + overlap.shared.size(); - unsigned int overlappingSegments2 = overlap.subsetSecond.size() + overlap.shared.size(); - - unsigned int uniqueSegments1 = overlap.uniqueFirst.size(); - unsigned int uniqueSegments2 = overlap.uniqueSecond.size(); - if( overlappingSegments1 > uniqueSegments1 || overlappingSegments2 > uniqueSegments2 || m_mergeAllCombis ) { - ATH_MSG_VERBOSE(" -> large overlap, merge candidate "); - - // set to make sure we are not adding segments twice - std::set<MuonSegment*> addedSegments; - std::vector< std::vector<MuonSegment* > > segmentsPerChamberLayer(MuonStationIndex::ChIndexMax); - - // first add shared segments, take one with best chi2 - std::vector< std::pair<MuonSegment*,MuonSegment*> >::iterator shit = overlap.shared.begin(); - std::vector< std::pair<MuonSegment*,MuonSegment*> >::iterator shit_end = overlap.shared.end(); - for( ;shit!=shit_end;++shit ){ - - // select segment with best chi2 - const Trk::FitQuality* fq1 =shit->first->fitQuality(); - const Trk::FitQuality* fq2 =shit->second->fitQuality(); - double chi2First = fq1 ? fq1->chiSquared() : 1e10; - double chi2Second = fq2 ? fq2->chiSquared() : 1e10; - MuonSegment* bestSegment = chi2First < chi2Second ? shit->first : shit->second; - - // check whether already added - if( addedSegments.count(bestSegment) ) continue; - addedSegments.insert(bestSegment); - Identifier chId = m_edmHelperSvc->chamberId( *bestSegment ); - MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chId); - segmentsPerChamberLayer[chIndex].push_back(bestSegment); - } - - std::vector<MuonSegment*>::iterator uit = overlap.uniqueFirst.begin(); - std::vector<MuonSegment*>::iterator uit_end = overlap.uniqueFirst.end(); - for( ;uit!=uit_end;++uit ){ - // check whether already added - MuonSegment* bestSegment = *uit; - - // check whether already added - if( addedSegments.count(bestSegment) ) continue; - addedSegments.insert(bestSegment); - Identifier chId = m_edmHelperSvc->chamberId( *bestSegment ); - MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chId); - segmentsPerChamberLayer[chIndex].push_back(bestSegment); - } - - uit = overlap.uniqueSecond.begin(); - uit_end = overlap.uniqueSecond.end(); - for( ;uit!=uit_end;++uit ){ - // check whether already added - MuonSegment* bestSegment = *uit; - - // check whether already added - if( addedSegments.count(bestSegment) ) continue; - addedSegments.insert(bestSegment); - Identifier chId = m_edmHelperSvc->chamberId( *bestSegment ); - MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chId); - segmentsPerChamberLayer[chIndex].push_back(bestSegment); - } - - shit = overlap.subsetFirst.begin(); - shit_end = overlap.subsetFirst.end(); - for( ;shit!=shit_end;++shit ){ - // check whether already added - MuonSegment* bestSegment = shit->second; - - // check whether already added - if( addedSegments.count(bestSegment) ) continue; - addedSegments.insert(bestSegment); - Identifier chId = m_edmHelperSvc->chamberId( *bestSegment ); - MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chId); - segmentsPerChamberLayer[chIndex].push_back(bestSegment); - } - - shit = overlap.subsetSecond.begin(); - shit_end = overlap.subsetSecond.end(); - for( ;shit!=shit_end;++shit ){ - // check whether already added - MuonSegment* bestSegment = shit->first; - - // check whether already added - if( addedSegments.count(bestSegment) ) continue; - addedSegments.insert(bestSegment); - Identifier chId = m_edmHelperSvc->chamberId( *bestSegment ); - MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chId); - segmentsPerChamberLayer[chIndex].push_back(bestSegment); - } - - // now create new combi - MuonSegmentCombination* newCombi = new MuonSegmentCombination(); - - // loop over layers and add segments - std::vector< std::vector<MuonSegment*> >::iterator chit = segmentsPerChamberLayer.begin(); - std::vector< std::vector<MuonSegment*> >::iterator chit_end = segmentsPerChamberLayer.end(); - for( ;chit!=chit_end;++chit ){ - - // skip empty ones - if( chit->empty() ) continue; - - std::unique_ptr<std::vector< std::unique_ptr<MuonSegment> > > segVec(new std::vector< std::unique_ptr<MuonSegment> >()); - segVec->reserve( chit->size() ); - std::vector<MuonSegment*>::iterator segit = chit->begin(); - std::vector<MuonSegment*>::iterator segit_end = chit->end(); - for( ;segit!=segit_end;++segit ) segVec->push_back( std::unique_ptr<MuonSegment>((*segit)->clone()) ); - newCombi->addSegments( std::move(segVec) ); - } - - // create new summary - MuonSegmentCombiSummary newSummary = createSummary( *newCombi ); - // hack to keep link with original combi - if( summary.combiOriginal ) { - // copy pointer to original combi, delete combi - newSummary.combiOriginal = summary.combiOriginal; - delete summary.m_combi; - }else{ - // set pointer to original - newSummary.combiOriginal = summary.m_combi; - } - if( sit->combiOriginal ) { - // copy pointer to original combi, delete combi - delete sit->m_combi; - } - - ATH_MSG_VERBOSE(" -> merged combis "); - *sit = newSummary; - hasOverlap = true; - break; - } + for (; sit != sit_end; ++sit) { + + MuonSegmentCombiOverlapSummary overlap = calculateOverlap(summary, *sit); + + // simplest case: no subsets + if (overlap.subsetFirst.empty() && overlap.subsetSecond.empty()) { + + // no overlap + if (overlap.shared.empty()) { + if (!m_mergeAllCombis) continue; + } + // complete overlap, keep previous + if (overlap.uniqueFirst.empty() && overlap.uniqueSecond.empty()) { + ATH_MSG_VERBOSE(" -> complete overlap, keeping first "); + hasOverlap = true; + break; + } + } + + // second simple case, no unique segments in first and no subsets in second combi + if (overlap.uniqueFirst.empty() && overlap.subsetSecond.empty()) { + + ATH_MSG_VERBOSE(" -> keeping selected combi "); + hasOverlap = true; + break; + } else if (overlap.uniqueSecond.empty() && overlap.subsetFirst.empty()) { + + ATH_MSG_VERBOSE(" -> replacing selected combi "); + + if (sit->combiOriginal) { + // copy pointer to original combi, delete combi + delete sit->m_combi; + } + *sit = summary; + hasOverlap = true; + break; + } + + // large overlap + + unsigned int overlappingSegments1 = overlap.subsetFirst.size() + overlap.shared.size(); + unsigned int overlappingSegments2 = overlap.subsetSecond.size() + overlap.shared.size(); + + unsigned int uniqueSegments1 = overlap.uniqueFirst.size(); + unsigned int uniqueSegments2 = overlap.uniqueSecond.size(); + if (overlappingSegments1 > uniqueSegments1 || overlappingSegments2 > uniqueSegments2 || m_mergeAllCombis) { + ATH_MSG_VERBOSE(" -> large overlap, merge candidate "); + + // set to make sure we are not adding segments twice + std::set<MuonSegment*> addedSegments; + std::vector<std::vector<MuonSegment*> > segmentsPerChamberLayer(MuonStationIndex::ChIndexMax); + + // first add shared segments, take one with best chi2 + std::vector<std::pair<MuonSegment*, MuonSegment*> >::iterator sh_iter = overlap.shared.begin(); + std::vector<std::pair<MuonSegment*, MuonSegment*> >::iterator sh_iter_end = overlap.shared.end(); + for (; sh_iter != sh_iter_end; ++sh_iter) { + + // select segment with best chi2 + const Trk::FitQuality* fq1 = sh_iter->first->fitQuality(); + const Trk::FitQuality* fq2 = sh_iter->second->fitQuality(); + double chi2First = fq1 ? fq1->chiSquared() : 1e10; + double chi2Second = fq2 ? fq2->chiSquared() : 1e10; + MuonSegment* bestSegment = chi2First < chi2Second ? sh_iter->first : sh_iter->second; + + // check whether already added + if (addedSegments.count(bestSegment)) continue; + addedSegments.insert(bestSegment); + Identifier chId = m_edmHelperSvc->chamberId(*bestSegment); + MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chId); + segmentsPerChamberLayer[chIndex].push_back(bestSegment); + } + + std::vector<MuonSegment*>::iterator uit = overlap.uniqueFirst.begin(); + std::vector<MuonSegment*>::iterator uit_end = overlap.uniqueFirst.end(); + for (; uit != uit_end; ++uit) { + // check whether already added + MuonSegment* bestSegment = *uit; + + // check whether already added + if (addedSegments.count(bestSegment)) continue; + addedSegments.insert(bestSegment); + Identifier chId = m_edmHelperSvc->chamberId(*bestSegment); + MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chId); + segmentsPerChamberLayer[chIndex].push_back(bestSegment); + } + + uit = overlap.uniqueSecond.begin(); + uit_end = overlap.uniqueSecond.end(); + for (; uit != uit_end; ++uit) { + // check whether already added + MuonSegment* bestSegment = *uit; + + // check whether already added + if (addedSegments.count(bestSegment)) continue; + addedSegments.insert(bestSegment); + Identifier chId = m_edmHelperSvc->chamberId(*bestSegment); + MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chId); + segmentsPerChamberLayer[chIndex].push_back(bestSegment); + } + + sh_iter = overlap.subsetFirst.begin(); + sh_iter_end = overlap.subsetFirst.end(); + for (; sh_iter != sh_iter_end; ++sh_iter) { + // check whether already added + MuonSegment* bestSegment = sh_iter->second; + + // check whether already added + if (addedSegments.count(bestSegment)) continue; + addedSegments.insert(bestSegment); + Identifier chId = m_edmHelperSvc->chamberId(*bestSegment); + MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chId); + segmentsPerChamberLayer[chIndex].push_back(bestSegment); + } + + sh_iter = overlap.subsetSecond.begin(); + sh_iter_end = overlap.subsetSecond.end(); + for (; sh_iter != sh_iter_end; ++sh_iter) { + // check whether already added + MuonSegment* bestSegment = sh_iter->first; + + // check whether already added + if (addedSegments.count(bestSegment)) continue; + addedSegments.insert(bestSegment); + Identifier chId = m_edmHelperSvc->chamberId(*bestSegment); + MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chId); + segmentsPerChamberLayer[chIndex].push_back(bestSegment); + } + + // now create new combi + MuonSegmentCombination* newCombi = new MuonSegmentCombination(); + + // loop over layers and add segments + std::vector<std::vector<MuonSegment*> >::iterator chit = segmentsPerChamberLayer.begin(); + std::vector<std::vector<MuonSegment*> >::iterator chit_end = segmentsPerChamberLayer.end(); + for (; chit != chit_end; ++chit) { + + // skip empty ones + if (chit->empty()) continue; + + std::unique_ptr<std::vector<std::unique_ptr<MuonSegment> > > segVec( + new std::vector<std::unique_ptr<MuonSegment> >()); + segVec->reserve(chit->size()); + std::vector<MuonSegment*>::iterator segit = chit->begin(); + std::vector<MuonSegment*>::iterator segit_end = chit->end(); + for (; segit != segit_end; ++segit) segVec->push_back(std::unique_ptr<MuonSegment>((*segit)->clone())); + newCombi->addSegments(std::move(segVec)); + } + + // create new summary + MuonSegmentCombiSummary newSummary = createSummary(*newCombi); + // hack to keep link with original combi + if (summary.combiOriginal) { + // copy pointer to original combi, delete combi + newSummary.combiOriginal = summary.combiOriginal; + delete summary.m_combi; + } else { + // set pointer to original + newSummary.combiOriginal = summary.m_combi; + } + if (sit->combiOriginal) { + // copy pointer to original combi, delete combi + delete sit->m_combi; + } + + ATH_MSG_VERBOSE(" -> merged combis "); + *sit = newSummary; + hasOverlap = true; + break; + } } return hasOverlap; - } - - - MuonSegmentCombiOverlapSummary MuonSegmentCombinationCleanerTool::calculateOverlap( MuonSegmentCombiSummary& summary1, - MuonSegmentCombiSummary& summary2 ) const { - - ATH_MSG_DEBUG(" calculating overlap, size first " << summary1.nsegments << " size second " << summary2.nsegments ); - +} + + +MuonSegmentCombiOverlapSummary +MuonSegmentCombinationCleanerTool::calculateOverlap(MuonSegmentCombiSummary& summary1, + MuonSegmentCombiSummary& summary2) const +{ + + ATH_MSG_DEBUG(" calculating overlap, size first " << summary1.nsegments << " size second " << summary2.nsegments); + MuonSegmentCombiOverlapSummary summary; - + // loop over all chamber layers and compare per layer - for( unsigned int i=0;i<MuonStationIndex::ChIndexMax; ++i ){ - - // get segment in chamber layer - MuonSegmentCombiSummary::SegVec& chamberVec1 = summary1.chamberSegments(i); - MuonSegmentCombiSummary::SegVec& chamberVec2 = summary2.chamberSegments(i); - - // if both no segments do nothing - if( chamberVec1.empty() && chamberVec2.empty() ) continue; - - // if both not empty compare the two, exception for CSCs - if( !chamberVec1.empty() && !chamberVec2.empty() ) { - ATH_MSG_DEBUG(" resolving chambe layer " << MuonStationIndex::chName((MuonStationIndex::ChIndex)i) ); - - resolveLayerOverlap(chamberVec1,chamberVec2,summary); - - }else{ - if( !chamberVec1.empty() ) summary.uniqueFirst.insert(summary.uniqueFirst.begin(),chamberVec1.begin(),chamberVec1.end()); - if( !chamberVec2.empty() ) summary.uniqueSecond.insert(summary.uniqueSecond.begin(),chamberVec2.begin(),chamberVec2.end()); - } + for (unsigned int i = 0; i < MuonStationIndex::ChIndexMax; ++i) { + + // get segment in chamber layer + MuonSegmentCombiSummary::SegVec& chamberVec1 = summary1.chamberSegments(i); + MuonSegmentCombiSummary::SegVec& chamberVec2 = summary2.chamberSegments(i); + + // if both no segments do nothing + if (chamberVec1.empty() && chamberVec2.empty()) continue; + + // if both not empty compare the two, exception for CSCs + if (!chamberVec1.empty() && !chamberVec2.empty()) { + ATH_MSG_DEBUG(" resolving chambe layer " << MuonStationIndex::chName((MuonStationIndex::ChIndex)i)); + + resolveLayerOverlap(chamberVec1, chamberVec2, summary); + + } else { + if (!chamberVec1.empty()) + summary.uniqueFirst.insert(summary.uniqueFirst.begin(), chamberVec1.begin(), chamberVec1.end()); + if (!chamberVec2.empty()) + summary.uniqueSecond.insert(summary.uniqueSecond.begin(), chamberVec2.begin(), chamberVec2.end()); + } } - ATH_MSG_VERBOSE( print(summary) ); + ATH_MSG_VERBOSE(print(summary)); return summary; - } +} - void MuonSegmentCombinationCleanerTool::resolveLayerOverlap( const std::vector<MuonSegment*>& chamberVec1, - const std::vector<MuonSegment*>& chamberVec2, - MuonSegmentCombiOverlapSummary& summary) const { +void +MuonSegmentCombinationCleanerTool::resolveLayerOverlap(const std::vector<MuonSegment*>& chamberVec1, + const std::vector<MuonSegment*>& chamberVec2, + MuonSegmentCombiOverlapSummary& summary) const +{ CompareMuonSegmentKeys compareKeys; - std::vector<int> uniqueFirst(chamberVec1.size(),1); - std::vector<int> uniqueSecond(chamberVec2.size(),1); + std::vector<int> uniqueFirst(chamberVec1.size(), 1); + std::vector<int> uniqueSecond(chamberVec2.size(), 1); - unsigned int index1 = 0; - std::vector<MuonSegment*>::const_iterator sit1 = chamberVec1.begin(); + unsigned int index1 = 0; + std::vector<MuonSegment*>::const_iterator sit1 = chamberVec1.begin(); std::vector<MuonSegment*>::const_iterator sit1_end = chamberVec1.end(); - for( ;sit1!=sit1_end;++sit1,++index1 ){ - // identifier(s) of MDT chambers on segment - std::set<Identifier> chIds1 = m_edmHelperSvc->chamberIds( **sit1 ); - - unsigned int index2 = 0; - std::vector<MuonSegment*>::const_iterator sit2 = chamberVec2.begin(); - std::vector<MuonSegment*>::const_iterator sit2_end = chamberVec2.end(); - for( ;sit2!=sit2_end;++sit2,++index2 ){ - - if( !uniqueSecond[index2] ) continue; - - // identifier(s) of MDT chambers on segment - std::set<Identifier> chIds2 = m_edmHelperSvc->chamberIds( **sit2 ); - - // check whether chamber identifiers overlap - bool hasOverlap = false; - std::set<Identifier>::iterator idit = chIds2.begin(); - std::set<Identifier>::iterator idit_end = chIds2.end(); - for( ;idit!=idit_end;++idit ){ - if( chIds1.count(*idit) ){ - hasOverlap = true; - break; - } - } - // if no chamber identifier overlap continue with next segment - if( !hasOverlap ) { - continue; - } - // compare the hits on the two segments - - MuonSegmentKey key1(**sit1); - MuonSegmentKey key2(**sit2); - CompareMuonSegmentKeys::OverlapResult overlapResult = compareKeys(key1,key2); - ATH_MSG_VERBOSE(" overlap Result: " << compareKeys.print(overlapResult) ); - - if( overlapResult == CompareMuonSegmentKeys::Identical ) { - summary.shared.push_back( std::make_pair(*sit1,*sit2) ); - uniqueFirst[index1] = 0; - uniqueSecond[index2] = 0; - }else if( overlapResult == CompareMuonSegmentKeys::SuperSet ){ - summary.subsetSecond.push_back( std::make_pair(*sit1,*sit2) ); - uniqueFirst[index1] = 0; - uniqueSecond[index2] = 0; - }else if( overlapResult == CompareMuonSegmentKeys::SubSet ){ - summary.subsetFirst.push_back( std::make_pair(*sit1,*sit2) ); - uniqueFirst[index1] = 0; - uniqueSecond[index2] = 0; - }else if( overlapResult == CompareMuonSegmentKeys::PartialOverlap ){ - // keep partial overlaps for now.... - - // in case of full overlap in the MDTs - if( compareKeys.intersectionSize == compareKeys.segment1Size && compareKeys.intersectionSize == compareKeys.segment2Size ) { - - // mark as same if more than 75% overlap in trigger hits - double intersectFrac1 = compareKeys.intersectionSizeTrigger == 0 ? 0. : compareKeys.intersectionSizeTrigger/(double)compareKeys.segment1SizeTrigger; - double intersectFrac2 = compareKeys.intersectionSizeTrigger == 0 ? 0. : compareKeys.intersectionSizeTrigger/(double)compareKeys.segment2SizeTrigger; - double openingAngle = (*sit1)->globalDirection().dot((*sit2)->globalDirection()); - ATH_MSG_VERBOSE(" Partial overlap: (" << intersectFrac1 << "," << intersectFrac2 << "), opening angle " << openingAngle ); - if( intersectFrac1 > 0.75 && intersectFrac2 > 0.75 && openingAngle > 0.99 ){ - summary.shared.push_back( std::make_pair(*sit1,*sit2) ); - uniqueFirst[index1] = 0; - uniqueSecond[index2] = 0; - } - } - - }else if( overlapResult == CompareMuonSegmentKeys::NoOverlap ){ - - }else if( overlapResult == CompareMuonSegmentKeys::Unknown ){ - ATH_MSG_WARNING(" Got invalid return argument comparing segments: " << compareKeys.print(overlapResult) ); - } - } + for (; sit1 != sit1_end; ++sit1, ++index1) { + // identifier(s) of MDT chambers on segment + std::set<Identifier> chIds1 = m_edmHelperSvc->chamberIds(**sit1); + + unsigned int index2 = 0; + std::vector<MuonSegment*>::const_iterator sit2 = chamberVec2.begin(); + std::vector<MuonSegment*>::const_iterator sit2_end = chamberVec2.end(); + for (; sit2 != sit2_end; ++sit2, ++index2) { + + if (!uniqueSecond[index2]) continue; + + // identifier(s) of MDT chambers on segment + std::set<Identifier> chIds2 = m_edmHelperSvc->chamberIds(**sit2); + + // check whether chamber identifiers overlap + bool hasOverlap = false; + std::set<Identifier>::iterator idit = chIds2.begin(); + std::set<Identifier>::iterator idit_end = chIds2.end(); + for (; idit != idit_end; ++idit) { + if (chIds1.count(*idit)) { + hasOverlap = true; + break; + } + } + // if no chamber identifier overlap continue with next segment + if (!hasOverlap) { + continue; + } + // compare the hits on the two segments + + MuonSegmentKey key1(**sit1); + MuonSegmentKey key2(**sit2); + CompareMuonSegmentKeys::OverlapResult overlapResult = compareKeys(key1, key2); + ATH_MSG_VERBOSE(" overlap Result: " << compareKeys.print(overlapResult)); + + if (overlapResult == CompareMuonSegmentKeys::Identical) { + summary.shared.push_back(std::make_pair(*sit1, *sit2)); + uniqueFirst[index1] = 0; + uniqueSecond[index2] = 0; + } else if (overlapResult == CompareMuonSegmentKeys::SuperSet) { + summary.subsetSecond.push_back(std::make_pair(*sit1, *sit2)); + uniqueFirst[index1] = 0; + uniqueSecond[index2] = 0; + } else if (overlapResult == CompareMuonSegmentKeys::SubSet) { + summary.subsetFirst.push_back(std::make_pair(*sit1, *sit2)); + uniqueFirst[index1] = 0; + uniqueSecond[index2] = 0; + } else if (overlapResult == CompareMuonSegmentKeys::PartialOverlap) { + // keep partial overlaps for now.... + + // in case of full overlap in the MDTs + if (compareKeys.intersectionSize == compareKeys.segment1Size + && compareKeys.intersectionSize == compareKeys.segment2Size) + { + + // mark as same if more than 75% overlap in trigger hits + double intersectFrac1 = + compareKeys.intersectionSizeTrigger == 0 + ? 0. + : compareKeys.intersectionSizeTrigger / (double)compareKeys.segment1SizeTrigger; + double intersectFrac2 = + compareKeys.intersectionSizeTrigger == 0 + ? 0. + : compareKeys.intersectionSizeTrigger / (double)compareKeys.segment2SizeTrigger; + double openingAngle = (*sit1)->globalDirection().dot((*sit2)->globalDirection()); + ATH_MSG_VERBOSE(" Partial overlap: (" << intersectFrac1 << "," << intersectFrac2 + << "), opening angle " << openingAngle); + if (intersectFrac1 > 0.75 && intersectFrac2 > 0.75 && openingAngle > 0.99) { + summary.shared.push_back(std::make_pair(*sit1, *sit2)); + uniqueFirst[index1] = 0; + uniqueSecond[index2] = 0; + } + } + + } else if (overlapResult == CompareMuonSegmentKeys::NoOverlap) { + + } else if (overlapResult == CompareMuonSegmentKeys::Unknown) { + ATH_MSG_WARNING( + " Got invalid return argument comparing segments: " << compareKeys.print(overlapResult)); + } + } } // add unique segments - index1 = 0; - sit1 = chamberVec1.begin(); + index1 = 0; + sit1 = chamberVec1.begin(); sit1_end = chamberVec1.end(); - for( ;sit1!=sit1_end;++sit1,++index1 ){ - if( uniqueFirst[index1] ) summary.uniqueFirst.push_back(*sit1); + for (; sit1 != sit1_end; ++sit1, ++index1) { + if (uniqueFirst[index1]) summary.uniqueFirst.push_back(*sit1); } - unsigned int index2 = 0; - std::vector<MuonSegment*>::const_iterator sit2 = chamberVec2.begin(); + unsigned int index2 = 0; + std::vector<MuonSegment*>::const_iterator sit2 = chamberVec2.begin(); std::vector<MuonSegment*>::const_iterator sit2_end = chamberVec2.end(); - for( ;sit2!=sit2_end;++sit2,++index2 ){ - if( uniqueSecond[index2] ) summary.uniqueSecond.push_back(*sit2); + for (; sit2 != sit2_end; ++sit2, ++index2) { + if (uniqueSecond[index2]) summary.uniqueSecond.push_back(*sit2); } - - } +} - MuonSegmentCombiSummary MuonSegmentCombinationCleanerTool::createSummary( const MuonSegmentCombination& combi ) const { +MuonSegmentCombiSummary +MuonSegmentCombinationCleanerTool::createSummary(const MuonSegmentCombination& combi) const +{ // create summary object MuonSegmentCombiSummary summary(combi); @@ -477,184 +500,195 @@ namespace Muon { // loop over segments, add them to the chamber layers // loop over chambers in combi and extract segments - for(unsigned int i=0; i<nstations; ++i){ - - // loop over segments in station - const MuonSegmentCombination::SegmentVec* stationSegs = combi.stationSegments( i ) ; - - // check if not empty - if( !stationSegs || stationSegs->empty() ) continue; - - // get chamber identifier, chamber index and station index - Identifier chid = m_edmHelperSvc->chamberId( *stationSegs->front().get() ); - MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chid); - MuonStationIndex::StIndex stIndex = MuonStationIndex::toStationIndex( chIndex ); - summary.stations.insert(stIndex); - // reserve space for the new segments - MuonSegmentCombiSummary::SegVec& chamberVec = summary.chamberSegments(chIndex); - chamberVec.reserve( chamberVec.size() + stationSegs->size() ); - - summary.nsegments += stationSegs->size(); - - MuonSegmentCombination::SegmentVec::const_iterator ipsg=stationSegs->begin(); - MuonSegmentCombination::SegmentVec::const_iterator ipsg_end=stationSegs->end(); - for (;ipsg!=ipsg_end;++ipsg){ - - MuonSegment* seg=(*ipsg).get(); - if( seg->numberOfContainedROTs() > 3 ) { - summary.stationsGood.insert(stIndex); - } - - chamberVec.push_back(seg); - } + for (unsigned int i = 0; i < nstations; ++i) { + + // loop over segments in station + const MuonSegmentCombination::SegmentVec* stationSegs = combi.stationSegments(i); + + // check if not empty + if (!stationSegs || stationSegs->empty()) continue; + + // get chamber identifier, chamber index and station index + Identifier chid = m_edmHelperSvc->chamberId(*stationSegs->front().get()); + MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(chid); + MuonStationIndex::StIndex stIndex = MuonStationIndex::toStationIndex(chIndex); + summary.stations.insert(stIndex); + // reserve space for the new segments + MuonSegmentCombiSummary::SegVec& chamberVec = summary.chamberSegments(chIndex); + chamberVec.reserve(chamberVec.size() + stationSegs->size()); + + summary.nsegments += stationSegs->size(); + + MuonSegmentCombination::SegmentVec::const_iterator ipsg = stationSegs->begin(); + MuonSegmentCombination::SegmentVec::const_iterator ipsg_end = stationSegs->end(); + for (; ipsg != ipsg_end; ++ipsg) { + + MuonSegment* seg = (*ipsg).get(); + if (seg->numberOfContainedROTs() > 3) { + summary.stationsGood.insert(stIndex); + } + + chamberVec.push_back(seg); + } } - + return summary; - } +} + +MuonSegmentCombination* +MuonSegmentCombinationCleanerTool::removeDuplicateSegments(MuonSegmentCombination& combi) const +{ - MuonSegmentCombination* MuonSegmentCombinationCleanerTool::removeDuplicateSegments( MuonSegmentCombination& combi ) const { - CompareMuonSegmentKeys compareKeys; // store pointers to segments that should be kept std::set<MuonSegment*> segmentsToBeKept; - unsigned int nsegments = 0; // total number of segments + unsigned int nsegments = 0; // total number of segments unsigned int nstations = combi.numberOfStations(); // loop over segments, add them to the chamber layers // loop over chambers in combi and extract segments - for(unsigned int i=0; i<nstations; ++i){ - - // loop over segments in station - MuonSegmentCombination::SegmentVec* stationSegs = combi.stationSegments( i ) ; - - // check if not empty - if( !stationSegs || stationSegs->empty() ) continue; - - std::vector< std::pair<MuonSegmentKey,MuonSegment*> > keys; - keys.reserve(stationSegs->size()); - - MuonSegmentCombination::SegmentVec::iterator ipsg=stationSegs->begin(); - MuonSegmentCombination::SegmentVec::iterator ipsg_end=stationSegs->end(); - for (;ipsg!=ipsg_end;++ipsg){ - - ++nsegments; - - MuonSegment* seg=(*ipsg).get(); - ATH_MSG_VERBOSE(" segment " << m_printer->print(*seg) << std::endl << m_printer->print( seg->containedMeasurements() ) ); - - // create key - MuonSegmentKey key(*seg); - - // loop over already added keys - bool addSegment = true; - std::vector< std::pair<MuonSegmentKey,MuonSegment*> >::iterator kit = keys.begin(); - std::vector< std::pair<MuonSegmentKey,MuonSegment*> >::iterator kit_end = keys.end(); - for( ;kit!=kit_end;++kit ) { - - CompareMuonSegmentKeys::OverlapResult overlapResult = compareKeys(key,kit->first); - ATH_MSG_VERBOSE(" overlap Result: " << compareKeys.print(overlapResult) ); - - if( overlapResult == CompareMuonSegmentKeys::Identical || - overlapResult == CompareMuonSegmentKeys::SubSet ){ - addSegment = false; - break; - }else if( overlapResult == CompareMuonSegmentKeys::SuperSet ) { - *kit = std::make_pair(key,seg); - addSegment = false; - break; - }else if( overlapResult == CompareMuonSegmentKeys::Unknown ){ - ATH_MSG_WARNING(" Got invalid return argument comparing segments: " << compareKeys.print(overlapResult) ); - } - } - - if( addSegment ) keys.push_back( std::make_pair(key,seg) ); - } - std::vector< std::pair<MuonSegmentKey,MuonSegment*> >::iterator kit = keys.begin(); - std::vector< std::pair<MuonSegmentKey,MuonSegment*> >::iterator kit_end = keys.end(); - for( ;kit!=kit_end;++kit ) segmentsToBeKept.insert( kit->second ); + for (unsigned int i = 0; i < nstations; ++i) { + + // loop over segments in station + MuonSegmentCombination::SegmentVec* stationSegs = combi.stationSegments(i); + + // check if not empty + if (!stationSegs || stationSegs->empty()) continue; + + std::vector<std::pair<MuonSegmentKey, MuonSegment*> > keys; + keys.reserve(stationSegs->size()); + + MuonSegmentCombination::SegmentVec::iterator ipsg = stationSegs->begin(); + MuonSegmentCombination::SegmentVec::iterator ipsg_end = stationSegs->end(); + for (; ipsg != ipsg_end; ++ipsg) { + + ++nsegments; + + MuonSegment* seg = (*ipsg).get(); + ATH_MSG_VERBOSE(" segment " << m_printer->print(*seg) << std::endl + << m_printer->print(seg->containedMeasurements())); + + // create key + MuonSegmentKey key(*seg); + + // loop over already added keys + bool addSegment = true; + std::vector<std::pair<MuonSegmentKey, MuonSegment*> >::iterator kit = keys.begin(); + std::vector<std::pair<MuonSegmentKey, MuonSegment*> >::iterator kit_end = keys.end(); + for (; kit != kit_end; ++kit) { + + CompareMuonSegmentKeys::OverlapResult overlapResult = compareKeys(key, kit->first); + ATH_MSG_VERBOSE(" overlap Result: " << compareKeys.print(overlapResult)); + + if (overlapResult == CompareMuonSegmentKeys::Identical + || overlapResult == CompareMuonSegmentKeys::SubSet) { + addSegment = false; + break; + } else if (overlapResult == CompareMuonSegmentKeys::SuperSet) { + *kit = std::make_pair(key, seg); + addSegment = false; + break; + } else if (overlapResult == CompareMuonSegmentKeys::Unknown) { + ATH_MSG_WARNING( + " Got invalid return argument comparing segments: " << compareKeys.print(overlapResult)); + } + } + + if (addSegment) keys.push_back(std::make_pair(key, seg)); + } + std::vector<std::pair<MuonSegmentKey, MuonSegment*> >::iterator kit = keys.begin(); + std::vector<std::pair<MuonSegmentKey, MuonSegment*> >::iterator kit_end = keys.end(); + for (; kit != kit_end; ++kit) segmentsToBeKept.insert(kit->second); } // check whether all segments were kept - if( nsegments == segmentsToBeKept.size() ){ - ATH_MSG_DEBUG(" no segments removed "); - return &combi; + if (nsegments == segmentsToBeKept.size()) { + ATH_MSG_DEBUG(" no segments removed "); + return &combi; } MuonSegmentCombination* newCombi = new MuonSegmentCombination(); // create a new combination removing segments that overlap - for(unsigned int i=0; i<nstations; ++i){ - - // loop over segments in station - MuonSegmentCombination::SegmentVec* stationSegs = combi.stationSegments( i ) ; - - // check if not empty - if( !stationSegs || stationSegs->empty() ) continue; - - std::unique_ptr<std::vector< std::unique_ptr< MuonSegment> > > segVec(new std::vector< std::unique_ptr< MuonSegment> >()); - segVec->reserve( stationSegs->size() ); - - MuonSegmentCombination::SegmentVec::iterator ipsg=stationSegs->begin(); - MuonSegmentCombination::SegmentVec::iterator ipsg_end=stationSegs->end(); - for (;ipsg!=ipsg_end;++ipsg){ - - MuonSegment* seg=(*ipsg).get(); - if( !segmentsToBeKept.count(seg) ){ - ATH_MSG_VERBOSE(" dropping segment " << m_printer->print(*seg) ); - continue; - }else ATH_MSG_VERBOSE(" adding segment " << m_printer->print(*seg) ); - segVec->push_back( std::move(*ipsg) ); - } - newCombi->addSegments( std::move(segVec) ); + for (unsigned int i = 0; i < nstations; ++i) { + + // loop over segments in station + MuonSegmentCombination::SegmentVec* stationSegs = combi.stationSegments(i); + + // check if not empty + if (!stationSegs || stationSegs->empty()) continue; + + std::unique_ptr<std::vector<std::unique_ptr<MuonSegment> > > segVec( + new std::vector<std::unique_ptr<MuonSegment> >()); + segVec->reserve(stationSegs->size()); + + MuonSegmentCombination::SegmentVec::iterator ipsg = stationSegs->begin(); + MuonSegmentCombination::SegmentVec::iterator ipsg_end = stationSegs->end(); + for (; ipsg != ipsg_end; ++ipsg) { + + MuonSegment* seg = (*ipsg).get(); + if (!segmentsToBeKept.count(seg)) { + ATH_MSG_VERBOSE(" dropping segment " << m_printer->print(*seg)); + continue; + } else + ATH_MSG_VERBOSE(" adding segment " << m_printer->print(*seg)); + segVec->push_back(std::move(*ipsg)); + } + newCombi->addSegments(std::move(segVec)); } - + return newCombi; - } +} + +std::string +MuonSegmentCombinationCleanerTool::print(MuonSegmentCombiSummary& summary) const +{ - std::string MuonSegmentCombinationCleanerTool::print( MuonSegmentCombiSummary& summary ) const { - std::ostringstream sout; // loop over chamber layers - int index = 0; + int index = 0; MuonSegmentCombiSummary::ChSegVec& segmentsPerLayer = summary.segmentsPerLayer(); sout << "SegmentCombi " << std::endl; - MuonSegmentCombiSummary::ChSegIt chit = segmentsPerLayer.begin(); + MuonSegmentCombiSummary::ChSegIt chit = segmentsPerLayer.begin(); MuonSegmentCombiSummary::ChSegIt chit_end = segmentsPerLayer.end(); - for( ;chit!=chit_end;++chit ){ - - // skip empty layers - if( chit->empty() ) continue; - - sout << " Chamber Layer: " << MuonStationIndex::chName((MuonStationIndex::ChIndex)index) << " with " << chit->size() << " segments " << std::endl; - - std::vector<MuonSegment*>::iterator segit=(*chit).begin(); - std::vector<MuonSegment*>::iterator segit_end=(*chit).end(); - for(;segit!=segit_end;++segit) sout<< m_printer->print( **segit ) << std::endl; - - ++index; + for (; chit != chit_end; ++chit) { + + // skip empty layers + if (chit->empty()) continue; + + sout << " Chamber Layer: " << MuonStationIndex::chName((MuonStationIndex::ChIndex)index) << " with " + << chit->size() << " segments " << std::endl; + + std::vector<MuonSegment*>::iterator segit = (*chit).begin(); + std::vector<MuonSegment*>::iterator segit_end = (*chit).end(); + for (; segit != segit_end; ++segit) sout << m_printer->print(**segit) << std::endl; + + ++index; } - + return sout.str(); - } +} + +std::string +MuonSegmentCombinationCleanerTool::print(MuonSegmentCombiOverlapSummary& summary) const +{ - std::string MuonSegmentCombinationCleanerTool::print( MuonSegmentCombiOverlapSummary& summary ) const { - std::ostringstream sout; sout << "SegmentCombi overlap " << std::endl - << " shared: " << summary.shared.size() << std::endl - << " uniqueFirst: " << summary.uniqueFirst.size() << std::endl - << " uniqueSecond: " << summary.uniqueSecond.size() << std::endl - << " subsetFirst: " << summary.subsetFirst.size() << std::endl - << " subsetSecond: " << summary.subsetSecond.size() << std::endl; + << " shared: " << summary.shared.size() << std::endl + << " uniqueFirst: " << summary.uniqueFirst.size() << std::endl + << " uniqueSecond: " << summary.uniqueSecond.size() << std::endl + << " subsetFirst: " << summary.subsetFirst.size() << std::endl + << " subsetSecond: " << summary.subsetSecond.size() << std::endl; return sout.str(); - } +} -} +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentCombinationCleanerTool.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentCombinationCleanerTool.h index 59e6dd5fde669e3822c184fcd83e7236eb7f0d7e..e707b85173cfd463793dd1663f0e04f0eea6918b 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentCombinationCleanerTool.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentCombinationCleanerTool.h @@ -5,81 +5,98 @@ #ifndef MUONSEGMENTCOMBINATIONCLEANERTOOL_H #define MUONSEGMENTCOMBINATIONCLEANERTOOL_H -#include <string> #include <map> +#include <string> #include <vector> #include "AthenaBaseComps/AthAlgTool.h" -#include "GaudiKernel/ToolHandle.h" #include "GaudiKernel/ServiceHandle.h" - -#include "MuonSegment/MuonSegmentCombinationCollection.h" -#include "MuonSegmentCombinerToolInterfaces/IMuonSegmentCombinationCleanerTool.h" -#include "MuonSegmentMakerUtils/MuonSegmentCombiSummary.h" -#include "MuonSegmentMakerUtils/MuonSegmentCombiOverlapSummary.h" -#include "MuonRecHelperTools/IMuonEDMHelperSvc.h" +#include "GaudiKernel/ToolHandle.h" #include "MuonIdHelpers/IMuonIdHelperSvc.h" +#include "MuonRecHelperTools/IMuonEDMHelperSvc.h" #include "MuonRecHelperTools/MuonEDMPrinterTool.h" +#include "MuonSegment/MuonSegmentCombinationCollection.h" +#include "MuonSegmentCombinerToolInterfaces/IMuonSegmentCombinationCleanerTool.h" #include "MuonSegmentMakerToolInterfaces/IMuonSegmentOverlapRemovalTool.h" +#include "MuonSegmentMakerUtils/MuonSegmentCombiOverlapSummary.h" +#include "MuonSegmentMakerUtils/MuonSegmentCombiSummary.h" namespace Muon { - class MuonSegment; +class MuonSegment; - class MuonSegmentCombinationCleanerTool : virtual public IMuonSegmentCombinationCleanerTool, public AthAlgTool - { +class MuonSegmentCombinationCleanerTool : virtual public IMuonSegmentCombinationCleanerTool, public AthAlgTool { public: /** constructor */ MuonSegmentCombinationCleanerTool(const std::string&, const std::string&, const IInterface*); /** destructor */ - virtual ~MuonSegmentCombinationCleanerTool() {}; + virtual ~MuonSegmentCombinationCleanerTool(){}; /** initializes private members */ virtual StatusCode initialize(); /** clean segment combination collections */ - std::unique_ptr<MuonSegmentCombinationCollection> clean( const MuonSegmentCombinationCollection& combiCol, MuonSegmentCombPatternCombAssociationMap* segPattMap ); + std::unique_ptr<MuonSegmentCombinationCollection> clean(const MuonSegmentCombinationCollection& combiCol, + MuonSegmentCombPatternCombAssociationMap* segPattMap); /** remove duplicates from a segment combination, returns a pointer to the original combi if unchanged */ - MuonSegmentCombination* removeDuplicateSegments( MuonSegmentCombination& combi ) const; + MuonSegmentCombination* removeDuplicateSegments(MuonSegmentCombination& combi) const; private: /** remove overlaps between combination and merge combinations with large overlap */ - void cleanAndMergeCombis( const MuonSegmentCombinationCollection& combiCol, MuonSegmentCombinationCollection* combiCleanCol, - MuonSegmentCombPatternCombAssociationMap* segPattMap ); + void cleanAndMergeCombis(const MuonSegmentCombinationCollection& combiCol, + MuonSegmentCombinationCollection* combiCleanCol, + MuonSegmentCombPatternCombAssociationMap* segPattMap); /** check whether current summary is a subset of the previous once */ - bool subSetOfPrevious( MuonSegmentCombiSummary& summary, std::vector<MuonSegmentCombiSummary>& summaries) const; + bool subSetOfPrevious(MuonSegmentCombiSummary& summary, std::vector<MuonSegmentCombiSummary>& summaries) const; /** calculate overlap between two summaries */ - MuonSegmentCombiOverlapSummary calculateOverlap( MuonSegmentCombiSummary& summary1, MuonSegmentCombiSummary& summary2 ) const; + MuonSegmentCombiOverlapSummary calculateOverlap(MuonSegmentCombiSummary& summary1, + MuonSegmentCombiSummary& summary2) const; /* resolve overlap between two vectors of segments */ - void resolveLayerOverlap( const std::vector<MuonSegment*>& chamberVec1, const std::vector<MuonSegment*>& chamberVec2, - MuonSegmentCombiOverlapSummary& summary) const; + void resolveLayerOverlap(const std::vector<MuonSegment*>& chamberVec1, const std::vector<MuonSegment*>& chamberVec2, + MuonSegmentCombiOverlapSummary& summary) const; /** create summary */ - MuonSegmentCombiSummary createSummary( const MuonSegmentCombination& combi ) const; + MuonSegmentCombiSummary createSummary(const MuonSegmentCombination& combi) const; /** print summaries */ - std::string print( MuonSegmentCombiSummary& summary ) const; - std::string print( MuonSegmentCombiOverlapSummary& summary ) const; - - ToolHandle<Muon::MuonEDMPrinterTool> m_printer; - ServiceHandle<Muon::IMuonEDMHelperSvc> m_edmHelperSvc {this, "edmHelper", - "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", - "Handle to the service providing the IMuonEDMHelperSvc interface" }; - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - ToolHandle<IMuonSegmentOverlapRemovalTool> m_overlapRemovalTool; - - /** If set to true, all combinaties will be merged into one big one */ + std::string print(MuonSegmentCombiSummary& summary) const; + std::string print(MuonSegmentCombiOverlapSummary& summary) const; + + ToolHandle<Muon::MuonEDMPrinterTool> m_printer{ + this, + "Printer", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; + ToolHandle<IMuonSegmentOverlapRemovalTool> m_overlapRemovalTool{ + this, + "SegmentOverlapRemovalTool", + "Muon::MuonSegmentOverlapRemovalTool/MuonSegmentOverlapRemovalTool", + "tool to removal overlaps in segment combinations", + }; + + ServiceHandle<Muon::IMuonEDMHelperSvc> m_edmHelperSvc{ + this, + "edmHelper", + "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", + "Handle to the service providing the IMuonEDMHelperSvc interface", + }; + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; + + + /** If set to true, all combinaties will be merged into one big one */ bool m_mergeAllCombis; +}; - }; - -} - -#endif //MUONSEGMENTCOMBINATIONCLEANER_H +} // namespace Muon +#endif // MUONSEGMENTCOMBINATIONCLEANER_H diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentMerger.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentMerger.cxx index 4aa3be5614ec3d6c90f133bbef1a1f239d847270..c7c9dfed04135da4eeb747565e754614ebdb93fd 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentMerger.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentMerger.cxx @@ -4,379 +4,392 @@ #include "MuonSegmentMerger.h" +#include "MuonClusterization/RpcHitClustering.h" +#include "MuonClusterization/TgcHitClustering.h" +#include "MuonCompetingRIOsOnTrack/CompetingMuonClustersOnTrack.h" +#include "MuonRIO_OnTrack/MuonClusterOnTrack.h" #include "MuonSegment/MuonSegment.h" #include "MuonSegment/MuonSegmentCombination.h" -#include "MuonRIO_OnTrack/MuonClusterOnTrack.h" -#include "MuonCompetingRIOsOnTrack/CompetingMuonClustersOnTrack.h" - -#include "MuonSegmentMakerUtils/MuonSegmentKey.h" #include "MuonSegmentMakerUtils/CompareMuonSegmentKeys.h" - -#include "TrkEventPrimitives/FitQuality.h" -#include "MuonClusterization/RpcHitClustering.h" -#include "MuonClusterization/TgcHitClustering.h" +#include "MuonSegmentMakerUtils/MuonSegmentKey.h" +#include "TrkEventPrimitives/FitQuality.h" namespace Muon { - MuonSegmentMerger::MuonSegmentMerger(const std::string& ty,const std::string& na,const IInterface* pa) - : AthAlgTool(ty,na,pa), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"), - m_triggerHitsAssociator("Muon::DCMathSegmentMaker/DCMathSegmentMaker") - { +MuonSegmentMerger::MuonSegmentMerger(const std::string& ty, const std::string& na, const IInterface* pa) + : AthAlgTool(ty, na, pa) +{ declareInterface<IMuonSegmentMerger>(this); +} - declareProperty("MuonEDMPrinterTool",m_printer); - declareProperty("TriggerHitAssociator",m_triggerHitsAssociator); - } - - StatusCode MuonSegmentMerger::initialize() - { +StatusCode +MuonSegmentMerger::initialize() +{ ATH_CHECK(AthAlgTool::initialize()); ATH_CHECK(m_edmHelperSvc.retrieve()); ATH_CHECK(m_printer.retrieve()); ATH_CHECK(m_idHelperSvc.retrieve()); ATH_CHECK(m_triggerHitsAssociator.retrieve()); return StatusCode::SUCCESS; - } +} - MuonSegmentMerger::SegVec - MuonSegmentMerger::findDuplicates( const MuonSegmentMerger::SegVec& segments ) const { +MuonSegmentMerger::SegVec +MuonSegmentMerger::findDuplicates(const MuonSegmentMerger::SegVec& segments) const +{ ATH_MSG_DEBUG(" working on segment vector of size " << segments.size()); CompareMuonSegmentKeys compareSegmentKeys; - SegVec outputSegments; + SegVec outputSegments; // create a vector with pairs of MuonSegmentKey and a pointer to the corresponding segment to resolve ambiguities - std::vector< std::pair<MuonSegmentKey,std::vector<const MuonSegment*> > > identicalSegments; + std::vector<std::pair<MuonSegmentKey, std::vector<const MuonSegment*> > > identicalSegments; identicalSegments.reserve(segments.size()); // loop over new segments, copy them into collection - SegCit sit = segments.begin(); + SegCit sit = segments.begin(); SegCit sit_end = segments.end(); - for( ; sit!=sit_end;++sit){ - - bool inserted = false; - - // create segment key object - MuonSegmentKey sk(**sit); - Identifier chId = m_edmHelperSvc->chamberId(**sit); - if(!m_idHelperSvc->isMdt(chId)) { - outputSegments.push_back(new MuonSegment(**sit)); - continue; - } - // loop over already accepted segments and compare the current segment with the good ones - std::vector< std::pair<MuonSegmentKey,std::vector<const MuonSegment*> > >::iterator gsit = identicalSegments.begin(); - std::vector< std::pair<MuonSegmentKey,std::vector<const MuonSegment*> > >::iterator gsit_end = identicalSegments.end(); - for( ;gsit!=gsit_end;++gsit ){ - CompareMuonSegmentKeys::OverlapResult overlapResult = compareSegmentKeys( gsit->first, sk, true ); - if( overlapResult == CompareMuonSegmentKeys::Identical ) { - gsit->second.push_back(*sit); -// ATH_MSG_DEBUG(" found identical segment " << m_printer->print(**sit) << " index " << std::distance(identicalSegments.begin(),gsit) -// << " total size " << identicalSegments.size() ); - inserted = true; - break; - } - } - - // add segment if needed - if( !inserted ) { -// ATH_MSG_DEBUG(" no overlap, adding " << m_printer->print(**sit) << " total size " << identicalSegments.size()); - std::vector<const MuonSegment*> vec; - vec.push_back(*sit); - identicalSegments.push_back( std::make_pair(sk,vec) ); - } - } - - + for (; sit != sit_end; ++sit) { + + bool inserted = false; + + // create segment key object + MuonSegmentKey sk(**sit); + Identifier chId = m_edmHelperSvc->chamberId(**sit); + if (!m_idHelperSvc->isMdt(chId)) { + outputSegments.push_back(new MuonSegment(**sit)); + continue; + } + // loop over already accepted segments and compare the current segment with the good ones + std::vector<std::pair<MuonSegmentKey, std::vector<const MuonSegment*> > >::iterator gsit = + identicalSegments.begin(); + std::vector<std::pair<MuonSegmentKey, std::vector<const MuonSegment*> > >::iterator gsit_end = + identicalSegments.end(); + for (; gsit != gsit_end; ++gsit) { + CompareMuonSegmentKeys::OverlapResult overlapResult = compareSegmentKeys(gsit->first, sk, true); + if (overlapResult == CompareMuonSegmentKeys::Identical) { + gsit->second.push_back(*sit); + // ATH_MSG_DEBUG(" found identical segment " << m_printer->print(**sit) << " index " << + // std::distance(identicalSegments.begin(),gsit) + // << " total size " << identicalSegments.size() ); + inserted = true; + break; + } + } + + // add segment if needed + if (!inserted) { + // ATH_MSG_DEBUG(" no overlap, adding " << m_printer->print(**sit) << " total size " << + // identicalSegments.size()); + std::vector<const MuonSegment*> vec; + vec.push_back(*sit); + identicalSegments.push_back(std::make_pair(sk, vec)); + } + } + + ATH_MSG_DEBUG(" input segment size " << segments.size() << " after overlap merging " << identicalSegments.size()); - std::vector< std::pair<MuonSegmentKey,std::vector<const MuonSegment*> > >::iterator gsit = identicalSegments.begin(); - std::vector< std::pair<MuonSegmentKey,std::vector<const MuonSegment*> > >::iterator gsit_end = identicalSegments.end(); - for( ;gsit!=gsit_end;++gsit ){ - - if( gsit->second.size() > 0 ){ - std::stable_sort(gsit->second.begin(),gsit->second.end(),LocalSortSegmentsByChi2()); - std::vector< SegVec > resolvedSegments = resolveClusterOverlaps( gsit->second ); - std::vector< SegVec >::iterator it = resolvedSegments.begin(); - std::vector< SegVec >::iterator it_end = resolvedSegments.end(); - for( ;it!=it_end;++it ){ - - const MuonSegment* mergedSegment = merge(*it); - if( mergedSegment ) outputSegments.push_back(mergedSegment); - else { - //outputSegments.push_back( new MuonSegment( *gsit->second.front() ) ); - ATH_MSG_DEBUG("Failed to merge segments of a total size identical ones: " << identicalSegments.size()); - } - } - } + std::vector<std::pair<MuonSegmentKey, std::vector<const MuonSegment*> > >::iterator gsit = + identicalSegments.begin(); + std::vector<std::pair<MuonSegmentKey, std::vector<const MuonSegment*> > >::iterator gsit_end = + identicalSegments.end(); + for (; gsit != gsit_end; ++gsit) { + + if (gsit->second.size() > 0) { + std::stable_sort(gsit->second.begin(), gsit->second.end(), LocalSortSegmentsByChi2()); + std::vector<SegVec> resolvedSegments = resolveClusterOverlaps(gsit->second); + std::vector<SegVec>::iterator it = resolvedSegments.begin(); + std::vector<SegVec>::iterator it_end = resolvedSegments.end(); + for (; it != it_end; ++it) { + + const MuonSegment* mergedSegment = merge(*it); + if (mergedSegment) + outputSegments.push_back(mergedSegment); + else { + // outputSegments.push_back( new MuonSegment( *gsit->second.front() ) ); + ATH_MSG_DEBUG( + "Failed to merge segments of a total size identical ones: " << identicalSegments.size()); + } + } + } } return outputSegments; - } +} - std::vector< MuonSegmentMerger::SegVec > MuonSegmentMerger::resolveClusterOverlaps( const MuonSegmentMerger::SegVec& segments ) const { - - if( segments.empty() ) return std::vector< MuonSegmentMerger::SegVec >(); +std::vector<MuonSegmentMerger::SegVec> +MuonSegmentMerger::resolveClusterOverlaps(const MuonSegmentMerger::SegVec& segments) const +{ + + if (segments.empty()) return std::vector<MuonSegmentMerger::SegVec>(); const MuonSegment* aSegment = 0; - std::map<IdentifierHash,std::vector<const RpcPrepData*> > rpcsPerCollection; - std::map<IdentifierHash,std::vector<const TgcPrepData*> > tgcsPerCollection; + std::map<IdentifierHash, std::vector<const RpcPrepData*> > rpcsPerCollection; + std::map<IdentifierHash, std::vector<const TgcPrepData*> > tgcsPerCollection; std::map<const MuonCluster*, std::vector<const MuonSegment*> > prdToSegmentMap; ATH_MSG_DEBUG(" resolving cluster overlap: segments " << segments.size()); - SegCit sit = segments.begin(); - SegCit sit_end = segments.end(); + SegCit sit = segments.begin(); + SegCit sit_end = segments.end(); std::vector<const MuonClusterOnTrack*> clusters; - for( ;sit!=sit_end;++sit ){ - ATH_MSG_DEBUG(" " << m_printer->print(**sit)); - - // Identifier chid = m_edmHelperSvc->chamberId(**sit); - - if( !aSegment ) aSegment = *sit; - - std::vector<const Trk::MeasurementBase*>::const_iterator hit = (*sit)->containedMeasurements().begin(); - std::vector<const Trk::MeasurementBase*>::const_iterator hit_end = (*sit)->containedMeasurements().end(); - for( ;hit!=hit_end;++hit ){ - const MuonClusterOnTrack* clot = dynamic_cast<const MuonClusterOnTrack*>(*hit); - if( clot ) { - ATH_MSG_DEBUG(" " << m_printer->print(*clot)); - const MuonCluster* cl = clot->prepRawData(); - if( cl ) { - - prdToSegmentMap[cl].push_back(*sit); - - const RpcPrepData* rpc = dynamic_cast<const RpcPrepData*>(cl); - if( rpc ){ - rpcsPerCollection[rpc->collectionHash()].push_back(const_cast<RpcPrepData*>(rpc)); - }else{ - const TgcPrepData* tgc = dynamic_cast<const TgcPrepData*>(cl); - if( tgc ){ - tgcsPerCollection[tgc->collectionHash()].push_back(const_cast<TgcPrepData*>(tgc)); - } - } - } - } - - const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*hit); - if( crot ){ - std::vector<const MuonClusterOnTrack*>::const_iterator clit = crot->containedROTs().begin(); - std::vector<const MuonClusterOnTrack*>::const_iterator clit_end = crot->containedROTs().end(); - for( ;clit!=clit_end;++clit ){ - const MuonClusterOnTrack* clot = *clit; - - if( clot ) { - ATH_MSG_DEBUG(" " << m_printer->print(*clot)); - const MuonCluster* cl = clot->prepRawData(); - if( cl ) { - - const RpcPrepData* rpc = dynamic_cast<const RpcPrepData*>(cl); - if( rpc ){ - rpcsPerCollection[rpc->collectionHash()].push_back(const_cast<RpcPrepData*>(rpc)); - }else{ - const TgcPrepData* tgc = dynamic_cast<const TgcPrepData*>(cl); - if( tgc ){ - tgcsPerCollection[tgc->collectionHash()].push_back(const_cast<TgcPrepData*>(tgc)); - } - } - } - } - } - } - } + for (; sit != sit_end; ++sit) { + ATH_MSG_DEBUG(" " << m_printer->print(**sit)); + + // Identifier chid = m_edmHelperSvc->chamberId(**sit); + + if (!aSegment) aSegment = *sit; + + std::vector<const Trk::MeasurementBase*>::const_iterator hit = (*sit)->containedMeasurements().begin(); + std::vector<const Trk::MeasurementBase*>::const_iterator hit_end = (*sit)->containedMeasurements().end(); + for (; hit != hit_end; ++hit) { + const MuonClusterOnTrack* clot = dynamic_cast<const MuonClusterOnTrack*>(*hit); + if (clot) { + ATH_MSG_DEBUG(" " << m_printer->print(*clot)); + const MuonCluster* cl = clot->prepRawData(); + if (cl) { + + prdToSegmentMap[cl].push_back(*sit); + + const RpcPrepData* rpc = dynamic_cast<const RpcPrepData*>(cl); + if (rpc) { + rpcsPerCollection[rpc->collectionHash()].push_back(const_cast<RpcPrepData*>(rpc)); + } else { + const TgcPrepData* tgc = dynamic_cast<const TgcPrepData*>(cl); + if (tgc) { + tgcsPerCollection[tgc->collectionHash()].push_back(const_cast<TgcPrepData*>(tgc)); + } + } + } + } + + const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*hit); + if (crot) { + std::vector<const MuonClusterOnTrack*>::const_iterator clit = crot->containedROTs().begin(); + std::vector<const MuonClusterOnTrack*>::const_iterator clit_end = crot->containedROTs().end(); + for (; clit != clit_end; ++clit) { + const MuonClusterOnTrack* clot = *clit; + + if (clot) { + ATH_MSG_DEBUG(" " << m_printer->print(*clot)); + const MuonCluster* cl = clot->prepRawData(); + if (cl) { + + const RpcPrepData* rpc = dynamic_cast<const RpcPrepData*>(cl); + if (rpc) { + rpcsPerCollection[rpc->collectionHash()].push_back(const_cast<RpcPrepData*>(rpc)); + } else { + const TgcPrepData* tgc = dynamic_cast<const TgcPrepData*>(cl); + if (tgc) { + tgcsPerCollection[tgc->collectionHash()].push_back(const_cast<TgcPrepData*>(tgc)); + } + } + } + } + } + } + } } - ATH_MSG_DEBUG("collected trigger hits: RPCs " << rpcsPerCollection.size() << " TGCs " << tgcsPerCollection.size() ); - - if( prdToSegmentMap.empty() ){ - std::vector< SegVec > overlappingSegments; - overlappingSegments.push_back(segments); - return overlappingSegments; + ATH_MSG_DEBUG("collected trigger hits: RPCs " << rpcsPerCollection.size() << " TGCs " + << tgcsPerCollection.size()); + + if (prdToSegmentMap.empty()) { + std::vector<SegVec> overlappingSegments; + overlappingSegments.push_back(segments); + return overlappingSegments; } - + std::map<int, std::set<const MuonSegment*> > clusterToSegmentMap; std::map<const MuonSegment*, std::set<int> > segmentToClusterMap; - if( !rpcsPerCollection.empty() ){ - std::map<IdentifierHash,std::vector<const RpcPrepData*> >::const_iterator rcit = rpcsPerCollection.begin(); - std::map<IdentifierHash,std::vector<const RpcPrepData*> >::const_iterator rcit_end = rpcsPerCollection.end(); - RpcHitClusteringObj rpcClustering(&m_idHelperSvc->rpcIdHelper()); - int offset = 0; - for( ;rcit!=rcit_end;++rcit ){ - ATH_MSG_DEBUG(" rpc Prd size " << rcit->second.size() ); - if( !rpcClustering.cluster( rcit->second ) ) { - continue; - } - ATH_MSG_DEBUG("RpcHitClusteringObj size " << rpcClustering.clustersPhi.size() ); - for( unsigned int i=0;i<rpcClustering.clustersPhi.size();++i){ - ATH_MSG_DEBUG(" RpcHitClusteringObj nr " << i << " hits "<< rpcClustering.clustersPhi[i].hitList.size() ); - RpcClusterObj::HitCit hit = rpcClustering.clustersPhi[i].hitList.begin(); - RpcClusterObj::HitCit hit_end = rpcClustering.clustersPhi[i].hitList.end(); - for( ;hit!=hit_end;++hit ){ - std::map<const MuonCluster*, std::vector<const MuonSegment*> >::iterator pos = prdToSegmentMap.find(*hit); - if( pos == prdToSegmentMap.end() ){ - ATH_MSG_WARNING("Prd not found, this should not happen!!"); - continue; - } - int index = 1000*offset + i; - clusterToSegmentMap[index].insert(pos->second.begin(),pos->second.end()); - std::vector<const MuonSegment*>::iterator sit = pos->second.begin(); - std::vector<const MuonSegment*>::iterator sit_end = pos->second.end(); - for( ;sit!=sit_end;++sit ) segmentToClusterMap[*sit].insert(index); - } - } - ++offset; - } + if (!rpcsPerCollection.empty()) { + std::map<IdentifierHash, std::vector<const RpcPrepData*> >::const_iterator rcit = rpcsPerCollection.begin(); + std::map<IdentifierHash, std::vector<const RpcPrepData*> >::const_iterator rcit_end = rpcsPerCollection.end(); + RpcHitClusteringObj rpcClustering(&m_idHelperSvc->rpcIdHelper()); + int offset = 0; + for (; rcit != rcit_end; ++rcit) { + ATH_MSG_DEBUG(" rpc Prd size " << rcit->second.size()); + if (!rpcClustering.cluster(rcit->second)) { + continue; + } + ATH_MSG_DEBUG("RpcHitClusteringObj size " << rpcClustering.clustersPhi.size()); + for (unsigned int i = 0; i < rpcClustering.clustersPhi.size(); ++i) { + ATH_MSG_DEBUG(" RpcHitClusteringObj nr " << i << " hits " + << rpcClustering.clustersPhi[i].hitList.size()); + RpcClusterObj::HitCit hit = rpcClustering.clustersPhi[i].hitList.begin(); + RpcClusterObj::HitCit hit_end = rpcClustering.clustersPhi[i].hitList.end(); + for (; hit != hit_end; ++hit) { + std::map<const MuonCluster*, std::vector<const MuonSegment*> >::iterator pos = + prdToSegmentMap.find(*hit); + if (pos == prdToSegmentMap.end()) { + ATH_MSG_WARNING("Prd not found, this should not happen!!"); + continue; + } + int index = 1000 * offset + i; + clusterToSegmentMap[index].insert(pos->second.begin(), pos->second.end()); + std::vector<const MuonSegment*>::iterator sit = pos->second.begin(); + std::vector<const MuonSegment*>::iterator sit_end = pos->second.end(); + for (; sit != sit_end; ++sit) segmentToClusterMap[*sit].insert(index); + } + } + ++offset; + } } - if( !tgcsPerCollection.empty() ){ - std::map<IdentifierHash,std::vector<const TgcPrepData*> >::const_iterator rcit = tgcsPerCollection.begin(); - std::map<IdentifierHash,std::vector<const TgcPrepData*> >::const_iterator rcit_end = tgcsPerCollection.end(); - TgcHitClusteringObj tgcClustering(&m_idHelperSvc->tgcIdHelper()); - int offset = 0; - for( ;rcit!=rcit_end;++rcit ){ - if( !tgcClustering.cluster( rcit->second ) ) { - continue; - } - for( unsigned int i=0;i<tgcClustering.clustersPhi.size();++i){ - TgcClusterObj::HitCit hit = tgcClustering.clustersPhi[i].hitList.begin(); - TgcClusterObj::HitCit hit_end = tgcClustering.clustersPhi[i].hitList.end(); - for( ;hit!=hit_end;++hit ){ - std::map<const MuonCluster*, std::vector<const MuonSegment*> >::iterator pos = prdToSegmentMap.find(*hit); - if( pos == prdToSegmentMap.end() ){ - ATH_MSG_WARNING("Prd not found, this should not happen!!"); - continue; - } - int tgcIndex = 100000+1000*offset+i; - clusterToSegmentMap[tgcIndex].insert(pos->second.begin(),pos->second.end()); - std::vector<const MuonSegment*>::iterator sit = pos->second.begin(); - std::vector<const MuonSegment*>::iterator sit_end = pos->second.end(); - for( ;sit!=sit_end;++sit ) segmentToClusterMap[*sit].insert(tgcIndex); - } - } - ++offset; - } + if (!tgcsPerCollection.empty()) { + std::map<IdentifierHash, std::vector<const TgcPrepData*> >::const_iterator rcit = tgcsPerCollection.begin(); + std::map<IdentifierHash, std::vector<const TgcPrepData*> >::const_iterator rcit_end = tgcsPerCollection.end(); + TgcHitClusteringObj tgcClustering(&m_idHelperSvc->tgcIdHelper()); + int offset = 0; + for (; rcit != rcit_end; ++rcit) { + if (!tgcClustering.cluster(rcit->second)) { + continue; + } + for (unsigned int i = 0; i < tgcClustering.clustersPhi.size(); ++i) { + TgcClusterObj::HitCit hit = tgcClustering.clustersPhi[i].hitList.begin(); + TgcClusterObj::HitCit hit_end = tgcClustering.clustersPhi[i].hitList.end(); + for (; hit != hit_end; ++hit) { + std::map<const MuonCluster*, std::vector<const MuonSegment*> >::iterator pos = + prdToSegmentMap.find(*hit); + if (pos == prdToSegmentMap.end()) { + ATH_MSG_WARNING("Prd not found, this should not happen!!"); + continue; + } + int tgcIndex = 100000 + 1000 * offset + i; + clusterToSegmentMap[tgcIndex].insert(pos->second.begin(), pos->second.end()); + std::vector<const MuonSegment*>::iterator sit = pos->second.begin(); + std::vector<const MuonSegment*>::iterator sit_end = pos->second.end(); + for (; sit != sit_end; ++sit) segmentToClusterMap[*sit].insert(tgcIndex); + } + } + ++offset; + } } // now try to merge segments that have a 100% overlap std::set<const MuonSegment*> usedSegments; - std::vector< SegVec > overlappingSegments; - sit = segments.begin(); + std::vector<SegVec> overlappingSegments; + sit = segments.begin(); sit_end = segments.end(); - for( ;sit!=sit_end;++sit){ - - // check whether this segment was already added - if( usedSegments.count(*sit) ) continue; - usedSegments.insert(*sit); - - std::map<const MuonSegment*, std::set<int> >::iterator scit = segmentToClusterMap.find(*sit); - if( scit == segmentToClusterMap.end() ) continue; - - SegVec segmentsFound; - segmentsFound.push_back(scit->first); - - // loop over clusters associated with this segment - std::set<int>::iterator cit = scit->second.begin(); - std::set<int>::iterator cit_end = scit->second.end(); - for( ;cit!=cit_end;++cit ){ - - // look up segments associated with this cluster - std::map<int, std::set<const MuonSegment*> >::iterator pos = clusterToSegmentMap.find(*cit); - if( pos == clusterToSegmentMap.end() ){ - ATH_MSG_WARNING("no segments found for this cluster, this should not happen!"); - continue; - } - - SegCit sit2 = segments.begin(); - SegCit sit2_end = segments.end(); - for( ;sit2!=sit2_end;++sit2 ){ - if( usedSegments.count(*sit2) ) continue; - if( !pos->second.count(*sit2) ) continue; - segmentsFound.push_back(*sit2); - usedSegments.insert(*sit2); - } - } - overlappingSegments.push_back(segmentsFound); + for (; sit != sit_end; ++sit) { + + // check whether this segment was already added + if (usedSegments.count(*sit)) continue; + usedSegments.insert(*sit); + + std::map<const MuonSegment*, std::set<int> >::iterator scit = segmentToClusterMap.find(*sit); + if (scit == segmentToClusterMap.end()) continue; + + SegVec segmentsFound; + segmentsFound.push_back(scit->first); + + // loop over clusters associated with this segment + std::set<int>::iterator cit = scit->second.begin(); + std::set<int>::iterator cit_end = scit->second.end(); + for (; cit != cit_end; ++cit) { + + // look up segments associated with this cluster + std::map<int, std::set<const MuonSegment*> >::iterator pos = clusterToSegmentMap.find(*cit); + if (pos == clusterToSegmentMap.end()) { + ATH_MSG_WARNING("no segments found for this cluster, this should not happen!"); + continue; + } + + SegCit sit2 = segments.begin(); + SegCit sit2_end = segments.end(); + for (; sit2 != sit2_end; ++sit2) { + if (usedSegments.count(*sit2)) continue; + if (!pos->second.count(*sit2)) continue; + segmentsFound.push_back(*sit2); + usedSegments.insert(*sit2); + } + } + overlappingSegments.push_back(segmentsFound); } - + return overlappingSegments; - } - - - const MuonSegment* MuonSegmentMerger::merge( const MuonSegmentMerger::SegVec& segments ) const { - - if( segments.empty() ) return 0; +} + + +const MuonSegment* +MuonSegmentMerger::merge(const MuonSegmentMerger::SegVec& segments) const +{ + + if (segments.empty()) return 0; const MuonSegment* aSegment = 0; ATH_MSG_DEBUG(" merging overlap " << segments.size()); - SegCit sit = segments.begin(); - SegCit sit_end = segments.end(); + SegCit sit = segments.begin(); + SegCit sit_end = segments.end(); std::vector<const MuonClusterOnTrack*> clusters; - for( ;sit!=sit_end;++sit ){ - ATH_MSG_DEBUG(" " << m_printer->print(**sit)); - - Identifier chid = m_edmHelperSvc->chamberId(**sit); - bool isEndcap = m_idHelperSvc->isEndcap(chid); - - if( !aSegment ) aSegment = *sit; - - std::vector<const Trk::MeasurementBase*>::const_iterator hit = (*sit)->containedMeasurements().begin(); - std::vector<const Trk::MeasurementBase*>::const_iterator hit_end = (*sit)->containedMeasurements().end(); - for( ;hit!=hit_end;++hit ){ - const MuonClusterOnTrack* clot = dynamic_cast<const MuonClusterOnTrack*>(*hit); - if( clot ) { - ATH_MSG_DEBUG(" " << m_printer->print(*clot)); - - if( m_idHelperSvc->isEndcap(clot->identify()) != isEndcap ){ - - if( segments.size() == 1 ) { - ATH_MSG_DEBUG("Inconsistent phi hit topology, keeping original"); - return new MuonSegment(**sit); - }else { - ATH_MSG_DEBUG("Inconsistent phi hit topology, dropping phi hit"); - continue; - } - } - clusters.push_back(clot); - continue; - } - - const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*hit); - if( crot ){ - std::vector<const MuonClusterOnTrack*>::const_iterator clit = crot->containedROTs().begin(); - std::vector<const MuonClusterOnTrack*>::const_iterator clit_end = crot->containedROTs().end(); - for( ;clit!=clit_end;++clit ){ - const MuonClusterOnTrack* clot = *clit; - - if( clot ) { - ATH_MSG_DEBUG(" " << m_printer->print(*clot)); - - if( m_idHelperSvc->isEndcap(clot->identify()) != isEndcap ){ - - if( segments.size() == 1 ) { - ATH_MSG_DEBUG("Inconsistent phi hit topology, keeping original"); - return new MuonSegment(**sit); - }else { - ATH_MSG_DEBUG("Inconsistent phi hit topology, dropping phi hit"); - continue; - } - } - clusters.push_back(clot); - continue; - } - } - } - } + for (; sit != sit_end; ++sit) { + ATH_MSG_DEBUG(" " << m_printer->print(**sit)); + + Identifier chid = m_edmHelperSvc->chamberId(**sit); + bool isEndcap = m_idHelperSvc->isEndcap(chid); + + if (!aSegment) aSegment = *sit; + + std::vector<const Trk::MeasurementBase*>::const_iterator hit = (*sit)->containedMeasurements().begin(); + std::vector<const Trk::MeasurementBase*>::const_iterator hit_end = (*sit)->containedMeasurements().end(); + for (; hit != hit_end; ++hit) { + const MuonClusterOnTrack* clot = dynamic_cast<const MuonClusterOnTrack*>(*hit); + if (clot) { + ATH_MSG_DEBUG(" " << m_printer->print(*clot)); + + if (m_idHelperSvc->isEndcap(clot->identify()) != isEndcap) { + + if (segments.size() == 1) { + ATH_MSG_DEBUG("Inconsistent phi hit topology, keeping original"); + return new MuonSegment(**sit); + } else { + ATH_MSG_DEBUG("Inconsistent phi hit topology, dropping phi hit"); + continue; + } + } + clusters.push_back(clot); + continue; + } + + const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(*hit); + if (crot) { + std::vector<const MuonClusterOnTrack*>::const_iterator clit = crot->containedROTs().begin(); + std::vector<const MuonClusterOnTrack*>::const_iterator clit_end = crot->containedROTs().end(); + for (; clit != clit_end; ++clit) { + const MuonClusterOnTrack* clot = *clit; + + if (clot) { + ATH_MSG_DEBUG(" " << m_printer->print(*clot)); + + if (m_idHelperSvc->isEndcap(clot->identify()) != isEndcap) { + + if (segments.size() == 1) { + ATH_MSG_DEBUG("Inconsistent phi hit topology, keeping original"); + return new MuonSegment(**sit); + } else { + ATH_MSG_DEBUG("Inconsistent phi hit topology, dropping phi hit"); + continue; + } + } + clusters.push_back(clot); + continue; + } + } + } + } } - if( !aSegment ) return 0; + if (!aSegment) return 0; ATH_MSG_DEBUG(" collected clusters " << clusters.size()); - const MuonSegment* seg = m_triggerHitsAssociator->associateTriggerHits(*aSegment,clusters,true); - - if( seg ) ATH_MSG_DEBUG(" Merged segment " << m_printer->print(*seg)); - else ATH_MSG_DEBUG(" trigger hit association failed"); + const MuonSegment* seg = m_triggerHitsAssociator->associateTriggerHits(*aSegment, clusters, true); + + if (seg) + ATH_MSG_DEBUG(" Merged segment " << m_printer->print(*seg)); + else + ATH_MSG_DEBUG(" trigger hit association failed"); return seg; - } } +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentMerger.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentMerger.h index c97e4faade3cf182956f931f33257346bcff864b..f183191fe1fa6f09b3d76a79d885243265095ff4 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentMerger.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentMerger.h @@ -5,75 +5,90 @@ #ifndef MUON_MUONSEGMENTMERGER_H #define MUON_MUONSEGMENTMERGER_H -#include "MuonSegmentMakerToolInterfaces/IMuonSegmentMerger.h" - #include "AthenaBaseComps/AthAlgTool.h" #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" -#include "MuonSegment/MuonSegment.h" -#include "TrkEventPrimitives/FitQuality.h" -#include "MuonRecHelperTools/IMuonEDMHelperSvc.h" #include "MuonIdHelpers/IMuonIdHelperSvc.h" +#include "MuonRecHelperTools/IMuonEDMHelperSvc.h" #include "MuonRecHelperTools/MuonEDMPrinterTool.h" +#include "MuonSegment/MuonSegment.h" +#include "MuonSegmentMakerToolInterfaces/IMuonSegmentMerger.h" #include "MuonSegmentMakerToolInterfaces/IMuonSegmentTriggerHitAssociator.h" +#include "TrkEventPrimitives/FitQuality.h" namespace Muon { - /** - @brief tool to remove overlaps between segments +/** + @brief tool to remove overlaps between segments - */ - class MuonSegmentMerger : virtual public IMuonSegmentMerger, public AthAlgTool { +*/ +class MuonSegmentMerger : virtual public IMuonSegmentMerger, public AthAlgTool { public: /** @brief constructor */ - MuonSegmentMerger(const std::string&,const std::string&,const IInterface*); + MuonSegmentMerger(const std::string&, const std::string&, const IInterface*); /** @brief destructor */ - virtual ~MuonSegmentMerger()=default; - + virtual ~MuonSegmentMerger() = default; + /** @brief AlgTool initilize */ StatusCode initialize(); - - /** @brief find segments sharing all MDT hits but different phi hits The caller should NOT take ownership of the segments */ - SegVec findDuplicates( const SegVec& segments ) const; + + /** @brief find segments sharing all MDT hits but different phi hits The caller should NOT take ownership of the + * segments */ + SegVec findDuplicates(const SegVec& segments) const; /** @brief merges duplicates in a vector of segments. The callers should take ownership of the new Segments.*/ - const MuonSegment* merge( const SegVec& segments ) const; - + const MuonSegment* merge(const SegVec& segments) const; + /** @brief group all segments that have at least one overlapping cluster */ - std::vector< SegVec > resolveClusterOverlaps( const SegVec& segments ) const ; + std::vector<SegVec> resolveClusterOverlaps(const SegVec& segments) const; private: + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; + ServiceHandle<Muon::IMuonEDMHelperSvc> m_edmHelperSvc{ + this, + "edmHelper", + "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", + "Handle to the service providing the IMuonEDMHelperSvc interface", + }; //!< EDM Helper tool - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - ServiceHandle<Muon::IMuonEDMHelperSvc> m_edmHelperSvc {this, "edmHelper", - "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", - "Handle to the service providing the IMuonEDMHelperSvc interface" }; //!< EDM Helper tool - ToolHandle<Muon::MuonEDMPrinterTool> m_printer; //!< EDM printer tool - ToolHandle<Muon::IMuonSegmentTriggerHitAssociator> m_triggerHitsAssociator; //!< trigger hit associator + ToolHandle<Muon::MuonEDMPrinterTool> m_printer{ + this, + "MuonEDMPrinterTool", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; //!< EDM printer tool + ToolHandle<Muon::IMuonSegmentTriggerHitAssociator> m_triggerHitsAssociator{ + this, + "TriggerHitAssociator", + "Muon::DCMathSegmentMaker/DCMathSegmentMaker", + }; //!< trigger hit associator +}; - }; - - class LocalSortSegmentsByChi2 { +class LocalSortSegmentsByChi2 { public: - bool operator()( const MuonSegment* seg1, const MuonSegment* seg2){ - - // prefer segments with fit quality (always expected) - const Trk::FitQuality* fq1 = seg1->fitQuality(); - const Trk::FitQuality* fq2 = seg2->fitQuality(); - if( !fq1 && fq2 ) return false; - if( fq1 && !fq2 ) return true; - if(!fq1 && !fq2) return false; - - if( fq1->numberDoF() > fq2->numberDoF() ) return true; - if( fq1->numberDoF() < fq2->numberDoF() ) return false; - - // select candidate with smallest chi2 - double chi2Ndof1 = fq1->chiSquared()/fq1->numberDoF(); - double chi2Ndof2 = fq2->chiSquared()/fq2->numberDoF(); - return chi2Ndof1 < chi2Ndof2; + bool operator()(const MuonSegment* seg1, const MuonSegment* seg2) + { + + // prefer segments with fit quality (always expected) + const Trk::FitQuality* fq1 = seg1->fitQuality(); + const Trk::FitQuality* fq2 = seg2->fitQuality(); + if (!fq1 && fq2) return false; + if (fq1 && !fq2) return true; + if (!fq1 && !fq2) return false; + + if (fq1->numberDoF() > fq2->numberDoF()) return true; + if (fq1->numberDoF() < fq2->numberDoF()) return false; + + // select candidate with smallest chi2 + double chi2Ndof1 = fq1->chiSquared() / fq1->numberDoF(); + double chi2Ndof2 = fq2->chiSquared() / fq2->numberDoF(); + return chi2Ndof1 < chi2Ndof2; } - }; +}; -} +} // namespace Muon #endif diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentOverlapRemovalTool.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentOverlapRemovalTool.cxx index 14fcc8bc920017907e800e20652d043e1c85c879..3e4b5ea9dad4539d6be84216fda91b2c08c49be7 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentOverlapRemovalTool.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentOverlapRemovalTool.cxx @@ -5,199 +5,204 @@ #include "MuonSegmentOverlapRemovalTool.h" #include "MuonSegment/MuonSegment.h" - -#include "MuonSegmentMakerUtils/MuonSegmentKey.h" #include "MuonSegmentMakerUtils/CompareMuonSegmentKeys.h" - +#include "MuonSegmentMakerUtils/MuonSegmentKey.h" #include "TrkEventPrimitives/FitQuality.h" namespace Muon { - MuonSegmentOverlapRemovalTool::MuonSegmentOverlapRemovalTool(const std::string& ty,const std::string& na,const IInterface* pa) - : AthAlgTool(ty,na,pa), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool") - { +MuonSegmentOverlapRemovalTool::MuonSegmentOverlapRemovalTool(const std::string& ty, const std::string& na, + const IInterface* pa) + : AthAlgTool(ty, na, pa) +{ declareInterface<IMuonSegmentOverlapRemovalTool>(this); - declareProperty("RemovePartialOverlaps",m_removePartialOverlaps = true,"removal partial overlaps between segments"); - declareProperty("OverlapFractionCut",m_overlapFractionCut = 0.8,"Cut overlap fraction, if fraction is smaller than cut both segments are kept"); - } + declareProperty("RemovePartialOverlaps", m_removePartialOverlaps = true, + "removal partial overlaps between segments"); + declareProperty("OverlapFractionCut", m_overlapFractionCut = 0.8, + "Cut overlap fraction, if fraction is smaller than cut both segments are kept"); +} - StatusCode MuonSegmentOverlapRemovalTool::initialize() - { - ATH_CHECK(AlgTool::initialize()); +StatusCode +MuonSegmentOverlapRemovalTool::initialize() +{ + ATH_CHECK(AlgTool::initialize()); ATH_CHECK(m_edmHelperSvc.retrieve()); ATH_CHECK(m_printer.retrieve()); ATH_CHECK(m_idHelperSvc.retrieve()); return StatusCode::SUCCESS; - } +} - void MuonSegmentOverlapRemovalTool::removeDuplicates( Trk::SegmentCollection* segments ) const { +void +MuonSegmentOverlapRemovalTool::removeDuplicates(Trk::SegmentCollection* segments) const +{ - ATH_MSG_DEBUG(" working on segment vector of size " << segments->size() ); + ATH_MSG_DEBUG(" working on segment vector of size " << segments->size()); CompareMuonSegmentKeys compareSegmentKeys; // create a vector with pairs of MuonSegmentKey and a pointer to the corresponding segment to resolve ambiguities - std::vector< std::pair<MuonSegmentKey,MuonSegment*> > goodSegments; + std::vector<std::pair<MuonSegmentKey, MuonSegment*> > goodSegments; goodSegments.reserve(segments->size()); std::vector<MuonSegment*> segmentsToErase; // loop over new segments, copy them into collection - Trk::SegmentCollection::iterator sit = segments->begin(); - Trk::SegmentCollection::iterator sit_end = segments->end(); - for( ; sit!=sit_end;++sit){ - - // create segment key object - Trk::Segment* tseg=*sit; - MuonSegment* seg=dynamic_cast<MuonSegment*>(tseg); - if(!seg){ - ATH_MSG_WARNING("segment is not MuonSegment"); - continue; - } - MuonSegmentKey sk(*seg); - Identifier chId = m_edmHelperSvc->chamberId(*seg); - bool isCsc = m_idHelperSvc->isCsc(chId); - - // should this segment be inserted? - bool insertAsGood(true); - - // loop over already accepted segments and compare the current segment with the good ones - std::vector< std::pair<MuonSegmentKey,MuonSegment*> >::iterator gsit = goodSegments.begin(); - std::vector< std::pair<MuonSegmentKey,MuonSegment*> >::iterator gsit_end = goodSegments.end(); - for( ;gsit!=gsit_end;++gsit ){ - CompareMuonSegmentKeys::OverlapResult overlapResult = compareSegmentKeys( gsit->first, sk ); - if( overlapResult == CompareMuonSegmentKeys::Identical ) { - // for now keep the one with the best chi2 - const Trk::FitQuality* fq1 = gsit->second->fitQuality(); - const Trk::FitQuality* fq2 = seg->fitQuality(); - double chi2good = fq1 ? fq1->chiSquared() : 1e10; - double chi2current = fq2 ? fq2->chiSquared() : 1e10; - // we should not insert this segment - if( chi2good > chi2current ) { - ATH_MSG_VERBOSE(" replacing (chi2) " << m_printer->print(*gsit->second) << std::endl - << " with " << m_printer->print(**sit) ); - - // good segment of worse quality, replace it - segmentsToErase.push_back(gsit->second); - gsit->first = sk; - gsit->second = seg; - - - }else{ - ATH_MSG_VERBOSE(" discarding (chi2) " << m_printer->print(*seg) ); - segmentsToErase.push_back(seg); - } - insertAsGood = false; - break; - }else if( overlapResult == CompareMuonSegmentKeys::SuperSet ){ - // good segment of better quality, keep it and discard current segment - ATH_MSG_VERBOSE(" discarding (subset) " << m_printer->print(*seg) ); - segmentsToErase.push_back(seg); - insertAsGood = false; - break; - }else if( overlapResult == CompareMuonSegmentKeys::SubSet ){ - // good segment of worse quality, replace it - ATH_MSG_VERBOSE(" replacing (superset) " << m_printer->print(*gsit->second) << std::endl - << " with " << m_printer->print(*seg) ); - segmentsToErase.push_back(gsit->second); - gsit->first = sk; - gsit->second = seg; - insertAsGood = false; - break; - }else if( overlapResult == CompareMuonSegmentKeys::PartialOverlap && m_removePartialOverlaps ){ - - // keep CSC segments with partial overlap - if( isCsc ) continue; - - // partial overlap, for now keep the one most hits - if( compareSegmentKeys.segment1Size < compareSegmentKeys.segment2Size ){ - ATH_MSG_VERBOSE(" replacing (mdt hits) " << m_printer->print(*gsit->second) << std::endl - << " with " << m_printer->print(*seg) ); - - // good segment of worse quality, replace it - segmentsToErase.push_back(gsit->second); - gsit->first = sk; - gsit->second = seg; - insertAsGood=false; - }else if( compareSegmentKeys.segment1Size == compareSegmentKeys.segment2Size ){ - // same size - - // if the original entry has more trigger hits discard current segment - if( compareSegmentKeys.segment1SizeTrigger > compareSegmentKeys.segment2SizeTrigger ){ - ATH_MSG_VERBOSE(" discarding (trigger hits) " << m_printer->print(*seg) ); - segmentsToErase.push_back(seg); - insertAsGood = false; - break; - }else if( compareSegmentKeys.segment1SizeTrigger < compareSegmentKeys.segment2SizeTrigger ){ - // good segment of worse quality, replace it - ATH_MSG_VERBOSE(" replacing (trigger hits) " << m_printer->print(*gsit->second) << std::endl - << " with " << m_printer->print(*seg) ); - segmentsToErase.push_back(gsit->second); - gsit->first = sk; - gsit->second = seg; - insertAsGood = false; - break; - }else if( compareSegmentKeys.segment1SizeTrigger == compareSegmentKeys.segment2SizeTrigger ){ - - // for now look at the overlap fraction - - } - // calculate the overlap fraction - double overlapFraction = (double)compareSegmentKeys.intersectionSize/(double)compareSegmentKeys.segment1Size; - if( overlapFraction > m_overlapFractionCut ){ - ATH_MSG_VERBOSE(" discarding (overlap fraction) " << m_printer->print(*seg) ); - segmentsToErase.push_back(seg); - insertAsGood = false; - break; - } - - continue; - }else{ - ATH_MSG_VERBOSE(" discarding " << m_printer->print(*seg) ); - segmentsToErase.push_back(seg); - } - insertAsGood = false; - break; - }else if( overlapResult == CompareMuonSegmentKeys::NoOverlap ){ - // no overlap, move on to next segment - continue; - }else if( overlapResult == CompareMuonSegmentKeys::Unknown ){ - ATH_MSG_WARNING(" Got invalid return argument comparing segments: " << compareSegmentKeys.print(overlapResult) ); - continue; - } - } - - // add segment if needed - if( insertAsGood ) { - ATH_MSG_VERBOSE(" no overlap " << m_printer->print(*seg) ); - goodSegments.push_back( std::make_pair(sk,seg) ); - } - } - - //erase rejected segments - for(std::vector<MuonSegment*>::iterator vit=segmentsToErase.begin();vit!=segmentsToErase.end();++vit){ - sit = segments->begin(); - for(; sit!=sit_end;++sit){ - //remove bad segments from collection, then delete them - Trk::Segment* tseg=*sit; - if((*vit)==dynamic_cast<MuonSegment*>(tseg)){ - segments->erase(sit); - break; - } - } - if(sit==sit_end) ATH_MSG_WARNING("did not find bad segment for deletion"); + Trk::SegmentCollection::iterator sit = segments->begin(); + Trk::SegmentCollection::iterator sit_end = segments->end(); + for (; sit != sit_end; ++sit) { + + // create segment key object + Trk::Segment* tseg = *sit; + MuonSegment* seg = dynamic_cast<MuonSegment*>(tseg); + if (!seg) { + ATH_MSG_WARNING("segment is not MuonSegment"); + continue; + } + MuonSegmentKey sk(*seg); + Identifier chId = m_edmHelperSvc->chamberId(*seg); + bool isCsc = m_idHelperSvc->isCsc(chId); + + // should this segment be inserted? + bool insertAsGood(true); + + // loop over already accepted segments and compare the current segment with the good ones + std::vector<std::pair<MuonSegmentKey, MuonSegment*> >::iterator gsit = goodSegments.begin(); + std::vector<std::pair<MuonSegmentKey, MuonSegment*> >::iterator gsit_end = goodSegments.end(); + for (; gsit != gsit_end; ++gsit) { + CompareMuonSegmentKeys::OverlapResult overlapResult = compareSegmentKeys(gsit->first, sk); + if (overlapResult == CompareMuonSegmentKeys::Identical) { + // for now keep the one with the best chi2 + const Trk::FitQuality* fq1 = gsit->second->fitQuality(); + const Trk::FitQuality* fq2 = seg->fitQuality(); + double chi2good = fq1 ? fq1->chiSquared() : 1e10; + double chi2current = fq2 ? fq2->chiSquared() : 1e10; + // we should not insert this segment + if (chi2good > chi2current) { + ATH_MSG_VERBOSE(" replacing (chi2) " << m_printer->print(*gsit->second) << std::endl + << " with " << m_printer->print(**sit)); + + // good segment of worse quality, replace it + segmentsToErase.push_back(gsit->second); + gsit->first = sk; + gsit->second = seg; + + + } else { + ATH_MSG_VERBOSE(" discarding (chi2) " << m_printer->print(*seg)); + segmentsToErase.push_back(seg); + } + insertAsGood = false; + break; + } else if (overlapResult == CompareMuonSegmentKeys::SuperSet) { + // good segment of better quality, keep it and discard current segment + ATH_MSG_VERBOSE(" discarding (subset) " << m_printer->print(*seg)); + segmentsToErase.push_back(seg); + insertAsGood = false; + break; + } else if (overlapResult == CompareMuonSegmentKeys::SubSet) { + // good segment of worse quality, replace it + ATH_MSG_VERBOSE(" replacing (superset) " << m_printer->print(*gsit->second) << std::endl + << " with " << m_printer->print(*seg)); + segmentsToErase.push_back(gsit->second); + gsit->first = sk; + gsit->second = seg; + insertAsGood = false; + break; + } else if (overlapResult == CompareMuonSegmentKeys::PartialOverlap && m_removePartialOverlaps) { + + // keep CSC segments with partial overlap + if (isCsc) continue; + + // partial overlap, for now keep the one most hits + if (compareSegmentKeys.segment1Size < compareSegmentKeys.segment2Size) { + ATH_MSG_VERBOSE(" replacing (mdt hits) " << m_printer->print(*gsit->second) << std::endl + << " with " << m_printer->print(*seg)); + + // good segment of worse quality, replace it + segmentsToErase.push_back(gsit->second); + gsit->first = sk; + gsit->second = seg; + insertAsGood = false; + } else if (compareSegmentKeys.segment1Size == compareSegmentKeys.segment2Size) { + // same size + + // if the original entry has more trigger hits discard current segment + if (compareSegmentKeys.segment1SizeTrigger > compareSegmentKeys.segment2SizeTrigger) { + ATH_MSG_VERBOSE(" discarding (trigger hits) " << m_printer->print(*seg)); + segmentsToErase.push_back(seg); + insertAsGood = false; + break; + } else if (compareSegmentKeys.segment1SizeTrigger < compareSegmentKeys.segment2SizeTrigger) { + // good segment of worse quality, replace it + ATH_MSG_VERBOSE(" replacing (trigger hits) " << m_printer->print(*gsit->second) << std::endl + << " with " << m_printer->print(*seg)); + segmentsToErase.push_back(gsit->second); + gsit->first = sk; + gsit->second = seg; + insertAsGood = false; + break; + } else if (compareSegmentKeys.segment1SizeTrigger == compareSegmentKeys.segment2SizeTrigger) { + + // for now look at the overlap fraction + } + // calculate the overlap fraction + double overlapFraction = + (double)compareSegmentKeys.intersectionSize / (double)compareSegmentKeys.segment1Size; + if (overlapFraction > m_overlapFractionCut) { + ATH_MSG_VERBOSE(" discarding (overlap fraction) " << m_printer->print(*seg)); + segmentsToErase.push_back(seg); + insertAsGood = false; + break; + } + + continue; + } else { + ATH_MSG_VERBOSE(" discarding " << m_printer->print(*seg)); + segmentsToErase.push_back(seg); + } + insertAsGood = false; + break; + } else if (overlapResult == CompareMuonSegmentKeys::NoOverlap) { + // no overlap, move on to next segment + continue; + } else if (overlapResult == CompareMuonSegmentKeys::Unknown) { + ATH_MSG_WARNING( + " Got invalid return argument comparing segments: " << compareSegmentKeys.print(overlapResult)); + continue; + } + } + + // add segment if needed + if (insertAsGood) { + ATH_MSG_VERBOSE(" no overlap " << m_printer->print(*seg)); + goodSegments.push_back(std::make_pair(sk, seg)); + } } - } + // erase rejected segments + for (std::vector<MuonSegment*>::iterator vit = segmentsToErase.begin(); vit != segmentsToErase.end(); ++vit) { + sit = segments->begin(); + for (; sit != sit_end; ++sit) { + // remove bad segments from collection, then delete them + Trk::Segment* tseg = *sit; + if ((*vit) == dynamic_cast<MuonSegment*>(tseg)) { + segments->erase(sit); + break; + } + } + if (sit == sit_end) ATH_MSG_WARNING("did not find bad segment for deletion"); + } +} - const MuonSegmentCombination* MuonSegmentOverlapRemovalTool::removeDuplicates( const MuonSegmentCombination& combi ) const { +const MuonSegmentCombination* +MuonSegmentOverlapRemovalTool::removeDuplicates(const MuonSegmentCombination& combi) const +{ // store pointers to segments that should be kept std::set<MuonSegment*> segmentsToBeKept; - unsigned int nsegments = 0; // total number of segments + unsigned int nsegments = 0; // total number of segments unsigned int nstations = combi.numberOfStations(); @@ -206,203 +211,207 @@ namespace Muon { // loop over segments, add them to the chamber layers // loop over chambers in combi and extract segments - for(unsigned int i=0; i<nstations; ++i){ - - // loop over segments in station - MuonSegmentCombination::SegmentVec* stationSegs = combi.stationSegments( i ) ; - - // check if not empty - if( !stationSegs || stationSegs->empty() ) continue; - - nsegments += stationSegs->size(); - - // clean segments - SegVec cleanedSegments = removeDuplicates(*stationSegs); - segmentsToBeKept.insert( cleanedSegments.begin(),cleanedSegments.end() ); + for (unsigned int i = 0; i < nstations; ++i) { + + // loop over segments in station + MuonSegmentCombination::SegmentVec* stationSegs = combi.stationSegments(i); + + // check if not empty + if (!stationSegs || stationSegs->empty()) continue; + + nsegments += stationSegs->size(); + + // clean segments + SegVec cleanedSegments = removeDuplicates(*stationSegs); + segmentsToBeKept.insert(cleanedSegments.begin(), cleanedSegments.end()); } // check whether all segments were kept - if( nsegments == segmentsToBeKept.size() ){ - ATH_MSG_DEBUG(" no segments removed "); - return &combi; + if (nsegments == segmentsToBeKept.size()) { + ATH_MSG_DEBUG(" no segments removed "); + return &combi; } MuonSegmentCombination* newCombi = new MuonSegmentCombination(); // create a new combination removing segments that overlap - for(unsigned int i=0; i<nstations; ++i){ - - // loop over segments in station - MuonSegmentCombination::SegmentVec* stationSegs = combi.stationSegments( i ) ; - - // check if not empty - if( !stationSegs || stationSegs->empty() ) continue; - - std::unique_ptr<std::vector< std::unique_ptr<MuonSegment> > > segVec(new std::vector< std::unique_ptr< MuonSegment> >()); - segVec->reserve( stationSegs->size() ); - - // loop over segments and add them if they are in the keep set - MuonSegmentCombination::SegmentVec::const_iterator ipsg=stationSegs->begin(); - MuonSegmentCombination::SegmentVec::const_iterator ipsg_end=stationSegs->end(); - for (;ipsg!=ipsg_end;++ipsg){ - - MuonSegment* seg = (*ipsg).get(); - - if( !segmentsToBeKept.count(seg) ){ - continue; - }else{ - segVec->push_back( std::unique_ptr<MuonSegment>(seg->clone()) ); - } - } - - // if not empty add segments - if( !segVec->empty() ) newCombi->addSegments( std::move(segVec) ); + for (unsigned int i = 0; i < nstations; ++i) { + + // loop over segments in station + MuonSegmentCombination::SegmentVec* stationSegs = combi.stationSegments(i); + + // check if not empty + if (!stationSegs || stationSegs->empty()) continue; + + std::unique_ptr<std::vector<std::unique_ptr<MuonSegment> > > segVec( + new std::vector<std::unique_ptr<MuonSegment> >()); + segVec->reserve(stationSegs->size()); + + // loop over segments and add them if they are in the keep set + MuonSegmentCombination::SegmentVec::const_iterator ipsg = stationSegs->begin(); + MuonSegmentCombination::SegmentVec::const_iterator ipsg_end = stationSegs->end(); + for (; ipsg != ipsg_end; ++ipsg) { + + MuonSegment* seg = (*ipsg).get(); + + if (!segmentsToBeKept.count(seg)) { + continue; + } else { + segVec->push_back(std::unique_ptr<MuonSegment>(seg->clone())); + } + } + + // if not empty add segments + if (!segVec->empty()) newCombi->addSegments(std::move(segVec)); } - ATH_MSG_DEBUG(" removed " << nsegments-segmentsToBeKept.size() << " duplicates, new size " << segmentsToBeKept.size() ); - + ATH_MSG_DEBUG(" removed " << nsegments - segmentsToBeKept.size() << " duplicates, new size " + << segmentsToBeKept.size()); + return newCombi; - } +} - //this applies only to the case of cleaning MuonSegmentCombinations, above - //currently not used, maybe it can be removed entirely? - MuonSegmentOverlapRemovalTool::SegVec - MuonSegmentOverlapRemovalTool::removeDuplicates( MuonSegmentCombination::SegmentVec& segments ) const { +// this applies only to the case of cleaning MuonSegmentCombinations, above +// currently not used, maybe it can be removed entirely? +MuonSegmentOverlapRemovalTool::SegVec +MuonSegmentOverlapRemovalTool::removeDuplicates(MuonSegmentCombination::SegmentVec& segments) const +{ - ATH_MSG_DEBUG(" working on segment vector of size " << segments.size() ); + ATH_MSG_DEBUG(" working on segment vector of size " << segments.size()); CompareMuonSegmentKeys compareSegmentKeys; // create a vector with pairs of MuonSegmentKey and a pointer to the corresponding segment to resolve ambiguities - std::vector< std::pair<MuonSegmentKey,MuonSegment*> > goodSegments; + std::vector<std::pair<MuonSegmentKey, MuonSegment*> > goodSegments; goodSegments.reserve(segments.size()); // loop over new segments, copy them into collection - MuonSegmentCombination::SegmentVec::iterator sit = segments.begin(); + MuonSegmentCombination::SegmentVec::iterator sit = segments.begin(); MuonSegmentCombination::SegmentVec::iterator sit_end = segments.end(); - for( ; sit!=sit_end;++sit){ - - // create segment key object - MuonSegment* seg=(*sit).get(); - MuonSegmentKey sk(*seg); - Identifier chId = m_edmHelperSvc->chamberId(*seg); - bool isCsc = m_idHelperSvc->isCsc(chId); - - // should this segment be inserted? - bool insertAsGood(true); - - // loop over already accepted segments and compare the current segment with the good ones - std::vector< std::pair<MuonSegmentKey,MuonSegment*> >::iterator gsit = goodSegments.begin(); - std::vector< std::pair<MuonSegmentKey,MuonSegment*> >::iterator gsit_end = goodSegments.end(); - for( ;gsit!=gsit_end;++gsit ){ - CompareMuonSegmentKeys::OverlapResult overlapResult = compareSegmentKeys( gsit->first, sk ); - if( overlapResult == CompareMuonSegmentKeys::Identical ) { - // for now keep the one with the best chi2 - const Trk::FitQuality* fq1 = gsit->second->fitQuality(); - const Trk::FitQuality* fq2 = seg->fitQuality(); - double chi2good = fq1 ? fq1->chiSquared() : 1e10; - double chi2current = fq2 ? fq2->chiSquared() : 1e10; - // we should not insert this segment - if( chi2good > chi2current ) { - ATH_MSG_VERBOSE(" replacing (chi2) " << m_printer->print(*gsit->second) << std::endl - << " with " << m_printer->print(*seg) ); - - // good segment of worse quality, replace it - gsit->first = sk; - gsit->second = seg; - - }else{ - ATH_MSG_VERBOSE(" discarding (chi2) " << m_printer->print(*seg) ); - } - insertAsGood = false; - break; - }else if( overlapResult == CompareMuonSegmentKeys::SuperSet ){ - // good segment of better quality, keep it and discard current segment - ATH_MSG_VERBOSE(" discarding (subset) " << m_printer->print(*seg) ); - insertAsGood = false; - break; - }else if( overlapResult == CompareMuonSegmentKeys::SubSet ){ - // good segment of worse quality, replace it - ATH_MSG_VERBOSE(" replacing (superset) " << m_printer->print(*gsit->second) << std::endl - << " with " << m_printer->print(*seg) ); - gsit->first = sk; - gsit->second = seg; - insertAsGood = false; - break; - }else if( overlapResult == CompareMuonSegmentKeys::PartialOverlap && m_removePartialOverlaps ){ - - // keep CSC segments with partial overlap - if( isCsc ) continue; - - // partial overlap, for now keep the one most hits - if( compareSegmentKeys.segment1Size < compareSegmentKeys.segment2Size ){ - ATH_MSG_VERBOSE(" replacing (mdt hits) " << m_printer->print(*gsit->second) << std::endl - << " with " << m_printer->print(*seg) ); - - // good segment of worse quality, replace it - gsit->first = sk; - gsit->second = seg; - }else if( compareSegmentKeys.segment1Size == compareSegmentKeys.segment2Size ){ - // same size - - // if the original entry has more trigger hits discard current segment - if( compareSegmentKeys.segment1SizeTrigger > compareSegmentKeys.segment2SizeTrigger ){ - ATH_MSG_VERBOSE(" discarding (trigger hits) " << m_printer->print(*seg) ); - insertAsGood = false; - break; - }else if( compareSegmentKeys.segment1SizeTrigger < compareSegmentKeys.segment2SizeTrigger ){ - // good segment of worse quality, replace it - ATH_MSG_VERBOSE(" replacing (trigger hits) " << m_printer->print(*gsit->second) << std::endl - << " with " << m_printer->print(*seg) ); - gsit->first = sk; - gsit->second = seg; - insertAsGood = false; - break; - }else if( compareSegmentKeys.segment1SizeTrigger == compareSegmentKeys.segment2SizeTrigger ){ - - // for now look at the overlap fraction - - } - // calculate the overlap fraction - double overlapFraction = (double)compareSegmentKeys.intersectionSize/(double)compareSegmentKeys.segment1Size; - if( overlapFraction > m_overlapFractionCut ){ - ATH_MSG_VERBOSE(" discarding (overlap fraction) " << m_printer->print(*seg) ); - insertAsGood = false; - break; - } - - continue; - }else{ - ATH_MSG_VERBOSE(" discarding " << m_printer->print(*seg) ); - } - insertAsGood = false; - break; - }else if( overlapResult == CompareMuonSegmentKeys::NoOverlap ){ - // no overlap, move on to next segment - continue; - }else if( overlapResult == CompareMuonSegmentKeys::Unknown ){ - ATH_MSG_WARNING(" Got invalid return argument comparing segments: " << compareSegmentKeys.print(overlapResult) ); - continue; - } - } - - // add segment if needed - if( insertAsGood ) { - ATH_MSG_VERBOSE(" no overlap " << m_printer->print(*seg) ); - goodSegments.push_back( std::make_pair(sk,seg) ); - } - } - - SegVec cleanedSegments; - std::vector< std::pair<MuonSegmentKey,MuonSegment*> >::iterator gsit = goodSegments.begin(); - std::vector< std::pair<MuonSegmentKey,MuonSegment*> >::iterator gsit_end = goodSegments.end(); - for( ; gsit!=gsit_end;++gsit){ - cleanedSegments.push_back( gsit->second ); + for (; sit != sit_end; ++sit) { + + // create segment key object + MuonSegment* seg = (*sit).get(); + MuonSegmentKey sk(*seg); + Identifier chId = m_edmHelperSvc->chamberId(*seg); + bool isCsc = m_idHelperSvc->isCsc(chId); + + // should this segment be inserted? + bool insertAsGood(true); + + // loop over already accepted segments and compare the current segment with the good ones + std::vector<std::pair<MuonSegmentKey, MuonSegment*> >::iterator gsit = goodSegments.begin(); + std::vector<std::pair<MuonSegmentKey, MuonSegment*> >::iterator gsit_end = goodSegments.end(); + for (; gsit != gsit_end; ++gsit) { + CompareMuonSegmentKeys::OverlapResult overlapResult = compareSegmentKeys(gsit->first, sk); + if (overlapResult == CompareMuonSegmentKeys::Identical) { + // for now keep the one with the best chi2 + const Trk::FitQuality* fq1 = gsit->second->fitQuality(); + const Trk::FitQuality* fq2 = seg->fitQuality(); + double chi2good = fq1 ? fq1->chiSquared() : 1e10; + double chi2current = fq2 ? fq2->chiSquared() : 1e10; + // we should not insert this segment + if (chi2good > chi2current) { + ATH_MSG_VERBOSE(" replacing (chi2) " << m_printer->print(*gsit->second) << std::endl + << " with " << m_printer->print(*seg)); + + // good segment of worse quality, replace it + gsit->first = sk; + gsit->second = seg; + + } else { + ATH_MSG_VERBOSE(" discarding (chi2) " << m_printer->print(*seg)); + } + insertAsGood = false; + break; + } else if (overlapResult == CompareMuonSegmentKeys::SuperSet) { + // good segment of better quality, keep it and discard current segment + ATH_MSG_VERBOSE(" discarding (subset) " << m_printer->print(*seg)); + insertAsGood = false; + break; + } else if (overlapResult == CompareMuonSegmentKeys::SubSet) { + // good segment of worse quality, replace it + ATH_MSG_VERBOSE(" replacing (superset) " << m_printer->print(*gsit->second) << std::endl + << " with " << m_printer->print(*seg)); + gsit->first = sk; + gsit->second = seg; + insertAsGood = false; + break; + } else if (overlapResult == CompareMuonSegmentKeys::PartialOverlap && m_removePartialOverlaps) { + + // keep CSC segments with partial overlap + if (isCsc) continue; + + // partial overlap, for now keep the one most hits + if (compareSegmentKeys.segment1Size < compareSegmentKeys.segment2Size) { + ATH_MSG_VERBOSE(" replacing (mdt hits) " << m_printer->print(*gsit->second) << std::endl + << " with " << m_printer->print(*seg)); + + // good segment of worse quality, replace it + gsit->first = sk; + gsit->second = seg; + } else if (compareSegmentKeys.segment1Size == compareSegmentKeys.segment2Size) { + // same size + + // if the original entry has more trigger hits discard current segment + if (compareSegmentKeys.segment1SizeTrigger > compareSegmentKeys.segment2SizeTrigger) { + ATH_MSG_VERBOSE(" discarding (trigger hits) " << m_printer->print(*seg)); + insertAsGood = false; + break; + } else if (compareSegmentKeys.segment1SizeTrigger < compareSegmentKeys.segment2SizeTrigger) { + // good segment of worse quality, replace it + ATH_MSG_VERBOSE(" replacing (trigger hits) " << m_printer->print(*gsit->second) << std::endl + << " with " << m_printer->print(*seg)); + gsit->first = sk; + gsit->second = seg; + insertAsGood = false; + break; + } else if (compareSegmentKeys.segment1SizeTrigger == compareSegmentKeys.segment2SizeTrigger) { + + // for now look at the overlap fraction + } + // calculate the overlap fraction + double overlapFraction = + (double)compareSegmentKeys.intersectionSize / (double)compareSegmentKeys.segment1Size; + if (overlapFraction > m_overlapFractionCut) { + ATH_MSG_VERBOSE(" discarding (overlap fraction) " << m_printer->print(*seg)); + insertAsGood = false; + break; + } + + continue; + } else { + ATH_MSG_VERBOSE(" discarding " << m_printer->print(*seg)); + } + insertAsGood = false; + break; + } else if (overlapResult == CompareMuonSegmentKeys::NoOverlap) { + // no overlap, move on to next segment + continue; + } else if (overlapResult == CompareMuonSegmentKeys::Unknown) { + ATH_MSG_WARNING( + " Got invalid return argument comparing segments: " << compareSegmentKeys.print(overlapResult)); + continue; + } + } + + // add segment if needed + if (insertAsGood) { + ATH_MSG_VERBOSE(" no overlap " << m_printer->print(*seg)); + goodSegments.push_back(std::make_pair(sk, seg)); + } } - ATH_MSG_DEBUG(" Segments after removal " << cleanedSegments.size() - << " total number of removed segments " << segments.size() - cleanedSegments.size() ); - - return cleanedSegments; - } + SegVec cleanedSegments; + std::vector<std::pair<MuonSegmentKey, MuonSegment*> >::iterator gsit = goodSegments.begin(); + std::vector<std::pair<MuonSegmentKey, MuonSegment*> >::iterator gsit_end = goodSegments.end(); + for (; gsit != gsit_end; ++gsit) { + cleanedSegments.push_back(gsit->second); + } + ATH_MSG_DEBUG(" Segments after removal " << cleanedSegments.size() << " total number of removed segments " + << segments.size() - cleanedSegments.size()); + + return cleanedSegments; } + +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentOverlapRemovalTool.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentOverlapRemovalTool.h index 807dd124b8c2f159ba42183bb7ca59675d499af7..413ff4392175f817484c6b56ee1120f32782c622 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentOverlapRemovalTool.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentOverlapRemovalTools/src/MuonSegmentOverlapRemovalTool.h @@ -5,61 +5,71 @@ #ifndef MUON_MUONSEGMENTSOVERLAPREMOVALTOOL_H #define MUON_MUONSEGMENTSOVERLAPREMOVALTOOL_H -#include "MuonSegmentMakerToolInterfaces/IMuonSegmentOverlapRemovalTool.h" - #include "AthenaBaseComps/AthAlgTool.h" #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" -#include "MuonSegment/MuonSegmentCombination.h" -#include "MuonRecHelperTools/IMuonEDMHelperSvc.h" #include "MuonIdHelpers/IMuonIdHelperSvc.h" +#include "MuonRecHelperTools/IMuonEDMHelperSvc.h" #include "MuonRecHelperTools/MuonEDMPrinterTool.h" +#include "MuonSegment/MuonSegmentCombination.h" +#include "MuonSegmentMakerToolInterfaces/IMuonSegmentOverlapRemovalTool.h" namespace Muon { - - class MuonSegment; - /** - @brief tool to remove overlaps between segments +class MuonSegment; + +/** + @brief tool to remove overlaps between segments - */ - class MuonSegmentOverlapRemovalTool : virtual public IMuonSegmentOverlapRemovalTool, public AthAlgTool { +*/ +class MuonSegmentOverlapRemovalTool : virtual public IMuonSegmentOverlapRemovalTool, public AthAlgTool { public: /** @brief constructor */ - MuonSegmentOverlapRemovalTool(const std::string&,const std::string&,const IInterface*); + MuonSegmentOverlapRemovalTool(const std::string&, const std::string&, const IInterface*); /** @brief destructor */ - virtual ~MuonSegmentOverlapRemovalTool () {}; - + virtual ~MuonSegmentOverlapRemovalTool(){}; + /** @brief AlgTool initilize */ StatusCode initialize(); - - /** @brief remove duplicates from a vector of segments. The caller should take - ownership of the segments */ - void removeDuplicates( Trk::SegmentCollection* segments ) const; + + /** @brief remove duplicates from a vector of segments. The caller should take + ownership of the segments */ + void removeDuplicates(Trk::SegmentCollection* segments) const; /** @brief remove duplicates from a MuonSegmentCombination. - The callers should take ownership of the new SegmentCombination. If the combination is + The callers should take ownership of the new SegmentCombination. If the combination is unchanged the routine will return a pointer to the input combination. The caller should check whether the two pointers are identical and avoid a double delete */ - const MuonSegmentCombination* removeDuplicates( const MuonSegmentCombination& combi ) const; - + const MuonSegmentCombination* removeDuplicates(const MuonSegmentCombination& combi) const; + private: + // this is only needed now by the call to remove duplicates from a MuonSegmentCombination + // cleaning of MuonSegmentCombinations is turned off, so perhaps this can be removed entirely + SegVec removeDuplicates(MuonSegmentCombination::SegmentVec& segments) const; - //this is only needed now by the call to remove duplicates from a MuonSegmentCombination - //cleaning of MuonSegmentCombinations is turned off, so perhaps this can be removed entirely - SegVec removeDuplicates( MuonSegmentCombination::SegmentVec& segments ) const; + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{ + this, + "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc", + }; + ServiceHandle<Muon::IMuonEDMHelperSvc> m_edmHelperSvc{ + this, + "edmHelper", + "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", + "Handle to the service providing the IMuonEDMHelperSvc interface", + }; //!< EDM Helper tool - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - ServiceHandle<Muon::IMuonEDMHelperSvc> m_edmHelperSvc {this, "edmHelper", - "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", - "Handle to the service providing the IMuonEDMHelperSvc interface" }; //!< EDM Helper tool - ToolHandle<Muon::MuonEDMPrinterTool> m_printer; //!< EDM printer tool + ToolHandle<Muon::MuonEDMPrinterTool> m_printer{ + this, + "Printer", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; //!< EDM printer tool - bool m_removePartialOverlaps; //!< remove partial overlaps between segments - double m_overlapFractionCut; //!< cut on overlap fraction for segments - }; + bool m_removePartialOverlaps; //!< remove partial overlaps between segments + double m_overlapFractionCut; //!< cut on overlap fraction for segments +}; -} +} // namespace Muon #endif diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentHitSummaryTool.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentHitSummaryTool.cxx index 8225e670e024b79c1e12e90ac7d98d15dacf8616..588cda04520c7adefaaf6ddb32899abf325700ea 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentHitSummaryTool.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentHitSummaryTool.cxx @@ -3,207 +3,221 @@ */ #include "MuonSegmentHitSummaryTool.h" - -#include "MuonSegment/MuonSegment.h" -#include "MuonRIO_OnTrack/MdtDriftCircleOnTrack.h" -#include "MuonPrepRawData/MdtPrepData.h" -#include "MuonSegment/MuonSegmentQuality.h" #include <map> +#include "MuonPrepRawData/MdtPrepData.h" +#include "MuonRIO_OnTrack/MdtDriftCircleOnTrack.h" +#include "MuonSegment/MuonSegment.h" +#include "MuonSegment/MuonSegmentQuality.h" + namespace Muon { - MuonSegmentHitSummaryTool::MuonSegmentHitSummaryTool(const std::string& ty,const std::string& na,const IInterface* pa) : - AthAlgTool(ty,na,pa), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool") { +MuonSegmentHitSummaryTool::MuonSegmentHitSummaryTool(const std::string& ty, const std::string& na, const IInterface* pa) + : AthAlgTool(ty, na, pa) +{ declareInterface<IMuonSegmentHitSummaryTool>(this); - declareProperty("PositionAlongTubeCut",m_positionAlongTubeCut = -200., "Cut on distance from tube end used for holes, negative value means in the tube"); - declareProperty("MinimumADCValue",m_lowerADCBound = 70. ); - } + declareProperty("PositionAlongTubeCut", m_positionAlongTubeCut = -200., + "Cut on distance from tube end used for holes, negative value means in the tube"); + declareProperty("MinimumADCValue", m_lowerADCBound = 70.); +} - StatusCode MuonSegmentHitSummaryTool::initialize() - { +StatusCode +MuonSegmentHitSummaryTool::initialize() +{ ATH_CHECK(m_DetectorManagerKey.initialize()); ATH_CHECK(m_edmHelperSvc.retrieve()); ATH_CHECK(m_printer.retrieve()); ATH_CHECK(m_idHelperSvc.retrieve()); return StatusCode::SUCCESS; - } +} - MuonSegmentHitSummaryTool::HitCounts MuonSegmentHitSummaryTool::getHitCounts( const MuonSegment& seg ) const { +MuonSegmentHitSummaryTool::HitCounts +MuonSegmentHitSummaryTool::getHitCounts(const MuonSegment& seg) const +{ HitCounts hitCounts; - + SG::ReadCondHandle<MuonGM::MuonDetectorManager> DetectorManagerHandle{m_DetectorManagerKey}; - const MuonGM::MuonDetectorManager* MuonDetMgr{*DetectorManagerHandle}; - if(MuonDetMgr==nullptr){ - ATH_MSG_ERROR("Null pointer to the read MuonDetectorManager conditions object"); - return hitCounts; - } + const MuonGM::MuonDetectorManager* MuonDetMgr{*DetectorManagerHandle}; + if (MuonDetMgr == nullptr) { + ATH_MSG_ERROR("Null pointer to the read MuonDetectorManager conditions object"); + return hitCounts; + } // calculate shortest channel - double shortestTube = 1e9; - const MdtDriftCircleOnTrack* mdtShortest = 0; - bool transformIsSet = false; - Amg::Transform3D gToAMDB; - Amg::Vector3D lpos(0., 0., 0.); - Amg::Vector3D ldir; - double dxdy = 1.; - - Identifier chid = m_edmHelperSvc->chamberId(seg); + double shortestTube = 1e9; + const MdtDriftCircleOnTrack* mdtShortest = 0; + bool transformIsSet = false; + Amg::Transform3D gToAMDB; + Amg::Vector3D lpos(0., 0., 0.); + Amg::Vector3D ldir; + double dxdy = 1.; + + Identifier chid = m_edmHelperSvc->chamberId(seg); MuonStationIndex::StIndex stIndex = m_idHelperSvc->stationIndex(chid); - if( (!m_idHelperSvc->isCsc(chid) && stIndex == MuonStationIndex::EI) || - stIndex == MuonStationIndex::BO ) hitCounts.nexpectedTrigHitLayers = 1; - else if( stIndex == MuonStationIndex::BM ) hitCounts.nexpectedTrigHitLayers = 2; - else if( stIndex == MuonStationIndex::EM ) hitCounts.nexpectedTrigHitLayers = 3; - + if ((!m_idHelperSvc->isCsc(chid) && stIndex == MuonStationIndex::EI) || stIndex == MuonStationIndex::BO) + hitCounts.nexpectedTrigHitLayers = 1; + else if (stIndex == MuonStationIndex::BM) + hitCounts.nexpectedTrigHitLayers = 2; + else if (stIndex == MuonStationIndex::EM) + hitCounts.nexpectedTrigHitLayers = 3; + // loop over hits - std::vector<const Trk::MeasurementBase*>::const_iterator mit = seg.containedMeasurements().begin(); + std::vector<const Trk::MeasurementBase*>::const_iterator mit = seg.containedMeasurements().begin(); std::vector<const Trk::MeasurementBase*>::const_iterator mit_end = seg.containedMeasurements().end(); - for( ;mit!=mit_end;++mit ){ - - // get id and check that it is a muon hit id - Identifier id = m_edmHelperSvc->getIdentifier(**mit); - if( !id.is_valid() || !m_idHelperSvc->isMuon(id) ) continue; - - // check if MDT is so increase ml counter - if( m_idHelperSvc->isMdt(id) ){ - // get layer index - int ml = m_idHelperSvc->mdtIdHelper().multilayer(id); - int lay = m_idHelperSvc->mdtIdHelper().tubeLayer(id); - int tube = m_idHelperSvc->mdtIdHelper().tube(id); - int layIndex = 4*(ml-1) + (lay-1); // start at 0 rather than at 1 - MdtLayerIntersect& layIntersect = hitCounts.mdtHitHolePerLayerCounts[layIndex]; - ++layIntersect.nhits; - - const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(*mit); - if( mdt ){ - - const MuonGM::MdtReadoutElement* detEl = mdt->prepRawData() ? mdt->prepRawData()->detectorElement() : MuonDetMgr->getMdtReadoutElement(id); - if( !detEl ){ - ATH_MSG_WARNING(" could not get MdtReadoutElement for tube " << m_idHelperSvc->toString(id)); - continue; - } - - double tubeLen = detEl->getActiveTubeLength(lay,tube); - layIntersect.tubeLength = tubeLen; - if( !transformIsSet ){ - gToAMDB = detEl->GlobalToAmdbLRSTransform(); - lpos = gToAMDB*seg.globalPosition(); - ldir = (gToAMDB*seg.globalDirection()).unit(); - dxdy = std::abs(ldir.y()) > 0.001 ? ldir.x()/ldir.y() : 1000.; - transformIsSet = true; - } - if( !mdtShortest || tubeLen < shortestTube ){ - mdtShortest = mdt; - shortestTube = tubeLen; - } - } - if( m_idHelperSvc->mdtIdHelper().multilayer(id) == 1 ) ++hitCounts.nmdtHitsMl1; - else ++hitCounts.nmdtHitsMl2; - - if (mdt){ - if( mdt->prepRawData() ){ - int adc = mdt->prepRawData()->adc(); - if( adc > m_lowerADCBound ) ++hitCounts.nmdtHighADCHits; - if( adc > hitCounts.adcMax ) hitCounts.adcMax = adc; - } + for (; mit != mit_end; ++mit) { + + // get id and check that it is a muon hit id + Identifier id = m_edmHelperSvc->getIdentifier(**mit); + if (!id.is_valid() || !m_idHelperSvc->isMuon(id)) continue; + + // check if MDT is so increase ml counter + if (m_idHelperSvc->isMdt(id)) { + // get layer index + int ml = m_idHelperSvc->mdtIdHelper().multilayer(id); + int lay = m_idHelperSvc->mdtIdHelper().tubeLayer(id); + int tube = m_idHelperSvc->mdtIdHelper().tube(id); + int layIndex = 4 * (ml - 1) + (lay - 1); // start at 0 rather than at 1 + MdtLayerIntersect& layIntersect = hitCounts.mdtHitHolePerLayerCounts[layIndex]; + ++layIntersect.nhits; + + const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(*mit); + if (mdt) { + + const MuonGM::MdtReadoutElement* detEl = + mdt->prepRawData() ? mdt->prepRawData()->detectorElement() : MuonDetMgr->getMdtReadoutElement(id); + if (!detEl) { + ATH_MSG_WARNING(" could not get MdtReadoutElement for tube " << m_idHelperSvc->toString(id)); + continue; + } + + double tubeLen = detEl->getActiveTubeLength(lay, tube); + layIntersect.tubeLength = tubeLen; + if (!transformIsSet) { + gToAMDB = detEl->GlobalToAmdbLRSTransform(); + lpos = gToAMDB * seg.globalPosition(); + ldir = (gToAMDB * seg.globalDirection()).unit(); + dxdy = std::abs(ldir.y()) > 0.001 ? ldir.x() / ldir.y() : 1000.; + transformIsSet = true; + } + if (!mdtShortest || tubeLen < shortestTube) { + mdtShortest = mdt; + shortestTube = tubeLen; + } + } + if (m_idHelperSvc->mdtIdHelper().multilayer(id) == 1) + ++hitCounts.nmdtHitsMl1; + else + ++hitCounts.nmdtHitsMl2; + + if (mdt) { + if (mdt->prepRawData()) { + int adc = mdt->prepRawData()->adc(); + if (adc > m_lowerADCBound) ++hitCounts.nmdtHighADCHits; + if (adc > hitCounts.adcMax) hitCounts.adcMax = adc; + } + } + + } else if (m_idHelperSvc->isTrigger(id)) { + // get gasgap ID (same for eta/phi projection) + Identifier gasGapId = m_idHelperSvc->gasGapId(id); + bool measuresPhi = m_idHelperSvc->measuresPhi(id); + if (measuresPhi) + ++hitCounts.hitCountsPerLayer[gasGapId].nphiHits; + else + ++hitCounts.hitCountsPerLayer[gasGapId].netaHits; + } else { + bool measuresPhi = m_idHelperSvc->measuresPhi(id); + if (measuresPhi) + ++hitCounts.ncscHitsPhi; + else + ++hitCounts.ncscHitsEta; } - - }else if( m_idHelperSvc->isTrigger(id) ){ - // get gasgap ID (same for eta/phi projection) - Identifier gasGapId = m_idHelperSvc->gasGapId(id); - bool measuresPhi = m_idHelperSvc->measuresPhi(id); - if( measuresPhi ) ++hitCounts.hitCountsPerLayer[gasGapId].nphiHits; - else ++hitCounts.hitCountsPerLayer[gasGapId].netaHits; - }else{ - bool measuresPhi = m_idHelperSvc->measuresPhi(id); - if( measuresPhi ) ++hitCounts.ncscHitsPhi; - else ++hitCounts.ncscHitsEta; - } } const MuonSegmentQuality* quality = dynamic_cast<const MuonSegmentQuality*>(seg.fitQuality()); - if( quality ){ - std::vector<Identifier>::const_iterator hit = quality->channelsWithoutHit().begin(); - std::vector<Identifier>::const_iterator hit_end = quality->channelsWithoutHit().end(); - for( ;hit!=hit_end;++hit ){ - - const Identifier& id = *hit; - // get layer index - int ml = m_idHelperSvc->mdtIdHelper().multilayer(id); - int lay = m_idHelperSvc->mdtIdHelper().tubeLayer(id); - int tube = m_idHelperSvc->mdtIdHelper().tube(id); - int layIndex = 4*(ml-1) + (lay-1); // subtract 1 as fields start with 1 instead of 0 - MdtLayerIntersect& layIntersect = hitCounts.mdtHitHolePerLayerCounts[layIndex]; - ++layIntersect.nholes; - - if( transformIsSet ){ - const MuonGM::MdtReadoutElement* detEl = MuonDetMgr->getMdtReadoutElement(id); - if( !detEl ){ - ATH_MSG_WARNING(" could not get MdtReadoutElement for tube " << m_idHelperSvc->toString(id)); - continue; - } - double tubeLen = detEl->getActiveTubeLength(lay,tube); - double ytube = (gToAMDB*detEl->center(id)).y(); - double xint = dxdy*( ytube - lpos.y() ) + lpos.x(); - layIntersect.distFromTubeEnd = xint; - layIntersect.tubeLength = tubeLen; - } - } + if (quality) { + std::vector<Identifier>::const_iterator hit = quality->channelsWithoutHit().begin(); + std::vector<Identifier>::const_iterator hit_end = quality->channelsWithoutHit().end(); + for (; hit != hit_end; ++hit) { + + const Identifier& id = *hit; + // get layer index + int ml = m_idHelperSvc->mdtIdHelper().multilayer(id); + int lay = m_idHelperSvc->mdtIdHelper().tubeLayer(id); + int tube = m_idHelperSvc->mdtIdHelper().tube(id); + int layIndex = 4 * (ml - 1) + (lay - 1); // subtract 1 as fields start with 1 instead of 0 + MdtLayerIntersect& layIntersect = hitCounts.mdtHitHolePerLayerCounts[layIndex]; + ++layIntersect.nholes; + + if (transformIsSet) { + const MuonGM::MdtReadoutElement* detEl = MuonDetMgr->getMdtReadoutElement(id); + if (!detEl) { + ATH_MSG_WARNING(" could not get MdtReadoutElement for tube " << m_idHelperSvc->toString(id)); + continue; + } + double tubeLen = detEl->getActiveTubeLength(lay, tube); + double ytube = (gToAMDB * detEl->center(id)).y(); + double xint = dxdy * (ytube - lpos.y()) + lpos.x(); + layIntersect.distFromTubeEnd = xint; + layIntersect.tubeLength = tubeLen; + } + } } // now loop over map and get the counts for the trigger hits - std::map<Identifier,EtaPhiHitCount>::iterator it = hitCounts.hitCountsPerLayer.begin(); - std::map<Identifier,EtaPhiHitCount>::iterator it_end = hitCounts.hitCountsPerLayer.end(); - for( ;it!=it_end;++it ){ - - EtaPhiHitCount& counts = it->second; - - // increase eta/phi hit counts - if( counts.nphiHits != 0 ) ++hitCounts.nphiTrigHitLayers; - if( counts.netaHits != 0 ){ - ++hitCounts.netaTrigHitLayers; - - // if both eta/phi projection have entries increase paired counters - if( counts.nphiHits != 0 ) ++hitCounts.npairedTrigHitLayers; - } + std::map<Identifier, EtaPhiHitCount>::iterator it = hitCounts.hitCountsPerLayer.begin(); + std::map<Identifier, EtaPhiHitCount>::iterator it_end = hitCounts.hitCountsPerLayer.end(); + for (; it != it_end; ++it) { + + EtaPhiHitCount& counts = it->second; + + // increase eta/phi hit counts + if (counts.nphiHits != 0) ++hitCounts.nphiTrigHitLayers; + if (counts.netaHits != 0) { + ++hitCounts.netaTrigHitLayers; + + // if both eta/phi projection have entries increase paired counters + if (counts.nphiHits != 0) ++hitCounts.npairedTrigHitLayers; + } } - int currentEnclosedHoles = 0; - bool firstLayerWithHits = false; + int currentEnclosedHoles = 0; + bool firstLayerWithHits = false; // now loop over mdt map and get the number of enclosed holes - MdtLayerIntersectMap::iterator lit = hitCounts.mdtHitHolePerLayerCounts.begin(); + MdtLayerIntersectMap::iterator lit = hitCounts.mdtHitHolePerLayerCounts.begin(); MdtLayerIntersectMap::iterator lit_end = hitCounts.mdtHitHolePerLayerCounts.end(); - for( ;lit!=lit_end;++lit ){ - //std::cout << " layer " << lit->first << " hits " << lit->second.nhits << " holes " << lit->second.nholes << std::endl; - hitCounts.nmdtHoles += lit->second.nholes; - if( lit->second.nhits == 0 ){ - ++currentEnclosedHoles; - // count holes within chamber bounds - if( std::abs(lit->second.distFromTubeEnd) - 0.5*lit->second.tubeLength < m_positionAlongTubeCut ) ++hitCounts.nmdtHolesInChamber; - }else{ - if( firstLayerWithHits ) hitCounts.nmdtEnclosedHoles += currentEnclosedHoles; - currentEnclosedHoles = 0; - firstLayerWithHits = true; - } + for (; lit != lit_end; ++lit) { + // std::cout << " layer " << lit->first << " hits " << lit->second.nhits << " holes " << lit->second.nholes << + // std::endl; + hitCounts.nmdtHoles += lit->second.nholes; + if (lit->second.nhits == 0) { + ++currentEnclosedHoles; + // count holes within chamber bounds + if (std::abs(lit->second.distFromTubeEnd) - 0.5 * lit->second.tubeLength < m_positionAlongTubeCut) + ++hitCounts.nmdtHolesInChamber; + } else { + if (firstLayerWithHits) hitCounts.nmdtEnclosedHoles += currentEnclosedHoles; + currentEnclosedHoles = 0; + firstLayerWithHits = true; + } } - if( mdtShortest ){ - double posAlongTube = (mdtShortest->associatedSurface().transform().inverse()*seg.globalPosition()).z(); - if( 0.5*shortestTube - std::abs(posAlongTube) < 100. ) hitCounts.closeToChamberEdge = true; + if (mdtShortest) { + double posAlongTube = (mdtShortest->associatedSurface().transform().inverse() * seg.globalPosition()).z(); + if (0.5 * shortestTube - std::abs(posAlongTube) < 100.) hitCounts.closeToChamberEdge = true; } - if( seg.fitQuality() ){ - // combine chi2 with missing hit information and apply cut - hitCounts.segmentQuality = seg.fitQuality()->chiSquared() + 5.1*( hitCounts.nmdtHoles ); - if( seg.fitQuality()->numberDoF() > 0 ) hitCounts.segmentQuality /= seg.fitQuality()->numberDoF(); + if (seg.fitQuality()) { + // combine chi2 with missing hit information and apply cut + hitCounts.segmentQuality = seg.fitQuality()->chiSquared() + 5.1 * (hitCounts.nmdtHoles); + if (seg.fitQuality()->numberDoF() > 0) hitCounts.segmentQuality /= seg.fitQuality()->numberDoF(); } - - - return hitCounts; - } + return hitCounts; } + +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentHitSummaryTool.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentHitSummaryTool.h index 5a26e209f7c6f19fdd11a44c10a35badb19c4e42..368016c24b1e680cdc4b079f846e3b782b4caa9c 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentHitSummaryTool.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentHitSummaryTool.h @@ -5,51 +5,54 @@ #ifndef MUON_MUONSEGMENTHITSUMMARYTOOL_H #define MUON_MUONSEGMENTHITSUMMARYTOOL_H -#include "MuonSegmentMakerToolInterfaces/IMuonSegmentHitSummaryTool.h" #include "AthenaBaseComps/AthAlgTool.h" #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" - +#include "MuonIdHelpers/IMuonIdHelperSvc.h" +#include "MuonReadoutGeometry/MuonDetectorManager.h" #include "MuonRecHelperTools/IMuonEDMHelperSvc.h" #include "MuonRecHelperTools/MuonEDMPrinterTool.h" -#include "MuonReadoutGeometry/MuonDetectorManager.h" -#include "MuonIdHelpers/IMuonIdHelperSvc.h" +#include "MuonSegmentMakerToolInterfaces/IMuonSegmentHitSummaryTool.h" namespace Muon { - class MuonSegment; +class MuonSegment; } namespace Muon { - /** - @brief tool to calculate muon segment hit summary - */ - class MuonSegmentHitSummaryTool : virtual public IMuonSegmentHitSummaryTool, public AthAlgTool { +/** + @brief tool to calculate muon segment hit summary +*/ +class MuonSegmentHitSummaryTool : virtual public IMuonSegmentHitSummaryTool, public AthAlgTool { public: - MuonSegmentHitSummaryTool(const std::string&,const std::string&,const IInterface*); + MuonSegmentHitSummaryTool(const std::string&, const std::string&, const IInterface*); + + virtual ~MuonSegmentHitSummaryTool() = default; - virtual ~MuonSegmentHitSummaryTool()=default; - StatusCode initialize(); /** @brief calculate segment hit counts */ - virtual HitCounts getHitCounts( const MuonSegment& seg ) const; - - private: - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - ServiceHandle<Muon::IMuonEDMHelperSvc> m_edmHelperSvc {this, "edmHelper", - "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", - "Handle to the service providing the IMuonEDMHelperSvc interface" }; //!< EDM Helper tool - ToolHandle<Muon::MuonEDMPrinterTool> m_printer; //!< EDM printer tool - - SG::ReadCondHandleKey<MuonGM::MuonDetectorManager> m_DetectorManagerKey {this, "DetectorManagerKey", - "MuonDetectorManager", - "Key of input MuonDetectorManager condition data"}; - - double m_positionAlongTubeCut; //!< cut on the distance from the tube wall use for hole count - double m_lowerADCBound; //!< lower bound for good MDT hits + virtual HitCounts getHitCounts(const MuonSegment& seg) const; - }; - -} + private: + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{this, "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; + ServiceHandle<Muon::IMuonEDMHelperSvc> m_edmHelperSvc{ + this, "edmHelper", "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", + "Handle to the service providing the IMuonEDMHelperSvc interface"}; //!< EDM Helper tool + + ToolHandle<Muon::MuonEDMPrinterTool> m_printer{ + this, + "Printer", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; //!< EDM printer tool + + SG::ReadCondHandleKey<MuonGM::MuonDetectorManager> m_DetectorManagerKey{ + this, "DetectorManagerKey", "MuonDetectorManager", "Key of input MuonDetectorManager condition data"}; + + double m_positionAlongTubeCut; //!< cut on the distance from the tube wall use for hole count + double m_lowerADCBound; //!< lower bound for good MDT hits +}; + +} // namespace Muon #endif diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentSelectionTool.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentSelectionTool.cxx index 22fe6aa87052f7f8bd216f981b37678267978b6a..87d4b01a49b1ae7c7c12d66d11479358bdd312ba 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentSelectionTool.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentSelectionTool.cxx @@ -3,252 +3,267 @@ */ #include "MuonSegmentSelectionTool.h" - -#include "MuonSegment/MuonSegment.h" -#include "MuonRIO_OnTrack/MdtDriftCircleOnTrack.h" -#include "MuonPrepRawData/MdtPrepData.h" -#include "MuonSegment/MuonSegmentQuality.h" #include <map> +#include "MuonPrepRawData/MdtPrepData.h" +#include "MuonRIO_OnTrack/MdtDriftCircleOnTrack.h" +#include "MuonSegment/MuonSegment.h" +#include "MuonSegment/MuonSegmentQuality.h" + namespace Muon { - MuonSegmentSelectionTool::MuonSegmentSelectionTool(const std::string& ty,const std::string& na,const IInterface* pa) : - AthAlgTool(ty,na,pa), - m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"), - m_hitSummaryTool("Muon::MuonSegmentHitSummaryTool/MuonSegmentHitSummaryTool", this) - { +MuonSegmentSelectionTool::MuonSegmentSelectionTool(const std::string& ty, const std::string& na, const IInterface* pa) + : AthAlgTool(ty, na, pa) +{ declareInterface<IMuonSegmentSelectionTool>(this); - declareProperty("SegmentQualityCut",m_cutSegmentQuality = 10.); - declareProperty("MinADCPerSegmentCut",m_minAdcPerSegmentCut = 70. ); - declareProperty("GoodADCFractionCut",m_adcFractionCut = -1. ); - } + declareProperty("SegmentQualityCut", m_cutSegmentQuality = 10.); + declareProperty("MinADCPerSegmentCut", m_minAdcPerSegmentCut = 70.); + declareProperty("GoodADCFractionCut", m_adcFractionCut = -1.); +} - StatusCode MuonSegmentSelectionTool::initialize() - { +StatusCode +MuonSegmentSelectionTool::initialize() +{ ATH_CHECK(m_edmHelperSvc.retrieve()); ATH_CHECK(m_printer.retrieve()); ATH_CHECK(m_idHelperSvc.retrieve()); ATH_CHECK(m_hitSummaryTool.retrieve()); return StatusCode::SUCCESS; - } +} - int MuonSegmentSelectionTool::quality( const MuonSegment& seg, bool ignoreHoles, bool useEta, bool usePhi ) const { +int +MuonSegmentSelectionTool::quality(const MuonSegment& seg, bool ignoreHoles, bool useEta, bool usePhi) const +{ Identifier chid = m_edmHelperSvc->chamberId(seg); - if( !chid.is_valid() ) { - ATH_MSG_WARNING("Got invalid segment identifier"); - return -1; + if (!chid.is_valid()) { + ATH_MSG_WARNING("Got invalid segment identifier"); + return -1; } - + // different treatment for CSC and MDT segments // mdt treatment - if( m_idHelperSvc->isMdt(chid) ) return mdtSegmentQuality(seg,chid,ignoreHoles); - + if (m_idHelperSvc->isMdt(chid)) return mdtSegmentQuality(seg, chid, ignoreHoles); + // csc segments - if( m_idHelperSvc->isCsc(chid) ) return cscSegmentQuality(seg,chid,ignoreHoles,useEta,usePhi); + if (m_idHelperSvc->isCsc(chid)) return cscSegmentQuality(seg, chid, ignoreHoles, useEta, usePhi); // rpc/tgc case - if( m_idHelperSvc->isTgc(chid) || m_idHelperSvc->isRpc(chid) ) return 1; + if (m_idHelperSvc->isTgc(chid) || m_idHelperSvc->isRpc(chid)) return 1; // NSW segments - return nswSegmentQuality(seg,chid,ignoreHoles); - } + return nswSegmentQuality(seg, chid, ignoreHoles); +} + +int +MuonSegmentSelectionTool::cscSegmentQuality(const MuonSegment& seg, const Identifier& /*chid*/, bool /*ignoreHoles*/, + bool useEta, bool usePhi) const +{ - int MuonSegmentSelectionTool::cscSegmentQuality( const MuonSegment& seg, const Identifier& /*chid*/, bool /*ignoreHoles*/, bool useEta, bool usePhi ) const { - // get hit counts IMuonSegmentHitSummaryTool::HitCounts hitCounts = m_hitSummaryTool->getHitCounts(seg); /**********************************/ /* cuts for quality level 0 */ - + // remove CSC segments with only 3 hits // unless either eta or phi are broken, in that case we accept the segment - if( hitCounts.ncscHitsPhi + hitCounts.ncscHitsEta < 4 && useEta && usePhi) return -1; - + if (hitCounts.ncscHitsPhi + hitCounts.ncscHitsEta < 4 && useEta && usePhi) return -1; + /**********************************/ /* cuts for quality level 1 */ // remove CSC segments with no layer with 4 hits - if( hitCounts.ncscHitsPhi != 4 && hitCounts.ncscHitsEta != 4 ) return 1; - + if (hitCounts.ncscHitsPhi != 4 && hitCounts.ncscHitsEta != 4) return 1; /**********************************/ /* cuts for quality level 2 */ // require hits in both projections - if( hitCounts.ncscHitsPhi == 0 || hitCounts.ncscHitsEta == 0 ) return 1; - + if (hitCounts.ncscHitsPhi == 0 || hitCounts.ncscHitsEta == 0) return 1; + /**********************************/ /* cuts for quality level 3 */ // require four hits in one of the projections and hits in the other - if( (hitCounts.ncscHitsEta == 4 && hitCounts.ncscHitsPhi != 4) || - (hitCounts.ncscHitsEta != 4 && hitCounts.ncscHitsPhi == 4) ) return 2; + if ((hitCounts.ncscHitsEta == 4 && hitCounts.ncscHitsPhi != 4) + || (hitCounts.ncscHitsEta != 4 && hitCounts.ncscHitsPhi == 4)) + return 2; /**********************************/ /* segment has highest quality */ - return 3; - } + return 3; +} + +int +MuonSegmentSelectionTool::nswSegmentQuality(const MuonSegment& seg, const Identifier& chid, bool /*ignoreHoles*/) const +{ - int MuonSegmentSelectionTool::nswSegmentQuality( const MuonSegment& seg, const Identifier& chid, bool /*ignoreHoles*/ ) const { - // get hit counts IMuonSegmentHitSummaryTool::HitCounts hitCounts = m_hitSummaryTool->getHitCounts(seg); /**********************************/ /* cuts for quality level 0 */ - + // remove NSW segments with only 3 hits - if( hitCounts.ncscHitsEta < 4 ) return -1; - + if (hitCounts.ncscHitsEta < 4) return -1; + /**********************************/ /* cuts for quality level 1 */ // remove NSW segments with less than 8 hits - if( hitCounts.ncscHitsEta < 8 ) return 1; + if (hitCounts.ncscHitsEta < 8) return 1; /**********************************/ /* cuts for quality level 2 */ // require hits in both projections - if( std::abs(m_idHelperSvc->stationEta(chid)) > 2 && hitCounts.ncscHitsPhi == 0 ) return 1; - + if (std::abs(m_idHelperSvc->stationEta(chid)) > 2 && hitCounts.ncscHitsPhi == 0) return 1; + /**********************************/ /* cuts for quality level 3 */ // require four hits in one of the projections and hits in the other - if( hitCounts.ncscHitsEta < 12 || - ( std::abs(m_idHelperSvc->stationEta(chid)) > 2 && hitCounts.ncscHitsPhi < 4 ) ) return 2; + if (hitCounts.ncscHitsEta < 12 || (std::abs(m_idHelperSvc->stationEta(chid)) > 2 && hitCounts.ncscHitsPhi < 4)) + return 2; /**********************************/ /* segment has highest quality */ - return 3; - } - - int MuonSegmentSelectionTool::mdtSegmentQuality( const MuonSegment& seg, const Identifier& /*chid*/, bool ignoreHoles ) const { - + return 3; +} + +int +MuonSegmentSelectionTool::mdtSegmentQuality(const MuonSegment& seg, const Identifier& /*chid*/, bool ignoreHoles) const +{ + // get hit counts IMuonSegmentHitSummaryTool::HitCounts hitCounts = m_hitSummaryTool->getHitCounts(seg); /**********************************/ /* cuts for quality level 0 */ - + // remove segments with less than 3 mdt hits - if( hitCounts.nmdtHits() < 3 ) return -1; + if (hitCounts.nmdtHits() < 3) return -1; // get holes unsigned int nholes = !ignoreHoles ? hitCounts.nmdtHoles : 0; - + // calculate hole fraction - double holeFraction = (double)nholes/(double)hitCounts.nmdtHits(); + double holeFraction = (double)nholes / (double)hitCounts.nmdtHits(); // check whether we expect trigger hits in the station bool triggerHitRegion = hitCounts.nexpectedTrigHitLayers > 0; - ATH_MSG_DEBUG("Segment: " << m_printer->print(seg) << std::endl << hitCounts.print() << " Hole frac " << holeFraction); - + ATH_MSG_DEBUG("Segment: " << m_printer->print(seg) << std::endl + << hitCounts.print() << " Hole frac " << holeFraction); + // only look at segments with phi hits - if( triggerHitRegion && hitCounts.nphiTrigHitLayers == 0 ){ - - // reject if more holes than hits - if( holeFraction > 1.1 ) return -1; + if (triggerHitRegion && hitCounts.nphiTrigHitLayers == 0) { + + // reject if more holes than hits + if (holeFraction > 1.1) return -1; } // reject events with a good ADC fraction below the cut - if( hitCounts.goodADCFraction() < m_adcFractionCut ) return -1; - if( hitCounts.nmdtHits() == 3 && hitCounts.adcMax < m_minAdcPerSegmentCut ) return -1; + if (hitCounts.goodADCFraction() < m_adcFractionCut) return -1; + if (hitCounts.nmdtHits() == 3 && hitCounts.adcMax < m_minAdcPerSegmentCut) return -1; /**********************************/ /* cuts for quality level 1 */ - if( !hitCounts.closeToChamberEdge ) { + if (!hitCounts.closeToChamberEdge) { + + // reject segments with phi hits and more holes as hits + if (hitCounts.nphiTrigHitLayers != 0 && holeFraction > 1.1) return 0; - // reject segments with phi hits and more holes as hits - if( hitCounts.nphiTrigHitLayers != 0 && holeFraction > 1.1 ) return 0; - -// // reject segments with phi hits and a hole fraction larger than 50% -// if( triggerHitRegion && hitCounts.nphiTrigHitLayers == 0 && holeFraction > 0.5 ) return 0; + // // reject segments with phi hits and a hole fraction larger than 50% + // if( triggerHitRegion && hitCounts.nphiTrigHitLayers == 0 && holeFraction > 0.5 ) return 0; } // reject segments with more than one enclosed hole and no trigger hits - if( hitCounts.nphiTrigHitLayers == 0 && hitCounts.nmdtEnclosedHoles > 2 ) return 0; - + if (hitCounts.nphiTrigHitLayers == 0 && hitCounts.nmdtEnclosedHoles > 2) return 0; + /**********************************/ /* cuts for quality level 2 */ // reject segments with phi hits and more holes as hits - if( hitCounts.nphiTrigHitLayers != 0 && holeFraction > 1.1 ) return 1; - + if (hitCounts.nphiTrigHitLayers != 0 && holeFraction > 1.1) return 1; + // reject segments with phi hits and a hole fraction larger than 50% - if( triggerHitRegion && hitCounts.nphiTrigHitLayers == 0 && holeFraction > 0.5 ) return 1; + if (triggerHitRegion && hitCounts.nphiTrigHitLayers == 0 && holeFraction > 0.5) return 1; // reject segments with more than one enclosed hole - if( hitCounts.nmdtEnclosedHoles > 2 ) return 0; + if (hitCounts.nmdtEnclosedHoles > 2) return 0; // reject all segments that have no phi hits and hits in only one multi layer - bool twoMultiLayerSegment = hitCounts.nmdtHitsMl1 > 1 && hitCounts.nmdtHitsMl2 > 1; - if( hitCounts.nphiTrigHitLayers == 0 && !twoMultiLayerSegment ) return 1; + bool twoMultiLayerSegment = hitCounts.nmdtHitsMl1 > 1 && hitCounts.nmdtHitsMl2 > 1; + if (hitCounts.nphiTrigHitLayers == 0 && !twoMultiLayerSegment) return 1; + + if (hitCounts.nphiTrigHitLayers == 0) { - if( hitCounts.nphiTrigHitLayers == 0 ){ + // cut on segment quality + if (hitCounts.segmentQuality > m_cutSegmentQuality) return 1; - // cut on segment quality - if( hitCounts.segmentQuality > m_cutSegmentQuality ) return 1; - - // tighter cut for segments with only on multi layer - if( (!twoMultiLayerSegment || hitCounts.nmdtHits() < 5) && hitCounts.segmentQuality > 0.5*m_cutSegmentQuality ) return 1; + // tighter cut for segments with only on multi layer + if ((!twoMultiLayerSegment || hitCounts.nmdtHits() < 5) && hitCounts.segmentQuality > 0.5 * m_cutSegmentQuality) + return 1; } // cut on number of holes - if( hitCounts.nmdtHoles > 2 ) { - ATH_MSG_DEBUG("Failed hole cut " << hitCounts.nmdtHoles ); - return 1; + if (hitCounts.nmdtHoles > 2) { + ATH_MSG_DEBUG("Failed hole cut " << hitCounts.nmdtHoles); + return 1; } /**********************************/ /* cuts for quality level 3 */ // cut on segment quality - if( hitCounts.segmentQuality > m_cutSegmentQuality ) { - ATH_MSG_DEBUG("Failed quality cut" << hitCounts.segmentQuality << " cut " << m_cutSegmentQuality); - return 2; - } + if (hitCounts.segmentQuality > m_cutSegmentQuality) { + ATH_MSG_DEBUG("Failed quality cut" << hitCounts.segmentQuality << " cut " << m_cutSegmentQuality); + return 2; + } // tighter cut for segments with only on multi layer - if( (!twoMultiLayerSegment || hitCounts.nmdtHits() < 5) && hitCounts.segmentQuality > 0.5*m_cutSegmentQuality ) { - ATH_MSG_DEBUG("Single multi layer or too few hits: quality " << hitCounts.segmentQuality << " cut " << 0.5*m_cutSegmentQuality); - return 2; - } + if ((!twoMultiLayerSegment || hitCounts.nmdtHits() < 5) && hitCounts.segmentQuality > 0.5 * m_cutSegmentQuality) { + ATH_MSG_DEBUG("Single multi layer or too few hits: quality " << hitCounts.segmentQuality << " cut " + << 0.5 * m_cutSegmentQuality); + return 2; + } // reject all segments that have in only one multi layer - if( !twoMultiLayerSegment ) { - ATH_MSG_DEBUG("Single multi layer"); - return 2; + if (!twoMultiLayerSegment) { + ATH_MSG_DEBUG("Single multi layer"); + return 2; } // reject segments without missing trigger layers in regions where we expect phi hits - if( triggerHitRegion && hitCounts.nphiTrigHitLayers < hitCounts.nexpectedTrigHitLayers ) { - ATH_MSG_DEBUG("Missing trigger hits: phi hits " <<hitCounts.nphiTrigHitLayers << " expected " << hitCounts.nexpectedTrigHitLayers); - return 2; + if (triggerHitRegion && hitCounts.nphiTrigHitLayers < hitCounts.nexpectedTrigHitLayers) { + ATH_MSG_DEBUG("Missing trigger hits: phi hits " << hitCounts.nphiTrigHitLayers << " expected " + << hitCounts.nexpectedTrigHitLayers); + return 2; } /**********************************/ /* segment has highest quality */ return 3; - } +} - bool MuonSegmentSelectionTool::select( const MuonSegment& seg, bool ignoreHoles, int qualityLevel, bool useEta, bool usePhi ) const { +bool +MuonSegmentSelectionTool::select(const MuonSegment& seg, bool ignoreHoles, int qualityLevel, bool useEta, + bool usePhi) const +{ // check quality is better or equal to required level - return quality(seg,ignoreHoles,useEta,usePhi) >= qualityLevel; - } - + return quality(seg, ignoreHoles, useEta, usePhi) >= qualityLevel; } + +} // namespace Muon diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentSelectionTool.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentSelectionTool.h index 26c2312f8c92c2bffad91bed31e55588d67ee406..94c63b50299efa1d4b526b5104a08bc98de2d451 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentSelectionTool.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/MuonSegmentSelectionTools/src/MuonSegmentSelectionTool.h @@ -5,70 +5,80 @@ #ifndef MUON_MUONSEGMENTSELECTIONTOOL_H #define MUON_MUONSEGMENTSELECTIONTOOL_H -#include "MuonSegmentMakerToolInterfaces/IMuonSegmentSelectionTool.h" #include "AthenaBaseComps/AthAlgTool.h" #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" - #include "MuonRecHelperTools/IMuonEDMHelperSvc.h" #include "MuonRecHelperTools/MuonEDMPrinterTool.h" #include "MuonSegmentMakerToolInterfaces/IMuonSegmentHitSummaryTool.h" +#include "MuonSegmentMakerToolInterfaces/IMuonSegmentSelectionTool.h" namespace Muon { - class MuonSegment; +class MuonSegment; } namespace Muon { - - - /** - @brief tool to select MDT segments, all CSC segments will be kept - Quality levels: - Level 0 = remove segments with more mdt holes than mdt hits that have no phi hits - remove segments with less than 3 mdt hits - Level 1 = remove segments with more than 50% mdt holes and no phi hits - with phi hits and more mdt holes than mdt hits - Level 2 = remove segments with mdt hits in only one multilayer - Level 3 = remove segments with mdt holes or no phi hits in chambers where one would expect phi hits - */ - class MuonSegmentSelectionTool : virtual public IMuonSegmentSelectionTool, public AthAlgTool { + + +/** + @brief tool to select MDT segments, all CSC segments will be kept + Quality levels: + Level 0 = remove segments with more mdt holes than mdt hits that have no phi hits + remove segments with less than 3 mdt hits + Level 1 = remove segments with more than 50% mdt holes and no phi hits + with phi hits and more mdt holes than mdt hits + Level 2 = remove segments with mdt hits in only one multilayer + Level 3 = remove segments with mdt holes or no phi hits in chambers where one would expect phi hits +*/ +class MuonSegmentSelectionTool : virtual public IMuonSegmentSelectionTool, public AthAlgTool { public: - MuonSegmentSelectionTool(const std::string&,const std::string&,const IInterface*); + MuonSegmentSelectionTool(const std::string&, const std::string&, const IInterface*); + + virtual ~MuonSegmentSelectionTool() = default; - virtual ~MuonSegmentSelectionTool ()=default; - StatusCode initialize(); - + /** @brief select segment */ - bool select( const MuonSegment& seg, bool ignoreHoles = false, int qualityLevel = 0, bool useEta=true, bool usePhi=true ) const; + bool select(const MuonSegment& seg, bool ignoreHoles = false, int qualityLevel = 0, bool useEta = true, + bool usePhi = true) const; /** @brief segment quality */ - int quality( const MuonSegment& seg, bool ignoreHoles = false, bool useEta=true, bool usePhi=true ) const; + int quality(const MuonSegment& seg, bool ignoreHoles = false, bool useEta = true, bool usePhi = true) const; private: - /** @brief calculate segment quality for MDT segments */ - int mdtSegmentQuality( const MuonSegment& seg, const Identifier& chid, bool ignoreHoles ) const; + int mdtSegmentQuality(const MuonSegment& seg, const Identifier& chid, bool ignoreHoles) const; /** @brief calculate segment quality for CSC segments */ - int cscSegmentQuality( const MuonSegment& seg, const Identifier& chid, bool ignoreHoles, bool useEta, bool usePhi ) const; + int cscSegmentQuality(const MuonSegment& seg, const Identifier& chid, bool ignoreHoles, bool useEta, + bool usePhi) const; /** @brief calculate segment quality for NSW segments */ - int nswSegmentQuality( const MuonSegment& seg, const Identifier& chid, bool ignoreHoles ) const; - - ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; - ServiceHandle<IMuonEDMHelperSvc> m_edmHelperSvc {this, "edmHelper", - "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", - "Handle to the service providing the IMuonEDMHelperSvc interface" }; //!< EDM Helper tool - ToolHandle<MuonEDMPrinterTool> m_printer; //!< EDM printer tool - ToolHandle<IMuonSegmentHitSummaryTool> m_hitSummaryTool; //!< hit summary tool - - double m_cutSegmentQuality; //!< cut on the segment quality - double m_adcFractionCut; //!< cut on fraction of MDT hits above ADC cut - int m_minAdcPerSegmentCut; //!< minimum value for the MDT with the highest ADC value on the segment - }; - -} + int nswSegmentQuality(const MuonSegment& seg, const Identifier& chid, bool ignoreHoles) const; + + ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{this, "MuonIdHelperSvc", + "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}; + ServiceHandle<IMuonEDMHelperSvc> m_edmHelperSvc{ + this, "edmHelper", "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc", + "Handle to the service providing the IMuonEDMHelperSvc interface"}; //!< EDM Helper tool + + ToolHandle<MuonEDMPrinterTool> m_printer{ + this, + "Printer", + "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool", + }; //!< EDM printer tool + ToolHandle<IMuonSegmentHitSummaryTool> m_hitSummaryTool{ + this, + "MuonSegmentHitSummaryTool", + "Muon::MuonSegmentHitSummaryTool/MuonSegmentHitSummaryTool", + }; //!< hit summary tool + + double m_cutSegmentQuality; //!< cut on the segment quality + double m_adcFractionCut; //!< cut on fraction of MDT hits above ADC cut + int m_minAdcPerSegmentCut; //!< minimum value for the MDT with the highest ADC value on the segment +}; + +} // namespace Muon #endif diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/TGC_LinearSegmentMakerTool/TGC_LinearSegmentMakerTool/TGC_LinearSegmentMakerTool.h b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/TGC_LinearSegmentMakerTool/TGC_LinearSegmentMakerTool/TGC_LinearSegmentMakerTool.h index 0e67fbc033f2f36b48ca0313bee0c63a53b78a19..3edd22f91b6dff829bff36a1a34265836cdad387 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/TGC_LinearSegmentMakerTool/TGC_LinearSegmentMakerTool/TGC_LinearSegmentMakerTool.h +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/TGC_LinearSegmentMakerTool/TGC_LinearSegmentMakerTool/TGC_LinearSegmentMakerTool.h @@ -1,74 +1,60 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ #ifndef TGC_LINEARSEGMENTMAKERTOOL_H #define TGC_LINEARSEGMENTMAKERTOOL_H -#include "MuonRecToolInterfaces/IMuonSegmentMaker.h" #include "AthenaBaseComps/AthAlgTool.h" #include "GaudiKernel/ToolHandle.h" +#include "MuonRecToolInterfaces/IMuonSegmentMaker.h" //#include "CLHEP/Vector/TwoVector.h" #include "TrkExInterfaces/IIntersector.h" class TgcIdHelper; -namespace MuonGM -{ - class MuonDetectorManager; +namespace MuonGM { +class MuonDetectorManager; } -class TGC_LinearSegmentMakerTool : virtual public Muon::IMuonSegmentMaker, public AthAlgTool -{ -public: - TGC_LinearSegmentMakerTool(const std::string& type, - const std::string& name, - const IInterface* pIID); +class TGC_LinearSegmentMakerTool : virtual public Muon::IMuonSegmentMaker, public AthAlgTool { + public: + TGC_LinearSegmentMakerTool(const std::string& type, const std::string& name, const IInterface* pIID); - StatusCode initialize(); - StatusCode Finalize(); - virtual void - find(const std::vector<const Trk::RIO_OnTrack*>&, - Trk::SegmentCollection*) const - { - } + StatusCode initialize(); + StatusCode Finalize(); + virtual void find(const std::vector<const Trk::RIO_OnTrack*>&, Trk::SegmentCollection*) const {} - virtual void - find(const std::vector<const Trk::RIO_OnTrack*>&, - const std::vector<const Trk::RIO_OnTrack*>&) const - { - } + virtual void find(const std::vector<const Trk::RIO_OnTrack*>&, const std::vector<const Trk::RIO_OnTrack*>&) const {} - virtual void - find(const std::vector<const Muon::MdtDriftCircleOnTrack*>&, - const std::vector<const Muon::MuonClusterOnTrack*>&, - Trk::SegmentCollection*) const + virtual void find(const std::vector<const Muon::MdtDriftCircleOnTrack*>&, + const std::vector<const Muon::MuonClusterOnTrack*>&, Trk::SegmentCollection*) const { } - virtual void - find(const Amg::Vector3D&, - const Amg::Vector3D&, - const std::vector<const Muon::MdtDriftCircleOnTrack*>&, - const std::vector<const Muon::MuonClusterOnTrack*>&, - bool,Trk::SegmentCollection*, - double,double) const + virtual void find(const Amg::Vector3D&, const Amg::Vector3D&, + const std::vector<const Muon::MdtDriftCircleOnTrack*>&, + const std::vector<const Muon::MuonClusterOnTrack*>&, bool, Trk::SegmentCollection*, double, + double) const { } - virtual void - find(const Trk::TrackRoad& road, - const std::vector< std::vector< const Muon::MdtDriftCircleOnTrack* > >& mdts, - const std::vector< std::vector< const Muon::MuonClusterOnTrack* > >& clusters, - Trk::SegmentCollection* segColl=0, - bool hasPhiMeasurements = false,double momentum=1e9) const; + virtual void find(const Trk::TrackRoad& road, + const std::vector<std::vector<const Muon::MdtDriftCircleOnTrack*> >& mdts, + const std::vector<std::vector<const Muon::MuonClusterOnTrack*> >& clusters, + Trk::SegmentCollection* segColl = 0, bool hasPhiMeasurements = false, + double momentum = 1e9) const; -private: + private: const MuonGM::MuonDetectorManager* m_pMuonMgr; const TgcIdHelper* m_pIdHelper; DoubleProperty m_fExclChi2; - ToolHandle<Trk::IIntersector> m_pIntersector; -}; -#endif //TGC_LINEARSEGMENTMAKERTOOL_H + ToolHandle<Trk::IIntersector> m_pIntersector{ + this, + "Intersector", + "Trk::RungeKuttaIntersector/Trk::RungeKuttaIntersector", + }; +}; +#endif // TGC_LINEARSEGMENTMAKERTOOL_H diff --git a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/TGC_LinearSegmentMakerTool/src/TGC_LinearSegmentMakerTool.cxx b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/TGC_LinearSegmentMakerTool/src/TGC_LinearSegmentMakerTool.cxx index 3af876cd36ae0278cc8e1ca9b04927da3a7b67c1..f06ac81cb784cff88cb60a9680121b8abc8caed5 100644 --- a/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/TGC_LinearSegmentMakerTool/src/TGC_LinearSegmentMakerTool.cxx +++ b/MuonSpectrometer/MuonReconstruction/MuonSegmentMakers/MuonSegmentMakerTools/TGC_LinearSegmentMakerTool/src/TGC_LinearSegmentMakerTool.cxx @@ -1,92 +1,87 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ -#include "StoreGate/StoreGateSvc.h" -#include "MuonReadoutGeometry/MuonDetectorManager.h" +#include "TGC_LinearSegmentMakerTool/TGC_LinearSegmentMakerTool.h" + +#include <set> +#include <sstream> + +#include "GeoPrimitives/GeoPrimitivesHelpers.h" +#include "MuonLinearSegmentMakerUtilities/Fit2D.h" #include "MuonRIO_OnTrack/MuonClusterOnTrack.h" -#include "TrkSurfaces/PlaneSurface.h" -#include "TrkEventPrimitives/FitQuality.h" -#include "MuonSegment/MuonSegment.h" #include "MuonRIO_OnTrack/TgcClusterOnTrack.h" -#include "TrkRoad/TrackRoad.h" +#include "MuonReadoutGeometry/MuonDetectorManager.h" +#include "MuonSegment/MuonSegment.h" +#include "StoreGate/StoreGateSvc.h" +#include "TrkEventPrimitives/FitQuality.h" #include "TrkEventPrimitives/LocalDirection.h" -#include "TrkExUtils/TrackSurfaceIntersection.h" #include "TrkExInterfaces/IIntersector.h" - -#include "TGC_LinearSegmentMakerTool/TGC_LinearSegmentMakerTool.h" -#include "MuonLinearSegmentMakerUtilities/Fit2D.h" -#include "GeoPrimitives/GeoPrimitivesHelpers.h" -#include <sstream> -#include <set> +#include "TrkExUtils/TrackSurfaceIntersection.h" +#include "TrkRoad/TrackRoad.h" +#include "TrkSurfaces/PlaneSurface.h" -TGC_LinearSegmentMakerTool::TGC_LinearSegmentMakerTool(const std::string& type, - const std::string& name, - const IInterface* pIID) : -AthAlgTool(type, name, pIID), -m_pIdHelper(NULL), -m_pIntersector("Trk::RungeKuttaIntersector/Trk::RungeKuttaIntersector") +TGC_LinearSegmentMakerTool::TGC_LinearSegmentMakerTool(const std::string& type, const std::string& name, + const IInterface* pIID) + : AthAlgTool(type, name, pIID), + m_pIdHelper(NULL) { declareInterface<Muon::IMuonSegmentMaker>(this); declareProperty("OutlierChi2", m_fExclChi2 = 10.0); - declareProperty("Intersector", m_pIntersector); } -StatusCode TGC_LinearSegmentMakerTool::initialize() +StatusCode +TGC_LinearSegmentMakerTool::initialize() { - ATH_MSG_INFO("Initializing TGC_LinearSegmentMakerTool - package version " << PACKAGE_VERSION ); + ATH_MSG_INFO("Initializing TGC_LinearSegmentMakerTool - package version " << PACKAGE_VERSION); StatusCode sc = StatusCode::SUCCESS; // initialize TgcIdHelper StoreGateSvc* pDetStore = NULL; - sc = svcLoc()->service("DetectorStore", pDetStore); - if (sc.isFailure() || pDetStore == NULL) - { + sc = svcLoc()->service("DetectorStore", pDetStore); + if (sc.isFailure() || pDetStore == NULL) { ATH_MSG_ERROR("Cannot locate DetectorStore"); return sc; } sc = pDetStore->retrieve(m_pMuonMgr); - if (sc.isFailure() || m_pMuonMgr == NULL) - { + if (sc.isFailure() || m_pMuonMgr == NULL) { ATH_MSG_ERROR("Cannot retrieve MuonDetectorManager"); return sc; } m_pIdHelper = m_pMuonMgr->tgcIdHelper(); - sc = m_pIntersector.retrieve(); - if (sc.isFailure()) - { - ATH_MSG_ERROR("Cannot retrieve IIntersector"); - return sc; - } + + ATH_CHECK(m_pIntersector.retrieve()); return StatusCode::SUCCESS; } -StatusCode TGC_LinearSegmentMakerTool::Finalize() +StatusCode +TGC_LinearSegmentMakerTool::Finalize() { return StatusCode::SUCCESS; } -static std::string point2String(const Amg::Vector3D& pt) +static std::string +point2String(const Amg::Vector3D& pt) { std::ostringstream oss; oss << "eta=" << pt.eta() << ",phi=" << pt.phi() << ",perp=" << pt.perp() << ",z=" << pt.z(); return oss.str(); } -static std::string dir2String(const Amg::Vector3D& dir) +static std::string +dir2String(const Amg::Vector3D& dir) { std::ostringstream oss; - oss << "eta=" << dir.eta() << ",phi=" << dir.phi()<< ",z=" << dir.z(); + oss << "eta=" << dir.eta() << ",phi=" << dir.phi() << ",z=" << dir.z(); return oss.str(); } -static inline double getFirstPointZ(const Muon::Fit2D::PointArray& points) +static inline double +getFirstPointZ(const Muon::Fit2D::PointArray& points) { - for (auto pPoint : points) - { - if (!pPoint->bExclude) - { + for (auto pPoint : points) { + if (!pPoint->bExclude) { auto pRIO = static_cast<const Muon::MuonClusterOnTrack*>(pPoint->pData); return pRIO->globalPosition().z(); } @@ -94,129 +89,110 @@ static inline double getFirstPointZ(const Muon::Fit2D::PointArray& points) return 0.0; } -void TGC_LinearSegmentMakerTool::find(const Trk::TrackRoad& road, - const std::vector< std::vector< const Muon::MdtDriftCircleOnTrack* > >&, - const std::vector< std::vector< const Muon::MuonClusterOnTrack* > >& clusters, - Trk::SegmentCollection*, - bool,double) const +void +TGC_LinearSegmentMakerTool::find(const Trk::TrackRoad& road, + const std::vector<std::vector<const Muon::MdtDriftCircleOnTrack*> >&, + const std::vector<std::vector<const Muon::MuonClusterOnTrack*> >& clusters, + Trk::SegmentCollection*, bool, double) const { ATH_MSG_DEBUG("TGC_LinearSegmentMakerTool::find"); - Muon::Fit2D::PointArray rhoPoints, phiPoints; + Muon::Fit2D::PointArray rhoPoints, phiPoints; std::vector<const Muon::MuonClusterOnTrack*> rios; for (std::vector<std::vector<const Muon::MuonClusterOnTrack*> >::const_iterator itClusters = clusters.begin(); - itClusters != clusters.end(); - itClusters++) + itClusters != clusters.end(); itClusters++) { const std::vector<const Muon::MuonClusterOnTrack*>& cluster = *itClusters; rios.insert(rios.end(), cluster.begin(), cluster.end()); } const MuonGM::TgcReadoutElement* pReadoutElement = - dynamic_cast<const MuonGM::TgcReadoutElement*>(rios.front()->detectorElement()); + dynamic_cast<const MuonGM::TgcReadoutElement*>(rios.front()->detectorElement()); if (!pReadoutElement) return; std::set<std::string> rhoStations, phiStations; - int iHit = 0; - for (std::vector<const Muon::MuonClusterOnTrack*>::const_iterator itHit = rios.begin(); - itHit != rios.end(); - itHit++, iHit++) + int iHit = 0; + for (std::vector<const Muon::MuonClusterOnTrack*>::const_iterator itHit = rios.begin(); itHit != rios.end(); + itHit++, iHit++) { - const Muon::MuonClusterOnTrack* pHit = *itHit; - const Amg::MatrixX & errMat = pHit->localCovariance(); - if (errMat.determinant()==0.) - { + const Muon::MuonClusterOnTrack* pHit = *itHit; + const Amg::MatrixX& errMat = pHit->localCovariance(); + if (errMat.determinant() == 0.) { ATH_MSG_DEBUG("RIO has a singular error matrix. Skipping"); continue; } - Amg::MatrixX wheight= errMat.inverse(); - double w = wheight(Trk::locX,Trk::locX); - if (m_pIdHelper->isStrip(pHit->identify())) - { + Amg::MatrixX wheight = errMat.inverse(); + double w = wheight(Trk::locX, Trk::locX); + if (m_pIdHelper->isStrip(pHit->identify())) { double rho = pHit->globalPosition().perp(); w *= rho * rho; - Muon::Fit2D::Point* pPt = new Muon::Fit2D::Point(iHit, - pHit->globalPosition().z(), - pHit->globalPosition().phi(), - w, - (void*)pHit); + Muon::Fit2D::Point* pPt = + new Muon::Fit2D::Point(iHit, pHit->globalPosition().z(), pHit->globalPosition().phi(), w, (void*)pHit); phiPoints.push_back(pPt); - const MuonGM::TgcReadoutElement* dEl = dynamic_cast<const MuonGM::TgcReadoutElement*>(pHit->detectorElement()); - if(dEl) - phiStations.insert(dEl->getStationName()); - } - else - { - Muon::Fit2D::Point* pPt = new Muon::Fit2D::Point(iHit, - pHit->globalPosition().z(), - pHit->globalPosition().perp(), - w, - (void*)pHit); + const MuonGM::TgcReadoutElement* dEl = + dynamic_cast<const MuonGM::TgcReadoutElement*>(pHit->detectorElement()); + if (dEl) phiStations.insert(dEl->getStationName()); + } else { + Muon::Fit2D::Point* pPt = + new Muon::Fit2D::Point(iHit, pHit->globalPosition().z(), pHit->globalPosition().perp(), w, (void*)pHit); rhoPoints.push_back(pPt); - const MuonGM::TgcReadoutElement* dEl = dynamic_cast<const MuonGM::TgcReadoutElement*>(pHit->detectorElement()); - if(dEl) - rhoStations.insert(dEl->getStationName()); + const MuonGM::TgcReadoutElement* dEl = + dynamic_cast<const MuonGM::TgcReadoutElement*>(pHit->detectorElement()); + if (dEl) rhoStations.insert(dEl->getStationName()); } } std::vector<const Muon::MuonSegment*>* pMuonSegs = NULL; - double dChi2 = 0.0; - int nDegf = 0; - double zCov[2][2], phiCov[2][2]; + double dChi2 = 0.0; + int nDegf = 0; + double zCov[2][2], phiCov[2][2]; memset(zCov, 0, sizeof(zCov)); memset(phiCov, 0, sizeof(phiCov)); - if (!rhoPoints.empty() && !phiPoints.empty()) - { - Muon::Fit2D fit; - Amg::Vector3D pos; - Amg::Vector3D dir = road.globalDirection(); + if (!rhoPoints.empty() && !phiPoints.empty()) { + Muon::Fit2D fit; + Amg::Vector3D pos; + Amg::Vector3D dir = road.globalDirection(); Muon::Fit2D::SimpleStats rhoSimpleStats, phiSimpleStats; - Muon::Fit2D::LinStats rhoLinStats, phiLinStats; - if (rhoStations.size() == 1 || rhoPoints.size() < 4) - { -// if (stations.size() == 1 && rhoPoints.size() >= 4) -// std::cout << "TGC_LinearSegmentMakerTool::find 1 station with " -// << rhoPoints.size() <<" eta points" << std::endl; + Muon::Fit2D::LinStats rhoLinStats, phiLinStats; + if (rhoStations.size() == 1 || rhoPoints.size() < 4) { + // if (stations.size() == 1 && rhoPoints.size() >= 4) + // std::cout << "TGC_LinearSegmentMakerTool::find 1 station with " + // << rhoPoints.size() <<" eta points" << std::endl; fit.fitPoint(rhoPoints, m_fExclChi2, msgLvl(MSG::DEBUG), rhoSimpleStats); fit.fitPoint(phiPoints, m_fExclChi2, msgLvl(MSG::DEBUG), phiSimpleStats); double baseZ = getFirstPointZ(rhoPoints); ATH_MSG_DEBUG(" baseZ=" << baseZ); - ATH_MSG_DEBUG("Rho: " << rhoSimpleStats.toString() ); - ATH_MSG_DEBUG("Phi: " << phiSimpleStats.toString() ); - pos[0]=rhoSimpleStats.fMean; - pos[1]=0.; - pos[2]=baseZ; + ATH_MSG_DEBUG("Rho: " << rhoSimpleStats.toString()); + ATH_MSG_DEBUG("Phi: " << phiSimpleStats.toString()); + pos[0] = rhoSimpleStats.fMean; + pos[1] = 0.; + pos[2] = baseZ; Amg::setPhi(pos, phiSimpleStats.fMean); - dChi2 = rhoSimpleStats.fChi2 + phiSimpleStats.fChi2; - nDegf = rhoSimpleStats.n + phiSimpleStats.n - 2; - zCov[0][0]=(rhoSimpleStats.fStd)*(rhoSimpleStats.fStd); - } - else - { + dChi2 = rhoSimpleStats.fChi2 + phiSimpleStats.fChi2; + nDegf = rhoSimpleStats.n + phiSimpleStats.n - 2; + zCov[0][0] = (rhoSimpleStats.fStd) * (rhoSimpleStats.fStd); + } else { double baseZ = getFirstPointZ(rhoPoints); ATH_MSG_DEBUG(" baseZ=" << baseZ); double rho, rhoErr, phi, phiErr, z = baseZ; fit.fitLine(rhoPoints, m_fExclChi2, msgLvl(MSG::DEBUG), rhoLinStats); ATH_MSG_DEBUG("Rho: " << rhoLinStats.toString()); rhoLinStats.eval(z, rho, rhoErr); - pos[0]=rho; - pos[1]=0.0; - pos[2]=z; - dChi2 = rhoLinStats.fChi2; - nDegf = rhoLinStats.n - 2; - if (phiStations.size() == 1 || phiPoints.size() < 4) - { + pos[0] = rho; + pos[1] = 0.0; + pos[2] = z; + dChi2 = rhoLinStats.fChi2; + nDegf = rhoLinStats.n - 2; + if (phiStations.size() == 1 || phiPoints.size() < 4) { fit.fitPoint(phiPoints, m_fExclChi2, msgLvl(MSG::DEBUG), phiSimpleStats); - ATH_MSG_DEBUG("Phi: " << phiSimpleStats.toString() ); + ATH_MSG_DEBUG("Phi: " << phiSimpleStats.toString()); Amg::setPhi(pos, phiSimpleStats.fMean); phiLinStats.fSlope = 0.0; dChi2 += phiSimpleStats.fChi2; nDegf += phiSimpleStats.n - 1; - phiCov[0][0]=(phiSimpleStats.fStd)*(phiSimpleStats.fStd); - } - else - { + phiCov[0][0] = (phiSimpleStats.fStd) * (phiSimpleStats.fStd); + } else { fit.fitLine(phiPoints, m_fExclChi2, msgLvl(MSG::DEBUG), phiLinStats); - ATH_MSG_DEBUG("Phi: " << phiLinStats.toString() ); + ATH_MSG_DEBUG("Phi: " << phiLinStats.toString()); phiLinStats.eval(z, phi, phiErr); Amg::setPhi(pos, phi); dChi2 += phiLinStats.fChi2; @@ -230,90 +206,82 @@ void TGC_LinearSegmentMakerTool::find(const Trk::TrackRoad& road, Amg::setPhi(p1, phi); dir = p1 - pos; } - ATH_MSG_DEBUG("Segment position " << point2String(pos) ); - ATH_MSG_DEBUG("Segment direction " << dir2String(dir) ); + ATH_MSG_DEBUG("Segment position " << point2String(pos)); + ATH_MSG_DEBUG("Segment direction " << dir2String(dir)); const Trk::Surface& surface = pReadoutElement->surface(); const Muon::TgcClusterOnTrack* pTgcCOT = dynamic_cast<const Muon::TgcClusterOnTrack*>(rios.front()); - if (pTgcCOT == NULL) - { + if (pTgcCOT == NULL) { ATH_MSG_WARNING("Cannot convert Muon::TgcClusterOnTrack to Muon::TgcClusterOnTrack"); goto done; } -// const Trk::Surface& surface = pTgcCOT->associatedSurface(); - if (msgLvl(MSG::DEBUG)) - { -// surface.dump(log); -// const Amg::Vector3D& pos = surface.center(); - ATH_MSG_DEBUG("Surface at " << point2String(surface.center()) ); + // const Trk::Surface& surface = pTgcCOT->associatedSurface(); + if (msgLvl(MSG::DEBUG)) { + // surface.dump(log); + // const Amg::Vector3D& pos = surface.center(); + ATH_MSG_DEBUG("Surface at " << point2String(surface.center())); } const Trk::PlaneSurface* pSurface = dynamic_cast<const Trk::PlaneSurface*>(&surface); - if (pSurface == NULL) - { + if (pSurface == NULL) { ATH_MSG_WARNING("Cannot get a PlaneSurface from TgcClusterOnTrack"); goto done; } - Trk::TrackSurfaceIntersection baseIsect(pos, dir, 0.0); + Trk::TrackSurfaceIntersection baseIsect(pos, dir, 0.0); const Trk::TrackSurfaceIntersection* pNewBaseIsect = m_pIntersector->intersectSurface(surface, &baseIsect, 0.0); - Amg::Vector2D pSegPos; - bool loc_pos_ok(false); - if(pNewBaseIsect) { - loc_pos_ok=pSurface->globalToLocal(pNewBaseIsect->position(), Amg::Vector3D(0., 0., 0.), pSegPos); - delete pNewBaseIsect; - } - if (!loc_pos_ok) - { - ATH_MSG_WARNING("Cannot get LocalPosition from surface for " << point2String(pos) ); + Amg::Vector2D pSegPos; + bool loc_pos_ok(false); + if (pNewBaseIsect) { + loc_pos_ok = pSurface->globalToLocal(pNewBaseIsect->position(), Amg::Vector3D(0., 0., 0.), pSegPos); + delete pNewBaseIsect; + } + if (!loc_pos_ok) { + ATH_MSG_WARNING("Cannot get LocalPosition from surface for " << point2String(pos)); goto done; } - ATH_MSG_DEBUG("Segment local position is" << " x=" << pSegPos[Trk::locX] << ",y=" << pSegPos[Trk::locY] ); + ATH_MSG_DEBUG("Segment local position is" + << " x=" << pSegPos[Trk::locX] << ",y=" << pSegPos[Trk::locY]); Trk::LocalDirection pSegDir; pSurface->globalToLocalDirection(dir.unit(), pSegDir); - ATH_MSG_DEBUG("Segment local direction is" << " angleXZ=" << pSegDir.angleXZ() << ",angleYZ=" << pSegDir.angleYZ() ); + ATH_MSG_DEBUG("Segment local direction is" + << " angleXZ=" << pSegDir.angleXZ() << ",angleYZ=" << pSegDir.angleYZ()); - AmgSymMatrix(4) pcov; - pcov(0,0) = zCov[0][0]; - pcov(0,1) = zCov[0][1]; - pcov(1,1) = zCov[1][1]; - pcov(2,2) = phiCov[0][0]; - pcov(2,3) = phiCov[0][1]; - pcov(3,3) = phiCov[1][1]; - pcov(0,2) = 0.0; - pcov(0,3) = 0.0; - pcov(1,2) = 0.0; - pcov(1,3) = 0.0; + AmgSymMatrix(4) pcov; + pcov(0, 0) = zCov[0][0]; + pcov(0, 1) = zCov[0][1]; + pcov(1, 1) = zCov[1][1]; + pcov(2, 2) = phiCov[0][0]; + pcov(2, 3) = phiCov[0][1]; + pcov(3, 3) = phiCov[1][1]; + pcov(0, 2) = 0.0; + pcov(0, 3) = 0.0; + pcov(1, 2) = 0.0; + pcov(1, 3) = 0.0; - Trk::FitQuality* pFitQuality = new Trk::FitQuality(dChi2, nDegf); - DataVector<const Trk::MeasurementBase>* pRios = new DataVector<const Trk::MeasurementBase>; - for (Muon::Fit2D::PointArray::const_iterator itPt = rhoPoints.begin(); itPt != rhoPoints.end(); itPt++) - { + Trk::FitQuality* pFitQuality = new Trk::FitQuality(dChi2, nDegf); + DataVector<const Trk::MeasurementBase>* pRios = new DataVector<const Trk::MeasurementBase>; + for (Muon::Fit2D::PointArray::const_iterator itPt = rhoPoints.begin(); itPt != rhoPoints.end(); itPt++) { Muon::Fit2D::Point* pPt = *itPt; - if (!pPt->bExclude) - { - pRios->push_back(static_cast<const Trk::MeasurementBase*>(((const Muon::MuonClusterOnTrack*)(pPt->pData))->clone())); + if (!pPt->bExclude) { + pRios->push_back( + static_cast<const Trk::MeasurementBase*>(((const Muon::MuonClusterOnTrack*)(pPt->pData))->clone())); } } - for (Muon::Fit2D::PointArray::const_iterator itPt = phiPoints.begin(); itPt != phiPoints.end(); itPt++) - { + for (Muon::Fit2D::PointArray::const_iterator itPt = phiPoints.begin(); itPt != phiPoints.end(); itPt++) { Muon::Fit2D::Point* pPt = *itPt; - if (!pPt->bExclude) - { - pRios->push_back(static_cast<const Trk::MeasurementBase*>(((const Muon::MuonClusterOnTrack*)(pPt->pData))->clone())); + if (!pPt->bExclude) { + pRios->push_back( + static_cast<const Trk::MeasurementBase*>(((const Muon::MuonClusterOnTrack*)(pPt->pData))->clone())); } } - Muon::MuonSegment* pMuonSeg = new Muon::MuonSegment(pSegPos, - pSegDir, - pcov, - const_cast<Trk::PlaneSurface*>(pSurface->clone()), - pRios, - pFitQuality); + Muon::MuonSegment* pMuonSeg = new Muon::MuonSegment( + pSegPos, pSegDir, pcov, const_cast<Trk::PlaneSurface*>(pSurface->clone()), pRios, pFitQuality); if (msgLvl(MSG::DEBUG)) -// pMuonSeg->dump(log); + // pMuonSeg->dump(log); ATH_MSG_DEBUG("Created a new Muon::MuonSegment"); - pMuonSegs = new std::vector<const Muon::MuonSegment*>(1); + pMuonSegs = new std::vector<const Muon::MuonSegment*>(1); (*pMuonSegs)[0] = pMuonSeg; -// delete pSegDir; + // delete pSegDir; } done: for (Muon::Fit2D::PointArray::const_iterator itPt = rhoPoints.begin(); itPt != rhoPoints.end(); itPt++) @@ -322,6 +290,5 @@ done: delete *itPt; ATH_MSG_DEBUG("TGC_LinearSegmentMakerTool::find ended"); - //return pMuonSegs; + // return pMuonSegs; } - diff --git a/Reconstruction/MuonIdentification/MuonCombinedRecExample/python/MuGirlTagTool.py b/Reconstruction/MuonIdentification/MuonCombinedRecExample/python/MuGirlTagTool.py index 132abad6018dea248378c903c79e1cd6dcc9e840..967db99b0a3a1c1362f75ae01f461e0a12f018ce 100644 --- a/Reconstruction/MuonIdentification/MuonCombinedRecExample/python/MuGirlTagTool.py +++ b/Reconstruction/MuonIdentification/MuonCombinedRecExample/python/MuGirlTagTool.py @@ -27,6 +27,7 @@ def MuonInsideOutRecoTool( name="MuonInsideOutRecoTool", **kwargs ): import MuonCombinedRecExample.CombinedMuonTrackSummary from AthenaCommon.AppMgr import ToolSvc kwargs.setdefault("TrackSummaryTool", ToolSvc.CombinedMuonTrackSummary) + kwargs.setdefault("MuonLayerSegmentFinderTool", getPublicTool("MuonLayerSegmentFinderTool")) return CfgMgr.MuonCombined__MuonInsideOutRecoTool(name,**kwargs ) def MuonCandidateTrackBuilderTool( name="MuonCandidateTrackBuilderTool",**kwargs): @@ -44,7 +45,7 @@ def MuonRecoValidationTool( name="MuonRecoValidationTool",**kwargs): return CfgMgr.Muon__MuonRecoValidationTool(name,**kwargs) def DCMathStauSegmentMaker( name="DCMathStauSegmentMaker", **kwargs ): - kwargs.setdefault("MdtCreator", getPublicTool("MdtDriftCircleOnTrackCreatorStau") ) + kwargs.setdefault("MdtCreator", getPublicTool("MdtDriftCircleOnTrackCreatorStau") ) return DCMathSegmentMaker(name,**kwargs) def MuonStauChamberHoleRecoveryTool(name="MuonStauChamberHoleRecoveryTool",**kwargs): diff --git a/Reconstruction/MuonIdentification/MuonCombinedRecExample/python/MuonCombinedAlgs.py b/Reconstruction/MuonIdentification/MuonCombinedRecExample/python/MuonCombinedAlgs.py index 270f322142284fb95d629aa8025e35a6e3562050..4bfc65d950b6fcae575a323f93f7bd5da8e554cf 100644 --- a/Reconstruction/MuonIdentification/MuonCombinedRecExample/python/MuonCombinedAlgs.py +++ b/Reconstruction/MuonIdentification/MuonCombinedRecExample/python/MuonCombinedAlgs.py @@ -42,11 +42,7 @@ def MuonSegmentTagAlg( name="MuonSegmentTagAlg", **kwargs ): def MuonInsideOutRecoAlg( name="MuonInsideOutRecoAlg", **kwargs ): tools = [getPublicTool("MuonInsideOutRecoTool") ] - from MuonLayerSegmentMakerTools.MuonLayerSegmentMakerToolsConf import Muon__MuonLayerSegmentFinderTool - from AthenaCommon.AppMgr import ToolSvc - MuonLayerSegmentFinderTool = Muon__MuonLayerSegmentFinderTool("MuonLayerSegmentFinderTool", Csc2DSegmentMaker=(getPublicTool("Csc2dSegmentMaker") if MuonGeometryFlags.hasCSC() else ""), Csc4DSegmentMaker=(getPublicTool("Csc4dSegmentMaker") if MuonGeometryFlags.hasCSC() else "")) - ToolSvc += MuonLayerSegmentFinderTool - tools[0].MuonLayerSegmentFinderTool = MuonLayerSegmentFinderTool + kwargs.setdefault("MuonCombinedInDetExtensionTools", tools ) kwargs.setdefault("usePRDs",True) kwargs.setdefault("HasCSC", MuonGeometryFlags.hasCSC() ) @@ -66,14 +62,14 @@ def MuGirlStauAlg(name="MuGirlStauAlg",**kwargs): kwargs.setdefault("METrackCollection","") kwargs.setdefault("SegmentCollection","MuGirlStauSegments") return CfgMgr.MuonCombinedInDetExtensionAlg(name,**kwargs) - + def MuonCombinedInDetCandidateAlg( name="MuonCombinedInDetCandidateAlg",**kwargs ): from InDetRecExample.InDetJobProperties import InDetFlags kwargs.setdefault("TrackSelector",getPublicTool("MuonCombinedInDetDetailedTrackSelectorTool") ) if muonCombinedRecFlags.doSiAssocForwardMuons() and InDetFlags.doForwardTracks(): kwargs.setdefault("DoSiliconAssocForwardMuons", True ) kwargs.setdefault("InDetForwardTrackSelector", getPublicTool("MuonCombinedInDetDetailedForwardTrackSelectorTool") ) - + kwargs.setdefault("MuonSystemExtensionTool", getPublicTool("MuonSystemExtensionTool")) return CfgMgr.MuonCombinedInDetCandidateAlg(name,**kwargs) @@ -113,11 +109,11 @@ def recordMuonCreatorAlgObjs (kw): if val('MakeClusters'): objs['CaloClusterCellLinkContainer'] = val('CaloClusterCellLinkName') + '_links' objs['xAOD::CaloClusterContainer'] = val('ClusterContainerName') - + from RecExConfig.ObjKeyStore import objKeyStore objKeyStore.addManyTypesTransient (objs) return - + def MuonCreatorAlg( name="MuonCreatorAlg",**kwargs ): kwargs.setdefault("MuonCreatorTool",getPublicTool("MuonCreatorTool")) recordMuonCreatorAlgObjs (kwargs) @@ -155,30 +151,30 @@ class MuonCombinedReconstruction(ConfiguredMuonRec): if not self.isEnabled(): return topSequence = AlgSequence() - + #if jobproperties.Beam.beamType()=='collisions': # creates input collections for ID and MS candidates - topSequence += getAlgorithm("MuonCombinedInDetCandidateAlg") - topSequence += getAlgorithm("MuonCombinedMuonCandidateAlg") - + topSequence += getAlgorithm("MuonCombinedInDetCandidateAlg") + topSequence += getAlgorithm("MuonCombinedMuonCandidateAlg") + # runs ID+MS combinations (fit, staco, mugirl, ID-taggers) if muonCombinedRecFlags.doStatisticalCombination() or muonCombinedRecFlags.doCombinedFit(): - topSequence += getAlgorithm("MuonCombinedAlg") + topSequence += getAlgorithm("MuonCombinedAlg") if muonCombinedRecFlags.doMuGirl(): - topSequence += getAlgorithm("MuonInsideOutRecoAlg") + topSequence += getAlgorithm("MuonInsideOutRecoAlg") if muonCombinedRecFlags.doMuGirlLowBeta(): topSequence += getAlgorithm("MuGirlStauAlg") if muonCombinedRecFlags.doCaloTrkMuId(): - topSequence += getAlgorithm("MuonCaloTagAlg") - + topSequence += getAlgorithm("MuonCaloTagAlg") + if muonCombinedRecFlags.doMuonSegmentTagger(): getPublicTool("MuonSegmentTagTool") - topSequence += getAlgorithm("MuonSegmentTagAlg") + topSequence += getAlgorithm("MuonSegmentTagAlg") # runs over outputs and create xAODMuon collection topSequence += getAlgorithm("MuonCreatorAlg") - + if muonCombinedRecFlags.doMuGirl() and muonCombinedRecFlags.doMuGirlLowBeta(): topSequence += getAlgorithm("StauCreatorAlg")