ATLAS Offline Software
Loading...
Searching...
No Matches
BinsDiffFromStripMedian.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/* BinsDiffFromStripMedian.cxx is to pick out the problematic bins in 2D histogram assuming that y-axis(the phi direction) be symmetric.
6 Author: Feng TIAN (columbia university)
7 Email: Feng.Tian@cern.ch
8*/
9
10#include <dqm_core/AlgorithmConfig.h>
13#include <dqm_core/AlgorithmManager.h>
14
15#include <TH1.h>
16#include <TF1.h>
17#include <TClass.h>
18#include <cmath>
19#include <format>
20
21#include <iostream>
22#include <string>
23
24bool mySortfunc(const bin& i,const bin& j){return (i.m_value > j.m_value);}
25bool mySortfunc_ratio(const bin& i, const bin& j){return (i.m_outstandingRatio> j.m_outstandingRatio);}
27
29{
30 dqm_core::AlgorithmManager::instance().registerAlgorithm("BinsDiffFromStripMedian", this);
31}
32
36
43
44
45dqm_core::Result *
47 const TObject& object,
48 const dqm_core::AlgorithmConfig& config )
49{
50 const TH1* histogram;
51
52 if( object.IsA()->InheritsFrom( "TH1" ) ) {
53 histogram = static_cast<const TH1*>(&object);
54 if (histogram->GetDimension() > 2 ){
55 throw dqm_core::BadConfig( ERS_HERE, name, "dimension > 2 " );
56 }
57 } else {
58 throw dqm_core::BadConfig( ERS_HERE, name, "does not inherit from TH1" );
59 }
60
61 const double minstat = dqm_algorithms::tools::GetFirstFromMap( "MinStat", config.getParameters(), -1);
62 const double ignoreval = dqm_algorithms::tools::GetFirstFromMap( "ignoreval", config.getParameters(), -99999);
63 const bool publish = (bool) dqm_algorithms::tools::GetFirstFromMap( "PublishBins", config.getParameters(), 1);
64 const int Nmaxpublish = (int) dqm_algorithms::tools::GetFirstFromMap( "MaxPublish", config.getParameters(), 20);
65 const bool VisualMode = (bool) dqm_algorithms::tools::GetFirstFromMap( "VisualMode", config.getParameters(), 1);
66 const int NpublishRed = (int) dqm_algorithms::tools::GetFirstFromMap( "PublishRedBins",config.getParameters(), 0);
67 const bool ClusterResult = (bool) dqm_algorithms::tools::GetFirstFromMap( "ClusterResult", config.getParameters(), 0);
68 const double suppressFactor = dqm_algorithms::tools::GetFirstFromMap("SuppressFactor", config.getParameters(), 0.05);
69 const double suppressRedFactor = dqm_algorithms::tools::GetFirstFromMap("SuppressRedFactor", config.getParameters(), 0.01);
70 if ( histogram->GetEntries() < minstat ) {
71 dqm_core::Result *result = new dqm_core::Result(dqm_core::Result::Undefined);
72 result->tags_["InsufficientEntries"] = histogram->GetEntries();
73 return result;
74 }
75
76 double gthreshold;
77 double rthreshold;
78 try {
79 rthreshold = dqm_algorithms::tools::GetFromMap( "MaxDeviation", config.getRedThresholds() );
80 gthreshold = dqm_algorithms::tools::GetFromMap( "MaxDeviation", config.getGreenThresholds() );
81 }
82 catch( dqm_core::Exception & ex ) {
83 throw dqm_core::BadConfig( ERS_HERE, name, ex.what(), ex );
84 }
85
86 std::vector<int> range=dqm_algorithms::tools::GetBinRange(histogram, config.getParameters());
87 std::vector<double> stripsMedian;
88 std::vector<double> stripsAvg;
89 std::vector<double> stripsVariance;
90 double maxInMap=0;
91 for ( int i = range[0]; i <= range[1]; ++i ) {
92 std::vector<double> onestrip;
93 double stripSum=0;
94 for ( int j = range[2]; j <= range[3]; ++j ) {
95 if (histogram->GetBinContent(i,j) == ignoreval) continue;
96 float binvalue = histogram->GetBinContent(i,j);
97 onestrip.push_back(binvalue);
98 stripSum += binvalue;
99 if(binvalue > maxInMap) {
100 maxInMap = binvalue;
101 }
102 }
103 stripsAvg.push_back(stripSum/onestrip.size());
104 FindStripMedian(std::move(onestrip),stripsMedian);
105 }
106 for ( int i = range[0]; i <= range[1]; ++i ) {
107 float sumdiff2=0;
108 int counter=0;
109 for ( int j = range[2]; j <= range[3]; ++j ) {
110 if (histogram->GetBinContent(i,j) == ignoreval) continue;
111 double binvalue = histogram->GetBinContent(i,j);
112 double diff=binvalue-stripsAvg[i-range[0]];
113 sumdiff2 +=std::pow(diff,2);
114 counter++;
115 }
116 double variance=-1;
117 if(counter!=0) variance = sumdiff2 / counter ;
118 stripsVariance.push_back(variance);
119 }
120 dqm_core::Result* result = new dqm_core::Result();
121 std::vector<bin> redbins;
122 std::vector<bin> yellowbins;
123 std::vector<bin> Allbins;
124 for ( int k = range[0]; k <= range[1]; ++k ) {
125 for ( int l = range[2]; l <= range[3]; ++l ) {
126 double binvalue = histogram->GetBinContent(k,l);
127 if (binvalue== ignoreval) continue;
128 double strip_median = stripsMedian[k-range[0]];
129 if(stripsMedian[k-range[0]]==0 && stripsVariance[k-range[0]]==0) continue; // skip empty strip
130 else if(stripsMedian[k-range[0]]==0 && stripsVariance[k-range[0]]!=0 && stripsAvg[k-range[0]]!=0) strip_median = stripsAvg[k-range[0]];
131 else if(stripsMedian[k-range[0]]==0 && stripsVariance[k-range[0]]!=0 && stripsAvg[k-range[0]]==0) continue;
132 double outstandingRatio=0;
133 if(std::abs(strip_median) > 0.00001 ) outstandingRatio= (binvalue-strip_median)/std::sqrt(std::abs(strip_median));
134 else continue;
135 double eta = histogram->GetXaxis()->GetBinCenter(k);
136 double phi = histogram->GetYaxis()->GetBinCenter(l);
137 bin onebin = {eta,phi,k,l,binvalue,outstandingRatio};
138 Allbins.push_back(onebin);
139 if (maxInMap == 0) continue;
140 if(std::abs(outstandingRatio) > rthreshold ) {
141 if( VisualMode && (binvalue / maxInMap < suppressRedFactor) )
142 continue;
143 redbins.push_back(onebin);
144 }
145 else if(std::abs(outstandingRatio) > gthreshold ){
146 if( VisualMode && (binvalue / maxInMap < suppressFactor) )
147 continue;
148 yellowbins.push_back(onebin);
149 }
150 }
151 }
152 int count_red_c = 0;
153 int count_yellow_c = 0;
154 std::vector<std::vector<colorbin> > ColorBinMap;
155if(ClusterResult){
156 // initialize ColorBinMap
157 for ( int k = range[0]; k <= range[1]; ++k ) {
158 std::vector<colorbin> oneColorStrip;
159 for ( int l = range[2]; l <= range[3]; ++l ) {
160 colorbin oneColorBin = {static_cast<double>(k), static_cast<double>(l), -1, -1, -1, green, 1};
161 oneColorStrip.push_back(oneColorBin);
162 }
163 ColorBinMap.push_back(std::move(oneColorStrip));
164 }
165
166// map redbins and yellowbins to ColorBinMap
167 for(unsigned int i=0;i<redbins.size();i++){
168 int k=redbins[i].m_ix;
169 int l=redbins[i].m_iy;
170
171 ColorBinMap[k-range[0]][l-range[2]].m_eta = redbins[i].m_eta;
172
173 ColorBinMap[k-range[0]][l-range[2]].m_phi = redbins[i].m_phi;
174 ColorBinMap[k-range[0]][l-range[2]].m_value = redbins[i].m_value;
175 ColorBinMap[k-range[0]][l-range[2]].m_color = red;
176
177 }
178
179
180 for(unsigned int i=0;i<yellowbins.size();i++){
181 int k=yellowbins[i].m_ix;
182 int l=yellowbins[i].m_iy;
183 ColorBinMap[k-range[0]][l-range[2]].m_eta = yellowbins[i].m_eta;
184 ColorBinMap[k-range[0]][l-range[2]].m_phi = yellowbins[i].m_phi;
185 ColorBinMap[k-range[0]][l-range[2]].m_value = yellowbins[i].m_value;
186 ColorBinMap[k-range[0]][l-range[2]].m_color = yellow;
187 }
188
189
190// cluster bad bins
191 std::vector<colorcluster > clusterArray;
192 for(unsigned int i=0;i<redbins.size();i++){
193 const int k=redbins[i].m_ix;
194 const int l=redbins[i].m_iy;
195 if(ColorBinMap[k-range[0]][l-range[2]].m_color != green){
196 colorcluster onecluster = MakeCluster(range[0],range[2],redbins[i],ColorBinMap);
197 if(onecluster.m_size > 1) clusterArray.push_back(onecluster);
198 }
199 }
200 for(unsigned int i=0;i<yellowbins.size();i++){
201 const int k=yellowbins[i].m_ix;
202 const int l=yellowbins[i].m_iy;
203 if(ColorBinMap[k-range[0]][l-range[2]].m_color != green){
204 colorcluster onecluster = MakeCluster(range[0],range[2],yellowbins[i],ColorBinMap);
205 if(onecluster.m_size > 1) clusterArray.push_back(onecluster);
206 }
207 }
208
209 // publish clusters here:
210 for(unsigned int i=0;i<clusterArray.size();i++){
211 std::string tag;
212 if(clusterArray[i].m_color==red){
213 tag = std::format(
214 "CR{}-(eta,phi)(r)(size)=({:.3f},{:.3f})({:.3f})({})",
215 count_red_c,
216 clusterArray[i].m_eta,
217 clusterArray[i].m_phi,
218 clusterArray[i].m_radius,
219 clusterArray[i].m_size);
220 count_red_c++;
221 }
222 else if(clusterArray[i].m_color==yellow){
223 tag = std::format(
224 "CY{}-(eta,phi)(r)(size)=({:.3f},{:.3f})({:.3f})({})",
225 count_yellow_c,
226 clusterArray[i].m_eta,
227 clusterArray[i].m_phi,
228 clusterArray[i].m_radius,
229 clusterArray[i].m_size);
230 count_yellow_c++;
231 }
232 result->tags_[tag] = clusterArray[i].m_value;
233 }
234 result->tags_["NRedClusters"] = count_red_c;
235 result->tags_["NYellowClusters"] = count_yellow_c;
236
237 }
238
239
240 std::sort(redbins.begin(),redbins.end(),mySortfunc);
241 std::sort(yellowbins.begin(),yellowbins.end(),mySortfunc);
242 std::sort(Allbins.begin(),Allbins.end(),mySortfunc_ratio);
243// publish red bins
244 int count_red=0;
245 for(unsigned int i=0;i<redbins.size();i++){
246 if(ClusterResult && ColorBinMap[redbins[i].m_ix-range[0]][redbins[i].m_iy-range[2]].m_status==0 ) continue;
247 if(publish){
248 char tmp[500];
249 sprintf(tmp,"R%i-(eta,phi)[OSRatio]=(%0.3f,%0.3f)[%0.2e]",count_red,redbins[i].m_eta,redbins[i].m_phi,redbins[i].m_outstandingRatio);
250 std::string tag = tmp;
251 result->tags_[tag] = redbins[i].m_value;
252 }
253 count_red++;
254 if(NpublishRed > 0){
255 if(count_red > NpublishRed) break;
256 }
257 }
258
259// publish yellow bins
260 int count_yellow=0;
261 for(unsigned int i=0;i<yellowbins.size();i++){
262 if(ClusterResult &&ColorBinMap[yellowbins[i].m_ix-range[0]][yellowbins[i].m_iy-range[2]].m_status==0) continue;
263 if(publish && (count_red+count_yellow) < Nmaxpublish ){
264 char tmp[500];
265 sprintf(tmp,"Y%i-(eta,phi)[OSRatio]=(%0.3f,%0.3f)[%.2e]",count_yellow,yellowbins[i].m_eta,yellowbins[i].m_phi,yellowbins[i].m_outstandingRatio);
266 std::string tag = tmp;
267 result->tags_[tag] = yellowbins[i].m_value;
268 }
269 count_yellow++;
270 }
271 result->tags_["NRedBins"] = count_red; // count_red is the number of red bins printed
272 result->tags_["NYellowBins"] = count_yellow; // count_yellow is the number of yellow bins printed
273
274 if(count_red+count_yellow==0 && Allbins.size()>=5 ){
275 for(int i=0;i<5;i++){
276 char tmptmp[500];
277 sprintf(tmptmp,"LeadingBin%i-(eta,phi)=(%0.3f,%0.3f)",i,Allbins[i].m_eta,Allbins[i].m_phi);
278 std::string tagtag = tmptmp;
279 result->tags_[tagtag] = Allbins[i].m_value;
280 }
281
282 }
283
284
285 if(count_red>0 || count_red_c>0) result->status_ = dqm_core::Result::Red;
286 else if (count_yellow>0||count_yellow_c>0) result->status_ = dqm_core::Result::Yellow;
287 else result->status_ = dqm_core::Result::Green;
288
289 return result;
290
291}
292void
293dqm_algorithms::BinsDiffFromStripMedian::FindStripMedian(std::vector<double> onestrip_tmp,std::vector<double>& stripsMedian){
294 double median=0;
295
296 std::sort(onestrip_tmp.begin(),onestrip_tmp.end());
297 int index1=onestrip_tmp.size()/4;
298
299 int index2=onestrip_tmp.size()/2;
300 int index3=3*onestrip_tmp.size()/4;
301 median = (onestrip_tmp[index1]+onestrip_tmp[index2]+onestrip_tmp[index3])/3.0;
302 stripsMedian.push_back(median);
303}
304void AddToList(const int r0,const int r2,int i,int j,std::vector<std::vector<colorbin> > & ColorBinMap, std::vector<colorbin>& LookAtList){
305
306 if( i-r0<0 || i-r0>=(int)ColorBinMap.size()
307 || j-r2<0 ||j-r2>=(int)ColorBinMap[0].size() ) return;
308
309 std::vector<colorbin> tmp;
310
311 if(i-1-r0>=0 && j-1-r2>=0 && ColorBinMap[i-1-r0][j-1-r2].m_status==1){
312 tmp.push_back(ColorBinMap[i-1-r0][j-1-r2]);
313 ColorBinMap[i-1-r0][j-1-r2].m_status=0;
314 }
315 if(j-1-r2 >=0 && ColorBinMap[i-r0][j-1-r2].m_status==1){
316 tmp.push_back(ColorBinMap[i-r0][j-1-r2]);
317 ColorBinMap[i-r0][j-1-r2].m_status=0;
318 }
319 if(i+1-r0<(int)ColorBinMap.size() && j-1-r2 >=0 && ColorBinMap[i+1-r0][j-1-r2].m_status==1){
320 tmp.push_back(ColorBinMap[i+1-r0][j-1-r2]);
321 ColorBinMap[i+1-r0][j-1-r2].m_status=0;
322 }
323 if(i-1-r0>=0 && ColorBinMap[i-1-r0][j-r2].m_status==1){
324 tmp.push_back(ColorBinMap[i-1-r0][j-r2]);
325 ColorBinMap[i-1-r0][j-r2].m_status=0;
326 }
327
328 if(i+1-r0<(int)ColorBinMap.size() && ColorBinMap[i+1-r0][j-r2].m_status==1){
329 tmp.push_back(ColorBinMap[i+1-r0][j-r2]);
330 ColorBinMap[i+1-r0][j-r2].m_status=0;
331 }
332 if(i-1-r0>=0 && j+1-r2 < (int)ColorBinMap[0].size()
333 && ColorBinMap[i-1-r0][j+1-r2].m_status==1){
334 tmp.push_back(ColorBinMap[i-1-r0][j+1-r2]);
335 ColorBinMap[i-1-r0][j+1-r2].m_status=0;
336 }
337if(j+1-r2<(int)ColorBinMap[0].size()&& ColorBinMap[i-r0][j+1-r2].m_status==1){
338 tmp.push_back(ColorBinMap[i-r0][j+1-r2]);
339 ColorBinMap[i-r0][j+1-r2].m_status=0;
340 }
341 if(i+1-r0<(int)ColorBinMap.size() && j+1-r2<(int)ColorBinMap[0].size()&&ColorBinMap[i+1-r0][j+1-r2].m_status==1){
342 tmp.push_back(ColorBinMap[i+1-r0][j+1-r2]);
343 ColorBinMap[i+1-r0][j+1-r2].m_status=0;
344 }
345
346 for(unsigned int k=0;k<tmp.size();k++){
347 if(tmp[k].m_color!=green){
348 LookAtList.push_back(tmp[k]);
349 AddToList(r0,r2,tmp[k].m_ix,tmp[k].m_iy,ColorBinMap,LookAtList);
350 }
351 }
352 return;
353
354}
355
356double CalEta(std::vector<colorbin>& LookAtList){
357 double sumEta=0;
358 double sumN=0;
359 for(unsigned int i=0;i<LookAtList.size();i++){
360 double eta = LookAtList[i].m_eta;
361 double n = LookAtList[i].m_value;
362 sumEta += n*eta;
363 sumN +=n;
364 }
365 if(sumN!=0) return sumEta/sumN;
366 else return -99;
367}
368double CalPhi(std::vector<colorbin>& LookAtList){
369 double sumPhi=0;
370 double sumN=0;
371 for(unsigned int i=0;i<LookAtList.size();i++){
372 double phi = LookAtList[i].m_phi;
373 double n = LookAtList[i].m_value;
374 sumPhi += n*phi;
375 sumN +=n;
376 }
377 if(sumN!=0) return sumPhi/sumN;
378 else return -99;
379}
380double CalVal(std::vector<colorbin>& LookAtList){
381 double sumN=0;
382 for(unsigned int i=0;i<LookAtList.size();i++){
383 double n = LookAtList[i].m_value;
384 sumN += n;
385 }
386 return sumN;
387}
388double CalR(std::vector<colorbin>& LookAtList,double eta, double phi){
389 if(LookAtList.size()<2) return 0;
390 double maxR=0;
391 for(unsigned int i=0;i<LookAtList.size();i++){
392 double distance = std::sqrt(std::pow((LookAtList[i].m_eta-eta),2)+std::pow((LookAtList[i].m_phi-phi),2));
393 maxR=distance>maxR?distance:maxR;
394 }
395 return maxR;
396}
397
398colorcluster
399dqm_algorithms::BinsDiffFromStripMedian::MakeCluster(const int r0,const int r2,bin& onebin, std::vector<std::vector<colorbin> > & ColorBinMap){
400 colorcluster onecluster={0,0,0,0,green,-1};
401 if(ColorBinMap[onebin.m_ix-r0][onebin.m_iy-r2].m_status==0)
402 return onecluster;
403 std::vector<colorbin> LookAtList;
404 if(ColorBinMap[onebin.m_ix-r0][onebin.m_iy-r2].m_color!=green){
405 LookAtList.push_back(ColorBinMap[onebin.m_ix-r0][onebin.m_iy-r2]);
406 ColorBinMap[onebin.m_ix-r0][onebin.m_iy-r2].m_status=0;
407 AddToList(r0,r2,onebin.m_ix,onebin.m_iy,ColorBinMap, LookAtList);
408 if(LookAtList.size()>1){
409 onecluster.m_size = LookAtList.size();
410 onecluster.m_value = CalVal(LookAtList);
411 if(ColorBinMap[onebin.m_ix-r0][onebin.m_iy-r2].m_color==red)
412 onecluster.m_color = red;
413 else onecluster.m_color = yellow;
414 onecluster.m_eta = CalEta(LookAtList);
415 onecluster.m_phi = CalPhi(LookAtList);
416 onecluster.m_radius = CalR(LookAtList,onecluster.m_eta,onecluster.m_phi);
417 }
418 else ColorBinMap[onebin.m_ix-r0][onebin.m_iy-r2].m_status=1;
419 }
420 return onecluster;
421}
422
423void
425{
426
427 out<<"BinsDiffFromStripMedian: Calculates smoothed strip median and then find out bins which are aliens "<<std::endl;
428
429 out<<"Mandatory Green/Red Threshold is the value of outstandingRatio=(bin value)/(strip median) based on which to give Green/Red result\n"<<std::endl;
430
431 out<<"Optional Parameter: MinStat: Minimum histogram statistics needed to perform Algorithm"<<std::endl;
432 out<<"Optional Parameter: ignoreval: valued to be ignored for being processed"<<std::endl;
433 out<<"Optional Parameter: PublishBins: Save bins which are different from average in Result (on:1,off:0,default is 1)"<<std::endl;
434 out<<"Optional Parameter: MaxPublish: Max number of bins to save (default 20)"<<std::endl;
435 out<<"Optional Parameter: VisualMode: is to make the evaluation process similar to the shift work, so one will get resonable result efficiently."<<std::endl;
436
437}
438
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
static dqm_algorithms::BinContentComp myInstance
double CalEta(std::vector< colorbin > &LookAtList)
double CalR(std::vector< colorbin > &LookAtList, double eta, double phi)
double CalPhi(std::vector< colorbin > &LookAtList)
void AddToList(const int r0, const int r2, int i, int j, std::vector< std::vector< colorbin > > &ColorBinMap, std::vector< colorbin > &LookAtList)
double CalVal(std::vector< colorbin > &LookAtList)
bool mySortfunc(const bin &i, const bin &j)
bool mySortfunc_ratio(const bin &i, const bin &j)
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
std::string histogram
Definition chains.cxx:52
double m_outstandingRatio
std::vector< int > GetBinRange(const TH1 *histogram, const std::map< std::string, double > &params)
double GetFirstFromMap(const std::string &paramName, const std::map< std::string, double > &params)
const T & GetFromMap(const std::string &pname, const std::map< std::string, T > &params)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
void FindStripMedian(std::vector< double > onestrip, std::vector< double > &stripsMedian)
colorcluster MakeCluster(const int r0, const int r2, bin &onebin, std::vector< std::vector< colorbin > > &ColorBinMap)
dqm_core::Result * execute(const std::string &, const TObject &, const dqm_core::AlgorithmConfig &)
#define IsA
Declare the TObject style functions.