CMS 3D CMS Logo

EcalRecHitWorkerRecover.cc
Go to the documentation of this file.
2 
14 
17 
20 
21 
24 {
25  rechitMaker_ = std::make_unique<EcalRecHitSimpleAlgo>();
26  // isolated channel recovery
27  singleRecoveryMethod_ = ps.getParameter<std::string>("singleChannelRecoveryMethod");
28  singleRecoveryThreshold_ = ps.getParameter<double>("singleChannelRecoveryThreshold");
29  killDeadChannels_ = ps.getParameter<bool>("killDeadChannels");
30  recoverEBIsolatedChannels_ = ps.getParameter<bool>("recoverEBIsolatedChannels");
31  recoverEEIsolatedChannels_ = ps.getParameter<bool>("recoverEEIsolatedChannels");
32  recoverEBVFE_ = ps.getParameter<bool>("recoverEBVFE");
33  recoverEEVFE_ = ps.getParameter<bool>("recoverEEVFE");
34  recoverEBFE_ = ps.getParameter<bool>("recoverEBFE");
35  recoverEEFE_ = ps.getParameter<bool>("recoverEEFE");
36 
37  dbStatusToBeExcludedEE_ = ps.getParameter<std::vector<int> >("dbStatusToBeExcludedEE");
38  dbStatusToBeExcludedEB_ = ps.getParameter<std::vector<int> >("dbStatusToBeExcludedEB");
39 
40  logWarningEtThreshold_EB_FE_ = ps.getParameter<double>("logWarningEtThreshold_EB_FE");
41  logWarningEtThreshold_EE_FE_ = ps.getParameter<double>("logWarningEtThreshold_EE_FE");
42 
43  tpDigiToken_ =
44  c.consumes<EcalTrigPrimDigiCollection>(ps.getParameter<edm::InputTag>("triggerPrimitiveDigiCollection"));
45 }
46 
47 
49 {
50 
51  es.get<EcalLaserDbRecord>().get(laser);
54  es.get<EcalMappingRcd>().get(pEcalMapping_);
56  // geometry...
57  es.get<EcalBarrelGeometryRecord>().get("EcalBarrel",pEBGeom_);
62  es.get<IdealGeometryRecord>().get(ttMap_);
63  recoveredDetIds_EB_.clear();
64  recoveredDetIds_EE_.clear();
66 }
67 
68 
69 bool
71  const EcalUncalibratedRecHit& uncalibRH,
73 {
74  DetId detId=uncalibRH.id();
75  uint32_t flags = (0xF & uncalibRH.flags());
76 
77  // get laser coefficient
78  //float lasercalib = laser->getLaserCorrection( detId, evt.time());
79 
80  // killDeadChannels_ = true, means explicitely kill dead channels even if the recovered energies are computed in the code
81  // if you don't want to store the recovered energies in the rechit you can produce LogWarnings if logWarningEtThreshold_EB(EE)_FE>0
82  // logWarningEtThreshold_EB(EE)_FE_<0 will not compute the recovered energies at all (faster)
83 
84  if ( killDeadChannels_ ) {
89  ) {
90  EcalRecHit hit( detId, 0., 0., EcalRecHit::kDead );
92  insertRecHit( hit, result); // insert trivial rechit with kDead flag
93  return true;
94  }
95  if ( flags == EcalRecHitWorkerRecover::EB_FE && !recoverEBFE_) {
96  EcalTrigTowerDetId ttDetId( ((EBDetId)detId).tower() );
97  std::vector<DetId> vid = ttMap_->constituentsOf( ttDetId );
98  for ( std::vector<DetId>::const_iterator dit = vid.begin(); dit != vid.end(); ++dit ) {
99  EcalRecHit hit( (*dit), 0., 0., EcalRecHit::kDead );
100  hit.setFlag( EcalRecHit::kDead ) ;
101  insertRecHit( hit, result ); // insert trivial rechit with kDead flag
102  }
103  if(logWarningEtThreshold_EB_FE_<0)return true; // if you don't want log warning just return true
104  }
105  if ( flags == EcalRecHitWorkerRecover::EE_FE && !recoverEEFE_) {
106  EEDetId id( detId );
107  EcalScDetId sc( 1+(id.ix()-1)/5, 1+(id.iy()-1)/5, id.zside() );
108  std::vector<DetId> eeC;
109  for(int dx=1; dx<=5; ++dx){
110  for(int dy=1; dy<=5; ++dy){
111  int ix = (sc.ix()-1)*5 + dx;
112  int iy = (sc.iy()-1)*5 + dy;
113  int iz = sc.zside();
114  if(EEDetId::validDetId(ix, iy, iz)){
115  eeC.push_back(EEDetId(ix, iy, iz));
116  }
117  }
118  }
119  for ( size_t i = 0; i < eeC.size(); ++i ) {
120  EcalRecHit hit( eeC[i], 0., 0., EcalRecHit::kDead );
121  hit.setFlag( EcalRecHit::kDead ) ;
122  insertRecHit( hit, result ); // insert trivial rechit with kDead flag
123  }
124  if(logWarningEtThreshold_EE_FE_<0) return true; // if you don't want log warning just return true
125  }
126  }
127 
128  if ( flags == EcalRecHitWorkerRecover::EB_single ) {
129  // recover as single dead channel
131 
132  // channel recovery. Accepted new RecHit has the flag AcceptRecHit=TRUE
133  bool AcceptRecHit=true;
135 
136  if ( hit.energy() != 0 and AcceptRecHit == true ) {
138  } else {
139  // recovery failed
140  hit.setFlag( EcalRecHit::kDead ) ;
141  }
142  insertRecHit( hit, result );
143 
144  } else if ( flags == EcalRecHitWorkerRecover::EE_single ) {
145  // recover as single dead channel
147 
148  // channel recovery. Accepted new RecHit has the flag AcceptRecHit=TRUE
149  bool AcceptRecHit=true;
151  if ( hit.energy() != 0 and AcceptRecHit == true ) {
153  } else {
154  // recovery failed
155  hit.setFlag( EcalRecHit::kDead ) ;
156  }
157  insertRecHit( hit, result );
158 
159  } else if ( flags == EcalRecHitWorkerRecover::EB_VFE ) {
160  // recover as dead VFE
161  EcalRecHit hit( detId, 0., 0.);
162  hit.setFlag( EcalRecHit::kDead ) ;
163  // recovery not implemented
164  insertRecHit( hit, result );
165  } else if ( flags == EcalRecHitWorkerRecover::EB_FE ) {
166  // recover as dead TT
167 
168  EcalTrigTowerDetId ttDetId( ((EBDetId)detId).tower() );
170  evt.getByToken(tpDigiToken_, pTPDigis);
171  const EcalTrigPrimDigiCollection * tpDigis = nullptr;
172  tpDigis = pTPDigis.product();
173 
174  EcalTrigPrimDigiCollection::const_iterator tp = tpDigis->find( ttDetId );
175  // recover the whole trigger tower
176  if ( tp != tpDigis->end() ) {
177  //std::vector<DetId> vid = ecalMapping_->dccTowerConstituents( ecalMapping_->DCCid( ttDetId ), ecalMapping_->iTT( ttDetId ) );
178  std::vector<DetId> vid = ttMap_->constituentsOf( ttDetId );
179  float tpEt = ecalScale_.getTPGInGeV( tp->compressedEt(), tp->id() );
180  float tpEtThreshEB = logWarningEtThreshold_EB_FE_;
181  if(tpEt>tpEtThreshEB){
182  edm::LogWarning("EnergyInDeadEB_FE")<<"TP energy in the dead TT = "<<tpEt<<" at "<<ttDetId;
183  }
184  if ( !killDeadChannels_ || recoverEBFE_ ) {
185  // democratic energy sharing
186 
187  for ( std::vector<DetId>::const_iterator dit = vid.begin(); dit != vid.end(); ++dit ) {
188  if (alreadyInserted(*dit)) continue;
189  float theta = ebGeom_->getGeometry(*dit)->getPosition().theta();
190  float tpEt = ecalScale_.getTPGInGeV( tp->compressedEt(), tp->id() );
192  EcalRecHit hit( *dit, tpEt /((float)vid.size()) / sin(theta), 0.);
194  if ( tp->compressedEt() == 0xFF ) hit.setFlag( EcalRecHit::kTPSaturated );
195  if ( tp->sFGVB() ) hit.setFlag( EcalRecHit::kL1SpikeFlag );
196  insertRecHit( hit, result );
197  }
198  }
199  } else {
200  // tp not found => recovery failed
201  std::vector<DetId> vid = ttMap_->constituentsOf( ttDetId );
202  for ( std::vector<DetId>::const_iterator dit = vid.begin(); dit != vid.end(); ++dit ) {
203  if (alreadyInserted(*dit)) continue;
204  EcalRecHit hit( *dit,0., 0. );
205  hit.setFlag( EcalRecHit::kDead ) ;
206  insertRecHit( hit, result );
207  }
208  }
209  }
210  } else if ( flags == EcalRecHitWorkerRecover::EE_FE ) {
211  // Structure for recovery:
212  // ** SC --> EEDetId constituents (eeC) --> associated Trigger Towers (aTT) --> EEDetId constituents (aTTC)
213  // ** energy for a SC EEDetId = [ sum_aTT(energy) - sum_aTTC(energy) ] / N_eeC
214  // .. i.e. the total energy of the TTs covering the SC minus
215  // .. the energy of the recHits in the TTs but not in the SC
216  //std::vector<DetId> vid = ecalMapping_->dccTowerConstituents( ecalMapping_->DCCid( ttDetId ), ecalMapping_->iTT( ttDetId ) );
217  // due to lack of implementation of the EcalTrigTowerDetId ix,iy methods in EE we compute Et recovered energies (in EB we compute E)
218 
219  EEDetId eeId( detId );
220  EcalScDetId sc( (eeId.ix()-1)/5+1, (eeId.iy()-1)/5+1, eeId.zside() );
221  std::set<DetId> eeC;
222  for(int dx=1; dx<=5; ++dx){
223  for(int dy=1; dy<=5; ++dy){
224  int ix = (sc.ix()-1)*5 + dx;
225  int iy = (sc.iy()-1)*5 + dy;
226  int iz = sc.zside();
227  if(EEDetId::validDetId(ix, iy, iz)){
228  EEDetId id(ix, iy, iz);
230  eeC.insert(id);
231  } // check status
232  }
233  }
234  }
235 
237  evt.getByToken(tpDigiToken_, pTPDigis);
238  const EcalTrigPrimDigiCollection * tpDigis = nullptr;
239  tpDigis = pTPDigis.product();
240 
241  // associated trigger towers
242  std::set<EcalTrigTowerDetId> aTT;
243  for ( std::set<DetId>::const_iterator it = eeC.begin(); it!=eeC.end(); ++it ) {
244  aTT.insert( ttMap_->towerOf( *it ) );
245  }
246  // associated trigger towers: total energy
247  float totE = 0;
248  // associated trigger towers: EEDetId constituents
249  std::set<DetId> aTTC;
250  bool atLeastOneTPSaturated = false;
251  for ( std::set<EcalTrigTowerDetId>::const_iterator it = aTT.begin(); it != aTT.end(); ++it ) {
252  // add the energy of this trigger tower
253  EcalTrigPrimDigiCollection::const_iterator itTP = tpDigis->find( *it );
254  if ( itTP != tpDigis->end() ) {
255 
256  std::vector<DetId> v = ttMap_->constituentsOf( *it );
257 
258  // from the constituents, remove dead channels
259  std::vector<DetId>::iterator ttcons = v.begin();
260  while (ttcons != v.end()){
262  ttcons=v.erase(ttcons);
263  } else {
264  ++ttcons;
265  }
266  }// while
267 
268  if ( itTP->compressedEt() == 0xFF ){ // In the case of a saturated trigger tower, a fraction
269  atLeastOneTPSaturated = true; //of the saturated energy is put in: number of xtals in dead region/total xtals in TT *63.75
270 
271  //Alternative recovery algorithm that I will now investigate.
272  //Estimate energy sums the energy in the working channels, then decides how much energy
273  //to put here depending on that. Duncan 20101203
274 
275  totE += estimateEnergy(itTP->id().ietaAbs(), &result, eeC, v);
276 
277  /*
278  These commented out lines use
279  64GeV*fraction of the TT overlapping the dead FE
280 
281  int count = 0;
282  for (std::vector<DetId>::const_iterator idsit = v.begin(); idsit != v.end(); ++ idsit){
283  std::set<DetId>::const_iterator itFind = eeC.find(*idsit);
284  if (itFind != eeC.end())
285  ++count;
286  }
287  //std::cout << count << ", " << v.size() << std::endl;
288  totE+=((float)count/(float)v.size())* ((it->ietaAbs()>26)?2*ecalScale_.getTPGInGeV( itTP->compressedEt(), itTP->id() ):ecalScale_.getTPGInGeV( itTP->compressedEt(), itTP->id() ));*/
289  }
290  else {totE += ((it->ietaAbs()>26)?2:1)*ecalScale_.getTPGInGeV( itTP->compressedEt(), itTP->id() );}
291 
292 
293  // get the trigger tower constituents
294 
295  if (itTP->compressedEt() == 0){ // If there's no energy in TT, the constituents are removed from the recovery.
296  for (size_t i = 0 ; i < v.size(); ++i)
297  eeC.erase(v[i]);
298  }
299  else if (itTP->compressedEt()!=0xFF){ //If it's saturated the energy has already been determined, so we do not want to subtract any channels
300  for ( size_t j = 0; j < v.size(); ++j ) {
301  aTTC.insert( v[j] );
302  }
303  }
304 
305  }
306  }
307  // remove crystals of dead SC
308  // (this step is not needed if sure that SC crystals are not
309  // in the recHit collection)
310 
311  for ( std::set<DetId>::const_iterator it = eeC.begin(); it != eeC.end(); ++it ) {
312  aTTC.erase(*it);
313  }
314  // compute the total energy for the dead SC
315  const EcalRecHitCollection * hits = &result;
316  for ( std::set<DetId>::const_iterator it = aTTC.begin(); it != aTTC.end(); ++it ) {
317  EcalRecHitCollection::const_iterator jt = hits->find( *it );
318  if ( jt != hits->end() ) {
319  float energy = jt->energy(); // Correct conversion to Et
320  float eta = geo_->getPosition(jt->id()).eta();
321  float pf = 1.0/cosh(eta);
322  // use Et instead of E, consistent with the Et estimation of the associated TT
323  totE -= energy*pf;
324  }
325  }
326 
327 
328  float scEt = totE;
329  float scEtThreshEE = logWarningEtThreshold_EE_FE_;
330  if(scEt>scEtThreshEE){
331  edm::LogWarning("EnergyInDeadEE_FE")<<"TP energy in the dead TT = "<<scEt<<" at "<<sc;
332  }
333 
334  // assign the energy to the SC crystals
335  if ( !killDeadChannels_ || recoverEEFE_ ) { // if eeC is empty, i.e. there are no hits
336  // in the tower, nothing is returned. No negative values from noise.
337  for ( std::set<DetId>::const_iterator it = eeC.begin(); it != eeC.end(); ++it ) {
338 
339  float eta = geo_->getPosition(*it).eta(); //Convert back to E from Et for the recovered hits
340  float pf = 1.0/cosh(eta);
341  EcalRecHit hit( *it, totE / ((float)eeC.size()*pf), 0);
342 
343  if (atLeastOneTPSaturated) hit.setFlag(EcalRecHit::kTPSaturated );
345  insertRecHit( hit, result );
346 
347  }// for
348  }// if
349  }
350  return true;
351 }
352 
353 float EcalRecHitWorkerRecover::estimateEnergy(int ieta, EcalRecHitCollection* hits, const std::set<DetId>& sId, const std::vector<DetId>& vId ) {
354 
355  float xtalE=0;
356  int count = 0;
357  for (std::vector<DetId>::const_iterator vIdit = vId.begin(); vIdit != vId.end(); ++ vIdit){
358  std::set<DetId>::const_iterator sIdit = sId.find(*vIdit);
359  if (sIdit==sId.end()){
360  float energy = hits->find(*vIdit)->energy();
361  float eta = geo_->getPosition(*vIdit).eta();
362  float pf = 1.0/cosh(eta);
363  xtalE += energy*pf;
364  count++;
365  }
366  }
367 
368  if (count==0) { // If there are no overlapping crystals return saturated value.
369 
370  double etsat = tpgscale_.getTPGInGeV(0xFF,
371  ttMap_->towerOf(*vId.begin())); // get saturation value for the first
372  // constituent, for the others it's the same
373 
374  return etsat/cosh(ieta)*(ieta>26?2:1); // account for duplicated TT in EE for ieta>26
375  }
376  else return xtalE*((vId.size()/(float)count) - 1)*(ieta>26?2:1);
377 
378 
379 }
380 
381 
383 {
384  // skip already inserted DetId's and raise a log warning
385  if ( alreadyInserted( hit.id() ) ) {
386  edm::LogWarning("EcalRecHitWorkerRecover") << "DetId already recovered! Skipping...";
387  return;
388  }
389  EcalRecHitCollection::iterator it = collection.find( hit.id() );
390  if ( it == collection.end() ) {
391  // insert the hit in the collection
392  collection.push_back( hit );
393  } else {
394  // overwrite existing recHit
395  *it = hit;
396  }
397  if ( hit.id().subdetId() == EcalBarrel ) {
398  recoveredDetIds_EB_.insert( hit.id() );
399  } else if ( hit.id().subdetId() == EcalEndcap ) {
400  recoveredDetIds_EE_.insert( hit.id() );
401  } else {
402  edm::LogError("EcalRecHitWorkerRecover::InvalidDetId") << "Invalid DetId " << hit.id().rawId();
403  }
404 }
405 
406 
408 {
409  bool res = false;
410  if ( id.subdetId() == EcalBarrel ) {
411  res = ( recoveredDetIds_EB_.find( id ) != recoveredDetIds_EB_.end() );
412  } else if ( id.subdetId() == EcalEndcap ) {
413  res = ( recoveredDetIds_EE_.find( id ) != recoveredDetIds_EE_.end() );
414  } else {
415  edm::LogError("EcalRecHitWorkerRecover::InvalidDetId") << "Invalid DetId " << id.rawId();
416  }
417  return res;
418 }
419 
420 // In the future, this will be used to calibrate the TT energy. There is a dependance on
421 // eta at lower energies that can be corrected for here after more validation.
422 float EcalRecHitWorkerRecover::recCheckCalib(float eTT, int ieta){
423 
424  return eTT;
425 
426 }
427 
428 // return false is the channel has status in the list of statusestoexclude
429 // true otherwise (channel ok)
430 // Careful: this function works on raw (encoded) channel statuses
432  const std::vector<int>& statusestoexclude){
433 
434 
435  if (!chStatus_.isValid())
436  edm::LogError("ObjectNotFound") << "Channel Status not set";
437 
438 
439  EcalChannelStatus::const_iterator chIt = chStatus_->find( id );
440  uint16_t dbStatus = 0;
441  if ( chIt != chStatus_->end() ) {
442  dbStatus = chIt->getEncodedStatusCode();
443  } else {
444  edm::LogError("ObjectNotFound") << "No channel status found for xtal "
445  << id.rawId()
446  << "! something wrong with EcalChannelStatus in your DB? ";
447  }
448 
449  for (std::vector<int>::const_iterator status = statusestoexclude.begin();
450  status!= statusestoexclude.end(); ++status){
451 
452  if ( *status == dbStatus) return false;
453 
454  }
455 
456  return true;
457 }
458 
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
T getParameter(std::string const &) const
int ix() const
Definition: EEDetId.h:76
bool alreadyInserted(const DetId &id)
void setEventSetup(const edm::EventSetup &evtSetup)
Definition: EcalTPGScale.cc:19
bool run(const edm::Event &evt, const EcalUncalibratedRecHit &uncalibRH, EcalRecHitCollection &result) override
EcalDeadChannelRecoveryAlgos< EEDetId > eeDeadChannelCorrector
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:519
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
std::vector< EcalTriggerPrimitiveDigi >::const_iterator const_iterator
Geom::Theta< T > theta() const
std::vector< int > dbStatusToBeExcludedEE_
void push_back(T const &t)
std::vector< Variable::Flags > flags
Definition: MVATrainer.cc:135
void setFlag(int flag)
set the flags (from Flags or ESFlags)
Definition: EcalRecHit.h:185
int zside(DetId const &)
edm::ESHandle< CaloTopology > caloTopology_
double getTPGInGeV(const EcalTriggerPrimitiveDigi &tpDigi)
Definition: EcalTPGScale.cc:24
float recCheckCalib(float energy, int ieta)
void setCaloTopology(const CaloTopology *topology)
Definition: Electron.h:6
EcalTrigTowerDetId towerOf(const DetId &id) const
Get the tower id for this det id (or null if not known)
void insertRecHit(const EcalRecHit &hit, EcalRecHitCollection &collection)
uint32_t rawId() const
get the raw id
Definition: DetId.h:44
std::unique_ptr< EcalRecHitSimpleAlgo > rechitMaker_
EcalRecHit correct(const DetIdT id, const EcalRecHitCollection &hit_collection, std::string algo, double Sum8Cut, bool *AccFlag)
int ix() const
Definition: EcalScDetId.h:71
edm::ESHandle< EcalTrigTowerConstituentsMap > ttMap_
int zside() const
Definition: EEDetId.h:70
GlobalPoint getPosition(const DetId &id) const
Get the position of a given detector id.
Definition: CaloGeometry.cc:69
float energy() const
Definition: EcalRecHit.h:68
int iy() const
Definition: EEDetId.h:82
edm::ESHandle< CaloSubdetectorGeometry > pEBGeom_
float estimateEnergy(int ieta, EcalRecHitCollection *hits, const std::set< DetId > &sId, const std::vector< DetId > &vId)
int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:38
std::vector< DetId > constituentsOf(const EcalTrigTowerDetId &id) const
Get the constituent detids for this tower id.
int iy() const
Definition: EcalScDetId.h:77
const CaloSubdetectorGeometry * ebGeom_
std::vector< EcalRecHit >::iterator iterator
const_iterator end() const
Definition: DetId.h:18
void set(const edm::EventSetup &es) override
DetId id() const
get the id
Definition: EcalRecHit.h:77
T const * product() const
Definition: Handle.h:81
virtual std::shared_ptr< const CaloCellGeometry > getGeometry(const DetId &id) const
Get the cell geometry of a given detector id. Should return false if not found.
static bool validDetId(int crystal_ix, int crystal_iy, int iz)
Definition: EEDetId.h:248
edm::EDGetTokenT< EcalTrigPrimDigiCollection > tpDigiToken_
const T & get() const
Definition: EventSetup.h:59
std::vector< Item >::const_iterator const_iterator
std::set< DetId > recoveredDetIds_EE_
int zside() const
Definition: EcalScDetId.h:65
T eta() const
Definition: PV3DBase.h:76
iterator find(key_type k)
EcalRecHitWorkerRecover(const edm::ParameterSet &, edm::ConsumesCollector &c)
edm::ESHandle< CaloGeometry > caloGeometry_
#define DEFINE_EDM_PLUGIN(factory, type, name)
std::vector< int > dbStatusToBeExcludedEB_
EcalDeadChannelRecoveryAlgos< EBDetId > ebDeadChannelCorrector
edm::ESHandle< EcalChannelStatus > chStatus_
T const * product() const
Definition: ESHandle.h:86
edm::ESHandle< EcalLaserDbService > laser
const EcalElectronicsMapping * ecalMapping_
edm::ESHandle< EcalElectronicsMapping > pEcalMapping_
bool checkChannelStatus(const DetId &id, const std::vector< int > &statusestoexclude)
std::set< DetId > recoveredDetIds_EB_