00001
00019 #include "RecoTauTag/RecoTau/interface/TauDiscriminationProducerBase.h"
00020 #include "FWCore/Framework/interface/ESHandle.h"
00021 #include "CondFormats/DataRecord/interface/EcalChannelStatusRcd.h"
00022 #include "CondFormats/EcalObjects/interface/EcalChannelStatus.h"
00023 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00024 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00025 #include "Geometry/CaloTopology/interface/EcalTrigTowerConstituentsMap.h"
00026 #include "Geometry/Records/interface/IdealGeometryRecord.h"
00027 #include "DataFormats/DetId/interface/DetId.h"
00028 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00029 #include "DataFormats/EcalDetId/interface/EEDetId.h"
00030 #include "DataFormats/Math/interface/deltaR.h"
00031 #include "DataFormats/TauReco/interface/PFTauDiscriminator.h"
00032
00033 #include <TMath.h>
00034
00035 using namespace reco;
00036
00037 class PFRecoTauDiscriminationAgainstElectronDeadECAL : public PFTauDiscriminationProducerBase
00038 {
00039 public:
00040 explicit PFRecoTauDiscriminationAgainstElectronDeadECAL(const edm::ParameterSet& cfg)
00041 : PFTauDiscriminationProducerBase(cfg),
00042 moduleLabel_(cfg.getParameter<std::string>("@module_label")),
00043 isFirstEvent_(true)
00044 {
00045 minStatus_ = cfg.getParameter<uint32_t>("minStatus");
00046 dR_ = cfg.getParameter<double>("dR");
00047 }
00048 ~PFRecoTauDiscriminationAgainstElectronDeadECAL() {}
00049
00050 void beginEvent(const edm::Event& evt, const edm::EventSetup& es)
00051 {
00052 updateBadTowers(es);
00053 }
00054
00055 double discriminate(const PFTauRef& pfTau)
00056 {
00057
00058
00059
00060 double discriminator = 1.;
00061 for ( std::vector<towerInfo>::const_iterator badTower = badTowers_.begin();
00062 badTower != badTowers_.end(); ++badTower ) {
00063 if ( deltaR(badTower->eta_, badTower->phi_, pfTau->eta(), pfTau->phi()) < dR_ ) discriminator = 0.;
00064 }
00065
00066 return discriminator;
00067 }
00068
00069 private:
00070 void updateBadTowers(const edm::EventSetup& es)
00071 {
00072
00073
00074 const uint32_t channelStatusId = es.get<EcalChannelStatusRcd>().cacheIdentifier();
00075 const uint32_t caloGeometryId = es.get<CaloGeometryRecord>().cacheIdentifier();
00076 const uint32_t idealGeometryId = es.get<IdealGeometryRecord>().cacheIdentifier();
00077
00078 if ( !isFirstEvent_ && channelStatusId == channelStatusId_cache_ && caloGeometryId == caloGeometryId_cache_ && idealGeometryId == idealGeometryId_cache_ ) return;
00079
00080 edm::ESHandle<EcalChannelStatus> channelStatus;
00081 es.get<EcalChannelStatusRcd>().get(channelStatus);
00082 channelStatusId_cache_ = channelStatusId;
00083
00084 edm::ESHandle<CaloGeometry> caloGeometry;
00085 es.get<CaloGeometryRecord>().get(caloGeometry);
00086 caloGeometryId_cache_ = caloGeometryId;
00087
00088 edm::ESHandle<EcalTrigTowerConstituentsMap> ttMap;
00089 es.get<IdealGeometryRecord>().get(ttMap);
00090 idealGeometryId_cache_ = idealGeometryId;
00091
00092 std::map<uint32_t,unsigned> nBadCrystals, maxStatus;
00093 std::map<uint32_t,double> sumEta, sumPhi;
00094
00095 loopXtals<EBDetId>(nBadCrystals, maxStatus, sumEta, sumPhi, channelStatus.product(), caloGeometry.product(), ttMap.product());
00096 loopXtals<EEDetId>(nBadCrystals, maxStatus, sumEta, sumPhi, channelStatus.product(), caloGeometry.product(), ttMap.product());
00097
00098 badTowers_.clear();
00099 for ( std::map<uint32_t, unsigned>::const_iterator it = nBadCrystals.begin();
00100 it != nBadCrystals.end(); ++it ) {
00101 uint32_t key = it->first;
00102 badTowers_.push_back(towerInfo(key, it->second, maxStatus[key], sumEta[key]/it->second, sumPhi[key]/it->second));
00103 }
00104
00105 isFirstEvent_ = false;
00106 }
00107
00108 template <class Id>
00109 void loopXtals(std::map<uint32_t, unsigned>& nBadCrystals,
00110 std::map<uint32_t, unsigned>& maxStatus,
00111 std::map<uint32_t, double>& sumEta,
00112 std::map<uint32_t, double>& sumPhi ,
00113 const EcalChannelStatus* channelStatus,
00114 const CaloGeometry* caloGeometry,
00115 const EcalTrigTowerConstituentsMap* ttMap) const
00116 {
00117
00118
00119 for ( int i = 0; i < Id::kSizeForDenseIndexing; ++i ) {
00120 Id id = Id::unhashIndex(i);
00121 if ( id == Id(0) ) continue;
00122 EcalChannelStatusMap::const_iterator it = channelStatus->getMap().find(id.rawId());
00123 unsigned status = ( it == channelStatus->end() ) ?
00124 0 : (it->getStatusCode() & statusMask_);
00125 if ( status >= minStatus_ ) {
00126 const GlobalPoint& point = caloGeometry->getPosition(id);
00127 uint32_t key = ttMap->towerOf(id);
00128 maxStatus[key] = TMath::Max(status, maxStatus[key]);
00129 ++nBadCrystals[key];
00130 sumEta[key] += point.eta();
00131 sumPhi[key] += point.phi();
00132 }
00133 }
00134 }
00135
00136 struct towerInfo
00137 {
00138 towerInfo(uint32_t id, unsigned nBad, unsigned maxStatus, double eta, double phi)
00139 : id_(id),
00140 nBad_(nBad),
00141 maxStatus_(maxStatus),
00142 eta_(eta),
00143 phi_(phi)
00144 {}
00145 uint32_t id_;
00146 unsigned nBad_;
00147 unsigned maxStatus_;
00148 double eta_;
00149 double phi_;
00150 };
00151 typedef ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiE4D<double> > PolarLorentzVector;
00152
00153 std::string moduleLabel_;
00154 unsigned minStatus_;
00155 double dR_;
00156
00157 std::vector<towerInfo> badTowers_;
00158 static const uint16_t statusMask_ = 0x1F;
00159
00160 uint32_t channelStatusId_cache_;
00161 uint32_t caloGeometryId_cache_;
00162 uint32_t idealGeometryId_cache_;
00163 bool isFirstEvent_;
00164 };
00165
00166 DEFINE_FWK_MODULE(PFRecoTauDiscriminationAgainstElectronDeadECAL);