Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:08:51

0001 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0002 
0003 #include "DQM/SiStripMonitorHardware/interface/SiStripFEDSpyBuffer.h"
0004 #include "DQM/SiStripMonitorHardware/interface/SiStripSpyUtilities.h"
0005 
0006 using edm::LogError;
0007 using edm::LogInfo;
0008 using edm::LogWarning;
0009 
0010 namespace sistrip {
0011   const SpyUtilities::Frame SpyUtilities::extractFrameInfo(
0012       const edm::DetSetVector<SiStripRawDigi>::detset& channelDigis, bool aPrintDebug) {
0013     SpyUtilities::Frame lFrame;
0014     lFrame.detId = channelDigis.detId();
0015     lFrame.firstHeaderBit = 0;
0016     lFrame.firstTrailerBit = 0;
0017     lFrame.digitalLow = 0;
0018     lFrame.digitalHigh = 0;
0019     lFrame.baseline = 0;
0020     lFrame.apvErrorBit.first = false;
0021     lFrame.apvErrorBit.second = false;
0022     lFrame.apvAddress.first = 0;
0023     lFrame.apvAddress.second = 0;
0024 
0025     uint16_t min = 0x3FF;
0026     uint16_t max = 0;
0027     edm::DetSetVector<SiStripRawDigi>::detset::const_iterator iDigi = channelDigis.begin();
0028     const edm::DetSetVector<SiStripRawDigi>::detset::const_iterator endChannelDigis = channelDigis.end();
0029 
0030     //counters for outputting warnings
0031     uint16_t numzeroes = 0, numsats = 0;
0032 
0033     if (iDigi == endChannelDigis)
0034       return lFrame;
0035 
0036     for (; iDigi != endChannelDigis; ++iDigi) {
0037       const uint16_t val = iDigi->adc();
0038       if (val < min)
0039         min = val;
0040       if (val > max)
0041         max = val;
0042       if (val == 0)
0043         numzeroes++;
0044       if (val == 0x3FF)
0045         numsats++;
0046       lFrame.baseline += val;
0047     }
0048 
0049     if (!channelDigis.empty())
0050       lFrame.baseline = lFrame.baseline / channelDigis.size();
0051     lFrame.digitalLow = min;
0052     lFrame.digitalHigh = max;
0053 
0054     const uint16_t threshold = static_cast<uint16_t>((2.0 * static_cast<double>(max - min)) / 3.0);
0055 
0056     if (aPrintDebug) {
0057       if (edm::isDebugEnabled()) {
0058         LogDebug("SiStripSpyUtilities") << "Channel with key: " << lFrame.detId << " Min: " << min << " Max: " << max
0059                                         << " Range: " << (max - min) << " Threshold: " << threshold;
0060       }
0061       if (numzeroes > 0 || numsats > 0) {
0062         edm::LogWarning("SiStripSpyUtilities") << "Channel with key: " << lFrame.detId << " has " << numzeroes
0063                                                << " zero and " << numsats << " saturated samples.";
0064       }
0065     }
0066 
0067     lFrame.firstHeaderBit = findHeaderBits(channelDigis, threshold);
0068     lFrame.firstTrailerBit = findTrailerBits(channelDigis, threshold);
0069 
0070     lFrame.apvErrorBit = findAPVErrorBits(channelDigis, threshold, lFrame.firstHeaderBit);
0071     lFrame.apvAddress = findAPVAddresses(channelDigis, threshold, lFrame.firstHeaderBit);
0072 
0073     return lFrame;
0074   }
0075 
0076   const uint16_t SpyUtilities::range(const SpyUtilities::Frame& aFrame) {
0077     if (aFrame.digitalHigh < aFrame.digitalLow)
0078       return 0;
0079     else
0080       return aFrame.digitalHigh - aFrame.digitalLow;
0081   }
0082 
0083   const uint16_t SpyUtilities::threshold(const SpyUtilities::Frame& aFrame) {
0084     return static_cast<uint16_t>((2.0 * static_cast<double>(range(aFrame))) / 3.0);
0085   }
0086 
0087   const uint8_t SpyUtilities::extractAPVaddress(const SpyUtilities::Frame& aFrame) {
0088     if (aFrame.apvErrorBit.first == false)
0089       return aFrame.apvAddress.first;
0090     else if (aFrame.apvErrorBit.second == false) {
0091       return aFrame.apvAddress.second;
0092     } else {
0093       return 0;
0094     }
0095   }
0096 
0097   void SpyUtilities::getMajorityHeader(const edm::DetSetVector<SiStripRawDigi>* aInputDigis,
0098                                        uint16_t& aFirstHeaderBit,
0099                                        bool printResult) {
0100     std::vector<uint16_t> lFirstBitVec;
0101     lFirstBitVec.reserve(aInputDigis->size());
0102     aFirstHeaderBit = 0;
0103     edm::DetSetVector<SiStripRawDigi>::const_iterator lDigis = aInputDigis->begin();
0104 
0105     for (; lDigis != aInputDigis->end(); lDigis++) {
0106       sistrip::SpyUtilities::Frame lFrame = sistrip::SpyUtilities::extractFrameInfo(*lDigis);
0107       lFirstBitVec.push_back(lFrame.firstHeaderBit);
0108     }
0109 
0110     std::pair<uint16_t, uint32_t> lMaj = sistrip::SpyUtilities::findMajorityValue(lFirstBitVec);
0111     aFirstHeaderBit = lMaj.first;
0112     uint32_t lMajorityCounter = lMaj.second;
0113 
0114     //header is 24-sample long (2*8+2+6)
0115     uint16_t lFirstTrailerBit = aFirstHeaderBit + 24 + sistrip::STRIPS_PER_FEDCH;
0116 
0117     if (printResult) {
0118       LogInfo("SiStripSpyUtilities") << " -- Found majority position of first header (trailer) bit: " << aFirstHeaderBit
0119                                      << " (" << lFirstTrailerBit << ") for " << lMajorityCounter << " out of "
0120                                      << lFirstBitVec.size() << " channels." << std::endl;
0121     }
0122   }
0123 
0124   const bool SpyUtilities::isValid(const SpyUtilities::Frame& aFrame,
0125                                    const FrameQuality& aQuality,
0126                                    const uint16_t aExpectedPos) {
0127     uint16_t lRange = sistrip::SpyUtilities::range(aFrame);
0128 
0129     if (lRange < aQuality.minDigiRange || lRange > aQuality.maxDigiRange) {
0130       return false;
0131     } else if (aFrame.digitalLow < aQuality.minZeroLight || aFrame.digitalLow > aQuality.maxZeroLight) {
0132       return false;
0133     } else if (aFrame.digitalHigh < aQuality.minTickHeight || aFrame.digitalHigh > aQuality.maxTickHeight) {
0134       return false;
0135     }
0136     //if expectedPos=0: return true whatever the position of header is...
0137     else if (aExpectedPos > 0 && (!(aFrame.firstHeaderBit == aExpectedPos &&
0138                                     aFrame.firstTrailerBit == aExpectedPos + 24 + sistrip::STRIPS_PER_FEDCH))) {
0139       return false;
0140     } else if (aFrame.apvErrorBit.first && aFrame.apvErrorBit.second) {
0141       return false;
0142     }
0143 
0144     return true;
0145   }
0146 
0147   const uint16_t SpyUtilities::findHeaderBits(const edm::DetSetVector<SiStripRawDigi>::detset& channelDigis,
0148                                               const uint16_t threshold) {
0149     // Loop over digis looking for first above threshold
0150     uint8_t aboveThreshold = 0;
0151     bool foundHeader = false;
0152     uint16_t count = 0;
0153 
0154     edm::DetSetVector<SiStripRawDigi>::detset::const_iterator iDigi = channelDigis.begin();
0155     const edm::DetSetVector<SiStripRawDigi>::detset::const_iterator endChannelDigis = channelDigis.end();
0156 
0157     for (; iDigi != endChannelDigis; ++iDigi) {
0158       if (iDigi->adc() > threshold) {
0159         aboveThreshold++;
0160       } else {
0161         aboveThreshold = 0;
0162       }
0163       if (aboveThreshold == 6) {
0164         foundHeader = true;
0165         break;
0166       }
0167       count++;
0168     }  //end of loop over digis
0169 
0170     //break before incrementing the last time... so count-5 is the first header sample.
0171     if (foundHeader && count < 5)
0172       return 0;
0173     if (foundHeader)
0174       return count - 5;
0175     return sistrip::SPY_SAMPLES_PER_CHANNEL;
0176   }
0177 
0178   const uint16_t SpyUtilities::findTrailerBits(const edm::DetSetVector<SiStripRawDigi>::detset& channelDigis,
0179                                                const uint16_t threshold) {
0180     // Loop over digis looking for last above threshold
0181     uint8_t aboveThreshold = 0;
0182     bool foundTrailer = false;
0183 
0184     //discard the first 30 values, which will have some digital high in them...
0185     //start searching from the expected position : sometimes after 24+256 samples,
0186     //normally at 6+24+256 if 6-bit low before tickmark header bits...
0187     uint16_t count = 24 + sistrip::STRIPS_PER_FEDCH;
0188 
0189     if (count >= sistrip::SPY_SAMPLES_PER_CHANNEL)
0190       return sistrip::SPY_SAMPLES_PER_CHANNEL;
0191 
0192     edm::DetSetVector<SiStripRawDigi>::detset::const_iterator iDigi = channelDigis.begin() + count;
0193     const edm::DetSetVector<SiStripRawDigi>::detset::const_iterator endChannelDigis = channelDigis.end();
0194 
0195     for (; iDigi != endChannelDigis; ++iDigi) {
0196       if (iDigi->adc() > threshold) {
0197         aboveThreshold++;
0198       } else {
0199         aboveThreshold = 0;
0200       }
0201       if (aboveThreshold == 2) {
0202         foundTrailer = true;
0203         break;
0204       }
0205       count++;
0206     }  //end of loop over digis
0207 
0208     //break before incrementing the last time... so count-1 is the first trailer sample.
0209     if (foundTrailer && count < 1)
0210       return 0;
0211     if (foundTrailer)
0212       return count - 1;
0213     return sistrip::SPY_SAMPLES_PER_CHANNEL;
0214   }
0215 
0216   const std::pair<bool, bool> SpyUtilities::findAPVErrorBits(
0217       const edm::DetSetVector<SiStripRawDigi>::detset& channelDigis,
0218       const uint16_t threshold,
0219       const uint16_t aFirstBits) {
0220     // Loop over digis looking for firstHeader+6+16
0221     uint16_t count = aFirstBits + 22;
0222 
0223     std::pair<bool, bool> lPair = std::pair<bool, bool>(false, false);
0224 
0225     //if header invalid: we don't know what apverr is....
0226     if (count >= sistrip::SPY_SAMPLES_PER_CHANNEL - 1)
0227       return lPair;
0228 
0229     edm::DetSetVector<SiStripRawDigi>::detset::const_iterator iDigi = channelDigis.begin() + count;
0230     const edm::DetSetVector<SiStripRawDigi>::detset::const_iterator endChannelDigis = channelDigis.end();
0231 
0232     //double check....
0233     if (iDigi == endChannelDigis)
0234       return lPair;
0235 
0236     if (iDigi->adc() <= threshold)
0237       lPair.first = true;
0238     ++iDigi;
0239 
0240     //triple check...
0241     if (iDigi == endChannelDigis)
0242       return std::pair<bool, bool>(false, false);
0243 
0244     if (iDigi->adc() <= threshold)
0245       lPair.second = true;
0246 
0247     return lPair;
0248   }
0249 
0250   const std::pair<uint8_t, uint8_t> SpyUtilities::findAPVAddresses(
0251       const edm::DetSetVector<SiStripRawDigi>::detset& channelDigis,
0252       const uint16_t threshold,
0253       const uint16_t aFirstBits) {
0254     // Loop over digis looking for firstHeader+6
0255     uint16_t count = aFirstBits + 6;
0256     std::pair<uint8_t, uint8_t> lPair = std::pair<uint8_t, uint8_t>(0, 0);
0257 
0258     //check enough room to have 16 values....
0259     if (count >= sistrip::SPY_SAMPLES_PER_CHANNEL - 15)
0260       return lPair;
0261 
0262     edm::DetSetVector<SiStripRawDigi>::detset::const_iterator iDigi = channelDigis.begin() + count;
0263     const edm::DetSetVector<SiStripRawDigi>::detset::const_iterator endChannelDigis = channelDigis.end();
0264 
0265     //double check....
0266     if (iDigi == endChannelDigis)
0267       return lPair;
0268 
0269     for (uint8_t i = 0; i < 16; ++i) {
0270       if (iDigi->adc() > threshold) {
0271         //data is MSB first
0272         if (i % 2 == 0)
0273           lPair.first |= (0x80 >> static_cast<uint8_t>(i / 2));
0274         else
0275           lPair.second |= (0x80 >> static_cast<uint8_t>(i / 2));
0276       }
0277       ++iDigi;
0278     }
0279 
0280     return lPair;
0281   }
0282 
0283   std::string SpyUtilities::print(const SpyUtilities::Frame& aFrame, std::string aErr) {
0284     std::ostringstream lOs;
0285     lOs << " ------------------------------------------------------" << std::endl
0286         << " -- Error: " << aErr << std::endl
0287         << " ------- Printing Frame for detId " << aFrame.detId << " --------" << std::endl
0288         << " -- firstHeaderBit = " << aFrame.firstHeaderBit << std::endl
0289         << " -- firstTrailerBit = " << aFrame.firstTrailerBit << std::endl
0290         << " -- digitalLow = " << aFrame.digitalLow << std::endl
0291         << " -- digitalHigh = " << aFrame.digitalHigh << std::endl
0292         << " -- baseline = " << aFrame.baseline << std::endl
0293         << " -- apvErrorBits = " << aFrame.apvErrorBit.first << " " << aFrame.apvErrorBit.second << std::endl
0294         << " -- apvAddresses = " << static_cast<uint16_t>(aFrame.apvAddress.first) << " "
0295         << static_cast<uint16_t>(aFrame.apvAddress.second) << std::endl
0296         << " ------------------------------------------------------" << std::endl;
0297     return lOs.str();
0298   }
0299 
0300   void SpyUtilities::fedIndex(const uint32_t aFedIndex, uint16_t& aFedId, uint16_t& aFedChannel) {
0301     //find the corresponding detId (for the pedestals)
0302     aFedId = static_cast<uint16_t>(aFedIndex / sistrip::FEDCH_PER_FED);
0303     aFedChannel = static_cast<uint16_t>(aFedIndex % sistrip::FEDCH_PER_FED);
0304 
0305     if (aFedId < sistrip::FED_ID_MIN || aFedId > sistrip::FED_ID_MAX || aFedChannel >= sistrip::FEDCH_PER_FED) {
0306       aFedId = sistrip::invalid_;
0307       aFedChannel = sistrip::invalid_;
0308     }
0309   }
0310 
0311   std::pair<uint16_t, uint32_t> SpyUtilities::findMajorityValue(std::vector<uint16_t>& values, const uint16_t aFedId) {
0312     uint32_t lTot = values.size();
0313     if (!lTot)
0314       return std::pair<uint16_t, uint32_t>(0, 0);
0315 
0316     std::sort(values.begin(), values.end());
0317     uint32_t lMajorityCounter = 0;
0318     uint16_t lMaj = 0;
0319 
0320     std::vector<uint16_t>::iterator lIter = values.begin();
0321     for (; lIter != values.end();) {
0322       uint32_t lCounter = std::count(lIter, values.end(), *lIter);
0323       if (lCounter > lMajorityCounter) {
0324         lMajorityCounter = lCounter;
0325         lMaj = *lIter;
0326       }
0327       lIter += lCounter;
0328     }
0329 
0330     //std::cout << " -- Found majority value " << lMaj << " for " << lMajorityCounter << " elements out of " << values.size() << "." << std::endl;
0331 
0332     if (static_cast<float>(lMajorityCounter) / lTot < 0.5) {
0333       LogError("SiStripSpyUtilities") << " -- Found majority position for index " << aFedId << ": " << lMaj
0334                                       << " for less than half the values : " << lMajorityCounter << " out of " << lTot
0335                                       << " values." << std::endl;
0336     }
0337 
0338     return std::pair<uint16_t, uint32_t>(lMaj, lMajorityCounter);
0339   }
0340 
0341   void SpyUtilities::fillFEDMajorities(const std::map<uint32_t, uint32_t>& channelValues,
0342                                        std::vector<uint32_t>& fedMajoritiesToFill) {
0343     std::map<uint32_t, uint32_t>::const_iterator lMapIter = channelValues.begin();
0344     uint16_t lPreviousFedId = 0;
0345     std::vector<uint16_t> lAddrVec;
0346     lAddrVec.reserve(sistrip::FEDCH_PER_FED);
0347     fedMajoritiesToFill.resize(sistrip::FED_ID_MAX - sistrip::FED_ID_MIN + 1, 0);
0348     uint32_t lChCount = 0;
0349 
0350     for (; lMapIter != channelValues.end(); ++lMapIter, ++lChCount) {
0351       uint16_t lFedId = static_cast<uint16_t>(lMapIter->first / sistrip::FEDCH_PER_FED);
0352 
0353       if (lPreviousFedId == 0) {
0354         lPreviousFedId = lFedId;
0355       }
0356       if (lFedId == lPreviousFedId) {
0357         lAddrVec.push_back(lMapIter->second);
0358       }
0359       if (lFedId != lPreviousFedId || (lChCount == channelValues.size() - 1)) {
0360         //extract majority address
0361 
0362         uint32_t lMaj = sistrip::SpyUtilities::findMajorityValue(lAddrVec, lPreviousFedId).first;
0363         fedMajoritiesToFill[lPreviousFedId] = lMaj;
0364 
0365         lAddrVec.clear();
0366 
0367         //if new fed, fill the first channel
0368         if (lFedId != lPreviousFedId) {
0369           lAddrVec.push_back(lMapIter->second);
0370           lPreviousFedId = lFedId;
0371         }
0372       }
0373     }
0374   }
0375 
0376 }  // namespace sistrip