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"
35 
36 
37 bool successful(bool arg) { return arg; }
38 bool successful(const StatusCode& arg) { return arg.isSuccess(); }
39 
40 #define FBT_CHECK1(x, FAIL) \
41  do { \
42  if(!successful(x)) { \
43  Error("fbtTestBasics", "failure encounted on l.%d", __LINE__); \
44  return FAIL; \
45  } \
46  } while(false)
47 #define FBT_CHECK(x) FBT_CHECK1(x, false)
48 
49 struct Result
50 {
51  float value = 0, statUp = 0, statDown = 0;
52  std::map<CP::SystematicVariation, float> variations;
53  bool operator==(const Result&) const;
54  void Print() const;
55 };
56 
57 #ifdef XAOD_STANDALONE
58 using Store_t = std::unique_ptr<xAOD::TStore>;
59 #else
61 #endif
62 
63 bool allTests(Store_t& store);
64 bool minimalTest(const std::string& type, const std::vector<std::string>& config, Store_t& store, Result& result);
65 bool parallelJob(const std::string& type, const std::vector<std::string>& config, Store_t& store, const std::string& saveAs, int nEvents, int eventOffset);
66 bool readFromROOT(std::vector<std::string>& config);
67 bool readFromXML(std::vector<std::string>& config);
68 
69 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="");
70 template<class Interface = CP::IFakeBkgTool> bool eventLoop(asg::AnaToolHandle<Interface>& tool, Store_t& store, Result& result, int nEvents, int eventOffset=0);
73 template<class Interface = CP::IFakeBkgTool> bool fillResult(asg::AnaToolHandle<Interface>& tool, Result& result);
74 
75 const std::string selection = ">=1T";
76 const std::string process = ">=1F[T]";
77 const bool readCPVariations = true;
78 const int nEvents = 48;
79 
80 std::atomic<bool> verbose = false; // set once in main
81 
82 int main(int argc, char* argv[])
83 {
84  for(int i=1;i<argc;++i)
85  {
86  std::string option = argv[i];
87  if(option=="-v" || option=="--verbose") verbose = true;
88  }
89 
90 #ifdef XAOD_STANDALONE
91  xAOD::Init("fbtTestBasics").ignore();
93  Store_t store = std::make_unique<xAOD::TStore>();
94  StatusCode::enableFailure();
95 #else
96  IAppMgrUI* app = POOL::Init();
98  FBT_CHECK1( event.evtStore().retrieve(), 1 );
99  Store_t store = event.evtStore().get();
100 #endif
101 
102  int returnCode = allTests(store) ? 0 : 1;
103 
104 #ifndef XAOD_STANDALONE
105  FBT_CHECK1( app->finalize(), 1 );
106 #endif
107  return returnCode;
108 }
109 
111 {
112  std::vector<std::string> config;
113  Result result0, result1, result2, result3, result4, result5;
114 
115  if(verbose) std::cout <<"\nWill do minimal test with CP::ApplyFakeFactor\n";
117  FBT_CHECK( minimalTest("CP::ApplyFakeFactor", config, store, result0) );
118 
119  if(verbose) std::cout <<"\nWill do minimal test with CP::AsymptMatrixTool\n";
120  FBT_CHECK( minimalTest("CP::AsymptMatrixTool", config, store, result1) );
121 
122  if(verbose) std::cout <<"\nWill do minimal test with CP::LhoodMM_tools\n";
123  FBT_CHECK( minimalTest("CP::LhoodMM_tools", config, store, result2) );
124 
125  if(verbose) std::cout <<"\nWill test loading efficiencies from XML\n";
127  FBT_CHECK( minimalTest("CP::AsymptMatrixTool", config, store, result3) );
129  FBT_CHECK( result1 == result3 );
130 
131  if(verbose) std::cout <<"\nWill test getEventWeight()\n";
132  {
134  FBT_CHECK( setup(tool, "CP::AsymptMatrixTool", config) );
135  FBT_CHECK( eventLoop(tool, store, result4, nEvents) );
136  if(verbose) result3.Print();
137  }
138  FBT_CHECK( result1 == result4 );
139 
140  if(verbose) std::cout <<"\nWill test parallel jobs and merging\n";
141  FBT_CHECK( parallelJob("CP::LhoodMM_tools", config, store, "fbt_job1.root", 16, 0) );
142  FBT_CHECK( parallelJob("CP::LhoodMM_tools", config, store, "fbt_job2.root", 16, 16) );
143  FBT_CHECK( parallelJob("CP::LhoodMM_tools", config, store, "fbt_job3.root", 16, 32) );
144  FBT_CHECK( gSystem->Exec("hadd -f fbt_merged.root fbt_job*.root") == 0 );
145  {
147  FBT_CHECK( setup(tool, "CP::LhoodMM_tools", config, "fbt_merged.root") );
148  FBT_CHECK( fillResult(tool, result5) );
149  }
150  FBT_CHECK(result2 == result5 );
151 
152  return true;
153 }
154 
155 bool minimalTest(const std::string& type, const std::vector<std::string>& config, Store_t& store, Result& result)
156 {
161  return true;
162 }
163 
164 bool parallelJob(const std::string& type, const std::vector<std::string>& config, Store_t& store, const std::string& saveAs, int nEvents, int eventOffset)
165 {
168  Result result;
169  FBT_CHECK( eventLoop(tool, store, result, nEvents, eventOffset) );
170  std::unique_ptr<TFile> f(TFile::Open(saveAs.c_str(), "RECREATE"));
171  FBT_CHECK( !!f );
172  FBT_CHECK( tool->saveProgress(f->mkdir("fakes")) );
173  f->Close();
174  if(verbose)
175  {
176  float value, up, down;
177  FBT_CHECK( tool->getTotalYield(value, up, down) );
178  std::cout << "Parallel job stored intermediate yield " << value << " +" << up << " -" << down << std::endl;
179  }
180  return true;
181 }
182 
183 static std::atomic<long> instance = 0;
184 
185 template<class Interface>
186 bool setup(asg::AnaToolHandle<Interface>& tool, const std::string& type, const std::vector<std::string>& config, const std::string& progressFile)
187 {
189  FBT_CHECK( tool.setProperty("InputFiles", config) );
190  FBT_CHECK( tool.setProperty("EnergyUnit", "GeV") );
191  FBT_CHECK( tool.setProperty("ConvertWhenMissing", true) );
192  FBT_CHECK( tool.setProperty("Selection", selection) );
193  FBT_CHECK( tool.setProperty("Process", process) );
194  if(!progressFile.empty())
195  {
196  FBT_CHECK( tool.setProperty("ProgressFileName", progressFile) );
197  FBT_CHECK( tool.setProperty("ProgressFileDirectory", "fakes") );
198  }
199  FBT_CHECK( tool.initialize() );
200  return true;
201 
202 }
203 
204 template<class Interface>
206 {
207  auto eventInfo = std::make_unique<xAOD::EventInfo>();
208  auto eventAuxInfo = std::make_unique<xAOD::EventAuxInfo>();
209  eventInfo->setStore(eventAuxInfo.get());
210  static const SG::Accessor<int> flagAcc("flag");
211  flagAcc(*eventInfo) = 1;
212  FBT_CHECK( store->record(std::move(eventInfo), "EventInfo") );
213  FBT_CHECK( store->record(std::move(eventAuxInfo), "EventInfoAux.") );
214 
216  auto e = std::make_unique<xAOD::Electron>();
217  e->makePrivateStore();
218  e->setCharge(1);
219  particles.push_back(static_cast<xAOD::IParticle*>(&*e));
220  static const SG::Accessor<char> TightAcc("Tight");
221  for(int i=eventOffset;i<nEvents+eventOffset;++i)
222  {
223  e->setP4((1 + (i%3))*1e4, 0., 0. ,ParticleConstants::electronMassInMeV);
224  TightAcc(*e) = (i%4)? 0 : 1;
225  FBT_CHECK( tool->addEvent(particles) );
227  }
228 
229 #ifdef XAOD_STANDALONE
230  store->clear();
231 #else
232  FBT_CHECK( store->clearStore(true) );
233 #endif
234  return true;
235 }
236 
238 {
239  FBT_CHECK( tool->applySystematicVariation({}) );
240  float y;
241  FBT_CHECK( tool->getEventWeight(y, selection, process) );
242  result.value += y;
243  result.statUp = sqrt(pow(result.statUp, 2) + y*y);
244  result.statDown = sqrt(pow(result.statDown, 2) + y*y);
245  for(auto& sysvar : tool->affectingSystematics())
246  {
247  FBT_CHECK( tool->applySystematicVariation({sysvar}) );
248  FBT_CHECK( tool->getEventWeight(y, selection, process) );
249  result.variations[sysvar] += y;
250  }
251  return true;
252 }
253 
255 {
256  return true;
257 }
258 
259 template<class Interface>
261 {
262  result.variations.clear();
263  FBT_CHECK( tool->getTotalYield(result.value, result.statUp, result.statDown) );
264  if(readCPVariations)
265  {
266  for(auto& sysvar : tool->affectingSystematics())
267  {
268  FBT_CHECK( tool->applySystematicVariation({sysvar}) );
269  float unused;
270  FBT_CHECK( tool->getTotalYield(result.variations[sysvar], unused, unused) );
271  }
272  }
273  if(verbose) result.Print();
274  return true;
275 }
276 
277 bool Result::operator==(const Result& rhs) const
278 {
279  auto compare = [&](auto x1, auto x2) -> bool
280  {
281  bool closeEnough = std::fabs(x1 - x2) < std::max(1e-5, 1e-3 * std::min(std::fabs(x1), std::fabs(x2)));;
282  if(!closeEnough)
283  {
284  std::cout << "ERROR: found different values for the equality test: " << x1 << " vs " << x2 << std::endl;
285  }
286  return closeEnough;
287  };
288  FBT_CHECK( compare(value, rhs.value) );
289  FBT_CHECK( compare(statUp, rhs.statUp) );
291  FBT_CHECK( variations.size() == rhs.variations.size() );
292  for(auto& kv : variations)
293  {
294  auto itr = rhs.variations.find(kv.first);
295  FBT_CHECK( itr != rhs.variations.end() );
296  FBT_CHECK( compare(kv.second, itr->second) );
297  }
298  return true;
299 }
300 
301 void Result::Print() const
302 {
303  std::cout << "Result: total yield = " << value << " +" << statUp << " -" << statDown << std::endl;
304  for(auto& kv : variations)
305  {
306  std::cout << " variation " << kv.first.name() << " = " << kv.second << std::endl;
307  }
308 }
309 
310 bool readFromROOT(std::vector<std::string>& config)
311 {
312  config.clear();
313  config.emplace_back("fbt_efficiencies.root");
314  TH1D hElFake("FakeEfficiency_el_pt","FakeEfficiency", 1, 10., 100.);
315  hElFake.SetBinContent(1, 0.05);
316  hElFake.SetBinError(1, 0.01);
317  TH1D hMuFake("FakeEfficiency_mu_pt","FakeEfficiency", 1, 10., 100.);
318  hMuFake.SetBinContent(1, 0.15);
319  hMuFake.SetBinError(1, 0.032);
320  TH1D hElReal("RealEfficiency_el_pt","RealEfficiency", 1, 10., 100.);
321  hElReal.SetBinContent(1, 0.90);
322  hElReal.SetBinError(1, 0.01);
323  TH1D hMuReal("RealEfficiency_mu_pt","RealEfficiency", 1, 10., 100.);
324  hMuReal.SetBinContent(1, 0.95);
325  hMuReal.SetBinError(1, 0.01);
326  std::unique_ptr<TFile> f(TFile::Open(config.back().c_str(), "RECREATE"));
327  FBT_CHECK( !!f );
328  f->cd();
329  hElFake.Write();
330  hElReal.Write();
331  hMuFake.Write();
332  hMuReal.Write();
333  f->Close();
334  return true;
335 }
336 
337 bool readFromXML(std::vector<std::string>& config)
338 {
339  config.clear();
340  config.emplace_back("fbt_efficiencies.xml");
341  std::ofstream out(config.back().c_str(), std::ios_base::out);
342  FBT_CHECK( out.is_open() );
345  out << "<efficiencies>\n";
346  out << "<param type=\"int\" level=\"event\"> flag </param>\n";
347  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";
348  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";
349  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";
350  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";
351  out << "</efficiencies>\n";
352  out.close();
353  return true;
354 }
nEvents
const int nEvents
Definition: fbtTestBasics.cxx:78
verbose
std::atomic< bool > verbose
Definition: fbtTestBasics.cxx:80
readCPVariations
const bool readCPVariations
Definition: fbtTestBasics.cxx:77
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:301
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:186
Muon.h
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
main
int main(int argc, char *argv[])
Definition: fbtTestBasics.cxx:82
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:52
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:101
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:205
minimalTest
bool minimalTest(const std::string &type, const std::vector< std::string > &config, Store_t &store, Result &result)
Definition: fbtTestBasics.cxx:155
FBT_CHECK1
#define FBT_CHECK1(x, FAIL)
Definition: fbtTestBasics.cxx:40
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
successful
bool successful(bool arg)
Definition: fbtTestBasics.cxx:37
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:47
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:51
StoreGateSvc
The Athena Transient Store API.
Definition: StoreGateSvc.h:120
allTests
bool allTests(Store_t &store)
Definition: fbtTestBasics.cxx:110
event
POOL::TEvent event(POOL::TEvent::kClassAccess)
ParticleConstants.h
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:337
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:141
fillResult
bool fillResult(asg::AnaToolHandle< Interface > &tool, Result &result)
Definition: fbtTestBasics.cxx:260
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:75
EventAuxInfo.h
POOL::TEvent
Definition: PhysicsAnalysis/POOLRootAccess/POOLRootAccess/TEvent.h:40
TEvent.h
Result
Definition: fbtTestBasics.cxx:50
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:310
Result::statDown
float statDown
Definition: fbtTestBasics.cxx:51
EventInfo.h
addEventWeight
bool addEventWeight(asg::AnaToolHandle< CP::ILinearFakeBkgTool > &tool, Result &result)
Definition: fbtTestBasics.cxx:237
unused
void unused(Args &&...)
Definition: VP1ExpertSettings.cxx:39
process
const std::string process
Definition: fbtTestBasics.cxx:76
y
#define y
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:164
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:85
Result::statUp
float statUp
Definition: fbtTestBasics.cxx:51
IFakeBkgTool.h
Result::operator==
bool operator==(const Result &) const
Definition: fbtTestBasics.cxx:277
xAOD::Init
StatusCode Init(const char *appname)
Function initialising ROOT/PyROOT for using the ATLAS EDM.
Definition: Init.cxx:31
ParticleConstants::PDG2011::electronMassInMeV
constexpr double electronMassInMeV
the mass of the electron (in MeV)
Definition: ParticleConstants.h:26