CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
PixelThresholdClusterizer.cc
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
20 //----------------------------------------------------------------------------
21 
22 // Our own includes
26 // Geometry
29 //#include "Geometry/CommonTopologies/RectangularPixelTopology.h"
30 
31 // STL
32 #include <stack>
33 #include <vector>
34 #include <iostream>
35 using namespace std;
36 
37 //----------------------------------------------------------------------------
41 //----------------------------------------------------------------------------
44  conf_(conf), bufferAlreadySet(false), theNumOfRows(0), theNumOfCols(0), detid_(0)
45 {
46  // Get thresholds in electrons
47  thePixelThreshold =
48  conf_.getParameter<int>("ChannelThreshold");
49  theSeedThreshold =
50  conf_.getParameter<int>("SeedThreshold");
51  theClusterThreshold =
52  conf_.getParameter<double>("ClusterThreshold");
53  theConversionFactor =
54  conf_.getParameter<int>("VCaltoElectronGain");
55  theOffset =
56  conf_.getParameter<int>("VCaltoElectronOffset");
57 
58 
59  // Get the constants for the miss-calibration studies
60  doMissCalibrate=conf_.getUntrackedParameter<bool>("MissCalibrate",true);
61  doSplitClusters = conf.getParameter<bool>("SplitClusters");
62  theBuffer.setSize( theNumOfRows, theNumOfCols );
63 }
66 
67 //----------------------------------------------------------------------------
70 //----------------------------------------------------------------------------
72 {
73  // Cache the topology.
74  const PixelTopology & topol = pixDet->specificTopology();
75 
76  // Get the new sizes.
77  int nrows = topol.nrows(); // rows in x
78  int ncols = topol.ncolumns(); // cols in y
79 
80  theNumOfRows = nrows; // Set new sizes
81  theNumOfCols = ncols;
82 
83  if ( nrows > theBuffer.rows() ||
84  ncols > theBuffer.columns() )
85  { // change only when a larger is needed
86  //if( nrows != theNumOfRows || ncols != theNumOfCols ) {
87  //cout << " PixelThresholdClusterizer: pixel buffer redefined to "
88  // << nrows << " * " << ncols << endl;
89  //theNumOfRows = nrows; // Set new sizes
90  //theNumOfCols = ncols;
91  // Resize the buffer
92  theBuffer.setSize(nrows,ncols); // Modify
93  bufferAlreadySet = true;
94  }
95 
96  return true;
97 }
98 //----------------------------------------------------------------------------
104 //----------------------------------------------------------------------------
106  const PixelGeomDetUnit * pixDet,
107  const std::vector<short>& badChannels,
109 
110  DigiIterator begin = input.begin();
111  DigiIterator end = input.end();
112 
113  // Do not bother for empty detectors
114  //if (begin == end) cout << " PixelThresholdClusterizer::clusterizeDetUnit - No digis to clusterize";
115 
116  // Set up the clusterization on this DetId.
117  if ( !setup(pixDet) )
118  return;
119 
120  detid_ = input.detId();
121 
122  // Copy PixelDigis to the buffer array; select the seed pixels
123  // on the way, and store them in theSeeds.
124  copy_to_buffer(begin, end);
125 
126  // At this point we know the number of seeds on this DetUnit, and thus
127  // also the maximal number of possible clusters, so resize theClusters
128  // in order to make vector<>::push_back() efficient.
129  // output.reserve ( theSeeds.size() ); //GPetruc: It is better *not* to reserve, with the new DetSetVector!
130 
131 
132  // Loop over all seeds. TO DO: wouldn't using iterators be faster?
133  // edm::LogError("PixelThresholdClusterizer") << "Starting clusterizing" << endl;
134  for (unsigned int i = 0; i < theSeeds.size(); i++)
135  {
136 
137  // Gavril : The charge of seeds that were already inlcuded in clusters is set to 1 electron
138  // so we don't want to call "make_cluster" for these cases
139  if ( theBuffer(theSeeds[i]) >= theSeedThreshold )
140  { // Is this seed still valid?
141  // Make a cluster around this seed
142  SiPixelCluster cluster = make_cluster( theSeeds[i] , output);
143 
144  // Check if the cluster is above threshold
145  // (TO DO: one is signed, other unsigned, gcc warns...)
146  if ( cluster.charge() >= theClusterThreshold)
147  {
148  // cout << "putting in this cluster" << endl;
149  output.push_back( cluster );
150  }
151  }
152  }
153 
154  // Erase the seeds.
155  theSeeds.clear();
156 
157  // Need to clean unused pixels from the buffer array.
158  clear_buffer(begin, end);
159 
160 }
161 
162 //----------------------------------------------------------------------------
170 //----------------------------------------------------------------------------
172 {
173  for(DigiIterator di = begin; di != end; ++di )
174  {
175  theBuffer.set_adc( di->row(), di->column(), 0 ); // reset pixel adc to 0
176  }
177 }
178 
179 //----------------------------------------------------------------------------
181 //----------------------------------------------------------------------------
183 {
184  for(DigiIterator di = begin; di != end; ++di)
185  {
186  int row = di->row();
187  int col = di->column();
188  int adc = calibrate(di->adc(),col,row); // convert ADC -> electrons
189  if ( adc >= thePixelThreshold)
190  {
191  theBuffer.set_adc( row, col, adc);
192  if ( adc >= theSeedThreshold)
193  {
194  theSeeds.push_back( SiPixelCluster::PixelPos(row,col) );
195  }
196  }
197  }
198 }
199 
200 //----------------------------------------------------------------------------
201 // Calibrate adc counts to electrons
202 //-----------------------------------------------------------------
203 int PixelThresholdClusterizer::calibrate(int adc, int col, int row)
204 {
205  int electrons = 0;
206 
207  if ( doMissCalibrate )
208  {
209  // do not perform calibration if pixel is dead!
210 
211  if ( !theSiPixelGainCalibrationService_->isDead(detid_,col,row) &&
212  !theSiPixelGainCalibrationService_->isNoisy(detid_,col,row) )
213  {
214 
215  // Linear approximation of the TANH response
216  // Pixel(0,0,0)
217  //const float gain = 2.95; // 1 ADC = 2.95 VCALs (1/0.339)
218  //const float pedestal = -83.; // -28/0.339
219  // Roc-0 average
220  //const float gain = 1./0.357; // 1 ADC = 2.80 VCALs
221  //const float pedestal = -28.2 * gain; // -79.
222 
223  float DBgain = theSiPixelGainCalibrationService_->getGain(detid_, col, row);
224  float DBpedestal = theSiPixelGainCalibrationService_->getPedestal(detid_, col, row) * DBgain;
225 
226 
227  // Roc-6 average
228  //const float gain = 1./0.313; // 1 ADC = 3.19 VCALs
229  //const float pedestal = -6.2 * gain; // -19.8
230  //
231  float vcal = adc * DBgain - DBpedestal;
232 
233  // atanh calibration
234  // Roc-6 average
235  //const float p0 = 0.00492;
236  //const float p1 = 1.998;
237  //const float p2 = 90.6;
238  //const float p3 = 134.1;
239  // Roc-6 average
240  //const float p0 = 0.00382;
241  //const float p1 = 0.886;
242  //const float p2 = 112.7;
243  //const float p3 = 113.0;
244  //float vcal = ( atanh( (adc-p3)/p2) + p1)/p0;
245 
246  electrons = int( vcal * theConversionFactor + theOffset);
247  }
248  }
249  else
250  { // No misscalibration in the digitizer
251  // Simple (default) linear gain
252  const float gain = 135.; // 1 ADC = 135 electrons
253  const float pedestal = 0.; //
254  electrons = int(adc * gain + pedestal);
255  }
256 
257  return electrons;
258 }
259 
260 //----------------------------------------------------------------------------
262 //----------------------------------------------------------------------------
266 {
267 
268  //First we acquire the seeds for the clusters
269  int seed_adc;
270  stack<SiPixelCluster::PixelPos, vector<SiPixelCluster::PixelPos> > pixel_stack;
271  stack<SiPixelCluster::PixelPos, vector<SiPixelCluster::PixelPos> > dead_pixel_stack;
272 
273  //The individual modules have been loaded into a buffer.
274  //After each pixel has been considered by the clusterizer, we set the adc count to 1
275  //to mark that we have already considered it.
276  //The only difference between dead/noisy pixels and standard ones is that for dead/noisy pixels,
277  //We consider the charge of the pixel to always be zero.
278 
279  if ( theSiPixelGainCalibrationService_->isDead(detid_,pix.col(),pix.row()) ||
280  theSiPixelGainCalibrationService_->isNoisy(detid_,pix.col(),pix.row()) )
281  {
282  seed_adc = 0;
283  theBuffer.set_adc(pix, 1);
284  }
285  else
286  {
287  seed_adc = theBuffer(pix.row(), pix.col());
288  theBuffer.set_adc( pix, 1);
289  }
290 
291  SiPixelCluster cluster( pix, seed_adc );
292 
293  //Here we search all pixels adjacent to all pixels in the cluster.
294  pixel_stack.push( pix);
295  bool dead_flag = false;
296  while ( ! pixel_stack.empty())
297  {
298  //This is the standard algorithm to find and add a pixel
299  SiPixelCluster::PixelPos curpix = pixel_stack.top(); pixel_stack.pop();
300  for ( int r = curpix.row()-1; r <= curpix.row()+1; ++r)
301  {
302  for ( int c = curpix.col()-1; c <= curpix.col()+1; ++c)
303  {
304  if ( theBuffer(r,c) >= thePixelThreshold)
305  {
306 
307  SiPixelCluster::PixelPos newpix(r,c);
308  cluster.add( newpix, theBuffer(r,c));
309  theBuffer.set_adc( newpix, 1);
310  pixel_stack.push( newpix);
311  }
312 
313 
314  /* //Commenting out the addition of dead pixels to the cluster until further testing -- dfehling 06/09
315  //Check on the bounds of the module; this is to keep the isDead and isNoisy modules from returning errors
316  else if(r>= 0 && c >= 0 && (r <= (theNumOfRows-1.)) && (c <= (theNumOfCols-1.))){
317  //Check for dead/noisy pixels check that the buffer is not -1 (already considered). Check whether we want to split clusters separated by dead pixels or not.
318  if((theSiPixelGainCalibrationService_->isDead(detid_,c,r) || theSiPixelGainCalibrationService_->isNoisy(detid_,c,r)) && theBuffer(r,c) != 1){
319 
320  //If a pixel is dead or noisy, check to see if we want to split the clusters or not.
321  //Push it into a dead pixel stack in case we want to split the clusters. Otherwise add it to the cluster.
322  //If we are splitting the clusters, we will iterate over the dead pixel stack later.
323 
324  SiPixelCluster::PixelPos newpix(r,c);
325  if(!doSplitClusters){
326 
327  cluster.add(newpix, theBuffer(r,c));}
328  else if(doSplitClusters){
329  dead_pixel_stack.push(newpix);
330  dead_flag = true;}
331 
332  theBuffer.set_adc(newpix, 1);
333  }
334 
335  }
336  */
337 
338 
339 
340  }
341  }
342 
343  }
344 
345  //Here we split the cluster, if the flag to do so is set and we have found a dead or noisy pixel.
346 
347  if (dead_flag && doSplitClusters)
348  {
349  //Set the first cluster equal to the existing cluster.
350  SiPixelCluster first_cluster = cluster;
351  bool have_second_cluster = false;
352  while ( !dead_pixel_stack.empty() )
353  {
354  //consider each found dead pixel
355  SiPixelCluster::PixelPos deadpix = dead_pixel_stack.top(); dead_pixel_stack.pop();
356  theBuffer.set_adc(deadpix, 1);
357 
358  //Clusterize the split cluster using the dead pixel as a seed
359  SiPixelCluster second_cluster = make_cluster(deadpix, output);
360 
361  //If both clusters would normally have been found by the clusterizer, put them into output
362  if ( second_cluster.charge() >= theClusterThreshold &&
363  first_cluster.charge() >= theClusterThreshold )
364  {
365  output.push_back( second_cluster );
366  have_second_cluster = true;
367  }
368 
369  //We also want to keep the merged cluster in data and let the RecHit algorithm decide which set to keep
370  //This loop adds the second cluster to the first.
371  const std::vector<SiPixelCluster::Pixel>& branch_pixels = second_cluster.pixels();
372  for ( unsigned int i = 0; i<branch_pixels.size(); i++)
373  {
374  int temp_x = branch_pixels[i].x;
375  int temp_y = branch_pixels[i].y;
376  int temp_adc = branch_pixels[i].adc;
377  SiPixelCluster::PixelPos newpix(temp_x, temp_y);
378  cluster.add(newpix, temp_adc);}
379  }
380 
381  //Remember to also add the first cluster if we added the second one.
382  if ( first_cluster.charge() >= theClusterThreshold && have_second_cluster)
383  {
384  output.push_back( first_cluster );
385  }
386  }
387 
388  return cluster;
389 }
390 
int adc(sample_type sample)
get the ADC sample (12 bits)
iterator end()
Definition: DetSet.h:61
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
float charge() const
void push_back(data_type const &d)
void clusterizeDetUnit(const edm::DetSet< PixelDigi > &input, const PixelGeomDetUnit *pixDet, 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...
PixelThresholdClusterizer(edm::ParameterSet const &conf)
det_id_type detId() const
Definition: DetSet.h:73
SiPixelCluster make_cluster(const SiPixelCluster::PixelPos &pix, edmNew::DetSetVector< SiPixelCluster >::FastFiller &output)
The actual clustering algorithm: group the neighboring pixels around the seed.
virtual int ncolumns() const =0
virtual int nrows() const =0
edm::DetSet< PixelDigi >::const_iterator DigiIterator
#define end
Definition: vmac.h:38
void add(const PixelPos &pix, int adc)
tuple conf
Definition: dbtoconf.py:185
iterator begin()
Definition: DetSet.h:60
void clear_buffer(DigiIterator begin, DigiIterator end)
Clear the internal buffer array.
virtual const PixelTopology & specificTopology() const
Returns a reference to the pixel proxy topology.
Pixel cluster – collection of neighboring pixels above threshold.
#define begin
Definition: vmac.h:31
bool setup(const PixelGeomDetUnit *pixDet)
Private helper methods:
int calibrate(int adc, int col, int row)
void setup(std::vector< TH2F > &depth, std::string name, std::string units="")
const std::vector< Pixel > pixels() const
void copy_to_buffer(DigiIterator begin, DigiIterator end)
Copy adc counts from PixelDigis into the buffer, identify seeds.