ATLAS Offline Software
Loading...
Searching...
No Matches
makeHIResponse.cxx File Reference
#include "TChain.h"
#include "TChainElement.h"
#include "TFile.h"
#include "TH1I.h"
#include "TH2F.h"
#include "TH3F.h"
#include "TObjArray.h"
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <memory>
#include <unordered_map>
#include <vector>
#include <string>

Go to the source code of this file.

Functions

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.
int main (int argc, char **argv)
 This macro reads outputs from "HIClusterGeoFiller.py" and performs a linear regression with prepared values.

Function Documentation

◆ getFileNamePattern()

std::string getFileNamePattern ( std::string name,
int runNr )

Gets a string with "%d" and replaces them with the same run number.

It's effectively "Form(...)" that works for an unknown number of placeholders

Definition at line 67 of file makeHIResponse.cxx.

67 {
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}

◆ getGRLMap()

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.

Parameters
grlPath to the GRL .xml file
Returns
unordered map of run numbers (as keys) and vectors of LB ranges (as values)

Definition at line 25 of file makeHIResponse.cxx.

25 {
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}
static Double_t a
status
Definition merge.py:16

◆ main()

int main ( int argc,
char ** argv )

This macro reads outputs from "HIClusterGeoFiller.py" and performs a linear regression with prepared values.

The input file names shall contain the run number. There has to be one file per run; ideally, every run mentioned in the GRL has its corresponding file and every LB mentioned in the GRL has its corresponding histogram in that file. The slope and intercept of the linear regression are written to an output files as response and offset. Response values are normalized to unity along the phi angle, i.e. in each eta slice. In the final root weight file, there are also histograms "h3_w", "h3_eta", "h3_phi", and "h3_R". These are produced by "HICaloGeoExtract.py".

Parameters
argv[1]Path to the GRL .xml file
argv[2],argv[3],...Parts of the path to the input files; blanks are filled with the run number
Returns
Technically integer, practically "cluster.geo.RESPONSE_OFFSET_RUNINDEX.root" file with response, offset, and run index

Definition at line 88 of file makeHIResponse.cxx.

88 {
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
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
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.
outFile
Comment Out Those You do not wish to run.
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