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):
00032 firstFIRSample(params.getParameter<int>("ecalDccZs1stSample")),
00033 weights(params.getParameter<vector<double> >("dccNormalizedWeights")),
00034 symetricZS(params.getParameter<bool>("symetricZS"))
00035 {
00036
00037 double adcToGeV = params.getParameter<double>("ebDccAdcToGeV");
00038 thrUnit[BARREL] = adcToGeV/4.;
00039
00040 adcToGeV = params.getParameter<double>("eeDccAdcToGeV");
00041 thrUnit[ENDCAP] = adcToGeV/4.;
00042 ecalSelectiveReadout
00043 = auto_ptr<EcalSelectiveReadout>(new EcalSelectiveReadout
00044 (params.getParameter<int>("deltaEta"),
00045 params.getParameter<int>("deltaPhi")));
00046 initCellThresholds(params.getParameter<double>("srpBarrelLowInterestChannelZS"),
00047 params.getParameter<double>("srpEndcapLowInterestChannelZS"),
00048 params.getParameter<double>("srpBarrelHighInterestChannelZS"),
00049 params.getParameter<double>("srpEndcapHighInterestChannelZS")
00050 );
00051 trigPrimBypass_ = params.getParameter<bool>("trigPrimBypass");
00052 trigPrimBypassWithPeakFinder_
00053 = params.getParameter<bool>("trigPrimBypassWithPeakFinder");
00054 trigPrimBypassLTH_ = params.getParameter<double>("trigPrimBypassLTH");
00055 trigPrimBypassHTH_ = params.getParameter<double>("trigPrimBypassHTH");
00056 if(trigPrimBypass_){
00057 edm::LogWarning("Digitization") << "Beware a simplified trigger primitive "
00058 "computation is used for the ECAL selective readout";
00059 }
00060 }
00061
00062
00063 void EcalSelectiveReadoutSuppressor::setTriggerMap(const EcalTrigTowerConstituentsMap * map){
00064 theTriggerMap = map;
00065 ecalSelectiveReadout->setTriggerMap(map);
00066 }
00067
00068
00069 void EcalSelectiveReadoutSuppressor::setGeometry(const CaloGeometry * caloGeometry)
00070 {
00071 #ifndef ECALSELECTIVEREADOUT_NOGEOM
00072 ecalSelectiveReadout->setGeometry(caloGeometry);
00073 #endif
00074 }
00075
00076
00077 void EcalSelectiveReadoutSuppressor::initCellThresholds(double barrelLowInterest,
00078 double endcapLowInterest,
00079 double barrelHighInterest,
00080 double endcapHighInterest){
00081
00082
00083 int lowInterestThr[2];
00084 int lowInterestSrFlag[2];
00085 int highInterestThr[2];
00086 int highInterestSrFlag[2];
00087
00088 lowInterestThr[BARREL] = internalThreshold(barrelLowInterest, BARREL);
00089 lowInterestSrFlag[BARREL] = thr2Srf(lowInterestThr[BARREL],
00090 EcalSrFlag::SRF_ZS1);
00091
00092 highInterestThr[BARREL] = internalThreshold(barrelHighInterest, BARREL);
00093 highInterestSrFlag[BARREL] = thr2Srf(highInterestThr[BARREL],
00094 EcalSrFlag::SRF_ZS2);
00095
00096 lowInterestThr[ENDCAP] = internalThreshold(endcapLowInterest, ENDCAP);
00097 lowInterestSrFlag[ENDCAP] = thr2Srf(lowInterestThr[ENDCAP],
00098 EcalSrFlag::SRF_ZS2);
00099
00100 highInterestThr[ENDCAP] = internalThreshold(endcapHighInterest, ENDCAP);
00101 highInterestSrFlag[ENDCAP] = thr2Srf(highInterestThr[ENDCAP],
00102 EcalSrFlag::SRF_ZS2);
00103
00104 for(int iSubDet = 0; iSubDet<2; ++iSubDet){
00105
00106 zsThreshold[iSubDet][0] = lowInterestThr[iSubDet];
00107 srFlags[iSubDet][0] = lowInterestSrFlag[iSubDet];
00108
00109
00110 zsThreshold[iSubDet][1] = highInterestThr[iSubDet];
00111 srFlags[iSubDet][1] = highInterestSrFlag[iSubDet];
00112
00113
00114 zsThreshold[iSubDet][2] = highInterestThr[iSubDet];
00115 srFlags[iSubDet][2] = highInterestSrFlag[iSubDet];
00116
00117
00118 zsThreshold[iSubDet][3] = highInterestThr[iSubDet];
00119 srFlags[iSubDet][3] = highInterestSrFlag[iSubDet];
00120 }
00121 }
00122
00123 int EcalSelectiveReadoutSuppressor::thr2Srf(int thr, int zsFlag) const{
00124 if(thr==numeric_limits<int>::max()){
00125 return EcalSrFlag::SRF_SUPPRESS;
00126 }
00127 if(thr==numeric_limits<int>::min()){
00128 return EcalSrFlag::SRF_FULL;
00129 }
00130 return zsFlag;
00131 }
00132
00133 int EcalSelectiveReadoutSuppressor::internalThreshold(double thresholdInGeV,
00134 int iSubDet) const{
00135 double thr_ = thresholdInGeV / thrUnit[iSubDet];
00136
00137
00138
00139
00140
00141 int thr;
00142 if(thr_>=0x7FF+.5){
00143 thr = numeric_limits<int>::max();
00144 } else if(thr_<=-0x7FF-.5){
00145 thr = numeric_limits<int>::min();
00146 } else{
00147 thr = lround(thr_);
00148 }
00149 return thr;
00150 }
00151
00152
00153
00154 bool EcalSelectiveReadoutSuppressor::accept(edm::DataFrame const & frame,
00155 int thr){
00156
00157 const vector<int>& w = getFIRWeigths();
00158
00159
00160 int acc = 0;
00161 bool gain12saturated = false;
00162 const int gain12 = 0x01;
00163 const int lastFIRSample = firstFIRSample + nFIRTaps - 1;
00164
00165 int iWeight = 0;
00166 for(int iSample=firstFIRSample-1;
00167 iSample<lastFIRSample; ++iSample, ++iWeight){
00168 if(iSample>=0 && iSample < (int)frame.size()){
00169 EcalMGPASample sample(frame[iSample]);
00170 if(sample.gainId()!=gain12) gain12saturated = true;
00171
00172
00173 acc+=sample.adc()*w[iWeight];
00174 } else{
00175 edm::LogWarning("DccFir") << __FILE__ << ":" << __LINE__ <<
00176 ": Not enough samples in data frame or 'ecalDccZs1stSample' module "
00177 "parameter is not valid...";
00178 }
00179 }
00180
00181 if(symetricZS){
00182 if(acc<0) acc = -acc;
00183 }
00184
00185
00186
00187
00188
00189
00190 acc = ((acc + (1<<30)) >>8) - (1 <<(30-8));
00191
00192
00193
00194
00195
00196 const bool result = (acc >= thr) || gain12saturated;
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 return result;
00207 }
00208
00209 void EcalSelectiveReadoutSuppressor::run(const edm::EventSetup& eventSetup,
00210 const EcalTrigPrimDigiCollection & trigPrims,
00211 EBDigiCollection & barrelDigis,
00212 EEDigiCollection & endcapDigis){
00213 EBDigiCollection selectedBarrelDigis;
00214 EEDigiCollection selectedEndcapDigis;
00215 EBSrFlagCollection ebSrFlags;
00216 EESrFlagCollection eeSrFlags;
00217
00218 run(eventSetup, trigPrims, barrelDigis, endcapDigis,
00219 selectedBarrelDigis, selectedEndcapDigis, ebSrFlags, eeSrFlags);
00220
00221
00222 barrelDigis.swap(selectedBarrelDigis);
00223 endcapDigis.swap(selectedEndcapDigis);
00224 }
00225
00226
00227 void
00228 EcalSelectiveReadoutSuppressor::run(const edm::EventSetup& eventSetup,
00229 const EcalTrigPrimDigiCollection & trigPrims,
00230 const EBDigiCollection & barrelDigis,
00231 const EEDigiCollection & endcapDigis,
00232 EBDigiCollection& selectedBarrelDigis,
00233 EEDigiCollection& selectedEndcapDigis,
00234 EBSrFlagCollection& ebSrFlags,
00235 EESrFlagCollection& eeSrFlags){
00236 if(!trigPrimBypass_){
00237 setTtFlags(trigPrims);
00238 } else{
00239 setTtFlags(eventSetup, barrelDigis, endcapDigis);
00240 }
00241
00242 ecalSelectiveReadout->runSelectiveReadout0(ttFlags);
00243
00244 selectedBarrelDigis.reserve(barrelDigis.size()/20);
00245 selectedEndcapDigis.reserve(endcapDigis.size()/20);
00246
00247
00248 for(EBDigiCollection::const_iterator digiItr = barrelDigis.begin();
00249 digiItr != barrelDigis.end(); ++digiItr){
00250 int interestLevel
00251 = ecalSelectiveReadout->getCrystalInterest(EBDigiCollection::DetId(digiItr->id()));
00252 if(accept(*digiItr, zsThreshold[BARREL][interestLevel])){
00253 selectedBarrelDigis.push_back(digiItr->id(), digiItr->begin());
00254 }
00255 }
00256
00257
00258 for(EEDigiCollection::const_iterator digiItr = endcapDigis.begin();
00259 digiItr != endcapDigis.end(); ++digiItr){
00260 int interestLevel = ecalSelectiveReadout->getCrystalInterest(EEDigiCollection::DetId(digiItr->id()));
00261 if(accept(*digiItr, zsThreshold[ENDCAP][interestLevel])){
00262 selectedEndcapDigis.push_back(digiItr->id(), digiItr->begin());
00263 }
00264 }
00265
00266 ebSrFlags.reserve(34*72);
00267 eeSrFlags.reserve(624);
00268
00269 for(int iZ = -1; iZ <=1; iZ+=2){
00270
00271 for(unsigned iEta = 1; iEta <= nBarrelTriggerTowersInEta/2; ++iEta){
00272 for(unsigned iPhi = 1; iPhi <= nTriggerTowersInPhi; ++iPhi){
00273 const EcalTrigTowerDetId id(iZ, EcalBarrel, iEta, iPhi);
00274 EcalSelectiveReadout::towerInterest_t interest
00275 = ecalSelectiveReadout->getTowerInterest(id);
00276 if(interest<0){
00277 throw cms::Exception("EcalSelectiveReadout")
00278 << __FILE__ << ":" << __LINE__ << ": " << "unknown SR flag. for "
00279 << " TT " << id << ". Most probably a bug.";
00280 }
00281 int flag;
00282 if(interest==EcalSelectiveReadout::FORCED_RO){
00283 flag = EcalSrFlag::SRF_FORCED_MASK | EcalSrFlag::SRF_FULL;
00284 } else{
00285 flag = srFlags[BARREL][interest];
00286 }
00287 ebSrFlags.push_back(EBSrFlag(id, flag));
00288 }
00289 }
00290
00291
00292 EcalScDetId id;
00293 for(int iX = 1; iX <= 20; ++iX){
00294 for(int iY = 1; iY <= 20; ++iY){
00295 if (EcalScDetId::validDetId(iX, iY, iZ))
00296 id = EcalScDetId(iX, iY, iZ);
00297 else
00298 continue;
00299
00300 EcalSelectiveReadout::towerInterest_t interest
00301 = ecalSelectiveReadout->getSuperCrystalInterest(id);
00302 if(interest>=0){
00303 int flag;
00304 if(interest==EcalSelectiveReadout::FORCED_RO){
00305 flag = EcalSrFlag::SRF_FORCED_MASK | EcalSrFlag::SRF_FULL;
00306 } else{
00307 flag = srFlags[BARREL][interest];
00308 }
00309 eeSrFlags.push_back(EESrFlag(id, flag));
00310 } else{
00311 cout << __FILE__ << ":" << __LINE__ << ": "
00312 << "negative interest in EE for SC "
00313 << id << "\n";
00314 }
00315 }
00316 }
00317 }
00318 }
00319
00320
00321 void EcalSelectiveReadoutSuppressor::setTtFlags(const EcalTrigPrimDigiCollection & trigPrims){
00322 for(size_t iEta0 = 0; iEta0 < nTriggerTowersInEta; ++iEta0){
00323 for(size_t iPhi0 = 0; iPhi0 < nTriggerTowersInPhi; ++iPhi0){
00324 ttFlags[iEta0][iPhi0] = EcalSelectiveReadout::TTF_FORCED_RO_OTHER1;
00325 }
00326 }
00327 for(EcalTrigPrimDigiCollection::const_iterator trigPrim = trigPrims.begin();
00328 trigPrim != trigPrims.end(); ++trigPrim){
00329 int iEta = trigPrim->id().ieta();
00330 unsigned int iEta0;
00331 if(iEta<0){
00332 iEta0 = iEta + nTriggerTowersInEta/2;
00333 } else{
00334 iEta0 = iEta + nTriggerTowersInEta/2 - 1;
00335 }
00336
00337 unsigned int iPhi0 = trigPrim->id().iphi() - 1;
00338 ttFlags[iEta0][iPhi0] =
00339 (EcalSelectiveReadout::ttFlag_t) trigPrim->ttFlag();
00340 }
00341 }
00342
00343
00344 vector<int> EcalSelectiveReadoutSuppressor::getFIRWeigths() {
00345 if(firWeights.size()==0){
00346 firWeights = vector<int>(nFIRTaps, 0);
00347 const static int maxWeight = 0xEFF;
00348 for(unsigned i=0; i < min((size_t)nFIRTaps,weights.size()); ++i){
00349 firWeights[i] = lround(weights[i] * (1<<10));
00350 if(abs(firWeights[i])>maxWeight){
00351 firWeights[i] = firWeights[i]<0?-maxWeight:maxWeight;
00352 }
00353 }
00354 }
00355 return firWeights;
00356 }
00357
00358 void
00359 EcalSelectiveReadoutSuppressor::setTtFlags(const edm::EventSetup& es,
00360 const EBDigiCollection& ebDigis,
00361 const EEDigiCollection& eeDigis){
00362 double trigPrim[nTriggerTowersInEta][nTriggerTowersInPhi];
00363
00364
00365
00366
00367 const CaloSubdetectorGeometry* eeGeometry = 0;
00368 const CaloSubdetectorGeometry* ebGeometry = 0;
00369
00370 edm::ESHandle<CaloGeometry> geoHandle;
00371 es.get<CaloGeometryRecord>().get(geoHandle);
00372 eeGeometry
00373 = (*geoHandle).getSubdetectorGeometry(DetId::Ecal, EcalEndcap);
00374 ebGeometry
00375 = (*geoHandle).getSubdetectorGeometry(DetId::Ecal, EcalBarrel);
00376
00377
00378
00379 bzero(trigPrim, sizeof(trigPrim));
00380
00381 for(EBDigiCollection::const_iterator it = ebDigis.begin();
00382 it != ebDigis.end(); ++it){
00383 EBDataFrame frame(*it);
00384 const EcalTrigTowerDetId& ttId = theTriggerMap->towerOf(frame.id());
00385
00386
00387
00388
00389 const int iTTEta0 = iTTEta2cIndex(ttId.ieta());
00390 const int iTTPhi0 = iTTPhi2cIndex(ttId.iphi());
00391 double theta = ebGeometry->getGeometry(frame.id())->getPosition().theta();
00392 double e = frame2Energy(frame);
00393 if(!trigPrimBypassWithPeakFinder_
00394 || ((frame2Energy(frame,-1) < e) && (frame2Energy(frame, 1) < e))){
00395 trigPrim[iTTEta0][iTTPhi0] += e*sin(theta);
00396 }
00397 }
00398
00399 for(EEDigiCollection::const_iterator it = eeDigis.begin();
00400 it != eeDigis.end(); ++it){
00401 EEDataFrame frame(*it);
00402 const EcalTrigTowerDetId& ttId = theTriggerMap->towerOf(frame.id());
00403 const int iTTEta0 = iTTEta2cIndex(ttId.ieta());
00404 const int iTTPhi0 = iTTPhi2cIndex(ttId.iphi());
00405
00406
00407
00408
00409 double theta = eeGeometry->getGeometry(frame.id())->getPosition().theta();
00410 double e = frame2Energy(frame);
00411 if(!trigPrimBypassWithPeakFinder_
00412 || ((frame2Energy(frame,-1) < e) && (frame2Energy(frame, 1) < e))){
00413 trigPrim[iTTEta0][iTTPhi0] += e*sin(theta);
00414 }
00415 }
00416
00417
00418 int innerTTEtas[] = {0, 1, 54, 55};
00419 for(unsigned iRing = 0; iRing < sizeof(innerTTEtas)/sizeof(innerTTEtas[0]);
00420 ++iRing){
00421 int iTTEta0 = innerTTEtas[iRing];
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 for(unsigned iTTPhi0 = 0; iTTPhi0 < nTriggerTowersInPhi-1; iTTPhi0 += 2){
00438 double et = .5*(trigPrim[iTTEta0][iTTPhi0]
00439 +trigPrim[iTTEta0][iTTPhi0+1]);
00440
00441
00442
00443 trigPrim[iTTEta0][iTTPhi0] = et;
00444 trigPrim[iTTEta0][iTTPhi0+1] = et;
00445 }
00446 }
00447
00448 for(unsigned iTTEta0 = 0; iTTEta0 < nTriggerTowersInEta; ++iTTEta0){
00449 for(unsigned iTTPhi0 = 0; iTTPhi0 < nTriggerTowersInPhi; ++iTTPhi0){
00450 if(trigPrim[iTTEta0][iTTPhi0] > trigPrimBypassHTH_){
00451 ttFlags[iTTEta0][iTTPhi0] = EcalSelectiveReadout::TTF_HIGH_INTEREST;
00452 } else if(trigPrim[iTTEta0][iTTPhi0] > trigPrimBypassLTH_){
00453 ttFlags[iTTEta0][iTTPhi0] = EcalSelectiveReadout::TTF_MID_INTEREST;
00454 } else{
00455 ttFlags[iTTEta0][iTTPhi0] = EcalSelectiveReadout::TTF_LOW_INTEREST;
00456 }
00457
00458
00459
00460
00461 }
00462 }
00463 }
00464
00465 template<class T>
00466 double EcalSelectiveReadoutSuppressor::frame2Energy(const T& frame,
00467 int offset) const{
00468
00469
00470 double weights[] = {0., -1/3., -1/3., -1/3., 0., 1.};
00471
00472 double adc2GeV = 0.;
00473 if(typeid(frame) == typeid(EBDataFrame)){
00474 adc2GeV = 0.035;
00475 } else if(typeid(frame) == typeid(EEDataFrame)){
00476 adc2GeV = 0.060;
00477 } else{
00478
00479 cerr << "Severe error. "
00480 << __FILE__ << ":" << __LINE__ << ": "
00481 << "this is a bug. Please report it.\n";
00482 }
00483
00484 double acc = 0;
00485
00486 const int n = min<int>(frame.size(), sizeof(weights)/sizeof(weights[0]));
00487
00488 double gainInv[] = {12., 1., 6., 12.};
00489
00490
00491
00492 for(int i=offset; i < n; ++i){
00493 int iframe = i + offset;
00494 if(iframe>=0 && iframe<frame.size()){
00495 acc += weights[i]*frame[iframe].adc()
00496 *gainInv[frame[iframe].gainId()]*adc2GeV;
00497
00498
00499
00500 }
00501 }
00502
00503 return acc;
00504 }
00505
00506 void EcalSelectiveReadoutSuppressor::printTTFlags(ostream& os, int iEvent,
00507 bool withHeader) const{
00508 const char tccFlagMarker[] = { '?', '.', 'S', '?', 'C', 'E', 'E', 'E', 'E'};
00509 const int nEta = EcalSelectiveReadout::nTriggerTowersInEta;
00510 const int nPhi = EcalSelectiveReadout::nTriggerTowersInPhi;
00511
00512 if(withHeader){
00513 os << "# TCC flag map\n#\n"
00514 "# +-->Phi " << tccFlagMarker[1+0] << ": 000 (low interest)\n"
00515 "# | " << tccFlagMarker[1+1] << ": 001 (mid interest)\n"
00516 "# | " << tccFlagMarker[1+2] << ": 010 (not valid)\n"
00517 "# V Eta " << tccFlagMarker[1+3] << ": 011 (high interest)\n"
00518 "# " << tccFlagMarker[1+4] << ": 1xx forced readout (Hw error)\n";
00519 }
00520
00521 if(iEvent>=0){
00522 os << "#\n#Event " << iEvent << "\n";
00523 }
00524
00525 for(int iEta=0; iEta<nEta; ++iEta){
00526 for(int iPhi=0; iPhi<nPhi; ++iPhi){
00527 os << tccFlagMarker[ttFlags[iEta][iPhi]+1];
00528 }
00529 os << "\n";
00530 }
00531 }
00532