Belle II Software development
ChannelMapper.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <top/geometry/ChannelMapper.h>
10#include <framework/database/DBImportArray.h>
11#include <unordered_set>
12#include <framework/logging/LogSystem.h>
13#include <iostream>
14
15using namespace std;
16
17namespace Belle2 {
22 namespace TOP {
23
25 {
27 "TOP::ChannelMapper: bug in coding (enum) - "
28 "number of channels and number of pixels disagree");
29
30 for (auto& channels : m_channels) {
31 for (auto& channel : channels) channel = 0;
32 }
33 for (auto& pixels : m_pixels) {
34 for (auto& pixel : pixels) pixel = 0;
35 }
36 }
37
38
39 void ChannelMapper::initialize(const GearDir& channelMapping)
40 {
41 clear();
42
43 string path = channelMapping.getPath();
44 auto i1 = path.rfind("type='") + 6;
45 auto i2 = path.rfind("']");
46 m_typeName = path.substr(i1, i2 - i1);
47
48 if (m_typeName == "IRS3B") {
49 m_type = c_IRS3B;
50 } else if (m_typeName == "IRSX") {
51 m_type = c_IRSX;
52 } else {
53 B2ERROR("TOP::ChannelMapper: unknown electronic type."
54 << LogVar("type", m_typeName));
55 }
56
57 // get parameters from Gearbox
58 for (const GearDir& map : channelMapping.getNodes("map")) {
59 std::vector<double> data = map.getArray("");
60 unsigned row = int(data[0]) - 1;
61 unsigned col = int(data[1]) - 1;
62 unsigned asic = int(data[2]);
63 unsigned chan = int(data[3]);
64 m_mapping.push_back(TOPChannelMap(row, col, asic, chan));
65 }
66 if (m_mapping.empty()) {
67 B2ERROR("TOP::ChannelMapper: mapping is not available in Gearbox");
68 return;
69 }
70
71 // check the size of the mapping
72 if (m_mapping.size() != c_numAsics * c_numChannels)
73 B2FATAL("TOP::ChannelMapper: got incorrect map size from xml file for '"
74 << m_typeName << "' - expect " << c_numAsics * c_numChannels
75 << ", got " << m_mapping.size());
76
77 // check the mapping for consistency
78 bool ok = true;
79 unordered_set<unsigned> pixels;
80 unordered_set<unsigned> channels;
81 for (unsigned ii = 0; ii < m_mapping.size(); ii++) {
82 const auto& map = m_mapping[ii];
83 unsigned row = map.getRow();
84 unsigned col = map.getColumn();
85 unsigned asic = map.getASICNumber();
86 unsigned chan = map.getASICChannel();
87 if (row >= c_numRows) {
88 B2ERROR("TOP::ChannelMapper: pixel row out of range."
89 << LogVar("node", ii)
90 << LogVar("row", row)
91 << LogVar("column", col)
92 << LogVar("ASIC", asic)
93 << LogVar("channel", chan));
94 ok = false;
95 }
96 if (col >= c_numColumns) {
97 B2ERROR("TOP::ChannelMapper: pixel column out of range."
98 << LogVar("node", ii)
99 << LogVar("row", row)
100 << LogVar("column", col)
101 << LogVar("ASIC", asic)
102 << LogVar("channel", chan));
103 ok = false;
104 }
105 if (asic >= c_numAsics) {
106 B2ERROR("TOP::ChannelMapper: ASIC number out of range."
107 << LogVar("node", ii)
108 << LogVar("row", row)
109 << LogVar("column", col)
110 << LogVar("ASIC", asic)
111 << LogVar("channel", chan));
112 ok = false;
113 }
114 if (chan >= c_numChannels) {
115 B2ERROR("TOP::ChannelMapper: ASIC channel number out of range."
116 << LogVar("node", ii)
117 << LogVar("row", row)
118 << LogVar("column", col)
119 << LogVar("ASIC", asic)
120 << LogVar("channel", chan));
121 ok = false;
122 }
123 if (!pixels.insert(col + row * c_numColumns).second) {
124 B2ERROR("TOP::ChannelMapper: pixel already mapped."
125 << LogVar("node", ii)
126 << LogVar("row", row)
127 << LogVar("column", col)
128 << LogVar("ASIC", asic)
129 << LogVar("channel", chan));
130 ok = false;
131 }
132 if (!channels.insert(chan + asic * c_numChannels).second) {
133 B2ERROR("TOP::ChannelMapper: channel already mapped."
134 << LogVar("node", ii)
135 << LogVar("row", row)
136 << LogVar("column", col)
137 << LogVar("ASIC", asic)
138 << LogVar("channel", chan));
139 ok = false;
140 }
141 }
142 if (!ok) {
143 B2FATAL("TOP::ChannelMapper: errors detected in xml file for '"
144 << m_typeName << "'");
145 return;
146 }
147
148 // prepare conversion arrays
149 for (const auto& map : m_mapping) {
150 m_channels[map.getRow()][map.getColumn()] = &map;
151 m_pixels[map.getASICNumber()][map.getASICChannel()] = &map;
152 }
153 m_valid = true;
154
155 B2INFO("TOP::ChannelMapper: " << m_mapping.size() <<
156 " channels of carrier board of type '" << m_typeName
157 << "' mapped to pixels.");
158
159 // print mappings if debug level for package 'top' is set to 100 or larger
160 const auto& logSystem = LogSystem::Instance();
161 if (logSystem.isLevelEnabled(LogConfig::c_Debug, 100, "top")) {
162 print();
163 }
164
165 }
166
167
169 {
170 m_type = c_default;
171
172 if (!m_mappingDB.isValid()) {
173 clear();
174 return;
175 }
176 update();
177
178 m_mappingDB.addCallback(this, &ChannelMapper::update);
179
180 const auto& logSystem = LogSystem::Instance();
181 if (logSystem.isLevelEnabled(LogConfig::c_Debug, 100, "top")) {
182 print();
183 }
184
185 }
186
187
189 {
191 for (const auto& map : m_mapping) {
192 array.appendNew(map);
193 }
194 array.import(iov);
195 }
196
197
198 unsigned ChannelMapper::getChannel(int pixel) const
199 {
200 if (!isPixelIDValid(pixel)) return c_invalidChannel; // cppcheck-suppress knownConditionTrueFalse
201
202 unsigned pix = pixel - 1;
203 unsigned pixRow = pix / c_numPixelColumns;
204 unsigned pixCol = pix % c_numPixelColumns;
205
206 unsigned carrier = pixRow / c_numRows;
207 unsigned row = pixRow % c_numRows;
208 unsigned boardstack = pixCol / c_numColumns;
209 unsigned col = pixCol % c_numColumns;
210
211 const auto& map = m_channels[row][col];
212 if (!map) {
213 B2WARNING("TOP::ChannelMapper: no channel mapped to pixel. Return invalid channel."
214 << LogVar("pixelID", pixel));
215 return c_invalidChannel;
216 }
217 unsigned asic = map->getASICNumber();
218 unsigned chan = map->getASICChannel();
219
220 return getChannel(boardstack, carrier, asic, chan);
221 }
222
223
225 unsigned& boardstack,
226 unsigned& carrier,
227 unsigned& asic,
228 unsigned& chan)
229 {
230 chan = channel % c_numChannels;
231 channel /= c_numChannels;
232 asic = channel % c_numAsics;
233 channel /= c_numAsics;
234 carrier = channel % c_numCarrierBoards;
235 boardstack = channel / c_numCarrierBoards;
236 }
237
238
239 int ChannelMapper::getPixelID(unsigned channel) const
240 {
241
242 if (!isChannelValid(channel)) return c_invalidPixelID;
243
244 unsigned boardstack = 0;
245 unsigned carrier = 0;
246 unsigned asic = 0;
247 unsigned chan = 0;
248 splitChannelNumber(channel, boardstack, carrier, asic, chan);
249
250 const auto& map = m_pixels[asic][chan];
251 if (!map) {
252 B2ERROR("TOP::ChannelMapper: no pixel mapped to channel. Return invalid pixel."
253 << LogVar("channel", channel));
254 return c_invalidPixelID;
255 }
256 unsigned row = map->getRow();
257 unsigned col = map->getColumn();
258 unsigned pixRow = row + carrier * c_numRows;
259 unsigned pixCol = col + boardstack * c_numColumns;
260
261 return pixCol + pixRow * c_numPixelColumns + 1;
262
263 }
264
266 {
267 if (not isPixelIDValid(pixel)) return 0; // cppcheck-suppress knownConditionTrueFalse
268 pixel--;
269 int pmtRow = pixel / 256;
270 int pmtCol = (pixel % 64) / 4;
271 return pmtRow * 16 + pmtCol + 1;
272 }
273
275 {
276 std::vector<std::string> what;
277 what.push_back(string("Boardstack numbers (view from the back):"));
278 what.push_back(string("Carrier board numbers (view from the back):"));
279 what.push_back(string("ASIC numbers (view from the back):"));
280 what.push_back(string("ASIC channel numbers (view from the back):"));
281 unsigned value[4] = {0, 0, 0, 0};
282
283 std::string xaxis("+------phi--------->");
284 std::string yaxis("|ohr|||^");
285
286 cout << endl;
287 cout << " Mapping of TOP electronic channels to pixels";
288 if (!m_typeName.empty()) cout << " for " << m_typeName;
289 cout << endl << endl;
290
291 for (int i = 0; i < 4; i++) {
292 cout << " " << what[i] << endl << endl;
293 for (int row = c_numPixelRows - 1; row >= 0; row--) {
294 cout << " " << yaxis[row] << " ";
295 for (int col = 0; col < c_numPixelColumns; col++) {
296 int pixel = col + c_numPixelColumns * row + 1;
297 auto channel = getChannel(pixel);
298 if (channel != c_invalidChannel) {
299 splitChannelNumber(channel, value[0], value[1], value[2], value[3]);
300 cout << value[i];
301 } else {
302 cout << "?";
303 }
304 }
305 cout << endl;
306 }
307 cout << " " << xaxis << endl << endl;
308 }
309
310 }
311
313 {
314 for (int pixel = 1; pixel <= c_numPixels; pixel++)
315 if (pixel != getPixelID(getChannel(pixel)))
316 B2ERROR("TOP::ChannelMapper: bug, getPixelID is not inverse of getChannel");
317
318 for (unsigned channel = 0; channel < c_numPixels; channel++)
319 if (channel != getChannel(getPixelID(channel)))
320 B2ERROR("TOP::ChannelMapper: bug, getChannel is not inverse of getPixelID");
321 }
322
323
325 {
326 m_mapping.clear();
327 for (auto& channels : m_channels) {
328 for (auto& channel : channels) channel = 0;
329 }
330 for (auto& pixels : m_pixels) {
331 for (auto& pixel : pixels) pixel = 0;
332 }
333 m_valid = false;
334 m_fromDB = false;
335 }
336
337
339 {
340 clear();
341 if (!m_mappingDB.isValid()) return;
342
343 for (const auto& map : m_mappingDB) {
344 m_channels[map.getRow()][map.getColumn()] = &map;
345 m_pixels[map.getASICNumber()][map.getASICChannel()] = &map;
346 }
347 m_valid = true;
348 m_fromDB = true;
349 }
350
351
352
353 } // TOP namespace
355} // Belle2 namespace
Class for importing array of objects to the database.
bool import(const IntervalOfValidity &iov)
Import the object to database.
GearDir is the basic class used for accessing the parameter store.
Definition GearDir.h:31
A class that describes the interval of experiments/runs for which an object in the database is valid.
@ c_Debug
Debug: for code development.
Definition LogConfig.h:26
static LogSystem & Instance()
Static method to get a reference to the LogSystem instance.
Definition LogSystem.cc:28
Map of pixels and channels within the carrier board.
EType m_type
electornic type
void test() const
test that the conversion and inverse of it gives identity, if not B2ERROR
void initialize()
Initialize from database.
bool m_fromDB
true, if from database
std::vector< TOPChannelMap > m_mapping
mappings from gearbox
static bool isChannelValid(unsigned channel)
Checks validity of hardware channel number.
DBArray< TOPChannelMap > m_mappingDB
mappings from database
const TOPChannelMap * m_pixels[c_numAsics][c_numChannels]
conversion array
@ c_numCarrierBoards
number of carrier boards per boardstack
@ c_numColumns
number of pixel columns per carrier board
@ c_numChannels
number of channels per ASIC
@ c_numRows
number of pixel rows per carrier board
@ c_invalidChannel
value of invalid channel number
@ c_invalidPixelID
value of invalid pixel ID
@ c_numAsics
number of ASIC's per carrier board
static void splitChannelNumber(unsigned channel, unsigned &boardstack, unsigned &carrier, unsigned &asic, unsigned &chan)
Splits hardware channel number into boardstack, carrier, asic and asic channel.
int getPixelID(unsigned channel) const
Converts hardware channel number to pixel ID (1-based)
static int getPmtID(int pixel)
Returns PMT ID (1-based)
bool m_valid
true if mapping available
void update()
re-do conversion arrays when DBArray has changed
void importPayload(const IntervalOfValidity &iov) const
import mappings to database
void print() const
Print mappings to terminal screen.
static bool isPixelIDValid(int pixel)
Checks validity of pixel ID.
const TOPChannelMap * m_channels[c_numRows][c_numColumns]
conversion array
unsigned getChannel(int pixel) const
Converts pixel to hardware channel number (0-based)
std::string m_typeName
electronic type name
std::string getPath() const
Return path of the current interface.
Definition Interface.h:70
std::vector< GearDir > getNodes(const std::string &path="") const
Get vector of GearDirs which point to all the nodes the given path evaluates to.
Definition Interface.cc:21
Class to store variables with their name which were sent to the logging service.
Abstract base class for different kinds of events.
STL namespace.