ATLAS Offline Software
Loading...
Searching...
No Matches
AFP_NoisyPixelTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include <iostream>
7
8
9int AFP_NoisyPixelTool::Identify(std::shared_ptr<const TH2F> input, std::vector<TH2F>& output) const
10{
11 if(output.size()!=1)
12 {
13 return 0;
14 }
15
16 output[0].Reset();
17 output.resize(4, output[0]);//container now has 4 copies of the 0'th element
18 auto name = [&output](const char * n)->TString{
19 return Form(n,output[0].GetName());
20 };
21 auto title = [&output](const char * t)->TString{
22 return Form(t,output[0].GetTitle());
23 };
24 output[1].SetNameTitle(name("leffpixels_found_%s"), title("low efficiency pixels, found, %s"));
25 output[2].SetNameTitle(name("noisypixels_eff_%s"), title("noisy pixels, efficiency, %s"));
26 output[3].SetNameTitle(name("leffpixels_eff_%s"), title("low efficiency pixels, efficiency, %s"));
27 output[0].SetNameTitle(name("noisypixels_found_%s"), title("noisy pixels, found, %s"));
28
29 TH2F& noisypixels_found_output = output[0];
30 TH2F& leffpixels_found_output = output[1];
31 TH2F& noisypixels_eff_output = output[2];
32 TH2F& leffpixels_eff_output = output[3];
33
34
35 if(input->GetMaximum()<0.5) return 0;
36
37 std::vector<TH2F> vec_found_leff{},vec_found_noisy{},vec_eff_leff{},vec_eff_noisy{};
38
39 for(const auto& method : m_methods)
40 {
41 TH2F tmp_eff_noisy, tmp_eff_leff;
42 TH2F tmp_found_leff, tmp_found_noisy;
43
44 if(method!="FIT")
45 {
46 // count inactive pixels around each pixel
47 TH2F tmp_inact_pix_around=countInactivePixelsAround(input);
48
49 // find low eff. and noisy pixels
50 std::tie(tmp_found_leff,tmp_found_noisy,tmp_eff_leff, tmp_eff_noisy) = findLEffAndNoisyPixels(input, tmp_inact_pix_around, method);
51
52 // reconsider some pixels
53 filterLEffPixelsAroundNoisy(input, tmp_inact_pix_around, tmp_found_leff,tmp_found_noisy,tmp_eff_leff,tmp_eff_noisy, method);
54 }
55 else
56 {
57 // method is "FIT"
58
59 tmp_eff_noisy=TH2F(*input);
60 tmp_eff_noisy.SetName("tmp_eff_noisy");
61 tmp_eff_noisy.Reset();
62 tmp_eff_leff=TH2F(*input);
63 tmp_eff_leff.SetName("tmp_eff_leff");
64 tmp_eff_leff.Reset();
65 tmp_found_noisy=TH2F(*input);
66 tmp_found_noisy.SetName("tmp_found_noisy");
67 tmp_found_noisy.Reset();
68 tmp_found_leff=TH2F(*input);
69 tmp_found_leff.SetName("tmp_found_leff");
70 tmp_found_leff.Reset();
71
72 auto p=makeFits(input);
73
74 const double Threshold_LEFF=5.;
75 const double Threshold_NOISY=(m_threshNoisy-1)*100;
76
77 for(int col_ID=1; col_ID<=input->GetNbinsY(); col_ID++)
78 {
79 for(int row_ID=1; row_ID<=input->GetNbinsX(); row_ID++)
80 {
81 double ratio_leff=0, ratio_noisy=0;
82 double gauss_helper_12 = (col_ID-p[1][row_ID])/p[2][row_ID];
83 double gauss_helper_45 = (col_ID-p[4][row_ID])/p[5][row_ID];
84 double fit = p[0][row_ID]*exp(-0.5*gauss_helper_12*gauss_helper_12)
85 + p[3][row_ID]*exp(-0.5*gauss_helper_45*gauss_helper_45) + p[6][row_ID];
86 double sigma=std::sqrt(fit);
87 if(sigma<1) sigma=1;
88
89 double bin_content=input->GetBinContent(row_ID,col_ID);
90
91 if(fit>=bin_content) ratio_leff = std::abs(fit-bin_content)/sigma;
92 else ratio_noisy = std::abs(fit-bin_content)/sigma;
93
94 if(bin_content!=0)
95 {
96 if( ratio_leff > Threshold_LEFF) tmp_found_leff.SetBinContent(row_ID,col_ID,1);
97 if( ratio_noisy > Threshold_NOISY) tmp_found_noisy.SetBinContent(row_ID,col_ID,1);
98 }
99 tmp_eff_leff.SetBinContent(row_ID,col_ID,100.*ratio_leff);
100 tmp_eff_noisy.SetBinContent(row_ID,col_ID,100.*ratio_noisy);
101 }
102 }
103 }
104
105 // save output for this method
106 vec_found_leff.push_back(tmp_found_leff);
107 vec_found_noisy.push_back(tmp_found_noisy);
108 vec_eff_leff.push_back(tmp_eff_leff);
109 vec_eff_noisy.push_back(tmp_eff_noisy);
110 }
111
112 // sum found pixels for all methods, set efficiency to the maximum of all methods
113 for(unsigned int m=0; m<m_methods.size(); m++)
114 {
115 for(int col_ID=1; col_ID<=input->GetNbinsY(); col_ID++)
116 {
117 for(int row_ID=1; row_ID<=input->GetNbinsX(); row_ID++)
118 {
119 noisypixels_found_output.Fill(row_ID,col_ID, vec_found_noisy[m].GetBinContent(row_ID,col_ID));
120 leffpixels_found_output.Fill(row_ID,col_ID, vec_found_leff[m].GetBinContent(row_ID,col_ID));
121
122 if(m==0)
123 {
124 noisypixels_eff_output.SetBinContent(row_ID,col_ID, vec_eff_noisy[m].GetBinContent(row_ID,col_ID));
125 leffpixels_eff_output.SetBinContent(row_ID,col_ID, vec_eff_leff[m].GetBinContent(row_ID,col_ID));
126 }
127 else
128 {
129 if(noisypixels_eff_output.GetBinContent(row_ID,col_ID)<vec_eff_noisy[m].GetBinContent(row_ID,col_ID))
130 {
131 noisypixels_eff_output.SetBinContent(row_ID,col_ID, vec_eff_noisy[m].GetBinContent(row_ID,col_ID));
132 }
133 if(leffpixels_eff_output.GetBinContent(row_ID,col_ID)>vec_eff_leff[m].GetBinContent(row_ID,col_ID))
134 {
135 leffpixels_eff_output.SetBinContent(row_ID,col_ID, vec_eff_leff[m].GetBinContent(row_ID,col_ID));
136 }
137 }
138 }
139 }
140 }
141
142 // report only pixels that are identified by all methods
143 for(int col_ID=1; col_ID<=input->GetNbinsY(); col_ID++)
144 {
145 for(int row_ID=1; row_ID<=input->GetNbinsX(); row_ID++)
146 {
147 if(noisypixels_found_output.GetBinContent(row_ID,col_ID)==m_methods.size()) noisypixels_found_output.SetBinContent(row_ID,col_ID,1);
148 else noisypixels_found_output.SetBinContent(row_ID,col_ID,0);
149
150 if(leffpixels_found_output.GetBinContent(row_ID,col_ID)==m_methods.size()) leffpixels_found_output.SetBinContent(row_ID,col_ID,1);
151 else leffpixels_found_output.SetBinContent(row_ID,col_ID,0);
152 }
153 }
154
155 return 0;
156}
157
158
159std::vector<std::pair<int,int>>
160AFP_NoisyPixelTool::getLegitPixels(std::shared_ptr<const TH2F> input, const int col_ID, const int row_ID, std::string_view method) const
161{
162 // method="8_PIX" means to investigate all pixels around
163
164 std::vector<std::pair<int,int>> legit_pixels={};
165
166 for(int r=-1; r<2; r++)
167 {
168 for(int c=-1; c<2; c++)
169 {
170 if( (row_ID+r)>=1 && (col_ID+c)>=1 && (col_ID+c)<=input->GetNbinsY() && (row_ID+r)<=input->GetNbinsX() && (r!=0 || c!=0))
171 {
172 if( (method=="2_ROW" && c==0) || (method=="2_COL" && r==0)
173 || (method=="4_PIX" && (c==0 || r==0)) || (method=="8_PIX") )
174 {
175 legit_pixels.push_back(std::pair<int,int>(row_ID+r,col_ID+c));
176 }
177 }
178 }
179 }
180
181 return legit_pixels;
182}
183
184
185TH2F AFP_NoisyPixelTool::countInactivePixelsAround(std::shared_ptr<const TH2F> input) const
186{
187 TH2F tmp_inact_pix_around(*input);
188 tmp_inact_pix_around.SetName("tmp_inact_pix_around");
189 tmp_inact_pix_around.Reset();
190
191 for(int col_ID=1; col_ID<=input->GetNbinsY(); col_ID++)
192 {
193 for(int row_ID=1; row_ID<=input->GetNbinsX(); row_ID++)
194 {
195 int inactive_pixels_around=0;
196 auto legit_pixels=getLegitPixels(input, col_ID, row_ID);
197
198 for(auto legpix : legit_pixels)
199 {
200 if(input->GetBinContent(legpix.first, legpix.second)<1) ++inactive_pixels_around;
201 }
202
203 tmp_inact_pix_around.SetBinContent(row_ID,col_ID, inactive_pixels_around+0.01);
204 }
205 }
206
207 return tmp_inact_pix_around;
208}
209
210
211double AFP_NoisyPixelTool::getNeighbours(std::shared_ptr<const TH2F> input, int row_ID, int col_ID) const
212{
213 if( row_ID!=input->GetNbinsX() && row_ID!=1 && col_ID!=1 && col_ID!=input->GetNbinsY()) return 8.;
214 else if( (row_ID==input->GetNbinsX() || row_ID==1) && (col_ID==1 || col_ID==input->GetNbinsY())) return 3.;
215 else return 5;
216}
217
218
219std::tuple<TH2F,TH2F,TH2F,TH2F> AFP_NoisyPixelTool::findLEffAndNoisyPixels(std::shared_ptr<const TH2F> input, const TH2F& tmp_inact_pix_around, const std::string& method) const
220{
221 TH2F tmp_found_leff(*input);
222 tmp_found_leff.SetName("tmp_found_leff");
223 tmp_found_leff.Reset();
224
225 TH2F tmp_found_noisy(*input);
226 tmp_found_noisy.SetName("tmp_found_noisy");
227 tmp_found_noisy.Reset();
228
229 TH2F tmp_eff_leff(*input);
230 tmp_eff_leff.SetName("tmp_eff_leff");
231 tmp_eff_leff.Reset();
232
233 TH2F tmp_eff_noisy(*input);
234 tmp_eff_noisy.SetName("tmp_eff_noisy");
235 tmp_eff_noisy.Reset();
236
237 for(int col_ID=1; col_ID<=input->GetNbinsY(); col_ID++)
238 {
239 for(int row_ID=1; row_ID<=input->GetNbinsX(); row_ID++)
240 {
241 if(input->GetBinContent(row_ID, col_ID)!=0 && tmp_inact_pix_around.GetBinContent(row_ID, col_ID)<0.1)
242 {
243 double npixels=getNeighbours(input, row_ID, col_ID);
244
245 double sum=0.;
246 auto legit_pixels=getLegitPixels(input, col_ID, row_ID, method);
247 for(auto legpix : legit_pixels)
248 {
249 sum+=input->GetBinContent(legpix.first,legpix.second);
250 }
251
252 double av_noisy=0;
253 double av_leff=0;
254
255 // TODO: something about edges?
256 if(method=="2_ROW" || method=="2_COL")
257 {
258 av_noisy=sum/(std::abs(npixels-4)*0.5);
259 av_leff=sum/2.;
260 }
261 else if(method=="4_PIX")
262 {
263 av_noisy=sum/(std::ceil(npixels*0.5));
264 av_leff=sum/4.;
265 }
266 else if(method=="8_PIX")
267 {
268 av_noisy=sum/(npixels);
269 av_leff=sum/8.;
270 }
271
272 if ((av_leff == 0) or (av_noisy == 0))[[unlikely]]{
273 std::cerr<< "AFP_NoisyPixelTool::findLEffAndNoisyPixels: denominator is zero\n";
274 continue;
275 }
276 double ratio_leff = input->GetBinContent(row_ID,col_ID)/av_leff;
277 double ratio_noisy = input->GetBinContent(row_ID,col_ID)/av_noisy;
278 tmp_eff_leff.SetBinContent(row_ID,col_ID,100.*ratio_leff);
279 tmp_eff_noisy.SetBinContent(row_ID,col_ID,100.*ratio_noisy);
280
281 if(ratio_leff < m_threshLEff) tmp_found_leff.SetBinContent(row_ID,col_ID,1.);
282 if(ratio_noisy > m_threshNoisy) tmp_found_noisy.SetBinContent(row_ID,col_ID,1.);
283 }
284 }
285 }
286
287 return {tmp_found_leff,tmp_found_noisy,tmp_eff_leff,tmp_eff_noisy};
288}
289
290
291void AFP_NoisyPixelTool::filterLEffPixelsAroundNoisy(std::shared_ptr<const TH2F> input, const TH2F& tmp_inact_pix_around, TH2F& tmp_found_leff, TH2F& tmp_found_noisy, TH2F& tmp_eff_leff, TH2F& tmp_eff_noisy, const std::string& method) const
292{
293 for(int col_ID=1; col_ID<=input->GetNbinsY(); col_ID++)
294 {
295 for(int row_ID=1; row_ID<=input->GetNbinsX(); row_ID++)
296 {
297 if(input->GetBinContent(row_ID,col_ID)==0) continue;
298
299 int inactive_pixels_around=tmp_inact_pix_around.GetBinContent(row_ID, col_ID);
300 int leff_pixels_around=0;
301 auto legit_pixels=getLegitPixels(input, col_ID,row_ID);
302 for(auto legpix : legit_pixels)
303 {
304 if(tmp_found_leff.GetBinContent(legpix.first,legpix.second)>0) leff_pixels_around++;
305 }
306
307 if(leff_pixels_around!=0 && inactive_pixels_around==0)
308 {
309 //if low eff. pixels around > 0, recalculate avarage
310 double re_av=0.;
311 int npix=0;
312
313 auto legit_pixels=getLegitPixels(input, col_ID,row_ID, method);
314 for(auto legpix : legit_pixels)
315 {
316 if(tmp_found_leff.GetBinContent(legpix.first,legpix.second)==0)
317 {
318 re_av+=input->GetBinContent(legpix.first,legpix.second);
319 npix++;
320 }
321 }
322
323 if(npix==0)
324 {
325 re_av=0;
326 for(const auto & legpix : legit_pixels)
327 {
328 re_av+=input->GetBinContent(legpix.first,legpix.second);
329 }
330
331 if(re_av/input->GetBinContent(row_ID,col_ID)<1.5 && re_av/input->GetBinContent(row_ID,col_ID)>0.5) re_av=1;
332 }
333 else
334 {
335 re_av/=npix;
336 }
337 if (re_av == 0)[[unlikely]]{
338 std::cerr<< "AFP_NoisyPixelTool::findLEffAndNoisyPixels: re_av denominator is zero\n";
339 continue;
340 }
341 double ratio_noisy = m_sensitivity+input->GetBinContent(row_ID,col_ID)/re_av;
342 double ratio_leff = input->GetBinContent(row_ID,col_ID)/re_av;
343 if(re_av==1)
344 {
345 tmp_eff_leff.SetBinContent(row_ID,col_ID,1);
346 tmp_eff_noisy.SetBinContent(row_ID,col_ID,1);
347 }
348
349 if(row_ID!=input->GetNbinsX() && row_ID!=1 && col_ID!=1 && col_ID!=input->GetNbinsY())
350 {
351 if( ((ratio_noisy>m_threshNoisy && re_av!=1) || re_av==1) )
352 {
353 tmp_found_noisy.SetBinContent(row_ID,col_ID,1);
354 if(re_av!=1) tmp_eff_noisy.SetBinContent(row_ID,col_ID,100.*ratio_noisy);
355 }
356 if( ((ratio_leff<m_threshLEff && re_av!=1) || re_av==1) )
357 {
358 tmp_found_leff.SetBinContent(row_ID,col_ID,1);
359 if(re_av!=1) tmp_eff_leff.SetBinContent(row_ID,col_ID,100.*ratio_leff);
360 }
361 }
362 }
363 }
364 }
365
366 return;
367}
368
369
370std::vector<std::vector<double>> AFP_NoisyPixelTool::makeFits(std::shared_ptr<const TH2F> input) const
371{
372 const int nParams=7;
373 std::vector<std::vector<double>> params(nParams, std::vector<double>(input->GetNbinsX()+1, 0.));
374
375 for(int row_ID=0; row_ID<=input->GetNbinsX(); row_ID++)
376 {
377 std::string srow_ID = std::to_string(row_ID);
378 std::unique_ptr<TH1F> hist(new TH1F(("ROW"+srow_ID).c_str(), ("ROW"+srow_ID).c_str(), input->GetNbinsY(), 0.5, input->GetNbinsX()+0.5));
379
380 for(int col_ID=1; col_ID<=input->GetNbinsY(); col_ID++)
381 {
382 hist->Fill(col_ID, 1.0*input->GetBinContent(row_ID,col_ID));
383 }
384
385 //Set double gaussian fit with starting parameters
386 std::shared_ptr<TF1> FIT_2(new TF1("gaus","gaus(0)+gaus(3)+[6]",0,input->GetNbinsY(),nParams));
387 if(row_ID==1)
388 {
389 FIT_2->SetParameters(25000,hist->GetMean(),hist->GetStdDev()/std::sqrt(2),
390 5000,hist->GetMean(),hist->GetStdDev()/std::sqrt(2),
391 std::max(hist->GetBinContent(2),std::max(hist->GetBinContent(3),hist->GetBinContent(4))) );
392 }
393 else
394 {
395 for(int par=0;par<nParams;++par)
396 {
397 FIT_2->SetParameter(par,params.at(par).at(row_ID-1));
398 }
399 }
400
401 //fit
402 hist->Fit(FIT_2.get(),"Q");
403
404 for(int par=0;par<nParams;++par)
405 {
406 params.at(par).at(row_ID-1)=FIT_2->GetParameter(par);
407 }
408 }
409
410 return params;
411}
412
413
std::tuple< TH2F, TH2F, TH2F, TH2F > findLEffAndNoisyPixels(std::shared_ptr< const TH2F > input, const TH2F &inact, const std::string &method) const
std::vector< std::pair< int, int > > getLegitPixels(std::shared_ptr< const TH2F > input, const int col_ID, const int row_ID, std::string_view method="8_PIX") const
std::vector< std::vector< double > > makeFits(std::shared_ptr< const TH2F > input) const
TH2F countInactivePixelsAround(std::shared_ptr< const TH2F > input) const
double getNeighbours(std::shared_ptr< const TH2F > input, int row_ID, int col_ID) const
int Identify(std::shared_ptr< const TH2F > input, std::vector< TH2F > &output) const override
void filterLEffPixelsAroundNoisy(std::shared_ptr< const TH2F > input, const TH2F &inact, TH2F &fleff, TH2F &fnoisy, TH2F &eleff, TH2F &enoisy, const std::string &method) const
std::vector< std::string > m_methods
int r
Definition globals.cxx:22
#define unlikely(x)