Skip to content

Commit 7f3bfdc

Browse files
authored
Add first working prototype of QC on TOF digits (#394)
* Add check on TOF digits * Add variables for cuts, add msg, improve style * Use info about TDC, ToT, Mult in sectors - To be fixed: sector decision, digit count in sectors * Filling hit mult. in every sector, filling time in every sector * Unified digit loops * Add realistic splitting in A/C O/I sides * Format header * Add support for newline * Add TObjArray.h as include
1 parent 2a5944b commit 7f3bfdc

3 files changed

Lines changed: 143 additions & 49 deletions

File tree

Modules/TOF/include/TOF/TOFCheckRawsMulti.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#define QC_MODULE_TOF_TOFCHECKRAWSMULTI_H
1818

1919
#include "QualityControl/CheckInterface.h"
20+
#include "TString.h"
2021

2122
namespace o2::quality_control_modules::tof
2223
{
@@ -38,10 +39,16 @@ class TOFCheckRawsMulti : public o2::quality_control::checker::CheckInterface
3839
void beautify(std::shared_ptr<MonitorObject> mo, Quality checkResult) override;
3940
std::string getAcceptedType() override;
4041

41-
/// Minumum value of TOF raw hit multiplicity
42+
/// Minimum value of TOF raw hit multiplicity
4243
Float_t minTOFrawhits;
4344
/// Maximum value of TOF raw hit multiplicity
4445
Float_t maxTOFrawhits;
46+
/// Fraction of the total integral which are considered Ok at 0 mult
47+
const Float_t fracAtZeroMult = 0.75;
48+
/// Fraction of the total integral which are considered Ok at low mult
49+
const Float_t fracAtLowMult = 0.75;
50+
/// Maximum average TOF raw hit multiplicity in Pb-Pb
51+
const Float_t maxTOFrawhitsPbPb = 500;
4552

4653
private:
4754
/// Mean of the TOF hit multiplicity histogram
@@ -52,6 +59,8 @@ class TOFCheckRawsMulti : public o2::quality_control::checker::CheckInterface
5259
Float_t lowMIntegral;
5360
/// Number of events with TOF hits multiplicity > 0
5461
Float_t totIntegral;
62+
/// Message to print
63+
TString shifter_msg = "";
5564

5665
ClassDefOverride(TOFCheckRawsMulti, 1);
5766
};

Modules/TOF/src/TOFCheckRawsMulti.cxx

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <TH1.h>
2424
#include <TPaveText.h>
2525
#include <TList.h>
26+
#include <TObjArray.h>
2627

2728
using namespace std;
2829

@@ -80,73 +81,79 @@ Quality TOFCheckRawsMulti::check(std::map<std::string, std::shared_ptr<MonitorOb
8081
// h->SetBit(AliQAv1::GetImageBit(), kTRUE);
8182
// }
8283
// }
83-
if (h->GetEntries() == 0) {
84+
if (h->GetEntries() == 0) { // Histogram is empty
8485
result = Quality::Medium;
8586
// flag = AliQAv1::kWARNING;
86-
} else {
87+
shifter_msg = "No counts!";
88+
} else { // Histogram is non empty
8789
multiMean = h->GetMean();
8890
zeroBinIntegral = h->Integral(1, 1);
8991
lowMIntegral = h->Integral(1, 10);
9092
totIntegral = h->Integral(2, h->GetNbinsX());
9193

9294
if (totIntegral == 0) { //if only "0 hits per event" bin is filled -> error
9395
if (h->GetBinContent(1) > 0) {
94-
result = Quality::Medium;
96+
result = Quality::Bad;
9597
// flag = AliQAv1::kERROR;
98+
shifter_msg = "Only events at 0 filled!";
9699
}
97100
} else {
98101
// if (AliRecoParam::ConvertIndex(specie) == AliRecoParam::kCosmic) {
99-
if (0) {
102+
if (0) { // TODO: this is only for cosmics, how to check?
100103
if (multiMean < 10.) {
101104
result = Quality::Good;
105+
shifter_msg = "Average within limits, OK!";
102106
// flag = AliQAv1::kINFO;
103107
} else {
104108
result = Quality::Medium;
109+
shifter_msg = "Average outside limits!";
105110
// flag = AliQAv1::kWARNING;
106111
}
107-
} else {
108-
Bool_t isZeroBinContentHigh = kFALSE;
109-
Bool_t isLowMultContentHigh = kFALSE;
110-
Bool_t isINT7AverageLow = kFALSE;
111-
Bool_t isINT7AverageHigh = kFALSE;
112-
113-
if (zeroBinIntegral > 0.75 * totIntegral)
114-
isZeroBinContentHigh = kTRUE;
115-
if (lowMIntegral > 0.75 * totIntegral)
116-
isLowMultContentHigh = kTRUE;
117-
if (multiMean < minTOFrawhits)
118-
isINT7AverageLow = kTRUE;
119-
if (multiMean > maxTOFrawhits)
120-
isINT7AverageHigh = kTRUE;
112+
} else { // Running with collisions
113+
const Bool_t isZeroBinContentHigh = (zeroBinIntegral > fracAtZeroMult * totIntegral);
114+
const Bool_t isLowMultContentHigh = (lowMIntegral > fracAtLowMult * totIntegral);
115+
const Bool_t isINT7AverageLow = (multiMean < minTOFrawhits);
116+
const Bool_t isINT7AverageHigh = (multiMean > maxTOFrawhits);
121117

122118
// if (AliRecoParam::ConvertIndex(specie) == AliRecoParam::kLowMult) {
123-
if (0) {
119+
if (0) { // TODO: Low multiplicity running, how to check if it is pp? Probably this can be simplified in the json
124120
if (isZeroBinContentHigh && (multiMean > 10.)) {
125121

126122
} else {
127123
// if (!histname.Contains("INT7") && (multiMean > 100.)) {
128124
if ((multiMean > 100.)) {
129125
result = Quality::Medium;
126+
shifter_msg = "Average outside limits!";
130127
// flag = AliQAv1::kWARNING;
131128
} else {
132129
// if (histname.Contains("INT7") && (isINT7AverageLow || isINT7AverageHigh)) {
133130
if ((isINT7AverageLow || isINT7AverageHigh)) {
134131
result = Quality::Medium;
132+
shifter_msg = "Average outside limits!";
135133
// flag = AliQAv1::kWARNING;
136134
} else {
137135
result = Quality::Good;
136+
shifter_msg = "Average within limits, OK!";
138137
// flag = AliQAv1::kINFO;
139138
}
140139
}
141140
}
142-
// } else if ((AliRecoParam::ConvertIndex(specie) == AliRecoParam::kHighMult) && (isLowMultContentHigh || (multiMean > 500.))) {
143-
} else if ((isLowMultContentHigh || (multiMean > 500.))) {
144-
//assume that good range of multi in PbPb goes from 20 to 500 tracks
145-
result = Quality::Medium;
146-
// flag = AliQAv1::kWARNING;
147-
} else {
148-
result = Quality::Good;
149-
// flag = AliQAv1::kINFO;
141+
}
142+
// } else if ((AliRecoParam::ConvertIndex(specie) == AliRecoParam::kHighMult) && (isLowMultContentHigh || (multiMean > 500.))) {
143+
else { // High multiplicity running e.g. Pb-Pb
144+
if (isLowMultContentHigh) {
145+
result = Quality::Medium;
146+
shifter_msg = Form("Low-multiplicity counts are high\n(%.2f higher than total)!", fracAtLowMult);
147+
} else if (multiMean > maxTOFrawhitsPbPb) {
148+
//assume that good range of multi in PbPb goes from 20 to 500 tracks
149+
result = Quality::Medium;
150+
shifter_msg = Form("Average higher than expected (%.2f)!", maxTOFrawhitsPbPb);
151+
// flag = AliQAv1::kWARNING;
152+
} else {
153+
result = Quality::Good;
154+
shifter_msg = "Average within limits";
155+
// flag = AliQAv1::kINFO;
156+
}
150157
}
151158
}
152159
}
@@ -166,10 +173,13 @@ void TOFCheckRawsMulti::beautify(std::shared_ptr<MonitorObject> mo, Quality chec
166173
h->GetListOfFunctions()->Add(msg);
167174
msg->Draw();
168175
msg->SetName(Form("%s_msg", mo->GetName()));
176+
msg->Clear();
177+
TObjArray* txt_arr = shifter_msg.Tokenize("\n");
178+
for (Int_t i = 0; i < txt_arr->GetEntries(); i++) {
179+
msg->AddText(txt_arr->At(i)->GetName());
180+
}
169181

170182
if (checkResult == Quality::Good) {
171-
LOG(INFO) << "Quality::Good, setting to green";
172-
msg->Clear();
173183
msg->AddText(Form("Mean value = %5.2f", multiMean));
174184
msg->AddText(Form("Reference range: %5.2f-%5.2f", minTOFrawhits, maxTOFrawhits));
175185
msg->AddText(Form("Events with 0 hits = %5.2f%%", zeroBinIntegral * 100. / totIntegral));
@@ -178,20 +188,12 @@ void TOFCheckRawsMulti::beautify(std::shared_ptr<MonitorObject> mo, Quality chec
178188
//
179189
h->SetFillColor(kGreen);
180190
} else if (checkResult == Quality::Bad) {
181-
LOG(INFO) << "Quality::Bad, setting to red";
182-
//
183-
msg->Clear();
184-
msg->AddText("No TOF hits for all events.");
185191
msg->AddText("Call TOF on-call.");
186192
msg->SetFillColor(kRed);
187193
//
188194
h->SetFillColor(kRed);
189195
} else if (checkResult == Quality::Medium) {
190-
LOG(INFO) << "Quality::medium, setting to orange";
191-
//
192-
msg->Clear();
193-
msg->AddText("No entries. IF TOF IN RUN");
194-
msg->AddText("check the TOF TWiki");
196+
msg->AddText("IF TOF IN RUN check the TOF TWiki");
195197
msg->SetFillColor(kYellow);
196198
//
197199
h->SetFillColor(kOrange);

Modules/TOF/src/TOFTask.cxx

Lines changed: 93 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
#include <TH1I.h>
2222
#include <TH2I.h>
2323

24+
// O2 includes
25+
#include "TOFBase/Digit.h"
26+
#include "TOFBase/Geo.h"
27+
2428
// QC includes
2529
#include "QualityControl/QcInfoLogger.h"
2630
#include "TOF/TOFTask.h"
@@ -274,6 +278,7 @@ void TOFTask::startOfCycle()
274278

275279
void TOFTask::monitorData(o2::framework::ProcessingContext& ctx)
276280
{
281+
// LOG(INFO) << "Monitoring in the TOF Task " << ENDM;
277282
// In this function you can access data inputs specified in the JSON config file, for example:
278283
// "query": "random:ITS/RAWDATA/0"
279284
// which is correspondingly <binding>:<dataOrigin>/<dataDescription>/<subSpecification
@@ -285,19 +290,97 @@ void TOFTask::monitorData(o2::framework::ProcessingContext& ctx)
285290

286291
// Some examples:
287292

288-
// 1. In a loop
289-
for (auto&& input : ctx.inputs()) {
290-
// get message header
291-
if (input.header != nullptr && input.payload != nullptr) {
292-
const auto* header = header::get<header::DataHeader*>(input.header);
293-
// get payload of a specific input, which is a char array.
294-
// const char* payload = input.payload;
295-
296-
// for the sake of an example, let's fill the histogram with payload sizes
297-
mTOFRawsMulti->Fill(header->payloadSize);
293+
// Get TOF digits
294+
auto digits = ctx.inputs().get<gsl::span<o2::tof::Digit>>("tofdigits");
295+
// Get TOF Readout window
296+
auto rows = ctx.inputs().get<std::vector<o2::tof::ReadoutWindowData>>("readoutwin");
297+
LOG(INFO) << "ReadoutWindow size::: " << rows.size();
298+
299+
Int_t eta, phi;
300+
// Int_t det[5] = { 0 }; // Coordinates
301+
Int_t strip = 0; // Strip (Put it into Geo.h?)
302+
Float_t tdc_time = 0;
303+
Float_t tot_time = 0;
304+
// SM in side I: 14-17, 0-4 -> 4 + 5
305+
// SM in side O: 5-13 -> 9
306+
// phi is counted every pad starting from SM 0.
307+
// There are 48 pads per SM. Side I is from phi 0:48*4 and 48*14:48*18
308+
const Int_t phi_I1 = 48 * 4;
309+
const Int_t phi_I2 = 48 * 14;
310+
// eta is counted every half strip starting from strip 0.
311+
// Halves strips in side A 0-90, in side C 91-181
312+
const Int_t half_eta = 91;
313+
Bool_t isSectorI = kFALSE;
314+
Int_t ndigits[4] = { 0 }; // Number of digits per side I/A,O/A,I/C,O/C
315+
316+
// Loop on readout windows
317+
for (const auto& row : rows) {
318+
mTOFRawsMulti->Fill(row.size()); // Number of digits inside a readout window
319+
auto digits_in_row = row.getBunchChannelData(digits); // Digits inside a readout window
320+
// Loop on digits
321+
for (auto const& digit : digits_in_row) {
322+
strip = ((digit.getChannel() / 96) % 91); // Strip index
323+
// o2::tof::Geo::getVolumeIndices(digit.getChannel(), det);
324+
// LOG(INFO) << "Filling digit #" << ndigits << " in sector #" << det[0] << " and strip #" << strip;
325+
Int_t ech = o2::tof::Geo::getECHFromCH(digit.getChannel());
326+
// mTOFRawHitMap->Fill(det[0], strip);
327+
mTOFRawHitMap->Fill(Float_t(o2::tof::Geo::getCrateFromECH(ech)) / 4.f, strip);
328+
// TDC time and ToT time
329+
tdc_time = digit.getTDC() * o2::tof::Geo::TDCBIN * 0.001;
330+
tot_time = digit.getTOT() * o2::tof::Geo::TOTBIN_NS;
331+
mTOFRawsTime->Fill(tdc_time);
332+
mTOFRawsToT->Fill(tot_time);
333+
digit.getPhiAndEtaIndex(phi, eta);
334+
isSectorI = phi < phi_I1 || phi > phi_I2;
335+
if (eta < half_eta) { // Sector A
336+
if (isSectorI) { // Sector I/A
337+
mTOFRawsTimeIA->Fill(tdc_time);
338+
mTOFRawsToTIA->Fill(tot_time);
339+
ndigits[0]++;
340+
} else { // Sector O/A
341+
mTOFRawsTimeOA->Fill(tdc_time);
342+
mTOFRawsToTOA->Fill(tot_time);
343+
ndigits[1]++;
344+
}
345+
} else { // Sector C
346+
if (isSectorI) { // Sector I/C
347+
mTOFRawsTimeIC->Fill(tdc_time);
348+
mTOFRawsToTIC->Fill(tot_time);
349+
ndigits[2]++;
350+
} else { // Sector O/C
351+
mTOFRawsTimeOC->Fill(tdc_time);
352+
mTOFRawsToTOC->Fill(tot_time);
353+
ndigits[3]++;
354+
}
355+
}
298356
}
357+
// Filling histograms of hit multiplicity
358+
mTOFRawsMultiIA->Fill(ndigits[0]);
359+
mTOFRawsMultiOA->Fill(ndigits[1]);
360+
mTOFRawsMultiIC->Fill(ndigits[2]);
361+
mTOFRawsMultiOC->Fill(ndigits[3]);
362+
//
363+
ndigits[0] = 0;
364+
ndigits[1] = 0;
365+
ndigits[2] = 0;
366+
ndigits[3] = 0;
299367
}
300368

369+
// LOG(INFO) << "Digits counted:::::::: " << ndigits << "stop";
370+
371+
// 1. In a loop
372+
// for (auto&& input : ctx.inputs()) {
373+
// get message header
374+
// if (input.header != nullptr && input.payload != nullptr) {
375+
// const auto* header = header::get<header::DataHeader*>(input.header);
376+
// get payload of a specific input, which is a char array.
377+
// const char* payload = input.payload;
378+
// LOG(INFO) << "Payload is :::::::: " << input.payload;
379+
// for the sake of an example, let's fill the histogram with payload sizes
380+
// mTOFRawsMulti->Fill(header->payloadSize);
381+
// }
382+
// }
383+
301384
// 2. Using get("<binding>")
302385

303386
// get the payload of a specific input, which is a char array. "random" is the binding specified in the config file.

0 commit comments

Comments
 (0)