ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
PhysicsAnalysis
JetTagging
FTagScaleFactorTools
src
QuantileFactory.cxx
Go to the documentation of this file.
1
/*
2
Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3
*/
4
#include "
VariableFactory.h
"
5
#include "
QuantileFactory.h
"
6
#include <iostream>
7
using
json
= nlohmann::json;
8
9
std::vector<float>
QuantileFactory::parseEdges
(
const
json
& cfg){
10
std::vector<float> edges;
11
edges.reserve(cfg.size());
12
13
for
(
const
auto
& val : cfg) {
14
if
(val.is_number()) {
15
edges.push_back(val.get<
float
>());
16
}
17
else
if
(val.is_string()) {
18
const
std::string s = val.get<std::string>();
19
20
if
(s ==
"inf"
|| s ==
"+inf"
) {
21
edges.push_back(std::numeric_limits<float>::infinity());
22
}
23
else
if
(s ==
"-inf"
) {
24
edges.push_back(-std::numeric_limits<float>::infinity());
25
}
26
else
{
27
throw
std::runtime_error(
"Invalid edge value: "
+ s);
28
}
29
}
30
else
{
31
throw
std::runtime_error(
"Edge must be a number or \"inf\"/\"-inf\", got:"
+ val.dump());
32
}
33
}
34
35
// Verify edges are strictly sorted ascending — catches malformed JSON early.
36
if
(!std::is_sorted(edges.begin(), edges.end())) {
37
throw
std::runtime_error(
"Bin edges must be sorted in ascending order"
);
38
}
39
40
return
edges;
41
}
42
43
QuantileFactory::QuantileFunc
QuantileFactory::makeCategory
(
const
json
& cfg) {
44
VariableFactory::IntFunc
var =
VariableFactory::intVariableFactory
(cfg.at(
"variable"
));
45
std::vector<int> values = cfg.at(
"values"
).get<std::vector<int>>();
46
int
default_bin = cfg.at(
"default"
).get<
int
>();
47
48
std::unordered_map<int,int> mapping;
49
for
(
int
i = 0; i < static_cast<int>(values.size()); ++i) {
50
mapping[values[i]] = i;
51
}
52
53
auto
func = [var, mapping, default_bin](
const
SG::AuxElement
& el) ->
int
{
54
int
v =
static_cast<
int
>
(var(el));
55
auto
it = mapping.find(v);
56
if
(it != mapping.end()) {
57
return
it->second;
58
}
59
return
default_bin;
60
};
61
62
return
{values.size(), func};
63
64
}
65
66
QuantileFactory::QuantileFunc
QuantileFactory::makeEnumerate
(
const
json
& cfg) {
67
VariableFactory::FloatFunc
var =
VariableFactory::floatVariableFactory
(cfg.at(
"variable"
));
68
std::vector<float> edges =
QuantileFactory::parseEdges
(cfg.at(
"edges"
));
69
70
const
bool
useAbs = cfg.value(
"abs"
,
false
);
71
72
int
underflow_bin = cfg.value(
"underflow_bin"
, -1);
73
int
overflow_bin = cfg.value(
"overflow_bin"
, -1);
74
75
auto
func = [var, edges, useAbs, underflow_bin, overflow_bin] (
const
SG::AuxElement
& el) ->
int
{
76
float
v = var(el);
77
if
(useAbs) v = std::abs(v);
78
79
if
(v < edges.front()) {
80
return
underflow_bin;
81
}
82
if
(v >= edges.back()) {
83
return
overflow_bin;
84
}
85
86
auto
it = std::lower_bound(edges.begin(), edges.end(), v);
87
return
static_cast<
int
>
(std::distance(edges.begin(), it)) - 1;
88
};
89
90
return
{edges.size() - 1, func};
91
}
92
93
// for 2-d tagging
94
QuantileFactory::QuantileFunc
QuantileFactory::makeNodes
(
const
json
& cfg) {
95
VariableFactory::FloatFunc
var =
VariableFactory::floatVariableFactory
(cfg.at(
"variable"
));
96
std::vector<float> edges =
QuantileFactory::parseEdges
(cfg.at(
"edges"
));
97
98
std::vector<std::function<int(
const
SG::AuxElement
&)>> sub_nodes;
99
std::vector<size_t> sub_sizes;
100
101
size_t
totalSize
= 0;
102
103
for
(
const
auto
&
node
: cfg.at(
"nodes"
)) {
104
auto
[
size
, func] =
QuantileFactory::quantileFactory
(
node
);
105
sub_nodes.push_back(func);
106
sub_sizes.push_back(
size
);
107
totalSize
+=
size
;
108
}
109
110
std::string numbering = cfg.value(
"numbering"
,
"sequential"
);
111
112
std::vector<int> offsets(sub_nodes.size(), 0);
113
if
(numbering ==
"sequential"
) {
114
for
(
size_t
i = 1; i < sub_nodes.size(); ++i) {
115
offsets[i] = offsets[i-1] + sub_sizes[i-1];
116
}
117
}
118
119
auto
func = [var, edges, sub_nodes, offsets, numbering]
120
(
const
SG::AuxElement
& el) ->
int
{
121
float
v = var(el);
122
123
auto
it = std::lower_bound(edges.begin(), edges.end(), v);
124
int
region =
static_cast<
int
>
(std::distance(edges.begin(), it)) - 1;
125
if
(region < 0 || region >=
static_cast<
int
>
(edges.size()) - 1) {
126
throw
std::runtime_error(
"Failed to find region for value "
+ std::to_string(v));
127
}
128
129
int
local = sub_nodes[region](el);
130
131
if
(numbering ==
"sequential"
) {
132
return
offsets[region] + local;
133
}
134
return
local;
135
};
136
137
return
{
totalSize
, func};
138
}
139
140
// turn the already computed per-axis bin indices into a flattened index
141
QuantileFactory::QuantileFunc
QuantileFactory::makeDense
(
const
json
& cfg) {
142
std::vector<std::function<int(
const
SG::AuxElement
&)>> axes;
143
std::vector<size_t> axis_sizes;
144
145
for
(
const
auto
& axis : cfg.at(
"axes"
)) {
146
auto
[
size
, func] =
QuantileFactory::quantileFactory
(axis);
147
axes.push_back(func);
148
axis_sizes.push_back(
size
);
149
}
150
151
std::vector<int> strides(axes.size(), 1);
152
for
(
int
i =
static_cast<
int
>
(axes.size()) - 2; i >= 0; --i) {
153
strides[i] = strides[i+1] * axis_sizes[i+1];
154
}
155
156
auto
func = [axes, strides](
const
SG::AuxElement
& el) ->
int
{
157
int
index
= 0;
158
for
(
size_t
i = 0; i < axes.size(); ++i) {
159
int
bin
= axes[i](el);
160
if
(
bin
< 0) {
return
-1;}
161
index
+=
bin
* strides[i];
162
}
163
return
index
;
164
};
165
166
size_t
total_size = 1;
167
for
(
size_t
size
: axis_sizes) {
168
total_size *=
size
;
169
}
170
171
return
{total_size, func};
172
}
173
174
QuantileFactory::QuantileFunc
QuantileFactory::quantileFactory
(
const
json
& cfg) {
175
176
std::string
type
= cfg.at(
"type"
);
177
178
if
(
type
==
"category"
)
return
QuantileFactory::makeCategory
(cfg);
179
if
(
type
==
"enumerate"
)
return
QuantileFactory::makeEnumerate
(cfg);
180
if
(
type
==
"nodes"
)
return
QuantileFactory::makeNodes
(cfg);
181
if
(
type
==
"dense"
)
return
QuantileFactory::makeDense
(cfg);
182
183
throw
std::runtime_error(
"Unknown quantile type: "
+
type
);
184
185
}
186
json
nlohmann::json json
Definition
HistogramDef.cxx:9
totalSize
static unsigned int totalSize(const MultiDimArray< T, N > &ht)
Definition
MultiDimArray.h:310
QuantileFactory.h
size
size_t size() const
Number of registered mappings.
VariableFactory.h
QuantileFactory::QuantileFunc
std::pair< size_t, std::function< int(const SG::AuxElement &)> > QuantileFunc
Definition
QuantileFactory.h:19
QuantileFactory::makeEnumerate
static QuantileFunc makeEnumerate(const nlohmann::json &cfg)
Maps discrete values to category indices.
Definition
QuantileFactory.cxx:66
QuantileFactory::makeNodes
static QuantileFunc makeNodes(const nlohmann::json &cfg)
Builds a tree-based lookup structure for node-based binning, primarily used for pseudo-continuous 2D ...
Definition
QuantileFactory.cxx:94
QuantileFactory::makeDense
static QuantileFunc makeDense(const nlohmann::json &cfg)
Combines multiple binning dimensions into a single flattened global index used for scale factor looku...
Definition
QuantileFactory.cxx:141
QuantileFactory::quantileFactory
static QuantileFunc quantileFactory(const nlohmann::json &cfg)
Dispatch to the appropriate binning scheme based on the JSON config.
Definition
QuantileFactory.cxx:174
QuantileFactory::parseEdges
static std::vector< float > parseEdges(const nlohmann::json &cfg)
Parse an ordered list of bin edges from the JSON config.
Definition
QuantileFactory.cxx:9
QuantileFactory::makeCategory
static QuantileFunc makeCategory(const nlohmann::json &cfg)
Converts a continuous variable into a bin index using an ordered list of bin edges.
Definition
QuantileFactory.cxx:43
VariableFactory::floatVariableFactory
static FloatFunc floatVariableFactory(const nlohmann::json &cfg)
Definition
VariableFactory.cxx:8
VariableFactory::FloatFunc
std::function< float(const SG::AuxElement &)> FloatFunc
Definition
VariableFactory.h:14
VariableFactory::intVariableFactory
static IntFunc intVariableFactory(const nlohmann::json &cfg)
Definition
VariableFactory.cxx:63
VariableFactory::IntFunc
std::function< int(const SG::AuxElement &)> IntFunc
Definition
VariableFactory.h:15
bin
Definition
BinsDiffFromStripMedian.h:43
node
Definition
node.h:24
SG::AuxElement
AuxElement(SG::AuxVectorData *container, size_t index)
Base class for elements of a container that can have aux data.
index
Definition
index.py:1
type
Generated on
for ATLAS Offline Software by
1.17.0