CMS 3D CMS Logo

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