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
#include "CommonTools/Egamma/interface/EffectiveAreas.h"
#include "FWCore/Utilities/interface/Exception.h"

#include <cmath>
#include <fstream>
#include <string>
#include <sstream>

EffectiveAreas::EffectiveAreas(const std::string& filename, const bool quadraticEAflag)
    : filename_(filename), quadraticEAflag_(quadraticEAflag) {
  // Open the file with the effective area constants
  std::ifstream inputFile;
  inputFile.open(filename_.c_str());
  if (!inputFile.is_open())
    throw cms::Exception("EffectiveAreas config failure") << "failed to open the file " << filename_ << std::endl;

  // Read file line by line
  std::string line;
  const float undef = -999;

  if (!quadraticEAflag_) {
    while (getline(inputFile, line)) {
      if (line[0] == '#')
        continue;  // skip the comments lines
      float etaMin = undef, etaMax = undef, effArea = undef;
      std::stringstream ss(line);
      ss >> etaMin >> etaMax >> effArea;
      // In case if the format is messed up, there are letters
      // instead of numbers, or not exactly three numbers in the line,
      // it is likely that one or more of these vars never changed
      // the original "undef" value:
      if (etaMin == undef || etaMax == undef || effArea == undef)
        throw cms::Exception("EffectiveAreas config failure")
            << "wrong file format, file name " << filename_ << std::endl;

      absEtaMin_.push_back(etaMin);
      absEtaMax_.push_back(etaMax);
      effectiveAreaValues_.push_back(effArea);
    }

  }

  else {
    while (getline(inputFile, line)) {
      if (line[0] == '#')
        continue;  // skip the comments lines

      float etaMin = undef, etaMax = undef;
      float linEffArea = undef, quadEffArea = undef;

      std::stringstream ss(line);

      ss >> etaMin >> etaMax >> linEffArea >> quadEffArea;

      // In case if the format is messed up, there are letters
      // instead of numbers, or not exactly three numbers in the line,
      // it is likely that one or more of these vars never changed
      // the original "undef" value:
      if (etaMin == undef || etaMax == undef || linEffArea == undef || quadEffArea == undef)
        throw cms::Exception("EffectiveAreas config failure")
            << "wrong file format, file name " << filename_ << std::endl;

      absEtaMin_.push_back(etaMin);
      absEtaMax_.push_back(etaMax);
      linearEffectiveAreaValues_.push_back(linEffArea);
      quadraticEffectiveAreaValues_.push_back(quadEffArea);
    }
  }

  // Extra consistency checks are in the function below.
  // If any of them fail, an exception is thrown.
  checkConsistency();
}

// Return effective area for given eta
const float EffectiveAreas::getEffectiveArea(float eta) const {
  float effArea = 0;
  uint nEtaBins = absEtaMin_.size();
  for (uint iEta = 0; iEta < nEtaBins; iEta++) {
    if (std::abs(eta) >= absEtaMin_[iEta] && std::abs(eta) < absEtaMax_[iEta]) {
      effArea = effectiveAreaValues_[iEta];
      break;
    }
  }

  return effArea;
}

// Return linear term of EA for given eta
const float EffectiveAreas::getLinearEA(float eta) const {
  float linEffArea = 0;
  uint nEtaBins = absEtaMin_.size();

  for (uint iEta = 0; iEta < nEtaBins; iEta++) {
    if (std::abs(eta) >= absEtaMin_[iEta] && std::abs(eta) < absEtaMax_[iEta]) {
      linEffArea = linearEffectiveAreaValues_[iEta];
      break;
    }
  }

  return linEffArea;
}

// Return quadratic term of EA for given eta
const float EffectiveAreas::getQuadraticEA(float eta) const {
  float quadEffArea = 0;
  uint nEtaBins = absEtaMin_.size();

  for (uint iEta = 0; iEta < nEtaBins; iEta++) {
    if (std::abs(eta) >= absEtaMin_[iEta] && std::abs(eta) < absEtaMax_[iEta]) {
      quadEffArea = quadraticEffectiveAreaValues_[iEta];
      break;
    }
  }

  return quadEffArea;
}

