Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
#include <memory>

#include <vector>

#include "FWCore/Utilities/interface/Exception.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"

#include "DataFormats/Common/interface/DetSetVector.h"
#include "DataFormats/Common/interface/DetSet.h"
#include "DataFormats/SiStripDigi/interface/SiStripRawDigi.h"
#include "DataFormats/SiStripCommon/interface/ConstantsForHardwareSystems.h"
#include "DataFormats/SiStripCommon/interface/SiStripFedKey.h"

#include "CondFormats/SiStripObjects/interface/SiStripFedCabling.h"
#include "CondFormats/SiStripObjects/interface/FedChannelConnection.h"

#include "EventFilter/SiStripRawToDigi/interface/SiStripFEDBufferComponents.h"
#include "EventFilter/SiStripRawToDigi/interface/SiStripDetSetVectorFiller.h"

#include "DQM/SiStripMonitorHardware/interface/SiStripFEDSpyBuffer.h"
#include "DQM/SiStripMonitorHardware/interface/SiStripSpyDigiConverter.h"

namespace sistrip {

  std::unique_ptr<SpyDigiConverter::DSVRawDigis> SpyDigiConverter::extractPayloadDigis(
      const DSVRawDigis* inputScopeDigis,
      std::vector<uint32_t>* pAPVAddresses,
      const bool discardDigisWithAPVAddrErr,
      const sistrip::SpyUtilities::FrameQuality& aQuality,
      const uint16_t expectedPos) {
    // Data is already sorted so push back fast into vector to avoid sorts and create DSV later
    std::vector<DetSetRawDigis> outputData;
    outputData.reserve(inputScopeDigis->size());

    //APV address vector indexed by fedid, majority value written.
    pAPVAddresses->resize(sistrip::FED_ID_MAX + 1, 0);
    std::vector<uint16_t> lAddrVec;
    lAddrVec.reserve(2 * sistrip::FEDCH_PER_FED);
    uint16_t lPreviousFedId = 0;
    std::vector<uint16_t> lHeaderBitVec;
    lHeaderBitVec.reserve(sistrip::FEDCH_PER_FED);
    std::vector<uint16_t> lTrailBitVec;
    lTrailBitVec.reserve(sistrip::FEDCH_PER_FED);

    //local DSVRawDigis per FED
    std::vector<DSVRawDigis::const_iterator> lFedScopeDigis;
    lFedScopeDigis.reserve(sistrip::FEDCH_PER_FED);

    // Loop over channels in input collection
    DSVRawDigis::const_iterator inputChannel = inputScopeDigis->begin();
    const DSVRawDigis::const_iterator endChannels = inputScopeDigis->end();
    bool hasBeenProcessed = false;

    for (; inputChannel != endChannels; ++inputChannel) {
      const uint32_t lFedIndex = inputChannel->detId();
      const uint16_t fedId = static_cast<uint16_t>((lFedIndex >> 16) & 0xFFFF);

      // Fill frame parameters. Second parameter is to print debug info (if logDebug enabled....)
      const sistrip::SpyUtilities::Frame lFrame = sistrip::SpyUtilities::extractFrameInfo(*inputChannel, false);

      if (lPreviousFedId == 0) {
        lPreviousFedId = fedId;
      }

      //print out warning only for non-empty frames....
      if (!sistrip::SpyUtilities::isValid(lFrame, aQuality, expectedPos)) {
        if (lFrame.firstHeaderBit < sistrip::SPY_SAMPLES_PER_CHANNEL) {
          //  edm::LogWarning("SiStripSpyDigiConverter") << " FED ID: " << fedId << ", channel: " << fedCh << std::endl
          //						     << sistrip::SpyUtilities::print(lFrame,
          //										     std::string("  -- Invalid Frame ")
          //										     );
        }
        continue;
      }

      //fill local vectors per FED
      if (fedId == lPreviousFedId) {
        if (hasBeenProcessed)
          hasBeenProcessed = false;
      }
      if (fedId != lPreviousFedId) {
        SpyDigiConverter::processFED(lPreviousFedId,
                                     discardDigisWithAPVAddrErr,
                                     pAPVAddresses,
                                     outputData,
                                     lAddrVec,
                                     lHeaderBitVec,
                                     lTrailBitVec,
                                     lFedScopeDigis);
        lPreviousFedId = fedId;
        hasBeenProcessed = true;
      }
      // add digis
      lFedScopeDigis.push_back(inputChannel);
      lAddrVec.push_back(lFrame.apvAddress.first);
      lAddrVec.push_back(lFrame.apvAddress.second);
      lHeaderBitVec.push_back(lFrame.firstHeaderBit);
      lTrailBitVec.push_back(lFrame.firstTrailerBit);

    }  // end of loop over channels.

    //process the last one if not already done.
    if (!hasBeenProcessed) {
      SpyDigiConverter::processFED(lPreviousFedId,
                                   discardDigisWithAPVAddrErr,
                                   pAPVAddresses,
                                   outputData,
                                   lAddrVec,
                                   lHeaderBitVec,
                                   lTrailBitVec,
                                   lFedScopeDigis);
    }

    //return DSV of output
    return std::make_unique<DSVRawDigis>(outputData, true);

  }  // end of SpyDigiConverter::extractPayloadDigis method

