Belle II Software  release-06-01-15
ARICHDatabaseTools.h
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 #pragma once
9 
10 #include <algorithm>
11 #include <sstream>
12 
13 #include <array>
14 #include <cctype>
15 #include <cstdint>
16 #include <string>
17 #include <vector>
18 
19 namespace Belle2 {
24  namespace ARICHTools {
25 
30  class ModuleID_t {
31  public:
32  // range definitions
36  static constexpr auto m_gValidSectors =
37  std::array<uint8_t, 4>({{'A', 'B', 'C', 'D'}});
38 
42  static constexpr auto m_gMaxChannel = int8_t{36};
43 
49  static constexpr auto isValidChannel(const int channel) noexcept -> bool
50  {
51  return (channel >= 0) && (channel <= m_gMaxChannel);
52  }
53 
54  static auto isValidSector(const uint8_t sector) noexcept -> bool
55  {
56  return std::find(m_gValidSectors.begin(), m_gValidSectors.end(), sector) !=
57  m_gValidSectors.end();
58  }
59 
60  public:
68  ModuleID_t(const int8_t sector = '0', const int channel = 0) noexcept
69  : m_ID((sector << m_gMemberSize) | channel) {}
70 
76  explicit ModuleID_t(const uint16_t id) noexcept : m_ID(id) {}
77 
82  inline auto isValidID() const noexcept -> bool
83  {
84  return ModuleID_t::isValidSector(this->getSector()) &&
86  }
87 
93  inline auto getSector() const noexcept -> int8_t
94  {
95  return ((m_ID >> m_gMemberSize) & m_gMemberMask);
96  }
97 
103  inline auto getChannel() const noexcept -> int8_t
104  {
105  return (m_ID & m_gMemberMask);
106  }
107 
114  inline auto getNumbering() const noexcept -> int
115  {
116  return (this->getSector() - m_gValidSectors.front()) * m_gMaxChannel +
117  this->getChannel();
118  }
119 
125  friend inline auto operator<<(std::ostream& rStream, const ModuleID_t id)
126  -> std::ostream& {
127  rStream << id.getSector() << static_cast<int>(id.getChannel());
128  return rStream;
129  }
130 
135  inline auto operator==(const ModuleID_t& rOther) const noexcept -> bool
136  {
137  return m_ID == rOther.m_ID;
138  }
139 
144  inline auto operator!=(const ModuleID_t& rOther) const noexcept -> bool
145  {
146  return m_ID != rOther.m_ID;
147  }
148 
153  inline auto operator<(const ModuleID_t& rOther) const noexcept -> bool
154  {
155  return m_ID < rOther.m_ID;
156  }
157 
162  inline auto operator<=(const ModuleID_t& rOther) const noexcept -> bool
163  {
164  return m_ID <= rOther.m_ID;
165  }
166 
171  inline auto operator>(const ModuleID_t& rOther) const noexcept -> bool
172  {
173  return m_ID > rOther.m_ID;
174  }
175 
180  inline auto operator>=(const ModuleID_t& rOther) const noexcept -> bool
181  {
182  return m_ID >= rOther.m_ID;
183  }
184 
189  inline auto operator++() noexcept -> ModuleID_t&
190  {
191  m_ID = this->getChannel() >= m_gMaxChannel
192  ? (((this->getSector() + 1) << m_gMemberSize) | 1)
193  : m_ID + 1;
194  return *this;
195  }
196 
201  inline auto operator++(int)noexcept -> ModuleID_t
202  {
203  auto tmp = ModuleID_t(m_ID);
204  this->operator++();
205  return tmp;
206  }
207 
208  private:
212  static constexpr auto m_gMemberSize = sizeof(int8_t) * 8;
216  static constexpr auto m_gMemberMask = 0xff;
217 
221  uint16_t m_ID;
222  };
223  constexpr std::array<uint8_t, 4> ModuleID_t::m_gValidSectors;
224 
225  namespace PrivateHelperClasses {
226 // helper classes for the defined conversions
227 
231  template <typename Desired_t> struct TokenCast;
232 
236  template <> struct TokenCast<int> {
242  inline auto isValidChar(const unsigned char character) const noexcept
243  -> bool
244  {
245  return std::isdigit(character);
246  }
247 
256  inline auto operator()(const std::string& rToken) const -> int
257  {
258  return std::stoi(rToken);
259  }
260  };
261 
268  template <> struct TokenCast<double> {
274  inline auto isValidChar(const unsigned char character) const noexcept
275  -> bool
276  {
277  return std::isdigit(character) || (static_cast<unsigned char>('.') == character);
278  }
279 
288  inline auto operator()(const std::string& rToken) const -> double
289  {
290  return std::stod(rToken);
291  }
292  };
293 
297  template <> struct TokenCast<ModuleID_t> {
303  inline auto isValidChar(const unsigned char character) const noexcept
304  -> bool
305  {
306  return std::isdigit(character) || ModuleID_t::isValidSector(character);
307  }
308 
317  inline auto operator()(const std::string& rToken) const -> ModuleID_t
318  {
319  const auto begin =
320  std::find_if(rToken.begin(), rToken.end(),
321  [](const char c) { return !std::isspace(c); });
322  const auto end = std::find_if(begin, rToken.end(),
323  [](const char c) { return std::isspace(c); });
324 
325  if ((begin + 1 == end) || !std::all_of(begin, end, [this](const char c) {
326  return this->isValidChar(c);
327  }))
328  throw std::invalid_argument("Invalid argiment for module cast, got: '" +
329  rToken + "'!");
330 
331  const auto chID = std::stoi(std::string(begin + 1, end));
332  if (ModuleID_t::isValidSector(*begin) && ModuleID_t::isValidChannel(chID))
333  return ModuleID_t(*begin, chID);
334 
335  throw std::out_of_range("Module ID out of range. got: '" + rToken + "' !");
336  }
337  };
338  } // end namespace PrivateHelperClasses
339 
346  public:
350  static const std::string m_gRangeOperator;
351 
352  public:
364  template <typename T>
365  static inline auto convert(const std::string& rLine, const char delim = ' ')
366  -> std::vector<T> {
367  const auto cast = PrivateHelperClasses::TokenCast<T>();
368  // check if line only contains white space, numbers and delimiter char.
369  if (!std::all_of(rLine.begin(), rLine.end(),
370  [&cast, delim](const unsigned char c)
371  {
372  return std::isdigit(c) || std::isspace(c) ||
373  (c == delim) || cast.isValidChar(c);
374  }))
375  throw std::runtime_error("Detected invalid character in '" + rLine +
376  "'!");
377 
378  auto iss = std::istringstream(rLine);
379  auto retval = std::vector<T>();
380  auto token = std::string();
381 
382  // convert string to number and add it to vector...
383  while (std::getline(iss, token, delim))
384  try {
385  retval.emplace_back(cast(token));
386  } catch (const std::invalid_argument& rErr)
387  {
388  throw std::runtime_error("Invalid token, got:'" + token + "'! " +
389  rErr.what());
390  } catch (const std::out_of_range& rErr)
391  {
392  // if the values exceeds the requested type
393  throw std::runtime_error("Conversion out of range, got: '" + token +
394  "'! " + rErr.what());
395  }
396 
397  return retval;
398  }
399 
410  template <typename T>
411  static inline auto parse(const std::string& rLine, const char delim = ' ')
412  -> std::string {
413  auto out = std::stringstream();
414  auto iss = std::istringstream(rLine);
415  auto token = std::string();
416 
417  if (!std::getline(iss, token, delim))
418  return std::string();
419 
420  if (std::search(token.begin(), token.end(), m_gRangeOperator.begin(),
421  m_gRangeOperator.end()) != token.end())
422  {
423  StringToVector::expand<T>(out, delim, token);
424  } else {
425  out << token;
426  }
427 
428  // convert string to number and add it to vector...
429  while (std::getline(iss, token, delim))
430  try {
431  if (std::search(token.begin(), token.end(), m_gRangeOperator.begin(),
432  m_gRangeOperator.end()) != token.end())
433  {
434  out << ',';
435  StringToVector::expand<T>(out, delim, token);
436  } else {
437  out << delim << token;
438  }
439  } catch (const std::invalid_argument& rErr)
440  {
441  throw std::runtime_error("Invalid token, got:'" + token + "'! " +
442  rErr.what());
443  } catch (const std::out_of_range& rErr)
444  {
445  // if the values exceeds the requested type
446  throw std::runtime_error("Conversion out of range, got: '" + token +
447  "'! " + rErr.what());
448  }
449  return out.str();
450  }
451 
452  private:
462  template <typename T>
463  static inline auto expand(std::ostream& rStream, const char delim,
464  const std::string& rToken) -> std::ostream& {
465  auto itPos = std::search(rToken.begin(), rToken.end(),
466  m_gRangeOperator.begin(), m_gRangeOperator.end());
467  const auto cast = PrivateHelperClasses::TokenCast<T>();
468  auto lhs = cast(std::string(rToken.begin(), itPos));
469  std::advance(itPos, m_gRangeOperator.size());
470  auto rhs = cast(std::string(itPos, rToken.end()));
471 
472  if (lhs >= rhs)
473  throw std::runtime_error(
474  "Invalid expansion! lhs ist greater then rhs, got: '" + rToken +
475  "'!");
476 
477  rStream << lhs;
478  for (++lhs; lhs <= rhs; ++lhs)
479  rStream << delim << lhs;
480  return rStream;
481  }
482  };
483  const std::string StringToVector::m_gRangeOperator("~");
484 
494  auto getDeadCutList(const char chipID, const std::string& line)
495  -> std::vector<int> {
496  auto ids = StringToVector::convert<int>(line, ','); // can throw
497  for (auto& rID : ids)
498  rID = ModuleID_t(chipID, rID).getNumbering();
499 
500  return ids;
501  }
502 
514  std::string& remove_nondigit(std::string& s)
515  {
516  // changed to unsigned char see documention of std::isdigit in <cctype>
517  s.erase(remove_if(s.begin(), s.end(),
518  [](const unsigned char& c) { return !std::isdigit(c); }),
519  s.end());
520  return s;
521  }
522 
530  std::string& remove_chars_if_not(std::string& s, const std::string& allowed)
531  {
532  s.erase(remove_if(s.begin(), s.end(),
533  [&allowed](const char& c) {
534  return allowed.find(c) == std::string::npos;
535  }),
536  s.end());
537  return s;
538  }
539 
540  } // end namepace ARICHTools
542 } // end namepace Belle2
The ModuleID_t class is a intermediate object generated to contain configurations in a sorted fashion...
static constexpr auto isValidChannel(const int channel) noexcept -> bool
isValidChannel defines the range of valid channels.
auto getSector() const noexcept -> int8_t
getSector returns the definded sectors.
ModuleID_t(const int8_t sector='0', const int channel=0) noexcept
ModuleID_t is the default ctor that construct an id out of a sector id and channel number.
ModuleID_t(const uint16_t id) noexcept
ModuleID_t used to construct from a given integer that has a valid module ID.
auto operator<=(const ModuleID_t &rOther) const noexcept -> bool
comparison operator<=
auto operator>=(const ModuleID_t &rOther) const noexcept -> bool
comparison operator>=
auto isValidID() const noexcept -> bool
isValidID check is constructed id is valid
static constexpr auto m_gMemberSize
m_gMemberSize size of each sub ids
uint16_t m_ID
m_ID contains the unique sector and channel ids.
auto operator==(const ModuleID_t &rOther) const noexcept -> bool
comparison operator==
static constexpr auto m_gMaxChannel
m_gMaxChannel number of maximum channel starting from 0
auto operator!=(const ModuleID_t &rOther) const noexcept -> bool
comparison operator!=
auto operator++() noexcept -> ModuleID_t &
precrement operator ++X
auto getChannel() const noexcept -> int8_t
getChannel return the defined channel
static constexpr auto m_gMemberMask
m_gMemberMask is a mask to get the desired sub id info.
auto operator>(const ModuleID_t &rOther) const noexcept -> bool
comparison operator>
static constexpr auto m_gValidSectors
m_gValidSectors is a array containing allowed sector ids
auto operator++(int) noexcept -> ModuleID_t
postcrement operator X++
friend auto operator<<(std::ostream &rStream, const ModuleID_t id) -> std::ostream &
operator << to print the id using any std::ostream implementation...
auto getNumbering() const noexcept -> int
getNumbering returns the channel number Ax = 1+x; Bx = 36 + x; Cx = 72 + x; Dx = 108 + x; Note: an in...
auto operator<(const ModuleID_t &rOther) const noexcept -> bool
comparison operator<
The StringToVector class converts a given string to the std::vector<T>.
static auto convert(const std::string &rLine, const char delim=' ') -> std::vector< T >
convert<T> converts the given string in to a std::vector<T> elements seperated by the given delimiter
static const std::string m_gRangeOperator
m_gRangeOperator is a std::wstring containing the range symbold
static auto expand(std::ostream &rStream, const char delim, const std::string &rToken) -> std::ostream &
expand<T> applies the given range and fills the given std::ostream with each element in range seperat...
static auto parse(const std::string &rLine, const char delim=' ') -> std::string
parse<T> expands the given string and evaluats defined operators.
Abstract base class for different kinds of events.
auto isValidChar(const unsigned char character) const noexcept -> bool
isValidChar defines characters that are allowed for the convertion
auto operator()(const std::string &rToken) const -> ModuleID_t
operator () converts given token to an integer.
auto operator()(const std::string &rToken) const -> double
operator () converts given token to an integer.
auto isValidChar(const unsigned char character) const noexcept -> bool
isValidChar defines characters that are allowed for the convertion
auto operator()(const std::string &rToken) const -> int
operator () converts given token to an integer.
auto isValidChar(const unsigned char character) const noexcept -> bool
isValidChar defines characters that are allowed for the convertion