CbmRoot
Loading...
Searching...
No Matches
CbmSeedFinderQa.cxx
Go to the documentation of this file.
1/* Copyright (C) 2007-2022 Facility for Antiproton and Ion Research in Europe, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Dominik Smith [committer] */
4
5#include "CbmSeedFinderQa.h"
6
7#include "CbmMCEventList.h"
8#include "CbmQaCanvas.h"
9#include "FairRootManager.h"
10#include "TH1.h"
11#include "TH2.h"
12
13#include <Logger.h>
14
15CbmSeedFinderQa::CbmSeedFinderQa() : fOutFolder("SeedFinderQA", "Seed finder QA")
16{
17 // --- Init histogram folder
18 histFolder = fOutFolder.AddFolder("hist", "Histogramms");
19
20 // --- Init histograms
22 new TH1F("fhLinkedMCEventsPerTrigger", "Linked MC events per trigger (=0 for pure noise)", 5, -1.5, 3.5);
23 fhLinkedMCEventsPerTrigger->SetCanExtend(TH1::kAllAxes);
24
25 fhLinkedTriggersPerMCEvent = new TH1F("fhLinkedTriggersPerMCEvent", "Linked triggers per MC event", 5, -1.5, 3.5);
26 fhLinkedTriggersPerMCEvent->SetCanExtend(TH1::kAllAxes);
27
28 fhMatchedTriggersPerMCEvent = new TH1F("fhMatchedTriggersPerMCEvent", "Matched triggers per MC event", 5, -1.5, 3.5);
29 fhMatchedTriggersPerMCEvent->SetCanExtend(TH1::kAllAxes);
30
31 fhCorrectDigiRatio = new TH1F("fhCorrectDigiRatio", "Correct digis per seed [pct]", 416, -2, 102);
33 new TH1F("fhCorrectDigiRatioNoNoise", "Correct digis per seed [pct], disregarding noise", 416, -2, 102);
34 fhNoiseDigiRatio = new TH1F("fhNoiseDigiRatio", "Noise digis per seed [pct]", 416, -2, 102);
35 fhFoundDigiRatio = new TH1F("fhFoundDigiRatio", "Found digis per seed [pct]", 416, -2, 102);
36 fhCorrectVsFound = new TH2I("fhCorrectVsFound", "Correct digis [pct] vs. Found digis [pct]; Correct; Found ", 110,
37 -5., 105., 110, -5., 105.);
39 new TH2I("fhCorrectVsFoundNoNoise", "Correct digis [pct] vs. Found digis [pct], no noise; Correct; Found ", 110,
40 -5., 105., 110, -5., 105.);
41
42 fhTimeOffset = new TH1F("fhTimeOffsetMatched", "tSeed - tMCMatched [ns]", 20, -5, 5);
43 fhTimeOffset->SetCanExtend(TH1::kAllAxes);
44
45 fhTimeOffsetSingletOnly = new TH1F("fhTimeOffsetSingletOnly", "tSeed - tMCMatched [ns], one-to-one only", 20, -5, 5);
46 fhTimeOffsetSingletOnly->SetCanExtend(TH1::kAllAxes);
47
48 fhTimeOffsetClosest = new TH1F("fhTimeOffsetClosest", "tSeed - tMCClosest [ns]", 20, -5, 5);
49 fhTimeOffsetClosest->SetCanExtend(TH1::kAllAxes);
50
63
64 fCanv = new CbmQaCanvas("cSummary", "", 4 * 400, 3 * 400);
65 fCanv->Divide2D(11);
66 fOutFolder.Add(fCanv);
67}
68
84
86{
87 if (!FairRootManager::Instance() || !FairRootManager::Instance()->GetObject("MCEventList.")) {
88 LOG(error) << "No MC event list found";
89 return;
90 }
91 fEventList = (CbmMCEventList*) FairRootManager::Instance()->GetObject("MCEventList.");
92}
93
99
100void CbmSeedFinderQa::FillQaSeedInfo(const int32_t WinStart, const int32_t WinEnd,
101 const std::vector<CbmMatch>* vDigiMatch, const double seedTime)
102{
103 fvSeedTimesFull.push_back(seedTime);
104 fvSeedTimesPerTs.push_back(seedTime);
105
106 int32_t digiCount = 0;
107 int32_t noiseDigiCount = 0;
108 int32_t correctDigiCount = 0;
109 int32_t matchedEventDigiCount = 0;
110 CbmMatch seedMatch;
111
112 for (int32_t iDigi = WinStart; iDigi <= WinEnd; iDigi++) {
113 const CbmMatch* digiMatch = &(vDigiMatch->at(iDigi));
114 digiCount++;
115 if (digiMatch->GetNofLinks() == 0) {
116 //skip digis with no links to avoid Bmon pollution
117 noiseDigiCount++;
118 continue;
119 }
120 if (digiMatch->GetMatchedLink().GetEntry() == -1) {
121 noiseDigiCount++;
122 continue; //disregard noise digis
123 }
124
125 // Update seed match with digi links
126 for (int32_t iLink = 0; iLink < digiMatch->GetNofLinks(); iLink++) {
127 int32_t entry = digiMatch->GetLink(iLink).GetEntry();
128 if (entry == -1) {
129 continue;
130 } //ignore noise links
131 int32_t file = digiMatch->GetLink(iLink).GetFile();
132 //double weight = digiMatch->GetLink(iLink).GetWeight();
133 const double weight =
134 .00001; // assign the same weight to all links, since different detectors don't use the same scale
135 // LOG(info) << "Adding link (number, weight, entry, file): " << iLink << " " << weight << " "
136 // << entry << " " << file;
137 seedMatch.AddLink(weight, 0, entry, file);
138 }
139 }
140 fvFullDigiCount.push_back(digiCount);
141 fvNoiseDigiCount.push_back(noiseDigiCount);
142 fvLinkedMCEventsCount.push_back(seedMatch.GetNofLinks());
143
144 if (seedMatch.GetNofLinks() == 0) //seed is only noise digis
145 {
146 seedMatch.AddLink(1.0, 0, -1, 0);
147 fvEventMatches.push_back(seedMatch);
148 fvEventMatchesPerTs.push_back(seedMatch);
149
150 //should never show up in histograms
151 fvCorrectDigiRatio.push_back(std::numeric_limits<double>::quiet_NaN());
152 fvCorrectDigiRatioNoNoise.push_back(std::numeric_limits<double>::quiet_NaN());
153 fvFoundDigiRatio.push_back(std::numeric_limits<double>::quiet_NaN());
154 fvTimeOffset.push_back(std::numeric_limits<double>::quiet_NaN());
155 return;
156 }
157 else {
158 fvEventMatches.push_back(seedMatch);
159 fvEventMatchesPerTs.push_back(seedMatch);
160 }
161
162 //correct digis in seed window
163 for (int32_t iDigi = WinStart; iDigi <= WinEnd; iDigi++) {
164 const CbmMatch* digiMatch = &(vDigiMatch->at(iDigi));
165 if (digiMatch->GetNofLinks() == 0) {
166 continue;
167 } //skip digis with no links to avoid Bmon pollution
168 const int32_t entry = digiMatch->GetMatchedLink().GetEntry();
169 if (entry != -1) // disregarding noise
170 {
171 if (entry == seedMatch.GetMatchedLink().GetEntry()) {
172 correctDigiCount++;
173 }
174 }
175 }
176 const double correctDigiRatio = (double) correctDigiCount / digiCount;
177 fvCorrectDigiRatio.push_back(correctDigiRatio);
178
179 const double correctDigiRatioNoNoise = (double) correctDigiCount / (digiCount - noiseDigiCount);
180 fvCorrectDigiRatioNoNoise.push_back(correctDigiRatioNoNoise);
181
182 //found digis of matched event in seed window
183 for (uint32_t iDigi = 0; iDigi < vDigiMatch->size(); iDigi++) {
184 const CbmMatch* digiMatch = &(vDigiMatch->at(iDigi));
185 if (digiMatch->GetNofLinks() == 0) {
186 continue;
187 } //skip digis with no links to avoid Bmon pollution
188 const int matchedEvent = digiMatch->GetMatchedLink().GetEntry();
189 if (matchedEvent == seedMatch.GetMatchedLink().GetEntry()) {
190 matchedEventDigiCount++;
191 }
192 }
193 const double foundDigiRatio = (double) correctDigiCount / matchedEventDigiCount;
194 fvFoundDigiRatio.push_back(foundDigiRatio);
195
196 //seed time offset to MC
197 const CbmLink& eventLink = seedMatch.GetMatchedLink();
198 const double timeDiff = seedTime - fEventList->GetEventTime(eventLink.GetEntry(), eventLink.GetFile());
199 fvTimeOffset.push_back(timeDiff);
200}
201
203{
204 const uint32_t nEvents = fEventList->GetNofEvents();
205 if (nEvents == 0) {
206 return;
207 }
208
209 std::vector<uint32_t> vLinkedTriggersPerMCEvent;
210 std::vector<uint32_t> vMatchedTriggersPerMCEvent;
211 vLinkedTriggersPerMCEvent.resize(nEvents, 0);
212 vMatchedTriggersPerMCEvent.resize(nEvents, 0);
213
214 for (uint32_t iSeed = 0; iSeed < fvEventMatchesPerTs.size(); iSeed++) {
215 const CbmMatch eventMatch = fvEventMatchesPerTs.at(iSeed);
216 const CbmLink matchedLink = eventMatch.GetMatchedLink();
217 if (fEventList->GetEventIndex(matchedLink) == -1) {
218 continue;
219 }
220
221 for (int32_t iLink = 0; iLink < eventMatch.GetNofLinks(); iLink++) {
222 const CbmLink eventLink = eventMatch.GetLink(iLink);
223 vLinkedTriggersPerMCEvent[fEventList->GetEventIndex(eventLink)]++;
224 }
225 vMatchedTriggersPerMCEvent[fEventList->GetEventIndex(matchedLink)]++;
226 }
227
228 for (uint32_t iSeed = 0; iSeed < fvEventMatchesPerTs.size(); iSeed++) {
229 const CbmMatch eventMatch = fvEventMatchesPerTs.at(iSeed);
230 const CbmLink matchedLink = eventMatch.GetMatchedLink();
231 if (fEventList->GetEventIndex(matchedLink) == -1) {
232 continue;
233 }
234
235 if (vMatchedTriggersPerMCEvent[fEventList->GetEventIndex(matchedLink)] == 1) {
236 const double seedTime = fvSeedTimesPerTs[iSeed];
237 const double timeDiff = seedTime - fEventList->GetEventTime(matchedLink.GetEntry(), matchedLink.GetFile());
238 fhTimeOffsetSingletOnly->Fill(timeDiff);
239 }
240 }
241
242 for (const auto& value : vLinkedTriggersPerMCEvent) {
243 fhLinkedTriggersPerMCEvent->Fill(value);
244 }
245 for (const auto& value : vMatchedTriggersPerMCEvent) {
246 fhMatchedTriggersPerMCEvent->Fill(value);
247 }
248
249 // get sorted vector of MC event times
250 std::vector<double> vMCEventTimes;
251 for (uint32_t iEvent = 0; iEvent < nEvents; iEvent++) {
252 vMCEventTimes.push_back(fEventList->GetEventTimeByIndex(iEvent));
253 }
254 std::sort(std::begin(vMCEventTimes), std::end(vMCEventTimes));
255
256 //find closest MC event for each seed (assumes both arrays are sorted in time)
257 auto minElem = vMCEventTimes.begin();
258 for (const auto& seedTime : fvSeedTimesPerTs) {
259 auto comp = [&, seedTime](double val1, double val2) { return fabs(seedTime - val1) < fabs(seedTime - val2); };
260 minElem = std::min_element(minElem, vMCEventTimes.end(), comp);
261 fhTimeOffsetClosest->Fill(seedTime - *minElem);
262 }
263}
264
266{
267 for (uint32_t iEvent = 0; iEvent < fvEventMatches.size(); iEvent++) {
268
270
271 const CbmMatch* match = &(fvEventMatches.at(iEvent));
272 const CbmLink& link = match->GetMatchedLink();
273 if (link.GetEntry() == -1) {
274 continue;
275 }
276
277 fhTimeOffset->Fill(fvTimeOffset.at(iEvent));
278 const int32_t digiCount = fvFullDigiCount.at(iEvent);
279 const int32_t noiseCount = fvNoiseDigiCount.at(iEvent);
280 const double noiseDigisPercent = 100. * (double) noiseCount / digiCount;
281 const double correctDigisPercent = 100. * fvCorrectDigiRatio.at(iEvent);
282 const double correctDigisPercentNoNoise = 100. * fvCorrectDigiRatioNoNoise.at(iEvent);
283 const double foundDigisPercent = 100. * fvFoundDigiRatio.at(iEvent);
284 fhCorrectDigiRatio->Fill(correctDigisPercent);
285 fhCorrectDigiRatioNoNoise->Fill(correctDigisPercentNoNoise);
286 fhNoiseDigiRatio->Fill(noiseDigisPercent);
287 fhFoundDigiRatio->Fill(foundDigisPercent);
288 fhCorrectVsFound->Fill(correctDigisPercent, foundDigisPercent);
289 fhCorrectVsFoundNoNoise->Fill(correctDigisPercentNoNoise, foundDigisPercent);
290 }
291}
292
294{
295 for (uint32_t iEvent = 0; iEvent < fvEventMatches.size(); iEvent++) {
296 const CbmMatch* match = &(fvEventMatches.at(iEvent));
297 const int32_t mcEventNr = match->GetMatchedLink().GetEntry();
298
299 std::cout << "QA for seed # " << iEvent << std::endl;
300 std::cout << "Seed time: " << fvSeedTimesFull.at(iEvent) << std::endl;
301 std::cout << "Links to MC events: " << match->GetNofLinks() << ", matched MC event number " << mcEventNr
302 << std::endl;
303 if (mcEventNr == -1) {
304 std::cout << "Warning: Seed was constructed from noise digis only (MC event = -1)!" << std::endl;
305 std::cout << " Please increase your noise threshold!" << std::endl;
306 }
307 std::cout << "Total digis in seed window: " << fvFullDigiCount.at(iEvent);
308 std::cout << ", Noise digis in seed window: " << fvNoiseDigiCount.at(iEvent) << std::endl;
309 std::cout << "Fraction of correctly matched digis in seed window: " << fvCorrectDigiRatio.at(iEvent) << std::endl;
310 std::cout << "Fraction of correctly matched digis in seed window (disregarding noise): "
311 << fvCorrectDigiRatioNoNoise.at(iEvent) << std::endl;
312 std::cout << "Fraction of digis of matched event found in seed window: " << fvFoundDigiRatio.at(iEvent);
313 std::cout << " (only from this timeslice)" << std::endl;
314 }
315 FillHistos();
316 WriteHistos();
317}
318
320{
321 fCanv->cd(1);
322 fhCorrectDigiRatio->DrawCopy("colz", "");
323
324 fCanv->cd(2);
325 fhCorrectDigiRatioNoNoise->DrawCopy("colz", "");
326
327 fCanv->cd(3);
328 fhNoiseDigiRatio->DrawCopy("colz", "");
329
330 fCanv->cd(4);
331 fhFoundDigiRatio->DrawCopy("colz", "");
332
333 fCanv->cd(5);
334 fhCorrectVsFound->DrawCopy("colz", "");
335
336 fCanv->cd(6);
337 fhCorrectVsFoundNoNoise->DrawCopy("colz", "");
338
339 fCanv->cd(7);
340 fhTimeOffset->DrawCopy("colz", "");
341
342 fCanv->cd(8);
343 fhTimeOffsetSingletOnly->DrawCopy("colz", "");
344
345 fCanv->cd(9);
346 fhTimeOffsetClosest->DrawCopy("colz", "");
347
348 fCanv->cd(10);
349 fhLinkedMCEventsPerTrigger->DrawCopy("colz", "");
350
351 fCanv->cd(11);
352 fhLinkedTriggersPerMCEvent->DrawCopy("colz", "");
353
354 fCanv->cd(12);
355 fhMatchedTriggersPerMCEvent->DrawCopy("colz", "");
356
357 FairSink* sink = FairRootManager::Instance()->GetSink();
358 sink->WriteObject(&fOutFolder, nullptr);
359}
Definition of the CbmQaCanvas class.
Class for sliding window seed finder.
InOutStructure val1
InOutStructure val2
Container class for MC events with number, file and start time.
double GetEventTimeByIndex(uint32_t index)
Event time by index @value Event time for event at given index in list.
Int_t GetEventIndex(UInt_t event, UInt_t file)
Event index.
std::size_t GetNofEvents() const
Number of events in the list @value Number of events.
double GetEventTime(uint32_t event, uint32_t file)
Event start time.
const CbmLink & GetLink(int32_t i) const
Definition CbmMatch.h:39
int32_t GetNofLinks() const
Definition CbmMatch.h:42
void AddLink(const CbmLink &newLink)
Definition CbmMatch.cxx:47
const CbmLink & GetMatchedLink() const
Definition CbmMatch.h:41
void Divide2D(int nPads)
Divide canvas into nPads in 2D in a nice way.
void FillQaSeedInfo(const int32_t WinStart, const int32_t WinEnd, const std::vector< CbmMatch > *vDigiMatch, const double seedTime)
Gather QA Information. @params WinStart Starting position of seed window. @params WinStart End positi...
std::vector< double > fvCorrectDigiRatio
Ratio of digis from matched MC event.
std::vector< uint32_t > fvLinkedMCEventsCount
Counts how many MC events contributed to a seed.
void Init()
Initialize communication with FairRootManager (needed for MC events).
TH2I * fhCorrectVsFound
digis found per event
void FillHistos()
Fill output histograms with data from current timeslice.
TH1F * fhFoundDigiRatio
noise digis per event
CbmQaCanvas * fCanv
difference between true event time and seed time for one-to-one matched cases
void WriteHistos()
Finalize histograms and canvases and write to file.
void OutputQa()
Output QA Information.
TH1F * fhTimeOffset
correct digis per event vs found digis per event, disregarding noise
std::vector< double > fvCorrectDigiRatioNoNoise
Ratio of digis from matched MC event (disregarding noise).
TH1F * fhNoiseDigiRatio
correct digis per event, disregarding noise
TFolder fOutFolder
subfolder for histograms
CbmSeedFinderQa()
Create the CbmSeedFinderQa object.
std::vector< double > fvSeedTimesFull
Full vector of all event seeds that is not cleared at the end of a timeslice.
TH1F * fhTimeOffsetClosest
difference between true event time and seed time
TH1F * fhCorrectDigiRatioNoNoise
correct digis per event
std::vector< int32_t > fvNoiseDigiCount
Counts how many noise digis contributed to a seed.
TH1F * fhCorrectDigiRatio
linked MC events per trigger
std::vector< CbmMatch > fvEventMatchesPerTs
Matches that link constructed event seeds to MC events, current timeslice only.
void ResetPerTsStorage()
Reset containers that are persistent for one TS.
std::vector< double > fvTimeOffset
Difference between true event time and seed time.
std::vector< double > fvSeedTimesPerTs
Vector of event seeds, current TS only.
TH1F * fhMatchedTriggersPerMCEvent
linked triggers per MC event
CbmMCEventList * fEventList
summary canvas
std::vector< CbmMatch > fvEventMatches
Matches that link constructed event seeds to MC events.
TH1F * fhTimeOffsetSingletOnly
difference between seed time and closest MC event time
~CbmSeedFinderQa()
Destructor.
std::vector< int32_t > fvFullDigiCount
Counts how many digis contributed to a seed.
TH1F * fhLinkedMCEventsPerTrigger
matchted triggers per MC event
TH1F * fhLinkedTriggersPerMCEvent
output folder with histos and canvases
void FillQaMCInfo()
Fill QA Information that uses the full list of MC events per TS.
std::vector< double > fvFoundDigiRatio
Ratio of digis of matched events that were included in event seed.
TH2I * fhCorrectVsFoundNoNoise
correct digis per event vs found digis per event