CMS 3D CMS Logo

OptoScanTask.cc

Go to the documentation of this file.
00001 #include "DQM/SiStripCommissioningSources/interface/OptoScanTask.h"
00002 #include "DataFormats/SiStripCommon/interface/SiStripConstants.h"
00003 #include "DataFormats/SiStripCommon/interface/SiStripHistoTitle.h"
00004 #include "DQMServices/Core/interface/DQMStore.h"
00005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00006 #include <algorithm>
00007 #include <math.h>
00008 
00009 #include "DataFormats/SiStripCommon/interface/SiStripFedKey.h"
00010 #include <iomanip>
00011 
00012 using namespace sistrip;
00013 
00014 // -----------------------------------------------------------------------------
00015 //
00016 OptoScanTask::OptoScanTask( DQMStore* dqm,
00017                             const FedChannelConnection& conn ) :
00018   CommissioningTask( dqm, conn, "OptoScanTask" ),
00019   opto_()
00020 {}
00021 
00022 // -----------------------------------------------------------------------------
00023 //
00024 OptoScanTask::~OptoScanTask() {
00025 }
00026 
00027 // -----------------------------------------------------------------------------
00028 //
00029 void OptoScanTask::book() {
00030 
00031   uint16_t nbins = 50; //@@ correct?
00032   uint16_t gains = 4;
00033 
00034   std::string title;
00035 
00036   // Resize "histo sets"
00037   opto_.resize( gains );
00038   for ( uint16_t igain = 0; igain < opto_.size(); igain++ ) { opto_[igain].resize(3); }
00039   
00040   for ( uint16_t igain = 0; igain < opto_.size(); igain++ ) { 
00041     for ( uint16_t ihisto = 0; ihisto < 3; ihisto++ ) { 
00042       
00043       // Extra info
00044       std::stringstream extra_info; 
00045       extra_info << sistrip::extrainfo::gain_ << igain;
00046       if ( ihisto == 0 || ihisto == 1 ) {
00047         extra_info << sistrip::extrainfo::digital_ << ihisto;
00048       } else {
00049         extra_info << sistrip::extrainfo::baselineRms_;
00050       }
00051 
00052       // Title
00053       title = SiStripHistoTitle( sistrip::EXPERT_HISTO, 
00054                                  sistrip::OPTO_SCAN, 
00055                                  sistrip::FED_KEY, 
00056                                  fedKey(),
00057                                  sistrip::LLD_CHAN, 
00058                                  connection().lldChannel(),
00059                                  extra_info.str() ).title();
00060 
00061       // Book histo
00062       opto_[igain][ihisto].histo( dqm()->bookProfile( title, title, 
00063                                                       nbins, 0.5, nbins*1.+0.5, // range is bias setting (1-50)
00064                                                       1024, -0.5, 1023.5 ) );
00065       
00066       opto_[igain][ihisto].vNumOfEntries_.resize(nbins,0);
00067       opto_[igain][ihisto].vSumOfContents_.resize(nbins,0);
00068       opto_[igain][ihisto].vSumOfSquares_.resize(nbins,0);
00069       
00070     }
00071   }
00072   
00073 }
00074 
00075 // -----------------------------------------------------------------------------
00076 //
00077 /*
00078   improve finding tick mark and baseline
00079   keep baseline "noise" along with tick hieght and base
00080   new histo plotting noise +/- spread in noise vs bias
00081 */
00082 void OptoScanTask::fill( const SiStripEventSummary& summary,
00083                          const edm::DetSet<SiStripRawDigi>& digis ) {
00084 
00085   //@@ if scope mode length is in trigger fed, then 
00086   //@@ can add check here on number of digis
00087   if ( digis.data.empty() ) {
00088     edm::LogWarning(mlDqmSource_)
00089       << "[OptoScanTask::" << __func__ << "]"
00090       << " Unexpected number of digis! " 
00091       << digis.data.size(); 
00092   } else {
00093     
00094     // Retrieve opt bias and gain setting from SiStripEventSummary
00095     uint16_t gain = summary.lldGain();
00096     uint16_t bias = summary.lldBias();
00097     
00098     if ( gain >= opto_.size() ) { 
00099       opto_.resize( gain );
00100       for ( uint16_t igain = 0; igain < opto_.size(); igain++ ) { 
00101         if ( opto_[gain].size() != 3 ) { opto_[gain].resize( 3 ); }
00102       }
00103       edm::LogWarning(mlDqmSource_)  
00104         << "[OptoScanTask::" << __func__ << "]"
00105         << " Unexpected gain value! " << gain;
00106     }
00107 
00108     if ( bias > 50 ) { return; } // only use bias settings 1-50
00109     
00110     // Find digital "0" and digital "1" levels from tick marks within scope mode data
00111     std::vector<float> baseline;
00112     std::pair<float,float> digital_range;
00113     digital_range.first  = sistrip::invalid_;
00114     digital_range.second = sistrip::invalid_;
00115     float baseline_rms   = sistrip::invalid_;
00116 
00117     locateTicks( digis, digital_range, baseline, baseline_rms );
00118 
00119     uint16_t bin = bias - 1; // fill "bins" (0-49), not bias (1-50)
00120     
00121     // Digital "0"
00122     if ( digital_range.first < 1. * sistrip::valid_ ) {
00123       updateHistoSet( opto_[gain][0], bin, digital_range.first );
00124     }
00125     
00126     // Digital "1"
00127     if ( digital_range.second < 1. * sistrip::valid_ ) {
00128       updateHistoSet( opto_[gain][1], bin, digital_range.second );
00129     }
00130     
00131     // Baseline rms
00132     if ( baseline_rms < 1. * sistrip::valid_ ) {
00133       updateHistoSet( opto_[gain][2], bin, baseline_rms );
00134     }
00135     
00136   }
00137 
00138 }
00139 
00140 
00141 // -----------------------------------------------------------------------------
00142 //
00143 void OptoScanTask::update() {
00144   
00145   for ( uint16_t igain = 0; igain < opto_.size(); igain++ ) { 
00146     for ( uint16_t ihisto = 0; ihisto < opto_[igain].size(); ihisto++ ) { 
00147       updateHistoSet( opto_[igain][ihisto] );
00148     }
00149   }
00150 
00151 }
00152 
00153 // -----------------------------------------------------------------------------
00154 //
00155 void OptoScanTask::locateTicks( const edm::DetSet<SiStripRawDigi>& digis, 
00156                                 std::pair<float,float>& range, 
00157                                 std::vector<float>& baseline,
00158                                 float& baseline_rms ) {
00159   
00160   // Copy ADC values and sort 
00161   std::vector<uint16_t> adc; 
00162   adc.reserve( digis.data.size() ); 
00163   for ( uint16_t iadc = 0; iadc < digis.data.size(); iadc++ ) { adc.push_back( digis.data[iadc].adc() ); }
00164   sort( adc.begin(), adc.end() );
00165 
00166   // Select algo 
00167   if ( true ) {
00168 
00169     if ( adc.size() > 70 ) {
00170       
00171       // Define "baseline" and "tick mark top" levels as ("min" and "max" ADC values)
00172       range.first  = adc.front();
00173       range.second = adc.back();
00174       
00175       // Construct vector to hold "baseline samples" (exclude tick mark samples and possible APV frames)
00176       std::vector<uint16_t>::const_iterator ii = adc.begin();
00177       std::vector<uint16_t>::const_iterator jj = adc.end() - 8 * ( ( adc.size() / 70 ) + 1 );
00178       std::vector<uint16_t> truncated; 
00179       truncated.resize( jj - ii );
00180       std::copy( ii, jj, truncated.begin() );
00181       if ( truncated.empty() ) { return; }
00182       
00183       // Calc mean baseline level
00184       float b_mean = 0.;
00185       std::vector<uint16_t>::const_iterator iii = truncated.begin();
00186       std::vector<uint16_t>::const_iterator jjj = truncated.end();
00187       for ( ; iii != jjj; ++iii ) { b_mean += *iii; }
00188       b_mean /= ( 1. * truncated.size() );
00189       
00190       // Calc baseline noise
00191       float b_rms = 0.;
00192       std::vector<uint16_t>::const_iterator iiii = truncated.begin();
00193       std::vector<uint16_t>::const_iterator jjjj = truncated.end();
00194       for ( ; iiii != jjjj; ++iiii ) { b_rms += fabs( *iiii - b_mean ); }
00195 
00196       // Set baseline "noise" (requires any possible APV frames are filtered from the data!)
00197       baseline_rms = sqrt ( b_rms / ( 1. * truncated.size() ) );
00198       
00199     } else {
00200       edm::LogWarning(mlDqmSource_)
00201         << "[OptoScanTask::" << __func__ << "]"
00202         << " Insufficient ADC values: " << adc.size();
00203     }
00204 
00205   } else {
00206   
00207     // Initialization for "baseline" 
00208     std::vector<float> base;
00209     base.reserve( adc.size() );
00210     float base_mean = 0.;
00211     float base_rms = 0.;
00212     float base_median = 0.;
00213     
00214     // Initialization for "tick marks" 
00215     std::vector<float> tick;
00216     tick.reserve( adc.size() );
00217     float tick_mean = 0.;
00218     float tick_rms = 0.;
00219     float tick_median = 0.;
00220   
00221     // Calculate mid-range of data 
00222     uint16_t mid_range = adc.front() + ( adc.back() - adc.front() ) / 2;
00223   
00224     // Associate ADC values with either "ticks" or "baseline"
00225     std::vector<uint16_t>::const_iterator iter = adc.begin();
00226     std::vector<uint16_t>::const_iterator jter = adc.end();
00227     for ( ; iter != jter; iter++ ) { 
00228       if ( *iter <= mid_range ) {
00229         base.push_back( *iter ); 
00230         base_mean += *iter;
00231         base_rms += (*iter) * (*iter);
00232       } else {
00233         tick.push_back( *iter ); 
00234         tick_mean += *iter;
00235         tick_rms += (*iter) * (*iter);
00236       }
00237     }
00238 
00239     // Calc mean and rms of baseline
00240     if ( !base.empty() ) { 
00241       base_mean = base_mean / base.size();
00242       base_rms = base_rms / base.size();
00243       base_rms = sqrt( fabs( base_rms - base_mean*base_mean ) ); 
00244     } else { 
00245       base_mean = 1. * sistrip::invalid_; 
00246       base_rms = 1. * sistrip::invalid_; 
00247       base_median = 1. * sistrip::invalid_; 
00248     }
00249 
00250     // Calc mean and rms of tick marks
00251     if ( !tick.empty() ) { 
00252       tick_mean = tick_mean / tick.size();
00253       tick_rms = tick_rms / tick.size();
00254       tick_rms = sqrt( fabs( tick_rms - tick_mean*tick_mean ) ); 
00255     } else { 
00256       tick_mean = 1. * sistrip::invalid_; 
00257       tick_rms = 1. * sistrip::invalid_; 
00258       tick_median = 1. * sistrip::invalid_; 
00259     }
00260   
00261     baseline.reserve( base.size() );
00262     baseline.assign( base.begin(), base.end() );
00263     range.first = base_mean; 
00264     range.second = tick_mean; 
00265     baseline_rms = base_rms;
00266 
00267   }
00268  
00269 }
00270 
00271 // -----------------------------------------------------------------------------
00272 //
00273 void OptoScanTask::deprecated( const edm::DetSet<SiStripRawDigi>& digis, 
00274                                std::pair< uint16_t, uint16_t >& digital_range, 
00275                                bool first_tick_only ) {
00276   
00277   //@@ RUBBISH!!!! simplify!!! find min/max, mid-range and push back into base and tick vectors (based on mid-range)
00278   
00279   // Copy ADC values and sort
00280   std::vector<uint16_t> adc; adc.reserve( digis.data.size() ); 
00281   for ( uint16_t iadc = 0; iadc < digis.data.size(); iadc++ ) { adc.push_back( digis.data[iadc].adc() ); }
00282   sort( adc.begin(), adc.end() );
00283   uint16_t size = adc.size();
00284 
00285   // Find mean and error
00286   float sum = 0, sum2 = 0, num = 0;
00287   for ( uint16_t iadc = static_cast<uint16_t>( 0.1*size ); 
00288         iadc < static_cast<uint16_t>( 0.9*adc.size() ); iadc++ ) {
00289     sum  += adc[iadc];
00290     sum2 += adc[iadc] * adc[iadc];
00291     num++;
00292   }
00293   float mean = 0, mean2 = 0, sigma = 0;
00294   if ( num ) { 
00295     mean = sum / num; 
00296     mean2 = sum2 / num;
00297     if ( mean2 > mean*mean ) { sigma = sqrt( mean2 - mean*mean ); }
00298   }
00299 
00300   // Identify samples belonging to "baseline" and "tick marks"
00301   float threshold = mean + sigma * 5.;
00302   //bool found_first_tick = false;
00303   std::vector<uint32_t> baseline; 
00304   std::vector<uint32_t> tickmark; 
00305   for ( uint16_t iadc = 0; iadc < adc.size(); iadc++ ) { 
00306     if ( adc[iadc] > threshold ) { tickmark.push_back( adc[iadc] ); }
00307     else { baseline.push_back( adc[iadc] ); }
00308   }
00309 
00310   // Define digital "0" and "1" levels (median values)
00311   if ( !baseline.empty() ) { 
00312     uint16_t sample = baseline.size()%2 ? baseline.size()/2 : baseline.size()/2-1;
00313     digital_range.first = baseline[ sample ]; // median
00314   } else { digital_range.first = 1025; }
00315 
00316   if ( !tickmark.empty() ) { 
00317     uint16_t sample = tickmark.size()%2 ? tickmark.size()/2 : tickmark.size()/2-1;
00318     digital_range.second = tickmark[ sample ]; // median
00319   } else { digital_range.second = 1025; }
00320   
00321 }

Generated on Tue Jun 9 17:33:33 2009 for CMSSW by  doxygen 1.5.4