Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210


#include "Alignment/LaserAlignment/interface/LASProfileJudge.h"

// terminal colors
#define _R "\033[1;31m"
#define _B "\033[1;34m"
#define _G "\033[1;32m"
#define _N "\033[22;30m"

///
///
///
LASProfileJudge::LASProfileJudge() : overdriveThreshold(0) {
  // switch on the zero filter by default
  isZeroFilter = true;
}

///
/// Check if a LASModuleProfile indicates that the module has been hit,
/// i.e. contains a visible signal or is even distorted by too high laser amplitude.
/// This method doesn't care if the profile is usable for analysis.
///
bool LASProfileJudge::IsSignalIn(const LASModuleProfile& aProfile, double offset) {
  profile = aProfile;

  // need only approx values, so cast here to use integers throughout
  const int approxOffset = static_cast<int>(offset);

  const double negativity = GetNegativity(approxOffset);
  const bool isPeaks = IsPeaksInProfile(approxOffset);
  const bool isNegativePeaks = IsNegativePeaksInProfile(approxOffset);

  bool result = (negativity < -1000.) ||  // if we see negativity, there was laser..
                (isPeaks) ||              // if we see a peak, " " "
                (isNegativePeaks);        // same here

  return (result);
}

///
/// Check if a LASModuleProfile is usable for being stored,
/// i.e. contains a visible signal & no baseline distortions
///
bool LASProfileJudge::JudgeProfile(const LASModuleProfile& aProfile, double offset = 0.) {
  profile = aProfile;

  // need only approx values, so cast here to use integers throughout
  const int approxOffset = static_cast<int>(offset);

  // run the tests
  const double negativity = GetNegativity(approxOffset);

  bool isPeaks;
  if (!isZeroFilter)
    isPeaks = true;  // disable this test if set in cfg
  else
    isPeaks = IsPeaksInProfile(approxOffset);

  const bool isNegativePeaks = IsNegativePeaksInProfile(approxOffset);

  bool isOverdrive;  // disable this test if set in cfg
  if (!isZeroFilter)
    isOverdrive = false;
  else
    isOverdrive = IsOverdrive(approxOffset);

  bool result = (negativity > -1000.) &&  // < 1000. = distorted profile
                (isPeaks) &&              // want to see a peak (zero filter)
                !(isNegativePeaks) &&     // no negative peaks
                !(isOverdrive);           // no overdrive

  return (result);
}

///
/// toggle the zero filter (passed from cfg file)
///
void LASProfileJudge::EnableZeroFilter(bool zeroFilter) {
  if (!zeroFilter) {
    std::cerr << " [LASProfileJudge::EnableZeroFilter] ** WARNING: Zero filter has been disabled." << std::endl;
  }

  isZeroFilter = zeroFilter;
}

///
/// set the threshold for overdriven profiles (passed from cfg file)
///
void LASProfileJudge::SetOverdriveThreshold(unsigned int aThreshold) { overdriveThreshold = aThreshold; }

///
/// In case of too high laser intensities, the APV baselines tend
/// to drop down. here, the strip amplitudes in the area around the
/// signal region are summed to return a variable which can indicate this.
///
double LASProfileJudge::GetNegativity(int offset) {
  // here we could later run the sum only on the affected (pair of) APV

  // expected beam position (in strips)
  const unsigned int meanPosition = 256 + offset;
  // backplane "alignment hole" (="signal region") approx. half size
  const unsigned int halfWindowSize = 33;
  // half size of range over which is summed (must be > halfWindowSize)
  const unsigned int sumHalfRange = 128;

  double neg = 0;

  // need only x values, so cast here
  for (unsigned int i = meanPosition - sumHalfRange; i < meanPosition - halfWindowSize; ++i) {
    neg += profile.GetValue(i);
  }

  for (unsigned int i = meanPosition + halfWindowSize; i < meanPosition + sumHalfRange; ++i) {
    neg += profile.GetValue(i);
  }

  return (neg);
}

///
/// If the laser intensity is too small, there's no peak at all.
/// Here we look if any strip is well above noise level.
///
bool LASProfileJudge::IsPeaksInProfile(int offset) {
  // expected beam position (in strips)
  const unsigned int meanPosition = 256 + offset;
  // backplane "alignment hole" approx. half size (in strips)
  const unsigned int halfWindowSize = 33;

  bool returnValue = false;

  // calculate average out-of-signal
  double average = 0., counterD = 0.;
  for (unsigned int strip = 0; strip < 512; ++strip) {
    if (strip < meanPosition - halfWindowSize || strip > meanPosition + halfWindowSize) {
      average += profile.GetValue(strip);
      counterD += 1.;
    }
  }
  average /= counterD;

  // find peaks well above noise level
  const double noiseLevel = 2.;  // to be softcoded..
  for (unsigned int strip = meanPosition - halfWindowSize; strip < meanPosition + halfWindowSize; ++strip) {
    if (profile.GetValue(strip) > (average + 10. * noiseLevel)) {
      returnValue = true;
      thePeak.first = strip;
      thePeak.second = profile.GetValue(strip);
      break;
    }
  }

  return (returnValue);
}

///
/// sometimes when the laser intensity is too high the APVs get confused
/// and a negative peak (dip) shows up. this is filtered here.
///
bool LASProfileJudge::IsNegativePeaksInProfile(int offset) {
  // expected beam position in middle of module (in strips)
  const unsigned int meanPosition = 256 + offset;
  // backplane "alignment hole" approx. half size (in strips)
  const unsigned int halfWindowSize = 33;

  bool returnValue = false;

  // calculate average out-of-signal
  double average = 0., counterD = 0.;
  for (unsigned int strip = 0; strip < 512; ++strip) {
    if (strip < meanPosition - halfWindowSize || strip > meanPosition + halfWindowSize) {
      average += profile.GetValue(strip);
      counterD += 1.;
    }
  }
  average /= counterD;

  // find strips with negative amplitude way above noise level
  const double noiseLevel = 2.;
  for (unsigned int strip = 0; strip < 512; ++strip) {
    if (profile.GetValue(strip) < (average - 10. * noiseLevel)) {
      returnValue = true;
      thePeak.first = strip;
      thePeak.second = profile.GetValue(strip);
      break;
    }
  }

  return (returnValue);
}

///
/// check if peak in signal region is too high;
/// this can cause baseline distortions and therefore position bias
///
bool LASProfileJudge::IsOverdrive(int offset) {
  // expected beam position in middle of module (in strips)
  const unsigned int meanPosition = 256 + offset;
  // backplane "alignment hole" approx. half size (in strips)
  const unsigned int halfWindowSize = 33;

  // find maximum strip amplitude in range
  for (unsigned int strip = meanPosition - halfWindowSize; strip < meanPosition + halfWindowSize; ++strip) {
    if (profile.GetValue(strip) > overdriveThreshold)
      return true;
  }

  return false;
}