Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:08:04

0001 // -*- Mode: C++; c-basic-offset: 8;  -*-
0002 #include "Geometry/EcalMapping/interface/EcalElectronicsMapping.h"
0003 #include "DataFormats/EcalDetId/interface/EEDetId.h"
0004 #include "DataFormats/EcalDetId/interface/EBDetId.h"
0005 #include "DataFormats/EcalDetId/interface/EcalTrigTowerDetId.h"
0006 
0007 #include "DataFormats/EcalDetId/interface/EcalElectronicsId.h"
0008 #include "DataFormats/EcalDetId/interface/EcalTriggerElectronicsId.h"
0009 
0010 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0011 #include "FWCore/Utilities/interface/Exception.h"
0012 #include <cassert>
0013 
0014 using boost::multi_index_container;
0015 using namespace boost::multi_index;
0016 
0017 // -----------------------------------------------------------------------
0018 //
0019 // -- Conventions :
0020 //
0021 //    DCCid and TCCid numbering : cf slides of Ph. Gras :
0022 //     in EE- : DCCid between 1 and 8.
0023 //              DCCid number 1 covers the range -30 deg < phi < 10 deg.
0024 //     in EB- : DCCid between 10 and 27.
0025 //          DCCid number 10 covers the range -10 deg < phi < 10 deg.
0026 //     in EB+:  DCCid between 28 and 45.
0027 //              DCCid number 28 covers the range -10 deg < phi < 10 deg.
0028 //     in EE+:  DCCid between 46 and 54;
0029 //          DCCid number 46 covers the range -30 deg < phi < 10 deg.
0030 //
0031 //    SMid : 1-18 correspond to EB+   (SMid 1 corresponds to DCC 28)
0032 //           19-36 correspond to EB-
0033 //
0034 // ------------------------------------------------------------------------
0035 
0036 EcalElectronicsMapping::EcalElectronicsMapping() {
0037   // Fill the map (Barrel) for the Laser Monitoring readout numbers :
0038   // Each DCC actually corresponds to 2 LMs,  ilm and ilm + 1
0039 
0040   int ilm = MIN_LM_EBM;
0041   for (int dcc = MIN_DCCID_EBM; dcc <= MAX_DCCID_EBM; dcc++) {
0042     LaserMonitoringMap_EB[dcc] = ilm;
0043     ilm += 2;
0044   }
0045   ilm = MIN_LM_EBP;
0046   for (int dcc = MIN_DCCID_EBP; dcc <= MAX_DCCID_EBP; dcc++) {
0047     LaserMonitoringMap_EB[dcc] = ilm;
0048     ilm += 2;
0049   }
0050 
0051   // Fill the map (EndCap) for the Laser Monitoring readout numbers :
0052   // Each DCC corresponds to onr LM, but DCC 8 (LM 80 and 81) and DCC 53 (LM 90 and 91)
0053 
0054   ilm = MIN_LM_EEM;
0055   for (int dcc = MIN_DCCID_EEM; dcc <= MAX_DCCID_EEM; dcc++) {
0056     LaserMonitoringMap_EE[dcc] = ilm;
0057     ilm += 1;
0058     if (dcc == 8)
0059       ilm += 1;
0060   }
0061   ilm = MIN_LM_EEP;
0062   for (int dcc = MIN_DCCID_EEP; dcc <= MAX_DCCID_EEP; dcc++) {
0063     LaserMonitoringMap_EE[dcc] = ilm;
0064     ilm += 1;
0065     if (dcc == 53)
0066       ilm += 1;
0067   }
0068 }
0069 
0070 int EcalElectronicsMapping::DCCid(const EBDetId& id) const
0071 
0072 // SM id, between 1 (phi = -10 deg) and 18 in EB+
0073 // between 19 (phi = -10 deg) and 27 in EB-.
0074 // returns DCCid, currently between 10 and 27 (EB-), 28 and 45 (EB+).
0075 // For the EE case, use getElectronicsId.
0076 {
0077   int dcc = id.ism();
0078   if (id.zside() < 0) {
0079     dcc += DCCID_PHI0_EBM - 19;
0080   } else {
0081     dcc += DCCID_PHI0_EBP - 1;
0082   }
0083   return dcc;
0084 }
0085 
0086 int EcalElectronicsMapping::TCCid(const EBDetId& id) const
0087 
0088 // SM id, between 1 (phi = -10 deg) and 18 in EB+
0089 // between 19 (phi = -10 deg) and 27 in EB-.
0090 // returns TCCid, currently between 37 and 54 (EB-), 55 and 72 (EB+).
0091 // For the EE case, use getEcalTriggerElectronicsId.
0092 {
0093   int tcc = id.ism();
0094   if (id.zside() < 0) {
0095     tcc += TCCID_PHI0_EBM - 19;
0096   } else {
0097     tcc += TCCID_PHI0_EBP - 1;
0098   }
0099   return tcc;
0100 }
0101 
0102 int EcalElectronicsMapping::iTT(const EcalTrigTowerDetId& id) const
0103 
0104 // returns the index of a Trigger Tower within its TCC.
0105 // This is between 1 and 68 for the Barrel, and between
0106 // 1 and 32 to 34 (t.b.c.) for the EndCap.
0107 
0108 {
0109   if (id.subDet() == EcalBarrel) {
0110     int ie = id.ietaAbs() - 1;
0111     int ip;
0112     int phi = id.iphi();
0113     phi += 2;
0114     if (phi > 72)
0115       phi = phi - 72;
0116     if (id.zside() < 0) {
0117       ip = ((phi - 1) % kEBTowersInPhi) + 1;
0118     } else {
0119       ip = kEBTowersInPhi - ((phi - 1) % kEBTowersInPhi);
0120     }
0121 
0122     return (ie * kEBTowersInPhi) + ip;
0123   } else if (id.subDet() == EcalEndcap) {
0124     int ie = id.ietaAbs();
0125     bool inner = (ie >= iEEEtaMinInner);
0126     if (inner) {
0127       ie = ie - iEEEtaMinInner;
0128       ie = ie % kEETowersInEtaPerInnerTCC;
0129     } else {
0130       ie = ie - iEEEtaMinOuter;
0131       ie = ie % kEETowersInEtaPerOuterTCC;
0132     }
0133 
0134     int ip = id.iphi();
0135     ip = (ip + 1) % (kEETowersInPhiPerQuadrant * 4);
0136     // now iphi between 0 and 71,
0137     // with iphi=0,1,2,3 in 1st Phi sector
0138     ip = ip % kEETowersInPhiPerTCC;
0139     int itt = kEETowersInPhiPerTCC * ie + ip + 1;
0140     return itt;
0141   } else {
0142     throw cms::Exception("InvalidDetId") << " Wrong EcalTrigTowerDetId in EcalElectronicsMapping::iTT. ";
0143     return 0;
0144   }
0145 }
0146 
0147 int EcalElectronicsMapping::TCCid(const EcalTrigTowerDetId& id) const {
0148   if (id.subDet() == EcalBarrel) {
0149     int phi = id.iphi() + 2;
0150     if (phi > 72)
0151       phi = phi - 72;
0152     int tcc = (phi - 1) / kEBTowersInPhi + 1;
0153     if (id.zside() < 0)
0154       tcc += 18;  // now id is the SMid
0155     if (id.zside() < 0) {
0156       tcc += TCCID_PHI0_EBM - 19;
0157     } else {
0158       tcc += TCCID_PHI0_EBP - 1;
0159     }
0160     return tcc;
0161   }
0162 
0163   else if (id.subDet() == EcalEndcap) {
0164     int ie = id.ietaAbs();
0165     bool inner = (ie >= iEEEtaMinInner);
0166     int ip = id.iphi();  // iphi = 1 corresponds to 0 < phi < 5 degrees
0167     ip = (ip + 1) % (kEETowersInPhiPerQuadrant * 4);
0168     // now iphi between 0 and 71,
0169     // with iphi=0,1,2,3 in 1st Phi sector
0170     int Phiindex = ip / 4;
0171     if (inner) {
0172       if (id.ieta() > 0)
0173         Phiindex += TCCID_PHI0_EEP_IN;
0174       else
0175         Phiindex += TCCID_PHI0_EEM_IN;
0176     } else {
0177       if (id.ieta() > 0)
0178         Phiindex += TCCID_PHI0_EEP_OUT;
0179       else
0180         Phiindex += TCCID_PHI0_EEM_OUT;
0181     }
0182     return Phiindex;
0183   } else {
0184     throw cms::Exception("InvalidDetId") << " Wrong EcalTrigTowerDetId in EcalElectronicsMapping::TCCid.";
0185     return 0;
0186   }
0187 }
0188 
0189 int EcalElectronicsMapping::DCCid(const EcalTrigTowerDetId& id) const {
0190   // This is needed for digitoraw. For a given Trigger Tower,
0191   // one needs to know to which FED it gets written.
0192 
0193   if (id.subDet() == EcalBarrel) {
0194     int phi = id.iphi() + 2;
0195     if (phi > 72)
0196       phi = phi - 72;
0197     int dcc = (phi - 1) / kEBTowersInPhi + 1;
0198     if (id.zside() < 0)
0199       dcc += 18;  // now id is the SMid
0200     if (id.zside() < 0) {
0201       dcc += DCCID_PHI0_EBM - 19;
0202     } else {
0203       dcc += DCCID_PHI0_EBP - 1;
0204     }
0205     return dcc;
0206   } else if (id.subDet() == EcalEndcap) {  //FIXME :  yes I need to improve this part of the code...
0207     int tccid = TCCid(id);
0208     int dcc = 0;
0209     int offset = 0;
0210     if (tccid >= 73) {
0211       tccid = tccid - 72;
0212       offset = 45;
0213     }
0214     if (tccid == 24 || tccid == 25 || tccid == 6 || tccid == 7)
0215       dcc = 4;
0216     if (tccid == 26 || tccid == 27 || tccid == 8 || tccid == 9)
0217       dcc = 5;
0218     if (tccid == 28 || tccid == 29 || tccid == 10 || tccid == 11)
0219       dcc = 6;
0220     if (tccid == 30 || tccid == 31 || tccid == 12 || tccid == 13)
0221       dcc = 7;
0222     if (tccid == 32 || tccid == 33 || tccid == 14 || tccid == 15)
0223       dcc = 8;
0224     if (tccid == 34 || tccid == 35 || tccid == 16 || tccid == 17)
0225       dcc = 9;
0226     if (tccid == 36 || tccid == 19 || tccid == 18 || tccid == 1)
0227       dcc = 1;
0228     if (tccid == 20 || tccid == 21 || tccid == 2 || tccid == 3)
0229       dcc = 2;
0230     if (tccid == 22 || tccid == 23 || tccid == 4 || tccid == 5)
0231       dcc = 3;
0232     dcc += offset;
0233     return dcc;
0234   } else {
0235     throw cms::Exception("InvalidDetId") << " Wrong EcalTrigTowerDetId in EcalElectronicsMapping::DCCid.";
0236     return 0;
0237   }
0238 }
0239 
0240 EcalTrigTowerDetId EcalElectronicsMapping::getTrigTowerDetId(int TCCid, int iTT) const {
0241   // needed for unpacking code.
0242 
0243   EcalSubdetector sub = subdet(TCCid, TCCMODE);
0244   int zIndex = zside(TCCid, TCCMODE);
0245 
0246   if (sub == EcalBarrel) {
0247     int DCCid = 0;
0248     int jtower = iTT - 1;
0249     if (zIndex > 0)
0250       DCCid = TCCid - TCCID_PHI0_EBP + DCCID_PHI0_EBP;
0251     else
0252       DCCid = TCCid - TCCID_PHI0_EBM + DCCID_PHI0_EBM;
0253     int SMid = (zIndex > 0) ? DCCid - 27 : DCCid + 9;
0254 
0255     int etaTT = jtower / kTowersInPhi + 1;  // between 1 and 17
0256     int phiTT;
0257 
0258     if (zIndex > 0)
0259       phiTT = (SMid - 1) * kTowersInPhi + (kTowersInPhi - (jtower % kTowersInPhi)) - 1;
0260     else
0261       phiTT = (SMid - 19) * kTowersInPhi + jtower % kTowersInPhi;
0262     phiTT++;
0263     phiTT = phiTT - 2;
0264     if (phiTT <= 0)
0265       phiTT = 72 + phiTT;
0266     EcalTrigTowerDetId tdetid(zIndex, EcalBarrel, etaTT, phiTT, EcalTrigTowerDetId::SUBDETIJMODE);
0267     return tdetid;
0268   }
0269 
0270   else if (sub == EcalEndcap) {
0271     bool EEminus = (zIndex < 0);
0272     bool EEplus = (zIndex > 0);
0273     if ((!EEminus) && (!EEplus))
0274       throw cms::Exception("InvalidDetId") << "EcalElectronicsMapping:  Cannot create EcalTrigTowerDetId object. ";
0275     int iz = 0;
0276     int tcc = TCCid;
0277     if (tcc < TCCID_PHI0_EEM_OUT + kTCCinPhi)
0278       iz = -1;
0279     else if (tcc >= TCCID_PHI0_EEP_OUT)
0280       iz = +1;
0281 
0282     bool inner = false;
0283     if (iz < 0 && tcc >= TCCID_PHI0_EEM_IN && tcc < TCCID_PHI0_EEM_IN + kTCCinPhi)
0284       inner = true;
0285     if (iz > 0 && tcc >= TCCID_PHI0_EEP_IN && tcc < TCCID_PHI0_EEP_IN + kTCCinPhi)
0286       inner = true;
0287     bool outer = !inner;
0288 
0289     int ieta = (iTT - 1) / kEETowersInPhiPerTCC;
0290     int iphi = (iTT - 1) % kEETowersInPhiPerTCC;
0291     if (inner)
0292       ieta += iEEEtaMinInner;
0293     else
0294       ieta += iEEEtaMinOuter;
0295     if (iz < 0)
0296       ieta = -ieta;
0297 
0298     int TCC_origin = 0;
0299     if (inner && iz < 0)
0300       TCC_origin = TCCID_PHI0_EEM_IN;
0301     if (outer && iz < 0)
0302       TCC_origin = TCCID_PHI0_EEM_OUT;
0303     if (inner && iz > 0)
0304       TCC_origin = TCCID_PHI0_EEP_IN;
0305     if (outer && iz > 0)
0306       TCC_origin = TCCID_PHI0_EEP_OUT;
0307     tcc = tcc - TCC_origin;
0308 
0309     iphi += kEETowersInPhiPerTCC * tcc;
0310     iphi = (iphi - 2 + 4 * kEETowersInPhiPerQuadrant) % (4 * kEETowersInPhiPerQuadrant) + 1;
0311 
0312     int tower_i = abs(ieta);
0313     int tower_j = iphi;
0314 
0315     EcalTrigTowerDetId tdetid(zIndex, EcalEndcap, tower_i, tower_j, EcalTrigTowerDetId::SUBDETIJMODE);
0316     return tdetid;
0317 
0318   } else {
0319     throw cms::Exception("InvalidDetId") << " Wrong indices in EcalElectronicsMapping::getTrigTowerDetId. TCCid = "
0320                                          << TCCid << " iTT = " << iTT << ".";
0321   }
0322 }
0323 
0324 EcalElectronicsId EcalElectronicsMapping::getElectronicsId(const DetId& id) const {
0325   EcalSubdetector subdet = EcalSubdetector(id.subdetId());
0326   if (subdet == EcalBarrel) {
0327     const EBDetId ebdetid = EBDetId(id);
0328 
0329     int dcc = DCCid(ebdetid);
0330     bool EBPlus = (zside(dcc, DCCMODE) > 0);
0331     bool EBMinus = !EBPlus;
0332 
0333     EcalTrigTowerDetId trigtower = ebdetid.tower();
0334     // int tower = trigtower.iTT();
0335     int tower = iTT(trigtower);
0336 
0337     int ieta = EBDetId(id).ietaAbs();
0338     int iphi = EBDetId(id).iphi();
0339     int strip(0);
0340     int channel(0);
0341     bool RightTower = rightTower(tower);
0342     if (RightTower) {
0343       strip = (ieta - 1) % 5;
0344       if (strip % 2 == 0) {
0345         if (EBMinus)
0346           channel = (iphi - 1) % 5;
0347         if (EBPlus)
0348           channel = 4 - ((iphi - 1) % 5);
0349       } else {
0350         if (EBMinus)
0351           channel = 4 - ((iphi - 1) % 5);
0352         if (EBPlus)
0353           channel = (iphi - 1) % 5;
0354       }
0355     } else {
0356       strip = 4 - ((ieta - 1) % 5);
0357       if (strip % 2 == 0) {
0358         if (EBMinus)
0359           channel = 4 - ((iphi - 1) % 5);
0360         if (EBPlus)
0361           channel = (iphi - 1) % 5;
0362       } else {
0363         if (EBMinus)
0364           channel = (iphi - 1) % 5;
0365         if (EBPlus)
0366           channel = 4 - ((iphi - 1) % 5);
0367       }
0368     }
0369     strip += 1;
0370     channel += 1;
0371 
0372     EcalElectronicsId elid = EcalElectronicsId(dcc, tower, strip, channel);
0373 
0374     return elid;
0375   } else if (subdet == EcalEndcap) {
0376     EcalElectronicsMap_by_DetId::const_iterator it = get<0>(m_items).find(id);
0377     if (it == get<0>(m_items).end()) {
0378       EcalElectronicsId elid(0);
0379       edm::LogError("EcalElectronicsMapping") << "Ecal mapping was asked non valid id";
0380       return elid;
0381     }
0382     EcalElectronicsId elid = it->elid;
0383     return elid;
0384   } else {
0385     throw cms::Exception("InvalidDetId") << " Wrong DetId in EcalElectronicsMapping::getElectronicsId.";
0386   }
0387 }
0388 
0389 EcalTriggerElectronicsId EcalElectronicsMapping::getTriggerElectronicsId(const DetId& id) const {
0390   EcalSubdetector subdet = EcalSubdetector(id.subdetId());
0391 
0392   if (subdet == EcalBarrel) {
0393     const EcalElectronicsId& elid = getElectronicsId(id);
0394     EcalTriggerElectronicsId trelid = getTriggerElectronicsId(elid);
0395     return trelid;
0396   } else if (subdet == EcalEndcap) {
0397     EcalElectronicsMap_by_DetId::const_iterator it = get<0>(m_items).find(id);
0398     if (it == get<0>(m_items).end()) {
0399       EcalTriggerElectronicsId trelid(0);
0400       edm::LogError("EcalElectronicsMapping") << "Ecal mapping was asked non valid trig id";
0401       return trelid;
0402     }
0403     EcalTriggerElectronicsId trelid = it->trelid;
0404     return trelid;
0405   } else {
0406     throw cms::Exception("InvalidDetId") << " Wrong DetId in EcalElectronicsMapping::getTriggerElectronicsId.";
0407   }
0408 }
0409 
0410 DetId EcalElectronicsMapping::getDetId(const EcalElectronicsId& id) const {
0411   EcalSubdetector subdet = id.subdet();
0412 
0413   if (subdet == EcalBarrel) {
0414     int dcc = id.dccId();
0415     int tower = id.towerId();
0416     int strip = id.stripId();
0417     int channel = id.xtalId();
0418 
0419     int smid = 0;
0420     int iphi = 0;
0421     bool EBPlus = (id.zside() > 0);
0422     bool EBMinus = !EBPlus;
0423 
0424     if (id.zside() < 0) {
0425       smid = dcc + 19 - DCCID_PHI0_EBM;
0426       iphi = (smid - 19) * kCrystalsInPhi;
0427       iphi += 5 * ((tower - 1) % kTowersInPhi);
0428     } else {
0429       smid = dcc + 1 - DCCID_PHI0_EBP;
0430       iphi = (smid - 1) * kCrystalsInPhi;
0431       iphi += 5 * (kTowersInPhi - ((tower - 1) % kTowersInPhi) - 1);
0432     }
0433     bool RightTower = rightTower(tower);
0434     int ieta = 5 * ((tower - 1) / kTowersInPhi) + 1;
0435     if (RightTower) {
0436       ieta += (strip - 1);
0437       if (strip % 2 == 1) {
0438         if (EBMinus)
0439           iphi += (channel - 1) + 1;
0440         if (EBPlus)
0441           iphi += (4 - (channel - 1)) + 1;
0442       } else {
0443         if (EBMinus)
0444           iphi += (4 - (channel - 1)) + 1;
0445         if (EBPlus)
0446           iphi += (channel - 1) + 1;
0447       }
0448     } else {
0449       ieta += 4 - (strip - 1);
0450       if (strip % 2 == 1) {
0451         if (EBMinus)
0452           iphi += (4 - (channel - 1)) + 1;
0453         if (EBPlus)
0454           iphi += (channel - 1) + 1;
0455       } else {
0456         if (EBMinus)
0457           iphi += (channel - 1) + 1;
0458         if (EBPlus)
0459           iphi += (4 - (channel - 1)) + 1;
0460       }
0461     }
0462     if (id.zside() < 0)
0463       ieta = -ieta;
0464 
0465     EBDetId e(ieta, iphi, EBDetId::ETAPHIMODE);
0466     return e;
0467   }
0468 
0469   else if (subdet == EcalEndcap) {
0470     EcalElectronicsMap_by_ElectronicsId::const_iterator it = get<1>(m_items).find(id);
0471     if (it == (get<1>(m_items).end())) {
0472       DetId cell(0);
0473       edm::LogError("EcalElectronicsMapping") << "Ecal mapping was asked non DetId";
0474       return cell;
0475     }
0476     DetId cell = it->cell;
0477     return cell;
0478   } else
0479     throw cms::Exception("InvalidDetId") << "Wrong EcalElectronicsId in EcalElectronicsMapping::getDetId.";
0480 }
0481 
0482 EcalTriggerElectronicsId EcalElectronicsMapping::getTriggerElectronicsId(const EcalElectronicsId& id) const {
0483   EcalSubdetector subdet = id.subdet();
0484 
0485   if (subdet == EcalBarrel) {
0486     int strip = id.stripId();
0487     int xtal = id.xtalId();
0488     int tower = id.towerId();
0489     int tcc = id.dccId();
0490     if (id.zside() < 0) {
0491       tcc += TCCID_PHI0_EBM - DCCID_PHI0_EBM;
0492     } else {
0493       tcc += TCCID_PHI0_EBP - DCCID_PHI0_EBP;
0494     }
0495     EcalTriggerElectronicsId trelid(tcc, tower, strip, xtal);
0496     return trelid;
0497 
0498   } else if (subdet == EcalEndcap) {
0499     EcalElectronicsMap_by_ElectronicsId::const_iterator it = get<1>(m_items).find(id);
0500     if (it == get<1>(m_items).end()) {
0501       EcalTriggerElectronicsId trelid(0);
0502       edm::LogError("EcalElectronicsMapping") << "Ecal mapping was asked non valid id";
0503       return trelid;
0504     }
0505     EcalTriggerElectronicsId trelid = it->trelid;
0506     return trelid;
0507   } else
0508     throw cms::Exception("InvalidDetId")
0509         << "Wrong EcalElectronicsId in EcalElectronicsMapping::getTriggerElectronicsId.";
0510 }
0511 
0512 DetId EcalElectronicsMapping::getDetId(const EcalTriggerElectronicsId& id) const {
0513   EcalSubdetector subdet = id.subdet();
0514 
0515   if (subdet == EcalBarrel) {
0516     const EcalElectronicsId& elid = getElectronicsId(id);
0517     DetId cell = getDetId(elid);
0518     return cell;
0519   } else if (subdet == EcalEndcap) {
0520     EcalElectronicsMap_by_TriggerElectronicsId::const_iterator it = get<2>(m_items).find(id);
0521     if (it == get<2>(m_items).end()) {
0522       DetId cell(0);
0523       edm::LogError("EcalElectronicsMapping") << "Ecal mapping was asked non valid DetId";
0524       return cell;
0525     }
0526     DetId cell = it->cell;
0527     return cell;
0528   } else
0529     throw cms::Exception("InvalidDetId") << "Wrong EcalTriggerElectronicsId in EcalElectronicsMapping::getDetId.";
0530 }
0531 
0532 EcalElectronicsId EcalElectronicsMapping::getElectronicsId(const EcalTriggerElectronicsId& id) const {
0533   EcalSubdetector subdet = id.subdet();
0534 
0535   if (subdet == EcalBarrel) {
0536     int strip = id.pseudoStripId();
0537     int xtal = id.channelId();
0538     int tower = id.ttId();
0539     int dcc = id.tccId();
0540     if (id.zside() < 0) {
0541       dcc -= TCCID_PHI0_EBM - DCCID_PHI0_EBM;
0542     } else {
0543       dcc -= TCCID_PHI0_EBP - DCCID_PHI0_EBP;
0544     }
0545     EcalElectronicsId elid(dcc, tower, strip, xtal);
0546     return elid;
0547   } else if (subdet == EcalEndcap) {
0548     EcalElectronicsMap_by_TriggerElectronicsId::const_iterator it = get<2>(m_items).find(id);
0549     if (it == get<2>(m_items).end()) {
0550       EcalElectronicsId elid(0);
0551       edm::LogError("EcalElectronicsMapping") << "Ecal mapping was asked non valid id";
0552       return elid;
0553     }
0554     EcalElectronicsId elid = it->elid;
0555     return elid;
0556   } else
0557     throw cms::Exception("InvalidDetId")
0558         << "Wrong EcalTriggerElectronicsId in EcalElectronicsMapping::getElectronicsId.";
0559 }
0560 
0561 std::vector<DetId> EcalElectronicsMapping::dccConstituents(int dccId) const {
0562   EcalSubdetector sub = subdet(dccId, DCCMODE);
0563   std::vector<DetId> items;
0564 
0565   if (sub == EcalBarrel) {
0566     for (int tower = 1; tower <= kEBTowersPerSM; tower++) {
0567       std::vector<DetId> xtals = dccTowerConstituents(dccId, tower);
0568       int size = xtals.size();
0569       for (int i = 0; i < size; i++) {
0570         DetId detid = xtals[i];
0571         items.emplace_back(detid);
0572       }
0573     }
0574     return items;
0575   } else if (sub == EcalEndcap) {
0576     EcalElectronicsMap_by_DccId::const_iterator lb, ub;
0577     boost::tuples::tie(lb, ub) = get<3>(m_items).equal_range(dccId);
0578     while (lb != ub) {
0579       DetId cell = lb->cell;
0580       items.emplace_back(cell);
0581       ++lb;
0582     }
0583     return items;
0584   } else
0585     throw cms::Exception("InvalidDetId") << "Wrong dccId = " << dccId
0586                                          << " in EcalElectronicsMapping::dccConstituents. ";
0587 }
0588 
0589 std::vector<DetId> EcalElectronicsMapping::dccTowerConstituents(int dccId, int tower) const {
0590   EcalSubdetector sub = subdet(dccId, DCCMODE);
0591   std::vector<DetId> items;
0592 
0593   if (sub == EcalBarrel) {
0594     int iz = zside(dccId, DCCMODE);
0595     int smid = 0;
0596     int iphi = 0;
0597     if (iz < 0) {
0598       smid = dccId + 19 - DCCID_PHI0_EBM;
0599       iphi = (smid - 19) * kCrystalsInPhi;
0600       iphi += 5 * ((tower - 1) % kTowersInPhi);
0601     } else {
0602       smid = dccId + 1 - DCCID_PHI0_EBP;
0603       iphi = (smid - 1) * kCrystalsInPhi;
0604       iphi += 5 * (kTowersInPhi - ((tower - 1) % kTowersInPhi) - 1);
0605     }
0606     int ieta = 5 * ((tower - 1) / kTowersInPhi) + 1;
0607     for (int ip = 1; ip <= 5; ip++) {
0608       for (int ie = 0; ie <= 4; ie++) {
0609         int ieta_xtal = ieta + ie;
0610         int iphi_xtal = iphi + ip;
0611         if (iz < 0)
0612           ieta_xtal = -ieta_xtal;
0613         EBDetId ebdetid(ieta_xtal, iphi_xtal, EBDetId::ETAPHIMODE);
0614         items.emplace_back(ebdetid);
0615       }
0616     }
0617     return items;
0618   }
0619 
0620   else if (sub == EcalEndcap) {
0621     EcalElectronicsMap_by_DccId_and_TowerId::const_iterator lb, ub;
0622     boost::tuples::tie(lb, ub) = get<4>(m_items).equal_range(boost::make_tuple(int(dccId), int(tower)));
0623     while (lb != ub) {
0624       DetId cell = lb->cell;
0625       items.emplace_back(cell);
0626       ++lb;
0627     }
0628     return items;
0629   } else
0630     throw cms::Exception("InvalidDetId") << "Wrong dccId = " << dccId << " tower = " << tower
0631                                          << " in EcalElectronicsMapping::dccTowerConstituents.";
0632 }
0633 
0634 std::vector<DetId> EcalElectronicsMapping::stripConstituents(int dccId, int tower, int strip) const {
0635   EcalSubdetector sub = subdet(dccId, DCCMODE);
0636   std::vector<DetId> items;
0637 
0638   if (sub == EcalBarrel) {
0639     int iz = zside(dccId, DCCMODE);
0640     bool RightTower = rightTower(tower);
0641     int smid = 0;
0642     int iphi = 0;
0643     if (iz < 0) {
0644       smid = dccId + 19 - DCCID_PHI0_EBM;
0645       iphi = (smid - 19) * kCrystalsInPhi;
0646       iphi += 5 * ((tower - 1) % kTowersInPhi);
0647     } else {
0648       smid = dccId + 1 - DCCID_PHI0_EBP;
0649       iphi = (smid - 1) * kCrystalsInPhi;
0650       iphi += 5 * (kTowersInPhi - ((tower - 1) % kTowersInPhi) - 1);
0651     }
0652     int ieta = 5 * ((tower - 1) / kTowersInPhi) + 1;
0653     if (RightTower) {
0654       ieta += (strip - 1);
0655     } else {
0656       ieta += 4 - (strip - 1);
0657     }
0658     for (int ip = 1; ip <= 5; ip++) {
0659       int ieta_xtal = ieta;
0660       int iphi_xtal = iphi + ip;
0661       if (iz < 0)
0662         ieta_xtal = -ieta_xtal;
0663       EBDetId ebdetid(ieta_xtal, iphi_xtal, EBDetId::ETAPHIMODE);
0664       items.emplace_back(ebdetid);
0665     }
0666 
0667     return items;
0668   } else {
0669     EcalElectronicsMap_by_DccId_TowerId_and_StripId::const_iterator lb, ub;
0670     boost::tuples::tie(lb, ub) = get<5>(m_items).equal_range(boost::make_tuple(int(dccId), int(tower), int(strip)));
0671     while (lb != ub) {
0672       DetId cell = lb->cell;
0673       items.emplace_back(cell);
0674       ++lb;
0675     }
0676     return items;
0677   }
0678 }
0679 
0680 std::vector<DetId> EcalElectronicsMapping::tccConstituents(int tccId) const {
0681   EcalSubdetector sub = subdet(tccId, TCCMODE);
0682   std::vector<DetId> items;
0683 
0684   if (sub == EcalBarrel) {
0685     int iz = zside(tccId, TCCMODE);
0686     int dccId = tccId;
0687     if (iz > 0)
0688       dccId = dccId - TCCID_PHI0_EBP + DCCID_PHI0_EBP;
0689     else
0690       dccId = dccId - TCCID_PHI0_EBM + DCCID_PHI0_EBM;
0691     items = dccConstituents(dccId);
0692     return items;
0693   } else {
0694     EcalElectronicsMap_by_TccId::const_iterator lb, ub;
0695     boost::tuples::tie(lb, ub) = get<6>(m_items).equal_range(tccId);
0696     while (lb != ub) {
0697       DetId cell = lb->cell;
0698       items.emplace_back(cell);
0699       ++lb;
0700     }
0701     return items;
0702   }
0703 }
0704 
0705 std::vector<DetId> EcalElectronicsMapping::ttConstituents(int tccId, int tt) const {
0706   EcalSubdetector sub = subdet(tccId, TCCMODE);
0707   std::vector<DetId> items;
0708 
0709   if (sub == EcalBarrel) {
0710     int iz = zside(tccId, TCCMODE);
0711     int dccId = tccId;
0712     if (iz > 0)
0713       dccId = dccId - TCCID_PHI0_EBP + DCCID_PHI0_EBP;
0714     else
0715       dccId = dccId - TCCID_PHI0_EBM + DCCID_PHI0_EBM;
0716     items = dccTowerConstituents(dccId, tt);
0717     return items;
0718   } else {
0719     EcalElectronicsMap_by_TccId_and_TtId::const_iterator lb, ub;
0720     boost::tuples::tie(lb, ub) = get<7>(m_items).equal_range(boost::make_tuple(int(tccId), int(tt)));
0721     while (lb != ub) {
0722       DetId cell = lb->cell;
0723       items.emplace_back(cell);
0724       ++lb;
0725     }
0726     return items;
0727   }
0728 }
0729 
0730 std::vector<DetId> EcalElectronicsMapping::pseudoStripConstituents(int tccId, int tt, int pseudostrip) const {
0731   EcalSubdetector sub = subdet(tccId, TCCMODE);
0732   std::vector<DetId> items;
0733 
0734   if (sub == EcalBarrel) {
0735     int iz = zside(tccId, TCCMODE);
0736     int dccId = tccId;
0737     if (iz > 0)
0738       dccId = dccId - TCCID_PHI0_EBP + DCCID_PHI0_EBP;
0739     else
0740       dccId = dccId - TCCID_PHI0_EBM + DCCID_PHI0_EBM;
0741     items = stripConstituents(dccId, tt, pseudostrip);
0742     return items;
0743   } else {
0744     EcalElectronicsMap_by_TccId_TtId_and_PseudostripId::const_iterator lb, ub;
0745     boost::tuples::tie(lb, ub) = get<8>(m_items).equal_range(boost::make_tuple(int(tccId), int(tt), int(pseudostrip)));
0746     while (lb != ub) {
0747       DetId cell = lb->cell;
0748       items.emplace_back(cell);
0749       ++lb;
0750     }
0751     return items;
0752   }
0753 }
0754 
0755 void EcalElectronicsMapping::assign(const DetId& cell,
0756                                     const EcalElectronicsId& elid,
0757                                     const EcalTriggerElectronicsId& tower) {
0758   m_items.insert(MapItem(cell, elid, tower));
0759 }
0760 
0761 std::pair<int, int> EcalElectronicsMapping::getDCCandSC(EcalScDetId id) const {
0762   // pair.first = DCC id
0763   // pair.second = DCC_channel
0764   // For digi2raw, read the SRflags and write the SR block :
0765   // need to find out, for an EcalScDetId, which is the DCC and the DCC_channel
0766 
0767   std::pair<int, int> ind;
0768   EEDetId dum;
0769   int ix = id.ix();
0770   int iy = id.iy();
0771   int zside = id.zside();
0772   ix = (ix - 1) * 5 + 1;
0773   iy = (iy - 1) * 5 + 1;
0774   ix = 5 * (ix / 5) + 1;
0775   iy = 5 * (iy / 5) + 1;
0776   int ix_c = ix;
0777   int iy_c = iy;
0778   if (!dum.validDetId(ix_c, iy_c, zside)) {
0779     ix_c = ix + 4;
0780     iy_c = iy;
0781     if (!dum.validDetId(ix_c, iy_c, zside)) {
0782       ix_c = ix + 4;
0783       iy_c = iy + 4;
0784       if (!dum.validDetId(ix_c, iy_c, zside)) {
0785         ix_c = ix;
0786         iy_c = iy + 4;
0787       }
0788     }
0789   }
0790   EEDetId eedetid(ix_c, iy_c, zside, EEDetId::XYMODE);
0791   EcalElectronicsId elid = getElectronicsId(eedetid);
0792   int Dccid = elid.dccId();
0793   int DCC_Channel = elid.towerId();
0794   ind.first = Dccid;
0795   ind.second = DCC_Channel;
0796   return ind;
0797 }
0798 
0799 std::vector<EcalScDetId> EcalElectronicsMapping::getEcalScDetId(int DCCid,
0800                                                                 int DCC_Channel,
0801                                                                 bool ignoreSingleCrystal) const {
0802   //Debug output switch:
0803   const bool debug = false;
0804 
0805   // For unpacking of ST flags.
0806   //result: SCs readout by the DCC channel DCC_channel of DCC DCCid.
0807   //Vector of 1 or 2 elements: most of the time there is only
0808   //one SC read-out by the DCC channel, but for some channels
0809   //there are 2 partial SCs which were grouped.
0810   std::vector<EcalScDetId> scDetIds;
0811 
0812   //There are 4 SCs in each endcap whose one crystal is read out
0813   //by a different DCC channel than the others.
0814   //Number of crystals of the SC read out by the DCC channel:
0815   std::vector<int> nReadoutXtals;
0816 
0817   std::vector<DetId> xtals = dccTowerConstituents(DCCid, DCC_Channel);
0818 
0819   if (debug) {
0820     std::cout << __FILE__ << ":" << __LINE__ << ": " << xtals.size() << " crystals read out by channel " << DCC_Channel
0821               << " of DCC " << DCCid << ": ";
0822     for (auto xtal : xtals) {
0823       std::cout << EEDetId(xtal) << " ";
0824     }
0825     std::cout << "\n";
0826   }
0827 
0828   if (xtals.empty())
0829     throw cms::Exception("InvalidDetId") << "EcalElectronicsMapping : can not create EcalScDetId for DCC " << DCCid
0830                                          << " and DCC_Channel " << DCC_Channel << ".";
0831 
0832   for (auto xtal : xtals) {
0833     EEDetId eedetid = xtal;
0834     int ix = eedetid.ix();
0835     int iy = eedetid.iy();
0836     int iz = eedetid.zside();
0837     int ix_SC = (ix - 1) / 5 + 1;
0838     int iy_SC = (iy - 1) / 5 + 1;
0839     //Supercrystal (SC) the crystal belongs to:
0840     EcalScDetId scdetid(ix_SC, iy_SC, iz);
0841     size_t iSc = 0;
0842     //look if the SC was already included:
0843     while (iSc < scDetIds.size() && scDetIds[iSc] != scdetid)
0844       ++iSc;
0845     if (iSc == scDetIds.size()) {  //SC not yet included
0846       scDetIds.emplace_back(scdetid);
0847       nReadoutXtals.emplace_back(1);  //crystal counter of the added SC
0848     } else {                          //SC already included
0849       ++nReadoutXtals[iSc];           // counting crystals in the SC
0850     }
0851   }
0852 
0853   if (ignoreSingleCrystal) {
0854     //For simplification, SC read out by two different DCC channels
0855     //will be associated to the DCC channel reading most of the crystals,
0856     //the other DCC channel which read only one crystal is discarded.
0857     //Discards SC with only one crystal read out by the considered,
0858     //DCC channel:
0859     assert(scDetIds.size() == nReadoutXtals.size());
0860     for (size_t iSc = 0; iSc < scDetIds.size(); /*NOOP*/) {
0861       if (nReadoutXtals[iSc] <= 1) {
0862         if (debug)
0863           std::cout << "EcalElectronicsMapping::getEcalScDetId: Ignore SC " << scDetIds[iSc]
0864                     << " whose only one channel is read out by "
0865                        "the DCC channel (DCC "
0866                     << DCCid << ", ch " << DCC_Channel << ").\n";
0867         scDetIds.erase(scDetIds.begin() + iSc);
0868         nReadoutXtals.erase(nReadoutXtals.begin() + iSc);
0869       } else {
0870         ++iSc;  //next SC;
0871       }
0872     }
0873   }
0874 
0875   return scDetIds;
0876 }
0877 
0878 EcalSubdetector EcalElectronicsMapping::subdet(int dcctcc, int mode) const {
0879   if (mode == DCCMODE) {
0880     if ((dcctcc >= MIN_DCCID_EBM && dcctcc <= MAX_DCCID_EBM) || (dcctcc >= MIN_DCCID_EBP && dcctcc <= MAX_DCCID_EBP))
0881       return EcalBarrel;
0882     else
0883       return EcalEndcap;
0884   } else if (mode == TCCMODE) {
0885     if ((dcctcc >= MIN_TCCID_EBM && dcctcc <= MAX_TCCID_EBM) || (dcctcc >= MIN_TCCID_EBP && dcctcc <= MAX_TCCID_EBP))
0886       return EcalBarrel;
0887     else
0888       return EcalEndcap;
0889   } else
0890     throw cms::Exception("InvalidDetId") << " Wrong mode in EcalElectronicsMapping::subdet " << mode << ".";
0891 }
0892 
0893 int EcalElectronicsMapping::zside(int dcctcc, int mode) const {
0894   if (mode == DCCMODE) {
0895     if (dcctcc >= MIN_DCCID_EBM && dcctcc <= MAX_DCCID_EBM)
0896       return -1;
0897     if (dcctcc >= MIN_DCCID_EBP && dcctcc <= MAX_DCCID_EBP)
0898       return +1;
0899     if (dcctcc >= MIN_DCCID_EEM && dcctcc <= MAX_DCCID_EEM)
0900       return -1;
0901     if (dcctcc >= MIN_DCCID_EEP && dcctcc <= MAX_DCCID_EEP)
0902       return +1;
0903   } else if (mode == TCCMODE) {
0904     if (dcctcc >= MIN_TCCID_EBM && dcctcc <= MAX_TCCID_EBM)
0905       return -1;
0906     if (dcctcc >= MIN_TCCID_EBP && dcctcc <= MAX_TCCID_EBP)
0907       return +1;
0908     if (dcctcc >= MIN_TCCID_EEM && dcctcc <= MAX_TCCID_EEM)
0909       return -1;
0910     if (dcctcc >= MIN_TCCID_EEP && dcctcc <= MAX_TCCID_EEP)
0911       return +1;
0912   } else {
0913     throw cms::Exception("InvalidDetId") << " Wrong mode in EcalElectronicsMapping::zside " << mode << ".";
0914   }
0915   return 0;
0916 }
0917 
0918 bool EcalElectronicsMapping::rightTower(int tower) const {
0919   // for EB, two types of tower (LVRB top/bottom)
0920 
0921   if ((tower > 12 && tower < 21) || (tower > 28 && tower < 37) || (tower > 44 && tower < 53) ||
0922       (tower > 60 && tower < 69))
0923     return true;
0924   else
0925     return false;
0926 }
0927 
0928 int EcalElectronicsMapping::DCCBoundary(int FED) const {
0929   if (FED >= MIN_DCCID_EEM && FED <= MAX_DCCID_EEM)
0930     return MIN_DCCID_EEM;
0931   if (FED >= MIN_DCCID_EBM && FED <= MAX_DCCID_EBM)
0932     return MIN_DCCID_EBM;
0933   if (FED >= MIN_DCCID_EBP && FED <= MAX_DCCID_EBP)
0934     return MIN_DCCID_EBP;
0935   if (FED >= MIN_DCCID_EEP && FED <= MAX_DCCID_EEP)
0936     return MIN_DCCID_EEP;
0937   return -1;
0938 }
0939 
0940 std::vector<int> EcalElectronicsMapping::GetListofFEDs(const RectangularEtaPhiRegion& region) const {
0941   std::vector<int> FEDs;
0942   GetListofFEDs(region, FEDs);
0943   return FEDs;
0944 }
0945 void EcalElectronicsMapping::GetListofFEDs(const RectangularEtaPhiRegion& region, std::vector<int>& FEDs) const {
0946   // for regional unpacking.
0947   // get list of FEDs corresponding to a region in (eta,phi)
0948 
0949   //    std::vector<int> FEDs;
0950   double radTodeg = 180. / M_PI;
0951   ;
0952 
0953   bool debug = false;
0954 
0955   double etalow = region.etaLow();
0956   double philow = region.phiLow() * radTodeg;
0957   if (debug)
0958     std::cout << " etalow philow " << etalow << " " << philow << std::endl;
0959   int FED_LB = GetFED(etalow, philow);  // left, bottom
0960 
0961   double phihigh = region.phiHigh() * radTodeg;
0962   if (debug)
0963     std::cout << " etalow phihigh " << etalow << " " << phihigh << std::endl;
0964   int FED_LT = GetFED(etalow, phihigh);  // left, top
0965 
0966   int DCC_BoundaryL = DCCBoundary(FED_LB);
0967   int deltaL = 18;
0968   if (FED_LB < MIN_DCCID_EBM || FED_LB > MAX_DCCID_EBP)
0969     deltaL = 9;
0970 
0971   if (philow < -170 && phihigh > 170) {
0972     FED_LB = DCC_BoundaryL;
0973     FED_LT = DCC_BoundaryL + deltaL - 1;
0974   }
0975   if (debug)
0976     std::cout << " FED_LB FED_LT " << FED_LB << " " << FED_LT << std::endl;
0977 
0978   bool dummy = true;
0979   int idx = 0;
0980   while (dummy) {
0981     int iL = (FED_LB - DCC_BoundaryL + idx) % deltaL + DCC_BoundaryL;
0982     FEDs.emplace_back(iL);
0983     if (debug)
0984       std::cout << "   add fed " << iL << std::endl;
0985     if (iL == FED_LT)
0986       break;
0987     idx++;
0988   }
0989 
0990   double etahigh = region.etaHigh();
0991   int FED_RB = GetFED(etahigh, philow);  // right, bottom
0992   if (FED_RB == FED_LB)
0993     return;  // FEDs;
0994 
0995   int FED_RT = GetFED(etahigh, phihigh);  // right, top
0996 
0997   if (debug)
0998     std::cout << "etahigh philow phihigh " << etahigh << " " << philow << " " << phihigh << std::endl;
0999   int DCC_BoundaryR = DCCBoundary(FED_RB);
1000   int deltaR = 18;
1001   if (FED_RB < MIN_DCCID_EBM || FED_RB > MAX_DCCID_EBP)
1002     deltaR = 9;
1003 
1004   if (philow < -170 && phihigh > 170) {
1005     FED_RB = DCC_BoundaryR;
1006     FED_RT = DCC_BoundaryR + deltaR - 1;
1007   }
1008   if (debug)
1009     std::cout << " FED_RB FED_RT " << FED_RB << " " << FED_RT << std::endl;
1010   idx = 0;
1011   while (dummy) {
1012     int iR = (FED_RB - DCC_BoundaryR + idx) % deltaR + DCC_BoundaryR;
1013     FEDs.emplace_back(iR);
1014     if (debug)
1015       std::cout << "   add fed " << iR << std::endl;
1016     if (iR == FED_RT)
1017       break;
1018     idx++;
1019   }
1020 
1021   if (FED_LB >= MIN_DCCID_EBM && FED_LB <= MAX_DCCID_EBM && FED_RB >= MIN_DCCID_EEP && FED_RB <= MAX_DCCID_EEP) {
1022     int minR = FED_LB + 18;
1023     int maxR = FED_LT + 18;
1024     int idx = 0;
1025     while (dummy) {
1026       int iR = (minR - MIN_DCCID_EBP + idx) % 18 + MIN_DCCID_EBP;
1027       FEDs.emplace_back(iR);
1028       if (debug)
1029         std::cout << "   add fed " << iR << std::endl;
1030       if (iR == maxR)
1031         break;
1032       idx++;
1033     }
1034     return;  // FEDs;
1035   }
1036 
1037   if (FED_LB >= MIN_DCCID_EEM && FED_LB <= MAX_DCCID_EEM && FED_RB >= MIN_DCCID_EBP && FED_RB <= MAX_DCCID_EBP) {
1038     int minL = FED_RB - 18;
1039     int maxL = FED_RT - 18;
1040     int idx = 0;
1041     while (dummy) {
1042       int iL = (minL - MIN_DCCID_EBM + idx) % 18 + MIN_DCCID_EBM;
1043       FEDs.emplace_back(iL);
1044       if (debug)
1045         std::cout << "   add fed " << iL << std::endl;
1046       if (iL == maxL)
1047         break;
1048       idx++;
1049     }
1050     return;  // FEDs;
1051   }
1052 
1053   if (FED_LB >= MIN_DCCID_EEM && FED_LB <= MAX_DCCID_EEM && FED_RB >= MIN_DCCID_EEP && FED_RB <= MAX_DCCID_EEP) {
1054     int minL = (FED_LB - 1) * 2 + MIN_DCCID_EBM;
1055     if (minL == MIN_DCCID_EBM)
1056       minL = MAX_DCCID_EBM;
1057     else
1058       minL = minL - 1;
1059     int maxL = (FED_LT - 1) * 2 + MIN_DCCID_EBM;
1060     int idx = 0;
1061     while (dummy) {
1062       int iL = (minL - MIN_DCCID_EBM + idx) % 18 + MIN_DCCID_EBM;
1063       FEDs.emplace_back(iL);
1064       if (debug)
1065         std::cout << "   add fed " << iL << std::endl;
1066       if (iL == maxL)
1067         break;
1068       idx++;
1069     }
1070     int minR = minL + 18;
1071     int maxR = maxL + 18;
1072     idx = 0;
1073     while (dummy) {
1074       int iR = (minR - MIN_DCCID_EBP + idx) % 18 + MIN_DCCID_EBP;
1075       FEDs.emplace_back(iR);
1076       if (debug)
1077         std::cout << "   add fed " << iR << std::endl;
1078       if (iR == maxR)
1079         break;
1080       idx++;
1081     }
1082   }
1083 
1084   return;  // FEDs;
1085 }
1086 
1087 int EcalElectronicsMapping::GetFED(double eta, double phi) const {
1088   // for regional unpacking.
1089   // eta is signed, phi is in degrees.
1090 
1091   int DCC_Phi0 = 0;
1092   bool IsBarrel = true;
1093   if (fabs(eta) > 1.479)
1094     IsBarrel = false;
1095   bool Positive = (eta > 0);
1096 
1097   if (IsBarrel && Positive)
1098     DCC_Phi0 = DCCID_PHI0_EBP;
1099   if (IsBarrel && (!Positive))
1100     DCC_Phi0 = DCCID_PHI0_EBM;
1101   if ((!IsBarrel) && Positive)
1102     DCC_Phi0 = MIN_DCCID_EEP;
1103   if ((!IsBarrel) && (!Positive))
1104     DCC_Phi0 = MIN_DCCID_EEM;
1105 
1106   // phi between 0 and 360 deg :
1107   if (phi < 0)
1108     phi += 360;
1109   if (phi > 360.)
1110     phi = 360.;
1111   if (phi < 0)
1112     phi = 0.;
1113 
1114   if (IsBarrel)
1115     phi = phi - 350;
1116   else
1117     phi = phi - 330;
1118   if (phi < 0)
1119     phi += 360;
1120   int iphi = -1;
1121   if (IsBarrel)
1122     iphi = (int)(phi / 20.);
1123   else
1124     iphi = (int)(phi / 40.);
1125 
1126   // std::cout << " in GetFED : phi iphi DCC0 " << phi << " " << iphi << " " << DCC_Phi0 << std::endl;
1127 
1128   int DCC = iphi + DCC_Phi0;
1129   // std::cout << "  eta phi " << eta << " " << " " << phi << " is in FED " << DCC << std::endl;
1130   return DCC;
1131 }
1132 
1133 int EcalElectronicsMapping::getLMNumber(const DetId& id) const {
1134   // Laser Monitoring readout number.
1135 
1136   EcalSubdetector subdet = EcalSubdetector(id.subdetId());
1137 
1138   if (subdet == EcalBarrel) {
1139     const EBDetId ebdetid = EBDetId(id);
1140     int dccid = DCCid(ebdetid);
1141     std::map<int, int>::const_iterator it = LaserMonitoringMap_EB.find(dccid);
1142     if (it != LaserMonitoringMap_EB.end()) {
1143       int ilm = it->second;
1144       int iETA = ebdetid.ietaSM();
1145       int iPHI = ebdetid.iphiSM();
1146       if (iPHI > 10 && iETA > 5) {
1147         ilm++;
1148       };
1149       return ilm;
1150     } else
1151       throw cms::Exception("InvalidDCCId") << "Wrong DCCId (EB) in EcalElectronicsMapping::getLMNumber.";
1152   }
1153 
1154   else if (subdet == EcalEndcap) {
1155     EcalElectronicsId elid = getElectronicsId(id);
1156     int dccid = elid.dccId();
1157     EEDetId eedetid = EEDetId(id);
1158     std::map<int, int>::const_iterator it = LaserMonitoringMap_EE.find(dccid);
1159     if (it != LaserMonitoringMap_EB.end()) {
1160       int ilm = it->second;
1161       if (dccid == 8) {
1162         int ix = eedetid.ix();
1163         if (ix > 50)
1164           ilm += 1;
1165       }
1166       if (dccid == 53) {
1167         int ix = eedetid.ix();
1168         if (ix > 50)
1169           ilm += 1;
1170       }
1171       return ilm;
1172     } else
1173       throw cms::Exception("InvalidDCCId") << "Wrong DCCId (EE) in EcalElectronicsMapping::getLMNumber.";
1174   }
1175 
1176   return -1;
1177 }