ATLAS Offline Software
BTaggingSelectionTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
11 
14 
15 #include "TFile.h"
16 #include "TObjArray.h"
17 #include "TObjString.h"
18 #include "TMatrixD.h"
19 
20 #include <algorithm>
21 #include <string>
22 
23 using std::string;
24 
25 using CP::CorrectionCode;
26 using CP::SystematicSet;
29 
35 using Analysis::Total;
36 using Analysis::SFEigen;
37 using Analysis::SFNamed;
38 using Analysis::None;
39 
40 using xAOD::IParticle;
41 
43  : asg::AsgTool( name ), m_acceptinfo( "JetSelection" )
44 {
45  m_initialised = false;
46  declareProperty( "MaxEta", m_maxEta = 2.5 );
47  declareProperty( "MinPt", m_minPt = -1 /*MeV*/);
48  declareProperty( "MaxRangePt", m_maxRangePt = 3000000 /*MeV*/);
49  declareProperty( "FlvTagCutDefinitionsFileName", m_CutFileName = "", "name of the files containing official cut definitions (uses PathResolver)");
50  declareProperty( "TaggerName", m_taggerName="", "tagging algorithm name");
51  declareProperty( "OperatingPoint", m_OP="", "operating point");
52  declareProperty( "JetAuthor", m_jetAuthor="", "jet collection");
53  declareProperty( "WorkingPointDefinitions", m_wps_raw="FixedCutBEff_85,FixedCutBEff_77,FixedCutBEff_70,FixedCutBEff_60", "Comma-separated list of tagger working points (in decreasing order of efficiency!) - required for 1D tagging purposes");
54  declareProperty( "ErrorOnTagWeightFailure", m_ErrorOnTagWeightFailure=true, "optionally ignore cases where the tagweight cannot be retrived. default behaviour is to give an error, switching to false will turn it into a warning");
55  declareProperty( "CutBenchmarksContinuousWP", m_ContinuousBenchmarks="", "comma separated list of tag bins that will be accepted as tagged: 1,2,3 etc.. ");
56  declareProperty( "useCTagging", m_useCTag=false, "Enabled only for FixedCut or Continuous WPs: define wether the cuts refer to b-tagging or c-tagging");
57 }
58 
60  m_initialised = true;
61 
62  if (""==m_OP){
63  ATH_MSG_ERROR( "BTaggingSelectionTool wasn't given a working point name" );
64  return StatusCode::FAILURE;
65  }
66 
67  TString pathtofile = PathResolverFindCalibFile(m_CutFileName);
68  m_inf = TFile::Open(pathtofile, "read");
69  if (0==m_inf) {
70  ATH_MSG_ERROR( "BTaggingSelectionTool couldn't access tagging cut definitions" );
71  return StatusCode::FAILURE;
72  }
73 
74  // check the CDI file for the selected tagger and jet collection
75  TString check_CDI = m_taggerName;
76  if(!m_inf->Get(check_CDI)){
77  ATH_MSG_ERROR( "Tagger: "+m_taggerName+" not found in this CDI file: "+m_CutFileName);
78  return StatusCode::FAILURE;
79  }
80  check_CDI = m_taggerName+"/"+m_jetAuthor;
81  if(!m_inf->Get(check_CDI)){
82  ATH_MSG_ERROR( "Tagger: "+m_taggerName+" and Jet Collection : "+m_jetAuthor+" not found in this CDI file: "+m_CutFileName);
83  return StatusCode::FAILURE;
84  }
85 
86  //set taggerEnum to avid string comparison:
88 
89  //special requirement for VR TrackJets:
90  if((m_jetAuthor.find("AntiKt2PV0TrackJets") != std::string::npos) ||
91  (m_jetAuthor.find("AntiKt4PV0TrackJets") != std::string::npos) ||
92  (m_jetAuthor.find("AntiKtVR30Rmax4Rmin02TrackJets") != std::string::npos)) {
93  m_StoreNConstituents = true;
94  }
95 
96  // Change the minPt cut if the user didn't touch it
97  if (m_minPt < 0) {
98  ATH_MSG_ERROR( "Tagger: "+m_taggerName+" and Jet Collection : "+m_jetAuthor+" do not have a minimum jet pT cut set.");
99  return StatusCode::FAILURE;
100  }
101 
102  // Operating point reading
103  TString cutname = m_OP;
104  m_continuous = false;
105  m_continuous2D = false;
106 
107  if(cutname.Contains("Continuous2D")){
108  ATH_MSG_INFO("Working with Continuous2D WP.");
109  m_continuous = true;
110  m_continuous2D = true;
111  m_useCTag = false; //important for backward compatibility in getTaggerWeight methods.
112  cutname = m_taggerName+"/"+m_jetAuthor+"/Continuous2D/cutvalue";
114  TMatrixD* matrix = (TMatrixD*) m_inf->Get(cutname);
116 
117  for (int bin = 0; bin < m_tagger.cuts2D->GetNrows(); bin++)
118  ATH_MSG_DEBUG("INITIALIZATION c-cuts : " <<m_tagger.get2DCutValue(bin,0) <<" "
119  <<m_tagger.get2DCutValue(bin,1) <<" b-cuts : "
120  <<m_tagger.get2DCutValue(bin,2) <<" "
121  <<m_tagger.get2DCutValue(bin,3));
122 
123  if (m_tagger.cuts2D == nullptr) ATH_MSG_ERROR( "Invalid operating point" );
124 
125  m_tagger.spline = nullptr;
126 
127  TString fraction_data_name = m_taggerName+"/"+m_jetAuthor+"/Continuous2D/fraction_b";
128  TVector *fraction_data = (TVector*) m_inf->Get(fraction_data_name);
129  if(fraction_data!=nullptr)
130  m_tagger.fraction_b = fraction_data[0](0);
131  else
132  ATH_MSG_ERROR("Tagger fraction_b in Continuous2D WP not available");
133 
134  //now the c-fraction:
135  fraction_data_name = m_taggerName+"/"+m_jetAuthor+"/Continuous2D/fraction_c";
136  fraction_data = (TVector*) m_inf->Get(fraction_data_name);
137  if(fraction_data!=nullptr){
138  m_tagger.fraction_c = fraction_data[0](0);}
139  else{
140  ATH_MSG_ERROR("Tagger fraction_c in Continuous2D WP not available");
141  }
142  } //Continuous2D
143  else if ("Continuous"==cutname(0,10)){ // For continuous tagging load all flat-cut WPs
144  if(m_useCTag)
145  ATH_MSG_WARNING( "Running in Continuous WP and using 1D c-tagging");
146  m_continuous = true;
147  // For GN2v01, we have different WPs than the default ones.
148  if ( m_taggerName == "GN2v01" )
149  m_wps_raw="FixedCutBEff_90,FixedCutBEff_85,FixedCutBEff_77,FixedCutBEff_70,FixedCutBEff_65";
150  std::vector<std::string> workingpoints = split(m_wps_raw, ',');
151  std::sort(workingpoints.begin(), workingpoints.end());
152  std::reverse(workingpoints.begin(), workingpoints.end()); // put in descending order
153  for(const std::string& wp : workingpoints){
154  cutname = m_taggerName + "/" + m_jetAuthor + "/" + wp + "/cutvalue";
155  m_tagger.constcut = (TVector*) m_inf->Get(cutname);
156  if (m_tagger.constcut != nullptr) {
157  m_continuouscuts.push_back(m_tagger.constcut[0](0));
158  } else {
159  ATH_MSG_ERROR( "Continuous tagging is trying to use an invalid operating point: " + wp );
160  }
161  }
162 
163  //The WP is not important. This is just to retrieve the c-fraction.
164  ExtractTaggerProperties(m_tagger, m_taggerName, workingpoints.at(0));
165 
166  } else { // FixedCut Working Point: load only one WP
167  if(m_useCTag){
168  ATH_MSG_WARNING( "Running in FixedCut WP and using c-tagging");
169  }
171  }
172 
173  //set the accept working points, jets in these pseudo-continuous bins will be accepted
174  if(m_continuous){
175  std::vector<std::string> tag_benchmarks_names = split(m_ContinuousBenchmarks, ',');
176  std::vector<int> tag_benchmarks;
177  for (const std::string& tagbin : tag_benchmarks_names){
178  tag_benchmarks.push_back(std::atoi(tagbin.c_str()));
179  ATH_MSG_INFO("adding " <<tag_benchmarks.back() <<" as tagged bin ");
180  }
181  m_tagger.benchmarks = tag_benchmarks;
182  }
183 
184  m_inf->Close();
185 
186  m_acceptinfo.addCut( "Eta", "Selection of jets according to their pseudorapidity" );
187  m_acceptinfo.addCut( "Pt", "Selection of jets according to their transverse momentum" );
188  m_acceptinfo.addCut( "WorkingPoint", "Working point for flavour-tagging of jets according to their b-tagging weight" );
189 
190  return StatusCode::SUCCESS;
191 }
192 
193 void BTaggingSelectionTool::ExtractTaggerProperties(taggerproperties &tagger, const std::string& taggerName, const std::string& OP){
194 
195  TString cutname = OP;
196 
197  //set the name
198  tagger.name = taggerName;
199 
200  if ("FlatBEff"==cutname(0,8) || "HybBEff"==cutname(0,7) ){
201  cutname = taggerName+"/"+m_jetAuthor+"/"+OP+"/cutprofile";
202  tagger.spline = (TSpline3*) m_inf->Get(cutname);
203  if (tagger.spline == nullptr) ATH_MSG_ERROR( "Invalid operating point" );
204  tagger.constcut = nullptr;
205  }
206  else {
207  cutname = taggerName+"/"+m_jetAuthor+"/"+OP+"/cutvalue";
208  tagger.constcut = (TVector*) m_inf->Get(cutname);
209  if (tagger.constcut == nullptr) ATH_MSG_ERROR( "Invalid operating point" );
210  tagger.spline = nullptr;
211  }
212 
213  //retrive the "fraction" used in the DL1 log likelihood from the CDI, if its not there, use the hard coded values
214  // (backwards compatibility)
215  if( (m_taggerEnum == Tagger::DL1) || (m_taggerEnum == Tagger::GN1) || (m_taggerEnum == Tagger::GN2)){
216 
217  TString fraction_data_name = taggerName+"/"+m_jetAuthor+"/"+OP+"/fraction";
218  TVector *fraction_data = (TVector*) m_inf->Get(fraction_data_name);
219 
220  double fraction = -1;
221  if(fraction_data!=nullptr){
222  fraction = fraction_data[0](0);
223  }else{
224  if("DL1" ==taggerName){ fraction = 0.08; }
225  if("DL1mu" ==taggerName){ fraction = 0.08; }
226  if("DL1rnn" ==taggerName){ fraction = 0.03; }
227  }
228  tagger.fraction_c = fraction;
229  tagger.fraction_b = fraction;
230 
231  double fraction_tau = 0.;
232  TString fraction_tau_name = taggerName+"/"+m_jetAuthor+"/"+OP+"/fraction_tau";
233  TVector *fraction_tau_data = (TVector*) m_inf->Get(fraction_tau_name);
234  if( fraction_tau_data != nullptr ) {
235  fraction_tau = fraction_tau_data[0](0);
236  }
237  tagger.fraction_tau = fraction_tau;
238 
239  delete fraction_data;
240  delete fraction_tau_data;
241  }
242 }
243 
245  return getTaggerWeight(jet, tagweight, m_useCTag);
246 }
247 
248 CorrectionCode BTaggingSelectionTool::getTaggerWeight( const xAOD::Jet& jet, double & tagweight, bool getCTagW) const{
249 
250  std::string taggerName = m_tagger.name;
251  // following taggerName change is needed given different name is used for GN2v00 in derivation and in CDI
252  if (taggerName == "GN2v00LegacyWP" || taggerName == "GN2v00NewAliasWP"){
253  taggerName = "GN2v00";
254  }
255  tagweight = -100.;
256 
257  if(!m_continuous2D && (getCTagW != m_useCTag) ){
258  ATH_MSG_ERROR("Difference between initialisation and getTaggerWeight request! useCTagging property set to " <<m_useCTag <<" while getTaggerWeight use c-tag is set to " <<getCTagW <<".");
259  return CorrectionCode::Error;
260  }
261 
262  if ( m_taggerEnum == Tagger::MV2c10 ){
263 
265 
266  if ((!btag) || (!btag->MVx_discriminant(taggerName, tagweight))){
268  ATH_MSG_ERROR("Failed to retrieve "+taggerName+" weight!");
269  return CorrectionCode::Error;
270  }else{
271  ATH_MSG_WARNING("Failed to retrieve "+taggerName+" weight!");
272  return CorrectionCode::Ok;
273  }
274  }
275  ATH_MSG_VERBOSE( taggerName << " " << tagweight );
276  return CorrectionCode::Ok;
277  } //MV2
278  else{
279  //DL1r or DL1
280  double dl1_pb(-10.);
281  double dl1_pc(-10.);
282  double dl1_pu(-10.);
283  double dl1_ptau(0.);
284 
286 
287  if ((!btag)){
288  ATH_MSG_ERROR("Failed to retrieve the BTagging information");
289  return CorrectionCode::Error;
290  }
291 
292  if ( (!btag->pb(taggerName, dl1_pb ))
293  || (!btag->pc(taggerName, dl1_pc ))
294  || (!btag->pu(taggerName, dl1_pu ))
295  || (taggerName=="GN2v01" && !btag->ptau(taggerName, dl1_ptau))){
296 
298  ATH_MSG_ERROR("Failed to retrieve "+taggerName+" weight!");
299  return CorrectionCode::Error;
300  }else{
301  ATH_MSG_WARNING("Failed to retrieve "+taggerName+" weight!");
302  return CorrectionCode::Ok;
303  }
304  }
305 
306  return getTaggerWeight(dl1_pb, dl1_pc, dl1_pu, tagweight, getCTagW, dl1_ptau);
307 
308  }
309 
310  //if we got here the tagger name is not configured properly
311  ATH_MSG_ERROR("BTaggingSelectionTool doesn't support tagger: "+m_taggerName);
312  return CorrectionCode::Error;
313 
314 }
315 
316 CorrectionCode BTaggingSelectionTool::getTaggerWeight( double pb, double pc, double pu, double & tagweight) const{
317  if (m_tagger.name == "GN2v01"){
318  ATH_MSG_ERROR("For GN2v01 tagger, there is a new tau claass in the NN output. Please update your getTaggerWeight() to getTaggerWeight( double pb, double pc, double pu, double & tagweight, double ptau)");
319  return CorrectionCode::Error;
320  } else {
321  return getTaggerWeight(pb, pc, pu, tagweight, m_useCTag, 0.);
322  }
323 }
324 
325 CorrectionCode BTaggingSelectionTool::getTaggerWeight( double pb, double pc, double pu, double & tagweight, double ptau) const{
326  return getTaggerWeight(pb, pc, pu, tagweight, m_useCTag, ptau);
327 }
328 
329 CorrectionCode BTaggingSelectionTool::getTaggerWeight( double pb, double pc, double pu, double & tagweight, bool getCTagW, double ptau) const {
330 
331  std::string taggerName = m_tagger.name;
332 
333  if(!m_continuous2D && (getCTagW != m_useCTag) ){
334  ATH_MSG_ERROR("Difference between initialisation and getTaggerWeight request! useCTagging property set to " <<m_useCTag <<" while getTaggerWeight use c-tag is set to " <<getCTagW <<".");
335  return CorrectionCode::Error;
336  }
337 
338  tagweight = -100.;
339  if( (m_taggerEnum == Tagger::DL1) || (m_taggerEnum == Tagger::GN1) || (m_taggerEnum == Tagger::GN2)){
340 
341  bool valid_input = (!std::isnan(pu) && pb>=0 && pc>=0 && pu>=0 && ptau>=0);
342 
343  if (!valid_input){
345  ATH_MSG_ERROR("Invalid inputs for "+taggerName+" pb " << pb << " pc " << pc << " pu " << pu << " ptau " << ptau << " ");
346  return CorrectionCode::Error;
347  }else{
348  ATH_MSG_WARNING("Invalid inputs for "+taggerName+" pb " << pb << " pc " << pc << " pu " << pu << " ptau " << ptau << " ");
349  return CorrectionCode::Ok;
350  }
351  }
352 
353  if(getCTagW){
354  tagweight = log(pc / (m_tagger.fraction_b * pb + (1. - m_tagger.fraction_b - m_tagger.fraction_tau) * pu + m_tagger.fraction_tau * ptau) );
355  }
356  else{
357  tagweight = log(pb / (m_tagger.fraction_c * pc + (1. - m_tagger.fraction_c - m_tagger.fraction_tau) * pu + m_tagger.fraction_tau * ptau) );
358  }
359 
360  ATH_MSG_VERBOSE( "pb " << pb );
361  ATH_MSG_VERBOSE( "pc " << pc );
362  ATH_MSG_VERBOSE( "pu " << pu );
363  ATH_MSG_VERBOSE( "ptau" << ptau );
364  ATH_MSG_VERBOSE( "tagweight " << tagweight );
365 
366  return CorrectionCode::Ok;
367  }
368 
369  //if we got here the tagger name is not configured properly
370  ATH_MSG_ERROR("this call to getTaggerWeight only works for DL1/GNx taggers");
371  return CorrectionCode::Error;
372 
373 }
374 
375 
376 
378 
379  // Check if this is a jet:
380  if( p->type() != xAOD::Type::Jet ) {
381  ATH_MSG_ERROR( "accept(...) Function received a non-jet" );
382  return asg::AcceptData (&m_acceptinfo);
383  }
384 
385  // Cast it to a jet:
386  const xAOD::Jet* jet = dynamic_cast< const xAOD::Jet* >( p );
387  if( ! jet ) {
388  ATH_MSG_FATAL( "accept(...) Failed to cast particle to jet" );
389  return asg::AcceptData (&m_acceptinfo);
390  }
391 
392  // Let the specific function do the work:
393  return accept( *jet );
394 }
395 
397  asg::AcceptData acceptData (&m_acceptinfo);
398 
399  if (! m_initialised) {
400  ATH_MSG_ERROR("BTaggingSelectionTool has not been initialised");
401  return acceptData;
402  }
403 
405  // We want at least 2 tracks in a track jet
406  acceptData.setCutResult( "NConstituents", jet.numConstituents() >= 2 );
407  }
408 
409  double pT = jet.pt();
410  double eta = jet.eta();
411 
412  if(m_continuous2D){
413  double taggerweight_b(-100);
414  double taggerweight_c(-100);
415  if( (getTaggerWeight( jet, taggerweight_b, false)!=CorrectionCode::Ok) ||
416  (getTaggerWeight( jet, taggerweight_c, true )!=CorrectionCode::Ok) )
417  return acceptData;
418 
419  return accept(pT, eta, taggerweight_b,taggerweight_c);
420  }
421  else{ //if here, we are in 1D mode
422  double taggerweight(-100);
423  if( getTaggerWeight( jet ,taggerweight, m_useCTag)!=CorrectionCode::Ok)
424  return acceptData;
425 
426  return accept(pT, eta, taggerweight);
427  }
428 }
429 
430 asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double tag_weight) const
431 {
432 
433  asg::AcceptData acceptData (&m_acceptinfo);
434 
435  if (! m_initialised) {
436  ATH_MSG_ERROR("BTaggingSelectionTool has not been initialised");
437  return acceptData;
438  }
439 
440  eta = std::abs(eta);
441  if (! checkRange(pT, eta, acceptData))
442  return acceptData;
443 
444  // After initialization, either m_tagger.spline or m_tagger.constcut should be non-zero
445  // Else, the initialization was incorrect and should be revisited
446  if(m_continuous){
447  for(size_t bin : m_tagger.benchmarks){
448  if(bin == 0){
449  throw std::logic_error("bin == 0 in the list of tagged bins. you should not be here. Wrong convention");
450  } else if ( bin == 1 ) {
451  if ( tag_weight < m_continuouscuts.at(bin-1) ) {
452  acceptData.setCutResult( "WorkingPoint", true );
453  }
454  } else if (bin > 1 && bin <= m_continuouscuts.size()){
455  if ( tag_weight > m_continuouscuts.at(bin-2) && tag_weight < m_continuouscuts.at(bin-1) ) {
456  acceptData.setCutResult( "WorkingPoint", true );
457  }
458  } else {
459  if ( tag_weight < m_continuouscuts.at(bin-2) ) {
460  acceptData.setCutResult( "WorkingPoint", true );
461  }
462  }
463  }
464  }
465  else{ //FixedCut
466  double cutvalue(DBL_MAX);
467  if( getCutValue(pT, cutvalue )!=CorrectionCode::Ok ){
468  return acceptData;
469  }
470 
471  if ( tag_weight < cutvalue ){
472  return acceptData;
473  }
474 
475  acceptData.setCutResult( "WorkingPoint", true );
476  }
477 
478  // Return the result:
479  return acceptData;
480 }
481 
482 asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double taggerWeight_b, double taggerWeight_c) const
483 {
484  asg::AcceptData acceptData (&m_acceptinfo);
485 
486  if (! m_initialised) {
487  ATH_MSG_ERROR("BTaggingSelectionTool has not been initialised");
488  return acceptData;
489  }
490 
491  eta = std::abs(eta);
492 
493  if (! checkRange(pT, eta, acceptData))
494  return acceptData;
495 
496  for(auto bin : m_tagger.benchmarks){
497 
498  ATH_MSG_DEBUG("bin" <<bin <<" taggerWeight_c "
499  <<taggerWeight_c <<" taggerWeight_b "
500  <<taggerWeight_b);
501 
502  ATH_MSG_DEBUG(" c-cuts : " <<m_tagger.get2DCutValue(bin,0) <<" "
503  <<m_tagger.get2DCutValue(bin,1) <<" b-cuts : "
504  <<m_tagger.get2DCutValue(bin,2) <<" "
505  <<m_tagger.get2DCutValue(bin,3));
506 
507  if (taggerWeight_c > m_tagger.get2DCutValue(bin,0) && //ctag low
508  taggerWeight_c <= m_tagger.get2DCutValue(bin,1) && //ctag max
509  taggerWeight_b > m_tagger.get2DCutValue(bin,2) && //btag low
510  taggerWeight_b <= m_tagger.get2DCutValue(bin,3) ) //btag max
511  {
512  acceptData.setCutResult( "WorkingPoint", true ); // IF we arrived here, the jet is tagged
513  break;
514  }
515  } //for loop
516 
517  // Return the result:
518  return acceptData;
519 }
520 
521 asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double pb, double pc, double pu) const
522 {
523  if (m_tagger.name == "GN2v01"){
524  asg::AcceptData acceptData (&m_acceptinfo);
525  ATH_MSG_ERROR("For GN2v01 tagger, there is a new tau claass in the NN output. Please update the accept() to accept(double pT, double eta, double pb, double pc, double pu, double ptau)");
526  return acceptData;
527  } else {
528  return accept(pT, eta, pb, pc, pu, 0.);
529  }
530 }
531 
532 asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double pb, double pc, double pu, double ptau) const
533  {
534  asg::AcceptData acceptData (&m_acceptinfo);
535 
536  if (! m_initialised) {
537  ATH_MSG_ERROR("BTaggingSelectionTool has not been initialised");
538  return acceptData;
539  }
540 
541  eta = std::abs(eta);
542  if (! checkRange(pT, eta, acceptData))
543  return acceptData;
544 
545  // After initialization, either m_tagger.spline or m_tagger.constcut should be non-zero
546  // Else, the initialization was incorrect and should be revisited
547  double cutvalue(DBL_MAX);
548 
549  if( getCutValue(pT, cutvalue)!=CorrectionCode::Ok){
550  return acceptData;
551  };
552 
553  if(m_continuous2D){
554  double tagger_weight_b(-100);
555  double tagger_weight_c(-100);
556  if( ( getTaggerWeight(pb, pc, pu, tagger_weight_b, false, ptau)!=CorrectionCode::Ok) ||
557  ( getTaggerWeight(pb, pc, pu, tagger_weight_c, true, ptau)!=CorrectionCode::Ok) )
558  return acceptData;
559  return accept(pT, eta, tagger_weight_b, tagger_weight_c);
560  }
561  else{
562  double tagger_weight(-100);
563  if( getTaggerWeight(pb, pc, pu, tagger_weight, m_useCTag, ptau)!=CorrectionCode::Ok)
564  return acceptData;
565  if ( tagger_weight < cutvalue )
566  return acceptData;
567  }
568  //if you made it here, the jet is tagged
569  acceptData.setCutResult( "WorkingPoint", true );
570  return acceptData;
571  }
572 
574  // Check if this is a jet:
575 
576 
577  if( p->type() != xAOD::Type::Jet ) {
578  ATH_MSG_ERROR( "accept(...) Function received a non-jet" );
579  return -1;
580  }
581 
582  // Cast it to a jet:
583  const xAOD::Jet* jet = dynamic_cast< const xAOD::Jet* >( p );
584  if( ! jet ) {
585  ATH_MSG_FATAL( "accept(...) Failed to cast particle to jet" );
586  return -1;
587  }
588 
589  // Let the specific function do the work:
590  return getQuantile( *jet );
591 }
592 
594  double pT = jet.pt();
595  double eta = std::abs( jet.eta() );
596  int quantile = -1;
597 
598  if (m_continuous2D){
599  double tag_weight_b(-100.);
600  double tag_weight_c(-100.);
601  if ( (getTaggerWeight(jet, tag_weight_b, false) == CP::CorrectionCode::Error) ||
602  (getTaggerWeight(jet, tag_weight_c, true ) == CP::CorrectionCode::Error) ){
603  ATH_MSG_WARNING("getQuantile: Failed to retrieve tag weight for Continuous2D!");
604  return -1;
605  }
606  quantile = getQuantile(pT, eta, tag_weight_b, tag_weight_c );
607  }
608  else{
609  // Retrieve the tagger weight which was assigned to the jet
610  double tag_weight(-100.);
612  ATH_MSG_WARNING("getQuantile: Failed to retrieve "+m_taggerName+" weight!");
613  return -1;
614  }
615  ATH_MSG_VERBOSE( m_taggerName << " " << tag_weight);
616  quantile = getQuantile(pT, eta, tag_weight);
617  }
618  return quantile;
619 }
620 
621 
622 int BTaggingSelectionTool::getQuantile(double pT, double eta, double tag_weight ) const
623 {
624  if (! m_initialised) {
625  ATH_MSG_ERROR("BTaggingSelectionTool has not been initialised");
626  }
628  // Cheatsheet:
629  // With n WPs, (from highest to lowest) A1 , A2, A3, ..., An
630  // return -1 if not in b-tagging acceptance
631  // return 1 if between 100% and A1 (untagged)
632  // return 2 if between A1 and A2 (tagged at the A1 WP)
633  // return 3 if between A2 and A3 (tagged at the A2 WP)
634  // ...
635  // return n if between An-1 and An (tagged at the An-1 WP)
636  // return n+1 if between An and 0% (tagged at the An WP)
638 
639  int bin_index = -1;
640 
641  // First, check if the jet is in acceptance
642  asg::AcceptData acceptData (&m_acceptinfo);
643  if (! checkRange(pT, eta,acceptData)) {
644  return bin_index;
645  }
646 
647  // Now we need to check each threshold in the PCBT vector
648  // and return the maximum WP bin index (1,2,...,n).
649  // Instead of checking low<tag_weight<high for each bin,
650  // we simply check tag_weight<high and therefore range
651  // from vector indices 1 to vector.size()
652  bin_index = 1; // setting the ones that pass selection you have default as 1
653  for (std::size_t i=0; i<m_continuouscuts.size(); i++) {
654  if ( tag_weight > m_continuouscuts.at(i) ) {
655  bin_index++;
656  } else {
657  break;
658  }
659  }
660  return bin_index;
661 }
662 
663 int BTaggingSelectionTool::getQuantile(double pT, double eta, double tag_weight_b, double tag_weight_c ) const
664 {
674 
675  //More details here: https://indico.cern.ch/event/1116952/#4-mr49953-implements-the-conti
676 
677  ATH_MSG_DEBUG("inside getQuantile 2D " <<pT <<" " <<eta <<" " <<tag_weight_b <<" " <<tag_weight_c);
678  int bin_index(-1);
679 
680  asg::AcceptData acceptData (&m_acceptinfo);
681  if (! checkRange(pT, eta, acceptData)) return bin_index;
682 
683  int ncuts = m_tagger.cuts2D->GetNrows();
684  ATH_MSG_VERBOSE("ncuts: " <<ncuts);
685 
686  //loop over all the cuts
687  for(int i = 0; i < ncuts ; i++){
688  double c_cut_low = m_tagger.get2DCutValue(i,0);
689  double c_cut_hig = m_tagger.get2DCutValue(i,1);
690  double b_cut_low = m_tagger.get2DCutValue(i,2);
691  double b_cut_hig = m_tagger.get2DCutValue(i,3);
692 
693  ATH_MSG_DEBUG("bin " <<i <<" c_cut low " <<c_cut_low <<" c_cut hig " <<c_cut_hig <<" c_cut low " <<b_cut_low <<" b_ct hig" <<b_cut_hig);
694  if (tag_weight_c > c_cut_low &&
695  tag_weight_c <= c_cut_hig &&
696  tag_weight_b > b_cut_low &&
697  tag_weight_b <= b_cut_hig){
698  bin_index = i;
699  break;
700  }
701  }
702 
703  ATH_MSG_VERBOSE("bin_index " <<bin_index);
704  return bin_index;
705 }
706 
707 bool BTaggingSelectionTool::checkRange(double pT, double eta,asg::AcceptData& acceptData) const
708 {
709  // Do the |eta| cut:
710  if( std::abs(eta) > m_maxEta ) {
711  return false;
712  }
713  acceptData.setCutResult( "Eta", true );
714 
715  // Do the pT cut:
716  ATH_MSG_VERBOSE( "Jet pT: " << pT );
717  if( pT < m_minPt ) {
718  return false;
719  }
720  acceptData.setCutResult( "Pt", true );
721 
722  return true;
723 }
724 
726 {
727  cutval = DBL_MAX;
728 
729  // flat cut for out of range pTs
730  if (pT>m_maxRangePt)
731  pT = m_maxRangePt;
732 
734 
735  if (tagger.spline != nullptr && tagger.constcut == nullptr) {
736  pT = pT/1000.0;
737  double maxsplinept = tagger.spline->GetXmax();
738  if (pT>maxsplinept){ pT = maxsplinept; }
739  cutval = tagger.spline->Eval(pT);
740  }
741 
742  else if (tagger.constcut != nullptr && tagger.spline == nullptr) {
743  cutval = tagger.constcut[0](0);
744  }
745  else{
746  ATH_MSG_ERROR( "Bad cut configuration!" );
747  return CorrectionCode::Error;
748  }
749 
750 
751  ATH_MSG_VERBOSE( "Cut value " << cutval );
752 
753  return CorrectionCode::Ok;
754 }
755 
756 std::vector<std::string> BTaggingSelectionTool::split (const std::string &input, const char &delimiter){
757  std::vector<std::string> v;
758  std::istringstream buf(input);
759  for(std::string token; std::getline(buf, token, delimiter); )
760  v.push_back(token);
761  return v;
762 }
BTaggingSelectionTool::m_StoreNConstituents
bool m_StoreNConstituents
Definition: BTaggingSelectionTool.h:71
Analysis::CalibResult
std::pair< double, double > CalibResult
Definition: CalibrationDataInterfaceBase.h:34
xAOD::BTagging_v1::ptau
bool ptau(const std::string &taggername, double &value) const
Definition: BTagging_v1.cxx:374
BTaggingUtilities.h
CalculateHighPtTerm.pT
pT
Definition: ICHEP2016/CalculateHighPtTerm.py:57
BTaggingSelectionTool::taggerproperties::fraction_b
double fraction_b
Definition: BTaggingSelectionTool.h:94
BTaggingSelectionTool::m_wps_raw
std::string m_wps_raw
Definition: BTaggingSelectionTool.h:87
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
BTaggingSelectionTool::m_continuous
bool m_continuous
Definition: BTaggingSelectionTool.h:72
BTaggingSelectionTool::initialize
StatusCode initialize() override
Dummy implementation of the initialisation function.
Definition: BTaggingSelectionTool.cxx:59
Analysis::CalibrationDataContainer
Definition: CalibrationDataContainer.h:51
BTaggingSelectionTool::m_maxRangePt
double m_maxRangePt
Definition: BTaggingSelectionTool.h:80
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
BTaggingSelectionTool::m_initialised
bool m_initialised
Definition: BTaggingSelectionTool.h:69
keylayer_zslicemap.pb
pb
Definition: keylayer_zslicemap.py:188
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
BTagging.h
CalibrationDataContainer.h
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:79
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
Analysis::SFNamed
@ SFNamed
Definition: CalibrationDataInterfaceROOT.h:70
BTaggingSelectionTool::m_continuous2D
bool m_continuous2D
Definition: BTaggingSelectionTool.h:73
BTaggingSelectionTool::m_continuouscuts
std::vector< double > m_continuouscuts
Definition: BTaggingSelectionTool.h:90
BTaggingSelectionTool::accept
virtual asg::AcceptData accept(const xAOD::IParticle *p) const override
Get the decision using a generic IParticle pointer.
Definition: BTaggingSelectionTool.cxx:377
asg
Definition: DataHandleTestTool.h:28
CP::SystematicSet
Class to wrap a set of SystematicVariations.
Definition: SystematicSet.h:31
bin
Definition: BinsDiffFromStripMedian.h:43
BTaggingSelectionTool::m_taggerEnum
Tagger m_taggerEnum
Definition: BTaggingSelectionTool.h:113
BTaggingSelectionTool::m_jetAuthor
std::string m_jetAuthor
Definition: BTaggingSelectionTool.h:85
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
CP::SystematicVariation
Definition: SystematicVariation.h:47
CalibrationDataVariables.h
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:40
BTaggingSelectionTool::m_ErrorOnTagWeightFailure
bool m_ErrorOnTagWeightFailure
Definition: BTaggingSelectionTool.h:70
BTaggingSelectionTool::m_acceptinfo
asg::AcceptInfo m_acceptinfo
Object used to store the last decision.
Definition: BTaggingSelectionTool.h:76
BTaggingSelectionTool::taggerproperties::benchmarks
std::vector< int > benchmarks
Definition: BTaggingSelectionTool.h:100
DeMoUpdate.reverse
reverse
Definition: DeMoUpdate.py:563
BTaggingSelectionTool::m_minPt
double m_minPt
Definition: BTaggingSelectionTool.h:79
Analysis::Total
@ Total
Definition: CalibrationDataInterfaceROOT.h:70
BTaggingSelectionTool::m_maxEta
double m_maxEta
Definition: BTaggingSelectionTool.h:78
BTaggingSelectionTool::m_useCTag
bool m_useCTag
Definition: BTaggingSelectionTool.h:74
BTaggingSelectionTool::split
std::vector< std::string > split(const std::string &input, const char &delimiter)
Definition: BTaggingSelectionTool.cxx:756
CP::CorrectionCode::Error
@ Error
Some error happened during the object correction.
Definition: CorrectionCode.h:36
BTaggingSelectionTool::taggerproperties::name
std::string name
Definition: BTaggingSelectionTool.h:93
CalibrationDataInterfaceROOT.h
python.AthDsoLogger.delimiter
delimiter
Definition: AthDsoLogger.py:71
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
BTaggingSelectionTool::getTaggerWeight
virtual CP::CorrectionCode getTaggerWeight(const xAOD::Jet &jet, double &tagweight) const override
Definition: BTaggingSelectionTool.cxx:244
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
xAOD::BTagging_v1::pc
bool pc(const std::string &taggername, double &value) const
Definition: BTagging_v1.cxx:367
lumiFormat.i
int i
Definition: lumiFormat.py:92
SystematicRegistry.h
Analysis::Uncertainty
Uncertainty
specification of type information requested by the user
Definition: CalibrationDataInterfaceROOT.h:70
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
BTaggingSelectionTool::m_tagger
taggerproperties m_tagger
Definition: BTaggingSelectionTool.h:110
BTaggingSelectionTool::taggerproperties::get2DCutValue
double get2DCutValue(int row, int column) const
Definition: BTaggingSelectionTool.h:102
PlotPulseshapeFromCool.input
input
Definition: PlotPulseshapeFromCool.py:106
BTaggingSelectionTool.h
BTaggingSelectionTool::m_taggerName
std::string m_taggerName
Definition: BTaggingSelectionTool.h:83
Analysis::SFEigen
@ SFEigen
Definition: CalibrationDataInterfaceROOT.h:70
BTaggingSelectionTool::m_ContinuousBenchmarks
std::string m_ContinuousBenchmarks
Definition: BTaggingSelectionTool.h:86
PlotSFuncertainty.wp
wp
Definition: PlotSFuncertainty.py:112
xAOD::BTagging_v1
Definition: BTagging_v1.h:39
BTaggingSelectionTool::m_CutFileName
std::string m_CutFileName
Definition: BTaggingSelectionTool.h:82
xAOD::BTagging_v1::pu
bool pu(const std::string &taggername, double &value) const
Definition: BTagging_v1.cxx:353
PathResolver.h
Analysis::CalibrationStatus
CalibrationStatus
Definition: CalibrationDataVariables.h:56
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
BTaggingSelectionTool::taggerproperties::fraction_c
double fraction_c
Definition: BTaggingSelectionTool.h:95
PathResolverFindCalibFile
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:431
xAOD::BTaggingUtilities::getBTagging
const BTagging * getBTagging(const SG::AuxElement &part)
Access the default xAOD::BTagging object associated to an object.
Definition: BTaggingUtilities.cxx:37
CheckAppliedSFs.pu
pu
Definition: CheckAppliedSFs.py:311
python.PyAthena.v
v
Definition: PyAthena.py:157
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
BTaggingSelectionTool::SetTaggerEnum
Tagger SetTaggerEnum(const std::string &taggerName)
Definition: BTaggingSelectionTool.h:115
python.testIfMatch.matrix
matrix
Definition: testIfMatch.py:66
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
BTaggingSelectionTool::taggerproperties
Definition: BTaggingSelectionTool.h:92
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
CP::SystematicRegistry
This module implements the central registry for handling systematic uncertainties with CP tools.
Definition: SystematicRegistry.h:25
BTaggingSelectionTool::getQuantile
virtual int getQuantile(const xAOD::IParticle *) const override
Decide in which quantile of the tag weight distribution the jet belongs (continuous tagging) The retu...
Definition: BTaggingSelectionTool.cxx:573
BTaggingSelectionTool::taggerproperties::spline
TSpline3 * spline
Definition: BTaggingSelectionTool.h:97
Analysis::CalibrationDataVariables
Definition: CalibrationDataVariables.h:42
CP::CorrectionCode
Return value from object correction CP tools.
Definition: CorrectionCode.h:31
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
Analysis::None
@ None
Definition: CalibrationDataInterfaceROOT.h:70
BTaggingSelectionTool::BTaggingSelectionTool
BTaggingSelectionTool(const std::string &name)
Create a proper constructor for Athena.
Definition: BTaggingSelectionTool.cxx:42
CxxUtils::atoi
int atoi(std::string_view str)
Helper functions to unpack numbers decoded in string into integers and doubles The strings are requir...
Definition: Control/CxxUtils/Root/StringUtils.cxx:85
L1Topo::Error
Error
The different types of error that can be flagged in the L1TopoRDO.
Definition: Error.h:16
BTaggingSelectionTool::ExtractTaggerProperties
void ExtractTaggerProperties(taggerproperties &tagger, const std::string &taggerName, const std::string &OP)
Definition: BTaggingSelectionTool.cxx:193
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
BTaggingSelectionTool::taggerproperties::cuts2D
TMatrixD * cuts2D
Definition: BTaggingSelectionTool.h:99
BTaggingSelectionTool::taggerproperties::constcut
TVector * constcut
Definition: BTaggingSelectionTool.h:98
BTaggingSelectionTool::m_inf
TFile * m_inf
Definition: BTaggingSelectionTool.h:89
BTaggingSelectionTool::getCutValue
virtual CP::CorrectionCode getCutValue(double, double &cutval) const override
Definition: BTaggingSelectionTool.cxx:725
asg::AcceptData
Definition: AcceptData.h:30
checker_macros.h
Define macros for attributes used to control the static checker.
BTaggingSelectionTool::checkRange
virtual bool checkRange(double, double, asg::AcceptData &) const
Helper function that decides whether a jet belongs to the correct jet selection for b-tagging.
Definition: BTaggingSelectionTool.cxx:707
BTaggingSelectionTool::m_OP
std::string m_OP
Definition: BTaggingSelectionTool.h:84
xAOD::Jet
Jet_v1 Jet
Definition of the current "jet version".
Definition: Event/xAOD/xAODJet/xAODJet/Jet.h:17
python.SystemOfUnits.pc
float pc
Definition: SystemOfUnits.py:99
BTaggingSelectionTool::taggerproperties::fraction_tau
double fraction_tau
Definition: BTaggingSelectionTool.h:96
asg::AcceptInfo::addCut
int addCut(const std::string &cutName, const std::string &cutDescription)
Add a cut; returning the cut position.
Definition: AcceptInfo.h:53
xAOD::BTagging_v1::MVx_discriminant
bool MVx_discriminant(const std::string &taggername, double &value) const
Definition: BTagging_v1.cxx:381
xAOD::BTagging_v1::pb
bool pb(const std::string &taggername, double &value) const
Definition: BTagging_v1.cxx:360