ATLAS Offline Software
JetQGTaggerBDT.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include <TSystem.h>
8 
10 
12 
13 namespace CP {
14 
15  JetQGTaggerBDT::JetQGTaggerBDT( const std::string& name ) :
17  m_BDTmethod("BDT_method"),
18  m_trkSelectionTool(name+"_trackselectiontool", this)
19  {
20 
22  declareProperty( "JetPtMin", m_jetPtMin = 20000.0);
23  declareProperty( "JetPtMax", m_jetPtMax = 1500000.0);
24  m_jetEtaMax = 2.5;
25 
27  m_calibArea = "BoostedJetTaggers/JetQGTaggerBDT/Oct18/";
28  declareProperty( "UseJetVars", m_mode = 1);
29 
30  m_tmvaConfigFileName="TMVAClassification_BDTQGTagger_Oct18_BDT.weights.xml";
31 
32  }
33 
35 
36  ATH_MSG_INFO( "Initializing JetQGTaggerBDT tool" );
37 
38  if( ! m_configFile.empty() ) {
39 
42 
43  // get the name/path of the JSON config
44  m_tmvaConfigFileName = m_configReader.GetValue("TMVAConfigFile" ,"");
45 
46  }
47 
49  if( m_calibArea.empty() ){
50  ATH_MSG_ERROR( "You need to specify where the calibArea is as either being Local or on CVMFS" );
51  return StatusCode::FAILURE;
52  }
53  else if(m_calibArea.compare("Local")==0){
54  std::string localCalibArea = "BoostedJetTaggers/share/JetQGTaggerBDT/";
55  ATH_MSG_INFO( "Using Local calibArea " << localCalibArea );
58  }
59  else{
60  ATH_MSG_INFO( "Using CVMFS calibArea" );
64  }
65 
67  m_strScoreCut = m_configReader.GetValue("ScoreCut" ,"");
68  if(m_strScoreCut.empty()){
69  ATH_MSG_ERROR( "Score cut function is empty!" );
70  return StatusCode::FAILURE;
71  }
72  else ATH_MSG_INFO( "scoreCut: " << m_strScoreCut );
73 
76  ANA_CHECK( m_trkSelectionTool.setProperty( "CutLevel", "Loose" ) );
78 
80  ATH_MSG_INFO( "BDT Tagger configured with: " << m_tmvaConfigFilePath );
81 
83  TMVA::Tools::Instance();
84  for (auto& tagger : m_bdtTagger) {
85  tagger.tmva = std::make_unique<TMVA::Reader>( "!Color:!Silent" );
86 
87  tagger.tmva->AddVariable( "NTracks", &tagger.ntracks );
88  tagger.tmva->AddVariable( "TrackWidth", &tagger.trackwidth );
89  tagger.tmva->AddVariable( "JetPt", &tagger.pt );
90  tagger.tmva->AddVariable( "JetEta", &tagger.eta );
91  tagger.tmva->AddVariable( "TrackC1", &tagger.trackC1 );
92 
94  tagger.tmva->BookMVA( m_BDTmethod.c_str(), m_tmvaConfigFilePath.c_str() );
95  }
96 
99 
100  ATH_CHECK( m_decScoreKey.initialize() );
101 
104 
105  return StatusCode::SUCCESS;
106 
107  }
108 
110 
111  ATH_MSG_DEBUG( "Obtaining BDT QG result" );
112 
114  asg::AcceptData acceptData( &m_acceptInfo );
115 
117  ATH_CHECK( resetCuts( acceptData ) );
118 
120  ATH_CHECK( checkKinRange( jet, acceptData ) );
121 
125 
127  if ( !passKinRange(jet) ) {
128  decTagged(jet) = false;
129  return StatusCode::SUCCESS;
130  }
131 
133  float jet_score = getScore( jet, acceptData );
134  ATH_MSG_DEBUG(TString::Format("jet score %g",jet_score) );
135 
137  float cut = m_funcScoreCut->Eval(jet.pt()/1000.);
138 
140  decScore(jet) = jet_score;
141 
143  if ( jet_score < cut ) acceptData.setCutResult("QuarkJetTag", true);
144  decTagged(jet) = acceptData.getCutResult( "QuarkJetTag" );
145 
146  return StatusCode::SUCCESS;
147 
148  }
149 
150  float JetQGTaggerBDT::getScore( const xAOD::Jet& jet, asg::AcceptData &acceptData ) const {
151 
153  bool validVars = getJetProperties( jet, acceptData );
154 
156  float bdt_score(-666.);
157  if ( !validVars ) {
158  ATH_MSG_WARNING( "One (or more) tagger input variable has an undefined value (NaN), setting score to -666" );
159  return bdt_score;
160  }
161  bdt_score = m_bdtTagger->tmva->EvaluateMVA( m_BDTmethod.c_str() );
162 
163  return bdt_score;
164  }
165 
166  bool JetQGTaggerBDT::getJetProperties( const xAOD::Jet& jet, asg::AcceptData &acceptData ) const {
167  /* Update the jet substructure variables for this jet */
168 
169  m_bdtTagger->pt = jet.pt()/1000.0;
170  m_bdtTagger->eta = jet.eta();
171 
172  ATH_MSG_DEBUG( TString::Format("pT: %g, eta: %g", m_bdtTagger->pt, m_bdtTagger->eta) );
173 
174  m_bdtTagger->ntracks = -1.;
175  m_bdtTagger->trackwidth = -1.;
176  m_bdtTagger->trackC1 = -1.;
177 
178  bool validVars = true;
179 
180  if ( m_mode == 1 ) {
181  validVars = getPrecomputedVariables( jet, acceptData );
182  }
183  else if( m_mode == 0 ) {
184  validVars = calculateVariables( jet, acceptData );
185  }
186 
187  if ( !validVars ) {
188  ATH_MSG_ERROR( "Can't determine QG tagging variables! Try different mode." );
189  }
190 
191  return validVars;
192 
193  }
194 
196 
197  bool validVars = true;
198 
199  int ntrk = -1;
200  float trkWidth = -1.;
201  float trkC1 = -1.;
202 
203  if ( !jet.getAttribute<int>("DFCommonJets_QGTagger_NTracks", ntrk) ) {
204  if ( m_nWarnVar++ < m_nWarnMax ) ATH_MSG_WARNING( "Unable to retrieve DFCommonJets_QGTagger_NTracks" );
205  else ATH_MSG_DEBUG( "Unable to retrieve DFCommonJets_QGTagger_NTracks" );
206  acceptData.setCutResult("ValidEventContent", false);
207  validVars = false;
208  }
209  if ( !jet.getAttribute<float>("DFCommonJets_QGTagger_TracksWidth", trkWidth) ) {
210  if ( m_nWarnVar++ < m_nWarnMax )ATH_MSG_WARNING( "Unable to retrieve DFCommonJets_QGTagger_TracksWidth" );
211  else ATH_MSG_DEBUG( "Unable to retrieve DFCommonJets_QGTagger_TracksWidth" );
212  acceptData.setCutResult("ValidEventContent", false);
213  validVars = false;
214  }
215  if ( !jet.getAttribute<float>("DFCommonJets_QGTagger_TracksC1", trkC1) ) {
216  if ( m_nWarnVar++ < m_nWarnMax ) ATH_MSG_WARNING( "Unable to retrieve DFCommonJets_QGTagger_TracksC1" );
217  else ATH_MSG_DEBUG( "Unable to retrieve DFCommonJets_QGTagger_TracksC1" );
218  acceptData.setCutResult("ValidEventContent", false);
219  validVars = false;
220  }
221 
222  m_bdtTagger->ntracks = (float) ntrk;
223  m_bdtTagger->trackwidth = trkWidth;
224  m_bdtTagger->trackC1 = trkC1;
225 
226  return validVars;
227 
228  }
229 
235 
236  bool validVars = true;
237  bool isValid = true;
238  const xAOD::Vertex* primvertex {nullptr};
239 
240  const xAOD::VertexContainer* vxCont = nullptr;
241  if ( evtStore()->retrieve( vxCont, "PrimaryVertices" ).isFailure() ) {
242  if ( m_nWarnVar++ < m_nWarnMax ) ATH_MSG_WARNING( "Unable to retrieve primary vertex container PrimaryVertices" );
243  else ATH_MSG_DEBUG( "Unable to retrieve primary vertex container PrimaryVertices" );
244  acceptData.setCutResult("ValidEventContent", false);
245  isValid = false;
246  }
247  else if ( vxCont->empty() ) {
248  if ( m_nWarnVar++ < m_nWarnMax ) ATH_MSG_WARNING( "Event has no primary vertices!" );
249  ATH_MSG_DEBUG( "Event has no primary vertices!" );
250  acceptData.setCutResult("ValidEventContent", false);
251  isValid = false;
252  }
253  else {
254  for ( const auto *vx : *vxCont ) {
256  if ( vx->vertexType()==xAOD::VxType::PriVtx ) {
257  primvertex = vx;
258  break;
259  }
260  }
261  }
262  if ( !primvertex ) isValid = false;
263 
264  if ( !isValid ) {
265  validVars = false;
266  return validVars;
267  }
268 
270  std::vector<int> nTrkVec;
271  if(jet.getAttribute(xAOD::JetAttribute::NumTrkPt500, nTrkVec)){
272  ATH_MSG_DEBUG(nTrkVec.size());
273  m_bdtTagger->ntracks = (float) nTrkVec[primvertex->index()];
274  }
275  else
277  validVars = false;
278 
280  bool undefTrackWidth = false;
281  std::vector<float> trkWidthVec;
282  if(jet.getAttribute(xAOD::JetAttribute::TrackWidthPt500, trkWidthVec)){
283  ATH_MSG_DEBUG(trkWidthVec.size());
284  m_bdtTagger->trackwidth = trkWidthVec[primvertex->index()];
285  }
286  else
288  undefTrackWidth = true;
289  float weightedwidth = 0.;
290 
292  float beta = 0.2;
293  float weightedwidth2 = 0.;
294  float sumPt = 0.;
295 
296  std::vector<const xAOD::TrackParticle*> trackParttmp;
297  if(!jet.getAssociatedObjects("GhostTrack",trackParttmp)){
298  ATH_MSG_ERROR("This jet has no associated objects");
299  validVars = false;
300  }
302  for(unsigned i=trackParttmp.size();i>0; i--){
303  if(!trackParttmp[i-1]){
304  trackParttmp.erase(trackParttmp.begin()+i-1);
305  continue;
306  }
307  const xAOD::TrackParticle* trk = static_cast<const xAOD::TrackParticle*>(trackParttmp[i-1]);
308  bool accept = (trk->pt()>500 &&
310  );
311  if (!accept){
312  trackParttmp.erase(trackParttmp.begin()+i-1);
313  }
314  }
315 
316  if(! isCorrectNumberOfTracks(m_bdtTagger->ntracks,trackParttmp.size())){
317  ATH_MSG_ERROR("Number of ghost associated tracks wrong!");
318  validVars = false;
319  }
320 
322  for(unsigned i=0; i<trackParttmp.size(); i++){
323  double ipt = trackParttmp.at(i)->pt();
324  double ieta = trackParttmp.at(i)->eta();
325  double iphi = trackParttmp.at(i)->phi();
326  sumPt += ipt;
327  if(undefTrackWidth){
328  double deta_i = trackParttmp.at(i)->eta() - jet.eta();
329  double dphi_i = TVector2::Phi_mpi_pi(trackParttmp.at(i)->phi() - jet.phi());
330  double dR_i = sqrt( deta_i*deta_i + dphi_i*dphi_i );
331  weightedwidth += ipt * dR_i;
332  }
333 
334  for(unsigned j=i+1; j<trackParttmp.size(); j++){
335  double deta = ieta - trackParttmp.at(j)->eta();
336  double dphi = TVector2::Phi_mpi_pi(iphi - trackParttmp.at(j)->phi());
337  double dR = sqrt( deta*deta + dphi*dphi );
338  weightedwidth2 += ipt * trackParttmp.at(j)->pt() * pow(dR,beta);
339  }
340  }
341 
342  if(undefTrackWidth) {
343  m_bdtTagger->trackwidth = sumPt>0 ? weightedwidth/sumPt : -0.1;
344  }
345  m_bdtTagger->trackC1 = sumPt>0 ? weightedwidth2/(sumPt*sumPt) : -0.1;
346 
347  return validVars;
348  }
349 
350  bool JetQGTaggerBDT::isCorrectNumberOfTracks(int expectedNTracks, int nTracksFromGhostTracks) const{
355  if(nTracksFromGhostTracks == 0){
356  if(expectedNTracks == 0)
357  return true;
358  return abs(expectedNTracks-nTracksFromGhostTracks) < 3;
359  }else if(expectedNTracks/nTracksFromGhostTracks < 0.5 && abs(expectedNTracks-nTracksFromGhostTracks) > 5){
360  return false;
361  }
362  return true;
363  }
364 
365 } /* namespace CP */
366 
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
CP::JetQGTaggerBDT::m_BDTmethod
std::string m_BDTmethod
Definition: JetQGTaggerBDT.h:62
xAOD::TrackParticle_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: TrackParticle_v1.cxx:73
CP::JetQGTaggerBDT::tag
virtual StatusCode tag(const xAOD::Jet &jet) const override
IBoostedJetTagger interface.
Definition: JetQGTaggerBDT.cxx:109
JSSTaggerBase::m_funcScoreCut
std::unique_ptr< TF1 > m_funcScoreCut
Definition: JSSTaggerBase.h:199
CP::JetQGTaggerBDT::JetQGTaggerBDT
JetQGTaggerBDT(const std::string &name)
Constructor.
Definition: JetQGTaggerBDT.cxx:15
JSSTaggerBase::resetCuts
StatusCode resetCuts(asg::AcceptData &acceptData) const
Reset cuts.
Definition: JSSTaggerBase.cxx:338
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
JSSTaggerBase::m_jetEtaMax
float m_jetEtaMax
Definition: JSSTaggerBase.h:134
JSSTaggerBase::m_nWarnVar
std::atomic< int > m_nWarnVar
Warning counters.
Definition: JSSTaggerBase.h:86
asg::AnaToolHandle::retrieve
StatusCode retrieve()
initialize the tool
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
JSSTaggerBase::m_configFile
std::string m_configFile
Configuration file name.
Definition: JSSTaggerBase.h:111
CP::JetQGTaggerBDT::m_decScoreKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_decScoreKey
WriteDecorHandle keys.
Definition: JetQGTaggerBDT.h:69
JSSTaggerBase::m_configReader
TEnv m_configReader
TEnv instance to read config files.
Definition: JSSTaggerBase.h:62
JetQGTaggerBDT.h
StateLessPT_NewConfig.Format
Format
Definition: StateLessPT_NewConfig.py:146
CutsMETMaker::accept
StatusCode accept(const xAOD::Muon *mu)
Definition: CutsMETMaker.cxx:18
JSSTaggerBase::m_nWarnMax
const int m_nWarnMax
Maximum number of warnings.
Definition: JSSTaggerBase.h:83
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
JSSTaggerBase::m_jetPtMin
float m_jetPtMin
Kinematic bounds for the jet - the units are controlled by m_ptGeV.
Definition: JSSTaggerBase.h:132
ANA_CHECK
#define ANA_CHECK(EXP)
check whether the given expression was successful
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:324
isValid
bool isValid(const T &p)
Definition: AtlasPID.h:214
ASG_MAKE_ANA_TOOL
#define ASG_MAKE_ANA_TOOL(handle, type)
create the tool in the given tool handle
Definition: AnaToolHandle.h:690
asg::AnaToolHandle::setProperty
StatusCode setProperty(const std::string &property, const T2 &value)
set the given property of the tool.
Phi_mpi_pi
__HOSTDEV__ double Phi_mpi_pi(double)
Definition: GeoRegion.cxx:7
CP
Select isolated Photons, Electrons and Muons.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:48
JSSTaggerBase::m_jetPtMax
float m_jetPtMax
Definition: JSSTaggerBase.h:133
JSSTaggerBase::m_calibArea
std::string m_calibArea
Location where config files live on cvmfs.
Definition: JSSTaggerBase.h:114
AthCommonDataStore< AthCommonMsg< AlgTool > >::evtStore
ServiceHandle< StoreGateSvc > & evtStore()
The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:85
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:92
JSSTaggerBase::m_tmvaConfigFileName
std::string m_tmvaConfigFileName
TMVA configurations for BDT taggers.
Definition: JSSTaggerBase.h:123
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
JSSTaggerBase::checkKinRange
StatusCode checkKinRange(const xAOD::Jet &jet, asg::AcceptData &acceptData) const
Check and record if jet passes kinematic constraints.
Definition: JSSTaggerBase.cxx:370
CP::JetQGTaggerBDT::getJetProperties
bool getJetProperties(const xAOD::Jet &jet, asg::AcceptData &acceptData) const
Update the jet substructure variables for each jet to use in BDT.
Definition: JetQGTaggerBDT.cxx:166
SG::WriteDecorHandle
Handle class for adding a decoration to an object.
Definition: StoreGate/StoreGate/WriteDecorHandle.h:99
xAOD::VxType::PriVtx
@ PriVtx
Primary vertex.
Definition: TrackingPrimitives.h:571
BindingsTest.cut
cut
This script demonstrates how to call a C++ class from Python Also how to use PyROOT is shown.
Definition: BindingsTest.py:13
InDetTrackSelectionTool.h
CP::JetQGTaggerBDT::getScore
float getScore(const xAOD::Jet &jet, asg::AcceptData &acceptData) const
Retrieve BDT score.
Definition: JetQGTaggerBDT.cxx:150
JSSTaggerBase::m_strScoreCut
std::string m_strScoreCut
Definition: JSSTaggerBase.h:194
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
CP::JetQGTaggerBDT::m_trkSelectionTool
asg::AnaToolHandle< InDet::IInDetTrackSelectionTool > m_trkSelectionTool
Definition: JetQGTaggerBDT.h:64
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
JSSTaggerBase
Definition: JSSTaggerBase.h:39
JSSTaggerBase::m_tmvaConfigFilePath
std::string m_tmvaConfigFilePath
Definition: JSSTaggerBase.h:124
CP::JetQGTaggerBDT::m_mode
int m_mode
Definition: JetQGTaggerBDT.h:66
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
JSSTaggerBase::initialize
virtual StatusCode initialize() override
Initialize the tool.
Definition: JSSTaggerBase.cxx:73
JSSTaggerBase::m_acceptInfo
asg::AcceptInfo m_acceptInfo
Object that stores the results for a jet.
Definition: JSSTaggerBase.h:65
InDet::IInDetTrackSelectionTool::accept
virtual asg::AcceptData accept(const xAOD::IParticle *p) const =0
Get the decision using a generic IParticle pointer.
PathResolverFindCalibFile
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:431
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
VertexContainer.h
asg::AcceptData::setCutResult
void setCutResult(const std::string &cutName, bool cutResult)
Set the result of a cut, based on the cut name (safer)
Definition: AcceptData.h:134
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
JSSTaggerBase::passKinRange
bool passKinRange(const xAOD::Jet &jet) const
Check if jet passes kinematic constraints.
Definition: JSSTaggerBase.cxx:356
CP::JetQGTaggerBDT::getPrecomputedVariables
bool getPrecomputedVariables(const xAOD::Jet &jet, asg::AcceptData &acceptData) const
Definition: JetQGTaggerBDT.cxx:195
asg::AcceptData::getCutResult
bool getCutResult(const std::string &cutName) const
Get the result of a cut, based on the cut name (safer)
Definition: AcceptData.h:98
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
JSSTaggerBase::getConfigReader
StatusCode getConfigReader()
Get configReader StatusCode.
Definition: JSSTaggerBase.cxx:300
xAOD::JetAttribute::TrackWidthPt500
@ TrackWidthPt500
Definition: JetAttributes.h:110
InDet::InDetTrackSelectionTool
Implementation of the track selector tool.
Definition: InDetTrackSelectionTool.h:51
CP::JetQGTaggerBDT::calculateVariables
bool calculateVariables(const xAOD::Jet &jet, asg::AcceptData &acceptData) const
Definition: JetQGTaggerBDT.cxx:230
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
CP::JetQGTaggerBDT::initialize
virtual StatusCode initialize() override
Run once at the start of the job to setup everything.
Definition: JetQGTaggerBDT.cxx:34
MuonParameters::beta
@ beta
Definition: MuonParamDefs.h:144
CP::JetQGTaggerBDT::isCorrectNumberOfTracks
bool isCorrectNumberOfTracks(int expectedNTracks, int nTracksFromGhostTracks) const
Definition: JetQGTaggerBDT.cxx:350
asg::AcceptData
Definition: AcceptData.h:30
xAOD::JetAttribute::NumTrkPt500
@ NumTrkPt500
Definition: JetAttributes.h:106
readCCLHist.float
float
Definition: readCCLHist.py:83
DataVector::empty
bool empty() const noexcept
Returns true if the collection is empty.
JSSTaggerBase::m_decTaggedKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_decTaggedKey
WriteDecorHandle keys for tagging bools.
Definition: JSSTaggerBase.h:71
JSSTaggerBase::m_containerName
std::string m_containerName
Configurable members.
Definition: JSSTaggerBase.h:105