File indexing completed on 2024-09-07 04:37:49
0001 #ifndef RecoParticleFlow_PFClusterProducer_PFHCALDenseIdNavigator_h
0002 #define RecoParticleFlow_PFClusterProducer_PFHCALDenseIdNavigator_h
0003
0004 #include "FWCore/Framework/interface/ESWatcher.h"
0005
0006 #include "RecoParticleFlow/PFClusterProducer/interface/PFRecHitNavigatorBase.h"
0007 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
0008 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
0009 #include "FWCore/Framework/interface/ConsumesCollector.h"
0010
0011 #include "RecoCaloTools/Navigation/interface/CaloNavigator.h"
0012 #include "DataFormats/EcalDetId/interface/EBDetId.h"
0013 #include "DataFormats/EcalDetId/interface/EEDetId.h"
0014 #include "DataFormats/EcalDetId/interface/ESDetId.h"
0015 #include "DataFormats/HcalDetId/interface/HcalDetId.h"
0016
0017 #include "Geometry/CaloTopology/interface/EcalEndcapTopology.h"
0018 #include "Geometry/CaloTopology/interface/EcalBarrelTopology.h"
0019 #include "Geometry/CaloTopology/interface/EcalPreshowerTopology.h"
0020 #include "Geometry/CaloTopology/interface/HcalTopology.h"
0021
0022 #include "Geometry/CaloTopology/interface/CaloTowerTopology.h"
0023 #include "DataFormats/CaloTowers/interface/CaloTowerDetId.h"
0024
0025 template <typename DET, typename TOPO, bool ownsTopo = true>
0026 class PFHCALDenseIdNavigator : public PFRecHitNavigatorBase {
0027 public:
0028 ~PFHCALDenseIdNavigator() override {
0029 if (!ownsTopo) {
0030 topology_.release();
0031 }
0032 }
0033
0034 PFHCALDenseIdNavigator(const edm::ParameterSet& iConfig, edm::ConsumesCollector& cc)
0035 : vhcalEnum_(iConfig.getParameter<std::vector<int>>("hcalEnums")),
0036 hcalToken_(cc.esConsumes<edm::Transition::BeginRun>()),
0037 geomToken_(cc.esConsumes<edm::Transition::BeginRun>()) {}
0038
0039
0040 void init(const edm::EventSetup& iSetup) override {
0041 bool check = theRecNumberWatcher_.check(iSetup);
0042 if (!check)
0043 return;
0044
0045 edm::ESHandle<HcalTopology> hcalTopology = iSetup.getHandle(hcalToken_);
0046 topology_.release();
0047 topology_.reset(hcalTopology.product());
0048
0049
0050 edm::ESHandle<CaloGeometry> hGeom = iSetup.getHandle(geomToken_);
0051 const CaloGeometry& caloGeom = *hGeom;
0052
0053 std::vector<DetId> vecHcal;
0054 std::vector<unsigned int> vDenseIdHcal;
0055 neighboursHcal_.clear();
0056 for (auto hcalSubdet : vhcalEnum_) {
0057 std::vector<DetId> vecDetIds(caloGeom.getValidDetIds(DetId::Hcal, hcalSubdet));
0058 vecHcal.insert(vecHcal.end(), vecDetIds.begin(), vecDetIds.end());
0059 }
0060 vDenseIdHcal.reserve(vecHcal.size());
0061 for (auto hDetId : vecHcal) {
0062 vDenseIdHcal.push_back(topology_.get()->detId2denseId(hDetId));
0063 }
0064 std::sort(vDenseIdHcal.begin(), vDenseIdHcal.end());
0065
0066
0067 denseIdHcalMax_ = *max_element(vDenseIdHcal.begin(), vDenseIdHcal.end());
0068 denseIdHcalMin_ = *min_element(vDenseIdHcal.begin(), vDenseIdHcal.end());
0069 neighboursHcal_.resize(denseIdHcalMax_ - denseIdHcalMin_ + 1);
0070
0071 for (auto denseid : vDenseIdHcal) {
0072 std::vector<DetId> neighbours(9, DetId(0));
0073
0074
0075 unsigned denseid_c = denseid;
0076 DetId detid_c = topology_.get()->denseId2detId(denseid_c);
0077 CaloNavigator<DET> navigator(detid_c, topology_.get());
0078
0079
0080
0081 neighbours.at(NONE) = detid_c;
0082
0083 neighbours.at(NORTH) = getNeighbourDetId(detid_c, 0);
0084 neighbours.at(SOUTH) = getNeighbourDetId(detid_c, 1);
0085 neighbours.at(EAST) = getNeighbourDetId(detid_c, 2);
0086 neighbours.at(WEST) = getNeighbourDetId(detid_c, 3);
0087
0088 neighbours.at(NORTHEAST) = getNeighbourDetId(detid_c, 4);
0089 neighbours.at(SOUTHWEST) = getNeighbourDetId(detid_c, 5);
0090 neighbours.at(SOUTHEAST) = getNeighbourDetId(detid_c, 6);
0091 neighbours.at(NORTHWEST) = getNeighbourDetId(detid_c, 7);
0092
0093 unsigned index = getIdx(denseid_c);
0094 neighboursHcal_[index] = neighbours;
0095
0096 }
0097
0098 if (debug) {
0099 backwardCompatibilityCheck(vDenseIdHcal);
0100 printNeighbourInfo(vDenseIdHcal);
0101 }
0102 }
0103
0104
0105 void backwardCompatibilityCheck(const std::vector<unsigned int> vDenseIdHcal) {
0106
0107
0108
0109 for (auto denseid : vDenseIdHcal) {
0110 DetId detid = topology_.get()->denseId2detId(denseid);
0111 HcalDetId hid = HcalDetId(detid);
0112 if (detid == DetId(0)) {
0113 edm::LogWarning("PFHCALDenseIdNavigator") << "Found an invalid DetId";
0114 continue;
0115 }
0116 if (!validNeighbours(denseid)) {
0117 edm::LogWarning("PFHCALDenseIdNavigator") << "The vector for neighbour information has an invalid length";
0118 continue;
0119 }
0120 std::vector<DetId> neighbours(9, DetId(0));
0121 unsigned index = getIdx(denseid);
0122 if (index >= neighboursHcal_.size()) {
0123 edm::LogWarning("PFHCALDenseIdNavigator") << "The vector for neighbour information is not found";
0124 continue;
0125 }
0126 neighbours = neighboursHcal_.at(index);
0127
0128
0129
0130 int ineighbour = -1;
0131 for (auto neighbour : neighbours) {
0132 ineighbour++;
0133 if (neighbour == DetId(0))
0134 continue;
0135 HcalDetId hidn = HcalDetId(neighbour);
0136 std::vector<DetId> neighboursOfNeighbour(9, DetId(0));
0137 std::unordered_set<unsigned int> listOfNeighboursOfNeighbour;
0138 unsigned denseidNeighbour = topology_.get()->detId2denseId(neighbour);
0139
0140 if (!validNeighbours(denseidNeighbour)) {
0141 edm::LogWarning("PFHCALDenseIdNavigator")
0142 << "This neighbour does not have a valid neighbour information (another subdetector?). Ignore: "
0143 << detid.det() << " " << hid.ieta() << " " << hid.iphi() << " " << hid.depth() << " " << neighbour.det()
0144 << " " << hidn.ieta() << " " << hidn.iphi() << " " << hidn.depth();
0145 neighboursHcal_[index][ineighbour] = DetId(0);
0146 continue;
0147 }
0148 if (getIdx(denseidNeighbour) >= neighboursHcal_.size())
0149 continue;
0150 neighboursOfNeighbour = neighboursHcal_.at(getIdx(denseidNeighbour));
0151
0152
0153
0154 for (auto neighbourOfNeighbour : neighboursOfNeighbour) {
0155 if (neighbourOfNeighbour == DetId(0))
0156 continue;
0157 unsigned denseidNeighbourOfNeighbour = topology_.get()->detId2denseId(neighbourOfNeighbour);
0158 if (!validNeighbours(denseidNeighbourOfNeighbour))
0159 continue;
0160 listOfNeighboursOfNeighbour.insert(denseidNeighbourOfNeighbour);
0161 }
0162
0163
0164 if (listOfNeighboursOfNeighbour.find(denseid) == listOfNeighboursOfNeighbour.end()) {
0165
0166 edm::LogWarning("PFHCALDenseIdNavigator")
0167 << "This neighbour does not have the original channel as its neighbour. Ignore: " << detid.det() << " "
0168 << hid.ieta() << " " << hid.iphi() << " " << hid.depth() << " " << neighbour.det() << " " << hidn.ieta()
0169 << " " << hidn.iphi() << " " << hidn.depth();
0170 neighboursHcal_[index][ineighbour] = DetId(0);
0171 }
0172
0173 }
0174 }
0175 }
0176
0177
0178 void printNeighbourInfo(const std::vector<unsigned int> vDenseIdHcal) {
0179
0180 for (auto denseid : vDenseIdHcal) {
0181 std::vector<DetId> neighbours(9, DetId(0));
0182
0183
0184 unsigned denseid_c = denseid;
0185 DetId detid_c = topology_.get()->denseId2detId(denseid_c);
0186 CaloNavigator<DET> navigator(detid_c, topology_.get());
0187
0188 unsigned index = getIdx(denseid_c);
0189
0190 neighbours = neighboursHcal_[index];
0191
0192 const DetId N = neighbours.at(NORTH);
0193 const DetId S = neighbours.at(SOUTH);
0194 const DetId E = neighbours.at(EAST);
0195 const DetId W = neighbours.at(WEST);
0196
0197 const DetId NE = neighbours.at(NORTHEAST);
0198 const DetId SW = neighbours.at(SOUTHWEST);
0199 const DetId SE = neighbours.at(SOUTHEAST);
0200 const DetId NW = neighbours.at(NORTHWEST);
0201
0202 edm::LogPrint("PFHCALDenseIdNavigator")
0203 << "PFHCALDenseIdNavigator: " << HcalDetId(detid_c).ieta() << " " << HcalDetId(detid_c).iphi() << " "
0204 << HcalDetId(detid_c).depth() << " " << HcalDetId(detid_c).subdetId() << ": " << HcalDetId(N).ieta() << " "
0205 << HcalDetId(N).iphi() << " " << HcalDetId(N).depth() << " " << HcalDetId(N).subdetId() << ", "
0206 << HcalDetId(E).ieta() << " " << HcalDetId(E).iphi() << " " << HcalDetId(E).depth() << " "
0207 << HcalDetId(E).subdetId() << ", " << HcalDetId(S).ieta() << " " << HcalDetId(S).iphi() << " "
0208 << HcalDetId(S).depth() << " " << HcalDetId(S).subdetId() << ", " << HcalDetId(W).ieta() << " "
0209 << HcalDetId(W).iphi() << " " << HcalDetId(W).depth() << " " << HcalDetId(W).subdetId() << ", "
0210 << HcalDetId(NE).ieta() << " " << HcalDetId(NE).iphi() << " " << HcalDetId(NE).depth() << " "
0211 << HcalDetId(NE).subdetId() << ", " << HcalDetId(SW).ieta() << " " << HcalDetId(SW).iphi() << " "
0212 << HcalDetId(SW).depth() << " " << HcalDetId(SW).subdetId() << ", " << HcalDetId(SE).ieta() << " "
0213 << HcalDetId(SE).iphi() << " " << HcalDetId(SE).depth() << " " << HcalDetId(SE).subdetId() << ", "
0214 << HcalDetId(NW).ieta() << " " << HcalDetId(NW).iphi() << " " << HcalDetId(NW).depth() << " "
0215 << HcalDetId(NW).subdetId();
0216
0217 }
0218 }
0219
0220
0221 const bool checkSameSubDet(const DetId detId, const DetId detId2) {
0222 HcalDetId hid = HcalDetId(detId);
0223 HcalDetId hid2 = HcalDetId(detId2);
0224 return hid.subdetId() == hid2.subdetId();
0225 }
0226
0227
0228 static constexpr int getZside(const DetId detId) { return ((detId & HcalDetId::kHcalZsideMask2) ? (1) : (-1)); }
0229
0230
0231 const uint32_t getNeighbourDetId(const DetId detId, const uint32_t direction) {
0232
0233 if (detId == DetId(0))
0234 return 0;
0235
0236 if (direction == 0)
0237 return topology_.get()->goNorth(detId);
0238
0239 if (direction == 1)
0240 return topology_.get()->goSouth(detId);
0241
0242
0243 if (direction == 2 && checkSameSubDet(detId, topology_.get()->goEast(detId)))
0244 return topology_.get()->goEast(detId);
0245
0246 if (direction == 3 && checkSameSubDet(detId, topology_.get()->goWest(detId)))
0247 return topology_.get()->goWest(detId);
0248
0249
0250
0251 if (direction == 4) {
0252 if (getZside(detId) > 0) {
0253 const DetId E = getNeighbourDetId(detId, 2);
0254 const DetId NE = getNeighbourDetId(E, 0);
0255 if (getNeighbourDetId(NE, 1) == E && NE != E)
0256 return NE;
0257 } else {
0258 const DetId N = getNeighbourDetId(detId, 0);
0259 const DetId NE = getNeighbourDetId(N, 2);
0260 const DetId E = getNeighbourDetId(detId, 2);
0261 if (getNeighbourDetId(NE, 3) == N && NE != E)
0262 return NE;
0263 }
0264 }
0265 if (direction == 5) {
0266 if (getZside(detId) > 0) {
0267 const DetId S = getNeighbourDetId(detId, 1);
0268 const DetId SW = getNeighbourDetId(S, 3);
0269 const DetId W = getNeighbourDetId(detId, 3);
0270 if (getNeighbourDetId(SW, 2) == S && SW != W)
0271 return SW;
0272 } else {
0273 const DetId W = getNeighbourDetId(detId, 3);
0274 const DetId SW = getNeighbourDetId(W, 1);
0275 if (getNeighbourDetId(SW, 0) == W && SW != W)
0276 return SW;
0277 }
0278 }
0279 if (direction == 6) {
0280 if (getZside(detId) > 0) {
0281 const DetId E = getNeighbourDetId(detId, 2);
0282 const DetId SE = getNeighbourDetId(E, 1);
0283 if (getNeighbourDetId(SE, 0) == E && SE != E)
0284 return SE;
0285 } else {
0286 const DetId S = getNeighbourDetId(detId, 1);
0287 const DetId SE = getNeighbourDetId(S, 2);
0288 const DetId E = getNeighbourDetId(detId, 2);
0289 if (getNeighbourDetId(SE, 3) == S && SE != E)
0290 return SE;
0291 }
0292 }
0293 if (direction == 7) {
0294 if (getZside(detId) > 0) {
0295 const DetId N = getNeighbourDetId(detId, 0);
0296 const DetId NW = getNeighbourDetId(N, 3);
0297 const DetId W = getNeighbourDetId(detId, 3);
0298 if (getNeighbourDetId(NW, 2) == N && NW != W)
0299 return NW;
0300 } else {
0301 const DetId W = getNeighbourDetId(detId, 3);
0302 const DetId NW = getNeighbourDetId(W, 0);
0303 if (getNeighbourDetId(NW, 1) == W && NW != W)
0304 return NW;
0305 }
0306 }
0307 return 0;
0308 }
0309
0310
0311 void associateNeighbours(reco::PFRecHit& hit,
0312 std::unique_ptr<reco::PFRecHitCollection>& hits,
0313 edm::RefProd<reco::PFRecHitCollection>& refProd) override {
0314 DetId detid(hit.detId());
0315 HcalDetId hid(detid);
0316 unsigned denseid = topology_.get()->detId2denseId(detid);
0317
0318 std::vector<DetId> neighbours(9, DetId(0));
0319
0320 if (denseid < denseIdHcalMin_ || denseid > denseIdHcalMax_) {
0321 edm::LogWarning("PFRecHitHCALCachedNavigator")
0322 << " DenseId for this cell is out of the expected range." << std::endl;
0323 } else if (!validNeighbours(denseid)) {
0324 edm::LogWarning("PFRecHitHCALCachedNavigator")
0325 << " DenseId for this cell does not have the neighbour information. " << hid.ieta() << " " << hid.iphi()
0326 << " " << hid.depth() << " " << hid.subdetId();
0327 } else {
0328 unsigned index = getIdx(denseid);
0329 neighbours = neighboursHcal_.at(index);
0330 }
0331
0332 associateNeighbour(neighbours.at(NORTH), hit, hits, refProd, 0, 1, 0);
0333 associateNeighbour(neighbours.at(NORTHEAST), hit, hits, refProd, 1, 1, 0);
0334 associateNeighbour(neighbours.at(SOUTH), hit, hits, refProd, 0, -1, 0);
0335 associateNeighbour(neighbours.at(SOUTHWEST), hit, hits, refProd, -1, -1, 0);
0336 associateNeighbour(neighbours.at(EAST), hit, hits, refProd, 1, 0, 0);
0337 associateNeighbour(neighbours.at(SOUTHEAST), hit, hits, refProd, 1, -1, 0);
0338 associateNeighbour(neighbours.at(WEST), hit, hits, refProd, -1, 0, 0);
0339 associateNeighbour(neighbours.at(NORTHWEST), hit, hits, refProd, -1, 1, 0);
0340 }
0341
0342
0343 const bool validNeighbours(const unsigned int denseid) const {
0344 if (denseid < denseIdHcalMin_ || denseid > denseIdHcalMax_)
0345 return false;
0346 unsigned index = getIdx(denseid);
0347 if (neighboursHcal_.at(index).size() != 9)
0348 return false;
0349 return true;
0350 }
0351
0352
0353 const unsigned int getIdx(const unsigned int denseid) const {
0354 if (denseid < denseIdHcalMin_ || denseid > denseIdHcalMax_)
0355 return unsigned(denseIdHcalMax_ - denseIdHcalMin_ +
0356 1);
0357 unsigned index = denseid - denseIdHcalMin_;
0358 return index;
0359 }
0360
0361 protected:
0362 edm::ESWatcher<HcalRecNumberingRecord> theRecNumberWatcher_;
0363 std::unique_ptr<const TOPO> topology_;
0364 std::vector<int> vhcalEnum_;
0365 std::vector<std::vector<DetId>> neighboursHcal_;
0366 unsigned int denseIdHcalMax_;
0367 unsigned int denseIdHcalMin_;
0368
0369 private:
0370 edm::ESGetToken<HcalTopology, HcalRecNumberingRecord> hcalToken_;
0371 edm::ESGetToken<CaloGeometry, CaloGeometryRecord> geomToken_;
0372 const bool debug = false;
0373 };
0374
0375 #endif