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 "R3BDataMonitor.h"
16#include "R3BNeulandCalData2.h"
18#include "R3BNeulandCommon.h"
21#include "R3BShared.h"
22#include "R3BValueError.h"
23#include <FairRootManager.h>
24#include <R3BEventHeader.h>
25#include <R3BException.h>
26#include <TH1.h>
27#include <TH2.h>
28#include <algorithm>
29#include <cmath>
30#include <fairlogger/Logger.h>
31#include <fmt/core.h>
32#include <fmt/format.h>
33#include <iterator>
34#include <range/v3/view/map.hpp>
35#include <string_view>
36#include <vector>
37
38namespace
39{
40 // NOLINTBEGIN
41 auto GetWalkCorrection(double value) -> double
42 {
43 value = value * 17.2278 / 162.464;
44 const auto veronika3 = -4.29359 + 17.3841 / sqrt(value) + 0.073181; // veronika 3
45 const auto veronika2 = 1.59667 + 78.5274 * pow(value, -1.97051) - 4.00192 / value - 0.125473 * value +
46 0.00130958 * value * value; // veronika 2
47 const auto result = (value > 25.0000) ? veronika3 : (veronika3 + veronika2) / 2.;
48 return -1. * result;
49 }
50 // NOLINTEND
51
52} // namespace
53
54namespace R3B::Neuland
55{
56 // NOLINTNEXTLINE
57 Map2CalTask::Map2CalTask(std::string_view map_data_name,
58 std::string_view trig_map_data_name,
59 std::string_view par_name,
60 std::string_view trig_par_name,
61 std::string_view cal_data_name)
62 : CalibrationTask("NeulandMap2CalTask", 1)
63 , map_data_{ map_data_name }
64 , trig_map_data_{ trig_map_data_name }
65 , cal_data_{ cal_data_name }
66 , calibration_par_{ par_name }
67 , calibration_trig_par_{ trig_par_name }
68 {
69 }
70
71 void Map2CalTask::SetExtraPar(FairRuntimeDb* /*rtdb*/)
72 {
73 calibration_par_.init(this);
74 calibration_trig_par_.init(this);
75 }
76
78 {
79 const auto total_bar_num = plane_num_ * BarsPerPlane;
80 constexpr auto BINSIZE_TOT = 1000;
81 constexpr auto BINSIZE_LT = 1000;
82 constexpr auto BINSIZE_TIME = 8000;
83 constexpr auto HIST_MAX_TIME = 6000.;
84 constexpr auto HIST_MIN_TIME = -5000.;
85 constexpr auto HIST_MAX_TOT = 600.;
86 constexpr auto HIST_MAX_LT = 2000.;
87
88 histograms.add_hist<TH1D>("module_num", "Counts with module ids", total_bar_num, -0.5, total_bar_num + 0.5);
89 histograms.add_hist<TH1D>("ToT", "Time over threshold", BINSIZE_TOT * 2, 0., BINSIZE_TOT + 0.);
90 histograms.add_hist<TH1D>("LeadingTime", "Leading time", BINSIZE_LT, 0., HIST_MAX_LT);
91 histograms.add_hist<TH1D>("TriggerTime", "Trigger time", BINSIZE_LT, 0., HIST_MAX_LT);
92 histograms.add_hist<TH1D>("Leading_minus_trigger", "Time", BINSIZE_TIME, HIST_MIN_TIME, HIST_MAX_TIME);
93 histograms.add_hist<TH1I>(
94 "Bar_hitNum_l", "Number of hits on the left PMT per bar", total_bar_num, 0.5, 0.5 + total_bar_num);
95 histograms.add_hist<TH1I>(
96 "Bar_hitNum_r", "Number of hits on the right PMT per bar", total_bar_num, 0.5, 0.5 + total_bar_num);
97
98 histograms.add_hist<TH2D>("TimeLVsBar",
99 "Time_vs_bar_left",
100 total_bar_num,
101 0.5,
102 0.5 + total_bar_num,
103 BINSIZE_TIME,
104 HIST_MIN_TIME,
105 HIST_MAX_TIME);
106 histograms.add_hist<TH2D>("TimeRVsBar",
107 "Time_vs_bar_right",
108 total_bar_num,
109 0.5,
110 0.5 + total_bar_num,
111 BINSIZE_TIME,
112 HIST_MIN_TIME,
113 HIST_MAX_TIME);
114
115 histograms.add_hist<TH2D>(
116 "ToTLVsBar", "ToT_vs_bar_left", total_bar_num, 0.5, 0.5 + total_bar_num, BINSIZE_TOT, 0., HIST_MAX_TOT);
117 histograms.add_hist<TH2D>(
118 "ToTRVsBar", "ToT_vs_bar_right", total_bar_num, 0.5, 0.5 + total_bar_num, BINSIZE_TOT, 0., HIST_MAX_TOT);
119 }
120
121 void Map2CalTask::ExtraInit(FairRootManager* /*rootMan*/)
122 {
123 map_data_.init();
124 trig_map_data_.init();
125 cal_data_.init(not IsHistDisabled());
126 set_pmt_num();
127 set_ct_freq();
128 }
129
131 {
132 if (plane_num_ = GetBasePar()->get_num_of_planes(); plane_num_ == 0)
133 {
134 LOGP(warn, "plane number obtained from the calibration parameters is 0!");
135 }
136 else
137 {
139 LOGP(info, "total number of PMTs set to be {}", total_pmt_nums_);
140 }
141
142 if (total_pmt_nums_ == 0)
143 {
144 throw R3B::runtime_error("The number of PMTs cannot be zero!");
145 }
146 }
147
149 {
150 if (auto ct_freq = calibration_par_->GetSlowClockFrequency(); ct_freq == 0)
151 {
152 LOGP(warn, "Coarse time frequency obtained from parameteers is 0! Use default value.");
154 }
155 else
156 {
157 coarse_time_frequency_ = ct_freq;
159 LOGP(info, "Coarse time frequency set to be {} MHz", ct_freq);
160 }
161 }
162
163 auto Map2CalTask::CheckConditions() const -> bool
164 {
165
166 auto signal_size = map_data_.size();
167 LOGP(debug2,
168 "Minimal signal size: {}. Current signal size: {}. Number of PMTs: {}",
170 signal_size,
172 if (signal_size < signal_min_size_)
173 {
174 LOGP(debug2,
175 "condition of the minimal size is not met with current paddle signal size. Skip the "
176 "current event.");
177 return false;
178 }
179 return is_pulse_mode_ ? signal_size > total_pmt_nums_ : signal_size < total_pmt_nums_ / 2;
180 }
181
183
185 SingleEdgeSignal signal,
186 FTType ftType,
187 int module_num) const -> ValueError<double>
188 {
189 const auto& modulePar = calPar->GetParamAt(module_num);
190 const auto fineTime = modulePar.GetFineTime(ftType, signal.fine);
191
192 // signal time in ns
193 const auto coarseTime = 1000. / coarse_time_frequency_ * static_cast<float>(signal.coarse + 1);
194 return { coarseTime - fineTime.value, fineTime.error };
195 }
196
197 auto Map2CalTask::get_trigger_time(int module_num, Side side) const -> ValueError<double>
198 {
199
200 const auto& triggerMap = GetBasePar()->get_trig_id_map();
201 auto triggerIDPair = triggerMap.find(module_num);
202 if (triggerIDPair == triggerMap.end())
203 {
204 const auto eventNum = GetEventHeader()->GetEventno();
205 LOGP(error, "Can't find the trigger ID for the module ID {} in the event {}", module_num, eventNum);
206 return { -1., 0 };
207 }
208 const auto triggerID = (side == Side::left) ? triggerIDPair->second.first : triggerIDPair->second.second;
209 const auto trigData = std::find_if(trig_map_data_.begin(),
210 trig_map_data_.end(),
211 [&triggerID](const auto& ele) { return ele.first == triggerID; });
212 if (trigData == trig_map_data_.end())
213 {
214 const auto eventNum = GetEventHeader()->GetEventno();
215 LOGP(error,
216 "No such trigger ID {} in mappedTrigData for moduleNum {} in the event {}!",
217 triggerID,
218 module_num,
219 eventNum);
220 LOGP(error, "Available trigIDs: {}", fmt::join(trig_map_data_ | ranges::views::keys, ", "));
221 return { -1., 0 };
222 }
224 calibration_trig_par_.get(), trigData->second.signal, FTType::trigger, trigData->first);
225 }
226
228 int module_num,
229 R3B::Side module_side) const -> ValueError<double>
230 {
231 const auto leadFType = (module_side == Side::left) ? FTType::leftleading : FTType::rightleading;
232 const auto trailFType = (module_side == Side::left) ? FTType::lefttrailing : FTType::righttrailing;
233 const auto leadingT = convert_to_real_time(calibration_par_.get(), pmtSignal.leading, leadFType, module_num);
234 const auto trailingT = convert_to_real_time(calibration_par_.get(), pmtSignal.trailing, trailFType, module_num);
235 const auto time_over_thres = trailingT - leadingT;
236 LOGP(debug3, "leading :{} trailing: {}", leadingT.value, trailingT.value);
237 return (time_over_thres.value > 0) ? time_over_thres : time_over_thres + max_coarse_time_;
238 }
239
241 {
242 // trigger time should come after signal time
243 if (calSignal.leading_time.value > calSignal.trigger_time.value)
244 {
245 calSignal.leading_time -= max_coarse_time_;
246 }
247 }
248
250 R3B::Side side,
251 int module_num) const -> CalDataSignal
252 {
253 auto calDataSignal = CalDataSignal{};
254 const auto ftType = (side == R3B::Side::left) ? FTType::leftleading : FTType::rightleading;
255 calDataSignal.time_over_threshold = get_tot(double_edge_signal, module_num, side);
256 const auto walk_correction =
257 (is_walk_enabled_) ? GetWalkCorrection(calDataSignal.time_over_threshold.value) : 0.;
258 calDataSignal.leading_time =
259 convert_to_real_time(calibration_par_.get(), double_edge_signal.leading, ftType, module_num) +
260 walk_correction;
261 calDataSignal.trigger_time = get_trigger_time(module_num, side);
262 overflow_correct(calDataSignal);
263 LOGP(debug, "Adding a new cal signal: {}", calDataSignal);
264 return calDataSignal;
265 }
266
268 int module_num,
269 R3B::Side side) const -> std::vector<CalDataSignal>
270 {
271 const auto& signals = (side == Side::left) ? map_bar_signals.left : map_bar_signals.right;
272 auto calSignals = std::vector<CalDataSignal>{};
273 calSignals.reserve(signals.size());
274 std::transform(signals.begin(),
275 signals.end(),
276 std::back_inserter(calSignals),
277 [module_num, side, this](const auto& dESignal)
278 { return doubleEdgeSignal_to_calSignal(dESignal, side, module_num); });
279 return calSignals;
280 }
281
283 {
286
287 if (not IsHistDisabled())
288 {
291 }
292 }
293
295 {
296 LOGP(debug2, "mapped Data size: {}", map_data_.size());
297
298 if (trig_map_data_.size() == 0)
299 {
300 return;
301 }
302 for (const auto& [plane_num, plane_signals] : map_data_)
303 {
304 for (const auto& [bar_num, bar_signals] : plane_signals.bars)
305 {
306 if (not IsHistDisabled())
307 {
308 GetHistMonitor().get("module_num")->Fill(bar_num);
309 }
310 const auto module_num = Neuland_PlaneBar2ModuleNum(plane_num, bar_num);
311 auto& cal = cal_data_.get().emplace_back(module_num);
312 fill_cal_data(cal, bar_signals);
313 }
314 }
315 }
316
318 {
319 auto& histograms = GetHistMonitor();
320 const auto module_num = cal.module_num;
321 const auto& calSignals = (side == Side::left) ? cal.left : cal.right;
322
323 for (const auto& signal : calSignals)
324 {
325 const auto lTime = signal.leading_time.value;
326 const auto time_over_thres = signal.time_over_threshold.value;
327 const auto triggerTime = signal.trigger_time.value;
328 histograms.get("ToT")->Fill(time_over_thres);
329 histograms.get("LeadingTime")->Fill(lTime);
330 histograms.get("TriggerTime")->Fill(triggerTime);
331 histograms.get("Leading_minus_trigger")->Fill(lTime - triggerTime);
332 if (side == Side::left)
333 {
334 histograms.get("TimeLVsBar")->Fill(module_num, lTime - triggerTime);
335 histograms.get("ToTLVsBar")->Fill(module_num, time_over_thres);
336 histograms.get("Bar_hitNum_l")->Fill(module_num);
337 }
338 else
339 {
340 histograms.get("TimeRVsBar")->Fill(module_num, lTime - triggerTime);
341 histograms.get("ToTRVsBar")->Fill(module_num, time_over_thres);
342 histograms.get("Bar_hitNum_r")->Fill(module_num);
343 }
344 }
345 }
346
348} // namespace R3B::Neuland
R3B::Map2CalPar R3BTCalPar2
auto add_hist(std::unique_ptr< TH1 > hist) -> TH1 *
void HistogramInit(DataMonitor &histograms) override
Map2CalTask(std::string_view map_data_name="NeulandMapData", std::string_view trig_map_data_name="NeulandTrigMapData", std::string_view par_name="LandTCalPar", std::string_view trig_par_name="LandTrigTCalPar", std::string_view cal_data_name="NeulandCalData")
auto mapBarSignal_to_calSignals(const MapBarSignal &map_bar_signals, int module_num, R3B::Side side) const -> std::vector< CalDataSignal >
OutputVectorConnector< BarCalData > cal_data_
auto CheckConditions() const -> bool override
auto convert_to_real_time(R3BTCalPar2 *calPar, SingleEdgeSignal signal, FTType ftType, int module_num) const -> ValueError< double >
InputMapConnector< int, PaddleTamexMappedData > map_data_
auto get_trigger_time(int module_num, Side side) const -> ValueError< double >
InputMapConnector< int, PaddleTamexTrigMappedData > trig_map_data_
void overflow_correct(R3B::Neuland::CalDataSignal &calSignal) const
auto doubleEdgeSignal_to_calSignal(const DoubleEdgeSignal &double_edge_signal, R3B::Side side, int module_num) const -> CalDataSignal
void ExtraInit(FairRootManager *rootMan) override
void fill_cal_data(BarCalData &cal, const MapBarSignal &signals)
void SetExtraPar(FairRuntimeDb *rtdb) override
InputParView< Map2CalPar > calibration_par_
auto get_tot(const DoubleEdgeSignal &pmtSignal, int module_num, R3B::Side module_side) const -> ValueError< double >
void histogram_monitor(const BarCalData &cal, Side side)
InputParView< Map2CalPar > calibration_trig_par_
Simulation of NeuLAND Bar/Paddle.
constexpr auto COARSE_TIME_CLOCK_FREQUENCY_MHZ
constexpr auto BarsPerPlane
constexpr auto Neuland_PlaneBar2ModuleNum(int planeNum, int barNum) -> int
std::vector< CalDataSignal > left
std::vector< CalDataSignal > right
ValueError< double > trigger_time
ValueError< double > leading_time