ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
testMappedImage.cc
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
4#define BOOST_TEST_DYN_LINK
5#define BOOST_TEST_MODULE MappedImageTest
6
7#include "Device.h"
8#include "MappedImage.h"
10
11#include <boost/test/unit_test.hpp>
12
13using namespace boost::unit_test_framework;
14using namespace ChimeraTK;
15
16BOOST_AUTO_TEST_SUITE(MappedImageTestSuite)
17
19 unsigned bufLen = 100; // includes header: 64 bytes
22 setDMapFilePath("testMappedImage.dmap");
24 device.open("DUMMY");
25
26 buf.replace(device.getOneDRegisterAccessor<unsigned char>("DAQ/IMAGE", bufLen));
27 }
28};
29
31 // this test shows an example how to map user-defined opaque structs onto a byte array
32 struct AStruct : public OpaqueStructHeader {
33 int a = 0;
34 float x = 0, y = 1;
35 AStruct() : OpaqueStructHeader(typeid(AStruct)) {}
36 };
37
39 auto* h = ms.header();
40 h->x = 4.;
41 BOOST_CHECK(h->totalLength == sizeof(AStruct));
42
44 BOOST_CHECK(ms1.header()->x == 4.);
45 BOOST_CHECK(ms1.header()->y == 1.); // a value set in constructor of AStruct
46
47 buf.write();
48 // test that values can be restored by reading from device
49 ms.header()->x = 0;
50 buf.read();
51 BOOST_CHECK(ms.header()->x == 4.);
52}
53
55 // this test shows MappedImage usage
56
57 MappedImage A0(buf);
58 unsigned w = 4, h = 2;
59 A0.setShape(w, h, ImgFormat::Gray16);
60 auto Av = A0.interpretedView<uint16_t>();
61 Av(0, 0) = 8;
62 Av(1, 0) = 7;
63 Av(2, 0) = 6;
64 Av(3, 0) = 5;
65 Av(0, 1) = 4;
66 Av(1, 1) = 3;
67 Av(2, 1) = 2;
68 Av(3, 1) = 1;
69 float val = Av(2, 0);
70 BOOST_CHECK(val == 6);
71
72 // also test iterator-style access
73 for(unsigned y = 0; y < h; y++) {
74 unsigned x = 0;
75 for(auto* it = Av.beginRow(y); it != Av.endRow(y); ++it) {
76 BOOST_CHECK(*it == Av(x, y));
77 x++;
78 }
79 }
80 // iterate over whole image
81 unsigned counter = 0;
82 for(auto& pixVal : Av) {
83 pixVal = ++counter;
84 }
85 counter = 0;
86 for(auto& pixVal : Av) {
87 counter++;
88 BOOST_CHECK(pixVal == counter);
89 }
90
91 // test actual header contents of our buffer
92 auto* bufData0 = buf.data();
93 auto* head = reinterpret_cast<ImgHeader*>(bufData0);
94 BOOST_CHECK(head->width == w);
95 BOOST_CHECK(head->height == h);
96 BOOST_CHECK(head->image_format == ImgFormat::Gray16);
97 BOOST_CHECK(head->channels == 1);
98 BOOST_CHECK(head->bytesPerPixel == 2);
99
100 // test actual image body contents of buffer
101 auto* imgBody = reinterpret_cast<uint16_t*>(buf.data() + sizeof(ImgHeader));
102 unsigned i = 0;
103 for(auto& pixVal : Av) {
104 BOOST_CHECK(imgBody[i] == pixVal);
105 i++;
106 }
107
108 ImgHeader head0 = *head;
109 buf.write(); // this allows to analyse data in dummy device, e.g. with shm dummy
110 // set up memory location buf1 with slightly modified image content
111 std::vector<unsigned char> buf1(buf.getNElements());
112 *reinterpret_cast<ImgHeader*>(buf1.data()) = head0; // copy back header
113 auto* imgBody1 = reinterpret_cast<uint16_t*>(buf1.data() + sizeof(ImgHeader));
114 imgBody1[w * h - 1] = 42;
115 buf.swap(buf1);
116 BOOST_CHECK(buf.data() != bufData0);
117 // check that ImgView can still be used, even though user buffer of accessor was swapped
118 // compare bottow right value with previously written content.
119 auto lastVal = Av(w - 1, h - 1);
120 BOOST_CHECK(lastVal == 42);
121
122 // re-use as float and check pixel channel access
123 A0.setShape(2, 1, ImgFormat::FLOAT2);
124 auto AvFloat2 = A0.interpretedView<float>();
125 AvFloat2(0, 0, 1) = 0.1F;
126 AvFloat2(1, 0, 1) = 1.1F;
127 BOOST_TEST(AvFloat2(0, 0, 1) == 0.1F);
128 BOOST_TEST(AvFloat2(1, 0, 1) == 1.1F);
129}
130
131BOOST_AUTO_TEST_SUITE_END()
Class allows to read/write registers from device.
Definition Device.h:39
OneDRegisterAccessor< UserType > getOneDRegisterAccessor(const RegisterPath &registerPathName, size_t numberOfWords=0, size_t wordOffsetInRegister=0, const AccessModeFlags &flags=AccessModeFlags({})) const
Get a OneDRegisterAccessor object for the given register.
Definition Device.h:276
void open(std::string const &aliasName)
Open a device by the given alias name from the DMAP file.
Definition Device.cc:58
interface to an image that is mapped onto a 1D array of ValType
ImgView< UserType, OPTIONS > interpretedView()
returns an ImgView object which can be used like a matrix.
void setShape(unsigned width, unsigned height, ImgFormat fmt)
needs to be called after construction.
Provides interface to a struct that is mapped onto a 1D array of ValType StructHeader must be derived...
Definition MappedImage.h:38
StructHeader * header()
returns header, e.g. for setting meta data
Definition MappedImage.h:54
void replace(const NDRegisterAccessorAbstractor< UserType > &newAccessor)
Assign a new accessor to this NDRegisterAccessorAbstractor.
Accessor class to read and write registers transparently by using the accessor object like a vector o...
void setDMapFilePath(std::string dmapFilePath)
Set the location of the dmap file.
Image header.
Definition MappedImage.h:86
generic header for opaque struct handling It has fields needed for communication in the same process,...
Definition MappedImage.h:23
ChimeraTK::OneDRegisterAccessor< unsigned char > buf
ctk::Device device
BOOST_FIXTURE_TEST_CASE(testStructMapping, DummyFixture)