FTLCluster

FTLHit

FTLHitPos

Shift

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 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
#ifndef DataFormats_FTLRecHit_FTLCluster_h
#define DataFormats_FTLRecHit_FTLCluster_h

/** \class FTLCluster
 *  
 * based on SiPixelCluster
 *
 * \author Paolo Meridiani
 */

#include <cmath>
#include <vector>
#include <cstdint>
#include <cassert>
#include <algorithm>
#include <numeric>

#include "DataFormats/DetId/interface/DetId.h"

class FTLCluster {
public:
  typedef DetId key_type;

  class FTLHit {
  public:
    constexpr FTLHit() : x_(0), y_(0), energy_(0), time_(0), time_error_(0) {}
    constexpr FTLHit(uint16_t hit_x, uint16_t hit_y, float hit_energy, float hit_time, float hit_time_error)
        : x_(hit_x), y_(hit_y), energy_(hit_energy), time_(hit_time), time_error_(hit_time_error) {}
    constexpr uint16_t x() { return x_; }
    constexpr uint16_t y() { return y_; }
    constexpr uint16_t energy() { return energy_; }
    constexpr uint16_t time() { return time_; }
    constexpr uint16_t time_error() { return time_error_; }

  private:
    uint16_t x_;  //row
    uint16_t y_;  //col
    float energy_;
    float time_;
    float time_error_;
  };

  //--- Integer shift in x and y directions.
  class Shift {
  public:
    constexpr Shift(int dx, int dy) : dx_(dx), dy_(dy) {}
    constexpr Shift() : dx_(0), dy_(0) {}
    constexpr int dx() const { return dx_; }
    constexpr int dy() const { return dy_; }

  private:
    int dx_;
    int dy_;
  };

  //--- Position of a FTL Hit
  class FTLHitPos {
  public:
    constexpr FTLHitPos() : row_(0), col_(0) {}
    constexpr FTLHitPos(int row, int col) : row_(row), col_(col) {}
    constexpr int row() const { return row_; }
    constexpr int col() const { return col_; }
    constexpr FTLHitPos operator+(const Shift& shift) const {
      return FTLHitPos(row() + shift.dx(), col() + shift.dy());
    }

  private:
    int row_;
    int col_;
  };

  static constexpr unsigned int MAXSPAN = 255;
  static constexpr unsigned int MAXPOS = 2047;

  /** Construct from a range of digis that form a cluster and from 
   *  a DetID. The range is assumed to be non-empty.
   */
  FTLCluster() {}

  FTLCluster(DetId id,
             unsigned int isize,
             float const* energys,
             float const* times,
             float const* time_errors,
             uint16_t const* xpos,
             uint16_t const* ypos,
             uint16_t const xmin,
             uint16_t const ymin)
      : theid(id),
        theHitOffset(2 * isize),
        theHitENERGY(energys, energys + isize),
        theHitTIME(times, times + isize),
        theHitTIME_ERROR(time_errors, time_errors + isize) {
    uint16_t maxCol = 0;
    uint16_t maxRow = 0;
    int maxHit = -1;
    float maxEnergy = -99999;
    for (unsigned int i = 0; i != isize; ++i) {
      uint16_t xoffset = xpos[i] - xmin;
      uint16_t yoffset = ypos[i] - ymin;
      theHitOffset[i * 2] = std::min(uint16_t(MAXSPAN), xoffset);
      theHitOffset[i * 2 + 1] = std::min(uint16_t(MAXSPAN), yoffset);
      if (xoffset > maxRow)
        maxRow = xoffset;
      if (yoffset > maxCol)
        maxCol = yoffset;
      if (theHitENERGY[i] > maxEnergy) {
        maxHit = i;
        maxEnergy = theHitENERGY[i];
      }
    }
    packRow(xmin, maxRow);
    packCol(ymin, maxCol);

    if (maxHit >= 0)
      seed_ = std::min(uint8_t(MAXSPAN), uint8_t(maxHit));
  }

  // linear average position (barycenter)
  inline float x() const {
    auto x_pos = [this](unsigned int i) { return this->theHitOffset[i * 2] + minHitRow(); };
    return weighted_mean(this->theHitENERGY, x_pos);
  }

  inline float y() const {
    auto y_pos = [this](unsigned int i) { return this->theHitOffset[i * 2 + 1] + minHitCol(); };
    return weighted_mean(this->theHitENERGY, y_pos);
  }

  inline float positionError(const float sigmaPos) const {
    float sumW2(0.f), sumW(0.f);
    for (const auto& hitW : theHitENERGY) {
      sumW2 += hitW * hitW;
      sumW += hitW;
    }
    if (sumW > 0)
      return sigmaPos * std::sqrt(sumW2) / sumW;
    else
      return -999.f;
  }

  inline float time() const {
    auto t = [this](unsigned int i) { return this->theHitTIME[i]; };
    return weighted_mean(this->theHitENERGY, t);
  }

  inline float timeError() const {
    auto t_err = [this](unsigned int i) { return this->theHitTIME_ERROR[i]; };
    return weighted_mean_error(this->theHitENERGY, t_err);
  }

  // Return number of hits.
  inline int size() const { return theHitENERGY.size(); }

  // Return cluster dimension in the x direction.
  inline int sizeX() const { return rowSpan() + 1; }

