diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index 957631e571b76..be9127a0c5070 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -509,9 +509,10 @@ AddOption(filterPID, int32_t, -1, "", 0, "Filter for Particle Type (0 Electron, AddOption(nativeFitResolutions, bool, false, "", 0, "Create resolution histograms in the native fit units (sin(phi), tan(lambda), Q/Pt)") AddOption(enableLocalOutput, bool, true, "", 0, "Enable normal output to local PDF files / console") AddOption(dumpToROOT, int32_t, 0, "", 0, "Dump all clusters and tracks to a ROOT file, 1 = combined TNTUple dump, 2 = also individual cluster / track branch dump") -AddOption(writeMCLabels, bool, false, "", 0, "Store mc labels to file for later matching") AddOption(writeRootFiles, bool, false, "", 0, "Create ROOT canvas files") +AddOption(writeMCLabels, bool, false, "", 0, "Store mc labels to file for later matching") AddOptionVec(matchMCLabels, std::string, "", 0, "Read labels from files and match them, only process tracks where labels differ") +AddOption(compareTrackStatus, uint32_t, 0, "", 0, "0 = disabled, 1 = write status file, 2 = read status file and compare with current tracks") AddOption(matchDisplayMinPt, float, 0, "", 0, "Minimum Pt of a matched track to be displayed") AddOption(noMC, bool, false, "", 0, "Force running QA without MC labels even if present") AddOption(shipToQC, bool, false, "", 0, "Do not write output files but ship histograms for QC") diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index b45f08ed00f50..2b7f23aba0557 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -902,7 +902,7 @@ GPUdii() void GPUTPCGMTrackParam::RefitTrack(GPUTPCGMMergedTrack& GPUrestrict() } // clang-format off - CADEBUG(if (DEBUG_SINGLE_TRACK >= 0 && iTrk != DEBUG_SINGLE_TRACK) { track.SetNClusters(0); track.SetOK(0); return; } ); + CADEBUG(if (DEBUG_SINGLE_TRACK != -1 && iTrk != ((DEBUG_SINGLE_TRACK == -2 && getenv("DEBUG_TRACK")) ? atoi(getenv("DEBUG_TRACK")) : DEBUG_SINGLE_TRACK)) { track.SetNClusters(0); track.SetOK(0); return; } ); // clang-format on int32_t nTrackHits = track.NClusters(); diff --git a/GPU/GPUTracking/qa/GPUQA.cxx b/GPU/GPUTracking/qa/GPUQA.cxx index 4f2c13635befa..cbeeb1076647f 100644 --- a/GPU/GPUTracking/qa/GPUQA.cxx +++ b/GPU/GPUTracking/qa/GPUQA.cxx @@ -73,6 +73,7 @@ #include #include #include +#include #include "utils/timer.h" @@ -1725,7 +1726,9 @@ void GPUQA::RunQA(bool matchOnly, const std::vector* tracksEx } } } - mNCl[1]->Fill(nClCorrected); + if (nClCorrected) { + mNCl[1]->Fill(nClCorrected); + } mT0[0]->Fill(track.GetParam().GetTOffset()); if (mTrackMCLabels.size() && !mTrackMCLabels[i].isFake() && !track.MergedLooper() && !track.CCE()) { const auto& info = GetMCTrack(mTrackMCLabels[i]); @@ -1897,6 +1900,56 @@ void GPUQA::RunQA(bool matchOnly, const std::vector* tracksEx } } } + + if (mConfig.compareTrackStatus) { +#ifdef GPUCA_DETERMINISTIC_MODE + if (!mTracking || !mTracking->GetProcessingSettings().deterministicGPUReconstruction) +#endif + { + throw std::runtime_error("Need deterministic processing to compare track status"); + } + std::vector status(mTracking->mIOPtrs.nMergedTracks); + for (uint32_t i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { + const auto& trk = mTracking->mIOPtrs.mergedTracks[i]; + status[i] = trk.OK() && trk.NClusters() && trk.GetParam().GetNDF() > 0 && (mConfig.noMC || (mTrackMCLabels[i].isValid() && !mTrackMCLabels[i].isFake())); + } + if (mConfig.compareTrackStatus == 1) { + std::ofstream("track.status", std::ios::binary).write((char*)status.data(), status.size() * sizeof(status[0])); + } else if (mConfig.compareTrackStatus == 2) { + std::ifstream f("track.status", std::ios::binary | std::ios::ate); + std::vector comp(f.tellg()); + f.seekg(0); + f.read((char*)comp.data(), comp.size()); + + if (comp.size() != status.size()) { + throw std::runtime_error("Number of tracks candidates in track fit in track.status and in current reconstruction differ"); + } + std::vector missing, missingComp; + for (uint32_t i = 0; i < status.size(); i++) { + if (status[i] && !comp[i]) { + missingComp.emplace_back(i); + } + if (comp[i] && !status[i]) { + missing.emplace_back(i); + } + } + auto printer = [](std::vector m, const char* name) { + if (m.size()) { + printf("Missing in %s reconstruction: (%zu)\n", name, m.size()); + for (uint32_t i = 0; i < m.size(); i++) { + if (i) { + printf(", "); + } + printf("%d", m[i]); + } + printf("\n"); + } + }; + printer(missing, "current"); + printer(missingComp, "comparison"); + } + } + mTrackingScratchBuffer.clear(); mTrackingScratchBuffer.shrink_to_fit(); }