ATLAS Offline Software
Loading...
Searching...
No Matches
makeHIResponse.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 "TChain.h"
6#include "TChainElement.h"
7#include "TFile.h"
8#include "TH1I.h"
9#include "TH2F.h"
10#include "TH3F.h"
11#include "TObjArray.h"
12
13#include <algorithm>
14#include <cmath>
15#include <cstdio>
16#include <iostream>
17#include <memory>
18#include <unordered_map>
19#include <vector>
20#include <string>
21
25std::unordered_map<int, std::vector<std::pair<int, int>>> getGRLMap(char *grl) {
26 // get rid of everything except the run numbers and LB ranges
27 // also removes the line with all the runs, so each run number is mentioned only once
28 FILE *runList = popen(Form("grep \"Run\\|LBRange\" %s | grep -v Metadata | grep -v GoodRunsListWriter"
29 " | sed -e's/[<>A-Za-z=\"/]//g' -e 's/^ //g' -e 's/ $//g' -e 's/ */ /g' ",
30 grl),
31 "r");
32
33 std::unordered_map<int, std::vector<std::pair<int, int>>> grlMap{};
34 int a, LB1 = 0;
35 int currentRun = -1;
36 while (fscanf(runList, "%d", &a) != EOF) {
37 if (a > 100000) {
38 // new run
39 if(LB1 != 0) {
40 std::cout << "Start of a new run " << a << ", but the previous LB range is not closed, LB1 = "
41 << LB1 << "; check the GRL file " << grl << std::endl;
42 }
43 currentRun = a;
44 continue;
45 } else {
46 // LB
47 if (LB1 == 0) {
48 LB1 = a; // starting LB
49 }
50 else {
51 // ending LB
52 grlMap[currentRun].push_back(std::make_pair(LB1, a));
53 LB1 = 0;
54 continue;
55 }
56 }
57 }
58 int status = pclose(runList);
59 if (status == -1) {
60 std::cout << "Error in pclose" << std::endl;
61 }
62 return grlMap;
63}
64
67std::string getFileNamePattern(std::string name, int runNr) {
68 std::string runStr = Form("%d", runNr);
69 size_t position = 0;
70 while ((position = name.find("%d", position)) != std::string::npos) {
71 name.replace(position, 2, runStr);
72 position += runStr.length();
73 }
74 return name;
75}
76
77
88int main(int argc, char **argv) {
89 if (argc <= 2) {
90 std::cout << "Syntax: " << argv[0] << " GoodRunList.xml /path/to/input/files/first.part. [.second.part [...]]" << std::endl;
91 return -1;
92 }
93
94 auto grlMap = getGRLMap(argv[1]);
96 // for(auto& run : grlMap)
97 // {
98 // std::cout<<"Run "<<run.first<<", size: "<<run.second.size()<<std::endl;
99 // for(auto& lb : run.second)
100 // {
101 // std::cout<<" LB "<<lb.first<<" "<<lb.second<<std::endl;
102 // }
103 // }
104 if (grlMap.size() == 0) {
105 std::cout << "No runs found, is the GRL file (" << argv[1] << ") correct?" << std::endl;
106 return -1;
107 }
108
109 std::vector<int> runs;
110 for (auto &run : grlMap) {
111 runs.push_back(run.first);
112 }
113 std::sort(runs.begin(), runs.end());
114
115 // create run index, since we have all the runs now
116 auto runIndex=std::make_unique<TH1I>("h1_run_index", "h1_run_index", runs.size(), 0, runs.size());
117 for (unsigned int r = 0; r < runs.size(); r++) {
118 runIndex->SetBinContent(r + 1, runs.at(r));
119 }
120
121 // connect all the parts of the file name with a placeholder for a run number
122 std::string fileNameTemplate="";
123 for(int a = 2; a < argc; ++a) {
124 fileNameTemplate += std::string(argv[a]);
125 if (a != argc-1) {
126 // this will be replaced by a run number
127 fileNameTemplate += std::string("%d");
128 }
129 }
130
131 std::unique_ptr<TH3F> response;
132 std::unique_ptr<TH3F> offset;
133 std::unique_ptr<TH3F> entries;
134 std::unique_ptr<TH2F> etaPhiMap;
135
136 // loop over runs
137 for (unsigned int r = 0; r < runs.size(); r++) {
138 int run = runs.at(r);
139 // replace placeholders with the actual run number;
140 std::string fileNamePattern = getFileNamePattern(fileNameTemplate, run);
141
142 std::unique_ptr<TChain> filesChain = std::make_unique<TChain>("");
143 // "Add" also resolves wildcards, if present
144 filesChain->Add(fileNamePattern.c_str());
145 TObjArray * files = filesChain->GetListOfFiles();
146
147 if (files->IsEmpty()) {
148 std::cout << "Could not open any file with pattern " << fileNamePattern << ", skipping the run " << run << std::endl;
149 continue;
150 }
151
152 int filesNum = files->GetEntries();
153 std::cout << "Opened " << filesNum << " file" << (filesNum > 1 ? "s" : "") << " with pattern " << fileNamePattern
154 << ", processing the run " << run << std::endl;
155
156 std::unique_ptr<TH2F> sums;
157
158 // for each file matching the pattern
159 TIter next(files);
160 TChainElement * fileEl = 0;
161 while (( fileEl = (TChainElement*)next() )) {
162 std::unique_ptr<TFile> file = std::make_unique<TFile>(fileEl->GetTitle());
163 std::cout << "Processing file " << file->GetName() << std::endl;
164
165 if (!etaPhiMap) {
166 // when the first file in opened, get the eta-phi mapping
167 etaPhiMap = std::make_unique<TH2F>(*(TH2F*)file->Get<TH2F>("h_etaPhiMapping"));
168 etaPhiMap->SetDirectory(nullptr);
169
170 // book response and offset once eta-phi mapping is known
171 response =
172 std::make_unique<TH3F>("h3_eta_phi_response", "h3_eta_phi_response",
173 etaPhiMap->GetNbinsX(), etaPhiMap->GetXaxis()->GetXmin(), etaPhiMap->GetXaxis()->GetXmax(),
174 etaPhiMap->GetNbinsY(), etaPhiMap->GetYaxis()->GetXmin(), etaPhiMap->GetYaxis()->GetXmax(),
175 runs.size(), 0, runs.size());
176 response->SetDirectory(nullptr);
177 offset = std::make_unique<TH3F>(*(TH3F*)response->Clone("h3_eta_phi_offset"));
178 offset->SetTitle("h3_eta_phi_offset");
179 offset->SetDirectory(nullptr);
180 entries = std::make_unique<TH3F>(*(TH3F*)response->Clone("h3_eta_phi_entries"));
181 entries->SetTitle("h3_eta_phi_entries");
182 entries->SetDirectory(nullptr);
183 }
184
185 // for each range of LBs
186 for (auto &lbs : grlMap[run]) {
187 // for each LB in that range
188 for (int lb = lbs.first; lb <= lbs.second; lb++) {
189 std::unique_ptr<TH2F> tmp(file->Get<TH2F>(Form("h_clusterET_fcalET_%d_%d", run, lb)));
190 if (!tmp) {
191 std::cout << "Could not get h_clusterET_fcalET_" << run << "_" << lb << ", skipping this LB, r = "<<r << std::endl;
192 continue;
193 }
194
195 // merge into a single histogram
196 if (!sums) {
197 sums = std::make_unique<TH2F>(*(TH2F*)tmp->Clone("h_clusterET_fcalET_sum"));
198 sums->SetDirectory(nullptr);
199 }
200 else {
201 sums->Add(tmp.get());
202 }
203 }
204 }
205 }
206
207 if(!sums)
208 {
209 std::cout << "Could not get any LB, skipping the run " << run <<std::endl;
210 continue;
211 }
212
213 // for each bin number
214 for (int binID = 1; binID <= sums->GetNbinsX(); binID++) {
215 float numEntries = sums->GetBinContent(binID, 6);
216 if (numEntries == 0) {
217 // skip empty bins - these are most likely under- and overflow bins
218 continue;
219 }
220
221 int eta, phi, dummy;
222 etaPhiMap->GetBinXYZ(binID - 1, eta, phi, dummy);
223
224 float sumFCalET = sums->GetBinContent(binID, 1);
225 float sumClusterET = sums->GetBinContent(binID, 2);
226 float sumFCalET2 = sums->GetBinContent(binID, 3);
227 // sumClusterET2 is not needed
228 float sumFCalET_clusterET = sums->GetBinContent(binID, 5);
229
230 float avgFCalET = sumFCalET / numEntries;
231 float avgClusterET = sumClusterET / numEntries;
232 float delta = sumFCalET2 - 2 * sumFCalET * avgFCalET + numEntries * avgFCalET * avgFCalET;
233 if (delta == 0) {
234 continue;
235 }
236
237 // response and offset; response is not normalized yet
238 float resp = (sumFCalET_clusterET - sumClusterET * avgFCalET) / delta;
239 float offs = avgClusterET - avgFCalET * resp;
240
241 if (resp < 0) {
242 resp = 0;
243 }
244
245 entries->SetBinContent(eta, phi, r + 1, numEntries);
246 response->SetBinContent(eta, phi, r + 1, resp);
247 offset->SetBinContent(eta, phi, r + 1, offs);
248 }
249 }
250
251 if (!response || !offset) {
252 std::cout << "Could not create response or offset" << std::endl;
253 return -1;
254 }
255
256 entries->GetXaxis()->SetRangeUser(-1.99,1.99);
257 std::unique_ptr<TH1F> avgEntries((TH1F *)entries->Project3D("z"));
258 avgEntries->Scale(1.0 / ((entries->GetXaxis()->GetLast() - entries->GetXaxis()->GetFirst()+1) * entries->GetNbinsY()));
259 entries->GetXaxis()->SetRange(0,0);
260
261 // normalize response in phi
262 for (int r = 1; r <= response->GetNbinsZ(); r++) {
263
264 // use bins with at least 10% of average entries
265 float limitEntries = 0.1 * avgEntries->GetBinContent(r);
266
267 for (int eta = 1; eta <= response->GetNbinsX(); eta++) {
268 int entr = 0;
269 float sum = 0;
270
271 for (int phi = 1; phi <= response->GetNbinsY(); phi++) {
272 if (entries->GetBinContent(eta, phi, r) < limitEntries) {
273 // skip this eta-phi bin
274 continue;
275 }
276 sum += response->GetBinContent(eta, phi, r);
277 ++entr;
278 }
279
280 if(entr > 0) {
281 sum /= entr;
282 }
283 else {
284 sum = 1.0;
285 }
286
287 for (int phi = 1; phi <= response->GetNbinsY(); phi++) {
288 if (entries->GetBinContent(eta, phi, r) < limitEntries) {
289 response->SetBinContent(eta, phi, r, 1.0);
290 offset->SetBinContent(eta, phi, r, 0.0);
291 } else {
292 float resp = response->GetBinContent(eta, phi, r) / sum;
293 if(std::isnan(resp) || resp<=0.) {
294 resp = 1.0;
295 }
296
297 response->SetBinContent(eta, phi, r, resp);
298 }
299 }
300 }
301 }
302
303
304 // save everything
305 std::unique_ptr<TFile> outFile(TFile::Open("cluster.geo.RESPONSE_OFFSET_RUNINDEX.root", "RECREATE"));
306 runIndex->Write();
307 response->Write();
308 offset->Write();
309
310 std::cout << "Created output file cluster.geo.RESPONSE_OFFSET_RUNINDEX.root" << std::endl;
311 return 0;
312}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
static Double_t a
MDT_Response response
int lb
Definition globals.cxx:23
int r
Definition globals.cxx:22
std::vector< std::string > files
file names and file pointers
Definition hcg.cxx:50
int main()
Definition hello.cxx:18
double entries
Definition listroot.cxx:49
std::unordered_map< int, std::vector< std::pair< int, int > > > getGRLMap(char *grl)
Reads the GRL .xml file and creates an unordered map of run numbers and associated LB ranges.
std::string getFileNamePattern(std::string name, int runNr)
Gets a string with "%d" and replaces them with the same run number.
Definition run.py:1
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
TFile * file