Belle II Software  release-08-01-10
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 
15 using namespace std;
16 
17 namespace Belle2 {
22  namespace TOP {
23 
24  ChannelMapper::ChannelMapper()
25  {
26  static_assert(c_numRows * c_numColumns == c_numAsics * c_numChannels,
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  ChannelMapper::~ChannelMapper()
40  {
41  if (m_mappingDB) delete m_mappingDB;
42  }
43 
44  void ChannelMapper::initialize(const GearDir& channelMapping)
45  {
46 
47  clear();
48 
49  string path = channelMapping.getPath();
50  auto i1 = path.rfind("type='") + 6;
51  auto i2 = path.rfind("']");
52  m_typeName = path.substr(i1, i2 - i1);
53 
54  if (m_typeName == "IRS3B") {
55  m_type = c_IRS3B;
56  } else if (m_typeName == "IRSX") {
57  m_type = c_IRSX;
58  } else {
59  B2ERROR("TOP::ChannelMapper: unknown electronic type."
60  << LogVar("type", m_typeName));
61  }
62 
63  // get parameters from Gearbox
64  for (const GearDir& map : channelMapping.getNodes("map")) {
65  std::vector<double> data = map.getArray("");
66  unsigned row = int(data[0]) - 1;
67  unsigned col = int(data[1]) - 1;
68  unsigned asic = int(data[2]);
69  unsigned chan = int(data[3]);
70  m_mapping.push_back(TOPChannelMap(row, col, asic, chan));
71  }
72  if (m_mapping.empty()) {
73  B2ERROR("TOP::ChannelMapper: mapping is not available in Gearbox");
74  return;
75  }
76 
77  // check the size of the mapping
78  if (m_mapping.size() != c_numAsics * c_numChannels)
79  B2FATAL("TOP::ChannelMapper: got incorrect map size from xml file for '"
80  << m_typeName << "' - expect " << c_numAsics * c_numChannels
81  << ", got " << m_mapping.size());
82 
83  // check the mapping for consistency
84  bool ok = true;
85  unordered_set<unsigned> pixels;
86  unordered_set<unsigned> channels;
87  for (unsigned ii = 0; ii < m_mapping.size(); ii++) {
88  const auto& map = m_mapping[ii];
89  unsigned row = map.getRow();
90  unsigned col = map.getColumn();
91  unsigned asic = map.getASICNumber();
92  unsigned chan = map.getASICChannel();
93  if (row >= c_numRows) {
94  B2ERROR("TOP::ChannelMapper: pixel row out of range."
95  << LogVar("node", ii)
96  << LogVar("row", row)
97  << LogVar("column", col)
98  << LogVar("ASIC", asic)
99  << LogVar("channel", chan));
100  ok = false;
101  }
102  if (col >= c_numColumns) {
103  B2ERROR("TOP::ChannelMapper: pixel column out of range."
104  << LogVar("node", ii)
105  << LogVar("row", row)
106  << LogVar("column", col)
107  << LogVar("ASIC", asic)
108  << LogVar("channel", chan));
109  ok = false;
110  }
111  if (asic >= c_numAsics) {
112  B2ERROR("TOP::ChannelMapper: ASIC number out of range."
113  << LogVar("node", ii)
114  << LogVar("row", row)
115  << LogVar("column", col)
116  << LogVar("ASIC", asic)
117  << LogVar("channel", chan));
118  ok = false;
119  }
120  if (chan >= c_numChannels) {
121  B2ERROR("TOP::ChannelMapper: ASIC channel number out of range."
122  << LogVar("node", ii)
123  << LogVar("row", row)
124  << LogVar("column", col)
125  << LogVar("ASIC", asic)
126  << LogVar("channel", chan));
127  ok = false;
128  }
129  if (!pixels.insert(col + row * c_numColumns).second) {
130  B2ERROR("TOP::ChannelMapper: pixel already mapped."
131  << LogVar("node", ii)
132  << LogVar("row", row)
133  << LogVar("column", col)
134  << LogVar("ASIC", asic)
135  << LogVar("channel", chan));
136  ok = false;
137  }
138  if (!channels.insert(chan + asic * c_numChannels).second) {
139  B2ERROR("TOP::ChannelMapper: channel already mapped."
140  << LogVar("node", ii)
141  << LogVar("row", row)
142  << LogVar("column", col)
143  << LogVar("ASIC", asic)
144  << LogVar("channel", chan));
145  ok = false;
146  }
147  }
148  if (!ok) {
149  B2FATAL("TOP::ChannelMapper: errors detected in xml file for '"
150  << m_typeName << "'");
151  return;
152  }
153 
154  // prepare conversion arrays
155  for (const auto& map : m_mapping) {
156  m_channels[map.getRow()][map.getColumn()] = &map;
157  m_pixels[map.getASICNumber()][map.getASICChannel()] = &map;
158  }
159  m_valid = true;
160 
161  B2INFO("TOP::ChannelMapper: " << m_mapping.size() <<
162  " channels of carrier board of type '" << m_typeName
163  << "' mapped to pixels.");
164 
165  // print mappings if debug level for package 'top' is set to 100 or larger
166  const auto& logSystem = LogSystem::Instance();
167  if (logSystem.isLevelEnabled(LogConfig::c_Debug, 100, "top")) {
168  print();
169  }
170 
171  }
172 
173 
174  void ChannelMapper::initialize()
175  {
176  m_type = c_default;
177 
178  if (m_mappingDB) delete m_mappingDB;
179  m_mappingDB = new DBArray<TOPChannelMap>();
180 
181  if (!m_mappingDB->isValid()) {
182  clear();
183  return;
184  }
185  update();
186 
187  m_mappingDB->addCallback(this, &ChannelMapper::update);
188 
189  const auto& logSystem = LogSystem::Instance();
190  if (logSystem.isLevelEnabled(LogConfig::c_Debug, 100, "top")) {
191  print();
192  }
193 
194  }
195 
196 
197  void ChannelMapper::importPayload(const IntervalOfValidity& iov) const
198  {
200  for (const auto& map : m_mapping) {
201  array.appendNew(map);
202  }
203  array.import(iov);
204  }
205 
206 
207  unsigned ChannelMapper::getChannel(int pixel) const
208  {
209  if (!isPixelIDValid(pixel)) return c_invalidChannel;
210 
211  unsigned pix = pixel - 1;
212  unsigned pixRow = pix / c_numPixelColumns;
213  unsigned pixCol = pix % c_numPixelColumns;
214 
215  unsigned carrier = pixRow / c_numRows;
216  unsigned row = pixRow % c_numRows;
217  unsigned boardstack = pixCol / c_numColumns;
218  unsigned col = pixCol % c_numColumns;
219 
220  const auto& map = m_channels[row][col];
221  if (!map) {
222  B2WARNING("TOP::ChannelMapper: no channel mapped to pixel. Return invalid channel."
223  << LogVar("pixelID", pixel));
224  return c_invalidChannel;
225  }
226  unsigned asic = map->getASICNumber();
227  unsigned chan = map->getASICChannel();
228 
229  return getChannel(boardstack, carrier, asic, chan);
230  }
231 
232 
233  void ChannelMapper::splitChannelNumber(unsigned channel,
234  unsigned& boardstack,
235  unsigned& carrier,
236  unsigned& asic,
237  unsigned& chan) const
238  {
239  chan = channel % c_numChannels;
240  channel /= c_numChannels;
241  asic = channel % c_numAsics;
242  channel /= c_numAsics;
243  carrier = channel % c_numCarrierBoards;
244  boardstack = channel / c_numCarrierBoards;
245  }
246 
247 
248  int ChannelMapper::getPixelID(unsigned channel) const
249  {
250 
251  if (!isChannelValid(channel)) return c_invalidPixelID;
252 
253  unsigned boardstack = 0;
254  unsigned carrier = 0;
255  unsigned asic = 0;
256  unsigned chan = 0;
257  splitChannelNumber(channel, boardstack, carrier, asic, chan);
258 
259  const auto& map = m_pixels[asic][chan];
260  if (!map) {
261  B2ERROR("TOP::ChannelMapper: no pixel mapped to channel. Return invalid pixel."
262  << LogVar("channel", channel));
263  return c_invalidPixelID;
264  }
265  unsigned row = map->getRow();
266  unsigned col = map->getColumn();
267  unsigned pixRow = row + carrier * c_numRows;
268  unsigned pixCol = col + boardstack * c_numColumns;
269 
270  return pixCol + pixRow * c_numPixelColumns + 1;
271 
272  }
273 
274  int ChannelMapper::getPmtID(int pixel) const
275  {
276  if (not isPixelIDValid(pixel)) return 0;
277  pixel--;
278  int pmtRow = pixel / 256;
279  int pmtCol = (pixel % 64) / 4;
280  return pmtRow * 16 + pmtCol + 1;
281  }
282 
283  void ChannelMapper::print() const
284  {
285  std::vector<std::string> what;
286  what.push_back(string("Boardstack numbers (view from the back):"));
287  what.push_back(string("Carrier board numbers (view from the back):"));
288  what.push_back(string("ASIC numbers (view from the back):"));
289  what.push_back(string("ASIC channel numbers (view from the back):"));
290  unsigned value[4] = {0, 0, 0, 0};
291 
292  std::string xaxis("+------phi--------->");
293  std::string yaxis("|ohr|||^");
294 
295  cout << endl;
296  cout << " Mapping of TOP electronic channels to pixels";
297  if (!m_typeName.empty()) cout << " for " << m_typeName;
298  cout << endl << endl;
299 
300  for (int i = 0; i < 4; i++) {
301  cout << " " << what[i] << endl << endl;
302  for (int row = c_numPixelRows - 1; row >= 0; row--) {
303  cout << " " << yaxis[row] << " ";
304  for (int col = 0; col < c_numPixelColumns; col++) {
305  int pixel = col + c_numPixelColumns * row + 1;
306  auto channel = getChannel(pixel);
307  if (channel != c_invalidChannel) {
308  splitChannelNumber(channel, value[0], value[1], value[2], value[3]);
309  cout << value[i];
310  } else {
311  cout << "?";
312  }
313  }
314  cout << endl;
315  }
316  cout << " " << xaxis << endl << endl;
317  }
318 
319  }
320 
321  void ChannelMapper::test() const
322  {
323  for (int pixel = 1; pixel <= c_numPixels; pixel++)
324  if (pixel != getPixelID(getChannel(pixel)))
325  B2ERROR("TOP::ChannelMapper: bug, getPixelID is not inverse of getChannel");
326 
327  for (unsigned channel = 0; channel < c_numPixels; channel++)
328  if (channel != getChannel(getPixelID(channel)))
329  B2ERROR("TOP::ChannelMapper: bug, getChannel is not inverse of getPixelID");
330  }
331 
332 
333  void ChannelMapper::clear()
334  {
335  m_mapping.clear();
336  for (auto& channels : m_channels) {
337  for (auto& channel : channels) channel = 0;
338  }
339  for (auto& pixels : m_pixels) {
340  for (auto& pixel : pixels) pixel = 0;
341  }
342  m_valid = false;
343  m_fromDB = false;
344  }
345 
346 
347  void ChannelMapper::update()
348  {
349  clear();
350  if (!m_mappingDB->isValid()) return;
351 
352  for (const auto& map : *m_mappingDB) {
353  m_channels[map.getRow()][map.getColumn()] = &map;
354  m_pixels[map.getASICNumber()][map.getASICChannel()] = &map;
355  }
356  m_valid = true;
357  m_fromDB = true;
358  }
359 
360 
361 
362  } // TOP namespace
364 } // Belle2 namespace
Class for accessing arrays of objects in the database.
Definition: DBArray.h:26
Class for importing array of objects to the database.
Definition: DBImportArray.h:25
T * appendNew()
Construct a new T object at the end of the array.
Definition: DBImportArray.h:67
bool import(const IntervalOfValidity &iov)
Import the object to database.
Definition: DBImportBase.cc:36
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.
Map of pixels and channels within the carrier board.
Definition: TOPChannelMap.h:22
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.