ATLAS Offline Software
Loading...
Searching...
No Matches
dqm_algorithms::L1Calo_BinsDiffFromStripMedian Struct Reference

#include <L1Calo_BinsDiffFromStripMedian.h>

Inheritance diagram for dqm_algorithms::L1Calo_BinsDiffFromStripMedian:
Collaboration diagram for dqm_algorithms::L1Calo_BinsDiffFromStripMedian:

Classes

class  bin

Public Member Functions

 L1Calo_BinsDiffFromStripMedian ()
 ~L1Calo_BinsDiffFromStripMedian ()
L1Calo_BinsDiffFromStripMedianclone ()
dqm_core::Result * execute (const std::string &, const TObject &, const dqm_core::AlgorithmConfig &)
void printDescription (std::ostream &out)

Detailed Description

Definition at line 21 of file L1Calo_BinsDiffFromStripMedian.h.

Constructor & Destructor Documentation

◆ L1Calo_BinsDiffFromStripMedian()

dqm_algorithms::L1Calo_BinsDiffFromStripMedian::L1Calo_BinsDiffFromStripMedian ( )

Definition at line 31 of file L1Calo_BinsDiffFromStripMedian.cxx.

32{
33 dqm_core::AlgorithmManager::instance().registerAlgorithm("L1Calo_BinsDiffFromStripMedian", this);
34}

◆ ~L1Calo_BinsDiffFromStripMedian()

dqm_algorithms::L1Calo_BinsDiffFromStripMedian::~L1Calo_BinsDiffFromStripMedian ( )

Definition at line 36 of file L1Calo_BinsDiffFromStripMedian.cxx.

37{
38}

Member Function Documentation

◆ clone()

dqm_algorithms::L1Calo_BinsDiffFromStripMedian * dqm_algorithms::L1Calo_BinsDiffFromStripMedian::clone ( )

◆ execute()

dqm_core::Result * dqm_algorithms::L1Calo_BinsDiffFromStripMedian::execute ( const std::string & name,
const TObject & object,
const dqm_core::AlgorithmConfig & config )

Definition at line 49 of file L1Calo_BinsDiffFromStripMedian.cxx.

