CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/RecoParticleFlow/PFClusterProducer/plugins/PFRecHitProducerHO.cc

Go to the documentation of this file.
00001 #include "RecoParticleFlow/PFClusterProducer/plugins/PFRecHitProducerHO.h"
00002 
00003 #include <memory>
00004 
00005 #include "DataFormats/ParticleFlowReco/interface/PFRecHit.h"
00006 
00007 #include "DataFormats/HcalRecHit/interface/HORecHit.h"
00008 #include "DataFormats/HcalRecHit/interface/HcalRecHitCollections.h"
00009 #include "DataFormats/HcalDetId/interface/HcalSubdetector.h"
00010 
00011 #include "DataFormats/DetId/interface/DetId.h"
00012 #include "DataFormats/EcalDetId/interface/EEDetId.h"
00013 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00014 
00015 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00016 #include "FWCore/Framework/interface/ESHandle.h"
00017 #include "FWCore/Framework/interface/EventSetup.h"
00018 
00019 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00020 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00021 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00022 #include "Geometry/CaloGeometry/interface/TruncatedPyramid.h"
00023 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00024 
00025 #include "Geometry/CaloTopology/interface/HcalTopology.h"
00026 #include "DataFormats/CaloTowers/interface/CaloTowerCollection.h"
00027 
00028 #include "Geometry/CaloTopology/interface/CaloTowerTopology.h"
00029 #include "RecoCaloTools/Navigation/interface/CaloTowerNavigator.h"
00030 
00031 #include "RecoLocalCalo/HcalRecAlgos/interface/HcalCaloFlagLabels.h"
00032 #include "RecoCaloTools/Navigation/interface/CaloNavigator.h"
00033 
00034 // Necessary includes for identify severity of flagged problems in HO rechits
00035 #include "RecoLocalCalo/HcalRecAlgos/interface/HcalCaloFlagLabels.h"
00036 #include "RecoLocalCalo/HcalRecAlgos/interface/HcalSeverityLevelComputer.h"
00037 #include "RecoLocalCalo/HcalRecAlgos/interface/HcalSeverityLevelComputerRcd.h"
00038 #include "CondFormats/HcalObjects/interface/HcalChannelQuality.h"
00039 
00040 using namespace std;
00041 using namespace edm;
00042 
00043 PFRecHitProducerHO::PFRecHitProducerHO(const edm::ParameterSet& iConfig)
00044   : PFRecHitProducer(iConfig) {
00045   
00046   // access to the collections of rechits
00047   inputTagHORecHits_ = 
00048     iConfig.getParameter<InputTag>("recHitsHO");
00049   
00050   HOMaxAllowedSev_ = iConfig.getParameter<int>("HOMaxAllowedSev");
00051   neighbourmapcalculated_ = false;
00052 }
00053 
00054 
00055 
00056 PFRecHitProducerHO::~PFRecHitProducerHO() {}
00057 
00058 void 
00059 PFRecHitProducerHO::createRecHits(vector<reco::PFRecHit>& rechits,
00060                                   vector<reco::PFRecHit>& rechitsCleaned,
00061                                   edm::Event& iEvent, 
00062                                   const edm::EventSetup& iSetup ) {
00063 
00064 
00065 
00066   // this map is necessary to find the rechit neighbours efficiently
00067   //C but I should think about using Florian's hashed index to do this.
00068   //C in which case the map might not be necessary anymore
00069   // 
00070   // the key of this map is detId. 
00071   // the value is the index in the rechits vector
00072   map<unsigned, unsigned > idSortedRecHits;
00073   //   typedef map<unsigned, unsigned >::iterator IDH;
00074   
00075   edm::ESHandle<CaloGeometry> geoHandle;
00076   iSetup.get<CaloGeometryRecord>().get(geoHandle);
00077   
00078   // get the HO geometry
00079   const CaloSubdetectorGeometry *hcalBarrelGeometry = 
00080     geoHandle->getSubdetectorGeometry(DetId::Hcal, HcalOuter);
00081   
00082   // get the HO topology
00083   HcalTopology hcalBarrelTopology; // (geoHandle);
00084   
00085   if(!neighbourmapcalculated_)
00086     hoNeighbArray( *hcalBarrelGeometry,
00087                    hcalBarrelTopology);
00088 
00089   // Get Hcal Severity Level Computer, so that the severity of each rechit flag/status may be determined
00090   edm::ESHandle<HcalSeverityLevelComputer> hcalSevLvlComputerHndl;
00091   iSetup.get<HcalSeverityLevelComputerRcd>().get(hcalSevLvlComputerHndl);
00092   const HcalSeverityLevelComputer* hcalSevLvlComputer = hcalSevLvlComputerHndl.product();
00093 
00094   
00095   // get the HO rechits
00096   
00097   edm::Handle<HORecHitCollection> rhcHandle;
00098   
00099   
00100   bool found = iEvent.getByLabel(inputTagHORecHits_, 
00101                                  rhcHandle);
00102   
00103   if(!found) {
00104     
00105     ostringstream err;
00106     err<<"could not find rechits "<<inputTagHORecHits_;
00107     LogError("PFRecHitProducerHO")<<err.str()<<endl;
00108     
00109     throw cms::Exception( "MissingProduct", err.str());
00110   }
00111   else {
00112     assert( rhcHandle.isValid() );
00113     
00114     // process HO rechits
00115     for(unsigned i=0; i<rhcHandle->size(); i++) {
00116       
00117       const HORecHit& erh = (*rhcHandle)[i];
00118       const HcalDetId& detid = (HcalDetId)erh.detid();
00119       
00120       double energy = erh.energy();
00121       // uint32_t flag = erh.recoFlag();
00122       double time = erh.time();
00123       
00124       HcalSubdetector esd=(HcalSubdetector)detid.subdetId();
00125       
00126       if (esd != 3) continue;
00127       
00128       int hoeta=detid.ieta();
00129       if ( (abs(hoeta)<=4 && energy < thresh_Barrel_) || 
00130            (abs(hoeta)> 4 && energy < thresh_Endcap_) ) continue;
00131       
00132 
00133       // Get Channel Quality information for the given detID
00134       const HcalChannelStatus* theStatus = theHcalChStatus->getValues(detid);
00135       unsigned theStatusValue = theStatus->getValue();
00136       // Now get severity of problems for the given detID, based on the rechit flag word and the channel quality status value
00137       int hitSeverity=hcalSevLvlComputer->getSeverityLevel(detid, erh.flags(),theStatusValue);
00138     
00139       // Skip hits whose problems are more severe than max accept level.  In the future, allow for cleaning of such hits?
00140       // Note:  As of April 2012, by default, all HO hits in rings +/-1, +/-2 should be identified as either "remove from calotowers" or "remove from rechit collections" in the channel quality database, and thus should be rejected by this conditional statement.
00141       if (hitSeverity>HOMaxAllowedSev_) 
00142         {
00143           //std::cout <<"Rejecting HO hit HO("<<hoeta<<", "<<detid.iphi()<<", "<<detid.depth()<<std::endl;
00144           continue;
00145         }  
00146 
00147 
00148       
00149       reco::PFRecHit *pfrh = createHORecHit(detid, energy,  
00150                                             PFLayer::HCAL_BARREL2, // HO,
00151                                             hcalBarrelGeometry);
00152       
00153       if( !pfrh ) continue; // problem with this rechit. skip it
00154       
00155       pfrh->setRescale(time);
00156       
00157       rechits.push_back( *pfrh );
00158       delete pfrh;
00159       idSortedRecHits.insert( make_pair(detid.rawId(), rechits.size()-1 ) ); 
00160     }      
00161   }
00162   
00163   // do navigation
00164   for(unsigned i=0; i<rechits.size(); i++ ) {
00165     findRecHitNeighboursHO( rechits[i], idSortedRecHits ); 
00166   }
00167   
00168 } 
00169 
00170 
00171 reco::PFRecHit* 
00172 PFRecHitProducerHO::createHORecHit( const DetId& detid,
00173                                     double energy,
00174                                     PFLayer::Layer layer,
00175                                     const CaloSubdetectorGeometry* geom ) {
00176   
00177   math::XYZVector position;
00178   math::XYZVector axis;
00179   
00180   const CaloCellGeometry *thisCell 
00181     = geom->getGeometry(detid);
00182   
00183   // find rechit geometry
00184   if(!thisCell) {
00185     LogError("PFRecHitProducerHO")
00186       <<"warning detid "<<detid.rawId()
00187       <<" not found in geometry"<<endl;
00188     return 0;
00189   }
00190   
00191   double sclel0l1r=0.946; //384.8/406.6
00192   
00193   if (abs(thisCell->getPosition().z())>130) {
00194     position.SetCoordinates ( sclel0l1r*thisCell->getPosition().x(),
00195                               sclel0l1r*thisCell->getPosition().y(),
00196                               sclel0l1r*thisCell->getPosition().z() );   
00197     
00198   } else {
00199     position.SetCoordinates ( thisCell->getPosition().x(),
00200                               thisCell->getPosition().y(),
00201                               thisCell->getPosition().z() );
00202   }
00203   
00204   // the axis vector is the difference 
00205   
00206   //   const TruncatedPyramid* pyr 
00207   //     = dynamic_cast< const TruncatedPyramid* > (thisCell);    
00208   //   if( pyr ) {
00209   //     axis.SetCoordinates( pyr->getPosition(1).x(), 
00210   //                     pyr->getPosition(1).y(), 
00211   //                     pyr->getPosition(1).z() ); 
00212   
00213   //     math::XYZVector axis0( pyr->getPosition(0).x(), 
00214   //                       pyr->getPosition(0).y(), 
00215   //                       pyr->getPosition(0).z() );
00216   
00217   //     axis -= axis0;    
00218   //   }
00219   //   else return 0;
00220   
00221   axis = math::XYZVector(0,0,0);
00222   
00223   //   if( !geomfound ) {
00224   //     LogError("PFRecHitProducerHO")<<"cannor find geometry for detid "
00225   //                             <<detid.rawId()<<" in layer "<<layer<<endl;
00226   //     return 0; // geometry not found, skip rechit
00227   //   }
00228   
00229   
00230   reco::PFRecHit *rh 
00231     = new reco::PFRecHit( detid.rawId(), layer, 
00232                           energy, 
00233                           position.x(), position.y(), position.z(), 
00234                           axis.x(), axis.y(), axis.z() ); 
00235   
00236   const CaloCellGeometry::CornersVec& corners = thisCell->getCorners();
00237   assert( corners.size() == 8 );
00238   
00239   if (abs(corners[0].z())>130.0) {
00240     rh->setNECorner( sclel0l1r*corners[0].x(), sclel0l1r*corners[0].y(),  sclel0l1r*corners[0].z() );
00241     rh->setSECorner( sclel0l1r*corners[1].x(), sclel0l1r*corners[1].y(),  sclel0l1r*corners[1].z() );
00242     rh->setSWCorner( sclel0l1r*corners[2].x(), sclel0l1r*corners[2].y(),  sclel0l1r*corners[2].z() );
00243     rh->setNWCorner( sclel0l1r*corners[3].x(), sclel0l1r*corners[3].y(),  sclel0l1r*corners[3].z() );
00244     
00245   } else {
00246     rh->setNECorner( corners[0].x(), corners[0].y(),  corners[0].z() );
00247     rh->setSECorner( corners[1].x(), corners[1].y(),  corners[1].z() );
00248     rh->setSWCorner( corners[2].x(), corners[2].y(),  corners[2].z() );
00249     rh->setNWCorner( corners[3].x(), corners[3].y(),  corners[3].z() );
00250   }
00251   
00252   return rh;
00253 }
00254 
00255 
00256 bool
00257 PFRecHitProducerHO::findHORecHitGeometry(const DetId& detid, 
00258                                          const CaloSubdetectorGeometry* geom,
00259                                          math::XYZVector& position, 
00260                                          math::XYZVector& axis ) {
00261   
00262   
00263   const CaloCellGeometry *thisCell 
00264     = geom->getGeometry(detid);
00265   
00266   // find rechit geometry
00267   if(!thisCell) {
00268     LogError("PFRecHitProducerHO")
00269       <<"warning detid "<<detid.rawId()
00270       <<" not found in geometry"<<endl;
00271     return false;
00272   }
00273   
00274   position.SetCoordinates ( thisCell->getPosition().x(),
00275                             thisCell->getPosition().y(),
00276                             thisCell->getPosition().z() );
00277   
00278   
00279   
00280   // the axis vector is the difference 
00281   //   const TruncatedPyramid* pyr 
00282   //     = dynamic_cast< const TruncatedPyramid* > (thisCell);    
00283   //   if( pyr ) {
00284   //     axis.SetCoordinates( pyr->getPosition(1).x(), 
00285   //                     pyr->getPosition(1).y(), 
00286   //                     pyr->getPosition(1).z() ); 
00287   
00288   //     math::XYZVector axis0( pyr->getPosition(0).x(), 
00289   //                       pyr->getPosition(0).y(), 
00290   //                       pyr->getPosition(0).z() );
00291   
00292   //     axis -= axis0;
00293   
00294   
00295   //     return true;
00296   //   }
00297   
00298   axis = math::XYZVector(0,0,0);
00299   return true;
00300   
00301   //  else return false;
00302 }
00303 
00304 
00305 
00306 void 
00307 PFRecHitProducerHO::findRecHitNeighboursHO
00308 ( reco::PFRecHit& rh, 
00309   const map<unsigned,unsigned >& sortedHits ) {
00310   
00311   DetId center( rh.detId() );
00312   
00313   
00314   DetId north = move( center, NORTH );
00315   DetId northeast = move( center, NORTHEAST );
00316   DetId northwest = move( center, NORTHWEST ); 
00317   DetId south = move( center, SOUTH );  
00318   DetId southeast = move( center, SOUTHEAST );  
00319   DetId southwest = move( center, SOUTHWEST );  
00320   DetId east  = move( center, EAST );  
00321   DetId west  = move( center, WEST );  
00322   
00323   IDH i = sortedHits.find( north.rawId() );
00324   if(i != sortedHits.end() ) 
00325     rh.add4Neighbour( i->second );
00326   
00327   i = sortedHits.find( northeast.rawId() );
00328   if(i != sortedHits.end() ) 
00329     rh.add8Neighbour( i->second );
00330   
00331   i = sortedHits.find( south.rawId() );
00332   if(i != sortedHits.end() ) 
00333     rh.add4Neighbour( i->second );
00334   
00335   i = sortedHits.find( southwest.rawId() );
00336   if(i != sortedHits.end() ) 
00337     rh.add8Neighbour( i->second );
00338   
00339   i = sortedHits.find( east.rawId() );
00340   if(i != sortedHits.end() ) 
00341     rh.add4Neighbour( i->second );
00342   
00343   i = sortedHits.find( southeast.rawId() );
00344   if(i != sortedHits.end() ) 
00345     rh.add8Neighbour( i->second );
00346   
00347   i = sortedHits.find( west.rawId() );
00348   if(i != sortedHits.end() ) 
00349     rh.add4Neighbour( i->second );
00350   
00351   i = sortedHits.find( northwest.rawId() );
00352   if(i != sortedHits.end() ) 
00353     rh.add8Neighbour( i->second );
00354 }
00355 
00356 
00357 // Build the array of (max)8 neighbors
00358 void 
00359 PFRecHitProducerHO::hoNeighbArray(
00360                                   const CaloSubdetectorGeometry& barrelGeom,
00361                                   const CaloSubdetectorTopology& barrelTopo){
00362   
00363   static const CaloDirection orderedDir[8]={SOUTHWEST,
00364                                             SOUTH,
00365                                             SOUTHEAST,
00366                                             WEST,
00367                                             EAST,
00368                                             NORTHWEST,
00369                                             NORTH,
00370                                             NORTHEAST};
00371   
00372   const unsigned nbarrel = 2160; //62000;
00373   // Barrel first. The hashed index runs from 0 to 2199 61199
00374   neighboursHO_.resize(nbarrel);
00375   
00376   //std::cout << " Building the array of neighbours (barrel) " ;
00377   
00378   const std::vector<DetId>& vec(barrelGeom.getValidDetIds(DetId::Hcal,
00379                                                           HcalOuter));
00380   unsigned size=vec.size();    
00381   for(unsigned ic=0; ic<size; ++ic) 
00382     {
00383       // We get the 9 cells in a square. 
00384       std::vector<DetId> neighbours(barrelTopo.getWindow(vec[ic],3,3));
00385       unsigned nneighbours=neighbours.size();
00386       
00387       unsigned hashedindex=HcalDetId(vec[ic]).hashed_index()-5184; //2*( kHBhalf + kHEhalf )
00388       //           std::cout << " Cell " << ic<<" "<<vec[ic].rawId()<<" "<<HcalDetId(vec[ic]) <<" "<<hashedindex<<" "<<nneighbours<< std::endl;
00389       if(hashedindex>=nbarrel)
00390         {
00391           LogDebug("CaloGeometryTools")  << " Array overflow " << std::endl;
00392         }
00393       
00394       
00395       // If there are 9 cells, it is easy, and this order is know:
00396       //      6  7  8
00397       //      3  4  5 
00398       //      0  1  2   (0 = SOUTHWEST)
00399       
00400       if(nneighbours==9)
00401         {
00402           neighboursHO_[hashedindex].reserve(8);
00403           for(unsigned in=0;in<nneighbours;++in)
00404             {
00405               // remove the centre
00406               //    cout<<"ic "<<ic<<" "<<in<<" "<<neighbours[in].rawId()<<" "<<vec[ic].rawId()<<" "<<hashedindex<<endl; 
00407               if(neighbours[in]!=vec[ic]) 
00408                 {
00409                   neighboursHO_[hashedindex].push_back(neighbours[in]);
00410                   //            std::cout << " Neighbour " << ic<<" "<<size<<" "<<in << " " <<hashedindex<<" "<< HcalDetId(neighbours[in]) << std::endl;
00411                 }
00412             }
00413         }
00414       else
00415         {
00416           DetId central(vec[ic]);
00417           neighboursHO_[hashedindex].resize(8,DetId(0));
00418           for(unsigned idir=0;idir<8;++idir)
00419             {
00420               DetId testid=central;
00421               bool status=stdmove(testid,orderedDir[idir],
00422                                   barrelTopo, barrelGeom);
00423               if(status) neighboursHO_[hashedindex][idir]=testid;
00424             }
00425           
00426         }
00427     }
00428   
00429   //    std::cout << " done " << size <<std::endl;
00430   neighbourmapcalculated_ = true;
00431 }
00432 
00433 bool 
00434 PFRecHitProducerHO::stdsimplemove(DetId& cell, 
00435                                   const CaloDirection& dir,
00436                                   const CaloSubdetectorTopology& barrelTopo,
00437                                   const CaloSubdetectorGeometry& barrelGeom)
00438   const {
00439   
00440   std::vector<DetId> neighbours;
00441   
00442   // BARREL CASE 
00443   if(cell.subdetId()==HcalOuter) {
00444     HcalDetId hoDetId = cell;
00445     
00446     neighbours = barrelTopo.getNeighbours(hoDetId,dir);
00447     
00448     // first try to move according to the standard navigation
00449     if(neighbours.size()>0 && !neighbours[0].null()) {
00450       cell = neighbours[0];
00451       return true;
00452     }
00453     
00454     // failed.
00455     
00456     
00457   }
00458   
00459   // everything failed 
00460   cell = DetId(0);
00461   return false;
00462 }
00463 
00464 
00465 
00466 bool 
00467 PFRecHitProducerHO::stdmove(DetId& cell, 
00468                             const CaloDirection& dir,
00469                             const CaloSubdetectorTopology& barrelTopo,
00470                             const CaloSubdetectorGeometry& barrelGeom)
00471   
00472   const {
00473   
00474   
00475   bool result; 
00476   
00477   if(dir==NORTH) {
00478     result = stdsimplemove(cell,NORTH, barrelTopo, barrelGeom);
00479     return result;
00480   }
00481   else if(dir==SOUTH) {
00482     result = stdsimplemove(cell,SOUTH, barrelTopo, barrelGeom);
00483     return result;
00484   }
00485   else if(dir==EAST) {
00486     result = stdsimplemove(cell,EAST, barrelTopo, barrelGeom);
00487     return result;
00488   }
00489   else if(dir==WEST) {
00490     result = stdsimplemove(cell,WEST, barrelTopo, barrelGeom);
00491     return result;
00492   }
00493   
00494   
00495   // One has to try both paths
00496   else if(dir==NORTHEAST)
00497     {
00498       result = stdsimplemove(cell,NORTH, barrelTopo, barrelGeom);
00499       if(result)
00500         return stdsimplemove(cell,EAST, barrelTopo, barrelGeom);
00501       else
00502         {
00503           result = stdsimplemove(cell,EAST, barrelTopo, barrelGeom);
00504           if(result)
00505             return stdsimplemove(cell,NORTH, barrelTopo, barrelGeom);
00506           else
00507             return false; 
00508         }
00509     }
00510   else if(dir==NORTHWEST)
00511     {
00512       result = stdsimplemove(cell,NORTH, barrelTopo, barrelGeom );
00513       if(result)
00514         return stdsimplemove(cell,WEST, barrelTopo, barrelGeom );
00515       else
00516         {
00517           result = stdsimplemove(cell,WEST, barrelTopo, barrelGeom );
00518           if(result)
00519             return stdsimplemove(cell,NORTH, barrelTopo, barrelGeom );
00520           else
00521             return false; 
00522         }
00523     }
00524   else if(dir == SOUTHEAST)
00525     {
00526       result = stdsimplemove(cell,SOUTH, barrelTopo, barrelGeom );
00527       if(result)
00528         return stdsimplemove(cell,EAST, barrelTopo, barrelGeom );
00529       else
00530         {
00531           result = stdsimplemove(cell,EAST, barrelTopo, barrelGeom );
00532           if(result)
00533             return stdsimplemove(cell,SOUTH, barrelTopo, barrelGeom );
00534           else
00535             return false; 
00536         }
00537     }
00538   else if(dir == SOUTHWEST)
00539     {
00540       result = stdsimplemove(cell,SOUTH, barrelTopo, barrelGeom );
00541       if(result)
00542         return stdsimplemove(cell,WEST, barrelTopo, barrelGeom );
00543       else
00544         {
00545           result = stdsimplemove(cell,SOUTH, barrelTopo, barrelGeom );
00546           if(result)
00547             return stdsimplemove(cell,WEST, barrelTopo, barrelGeom );
00548           else
00549             return false; 
00550         }
00551     }
00552   cell = DetId(0);
00553   return false;
00554 }
00555 
00556 DetId PFRecHitProducerHO::move(DetId cell, 
00557                                const CaloDirection&dir ) const
00558 {  
00559   DetId originalcell = cell; 
00560   if(dir==NONE || cell==DetId(0)) return false;
00561   
00562   // Conversion CaloDirection and index in the table
00563   // CaloDirection :NONE,SOUTH,SOUTHEAST,SOUTHWEST,EAST,WEST, NORTHEAST,NORTHWEST,NORTH
00564   // Table : SOUTHWEST,SOUTH,SOUTHEAST,WEST,EAST,NORTHWEST,NORTH, NORTHEAST
00565   static const int calodirections[9]={-1,1,2,0,4,3,7,5,6};
00566   
00567   assert(neighbourmapcalculated_);
00568   
00569   DetId result = neighboursHO_[HcalDetId(originalcell).hashed_index()-5184][calodirections[dir]];
00570   return result; 
00571 }
00572