  void SpyDigiConverter::processFED(const uint16_t aPreviousFedId,
                                    const bool discardDigisWithAPVAddrErr,
                                    std::vector<uint32_t>* pAPVAddresses,
                                    std::vector<DetSetRawDigis>& outputData,
                                    std::vector<uint16_t>& aAddrVec,
                                    std::vector<uint16_t>& aHeaderBitVec,
                                    std::vector<uint16_t>& aTrailBitVec,
                                    std::vector<DSVRawDigis::const_iterator>& aFedScopeDigis) {
    //extract majority address
    uint32_t lMaj = sistrip::SpyUtilities::findMajorityValue(aAddrVec, aPreviousFedId).first;
    if (pAPVAddresses)
      (*pAPVAddresses)[aPreviousFedId] = lMaj;

    //loop over iterators and fill payload
    std::vector<DSVRawDigis::const_iterator>::iterator lIter;
    unsigned int lCh = 0;
    for (lIter = aFedScopeDigis.begin(); lIter != aFedScopeDigis.end(); ++lIter, ++lCh) {
      //discard if APV address different from majority.
      //Keep if only one of them is wrong: the other APV might be alright ??

      if (discardDigisWithAPVAddrErr && aAddrVec[2 * lCh] != lMaj && aAddrVec[2 * lCh + 1] != lMaj) {
        continue;
      }

      DetSetRawDigis::const_iterator iDigi = (*lIter)->begin();
      const DetSetRawDigis::const_iterator endOfChannel = (*lIter)->end();

      if (iDigi == endOfChannel) {
        continue;
      }

      //header starts in sample firstHeaderBit and is 18+6 samples long
      const DetSetRawDigis::const_iterator payloadBegin = iDigi + aHeaderBitVec[lCh] + 24;
      const DetSetRawDigis::const_iterator payloadEnd = payloadBegin + STRIPS_PER_FEDCH;

      if (payloadEnd - iDigi >= endOfChannel - iDigi)
        continue;  // few-cases where this is possible, i.e. nothing above frame-threhsold

      // Copy data into output collection
      // Create new detSet with same key (in this case it is the fedKey, not detId)
      outputData.push_back(DetSetRawDigis((*lIter)->detId()));
      std::vector<SiStripRawDigi>& outputDetSetData = outputData.back().data;
      outputDetSetData.resize(STRIPS_PER_FEDCH);
      std::vector<SiStripRawDigi>::iterator outputBegin = outputDetSetData.begin();
      std::copy(payloadBegin, payloadEnd, outputBegin);
    }

    aFedScopeDigis.clear();
    aAddrVec.clear();
    aHeaderBitVec.clear();
    aTrailBitVec.clear();

    aAddrVec.reserve(2 * sistrip::FEDCH_PER_FED);
    aHeaderBitVec.reserve(sistrip::FEDCH_PER_FED);
    aTrailBitVec.reserve(sistrip::FEDCH_PER_FED);
    aFedScopeDigis.reserve(sistrip::FEDCH_PER_FED);
  }