51 {
52 const TH1* histogram;
53
54 if( object.IsA()->InheritsFrom( "TH1" ) ) {
55 histogram = static_cast<const TH1*>(&object);
56 if (histogram->GetDimension() > 2 ){
57 throw dqm_core::BadConfig( ERS_HERE, name, "dimension > 2 " );
58 }
59 } else {
60 throw dqm_core::BadConfig( ERS_HERE, name, "does not inherit from TH1" );
61 }
62
63 const double minstat = dqm_algorithms::tools::GetFirstFromMap( "MinStat", config.getParameters(), 100);
64 const double ignoreBelow = dqm_algorithms::tools::GetFirstFromMap( "IgnoreBelow", config.getParameters(), 0);
65 const double probThreshold = dqm_algorithms::tools::GetFirstFromMap( "ProbThreshold", config.getParameters(), 0.01);
66 const int publishDetail = dqm_algorithms::tools::GetFirstFromMap( "PublishDetail", config.getParameters(), 0x20/*publish status code - since saw some inconsistencies in webdisplay on local testing. Should plan to set to 0 in future*/);
67 const int nBinsZ = dqm_algorithms::tools::GetFirstFromMap( "NBinsY", config.getParameters(), 0); // if this is specified, plot is interpreted as being temporal ... this is number of bins in the 'y-axis' direction of each time slice
68 const int minDuration = dqm_algorithms::tools::GetFirstFromMap( "MinDuration", config.getParameters(),3); // when in temporal mode, this is the number of consecutive bins in the time axis (x-axis) that an anomaly must exist for to be flagged
69 const int liveMode = dqm_algorithms::tools::GetFirstFromMap( "LiveMode", config.getParameters(), 0); // if non-zero, running in live (p1) mode, will influence how results presented
70 const int printLevel = dqm_algorithms::tools::GetFirstFromMap("OutputLevel",config.getParameters(),3); // controls debugging printout .. follows same outputlevel codes as athena (3=info)
71
72 // use y-axis label to determine convention for temporal plot
73 bool reverseConvention = TString(histogram->GetYaxis()->GetTitle()).EndsWith("+y");
74
75 std::map<std::string,std::set<std::pair<int,int>>> knownBins; // bins which are known to be a particular class
76
77 auto knownBinParser = [&](const std::string& cutName) {
78 std::string known = dqm_algorithms::tools::GetFirstFromMap("Known"+cutName, config.getGenericParameters(), "");
79 // strip any non-numeric chars from the front
80 size_t i = 0;
81 while (i < known.length() && !std::isdigit(known[i])) {
82 i++;
83 }
84 known = known.substr(i);
85 known += ";"; // add final semicolon
86 i = known.find(",");
87 while(i != std::string::npos) {
88 size_t j = known.find(";");
89 knownBins[cutName].insert({TString(known.substr(0,i)).Atoi(),TString(known.substr(i+1,j-i-1)).Atoi()});
90 known = known.substr(j+1);
91 i = known.find(",");
92 }
93 };
94
95 std::vector<std::pair<double,std::string>> orderedCuts;
96 double mostNegativeCut = 0;
97 for(auto& [k,v] : config.getParameters()) {
98 TString kk(k);
99 if(!kk.EndsWith("Cut")) continue;
100 kk = kk(0,kk.Length()-3);
101 orderedCuts.push_back({v,kk.Data()});
102 mostNegativeCut = std::min(mostNegativeCut,v);
103 knownBinParser(kk.Data());
104 }
105 knownBinParser("Dead"); // also parse for any known dead spots
106
107 // order cuts by magnitude of cut, biggest first
108 std::sort(orderedCuts.begin(),orderedCuts.end(),[](const auto& v1, const auto& v2) { return std::abs(v1.first) > std::abs(v2.first); });
109
110 if ( histogram->GetEntries() < minstat ) {
111 dqm_core::Result *result = new dqm_core::Result(dqm_core::Result::Undefined);
112 result->status_ = dqm_core::Result::Yellow; // will treat almost-empty histograms as a warning .... shifter should think if this is expected
113 result->tags_["InsufficientEntries"] = histogram->GetEntries();
114 return result;
115 }
116
117
118 std::vector<int> range=dqm_algorithms::tools::GetBinRange(histogram, config.getParameters());
119
120 std::map<int,dqm_core::Result*> resultsByTimeBin;
121 std::map<std::string,int> counts;
122 dqm_core::Result* lastFilledResult = nullptr;
123 //if nBinsZ == 0, this loop executes *once* with t = -1
124 for(int t=(nBinsZ>0 ? range[0] : -1) ; t <= (nBinsZ>0 ? range[1] : -1); t++) {
125 int xmin = range[0], xmax = range[1];
126 int ymin = range[2], ymax = range[3];
127 if(t!=-1) {
128 // need to adjust ranges using y-axis bins and nBinsZ parameter
129 //coverity[DIVIDE_BY_ZERO]
130 xmin = 1; xmax = histogram->GetNbinsY()/nBinsZ;
131 ymin = 1; ymax = nBinsZ;
132 }
133
134
135 std::set<int> filledRows; // will only look for dead strips once all rows are filled
136
137 // compute medians, means, variances, k-test probabilities
138 std::vector<double> stripsMedian;
139 std::vector<double> stripsAvg;
140 std::vector<double> stripsVariance;
141 std::vector<size_t> stripsN;
142 std::vector<double> stripsProb;
143 TRandom3 r;
144 for ( int i = xmin; i <= xmax; ++i ) {
145 std::vector<double> onestrip;
146 double stripSum=0/*, stripSum2=0*/;
147 for ( int j = ymin; j <= ymax; ++j ) {
148 double binvalue = (nBinsZ<=0) ? histogram->GetBinContent(i,j) : histogram->GetBinContent(t,reverseConvention ? ((ymax-ymin+1)*(i-1)+j) : ((xmax-xmin+1)*(j-1)+i));
149 if (binvalue < ignoreBelow) continue;
150 if(binvalue>0) filledRows.insert(j); // used to veto running deadstrip tests on sparsely populated plots
151 // don't include known anomalous bins in strip calculations
152 bool knownAnomaly=false;
153 for(auto& [k,v] : knownBins) {
154 if(v.find({i,j})!=v.end()) {
155 knownAnomaly = true; break;
156 }
157 }
158 if(!knownAnomaly) {
159 onestrip.push_back(binvalue);
160 stripSum += binvalue;
161 }
162 //stripSum2 += binvalue*binvalue;
163 }
164 stripsAvg.push_back(stripSum/onestrip.size());
165 // traditional variance calculation, not robust to outliers
166 // leaving this commented for reference
167 //stripsVariance.push_back( stripSum2/onestrip.size() - std::pow(stripsAvg.back(),2) );
168
169 std::sort(onestrip.begin(),onestrip.end());
170
171 stripsMedian.push_back( onestrip.at(onestrip.size()/2) );
172 // estimate variance as square of half of the middle ~68% - more robust against outliers than calculating from sumw2
173 stripsVariance.push_back( std::pow((onestrip.at(onestrip.size()*0.84) - onestrip.at(onestrip.size()*0.16))/2.,2) );
174 stripsN.push_back(onestrip.size());
175 // also compute Kolmogorov test probability vs a same-size dataset generated from a gaussian with the strip mean and variance
176 if(stripsVariance.back() > 0) {
177 std::vector<double> stripRef;
178 for (size_t i = 0; i < onestrip.size(); i++) {
179 // use possion for variances less than 100 (corresponding ~ to averages fewer than 100)
180 // otherwise switch to gaussian
181 double nextVal = 0;
182 do {
183 nextVal = (stripsVariance.back()>=100) ? r.Gaus(stripsAvg.back(), std::sqrt(stripsVariance.back())) : r.Poisson(stripsAvg.back());
184 } while(nextVal<ignoreBelow);
185 stripRef.push_back(nextVal);
186 }
187 std::sort(stripRef.begin(),stripRef.end());
188 stripsProb.push_back( TMath::KolmogorovTest(onestrip.size(),&onestrip[0],stripRef.size(),&stripRef[0],"") );
189 } else {
190 stripsProb.push_back(1);
191 }
192 }
193 if(nBinsZ>0 && filledRows.empty()) {
194 continue; // don't create a result object for empty time slices
195 }
196
197 dqm_core::Result* result = new dqm_core::Result();
198 std::map<std::pair<int,int>,bin> bins;
199 for ( int k = xmin; k <= xmax; ++k ) {
200 double strip_median = stripsMedian[k - xmin];
201 double strip_variance = stripsVariance[k - xmin];
202 for (int l = ymin; l <= ymax; ++l) {
203 double binvalue = (nBinsZ<=0) ? histogram->GetBinContent(k,l) : histogram->GetBinContent(t,reverseConvention ? ((ymax-ymin+1)*(k-1)+l) : ((xmax-xmin+1)*(l-1)+k));
204 if (binvalue < ignoreBelow) continue;
205 double residual = (strip_variance) ? ((binvalue - strip_median) / std::sqrt(strip_variance)) : 0;
206 bins[{k,l}] = {/*histogram->GetXaxis()->GetBinCenter(k), histogram->GetYaxis()->GetBinCenter(l),*/ k, l,
207 binvalue, residual};
208 }
209 }
210
211
212 bool testDeadStrips = (filledRows.size() == size_t(ymax-ymin+1));
213
214
215
216 // ensure all counts defined, even if will end up being 0
217 counts["NDeadStrip"]= (testDeadStrips) ? 0 : -1; // use -1 to flag not running this test
218 counts["NDead"]=0;
219 counts["NWrongKnown"]=0;
220 counts["NConsecUnlikelyStrip"]=0;
221 for(auto& [cut,k] : orderedCuts) {
222 counts["N"+k] = 0;
223 }
224
225 // publish deadstrips (whole strip is 0), and unlikely strips
226 int nUnlikelyStrips = 0;
227 for(size_t i = 0;i<stripsVariance.size();i++) {
228 if (testDeadStrips && stripsVariance.at(i) == 0 && stripsAvg.at(i) == 0) {
229 // only dead if at least one of the neighbour strips has enough entries in it
230 if( (i>0 && (stripsAvg.at(i-1)*stripsN.at(i-1))>=minstat) || (i<stripsVariance.size()-1 && (stripsAvg.at(i+1)*stripsN.at(i+1))>=minstat)) {
231 result->tags_[TString::Format("_DeadStrip%02ld", i+1).Data()] = histogram->GetXaxis()->GetBinCenter(xmin + i);
232 counts["NDeadStrip"]++;
233 }
234
235 }
236 if (stripsProb.at(i) < probThreshold) {
237 result->tags_[TString::Format("_UnlikelyStrip%02ld", i+1).Data()] = -log(stripsProb.at(i));
238 nUnlikelyStrips++;
239 if(nUnlikelyStrips > counts["NConsecUnlikelyStrip"]) counts["NConsecUnlikelyStrip"] = nUnlikelyStrips;
240 } else {
241 nUnlikelyStrips=0; // reset counter
242 }
243 if(publishDetail & 0x1) {
244 result->tags_[TString::Format("_Median%02ld", i+1).Data()] = stripsMedian.at(i);
245 }
246 if(publishDetail & 0x2) {
247 result->tags_[TString::Format("_StdDev%02ld", i+1).Data()] = sqrt(stripsVariance.at(i));
248 }
249 if(publishDetail & 0x4) {
250 result->tags_[TString::Format("_Prob%02ld", i+1).Data()] = stripsProb.at(i);
251 }
252 if(publishDetail & 0x8) {
253 // attempt to estimate residual noise, by subtracting off the statistical variance (which equals the average, i.e. poissonian)
254 result->tags_[TString::Format("_Noise%02ld", i+1).Data()] = sqrt(std::abs(stripsVariance.at(i) - stripsMedian.at(i)));
255 }
256 }
257
258 // publish deadspots (anomalous 0s) and other anomalies defined by the cuts
259
260 for(auto& [pos,bin] : bins) {
261 if(bin.m_value==0 && bin.m_outstandingRatio < mostNegativeCut) {
262 // publish if spot is not known
263 if(knownBins["Dead"].find({bin.m_ix,bin.m_iy})==knownBins["Dead"].end()) {
264 result->tags_[TString::Format("_Dead(%d,%d)", bin.m_ix, bin.m_iy).Data()] = bin.m_outstandingRatio;
265 counts["NDead"]++;
266 }
267 } else {
268 if( (publishDetail & 0x10) && bin.m_value==0) {
269 result->tags_[TString::Format("_Zero(%d,%d)",bin.m_ix,bin.m_iy).Data()] = bin.m_outstandingRatio;
270 }
271 // loop through cuts, assign bin to one of the ranges, and report if not a known bin
272 double classCut = 0;
273 for(auto& [cut,k] : orderedCuts) {
274 if( (cut < 0 && bin.m_outstandingRatio < cut) || (cut > 0 && bin.m_outstandingRatio > cut && bin.m_value>=minstat) ) {
275 classCut = cut;
276 if(knownBins[k].find({bin.m_ix,bin.m_iy})==knownBins[k].end()) {
277 if(printLevel<=2) std::cout << " found " << k << " @ " << bin.m_ix << " " << bin.m_iy << " " << t << " : " << bin.m_outstandingRatio << std::endl;
278 result->tags_[TString::Format("_%s(%d,%d)", k.c_str(), bin.m_ix,
279 bin.m_iy).Data()] = bin.m_outstandingRatio;
280 counts["N"+k]++;
281 } else {
282 // report as a known anomaly
283 result->tags_[TString::Format("_Known%s(%d,%d)",k.c_str(), bin.m_ix,
284 bin.m_iy).Data()] = bin.m_outstandingRatio;
285 }
286 break;
287 }
288 }
289 // if this is a known bin in a given cut range, check if we have any evidence it is wrong
290 // start with known dead ... if this bin has an entry, its not dead
291 if(bin.m_value>0 && knownBins["Dead"].find({bin.m_ix,bin.m_iy})!=knownBins["Dead"].end()) {
292 counts["NWrongKnown"]++;
293 result->tags_[TString::Format("_UnDead(%d,%d)", bin.m_ix,
294 bin.m_iy).Data()] = bin.m_outstandingRatio;
295 } else if(classCut != 0) {
296 // if class cut is in opposite direction to known bin list, report that too
297 for(auto& [cut,k] : orderedCuts) {
298 if(knownBins[k].find({bin.m_ix,bin.m_iy})==knownBins[k].end()) continue;
299 if(cut*classCut < 0) {
300 counts["NWrongKnown"]++;
301 result->tags_[TString::Format("_Un%s(%d,%d)",k.c_str(), bin.m_ix,
302 bin.m_iy).Data()] = bin.m_outstandingRatio;
303 }
304 }
305 }
306 }
307 }
308
309 resultsByTimeBin[t] = result;
310 lastFilledResult = result;
311
312 }
313
314 dqm_core::Result* result;
315 if(nBinsZ>0) {
316 // ensure all counts defined, even if will end up being 0
317 counts["NDeadStrip"]= 0;
318 counts["NDead"]=0;
319 counts["NWrongKnown"]=0;
320 counts["NConsecUnlikelyStrip"]=0;
321 for(auto& [cut,k] : orderedCuts) {
322 counts["N"+k] = 0;
323 }
324 dqm_core::Result* lastResult = nullptr;
325 result = new dqm_core::Result();
326 // must now analyse results by time slice ... require a result in min number of consecutive slices to count an anomaly
327 std::map<std::string,int> anomalies;
328 for(int t=range[0];t<=range[1]+1;t++) { // go one extra slice to trigger 'empty slice' condition to write active anomalies
329 if(resultsByTimeBin.find(t)==resultsByTimeBin.end()) {
330 // empty slice .. record all sufficiently large anomalies and reset
331 for(auto& [k,v] : anomalies) {
332 if(v>=minDuration) {
333 if(printLevel<=2) std::cout << " Got anomaly: " << k << " duration: " << v << " end: " << t << std::endl;
334 int lbStart = histogram->GetXaxis()->GetBinLowEdge(t-v);
335 int lbEnd = histogram->GetXaxis()->GetBinLowEdge(t);
336 // in liveMode (for P1 monitoring), don't put the LBs in the result name, so that we get a consistent history plot
337 if (lastResult){
338 if(liveMode) {
339 result->tags_[k] = lastResult->tags_[k];//lastResult must not be null
340 } else {
341 result->tags_[k +
342 TString::Format("_LB%d-%d", lbStart, lbEnd).Data()] = lastResult->tags_[k];
343 }
344 }
345 // increment appropriate counter
346 if(k.find("_DeadStrip")==0) {
347 counts["NDeadStrip"]++;
348 } else if(k.find("_Dead")==0) {
349 counts["NDead"]++;
350 } else if(k.find("_UnlikelyStrip")==0) {
351 // not sure how to handle this one
352 } else if(k.find("_Un")==0) {
353 counts["NWrongKnown"]++;
354 } else {
355 for(auto& [cut,k2] : orderedCuts) {
356 if(k.find("_" + k2)==0) {
357 counts["N"+k2]++;
358 }
359 }
360 }
361 }
362 }
363 anomalies.clear();
364 } else {
365 auto thisResult = resultsByTimeBin[t];
366 if(liveMode && thisResult==lastFilledResult) {
367 // don't consider the time slice that is currently being filled, statistics not reliable
368 // can delete this slice because we wont use it
369 delete thisResult;
370 continue;
371 }
372 // increase counts on all active anomalies ...
373 for(auto& [k,v] : thisResult->tags_) {
374 // increment time counter for anomalies
375 if(k.find("_DeadStrip")==0) {
376 anomalies[k]++;
377 } else if(k.find("_Dead")==0) {
378 anomalies[k]++;
379 } else if(k.find("_UnlikelyStrip")==0) {
380 anomalies[k]++;
381 } else if(k.find("_Un")==0) {
382 anomalies[k]++;
383 } else {
384 for(auto& [cut,k2] : orderedCuts) {
385 if(k.find("_" + k2)==0) {
386 anomalies[k]++;
387 }
388 }
389 }
390 }
391
392 // reset counts on all disappeared anomalies (recording to results if was long enough)
393 // empty slice .. record all sufficiently large anomalies and reset
394 for(auto& [k,v] : anomalies) {
395 if(thisResult->tags_.find(k) != thisResult->tags_.end()) continue;
396 if(v>=minDuration) {
397 int lbStart = histogram->GetXaxis()->GetBinLowEdge(t-v);
398 int lbEnd = histogram->GetXaxis()->GetBinLowEdge(t);
399 if(liveMode) {
400 // don't record any result for an anomaly that has disappeared
401 } else {
402 result->tags_[k+TString::Format("_LB%d-%d",lbStart,lbEnd).Data()]=lastResult->tags_[k];
403 }
404
405 // increment appropriate counter
406 if(k.find("_DeadStrip")==0) {
407 counts["NDeadStrip"]++;
408 } else if(k.find("_Dead")==0) {
409 counts["NDead"]++;
410 } else if(k.find("_UnlikelyStrip")==0) {
411 // not sure how to handle this one
412 } else if(k.find("_Un")==0) {
413 counts["NWrongKnown"]++;
414 } else {
415 for(auto& [cut,k2] : orderedCuts) {
416 if(k.find("_" + k2)==0) {
417 counts["N"+k2]++;
418 }
419 }
420 }
421 }
422 v=0; // reset counter on the anomaly
423 }
424 // delete the lastResult if there is one
425 if(lastResult) delete lastResult;
426 lastResult = thisResult;
427 }
428 }
429 if(lastResult) delete lastResult; // cleans up unneeded results
430
431
432 } else {
433 // not doing a temporal analysis, just use the single result object
434 result = resultsByTimeBin[-1];
435 }
436
437
438
439 // determine algorithm status from provided thresholds
440
441 const auto& redThresholds = config.getRedThresholds();
442 const auto& greenThresholds = config.getGreenThresholds();
443 result->status_ = dqm_core::Result::Undefined;
444 if(publishDetail & 0x20) {
445 result->tags_["StatusCode"] = 0;
446 }
447 for(auto& [k,v] : counts) {
448 if(nBinsZ>0 && k=="NConsecUnlikelyStrip") continue; // not currently counting consecutive unlikely strips in temporal mode
449 result->tags_[k] = v;
450 if(v>dqm_algorithms::tools::GetFirstFromMap(k, redThresholds, std::numeric_limits<double>::max())||result->status_ == dqm_core::Result::Red) {
451 result->status_ = dqm_core::Result::Red;
452 if(publishDetail & 0x20) {
453 result->tags_["StatusCode"] = 3;
454 }
455 } else if(v>dqm_algorithms::tools::GetFirstFromMap(k, greenThresholds, std::numeric_limits<double>::max())) {
456 result->status_ = dqm_core::Result::Yellow;
457 if(publishDetail & 0x20) {
458 result->tags_["StatusCode"] = 2;
459 }
460 } else if(result->status_==dqm_core::Result::Undefined && greenThresholds.find(k)!=greenThresholds.end()) {
461 result->status_ = dqm_core::Result::Green;
462 if(publishDetail & 0x20) {
463 result->tags_["StatusCode"] = 1;
464 }
465 }
466 }
467
468
469 return result;
470
471}
static const std::vector< std::string > bins
std::string histogram
Definition chains.cxx:52
int r
Definition globals.cxx:22
std::string find(const std::string &s)
return a remapped string
Definition hcg.cxx:138
double xmax
Definition listroot.cxx:61
double ymin
Definition listroot.cxx:63
double xmin
Definition listroot.cxx:60
double ymax
Definition listroot.cxx:64
cut
This script demonstrates how to call a C++ class from Python Also how to use PyROOT is shown.
l
Printing final latex table to .tex output file.
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)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
#define IsA
Declare the TObject style functions.

