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 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
#include "EventFilter/EcalRawToDigi/interface/DCCSCBlock.h"
#include "EventFilter/EcalRawToDigi/interface/DCCEventBlock.h"
#include "EventFilter/EcalRawToDigi/interface/DCCDataUnpacker.h"
#include <cstdio>
#include "EventFilter/EcalRawToDigi/interface/EcalElectronicsMapper.h"

DCCSCBlock::DCCSCBlock(
    DCCDataUnpacker *u, EcalElectronicsMapper *m, DCCEventBlock *e, bool unpack, bool forceToKeepFRdata)
    : DCCFEBlock(u, m, e, unpack, forceToKeepFRdata) {}

void DCCSCBlock::updateCollectors() {
  DCCFEBlock::updateCollectors();

  // needs to be update for eb/ee
  digis_ = unpacker_->eeDigisCollection();

  invalidGains_ = unpacker_->invalidEEGainsCollection();
  invalidGainsSwitch_ = unpacker_->invalidEEGainsSwitchCollection();
  invalidChIds_ = unpacker_->invalidEEChIdsCollection();
}

int DCCSCBlock::unpackXtalData(unsigned int expStripID, unsigned int expXtalID) {
  bool errorOnXtal(false);

  const uint16_t *xData_ = reinterpret_cast<const uint16_t *>(data_);

  // Get xtal data ids
  unsigned int stripId = (*xData_) & TOWER_STRIPID_MASK;
  unsigned int xtalId = ((*xData_) >> TOWER_XTALID_B) & TOWER_XTALID_MASK;

  // std::cout<<"\n DEBUG : unpacked xtal data for strip id "<<stripId<<" and xtal id "<<xtalId<<std::endl;
  // std::cout<<"\n DEBUG : expected strip id "<<expStripID<<" expected xtal id "<<expXtalID<<std::endl;

  if (!zs_ && (expStripID != stripId || expXtalID != xtalId)) {
    if (!DCCDataUnpacker::silentMode_) {
      edm::LogWarning("IncorrectBlock") << "For event LV1: " << event_->l1A() << ", fed " << mapper_->getActiveDCC()
                                        << " and tower " << towerId_ << "\n The expected strip is " << expStripID
                                        << " and " << stripId << " was found"
                                        << "\n The expected xtal  is " << expXtalID << " and " << xtalId
                                        << " was found";
    }

    // using expected cry_di to raise warning about xtal_id problem
    pDetId_ = (EEDetId *)mapper_->getDetIdPointer(towerId_, expStripID, expXtalID);
    if (pDetId_) {
      (*invalidChIds_)->push_back(*pDetId_);
    }

    // return here, so to skip all following checks
    data_ += numbDWInXtalBlock_;
    return BLOCK_UNPACKED;
  }

  // check id in case of 0suppressed data

  else if (zs_) {
    // Check for valid Ids 1) values out of range

    if (stripId == 0 || stripId > 5 || xtalId == 0 || xtalId > 5) {
      if (!DCCDataUnpacker::silentMode_) {
        edm::LogWarning("IncorrectBlock")
            << "For event LV1: " << event_->l1A() << ", fed " << mapper_->getActiveDCC() << " and tower " << towerId_
            << "\n Invalid strip : " << stripId << " or xtal : " << xtalId << " ids ( last strip was: " << lastStripId_
            << " last ch was: " << lastXtalId_ << ")";
      }

      int st = lastStripId_;
      int ch = lastXtalId_;
      ch++;
      if (ch > NUMB_XTAL) {
        ch = 1;
        st++;
      }
      if (st > NUMB_STRIP) {
        ch = 1;
        st = 1;
      }

      // adding channel following the last valid
      //pDetId_ = (EEDetId*) mapper_->getDetIdPointer(towerId_,st,ch);
      //(*invalidChIds_)->push_back(*pDetId_);
      fillEcalElectronicsError(invalidZSXtalIds_);

      lastStripId_ = st;
      lastXtalId_ = ch;

      // return here, so to skip all following checks
      return SKIP_BLOCK_UNPACKING;
    } else {
      // Check for zs valid Ids 2) if channel-in-strip has increased wrt previous xtal
      //                        3) if strip has increased wrt previous xtal
      if ((stripId == lastStripId_ && xtalId <= lastXtalId_) || (stripId < lastStripId_)) {
        if (!DCCDataUnpacker::silentMode_) {
          edm::LogWarning("IncorrectBlock")
              << "Xtal id was expected to increase but it didn't - last xtal id was " << lastXtalId_
              << " while current xtal is " << xtalId << " (LV1 " << event_->l1A() << " fed " << mapper_->getActiveDCC()
              << " tower " << towerId_ << ")";
        }

        int st = lastStripId_;
        int ch = lastXtalId_;
        ch++;
        if (ch > NUMB_XTAL) {
          ch = 1;
          st++;
        }
        if (st > NUMB_STRIP) {
          ch = 1;
          st = 1;
        }

        // adding channel following the last valid
        //pDetId_ = (EEDetId*) mapper_->getDetIdPointer(towerId_,stripId,xtalId);
        //(*invalidChIds_)->push_back(*pDetId_);
        fillEcalElectronicsError(invalidZSXtalIds_);

        lastStripId_ = st;
        lastXtalId_ = ch;

        // return here, so to skip all following checks
        return SKIP_BLOCK_UNPACKING;
      }

      lastStripId_ = stripId;
      lastXtalId_ = xtalId;
    }  // end else
  }  // end if(zs_)

  bool addedFrame = false;

  // if there is an error on xtal id ignore next error checks
  // otherwise, assume channel_id is valid and proceed with making and checking the data frame
  if (errorOnXtal)
    return SKIP_BLOCK_UNPACKING;

  pDetId_ = (EEDetId *)mapper_->getDetIdPointer(towerId_, stripId, xtalId);

  if (pDetId_) {  // checking that requested EEDetId exists

    (*digis_)->push_back(*pDetId_);
    EEDataFrame df((*digis_)->back());
    addedFrame = true;
    bool wrongGain(false);

    //set samples in the frame
    for (unsigned int i = 0; i < nTSamples_; i++) {
      xData_++;
      unsigned int data = (*xData_) & TOWER_DIGI_MASK;
      unsigned int gain = data >> 12;
      xtalGains_[i] = gain;
      if (gain == 0) {
        wrongGain = true;
      }  // although gain==0 found, produce the dataFrame in order to have it, for saturation case
      df.setSample(i, data);
    }

    bool isSaturation(true);
    if (wrongGain) {
      // check whether the gain==0 has features of saturation or not
      // gain==0 occurs either in case of data corruption or of ADC saturation
      //                                  \->reject digi            \-> keep digi

      // determine where gainId==0 starts
      short firstGainZeroSampID(-1);
      short firstGainZeroSampADC(-1);
      for (unsigned int s = 0; s < nTSamples_; s++) {
        if (df.sample(s).gainId() == 0 && firstGainZeroSampID == -1) {
          firstGainZeroSampID = s;
          firstGainZeroSampADC = df.sample(s).adc();
          break;
        }
      }

      // check whether gain==0 and adc() stays constant for (at least) 5 consecutive samples
      unsigned int plateauEnd = std::min(nTSamples_, (unsigned int)(firstGainZeroSampID + 5));
      for (unsigned int s = firstGainZeroSampID; s < plateauEnd; s++) {
        if (df.sample(s).gainId() == 0 && df.sample(s).adc() == firstGainZeroSampADC) {
          ;
        } else {
          isSaturation = false;
          break;
        }  //it's not saturation
      }
      // get rid of channels which are stuck in gain0
      if (firstGainZeroSampID < 3) {
        isSaturation = false;
      }

      if (!DCCDataUnpacker::silentMode_) {
        if (unpacker_->getChannelValue(mapper_->getActiveDCC(), towerId_, stripId, xtalId) != 10) {
          edm::LogWarning("IncorrectGain")
              << "Gain zero" << (isSaturation ? " with features of saturation" : "") << " was found in SC Block"
              << " (L1A " << event_->l1A() << " bx " << event_->bx() << " fed " << mapper_->getActiveDCC() << " tower "
              << towerId_ << " strip " << stripId << " xtal " << xtalId << ")";
        }
      }

      if (!isSaturation) {
        (*invalidGains_)->push_back(*pDetId_);
        (*digis_)->pop_back();

        //return here, so to skip all the rest
        //make special collection for gain0 data frames (saturation)
        //Point to begin of next xtal Block
        data_ += numbDWInXtalBlock_;

        return BLOCK_UNPACKED;

      }  //end isSaturation
      else {
        data_ += numbDWInXtalBlock_;
        return BLOCK_UNPACKED;
      }
    }  //end WrongGain

    short firstGainWrong = -1;
    short numGainWrong = 0;

    for (unsigned int i = 1; i < nTSamples_; i++) {
      if (xtalGains_[i - 1] > xtalGains_[i]) {
        numGainWrong++;

        if (firstGainWrong == -1) {
          firstGainWrong = i;
        }
      }
    }

    if (numGainWrong > 0) {
      if (!DCCDataUnpacker::silentMode_) {
        edm::LogWarning("IncorrectGain") << "A wrong gain transition switch was found for SC Block in strip " << stripId
                                         << " and xtal " << xtalId << " (L1A " << event_->l1A() << " bx "
                                         << event_->bx() << " fed " << mapper_->getActiveDCC() << " tower " << towerId_
                                         << ")";
      }

      (*invalidGainsSwitch_)->push_back(*pDetId_);

      errorOnXtal = true;
    }

    //Add frame to collection only if all data format and gain rules are respected
    if (errorOnXtal && addedFrame) {
      (*digis_)->pop_back();
    }

  }  // End 'if EE id exist'

  else {
    // in case EEDetId do not exist
    // In EE we may have crystals with no valid EEDetId
    if (!mapper_->isGhost(mapper_->getActiveDCC(), towerId_, stripId)) {  // check the VFE is not a 'ghost'

      // this is real EE VFE - print warning
      if (!DCCDataUnpacker::silentMode_) {
        edm::LogWarning("IncorrectBlock") << "An EEDetId was requested that does not exist "
                                          << "(LV1 " << event_->l1A() << " fed " << mapper_->getActiveDCC() << " tower "
                                          << towerId_ << " strip " << stripId << " xtal " << xtalId << ")";
      }
    }
  }

  //Point to begin of next xtal Block
  data_ += numbDWInXtalBlock_;

  return BLOCK_UNPACKED;
}

void DCCSCBlock::fillEcalElectronicsError(std::unique_ptr<EcalElectronicsIdCollection> *errorColection) {
  const int activeDCC = mapper_->getActiveSM();

  if ((NUMB_SM_EE_MIN_MIN <= activeDCC && activeDCC <= NUMB_SM_EE_MIN_MAX) ||
      (NUMB_SM_EE_PLU_MIN <= activeDCC && activeDCC <= NUMB_SM_EE_PLU_MAX)) {
    EcalElectronicsId *eleTp = mapper_->getSCElectronicsPointer(activeDCC, expTowerID_);
    (*errorColection)->push_back(*eleTp);
  } else {
    if (!DCCDataUnpacker::silentMode_) {
      edm::LogWarning("IncorrectBlock") << "For event " << event_->l1A() << " there's fed: " << activeDCC
                                        << " activeDcc: " << mapper_->getActiveSM()
                                        << " but that activeDcc is not valid in EE.";
    }
  }
}