CMS 3D CMS Logo

/data/git/CMSSW_5_3_11_patch5/src/DQM/SiStripMonitorHardware/src/SiStripSpyUtilities.cc

Go to the documentation of this file.
00001 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00002 #include "FWCore/Framework/interface/EventSetup.h"
00003 #include "FWCore/Framework/interface/ESHandle.h"
00004 
00005 // Needed for the FED cabling and pedestals
00006 #include "CondFormats/DataRecord/interface/SiStripFedCablingRcd.h"
00007 #include "CalibTracker/Records/interface/SiStripDetCablingRcd.h"
00008 #include "CondFormats/SiStripObjects/interface/SiStripFedCabling.h"
00009 #include "CondFormats/DataRecord/interface/SiStripPedestalsRcd.h"
00010 #include "CondFormats/DataRecord/interface/SiStripNoisesRcd.h"
00011 
00012 #include "DQM/SiStripMonitorHardware/interface/SiStripFEDSpyBuffer.h"
00013 #include "DQM/SiStripMonitorHardware/interface/SiStripSpyUtilities.h"
00014 
00015 using edm::LogError;
00016 using edm::LogWarning;
00017 using edm::LogInfo;
00018 
00019 
00020 namespace sistrip {
00021   SpyUtilities::SpyUtilities() :
00022     cabling_(0),
00023     cacheId_(0),
00024     detCabling_(0),
00025     cacheIdDet_(0),
00026     pedsCacheId_(0),
00027     pedsHandle_(0),
00028     noiseCacheId_(0),
00029     noiseHandle_(0)
00030   {
00031     
00032   }
00033   
00034   SpyUtilities::~SpyUtilities()
00035   {
00036     if ( cabling_ ) cabling_ = 0;
00037     if ( detCabling_ ) detCabling_ = 0;
00038   }
00039 
00040   const SiStripFedCabling*  SpyUtilities::getCabling( const edm::EventSetup& setup )
00041   {
00042     
00043     uint32_t cache_id = setup.get<SiStripFedCablingRcd>().cacheIdentifier();
00044    
00045     if ( cacheId_ != cache_id ) { // If the cache ID has changed since the last update...
00046       // Update the cabling object
00047       edm::ESHandle<SiStripFedCabling> c;
00048       setup.get<SiStripFedCablingRcd>().get( c );
00049       cabling_ = c.product();
00050       
00051 //                if ( edm::isDebugEnabled() ) {
00052 //          if ( !cacheId_ ) { // First time cabling has been retrieved - print it out in full.
00053 //            std::stringstream ss;
00054 //            ss << "[sistrip::SpyChannelUnpackerModule::" << __func__ << "]"
00055 //               << " Updating cabling for first time..." << std::endl
00056 //               << " Terse print out of FED cabling:" << std::endl;
00057 //            //cabling_->terse(ss);
00058 //            //LogTrace("SiStripMonitorHardwareUnpacker") << ss.str();
00059 //          } // end of cacheId_ check
00060 //        } // end of debugEnabled check
00061       
00062 //       if ( edm::isDebugEnabled() ) {
00063 //      std::stringstream sss;
00064 //      sss << "[sistrip::SpyUtilities::" << __func__ << "]"
00065 //          << " Summary of FED cabling:" << std::endl;
00066 //      cabling_->summary(sss);
00067 //      LogTrace("SiStripSpyUtilities") << sss.str();
00068 //       }
00069 
00070       // Update the cache ID with the new value.
00071       cacheId_ = cache_id;
00072 
00073     } // end of new cache ID check
00074         
00075     return cabling_;
00076   }
00077 
00078   const SiStripDetCabling*  SpyUtilities::getDetCabling( const edm::EventSetup& setup )
00079   {
00080     
00081     uint32_t cache_id = setup.get<SiStripDetCablingRcd>().cacheIdentifier();//.get( cabling_ );
00082    
00083     if ( cacheIdDet_ != cache_id ) { // If the cache ID has changed since the last update...
00084       // Update the cabling object
00085       edm::ESHandle<SiStripDetCabling> c;
00086       setup.get<SiStripDetCablingRcd>().get( c );
00087       detCabling_ = c.product();
00088       cacheIdDet_ = cache_id;
00089     } // end of new cache ID check
00090         
00091     return detCabling_;
00092   }
00093 
00094   edm::ESHandle<SiStripPedestals> SpyUtilities::getPedestalHandle(const edm::EventSetup& eventSetup)
00095   {
00096     //check if new pedestal values are available
00097     uint32_t lCacheId = eventSetup.get<SiStripPedestalsRcd>().cacheIdentifier();
00098     if (lCacheId != pedsCacheId_) {
00099       eventSetup.get<SiStripPedestalsRcd>().get(pedsHandle_);
00100       pedsCacheId_ = lCacheId;
00101     }
00102 
00103     return pedsHandle_;
00104   }
00105 
00106 
00107   edm::ESHandle<SiStripNoises> SpyUtilities::getNoiseHandle(const edm::EventSetup& eventSetup)
00108   {
00109     //check if new noise values are available
00110     uint32_t lCacheId = eventSetup.get<SiStripNoisesRcd>().cacheIdentifier();
00111     if (lCacheId != noiseCacheId_) {
00112       eventSetup.get<SiStripNoisesRcd>().get(noiseHandle_);
00113       noiseCacheId_ = lCacheId;
00114     }
00115 
00116     return noiseHandle_;
00117   }
00118 
00119 
00120   const SpyUtilities::Frame 
00121   SpyUtilities::extractFrameInfo(const edm::DetSetVector<SiStripRawDigi>::detset & channelDigis,
00122                                  bool aPrintDebug)
00123   {
00124 
00125     SpyUtilities::Frame lFrame;
00126     lFrame.detId = channelDigis.detId();
00127     lFrame.firstHeaderBit = 0;
00128     lFrame.firstTrailerBit = 0;
00129     lFrame.digitalLow = 0;
00130     lFrame.digitalHigh = 0;
00131     lFrame.baseline = 0;
00132     lFrame.apvErrorBit.first = false;
00133     lFrame.apvErrorBit.second = false;
00134     lFrame.apvAddress.first = 0;
00135     lFrame.apvAddress.second = 0;
00136 
00137     uint16_t min = 0x3FF;
00138     uint16_t max = 0;
00139     edm::DetSetVector<SiStripRawDigi>::detset::const_iterator iDigi = channelDigis.begin();
00140     const edm::DetSetVector<SiStripRawDigi>::detset::const_iterator endChannelDigis = channelDigis.end();
00141 
00142     //counters for outputting warnings
00143     uint16_t numzeroes = 0, numsats = 0;
00144 
00145     if (iDigi == endChannelDigis) return lFrame;
00146 
00147     for (; iDigi != endChannelDigis; ++iDigi) {
00148       const uint16_t val = iDigi->adc();
00149       if (val < min) min = val;
00150       if (val > max) max = val;
00151       if (val==0)     numzeroes++;
00152       if (val==0x3FF) numsats++;
00153       lFrame.baseline += val;
00154     }
00155 
00156     if (channelDigis.size()>0) lFrame.baseline = lFrame.baseline/channelDigis.size();
00157     lFrame.digitalLow = min;
00158     lFrame.digitalHigh = max;
00159 
00160     const uint16_t threshold = static_cast<uint16_t>( (2.0 * static_cast<double>(max-min)) / 3.0 );
00161 
00162     if (aPrintDebug){
00163 //       if ( edm::isDebugEnabled() ) {
00164 //      LogDebug("SiStripSpyUtilities") << "Channel with key: " << lFrame.detId
00165 //                                      << " Min: " << min << " Max: " << max
00166 //                                      << " Range: " << (max-min) << " Threshold: " << threshold;
00167 //       }
00168       if (numzeroes>0 || numsats>0) {
00169         edm::LogWarning("SiStripSpyUtilities") << "Channel with key: " << lFrame.detId << " has "
00170                                                << numzeroes << " zero and "
00171                                                << numsats   << " saturated samples.";
00172       }
00173     }
00174 
00175     lFrame.firstHeaderBit = findHeaderBits(channelDigis,threshold);
00176     lFrame.firstTrailerBit = findTrailerBits(channelDigis,threshold);
00177 
00178     lFrame.apvErrorBit = findAPVErrorBits(channelDigis,threshold,lFrame.firstHeaderBit);
00179     lFrame.apvAddress = findAPVAddresses(channelDigis,threshold,lFrame.firstHeaderBit);
00180   
00181     return lFrame;
00182  
00183   }
00184 
00185   const uint16_t SpyUtilities::range(const SpyUtilities::Frame & aFrame)
00186   {
00187     if (aFrame.digitalHigh < aFrame.digitalLow) return 0;
00188     else return aFrame.digitalHigh-aFrame.digitalLow;
00189   }
00190 
00191   const uint16_t SpyUtilities::threshold(const SpyUtilities::Frame & aFrame)
00192   {
00193     return static_cast<uint16_t>( (2.0 * static_cast<double>(range(aFrame))) / 3.0 );
00194   }
00195 
00196   const uint8_t SpyUtilities::extractAPVaddress(const SpyUtilities::Frame & aFrame)
00197   {
00198 
00199     if (aFrame.apvErrorBit.first == false) return aFrame.apvAddress.first;
00200     else if (aFrame.apvErrorBit.second == false) {
00201       return aFrame.apvAddress.second;
00202     }
00203     else {
00204       return 0;
00205     }
00206     
00207   }
00208    
00209   void SpyUtilities::getMajorityHeader(const edm::DetSetVector<SiStripRawDigi> *aInputDigis,
00210                                        uint16_t & aFirstHeaderBit,
00211                                        bool printResult)
00212   {
00213 
00214     std::vector<uint16_t> lFirstBitVec;
00215     lFirstBitVec.reserve(aInputDigis->size());
00216     aFirstHeaderBit = 0;
00217     edm::DetSetVector<SiStripRawDigi>::const_iterator lDigis = aInputDigis->begin();
00218     
00219     for ( ; lDigis != aInputDigis->end(); lDigis++){
00220       sistrip::SpyUtilities::Frame lFrame = sistrip::SpyUtilities::extractFrameInfo(*lDigis);
00221       lFirstBitVec.push_back(lFrame.firstHeaderBit);
00222     }
00223 
00224     std::pair<uint16_t,uint32_t> lMaj = sistrip::SpyUtilities::findMajorityValue(lFirstBitVec);
00225     aFirstHeaderBit = lMaj.first;
00226     uint32_t lMajorityCounter = lMaj.second;
00227     
00228     //header is 24-sample long (2*8+2+6)
00229     uint16_t lFirstTrailerBit = aFirstHeaderBit+24+sistrip::STRIPS_PER_FEDCH;
00230     
00231     if (printResult)
00232       {
00233         LogInfo("SiStripSpyUtilities") << " -- Found majority position of first header (trailer) bit: " 
00234                                        << aFirstHeaderBit
00235                                        << " (" << lFirstTrailerBit 
00236                                        << ") for " << lMajorityCounter << " out of " << lFirstBitVec.size() << " channels."
00237                                        << std::endl;
00238       }
00239   }
00240 
00241 
00242   const bool SpyUtilities::isValid(const SpyUtilities::Frame & aFrame,
00243                                    const FrameQuality & aQuality,
00244                                    const uint16_t aExpectedPos)
00245   {
00246 
00247     uint16_t lRange = sistrip::SpyUtilities::range(aFrame);
00248 
00249     if (lRange < aQuality.minDigiRange || lRange > aQuality.maxDigiRange) {
00250       return false;
00251     }
00252     else if (aFrame.digitalLow < aQuality.minZeroLight || aFrame.digitalLow > aQuality.maxZeroLight) {
00253       return false;
00254     }
00255     else if (aFrame.digitalHigh < aQuality.minTickHeight || aFrame.digitalHigh > aQuality.maxTickHeight){
00256       return false;
00257     }
00258     //if expectedPos=0: return true whatever the position of header is...
00259     else if ( aExpectedPos > 0 && 
00260               (
00261                !(aFrame.firstHeaderBit == aExpectedPos && 
00262                  aFrame.firstTrailerBit == aExpectedPos+24+sistrip::STRIPS_PER_FEDCH)
00263                )
00264               ) {
00265       return false;
00266     }
00267     else if (aFrame.apvErrorBit.first && aFrame.apvErrorBit.second) {
00268       return false;
00269     }
00270     
00271     return true;
00272   }
00273 
00274 
00275   const uint16_t SpyUtilities::findHeaderBits(const edm::DetSetVector<SiStripRawDigi>::detset & channelDigis,
00276                                               const uint16_t threshold)
00277   {
00278 
00279     // Loop over digis looking for first above threshold
00280     uint8_t aboveThreshold = 0;
00281     bool foundHeader = false;
00282     uint16_t count = 0;
00283 
00284     edm::DetSetVector<SiStripRawDigi>::detset::const_iterator iDigi = channelDigis.begin();
00285     const edm::DetSetVector<SiStripRawDigi>::detset::const_iterator endChannelDigis = channelDigis.end();
00286 
00287     for (; iDigi != endChannelDigis; ++iDigi) {
00288       if ( iDigi->adc() > threshold) {
00289         aboveThreshold++;
00290       }
00291       else {
00292         aboveThreshold = 0;
00293       }
00294       if (aboveThreshold == 6) {foundHeader = true; break; }
00295       count++;
00296     }//end of loop over digis
00297 
00298     //break before incrementing the last time... so count-5 is the first header sample.
00299     if (foundHeader && count < 5) return 0;
00300     if (foundHeader) return count-5;
00301     return sistrip::SPY_SAMPLES_PER_CHANNEL;
00302  
00303   }
00304 
00305   const uint16_t SpyUtilities::findTrailerBits(const edm::DetSetVector<SiStripRawDigi>::detset & channelDigis,
00306                                                const uint16_t threshold)
00307   {
00308 
00309     // Loop over digis looking for last above threshold
00310     uint8_t aboveThreshold = 0;
00311     bool foundTrailer = false;
00312 
00313     //discard the first 30 values, which will have some digital high in them...
00314     //start searching from the expected position : sometimes after 24+256 samples,
00315     //normally at 6+24+256 if 6-bit low before tickmark header bits...
00316     uint16_t count = 24+sistrip::STRIPS_PER_FEDCH;
00317 
00318     if (count >= sistrip::SPY_SAMPLES_PER_CHANNEL) return sistrip::SPY_SAMPLES_PER_CHANNEL;
00319 
00320     edm::DetSetVector<SiStripRawDigi>::detset::const_iterator iDigi = channelDigis.begin()+count;
00321     const edm::DetSetVector<SiStripRawDigi>::detset::const_iterator endChannelDigis = channelDigis.end();
00322 
00323     for (; iDigi != endChannelDigis; ++iDigi) {
00324       if ( iDigi->adc() > threshold) {
00325         aboveThreshold++;
00326       }
00327       else {
00328         aboveThreshold = 0;
00329       }
00330       if (aboveThreshold == 2) {foundTrailer = true; break; }
00331       count++;
00332     }//end of loop over digis
00333 
00334     //break before incrementing the last time... so count-1 is the first trailer sample.
00335     if (foundTrailer && count < 1) return 0;
00336     if (foundTrailer) return count-1;
00337     return sistrip::SPY_SAMPLES_PER_CHANNEL;
00338  
00339   }
00340 
00341 
00342 
00343   const std::pair<bool,bool> 
00344   SpyUtilities::findAPVErrorBits(const edm::DetSetVector<SiStripRawDigi>::detset & channelDigis,
00345                                  const uint16_t threshold,
00346                                  const uint16_t aFirstBits)
00347   {
00348   
00349     // Loop over digis looking for firstHeader+6+16
00350     uint16_t count = aFirstBits+22;
00351 
00352     std::pair<bool,bool> lPair = std::pair<bool,bool>(false,false);
00353 
00354     //if header invalid: we don't know what apverr is....
00355     if (count >= sistrip::SPY_SAMPLES_PER_CHANNEL-1) return lPair;
00356 
00357     edm::DetSetVector<SiStripRawDigi>::detset::const_iterator iDigi = channelDigis.begin()+count;
00358     const edm::DetSetVector<SiStripRawDigi>::detset::const_iterator endChannelDigis = channelDigis.end();
00359 
00360     //double check....
00361     if (iDigi == endChannelDigis) return lPair;
00362 
00363     if ( iDigi->adc() <= threshold) lPair.first = true;
00364     ++iDigi;
00365 
00366     //triple check...
00367     if (iDigi == endChannelDigis) return std::pair<bool,bool>(false,false);
00368 
00369     if ( iDigi->adc() <= threshold) lPair.second = true;
00370 
00371     return lPair; 
00372   }
00373 
00374 
00375   const std::pair<uint8_t,uint8_t> 
00376   SpyUtilities::findAPVAddresses(const edm::DetSetVector<SiStripRawDigi>::detset & channelDigis,
00377                                  const uint16_t threshold,
00378                                  const uint16_t aFirstBits)
00379   {
00380   
00381     // Loop over digis looking for firstHeader+6
00382     uint16_t count = aFirstBits+6;
00383     std::pair<uint8_t,uint8_t> lPair = std::pair<uint8_t,uint8_t>(0,0);
00384 
00385     //check enough room to have 16 values....
00386     if (count >= sistrip::SPY_SAMPLES_PER_CHANNEL-15) return lPair;
00387 
00388     edm::DetSetVector<SiStripRawDigi>::detset::const_iterator iDigi = channelDigis.begin()+count;
00389     const edm::DetSetVector<SiStripRawDigi>::detset::const_iterator endChannelDigis = channelDigis.end();
00390 
00391     //double check....
00392     if (iDigi == endChannelDigis) return lPair;
00393 
00394     for (uint8_t i = 0; i < 16; ++i) {
00395       if ( iDigi->adc() > threshold) {
00396         //data is MSB first
00397         if (i%2==0)
00398           lPair.first |= (0x80 >> static_cast<uint8_t>(i/2));
00399         else 
00400           lPair.second |= (0x80 >> static_cast<uint8_t>(i/2));
00401       }
00402       ++iDigi;
00403     }
00404 
00405     return lPair;
00406 
00407   }
00408 
00409 
00410   std::string SpyUtilities::print(const SpyUtilities::Frame & aFrame,
00411                                   std::string aErr)
00412   {
00413 
00414     std::ostringstream lOs;
00415     lOs << " ------------------------------------------------------" << std::endl
00416         << " -- Error: " << aErr << std::endl
00417         << " ------- Printing Frame for detId " << aFrame.detId << " --------" << std::endl
00418         << " -- firstHeaderBit = " << aFrame.firstHeaderBit << std::endl
00419         << " -- firstTrailerBit = " << aFrame.firstTrailerBit << std::endl
00420         << " -- digitalLow = " << aFrame.digitalLow << std::endl
00421         << " -- digitalHigh = " << aFrame.digitalHigh << std::endl
00422         << " -- baseline = " << aFrame.baseline << std::endl
00423         << " -- apvErrorBits = " << aFrame.apvErrorBit.first
00424         << " " << aFrame.apvErrorBit.second << std::endl
00425         << " -- apvAddresses = " << static_cast<uint16_t>(aFrame.apvAddress.first)
00426         << " " << static_cast<uint16_t>(aFrame.apvAddress.second) << std::endl
00427         << " ------------------------------------------------------" << std::endl;
00428     return lOs.str();
00429 
00430   }
00431 
00432 
00433   void SpyUtilities::fedIndex(const uint32_t aFedIndex,
00434                               uint16_t & aFedId,
00435                               uint16_t & aFedChannel){
00436 
00437     //find the corresponding detId (for the pedestals)
00438     aFedId = static_cast<uint16_t>(aFedIndex/sistrip::FEDCH_PER_FED);
00439     aFedChannel = static_cast<uint16_t>(aFedIndex%sistrip::FEDCH_PER_FED);
00440   
00441     if (aFedId < sistrip::FED_ID_MIN ||
00442         aFedId > sistrip::FED_ID_MAX ||
00443         aFedChannel >= sistrip::FEDCH_PER_FED ) { 
00444       aFedId = sistrip::invalid_;
00445       aFedChannel = sistrip::invalid_;
00446     }
00447 
00448   }
00449 
00450   std::pair<uint16_t,uint32_t> SpyUtilities::findMajorityValue(std::vector<uint16_t>& values,
00451                                                                const uint16_t aFedId)
00452   {
00453 
00454     uint32_t lTot = values.size();
00455     if (!lTot) return std::pair<uint16_t,uint32_t>(0,0);
00456 
00457     std::sort(values.begin(),values.end());
00458     uint32_t lMajorityCounter = 0;
00459     uint16_t lMaj = 0;
00460 
00461     std::vector<uint16_t>::iterator lIter = values.begin();
00462     for ( ; lIter != values.end(); ) {
00463       uint32_t lCounter = std::count(lIter,values.end(),*lIter);
00464       if (lCounter > lMajorityCounter) {
00465         lMajorityCounter = lCounter;
00466         lMaj = *lIter;
00467       }
00468       lIter += lCounter;
00469     }
00470     
00471     //std::cout << " -- Found majority value " << lMaj << " for " << lMajorityCounter << " elements out of " << values.size() << "." << std::endl;
00472 
00473     if (static_cast<float>(lMajorityCounter)/lTot < 0.5) {
00474       LogError("SiStripSpyUtilities") << " -- Found majority position for index "
00475                                       << aFedId
00476                                       << ": " << lMaj
00477                                       << " for less than half the values : " << lMajorityCounter << " out of " << lTot << " values."
00478                                       << std::endl;
00479     }
00480 
00481     return std::pair<uint16_t,uint32_t>(lMaj,lMajorityCounter);
00482     
00483   }
00484 
00485   void SpyUtilities::fillFEDMajorities(const std::map<uint32_t,uint32_t>& channelValues, 
00486                                        std::vector<uint32_t> & fedMajoritiesToFill)
00487   {
00488 
00489     std::map<uint32_t,uint32_t>::const_iterator lMapIter = channelValues.begin();
00490     uint16_t lPreviousFedId = 0;
00491     std::vector<uint16_t> lAddrVec;
00492     lAddrVec.reserve(sistrip::FEDCH_PER_FED);
00493     fedMajoritiesToFill.resize(sistrip::FED_ID_MAX-sistrip::FED_ID_MIN+1,0);
00494     uint32_t lChCount = 0;
00495 
00496     for ( ; lMapIter != channelValues.end(); ++lMapIter,++lChCount){
00497 
00498       uint16_t lFedId = static_cast<uint16_t>(lMapIter->first/sistrip::FEDCH_PER_FED);
00499 
00500       if (lPreviousFedId == 0) {
00501         lPreviousFedId = lFedId;
00502       }
00503       if (lFedId == lPreviousFedId) {
00504         lAddrVec.push_back(lMapIter->second);
00505       }
00506       if (lFedId != lPreviousFedId || (lChCount == channelValues.size()-1)) {
00507         //extract majority address
00508 
00509         uint32_t lMaj = sistrip::SpyUtilities::findMajorityValue(lAddrVec,lPreviousFedId).first;
00510         fedMajoritiesToFill[lPreviousFedId] = lMaj;
00511 
00512         lAddrVec.clear();
00513         
00514         //if new fed, fill the first channel
00515         if (lFedId != lPreviousFedId) {
00516           lAddrVec.push_back(lMapIter->second);
00517           lPreviousFedId = lFedId;
00518         }
00519 
00520       }
00521     }
00522 
00523   }
00524 
00525 }//namespace