ATLAS Offline Software
L1Calo_OutlierAndFlatnessTest.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
11 
12 #include <dqm_core/AlgorithmManager.h>
13 #include "dqm_core/exceptions.h"
14 #include <dqm_core/AlgorithmConfig.h>
15 #include <dqm_core/Result.h>
16 
17 #include <TH1.h>
18 #include <TF1.h>
19 #include <TClass.h>
20 #include <cmath>
21 
22 namespace
23 {
24  dqm_algorithms::L1Calo_OutlierAndFlatnessTest L1Calo_OutlierAndFlatnessTest( "L1Calo_OutlierAndFlatnessTest" );
25 }
26 
27 
29  dqm_core::AlgorithmManager::instance().registerAlgorithm(name, this);
30  m_counterSkip = 0;
31 }
32 
34  return new L1Calo_OutlierAndFlatnessTest( m_name );
35 }
36 
38  const dqm_core::AlgorithmConfig& config) {
39 
40 // if(m_counterSkip < counterSkipMax){
41 // dqm_core::Result* result = new dqm_core::Result();
42 // result->status_ = dqm_core::Result::Green;
43 // m_counterSkip++;
44 // return result;
45 // }
46 
47 // m_counterSkip = 0;
48 
49  TH1 const * histogram;
50  if( object.IsA()->InheritsFrom( "TH1" ) ) {
51  histogram = static_cast<TH1 const *>(&object);
52 
53  if (histogram->GetDimension() > 2 ) {
54  throw dqm_core::BadConfig( ERS_HERE, name, "dimension > 2 " );
55  }
56  } else {
57  throw dqm_core::BadConfig( ERS_HERE, name, "does not inherit from TH1" );
58  }
59 
60  const double minstat = tools::GetFirstFromMap( "MinStat", config.getParameters(), 1);
61 
62  //Check for minimum statistics
63  if (histogram->GetEntries() < minstat ) {
66  result->tags_["Not enough Signal Statistics"] = minstat;
67  //delete histogram;
68  return result;
69  }
70 
71  //check if histogram contains only zeros
72  int checkZeroContent = (int) tools::GetFirstFromMap( "CheckZeroContent", config.getParameters(), 1 );
73 
74  if ((checkZeroContent > 0) && (histogram->Integral() == 0) && (histogram->GetEntries() > 0)) {
75  ERS_DEBUG(1, "Histogram " <<histogram->GetName()<<" is filled with zeroes!");
77  result->status_ = dqm_core::Result::Red;
78  result->tags_["Integral"] = histogram->Integral();
79  //delete histogram;
80  return result;
81  }
82 
83 
84  int checkSigmaDev = 1;
85  int dontCountSigmaOutliers = 0;
86  int ignore0 = 1;
87  double sigmaDev = 0;
88  double absDev = 0;
89 
90  //Get configuration parameters and set defaults
91  try {
92  ignore0 = (int) tools::GetFirstFromMap( "Ignore0", config.getParameters(), 1 );
93 
94  checkSigmaDev = (int) tools::GetFirstFromMap( "CheckSigmaDev", config.getParameters(), 1 );
95 
96  absDev = tools::GetFirstFromMap( "AbsDev", config.getParameters(), 15.0 );
97 
98  if (checkSigmaDev) {
99  sigmaDev = tools::GetFirstFromMap( "SigmaDev", config.getParameters());
100  dontCountSigmaOutliers = (int) tools::GetFirstFromMap( "DontCountSigmaOutliers", config.getParameters(), 0);
101  }
102  }
103  catch( dqm_core::Exception & ex ) {
104  throw dqm_core::BadConfig( ERS_HERE, name, ex.what(), ex );
105  }
106 
107 
108  const std::vector<int> range = dqm_algorithms::tools::GetBinRange(histogram, config.getParameters());
109  const int xminBin = range[0];
110  const int xmaxBin = range[1];
111 
112  //compute the number of empty bins (or bins=0)
113  int zeroBins = 0;
114  for (int i = xminBin; i <= xmaxBin; i++) {
115  if (histogram->GetBinContent(i) == 0) zeroBins++;
116  }
117 
118  //Compute outlier bins by using a simplified Grubb's test without cutting on a t-distribution but by giving an external threshold defining how many standard deviations a value has to differ from the mean to be classified as an outlier or by giving an absolute threshold for classifying values as outliers
119  int totalBadBins = 0;
120  double mean=0;
121  double stdev=0;
122 
123  //compute the arithmetic mean
124  double sum=0,sum2=0;
125  int counter = 0;
126 
127  for(int i=xminBin;i <= xmaxBin;i++){
128  if( histogram->GetBinContent(i) != 0 || ignore0 == false) {
129  sum += histogram->GetBinContent(i);
130  sum2 += histogram->GetBinContent(i)*histogram->GetBinContent(i);
131  counter++;
132  }
133  }
134 
135  mean = counter > 0 ? sum/(double)counter : 0;
136  stdev = counter > 0 ? std::sqrt( sum2/static_cast<double>(counter) - mean*mean) : 0;
137 
138 
139  //check how many bins are out of N sigma range (SigmaDev) or out of the absolute dev (AbsDev) or over absolute limit (AbsLimit), count them as (uncounted) outliers
140  double dev;
141  double absdev_test = 0;
142  if (checkSigmaDev) {
143  for (int i = xminBin; i <= xmaxBin; i++) {
144  if ((histogram->GetBinContent(i) != 0) || (ignore0 == 0)) {
145  dev=std::abs(histogram->GetBinContent(i) - mean)/stdev;
146  absdev_test=std::abs(histogram->GetBinContent(i) - mean);
147  if ((dev > sigmaDev) && (absdev_test > absDev)) {
148  if (!dontCountSigmaOutliers){
149  totalBadBins++;
150  }
151  }
152  }
153  }
154  }
155 
156  int totalBadBins_all = 0;
157  double mean_all=0;
158  double stdev_all=0;
159 
160  //compute the arithmetic mean
161  double sum_all=0,sum2_all=0;
162  int counter_all = 0;
163 
164  for(int i=0;i <= histogram->GetNbinsX() ;i++){
165  if( histogram->GetBinContent(i) != 0 || ignore0 == false) {
166  sum_all += histogram->GetBinContent(i);
167  sum2_all += histogram->GetBinContent(i)*histogram->GetBinContent(i);
168  counter_all++;
169  }
170  }
171 
172  mean_all = counter_all > 0 ? sum_all/(double)counter_all : 0;
173  stdev_all = counter_all > 0 ? std::sqrt( sum2_all/static_cast<double>(counter_all) - mean_all*mean_all) : 0;
174 
175 
176  //check how many bins are out of N sigma range (SigmaDev) or out of the absolute dev (AbsDev) or over absolute limit (AbsLimit), count them as (uncounted) outliers
177  double dev_all;
178  double absdev_test_all = 0;
179  if (checkSigmaDev) {
180  for (int i=0;i <= histogram->GetNbinsX() ;i++) {
181  if ((histogram->GetBinContent(i) != 0) || (ignore0 == 0)) {
182  dev_all=std::abs(histogram->GetBinContent(i) - mean_all)/stdev_all;
183  absdev_test_all=std::abs(histogram->GetBinContent(i) - mean_all);
184  if ((dev_all > sigmaDev) && (absdev_test_all > absDev)) {
185  if (!dontCountSigmaOutliers){
186  totalBadBins_all++;
187  }
188  }
189  }
190  }
191  }
192 
193 
194  //Prepare map for results and commit outlier specific parts
195  std::map<std::string,double> algparams;
196  algparams["Number_of_outlier_bins"] = totalBadBins;
197  algparams["Number_of_outlier_bins_all"] = totalBadBins_all;
198  algparams["Mean"] = mean;
199  algparams["Standard_deviation"] = stdev;
200  algparams["Number_of_bins_equal_zero"] = zeroBins;
201 
202 
203  //Compare with given thresholds and compute DQ-Flag
204  dqm_core::Result *result = tools::MakeComparisons(algparams, config.getGreenThresholds(), config.getRedThresholds());
205 
206 
207  return result;
208 }
209 
211  out << m_name << ": derivation of OutlierAndFlatnessTest, slimmed and optimized for L1Calo needs"
212  "Checks TH1-inherited histograms for bins which lie either Nsigma or AbsDev away from the mean (by default excludes bins with zero entries). Can also check mean itself\n"
213  "Config Parameters:\n"
214  "\tCheckSigmaDev:\tCheck for deviation in units of standard deviations from mean (default 1).\n"
215  "\tMinStat:\tMinimum Statistics for the histogram to be checked (default 1).\n"
216  "\txmin and/or xmax:\tRestrict all counting to this x-axis interval (default: full axis range).\n"
217  "\txmin and/or xmax:\tThere is a second output parameter (Number_of_outlier_bins_all), which always uses the full range.\n"
218  "\tIgnore0:\tBins with 0 content are ignored for outlier/mean computation (default 1).\n"
219  "\tSigmaDev:\tNumber of Standard Deviations a single bin has to differ from the mean of the distribution to be classified as outlier. Has to be given if \"CheckSigmaDev\" is set to 1. (default 5)\n"
220  "\tAbsDev:\tAbsolute value a single bin has to differ from the mean of the distribution to be classified as outlier. Has to be given if \"CheckAbsDev\" is set to 1.\n"
221  "\tDontCountSigmaDev:\tBins deviating by a given number of standard deviations are not counted as outliers (default 0)."
222  "\tDontCountSigmaDev:\t(Not recommended to be switched on in current config)\n"
223  "Threshold Parameters:\n"
224  "\tStandard_deviation: \tStandard Deviation of distribution.\n"
225  "\tNumber_of_outlier_bins:\tNumber of bins classified as outliers using the given thresholds (in chosen histogram range).\n"
226  "\tNumber_of_outlier_bins_all:\tNumber of bins classified as outliers using the given thresholds (in full histogram range).\n"
227  "\tMean:\tMean of distribution.\n"
228  "\tNumber_of_bins_equal_zero:\tNumber of Bins with zero content." << std::endl;
229 }
dqm_algorithms::tools::GetBinRange
std::vector< int > GetBinRange(const TH1 *histogram, const std::map< std::string, double > &params)
Definition: AlgorithmHelper.cxx:380
mean
void mean(std::vector< double > &bins, std::vector< double > &values, const std::vector< std::string > &files, const std::string &histname, const std::string &tplotname, const std::string &label="")
Definition: dependence.cxx:254
get_generator_info.result
result
Definition: get_generator_info.py:21
IsA
#define IsA
Declare the TObject style functions.
Definition: xAODTEventBranch.h:59
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
dqm_algorithms::L1Calo_OutlierAndFlatnessTest::m_counterSkip
unsigned int m_counterSkip
Definition: L1Calo_OutlierAndFlatnessTest.h:31
config
Definition: PhysicsAnalysis/AnalysisCommon/AssociationUtils/python/config.py:1
instance
std::map< std::string, double > instance
Definition: Run_To_Get_Tags.h:8
convertTimingResiduals.sum
sum
Definition: convertTimingResiduals.py:55
lumiFormat.i
int i
Definition: lumiFormat.py:92
Result
ICscStripFitter::Result Result
Definition: CalibCscStripFitter.cxx:13
dqm_algorithms::L1Calo_OutlierAndFlatnessTest::clone
L1Calo_OutlierAndFlatnessTest * clone()
Definition: L1Calo_OutlierAndFlatnessTest.cxx:33
dqm_algorithms::L1Calo_OutlierAndFlatnessTest::L1Calo_OutlierAndFlatnessTest
L1Calo_OutlierAndFlatnessTest(const std::string &name)
Definition: L1Calo_OutlierAndFlatnessTest.cxx:28
dqm_algorithms::tools::MakeComparisons
dqm_core::Result * MakeComparisons(const std::map< std::string, double > &algparams, const std::map< std::string, double > &gthreshold, const std::map< std::string, double > &rthreshold)
Definition: AlgorithmHelper.cxx:60
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
python.handimod.Green
int Green
Definition: handimod.py:524
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
dqm_algorithms::L1Calo_OutlierAndFlatnessTest::printDescription
void printDescription(std::ostream &out)
Definition: L1Calo_OutlierAndFlatnessTest.cxx:210
L1Calo_OutlierAndFlatnessTest.h
python.handimod.Red
Red
Definition: handimod.py:551
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
dqm_algorithms::L1Calo_OutlierAndFlatnessTest
Definition: L1Calo_OutlierAndFlatnessTest.h:18
TH1
Definition: rootspy.cxx:268
AlgorithmHelper.h
pickleTool.object
object
Definition: pickleTool.py:30
test_pyathena.counter
counter
Definition: test_pyathena.py:15
dqm_algorithms::tools::GetFirstFromMap
double GetFirstFromMap(const std::string &paramName, const std::map< std::string, double > &params)
Definition: AlgorithmHelper.cxx:339
dqm_algorithms::L1Calo_OutlierAndFlatnessTest::execute
dqm_core::Result * execute(const std::string &, const TObject &, const dqm_core::AlgorithmConfig &)
Definition: L1Calo_OutlierAndFlatnessTest.cxx:37
histogram
std::string histogram
Definition: chains.cxx:52