Commit ec6ce0df authored by Aaron Joseph Kilgallon's avatar Aaron Joseph Kilgallon Committed by Walter Lampl
Browse files

Initial push of exotic hypo and chain definitions

parent d53fd328
......@@ -27,7 +27,6 @@ from JetRecConfig.JetGrooming import GroomingDefinition
from JetRecConfig.DependencyHelper import solveDependencies, solveGroomingDependencies, aliasToModDef
__all__ = ["JetRecCfg", "JetInputCfg"]
......@@ -209,7 +208,7 @@ def getPseudoJetAlgs(jetdef):
(this function is factorized out of PseudoJetCfg so it can be used standalone in the trigger config)
"""
constitpjalg = getConstitPJGAlg( jetdef.inputdef )
constitpjalg = getConstitPJGAlg( jetdef.inputdef , suffix=None)
#print("aaaa" , constitpjalg, constitpjalg.OutputContainer)
finalPJContainer = str(constitpjalg.OutputContainer)
pjalglist = [constitpjalg]
......@@ -315,18 +314,18 @@ def getInputAlgs(jetOrConstitdef, configFlags=None, context="default", monTool=N
def getConstitPJGAlg(constitdef):
def getConstitPJGAlg(constitdef,suffix=None):
"""returns a configured PseudoJetAlgorithm which converts the inputs defined by constitdef into fastjet::PseudoJet
IMPORTANT : constitdef must have its dependencies solved (i.e. it must result from a solveDependencies() call)
"""
jetlog.debug("Getting PseudoJetAlg for label {0} from {1}".format(constitdef.name,constitdef.inputname))
full_label = constitdef.label
full_label = constitdef.label + '' if suffix is None else f'_{suffix}'
pjgalg = CompFactory.PseudoJetAlgorithm(
"pjgalg_"+constitdef.label,
"pjgalg_"+full_label,
InputContainer = constitdef.containername,
OutputContainer = "PseudoJet"+full_label,
Label = full_label,
......@@ -362,7 +361,7 @@ def getGhostPJGAlg(ghostdef):
return pjgalg
def getJetRecAlg( jetdef, monTool = None):
def getJetRecAlg( jetdef, monTool = None, ftf_suffix = ''):
"""Returns the configured JetRecAlg instance corresponding to jetdef
IMPORTANT : jetdef must have its dependencies solved (i.e. it must result from solveDependencies() )
......@@ -370,10 +369,10 @@ def getJetRecAlg( jetdef, monTool = None):
pjContNames = jetdef._internalAtt['finalPJContainer']
jclust = CompFactory.JetClusterer(
"builder",
JetAlgorithm = jetdef.algorithm,
JetAlgorithm = jetdef.algorithm,#
JetRadius = jetdef.radius,
PtMin = jetdef.ptmin,
InputPseudoJets = pjContNames,
InputPseudoJets = pjContNames,#
GhostArea = 0.01,
JetInputType = int(jetdef.inputdef.jetinputtype),
RandomOption = 1,
......@@ -385,10 +384,10 @@ def getJetRecAlg( jetdef, monTool = None):
jetname = jetdef.fullname()
jra = CompFactory.JetRecAlg(
"jetrecalg_"+jetname,
"jetrecalg_"+jetname+ftf_suffix,
Provider = jclust,
Modifiers = mods,
OutputContainer = jetname,
OutputContainer = jetname+ftf_suffix,
)
if monTool:
# this option can't be set in AnalysisBase -> set only if explicitly asked :
......
......@@ -73,6 +73,27 @@ def trigJetHypoToolFromDict(chain_dict):
def trigJetTLAHypoToolFromDict(chain_dict):
return CompFactory.TrigJetTLAHypoTool(chain_dict['chainName'])
def trigJetEJsHypoToolFromDict(chain_dict):
chain_name = chain_dict['chainName']
if 'Exotic' in chain_name:
trackless = int(0)
ptf = float(chain_name.split('PTF')[1].split('dR')[0].replace('p', '.'))
dr = float(chain_name.split('dR')[1].split('_')[0].replace('p', '.'))
elif 'Trackless' in chain_name:
trackless = int(1)
ptf = 0.0
dr = float(chain_name.split('dR')[1].split('_')[0].replace('p', '.'))
else:
raise Exception("misconfiguration of Exotic jet chain")
hypo = CompFactory.TrigJetEJsHypoTool(chain_name)
hypo.PTF = ptf
hypo.dR = dr
hypo.Trackless = trackless
return hypo
import unittest
class TestStringMethods(unittest.TestCase):
......
/*
Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
*/
#include <algorithm>
#include "TrigJetEJsHypoAlg.h"
#include "TrigJetEJsHypoTool.h"
#include "TrigCompositeUtils/HLTIdentifier.h"
#include "TrigCompositeUtils/TrigCompositeUtils.h"
using namespace TrigCompositeUtils;
using xAOD::JetContainer;
using xAOD::TrackParticleContainer;
using xAOD::VertexContainer;
TrigJetEJsHypoAlg::TrigJetEJsHypoAlg( const std::string& name,
ISvcLocator* pSvcLocator ) :
::HypoBase( name, pSvcLocator ) { }
StatusCode TrigJetEJsHypoAlg::initialize() {
CHECK( m_hypoTools.retrieve() );
CHECK( m_tracksKey.initialize() );
CHECK( m_PV.initialize() );
return StatusCode::SUCCESS;
}
StatusCode TrigJetEJsHypoAlg::execute( const EventContext& context ) const {
ATH_MSG_DEBUG ( "Executing " << name() << "..." );
// get the HLT decision container for the previous decisions (one per jet in the original collection)
ATH_MSG_DEBUG("Retrieving HLT decision \"" << decisionInput().key() << "\"");
auto previousDecisionsHandle = SG::makeHandle(decisionInput(), context );
ATH_CHECK(previousDecisionsHandle.isValid());
const DecisionContainer* prevDecisions = previousDecisionsHandle.get();
// read in tracks container
ATH_MSG_DEBUG("Retrieving tracks from the track container \"" << m_tracksKey << "\"");
auto TracksHandle = SG::makeHandle(m_tracksKey, context );
ATH_CHECK(TracksHandle.isValid());
const TrackParticleContainer* tracks = TracksHandle.get();
// read in primary vertex container
ATH_MSG_DEBUG("Retrieving PV from the vertex container \"" << m_PV << "\"");
auto PVHandle = SG::makeHandle(m_PV, context );
ATH_CHECK(PVHandle.isValid());
const VertexContainer* vertices = PVHandle.get();
const xAOD::Vertex_v1 *PV = vertices->at(0);
std::vector<TrigJetEJsHypoTool::JetInfo> hypoToolInput;
SG::WriteHandle<DecisionContainer> outputHandle = createAndStore(decisionOutput(), context);
DecisionContainer* outputDecisions = outputHandle.ptr();
for (const Decision* previousDecision : *prevDecisions) {
LinkInfo< xAOD::JetContainer > myFeature = findLink< xAOD::JetContainer >(previousDecision, featureString());
TrigCompositeUtils::DecisionIDContainer previousDecisionIDs;
TrigCompositeUtils::decisionIDs(previousDecision, previousDecisionIDs);
Decision* newDecision = newDecisionIn(outputDecisions, previousDecision, hypoAlgNodeName(), context);
newDecision->setObjectLink<xAOD::JetContainer>(featureString(), myFeature.link);
hypoToolInput.emplace_back(TrigJetEJsHypoTool::JetInfo{newDecision, *(myFeature.link), tracks, PV, previousDecisionIDs});
}//end loop on previous decisions
for (const auto& tool: m_hypoTools) {
ATH_MSG_DEBUG("Now computing decision for " << tool->name());
CHECK(tool->decide(hypoToolInput));
}//end loop on hypoTools
DecisionContainer::iterator it = outputDecisions->begin();
while(it != outputDecisions->end()) {
if (allFailed( *it )) {
it = outputDecisions->erase(it);
} else {
++it;
}
}//end loop on output decisios
return StatusCode::SUCCESS;
}//end execute
/*
Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
*/
#ifndef TrigHLTJetHypo_TrigJetEJsHypoAlg_H
#define TrigHLTJetHypo_TrigJetEJsHypoAlg_H
#include <string>
#include "TrigJetEJsHypoAlg.h"
#include "AthenaBaseComps/AthReentrantAlgorithm.h"
#include "xAODJet/JetContainer.h"
#include "xAODTracking/VertexContainer.h"
#include "DecisionHandling/HypoBase.h"
#include "TrigJetEJsHypoTool.h"
/**
* @class TrigJetEJsHypoAlg
* @brief HypoAlg for exotic jets / emerging jets algorithm
* @details HypoAlg needed to associate trigger navigation to jets selected for writing out by exotic jets algorithms
* @author Aaron Kilgallon
* @author Antonio Boveia
* @author Caterina Doglioni
* @author Teng Jian Khoo
* @author Tim Martin
* @author Rafal Bielski
**/
class TrigJetEJsHypoAlg : public ::HypoBase {
public:
TrigJetEJsHypoAlg( const std::string& name, ISvcLocator* pSvcLocator );
virtual StatusCode initialize() override;
virtual StatusCode execute( const EventContext& context ) const override;
private:
ToolHandleArray<TrigJetEJsHypoTool> m_hypoTools {
this, "HypoTools", {}, "Hypo tools"};
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_tracksKey
{this,"Tracks","Key for precision tracks"};
SG::ReadHandleKey< xAOD::VertexContainer > m_PV
{this,"PV","Key for Primary Vertex"};
};
#endif
/*
Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
*/
// ********************************************************************
//
// NAME: TrigJetEJsHypoTool.cxx
// PACKAGE: Trigger/TrigHypothesis/TrigHLTJetHypo
//
//
// ********************************************************************
#include "TrigJetEJsHypoTool.h"
#include "GaudiKernel/StatusCode.h"
#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/xAODJetAsIJetFactory.h"
#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/lineSplitter.h"
#include "./DebugInfoCollector.h"
#include "./xAODJetCollector.h"
#include "TrigCompositeUtils/HLTIdentifier.h"
#include "TrigCompositeUtils/TrigCompositeUtils.h"
#include "xAODTrigger/TrigCompositeContainer.h"
using TrigCompositeUtils::DecisionID;
using TrigCompositeUtils::Decision;
using TrigCompositeUtils::DecisionContainer;
using TrigCompositeUtils::DecisionIDContainer;
using TrigCompositeUtils::decisionIDs;
using namespace TrigCompositeUtils;
TrigJetEJsHypoTool::TrigJetEJsHypoTool(const std::string& type,
const std::string& name,
const IInterface* parent) :
AthAlgTool(type, name, parent),
m_decisionId(HLT::Identifier::fromToolName(name)){
}
TrigJetEJsHypoTool::~TrigJetEJsHypoTool(){
}
StatusCode TrigJetEJsHypoTool::initialize(){
if (m_visitDebug){
DebugInfoCollector collector(name());
CHECK(m_helper->getDescription(collector));
auto s = collector.toString();
for(const auto& l : lineSplitter(s)){
ATH_MSG_INFO(l);
}
}
return StatusCode::SUCCESS;
}
StatusCode TrigJetEJsHypoTool::finalize(){
return StatusCode::SUCCESS;
}
StatusCode
TrigJetEJsHypoTool::decide( std::vector<JetInfo>& input ) const {
for ( auto i: input ) {
if ( i.previousDecisionsIDs.count( m_decisionId.numeric() ) == 0 ) {
continue;
}
ATH_MSG_DEBUG("starting exotic/trackless jet chain");
bool objDecision = true;
// start with cut on jet pT
auto jetPt= (i.jet)->pt();
if((m_trackless == 0 && jetPt < m_jetPtCut_Exotics ) || \
(m_trackless == 1 && jetPt < m_jetPtCut_Trackless)) {
objDecision = false;
}
// cut on jet eta
auto jetEta=std::abs( (i.jet)->p4().Eta() );
if( (m_trackless == 0 && jetEta > m_jetEtaCut_Exotics ) || \
(m_trackless == 1 && jetEta > m_jetEtaCut_Trackless)) {
objDecision = false;
}
float promptTrackFrac = -2.0;
if (objDecision == true) {
// Exotics (emerging jets) chain decision
if (m_trackless == 0) {
promptTrackFrac = 0.0;
for (auto trackIter = i.AllTracks->begin(); trackIter != i.AllTracks->end(); ++trackIter){
float trackPt = (*trackIter)->pt();
if (std::abs((*trackIter)->z0() - i.PV->z()) > m_PV_z || trackPt < m_trackPtCut_Exotics || \
std::abs((*trackIter)->eta()) > m_trackEtaCut_Exotics || (i.jet)->p4().DeltaR((*trackIter)->p4()) > m_dr)
continue;
float sigma = 1e6;
// Definition of promptTrackFrac background jet d0 RMS
if (trackPt > 0.0) sigma = 1000.0 * 0.0463 / trackPt + 0.0195;
// if d0 greater than a multiple of sigma, is not a prompt track
if (std::abs((*trackIter)->d0()) > m_PTFSigmaCut*sigma) continue;
promptTrackFrac += trackPt;
}
if (jetPt > 0.0) promptTrackFrac /= jetPt;
else promptTrackFrac = -1.0;
ATH_MSG_DEBUG("exotics jets chain promptTrackFrac: " << promptTrackFrac);
if (promptTrackFrac < -0.5 || promptTrackFrac > m_ptf) objDecision = false;
}
// Trackless chain decision
else if (m_trackless == 1) {
int matchedtracks = 0;
// Loop over tracks, selection ones passing pT, eta, and dR cuts to jet
for (auto trackIter = i.AllTracks->begin(); trackIter != i.AllTracks->end(); ++trackIter){
if ((*trackIter)->pt() < m_trackPtCut_Trackless || std::abs((*trackIter)->eta()) > m_trackEtaCut_Trackless \
|| (i.jet)->p4().DeltaR((*trackIter)->p4()) > m_dr)
continue;
matchedtracks++;
if (matchedtracks > m_matchedTracksCut_Trackless) {
objDecision = false;
break;
}
}
ATH_MSG_DEBUG("Number of matched tracks (" << matchedtracks << ") greater than cutoff - in trackless jet chain");
}
} // end if objDecision == true
if ( objDecision == true ) {
ATH_MSG_DEBUG("passed exotics/trackless jet chain decision with PTF: " << promptTrackFrac << "\ttrackless: " << m_trackless << "\tpt: " << jetPt << "\teta: " << jetEta);
addDecisionID( m_decisionId.numeric(), i.decision );
}
} // end loop over inputs
return StatusCode::SUCCESS;
}
/*
Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
*/
#ifndef TRIGJETEJSHYPOTOOL_H
#define TRIGJETEJSHYPOTOOL_H
/********************************************************************
*
* NAME: TrigJetEJsHypoTool.h
* PACKAGE: Trigger/TrigHypothesis/TrigHLTJetHypo
*
* * @class TrigJetEJsHypoTool
* * @brief HypoTool for
* * @details HypoTool needed to decide on exotic jet selections
* * @author Aaron Kilgallon
* * @author Antonio Boveia
* * @author Caterina Doglioni
* * @author Teng Jian Khoo
* * @author Tim Martin
* * @author Rafal Bielski
*
*
********************************************************************/
#include "TrigCompositeUtils/HLTIdentifier.h"
#include "AthenaBaseComps/AthAlgTool.h"
#include "TrigCompositeUtils/TrigCompositeUtils.h"
#include "AthenaMonitoringKernel/GenericMonitoringTool.h"
#include "TrigHLTJetHypo/ITrigJetHypoToolHelper.h"
#include "xAODEventInfo/EventInfo.h"
#include "xAODJet/JetContainer.h"
#include "xAODTracking/TrackParticlexAODHelpers.h"
#include "xAODTracking/TrackParticleContainer.h"
#include "xAODTracking/VertexContainer.h"
class TrigJetEJsHypoTool: public AthAlgTool{
public:
TrigJetEJsHypoTool(const std::string& type,
const std::string& name,
const IInterface* parent);
~TrigJetEJsHypoTool();
StatusCode initialize();
StatusCode finalize();
// typedef for passing jet - decision object assocation
using JetDecision = std::pair<const xAOD::Jet*,TrigCompositeUtils::Decision*>;
struct JetInfo {
TrigCompositeUtils::Decision* decision;
const xAOD::Jet_v1* jet;
const xAOD::TrackParticleContainer* AllTracks;
const xAOD::Vertex_v1 *PV;
const TrigCompositeUtils::DecisionIDContainer previousDecisionsIDs;
};
StatusCode decide( std::vector<JetInfo>& decisions ) const;
const HLT::Identifier& getId() const;
private:
// Identifier is used to keep track of which tool made which decision.
// The information is stored in the event store.
HLT::Identifier m_decisionId;
ToolHandle<ITrigJetHypoToolHelper> m_helper {
this, "helper_tool", {}, "Jet hypo helper AlgTool"};
Gaudi::Property<bool>
m_visitDebug {this, "visit_debug", false, "debug flag"};
Gaudi::Property<std::string> m_chainName {
this, "chain_name", {}, "chain name"};
Gaudi::Property< double > m_ptf {this, "PTF", 1.0, ""};
Gaudi::Property< double > m_dr {this, "dR", 1.0, ""};
Gaudi::Property< int > m_trackless {this, "Trackless", 1.0, ""};
// Track eta cuts for exotics and trackless hypos
double m_trackEtaCut_Exotics = 2.4;
double m_trackEtaCut_Trackless = 2.4;
// Track pT cuts for exotics hypos
double m_trackPtCut_Exotics = 1.0*Gaudi::Units::GeV;
double m_trackPtCut_Trackless = 1.0*Gaudi::Units::GeV;
// Jet pT cut for promptTrackFrac definition (studies only
// done down to a 50 GeV cut)
double m_jetPtCut_Exotics = 50.0*Gaudi::Units::GeV;
double m_jetPtCut_Trackless = 50.0*Gaudi::Units::GeV;
// Eta cut for exotics jet selections (may need to be reduced
// to 1.4 for large-R jets to have complete overlapy with
// the tracker)
double m_jetEtaCut_Exotics = 2.0;
double m_jetEtaCut_Trackless = 2.0;
// Track d0 cuts based on a multiple of background distribution
// 2.5 was found to be best signal sensitivity for R-Hadrons
double m_PTFSigmaCut = 2.5;
// Cut on number of tracks associated to jet in the soft-bomb
// trigger case (likely to be changed based on physics studies)
int m_matchedTracksCut_Trackless = 0;
// |z0 - PV_z| cut on tracks
double m_PV_z = 10.0;
};
#endif
......@@ -30,6 +30,8 @@
#include "../TrigJetHypoToolHelperNoGrouper.h"
#include "../TrigJetTLAHypoAlg.h"
#include "../TrigJetTLAHypoTool.h"
#include "../TrigJetEJsHypoAlg.h"
#include "../TrigJetEJsHypoTool.h"
DECLARE_COMPONENT(TrigJetHypoToolConfig_fastreduction)
DECLARE_COMPONENT(TrigJetHypoToolConfig_conditionfilter)
......@@ -58,3 +60,5 @@ DECLARE_COMPONENT(TrigJetTLAHypoAlg)
DECLARE_COMPONENT(TrigJetTLAHypoTool)
DECLARE_COMPONENT(TrigJetHypoToolHelperNoGrouper)
DECLARE_COMPONENT(TrigJetEJsHypoAlg)
DECLARE_COMPONENT(TrigJetEJsHypoTool)
......@@ -4279,6 +4279,90 @@ HLT_j100_pf_ftf_bdl1r60_xe50_cell_xe85_tcpufit_L1XE55:
1: 5
HLT_j110_320eta490_L1J30p31ETA49:
eventCount: 0
HLT_j110_a10r_subjesIS_ftf_0eta200_ExoticPTF0p0dR1p2_L1J100:
eventCount: 0
stepCounts:
0: 3
1: 2
stepFeatures:
0: 3
1: 4
HLT_j110_a10r_subjesIS_ftf_0eta200_ExoticPTF0p0dR1p2_L1SC111-CJ15:
eventCount: 0
stepCounts:
0: 4
1: 4
stepFeatures:
0: 4
1: 7
HLT_j110_a10r_subjesIS_ftf_0eta200_ExoticPTF0p1dR1p2_L1J100:
eventCount: 0
stepCounts:
0: 3
1: 2
stepFeatures:
0: 3
1: 4
HLT_j110_a10r_subjesIS_ftf_0eta200_ExoticPTF0p1dR1p2_L1SC111-CJ15:
eventCount: 0
stepCounts:
0: 4
1: 4
stepFeatures:
0: 4
1: 7
HLT_j110_a10r_subjesIS_ftf_0eta200_ExoticPTF0p2dR1p2_L1J100:
eventCount: 0
stepCounts:
0: 3
1: 2
stepFeatures:
0: 3
1: 4
HLT_j110_a10r_subjesIS_ftf_0eta200_ExoticPTF0p2dR1p2_L1SC111-CJ15:
eventCount: 0
stepCounts:
0: 4
1: 4
stepFeatures:
0: 4
1: 7
HLT_j110_a10r_subjesIS_ftf_0eta200_ExoticPTF0p3dR1p2_L1J100:
eventCount: 1
stepCounts:
0: 3
1: 2
2: 1
stepFeatures:
0: 3
1: 4
2: 1
HLT_j110_a10r_subjesIS_ftf_0eta200_ExoticPTF0p3dR1p2_L1SC111-CJ15:
eventCount: 1
stepCounts:
0: 4