CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/RecoParticleFlow/PFClusterProducer/plugins/PFRecHitProducerHCAL.cc

Go to the documentation of this file.
00001 #include "RecoParticleFlow/PFClusterProducer/plugins/PFRecHitProducerHCAL.h"
00002 
00003 #include <memory>
00004 
00005 #include "DataFormats/ParticleFlowReco/interface/PFRecHit.h"
00006 
00007 #include "DataFormats/HcalRecHit/interface/HFRecHit.h"
00008 #include "DataFormats/HcalRecHit/interface/HBHERecHit.h"
00009 #include "DataFormats/HcalRecHit/interface/HcalRecHitCollections.h"
00010 #include "DataFormats/HcalDetId/interface/HcalSubdetector.h"
00011 
00012 #include "DataFormats/DetId/interface/DetId.h"
00013 #include "DataFormats/EcalDetId/interface/EEDetId.h"
00014 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00015 
00016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00017 #include "FWCore/Framework/interface/ESHandle.h"
00018 #include "FWCore/Framework/interface/EventSetup.h"
00019 
00020 
00021 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00022 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00023 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00024 #include "Geometry/CaloGeometry/interface/TruncatedPyramid.h"
00025 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00026 
00027 #include "Geometry/CaloTopology/interface/HcalTopology.h"
00028 #include "RecoCaloTools/Navigation/interface/CaloNavigator.h"
00029 
00030 #include "DataFormats/CaloTowers/interface/CaloTowerCollection.h"
00031 
00032 #include "Geometry/CaloTopology/interface/CaloTowerTopology.h"
00033 #include "RecoCaloTools/Navigation/interface/CaloTowerNavigator.h"
00034 
00035 #include "RecoLocalCalo/HcalRecAlgos/interface/HcalCaloFlagLabels.h"
00036 
00037 
00038 using namespace std;
00039 using namespace edm;
00040 
00041 PFRecHitProducerHCAL::PFRecHitProducerHCAL(const edm::ParameterSet& iConfig)
00042   : PFRecHitProducer( iConfig ) 
00043 {
00044 
00045  
00046 
00047   // access to the collections of rechits 
00048 
00049   
00050   inputTagHcalRecHitsHBHE_ =
00051     iConfig.getParameter<InputTag>("hcalRecHitsHBHE");
00052     
00053   inputTagHcalRecHitsHF_ =
00054     iConfig.getParameter<InputTag>("hcalRecHitsHF");
00055     
00056  
00057   inputTagCaloTowers_ = 
00058     iConfig.getParameter<InputTag>("caloTowers");
00059    
00060   thresh_HF_ = 
00061     iConfig.getParameter<double>("thresh_HF");
00062   navigation_HF_ = 
00063     iConfig.getParameter<bool>("navigation_HF");
00064   weight_HFem_ =
00065     iConfig.getParameter<double>("weight_HFem");
00066   weight_HFhad_ =
00067     iConfig.getParameter<double>("weight_HFhad");
00068 
00069   HCAL_Calib_ =
00070     iConfig.getParameter<bool>("HCAL_Calib");
00071   HF_Calib_ =
00072     iConfig.getParameter<bool>("HF_Calib");
00073   max_Calib_ = 
00074     iConfig.getParameter<double>("Max_Calib");
00075 
00076   shortFibre_Cut = iConfig.getParameter<double>("ShortFibre_Cut");
00077   longFibre_Fraction = iConfig.getParameter<double>("LongFibre_Fraction");
00078 
00079   longFibre_Cut = iConfig.getParameter<double>("LongFibre_Cut");
00080   shortFibre_Fraction = iConfig.getParameter<double>("ShortFibre_Fraction");
00081 
00082   applyLongShortDPG_ = iConfig.getParameter<bool>("ApplyLongShortDPG");
00083 
00084   longShortFibre_Cut = iConfig.getParameter<double>("LongShortFibre_Cut");
00085   minShortTiming_Cut = iConfig.getParameter<double>("MinShortTiming_Cut");
00086   maxShortTiming_Cut = iConfig.getParameter<double>("MaxShortTiming_Cut");
00087   minLongTiming_Cut = iConfig.getParameter<double>("MinLongTiming_Cut");
00088   maxLongTiming_Cut = iConfig.getParameter<double>("MaxLongTiming_Cut");
00089 
00090   applyTimeDPG_ = iConfig.getParameter<bool>("ApplyTimeDPG");
00091   applyPulseDPG_ = iConfig.getParameter<bool>("ApplyPulseDPG");
00092 
00093   ECAL_Compensate_ = iConfig.getParameter<bool>("ECAL_Compensate");
00094   ECAL_Threshold_ = iConfig.getParameter<double>("ECAL_Threshold");
00095   ECAL_Compensation_ = iConfig.getParameter<double>("ECAL_Compensation");
00096   ECAL_Dead_Code_ = iConfig.getParameter<unsigned int>("ECAL_Dead_Code");
00097 
00098   EM_Depth_ = iConfig.getParameter<double>("EM_Depth");
00099   HAD_Depth_ = iConfig.getParameter<double>("HAD_Depth");
00100 
00101   //--ab
00102   produces<reco::PFRecHitCollection>("HFHAD").setBranchAlias("HFHADRecHits");
00103   produces<reco::PFRecHitCollection>("HFEM").setBranchAlias("HFEMRecHits");
00104   //--ab
00105 }
00106 
00107 
00108 
00109 PFRecHitProducerHCAL::~PFRecHitProducerHCAL() {}
00110 
00111 
00112 
00113 void PFRecHitProducerHCAL::createRecHits(vector<reco::PFRecHit>& rechits,
00114                                          vector<reco::PFRecHit>& rechitsCleaned,
00115                                          edm::Event& iEvent, 
00116                                          const edm::EventSetup& iSetup ) {
00117 
00118   
00119   // this map is necessary to find the rechit neighbours efficiently
00120   //C but I should think about using Florian's hashed index to do this.
00121   //C in which case the map might not be necessary anymore
00122   //C however the hashed index does not seem to be implemented for HCAL
00123   // 
00124   // the key of this map is detId. 
00125   // the value is the index in the rechits vector
00126   map<unsigned,  unsigned > idSortedRecHits;
00127   map<unsigned,  unsigned > idSortedRecHitsHFEM;
00128   map<unsigned,  unsigned > idSortedRecHitsHFHAD;
00129   typedef map<unsigned, unsigned >::iterator IDH;  
00130 
00131 
00132   edm::ESHandle<CaloGeometry> geoHandle;
00133   iSetup.get<CaloGeometryRecord>().get(geoHandle);
00134   
00135   // get the hcalBarrel geometry
00136   const CaloSubdetectorGeometry *hcalBarrelGeometry = 
00137     geoHandle->getSubdetectorGeometry(DetId::Hcal, HcalBarrel);
00138 
00139   // get the endcap geometry
00140   const CaloSubdetectorGeometry *hcalEndcapGeometry = 
00141     geoHandle->getSubdetectorGeometry(DetId::Hcal, HcalEndcap);
00142 
00143   //--ab
00144   auto_ptr< vector<reco::PFRecHit> > HFHADRecHits( new vector<reco::PFRecHit> ); 
00145   auto_ptr< vector<reco::PFRecHit> > HFEMRecHits( new vector<reco::PFRecHit> ); 
00146   //--ab
00147 
00148   // 2 possibilities to make HCAL clustering :
00149   // - from the HCAL rechits
00150   // - from the CaloTowers. 
00151   // ultimately, clustering will be done taking CaloTowers as an 
00152   // input. This possibility is currently under investigation, and 
00153   // was thus made optional.
00154 
00155   // in the first step, we will fill the map of PFRecHits hcalrechits
00156   // either from CaloTowers or from HCAL rechits. 
00157 
00158   // in the second step, we will perform clustering on this map.
00159 
00160   if( !(inputTagCaloTowers_ == InputTag()) ) {
00161       
00162     edm::Handle<CaloTowerCollection> caloTowers; 
00163     CaloTowerTopology caloTowerTopology; 
00164     const CaloSubdetectorGeometry *caloTowerGeometry = 0; 
00165     // = geometry_->getSubdetectorGeometry(id)
00166 
00167     // get calotowers
00168     bool found = iEvent.getByLabel(inputTagCaloTowers_,
00169                                    caloTowers);
00170 
00171     if(!found) {
00172       ostringstream err;
00173       err<<"could not find rechits "<<inputTagCaloTowers_;
00174       LogError("PFRecHitProducerHCAL")<<err.str()<<endl;
00175     
00176       throw cms::Exception( "MissingProduct", err.str());
00177     }
00178     else {
00179       assert( caloTowers.isValid() );
00180 
00181       // get HF rechits
00182       edm::Handle<HFRecHitCollection>  hfHandle;  
00183       found = iEvent.getByLabel(inputTagHcalRecHitsHF_,
00184                                 hfHandle);
00185       
00186       if(!found) {
00187         ostringstream err;
00188         err<<"could not find HF rechits "<<inputTagHcalRecHitsHF_;
00189         LogError("PFRecHitProducerHCAL")<<err.str()<<endl;
00190         
00191         throw cms::Exception( "MissingProduct", err.str());
00192       }
00193       else {
00194         assert( hfHandle.isValid() );
00195       }
00196       
00197       // get HBHE rechits
00198       edm::Handle<HBHERecHitCollection>  hbheHandle;  
00199       found = iEvent.getByLabel(inputTagHcalRecHitsHBHE_,
00200                                 hbheHandle);
00201       
00202       if(!found) {
00203         ostringstream err;
00204         err<<"could not find HBHE rechits "<<inputTagHcalRecHitsHBHE_;
00205         LogError("PFRecHitProducerHCAL")<<err.str()<<endl;
00206         
00207         throw cms::Exception( "MissingProduct", err.str());
00208       }
00209       else {
00210         assert( hbheHandle.isValid() );
00211       }
00212       
00213       // create rechits
00214       typedef CaloTowerCollection::const_iterator ICT;
00215     
00216       for(ICT ict=caloTowers->begin(); ict!=caloTowers->end();ict++) {
00217           
00218         const CaloTower& ct = (*ict);
00219           
00220         //C     
00221         if(!caloTowerGeometry) 
00222           caloTowerGeometry = geoHandle->getSubdetectorGeometry(ct.id());
00223 
00224           
00225         // get the hadronic energy.
00226         
00227         // Mike: Just ask for the Hadronic part only now!
00228         // Patrick : ARGH ! While this is ok for the HCAL, this is 
00229         // just wrong for the HF (in which em/had are artificially 
00230         // separated. 
00231         double energy = ct.hadEnergy();
00232         //Auguste: Photons in HF have no hadEnergy in fastsim: -> all RecHit collections are empty with photons.
00233         double energyEM = ct.emEnergy(); // For HF !
00234         //so test the total energy to deal with the photons in  HF:
00235         if( (energy+energyEM) < 1e-9 ) continue;
00236           
00237         assert( ct.constituentsSize() );          
00238         //Mike: The DetId will be taken by the first Hadronic constituent
00239         //         of the tower. That is only what we need
00240 
00241         
00242         //get the constituents of the tower
00243         const std::vector<DetId>& hits = ct.constituents();
00244         const std::vector<DetId>& allConstituents = theTowerConstituentsMap->constituentsOf(ct.id());
00245 
00246         /*
00247         for(unsigned int i=0;i< hits.size();++i) {
00248           if(hits[i].det()==DetId::Hcal) {
00249             HcalDetId did = hits[i];
00250             if ( did.subdet()==HcalEndcap || did.subdet()==HcalForward ) { 
00251               //double en = hits[i].energy();
00252               int ieta = did.ieta();
00253               const CaloCellGeometry *thisCell = hcalEndcapGeometry->getGeometry(did);
00254               const GlobalPoint& position = thisCell->getPosition();
00255               if ( abs(ieta) > 27 && abs(ieta) < 33 && energy > 10. ) { 
00256                 std::cout << "HE/HF hit " << i << " at eta = " << ieta 
00257                           << " with CT energy = " << energy 
00258                           << " at eta, z (hit) = " << position.eta() << " " << position.z()
00259                           << " at eta, z (cte) = " << ct.emPosition().eta() << " " << ct.emPosition().z()
00260                           << " at eta, z (cth) = " << ct.hadPosition().eta() << " " << ct.hadPosition().z()
00261                           << " at eta, z (cto) = " << ct.eta() << " " << ct.vz() 
00262                           << std::endl;
00263               }
00264             }
00265           }
00266         }
00267         */
00268         
00269         //Reserve the DetId we are looking for:
00270 
00271         HcalDetId detid;
00272         // EcalDetId edetid;
00273         bool foundHCALConstituent = false;
00274 
00275  
00276         //Loop on the calotower constituents and search for HCAL
00277         double dead = 0.;
00278         double alive = 0.;
00279         for(unsigned int i=0;i< hits.size();++i) {
00280           if(hits[i].det()==DetId::Hcal) { 
00281             foundHCALConstituent = true;
00282             detid = hits[i];
00283             // An HCAL tower was found: Look for dead ECAL channels in the same CaloTower.
00284             if ( ECAL_Compensate_ && energy > ECAL_Threshold_ ) {
00285               for(unsigned int j=0;j<allConstituents.size();++j) { 
00286                 if ( allConstituents[j].det()==DetId::Ecal ) { 
00287                   alive += 1.;
00288                   EcalChannelStatus::const_iterator chIt = theEcalChStatus->find(allConstituents[j]);
00289                   unsigned int dbStatus = chIt != theEcalChStatus->end() ? chIt->getStatusCode() : 0;
00290                   if ( dbStatus > ECAL_Dead_Code_ ) dead += 1.;
00291                 }
00292               }
00293             } 
00294             // Protection: tower 29 in HF is merged with tower 30. 
00295             // Just take the position of tower 30 in that case. 
00296             if ( detid.subdet() == HcalForward && abs(detid.ieta()) == 29 ) continue; 
00297             break;
00298           }
00299         }
00300 
00301         // In case of dead ECAL channel, rescale the HCAL energy...
00302         double rescaleFactor = alive > 0. ? 1. + ECAL_Compensation_*dead/alive : 1.;
00303           
00304         reco::PFRecHit* pfrh = 0;
00305         reco::PFRecHit* pfrhCleaned = 0;
00306         //---ab: need 2 rechits for the HF:
00307         reco::PFRecHit* pfrhHFEM = 0;
00308         reco::PFRecHit* pfrhHFHAD = 0;
00309         reco::PFRecHit* pfrhHFEMCleaned = 0;
00310         reco::PFRecHit* pfrhHFHADCleaned = 0;
00311         reco::PFRecHit* pfrhHFEMCleaned29 = 0;
00312         reco::PFRecHit* pfrhHFHADCleaned29 = 0;
00313 
00314         if(foundHCALConstituent)
00315           {
00316             // std::cout << ", new Energy = " << energy << std::endl;
00317             switch( detid.subdet() ) {
00318             case HcalBarrel: 
00319               {
00320                 if(energy < thresh_Barrel_ ) continue;
00321 
00322                 /*
00323                 // Check the timing
00324                 if ( energy > 5. ) { 
00325                   for(unsigned int i=0;i< hits.size();++i) {
00326                     if( hits[i].det() != DetId::Hcal ) continue; 
00327                     HcalDetId theDetId = hits[i]; 
00328                     typedef HBHERecHitCollection::const_iterator iHBHE;
00329                     iHBHE theHit = hbheHandle->find(theDetId); 
00330                     if ( theHit != hbheHandle->end() ) 
00331                       std::cout << "HCAL hit : " 
00332                                 << theDetId.ieta() << " " << theDetId.iphi() << " " 
00333                                 << theHit->energy() << " " << theHit->time() << std::endl;
00334                   }
00335                 }
00336                 */
00337 
00338 
00339                 if ( HCAL_Calib_ ) energy   *= std::min(max_Calib_,myPFCorr->getValues(detid)->getValue());
00340                 //if ( rescaleFactor > 1. ) 
00341                 // std::cout << "Barrel HCAL energy rescaled from = " << energy << " to " << energy*rescaleFactor << std::endl;
00342                 if ( rescaleFactor > 1. ) { 
00343                   pfrhCleaned = createHcalRecHit( detid, 
00344                                                   energy, 
00345                                                   PFLayer::HCAL_BARREL1, 
00346                                                   hcalBarrelGeometry,
00347                                                   ct.id().rawId() );
00348                   pfrhCleaned->setRescale(rescaleFactor);
00349                   energy *= rescaleFactor;
00350                 }
00351                 pfrh = createHcalRecHit( detid, 
00352                                          energy, 
00353                                  PFLayer::HCAL_BARREL1, 
00354                                          hcalBarrelGeometry,
00355                                          ct.id().rawId() );
00356                 pfrh->setRescale(rescaleFactor);
00357               }
00358               break;
00359             case HcalEndcap:
00360               {
00361                 if(energy < thresh_Endcap_ ) continue;
00362 
00363                 /*
00364                 // Check the timing
00365                 if ( energy > 5. ) { 
00366                   for(unsigned int i=0;i< hits.size();++i) {
00367                     if( hits[i].det() != DetId::Hcal ) continue; 
00368                     HcalDetId theDetId = hits[i]; 
00369                     typedef HBHERecHitCollection::const_iterator iHBHE;
00370                     iHBHE theHit = hbheHandle->find(theDetId); 
00371                     if ( theHit != hbheHandle->end() ) 
00372                       std::cout << "HCAL hit : " 
00373                                 << theDetId.ieta() << " " << theDetId.iphi() << " " 
00374                                 << theHit->energy() << " " << theHit->time() << std::endl;
00375                   }
00376                 }
00377                 */
00378 
00379                 if ( HCAL_Calib_ ) energy   *= std::min(max_Calib_,myPFCorr->getValues(detid)->getValue());
00380                 //if ( rescaleFactor > 1. ) 
00381                 // std::cout << "End-cap HCAL energy rescaled from = " << energy << " to " << energy*rescaleFactor << std::endl;
00382                 if ( rescaleFactor > 1. ) { 
00383                   pfrhCleaned = createHcalRecHit( detid, 
00384                                                   energy, 
00385                                                   PFLayer::HCAL_ENDCAP, 
00386                                                   hcalEndcapGeometry,
00387                                                   ct.id().rawId() );
00388                   pfrhCleaned->setRescale(rescaleFactor);
00389                   energy *= rescaleFactor;
00390                 }
00391                 pfrh = createHcalRecHit( detid, 
00392                                          energy, 
00393                                          PFLayer::HCAL_ENDCAP, 
00394                                          hcalEndcapGeometry,
00395                                          ct.id().rawId() );
00396                 pfrh->setRescale(rescaleFactor);
00397               }
00398               break;
00399             case HcalOuter:
00400               {
00401               }
00402               break;
00403             case HcalForward:
00404               {
00405                 //---ab: 2 rechits for HF:
00406                 //double energyemHF = weight_HFem_*ct.emEnergy();
00407                 //double energyhadHF = weight_HFhad_*ct.hadEnergy();
00408                 double energyemHF = weight_HFem_ * energyEM;
00409                 double energyhadHF = weight_HFhad_ * energy;
00410                 // Some energy in the tower !
00411                 if((energyemHF+energyhadHF) < thresh_HF_ ) continue;
00412 
00413                 // Some cleaning in the HF 
00414                 double longFibre = energyemHF + energyhadHF/2.;
00415                 double shortFibre = energyhadHF/2.;
00416                 int ieta = detid.ieta();
00417                 int iphi = detid.iphi();
00418                 HcalDetId theLongDetId (HcalForward, ieta, iphi, 1);
00419                 HcalDetId theShortDetId (HcalForward, ieta, iphi, 2);
00420                 typedef HFRecHitCollection::const_iterator iHF;
00421                 iHF theLongHit = hfHandle->find(theLongDetId); 
00422                 iHF theShortHit = hfHandle->find(theShortDetId); 
00423                 // 
00424                 double theLongHitEnergy = 0.;
00425                 double theShortHitEnergy = 0.;
00426                 bool flagShortDPG =  false; 
00427                 bool flagLongDPG = false; 
00428                 bool flagShortTimeDPG = false; 
00429                 bool flagLongTimeDPG = false;
00430                 bool flagShortPulseDPG = false;
00431                 bool flagLongPulseDPG = false;
00432                 //
00433                 if ( theLongHit != hfHandle->end() ) { 
00434                   theLongHitEnergy = theLongHit->energy();
00435                   flagLongDPG = applyLongShortDPG_ && theLongHit->flagField(HcalCaloFlagLabels::HFLongShort)==1;
00436                   flagLongTimeDPG = applyTimeDPG_ && theLongHit->flagField(HcalCaloFlagLabels::HFInTimeWindow)==1;
00437                   flagLongPulseDPG = applyPulseDPG_ && theLongHit->flagField(HcalCaloFlagLabels::HFDigiTime)==1;
00438                 }
00439                 //
00440                 if ( theShortHit != hfHandle->end() ) { 
00441                   theShortHitEnergy = theShortHit->energy();
00442                   flagShortDPG =  applyLongShortDPG_ && theShortHit->flagField(HcalCaloFlagLabels::HFLongShort)==1;
00443                   flagShortTimeDPG = applyTimeDPG_ && theShortHit->flagField(HcalCaloFlagLabels::HFInTimeWindow)==1;
00444                   flagShortPulseDPG = applyPulseDPG_ && theShortHit->flagField(HcalCaloFlagLabels::HFDigiTime)==1;
00445                 }
00446 
00447                 // Then check the timing in short and long fibres in all other towers.
00448                 if ( theShortHitEnergy > longShortFibre_Cut && 
00449                      ( theShortHit->time() < minShortTiming_Cut ||
00450                        theShortHit->time() > maxShortTiming_Cut || 
00451                        flagShortTimeDPG || flagShortPulseDPG ) ) { 
00452                   // rescaleFactor = 0. ;
00453                   pfrhHFHADCleaned = createHcalRecHit( detid, 
00454                                                        theShortHitEnergy, 
00455                                                        PFLayer::HF_HAD, 
00456                                                        hcalEndcapGeometry,
00457                                                        ct.id().rawId() );
00458                   pfrhHFHADCleaned->setRescale(theShortHit->time());
00459                   /*
00460                   std::cout << "ieta/iphi = " << ieta << " " << iphi 
00461                             << ", Energy em/had/long/short = " 
00462                             << energyemHF << " " << energyhadHF << " "
00463                             << theLongHitEnergy << " " << theShortHitEnergy << " " 
00464                             << ". Time = " << theShortHit->time() << " " 
00465                             << ". The short and long flags : " 
00466                             << flagShortDPG << " " << flagLongDPG << " "  
00467                             << flagShortTimeDPG << " " << flagLongTimeDPG << " "  
00468                             << flagShortPulseDPG << " " << flagLongPulseDPG << " "  
00469                             << ". Short fibres were cleaned." << std::endl;
00470                   */
00471                   shortFibre -= theShortHitEnergy;
00472                   theShortHitEnergy = 0.;
00473                 }
00474                 
00475                 
00476                 if ( theLongHitEnergy > longShortFibre_Cut && 
00477                      ( theLongHit->time() < minLongTiming_Cut ||
00478                        theLongHit->time() > maxLongTiming_Cut  || 
00479                        flagLongTimeDPG || flagLongPulseDPG ) ) { 
00480                   //rescaleFactor = 0. ;
00481                   pfrhHFEMCleaned = createHcalRecHit( detid, 
00482                                                       theLongHitEnergy, 
00483                                                       PFLayer::HF_EM, 
00484                                                       hcalEndcapGeometry,
00485                                                       ct.id().rawId() );
00486                   pfrhHFEMCleaned->setRescale(theLongHit->time());
00487                   /*
00488                   std::cout << "ieta/iphi = " << ieta << " " << iphi 
00489                             << ", Energy em/had/long/short = " 
00490                             << energyemHF << " " << energyhadHF << " "
00491                             << theLongHitEnergy << " " << theShortHitEnergy << " " 
00492                             << ". Time = " << theLongHit->time() << " " 
00493                             << ". The short and long flags : " 
00494                             << flagShortDPG << " " << flagLongDPG << " "  
00495                             << flagShortTimeDPG << " " << flagLongTimeDPG << " "  
00496                             << flagShortPulseDPG << " " << flagLongPulseDPG << " "  
00497                             << ". Long fibres were cleaned." << std::endl;
00498                   */
00499                   longFibre -= theLongHitEnergy;
00500                   theLongHitEnergy = 0.;
00501                 }
00502 
00503                 // Some energy must be in the long fibres is there is some energy in the short fibres ! 
00504                 if ( theShortHitEnergy > shortFibre_Cut && 
00505                      ( theLongHitEnergy/theShortHitEnergy < longFibre_Fraction || 
00506                        flagShortDPG ) ) {
00507                   // Check if the long-fibre hit was not cleaned already (because hot)
00508                   // In this case don't apply the cleaning
00509                   const HcalChannelStatus* theStatus = theHcalChStatus->getValues(theLongDetId);
00510                   unsigned theStatusValue = theStatus->getValue();
00511                   // The channel is killed
00512                   if ( !theStatusValue ) { 
00513                     // rescaleFactor = 0. ;
00514                     pfrhHFHADCleaned = createHcalRecHit( detid, 
00515                                                          theShortHitEnergy, 
00516                                                          PFLayer::HF_HAD, 
00517                                                          hcalEndcapGeometry,
00518                                                          ct.id().rawId() );
00519                     pfrhHFHADCleaned->setRescale(theShortHit->time());
00520                     /*
00521                     std::cout << "ieta/iphi = " << ieta << " " << iphi 
00522                               << ", Energy em/had/long/short = " 
00523                               << energyemHF << " " << energyhadHF << " "
00524                               << theLongHitEnergy << " " << theShortHitEnergy << " " 
00525                               << ". Time = " << theShortHit->time() << " " 
00526                               << ". The status value is " << theStatusValue
00527                               << ". The short and long flags : " 
00528                               << flagShortDPG << " " << flagLongDPG << " "  
00529                               << flagShortTimeDPG << " " << flagLongTimeDPG << " "  
00530                               << flagShortPulseDPG << " " << flagLongPulseDPG << " "  
00531                               << ". Short fibres were cleaned." << std::endl;
00532                     */
00533                     shortFibre -= theShortHitEnergy;
00534                     theShortHitEnergy = 0.;
00535                   }
00536                 }
00537 
00538                 if ( theLongHitEnergy > longFibre_Cut && 
00539                      ( theShortHitEnergy/theLongHitEnergy < shortFibre_Fraction || 
00540                        flagLongDPG ) ) {
00541                   // Check if the long-fibre hit was not cleaned already (because hot)
00542                   // In this case don't apply the cleaning
00543                   const HcalChannelStatus* theStatus = theHcalChStatus->getValues(theShortDetId);
00544                   unsigned theStatusValue = theStatus->getValue();
00545                   // The channel is killed
00546                   if ( !theStatusValue ) { 
00547                     //rescaleFactor = 0. ;
00548                     pfrhHFEMCleaned = createHcalRecHit( detid, 
00549                                                       theLongHitEnergy, 
00550                                                       PFLayer::HF_EM, 
00551                                                       hcalEndcapGeometry,
00552                                                       ct.id().rawId() );
00553                     pfrhHFEMCleaned->setRescale(theLongHit->time());
00554                     /*
00555                     std::cout << "ieta/iphi = " << ieta << " " << iphi 
00556                               << ", Energy em/had/long/short = " 
00557                               << energyemHF << " " << energyhadHF << " "
00558                               << theLongHitEnergy << " " << theShortHitEnergy << " " 
00559                               << ". The status value is " << theStatusValue
00560                               << ". Time = " << theLongHit->time() << " " 
00561                               << ". The short and long flags : " 
00562                               << flagShortDPG << " " << flagLongDPG << " "  
00563                               << flagShortTimeDPG << " " << flagLongTimeDPG << " "  
00564                               << flagShortPulseDPG << " " << flagLongPulseDPG << " "  
00565                               << ". Long fibres were cleaned." << std::endl;
00566                     */
00567                     longFibre -= theLongHitEnergy;
00568                     theLongHitEnergy = 0.;
00569                   }
00570                 }
00571 
00572                 // Special treatment for tower 29
00573                 // A tower with energy only at ieta = +/- 29 is not physical -> Clean
00574                 if ( abs(ieta) == 29 ) { 
00575                   // rescaleFactor = 0. ;
00576                   // Clean long fibres
00577                   if ( theLongHitEnergy > shortFibre_Cut/2. ) { 
00578                     pfrhHFEMCleaned29 = createHcalRecHit( detid, 
00579                                                           theLongHitEnergy, 
00580                                                           PFLayer::HF_EM, 
00581                                                           hcalEndcapGeometry,
00582                                                           ct.id().rawId() );
00583                     pfrhHFEMCleaned29->setRescale(theLongHit->time());
00584                     /*
00585                     std::cout << "ieta/iphi = " << ieta << " " << iphi 
00586                               << ", Energy em/had/long/short = " 
00587                               << energyemHF << " " << energyhadHF << " "
00588                               << theLongHitEnergy << " " << theShortHitEnergy << " " 
00589                               << ". Long fibres were cleaned." << std::endl;
00590                     */
00591                     longFibre -= theLongHitEnergy;
00592                     theLongHitEnergy = 0.;
00593                   }
00594                   // Clean short fibres
00595                   if ( theShortHitEnergy > shortFibre_Cut/2. ) { 
00596                     pfrhHFHADCleaned29 = createHcalRecHit( detid, 
00597                                                            theShortHitEnergy, 
00598                                                            PFLayer::HF_HAD, 
00599                                                            hcalEndcapGeometry,
00600                                                            ct.id().rawId() );
00601                     pfrhHFHADCleaned29->setRescale(theShortHit->time());
00602                     /*
00603                     std::cout << "ieta/iphi = " << ieta << " " << iphi 
00604                               << ", Energy em/had/long/short = " 
00605                               << energyemHF << " " << energyhadHF << " "
00606                               << theLongHitEnergy << " " << theShortHitEnergy << " " 
00607                               << ". Short fibres were cleaned." << std::endl;
00608                     */
00609                     shortFibre -= theShortHitEnergy;
00610                     theShortHitEnergy = 0.;
00611                   }
00612                 }
00613                 // Check the timing of the long and short fibre rechits
00614                 
00615                 // First, check the timing of long and short fibre in eta = 29 if tower 30.
00616                 else if ( abs(ieta) == 30 ) { 
00617                   int ieta29 = ieta > 0 ? 29 : -29;
00618                   HcalDetId theLongDetId29 (HcalForward, ieta29, iphi, 1);
00619                   HcalDetId theShortDetId29 (HcalForward, ieta29, iphi, 2);
00620                   iHF theLongHit29 = hfHandle->find(theLongDetId29); 
00621                   iHF theShortHit29 = hfHandle->find(theShortDetId29); 
00622                   // 
00623                   double theLongHitEnergy29 = 0.;
00624                   double theShortHitEnergy29 = 0.;
00625                   bool flagShortDPG29 =  false; 
00626                   bool flagLongDPG29 = false; 
00627                   bool flagShortTimeDPG29 = false; 
00628                   bool flagLongTimeDPG29 = false;
00629                   bool flagShortPulseDPG29 = false;
00630                   bool flagLongPulseDPG29 = false;
00631                   //
00632                   if ( theLongHit29 != hfHandle->end() ) {                  
00633                     theLongHitEnergy29 = theLongHit29->energy() ;
00634                     flagLongDPG29 = applyLongShortDPG_ && theLongHit29->flagField(HcalCaloFlagLabels::HFLongShort)==1;
00635                     flagLongTimeDPG29 = applyTimeDPG_ && theLongHit29->flagField(HcalCaloFlagLabels::HFInTimeWindow)==1;
00636                     flagLongPulseDPG29 = applyPulseDPG_ && theLongHit29->flagField(HcalCaloFlagLabels::HFDigiTime)==1;
00637                   }
00638                   //
00639                   if ( theShortHit29 != hfHandle->end() ) {                 
00640                     theShortHitEnergy29 = theShortHit29->energy();                
00641                     flagShortDPG29 = applyLongShortDPG_ && theShortHit29->flagField(HcalCaloFlagLabels::HFLongShort)==1;
00642                     flagShortTimeDPG29 = applyTimeDPG_ && theShortHit29->flagField(HcalCaloFlagLabels::HFInTimeWindow)==1;
00643                     flagShortPulseDPG29 = applyPulseDPG_ && theShortHit29->flagField(HcalCaloFlagLabels::HFDigiTime)==1;
00644                   }
00645 
00646                   if ( theLongHitEnergy29 > longShortFibre_Cut && 
00647                        ( theLongHit29->time() < minLongTiming_Cut ||
00648                          theLongHit29->time() > maxLongTiming_Cut ||
00649                          flagLongTimeDPG29 || flagLongPulseDPG29 ) ) { 
00650                     //rescaleFactor = 0. ;
00651                     pfrhHFEMCleaned29 = createHcalRecHit( detid, 
00652                                                           theLongHitEnergy29, 
00653                                                           PFLayer::HF_EM, 
00654                                                           hcalEndcapGeometry,
00655                                                           ct.id().rawId() );
00656                     pfrhHFEMCleaned29->setRescale(theLongHit29->time());
00657                     /*
00658                     std::cout << "ieta/iphi = " << ieta29 << " " << iphi 
00659                               << ", Energy em/had/long/short = " 
00660                               << energyemHF << " " << energyhadHF << " "
00661                               << theLongHitEnergy29 << " " << theShortHitEnergy29 << " " 
00662                               << ". Time = " << theLongHit29->time() << " " 
00663                               << ". The short and long flags : " 
00664                               << flagShortDPG29 << " " << flagLongDPG29 << " "  
00665                               << flagShortTimeDPG29 << " " << flagLongTimeDPG29 << " "  
00666                               << flagShortPulseDPG29 << " " << flagLongPulseDPG29 << " "  
00667                               << ". Long fibres were cleaned." << std::endl;
00668                     */
00669                     longFibre -= theLongHitEnergy29;
00670                     theLongHitEnergy29 = 0;
00671                   }
00672 
00673                   if ( theShortHitEnergy29 > longShortFibre_Cut && 
00674                        ( theShortHit29->time() < minShortTiming_Cut ||
00675                          theShortHit29->time() > maxShortTiming_Cut ||
00676                          flagShortTimeDPG29 || flagShortPulseDPG29 ) ) { 
00677                     //rescaleFactor = 0. ;
00678                     pfrhHFHADCleaned29 = createHcalRecHit( detid, 
00679                                                          theShortHitEnergy29, 
00680                                                          PFLayer::HF_HAD, 
00681                                                          hcalEndcapGeometry,
00682                                                          ct.id().rawId() );
00683                     pfrhHFHADCleaned29->setRescale(theShortHit29->time());
00684                     /*
00685                     std::cout << "ieta/iphi = " << ieta29 << " " << iphi 
00686                               << ", Energy em/had/long/short = " 
00687                               << energyemHF << " " << energyhadHF << " "
00688                               << theLongHitEnergy29 << " " << theShortHitEnergy29 << " " 
00689                               << ". Time = " << theShortHit29->time() << " " 
00690                               << ". The short and long flags : " 
00691                               << flagShortDPG29 << " " << flagLongDPG29 << " "  
00692                               << flagShortTimeDPG29 << " " << flagLongTimeDPG29 << " "  
00693                               << flagShortPulseDPG29 << " " << flagLongPulseDPG29 << " "  
00694                               << ". Short fibres were cleaned." << std::endl;
00695                     */
00696                     shortFibre -= theShortHitEnergy29;
00697                     theShortHitEnergy29 = 0.;
00698                   }
00699 
00700                   // Some energy must be in the long fibres is there is some energy in the short fibres ! 
00701                   if ( theShortHitEnergy29 > shortFibre_Cut && 
00702                        ( theLongHitEnergy29/theShortHitEnergy29 < 2.*longFibre_Fraction || 
00703                          flagShortDPG29 ) ) {
00704                     // Check if the long-fibre hit was not cleaned already (because hot)
00705                     // In this case don't apply the cleaning
00706                     const HcalChannelStatus* theStatus = theHcalChStatus->getValues(theLongDetId29);
00707                     unsigned theStatusValue = theStatus->getValue();
00708                     // The channel is killed
00709                     if ( !theStatusValue ) { 
00710                       //rescaleFactor = 0. ;
00711                       pfrhHFHADCleaned29 = createHcalRecHit( detid, 
00712                                                            theShortHitEnergy29, 
00713                                                            PFLayer::HF_HAD, 
00714                                                            hcalEndcapGeometry,
00715                                                            ct.id().rawId() );
00716                       pfrhHFHADCleaned29->setRescale(theShortHit29->time());
00717                       /*
00718                       std::cout << "ieta/iphi = " << ieta29 << " " << iphi 
00719                                 << ", Energy em/had/long/short = " 
00720                                 << energyemHF << " " << energyhadHF << " "
00721                                 << theLongHitEnergy29 << " " << theShortHitEnergy29 << " " 
00722                                 << ". Time = " << theShortHit29->time() << " " 
00723                                 << ". The status value is " << theStatusValue
00724                                 << ". The short and long flags : " 
00725                                 << flagShortDPG29 << " " << flagLongDPG29 << " "  
00726                                 << flagShortTimeDPG29 << " " << flagLongTimeDPG29 << " "  
00727                                 << flagShortPulseDPG29 << " " << flagLongPulseDPG29 << " "  
00728                                 << ". Short fibres were cleaned." << std::endl;
00729                       */
00730                       shortFibre -= theShortHitEnergy29;
00731                       theShortHitEnergy29 = 0.;
00732                     }       
00733                   }
00734                   
00735                   // Some energy must be in the short fibres is there is some energy in the long fibres ! 
00736                   if ( theLongHitEnergy29 > longFibre_Cut && 
00737                        ( theShortHitEnergy29/theLongHitEnergy29 < shortFibre_Fraction || 
00738                          flagLongDPG29 ) ) {
00739                     // Check if the long-fibre hit was not cleaned already (because hot)
00740                     // In this case don't apply the cleaning
00741                     const HcalChannelStatus* theStatus = theHcalChStatus->getValues(theShortDetId29);
00742                     unsigned theStatusValue = theStatus->getValue();
00743                     // The channel is killed
00744                     if ( !theStatusValue ) { 
00745                       //rescaleFactor = 0. ;
00746                       pfrhHFEMCleaned29 = createHcalRecHit( detid, 
00747                                                             theLongHitEnergy29, 
00748                                                             PFLayer::HF_EM, 
00749                                                             hcalEndcapGeometry,
00750                                                             ct.id().rawId() );
00751                       pfrhHFEMCleaned29->setRescale(theLongHit29->time());
00752                       /* 
00753                       std::cout << "ieta/iphi = " << ieta29 << " " << iphi 
00754                                 << ", Energy em/had/long/short = " 
00755                                 << energyemHF << " " << energyhadHF << " "
00756                                 << theLongHitEnergy29 << " " << theShortHitEnergy29 << " " 
00757                                 << ". The status value is " << theStatusValue
00758                                 << ". Time = " << theLongHit29->time() << " " 
00759                                 << ". The short and long flags : " 
00760                                 << flagShortDPG29 << " " << flagLongDPG29 << " "  
00761                                 << flagShortTimeDPG29 << " " << flagLongTimeDPG29 << " "  
00762                                 << flagShortPulseDPG29 << " " << flagLongPulseDPG29 << " "  
00763                                 << ". Long fibres were cleaned." << std::endl;
00764                       */
00765                       longFibre -= theLongHitEnergy29;
00766                       theLongHitEnergy29 = 0.;
00767                     }
00768                   }
00769 
00770                   // Check that the energy in tower 29 is smaller than in tower 30
00771                   // First in long fibres
00772                   if ( theLongHitEnergy29 > std::max(theLongHitEnergy,shortFibre_Cut/2) ) { 
00773                     pfrhHFEMCleaned29 = createHcalRecHit( detid, 
00774                                                           theLongHitEnergy29, 
00775                                                           PFLayer::HF_EM, 
00776                                                           hcalEndcapGeometry,
00777                                                           ct.id().rawId() );
00778                     pfrhHFEMCleaned29->setRescale(theLongHit29->time());
00779                     /*
00780                     std::cout << "ieta/iphi = " << ieta29 << " " << iphi 
00781                               << ", Energy L29/S29/L30/S30 = " 
00782                               << theLongHitEnergy29 << " " << theShortHitEnergy29 << " "
00783                               << theLongHitEnergy << " " << theShortHitEnergy << " " 
00784                               << ". Long fibres were cleaned." << std::endl;
00785                     */
00786                     longFibre -= theLongHitEnergy29;
00787                     theLongHitEnergy29 = 0.;
00788                   }
00789                   // Second in short fibres
00790                   if ( theShortHitEnergy29 > std::max(theShortHitEnergy,shortFibre_Cut/2.) ) { 
00791                     pfrhHFHADCleaned29 = createHcalRecHit( detid, 
00792                                                            theShortHitEnergy29, 
00793                                                            PFLayer::HF_HAD, 
00794                                                            hcalEndcapGeometry,
00795                                                            ct.id().rawId() );
00796                     pfrhHFHADCleaned29->setRescale(theShortHit29->time());
00797                     /*
00798                     std::cout << "ieta/iphi = " << ieta << " " << iphi 
00799                               << ", Energy L29/S29/L30/S30 = " 
00800                               << theLongHitEnergy29 << " " << theShortHitEnergy29 << " "
00801                               << theLongHitEnergy << " " << theShortHitEnergy << " " 
00802                               << ". Short fibres were cleaned." << std::endl;
00803                     */
00804                     shortFibre -= theShortHitEnergy29;
00805                     theShortHitEnergy29 = 0.;
00806                   }
00807                 }
00808 
00809 
00810                 // Determine EM and HAD after cleaning of short and long fibres
00811                 energyhadHF = 2.*shortFibre;
00812                 energyemHF = longFibre - shortFibre;
00813 
00814                 // The EM energy might be negative, as it amounts to Long - Short
00815                 // In that case, put the EM "energy" in the HAD energy
00816                 // Just to avoid systematic positive bias due to "Short" high fluctuations
00817                 if ( energyemHF < thresh_HF_ ) { 
00818                   energyhadHF += energyemHF;
00819                   energyemHF = 0.;
00820                 }
00821 
00822                 // Apply HCAL DPG calibration factors, if requested
00823                 if ( HF_Calib_ ) { 
00824                   energyhadHF   *= myPFCorr->getValues(detid)->getValue();
00825                   energyemHF *= myPFCorr->getValues(detid)->getValue();
00826                 }
00827                 
00828                 
00829                 // Create an EM and a HAD rechit if above threshold.
00830                 if ( energyemHF > thresh_HF_ || energyhadHF > thresh_HF_ ) { 
00831                   pfrhHFEM = createHcalRecHit( detid, 
00832                                                energyemHF, 
00833                                                PFLayer::HF_EM, 
00834                                                hcalEndcapGeometry,
00835                                                ct.id().rawId() );
00836                   pfrhHFHAD = createHcalRecHit( detid, 
00837                                                 energyhadHF, 
00838                                                 PFLayer::HF_HAD, 
00839                                                 hcalEndcapGeometry,
00840                                                 ct.id().rawId() );
00841                   pfrhHFEM->setEnergyUp(energyhadHF);
00842                   pfrhHFHAD->setEnergyUp(energyemHF);
00843                 }
00844                 
00845               }
00846               break;
00847             default:
00848               LogError("PFRecHitProducerHCAL")
00849                 <<"CaloTower constituent: unknown layer : "
00850                 <<detid.subdet()<<endl;
00851             } 
00852 
00853             if(pfrh) { 
00854               rechits.push_back( *pfrh );
00855               delete pfrh;
00856               idSortedRecHits.insert( make_pair(ct.id().rawId(), 
00857                                                 rechits.size()-1 ) ); 
00858             }
00859             if(pfrhCleaned) { 
00860               rechitsCleaned.push_back( *pfrhCleaned );
00861               delete pfrhCleaned;
00862             }
00863             //---ab: 2 rechits for HF:     
00864             if(pfrhHFEM) { 
00865               HFEMRecHits->push_back( *pfrhHFEM );
00866               delete pfrhHFEM;
00867               idSortedRecHitsHFEM.insert( make_pair(ct.id().rawId(), 
00868                                                 HFEMRecHits->size()-1 ) ); 
00869             }
00870             if(pfrhHFHAD) { 
00871               HFHADRecHits->push_back( *pfrhHFHAD );
00872               delete pfrhHFHAD;
00873               idSortedRecHitsHFHAD.insert( make_pair(ct.id().rawId(), 
00874                                                 HFHADRecHits->size()-1 ) ); 
00875             }
00876             //---ab        
00877             if(pfrhHFEMCleaned) { 
00878               rechitsCleaned.push_back( *pfrhHFEMCleaned );
00879               delete pfrhHFEMCleaned;
00880             }
00881             if(pfrhHFHADCleaned) { 
00882               rechitsCleaned.push_back( *pfrhHFHADCleaned );
00883               delete pfrhHFHADCleaned;
00884             }
00885             if(pfrhHFEMCleaned29) { 
00886               rechitsCleaned.push_back( *pfrhHFEMCleaned29 );
00887               delete pfrhHFEMCleaned29;
00888             }
00889             if(pfrhHFHADCleaned29) { 
00890               rechitsCleaned.push_back( *pfrhHFHADCleaned29 );
00891               delete pfrhHFHADCleaned29;
00892             }
00893           }
00894       }
00895       // do navigation 
00896       for(unsigned i=0; i<rechits.size(); i++ ) {
00897         findRecHitNeighboursCT( rechits[i], 
00898                                 idSortedRecHits, 
00899                                 caloTowerTopology);
00900       }
00901       for(unsigned i=0; i<HFEMRecHits->size(); i++ ) {
00902         findRecHitNeighboursCT( (*HFEMRecHits)[i], 
00903                                 idSortedRecHitsHFEM, 
00904                                 caloTowerTopology);
00905       }
00906       for(unsigned i=0; i<HFHADRecHits->size(); i++ ) {
00907         findRecHitNeighboursCT( (*HFHADRecHits)[i], 
00908                                 idSortedRecHitsHFHAD, 
00909                                 caloTowerTopology);
00910       }
00911       iEvent.put( HFHADRecHits,"HFHAD" );       
00912       iEvent.put( HFEMRecHits,"HFEM" ); 
00913     }   
00914   }
00915   else if( !(inputTagHcalRecHitsHBHE_ == InputTag()) ) { 
00916     // clustering is not done on CaloTowers but on HCAL rechits.
00917        
00918   
00919     // get the hcal topology
00920     HcalTopology hcalTopology;
00921     
00922     // HCAL rechits 
00923     //    vector<edm::Handle<HBHERecHitCollection> > hcalHandles;  
00924     edm::Handle<HBHERecHitCollection>  hcalHandle;  
00925 
00926     
00927     bool found = iEvent.getByLabel(inputTagHcalRecHitsHBHE_, 
00928                                    hcalHandle );
00929 
00930     if(!found) {
00931       ostringstream err;
00932       err<<"could not find rechits "<<inputTagHcalRecHitsHBHE_;
00933       LogError("PFRecHitProducerHCAL")<<err.str()<<endl;
00934     
00935       throw cms::Exception( "MissingProduct", err.str());
00936     }
00937     else {
00938       assert( hcalHandle.isValid() );
00939       
00940       const edm::Handle<HBHERecHitCollection>& handle = hcalHandle;
00941       for(unsigned irechit=0; irechit<handle->size(); irechit++) {
00942         const HBHERecHit& hit = (*handle)[irechit];
00943         
00944         double energy = hit.energy();
00945         
00946         reco::PFRecHit* pfrh = 0;
00947         
00948 
00949         const HcalDetId& detid = hit.detid();
00950         switch( detid.subdet() ) {
00951         case HcalBarrel:
00952           {
00953             if(energy < thresh_Barrel_ ) continue;
00954             pfrh = createHcalRecHit( detid, 
00955                                      energy, 
00956                                      PFLayer::HCAL_BARREL1, 
00957                                      hcalBarrelGeometry );
00958           }
00959           break;
00960         case HcalEndcap:
00961           {
00962             if(energy < thresh_Endcap_ ) continue;
00963             pfrh = createHcalRecHit( detid, 
00964                                      energy, 
00965                                      PFLayer::HCAL_ENDCAP, 
00966                                      hcalEndcapGeometry );        
00967           }
00968           break;
00969         case HcalForward:
00970           {
00971             if(energy < thresh_HF_ ) continue;
00972             pfrh = createHcalRecHit( detid, 
00973                                      energy, 
00974                                      PFLayer::HF_HAD, 
00975                                      hcalEndcapGeometry );
00976           }
00977           break;
00978         default:
00979           LogError("PFRecHitProducerHCAL")
00980             <<"HCAL rechit: unknown layer : "<<detid.subdet()<<endl;
00981           continue;
00982         } 
00983 
00984         if(pfrh) { 
00985           rechits.push_back( *pfrh );
00986           delete pfrh;
00987           idSortedRecHits.insert( make_pair(detid.rawId(), 
00988                                             rechits.size()-1 ) ); 
00989         }
00990       }
00991       
00992       
00993       // do navigation:
00994       for(unsigned i=0; i<rechits.size(); i++ ) {
00995         
00996         findRecHitNeighbours( rechits[i], idSortedRecHits, 
00997                               hcalTopology, 
00998                               *hcalBarrelGeometry, 
00999                               hcalTopology,
01000                               *hcalEndcapGeometry);
01001       } // loop for navigation
01002     }  // endif hcal rechits were found
01003   } // endif clustering on rechits in hcal
01004 }
01005 
01006 
01007 
01008 
01009 
01010 
01011 reco::PFRecHit* 
01012 PFRecHitProducerHCAL::createHcalRecHit( const DetId& detid,
01013                                         double energy,
01014                                         PFLayer::Layer layer,
01015                                         const CaloSubdetectorGeometry* geom,
01016                                         unsigned newDetId ) {
01017   
01018   const CaloCellGeometry *thisCell = geom->getGeometry(detid);
01019   if(!thisCell) {
01020     edm::LogError("PFRecHitProducerHCAL")
01021       <<"warning detid "<<detid.rawId()<<" not found in layer "
01022       <<layer<<endl;
01023     return 0;
01024   }
01025   
01026   const GlobalPoint& position = thisCell->getPosition();
01027   
01028   double depth_correction = 0.;
01029   switch ( layer ) { 
01030   case PFLayer::HF_EM:
01031     depth_correction = position.z() > 0. ? EM_Depth_ : -EM_Depth_;
01032     break;
01033   case PFLayer::HF_HAD:
01034     depth_correction = position.z() > 0. ? HAD_Depth_ : -HAD_Depth_;
01035     break;
01036   default:
01037     break;
01038   }
01039 
01040   unsigned id = detid;
01041   if(newDetId) id = newDetId;
01042   reco::PFRecHit *rh = 
01043     new reco::PFRecHit( id,  layer, energy, 
01044                         position.x(), position.y(), position.z()+depth_correction, 
01045                         0,0,0 );
01046  
01047   
01048   
01049   
01050   // set the corners
01051   const CaloCellGeometry::CornersVec& corners = thisCell->getCorners();
01052 
01053   assert( corners.size() == 8 );
01054 
01055   rh->setNECorner( corners[0].x(), corners[0].y(),  corners[0].z()+depth_correction );
01056   rh->setSECorner( corners[1].x(), corners[1].y(),  corners[1].z()+depth_correction );
01057   rh->setSWCorner( corners[2].x(), corners[2].y(),  corners[2].z()+depth_correction );
01058   rh->setNWCorner( corners[3].x(), corners[3].y(),  corners[3].z()+depth_correction );
01059  
01060   return rh;
01061 }
01062 
01063 
01064 
01065 
01066 void 
01067 PFRecHitProducerHCAL::findRecHitNeighbours
01068 ( reco::PFRecHit& rh, 
01069   const map<unsigned,unsigned >& sortedHits, 
01070   const CaloSubdetectorTopology& barrelTopology, 
01071   const CaloSubdetectorGeometry& barrelGeometry, 
01072   const CaloSubdetectorTopology& endcapTopology, 
01073   const CaloSubdetectorGeometry& endcapGeometry ) {
01074   
01075   //cout<<"------PFRecHitProducerHcaL:findRecHitNeighbours navigation value "<<navigation_HF_<<endl;
01076  if(navigation_HF_ == false){
01077     if( rh.layer() == PFLayer::HF_HAD )
01078       return;
01079     if( rh.layer() == PFLayer::HF_EM )
01080       return;
01081   } 
01082   DetId detid( rh.detId() );
01083 
01084   const CaloSubdetectorTopology* topology = 0;
01085   const CaloSubdetectorGeometry* geometry = 0;
01086   const CaloSubdetectorGeometry* othergeometry = 0;
01087   
01088   switch( rh.layer() ) {
01089   case PFLayer::ECAL_ENDCAP: 
01090     topology = &endcapTopology;
01091     geometry = &endcapGeometry;
01092     break;
01093   case PFLayer::ECAL_BARREL: 
01094     topology = &barrelTopology;
01095     geometry = &barrelGeometry;
01096     break;
01097   case PFLayer::HCAL_ENDCAP:
01098     topology = &endcapTopology;
01099     geometry = &endcapGeometry;
01100     othergeometry = &barrelGeometry;
01101     break;
01102   case PFLayer::HCAL_BARREL1:
01103     topology = &barrelTopology;
01104     geometry = &barrelGeometry;
01105     othergeometry = &endcapGeometry;
01106     break;
01107   case PFLayer::PS1:
01108   case PFLayer::PS2:
01109     topology = &barrelTopology;
01110     geometry = &barrelGeometry;
01111     othergeometry = &endcapGeometry;
01112     break;
01113   default:
01114     assert(0);
01115   }
01116   
01117   assert( topology && geometry );
01118 
01119   CaloNavigator<DetId> navigator(detid, topology);
01120 
01121   DetId north = navigator.north();  
01122   
01123   DetId northeast(0);
01124   if( north != DetId(0) ) {
01125     northeast = navigator.east();  
01126   }
01127   navigator.home();
01128 
01129 
01130   DetId south = navigator.south();
01131 
01132   
01133 
01134   DetId southwest(0); 
01135   if( south != DetId(0) ) {
01136     southwest = navigator.west();
01137   }
01138   navigator.home();
01139 
01140 
01141   DetId east = navigator.east();
01142   DetId southeast;
01143   if( east != DetId(0) ) {
01144     southeast = navigator.south(); 
01145   }
01146   navigator.home();
01147   DetId west = navigator.west();
01148   DetId northwest;
01149   if( west != DetId(0) ) {   
01150     northwest = navigator.north();  
01151   }
01152   navigator.home();
01153     
01154   IDH i = sortedHits.find( north.rawId() );
01155   if(i != sortedHits.end() ) 
01156     rh.add4Neighbour( i->second );
01157   
01158   i = sortedHits.find( northeast.rawId() );
01159   if(i != sortedHits.end() ) 
01160     rh.add8Neighbour( i->second );
01161   
01162   i = sortedHits.find( south.rawId() );
01163   if(i != sortedHits.end() ) 
01164     rh.add4Neighbour( i->second );
01165     
01166   i = sortedHits.find( southwest.rawId() );
01167   if(i != sortedHits.end() ) 
01168     rh.add8Neighbour( i->second );
01169     
01170   i = sortedHits.find( east.rawId() );
01171   if(i != sortedHits.end() ) 
01172     rh.add4Neighbour( i->second );
01173     
01174   i = sortedHits.find( southeast.rawId() );
01175   if(i != sortedHits.end() ) 
01176     rh.add8Neighbour( i->second );
01177     
01178   i = sortedHits.find( west.rawId() );
01179   if(i != sortedHits.end() ) 
01180      rh.add4Neighbour( i->second );
01181    
01182   i = sortedHits.find( northwest.rawId() );
01183   if(i != sortedHits.end() ) 
01184     rh.add8Neighbour( i->second );
01185     
01186 
01187 }
01188 
01189 
01190 void 
01191 PFRecHitProducerHCAL::findRecHitNeighboursCT
01192 ( reco::PFRecHit& rh, 
01193   const map<unsigned, unsigned >& sortedHits, 
01194   const CaloSubdetectorTopology& topology ) {
01195   //cout<<"------PFRecHitProducerHcaL:findRecHitNeighboursCT navigation value "<<navigation_HF_<<endl;
01196   //  cout<<"----------- rechit print out"<<endl;
01197   // if(( rh.layer() == PFLayer::HF_HAD )||(rh.layer() == PFLayer::HF_EM)) {  
01198     
01199   //    cout<<rh<<endl;
01200     //  }
01201   if(navigation_HF_ == false){
01202     if( rh.layer() == PFLayer::HF_HAD )
01203       return;
01204     if( rh.layer() == PFLayer::HF_EM )
01205       return;
01206   }
01207   CaloTowerDetId ctDetId( rh.detId() );
01208     
01209 
01210   vector<DetId> northids = topology.north(ctDetId);
01211   vector<DetId> westids = topology.west(ctDetId);
01212   vector<DetId> southids = topology.south(ctDetId);
01213   vector<DetId> eastids = topology.east(ctDetId);
01214 
01215 
01216   CaloTowerDetId badId;
01217 
01218   // all the following detids will be CaloTowerDetId
01219   CaloTowerDetId north;
01220   CaloTowerDetId northwest;
01221   CaloTowerDetId northwest2;
01222   CaloTowerDetId west;
01223   CaloTowerDetId west2;
01224   CaloTowerDetId southwest;
01225   CaloTowerDetId southwest2;
01226   CaloTowerDetId south;
01227   CaloTowerDetId southeast;
01228   CaloTowerDetId southeast2;
01229   CaloTowerDetId east;
01230   CaloTowerDetId east2;
01231   CaloTowerDetId northeast;
01232   CaloTowerDetId northeast2;
01233   
01234   // for north and south, there is no ambiguity : 1 or 0 neighbours
01235   stringstream err("PFRecHitProducerHCAL::findRecHitNeighboursCT : incorrect number of neighbours "); 
01236   
01237   switch( northids.size() ) {
01238   case 0: 
01239     break;
01240   case 1: 
01241     north = northids[0];
01242     break;
01243   default:
01244     err<<"north: "<<northids.size();
01245     throw( err.str() ); 
01246   }
01247 
01248   switch( southids.size() ) {
01249   case 0: 
01250     break;
01251   case 1: 
01252     south = southids[0];
01253     break;
01254   default:
01255     err<<"south: "<<southids.size();
01256     throw( err.str() ); 
01257   }
01258   
01259   // for east and west, one must take care 
01260   // of the pitch change in HCAL endcap.
01261 
01262   switch( eastids.size() ) {
01263   case 0: 
01264     break;
01265   case 1: 
01266     east = eastids[0];
01267     northeast = getNorth(east, topology);
01268     southeast = getSouth(east, topology);
01269     break;
01270   case 2:  
01271     // in this case, 0 is more on the north than 1
01272     east = eastids[0];
01273     east2 = eastids[1];
01274     northeast = getNorth(east, topology );
01275     southeast = getSouth(east2, topology);    
01276     northeast2 = getNorth(northeast, topology );
01277     southeast2 = getSouth(southeast, topology);    
01278     break;
01279   default:
01280     err<<"eastids: "<<eastids.size();
01281     throw( err.str() ); 
01282   }
01283   
01284   
01285   switch( westids.size() ) {
01286   case 0: 
01287     break;
01288   case 1: 
01289     west = westids[0];
01290     northwest = getNorth(west, topology);
01291     southwest = getSouth(west, topology);
01292     break;
01293   case 2:  
01294     // in this case, 0 is more on the north than 1
01295     west = westids[0];
01296     west2 = westids[1];
01297     northwest = getNorth(west, topology );
01298     southwest = getSouth(west2, topology );    
01299     northwest2 = getNorth(northwest, topology );
01300     southwest2 = getSouth(southwest, topology );    
01301     break;
01302   default:
01303     err<<"westids: "<< westids.size();
01304     throw( err.str() ); 
01305   }
01306 
01307 
01308 
01309 
01310   // find and set neighbours
01311     
01312   IDH i = sortedHits.find( north.rawId() );
01313   if(i != sortedHits.end() ) 
01314     rh.add4Neighbour( i->second );
01315   
01316   i = sortedHits.find( northeast.rawId() );
01317   if(i != sortedHits.end() ) 
01318     rh.add8Neighbour( i->second );
01319   
01320   i = sortedHits.find( northeast2.rawId() );
01321   if(i != sortedHits.end() ) 
01322     rh.add8Neighbour( i->second );
01323   
01324   i = sortedHits.find( south.rawId() );
01325   if(i != sortedHits.end() ) 
01326     rh.add4Neighbour( i->second );
01327     
01328   i = sortedHits.find( southwest.rawId() );
01329   if(i != sortedHits.end() ) 
01330     rh.add8Neighbour( i->second );
01331     
01332   i = sortedHits.find( southwest2.rawId() );
01333   if(i != sortedHits.end() ) 
01334     rh.add8Neighbour( i->second );
01335     
01336   i = sortedHits.find( east.rawId() );
01337   if(i != sortedHits.end() ) 
01338     rh.add4Neighbour( i->second );
01339     
01340   i = sortedHits.find( east2.rawId() );
01341   if(i != sortedHits.end() ) 
01342     rh.add4Neighbour( i->second );
01343     
01344   i = sortedHits.find( southeast.rawId() );
01345   if(i != sortedHits.end() ) 
01346     rh.add8Neighbour( i->second );
01347     
01348   i = sortedHits.find( southeast2.rawId() );
01349   if(i != sortedHits.end() ) 
01350     rh.add8Neighbour( i->second );
01351     
01352   i = sortedHits.find( west.rawId() );
01353   if(i != sortedHits.end() ) 
01354      rh.add4Neighbour( i->second );
01355    
01356   i = sortedHits.find( west2.rawId() );
01357   if(i != sortedHits.end() ) 
01358      rh.add4Neighbour( i->second );
01359    
01360   i = sortedHits.find( northwest.rawId() );
01361   if(i != sortedHits.end() ) 
01362     rh.add8Neighbour( i->second );
01363 
01364   i = sortedHits.find( northwest2.rawId() );
01365   if(i != sortedHits.end() ) 
01366     rh.add8Neighbour( i->second );
01367 
01368   //  cout<<"----------- rechit print out"<<endl;
01369   // if(( rh.layer() == PFLayer::HF_HAD )||(rh.layer() == PFLayer::HF_EM)) {  
01370     
01371   //   cout<<rh<<endl;
01372     //  }
01373 }
01374 
01375 
01376 
01377 DetId 
01378 PFRecHitProducerHCAL::getSouth(const DetId& id, 
01379                                const CaloSubdetectorTopology& topology) {
01380 
01381   DetId south;
01382   vector<DetId> sids = topology.south(id);
01383   if(sids.size() == 1)
01384     south = sids[0];
01385   
01386   return south;
01387 } 
01388 
01389 
01390 
01391 DetId 
01392 PFRecHitProducerHCAL::getNorth(const DetId& id, 
01393                                const CaloSubdetectorTopology& topology) {
01394 
01395   DetId north;
01396   vector<DetId> nids = topology.north(id);
01397   if(nids.size() == 1)
01398     north = nids[0];
01399   
01400   return north;
01401 } 
01402 
01403