Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:14:36

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