Skip to content

Commit

Permalink
ITS - rearrangement of plots and checks for shifters (#2411)
Browse files Browse the repository at this point in the history
* [WIP] ITS - rearrangements of plots and checks for shifters

* json typos

* Final modifications after local test

* forgotten...
  • Loading branch information
nicolovalle committed Sep 11, 2024
1 parent 2816baf commit 35fe424
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 7 deletions.
1 change: 1 addition & 0 deletions Modules/ITS/include/ITS/ITSChipStatusCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class ITSChipStatusCheck : public o2::quality_control::checker::CheckInterface
static const int NLayer = 7;
const int StaveBoundary[NLayer + 1] = { 0, 12, 28, 48, 72, 102, 144, 192 };
std::shared_ptr<TLatex> tInfo;
const int FeeIDBoundaryVsBarrel[4] = { 0, 144, 252, 432 };
};

} // namespace o2::quality_control_modules::its
Expand Down
4 changes: 4 additions & 0 deletions Modules/ITS/include/ITS/ITSChipStatusTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,13 @@ class ITSChipStatusTask final : public TaskInterface
void setAxisTitle(TH1* object, const char* xTitle, const char* yTitle);
void Beautify();
void getStavePoint(int layer, int stave, double* px, double* py);
int getFEEID(int barrel, int chipinbarrel);

static constexpr int NLayer = 7;
static constexpr int NLayerIB = 3;
const int nHicPerStave[NLayer] = { 1, 1, 1, 8, 8, 14, 14 };
const int nChipsPerHic[NLayer] = { 9, 9, 9, 14, 14, 14, 14 };
const int nChipsPerFeeID[3] = { 3, 56, 98 }; // index is the barrel
const int nChipsPerLayer[NLayer] = { 108, 144, 180, 2688, 3360, 8232, 9408 };
const int StaveBoundary[NLayer + 1] = { 0, 12, 28, 48, 72, 102, 144, 192 };
const int ChipBoundary[NLayer + 1] = { 0, 108, 252, 432, 3120, 6480, 14712, 24120 };
Expand All @@ -105,6 +108,7 @@ class ITSChipStatusTask final : public TaskInterface
int nQCCycleToMonitor = 10;
TString BarrelNames[3] = { "IB", "ML", "OB" };
TH2Poly* StaveOverview;
TH1D* FeeIDOverview;
int NCycleForOverview = 3;
int nRotationType = 1;
std::vector<int> CurrentDeadChips[3]; // Vectors of Dead Chips in current QC cycle
Expand Down
1 change: 1 addition & 0 deletions Modules/ITS/include/ITS/ITSDecodingErrorCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class ITSDecodingErrorCheck : public o2::quality_control::checker::CheckInterfac
void beautify(std::shared_ptr<MonitorObject> mo, Quality checkResult = Quality::Null) override;
std::vector<int> vListErrorIdBad, vListErrorIdMedium;
bool doFlatCheck = false;
std::map<int, std::vector<int>> vAlreadyCheckedFeeIDs{}; // alreadychecked[fee] = <vector of error flags to skip>
o2::itsmft::GBTLinkDecodingStat statistics;

