Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:09:31

0001 /*  =====================================================================================
0002  *
0003  *       Filename:  CSCDQM_Utility.cc
0004  *
0005  *    Description:  Histogram Utility code
0006  *
0007  *        Version:  1.0
0008  *        Created:  04/18/2008 03:39:49 PM
0009  *       Revision:  none
0010  *       Compiler:  gcc
0011  *
0012  *         Author:  Valdas Rapsevicius (VR), Valdas.Rapsevicius@cern.ch
0013  *        Company:  CERN, CH
0014  *
0015  *  =====================================================================================
0016  */
0017 
0018 #ifdef CSC_RENDER_PLUGIN
0019 #include "CSCDQM_Utility.h"
0020 #else
0021 #include "CSCDQM_Utility.h"
0022 #endif
0023 
0024 #include <cstdint>
0025 
0026 namespace cscdqm {
0027 
0028   /**
0029     * @brief  Get CSC y-axis position from chamber string
0030     * @param  cstr Chamber string
0031     * @return chamber y-axis position
0032     */
0033   int Utility::getCSCTypeBin(const std::string& cstr) {
0034     if (cstr == "ME-4/2")
0035       return 0;
0036     if (cstr == "ME-4/1")
0037       return 1;
0038     if (cstr == "ME-3/2")
0039       return 2;
0040     if (cstr == "ME-3/1")
0041       return 3;
0042     if (cstr == "ME-2/2")
0043       return 4;
0044     if (cstr == "ME-2/1")
0045       return 5;
0046     if (cstr == "ME-1/3")
0047       return 6;
0048     if (cstr == "ME-1/2")
0049       return 7;
0050     if (cstr == "ME-1/1")
0051       return 8;
0052     if (cstr == "ME+1/1")
0053       return 9;
0054     if (cstr == "ME+1/2")
0055       return 10;
0056     if (cstr == "ME+1/3")
0057       return 11;
0058     if (cstr == "ME+2/1")
0059       return 12;
0060     if (cstr == "ME+2/2")
0061       return 13;
0062     if (cstr == "ME+3/1")
0063       return 14;
0064     if (cstr == "ME+3/2")
0065       return 15;
0066     if (cstr == "ME+4/1")
0067       return 16;
0068     if (cstr == "ME+4/2")
0069       return 17;
0070     return 0;
0071   }
0072 
0073   /**
0074    * @brief  Get CSC label from CSC parameters
0075    * @param  endcap Endcap number
0076    * @param  station Station number
0077    * @param  ring Ring number
0078    * @return chamber label
0079    */
0080   std::string Utility::getCSCTypeLabel(int endcap, int station, int ring) {
0081     std::string label = "Unknown";
0082     std::ostringstream st;
0083     if ((endcap > 0) && (station > 0) && (ring > 0)) {
0084       if (endcap == 1) {
0085         st << "ME+" << station << "/" << ring;
0086         label = st.str();
0087       } else if (endcap == 2) {
0088         st << "ME-" << station << "/" << ring;
0089         label = st.str();
0090       } else {
0091         label = "Unknown";
0092       }
0093     }
0094     return label;
0095   }
0096 
0097   /**
0098    * @brief  Break string into tokens
0099    * @param  str source string to break
0100    * @param  tokens pointer to result vector
0101    * @param  delimiters delimiter string, default " "
0102    * @return 
0103    */
0104   int Utility::tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters) {
0105     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
0106     std::string::size_type pos = str.find_first_of(delimiters, lastPos);
0107     while (std::string::npos != pos || std::string::npos != lastPos) {
0108       tokens.push_back(str.substr(lastPos, pos - lastPos));
0109       lastPos = str.find_first_not_of(delimiters, pos);
0110       pos = str.find_first_of(delimiters, lastPos);
0111     }
0112     return tokens.size();
0113   }
0114 
0115   /**
0116    * @brief  Split string according to delimiter
0117    * @param  str String to split
0118    * @param  delim Delimiter
0119    * @param  results Vector to write results to
0120    * @return 
0121    */
0122   void Utility::splitString(const std::string& str, const std::string& delim, std::vector<std::string>& results) {
0123     std::string::size_type lastPos = str.find_first_not_of(delim, 0);
0124     std::string::size_type pos = str.find_first_of(delim, lastPos);
0125     while (std::string::npos != pos || std::string::npos != lastPos) {
0126       results.push_back(str.substr(lastPos, pos - lastPos));
0127       lastPos = str.find_first_not_of(delim, pos);
0128       pos = str.find_first_of(delim, lastPos);
0129     }
0130   }
0131 
0132   /**
0133    * @brief  Trim string
0134    * @param  str string to trim
0135    */
0136   void Utility::trimString(std::string& str) {
0137     std::string::size_type pos = str.find_last_not_of(' ');
0138     if (pos != std::string::npos) {
0139       str.erase(pos + 1);
0140       pos = str.find_first_not_of(' ');
0141       if (pos != std::string::npos) {
0142         str.erase(0, pos);
0143       }
0144     } else {
0145       str.erase(str.begin(), str.end());
0146     }
0147   }
0148 
0149   /**
0150    * @brief  Match RegExp expression against string message and return result
0151    * @param  re_expression RegExp expression to match
0152    * @param  message value to check
0153    * @return true if message matches RegExp expression
0154    */
0155   bool Utility::regexMatch(const TPRegexp& re_expression, const std::string& message) {
0156     TPRegexp* re = const_cast<TPRegexp*>(&re_expression);
0157     return re->MatchB(message);
0158   }
0159 
0160   /**
0161    * @brief  Match RegExp expression string against string message and return result
0162    * @param  expression RegExp expression in string to match
0163    * @param  message value to check
0164    * @return true if message matches RegExp expression
0165    */
0166   bool Utility::regexMatch(const std::string& expression, const std::string& message) {
0167     return regexMatch(TPRegexp(expression), message);
0168   }
0169 
0170   /**
0171    * @brief  Replace string part that matches RegExp expression with some
0172    * string
0173    * @param  expression RegExp expression in string to match
0174    * @param  message value to check
0175    * @param  replace string to replace matched part 
0176    */
0177   void Utility::regexReplace(const std::string& expression, std::string& message, const std::string replace) {
0178     Utility::regexReplace(TPRegexp(expression), message, replace);
0179   }
0180 
0181   /**
0182    * @brief  Replace string part that matches RegExp expression with some
0183    * string
0184    * @param  re_expression RegExp expression to match
0185    * @param  message value to check
0186    * @param  replace string to replace matched part 
0187    */
0188   void Utility::regexReplace(const TPRegexp& re_expression, std::string& message, const std::string replace) {
0189     TString s(message);
0190     TPRegexp* re = const_cast<TPRegexp*>(&re_expression);
0191     re->Substitute(s, replace);
0192     message = static_cast<const char*>(s);
0193   }
0194 
0195   /**
0196    * @brief  Replace string part that matches RegExp expression with some
0197    * string
0198    * @param  expression RegExp expression in string to match
0199    * @param  message value to check
0200    * @param  replace string to replace matched part 
0201    * @return modified string
0202    */
0203   std::string Utility::regexReplaceStr(const std::string& expression,
0204                                        const std::string& message,
0205                                        const std::string replace) {
0206     return regexReplaceStr(TPRegexp(expression), message, replace);
0207   }
0208 
0209   /**
0210    * @brief  Replace string part that matches RegExp expression with some
0211    * string
0212    * @param  re_expression RegExp expression to match
0213    * @param  message value to check
0214    * @param  replace string to replace matched part 
0215    * @return modified string
0216    */
0217   std::string Utility::regexReplaceStr(const TPRegexp& re_expression,
0218                                        const std::string& message,
0219                                        const std::string replace) {
0220     TString s(message);
0221     TPRegexp* re = const_cast<TPRegexp*>(&re_expression);
0222     re->Substitute(s, replace);
0223     return s.Data();
0224   }
0225 
0226 #undef get16bits
0227 #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__BORLANDC__) || \
0228     defined(__TURBOC__)
0229 #define get16bits(d) (*((const uint16_t*)(d)))
0230 #endif
0231 
0232 #if !defined(get16bits)
0233 #define get16bits(d) ((((uint32_t)(((const uint8_t*)(d))[1])) << 8) + (uint32_t)(((const uint8_t*)(d))[0]))
0234 #endif
0235 
0236   /**
0237   * @brief  Calculate super fast hash (from http://www.azillionmonkeys.com/qed/hash.html)
0238   * @param  data Source Data 
0239   * @param  length of data
0240   * @return hash result
0241   */
0242   uint32_t Utility::fastHash(const char* data, int len) {
0243     uint32_t hash = len, tmp;
0244     int rem;
0245 
0246     if (len <= 0 || data == nullptr)
0247       return 0;
0248     rem = len & 3;
0249     len >>= 2;
0250 
0251     /* Main loop */
0252     for (; len > 0; len--) {
0253       hash += get16bits(data);
0254       tmp = (get16bits(data + 2) << 11) ^ hash;
0255       hash = (hash << 16) ^ tmp;
0256       data += 2 * sizeof(uint16_t);
0257       hash += hash >> 11;
0258     }
0259 
0260     /* Handle end cases */
0261     switch (rem) {
0262       case 3:
0263         hash += get16bits(data);
0264         hash ^= hash << 16;
0265         hash ^= data[sizeof(uint16_t)] << 18;
0266         hash += hash >> 11;
0267         break;
0268       case 2:
0269         hash += get16bits(data);
0270         hash ^= hash << 11;
0271         hash += hash >> 17;
0272         break;
0273       case 1:
0274         hash += *data;
0275         hash ^= hash << 10;
0276         hash += hash >> 1;
0277     }
0278 
0279     /* Force "avalanching" of final 127 bits */
0280     hash ^= hash << 3;
0281     hash += hash >> 5;
0282     hash ^= hash << 4;
0283     hash += hash >> 17;
0284     hash ^= hash << 25;
0285     hash += hash >> 6;
0286 
0287     return hash;
0288   }
0289 
0290   /**
0291    * @brief  Check the hypothesis that observed events (n) value is too low or too high comparing with the expected N 
0292    * @param  N Expected number of events
0293    * @param  n Actual (observed) number of events
0294    * @param  low_threshold Rate of lower boundary of tolerance (< 1)
0295    * @param  high_threshold Rate of higher boundary of tolerance (> 1)
0296    * @param  low_sigfail Significance threshold for low value
0297    * @param  high_sigfail Significance threshold for high value
0298    * @return check outcome: 1 - observed number of events too high wrt expected
0299    * (HOT), -1 - observed number of events too low wrt expected (COLD), 0 -
0300    * observed number of events is fine wrt expected
0301    */
0302   short Utility::checkOccupancy(const unsigned int N,
0303                                 const unsigned int n,
0304                                 const double low_threshold,
0305                                 const double high_threshold,
0306                                 const double low_sigfail,
0307                                 const double high_sigfail) {
0308     if (N > 0) {
0309       double eps_meas = (1.0 * n) / (1.0 * N);
0310       if (eps_meas < low_threshold) {
0311         double S = Utility::SignificanceLevelLow(N, n, low_threshold);
0312         if (S > low_sigfail)
0313           return -1;
0314       } else if (eps_meas > high_threshold) {
0315         double S = Utility::SignificanceLevelHigh(N, n);
0316         if (S > high_sigfail)
0317           return 1;
0318       }
0319     }
0320     return 0;
0321   }
0322 
0323   /**
0324    * @brief  Check the hypothesis that error events (n) value above threshold comparing with the expected 0 and statistics is enough
0325    * @param  N Number of total events
0326    * @param  n Actual (observed) number of events errors
0327    * @param  threshold Rate of tolerance (<1)
0328    * @param  sigfail Significance threshold for low value
0329    * @return check result: true - error is significant, false - otherwise
0330    */
0331   bool Utility::checkError(const unsigned int N, const unsigned int n, const double threshold, const double sigfail) {
0332     if (N > 0) {
0333       const double eps_meas = (1.0 * n) / (1.0 * N);
0334       if (eps_meas > threshold) {
0335         if (Utility::SignificanceLevelLow(N, n, threshold) > sigfail) {
0336           return true;
0337         }
0338       }
0339     }
0340     return false;
0341   }
0342 
0343   /**
0344    * @brief  Calculate error significance alpha for the given number of errors 
0345    * based on reference number of errors for "cold" elements: actual number of 
0346    * events have to be less then the reference.
0347    * @param  N Number of events
0348    * @param  n Number of errors
0349    * @param  eps Rate of tolerance
0350    * @return Significance level
0351    */
0352   double Utility::SignificanceLevelLow(const unsigned int N, const unsigned int n, const double eps) {
0353     /** std::cout << "N = " << N << ", n = " << n << ", eps = " << eps << "\n"; */
0354 
0355     double l_eps = eps;
0356     if (l_eps <= 0.0)
0357       l_eps = 0.000001;
0358     if (l_eps >= 1.0)
0359       l_eps = 0.999999;
0360 
0361     double eps_meas = (1.0 * n) / (1.0 * N);
0362     double a = 1.0, b = 1.0;
0363 
0364     if (n > 0) {
0365       for (unsigned int r = 0; r < n; r++)
0366         a = a * (eps_meas / l_eps);
0367     }
0368 
0369     if (n < N) {
0370       for (unsigned int r = 0; r < (N - n); r++)
0371         b = b * (1 - eps_meas) / (1 - l_eps);
0372     }
0373 
0374     return sqrt(2.0 * log(a * b));
0375   }
0376 
0377   /**
0378    * @brief  Calculate error significance alpha for the given number of events
0379    * based on reference number of errors for "hot" elements: actual number of
0380    * events have to be larger then the reference.
0381    * @param  N number of reference events
0382    * @param  n number of actual events
0383    * @return error significance
0384    */
0385   double Utility::SignificanceLevelHigh(const unsigned int N, const unsigned int n) {
0386     if (N > n)
0387       return 0.0;
0388     /**  no - n observed, ne - n expected */
0389     double no = 1.0 * n, ne = 1.0 * N;
0390     return sqrt(2.0 * (no * (log(no / ne) - 1) + ne));
0391   }
0392 
0393   /**
0394    * @brief Get RUI Number from DDU source ID for post LS1 configuration
0395    * @param ddu_id DDI Source ID
0396    */
0397   int Utility::getRUIfromDDUId(unsigned ddu_id) {
0398     int rui = -1;
0399     const unsigned postLS1_map[] = {841, 842, 843, 844, 845, 846, 847, 848, 849, 831, 832, 833,
0400                                     834, 835, 836, 837, 838, 839, 861, 862, 863, 864, 865, 866,
0401                                     867, 868, 869, 851, 852, 853, 854, 855, 856, 857, 858, 859};
0402     if ((ddu_id >= FEDNumbering::MINCSCDDUFEDID) && (ddu_id <= FEDNumbering::MAXCSCDDUFEDID)) {
0403       for (int i = 0; i < 36; i++) {
0404         if (ddu_id == postLS1_map[i]) {
0405           rui = i + 1;
0406           return rui;
0407         }
0408       }
0409     } else {
0410       rui = ddu_id & 0xFF;
0411     }
0412     return rui;
0413   }
0414 
0415 }  // namespace cscdqm