diff --git a/Trigger/TrigHypothesis/TrigMuonHypoMT/CMakeLists.txt b/Trigger/TrigHypothesis/TrigMuonHypoMT/CMakeLists.txt index 468a93078c410fc0dd3b49eddc4ac17f99a83160..bbf06bebc98fee203b18fca92799650007b045e3 100644 --- a/Trigger/TrigHypothesis/TrigMuonHypoMT/CMakeLists.txt +++ b/Trigger/TrigHypothesis/TrigMuonHypoMT/CMakeLists.txt @@ -22,7 +22,7 @@ atlas_add_component( TrigMuonHypoMT src/*.cxx src/components/*.cxx INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} - LINK_LIBRARIES ${CLHEP_LIBRARIES} xAODTrigMuon TrigInterfacesLib DecisionHandling AthViews xAODMuon GaudiKernel ) + LINK_LIBRARIES ${CLHEP_LIBRARIES} xAODTrigMuon TrigInterfacesLib DecisionHandling AthViews xAODMuon GaudiKernel TrigT1Interfaces) # Install files from the package: atlas_install_python_modules( python/*.py ) diff --git a/Trigger/TrigHypothesis/TrigMuonHypoMT/python/TrigMuonHypoMTConfig.py b/Trigger/TrigHypothesis/TrigMuonHypoMT/python/TrigMuonHypoMTConfig.py index b35020146aaf62aa944a97b9baa17a7c53740082..b85b046a11b5ca3947b638bc0dd90ff40e7769d8 100755 --- a/Trigger/TrigHypothesis/TrigMuonHypoMT/python/TrigMuonHypoMTConfig.py +++ b/Trigger/TrigHypothesis/TrigMuonHypoMT/python/TrigMuonHypoMTConfig.py @@ -7,7 +7,8 @@ from TrigMuonHypoMT.TrigMuonHypoMTConf import ( # noqa: F401 (algs not used her TrigMuonEFMSonlyHypoAlg, TrigMuonEFMSonlyHypoTool, TrigMuisoHypoAlg, TrigMuisoHypoTool, TrigMuonEFCombinerHypoAlg, TrigMuonEFCombinerHypoTool, - TrigMuonEFTrackIsolationHypoAlg, TrigMuonEFTrackIsolationHypoTool + TrigMuonEFTrackIsolationHypoAlg, TrigMuonEFTrackIsolationHypoTool, + TrigL2MuonOverlapRemoverMufastAlg, TrigL2MuonOverlapRemoverMucombAlg, TrigL2MuonOverlapRemoverTool ) # import monitoring @@ -16,7 +17,9 @@ from TrigMuonHypoMT.TrigMuonHypoMonitoringMT import ( TrigmuCombHypoMonitoring, TrigMuonEFMSonlyHypoMonitoring, TrigMuisoHypoMonitoring, - TrigMuonEFCombinerHypoMonitoring + TrigMuonEFCombinerHypoMonitoring, + TrigL2MuonOverlapRemoverMonitoringMufast, + TrigL2MuonOverlapRemoverMonitoringMucomb ) # other imports @@ -286,6 +289,87 @@ class TrigMufastHypoConfig(object): return tool +### for TrigL2MuonOverlapRemoverMufast +def TrigL2MuonOverlapRemoverMufastToolFromDict( chainDict ): + + # will change after adding muComb OverlapRemover + basedFex = 'Mufast' + config = TrigL2MuonOverlapRemoverMufastConfig() + tool=config.ConfigurationHypoTool( chainDict['chainName'], basedFex) + # # Setup MonTool for monitored variables in AthenaMonitoring package + addMonitoring( tool, TrigL2MuonOverlapRemoverMonitoringMufast, 'TrigL2MuonOverlapRemoverMufastTool', chainDict['chainName'] ) + + return tool + + +class TrigL2MuonOverlapRemoverMufastConfig(object): + + def ConfigurationHypoTool( self, thresholdHLT, basedFex): + + tool = TrigL2MuonOverlapRemoverTool( thresholdHLT ) + + if (basedFex=='Mufast'): + tool.DoMufastBasedRemoval = True + else: + raise Exception('TrigL2MuonOverlapRemover Misconfigured (basedFex)!') + + # cut defintion + if(tool.DoMufastBasedRemoval): + tool.MufastRequireDR = True + tool.MufastRequireMass = True + tool.MufastRequireSameSign = True + # BB + tool.MufastDRThresBB = 0.05 + tool.MufastMassThresBB = 0.20 + # BE + tool.MufastDRThresBE = 0.05 + tool.MufastMassThresBE = 0.20 + # EE + tool.MufastEtaBinsEC = [0, 1.9, 2.1, 9.9] + tool.MufastDRThresEC = [0.06, 0.05, 0.05] + tool.MufastMassThresEC = [0.20, 0.15, 0.10] + + return tool + + +### for TrigL2MuonOverlapRemoverMucomb +def TrigL2MuonOverlapRemoverMucombToolFromDict( chainDict ): + + # will change after adding muComb OverlapRemover + basedFex = 'Mucomb' + config = TrigL2MuonOverlapRemoverMucombConfig() + tool=config.ConfigurationHypoTool( chainDict['chainName'], basedFex) + # # Setup MonTool for monitored variables in AthenaMonitoring package + addMonitoring( tool, TrigL2MuonOverlapRemoverMonitoringMucomb, 'TrigL2MuonOverlapRemoverMucombTool', chainDict['chainName'] ) + + return tool + + +class TrigL2MuonOverlapRemoverMucombConfig(object): + + def ConfigurationHypoTool( self, thresholdHLT, basedFex): + + tool = TrigL2MuonOverlapRemoverTool( thresholdHLT ) + + if (basedFex=='Mucomb'): + tool.DoMucombBasedRemoval = True + else: + raise Exception('TrigL2MuonOverlapRemover Misconfigured (basedFex)!') + + # cut defintion + if(tool.DoMucombBasedRemoval): + tool.MucombRequireDR = True + tool.MucombRequireMufastDR = True + tool.MucombRequireMass = True + tool.MucombRequireSameSign = True + tool.MucombEtaBins = [0, 0.9, 1.1, 1.9, 2.1, 9.9] + tool.MucombDRThres = [0.002, 0.001, 0.002, 0.002, 0.002] + tool.MucombMufastDRThres = [0.4, 0.4, 0.4, 0.4, 0.4] + tool.MucombMassThres = [0.004, 0.002, 0.006, 0.006, 0.006] + + return tool + + def TrigmuCombHypoToolFromDict( chainDict ): thresholds = getThresholdsFromDict( chainDict ) diff --git a/Trigger/TrigHypothesis/TrigMuonHypoMT/python/TrigMuonHypoMonitoringMT.py b/Trigger/TrigHypothesis/TrigMuonHypoMT/python/TrigMuonHypoMonitoringMT.py index f6eb0519561f9787a131d0a959ab81aa0cf2e590..b51018c44c8fcd5b504778d058d920321f8b6f75 100755 --- a/Trigger/TrigHypothesis/TrigMuonHypoMT/python/TrigMuonHypoMonitoringMT.py +++ b/Trigger/TrigHypothesis/TrigMuonHypoMT/python/TrigMuonHypoMonitoringMT.py @@ -25,6 +25,32 @@ class TrigMufastHypoMonitoring(GenericMonitoringTool): self.defineHistogram('XatBe', type='TH1F', path='EXPERT', title="DCA along X; X (cm)", xbins=100, xmin=-1000, xmax=1000) +class TrigL2MuonOverlapRemoverMonitoringMufast(GenericMonitoringTool): + def __init__ (self, name): + super(TrigL2MuonOverlapRemoverMonitoringMufast, self).__init__(name) + + self.defineHistogram('MufastError', type='TH1F', path='EXPERT', title="error in #muFast based overlap removal; error code", + xbins=10, xmin=0, xmax=10) + self.defineHistogram('DR', type='TH1F', path='EXPERT', title="#muFast objects dR; dR", + xbins=108, xmin=-0.1, xmax=3.5) + self.defineHistogram('Mass',type='TH1F', path='EXPERT', title="#muFast objects invMass; Mass (GeV)", + xbins=202, xmin=-1, xmax=100) + self.defineHistogram('DRLog10', type='TH1F', path='EXPERT', title="#muFast objects Log10(dR); Log10(dR)", + xbins=102, xmin=-4.1, xmax=1.0) + self.defineHistogram('MassLog10',type='TH1F', path='EXPERT', title="#muFast objects Log10(invMass); Log10(Mass (GeV))", + xbins=142, xmin=-4.1, xmax=3.0) + self.defineHistogram('Mass , DR', type='TH2F', path='EXPERT', title="#muFast objects Mass vs DR; Mass; dR", + xbins=54, xmin=-0.1, xmax=3.5, ybins=101, ymin=-1, ymax=100) + self.defineHistogram('NrAllEVs',type='TH1F', path='EXPERT', title="nr of all EVs received for #muFast removal; nr", + xbins=10, xmin=0, xmax=10) + self.defineHistogram('NrActiveEVs',type='TH1F', path='EXPERT', title="nr of active EVs after #muFast removal ; nr", + xbins=10, xmin=0, xmax=10) + self.defineHistogram('NrOverlapped',type='TH1F', path='EXPERT', title="nr of #muFast overlapped; nr", + xbins=10, xmin=0, xmax=10) + self.defineHistogram('OverlappedEta , OverlappedPhi', type='TH2F', path='EXPERT', title="#muFast overlapped Eta vs Phi; Eta; Phi", + xbins=50, xmin=-3.2, xmax=3.2, ybins=25, ymin=-3.15, ymax=3.15) + self.defineHistogram('OverlappedPt', type='TH1F', path='EXPERT', title="#muFast overlapped P_{T}; P_{T} (GeV)", + xbins=200, xmin=-100, xmax=100) class TrigmuCombHypoMonitoring(GenericMonitoringTool): def __init__ (self, name): @@ -45,6 +71,34 @@ class TrigmuCombHypoMonitoring(GenericMonitoringTool): self.defineHistogram('A0', type='TH1F', path='EXPERT', title="PCA along x-y from ID track from #muComb; PCA(A0) (mm)", xbins=100, xmin=-0.6, xmax=0.6) +class TrigL2MuonOverlapRemoverMonitoringMucomb(GenericMonitoringTool): + def __init__ (self, name): + super(TrigL2MuonOverlapRemoverMonitoringMucomb, self).__init__(name) + + self.defineHistogram('MucombError', type='TH1F', path='EXPERT', title="error in #muComb based overlap removal; error code", + xbins=10, xmin=0, xmax=10) + self.defineHistogram('DR', type='TH1F', path='EXPERT', title="#muComb objects dR; dR", + xbins=108, xmin=-0.1, xmax=3.5) + self.defineHistogram('Mass',type='TH1F', path='EXPERT', title="#muComb objects invMass; Mass (GeV)", + xbins=202, xmin=-1, xmax=100) + self.defineHistogram('DRLog10', type='TH1F', path='EXPERT', title="#muFast objects Log10(dR); Log10(dR)", + xbins=102, xmin=-4.1, xmax=1.0) + self.defineHistogram('MassLog10',type='TH1F', path='EXPERT', title="#muFast objects Log10(invMass); Log10(Mass (GeV))", + xbins=142, xmin=-4.1, xmax=3.0) + self.defineHistogram('Mass , DR', type='TH2F', path='EXPERT', title="#muComb objects Mass vs DR; Mass; dR", + xbins=54, xmin=-0.1, xmax=3.5, ybins=101, ymin=-1, ymax=100) + self.defineHistogram('NrAllEVs',type='TH1F', path='EXPERT', title="nr of all EVs received for #muComb removal; nr", + xbins=10, xmin=0, xmax=10) + self.defineHistogram('NrActiveEVs',type='TH1F', path='EXPERT', title="nr of active EVs after #muComb removal ; nr", + xbins=10, xmin=0, xmax=10) + self.defineHistogram('NrOverlapped',type='TH1F', path='EXPERT', title="nr of #muComb overlapped; nr", + xbins=10, xmin=0, xmax=10) + self.defineHistogram('OverlappedEta , OverlappedPhi', type='TH2F', path='EXPERT', title="#muComb overlapped Eta vs Phi; Eta; Phi", + xbins=50, xmin=-3.2, xmax=3.2, ybins=25, ymin=-3.15, ymax=3.15) + self.defineHistogram('OverlappedPt', type='TH1F', path='EXPERT', title="#muComb overlapped P_{T}; P_{T} (GeV)", + xbins=200, xmin=-100, xmax=100) + + class TrigMuisoHypoMonitoring(GenericMonitoringTool): def __init__ (self, name): diff --git a/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverMucombAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverMucombAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..f496880ae8467991e1c0423155d500f12d344d74 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverMucombAlg.cxx @@ -0,0 +1,127 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include <math.h> + +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/StatusCode.h" +#include "AthLinks/ElementLink.h" + +#include "DecisionHandling/TrigCompositeUtils.h" +#include "xAODTrigMuon/L2StandAloneMuonContainer.h" +#include "xAODTrigger/TrigCompositeContainer.h" + +#include "TrigL2MuonOverlapRemoverMucombAlg.h" +#include "AthViews/ViewHelper.h" + +using namespace TrigCompositeUtils; + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +TrigL2MuonOverlapRemoverMucombAlg::TrigL2MuonOverlapRemoverMucombAlg( const std::string& name, + ISvcLocator* pSvcLocator ) : + ::HypoBase( name, pSvcLocator ) +{} + +TrigL2MuonOverlapRemoverMucombAlg::~TrigL2MuonOverlapRemoverMucombAlg() +{} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +StatusCode TrigL2MuonOverlapRemoverMucombAlg::initialize() +{ + ATH_MSG_DEBUG( "Initializing " << name() << "..." ); + ATH_CHECK(m_OverlapRemoverTools.retrieve()); + + renounce(m_OverlapRemoverKey); + ATH_CHECK(m_OverlapRemoverKey.initialize()); + + ATH_MSG_DEBUG( "Initialization completed successfully" ); + return StatusCode::SUCCESS; +} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +StatusCode TrigL2MuonOverlapRemoverMucombAlg::execute(const EventContext& context) const +{ + ATH_MSG_DEBUG("StatusCode TrigL2MuonOverlapRemoverMucomb::execute start"); + auto previousDecisionsHandle = SG::makeHandle( decisionInput(), context); + ATH_MSG_DEBUG("Runnung with " << previousDecisionsHandle->size() << " implicit ReadHandles for previous decision"); + + // new output decisions + SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context ); + auto decisions = outputHandle.ptr(); + // end of common + + + std::vector<TrigL2MuonOverlapRemoverTool::L2CBMuonOverlapInfo> toolInput; + // loop over previous decisions + size_t counter = 0; + + for ( const auto previousDecision: *previousDecisionsHandle ) { + //get RecRoI + auto RecRoIInfo = TrigCompositeUtils::findLink< DataVector< LVL1::RecMuonRoI > >( previousDecision, initialRecRoIString() ); + auto RecRoIEL = RecRoIInfo.link; + ATH_CHECK( RecRoIEL.isValid() ); + const LVL1::RecMuonRoI* RecRoI = *RecRoIEL; + + // get View + ATH_CHECK( previousDecision->hasObjectLink( viewString()) ); + auto viewEL = previousDecision->objectLink<ViewContainer>( viewString() ); + ATH_CHECK( viewEL.isValid() ); + + // get info + auto L2MuonOverlapRemoverHandle = ViewHelper::makeHandle( *viewEL, m_OverlapRemoverKey, context ); + ATH_CHECK( L2MuonOverlapRemoverHandle.isValid() ); + ATH_MSG_DEBUG( "Muinfo handle size: " << L2MuonOverlapRemoverHandle->size() << "..."); + + auto overlapEL = ViewHelper::makeLink( *viewEL, L2MuonOverlapRemoverHandle, 0 ); + ATH_CHECK( overlapEL.isValid() ); + const xAOD::L2CombinedMuon* overlap = *overlapEL; + + // create new decisions + auto newd = newDecisionIn( decisions ); + + if ( decisionIDs( previousDecision ).size() != 0 ) { + toolInput.emplace_back( TrigL2MuonOverlapRemoverTool::L2CBMuonOverlapInfo{ newd, RecRoI, overlap, previousDecision} ); + } + + // set objectLink + newd->setObjectLink( featureString(), overlapEL ); + TrigCompositeUtils::linkToPrevious( newd, previousDecision, context); + + // DEBUG + auto muFastInfo = (*overlapEL)->muSATrack(); + ATH_MSG_DEBUG("REGTEST: muSATrack pt in " << m_OverlapRemoverKey.key() << " = " << muFastInfo->pt() << " GeV"); + ATH_MSG_DEBUG("REGTEST: muSATrack eta/phi in " << m_OverlapRemoverKey.key() << " = " << muFastInfo->eta() << "/" << muFastInfo->phi()); + ATH_MSG_DEBUG("REGTEST: L2MuonCBTrack pt in " << m_OverlapRemoverKey.key() << " = " << (*overlapEL)->pt() << " GeV"); + ATH_MSG_DEBUG("REGTEST: L2MuonCBTrack eta/phi in " << m_OverlapRemoverKey.key() << " = " << (*overlapEL)->eta() << "/" << (*overlapEL)->phi()); + ATH_MSG_DEBUG("Added view, features, previous decision to new decision "<<counter <<" for view "<<(*viewEL)->name() ); + ATH_MSG_DEBUG("Number of positive previous hypo Decision::" << decisionIDs( previousDecision ).size() ); + + counter++; + } + + ATH_MSG_DEBUG("Found " << toolInput.size() << " input to tools"); + + // to TrigL2MuonOverlapRemoverTool + StatusCode sc = StatusCode::SUCCESS; + for ( auto& tool: m_OverlapRemoverTools ) { + ATH_MSG_DEBUG("Go to " << tool ); + sc = tool->decide(toolInput); + if (!sc.isSuccess()) { + ATH_MSG_ERROR("MuonHypoTool is failed"); + return StatusCode::FAILURE; + } + } // End of tool algorithms */ + + ATH_CHECK(hypoBaseOutputProcessing(outputHandle)); + + ATH_MSG_DEBUG("StatusCode TrigL2MuonOverlapRemoverMucombAlg::execute success"); + return StatusCode::SUCCESS; + +} diff --git a/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverMucombAlg.h b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverMucombAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..f3a2fff63dcc300e37fd13d367216efdb0012e67 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverMucombAlg.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGL2MUONOVERLAPREMOVER_TRIGL2MUONOVERLAPREMOVERMUCOMBALG_H +#define TRIGL2MUONOVERLAPREMOVER_TRIGL2MUONOVERLAPREMOVERMUCOMBALG_H 1 + +#include <string> + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "StoreGate/ReadHandleKey.h" +#include "StoreGate/WriteHandleKey.h" + +#include "xAODTrigMuon/L2CombinedMuonContainer.h" +#include "xAODTrigMuon/L2StandAloneMuonContainer.h" +#include "TrigSteeringEvent/TrigRoiDescriptorCollection.h" +#include "xAODTrigger/TrigCompositeContainer.h" + +#include "DecisionHandling/TrigCompositeUtils.h" +#include "AthViews/View.h" + +#include "TrigL2MuonOverlapRemoverTool.h" +#include "DecisionHandling/HypoBase.h" + +class StoreGateSvc; +class TriggerElement; + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +using namespace TrigCompositeUtils; +class TrigL2MuonOverlapRemoverMucombAlg + : public ::HypoBase +{ + public: + + TrigL2MuonOverlapRemoverMucombAlg( const std::string& name, ISvcLocator* pSvcLocator ); + + virtual ~TrigL2MuonOverlapRemoverMucombAlg(); + + virtual StatusCode initialize() override; + virtual StatusCode execute( const EventContext& context ) const override; + + private: + + TrigL2MuonOverlapRemoverMucombAlg(); + ToolHandleArray<TrigL2MuonOverlapRemoverTool> m_OverlapRemoverTools {this, "HypoTools", {}, "Tools to perform selection"}; + + SG::ReadHandleKey<xAOD::L2CombinedMuonContainer> m_OverlapRemoverKey { + this, "L2MuonOverlapInfoFromMuCombAlg", "MuonL2CBInfo", "Key for overlap removal from previousDecisions"}; + +}; + +#endif diff --git a/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverMufastAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverMufastAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..af61ae8a9cf8109a8ef5f66d23c222664e95b617 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverMufastAlg.cxx @@ -0,0 +1,125 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include <math.h> + +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/StatusCode.h" +#include "AthLinks/ElementLink.h" + +#include "DecisionHandling/TrigCompositeUtils.h" +#include "xAODTrigMuon/L2StandAloneMuonContainer.h" +#include "xAODTrigger/TrigCompositeContainer.h" +#include "TrigT1Interfaces/RecMuonRoI.h" + +#include "TrigL2MuonOverlapRemoverMufastAlg.h" +#include "AthViews/ViewHelper.h" + +using namespace TrigCompositeUtils; + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +TrigL2MuonOverlapRemoverMufastAlg::TrigL2MuonOverlapRemoverMufastAlg( const std::string& name, + ISvcLocator* pSvcLocator ) : + ::HypoBase( name, pSvcLocator ) +{} + +TrigL2MuonOverlapRemoverMufastAlg::~TrigL2MuonOverlapRemoverMufastAlg() +{} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +StatusCode TrigL2MuonOverlapRemoverMufastAlg::initialize() +{ + ATH_MSG_DEBUG( "Initializing " << name() << "..." ); + ATH_CHECK(m_OverlapRemoverTools.retrieve()); + + renounce(m_OverlapRemoverKey); + ATH_CHECK(m_OverlapRemoverKey.initialize()); + + ATH_MSG_DEBUG( "Initialization completed successfully" ); + return StatusCode::SUCCESS; +} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +StatusCode TrigL2MuonOverlapRemoverMufastAlg::execute(const EventContext& context) const +{ + ATH_MSG_DEBUG("StatusCode TrigL2MuonOverlapRemoverMufast::execute start"); + auto previousDecisionsHandle = SG::makeHandle( decisionInput(), context); + ATH_MSG_DEBUG("Runnung with " << previousDecisionsHandle->size() << " implicit ReadHandles for previous decision"); + + // new output decisions + SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context ); + auto decisions = outputHandle.ptr(); + // end of common + + + std::vector<TrigL2MuonOverlapRemoverTool::L2SAMuonOverlapInfo> toolInput; + // loop over previous decisions + size_t counter = 0; + + for ( const auto previousDecision: *previousDecisionsHandle ) { + //get RecRoI + auto RecRoIInfo = TrigCompositeUtils::findLink< DataVector< LVL1::RecMuonRoI > >( previousDecision, initialRecRoIString() ); + auto RecRoIEL = RecRoIInfo.link; + ATH_CHECK( RecRoIEL.isValid() ); + const LVL1::RecMuonRoI* RecRoI = *RecRoIEL; + + // get View + ATH_CHECK( previousDecision->hasObjectLink( viewString()) ); + auto viewEL = previousDecision->objectLink<ViewContainer>( viewString() ); + ATH_CHECK( viewEL.isValid() ); + + // get info + auto L2MuonOverlapRemoverHandle = ViewHelper::makeHandle( *viewEL, m_OverlapRemoverKey, context ); + ATH_CHECK( L2MuonOverlapRemoverHandle.isValid() ); + ATH_MSG_DEBUG( "Muinfo handle size: " << L2MuonOverlapRemoverHandle->size() << "..."); + + auto overlapEL = ViewHelper::makeLink( *viewEL, L2MuonOverlapRemoverHandle, 0 ); + ATH_CHECK( overlapEL.isValid() ); + const xAOD::L2StandAloneMuon* overlap = *overlapEL; + + // create new decisions + auto newd = newDecisionIn( decisions ); + + if ( decisionIDs( previousDecision ).size() != 0 ) { + toolInput.emplace_back( TrigL2MuonOverlapRemoverTool::L2SAMuonOverlapInfo{ newd, RecRoI, overlap, previousDecision} ); + } + + // set objectLink + newd->setObjectLink( featureString(), overlapEL ); + TrigCompositeUtils::linkToPrevious( newd, previousDecision, context); + + // DEBUG + ATH_MSG_DEBUG("REGTEST: L2MuonSATrack pt in " << m_OverlapRemoverKey.key() << " = " << (*overlapEL)->pt() << " GeV"); + ATH_MSG_DEBUG("REGTEST: L2MuonSATrack eta/phi in " << m_OverlapRemoverKey.key() << " = " << (*overlapEL)->eta() << "/" << (*overlapEL)->phi()); + ATH_MSG_DEBUG("Added view, features, previous decision to new decision "<<counter <<" for view "<<(*viewEL)->name() ); + ATH_MSG_DEBUG("Number of positive previous hypo Decision::" << decisionIDs( previousDecision ).size() ); + + counter++; + } + + ATH_MSG_DEBUG("Found " << toolInput.size() << " input to tools"); + + // to TrigL2MuonOverlapRemoverTool + StatusCode sc = StatusCode::SUCCESS; + for ( auto& tool: m_OverlapRemoverTools ) { + ATH_MSG_DEBUG("Go to " << tool ); + sc = tool->decide(toolInput); + if (!sc.isSuccess()) { + ATH_MSG_ERROR("MuonHypoTool is failed"); + return StatusCode::FAILURE; + } + } // End of tool algorithms */ + + ATH_CHECK(hypoBaseOutputProcessing(outputHandle)); + + ATH_MSG_DEBUG("StatusCode TrigL2MuonOverlapRemoverAlg::execute success"); + return StatusCode::SUCCESS; + +} diff --git a/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverMufastAlg.h b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverMufastAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..0543a0fbf6b8e320667cf84f8c1def0f30c0c875 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverMufastAlg.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGL2MUONOVERLAPREMOVER_TRIGL2MUONOVERLAPREMOVERMUFASTALG_H +#define TRIGL2MUONOVERLAPREMOVER_TRIGL2MUONOVERLAPREMOVERMUFASTALG_H 1 + +#include <string> + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "StoreGate/ReadHandleKey.h" +#include "StoreGate/WriteHandleKey.h" + +#include "xAODTrigMuon/L2CombinedMuonContainer.h" +#include "xAODTrigMuon/L2StandAloneMuonContainer.h" +#include "TrigSteeringEvent/TrigRoiDescriptorCollection.h" +#include "xAODTrigger/TrigCompositeContainer.h" + +#include "DecisionHandling/TrigCompositeUtils.h" +#include "AthViews/View.h" + +#include "TrigL2MuonOverlapRemoverTool.h" +#include "DecisionHandling/HypoBase.h" + +class StoreGateSvc; +class TriggerElement; + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +using namespace TrigCompositeUtils; +class TrigL2MuonOverlapRemoverMufastAlg + : public ::HypoBase +{ + public: + + TrigL2MuonOverlapRemoverMufastAlg( const std::string& name, ISvcLocator* pSvcLocator ); + + virtual ~TrigL2MuonOverlapRemoverMufastAlg(); + + virtual StatusCode initialize() override; + virtual StatusCode execute( const EventContext& context ) const override; + + private: + + TrigL2MuonOverlapRemoverMufastAlg(); + ToolHandleArray<TrigL2MuonOverlapRemoverTool> m_OverlapRemoverTools {this, "HypoTools", {}, "Tools to perform selection"}; + + SG::ReadHandleKey<xAOD::L2StandAloneMuonContainer> m_OverlapRemoverKey { + this, "L2MuonOverlapInfoFromMuFastAlg", "MuonL2SAInfo", "Key for overlap removal from previousDecisions"}; + +}; + +#endif diff --git a/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverTool.cxx b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e9ec93c9b1342678e43578f665833192b1b80e21 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverTool.cxx @@ -0,0 +1,873 @@ +/* +Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include <math.h> +#include <algorithm> + +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/StatusCode.h" +#include "AthenaMonitoring/Monitored.h" + +#include "DecisionHandling/Combinators.h" + +#include "xAODTrigMuon/L2CombinedMuonContainer.h" +#include "xAODTrigMuon/versions/L2CombinedMuonContainer_v1.h" +#include "xAODTrigMuon/L2CombinedMuon.h" +#include "DecisionHandling/TrigCompositeUtils.h" +#include "TrigL2MuonOverlapRemoverTool.h" + +using namespace TrigCompositeUtils; +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +TrigL2MuonOverlapRemoverTool::TrigL2MuonOverlapRemoverTool(const std::string& type, + const std::string & name, + const IInterface* parent ) + : AthAlgTool( type, name, parent ), + m_decisionId( HLT::Identifier::fromToolName( name ) ) +{ +} + +TrigL2MuonOverlapRemoverTool::~TrigL2MuonOverlapRemoverTool(){ +} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +StatusCode TrigL2MuonOverlapRemoverTool::initialize() +{ + ATH_MSG_DEBUG("Initializing " << name() ); + + ATH_MSG_DEBUG( "Tool configured for chain/id: " << m_decisionId ); + + // MufastOverlapRemoval + if( m_doMufastBasedRemoval ) { + ATH_MSG_DEBUG( "--- muFast based overlap removal as: ---" ); + if( m_muFastRequireDR ) { + ATH_MSG_DEBUG( "+ dR cut:" ); + if( (m_muFastEtaBinsEC.size()-1) != m_muFastDRThresEC.size() ) { + ATH_MSG_DEBUG( "bad thresholds setup .... exiting!" ); + return StatusCode::FAILURE; + } + ATH_MSG_DEBUG( " B-B : dR < " << m_muFastDRThresBB ); + ATH_MSG_DEBUG( " B-E : dR < " << m_muFastDRThresBE ); + ATH_MSG_DEBUG( " E-E : " ); + for(unsigned int i=0; i<m_muFastDRThresEC.size(); i++) { + ATH_MSG_DEBUG( " EtaBin " << m_muFastEtaBinsEC[i] << " - " << m_muFastEtaBinsEC[i+1] + << " : dR < " << m_muFastDRThresEC[i] ); + } + } + if( m_muFastRequireMass ) { + ATH_MSG_DEBUG( "+ Mass cut:" ); + if( (m_muFastEtaBinsEC.size()-1) != m_muFastMassThresEC.size() ) { + ATH_MSG_DEBUG( "bad thresholds setup .... exiting!" ); + return StatusCode::FAILURE; + } + ATH_MSG_DEBUG( " B-B : Mass < " << m_muFastMassThresBB ); + ATH_MSG_DEBUG( " B-E : Mass < " << m_muFastMassThresBE ); + ATH_MSG_DEBUG( " E-E : " ); + for(unsigned int i=0; i<m_muFastMassThresEC.size(); i++) { + ATH_MSG_DEBUG( " EtaBin " << m_muFastEtaBinsEC[i] << " - " << m_muFastEtaBinsEC[i+1] + << " : Mass < " << m_muFastMassThresEC[i] ); + } + } + if( m_muFastRequireSameSign ) ATH_MSG_DEBUG( "+ Same charge sign" ); + } + + // MucombOverlapRemoval + if( m_doMucombBasedRemoval ) { + ATH_MSG_DEBUG( "--- muComb based overlap removal as: ---" ); + if( m_muCombRequireDR ) { + ATH_MSG_DEBUG( "+ dR cut:" ); + if( (m_muCombEtaBins.size()-1) != m_muCombDRThres.size() ) { + ATH_MSG_DEBUG( "bad thresholds setup .... exiting!" ); + return StatusCode::FAILURE; + } + for(unsigned int i=0; i<m_muCombDRThres.size(); i++) { + ATH_MSG_DEBUG( " EtaBin " << m_muCombEtaBins[i] << " - " << m_muCombEtaBins[i+1] + << " : dR < " << m_muCombDRThres[i] ); + } + } + if( m_muCombRequireMufastDR ) { + ATH_MSG_DEBUG( "+ dr(by mF) cut:" ); + if( (m_muCombEtaBins.size()-1) != m_muCombMufastDRThres.size() ) { + ATH_MSG_DEBUG( "bad thresholds setup .... exiting!" ); + return StatusCode::FAILURE; + } + for(unsigned int i=0; i<m_muCombMufastDRThres.size(); i++) { + ATH_MSG_DEBUG( " EtaBin " << m_muCombEtaBins[i] << " - " << m_muCombEtaBins[i+1] + << " : dR(mF) < " << m_muCombMufastDRThres[i] ); + } + } + if( m_muCombRequireMass ) { + ATH_MSG_DEBUG( "+ Mass cut:" ); + if( (m_muCombEtaBins.size()-1) != m_muCombMassThres.size() ) { + ATH_MSG_DEBUG( "bad thresholds setup .... exiting!" ); + return StatusCode::FAILURE; + } + for(unsigned int i=0; i<m_muCombMassThres.size(); i++) { + ATH_MSG_DEBUG( " EtaBin " << m_muCombEtaBins[i] << " - " << m_muCombEtaBins[i+1] + << " : Mass < " << m_muCombMassThres[i] ); + } + } + if( m_muCombRequireSameSign ) ATH_MSG_DEBUG( "+ Same charge sign" ); + } + + if ( not m_monTool.name().empty() ) { + ATH_CHECK( m_monTool.retrieve() ); + ATH_MSG_DEBUG("MonTool name: " << m_monTool); + } + + ATH_MSG_DEBUG("Initializing" << name() << "successfully"); + + return StatusCode::SUCCESS; +} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +StatusCode TrigL2MuonOverlapRemoverTool::decide(std::vector<L2SAMuonOverlapInfo>& toolInput) const { + + ATH_MSG_DEBUG("Retrieved from TrigL2MuonOverlapRemoverMufastAlg and Running TrigL2MuonOverlapRemoverTool for selections."); + + std::vector<TrigL2MuonOverlapRemoverTool::L2SAMuonOverlapInfo> input; + + for( unsigned int i=0; i<toolInput.size(); ++i ) { + if ( TrigCompositeUtils::passed( m_decisionId.numeric(), toolInput[i].previousDecisionIDs) ){ + input.push_back(toolInput[i]); + } + } + + size_t numMuon = input.size(); + + if ( numMuon == 0) { + ATH_MSG_DEBUG( "No positive previous hypo decision. Not need overlap removal." ); + auto mufastNrAllEVs = Monitored::Scalar("NrAllEVs", -9999.); + auto mufastNrActiveEVs = Monitored::Scalar("NrActiveEVs", -9999.); + auto monitorIt = Monitored::Group(m_monTool, mufastNrAllEVs, mufastNrActiveEVs); + mufastNrActiveEVs = numMuon; + mufastNrAllEVs = numMuon; + return StatusCode::SUCCESS; + } + else if ( numMuon == 1 ) { + ATH_MSG_DEBUG("Number of muon event = " << numMuon ); + ATH_MSG_DEBUG("no overlap Removal necessary. exitting with all EventViews active." ); + auto mufastNrAllEVs = Monitored::Scalar("NrAllEVs", -9999.); + auto mufastNrActiveEVs = Monitored::Scalar("NrActiveEVs", -9999.); + auto monitorIt = Monitored::Group(m_monTool, mufastNrAllEVs, mufastNrActiveEVs); + mufastNrActiveEVs = numMuon; + mufastNrAllEVs = numMuon; + if ( TrigCompositeUtils::passed( m_decisionId.numeric(), input[0].previousDecisionIDs) ) { + TrigCompositeUtils::addDecisionID(m_decisionId, input[0].decision); + } else { + ATH_MSG_DEBUG("Not match DecisionID:" << m_decisionId ); + } + return StatusCode::SUCCESS; + } else { + ATH_MSG_DEBUG("Number of muon event = " << numMuon ); + auto mufastNrAllEVs = Monitored::Scalar("NrAllEVs", -9999.); + auto monitorIt = Monitored::Group(m_monTool, mufastNrAllEVs); + mufastNrAllEVs = numMuon; + checkOverlap(input); + return StatusCode::SUCCESS; + } + return StatusCode::SUCCESS; +} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +StatusCode TrigL2MuonOverlapRemoverTool::checkOverlap(std::vector<L2SAMuonOverlapInfo>& toolInput) const { + + size_t numMuon = toolInput.size(); + unsigned int i,j; + std::vector<unsigned int> mufastResult; + + for(i=0; i<numMuon; i++) {mufastResult.push_back(i); } + for(i=0; i<numMuon-1; i++){ + if( TrigCompositeUtils::passed( m_decisionId.numeric(), toolInput[i].previousDecisionIDs ) ){ + for(j=i+1; j<numMuon; j++){ + if( TrigCompositeUtils::passed( m_decisionId.numeric(), toolInput[j].previousDecisionIDs ) ){ + ATH_MSG_DEBUG("++ i=" << i << " vs j=" << j); + bool overlapped = isOverlap(toolInput[i].overlap, toolInput[j].overlap); + if( ! overlapped ){ // judged as different + ATH_MSG_DEBUG(" judged as: differenr objects"); + if( mufastResult[i] == mufastResult[j] ) { // but marked as same by someone + ATH_MSG_ERROR( "inconsistentency in muFast based overlap removal for more than two objects" ); + ATH_MSG_DEBUG( "two objects are judged as different but both were already marked as identical by someone else as: " ); + ATH_MSG_DEBUG( "i/j/result[i]/result[j]=" << i << " / " << j << " / " << mufastResult[i] << " / " << mufastResult[j] ); + auto mufastError = Monitored::Scalar("MufastError", -9999.); + auto monitorIt = Monitored::Group(m_monTool, mufastError); + mufastError = TrigL2MuonOverlapRemoverToolConsts::errorCode_inconsistent_overlap1; + return StatusCode::FAILURE; + } + } + else{ // judged as overlap + if( (mufastResult[j] != j && mufastResult[i] != mufastResult[j]) || (mufastResult[j] == j && mufastResult[i] != i) ){ + ATH_MSG_ERROR( "inconsistentency in muFast based overlap removal for more than two objects" ); + ATH_MSG_DEBUG( "two objects are judged as overlap but only either was already marked as overlap to someone else: " ); + ATH_MSG_DEBUG( "i/j/result[i]/result[j]=" << i << " / " << j << " / " << mufastResult[i] << " / " << mufastResult[j] ); + auto mufastError = Monitored::Scalar("MufastError", -9999.); + auto monitorIt = Monitored::Group(m_monTool, mufastError); + mufastError = TrigL2MuonOverlapRemoverToolConsts::errorCode_inconsistent_overlap2; + return StatusCode::FAILURE; + } + ATH_MSG_DEBUG(" judged as: overlapped objects"); + if( mufastResult[i] == i ) { + ATH_MSG_DEBUG( " i is not yet marked as overlap. so, it is a newly found overlap" ); + ATH_MSG_DEBUG( " -> marking mufastResult[j] as i..." ); + mufastResult[j] = i; + } else { + ATH_MSG_DEBUG( " both i/j already marked as overlap by: mufastResult[i]=" << mufastResult[i] ); + ATH_MSG_DEBUG( " -> do nothing..." ); + } + } + } + } + } + } + + + unsigned int n_uniqueMuon = 0; + for(i=0; i<numMuon; i++) { + ATH_MSG_DEBUG( "muFast based results: i=" << i << ": "); + if( mufastResult[i] != i ) { ATH_MSG_DEBUG( " overlap to j=" << mufastResult[i] ); } + else { + n_uniqueMuon++; + ATH_MSG_DEBUG( " unique" ); + if( ! TrigCompositeUtils::passed( m_decisionId.numeric(), toolInput[i].previousDecisionIDs ) ){ + ATH_MSG_DEBUG(" ,but not match DecisionID:" << m_decisionId ); + } + } + } + + ATH_MSG_DEBUG( "nr of unique Muons after muFast-based removal=" << n_uniqueMuon ); + + if( numMuon != n_uniqueMuon ){ + chooseBestMuon(toolInput, mufastResult); + } else { + ATH_MSG_DEBUG( "no overlap identified. exitting with all EventViews active" ); + auto mufastNrActiveEVs = Monitored::Scalar("NrActiveEVs", -9999.); + auto monitorIt = Monitored::Group(m_monTool, mufastNrActiveEVs); + mufastNrActiveEVs = n_uniqueMuon; + for(i=0; i<numMuon; i++){ + if( TrigCompositeUtils::passed( m_decisionId.numeric(), toolInput[i].previousDecisionIDs ) ){ + ATH_MSG_DEBUG("Match DecisionID:" << m_decisionId ); + TrigCompositeUtils::addDecisionID( m_decisionId, toolInput[i].decision ); + } + else{ ATH_MSG_DEBUG( ",but not match DecisionID:" << m_decisionId );} + } + return StatusCode::SUCCESS; + } + return StatusCode::SUCCESS; +} + + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +bool TrigL2MuonOverlapRemoverTool::isOverlap(const xAOD::L2StandAloneMuon *mf1, + const xAOD::L2StandAloneMuon *mf2) const +{ + + auto mufastDR = Monitored::Scalar("DR", -9999.); + auto mufastMass = Monitored::Scalar("Mass", -9999.); + auto mufastDRLog10 = Monitored::Scalar("DRLog10", -9999.); + auto mufastMassLog10 = Monitored::Scalar("MassLog10", -9999.); + + auto monitorIt = Monitored::Group(m_monTool, mufastDR, mufastMass, mufastDRLog10, mufastMassLog10); + + + ATH_MSG_DEBUG( " ...mF1: pt/eta/phi=" << mf1->pt() << " / " << mf1->etaMS() << " / " << mf1->phiMS() ); + ATH_MSG_DEBUG( " ...mF2: pt/eta/phi=" << mf2->pt() << " / " << mf2->etaMS() << " / " << mf2->phiMS() ); + + // if dR or invMass is necessary but (eta,phi) info is not avaiable + // (i.e. eta,phi=0,0; rec failed) + const double ZERO_LIMIT_FOR_ETAPHI = 1e-4; + if( (fabs(mf1->etaMS()) <ZERO_LIMIT_FOR_ETAPHI && fabs(mf1->phiMS()) < ZERO_LIMIT_FOR_ETAPHI) || + (fabs(mf2->etaMS()) <ZERO_LIMIT_FOR_ETAPHI && fabs(mf2->phiMS()) < ZERO_LIMIT_FOR_ETAPHI) ) { + ATH_MSG_DEBUG( " ...-> (eta,phi) info not available (rec at (eta,phi)=(0,0))" ); + ATH_MSG_DEBUG( " ...-> but dR of invMass check is required. cannot judge overlap -> return with false" ); + return false; + } + + // if charge or invMass is necessary but charge(=pT) info is not avaiable + const double ZERO_LIMIT_FOR_PT = 1e-4; + if( (fabs(mf1->pt()) <ZERO_LIMIT_FOR_PT) || (fabs(mf2->pt()) < ZERO_LIMIT_FOR_PT) ) { + ATH_MSG_DEBUG( " ...-> pT info not available (rec at pT=0)" ); + ATH_MSG_DEBUG( " ...-> but same sign or invMass check is required. cannot judge overlap -> return with false" ); + return false; + } + + + // determine dR, mass threshold separately for: BB, BE, EE + double dRThres = 9999; + double massThres = 9999; + + const int SADDRESS_EC = -1; + bool isBarrel1 = (mf1->sAddress() != SADDRESS_EC ) ? true : false; + bool isBarrel2 = (mf2->sAddress() != SADDRESS_EC ) ? true : false; + + if( isBarrel1 && isBarrel2 ) { // BB + ATH_MSG_DEBUG( " ...B-B" ); + dRThres =m_muFastDRThresBB; + massThres=m_muFastMassThresBB; + } + else if( (isBarrel1 && ! isBarrel2) || (!isBarrel1 && isBarrel2) ) { // BE + ATH_MSG_DEBUG( " ...B-E" ); + dRThres =m_muFastDRThresBE; + massThres=m_muFastMassThresBE; + } + else { // EE + ATH_MSG_DEBUG( " ...E-E" ); + double absEta = (fabs(mf1->pt()) > fabs(mf2->pt())) ? fabs(mf1->etaMS()) : fabs(mf2->etaMS()); + unsigned int iThres=0; + for(unsigned int i=0; i<(m_muFastEtaBinsEC.size()-1); i++) { + if ( m_muFastEtaBinsEC[i] <= absEta && absEta < m_muFastEtaBinsEC[i+1] ) iThres = i; + } + ATH_MSG_DEBUG( " ...iThres=" << iThres ); + dRThres = m_muFastDRThresEC[iThres]; + massThres = m_muFastMassThresEC[iThres]; + } + ATH_MSG_DEBUG( " ...dR threshold=" << dRThres ); + ATH_MSG_DEBUG( " ...mass threshold=" << massThres ); + + + // same sign cut + bool sameSign = false; + if( m_muFastRequireSameSign ) { + sameSign = ((mf1->pt()*mf2->pt()) > 0) ? true : false; + ATH_MSG_DEBUG( " ...-> sameSign=" << sameSign ); + } + + // dR cut + bool dRisClose = false; + double dr = dR(mf1->etaMS(),mf1->phiMS(),mf2->etaMS(),mf2->phiMS()); + + // for monitoring + mufastDR = dr; + const double monitor_limit = 1e-4; + double dr_mon = (dr>=monitor_limit) ? dr : monitor_limit; + mufastDRLog10 = log10(dr_mon); + + if( m_muFastRequireDR ) { + if( dr < dRThres ) dRisClose = true; + ATH_MSG_DEBUG( " ...-> dR=" << dr << " : dRisClose=" << dRisClose ); + } + + // mass cut + const double TRACK_MASS = 0; // just assume zero mass + bool massIsClose = false; + double mass = invMass(TRACK_MASS,mf1->pt(),mf1->etaMS(),mf1->phiMS(),TRACK_MASS,mf2->pt(),mf2->etaMS(),mf2->phiMS()); + + // for monitoring + mufastMass = mass; + double mass_mon = (mass>=monitor_limit) ? mass : monitor_limit; + mufastMassLog10 = log10(mass_mon); + + if( m_muFastRequireMass ) { + if( mass < massThres ) massIsClose = true; + ATH_MSG_DEBUG( " ...-> mass=" << mass << " : massIsClose=" << massIsClose ); + } + + // total judge + bool overlap = false; + if( ((m_muFastRequireSameSign && sameSign) || (! m_muFastRequireSameSign)) && + ((m_muFastRequireDR && dRisClose) || (! m_muFastRequireDR)) && + ((m_muFastRequireMass && massIsClose) || (! m_muFastRequireMass)) ) { + overlap = true; + } + + ATH_MSG_DEBUG( " ...=> isOverlap=" << overlap ); + + return overlap; + +} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +double TrigL2MuonOverlapRemoverTool::dR(double eta1, double phi1, double eta2, double phi2) const +{ + double deta = eta1 - eta2; + double dphi = fabs(phi1 - phi2); + if( dphi > CLHEP::pi ) dphi = CLHEP::twopi - dphi; + double dR = pow( (deta*deta + dphi*dphi), 0.5 ); + return dR; +} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +double TrigL2MuonOverlapRemoverTool::invMass(double m1, double pt1, double eta1, double phi1, + double m2, double pt2, double eta2, double phi2) const +{ + const double ZERO_LIMIT = 1e-12; + + double theta1 = 2*atan2((double)exp(-eta1),1.); + double theta2 = 2*atan2((double)exp(-eta2),1.); + + double fpt1 = fabs(pt1); + double fpt2 = fabs(pt2); + + double px1 = fpt1*cos(phi1); + double py1 = fpt1*sin(phi1); + double pz1 = fpt1/tan(theta1); + double e1 = sqrt(px1*px1+py1*py1+pz1*pz1+m1*m1); + + double px2 = fpt2*cos(phi2); + double py2 = fpt2*sin(phi2); + double pz2 = fpt2/tan(theta2); + double e2 = sqrt(px2*px2+py2*py2+pz2*pz2+m2*m2); + + double pxsum = px1 + px2; + double pysum = py1 + py2; + double pzsum = pz1 + pz2; + double esum = e1 + e2; + + double mass = 0; + double mass2 = esum*esum - pxsum*pxsum - pysum*pysum - pzsum*pzsum; + if( mass2 > ZERO_LIMIT ) mass = sqrt(mass2); + + return mass; +} + + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + + +StatusCode TrigL2MuonOverlapRemoverTool::chooseBestMuon(std::vector<L2SAMuonOverlapInfo>& toolInput, std::vector<unsigned int> mufastResult) const +{ + size_t numMuon = toolInput.size(); + unsigned int i,j,k; + + auto mufastNrActiveEVs = Monitored::Scalar("NrActiveEVs", -9999.); + auto mufastNrOverlapped = Monitored::Scalar("NrOverlapped", 0); + auto mufastOverlappedEta = Monitored::Scalar("OverlappedEta", -9999.); + auto mufastOverlappedPhi = Monitored::Scalar("OverlappedPhi", -9999.); + auto mufastOverlappedPt = Monitored::Scalar("OverlappedPt", -9999.); + + auto monitorIt = Monitored::Group(m_monTool, mufastNrActiveEVs, mufastNrOverlapped, + mufastOverlappedPt, mufastOverlappedEta, mufastOverlappedPhi); + + if( m_doMufastBasedRemoval ) { + ATH_MSG_DEBUG( "--- choose best among overlaps & disable EVs (muFast based) ---" ); + for(i=0; i<numMuon; i++) { + if( TrigCompositeUtils::passed( m_decisionId.numeric(), toolInput[i].previousDecisionIDs ) ){ + ATH_MSG_DEBUG( "++ i=" << i << ": result=" << mufastResult[i] ); + if( mufastResult[i] != i ) { + ATH_MSG_DEBUG( " overlap to some one. skip." ); + continue; + } + std::vector<unsigned int> others; + for(j=0; j<numMuon; j++) { + if( mufastResult[j] == mufastResult[i] ) others.push_back(j); + } + if( others.size() == 1 ) { + ATH_MSG_DEBUG( " unique object. keep it active." ); + TrigCompositeUtils::addDecisionID( m_decisionId, toolInput[i].decision ); + continue; + } + else { + // must choose one best + ATH_MSG_DEBUG( " overlapped objects among: " << others ); + unsigned int best_ev = 0; + float maxPtMf = 0; + float maxPtRoI = 0; + for(k=0; k<others.size(); k++) { + j=others[k]; + const LVL1::RecMuonRoI* muonRoI = toolInput[j].RecRoI; + float ptRoI = muonRoI->getThresholdValue(); + const xAOD::L2StandAloneMuon* mf = toolInput[j].overlap; + float ptMf = fabs(mf->pt()); + ATH_MSG_DEBUG(" ev/PtRoI/ptMf="<< j << "/" << ptRoI << "/" << ptMf); + if( (ptRoI-maxPtRoI) > 0.1 ) { + maxPtRoI = ptRoI; + maxPtMf = ptMf; + best_ev = j; + } + else if( fabs(ptRoI-maxPtRoI) < 0.1 ) { + if( ptMf > maxPtMf ) { + maxPtRoI = ptRoI; + maxPtMf = ptMf; + best_ev = j; + } + } + } + ATH_MSG_DEBUG( " best is: best_ev/maxPtRoI/maxPtMf=" << best_ev << " / " << maxPtRoI << " / " << maxPtMf ); + + for(k=0; k<others.size(); k++) { + j=others[k]; + if( j != best_ev ) { + ATH_MSG_DEBUG( " EventView( j=" << j << " ) is not active" ); + + // monitoring + const xAOD::L2StandAloneMuon* mf = toolInput[j].overlap; + mufastNrOverlapped++; + mufastOverlappedPt = mf->pt(); + mufastOverlappedEta = mf->etaMS(); + mufastOverlappedPhi = mf->phiMS(); + } + if( j == best_ev ){ + ATH_MSG_DEBUG( " EventView( j=" << j << " ) is best one" ); + TrigCompositeUtils::addDecisionID( m_decisionId, toolInput[j].decision ); + } + } + } + } + else { ATH_MSG_DEBUG( "this muon is not match previousDecisionID:" << m_decisionId << " -> skip." ); } + } + mufastNrActiveEVs = numMuon - mufastNrOverlapped; + } + + + return StatusCode::SUCCESS; +} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +StatusCode TrigL2MuonOverlapRemoverTool::decide(std::vector<L2CBMuonOverlapInfo>& toolInput) const { + + ATH_MSG_DEBUG("Retrieved from TrigL2MuonOverlapRemoverMucombAlg and Running TrigL2MuonOverlapRemoverTool for selections."); + + std::vector<TrigL2MuonOverlapRemoverTool::L2CBMuonOverlapInfo> input; + + for( unsigned int i=0; i<toolInput.size(); ++i ) { + if ( TrigCompositeUtils::passed( m_decisionId.numeric(), toolInput[i].previousDecisionIDs) ){ + input.push_back(toolInput[i]); + } + } + + size_t numMuon = input.size(); + + if ( numMuon == 0) { + ATH_MSG_DEBUG( "No positive previous hypo decision. Not need overlap removal." ); + auto mucombNrAllEVs = Monitored::Scalar("NrAllEVs", -9999.); + auto mucombNrActiveEVs = Monitored::Scalar("NrActiveEVs", -9999.); + auto monitorIt = Monitored::Group(m_monTool, mucombNrAllEVs, mucombNrActiveEVs); + mucombNrActiveEVs = numMuon; + mucombNrAllEVs = numMuon; + return StatusCode::SUCCESS; + } + else if ( numMuon == 1 ) { + ATH_MSG_DEBUG("Number of muon event = " << numMuon ); + ATH_MSG_DEBUG("no overlap Removal necessary. exitting with all EventViews active." ); + auto mucombNrAllEVs = Monitored::Scalar("NrAllEVs", -9999.); + auto mucombNrActiveEVs = Monitored::Scalar("NrActiveEVs", -9999.); + auto monitorIt = Monitored::Group(m_monTool, mucombNrAllEVs, mucombNrActiveEVs); + mucombNrActiveEVs = numMuon; + mucombNrAllEVs = numMuon; + if ( TrigCompositeUtils::passed( m_decisionId.numeric(), input[0].previousDecisionIDs) ) { + TrigCompositeUtils::addDecisionID(m_decisionId, input[0].decision); + } else { + ATH_MSG_DEBUG("Not match DecisionID:" << m_decisionId ); + } + return StatusCode::SUCCESS; + } else { + ATH_MSG_DEBUG("Number of muon event = " << numMuon ); + auto mucombNrAllEVs = Monitored::Scalar("NrAllEVs", -9999.); + auto monitorIt = Monitored::Group(m_monTool, mucombNrAllEVs); + mucombNrAllEVs = numMuon; + checkOverlap(input); + return StatusCode::SUCCESS; + } + + return StatusCode::SUCCESS; +} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +StatusCode TrigL2MuonOverlapRemoverTool::checkOverlap(std::vector<L2CBMuonOverlapInfo>& toolInput) const { + + size_t numMuon = toolInput.size(); + unsigned int i,j; + std::vector<unsigned int> mucombResult; + + for(i=0; i<numMuon; i++) {mucombResult.push_back(i); } + for(i=0; i<numMuon-1; i++){ + if( TrigCompositeUtils::passed( m_decisionId.numeric(), toolInput[i].previousDecisionIDs ) ){ + for(j=i+1; j<numMuon; j++){ + if( TrigCompositeUtils::passed( m_decisionId.numeric(), toolInput[j].previousDecisionIDs ) ){ + ATH_MSG_DEBUG("++ i=" << i << " vs j=" << j); + bool overlapped = isOverlap(toolInput[i].overlap, toolInput[j].overlap); + if( ! overlapped ){ // judged as different + ATH_MSG_DEBUG(" judged as: differenr objects"); + if( mucombResult[i] == mucombResult[j] ) { // but marked as same by someone + ATH_MSG_ERROR( "inconsistentency in muComb based overlap removal for more than two objects" ); + ATH_MSG_DEBUG( "two objects are judged as different but both were already marked as identical by someone else as: " ); + ATH_MSG_DEBUG( "i/j/result[i]/result[j]=" << i << " / " << j << " / " << mucombResult[i] << " / " << mucombResult[j] ); + auto mucombError = Monitored::Scalar("MucombError", -9999.); + auto monitorIt = Monitored::Group(m_monTool, mucombError); + mucombError = TrigL2MuonOverlapRemoverToolConsts::errorCode_inconsistent_overlap1; + return StatusCode::FAILURE; + } + } + else{ // judged as overlap + if( (mucombResult[j] != j && mucombResult[i] != mucombResult[j]) || (mucombResult[j] == j && mucombResult[i] != i) ){ + ATH_MSG_ERROR( "inconsistentency in muComb based overlap removal for more than two objects" ); + ATH_MSG_DEBUG( "two objects are judged as overlap but only either was already marked as overlap to someone else: " ); + ATH_MSG_DEBUG( "i/j/result[i]/result[j]=" << i << " / " << j << " / " << mucombResult[i] << " / " << mucombResult[j] ); + auto mucombError = Monitored::Scalar("MucombError", -9999.); + auto monitorIt = Monitored::Group(m_monTool, mucombError); + mucombError = TrigL2MuonOverlapRemoverToolConsts::errorCode_inconsistent_overlap2; + return StatusCode::FAILURE; + } + ATH_MSG_DEBUG(" judged as: overlapped objects"); + if( mucombResult[i] == i ) { + ATH_MSG_DEBUG( " i is not yet marked as overlap. so, it is a newly found overlap" ); + ATH_MSG_DEBUG( " -> marking mucombResult[j] as i..." ); + mucombResult[j] = i; + } else { + ATH_MSG_DEBUG( " both i/j already marked as overlap by: mucombResult[i]=" << mucombResult[i] ); + ATH_MSG_DEBUG( " -> do nothing..." ); + } + } + } + } + } + } + + unsigned int n_uniqueMuon = 0; + for(i=0; i<numMuon; i++) { + ATH_MSG_DEBUG( "muComb based results: i=" << i << ": "); + if( mucombResult[i] != i ) { ATH_MSG_DEBUG( " overlap to j=" << mucombResult[i] ); } + else { + n_uniqueMuon++; + ATH_MSG_DEBUG( " unique" ); + if( ! TrigCompositeUtils::passed( m_decisionId.numeric(), toolInput[i].previousDecisionIDs ) ){ + ATH_MSG_DEBUG(" ,but not match DecisionID:" << m_decisionId ); + } + } + } + + ATH_MSG_DEBUG( "nr of unique Muons after muComb-based removal=" << n_uniqueMuon ); + + if( numMuon != n_uniqueMuon ){ + chooseBestMuon(toolInput, mucombResult); + } else { + ATH_MSG_DEBUG( "no overlap identified. exitting with all EventViews active" ); + auto mucombNrActiveEVs = Monitored::Scalar("NrActiveEVs", -9999.); + auto monitorIt = Monitored::Group(m_monTool, mucombNrActiveEVs); + mucombNrActiveEVs = n_uniqueMuon; + for(i=0; i<numMuon; i++){ + if( TrigCompositeUtils::passed( m_decisionId.numeric(), toolInput[i].previousDecisionIDs ) ){ + ATH_MSG_DEBUG("Match DecisionID:" << m_decisionId ); + TrigCompositeUtils::addDecisionID( m_decisionId, toolInput[i].decision ); + } + else{ ATH_MSG_DEBUG( ",but not match DecisionID:" << m_decisionId );} + } + return StatusCode::SUCCESS; + } + return StatusCode::SUCCESS; +} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +bool TrigL2MuonOverlapRemoverTool::isOverlap(const xAOD::L2CombinedMuon *combMf1, + const xAOD::L2CombinedMuon *combMf2) const +{ + + auto mucombDR = Monitored::Scalar("DR", -9999.); + auto mucombMass = Monitored::Scalar("Mass", -9999.); + auto mucombDRLog10 = Monitored::Scalar("DRLog10", -9999.); + auto mucombMassLog10 = Monitored::Scalar("MassLog10", -9999.); + + auto monitorIt = Monitored::Group(m_monTool, mucombDR, mucombMass, mucombDRLog10, mucombMassLog10); + + + ATH_MSG_DEBUG( " ...mF1: pt/eta/phi=" << combMf1->pt()/CLHEP::GeV << " / " << combMf1->eta() << " / " << combMf1->phi() ); + ATH_MSG_DEBUG( " ...mF2: pt/eta/phi=" << combMf2->pt()/CLHEP::GeV << " / " << combMf2->eta() << " / " << combMf2->phi() ); + + // if dR or invMass is necessary but (eta,phi) info is not avaiable + // (i.e. eta,phi=0,0; rec failed) + const double ZERO_LIMIT_FOR_ETAPHI = 1e-4; + if( (fabs(combMf1->eta()) <ZERO_LIMIT_FOR_ETAPHI && fabs(combMf1->phi()) < ZERO_LIMIT_FOR_ETAPHI) || + (fabs(combMf2->eta()) <ZERO_LIMIT_FOR_ETAPHI && fabs(combMf2->phi()) < ZERO_LIMIT_FOR_ETAPHI) ) { + ATH_MSG_DEBUG( " ...-> (eta,phi) info not available (rec at (eta,phi)=(0,0))" ); + if( m_muCombRequireDR || m_muCombRequireMass ) { + ATH_MSG_DEBUG( " ...-> but dR of invMass check is required. cannot judge overlap -> return with false" ); + return false; + } + } + + // if charge or invMass is necessary but charge(=pT) info is not avaiable + const double ZERO_LIMIT_FOR_PT = 1e-4; + if( (fabs(combMf1->pt()) <ZERO_LIMIT_FOR_PT) || (fabs(combMf2->pt()) < ZERO_LIMIT_FOR_PT) ) { + ATH_MSG_DEBUG( " ...-> pT info not available (rec at pT=0)" ); + if( m_muCombRequireSameSign || m_muCombRequireMass ) { + ATH_MSG_DEBUG( " ...-> but same sign or invMass check is required. cannot judge overlap -> return with false" ); + return false; + } + } + + // determine etabin and thresholds + double absEta = (fabs(combMf1->pt()) > fabs(combMf2->pt())) ? fabs(combMf1->eta()) : fabs(combMf2->eta()); + unsigned int iThres = 0; + for(unsigned int i=0; i<(m_muCombEtaBins.size()-1); i++) { + if ( m_muCombEtaBins[i] <= absEta && absEta < m_muCombEtaBins[i+1] ) iThres = i; + } + double dRThres = m_muCombDRThres[iThres]; + double dRbyMFThres = m_muCombMufastDRThres[iThres]; + double massThres = m_muCombMassThres[iThres]; + ATH_MSG_DEBUG( " ...iThres=" << iThres ); + if(m_muCombRequireDR) ATH_MSG_DEBUG( " ...dR threshold=" << dRThres ); + if(m_muCombRequireMufastDR) ATH_MSG_DEBUG( " ...dR(byMF) threshold=" << dRbyMFThres ); + if(m_muCombRequireMass) ATH_MSG_DEBUG( " ...mass threshold=" << massThres ); + + // same sign cut + bool sameSign = false; + if( m_muCombRequireSameSign ) { + sameSign = ((combMf1->pt()*combMf2->pt()) > 0) ? true : false; + ATH_MSG_DEBUG( " ...-> sameSign=" << sameSign ); + } + + // dR cut + bool dRisClose = false; + double dr = dR(combMf1->eta(),combMf1->phi(),combMf2->eta(),combMf2->phi()); + + mucombDR = dr; + const double monitor_limit = 1e-4; + double dr_mon = (dr>=monitor_limit) ? dr : monitor_limit; + mucombDRLog10 = log10(dr_mon); + + if( m_muCombRequireDR ) { + if( dr < dRThres ) dRisClose = true; + ATH_MSG_DEBUG( " ...-> dR=" << dr << " : dRisClose=" << dRisClose ); + } + + // dR(by MF) cut + bool dRbyMFisClose = false; + if( m_muCombRequireMufastDR ) { + const xAOD::L2StandAloneMuon* mf1 = combMf1->muSATrack(); + const xAOD::L2StandAloneMuon* mf2 = combMf2->muSATrack(); + if( mf1 == 0 || mf2 == 0 ) { + ATH_MSG_DEBUG( "mF link from combinedMF broken" ); + ATH_MSG_DEBUG( " ...-> mF dR is required but mF link broken. cannot judge overlap -> return with false" ); + return false; + } + else { + // here, we do not check (eta,phi) of mF is not (0,0) + // (i.e. we apply muComb based cut even if muFast rec is failed) + double dRByMF = dR(mf1->etaMS(),mf1->phiMS(),mf2->etaMS(),mf2->phiMS()); + if( dRByMF < dRbyMFThres ) dRbyMFisClose = true; + ATH_MSG_DEBUG( " ...-> dR(by MF)=" << dRByMF << " : dRbyMFisClose=" << dRbyMFisClose ); + } + } + + // mass cut + const double TRACK_MASS = 0; // just assume zero mass + bool massIsClose = false; + double mass = invMass(TRACK_MASS,combMf1->pt()/CLHEP::GeV,combMf1->eta(),combMf1->phi(),TRACK_MASS,combMf2->pt()/CLHEP::GeV,combMf2->eta(),combMf2->phi()); + + mucombMass = mass; + double mass_mon = (mass>=monitor_limit) ? mass : monitor_limit; + mucombMassLog10 = log10(mass_mon); + + if( m_muCombRequireMass ) { + if( mass < massThres ) massIsClose = true; + ATH_MSG_DEBUG( " ...-> mass=" << mass << " : massIsClose=" << massIsClose ); + } + + // total judge + bool overlap = false; + if( ((m_muCombRequireSameSign && sameSign) || (! m_muCombRequireSameSign)) && + ((m_muCombRequireDR && dRisClose) || (! m_muCombRequireDR)) && + ((m_muCombRequireMufastDR && dRbyMFisClose) || (! m_muCombRequireMufastDR)) && + ((m_muCombRequireMass && massIsClose) || (! m_muCombRequireMass)) ) { + overlap = true; + } + + ATH_MSG_DEBUG( " ...=> isOverlap=" << overlap ); + + return overlap; + +} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +StatusCode TrigL2MuonOverlapRemoverTool::chooseBestMuon(std::vector<L2CBMuonOverlapInfo>& toolInput, std::vector<unsigned int> mucombResult) const +{ + size_t numMuon = toolInput.size(); + unsigned int i,j,k; + + auto mucombNrActiveEVs = Monitored::Scalar("NrActiveEVs", -9999.); + auto mucombNrOverlapped = Monitored::Scalar("NrOverlapped", 0); + auto mucombOverlappedEta = Monitored::Scalar("OverlappedEta", -9999.); + auto mucombOverlappedPhi = Monitored::Scalar("OverlappedPhi", -9999.); + auto mucombOverlappedPt = Monitored::Scalar("OverlappedPt", -9999.); + + auto monitorIt = Monitored::Group(m_monTool, mucombNrActiveEVs, mucombNrOverlapped, + mucombOverlappedPt, mucombOverlappedEta, mucombOverlappedPhi); + + if( m_doMucombBasedRemoval ) { + ATH_MSG_DEBUG( "--- choose best among overlaps & disable EVs (muComb based) ---" ); + for(i=0; i<numMuon; i++) { + if( TrigCompositeUtils::passed( m_decisionId.numeric(), toolInput[i].previousDecisionIDs ) ){ + ATH_MSG_DEBUG( "++ i=" << i << ": result=" << mucombResult[i] ); + if( mucombResult[i] != i ) { + ATH_MSG_DEBUG( " overlap to some one. skip." ); + continue; + } + std::vector<unsigned int> others; + for(j=0; j<numMuon; j++) { + if( mucombResult[j] == mucombResult[i] ) others.push_back(j); + } + if( others.size() == 1 ) { + ATH_MSG_DEBUG( " unique object. keep it active." ); + TrigCompositeUtils::addDecisionID( m_decisionId, toolInput[i].decision ); + continue; + } + else {// must choose one best + ATH_MSG_DEBUG( " overlapped objects among: " << others ); + unsigned int best_ev = 0; + float maxPtCombMf = 0; + for(k=0; k<others.size(); k++) { + j=others[k]; + + float ptCombMf = 0.; + const xAOD::L2CombinedMuon* combMf = toolInput[j].overlap; + ptCombMf = fabs(combMf->pt()/CLHEP::GeV); + ATH_MSG_DEBUG(" j="<< j << " , ptCombMf=" << ptCombMf); + if( ptCombMf > maxPtCombMf ) { + maxPtCombMf = ptCombMf; + best_ev = j; + } + } + ATH_MSG_DEBUG( " best is: best_ev/maxPtCombMf=" << best_ev << " / " << maxPtCombMf ); + + for(k=0; k<others.size(); k++) { + j=others[k]; + if( j != best_ev ) { + ATH_MSG_DEBUG( " EventView( j=" << j << " ) is not active" ); + + // monitoring + const xAOD::L2CombinedMuon* CombMf = toolInput[j].overlap; + mucombNrOverlapped++; + mucombOverlappedPt = CombMf->pt()* CombMf->charge() /CLHEP::GeV; + mucombOverlappedEta = CombMf->eta(); + mucombOverlappedPhi = CombMf->phi(); + } + if( j == best_ev ){ + ATH_MSG_DEBUG( " EventView( j=" << j << " ) is best one" ); + TrigCompositeUtils::addDecisionID( m_decisionId, toolInput[j].decision ); + } + } + } + } + else { ATH_MSG_DEBUG( "this muon is not match previousDecisionID:" << m_decisionId << " -> skip." ); } + } + mucombNrActiveEVs = numMuon - mucombNrOverlapped; + } + + return StatusCode::SUCCESS; +} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + diff --git a/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverTool.h b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverTool.h new file mode 100644 index 0000000000000000000000000000000000000000..fdc42fb6fb4082664bbc26eb1e303b68e36aa866 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigL2MuonOverlapRemoverTool.h @@ -0,0 +1,185 @@ +/* +Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGL2MUONOVERLAPREMOVER_TRIGL2MUONOVERLAPREMOVERTOOL_H +#define TRIGL2MUONOVERLAPREMOVER_TRIGL2MUONOVERLAPREMOVERTOOL_H 1 + +#include <string> +#include "AthenaBaseComps/AthAlgTool.h" +#include "DecisionHandling/HLTIdentifier.h" +#include "CLHEP/Units/SystemOfUnits.h" + +#include "xAODTrigMuon/L2CombinedMuonContainer.h" +#include "xAODTrigMuon/versions/L2CombinedMuonContainer_v1.h" +#include "xAODTrigMuon/L2CombinedMuon.h" +#include "TrigT1Interfaces/RecMuonRoI.h" + +#include "DecisionHandling/TrigCompositeUtils.h" +#include "DecisionHandling/Combinators.h" + +#include "AthenaMonitoring/GenericMonitoringTool.h" + +class StoreGateSvc; +class TriggerElement; + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +namespace TrigL2MuonOverlapRemoverToolConsts { +const int errorCode_cannot_get_EL = 1; +const int errorCode_EL_not_valid = 2; +const int errorCode_inconsistent_overlap1 = 3; +const int errorCode_inconsistent_overlap2 = 4; +const int errorCode_cannot_get_RoI = 5; +} + +// -------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- + +class TrigL2MuonOverlapRemoverTool: public ::AthAlgTool { + + public: + + TrigL2MuonOverlapRemoverTool(const std::string& type, + const std::string & name, + const IInterface* parent ); + + virtual ~TrigL2MuonOverlapRemoverTool(); + + struct L2SAMuonOverlapInfo { + L2SAMuonOverlapInfo( TrigCompositeUtils::Decision* d, + const LVL1::RecMuonRoI* r, + const xAOD::L2StandAloneMuon* o, + const TrigCompositeUtils::Decision* previousDecision ) + : decision( d ), + RecRoI( r ), + overlap( o ), + previousDecisionIDs( TrigCompositeUtils::decisionIDs( previousDecision ).begin(), + TrigCompositeUtils::decisionIDs( previousDecision ).end() ) + {} + + + TrigCompositeUtils::Decision* decision; + const LVL1::RecMuonRoI* RecRoI; + const xAOD::L2StandAloneMuon* overlap; + const TrigCompositeUtils::DecisionIDContainer previousDecisionIDs; + }; + + struct L2CBMuonOverlapInfo { + L2CBMuonOverlapInfo( TrigCompositeUtils::Decision* d, + const LVL1::RecMuonRoI* r, + const xAOD::L2CombinedMuon* o, + const TrigCompositeUtils::Decision* previousDecision ) + : decision( d ), + RecRoI( r ), + overlap( o ), + previousDecisionIDs( TrigCompositeUtils::decisionIDs( previousDecision ).begin(), + TrigCompositeUtils::decisionIDs( previousDecision ).end() ) + {} + + + TrigCompositeUtils::Decision* decision; + const LVL1::RecMuonRoI* RecRoI; + const xAOD::L2CombinedMuon* overlap; + const TrigCompositeUtils::DecisionIDContainer previousDecisionIDs; + }; + + + virtual StatusCode initialize() override; + + virtual StatusCode decide(std::vector<TrigL2MuonOverlapRemoverTool::L2SAMuonOverlapInfo>& toolInput) const; + virtual StatusCode decide(std::vector<TrigL2MuonOverlapRemoverTool::L2CBMuonOverlapInfo>& toolInput) const; + + virtual StatusCode checkOverlap(std::vector<L2SAMuonOverlapInfo>& toolInput) const; + virtual StatusCode checkOverlap(std::vector<L2CBMuonOverlapInfo>& toolInput) const; + + bool isOverlap(const xAOD::L2StandAloneMuon *mf1, const xAOD::L2StandAloneMuon *mf2) const; + bool isOverlap(const xAOD::L2CombinedMuon *mf1, const xAOD::L2CombinedMuon *mf2) const; + + double dR(double eta1, double phi1, double eta2, double phi2) const; + + double invMass(double m1, double pt1, double eta1, double phi1, + double m2, double pt2, double eta2, double phi2) const; + + virtual StatusCode chooseBestMuon(std::vector<L2SAMuonOverlapInfo>& toolInput, std::vector<unsigned int> mufastResult) const; + virtual StatusCode chooseBestMuon(std::vector<L2CBMuonOverlapInfo>& toolInput, std::vector<unsigned int> mucombResult) const; + + + private: + + HLT::Identifier m_decisionId; + + + // Mufast based cuts + Gaudi::Property<bool> m_doMufastBasedRemoval { + this, "DoMufastBasedRemoval", false, "execute or not mufast overlap removal"}; + + Gaudi::Property<bool> m_muFastRequireDR{ + this, "MufastRequireDR", true, "require or not DR cut for mufast overlap removal"}; + + Gaudi::Property<bool> m_muFastRequireMass{ + this, "MufastRequireMass", true, "require or not mass cut for mufast overlap removal"}; + + Gaudi::Property<bool> m_muFastRequireSameSign{ + this, "MufastRequireSameSign", true, "require or not charge cut for mufast overlap removal"}; + + Gaudi::Property< float > m_muFastDRThresBB { + this, "MufastDRThresBB", 0.05, "DR threshold for mufast in barel and barel region"}; + + Gaudi::Property< float > m_muFastMassThresBB { + this, "MufastMassThresBB", 0.20, "mass threshold for mufast in barel and barel region"}; + + Gaudi::Property< float > m_muFastDRThresBE { + this, "MufastDRThresBE", 0.05, "DR threshold for mufast in barel and barel region"}; + + Gaudi::Property< float > m_muFastMassThresBE { + this, "MufastMassThresBE", 0.20, "mass threshold for mufast in barel and endcap region"}; + + Gaudi::Property< std::vector<float> > m_muFastEtaBinsEC { + this, "MufastEtaBinsEC", {0, 1.9, 2.1, 9.9}, "eta bins of DR and mass thresholds for mufast in endcap and barel region"}; + + Gaudi::Property< std::vector<float> > m_muFastDRThresEC { + this, "MufastDRThresEC", {0.06, 0.05, 0.05}, "DR threshold for mufast in endcap and barel region"}; + + Gaudi::Property< std::vector<float> > m_muFastMassThresEC { + this, "MufastMassThresEC", {0.20, 0.15, 0.10}, "mass threshold for mufast in endcap and endcap region"}; + + + // Mucomb based cuts + Gaudi::Property<bool> m_doMucombBasedRemoval { + this, "DoMucombBasedRemoval", false, "execute or not mucomb overlap removal"}; + + Gaudi::Property<bool> m_muCombRequireDR{ + this, "MucombRequireDR", true, "require or not DR cut for mucomb overlap removal"}; + + Gaudi::Property<bool> m_muCombRequireMufastDR{ + this, "MucombRequireMufastDR", true, "require or not mufast DR cut for mucomb overlap removal"}; + + Gaudi::Property<bool> m_muCombRequireMass{ + this, "MucombRequireMass", true, "require or not mass cut for mucomb overlap removal"}; + + Gaudi::Property<bool> m_muCombRequireSameSign{ + this, "MucombRequireSameSign", true, "require or not charge cut for mucomb overlap removal"}; + + Gaudi::Property< std::vector<float> > m_muCombEtaBins { + this, "MucombEtaBins", {0, 1.9, 2.1, 9.9}, "eta bins of DR and mass thresholds for mucomb"}; + + Gaudi::Property< std::vector<float> > m_muCombDRThres { + this, "MucombDRThres", {0.06, 0.05, 0.05}, "DR threshold for mucomb"}; + + Gaudi::Property< std::vector<float> > m_muCombMufastDRThres { + this, "MucombMufastDRThres", {0.06, 0.05, 0.05}, "mufast DR threshold for mucomb"}; + + Gaudi::Property< std::vector<float> > m_muCombMassThres { + this, "MucombMassThres", {0.20, 0.15, 0.10}, "mass threshold for mucomb"}; + + + // Other members: + std::vector<size_t> m_bins = {0}; + + ToolHandle< GenericMonitoringTool > m_monTool { this, "MonTool", "", "Monitoring tool" }; + +}; + +#endif diff --git a/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigMufastHypoAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigMufastHypoAlg.cxx index b07743b59a5796d6f81d80e85cfd09f9be0abe1e..a500ac52f21ab5e88b6ae310f26e40ba7ee8cfee 100755 --- a/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigMufastHypoAlg.cxx +++ b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigMufastHypoAlg.cxx @@ -101,6 +101,7 @@ StatusCode TrigMufastHypoAlg::execute( const EventContext& context ) const toolInput.emplace_back( newd, roi, muon, previousDecision ); newd->setObjectLink( featureString(), muonEL ); + newd->setObjectLink( viewString(), viewEL); TrigCompositeUtils::linkToPrevious( newd, previousDecision, context ); ATH_MSG_DEBUG("REGTEST: " << m_muFastKey.key() << " pT = " << (*muonEL)->pt() << " GeV"); diff --git a/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigmuCombHypoAlg.cxx b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigmuCombHypoAlg.cxx index a755646f43429b988c212665f083370b1a81229f..a1e8cefec5f5f3f33394a2149818f246e2a4ac74 100644 --- a/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigmuCombHypoAlg.cxx +++ b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/TrigmuCombHypoAlg.cxx @@ -104,6 +104,7 @@ StatusCode TrigmuCombHypoAlg::execute(const EventContext& context) const // set objectLink newd->setObjectLink( featureString(), muCombEL ); + newd->setObjectLink( viewString(), viewEL); TrigCompositeUtils::linkToPrevious( newd, previousDecision, context); // DEBUG diff --git a/Trigger/TrigHypothesis/TrigMuonHypoMT/src/components/TrigMuonHypo_entries.cxx b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/components/TrigMuonHypo_entries.cxx index 1a5904cabfdc778b29173bdbf41e5b0485ff687e..93eb1878570a505805ec74ffb98dcdd2c5ccb254 100644 --- a/Trigger/TrigHypothesis/TrigMuonHypoMT/src/components/TrigMuonHypo_entries.cxx +++ b/Trigger/TrigHypothesis/TrigMuonHypoMT/src/components/TrigMuonHypo_entries.cxx @@ -9,6 +9,10 @@ #include "src/TrigMuonEFMSonlyHypoTool.h" #include "src/TrigMuonEFCombinerHypoAlg.h" #include "src/TrigMuonEFCombinerHypoTool.h" +#include "src/TrigL2MuonOverlapRemoverMufastAlg.h" +#include "src/TrigL2MuonOverlapRemoverMucombAlg.h" +#include "src/TrigL2MuonOverlapRemoverTool.h" + DECLARE_COMPONENT( TrigMufastHypoAlg ) DECLARE_COMPONENT( TrigMufastHypoTool ) @@ -22,3 +26,6 @@ DECLARE_COMPONENT( TrigMuonEFMSonlyHypoAlg ) DECLARE_COMPONENT( TrigMuonEFMSonlyHypoTool ) DECLARE_COMPONENT( TrigMuonEFCombinerHypoAlg ) DECLARE_COMPONENT( TrigMuonEFCombinerHypoTool ) +DECLARE_COMPONENT( TrigL2MuonOverlapRemoverMufastAlg ) +DECLARE_COMPONENT( TrigL2MuonOverlapRemoverMucombAlg ) +DECLARE_COMPONENT( TrigL2MuonOverlapRemoverTool ) diff --git a/Trigger/TrigValidation/TrigAnalysisTest/share/q221_RDOtoRDOTrig_mt1_build.ref b/Trigger/TrigValidation/TrigAnalysisTest/share/q221_RDOtoRDOTrig_mt1_build.ref index 53e9d278542075872bee3c03ebd646564cb84ea3..6580bd69217ea85b4e905d7f16fc2b002bb05f59 100644 --- a/Trigger/TrigValidation/TrigAnalysisTest/share/q221_RDOtoRDOTrig_mt1_build.ref +++ b/Trigger/TrigValidation/TrigAnalysisTest/share/q221_RDOtoRDOTrig_mt1_build.ref @@ -1,11 +1,11 @@ TrigSignatureMoniMT INFO HLT_2j330_a10t_lcw_jes_30smcINF_L1J2019 19 0 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_2j330_a10t_lcw_jes_30smcINF_L1J20 decisions 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_2mu14_L12MU10 3 3 3 1 1 1 0 1 -TrigSignatureMoniMT INFO HLT_2mu14_L12MU10 decisions 12 4 4 4 0 +TrigSignatureMoniMT INFO HLT_2mu14_L12MU10 decisions 18 6 4 4 0 TrigSignatureMoniMT INFO HLT_2mu6Comb_L12MU6 4 4 4 3 0 0 0 3 -TrigSignatureMoniMT INFO HLT_2mu6Comb_L12MU6 decisions 16 12 0 0 0 +TrigSignatureMoniMT INFO HLT_2mu6Comb_L12MU6 decisions 24 18 0 0 0 TrigSignatureMoniMT INFO HLT_2mu6_L12MU6 4 4 4 3 3 3 0 3 -TrigSignatureMoniMT INFO HLT_2mu6_L12MU6 decisions 16 12 18 18 0 +TrigSignatureMoniMT INFO HLT_2mu6_L12MU6 decisions 24 18 18 18 0 TrigSignatureMoniMT INFO HLT_3j200_L1J100 4 4 0 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_3j200_L1J100 decisions 0 0 0 0 0 TrigSignatureMoniMT INFO HLT_3j200_L1J20 19 19 0 0 0 0 0 0 @@ -85,7 +85,7 @@ TrigSignatureMoniMT INFO HLT_mu6_ivarmedium_L1MU6 TrigSignatureMoniMT INFO HLT_mu6_msonly_L1MU6 10 10 10 0 10 0 0 10 TrigSignatureMoniMT INFO HLT_mu6_msonly_L1MU6 decisions 14 0 17 0 0 TrigSignatureMoniMT INFO HLT_mu6_mu4_L12MU4 4 4 4 4 4 4 0 3 -TrigSignatureMoniMT INFO HLT_mu6_mu4_L12MU4 decisions 24 22 32 29 0 +TrigSignatureMoniMT INFO HLT_mu6_mu4_L12MU4 decisions 40 37 32 29 0 TrigSignatureMoniMT INFO HLT_mu6fast_L1MU6 10 10 10 0 0 0 0 10 TrigSignatureMoniMT INFO HLT_mu6fast_L1MU6 decisions 14 0 0 0 0 TrigSignatureMoniMT INFO HLT_mu6noL1_L1MU6 10 10 10 10 0 0 0 10 diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref b/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref index 8596980a1f8dfb22e69855f7d5cf8ea60c4877a5..4cedc123190de612f895efad6240aa7e25469bb0 100644 --- a/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref +++ b/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu_build.ref @@ -447,7 +447,7 @@ TrigSignatureMoniMT INFO HLT_mu6_ivarmedium_L1MU6 TrigSignatureMoniMT INFO HLT_mu6_msonly_L1MU6 20 20 3 0 2 0 0 2 TrigSignatureMoniMT INFO HLT_mu6_msonly_L1MU6 decisions 3 0 2 0 0 TrigSignatureMoniMT INFO HLT_mu6_mu4_L12MU4 20 20 4 0 0 0 0 0 -TrigSignatureMoniMT INFO HLT_mu6_mu4_L12MU4 decisions 7 0 0 0 0 +TrigSignatureMoniMT INFO HLT_mu6_mu4_L12MU4 decisions 14 0 0 0 0 TrigSignatureMoniMT INFO HLT_mu6fast_L1MU6 20 20 3 0 0 0 0 3 TrigSignatureMoniMT INFO HLT_mu6fast_L1MU6 decisions 3 0 0 0 0 TrigSignatureMoniMT INFO HLT_mu6noL1_L1MU6 20 20 4 1 0 0 0 1 diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Bphysics/BphysicsDef.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Bphysics/BphysicsDef.py index f4df6f1abe54a6ee8de97bdfc121235990f81326..7db029d599a7842bf7030f0e2fb914209b717331 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Bphysics/BphysicsDef.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Bphysics/BphysicsDef.py @@ -35,7 +35,7 @@ class BphysicsChainConfiguration(MuonChainConfiguration): def __init__(self, chainDict): ChainConfigurationBase.__init__(self,chainDict) - + # ---------------------- # Assemble the chain depending on information from chainName # ---------------------- diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTCFConfig.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTCFConfig.py index fdc6bce86b681d43c22bb335cac7db70919a7290..d40b50a27740e7f303168c02ecd0b69e47f9f10b 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTCFConfig.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTCFConfig.py @@ -102,7 +102,11 @@ def createCFTree(CFseq): else: already_connected.append(name) stepReco += ath_sequence - seqAndView += menuseq.hypo.Alg + if type(menuseq.hypo) is list: + for hp in menuseq.hypo: + seqAndView += hp.Alg + else: + seqAndView += menuseq.hypo.Alg if CFseq.step.isCombo: seqAndView += CFseq.step.combo.Alg @@ -226,7 +230,10 @@ def matrixDisplay( allCFSeq ): longestName = longestName + 1 def __getHyposOfStep( s ): if len(s.step.sequences): - return s.step.sequences[0].hypo.tools + if type(s.step.sequences[0].hypo) is list: + return s.step.sequences[0].hypo[0].tools + else: + return s.step.sequences[0].hypo.tools return [] @@ -372,11 +379,20 @@ def createDataFlow(chains, allDicts): new_sequence=copy.deepcopy(sequence) new_sequence.resetConnections() new_sequence.name = "%s_%d"%(sequence.name, count_fil) - oldhypo=sequence.hypo.Alg - newHypoAlgName = "%s_%d"%(oldhypo.name(),count_fil) - new_hypoAlg=oldhypo.clone(newHypoAlgName) - new_sequence.replaceHypoForDuplication(new_hypoAlg) - new_sequences.append(new_sequence) + if type(sequence.hypo) is list: + new_hypoAlg = [] + for hp in sequence.hypo: + oldhypo=hp.Alg + newHypoAlgName = "%s_%d"%(oldhypo.name(),count_fil) + new_hypoAlg.append( oldhypo.clone(newHypoAlgName) ) + new_sequence.replaceHypoForDuplication(new_hypoAlg) + new_sequences.append(new_sequence) + else: + oldhypo=sequence.hypo.Alg + newHypoAlgName = "%s_%d"%(oldhypo.name(),count_fil) + new_hypoAlg=oldhypo.clone(newHypoAlgName) + new_sequence.replaceHypoForDuplication(new_hypoAlg) + new_sequences.append(new_sequence) new_chain_step_name="%s_%d"%(chain_step.name, count_fil) # making new ChainStep diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTCFDot.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTCFDot.py index fbd6c0106ec85c31333ffe29fd92111a5bc095cf..65ad231353f393c84adad62e8e812337243cb70c 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTCFDot.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTCFDot.py @@ -124,10 +124,18 @@ def all_DataFlow_to_dot(name, step_list): file.write(" %s[fillcolor=%s]\n"%(menuseq.maker.Alg.name(), algColor(menuseq.maker.Alg))) file.write(" %s[fillcolor=%s]\n"%(menuseq.sequence.Alg.name(), algColor(menuseq.sequence.Alg))) menuseq.reuse=True - cfseq_algs.append(menuseq.hypo) + if type(menuseq.hypo) is list: + for hp in menuseq.hypo: + cfseq_algs.append(hp) + file.write(" %s[color=%s]\n"%(hp.Alg.name(), algColor(hp.Alg))) + else: + cfseq_algs.append(menuseq.hypo) + file.write(" %s[color=%s]\n"%(menuseq.hypo.Alg.name(), algColor(menuseq.hypo.Alg))) if not cfseq.step.isCombo: - last_step_hypoNodes.append(menuseq.hypo) - file.write(" %s[color=%s]\n"%(menuseq.hypo.Alg.name(), algColor(menuseq.hypo.Alg))) + if type(menuseq.hypo) is list: + last_step_hypoNodes.append(menuseq.hypo[-1]) + else: + last_step_hypoNodes.append(menuseq.hypo) #combo if cfseq.step.isCombo: @@ -185,8 +193,13 @@ def stepCF_DataFlow_to_dot(name, cfseq_list): file.write(" %s[fillcolor=%s]\n"%(menuseq.maker.Alg.name(), algColor(menuseq.maker.Alg))) file.write(" %s[fillcolor=%s]\n"%(menuseq.sequence.Alg.name(), algColor(menuseq.sequence.Alg))) menuseq.reuse=True - cfseq_algs.append(menuseq.hypo) - file.write(" %s[color=%s]\n"%(menuseq.hypo.Alg.name(), algColor(menuseq.hypo.Alg))) + if type(menuseq.hypo) is list: + for hp in menuseq.hypo: + cfseq_algs.append(hp) + file.write(" %s[color=%s]\n"%(hp.Alg.name(), algColor(hp.Alg))) + else: + cfseq_algs.append(menuseq.hypo) + file.write(" %s[color=%s]\n"%(menuseq.hypo.Alg.name(), algColor(menuseq.hypo.Alg))) #combo diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py index 986c07ed6973cf291039975b9071b03422adb180..9dd9775a39ccc1f9764be84739fb2198ecf0cc0e 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponents.py @@ -183,7 +183,6 @@ class HypoAlgNode(AlgNode): ' '.join(map(str, self.tools))) - class SequenceFilterNode(AlgNode): """Node for any kind of sequence filter""" def __init__(self, Alg, inputProp, outputProp): @@ -274,26 +273,48 @@ class MenuSequence(object): """ Class to group reco sequences with the Hypo""" def __init__(self, Sequence, Maker, Hypo, HypoToolGen, CA=None ): assert Maker.name().startswith("IM"), "The input maker {} name needs to start with letter: IM".format(Maker.name()) - self.name = CFNaming.menuSequenceName(Hypo.name()) self.sequence = Node( Alg=Sequence) self._maker = InputMakerNode( Alg = Maker ) - self.hypoToolConf = HypoToolConf( HypoToolGen ) - self._hypo = HypoAlgNode( Alg = Hypo ) self.inputs=[] self.outputs=[] self.seed='' self.reuse = False # flag to draw dot diagrmas self.ca = CA + if type(Hypo) is list: + self.name=[] + self.hypoToolConf=[] + self._hypo=[] + for hp, hptool in zip(Hypo, HypoToolGen): + self.name.append( CFNaming.menuSequenceName(hp.name()) ) + self.hypoToolConf.append( HypoToolConf( hptool ) ) + self._hypo.append( HypoAlgNode( Alg = hp ) ) + else: + self.name = CFNaming.menuSequenceName(Hypo.name()) + self.hypoToolConf = HypoToolConf( HypoToolGen ) + self._hypo = HypoAlgNode( Alg = Hypo ) + def replaceHypoForCombo(self, HypoAlg): - log.debug("set new Hypo %s for combo sequence %s ", HypoAlg.name(), self.name) - self._hypo = HypoAlgNode( Alg=HypoAlg ) + if type(HypoAlg) is list and type(self.name) is list: + self._hypo=[] + for hp, Name in zip(HypoAlg, self.name): + log.debug("set new Hypo %s for combo sequence %s ", hp.name(), Name) + self._hypo.append( HypoAlgNode( Alg=hp ) ) + else: + log.debug("set new Hypo %s for combo sequence %s ", HypoAlg.name(), self.name) + self._hypo = HypoAlgNode( Alg=HypoAlg ) def replaceHypoForDuplication(self, HypoAlg): - log.debug("set new Hypo %s for duplicated sequence %s, resetting decisions ", HypoAlg.name(), self.name) - self._hypo = HypoAlgNode( Alg=HypoAlg ) + if type(HypoAlg) is list: + self._hypo = [] + for hp, Name in zip(HypoAlg, self.name): + log.debug("set new Hypo %s for duplicated sequence %s, resetting decisions ", hp.name(), Name) + self._hypo.append( HypoAlgNode( Alg=hp ) ) + else: + log.debug("set new Hypo %s for duplicated sequence %s, resetting decisions ", HypoAlg.name(), self.name) + self._hypo = HypoAlgNode( Alg=HypoAlg ) # do we need this? # self._hypo.resetInput() # self._hypo.resetOutput() @@ -327,27 +348,58 @@ class MenuSequence(object): self.maker.addOutput(input_maker_output) #### Add input/output Decision to Hypo - self.hypo.setPreviousDecision( input_maker_output) - hypo_output = CFNaming.hypoAlgOutName(self.hypo.Alg.name(), input_maker_output) - if len(self.hypo.getOutputList()): - log.error("Hypo " + self.hypo.name() +" has already an output configured: you may want to duplicate the Hypo!") - self.hypo.addOutput(hypo_output) + if type(self._hypo) is list: + hypo_input_total=[] + hypo_output_total=[] + hypo_input = input_maker_output + for hp in self._hypo: + hypo_input_total.append(hypo_input) + hp.setPreviousDecision(hypo_input) + hypo_output = CFNaming.hypoAlgOutName(hp.Alg.name(), hypo_input) + if len(hp.getOutputList()): + log.error("Hypo " + hp.name() +" has already an output configured: you may want to duplicate the Hypo!") + hp.addOutput(hypo_output) + hypo_output_total.append(hypo_output) + hypo_input = hypo_output + else: + self.hypo.setPreviousDecision( input_maker_output) + hypo_output = CFNaming.hypoAlgOutName(self.hypo.Alg.name(), input_maker_output) + if len(self.hypo.getOutputList()): + log.error("Hypo " + self.hypo.name() +" has already an output configured: you may want to duplicate the Hypo!") + self.hypo.addOutput(hypo_output) # needed for drawing self.inputs.append(outfilter) self.outputs.append(hypo_output) + log.debug("MenuSequence.connectToFilter: connecting InputMaker and HypoAlg and OverlapRemoverAlg, adding: \n\ + InputMaker::%s.output=%s",\ + self.maker.Alg.name(), input_maker_output) + if type(self._hypo) is list: + for hp, hp_in, hp_out in zip( self._hypo, hypo_input_total, hypo_output_total): + log.debug("HypoAlg::%s.previousDecision=%s, \n\ + HypoAlg::%s.output=%s",\ + hp.Alg.name(), hp_in, hp.Alg.name(), hp_out) + else: + log.debug("HypoAlg::%s.previousDecision=%s, \n\ + HypoAlg::%s.output=%s",\ + self.hypo.Alg.name(), input_maker_output, self.hypo.Alg.name(), hypo_output) - log.debug("MenuSequence.connectToFilter: connecting InputMaker and HypoAlg, adding: \n\ - InputMaker::%s.output=%s, \n\ - HypoAlg::%s.previousDecision=%s, \n\ - HypoAlg::%s.output=%s",\ - self.maker.Alg.name(), input_maker_output, self.hypo.Alg.name(), input_maker_output, self.hypo.Alg.name(), hypo_output ) def __repr__(self): - hypotool = self.hypoToolConf.name - return "MenuSequence::%s \n Hypo::%s \n Maker::%s \n Sequence::%s \n HypoTool::%s\n"\ - %(self.name, self.hypo.Alg.name(), self.maker.Alg.name(), self.sequence.Alg.name(), hypotool) + if type(self._hypo) is list: + hyponame=[] + hypotool=[] + for hp, hptool in zip(self._hypo, self.hypoToolConf): + hyponame.append( hp.Alg.name() ) + hypotool.append( hptool.name ) + return "MenuSequence::%s \n Hypo::%s \n Maker::%s \n Sequence::%s \n HypoTool::%s"\ + %(self.name, hyponame, self.maker.Alg.name(), self.sequence.Alg.name(), hypotool) + else: + hyponame = self._hypo.Alg.name() + hypotool = self.hypoToolConf.name + return "MenuSequence::%s \n Hypo::%s \n Maker::%s \n Sequence::%s \n HypoTool::%s\n"\ + %(self.name, hyponame, self.maker.Alg.name(), self.sequence.Alg.name(), hypotool) @@ -427,8 +479,13 @@ class Chain(object): onePartChainDict = copy.deepcopy( chainDict ) onePartChainDict['chainParts'] = [ chainDictPart ] - seq.hypoToolConf.setConf( onePartChainDict ) - seq.hypo.addHypoTool(seq.hypoToolConf) #this creates the HypoTools + if type(seq.hypoToolConf) is list: + for hp, hptoolConf in zip( seq.hypo, seq.hypoToolConf ): + hptoolConf.setConf( onePartChainDict ) + hp.addHypoTool(hptoolConf) #this creates tge HypoTools + else: + seq.hypoToolConf.setConf( onePartChainDict ) + seq.hypo.addHypoTool(seq.hypoToolConf) #this creates the HypoTools def __repr__(self): @@ -496,7 +553,10 @@ class CFSequence(object): seq.outputs=[] for seq in self.step.sequences: - combo_input=seq.hypo.getOutputList()[0] + if type(seq.hypo) is list: + combo_input=seq.hypo[1].getOutputList()[0] + else: + combo_input=seq.hypo.getOutputList()[0] self.step.combo.addInput(combo_input) log.debug("Adding inputs %s to combo %s", combo_input, self.step.combo.Alg.name()) # inputs are the output decisions of the hypos of the sequences @@ -535,17 +595,35 @@ class ChainStep(object): self.combo = ComboMaker(CFNaming.comboHypoName(self.name)) duplicatedHypos = [] for sequence in Sequences: - oldhypo=sequence.hypo.Alg - duplicatedHypos.append(oldhypo.name()) - ncopy=duplicatedHypos.count(oldhypo.name()) + if type(sequence.hypo) is list: + new_hypoAlg = [] + NewHypoAlgName = [] + for hp in sequence.hypo: + oldhypo=hp.Alg + duplicatedHypos.append(oldhypo.name()) + ncopy=duplicatedHypos.count(oldhypo.name()) + + new_sequence=copy.deepcopy(sequence) + new_sequence.name = CFNaming.comboSequenceCopyName(sequence.name,ncopy, self.name) + + newHypoAlgName = CFNaming.comboHypoCopyName(oldhypo.name(),ncopy, self.name) + new_hypoAlg.append( oldhypo.clone(newHypoAlgName) ) # need to reset decisions? + NewHypoAlgName.append( newHypoAlgName ) + new_sequence.replaceHypoForCombo(new_hypoAlg) + self.sequences.append(new_sequence) + + else: + oldhypo=sequence.hypo.Alg + duplicatedHypos.append(oldhypo.name()) + ncopy=duplicatedHypos.count(oldhypo.name()) - new_sequence=copy.deepcopy(sequence) - new_sequence.name = CFNaming.comboSequenceCopyName(sequence.name,ncopy, self.name) + new_sequence=copy.deepcopy(sequence) + new_sequence.name = CFNaming.comboSequenceCopyName(sequence.name,ncopy, self.name) - newHypoAlgName = CFNaming.comboHypoCopyName(oldhypo.name(),ncopy, self.name) - new_hypoAlg=oldhypo.clone(newHypoAlgName) # need to reset decisions? - new_sequence.replaceHypoForCombo(new_hypoAlg) - self.sequences.append(new_sequence) + newHypoAlgName = CFNaming.comboHypoCopyName(oldhypo.name(),ncopy, self.name) + new_hypoAlg=oldhypo.clone(newHypoAlgName) # need to reset decisions? + new_sequence.replaceHypoForCombo(new_hypoAlg) + self.sequences.append(new_sequence) def __repr__(self): return "--- ChainStep %s ---\n + isCombo: %d, multiplicity= %d \n + %s \n "%(self.name, self.isCombo,self.multiplicity, ' '.join(map(str, self.sequences) )) diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponentsNaming.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponentsNaming.py index 2ef0dd1e2aaaec9d83a91980bdb2292d6606cd24..97ef86de8dad585314d02e811010704b6759770a 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponentsNaming.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/MenuComponentsNaming.py @@ -45,8 +45,14 @@ class CFNaming(object): return "ComboHypo_" + HypoName @staticmethod - def comboSequenceCopyName(SequenceName, ncopy, StepName): - return "%s%d_for_%s"%(SequenceName, ncopy, StepName) + def comboSequenceCopyName(SequenceName, ncopy, StepName): + if type(SequenceName) is list: + sequence = [] + for sq in SequenceName: + sequence.append("%s%d_for_%s"%(sq, ncopy, StepName)) + return sequence + else: + return "%s%d_for_%s"%(SequenceName, ncopy, StepName) @staticmethod def comboHypoCopyName(HypoName,ncopy,StepName): diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonDef.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonDef.py index 45bbec3c12bab3054b28cfc780c0bea5adedb36b..7682d7e0c02a78bddb0688ba3254381087773e2e 100755 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonDef.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonDef.py @@ -11,7 +11,7 @@ log = logging.getLogger("TriggerMenuMT.HLTMenuConfig.Muon.MuonDef") from TriggerMenuMT.HLTMenuConfig.Menu.ChainConfigurationBase import ChainConfigurationBase -from TriggerMenuMT.HLTMenuConfig.Muon.MuonSequenceSetup import muFastSequence, muCombSequence, muEFMSSequence, muEFSASequence, muIsoSequence, muEFCBSequence, muEFSAFSSequence, muEFCBFSSequence, muEFIsoSequence +from TriggerMenuMT.HLTMenuConfig.Muon.MuonSequenceSetup import muFastSequence, muFastOvlpRmSequence, muCombSequence, muCombOvlpRmSequence, muEFMSSequence, muEFSASequence, muIsoSequence, muEFCBSequence, muEFSAFSSequence, muEFCBFSSequence, muEFIsoSequence @@ -21,9 +21,15 @@ from TriggerMenuMT.HLTMenuConfig.Muon.MuonSequenceSetup import muFastSequence, m def muFastSequenceCfg(flags): return muFastSequence() +def muFastOvlpRmSequenceCfg(flags): + return muFastOvlpRmSequence() + def muCombSequenceCfg(flags): return muCombSequence() +def muCombOvlpRmSequenceCfg(flags): + return muCombOvlpRmSequence() + def muEFMSSequenceCfg(flags): return muEFMSSequence() @@ -54,6 +60,7 @@ class MuonChainConfiguration(ChainConfigurationBase): def __init__(self, chainDict): ChainConfigurationBase.__init__(self,chainDict) + # ---------------------- # Assemble the chain depending on information from chainName # ---------------------- @@ -101,11 +108,37 @@ class MuonChainConfiguration(ChainConfigurationBase): # -------------------- def getmuFast(self): - return self.getStep(1,"mufast", [muFastSequenceCfg] ) + doOvlpRm = False + if "bTau" in self.chainName or "bJpsi" in self.chainName or "bUpsi" in self.chainName or "bDimu" in self.chainName or "bBmu" in self.chainName: + doOvlpRm = False + elif self.mult>1: + doOvlpRm = True + elif len( self.dict['signatures'] )>1 and not self.chainPart['extra']: + doOvlpRm = True + else: + doOvlpRm = False + + if doOvlpRm: + return self.getStep(1,"mufast", [muFastOvlpRmSequenceCfg] ) + else: + return self.getStep(1,"mufast", [muFastSequenceCfg] ) # -------------------- def getmuComb(self): - return self.getStep(2, 'muComb', [muCombSequenceCfg] ) + doOvlpRm = False + if "bTau" in self.chainName or "bJpsi" in self.chainName or "bUpsi" in self.chainName or "bDimu" in self.chainName or "bBmu" in self.chainName: + doOvlpRm = False + elif self.mult>1: + doOvlpRm = True + elif len( self.dict['signatures'] )>1 and not self.chainPart['extra']: + doOvlpRm = True + else: + doOvlpRm = False + + if doOvlpRm: + return self.getStep(2, 'muComb', [muCombOvlpRmSequenceCfg] ) + else: + return self.getStep(2, 'muComb', [muCombSequenceCfg] ) # -------------------- def getmuEFSA(self): diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSequenceSetup.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSequenceSetup.py index 9e68ed9a7b5a0af9718451f7c73621fd913c8c8f..aa1054c5711a70508cd1ba11e65b133d09b3820f 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSequenceSetup.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Muon/MuonSequenceSetup.py @@ -57,11 +57,35 @@ def muFastSequence(): trigMufastHypo.MuonL2SAInfoFromMuFastAlg = sequenceOut from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigMufastHypoToolFromDict - + return MenuSequence( Sequence = l2muFastSequence, Maker = l2MuViewsMaker, Hypo = trigMufastHypo, - HypoToolGen = TrigMufastHypoToolFromDict ) + HypoToolGen = TrigMufastHypoToolFromDict ) + + +def muFastOvlpRmSequence(): + + (l2muFastSequence, l2MuViewsMaker, sequenceOut) = RecoFragmentsPool.retrieve(muFastAlgSequence, ConfigFlags) + + ### set up MuFastHypo ### + from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigMufastHypoAlg + trigMufastHypo = TrigMufastHypoAlg("TrigL2MufastHypoAlg") + trigMufastHypo.MuonL2SAInfoFromMuFastAlg = sequenceOut + + from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigMufastHypoToolFromDict + + ### set up MuSAOverlapRemoval ### + from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigL2MuonOverlapRemoverMufastAlg + trigL2MuonOverlapRemover = TrigL2MuonOverlapRemoverMufastAlg("TrigL2MuonOverlapRemoverMufastAlg") + trigL2MuonOverlapRemover.L2MuonOverlapInfoFromMuFastAlg = sequenceOut + + from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigL2MuonOverlapRemoverMufastToolFromDict + + return MenuSequence( Sequence = l2muFastSequence, + Maker = l2MuViewsMaker, + Hypo = [trigMufastHypo, trigL2MuonOverlapRemover], + HypoToolGen = [TrigMufastHypoToolFromDict, TrigL2MuonOverlapRemoverMufastToolFromDict] ) #-----------------------------------------------------# @@ -112,7 +136,7 @@ def muCombSequence(): trigmuCombHypo.MuonL2CBInfoFromMuCombAlg = sequenceOut from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigmuCombHypoToolFromDict - + return MenuSequence( Sequence = l2muCombSequence, Maker = l2muCombViewsMaker, Hypo = trigmuCombHypo, @@ -120,6 +144,31 @@ def muCombSequence(): +def muCombOvlpRmSequence(): + + (l2muCombSequence, l2muCombViewsMaker, sequenceOut) = RecoFragmentsPool.retrieve(muCombAlgSequence, ConfigFlags) + + ### set up muCombHypo algorithm ### + from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigmuCombHypoAlg + trigmuCombHypo = TrigmuCombHypoAlg("TrigL2MuCBHypoAlg") + trigmuCombHypo.MuonL2CBInfoFromMuCombAlg = sequenceOut + + from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigmuCombHypoToolFromDict + + ### set up MuSAOverlapRemoval ### + from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigL2MuonOverlapRemoverMucombAlg + trigL2MuonOverlapRemover = TrigL2MuonOverlapRemoverMucombAlg("TrigL2MuonOverlapRemoverMucombAlg") + trigL2MuonOverlapRemover.L2MuonOverlapInfoFromMuCombAlg = sequenceOut + + from TrigMuonHypoMT.TrigMuonHypoMTConfig import TrigL2MuonOverlapRemoverMucombToolFromDict + + return MenuSequence( Sequence = l2muCombSequence, + Maker = l2muCombViewsMaker, + Hypo = [trigmuCombHypo, trigL2MuonOverlapRemover], + HypoToolGen = [TrigmuCombHypoToolFromDict, TrigL2MuonOverlapRemoverMucombToolFromDict] ) + + + ###################### ### EFSA step ### ######################