CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/SimCalorimetry/EcalSelectiveReadoutAlgos/src/EcalSelectiveReadoutSuppressor.cc

Go to the documentation of this file.
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/Selector.h"
00008 #include "FWCore/Framework/interface/ESHandle.h"
00009 
00010 // Geometry
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 //exceptions:
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   //online configuration has only 4 actions flags, the 4 'forced' flags being the same with the force
00051   //bit set to 1. Extends the actions vector for case of online-type configuration:
00052   if(actions_.size()==4){
00053      for(int i = 0; i < 4; ++i){
00054         actions_.push_back(actions_[i] | 0x4);
00055      }
00056   }
00057 
00058 
00059   bool actionValid = actions_.size()==8;
00060   for(size_t i = 0; i < actions_.size(); ++i){
00061     if(actions_[i] < 0 || actions_[i] > 7) actionValid = false;
00062   }
00063 
00064   if(!actionValid){
00065     throw cms::Exception("InvalidParameter") << "EcalSelectiveReadoutProducer module parameter 'actions' is "
00066       "not valid. It must be a vector of 8 integer values comprised between 0 and 7\n";
00067   }
00068   
00069   double adcToGeV = settings->ebDccAdcToGeV_;
00070   thrUnit[BARREL] = adcToGeV/4.; //unit=1/4th ADC count
00071   
00072   adcToGeV = settings->eeDccAdcToGeV_;
00073   thrUnit[ENDCAP] = adcToGeV/4.; //unit=1/4th ADC count
00074   ecalSelectiveReadout
00075     = auto_ptr<EcalSelectiveReadout>(new EcalSelectiveReadout(
00076                                                               settings->deltaEta_[0],
00077                                                               settings->deltaPhi_[0]));
00078   const int eb = 0;
00079   const int ee = 1;
00080   initCellThresholds(settings->srpLowInterestChannelZS_[eb],
00081                      settings->srpLowInterestChannelZS_[ee],
00082                      settings->srpHighInterestChannelZS_[eb],
00083                      settings->srpHighInterestChannelZS_[ee]
00084                      );
00085   trigPrimBypass_ = params.getParameter<bool>("trigPrimBypass");
00086   trigPrimBypassMode_ = params.getParameter<int>("trigPrimBypassMode");
00087   trigPrimBypassWithPeakFinder_
00088     = params.getParameter<bool>("trigPrimBypassWithPeakFinder");
00089   trigPrimBypassLTH_ = params.getParameter<double>("trigPrimBypassLTH");
00090   trigPrimBypassHTH_ = params.getParameter<double>("trigPrimBypassHTH");
00091   if(trigPrimBypass_){
00092     edm::LogWarning("Digitization") << "Beware a simplified trigger primitive "
00093       "computation is used for the ECAL selective readout";
00094     if(trigPrimBypassMode_ !=0 && trigPrimBypassMode_ !=1){
00095       throw cms::Exception("InvalidParameter")
00096         << "Invalid value for EcalSelectiveReadoutProducer parameter 'trigPrimBypassMode_'."
00097         " Valid values are 0 and 1.\n";
00098     }
00099     ttThresOnCompressedEt_ = (trigPrimBypassMode_==1);
00100   }
00101 }
00102 
00103 
00104 void EcalSelectiveReadoutSuppressor::setTriggerMap(const EcalTrigTowerConstituentsMap * map){
00105   theTriggerMap = map;
00106   ecalSelectiveReadout->setTriggerMap(map);
00107 }
00108 
00109 void EcalSelectiveReadoutSuppressor::setElecMap(const EcalElectronicsMapping * map){
00110   ecalSelectiveReadout->setElecMap(map);
00111 }
00112 
00113 
00114 void EcalSelectiveReadoutSuppressor::setGeometry(const CaloGeometry * caloGeometry) 
00115 {
00116 #ifndef ECALSELECTIVEREADOUT_NOGEOM
00117    ecalSelectiveReadout->setGeometry(caloGeometry);
00118 #endif
00119 }
00120 
00121 
00122 void EcalSelectiveReadoutSuppressor::initCellThresholds(double barrelLowInterest,
00123                                                         double endcapLowInterest,
00124                                                         double barrelHighInterest,
00125                                                         double endcapHighInterest){
00126   //center, neighbour and single RUs are grouped into a single
00127   //'high interest' group
00128   int lowInterestThr[2]; //index for BARREL/ENDCAP
00129   //  int lowInterestSrFlag[2];
00130   int highInterestThr[2];
00131   // int highInterestSrFlag[2];
00132   
00133   lowInterestThr[BARREL] = internalThreshold(barrelLowInterest, BARREL);
00134   //  lowInterestSrFlag[BARREL] = thr2Srf(lowInterestThr[BARREL],
00135   //                                  EcalSrFlag::SRF_ZS1);
00136   
00137   highInterestThr[BARREL] = internalThreshold(barrelHighInterest, BARREL);
00138   //  highInterestSrFlag[BARREL] = thr2Srf(highInterestThr[BARREL],
00139   //                                   EcalSrFlag::SRF_ZS2);
00140   
00141   lowInterestThr[ENDCAP] = internalThreshold(endcapLowInterest, ENDCAP);
00142   //lowInterestSrFlag[ENDCAP] = thr2Srf(lowInterestThr[ENDCAP],
00143   //                          EcalSrFlag::SRF_ZS1);
00144 
00145   highInterestThr[ENDCAP] = internalThreshold(endcapHighInterest, ENDCAP); 
00146   //  highInterestSrFlag[ENDCAP] = thr2Srf(highInterestThr[ENDCAP],
00147   //                           EcalSrFlag::SRF_ZS2);
00148 
00149   const int FORCED_MASK = EcalSelectiveReadout::FORCED_MASK;
00150   
00151   for(int iSubDet = 0; iSubDet<2; ++iSubDet){
00152     //low interest
00153     //zsThreshold[iSubDet][0] = lowInterestThr[iSubDet];
00154     //srFlags[iSubDet][0] = lowInterestSrFlag[iSubDet];
00155     //srFlags[iSubDet][0 + FORCED_MASK] = FORCED_MASK | lowInterestSrFlag[iSubDet];
00156 
00157     //single->high interest
00158     //zsThreshold[iSubDet][1] = highInterestThr[iSubDet];
00159     //srFlags[iSubDet][1] = highInterestSrFlag[iSubDet];
00160     //srFlags[iSubDet][1 +  FORCED_MASK] = FORCED_MASK | highInterestSrFlag[iSubDet];
00161 
00162     //neighbour->high interest
00163     //zsThreshold[iSubDet][2] = highInterestThr[iSubDet];
00164     //srFlags[iSubDet][2] = highInterestSrFlag[iSubDet];
00165     //srFlags[iSubDet][2 + FORCED_MASK] = FORCED_MASK | highInterestSrFlag[iSubDet];
00166 
00167     //center->high interest
00168     //zsThreshold[iSubDet][3] = highInterestThr[iSubDet];
00169     //srFlags[iSubDet][3] = highInterestSrFlag[iSubDet];
00170     //srFlags[iSubDet][3 + FORCED_MASK] = FORCED_MASK | highInterestSrFlag[iSubDet];
00171     for(size_t i = 0; i < 8; ++i){
00172       srFlags[iSubDet][i] = actions_[i];
00173       if((actions_[i] & ~FORCED_MASK) == 0) zsThreshold[iSubDet][i] = numeric_limits<int>::max();
00174       else if((actions_[i] & ~FORCED_MASK) == 1) zsThreshold[iSubDet][i] = lowInterestThr[iSubDet];
00175       else if((actions_[i] & ~FORCED_MASK) == 2)  zsThreshold[iSubDet][i] = highInterestThr[iSubDet];
00176       else zsThreshold[iSubDet][i] = numeric_limits<int>::min();
00177     }
00178 
00179 //     for(size_t i = 0; i < 8; ++i){
00180 //       cout << "zsThreshold[" << iSubDet << "]["  << i << "] = " << zsThreshold[iSubDet][i] << endl;
00181 //     }
00182   }
00183 }
00184 
00185 // int EcalSelectiveReadoutSuppressor::thr2Srf(int thr, int zsFlag) const{
00186 //   if(thr==numeric_limits<int>::max()){
00187 //     return EcalSrFlag::SRF_SUPPRESS;
00188 //   }
00189 //   if(thr==numeric_limits<int>::min()){
00190 //     return EcalSrFlag::SRF_FULL;
00191 //   } 
00192 //   return zsFlag;
00193 // }
00194 
00195 int EcalSelectiveReadoutSuppressor::internalThreshold(double thresholdInGeV,
00196                                                       int iSubDet) const{
00197   double thr_ = thresholdInGeV / thrUnit[iSubDet];
00198   //treating over- and underflows, threshold is coded on 11+1 signed bits
00199   //an underflow threshold is considered here as if NoRO DCC switch is on
00200   //an overflow threshold is considered here as if ForcedRO DCC switch in on
00201   //Beware that conparison must be done on a double type, because conversion
00202   //cast to an int of a double higher than MAX_INT is undefined.
00203   int thr;
00204   if(thr_>=0x7FF+.5){
00205     thr = numeric_limits<int>::max();
00206   } else if(thr_<=-0x7FF-.5){
00207     thr = numeric_limits<int>::min();
00208   } else{
00209     thr = lround(thr_);
00210   }
00211   return thr;
00212 }
00213 
00214 //This implementation  assumes that int is coded on at least 28-bits,
00215 //which in pratice should be always true.
00216 bool EcalSelectiveReadoutSuppressor::accept(edm::DataFrame const & frame,
00217                                             int thr){
00218   //FIR filter weights:
00219   const vector<int>& w = getFIRWeigths();
00220   
00221   //accumulator used to compute weighted sum of samples
00222   int acc = 0;
00223   bool gain12saturated = false;
00224   const int gain12 = 0x01; 
00225   const int lastFIRSample = firstFIRSample + nFIRTaps - 1;
00226   //LogDebug("DccFir") << "DCC FIR operation: ";
00227   int iWeight = 0;
00228   for(int iSample=firstFIRSample-1;
00229       iSample<lastFIRSample; ++iSample, ++iWeight){
00230     if(iSample>=0 && iSample < (int)frame.size()){
00231       EcalMGPASample sample(frame[iSample]);
00232       if(sample.gainId()!=gain12) gain12saturated = true;
00233       //LogTrace("DccFir") << (iSample>=firstFIRSample?"+":"") << sample.adc()
00234       //                 << "*(" << w[iWeight] << ")";
00235       acc+=sample.adc()*w[iWeight];
00236     } else{
00237       edm::LogWarning("DccFir") << __FILE__ << ":" << __LINE__ <<
00238         ": Not enough samples in data frame or 'ecalDccZs1stSample' module "
00239         "parameter is not valid...";
00240     }
00241   }
00242 
00243   if(symetricZS){//cut on absolute value
00244     if(acc<0) acc = -acc;
00245   }
00246   
00247   //LogTrace("DccFir") << "\n";
00248   //discards the 8 LSBs 
00249   //(result of shift operator on negative numbers depends on compiler
00250   //implementation, therefore the value is offset to make sure it is positive
00251   //before performing the bit shift).
00252   acc = ((acc + (1<<30)) >>8) - (1 <<(30-8));
00253 
00254   //ZS passed if weigthed sum acc above ZS threshold or if
00255   //one sample has a lower gain than gain 12 (that is gain 12 output
00256   //is saturated)
00257   
00258   const bool result = (acc >= thr) || gain12saturated;
00259   
00260   //LogTrace("DccFir") << "acc: " << acc << "\n"
00261   //                   << "threshold: " << thr << " ("
00262   //                   << thr*thrUnit[((EcalDataFrame&)frame).id().subdetId()==EcalBarrel?0:1]
00263   //                   << "GeV)\n"
00264   //                   << "saturated: " << (gain12saturated?"yes":"no") << "\n"
00265   //                   << "ZS passed: " << (result?"yes":"no")
00266   //                   << (symetricZS?" (symetric cut)":"") << "\n";
00267   
00268   return result;
00269 }
00270 
00271 void EcalSelectiveReadoutSuppressor::run(const edm::EventSetup& eventSetup,   
00272                                          const EcalTrigPrimDigiCollection & trigPrims,
00273                                          EBDigiCollection & barrelDigis,
00274                                          EEDigiCollection & endcapDigis){
00275   EBDigiCollection selectedBarrelDigis;
00276   EEDigiCollection selectedEndcapDigis;
00277   
00278   run(eventSetup, trigPrims, barrelDigis, endcapDigis,
00279       &selectedBarrelDigis, &selectedEndcapDigis, 0, 0);
00280   
00281 //replaces the input with the suppressed version
00282   barrelDigis.swap(selectedBarrelDigis);
00283   endcapDigis.swap(selectedEndcapDigis);  
00284 }
00285 
00286 
00287 void
00288 EcalSelectiveReadoutSuppressor::run(const edm::EventSetup& eventSetup,
00289                                     const EcalTrigPrimDigiCollection & trigPrims,
00290                                     const EBDigiCollection & barrelDigis,
00291                                     const EEDigiCollection & endcapDigis,
00292                                     EBDigiCollection* selectedBarrelDigis,
00293                                     EEDigiCollection* selectedEndcapDigis,
00294                                     EBSrFlagCollection* ebSrFlags,
00295                                     EESrFlagCollection* eeSrFlags){
00296   ++ievt_;
00297   if(!trigPrimBypass_ || ttThresOnCompressedEt_){//uses output of TPG emulator
00298     setTtFlags(trigPrims);
00299   } else{//debug mode, run w/o TP digis
00300     setTtFlags(eventSetup, barrelDigis, endcapDigis);
00301   }
00302 
00303   ecalSelectiveReadout->runSelectiveReadout0(ttFlags);  
00304 
00305   if(selectedBarrelDigis){
00306     selectedBarrelDigis->reserve(barrelDigis.size()/20);
00307     
00308     // do barrel first
00309     for(EBDigiCollection::const_iterator digiItr = barrelDigis.begin();
00310         digiItr != barrelDigis.end(); ++digiItr){
00311       int interestLevel
00312         = ecalSelectiveReadout->getCrystalInterest(EBDigiCollection::DetId(digiItr->id())) && ~EcalSelectiveReadout::FORCED_MASK;
00313       if(accept(*digiItr, zsThreshold[BARREL][interestLevel])){
00314         selectedBarrelDigis->push_back(digiItr->id(), digiItr->begin());
00315       } 
00316     }
00317   }
00318   
00319   // and endcaps
00320   if(selectedEndcapDigis){
00321     selectedEndcapDigis->reserve(endcapDigis.size()/20);
00322     for(EEDigiCollection::const_iterator digiItr = endcapDigis.begin();
00323         digiItr != endcapDigis.end(); ++digiItr){
00324       int interestLevel
00325         = ecalSelectiveReadout->getCrystalInterest(EEDigiCollection::DetId(digiItr->id()))
00326         & ~EcalSelectiveReadout::FORCED_MASK;
00327       if(accept(*digiItr, zsThreshold[ENDCAP][interestLevel])){
00328         selectedEndcapDigis->push_back(digiItr->id(), digiItr->begin());
00329       }
00330     }
00331   }
00332 
00333    if(ievt_ <= 10){
00334      if(selectedEndcapDigis) LogDebug("EcalSelectiveReadout")
00335                                //       << __FILE__ << ":" << __LINE__ << ": "
00336        << "Number of EB digis passing the SR: "
00337        << selectedBarrelDigis->size()
00338        << " / " << barrelDigis.size() << "\n";
00339      if(selectedEndcapDigis) LogDebug("EcalSelectiveReadout")
00340                                //       << __FILE__ << ":" << __LINE__ << ": "
00341        << "\nNumber of EE digis passing the SR: "
00342        << selectedEndcapDigis->size()
00343        << " / " << endcapDigis.size() << "\n";
00344    }
00345   
00346   if(ebSrFlags) ebSrFlags->reserve(34*72);
00347   if(eeSrFlags) eeSrFlags->reserve(624);
00348   //SR flags:
00349   for(int iZ = -1; iZ <=1; iZ+=2){ //-1=>EE-, EB-, +1=>EE+, EB+
00350     //barrel:
00351     for(unsigned iEta = 1; iEta <= nBarrelTriggerTowersInEta/2; ++iEta){
00352       for(unsigned iPhi = 1; iPhi <= nTriggerTowersInPhi; ++iPhi){
00353         const EcalTrigTowerDetId id(iZ, EcalBarrel, iEta, iPhi);
00354         EcalSelectiveReadout::towerInterest_t interest
00355           = ecalSelectiveReadout->getTowerInterest(id);
00356         if(interest<0){
00357           throw cms::Exception("EcalSelectiveReadout")
00358             << __FILE__ << ":" << __LINE__ << ": " << "unknown SR flag. for "
00359             << " TT " << id << ". Most probably a bug.";
00360         }
00361         int flag;
00362         //      if(interest==EcalSelectiveReadout::FORCED_RO){
00363         //  flag = EcalSrFlag::SRF_FORCED_MASK | EcalSrFlag::SRF_FULL;
00364         //} else{
00365         flag = srFlags[BARREL][interest];
00366         //}
00367         if(ebSrFlags) ebSrFlags->push_back(EBSrFlag(id, flag));
00368       }//next iPhi
00369     } //next barrel iEta
00370 
00371     //endcap:
00372     EcalScDetId id;
00373     for(int iX = 1; iX <= 20; ++iX){
00374       for(int iY = 1; iY <= 20; ++iY){
00375 
00376         if (EcalScDetId::validDetId(iX, iY, iZ))
00377           id = EcalScDetId(iX, iY, iZ);
00378         else
00379           continue;
00380         
00381         EcalSelectiveReadout::towerInterest_t interest
00382           = ecalSelectiveReadout->getSuperCrystalInterest(id);
00383         
00384         if(interest>=0){//negative no SC at (iX,iY) coordinates
00385           int flag;
00386           //      if(interest==EcalSelectiveReadout::FORCED_RO){
00387           //  flag = EcalSrFlag::SRF_FORCED_MASK | EcalSrFlag::SRF_FULL;
00388           //} else{
00389           flag = srFlags[ENDCAP][interest];
00390           //}
00391           if(eeSrFlags) eeSrFlags->push_back(EESrFlag(id, flag));
00392         } else  if(iX < 9 || iX > 12 || iY < 9 || iY >12){ //not an inner partial SC
00393           edm::LogError("EcalSelectiveReadout") << __FILE__ << ":" << __LINE__ << ": "
00394                                                 <<  "negative interest in EE for SC "
00395                                                 << id << "\n";
00396         }
00397       } //next iY
00398     } //next iX
00399   }
00400 }
00401 
00402 
00403 void EcalSelectiveReadoutSuppressor::setTtFlags(const EcalTrigPrimDigiCollection & trigPrims){
00404   for(size_t iEta0 = 0; iEta0 < nTriggerTowersInEta; ++iEta0){
00405     for(size_t iPhi0 = 0; iPhi0 < nTriggerTowersInPhi; ++iPhi0){
00406       ttFlags[iEta0][iPhi0] = defaultTtf_;
00407     }
00408   }
00409   for(EcalTrigPrimDigiCollection::const_iterator trigPrim = trigPrims.begin();
00410       trigPrim != trigPrims.end(); ++trigPrim){
00411     int iEta =  trigPrim->id().ieta();
00412     unsigned int iEta0;
00413     if(iEta<0){ //z- half ECAL: transforming ranges -28;-1 => 0;27
00414       iEta0 = iEta + nTriggerTowersInEta/2;
00415     } else{ //z+ halfECAL: transforming ranges 1;28 => 28;55
00416       iEta0 = iEta + nTriggerTowersInEta/2 - 1;
00417     }
00418 
00419     unsigned int iPhi0 = trigPrim->id().iphi() - 1;
00420 
00421     if(!ttThresOnCompressedEt_){
00422       ttFlags[iEta0][iPhi0] =
00423         (EcalSelectiveReadout::ttFlag_t) trigPrim->ttFlag();
00424     } else{
00425       int compressedEt = trigPrim->compressedEt();
00426       if(compressedEt < trigPrimBypassLTH_){
00427         ttFlags[iEta0][iPhi0] = EcalSelectiveReadout::TTF_LOW_INTEREST;
00428       } else if(compressedEt < trigPrimBypassHTH_){
00429         ttFlags[iEta0][iPhi0] = EcalSelectiveReadout::TTF_MID_INTEREST;
00430       } else{
00431         ttFlags[iEta0][iPhi0] = EcalSelectiveReadout::TTF_HIGH_INTEREST;
00432       }
00433     }
00434   }
00435 }
00436 
00437 
00438 vector<int> EcalSelectiveReadoutSuppressor::getFIRWeigths() {
00439   if(firWeights.size()==0){
00440     firWeights = vector<int>(nFIRTaps, 0); //default weight: 0;
00441     const static int maxWeight = 0xEFF; //weights coded on 11+1 signed bits
00442     for(unsigned i=0; i < min((size_t)nFIRTaps,weights.size()); ++i){ 
00443       firWeights[i] = lround(weights[i] * (1<<10));
00444       if(abs(firWeights[i])>maxWeight){//overflow
00445         firWeights[i] = firWeights[i]<0?-maxWeight:maxWeight;
00446       }
00447     }
00448   }
00449   return firWeights;
00450 }
00451 
00452 void
00453 EcalSelectiveReadoutSuppressor::setTtFlags(const edm::EventSetup& es,
00454                                            const EBDigiCollection& ebDigis,
00455                                            const EEDigiCollection& eeDigis){
00456   double trigPrim[nTriggerTowersInEta][nTriggerTowersInPhi];
00457 
00458   //ecal geometry:
00459 //  static const CaloSubdetectorGeometry* eeGeometry = 0;
00460 //  static const CaloSubdetectorGeometry* ebGeometry = 0;
00461   const CaloSubdetectorGeometry* eeGeometry = 0;
00462   const CaloSubdetectorGeometry* ebGeometry = 0;
00463 //  if(eeGeometry==0 || ebGeometry==0){
00464     edm::ESHandle<CaloGeometry> geoHandle;
00465     es.get<CaloGeometryRecord>().get(geoHandle);
00466     eeGeometry
00467       = (*geoHandle).getSubdetectorGeometry(DetId::Ecal, EcalEndcap);
00468     ebGeometry
00469       = (*geoHandle).getSubdetectorGeometry(DetId::Ecal, EcalBarrel);
00470 //  }
00471 
00472   //init trigPrim array:
00473   bzero(trigPrim, sizeof(trigPrim));
00474         
00475   for(EBDigiCollection::const_iterator it = ebDigis.begin();
00476       it != ebDigis.end(); ++it){
00477     EBDataFrame frame(*it);
00478     const EcalTrigTowerDetId& ttId = theTriggerMap->towerOf(frame.id());
00479 //      edm:::LogDebug("TT") << __FILE__ << ":" << __LINE__ << ": "
00480 //       <<  ((EBDetId&)frame.id()).ieta()
00481 //       << "," << ((EBDetId&)frame.id()).iphi()
00482 //       << " -> " << ttId.ieta() << "," << ttId.iphi() << "\n";
00483     const int iTTEta0 = iTTEta2cIndex(ttId.ieta());
00484     const int iTTPhi0 = iTTPhi2cIndex(ttId.iphi());
00485     double theta = ebGeometry->getGeometry(frame.id())->getPosition().theta();
00486     double e = frame2Energy(frame);
00487     if(!trigPrimBypassWithPeakFinder_
00488        || ((frame2Energy(frame,-1) < e) && (frame2Energy(frame, 1) < e))){
00489       trigPrim[iTTEta0][iTTPhi0] += e*sin(theta);
00490     }
00491   }
00492 
00493   for(EEDigiCollection::const_iterator it = eeDigis.begin();
00494       it != eeDigis.end(); ++it){
00495     EEDataFrame frame(*it);
00496     const EcalTrigTowerDetId& ttId = theTriggerMap->towerOf(frame.id());
00497     const int iTTEta0 = iTTEta2cIndex(ttId.ieta());
00498     const int iTTPhi0 = iTTPhi2cIndex(ttId.iphi());
00499 //     cout << __FILE__ << ":" << __LINE__ << ": EE xtal->TT "
00500 //       <<  ((EEDetId&)frame.id()).ix()
00501 //       << "," << ((EEDetId&)frame.id()).iy()
00502 //       << " -> " << ttId.ieta() << "," << ttId.iphi() << "\n";
00503     double theta = eeGeometry->getGeometry(frame.id())->getPosition().theta();
00504     double e = frame2Energy(frame);
00505     if(!trigPrimBypassWithPeakFinder_
00506        || ((frame2Energy(frame,-1) < e) && (frame2Energy(frame, 1) < e))){
00507       trigPrim[iTTEta0][iTTPhi0] += e*sin(theta);
00508     }
00509   }
00510 
00511   //dealing with pseudo-TT in two inner EE eta-ring:
00512   int innerTTEtas[] = {0, 1, 54, 55};
00513   for(unsigned iRing = 0; iRing < sizeof(innerTTEtas)/sizeof(innerTTEtas[0]);
00514       ++iRing){
00515     int iTTEta0 = innerTTEtas[iRing];
00516     //this detector eta-section is divided in only 36 phi bins
00517     //For this eta regions,
00518     //current tower eta numbering scheme is inconsistent. For geometry
00519     //version 133:
00520     //- TT are numbered from 0 to 72 for 36 bins
00521     //- some TT have an even index, some an odd index
00522     //For geometry version 125, there are 72 phi bins.
00523     //The code below should handle both geometry definition.
00524     //If there are 72 input trigger primitives for each inner eta-ring,
00525     //then the average of the trigger primitive of the two pseudo-TT of
00526     //a pair (nEta, nEta+1) is taken as Et of both pseudo TTs.
00527     //If there are only 36 input TTs for each inner eta ring, then half
00528     //of the present primitive of a pseudo TT pair is used as Et of both
00529     //pseudo TTs.
00530 
00531     for(unsigned iTTPhi0 = 0; iTTPhi0 < nTriggerTowersInPhi-1; iTTPhi0 += 2){
00532       double et = .5*(trigPrim[iTTEta0][iTTPhi0]
00533                       +trigPrim[iTTEta0][iTTPhi0+1]);
00534       //divides the TT into 2 phi bins in order to match with 72 phi-bins SRP
00535       //scheme or average the Et on the two pseudo TTs if the TT is already
00536       //divided into two trigger primitives.
00537       trigPrim[iTTEta0][iTTPhi0] = et;
00538       trigPrim[iTTEta0][iTTPhi0+1] = et;
00539     }
00540   }
00541     
00542   for(unsigned iTTEta0 = 0; iTTEta0 < nTriggerTowersInEta; ++iTTEta0){
00543     for(unsigned iTTPhi0 = 0; iTTPhi0 < nTriggerTowersInPhi; ++iTTPhi0){
00544       if(trigPrim[iTTEta0][iTTPhi0] > trigPrimBypassHTH_){
00545         ttFlags[iTTEta0][iTTPhi0] = EcalSelectiveReadout::TTF_HIGH_INTEREST;
00546       } else if(trigPrim[iTTEta0][iTTPhi0] > trigPrimBypassLTH_){
00547         ttFlags[iTTEta0][iTTPhi0] = EcalSelectiveReadout::TTF_MID_INTEREST;
00548       } else{
00549         ttFlags[iTTEta0][iTTPhi0] = EcalSelectiveReadout::TTF_LOW_INTEREST;
00550       }
00551       
00552       // cout /*LogDebug("TT")*/
00553       //        << "ttFlags[" << iTTEta0 << "][" << iTTPhi0 << "] = "
00554       //        << ttFlags[iTTEta0][iTTPhi0] << "\n";
00555     }
00556   }
00557 }
00558 
00559 template<class T>
00560 double EcalSelectiveReadoutSuppressor::frame2Energy(const T& frame,
00561                                                     int offset) const{
00562   //we have to start by 0 in order to handle offset=-1
00563   //(however Fenix FIR has AFAK only 5 taps)
00564   double weights[] = {0., -1/3., -1/3., -1/3., 0., 1.};   
00565 
00566   double adc2GeV = 0.;
00567   if(typeid(frame) == typeid(EBDataFrame)){
00568     adc2GeV = 0.035;
00569   } else if(typeid(frame) == typeid(EEDataFrame)){
00570     adc2GeV = 0.060;
00571   } else{ //T is an invalid type!
00572     //TODO: replace message by a cms exception
00573     cerr << "Severe error. "
00574          << __FILE__ << ":" << __LINE__ << ": "
00575          << "this is a bug. Please report it.\n";
00576   }
00577     
00578   double acc = 0;
00579 
00580   const int n = min<int>(frame.size(), sizeof(weights)/sizeof(weights[0]));
00581 
00582   double gainInv[] = {12., 1., 6., 12.};
00583 
00584 
00585   //cout << __PRETTY_FUNCTION__ << ": ";
00586   for(int i=offset; i < n; ++i){
00587     int iframe = i + offset;
00588     if(iframe>=0 && iframe<frame.size()){
00589       acc += weights[i]*frame[iframe].adc()
00590         *gainInv[frame[iframe].gainId()]*adc2GeV;
00591       //cout << (iframe>offset?"+":"")
00592       //     << frame[iframe].adc() << "*" << gainInv[frame[iframe].gainId()]
00593       //     << "*" << adc2GeV << "*(" << weights[i] << ")";
00594     }
00595   }
00596   //cout << "\n";
00597   return acc;
00598 }
00599 
00600 void EcalSelectiveReadoutSuppressor::printTTFlags(ostream& os, int iEvent,
00601                                                   bool withHeader) const{
00602   const char tccFlagMarker[] = { '?', '.', 'S', '?', 'C', 'E', 'E', 'E', 'E'};
00603   const int nEta = EcalSelectiveReadout::nTriggerTowersInEta;
00604   const int nPhi = EcalSelectiveReadout::nTriggerTowersInPhi;
00605   
00606   if(withHeader){
00607     os << "# TCC flag map\n#\n"
00608       "# +-->Phi            " << tccFlagMarker[1+0] << ": 000 (low interest)\n"
00609       "# |                  " << tccFlagMarker[1+1] << ": 001 (mid interest)\n"
00610       "# |                  " << tccFlagMarker[1+2] << ": 010 (not valid)\n"
00611       "# V Eta              " << tccFlagMarker[1+3] << ": 011 (high interest)\n"
00612       "#                    " << tccFlagMarker[1+4] << ": 1xx forced readout (Hw error)\n";
00613   }
00614 
00615   if(iEvent>=0){
00616     os << "#\n#Event " << iEvent << "\n";
00617   }
00618   
00619   for(int iEta=0; iEta<nEta; ++iEta){
00620     for(int iPhi=0; iPhi<nPhi; ++iPhi){
00621       os << tccFlagMarker[ttFlags[iEta][iPhi]+1];
00622     }
00623     os << "\n";
00624   }
00625 }