CbmRoot
Loading...
Searching...
No Matches
CbmStsTimeCal.cxx
Go to the documentation of this file.
1/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Dario Ramirez [committer] */
4
5#include "CbmStsTimeCal.h"
6
7#include "CbmBmonDigi.h"
8#include "CbmFsdDigi.h"
9#include "CbmMuchDigi.h"
10#include "CbmMvdDigi.h"
11#include "CbmRichDigi.h"
12#include "CbmStsDigi.h"
13#include "CbmTofDigi.h"
14#include "CbmTrdDigi.h"
15
16#include <TColor.h>
17#include <TDirectory.h>
18#include <TF1.h>
19#include <TFitResult.h>
20#include <TLine.h>
21#include <TPaveText.h>
22#include <TStyle.h>
23
24#include <cassert>
25#include <ctime>
26#include <fstream>
27#include <iostream>
28#include <typeinfo>
29
30#include <fmt/core.h>
31#include <yaml-cpp/emitter.h>
32#include <yaml-cpp/emittermanip.h>
33#include <yaml-cpp/node/node.h>
34
35CbmStsTimeCal::CbmStsTimeCal(ECbmModuleId ref_sys, double t_min, double t_max)
36 : fTimeWindowMin(t_min)
37 , fTimeWindowMax(t_max)
38 , fRefSystem(ref_sys)
39{
40}
41
42CbmStsTimeCal::CbmStsTimeCal(int run_id, ECbmModuleId ref_sys, double t_min, double t_max)
43{
44 fRunId = run_id;
45 fTimeWindowMin = t_min;
46 fTimeWindowMax = t_max;
47 fRefSystem = ref_sys;
48}
49
50
52{
53 FairRootManager* ioman = FairRootManager::Instance();
54 if (ioman != nullptr) {
56 fDigiManager->Init();
57
58 fCbmEvtArray = (TClonesArray*) ioman->GetObject("CbmEvent");
59
60 if (!fDigiManager->IsPresent(ECbmModuleId::kSts)) LOG(fatal) << GetName() << ": No StsDigi branch in input!";
61 if (!fDigiManager->IsPresent(fRefSystem)) LOG(fatal) << GetName() << ": No " << fRefSystem << " branch in input!";
62
64
65 fOutputPath = fRunId > 0 ? Form("%d", fRunId) : ".";
66 if (gSystem->AccessPathName(fOutputPath.c_str(), kFileExists)) {
67 if (system(("mkdir -p " + fOutputPath).c_str())) { // Check output folder
68 LOG(warning) << "Could not create output directory\n Setting output path at current location:\n";
69 }
70 }
71 fReportOffset = std::make_unique<TFile>(Form("%s/cbm_sts_time_cal_offset.root", fOutputPath.c_str()), "RECREATE");
72 fReportFile = std::make_unique<TFile>(Form("%s/cbm_sts_time_cal_report.root", fOutputPath.c_str()), "RECREATE");
73 fReportFit = std::make_unique<TFile>(Form("%s/cbm_sts_time_cal_fits.root", fOutputPath.c_str()), "RECREATE");
74
75 return kSUCCESS;
76 }
77 return kERROR;
78}
79
80void CbmStsTimeCal::InitTimeWalkMap(int32_t address)
81{
82 for (unsigned int asic_idx = 0; asic_idx < 16; asic_idx++) {
83 fWalkMapRaw[address][asic_idx] = std::vector<double>(32, 0);
84 auto loaded_par = fWalkMap.Get(address, asic_idx);
85 if (loaded_par.size() == 31) {
86 for (int adc = 1; adc <= 31; adc++) {
87 fWalkMapRaw[address][asic_idx][adc] = loaded_par[adc - 1];
88 }
89 }
90 }
91}
92
93void CbmStsTimeCal::SetWalkFile(std::string f_name)
94{
95 LOG(debug) << Form("Setting user define time calibration file: %s", f_name.c_str());
96 fParFile = f_name;
97}
98
100{
101 if (!fParFile.length()) return;
102
103 if (TString(fParFile.c_str()).EndsWith(".yaml") || TString(fParFile.c_str()).EndsWith(".yml")) {
104 LOG(info) << Form("Loading time calibration from parameter file: %s", fParFile.c_str());
106 fGlobalTimeOffset = fWalkMap.GetSystemTimeOffset();
107 LOG(info) << "Current system offset: " << fGlobalTimeOffset << " ns";
108 }
109}
110
111void CbmStsTimeCal::BookHistograms(int32_t address)
112{
113 LOG(debug) << Form("Booking histograms for module: 0x%x", address);
114
115 std::string h_name, h_title;
116 int nb_time_bins = (std::abs(fTimeWindowMax - fTimeWindowMin) + kStsClock) / kStsClock;
117
118 int unit = CbmStsAddress::GetElementId(address, kStsUnit);
119 int ladd = CbmStsAddress::GetElementId(address, kStsLadder);
120 int modu = CbmStsAddress::GetElementId(address, kStsModule);
121 std::string smart_name = Form("U%d_L%d_M%d", unit, ladd, modu);
122
123 for (int asic_idx = 0; asic_idx < 16; asic_idx++) {
124 h_name = Form("0x%x_%02d", address, asic_idx);
125 h_title = Form("%s_%02d", smart_name.c_str(), asic_idx);
126
127 fH2D[h_name] =
128 std::make_unique<TH2D>(h_name.c_str(), h_title.c_str(), nb_time_bins, fTimeWindowMin - 0.5 * kStsClock,
129 fTimeWindowMax + 0.5 * kStsClock, 31, 1, 32);
130
131 fH2D[h_name]->GetXaxis()->SetTitle(
132 Form("t_{%s} - t_{StsDigi} [ns]", std::string(cbm::util::ToString(fRefSystem)).c_str()));
133 fH2D[h_name]->GetYaxis()->SetTitle("Charge_{StsDigi} [ADC]");
134 }
135
136 h_name = Form("0x%x_dt_vs_channel", address);
137 h_title = smart_name;
138 fH2D[h_name] = std::make_unique<TH2D>(h_name.c_str(), h_title.c_str(), 2048, 0, 2048, nb_time_bins,
140
141 fH2D[h_name]->GetYaxis()->SetTitle(
142 Form("t_{%s} - t_{StsDigi} [ns]", std::string(cbm::util::ToString(fRefSystem)).c_str()));
143 fH2D[h_name]->GetXaxis()->SetTitle("Channel_{StsDigi}");
144
145 fAddressBook.insert(address);
146}
147
148void CbmStsTimeCal::Exec(Option_t*)
149{
150 LOG(info) << "Running CbmStsTimeCal - Entry " << entry_;
151
155
156 entry_++;
157}
158
159template<class Digi>
161{
162 auto sts_digis_ = fDigiManager->GetArray<CbmStsDigi>();
163 auto ref_digis_ = fDigiManager->GetArray<Digi>();
164
165 size_t nb_sts_digis = fDigiManager->GetNofDigis(ECbmModuleId::kSts);
166 size_t nb_ref_digis = fDigiManager->GetNofDigis(Digi::GetSystem());
167
168 LOG(info) << nb_sts_digis << "\t" << nb_ref_digis;
169
170 // Loops over Ref Detector
171 for (size_t ref_digi_idx = 0; ref_digi_idx < nb_ref_digis - 1; ref_digi_idx++) {
172 const Digi* ref_digi = &ref_digis_[ref_digi_idx];
173 double ref_digi_time = ref_digi->GetTime();
174
175 if (fAnalysisCuts != nullptr
176 && !fAnalysisCuts->Check(CbmCutId::kBmonDigiSide, CbmTofAddress::GetChannelSide(ref_digi->GetAddress())))
177 continue;
178
179 double first_digi_in_window = ref_digi_time + fTimeWindowMin;
180 double last_digi_in_window = ref_digi_time + fTimeWindowMax;
181 // Find first_digi_in_window
182 int lo = 0, hi = nb_sts_digis - 1;
183 while (lo < hi) {
184 int m = (lo + hi) / 2;
185 if (sts_digis_[m].GetTime() >= first_digi_in_window) {
186 hi = m;
187 }
188 else {
189 lo = m + 1;
190 }
191 }
192 int lower_hitB = lo;
193
194 // Find last_digi_in_window
195 lo = 0, hi = nb_sts_digis - 1;
196 while (lo < hi) {
197 int m = (lo + hi + 1) / 2;
198 if (sts_digis_[m].GetTime() <= last_digi_in_window) {
199 lo = m;
200 }
201 else {
202 hi = m - 1;
203 }
204 }
205 int upper_hitB = lo;
206 if (lower_hitB > upper_hitB) {
207 LOG(debug) << "Not time match found for the current hit within the time window";
208 continue;
209 }
210
211 for (int sts_digi_idx = lower_hitB; sts_digi_idx < upper_hitB; sts_digi_idx++) {
212 const CbmStsDigi* sts_digi = &sts_digis_[sts_digi_idx];
213 int32_t sts_digi_addr = sts_digi->GetAddress();
214
215 if (!fAddressBook.count(sts_digi_addr)) {
216 BookHistograms(sts_digi_addr);
217 InitTimeWalkMap(sts_digi_addr);
218 }
219
220 int32_t sts_digi_chan = sts_digi->GetChannel();
221 int32_t sts_digi_char = sts_digi->GetCharge();
222 int32_t asic_idx = sts_digi_chan / 128;
223 double sts_digi_time = sts_digi->GetTime();
224
225 fH2D[Form("0x%x_%02d", sts_digi_addr, asic_idx)]->Fill(ref_digi_time - sts_digi_time, sts_digi_char);
226 fH2D[Form("0x%x_dt_vs_channel", sts_digi_addr)]->Fill(sts_digi_chan, ref_digi_time - sts_digi_time);
227 } // end sts loop
228 } // end ref loop
229}
230
231
233 std::unique_ptr<TH1> h_x;
234 std::unique_ptr<TF1> f_x;
235 std::unique_ptr<TF1> f_peak;
236 std::unique_ptr<TF1> f_bkgd;
237 TFitResultPtr fit_ptr;
238 bool use_fit_result{false};
239 double time_offset{0};
240
241 TCanvas* Draw()
242 {
243 if (h_x == nullptr) {
244 return nullptr;
245 }
246 int pad_x = 1024;
247 int pad_y = 1024;
248
249 std::unique_ptr<TCanvas> canvas = std::make_unique<TCanvas>("_c0", "", pad_x, pad_y);
250 canvas->cd();
251
252 double line_width = 0.06;
253 double pave0_top_edge = 0.95;
254 double pave0_bot_edge = pave0_top_edge - line_width * 3;
255 double pave1_top_edge = pave0_bot_edge;
256 double pave1_bot_edge = pave1_top_edge - line_width * 3;
257
258 h_x->SetLineStyle(1);
259 h_x->SetLineWidth((0.002 * pad_y));
260 h_x->SetLineColor(kBlack);
261 h_x->DrawClone("histo");
262
263 if (use_fit_result) {
264 f_x->SetTitle("Fitted function");
265 f_x->SetLineStyle(1);
266 f_x->SetLineWidth((0.002 * pad_y));
267 f_x->SetLineColor(kRed);
268 f_x->DrawClone("same");
269 }
270
271 if (use_fit_result) {
272 f_peak->SetTitle("Peak");
273 f_peak->SetLineStyle(kDotted);
274 f_peak->SetLineWidth((0.002 * pad_y));
275 f_peak->SetLineColor(kBlue);
276 f_peak->DrawClone("same");
277 std::unique_ptr<TPaveText> pave = std::make_unique<TPaveText>(0.16, pave0_bot_edge, 0.45, pave0_top_edge, "NDC");
278 pave->SetBorderSize(1);
279 pave->SetFillColor(0);
280 pave->SetTextAlign(12);
281 pave->AddText(Form("p0 = %.3f", f_peak->GetParameter(0)))->SetTextColor(kBlue);
282 pave->AddText(Form("p1 = %.3f", f_peak->GetParameter(1)))->SetTextColor(kBlue);
283 pave->AddText(Form("p2 = %.3f", f_peak->GetParameter(2)))->SetTextColor(kBlue);
284 pave->DrawClone();
285 }
286
287 if (use_fit_result) {
288 f_bkgd->SetTitle("Background");
289 f_bkgd->SetLineStyle(kDotted);
290 f_bkgd->SetLineWidth((0.002 * pad_y));
291 f_bkgd->SetLineColor(kOrange);
292 f_bkgd->DrawClone("same");
293 std::unique_ptr<TPaveText> pave = std::make_unique<TPaveText>(0.16, pave1_bot_edge, 0.45, pave1_top_edge, "NDC");
294 pave->SetBorderSize(1);
295 pave->SetFillColor(0);
296 pave->SetTextAlign(12);
297 pave->AddText(Form("p0 = %.3f", f_bkgd->GetParameter(0)))->SetTextColor(kOrange);
298 pave->AddText(Form("p1 = %.3f", f_bkgd->GetParameter(1)))->SetTextColor(kOrange);
299 pave->AddText(Form("p2 = %.3f", f_bkgd->GetParameter(2)))->SetTextColor(kOrange);
300 pave->DrawClone();
301 }
302
303 TLine offset(time_offset, h_x->GetMinimum(), time_offset, h_x->GetMaximum());
304 offset.SetLineWidth(0.004 * pad_y);
305 offset.SetLineColor(kGray);
306 offset.SetLineStyle(kDotted);
307 offset.DrawClone();
308
309 // Fit convergence
310 std::unique_ptr<TPaveText> fit_pave = std::make_unique<TPaveText>(0.65, 0.75, 0.95, 0.95, "NDC");
311 fit_pave->SetBorderSize(1);
312 fit_pave->SetFillColor(0);
313 fit_pave->SetTextAlign(12);
314 fit_pave->AddText(Form("NDF = %d", fit_ptr->Ndf()));
315 fit_pave->AddText(Form("Chi2 = %.3f", fit_ptr->Chi2()));
316 fit_pave->AddText(Form("PRob = %E", fit_ptr->Prob()));
317 fit_pave->DrawClone();
318
319 return (TCanvas*) canvas->Clone();
320 }
321
323 {
324 if (h == nullptr) {
325 return;
326 }
327 h_x = std::make_unique<TH1D>(*h);
328 h_x->Scale(1. / h_x->Integral());
329
330 // Fit configuration
331 double time_resolution = 4.8;
332 double h_max = h_x->GetBinCenter(h_x->GetMaximumBin());
333 double fit_x_min = h_max - 10. * time_resolution;
334 double fit_x_max = h_max + 10. * time_resolution;
335
336 f_x = std::make_unique<TF1>("f_x", "[0]*TMath::Gaus(x, [1], [2]) + [3] + [4]*x + [5]*x*x", fit_x_min, fit_x_max);
337 f_peak = std::make_unique<TF1>("f_peak", "[0]*TMath::Gaus(x, [1], [2])", fit_x_min, fit_x_max);
338 f_bkgd = std::make_unique<TF1>("f_bkgd", "[0] + [1]*x + [2]*x*x", fit_x_min, fit_x_max);
339
340 // Initial values
341 f_x->SetParameter(0, 0.5);
342 f_x->SetParameter(1, h_max);
343 f_x->SetParameter(2, time_resolution);
344 f_x->SetParameter(5, -1e-4);
345
346 // Limits
347 f_x->SetParLimits(0, 0.0, 1.0);
348 f_x->SetParLimits(1, h_max - 2. * time_resolution, h_max + 2. * time_resolution);
349 f_x->SetParLimits(2, 3.125, 25);
350 f_x->SetParLimits(5, -1, 0.0);
351
352
353 fit_ptr = h_x->Fit("f_x", "SQN0", "", fit_x_min, fit_x_max);
354
355 f_x->SetParameters(fit_ptr->GetParams());
356 f_peak->SetParameter(0, fit_ptr->Parameter(0));
357 f_peak->SetParameter(1, fit_ptr->Parameter(1));
358 f_peak->SetParameter(2, fit_ptr->Parameter(2));
359 f_bkgd->SetParameter(0, fit_ptr->Parameter(3));
360 f_bkgd->SetParameter(1, fit_ptr->Parameter(4));
361 f_bkgd->SetParameter(2, fit_ptr->Parameter(5));
362
363 bool par_out_of_limits =
364 fit_ptr->Parameter(1) < h_max - 2. * time_resolution || h_max + 2. * time_resolution < fit_ptr->Parameter(1);
365
366 use_fit_result = !fit_ptr && fit_ptr->IsValid() && !par_out_of_limits;
367
368 if (use_fit_result) {
369 time_offset = f_peak->GetParameter(1);
370 }
371 else {
372 time_offset = h_max;
373 }
374 }
375};
376
377double CbmStsTimeCal::FindModuleOffset(int32_t address)
378{
379
380 double module_offset = 0;
381 TH2D* dt_vs_chn = fH2D[Form("0x%x_dt_vs_channel", address)].get();
382 if (dt_vs_chn != nullptr) {
383 TH1D* p_y = (TH1D*) dt_vs_chn->ProjectionY();
384
385 double peak = p_y->GetBinCenter(p_y->GetMaximumBin());
386
387 FitStsTime offset_fit(p_y);
388 TCanvas* drawing = offset_fit.Draw();
389 if (drawing != nullptr) {
390 fReportOffset->cd();
391 drawing->Write(Form("0x%x_offset", address));
392 }
393
394 if (offset_fit.use_fit_result) {
395 module_offset = offset_fit.time_offset;
396 }
397 else {
398 module_offset = peak;
399 }
400 }
401 return module_offset;
402}
403
405{
406 /* This function can be optimized by parallelizing the loop over modules or ASIC idx, depending on the ratio
407 * For mCBM case, there are usually less than 16 modules so it makes more sense to parallelize the ASIC idx loop
408 * but for the full CBM case, the amount of modules greatly exceeds the number of ASIC per modules (16)
409 */
410 for (int32_t module : fAddressBook) { // loop over modules
411 double module_offset = FindModuleOffset(module);
412 for (unsigned int asic_idx = 0; asic_idx < 16; asic_idx++) { // loop over ASICs
413
414 double adc_channel[32];
415 double adc_channel_err[32];
416 double time_offset[32];
417 double time_offset_err[32];
418 int n_pts = 0;
419
420 std::string h_name = Form("0x%x_%02d", module, asic_idx);
421 if (!fH2D.count(h_name)) return;
422
423 auto h = fH2D[h_name].get();
424
425 for (int adc = 1; adc <= 31; adc++) {
426 TH1D* h_x = h->ProjectionX(Form("%s_dt", h_name.c_str()), adc, adc);
427
428 FitStsTime offset_fit(h_x);
429 TCanvas* drawing = offset_fit.Draw();
430 if (drawing != nullptr) {
431 std::string fit_folder = Form("0x%x/%02d", module, asic_idx);
432 TDirectory* dir = (TDirectory*) fReportFit->Get(fit_folder.c_str());
433 if (!dir) {
434 dir = fReportFit->mkdir(fit_folder.c_str());
435 }
436 dir->cd();
437 drawing->Write(Form("0x%x_%02d_%02d", module, asic_idx, adc));
438 }
439
440 if (offset_fit.use_fit_result) {
441 time_offset[n_pts] = offset_fit.fit_ptr->Parameter(1);
442 time_offset_err[n_pts] = offset_fit.fit_ptr->Parameter(2);
443 }
444 else {
445 /* If the fitting for individual ADC of the ASIC was unsuccessful
446 * the time offset is taken as the one estimated for the whole module
447 */
448 time_offset[n_pts] = module_offset;
449 time_offset_err[n_pts] = h_x->GetRMS();
450 }
451 adc_channel[n_pts] = adc;
452 adc_channel_err[n_pts] = 0;
453
454 // Update time walk map
455 fWalkMapRaw[module][asic_idx][adc] += time_offset[n_pts];
456
457 n_pts++;
458
459 } // ---- end ADC loop ----
460
461 fG1D[h_name] = std::make_unique<TGraphErrors>(n_pts, adc_channel, time_offset, adc_channel_err, time_offset_err);
462 fG1D[h_name]->SetTitle(
463 Form("%s : StsDigi_0x%x time off-set", std::string(cbm::util::ToString(fRefSystem)).c_str(), module));
464 fG1D[h_name]->GetXaxis()->SetTitle("Charge_{StsDigi} [ADC]");
465 fG1D[h_name]->GetYaxis()->SetTitle(
466 Form("t_{%s} - t_{StsDigi} [ns]", std::string(cbm::util::ToString(fRefSystem)).c_str()));
467 fG1D[h_name]->SetMinimum(fTimeWindowMin);
468 fG1D[h_name]->SetMaximum(fTimeWindowMax);
469
470 } // ---- end module loop ----
471 } // ---- end ASICs loop ----
472}
473
475{
476 double setup_offset = 0;
477 double min_sum_sigma = 999;
478 for (int32_t module : fAddressBook) { // module loop
479 double module_avg_sigma = 0;
480 double module_avg_offset = 0;
481 int n_of_values = 0;
482
483 for (unsigned int asic_idx = 0; asic_idx < 16; asic_idx++) { // asic loop
484 std::string h_name = Form("0x%x_%02d", module, asic_idx);
485 auto g = fG1D[h_name].get();
486
487 int n_of_pto = g->GetN();
488 int lower_bound = n_of_pto > 5 ? n_of_pto - 5 : 0;
489
490 // Calculate the average value of the sigma for the last ADC
491 for (int pto = n_of_pto; pto > lower_bound - 5; pto--) {
492 double offset = g->GetPointY(pto);
493 double sigma = g->GetErrorY(pto);
494 if (sigma) {
495 module_avg_sigma += sigma;
496 module_avg_offset += offset;
497 n_of_values++;
498 }
499 }
500 } // end asic loop
501
502 module_avg_sigma = n_of_values ? module_avg_sigma / n_of_values : -1;
503 module_avg_offset = n_of_values ? module_avg_offset / n_of_values : -1;
504
505 if (module_avg_sigma && module_avg_sigma < min_sum_sigma) {
506 min_sum_sigma = module_avg_sigma;
507 setup_offset = module_avg_offset;
508 }
509 } // end module loop
510
511 return setup_offset;
512}
513
515{
516 std::string o_yaml_file = fOutputPath + "/StsTimeCalibration.yaml";
517 LOG(info) << "Writing parameter file to:" << o_yaml_file;
518
519 YAML::Emitter walk_map;
520 walk_map << YAML::BeginMap;
521 walk_map << YAML::Key << "timeOffset";
522 walk_map << YAML::Value << (int) fGlobalTimeOffset;
523 walk_map << YAML::Key << "WalkMap";
524 walk_map << YAML::Value << YAML::BeginMap;
525 for (const auto& [module, asics] : fWalkMapRaw) {
526 walk_map << YAML::Key << fmt::format("0x{:x}", module);
527 walk_map << YAML::Value << YAML::BeginSeq;
528 for (const auto& [asic, pars] : asics) {
529 // Begin a flow sequence
530 walk_map << YAML::Flow << YAML::BeginSeq;
531 for (const auto& value : pars) {
532 walk_map << fmt::format("{:+.3f}", value); // Add '+' for positive numbers
533 }
534 // End the flow sequence
535 walk_map << YAML::EndSeq;
536 }
537 walk_map << YAML::EndSeq;
538 }
539 walk_map << YAML::EndMap << YAML::EndMap;
540 assert(walk_map.good());
541
542 std::ofstream walk_map_out(o_yaml_file);
543 assert(walk_map_out.is_open());
544
545 walk_map_out << walk_map.c_str();
546 walk_map_out.close();
547}
548
550{
552
553 // resize ADC offset vector to 31 channels from 0 [0-30`]
554 for (auto& [module, asics] : fWalkMapRaw) { // Loop over modules
555 for (auto& [asic_idx, asic_par] : asics) { // Loop over ASICs
556 for (int adc = 1; adc <= 31; adc++) { // loop over ADC channels 31 channels [1 - 31]
557 asic_par[adc - 1] = asic_par[adc];
558 }
559 asic_par.pop_back();
560 }
561 }
562
563 WriteYAML();
564
565 DrawResults();
566 SaveToFile();
567
568
569 fH1D.clear();
570 fH2D.clear();
571}
572
573
575{
576 std::unique_ptr<TCanvas> adc_vs_dt_1d =
577 std::make_unique<TCanvas>("adc_vs_dt_1d", "adc_vs_dt_1d", 10, 10, 4 * 1024, 4 * 1024);
578 adc_vs_dt_1d->Divide(4, 4);
579
580 std::unique_ptr<TCanvas> adc_vs_dt_2d =
581 std::make_unique<TCanvas>("adc_vs_dt_2d", "adc_vs_dt_2d", 10, 10, 4 * 1024, 4 * 1024);
582 adc_vs_dt_2d->Divide(4, 4);
583
584 std::unique_ptr<TCanvas> dt_vs_chn = std::make_unique<TCanvas>("dt_vs_chn", "dt_vs_chn", 10, 10, 1024, 1024);
585
586 fReportFile->cd();
587 for (int32_t sensor : fAddressBook) {
588 for (int asic_idx = 0; asic_idx < 16; asic_idx++) {
589 adc_vs_dt_1d->cd(asic_idx + 1);
590 if (fG1D[Form("0x%x_%02d", sensor, asic_idx)] != nullptr) {
591 fG1D[Form("0x%x_%02d", sensor, asic_idx)]->Draw("APL");
592 }
593
594 adc_vs_dt_2d->cd(asic_idx + 1);
595 if (fH2D[Form("0x%x_%02d", sensor, asic_idx)] != nullptr) {
596 fH2D[Form("0x%x_%02d", sensor, asic_idx)]->Draw("colz");
597 }
598 }
599
600 dt_vs_chn->cd();
601 if (fH2D[Form("0x%x_dt_vs_channel", sensor)] != nullptr) {
602 fH2D[Form("0x%x_dt_vs_channel", sensor)]->Draw("colz");
603 }
604
605 adc_vs_dt_1d->Write(Form("adc_vs_dt_1d_0x%x", sensor));
606 adc_vs_dt_2d->Write(Form("adc_vs_dt_2d_0x%x", sensor));
607 dt_vs_chn->Write(Form("dt_vs_chn_0x%x", sensor));
608 }
609}
@ kBmonDigiSide
Definition CbmCutId.h:18
ECbmModuleId
Enumerator for module Identifiers.
Definition CbmDefs.h:45
@ kTof
Time-of-flight Detector.
Definition CbmDefs.h:52
@ kSts
Silicon Tracking System.
Definition CbmDefs.h:48
@ kBmon
Bmon Counter.
Definition CbmDefs.h:57
@ kRich
Ring-Imaging Cherenkov Detector.
Definition CbmDefs.h:49
@ kStsModule
@ kStsLadder
@ kStsUnit
static CbmDigiManager * Instance()
Static instance.
CbmCutMap * fAnalysisCuts
std::unordered_set< int32_t > fAddressBook
std::unique_ptr< TFile > fReportFile
std::map< std::string, std::unique_ptr< TGraphErrors > > fG1D
std::map< std::string, std::unique_ptr< TH2D > > fH2D
void SaveToFile()
It write all mapped objects to the FairRunAna sink file.
std::map< std::string, std::unique_ptr< TH1D > > fH1D
Data class for a single-channel message in the STS.
Definition CbmStsDigi.h:40
XPU_D uint16_t GetChannel() const
Channel number in module @value Channel number.
Definition CbmStsDigi.h:93
XPU_D int32_t GetAddress() const
Definition CbmStsDigi.h:74
double FindModuleOffset(int32_t)
Extract Time general offset for a given module.
void SetWalkFile(std::string par_file)
Set parameter file used during unpacking.
void DrawResults()
Virtual function to draw analysis results.
std::string fParFile
double fGlobalTimeOffset
void CheckTimeWalk()
Extract Time Walk parameters.
double fTimeWindowMin
std::unique_ptr< TFile > fReportFit
void WriteYAML()
Write parameters file in YAML format.
ECbmModuleId fRefSystem
void BookHistograms(int32_t address)
Book histograms.
void LoadWalkFromFile()
Load the time calibration parameters from user define file.
void CheckTiming()
Check timing for a specific digi type It fills StsDigi time difference respect to fRefSystem Digis hi...
std::unique_ptr< TFile > fReportOffset
TClonesArray * fCbmEvtArray
double fTimeWindowMax
void InitTimeWalkMap(int32_t address)
Initialized the Time Walk map.
cbm::algo::sts::WalkMap fWalkMap
CbmDigiManager * fDigiManager
CbmStsTimeCal()=default
const double kStsClock
void Exec(Option_t *)
std::string fOutputPath
std::map< int, std::map< int, std::vector< double > > > fWalkMapRaw
InitStatus Init()
double FindGlobalOffset()
Find a common offset for STS setup. It is taken as the average of the time offset for ADC > 25 for th...
Data class with information on a STS local track.
static int32_t GetChannelSide(uint32_t address)
uint32_t GetElementId(int32_t address, int32_t level)
Get the index of an element.
T ReadFromFile(fs::path path)
Definition CbmYaml.h:66
std::string_view ToString(T t)
Definition CbmEnumDict.h:64
std::unique_ptr< TH1 > h_x
std::unique_ptr< TF1 > f_x
FitStsTime(TH1D *h)
TCanvas * Draw()
std::unique_ptr< TF1 > f_peak
std::unique_ptr< TF1 > f_bkgd
TFitResultPtr fit_ptr