Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 10:39:19

0001 
0002 
0003 #include "Alignment/LaserAlignment/interface/LASProfileJudge.h"
0004 
0005 // terminal colors
0006 #define _R "\033[1;31m"
0007 #define _B "\033[1;34m"
0008 #define _G "\033[1;32m"
0009 #define _N "\033[22;30m"
0010 
0011 ///
0012 ///
0013 ///
0014 LASProfileJudge::LASProfileJudge() : overdriveThreshold(0) {
0015   // switch on the zero filter by default
0016   isZeroFilter = true;
0017 }
0018 
0019 ///
0020 /// Check if a LASModuleProfile indicates that the module has been hit,
0021 /// i.e. contains a visible signal or is even distorted by too high laser amplitude.
0022 /// This method doesn't care if the profile is usable for analysis.
0023 ///
0024 bool LASProfileJudge::IsSignalIn(const LASModuleProfile& aProfile, double offset) {
0025   profile = aProfile;
0026 
0027   // need only approx values, so cast here to use integers throughout
0028   const int approxOffset = static_cast<int>(offset);
0029 
0030   const double negativity = GetNegativity(approxOffset);
0031   const bool isPeaks = IsPeaksInProfile(approxOffset);
0032   const bool isNegativePeaks = IsNegativePeaksInProfile(approxOffset);
0033 
0034   bool result = (negativity < -1000.) ||  // if we see negativity, there was laser..
0035                 (isPeaks) ||              // if we see a peak, " " "
0036                 (isNegativePeaks);        // same here
0037 
0038   return (result);
0039 }
0040 
0041 ///
0042 /// Check if a LASModuleProfile is usable for being stored,
0043 /// i.e. contains a visible signal & no baseline distortions
0044 ///
0045 bool LASProfileJudge::JudgeProfile(const LASModuleProfile& aProfile, double offset = 0.) {
0046   profile = aProfile;
0047 
0048   // need only approx values, so cast here to use integers throughout
0049   const int approxOffset = static_cast<int>(offset);
0050 
0051   // run the tests
0052   const double negativity = GetNegativity(approxOffset);
0053 
0054   bool isPeaks;
0055   if (!isZeroFilter)
0056     isPeaks = true;  // disable this test if set in cfg
0057   else
0058     isPeaks = IsPeaksInProfile(approxOffset);
0059 
0060   const bool isNegativePeaks = IsNegativePeaksInProfile(approxOffset);
0061 
0062   bool isOverdrive;  // disable this test if set in cfg
0063   if (!isZeroFilter)
0064     isOverdrive = false;
0065   else
0066     isOverdrive = IsOverdrive(approxOffset);
0067 
0068   bool result = (negativity > -1000.) &&  // < 1000. = distorted profile
0069                 (isPeaks) &&              // want to see a peak (zero filter)
0070                 !(isNegativePeaks) &&     // no negative peaks
0071                 !(isOverdrive);           // no overdrive
0072 
0073   return (result);
0074 }
0075 
0076 ///
0077 /// toggle the zero filter (passed from cfg file)
0078 ///
0079 void LASProfileJudge::EnableZeroFilter(bool zeroFilter) {
0080   if (!zeroFilter) {
0081     std::cerr << " [LASProfileJudge::EnableZeroFilter] ** WARNING: Zero filter has been disabled." << std::endl;
0082   }
0083 
0084   isZeroFilter = zeroFilter;
0085 }
0086 
0087 ///
0088 /// set the threshold for overdriven profiles (passed from cfg file)
0089 ///
0090 void LASProfileJudge::SetOverdriveThreshold(unsigned int aThreshold) { overdriveThreshold = aThreshold; }
0091 
0092 ///
0093 /// In case of too high laser intensities, the APV baselines tend
0094 /// to drop down. here, the strip amplitudes in the area around the
0095 /// signal region are summed to return a variable which can indicate this.
0096 ///
0097 double LASProfileJudge::GetNegativity(int offset) {
0098   // here we could later run the sum only on the affected (pair of) APV
0099 
0100   // expected beam position (in strips)
0101   const unsigned int meanPosition = 256 + offset;
0102   // backplane "alignment hole" (="signal region") approx. half size
0103   const unsigned int halfWindowSize = 33;
0104   // half size of range over which is summed (must be > halfWindowSize)
0105   const unsigned int sumHalfRange = 128;
0106 
0107   double neg = 0;
0108 
0109   // need only x values, so cast here
0110   for (unsigned int i = meanPosition - sumHalfRange; i < meanPosition - halfWindowSize; ++i) {
0111     neg += profile.GetValue(i);
0112   }
0113 
0114   for (unsigned int i = meanPosition + halfWindowSize; i < meanPosition + sumHalfRange; ++i) {
0115     neg += profile.GetValue(i);
0116   }
0117 
0118   return (neg);
0119 }
0120 
0121 ///
0122 /// If the laser intensity is too small, there's no peak at all.
0123 /// Here we look if any strip is well above noise level.
0124 ///
0125 bool LASProfileJudge::IsPeaksInProfile(int offset) {
0126   // expected beam position (in strips)
0127   const unsigned int meanPosition = 256 + offset;
0128   // backplane "alignment hole" approx. half size (in strips)
0129   const unsigned int halfWindowSize = 33;
0130 
0131   bool returnValue = false;
0132 
0133   // calculate average out-of-signal
0134   double average = 0., counterD = 0.;
0135   for (unsigned int strip = 0; strip < 512; ++strip) {
0136     if (strip < meanPosition - halfWindowSize || strip > meanPosition + halfWindowSize) {
0137       average += profile.GetValue(strip);
0138       counterD += 1.;
0139     }
0140   }
0141   average /= counterD;
0142 
0143   // find peaks well above noise level
0144   const double noiseLevel = 2.;  // to be softcoded..
0145   for (unsigned int strip = meanPosition - halfWindowSize; strip < meanPosition + halfWindowSize; ++strip) {
0146     if (profile.GetValue(strip) > (average + 10. * noiseLevel)) {
0147       returnValue = true;
0148       thePeak.first = strip;
0149       thePeak.second = profile.GetValue(strip);
0150       break;
0151     }
0152   }
0153 
0154   return (returnValue);
0155 }
0156 
0157 ///
0158 /// sometimes when the laser intensity is too high the APVs get confused
0159 /// and a negative peak (dip) shows up. this is filtered here.
0160 ///
0161 bool LASProfileJudge::IsNegativePeaksInProfile(int offset) {
0162   // expected beam position in middle of module (in strips)
0163   const unsigned int meanPosition = 256 + offset;
0164   // backplane "alignment hole" approx. half size (in strips)
0165   const unsigned int halfWindowSize = 33;
0166 
0167   bool returnValue = false;
0168 
0169   // calculate average out-of-signal
0170   double average = 0., counterD = 0.;
0171   for (unsigned int strip = 0; strip < 512; ++strip) {
0172     if (strip < meanPosition - halfWindowSize || strip > meanPosition + halfWindowSize) {
0173       average += profile.GetValue(strip);
0174       counterD += 1.;
0175     }
0176   }
0177   average /= counterD;
0178 
0179   // find strips with negative amplitude way above noise level
0180   const double noiseLevel = 2.;
0181   for (unsigned int strip = 0; strip < 512; ++strip) {
0182     if (profile.GetValue(strip) < (average - 10. * noiseLevel)) {
0183       returnValue = true;
0184       thePeak.first = strip;
0185       thePeak.second = profile.GetValue(strip);
0186       break;
0187     }
0188   }
0189 
0190   return (returnValue);
0191 }
0192 
0193 ///
0194 /// check if peak in signal region is too high;
0195 /// this can cause baseline distortions and therefore position bias
0196 ///
0197 bool LASProfileJudge::IsOverdrive(int offset) {
0198   // expected beam position in middle of module (in strips)
0199   const unsigned int meanPosition = 256 + offset;
0200   // backplane "alignment hole" approx. half size (in strips)
0201   const unsigned int halfWindowSize = 33;
0202 
0203   // find maximum strip amplitude in range
0204   for (unsigned int strip = meanPosition - halfWindowSize; strip < meanPosition + halfWindowSize; ++strip) {
0205     if (profile.GetValue(strip) > overdriveThreshold)
0206       return true;
0207   }
0208 
0209   return false;
0210 }