R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
testNeulandDigitizingPaddle.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 "MockModels.h"
16#include "R3BDigitizingPaddle.h"
18#include "R3BShared.h"
19#include "gtest/gtest.h"
20#include <gmock/gmock-matchers.h>
21#include <gmock/gmock-spec-builders.h>
22#include <memory>
23#include <utility>
24#include <vector>
25
31// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)
32namespace
33{
34 namespace Digitizing = R3B::Digitizing;
35 using Channel = Digitizing::AbstractChannel;
36 using Digitizing::PaddleSignal;
37 using NeulandPaddle = Digitizing::Neuland::Paddle;
38 using R3B::Side;
40 // using ::testing::Return;
41 template <typename Type>
42 using Pair = Digitizing::LRPair<Type>;
43
44 class testNeulandPaddle : public ::testing::Test
45 {
46 protected:
47 testNeulandPaddle() = default;
48
49 void SetUp() override
50 {
51 auto leftChannel = std::make_unique<GMockChannel>(Side::left);
52 auto rightChannel = std::make_unique<GMockChannel>(Side::right);
53 leftChannel->DelegateToFake();
54 rightChannel->DelegateToFake();
55 channels_.left = leftChannel.get();
56 channels_.right = rightChannel.get();
57 paddle_->SetChannel(std::move(leftChannel));
58 paddle_->SetChannel(std::move(rightChannel));
59 }
60
61 // void SetExpectCall()
62 // {
63 // EXPECT_CALL(*channels_.left,
64 // ConstructSignals()).Times(1).WillOnce(Return(std::move(channelSignals_.left)));
65 // EXPECT_CALL(*channels_.right, ConstructSignals())
66 // .Times(1)
67 // .WillOnce(Return(std::move(channelSignals_.right)));
68 // }
69
70 template <Side side>
71 void AddChannelSignal(const double& time, const double& energy)
72 {
73 auto signal = Channel::Hit{};
74 signal.tdc = time;
75 signal.qdc = energy;
76 signal.qdcUnSat = energy;
77 signal.side = side;
78 if constexpr (side == Side::right)
79 {
80 channelSignals_.right.push_back(signal);
81 }
82 else
83 {
84 channelSignals_.left.push_back(signal);
85 }
86 }
87
88 template <Side side>
89 auto ExtractChannelSignals()
90 {
91 if constexpr (side == Side::right)
92 {
93 return std::move(channelSignals_.right);
94 }
95 else
96 {
97 return std::move(channelSignals_.left);
98 }
99 }
100 [[nodiscard]] auto GetChannels() const -> const auto& { return channels_; }
101 [[nodiscard]] auto GetPaddle() const -> auto* { return paddle_.get(); }
102
103 private:
104 std::unique_ptr<NeulandPaddle> paddle_ = std::make_unique<NeulandPaddle>(0);
105 Pair<std::vector<Channel::Hit>> channelSignals_;
106 Pair<GMockChannel*> channels_ = { nullptr, nullptr };
107 };
108
109 TEST_F(testNeulandPaddle, check_inputN_to_channel)
110 {
111 auto* paddle = GetPaddle();
112 paddle->DepositLight(PaddleSignal{ 10., 20., 0. });
113 paddle->DepositLight(PaddleSignal{ 10., 20., 0. });
114 paddle->DepositLight(PaddleSignal{ 20., 0., 0. });
115 EXPECT_CALL(*GetChannels().left, construct_hits(testing::_)).Times(1);
116 EXPECT_CALL(*GetChannels().right, construct_hits(testing::_)).Times(1);
117 paddle->Construct();
118 const auto& leftHits = GetChannels().left->hits_;
119 const auto& rightHits = GetChannels().right->hits_;
120 ASSERT_EQ(leftHits.size(), rightHits.size()) << "Numbers of hits of both PMT channels don't match!";
121 ASSERT_EQ(leftHits.size(), 3) << "Number of hits for a PMT channel doesn't match with paddle inputs";
122 }
123
124 TEST_F(testNeulandPaddle, check_light_attenuation) // NOLINT
125 {
126 auto* paddle = GetPaddle();
127 auto const inputE = 20.;
128 auto paddle_signal = PaddleSignal{ 10., inputE, 0 };
129 paddle->DepositLight(paddle_signal);
130 EXPECT_CALL(*GetChannels().left, construct_hits(testing::_)).Times(1);
131 EXPECT_CALL(*GetChannels().right, construct_hits(testing::_)).Times(1);
132 paddle->Construct();
133 const auto& leftHits = GetChannels().left->hits_;
134 const auto& rightHits = GetChannels().right->hits_;
135 ASSERT_LT(leftHits[0].intensity, inputE) << "No light attenuation for the left channel!";
136 ASSERT_LT(rightHits[0].intensity, inputE) << "No light attenuation for the right channel!";
137 }
138
139 TEST_F(testNeulandPaddle, check_positive_direction) // NOLINT
140 {
141 auto* paddle = GetPaddle();
142 auto const inputE = 20.;
143 auto const initPos = 0.8 * NeulandPaddle::HALF_BAR_LENGTH;
144 auto paddle_signal = PaddleSignal{ 10., inputE, initPos };
145 paddle->DepositLight(paddle_signal);
146 EXPECT_CALL(*GetChannels().left, construct_hits(testing::_)).Times(1);
147 EXPECT_CALL(*GetChannels().right, construct_hits(testing::_)).Times(1);
148 paddle->Construct();
149 const auto& leftHits = GetChannels().left->hits_;
150 const auto& rightHits = GetChannels().right->hits_;
151 ASSERT_LT(leftHits[0].intensity, rightHits[0].intensity)
152 << "left channel has larger light input with longer distance!";
153 ASSERT_GT(leftHits[0].time, rightHits[0].time) << "light hit left channel ealier with longer distance!";
154 }
155
156 TEST_F(testNeulandPaddle, check_coupling_counts) // NOLINT
157 {
158 auto* paddle = GetPaddle();
159 paddle->DepositLight(PaddleSignal{ 10., 20., 0.5 * NeulandPaddle::HALF_BAR_LENGTH });
160 paddle->DepositLight(PaddleSignal{ 60., 10., -0.3 * NeulandPaddle::HALF_BAR_LENGTH });
161 EXPECT_CALL(*GetChannels().left, construct_hits(testing::_)).Times(1);
162 EXPECT_CALL(*GetChannels().right, construct_hits(testing::_)).Times(1);
163 paddle->Construct();
164 // const auto& leftHits = GetChannels().left->hits_;
165 // const auto& rightHits = GetChannels().right->hits_;
166 // AddChannelSignal<Side::left>(leftHits[0].time, leftHits[0].light);
167 // AddChannelSignal<Side::left>(leftHits[1].time, leftHits[1].light);
168 // AddChannelSignal<Side::right>(rightHits[1].time, rightHits[1].light);
169 // AddChannelSignal<Side::right>(rightHits[0].time, rightHits[0].light);
170 const auto& signals = paddle->GetHits();
171 ASSERT_EQ(signals.size(), 2) << "Fail to reconstruct the same number of signals!";
172 }
173
174 TEST_F(testNeulandPaddle, check_output_singal) // NOLINT
175 {
176 auto* paddle = GetPaddle();
177 paddle->DepositLight(PaddleSignal{ 10., 20., 0.5 * NeulandPaddle::HALF_BAR_LENGTH });
178 EXPECT_CALL(*GetChannels().left, construct_hits(testing::_)).Times(1);
179 EXPECT_CALL(*GetChannels().right, construct_hits(testing::_)).Times(1);
180 paddle->Construct();
181 // const auto& leftHits = GetChannels().left->hits_;
182 // const auto& rightHits = GetChannels().right->hits_;
183 // AddChannelSignal<Side::left>(leftHits[0].time, leftHits[0].light);
184 // AddChannelSignal<Side::right>(rightHits[0].time, rightHits[0].light);
185 auto const& signals = paddle->GetHits();
186 ASSERT_EQ(signals.size(), 1) << "Fail to reconstruct the same number of signals!";
187 const double err = 0.1 * 0.5 * NeulandPaddle::HALF_BAR_LENGTH;
188 ASSERT_NEAR(0.5 * NeulandPaddle::HALF_BAR_LENGTH, signals.front().position, err)
189 << "reconstructed position is way different to predefined position!";
190 }
191
192 TEST_F(testNeulandPaddle, check_reset)
193 {
194 auto* paddle = GetPaddle();
195 paddle->DepositLight(PaddleSignal{ 10., 20., 0.5 * NeulandPaddle::HALF_BAR_LENGTH });
196 EXPECT_CALL(*GetChannels().left, construct_hits(testing::_)).Times(2);
197 EXPECT_CALL(*GetChannels().right, construct_hits(testing::_)).Times(2);
198 paddle->Construct();
199 EXPECT_EQ(paddle->GetHits().size(), 1);
200 paddle->Reset();
201 paddle->Construct();
202 EXPECT_EQ(paddle->GetHits().size(), 0);
203 }
204
205 // TEST_F(testNeulandPaddle, check_coupling_NoEQ_counts) // NOLINT
206 // {
207 // auto* paddle = GetPaddle();
208 // paddle->DepositLight(PaddleSignal{ 10., 20., 0.5 * NeulandPaddle::gHalfLength });
209 // paddle->DepositLight(PaddleSignal{ 60., 10., -0.3 * NeulandPaddle::gHalfLength });
210 // const auto& leftHits = GetChannels().left->hits_;
211 // const auto& rightHits = GetChannels().right->hits_;
212 // AddChannelSignal<Side::left>(leftHits[0].time, leftHits[0].light);
213 // AddChannelSignal<Side::left>(leftHits[1].time, leftHits[1].light);
214 // AddChannelSignal<Side::right>(rightHits[1].time, rightHits[1].light);
215 // SetExpectCall();
216 // const auto& signals = paddle->GetSignals();
217 // ASSERT_EQ(signals.size(), 1) << "inequal number of channel signals are not paired correctly!";
218 // }
219
220 // TEST_F(testNeulandPaddle, check_coupling_badParing) // NOLINT
221 // {
222 // FairLogger::GetLogger()->SetLogScreenLevel("error");
223 // auto* paddle = GetPaddle();
224 // paddle->DepositLight(PaddleSignal{ 10., 20., 0.5 * NeulandPaddle::gHalfLength });
225 // paddle->DepositLight(PaddleSignal{ 60., 10., -0.3 * NeulandPaddle::gHalfLength });
226 // const auto& leftHits = GetChannels().left->hits_;
227 // const auto& rightHits = GetChannels().right->hits_;
228 // AddChannelSignal<Side::left>(leftHits[0].time, leftHits[0].light);
229 // AddChannelSignal<Side::left>(leftHits[0].time, leftHits[0].light);
230 // AddChannelSignal<Side::right>(rightHits[0].time, rightHits[0].light);
231 // AddChannelSignal<Side::right>(rightHits[1].time, rightHits[1].light);
232 // SetExpectCall();
233 // const auto& signals = paddle->GetSignals();
234 // ASSERT_EQ(signals.size(), 1) << "recursive paring is not prohibited!";
235 // }
236} // namespace
237// NOLINTEND(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)