CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/RecoMET/METFilters/interface/EcalBoundaryInfoCalculator.h

Go to the documentation of this file.
00001 #ifndef ECALBOUNDARYINFOCALCULATOR_H_
00002 #define ECALBOUNDARYINFOCALCULATOR_H_
00003 #include <memory>
00004 #include "Geometry/CaloEventSetup/interface/CaloTopologyRecord.h"
00005 #include "Geometry/CaloTopology/interface/CaloSubdetectorTopology.h"
00006 #include "Geometry/CaloTopology/interface/CaloTopology.h"
00007 #include "RecoCaloTools/Navigation/interface/EcalBarrelNavigator.h"
00008 #include "RecoCaloTools/Navigation/interface/EcalEndcapNavigator.h"
00009 #include "RecoCaloTools/Navigation/interface/EcalPreshowerNavigator.h"
00010 #include "RecoCaloTools/Navigation/interface/CaloTowerNavigator.h"
00011 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00012 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00013 #include "DataFormats/EcalDetId/interface/EEDetId.h"
00014 #include "DataFormats/EcalDetId/interface/ESDetId.h"
00015 #include "DataFormats/EcalRecHit/interface/EcalRecHitCollections.h"
00016 #include "FWCore/Framework/interface/ESHandle.h"
00017 #include "DataFormats/METReco/interface/BoundaryInformation.h"
00018 
00019 
00020 enum CdOrientation {
00021     north, east, south, west, none
00022 };
00023 
00024 template<class EcalDetId> class EcalBoundaryInfoCalculator {
00025 
00026 public:
00027 
00028     EcalBoundaryInfoCalculator();
00029     ~EcalBoundaryInfoCalculator();
00030 
00031     BoundaryInformation boundaryRecHits(const edm::Handle<EcalRecHitCollection>&, const EcalRecHit*,
00032                                         const edm::ESHandle<CaloTopology> theCaloTopology, const edm::ESHandle<EcalChannelStatus> ecalStatus,
00033                                         const edm::ESHandle<CaloGeometry> geometry);
00034 
00035     BoundaryInformation gapRecHits(const edm::Handle<EcalRecHitCollection>&, const EcalRecHit*, const edm::ESHandle<
00036                                    CaloTopology> theCaloTopology, const edm::ESHandle<EcalChannelStatus> ecalStatus, const edm::ESHandle<
00037                                    CaloGeometry> geometry);
00038 
00039     bool checkRecHitHasDeadNeighbour(const EcalRecHit hit, const edm::ESHandle<EcalChannelStatus> ecalStatus, std::vector<
00040                                      int> &stati) {
00041 
00042         stati.clear();
00043         EcalDetId hitdetid = EcalDetId(hit.id());
00044 
00045         if (hitdetid.subdet() == EcalBarrel) {
00046 
00047             EBDetId ebhitdetid = (EBDetId) hitdetid;
00048 
00049             int hitIeta = ebhitdetid.ieta();
00050             int hitIphi = ebhitdetid.iphi();
00051 
00052             for (int ieta = -1; ieta <= 1; ieta++) {
00053                 for (int iphi = -1; iphi <= 1; iphi++) {
00054                     if ((iphi == 0 && ieta == 0) || iphi * ieta != 0)
00055                         //if (iphi == 0 && ieta == 0)
00056                         continue;
00057                     int neighbourIeta = hitIeta + ieta;
00058                     int neighbourIphi = hitIphi + iphi;
00059                     if (!EBDetId::validDetId(neighbourIeta, neighbourIphi)) {
00060                         if (neighbourIphi < 1)
00061                             neighbourIphi += 360;
00062                         if (neighbourIphi > 360)
00063                             neighbourIphi -= 360;
00064                         if (neighbourIeta == 0) {
00065                             neighbourIeta += ieta;
00066                         }
00067                     }
00068 
00069                     if (EBDetId::validDetId(neighbourIeta, neighbourIphi)) {
00070 
00071                         const EBDetId detid = EBDetId(neighbourIeta, neighbourIphi, EBDetId::ETAPHIMODE);
00072                         EcalChannelStatus::const_iterator chit = ecalStatus->find(detid);
00073                         int status = (chit != ecalStatus->end()) ? chit->getStatusCode() & 0x1F : -1;
00074 
00075                         if (status > 0) {
00076                             bool present = false;
00077                             for (std::vector<int>::const_iterator s = stati.begin(); s != stati.end(); ++s) {
00078                                 if (*s == status) {
00079                                     present = true;
00080                                     break;
00081                                 }
00082                             }
00083                             if (!present)
00084                                 stati.push_back(status);
00085                         }
00086                     }
00087                 }
00088             }
00089 
00090         } else if (hitdetid.subdet() == EcalEndcap) {
00091 
00092             EEDetId eehitdetid = (EEDetId) hitdetid;
00093             int hitIx = eehitdetid.ix();
00094             int hitIy = eehitdetid.iy();
00095             int hitIz = eehitdetid.zside();
00096 
00097             for (int ix = -1; ix <= 1; ix++) {
00098                 for (int iy = -1; iy <= 1; iy++) {
00099                     if ((ix == 0 && iy == 0) || ix * iy != 0)
00100                         //if (ix == 0 && iy == 0)
00101                         continue;
00102                     int neighbourIx = hitIx + ix;
00103                     int neighbourIy = hitIy + iy;
00104 
00105                     if (EEDetId::validDetId(neighbourIx, neighbourIy, hitIz)) {
00106 
00107                         const EEDetId detid = EEDetId(neighbourIx, neighbourIy, hitIz, EEDetId::XYMODE);
00108                         EcalChannelStatus::const_iterator chit = ecalStatus->find(detid);
00109                         int status = (chit != ecalStatus->end()) ? chit->getStatusCode() & 0x1F : -1;
00110 
00111                         if (status > 0) {
00112                             bool present = false;
00113                             for (std::vector<int>::const_iterator s = stati.begin(); s != stati.end(); ++s) {
00114                                 if (*s == status) {
00115                                     present = true;
00116                                     break;
00117                                 }
00118                             }
00119                             if (!present)
00120                                 stati.push_back(status);
00121                         }
00122                     }
00123                 }
00124             }
00125 
00126         } else {
00127             std::cout << "ERROR - RecHit belongs to wrong sub detector" << std::endl;
00128         }
00129 
00130         if (stati.size() > 0)
00131             return true;
00132         return false;
00133 
00134     }
00135 
00136     bool checkRecHitHasInvalidNeighbour(const EcalRecHit hit, const edm::ESHandle<EcalChannelStatus> ecalStatus) {
00138 
00139         EcalDetId hitdetid = EcalDetId(hit.id());
00140 
00141         if (hitdetid.subdet() == EcalBarrel) {
00142 
00143             EBDetId ebhitdetid = (EBDetId) hitdetid;
00144 
00145             int hitIeta = ebhitdetid.ieta();
00146             int hitIphi = ebhitdetid.iphi();
00147 
00148             for (int ieta = -1; ieta <= 1; ieta++) {
00149                 for (int iphi = -1; iphi <= 1; iphi++) {
00150                     if ((iphi == 0 && ieta == 0) || iphi * ieta != 0)
00151                         //if (iphi == 0 && ieta == 0)
00152                         continue;
00153                     int neighbourIeta = hitIeta + ieta;
00154                     int neighbourIphi = hitIphi + iphi;
00155                     if (!EBDetId::validDetId(neighbourIeta, neighbourIphi)) {
00156                         if (neighbourIphi < 1)
00157                             neighbourIphi += 360;
00158                         if (neighbourIphi > 360)
00159                             neighbourIphi -= 360;
00160                         if (neighbourIeta == 0) {
00161                             neighbourIeta += ieta;
00162                         }
00163                     }
00164 
00165                     if (!EBDetId::validDetId(neighbourIeta, neighbourIphi)) {
00166                         return true;
00167                     }
00168                 }
00169             }
00170 
00171         } else if (hitdetid.subdet() == EcalEndcap) {
00172 
00173             EEDetId eehitdetid = (EEDetId) hitdetid;
00174             int hitIx = eehitdetid.ix();
00175             int hitIy = eehitdetid.iy();
00176             int hitIz = eehitdetid.zside();
00177 
00178             for (int ix = -1; ix <= 1; ix++) {
00179                 for (int iy = -1; iy <= 1; iy++) {
00180                     if ((ix == 0 && iy == 0) || ix * iy != 0)
00181                         //if (ix == 0 && iy == 0)
00182                         continue;
00183                     int neighbourIx = hitIx + ix;
00184                     int neighbourIy = hitIy + iy;
00185 
00186                     if (!EEDetId::validDetId(neighbourIx, neighbourIy, hitIz)) {
00187                         return true;
00188                     }
00189                 }
00190             }
00191 
00192         } else {
00193             std::cout << "ERROR - RecHit belongs to wrong sub detector" << std::endl;
00194         }
00195 
00196         return false;
00197     }
00198 
00199     void setDebugMode() {
00200         std::cout << "set Debug Mode!" << std::endl;
00201         debug = true;
00202     }
00203 
00204 private:
00205 
00206     EcalDetId makeStepInDirection(CdOrientation direction, CaloNavigator<EcalDetId> * theNavi) {
00207         EcalDetId next;
00208         switch (direction) {
00209         case north: {
00210                 //std::cout<<"go north"<<std::endl;
00211                 next = theNavi->north();
00212                 break;
00213             }
00214         case east: {
00215                 //std::cout<<"go east"<<std::endl;
00216                 next = theNavi->east();
00217                 break;
00218             }
00219         case south: {
00220                 //std::cout<<"go south"<<std::endl;
00221                 next = theNavi->south();
00222                 break;
00223             }
00224         case west: {
00225                 //std::cout<<"go west"<<std::endl;
00226                 next = theNavi->west();
00227                 break;
00228             }
00229         default:
00230                 break;
00231         }
00232         return next;
00233     }
00234 
00235     CdOrientation goBackOneCell(CdOrientation currDirection, EcalDetId prev) {
00236         std::map<CdOrientation, CdOrientation>::iterator oIt = oppositeDirs.find(currDirection);
00237         CdOrientation oppDirection=none;
00238         if (oIt != oppositeDirs.end()) {
00239             oppDirection = oIt->second;
00240             theEcalNav->setHome(prev);
00241         }
00242         EcalDetId currDetId = theEcalNav->pos();
00243 
00244         return oppDirection;
00245     }
00246 
00247     CdOrientation turnRight(CdOrientation currDirection, bool reverseOrientation) {
00248         //read nextDirection
00249         std::map<CdOrientation, CdOrientation> turnMap = nextDirs;
00250         if (reverseOrientation)
00251             turnMap = prevDirs;
00252         std::map<CdOrientation, CdOrientation>::iterator nIt = turnMap.find(currDirection);
00253         CdOrientation nextDirection=none;
00254         if (nIt != turnMap.end())
00255             nextDirection = (*nIt).second;
00256         else
00257             std::cout << "ERROR - no Next Direction found!?!?" << std::endl;
00258         return nextDirection;
00259     }
00260 
00261     CdOrientation turnLeft(CdOrientation currDirection, bool reverseOrientation) {
00262         //read nextDirection
00263         std::map<CdOrientation, CdOrientation> turnMap = prevDirs;
00264         if (reverseOrientation)
00265             turnMap = nextDirs;
00266         std::map<CdOrientation, CdOrientation>::iterator nIt = turnMap.find(currDirection);
00267         CdOrientation nextDirection=none;
00268         if (nIt != turnMap.end())
00269             nextDirection = (*nIt).second;
00270         else
00271             std::cout << "ERROR - no Next Direction found!?!?" << std::endl;
00272         return nextDirection;
00273     }
00274 
00275     void initializeEcalNavigator(DetId startE, const edm::ESHandle<CaloTopology> theCaloTopology,
00276                                  EcalSubdetector ecalSubDet) {
00277         if (ecalSubDet == EcalBarrel) {
00278             if (theEcalNav != 0) {
00279                 delete theEcalNav;
00280                 theEcalNav = 0;
00281             }
00282             theEcalNav = new CaloNavigator<EcalDetId> ((EBDetId) startE, (theCaloTopology->getSubdetectorTopology(
00283                              DetId::Ecal, ecalSubDet)));
00284         } else if (ecalSubDet == EcalEndcap) {
00285             if (theEcalNav != 0) {
00286                 delete theEcalNav;
00287                 theEcalNav = 0;
00288             }
00289             theEcalNav = new CaloNavigator<EcalDetId> ((EEDetId) startE, (theCaloTopology->getSubdetectorTopology(
00290                              DetId::Ecal, ecalSubDet)));
00291         } else {
00292             std::cout << "initializeEcalNavigator not implemented for subDet: " << ecalSubDet << std::endl;
00293         }
00294 
00295     }
00296 
00297     std::map<CdOrientation, CdOrientation> nextDirs;
00298     std::map<CdOrientation, CdOrientation> prevDirs;
00299     std::map<CdOrientation, CdOrientation> oppositeDirs;
00300     CaloNavigator<EcalDetId> * theEcalNav;
00301     bool debug;
00302 
00303 };
00304 
00305 template<class EcalDetId> EcalBoundaryInfoCalculator<EcalDetId>::EcalBoundaryInfoCalculator() {
00306 
00307     nextDirs.clear();
00308     nextDirs[north] = east;
00309     nextDirs[east] = south;
00310     nextDirs[south] = west;
00311     nextDirs[west] = north;
00312 
00313     prevDirs.clear();
00314     prevDirs[north] = west;
00315     prevDirs[east] = north;
00316     prevDirs[south] = east;
00317     prevDirs[west] = south;
00318 
00319     oppositeDirs.clear();
00320     oppositeDirs[north] = south;
00321     oppositeDirs[south] = north;
00322     oppositeDirs[east] = west;
00323     oppositeDirs[west] = east;
00324 
00325     theEcalNav = 0;
00326     debug = false;
00327 
00328 }
00329 
00330 template<class EcalDetId> EcalBoundaryInfoCalculator<EcalDetId>::~EcalBoundaryInfoCalculator() {
00331     delete theEcalNav;
00332 }
00333 
00334 template<class EcalDetId> BoundaryInformation EcalBoundaryInfoCalculator<EcalDetId>::boundaryRecHits(const edm::Handle<
00335         EcalRecHitCollection>& RecHits, const EcalRecHit* hit, const edm::ESHandle<CaloTopology> theCaloTopology,
00336         edm::ESHandle<EcalChannelStatus> ecalStatus, edm::ESHandle<CaloGeometry> geometry) {
00337 
00338     //initialize boundary information
00339     std::vector<EcalRecHit> boundaryRecHits;
00340     std::vector<DetId> boundaryDetIds;
00341     std::vector<int> stati;
00342 
00343     double boundaryEnergy = 0;
00344     double boundaryET = 0;
00345     int beCellCounter = 0;
00346     bool nextToBorder = false;
00347 
00348     boundaryRecHits.push_back(*hit);
00349     ++beCellCounter;
00350     boundaryEnergy += hit->energy();
00351     EcalDetId hitdetid = (EcalDetId) hit->id();
00352     boundaryDetIds.push_back(hitdetid);
00353     const CaloSubdetectorGeometry* subGeom = geometry->getSubdetectorGeometry(hitdetid);
00354     const CaloCellGeometry* cellGeom = subGeom->getGeometry(hitdetid);
00355     double eta = cellGeom->getPosition().eta();
00356     boundaryET += hit->energy() / cosh(eta);
00357 
00358     if (debug) {
00359         std::cout << "Find Boundary RecHits..." << std::endl;
00360 
00361         if (hitdetid.subdet() == EcalBarrel) {
00362             std::cout << "Starting at : (" << ((EBDetId) hitdetid).ieta() << "," << ((EBDetId) hitdetid).iphi() << ")"
00363             << std::endl;
00364 
00365         } else if (hitdetid.subdet() == EcalEndcap) {
00366             std::cout << "Starting at : (" << ((EEDetId) hitdetid).ix() << "," << ((EEDetId) hitdetid).iy() << ")"
00367             << std::endl;
00368         }
00369     }
00370 
00371     //initialize navigator
00372     initializeEcalNavigator(hitdetid, theCaloTopology, EcalDetId::subdet());
00373     CdOrientation currDirection = north;
00374     bool reverseOrientation = false;
00375 
00376     EcalDetId next(0);
00377     EcalDetId start = hitdetid;
00378     EcalDetId current = start;
00379     int current_status = 0;
00380 
00381     // Search until a dead cell is ahead
00382     bool startAlgo = false;
00383     int noDirs = 0;
00384     while (!startAlgo) {
00385         next = makeStepInDirection(currDirection, theEcalNav);
00386         theEcalNav->setHome(current);
00387         theEcalNav->home();
00388         EcalChannelStatus::const_iterator chit = ecalStatus->find(next);
00389         int status = (chit != ecalStatus->end()) ? chit->getStatusCode() & 0x1F : -1;
00390         if (status > 0) {
00391             stati.push_back(status);
00392             startAlgo = true;
00393             break;
00394         }
00395         currDirection = turnLeft(currDirection, reverseOrientation);
00396         ++noDirs;
00397         if (noDirs > 4) {
00398 
00399             std::cout << "No starting direction can be found: This should never happen if RecHit has a dead neighbour!" << std::endl;
00400             throw "ERROR";
00401             break;
00402         }
00403     }
00404 
00405     // go around dead clusters counter clock wise
00406     currDirection = turnRight(currDirection, reverseOrientation);
00407 
00408     // Search for next boundary element
00409     bool nextIsStart = false;
00410     bool atBorder = false;
00411 
00412     while (!nextIsStart) {
00413 
00414         bool nextStepFound = false;
00415         int status = 0;
00416         noDirs = 0;
00417         while (!nextStepFound) {
00418             next = makeStepInDirection(currDirection, theEcalNav);
00419             theEcalNav->setHome(current);
00420             theEcalNav->home();
00421             EcalChannelStatus::const_iterator chit = ecalStatus->find(next);
00422             status = (chit != ecalStatus->end()) ? chit->getStatusCode() & 0x1F : -1;
00423             if (status > 0) {
00424                 // New dead cell found: update status std::vector of dead channels
00425                 bool present = false;
00426                 for (std::vector<int>::const_iterator s = stati.begin(); s != stati.end(); ++s) {
00427                     if (*s == status) {
00428                         present = true;
00429                         break;
00430                     }
00431                 }
00432                 if (!present)
00433                     stati.push_back(status);
00434 
00435                 if (atBorder) {
00436                     nextStepFound = true;
00437                 } else {
00438                     currDirection = turnRight(currDirection, reverseOrientation);
00439                 }
00440             } else if (next == EcalDetId(0)) {
00441                 // In case the Ecal border is reached -> go along dead cells
00442                 currDirection = turnLeft(currDirection, reverseOrientation);
00443                 atBorder = true;
00444             } else if (status == 0) {
00445                 nextStepFound = true;
00446             }
00447             ++noDirs;
00448             if (noDirs > 4) {
00449                 std::cout << "No valid next direction can be found: This should never happen!" << std::endl;
00450                 throw "ERROR";
00451                 break;
00452             }
00453         }
00454 
00455         // make next step
00456         next = makeStepInDirection(currDirection, theEcalNav);
00457 
00458         if (next == start) {
00459             nextIsStart = true;
00460             if (debug)
00461                 std::cout << "Boundary path reached starting position!" << std::endl;
00462         }
00463 
00464         if (debug)
00465             std::cout << "Next step: " << (EcalDetId) next << " Status: " << status << " Start: " << (EcalDetId) start << std::endl;
00466 
00467         // save recHits and add energy if on the boundary (and not inside at border)
00468         if ((!atBorder || status == 0) && !nextIsStart) {
00469             boundaryDetIds.push_back(next);
00470             if (RecHits->find(next) != RecHits->end() && status == 0) {
00471                 EcalRecHit nexthit = *RecHits->find(next);
00472                 ++beCellCounter;
00473                 boundaryRecHits.push_back(nexthit);
00474                 boundaryEnergy += nexthit.energy();
00475                 cellGeom = subGeom->getGeometry(hitdetid);
00476                 eta = cellGeom->getPosition().eta();
00477                 boundaryET += nexthit.energy() / cosh(eta);
00478             }
00479         }
00480 
00481         if (current_status == 0 && status == 0 && atBorder) {
00482             // this is for a special case, where dead cells are at border corner
00483             currDirection = turnRight(currDirection, reverseOrientation);
00484         } else {
00485             // if dead region along a border is left, turn left
00486             if (status == 0 && atBorder) {
00487                 atBorder = false;
00488                 currDirection = turnLeft(currDirection, reverseOrientation);
00489             }
00490             if (status == 0) {
00491                 // if outside the cluster turn left to follow boundary
00492                 currDirection = turnLeft(currDirection, reverseOrientation);
00493             } else {
00494                 // else turn right to check if dead region can be left
00495                 currDirection = turnRight(currDirection, reverseOrientation);
00496             }
00497         }
00498 
00499         // save currect position
00500         current = next;
00501         current_status = status;
00502 
00503     }
00504 
00505     if (debug) {
00506         std::cout << "<<<<<<<<<<<<<<< Final Boundary object <<<<<<<<<<<<<<<" << std::endl;
00507         std::cout << "no of neighbouring RecHits: " << boundaryRecHits.size() << std::endl;
00508         std::cout << "no of neighbouring DetIds: " << boundaryDetIds.size() << std::endl;
00509         std::cout << "boundary energy: " << boundaryEnergy << std::endl;
00510         std::cout << "boundary ET: " << boundaryET << std::endl;
00511         std::cout << "no of cells contributing to boundary energy: " << beCellCounter << std::endl;
00512         std::cout << "Channel stati: ";
00513         for (std::vector<int>::iterator it = stati.begin(); it != stati.end(); ++it) {
00514             std::cout << *it << " ";
00515         }
00516         std::cout << std::endl;
00517     }
00518 
00519     BoundaryInformation boundInfo;
00520     boundInfo.subdet = hitdetid.subdet();
00521     boundInfo.detIds = boundaryDetIds;
00522     boundInfo.recHits = boundaryRecHits;
00523     boundInfo.boundaryEnergy = boundaryEnergy;
00524     boundInfo.boundaryET = boundaryET;
00525     boundInfo.nextToBorder = nextToBorder;
00526     boundInfo.channelStatus = stati;
00527 
00528     if (theEcalNav != 0) {
00529         delete theEcalNav;
00530         theEcalNav = 0;
00531     }
00532     return boundInfo;
00533 }
00534 
00535 template<class EcalDetId> BoundaryInformation EcalBoundaryInfoCalculator<EcalDetId>::gapRecHits(const edm::Handle<
00536         EcalRecHitCollection>& RecHits, const EcalRecHit* hit, const edm::ESHandle<CaloTopology> theCaloTopology,
00537         edm::ESHandle<EcalChannelStatus> ecalStatus, edm::ESHandle<CaloGeometry> geometry) {
00538 
00539     //initialize boundary information
00540     std::vector<EcalRecHit> gapRecHits;
00541     std::vector<DetId> gapDetIds;
00542 
00543     double gapEnergy = 0;
00544     double gapET = 0;
00545     int gapCellCounter = 0;
00546     bool nextToBorder = false;
00547 
00548     gapRecHits.push_back(*hit);
00549     ++gapCellCounter;
00550     gapEnergy += hit->energy();
00551     EcalDetId hitdetid = (EcalDetId) hit->id();
00552     gapDetIds.push_back(hitdetid);
00553     const CaloSubdetectorGeometry* subGeom = geometry->getSubdetectorGeometry(hitdetid);
00554     const CaloCellGeometry* cellGeom = subGeom->getGeometry(hitdetid);
00555     double eta = cellGeom->getPosition().eta();
00556     gapET += hit->energy() / cosh(eta);
00557 
00558     if (debug) {
00559         std::cout << "Find Border RecHits..." << std::endl;
00560 
00561         if (hitdetid.subdet() == EcalBarrel) {
00562             std::cout << "Starting at : (" << ((EBDetId) hitdetid).ieta() << "," << ((EBDetId) hitdetid).iphi() << ")"
00563             << std::endl;
00564 
00565         } else if (hitdetid.subdet() == EcalEndcap) {
00566             std::cout << "Starting at : (" << ((EEDetId) hitdetid).ix() << "," << ((EEDetId) hitdetid).iy() << ")"
00567             << std::endl;
00568         }
00569     }
00570 
00571     //initialize navigator
00572     initializeEcalNavigator(hitdetid, theCaloTopology, EcalDetId::subdet());
00573     CdOrientation currDirection = north;
00574     bool reverseOrientation = false;
00575 
00576     EcalDetId next(0);
00577     EcalDetId start = hitdetid;
00578     EcalDetId current = start;
00579 
00580     // Search until a invalid cell is ahead
00581     bool startAlgo = false;
00582     int noDirs = 0;
00583     while (!startAlgo) {
00584         next = makeStepInDirection(currDirection, theEcalNav);
00585         theEcalNav->setHome(start);
00586         theEcalNav->home();
00587         if (next == EcalDetId(0)) {
00588             startAlgo = true;
00589             nextToBorder = true;
00590             break;
00591         }
00592         currDirection = turnLeft(currDirection, reverseOrientation);
00593         ++noDirs;
00594         if (noDirs > 4) {
00595 
00596             std::cout << "No starting direction can be found: This should never happen if RecHit is at border!" << std::endl;
00597             throw "ERROR";
00598             break;
00599         }
00600     }
00601 
00603     CdOrientation startDirection = currDirection;
00604     currDirection = turnLeft(currDirection, reverseOrientation);
00605 
00606     // Search for next border element
00607     bool endIsFound = false;
00608     bool startIsEnd = false;
00609 
00610     while (!endIsFound) {
00611 
00612         bool nextStepFound = false;
00613         int status = 0;
00614         noDirs = 0;
00615         while (!nextStepFound) {
00616             next = makeStepInDirection(currDirection, theEcalNav);
00617             theEcalNav->setHome(current);
00618             theEcalNav->home();
00619             EcalChannelStatus::const_iterator chit = ecalStatus->find(next);
00620             status = (chit != ecalStatus->end()) ? chit->getStatusCode() & 0x1F : -1;
00621             if (status > 0) {
00622                 // Find dead cell along border -> end of cluster
00623                 endIsFound = true;
00624                 break;
00625             } else if (next == EcalDetId(0)) {
00626                 // In case the Ecal border -> go along gap
00627                 currDirection = turnLeft(currDirection, reverseOrientation);
00628             } else if (status == 0) {
00629                 if (RecHits->find(next) != RecHits->end()) {
00630                     nextStepFound = true;
00631                 } else {
00632                     endIsFound = true;
00633                     break;
00634                 }
00635             }
00636             ++noDirs;
00637             if (noDirs > 4) {
00638                 std::cout << "No valid next direction can be found: This should never happen!" << std::endl;
00639                 throw "ERROR";
00640                 break;
00641             }
00642         }
00643 
00644         // make next step
00645         next = makeStepInDirection(currDirection, theEcalNav);
00646         current = next;
00647 
00648         if (next == start) {
00649             startIsEnd = true;
00650             endIsFound = true;
00651             if (debug)
00652                 std::cout << "Path along gap reached starting position!" << std::endl;
00653         }
00654 
00655         if (debug) {
00656             std::cout << "Next step: " << (EcalDetId) next << " Status: " << status << " Start: " << (EcalDetId) start << std::endl;
00657             if (endIsFound)
00658                 std::cout << "End of gap cluster is found going left" << std::endl;
00659         }
00660 
00661         // save recHits and add energy
00662         if (!endIsFound) {
00663             gapDetIds.push_back(next);
00664             if (RecHits->find(next) != RecHits->end()) {
00665                 EcalRecHit nexthit = *RecHits->find(next);
00666                 ++gapCellCounter;
00667                 gapRecHits.push_back(nexthit);
00668                 gapEnergy += nexthit.energy();
00669                 cellGeom = subGeom->getGeometry(next);
00670                 eta = cellGeom->getPosition().eta();
00671                 gapET += nexthit.energy() / cosh(eta);
00672             }
00673         }
00674 
00675         // turn right to follow gap
00676         currDirection = turnRight(currDirection, reverseOrientation);
00677 
00678     }
00679 
00681     theEcalNav->setHome(start);
00682     theEcalNav->home();
00683     current = start;
00684     currDirection = startDirection;
00685     currDirection = turnRight(currDirection, reverseOrientation);
00686 
00687     // Search for next border element
00688     endIsFound = false;
00689 
00690     if (!startIsEnd) {
00691 
00692         while (!endIsFound) {
00693 
00694             bool nextStepFound = false;
00695             int status = 0;
00696             noDirs = 0;
00697             while (!nextStepFound) {
00698                 next = makeStepInDirection(currDirection, theEcalNav);
00699                 theEcalNav->setHome(current);
00700                 theEcalNav->home();
00701                 EcalChannelStatus::const_iterator chit = ecalStatus->find(next);
00702                 status = (chit != ecalStatus->end()) ? chit->getStatusCode() & 0x1F : -1;
00703                 if (status > 0) {
00704                     // Find dead cell along border -> end of cluster
00705                     endIsFound = true;
00706                     break;
00707                 } else if (next == EcalDetId(0)) {
00708                     // In case the Ecal border -> go along gap
00709                     currDirection = turnRight(currDirection, reverseOrientation);
00710                 } else if (status == 0) {
00711                     if (RecHits->find(next) != RecHits->end()) {
00712                         nextStepFound = true;
00713                     } else {
00714                         endIsFound = true;
00715                         break;
00716                     }
00717                 }
00718                 ++noDirs;
00719                 if (noDirs > 4) {
00720                     std::cout << "No valid next direction can be found: This should never happen!" << std::endl;
00721                     throw "ERROR";
00722                     break;
00723                 }
00724             }
00725 
00726             // make next step
00727             next = makeStepInDirection(currDirection, theEcalNav);
00728             current = next;
00729 
00730             if (debug) {
00731                 std::cout << "Next step: " << (EcalDetId) next << " Status: " << status << " Start: " << (EcalDetId) start
00732                 << std::endl;
00733                 if (endIsFound)
00734                     std::cout << "End of gap cluster is found going right" << std::endl;
00735             }
00736 
00737             // save recHits and add energy
00738             if (!endIsFound) {
00739                 gapDetIds.push_back(next);
00740                 if (RecHits->find(next) != RecHits->end()) {
00741                     EcalRecHit nexthit = *RecHits->find(next);
00742                     ++gapCellCounter;
00743                     gapRecHits.push_back(nexthit);
00744                     gapEnergy += nexthit.energy();
00745                     cellGeom = subGeom->getGeometry(next);
00746                     eta = cellGeom->getPosition().eta();
00747                     gapET += nexthit.energy() / cosh(eta);
00748                 }
00749             }
00750 
00751             // turn left to follow gap
00752             currDirection = turnLeft(currDirection, reverseOrientation);
00753 
00754         }
00755     }
00756 
00757     if (debug) {
00758         std::cout << "<<<<<<<<<<<<<<< Final Gap object <<<<<<<<<<<<<<<" << std::endl;
00759         std::cout << "No of RecHits along gap: " << gapRecHits.size() << std::endl;
00760         std::cout << "No of DetIds along gap: " << gapDetIds.size() << std::endl;
00761         std::cout << "Gap energy: " << gapEnergy << std::endl;
00762         std::cout << "Gap ET: " << gapET << std::endl;
00763     }
00764 
00765     BoundaryInformation gapInfo;
00766     gapInfo.subdet = hitdetid.subdet();
00767     gapInfo.detIds = gapDetIds;
00768     gapInfo.recHits = gapRecHits;
00769     gapInfo.boundaryEnergy = gapEnergy;
00770     gapInfo.boundaryET = gapET;
00771     gapInfo.nextToBorder = nextToBorder;
00772     std::vector<int> stati;
00773     gapInfo.channelStatus = stati;
00774 
00775     if (theEcalNav != 0) {
00776         delete theEcalNav;
00777         theEcalNav = 0;
00778     }
00779     return gapInfo;
00780 }
00781 
00782 #endif /*ECALBOUNDARYINFOCALCULATOR_H_*/