Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-04-07 05:50:22

0001 #include "EventFilter/CSCRawToDigi/interface/CSCEventData.h"
0002 #include "EventFilter/CSCRawToDigi/interface/CSCCFEBData.h"
0003 #include "EventFilter/CSCRawToDigi/interface/cscPackerCompare.h"
0004 #include "EventFilter/CSCRawToDigi/interface/bitset_append.h"
0005 #include "DataFormats/CSCDigi/interface/CSCStripDigi.h"
0006 #include "DataFormats/CSCDigi/interface/CSCConstants.h"
0007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0008 #include "FWCore/Utilities/interface/Exception.h"
0009 #include <iostream>
0010 #include <iterator>
0011 
0012 #ifdef LOCAL_UNPACK
0013 bool CSCEventData::debug = false;
0014 #else
0015 std::atomic<bool> CSCEventData::debug{false};
0016 #endif
0017 
0018 CSCEventData::CSCEventData(int chamberType, uint16_t format_version)
0019     : theDMBHeader(format_version),
0020       theALCTHeader(nullptr),
0021       theAnodeData(nullptr),
0022       theALCTTrailer(nullptr),
0023       theTMBData(nullptr),
0024       theDMBTrailer(format_version),
0025       theChamberType(chamberType),
0026       alctZSErecovered(nullptr),
0027       zseEnable(0),
0028       theFormatVersion(format_version) {
0029   for (unsigned i = 0; i < CSCConstants::MAX_CFEBS_RUN2; ++i) {
0030     theCFEBData[i] = nullptr;
0031   }
0032 }
0033 
0034 CSCEventData::CSCEventData(const uint16_t* buf, uint16_t format_version) : theFormatVersion(format_version) {
0035   theFormatVersion = format_version;
0036   unpack_data(buf);
0037 }
0038 
0039 void CSCEventData::unpack_data(const uint16_t* buf) {
0040   // zero everything
0041   init();
0042   const uint16_t* pos = buf;
0043   if (debug) {
0044     LogTrace("CSCEventData|CSCRawToDigi") << "The event data ";
0045     for (int i = 0; i < 16; ++i) {
0046       LogTrace("CSCEventData|CSCRawToDigi") << std::hex << pos[i] << " ";
0047     }
0048   }
0049 
0050   theDMBHeader = CSCDMBHeader(pos, theFormatVersion);
0051   if (!(theDMBHeader.check())) {
0052     LogTrace("CSCEventData|CSCRawToDigi") << "Bad DMB Header??? "
0053                                           << " first four words: ";
0054     for (int i = 0; i < 4; ++i) {
0055       LogTrace("CSCEventData|CSCRawToDigi") << std::hex << pos[i] << " ";
0056     }
0057   }
0058 
0059   if (debug) {
0060     LogTrace("CSCEventData|CSCRawToDigi") << "nalct = " << nalct();
0061     LogTrace("CSCEventData|CSCRawToDigi") << "nclct = " << nclct();
0062   }
0063 
0064   if (debug) {
0065     LogTrace("CSCEventData|CSCRawToDigi") << "size in words of DMBHeader" << theDMBHeader.sizeInWords();
0066     LogTrace("CSCEventData|CSCRawToDigi") << "sizeof(DMBHeader)" << sizeof(theDMBHeader);
0067   }
0068 
0069   pos += theDMBHeader.sizeInWords();
0070 
0071   if (nalct() == 1) {
0072     if (isALCT(pos))  //checking for ALCTData
0073     {
0074       theALCTHeader = new CSCALCTHeader(pos);
0075       if (!theALCTHeader->check()) {
0076         LogTrace("CSCEventData|CSCRawToDigi") << "+++WARNING: Corrupt ALCT data - won't attempt to decode";
0077       } else {
0078         //dataPresent|=0x40;
0079         pos += theALCTHeader->sizeInWords();  //size of the header
0080         //fill ALCT Digis
0081         theALCTHeader->ALCTDigis();
0082 
0083         //theAnodeData = new CSCAnodeData(*theALCTHeader, pos);
0084 
0085         /// The size of the ALCT payload is determined here
0086         /*
0087               std::cout << " ****The ALCT information from CSCEventData.cc (begin)**** " << std::endl; ///to_rm
0088               std::cout << " alctHeader2007().size: " << theALCTHeader->alctHeader2007().sizeInWords() << std::endl; ///to_rm
0089               std::cout << " ALCT Header Content: " << std::endl; ///to_rm
0090               /// to_rm (6 lines)
0091               for(int k=0; k<theALCTHeader->sizeInWords(); k+=4){
0092                  std::cout << std::hex << theALCTHeader->data()[k+3]
0093                            << " " << theALCTHeader->data()[k+2]
0094                            << " " << theALCTHeader->data()[k+1]
0095                            << " " << theALCTHeader->data()[k] << std::dec << std::endl;
0096                  }
0097                */
0098         //std::cout << " ALCT Size: " << theAnodeData->sizeInWords() << std::endl;
0099         /// Check if Zero Suppression ALCT Enabled
0100         // int zseEnable = 0;
0101         zseEnable = (theALCTHeader->data()[5] & 0x1000) >> 12;
0102         //std::cout << " ZSE Bit: " <<  zseEnable << std::endl; /// to_rm
0103         int sizeInWord_ZSE = 0;
0104 
0105         //alctZSErecovered = new unsigned short [theAnodeData->sizeInWords()];
0106 
0107         if (zseEnable) {
0108           /// Aauxilary variables neede to recover zero suppression
0109           /// Calculate the number of wire groups per layer
0110           int nWGs_per_layer = ((theALCTHeader->data()[6] & 0x0007) + 1) * 16;
0111           /// Calculate the number of words in the layer
0112           int nWG_round_up = int(nWGs_per_layer / 12) + (nWGs_per_layer % 3 ? 1 : 0);
0113           //std::cout << " Words per layer: " << nWG_round_up << std::endl; ///to_rm
0114           const uint16_t* posZSE = pos;
0115           std::vector<unsigned short> alctZSErecoveredVector;
0116           alctZSErecoveredVector.clear();
0117 
0118           //alctZSErecovered = new unsigned short [theAnodeData->sizeInWords()];
0119           //delete [] alctZSErecovered;
0120           //std::cout << " ALCT Buffer with ZSE: " << std::endl; ///to_rm
0121           /// unsigned short * posZSEtmpALCT = pos;
0122           /// This is just to dump the actual ALCT payload ** begin **
0123           /// For debuggin purposes
0124           //unsigned short * posZSEdebug = pos; ///to_rm
0125 
0126           /// to_rm (8 lines)
0127           /*
0128                   while (*posZSEdebug != 0xDE0D){
0129                         unsigned short d = *posZSEdebug;
0130                         unsigned short c = *(posZSEdebug+1);
0131                         unsigned short b = *(posZSEdebug+2);
0132                         unsigned short a = *(posZSEdebug+3);
0133                         posZSEdebug+=4;
0134                         std::cout << std::hex << a << " " << b << " " << c << " " << d << std::dec << std::endl;
0135                   }
0136                   */
0137           /// This is just to dump the actual ALCT payload ** end **
0138 
0139           /// Actual word counting and recovering the original ALCT payload
0140           int alctZSErecoveredPos = 0;
0141           while (*posZSE != 0xDE0D) {
0142             if ((*posZSE == 0x1000) && (*posZSE != 0x3000)) {
0143               for (int j = 0; j < nWG_round_up; j++) {
0144                 alctZSErecoveredVector.push_back(0x0000);
0145               }
0146               alctZSErecoveredPos += nWG_round_up;
0147             } else {
0148               alctZSErecoveredVector.push_back(*posZSE);
0149               ++alctZSErecoveredPos;
0150             }
0151             posZSE++;
0152             sizeInWord_ZSE++;
0153           }
0154 
0155           alctZSErecovered = new unsigned short[alctZSErecoveredVector.size()];
0156 
0157           /// Convert the recovered vector into the array
0158           for (int l = 0; l < (int)alctZSErecoveredVector.size(); l++) {
0159             alctZSErecovered[l] = alctZSErecoveredVector[l];
0160           }
0161 
0162           unsigned short* posRecovered = alctZSErecovered;
0163           theAnodeData = new CSCAnodeData(*theALCTHeader, posRecovered);
0164 
0165           /// This is to check the content of the recovered ALCT payload
0166           /// to_rm (7 lines)
0167           /*
0168                   std::cout << " The ALCT payload recovered: " << std::endl;
0169                   for(int k=0; k<theAnodeData->sizeInWords(); k+=4){
0170                      std::cout << std::hex << alctZSErecovered[k+3] << " "
0171                                            << alctZSErecovered[k+2] << " "
0172                                            << alctZSErecovered[k+1] << " "
0173                                            << alctZSErecovered[k] << std::dec << std::endl;
0174                   }
0175                   */
0176           //delete [] alctZSErecovered;
0177           //std::cout << " ALCT SizeZSE : " << sizeInWord_ZSE << std::endl; ///to_rm
0178           //std::cout << " ALCT SizeZSE Recovered: " << alctZSErecoveredPos << std::endl; ///to_rm
0179           //std::cout << " ALCT Size Expected: " << theAnodeData->sizeInWords() << std::endl; ///to_rm
0180           pos += sizeInWord_ZSE;
0181         } else {
0182           //pos +=sizeInWord_ZSE;
0183           theAnodeData = new CSCAnodeData(*theALCTHeader, pos);
0184           pos += theAnodeData->sizeInWords();  // size of the data is determined during unpacking
0185         }
0186         //std::cout << " ****The ALCT information from CSCEventData.cc (end)**** " << std::endl; ///to_rm
0187         theALCTTrailer = new CSCALCTTrailer(pos);
0188         pos += theALCTTrailer->sizeInWords();
0189       }
0190     } else {
0191       LogTrace("CSCEventData|CSCRawToDigi") << "Error:nalct reported but no ALCT data found!!!";
0192     }
0193   }
0194 
0195   if (nclct() == 1) {
0196     if (isTMB(pos)) {
0197       //dataPresent|=0x20;
0198       theTMBData = new CSCTMBData(pos);  //fill all TMB data
0199       pos += theTMBData->size();
0200     } else {
0201       LogTrace("CSCEventData|CSCRawToDigi") << "Error:nclct reported but no TMB data found!!!";
0202     }
0203   }
0204 
0205   //now let's try to find and unpack the DMBTrailer
0206   bool dmbTrailerReached = false;
0207   for (int i = 0; i < 12000; ++i)  //8000 max for cfeb + 1980ALCT + 287 TMB
0208   {
0209     dmbTrailerReached = (*(i + pos) & 0xF000) == 0xF000 && (*(i + pos + 1) & 0xF000) == 0xF000 &&
0210                         (*(i + pos + 2) & 0xF000) == 0xF000 && (*(i + pos + 3) & 0xF000) == 0xF000 &&
0211                         (*(i + pos + 4) & 0xF000) == 0xE000 && (*(i + pos + 5) & 0xF000) == 0xE000 &&
0212                         (*(i + pos + 6) & 0xF000) == 0xE000 && (*(i + pos + 7) & 0xF000) == 0xE000;
0213     if (dmbTrailerReached) {
0214       // theDMBTrailer = *( (CSCDMBTrailer *) (pos+i) );
0215       theDMBTrailer = CSCDMBTrailer(pos + i, theFormatVersion);
0216       break;
0217     }
0218   }
0219   if (dmbTrailerReached) {
0220     for (int icfeb = 0; icfeb < CSCConstants::MAX_CFEBS_RUN2; ++icfeb) {
0221       theCFEBData[icfeb] = nullptr;
0222       int cfeb_available = theDMBHeader.cfebAvailable(icfeb);
0223       unsigned int cfebTimeout = theDMBTrailer.cfeb_starttimeout() | theDMBTrailer.cfeb_endtimeout();
0224       //cfeb_available cannot be trusted - need additional verification!
0225       if (cfeb_available == 1) {
0226         if ((cfebTimeout >> icfeb) & 1) {
0227           if (debug)
0228             LogTrace("CSCEventData|CSCRawToDigi") << "CFEB Timed out! ";
0229         } else {
0230           //dataPresent|=(0x1>>icfeb);
0231           // Fill CFEB data and convert it into cathode digis
0232 
0233           // Check if we have here DCFEB  using DMB format version field (new ME11 with DCFEBs - 0x2, other chamber types 0x1)
0234           bool isDCFEB = false;
0235           if (theDMBHeader.format_version() == 2)
0236             isDCFEB = true;
0237 
0238           theCFEBData[icfeb] = new CSCCFEBData(icfeb, pos, theFormatVersion, isDCFEB);
0239           pos += theCFEBData[icfeb]->sizeInWords();
0240         }
0241       }
0242     }
0243     pos += theDMBTrailer.sizeInWords();
0244     size_ = pos - buf;
0245   } else {
0246     LogTrace("CSCEventData|CSCRawToDigi") << "Critical Error: DMB Trailer was not found!!! ";
0247   }
0248 
0249   // std::cout << "CSC format: " << theFormatVersion << " " << getFormatVersion() << std::endl;
0250 }
0251 
0252 bool CSCEventData::isALCT(const short unsigned int* buf) {
0253   return (((buf[0] & 0xFFFF) == 0xDB0A) || (((buf[0] & 0xF800) == 0x6000) && ((buf[1] & 0xF800) == 0)));
0254 }
0255 
0256 bool CSCEventData::isTMB(const short unsigned int* buf) { return ((buf[0] & 0xFFF) == 0xB0C); }
0257 
0258 CSCEventData::CSCEventData(const CSCEventData& data) { copy(data); }
0259 
0260 CSCEventData::~CSCEventData() { destroy(); }
0261 
0262 CSCEventData CSCEventData::operator=(const CSCEventData& data) {
0263   // check for self-assignment before destructing
0264   if (&data != this)
0265     destroy();
0266   copy(data);
0267   return *this;
0268 }
0269 
0270 void CSCEventData::init() {
0271   //dataPresent = 0;
0272   theALCTHeader = nullptr;
0273   theAnodeData = nullptr;
0274   theALCTTrailer = nullptr;
0275   theTMBData = nullptr;
0276   for (int icfeb = 0; icfeb < CSCConstants::MAX_CFEBS_RUN2; ++icfeb) {
0277     theCFEBData[icfeb] = nullptr;
0278   }
0279   alctZSErecovered = nullptr;
0280   zseEnable = 0;
0281 }
0282 
0283 void CSCEventData::copy(const CSCEventData& data) {
0284   init();
0285   theFormatVersion = data.theFormatVersion;
0286   theDMBHeader = data.theDMBHeader;
0287   theDMBTrailer = data.theDMBTrailer;
0288   if (data.theALCTHeader != nullptr)
0289     theALCTHeader = new CSCALCTHeader(*(data.theALCTHeader));
0290   if (data.theAnodeData != nullptr)
0291     theAnodeData = new CSCAnodeData(*(data.theAnodeData));
0292   if (data.theALCTTrailer != nullptr)
0293     theALCTTrailer = new CSCALCTTrailer(*(data.theALCTTrailer));
0294   if (data.theTMBData != nullptr)
0295     theTMBData = new CSCTMBData(*(data.theTMBData));
0296   for (int icfeb = 0; icfeb < CSCConstants::MAX_CFEBS_RUN2; ++icfeb) {
0297     theCFEBData[icfeb] = nullptr;
0298     if (data.theCFEBData[icfeb] != nullptr)
0299       theCFEBData[icfeb] = new CSCCFEBData(*(data.theCFEBData[icfeb]));
0300   }
0301   size_ = data.size_;
0302   theChamberType = data.theChamberType;
0303 }
0304 
0305 void CSCEventData::destroy() {
0306   if (zseEnable) {
0307     delete[] alctZSErecovered;
0308   }
0309   delete theALCTHeader;
0310   delete theAnodeData;
0311   delete theALCTTrailer;
0312   delete theTMBData;
0313   for (int icfeb = 0; icfeb < CSCConstants::MAX_CFEBS_RUN2; ++icfeb) {
0314     delete theCFEBData[icfeb];
0315   }
0316   /*
0317     std::cout << "Before delete alctZSErecovered " << std::endl;
0318     delete [] alctZSErecovered;
0319     std::cout << "After delete alctZSErecovered " << std::endl;
0320   */
0321 }
0322 
0323 std::vector<CSCStripDigi> CSCEventData::stripDigis(const CSCDetId& idlayer) const {
0324   std::vector<CSCStripDigi> result;
0325   for (unsigned icfeb = 0; icfeb < CSCConstants::MAX_CFEBS_RUN2; ++icfeb) {
0326     std::vector<CSCStripDigi> newDigis = stripDigis(idlayer, icfeb);
0327     result.insert(result.end(), newDigis.begin(), newDigis.end());
0328   }
0329   return result;
0330 }
0331 
0332 std::vector<CSCStripDigi> CSCEventData::stripDigis(unsigned idlayer, unsigned icfeb) const {
0333   std::vector<CSCStripDigi> result;
0334   if (theCFEBData[icfeb] != nullptr) {
0335     std::vector<CSCStripDigi> newDigis = theCFEBData[icfeb]->digis(idlayer);
0336     result.insert(result.end(), newDigis.begin(), newDigis.end());
0337   }
0338 
0339   return result;
0340 }
0341 
0342 std::vector<CSCWireDigi> CSCEventData::wireDigis(unsigned ilayer) const {
0343   if (theAnodeData == nullptr) {
0344     return std::vector<CSCWireDigi>();
0345   } else {
0346     return theAnodeData->wireDigis(ilayer);
0347   }
0348 }
0349 
0350 std::vector<std::vector<CSCStripDigi> > CSCEventData::stripDigis() const {
0351   std::vector<std::vector<CSCStripDigi> > result;
0352   for (int layer = CSCDetId::minLayerId(); layer <= CSCDetId::maxLayerId(); ++layer) {
0353     std::vector<CSCStripDigi> digis = stripDigis(layer);
0354     result.push_back(digis);
0355   }
0356   return result;
0357 }
0358 
0359 std::vector<std::vector<CSCWireDigi> > CSCEventData::wireDigis() const {
0360   std::vector<std::vector<CSCWireDigi> > result;
0361   for (int layer = CSCDetId::minLayerId(); layer <= CSCDetId::maxLayerId(); ++layer) {
0362     result.push_back(wireDigis(layer));
0363   }
0364   return result;
0365 }
0366 
0367 const CSCCFEBData* CSCEventData::cfebData(unsigned icfeb) const { return theCFEBData[icfeb]; }
0368 
0369 CSCALCTHeader* CSCEventData::alctHeader() const {
0370   if (nalct() == 0)
0371     throw cms::Exception("No ALCT for this chamber");
0372   return theALCTHeader;
0373 }
0374 
0375 CSCALCTTrailer* CSCEventData::alctTrailer() const {
0376   if (nalct() == 0)
0377     throw cms::Exception("No ALCT for this chamber");
0378   return theALCTTrailer;
0379 }
0380 
0381 CSCAnodeData* CSCEventData::alctData() const {
0382   if (nalct() == 0)
0383     throw cms::Exception("No ALCT for this chamber");
0384   return theAnodeData;
0385 }
0386 
0387 CSCTMBData* CSCEventData::tmbData() const {
0388   if (nclct() == 0)
0389     throw cms::Exception("No CLCT for this chamber");
0390   return theTMBData;
0391 }
0392 
0393 CSCTMBHeader* CSCEventData::tmbHeader() const {
0394   if ((nclct() == 0) || (tmbData() == nullptr))
0395     throw cms::Exception("No CLCT header for this chamber");
0396   return tmbData()->tmbHeader();
0397 }
0398 
0399 CSCComparatorData* CSCEventData::comparatorData() const {
0400   if ((nclct() == 0) || (tmbData() == nullptr))
0401     throw cms::Exception("No CLCT data for this chamber");
0402   return tmbData()->comparatorData();
0403 }
0404 
0405 void CSCEventData::setEventInformation(int bxnum, int lvl1num) {
0406   theDMBHeader.setBXN(bxnum);
0407   theDMBHeader.setL1A(lvl1num);
0408   theDMBHeader.setL1A24(lvl1num);
0409   if (theALCTHeader) {
0410     theALCTHeader->setEventInformation(theDMBHeader);
0411   }
0412   if (theTMBData) {
0413     theTMBData->tmbHeader()->setEventInformation(theDMBHeader);
0414 
0415     assert(theChamberType > 0);
0416 
0417     theTMBData->tmbHeader()->setNCFEBs(CSCConstants::MAX_CFEBS_RUN1);
0418 
0419     // Set number of CFEBs to 7 for Post-LS1 ME11
0420     if ((theFormatVersion >= 2013) && ((theChamberType == 1) || (theChamberType == 2))) {
0421       theTMBData->tmbHeader()->setNCFEBs(CSCConstants::MAX_CFEBS_RUN2);
0422     }
0423   }
0424   for (unsigned cfeb = 0; cfeb < CSCConstants::MAX_CFEBS_RUN2; cfeb++) {
0425     if (theCFEBData[cfeb])
0426       theCFEBData[cfeb]->setL1A(lvl1num);
0427   }
0428 }
0429 
0430 void CSCEventData::checkALCTClasses() {
0431   if (theAnodeData == nullptr) {
0432     assert(theChamberType > 0);
0433     theALCTHeader = new CSCALCTHeader(theChamberType);
0434     theALCTHeader->setEventInformation(theDMBHeader);
0435     theAnodeData = new CSCAnodeData(*theALCTHeader);
0436     int size = theALCTHeader->sizeInWords() + theAnodeData->sizeInWords() + CSCALCTTrailer::sizeInWords();
0437     theALCTTrailer = new CSCALCTTrailer(size, theALCTHeader->alctFirmwareVersion());
0438     // set data available flag
0439     theDMBHeader.addNALCT();
0440   }
0441 }
0442 
0443 void CSCEventData::checkTMBClasses() {
0444   int nCFEBs = CSCConstants::MAX_CFEBS_RUN1;
0445   if ((theFormatVersion >= 2013) && ((theChamberType == 1) || (theChamberType == 2))) {
0446     nCFEBs = CSCConstants::MAX_CFEBS_RUN2;
0447   }
0448   if (theTMBData == nullptr) {
0449     if (theFormatVersion == 2013) {  // Set to TMB format for Post-LS1/Run2 data
0450       theTMBData = new CSCTMBData(2013, 0x7a76, nCFEBs);
0451     } else if (theFormatVersion == 2020) {  // Set to TMB format for Run3 data
0452       if ((theChamberType == 1) || (theChamberType == 2)) {
0453         theTMBData = new CSCTMBData(2020, 0x602, nCFEBs);  // ME11 GEM fw
0454       } else {
0455         theTMBData = new CSCTMBData(2020, 0x403);  // MEx1 CCLUT fw
0456       }
0457     } else {
0458       theTMBData = new CSCTMBData(2007, 0x50c3);
0459     }
0460     theTMBData->tmbHeader()->setEventInformation(theDMBHeader);
0461     theDMBHeader.addNCLCT();
0462   }
0463   theTMBData->tmbHeader()->setNCFEBs(nCFEBs);
0464 }
0465 
0466 void CSCEventData::add(const CSCStripDigi& digi, int layer) {
0467   //@@ need special logic here for ME11
0468   unsigned cfeb = digi.getCFEB();
0469   bool sixteenSamples = false;
0470   if (digi.getADCCounts().size() == 16)
0471     sixteenSamples = true;
0472   if (theCFEBData[cfeb] == nullptr) {
0473     bool isDCFEB = false;
0474     if (theDMBHeader.format_version() == 2)
0475       isDCFEB = true;
0476     theCFEBData[cfeb] = new CSCCFEBData(cfeb, sixteenSamples, theFormatVersion, isDCFEB);
0477     theDMBHeader.addCFEB(cfeb);
0478   }
0479   theCFEBData[cfeb]->add(digi, layer);
0480 }
0481 
0482 void CSCEventData::add(const CSCWireDigi& digi, int layer) {
0483   checkALCTClasses();
0484   theAnodeData->add(digi, layer);
0485   theALCTHeader->setDAVForChannel(digi.getWireGroup());
0486   theALCTHeader->setBXNCount(digi.getWireGroupBX());
0487 }
0488 
0489 void CSCEventData::add(const CSCComparatorDigi& digi, int layer) {
0490   checkTMBClasses();
0491   theTMBData->comparatorData()->add(digi, layer);
0492 }
0493 
0494 void CSCEventData::add(const CSCComparatorDigi& digi, const CSCDetId& cid) {
0495   checkTMBClasses();
0496   theTMBData->comparatorData()->add(digi, cid);
0497 }
0498 
0499 void CSCEventData::add(const std::vector<CSCALCTDigi>& digis) {
0500   checkALCTClasses();
0501   theALCTHeader->add(digis);
0502 }
0503 
0504 void CSCEventData::add(const std::vector<CSCCLCTDigi>& digis) {
0505   checkTMBClasses();
0506   theTMBData->tmbHeader()->add(digis);
0507 }
0508 
0509 void CSCEventData::add(const std::vector<CSCCorrelatedLCTDigi>& digis) {
0510   checkTMBClasses();
0511   theTMBData->tmbHeader()->add(digis);
0512 }
0513 
0514 /// Add/pack LCT CSCShower object
0515 void CSCEventData::addShower(const std::vector<CSCShowerDigi>& digis) {
0516   checkTMBClasses();
0517   for (auto it : digis) {
0518     theTMBData->tmbHeader()->addShower(it);
0519   }
0520 }
0521 
0522 /// Add/pack anode CSCShower object (from OTMB header)
0523 void CSCEventData::addAnodeShower(const std::vector<CSCShowerDigi>& digis) {
0524   checkTMBClasses();
0525   for (auto it : digis) {
0526     theTMBData->tmbHeader()->addAnodeShower(it);
0527   }
0528 }
0529 
0530 /// Add/pack cathode CSCShower object (from OTMB header)
0531 void CSCEventData::addCathodeShower(const std::vector<CSCShowerDigi>& digis) {
0532   checkTMBClasses();
0533   for (auto it : digis) {
0534     theTMBData->tmbHeader()->addCathodeShower(it);
0535   }
0536 }
0537 
0538 /// Add/pack anode CSCShower objects (from ALCT board data)
0539 void CSCEventData::addAnodeALCTShower(const std::vector<CSCShowerDigi>& digis) {
0540   checkALCTClasses();
0541   theALCTHeader->addShower(digis);
0542 }
0543 
0544 /// Add/pack GE11 GEM Pad Clusters trigger objects received by OTMB from GEM
0545 void CSCEventData::add(const std::vector<GEMPadDigiCluster>& clusters, const GEMDetId& gemdetid) {
0546   checkTMBClasses();
0547   if (theTMBData->hasGEM()) {
0548     int gem_layer = gemdetid.layer();
0549     int eta_roll = gemdetid.roll();
0550     for (const auto& it : clusters) {
0551       theTMBData->gemData()->addEtaPadCluster(it, gem_layer - 1, 8 - eta_roll);
0552     }
0553   }
0554 }
0555 
0556 std::ostream& operator<<(std::ostream& os, const CSCEventData& evt) {
0557   for (int ilayer = CSCDetId::minLayerId(); ilayer <= CSCDetId::maxLayerId(); ++ilayer) {
0558     std::vector<CSCStripDigi> stripDigis = evt.stripDigis(ilayer);
0559     //copy(stripDigis.begin(), stripDigis.end(), std::ostream_iterator<CSCStripDigi>(os, "\n"));
0560     //print your scas here
0561     std::vector<CSCWireDigi> wireDigis = evt.wireDigis(ilayer);
0562     //copy(wireDigis.begin(), wireDigis.end(), std::ostream_iterator<CSCWireDigi>(os, "\n"));
0563   }
0564   return os;
0565 }
0566 
0567 boost::dynamic_bitset<> CSCEventData::pack() {
0568   boost::dynamic_bitset<> result =
0569       bitset_utilities::ushortToBitset(theDMBHeader.sizeInWords() * 16, theDMBHeader.data());
0570 
0571   // Container for CRC calculations
0572   std::vector<std::pair<unsigned int, unsigned short*> > crcvec;
0573 
0574   if (theALCTHeader != nullptr) {
0575     boost::dynamic_bitset<> alctHeader = theALCTHeader->pack();
0576     result = bitset_utilities::append(result, alctHeader);
0577     crcvec.push_back(std::make_pair(theALCTHeader->sizeInWords(), theALCTHeader->data()));
0578   }
0579   if (theAnodeData != nullptr) {
0580     boost::dynamic_bitset<> anodeData =
0581         bitset_utilities::ushortToBitset(theAnodeData->sizeInWords() * 16, theAnodeData->data());
0582     result = bitset_utilities::append(result, anodeData);
0583     crcvec.push_back(std::make_pair(theAnodeData->sizeInWords(), theAnodeData->data()));
0584   }
0585   if (theALCTTrailer != nullptr) {
0586     unsigned int crc = calcALCTcrc(crcvec);
0587     theALCTTrailer->setCRC(crc);
0588     boost::dynamic_bitset<> alctTrailer =
0589         bitset_utilities::ushortToBitset(theALCTTrailer->sizeInWords() * 16, theALCTTrailer->data());
0590     result = bitset_utilities::append(result, alctTrailer);
0591   }
0592   if (theTMBData != nullptr) {
0593     result = bitset_utilities::append(result, theTMBData->pack());
0594   }
0595 
0596   for (int icfeb = 0; icfeb < CSCConstants::MAX_CFEBS_RUN2; ++icfeb) {
0597     if (theCFEBData[icfeb] != nullptr) {
0598       boost::dynamic_bitset<> cfebData =
0599           bitset_utilities::ushortToBitset(theCFEBData[icfeb]->sizeInWords() * 16, theCFEBData[icfeb]->data());
0600       result = bitset_utilities::append(result, cfebData);
0601     }
0602   }
0603 
0604   boost::dynamic_bitset<> dmbTrailer =
0605       bitset_utilities::ushortToBitset(theDMBTrailer.sizeInWords() * 16, theDMBTrailer.data());
0606   result = bitset_utilities::append(result, dmbTrailer);
0607   return result;
0608 }
0609 
0610 unsigned int CSCEventData::calcALCTcrc(std::vector<std::pair<unsigned int, unsigned short*> >& vec) {
0611   int CRC = 0;
0612 
0613   for (unsigned int n = 0; n < vec.size(); n++) {
0614     for (uint16_t j = 0, w = 0; j < vec[n].first; j++) {
0615       if (vec[n].second != nullptr) {
0616         w = vec[n].second[j] & 0xffff;
0617         for (uint32_t i = 15, t = 0, ncrc = 0; i < 16; i--) {
0618           t = ((w >> i) & 1) ^ ((CRC >> 21) & 1);
0619           ncrc = (CRC << 1) & 0x3ffffc;
0620           ncrc |= (t ^ (CRC & 1)) << 1;
0621           ncrc |= t;
0622           CRC = ncrc;
0623         }
0624       }
0625     }
0626   }
0627 
0628   return CRC;
0629 }
0630 
0631 void CSCEventData::selfTest() {
0632   CSCEventData chamberData(5);
0633   CSCDetId detId(1, 3, 2, 1, 3);
0634   std::vector<CSCCLCTDigi> clctDigis;
0635   // Both CLCTs are read-out at the same (pre-trigger) bx, so the last-but-one
0636   // arguments in both digis must be the same.
0637   clctDigis.push_back(CSCCLCTDigi(1, 1, 4, 1, 0, 30, 3, 2, 1));  // valid for 2007
0638   clctDigis.push_back(CSCCLCTDigi(1, 1, 2, 1, 1, 31, 1, 2, 2));
0639 
0640   // BX of LCT (8th argument) is 1-bit word (the least-significant bit
0641   // of ALCT's bx).
0642   std::vector<CSCCorrelatedLCTDigi> corrDigis;
0643   corrDigis.push_back(CSCCorrelatedLCTDigi(1, 1, 2, 10, 98, 5, 0, 1, 0, 0, 0, 0));
0644   corrDigis.push_back(CSCCorrelatedLCTDigi(2, 1, 2, 20, 15, 9, 1, 0, 0, 0, 0, 0));
0645 
0646   chamberData.add(clctDigis);
0647   chamberData.add(corrDigis);
0648 
0649   CSCWireDigi wireDigi(10, 6);
0650   CSCComparatorDigi comparatorDigi(30, 1, 6);
0651   chamberData.add(wireDigi, 3);
0652   chamberData.add(comparatorDigi, 3);
0653 
0654   CSCEventData newData = cscPackAndUnpack(chamberData);
0655 
0656   std::vector<CSCCLCTDigi> clcts = newData.tmbHeader()->CLCTDigis(detId.rawId());
0657   assert(cscPackerCompare(clcts[0], clctDigis[0]));
0658   assert(cscPackerCompare(clcts[1], clctDigis[1]));
0659 
0660   std::vector<CSCCorrelatedLCTDigi> lcts = newData.tmbHeader()->CorrelatedLCTDigis(detId.rawId());
0661   assert(cscPackerCompare(lcts[0], corrDigis[0]));
0662   assert(cscPackerCompare(lcts[1], corrDigis[1]));
0663 
0664   // test strip digis
0665   CSCDetId me1adet1(1, 1, 1, 4, 1);
0666   CSCDetId me1bdet1(1, 1, 4, 4, 6);
0667   CSCDetId me1adet2(2, 1, 1, 4, 2);
0668   CSCDetId me1bdet2(2, 1, 4, 4, 5);
0669 
0670   std::vector<int> sca(16, 600);
0671   std::vector<unsigned short> overflow(16, 0), overlap(16, 0), errorfl(16, 0);
0672   CSCStripDigi me1a(5, sca, overflow, overlap, errorfl);
0673   CSCStripDigi me1b(8, sca, overflow, overlap, errorfl);
0674 
0675   CSCEventData forward(1);
0676   CSCEventData backward(1);
0677 
0678   forward.add(me1a, me1adet1.layer());
0679   forward.add(me1b, me1bdet1.layer());
0680   backward.add(me1a, me1adet2.layer());
0681   backward.add(me1b, me1adet2.layer());
0682   std::vector<CSCStripDigi> me1afs = forward.stripDigis(me1adet1);
0683   std::vector<CSCStripDigi> me1bfs = forward.stripDigis(me1bdet1);
0684   std::vector<CSCStripDigi> me1abs = backward.stripDigis(me1adet2);
0685   std::vector<CSCStripDigi> me1bbs = backward.stripDigis(me1bdet2);
0686   //FIXME The current code works under the assumption that ME11 and ME1A
0687   // go into separate EventData.  They need to be combined.
0688   assert(me1afs.size() == 16);
0689   assert(me1bfs.size() == 16);
0690   assert(me1abs.size() == 16);
0691   assert(me1bbs.size() == 16);
0692 
0693   assert(me1afs[4].getStrip() == 5);
0694   assert(me1bfs[7].getStrip() == 8);
0695   assert(me1abs[4].getStrip() == 5);
0696   assert(me1bbs[7].getStrip() == 8);
0697   assert(me1afs[4].pedestal() == 600);
0698   assert(me1bfs[7].pedestal() == 600);
0699   assert(me1abs[4].pedestal() == 600);
0700   assert(me1bbs[7].pedestal() == 600);
0701 }