ATLAS Offline Software
Loading...
Searching...
No Matches
ElectronDNNCalculator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
13
15#include "TFile.h"
16#include <map>
17#include <fstream>
18#include "lwtnn/parse_json.hh"
19#include "lwtnn/InputOrder.hh"
20#include <Eigen/Dense>
21
22
24 const std::string& modelFileName,
25 const std::string& quantileFileName,
26 const std::vector<std::string>& variables) :
28 m_quantiles(variables.size()),
29 m_variables(variables),
30 m_var_size(variables.size())
31{
32
33 ATH_MSG_INFO("Initializing ElectronDNNCalculator...");
34 for (const auto& var : m_variables) {
35 ATH_MSG_DEBUG("VARIABLE: " << var );
36 }
37 if (modelFileName.empty()){
38 throw std::runtime_error("No file found at '" + modelFileName + "'");
39 }
40
41 // Make an input file object
42 std::ifstream inputFile;
43
44 // Open your trained model
45 ATH_MSG_INFO("Loading model: " << modelFileName.c_str());
46
47 // Create input order for the NN, the data needs to be passed in this exact order
48 lwt::InputOrder order;
49 order.scalar.emplace_back("node_0", m_variables );
50
51 // create the model
52 inputFile.open(modelFileName);
53 auto parsedGraph = lwt::parse_json_graph(inputFile);
54
55 m_graph = std::make_unique<lwt::generic::FastGraph<float>>(parsedGraph, order);
56
57 if (quantileFileName.empty()){
58 throw std::runtime_error("No file found at '" + quantileFileName + "'");
59 }
60
61 // Open quantiletransformer file
62 ATH_MSG_INFO("Loading QuantileTransformer " << quantileFileName);
63 std::unique_ptr<TFile> qtfile(TFile::Open(quantileFileName.data()));
64 if (readQuantileTransformer((TTree*)qtfile->Get("tree")) == 0){
65 throw std::runtime_error("Could not load all variables for the QuantileTransformer");
66
67 }
68}
69
70// takes the input variables, transforms them according to the given QuantileTransformer and predicts the DNN value(s)
71Eigen::Matrix<float, -1, 1> ElectronDNNCalculator::calculate( const std::vector<double>& variableValues ) const
72{
73
74 if(variableValues.size() != m_var_size)
75 throw std::runtime_error("Passed vector of variables has wrong size");
76
77 // Create the input for the model
78 Eigen::VectorXf inputVector(m_variables.size());
79
80 // This has to be in the same order as the InputOrder was defined
81 for(uint i = 0; i < m_var_size; ++i){
82 inputVector(i) = transformInput(m_quantiles.at(i), variableValues.at(i));
83 }
84
85 std::vector<Eigen::VectorXf> inp;
86 inp.emplace_back(std::move(inputVector));
87
88 auto output = m_graph->compute(inp);
89 return output;
90}
91
92
93// transform the input based on a QuantileTransformer. quantiles are bins in the variable, while references are bins from 0 to 1
94// The interpolation is done averaging the interpolation going from small to large bins and going from large to small bins
95// to deal with non strictly monotonic rising bins.
96double ElectronDNNCalculator::transformInput( const std::vector<double>& quantiles, double value ) const
97{
98 int size = quantiles.size();
99
100 // if given value is outside of range of the given quantiles return min (0) or max (1) of references
101 if (value <= quantiles[0]) return m_references[0];
102 if (value >= quantiles[size-1]) return m_references[size-1];
103
104 // find the bin where the value is smaller than the next bin (going from low bins to large bins)
105 auto lowBound = std::lower_bound(quantiles.begin(), quantiles.end(), value);
106 int lowBin = lowBound - quantiles.begin() - 1;
107
108 // get x and y values on left and right side from value while going up
109 double xLup = quantiles[lowBin], yLup = m_references[lowBin], xRup = quantiles[lowBin+1], yRup = m_references[lowBin+1];
110
111 // find the bin where the value is larger than the next bin (going from large bins to low bins)
112 auto upperBound = std::upper_bound(quantiles.begin(), quantiles.end(), value);
113 int upperBin = upperBound - quantiles.begin();
114
115 // get x and y values on left and right side from value while going down
116 double xRdown = quantiles[upperBin], yRdown = m_references[upperBin], xLdown = quantiles[upperBin-1], yLdown = m_references[upperBin-1];
117
118 // calculate the gradients
119 double dydxup = ( yRup - yLup ) / ( xRup - xLup );
120 double dydxdown = ( yRdown - yLdown ) / ( xRdown - xLdown );
121
122 // average linear interpolation of up and down case
123 return 0.5 * ((yLup + dydxup * (value - xLup)) + (yLdown + dydxdown * (value - xLdown)));
124}
125
126
127// Read the information needed for the QuantileTransformer from a ROOT TTree
129{
130 int sc(1);
131 // the reference bins to which the variables will be transformed to
132 double references;
133 sc = tree->SetBranchAddress("references", &references) == -5 ? 0 : 1;
134
135 std::map<std::string, double> readVars;
136 for ( const auto& var : m_variables ){
137 sc = tree->SetBranchAddress(TString(var), &readVars[var]) == -5 ? 0 : 1;
138 }
139
140 for (int ientry = 0; ientry < tree->GetEntries(); ientry++){
141 tree->GetEntry(ientry);
142 m_references.push_back(references);
143 for(uint ivar = 0; ivar < m_var_size; ++ivar){
144 m_quantiles.at(ivar).push_back(readVars[m_variables.at(ivar)]);
145 }
146 }
147 return sc;
148}
149
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_INFO(x,...)
unsigned int uint
static Double_t sc
size_t size() const
Number of registered mappings.
Electron selector tool to select signal electrons using the ElectronDNNCalculator retrieve a score ba...
Eigen::Matrix< float, -1, 1 > calculate(const std::vector< double > &) const
Get the prediction of the DNN model.
std::vector< std::vector< double > > m_quantiles
Quantile values for each variable that needs to be transformed with the QuantileTransformer.
std::unique_ptr< lwt::generic::FastGraph< float > > m_graph
DNN interface via lwtnn.
double transformInput(const std::vector< double > &quantiles, double value) const
transform the input variables according to a given QuantileTransformer.
std::vector< std::string > m_variables
Model variables.
int readQuantileTransformer(TTree *tree)
read the bins and values of the QuantileTransformer to transform the input variables.
std::vector< double > m_references
Reference values for the QuantileTransformer. Basically just equidistant bins between 0 and 1.
ElectronDNNCalculator(AsgElectronSelectorTool *owner, const std::string &modelFileName, const std::string &quantileFileName, const std::vector< std::string > &variablesName)
Constructor of the class.
AsgMessagingForward(T *owner)
forwarding constructor
std::vector< reference > references
Definition hcg.cxx:525
TChain * tree