SiStripCluster

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
#ifndef DATAFORMATS_SISTRIPCLUSTER_H
#define DATAFORMATS_SISTRIPCLUSTER_H

#include "DataFormats/SiStripDigi/interface/SiStripDigi.h"
#include "DataFormats/SiStripCluster/interface/SiStripApproximateCluster.h"
#include <vector>
#include <numeric>
#include <iostream>

class SiStripApproximateCluster;

class SiStripCluster {
public:
  typedef std::vector<SiStripDigi>::const_iterator SiStripDigiIter;
  typedef std::pair<SiStripDigiIter, SiStripDigiIter> SiStripDigiRange;

  static const uint16_t stripIndexMask = 0x3FFF;   // The first strip index is in the low 15 bits of firstStrip_
  static const uint16_t mergedValueMask = 0x8000;  // The merged state is given by the high bit of firstStrip_
  static const uint16_t approximateMask = 0x4000;  // The approximate state is the high-1 bit of firstStrip_

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

  SiStripCluster() {}

  explicit SiStripCluster(const SiStripDigiRange& range);

  SiStripCluster(uint16_t firstStrip, std::vector<uint8_t>&& data)
      : amplitudes_(std::move(data)), firstStrip_(firstStrip) {
    initQB();
  }

  template <typename Iter>
  SiStripCluster(const uint16_t& firstStrip, Iter begin, Iter end) : amplitudes_(begin, end), firstStrip_(firstStrip) {
    initQB();
  }

  template <typename Iter>
  SiStripCluster(const uint16_t& firstStrip, Iter begin, Iter end, bool merged)
      : amplitudes_(begin, end), firstStrip_(firstStrip) {
    if (merged)
      firstStrip_ |= mergedValueMask;  // if this is a candidate merged cluster
    initQB();
  }

  SiStripCluster(const SiStripApproximateCluster cluster, const uint16_t maxStrips);

  // extend the cluster
  template <typename Iter>
  void extend(Iter begin, Iter end) {
    amplitudes_.insert(amplitudes_.end(), begin, end);
    initQB();
  }

  /** The amplitudes of the strips forming the cluster.
   *  The amplitudes are on consecutive strips; if a strip is missing
   *  the amplitude is set to zero.
   *  A strip may be missing in the middle of a cluster because of a
   *  clusterizer that accepts holes.
   *  A strip may also be missing anywhere in the cluster, including the 
   *  edge, to record a dead/noisy channel.
   *
   *  You can find the special meanings of values { 0, 254, 255} in section 3.4.1 of
   *  http://www.te.rl.ac.uk/esdg/cms-fed/firmware/Documents/FE_FPGA_Technical_Description.pdf
   */
  auto size() const { return amplitudes_.size(); }
  auto const* begin() const { return amplitudes_.data(); }
  auto const* end() const { return begin() + size(); }
  auto operator[](int i) const { return *(begin() + i); }
  bool empty() const { return amplitudes_.empty(); }
  bool full() const { return false; }

  SiStripCluster const& amplitudes() const { return *this; }

  /** The number of the first strip in the cluster.
   *  The high bit of firstStrip_ indicates whether the cluster is a candidate for being merged.
   */
  uint16_t firstStrip() const { return firstStrip_ & stripIndexMask; }
  uint16_t endStrip() const { return firstStrip() + size(); }

  /** The barycenter of the cluster, not corrected for Lorentz shift;
   *  should not be used as position estimate for tracking.
   */
  float barycenter() const { return barycenter_; }

  /** total charge
   *
   */
  int charge() const { return charge_; }

  bool filter() const { return filter_; }

  bool isFromApprox() const { return (firstStrip_ & approximateMask) != 0; }

  /** Test (set) the merged status of the cluster
   *
   */
  bool isMerged() const { return (firstStrip_ & mergedValueMask) != 0; }
  void setMerged(bool mergedState) { mergedState ? firstStrip_ |= mergedValueMask : firstStrip_ &= stripIndexMask; }

  float getSplitClusterError() const { return error_x; }
  void setSplitClusterError(float errx) { error_x = errx; }

  void initQB();

private:
  std::vector<uint8_t> amplitudes_;

  uint16_t firstStrip_ = 0;

  //these are used if amplitude information is not available (using approximate cluster constructor)
  float barycenter_ = 0;
  int charge_ = 0;
  bool filter_ = false;

  // ggiurgiu@fnal.gov, 01/05/12
  // Add cluster errors to be used by rechits from split clusters.
  // A rechit from a split cluster has larger errors than rechits from normal clusters.
  // However, when presented with a cluster, the CPE does not know if the cluster comes
  // from a splitting procedure or not. That's why we have to instruct the CPE to use
  // appropriate errors for split clusters.
  // To avoid increase of data size on disk,these new data members are set as transient in:
  // DataFormats/SiStripCluster/src/classes_def.xml
  float error_x = -99999.9;

  // ggiurgiu@fnal.gov, 01/05/12
  // Initialize the split cluster errors to un-physical values.
  // The CPE will check these errors and if they are not un-physical,
  // it will recognize the clusters as split and assign these (increased)
  // errors to the corresponding rechit.
};

// Comparison operators
inline bool operator<(const SiStripCluster& one, const SiStripCluster& other) {
  return one.firstStrip() < other.firstStrip();
}

inline bool operator<(const SiStripCluster& cluster, const uint16_t& firstStrip) {
  return cluster.firstStrip() < firstStrip;
}

inline bool operator<(const uint16_t& firstStrip, const SiStripCluster& cluster) {
  return firstStrip < cluster.firstStrip();
}

inline void SiStripCluster::initQB() {
  int sumx = 0;
  int suma = 0;
  auto asize = size();
  for (auto i = 0U; i < asize; ++i) {
    sumx += i * amplitudes_[i];
    suma += amplitudes_[i];
  }
  charge_ = suma;

  // strip centers are offset by half pitch w.r.t. strip numbers,
  // so one has to add 0.5 to get the correct barycenter position.
  // Need to mask off the high bit of firstStrip_, which contains the merged status.
  barycenter_ = float((firstStrip_ & stripIndexMask)) + float(sumx) / float(suma) + 0.5f;
}

#endif  // DATAFORMATS_SISTRIPCLUSTER_H