Belle II Software  release-05-01-25
ARICHDatabaseTools.h
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2017 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Manca Mrvar *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 #pragma once
11 
12 #include <algorithm>
13 #include <sstream>
14 
15 #include <array>
16 #include <cctype>
17 #include <cstdint>
18 #include <string>
19 #include <vector>
20 
21 namespace Belle2 {
26  namespace ARICHTools {
27 
32  class ModuleID_t {
33  public:
34  // range definitions
38  static constexpr auto m_gValidSectors =
39  std::array<uint8_t, 4>({{'A', 'B', 'C', 'D'}});
40 
44  static constexpr auto m_gMaxChannel = int8_t{36};
45 
51  static constexpr auto isValidChannel(const int channel) noexcept -> bool
52  {
53  return (channel >= 0) && (channel <= m_gMaxChannel);
54  }
55 
56  static auto isValidSector(const uint8_t sector) noexcept -> bool
57  {
58  return std::find(m_gValidSectors.begin(), m_gValidSectors.end(), sector) !=
60  }
61 
62  public:
70  ModuleID_t(const int8_t sector = '0', const int channel = 0) noexcept
71  : m_ID((sector << m_gMemberSize) | channel) {}
72 
78  explicit ModuleID_t(const uint16_t id) noexcept : m_ID(id) {}
79 
84  inline auto isValidID() const noexcept -> bool
85  {
86  return ModuleID_t::isValidSector(this->getSector()) &&
88  }
89 
95  inline auto getSector() const noexcept -> int8_t
96  {
97  return ((m_ID >> m_gMemberSize) & m_gMemberMask);
98  }
99 
105  inline auto getChannel() const noexcept -> int8_t
106  {
107  return (m_ID & m_gMemberMask);
108  }
109 
116  inline auto getNumbering() const noexcept -> int
117  {
118  return (this->getSector() - m_gValidSectors.front()) * m_gMaxChannel +
119  this->getChannel();
120  }
121 
127  friend inline auto operator<<(std::ostream& rStream, const ModuleID_t id)
128  -> std::ostream& {
129  rStream << id.getSector() << static_cast<int>(id.getChannel());
130  return rStream;
131  }
132 
137  inline auto operator==(const ModuleID_t& rOther) const noexcept -> bool
138  {
139  return m_ID == rOther.m_ID;
140  }
141 
146  inline auto operator!=(const ModuleID_t& rOther) const noexcept -> bool
147  {
148  return m_ID != rOther.m_ID;
149  }
150 
155  inline auto operator<(const ModuleID_t& rOther) const noexcept -> bool
156  {
157  return m_ID < rOther.m_ID;
158  }
159 
164  inline auto operator<=(const ModuleID_t& rOther) const noexcept -> bool
165  {
166  return m_ID <= rOther.m_ID;
167  }
168 
173  inline auto operator>(const ModuleID_t& rOther) const noexcept -> bool
174  {
175  return m_ID > rOther.m_ID;
176  }
177 
182  inline auto operator>=(const ModuleID_t& rOther) const noexcept -> bool
183  {
184  return m_ID >= rOther.m_ID;
185  }
186 
191  inline auto operator++() noexcept -> ModuleID_t&
192  {
193  m_ID = this->getChannel() >= m_gMaxChannel
194  ? (((this->getSector() + 1) << m_gMemberSize) | 1)
195  : m_ID + 1;
196  return *this;
197  }
198 
203  inline auto operator++(int)noexcept -> ModuleID_t
204  {
205  auto tmp = ModuleID_t(m_ID);
206  this->operator++();
207  return tmp;
208  }
209 
210  private:
214  static constexpr auto m_gMemberSize = sizeof(int8_t) * 8;
218  static constexpr auto m_gMemberMask = 0xff;
219 
223  uint16_t m_ID;
224  };
225  constexpr std::array<uint8_t, 4> ModuleID_t::m_gValidSectors;
226 
227  namespace PrivateHelperClasses {
228 // helper classes for the defined conversions
229 
233  template <typename Desired_t> struct TokenCast;
234 
238  template <> struct TokenCast<int> {
244  inline auto isValidChar(const unsigned char character) const noexcept
245  -> bool
246  {
247  return std::isdigit(character);
248  }
249 
258  inline auto operator()(const std::string& rToken) const -> int
259  {
260  return std::stoi(rToken);
261  }
262  };
263 
270  template <> struct TokenCast<double> {
276  inline auto isValidChar(const unsigned char character) const noexcept
277  -> bool
278  {
279  return std::isdigit(character) || (static_cast<unsigned char>('.') == character);
280  }
281 
290  inline auto operator()(const std::string& rToken) const -> double
291  {
292  return std::stod(rToken);
293  }
294  };
295 
299  template <> struct TokenCast<ModuleID_t> {
305  inline auto isValidChar(const unsigned char character) const noexcept
306  -> bool
307  {
308  return std::isdigit(character) || ModuleID_t::isValidSector(character);
309  }
310 
319  inline auto operator()(const std::string& rToken) const -> ModuleID_t
320  {
321  const auto begin =
322  std::find_if(rToken.begin(), rToken.end(),
323  [](const char c) { return !std::isspace(c); });
324  const auto end = std::find_if(begin, rToken.end(),
325  [](const char c) { return std::isspace(c); });
326 
327  if ((begin + 1 == end) || !std::all_of(begin, end, [this](const char c) {
328  return this->isValidChar(c);
329  }))
330  throw std::invalid_argument("Invalid argiment for module cast, got: '" +
331  rToken + "'!");
332 
333  const auto chID = std::stoi(std::string(begin + 1, end));
334  if (ModuleID_t::isValidSector(*begin) && ModuleID_t::isValidChannel(chID))
335  return ModuleID_t(*begin, chID);
336 
337  throw std::out_of_range("Module ID out of range. got: '" + rToken + "' !");
338  }
339  };
340  } // end namespace PrivateHelperClasses
341 
347  class StringToVector {
348  public:
352  static const std::string m_gRangeOperator;
353 
354  public:
366  template <typename T>
367  static inline auto convert(const std::string& rLine, const char delim = ' ')
368  -> std::vector<T> {
369  const auto cast = PrivateHelperClasses::TokenCast<T>();
370  // check if line only contains white space, numbers and delimiter char.
371  if (!std::all_of(rLine.begin(), rLine.end(),
372  [&cast, delim](const unsigned char c)
373  {
374  return std::isdigit(c) || std::isspace(c) ||
375  (c == delim) || cast.isValidChar(c);
376  }))
377  throw std::runtime_error("Detected invalid character in '" + rLine +
378  "'!");
379 
380  auto iss = std::istringstream(rLine);
381  auto retval = std::vector<T>();
382  auto token = std::string();
383 
384  // convert string to number and add it to vector...
385  while (std::getline(iss, token, delim))
386  try {
387  retval.emplace_back(cast(token));
388  } catch (const std::invalid_argument& rErr)
389  {
390  throw std::runtime_error("Invalid token, got:'" + token + "'! " +
391  rErr.what());
392  } catch (const std::out_of_range& rErr)
393  {
394  // if the values exceeds the requested type
395  throw std::runtime_error("Conversion out of range, got: '" + token +
396  "'! " + rErr.what());
397  }
398 
399  return retval;
400  }
401 
412  template <typename T>
413  static inline auto parse(const std::string& rLine, const char delim = ' ')
414  -> std::string {
415  auto out = std::stringstream();
416  auto iss = std::istringstream(rLine);
417  auto token = std::string();
418 
419  if (!std::getline(iss, token, delim))
420  return std::string();
421 
422  if (std::search(token.begin(), token.end(), m_gRangeOperator.begin(),
423  m_gRangeOperator.end()) != token.end())
424  {
425  StringToVector::expand<T>(out, delim, token);
426  } else {
427  out << token;
428  }
429 
430  // convert string to number and add it to vector...
431  while (std::getline(iss, token, delim))
432  try {
433  if (std::search(token.begin(), token.end(), m_gRangeOperator.begin(),
434  m_gRangeOperator.end()) != token.end())
435  {
436  out << ',';
437  StringToVector::expand<T>(out, delim, token);
438  } else {
439  out << delim << token;
440  }
441  } catch (const std::invalid_argument& rErr)
442  {
443  throw std::runtime_error("Invalid token, got:'" + token + "'! " +
444  rErr.what());
445  } catch (const std::out_of_range& rErr)
446  {
447  // if the values exceeds the requested type
448  throw std::runtime_error("Conversion out of range, got: '" + token +
449  "'! " + rErr.what());
450  }
451  return out.str();
452  }
453 
454  private:
464  template <typename T>
465  static inline auto expand(std::ostream& rStream, const char delim,
466  const std::string& rToken) -> std::ostream& {
467  auto itPos = std::search(rToken.begin(), rToken.end(),
468  m_gRangeOperator.begin(), m_gRangeOperator.end());
469  const auto cast = PrivateHelperClasses::TokenCast<T>();
470  auto lhs = cast(std::string(rToken.begin(), itPos));
471  std::advance(itPos, m_gRangeOperator.size());
472  auto rhs = cast(std::string(itPos, rToken.end()));
473 
474  if (lhs >= rhs)
475  throw std::runtime_error(
476  "Invalid expansion! lhs ist greater then rhs, got: '" + rToken +
477  "'!");
478 
479  rStream << lhs;
480  for (++lhs; lhs <= rhs; ++lhs)
481  rStream << delim << lhs;
482  return rStream;
483  }
484  };
485  const std::string StringToVector::m_gRangeOperator("~");
486 
496  auto getDeadCutList(const char chipID, const std::string& line)
497  -> std::vector<int> {
498  auto ids = StringToVector::convert<int>(line, ','); // can throw
499  for (auto& rID : ids)
500  rID = ModuleID_t(chipID, rID).getNumbering();
501 
502  return ids;
503  }
504 
516  std::string& remove_nondigit(std::string& s)
517  {
518  // changed to unsigned char see documention of std::isdigit in <cctype>
519  s.erase(remove_if(s.begin(), s.end(),
520  [](const unsigned char& c) { return !std::isdigit(c); }),
521  s.end());
522  return s;
523  }
524 
532  std::string& remove_chars_if_not(std::string& s, const std::string& allowed)
533  {
534  s.erase(remove_if(s.begin(), s.end(),
535  [&allowed](const char& c) {
536  return allowed.find(c) == std::string::npos;
537  }),
538  s.end());
539  return s;
540  }
541 
542  } // end namepace ARICHTools
544 } // end namepace Belle2
Belle2::ARICHTools::ModuleID_t::operator<<
friend auto operator<<(std::ostream &rStream, const ModuleID_t id) -> std::ostream &
operator << to print the id using any std::ostream implementation...
Definition: ARICHDatabaseTools.h:135
Belle2::ARICHTools::ModuleID_t::m_gMaxChannel
static constexpr auto m_gMaxChannel
m_gMaxChannel number of maximum channel starting from 0
Definition: ARICHDatabaseTools.h:52
Belle2::ARICHTools::ModuleID_t::m_gValidSectors
static constexpr auto m_gValidSectors
m_gValidSectors is a array containing allowed sector ids
Definition: ARICHDatabaseTools.h:46
Belle2::ARICHTools::ModuleID_t::getSector
auto getSector() const noexcept -> int8_t
getSector returns the definded sectors.
Definition: ARICHDatabaseTools.h:103
Belle2::ARICHTools::ModuleID_t::m_gMemberMask
static constexpr auto m_gMemberMask
m_gMemberMask is a mask to get the desired sub id info.
Definition: ARICHDatabaseTools.h:226
Belle2::ARICHTools::ModuleID_t::ModuleID_t
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.
Definition: ARICHDatabaseTools.h:78
Belle2::ARICHTools::ModuleID_t::operator<=
auto operator<=(const ModuleID_t &rOther) const noexcept -> bool
comparison operator<=
Definition: ARICHDatabaseTools.h:172
Belle2::ARICHTools::ModuleID_t::m_ID
uint16_t m_ID
m_ID contains the unique sector and channel ids.
Definition: ARICHDatabaseTools.h:231
Belle2::ARICHTools::ModuleID_t::operator>
auto operator>(const ModuleID_t &rOther) const noexcept -> bool
comparison operator>
Definition: ARICHDatabaseTools.h:181
Belle2::ARICHTools::StringToVector::expand
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...
Definition: ARICHDatabaseTools.h:473
Belle2::ARICHTools::ModuleID_t::operator<
auto operator<(const ModuleID_t &rOther) const noexcept -> bool
comparison operator<
Definition: ARICHDatabaseTools.h:163
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::ARICHTools::ModuleID_t::operator!=
auto operator!=(const ModuleID_t &rOther) const noexcept -> bool
comparison operator!=
Definition: ARICHDatabaseTools.h:154
Belle2::ARICHTools::ModuleID_t::isValidChannel
static constexpr auto isValidChannel(const int channel) noexcept -> bool
isValidChannel defines the range of valid channels.
Definition: ARICHDatabaseTools.h:59
Belle2::ARICHTools::ModuleID_t::operator++
auto operator++() noexcept -> ModuleID_t &
precrement operator ++X
Definition: ARICHDatabaseTools.h:199
Belle2::ARICHTools::StringToVector::parse
static auto parse(const std::string &rLine, const char delim=' ') -> std::string
parse<T> expands the given string and evaluats defined operators.
Definition: ARICHDatabaseTools.h:421
Belle2::ARICHTools::ModuleID_t::isValidID
auto isValidID() const noexcept -> bool
isValidID check is constructed id is valid
Definition: ARICHDatabaseTools.h:92
Belle2::ARICHTools::ModuleID_t::operator>=
auto operator>=(const ModuleID_t &rOther) const noexcept -> bool
comparison operator>=
Definition: ARICHDatabaseTools.h:190
Belle2::ARICHTools::ModuleID_t::getChannel
auto getChannel() const noexcept -> int8_t
getChannel return the defined channel
Definition: ARICHDatabaseTools.h:113
Belle2::ARICHTools::ModuleID_t::operator==
auto operator==(const ModuleID_t &rOther) const noexcept -> bool
comparison operator==
Definition: ARICHDatabaseTools.h:145
Belle2::ARICHTools::ModuleID_t::getNumbering
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...
Definition: ARICHDatabaseTools.h:124
Belle2::ARICHTools::StringToVector::m_gRangeOperator
static const std::string m_gRangeOperator
m_gRangeOperator is a std::wstring containing the range symbold
Definition: ARICHDatabaseTools.h:360
Belle2::ARICHTools::StringToVector::convert
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
Definition: ARICHDatabaseTools.h:375
Belle2::ARICHTools::ModuleID_t::m_gMemberSize
static constexpr auto m_gMemberSize
m_gMemberSize size of each sub ids
Definition: ARICHDatabaseTools.h:222
Belle2::ARICHTools::ModuleID_t
The ModuleID_t class is a intermediate object generated to contain configurations in a sorted fashion...
Definition: ARICHDatabaseTools.h:40