23#include "TGraphAsymmErrors.h"
41#include "GPUChainTrackingGetters.inc"
49#include "GPUParam.inc"
58#ifndef GPUCA_STANDALONE
69#include "TParticlePDG.h"
70#include "TDatabasePDG.h"
80#include <oneapi/tbb.h>
98template <
bool COUNT,
class T>
105 r.qpt = fabsf(mTracking->mIOPtrs.mergedTracks[
r.id].GetParam().GetQPt());
106 r.lowPt =
r.qpt * mTracking->GetParam().qptB5Scaler > mTracking->GetParam().rec.tpc.rejectQPtB5;
107 r.mev200 =
r.qpt > 5;
108 r.mergedLooperUnconnected = mTracking->mIOPtrs.mergedTracks[
r.id].MergedLooperUnconnected();
109 r.mergedLooperConnected = mTracking->mIOPtrs.mergedTracks[
r.id].MergedLooperConnected();
112 if constexpr (COUNT) {
117 if constexpr (COUNT) {
120 }
else if (
r.mergedLooperUnconnected) {
121 if constexpr (COUNT) {
122 counts->nMergedLooperUnconnected++;
124 }
else if (
r.mergedLooperConnected) {
125 if constexpr (COUNT) {
126 counts->nMergedLooperConnected++;
129 r.protect = !GPUTPCClusterRejection::GetRejectionStatus<COUNT>(attach,
r.physics, counts, &
r.mev200) && ((attach &
gputpcgmmergertypes::attachProtect) || !GPUTPCClusterRejection::IsTrackRejected(mTracking->mIOPtrs.mergedTracks[
r.id], mTracking->GetParam()));
136 static GPUSettingsQA defaultConfig;
138 return *
chain->mConfigQA;
140 return defaultConfig;
144static const constexpr float LOG_PT_MIN = -1.;
146static constexpr float Y_MAX = 40;
147static constexpr float Z_MAX = 100;
148static constexpr float PT_MIN = 0.01;
149static constexpr float PT_MIN_PRIM = 0.1;
150static constexpr float PT_MIN_CLUST = 0.01;
151static constexpr float PT_MAX = 20;
152static constexpr float ETA_MAX = 1.5;
153static constexpr float ETA_MAX2 = 0.9;
154static constexpr int32_t PADROW_CHECK_MINCLS = 50;
156static constexpr bool CLUST_HIST_INT_SUM =
false;
158static constexpr const int32_t COLORCOUNT = 12;
160static const constexpr char* EFF_TYPES[6] = {
"Rec",
"Clone",
"Fake",
"All",
"RecAndClone",
"MC"};
161static const constexpr char* FINDABLE_NAMES[2] = {
"All",
"Findable"};
162static const constexpr char* PRIM_NAMES[2] = {
"Prim",
"Sec"};
163static const constexpr char* PARAMETER_NAMES[5] = {
"Y",
"Z",
"#Phi",
"#lambda",
"Relative #it{p}_{T}"};
164static const constexpr char* PARAMETER_NAMES_NATIVE[5] = {
"Y",
"Z",
"sin(#Phi)",
"tan(#lambda)",
"q/#it{p}_{T} (curvature)"};
165static const constexpr char* VSPARAMETER_NAMES[6] = {
"Y",
"Z",
"Phi",
"Eta",
"Pt",
"Pt_log"};
166static const constexpr char* EFF_NAMES[3] = {
"Efficiency",
"Clone Rate",
"Fake Rate"};
167static const constexpr char* EFFICIENCY_TITLES[4] = {
"Efficiency (Primary Tracks, Findable)",
"Efficiency (Secondary Tracks, Findable)",
"Efficiency (Primary Tracks)",
"Efficiency (Secondary Tracks)"};
168static const constexpr double SCALE[5] = {10., 10., 1000., 1000., 100.};
169static const constexpr double SCALE_NATIVE[5] = {10., 10., 1000., 1000., 1.};
170static const constexpr char* XAXIS_TITLES[5] = {
"#it{y}_{mc} (cm)",
"#it{z}_{mc} (cm)",
"#Phi_{mc} (rad)",
"#eta_{mc}",
"#it{p}_{Tmc} (GeV/#it{c})"};
171static const constexpr char* AXIS_TITLES[5] = {
"#it{y}-#it{y}_{mc} (mm) (Resolution)",
"#it{z}-#it{z}_{mc} (mm) (Resolution)",
"#phi-#phi_{mc} (mrad) (Resolution)",
"#lambda-#lambda_{mc} (mrad) (Resolution)",
"(#it{p}_{T} - #it{p}_{Tmc}) / #it{p}_{Tmc} (%) (Resolution)"};
172static const constexpr char* AXIS_TITLES_NATIVE[5] = {
"#it{y}-#it{y}_{mc} (mm) (Resolution)",
"#it{z}-#it{z}_{mc} (mm) (Resolution)",
"sin(#phi)-sin(#phi_{mc}) (Resolution)",
"tan(#lambda)-tan(#lambda_{mc}) (Resolution)",
"q*(q/#it{p}_{T} - q/#it{p}_{Tmc}) (Resolution)"};
173static const constexpr char* AXIS_TITLES_PULL[5] = {
"#it{y}-#it{y}_{mc}/#sigma_{y} (Pull)",
"#it{z}-#it{z}_{mc}/#sigma_{z} (Pull)",
"sin(#phi)-sin(#phi_{mc})/#sigma_{sin(#phi)} (Pull)",
"tan(#lambda)-tan(#lambda_{mc})/#sigma_{tan(#lambda)} (Pull)",
174 "q*(q/#it{p}_{T} - q/#it{p}_{Tmc})/#sigma_{q/#it{p}_{T}} (Pull)"};
175static const constexpr char* CLUSTER_NAMES[GPUQA::N_CLS_HIST] = {
"Correctly attached clusters",
"Fake attached clusters",
"Attached + adjacent clusters",
"Fake adjacent clusters",
"Clusters of reconstructed tracks",
"Used in Physics",
"Protected",
"All clusters"};
176static const constexpr char* CLUSTER_TITLES[GPUQA::N_CLS_TYPE] = {
"Clusters Pt Distribution / Attachment",
"Clusters Pt Distribution / Attachment (relative to all clusters)",
"Clusters Pt Distribution / Attachment (integrated)"};
177static const constexpr char* CLUSTER_NAMES_SHORT[GPUQA::N_CLS_HIST] = {
"Attached",
"Fake",
"AttachAdjacent",
"FakeAdjacent",
"FoundTracks",
"Physics",
"Protected",
"All"};
178static const constexpr char* CLUSTER_TYPES[GPUQA::N_CLS_TYPE] = {
"",
"Ratio",
"Integral"};
179static const constexpr char* REJECTED_NAMES[3] = {
"All",
"Rejected",
"Fraction"};
180static const constexpr int32_t COLORS_HEX[COLORCOUNT] = {0xB03030, 0x00A000, 0x0000C0, 0x9400D3, 0x19BBBF, 0xF25900, 0x7F7F7F, 0xFFD700, 0x07F707, 0x07F7F7, 0xF08080, 0x000000};
182static const constexpr int32_t CONFIG_DASHED_MARKERS = 0;
184static const constexpr float AXES_MIN[5] = {-Y_MAX, -Z_MAX, 0.f, -ETA_MAX, PT_MIN};
185static const constexpr float AXES_MAX[5] = {Y_MAX, Z_MAX, 2.f * M_PI, ETA_MAX, PT_MAX};
186static const constexpr int32_t AXIS_BINS[5] = {51, 51, 144, 31, 50};
187static const constexpr int32_t RES_AXIS_BINS[] = {1017, 113};
188static const constexpr float RES_AXES[5] = {1., 1., 0.03, 0.03, 1.0};
189static const constexpr float RES_AXES_NATIVE[5] = {1., 1., 0.1, 0.1, 5.0};
190static const constexpr float PULL_AXIS = 10.f;
192std::vector<TColor*> GPUQA::mColors;
193int32_t GPUQA::initColors()
195 mColors.reserve(COLORCOUNT);
196 for (int32_t
i = 0;
i < COLORCOUNT;
i++) {
197 float f1 = (float)((COLORS_HEX[
i] >> 16) & 0xFF) / (
float)0xFF;
198 float f2 = (float)((COLORS_HEX[
i] >> 8) & 0xFF) / (
float)0xFF;
199 float f3 = (float)((COLORS_HEX[
i] >> 0) & 0xFF) / (
float)0xFF;
200 mColors.emplace_back(
new TColor(10000 +
i, f1, f2, f3));
204static constexpr Color_t defaultColorNums[COLORCOUNT] = {kRed, kBlue, kGreen, kMagenta, kOrange, kAzure, kBlack, kYellow, kGray, kTeal, kSpring, kPink};
206#define TRACK_EXPECTED_REFERENCE_X_DEFAULT 81
208static inline int32_t GPUQA_O2_ConvertFakeLabel(int32_t
label) {
return label >= 0x7FFFFFFE ? -1 :
label; }
209inline uint32_t GPUQA::GetNMCCollissions()
const {
return mMCInfosCol.size(); }
210inline uint32_t GPUQA::GetNMCTracks(int32_t iCol)
const {
return mMCInfosCol[iCol].num; }
211inline uint32_t GPUQA::GetNMCTracks(
const mcLabelI_t&
label)
const {
return mMCInfosCol[mMCEventOffset[
label.getSourceID()] +
label.getEventID()].num; }
212inline uint32_t GPUQA::GetNMCLabels()
const {
return mClNative->clustersMCTruth ? mClNative->clustersMCTruth->getIndexedSize() : 0; }
213inline const GPUQA::mcInfo_t& GPUQA::GetMCTrack(uint32_t iTrk, uint32_t iCol) {
return mMCInfos[mMCInfosCol[iCol].first + iTrk]; }
214inline const GPUQA::mcInfo_t& GPUQA::GetMCTrack(
const mcLabel_t&
label) {
return mMCInfos[mMCInfosCol[mMCEventOffset[
label.getSourceID()] +
label.getEventID()].first +
label.getTrackID()]; }
215inline GPUQA::mcLabels_t GPUQA::GetMCLabel(uint32_t
i) {
return mClNative->clustersMCTruth->getLabels(
i); }
216inline int32_t GPUQA::GetMCLabelNID(
const mcLabels_t&
label) {
return label.size(); }
217inline int32_t GPUQA::GetMCLabelNID(uint32_t
i) {
return mClNative->clustersMCTruth->getLabels(
i).size(); }
218inline GPUQA::mcLabel_t GPUQA::GetMCLabel(uint32_t
i, uint32_t
j) {
return mClNative->clustersMCTruth->getLabels(
i)[
j]; }
219inline int32_t GPUQA::GetMCLabelID(uint32_t
i, uint32_t
j) {
return GPUQA_O2_ConvertFakeLabel(mClNative->clustersMCTruth->getLabels(
i)[
j].getTrackID()); }
220inline int32_t GPUQA::GetMCLabelID(
const mcLabels_t&
label, uint32_t
j) {
return GPUQA_O2_ConvertFakeLabel(
label[
j].getTrackID()); }
221inline int32_t GPUQA::GetMCLabelID(
const mcLabel_t&
label) {
return GPUQA_O2_ConvertFakeLabel(
label.getTrackID()); }
222inline uint32_t GPUQA::GetMCLabelCol(uint32_t
i, uint32_t
j) {
return mMCEventOffset[mClNative->clustersMCTruth->getLabels(
i)[
j].getSourceID()] + mClNative->clustersMCTruth->getLabels(
i)[
j].getEventID(); }
223inline const auto& GPUQA::GetClusterLabels() {
return mClNative->clustersMCTruth; }
224inline float GPUQA::GetMCLabelWeight(uint32_t
i, uint32_t
j) {
return 1; }
225inline float GPUQA::GetMCLabelWeight(
const mcLabels_t&
label, uint32_t
j) {
return 1; }
226inline float GPUQA::GetMCLabelWeight(
const mcLabel_t&
label) {
return 1; }
227inline bool GPUQA::mcPresent() {
return !mConfig.noMC && mTracking && mClNative && mClNative->clustersMCTruth && mMCInfos.size(); }
228uint32_t GPUQA::GetMCLabelCol(
const mcLabel_t&
label)
const {
return !
label.isValid() ? 0 : (mMCEventOffset[
label.getSourceID()] +
label.getEventID()); }
230bool GPUQA::CompareIgnoreFake(
const mcLabelI_t& l1,
const mcLabelI_t& l2) {
return l1.compare(l2) >= 0; }
231#define TRACK_EXPECTED_REFERENCE_X 78
233inline GPUQA::mcLabelI_t::mcLabelI_t(
const GPUQA::mcLabel_t& l) : track(l.fMCID) {}
234inline bool GPUQA::mcLabelI_t::operator==(
const GPUQA::mcLabel_t& l) {
return AbsLabelID(track) == l.fMCID; }
235inline uint32_t GPUQA::GetNMCCollissions()
const {
return 1; }
236inline uint32_t GPUQA::GetNMCTracks(int32_t iCol)
const {
return mTracking->mIOPtrs.nMCInfosTPC; }
237inline uint32_t GPUQA::GetNMCTracks(
const mcLabelI_t&
label)
const {
return mTracking->mIOPtrs.nMCInfosTPC; }
238inline uint32_t GPUQA::GetNMCLabels()
const {
return mTracking->mIOPtrs.nMCLabelsTPC; }
239inline const GPUQA::mcInfo_t& GPUQA::GetMCTrack(uint32_t iTrk, uint32_t iCol) {
return mTracking->mIOPtrs.mcInfosTPC[AbsLabelID(iTrk)]; }
240inline const GPUQA::mcInfo_t& GPUQA::GetMCTrack(
const mcLabel_t&
label) {
return GetMCTrack(
label.fMCID, 0); }
241inline const GPUQA::mcInfo_t& GPUQA::GetMCTrack(
const mcLabelI_t&
label) {
return GetMCTrack(
label.track, 0); }
242inline const GPUQA::mcLabels_t& GPUQA::GetMCLabel(uint32_t
i) {
return mTracking->mIOPtrs.mcLabelsTPC[
i]; }
243inline const GPUQA::mcLabel_t& GPUQA::GetMCLabel(uint32_t
i, uint32_t
j) {
return mTracking->mIOPtrs.mcLabelsTPC[
i].fClusterID[
j]; }
244inline int32_t GPUQA::GetMCLabelNID(
const mcLabels_t&
label) {
return 3; }
245inline int32_t GPUQA::GetMCLabelNID(uint32_t
i) {
return 3; }
246inline int32_t GPUQA::GetMCLabelID(uint32_t
i, uint32_t
j) {
return mTracking->mIOPtrs.mcLabelsTPC[
i].fClusterID[
j].fMCID; }
247inline int32_t GPUQA::GetMCLabelID(
const mcLabels_t&
label, uint32_t
j) {
return label.fClusterID[
j].fMCID; }
248inline int32_t GPUQA::GetMCLabelID(
const mcLabel_t&
label) {
return label.fMCID; }
249inline uint32_t GPUQA::GetMCLabelCol(uint32_t
i, uint32_t
j) {
return 0; }
250inline const auto& GPUQA::GetClusterLabels() {
return mTracking->mIOPtrs.mcLabelsTPC; }
251inline float GPUQA::GetMCLabelWeight(uint32_t
i, uint32_t
j) {
return mTracking->mIOPtrs.mcLabelsTPC[
i].fClusterID[
j].fWeight; }
252inline float GPUQA::GetMCLabelWeight(
const mcLabels_t&
label, uint32_t
j) {
return label.fClusterID[
j].fWeight; }
253inline float GPUQA::GetMCLabelWeight(
const mcLabel_t&
label) {
return label.fWeight; }
254inline int32_t GPUQA::FakeLabelID(int32_t
id) {
return id < 0 ?
id : (-2 -
id); }
255inline int32_t GPUQA::AbsLabelID(int32_t
id) {
return id >= 0 ?
id : (-
id - 2); }
256inline bool GPUQA::mcPresent() {
return !mConfig.noMC && mTracking && GetNMCLabels() && GetNMCTracks(0); }
257uint32_t GPUQA::GetMCLabelCol(
const mcLabel_t&
label)
const {
return 0; }
259bool GPUQA::CompareIgnoreFake(
const mcLabelI_t& l1,
const mcLabelI_t& l2) {
return AbsLabelID(l1.track) == AbsLabelID(l2.track); }
260#define TRACK_EXPECTED_REFERENCE_X TRACK_EXPECTED_REFERENCE_X_DEFAULT
265 return obj[mMCEventOffset[l.getSourceID()] + l.getEventID()][l.getTrackID()];
269auto GPUQA::getHistArray<TH1F>()
271 return std::make_pair(mHist1D, &mHist1D_pos);
274auto GPUQA::getHistArray<TH2F>()
276 return std::make_pair(mHist2D, &mHist2D_pos);
279auto GPUQA::getHistArray<TH1D>()
281 return std::make_pair(mHist1Dd, &mHist1Dd_pos);
284auto GPUQA::getHistArray<TGraphAsymmErrors>()
286 return std::make_pair(mHistGraph, &mHistGraph_pos);
288template <
class T,
typename... Args>
289void GPUQA::createHist(T*&
h,
const char*
name, Args... args)
291 const auto&
p = getHistArray<T>();
292 if (mHaveExternalHists) {
293 if (
p.first->size() <=
p.second->size()) {
294 GPUError(
"Array sizes mismatch: Histograms %lu <= Positions %lu",
p.first->size(),
p.second->size());
295 throw std::runtime_error(
"Incoming histogram array incomplete");
297 if (strcmp((*
p.first)[
p.second->size()].GetName(),
name)) {
298 GPUError(
"Histogram name mismatch: in array %s, trying to create %s", (*
p.first)[
p.second->size()].GetName(),
name);
299 throw std::runtime_error(
"Incoming histogram has incorrect name");
302 if constexpr (std::is_same_v<T, TGraphAsymmErrors>) {
303 p.first->emplace_back();
304 p.first->back().SetName(
name);
306 p.first->emplace_back(
name, args...);
309 h = &((*
p.first)[
p.second->size()]);
310 p.second->emplace_back(&
h);
316 std::tuple<std::vector<std::unique_ptr<TCanvas>>, std::vector<std::unique_ptr<TLegend>>, std::vector<std::unique_ptr<TPad>>, std::vector<std::unique_ptr<TLatex>>, std::vector<std::unique_ptr<TH1D>>>
v;
320template <
class T,
typename... Args>
321T* GPUQA::createGarbageCollected(Args... args)
323 auto&
v = std::get<std::vector<std::unique_ptr<T>>>(mGarbageCollector->v);
324 v.emplace_back(std::make_unique<T>(args...));
325 return v.back().get();
327void GPUQA::clearGarbagageCollector()
329 std::get<std::vector<std::unique_ptr<TPad>>>(mGarbageCollector->v).
clear();
330 std::apply([](
auto&&... args) { ((args.clear()), ...); }, mGarbageCollector->v);
335 mMCEventOffset.resize(1, 0);
340 if (mQAInitialized && !mHaveExternalHists) {
346 clearGarbagageCollector();
351 const auto&
r = checkClusterState<false>(attach);
353 return r.protect ||
r.physics;
355 return (!
r.unattached && !
r.physics && !
r.protect);
359void GPUQA::SetAxisSize(T* e)
361 e->GetYaxis()->SetTitleOffset(1.0);
362 e->GetYaxis()->SetTitleSize(0.045);
363 e->GetYaxis()->SetLabelSize(0.045);
364 e->GetXaxis()->SetTitleOffset(1.03);
365 e->GetXaxis()->SetTitleSize(0.045);
366 e->GetXaxis()->SetLabelOffset(-0.005);
367 e->GetXaxis()->SetLabelSize(0.045);
370void GPUQA::SetLegend(TLegend* l,
bool bigText)
373 l->SetTextSize(bigText ? 0.03 : 0.016);
377double* GPUQA::CreateLogAxis(int32_t nbins,
float xmin,
float xmax)
379 float logxmin = std::log10(xmin);
380 float logxmax = std::log10(xmax);
381 float binwidth = (logxmax - logxmin) / nbins;
383 double* xbins =
new double[nbins + 1];
386 for (int32_t
i = 1;
i <= nbins;
i++) {
387 xbins[
i] = std::pow(10, logxmin +
i * binwidth);
392void GPUQA::ChangePadTitleSize(TPad* p,
float size)
395 TPaveText* pt = (TPaveText*)(
p->GetPrimitive(
"title"));
397 GPUError(
"Error changing title");
399 pt->SetTextSize(
size);
404void GPUQA::DrawHisto(TH1* histo,
char*
filename,
char* options)
408 histo->Draw(options);
412void GPUQA::doPerfFigure(
float x,
float y,
float size)
414 if (mConfig.perfFigure ==
"") {
417 static constexpr const char* str_perf_figure_1 =
"ALICE Performance";
418 static constexpr const char* str_perf_figure_2_mc =
"MC, Pb#minusPb, #sqrt{s_{NN}} = 5.36 TeV";
419 static constexpr const char* str_perf_figure_2_data =
"Pb#minusPb, #sqrt{s_{NN}} = 5.36 TeV";
420 const char* str_perf_figure_2 = (mConfig.perfFigure ==
"mc" || mConfig.perfFigure ==
"MC") ? str_perf_figure_2_mc : (mConfig.perfFigure ==
"data" ? str_perf_figure_2_data : mConfig.perfFigure.c_str());
422 TLatex* t = createGarbageCollected<TLatex>();
425 t->SetTextSize(
size);
426 t->DrawLatex(
x,
y, str_perf_figure_1);
427 t->SetTextSize(
size * 0.8);
428 t->DrawLatex(
x,
y - 0.01 -
size, str_perf_figure_2);
437int32_t GPUQA::InitQACreateHistograms()
439 char name[2048], fname[1024];
440 if (mQATasks & taskTrackingEff) {
442 for (int32_t
i = 0;
i < 6;
i++) {
443 for (int32_t
j = 0;
j < 2;
j++) {
444 for (int32_t k = 0; k < 2; k++) {
445 for (int32_t l = 0; l < 5; l++) {
446 snprintf(
name, 2048,
"%s%s%s%sVs%s",
"tracks", EFF_TYPES[
i], FINDABLE_NAMES[
j], PRIM_NAMES[k], VSPARAMETER_NAMES[l]);
448 std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], k == 0 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])};
449 createHist(mEff[
i][
j][k][l],
name,
name, AXIS_BINS[l], binsPt.get());
451 createHist(mEff[
i][
j][k][l],
name,
name, AXIS_BINS[l], AXES_MIN[l], AXES_MAX[l]);
453 if (!mHaveExternalHists) {
454 mEff[
i][
j][k][l]->Sumw2();
456 strcat(
name,
"_eff");
458 createHist(mEffResult[
i][
j][k][l],
name);
467 if (mQATasks & taskTrackingRes) {
468 for (int32_t
i = 0;
i < 5;
i++) {
469 for (int32_t
j = 0;
j < 5;
j++) {
470 snprintf(
name, 2048,
"rms_%s_vs_%s", VSPARAMETER_NAMES[
i], VSPARAMETER_NAMES[
j]);
471 snprintf(fname, 1024,
"mean_%s_vs_%s", VSPARAMETER_NAMES[
i], VSPARAMETER_NAMES[
j]);
473 std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])};
474 createHist(mRes[
i][
j][0],
name,
name, AXIS_BINS[
j], binsPt.get());
475 createHist(mRes[
i][
j][1], fname, fname, AXIS_BINS[
j], binsPt.get());
477 createHist(mRes[
i][
j][0],
name,
name, AXIS_BINS[
j], AXES_MIN[
j], AXES_MAX[
j]);
478 createHist(mRes[
i][
j][1], fname, fname, AXIS_BINS[
j], AXES_MIN[
j], AXES_MAX[
j]);
480 snprintf(
name, 2048,
"res_%s_vs_%s", VSPARAMETER_NAMES[
i], VSPARAMETER_NAMES[
j]);
481 const float* axis = mConfig.nativeFitResolutions ? RES_AXES_NATIVE : RES_AXES;
482 const int32_t nbins =
i == 4 && mConfig.nativeFitResolutions ? (10 * RES_AXIS_BINS[0]) : RES_AXIS_BINS[0];
484 std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])};
485 createHist(mRes2[
i][
j],
name,
name, nbins, -axis[
i], axis[
i], AXIS_BINS[
j], binsPt.get());
487 createHist(mRes2[
i][
j],
name,
name, nbins, -axis[
i], axis[
i], AXIS_BINS[
j], AXES_MIN[
j], AXES_MAX[
j]);
494 if (mQATasks & taskTrackingResPull) {
495 for (int32_t
i = 0;
i < 5;
i++) {
496 for (int32_t
j = 0;
j < 5;
j++) {
497 snprintf(
name, 2048,
"pull_rms_%s_vs_%s", VSPARAMETER_NAMES[
i], VSPARAMETER_NAMES[
j]);
498 snprintf(fname, 1024,
"pull_mean_%s_vs_%s", VSPARAMETER_NAMES[
i], VSPARAMETER_NAMES[
j]);
500 std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])};
501 createHist(mPull[
i][
j][0],
name,
name, AXIS_BINS[
j], binsPt.get());
502 createHist(mPull[
i][
j][1], fname, fname, AXIS_BINS[
j], binsPt.get());
504 createHist(mPull[
i][
j][0],
name,
name, AXIS_BINS[
j], AXES_MIN[
j], AXES_MAX[
j]);
505 createHist(mPull[
i][
j][1], fname, fname, AXIS_BINS[
j], AXES_MIN[
j], AXES_MAX[
j]);
507 snprintf(
name, 2048,
"pull_%s_vs_%s", VSPARAMETER_NAMES[
i], VSPARAMETER_NAMES[
j]);
509 std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])};
510 createHist(mPull2[
i][
j],
name,
name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[
j], binsPt.get());
512 createHist(mPull2[
i][
j],
name,
name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[
j], AXES_MIN[
j], AXES_MAX[
j]);
519 if (mQATasks & taskClusterAttach) {
520 for (int32_t
i = 0;
i < N_CLS_TYPE * N_CLS_HIST - 1;
i++) {
521 int32_t ioffset =
i >= (2 * N_CLS_HIST - 1) ? (2 * N_CLS_HIST - 1) :
i >= N_CLS_HIST ? N_CLS_HIST : 0;
522 int32_t itype =
i >= (2 * N_CLS_HIST - 1) ? 2 :
i >= N_CLS_HIST ? 1 : 0;
523 snprintf(
name, 2048,
"clusters%s%s", CLUSTER_NAMES_SHORT[
i - ioffset], CLUSTER_TYPES[itype]);
524 std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)};
525 createHist(mClusters[
i],
name,
name, AXIS_BINS[4], binsPt.get());
534 if (mQATasks & taskTrackStatistics) {
536 for (int32_t
i = 0;
i < 2;
i++) {
537 snprintf(
name, 2048,
i ?
"nrows_with_cluster" :
"nclusters");
540 std::unique_ptr<double[]> binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)};
541 createHist(mTrackPt,
"tracks_pt",
"tracks_pt", AXIS_BINS[4], binsPt.get());
542 for (int32_t
i = 0;
i < 2;
i++) {
543 snprintf(
name, 2048,
i ?
"tracks_dedx_max" :
"tracks_dedx_tot");
544 createHist(mTrackdEdx[
i],
name,
name, 200, -3, 1, 1000, 0,
i ? 1500 : 5000);
546 const uint32_t maxTime = (mTracking && mTracking->GetParam().continuousMaxTimeBin > 0) ? mTracking->GetParam().continuousMaxTimeBin : constants::TPC_MAX_TIME_BIN_TRIGGERED;
547 createHist(mT0[0],
"tracks_t0",
"tracks_t0", (maxTime + 1) / 10, 0, maxTime);
548 createHist(mT0[1],
"tracks_t0_res",
"tracks_t0_res", 1000, -100, 100);
549 createHist(mClXY,
"clXY",
"clXY", 1000, -250, 250, 1000, -250, 250);
551 if (mQATasks & taskClusterRejection) {
553 for (int32_t
i = 0;
i < 3;
i++) {
554 snprintf(
name, 2048,
"clrej_%d",
i);
560 if ((mQATasks & taskClusterCounts) && mConfig.clusterRejectionHistograms) {
561 int32_t
num = DoClusterCounts(
nullptr, 2);
562 mHistClusterCount.resize(
num);
563 DoClusterCounts(
nullptr, 1);
566 for (uint32_t
i = 0;
i < mHist1D->size();
i++) {
567 *mHist1D_pos[
i] = &(*mHist1D)[
i];
569 for (uint32_t
i = 0;
i < mHist2D->size();
i++) {
570 *mHist2D_pos[
i] = &(*mHist2D)[
i];
572 for (uint32_t
i = 0;
i < mHist1Dd->size();
i++) {
573 *mHist1Dd_pos[
i] = &(*mHist1Dd)[
i];
575 for (uint32_t
i = 0;
i < mHistGraph->size();
i++) {
576 *mHistGraph_pos[
i] = &(*mHistGraph)[
i];
582int32_t GPUQA::loadHistograms(std::vector<TH1F>& i1, std::vector<TH2F>& i2, std::vector<TH1D>& i3, std::vector<TGraphAsymmErrors>& i4, int32_t tasks)
584 if (tasks == tasksAutomatic) {
587 if (mQAInitialized && (!mHaveExternalHists || tasks != mQATasks)) {
588 throw std::runtime_error(
"QA not initialized or initialized with different task array");
596 mHist1Dd_pos.clear();
597 mHistGraph_pos.clear();
598 mHaveExternalHists =
true;
603 if (InitQACreateHistograms()) {
606 mQAInitialized =
true;
616 uint32_t
n = mMCInfos.size();
617 fwrite(&
n,
sizeof(
n), 1, fp);
618 fwrite(mMCInfos.data(),
sizeof(mMCInfos[0]),
n, fp);
619 n = mMCInfosCol.size();
620 fwrite(&
n,
sizeof(
n), 1, fp);
621 fwrite(mMCInfosCol.data(),
sizeof(mMCInfosCol[0]),
n, fp);
622 n = mMCEventOffset.size();
623 fwrite(&
n,
sizeof(
n), 1, fp);
624 fwrite(mMCEventOffset.data(),
sizeof(mMCEventOffset[0]),
n, fp);
636 if ((
x = fread(&
n,
sizeof(
n), 1, fp)) != 1) {
641 if (fread(mMCInfos.data(),
sizeof(mMCInfos[0]),
n, fp) !=
n) {
645 if ((
x = fread(&
n,
sizeof(
n), 1, fp)) != 1) {
649 mMCInfosCol.resize(
n);
650 if (fread(mMCInfosCol.data(),
sizeof(mMCInfosCol[0]),
n, fp) !=
n) {
654 if ((
x = fread(&
n,
sizeof(
n), 1, fp)) != 1) {
658 mMCEventOffset.resize(
n);
659 if (fread(mMCEventOffset.data(),
sizeof(mMCEventOffset[0]),
n, fp) !=
n) {
663 if (mTracking && mTracking->GetProcessingSettings().debugLevel >= 2) {
664 printf(
"Read %ld bytes MC Infos\n", ftell(fp));
668 CopyO2MCtoIOPtr(&mTracking->mIOPtrs);
675 ptr->mcInfosTPC = mMCInfos.data();
676 ptr->nMCInfosTPC = mMCInfos.size();
677 ptr->mcInfosTPCCol = mMCInfosCol.data();
678 ptr->nMCInfosTPCCol = mMCInfosCol.size();
683#ifndef GPUCA_STANDALONE
684 if (!mO2MCDataLoaded) {
685 HighResTimer timer(mTracking && mTracking->GetProcessingSettings().debugLevel);
686 if (mTracking && mTracking->GetProcessingSettings().debugLevel) {
687 GPUInfo(
"Start reading O2 Track MC information");
689 static constexpr float PRIM_MAX_T = 0.01f;
692 std::vector<int32_t> refId;
695 const auto& evrec = dc->getEventRecords();
696 const auto& evparts = dc->getEventParts();
697 std::vector<std::vector<float>> evTimeBins(mcReader.getNSources());
698 for (uint32_t
i = 0;
i < evTimeBins.size();
i++) {
699 evTimeBins[
i].resize(mcReader.getNEvents(
i), -100.f);
701 for (uint32_t
i = 0;
i < evrec.size();
i++) {
702 const auto&
ir = evrec[
i];
703 for (uint32_t
j = 0;
j < evparts[
i].size();
j++) {
704 const int iSim = evparts[
i][
j].sourceID;
705 const int iEv = evparts[
i][
j].entryID;
709 if (evTimeBins[iSim][iEv] >= 0) {
710 throw std::runtime_error(
"Multiple time bins for same MC collision found");
712 evTimeBins[iSim][iEv] = timebin;
717 uint32_t nSimSources = mcReader.getNSources();
718 mMCEventOffset.resize(nSimSources);
719 uint32_t nSimTotalEvents = 0;
720 uint32_t nSimTotalTracks = 0;
721 for (uint32_t
i = 0;
i < nSimSources;
i++) {
722 mMCEventOffset[
i] = nSimTotalEvents;
723 nSimTotalEvents += mcReader.getNEvents(
i);
726 mMCInfosCol.resize(nSimTotalEvents);
727 for (int32_t iSim = 0; iSim < mcReader.getNSources(); iSim++) {
728 for (int32_t
i = 0;
i < mcReader.getNEvents(iSim);
i++) {
729 const float timebin = evTimeBins[iSim][
i];
731 const std::vector<o2::MCTrack>&
tracks = mcReader.getTracks(iSim,
i);
732 const std::vector<o2::TrackReference>& trackRefs = mcReader.getTrackRefsByEvent(iSim,
i);
734 refId.resize(
tracks.size());
735 std::fill(refId.begin(), refId.end(), -1);
736 for (uint32_t
j = 0;
j < trackRefs.size();
j++) {
738 int32_t trkId = trackRefs[
j].getTrackID();
739 if (refId[trkId] == -1) {
744 mMCInfosCol[mMCEventOffset[iSim] +
i].first = mMCInfos.size();
745 mMCInfosCol[mMCEventOffset[iSim] +
i].num =
tracks.size();
746 mMCInfos.resize(mMCInfos.size() +
tracks.size());
747 for (uint32_t
j = 0;
j <
tracks.size();
j++) {
748 auto&
info = mMCInfos[mMCInfosCol[mMCEventOffset[iSim] +
i].first +
j];
750 TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(trk.GetPdgCode());
752 if (abs(trk.GetPdgCode()) == kElectron) {
755 if (abs(trk.GetPdgCode()) == kMuonMinus) {
758 if (abs(trk.GetPdgCode()) == kPiPlus) {
761 if (abs(trk.GetPdgCode()) == kKPlus) {
764 if (abs(trk.GetPdgCode()) == kProton) {
768 info.charge = particle ? particle->Charge() : 0;
769 info.prim = trk.T() < PRIM_MAX_T;
770 info.primDaughters = 0;
771 if (trk.getFirstDaughterTrackId() != -1) {
772 for (int32_t k = trk.getFirstDaughterTrackId(); k <= trk.getLastDaughterTrackId(); k++) {
773 if (tracks[k].
T() < PRIM_MAX_T) {
774 info.primDaughters = 1;
782 const auto& trkRef = trackRefs[refId[
j]];
786 info.pX = trkRef.Px();
787 info.pY = trkRef.Py();
788 info.pZ = trkRef.Pz();
789 info.genRadius = std::sqrt(trk.GetStartVertexCoordinatesX() * trk.GetStartVertexCoordinatesX() + trk.GetStartVertexCoordinatesY() * trk.GetStartVertexCoordinatesY() + trk.GetStartVertexCoordinatesZ() * trk.GetStartVertexCoordinatesZ());
797 if (timer.IsRunning()) {
798 GPUInfo(
"Finished reading O2 Track MC information (%f seconds)", timer.GetCurrentElapsedTime());
800 mO2MCDataLoaded =
true;
803 CopyO2MCtoIOPtr(updateIOPtr);
810 if (mQAInitialized) {
811 throw std::runtime_error(
"QA already initialized");
813 if (tasks == tasksAutomatic) {
817 mHist1D =
new std::vector<TH1F>;
818 mHist2D =
new std::vector<TH2F>;
819 mHist1Dd =
new std::vector<TH1D>;
820 mHistGraph =
new std::vector<TGraphAsymmErrors>;
826 if (mTracking->GetProcessingSettings().qcRunFraction != 100.f && mQATasks != taskClusterCounts) {
827 throw std::runtime_error(
"QA with qcRunFraction only supported for taskClusterCounts");
831 mClNative = mTracking->mIOPtrs.clustersNative;
834 if (InitQACreateHistograms()) {
838 if (mConfig.enableLocalOutput) {
839 mkdir(mConfig.plotsDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
842#ifndef GPUCA_STANDALONE
844 InitO2MCData(mTracking ? &mTracking->mIOPtrs : nullptr);
848 if (mConfig.matchMCLabels.size()) {
849 uint32_t nFiles = mConfig.matchMCLabels.size();
850 std::vector<std::unique_ptr<TFile>> files;
851 std::vector<std::vector<std::vector<int32_t>>*> labelsBuffer(nFiles);
852 std::vector<std::vector<std::vector<int32_t>>*> effBuffer(nFiles);
853 for (uint32_t
i = 0;
i < nFiles;
i++) {
854 files.emplace_back(std::make_unique<TFile>(mConfig.matchMCLabels[
i].c_str()));
855 labelsBuffer[
i] = (std::vector<std::vector<int32_t>>*)files[
i]->Get(
"mcLabelBuffer");
856 effBuffer[
i] = (std::vector<std::vector<int32_t>>*)files[
i]->Get(
"mcEffBuffer");
857 if (labelsBuffer[
i] ==
nullptr || effBuffer[
i] ==
nullptr) {
858 GPUError(
"Error opening / reading from labels file %u/%s: %p %p",
i, mConfig.matchMCLabels[
i].c_str(), (
void*)labelsBuffer[
i], (
void*)effBuffer[
i]);
863 mGoodTracks.resize(labelsBuffer[0]->
size());
864 mGoodHits.resize(labelsBuffer[0]->
size());
865 for (uint32_t iEvent = 0; iEvent < labelsBuffer[0]->size(); iEvent++) {
866 std::vector<bool> labelsOK((*effBuffer[0])[iEvent].
size());
867 for (uint32_t k = 0; k < (*effBuffer[0])[iEvent].
size(); k++) {
869 for (uint32_t l = 0; l < nFiles; l++) {
870 if ((*effBuffer[0])[iEvent][k] != (*effBuffer[l])[iEvent][k]) {
876 mGoodTracks[iEvent].resize((*labelsBuffer[0])[iEvent].size());
877 for (uint32_t k = 0; k < (*labelsBuffer[0])[iEvent].
size(); k++) {
878 if ((*labelsBuffer[0])[iEvent][k] == MC_LABEL_INVALID) {
881 mGoodTracks[iEvent][k] = labelsOK[abs((*labelsBuffer[0])[iEvent][k])];
885 mQAInitialized =
true;
891 if (!mQAInitialized) {
892 throw std::runtime_error(
"QA not initialized");
894 if (mTracking && mTracking->GetProcessingSettings().debugLevel >= 2) {
895 GPUInfo(
"Running QA - Mask %d, Efficiency %d, Resolution %d, Pulls %d, Cluster Attachment %d, Track Statistics %d, Cluster Counts %d", mQATasks, (int32_t)(mQATasks & taskTrackingEff), (int32_t)(mQATasks & taskTrackingRes), (int32_t)(mQATasks & taskTrackingResPull), (int32_t)(mQATasks & taskClusterAttach), (int32_t)(mQATasks & taskTrackStatistics), (int32_t)(mQATasks & taskClusterCounts));
897 if (!clNative && mTracking) {
898 clNative = mTracking->mIOPtrs.clustersNative;
900 mClNative = clNative;
903 uint32_t nSimEvents = GetNMCCollissions();
904 if (mTrackMCLabelsReverse.size() < nSimEvents) {
905 mTrackMCLabelsReverse.resize(nSimEvents);
907 if (mRecTracks.size() < nSimEvents) {
908 mRecTracks.resize(nSimEvents);
910 if (mFakeTracks.size() < nSimEvents) {
911 mFakeTracks.resize(nSimEvents);
913 if (mMCParam.size() < nSimEvents) {
914 mMCParam.resize(nSimEvents);
919 uint32_t nReconstructedTracks = 0;
920 if (tracksExternal) {
921#ifndef GPUCA_STANDALONE
922 nReconstructedTracks = tracksExternal->size();
925 nReconstructedTracks = mTracking->mIOPtrs.nMergedTracks;
927 mTrackMCLabels.resize(nReconstructedTracks);
928 for (uint32_t iCol = 0; iCol < GetNMCCollissions(); iCol++) {
929 mTrackMCLabelsReverse[iCol].resize(GetNMCTracks(iCol));
930 mRecTracks[iCol].resize(GetNMCTracks(iCol));
931 mFakeTracks[iCol].resize(GetNMCTracks(iCol));
932 mMCParam[iCol].resize(GetNMCTracks(iCol));
933 memset(mRecTracks[iCol].
data(), 0, mRecTracks[iCol].
size() *
sizeof(mRecTracks[iCol][0]));
934 memset(mFakeTracks[iCol].
data(), 0, mFakeTracks[iCol].
size() *
sizeof(mFakeTracks[iCol][0]));
935 for (
size_t i = 0;
i < mTrackMCLabelsReverse[iCol].size();
i++) {
936 mTrackMCLabelsReverse[iCol][
i] = -1;
939 if (mQATasks & taskClusterAttach && GetNMCLabels()) {
940 mClusterParam.resize(GetNMCLabels());
941 memset(mClusterParam.data(), 0, mClusterParam.size() *
sizeof(mClusterParam[0]));
946 if (mConfig.writeMCLabels) {
947 mcEffBuffer.resize(mNEvents);
948 mcLabelBuffer.resize(mNEvents);
949 mcEffBuffer[mNEvents - 1].resize(GetNMCTracks(0));
950 mcLabelBuffer[mNEvents - 1].resize(nReconstructedTracks);
953 bool mcAvail = mcPresent() || tracksExtMC;
956 if (tracksExternal) {
957#ifndef GPUCA_STANDALONE
958 for (uint32_t
i = 0;
i < tracksExternal->size();
i++) {
959 mTrackMCLabels[
i] = (*tracksExtMC)[
i];
963 tbb::parallel_for(tbb::blocked_range<uint32_t>(0, nReconstructedTracks, (
QA_DEBUG == 0) ? 32 : nReconstructedTracks), [&](const tbb::blocked_range<uint32_t>&
range) {
964 auto acc = GPUTPCTrkLbl<true, mcLabelI_t>(GetClusterLabels(), 1.f - mConfig.recThreshold);
969 std::vector<mcLabel_t>
labels;
970 for (uint32_t k = 0; k <
track.NClusters(); k++) {
975 uint32_t hitId = mTracking->mIOPtrs.mergedTrackHits[
track.FirstClusterRef() + k].num;
976 if (hitId >= GetNMCLabels()) {
977 GPUError(
"Invalid hit id %u > %d (nClusters %d)", hitId, GetNMCLabels(), clNative ? clNative->
nClustersTotal : 0);
978 throw std::runtime_error(
"qa error");
981 for (int32_t
j = 0;
j < GetMCLabelNID(hitId);
j++) {
982 if (GetMCLabelID(hitId,
j) >= (int32_t)GetNMCTracks(GetMCLabelCol(hitId,
j))) {
983 GPUError(
"Invalid label %d > %d (hit %d, label %d, col %d)", GetMCLabelID(hitId,
j), GetNMCTracks(GetMCLabelCol(hitId,
j)), hitId,
j, (int32_t)GetMCLabelCol(hitId,
j));
984 throw std::runtime_error(
"qa error");
986 if (GetMCLabelID(hitId,
j) >= 0) {
988 GPUInfo(
"Track %d Cluster %u Label %d: %d (%f)",
i, k,
j, GetMCLabelID(hitId,
j), GetMCLabelWeight(hitId,
j));
994 float maxweight, sumweight;
996 auto maxLabel = acc.computeLabel(&maxweight, &sumweight, &maxcount);
997 mTrackMCLabels[
i] = maxLabel;
998 if (
QA_DEBUG &&
track.OK() && GetNMCTracks(maxLabel) > (uint32_t)maxLabel.getTrackID()) {
999 const mcInfo_t& mc = GetMCTrack(maxLabel);
1000 GPUInfo(
"Track %d label %d (fake %d) weight %f clusters %d (fitted %d) (%f%% %f%%) Pt %f",
i, maxLabel.getTrackID(), (int32_t)(maxLabel.isFake()), maxweight,
nClusters,
track.NClustersFitted(), 100.f * maxweight / sumweight, 100.f * (
float)maxcount / (
float)
nClusters,
1001 std::sqrt(mc.pX * mc.pX + mc.pY * mc.pY));
1006 if (timer.IsRunning()) {
1007 GPUInfo(
"QA Time: Assign Track Labels:\t\t%6.0f us", timer.GetCurrentElapsedTime(
true) * 1e6);
1010 for (uint32_t
i = 0;
i < nReconstructedTracks;
i++) {
1012 mcLabelI_t
label = mTrackMCLabels[
i];
1013 if (mQATasks & taskClusterAttach) {
1018 if (!mTrackMCLabels[
i].
isValid()) {
1019 for (uint32_t k = 0; k <
track->NClusters(); k++) {
1023 mClusterParam[mTracking->mIOPtrs.mergedTrackHits[
track->FirstClusterRef() + k].num].fakeAttached++;
1027 if (mMCTrackMin == -1 || (
label.getTrackID() >= mMCTrackMin &&
label.getTrackID() < mMCTrackMax)) {
1028 for (uint32_t k = 0; k <
track->NClusters(); k++) {
1032 int32_t hitId = mTracking->mIOPtrs.mergedTrackHits[
track->FirstClusterRef() + k].num;
1033 bool correct =
false;
1034 for (int32_t
j = 0;
j < GetMCLabelNID(hitId);
j++) {
1035 if (
label == GetMCLabel(hitId,
j)) {
1041 mClusterParam[hitId].attached++;
1043 mClusterParam[hitId].fakeAttached++;
1049 if (mTrackMCLabels[
i].isFake()) {
1050 (GetMCTrackObj(mFakeTracks,
label))++;
1051 }
else if (tracksExternal || !
track->MergedLooper()) {
1052 GetMCTrackObj(mRecTracks,
label)++;
1053 if (mMCTrackMin == -1 || (
label.getTrackID() >= mMCTrackMin &&
label.getTrackID() < mMCTrackMax)) {
1054 int32_t& revLabel = GetMCTrackObj(mTrackMCLabelsReverse,
label);
1055 if (tracksExternal) {
1056#ifndef GPUCA_STANDALONE
1057 if (revLabel == -1 || fabsf((*tracksExternal)[
i].getZ()) < fabsf((*tracksExternal)[revLabel].getZ())) {
1062 const auto* trks = mTracking->mIOPtrs.mergedTracks;
1064 if (revLabel == -1) {
1067 float shift1 = mTracking->GetTPCTransform()->convDeltaTimeToDeltaZinTimeFrame(trks[
i].CSide() *
GPUChainTracking::NSECTORS / 2, trks[
i].GetParam().GetTOffset());
1068 float shift2 = mTracking->GetTPCTransform()->convDeltaTimeToDeltaZinTimeFrame(trks[revLabel].CSide() *
GPUChainTracking::NSECTORS / 2, trks[revLabel].GetParam().GetTOffset());
1069 comp = fabsf(trks[
i].GetParam().GetZ() + shift1) < fabsf(trks[revLabel].GetParam().GetZ() + shift2);
1071 if (revLabel == -1 || !trks[revLabel].OK() || (trks[
i].OK() && comp)) {
1078 if ((mQATasks & taskClusterAttach) && !tracksExternal) {
1079 std::vector<uint8_t> lowestPadRow(mTracking->mIOPtrs.nMergedTracks);
1081 if (mTracking->mIOPtrs.mergedTrackHitAttachment) {
1082 for (uint32_t
i = 0;
i < GetNMCLabels();
i++) {
1083 if (mClusterParam[
i].attached == 0 && mClusterParam[
i].fakeAttached == 0) {
1084 int32_t attach = mTracking->mIOPtrs.mergedTrackHitAttachment[
i];
1087 mcLabelI_t trackL = mTrackMCLabels[
track];
1089 for (int32_t
j = 0;
j < GetMCLabelNID(
i);
j++) {
1091 if (trackL == GetMCLabel(
i,
j)) {
1097 mClusterParam[
i].fakeAdjacent++;
1099 mClusterParam[
i].adjacent++;
1105 if (mTracking->mIOPtrs.nMergedTracks && clNative) {
1106 std::fill(lowestPadRow.begin(), lowestPadRow.end(), 255);
1111 for (int32_t
j = 0;
j < GetMCLabelNID(
i);
j++) {
1112 uint32_t trackId = GetMCTrackObj(mTrackMCLabelsReverse, GetMCLabel(
i,
j));
1113 if (trackId < lowestPadRow.size() && lowestPadRow[trackId] > iRow) {
1114 lowestPadRow[trackId] = iRow;
1120 for (uint32_t
i = 0;
i < mTracking->mIOPtrs.nMergedTracks;
i++) {
1121 const auto& trk = mTracking->mIOPtrs.mergedTracks[
i];
1122 if (trk.OK() && lowestPadRow[
i] != 255 && trk.NClustersFitted() >= PADROW_CHECK_MINCLS && CAMath::Abs(trk.GetParam().GetQPt()) < 1.0) {
1123 const auto& lowestCl = mTracking->mIOPtrs.mergedTrackHits[trk.FirstClusterRef()].row < mTracking->mIOPtrs.mergedTrackHits[trk.FirstClusterRef() + trk.NClusters() - 1].row ? mTracking->mIOPtrs.mergedTrackHits[trk.FirstClusterRef()] : mTracking->mIOPtrs.mergedTrackHits[trk.FirstClusterRef() + trk.NClusters() - 1];
1124 const int32_t lowestRow = lowestCl.row;
1125 mPadRow[0]->Fill(lowestPadRow[
i], lowestRow, 1.f);
1126 mPadRow[1]->Fill(CAMath::ATan2(trk.GetParam().GetY(), trk.GetParam().GetX()), lowestRow, 1.f);
1127 if (lowestPadRow[
i] < 10 && lowestRow > lowestPadRow[
i] + 3) {
1130 mTracking->GetTPCTransform()->Transform(lowestCl.sector, lowestCl.row, cl.getPad(), cl.getTime(),
x,
y,
z, trk.GetParam().GetTOffset());
1131 float phi = CAMath::ATan2(
y,
x);
1132 mPadRow[2]->Fill(phi, lowestRow, 1.f);
1133 if (CAMath::Abs(phi) < 0.15) {
1134 const float time = cl.getTime();
1135 mPadRow[3]->Fill(mTracking->GetParam().GetUnscaledMult(
time), lowestRow, 1.f);
1143 if (mConfig.matchMCLabels.size()) {
1144 mGoodHits[mNEvents - 1].resize(GetNMCLabels());
1145 std::vector<bool> allowMCLabels(GetNMCTracks(0));
1146 for (uint32_t k = 0; k < GetNMCTracks(0); k++) {
1147 allowMCLabels[k] =
false;
1149 for (uint32_t
i = 0;
i < nReconstructedTracks;
i++) {
1150 if (!mGoodTracks[mNEvents - 1][
i]) {
1153 if (mConfig.matchDisplayMinPt > 0) {
1154 if (!mTrackMCLabels[
i].
isValid()) {
1157 const mcInfo_t&
info = GetMCTrack(mTrackMCLabels[
i]);
1158 if (
info.pX *
info.pX +
info.pY *
info.pY < mConfig.matchDisplayMinPt * mConfig.matchDisplayMinPt) {
1164 for (uint32_t
j = 0;
j <
track.NClusters();
j++) {
1165 int32_t hitId = mTracking->mIOPtrs.mergedTrackHits[
track.FirstClusterRef() +
j].num;
1166 if (GetMCLabelNID(hitId)) {
1167 int32_t mcID = GetMCLabelID(hitId, 0);
1169 allowMCLabels[mcID] =
true;
1174 for (uint32_t
i = 0;
i < GetNMCLabels();
i++) {
1175 for (int32_t
j = 0;
j < GetMCLabelNID(
i);
j++) {
1176 int32_t mcID = GetMCLabelID(
i,
j);
1177 if (mcID >= 0 && allowMCLabels[mcID]) {
1178 mGoodHits[mNEvents - 1][
i] =
true;
1183 if (timer.IsRunning()) {
1184 GPUInfo(
"QA Time: Cluster attach status:\t\t%6.0f us", timer.GetCurrentElapsedTime(
true) * 1e6);
1192 for (uint32_t iCol = 0; iCol < GetNMCCollissions(); iCol++) {
1193 for (uint32_t
i = 0;
i < GetNMCTracks(iCol);
i++) {
1194 mMCParam[iCol][
i].nWeightCls = 0.;
1197 for (uint32_t
i = 0;
i < GetNMCLabels();
i++) {
1198 float weightTotal = 0.f;
1199 for (int32_t
j = 0;
j < GetMCLabelNID(
i);
j++) {
1200 if (GetMCLabelID(
i,
j) >= 0) {
1201 weightTotal += GetMCLabelWeight(
i,
j);
1204 for (int32_t
j = 0;
j < GetMCLabelNID(
i);
j++) {
1205 if (GetMCLabelID(
i,
j) >= 0) {
1206 GetMCTrackObj(mMCParam, GetMCLabel(
i,
j)).nWeightCls += GetMCLabelWeight(
i,
j) / weightTotal;
1210 if (timer.IsRunning()) {
1211 GPUInfo(
"QA Time: Compute cluster label weights:\t%6.0f us", timer.GetCurrentElapsedTime(
true) * 1e6);
1215 tbb::parallel_for<uint32_t>(0, GetNMCCollissions(), [&](
auto iCol) {
1216 for (uint32_t
i = 0;
i < GetNMCTracks(iCol);
i++) {
1217 const mcInfo_t&
info = GetMCTrack(
i, iCol);
1218 additionalMCParameters& mc2 = mMCParam[iCol][
i];
1220 mc2.phi = M_PI + std::atan2(-
info.pY, -
info.pX);
1223 mc2.theta = mc2.eta = 0.f;
1225 mc2.theta =
info.pZ == 0 ? (M_PI / 2) : (
std::acos(
info.pZ /
std::sqrt(
p)));
1226 mc2.eta = -std::log(std::tan(0.5 * mc2.theta));
1228 if (mConfig.writeMCLabels) {
1229 std::vector<int32_t>& effBuffer = mcEffBuffer[mNEvents - 1];
1230 effBuffer[
i] = mRecTracks[iCol][
i] * 1000 + mFakeTracks[iCol][
i];
1233 }, tbb::simple_partitioner());
1234 if (timer.IsRunning()) {
1235 GPUInfo(
"QA Time: Compute track mc parameters:\t%6.0f us", timer.GetCurrentElapsedTime(
true) * 1e6);
1239 if (mQATasks & taskTrackingEff) {
1240 for (uint32_t iCol = 0; iCol < GetNMCCollissions(); iCol++) {
1241 for (uint32_t
i = 0;
i < GetNMCTracks(iCol);
i++) {
1242 if ((mMCTrackMin != -1 && (int32_t)
i < mMCTrackMin) || (mMCTrackMax != -1 && (int32_t)
i >= mMCTrackMax)) {
1245 const mcInfo_t&
info = GetMCTrack(
i, iCol);
1246 const additionalMCParameters& mc2 = mMCParam[iCol][
i];
1247 if (mc2.nWeightCls == 0.f) {
1250 const float& mcpt = mc2.pt;
1251 const float& mcphi = mc2.phi;
1252 const float& mceta = mc2.eta;
1254 if (
info.primDaughters) {
1257 if (mc2.nWeightCls < mConfig.minNClEff) {
1260 int32_t findable = mc2.nWeightCls >= mConfig.minNClFindable;
1264 if (
info.charge == 0.f) {
1267 if (mConfig.filterCharge &&
info.charge * mConfig.filterCharge < 0) {
1270 if (mConfig.filterPID >= 0 &&
info.pid != mConfig.filterPID) {
1274 if (fabsf(mceta) > ETA_MAX || mcpt < PT_MIN || mcpt > PT_MAX) {
1279 alpha /= M_PI / 9.f;
1281 alpha *= M_PI / 9.f;
1282 alpha += M_PI / 18.f;
1284 float c = std::cos(
alpha);
1285 float s = std::sin(
alpha);
1288 if (mConfig.dumpToROOTLevel >= 1) {
1291 effdump.Fill(
alpha, localX, localY,
info.z, mcphi, mceta, mcpt, mRecTracks[iCol][
i], mFakeTracks[iCol][
i], findable,
info.prim, mc2.nWeightCls);
1294 for (int32_t
j = 0;
j < 6;
j++) {
1295 if (
j == 3 ||
j == 4) {
1298 for (int32_t k = 0; k < 2; k++) {
1299 if (k == 0 && findable == 0) {
1303 int32_t
val = (
j == 0) ? (mRecTracks[iCol][
i] ? 1 : 0) : (
j == 1) ? (mRecTracks[iCol][
i] ? mRecTracks[iCol][
i] - 1 : 0) : (
j == 2) ? mFakeTracks[iCol][
i] : 1;
1308 for (int32_t l = 0; l < 5; l++) {
1309 if (
info.prim && mcpt < PT_MIN_PRIM) {
1312 if (l != 3 && fabsf(mceta) > ETA_MAX2) {
1315 if (l < 4 && mcpt < 1.f / mConfig.qpt) {
1319 float pos = l == 0 ? localY : l == 1 ?
info.z : l == 2 ? mcphi : l == 3 ? mceta : mcpt;
1327 if (timer.IsRunning()) {
1328 GPUInfo(
"QA Time: Fill efficiency histograms:\t%6.0f us", timer.GetCurrentElapsedTime(
true) * 1e6);
1333 if (mQATasks & (taskTrackingRes | taskTrackingResPull)) {
1335 prop.SetMaxSinPhi(.999);
1336 prop.SetMaterialTPC();
1337 prop.SetPolynomialField(&mParam->polynomialField);
1339 for (uint32_t
i = 0;
i < mTrackMCLabels.size();
i++) {
1340 if (mConfig.writeMCLabels) {
1341 std::vector<int32_t>& labelBuffer = mcLabelBuffer[mNEvents - 1];
1342 labelBuffer[
i] = mTrackMCLabels[
i].getTrackID();
1344 if (mTrackMCLabels[
i].isFake()) {
1347 const mcInfo_t& mc1 = GetMCTrack(mTrackMCLabels[
i]);
1348 const additionalMCParameters& mc2 = GetMCTrackObj(mMCParam, mTrackMCLabels[
i]);
1350 if (mc1.primDaughters) {
1353 if (!tracksExternal) {
1354 if (!mTracking->mIOPtrs.mergedTracks[
i].OK()) {
1357 if (mTracking->mIOPtrs.mergedTracks[
i].MergedLooper()) {
1361 if ((mMCTrackMin != -1 && mTrackMCLabels[
i].getTrackID() < mMCTrackMin) || (mMCTrackMax != -1 && mTrackMCLabels[
i].getTrackID() >= mMCTrackMax)) {
1364 if (fabsf(mc2.eta) > ETA_MAX || mc2.pt < PT_MIN || mc2.pt > PT_MAX) {
1367 if (mc1.charge == 0.f) {
1374 if (mc1.t0 == -100.f) {
1378 if (mConfig.filterCharge && mc1.charge * mConfig.filterCharge < 0) {
1381 if (mConfig.filterPID >= 0 && mc1.pid != mConfig.filterPID) {
1384 if (mc2.nWeightCls < mConfig.minNClRes) {
1387 if (mConfig.resPrimaries == 1 && !mc1.prim) {
1389 }
else if (mConfig.resPrimaries == 2 && mc1.prim) {
1392 if (GetMCTrackObj(mTrackMCLabelsReverse, mTrackMCLabels[
i]) != (int32_t)
i) {
1399 if (tracksExternal) {
1400#ifndef GPUCA_STANDALONE
1401 for (int32_t k = 0; k < 5; k++) {
1402 param.Par()[k] = (*tracksExternal)[
i].getParams()[k];
1404 for (int32_t k = 0; k < 15; k++) {
1405 param.Cov()[k] = (*tracksExternal)[
i].getCov()[k];
1407 param.X() = (*tracksExternal)[
i].getX();
1408 param.TOffset() = (*tracksExternal)[
i].getTime0();
1409 alpha = (*tracksExternal)[
i].getAlpha();
1410 side = (*tracksExternal)[
i].hasBothSidesClusters() ? 2 : ((*tracksExternal)[
i].hasCSideClusters() ? 1 : 0);
1413 param = mTracking->mIOPtrs.mergedTracks[
i].GetParam();
1414 alpha = mTracking->mIOPtrs.mergedTracks[
i].GetAlpha();
1415 side = mTracking->mIOPtrs.mergedTracks[
i].CCE() ? 2 : (mTracking->mIOPtrs.mergedTracks[
i].CSide() ? 1 : 0);
1419 float c = std::cos(
alpha);
1420 float s = std::sin(
alpha);
1423 mclocal[0] =
x *
c +
y *
s;
1424 mclocal[1] = -
x *
s +
y *
c;
1427 mclocal[2] = px *
c + py *
s;
1428 mclocal[3] = -px *
s + py *
c;
1433 if (mclocal[0] >
param.GetX() + 20) {
1436 if (
param.GetX() > mConfig.maxResX) {
1440 auto getdz = [
this, &
param, &mc1, &
side, tracksExternal]() {
1441 if (tracksExternal) {
1442 return param.GetZ();
1444 if (!mParam->continuousMaxTimeBin) {
1445 return param.GetZ() - mc1.z;
1453 return param.GetZ() + shift - mc1.z;
1457 bool inFlyDirection = 0;
1458 if (mConfig.strict) {
1460 const float dy =
param.Y() - mclocal[1];
1461 const float dz = getdz();
1462 if (dx * dx + dy * dy + dz * dz > 5.f * 5.f) {
1467 if (prop.PropagateToXAlpha(mclocal[0],
alpha, inFlyDirection)) {
1470 if (fabsf(
param.Y() - mclocal[1]) > (mConfig.strict ? 1.f : 4.f) || fabsf(getdz()) > (mConfig.strict ? 1.f : 4.f)) {
1473 float charge = mc1.charge > 0 ? 1.f : -1.f;
1475 float deltaY =
param.GetY() - mclocal[1];
1476 float deltaZ = getdz();
1477 float deltaPhiNative =
param.GetSinPhi() - mclocal[3] / mc2.pt;
1478 float deltaPhi = std::asin(
param.GetSinPhi()) - std::atan2(mclocal[3], mclocal[2]);
1479 float deltaLambdaNative =
param.GetDzDs() - mc1.pZ / mc2.pt;
1480 float deltaLambda = std::atan(
param.GetDzDs()) - std::atan2(mc1.pZ, mc2.pt);
1482 float deltaPt = (fabsf(1.f /
param.GetQPt()) - mc2.pt) / mc2.pt;
1484 float paramval[5] = {mclocal[1], mc1.z, mc2.phi, mc2.eta, mc2.pt};
1485 float resval[5] = {deltaY, deltaZ, mConfig.nativeFitResolutions ? deltaPhiNative : deltaPhi, mConfig.nativeFitResolutions ? deltaLambdaNative : deltaLambda, mConfig.nativeFitResolutions ? deltaPtNative : deltaPt};
1486 float pullval[5] = {deltaY / std::sqrt(
param.GetErr2Y()), deltaZ / std::sqrt(
param.GetErr2Z()), deltaPhiNative / std::sqrt(
param.GetErr2SinPhi()), deltaLambdaNative / std::sqrt(
param.GetErr2DzDs()), deltaPtNative / std::sqrt(
param.GetErr2QPt())};
1488 for (int32_t
j = 0;
j < 5;
j++) {
1489 for (int32_t k = 0; k < 5; k++) {
1490 if (k != 3 && fabsf(mc2.eta) > ETA_MAX2) {
1493 if (k < 4 && mc2.pt < 1.f / mConfig.qpt) {
1496 if (mQATasks & taskTrackingRes) {
1497 mRes2[
j][k]->Fill(resval[
j], paramval[k]);
1499 if (mQATasks & taskTrackingResPull) {
1500 mPull2[
j][k]->Fill(pullval[
j], paramval[k]);
1505 if (timer.IsRunning()) {
1506 GPUInfo(
"QA Time: Fill resolution histograms:\t%6.0f us", timer.GetCurrentElapsedTime(
true) * 1e6);
1510 if ((mQATasks & taskClusterAttach) && !tracksExternal) {
1512 for (uint32_t iTrk = 0; iTrk < nReconstructedTracks; iTrk++) {
1517 if (!mTrackMCLabels[iTrk].
isValid()) {
1518 for (uint32_t k = 0; k <
track.NClusters(); k++) {
1522 int32_t hitId = mTracking->mIOPtrs.mergedTrackHits[
track.FirstClusterRef() + k].num;
1523 float totalWeight = 0.;
1524 for (int32_t
j = 0;
j < GetMCLabelNID(hitId);
j++) {
1525 if (GetMCLabelID(hitId,
j) >= 0 && GetMCTrackObj(mMCParam, GetMCLabel(hitId,
j)).pt > 1.f / mTracking->GetParam().rec.maxTrackQPtB5) {
1526 totalWeight += GetMCLabelWeight(hitId,
j);
1529 int32_t attach = mTracking->mIOPtrs.mergedTrackHitAttachment[hitId];
1530 const auto&
r = checkClusterState<false>(attach);
1531 if (totalWeight > 0) {
1532 float weight = 1.f / (totalWeight * (mClusterParam[hitId].attached + mClusterParam[hitId].fakeAttached));
1533 for (int32_t
j = 0;
j < GetMCLabelNID(hitId);
j++) {
1534 mcLabelI_t
label = GetMCLabel(hitId,
j);
1535 if (!
label.isFake() && GetMCTrackObj(mMCParam,
label).pt > 1.f / mTracking->GetParam().rec.maxTrackQPtB5) {
1536 float pt = GetMCTrackObj(mMCParam,
label).pt;
1537 if (pt < PT_MIN_CLUST) {
1540 mClusters[CL_fake]->Fill(pt, GetMCLabelWeight(hitId,
j) *
weight);
1541 mClusters[CL_att_adj]->Fill(pt, GetMCLabelWeight(hitId,
j) *
weight);
1542 if (GetMCTrackObj(mRecTracks,
label)) {
1543 mClusters[CL_tracks]->Fill(pt, GetMCLabelWeight(hitId,
j) *
weight);
1545 mClusters[CL_all]->Fill(pt, GetMCLabelWeight(hitId,
j) *
weight);
1546 if (
r.protect ||
r.physics) {
1547 mClusters[CL_prot]->Fill(pt, GetMCLabelWeight(hitId,
j) *
weight);
1550 mClusters[CL_physics]->Fill(pt, GetMCLabelWeight(hitId,
j) *
weight);
1555 float weight = 1.f / (mClusterParam[hitId].attached + mClusterParam[hitId].fakeAttached);
1556 mClusters[CL_fake]->Fill(0.f,
weight);
1557 mClusters[CL_att_adj]->Fill(0.f,
weight);
1558 mClusters[CL_all]->Fill(0.f,
weight);
1559 mClusterCounts.nUnaccessible +=
weight;
1560 if (
r.protect ||
r.physics) {
1561 mClusters[CL_prot]->Fill(0.f,
weight);
1564 mClusters[CL_physics]->Fill(0.f,
weight);
1570 mcLabelI_t
label = mTrackMCLabels[iTrk];
1571 if (mMCTrackMin != -1 && (
label.getTrackID() < mMCTrackMin ||
label.getTrackID() >= mMCTrackMax)) {
1574 for (uint32_t k = 0; k <
track.NClusters(); k++) {
1578 int32_t hitId = mTracking->mIOPtrs.mergedTrackHits[
track.FirstClusterRef() + k].num;
1579 float pt = GetMCTrackObj(mMCParam,
label).pt;
1580 if (pt < PT_MIN_CLUST) {
1583 float weight = 1.f / (mClusterParam[hitId].attached + mClusterParam[hitId].fakeAttached);
1584 bool correct =
false;
1585 for (int32_t
j = 0;
j < GetMCLabelNID(hitId);
j++) {
1586 if (
label == GetMCLabel(hitId,
j)) {
1592 mClusters[CL_attached]->Fill(pt,
weight);
1593 mClusters[CL_tracks]->Fill(pt,
weight);
1595 mClusters[CL_fake]->Fill(pt,
weight);
1597 mClusters[CL_att_adj]->Fill(pt,
weight);
1598 mClusters[CL_all]->Fill(pt,
weight);
1599 int32_t attach = mTracking->mIOPtrs.mergedTrackHitAttachment[hitId];
1600 const auto&
r = checkClusterState<false>(attach);
1601 if (
r.protect ||
r.physics) {
1602 mClusters[CL_prot]->Fill(pt,
weight);
1605 mClusters[CL_physics]->Fill(pt,
weight);
1609 for (uint32_t
i = 0;
i < GetNMCLabels();
i++) {
1610 if ((mMCTrackMin != -1 && GetMCLabelID(
i, 0) < mMCTrackMin) || (mMCTrackMax != -1 && GetMCLabelID(
i, 0) >= mMCTrackMax)) {
1613 if (mClusterParam[
i].attached || mClusterParam[
i].fakeAttached) {
1616 int32_t attach = mTracking->mIOPtrs.mergedTrackHitAttachment[
i];
1617 const auto&
r = checkClusterState<false>(attach);
1618 if (mClusterParam[
i].adjacent) {
1621 float totalWeight = 0.;
1622 for (int32_t
j = 0;
j < GetMCLabelNID(
i);
j++) {
1623 mcLabelI_t labelT = GetMCLabel(
i,
j);
1624 if (!labelT.isFake() && GetMCTrackObj(mMCParam, labelT).pt > 1.f / mTracking->GetParam().rec.maxTrackQPtB5) {
1625 totalWeight += GetMCLabelWeight(
i,
j);
1628 float weight = 1.f / totalWeight;
1629 if (totalWeight > 0) {
1630 for (int32_t
j = 0;
j < GetMCLabelNID(
i);
j++) {
1631 mcLabelI_t labelT = GetMCLabel(
i,
j);
1632 if (!labelT.isFake() && GetMCTrackObj(mMCParam, labelT).pt > 1.f / mTracking->GetParam().rec.maxTrackQPtB5) {
1633 float pt = GetMCTrackObj(mMCParam, labelT).pt;
1634 if (pt < PT_MIN_CLUST) {
1637 if (GetMCTrackObj(mRecTracks, labelT)) {
1638 mClusters[CL_tracks]->Fill(pt, GetMCLabelWeight(
i,
j) *
weight);
1640 mClusters[CL_att_adj]->Fill(pt, GetMCLabelWeight(
i,
j) *
weight);
1641 mClusters[CL_fakeAdj]->Fill(pt, GetMCLabelWeight(
i,
j) *
weight);
1642 mClusters[CL_all]->Fill(pt, GetMCLabelWeight(
i,
j) *
weight);
1643 if (
r.protect ||
r.physics) {
1644 mClusters[CL_prot]->Fill(pt, GetMCLabelWeight(
i,
j) *
weight);
1647 mClusters[CL_physics]->Fill(pt, GetMCLabelWeight(
i,
j) *
weight);
1652 mClusters[CL_att_adj]->Fill(0.f, 1.f);
1653 mClusters[CL_fakeAdj]->Fill(0.f, 1.f);
1654 mClusters[CL_all]->Fill(0.f, 1.f);
1655 mClusterCounts.nUnaccessible++;
1656 if (
r.protect ||
r.physics) {
1657 mClusters[CL_prot]->Fill(0.f, 1.f);
1660 mClusters[CL_physics]->Fill(0.f, 1.f);
1664 float pt = GetMCTrackObj(mMCParam, mTrackMCLabels[
label]).pt;
1665 if (pt < PT_MIN_CLUST) {
1668 mClusters[CL_att_adj]->Fill(pt, 1.f);
1669 mClusters[CL_tracks]->Fill(pt, 1.f);
1670 mClusters[CL_all]->Fill(pt, 1.f);
1671 if (
r.protect ||
r.physics) {
1672 mClusters[CL_prot]->Fill(pt, 1.f);
1675 mClusters[CL_physics]->Fill(pt, 1.f);
1679 float totalWeight = 0.;
1680 for (int32_t
j = 0;
j < GetMCLabelNID(
i);
j++) {
1681 mcLabelI_t labelT = GetMCLabel(
i,
j);
1682 if (!labelT.isFake() && GetMCTrackObj(mMCParam, labelT).pt > 1.f / mTracking->GetParam().rec.maxTrackQPtB5) {
1683 totalWeight += GetMCLabelWeight(
i,
j);
1686 if (totalWeight > 0) {
1687 for (int32_t
j = 0;
j < GetMCLabelNID(
i);
j++) {
1688 mcLabelI_t
label = GetMCLabel(
i,
j);
1689 if (!
label.isFake() && GetMCTrackObj(mMCParam,
label).pt > 1.f / mTracking->GetParam().rec.maxTrackQPtB5) {
1690 float pt = GetMCTrackObj(mMCParam,
label).pt;
1691 if (pt < PT_MIN_CLUST) {
1694 float weight = GetMCLabelWeight(
i,
j) / totalWeight;
1695 if (mClusterParam[
i].fakeAdjacent) {
1696 mClusters[CL_fakeAdj]->Fill(pt,
weight);
1698 if (mClusterParam[
i].fakeAdjacent) {
1699 mClusters[CL_att_adj]->Fill(pt,
weight);
1701 if (GetMCTrackObj(mRecTracks,
label)) {
1702 mClusters[CL_tracks]->Fill(pt,
weight);
1704 mClusters[CL_all]->Fill(pt,
weight);
1705 if (
r.protect ||
r.physics) {
1706 mClusters[CL_prot]->Fill(pt,
weight);
1709 mClusters[CL_physics]->Fill(pt,
weight);
1714 if (mClusterParam[
i].fakeAdjacent) {
1715 mClusters[CL_fakeAdj]->Fill(0.f, 1.f);
1717 if (mClusterParam[
i].fakeAdjacent) {
1718 mClusters[CL_att_adj]->Fill(0.f, 1.f);
1720 mClusters[CL_all]->Fill(0.f, 1.f);
1721 mClusterCounts.nUnaccessible++;
1722 if (
r.protect ||
r.physics) {
1723 mClusters[CL_prot]->Fill(0.f, 1.f);
1726 mClusters[CL_physics]->Fill(0.f, 1.f);
1732 if (timer.IsRunning()) {
1733 GPUInfo(
"QA Time: Fill cluster histograms:\t%6.0f us", timer.GetCurrentElapsedTime(
true) * 1e6);
1736 }
else if (!mConfig.inputHistogramsOnly && !mConfig.noMC && (mQATasks & (taskTrackingEff | taskTrackingRes | taskTrackingResPull | taskClusterAttach))) {
1737 GPUWarning(
"No MC information available, only running partial TPC QA!");
1740 if ((mQATasks & taskTrackStatistics) && !tracksExternal) {
1742 std::vector<std::array<float, 3>> clusterAttachCounts;
1744 clusterAttachCounts.resize(GetNMCLabels(), {0.f, 0.f});
1746 for (uint32_t
i = 0;
i < nReconstructedTracks;
i++) {
1751 mTrackPt->Fill(1.f / fabsf(
track.GetParam().GetQPt()));
1752 if (mParam->par.dodEdx && mParam->dodEdxEnabled &&
track.NClusters() >= 60) {
1753 const GPUdEdxInfo& trackdEdx = mTracking->GetProcessors()->tpcMerger.MergedTracksdEdx()[
i];
1754 const float logp = logf(1.f / fabsf(
track.GetParam().GetQPt()) * sqrtf(1.f +
track.GetParam().GetDzDs() *
track.GetParam().GetDzDs()));
1755 mTrackdEdx[0]->Fill(logp, trackdEdx.
dEdxTotTPC);
1756 mTrackdEdx[1]->Fill(logp, trackdEdx.
dEdxMaxTPC);
1758 mNCl[0]->Fill(
track.NClustersFitted());
1759 uint32_t nClCorrected = 0;
1760 const auto& trackClusters = mTracking->mIOPtrs.mergedTrackHits;
1762 for (uint32_t
j = 0;
j <
track.NClusters();
j = jNext) {
1764 for (jNext =
j + 1;
j <
track.NClusters(); jNext++) {
1765 if (trackClusters[
track.FirstClusterRef() +
j].sector != trackClusters[
track.FirstClusterRef() + jNext].sector || trackClusters[
track.FirstClusterRef() +
j].row != trackClusters[
track.FirstClusterRef() + jNext].row) {
1770 if (!
track.MergedLooper() && rowClCount) {
1773 if (mcAvail && rowClCount) {
1774 for (uint32_t k =
j; k < jNext; k++) {
1775 const auto& cl = trackClusters[
track.FirstClusterRef() + k];
1779 bool labelOk =
false, labelOkNonFake =
false;
1780 const mcLabelI_t& trkLabel = mTrackMCLabels[
i];
1781 if (trkLabel.isValid() && !trkLabel.isNoise()) {
1782 for (int32_t l = 0; l < GetMCLabelNID(cl.num); l++) {
1783 const mcLabelI_t& clLabel = GetMCLabel(cl.num, l);
1784 if (clLabel.isValid() && !clLabel.isNoise() && CompareIgnoreFake(trkLabel, clLabel)) {
1786 if (!trkLabel.isFake()) {
1787 labelOkNonFake =
true;
1793 clusterAttachCounts[cl.num][0] += 1.0f;
1794 clusterAttachCounts[cl.num][1] += (float)labelOk / rowClCount;
1795 clusterAttachCounts[cl.num][2] += (float)labelOkNonFake / rowClCount;
1800 mNCl[1]->Fill(nClCorrected);
1802 mT0[0]->Fill(
track.GetParam().GetTOffset());
1804 if (mTrackMCLabels.size() && !mTrackMCLabels[
i].isFake() && !
track.MergedLooper() && !
track.CCE()) {
1805 const auto&
info = GetMCTrack(mTrackMCLabels[
i]);
1806 if (
info.t0 != -100.f) {
1807 mT0[1]->Fill(
track.GetParam().GetTOffset() -
info.t0);
1812 if (mClNative && mTracking && mTracking->GetTPCTransform()) {
1815 for (uint32_t k = 0; k < mClNative->nClusters[
i][
j]; k++) {
1816 const auto& cl = mClNative->clusters[
i][
j][k];
1818 GPUTPCConvertImpl::convert(*mTracking->GetTPCTransform(), mTracking->GetParam(),
i,
j, cl.getPad(), cl.getTime(),
x,
y,
z);
1819 mTracking->GetParam().Sector2Global(
i,
x,
y,
z, &
x, &
y, &
z);
1826 double clusterAttachNormalizedCount = 0, clusterAttachNormalizedCountNonFake = 0;
1827 for (uint32_t
i = 0;
i < clusterAttachCounts.size();
i++) {
1828 if (clusterAttachCounts[
i][0]) {
1829 clusterAttachNormalizedCount += clusterAttachCounts[
i][1] / clusterAttachCounts[
i][0];
1830 clusterAttachNormalizedCountNonFake += clusterAttachCounts[
i][2] / clusterAttachCounts[
i][0];
1833 mClusterCounts.nCorrectlyAttachedNormalized = clusterAttachNormalizedCount;
1834 mClusterCounts.nCorrectlyAttachedNormalizedNonFake = clusterAttachNormalizedCountNonFake;
1835 clusterAttachCounts.clear();
1838 if (timer.IsRunning()) {
1839 GPUInfo(
"QA Time: Fill track statistics:\t%6.0f us", timer.GetCurrentElapsedTime(
true) * 1e6);
1843 uint32_t
nCl = clNative ? clNative->
nClustersTotal : mTracking->GetProcessors()->tpcMerger.NMaxClusters();
1844 mClusterCounts.nTotal +=
nCl;
1845 if (mQATasks & (taskClusterCounts | taskClusterRejection)) {
1850 int32_t attach = mTracking->mIOPtrs.mergedTrackHitAttachment[
i];
1851 const auto&
r = checkClusterState<true>(attach, &mClusterCounts);
1853 if (mQATasks & taskClusterRejection) {
1855 float totalWeight = 0, weight400 = 0, weight40 = 0;
1856 for (int32_t
j = 0;
j < GetMCLabelNID(
i);
j++) {
1857 const auto&
label = GetMCLabel(
i,
j);
1858 if (GetMCLabelID(
label) >= 0) {
1859 totalWeight += GetMCLabelWeight(
label);
1860 if (GetMCTrackObj(mMCParam,
label).pt >= 0.4) {
1861 weight400 += GetMCLabelWeight(
label);
1863 if (GetMCTrackObj(mMCParam,
label).pt <= 0.04) {
1864 weight40 += GetMCLabelWeight(
label);
1868 if (totalWeight > 0 && 10.f * weight400 >= totalWeight) {
1869 if (!
r.unattached && !
r.protect && !
r.physics) {
1870 mClusterCounts.nFakeRemove400++;
1871 int32_t totalFake = weight400 < 0.9f * totalWeight;
1873 mClusterCounts.nFullFakeRemove400++;
1888 mClusterCounts.nAbove400++;
1890 if (totalWeight > 0 && weight40 >= 0.9 * totalWeight) {
1891 mClusterCounts.nBelow40++;
1892 if (
r.protect ||
r.physics) {
1893 mClusterCounts.nFakeProtect40++;
1899 mClusterCounts.nPhysics++;
1902 mClusterCounts.nProt++;
1905 mClusterCounts.nUnattached++;
1908 if (mQATasks & taskClusterRejection) {
1909 if (mTracking && clNative) {
1911 mClRej[0]->Fill(cl.getPad() - GPUTPCGeometry::NPads(iRow) / 2 + 0.5, iRow, 1.f);
1912 if (!
r.unattached && !
r.protect) {
1913 mClRej[1]->Fill(cl.getPad() - GPUTPCGeometry::NPads(iRow) / 2 + 0.5, iRow, 1.f);
1923 if ((mQATasks & taskClusterCounts) && mConfig.clusterRejectionHistograms) {
1924 DoClusterCounts(
nullptr);
1925 mClusterCounts = counts_t();
1928 if (timer.IsRunning()) {
1929 GPUInfo(
"QA Time: Cluster Counts:\t%6.0f us", timer.GetCurrentElapsedTime(
true) * 1e6);
1932 if (mConfig.dumpToROOTLevel >= 1 && !tracksExternal) {
1933 if (!clNative || !mTracking || !mTracking->mIOPtrs.mergedTrackHitAttachment || !mTracking->mIOPtrs.mergedTracks) {
1934 throw std::runtime_error(
"Cannot dump non o2::tpc::clusterNative clusters, need also hit attachmend and GPU tracks");
1939 for (uint32_t k = 0; k < mClNative->nClusters[
i][
j]; k++) {
1940 const auto& cl = mClNative->clusters[
i][
j][k];
1941 uint32_t attach = mTracking->mIOPtrs.mergedTrackHitAttachment[clid];
1942 float x = 0,
y = 0,
z = 0;
1945 const auto& trk = mTracking->mIOPtrs.mergedTracks[
track];
1946 mTracking->GetTPCTransform()->Transform(
i,
j, cl.getPad(), cl.getTime(),
x,
y,
z, trk.GetParam().GetTOffset());
1947 mTracking->GetParam().Sector2Global(
i,
x,
y,
z, &
x, &
y, &
z);
1949 uint32_t extState = mTracking->mIOPtrs.mergedTrackHitStates ? mTracking->mIOPtrs.mergedTrackHitStates[clid] : 0;
1951 if (mConfig.dumpToROOTLevel >= 2) {
1954 memset((
void*)&trk, 0,
sizeof(trk));
1955 memset((
void*)&trkHit, 0,
sizeof(trkHit));
1958 trk = mTracking->mIOPtrs.mergedTracks[
track];
1959 for (uint32_t l = 0; l < trk.NClusters(); l++) {
1960 const auto& tmp = mTracking->mIOPtrs.mergedTrackHits[trk.FirstClusterRef() + l];
1961 if (tmp.num == clid) {
1967 static auto cldump =
GPUROOTDump<o2::tpc::ClusterNative, GPUTPCGMMergedTrack, GPUTPCGMMergedTrackHit, uint32_t, uint32_t, float, float, float, uint32_t, uint32_t, uint32_t>::getNew(
"cluster",
"track",
"trackHit",
"attach",
"extState",
"x",
"y",
"z",
"sector",
"row",
"nEv",
"clusterTree");
1968 cldump.Fill(cl, trk, trkHit, attach, extState,
x,
y,
z,
i,
j, mNEvents - 1);
1970 static auto cldump =
GPUROOTDump<o2::tpc::ClusterNative, uint32_t, uint32_t, float, float, float, uint32_t, uint32_t, uint32_t>::getNew(
"cluster",
"attach",
"extState",
"x",
"y",
"z",
"sector",
"row",
"nEv",
"clusterTree");
1971 cldump.Fill(cl, attach, extState,
x,
y,
z,
i,
j, mNEvents - 1);
1979 for (uint32_t
i = 0;
i < mTracking->mIOPtrs.nMergedTracks;
i++) {
1980 if (mTracking->mIOPtrs.mergedTracks[
i].OK()) {
1981 trkdump.Fill(mNEvents - 1, mTracking->mIOPtrs.mergedTracks[
i]);
1985 if (mTracking && mTracking->GetProcessingSettings().createO2Output) {
1987 for (uint32_t
i = 0;
i < mTracking->mIOPtrs.nOutputTracksTPCO2;
i++) {
1988 o2trkdump.Fill(mNEvents - 1, mTracking->mIOPtrs.outputTracksTPCO2[
i]);
1993 if (mConfig.compareTrackStatus) {
1994#ifdef GPUCA_DETERMINISTIC_MODE
1995 if (!mTracking || !mTracking->GetProcessingSettings().deterministicGPUReconstruction)
1998 throw std::runtime_error(
"Need deterministic processing to compare track status");
2000 std::vector<uint8_t> status(mTracking->mIOPtrs.nMergedTracks);
2001 for (uint32_t
i = 0;
i < mTracking->mIOPtrs.nMergedTracks;
i++) {
2002 const auto& trk = mTracking->mIOPtrs.mergedTracks[
i];
2003 status[
i] = trk.OK() && trk.NClusters() && trk.GetParam().GetNDF() > 0 && (mConfig.noMC || (mTrackMCLabels[
i].isValid() && !mTrackMCLabels[
i].isFake()));
2005 if (mConfig.compareTrackStatus == 1) {
2006 std::ofstream(
"track.status", std::ios::binary).write((
char*)status.data(), status.size() *
sizeof(status[0]));
2007 }
else if (mConfig.compareTrackStatus == 2) {
2008 std::ifstream
f(
"track.status", std::ios::binary | std::ios::ate);
2009 std::vector<uint8_t> comp(
f.tellg());
2011 f.read((
char*)comp.data(), comp.size());
2013 if (comp.size() != status.size()) {
2014 throw std::runtime_error(
"Number of tracks candidates in track fit in track.status and in current reconstruction differ");
2016 std::vector<uint32_t> missing, missingComp;
2017 for (uint32_t
i = 0;
i < status.size();
i++) {
2018 if (status[
i] && !comp[
i]) {
2019 missingComp.emplace_back(
i);
2021 if (comp[
i] && !status[
i]) {
2022 missing.emplace_back(
i);
2025 auto printer = [](std::vector<uint32_t>
m,
const char*
name) {
2027 printf(
"Missing in %s reconstruction: (%zu)\n",
name,
m.size());
2028 for (uint32_t
i = 0;
i <
m.size();
i++) {
2037 printer(missing,
"current");
2038 printer(missingComp,
"comparison");
2042 mTrackingScratchBuffer.clear();
2043 mTrackingScratchBuffer.shrink_to_fit();
2046void GPUQA::GetName(
char* fname, int32_t k,
bool noDash)
2048 const int32_t nNewInput = mConfig.inputHistogramsOnly ? 0 : 1;
2049 if (k || mConfig.inputHistogramsOnly || mConfig.name.size()) {
2050 if (!(mConfig.inputHistogramsOnly || k)) {
2051 snprintf(fname, 1024,
"%s%s", mConfig.name.c_str(), noDash ?
"" :
" - ");
2052 }
else if (mConfig.compareInputNames.size() > (
unsigned)(k - nNewInput)) {
2053 snprintf(fname, 1024,
"%s%s", mConfig.compareInputNames[k - nNewInput].c_str(), noDash ?
"" :
" - ");
2055 strcpy(fname, mConfig.compareInputs[k - nNewInput].c_str());
2056 if (strlen(fname) > 5 && strcmp(fname + strlen(fname) - 5,
".root") == 0) {
2057 fname[strlen(fname) - 5] = 0;
2060 strcat(fname,
" - ");
2069T* GPUQA::GetHist(T*& ee, std::vector<std::unique_ptr<TFile>>& tin, int32_t k, int32_t nNewInput)
2072 if ((mConfig.inputHistogramsOnly || k) && (e =
dynamic_cast<T*
>(tin[k - nNewInput]->Get(e->GetName()))) ==
nullptr) {
2073 GPUWarning(
"Missing histogram in input %s: %s", mConfig.compareInputs[k - nNewInput].c_str(), ee->GetName());
2080void GPUQA::DrawQAHistogramsCleanup()
2082 clearGarbagageCollector();
2085void GPUQA::resetHists()
2087 if (!mQAInitialized) {
2088 throw std::runtime_error(
"QA not initialized");
2090 if (mHaveExternalHists) {
2091 throw std::runtime_error(
"Cannot reset external hists");
2093 for (
auto&
h : *mHist1D) {
2096 for (
auto&
h : *mHist2D) {
2099 for (
auto&
h : *mHist1Dd) {
2102 for (
auto&
h : *mHistGraph) {
2103 h = TGraphAsymmErrors();
2105 mClusterCounts = counts_t();
2110 const auto oldRootIgnoreLevel = gErrorIgnoreLevel;
2111 gErrorIgnoreLevel = kWarning;
2112 if (!mQAInitialized) {
2113 throw std::runtime_error(
"QA not initialized");
2116 if (mTracking && mTracking->GetProcessingSettings().debugLevel >= 2) {
2117 printf(
"Creating QA Histograms\n");
2120 std::vector<Color_t> colorNums(COLORCOUNT);
2121 if (!(qcout || mConfig.writeFileExt ==
"root" || mConfig.writeFileExt ==
"C")) {
2122 [[maybe_unused]]
static int32_t initColorsInitialized = initColors();
2124 for (int32_t
i = 0;
i < COLORCOUNT;
i++) {
2125 colorNums[
i] = (qcout || mConfig.writeFileExt ==
"root" || mConfig.writeFileExt ==
"C") ? defaultColorNums[
i] : mColors[
i]->GetNumber();
2128 bool mcAvail = mcPresent();
2129 char name[2048], fname[1024];
2131 const int32_t nNewInput = mConfig.inputHistogramsOnly ? 0 : 1;
2132 const int32_t ConfigNumInputs = nNewInput + mConfig.compareInputs.size();
2134 std::vector<std::unique_ptr<TFile>> tin;
2135 for (uint32_t
i = 0;
i < mConfig.compareInputs.size();
i++) {
2136 tin.emplace_back(std::make_unique<TFile>(mConfig.compareInputs[
i].c_str()));
2138 std::unique_ptr<TFile> tout =
nullptr;
2139 if (mConfig.output.size()) {
2140 tout = std::make_unique<TFile>(mConfig.output.c_str(),
"RECREATE");
2143 if (mConfig.enableLocalOutput || mConfig.shipToQCAsCanvas) {
2144 float legendSpacingString = 0.025;
2145 for (int32_t
i = 0;
i < ConfigNumInputs;
i++) {
2147 if (strlen(fname) * 0.006 > legendSpacingString) {
2148 legendSpacingString = strlen(fname) * 0.006;
2153 if (mQATasks & taskTrackingEff) {
2154 for (int32_t ii = 0; ii < 6; ii++) {
2155 snprintf(
name, 1024,
"eff_vs_%s_layout", VSPARAMETER_NAMES[ii]);
2156 mCEff[ii] = createGarbageCollected<TCanvas>(
name,
name, 0, 0, 700, 700. * 2. / 3.);
2159 mPEff[ii][0] = createGarbageCollected<TPad>(
"p0",
"", 0.0, dy * 0, 0.5, dy * 1);
2160 mPEff[ii][0]->Draw();
2161 mPEff[ii][0]->SetRightMargin(0.04);
2162 mPEff[ii][1] = createGarbageCollected<TPad>(
"p1",
"", 0.5, dy * 0, 1.0, dy * 1);
2163 mPEff[ii][1]->Draw();
2164 mPEff[ii][1]->SetRightMargin(0.04);
2165 mPEff[ii][2] = createGarbageCollected<TPad>(
"p2",
"", 0.0, dy * 1, 0.5, dy * 2 - .001);
2166 mPEff[ii][2]->Draw();
2167 mPEff[ii][2]->SetRightMargin(0.04);
2168 mPEff[ii][3] = createGarbageCollected<TPad>(
"p3",
"", 0.5, dy * 1, 1.0, dy * 2 - .001);
2169 mPEff[ii][3]->Draw();
2170 mPEff[ii][3]->SetRightMargin(0.04);
2171 mLEff[ii] = createGarbageCollected<TLegend>(0.92 - legendSpacingString * 1.45, 0.83 - (0.93 - 0.82) / 2. * (
float)ConfigNumInputs, 0.98, 0.849);
2172 SetLegend(mLEff[ii]);
2177 if (mQATasks & taskTrackingRes) {
2178 for (int32_t ii = 0; ii < 7; ii++) {
2180 snprintf(
name, 1024,
"res_integral_layout");
2182 snprintf(
name, 1024,
"res_vs_%s_layout", VSPARAMETER_NAMES[ii]);
2184 mCRes[ii] = createGarbageCollected<TCanvas>(
name,
name, 0, 0, 700, 700. * 2. / 3.);
2186 gStyle->SetOptFit(1);
2189 mPRes[ii][3] = createGarbageCollected<TPad>(
"p0",
"", 0.0, dy * 0, 0.5, dy * 1);
2190 mPRes[ii][3]->Draw();
2191 mPRes[ii][3]->SetRightMargin(0.04);
2192 mPRes[ii][4] = createGarbageCollected<TPad>(
"p1",
"", 0.5, dy * 0, 1.0, dy * 1);
2193 mPRes[ii][4]->Draw();
2194 mPRes[ii][4]->SetRightMargin(0.04);
2195 mPRes[ii][0] = createGarbageCollected<TPad>(
"p2",
"", 0.0, dy * 1, 1. / 3., dy * 2 - .001);
2196 mPRes[ii][0]->Draw();
2197 mPRes[ii][0]->SetRightMargin(0.04);
2198 mPRes[ii][0]->SetLeftMargin(0.15);
2199 mPRes[ii][1] = createGarbageCollected<TPad>(
"p3",
"", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001);
2200 mPRes[ii][1]->Draw();
2201 mPRes[ii][1]->SetRightMargin(0.04);
2202 mPRes[ii][1]->SetLeftMargin(0.135);
2203 mPRes[ii][2] = createGarbageCollected<TPad>(
"p4",
"", 2. / 3., dy * 1, 1.0, dy * 2 - .001);
2204 mPRes[ii][2]->Draw();
2205 mPRes[ii][2]->SetRightMargin(0.06);
2206 mPRes[ii][2]->SetLeftMargin(0.135);
2208 mLRes[ii] = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (
float)ConfigNumInputs, 0.98, 0.949);
2209 SetLegend(mLRes[ii]);
2215 if (mQATasks & taskTrackingResPull) {
2216 for (int32_t ii = 0; ii < 7; ii++) {
2218 snprintf(
name, 1024,
"pull_integral_layout");
2220 snprintf(
name, 1024,
"pull_vs_%s_layout", VSPARAMETER_NAMES[ii]);
2222 mCPull[ii] = createGarbageCollected<TCanvas>(
name,
name, 0, 0, 700, 700. * 2. / 3.);
2224 gStyle->SetOptFit(1);
2227 mPPull[ii][3] = createGarbageCollected<TPad>(
"p0",
"", 0.0, dy * 0, 0.5, dy * 1);
2228 mPPull[ii][3]->Draw();
2229 mPPull[ii][3]->SetRightMargin(0.04);
2230 mPPull[ii][4] = createGarbageCollected<TPad>(
"p1",
"", 0.5, dy * 0, 1.0, dy * 1);
2231 mPPull[ii][4]->Draw();
2232 mPPull[ii][4]->SetRightMargin(0.04);
2233 mPPull[ii][0] = createGarbageCollected<TPad>(
"p2",
"", 0.0, dy * 1, 1. / 3., dy * 2 - .001);
2234 mPPull[ii][0]->Draw();
2235 mPPull[ii][0]->SetRightMargin(0.04);
2236 mPPull[ii][0]->SetLeftMargin(0.15);
2237 mPPull[ii][1] = createGarbageCollected<TPad>(
"p3",
"", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001);
2238 mPPull[ii][1]->Draw();
2239 mPPull[ii][1]->SetRightMargin(0.04);
2240 mPPull[ii][1]->SetLeftMargin(0.135);
2241 mPPull[ii][2] = createGarbageCollected<TPad>(
"p4",
"", 2. / 3., dy * 1, 1.0, dy * 2 - .001);
2242 mPPull[ii][2]->Draw();
2243 mPPull[ii][2]->SetRightMargin(0.06);
2244 mPPull[ii][2]->SetLeftMargin(0.135);
2246 mLPull[ii] = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (
float)ConfigNumInputs, 0.98, 0.949);
2247 SetLegend(mLPull[ii]);
2253 if (mQATasks & taskClusterAttach) {
2254 for (int32_t
i = 0;
i < 3;
i++) {
2255 snprintf(
name, 1024,
"clusters_%s_layout", CLUSTER_TYPES[
i]);
2256 mCClust[
i] = createGarbageCollected<TCanvas>(
name,
name, 0, 0, 700, 700. * 2. / 3.);
2258 mPClust[
i] = createGarbageCollected<TPad>(
"p0",
"", 0.0, 0.0, 1.0, 1.0);
2260 float y1 =
i != 1 ? 0.77 : 0.27,
y2 =
i != 1 ? 0.9 : 0.42;
2261 mLClust[
i] = createGarbageCollected<TLegend>(
i == 2 ? 0.1 : (0.65 - legendSpacingString * 1.45),
y2 - (
y2 -
y1) * (ConfigNumInputs + (
i != 1) / 2.) + 0.005,
i == 2 ? (0.3 + legendSpacingString * 1.45) : 0.9,
y2);
2262 SetLegend(mLClust[
i]);
2267 if (mQATasks & taskTrackStatistics) {
2268 for (int32_t
i = 0;
i < 3;
i++) {
2269 snprintf(
name, 2048,
"ctracks%s",
i ? (
i == 2 ?
"dedxmax" :
"dedxtot") :
"pt");
2270 mCTracks[
i] = createGarbageCollected<TCanvas>(
name,
name, 0, 0, 700, 700. * 2. / 3.);
2272 mPTracks[
i] = createGarbageCollected<TPad>(
"p0",
"", 0.0, 0.0, 1.0, 1.0);
2273 mPTracks[
i]->Draw();
2274 mLTracks[
i] = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.5, 0.93 - (0.93 - 0.86) / 2. * (
float)ConfigNumInputs, 0.98, 0.949);
2275 SetLegend(mLTracks[
i],
true);
2278 for (int32_t
i = 0;
i < 2;
i++) {
2279 snprintf(
name, 2048,
"ctrackst0%d",
i);
2280 mCT0[
i] = createGarbageCollected<TCanvas>(
name,
name, 0, 0, 700, 700. * 2. / 3.);
2282 mPT0[
i] = createGarbageCollected<TPad>(
"p0",
"", 0.0, 0.0, 1.0, 1.0);
2284 mLT0[
i] = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (
float)ConfigNumInputs, 0.98, 0.949);
2287 snprintf(
name, 2048,
"cncl%d",
i);
2288 mCNCl[
i] = createGarbageCollected<TCanvas>(
name,
name, 0, 0, 700, 700. * 2. / 3.);
2290 mPNCl[
i] = createGarbageCollected<TPad>(
"p0",
"", 0.0, 0.0, 1.0, 1.0);
2292 mLNCl[
i] = createGarbageCollected<TLegend>(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (
float)ConfigNumInputs, 0.98, 0.949);
2293 SetLegend(mLNCl[
i],
true);
2296 mCClXY = createGarbageCollected<TCanvas>(
"clxy",
"clxy", 0, 0, 700, 700. * 2. / 3.);
2298 mPClXY = createGarbageCollected<TPad>(
"p0",
"", 0.0, 0.0, 1.0, 1.0);
2302 if (mQATasks & taskClusterRejection) {
2303 for (int32_t
i = 0;
i < 3;
i++) {
2304 snprintf(
name, 2048,
"cnclrej%d",
i);
2305 mCClRej[
i] = createGarbageCollected<TCanvas>(
name,
name, 0, 0, 700, 700. * 2. / 3.);
2307 mPClRej[
i] = createGarbageCollected<TPad>(
"p0",
"", 0.0, 0.0, 1.0, 1.0);
2310 mCClRejP = createGarbageCollected<TCanvas>(
"cnclrejp",
"cnclrejp", 0, 0, 700, 700. * 2. / 3.);
2312 mPClRejP = createGarbageCollected<TPad>(
"p0",
"", 0.0, 0.0, 1.0, 1.0);
2316 if (mQATasks & taskClusterAttach) {
2317 for (int32_t
i = 0;
i < 4;
i++) {
2318 snprintf(
name, 2048,
"cpadrow%d",
i);
2319 mCPadRow[
i] = createGarbageCollected<TCanvas>(
name,
name, 0, 0, 700, 700. * 2. / 3.);
2321 mPPadRow[
i] = createGarbageCollected<TPad>(
"p0",
"", 0.0, 0.0, 1.0, 1.0);
2322 mPPadRow[
i]->Draw();
2327 if (mConfig.enableLocalOutput && !mConfig.inputHistogramsOnly && (mQATasks & taskTrackingEff) && mcPresent()) {
2328 GPUInfo(
"QA Stats: Eff: Tracks Prim %d (Eta %d, Pt %d) %f%% (%f%%) Sec %d (Eta %d, Pt %d) %f%% (%f%%) - Res: Tracks %d (Eta %d, Pt %d)", (int32_t)mEff[3][1][0][0]->GetEntries(), (int32_t)mEff[3][1][0][3]->GetEntries(), (int32_t)mEff[3][1][0][4]->GetEntries(),
2329 mEff[0][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][0][0]->GetSumOfWeights()), mEff[0][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][0][0]->GetSumOfWeights()), (int32_t)mEff[3][1][1][0]->GetEntries(), (int32_t)mEff[3][1][1][3]->GetEntries(),
2330 (int32_t)mEff[3][1][1][4]->GetEntries(), mEff[0][0][1][0]->GetSumOfWeights() / std::max(1., mEff[3][0][1][0]->GetSumOfWeights()), mEff[0][1][1][0]->GetSumOfWeights() / std::max(1., mEff[3][1][1][0]->GetSumOfWeights()), (int32_t)mRes2[0][0]->GetEntries(),
2331 (int32_t)mRes2[0][3]->GetEntries(), (int32_t)mRes2[0][4]->GetEntries());
2334 int32_t flagShowVsPtLog = (mConfig.enableLocalOutput || mConfig.shipToQCAsCanvas) ? 1 : 0;
2336 if (mQATasks & taskTrackingEff) {
2338 for (int32_t ii = 0; ii < 5 + flagShowVsPtLog; ii++) {
2339 int32_t
i = ii == 5 ? 4 : ii;
2340 for (int32_t k = 0; k < ConfigNumInputs; k++) {
2341 for (int32_t
j = 0;
j < 4;
j++) {
2342 if (mConfig.enableLocalOutput || mConfig.shipToQCAsCanvas) {
2345 mPEff[ii][
j]->SetLogx();
2348 for (int32_t l = 0; l < 3; l++) {
2349 if (k == 0 && mConfig.inputHistogramsOnly == 0 && ii != 5) {
2352 auto oldLevel = gErrorIgnoreLevel;
2353 gErrorIgnoreLevel = kError;
2354 mEffResult[0][
j / 2][
j % 2][
i]->Divide(mEff[l][
j / 2][
j % 2][
i], mEff[5][
j / 2][
j % 2][
i],
"cl=0.683 b(1,1) mode");
2355 gErrorIgnoreLevel = oldLevel;
2356 mEff[3][
j / 2][
j % 2][
i]->Reset();
2357 mEff[3][
j / 2][
j % 2][
i]->Add(mEff[0][
j / 2][
j % 2][
i]);
2358 mEff[3][
j / 2][
j % 2][
i]->Add(mEff[1][
j / 2][
j % 2][
i]);
2359 mEff[3][
j / 2][
j % 2][
i]->Add(mEff[2][
j / 2][
j % 2][
i]);
2360 mEff[4][
j / 2][
j % 2][
i]->Reset();
2361 mEff[4][
j / 2][
j % 2][
i]->Add(mEff[0][
j / 2][
j % 2][
i]);
2362 mEff[4][
j / 2][
j % 2][
i]->Add(mEff[1][
j / 2][
j % 2][
i]);
2365 auto oldLevel = gErrorIgnoreLevel;
2366 gErrorIgnoreLevel = kError;
2367 mEffResult[l][
j / 2][
j % 2][
i]->Divide(mEff[l][
j / 2][
j % 2][
i], mEff[l == 1 ? 4 : 3][
j / 2][
j % 2][
i],
"cl=0.683 b(1,1) mode");
2368 gErrorIgnoreLevel = oldLevel;
2372 TGraphAsymmErrors* e = mEffResult[l][
j / 2][
j % 2][
i];
2374 if (!mConfig.inputHistogramsOnly && k == 0) {
2376 mEff[l][
j / 2][
j % 2][
i]->Write();
2379 mEff[3][
j / 2][
j % 2][
i]->Write();
2380 mEff[4][
j / 2][
j % 2][
i]->Write();
2383 }
else if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
2386 e->SetTitle(EFFICIENCY_TITLES[
j]);
2387 e->GetYaxis()->SetTitle(
"(Efficiency)");
2388 e->GetXaxis()->SetTitle(XAXIS_TITLES[
i]);
2391 e->SetLineStyle(CONFIG_DASHED_MARKERS ? k + 1 : 1);
2393 if (qcout && !mConfig.shipToQCAsCanvas) {
2396 if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) {
2399 e->SetMarkerColor(kBlack);
2400 e->SetLineColor(colorNums[(k < 3 ? (l * 3 + k) : (k * 3 + l)) % COLORCOUNT]);
2401 e->GetHistogram()->GetYaxis()->SetRangeUser(-0.02, 1.02);
2402 e->Draw(k || l ?
"same P" :
"AP");
2405 mLEff[ii]->AddEntry(e, Form(
"%s%s", fname, EFF_NAMES[l]),
"l");
2408 if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) {
2412 ChangePadTitleSize(mPEff[ii][
j], 0.056);
2415 if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) {
2422 qcout->Add(mCEff[ii]);
2424 if (!mConfig.enableLocalOutput) {
2427 doPerfFigure(0.2, 0.295, 0.025);
2428 mCEff[ii]->Print(Form(
"%s/eff_vs_%s.pdf", mConfig.plotsDir.c_str(), VSPARAMETER_NAMES[ii]));
2429 if (mConfig.writeFileExt !=
"") {
2430 mCEff[ii]->Print(Form(
"%s/eff_vs_%s.%s", mConfig.plotsDir.c_str(), VSPARAMETER_NAMES[ii], mConfig.writeFileExt.c_str()));
2435 if (mQATasks & (taskTrackingRes | taskTrackingResPull)) {
2437 TH1D *resIntegral[5] = {}, *pullIntegral[5] = {};
2438 TCanvas* cfit =
nullptr;
2439 std::unique_ptr<TF1> customGaus = std::make_unique<TF1>(
"G",
"[0]*exp(-(x-[1])*(x-[1])/(2.*[2]*[2]))");
2440 for (int32_t p = 0;
p < 2;
p++) {
2441 if ((p == 0 && (mQATasks & taskTrackingRes) == 0) || (p == 1 && (mQATasks & taskTrackingResPull) == 0)) {
2444 for (int32_t ii = 0; ii < 5 + flagShowVsPtLog; ii++) {
2445 TCanvas* can =
p ? mCPull[ii] : mCRes[ii];
2446 TLegend* leg =
p ? mLPull[ii] : mLRes[ii];
2447 int32_t
i = ii == 5 ? 4 : ii;
2448 for (int32_t
j = 0;
j < 5;
j++) {
2449 TH2F*
src =
p ? mPull2[
j][
i] : mRes2[
j][
i];
2450 TH1F**
dst =
p ? mPull[
j][
i] : mRes[
j][
i];
2451 TH1D*& dstIntegral =
p ? pullIntegral[
j] : resIntegral[
j];
2452 TPad* pad =
p ? mPPull[ii][
j] : mPRes[ii][
j];
2454 if (!mConfig.inputHistogramsOnly && ii != 5) {
2455 if (cfit ==
nullptr) {
2456 cfit = createGarbageCollected<TCanvas>();
2460 TAxis* axis =
src->GetYaxis();
2461 int32_t nBins = axis->GetNbins();
2463 for (int32_t bin = 1; bin <= nBins; bin++) {
2464 int32_t bin0 = std::max(bin - integ, 0);
2465 int32_t bin1 = std::min(bin + integ, nBins);
2466 std::unique_ptr<TH1D> proj{
src->ProjectionX(
"proj", bin0, bin1)};
2467 proj->ClearUnderflowAndOverflow();
2468 if (proj->GetEntries()) {
2470 while (proj->GetMaximum() < 50 && rebin <
sizeof(RES_AXIS_BINS) /
sizeof(RES_AXIS_BINS[0])) {
2471 proj->Rebin(RES_AXIS_BINS[rebin - 1] / RES_AXIS_BINS[rebin]);
2475 if (proj->GetEntries() < 20 || proj->GetRMS() < 0.00001) {
2476 dst[0]->SetBinContent(bin, proj->GetRMS());
2477 dst[0]->SetBinError(bin, std::sqrt(proj->GetRMS()));
2478 dst[1]->SetBinContent(bin, proj->GetMean());
2479 dst[1]->SetBinError(bin, std::sqrt(proj->GetRMS()));
2481 proj->GetXaxis()->SetRange(0, 0);
2482 proj->GetXaxis()->SetRangeUser(std::max(proj->GetXaxis()->GetXmin(), proj->GetMean() - 3. * proj->GetRMS()), std::min(proj->GetXaxis()->GetXmax(), proj->GetMean() + 3. * proj->GetRMS()));
2483 bool forceLogLike = proj->GetMaximum() < 20;
2484 for (int32_t k = forceLogLike ? 2 : 0; k < 3; k++) {
2485 proj->Fit(
"gaus", forceLogLike || k == 2 ?
"sQl" : k ?
"sQww" :
"sQ");
2486 TF1* fitFunc = proj->GetFunction(
"gaus");
2488 if (k && !forceLogLike) {
2489 customGaus->SetParameters(fitFunc->GetParameter(0), fitFunc->GetParameter(1), fitFunc->GetParameter(2));
2490 proj->Fit(customGaus.get(),
"sQ");
2491 fitFunc = customGaus.get();
2494 const float sigma = fabs(fitFunc->GetParameter(2));
2495 dst[0]->SetBinContent(bin, sigma);
2496 dst[1]->SetBinContent(bin, fitFunc->GetParameter(1));
2497 dst[0]->SetBinError(bin, fitFunc->GetParError(2));
2498 dst[1]->SetBinError(bin, fitFunc->GetParError(1));
2500 const bool fail1 = sigma <= 0.f;
2501 const bool fail2 = fabs(proj->GetMean() -
dst[1]->GetBinContent(bin)) > std::min<float>(p ? PULL_AXIS : mConfig.nativeFitResolutions ? RES_AXES_NATIVE[
j] : RES_AXES[
j], 3.f * proj->GetRMS());
2502 const bool fail3 =
dst[0]->GetBinContent(bin) > 3.f * proj->GetRMS() ||
dst[0]->GetBinError(bin) > 1 ||
dst[1]->GetBinError(bin) > 1;
2503 const bool fail4 = fitFunc->GetParameter(0) < proj->GetMaximum() / 5.;
2504 const bool fail = fail1 || fail2 || fail3 || fail4;
2509 }
else if (k >= 2) {
2510 dst[0]->SetBinContent(bin, proj->GetRMS());
2511 dst[0]->SetBinError(bin, std::sqrt(proj->GetRMS()));
2512 dst[1]->SetBinContent(bin, proj->GetMean());
2513 dst[1]->SetBinError(bin, std::sqrt(proj->GetRMS()));
2518 dst[0]->SetBinContent(bin, 0.f);
2519 dst[0]->SetBinError(bin, 0.f);
2520 dst[1]->SetBinContent(bin, 0.f);
2521 dst[1]->SetBinError(bin, 0.f);
2525 dstIntegral =
src->ProjectionX(mConfig.nativeFitResolutions ? PARAMETER_NAMES_NATIVE[
j] : PARAMETER_NAMES[
j], 0, nBins + 1);
2527 while (dstIntegral->GetMaximum() < 50 && rebin <
sizeof(RES_AXIS_BINS) /
sizeof(RES_AXIS_BINS[0])) {
2528 dstIntegral->Rebin(RES_AXIS_BINS[rebin - 1] / RES_AXIS_BINS[rebin]);
2534 if (mConfig.inputHistogramsOnly) {
2535 dstIntegral = createGarbageCollected<TH1D>();
2537 dstIntegral->SetName(Form(p ?
"IntPull%s" :
"IntRes%s", VSPARAMETER_NAMES[
j]));
2538 dstIntegral->SetTitle(Form(p ?
"%s Pull" :
"%s Resolution",
p || mConfig.nativeFitResolutions ? PARAMETER_NAMES_NATIVE[
j] : PARAMETER_NAMES[
j]));
2540 if (mConfig.enableLocalOutput || mConfig.shipToQCAsCanvas) {
2543 int32_t numColor = 0;
2544 float tmpMax = -1000.;
2545 float tmpMin = 1000.;
2547 for (int32_t l = 0; l < 2; l++) {
2548 for (int32_t k = 0; k < ConfigNumInputs; k++) {
2550 if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
2553 if (nNewInput && k == 0 && ii != 5) {
2555 e->Scale(mConfig.nativeFitResolutions ? SCALE_NATIVE[
j] : SCALE[
j]);
2559 e->GetXaxis()->SetRangeUser(0.2, PT_MAX);
2560 }
else if (LOG_PT_MIN > 0 && ii == 5) {
2561 e->GetXaxis()->SetRangeUser(LOG_PT_MIN, PT_MAX);
2562 }
else if (ii == 5) {
2563 e->GetXaxis()->SetRange(1, 0);
2565 e->SetMinimum(-1111);
2566 e->SetMaximum(-1111);
2568 if (e->GetMaximum() > tmpMax) {
2569 tmpMax = e->GetMaximum();
2571 if (e->GetMinimum() < tmpMin) {
2572 tmpMin = e->GetMinimum();
2578 tmpSpan = tmpMax - tmpMin;
2579 tmpMax += tmpSpan * .02;
2580 tmpMin -= tmpSpan * .02;
2581 if (
j == 2 &&
i < 3) {
2582 tmpMax += tmpSpan * 0.13 * ConfigNumInputs;
2585 for (int32_t k = 0; k < ConfigNumInputs; k++) {
2586 for (int32_t l = 0; l < 2; l++) {
2588 if (!mConfig.inputHistogramsOnly && k == 0) {
2589 e->SetTitle(Form(p ?
"%s Pull" :
"%s Resolution",
p || mConfig.nativeFitResolutions ? PARAMETER_NAMES_NATIVE[
j] : PARAMETER_NAMES[
j]));
2590 e->SetStats(kFALSE);
2593 mRes2[
j][
i]->SetOption(
"colz");
2594 mRes2[
j][
i]->Write();
2598 }
else if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
2601 e->SetMaximum(tmpMax);
2602 e->SetMinimum(tmpMin);
2604 e->SetLineStyle(CONFIG_DASHED_MARKERS ? k + 1 : 1);
2606 e->GetYaxis()->SetTitle(p ? AXIS_TITLES_PULL[
j] : mConfig.nativeFitResolutions ? AXIS_TITLES_NATIVE[
j] : AXIS_TITLES[
j]);
2607 e->GetXaxis()->SetTitle(XAXIS_TITLES[
i]);
2608 if (LOG_PT_MIN > 0 && ii == 5) {
2609 e->GetXaxis()->SetRangeUser(LOG_PT_MIN, PT_MAX);
2613 e->GetYaxis()->SetTitleOffset(1.5);
2615 e->GetYaxis()->SetTitleOffset(1.4);
2617 if (qcout && !mConfig.shipToQCAsCanvas) {
2620 if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) {
2624 e->SetMarkerColor(kBlack);
2625 e->SetLineColor(colorNums[numColor++ % COLORCOUNT]);
2626 e->Draw(k || l ?
"same" :
"");
2629 leg->AddEntry(e, Form(
"%s%s", fname, l ?
"Mean" : (
p ?
"Pull" :
"Resolution")),
"l");
2633 if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) {
2642 ChangePadTitleSize(pad, 0.056);
2645 if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) {
2654 if (!mConfig.enableLocalOutput) {
2657 doPerfFigure(0.2, 0.295, 0.025);
2658 can->Print(Form(p ?
"%s/pull_vs_%s.pdf" :
"%s/res_vs_%s.pdf", mConfig.plotsDir.c_str(), VSPARAMETER_NAMES[ii]));
2659 if (mConfig.writeFileExt !=
"") {
2660 can->Print(Form(p ?
"%s/pull_vs_%s.%s" :
"%s/res_vs_%s.%s", mConfig.plotsDir.c_str(), VSPARAMETER_NAMES[ii], mConfig.writeFileExt.c_str()));
2666 for (int32_t p = 0;
p < 2;
p++) {
2667 if ((p == 0 && (mQATasks & taskTrackingRes) == 0) || (p == 1 && (mQATasks & taskTrackingResPull) == 0)) {
2670 TCanvas* can =
p ? mCPull[6] : mCRes[6];
2671 for (int32_t
i = 0;
i < 5;
i++) {
2672 TPad* pad =
p ? mPPull[6][
i] : mPRes[6][
i];
2673 TH1D* hist =
p ? pullIntegral[
i] : resIntegral[
i];
2674 int32_t numColor = 0;
2675 if (mConfig.enableLocalOutput || mConfig.shipToQCAsCanvas) {
2678 if (!mConfig.inputHistogramsOnly && mcAvail) {
2680 if (e && e->GetEntries()) {
2681 e->Fit(
"gaus",
"sQ");
2686 for (int32_t k = 0; k < ConfigNumInputs; k++) {
2688 if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
2691 e->SetMaximum(-1111);
2692 if (e->GetMaximum() > tmpMax) {
2693 tmpMax = e->GetMaximum();
2697 for (int32_t k = 0; k < ConfigNumInputs; k++) {
2699 if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
2702 e->SetMaximum(tmpMax * 1.02);
2703 e->SetMinimum(tmpMax * -0.02);
2704 if (tout && !mConfig.inputHistogramsOnly && k == 0) {
2707 if (qcout && !mConfig.shipToQCAsCanvas) {
2710 if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) {
2714 e->SetLineColor(colorNums[numColor++ % COLORCOUNT]);
2715 e->Draw(k == 0 ?
"" :
"same");
2717 if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) {
2725 if (!mConfig.enableLocalOutput) {
2729 can->Print(Form(p ?
"%s/pull_integral.pdf" :
"%s/res_integral.pdf", mConfig.plotsDir.c_str()));
2730 if (mConfig.writeFileExt !=
"") {
2731 can->Print(Form(p ?
"%s/pull_integral.%s" :
"%s/res_integral.%s", mConfig.plotsDir.c_str(), mConfig.writeFileExt.c_str()));
2736 uint64_t attachClusterCounts[N_CLS_HIST];
2737 if (mQATasks & taskClusterAttach) {
2739 if (mConfig.inputHistogramsOnly == 0) {
2740 for (int32_t
i = N_CLS_HIST;
i < N_CLS_TYPE * N_CLS_HIST - 1;
i++) {
2741 mClusters[
i]->Sumw2(
true);
2743 double totalVal = 0;
2744 if (!CLUST_HIST_INT_SUM) {
2745 for (int32_t
j = 0;
j < mClusters[N_CLS_HIST - 1]->GetXaxis()->GetNbins() + 2;
j++) {
2746 totalVal += mClusters[N_CLS_HIST - 1]->GetBinContent(
j);
2749 if (totalVal == 0.) {
2752 for (int32_t
i = 0;
i < N_CLS_HIST;
i++) {
2754 for (int32_t
j = 0;
j < mClusters[
i]->GetXaxis()->GetNbins() + 2;
j++) {
2755 val += mClusters[
i]->GetBinContent(
j);
2756 mClusters[2 * N_CLS_HIST - 1 +
i]->SetBinContent(
j,
val / totalVal);
2758 attachClusterCounts[
i] =
val;
2761 if (!CLUST_HIST_INT_SUM) {
2762 for (int32_t
i = 0;
i < N_CLS_HIST;
i++) {
2763 mClusters[2 * N_CLS_HIST - 1 +
i]->SetMaximum(1.02);
2764 mClusters[2 * N_CLS_HIST - 1 +
i]->SetMinimum(-0.02);
2768 for (int32_t
i = 0;
i < N_CLS_HIST - 1;
i++) {
2769 auto oldLevel = gErrorIgnoreLevel;
2770 gErrorIgnoreLevel = kError;
2771 mClusters[N_CLS_HIST +
i]->Divide(mClusters[
i], mClusters[N_CLS_HIST - 1], 1, 1,
"B");
2772 gErrorIgnoreLevel = oldLevel;
2773 mClusters[N_CLS_HIST +
i]->SetMinimum(-0.02);
2774 mClusters[N_CLS_HIST +
i]->SetMaximum(1.02);
2778 float tmpMax[2] = {0, 0}, tmpMin[2] = {0, 0};
2779 for (int32_t l = 0; l <= CLUST_HIST_INT_SUM; l++) {
2780 for (int32_t k = 0; k < ConfigNumInputs; k++) {
2781 TH1* e = mClusters[l ? (N_CLS_TYPE * N_CLS_HIST - 2) : (N_CLS_HIST - 1)];
2782 if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
2785 e->SetMinimum(-1111);
2786 e->SetMaximum(-1111);
2788 e->GetXaxis()->SetRange(2, AXIS_BINS[4]);
2790 if (e->GetMaximum() > tmpMax[l]) {
2791 tmpMax[l] = e->GetMaximum();
2793 if (e->GetMinimum() < tmpMin[l]) {
2794 tmpMin[l] = e->GetMinimum();
2797 for (int32_t k = 0; k < ConfigNumInputs; k++) {
2798 for (int32_t
i = 0;
i < N_CLS_HIST;
i++) {
2799 TH1* e = mClusters[l ? (2 * N_CLS_HIST - 1 +
i) :
i];
2800 if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
2803 e->SetMaximum(tmpMax[l] * 1.02);
2804 e->SetMinimum(tmpMax[l] * -0.02);
2809 for (int32_t
i = 0;
i < N_CLS_TYPE;
i++) {
2810 if (mConfig.enableLocalOutput || mConfig.shipToQCAsCanvas) {
2812 mPClust[
i]->SetLogx();
2814 int32_t
begin =
i == 2 ? (2 * N_CLS_HIST - 1) :
i == 1 ? N_CLS_HIST : 0;
2815 int32_t
end =
i == 2 ? (3 * N_CLS_HIST - 1) :
i == 1 ? (2 * N_CLS_HIST - 1) : N_CLS_HIST;
2816 int32_t numColor = 0;
2817 for (int32_t k = 0; k < ConfigNumInputs; k++) {
2819 TH1* e = mClusters[
j];
2820 if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
2824 e->SetTitle(mConfig.plotsNoTitle ?
"" : CLUSTER_TITLES[
i]);
2825 e->GetYaxis()->SetTitle(
i == 0 ?
"Number of TPC clusters" :
i == 1 ?
"Fraction of TPC clusters" : CLUST_HIST_INT_SUM ?
"Total TPC clusters (integrated)" :
"Fraction of TPC clusters (integrated)");
2826 e->GetXaxis()->SetTitle(
"#it{p}_{Tmc} (GeV/#it{c})");
2827 e->GetXaxis()->SetTitleOffset(1.1);
2828 e->GetXaxis()->SetLabelOffset(-0.005);
2829 if (tout && !mConfig.inputHistogramsOnly && k == 0) {
2832 e->SetStats(kFALSE);
2834 e->SetLineStyle(CONFIG_DASHED_MARKERS ?
j + 1 : 1);
2836 e->GetXaxis()->SetRange(2, AXIS_BINS[4]);
2838 if (qcout && !mConfig.shipToQCAsCanvas) {
2841 if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) {
2845 e->SetMarkerColor(kBlack);
2846 e->SetLineColor(colorNums[numColor++ % COLORCOUNT]);
2847 e->Draw(
j ==
end - 1 && k == 0 ?
"" :
"same");
2849 mLClust[
i]->AddEntry(e, Form(
"%s%s", fname, CLUSTER_NAMES[
j - begin]),
"l");
2852 if (ConfigNumInputs == 1) {
2853 TH1* e =
reinterpret_cast<TH1F*
>(mClusters[
begin + CL_att_adj]->Clone());
2854 e->Add(mClusters[begin + CL_prot], -1);
2855 if (qcout && !mConfig.shipToQCAsCanvas) {
2858 if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) {
2862 e->SetLineColor(colorNums[numColor++ % COLORCOUNT]);
2864 mLClust[
i]->AddEntry(e,
"Removed (Strategy A)",
"l");
2866 if (!mConfig.enableLocalOutput && !mConfig.shipToQCAsCanvas) {
2873 qcout->Add(mCClust[
i]);
2875 if (!mConfig.enableLocalOutput) {
2878 doPerfFigure(
i == 0 ? 0.37 : (
i == 1 ? 0.34 : 0.6), 0.295, 0.030);
2880 mCClust[
i]->Print(Form(
i == 2 ?
"%s/clusters_integral.pdf" :
i == 1 ?
"%s/clusters_relative.pdf" :
"%s/clusters.pdf", mConfig.plotsDir.c_str()));
2881 if (mConfig.writeFileExt !=
"") {
2882 mCClust[
i]->Print(Form(
i == 2 ?
"%s/clusters_integral.%s" :
i == 1 ?
"%s/clusters_relative.%s" :
"%s/clusters.%s", mConfig.plotsDir.c_str(), mConfig.writeFileExt.c_str()));
2886 for (int32_t
i = 0;
i < 4;
i++) {
2887 auto* e = mPadRow[
i];
2888 if (tout && !mConfig.inputHistogramsOnly) {
2892 e->SetOption(
"colz");
2893 std::string title =
"First Track Pad Row (p_{T} > 1GeV, N_{Cl} #geq " +
std::to_string(PADROW_CHECK_MINCLS);
2895 title +=
", row_{trk} > row_{MC} + 3, row_{MC} < 10";
2898 title +=
", #Phi_{Cl} < 0.15";
2902 e->SetTitle(mConfig.plotsNoTitle ?
"" : title.c_str());
2903 e->GetXaxis()->SetTitle(
i == 3 ?
"Local Occupancy" : (
i ?
"#Phi_{Cl} (sector)" :
"First MC Pad Row"));
2904 e->GetYaxis()->SetTitle(
"First Pad Row");
2907 static const constexpr char* PADROW_NAMES[4] = {
"MC",
"Phi",
"Phi1",
"Occ"};
2908 mCPadRow[
i]->Print(Form(
"%s/padRow%s.pdf", mConfig.plotsDir.c_str(), PADROW_NAMES[
i]));
2909 if (mConfig.writeFileExt !=
"") {
2910 mCPadRow[
i]->Print(Form(
"%s/padRow%s.%s", mConfig.plotsDir.c_str(), PADROW_NAMES[
i], mConfig.writeFileExt.c_str()));
2916 if ((mQATasks & taskClusterCounts) && !mHaveExternalHists && !mConfig.clusterRejectionHistograms && !mConfig.inputHistogramsOnly) {
2917 DoClusterCounts(attachClusterCounts);
2919 if ((qcout || tout) && (mQATasks & taskClusterCounts) && mConfig.clusterRejectionHistograms) {
2920 for (uint32_t
i = 0;
i < mHistClusterCount.size();
i++) {
2922 mHistClusterCount[
i]->Write();
2925 qcout->Add(mHistClusterCount[
i]);
2930 if (mQATasks & taskTrackStatistics) {
2934 for (int32_t k = 0; k < ConfigNumInputs; k++) {
2936 if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
2939 e->SetMaximum(-1111);
2940 if (e->GetMaximum() > tmpMax) {
2941 tmpMax = e->GetMaximum();
2945 mPTracks[0]->SetLogx();
2946 for (int32_t k = 0; k < ConfigNumInputs; k++) {
2948 if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
2951 if (tout && !mConfig.inputHistogramsOnly && k == 0) {
2954 e->SetMaximum(tmpMax * 1.02);
2955 e->SetMinimum(tmpMax * -0.02);
2956 e->SetStats(kFALSE);
2958 e->SetTitle(mConfig.plotsNoTitle ?
"" :
"Number of Tracks vs #it{p}_{T}");
2959 e->GetYaxis()->SetTitle(
"Number of Tracks");
2960 e->GetXaxis()->SetTitle(
"#it{p}_{T} (GeV/#it{c})");
2961 e->GetXaxis()->SetTitleOffset(1.2);
2965 e->SetMarkerColor(kBlack);
2966 e->SetLineColor(colorNums[k % COLORCOUNT]);
2967 e->Draw(k == 0 ?
"" :
"same");
2968 GetName(fname, k, mConfig.inputHistogramsOnly);
2969 mLTracks[0]->AddEntry(e, Form(mConfig.inputHistogramsOnly ?
"%s" :
"%sTrack #it{p}_{T}", fname),
"l");
2971 mLTracks[0]->Draw();
2972 doPerfFigure(0.63, 0.7, 0.030);
2974 mCTracks[0]->Print(Form(
"%s/tracks%s.pdf", mConfig.plotsDir.c_str(),
"pt"));
2975 if (mConfig.writeFileExt !=
"") {
2976 mCTracks[0]->Print(Form(
"%s/tracks%s.%s", mConfig.plotsDir.c_str(),
"pt", mConfig.writeFileExt.c_str()));
2979 for (int32_t
i = 0;
i < 2;
i++) {
2980 mPTracks[1 +
i]->cd();
2982 TH2F* e = mTrackdEdx[
i];
2983 if (tout && !mConfig.inputHistogramsOnly) {
2987 e->SetTitle(mConfig.plotsNoTitle ?
"" : (
i ?
"Track dE/dx (Max)" :
"Track dE/dx (Tot)"));
2988 e->GetYaxis()->SetTitle(
i ?
"dE/dx (max)" :
"dE/dx (tot)");
2989 e->GetXaxis()->SetTitle(
"log(#it{p})");
2990 e->GetXaxis()->SetTitleOffset(1.2);
2994 e->SetOption(
"colz");
2997 mCTracks[1 +
i]->cd();
2998 mCTracks[1 +
i]->Print(Form(
"%s/tracks%s.pdf", mConfig.plotsDir.c_str(),
i ?
"dedx_max" :
"dedx_tot"));
2999 if (mConfig.writeFileExt !=
"") {
3000 mCTracks[1 +
i]->Print(Form(
"%s/tracks%s.%s", mConfig.plotsDir.c_str(),
i ?
"dedx_max" :
"dedx_tot", mConfig.writeFileExt.c_str()));
3004 for (int32_t k = 0; k < ConfigNumInputs; k++) {
3006 if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
3009 e->SetMaximum(-1111);
3010 if (e->GetMaximum() > tmpMax) {
3011 tmpMax = e->GetMaximum();
3015 for (int32_t k = 0; k < ConfigNumInputs; k++) {
3017 if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
3020 if (tout && !mConfig.inputHistogramsOnly && k == 0) {
3023 e->SetMaximum(tmpMax * 1.02);
3024 e->SetMinimum(tmpMax * -0.02);
3025 e->SetStats(kFALSE);
3027 e->SetTitle(mConfig.plotsNoTitle ?
"" : (
i ?
"Track t_{0} resolution" :
"Track t_{0} distribution"));
3028 e->GetYaxis()->SetTitle(
"a.u.");
3029 e->GetXaxis()->SetTitle(
i ?
"t_{0} - t_{0, mc}" :
"t_{0}");
3033 e->SetMarkerColor(kBlack);
3034 e->SetLineColor(colorNums[k % COLORCOUNT]);
3035 e->Draw(k == 0 ?
"" :
"same");
3036 GetName(fname, k, mConfig.inputHistogramsOnly);
3037 mLT0[
i]->AddEntry(e, Form(mConfig.inputHistogramsOnly ?
"%s (%s)" :
"%sTrack t_{0} %s", fname,
i ?
"" :
"resolution"),
"l");
3040 doPerfFigure(0.63, 0.7, 0.030);
3042 mCT0[
i]->Print(Form(
"%s/t0%s.pdf", mConfig.plotsDir.c_str(),
i ?
"_res" :
""));
3043 if (mConfig.writeFileExt !=
"") {
3044 mCT0[
i]->Print(Form(
"%s/t0%s.%s", mConfig.plotsDir.c_str(),
i ?
"_res" :
"", mConfig.writeFileExt.c_str()));
3048 for (int32_t k = 0; k < ConfigNumInputs; k++) {
3050 if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
3053 e->SetMaximum(-1111);
3054 if (e->GetMaximum() > tmpMax) {
3055 tmpMax = e->GetMaximum();
3059 for (int32_t k = 0; k < ConfigNumInputs; k++) {
3061 if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
3064 if (tout && !mConfig.inputHistogramsOnly && k == 0) {
3067 e->SetMaximum(tmpMax * 1.02);
3068 e->SetMinimum(tmpMax * -0.02);
3069 e->SetStats(kFALSE);
3071 e->SetTitle(mConfig.plotsNoTitle ?
"" : (
i ?
"Number of Rows with attached Cluster" :
"Number of Clusters"));
3072 e->GetYaxis()->SetTitle(
"a.u.");
3073 e->GetXaxis()->SetTitle(
i ?
"N_{Rows with Clusters}" :
"N_{Clusters}");
3077 e->SetMarkerColor(kBlack);
3078 e->SetLineColor(colorNums[k % COLORCOUNT]);
3079 e->Draw(k == 0 ?
"" :
"same");
3080 GetName(fname, k, mConfig.inputHistogramsOnly);
3081 mLNCl[
i]->AddEntry(e, Form(mConfig.inputHistogramsOnly ?
"%s" : (
i ?
"%sN_{Clusters}" :
"%sN_{Rows with Clusters}"), fname),
"l");
3084 doPerfFigure(0.6, 0.7, 0.030);
3086 mCNCl[
i]->Print(Form(
"%s/nClusters%s.pdf", mConfig.plotsDir.c_str(),
i ?
"_corrected" :
""));
3087 if (mConfig.writeFileExt !=
"") {
3088 mCNCl[
i]->Print(Form(
"%s/nClusters%s.%s", mConfig.plotsDir.c_str(),
i ?
"_corrected" :
"", mConfig.writeFileExt.c_str()));
3093 mClXY->SetOption(
"colz");
3096 mCClXY->Print(Form(
"%s/clustersXY.pdf", mConfig.plotsDir.c_str()));
3097 if (mConfig.writeFileExt !=
"") {
3098 mCClXY->Print(Form(
"%s/clustersXY.%s", mConfig.plotsDir.c_str(), mConfig.writeFileExt.c_str()));
3102 if (mQATasks & taskClusterRejection) {
3103 mClRej[2]->Divide(mClRej[1], mClRej[0]);
3105 for (int32_t
i = 0;
i < 3;
i++) {
3106 if (tout && !mConfig.inputHistogramsOnly) {
3110 mClRej[
i]->SetTitle(mConfig.plotsNoTitle ?
"" : REJECTED_NAMES[
i]);
3111 mClRej[
i]->SetOption(
"colz");
3114 mCClRej[
i]->Print(Form(
"%s/clustersRej%d%s.pdf", mConfig.plotsDir.c_str(),
i, REJECTED_NAMES[
i]));
3115 if (mConfig.writeFileExt !=
"") {
3116 mCClRej[
i]->Print(Form(
"%s/clustersRej%d%s.%s", mConfig.plotsDir.c_str(),
i, REJECTED_NAMES[
i], mConfig.writeFileExt.c_str()));
3121 for (int32_t k = 0; k < ConfigNumInputs; k++) {
3122 auto* tmp = mClRej[0];
3123 if (GetHist(tmp, tin, k, nNewInput) ==
nullptr) {
3126 TH1D* proj1 = tmp->ProjectionY(Form(
"clrejptmp1%d", k));
3127 proj1->SetDirectory(
nullptr);
3129 if (GetHist(tmp, tin, k, nNewInput) ==
nullptr) {
3132 TH1D* proj2 = tmp->ProjectionY(Form(
"clrejptmp2%d", k));
3133 proj2->SetDirectory(
nullptr);
3136 if (GetHist(e, tin, k, nNewInput) ==
nullptr) {
3139 e->Divide(proj2, proj1);
3140 if (tout && !mConfig.inputHistogramsOnly && k == 0) {
3145 e->SetMinimum(-0.02);
3146 e->SetMaximum(0.22);
3147 e->SetTitle(mConfig.plotsNoTitle ?
"" :
"Rejected Clusters");
3148 e->GetXaxis()->SetTitle(
"Pad Row");
3149 e->GetYaxis()->SetTitle(
"Rejected Clusters (fraction)");
3150 e->Draw(k == 0 ?
"" :
"same");
3152 mPClRejP->Print(Form(
"%s/clustersRejProjected.pdf", mConfig.plotsDir.c_str()));
3153 if (mConfig.writeFileExt !=
"") {
3154 mPClRejP->Print(Form(
"%s/clustersRejProjected.%s", mConfig.plotsDir.c_str(), mConfig.writeFileExt.c_str()));
3158 if (tout && !mConfig.inputHistogramsOnly && mConfig.writeMCLabels) {
3159 gInterpreter->GenerateDictionary(
"vector<vector<int32_t>>",
"");
3160 tout->WriteObject(&mcEffBuffer,
"mcEffBuffer");
3161 tout->WriteObject(&mcLabelBuffer,
"mcLabelBuffer");
3162 remove(
"AutoDict_vector_vector_int__.cxx");
3163 remove(
"AutoDict_vector_vector_int___cxx_ACLiC_dict_rdict.pcm");
3164 remove(
"AutoDict_vector_vector_int___cxx.d");
3165 remove(
"AutoDict_vector_vector_int___cxx.so");
3171 for (uint32_t
i = 0;
i < mConfig.compareInputs.size();
i++) {
3175 clearGarbagageCollector();
3177 GPUInfo(
"GPU TPC QA histograms have been written to pdf%s%s files", mConfig.writeFileExt ==
"" ?
"" :
" and ", mConfig.writeFileExt.c_str());
3178 gErrorIgnoreLevel = oldRootIgnoreLevel;
3182void GPUQA::PrintClusterCount(int32_t
mode, int32_t&
num,
const char*
name, uint64_t
n, uint64_t normalization)
3186 }
else if (
mode == 1) {
3188 snprintf(name2, 128,
"clusterCount%d_",
num);
3189 char*
ptr = name2 + strlen(name2);
3190 for (uint32_t
i = 0;
i < strlen(
name);
i++) {
3196 createHist(mHistClusterCount[
num], name2,
name, 1000, 0, mConfig.histMaxNClusters, 1000, 0, 100);
3197 }
else if (
mode == 0) {
3198 if (normalization && mConfig.enableLocalOutput) {
3199 for (uint32_t
i = 0;
i < 1 + (mTextDump !=
nullptr);
i++) {
3200 fprintf(
i ? mTextDump : stdout,
"\t%40s: %'12" PRIu64
" (%6.2f%%)\n",
name,
n, 100.f *
n / normalization);
3203 if (mConfig.clusterRejectionHistograms) {
3204 float ratio = 100.f *
n / std::max<uint64_t>(normalization, 1);
3205 mHistClusterCount[
num]->Fill(normalization, ratio, 1);
3211int32_t GPUQA::DoClusterCounts(uint64_t* attachClusterCounts, int32_t
mode)
3213 if (mConfig.enableLocalOutput && !mConfig.inputHistogramsOnly && mConfig.plotsDir !=
"") {
3214 mTextDump = fopen((mConfig.plotsDir +
"/clusterCounts.txt").c_str(),
"w+");
3217 if (mcPresent() && (mQATasks & taskClusterAttach) && attachClusterCounts) {
3218 for (int32_t
i = 0;
i < N_CLS_HIST;
i++) {
3219 PrintClusterCount(
mode,
num, CLUSTER_NAMES[
i], attachClusterCounts[
i], mClusterCounts.nTotal);
3221 PrintClusterCount(
mode,
num,
"Unattached", attachClusterCounts[N_CLS_HIST - 1] - attachClusterCounts[CL_att_adj], mClusterCounts.nTotal);
3222 PrintClusterCount(
mode,
num,
"Removed (Strategy A)", attachClusterCounts[CL_att_adj] - attachClusterCounts[CL_prot], mClusterCounts.nTotal);
3223 PrintClusterCount(
mode,
num,
"Unaccessible", mClusterCounts.nUnaccessible, mClusterCounts.nTotal);
3225 PrintClusterCount(
mode,
num,
"All Clusters", mClusterCounts.nTotal, mClusterCounts.nTotal);
3226 PrintClusterCount(
mode,
num,
"Used in Physics", mClusterCounts.nPhysics, mClusterCounts.nTotal);
3227 PrintClusterCount(
mode,
num,
"Protected", mClusterCounts.nProt, mClusterCounts.nTotal);
3228 PrintClusterCount(
mode,
num,
"Unattached", mClusterCounts.nUnattached, mClusterCounts.nTotal);
3229 PrintClusterCount(
mode,
num,
"Removed (Strategy A)", mClusterCounts.nTotal - mClusterCounts.nUnattached - mClusterCounts.nProt, mClusterCounts.nTotal);
3230 PrintClusterCount(
mode,
num,
"Removed (Strategy B)", mClusterCounts.nTotal - mClusterCounts.nProt, mClusterCounts.nTotal);
3233 PrintClusterCount(
mode,
num,
"Merged Loopers (Track Merging)", mClusterCounts.nMergedLooperConnected, mClusterCounts.nTotal);
3234 PrintClusterCount(
mode,
num,
"Merged Loopers (Afterburner)", mClusterCounts.nMergedLooperUnconnected, mClusterCounts.nTotal);
3235 PrintClusterCount(
mode,
num,
"Looping Legs (other)", mClusterCounts.nLoopers, mClusterCounts.nTotal);
3236 PrintClusterCount(
mode,
num,
"High Inclination Angle", mClusterCounts.nHighIncl, mClusterCounts.nTotal);
3237 PrintClusterCount(
mode,
num,
"Rejected", mClusterCounts.nRejected, mClusterCounts.nTotal);
3238 PrintClusterCount(
mode,
num,
"Tube (> 200 MeV)", mClusterCounts.nTube, mClusterCounts.nTotal);
3239 PrintClusterCount(
mode,
num,
"Tube (< 200 MeV)", mClusterCounts.nTube200, mClusterCounts.nTotal);
3240 PrintClusterCount(
mode,
num,
"Low Pt < 50 MeV", mClusterCounts.nLowPt, mClusterCounts.nTotal);
3241 PrintClusterCount(
mode,
num,
"Low Pt < 200 MeV", mClusterCounts.n200MeV, mClusterCounts.nTotal);
3243 if (mcPresent() && (mQATasks & taskClusterAttach)) {
3244 PrintClusterCount(
mode,
num,
"Tracks > 400 MeV", mClusterCounts.nAbove400, mClusterCounts.nTotal);
3245 PrintClusterCount(
mode,
num,
"Fake Removed (> 400 MeV)", mClusterCounts.nFakeRemove400, mClusterCounts.nAbove400);
3246 PrintClusterCount(
mode,
num,
"Full Fake Removed (> 400 MeV)", mClusterCounts.nFullFakeRemove400, mClusterCounts.nAbove400);
3247 PrintClusterCount(
mode,
num,
"Tracks < 40 MeV", mClusterCounts.nBelow40, mClusterCounts.nTotal);
3248 PrintClusterCount(
mode,
num,
"Fake Protect (< 40 MeV)", mClusterCounts.nFakeProtect40, mClusterCounts.nBelow40);
3250 if (mcPresent() && (mQATasks & taskTrackStatistics)) {
3251 PrintClusterCount(
mode,
num,
"Correctly Attached all-trk normalized", mClusterCounts.nCorrectlyAttachedNormalized, mClusterCounts.nTotal);
3252 PrintClusterCount(
mode,
num,
"Correctly Attached non-fake normalized", mClusterCounts.nCorrectlyAttachedNormalizedNonFake, mClusterCounts.nTotal);
3256 mTextDump =
nullptr;
3263 mTrackingScratchBuffer.resize((nBytes +
sizeof(mTrackingScratchBuffer[0]) - 1) /
sizeof(mTrackingScratchBuffer[0]));
3264 return mTrackingScratchBuffer.data();
std::vector< std::string > labels
A const (ready only) version of MCTruthContainer.
#define TRACK_EXPECTED_REFERENCE_X_DEFAULT
#define TRACK_EXPECTED_REFERENCE_X
Definition of the MCTrack class.
Definition of the Names Generator class.
Class for time synchronization of RawReader instances.
static const HBFUtils & Instance()
static constexpr int32_t NSECTORS
int32_t ReadO2MCData(const char *filename)
bool clusterRemovable(int32_t attach, bool prot) const
void * AllocateScratchBuffer(size_t nBytes)
void SetMCTrackRange(int32_t min, int32_t max)
mcLabelI_t GetMCTrackLabel(uint32_t trackId) const
int32_t DrawQAHistograms()
int32_t InitQA(int32_t tasks=0)
void DumpO2MCData(const char *filename) const
void RunQA(bool matchOnly=false)
static constexpr uint32_t NROWS
static constexpr uint32_t NSECTORS
static DigitizationContext * loadFromFile(std::string_view filename="")
GLfloat GLfloat GLfloat alpha
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLuint const GLchar * name
GLuint GLuint GLfloat weight
GLuint GLsizei const GLchar * label
GLdouble GLdouble GLdouble z
@ tasksDefaultPostprocess
o2::track::TrackParCov int int int float int nCl
const bool const int TrackITSInternal< NLayers > & track
constexpr int LHCBCPERTIMEBIN
Enum< T >::Iterator begin(Enum< T >)
struct o2::upgrades_utils::@469 tracks
structure to keep trigger-related info
std::string to_string(gsl::span< T, Size > span)
bool isValid(std::string alias)
int64_t differenceInBC(const InteractionRecord &other) const
bool mergedLooperConnected
bool mergedLooperUnconnected
std::tuple< std::vector< std::unique_ptr< TCanvas > >, std::vector< std::unique_ptr< TLegend > >, std::vector< std::unique_ptr< TPad > >, std::vector< std::unique_ptr< TLatex > >, std::vector< std::unique_ptr< TH1D > > > v
IR getFirstIRofTF(const IR &rec) const
get 1st IR of TF corresponding to the 1st sampled orbit (in MC)
unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
unsigned int nClustersTotal
unsigned int clusterOffset[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
const ClusterNative * clustersLinear
o2::InteractionRecord ir(0, 0)
o2::InteractionRecord ir0(3, 5)