15#include "FairRunAna.h"
16#include "FairRuntimeDb.h"
35#include <RtypesCore.h>
41#include <fairlogger/Logger.h>
46#include <range/v3/view/zip.hpp>
58 inline auto CreateDigiEngine(
const DigiTaskOptions& option, std::string_view hit_par_name, FairRun* run)
61 using NeulandPaddle = Digitizing::Neuland::Paddle;
62 namespace Tamex = Digitizing::Neuland::Tamex;
63 using TamexChannel = Tamex::Channel;
64 using Digitizing::UseChannel;
65 using Digitizing::UsePaddle;
66 using MockPaddle = Digitizing::Neuland::MockPaddle;
67 using MockChannel = Digitizing::Neuland::MockChannel;
68 using TacquilaChannel = Digitizing::Neuland::TacQuila::Channel;
70 auto pileup_strategy = option.pileup_strategy;
71 const auto& tamex_par = option.tamex_par;
72 Cal2HitPar* cal_to_hit_par{
nullptr };
73 if (option.enable_hit_par)
75 LOGP(info,
"cal_to_hit_par is used in digitization task!");
76 cal_to_hit_par = std::make_unique<Cal2HitPar>(hit_par_name).release();
77 run->GetRuntimeDb()->addContainer(cal_to_hit_par);
81 LOGP(info,
"cal_to_hit_par is not used in digitization task!");
83 return std::map<std::pair<const std::string, const std::string>,
84 std::function<std::unique_ptr<Digitizing::EngineInterface>()>>{
85 { {
"neuland",
"tamex" },
86 [&tamex_par, pileup_strategy, cal_to_hit_par, enable_sim_cal = option.enable_sim_cal]()
89 UsePaddle<NeulandPaddle>(cal_to_hit_par),
90 UseChannel<TamexChannel>(pileup_strategy, tamex_par, cal_to_hit_par, enable_sim_cal));
92 { {
"neuland",
"tacquila" },
95 UseChannel<TacquilaChannel>());
97 { {
"mock",
"tamex" },
98 [&tamex_par, pileup_strategy, cal_to_hit_par, enable_sim_cal = option.enable_sim_cal]()
101 UsePaddle<MockPaddle>(),
102 UseChannel<TamexChannel>(pileup_strategy, tamex_par, cal_to_hit_par, enable_sim_cal));
104 { {
"neuland",
"mock" },
107 UseChannel<MockChannel>());
109 { {
"mock",
"mock" },
122 std::string_view points_name,
123 std::string_view hits_name,
124 std::string_view cal_hits_name)
125 : FairTask(
"R3BNeulandDigitizer")
140 FairRunAna* run = FairRunAna::Instance();
146 FairRuntimeDb* rtdb = run->GetRuntimeDb();
149 throw R3B::runtime_error(
"R3BNeulandDigitizer::SetParContainers: No runtime database");
155 throw R3B::runtime_error(
"R3BNeulandDigitizer::SetParContainers: No R3BNeulandGeoPar");
163 throw R3B::runtime_error(
"neuland_geo_par is still nullptr during the initialization!");
183 "MultiplicityOne",
"Paddle multiplicity: only one PMT per paddle", paddle_size, 0, paddle_size);
186 "MultiplicityTwo",
"Paddle multiplicity: both PMTs of a paddle", paddle_size, 0, paddle_size);
187 auto const timeBinSize = 200;
189 data_monitor_.add_hist<TH1F>(
"hRLTimeToTrig",
"R/Ltime-triggerTime", timeBinSize, -100., 100.);
203 for (
int paddle_id{}; paddle_id < paddle_size; ++paddle_id)
227 if (!paddle.HasFired())
246 LOG(debug) << fmt::format(
"Produced {} hits",
neuland_hits_.size());
254 const auto& paddle_hits = paddle.
GetHits();
258 for (
const auto side : sides)
260 const auto& channel = paddle.
GetChannel(side);
268 static constexpr auto GeVToMeVFac = 1000.;
278 if (point.GetEnergyLoss() > 0.)
280 const auto paddle_ID = point.GetPaddle();
283 const auto& position = point.GetPosition();
284 const auto converted_position =
neuland_geo_par_->ConvertToLocalCoordinates(position, paddle_ID);
285 LOGP(debug2,
"Point in paddle: {}, with global position XYZ: {}", paddle_ID, position);
286 LOGP(debug2,
"Converted to local position XYZ: {}", converted_position);
290 const auto dist = converted_position.X();
291 digitizing_engine_->DepositLight(paddle_ID, point.GetTime(), point.GetLightYield() * GeVToMeVFac, dist);
307 [](
auto paddles_view)
309 return static_cast<double>(std::count_if(paddles_view.begin(),
311 [](const auto& paddle) { return paddle.HasHalfFired(); }));
314 hist_multi_two_->Fill(digitizing_engine_->DoAllPaddles(
315 [](
auto paddles_view)
317 return static_cast<double>(std::count_if(
318 paddles_view.begin(), paddles_view.end(), [](
const auto& paddle) { return paddle.HasFired(); }));
320 if (has_size_monitor_)
322 for (
const auto [key, value] : point_size_tracker_)
328 hist_point_size_->Fill(value);
335 auto read_branch_names = std::vector<std::string>{};
336 auto write_branch_names = std::vector<std::string>{};
339 auto engine_map = CreateDigiEngine(option, read_branch_names.at(1), run);
340 auto engine_gen = engine_map.at({ option.paddle, option.channel });
341 auto task = std::make_unique<Digitizer>(
342 engine_gen(), read_branch_names.at(0), write_branch_names.at(0), write_branch_names.at(1));
343 task->EnableCalDataOutput(option.enable_sim_cal);
344 task->EnableSizeMonitor(option.enable_size_monitor);
345 task->SetName(option.name.c_str());
347 LOG(info) << point_filter.Print();
348 task->SetPointFilter(std::move(point_filter));
354 const auto& signals = paddle.
GetHits();
356 for (
const auto& signal : signals)
358 const TVector3 hitPositionLocal = TVector3(signal.position, 0., 0.);
359 const TVector3 hitPositionGlobal =
361 const TVector3 hitPixel =
neuland_geo_par_->ConvertGlobalToPixel(hitPositionGlobal);
364 signal.left_channel_hit->tdc,
365 signal.right_channel_hit->tdc,
367 signal.left_channel_hit->qdcUnSat,
368 signal.right_channel_hit->qdcUnSat,
376 LOGP(debug,
"Adding neuland hit: {}", hit);
389 const auto& left_channel_signals = left_channel.GetCalSignals();
390 const auto& right_channel_signals = right_channel.GetCalSignals();
392 if (left_channel_signals.size() != right_channel_signals.size())
397 for (
const auto& [
left,
right] : ranges::zip_view(left_channel_signals, right_channel_signals))
404 cal_hits.push_back(std::move(cal_data));
405 LOGP(debug2,
"Adding sim cal with {}", cal_data);
constexpr auto MAX_SIZE_BIN
auto GetRightChannelRef() const -> auto &
auto GetPaddleID() const -> int
auto GetLeftChannelRef() const -> auto &
auto GetChannel(R3B::Side side) const -> const Digitizing::AbstractChannel &
auto GetHits() const -> const std::vector< Hit > &
Digitizing::Neuland::TacQuila::Channel TacquilaChannel
void Exec(Option_t *) override
static auto Create(const R3B::Neuland::DigiTaskOptions &option, FairRun *run) -> std::unique_ptr< Digitizer >
Generator of the digitizing class.
Filterable< R3BNeulandHit & > hit_filters_
Digitizer()
Constructor with no input parameters.
R3B::Neuland::ParticleFilter neuland_point_filter_
R3BNeulandGeoPar * neuland_geo_par_
Digitizing::UsePaddle< Type > UsePaddle
std::unique_ptr< Digitizing::EngineInterface > digitizing_engine_
void FinishEvent() override
void fill_size_histograms(const Digitizing::AbstractPaddle &paddle)
void SetParContainers() override
TH1F * hist_rl_time_to_trig_
void fill_points_to_engine()
std::unordered_map< int, int > point_size_tracker_
R3B::OutputVectorConnector< R3BNeulandHit > neuland_hits_
auto Init() -> InitStatus override
void fill_hit_data(const R3B::Digitizing::AbstractPaddle &paddle)
Digitizing::Neuland::Paddle NeulandPaddle
void fill_cal_data(const R3B::Digitizing::AbstractPaddle &paddle)
void SetEngine(std::unique_ptr< Digitizing::EngineInterface > engine)
Setter of the internal engine.
void FinishTask() override
TH1D * hist_paddle_hit_size_
Filterable< R3B::Neuland::SimCalData & > cal_hit_filter_
R3B::InputVectorConnector< R3BNeulandPoint > neuland_points_
TH1D * hist_channel_signal_size_
Digitizing::UseChannel< Type > UseChannel
R3B::DataMonitor data_monitor_
R3B::OutputVectorConnector< R3B::Neuland::SimCalData > neuland_cal_hits_
TH1D * hist_channel_hit_size_
static auto Create(const Options &options) -> ParticleFilter
Generator for the filter object from the configuration.
NeuLAND geometry parameter storage.
auto CreateEngine(Args &&... args) -> std::unique_ptr< decltype(Engine{ std::forward< Args >(args)... })>
Simulation of NeuLAND Bar/Paddle.
constexpr auto BarsPerPlane
void parse_io_branch_names(const Option &option, std::vector< std::string > &read, int read_num, std::vector< std::string > &write, int write_num)
Configuration struct for R3B::Neuland::Digitizer used in R3B::Neuland::AnalysisApplication.