ATLAS Offline Software
Loading...
Searching...
No Matches
BinsDiffByStrips.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
8
9
10
11#include <dqm_core/AlgorithmConfig.h>
14#include <dqm_core/AlgorithmManager.h>
15
16#include <TH1.h>
17#include <TH1F.h>
18#include <TH2F.h>
19#include <TClass.h>
20#include <TObjArray.h>
21#include <TMath.h>
22
23#include <cmath>
24#include <string>
25#include <algorithm> // for std::sort
26
27
29
31{
32 dqm_core::AlgorithmManager::instance().registerAlgorithm("BinsDiffByStrips", this);
33 TH1::AddDirectory(false);
34}
35
39
46
47
48dqm_core::Result *
50 const TObject& object,
51 const dqm_core::AlgorithmConfig& config ){
52
53 dqm_core::Result* result = new dqm_core::Result();
54
55 //==========================================================================
56 //-- Input Histogram Retrieval --
57 //==========================================================================
58 // Retrieve input object, test if it is a valid 2D histogram:
59
60 const TH1* histogram;
61
62 if( object.IsA()->InheritsFrom( "TH1" ) ) {
63 histogram = static_cast<const TH1*>(&object);
64 if (histogram->GetDimension() != 2 ){
65 throw dqm_core::BadConfig( ERS_HERE, name, "dimension != 2 " );
66 }
67 } else {
68 throw dqm_core::BadConfig( ERS_HERE, name, "does not inherit from TH1" );
69 }
70
71 //==========================================================================
72 //-- Algorithm Configuration --
73 //==========================================================================
74 // Loading of parameters, thresholds from config,
75
76 // Thresholds:
77 //-------------------
78 double gthreshold;
79 double rthreshold;
80 try {
81 rthreshold = dqm_algorithms::tools::GetFromMap( "MaxDeviation", config.getRedThresholds() );
82 gthreshold = dqm_algorithms::tools::GetFromMap( "MaxDeviation", config.getGreenThresholds() );
83 }
84 catch( dqm_core::Exception & ex ) {
85 throw dqm_core::BadConfig( ERS_HERE, name, ex.what(), ex );
86 }
87
88 // Configuration Parameters:
89 //-------------------------------
90
91
92 // Parameters giving the minimum number(fraction) of bins with a certain status to change the histogram level result
93 // (If the histogram status is not determined by a Chi-Squared test):
94 const int nRedBinsToRedStatus = (int) dqm_algorithms::tools::GetFirstFromMap("NBinsRedToRedStatus", config.getParameters(), 1);
95 const double redFracToRedStatus = dqm_algorithms::tools::GetFirstFromMap("RedFractionToRedStatus", config.getParameters(), 0.01);
96 const int nYellowBinsToYellowStatus = (int) dqm_algorithms::tools::GetFirstFromMap("NBinsYellowToYellowStatus", config.getParameters(), 1);
97 const double yellowFracToYellowStatus = dqm_algorithms::tools::GetFirstFromMap("YellowFractionToYellowStatus", config.getParameters(), 0.05);
98 const double greenFracToGreenStatus = dqm_algorithms::tools::GetFirstFromMap("GreenFractionToGreenStatus", config.getParameters(), 0.5);
99
100 // Minimum statistics for test:
101 const double minStat = dqm_algorithms::tools::GetFirstFromMap( "MinStat", config.getParameters(), -1);
102 if ( histogram->GetEntries() < minStat ) {
103 result->status_ = dqm_core::Result::Undefined;
104 return result;
105 }
106
107 // Parameter for exclusion of bins from consideration:
108 const double ignoreValue = dqm_algorithms::tools::GetFirstFromMap( "ignoreval", config.getParameters(), -99999);
109 const double minError = dqm_algorithms::tools::GetFirstFromMap( "minError", config.getParameters(), -1);
110
111 // Parameter giving the range of the histogram to be tested:
112 std::vector<int> range;
113 try{
114 range=dqm_algorithms::tools::GetBinRange(histogram, config.getParameters());
115 }
116 catch( dqm_core::Exception & ex ) {
117 throw dqm_core::BadConfig( ERS_HERE, name, ex.what(), ex );
118 }
119
120 const bool yStrips = static_cast<bool>(dqm_algorithms::tools::GetFirstFromMap( "useStripsOfConstantY", config.getParameters(), 0));
121
122 // Parameter giving minimal statistical significance for bin test results:
123 const double sigmaThresh = dqm_algorithms::tools::GetFirstFromMap("SigmaThresh", config.getParameters(), 5);
124 // Tag publishing options:
125 const bool publish = static_cast<bool>(dqm_algorithms::tools::GetFirstFromMap( "PublishBins", config.getParameters(), 0));
126 const bool publishRed = static_cast<bool>(dqm_algorithms::tools::GetFirstFromMap( "PublishRedBins", config.getParameters(), 0));
127 int maxPublish = (int) dqm_algorithms::tools::GetFirstFromMap( "MaxPublish", config.getParameters(), 50);
128 if (maxPublish > 999) maxPublish=999;
129
130 // Clustering options:
131 const bool clusterResults = static_cast<bool>(dqm_algorithms::tools::GetFirstFromMap( "ClusterResults", config.getParameters(), 1));
132 const double seedThreshold = dqm_algorithms::tools::GetFirstFromMap( "SeedThreshold", config.getParameters(), rthreshold);
133 const double growthThreshold = dqm_algorithms::tools::GetFirstFromMap( "GrowthThreshold", config.getParameters(), gthreshold);
134 const int topology = static_cast<int>(dqm_algorithms::tools::GetFirstFromMap( "Topology", config.getParameters(), tools::CylinderX));
135
136 // Test Directionality: exclude bins over(under) average by setting to a value other than 1:
137 const bool greaterThan = static_cast<bool>(dqm_algorithms::tools::GetFirstFromMap( "GreaterThan", config.getParameters(), 0));
138 const bool lessThan = static_cast<bool>(dqm_algorithms::tools::GetFirstFromMap( "LessThan", config.getParameters(), 0));
139 bool findBinsOverAvg = true;
140 bool findBinsUnderAvg = true;
141
142 if (!lessThan && greaterThan) {
143 findBinsUnderAvg = false;
144 }
145 else if (!greaterThan && lessThan) {
146 findBinsOverAvg = false;
147 }
148
149
150
151 // Master switch: trust errors and make this algorithm a test of whether that trust is warranted: (changes three defaults and final test)
152 const bool testConsistencyWithErrors = static_cast<bool>(dqm_algorithms::tools::GetFirstFromMap("TestConsistencyWithErrors", config.getParameters(), 0));
153
154 // Switch to use the mean error instead of the variance as the yard stick by which deviations are measured:
155 const bool useMeanErrorForScale = (testConsistencyWithErrors || static_cast<bool>(dqm_algorithms::tools::GetFirstFromMap("UseMeanErrorForScale", config.getParameters(), 0)));
156
157 // Switch to decide whether to do a Chi-Squared test:
158 const bool doChiSquaredTest = (testConsistencyWithErrors || static_cast<bool>(dqm_algorithms::tools::GetFirstFromMap("DoChiSquaredTest", config.getParameters(), 0)));
159
160 // Minimum bins required before(after) removal of outliers for testing of a strip to proceed:
161
162 //minimum number of bins left after skimming for bins in this strip to be tested:
163 int minBinsBeforeSkimming = (int) dqm_algorithms::tools::GetFirstFromMap("MinBinsBeforeSkimming", config.getParameters(), -1);
164 if (minBinsBeforeSkimming < 3) {
165 if ( !testConsistencyWithErrors ) minBinsBeforeSkimming = 50;
166 else minBinsBeforeSkimming = 8;
167 }
168 //minimum number of bins left after skimming for bins in this strip to be tested:
169 int minBinsAfterSkimming = (int) dqm_algorithms::tools::GetFirstFromMap("MinBinsAfterSkimming", config.getParameters(), -1);
170 if (minBinsAfterSkimming < 2) {
171 if ( !testConsistencyWithErrors ) minBinsAfterSkimming = 8;
172 else minBinsAfterSkimming = 3;
173 }
174
175 // What to do if minimum bin requirement is not met: mark all bins as "Undefined" or add them all to the next strip:
176 const bool combineStripsBeforeSkimming = static_cast<bool>(dqm_algorithms::tools::GetFirstFromMap("CombineStripsBeforeSkimming", config.getParameters(), 1));
177
178 // Parameter to declare a bin as green regardless of its relative deviation: (Also will exclude this bin from any clustering of bad bins)
179 double absDiffGreenThresh = dqm_algorithms::tools::GetFirstFromMap("AbsDiffGreenThresh", config.getParameters(), 0);
180
181
182
183
184
185 // Parameters for configuring the iterative oulier identification process:
186
187 // Switch to use error based outlier identification:
188 const bool findOutliersUsingErrors = (testConsistencyWithErrors || static_cast<bool>(dqm_algorithms::tools::GetFirstFromMap("FindOutliersUsingErrors", config.getParameters(), 0)));
189
190 // Switch to configure non error based outlier identification: (id based on shape of distribution)
191 int nIter = (int) dqm_algorithms::tools::GetFirstFromMap( "nIterations", config.getParameters(), 100); //Defines a maximum: iteration will terminate on stabilization.
192 double iterThresh = dqm_algorithms::tools::GetFirstFromMap("IterDeviationThresh", config.getParameters(), 2.075);
193 double iVarExp = dqm_algorithms::tools::GetFirstFromMap("IterVariationExponent", config.getParameters(), 0.275);
194 double isbf = dqm_algorithms::tools::GetFirstFromMap("IterScaleBiasCorrectionFactor", config.getParameters(), 0.4);
195 double ibc = dqm_algorithms::tools::GetFirstFromMap("IterBreakConstant", config.getParameters(), 25);
196
197// empty ratio
198 double emptyRatio = dqm_algorithms::tools::GetFirstFromMap("EmptyRatio",
199config.getParameters(), 0.3);
200 double outstandingRatio = dqm_algorithms::tools::GetFirstFromMap("OutstandingRatio",config.getParameters(), 50);
201
202 //=======================================================
203 //-- Setup --
204 //=======================================================
205 //Prepare for testing
206
207 int ixmax = range[1] - range[0] + 1;
208 int iymax = range[3] - range[2] + 1;
209
210 int ismax = ixmax;
211 int inmax = iymax;
212 if( yStrips) {
213 ismax = iymax;
214 inmax = ixmax;
215 }
216
217 //Build vectors to store the axis information more efficiently, keeping to Root's use of overflow bins to keep things
218 //intuitive, aswell as temporary arrays to facilitate booking of results histograms:
219 std::vector<double> xBinCenters;
220 std::vector<double> yBinCenters;
221 double * xBinEdges = new double[ixmax+1];
222 double * yBinEdges = new double[iymax+1];
223
224 //X-Axis:
225 xBinCenters.push_back( histogram->GetXaxis()->GetBinLowEdge(range[0]) ); //Underflow bin
226 for ( int i = range[0]; i <= range[1]; i++ ) {
227 xBinCenters.push_back( histogram->GetXaxis()->GetBinCenter(i) );
228 xBinEdges[i-range[0]] = histogram->GetXaxis()->GetBinLowEdge(i);
229 }
230 xBinEdges[ixmax] = histogram->GetXaxis()->GetBinUpEdge(range[1]);
231 xBinCenters.push_back( xBinEdges[ixmax] ); //Overflow bin
232
233 //Y-Axis:
234 yBinCenters.push_back( histogram->GetYaxis()->GetBinLowEdge(range[2]) ); //Underflow bin
235
236 for ( int j = range[2]; j <= range[3]; j++ ) {
237 yBinCenters.push_back( histogram->GetYaxis()->GetBinCenter(j) );
238 yBinEdges[j-range[2]] = histogram->GetYaxis()->GetBinLowEdge(j);
239 }
240 yBinEdges[iymax] = histogram->GetYaxis()->GetBinUpEdge(range[3]);
241 yBinCenters.push_back( yBinEdges[iymax] ); //Overflow bin
242
243 double * sBinEdges = xBinEdges;
244 if( yStrips ) {
245 sBinEdges = yBinEdges;
246 }
247
248 //Book result histograms:
249 TH2F* inputBins = new TH2F("inputBins", histogram->GetTitle(), ixmax, xBinEdges, iymax, yBinEdges);
250 TH2F* binwiseStatus = new TH2F("binewiseStatus", "BinsDiffByStrips Status Results per Bin", ixmax, xBinEdges,
251 iymax, yBinEdges);
252 TH2F* binDeviations = new TH2F("binDeviations","Input bin content normalized by skimmed average and variance per strip",
253 ixmax, xBinEdges, iymax, yBinEdges);
254 TH1F* stripAverages = new TH1F("stripAverages", "Average Value from Cells in Strip After Removal of Outliers",
255 ismax, sBinEdges);
256 TH1F* stripVariances = new TH1F("stripVariances","Standard Variance of Cells in Strip After Removal of Outliers",
257 ismax, sBinEdges);
258
259 delete[] xBinEdges;
260 delete[] yBinEdges;
261 //Intialize result variables:
262 double maxDeviation = 0;
263 std::vector <tools::binContainer> yellowBins;
264 std::vector <tools::binContainer> redBins;
265 int nBinsRed = 0;
266 int nBinsYellow = 0;
267 int nBinsGreen = 0;
268 int nBinsUndefined = 0;
269
270
271 //===============================================================================================
272 //-- Test --
273 //===============================================================================================
274 // Examination of bin values, filling of result histograms, and determination of dq result:
275
276 std::vector<std::vector<tools::binContainer> > strips;
277//test_change begin
278std::vector<tools::binContainer> AllBinInOneStrip;
279double emptyBinCounter=0;
280int name_flag = 0;
281//test_change end
282 //Loop to process histogram and pack it into a vector of strip vectors:
283 for ( int is = 1; is <= ismax; is++ ) {
284 std::vector<tools::binContainer> inputs;
285
286 int ix = is;
287 int iy = 1;
288 if ( yStrips ) {
289 iy = is;
290 ix = 1;
291 }
292 for ( int in = 1; in <= inmax; in++ ) {
293
294 if ( yStrips ) {
295 ix = in;
296 }
297 else {
298 iy = in;
299 }
300
301 int bin = histogram->GetBin(ix + range[0]-1,iy + range[2]-1);
302 double value = histogram->GetBinContent(bin);
303 double error = histogram->GetBinError(bin);
304 inputBins->SetBinContent(ix,iy,value);
305 inputBins->SetBinError(ix,iy,error);
306 if(value==0) emptyBinCounter++;
307tools::binContainer binContent_tmp = {value,error,1,ix,iy,xBinCenters[ix],yBinCenters[iy] };
308AllBinInOneStrip.push_back(binContent_tmp);
309 if( (value != ignoreValue) && (error > minError) ){
310 tools::binContainer binContent = {value,error,1,ix,iy,xBinCenters[ix],yBinCenters[iy] };
311
312 inputs.push_back(binContent);
313 }
314 else {
315 binwiseStatus->SetBinContent(ix,iy,dqm_core::Result::Disabled);
316 }
317 }
318
319 // If there are not enough bins in this strip and we are not combining strips, then
320 // all the active bins in this strip should be considered undefined and ignored.
321 if( (!combineStripsBeforeSkimming) && ((int)inputs.size() < minBinsBeforeSkimming) ) {
322 nBinsUndefined += inputs.size();
323 }
324 else if(not inputs.empty()) {
325 strips.push_back(std::move(inputs));
326 }
327 }
328
329 //If combine strips before skimming is on, combine the strips with the fewest active bins with their neighbors.
330 if( combineStripsBeforeSkimming ) {
331 tools::MergePastMinStat(strips,minBinsBeforeSkimming);
332 }
333
334
335 //Vectors to store values for chi-squared test, if one is performed: (could one be performed on deviations alone?)
336 std::vector<double> inputValues;
337 std::vector<double> inputErrors;
338 std::vector<double> stripAveragesVector;
339 std::vector<double> stripErrors;
340
341 std::vector<tools::binContainer> deviations;
342 //Loop over strips:
343 for( std::vector<std::vector<tools::binContainer> >::iterator stripItr = strips.begin(); stripItr != strips.end(); ++stripItr ) {
344
345 if ( stripItr->empty() ) {
346 continue;
347 }
348
349 //Find outliers and average when outliers are exluded:
350 double stripAvg = 0;
351 double iScale = 0;
352 int nIn = 0;
353 int nTot = stripItr->size();
354 if( findOutliersUsingErrors ) {
355 tools::findOutliersUsingErrors(*stripItr, stripAvg, iScale, nIn, absDiffGreenThresh);
356 }
357 else {
358 tools::findOutliers(*stripItr, stripAvg, iScale, nIn, nIter, iVarExp , iterThresh, isbf, ibc);
359 }
360
361 // Check if there are enough bins after outliers skimming for any bins from this strip to be flagged,
362 // if not, either label them all as undefined (error = -1) or combine with the next strip:
363 // (Note: in the second case we do not reset binContent.test:
364 // outliers found here will be excluded in the first iteration when they are processed with the next strip)
365
366 if ( (nIn < minBinsAfterSkimming) ) {
367 for (std::vector<tools::binContainer>::const_iterator it = stripItr->begin(); it != stripItr->end(); ++it) {
368 tools::binContainer deviationContainer = { 0, -3, -13, it->ix, it->iy, it->x, it->y };
369 deviations.push_back(deviationContainer);
370 }
371 continue; //Next strip;
372 }
373
374
375 double stripVariance = 0;
376 double stripVarianceError = 0;
377 double stripAvgError = 0;
378 double err2Sum = 0;
379
380 if( !useMeanErrorForScale ) {
381 // We will now calculate the variance with two methods, one using the the number of bins in (nIn), the number out,
382 // and range from above, and one looking at the standard variance of the nIn bins in inputs marked as good by
383 // findOutliers. We will then take a weighted average of the two measures as our final estimate of the variance of
384 // the underlying, outlier free population.
385
386 // Get range and measures of distribution:
387 double S2 = 0;
388 double sumSquaredDiffFromAvg = 0;
389 double sumCompensator = 0;
390 double err2Diff2Sum = 0;
391 double min = 0;
392 double max = 0;
393 nIn = 0;
394
395
396 for (std::vector<tools::binContainer>::const_iterator it = stripItr->begin(); it != stripItr->end(); ++it) {
397 //it->test will evaluate as true iff tools::findOutliers determined it was sufficiently close to the mean
398 // to not be a variance spoiling outlier:
399
400 if(it->test){
401 if( nIn == 0 ) {
402 min = it->value;
403 max = it->value;
404 }
405 if( it->value > max ) max = it->value;
406 if( it->value < min ) min = it->value;
407 nIn++;
408
409 double diffFromAvg = it->value - stripAvg;
410 sumSquaredDiffFromAvg += std::pow( diffFromAvg, 2);
411 sumCompensator += ( diffFromAvg ); //Use to compensate for floating point issues if they should crop up:
412 // (would be zero if precision was perfect)
413
414 double inputErr2 = std::pow(it->error,2.);
415 err2Sum += inputErr2;
416 err2Diff2Sum += inputErr2 * std::pow( diffFromAvg, 2);
417 }
418 }
419
420 // Record the range
421 double range = max - min;
422
423
424 //Method 1: ErfInverse:
425 double countingVariance = 0;
426 double countingWeight = 0;
427
428 if( (nTot != 0) && (range != 0) && ((nTot - nIn) != 0) ) {
429 double erfin = TMath::ErfInverse( (1.0 * nIn) / nTot );
430 double erfin2 = std::pow(erfin,2);
431
432 if( erfin2 != 0 ) {
433 countingVariance = range / (erfin * 2 * std::sqrt(2));
434 countingWeight = 8 * std::pow(erfin2 / (range * std::exp(erfin2)),2) * std::pow(1.0 * nTot,3.) / (M_PI * nIn * (nTot - nIn));
435 }
436 }
437
438 //Method 2: Compensated Bounded Variance:
439 double boundedVariance = 0;
440 double boundedWeight = 0;
441 double sumWeights = 0;
442 if(nIn > 2) {
443 S2 = (sumSquaredDiffFromAvg - (std::pow(sumCompensator,2)/nIn) )/(nIn - 1);
444 boundedVariance = std::sqrt(S2);
445 double boundEffect = 1;
446 double U = 0;
447 if( countingVariance != 0 ) {
448 U = range / (2 * countingVariance);
449 }
450 else if( boundedVariance != 0 ) {
451 U = range / (2 * boundedVariance);
452 }
453 if( U != 0 ) {
454 boundEffect = TMath::Erf( U / 2 ) ;
455 }
456 if(boundEffect != 0) {
457 boundedVariance = boundedVariance / boundEffect;
458 }
459 double boundedErr2 = 0;
460 if (S2 != 0) {
461 boundedErr2 = ( std::pow( err2Diff2Sum / (std::pow(nIn-1,2.) * S2), 2) + std::pow( boundedVariance*(1 - boundEffect)/2,2) );
462 }
463 if( boundedErr2 != 0 ) {
464 boundedWeight = 1/boundedErr2;
465 }
466 sumWeights = ( countingWeight + boundedWeight );
467 stripVariance = 0;
468 if(sumWeights != 0) {
469 //Recalculate boundEffect and rederive boundedVariance using preliminary combined strip variance:
470 stripVariance = (countingVariance * countingWeight + boundedVariance * boundedWeight ) / sumWeights;
471 if(stripVariance != 0 ) {
472 boundEffect = TMath::Erf( range / (4 * stripVariance) );
473 if( boundEffect != 0 ) {
474 boundedVariance = std::sqrt(S2) / boundEffect;
475 boundedErr2 = ( std::pow( err2Diff2Sum / (std::pow(nIn-1,2.) * S2), 2) + std::pow( boundedVariance*(1 - boundEffect)/2,2) );
476 }
477 }
478 }
479
480
481 }
482 else if ( iScale != 0 ){
483 //Use the iScale as a last resort, as method 1 is not very good with nIn <= 2 either, but give it a big error
484 boundedVariance = iScale;
485 boundedWeight = std::pow(iScale, -2);
486 }
487
488 // Make final Combination of the two variance estimations, weighted with their errors:
489 sumWeights = ( countingWeight + boundedWeight );
490 stripVariance = 0;
491
492 if(sumWeights != 0) {
493 stripVariance = (countingVariance * countingWeight + boundedVariance * boundedWeight ) / sumWeights;
494 stripVarianceError = 1./std::sqrt(sumWeights);
495
496 }
497 }
498 else if (nIn > 2) {
499 // Just calculate error based quantities and use these:
500 for (std::vector<tools::binContainer>::const_iterator it = stripItr->begin(); it != stripItr->end(); ++it) {
501 //it->test will evaluate as true iff tools::findOutliers determined it was sufficiently close to the mean
502 // to not be a variance spoiling outlier:
503 if(it->test){
504 err2Sum += std::pow(it->error,2.);
505 }
506 }
507 stripVariance = std::sqrt( err2Sum / nIn ); //<- what we would expect the variance to be if the errors are correct
508 stripVarianceError = stripVariance / std::sqrt( nIn );
509 }
510
511
512 // Calculate error on the mean:
513 stripAvgError = std::sqrt(err2Sum)/nIn;
514
515 int is = 0;
516 if (yStrips) {
517 is = stripItr->front().iy;
518 }
519 else {
520 is = stripItr->front().ix;
521 }
522
523 // Store final skimmed Average and Variance found for this strip:
524 stripAverages->SetBinContent(is,stripAvg);
525 stripAverages->SetBinError(is,stripAvgError);
526 stripVariances->SetBinContent(is,stripVariance);
527 stripVariances->SetBinError(is,stripVarianceError);
528
529
530 if(doChiSquaredTest) {
531 for (std::vector<tools::binContainer>::const_iterator it = stripItr->begin(); it != stripItr->end(); ++it) {
532 inputValues.push_back( it->value );
533 inputErrors.push_back( 0. );
534 stripAveragesVector.push_back( stripAvg );
535 stripErrors.push_back( stripVariance );
536 }
537 }
538
539 //Now find the deviation from the strip average, in multiples of the strip variance, for each bin in this strip:
540 for (std::vector<tools::binContainer>::const_iterator it = stripItr->begin(); it != stripItr->end(); ++it) {
541 double deviation = 0;
542 double deviationError = -1;
543 double diffFromAvg = it->value - stripAvg;
544
545// test_change begin
546 if(stripVariance > 0.00001){
547 deviation = diffFromAvg / stripVariance;
548 if ( nIn > 1 ) {
549 deviationError = sqrt( (( std::pow(it->error,2) + std::pow(stripAvgError,2) ) / std::pow(stripVariance,2))
550 + ( std::pow(diffFromAvg,2) * std::pow(stripVarianceError,2) / std::pow(stripVariance,4)) );
551
552 }
553 }
554 else {deviation=0;
555 deviationError=0;
556 if( (it->test==0) && (std::abs(it->value)/std::abs(stripAvg)) > outstandingRatio ) {
557 name_flag = 1;
558 }
559 } //test_change
560 int binStatus = 0;
561 if ( std::abs(diffFromAvg) < (absDiffGreenThresh + std::sqrt(std::pow(it->error,2) + (err2Sum/nIn))) ) {
562 binStatus = 3;
563 }
564 //Save bin for future processing and tests:
565 tools::binContainer deviationContainer = { deviation , deviationError, binStatus, it->ix, it->iy, it->x, it->y };
566 deviations.push_back(deviationContainer);
567 //Write bin to result histogram:
568 int bin = binDeviations->GetBin(it->ix,it->iy);
569 binDeviations->SetBinContent(bin,deviation);
570 binDeviations->SetBinError(bin,deviationError); // i change this
571 }
572 }
573
574
575 //If clustering of results is turned on, cluster the bins according to their deviation:
576 std::vector<tools::binCluster> clusters;
577 std::vector<tools::binCluster> redClusters;
578 std::vector<tools::binCluster> yellowClusters;
579 if(clusterResults) {
580
581 //First sort the bins:
582 std::sort( deviations.begin(), deviations.end(), dqm_algorithms::tools::binContainer::comp );
583
584 //Now map the deviations according to ix, iy,
585 std::vector<std::vector<tools::binContainer*> > binMap = makeBinMap(deviations, ixmax, iymax, topology);
586 //Now do the clustering:
587 for (std::vector<tools::binContainer>::iterator it = deviations.begin(); it != deviations.end(); ++it) {
588 if( (it->value > seedThreshold + it->error) && !it->test ) {
589 tools::binCluster cluster = tools::buildCluster(*it,binMap,xBinCenters,yBinCenters,growthThreshold,topology);
590 if(cluster.n > 1) {
591 // Only keep clusters with more than 1 bin
592 clusters.push_back(cluster);
593 }
594 else {
595 // Unmark this bin: it is not in a cluster
596 it->test = 0;
597 }
598 }
599 }
600
601
602 //Score each cluster based on the significance of its total deviation: (Using the same criteria to be used for bins)
603 for( std::vector<tools::binCluster>::const_iterator it = clusters.begin(); it != clusters.end(); ++it) {
604 double fabsDeviation = std::abs(it->value);
605 double significanceBound = sigmaThresh * it->error;
606 bool overAvg = ( it->value >= 0 );
607 if ( (findBinsOverAvg && overAvg) || (findBinsUnderAvg && !overAvg) ) {
608 if ( fabsDeviation > (gthreshold + significanceBound) ) {
609 if ( fabsDeviation > (rthreshold + significanceBound) ) {
610 nBinsRed += it->n;
611 if (publish || publishRed) {
612 redClusters.push_back(*it);
613 }
614 continue;
615 }
616 nBinsYellow += it->n;
617 if (publish) {
618 yellowClusters.push_back(*it);
619 }
620 }
621 }
622 }
623 }
624
625 tools::binContainer maxDevBin = { 0, -999.9, 0, 0, 0, 0, 0 };
626
627 // Now score each bin based on the significance of its deviation:
628 for (std::vector<tools::binContainer>::const_iterator it = deviations.begin(); it != deviations.end(); ++it) {
629 int bin = binwiseStatus->GetBin(it->ix,it->iy);
630 //Check for bins with no defined deviation / deviation error
631 if ( it->error < 0 ) {
632 binwiseStatus->SetBinContent(bin,dqm_core::Result::Undefined);
633 nBinsUndefined++;
634 continue;
635 }
636 //Check if this is the maximum deviation so far:
637 if (std::abs(it->value) > std::abs(maxDeviation) ) { // i change the maxDeviation to
638 // std::abs(maxDeviation)
639 maxDeviation = it->value;
640 maxDevBin = *it;
641 }
642 //Check if this bin was marked as green by a prior test:
643 if ( it->test == 3 ) {
644 binwiseStatus->SetBinContent(bin,dqm_core::Result::Green);
645 nBinsGreen++;
646 continue;
647 }
648
649
650 double fabsDeviation = std::abs(it->value);
651 double significanceBound = sigmaThresh * it->error;
652
653 //Flag Green bins:
654 if ( fabsDeviation < (gthreshold - significanceBound ) ) {
655 binwiseStatus->SetBinContent(bin,dqm_core::Result::Green);
656 nBinsGreen++;
657 continue;
658 }
659 bool overAvg = ( it->value >= 0 );
660 if ( (findBinsOverAvg && overAvg) || (findBinsUnderAvg && !overAvg) ) {
661 if ( fabsDeviation > (gthreshold + significanceBound) ) {
662 if ( fabsDeviation > (rthreshold + significanceBound) ) {
663
664 binwiseStatus->SetBinContent(bin,dqm_core::Result::Red);
665
666 //Only publish and count red bins here if they were not grouped in any cluster of bad bins:
667 if( it->test != 10 ) {
668 // Using map machinery to ensure proper ordering: worst bins should have preference in publishing.
669 if (publish || publishRed) {
670 redBins.push_back( *it );
671 }
672 nBinsRed++;
673 }
674 continue;
675 }
676
677 binwiseStatus->SetBinContent(bin,dqm_core::Result::Yellow);
678 //Similarly exclude clustered yellow bins from publishing and counting:
679 if( it->test != 10 ) {
680 if (publish) {
681 yellowBins.push_back( *it );
682 }
683 nBinsYellow++;
684 }
685 continue;
686 }
687 }
688 binwiseStatus->SetBinContent(bin,dqm_core::Result::Undefined);
689 nBinsUndefined++;
690 }
691//test_change begin
692tools::binContainer onebin_my={0,0,0,0,0,0,0};
693tools::binContainer onebin_my_pre={0,0,0,0,0,0,0};
694double maxvalue_pre=-1;
695std::vector<tools::binContainer> topBinEntries;
696std::vector<tools::binContainer> topDeviations;
697double emptyRatio_this = emptyBinCounter/(histogram->GetNbinsX()*histogram->GetNbinsY());
698if (emptyRatio_this > emptyRatio) name_flag=1;
699if(name_flag==1){
700 int NTopEntries=0;
701 if(AllBinInOneStrip.size()>10 ) NTopEntries=10;
702 else NTopEntries = AllBinInOneStrip.size();
703 int AllBinInOneStrip_size = AllBinInOneStrip.size();
704 bool *bin_entries_status = new bool [AllBinInOneStrip_size];
705 for(int i=0; i< AllBinInOneStrip_size; i++) bin_entries_status[i] = true;
706 for(int i=0;i<NTopEntries;i++){
707 double maxvalue=0;
708 int counter=0;
709 int counter2=0;
710 for(std::vector<tools::binContainer>::const_iterator it =AllBinInOneStrip.begin();it!=AllBinInOneStrip.end();++it){
711 int flag_my = i==0 || ( bin_entries_status[counter] && it->value <= maxvalue_pre);
712 if(std::abs(it->value) >= std::abs(maxvalue) && flag_my) {
713 maxvalue = it->value;
714 onebin_my = *it;
715 counter2 = counter;
716 }
717 counter++;
718 }
719 bin_entries_status[counter2]=0;
720if (onebin_my.x!= onebin_my_pre.x||onebin_my.y!=onebin_my_pre.y) topBinEntries.push_back(onebin_my);
721 maxvalue_pre = maxvalue;
722 onebin_my_pre = onebin_my;
723 }
724 delete[] bin_entries_status;
725}
726else {
727 int NTopdeviation=0;
728 if(deviations.size()>5) NTopdeviation = 5;
729 else NTopdeviation = deviations.size();
730 int deviations_size = deviations.size();
731 bool *bin_dev_status = new bool [ deviations_size];
732 for(int i=0; i< deviations_size ; i++) bin_dev_status[i] = true;
733 for(int i=0;i<NTopdeviation;i++){
734 double maxvalue=0;
735 int counter=0;
736 int counter2=0;
737 if(deviations.size()!=0){
738 for (std::vector<tools::binContainer>::const_iterator it = deviations.begin(); it != deviations.end(); ++it){
739 int flag_my = i==0 || ( bin_dev_status[counter] && it->value <= maxvalue_pre);
740 if(std::abs(it->value) >= std::abs(maxvalue) && flag_my) {
741 maxvalue = it->value;
742 onebin_my = *it;
743 counter2 = counter;
744 }
745 counter++;
746 }
747 bin_dev_status[counter2]=0;
748 if (onebin_my.x!= onebin_my_pre.x||onebin_my.y!=onebin_my_pre.y) {
749 topDeviations.push_back(onebin_my);
750 maxvalue_pre = maxvalue;
751 onebin_my_pre = onebin_my;
752 }
753}
754
755 }
756 delete[] bin_dev_status;
757 }
758 if ( publish || publishRed) {
759
760 int objectsPublished = 0;
761 int clustersPublished = 0;
762 // Publish red clusters first:
763 std::sort( redClusters.begin(), redClusters.end(), dqm_algorithms::tools::binCluster::comp );
764 std::vector<tools::binCluster>::const_reverse_iterator rbcrbegin = redClusters.rbegin();
765 std::vector<tools::binCluster>::const_reverse_iterator rbcrend = redClusters.rend();
766 for (std::vector<tools::binCluster>::const_reverse_iterator it = rbcrbegin;
767 it != rbcrend; ++it) {
768
769 if (objectsPublished < maxPublish) {
770 char ctag[256];
771 sprintf(ctag,"C%.3i-R-%.3iBins@ Eta=(%+.3f_to_%+.3f) Phi=(%+.3f_to_%+.3f) Center=(%+.3f,%+.3f) Radius=%+.3f",clustersPublished,it->n,
772 xBinCenters[it->ixmin],xBinCenters[it->ixmax],yBinCenters[it->iymin],yBinCenters[it->iymax],it->x,it->y,it->radius);
773
774 std::string tag = ctag;
775 int sizeDiff = 30 - tag.size();
776 if( sizeDiff > 0 ) {
777 tag.append(sizeDiff, '_');
778 }
779
780 result->tags_[tag] = it->value;
781 clustersPublished++;
782 objectsPublished++;
783 }
784 }
785
786
787 // Publish red bins next:
788 int binsPublished = 0;
789 std::sort( redBins.begin(), redBins.end(), dqm_algorithms::tools::binContainer::comp );
790
791 for ( std::vector<tools::binContainer>::const_reverse_iterator rIter = redBins.rbegin();
792 rIter != redBins.rend();
793 ++rIter) {
794 if (objectsPublished < maxPublish) {
795 char ctag[16];
796 sprintf(ctag,"%.3i-R-",binsPublished);
797 std::string tag = ctag;
798 tools::MakeBinTag(*rIter,tag);
799 result->tags_[tag] = rIter->value;
800 binsPublished++;
801 objectsPublished++;
802 }
803 else {
804 break;
805 }
806 }
807
808 // Now publish yellow bins:
809 if ( publish ) {
810 std::sort( yellowBins.begin(), yellowBins.end(), dqm_algorithms::tools::binContainer::comp );
811 for ( std::vector<tools::binContainer>::const_reverse_iterator rIter = yellowBins.rbegin();
812 rIter != yellowBins.rend();
813 ++rIter) {
814 if (objectsPublished < maxPublish) {
815 char ctag[16];
816 sprintf(ctag,"%.3i-Y-",binsPublished);
817 std::string tag = ctag;
818 tools::MakeBinTag(*rIter,tag);
819 result->tags_[tag] = rIter->value;
820 binsPublished++;
821 objectsPublished++;
822
823 }
824 else {
825 break;
826 }
827 }
828 }
829 //Lastly publish yellow clusters: (What are these, anyway?)
830 if ( publish ) {
831 std::sort( yellowClusters.begin(), yellowClusters.end(), dqm_algorithms::tools::binCluster::comp );
832 for (std::vector<tools::binCluster>::const_reverse_iterator it = yellowClusters.rbegin();
833 it != yellowClusters.rend(); ++it) {
834 if (objectsPublished < maxPublish) {
835 char ctag[256];
836 sprintf(ctag,"C%.3i-Y-%.3iBins@ Eta=(%+.3f_to_%+.3f) Phi=(%+.3f_to_%+.3f) Center=(%+.3f,%+.3f) Radius=%+.3f",clustersPublished,it->n,
837 xBinCenters[it->ixmin],xBinCenters[it->ixmax],yBinCenters[it->iymin],yBinCenters[it->iymax],it->x,it->y,it->radius);
838 std::string tag = ctag;
839 int sizeDiff = 30 - tag.size();
840 if( sizeDiff > 0 ) {
841 tag.append(sizeDiff, '_');
842 }
843 result->tags_[tag] = it->value;
844 clustersPublished++;
845 objectsPublished++;
846 }
847 }
848 }
849
850 }
851 result->tags_["NBins_RED"] = nBinsRed;
852 result->tags_["NBins_YELLOW"] = nBinsYellow;
853
854//test_change begin
855if(name_flag!=1){
856 for(unsigned int i=0;i<topDeviations.size();i++){
857 if(topDeviations[i].error !=-999.9 ) {
858 char tmp[100];
859 sprintf(tmp,"MaxDeviation%u-",i);
860 std::string myString = tmp;
861 tools::MakeBinTag(topDeviations[i], myString);
862 result->tags_[myString] = topDeviations[i].value;
863 }
864 }
865}
866if(name_flag==1) {
867 if( maxDevBin.error != -999.9 ) {
868 std::string devString = "MaxDeviation-";
869 tools::MakeBinTag(maxDevBin,devString);
870 result->tags_[devString] = maxDeviation;
871 }
872 for(unsigned int i=0;i<topBinEntries.size();i++){
873 char tmp[100];
874 sprintf(tmp,"LeadingBinContents%u-",i);
875 std::string myString = tmp;
876 tools::MakeBinTag(topBinEntries[i], myString);
877 result->tags_[myString] = topBinEntries[i].value;
878 }
879}
880//test_change end
881
882 result->tags_["Algorithm--BinsDiffByStrips"] = 5; //Provide algorithm name and number of results histograms in TObjArray, for convenience of summary maker:
883
884 //Determine if the configuration wants this to be part of an AndGroup, used by BinwiseSummary to require reds from the
885 // same bin in multiple plots for red to be propogated.
886 const double andGroup = dqm_algorithms::tools::GetFirstFromMap("AndGroup", config.getParameters(), -99999);
887 if( andGroup != -99999 ) {
888 result->tags_["AndGroup"] = andGroup;
889 }
890
891
892 TObjArray * resultList = new TObjArray(5,0);
893
894 //This order is important! Add new histograms at the end of the list only to avoid breaking summarymakers and be sure to increase
895 // the alocated capacity of the TObjArray set in the constructor above.
896 resultList->Add(binwiseStatus);
897 resultList->Add(inputBins);
898 resultList->Add(binDeviations);
899 resultList->Add(stripAverages);
900 resultList->Add(stripVariances);
901
902 resultList->SetOwner(true);
903
904 result->object_ = boost::shared_ptr<TObject>(resultList);
905
906
907 if( doChiSquaredTest ) {
908
909 std::pair<double,double> chiSquareResult = dqm_algorithms::tools::CalcBinsProbChisq(inputValues,inputErrors,stripAveragesVector,stripErrors);
910 result->tags_["SigmaChiSq"] = chiSquareResult.second;
911
912 if ( testConsistencyWithErrors ) {
913 //Determine status based on quality of chi squared fit:
914 if ( chiSquareResult.second <= gthreshold ) {
915 result->status_ = dqm_core::Result::Green;
916 } else if ( chiSquareResult.second < rthreshold ) {
917 result->status_ = dqm_core::Result::Yellow;
918 } else {
919 result->status_ = dqm_core::Result::Red;
920 }
921
922 return result;
923 }
924 }
925
926 // Determine status based on the number of red, yellow, green, and other bins:
927 int nActiveBins = nBinsGreen + nBinsRed + nBinsYellow + nBinsUndefined;
928 if( nActiveBins != 0 ) {
929 if ( (nBinsRed >= nRedBinsToRedStatus) || ((nBinsRed * 1.0 / nActiveBins) > redFracToRedStatus) ) {
930 result->status_ = dqm_core::Result::Red;
931 }
932 else if ( ((nBinsRed + nBinsYellow) >= nYellowBinsToYellowStatus)
933 || ((static_cast<double>(nBinsRed + nBinsYellow) / nActiveBins) > yellowFracToYellowStatus) ) {
934 result->status_ = dqm_core::Result::Yellow;
935 }
936 else if ( (nBinsGreen * 1.0 / nActiveBins ) >= greenFracToGreenStatus ) {
937 result->status_ = dqm_core::Result::Green;
938 }
939 else {
940 result->status_ = dqm_core::Result::Undefined;
941 }
942 }
943 else {
944 result->status_ = dqm_core::Result::Disabled;
945 }
946 return result;
947}
948
949
950void
952{
953
954 out<<"BinsDiffByStrips: Calculates Average bin value and variance for each strip of constant x and finds bins in that strip that our outliers from the mean\n"<<std::endl;
955 out<<"Mandatory Green/Red Threshold: MaxDeviation: size of deviation from mean, in multiples of variance, for bin to be considered Green/Red. Overall result is result for worst bin"<<std::endl;
956 out<<"Optional Parameter: MinStat: Minimum histogram statistics needed to return defined result"<<std::endl;
957 out<<"Optional Parameter: ignoreval: value to be ignored for calculating average, variance, and identifying bad bins. Ignored bins are flagged as Disabled"<<std::endl;
958 out<<"Optional Parameter: useStripsOfConstantY: compare bins in strips of constant Y rather than constant X, as is the defualt (set to 1 for true). Default = false"<<std::endl;
959
960 out<<"Optional Parameter: xmin: minimum x range"<<std::endl;
961 out<<"Optional Parameter: xmax: maximum x range"<<std::endl;
962 out<<"Optional Parameter: ymin: minimum y range"<<std::endl;
963 out<<"Optional Parameter: ymax: maximum y range"<<std::endl;
964 out<<"Optional Parameter: GreaterThan: check for bins which are GreaterThan average (set to 1 for true). Default = true"<<std::endl;
965 out<<"Optional Parameter: LessThan: check for bins which are LessThan average (set to 1 for true). Default = true"<<std::endl;
966 out<<"Optional Parameter: PublishBins: Save all bin quality decisions in output histogram and save Red and Yellow bins in tag output (set to 1 for true). Default = false"<<std::endl;
967 out<<"Optional Parameter: PublishRedBins: Save bins identified as Red in tag output(set to 1 for true). Default = false"<<std::endl;
968 out<<"Optional Parameter: MaxPublish: Max number of bins to save in tag output. Default = 20"<<std::endl;
969 out<<"Optional Parameter: MinBinsAfterSkimming : Minimum number of bins remaining after skimming for any bins to be flagged as Red/Yellow/Green. If threshold is not met, another attempt will be made at the iteration process with these few bin excluded in the first pass. Failing success, the entire strip will be flagged as Undefined. Default = 5"<<std::endl;
970 out<<"Optional Parameter: MinAbsDiffFromAvg : Bins whose absolute difference from the mean is less than this amount, in a statistically significant fashion, will always be flagged as green."
971 <<"Bin will be flagged as either Green or Undefined, depending on significance by which it passes this cut."<<std::endl;
972 out<<"Optional Parameter: nIterations : Number of iterations to be used in calculating mean and variance while skimming outliers. Default = 10" <<std::endl;
973 out<<"Optional Parameter: MaxNRetryIteration : Maxiumum number of times the iteration should be restarted should it fail (by leaving fewer than MinBinsAfterSkimming), reseeding with those cells that pass the iteration removed in the first pass. If MaxNRetryIteration = 0, will never retry. Default = 5. " <<std::endl;
974 out<<"Optional Parameter: IterVariationExponent: exponent k used in calculating the generalized variance, iVar, where iVar = (sum[ (abs[ x - xbar ])^k ])^(1/k). If k = 2, for instance, iVar is equivalent to the standard variance. (If nIterations = 1, this parameter has no effect.) Default = -1.4235"<<std::endl;
975 out<<"Optional Parameter: IterDeviationThresh : size of deviation from mean, in multiples of the generalized variance, for bin to be excluded during iterative calculation of mean and variance. (If nIterations = 1, this parameter has no effect.) Default = 1.3"<<std::endl;
976
977 out<<"Optional Parameter: SigmaThresh : Minimum significance (distance from threshold in multiples of the error) for quality statement to be made about a bin). Default = 5"<<std::endl;
978 out<<"Optional Parameter: FindOutliersUsingErrors : Switch to use outlier finding based on the pull of the mean of each bin given its error as compared to the error on the mean, rather than the default error independent aproach."<<std::endl;
979 out<<"Optional Parameter: UseMeanErrorForScale : Use the average error of the non-outliers, rather than their estimated variance, as the scale against which deviations are measured."<<std::endl;
980 out<<"Optional Parameter: DoChiSquaredTest : Calculate the Chi_Squared value for the distribution of all the bin values given the scale (estimated variance or, if UseMeanErrorForScale is used, mean error."<<std::endl;
981 out<<"Optional Parameter: TestConsistencyWithErrors : Switch on FindOutliersUsingErrors, UseMeanErrorForScale, and DoChiSquaredTest and base the DQ decision on the Chi-Squared result"<<std::endl;
982}
983void
984dqm_algorithms::BinsDiffByStrips::find_n(const std::string& name_tmp,int& name_flag){
985 int where = name_tmp.find_last_of("_");
986 std::string name;
987 name = name_tmp.substr(where+1);
988 if(name.compare("5Sigma")==0 || name_tmp.compare("m_EtavsPhi3")==0 || name_tmp.compare("m_EtavsPhi4")==0 ) name_flag=1;
989 else name_flag = 0;
990}
991
992
#define M_PI
static dqm_algorithms::BinContentComp myInstance
file declares the dqm_algorithms::BinContentComp class.
struct TBPatternUnitContext S2
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
std::string histogram
Definition chains.cxx:52
std::vector< int > GetBinRange(const TH1 *histogram, const std::map< std::string, double > &params)
void findOutliersUsingErrors(std::vector< binContainer > &input, double &mean, double &meanError, int &nIn, double mindiff=0, int minNin=4)
std::pair< double, double > CalcBinsProbChisq(const std::vector< double > &inputval, const std::vector< double > &inputerr, double x0, double x0_err)
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 MakeBinTag(const binContainer &bin, std::string &tag)
void MergePastMinStat(std::vector< std::vector< tools::binContainer > > &strips, int minStat)
void findOutliers(std::vector< binContainer > &input, double &mean, double &scale, int &nIn, int nIterations, double exponent, double threshold, double SBCF=1., double nStop=8.)
binCluster buildCluster(binContainer &seed, const std::vector< std::vector< binContainer * > > &binMap, const std::vector< double > &xValues, const std::vector< double > &yValues, double threhold, int topology=CylinderX)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
void find_n(const std::string &, int &)
dqm_core::Result * execute(const std::string &, const TObject &, const dqm_core::AlgorithmConfig &)
void printDescription(std::ostream &out)
static bool comp(const binCluster &lhs, const binCluster &rhs)
static bool comp(const binContainer &lhs, const binContainer &rhs)
#define IsA
Declare the TObject style functions.