void EffectiveAreas::printEffectiveAreas() const {
  printf("EffectiveAreas: source file %s\n", filename_.c_str());

  if (!quadraticEAflag_) {
    printf("  eta_min   eta_max    effective area\n");
    uint nEtaBins = absEtaMin_.size();

    for (uint iEta = 0; iEta < nEtaBins; iEta++) {
      printf("  %8.4f    %8.4f   %8.5f\n", absEtaMin_[iEta], absEtaMax_[iEta], effectiveAreaValues_[iEta]);
    }
  }

  else {
    printf("  eta_min   eta_max    EA linear term    EA quadratic term\n");
    uint nEtaBins = absEtaMin_.size();
    for (uint iEta = 0; iEta < nEtaBins; iEta++) {
      printf("  %8.4f    %8.4f   %8.5f    %8.5f\n",
             absEtaMin_[iEta],
             absEtaMax_[iEta],
             linearEffectiveAreaValues_[iEta],
             quadraticEffectiveAreaValues_[iEta]);
    }
  }
}

// Basic common sense checks
void EffectiveAreas::checkConsistency() const {
  // There should be at least one eta range with one constant

  if (!quadraticEAflag_) {
    if (effectiveAreaValues_.empty())
      throw cms::Exception("EffectiveAreas config failure")
          << "found no effective area constants in the file " << filename_ << std::endl;

    uint nEtaBins = absEtaMin_.size();

    for (uint iEta = 0; iEta < nEtaBins; iEta++) {
      // The low limit should be lower than the upper limit
      if (!(absEtaMin_[iEta] < absEtaMax_[iEta]))
        throw cms::Exception("EffectiveAreas config failure")
            << "eta ranges improperly defined (min>max) in the file" << filename_ << std::endl;

      // The low limit of the next range should be (near) equal to the
      // upper limit of the previous range
      if (iEta != nEtaBins - 1)  // don't do the check for the last bin
        if (!(absEtaMin_[iEta + 1] - absEtaMax_[iEta] < 0.0001))
          throw cms::Exception("EffectiveAreas config failure")
              << "eta ranges improperly defined (disjointed) in the file " << filename_ << std::endl;

      // The effective area should be non-negative number,
      // and should be less than the whole calorimeter area
      // eta range -2.5 to 2.5, phi 0 to 2pi => Amax = 5*2*pi ~= 31.4
      if (!(effectiveAreaValues_[iEta] >= 0 && effectiveAreaValues_[iEta] < 31.4))
        throw cms::Exception("EffectiveAreas config failure")
            << "effective area values are too large or negative in the file" << filename_ << std::endl;
    }
  }

  else {
    if (linearEffectiveAreaValues_.empty() || quadraticEffectiveAreaValues_.empty())
      throw cms::Exception("EffectiveAreas config failure")
          << "found no effective area constants (linear and/or quadratic) in the file " << filename_ << std::endl;

    uint nEtaBins = absEtaMin_.size();

    for (uint iEta = 0; iEta < nEtaBins; iEta++) {
      // The low limit should be lower than the upper limit
      if (!(absEtaMin_[iEta] < absEtaMax_[iEta]))
        throw cms::Exception("EffectiveAreas config failure")
            << "eta ranges improperly defined (min>max) in the file" << filename_ << std::endl;

      // The low limit of the next range should be (near) equal to the
      // upper limit of the previous range
      if (iEta != nEtaBins - 1)  // don't do the check for the last bin
        if (!(absEtaMin_[iEta + 1] - absEtaMax_[iEta] < 0.0001))
          throw cms::Exception("EffectiveAreas config failure")
              << "eta ranges improperly defined (disjointed) in the file " << filename_ << std::endl;

      // The linear effective area should be non-negative number,
      // and should be less than the whole calorimeter area
      // eta range -2.5 to 2.5, phi 0 to 2pi => Amax = 5*2*pi ~= 31.4
      if (!(linearEffectiveAreaValues_[iEta] >= 0 && linearEffectiveAreaValues_[iEta] < 31.4))
        throw cms::Exception("EffectiveAreas config failure")
            << "effective area values are too large or negative in the file" << filename_ << std::endl;
    }
  }
}