CMS 3D CMS Logo

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