R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
R3BDigitizingPaddle.cxx
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) 2019 GSI Helmholtzzentrum für Schwerionenforschung GmbH *
3 * Copyright (C) 2019-2025 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 "R3BDigitizingPaddle.h"
15
16namespace R3B::Digitizing
17{
18 Paddle::Paddle(int paddleID, SignalCouplingStrategy strategy)
19 : fPaddleID{ paddleID }
20 , fSignalCouplingStrategy{ std::move(strategy) }
21 {
22 }
23
24 void Paddle::SetChannel(std::unique_ptr<Channel> channel)
25 {
26 channel->SetPaddle(this);
27 channel->AttachToPaddle(this);
28 if (channel->GetSide() == ChannelSide::left)
29 {
30 fLeftChannel = std::move(channel);
31 }
32 else if (channel->GetSide() == ChannelSide::right)
33 {
34 fRightChannel = std::move(channel);
35 }
36 else
37 {
38 LOG(error) << "Channel side is invalid!";
39 }
40 }
41
42 void Paddle::DepositLight(const Hit& hit)
43 {
44 auto channelHits = ComputeChannelHits(hit);
45 fLeftChannel->AddHit(channelHits.left);
46 fRightChannel->AddHit(channelHits.right);
47 }
48
49 auto Paddle::HasFired() const -> bool
50 {
51 if (!fLeftChannel || !fRightChannel)
52 {
53 LOG(fatal) << "channels failed to be constructed when checking fire! ";
54 return false;
55 }
56 return (fLeftChannel->HasFired() && fRightChannel->HasFired());
57 }
58
59 auto Paddle::HasHalfFired() const -> bool
60 {
61 return (fLeftChannel->HasFired() && !fRightChannel->HasFired()) ||
62 (!fLeftChannel->HasFired() && fRightChannel->HasFired());
63 }
64
66 const Channel::Signals& secondSignals) const -> Signals
67 {
68 auto channelSignalPairs = fSignalCouplingStrategy(*this, firstSignals, secondSignals);
69
70 auto paddleSignals = std::vector<Signal>();
71 paddleSignals.reserve(channelSignalPairs.size());
72
73 for (auto& it : channelSignalPairs)
74 {
75 // warning if two channel signals are from the same side
76 if (it.left.get().side == it.right.get().side)
77 {
78 LOG(warn) << "DigitizingEngine: ConstructPaddleSignals(): cannot construct the paddle signal from the "
79 "channels on the same side!";
80 }
81
82 // swap the channel signals if necessary
83 if (it.left.get().side != ChannelSide::left)
84 {
85 std::swap(it.left, it.right);
86 }
87 auto paddleSignal = Signal{ LRPair{ it.left, it.right } };
88
89 paddleSignal.energy = ComputeEnergy(it.left, it.right);
90 paddleSignal.time = ComputeTime(it.left, it.right);
91 paddleSignal.position = ComputePosition(it.left, it.right);
92 paddleSignals.push_back(paddleSignal);
93 }
94 return paddleSignals;
95 }
96
97 auto Paddle::GetSignals() const -> const Signals&
98 {
99 if (!fSignals.valid())
100 {
101 if (HasFired())
102 {
103 auto signals = ConstructPaddelSignals(fLeftChannel->GetSignals(), fRightChannel->GetSignals());
104 fSignals.set(std::move(signals));
105 }
106 else
107 {
108 fSignals.set({});
109 }
110 }
111
112 return fSignals.getRef();
113 }
114
116 const Channel::Signals& firstSignals,
117 const Channel::Signals& secondSignals) -> std::vector<ChannelSignalPair>
118 {
119 auto firstSignalRefs =
120 std::vector<std::reference_wrapper<const Channel::Signal>>(firstSignals.begin(), firstSignals.end());
121 auto secondSignalRefs =
122 std::vector<std::reference_wrapper<const Channel::Signal>>(secondSignals.begin(), secondSignals.end());
123 auto channelSignalPairs = std::vector<ChannelSignalPair>{};
124 channelSignalPairs.reserve(std::min(firstSignals.size(), secondSignals.size()));
125
126 auto sortSignalByTime = [](auto signals)
127 {
128 std::sort(signals.begin(),
129 signals.end(),
130 [](auto& first, auto& second) { return first.get().tdc < second.get().tdc; });
131 };
132 sortSignalByTime(firstSignalRefs);
133 sortSignalByTime(secondSignalRefs);
134
135 for (auto first_it = firstSignalRefs.begin(), second_it = secondSignalRefs.begin();
136 first_it < firstSignalRefs.end() && second_it < secondSignalRefs.end();
137 ++first_it, ++second_it)
138 {
139 channelSignalPairs.emplace_back(*first_it, *second_it);
140 }
141 return channelSignalPairs;
142 }
143
144 auto Paddle::GetTrigTime() const -> double
145 {
146 return std::min(fRightChannel->GetTrigTime(), fLeftChannel->GetTrigTime());
147 }
148
149} // namespace R3B::Digitizing
std::vector< Signal > Signals
void SetChannel(std::unique_ptr< Channel > channel)
std::function< std::vector< ChannelSignalPair >(const Paddle &, const Channel::Signals &, const Channel::Signals &)> SignalCouplingStrategy
virtual auto ComputePosition(const Channel::Signal &rightSignal, const Channel::Signal &leftSignal) const -> double=0
std::vector< Signal > Signals
static auto SignalCouplingByTime(const Paddle &self, const Channel::Signals &firstSignals, const Channel::Signals &secondSignals) -> std::vector< ChannelSignalPair >
auto HasHalfFired() const -> bool
virtual auto ComputeChannelHits(const Hit &hit) const -> Pair< Channel::Hit >=0
Paddle(int paddleID, SignalCouplingStrategy strategy=SignalCouplingByTime)
void DepositLight(const Hit &hit)
auto GetSignals() const -> const std::vector< Signal > &
virtual auto ComputeEnergy(const Channel::Signal &firstSignal, const Channel::Signal &secondSignal) const -> double=0
auto GetTrigTime() const -> double
virtual auto ConstructPaddelSignals(const Channel::Signals &firstSignals, const Channel::Signals &secondSignals) const -> Signals
virtual auto ComputeTime(const Channel::Signal &firstSignal, const Channel::Signal &secondSignal) const -> double=0
auto HasFired() const -> bool