Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-01-21 01:39:40

0001 #ifndef DATAFORMATS_SISTRIPCLUSTER_H
0002 #define DATAFORMATS_SISTRIPCLUSTER_H
0003 
0004 #include "DataFormats/SiStripDigi/interface/SiStripDigi.h"
0005 #include "DataFormats/SiStripCluster/interface/SiStripApproximateCluster.h"
0006 #include <vector>
0007 #include <numeric>
0008 #include <iostream>
0009 
0010 class SiStripApproximateCluster;
0011 
0012 class SiStripCluster {
0013 public:
0014   typedef std::vector<SiStripDigi>::const_iterator SiStripDigiIter;
0015   typedef std::pair<SiStripDigiIter, SiStripDigiIter> SiStripDigiRange;
0016 
0017   static const uint16_t stripIndexMask = 0x3FFF;   // The first strip index is in the low 15 bits of firstStrip_
0018   static const uint16_t mergedValueMask = 0x8000;  // The merged state is given by the high bit of firstStrip_
0019   static const uint16_t approximateMask = 0x4000;  // The approximate state is the high-1 bit of firstStrip_
0020 
0021   /** Construct from a range of digis that form a cluster and from 
0022    *  a DetID. The range is assumed to be non-empty.
0023    */
0024 
0025   SiStripCluster() {}
0026 
0027   explicit SiStripCluster(const SiStripDigiRange& range);
0028 
0029   SiStripCluster(uint16_t firstStrip, std::vector<uint8_t>&& data)
0030       : amplitudes_(std::move(data)), firstStrip_(firstStrip) {
0031     initQB();
0032   }
0033 
0034   template <typename Iter>
0035   SiStripCluster(const uint16_t& firstStrip, Iter begin, Iter end) : amplitudes_(begin, end), firstStrip_(firstStrip) {
0036     initQB();
0037   }
0038 
0039   template <typename Iter>
0040   SiStripCluster(const uint16_t& firstStrip, Iter begin, Iter end, bool merged)
0041       : amplitudes_(begin, end), firstStrip_(firstStrip) {
0042     if (merged)
0043       firstStrip_ |= mergedValueMask;  // if this is a candidate merged cluster
0044     initQB();
0045   }
0046 
0047   SiStripCluster(const SiStripApproximateCluster cluster, const uint16_t maxStrips);
0048 
0049   // extend the cluster
0050   template <typename Iter>
0051   void extend(Iter begin, Iter end) {
0052     amplitudes_.insert(amplitudes_.end(), begin, end);
0053     initQB();
0054   }
0055 
0056   /** The amplitudes of the strips forming the cluster.
0057    *  The amplitudes are on consecutive strips; if a strip is missing
0058    *  the amplitude is set to zero.
0059    *  A strip may be missing in the middle of a cluster because of a
0060    *  clusterizer that accepts holes.
0061    *  A strip may also be missing anywhere in the cluster, including the 
0062    *  edge, to record a dead/noisy channel.
0063    *
0064    *  You can find the special meanings of values { 0, 254, 255} in section 3.4.1 of
0065    *  http://www.te.rl.ac.uk/esdg/cms-fed/firmware/Documents/FE_FPGA_Technical_Description.pdf
0066    */
0067   auto size() const { return amplitudes_.size(); }
0068   auto const* begin() const { return amplitudes_.data(); }
0069   auto const* end() const { return begin() + size(); }
0070   auto operator[](int i) const { return *(begin() + i); }
0071   bool empty() const { return amplitudes_.empty(); }
0072   bool full() const { return false; }
0073 
0074   SiStripCluster const& amplitudes() const { return *this; }
0075 
0076   /** The number of the first strip in the cluster.
0077    *  The high bit of firstStrip_ indicates whether the cluster is a candidate for being merged.
0078    */
0079   uint16_t firstStrip() const { return firstStrip_ & stripIndexMask; }
0080   uint16_t endStrip() const { return firstStrip() + size(); }
0081 
0082   /** The barycenter of the cluster, not corrected for Lorentz shift;
0083    *  should not be used as position estimate for tracking.
0084    */
0085   float barycenter() const { return barycenter_; }
0086 
0087   /** total charge
0088    *
0089    */
0090   int charge() const { return charge_; }
0091 
0092   bool filter() const { return filter_; }
0093 
0094   bool isFromApprox() const { return (firstStrip_ & approximateMask) != 0; }
0095 
0096   /** Test (set) the merged status of the cluster
0097    *
0098    */
0099   bool isMerged() const { return (firstStrip_ & mergedValueMask) != 0; }
0100   void setMerged(bool mergedState) { mergedState ? firstStrip_ |= mergedValueMask : firstStrip_ &= stripIndexMask; }
0101 
0102   float getSplitClusterError() const { return error_x; }
0103   void setSplitClusterError(float errx) { error_x = errx; }
0104 
0105   void initQB();
0106 
0107 private:
0108   std::vector<uint8_t> amplitudes_;
0109 
0110   uint16_t firstStrip_ = 0;
0111 
0112   //these are used if amplitude information is not available (using approximate cluster constructor)
0113   float barycenter_ = 0;
0114   int charge_ = 0;
0115   bool filter_ = false;
0116 
0117   // ggiurgiu@fnal.gov, 01/05/12
0118   // Add cluster errors to be used by rechits from split clusters.
0119   // A rechit from a split cluster has larger errors than rechits from normal clusters.
0120   // However, when presented with a cluster, the CPE does not know if the cluster comes
0121   // from a splitting procedure or not. That's why we have to instruct the CPE to use
0122   // appropriate errors for split clusters.
0123   // To avoid increase of data size on disk,these new data members are set as transient in:
0124   // DataFormats/SiStripCluster/src/classes_def.xml
0125   float error_x = -99999.9;
0126 
0127   // ggiurgiu@fnal.gov, 01/05/12
0128   // Initialize the split cluster errors to un-physical values.
0129   // The CPE will check these errors and if they are not un-physical,
0130   // it will recognize the clusters as split and assign these (increased)
0131   // errors to the corresponding rechit.
0132 };
0133 
0134 // Comparison operators
0135 inline bool operator<(const SiStripCluster& one, const SiStripCluster& other) {
0136   return one.firstStrip() < other.firstStrip();
0137 }
0138 
0139 inline bool operator<(const SiStripCluster& cluster, const uint16_t& firstStrip) {
0140   return cluster.firstStrip() < firstStrip;
0141 }
0142 
0143 inline bool operator<(const uint16_t& firstStrip, const SiStripCluster& cluster) {
0144   return firstStrip < cluster.firstStrip();
0145 }
0146 
0147 inline void SiStripCluster::initQB() {
0148   int sumx = 0;
0149   int suma = 0;
0150   auto asize = size();
0151   for (auto i = 0U; i < asize; ++i) {
0152     sumx += i * amplitudes_[i];
0153     suma += amplitudes_[i];
0154   }
0155   charge_ = suma;
0156 
0157   // strip centers are offset by half pitch w.r.t. strip numbers,
0158   // so one has to add 0.5 to get the correct barycenter position.
0159   // Need to mask off the high bit of firstStrip_, which contains the merged status.
0160   barycenter_ = float((firstStrip_ & stripIndexMask)) + float(sumx) / float(suma) + 0.5f;
0161 }
0162 
0163 #endif  // DATAFORMATS_SISTRIPCLUSTER_H