  std::unique_ptr<SpyDigiConverter::DSVRawDigis> SpyDigiConverter::reorderDigis(const DSVRawDigis* inputPayloadDigis) {
    // Data is already sorted so push back fast into vector to avoid sorts and create DSV later
    std::vector<DetSetRawDigis> outputData;
    outputData.reserve(inputPayloadDigis->size());

    // Loop over channels in input collection
    for (DSVRawDigis::const_iterator inputChannel = inputPayloadDigis->begin();
         inputChannel != inputPayloadDigis->end();
         ++inputChannel) {
      const std::vector<SiStripRawDigi>& inputDetSetData = inputChannel->data;
      outputData.push_back(DetSetRawDigis(inputChannel->detId()));
      std::vector<SiStripRawDigi>& outputDetSetData = outputData.back().data;
      outputDetSetData.resize(STRIPS_PER_FEDCH);
      // Copy the data into the output vector reordering
      for (uint16_t readoutOrderStripIndex = 0; readoutOrderStripIndex < inputDetSetData.size();
           ++readoutOrderStripIndex) {
        const uint16_t physicalOrderStripIndex =
            FEDStripOrdering::physicalOrderForStripInChannel(readoutOrderStripIndex);
        outputDetSetData.at(physicalOrderStripIndex) = inputDetSetData.at(readoutOrderStripIndex);
      }
    }

    //return DSV of output
    return std::make_unique<DSVRawDigis>(outputData, true);
  }  // end of SpyDigiConverter::reorderDigis method.

  std::unique_ptr<SpyDigiConverter::DSVRawDigis> SpyDigiConverter::mergeModuleChannels(
      const DSVRawDigis* inputPhysicalOrderChannelDigis, const SiStripFedCabling& cabling) {
    // Create filler for detSetVector to create output (with maximum number of DetSets and digis)
    uint16_t nFeds = static_cast<uint16_t>(FED_ID_MAX - FED_ID_MIN + 1);

    RawDigiDetSetVectorFiller dsvFiller(nFeds * FEDCH_PER_FED / 2, nFeds * FEDCH_PER_FED * STRIPS_PER_FEDCH);
    // Loop over FEDs in cabling
    auto iFed = cabling.fedIds().begin();
    auto endFeds = cabling.fedIds().end();
    for (; iFed != endFeds; ++iFed) {
      // Loop over cabled channels
      auto conns = cabling.fedConnections(*iFed);
      auto iConn = conns.begin();
      auto endConns = conns.end();
      for (; iConn != endConns; ++iConn) {
        // Skip channels not connected to a detector.
        if (!iConn->isConnected())
          continue;
        if (iConn->detId() == sistrip::invalid32_)
          continue;

        // Find the data from the input collection
        const uint32_t fedIndex = ((iConn->fedId() & sistrip::invalid_) << 16) | (iConn->fedCh() & sistrip::invalid_);
        const DSVRawDigis::const_iterator iDetSet = inputPhysicalOrderChannelDigis->find(fedIndex);
        if (iDetSet == inputPhysicalOrderChannelDigis->end()) {
          // NOTE: It will display this warning if channel hasn't been unpacked...
          // Will comment out for now.
          //edm::LogWarning("SiStripSpyDigiConverter") << "No data found for FED ID: " << iConn->fedId() << " channel: " << iConn->fedCh();
          continue;
        }

        // Start a new channel indexed by the detId in the filler
        dsvFiller.newChannel(iConn->detId(), iConn->apvPairNumber() * STRIPS_PER_FEDCH);

        // Add the data
        DetSetRawDigis::const_iterator iDigi = iDetSet->begin();
        const DetSetRawDigis::const_iterator endDetSetDigis = iDetSet->end();
        for (; iDigi != endDetSetDigis; ++iDigi) {
          dsvFiller.addItem(*iDigi);
        }  // end of loop over the digis.
      }  // end of loop over channels.
    }  // end of loop over FEDs

    return dsvFiller.createDetSetVector();
  }  // end of SpyDigiConverter::mergeModuleChannels method.

}  // namespace sistrip