Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:51:17

0001 //-------------------------------------------------
0002 //
0003 //   \class L1MuScale
0004 //
0005 //   Description:  A Scale for use in the L1 muon trigger
0006 //
0007 //
0008 //
0009 //   $Date: 2011/05/30 04:59:35 $
0010 //   $Revision: 1.8 $
0011 //
0012 //   Original Author :
0013 //   Hannes Sakulin      HEPHY / Vienna
0014 //
0015 //   Migrated to CMSSW:
0016 //   I. Mikulec
0017 //
0018 //--------------------------------------------------
0019 #ifndef CondFormatsL1TObjects_L1MuScale_h
0020 #define CondFormatsL1TObjects_L1MuScale_h
0021 
0022 #include "CondFormats/Serialization/interface/Serializable.h"
0023 
0024 #include <iostream>
0025 #include <sstream>
0026 #include <iomanip>
0027 #include <vector>
0028 #include <cmath>
0029 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0030 #include "CondFormats/L1TObjects/interface/L1MuPacking.h"
0031 
0032 /**
0033  * \class L1MuScale
0034  *
0035  * define the abstract interface to all scales
0036 */
0037 
0038 class L1MuScale {
0039 public:
0040   L1MuScale() {}
0041 
0042   virtual ~L1MuScale() {}
0043 
0044   /// get the center of bin represented by packed
0045   virtual float getCenter(unsigned packed) const = 0;
0046 
0047   /// get the low edge of bin represented by packed
0048   virtual float getLowEdge(unsigned packed) const = 0;
0049 
0050   /// get the upper edge of bin represented by packed
0051   virtual float getHighEdge(unsigned packed) const = 0;
0052 
0053   /// get the upper edge of the last bin
0054   virtual float getScaleMax() const = 0;
0055 
0056   /// get the lower edge of the first bin
0057   virtual float getScaleMin() const = 0;
0058 
0059   /// pack a value
0060   virtual unsigned getPacked(float value) const = 0;
0061 
0062   /// get number of bins
0063   virtual unsigned getNBins() const = 0;
0064 
0065   /// get value of the underlying vector for bin i
0066   virtual float getValue(unsigned i) const = 0;
0067 
0068   virtual std::string print() const = 0;
0069 
0070 private:
0071   COND_SERIALIZABLE;
0072 };
0073 
0074 //
0075 // define default scale implementations
0076 //
0077 
0078 /**
0079  * \class L1MuBinnedScale
0080  *
0081  * implements a continuous scale of NBins bins. 
0082  *
0083  * the index into the binned scale runs from 0 to NBins-1.
0084  * 
0085  * It is packed into a data word (unsigned) using a Packing (template parameter)
0086  *  
0087  * If the packing accepts negative values, an offset can be specified which 
0088  * will be subtracted from the index before packing. ( The offset is in turn added to the packed
0089  * value before using it as an index into the scale.)
0090  *
0091 */
0092 
0093 class L1MuBinnedScale : public L1MuScale {
0094 public:
0095   ///
0096   /// constructor
0097   ///
0098   /// packing is a pointer to a packing object. The L1MuBinnedScale
0099   /// takes ownership of the packing object and deletes it in its
0100   /// destructor
0101   ///
0102   L1MuBinnedScale() : m_nbits(0), m_signedPacking(false), m_NBins(0), m_idxoffset(0) {}
0103 
0104   /// NBins=number of bins, Scale[NBins+1]=bin edges, idx_offset=offeset to index (if stored as signed)
0105   ///
0106   //  L1MuBinnedScale(unsigned int nbits, bool signedPacking, int NBins, const float* Scale, int idx_offset=0)
0107   L1MuBinnedScale(
0108       unsigned int nbits, bool signedPacking, int NBins, const std::vector<double>& Scale, int idx_offset = 0)
0109       : m_nbits(nbits), m_signedPacking(signedPacking) {
0110     m_NBins = NBins;
0111     m_idxoffset = idx_offset;
0112 
0113     m_Scale.reserve(m_NBins + 1);
0114     for (int i = 0; i < m_NBins + 1; i++)
0115       //m_Scale[i] = Scale[i];
0116       m_Scale.push_back(Scale[i]);
0117   };
0118 
0119   ///
0120   /// constructor
0121   ///
0122   /// packing is a pointer to a packing object. The L1MuBinnedScale
0123   /// takes ownership of the packing object and deletes it in its
0124   /// destructor
0125   ///
0126   /// NBins=number of bins, xmin = low edge of first bin,
0127   /// xmax=high edge of last bin, idx_offset=offeset to index (if stored as signed)
0128   ///
0129   L1MuBinnedScale(unsigned int nbits, bool signedPacking, int NBins, float xmin, float xmax, int idx_offset = 0)
0130       : m_nbits(nbits), m_signedPacking(signedPacking) {
0131     m_NBins = NBins;
0132     m_idxoffset = idx_offset;
0133 
0134     m_Scale.reserve(m_NBins + 1);
0135     for (int i = 0; i < m_NBins + 1; i++)
0136       //      m_Scale[i] = xmin + i * (xmax-xmin) / m_NBins;
0137       m_Scale.push_back(xmin + i * (xmax - xmin) / m_NBins);
0138   };
0139 
0140   /// destructor
0141   ~L1MuBinnedScale() override{
0142       //    delete m_packing;
0143   };
0144 
0145   /// get the center of bin represented by packed
0146   float getCenter(unsigned packed) const override {
0147     int idx = get_idx(packed);
0148     return (m_Scale[idx] + m_Scale[idx + 1]) / 2.;
0149   };
0150 
0151   /// get the low edge of bin represented by packed
0152   float getLowEdge(unsigned packed) const override { return m_Scale[get_idx(packed)]; };
0153 
0154   /// get the upper edge of bin represented by packed
0155   float getHighEdge(unsigned packed) const override { return m_Scale[get_idx(packed) + 1]; };
0156 
0157   /// pack a value
0158 
0159   unsigned getPacked(float value) const override {
0160     if (value < m_Scale[0] || value > m_Scale[m_NBins])
0161       edm::LogWarning("ScaleRangeViolation")
0162           << "L1MuBinnedScale::getPacked: value out of scale range: " << value << std::endl;
0163     int idx = 0;
0164     if (value < m_Scale[0])
0165       idx = 0;
0166     else if (value >= m_Scale[m_NBins])
0167       idx = m_NBins - 1;
0168     else {
0169       for (; idx < m_NBins; idx++)
0170         if (value >= m_Scale[idx] && value < m_Scale[idx + 1])
0171           break;
0172     }
0173 
0174     return (m_signedPacking ? L1MuSignedPackingGeneric::packedFromIdx(idx - m_idxoffset, m_nbits)
0175                             : L1MuUnsignedPackingGeneric::packedFromIdx(idx - m_idxoffset, m_nbits));
0176   };
0177 
0178   /// get the upper edge of the last bin
0179   float getScaleMax() const override { return m_Scale[m_NBins]; }
0180 
0181   /// get the lower edge of the first bin
0182   float getScaleMin() const override { return m_Scale[0]; }
0183 
0184   /// get number of bins
0185   unsigned getNBins() const override { return m_NBins; }
0186 
0187   /// get value of the underlying vector for bin i
0188   float getValue(unsigned i) const override { return m_Scale[i]; }
0189 
0190   std::string print() const override {
0191     std::ostringstream str;
0192 
0193     str << " ind |   low edge |     center |  high edge" << std::endl;
0194     str << "-------------------------------------------" << std::endl;
0195     for (int i = 0; i < m_NBins; i++) {
0196       unsigned int ipack = getPacked(m_Scale[i]);
0197       str << std::setw(4) << ipack << " | " << std::setw(10) << getLowEdge(ipack) << " | " << std::setw(10)
0198           << getCenter(ipack) << " | " << std::setw(10) << getHighEdge(ipack) << std::endl;
0199     }
0200 
0201     return str.str();
0202   }
0203 
0204 protected:
0205   int get_idx(unsigned packed) const {
0206     int idxFromPacked = m_signedPacking ? L1MuSignedPackingGeneric::idxFromPacked(packed, m_nbits)
0207                                         : L1MuUnsignedPackingGeneric::idxFromPacked(packed, m_nbits);
0208     int idx = idxFromPacked + m_idxoffset;
0209     if (idx < 0)
0210       idx = 0;
0211     if (idx >= m_NBins)
0212       idx = m_NBins - 1;
0213     return idx;
0214   }
0215 
0216   unsigned int m_nbits;
0217   bool m_signedPacking;
0218   int m_NBins;
0219   int m_idxoffset;
0220   std::vector<float> m_Scale;
0221 
0222   COND_SERIALIZABLE;
0223 };
0224 
0225 /**
0226  * \class  L1MuSymmetricBinnedScale
0227  *
0228  * In the GMT the concept of a symmetric scale exists 
0229  * The internal representation of scale values is "pseudo-signed", i.e.
0230  * the highest bit stores the sign and the lower bits contain the absolute value
0231  * 
0232  * Attention: for reasons of symmetry, the low edge in this scale is the edge closer to zero.
0233  *            the high edge is the edge further away from zero
0234 */
0235 
0236 class L1MuSymmetricBinnedScale : public L1MuScale {
0237 public:
0238   ///
0239   /// constructor
0240   ///
0241   /// packing is a pointer to a packing object. The L1MuSymmetricBinnedScale
0242   /// takes ownership of the packing object and deletes it in its
0243   /// destructor
0244   ///
0245 
0246   L1MuSymmetricBinnedScale() : m_NBins(0) {}
0247 
0248   /// NBins=number of bins (in one half of the scale), Scale[NBins+1]=bin edges
0249   ///
0250   //  L1MuSymmetricBinnedScale(int nbits, int NBins, const float* Scale)
0251   L1MuSymmetricBinnedScale(int nbits, int NBins, const std::vector<double>& Scale)
0252       : m_packing(L1MuPseudoSignedPacking(nbits)) {
0253     m_NBins = NBins;
0254     m_Scale.reserve(m_NBins + 1);
0255     for (int i = 0; i < m_NBins + 1; i++)
0256       //      m_Scale[i] = Scale[i];
0257       m_Scale.push_back(Scale[i]);
0258   };
0259 
0260   ///
0261   /// constructor
0262   ///
0263   /// packing is a pointer to a packing object. The L1MuSymmetricBinnedScale
0264   /// takes ownership of the packing object and deletes it in its
0265   /// destructor
0266   ///
0267   /// NBins=number of bins, xmin = low edge of first bin (in positive half)
0268   /// xmax=high edge of last bin (in positive half)
0269   ///
0270   L1MuSymmetricBinnedScale(int nbits, int NBins, float xmin, float xmax) : m_packing(L1MuPseudoSignedPacking(nbits)) {
0271     m_NBins = NBins;
0272     m_Scale.reserve(m_NBins + 1);
0273     for (int i = 0; i < m_NBins + 1; i++)
0274       //      m_Scale[i] = xmin + i * (xmax-xmin) / m_NBins;
0275       m_Scale.push_back(xmin + i * (xmax - xmin) / m_NBins);
0276   };
0277 
0278   /// destructor
0279   ~L1MuSymmetricBinnedScale() override{
0280       //    delete m_packing;
0281   };
0282 
0283   /// get the center of bin represented by packed
0284   float getCenter(unsigned packed) const override {
0285     int absidx = abs(m_packing.idxFromPacked(packed));
0286     if (absidx >= m_NBins)
0287       absidx = m_NBins - 1;
0288     float center = (m_Scale[absidx] + m_Scale[absidx + 1]) / 2.;
0289     float fsign = m_packing.signFromPacked(packed) == 0 ? 1. : -1.;
0290     return center * fsign;
0291   };
0292 
0293   /// get the low edge of bin represented by packed
0294   float getLowEdge(unsigned packed) const override {  // === edge towards 0
0295     int absidx = abs(m_packing.idxFromPacked(packed));
0296     if (absidx >= m_NBins)
0297       absidx = m_NBins - 1;
0298     float low = m_Scale[absidx];
0299     float fsign = m_packing.signFromPacked(packed) == 0 ? 1. : -1.;
0300     return low * fsign;
0301   };
0302 
0303   /// get the upper edge of bin represented by packed
0304   float getHighEdge(unsigned packed) const override {
0305     edm::LogWarning("NotImplemented") << "L1MuSymmetricBinnedScale::getHighEdge not implemented" << std::endl;
0306     return 0;
0307   };
0308 
0309   /// pack a value
0310   unsigned getPacked(float value) const override {
0311     float absval = fabs(value);
0312     if (absval < m_Scale[0] || absval > m_Scale[m_NBins])
0313       edm::LogWarning("ScaleRangeViolation")
0314           << "L1MuSymmetricBinnedScale::getPacked: value out of scale range!!! abs(val) = " << absval
0315           << " min= " << m_Scale[0] << " max = " << m_Scale[m_NBins] << std::endl;
0316     int idx = 0;
0317     for (; idx < m_NBins; idx++)
0318       if (absval >= m_Scale[idx] && absval < m_Scale[idx + 1])
0319         break;
0320     if (idx >= m_NBins)
0321       idx = m_NBins - 1;
0322     return m_packing.packedFromIdx(idx, (value >= 0) ? 0 : 1);
0323   };
0324   /// get the upper edge of the last bin (posivie half)
0325   float getScaleMax() const override { return m_Scale[m_NBins]; }
0326 
0327   /// get the lower edge of the first bin (positive half)
0328   float getScaleMin() const override { return m_Scale[0]; }
0329 
0330   /// get number of bins
0331   unsigned getNBins() const override { return m_NBins; }
0332 
0333   /// get value of the underlying vector for bin i
0334   float getValue(unsigned i) const override { return m_Scale[i]; }
0335 
0336   std::string print() const override {
0337     std::ostringstream str;
0338 
0339     str << " ind |   low edge |     center" << std::endl;
0340     str << "-------------------------------------------" << std::endl;
0341     for (int i = 0; i < m_NBins; i++) {
0342       unsigned int ipack = getPacked(m_Scale[i]);
0343       str << std::setw(4) << ipack << " | " << std::setw(10) << getLowEdge(ipack) << " | " << std::setw(10)
0344           << getCenter(ipack) << std::endl;
0345     }
0346 
0347     return str.str();
0348   }
0349 
0350 protected:
0351   L1MuPseudoSignedPacking m_packing;
0352   int m_NBins;
0353   std::vector<float> m_Scale;
0354 
0355   COND_SERIALIZABLE;
0356 };
0357 #endif