CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_6/src/FastSimulation/CaloGeometryTools/src/CaloGeometryHelper.cc

Go to the documentation of this file.
00001 #include "FastSimulation/CaloGeometryTools/interface/CaloGeometryHelper.h"
00002 
00003 //#include "FWCore/ParameterSet/interface/ParameterSet.h"
00004 
00005 // needed for the debugging
00006 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00007 #include "Geometry/EcalAlgo/interface/EcalBarrelGeometry.h"
00008 #include "Geometry/EcalAlgo/interface/EcalEndcapGeometry.h"
00009 #include "Geometry/CaloTopology/interface/CaloSubdetectorTopology.h"
00010 
00011 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00012 #include "DataFormats/EcalDetId/interface/EEDetId.h"
00013 #include "DataFormats/EcalDetId/interface/ESDetId.h"
00014 #include "DataFormats/HcalDetId/interface/HcalDetId.h"
00015 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00016 #include "Geometry/EcalAlgo/interface/EcalPreshowerGeometry.h"
00017 
00018 #include "FastSimulation/CaloGeometryTools/interface/DistanceToCell.h"
00019 #include "FastSimulation/CaloGeometryTools/interface/Crystal.h"
00020 
00021 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00022 
00023 #include <algorithm>
00024 
00025 CaloGeometryHelper::CaloGeometryHelper():Calorimeter()
00026 {
00027   neighbourmapcalculated_= false;
00028   psLayer1Z_ = 303;
00029   psLayer2Z_ = 307;
00030 }
00031 
00032 CaloGeometryHelper::CaloGeometryHelper(const edm::ParameterSet& fastCalo):Calorimeter(fastCalo)
00033 {
00034   //  std::cout << " In the constructor with ParameterSet " << std::endl;
00035   psLayer1Z_ = 303;
00036   psLayer2Z_ = 307;
00037 }
00038 
00039 void CaloGeometryHelper::initialize(double bField)
00040 {
00041   buildCrystalArray();
00042   buildNeighbourArray();
00043   bfield_ = bField;
00044   preshowerPresent_=(getEcalPreshowerGeometry()!=0);
00045     
00046   if(preshowerPresent_)
00047     {
00048       ESDetId cps1(getEcalPreshowerGeometry()->getClosestCellInPlane(GlobalPoint(80.,80.,303.),1));
00049       psLayer1Z_ = getEcalPreshowerGeometry()->getGeometry(cps1)->getPosition().z();
00050       ESDetId cps2(getEcalPreshowerGeometry()->getClosestCellInPlane(GlobalPoint(80.,80.,307.),2));
00051       psLayer2Z_ = getEcalPreshowerGeometry()->getGeometry(cps2)->getPosition().z();
00052       LogDebug("CaloGeometryTools")  << " Preshower layer positions " << psLayer1Z_ << " " << psLayer2Z_ << std::endl;
00053     }
00054   else
00055     LogDebug("CaloGeometryTools")  << " No preshower present" << std::endl;
00056 
00057   //  std::cout << " Preshower layer positions " << psLayer1Z_ << " " << psLayer2Z_ << std::endl;
00058 
00059 }
00060 
00061 CaloGeometryHelper::~CaloGeometryHelper()
00062 {;
00063 }
00064 
00065 DetId CaloGeometryHelper::getClosestCell(const XYZPoint& point, bool ecal, bool central) const
00066 {
00067   DetId result;
00068   if(ecal)
00069     {
00070       if(central)
00071         {
00072           //      std::cout << "EcalBarrelGeometry_" << " " << EcalBarrelGeometry_ << std::endl;
00073           result = EcalBarrelGeometry_->getClosestCell(GlobalPoint(point.X(),point.Y(),point.Z()));
00074 #ifdef DEBUGGCC
00075           if(result.null()) return result;
00076           GlobalPoint ip=GlobalPoint(point.X(),point.Y(),point.Z());
00077           GlobalPoint cc=EcalBarrelGeometry_->getGeometry(result)->getPosition();
00078           float deltaeta2 = ip.eta()-cc.eta();
00079           deltaeta2 *= deltaeta2;
00080           float deltaphi2 = acos(cos(ip.phi()-cc.phi()));
00081           deltaphi2 *= deltaphi2;
00082           Histos::instance()->fill("h100",point.eta(),sqrt(deltaeta2+deltaphi2));
00083 #endif
00084         }
00085       else
00086         {
00087           result = EcalEndcapGeometry_->getClosestCell(GlobalPoint(point.X(),point.Y(),point.Z()));
00088 #ifdef DEBUGGCC
00089           if(result.null()) 
00090             {
00091               return result;
00092             }
00093           GlobalPoint ip=GlobalPoint(point.X(),point.Y(),point.Z());
00094           GlobalPoint cc=EcalEndcapGeometry_->getGeometry(result)->getPosition();
00095           Histos::instance()->fill("h110",point.eta(),(ip-cc).perp());
00096 #endif
00097         }
00098     }
00099   else
00100     {
00101       result=HcalGeometry_->getClosestCell(GlobalPoint(point.X(),point.Y(),point.Z()));
00102       HcalDetId myDetId(result);
00103 
00104       // special patch for HF
00105       if ( myDetId.subdetId() == HcalForward ) {
00106         int mylayer;
00107         if ( fabs(point.Z()) > 1132. ) {
00108           mylayer = 2;
00109         } else {
00110           mylayer = 1;
00111         }
00112         HcalDetId myDetId2((HcalSubdetector)myDetId.subdetId(),myDetId.ieta(),myDetId.iphi(),mylayer);
00113         result = myDetId2;
00114         return result;
00115       }
00116 
00117 
00118       if(result.subdetId()!=HcalEndcap) return result;
00119       // Special patch to correct the HCAL geometry
00120       if(myDetId.depth()==3) return result;
00121 
00122       int ieta=myDetId.ietaAbs();
00123       float azmin=400.458;         
00124 
00125       if(ieta<=17) 
00126         return result;
00127       else if(ieta>=18 && ieta<=26) 
00128         azmin += 35.0;    // don't consider ieta=18 nose separately
00129       else if(ieta>=27)
00130         azmin += 21.0;
00131 
00132       HcalDetId first(HcalEndcap,myDetId.ieta(),myDetId.iphi(),1);
00133       bool layer2=(fabs(point.Z())>azmin);
00134       if(!layer2)
00135         {
00136           return first;
00137         }
00138       else
00139         {
00140           HcalDetId second(HcalEndcap,myDetId.ieta(),myDetId.iphi(),2);
00141           if(second!=HcalDetId()) result=second;
00142         }
00143 #ifdef DEBUGGCC
00144       if(result.null()) 
00145         {
00146           return result;
00147         }
00148       GlobalPoint ip=GlobalPoint(point.x(),point.y(),point.z());
00149       GlobalPoint cc=HcalGeometry_->getGeometry(result)->getPosition();
00150       float deltaeta2 = ip.eta()-cc.eta();
00151       deltaeta2 *= deltaeta2;
00152       float deltaphi2 = acos(cos(ip.phi()-cc.phi()));
00153       deltaphi2 *= deltaphi2;
00154 
00155       Histos::instance()->fill("h120",point.eta(),sqrt(deltaeta2+deltaphi2));
00156 #endif
00157       
00158     }
00159   return result;
00160 }
00161 
00162 void CaloGeometryHelper::getWindow(const DetId& pivot,int s1,int s2,std::vector<DetId>& vec) const
00163 {
00164   // currently the getWindow method is the same for EcalBarrelTopology and EndcapTopology
00165   // (implemented in CaloSubDetectorTopology)
00166   // optimized versions are foreseen 
00167   vec=getEcalTopology(pivot.subdetId())->getWindow(pivot,s1,s2);
00168   DistanceToCell distance(getEcalGeometry(pivot.subdetId()),pivot);
00169   sort(vec.begin(),vec.end(),distance);
00170 }
00171 
00172 void CaloGeometryHelper::buildCrystal(const DetId & cell,Crystal& xtal) const
00173 {
00174   if(cell.subdetId()==EcalBarrel)
00175     {
00176       xtal=Crystal(cell,&barrelCrystals_[EBDetId(cell).hashedIndex()]);
00177       return;
00178     }
00179   if(cell.subdetId()==EcalEndcap)
00180     {
00181       xtal=Crystal(cell,&endcapCrystals_[EEDetId(cell).hashedIndex()]);
00182       return;
00183     }     
00184 }
00185 
00186 // Build the array of (max)8 neighbors
00187 void CaloGeometryHelper::buildNeighbourArray()
00188 {
00189 
00190   static const CaloDirection orderedDir[8]={SOUTHWEST,SOUTH,SOUTHEAST,WEST,EAST,NORTHWEST,NORTH,
00191                                             NORTHEAST};
00192 
00193   const unsigned nbarrel = EBDetId::kSizeForDenseIndexing;
00194   // Barrel first. The hashed index runs from 0 to 61199
00195   barrelNeighbours_.resize(nbarrel);
00196   
00197   //std::cout << " Building the array of neighbours (barrel) " ;
00198 
00199   const std::vector<DetId>&  vec(EcalBarrelGeometry_->getValidDetIds(DetId::Ecal,EcalBarrel));
00200   unsigned size=vec.size();    
00201   for(unsigned ic=0; ic<size; ++ic) 
00202     {
00203       // We get the 9 cells in a square. 
00204       std::vector<DetId> neighbours(EcalBarrelTopology_->getWindow(vec[ic],3,3));
00205       //      std::cout << " Cell " << EBDetId(vec[ic]) << std::endl;
00206       unsigned nneighbours=neighbours.size();
00207 
00208       unsigned hashedindex=EBDetId(vec[ic]).hashedIndex();
00209       if(hashedindex>=nbarrel)
00210         {
00211           LogDebug("CaloGeometryTools")  << " Array overflow " << std::endl;
00212         }
00213 
00214 
00215       // If there are 9 cells, it is easy, and this order is know:
00216 //      6  7  8
00217 //      3  4  5 
00218 //      0  1  2   (0 = SOUTHWEST)
00219 
00220       if(nneighbours==9)
00221         {
00222           barrelNeighbours_[hashedindex].reserve(8);
00223           for(unsigned in=0;in<nneighbours;++in)
00224             {
00225               // remove the centre
00226               if(neighbours[in]!=vec[ic]) 
00227                 {
00228                   barrelNeighbours_[hashedindex].push_back(neighbours[in]);
00229                   //          std::cout << " Neighbour " << in << " " << EBDetId(neighbours[in]) << std::endl;
00230                 }
00231             }
00232         }
00233       else
00234         {
00235           DetId central(vec[ic]);
00236           barrelNeighbours_[hashedindex].resize(8,DetId(0));
00237           for(unsigned idir=0;idir<8;++idir)
00238             {
00239               DetId testid=central;
00240               bool status=move(testid,orderedDir[idir],false);
00241               if(status) barrelNeighbours_[hashedindex][idir]=testid;
00242             }
00243 
00244         }
00245     }
00246 
00247   // Moved to the endcap
00248 
00249   //  std::cout << " done " << size << std::endl;
00250   //  std::cout << " Building the array of neighbours (endcap) " ;
00251 
00252 
00253   const std::vector<DetId> & vece(EcalEndcapGeometry_->getValidDetIds(DetId::Ecal,EcalEndcap));
00254   size=vece.size();    
00255   // There are some holes in the hashedIndex for the EE. Hence the array is bigger than the number
00256   // of crystals
00257   const unsigned nendcap=EEDetId::kSizeForDenseIndexing;
00258 
00259   endcapNeighbours_.resize(nendcap);
00260   for(unsigned ic=0; ic<size; ++ic) 
00261     {
00262       // We get the 9 cells in a square. 
00263       std::vector<DetId> neighbours(EcalEndcapTopology_->getWindow(vece[ic],3,3));
00264       unsigned nneighbours=neighbours.size();
00265       // remove the centre
00266       unsigned hashedindex=EEDetId(vece[ic]).hashedIndex();
00267       
00268       if(hashedindex>=nendcap)
00269         {
00270           LogDebug("CaloGeometryTools")  << " Array overflow " << std::endl;
00271         }
00272 
00273       if(nneighbours==9)
00274         {
00275           endcapNeighbours_[hashedindex].reserve(8);
00276           for(unsigned in=0;in<nneighbours;++in)
00277             {     
00278               // remove the centre
00279               if(neighbours[in]!=vece[ic]) 
00280                 {
00281                   endcapNeighbours_[hashedindex].push_back(neighbours[in]);
00282                 }
00283             }
00284         }
00285       else
00286         {
00287           DetId central(vece[ic]);
00288           endcapNeighbours_[hashedindex].resize(8,DetId(0));
00289           for(unsigned idir=0;idir<8;++idir)
00290             {
00291               DetId testid=central;
00292               bool status=move(testid,orderedDir[idir],false);
00293               if(status) endcapNeighbours_[hashedindex][idir]=testid;
00294             }
00295 
00296         }
00297     }
00298   //  std::cout << " done " << size <<std::endl;
00299   neighbourmapcalculated_ = true;
00300 }
00301 
00302 const std::vector<DetId>& CaloGeometryHelper::getNeighbours(const DetId& detid) const
00303 {
00304   return (detid.subdetId()==EcalBarrel)?barrelNeighbours_[EBDetId(detid).hashedIndex()]:
00305     endcapNeighbours_[EEDetId(detid).hashedIndex()];
00306 }
00307 
00308 bool CaloGeometryHelper::move(DetId& cell, const CaloDirection&dir,bool fast) const
00309 {  
00310   DetId originalcell = cell; 
00311   if(dir==NONE || cell==DetId(0)) return false;
00312 
00313   // Conversion CaloDirection and index in the table
00314   // CaloDirection :NONE,SOUTH,SOUTHEAST,SOUTHWEST,EAST,WEST, NORTHEAST,NORTHWEST,NORTH
00315   // Table : SOUTHWEST,SOUTH,SOUTHEAST,WEST,EAST,NORTHWEST,NORTH, NORTHEAST
00316   static const int calodirections[9]={-1,1,2,0,4,3,7,5,6};
00317     
00318   if(fast&&neighbourmapcalculated_)
00319     {
00320       DetId result = (originalcell.subdetId()==EcalBarrel) ? 
00321         barrelNeighbours_[EBDetId(originalcell).hashedIndex()][calodirections[dir]]:
00322         endcapNeighbours_[EEDetId(originalcell).hashedIndex()][calodirections[dir]];
00323       bool status =  !result.null();
00324       cell = result;
00325       return status; 
00326     }
00327   
00328   if(dir==NORTH || dir ==SOUTH || dir==EAST || dir==WEST)
00329     {
00330       return simplemove(cell,dir);
00331     }
00332   else
00333     {
00334       if(dir == NORTHEAST || dir==NORTHWEST || dir==SOUTHEAST || dir==SOUTHWEST)
00335         return diagonalmove(cell,dir);
00336     }
00337   
00338   cell = DetId(0);
00339   return false;
00340 }
00341 
00342 
00343 bool CaloGeometryHelper::simplemove(DetId& cell, const CaloDirection& dir) const
00344 {
00345   std::vector<DetId> neighbours;
00346   if(cell.subdetId()==EcalBarrel)
00347     neighbours = EcalBarrelTopology_->getNeighbours(cell,dir);
00348   else if(cell.subdetId()==EcalEndcap)
00349     neighbours= EcalEndcapTopology_->getNeighbours(cell,dir);
00350   
00351   if(neighbours.size()>0 && !neighbours[0].null())
00352     {
00353       cell = neighbours[0];
00354       return true;
00355     }
00356   else 
00357     {
00358       cell = DetId(0);
00359       return false;
00360     }
00361 }
00362 
00363 bool CaloGeometryHelper::diagonalmove(DetId& cell, const CaloDirection& dir) const
00364 {
00365   bool result; 
00366   // One has to try both paths
00367   if(dir==NORTHEAST)
00368     {
00369       result = simplemove(cell,NORTH);
00370       if(result)
00371         return simplemove(cell,EAST);
00372       else
00373         {
00374           result = simplemove(cell,EAST);
00375           if(result)
00376             return simplemove(cell,NORTH);
00377           else
00378             return false; 
00379         }
00380     }
00381   else if(dir==NORTHWEST)
00382     {
00383       result = simplemove(cell,NORTH);
00384       if(result)
00385         return simplemove(cell,WEST);
00386       else
00387         {
00388           result = simplemove(cell,WEST);
00389           if(result)
00390             return simplemove(cell,NORTH);
00391           else
00392             return false; 
00393         }
00394     }
00395   else if(dir == SOUTHEAST)
00396     {
00397       result = simplemove(cell,SOUTH);
00398       if(result)
00399         return simplemove(cell,EAST);
00400       else
00401         {
00402           result = simplemove(cell,EAST);
00403           if(result)
00404             return simplemove(cell,SOUTH);
00405           else
00406             return false; 
00407         }
00408     }
00409   else if(dir == SOUTHWEST)
00410     {
00411       result = simplemove(cell,SOUTH);
00412       if(result)
00413         return simplemove(cell,WEST);
00414       else
00415         {
00416           result = simplemove(cell,SOUTH);
00417           if(result)
00418             return simplemove(cell,WEST);
00419           else
00420             return false; 
00421         }
00422     }
00423   cell = DetId(0);
00424   return false;
00425 }
00426 
00427 bool CaloGeometryHelper::borderCrossing(const DetId& c1, const DetId& c2) const
00428 {
00429   if(c1.subdetId()!=c2.subdetId()) return false;
00430 
00431   if(c1.subdetId()==EcalBarrel)
00432     {
00433       // there is a crack if the two cells don't belong to the same 
00434       // module
00435       EBDetId cc1(c1);
00436       EBDetId cc2(c2);
00437       return (cc1.im()!=cc2.im()||cc1.ism()!=cc2.ism() );
00438     }
00439   
00440 if(c1.subdetId()==EcalEndcap)
00441     {
00442       // there is a crack if the two cells don't belong to the same 
00443       // module
00444       return (EEDetId(c1).isc()!=EEDetId(c2).isc());
00445     }
00446  return false;
00447 }
00448 
00449 void CaloGeometryHelper::buildCrystalArray()
00450 {
00451   const unsigned nbarrel = EBDetId::kSizeForDenseIndexing;
00452   // Barrel first. The hashed index runs from 0 to 61199
00453   barrelCrystals_.resize(nbarrel,BaseCrystal());
00454 
00455   //std::cout << " Building the array of crystals (barrel) " ;
00456   const std::vector<DetId>&  vec(EcalBarrelGeometry_->getValidDetIds(DetId::Ecal,EcalBarrel));
00457   unsigned size=vec.size();    
00458   const CaloCellGeometry * geom=0;
00459   for(unsigned ic=0; ic<size; ++ic) 
00460     {
00461       unsigned hashedindex=EBDetId(vec[ic]).hashedIndex();
00462       geom = EcalBarrelGeometry_->getGeometry(vec[ic]);
00463       BaseCrystal xtal(vec[ic]);
00464       xtal.setCorners(geom->getCorners(),geom->getPosition());
00465       barrelCrystals_[hashedindex]=xtal;
00466     }
00467   
00468   //  std::cout << " done " << size << std::endl;
00469   //  std::cout << " Building the array of crystals (endcap) " ;
00470   
00471 
00472   const std::vector<DetId>&  vece(EcalEndcapGeometry_->getValidDetIds(DetId::Ecal,EcalEndcap));
00473   size=vece.size();    
00474   // There are some holes in the hashedIndex for the EE. Hence the array is bigger than the number
00475   // of crystals
00476   const unsigned nendcap=EEDetId::kSizeForDenseIndexing;
00477 
00478   endcapCrystals_.resize(nendcap,BaseCrystal());
00479   for(unsigned ic=0; ic<size; ++ic) 
00480     {
00481       unsigned hashedindex=EEDetId(vece[ic]).hashedIndex();
00482       geom = EcalEndcapGeometry_->getGeometry(vece[ic]);
00483       BaseCrystal xtal(vece[ic]);
00484       xtal.setCorners(geom->getCorners(),geom->getPosition());
00485       endcapCrystals_[hashedindex]=xtal;
00486     }
00487   //  std::cout << " done " << size << std::endl;
00488 }