  // Return cluster dimension in the y direction.
  inline int sizeY() const { return colSpan() + 1; }

  inline float energy() const {
    return std::accumulate(theHitENERGY.begin(), theHitENERGY.end(), 0.f);
  }  // Return total cluster energy.

  inline int minHitRow() const { return theMinHitRow; }             // The min x index.
  inline int maxHitRow() const { return minHitRow() + rowSpan(); }  // The max x index.
  inline int minHitCol() const { return theMinHitCol; }             // The min y index.
  inline int maxHitCol() const { return minHitCol() + colSpan(); }  // The max y index.

  const std::vector<uint8_t>& hitOffset() const { return theHitOffset; }
  const std::vector<float>& hitENERGY() const { return theHitENERGY; }
  const std::vector<float>& hitTIME() const { return theHitTIME; }
  const std::vector<float>& hitTIME_ERROR() const { return theHitTIME_ERROR; }

  // infinite faster than above...
  FTLHit hit(int i) const {
    return FTLHit(minHitRow() + theHitOffset[i * 2],
                  minHitCol() + theHitOffset[i * 2 + 1],
                  theHitENERGY[i],
                  theHitTIME[i],
                  theHitTIME_ERROR[i]);
  }

  FTLHit seed() const { return hit(seed_); }

  int colSpan() const { return theHitColSpan; }

  int rowSpan() const { return theHitRowSpan; }

  const DetId& id() const { return theid; }
  const DetId& detid() const { return id(); }

  bool overflowCol() const { return overflow_(theHitColSpan); }

  bool overflowRow() const { return overflow_(theHitRowSpan); }

  bool overflow() const { return overflowCol() || overflowRow(); }

  void packCol(uint16_t ymin, uint16_t yspan) {
    theMinHitCol = ymin;
    theHitColSpan = std::min(yspan, uint16_t(MAXSPAN));
  }
  void packRow(uint16_t xmin, uint16_t xspan) {
    theMinHitRow = xmin;
    theHitRowSpan = std::min(xspan, uint16_t(MAXSPAN));
  }

  void setClusterPosX(float posx) { pos_x = posx; }
  void setClusterErrorX(float errx) { err_x = errx; }
  void setClusterErrorTime(float errtime) { err_time = errtime; }
  float getClusterPosX() const { return pos_x; }
  float getClusterErrorX() const { return err_x; }
  float getClusterErrorTime() const { return err_time; }

private:
  DetId theid;

  std::vector<uint8_t> theHitOffset;
  std::vector<float> theHitENERGY;
  std::vector<float> theHitTIME;
  std::vector<float> theHitTIME_ERROR;

  uint16_t theMinHitRow = MAXPOS;  // Minimum hit index in the x direction (low edge).
  uint16_t theMinHitCol = MAXPOS;  // Minimum hit index in the y direction (left edge).
  uint8_t theHitRowSpan = 0;       // Span hit index in the x direction (low edge).
  uint8_t theHitColSpan = 0;       // Span hit index in the y direction (left edge).

  float pos_x = -99999.9f;  // For pixels with internal position information in one coordinate (i.e. BTL crystals)
  float err_x = -99999.9f;  // For pixels with internal position information in one coordinate (i.e. BTL crystals)
  float err_time = -99999.9f;

  uint8_t seed_;

  template <typename SumFunc, typename OutFunc>
  float weighted_sum(const std::vector<float>& weights, SumFunc&& sumFunc, OutFunc&& outFunc) const {
    float tot = 0;
    float sumW = 0;
    for (unsigned int i = 0; i < weights.size(); ++i) {
      tot += sumFunc(i);
      sumW += weights[i];
    }
    return outFunc(tot, sumW);
  }

  template <typename Value>
  float weighted_mean(const std::vector<float>& weights, Value&& value) const {
    auto sumFunc = [&weights, value](unsigned int i) { return weights[i] * value(i); };
    auto outFunc = [](float x, float y) {
      if (y > 0)
        return (float)x / y;
      else
        return -999.f;
    };
    return weighted_sum(weights, sumFunc, outFunc);
  }

  template <typename Err>
  float weighted_mean_error(const std::vector<float>& weights, Err&& err) const {
    auto sumFunc = [&weights, err](unsigned int i) { return weights[i] * weights[i] * err(i) * err(i); };
    auto outFunc = [](float x, float y) {
      if (y > 0)
        return (float)sqrt(x) / y;
      else
        return -999.f;
    };
    return weighted_sum(weights, sumFunc, outFunc);
  }

  static int overflow_(uint16_t span) { return span == uint16_t(MAXSPAN); }
};

// Comparison operators  (needed by DetSetVector & SortedCollection )
inline bool operator<(const FTLCluster& one, const FTLCluster& other) {
  if (one.detid() == other.detid()) {
    if (one.minHitRow() < other.minHitRow()) {
      return true;
    } else if (one.minHitRow() > other.minHitRow()) {
      return false;
    } else if (one.minHitCol() < other.minHitCol()) {
      return true;
    } else {
      return false;
    }
  }
  return one.detid() < other.detid();
}

inline bool operator<(const FTLCluster& one, const uint32_t& detid) { return one.detid() < detid; }

inline bool operator<(const uint32_t& detid, const FTLCluster& other) { return detid < other.detid(); }

#endif