Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ITS - rearrangement of plots and checks for shifters #2411

Merged
merged 4 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading