Project
Loading...
Searching...
No Matches
Segmentation.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
15#define BOOST_TEST_DYN_LINK
16
17#include <boost/test/unit_test.hpp>
18
19#include "boost/format.hpp"
22#include <boost/test/data/monomorphic.hpp>
23#include <boost/test/data/monomorphic/generators/xrange.hpp>
24#include <boost/test/data/test_case.hpp>
25#include <fstream>
26#include <iostream>
27#include "TestParameters.h"
28#include <fmt/format.h>
29
30using namespace o2::mch::mapping;
31namespace bdata = boost::unit_test::data;
32
33BOOST_AUTO_TEST_SUITE(o2_mch_mapping)
34BOOST_AUTO_TEST_SUITE(segmentation_both_cathodes)
35
36BOOST_AUTO_TEST_CASE(GetSegmentationMustNotThrowIfDetElemIdIsValid)
37{
38 // do not use the o2::mch::mapping::segmentation() cache here as we want to test the object
39 // construction (which is used also by the o2::mch::mapping::segmentation() function...)
42 });
43}
44
45BOOST_AUTO_TEST_CASE(GetSegmentationThrowsIfDetElemIdIsNotValid)
46{
47 // do not use the o2::mch::mapping::segmentation() cache here as we want to test the object
48 // construction (which is used also by the o2::mch::mapping::segmentation() function...)
49 BOOST_CHECK_THROW(Segmentation(-1), std::runtime_error);
50 BOOST_CHECK_THROW(Segmentation(121), std::runtime_error);
51}
52
54{
55 // Explicitly don't make a loop to more clearly document the number of pads
56 // per detection element.
57 //
58 // Sorted by decreasing number of pads.
60#ifdef MCH_MAPPING_RUN3_AND_ABOVE
62#else
64#endif
84}
85
86BOOST_AUTO_TEST_CASE(TotalNofFECInSegTypesIs2265)
87{
88 int n{0};
91 });
92#ifdef MCH_MAPPING_RUN3_AND_ABOVE
93 BOOST_CHECK_EQUAL(n, 2264);
94#else
95 BOOST_CHECK_EQUAL(n, 2265);
96#endif
97}
98
99BOOST_AUTO_TEST_CASE(CheckBoundingBoxesAreAsExpected)
100{
101 // BOOST_CHECK_EQUAL(getBBox(Segmentation(300)), o2::mch::contour::BBox<double>(-1, -0.75, 116, 117.25));
102 // BOOST_CHECK_EQUAL(getBBox(Segmentation(500)), o2::mch::contour::BBox<double>(-75, -20, 57.5, 20));
107 // BOOST_CHECK_EQUAL(getBBox(Segmentation(600)), o2::mch::contour::BBox<double>(-80, -20, 57.5, 20));
121}
122
123BOOST_AUTO_TEST_CASE(CheckNofBendingFEC)
124{
126#ifdef MCH_MAPPING_RUN3_AND_ABOVE
128#else
130#endif
150}
151
152BOOST_AUTO_TEST_CASE(PadCountInSegmentationTypesMustBe143469)
153{
154 int n{0};
157 });
158#ifdef MCH_MAPPING_RUN3_AND_ABOVE
159 BOOST_CHECK_EQUAL(n, 143409);
160#else
161 BOOST_CHECK_EQUAL(n, 143469);
162#endif
163}
164
165BOOST_AUTO_TEST_CASE(PadCountInAllSegmentationsMustBe1064008)
166{
167 int n{0};
168 forEachDetectionElement([&n](int detElemId) {
170 });
171#ifdef MCH_MAPPING_RUN3_AND_ABOVE
172 BOOST_CHECK_EQUAL(n, 1063528);
173#else
174 BOOST_CHECK_EQUAL(n, 1064008);
175#endif
176}
177
178BOOST_AUTO_TEST_CASE(NumberOfSegmentationsMustBe21)
179{
180 int n{0};
182 n++;
183 });
184 BOOST_CHECK_EQUAL(n, 21);
185}
186
187BOOST_AUTO_TEST_CASE(CheckPadOffsetsAfterCopy)
188{
189 forEachDetectionElement([](int detElemId) {
190 bool ok{true};
191 auto s = o2::mch::mapping::segmentation(detElemId);
192 auto seg = s;
193 for (auto padid = 0; padid < seg.bending().nofPads(); padid++) {
194 if (seg.isBendingPad(padid) != true) {
195 ok = false;
196 break;
197 }
198 }
199 BOOST_CHECK_MESSAGE(ok == true, "inconsistent isBendingPad for bending plane");
200 ok = true;
201 for (auto padid = seg.bending().nofPads(); padid < seg.nofPads(); padid++) {
202 if (seg.isBendingPad(padid) != false) {
203 ok = false;
204 break;
205 }
206 }
207 BOOST_CHECK_MESSAGE(ok == true, "inconsistent isBendingPad for non-bending plane");
208 });
209}
210
211struct SEG100 {
213};
214
215BOOST_AUTO_TEST_CASE(TestForEachPadAndPadIndexRange)
216{
217 int npads = 0;
218 forOneDetectionElementOfEachSegmentationType([&npads](int detElemId) {
219 int n = 0;
220 int pmin = std::numeric_limits<int>::max();
221 int pmax = 0;
222 Segmentation seg{detElemId};
223 seg.forEachPad([&n, &pmin, &pmax, &npads](int dePadIndex) {
224 npads++;
225 n++;
226 pmin = std::min(pmin, dePadIndex);
227 pmax = std::max(pmax, dePadIndex);
228 });
230 BOOST_CHECK_EQUAL(pmin, 0);
231 BOOST_CHECK_EQUAL(pmax, seg.nofPads() - 1);
232 });
233}
234
235BOOST_AUTO_TEST_CASE(CheckOnePadPositionPresentOnOnlyBendingPlaneDE600)
236{
237 Segmentation de600(600);
238 double x = 54.34;
239 double y = -12.40;
240 int b, nb;
241 bool ok = de600.findPadPairByPosition(x, y, b, nb);
243 int testChannel = 12;
244 if (params.isSegmentationRun3) {
245 testChannel = 44;
246 }
247 BOOST_CHECK_EQUAL(ok, false);
248 int p = de600.findPadByFEE(307, testChannel);
250 BOOST_CHECK_EQUAL(de600.isValid(b), true);
251 BOOST_CHECK_EQUAL(de600.isValid(nb), false);
252}
253
254BOOST_AUTO_TEST_CASE(CheckOnePadPositionPresentOnOnlyBendingPlaneDE825)
255{
256 Segmentation de825(825);
257 double x = 110.09;
258 double y = -1.25;
259 int b, nb;
260 bool ok = de825.findPadPairByPosition(x, y, b, nb);
262 int testChannel{55};
263 if (params.isSegmentationRun3) {
264 testChannel = 23;
265 }
266 BOOST_CHECK_EQUAL(ok, false);
267 int p = de825.findPadByFEE(1333, testChannel);
268 BOOST_CHECK_EQUAL(p, nb);
269 BOOST_CHECK_EQUAL(de825.isValid(b), false);
270 BOOST_CHECK_EQUAL(de825.isValid(nb), true);
271}
272
273BOOST_AUTO_TEST_CASE(CheckOnePadPositionTotallyAbsentDE604)
274{
275 Segmentation de604(604);
276 double x = -19.25;
277 double y = 20.04;
278 int b, nb;
279 bool ok = de604.findPadPairByPosition(x, y, b, nb);
280 BOOST_CHECK_EQUAL(ok, false);
281 BOOST_CHECK_EQUAL(de604.isValid(nb), false);
282 BOOST_CHECK_EQUAL(de604.isValid(b), false);
283}
284
285// All the remaining tests of this file are using specific
286// detection elements DE100
287
288BOOST_FIXTURE_TEST_SUITE(DE100, SEG100)
289
290BOOST_TEST_DECORATOR(*boost::unit_test::tolerance(1E-3))
291BOOST_AUTO_TEST_CASE(CheckOnePosition)
292{
293 int b, nb;
294 bool ok = seg.findPadPairByPosition(24.2, 23.70, b, nb);
295 BOOST_CHECK_EQUAL(ok, true);
296 BOOST_TEST(seg.padPositionX(b) == 24.255);
297 BOOST_TEST(seg.padPositionY(b) == 23.73);
298 BOOST_TEST(seg.padSizeX(b) == 0.63);
299 BOOST_TEST(seg.padSizeY(b) == 0.42);
300}
301
302bool checkSameCathode(const Segmentation& seg, int depadindex, const std::vector<int>& padindices)
303{
304 bool isBending = seg.isBendingPad(depadindex);
305 for (auto n : padindices) {
306 if (seg.isBendingPad(n) != isBending) {
307 return false;
308 }
309 }
310 return true;
311}
312
313struct PadInfo {
314 int fec, ch;
315 double x, y, sx, sy;
316};
317
318// areEqual returns true if the two values are within 1 micron.
319bool areEqual(double a, double b)
320{
321 return std::fabs(a - b) < 1E-4; // 1 micron expressed in centimeters
322}
323
324// testNeighbours returns true if the neighbours of dePadIndex, as
325// returned by the Segmentation::forEachNeighbouringPad, are the same
326// as the elements of expected vector.
327bool testNeighbours(const Segmentation& seg, int dePadIndex, std::vector<PadInfo>& expected)
328{
329 std::vector<int> nei;
330 seg.forEachNeighbouringPad(dePadIndex, [&nei](int depadindex) {
331 nei.push_back(depadindex);
332 });
333
334 if (nei.size() != expected.size()) {
335 return false;
336 }
337 auto notFound = nei.size();
338 for (auto n : nei) {
339 for (auto e : expected) {
340 if (seg.padDualSampaId(n) == e.fec &&
341 seg.padDualSampaChannel(n) == e.ch &&
342 areEqual(seg.padPositionX(n), e.x) &&
343 areEqual(seg.padPositionY(n), e.y) &&
344 areEqual(seg.padSizeX(n), e.sx) &&
345 areEqual(seg.padSizeY(n), e.sy)) {
346 notFound--;
347 }
348 }
349 }
350 return notFound == 0;
351}
352
353BOOST_AUTO_TEST_CASE(CheckOnePadNeighbours)
354{
355 // Below are the neighbouring pads of the pad(s) @ (24.0, 24.0)cm
356 // for DE 100.
357 // What is tested below is not the PAD (index might depend on
358 // the underlying implementation) but the rest of the information :
359 // (FEC,CH), (X,Y), (SX,SY)
360 //
361 // PAD 5208 FEC 95 CH 0 X 23.625 Y 23.730 SX 0.630 SY 0.420
362 // PAD 5209 FEC 95 CH 3 X 23.625 Y 24.150 SX 0.630 SY 0.420
363 // PAD 5210 FEC 95 CH 4 X 23.625 Y 24.570 SX 0.630 SY 0.420
364 // PAD 5226 FEC 95 CH 42 X 24.255 Y 24.570 SX 0.630 SY 0.420
365 // PAD 5242 FEC 95 CH 43 X 24.885 Y 24.570 SX 0.630 SY 0.420
366 // PAD 5241 FEC 95 CH 2 X 24.885 Y 24.150 SX 0.630 SY 0.420
367 // PAD 5240 FEC 95 CH 46 X 24.885 Y 23.730 SX 0.630 SY 0.420
368 // PAD 5224 FEC 95 CH 31 X 24.255 Y 23.730 SX 0.630 SY 0.420
369 // PAD 19567 FEC 1119 CH 48 X 23.310 Y 23.520 SX 0.630 SY 0.420
370 // PAD 19568 FEC 1119 CH 46 X 23.310 Y 23.940 SX 0.630 SY 0.420
371 // PAD 19569 FEC 1119 CH 0 X 23.310 Y 24.360 SX 0.630 SY 0.420
372 // PAD 19585 FEC 1119 CH 42 X 23.940 Y 24.360 SX 0.630 SY 0.420
373 // PAD 19601 FEC 1119 CH 1 X 24.570 Y 24.360 SX 0.630 SY 0.420
374 // PAD 19600 FEC 1119 CH 44 X 24.570 Y 23.940 SX 0.630 SY 0.420
375 // PAD 19599 FEC 1119 CH 30 X 24.570 Y 23.520 SX 0.630 SY 0.420
376 // PAD 19583 FEC 1119 CH 29 X 23.940 Y 23.520 SX 0.630 SY 0.420
377
378 std::vector<PadInfo> bendingNeighbours{
379 {95, 0, 23.625, 23.730, 0.630, 0.420},
380 {95, 3, 23.625, 24.150, 0.630, 0.420},
381 {95, 4, 23.625, 24.570, 0.630, 0.420},
382 {95, 42, 24.255, 24.570, 0.630, 0.420},
383 {95, 43, 24.885, 24.570, 0.630, 0.420},
384 {95, 2, 24.885, 24.150, 0.630, 0.420},
385 {95, 46, 24.885, 23.730, 0.630, 0.420},
386 {95, 31, 24.255, 23.730, 0.630, 0.420}};
387
388 std::vector<PadInfo> nonBendingNeighbours{
389 {1119, 48, 23.310, 23.520, 0.630, 0.420},
390 {1119, 46, 23.310, 23.940, 0.630, 0.420},
391 {1119, 0, 23.310, 24.360, 0.630, 0.420},
392 {1119, 42, 23.940, 24.360, 0.630, 0.420},
393 {1119, 1, 24.570, 24.360, 0.630, 0.420},
394 {1119, 44, 24.570, 23.940, 0.630, 0.420},
395 {1119, 30, 24.570, 23.520, 0.630, 0.420},
396 {1119, 29, 23.940, 23.520, 0.630, 0.420}};
397
399 if (params.isSegmentationRun3) {
400 for (auto& p : bendingNeighbours) {
401 p.ch = manu2ds(100, p.ch);
402 }
403 for (auto& p : nonBendingNeighbours) {
404 p.ch = manu2ds(100, p.ch);
405 }
406 }
407
408 int pb, pnb;
409 bool ok = seg.findPadPairByPosition(24.0, 24.0, pb, pnb);
410 BOOST_CHECK_EQUAL(ok, true);
411 BOOST_CHECK_EQUAL(testNeighbours(seg, pb, bendingNeighbours), true);
412 BOOST_CHECK_EQUAL(testNeighbours(seg, pnb, nonBendingNeighbours), true);
413}
414
416{
417 std::vector<std::pair<int, int>> tp{
418 {95, 45},
419 {1119, 45} // both pads @pos 24.0, 24.0cm
420 };
421
422 for (auto p : tp) {
423 auto dsid = p.first;
424 auto dsch = p.second;
425 auto dePadIndex = seg.findPadByFEE(dsid, dsch);
426 BOOST_CHECK_EQUAL(seg.padDualSampaId(dePadIndex), dsid);
427 BOOST_CHECK_EQUAL(seg.padDualSampaChannel(dePadIndex), dsch);
428 }
429}
430
431BOOST_AUTO_TEST_CASE(ThrowsIfDualSampaChannelIsNotBetween0And63)
432{
433 BOOST_CHECK_THROW(seg.findPadByFEE(102, -1), std::out_of_range);
434 BOOST_CHECK_THROW(seg.findPadByFEE(102, 64), std::out_of_range);
435}
436
437BOOST_AUTO_TEST_CASE(ReturnsTrueIfPadIsConnected) { BOOST_CHECK_EQUAL(seg.isValid(seg.findPadByFEE(102, 3)), true); }
438
439BOOST_AUTO_TEST_CASE(ReturnsFalseIfPadIsNotConnected)
440{
442 int testChannel{14};
443 if (params.isSegmentationRun3) {
444 testChannel = 39;
445 }
446 BOOST_CHECK_EQUAL(seg.isValid(seg.findPadByFEE(214, testChannel)), false);
447}
448
449BOOST_AUTO_TEST_CASE(ReturnsFalseIfCatPadIdIsOutOfRange)
450{
452 Segmentation seg{detElemId};
453 BOOST_TEST_INFO_SCOPE(fmt::format("DeId {}", detElemId));
454 BOOST_CHECK_EQUAL(seg.isValid(0), true);
456 BOOST_CHECK_EQUAL(seg.isValid(-1), false);
458 });
459}
460BOOST_AUTO_TEST_CASE(HasPadByPosition)
461{
462 int b, nb;
463 bool ok = seg.findPadPairByPosition(40.0, 30.0, b, nb);
464 BOOST_CHECK_EQUAL(ok, true);
465}
466
467BOOST_AUTO_TEST_CASE(CheckOnePadPositionPresentOnOnlyBendingPlane)
468{
469 double x = 1.575;
470 double y = 18.69;
471 int b, nb;
472 bool ok = seg.findPadPairByPosition(x, y, b, nb);
474 int testChannel{9};
475 if (params.isSegmentationRun3) {
476 testChannel = 47;
477 }
478 BOOST_CHECK_EQUAL(ok, false);
479 BOOST_CHECK_EQUAL(seg.findPadByFEE(76, testChannel), b);
480 BOOST_CHECK_EQUAL(seg.isValid(nb), false);
481}
482
483BOOST_AUTO_TEST_CASE(WhenOnlyOneCathodeHasAPadTheValidIndexMustRelativeToDeNotToCathode)
484{
485 double x = 8.8;
486 double y = 18;
487 int b, nb;
488 bool ok = seg.findPadPairByPosition(x, y, b, nb);
489 BOOST_CHECK_EQUAL(ok, false);
490 BOOST_CHECK_EQUAL(seg.isValid(nb), true);
492 BOOST_CHECK_EQUAL(seg.isBendingPad(nb), false);
493}
494
496{
497 Segmentation copy{seg};
498 BOOST_TEST((copy == seg));
499 BOOST_TEST(copy.nofPads() == seg.nofPads());
500}
501
502BOOST_AUTO_TEST_CASE(CheckAssignment)
503{
504 Segmentation copy{200};
505 copy = seg;
506 BOOST_TEST((copy == seg));
507 BOOST_TEST(copy.nofPads() == seg.nofPads());
508}
509
510BOOST_AUTO_TEST_SUITE_END()
511BOOST_AUTO_TEST_SUITE_END()
512BOOST_AUTO_TEST_SUITE_END()
o2::mch::mapping::CathodeSegmentation seg
bool areEqual(double a, double b)
bool testNeighbours(const Segmentation &seg, int dePadIndex, std::vector< PadInfo > &expected)
BOOST_AUTO_TEST_CASE(GetSegmentationMustNotThrowIfDetElemIdIsValid)
bool checkSameCathode(const Segmentation &seg, int depadindex, const std::vector< int > &padindices)
int manu2ds(int deId, int ch)
double padSizeY(int catPadIndex) const
double padSizeX(int catPadIndex) const
int padDualSampaChannel(int catPadIndex) const
int padDualSampaId(int catPadIndex) const
double padPositionY(int catPadIndex) const
int findPadByFEE(int dualSampaId, int dualSampaChannel) const
double padPositionX(int catPadIndex) const
void forEachNeighbouringPad(int catPadIndex, CALLABLE &&func) const
bool isValid(int catPadIndex) const
Not every integer is a valid catPadIndex. This method will tell if catPadIndex is a valid one.
A Segmentation lets you find pads of a detection element and then inspect those pads.
bool findPadPairByPosition(double x, double y, int &bpad, int &nbpad) const
int findPadByFEE(int dualSampaId, int dualSampaChannel) const
bool isValid(int dePadIndex) const
GLdouble n
Definition glcorearb.h:1982
GLint GLenum GLint x
Definition glcorearb.h:403
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLenum const GLfloat * params
Definition glcorearb.h:272
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
O2MCHMAPPINGIMPL3_EXPORT const Segmentation & segmentation(int detElemId)
void forOneDetectionElementOfEachSegmentationType(CALLABLE &&func)
o2::mch::contour::BBox< double > getBBox(const CathodeSegmentation &seg)
void forEachDetectionElement(CALLABLE &&func)
Segmentation seg
std::map< std::string, ID > expected
std::set< int > nofDualSampas(std::array< int, N > deIds)
BOOST_CHECK_NO_THROW(algorithm::merge(target, other))
BOOST_TEST(digits==digitsD, boost::test_tools::per_element())
BOOST_CHECK_EQUAL(triggersD.size(), triggers.size())