Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:45:23

0001 /*
0002  *
0003  *  \author  N. Marinelli IASA 
0004  *  \author G. Della Ricca
0005  *  \author G. Franzoni
0006  *  \author A. Ghezzi
0007  *
0008  */
0009 
0010 #include "EcalTBDaqFormatter.h"
0011 #include <DataFormats/FEDRawData/interface/FEDRawData.h>
0012 #include <DataFormats/EcalDetId/interface/EBDetId.h>
0013 #include <DataFormats/EcalDetId/interface/EcalTrigTowerDetId.h>
0014 #include <DataFormats/EcalDigi/interface/EBDataFrame.h>
0015 #include <DataFormats/EcalDigi/interface/EcalDigiCollections.h>
0016 
0017 #include <EventFilter/EcalTBRawToDigi/interface/EcalDCCHeaderRuntypeDecoder.h>
0018 #include <DataFormats/EcalDigi/interface/EcalTriggerPrimitiveDigi.h>
0019 #include <DataFormats/EcalDigi/interface/EcalTriggerPrimitiveSample.h>
0020 
0021 #include "DCCDataParser.h"
0022 #include "DCCEventBlock.h"
0023 #include "DCCTowerBlock.h"
0024 #include "DCCTCCBlock.h"
0025 #include "DCCXtalBlock.h"
0026 #include "DCCDataMapper.h"
0027 
0028 #include <iostream>
0029 
0030 EcalTBDaqFormatter::EcalTBDaqFormatter() {
0031   LogDebug("EcalTBRawToDigi") << "@SUB=EcalTBDaqFormatter";
0032   std::vector<uint32_t> parameters;
0033   parameters.push_back(10);  // parameters[0] is the xtal samples
0034   parameters.push_back(1);   // parameters[1] is the number of trigger time samples for TPG's
0035   parameters.push_back(68);  // parameters[2] is the number of TT
0036   parameters.push_back(68);  // parameters[3] is the number of SR Flags
0037   parameters.push_back(1);   // parameters[4] is the dcc id
0038   parameters.push_back(1);   // parameters[5] is the sr id
0039   parameters.push_back(1);   // parameters[6] is the tcc1 id
0040   parameters.push_back(2);   // parameters[7] is the tcc2 id
0041   parameters.push_back(3);   // parameters[8] is the tcc3 id
0042   parameters.push_back(4);   // parameters[9] is the tcc4 id
0043 
0044   theParser_ = new DCCTBDataParser(parameters);
0045 }
0046 
0047 void EcalTBDaqFormatter::interpretRawData(const FEDRawData& fedData,
0048                                           EBDigiCollection& digicollection,
0049                                           EcalPnDiodeDigiCollection& pndigicollection,
0050                                           EcalRawDataCollection& DCCheaderCollection,
0051                                           EBDetIdCollection& dccsizecollection,
0052                                           EcalElectronicsIdCollection& ttidcollection,
0053                                           EcalElectronicsIdCollection& blocksizecollection,
0054                                           EBDetIdCollection& chidcollection,
0055                                           EBDetIdCollection& gaincollection,
0056                                           EBDetIdCollection& gainswitchcollection,
0057                                           EcalElectronicsIdCollection& memttidcollection,
0058                                           EcalElectronicsIdCollection& memblocksizecollection,
0059                                           EcalElectronicsIdCollection& memgaincollection,
0060                                           EcalElectronicsIdCollection& memchidcollection,
0061                                           EcalTrigPrimDigiCollection& tpcollection) {
0062   const unsigned char* pData = fedData.data();
0063   int length = fedData.size();
0064   bool shit = true;
0065   unsigned int tower = 0;
0066   int ch = 0;
0067   int strip = 0;
0068 
0069   LogDebug("EcalTBRawToDigi") << "@SUB=EcalTBDaqFormatter::interpretRawData"
0070                               << "size " << length;
0071 
0072   // mean + 3sigma estimation needed when switching to 0suppressed data
0073   digicollection.reserve(kCrystals);
0074   pnAllocated = false;
0075 
0076   theParser_->parseBuffer(reinterpret_cast<const uint32_t*>(pData), static_cast<uint32_t>(length), shit);
0077 
0078   std::vector<DCCTBEventBlock*>& dccEventBlocks = theParser_->dccEvents();
0079 
0080   // Access each DCCTB block
0081   for (std::vector<DCCTBEventBlock*>::iterator itEventBlock = dccEventBlocks.begin();
0082        itEventBlock != dccEventBlocks.end();
0083        itEventBlock++) {
0084     bool _displayParserMessages = false;
0085     if ((*itEventBlock)->eventHasErrors() && _displayParserMessages) {
0086       edm::LogWarning("EcalTBRawToDigi") << "@SUB=EcalTBDaqFormatter::interpretRawData"
0087                                          << "errors found from parser... ";
0088       edm::LogWarning("EcalTBRawToDigi") << (*itEventBlock)->eventErrorString();
0089       edm::LogWarning("EcalTBRawToDigi") << "@SUB=EcalTBDaqFormatter::interpretRawData"
0090                                          << "... errors from parser notified";
0091     }
0092 
0093     // getting the fields of the DCC header
0094     EcalDCCHeaderBlock theDCCheader;
0095 
0096     theDCCheader.setId(28);  // tb unpacker: forced to 28 to get first geom slot in EB
0097     int fedId = (*itEventBlock)->getDataField("FED/DCC ID");
0098     theDCCheader.setFedId(fedId);  // fed id as found in raw data (0... 35 at tb )
0099 
0100     theDCCheader.setRunNumber((*itEventBlock)->getDataField("RUN NUMBER"));
0101     short trigger_type = (*itEventBlock)->getDataField("TRIGGER TYPE");
0102     short zs = (*itEventBlock)->getDataField("ZS");
0103     short tzs = (*itEventBlock)->getDataField("TZS");
0104     short sr = (*itEventBlock)->getDataField("SR");
0105     bool dataIsSuppressed;
0106 
0107     // if zs&&tzs the suppression algo is used in DCC, the data are not suppressed and zs-bits are set
0108     if (zs && !(tzs))
0109       dataIsSuppressed = true;
0110     else
0111       dataIsSuppressed = false;
0112 
0113     if (trigger_type > 0 && trigger_type < 5) {
0114       theDCCheader.setBasicTriggerType(trigger_type);
0115     } else {
0116       edm::LogWarning("EcalTBRawToDigiTriggerType") << "@SUB=EcalTBDaqFormatter::interpretRawData"
0117                                                     << "unrecognized TRIGGER TYPE: " << trigger_type;
0118     }
0119     theDCCheader.setLV1((*itEventBlock)->getDataField("LV1"));
0120     theDCCheader.setOrbit((*itEventBlock)->getDataField("ORBIT COUNTER"));
0121     theDCCheader.setBX((*itEventBlock)->getDataField("BX"));
0122     theDCCheader.setErrors((*itEventBlock)->getDataField("DCC ERRORS"));
0123     theDCCheader.setSelectiveReadout(sr);
0124     theDCCheader.setZeroSuppression(zs);
0125     theDCCheader.setTestZeroSuppression(tzs);
0126     theDCCheader.setSrpStatus((*itEventBlock)->getDataField("SR_CHSTATUS"));
0127 
0128     std::vector<short> theTCCs;
0129     for (int i = 0; i < MAX_TCC_SIZE; i++) {
0130       char TCCnum[20];
0131       sprintf(TCCnum, "TCC_CHSTATUS#%d", i + 1);
0132       std::string TCCnumS(TCCnum);
0133       theTCCs.push_back((*itEventBlock)->getDataField(TCCnumS));
0134     }
0135     theDCCheader.setTccStatus(theTCCs);
0136 
0137     std::vector<DCCTBTCCBlock*> tccBlocks = (*itEventBlock)->tccBlocks();
0138 
0139     for (std::vector<DCCTBTCCBlock*>::iterator itTCCBlock = tccBlocks.begin(); itTCCBlock != tccBlocks.end();
0140          itTCCBlock++) {
0141       std::vector<std::pair<int, bool> > TpSamples = (*itTCCBlock)->triggerSamples();
0142       // std::vector of 3 bits
0143       std::vector<int> TpFlags = (*itTCCBlock)->triggerFlags();
0144 
0145       // there have always to be 68 primitives and flags, per FED
0146       if (TpSamples.size() == 68 && TpFlags.size() == 68) {
0147         for (int i = 0; i < ((int)TpSamples.size()); i++) {
0148           int etaTT = (i) / kTowersInPhi + 1;
0149           int phiTT = (i) % kTowersInPhi + 1;
0150 
0151           // follow HB convention in iphi
0152           phiTT = 3 - phiTT;
0153           if (phiTT <= 0)
0154             phiTT = phiTT + 72;
0155 
0156           EcalTriggerPrimitiveSample theSample(TpSamples[i].first, TpSamples[i].second, TpFlags[i]);
0157 
0158           EcalTrigTowerDetId idtt(1, EcalBarrel, etaTT, phiTT, 0);
0159 
0160           EcalTriggerPrimitiveDigi thePrimitive(idtt);
0161           thePrimitive.setSize(1);  // hard coded
0162           thePrimitive.setSample(0, theSample);
0163 
0164           tpcollection.push_back(thePrimitive);
0165 
0166           LogDebug("EcalTBRawToDigiTpg") << "@SUBS=EcalTBDaqFormatter::interpretRawData"
0167                                          << "tower: " << (i + 1) << " primitive: " << TpSamples[i].first
0168                                          << " flag: " << TpSamples[i].second;
0169 
0170           LogDebug("EcalTBRawToDigiTpg") << "@SUBS=EcalTBDaqFormatter::interpretRawData"
0171                                          << "tower: " << (i + 1) << " flag: " << TpFlags[i];
0172         }  // end loop on tower primitives
0173 
0174       }  // end if
0175       else {
0176         edm::LogWarning("EcalTBRawToDigiTpg")
0177             << "68 elements not found for TpFlags or TpSamples, collection will be empty";
0178       }
0179     }
0180 
0181     short TowerStatus[MAX_TT_SIZE + 1];
0182     char buffer[25];
0183     std::vector<short> theTTstatus;
0184     for (int i = 1; i < MAX_TT_SIZE + 1; i++) {
0185       sprintf(buffer, "FE_CHSTATUS#%d", i);
0186       std::string Tower(buffer);
0187       TowerStatus[i] = (*itEventBlock)->getDataField(Tower);
0188       theTTstatus.push_back(TowerStatus[i]);
0189       //std::cout << "tower " << i << " has status " <<  TowerStatus[i] << std::endl;
0190     }
0191 
0192     theDCCheader.setFEStatus(theTTstatus);
0193 
0194     EcalDCCTBHeaderRuntypeDecoder theRuntypeDecoder;
0195     uint32_t DCCruntype = (*itEventBlock)->getDataField("RUN TYPE");
0196     theRuntypeDecoder.Decode(DCCruntype, &theDCCheader);
0197     //DCCHeader filled!
0198     DCCheaderCollection.push_back(theDCCheader);
0199 
0200     std::vector<DCCTBTowerBlock*> dccTowerBlocks = (*itEventBlock)->towerBlocks();
0201     LogDebug("EcalTBRawToDigi") << "@SUBS=EcalTBDaqFormatter::interpretRawData"
0202                                 << "dccTowerBlocks size " << dccTowerBlocks.size();
0203 
0204     _expTowersIndex = 0;
0205     _numExpectedTowers = 0;
0206     for (int v = 0; v < 71; v++) {
0207       _ExpectedTowers[v] = 99999;
0208     }
0209 
0210     // note: these are the tower statuses handled at the moment - to be completed
0211     // staus==0:   tower expected;
0212     // staus==9:   Synk error LV1, tower expected;
0213     // staus==10:  Synk error BX, tower expected;
0214     // status==1, 2, 3, 4, 5:  tower not expected
0215     for (int u = 1; u < (kTriggerTowersAndMem + 1); u++) {
0216       if (TowerStatus[u] == 0 || TowerStatus[u] == 9 || TowerStatus[u] == 10) {
0217         _ExpectedTowers[_expTowersIndex] = u;
0218         _expTowersIndex++;
0219         _numExpectedTowers++;
0220       }
0221     }
0222     // resetting counter of expected towers
0223     _expTowersIndex = 0;
0224 
0225     // if number of dccEventBlocks NOT same as expected stop
0226     if (!(dccTowerBlocks.size() == _numExpectedTowers)) {
0227       // we probably always want to know if this happens
0228       edm::LogWarning("EcalTBRawToDigiNumTowerBlocks")
0229           << "@SUB=EcalTBDaqFormatter::interpretRawData"
0230           << "number of TowerBlocks found (" << dccTowerBlocks.size() << ") differs from expected ("
0231           << _numExpectedTowers << ") skipping event";
0232 
0233       EBDetId idsm(1, 1);
0234       dccsizecollection.push_back(idsm);
0235 
0236       return;
0237     }
0238 
0239     // Access the Tower block
0240     for (std::vector<DCCTBTowerBlock*>::iterator itTowerBlock = dccTowerBlocks.begin();
0241          itTowerBlock != dccTowerBlocks.end();
0242          itTowerBlock++) {
0243       tower = (*itTowerBlock)->towerID();
0244 
0245       // checking if tt in data is the same as tt expected
0246       // else skip tower and increment problem counter
0247 
0248       // compute eta/phi in order to have iTT = _ExpectedTowers[_expTowersIndex]
0249       // for the time being consider only zside>0
0250 
0251       EcalElectronicsId idtt(28, _ExpectedTowers[_expTowersIndex], 1, 1);
0252 
0253       if (!(tower == _ExpectedTowers[_expTowersIndex])) {
0254         if (_ExpectedTowers[_expTowersIndex] <= 68) {
0255           edm::LogWarning("EcalTBRawToDigiTowerId")
0256               << "@SUBS=EcalTBDaqFormatter::interpretRawData"
0257               << "TTower id found (=" << tower << ") different from expected (=" << _ExpectedTowers[_expTowersIndex]
0258               << ") " << (_expTowersIndex + 1) << "-th tower checked";
0259 
0260           //  report on failed tt_id for regular tower block
0261           ttidcollection.push_back(idtt);
0262         } else {
0263           edm::LogWarning("EcalTBRawToDigiTowerId")
0264               << "@SUB=EcalTBDaqFormatter:interpretRawData"
0265               << "DecodeMEM: tower " << tower << " is not the same as expected "
0266               << ((int)_ExpectedTowers[_expTowersIndex]) << " (according to DCC header channel status)";
0267 
0268           // report on failed tt_id for mem tower block
0269           // chosing channel 1 as representative
0270           EcalElectronicsId id(1, (int)_ExpectedTowers[_expTowersIndex], 1, 1);
0271           memttidcollection.push_back(id);
0272         }
0273 
0274         ++_expTowersIndex;
0275         continue;
0276       }  // if TT id found  different than expected
0277 
0278       /*********************************
0279        //    tt: 1 ... 68: crystal data
0280        *********************************/
0281       if (0 < (*itTowerBlock)->towerID() && (*itTowerBlock)->towerID() < (kTriggerTowers + 1)) {
0282         std::vector<DCCTBXtalBlock*>& xtalDataBlocks = (*itTowerBlock)->xtalBlocks();
0283 
0284         // if there is no zero suppression, tower block must have have 25 channels in it
0285         if ((!dataIsSuppressed) && (xtalDataBlocks.size() != kChannelsPerTower)) {
0286           edm::LogWarning("EcalTBRawToDigiTowerSize")
0287               << "EcalTBDaqFormatter::interpretRawData, no zero suppression "
0288               << "wrong tower block size is: " << xtalDataBlocks.size() << " at LV1 "
0289               << (*itEventBlock)->getDataField("LV1") << " for TT " << _ExpectedTowers[_expTowersIndex];
0290           // report on wrong tt block size
0291           blocksizecollection.push_back(idtt);
0292 
0293           ++_expTowersIndex;
0294           continue;
0295         }
0296 
0297         short cryInTower = 0;
0298 
0299         short expStripInTower;
0300         short expCryInStrip;
0301         short expCryInTower = 0;
0302 
0303         // Access the Xstal data
0304         for (std::vector<DCCTBXtalBlock*>::iterator itXtalBlock = xtalDataBlocks.begin();
0305              itXtalBlock != xtalDataBlocks.end();
0306              itXtalBlock++) {  //loop on crys of a  tower
0307 
0308           strip = (*itXtalBlock)->stripID();
0309           ch = (*itXtalBlock)->xtalID();
0310           cryInTower = (strip - 1) * kChannelsPerCard + (ch - 1);
0311 
0312           expStripInTower = expCryInTower / 5 + 1;
0313           expCryInStrip = expCryInTower % 5 + 1;
0314 
0315           // FIXME: waiting for geometry to do (TT, strip,chNum) <--> (SMChId)
0316           // short abscissa = (_ExpectedTowers[_expTowersIndex]-1)  /4;
0317           // short ordinate = (_ExpectedTowers[_expTowersIndex]-1)  %4;
0318           // temporarily choosing central crystal in trigger tower
0319           // int cryIdInSM  = 45 + ordinate*5 + abscissa * 100;
0320 
0321           // in case of 0 zuppressed data, check that cryInTower constantly grows
0322           if (dataIsSuppressed) {
0323             if (strip < 1 || 5 < strip || ch < 1 || 5 < ch) {
0324               int sm = 1;  // hardcoded because of test  beam
0325               for (int StripInTower_ = 1; StripInTower_ < 6; StripInTower_++) {
0326                 for (int CryInStrip_ = 1; CryInStrip_ < 6; CryInStrip_++) {
0327                   int ic = cryIc(tower, StripInTower_, CryInStrip_);
0328                   EBDetId idExp(sm, ic, 1);
0329                   chidcollection.push_back(idExp);
0330                 }
0331               }
0332 
0333               edm::LogWarning("EcalTBRawToDigiChId")
0334                   << "EcalTBDaqFormatter::interpretRawData with zero suppression, "
0335                   << " wrong channel id, since out of range: "
0336                   << "\t strip: " << strip << "\t channel: " << ch << "\t in TT: " << _ExpectedTowers[_expTowersIndex]
0337                   << "\t at LV1 : " << (*itEventBlock)->getDataField("LV1");
0338 
0339               expCryInTower++;
0340               continue;
0341             }
0342 
0343             // correct ordering
0344             if (cryInTower >= expCryInTower) {
0345               expCryInTower = cryInTower + 1;
0346             }
0347 
0348             // cry_id wrong because of incorrect ordering within trigger tower
0349             else {
0350               edm::LogWarning("EcalTBRawToDigiChId")
0351                   << "EcalTBDaqFormatter::interpretRawData with zero suppression, "
0352                   << " based on ch ordering within tt, wrong channel id: "
0353                   << "\t strip: " << strip << "\t channel: " << ch << "\t cryInTower " << cryInTower
0354                   << "\t expCryInTower: " << expCryInTower << "\t in TT: " << _ExpectedTowers[_expTowersIndex]
0355                   << "\t at LV1: " << (*itEventBlock)->getDataField("LV1");
0356 
0357               int sm = 1;  // hardcoded because of test  beam
0358               for (int StripInTower_ = 1; StripInTower_ < 6; StripInTower_++) {
0359                 for (int CryInStrip_ = 1; CryInStrip_ < 6; CryInStrip_++) {
0360                   int ic = cryIc(tower, StripInTower_, CryInStrip_);
0361                   EBDetId idExp(sm, ic, 1);
0362                   chidcollection.push_back(idExp);
0363                 }
0364               }
0365 
0366               // chennel with id which does not follow correct odering
0367               expCryInTower++;
0368               continue;
0369 
0370             }  // end 'ch_id does not respect growing order'
0371 
0372           }  // end   if zero supression
0373 
0374           else {
0375             // checking that ch and strip are within range and cryInTower is as expected
0376             if (cryInTower != expCryInTower || strip < 1 || kStripsPerTower < strip || ch < 1 ||
0377                 kChannelsPerStrip < ch) {
0378               int ic = cryIc(tower, expStripInTower, expCryInStrip);
0379               int sm = 1;  // hardcoded because of test  beam
0380               EBDetId idExp(sm, ic, 1);
0381 
0382               edm::LogWarning("EcalTBRawToDigiChId")
0383                   << "EcalTBDaqFormatter::interpretRawData no zero suppression "
0384                   << " wrong channel id for channel: " << expCryInStrip << "\t strip: " << expStripInTower
0385                   << "\t in TT: " << _ExpectedTowers[_expTowersIndex]
0386                   << "\t at LV1: " << (*itEventBlock)->getDataField("LV1")
0387                   << "\t   (in the data, found channel:  " << ch << "\t strip:  " << strip << " ).";
0388 
0389               // report on wrong channel id
0390               chidcollection.push_back(idExp);
0391 
0392               // there has been unexpected crystal id, dataframe not to go to the Event
0393               expCryInTower++;
0394               continue;
0395 
0396             }  // if channel in data does not equal expected channel
0397 
0398             expCryInTower++;
0399 
0400           }  // end 'not zero suppression'
0401 
0402           // data  to be stored in EBDataFrame, identified by EBDetId
0403           int ic = cryIc(tower, strip, ch);
0404           int sm = 1;
0405           EBDetId id(sm, ic, 1);
0406 
0407           // here data frame go into the Event
0408           // removed later on (with a pop_back()) if gain==0 or if forbidden-gain-switch
0409           digicollection.push_back(id);
0410           EBDataFrame theFrame(digicollection.back());
0411           std::vector<int> xtalDataSamples = (*itXtalBlock)->xtalDataSamples();
0412           //theFrame.setSize(xtalDataSamples.size()); // if needed, to be changed when constructing digicollection
0413 
0414           // gain cannot be 0, checking for that
0415           bool gainIsOk = true;
0416           unsigned gain_mask = 12288;  //12th and 13th bit
0417           std::vector<int> xtalGain;
0418 
0419           for (unsigned short i = 0; i < xtalDataSamples.size(); ++i) {
0420             theFrame.setSample(i, xtalDataSamples[i]);
0421 
0422             if ((xtalDataSamples[i] & gain_mask) == 0) {
0423               gainIsOk = false;
0424             }
0425 
0426             xtalGain.push_back(0);
0427             xtalGain[i] |= (xtalDataSamples[i] >> 12);
0428           }
0429 
0430           if (!gainIsOk) {
0431             edm::LogWarning("EcalTBRawToDigiGainZero")
0432                 << "@SUB=EcalTBDaqFormatter::interpretRawData"
0433                 << " gain==0 for strip: " << expStripInTower << "\t channel: " << expCryInStrip
0434                 << "\t in TT: " << _ExpectedTowers[_expTowersIndex] << "\t ic: " << ic
0435                 << "\t at LV1: " << (*itEventBlock)->getDataField("LV1");
0436             // report on gain==0
0437             gaincollection.push_back(id);
0438 
0439             // there has been a gain==0, dataframe not to go to the Event
0440             digicollection.pop_back();
0441             continue;  //         expCryInTower already incremented
0442           }
0443 
0444           // looking for forbidden gain transitions
0445 
0446           short firstGainWrong = -1;
0447           short numGainWrong = 0;
0448 
0449           for (unsigned short i = 0; i < xtalGain.size(); i++) {
0450             if (i > 0 && xtalGain[i - 1] > xtalGain[i]) {
0451               numGainWrong++;  // counting forbidden gain transitions
0452 
0453               if (firstGainWrong == -1) {
0454                 firstGainWrong = i;
0455                 edm::LogWarning("EcalTBRawToDigiGainSwitch")
0456                     << "@SUB=EcalTBDaqFormatter::interpretRawData"
0457                     << "channelHasGainSwitchProblem: crystal eta = " << id.ieta() << " phi = " << id.iphi();
0458               }
0459               edm::LogWarning("EcalTBRawToDigiGainSwitch")
0460                   << "@SUB=EcalTBDaqFormatter::interpretRawData"
0461                   << "channelHasGainSwitchProblem: sample = " << (i - 1) << " gain: " << xtalGain[i - 1]
0462                   << " sample: " << i << " gain: " << xtalGain[i];
0463             }
0464           }
0465 
0466           if (numGainWrong > 0) {
0467             gainswitchcollection.push_back(id);
0468 
0469             edm::LogWarning("EcalTBRawToDigiGainSwitch") << "@SUB=EcalTBDaqFormatter:interpretRawData"
0470                                                          << "channelHasGainSwitchProblem: more than 1 wrong transition";
0471 
0472             for (unsigned short i1 = 0; i1 < xtalDataSamples.size(); ++i1) {
0473               int countADC = 0x00000FFF;
0474               countADC &= xtalDataSamples[i1];
0475               LogDebug("EcalTBRawToDigi") << "Sample " << i1 << " ADC " << countADC << " Gain " << xtalGain[i1];
0476             }
0477 
0478             // there has been a forbidden gain transition,  dataframe not to go to the Event
0479             digicollection.pop_back();
0480             continue;  //         expCryInTower already incremented
0481 
0482           }  // END of:   'if there is a forbidden gain transition'
0483 
0484         }  // end loop on crystals within a tower block
0485 
0486         _expTowersIndex++;
0487       }  // end: tt1 ... tt68, crystal data
0488 
0489       /******************************************************************
0490        //    tt 69 and 70:  two mem boxes, holding PN0 ... PN9
0491        ******************************************************************/
0492       else if ((*itTowerBlock)->towerID() == 69 || (*itTowerBlock)->towerID() == 70) {
0493         LogDebug("EcalTBRawToDigi") << "@SUB=EcalTBDaqFormatter::interpretRawData"
0494                                     << "processing mem box num: " << (*itTowerBlock)->towerID();
0495 
0496         // if tt 69 or 70 found, allocate Pn digi collection
0497         if (!pnAllocated) {
0498           pndigicollection.reserve(kPns);
0499           pnAllocated = true;
0500         }
0501 
0502         DecodeMEM((*itTowerBlock),
0503                   pndigicollection,
0504                   memttidcollection,
0505                   memblocksizecollection,
0506                   memgaincollection,
0507                   memchidcollection);
0508 
0509       }  // end of < if it is a mem box>
0510 
0511       // wrong tt id
0512       else {
0513         edm::LogWarning("EcalTBRawToDigiTowerId")
0514             << "@SUB=EcalTBDaqFormatter::interpretRawData"
0515             << " processing tt with ID not existing ( " << (*itTowerBlock)->towerID() << ")";
0516         ++_expTowersIndex;
0517         continue;
0518       }  // end: tt id error
0519 
0520     }  // end loop on trigger towers
0521 
0522   }  // end loop on events
0523 }
0524 
0525 void EcalTBDaqFormatter::DecodeMEM(DCCTBTowerBlock* towerblock,
0526                                    EcalPnDiodeDigiCollection& pndigicollection,
0527                                    EcalElectronicsIdCollection& memttidcollection,
0528                                    EcalElectronicsIdCollection& memblocksizecollection,
0529                                    EcalElectronicsIdCollection& memgaincollection,
0530                                    EcalElectronicsIdCollection& memchidcollection) {
0531   LogDebug("EcalTBRawToDigi") << "@SUB=EcalTBDaqFormatter::DecodeMEM"
0532                               << "in mem " << towerblock->towerID();
0533 
0534   int tower_id = towerblock->towerID();
0535   int mem_id = tower_id - 69;
0536 
0537   // initializing container
0538   for (int st_id = 0; st_id < kStripsPerTower; st_id++) {
0539     for (int ch_id = 0; ch_id < kChannelsPerStrip; ch_id++) {
0540       for (int sa = 0; sa < 11; sa++) {
0541         memRawSample_[st_id][ch_id][sa] = -1;
0542       }
0543     }
0544   }
0545 
0546   // check that tower block id corresponds to mem boxes
0547   if (tower_id != 69 && tower_id != 70) {
0548     edm::LogWarning("EcalTBRawToDigiTowerId") << "@SUB=EcalTBDaqFormatter:decodeMem"
0549                                               << "DecodeMEM: this is not a mem box tower (" << tower_id << ")";
0550     ++_expTowersIndex;
0551     return;
0552   }
0553 
0554   /******************************************************************************
0555    // getting the raw hits from towerBlock while checking tt and ch data structure 
0556    ******************************************************************************/
0557   std::vector<DCCTBXtalBlock*>& dccXtalBlocks = towerblock->xtalBlocks();
0558   std::vector<DCCTBXtalBlock*>::iterator itXtal;
0559 
0560   // checking mem tower block fo size
0561   if (dccXtalBlocks.size() != kChannelsPerTower) {
0562     LogDebug("EcalTBRawToDigiDccBlockSize")
0563         << "@SUB=EcalTBDaqFormatter:decodeMem"
0564         << " wrong dccBlock size, namely: " << dccXtalBlocks.size() << ", for mem " << _ExpectedTowers[_expTowersIndex];
0565 
0566     // reporting mem-tt block size problem
0567     // chosing channel 1 as representative as a dummy...
0568     EcalElectronicsId id(1, (int)_ExpectedTowers[_expTowersIndex], 1, 1);
0569     memblocksizecollection.push_back(id);
0570 
0571     ++_expTowersIndex;
0572     return;  // if mem tt block size not ok - do not build any Pn digis
0573   }
0574 
0575   // loop on channels of the mem block
0576   int cryCounter = 0;
0577   int strip_id = 0;
0578   int xtal_id = 0;
0579 
0580   for (itXtal = dccXtalBlocks.begin(); itXtal < dccXtalBlocks.end(); itXtal++) {
0581     strip_id = (*itXtal)->getDataField("STRIP ID");
0582     xtal_id = (*itXtal)->getDataField("XTAL ID");
0583     int wished_strip_id = cryCounter / kStripsPerTower;
0584     int wished_ch_id = cryCounter % kStripsPerTower;
0585 
0586     if ((wished_strip_id + 1) != ((int)strip_id) || (wished_ch_id + 1) != ((int)xtal_id)) {
0587       LogDebug("EcalTBRawToDigiChId") << "@SUB=EcalTBDaqFormatter:decodeMem"
0588                                       << " in mem " << towerblock->towerID() << ", expected:\t strip"
0589                                       << (wished_strip_id + 1) << " cry " << (wished_ch_id + 1) << "\tfound: "
0590                                       << "  strip " << strip_id << "  cry " << xtal_id;
0591 
0592       // report on crystal with unexpected indices
0593       EcalElectronicsId id(1, (int)_ExpectedTowers[_expTowersIndex], wished_strip_id, wished_ch_id);
0594       memchidcollection.push_back(id);
0595     }
0596 
0597     // Accessing the 10 time samples per Xtal:
0598     memRawSample_[wished_strip_id][wished_ch_id][1] = (*itXtal)->getDataField("ADC#1");
0599     memRawSample_[wished_strip_id][wished_ch_id][2] = (*itXtal)->getDataField("ADC#2");
0600     memRawSample_[wished_strip_id][wished_ch_id][3] = (*itXtal)->getDataField("ADC#3");
0601     memRawSample_[wished_strip_id][wished_ch_id][4] = (*itXtal)->getDataField("ADC#4");
0602     memRawSample_[wished_strip_id][wished_ch_id][5] = (*itXtal)->getDataField("ADC#5");
0603     memRawSample_[wished_strip_id][wished_ch_id][6] = (*itXtal)->getDataField("ADC#6");
0604     memRawSample_[wished_strip_id][wished_ch_id][7] = (*itXtal)->getDataField("ADC#7");
0605     memRawSample_[wished_strip_id][wished_ch_id][8] = (*itXtal)->getDataField("ADC#8");
0606     memRawSample_[wished_strip_id][wished_ch_id][9] = (*itXtal)->getDataField("ADC#9");
0607     memRawSample_[wished_strip_id][wished_ch_id][10] = (*itXtal)->getDataField("ADC#10");
0608 
0609     cryCounter++;
0610   }  // end loop on crystals of mem dccXtalBlock
0611 
0612   // tower accepted and digi read from all 25 channels.
0613   // Increase counter of expected towers before unpacking in the 5 PNs
0614   ++_expTowersIndex;
0615 
0616   /************************************************************
0617    // unpacking and 'cooking' the raw numbers to get PN sample
0618    ************************************************************/
0619   int tempSample = 0;
0620   int memStoreIndex = 0;
0621   int ipn = 0;
0622   for (memStoreIndex = 0; memStoreIndex < 500; memStoreIndex++) {
0623     data_MEM[memStoreIndex] = -1;
0624   }
0625 
0626   for (int strip = 0; strip < kStripsPerTower; strip++) {            // loop on strips
0627     for (int channel = 0; channel < kChannelsPerStrip; channel++) {  // loop on channels
0628 
0629       if (strip % 2 == 0) {
0630         ipn = mem_id * 5 + channel;
0631       } else {
0632         ipn = mem_id * 5 + 4 - channel;
0633       }
0634 
0635       for (int sample = 0; sample < kSamplesPerChannel; sample++) {
0636         tempSample = memRawSample_[strip][channel][sample + 1];
0637 
0638         int new_data = 0;
0639         if (strip % 2 == 1) {
0640           // 1) if strip number is even, 14 bits are reversed in order
0641           for (int ib = 0; ib < 14; ib++) {
0642             new_data <<= 1;
0643             new_data = new_data | (tempSample & 1);
0644             tempSample >>= 1;
0645           }
0646         } else {
0647           new_data = tempSample;
0648         }
0649 
0650         // 2) flip 11th bit for AD9052 still there on MEM !
0651         // 3) mask with 1 1111 1111 1111
0652         new_data = (new_data ^ 0x800) & 0x3fff;  // (new_data  XOR 1000 0000 0000) & 11 1111 1111 1111
0653         // new_data = (new_data ^ 0x800) & 0x1fff;    // (new_data  XOR 1000 0000 0000) & 1 1111 1111 1111
0654 
0655         //(Bit 12) == 1 -> Gain 16;    (Bit 12) == 0 -> Gain 1
0656         // gain in mem can be 1 or 16 encoded resp. with 0 ir 1 in the 13th bit.
0657         // checking and reporting if there is any sample with gain==2,3
0658         short sampleGain = (new_data & 0x3000) / 4096;
0659         if (sampleGain == 2 || sampleGain == 3) {
0660           EcalElectronicsId id(1, (int)_ExpectedTowers[_expTowersIndex], strip, channel);
0661           memgaincollection.push_back(id);
0662 
0663           edm::LogWarning("EcalTBRawToDigiGainZero")
0664               << "@SUB=EcalTBDaqFormatter:decodeMem"
0665               << "in mem " << towerblock->towerID() << " :\t strip: " << (strip + 1) << " cry: " << (channel + 1)
0666               << " has 14th bit non zero! Gain results: " << sampleGain << ".";
0667 
0668           continue;
0669         }  // end 'if gain is zero'
0670 
0671         memStoreIndex = ipn * 50 + strip * kSamplesPerChannel + sample;
0672         // storing in data_MEM also the gain bits
0673         data_MEM[memStoreIndex] = new_data & 0x3fff;
0674 
0675       }  // loop on samples
0676     }    // loop on strips
0677   }      // loop on channels
0678 
0679   for (int pnId = 0; pnId < kPnPerTowerBlock; pnId++)
0680     pnIsOkInBlock[pnId] = true;
0681   // if anything was wrong with mem_tt_id or mem_tt_size: you would have already exited
0682   // otherwise, if any problem with ch_gain or ch_id: must not produce digis for the pertaining Pn
0683 
0684   if (!(memgaincollection.empty() && memchidcollection.empty())) {
0685     for (EcalElectronicsIdCollection::const_iterator idItr = memgaincollection.begin();
0686          idItr != memgaincollection.end();
0687          ++idItr) {
0688       int ch = (*idItr).channelId();
0689       ch = (ch - 1) / 5;
0690       pnIsOkInBlock[ch] = false;
0691     }
0692 
0693     for (EcalElectronicsIdCollection::const_iterator idItr = memchidcollection.begin();
0694          idItr != memchidcollection.end();
0695          ++idItr) {
0696       int ch = (*idItr).channelId();
0697       ch = (ch - 1) / 5;
0698       pnIsOkInBlock[ch] = false;
0699     }
0700 
0701   }  // end: if any ch_gain or ch_id problems exclude the Pn's from digi production
0702 
0703   // looping on PN's of current mem box
0704   for (int pnId = 1; pnId < (kPnPerTowerBlock + 1); pnId++) {
0705     // if present Pn has any of its 5 channels with problems, do not produce digi for it
0706     if (!pnIsOkInBlock[pnId - 1])
0707       continue;
0708 
0709     // DccId set to 28 to be consistent with ism==1
0710     EcalPnDiodeDetId PnId(1, 28, pnId + kPnPerTowerBlock * mem_id);
0711     EcalPnDiodeDigi thePnDigi(PnId);
0712 
0713     thePnDigi.setSize(kSamplesPerPn);
0714 
0715     for (int sample = 0; sample < kSamplesPerPn; sample++) {
0716       EcalFEMSample thePnSample(data_MEM[(mem_id)*250 + (pnId - 1) * kSamplesPerPn + sample]);
0717       thePnDigi.setSample(sample, thePnSample);
0718     }
0719     pndigicollection.push_back(thePnDigi);
0720   }
0721 }
0722 
0723 std::pair<int, int> EcalTBDaqFormatter::cellIndex(int tower_id, int strip, int ch) {
0724   int xtal = (strip - 1) * 5 + ch - 1;
0725   //  std::cout << " cellIndex input xtal " << xtal << std::endl;
0726   std::pair<int, int> ind;
0727 
0728   int eta = (tower_id - 1) / kTowersInPhi * kCardsPerTower;
0729   int phi = (tower_id - 1) % kTowersInPhi * kChannelsPerCard;
0730 
0731   if (rightTower(tower_id))
0732     eta += xtal / kCardsPerTower;
0733   else
0734     eta += (kCrystalsPerTower - 1 - xtal) / kCardsPerTower;
0735 
0736   if ((rightTower(tower_id) && (xtal / kCardsPerTower) % 2 == 1) ||
0737       (!rightTower(tower_id) && (xtal / kCardsPerTower) % 2 == 0))
0738 
0739     phi += (kChannelsPerCard - 1 - xtal % kChannelsPerCard);
0740   else
0741     phi += xtal % kChannelsPerCard;
0742 
0743   ind.first = eta + 1;
0744   ind.second = phi + 1;
0745 
0746   //  std::cout << "  EcalTBDaqFormatter::cell_index eta " << ind.first << " phi " << ind.second << " " << std::endl;
0747 
0748   return ind;
0749 }
0750 
0751 int EcalTBDaqFormatter::cryIc(int tower, int strip, int ch) {
0752   if (strip < 1 || 5 < strip || ch < 1 || 5 < ch || 68 < tower) {
0753     edm::LogWarning("EcalTBRawToDigiChId") << "EcalTBDaqFormatter::interpretRawData (cryIc) "
0754                                            << " wrong channel id, since out of range: "
0755                                            << "\t strip: " << strip << "\t channel: " << ch << "\t in TT: " << tower;
0756     return -1;
0757   }
0758 
0759   std::pair<int, int> cellInd = EcalTBDaqFormatter::cellIndex(tower, strip, ch);
0760   return cellInd.second + (cellInd.first - 1) * kCrystalsInPhi;
0761 }
0762 
0763 bool EcalTBDaqFormatter::rightTower(int tower) const {
0764   if ((tower > 12 && tower < 21) || (tower > 28 && tower < 37) || (tower > 44 && tower < 53) ||
0765       (tower > 60 && tower < 69))
0766     return true;
0767   else
0768     return false;
0769 }
0770 
0771 bool EcalTBDaqFormatter::leftTower(int tower) const { return !rightTower(tower); }