CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/DQM/SiStripCommissioningAnalysis/src/OptoScanAlgorithm.cc

Go to the documentation of this file.
00001 #include "DQM/SiStripCommissioningAnalysis/interface/OptoScanAlgorithm.h"
00002 #include "CondFormats/SiStripObjects/interface/OptoScanAnalysis.h"
00003 #include "DataFormats/SiStripCommon/interface/SiStripHistoTitle.h"
00004 #include "DataFormats/SiStripCommon/interface/SiStripEnumsAndStrings.h"
00005 #include "DQM/SiStripCommissioningAnalysis/src/Utility.h"
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007 #include "TProfile.h"
00008 #include "TH1.h"
00009 #include <iostream>
00010 #include <sstream>
00011 #include <iomanip>
00012 
00013 using namespace sistrip;
00014 
00015 // ----------------------------------------------------------------------------
00016 // 
00017 OptoScanAlgorithm::OptoScanAlgorithm( const edm::ParameterSet & pset, OptoScanAnalysis* const anal ) 
00018   : CommissioningAlgorithm(anal),
00019     histos_( 4, std::vector<Histo>( 3, Histo(0,"") ) ),
00020     targetGain_(pset.getParameter<double>("TargetGain"))
00021 {
00022   edm::LogInfo(mlCommissioning_)
00023     << "[PedestalsAlgorithm::" << __func__ << "]"
00024     << " Set target gain to: " << targetGain_;
00025 }
00026   
00027 // ----------------------------------------------------------------------------
00028 // 
00029 void OptoScanAlgorithm::extract( const std::vector<TH1*>& histos ) { 
00030 
00031   if ( !anal() ) {
00032     edm::LogWarning(mlCommissioning_)
00033       << "[OptoScanAlgorithm::" << __func__ << "]"
00034       << " NULL pointer to Analysis object!";
00035     return; 
00036   }
00037 
00038   // Check number of histograms
00039   if ( histos.size() != 12 ) {
00040     anal()->addErrorCode(sistrip::numberOfHistos_);
00041   }
00042   
00043   // Extract FED key from histo title
00044   if ( !histos.empty() ) anal()->fedKey( extractFedKey( histos.front() ) );
00045 
00046   // Extract histograms
00047   std::vector<TH1*>::const_iterator ihis = histos.begin();
00048   for ( ; ihis != histos.end(); ihis++ ) {
00049     
00050     // Check for NULL pointer
00051     if ( !(*ihis) ) { continue; }
00052 
00053     // Check name
00054     SiStripHistoTitle title( (*ihis)->GetName() );
00055     if ( title.runType() != sistrip::OPTO_SCAN ) {
00056       anal()->addErrorCode(sistrip::unexpectedTask_);
00057       continue;
00058     }
00059 
00060     // Extract gain setting and digital high/low info
00061     uint16_t gain = sistrip::invalid_; 
00062     if ( title.extraInfo().find(sistrip::extrainfo::gain_) != std::string::npos ) {
00063       std::stringstream ss;
00064       ss << title.extraInfo().substr( title.extraInfo().find(sistrip::extrainfo::gain_) + (sizeof(sistrip::extrainfo::gain_) - 1), 1 );
00065       ss >> std::dec >> gain;
00066     }
00067     uint16_t digital = sistrip::invalid_; 
00068     if ( title.extraInfo().find(sistrip::extrainfo::digital_) != std::string::npos ) {
00069       std::stringstream ss;
00070       ss << title.extraInfo().substr( title.extraInfo().find(sistrip::extrainfo::digital_) + (sizeof(sistrip::extrainfo::digital_) - 1), 1 );
00071       ss >> std::dec >> digital;
00072     }
00073     bool baseline_rms = false;
00074     if ( title.extraInfo().find(sistrip::extrainfo::baselineRms_) != std::string::npos ) {
00075       baseline_rms = true;
00076     }
00077     
00078     if ( gain <= 3 ) { 
00079       if ( digital <= 1 ) {
00080         histos_[gain][digital].first = *ihis; 
00081         histos_[gain][digital].second = (*ihis)->GetName();
00082       } else if ( baseline_rms ) {
00083         histos_[gain][2].first = *ihis; 
00084         histos_[gain][2].second = (*ihis)->GetName();
00085       } else {
00086         anal()->addErrorCode(sistrip::unexpectedExtraInfo_);
00087       }
00088     } else {
00089       anal()->addErrorCode(sistrip::unexpectedExtraInfo_);
00090     }
00091     
00092   }
00093 
00094 }
00095 
00096 // ----------------------------------------------------------------------------
00097 // 
00098 void OptoScanAlgorithm::analyse() { 
00099   
00100   if ( !anal() ) {
00101     edm::LogWarning(mlCommissioning_)
00102       << "[OptoScanAlgorithm::" << __func__ << "]"
00103       << " NULL pointer to base Analysis object!";
00104     return; 
00105   }
00106   
00107   CommissioningAnalysis* tmp = const_cast<CommissioningAnalysis*>( anal() );
00108   OptoScanAnalysis* anal = dynamic_cast<OptoScanAnalysis*>( tmp );
00109   if ( !anal ) {
00110     edm::LogWarning(mlCommissioning_)
00111       << "[OptoScanAlgorithm::" << __func__ << "]"
00112       << " NULL pointer to derived Analysis object!";
00113     return; 
00114   }
00115   
00116   // Iterate through four gain settings
00117   for ( uint16_t igain = 0; igain < 4; igain++ ) {
00118     
00119     // Select histos appropriate for gain setting
00120     TH1* base_his = histos_[igain][0].first; 
00121     TH1* peak_his = histos_[igain][1].first;
00122     TH1* noise_his = histos_[igain][2].first;
00123 
00124     if ( !base_his ) {
00125       anal->addErrorCode(sistrip::nullPtr_);
00126       return;
00127     }
00128     
00129     if ( !peak_his ) {
00130       anal->addErrorCode(sistrip::nullPtr_);
00131       return;
00132     }
00133 
00134     if ( !noise_his ) {
00135       anal->addErrorCode(sistrip::nullPtr_);
00136       return;
00137     }
00138     
00139     TProfile* base_histo = dynamic_cast<TProfile*>(base_his);
00140     if ( !base_histo ) {
00141       anal->addErrorCode(sistrip::nullPtr_);
00142       return;
00143     }
00144     
00145     TProfile* peak_histo = dynamic_cast<TProfile*>(peak_his);
00146     if ( !peak_histo ) {
00147       anal->addErrorCode(sistrip::nullPtr_);
00148       return;
00149     }
00150     
00151     TProfile* noise_histo = dynamic_cast<TProfile*>(noise_his);
00152     if ( !noise_histo ) {
00153       anal->addErrorCode(sistrip::nullPtr_);
00154       return;
00155     }
00156 
00157     // Check histogram binning
00158     uint16_t nbins = static_cast<uint16_t>( peak_histo->GetNbinsX() );
00159     if ( static_cast<uint16_t>( base_histo->GetNbinsX() ) != nbins ) {
00160       anal->addErrorCode(sistrip::numberOfBins_);
00161       if ( static_cast<uint16_t>( base_histo->GetNbinsX() ) < nbins ) {
00162         nbins = static_cast<uint16_t>( base_histo->GetNbinsX() );
00163       }
00164     }
00165 
00166     // Some containers
00167     std::vector<float> peak_contents(0);
00168     std::vector<float> peak_errors(0);
00169     std::vector<float> peak_entries(0);
00170     std::vector<float> base_contents(0);
00171     std::vector<float> base_errors(0);
00172     std::vector<float> base_entries(0);
00173     std::vector<float> noise_contents(0);
00174     std::vector<float> noise_errors(0);
00175     std::vector<float> noise_entries(0);
00176     float peak_max = -1.*sistrip::invalid_;
00177     float peak_min =  1.*sistrip::invalid_;
00178     float base_max = -1.*sistrip::invalid_;
00179     float base_min =  1.*sistrip::invalid_;
00180     float noise_max = -1.*sistrip::invalid_;
00181     float noise_min =  1.*sistrip::invalid_;
00182 
00183     // Transfer histogram contents/errors/stats to containers
00184     for ( uint16_t ibin = 0; ibin < nbins; ibin++ ) {
00185 
00186       // Peak histogram
00187       peak_contents.push_back( peak_histo->GetBinContent(ibin+1) );
00188       peak_errors.push_back( peak_histo->GetBinError(ibin+1) );
00189       peak_entries.push_back( peak_histo->GetBinEntries(ibin+1) );
00190       if ( peak_entries[ibin] ) { 
00191         if ( peak_contents[ibin] > peak_max ) { peak_max = peak_contents[ibin]; }
00192         if ( peak_contents[ibin] < peak_min && ibin ) { peak_min = peak_contents[ibin]; }
00193       }
00194 
00195       // Base histogram
00196       base_contents.push_back( base_histo->GetBinContent(ibin+1) );
00197       base_errors.push_back( base_histo->GetBinError(ibin+1) );
00198       base_entries.push_back( base_histo->GetBinEntries(ibin+1) );
00199       if ( base_entries[ibin] ) { 
00200         if ( base_contents[ibin] > base_max ) { base_max = base_contents[ibin]; }
00201         if ( base_contents[ibin] < base_min && ibin ) { base_min = base_contents[ibin]; }
00202       }
00203 
00204       // Noise histogram
00205       noise_contents.push_back( noise_histo->GetBinContent(ibin+1) );
00206       noise_errors.push_back( noise_histo->GetBinError(ibin+1) );
00207       noise_entries.push_back( noise_histo->GetBinEntries(ibin+1) );
00208       if ( noise_entries[ibin] ) { 
00209         if ( noise_contents[ibin] > noise_max ) { noise_max = noise_contents[ibin]; }
00210         if ( noise_contents[ibin] < noise_min && ibin ) { noise_min = noise_contents[ibin]; }
00211       }
00212 
00213     }
00214     
00215     // Find "zero light" level and error
00216     //@@ record bias setting used for zero light level
00217     //@@ zero light error changes wrt gain setting ???
00218     float zero_light_level = sistrip::invalid_;
00219     float zero_light_error = sistrip::invalid_;
00220     for ( uint16_t ibin = 0; ibin < nbins; ibin++ ) {
00221       if ( base_entries[ibin] ) { 
00222         zero_light_level = base_contents[ibin];
00223         zero_light_error = base_errors[ibin];
00224         break;
00225       }
00226     }
00227 
00228     float zero_light_thres = sistrip::invalid_;
00229     if ( zero_light_level <= sistrip::maximum_ && 
00230          zero_light_error <= sistrip::maximum_ ) { 
00231       zero_light_thres = zero_light_level + 5. * zero_light_error;
00232     } else {
00233       std::stringstream ss;
00234       ss << sistrip::invalidZeroLightLevel_ << "ForGain" << igain;
00235       anal->addErrorCode( ss.str() );
00236       continue;
00237     }
00238     
00239     // Find range of base histogram
00240     float base_range = base_max - base_min;
00241 
00242     // Find overlapping max/min region that constrains range of linear fit
00243     float max = peak_max < base_max ? peak_max : base_max;
00244     float min = peak_min > base_min ? peak_min : base_min;
00245     float range = max - min;
00246 
00247     // Container identifying whether samples from 'base' histo are above "zero light" 
00248     std::vector<bool> above_zero_light;
00249     above_zero_light.resize(3,true);
00250     
00251     // Linear fits to top of peak and base curves and one to bottom of base curve
00252     sistrip::LinearFit peak_high;
00253     sistrip::LinearFit base_high;
00254     sistrip::LinearFit base_low;
00255 
00256     // Iterate through histogram bins
00257     uint16_t peak_bin = 0;
00258     uint16_t base_bin = 0;
00259     uint16_t low_bin = 0;
00260     for ( uint16_t ibin = 0; ibin < nbins; ibin++ ) {
00261       
00262       // Record whether consecutive samples from 'base' histo are above the "zero light" level
00263       if ( base_entries[ibin] ) {
00264         above_zero_light.erase( above_zero_light.begin() );
00265         if ( base_contents[ibin] > zero_light_thres ) { above_zero_light.push_back( true ); }
00266         else { above_zero_light.push_back( false ); }
00267         if ( above_zero_light.size() != 3 ) { above_zero_light.resize(3,false); } 
00268       }
00269       
00270       // Linear fit to peak histogram
00271       if ( peak_entries[ibin] &&
00272            peak_contents[ibin] > ( min + 0.2*range ) &&
00273            peak_contents[ibin] < ( min + 0.8*range ) ) {
00274         if ( !peak_bin ) { peak_bin = ibin; }
00275         if ( ( ibin - peak_bin ) < 10 ) { 
00276           peak_high.add( ibin, peak_contents[ibin] ); //@@ should weight using bin error or bin contents (sqrt(N)/N)
00277         }
00278       }
00279       // Linear fit to base histogram
00280       if ( base_entries[ibin] &&
00281            base_contents[ibin] > ( min + 0.2*range ) &&
00282            base_contents[ibin] < ( min + 0.8*range ) ) {
00283         if ( !base_bin ) { base_bin = ibin; }
00284         if ( ( ibin - base_bin ) < 10 ) { 
00285           base_high.add( ibin, base_contents[ibin] ); //@@ should weight using bin error or bin contents (sqrt(N)/N)
00286         }
00287       }
00288       // Low linear fit to base histogram
00289       if ( base_entries[ibin] &&
00290            //@@ above_zero_light[0] && above_zero_light[1] && above_zero_light[2] && 
00291            base_contents[ibin] > ( base_min + 0.2*base_range ) &&
00292            base_contents[ibin] < ( base_min + 0.6*base_range ) ) { 
00293         if ( !low_bin ) { low_bin = ibin; }
00294         if ( ( ibin - low_bin ) < 10 ) { 
00295           base_low.add( ibin, base_contents[ibin] ); //@@ should weight using bin error or bin contents (sqrt(N)/N)
00296         }
00297       }
00298       
00299     }
00300     
00301     // Extract width between two curves at midpoint within range
00302     float mid = min + 0.5*range;
00303     sistrip::LinearFit::Params peak_params;
00304     sistrip::LinearFit::Params base_params;
00305     peak_high.fit( peak_params );
00306     base_high.fit( base_params );
00307 
00308     float peak_pos = sistrip::invalid_;
00309     float base_pos = sistrip::invalid_;
00310     float width    = sistrip::invalid_;
00311     if ( peak_params.b_ > 0. ) {
00312       peak_pos = ( mid - peak_params.a_ ) / peak_params.b_;
00313     }
00314     if ( base_params.b_ > 0. ) {
00315       base_pos = ( mid - base_params.a_ ) / base_params.b_;
00316     }
00317     if ( base_pos < sistrip::valid_ &&
00318          peak_pos < sistrip::valid_ ) {
00319       width = base_pos - peak_pos;
00320     }
00321 
00322     // Extrapolate to zero light to find "lift off"
00323     sistrip::LinearFit::Params low_params;
00324     base_low.fit( low_params );
00325     float lift_off = sistrip::invalid_;
00326     if ( low_params.b_ > 0. ) {
00327       lift_off = ( zero_light_level - low_params.a_ ) / low_params.b_;
00328     }
00329     
00330     // ---------- Set all parameters ----------
00331     
00332     // Slope of baseline
00333     if ( low_params.b_ > 0. ) {
00334       anal->baseSlope_[igain] = low_params.b_;
00335     } 
00336     
00337     // Check "lift off" value and set bias setting accordingly
00338     if ( lift_off <= sistrip::maximum_ ) {
00339       anal->bias_[igain] = static_cast<uint16_t>( lift_off ) + 2;
00340     } else { anal->bias_[igain] = OptoScanAnalysis::defaultBiasSetting_; } 
00341     
00342     // Calculate "lift off" (in mA)
00343     if ( lift_off <= sistrip::maximum_ ) {
00344       anal->liftOff_[igain] = 0.45 * lift_off;
00345     }
00346     
00347     // Calculate laser threshold (in mA)
00348     if ( width < sistrip::invalid_ ) {
00349       anal->threshold_[igain] = 0.45 * ( lift_off - width/2. );
00350     }
00351 
00352     // Set "zero light" level
00353     anal->zeroLight_[igain] = zero_light_level;
00354     
00355     // Set link noise
00356     uint16_t bin_number = sistrip::invalid_;
00357     if ( anal->threshold_[igain] < sistrip::valid_ ) {
00358       // Old calculation, used in commissioning in 2008
00359       //   always leads to zero link noise
00360       //   bin_number = static_cast<uint16_t>( anal->threshold_[igain] / 0.45 ); 
00361       // New calculation asked by Karl et al, for commissioning in 2009
00362       bin_number = (uint16_t) (lift_off + width / 3.);
00363     }
00364     if ( bin_number < sistrip::valid_ ) {
00365       if ( bin_number < noise_contents.size() ) { 
00366         anal->linkNoise_[igain] = noise_contents[bin_number]; 
00367       } else { anal->addErrorCode(sistrip::unexpectedBinNumber_); }
00368     }
00369       
00370     // Calculate tick mark height
00371     if ( low_params.b_ <= sistrip::maximum_ &&
00372          width <= sistrip::maximum_ ) {
00373       anal->tickHeight_[igain] = width * low_params.b_;
00374     }
00375       
00376     // Set measured gain 
00377     if ( anal->tickHeight_[igain] < sistrip::invalid_-1. ) {
00378       anal->measGain_[igain] = anal->tickHeight_[igain] * OptoScanAnalysis::fedAdcGain_ / 0.800;
00379     } else { anal->measGain_[igain] = sistrip::invalid_; }
00380       
00381   } // gain loop
00382 
00383   // Iterate through four gain settings and identify optimum gain setting
00384   const float target_gain = targetGain_; //0.863; // changed from 0.8 to avoid choice of low tickheights (Xtof, SL, 15/6/2009)
00385 
00386   float diff_in_gain = sistrip::invalid_;
00387   for ( uint16_t igain = 0; igain < 4; igain++ ) {
00388     
00389     // Check for sensible gain value
00390     if ( anal->measGain_[igain] > sistrip::maximum_ ) { continue; }
00391     
00392     // Find optimum gain setting
00393     if ( fabs( anal->measGain_[igain] - target_gain ) < diff_in_gain ) {
00394       anal->gain_ = igain;
00395       diff_in_gain = fabs( anal->measGain_[igain] - target_gain );
00396     }
00397     
00398   } 
00399   
00400   // Check optimum gain setting
00401   if ( anal->gain_ > sistrip::maximum_ ) { anal->gain_ = OptoScanAnalysis::defaultGainSetting_; }
00402   
00403 }
00404 
00405 // ----------------------------------------------------------------------------
00406 // 
00407 CommissioningAlgorithm::Histo OptoScanAlgorithm::histo( const uint16_t& gain, 
00408                                                         const uint16_t& digital_level ) const {
00409   if ( gain <= 3 && digital_level <= 1 ) { return histos_[gain][digital_level]; }
00410   else { return Histo(0,""); }
00411 }