Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-06-06 22:22:00

0001 //emacs settings:-*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil -*-
0002 /*
0003  *
0004  * Author: Ph Gras. CEA/IRFU - Saclay
0005  *
0006  */
0007 
0008 #include "EventFilter/EcalRawToDigi/interface/EcalDumpRaw.h"
0009 
0010 #include <iostream>
0011 #include <fstream>
0012 #include <iomanip>
0013 #include <limits>
0014 #include <algorithm>
0015 #include <sys/time.h>
0016 
0017 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0018 #include "FWCore/Framework/interface/Event.h"
0019 #include "FWCore/Framework/interface/EventSetup.h"
0020 
0021 #include "DataFormats/FEDRawData/interface/FEDRawData.h"
0022 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
0023 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
0024 #include "DataFormats/Scalers/interface/L1AcceptBunchCrossing.h"
0025 
0026 // FE BX counter starts at 0, while OD BX starts at 1.
0027 // For some reason, I do not understand myself,
0028 // Bx offset is often set such that:
0029 //     BX_FE = BX_OD for BX_OD < 3564
0030 // and BX_FE = BX_OD - 3564 for BX_OD = 3564
0031 // set feBxOffset to 1 if this FE BX shift is operated, 0 otherwise
0032 //Ph. Gras.
0033 const int feBxOffset = 1;
0034 
0035 const int EcalDumpRaw::ttId_[nTccTypes_][maxTpgsPerTcc_] = {
0036     //EB-
0037     {1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
0038      24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
0039      47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68},
0040 
0041     //EB+
0042     {4,  3,  2,  1,  8,  7,  6,  5,  12, 11, 10, 9,  16, 15, 14, 13, 20, 19, 18, 17, 24, 23, 22,
0043      21, 28, 27, 26, 25, 32, 31, 30, 29, 36, 35, 34, 33, 40, 39, 38, 37, 44, 43, 42, 41, 48, 47,
0044      46, 45, 52, 51, 50, 49, 56, 55, 54, 53, 60, 59, 58, 57, 64, 63, 62, 61, 68, 67, 66, 65},
0045 
0046     //inner EE
0047     {1,  2,  3,  4,  5,  6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
0048      24, 25, 26, 27, 28, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0049      0,  0,  0,  0,  0,  0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0},
0050 
0051     //outer EE
0052     {1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0053      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0}};
0054 
0055 using namespace std;
0056 
0057 static const char* const trigNames[] = {"Unknown", "Phys", "Calib", "Test", "Ext", "Simu", "Trace", "Err"};
0058 
0059 static const char* const detailedTrigNames[] = {
0060     "?",    //000
0061     "?",    //001
0062     "?",    //010
0063     "?",    //011
0064     "Las",  //100
0065     "Led",  //101
0066     "TP",   //110
0067     "Ped"   //111
0068 };
0069 
0070 static const char* const colorNames[] = {"Blue", "Green", "Red", "IR"};
0071 
0072 static const char* const ttsNames[] = {
0073     "Discon'd",  //0000
0074     "OvFWarn",   //0001
0075     "OoS",       //0010
0076     "Forb",      //0011
0077     "Busy",      //0100
0078     "Forb",      //0101
0079     "Forb",      //0110
0080     "Forb",      //0111
0081     "Ready",     //1000
0082     "Forb",      //1001
0083     "Idle",      //1010
0084     "Forb",      //1011
0085     "Err",       //1100
0086     "Forb",      //1101
0087     "Forb",      //1110
0088     "Discon'd"   //1111
0089 };
0090 
0091 //double mgpaGainFactors[] = {12., 1., 12./6., 12.}; //index 0->saturation
0092 //          gain setting:     sat  12       6    1  //index 0->saturation
0093 //          gain setting:  1(sat)     12      6        1
0094 //index 0->saturation
0095 static const double mgpaGainFactors[] = {10.63, 1., 10.63 / 5.43, 10.63};
0096 
0097 EcalDumpRaw::EcalDumpRaw(const edm::ParameterSet& ps)
0098     : iEvent_(0),
0099       adc_(nSamples, 0.),
0100       amplCut_(ps.getUntrackedParameter<double>("amplCut", 5.)),
0101       dump_(ps.getUntrackedParameter<bool>("dump", true)),
0102       dumpAdc_(ps.getUntrackedParameter<bool>("dumpAdc", true)),
0103       l1aHistory_(ps.getUntrackedParameter<bool>("l1aHistory", true)),
0104       //  doHisto_(ps.getUntrackedParameter<bool>("doHisto", true)),
0105       maxEvt_(ps.getUntrackedParameter<int>("maxEvt", 10000)),
0106       profileFedId_(ps.getUntrackedParameter<int>("profileFedId", 0)),
0107       profileRuId_(ps.getUntrackedParameter<int>("profileRuId", 1)),
0108       l1aMinX_(ps.getUntrackedParameter<int>("l1aMinX", 1)),
0109       l1aMaxX_(ps.getUntrackedParameter<int>("l1aMaxX", 601)),
0110       lastOrbit_(nDccs_, numeric_limits<uint32_t>::max()),
0111       eventId_(numeric_limits<unsigned>::max()),
0112       eventList_(ps.getUntrackedParameter<vector<unsigned> >("eventList", vector<unsigned>())),
0113       minEventId_(999999),
0114       maxEventId_(0),
0115       orbit0_(0),
0116       orbit0Set_(false),
0117       bx_(-1),
0118       l1a_(-1),
0119       simpleTrigType_(-1),
0120       detailedTrigType_(-1),
0121       //  histo_("hist.root", "RECREATE"),
0122       l1as_(36 + 2),
0123       orbits_(36 + 2),
0124       tpg_(maxTccsPerDcc_, std::vector<int>(maxTpgsPerTcc_)),
0125       nTpgs_(maxTccsPerDcc_, 0),
0126       dccChStatus_(70, 0),
0127       srpL1a_(-1),
0128       tccL1a_(-1),
0129       nTts_(-1),
0130       tccBlockLen64_(19),
0131       feL1a_(nRu_, -1),
0132       srpBx_(-1),
0133       tccBx_(-1),
0134       tccType_(0),
0135       feBx_(nRu_, -1),
0136       feRuId_(nRu_, -1),
0137       iTow_(0),
0138       pulsePerRu_(ps.getUntrackedParameter<bool>("pulsePerRu", true)),
0139       pulsePerLmod_(ps.getUntrackedParameter<bool>("pulsePerLmod", true)),
0140       pulsePerLme_(ps.getUntrackedParameter<bool>("pulsePerLme", true)),
0141       tccId_(0),
0142       fedRawDataCollectionTag_(ps.getParameter<edm::InputTag>("fedRawDataCollectionTag")),
0143       l1AcceptBunchCrossingCollectionTag_(ps.getParameter<edm::InputTag>("l1AcceptBunchCrossingCollectionTag")) {
0144   verbosity_ = ps.getUntrackedParameter<int>("verbosity", 1);
0145 
0146   beg_fed_id_ = ps.getUntrackedParameter<int>("beg_fed_id", 601);
0147   end_fed_id_ = ps.getUntrackedParameter<int>("end_fed_id", 654);
0148 
0149   first_event_ = ps.getUntrackedParameter<int>("first_event", 1);
0150   last_event_ = ps.getUntrackedParameter<int>("last_event", numeric_limits<int>::max());
0151 
0152   writeDcc_ = ps.getUntrackedParameter<bool>("writeDCC", false);
0153   filename_ = ps.getUntrackedParameter<string>("filename", "dump.bin");
0154 
0155   fedRawDataCollectionToken_ = consumes<FEDRawDataCollection>(fedRawDataCollectionTag_);
0156   l1AcceptBunchCrossingCollectionToken_ =
0157       consumes<L1AcceptBunchCrossingCollection>(l1AcceptBunchCrossingCollectionTag_);
0158 
0159   if (writeDcc_) {
0160     dumpFile_.open(filename_.c_str());
0161     if (dumpFile_.bad()) {
0162       /*edm::LogError("EcalDumpRaw")*/ std::cout << "Failed to open file '" << filename_.c_str() << "' specified by "
0163                                                  << "parameter filename for writing. DCC data "
0164                                                     " dump will be disabled.";
0165       writeDcc_ = false;
0166     }
0167   }
0168 }
0169 
0170 void EcalDumpRaw::endJob() {}
0171 
0172 EcalDumpRaw::~EcalDumpRaw() {}
0173 
0174 // ------------ method called to analyze the data  ------------
0175 void EcalDumpRaw::analyze(const edm::Event& event, const edm::EventSetup& es) {
0176   ++iEvent_;
0177   eventId_ = event.id().event();
0178 
0179   if (!eventList_.empty() && find(eventList_.begin(), eventList_.end(), eventId_) == eventList_.end()) {
0180     cout << "Skipping event " << eventId_ << ".\n";
0181     return;
0182   }
0183 
0184   if ((first_event_ > 0 && iEvent_ < first_event_) || (last_event_ > 0 && last_event_ < iEvent_))
0185     return;
0186   timeval start;
0187   timeval stop;
0188   gettimeofday(&start, nullptr);
0189 
0190   edm::Handle<FEDRawDataCollection> rawdata;
0191   event.getByToken(fedRawDataCollectionToken_, rawdata);
0192 
0193   if (dump_ || l1aHistory_)
0194     cout << "\n======================================================================\n"
0195          << toNth(iEvent_) << " read event. "
0196          << "Event id: "
0197          << " " << eventId_ << "\n----------------------------------------------------------------------\n";
0198 
0199   if (l1aHistory_) {
0200     edm::Handle<L1AcceptBunchCrossingCollection> l1aHist;
0201     event.getByToken(l1AcceptBunchCrossingCollectionToken_, l1aHist);
0202     if (!l1aHist.isValid()) {
0203       cout << "L1A history not found.\n";
0204     } else if (l1aHist->empty()) {
0205       cout << "L1A history is empty.\n";
0206     } else {
0207       cout << "L1A history: \n";
0208       for (L1AcceptBunchCrossingCollection::const_iterator it = l1aHist->begin(); it != l1aHist->end(); ++it) {
0209         cout << "L1A offset: " << it->l1AcceptOffset() << "\t"
0210              << "BX: " << it->bunchCrossing() << "\t"
0211              << "Orbit ID: " << it->orbitNumber() << "\t"
0212              << "Trigger type: " << it->eventType() << " (" << trigNames[it->eventType() & 0xF] << ")\n";
0213       }
0214     }
0215     cout << "----------------------------------------------------------------------\n";
0216   }
0217 
0218   if (eventId_ < minEventId_)
0219     minEventId_ = eventId_;
0220   if (eventId_ > maxEventId_)
0221     maxEventId_ = eventId_;
0222 
0223 #if 1
0224 
0225   bool dccIdErr = false;
0226   unsigned iFed = 0;
0227   unsigned refDccId = 0;
0228   //  static bool recordNextPhys = false;
0229   //static int bxCalib = -1;
0230   //x static int nCalib = 0;
0231 
0232   for (int id = 0; id <= FEDNumbering::lastFEDId(); ++id) {
0233     if (id < beg_fed_id_ || end_fed_id_ < id)
0234       continue;
0235 
0236     const FEDRawData& data = rawdata->FEDData(id);
0237 
0238     if (data.size() > 4) {
0239       ++iFed;
0240       if ((data.size() % 8) != 0) {
0241         cout << "***********************************************\n";
0242         cout << " Fed size in bits not multiple of 64, strange.\n";
0243         cout << "***********************************************\n";
0244       }
0245 
0246       size_t nWord32 = data.size() / 4;
0247       const uint32_t* pData = (reinterpret_cast<uint32_t*>(const_cast<unsigned char*>(data.data())));
0248       stringstream s;
0249       srpL1a_ = -1;
0250       tccL1a_ = -1;
0251       srpBx_ = -1;
0252       tccBx_ = -1;
0253       iTow_ = 0;
0254       iRu_ = 0;
0255       nTts_ = -1;
0256       iTcc_ = 0;
0257       tccType_ = 0;
0258 
0259       for (int i = 0; i < nRu_; ++i) {
0260         feL1a_[i] = -1;
0261         feBx_[i] = -1;
0262         feRuId_[i] = -1;
0263       }
0264 
0265       fill(nTpgs_.begin(), nTpgs_.end(), 0);
0266 
0267       fill(dccChStatus_.begin(), dccChStatus_.end(), 0);
0268 
0269       bool rc;
0270       for (size_t iWord32 = 0; iWord32 < nWord32; iWord32 += 2) {
0271         s.str("");
0272         if (id >= 601 && id <= 654) {  // ECAL DCC data
0273           rc = decode(pData + iWord32, iWord32 / 2, s);
0274         } else {
0275           rc = true;
0276         }
0277         if (rc && dump_) {
0278           cout << setfill('0') << hex << "[" << setw(8) << iWord32 * 4 << "] " << setw(4)
0279                << (pData[iWord32 + 1] >> 16 & 0xFFFF) << " " << setw(4) << (pData[iWord32 + 1] >> 0 & 0xFFFF) << " "
0280                << setw(4) << (pData[iWord32] >> 16 & 0xFFFF) << " " << setw(4) << (pData[iWord32] >> 0 & 0xFFFF) << " "
0281                << setfill(' ') << dec << s.str() << "\n";
0282         }
0283       }
0284 
0285       if (iFed == 1) {
0286         refDccId = dccId_;
0287       } else {
0288         if (dccId_ != refDccId) {
0289           dccIdErr = true;
0290         }
0291       }
0292 
0293       if (dump_)
0294         cout << flush;  //flushing cout before writing to cerr
0295 
0296       if (srpBx_ != -1 && srpBx_ != bx_) {
0297         cerr << "Bx discrepancy between SRP and DCC, Bx(SRP) = " << srpBx_ << ", Bx(DCC) = " << bx_ << " in "
0298              << toNth(iEvent_) << " event, FED " << id << endl;
0299       }
0300 
0301       if (tccBx_ != -1 && tccBx_ != bx_) {
0302         cerr << "Bx discrepancy between TCC and DCC, Bx(TCC) = " << srpBx_ << ", Bx(DCC) = " << bx_ << " in "
0303              << toNth(iEvent_) << " event, FED " << id << endl;
0304       }
0305 
0306       bool feBxErr = false;
0307       for (int i = 0; i < nRu_; ++i) {
0308         int expectedFeBx;
0309         if (feBxOffset == 0) {
0310           expectedFeBx = bx_ - 1;
0311         } else {
0312           expectedFeBx = (bx_ == 3564) ? 0 : bx_;
0313         }
0314         if (feBx_[i] != -1 && feBx_[i] != expectedFeBx) {
0315           cerr << "BX error for " << toNth(i + 1) << " RU, RU ID " << feRuId_[i];
0316           if ((unsigned)feRuId_[i] <= dccChStatus_.size()) {
0317             bool detected = (dccChStatus_[feRuId_[i] - 1] == 10 || dccChStatus_[feRuId_[i] - 1] == 11);
0318             cerr << (detected ? " " : " not ") << "detected by DCC (ch status: " << dccChStatus_[feRuId_[i] - 1] << ")";
0319           }
0320           cerr << " in " << toNth(iEvent_) << " event, FED " << id << "." << endl;
0321 
0322           feBxErr = true;
0323         }
0324       }
0325       if (feBxErr)
0326         cerr << "Bx discrepancy between DCC and at least one FE"
0327              << " in " << toNth(iEvent_) << " event, FED " << id << "\n";
0328 
0329       int localL1a = l1a_ & 0xFFF;
0330       if (srpL1a_ != -1 && srpL1a_ != localL1a) {
0331         cerr << "Discrepancy between SRP and DCC L1a counter, L1a(SRP) = " << srpL1a_
0332              << ", L1a(DCC) & 0xFFF = " << localL1a << " in " << toNth(iEvent_) << " event, FED " << id << endl;
0333       }
0334 
0335       if (tccL1a_ != -1 && tccL1a_ != localL1a) {
0336         cerr << "Discrepancy between TCC and DCC L1a counter, L1a(TCC) = " << srpL1a_
0337              << ", L1a(DCC) & 0xFFF = " << localL1a << " in " << toNth(iEvent_) << " event, FED " << id << endl;
0338       }
0339 
0340       bool feL1aErr = false;
0341       for (int i = 0; i < nRu_; ++i) {
0342         if (feL1a_[i] != -1 && feL1a_[i] != ((localL1a - 1) & 0xFFF)) {
0343           cerr << "FE L1A error for " << toNth(i + 1) << " RU, RU ID " << feRuId_[i];
0344           if ((unsigned)feRuId_[i] <= dccChStatus_.size()) {
0345             bool detected = (dccChStatus_[feRuId_[i] - 1] == 9 || dccChStatus_[feRuId_[i] - 1] == 11);
0346             cerr << (detected ? " " : " not ") << "detected by DCC (ch status: " << dccChStatus_[feRuId_[i] - 1] << ")";
0347           }
0348           cerr << " in " << toNth(iEvent_) << " event, FED " << id << "." << endl;
0349           feL1aErr = true;
0350         }
0351       }
0352       if (feL1aErr)
0353         cerr << "Discrepancy in L1a counter between DCC "
0354                 "and at least one FE (L1A(DCC) & 0xFFF = "
0355              << localL1a << ")"
0356              << " in " << toNth(iEvent_) << " event, FED " << id << "\n";
0357 
0358       if (iTow_ > 0 && iTow_ < nRu_ && feRuId_[iTow_] < feRuId_[iTow_ - 1]) {
0359         cerr << "Error in RU ID (TT/SC ID)"
0360              << " in " << toNth(iEvent_) << " event, FED " << id << endl;
0361       }
0362 
0363       if (beg_fed_id_ <= id && id <= end_fed_id_ && writeDcc_) {
0364         dumpFile_.write(reinterpret_cast<const char*>(pData), nWord32 * 4);
0365       }
0366 
0367       if (dump_)
0368         cout << "\n";
0369     } else {
0370       //      cout << "No data for FED " <<  id << ". Size = "
0371       //     << data.size() << " byte(s).\n";
0372     }
0373   }  //next fed
0374 
0375   if (dump_)
0376     cout << "Number of selected FEDs with a data block: " << iFed << "\n";
0377 
0378   if (dccIdErr) {
0379     cout << flush;
0380     cerr << "DCC ID discrepancy in detailed trigger type "
0381          << " of " << toNth(iEvent_) << " event." << endl;
0382   }
0383 
0384 #endif
0385 
0386   gettimeofday(&stop, nullptr);
0387   //  double dt  = (stop.tv_sec-start.tv_sec)*1.e3
0388   //  + (stop.tv_usec-start.tv_usec)*1.e-3;
0389   //  histo_.fillD("hCodeTime", "Code execution time;Duration (ms);Event count",
0390   //             PGXAxis(100, 0, 100),
0391   //             dt);
0392 }
0393 
0394 string EcalDumpRaw::toNth(int n) {
0395   stringstream s;
0396   s << n;
0397   if (n % 100 < 10 || n % 100 > 20) {
0398     switch (n % 10) {
0399       case 1:
0400         s << "st";
0401         break;
0402       case 2:
0403         s << "nd";
0404         break;
0405       case 3:
0406         s << "rd";
0407         break;
0408       default:
0409         s << "th";
0410     }
0411   } else {
0412     s << "th";
0413   }
0414   return s.str();
0415 }
0416 
0417 bool EcalDumpRaw::decode(const uint32_t* data, int iWord64, ostream& out) {
0418   bool rc = true;
0419   const bool d = dump_;
0420   if (iWord64 == 0) {  //start of event
0421     iSrWord64_ = 0;
0422     iTccWord64_ = 0;
0423     iTowerWord64_ = 0;
0424   }
0425   int dataType = (data[1] >> 28) & 0xF;
0426   const int boe = 5;
0427   const int eoe = 10;
0428   if (dataType == boe) {  //Begin of Event header
0429     /**********************************************************************
0430      *  DAQ header
0431      *
0432      **********************************************************************/
0433     simpleTrigType_ = (data[1] >> 24) & 0xF;
0434     l1a_ = (data[1] >> 0) & 0xFFffFF;
0435     bx_ = (data[0] >> 20) & 0xFFF;
0436     fedId_ = (data[0] >> 8) & 0xFFF;
0437     if (d)
0438       out << "Trigger type: " << simpleTrigType_ << "(" << trigNames[(data[1] >> 24) & 0xF] << ")"
0439           << " L1A: " << l1a_ << " BX: " << bx_ << " FED ID: " << fedId_ << " FOV: " << ((data[0] >> 4) & 0xF)
0440           << " H: " << ((data[0] >> 3) & 0x1);
0441   } else if ((dataType >> 2) == 0) {  //DCC header
0442     /**********************************************************************
0443      * ECAL DCC header
0444      *
0445      **********************************************************************/
0446     int dccHeaderId = (data[1] >> 24) & 0x3F;
0447     switch (dccHeaderId) {
0448       case 1:
0449         if (d)
0450           out << "Run #: " << ((data[1] >> 0) & 0xFFFFFF) << " DCC Err: " << ((data[0] >> 24) & 0xFF)
0451               << " Evt Len:  " << ((data[0] >> 0) & 0xFFFFFF);
0452         break;
0453       case 2:
0454         side_ = (data[1] >> 11) & 0x1;
0455         detailedTrigType_ = (data[1] >> 8) & 0x7;
0456         dccId_ = (data[1] >> 0) & 0x3F;
0457         if (d)
0458           out << "DCC FOV: " << ((data[1] >> 16) & 0xF) << " Side: " << side_ << " Trig.: " << detailedTrigType_ << " ("
0459               << detailedTrigNames[(data[1] >> 8) & 0x7] << ")"
0460               << " Color: " << ((data[1] >> 6) & 0x3) << " (" << colorNames[(data[1] >> 6) & 0x3] << ")"
0461               << " DCC ID: " << dccId_;
0462         break;
0463       case 3: {
0464         if (d)
0465           out << "TCC Status ch<4..1>: 0x" << hex << ((data[1] >> 8) & 0xFFFF) << dec
0466               << " SR status: " << ((data[1] >> 4) & 0xF) << " TZS: " << ((data[1] >> 2) & 0x1)
0467               << " ZS: " << ((data[1] >> 1) & 0x1) << " SR: " << ((data[1] >> 0) & 0x1);
0468         orbit_ = data[0];
0469         if (d)
0470           out << " Orbit: " << orbit_;
0471         if (!orbit0Set_) {
0472           orbit0_ = orbit_;
0473           orbit0Set_ = true;
0474         }
0475         int iDcc0 = fedId_ - fedStart_;
0476         if ((unsigned)iDcc0 < nDccs_) {
0477           if (lastOrbit_[iDcc0] != numeric_limits<uint32_t>::max()) {
0478             if (d)
0479               out << " (+" << (int)orbit_ - (int)lastOrbit_[iDcc0] << ")";
0480           }
0481           lastOrbit_[iDcc0] = orbit_;
0482         }
0483       } break;
0484       case 4:
0485       case 5:
0486       case 6:
0487       case 7:
0488       case 8: {
0489         int chOffset = (dccHeaderId - 4) * 14;
0490         dccChStatus_[13 + chOffset] = ((data[1] >> 20) & 0xF);
0491         dccChStatus_[12 + chOffset] = ((data[1] >> 16) & 0xF);
0492         dccChStatus_[11 + chOffset] = ((data[1] >> 12) & 0xF);
0493         dccChStatus_[10 + chOffset] = ((data[1] >> 8) & 0xF);
0494         dccChStatus_[9 + chOffset] = ((data[1] >> 4) & 0xF);
0495         dccChStatus_[8 + chOffset] = ((data[1] >> 0) & 0xF);
0496         dccChStatus_[7 + chOffset] = ((data[0] >> 28) & 0xF);
0497         dccChStatus_[6 + chOffset] = ((data[0] >> 24) & 0xF);
0498         dccChStatus_[5 + chOffset] = ((data[0] >> 20) & 0xF);
0499         dccChStatus_[4 + chOffset] = ((data[0] >> 16) & 0xF);
0500         dccChStatus_[3 + chOffset] = ((data[0] >> 12) & 0xF);
0501         dccChStatus_[2 + chOffset] = ((data[0] >> 8) & 0xF);
0502         dccChStatus_[1 + chOffset] = ((data[0] >> 4) & 0xF);
0503         dccChStatus_[0 + chOffset] = ((data[0] >> 0) & 0xF);
0504 
0505         if (d) {
0506           out << "FE CH status:";
0507           for (int i = chOffset; i < chOffset + 14; ++i) {
0508             out << " #" << (i + 1) << ":" << dccChStatus_[i];
0509           }
0510         }
0511       } break;
0512       default:
0513         if (d)
0514           out << " bits<63..62>=0 (DCC header) bits<61..56>=" << dccHeaderId << "(unknown=>ERROR?)";
0515     }
0516   } else if ((dataType >> 1) == 3) {  //TCC block
0517     /**********************************************************************
0518      * TCC block
0519      *
0520      **********************************************************************/
0521     if (iTccWord64_ == 0) {
0522       //header
0523       tccL1a_ = (data[1] >> 0) & 0xFFF;
0524       tccId_ = ((data[0] >> 0) & 0xFF);
0525       nTts_ = ((data[1] >> 16) & 0x7F);
0526       if (iTcc_ < maxTccsPerDcc_)
0527         nTpgs_[iTcc_] = nTts_;
0528       ++iTcc_;
0529       if (d)
0530         out << "LE1: " << ((data[1] >> 28) & 0x1) << " LE0: " << ((data[1] >> 27) & 0x1)
0531             << " N_samples: " << ((data[1] >> 23) & 0x1F) << " N_TTs: " << nTts_ << " E1: " << ((data[1] >> 12) & 0x1)
0532             << " L1A: " << tccL1a_ << " '3': " << ((data[0] >> 29) & 0x7) << " E0: " << ((data[0] >> 28) & 0x1)
0533             << " Bx: " << ((data[0] >> 16) & 0xFFF) << " TTC ID: " << tccId_;
0534       if (nTts_ == 68) {  //EB TCC (TCC68)
0535         if (fedId_ < 628)
0536           tccType_ = ebmTcc_;
0537         else
0538           tccType_ = ebpTcc_;
0539       } else if (nTts_ == 16) {  //Inner EE TCC (TCC48)
0540         tccType_ = eeOuterTcc_;
0541       } else if (nTts_ == 28) {  //Outer EE TCC (TCC48)
0542         tccType_ = eeInnerTcc_;
0543       } else {
0544         cout << flush;
0545         cerr << "Error in #TT field of TCC block."
0546                 "This field is normally used to determine type of TCC "
0547                 "(TCC48 or TCC68). Type of TCC will be deduced from the TCC ID.\n";
0548         if (tccId_ < 19)
0549           tccType_ = eeInnerTcc_;
0550         else if (tccId_ < 37)
0551           tccType_ = eeOuterTcc_;
0552         else if (tccId_ < 55)
0553           tccType_ = ebmTcc_;
0554         else if (tccId_ < 73)
0555           tccType_ = ebpTcc_;
0556         else if (tccId_ < 91)
0557           tccType_ = eeOuterTcc_;
0558         else if (tccId_ < 109)
0559           tccType_ = eeInnerTcc_;
0560         else {
0561           cerr << "TCC ID is also invalid. EB- TCC type will be assumed.\n";
0562           tccType_ = ebmTcc_;
0563         }
0564         cerr << flush;
0565       }
0566       tccBlockLen64_ = (tccType_ == ebmTcc_ || tccType_ == ebpTcc_) ? 18 : 9;
0567     } else {  // if(iTccWord64_<18){
0568       int tpgOffset = (iTccWord64_ - 1) * 4;
0569       if (iTcc_ > maxTccsPerDcc_) {
0570         out << "Too many TCC blocks";
0571       } else if (tpgOffset > (maxTpgsPerTcc_ - 4)) {
0572         out << "Too many TPG in one TCC block";
0573       } else {
0574         tpg_[iTcc_ - 1][3 + tpgOffset] = (data[1] >> 16) & 0x1FF;
0575         tpg_[iTcc_ - 1][2 + tpgOffset] = (data[1] >> 0) & 0x1FF;
0576         tpg_[iTcc_ - 1][1 + tpgOffset] = (data[0] >> 16) & 0x1FF;
0577         tpg_[iTcc_ - 1][0 + tpgOffset] = (data[0] >> 0) & 0x1FF;
0578         //int n[2][4] = {{1,2,3,4},
0579         //             {4,3,2,1}};
0580         //int iorder = (628<=fedId_ && fedId_<=645)?1:0;
0581         if (d)
0582           out << ttfTag(tccType_, 3 + tpgOffset) << ":"  //"TTF# " << setw(2) << ttId_[3 + tpgOffset] << ":"
0583               << ((data[1] >> 25) & 0x7) << " " << tpgTag(tccType_, 3 + tpgOffset)
0584               << ":"  //" TPG# "<< setw(2) << ttId_[3 + tpgOffset] << ":"
0585               << setw(3) << tpg_[iTcc_ - 1][3 + tpgOffset] << " " << ttfTag(tccType_, 2 + tpgOffset)
0586               << ":"  //" TTF# "<< setw(2) << ttId_[2 + tpgOffset] << ":"
0587               << ((data[1] >> 9) & 0x7) << " " << tpgTag(tccType_, 2 + tpgOffset)
0588               << ":"  //" TPG# "<< setw(2) << ttId_[2 + tpgOffset] << ":"
0589               << setw(3) << tpg_[iTcc_ - 1][2 + tpgOffset] << " "
0590               << " '3': " << ((data[0] >> 29) & 0x7) << " " << ttfTag(tccType_, 1 + tpgOffset)
0591               << ":"  //" TTF# "<< setw(2) << ttId_[1 + tpgOffset] << ":"
0592               << ((data[0] >> 25) & 0x7) << " " << setw(3) << tpgTag(tccType_, 1 + tpgOffset)
0593               << ": "  //" TPG# "<< setw(2) << ttId_[1 + tpgOffset] << ":"
0594               << tpg_[iTcc_ - 1][1 + tpgOffset] << " " << ttfTag(tccType_, 0 + tpgOffset)
0595               << ":"  //" TTF# "<< setw(2) << ttId_[0 + tpgOffset] << ":"
0596               << ((data[0] >> 9) & 0x7) << " " << setw(3) << tpgTag(tccType_, 0 + tpgOffset)
0597               << ":"  //" TPG# "<< setw(2) << ttId_[0 + tpgOffset] << ":"
0598               << tpg_[iTcc_ - 1][0 + tpgOffset];
0599       }
0600     }  // else{
0601        // if(d) out << "ERROR";
0602     //}
0603     ++iTccWord64_;
0604     if (iTccWord64_ >= (unsigned)tccBlockLen64_)
0605       iTccWord64_ = 0;
0606   } else if ((dataType >> 1) == 4) {  //SRP block
0607     /**********************************************************************
0608      * SRP block
0609      *
0610      **********************************************************************/
0611     if (iSrWord64_ == 0) {  //header
0612       srpL1a_ = (data[1] >> 0) & 0xFFF;
0613       srpBx_ = (data[0] >> 16) & 0xFFF;
0614       if (d)
0615         out << "LE1: " << ((data[1] >> 28) & 0x1) << " LE0: " << ((data[1] >> 27) & 0x1)
0616             << " N_SRFs: " << ((data[1] >> 16) & 0x7F) << " E1: " << ((data[1] >> 12) & 0x1) << " L1A: " << srpL1a_
0617             << " '4': " << ((data[0] >> 29) & 0x7) << " E0: " << ((data[0] >> 28) & 0x1) << " Bx: " << srpBx_
0618             << " SRP ID: " << ((data[0] >> 0) & 0xFF);
0619     } else if (iSrWord64_ < 6) {
0620       int ttfOffset = (iSrWord64_ - 1) * 16;
0621       if (d) {
0622         if (iSrWord64_ < 5) {
0623           out << "SRF# " << setw(6) << right
0624               << srRange(12 + ttfOffset) /*16+ttfOffset << "..#" << 13+ttfOffset*/ << ": " << oct
0625               << ((data[1] >> 16) & 0xFFF) << dec << " SRF# "
0626               << srRange(8 + ttfOffset) /*12+ttfOffset << "..#" << 9+ttfOffset*/ << ": " << oct
0627               << ((data[1] >> 0) & 0xFFF) << dec << " '4':" << ((data[0] >> 29) & 0x7) << " SRF# "
0628               << srRange(4 + ttfOffset) /*8+ttfOffset << "..#" << 5+ttfOffset*/ << ": " << oct
0629               << ((data[0] >> 16) & 0xFFF) << dec;
0630         } else {  //last 64-bit word has only 4 SRFs.
0631           out << "                                                           ";
0632         }
0633         out << " SRF# " << srRange(ttfOffset) /*4+ttfOffset << "..#" << 1+ttfOffset*/ << ": " << oct
0634             << ((data[0] >> 0) & 0xFFF) << dec;
0635       }
0636     } else {
0637       if (d)
0638         out << "ERROR";
0639     }
0640     ++iSrWord64_;
0641   } else if ((dataType >> 2) == 3) {  //Tower block
0642     /**********************************************************************
0643      * "Tower" block (crystal channel data from a RU (=1 FE cards))
0644      *
0645      **********************************************************************/
0646     if (iTowerWord64_ == 0) {  //header
0647       towerBlockLength_ = (data[1] >> 16) & 0x1FF;
0648       int l1a;
0649       int bx;
0650       l1a = (data[1] >> 0) & 0xFFF;
0651       bx = (data[0] >> 16) & 0xFFF;
0652       dccCh_ = (data[0] >> 0) & 0xFF;
0653       if (d)
0654         out << "Block Len: " << towerBlockLength_ << " E1: " << ((data[1] >> 12) & 0x1) << " L1A: " << l1a
0655             << " '3': " << ((data[0] >> 30) & 0x3) << " E0: " << ((data[0] >> 28) & 0x1) << " Bx: " << bx
0656             << " N_samples: " << ((data[0] >> 8) & 0x7F) << " RU ID: " << dccCh_;
0657       if (iRu_ < nRu_) {
0658         feL1a_[iRu_] = l1a;
0659         feBx_[iRu_] = bx;
0660         feRuId_[iRu_] = dccCh_;
0661         ++iRu_;
0662       }
0663     } else if ((unsigned)iTowerWord64_ < towerBlockLength_) {
0664       if (!dumpAdc_) {
0665         //no output.
0666         rc = false;
0667       }
0668       const bool da = dumpAdc_ && dump_;
0669       switch ((iTowerWord64_ - 1) % 3) {
0670         int s[4];
0671         int g[4];
0672         case 0:
0673           s[0] = (data[0] >> 16) & 0xFFF;
0674           g[0] = (data[0] >> 28) & 0x3;
0675           s[1] = (data[1] >> 0) & 0xFFF;
0676           g[1] = (data[1] >> 12) & 0x3;
0677           s[2] = (data[1] >> 16) & 0xFFF;
0678           g[2] = (data[1] >> 28) & 0x3;
0679           fill(adc_.begin(), adc_.end(), 0.);
0680           if (da)
0681             out << "GMF: " << ((data[0] >> 11) & 0x1) << " SMF: " << ((data[0] >> 9) & 0x1)
0682                 << " M: " << ((data[0] >> 8) & 0x1) << " XTAL: " << ((data[0] >> 4) & 0x7)
0683                 << " STRIP: " << ((data[0] >> 0) & 0x7) << " " << setw(4) << s[0] << "G" << g[0] << " " << setw(4)
0684                 << s[1] << "G" << g[1] << " " << setw(4) << s[2] << "G" << g[2];
0685           for (int i = 0; i < 3; ++i)
0686             adc_[i] = s[i] * mgpaGainFactors[g[i]];
0687           break;
0688         case 1:
0689           s[0] = (data[0] >> 0) & 0xFFF;
0690           g[0] = (data[0] >> 12) & 0x3;
0691           s[1] = (data[0] >> 16) & 0xFFF;
0692           g[1] = (data[0] >> 28) & 0x3;
0693           s[2] = (data[1] >> 0) & 0xFFF;
0694           g[2] = (data[1] >> 12) & 0x3;
0695           s[3] = (data[1] >> 16) & 0xFFF;
0696           g[3] = (data[1] >> 28) & 0x3;
0697           if (da)
0698             out << "                                   "
0699                 << " " << setw(4) << s[0] << "G" << g[0] << " " << setw(4) << s[1] << "G" << g[1] << " " << setw(4)
0700                 << s[2] << "G" << g[2] << " " << setw(4) << s[3] << "G" << g[3];
0701           for (int i = 0; i < 4; ++i)
0702             adc_[i + 3] = s[i] * mgpaGainFactors[g[i]];
0703           break;
0704         case 2:
0705           if (da)
0706             out << "TZS: " << ((data[1] >> 14) & 0x1);
0707 
0708           s[0] = (data[0] >> 0) & 0xFFF;
0709           g[0] = (data[0] >> 12) & 0x3;
0710           s[1] = (data[0] >> 16) & 0xFFF;
0711           g[1] = (data[0] >> 28) & 0x3;
0712           s[2] = (data[1] >> 0) & 0xFFF;
0713           g[2] = (data[1] >> 12) & 0x3;
0714 
0715           for (int i = 0; i < 3; ++i)
0716             adc_[i + 7] = s[i] * mgpaGainFactors[g[i]];
0717           if (dccCh_ <= 68) {
0718             unsigned bom0;  //Bin of Maximum, starting counting from 0
0719             double ampl = max(adc_, bom0) - min(adc_);
0720             if (da)
0721               out << " Ampl: " << setw(4) << ampl << (ampl > amplCut_ ? "*" : " ") << " BoM:" << setw(2) << (bom0 + 1)
0722                   << "          ";
0723             if (fedId_ == dccId_ + 600  //block of the read-out SM
0724                 //if laser, only one side:
0725                 && (detailedTrigType_ != 4 || sideOfRu(dccCh_) == (int)side_)) {
0726             }
0727           } else {
0728             if (da)
0729               out << setw(29) << "";
0730           }
0731           if (da)
0732             out << " " << setw(4) << s[0] << "G" << g[0] << " " << setw(4) << s[1] << "G" << g[1] << " " << setw(4)
0733                 << s[2] << "G" << g[2];
0734           break;
0735         default:
0736           assert(false);
0737       }
0738     } else {
0739       if (d)
0740         out << "ERROR";
0741     }
0742     ++iTowerWord64_;
0743     if (iTowerWord64_ >= towerBlockLength_) {
0744       iTowerWord64_ -= towerBlockLength_;
0745       ++dccCh_;
0746     }
0747   } else if (dataType == eoe) {  //End of event trailer
0748     /**********************************************************************
0749      * Event DAQ trailer
0750      *
0751      **********************************************************************/
0752     int tts = (data[0] >> 4) & 0xF;
0753     if (d)
0754       out << "Evt Len.: " << ((data[1] >> 0) & 0xFFFFFF) << " CRC16: " << ((data[0] >> 16) & 0xFFFF)
0755           << " Evt Status: " << ((data[0] >> 8) & 0xF) << " TTS: " << tts << " (" << ttsNames[tts] << ")"
0756           << " T:" << ((data[0] >> 3) & 0x1);
0757   } else {
0758     if (d)
0759       out << " incorrect 64-bit word type marker (see MSBs)";
0760   }
0761   return rc;
0762 }
0763 
0764 // The following method was not removed due to package maintainer
0765 // (Philippe Gras <philippe.gras@cern.ch>) request.
0766 
0767 //int EcalDumpRaw::lme(int dcc1, int side){
0768 //  int fedid = ((dcc1-1)%600) + 600; //to handle both FED and DCC id.
0769 //   vector<int> lmes;
0770 //   // EE -
0771 //   if( fedid <= 609 ) {
0772 //     if ( fedid <= 607 ) {
0773 //       lmes.push_back(fedid-601+83);
0774 //     } else if ( fedid == 608 ) {
0775 //       lmes.push_back(90);
0776 //       lmes.push_back(91);
0777 //     } else if ( fedid == 609 ) {
0778 //       lmes.push_back(92);
0779 //     }
0780 //   } //EB
0781 //   else if ( fedid >= 610  && fedid <= 645 ) {
0782 //     lmes.push_back(2*(fedid-610)+1);
0783 //     lmes.push_back(lmes[0]+1);
0784 //   } // EE+
0785 //   else if ( fedid >= 646 ) {
0786 //     if ( fedid <= 652 ) {
0787 //       lmes.push_back(fedid-646+73);
0788 //     } else if ( fedid == 653 ) {
0789 //       lmes.push_back(80);
0790 //       lmes.push_back(81);
0791 //     } else if ( fedid == 654 ) {
0792 //       lmes.push_back(82);
0793 //     }
0794 //   }
0795 //   return lmes.size()==0?-1:lmes[std::min(lmes.size(), (size_t)side)];
0796 //}
0797 
0798 int EcalDumpRaw::sideOfRu(int ru1) {
0799   if (ru1 < 5 || (ru1 - 5) % 4 >= 2) {
0800     return 0;
0801   } else {
0802     return 1;
0803   }
0804 }
0805 
0806 int EcalDumpRaw::modOfRu(int ru1) {
0807   int iEta0 = (ru1 - 1) / 4;
0808   if (iEta0 < 5) {
0809     return 1;
0810   } else {
0811     return 2 + (iEta0 - 5) / 4;
0812   }
0813 }
0814 
0815 int EcalDumpRaw::lmodOfRu(int ru1) {
0816   int iEta0 = (ru1 - 1) / 4;
0817   int iPhi0 = (ru1 - 1) % 4;
0818   int rs;
0819   if (iEta0 == 0) {
0820     rs = 1;
0821   } else {
0822     rs = 2 + ((iEta0 - 1) / 4) * 2 + (iPhi0 % 4) / 2;
0823   }
0824   //  cout << "ru1 = " << ru1 << " -> lmod = " << rs << "\n";
0825   return rs;
0826 }
0827 
0828 std::string EcalDumpRaw::srRange(int offset) const {
0829   int min = offset + 1;
0830   int max = offset + 4;
0831   stringstream buf;
0832   if (628 <= fedId_ && fedId_ <= 646) {  //EB+
0833     buf << right << min << ".." << left << max;
0834   } else {
0835     buf << right << max << ".." << left << min;
0836   }
0837   string s = buf.str();
0838   buf.str("");
0839   buf << setw(6) << right << s;
0840   return buf.str();
0841 }
0842 
0843 std::string EcalDumpRaw::ttfTag(int tccType, unsigned iSeq) const {
0844   if ((unsigned)iSeq > sizeof(ttId_))
0845     throw cms::Exception("OutOfRange") << __FILE__ << ":" << __LINE__ << ": "
0846                                        << "parameter out of range\n";
0847 
0848   const int ttId = ttId_[tccType][iSeq];
0849   stringstream buf;
0850   buf.str("");
0851   if (ttId == 0) {
0852     buf << "    '0'";
0853   } else {
0854     buf << "TTF# " << setw(2) << ttId;
0855   }
0856   return buf.str();
0857 }
0858 
0859 std::string EcalDumpRaw::tpgTag(int tccType, unsigned iSeq) const {
0860   if ((unsigned)iSeq > sizeof(ttId_))
0861     throw cms::Exception("OutOfRange") << __FILE__ << ":" << __LINE__ << ": "
0862                                        << "parameter out of range\n";
0863 
0864   const int ttId = ttId_[tccType][iSeq];
0865   stringstream buf;
0866   buf.str("");
0867   if (ttId == 0) {
0868     buf << "    '0'";
0869   } else {
0870     buf << "TPG# " << setw(2) << ttId;
0871   }
0872   return buf.str();
0873 }
0874 
0875 #include "FWCore/Framework/interface/MakerMacros.h"
0876 DEFINE_FWK_MODULE(EcalDumpRaw);