private:
Expand Down
6 changes: 6 additions & 0 deletions Modules/ITS/itsChipStatus.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@
"moduleName": "QcITS",
"policy": "OnEachSeparately",
"detectorName": "ITS",
"checkParameters": {
"feeidlimitsIB": "1,1",
"feeidlimitsML": "1,0.87",
"feeidlimitsOL": "1,0.92",
"excludedfeeid": ""
},
"dataSource": [{
"type": "Task",
"name": "ITSChipStatus",
Expand Down
1 change: 1 addition & 0 deletions Modules/ITS/itsDecoding.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"policy": "OnEachSeparately",
"detectorName": "ITS",
"checkParameters": {
"checkfeeIDonlyonce": "true",
"DecLinkErrorLimits": "5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -1",
"DecLinkErrorLimitsRatio": "0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1",
"DecLinkErrorType": "0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0",
Expand Down
89 changes: 86 additions & 3 deletions Modules/ITS/src/ITSChipStatusCheck.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,37 @@ namespace o2::quality_control_modules::its

Quality ITSChipStatusCheck::check(std::map<std::string, std::shared_ptr<MonitorObject>>* moMap)
{

// limits to be used as "X,Y" --> BAD if at least X FFEIDs have at least Y chips each into error
std::vector<float> feeidlimitsIB = convertToArray<float>(o2::quality_control_modules::common::getFromConfig<string>(mCustomParameters, "feeidlimitsIB", ""));
std::vector<float> feeidlimitsML = convertToArray<float>(o2::quality_control_modules::common::getFromConfig<string>(mCustomParameters, "feeidlimitsML", ""));
std::vector<float> feeidlimitsOL = convertToArray<float>(o2::quality_control_modules::common::getFromConfig<string>(mCustomParameters, "feeidlimitsOL", ""));
std::vector<int> excludedfeeid = convertToArray<int>(o2::quality_control_modules::common::getFromConfig<string>(mCustomParameters, "excludedfeeid", ""));

if (feeidlimitsIB.size() != 2) {
ILOG(Error, Support) << "Incorrect setting for feeidlimitsIB, check .json. Using default 1,1" << ENDM;
feeidlimitsIB.clear();
feeidlimitsIB = std::vector<float>{ 1, 1. };
}
if (feeidlimitsML.size() != 2) {
ILOG(Error, Support) << "Incorrect setting for feeidlimitsML, check .json. Using default 1,1" << ENDM;
feeidlimitsML.clear();
feeidlimitsML = std::vector<float>{ 1, 1. };
}
if (feeidlimitsOL.size() != 2) {
ILOG(Error, Support) << "Incorrect setting for feeidlimitsOL, check .json. Using default 1,1" << ENDM;
feeidlimitsOL.clear();
feeidlimitsOL = std::vector<float>{ 1, 1. };
}

Quality result = Quality::Null;
for (auto& [moName, mo] : *moMap) {

if (mo->getName() == "StaveStatusOverview") {
result = Quality::Good;
auto* h = dynamic_cast<TH2Poly*>(mo->getObject());
if (h == nullptr) {
ILOG(Error, Support) << "could not cast ChipError plots to TH2Poly" << ENDM;
ILOG(Error, Support) << "could not cast StaveStatusOverview plot from ChipError to TH2Poly" << ENDM;
continue;
}
for (int ilayer = 0; ilayer < NLayer; ilayer++) {
Expand All @@ -49,6 +73,41 @@ Quality ITSChipStatusCheck::check(std::map<std::string, std::shared_ptr<MonitorO
}
}
}

if (mo->getName() == "FEEIDOverview") {
result = Quality::Good;
auto* h = dynamic_cast<TH1D*>(mo->getObject());
if (h == nullptr) {
ILOG(Error, Support) << "could not cast FEEIDoverview plot from ChipStatus to TH1D" << ENDM;
continue;
}

int nBadIB = 0;
int nBadML = 0;
int nBadOL = 0;
for (int ifee = 0; ifee < h->GetNbinsX(); ifee++) {

if (excludedfeeid.size() > 0 && std::find(excludedfeeid.begin(), excludedfeeid.end(), ifee) != excludedfeeid.end()) {
continue;
}

if (ifee >= FeeIDBoundaryVsBarrel[0] && ifee < FeeIDBoundaryVsBarrel[1] && h->GetBinContent(ifee + 1) >= feeidlimitsIB[1]) {
nBadIB++;
}
if (ifee >= FeeIDBoundaryVsBarrel[1] && ifee < FeeIDBoundaryVsBarrel[2] && h->GetBinContent(ifee + 1) >= feeidlimitsML[1]) {
nBadML++;
}
if (ifee >= FeeIDBoundaryVsBarrel[2] && ifee < FeeIDBoundaryVsBarrel[3] && h->GetBinContent(ifee + 1) >= feeidlimitsOL[1]) {
nBadOL++;
}
}

if (nBadIB >= feeidlimitsIB[0] || nBadML >= feeidlimitsML[0] || nBadOL >= feeidlimitsOL[0]) {
result = Quality::Bad;
TString text = "At least one FEEid with large number of missing chips";
result.addFlag(o2::quality_control::FlagTypeFactory::Unknown(), text.Data());
}
}
}
return result;
}
Expand All @@ -57,10 +116,34 @@ void ITSChipStatusCheck::beautify(std::shared_ptr<MonitorObject> mo, Quality che
{
TString status;
int textColor;
if ((mo->getName() == "StaveStatusOverview")) {

if ((string)mo->GetName() == "FEEIDOverview") {
auto* h = dynamic_cast<TH1D*>(mo->getObject());
if (h == nullptr) {
ILOG(Error, Support) << "could not cast FEEIDOverview to TH1D*" << ENDM;
return;
}

if (checkResult == Quality::Good) {
status = "Quality::GOOD";
textColor = kGreen;
} else if (checkResult == Quality::Bad) {
status = "Quality::BAD (call expert)";
textColor = kRed + 2;
}

tInfo = std::make_shared<TLatex>(0.05, 0.95, Form("#bf{%s}", status.Data()));
tInfo->SetTextColor(textColor);
tInfo->SetTextSize(0.06);
tInfo->SetTextFont(43);
tInfo->SetNDC();
h->GetListOfFunctions()->Add(tInfo->Clone());
}

if ((string)mo->getName() == "StaveStatusOverview") {
auto* h = dynamic_cast<TH2Poly*>(mo->getObject());
if (h == nullptr) {
ILOG(Error, Support) << "could not cast StatusOverview to TH2Poly*" << ENDM;
ILOG(Error, Support) << "could not cast StaveStatusOverview to TH2Poly*" << ENDM;
return;
}
if (checkResult == Quality::Good) {
Expand Down
46 changes: 43 additions & 3 deletions Modules/ITS/src/ITSChipStatusTask.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ void ITSChipStatusTask::initialize(o2::framework::InitContext& /*ctx*/)
}
}
getObjectsManager()->startPublishing(StaveOverview);

FeeIDOverview = new TH1D("FEEIDOverview", Form("Fraction of missing chips in the last %d cycles;QC FEEid;fraction of missing chips", NCycleForOverview), NFees, 0, NFees);
getObjectsManager()->startPublishing(FeeIDOverview);
}

void ITSChipStatusTask::setAxisTitle(TH1* object, const char* xTitle, const char* yTitle)
Expand Down Expand Up @@ -131,6 +134,22 @@ void ITSChipStatusTask::getStavePoint(int layer, int stave, double* px, double*
}
}

int ITSChipStatusTask::getFEEID(int barrel, int chipinbarrel)
{
if (barrel == 0) {
return chipinbarrel / nChipsPerFeeID[0];
}
if (barrel == 1) {
return ChipsBoundaryBarrels[1] / nChipsPerFeeID[0] + chipinbarrel / nChipsPerFeeID[1];
}
if (barrel == 2) {
return (ChipsBoundaryBarrels[1] / nChipsPerFeeID[0]) +
((ChipsBoundaryBarrels[2] - ChipsBoundaryBarrels[1]) / nChipsPerFeeID[1]) +
chipinbarrel / nChipsPerFeeID[2];
}
return -1;
}

void ITSChipStatusTask::monitorData(o2::framework::ProcessingContext& ctx)
{
auto aliveChips = ctx.inputs().get<gsl::span<char>>("chipstatus");
Expand Down Expand Up @@ -179,6 +198,21 @@ void ITSChipStatusTask::endOfCycle()
Beautify();
//---------- Shifter plot

FeeIDOverview->Reset();
for (int iBarrel = 0; iBarrel < 3; iBarrel++) {
TH1D* hBarProj = DeadChips[iBarrel]->getNum()->ProjectionY("temp", TMath::Max(1, nQCCycleToMonitor - NCycleForOverview + 1), nQCCycleToMonitor);

for (int ic = 0; ic < hBarProj->GetNbinsX(); ic++) {
if (hBarProj->GetBinContent(ic + 1) < NCycleForOverview) { // report only chips dead for N consecutive cycles
continue;
}
FeeIDOverview->Fill(getFEEID(iBarrel, ic), 1. / nChipsPerFeeID[iBarrel]);
}
}
FeeIDOverview->Sumw2(kFALSE);
FeeIDOverview->SetMinimum(0);
FeeIDOverview->SetMaximum(1);

int iLayer = 0;
int iStave = 0;
StaveOverview->Reset("content");
Expand All @@ -190,11 +224,16 @@ void ITSChipStatusTask::endOfCycle()
TH1D* hBarrelProj = DeadChips[iBarrel]->getNum()->ProjectionY("dummy", nQCCycleToMonitor - iSlice, nQCCycleToMonitor - iSlice);
iStave = 0;
int nEmptyChips = 0;

for (int iChip = 1; iChip <= hBarrelProj->GetNbinsX(); iChip++) {

if (hBarrelProj->GetBinContent(iChip) > 0)
nEmptyChips++;
if (((iChip) % (nChipsPerHic[iLayer] * nHicPerStave[iLayer]) == 0)) {
if (nEmptyChips == nChipsPerHic[iLayer] * nHicPerStave[iLayer]) {

if ((iChip) % (nChipsPerHic[iLayer] * nHicPerStave[iLayer]) == 0) {

if (nEmptyChips == nChipsPerHic[iLayer] * nHicPerStave[iLayer]) { // all the chips of the stave are dead

int binContent = StaveOverview->GetBinContent(iStave + StaveBoundary[iLayer]) * NCycleForOverview + 1;
StaveOverview->SetBinContent(iStave + StaveBoundary[iLayer], 1. * binContent / NCycleForOverview);
}
Expand All @@ -204,7 +243,8 @@ void ITSChipStatusTask::endOfCycle()
iLayer++;
iStave = 0;
}
}

} // end of ((iChip) % (nChipsPerHic[iLayer] * nHicPerStave[iLayer]) == 0)
}
}
}
Expand Down
69 changes: 68 additions & 1 deletion Modules/ITS/src/ITSDecodingErrorCheck.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,13 @@ Quality ITSDecodingErrorCheck::check(std::map<std::string, std::shared_ptr<Monit
doFlatCheck = true;
}

bool checkFeeIDOnce = o2::quality_control_modules::common::getFromConfig<bool>(mCustomParameters, "checkfeeIDonlyonce", "");

Quality result = Quality::Null;
for (auto& [moName, mo] : *moMap) {
(void)moName;
if (mo->getName() == "General/ChipErrorPlots") {

if ((string)mo->getName() == "General/ChipErrorPlots") {
result = Quality::Good;
auto* h = dynamic_cast<TH1D*>(mo->getObject());
if (h == nullptr) {
Expand All @@ -67,6 +70,45 @@ Quality ITSDecodingErrorCheck::check(std::map<std::string, std::shared_ptr<Monit
result.set(Quality::Bad);
}

if ((string)mo->GetName() == "General/LinkErrorVsFeeid") {

result = Quality::Good;
auto* h = dynamic_cast<TH2D*>(mo->getObject());
if (h == nullptr) {
ILOG(Error, Support) << "could not cast LinkErrorVsFeeid plot to TH2D*" << ENDM;
continue;
}
for (int ifee = 0; ifee < h->GetNbinsX(); ifee++) {
for (int ierr = 0; ierr < h->GetNbinsY() - 1; ierr++) { // last y bin is recovery flag: do not check

if ((doFlatCheck && h->GetBinContent(ifee, ierr + 1) == 0) || (!doFlatCheck && h->GetBinContent(ifee + 1, ierr + 1) < vDecErrorLimits[ierr])) { // ok if below threshold
continue;
}

if (vAlreadyCheckedFeeIDs.count(ifee) > 0) {
std::vector<int> flagskip = vAlreadyCheckedFeeIDs[ifee];
if (std::find(flagskip.begin(), flagskip.end(), ierr) != flagskip.end()) {
continue; // bin to be skipped
}
}

// if here, quality is BAD

if (checkFeeIDOnce) { // gives instruction to exclude chech on this bin from now on
if (vAlreadyCheckedFeeIDs.count(ifee) > 0) {
vAlreadyCheckedFeeIDs[ifee].push_back(ierr);
} else {
vAlreadyCheckedFeeIDs[ifee] = std::vector<int>{ ierr };
}
}

result.set(Quality::Bad);
result.addFlag(o2::quality_control::FlagTypeFactory::Unknown(), Form("BAD: ID = %d, %s", ierr, std::string(statistics.ErrNames[ierr]).c_str()));

} // end of y axis loop
} // end of x axis loop
} // end of check on General/LinkErrorVsFeeid

if (((string)mo->getName()).find("General/LinkErrorPlots") != std::string::npos) {
result = Quality::Good;
auto* h = dynamic_cast<TH1D*>(mo->getObject());
Expand Down Expand Up @@ -137,6 +179,31 @@ void ITSDecodingErrorCheck::beautify(std::shared_ptr<MonitorObject> mo, Quality

TString status;
int textColor;

if (((string)mo->GetName()).find("General/LinkErrorVsFeeid") != std::string::npos) {

auto* h = dynamic_cast<TH2D*>(mo->getObject());
if (h == nullptr) {
ILOG(Error, Support) << "could not cast LinkErrorVsFeeid plot to TH2D*" << ENDM;
return;
}
if (checkResult == Quality::Good) {
status = "Quality::GOOD";
textColor = kGreen;
} else if (checkResult == Quality::Bad) {
status = "Quality::BAD (call expert)";
textColor = kRed + 2;
}

tInfo = std::make_shared<TLatex>(0.05, 0.95, Form("#bf{%s}", status.Data()));
tInfo->SetTextColor(textColor);
tInfo->SetTextSize(0.06);
tInfo->SetTextFont(43);
tInfo->SetNDC();
h->GetListOfFunctions()->Add(tInfo->Clone());

} // end of beautify LinkErrorVsFeeid

if ((((string)mo->getName()).find("General/LinkErrorPlots") != std::string::npos) || (mo->getName() == "General/ChipErrorPlots")) {
auto* h = dynamic_cast<TH1D*>(mo->getObject());
if (h == nullptr) {
Expand Down

0 comments on commit 35fe424

Please sign in to comment.