ATLAS Offline Software
Loading...
Searching...
No Matches
AsymptMatrixTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
7
8#include <algorithm>
9#include <numeric>
10
11using namespace FakeBkgTools;
12using namespace CP;
13
18
22
26
31
33{
34 m_cachedWeights.clear();
35
36 m_components.clear();
37 m_derivatives.clear();
38 for(auto& p : m_particles)
39 {
40 double e = p.real_efficiency.nominal, z = p.fake_efficiency.nominal;
41 double den = 1. / (e - z);
42 double delta = p.tight? 1. : 0.;
43 m_components.emplace_back(std::array<double,2>{den*(delta-z), den*(e-delta)});
44 m_derivatives.emplace_back(std::array<double,2>{den*den*(z-delta), den*den*(delta-z)});
45 m_derivatives.emplace_back(std::array<double,2>{den*den*(delta-e), den*den*(e-delta)});
46 }
47
48 return incrementTotalYield();
49}
50
52{
53 const uint64_t n = m_particles.size();
54 const uint64_t nc = (1ull << n);
55
56 std::array<double, maxCombinations()> w;
57 std::array<std::array<double, maxCombinations()>, 2*maxParticles()> dproj_dt;
58
60 std::fill_n(w.begin(), nc, 0.);
61 for(uint64_t k=0;k<2*n;++k) std::fill_n(dproj_dt[k].begin(), nc, 0.);
62
63 auto charges = fs.retrieveCharges(m_particles);
64 std::array<double, maxParticles()+1> effprod;
65 for(uint64_t i=0;i<nc;++i) // loop on tight/loose
66 {
67 FSBitset tights(i);
68 if(!fs.accept_selection(tights, charges)) continue;
69 for(uint64_t j=0;j<nc;++j) // loop on real/fake
70 {
71 FSBitset reals(j);
72 if(!fs.accept_process(n, reals, tights)) continue;
73 std::fill(effprod.begin(), effprod.begin()+n+1, 1.);
74 for(uint64_t k=0;k<n;++k)
75 {
76 double eff = reals[k]? m_particles[k].real_efficiency.nominal : m_particles[k].fake_efficiency.nominal;
77 double x = tights[k]? eff : 1.-eff;
78 effprod[0] *= x;
79 for(uint64_t l=1;l<n+1;++l)
80 {
81 if(l != k+1) effprod[l] *= x;
82 }
83 }
84 auto rev_j = nc-j-1;
85 w[rev_j] += effprod[0];
86 for(uint64_t k=0;k<n;++k) dproj_dt[2*k+!reals[k]][rev_j] += effprod[k+1];
87 }
88 }
89
90
91 std::array<std::array<double, maxCombinations()>, 2*maxParticles()> dlambdaprod_dt;
92 for(uint64_t k=0;k<2*n;++k) std::copy(w.begin(), w.begin()+nc, dlambdaprod_dt[k].begin());
93
94 for(unsigned k=0;k<n;++k)
95 {
96 for(uint64_t j=0;j<nc;++j)
97 {
98 char index = (j>>k)&1;
99 double x = m_components[k][index];
100 w[j] *= x;
101 for(uint64_t u=0;u<n;++u)
102 {
103 dproj_dt[2*u][j] *= x;
104 dproj_dt[2*u+1][j] *= x;
105 if(u != k)
106 {
107 dlambdaprod_dt[2*u][j] *= x;
108 dlambdaprod_dt[2*u+1][j] *= x;
109 }
110 else
111 {
112 dlambdaprod_dt[2*u][j] *= m_derivatives[2*u][index];
113 dlambdaprod_dt[2*u+1][j] *= m_derivatives[2*u+1][index];
114 }
115 }
116 }
117 }
118 weight.nominal = std::accumulate(w.begin(), w.begin()+nc, 0.);
119 auto wu = dlambdaprod_dt.begin(), wv = dproj_dt.begin();
120 for(auto& p : m_particles)
121 {
122 double theta = std::accumulate(wu->begin(), wu->begin()+nc, 0.) + std::accumulate(wv->begin(), wv->begin()+nc, 0.);
123 ++wu;
124 ++wv;
125 for(auto& kv : p.real_efficiency.uncertainties)
126 {
127 auto& uncertainties = weight.uncertainties[kv.first];
128 uncertainties.up += theta * kv.second.up;
129 uncertainties.down += theta * kv.second.down;
130 }
131 theta = std::accumulate(wu->begin(), wu->begin()+nc, 0.) + std::accumulate(wv->begin(), wv->begin()+nc, 0.);
132 ++wu;
133 ++wv;
134 for(auto& kv : p.fake_efficiency.uncertainties)
135 {
136 auto& uncertainties = weight.uncertainties[kv.first];
137 uncertainties.up += theta * kv.second.up;
138 uncertainties.down += theta * kv.second.down;
139 }
140 }
141 return StatusCode::SUCCESS;
142}
Scalar theta() const
theta method
static Double_t fs
#define x
#define z
std::vector< std::array< double, 2 > > m_derivatives
virtual FakeBkgTools::Client clientForDB() override
This indicates which type of efficiencies/fake factor need to be filled.
virtual StatusCode getEventWeightCustom(FakeBkgTools::Weight &weight, const FakeBkgTools::FinalState &fs) override
AsymptMatrixTool(const std::string &name)
virtual StatusCode addEventCustom() override
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
std::vector< std::array< double, 2 > > m_components
std::vector< FakeBkgTools::ParticleData > m_particles
BaseLinearFakeBkgTool(const std::string &toolname)
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
StatusCode incrementTotalYield()
be sure to only call this once per event! (typically at the end of addEvent())
std::map< FakeBkgTools::FinalState, FakeBkgTools::Weight > m_cachedWeights
cached weight+uncertainties for a single event Each tool derived from this base class MUST clear the ...
Select isolated Photons, Electrons and Muons.
constexpr uint64_t maxCombinations()
std::bitset< maxCombinations()> FSBitset
constexpr uint8_t maxParticles()
Definition index.py:1
a structure to hold a weight together with a variable number of systematic uncertainties