Commit cf976e31 authored by Heather Russell's avatar Heather Russell Committed by Adam Edward Barton
Browse files

ATR-22749 - B-phys di-electron chain

parent 604091cf
......@@ -11,7 +11,7 @@ atlas_add_component( TrigBphysHypo
src/*.cxx
src/components/*.cxx
INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
LINK_LIBRARIES ${ROOT_LIBRARIES} AthContainers AthViews AthenaBaseComps AthenaMonitoringKernelLib BeamSpotConditionsData DecisionHandlingLib GeoPrimitives InDetConversionFinderToolsLib ITrackToVertex StoreGateLib TrigCompositeUtilsLib TrkVKalVrtFitterLib xAODMuon xAODTracking xAODTrigBphys xAODTrigger xAODTrigMuon )
LINK_LIBRARIES ${ROOT_LIBRARIES} AthContainers AthViews AthenaBaseComps AthenaMonitoringKernelLib BeamSpotConditionsData DecisionHandlingLib GeoPrimitives InDetConversionFinderToolsLib ITrackToVertex StoreGateLib TrigCompositeUtilsLib TrkVKalVrtFitterLib xAODMuon xAODEgamma xAODTracking xAODTrigBphys xAODTrigger xAODTrigMuon )
# Install files from the package:
atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} --extend-extensions=ATL900,ATL901 )
......@@ -18,6 +18,7 @@ trigMultiTrkComboHypoToolDict = {
'bBmumu' : { 'massRange' : (4000., 8500.), 'chi2' : 20. },
'bPhi' : { 'massRange' : ( 940., 1100.), 'chi2' : 10. },
'bTau' : { 'massRange' : ( 0., 2700.), 'chi2' : 50. },
'bBeeM6000' : { 'massRange' : ( 100., 6000.), 'chi2' : 20. },
}
......@@ -65,6 +66,31 @@ def StreamerDimuEFComboHypoCfg(name):
hypo.massRanges = [ (100., 6000.) ]
return hypo
def StreamerDiElecFastComboHypoCfg(name):
log.debug('StreamerDiElecFastComboHypoCfg.name = %s ', name)
config = TrigMultiTrkComboHypoConfig()
hypo = config.ConfigurationComboHypo(
isStreamer = True,
trigSequenceName = 'DiElecFast',
trigLevel = 'L2',
doElectrons = True,
trackCollection='HLT_IDTrack_Electron_FTF')
return hypo
def DiElecPrecisionComboHypoCfg(name):
log.debug('DiElecPrecisionComboHypoCfg.name = %s ', name)
config = TrigMultiTrkComboHypoConfig()
hypo = config.ConfigurationComboHypo(
isStreamer = False,
trigSequenceName = 'DiElecPrecision',
trigLevel = 'EF',
doElectrons = True,
outputTrigBphysCollection = 'HLT_DiElecPrecision')
return hypo
def TrigMultiTrkComboHypoToolFromDict(chainDict):
config = TrigMultiTrkComboHypoConfig()
tool = config.ConfigurationComboHypoTool(chainDict)
......@@ -72,7 +98,7 @@ def TrigMultiTrkComboHypoToolFromDict(chainDict):
class TrigMultiTrkComboHypoConfig(object):
def ConfigurationComboHypo(self, isStreamer='False', trigSequenceName='Dimu', trigLevel='L2', trackCollection='', outputTrigBphysCollection='TrigBphysContainer'):
def ConfigurationComboHypo(self, isStreamer='False', trigSequenceName='Dimu', trigLevel='L2', trackCollection='', outputTrigBphysCollection='TrigBphysContainer', doElectrons = False):
trigLevelDict = {'L2':0, 'L2IO':1, 'EF':2}
......@@ -98,6 +124,24 @@ class TrigMultiTrkComboHypoConfig(object):
MaxPhi = [ 10000., 10000., 10000.],
MaxChi2OfVtxEstimation = 2000.)
if doElectrons:
trackMasses = [0.511,0.511]
tool = CompFactory.TrigMultiTrkComboHypo(
name = baseName+'ComboHypo',
isStreamer = isStreamer,
doElectrons = True,
trigLevel = trigLevel,
nTracks = 2,
trackMasses = trackMasses,
massRanges = [ (100., 20000.) ],
TrackCollectionKey = trackCollection,
TrigBphysCollectionKey = outputTrigBphysCollection,
VertexFitter = VertexFitter,
VertexPointEstimator = VertexPointEstimator,
CheckMultiplicityMap = False,
MonTool = TrigMultiTrkComboHypoMonitoring('TrigMultiTrkComboHypoMonitoring_'+baseName))
tool = CompFactory.TrigMultiTrkComboHypo(
name = baseName+'ComboHypo',
isStreamer = isStreamer,
......
......@@ -18,6 +18,7 @@
#include "TrigMultiTrkComboHypo.h"
#include "xAODMuon/Muon.h"
#include "xAODEgamma/Electron.h"
#include "xAODTracking/TrackParticle.h"
#include "xAODTracking/TrackParticleContainer.h"
#include "xAODTrigger/TrigComposite.h"
......@@ -99,6 +100,7 @@ StatusCode TrigMultiTrkComboHypo::initialize() {
ATH_MSG_ERROR( "trigLevel should be L2, L2IO or EF, but " << m_trigLevel << " provided" );
return StatusCode::FAILURE;
}
ATH_CHECK( m_trigBphysContainerKey.initialize(!m_isStreamer.value()) );
ATH_CHECK( m_beamSpotKey.initialize(!m_isStreamer.value()) ); // need beamSpot only to create xAOD::TrigBphys object
......@@ -173,28 +175,43 @@ StatusCode TrigMultiTrkComboHypo::execute(const EventContext& context) const {
// create the mutable output DecisionContainer and register it to StoreGate
SG::WriteHandle<DecisionContainer> outputDecisionsHandle = TrigCompositeUtils::createAndStore(decisionsOutput().at(0), context);
auto state = makeState(&context, previousDecisionsHandle.cptr(), outputDecisionsHandle.ptr(), nullptr);
std::unique_ptr<TrigMultiTrkStateCand<xAOD::MuonContainer>> muonstate;
std::unique_ptr<TrigMultiTrkStateCand<xAOD::ElectronContainer>> electronstate;
TrigMultiTrkState* commonstate=nullptr;
if(m_doElectrons == true){
electronstate = std::make_unique<TrigMultiTrkStateCand<xAOD::ElectronContainer>>();
commonstate = electronstate.get();
}else{
muonstate = std::make_unique<TrigMultiTrkStateCand<xAOD::MuonContainer>>();
commonstate = muonstate.get();
}
FillState(commonstate, &context, previousDecisionsHandle.cptr(), outputDecisionsHandle.ptr(), nullptr);
if (m_isStreamer) {
if (m_trigLevel == "L2") {
ATH_CHECK( mergeTracksFromViews(*state) );
ATH_CHECK( mergeTracksFromViews(*commonstate) );
}
else {
ATH_CHECK( mergeTracksFromDecisions(*state) );
ATH_CHECK( mergeTracksFromDecisions(*commonstate) );
}
ATH_CHECK( filterTrackCombinations(*state) );
ATH_CHECK( copyDecisionObjects(*state) );
ATH_CHECK( filterTrackCombinations(*commonstate) );
ATH_CHECK( copyDecisionObjects(*commonstate) );
}
else {
auto trigBphysHandle = SG::makeHandle(m_trigBphysContainerKey, context);
ATH_CHECK( trigBphysHandle.record(std::make_unique<xAOD::TrigBphysContainer>(),
std::make_unique<xAOD::TrigBphysAuxContainer>()) );
state->trigBphysCollection = trigBphysHandle.ptr();
ATH_CHECK( mergeMuonsFromDecisions(*state) );
ATH_CHECK( findDimuonCandidates(*state) );
ATH_CHECK( createDecisionObjects(*state) );
commonstate->trigBphysCollection = trigBphysHandle.ptr();
if(m_doElectrons == true){
ATH_CHECK( mergeFromDecisions(*electronstate) );
ATH_CHECK( findDiTrackCandidates(*electronstate) );
} else{
ATH_CHECK( mergeFromDecisions(*muonstate) );
ATH_CHECK( findDiTrackCandidates(*muonstate) );
}
ATH_CHECK( createDecisionObjects(*commonstate) );
}
ATH_MSG_DEBUG( "TrigMultiTrkHypo::execute() terminates with StatusCode::SUCCESS" );
......@@ -202,36 +219,38 @@ StatusCode TrigMultiTrkComboHypo::execute(const EventContext& context) const {
}
std::unique_ptr<TrigMultiTrkState> TrigMultiTrkComboHypo::makeState(const EventContext* context,
void TrigMultiTrkComboHypo::FillState(TrigMultiTrkState* state,
const EventContext* context,
const DecisionContainer* previousDecisions,
DecisionContainer* decisions,
xAOD::TrigBphysContainer* trigBphysCollection) const {
auto state = std::make_unique<TrigMultiTrkState>();
state->context = context;
state->previousDecisions = previousDecisions;
state->decisions = decisions;
state->trigBphysCollection = trigBphysCollection;
return state;
}
template<typename T>
StatusCode TrigMultiTrkComboHypo::mergeFromDecisions(TrigMultiTrkStateCand<T>& state) const {
StatusCode TrigMultiTrkComboHypo::mergeMuonsFromDecisions(TrigMultiTrkState& state) const {
auto& muons = state.muons;
muons.clear();
auto& leptons = state.LegList;
leptons.clear();
// all muons from views are already connected with previous decisions by TrigMuonEFHypoAlg
for (const Decision* decision : *state.previousDecisions) {
ATH_CHECK( decision->hasObjectLink(TrigCompositeUtils::featureString(), ClassID_traits<xAOD::MuonContainer>::ID()) );
auto muonEL = decision->objectLink<xAOD::MuonContainer>(TrigCompositeUtils::featureString());
const xAOD::Muon* muon = *muonEL;
if (!muon->trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle)) continue;
if (!muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle)) continue;
ATH_CHECK( decision->hasObjectLink(TrigCompositeUtils::featureString(), ClassID_traits<T>::ID()) );
auto leptonEL = decision->objectLink<T>(TrigCompositeUtils::featureString());
const auto lepton = *leptonEL;
if constexpr (std::is_same<T, xAOD::MuonContainer>::value){
if (!lepton->trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle)) continue;
if (!lepton->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle)) continue;
} else {
if (!lepton->trackParticle()) continue;
}
auto decisionEL = TrigCompositeUtils::decisionToElementLink(decision, *state.context);
auto itr = std::find_if(muons.begin(), muons.end(), [this, muon = muon](const auto& x){ return isIdenticalTracks(muon, *x.link); });
if (itr == muons.end()) {
muons.push_back({muonEL, ElementLinkVector<DecisionContainer>(1, decisionEL), DecisionIDContainer()});
auto itr = std::find_if(leptons.begin(), leptons.end(), [this, lepton = lepton](const auto& x){ return isIdenticalTracks(lepton, *x.link); });
if (itr == leptons.end()) {
leptons.push_back({leptonEL, ElementLinkVector<DecisionContainer>(1, decisionEL), DecisionIDContainer()});
}
else {
(*itr).decisionLinks.push_back(decisionEL);
......@@ -240,22 +259,27 @@ StatusCode TrigMultiTrkComboHypo::mergeMuonsFromDecisions(TrigMultiTrkState& sta
// muon->pt() is equal to muon->trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle)->pt()
// and the later is used by TrigMuonEFHypoTool for classification of muEFCB candidates
std::sort(muons.begin(), muons.end(), [](const auto& lhs, const auto& rhs){ return ((*lhs.link)->pt() > (*rhs.link)->pt()); });
std::sort(leptons.begin(), leptons.end(), [](const auto& lhs, const auto& rhs){ return ((*lhs.link)->pt() > (*rhs.link)->pt()); });
// for each muon we extract DecisionIDs stored in the associated Decision objects and copy them at muon.decisionIDs
for (auto& item : muons) {
for (auto& item : leptons) {
for (const ElementLink<xAOD::TrigCompositeContainer> decisionEL : item.decisionLinks) {
TrigCompositeUtils::decisionIDs(*decisionEL, item.decisionIDs);
}
}
if (msgLvl(MSG::DEBUG)) {
ATH_MSG_DEBUG( "Dump found muons before vertex fit: " << muons.size() << " candidates" );
for (const auto& item : muons) {
const xAOD::Muon* muon = *item.link;
const xAOD::TrackParticle* track = *muon->inDetTrackParticleLink();
ATH_MSG_DEBUG( " -- muon InDetTrackParticle pt/eta/phi/q: " << track->pt() << " / " << track->eta() << " / " << track->phi() << " / " << track->charge() );
ATH_MSG_DEBUG( " muon CombinedTrackParticle pt: " << muon->pt() );
ATH_MSG_DEBUG( "Dump found leptons before vertex fit: " << leptons.size() << " candidates" );
for (const auto& item : leptons) {
const auto lepton = *item.link;
const xAOD::TrackParticle* track;
if constexpr (std::is_same<T, xAOD::MuonContainer>::value){
track = *lepton->inDetTrackParticleLink();
}else{
track = *lepton->trackParticleLink();
}
ATH_MSG_DEBUG( " -- lepton InDetTrackParticle pt/eta/phi/q: " << track->pt() << " / " << track->eta() << " / " << track->phi() << " / " << track->charge() );
ATH_MSG_DEBUG( " lepton pt (muon: CombinedTrackParticle): " << lepton->pt() );
ATH_MSG_DEBUG( " allowed decisions:" );
for (const DecisionID& id : item.decisionIDs) {
ATH_MSG_DEBUG( " +++ " << HLT::Identifier(id) );
......@@ -266,6 +290,8 @@ StatusCode TrigMultiTrkComboHypo::mergeMuonsFromDecisions(TrigMultiTrkState& sta
}
StatusCode TrigMultiTrkComboHypo::mergeTracksFromViews(TrigMultiTrkState& state) const {
auto& tracks = state.tracks;
......@@ -443,17 +469,17 @@ StatusCode TrigMultiTrkComboHypo::filterTrackCombinations(TrigMultiTrkState& sta
return StatusCode::SUCCESS;
}
template<typename T>
StatusCode TrigMultiTrkComboHypo::findDiTrackCandidates(TrigMultiTrkStateCand<T>& state) const {
StatusCode TrigMultiTrkComboHypo::findDimuonCandidates(TrigMultiTrkState& state) const {
state.trigBphysMuonIndices.clear();
auto& muons = state.muons;
state.trigBphysIndices.clear();
auto& legs = state.LegList;
SG::ReadCondHandle<InDet::BeamSpotData> beamSpotHandle {m_beamSpotKey, *state.context};
ATH_CHECK( beamSpotHandle.isValid() );
// monitored variables
auto mon_nAcceptedTrk = Monitored::Scalar<int>("nAcceptedTrk", muons.size());
auto mon_nAcceptedTrk = Monitored::Scalar<int>("nAcceptedTrk", legs.size());
auto mon_nCombination = Monitored::Scalar<int>("nCombination", 0);
auto mon_nCombinationBeforeFit = Monitored::Scalar<int>("nCombinationBeforeFit", 0);
auto mon_nBPhysObject = Monitored::Scalar<int>("nBPhysObject", 0);
......@@ -475,29 +501,34 @@ StatusCode TrigMultiTrkComboHypo::findDimuonCandidates(TrigMultiTrkState& state)
mon_trkMassBeforeFit, mon_bphysChi2, mon_bphysLxy, mon_bphysFitMass, mon_bphysMass, mon_bphysCharge,
mon_timer);
if (muons.size() < m_nTrk) {
ATH_MSG_DEBUG( "Could not build a subset of " << m_nTrk.value() << " muons from collection which contains only " << muons.size() << " objects" );
if (legs.size() < m_nTrk) {
ATH_MSG_DEBUG( "Could not build a subset of " << m_nTrk.value() << " legs from collection which contains only " << legs.size() << " objects" );
return StatusCode::SUCCESS;
}
ATH_MSG_DEBUG( "Consider all combinations of " << m_nTrk.value() << " muons from collection which contains " << muons.size() << " objects" );
ATH_MSG_DEBUG( "Consider all combinations of " << m_nTrk.value() << "legs from collection which contains " << legs.size() << " objects" );
std::vector<size_t> muonIndices(m_nTrk);
std::vector<size_t> leptonIndices(m_nTrk);
std::vector<ElementLink<xAOD::TrackParticleContainer>> tracklist(m_nTrk);
std::vector<xAOD::TrackParticle::GenVecFourMom_t> p(m_nTrk);
std::vector<char> muonTags(muons.size(), 0);
std::fill(muonTags.begin(), muonTags.begin() + m_nTrk, 1);
std::vector<char> leptonTags(legs.size(), 0);
std::fill(leptonTags.begin(), leptonTags.begin() + m_nTrk, 1);
do {
// fill tracklist and momenta of muons in the current subset
bool isValidCombination = true;
int charge = 0;
size_t j = 0;
for (size_t i = 0; i < muonTags.size(); ++i) {
if (!muonTags[i]) continue;
muonIndices[j] = i;
const xAOD::Muon* muon = *muons[i].link;
charge += static_cast<int>(lround(muon->charge()));
const auto& trackEL = muon->inDetTrackParticleLink();
for (size_t i = 0; i < leptonTags.size(); ++i) {
if (!leptonTags[i]) continue;
leptonIndices[j] = i;
auto leg = *legs[i].link;
charge += static_cast<int>(lround(leg->charge()));
ElementLink<xAOD::TrackParticleContainer> trackEL;
if constexpr(std::is_same<T, xAOD::MuonContainer>::value){
trackEL = leg->inDetTrackParticleLink();
} else{
trackEL = leg->trackParticleLink();
}
tracklist[j] = trackEL;
p[j] = (*trackEL)->genvecP4();
p[j].SetM(m_trkMass[j]);
......@@ -510,10 +541,10 @@ StatusCode TrigMultiTrkComboHypo::findDimuonCandidates(TrigMultiTrkState& state)
if (!isValidCombination) continue;
if (msgLvl(MSG::DEBUG)) {
ATH_MSG_DEBUG( "Dump found muons before vertex fit: pT / eta / phi / charge" );
ATH_MSG_DEBUG( "Dump found leptons before vertex fit: pT / eta / phi / charge" );
for (size_t i = 0; i < tracklist.size(); ++i) {
const auto track = *tracklist[i];
ATH_MSG_DEBUG( "muon " << i + 1 << ": " << p[i].Pt() << " / " << p[i].Eta() << " / " << p[i].Phi() << " / " << track->charge() );
ATH_MSG_DEBUG( "legs " << i + 1 << ": " << p[i].Pt() << " / " << p[i].Eta() << " / " << p[i].Phi() << " / " << track->charge() );
}
}
......@@ -530,18 +561,19 @@ StatusCode TrigMultiTrkComboHypo::findDimuonCandidates(TrigMultiTrkState& state)
if (!vertex) continue;
xAOD::TrigBphys* trigBphys = makeTrigBPhys(vertex.get(), fitterState.get(), beamSpotHandle->beamPos());
state.trigBphysCollection->push_back(trigBphys);
state.trigBphysMuonIndices.push_back(muonIndices);
state.trigBphysIndices.push_back(leptonIndices);
mon_nBPhysObject++;
bphysMass.push_back(mass * 0.001);
bphysCharge.push_back(charge);
} while (std::prev_permutation(muonTags.begin(), muonTags.end()));
} while (std::prev_permutation(leptonTags.begin(), leptonTags.end()));
return StatusCode::SUCCESS;
}
StatusCode TrigMultiTrkComboHypo::copyDecisionObjects(TrigMultiTrkState& state) const {
if (state.isEventAccepted) {
......@@ -567,7 +599,7 @@ StatusCode TrigMultiTrkComboHypo::createDecisionObjects(TrigMultiTrkState& state
size_t idx = 0;
for (const xAOD::TrigBphys* triggerObject : *state.trigBphysCollection) {
ATH_MSG_DEBUG( "Found xAOD::TrigBphys: mass = " << triggerObject->mass() );
ATH_MSG_DEBUG( "Found xAOD::TrigBphys: mass / chi2 = " << triggerObject->mass() << " / " << triggerObject->fitchi2() );
auto triggerObjectEL = ElementLink<xAOD::TrigBphysContainer>(*state.trigBphysCollection, triggerObject->index());
ATH_CHECK( triggerObjectEL.isValid() );
......@@ -576,12 +608,12 @@ StatusCode TrigMultiTrkComboHypo::createDecisionObjects(TrigMultiTrkState& state
Decision* decision = TrigCompositeUtils::newDecisionIn(state.decisions, TrigCompositeUtils::comboHypoAlgNodeName());
std::vector<const DecisionIDContainer*> previousDecisionIDs;
for (const size_t& i : state.trigBphysMuonIndices[idx]) {
const auto& muon = state.muons.at(i);
// attach all previous decisions: if the same previous decision is called twice, that's fine - internally takes care of that
// we already have an array of links to the previous decisions, so there is no need to use TrigCompositeUtils::linkToPrevious()
decision->addObjectCollectionLinks(TrigCompositeUtils::seedString(), muon.decisionLinks);
previousDecisionIDs.push_back(&muon.decisionIDs);
for (const size_t& i : state.trigBphysIndices[idx]) {
// attach all previous decisions: if the same previous decision is called twice, that's fine - internally takes care of that
// we already have an array of links to the previous decisions, so there is no need to use TrigCompositeUtils::linkToPrevious()
decision->addObjectCollectionLinks(TrigCompositeUtils::seedString(), state.getDecisionLinks(i));
previousDecisionIDs.push_back(&state.getDecisionID(i));
}
// set mandatory feature ElementLink to xAOD::TrigBphys object
......@@ -689,6 +721,11 @@ bool TrigMultiTrkComboHypo::isIdenticalTracks(const xAOD::Muon* lhs, const xAOD:
return isIdenticalTracks(*lhs->inDetTrackParticleLink(), *rhs->inDetTrackParticleLink());
}
bool TrigMultiTrkComboHypo::isIdenticalTracks(const xAOD::Electron* lhs, const xAOD::Electron* rhs) const {
return isIdenticalTracks(*lhs->trackParticleLink(), *rhs->trackParticleLink());
}
float TrigMultiTrkComboHypo::Lxy(const xAOD::TrigBphys* vertex, const Amg::Vector3D& beamSpot) const {
......@@ -711,3 +748,5 @@ bool TrigMultiTrkComboHypo::isInMassRange(double mass) const {
}
return result;
}
TrigMultiTrkState::~TrigMultiTrkState(){ }
......@@ -22,6 +22,7 @@
#include "xAODTracking/VertexContainer.h"
#include "xAODTracking/VertexAuxContainer.h"
#include "xAODMuon/MuonContainer.h"
#include "xAODEgamma/ElectronContainer.h"
#include "xAODTrigger/TrigComposite.h"
#include "xAODTrigBphys/TrigBphys.h"
#include "xAODTrigBphys/TrigBphysContainer.h"
......@@ -51,25 +52,39 @@ class IVKalState;
* @class TrigMultiTrkState
* @brief State class for TrigMultiTrkComboHypo algorithm
*/
class TrigMultiTrkState: public ::ITrigBphysState {
public:
virtual ~TrigMultiTrkState();
const EventContext* context;
const TrigCompositeUtils::DecisionContainer* previousDecisions;
TrigCompositeUtils::DecisionContainer* decisions;
xAOD::TrigBphysContainer* trigBphysCollection;
struct Muon {
ElementLink<xAOD::MuonContainer> link;
ElementLinkVector<TrigCompositeUtils::DecisionContainer> decisionLinks;
TrigCompositeUtils::DecisionIDContainer decisionIDs;
};
std::vector<Muon> muons;
std::vector<ElementLink<xAOD::TrackParticleContainer>> tracks;
int isEventAccepted;
std::vector<std::vector<size_t>> trigBphysMuonIndices;
std::vector<std::vector<size_t>> trigBphysIndices;
virtual ElementLinkVector<TrigCompositeUtils::DecisionContainer>& getDecisionLinks(size_t) =0 ;
virtual TrigCompositeUtils::DecisionIDContainer& getDecisionID(size_t) =0 ;
};
template<typename CONTAINER>
class TrigMultiTrkStateCand : public TrigMultiTrkState{
public:
virtual ~TrigMultiTrkStateCand<CONTAINER>() = default;
struct LEG {
ElementLink<CONTAINER> link;
ElementLinkVector<TrigCompositeUtils::DecisionContainer> decisionLinks;
TrigCompositeUtils::DecisionIDContainer decisionIDs;
};
std::vector<LEG> LegList;
virtual ElementLinkVector<TrigCompositeUtils::DecisionContainer>& getDecisionLinks(size_t i) override
{ return LegList.at(i).decisionLinks; }
virtual TrigCompositeUtils::DecisionIDContainer& getDecisionID(size_t i) override
{ return LegList.at(i).decisionIDs; }
};
class TrigMultiTrkComboHypo: public ::ComboHypo {
public:
TrigMultiTrkComboHypo(const std::string& name, ISvcLocator* pSvcLocator);
......@@ -80,23 +95,30 @@ class TrigMultiTrkComboHypo: public ::ComboHypo {
private:
std::unique_ptr<TrigMultiTrkState> makeState(const EventContext* context,
const TrigCompositeUtils::DecisionContainer* previousDecisions,
TrigCompositeUtils::DecisionContainer* decisions,
xAOD::TrigBphysContainer* trigBphysCollection) const;
void FillState(TrigMultiTrkState* state,
const EventContext* context,
const TrigCompositeUtils::DecisionContainer* previousDecisions,
TrigCompositeUtils::DecisionContainer* decisions,
xAOD::TrigBphysContainer* trigBphysCollection) const;
template<typename T>
StatusCode mergeFromDecisions(TrigMultiTrkStateCand<T>&) const;
StatusCode mergeMuonsFromDecisions(TrigMultiTrkState&) const;
StatusCode mergeTracksFromViews(TrigMultiTrkState&) const;
StatusCode mergeTracksFromDecisions(TrigMultiTrkState&) const;
StatusCode filterTrackCombinations(TrigMultiTrkState&) const;
StatusCode copyDecisionObjects(TrigMultiTrkState&) const;
StatusCode findDimuonCandidates(TrigMultiTrkState&) const;
template<typename T>
StatusCode findDiTrackCandidates(TrigMultiTrkStateCand<T>&) const;
StatusCode createDecisionObjects(TrigMultiTrkState&) const;
xAOD::Vertex* fit(const std::vector<ElementLink<xAOD::TrackParticleContainer>>& tracklist, Trk::IVKalState*) const;
xAOD::TrigBphys* makeTrigBPhys(xAOD::Vertex* vertex, Trk::IVKalState* fitterState, const Amg::Vector3D& beamspot) const;
bool isIdenticalTracks(const xAOD::TrackParticle* lhs, const xAOD::TrackParticle* rhs) const;
bool isIdenticalTracks(const xAOD::Muon* lhs, const xAOD::Muon* rhs) const;
bool isIdenticalTracks(const xAOD::Electron* lhs, const xAOD::Electron* rhs) const;
bool isInMassRange(double mass) const;
float Lxy(const xAOD::TrigBphys*, const Amg::Vector3D&) const;
......@@ -117,6 +139,7 @@ class TrigMultiTrkComboHypo: public ::ComboHypo {
Gaudi::Property<float> m_chi2 {this, "chi2", 150., "chi2 cut for the fitted vertex"};
Gaudi::Property<bool> m_isStreamer {this, "isStreamer", false, "if true we do not create trigger objects, just copy all appropriate decisions to the next step or break the chain"};
Gaudi::Property<bool> m_doElectrons {this, "doElectrons", false, "use electrons instead of muons"};
Gaudi::Property<std::string> m_trigLevel {this, "trigLevel", "EF", "trigger Level to set for created TrigBphys objects"};
ToolHandle<InDet::VertexPointEstimator> m_vertexPointEstimator {this, "VertexPointEstimator", "", "tool to find starting point for the vertex fitter"};
......
......@@ -107,7 +107,7 @@ bool TrigMultiTrkComboHypoTool::checkPreviousDecisionIDs(const std::vector<const
if (decisionId() == legDecisionId(0)) { // trigger with symmetric legs like HLT_3mu6_bDimu_L13MU6
for (size_t i = 0; i < m_nTrk; ++i) {
if (!TrigCompositeUtils::passed(decisionId().numeric(), *previousDecisionIDs[i])) {
if (!TrigCompositeUtils::passed(decisionId().numeric(), *previousDecisionIDs[i])) {
ATH_MSG_DEBUG( "Trigger with symmetric legs didn't pass previous decision" );
return false;
}
......
......@@ -66,6 +66,19 @@ HLT_2e5_lhmedium_j70_0eta320_j50_0eta490_j0_dijet50j12etSEP900djmass_L1MJJ-500-N
1: 49
2: 4
3: 3
HLT_2e5_lhvloose_bBeeM6000_L12EM3:
eventCount: 0
stepCounts:
0: 14
1: 9
2: 6
3: 6
stepFeatures:
0: 64
1: 122
2: 18
3: 15
4: 5
HLT_2g10_loose_mu20_L1MU20:
eventCount: 0
stepCounts:
......
......@@ -52,6 +52,18 @@ HLT_2e5_lhmedium_j70_0eta320_j50_0eta490_j0_dijet50j12etSEP900djmass_L1MJJ-500-N
1: 14
2: 4
3: 2
HLT_2e5_lhvloose_bBeeM6000_L12EM3:
eventCount: 0
stepCounts:
0: 7
1: 2
2: 1
3: 1
stepFeatures:
0: 21
1: 14
2: 3
3: 2
HLT_2g10_loose_mu20_L1MU20:
eventCount: 0
stepFeatures:
......
......@@ -20,6 +20,8 @@ from .PrecisionElectronMenuSequences_LRT import precisionElectronMenuSequence_LR
from .PrecisionTrackingMenuSequences import precisionTrackingMenuSequence
from .PrecisionTrackingMenuSequences_LRT import precisionTrackingMenuSequence_LRT
from TrigBphysHypo.TrigMultiTrkComboHypoConfig import StreamerDiElecFastComboHypoCfg, DiElecPrecisionComboHypoCfg, TrigMultiTrkComboHypoToolFromDict
from AthenaMonitoringKernel.GenericMonitoringTool import GenericMonitoringTool, defineHistogram
#----------------------------------------------------------------
# fragments generating configuration will be functions in New JO,
......@@ -195,8 +197,12 @@ class ElectronChainConfiguration(ChainConfigurationBase):
return self.getStep(1, stepName, [fastCaloCfg])
def getFastElectron(self):
stepName = "fast_electron"
return self.getStep(2,stepName,[ fastElectronSequenceCfg])
if "bBeeM6000" in self.chainName:
stepName = "fast_electron_bBee"
return self.getStep(5,stepName,sequenceCfgArray=[fastElectronSequenceCfg], comboHypoCfg=StreamerDiElecFastComboHypoCfg)