ATLAS Offline Software
Loading...
Searching...
No Matches
NetworkToHistoTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include <TH1D.h>
6#include <TH2D.h>
8#include "TrkNeuralNetworkUtils/NetworkToHistoTool.hh"
9#include <cmath>
10#include <stdexcept>
11#include <cassert>
12#include <cstdlib> // rand
13#include <format>
14
15std::map<std::string,TH1*>
16NetworkToHistoTool::histsFromNetwork(const TTrainedNetwork* trainedNetwork)
17
18{
19
20 std::map<std::string,TH1*> outputHistos;
21
22
23 assert(trainedNetwork->getActivationFunction() == 1);
24
25 unsigned nInput=trainedNetwork->getnInput();
26 std::vector<Int_t> nHiddenLayerSize=trainedNetwork->getnHiddenLayerSize();
27 Int_t nHidden=nHiddenLayerSize.size();
28
29 Int_t nOutput=trainedNetwork->getnOutput();
30
31 std::vector<TVectorD*> thresholdVectors=trainedNetwork->getThresholdVectors();
32 std::vector<TMatrixD*> weightMatrices=trainedNetwork->weightMatrices();
33
34 //LayersInfo
35 //weak random function, not used for crypto
36 //coverity[dont_call]
37 std::string li_string = std::format("LayersInfo_{}", rand());
38 TH1D* histoLayersInfo=new TH1D(li_string.c_str(),
39 "LayersInfo",
40 nHidden+2,
41 0,
42 nHidden+2);
43
44 histoLayersInfo->SetBinContent(1,nInput);
45
46 for (Int_t i=0;i<nHidden;++i)
47 {
48 histoLayersInfo->SetBinContent(2+i,nHiddenLayerSize[i]);
49 }
50
51 histoLayersInfo->SetBinContent(2+nHidden,nOutput);
52
53 //underflow for linear output
54 if (trainedNetwork->getIfLinearOutput()){
55 histoLayersInfo->SetBinContent(0,1);
56 }
57 //overflow for normalized output (Pott nodes)
58 if (trainedNetwork->getIfNormalizeOutput()){
59 histoLayersInfo->SetBinContent(nHidden+3,1);
60 }
61
62
63 outputHistos["LayersInfo"] = histoLayersInfo;
64
65 //ThresholdInfo
66 for (Int_t i=0;i<nHidden+1;++i)
67 {
68 std::string threName = std::format("Layer{}_thresholds", i);
69
70 Int_t layerSize=(i<nHidden)?nHiddenLayerSize[i]:nOutput;
71 Int_t previousLayerSize=(i==0)?nInput:nHiddenLayerSize[i-1];
72 //weak random function, not used for crypto
73 //coverity[dont_call]
74 std::string th_str = std::format("{}_{}", threName, rand());
75
76 TH1D* histoThreshLayer=new TH1D(th_str.c_str(),
77 threName.c_str(),
78 layerSize,
79 0,
80 layerSize);
81
82 for (Int_t s=0;s<layerSize;s++)
83 {
84 histoThreshLayer->SetBinContent(s+1,(*thresholdVectors[i])(s));
85 }
86
87 std::string weightsName = std::format("Layer{}_weights", i);
88
89 outputHistos[threName] = histoThreshLayer;
90 //weak random function, not used for crypto
91 //coverity[dont_call]
92 std::string wt_str = std::format("{}_{}", weightsName, rand());
93 TH2D* histoWeightsLayer=new TH2D(wt_str.c_str(),
94 weightsName.c_str(),
95 previousLayerSize,
96 0,
97 previousLayerSize,
98 layerSize,
99 0,
100 layerSize);
101
102 for (Int_t s=0;s<layerSize;s++)
103 {
104 for (Int_t p=0;p<previousLayerSize;++p)
105 {
106 histoWeightsLayer->SetBinContent(p+1,s+1,(*weightMatrices[i])(p,s));
107 }
108 }
109
110 outputHistos[weightsName] = histoWeightsLayer;
111
112 }
113
115 std::vector<Input> inputs = trainedNetwork->getInputs();
116
117 if (inputs.empty()) {
118 return outputHistos;
119 }
120 assert(inputs.size() == nInput);
121 //weak random function, not used for crypto
122 //coverity[dont_call]
123 std::string ii_str = std::format("InputsInfo_{}", rand());
124 TH2D* histoInputs = new TH2D(ii_str.c_str(), "InputsInfo",
125 nInput, 0, 1,
126 2, 0, 1);
127
128 for (unsigned input_n = 0; input_n < nInput; input_n++ ) {
129 Input input = inputs.at(input_n);
130 histoInputs->SetBinContent(input_n + 1, 1, input.offset);
131 histoInputs->SetBinContent(input_n + 1, 2, input.scale);
132 histoInputs->GetXaxis()->SetBinLabel(input_n + 1, input.name.c_str());
133 }
134 outputHistos["InputsInfo"] = histoInputs;
135
136 return outputHistos;
137
138}
139
140
142NetworkToHistoTool::networkFromHists(const std::map<std::string,const TH1*>& inputHistos)
143
144{
145 auto getHist = [&inputHistos] (const std::string& name) -> const TH1*
146 {
147 auto it = inputHistos.find (name);
148 if (it == inputHistos.end()) return nullptr;
149 return it->second;
150 };
151
152 const TH1* histoLayersInfo = getHist ("LayersInfo");
153
154 if (histoLayersInfo==nullptr)
155 {
156 throw std::runtime_error(" Could not find LayersInfo histogram...");
157 }
158
159
160 Int_t nHidden=histoLayersInfo->GetNbinsX()-2;
161 unsigned nInput = static_cast<unsigned>
162 (std::floor(histoLayersInfo->GetBinContent(1)+0.5));
163
164 std::vector<Int_t> nHiddenLayerSize;
165 nHiddenLayerSize.reserve(nHidden);
166
167for (Int_t i=0;i<nHidden;++i)
168 {
169 nHiddenLayerSize.push_back( (Int_t)std::floor
170 (histoLayersInfo->GetBinContent(2+i)+0.5));
171 }
172
173 Int_t nOutput=(Int_t)std::floor
174 (histoLayersInfo->GetBinContent(2+nHidden)+0.5);
175
176 unsigned options = 0;
177 if (histoLayersInfo->GetBinContent(0)>0.5)
178 {
180 }
181 if (histoLayersInfo->GetBinContent(nHidden+3)>0.5)
182 {
184 }
185
186
187 std::vector<TVectorD*> thresholdVectors;
188 std::vector<TMatrixD*> weightMatrices;
189
190
191 //Reconstruct thresholdInfo
192 for (Int_t i=0;i<nHidden+1;++i)
193 {
194 std::string threName = std::format("Layer{}_thresholds", i);
195
196 Int_t layerSize=(i<nHidden)?nHiddenLayerSize[i]:nOutput;
197 Int_t previousLayerSize=(i==0)?nInput:nHiddenLayerSize[i-1];
198
199 TVectorD* thresholdVector=new TVectorD(layerSize);
200 TMatrixD* weightMatrix=new TMatrixD(previousLayerSize,layerSize);
201
202 const TH1* histoThreshLayer = getHist (threName);
203 if (!histoThreshLayer)
204 throw std::runtime_error("could not find " + threName);
205
206 if (layerSize != histoThreshLayer->GetNbinsX()) {
207 std::string err = std::format("inconsistency between LayersInfo and {} found: LayersInfo reports {} layers, {} has {} bins", threName, layerSize, threName, histoThreshLayer->GetNbinsX());
208 throw std::runtime_error(err);
209 }
210
211 for (Int_t s=0;s<layerSize;s++)
212 {
213 (*thresholdVector)(s) = histoThreshLayer->GetBinContent(s+1);
214 }
215
216 std::string weightsName = std::format("Layer{}_weights", i);
217
218 const TH1* histoWeightsLayer = getHist (weightsName);
219 if (!histoWeightsLayer) {
220 throw std::runtime_error("could not find " + weightsName);
221 }
222
223 if (layerSize != histoWeightsLayer->GetNbinsY()) {
224 std::string err = std::format("inconsistency between LayersInfo and {} found: LayersInfo reports {} layers, {} has {} bins", weightsName, layerSize, weightsName, histoWeightsLayer->GetNbinsY());
225 throw std::runtime_error(err);
226 }
227
228
229 for (Int_t s=0;s<layerSize;s++)
230 {
231 for (Int_t p=0;p<previousLayerSize;++p)
232 {
233 (*weightMatrix)(p,s) = histoWeightsLayer->GetBinContent(p+1,s+1);
234 }
235 }
236
237 thresholdVectors.push_back(thresholdVector);
238 weightMatrices.push_back(weightMatrix);
239
240 }
241
242 const TH1* histoInputs = getHist ("InputsInfo");
243 std::vector<TTrainedNetwork::Input> inputs;
244 if (!histoInputs) {
245 inputs.resize(nInput);
246 }
247 else {
248 for (unsigned i = 0 ; i < nInput; i++) {
249 const auto & name = histoInputs->GetXaxis()->GetBinLabel(i + 1);
250 const auto & offset = histoInputs->GetBinContent(i + 1, 1);
251 const auto & scale = histoInputs->GetBinContent(i + 1, 2);
252 inputs.emplace_back(name, offset, scale);
253 }
254 }
255 TTrainedNetwork* trainedNetwork =
256 new TTrainedNetwork(inputs,
257 nOutput,
258 thresholdVectors,
259 weightMatrices,
261 options);
262 return trainedNetwork;
263
264}
265
266std::vector<TH1*> NetworkToHistoTool
267::fromTrainedNetworkToHisto(const TTrainedNetwork* net)
268{
269 std::map<std::string, TH1*> hists = histsFromNetwork(net);
270 std::vector<TH1*> hist_vec;
271 for (std::map<std::string, TH1*>::const_iterator itr = hists.begin();
272 itr != hists.end(); ++itr) {
273 itr->second->SetName(itr->first.c_str());
274 hist_vec.push_back(itr->second);
275 }
276 return hist_vec;
277}
278
279TTrainedNetwork* NetworkToHistoTool
280::fromHistoToTrainedNetwork(const std::vector<TH1*>& hists)
281{
282 std::map<std::string, const TH1*> hist_map;
283 for (const TH1* h : hists) {
284 hist_map[h->GetName()] = h;
285 }
286 return networkFromHists(hist_map);
287}
288
289TTrainedNetwork* NetworkToHistoTool
290::fromHistoToTrainedNetwork(const std::vector<const TH1*>& hists)
291{
292 std::map<std::string, const TH1*> hist_map;
293 for (const TH1* h : hists) {
294 hist_map[h->GetName()] = h;
295 }
296 return networkFromHists(hist_map);
297}
NswErrorCalibData::Input Input
Header file for AthHistogramAlgorithm.