CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/EventFilter/EcalRawToDigi/src/DCCTowerBlock.cc

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <algorithm>
00003 #include "EventFilter/EcalRawToDigi/interface/DCCTowerBlock.h"
00004 #include "EventFilter/EcalRawToDigi/interface/DCCEventBlock.h"
00005 #include "EventFilter/EcalRawToDigi/interface/DCCDataUnpacker.h"
00006 #include "EventFilter/EcalRawToDigi/interface/EcalElectronicsMapper.h"
00007 
00008 
00009 
00010 DCCTowerBlock::DCCTowerBlock( DCCDataUnpacker * u, EcalElectronicsMapper * m, DCCEventBlock * e, bool unpack , bool forceToKeepFRdata)
00011 : DCCFEBlock(u,m,e,unpack,forceToKeepFRdata){}
00012 
00013 
00014 void DCCTowerBlock::updateCollectors(){
00015 
00016   DCCFEBlock::updateCollectors();
00017   
00018   // needs to be update for eb/ee
00019   digis_                 = unpacker_->ebDigisCollection();
00020    
00021   invalidGains_          = unpacker_->invalidGainsCollection();
00022   invalidGainsSwitch_    = unpacker_->invalidGainsSwitchCollection();
00023   invalidChIds_          = unpacker_->invalidChIdsCollection();
00024 
00025 }
00026 
00027 
00028 
00029 int DCCTowerBlock::unpackXtalData(unsigned int expStripID, unsigned int expXtalID){
00030   
00031   bool errorOnXtal(false);
00032  
00033   const uint16_t * xData_= reinterpret_cast<const uint16_t *>(data_);
00034 
00035   // Get xtal data ids
00036   unsigned int stripId  = (*xData_)                     & TOWER_STRIPID_MASK;
00037   unsigned int xtalId   = ((*xData_)>>TOWER_XTALID_B )  & TOWER_XTALID_MASK;
00038 
00039   // check id in case data are not 0suppressed
00040   if( !zs_ && (expStripID != stripId || expXtalID != xtalId)){ 
00041     if(! DCCDataUnpacker::silentMode_){ 
00042       edm::LogWarning("IncorrectBlock")
00043         <<"For event L1A: "<<event_->l1A()<<", fed "<<mapper_->getActiveDCC()<<" and tower "<<towerId_
00044         <<"\n The expected strip is "<<expStripID<<" and "<<stripId<<" was found"
00045         <<"\n The expected xtal  is "<<expXtalID <<" and "<<xtalId<<" was found";        
00046     } 
00047     // using expected cry_di to raise warning about xtal_id problem
00048     pDetId_ = (EBDetId*) mapper_->getDetIdPointer(towerId_,expStripID,expXtalID);
00049     (*invalidChIds_)->push_back(*pDetId_);
00050     
00051     stripId    = expStripID;
00052     xtalId     = expXtalID;
00053     errorOnXtal= true;
00054     
00055     // return here, so to skip all following checks
00056     lastXtalId_++;
00057     if (lastXtalId_ > NUMB_XTAL)         {lastXtalId_=1; lastStripId_++;}
00058     data_ += numbDWInXtalBlock_;
00059     return BLOCK_UNPACKED;
00060   }
00061 
00062 
00063   // check id in case of 0suppressed data
00064 
00065   else if(zs_){
00066 
00067     // Check for valid Ids 1) values out of range
00068 
00069     if(stripId == 0 || stripId > 5 || xtalId == 0 || xtalId > 5){
00070       if( ! DCCDataUnpacker::silentMode_ ){
00071         edm::LogWarning("IncorrectBlock")
00072           <<"For event L1A: "<<event_->l1A()<<", fed "<<mapper_->getActiveDCC()<<" and tower "<<towerId_
00073           <<"\n Invalid strip : "<<stripId<<" or xtal : "<<xtalId
00074           <<" ids ( last strip was: " << lastStripId_ << " last ch was: " << lastXtalId_ << ")";
00075       }
00076       
00077       int st = lastStripId_;
00078       int ch = lastXtalId_;
00079       ch++;
00080       if (ch > NUMB_XTAL)         {ch=1; st++;}
00081       if (st > NUMB_STRIP)        {ch=1; st=1;}
00082       
00083       // adding channel following the last valid
00084       //pDetId_ = (EBDetId*) mapper_->getDetIdPointer(towerId_,st,ch);
00085       //(*invalidChIds_)->push_back(*pDetId_);
00086       fillEcalElectronicsError(invalidZSXtalIds_); 
00087 
00088       errorOnXtal = true;
00089 
00090       lastStripId_ = st;
00091       lastXtalId_  = ch;
00092       
00093       // return here, so to skip all following checks
00094       return SKIP_BLOCK_UNPACKING;
00095       
00096     }else{
00097 
00098       // Check for zs valid Ids 2) if channel-in-strip has increased wrt previous xtal
00099       
00100       
00101       // Check for zs valid Ids 2) if channel-in-strip has increased wrt previous xtal
00102       //                        3) if strip has increased wrt previous xtal
00103       if( ( stripId == lastStripId_ && xtalId <= lastXtalId_ ) ||
00104           (stripId < lastStripId_))
00105         {
00106           if (! DCCDataUnpacker::silentMode_) {
00107             edm::LogWarning("IncorrectBlock")
00108               << "Xtal id was expected to increase but it didn't - last valid xtal id was " << lastXtalId_ << " while current xtal is " << xtalId
00109               << " (LV1 " << event_->l1A() << " fed " << mapper_->getActiveDCC() << " tower " << towerId_ << ")";
00110           }
00111           
00112           int st = lastStripId_;
00113           int ch = lastXtalId_;
00114           ch++;
00115           if (ch > NUMB_XTAL)        {ch=1; st++;}
00116           if (st >  NUMB_STRIP)        {ch=1; st=1;}
00117           
00118           // adding channel following the last valid
00119           //pDetId_ = (EBDetId*) mapper_->getDetIdPointer(towerId_,st,ch);
00120           //(*invalidChIds_)->push_back(*pDetId_);
00121           fillEcalElectronicsError(invalidZSXtalIds_); 
00122           
00123           errorOnXtal = true;
00124           lastStripId_ = st;
00125           lastXtalId_  = ch;
00126 
00127           // return here, so to skip all following checks
00128           return SKIP_BLOCK_UNPACKING;
00129           
00130         }
00131       
00132       // if channel id not proven wrong, update lastStripId_ and lastXtalId_
00133       lastStripId_  = stripId;
00134       lastXtalId_   = xtalId;
00135     }//end else
00136   }// end if (zs_)
00137 
00138 
00139   bool addedFrame=false;
00140 
00141   // if there is an error on xtal id ignore next error checks  
00142   // otherwise, assume channel_id is valid and proceed with making and checking the data frame
00143   if(errorOnXtal) return SKIP_BLOCK_UNPACKING;
00144 
00145   pDetId_ = (EBDetId*) mapper_->getDetIdPointer(towerId_,stripId,xtalId);
00146   (*digis_)->push_back(*pDetId_);
00147   EBDataFrame df( (*digis_)->back() );
00148   addedFrame=true;
00149   bool wrongGain(false);
00150 
00151   //set samples in the data frame
00152   for(unsigned int i =0; i< nTSamples_ ;i++){ // loop on samples 
00153     xData_++;
00154     unsigned int data =  (*xData_) & TOWER_DIGI_MASK;
00155     unsigned int gain =  data>>12;
00156     xtalGains_[i]=gain;
00157     if(gain == 0){ 
00158       wrongGain = true; 
00159       // although gain==0 found, produce the dataFrame in order to have it, for saturation case
00160     } 
00161     df.setSample(i,data);
00162   }// loop on samples        
00163 
00164   bool isSaturation(true);
00165   if(wrongGain){
00166     
00167     // check whether the gain==0 has features of saturation or not
00168     // gain==0 occurs either in case of data corruption or of ADC saturation
00169     //                                  \->reject digi            \-> keep digi
00170     
00171     // determine where gainId==0 starts
00172     short firstGainZeroSampID(-1);    short firstGainZeroSampADC(-1);
00173     for (unsigned int s=0; s<nTSamples_; s++ ) {
00174       if(df.sample(s).gainId()==0 && firstGainZeroSampID==-1)
00175         {
00176           firstGainZeroSampID  = s;
00177           firstGainZeroSampADC = df.sample(s).adc();
00178           break;
00179         }
00180     }
00181     
00182     // check whether gain==0 and adc() stays constant for (at least) 5 consecutive samples
00183     unsigned int plateauEnd = std::min(nTSamples_,(unsigned int)(firstGainZeroSampID+5));
00184     for (unsigned int s=firstGainZeroSampID; s<plateauEnd; s++) 
00185       {
00186         if( df.sample(s).gainId()==0 && df.sample(s).adc()==firstGainZeroSampADC ) {;}
00187         else
00188           { isSaturation=false;  break;}  //it's not saturation
00189       }
00190     // get rid of channels which are stuck in gain0
00191     if(firstGainZeroSampID<3) {isSaturation=false; }
00192     
00193     if (! DCCDataUnpacker::silentMode_) {
00194       if (unpacker_->getChannelValue(mapper_->getActiveDCC(), towerId_, stripId, xtalId) != 10) {
00195         edm::LogWarning("IncorrectGain")
00196           << "Gain zero" << (isSaturation ? " with features of saturation" : "" ) << " was found in Tower Block"
00197           << " (L1A " << event_->l1A() << " bx " << event_->bx() << " fed " << mapper_->getActiveDCC()
00198           << " tower " << towerId_ << " strip " << stripId << " xtal " << xtalId << ")";
00199       }
00200     }
00201     
00202     if (! isSaturation)
00203       {
00204         (*invalidGains_)->push_back(*pDetId_);
00205         (*digis_)->pop_back(); 
00206         errorOnXtal = true; 
00207         
00208         //Point to begin of next xtal Block
00209         data_ += numbDWInXtalBlock_;
00210         //return here, so to skip all the rest
00211         //make special collection for gain0 data frames when due to saturation
00212         return BLOCK_UNPACKED;
00213       }//end isSaturation 
00214     else {
00215         data_ += numbDWInXtalBlock_;
00216         return BLOCK_UNPACKED;
00217     }
00218 
00219     }//end WrongGain
00220   
00221   
00222   // from here on, care about gain switches
00223   
00224   short firstGainWrong=-1;
00225   short numGainWrong=0;
00226   
00227   for (unsigned int i=1; i<nTSamples_; i++ ) {
00228     if (i>0 && xtalGains_[i-1]>xtalGains_[i]) {
00229           numGainWrong++;
00230           if (firstGainWrong == -1) { firstGainWrong=i;}
00231     }
00232   }
00233   
00234   
00235   if (numGainWrong > 0) {
00236     if (! DCCDataUnpacker::silentMode_) {
00237       edm::LogWarning("IncorrectGain")
00238         << "A wrong gain transition switch was found for Tower Block in strip " << stripId << " and xtal " << xtalId
00239         << " (L1A " << event_->l1A() << " bx " << event_->bx() << " fed " << mapper_->getActiveDCC() << " tower " << towerId_ << ")";
00240     }
00241     
00242     (*invalidGainsSwitch_)->push_back(*pDetId_);
00243     errorOnXtal = true;
00244   }
00245   
00246   //Add frame to collection only if all data format and gain rules are respected
00247   if (errorOnXtal && addedFrame) {
00248     (*digis_)->pop_back();
00249   }
00250   
00251   //Point to begin of next xtal Block
00252   data_ += numbDWInXtalBlock_;
00253   
00254   return BLOCK_UNPACKED;
00255 }
00256 
00257 
00258 
00259 void DCCTowerBlock::fillEcalElectronicsError( std::auto_ptr<EcalElectronicsIdCollection> * errorColection ){
00260 
00261    const int activeDCC = mapper_->getActiveSM();
00262 
00263    if(NUMB_SM_EB_MIN_MIN<=activeDCC && activeDCC<=NUMB_SM_EB_PLU_MAX){
00264      EcalElectronicsId  *  eleTp = mapper_->getTTEleIdPointer(activeDCC+TCCID_SMID_SHIFT_EB,expTowerID_);
00265      (*errorColection)->push_back(*eleTp);
00266    }else{
00267       if( ! DCCDataUnpacker::silentMode_ ){
00268           edm::LogWarning("IncorrectBlock")
00269             <<"For event "<<event_->l1A()<<" there's fed: "<< activeDCC
00270             <<" activeDcc: "<<mapper_->getActiveSM()
00271             <<" but that activeDcc is not valid in EB.";
00272         }
00273 
00274    }
00275 
00276 }
00277