Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-08-10 22:49:28

0001 
0002 #include "DQM/SiStripCommissioningDbClients/interface/FastFedCablingHistosUsingDb.h"
0003 #include "CondFormats/SiStripObjects/interface/FastFedCablingAnalysis.h"
0004 #include "DataFormats/SiStripCommon/interface/SiStripConstants.h"
0005 #include "DataFormats/SiStripCommon/interface/SiStripFecKey.h"
0006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0007 #include <iostream>
0008 
0009 using namespace sistrip;
0010 
0011 // -----------------------------------------------------------------------------
0012 /** */
0013 FastFedCablingHistosUsingDb::FastFedCablingHistosUsingDb(const edm::ParameterSet& pset,
0014                                                          DQMStore* bei,
0015                                                          SiStripConfigDb* const db,
0016                                                          edm::ESGetToken<TrackerTopology, TrackerTopologyRcd> tTopoToken)
0017     : CommissioningHistograms(
0018           pset.getParameter<edm::ParameterSet>("FastFedCablingParameters"), bei, sistrip::FAST_CABLING),
0019       CommissioningHistosUsingDb(db, tTopoToken, sistrip::FAST_CABLING),
0020       FastFedCablingHistograms(pset.getParameter<edm::ParameterSet>("FastFedCablingParameters"), bei) {
0021   LogTrace(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0022                          << " Constructing object...";
0023 }
0024 
0025 // -----------------------------------------------------------------------------
0026 /** */
0027 FastFedCablingHistosUsingDb::~FastFedCablingHistosUsingDb() {
0028   LogTrace(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0029                          << " Destructing object...";
0030 }
0031 
0032 // -----------------------------------------------------------------------------
0033 /** */
0034 void FastFedCablingHistosUsingDb::uploadConfigurations() {
0035   LogTrace(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]";
0036 
0037   if (!db()) {
0038     edm::LogError(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0039                                 << " NULL pointer to SiStripConfigDb interface!"
0040                                 << " Aborting upload...";
0041     return;
0042   }
0043 
0044   SiStripDbParams::SiStripPartitions::const_iterator ip = db()->dbParams().partitions().begin();
0045   SiStripDbParams::SiStripPartitions::const_iterator jp = db()->dbParams().partitions().end();
0046   for (; ip != jp; ++ip) {
0047     // Retrieve descriptions
0048     db()->clearFedConnections();
0049     SiStripConfigDb::FedDescriptionsRange feds = db()->getFedDescriptions(ip->second.partitionName());
0050     SiStripConfigDb::DeviceDescriptionsRange dcus = db()->getDeviceDescriptions(DCU, ip->second.partitionName());
0051     SiStripConfigDb::DcuDetIdsRange detids = db()->getDcuDetIds(ip->second.partitionName());
0052 
0053     // Update FED connection descriptions
0054     SiStripConfigDb::FedConnectionsV conns;
0055     update(conns, feds, dcus, detids);
0056 
0057     if (doUploadConf()) {
0058       edm::LogVerbatim(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0059                                      << " Uploading FED connections for partition \"" << ip->second.partitionName()
0060                                      << "\" to DB...";
0061       db()->clearFedConnections(ip->second.partitionName());
0062       db()->addFedConnections(ip->second.partitionName(), conns);
0063       db()->uploadFedConnections(ip->second.partitionName());
0064       edm::LogVerbatim(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0065                                      << " Completed database upload of " << conns.size() << " ConnectionDescriptions!";
0066     } else {
0067       edm::LogWarning(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0068                                     << " TEST only! No FED connections will be uploaded to DB...";
0069     }
0070 
0071     // Update FED descriptions with enabled/disabled channels
0072     update(feds);
0073     if (doUploadConf()) {
0074       edm::LogVerbatim(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0075                                      << " Uploading FED descriptions to DB...";
0076       db()->uploadFedDescriptions(ip->second.partitionName());
0077       edm::LogVerbatim(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0078                                      << " Completed database upload of " << feds.size()
0079                                      << " Fed9UDescriptions (with connected channels enabled)!";
0080     } else {
0081       edm::LogWarning(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0082                                     << " TEST only! No FED descriptions will be uploaded to DB...";
0083     }
0084 
0085     // Some debug on good / dirty / missing connections
0086     connections(dcus, detids);
0087   }
0088 }
0089 
0090 // -----------------------------------------------------------------------------
0091 /** */
0092 void FastFedCablingHistosUsingDb::update(SiStripConfigDb::FedConnectionsV& conns,
0093                                          SiStripConfigDb::FedDescriptionsRange feds,
0094                                          SiStripConfigDb::DeviceDescriptionsRange dcus,
0095                                          SiStripConfigDb::DcuDetIdsRange detids) {
0096   // Update FED-FEC mapping in base class, based on analysis results
0097   Analyses::iterator ianal = data().begin();
0098   Analyses::iterator janal = data().end();
0099   for (; ianal != janal; ++ianal) {
0100     FastFedCablingAnalysis* anal = dynamic_cast<FastFedCablingAnalysis*>(ianal->second);
0101     if (!anal) {
0102       edm::LogError(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0103                                   << " NULL pointer to analysis object!";
0104       continue;
0105     }
0106 
0107     if (!anal->isValid() || anal->dcuId() == sistrip::invalid32_) {
0108       continue;
0109     }
0110 
0111     SiStripFecKey fec_key(anal->fecKey());
0112     SiStripFedKey fed_key(anal->fedKey());
0113 
0114     ConnectionDescription* conn = new ConnectionDescription();
0115     conn->setFedId(fed_key.fedId());
0116     conn->setFedChannel(fed_key.fedChannel());
0117     conn->setFecHardwareId("");  //@@
0118     conn->setFecCrateId(fec_key.fecCrate());
0119     conn->setFecSlot(fec_key.fecSlot());
0120     conn->setRingSlot(fec_key.fecRing());
0121     conn->setCcuAddress(fec_key.ccuAddr());
0122     conn->setI2cChannel(fec_key.ccuChan());
0123     conn->setApvAddress(SiStripFecKey::i2cAddr(anal->lldCh(), true));
0124     conn->setDcuHardId(anal->dcuHardId());
0125 
0126     // Retrieve FED crate and slot numbers
0127     bool found = false;
0128     SiStripConfigDb::FedDescriptionsV::const_iterator ifed = feds.begin();
0129     while (ifed != feds.end() && !found) {
0130       if (*ifed) {
0131         uint16_t fed_id = static_cast<uint16_t>((*ifed)->getFedId());
0132         if (fed_key.fedId() == fed_id) {
0133           conn->setFedCrateId(static_cast<uint16_t>((*ifed)->getCrateNumber()));
0134           conn->setFedSlot(static_cast<uint16_t>((*ifed)->getSlotNumber()));
0135           found = true;
0136         }
0137       } else {
0138         edm::LogError(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0139                                     << " NULL pointer to Fed9UDescription object!";
0140         continue;
0141       }
0142       ++ifed;
0143     }
0144     if (!found) {
0145       edm::LogError(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0146                                   << " Could not find FED id " << fed_key.fedId() << " in vector of FED descriptions!"
0147                                   << " Unable to set FED crate and slot for this FED!";
0148     }
0149 
0150     conns.push_back(conn);
0151   }
0152 
0153   if (false) {
0154     SiStripConfigDb::FedConnectionsV::iterator ifed = conns.begin();
0155     for (; ifed != conns.end(); ifed++) {
0156       (*ifed)->display();
0157     }
0158   }
0159 }
0160 
0161 // -----------------------------------------------------------------------------
0162 /** */
0163 void FastFedCablingHistosUsingDb::update(SiStripConfigDb::FedDescriptionsRange feds) {
0164   // Iterate through feds and disable all channels
0165   SiStripConfigDb::FedDescriptionsV::const_iterator ifed = feds.begin();
0166   SiStripConfigDb::FedDescriptionsV::const_iterator jfed = feds.end();
0167   try {
0168     for (; ifed != jfed; ++ifed) {
0169       for (uint16_t ichan = 0; ichan < sistrip::FEDCH_PER_FED; ichan++) {
0170         Fed9U::Fed9UAddress addr(ichan);
0171         Fed9U::Fed9UAddress addr0(ichan, static_cast<Fed9U::u8>(0));
0172         Fed9U::Fed9UAddress addr1(ichan, static_cast<Fed9U::u8>(1));
0173         (*ifed)->setFedFeUnitDisable(addr, true);
0174         (*ifed)->setApvDisable(addr0, true);
0175         (*ifed)->setApvDisable(addr1, true);
0176       }
0177     }
0178   } catch (ICUtils::ICException& e) {
0179     edm::LogWarning(mlDqmClient_) << e.what();
0180   }
0181 
0182   // Counters for number of connected / enabled channels
0183   uint16_t connected = 0;
0184   std::map<uint16_t, std::vector<uint16_t> > enabled;
0185 
0186   // Iterate through feds and enable connected channels
0187   for (ifed = feds.begin(); ifed != feds.end(); ifed++) {
0188     for (uint16_t ichan = 0; ichan < sistrip::FEDCH_PER_FED; ichan++) {
0189       // Retrieve FEC key from FED-FEC map
0190       SiStripFedKey fed(
0191           static_cast<uint16_t>((*ifed)->getFedId()), SiStripFedKey::feUnit(ichan), SiStripFedKey::feChan(ichan));
0192       uint32_t fed_key = fed.key();
0193 
0194       // Retrieve analysis for given FED id and channel
0195       Analyses::const_iterator iter = data().find(fed_key);
0196       if (iter == data().end()) {
0197         continue;
0198       }
0199 
0200       if (!iter->second->isValid()) {
0201         continue;
0202       }
0203 
0204       FastFedCablingAnalysis* anal = dynamic_cast<FastFedCablingAnalysis*>(iter->second);
0205       if (!anal) {
0206         edm::LogError(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0207                                     << " NULL pointer to OptoScanAnalysis object!";
0208         continue;
0209       }
0210 
0211       // Retrieve FED id and channel
0212       SiStripFedKey key(anal->fedKey());
0213       uint16_t fed_id = key.fedId();
0214       uint16_t fed_ch = key.fedChannel();
0215 
0216       // Enable front-end unit and channel
0217       Fed9U::Fed9UAddress addr(fed_ch);
0218       Fed9U::Fed9UAddress addr0(fed_ch, static_cast<Fed9U::u8>(0));
0219       Fed9U::Fed9UAddress addr1(fed_ch, static_cast<Fed9U::u8>(1));
0220       (*ifed)->setFedFeUnitDisable(addr, false);
0221       (*ifed)->setApvDisable(addr0, false);
0222       (*ifed)->setApvDisable(addr1, false);
0223       connected++;
0224       enabled[fed_id].push_back(fed_ch);
0225     }
0226   }
0227 
0228   // Some debug
0229   std::stringstream sss;
0230   if (!feds.empty()) {
0231     sss << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0232         << " Enabled a total of " << connected << " FED channels and disabled " << feds.size() * 96 - connected
0233         << " FED channels (" << 100 * connected / (feds.size() * 96) << "% of total)";
0234     edm::LogVerbatim(mlDqmClient_) << sss.str();
0235   } else {
0236     sss << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0237         << " Found no FEDs! (and therefore no connected channels)";
0238     edm::LogWarning(mlDqmClient_) << sss.str();
0239   }
0240 
0241   // Some debug
0242   std::stringstream ss;
0243   ss << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0244      << " Dump of enabled FED channels:" << std::endl;
0245   std::map<uint16_t, std::vector<uint16_t> >::const_iterator fed = enabled.begin();
0246   for (; fed != enabled.end(); fed++) {
0247     ss << " Enabled " << fed->second.size() << " channels for FED id " << std::setw(3) << fed->first << ": ";
0248     if (!fed->second.empty()) {
0249       uint16_t first = fed->second.front();
0250       uint16_t last = fed->second.front();
0251       std::vector<uint16_t>::const_iterator chan = fed->second.begin();
0252       for (; chan != fed->second.end(); chan++) {
0253         if (chan != fed->second.begin()) {
0254           if (*chan != last + 1) {
0255             ss << std::setw(2) << first << "->" << std::setw(2) << last << ", ";
0256             if (chan != fed->second.end()) {
0257               first = *(chan + 1);
0258             }
0259           }
0260         }
0261         last = *chan;
0262       }
0263       if (first != last) {
0264         ss << std::setw(2) << first << "->" << std::setw(2) << last;
0265       }
0266       ss << std::endl;
0267     }
0268   }
0269   LogTrace(mlDqmClient_) << ss.str();
0270 }
0271 
0272 // -----------------------------------------------------------------------------
0273 //
0274 void FastFedCablingHistosUsingDb::addDcuDetIds() {
0275   if (!cabling()) {
0276     edm::LogError(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0277                                 << " NULL pointer to SiStripFedCabling object!";
0278     return;
0279   }
0280 
0281   // retrieve descriptions for dcu id and det id
0282   SiStripConfigDb::DeviceDescriptionsRange dcus = db()->getDeviceDescriptions(DCU);
0283   SiStripConfigDb::DcuDetIdsRange detids = db()->getDcuDetIds();
0284 
0285   if (dcus.empty()) {
0286     edm::LogError(mlCabling_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0287                               << " No DCU descriptions found!";
0288     return;
0289   }
0290 
0291   if (detids.empty()) {
0292     edm::LogWarning(mlCabling_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0293                                 << " DCU-DetId map is empty!";
0294   }
0295 
0296   Analyses::iterator ianal = data().begin();
0297   Analyses::iterator janal = data().end();
0298   for (; ianal != janal; ++ianal) {
0299     // check if analysis is valid (ie, dcu id and lld channel have been identified)
0300     if (!ianal->second->isValid()) {
0301       continue;
0302     }
0303 
0304     // retrieve analysis object
0305     FastFedCablingAnalysis* anal = dynamic_cast<FastFedCablingAnalysis*>(ianal->second);
0306 
0307     if (!anal) {
0308       edm::LogError(mlDqmClient_) << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0309                                   << " NULL pointer to FastFedCablingAnalysis object!";
0310       return;
0311     }
0312 
0313     // find dcu that matches analysis result
0314     bool found = false;
0315     SiStripConfigDb::DeviceDescriptionsV::const_iterator idcu = dcus.begin();
0316     SiStripConfigDb::DeviceDescriptionsV::const_iterator jdcu = dcus.end();
0317     while (!found && idcu != jdcu) {
0318       dcuDescription* dcu = dynamic_cast<dcuDescription*>(*idcu);
0319       if (dcu) {
0320         if (dcu->getDcuType() == "FEH") {
0321           if (dcu->getDcuHardId() == anal->dcuHardId()) {
0322             found = true;
0323             anal->dcuId(dcu->getDcuHardId());
0324             const SiStripConfigDb::DeviceAddress& addr = db()->deviceAddress(*dcu);
0325             uint32_t fec_key =
0326                 SiStripFecKey(addr.fecCrate_, addr.fecSlot_, addr.fecRing_, addr.ccuAddr_, addr.ccuChan_, anal->lldCh())
0327                     .key();
0328             anal->fecKey(fec_key);
0329             SiStripConfigDb::DcuDetIdsV::const_iterator idet = detids.end();
0330             idet = SiStripConfigDb::findDcuDetId(detids.begin(), detids.end(), dcu->getDcuHardId());
0331             if (idet != detids.end()) {
0332               anal->detId(idet->second->getDetId());
0333             }
0334           }
0335         }
0336       }
0337       idcu++;
0338     }
0339   }
0340 }
0341 
0342 // -----------------------------------------------------------------------------
0343 /** */
0344 void FastFedCablingHistosUsingDb::create(SiStripConfigDb::AnalysisDescriptionsV& desc, Analysis analysis) {
0345   FastFedCablingAnalysis* anal = dynamic_cast<FastFedCablingAnalysis*>(analysis->second);
0346   if (!anal) {
0347     return;
0348   }
0349 
0350   if (!anal->isValid() || anal->dcuId() == sistrip::invalid32_) {
0351     return;
0352   }  //@@ only store valid descriptions!
0353 
0354   SiStripFecKey fec_key(anal->fecKey());
0355   SiStripFedKey fed_key(anal->fedKey());
0356 
0357   for (uint16_t iapv = 0; iapv < 2; ++iapv) {
0358     // Create description
0359     FastFedCablingAnalysisDescription* tmp;
0360     tmp = new FastFedCablingAnalysisDescription(anal->highLevel(),
0361                                                 anal->highRms(),
0362                                                 anal->lowLevel(),
0363                                                 anal->lowRms(),
0364                                                 anal->max(),
0365                                                 anal->min(),
0366                                                 anal->dcuId(),
0367                                                 anal->lldCh(),
0368                                                 anal->isDirty(),
0369                                                 FastFedCablingAnalysis::threshold_,
0370                                                 FastFedCablingAnalysis::dirtyThreshold_,
0371                                                 fec_key.fecCrate(),
0372                                                 fec_key.fecSlot(),
0373                                                 fec_key.fecRing(),
0374                                                 fec_key.ccuAddr(),
0375                                                 fec_key.ccuChan(),
0376                                                 SiStripFecKey::i2cAddr(fec_key.lldChan(), !iapv),
0377                                                 db()->dbParams().partitions().begin()->second.partitionName(),
0378                                                 db()->dbParams().partitions().begin()->second.runNumber(),
0379                                                 anal->isValid(),
0380                                                 "",
0381                                                 fed_key.fedId(),
0382                                                 fed_key.feUnit(),
0383                                                 fed_key.feChan(),
0384                                                 fed_key.fedApv());
0385 
0386     // Add comments
0387     typedef std::vector<std::string> Strings;
0388     Strings errors = anal->getErrorCodes();
0389     Strings::const_iterator istr = errors.begin();
0390     Strings::const_iterator jstr = errors.end();
0391     for (; istr != jstr; ++istr) {
0392       tmp->addComments(*istr);
0393     }
0394 
0395     // Store description
0396     desc.push_back(tmp);
0397   }
0398 }
0399 
0400 // -----------------------------------------------------------------------------
0401 // prints debug info on good, dirty, missing connections, and missing devices
0402 void FastFedCablingHistosUsingDb::connections(SiStripConfigDb::DeviceDescriptionsRange dcus,
0403                                               SiStripConfigDb::DcuDetIdsRange detids) {
0404   // strings
0405   std::vector<std::string> valid;
0406   std::vector<std::string> dirty;
0407   std::vector<std::string> trimdac;
0408   std::vector<std::string> missing;
0409   std::vector<std::string> devices;
0410   uint32_t missing_pairs = 0;
0411 
0412   // iterate through analyses
0413   std::vector<uint32_t> found_dcus;
0414   Analyses::iterator ianal = data().begin();
0415   Analyses::iterator janal = data().end();
0416   for (; ianal != janal; ++ianal) {
0417     // extract fast fed cabling object
0418     FastFedCablingAnalysis* anal = dynamic_cast<FastFedCablingAnalysis*>(ianal->second);
0419     if (!anal) {
0420       continue;
0421     }
0422 
0423     // construct strings for various categories of connections
0424     std::stringstream ss;
0425     SiStripFedKey(anal->fedKey()).terse(ss);
0426     ss << " ";
0427     SiStripFecKey(anal->fecKey()).terse(ss);
0428     ss << " ";
0429     ss << "DcuId= " << std::hex << std::setw(8) << std::setfill('0') << anal->dcuId() << std::dec << " ";
0430     ss << "DetId= " << std::hex << std::setw(8) << std::setfill('0') << anal->detId() << std::dec;
0431     if (anal->isValid() && !(anal->isDirty()) && !(anal->badTrimDac())) {
0432       valid.push_back(ss.str());
0433     }
0434     if (anal->isDirty()) {
0435       dirty.push_back(ss.str());
0436     }
0437     if (anal->badTrimDac()) {
0438       trimdac.push_back(ss.str());
0439     }
0440 
0441     // record "found" dcus
0442     found_dcus.push_back(anal->dcuHardId());
0443   }
0444 
0445   // iterate through dcu devices
0446   SiStripConfigDb::DeviceDescriptionsV::const_iterator idcu = dcus.begin();
0447   SiStripConfigDb::DeviceDescriptionsV::const_iterator jdcu = dcus.end();
0448   for (; idcu != jdcu; ++idcu) {
0449     // extract dcu description
0450     dcuDescription* dcu = dynamic_cast<dcuDescription*>(*idcu);
0451     if (!dcu) {
0452       continue;
0453     }
0454     if (dcu->getDcuType() != "FEH") {
0455       continue;
0456     }
0457     SiStripConfigDb::DeviceAddress dcu_addr = db()->deviceAddress(*dcu);
0458 
0459     // continue if dcu has been "found"
0460     std::vector<uint32_t>::const_iterator iter = find(found_dcus.begin(), found_dcus.end(), dcu->getDcuHardId());
0461     if (iter != found_dcus.end()) {
0462       continue;
0463     }
0464 
0465     // find detid for "missing" dcu
0466     SiStripConfigDb::DcuDetIdsV::const_iterator idet = detids.end();
0467     idet = SiStripConfigDb::findDcuDetId(detids.begin(), detids.end(), dcu->getDcuHardId());
0468     if (idet == detids.end()) {
0469       continue;
0470     }
0471     if (!idet->second) {
0472       continue;
0473     }
0474 
0475     // retrieve number of apv pairs
0476     uint16_t npairs = idet->second->getApvNumber() / 2;
0477 
0478     // retrieve apvs for given dcu
0479     vector<bool> addrs;
0480     addrs.resize(6, false);
0481     SiStripConfigDb::DeviceDescriptionsRange apvs = db()->getDeviceDescriptions(APV25);
0482     SiStripConfigDb::DeviceDescriptionsV::const_iterator iapv = apvs.begin();
0483     SiStripConfigDb::DeviceDescriptionsV::const_iterator japv = apvs.end();
0484     for (; iapv != japv; ++iapv) {
0485       apvDescription* apv = dynamic_cast<apvDescription*>(*iapv);
0486       if (!apv) {
0487         continue;
0488       }
0489       SiStripConfigDb::DeviceAddress apv_addr = db()->deviceAddress(*apv);
0490       if (apv_addr.fecCrate_ == dcu_addr.fecCrate_ && apv_addr.fecSlot_ == dcu_addr.fecSlot_ &&
0491           apv_addr.fecRing_ == dcu_addr.fecRing_ && apv_addr.ccuAddr_ == dcu_addr.ccuAddr_ &&
0492           apv_addr.ccuChan_ == dcu_addr.ccuChan_) {
0493         uint16_t pos = apv_addr.i2cAddr_ - 32;
0494         if (pos < 6) {
0495           addrs[pos] = true;
0496         }
0497       }
0498     }
0499 
0500     // construct strings for missing fibres
0501     uint16_t pairs = 0;
0502     if (addrs[0] || addrs[1]) {
0503       pairs++;
0504       std::stringstream ss;
0505       SiStripFecKey(dcu_addr.fecCrate_, dcu_addr.fecSlot_, dcu_addr.fecRing_, dcu_addr.ccuAddr_, dcu_addr.ccuChan_, 1)
0506           .terse(ss);
0507       ss << " DcuId=" << std::hex << std::setw(8) << std::setfill('0') << dcu->getDcuHardId() << std::dec;
0508       ss << " DetId=" << std::hex << std::setw(8) << std::setfill('0') << idet->first << std::dec;
0509       missing.push_back(ss.str());
0510     }
0511     if (addrs[2] || addrs[3]) {
0512       pairs++;
0513       std::stringstream ss;
0514       SiStripFecKey(dcu_addr.fecCrate_, dcu_addr.fecSlot_, dcu_addr.fecRing_, dcu_addr.ccuAddr_, dcu_addr.ccuChan_, 2)
0515           .terse(ss);
0516       ss << " DcuId=" << std::hex << std::setw(8) << std::setfill('0') << dcu->getDcuHardId() << std::dec;
0517       ss << " DetId=" << std::hex << std::setw(8) << std::setfill('0') << idet->first << std::dec;
0518       missing.push_back(ss.str());
0519     }
0520     if (addrs[4] || addrs[5]) {
0521       pairs++;
0522       std::stringstream ss;
0523       SiStripFecKey(dcu_addr.fecCrate_, dcu_addr.fecSlot_, dcu_addr.fecRing_, dcu_addr.ccuAddr_, dcu_addr.ccuChan_, 3)
0524           .terse(ss);
0525       ss << " DcuId=" << std::hex << std::setw(8) << std::setfill('0') << dcu->getDcuHardId() << std::dec;
0526       ss << " DetId=" << std::hex << std::setw(8) << std::setfill('0') << idet->first << std::dec;
0527       missing.push_back(ss.str());
0528     }
0529 
0530     if (pairs != npairs) {
0531       missing_pairs = npairs - pairs;
0532 
0533       if (!addrs[0]) {
0534         std::stringstream ss;
0535         SiStripFecKey(
0536             dcu_addr.fecCrate_, dcu_addr.fecSlot_, dcu_addr.fecRing_, dcu_addr.ccuAddr_, dcu_addr.ccuChan_, 1, 32)
0537             .terse(ss);
0538         ss << " DcuId=" << std::hex << std::setw(8) << std::setfill('0') << dcu->getDcuHardId() << std::dec;
0539         ss << " DetId=" << std::hex << std::setw(8) << std::setfill('0') << idet->first << std::dec;
0540         devices.push_back(ss.str());
0541       }
0542 
0543       if (!addrs[1]) {
0544         std::stringstream ss;
0545         SiStripFecKey(
0546             dcu_addr.fecCrate_, dcu_addr.fecSlot_, dcu_addr.fecRing_, dcu_addr.ccuAddr_, dcu_addr.ccuChan_, 1, 33)
0547             .terse(ss);
0548         ss << " DcuId=" << std::hex << std::setw(8) << std::setfill('0') << dcu->getDcuHardId() << std::dec;
0549         ss << " DetId=" << std::hex << std::setw(8) << std::setfill('0') << idet->first << std::dec;
0550         devices.push_back(ss.str());
0551       }
0552 
0553       if (!addrs[2] && npairs == 3) {
0554         std::stringstream ss;
0555         SiStripFecKey(
0556             dcu_addr.fecCrate_, dcu_addr.fecSlot_, dcu_addr.fecRing_, dcu_addr.ccuAddr_, dcu_addr.ccuChan_, 2, 34)
0557             .terse(ss);
0558         ss << " DcuId=" << std::hex << std::setw(8) << std::setfill('0') << dcu->getDcuHardId() << std::dec;
0559         ss << " DetId=" << std::hex << std::setw(8) << std::setfill('0') << idet->first << std::dec;
0560         devices.push_back(ss.str());
0561       }
0562 
0563       if (!addrs[3] && npairs == 3) {
0564         std::stringstream ss;
0565         SiStripFecKey(
0566             dcu_addr.fecCrate_, dcu_addr.fecSlot_, dcu_addr.fecRing_, dcu_addr.ccuAddr_, dcu_addr.ccuChan_, 2, 35)
0567             .terse(ss);
0568         ss << " DcuId=" << std::hex << std::setw(8) << std::setfill('0') << dcu->getDcuHardId() << std::dec;
0569         ss << " DetId=" << std::hex << std::setw(8) << std::setfill('0') << idet->first << std::dec;
0570         devices.push_back(ss.str());
0571       }
0572 
0573       if (!addrs[4]) {
0574         std::stringstream ss;
0575         SiStripFecKey(
0576             dcu_addr.fecCrate_, dcu_addr.fecSlot_, dcu_addr.fecRing_, dcu_addr.ccuAddr_, dcu_addr.ccuChan_, 3, 36)
0577             .terse(ss);
0578         ss << " DcuId=" << std::hex << std::setw(8) << std::setfill('0') << dcu->getDcuHardId() << std::dec;
0579         ss << " DetId=" << std::hex << std::setw(8) << std::setfill('0') << idet->first << std::dec;
0580         devices.push_back(ss.str());
0581       }
0582 
0583       if (!addrs[5]) {
0584         std::stringstream ss;
0585         SiStripFecKey(
0586             dcu_addr.fecCrate_, dcu_addr.fecSlot_, dcu_addr.fecRing_, dcu_addr.ccuAddr_, dcu_addr.ccuChan_, 3, 37)
0587             .terse(ss);
0588         ss << " DcuId=" << std::hex << std::setw(8) << std::setfill('0') << dcu->getDcuHardId() << std::dec;
0589         ss << " DetId=" << std::hex << std::setw(8) << std::setfill('0') << idet->first << std::dec;
0590         devices.push_back(ss.str());
0591       }
0592     }
0593   }
0594 
0595   // summary
0596   {
0597     std::stringstream ss;
0598     ss << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0599        << " Summary of connections: " << std::endl
0600        << " \"Good\" connections     : " << valid.size() << std::endl
0601        << " \"Dirty\" connections    : " << dirty.size() << std::endl
0602        << " \"Bad\" TrimDAQ settings : " << trimdac.size() << std::endl
0603        << " (\"Missing\" connections : " << missing.size() << ")" << std::endl
0604        << " (\"Missing\" APV pairs   : " << missing_pairs << ")" << std::endl
0605        << " (\"Missing\" APVs        : " << devices.size() << ")" << std::endl;
0606     edm::LogVerbatim(mlCabling_) << ss.str();
0607   }
0608 
0609   // good connections
0610   if (!valid.empty()) {
0611     std::stringstream ss;
0612     ss << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0613        << " List of \"good\" connections: " << std::endl;
0614     std::vector<std::string>::const_iterator istr = valid.begin();
0615     std::vector<std::string>::const_iterator jstr = valid.end();
0616     for (; istr != jstr; ++istr) {
0617       ss << *istr << std::endl;
0618     }
0619     LogTrace(mlCabling_) << ss.str();
0620   }
0621 
0622   // dirty connections
0623   if (!dirty.empty()) {
0624     std::stringstream ss;
0625     ss << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0626        << " List of \"dirty\" connections: " << std::endl;
0627     std::vector<std::string>::const_iterator istr = dirty.begin();
0628     std::vector<std::string>::const_iterator jstr = dirty.end();
0629     for (; istr != jstr; ++istr) {
0630       ss << *istr << std::endl;
0631     }
0632     edm::LogWarning(mlCabling_) << ss.str();
0633   }
0634 
0635   // TrimDAC connections
0636   if (!trimdac.empty()) {
0637     std::stringstream ss;
0638     ss << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0639        << " List of \"bad\" TrimDAC settings: " << std::endl;
0640     std::vector<std::string>::const_iterator istr = trimdac.begin();
0641     std::vector<std::string>::const_iterator jstr = trimdac.end();
0642     for (; istr != jstr; ++istr) {
0643       ss << *istr << std::endl;
0644     }
0645     edm::LogWarning(mlCabling_) << ss.str();
0646   }
0647 
0648   // missing connections
0649   if (!missing.empty()) {
0650     std::stringstream ss;
0651     ss << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0652        << " List of \"missing\" connections: " << std::endl;
0653     std::vector<std::string>::const_iterator istr = missing.begin();
0654     std::vector<std::string>::const_iterator jstr = missing.end();
0655     for (; istr != jstr; ++istr) {
0656       ss << *istr << std::endl;
0657     }
0658     edm::LogError(mlCabling_) << ss.str();
0659   }
0660 
0661   // missing devices
0662   if (!devices.empty()) {
0663     std::stringstream ss;
0664     ss << "[FastFedCablingHistosUsingDb::" << __func__ << "]"
0665        << " List of \"missing\" APVs: " << std::endl;
0666     std::vector<std::string>::const_iterator istr = devices.begin();
0667     std::vector<std::string>::const_iterator jstr = devices.end();
0668     for (; istr != jstr; ++istr) {
0669       ss << *istr << std::endl;
0670     }
0671     edm::LogError(mlCabling_) << ss.str();
0672   }
0673 }