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