R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
R3BNeulandMapToCalTask.cxx
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) 2019 GSI Helmholtzzentrum für Schwerionenforschung GmbH *
3 * Copyright (C) 2019-2023 Members of R3B Collaboration *
4 * *
5 * This software is distributed under the terms of the *
6 * GNU General Public Licence (GPL) version 3, *
7 * copied verbatim in the file "LICENSE". *
8 * *
9 * In applying this license GSI does not waive the privileges and immunities *
10 * granted to it by virtue of its status as an Intergovernmental Organization *
11 * or submit itself to any jurisdiction. *
12 ******************************************************************************/
13
15#include "R3BNeulandCalData2.h"
16#include "R3BNeulandCommon.h"
17#include <FairRootManager.h>
18#include <FairRuntimeDb.h>
19#include <R3BEventHeader.h>
20#include <R3BException.h>
21#include <R3BLogger.h>
22#include <TH1D.h>
23#include <TH2D.h>
24#include <fmt/core.h>
25#include <fmt/ranges.h>
26#include <range/v3/all.hpp>
27
28namespace
29{
30 // NOLINTBEGIN
31 auto GetWalkCorrection(double value) -> double
32 {
33 value = value * 17.2278 / 162.464;
34 const auto veronika3 = -4.29359 + 17.3841 / sqrt(value) + 0.073181; // veronika 3
35 const auto veronika2 = 1.59667 + 78.5274 * pow(value, -1.97051) - 4.00192 / value - 0.125473 * value +
36 0.00130958 * value * value; // veronika 2
37 const auto result = (value > 25.0000) ? veronika3 : (veronika3 + veronika2) / 2.;
38 return -1. * result;
39 }
40 // NOLINTEND
41
42} // namespace
43
44namespace R3B::Neuland
45{
46
48 : Map2CalTask{ "NeulandMapped2Cal", 1 }
49 {
50 }
51
52 Map2CalTask::Map2CalTask(std::string_view name, int iVerbose)
53 : CalibrationTask(name.data(), iVerbose)
54 {
55 }
56
58 {
59 const auto total_bar_num = plane_num_ * BarsPerPlane;
60 constexpr auto BINSIZE_TOT = 1000;
61 constexpr auto BINSIZE_LT = 1000;
62 constexpr auto BINSIZE_TIME = 8000;
63 constexpr auto HIST_MAX_TIME = 6000.;
64 constexpr auto HIST_MIN_TIME = -5000.;
65 constexpr auto HIST_MAX_TOT = 600.;
66 constexpr auto HIST_MAX_LT = 2000.;
67
68 histograms.add_hist<TH1D>("module_num", "Counts with module ids", total_bar_num, -0.5, total_bar_num + 0.5);
69 histograms.add_hist<TH1D>("ToT", "Time over threshold", BINSIZE_TOT * 2, 0., BINSIZE_TOT + 0.);
70 histograms.add_hist<TH1D>("LeadingTime", "Leading time", BINSIZE_LT, 0., HIST_MAX_LT);
71 histograms.add_hist<TH1D>("TriggerTime", "Trigger time", BINSIZE_LT, 0., HIST_MAX_LT);
72 histograms.add_hist<TH1D>("Leading_minus_trigger", "Time", BINSIZE_TIME, HIST_MIN_TIME, HIST_MAX_TIME);
73 histograms.add_hist<TH1I>(
74 "Bar_hitNum_l", "Number of hits on the left PMT per bar", total_bar_num, 0.5, 0.5 + total_bar_num);
75 histograms.add_hist<TH1I>(
76 "Bar_hitNum_r", "Number of hits on the right PMT per bar", total_bar_num, 0.5, 0.5 + total_bar_num);
77
78 histograms.add_hist<TH2D>("TimeLVsBar",
79 "Time_vs_bar_left",
80 total_bar_num,
81 0.5,
82 0.5 + total_bar_num,
83 BINSIZE_TIME,
84 HIST_MIN_TIME,
85 HIST_MAX_TIME);
86 histograms.add_hist<TH2D>("TimeRVsBar",
87 "Time_vs_bar_right",
88 total_bar_num,
89 0.5,
90 0.5 + total_bar_num,
91 BINSIZE_TIME,
92 HIST_MIN_TIME,
93 HIST_MAX_TIME);
94
95 histograms.add_hist<TH2D>(
96 "ToTLVsBar", "ToT_vs_bar_left", total_bar_num, 0.5, 0.5 + total_bar_num, BINSIZE_TOT, 0., HIST_MAX_TOT);
97 histograms.add_hist<TH2D>(
98 "ToTRVsBar", "ToT_vs_bar_right", total_bar_num, 0.5, 0.5 + total_bar_num, BINSIZE_TOT, 0., HIST_MAX_TOT);
99 }
100
101 void Map2CalTask::ExtraInit(FairRootManager* /*rootMan*/)
102 {
103 mappedData_.init();
104 trigMappedData_.init();
105 calData_.init(not IsHistDisabled());
106 set_pmt_num();
107 set_ct_freq();
108 }
109
110 void Map2CalTask::set_pmt_num()
111 {
112 if (plane_num_ = base_par_->GetNumOfPlanes(); plane_num_ == 0)
113 {
114 R3BLOG(warn, "plane number obtained from the calibration parameters is 0!");
115 }
116 else
117 {
118 total_pmt_nums_ = 2 * plane_num_ * BarsPerPlane;
119 R3BLOG(info, fmt::format("total number of PMTs set to be {}", total_pmt_nums_).c_str());
120 }
121
122 if (total_pmt_nums_ == 0)
123 {
124 throw R3B::runtime_error("The number of PMTs cannot be zero!");
125 }
126 }
127
128 void Map2CalTask::set_ct_freq()
129 {
130 if (auto ct_freq = calibrationPar_->GetSlowClockFrequency(); ct_freq == 0)
131 {
132 R3BLOG(warn, "Coarse time frequency obtained from parameteers is 0! Use default value.");
133 coarse_time_frequency_ = COARSE_TIME_CLOCK_FREQUENCY_MHZ;
134 }
135 else
136 {
137 coarse_time_frequency_ = ct_freq;
138 max_coarse_time_ = 1000. * coarse_time_max_num_ / coarse_time_frequency_;
139 R3BLOG(info, fmt::format("Coarse time frequency set to be {} MHz", ct_freq).c_str());
140 }
141 }
142
143 auto Map2CalTask::CheckConditions() const -> bool
144 {
145
146 auto signal_size = mappedData_.size();
147 R3BLOG(debug2,
148 fmt::format("Minimal signal size: {}. Current signal size: {}. Number of PMTs: {}",
149 signal_min_size_,
150 signal_size,
151 total_pmt_nums_));
152 if (signal_size < signal_min_size_)
153 {
154 R3BLOG(debug2,
155 fmt::format("condition of the minimal size is not met with current paddle signal size. Skip the "
156 "current event."));
157 return false;
158 }
159 return is_pulse_mode_ ? signal_size > total_pmt_nums_ : signal_size < total_pmt_nums_ / 2;
160 }
161
162 void Map2CalTask::TriggeredExec() { calibrate(); }
163
164 auto Map2CalTask::convert_to_real_time(R3BTCalPar2* calPar,
165 SingleEdgeSignal signal,
166 FTType ftType,
167 unsigned int module_num) const -> ValueError<double>
168 {
169 const auto& modulePar = calPar->GetParamAt(module_num);
170 const auto fineTime = modulePar.GetFineTime(ftType, signal.fine);
171
172 // signal time in ns
173 const auto coarseTime = 1000. / coarse_time_frequency_ * static_cast<float>(signal.coarse + 1);
174 return { coarseTime - fineTime.value, fineTime.error };
175 }
176
177 auto Map2CalTask::get_trigger_time(unsigned int module_num, Side side) const -> ValueError<double>
178 {
179
180 const auto& triggerMap = base_par_->GetTrigIDMap();
181 auto triggerIDPair = triggerMap.find(module_num);
182 if (triggerIDPair == triggerMap.end())
183 {
184 const auto eventNum = GetEventHeader()->GetEventno();
185 R3BLOG(error,
186 fmt::format("Can't find the trigger ID for the module ID {} in the event {}", module_num, eventNum));
187 return { -1., 0 };
188 }
189 const auto triggerID = (side == Side::left) ? triggerIDPair->second.first : triggerIDPair->second.second;
190 const auto trigData = std::find_if(trigMappedData_.begin(),
191 trigMappedData_.end(),
192 [&triggerID](const auto& ele) { return ele.first == triggerID; });
193 if (trigData == trigMappedData_.end())
194 {
195 const auto eventNum = GetEventHeader()->GetEventno();
196 R3BLOG(error,
197 fmt::format("No such trigger ID {} in mappedTrigData for moduleNum {} in the event {}!",
198 triggerID,
199 module_num,
200 eventNum));
201 R3BLOG(error, fmt::format("Available trigIDs: {}", fmt::join(trigMappedData_ | ranges::views::keys, ", ")));
202 return { -1., 0 };
203 }
204 return convert_to_real_time(calibrationTrigPar_, trigData->second.signal, FTType::trigger, trigData->first);
205 }
206
207 auto Map2CalTask::get_tot(DoubleEdgeSignal pmtSignal,
208 unsigned int module_num,
209 Side side) const -> ValueError<double>
210 {
211 const auto leadFType = (side == Side::left) ? FTType::leftleading : FTType::rightleading;
212 const auto trailFType = (side == Side::left) ? FTType::lefttrailing : FTType::righttrailing;
213 const auto leadingT = convert_to_real_time(calibrationPar_, pmtSignal.leading, leadFType, module_num);
214 const auto trailingT = convert_to_real_time(calibrationPar_, pmtSignal.trailing, trailFType, module_num);
215 const auto time_over_thres = trailingT - leadingT;
216 R3BLOG(debug3, fmt::format("leading :{} trailing: {}", leadingT.value, trailingT.value));
217 return (time_over_thres.value > 0) ? time_over_thres : time_over_thres + max_coarse_time_;
218 }
219
220 void Map2CalTask::overflow_correct(R3B::Neuland::CalDataSignal& calSignal) const
221 {
222 // trigger time should come after signal time
223 if (calSignal.leading_time.value > calSignal.trigger_time.value)
224 {
225 calSignal.leading_time -= max_coarse_time_;
226 }
227 }
228
229 auto Map2CalTask::doubleEdgeSignal_to_calSignal(const DoubleEdgeSignal& double_edge_signal,
230 R3B::Side side,
231 unsigned int module_num) const -> CalDataSignal
232 {
233 auto calDataSignal = CalDataSignal{};
234 const auto ftType = (side == R3B::Side::left) ? FTType::leftleading : FTType::rightleading;
235 calDataSignal.time_over_threshold = get_tot(double_edge_signal, module_num, side);
236 const auto walk_correction =
237 (is_walk_enabled_) ? GetWalkCorrection(calDataSignal.time_over_threshold.value) : 0.;
238 calDataSignal.leading_time =
239 convert_to_real_time(calibrationPar_, double_edge_signal.leading, ftType, module_num) + walk_correction;
240 calDataSignal.trigger_time = get_trigger_time(module_num, side);
241 overflow_correct(calDataSignal);
242 R3BLOG(debug, fmt::format("Adding a new cal signal: {}", calDataSignal));
243 return calDataSignal;
244 }
245
246 auto Map2CalTask::mapBarSignal_to_calSignals(const MapBarSignal& map_bar_signals,
247 unsigned int module_num,
248 R3B::Side side) const -> std::vector<CalDataSignal>
249 {
250 const auto& signals = (side == Side::left) ? map_bar_signals.left : map_bar_signals.right;
251 auto calSignals = std::vector<CalDataSignal>{};
252 calSignals.reserve(signals.size());
253 std::transform(signals.begin(),
254 signals.end(),
255 std::back_inserter(calSignals),
256 [module_num, side, this](const auto& dESignal)
257 { return doubleEdgeSignal_to_calSignal(dESignal, side, module_num); });
258 return calSignals;
259 }
260
261 void Map2CalTask::fill_cal_data(BarCalData& cal, const MapBarSignal& signals)
262 {
263 cal.left = mapBarSignal_to_calSignals(signals, cal.module_num, Side::left);
264 cal.right = mapBarSignal_to_calSignals(signals, cal.module_num, Side::right);
265
266 if (not IsHistDisabled())
267 {
268 histogram_monitor(cal, Side::left);
269 histogram_monitor(cal, Side::right);
270 }
271 }
272
273 void Map2CalTask::calibrate()
274 {
275 R3BLOG(debug2, fmt::format("mapped Data size: {}", mappedData_.size()));
276 for (const auto& planeSignals : mappedData_)
277 {
278 const auto planeNum = planeSignals.plane_num;
279 for (const auto& [barNum, barSignals] : planeSignals.bars)
280 {
281 if (not IsHistDisabled())
282 {
283 GetHistMonitor().get("module_num")->Fill(barNum);
284 }
285 const auto module_num = Neuland_PlaneBar2ModuleNum(planeNum, barNum);
286 auto& cal = calData_.get().emplace_back(module_num);
287 fill_cal_data(cal, barSignals);
288 }
289 }
290 }
291
292 void Map2CalTask::histogram_monitor(const BarCalData& cal, Side side)
293 {
294 auto& histograms = GetHistMonitor();
295 const auto module_num = cal.module_num;
296 const auto& calSignals = (side == Side::left) ? cal.left : cal.right;
297
298 for (const auto& signal : calSignals)
299 {
300 const auto lTime = signal.leading_time.value;
301 const auto time_over_thres = signal.time_over_threshold.value;
302 const auto triggerTime = signal.trigger_time.value;
303 histograms.get("ToT")->Fill(time_over_thres);
304 histograms.get("LeadingTime")->Fill(lTime);
305 histograms.get("TriggerTime")->Fill(triggerTime);
306 histograms.get("Leading_minus_trigger")->Fill(lTime - triggerTime);
307 if (side == Side::left)
308 {
309 histograms.get("TimeLVsBar")->Fill(module_num, lTime - triggerTime);
310 histograms.get("ToTLVsBar")->Fill(module_num, time_over_thres);
311 histograms.get("Bar_hitNum_l")->Fill(module_num);
312 }
313 else
314 {
315 histograms.get("TimeRVsBar")->Fill(module_num, lTime - triggerTime);
316 histograms.get("ToTRVsBar")->Fill(module_num, time_over_thres);
317 histograms.get("Bar_hitNum_r")->Fill(module_num);
318 }
319 }
320 }
321
323} // namespace R3B::Neuland
#define R3BLOG(severity, x)
Definition R3BLogger.h:35
R3B::Map2CalPar R3BTCalPar2
Side
Definition R3BShared.h:105
auto add_hist(std::unique_ptr< TH1 > hist) -> TH1 *
void HistogramInit(DataMonitor &histograms) override
auto CheckConditions() const -> bool override
void ExtraInit(FairRootManager *rootMan) override
Simulation of NeuLAND Bar/Paddle.
constexpr auto COARSE_TIME_CLOCK_FREQUENCY_MHZ
constexpr auto BarsPerPlane
constexpr auto Neuland_PlaneBar2ModuleNum(unsigned int planeNum, unsigned int barNum) -> unsigned int
ValueError< double > trigger_time
ValueError< double > leading_time