ATLAS Offline Software
Loading...
Searching...
No Matches
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"
21#else
23#endif
24
28#include "xAODEgamma/Electron.h"
29#include "xAODMuon/Muon.h"
35
36
37bool successful(bool arg) { return arg; }
38bool 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
49struct 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
58using Store_t = std::unique_ptr<xAOD::TStore>;
59#else
61#endif
62
63bool allTests(Store_t& store);
64bool minimalTest(const std::string& type, const std::vector<std::string>& config, Store_t& store, Result& result);
65bool parallelJob(const std::string& type, const std::vector<std::string>& config, Store_t& store, const std::string& saveAs, int nEvents, int eventOffset);
66bool readFromROOT(std::vector<std::string>& config);
67bool readFromXML(std::vector<std::string>& config);
68
69template<class Interface = CP::IFakeBkgTool> bool setup(asg::AnaToolHandle<Interface>& tool, const std::string& type, const std::vector<std::string>& config, const std::string& progressFile="");
70template<class Interface = CP::IFakeBkgTool> bool eventLoop(asg::AnaToolHandle<Interface>& tool, Store_t& store, Result& result, int nEvents, int eventOffset=0);
73template<class Interface = CP::IFakeBkgTool> bool fillResult(asg::AnaToolHandle<Interface>& tool, Result& result);
74
75const std::string selection = ">=1T";
76const std::string process = ">=1F[T]";
77const bool readCPVariations = true;
78const int nEvents = 48;
79
80std::atomic<bool> verbose = false; // set once in main
81
82int 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
110bool allTests(Store_t& store)
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
155bool minimalTest(const std::string& type, const std::vector<std::string>& config, Store_t& store, Result& result)
156{
158 FBT_CHECK( setup(tool, type, config) );
159 FBT_CHECK( eventLoop(tool, store, result, nEvents) );
160 FBT_CHECK( fillResult(tool, result) );
161 return true;
162}
163
164bool parallelJob(const std::string& type, const std::vector<std::string>& config, Store_t& store, const std::string& saveAs, int nEvents, int eventOffset)
165{
167 FBT_CHECK( setup(tool, type, config) );
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
183static std::atomic<long> instance = 0;
184
185template<class Interface>
186bool setup(asg::AnaToolHandle<Interface>& tool, const std::string& type, const std::vector<std::string>& config, const std::string& progressFile)
187{
188 tool = asg::AnaToolHandle<Interface>(type + "/FBT" + std::to_string(++instance));
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
204template<class Interface>
205bool eventLoop(asg::AnaToolHandle<Interface>& tool, Store_t& store, Result& result, int nEvents, int eventOffset)
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->setPtEtaPhi((1 + (i%3))*1e4, 0., 0.);
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
258
259template<class Interface>
261{
262 result.variations.clear();
263 FBT_CHECK( tool->getTotalYield(result.value, result.statUp, result.statDown) );
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
277bool 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) );
290 FBT_CHECK( compare(statDown, rhs.statDown) );
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
301void 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
310bool 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
337bool 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}
Helper class to provide type-safe access to aux data.
macros for messaging and checking status codes
A number of constexpr particle constants to avoid hardcoding them directly in various places.
std::map< std::string, double > instance
#define y
void unused(Args &&...)
constexpr int pow(int base, int exp) noexcept
void record(const T *p, const std::string &key)
Definition TestStore.h:81
Helper class to provide type-safe access to aux data.
The Athena Transient Store API.
a modified tool handle that allows its owner to configure new tools from the C++ side
Class providing the definition of the 4-vector interface.
Tool for accessing xAOD files outside of Athena.
@ kClassAccess
Access auxiliary data using the aux containers.
const bool readCPVariations
bool successful(bool arg)
bool fillResult(asg::AnaToolHandle< Interface > &tool, Result &result)
bool parallelJob(const std::string &type, const std::vector< std::string > &config, Store_t &store, const std::string &saveAs, int nEvents, int eventOffset)
bool eventLoop(asg::AnaToolHandle< Interface > &tool, Store_t &store, Result &result, int nEvents, int eventOffset=0)
#define FBT_CHECK(x)
bool readFromXML(std::vector< std::string > &config)
bool allTests(Store_t &store)
bool addEventWeight(asg::AnaToolHandle< CP::ILinearFakeBkgTool > &tool, Result &result)
const std::string selection
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
#define FBT_CHECK1(x, FAIL)
const int nEvents
StoreGateSvc * Store_t
const std::string process
bool minimalTest(const std::string &type, const std::vector< std::string > &config, Store_t &store, Result &result)
bool readFromROOT(std::vector< std::string > &config)
bool verbose
Definition hcg.cxx:73
int main()
Definition hello.cxx:18
IAppMgrUI * Init(const char *options="POOLRootAccess/basic.opts")
Bootstraps (creates and configures) the Gaudi Application with the provided options file.
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
StatusCode Init(const char *appname)
Function initialising ROOT/PyROOT for using the ATLAS EDM.
Definition Init.cxx:31
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.
std::map< CP::SystematicVariation, float > variations
void Print() const
bool operator==(const Result &) const
float statUp
float value
float statDown