11 #include <dqm_core/AlgorithmConfig.h>
14 #include <dqm_core/AlgorithmManager.h>
50 const TObject&
object,
51 const dqm_core::AlgorithmConfig&
config ) {
54 if(
object.
IsA()->InheritsFrom(
"TH1" ) ) {
57 throw dqm_core::BadConfig( ERS_HERE,
name,
"dimension > 2 " );
60 throw dqm_core::BadConfig( ERS_HERE,
name,
"does not inherit from TH1" );
73 bool reverseConvention = TString(
histogram->GetYaxis()->GetTitle()).EndsWith(
"+y");
75 std::map<std::string,std::set<std::pair<int,int>>> knownBins;
77 auto knownBinParser = [&](
const std::string& cutName) {
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()});
95 std::vector<std::pair<double,std::string>> orderedCuts;
96 double mostNegativeCut = 0;
97 for(
auto& [
k,
v] :
config.getParameters()) {
99 if(!
kk.EndsWith(
"Cut"))
continue;
101 orderedCuts.push_back({
v,
kk.Data()});
102 mostNegativeCut =
std::min(mostNegativeCut,
v);
103 knownBinParser(
kk.Data());
105 knownBinParser(
"Dead");
108 std::sort(orderedCuts.begin(),orderedCuts.end(),[](
const auto& v1,
const auto&
v2) { return std::abs(v1.first) > std::abs(v2.first); });
110 if (
histogram->GetEntries() < minstat ) {
112 result->status_ = dqm_core::Result::Yellow;
120 std::map<int,dqm_core::Result*> resultsByTimeBin;
121 std::map<std::string,int> counts;
124 for(
int t=(nBinsZ>0 ?
range[0] : -1) ;
t <= (nBinsZ>0 ?
range[1] : -1);
t++) {
134 std::set<int> filledRows;
137 std::vector<double> stripsMedian;
138 std::vector<double> stripsAvg;
139 std::vector<double> stripsVariance;
140 std::vector<size_t> stripsN;
141 std::vector<double> stripsProb;
144 std::vector<double> onestrip;
146 for (
int j =
ymin; j <=
ymax; ++j ) {
148 if (binvalue < ignoreBelow)
continue;
149 if(binvalue>0) filledRows.insert(j);
150 onestrip.push_back(binvalue);
151 stripSum += binvalue;
154 stripsAvg.push_back(stripSum/onestrip.size());
159 std::sort(onestrip.begin(),onestrip.end());
161 stripsMedian.push_back( onestrip.at(onestrip.size()/2) );
163 stripsVariance.push_back(
std::pow((onestrip.at(onestrip.size()*0.84) - onestrip.at(onestrip.size()*0.16))/2.,2) );
164 stripsN.push_back(onestrip.size());
166 if(stripsVariance.back() > 0) {
167 std::vector<double> stripRef;
168 for (
size_t i = 0;
i < onestrip.size();
i++) {
173 nextVal = (stripsVariance.back()>=100) ?
r.Gaus(stripsAvg.back(), std::sqrt(stripsVariance.back())) :
r.Poisson(stripsAvg.back());
174 }
while(nextVal<ignoreBelow);
175 stripRef.push_back(nextVal);
177 std::sort(stripRef.begin(),stripRef.end());
178 stripsProb.push_back( TMath::KolmogorovTest(onestrip.size(),&onestrip[0],stripRef.size(),&stripRef[0],
"") );
180 stripsProb.push_back(1);
183 if(nBinsZ>0 && filledRows.empty()) {
188 std::map<std::pair<int,int>,
bin>
bins;
190 double strip_median = stripsMedian[
k -
xmin];
191 double strip_variance = stripsVariance[
k -
xmin];
194 if (binvalue < ignoreBelow)
continue;
195 double residual = (strip_variance) ? ((binvalue - strip_median) / std::sqrt(strip_variance)) : 0;
202 bool testDeadStrips = (filledRows.size() == size_t(
ymax-
ymin+1));
207 counts[
"NDeadStrip"]= (testDeadStrips) ? 0 : -1;
209 counts[
"NWrongKnown"]=0;
210 counts[
"NConsecUnlikelyStrip"]=0;
211 for(
auto& [
cut,
k] : orderedCuts) {
216 int nUnlikelyStrips = 0;
217 for(
size_t i = 0;
i<stripsVariance.size();
i++) {
218 if (testDeadStrips && stripsVariance.at(
i) == 0 && stripsAvg.at(
i) == 0) {
220 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)) {
222 counts[
"NDeadStrip"]++;
226 if (stripsProb.at(
i) < probThreshold) {
229 if(nUnlikelyStrips > counts[
"NConsecUnlikelyStrip"]) counts[
"NConsecUnlikelyStrip"] = nUnlikelyStrips;
233 if(publishDetail & 0
x1) {
236 if(publishDetail & 0
x2) {
239 if(publishDetail & 0x4) {
242 if(publishDetail & 0x8) {
244 result->tags_[
TString::Format(
"_Noise%02ld",
i+1).Data()] = sqrt(std::abs(stripsVariance.at(
i) - stripsMedian.at(
i)));
258 if( (publishDetail & 0x10) &&
bin.
m_value==0) {
263 for(
auto& [
cut,
k] : orderedCuts) {
281 if(
bin.
m_value>0 && knownBins[
"Dead"].find({bin.m_ix,bin.m_iy})!=knownBins[
"Dead"].end()) {
282 counts[
"NWrongKnown"]++;
285 }
else if(classCut != 0) {
287 for(
auto& [
cut,
k] : orderedCuts) {
289 if(
cut*classCut < 0) {
290 counts[
"NWrongKnown"]++;
300 lastFilledResult =
result;
307 counts[
"NDeadStrip"]= 0;
309 counts[
"NWrongKnown"]=0;
310 counts[
"NConsecUnlikelyStrip"]=0;
311 for(
auto& [
cut,
k] : orderedCuts) {
317 std::map<std::string,int> anomalies;
319 if(resultsByTimeBin.find(
t)==resultsByTimeBin.end()) {
321 for(
auto& [
k,
v] : anomalies) {
323 if(printLevel<=2) std::cout <<
" Got anomaly: " <<
k <<
" duration: " <<
v <<
" end: " <<
t << std::endl;
324 int lbStart =
histogram->GetXaxis()->GetBinLowEdge(
t-
v);
325 int lbEnd =
histogram->GetXaxis()->GetBinLowEdge(
t);
329 result->tags_[
k] = lastResult->tags_[
k];
336 if(
k.find(
"_DeadStrip")==0) {
337 counts[
"NDeadStrip"]++;
338 }
else if(
k.find(
"_Dead")==0) {
340 }
else if(
k.find(
"_UnlikelyStrip")==0) {
342 }
else if(
k.find(
"_Un")==0) {
343 counts[
"NWrongKnown"]++;
345 for(
auto& [
cut,k2] : orderedCuts) {
346 if(
k.find(
"_" + k2)==0) {
355 auto thisResult = resultsByTimeBin[
t];
356 if(liveMode && thisResult==lastFilledResult) {
363 for(
auto& [
k,
v] : thisResult->tags_) {
365 if(
k.find(
"_DeadStrip")==0) {
367 }
else if(
k.find(
"_Dead")==0) {
369 }
else if(
k.find(
"_UnlikelyStrip")==0) {
371 }
else if(
k.find(
"_Un")==0) {
374 for(
auto& [
cut,k2] : orderedCuts) {
375 if(
k.find(
"_" + k2)==0) {
384 for(
auto& [
k,
v] : anomalies) {
385 if(thisResult->tags_.find(
k) != thisResult->tags_.end())
continue;
387 int lbStart =
histogram->GetXaxis()->GetBinLowEdge(
t-
v);
388 int lbEnd =
histogram->GetXaxis()->GetBinLowEdge(
t);
396 if(
k.find(
"_DeadStrip")==0) {
397 counts[
"NDeadStrip"]++;
398 }
else if(
k.find(
"_Dead")==0) {
400 }
else if(
k.find(
"_UnlikelyStrip")==0) {
402 }
else if(
k.find(
"_Un")==0) {
403 counts[
"NWrongKnown"]++;
405 for(
auto& [
cut,k2] : orderedCuts) {
406 if(
k.find(
"_" + k2)==0) {
415 if(lastResult)
delete lastResult;
416 lastResult = thisResult;
419 if(lastResult)
delete lastResult;
424 result = resultsByTimeBin[-1];
431 const auto& redThresholds =
config.getRedThresholds();
432 const auto& greenThresholds =
config.getGreenThresholds();
434 if(publishDetail & 0x20) {
435 result->tags_[
"StatusCode"] = 0;
437 for(
auto& [
k,
v] : counts) {
438 if(nBinsZ>0 &&
k==
"NConsecUnlikelyStrip")
continue;
442 if(publishDetail & 0x20) {
443 result->tags_[
"StatusCode"] = 3;
446 result->status_ = dqm_core::Result::Yellow;
447 if(publishDetail & 0x20) {
448 result->tags_[
"StatusCode"] = 2;
452 if(publishDetail & 0x20) {
453 result->tags_[
"StatusCode"] = 1;
467 out<<
"L1Calo_BinsDiffFromStripMedian: Calculates strip median and then find out bins which are aliens "<<std::endl;
468 out<<
"Specify cuts with parameters named <cutName>Cut will generate a result of form Nxxx" << std::endl;
469 out<<
"Specify known anomalies with Known<cutName> string argument - note any leading non-numeric char will be stripped" << std::endl;
470 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;
471 out<<
"Thresholds can be set on any of the results\n"<<std::endl;
473 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;
474 out<<
"Optional Parameter: IgnoreBelow: values below which the bins wont be considered (default 0)"<<std::endl;
475 out<<
"Optional Parameter: ProbThreshold: cutoff for strip k-test probabilities for strip to be considered unlikely (default 0.05)"<<std::endl;
476 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;