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);
151 bool knownAnomaly=
false;
152 for(
auto& [
k,
v] : knownBins) {
153 if(
v.find({
i,j})!=
v.end()) {
154 knownAnomaly =
true;
break;
158 onestrip.push_back(binvalue);
159 stripSum += binvalue;
163 stripsAvg.push_back(stripSum/onestrip.size());
168 std::sort(onestrip.begin(),onestrip.end());
170 stripsMedian.push_back( onestrip.at(onestrip.size()/2) );
172 stripsVariance.push_back(
std::pow((onestrip.at(onestrip.size()*0.84) - onestrip.at(onestrip.size()*0.16))/2.,2) );
173 stripsN.push_back(onestrip.size());
175 if(stripsVariance.back() > 0) {
176 std::vector<double> stripRef;
177 for (
size_t i = 0;
i < onestrip.size();
i++) {
182 nextVal = (stripsVariance.back()>=100) ?
r.Gaus(stripsAvg.back(), std::sqrt(stripsVariance.back())) :
r.Poisson(stripsAvg.back());
183 }
while(nextVal<ignoreBelow);
184 stripRef.push_back(nextVal);
186 std::sort(stripRef.begin(),stripRef.end());
187 stripsProb.push_back( TMath::KolmogorovTest(onestrip.size(),&onestrip[0],stripRef.size(),&stripRef[0],
"") );
189 stripsProb.push_back(1);
192 if(nBinsZ>0 && filledRows.empty()) {
197 std::map<std::pair<int,int>,
bin>
bins;
199 double strip_median = stripsMedian[
k -
xmin];
200 double strip_variance = stripsVariance[
k -
xmin];
203 if (binvalue < ignoreBelow)
continue;
204 double residual = (strip_variance) ? ((binvalue - strip_median) / std::sqrt(strip_variance)) : 0;
211 bool testDeadStrips = (filledRows.size() == size_t(
ymax-
ymin+1));
216 counts[
"NDeadStrip"]= (testDeadStrips) ? 0 : -1;
219 counts[
"NConsecUnlikelyStrip"]=0;
220 for(
auto& [
cut,
k] : orderedCuts) {
225 int nUnlikelyStrips = 0;
226 for(
size_t i = 0;
i<stripsVariance.size();
i++) {
227 if (testDeadStrips && stripsVariance.at(
i) == 0 && stripsAvg.at(
i) == 0) {
229 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)) {
235 if (stripsProb.at(
i) < probThreshold) {
238 if(nUnlikelyStrips >
counts[
"NConsecUnlikelyStrip"])
counts[
"NConsecUnlikelyStrip"] = nUnlikelyStrips;
242 if(publishDetail & 0
x1) {
245 if(publishDetail & 0
x2) {
248 if(publishDetail & 0x4) {
251 if(publishDetail & 0x8) {
253 result->tags_[
TString::Format(
"_Noise%02ld",
i+1).Data()] = sqrt(std::abs(stripsVariance.at(
i) - stripsMedian.at(
i)));
267 if( (publishDetail & 0x10) &&
bin.
m_value==0) {
272 for(
auto& [
cut,
k] : orderedCuts) {
290 if(
bin.
m_value>0 && knownBins[
"Dead"].find({bin.m_ix,bin.m_iy})!=knownBins[
"Dead"].end()) {
294 }
else if(classCut != 0) {
296 for(
auto& [
cut,
k] : orderedCuts) {
298 if(
cut*classCut < 0) {
309 lastFilledResult =
result;
319 counts[
"NConsecUnlikelyStrip"]=0;
320 for(
auto& [
cut,
k] : orderedCuts) {
326 std::map<std::string,int> anomalies;
328 if(resultsByTimeBin.find(
t)==resultsByTimeBin.end()) {
330 for(
auto& [
k,
v] : anomalies) {
332 if(printLevel<=2) std::cout <<
" Got anomaly: " <<
k <<
" duration: " <<
v <<
" end: " <<
t << std::endl;
333 int lbStart =
histogram->GetXaxis()->GetBinLowEdge(
t-
v);
334 int lbEnd =
histogram->GetXaxis()->GetBinLowEdge(
t);
338 result->tags_[
k] = lastResult->tags_[
k];
345 if(
k.find(
"_DeadStrip")==0) {
347 }
else if(
k.find(
"_Dead")==0) {
349 }
else if(
k.find(
"_UnlikelyStrip")==0) {
351 }
else if(
k.find(
"_Un")==0) {
354 for(
auto& [
cut,k2] : orderedCuts) {
355 if(
k.find(
"_" + k2)==0) {
364 auto thisResult = resultsByTimeBin[
t];
365 if(liveMode && thisResult==lastFilledResult) {
372 for(
auto& [
k,
v] : thisResult->tags_) {
374 if(
k.find(
"_DeadStrip")==0) {
376 }
else if(
k.find(
"_Dead")==0) {
378 }
else if(
k.find(
"_UnlikelyStrip")==0) {
380 }
else if(
k.find(
"_Un")==0) {
383 for(
auto& [
cut,k2] : orderedCuts) {
384 if(
k.find(
"_" + k2)==0) {
393 for(
auto& [
k,
v] : anomalies) {
394 if(thisResult->tags_.find(
k) != thisResult->tags_.end())
continue;
396 int lbStart =
histogram->GetXaxis()->GetBinLowEdge(
t-
v);
397 int lbEnd =
histogram->GetXaxis()->GetBinLowEdge(
t);
405 if(
k.find(
"_DeadStrip")==0) {
407 }
else if(
k.find(
"_Dead")==0) {
409 }
else if(
k.find(
"_UnlikelyStrip")==0) {
411 }
else if(
k.find(
"_Un")==0) {
414 for(
auto& [
cut,k2] : orderedCuts) {
415 if(
k.find(
"_" + k2)==0) {
424 if(lastResult)
delete lastResult;
425 lastResult = thisResult;
428 if(lastResult)
delete lastResult;
433 result = resultsByTimeBin[-1];
440 const auto& redThresholds =
config.getRedThresholds();
441 const auto& greenThresholds =
config.getGreenThresholds();
443 if(publishDetail & 0x20) {
444 result->tags_[
"StatusCode"] = 0;
447 if(nBinsZ>0 &&
k==
"NConsecUnlikelyStrip")
continue;
451 if(publishDetail & 0x20) {
452 result->tags_[
"StatusCode"] = 3;
455 result->status_ = dqm_core::Result::Yellow;
456 if(publishDetail & 0x20) {
457 result->tags_[
"StatusCode"] = 2;
461 if(publishDetail & 0x20) {
462 result->tags_[
"StatusCode"] = 1;