Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:10:26

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