00001 #include "Geometry/CaloTopology/interface/HcalTopology.h"
00002 #include <cmath>
00003 #include <iostream>
00004 #include <cassert>
00005 #include <algorithm>
00006
00007 static const int IPHI_MAX=72;
00008
00009 HcalTopology::HcalTopology(bool h2_mode) :
00010 excludeHB_(false),
00011 excludeHE_(false),
00012 excludeHO_(false),
00013 excludeHF_(false),
00014 h2mode_(h2_mode),
00015 firstHBRing_(1),
00016 lastHBRing_(16),
00017 firstHERing_(16),
00018 lastHERing_(29),
00019 firstHFRing_(29),
00020 lastHFRing_(41),
00021 firstHORing_(1),
00022 lastHORing_(15),
00023 firstHEDoublePhiRing_((h2_mode)?(22):(21)),
00024 firstHFQuadPhiRing_(40),
00025 firstHETripleDepthRing_((h2_mode)?(24):(27)),
00026 singlePhiBins_(72),
00027 doublePhiBins_(36)
00028 {
00029 }
00030
00031
00032 bool HcalTopology::valid(const HcalDetId& id) const {
00033
00034 bool ok=validRaw(id);
00035
00036 ok=ok && !isExcluded(id);
00037
00038 return ok;
00039 }
00040
00041 bool HcalTopology::isExcluded(const HcalDetId& id) const {
00042 bool exed=false;
00043
00044 switch (id.subdet()) {
00045 case(HcalBarrel): exed=excludeHB_; break;
00046 case(HcalEndcap): exed=excludeHE_; break;
00047 case(HcalOuter): exed=excludeHO_; break;
00048 case(HcalForward): exed=excludeHF_; break;
00049 default: exed=false;
00050 }
00051
00052 if (!exed && !exclusionList_.empty()) {
00053 std::vector<HcalDetId>::const_iterator i=std::lower_bound(exclusionList_.begin(),exclusionList_.end(),id);
00054 if (i!=exclusionList_.end() && *i==id) exed=true;
00055 }
00056 return exed;
00057 }
00058
00059 void HcalTopology::exclude(const HcalDetId& id) {
00060 std::vector<HcalDetId>::iterator i=std::lower_bound(exclusionList_.begin(),exclusionList_.end(),id);
00061 if (i==exclusionList_.end() || *i!=id) {
00062 exclusionList_.insert(i,id);
00063 }
00064 }
00065
00066 void HcalTopology::excludeSubdetector(HcalSubdetector subdet) {
00067 switch (subdet) {
00068 case(HcalBarrel): excludeHB_=true; break;
00069 case(HcalEndcap): excludeHE_=true; break;
00070 case(HcalOuter): excludeHO_=true; break;
00071 case(HcalForward): excludeHF_=true; break;
00072 default: break;
00073 }
00074 }
00075
00076 std::vector<DetId> HcalTopology::east(const DetId& id) const {
00077 std::vector<DetId> vNeighborsDetId;
00078 HcalDetId neighbors[2];
00079 for (int i=0;i<decIEta(HcalDetId(id),neighbors);i++)
00080 vNeighborsDetId.push_back(DetId(neighbors[i].rawId()));
00081 return vNeighborsDetId;
00082 }
00083
00084 std::vector<DetId> HcalTopology::west(const DetId& id) const {
00085 std::vector<DetId> vNeighborsDetId;
00086 HcalDetId neighbors[2];
00087 for (int i=0;i<incIEta(HcalDetId(id),neighbors);i++)
00088 vNeighborsDetId.push_back(DetId(neighbors[i].rawId()));
00089 return vNeighborsDetId;
00090 }
00091
00092 std::vector<DetId> HcalTopology::north(const DetId& id) const {
00093 std::vector<DetId> vNeighborsDetId;
00094 HcalDetId neighbor;
00095 if (incIPhi(HcalDetId(id),neighbor))
00096 vNeighborsDetId.push_back(DetId(neighbor.rawId()));
00097 return vNeighborsDetId;
00098 }
00099
00100 std::vector<DetId> HcalTopology::south(const DetId& id) const {
00101 std::vector<DetId> vNeighborsDetId;
00102 HcalDetId neighbor;
00103 if (decIPhi(HcalDetId(id),neighbor))
00104 vNeighborsDetId.push_back(DetId(neighbor.rawId()));
00105 return vNeighborsDetId;
00106 }
00107
00108 std::vector<DetId> HcalTopology::up(const DetId& id) const {
00109 HcalDetId neighbor = id;
00110
00111
00112 std::vector<DetId> vNeighborsDetId;
00113 if(incrementDepth(neighbor))
00114 {
00115 vNeighborsDetId.push_back(neighbor);
00116 }
00117 return vNeighborsDetId;
00118 }
00119
00120 std::vector<DetId> HcalTopology::down(const DetId& id) const {
00121 std::cout << "HcalTopology::down() not yet implemented" << std::endl;
00122 std::vector<DetId> vNeighborsDetId;
00123 return vNeighborsDetId;
00124 }
00125
00126 int HcalTopology::exclude(HcalSubdetector subdet, int ieta1, int ieta2, int iphi1, int iphi2, int depth1, int depth2) {
00127
00128 bool exed=false;
00129
00130 switch (subdet) {
00131 case(HcalBarrel): exed=excludeHB_; break;
00132 case(HcalEndcap): exed=excludeHE_; break;
00133 case(HcalOuter): exed=excludeHO_; break;
00134 case(HcalForward): exed=excludeHF_; break;
00135 default: exed=false;
00136 }
00137 if (exed) return 0;
00138
00139 int ieta_l=std::min(ieta1,ieta2);
00140 int ieta_h=std::max(ieta1,ieta2);
00141 int iphi_l=std::min(iphi1,iphi2);
00142 int iphi_h=std::max(iphi1,iphi2);
00143 int depth_l=std::min(depth1,depth2);
00144 int depth_h=std::max(depth1,depth2);
00145
00146 int n=0;
00147 for (int ieta=ieta_l; ieta<=ieta_h; ieta++)
00148 for (int iphi=iphi_l; iphi<=iphi_h; iphi++)
00149 for (int depth=depth_l; depth<=depth_h; depth++) {
00150 HcalDetId id(subdet,ieta,iphi,depth);
00151 if (validRaw(id)) {
00152 exclude(id);
00153 n++;
00154 }
00155 }
00156 return n;
00157 }
00158
00186 bool HcalTopology::validRaw(const HcalDetId& id) const {
00187 bool ok=true;
00188 int ieta=id.ieta();
00189 int aieta=id.ietaAbs();
00190 int depth=id.depth();
00191 int iphi=id.iphi();
00192
00193 if ((ieta==0 || iphi<=0 || iphi>IPHI_MAX) || aieta>41) return false;
00194
00195 if (ok) {
00196 HcalSubdetector subdet=id.subdet();
00197 if (subdet==HcalBarrel) {
00198 if (aieta>16 || depth>2 || (aieta<=14 && depth>1)) ok=false;
00199 } else if (subdet==HcalEndcap) {
00200 if (depth>3 || aieta<16 || aieta>lastHERing() ||
00201 (aieta==16 && depth!=3) ||
00202 (aieta==17 && depth!=1 && !h2mode_) ||
00203 (((aieta>=17 && aieta<firstHETripleDepthRing()) || aieta==29) && depth>2) ||
00204 (aieta>=firstHEDoublePhiRing() && (iphi%2)==0)) ok=false;
00205 } else if (subdet==HcalOuter) {
00206 if (aieta>15 || iphi>IPHI_MAX || depth!=4) ok=false;
00207 } else if (subdet==HcalForward) {
00208 if (aieta<firstHFRing() || aieta>lastHFRing() ||
00209 ((iphi%2)==0) ||
00210 (depth>2) ||
00211 (aieta>=firstHFQuadPhiRing() && ((iphi+1)%4)!=0)) ok=false;
00212 } else ok=false;
00213 }
00214
00215 return ok;
00216 }
00217
00218
00219 bool HcalTopology::incIPhi(const HcalDetId& id, HcalDetId &neighbor) const {
00220 bool ok=valid(id);
00221 if (ok) {
00222 switch (id.subdet()) {
00223 case (HcalBarrel):
00224 case (HcalOuter):
00225 if (id.iphi()==IPHI_MAX) neighbor=HcalDetId(id.subdet(),id.ieta(),1,id.depth());
00226 else neighbor=HcalDetId(id.subdet(),id.ieta(),id.iphi()+1,id.depth());
00227 break;
00228 case (HcalEndcap):
00229 if (id.ietaAbs()>=firstHEDoublePhiRing()) {
00230 if (id.iphi()==IPHI_MAX-1) neighbor=HcalDetId(id.subdet(),id.ieta(),1,id.depth());
00231 else neighbor=HcalDetId(id.subdet(),id.ieta(),id.iphi()+2,id.depth());
00232 } else {
00233 if (id.iphi()==IPHI_MAX) neighbor=HcalDetId(id.subdet(),id.ieta(),1,id.depth());
00234 else neighbor=HcalDetId(id.subdet(),id.ieta(),id.iphi()+1,id.depth());
00235 }
00236 break;
00237 case (HcalForward):
00238 if (id.ietaAbs()>=firstHFQuadPhiRing()) {
00239 if (id.iphi()==IPHI_MAX-1) neighbor=HcalDetId(id.subdet(),id.ieta(),3,id.depth());
00240 else neighbor=HcalDetId(id.subdet(),id.ieta(),id.iphi()+4,id.depth());
00241 } else {
00242 if (id.iphi()==IPHI_MAX-1) neighbor=HcalDetId(id.subdet(),id.ieta(),1,id.depth());
00243 else neighbor=HcalDetId(id.subdet(),id.ieta(),id.iphi()+2,id.depth());
00244 }
00245 break;
00246 default: ok=false;
00247 }
00248 }
00249 return ok;
00250 }
00251
00253 bool HcalTopology::decIPhi(const HcalDetId& id, HcalDetId &neighbor) const {
00254 bool ok=valid(id);
00255 if (ok) {
00256 switch (id.subdet()) {
00257 case (HcalBarrel):
00258 case (HcalOuter):
00259 if (id.iphi()==1) neighbor=HcalDetId(id.subdet(),id.ieta(),IPHI_MAX,id.depth());
00260 else neighbor=HcalDetId(id.subdet(),id.ieta(),id.iphi()-1,id.depth());
00261 break;
00262 case (HcalEndcap):
00263 if (id.ietaAbs()>=firstHEDoublePhiRing()) {
00264 if (id.iphi()==1) neighbor=HcalDetId(id.subdet(),id.ieta(),IPHI_MAX-1,id.depth());
00265 else neighbor=HcalDetId(id.subdet(),id.ieta(),id.iphi()-2,id.depth());
00266 } else {
00267 if (id.iphi()==1) neighbor=HcalDetId(id.subdet(),id.ieta(),IPHI_MAX,id.depth());
00268 else neighbor=HcalDetId(id.subdet(),id.ieta(),id.iphi()-1,id.depth());
00269 }
00270 break;
00271 case (HcalForward):
00272 if (id.ietaAbs()>=firstHFQuadPhiRing()) {
00273 if (id.iphi()==3) neighbor=HcalDetId(id.subdet(),id.ieta(),IPHI_MAX-1,id.depth());
00274 else neighbor=HcalDetId(id.subdet(),id.ieta(),id.iphi()-4,id.depth());
00275 } else {
00276 if (id.iphi()==1) neighbor=HcalDetId(id.subdet(),id.ieta(),IPHI_MAX-1,id.depth());
00277 else neighbor=HcalDetId(id.subdet(),id.ieta(),id.iphi()-2,id.depth());
00278 }
00279 break;
00280 default: ok=false;
00281 }
00282 }
00283 return ok;
00284 }
00285
00286 int HcalTopology::incIEta(const HcalDetId& id, HcalDetId neighbors[2]) const {
00287 if (id.zside()==1) return incAIEta(id,neighbors);
00288 else return decAIEta(id,neighbors);
00289 }
00290
00291 int HcalTopology::decIEta(const HcalDetId& id, HcalDetId neighbors[2]) const {
00292 if (id.zside()==1) return decAIEta(id,neighbors);
00293 else return incAIEta(id,neighbors);
00294 }
00295
00297 int HcalTopology::incAIEta(const HcalDetId& id, HcalDetId neighbors[2]) const {
00298 int n=1;
00299 int aieta=id.ietaAbs();
00300
00301 if (aieta==firstHEDoublePhiRing()-1 && (id.iphi()%2)==0)
00302 neighbors[0]=HcalDetId(HcalEndcap,(aieta+1)*id.zside(),id.iphi()-1,id.depth());
00303 else if (aieta==firstHFQuadPhiRing()-1 && ((id.iphi()+1)%4)!=0)
00304 neighbors[0]=(id.iphi()==1)? HcalDetId(HcalForward,(aieta+1)*id.zside(),71,id.depth()) : HcalDetId(HcalForward,(aieta+1)*id.zside(),(id.iphi()-2),id.depth());
00305 else if (aieta==lastHBRing())
00306 neighbors[0]=HcalDetId(HcalEndcap,(aieta+1)*id.zside(),id.iphi(),1);
00307 else if (aieta==lastHERing())
00308 neighbors[0]=HcalDetId(HcalForward,(aieta+1)*id.zside(),id.iphi(),1);
00309 else
00310 neighbors[0]=HcalDetId(id.subdet(),(aieta+1)*id.zside(),id.iphi(),id.depth());
00311
00312 if (!valid(neighbors[0])) n=0;
00313 return n;
00314 }
00315
00317 int HcalTopology::decAIEta(const HcalDetId& id, HcalDetId neighbors[2]) const {
00318 int n=1;
00319 int aieta=id.ietaAbs();
00320
00321 if (aieta==firstHEDoublePhiRing()) {
00322 n=2;
00323 neighbors[0]=HcalDetId(HcalEndcap,(aieta-1)*id.zside(),id.iphi(),id.depth());
00324 neighbors[1]=HcalDetId(HcalEndcap,(aieta-1)*id.zside(),id.iphi()+1,id.depth());
00325 } else if (aieta==firstHFQuadPhiRing()) {
00326 n=2;
00327 neighbors[0]=HcalDetId(HcalForward,(aieta-1)*id.zside(),id.iphi(),id.depth());
00328 if (id.iphi()==IPHI_MAX-1) neighbors[1]=HcalDetId(HcalForward,(aieta-1)*id.zside(),1,id.depth());
00329 else neighbors[1]=HcalDetId(HcalForward,(aieta-1)*id.zside(),id.iphi()+2,id.depth());
00330 } else if (aieta==1) {
00331 neighbors[0]=HcalDetId(id.subdet(),-aieta*id.zside(),id.iphi(),id.depth());
00332 } else if (aieta==lastHBRing()+1) {
00333 neighbors[0]=HcalDetId(HcalBarrel,(aieta-1)*id.zside(),id.iphi(),id.depth());
00334 } else if (aieta==lastHERing()+1) {
00335 neighbors[0]=HcalDetId(HcalEndcap,(aieta-1)*id.zside(),id.iphi(),id.depth());
00336 } else
00337 neighbors[0]=HcalDetId(id.subdet(),(aieta-1)*id.zside(),id.iphi(),id.depth());
00338
00339 if (!valid(neighbors[0]) && n==2) {
00340 if (!valid(neighbors[1])) n=0;
00341 else {
00342 n=1;
00343 neighbors[0]=neighbors[1];
00344 }
00345 }
00346 if (n==2 && !valid(neighbors[1])) n=1;
00347 if (n==1 && !valid(neighbors[0])) n=0;
00348
00349 return n;
00350 }
00351
00352
00353 void HcalTopology::depthBinInformation(HcalSubdetector subdet, int etaRing,
00354 int & nDepthBins, int & startingBin) const {
00355 if(subdet == HcalBarrel) {
00356 if (etaRing<=14) {
00357 nDepthBins = 1;
00358 startingBin = 1;
00359 } else {
00360 nDepthBins = 2;
00361 startingBin = 1;
00362 }
00363 } else if(subdet == HcalEndcap) {
00364 if (etaRing==16) {
00365 nDepthBins = 1;
00366 startingBin = 3;
00367 } else if (etaRing==17) {
00368 nDepthBins = 1;
00369 startingBin = 1;
00370 } else if (etaRing==lastHERing()) {
00371 nDepthBins = 2;
00372 startingBin = 1;
00373 }
00374 else {
00375 nDepthBins = (etaRing >= firstHETripleDepthRing()) ? 3 : 2;
00376 startingBin = 1;
00377 }
00378 }
00379
00380 else if(subdet == HcalForward) {
00381 nDepthBins = 2;
00382 startingBin = 1;
00383 }
00384
00385 else if(subdet == HcalOuter) {
00386 nDepthBins = 1;
00387 startingBin = 4;
00388 }
00389
00390 else {
00391 std::cerr << "Bad HCAL subdetector " << subdet << std::endl;
00392 }
00393 }
00394
00395
00396 bool HcalTopology::incrementDepth(HcalDetId & detId) const
00397 {
00398 HcalSubdetector subdet = detId.subdet();
00399 int ieta = detId.ieta();
00400 int etaRing = detId.ietaAbs();
00401 int depth = detId.depth();
00402 int nDepthBins, startingBin;
00403 depthBinInformation(subdet, etaRing, nDepthBins, startingBin);
00404
00405
00406 ++depth;
00407 if(depth > nDepthBins)
00408 {
00409
00410 if(subdet == HcalBarrel && etaRing < lastHORing())
00411 {
00412
00413 subdet = HcalOuter;
00414 depth = 4;
00415 }
00416 else if(subdet == HcalBarrel && etaRing == lastHBRing())
00417 {
00418
00419 subdet = HcalEndcap;
00420 }
00421 else if(subdet == HcalEndcap && etaRing == lastHERing()-1)
00422 {
00423
00424 subdet = HcalForward;
00425 (ieta > 0) ? ++ieta : --ieta;
00426 depth = 1;
00427 }
00428 else if(subdet == HcalEndcap && etaRing == lastHERing())
00429 {
00430
00431 (ieta > 0) ? --ieta : ++ieta;
00432 }
00433 else
00434 {
00435
00436 detId = HcalDetId();
00437 return false;
00438 }
00439 }
00440 detId = HcalDetId(subdet, ieta, detId.iphi(), depth);
00441
00442
00443 return validRaw(detId);
00444
00445 }
00446
00447
00448 int HcalTopology::nPhiBins(int etaRing) const {
00449 int lastPhiBin=singlePhiBins_;
00450 if (etaRing>= firstHFQuadPhiRing()) lastPhiBin=doublePhiBins_/2;
00451 else if (etaRing>= firstHEDoublePhiRing()) lastPhiBin=doublePhiBins_;
00452 return lastPhiBin;
00453 }
00454
00455
00456