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