CMS 3D CMS Logo

PixelThresholdClusterizerForBricked.cc
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7 
8 // Our own includes
10 #include "SiPixelArrayBuffer.h"
12 // Geometry
15 //#include "Geometry/CommonTopologies/RectangularPixelTopology.h"
16 
17 // STL
18 #include <stack>
19 #include <vector>
20 #include <iostream>
21 #include <atomic>
22 #include <algorithm>
23 #include <limits>
24 
25 //----------------------------------------------------------------------------
29 //----------------------------------------------------------------------------
31  : PixelThresholdClusterizer(conf) {}
34 
35 //----------------------------------------------------------------------------
41 //----------------------------------------------------------------------------
42 template <typename T>
44  const PixelGeomDetUnit* pixDet,
45  const TrackerTopology* tTopo,
46  const std::vector<short>& badChannels,
48  typename T::const_iterator begin = input.begin();
49  typename T::const_iterator end = input.end();
50 
51  edm::LogInfo("PixelThresholdClusterizerForBricked::clusterizeDetUnitT()");
52 
53  // this should never happen and the raw2digi does not create empty detsets
54  if (begin == end) {
55  edm::LogError("PixelThresholdClusterizerForBricked")
56  << "@SUB=PixelThresholdClusterizerForBricked::clusterizeDetUnitT()"
57  << " No digis to clusterize";
58  }
59 
60  // Set up the clusterization on this DetId.
61  if (!setup(pixDet))
62  return;
63 
64  theDetid = input.detId();
65 
67  // Set separate cluster threshold for L1 (needed for phase1)
69  theLayer = (DetId(theDetid).subdetId() == 1) ? tTopo->pxbLayer(theDetid) : 0;
70  if (theLayer == 1)
72 
73  // Copy PixelDigis to the buffer array; select the seed pixels
74  // on the way, and store them in theSeeds.
75  if (end > begin)
76  copy_to_buffer(begin, end);
77 
78  assert(output.empty());
79  // Loop over all seeds. TO DO: wouldn't using iterators be faster?
80  for (unsigned int i = 0; i < theSeeds.size(); i++) {
81  // Gavril : The charge of seeds that were already inlcuded in clusters is set to 1 electron
82  // so we don't want to call "make_cluster" for these cases
83  if (theBuffer(theSeeds[i]) >= theSeedThreshold) { // Is this seed still valid?
84  // Make a cluster around this seed
85  SiPixelCluster cluster;
86  if ((&pixDet->specificTopology())->isBricked()) {
88  } else {
89  cluster = make_cluster(theSeeds[i], output);
90  }
91 
92  // Check if the cluster is above threshold
93  // (TO DO: one is signed, other unsigned, gcc warns...)
94  if (cluster.charge() >= clusterThreshold) {
95  // sort by row (x)
96  output.push_back(std::move(cluster));
97  std::push_heap(output.begin(), output.end(), [](SiPixelCluster const& cl1, SiPixelCluster const& cl2) {
98  return cl1.minPixelRow() < cl2.minPixelRow();
99  });
100  }
101  }
102  }
103  // sort by row (x) maybe sorting the seed would suffice....
104  std::sort_heap(output.begin(), output.end(), [](SiPixelCluster const& cl1, SiPixelCluster const& cl2) {
105  return cl1.minPixelRow() < cl2.minPixelRow();
106  });
107 
108  // Erase the seeds.
109  theSeeds.clear();
110 
111  // Need to clean unused pixels from the buffer array.
112  clear_buffer(begin, end);
113 
114  theFakePixels.clear();
115 }
116 
117 //----------------------------------------------------------------------------
119 //----------------------------------------------------------------------------
122  //First we acquire the seeds for the clusters
123  std::stack<SiPixelCluster::PixelPos, std::vector<SiPixelCluster::PixelPos> > dead_pixel_stack;
124 
125  //The individual modules have been loaded into a buffer.
126  //After each pixel has been considered by the clusterizer, we set the adc count to 1
127  //to mark that we have already considered it.
128  //The only difference between dead/noisy pixels and standard ones is that for dead/noisy pixels,
129  //We consider the charge of the pixel to always be zero.
130 
131  // Note: each ADC value is limited here to 65535 (std::numeric_limits<uint16_t>::max),
132  // as it is later stored as uint16_t in SiPixelCluster and PixelClusterizerBase/AccretionCluster
133  // (reminder: ADC values here may be expressed in number of electrons)
134  uint16_t seed_adc = std::min(theBuffer(pix.row(), pix.col()), int(std::numeric_limits<uint16_t>::max()));
135  theBuffer.set_adc(pix, 1);
136 
137  AccretionCluster acluster;
138  acluster.add(pix, seed_adc);
139 
140  //Here we search all pixels adjacent to all pixels in the cluster.
141  bool dead_flag = false;
142  while (!acluster.empty()) {
143  //This is the standard algorithm to find and add a pixel
144  auto curInd = acluster.top();
145  acluster.pop();
146 
147  for (auto r = std::max(0, int(acluster.x[curInd]) - 1); r < std::min(int(acluster.x[curInd]) + 2, theBuffer.rows());
148  ++r) {
149  int LowerAccLimity = 0;
150  int UpperAccLimity = 0;
151 
152  if (r % 2 == int(acluster.x[curInd]) % 2) {
153  LowerAccLimity = std::max(0, int(acluster.y[curInd]) - 1);
154  UpperAccLimity = std::min(int(acluster.y[curInd]) + 2, theBuffer.columns());
155  }
156 
157  else {
158  int parity_curr = int(acluster.x[curInd]) % 2;
159  int parity_hit = r % 2;
160 
161  LowerAccLimity = std::max(0, int(acluster.y[curInd]) - parity_hit);
162  UpperAccLimity = std::min(int(acluster.y[curInd]) + parity_curr + 1, theBuffer.columns());
163  }
164 
165  /*
166  for (auto c = std::max(0, int(acluster.y[curInd]) - 1);
167  c < std::min(int(acluster.y[curInd]) + 2, theBuffer.columns());
168  ++c)
169  */
170  for (auto c = LowerAccLimity; c < UpperAccLimity; ++c) {
171  if (theBuffer(r, c) >= thePixelThreshold) {
172  SiPixelCluster::PixelPos newpix(r, c);
173  auto const newpix_adc = std::min(theBuffer(r, c), int(std::numeric_limits<uint16_t>::max()));
174  if (!acluster.add(newpix, newpix_adc))
175  goto endClus;
176  if (isbarrel)
177  edm::LogInfo("make_cluster_bricked()") << "add" << r << c << theBuffer(r, c);
178  theBuffer.set_adc(newpix, 1);
179  //std::cout<<"col "<<c<<" row "<<r<<std::endl;
180  }
181  }
182  }
183 
184  } // while accretion
185 endClus:
186  SiPixelCluster cluster(acluster.isize, acluster.adc, acluster.x, acluster.y, acluster.xmin, acluster.ymin);
187  //Here we split the cluster, if the flag to do so is set and we have found a dead or noisy pixel.
188 
189  if (dead_flag && doSplitClusters) {
190  // Set separate cluster threshold for L1 (needed for phase1)
192  if (theLayer == 1)
194 
195  //Set the first cluster equal to the existing cluster.
196  SiPixelCluster first_cluster = cluster;
197  bool have_second_cluster = false;
198  while (!dead_pixel_stack.empty()) {
199  //consider each found dead pixel
200  SiPixelCluster::PixelPos deadpix = dead_pixel_stack.top();
201  dead_pixel_stack.pop();
202  theBuffer.set_adc(deadpix, 1);
203 
204  //Clusterize the split cluster using the dead pixel as a seed
205  SiPixelCluster second_cluster = make_cluster_bricked(deadpix, output, isbarrel);
206 
207  //If both clusters would normally have been found by the clusterizer, put them into output
208  if (second_cluster.charge() >= clusterThreshold && first_cluster.charge() >= clusterThreshold) {
209  output.push_back(second_cluster);
210  have_second_cluster = true;
211  }
212 
213  //We also want to keep the merged cluster in data and let the RecHit algorithm decide which set to keep
214  //This loop adds the second cluster to the first.
215  const std::vector<SiPixelCluster::Pixel>& branch_pixels = second_cluster.pixels();
216  for (unsigned int i = 0; i < branch_pixels.size(); i++) {
217  auto const temp_x = branch_pixels[i].x;
218  auto const temp_y = branch_pixels[i].y;
219  auto const temp_adc = branch_pixels[i].adc;
220  SiPixelCluster::PixelPos newpix(temp_x, temp_y);
221  cluster.add(newpix, temp_adc);
222  }
223  }
224 
225  //Remember to also add the first cluster if we added the second one.
226  if (first_cluster.charge() >= clusterThreshold && have_second_cluster) {
227  output.push_back(first_cluster);
228  std::push_heap(output.begin(), output.end(), [](SiPixelCluster const& cl1, SiPixelCluster const& cl2) {
229  return cl1.minPixelRow() < cl2.minPixelRow();
230  });
231  }
232  }
233 
234  return cluster;
235 }
unsigned int pxbLayer(const DetId &id) const
SiPixelArrayBuffer theBuffer
Data storage.
SiPixelCluster make_cluster(const SiPixelCluster::PixelPos &pix, edmNew::DetSetVector< SiPixelCluster >::FastFiller &output)
The actual clustering algorithm: group the neighboring pixels around the seed.
Log< level::Error, false > LogError
assert(be >=bs)
void set_adc(int row, int col, int adc)
static std::string const input
Definition: EdmProvDump.cc:47
int minPixelRow() const
int charge() const
const std::vector< Pixel > pixels() const
constexpr int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:48
void add(const PixelPos &pix, int adc)
Log< level::Info, false > LogInfo
void clusterizeDetUnitT(const T &input, const PixelGeomDetUnit *pixDet, const TrackerTopology *tTopo, const std::vector< short > &badChannels, edmNew::DetSetVector< SiPixelCluster >::FastFiller &output)
Cluster pixels. This method operates on a matrix of pixels and finds the largest contiguous cluster a...
Definition: DetId.h:17
void clear_buffer(DigiIterator begin, DigiIterator end)
Clear the internal buffer array.
SiPixelCluster make_cluster_bricked(const SiPixelCluster::PixelPos &pix, edmNew::DetSetVector< SiPixelCluster >::FastFiller &output, bool isbarrel)
The actual clustering algorithm: group the neighboring pixels around the seed.
Pixel cluster – collection of neighboring pixels above threshold.
virtual const PixelTopology & specificTopology() const
Returns a reference to the pixel proxy topology.
constexpr int row() const
bool setup(const PixelGeomDetUnit *pixDet)
Private helper methods:
constexpr int col() const
bool add(SiPixelCluster::PixelPos const &p, uint16_t const iadc)
std::vector< SiPixelCluster::PixelPos > theSeeds
PixelThresholdClusterizerForBricked(edm::ParameterSet const &conf)
long double T
def move(src, dest)
Definition: eostools.py:511
void copy_to_buffer(DigiIterator begin, DigiIterator end)
Copy adc counts from PixelDigis into the buffer, identify seeds.
A specific threshold-based pixel clustering algorithm.