00001 #include "SimCalorimetry/EcalSelectiveReadoutAlgos/interface/EcalSelectiveReadoutSuppressor.h"
00002 #include "SimCalorimetry/EcalSelectiveReadoutAlgos/src/EcalSelectiveReadout.h"
00003 #include "DataFormats/EcalDigi/interface/EEDataFrame.h"
00004 #include "DataFormats/EcalDigi/interface/EBDataFrame.h"
00005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00006
00007 #include "FWCore/Framework/interface/ESHandle.h"
00008
00009
00010 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00011 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00012 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00013 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00014 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00015
00016 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00017
00018
00019 #include "FWCore/Utilities/interface/Exception.h"
00020
00021 #include <limits>
00022 #include <cmath>
00023 #include <iostream>
00024
00025 using namespace boost;
00026 using namespace std;
00027
00028 const int EcalSelectiveReadoutSuppressor::nFIRTaps = 6;
00029
00030 EcalSelectiveReadoutSuppressor::EcalSelectiveReadoutSuppressor(const edm::ParameterSet & params, const EcalSRSettings* settings):
00031 ttThresOnCompressedEt_(false),
00032 ievt_(0)
00033 {
00034
00035 firstFIRSample = settings->ecalDccZs1stSample_[0];
00036 weights = settings->dccNormalizedWeights_[0];
00037 symetricZS = settings->symetricZS_[0];
00038 actions_ = settings->actions_;
00039
00040
00041 int defTtf = params.getParameter<int>("defaultTtf");
00042 if(defTtf < 0 || defTtf > 7){
00043 throw cms::Exception("InvalidParameter") << "Value of EcalSelectiveReadoutProducer module parameter defaultTtf, "
00044 << defaultTtf_ << ", is out of the valid range 0..7\n";
00045 } else{
00046 defaultTtf_ = (EcalSelectiveReadout::ttFlag_t) defTtf;
00047 }
00048
00049
00050
00051 if(actions_.size()==4){
00052 for(int i = 0; i < 4; ++i){
00053 actions_.push_back(actions_[i] | 0x4);
00054 }
00055 }
00056
00057
00058 bool actionValid = actions_.size()==8;
00059 for(size_t i = 0; i < actions_.size(); ++i){
00060 if(actions_[i] < 0 || actions_[i] > 7) actionValid = false;
00061 }
00062
00063 if(!actionValid){
00064 throw cms::Exception("InvalidParameter") << "EcalSelectiveReadoutProducer module parameter 'actions' is "
00065 "not valid. It must be a vector of 8 integer values comprised between 0 and 7\n";
00066 }
00067
00068 double adcToGeV = settings->ebDccAdcToGeV_;
00069 thrUnit[BARREL] = adcToGeV/4.;
00070
00071 adcToGeV = settings->eeDccAdcToGeV_;
00072 thrUnit[ENDCAP] = adcToGeV/4.;
00073 ecalSelectiveReadout
00074 = auto_ptr<EcalSelectiveReadout>(new EcalSelectiveReadout(
00075 settings->deltaEta_[0],
00076 settings->deltaPhi_[0]));
00077 const int eb = 0;
00078 const int ee = 1;
00079 initCellThresholds(settings->srpLowInterestChannelZS_[eb],
00080 settings->srpLowInterestChannelZS_[ee],
00081 settings->srpHighInterestChannelZS_[eb],
00082 settings->srpHighInterestChannelZS_[ee]
00083 );
00084 trigPrimBypass_ = params.getParameter<bool>("trigPrimBypass");
00085 trigPrimBypassMode_ = params.getParameter<int>("trigPrimBypassMode");
00086 trigPrimBypassWithPeakFinder_
00087 = params.getParameter<bool>("trigPrimBypassWithPeakFinder");
00088 trigPrimBypassLTH_ = params.getParameter<double>("trigPrimBypassLTH");
00089 trigPrimBypassHTH_ = params.getParameter<double>("trigPrimBypassHTH");
00090 if(trigPrimBypass_){
00091 edm::LogWarning("Digitization") << "Beware a simplified trigger primitive "
00092 "computation is used for the ECAL selective readout";
00093 if(trigPrimBypassMode_ !=0 && trigPrimBypassMode_ !=1){
00094 throw cms::Exception("InvalidParameter")
00095 << "Invalid value for EcalSelectiveReadoutProducer parameter 'trigPrimBypassMode_'."
00096 " Valid values are 0 and 1.\n";
00097 }
00098 ttThresOnCompressedEt_ = (trigPrimBypassMode_==1);
00099 }
00100 }
00101
00102
00103 void EcalSelectiveReadoutSuppressor::setTriggerMap(const EcalTrigTowerConstituentsMap * map){
00104 theTriggerMap = map;
00105 ecalSelectiveReadout->setTriggerMap(map);
00106 }
00107
00108 void EcalSelectiveReadoutSuppressor::setElecMap(const EcalElectronicsMapping * map){
00109 ecalSelectiveReadout->setElecMap(map);
00110 }
00111
00112
00113 void EcalSelectiveReadoutSuppressor::setGeometry(const CaloGeometry * caloGeometry)
00114 {
00115 #ifndef ECALSELECTIVEREADOUT_NOGEOM
00116 ecalSelectiveReadout->setGeometry(caloGeometry);
00117 #endif
00118 }
00119
00120
00121 void EcalSelectiveReadoutSuppressor::initCellThresholds(double barrelLowInterest,
00122 double endcapLowInterest,
00123 double barrelHighInterest,
00124 double endcapHighInterest){
00125
00126
00127 int lowInterestThr[2];
00128
00129 int highInterestThr[2];
00130
00131
00132 lowInterestThr[BARREL] = internalThreshold(barrelLowInterest, BARREL);
00133
00134
00135
00136 highInterestThr[BARREL] = internalThreshold(barrelHighInterest, BARREL);
00137
00138
00139
00140 lowInterestThr[ENDCAP] = internalThreshold(endcapLowInterest, ENDCAP);
00141
00142
00143
00144 highInterestThr[ENDCAP] = internalThreshold(endcapHighInterest, ENDCAP);
00145
00146
00147
00148 const int FORCED_MASK = EcalSelectiveReadout::FORCED_MASK;
00149
00150 for(int iSubDet = 0; iSubDet<2; ++iSubDet){
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 for(size_t i = 0; i < 8; ++i){
00171 srFlags[iSubDet][i] = actions_[i];
00172 if((actions_[i] & ~FORCED_MASK) == 0) zsThreshold[iSubDet][i] = numeric_limits<int>::max();
00173 else if((actions_[i] & ~FORCED_MASK) == 1) zsThreshold[iSubDet][i] = lowInterestThr[iSubDet];
00174 else if((actions_[i] & ~FORCED_MASK) == 2) zsThreshold[iSubDet][i] = highInterestThr[iSubDet];
00175 else zsThreshold[iSubDet][i] = numeric_limits<int>::min();
00176 }
00177
00178
00179
00180
00181 }
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 int EcalSelectiveReadoutSuppressor::internalThreshold(double thresholdInGeV,
00195 int iSubDet) const{
00196 double thr_ = thresholdInGeV / thrUnit[iSubDet];
00197
00198
00199
00200
00201
00202 int thr;
00203 if(thr_>=0x7FF+.5){
00204 thr = numeric_limits<int>::max();
00205 } else if(thr_<=-0x7FF-.5){
00206 thr = numeric_limits<int>::min();
00207 } else{
00208 thr = lround(thr_);
00209 }
00210 return thr;
00211 }
00212
00213
00214
00215 bool EcalSelectiveReadoutSuppressor::accept(edm::DataFrame const & frame,
00216 int thr){
00217
00218 const vector<int>& w = getFIRWeigths();
00219
00220
00221 int acc = 0;
00222 bool gain12saturated = false;
00223 const int gain12 = 0x01;
00224 const int lastFIRSample = firstFIRSample + nFIRTaps - 1;
00225
00226 int iWeight = 0;
00227 for(int iSample=firstFIRSample-1;
00228 iSample<lastFIRSample; ++iSample, ++iWeight){
00229 if(iSample>=0 && iSample < (int)frame.size()){
00230 EcalMGPASample sample(frame[iSample]);
00231 if(sample.gainId()!=gain12) gain12saturated = true;
00232
00233
00234 acc+=sample.adc()*w[iWeight];
00235 } else{
00236 edm::LogWarning("DccFir") << __FILE__ << ":" << __LINE__ <<
00237 ": Not enough samples in data frame or 'ecalDccZs1stSample' module "
00238 "parameter is not valid...";
00239 }
00240 }
00241
00242 if(symetricZS){
00243 if(acc<0) acc = -acc;
00244 }
00245
00246
00247
00248
00249
00250
00251 acc = ((acc + (1<<30)) >>8) - (1 <<(30-8));
00252
00253
00254
00255
00256
00257 const bool result = (acc >= thr) || gain12saturated;
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 return result;
00268 }
00269
00270 void EcalSelectiveReadoutSuppressor::run(const edm::EventSetup& eventSetup,
00271 const EcalTrigPrimDigiCollection & trigPrims,
00272 EBDigiCollection & barrelDigis,
00273 EEDigiCollection & endcapDigis){
00274 EBDigiCollection selectedBarrelDigis;
00275 EEDigiCollection selectedEndcapDigis;
00276
00277 run(eventSetup, trigPrims, barrelDigis, endcapDigis,
00278 &selectedBarrelDigis, &selectedEndcapDigis, 0, 0);
00279
00280
00281 barrelDigis.swap(selectedBarrelDigis);
00282 endcapDigis.swap(selectedEndcapDigis);
00283 }
00284
00285
00286 void
00287 EcalSelectiveReadoutSuppressor::run(const edm::EventSetup& eventSetup,
00288 const EcalTrigPrimDigiCollection & trigPrims,
00289 const EBDigiCollection & barrelDigis,
00290 const EEDigiCollection & endcapDigis,
00291 EBDigiCollection* selectedBarrelDigis,
00292 EEDigiCollection* selectedEndcapDigis,
00293 EBSrFlagCollection* ebSrFlags,
00294 EESrFlagCollection* eeSrFlags){
00295 ++ievt_;
00296 if(!trigPrimBypass_ || ttThresOnCompressedEt_){
00297 setTtFlags(trigPrims);
00298 } else{
00299 setTtFlags(eventSetup, barrelDigis, endcapDigis);
00300 }
00301
00302 ecalSelectiveReadout->runSelectiveReadout0(ttFlags);
00303
00304 if(selectedBarrelDigis){
00305 selectedBarrelDigis->reserve(barrelDigis.size()/20);
00306
00307
00308 for(EBDigiCollection::const_iterator digiItr = barrelDigis.begin();
00309 digiItr != barrelDigis.end(); ++digiItr){
00310 int interestLevel
00311 = ecalSelectiveReadout->getCrystalInterest(EBDigiCollection::DetId(digiItr->id())) && ~EcalSelectiveReadout::FORCED_MASK;
00312 if(accept(*digiItr, zsThreshold[BARREL][interestLevel])){
00313 selectedBarrelDigis->push_back(digiItr->id(), digiItr->begin());
00314 }
00315 }
00316 }
00317
00318
00319 if(selectedEndcapDigis){
00320 selectedEndcapDigis->reserve(endcapDigis.size()/20);
00321 for(EEDigiCollection::const_iterator digiItr = endcapDigis.begin();
00322 digiItr != endcapDigis.end(); ++digiItr){
00323 int interestLevel
00324 = ecalSelectiveReadout->getCrystalInterest(EEDigiCollection::DetId(digiItr->id()))
00325 & ~EcalSelectiveReadout::FORCED_MASK;
00326 if(accept(*digiItr, zsThreshold[ENDCAP][interestLevel])){
00327 selectedEndcapDigis->push_back(digiItr->id(), digiItr->begin());
00328 }
00329 }
00330 }
00331
00332 if(ievt_ <= 10){
00333 if(selectedEndcapDigis) LogDebug("EcalSelectiveReadout")
00334
00335 << "Number of EB digis passing the SR: "
00336 << selectedBarrelDigis->size()
00337 << " / " << barrelDigis.size() << "\n";
00338 if(selectedEndcapDigis) LogDebug("EcalSelectiveReadout")
00339
00340 << "\nNumber of EE digis passing the SR: "
00341 << selectedEndcapDigis->size()
00342 << " / " << endcapDigis.size() << "\n";
00343 }
00344
00345 if(ebSrFlags) ebSrFlags->reserve(34*72);
00346 if(eeSrFlags) eeSrFlags->reserve(624);
00347
00348 for(int iZ = -1; iZ <=1; iZ+=2){
00349
00350 for(unsigned iEta = 1; iEta <= nBarrelTriggerTowersInEta/2; ++iEta){
00351 for(unsigned iPhi = 1; iPhi <= nTriggerTowersInPhi; ++iPhi){
00352 const EcalTrigTowerDetId id(iZ, EcalBarrel, iEta, iPhi);
00353 EcalSelectiveReadout::towerInterest_t interest
00354 = ecalSelectiveReadout->getTowerInterest(id);
00355 if(interest<0){
00356 throw cms::Exception("EcalSelectiveReadout")
00357 << __FILE__ << ":" << __LINE__ << ": " << "unknown SR flag. for "
00358 << " TT " << id << ". Most probably a bug.";
00359 }
00360 int flag;
00361
00362
00363
00364 flag = srFlags[BARREL][interest];
00365
00366 if(ebSrFlags) ebSrFlags->push_back(EBSrFlag(id, flag));
00367 }
00368 }
00369
00370
00371 EcalScDetId id;
00372 for(int iX = 1; iX <= 20; ++iX){
00373 for(int iY = 1; iY <= 20; ++iY){
00374
00375 if (EcalScDetId::validDetId(iX, iY, iZ))
00376 id = EcalScDetId(iX, iY, iZ);
00377 else
00378 continue;
00379
00380 EcalSelectiveReadout::towerInterest_t interest
00381 = ecalSelectiveReadout->getSuperCrystalInterest(id);
00382
00383 if(interest>=0){
00384 int flag;
00385
00386
00387
00388 flag = srFlags[ENDCAP][interest];
00389
00390 if(eeSrFlags) eeSrFlags->push_back(EESrFlag(id, flag));
00391 } else if(iX < 9 || iX > 12 || iY < 9 || iY >12){
00392 edm::LogError("EcalSelectiveReadout") << __FILE__ << ":" << __LINE__ << ": "
00393 << "negative interest in EE for SC "
00394 << id << "\n";
00395 }
00396 }
00397 }
00398 }
00399 }
00400
00401
00402 void EcalSelectiveReadoutSuppressor::setTtFlags(const EcalTrigPrimDigiCollection & trigPrims){
00403 for(size_t iEta0 = 0; iEta0 < nTriggerTowersInEta; ++iEta0){
00404 for(size_t iPhi0 = 0; iPhi0 < nTriggerTowersInPhi; ++iPhi0){
00405 ttFlags[iEta0][iPhi0] = defaultTtf_;
00406 }
00407 }
00408 for(EcalTrigPrimDigiCollection::const_iterator trigPrim = trigPrims.begin();
00409 trigPrim != trigPrims.end(); ++trigPrim){
00410 int iEta = trigPrim->id().ieta();
00411 unsigned int iEta0;
00412 if(iEta<0){
00413 iEta0 = iEta + nTriggerTowersInEta/2;
00414 } else{
00415 iEta0 = iEta + nTriggerTowersInEta/2 - 1;
00416 }
00417
00418 unsigned int iPhi0 = trigPrim->id().iphi() - 1;
00419
00420 if(!ttThresOnCompressedEt_){
00421 ttFlags[iEta0][iPhi0] =
00422 (EcalSelectiveReadout::ttFlag_t) trigPrim->ttFlag();
00423 } else{
00424 int compressedEt = trigPrim->compressedEt();
00425 if(compressedEt < trigPrimBypassLTH_){
00426 ttFlags[iEta0][iPhi0] = EcalSelectiveReadout::TTF_LOW_INTEREST;
00427 } else if(compressedEt < trigPrimBypassHTH_){
00428 ttFlags[iEta0][iPhi0] = EcalSelectiveReadout::TTF_MID_INTEREST;
00429 } else{
00430 ttFlags[iEta0][iPhi0] = EcalSelectiveReadout::TTF_HIGH_INTEREST;
00431 }
00432 }
00433 }
00434 }
00435
00436
00437 vector<int> EcalSelectiveReadoutSuppressor::getFIRWeigths() {
00438 if(firWeights.size()==0){
00439 firWeights = vector<int>(nFIRTaps, 0);
00440 const static int maxWeight = 0xEFF;
00441 for(unsigned i=0; i < min((size_t)nFIRTaps,weights.size()); ++i){
00442 firWeights[i] = lround(weights[i] * (1<<10));
00443 if(abs(firWeights[i])>maxWeight){
00444 firWeights[i] = firWeights[i]<0?-maxWeight:maxWeight;
00445 }
00446 }
00447 }
00448 return firWeights;
00449 }
00450
00451 void
00452 EcalSelectiveReadoutSuppressor::setTtFlags(const edm::EventSetup& es,
00453 const EBDigiCollection& ebDigis,
00454 const EEDigiCollection& eeDigis){
00455 double trigPrim[nTriggerTowersInEta][nTriggerTowersInPhi];
00456
00457
00458
00459
00460 const CaloSubdetectorGeometry* eeGeometry = 0;
00461 const CaloSubdetectorGeometry* ebGeometry = 0;
00462
00463 edm::ESHandle<CaloGeometry> geoHandle;
00464 es.get<CaloGeometryRecord>().get(geoHandle);
00465 eeGeometry
00466 = (*geoHandle).getSubdetectorGeometry(DetId::Ecal, EcalEndcap);
00467 ebGeometry
00468 = (*geoHandle).getSubdetectorGeometry(DetId::Ecal, EcalBarrel);
00469
00470
00471
00472 bzero(trigPrim, sizeof(trigPrim));
00473
00474 for(EBDigiCollection::const_iterator it = ebDigis.begin();
00475 it != ebDigis.end(); ++it){
00476 EBDataFrame frame(*it);
00477 const EcalTrigTowerDetId& ttId = theTriggerMap->towerOf(frame.id());
00478
00479
00480
00481
00482 const int iTTEta0 = iTTEta2cIndex(ttId.ieta());
00483 const int iTTPhi0 = iTTPhi2cIndex(ttId.iphi());
00484 double theta = ebGeometry->getGeometry(frame.id())->getPosition().theta();
00485 double e = frame2Energy(frame);
00486 if(!trigPrimBypassWithPeakFinder_
00487 || ((frame2Energy(frame,-1) < e) && (frame2Energy(frame, 1) < e))){
00488 trigPrim[iTTEta0][iTTPhi0] += e*sin(theta);
00489 }
00490 }
00491
00492 for(EEDigiCollection::const_iterator it = eeDigis.begin();
00493 it != eeDigis.end(); ++it){
00494 EEDataFrame frame(*it);
00495 const EcalTrigTowerDetId& ttId = theTriggerMap->towerOf(frame.id());
00496 const int iTTEta0 = iTTEta2cIndex(ttId.ieta());
00497 const int iTTPhi0 = iTTPhi2cIndex(ttId.iphi());
00498
00499
00500
00501
00502 double theta = eeGeometry->getGeometry(frame.id())->getPosition().theta();
00503 double e = frame2Energy(frame);
00504 if(!trigPrimBypassWithPeakFinder_
00505 || ((frame2Energy(frame,-1) < e) && (frame2Energy(frame, 1) < e))){
00506 trigPrim[iTTEta0][iTTPhi0] += e*sin(theta);
00507 }
00508 }
00509
00510
00511 int innerTTEtas[] = {0, 1, 54, 55};
00512 for(unsigned iRing = 0; iRing < sizeof(innerTTEtas)/sizeof(innerTTEtas[0]);
00513 ++iRing){
00514 int iTTEta0 = innerTTEtas[iRing];
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530 for(unsigned iTTPhi0 = 0; iTTPhi0 < nTriggerTowersInPhi-1; iTTPhi0 += 2){
00531 double et = .5*(trigPrim[iTTEta0][iTTPhi0]
00532 +trigPrim[iTTEta0][iTTPhi0+1]);
00533
00534
00535
00536 trigPrim[iTTEta0][iTTPhi0] = et;
00537 trigPrim[iTTEta0][iTTPhi0+1] = et;
00538 }
00539 }
00540
00541 for(unsigned iTTEta0 = 0; iTTEta0 < nTriggerTowersInEta; ++iTTEta0){
00542 for(unsigned iTTPhi0 = 0; iTTPhi0 < nTriggerTowersInPhi; ++iTTPhi0){
00543 if(trigPrim[iTTEta0][iTTPhi0] > trigPrimBypassHTH_){
00544 ttFlags[iTTEta0][iTTPhi0] = EcalSelectiveReadout::TTF_HIGH_INTEREST;
00545 } else if(trigPrim[iTTEta0][iTTPhi0] > trigPrimBypassLTH_){
00546 ttFlags[iTTEta0][iTTPhi0] = EcalSelectiveReadout::TTF_MID_INTEREST;
00547 } else{
00548 ttFlags[iTTEta0][iTTPhi0] = EcalSelectiveReadout::TTF_LOW_INTEREST;
00549 }
00550
00551
00552
00553
00554 }
00555 }
00556 }
00557
00558 template<class T>
00559 double EcalSelectiveReadoutSuppressor::frame2Energy(const T& frame,
00560 int offset) const{
00561
00562
00563 double weights[] = {0., -1/3., -1/3., -1/3., 0., 1.};
00564
00565 double adc2GeV = 0.;
00566 if(typeid(frame) == typeid(EBDataFrame)){
00567 adc2GeV = 0.035;
00568 } else if(typeid(frame) == typeid(EEDataFrame)){
00569 adc2GeV = 0.060;
00570 } else{
00571
00572 cerr << "Severe error. "
00573 << __FILE__ << ":" << __LINE__ << ": "
00574 << "this is a bug. Please report it.\n";
00575 }
00576
00577 double acc = 0;
00578
00579 const int n = min<int>(frame.size(), sizeof(weights)/sizeof(weights[0]));
00580
00581 double gainInv[] = {12., 1., 6., 12.};
00582
00583
00584
00585 for(int i=offset; i < n; ++i){
00586 int iframe = i + offset;
00587 if(iframe>=0 && iframe<frame.size()){
00588 acc += weights[i]*frame[iframe].adc()
00589 *gainInv[frame[iframe].gainId()]*adc2GeV;
00590
00591
00592
00593 }
00594 }
00595
00596 return acc;
00597 }
00598
00599 void EcalSelectiveReadoutSuppressor::printTTFlags(ostream& os, int iEvent,
00600 bool withHeader) const{
00601 const char tccFlagMarker[] = { '?', '.', 'S', '?', 'C', 'E', 'E', 'E', 'E'};
00602 const int nEta = EcalSelectiveReadout::nTriggerTowersInEta;
00603 const int nPhi = EcalSelectiveReadout::nTriggerTowersInPhi;
00604
00605 if(withHeader){
00606 os << "# TCC flag map\n#\n"
00607 "# +-->Phi " << tccFlagMarker[1+0] << ": 000 (low interest)\n"
00608 "# | " << tccFlagMarker[1+1] << ": 001 (mid interest)\n"
00609 "# | " << tccFlagMarker[1+2] << ": 010 (not valid)\n"
00610 "# V Eta " << tccFlagMarker[1+3] << ": 011 (high interest)\n"
00611 "# " << tccFlagMarker[1+4] << ": 1xx forced readout (Hw error)\n";
00612 }
00613
00614 if(iEvent>=0){
00615 os << "#\n#Event " << iEvent << "\n";
00616 }
00617
00618 for(int iEta=0; iEta<nEta; ++iEta){
00619 for(int iPhi=0; iPhi<nPhi; ++iPhi){
00620 os << tccFlagMarker[ttFlags[iEta][iPhi]+1];
00621 }
00622 os << "\n";
00623 }
00624 }