◆ printDescription()

void dqm_algorithms::L1Calo_BinsDiffFromStripMedian::printDescription ( std::ostream & out)

Definition at line 475 of file L1Calo_BinsDiffFromStripMedian.cxx.

475 {
476
477 out<<"L1Calo_BinsDiffFromStripMedian: Calculates strip median and then find out bins which are aliens "<<std::endl;
478 out<<"Specify cuts with parameters named <cutName>Cut will generate a result of form Nxxx" << std::endl;
479 out<<"Specify known anomalies with Known<cutName> string argument - note any leading non-numeric char will be stripped" << std::endl;
480 out<<"Special results are: NDead (number of 0 bins below most negative cut), NDeadStrip (strips that are all 0 .. will be -1 if not got an entry in every row of plot), NConsecUnlikelyStrip (most consecutive strips that are below ProbThreshold)" << std::endl;
481 out<<"Thresholds can be set on any of the results\n"<<std::endl;
482
483 out<<"Optional Parameter: MinStat: Minimum histogram statistics needed to perform Algorithm, also min entries for warm/hot spots (cuts > 0), and min entries in neighbour strip to declare a strip dead"<<std::endl;
484 out<<"Optional Parameter: IgnoreBelow: values below which the bins wont be considered (default 0)"<<std::endl;
485 out<<"Optional Parameter: ProbThreshold: cutoff for strip k-test probabilities for strip to be considered unlikely (default 0.05)"<<std::endl;
486 out<<"Optional Parameter: PublishDetail: Bitmask of what extra info to publish about strips. Starting with MSB: AlgStatusCode,Zeros,Noise,Prob,StdDev,Median (default 100000)"<<std::endl;
487
488}

The documentation for this struct was generated from the following files: