ATLAS Offline Software
fbtTestBasics.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // System include(s):
6 #include <fstream>
7 #include <map>
8 #include <memory>
9 #include <getopt.h>
10 
11 // ROOT include(s):
12 #include <TSystem.h>
13 #include <TError.h>
14 #include <TFile.h>
15 #include <TH1F.h>
16 
17 #ifdef XAOD_STANDALONE
18 #include "xAODRootAccess/Init.h"
19 #include "xAODRootAccess/TEvent.h"
20 #include "xAODRootAccess/TStore.h"
21 #else
22 #include "POOLRootAccess/TEvent.h"
23 #endif
24 
25 #include "AsgTools/AnaToolHandle.h"
28 #include "xAODEgamma/Electron.h"
29 #include "xAODMuon/Muon.h"
30 #include "AthContainers/Accessor.h"
34 
35 
36 bool successful(bool arg) { return arg; }
37 bool successful(const StatusCode& arg) { return arg.isSuccess(); }
38 
39 #define FBT_CHECK1(x, FAIL) \
40  do { \
41  if(!successful(x)) { \
42  Error("fbtTestBasics", "failure encounted on l.%d", __LINE__); \
43  return FAIL; \
44  } \
45  } while(false)
46 #define FBT_CHECK(x) FBT_CHECK1(x, false)
47 
48 struct Result
49 {
50  float value = 0, statUp = 0, statDown = 0;
51  std::map<CP::SystematicVariation, float> variations;
52  bool operator==(const Result&) const;
53  void Print() const;
54 };
55 
56 #ifdef XAOD_STANDALONE
57 using Store_t = std::unique_ptr<xAOD::TStore>;
58 #else
60 #endif
61 
62 bool allTests(Store_t& store);
63 bool minimalTest(const std::string& type, const std::vector<std::string>& config, Store_t& store, Result& result);
64 bool parallelJob(const std::string& type, const std::vector<std::string>& config, Store_t& store, const std::string& saveAs, int nEvents, int eventOffset);
65 bool readFromROOT(std::vector<std::string>& config);
66 bool readFromXML(std::vector<std::string>& config);
67 
68 template<class Interface = CP::IFakeBkgTool> bool setup(asg::AnaToolHandle<Interface>& tool, const std::string& type, const std::vector<std::string>& config, const std::string& progressFile="");
69 template<class Interface = CP::IFakeBkgTool> bool eventLoop(asg::AnaToolHandle<Interface>& tool, Store_t& store, Result& result, int nEvents, int eventOffset=0);
72 template<class Interface = CP::IFakeBkgTool> bool fillResult(asg::AnaToolHandle<Interface>& tool, Result& result);
73 
74 const std::string selection = ">=1T";
75 const std::string process = ">=1F[T]";
76 const bool readCPVariations = true;
77 const int nEvents = 48;
78 
79 std::atomic<bool> verbose = false; // set once in main
80 
81 int main(int argc, char* argv[])
82 {
83  for(int i=1;i<argc;++i)
84  {
85  std::string option = argv[i];
86  if(option=="-v" || option=="--verbose") verbose = true;
87  }
88 
89 #ifdef XAOD_STANDALONE
90  xAOD::Init("fbtTestBasics").ignore();
92  Store_t store = std::make_unique<xAOD::TStore>();
93  StatusCode::enableFailure();
94 #else
95  IAppMgrUI* app = POOL::Init();
97  FBT_CHECK1( event.evtStore().retrieve(), 1 );
98  Store_t store = event.evtStore().get();
99 #endif
100 
101  int returnCode = allTests(store) ? 0 : 1;
102 
103 #ifndef XAOD_STANDALONE
104  FBT_CHECK1( app->finalize(), 1 );
105 #endif
106  return returnCode;
107 }
108 
110 {
111  std::vector<std::string> config;
112  Result result0, result1, result2, result3, result4, result5;
113 
114  if(verbose) std::cout <<"\nWill do minimal test with CP::ApplyFakeFactor\n";
116  FBT_CHECK( minimalTest("CP::ApplyFakeFactor", config, store, result0) );
117 
118  if(verbose) std::cout <<"\nWill do minimal test with CP::AsymptMatrixTool\n";
119  FBT_CHECK( minimalTest("CP::AsymptMatrixTool", config, store, result1) );
120 
121  if(verbose) std::cout <<"\nWill do minimal test with CP::LhoodMM_tools\n";
122  FBT_CHECK( minimalTest("CP::LhoodMM_tools", config, store, result2) );
123 
124  if(verbose) std::cout <<"\nWill test loading efficiencies from XML\n";
126  FBT_CHECK( minimalTest("CP::AsymptMatrixTool", config, store, result3) );
128  FBT_CHECK( result1 == result3 );
129 
130  if(verbose) std::cout <<"\nWill test getEventWeight()\n";
131  {
133  FBT_CHECK( setup(tool, "CP::AsymptMatrixTool", config) );
134  FBT_CHECK( eventLoop(tool, store, result4, nEvents) );
135  if(verbose) result3.Print();
136  }
137  FBT_CHECK( result1 == result4 );
138 
139  if(verbose) std::cout <<"\nWill test parallel jobs and merging\n";
140  FBT_CHECK( parallelJob("CP::LhoodMM_tools", config, store, "fbt_job1.root", 16, 0) );
141  FBT_CHECK( parallelJob("CP::LhoodMM_tools", config, store, "fbt_job2.root", 16, 16) );
142  FBT_CHECK( parallelJob("CP::LhoodMM_tools", config, store, "fbt_job3.root", 16, 32) );
143  FBT_CHECK( gSystem->Exec("hadd -f fbt_merged.root fbt_job*.root") == 0 );
144  {
146  FBT_CHECK( setup(tool, "CP::LhoodMM_tools", config, "fbt_merged.root") );
147  FBT_CHECK( fillResult(tool, result5) );
148  }
149  FBT_CHECK(result2 == result5 );
150 
151  return true;
152 }
153 
154 bool minimalTest(const std::string& type, const std::vector<std::string>& config, Store_t& store, Result& result)
155 {
160  return true;
161 }
162 
163 bool parallelJob(const std::string& type, const std::vector<std::string>& config, Store_t& store, const std::string& saveAs, int nEvents, int eventOffset)
164 {
167  Result result;
168  FBT_CHECK( eventLoop(tool, store, result, nEvents, eventOffset) );
169  std::unique_ptr<TFile> f(TFile::Open(saveAs.c_str(), "RECREATE"));
170  FBT_CHECK( !!f );
171  FBT_CHECK( tool->saveProgress(f->mkdir("fakes")) );
172  f->Close();
173  if(verbose)
174  {
175  float value, up, down;
176  FBT_CHECK( tool->getTotalYield(value, up, down) );
177  std::cout << "Parallel job stored intermediate yield " << value << " +" << up << " -" << down << std::endl;
178  }
179  return true;
180 }
181 
182 static std::atomic<long> instance = 0;
183 
184 template<class Interface>
185 bool setup(asg::AnaToolHandle<Interface>& tool, const std::string& type, const std::vector<std::string>& config, const std::string& progressFile)
186 {
188  FBT_CHECK( tool.setProperty("InputFiles", config) );
189  FBT_CHECK( tool.setProperty("EnergyUnit", "GeV") );
190  FBT_CHECK( tool.setProperty("ConvertWhenMissing", true) );
191  FBT_CHECK( tool.setProperty("Selection", selection) );
192  FBT_CHECK( tool.setProperty("Process", process) );
193  if(!progressFile.empty())
194  {
195  FBT_CHECK( tool.setProperty("ProgressFileName", progressFile) );
196  FBT_CHECK( tool.setProperty("ProgressFileDirectory", "fakes") );
197  }
198  FBT_CHECK( tool.initialize() );
199  return true;
200 
201 }
202 
203 template<class Interface>
205 {
206  auto eventInfo = std::make_unique<xAOD::EventInfo>();
207  auto eventAuxInfo = std::make_unique<xAOD::EventAuxInfo>();
208  eventInfo->setStore(eventAuxInfo.get());
209  static const SG::Accessor<int> flagAcc("flag");
210  flagAcc(*eventInfo) = 1;
211  FBT_CHECK( store->record(std::move(eventInfo), "EventInfo") );
212  FBT_CHECK( store->record(std::move(eventAuxInfo), "EventInfoAux.") );
213 
215  auto e = std::make_unique<xAOD::Electron>();
216  e->makePrivateStore();
217  e->setCharge(1);
218  particles.push_back(static_cast<xAOD::IParticle*>(&*e));
219  static const SG::Accessor<char> TightAcc("Tight");
220  for(int i=eventOffset;i<nEvents+eventOffset;++i)
221  {
222  e->setP4((1 + (i%3))*1e4, 0., 0. ,0.511);
223  TightAcc(*e) = (i%4)? 0 : 1;
224  FBT_CHECK( tool->addEvent(particles) );
226  }
227 
228 #ifdef XAOD_STANDALONE
229  store->clear();
230 #else
231  FBT_CHECK( store->clearStore(true) );
232 #endif
233  return true;
234 }
235 
237 {
238  FBT_CHECK( tool->applySystematicVariation({}) );
239  float y;
240  FBT_CHECK( tool->getEventWeight(y, selection, process) );
241  result.value += y;
242  result.statUp = sqrt(pow(result.statUp, 2) + y*y);
243  result.statDown = sqrt(pow(result.statDown, 2) + y*y);
244  for(auto& sysvar : tool->affectingSystematics())
245  {
246  FBT_CHECK( tool->applySystematicVariation({sysvar}) );
247  FBT_CHECK( tool->getEventWeight(y, selection, process) );
248  result.variations[sysvar] += y;
249  }
250  return true;
251 }
252 
254 {
255  return true;
256 }
257 
258 template<class Interface>
260 {
261  result.variations.clear();
262  FBT_CHECK( tool->getTotalYield(result.value, result.statUp, result.statDown) );
263  if(readCPVariations)
264  {
265  for(auto& sysvar : tool->affectingSystematics())
266  {
267  FBT_CHECK( tool->applySystematicVariation({sysvar}) );
268  float unused;
269  FBT_CHECK( tool->getTotalYield(result.variations[sysvar], unused, unused) );
270  }
271  }
272  if(verbose) result.Print();
273  return true;
274 }
275 
276 bool Result::operator==(const Result& rhs) const
277 {
278  auto compare = [&](auto x1, auto x2) -> bool
279  {
280  bool closeEnough = std::fabs(x1 - x2) < std::max(1e-5, 1e-3 * std::min(std::fabs(x1), std::fabs(x2)));;
281  if(!closeEnough)
282  {
283  std::cout << "ERROR: found different values for the equality test: " << x1 << " vs " << x2 << std::endl;
284  }
285  return closeEnough;
286  };
287  FBT_CHECK( compare(value, rhs.value) );
288  FBT_CHECK( compare(statUp, rhs.statUp) );
290  FBT_CHECK( variations.size() == rhs.variations.size() );
291  for(auto& kv : variations)
292  {
293  auto itr = rhs.variations.find(kv.first);
294  FBT_CHECK( itr != rhs.variations.end() );
295  FBT_CHECK( compare(kv.second, itr->second) );
296  }
297  return true;
298 }
299 
300 void Result::Print() const
301 {
302  std::cout << "Result: total yield = " << value << " +" << statUp << " -" << statDown << std::endl;
303  for(auto& kv : variations)
304  {
305  std::cout << " variation " << kv.first.name() << " = " << kv.second << std::endl;
306  }
307 }
308 
309 bool readFromROOT(std::vector<std::string>& config)
310 {
311  config.clear();
312  config.emplace_back("fbt_efficiencies.root");
313  TH1D hElFake("FakeEfficiency_el_pt","FakeEfficiency", 1, 10., 100.);
314  hElFake.SetBinContent(1, 0.05);
315  hElFake.SetBinError(1, 0.01);
316  TH1D hMuFake("FakeEfficiency_mu_pt","FakeEfficiency", 1, 10., 100.);
317  hMuFake.SetBinContent(1, 0.15);
318  hMuFake.SetBinError(1, 0.032);
319  TH1D hElReal("RealEfficiency_el_pt","RealEfficiency", 1, 10., 100.);
320  hElReal.SetBinContent(1, 0.90);
321  hElReal.SetBinError(1, 0.01);
322  TH1D hMuReal("RealEfficiency_mu_pt","RealEfficiency", 1, 10., 100.);
323  hMuReal.SetBinContent(1, 0.95);
324  hMuReal.SetBinError(1, 0.01);
325  std::unique_ptr<TFile> f(TFile::Open(config.back().c_str(), "RECREATE"));
326  FBT_CHECK( !!f );
327  f->cd();
328  hElFake.Write();
329  hElReal.Write();
330  hMuFake.Write();
331  hMuReal.Write();
332  f->Close();
333  return true;
334 }
335 
336 bool readFromXML(std::vector<std::string>& config)
337 {
338  config.clear();
339  config.emplace_back("fbt_efficiencies.xml");
340  std::ofstream out(config.back().c_str(), std::ios_base::out);
341  FBT_CHECK( out.is_open() );
344  out << "<efficiencies>\n";
345  out << "<param type=\"int\" level=\"event\"> flag </param>\n";
346  out << "<electron type=\"fake-efficiency\" input=\"central-value\" stat=\"per-bin\" >\n\t<bin flag=\"1\">\n 0.05 +- 0.01 (stat) </bin>\n</electron>\n";
347  out << "<electron type=\"real-efficiency\" input=\"central-value\" stat=\"global\" >\n\t<bin flag=\"1\">\n 0.90 +- 0.01 (stat) </bin>\n</electron>\n";
348  out << "<muon type=\"fake-efficiency\" input=\"central-value\" stat=\"per-bin\" >\n\t<bin flag=\"1\">\n 0.15 +- 0.032 (stat) </bin>\n</muon>\n";
349  out << "<muon type=\"real-efficiency\" input=\"central-value\" stat=\"global\" >\n\t<bin flag=\"1\">\n 0.95 +- 0.01 (stat) </bin>\n</muon>\n";
350  out << "</efficiencies>\n";
351  out.close();
352  return true;
353 }
nEvents
const int nEvents
Definition: fbtTestBasics.cxx:77
verbose
std::atomic< bool > verbose
Definition: fbtTestBasics.cxx:79
readCPVariations
const bool readCPVariations
Definition: fbtTestBasics.cxx:76
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
SGTest::store
TestStore store
Definition: TestStore.cxx:23
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
Amg::compare
std::pair< int, int > compare(const AmgSymMatrix(N) &m1, const AmgSymMatrix(N) &m2, double precision=1e-9, bool relative=false)
compare two matrices, returns the indices of the first element that fails the condition,...
Definition: EventPrimitivesHelpers.h:109
asg::AnaToolHandle
a modified tool handle that allows its owner to configure new tools from the C++ side
Definition: AnaToolHandle.h:34
get_generator_info.result
result
Definition: get_generator_info.py:21
Result::Print
void Print() const
Definition: fbtTestBasics.cxx:300
SG::Accessor< int >
SG::VIEW_ELEMENTS
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
Definition: OwnershipPolicy.h:18
setup
bool setup(asg::AnaToolHandle< Interface > &tool, const std::string &type, const std::vector< std::string > &config, const std::string &progressFile="")
mostly useful for athena, which will otherwise re-use the previous tool
Definition: fbtTestBasics.cxx:185
Muon.h
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
main
int main(int argc, char *argv[])
Definition: fbtTestBasics.cxx:81
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
plotBeamSpotCompare.x2
x2
Definition: plotBeamSpotCompare.py:218
python.base_data.config
config
Definition: base_data.py:21
Result::variations
std::map< CP::SystematicVariation, float > variations
Definition: fbtTestBasics.cxx:51
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
athena.value
value
Definition: athena.py:124
xAOD::TEvent::kClassAccess
@ kClassAccess
Access auxiliary data using the aux containers.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:100
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:41
eventLoop
bool eventLoop(asg::AnaToolHandle< Interface > &tool, Store_t &store, Result &result, int nEvents, int eventOffset=0)
Definition: fbtTestBasics.cxx:204
minimalTest
bool minimalTest(const std::string &type, const std::vector< std::string > &config, Store_t &store, Result &result)
Definition: fbtTestBasics.cxx:154
FBT_CHECK1
#define FBT_CHECK1(x, FAIL)
Definition: fbtTestBasics.cxx:39
successful
bool successful(bool arg)
Definition: fbtTestBasics.cxx:36
config
Definition: PhysicsAnalysis/AnalysisCommon/AssociationUtils/python/config.py:1
POOL::Init
IAppMgrUI * Init(const char *options="POOLRootAccess/basic.opts")
Bootstraps (creates and configures) the Gaudi Application with the provided options file.
Definition: PhysicsAnalysis/POOLRootAccess/src/TEvent.cxx:29
FBT_CHECK
#define FBT_CHECK(x)
Definition: fbtTestBasics.cxx:46
POOL::TEvent::kClassAccess
@ kClassAccess
Definition: PhysicsAnalysis/POOLRootAccess/POOLRootAccess/TEvent.h:46
instance
std::map< std::string, double > instance
Definition: Run_To_Get_Tags.h:8
Result::value
float value
Definition: fbtTestBasics.cxx:50
StoreGateSvc
The Athena Transient Store API.
Definition: StoreGateSvc.h:125
allTests
bool allTests(Store_t &store)
Definition: fbtTestBasics.cxx:109
event
POOL::TEvent event(POOL::TEvent::kClassAccess)
lumiFormat.i
int i
Definition: lumiFormat.py:85
PixelAthClusterMonAlgCfg.e4
e4
Definition: PixelAthClusterMonAlgCfg.py:332
LArCellNtuple.argv
argv
Definition: LArCellNtuple.py:152
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
readFromXML
bool readFromXML(std::vector< std::string > &config)
Definition: fbtTestBasics.cxx:336
ILinearFakeBkgTool.h
MessageCheck.h
macros for messaging and checking status codes
TEvent.h
CalibCoolCompareRT.up
up
Definition: CalibCoolCompareRT.py:109
Init.h
hist_file_dump.f
f
Definition: hist_file_dump.py:135
fillResult
bool fillResult(asg::AnaToolHandle< Interface > &tool, Result &result)
Definition: fbtTestBasics.cxx:259
DQHistogramMergeRegExp.argc
argc
Definition: DQHistogramMergeRegExp.py:20
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
AnaToolHandle.h
create_dcsc_inputs_sqlite.arg
list arg
Definition: create_dcsc_inputs_sqlite.py:48
selection
const std::string selection
Definition: fbtTestBasics.cxx:74
EventAuxInfo.h
POOL::TEvent
Definition: PhysicsAnalysis/POOLRootAccess/POOLRootAccess/TEvent.h:40
TEvent.h
Result
Definition: fbtTestBasics.cxx:49
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
POOL::TEvent::evtStore
ServiceHandle< StoreGateSvc > & evtStore()
Definition: PhysicsAnalysis/POOLRootAccess/POOLRootAccess/TEvent.h:60
AtlCoolConsole.tool
tool
Definition: AtlCoolConsole.py:453
Accessor.h
Helper class to provide type-safe access to aux data.
SGTest::TestStore::record
void record(const T *p, const std::string &key)
Definition: TestStore.h:81
readFromROOT
bool readFromROOT(std::vector< std::string > &config)
Definition: fbtTestBasics.cxx:309
Result::statDown
float statDown
Definition: fbtTestBasics.cxx:50
EventInfo.h
addEventWeight
bool addEventWeight(asg::AnaToolHandle< CP::ILinearFakeBkgTool > &tool, Result &result)
Definition: fbtTestBasics.cxx:236
unused
void unused(Args &&...)
Definition: VP1ExpertSettings.cxx:39
process
const std::string process
Definition: fbtTestBasics.cxx:75
y
#define y
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
LArG4FSStartPointFilter.particles
list particles
Definition: LArG4FSStartPointFilter.py:84
Electron.h
parallelJob
bool parallelJob(const std::string &type, const std::vector< std::string > &config, Store_t &store, const std::string &saveAs, int nEvents, int eventOffset)
Definition: fbtTestBasics.cxx:163
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
TStore.h
xAOD::TEvent
Tool for accessing xAOD files outside of Athena.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:84
Result::statUp
float statUp
Definition: fbtTestBasics.cxx:50
IFakeBkgTool.h
Result::operator==
bool operator==(const Result &) const
Definition: fbtTestBasics.cxx:276
xAOD::Init
StatusCode Init(const char *appname)
Function initialising ROOT/PyROOT for using the ATLAS EDM.
Definition: Init.cxx:31