R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
R3BNeulandMillepede.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
14#include "R3BNeulandMillepede.h"
15#include "Mille.h"
16#include "ParResultReader.h"
17#include "PedeLauncher.h"
18#include "R3BDataMonitor.h"
19#include "R3BNeulandCalData2.h"
22#include <R3BException.h>
24#include <R3BNeulandCommon.h>
26#include <SteerWriter.h>
27
28#include <TGraphErrors.h>
29#include <TH1.h>
30#include <algorithm>
31#include <array>
32#include <chrono>
33#include <cmath>
34#include <cstdint>
35#include <cstdlib>
36#include <fairlogger/Logger.h>
37#include <filesystem>
38#include <fmt/core.h>
39#include <fmt/format.h>
40#include <functional>
41#include <iterator>
42#include <magic_enum/magic_enum.hpp>
43#include <memory>
44#include <numeric>
45#include <optional>
46#include <range/v3/algorithm/all_of.hpp>
47#include <range/v3/algorithm/copy.hpp>
48#include <range/v3/algorithm/max.hpp>
49#include <range/v3/algorithm/min_element.hpp>
50#include <range/v3/iterator/operations.hpp>
51#include <range/v3/numeric/accumulate.hpp>
52#include <range/v3/view/all.hpp>
53#include <range/v3/view/drop.hpp>
54#include <range/v3/view/filter.hpp>
55#include <range/v3/view/iota.hpp>
56#include <range/v3/view/join.hpp>
57#include <range/v3/view/map.hpp>
58#include <range/v3/view/repeat.hpp>
59#include <range/v3/view/sliding.hpp>
60#include <range/v3/view/take.hpp>
61#include <range/v3/view/transform.hpp>
62#include <stdexcept>
63#include <string>
64#include <string_view>
65#include <utility>
66#include <vector>
67
68// #define TWO_PAR
69
70namespace rng = ranges;
71
72constexpr auto DEFAULT_RES_FILENAME = "millepede.res";
73constexpr auto DEFAULT_RES_JSON_FILENAME = "millepede.res.json";
74constexpr auto SCALE_FACTOR = 10.F;
75// constexpr auto REFERENCE_BAR_NUM = 25;
76constexpr auto MILLE_BUFFER_SIZE = std::size_t{ 100000 };
77constexpr auto DEFAULT_T_ERROR = 2; // ns
78
79namespace
80{
81 enum class FilterEvent : uint8_t
82 {
83 after_trigger,
84 n_plane_filter,
85 };
86 void calculate_time_offset(R3B::Neuland::Cal2HitPar& cal_to_hit_par)
87 {
88 auto& module_pars = cal_to_hit_par.GetListOfModuleParRef();
89 for (auto& [module_num, module_par] : module_pars)
90 {
91 if (module_par.effective_speed.value != 0)
92 {
93 module_par.t_diff = module_par.t_diff / module_par.effective_speed;
94 }
95 }
96 }
97
98 void change_time_offset(R3B::Neuland::Cal2HitPar& cal_to_hit_par)
99 {
100 auto& module_pars = cal_to_hit_par.GetListOfModuleParRef();
101 for (auto& [module_num, module_par] : module_pars)
102 {
103 module_par.t_diff = module_par.t_diff * module_par.effective_speed;
104 }
105 }
106
107 template <typename T, typename U>
108 void vector_zip_action(const T& data, U&& unitary_action)
109 {
110 namespace sr = ranges;
111 namespace sv = ranges::views;
112 const auto max_size = sr::max(data | sv::transform([](const auto& vec) -> auto { return vec.size(); }));
113 static constexpr auto nth_element = [](auto& vec, const int n) -> auto
114 { return sv::repeat(vec) | sv::join | sv::drop(n) | sv::take(1); };
115
116 for (const auto index : sv::iota(std::size_t{ 0 }, max_size))
117 {
118 auto zip_view = data | sv::filter([](const auto& vec) -> auto { return not vec.empty(); }) |
119 sv::transform([index](auto&& vec) -> auto { return nth_element(vec, index); }) | sv::join;
120 std::forward<U>(unitary_action)(zip_view);
121 }
122 }
123
124 namespace sv = ranges::views;
125} // namespace
126
128{
129 void MillepedeEngine::set_options(const MillepedeOptions& options) { config_ = options; }
130
132 {
134 if (config_.enable_data_write)
135 {
136 output_mille_data_.init();
139 }
140 fs::create_directories(fs::path(working_dir_));
141 cal_to_hit_par_ = GetTask()->GetCal2HitPar();
142
143 par_result_.set_filename((fs::path(working_dir_) / DEFAULT_RES_FILENAME).string());
144 pede_launcher_.set_steer_filename(pede_steer_filename_);
145 pede_launcher_.set_parameter_filename(config_.pede_par_filename);
146 if (const auto* r3b_dir = std::getenv("R3BROOTPATH"); r3b_dir != nullptr)
147 {
148 pede_launcher_.set_binary_dir(fmt::format("{}/bin", r3b_dir));
149 // TODO: make subdir configurable
150 pede_launcher_.set_working_dir(fs::absolute(fs::path{ working_dir_ }).string());
151 }
152 else
153 {
154 throw R3B::runtime_error(
155 "Environment variable R3BROOTPATH is not defined! Did you forget to source the \"config.sh\" file?");
156 }
158 std::make_unique<Mille>((fs::path{ working_dir_ } / config_.mille_data_filename).string());
159 binary_data_writer_->set_buffer_size(MILLE_BUFFER_SIZE);
160 data_preprocessor_ = std::make_unique<MilleDataProcessor>(GetModuleSize());
161 data_preprocessor_->set_p_value_cut(config_.p_value_cut);
162
165 }
166
168 {
169 const auto filename = FairRun::Instance()->GetSink()->GetFileName();
170 const auto output_dir = fs::path{ filename.View() }.parent_path();
171 const auto time_now = std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now());
172 const auto output_folder_name =
173 config_.outdir_has_timestamp ? fmt::format("{:%Y-%m-%d_%H-%M-%S}", time_now) : "output";
174
175 working_dir_ = (output_dir / DEFAULT_SUB_DIR / output_folder_name);
176 LOGP(debug, "Working dir has set to be: {}", working_dir_);
177 }
178
179 // output: module_num & global label
180 inline auto MillepedeEngine::to_module_num_label(int par_num) -> std::pair<int, GlobalLabel>
181 {
182 const auto num_of_module = GetModuleSize();
183 auto res = std::pair<int, GlobalLabel>{};
184 res.first = ((par_num - 1) % num_of_module) + 1;
185
187 {
188 res.second = GlobalLabel::tsync;
189 }
191 {
192 const auto factor = (par_num - 1) / num_of_module;
193 switch (factor)
194 {
195 case 0:
197 break;
198 case 1:
199 res.second = GlobalLabel::effective_c;
200 break;
201 default:
202 throw R3B::logic_error(
203 fmt::format("An error occurred with unrecognized global par id: {}", par_num));
204 }
205 }
206 else
207 {
208 throw R3B::logic_error(
209 fmt::format("cal mode {} is not implemented!", magic_enum::enum_name(config_.cal_mode)));
210 }
211
212 return res;
213 }
214
215 inline auto MillepedeEngine::get_global_label_id(int module_num, GlobalLabel label) -> int
216 {
217 const auto num_of_module = GetModuleSize();
218
220 {
221 return module_num;
222 }
224 {
225 switch (label)
226 {
228 return module_num;
230 return module_num + num_of_module;
231 default:
232 }
233 }
234 throw R3B::logic_error(fmt::format("cal mode {} is not implemented!", magic_enum::enum_name(config_.cal_mode)));
235 }
236
238 Neuland::Cal2HitPar& cal_to_hit_par)
239 {
240 // this changes the t_diff value to the product of t_diff and speed.
242 {
243 change_time_offset(cal_to_hit_par);
244 }
245
246 const auto& pars = result.get_pars();
247 for (const auto& [par_id, par] : pars)
248 {
249 const auto [module_num, global_label] = to_module_num_label(par_id);
250 auto& module_pars = cal_to_hit_par.GetListOfModuleParRef();
251
252 auto& par_ref = module_pars.emplace(module_num, HitModulePar{}).first->second;
254 {
255 if (module_num == DEFAULT_TSYNC_REFERENCE_BAR_NUM)
256 {
257 par_ref.t_sync.value = DEFAULT_TSYNC_REFERENCE_BAR_VALUE;
258 par_ref.t_sync.error = 0.;
259 }
260 else
261 {
262 par_ref.t_sync.value += par.value * SCALE_FACTOR;
263 par_ref.t_sync.error = par.error * SCALE_FACTOR;
264 }
265 }
267 {
268 switch (global_label)
269 {
271 // NOTE: The value here is the product of tDiff and effectiveSped. Real tDiff will be calculated
272 // later
273 par_ref.t_diff.value += par.value * SCALE_FACTOR;
274 par_ref.t_diff.error = par.error * SCALE_FACTOR;
275 break;
277 par_ref.effective_speed.value += par.value;
278 par_ref.effective_speed.error = par.error;
279 break;
280 default:
281 throw std::runtime_error("An error occurred with unrecognized global tag");
282 }
283 }
284 else
285 {
286 throw R3B::logic_error(
287 fmt::format("cal mode {} is not implemented!", magic_enum::enum_name(config_.cal_mode)));
288 }
289 }
290
292 {
293 calculate_time_offset(cal_to_hit_par);
294 }
295 }
296
297 auto MillepedeEngine::set_minimum_values(const std::vector<R3B::Neuland::BarCalData>& signals) -> bool
298 {
299 // make sure only one hit exists in one bar
300 auto filtered_signals =
301 rng::filter_view(signals | rng::views::all,
302 [](const auto& bar_signal) -> auto
303 { return bar_signal.left.size() == 1 and bar_signal.right.size() == 1; });
304 if (filtered_signals.empty())
305 {
306 return false;
307 }
308
309 if (not average_t_sum_.has_value())
310 {
311 auto t_sum_view = filtered_signals | rng::views::transform(
312 [](const auto& bar_signal) -> auto
313 {
314 const auto& left_signal = bar_signal.left.front();
315 const auto& right_signal = bar_signal.right.front();
316 return (left_signal.leading_time - left_signal.trigger_time +
317 right_signal.leading_time - right_signal.trigger_time)
318 .value;
319 });
320 auto sum = rng::accumulate(t_sum_view, 0.F);
321 average_t_sum_ = sum / static_cast<float>(rng::distance(t_sum_view.begin(), t_sum_view.end()));
322 LOGP(info, "Average t_sum is calculated to be {}", average_t_sum_.value());
323 }
324 return true;
325 }
326
327 auto MillepedeEngine::SignalFilter(const std::vector<BarCalData>& signals) -> bool
328 {
329 const auto n_plane = GetTask()->GetBasePar()->get_num_of_planes();
330 plane_counter_.clear();
331 plane_counter_.resize(n_plane, 0);
332
333 // select out events with less plane hits
334 for (const auto& bar_data : signals)
335 {
336 if (bar_data.left.size() != bar_data.right.size())
337 {
338 continue;
339 }
340 if (bar_data.left.size() != 1)
341 {
342 continue;
343 }
344 const auto module_num = bar_data.module_num;
345 const auto plane_id = Common::ModuleID2PlaneID(module_num - 1);
346 ++plane_counter_.at(plane_id);
347 }
348 const auto n_hit_plane = std::ranges::count_if(plane_counter_, [](auto val) -> bool { return val != 0; });
349 hist_plane_hit_num_->Fill(static_cast<double>(n_hit_plane));
350 if (n_hit_plane < config_.min_plane_num)
351 {
352 return false;
353 }
354
355 if (not set_minimum_values(signals))
356 {
357 return false;
358 }
359
360 return true;
361 }
362
363 auto MillepedeEngine::add_signal_t_sum(const MilleCalData& signal, const TrackFitResult& fit_coeff) -> float
364 {
365 buffer_clear();
366
367 const auto x_z_slope = fit_coeff.x_z.slope;
368 const auto y_z_slope = fit_coeff.y_z.slope;
369 const auto a_z = std::sqrt(1 + (x_z_slope * x_z_slope) + (y_z_slope * y_z_slope)) / CLight;
370 const auto sign_factor = (y_z_slope > 0.) ? 1. : -1.;
371
372 const auto module_num = static_cast<int>(signal.module_num);
373 const auto pos_z = ModuleNum2ZPos<float>(static_cast<int>(module_num));
374
375 const auto init_effective_c = cal_to_hit_par_->GetModuleParAt(module_num).effective_speed.value;
376 const auto init_t_sync = (module_num == DEFAULT_TSYNC_REFERENCE_BAR_NUM)
378 : cal_to_hit_par_->GetModuleParAt(module_num).t_sync.value;
379
380 const auto& left_signal = signal.left;
381 const auto& right_signal = signal.right;
382 const auto t_sum = (left_signal.leading_time - left_signal.trigger_time) +
383 (right_signal.leading_time - right_signal.trigger_time) - average_t_sum_.value_or(0.F);
384
385 auto meas = static_cast<float>((t_sum.value / 2.F) + (sign_factor * pos_z * a_z) -
386 (BarLength / init_effective_c / 2.F) - init_t_sync) /
388 // auto meas = static_cast<float>((t_sum.value / 2.F) + (sign_factor * pos_z * a_z) +
389 // (BarLength / init_effective_c) - init_t_sync) /
390 // SCALE_FACTOR;
391 input_data_buffer_.measurement = meas;
392 input_data_buffer_.sigma = static_cast<float>(t_sum.error / SCALE_FACTOR / 2. * config_.scale_factor);
393
394 const auto local_derivs_t = std::array{ 1.F };
395#ifdef HAS_CPP_STANDARD_17
396 std::copy(local_derivs_t.begin(), local_derivs_t.end(), std::back_inserter(input_data_buffer_.locals));
397#else
398 ranges::copy(local_derivs_t, std::back_inserter(input_data_buffer_.locals));
399#endif
400 input_data_buffer_.globals.emplace_back(get_global_label_id(module_num, GlobalLabel::tsync), 1.F);
401
403 return meas;
404 }
405
406 void MillepedeEngine::add_spacial_local_constraint(int plane_id, const std::vector<MilleCalData>& plane_signals)
407 {
408 buffer_clear();
409 const auto pos_z = PlaneID2ZPos<float>(plane_id);
410 const auto is_horizontal = IsPlaneIDHorizontal(plane_id);
411 // const auto pos_bar_vert_disp = GetBarVerticalDisplacement(module_num);
412 auto n_not_outlier = 0;
413 auto pos_bar_vert_disp = std::accumulate(plane_signals.begin(),
414 plane_signals.end(),
415 0.,
416 [this, &n_not_outlier](double sum, const auto& signal) -> double
417 {
418 if (data_preprocessor_->check_is_outlier(signal.module_num))
419 {
420 return 0.;
421 }
422 ++n_not_outlier;
423 return sum + GetBarVerticalDisplacement(signal.module_num);
424 });
425 if (n_not_outlier == 0)
426 {
427 LOGP(debug, "no valid constraint found in event id: {}", GetTask()->GetEventHeader()->GetEventno());
428 return;
429 }
430 pos_bar_vert_disp /= n_not_outlier;
431 const auto local_derivs = std::array{ pos_z / SCALE_FACTOR, 1.F };
432
433 input_data_buffer_.measurement = static_cast<float>(pos_bar_vert_disp / SCALE_FACTOR);
434 input_data_buffer_.sigma = static_cast<float>(BarSize_XY / SQRT_12 / SCALE_FACTOR * n_not_outlier);
435
436#ifdef HAS_CPP_STANDARD_17
437 std::copy(local_derivs.begin(), local_derivs.end(), std::back_inserter(input_data_buffer_.locals));
438#else
439 ranges::copy(local_derivs, std::back_inserter(input_data_buffer_.locals));
440#endif
441 write_to_buffer();
442 }
443
445 {
446 buffer_clear();
447 const auto module_num = static_cast<int>(signal.module_num);
448 const auto plane_id = ModuleID2PlaneID(static_cast<int>(module_num) - 1);
449 const auto is_horizontal = IsPlaneIDHorizontal(plane_id);
450 const auto& module_par = cal_to_hit_par_->GetModuleParAt(module_num);
451 const auto init_effective_c = module_par.effective_speed.value;
452 const auto init_t_offset = module_par.t_diff.value;
453 const auto pos_z = static_cast<float>(PlaneID2ZPos(plane_id));
454
455 const auto& left_signal = signal.left;
456 const auto& right_signal = signal.right;
457 const auto t_diff = (right_signal.leading_time - right_signal.trigger_time) -
458 (left_signal.leading_time - left_signal.trigger_time);
459
460 const auto t_error = t_diff.error == 0 ? DEFAULT_T_ERROR : t_diff.error;
461 input_data_buffer_.measurement = static_cast<float>((init_effective_c * init_t_offset / 2. / SCALE_FACTOR) -
462 (init_effective_c * t_diff.value / SCALE_FACTOR / 2.));
463 input_data_buffer_.sigma =
464 static_cast<float>(t_error / SCALE_FACTOR / 2. * std::abs(init_effective_c) * config_.scale_factor);
465 const auto local_derivs = std::array{ pos_z / SCALE_FACTOR, 1.F };
466 ranges::copy(local_derivs, std::back_inserter(input_data_buffer_.locals));
468 -0.5F);
469 input_data_buffer_.globals.emplace_back(get_global_label_id(module_num, GlobalLabel::effective_c),
470 static_cast<float>(t_diff.value / SCALE_FACTOR / 2.));
471
473 LOGP(debug,
474 "Writing Mille data to binary file with meas = {} and z = {}",
475 input_data_buffer_.measurement,
476 pos_z);
477 }
478
479 auto MillepedeEngine::select_t_sync_signal(const std::vector<MilleCalData>& plane_data)
480 {
481 auto iter = ranges::min_element(plane_data, std::less{}, &MilleCalData::residual);
482 if (iter != plane_data.end())
483 {
484 auto residual = iter->residual;
485 hist_t_offset_residual_->Fill(residual);
486 if (residual > config_.t_diff_residual_cut)
487 {
488 return plane_data.end();
489 }
490 // fmt::println("selected signal residual: {}", residual);
491 }
492 return iter;
493 }
494
495 template <>
497 const DataBufferType& processed_data,
498 const TrackFitResult& fit_coeff)
499 {
500 const auto is_xz_flat = std::abs(fit_coeff.x_z.slope) < std::abs(config_.max_abs_a_xz);
501 const auto is_yz_flat = std::abs(fit_coeff.y_z.slope) < std::abs(config_.max_abs_a_yz);
502 auto add_to_constraints = [this, &processed_data](bool is_x_z) -> void
503 {
504 for (const auto& [plane_id, plane_signals] :
505 processed_data | rng::views::filter(
506 [is_x_z](const auto& planeid_signals) -> auto
507 {
508 return (not planeid_signals.second.empty()) and
509 (IsPlaneIDHorizontal(planeid_signals.first) != is_x_z);
510 }))
511 {
512 add_spacial_local_constraint(plane_id, plane_signals);
513 }
514 };
515 for (const auto& [plane_id, plane_signals] :
516 processed_data | rng::views::filter([](const auto& planeid_signals) -> auto
517 { return not planeid_signals.second.empty(); }))
518 {
519 const auto is_horizontal = IsPlaneIDHorizontal(plane_id);
520 if (not(is_horizontal ? is_xz_flat : is_yz_flat))
521 {
522 continue;
523 }
524 for (const auto& signal : plane_signals)
525 {
526 add_signal_t_diff(signal);
527 add_to_constraints(is_horizontal);
528 binary_data_writer_->end();
529 }
530 }
531 if (config_.enable_data_write)
532 {
533 for (const auto& bar_signal : processed_data | sv::values | sv::join)
534 {
535 output_mille_data_.get().push_back(bar_signal);
536 }
537 }
538 }
539
540 template <>
542 const TrackFitResult& fit_coeff)
543 {
544 for (const auto& [plane_id, plane_signals] :
545 processed_data | rng::views::filter([](const auto& planeid_signals) -> auto
546 { return not planeid_signals.second.empty(); }))
547 {
548 auto iter = select_t_sync_signal(plane_signals);
549 if (iter == plane_signals.end())
550 {
551 continue;
552 }
553 auto mille_data = *iter;
554 mille_data.tsync_meas = add_signal_t_sum(mille_data, fit_coeff);
555 if (config_.enable_data_write)
556 {
557 output_tsync_mille_data_.get().push_back(mille_data);
558 }
559 }
560
561 binary_data_writer_->end();
562 }
563
564 void MillepedeEngine::AddSignals(const std::vector<BarCalData>& signals)
565 {
566 auto* task = GetTask();
567 if (not data_preprocessor_->process(signals, *cal_to_hit_par_))
568 {
569 task->ConditionFillToHist("preprocess_fail");
570 return;
571 }
572 task->ConditionFillToHist("preprocess_success");
573 const auto& processed_data = data_preprocessor_->get_data();
574 if (config_.enable_data_write)
575 {
577 }
578 const auto& fit_coeff = data_preprocessor_->get_track_info().bar_disp_data;
579
580 const auto is_xz_flat = std::abs(fit_coeff.x_z.slope) < std::abs(config_.max_abs_a_xz);
581 const auto is_yz_flat = std::abs(fit_coeff.y_z.slope) < std::abs(config_.max_abs_a_yz);
582
583 if (not(is_xz_flat or is_yz_flat))
584 {
585 return;
586 }
587
588 switch (config_.cal_mode)
589 {
592 break;
594 add_signals<MillepedeCalibrationMode::tsync>(processed_data, fit_coeff);
595 break;
596 default:
597 throw R3B::logic_error(
598 fmt::format("Unrecognized calibration mode: {}", magic_enum::enum_name(config_.cal_mode)));
599 }
600
601 add_fit_result_hist(fit_coeff);
602 }
603
605 {
606 binary_data_writer_->close();
607 LOGP(info, "Launching pede algorithm..");
608 pede_launcher_.launch();
609 pede_launcher_.end();
610
611 par_result_.read();
613 fill_data_to_figure(hit_par);
614 }
615
617 {
618 const auto& pars = hit_par.GetListOfModulePar();
619 for (const auto& [module_num, par] : pars)
620 {
621 graph_time_offset_->SetPoint(static_cast<int>(module_num), module_num, par.t_diff.value);
622 graph_time_offset_->SetPointError(static_cast<int>(module_num), 0., par.t_diff.error);
623 graph_time_sync_->SetPoint(static_cast<int>(module_num), module_num, par.t_sync.value);
624 graph_time_sync_->SetPointError(static_cast<int>(module_num), 0., par.t_sync.error);
625 graph_effective_c_->SetPoint(static_cast<int>(module_num), module_num, par.effective_speed.value);
626 graph_effective_c_->SetPointError(static_cast<int>(module_num), 0., par.effective_speed.error);
627 }
628 }
629
630 void MillepedeEngine::EndOfEvent([[maybe_unused]] unsigned int event_num)
631 {
632 // TODO: could be an empty event
633 binary_data_writer_->end();
634 data_preprocessor_->reset();
635 // fmt::println("<<<<<<<<<<<<<<<< End of the event {}", event_num);
636 }
637
639
641 {
642 const auto module_size = GetModuleSize();
643
644 graph_time_offset_ = histograms.add_graph("time_offset", std::make_unique<TGraphErrors>(module_size));
645 graph_time_offset_->SetTitle("Time offset vs BarNum");
646
647 graph_time_sync_ = histograms.add_graph("time_sync", std::make_unique<TGraphErrors>(module_size));
648 graph_time_sync_->SetTitle("Time sync vs BarNum");
649
650 graph_effective_c_ = histograms.add_graph("effective_c", std::make_unique<TGraphErrors>(module_size));
651 graph_effective_c_->SetTitle("Effective c vs BarNum");
652
653 static constexpr auto RESIDUAL_BIN_NUM = 500;
654 static constexpr auto PAR_BIN_NUM = 400;
655 static const auto SLOPE_MAX = 10.;
656 static const auto OFFSET_MAX = 200.;
657
658 auto set_x_title = [](auto* hist, std::string_view title) -> void { hist->GetXaxis()->SetTitle(title.data()); };
659 auto set_y_title = [](auto* hist, std::string_view title) -> void { hist->GetYaxis()->SetTitle(title.data()); };
660
661 hist_t_offset_residual_ = histograms.add_hist<TH1D>(
662 "t_diff_residual", "Residual values of the positions calculated from t_dff", RESIDUAL_BIN_NUM, 0., 1000.);
663
664 hist_p_value_xz_ = histograms.add_hist<TH1D>(
665 "p_value_xz", "p values from the fitting of the muon track in xz plane", RESIDUAL_BIN_NUM, 0., 1.);
666 hist_p_value_yz_ = histograms.add_hist<TH1D>(
667 "p_value_yz", "p values from the fitting of the muon track in yz plane", RESIDUAL_BIN_NUM, 0., 1.);
668 hist_a_xz_ = histograms.add_hist<TH1D>("a_xz", "slope of the xz plane", PAR_BIN_NUM, 0., SLOPE_MAX);
669 set_x_title(hist_a_xz_, "abs(a_xz)");
670 set_y_title(hist_a_xz_, fmt::format("counts per {}", SLOPE_MAX / PAR_BIN_NUM));
671
672 hist_b_xz_ = histograms.add_hist<TH1D>("b_xz", "offset of the xz plane", PAR_BIN_NUM, 0., OFFSET_MAX);
673 set_x_title(hist_b_xz_, "abs(b_xz)");
674 set_y_title(hist_b_xz_, fmt::format("counts per {}", OFFSET_MAX / PAR_BIN_NUM));
675
676 hist_a_yz_ = histograms.add_hist<TH1D>("a_yz", "slope of the yz plane", PAR_BIN_NUM, 0., SLOPE_MAX);
677 set_x_title(hist_a_yz_, "abs(a_yz)");
678 set_y_title(hist_a_yz_, fmt::format("counts per {}", SLOPE_MAX / PAR_BIN_NUM));
679
680 hist_b_yz_ = histograms.add_hist<TH1D>("b_yz", "offset of the yz plane", PAR_BIN_NUM, 0., OFFSET_MAX);
681 set_x_title(hist_b_yz_, "abs(b_yz)");
682 set_y_title(hist_b_yz_, fmt::format("counts per {}", OFFSET_MAX / PAR_BIN_NUM));
683
684 barplot_filter_counts_ = histograms.add_hist<TH1L>("filter_counts", "Counts after filters", 1, 0., 0.);
685
686 const auto n_plane = module_size / R3B::Neuland::BarsPerPlane;
688 histograms.add_hist<TH1D>("plane_hit_num", "Number of hit planes", n_plane + 1, -0.5, 0.5 + n_plane);
689 hist_plane_hit_num_->GetXaxis()->SetTitle("Number of planes hit");
690 hist_plane_hit_num_->GetYaxis()->SetTitle("Counts");
691
692 static constexpr auto residual_bin_num = 1000;
693 static constexpr auto max_residual = 300.;
694 static constexpr auto max_diff = 50;
695 }
696
698 {
699 input_data_buffer_.locals.clear();
700 input_data_buffer_.globals.clear();
701 input_data_buffer_.measurement = 0.F;
702 input_data_buffer_.sigma = 0.F;
703 }
704
706 {
708 // output_mille_data_point_->push_back(input_data_buffer_);
709 }
710
712 {
713 average_t_sum_.reset();
714 buffer_clear();
715 }
716
718 {
719 if (cal_to_hit_par_ == nullptr)
720 {
721 throw R3B::runtime_error("Pointer to cal_to_hit_par is nullptr!");
722 }
723
725 {
726 auto& module_pars = cal_to_hit_par_->GetListOfModuleParRef();
727 auto reference_bar_value = module_pars.at(DEFAULT_TSYNC_REFERENCE_BAR_NUM).t_sync.value;
728 if (reference_bar_value != DEFAULT_TSYNC_REFERENCE_BAR_VALUE)
729 {
730 LOGP(info,
731 "The reference bar (bar_num {}) from the input tsync parameter has the wrong value ({}, should be "
732 "{}). Offsetting the input parameters ...",
734 reference_bar_value,
736 for (auto& [module_num, module_par] : module_pars)
737 {
738 module_par.t_sync.value -= reference_bar_value;
739 }
740 }
741 }
742 }
743
745 {
746 hist_p_value_xz_->Fill(fit_result.x_z.p_value);
747 hist_p_value_yz_->Fill(fit_result.y_z.p_value);
748 hist_a_xz_->Fill(std::abs(fit_result.x_z.slope));
749 hist_b_xz_->Fill(std::abs(fit_result.x_z.offset));
750 hist_a_yz_->Fill(std::abs(fit_result.y_z.slope));
751 hist_b_yz_->Fill(std::abs(fit_result.y_z.offset));
752 }
753
755 {
756 auto steer_writer = SteerWriter{};
757 steer_writer.set_working_dir(working_dir_);
758 steer_writer.set_filepath(pede_steer_filename_);
759 steer_writer.set_parameter_file(input_parameter_filename_);
760 steer_writer.set_data_filepath(config_.mille_data_filename);
761 static constexpr auto NUMBER_OF_ITERATION = 3.F;
762 static constexpr auto CONVERGENCE_RECOGNITION = 0.001F;
763 steer_writer.add_method(SteerWriter::Method::inversion,
764 std::make_pair(NUMBER_OF_ITERATION, CONVERGENCE_RECOGNITION));
765 steer_writer.add_other_options(std::vector<std::string>{ "hugecut", "50000" });
766
768 {
769
771 std::make_pair(DEFAULT_TSYNC_REFERENCE_BAR_VALUE / SCALE_FACTOR, -1.F));
772 }
773 else
774 {
775 steer_writer.add_other_options(std::vector<std::string>{ "outlierdownweighting", "2" });
776 }
777
778 if (config_.num_of_threads > 0)
779 {
780 steer_writer.add_other_options(std::vector<std::string>{
781 "threads", fmt::format("{}", config_.num_of_threads), fmt::format("{}", config_.num_of_threads) });
782 }
783 steer_writer.write();
784 }
785} // namespace R3B::Neuland::Calibration
constexpr auto SCALE_FACTOR
constexpr auto DEFAULT_T_ERROR
constexpr auto DEFAULT_RES_FILENAME
constexpr auto DEFAULT_RES_JSON_FILENAME
constexpr auto MILLE_BUFFER_SIZE
auto add_hist(std::unique_ptr< TH1 > hist) -> TH1 *
auto add_graph(std::string_view graph_name, std::unique_ptr< GraphType > graph) -> GraphType *
auto get_pars() const -> const auto &
auto GetListOfModulePar() const -> const std::unordered_map< int, ::R3B::Neuland::HitModulePar > &
auto to_module_num_label(int par_num) -> std::pair< int, GlobalLabel >
R3B::OutputVectorConnector< MilleCalData > output_tsync_mille_data_
R3B::OutputConnector< NeulandTrackInfo > output_mille_track_info_
void add_fit_result_hist(const MilleDataProcessor::FitResult &fit_result)
auto select_t_sync_signal(const std::vector< MilleCalData > &plane_data)
void Calibrate(Cal2HitPar &hit_par) override
void add_spacial_local_constraint(int plane_id, const std::vector< MilleCalData > &plane_signals)
auto set_minimum_values(const std::vector< R3B::Neuland::BarCalData > &signals) -> bool
void EndOfEvent(unsigned int event_num=0) override
static constexpr std::string_view DEFAULT_SUB_DIR
void fill_module_parameters(const Millepede::ResultReader &result, Neuland::Cal2HitPar &cal_to_hit_par)
void set_options(const MillepedeOptions &options)
std::unique_ptr< MilleDataProcessor > data_preprocessor_
auto add_signal_t_sum(const MilleCalData &signal, const TrackFitResult &fit_coeff) -> float
void add_signal_t_diff(const MilleCalData &signal)
auto SignalFilter(const std::vector< BarCalData > &signals) -> bool override
void add_signals(const DataBufferType &processed_data, const TrackFitResult &fit_coeff)
void AddSignals(const std::vector< BarCalData > &signals) override
auto get_global_label_id(int module_num, GlobalLabel label) -> int
void HistInit(DataMonitor &histograms) override
R3B::OutputVectorConnector< MilleCalData > output_mille_data_
static constexpr auto ModuleID2PlaneID(int moduleID) -> int
void set_working_dir(std::string_view dir)
Definition SteerWriter.h:51
constexpr auto DEFAULT_TSYNC_REFERENCE_BAR_VALUE
constexpr auto DEFAULT_TSYNC_REFERENCE_BAR_NUM
std::unordered_map< int, std::vector< MilleCalData > > DataBufferType
constexpr auto BarsPerPlane
constexpr auto ModuleID2PlaneID(int moduleID) -> int
constexpr auto GetBarVerticalDisplacement(int module_num) -> double
constexpr auto SQRT_12
constexpr auto BarLength
constexpr auto CLight
constexpr auto BarSize_XY
constexpr auto ModuleNum2ZPos(int module_num) -> T
constexpr auto IsPlaneIDHorizontal(int plane_id) -> bool
constexpr auto PlaneID2ZPos(int plane_id) -> T
Data structure to store the cal level data for the data preprocessing.
float residual
residual value against the fitted line