CMS 3D CMS Logo

SiPixelTemplateSplit.cc
Go to the documentation of this file.
1 //
2 // SiPixelTemplateSplit.cc (Version 2.30)
3 //
4 // Procedure to fit two templates (same angle hypotheses) to a single cluster
5 // Return two x- and two y-coordinates for the cluster
6 //
7 // Created by Morris Swartz on 04/10/08.
8 //
9 // Incorporate "cluster repair" to handle dead pixels
10 // Take truncation size from new pixmax information
11 // Change to allow template sizes to be changed at compile time
12 // Move interpolation range error to LogDebug
13 // Add q2bin = 5 and change 1-pixel probability to use new template info
14 // Add floor for probabilities (no exact zeros)
15 // Add ambiguity resolution with crude 2-D templates (v2.00)
16 // Pass all containers by alias to prevent excessive cpu-usage (v2.01)
17 // Add ambiguity resolution with fancy 2-D templates (v2.10)
18 // Make small change to indices for ambiguity resolution (v2.11)
19 // Tune x and y errors separately (v2.12)
20 // Use template cytemp/cxtemp methods to center the data cluster in the right place when the templates become asymmetric after irradiation (v2.20)
21 // Add charge probability to the splitter [tests consistency with a two-hit merged cluster hypothesis] (v2.20)
22 // Improve likelihood normalization slightly (v2.21)
23 // Replace hardwired pixel size derived errors with ones from templated pixel sizes (v2.22)
24 // Add shape and charge probabilities for the merged cluster hypothesis (v2.23)
25 // Incorporate VI-like speed improvements (v2.25)
26 // Improve speed by eliminating the triple index boost::multiarray objects and add speed switch to optimize the algorithm (v2.30)
27 // Change VVIObjF so it only reads kappa
28 //
29 
30 #ifndef SI_PIXEL_TEMPLATE_STANDALONE
31 //#include <cmath.h>
32 #else
33 #include <math.h>
34 #endif
35 #include <algorithm>
36 #include <vector>
37 #include <list>
38 #include <iostream>
39 // ROOT::Math has a c++ function that does the probability calc, but only in v5.12 and later
40 #include "Math/DistFunc.h"
41 #include "TMath.h"
42 // Use current version of gsl instead of ROOT::Math
43 //#include <gsl/gsl_cdf.h>
44 
45 #ifndef SI_PIXEL_TEMPLATE_STANDALONE
49 #define LOGERROR(x) edm::LogError(x)
50 #define LOGDEBUG(x) LogDebug(x)
51 static constexpr int theVerboseLevel = 2;
52 #define ENDL " "
53 #else
54 #include "SiPixelTemplateSplit.h"
55 #include "VVIObj.h"
56 //#include "SiPixelTemplate2D.h"
57 //#include "SimpleTemplate2D.h"
58 //static int theVerboseLevel = {2};
59 #define LOGERROR(x) std::cout << x << ": "
60 #define LOGDEBUG(x) std::cout << x << ": "
61 #define ENDL std::endl
62 #endif
63 
64 using namespace SiPixelTemplateSplit;
65 
66 // *************************************************************************************************************************************
97 // *************************************************************************************************************************************
99  float cotalpha,
100  float cotbeta,
101  array_2d& clust,
102  std::vector<bool>& ydouble,
103  std::vector<bool>& xdouble,
104  SiPixelTemplate& templ,
105  float& yrec1,
106  float& yrec2,
107  float& sigmay,
108  float& prob2y,
109  float& xrec1,
110  float& xrec2,
111  float& sigmax,
112  float& prob2x,
113  int& q2bin,
114  float& prob2Q,
115  bool resolve,
116  int speed,
117  float& dchisq,
118  bool deadpix,
119  std::vector<std::pair<int, int> >& zeropix,
120  SiPixelTemplate2D& templ2D)
121 
122 {
123  // Local variables
124  int i, j, k, binq, midpix, fypix, nypix, lypix, logypx, lparm;
125  int fxpix, nxpix, lxpix, logxpx, shifty, shiftx;
126  int nclusx, nclusy;
127  int nybin, ycbin, nxbin, xcbin, minbinj, minbink;
128  int deltaj, jmin, jmax, kmin, kmax, km, fxbin, lxbin, fybin, lybin, djy, djx;
129  float sythr, sxthr, delta, sigma, sigavg, pseudopix, xsize, ysize, qscale, lanpar[2][5];
130  float ss2, ssa, sa2, rat, fq, qtotal, qpixel, qavg;
131  float x1p, x2p, y1p, y2p, deltachi2;
132  float originx, originy, bias, maxpix, minmax;
133  double chi2x, meanx, chi2y, meany, chi2ymin, chi2xmin, chi21max;
134  double hchi2, hndof, sigmal1, sigmal2, mpv1, mpv2, arg1, arg2, q05, like, loglike1, loglike2;
135  double prvav, mpv, sigmaQ, kappa, xvav;
136  float ysum[BYSIZE], xsum[BXSIZE], ysort[BYSIZE], xsort[BXSIZE];
137  float ysig2[BYSIZE], xsig2[BXSIZE];
138  float yw2[BYSIZE], xw2[BXSIZE], ysw[BYSIZE], xsw[BXSIZE];
139  float cluster2[BXM2][BYM2], temp2d1[BXM2][BYM2], temp2d2[BXM2][BYM2];
140  bool yd[BYSIZE], xd[BXSIZE], anyyd, anyxd, any2dfail;
141  const float sqrt2x = {3.0000}, sqrt2y = {1.7000};
142  const float sqrt12 = {3.4641};
143  const float probmin = {1.110223e-16};
144  const float prob2Qmin = {1.e-5};
145  std::pair<int, int> pixel;
146 
147  // bool SiPixelTemplateSplit::SimpleTemplate2D(float cotalpha, float cotbeta, float xhit, float yhit, float thick, float lorxwidth, float lorywidth,
148  // float qavg, std::vector<bool> ydouble, std::vector<bool> xdouble, float template2d[BXM2][BYM2]);
149 
150  // The minimum chi2 for a valid one pixel cluster = pseudopixel contribution only
151 
152  const double mean1pix = {0.100}, chi21min = {0.160};
153 
154  // First, interpolate the template needed to analyze this cluster
155  // check to see of the track direction is in the physical range of the loaded template
156 
157  if (!templ.interpolate(id, cotalpha, cotbeta)) {
158  LOGDEBUG("SiPixelTemplateReco") << "input cluster direction cot(alpha) = " << cotalpha
159  << ", cot(beta) = " << cotbeta
160  << " is not within the acceptance of template ID = " << id
161  << ", no reconstruction performed" << ENDL;
162  return 20;
163  }
164 
165  // Get pixel dimensions from the template (to allow multiple detectors in the future)
166 
167  xsize = templ.xsize();
168  ysize = templ.ysize();
169 
170  // Define size of pseudopixel
171 
172  pseudopix = templ.s50();
173  // q05 = 0.28*pseudopix;
174  q05 = 0.05f * pseudopix;
175 
176  // Get charge scaling factor
177 
178  qscale = templ.qscale();
179 
180  // Make a local copy of the cluster container so that we can muck with it
181 
182  array_2d cluster = clust;
183 
184  // Check that the cluster container is (up to) a 7x21 matrix and matches the dimensions of the double pixel flags
185 
186  if (cluster.num_dimensions() != 2) {
187  LOGERROR("SiPixelTemplateReco") << "input cluster container (BOOST Multiarray) has wrong number of dimensions"
188  << ENDL;
189  return 3;
190  }
191  nclusx = (int)cluster.shape()[0];
192  nclusy = (int)cluster.shape()[1];
193  if (nclusx != (int)xdouble.size()) {
194  LOGERROR("SiPixelTemplateReco") << "input cluster container x-size is not equal to double pixel flag container size"
195  << ENDL;
196  return 4;
197  }
198  if (nclusy != (int)ydouble.size()) {
199  LOGERROR("SiPixelTemplateReco") << "input cluster container y-size is not equal to double pixel flag container size"
200  << ENDL;
201  return 5;
202  }
203 
204  // enforce maximum size
205 
206  if (nclusx > TXSIZE) {
207  nclusx = TXSIZE;
208  }
209  if (nclusy > TYSIZE) {
210  nclusy = TYSIZE;
211  }
212 
213  // First, rescale all pixel charges
214 
215  for (i = 0; i < nclusy; ++i) {
216  for (j = 0; j < nclusx; ++j) {
217  if (cluster[j][i] > 0) {
218  cluster[j][i] *= qscale;
219  }
220  }
221  }
222 
223  // Next, sum the total charge and "decapitate" big pixels
224 
225  qtotal = 0.f;
226  minmax = 2.0f * templ.pixmax();
227  for (i = 0; i < nclusy; ++i) {
228  maxpix = minmax;
229  if (ydouble[i]) {
230  maxpix *= 2.f;
231  }
232  for (j = 0; j < nclusx; ++j) {
233  qtotal += cluster[j][i];
234  if (cluster[j][i] > maxpix) {
235  cluster[j][i] = maxpix;
236  }
237  }
238  }
239 
240  // Do the cluster repair here
241 
242  if (deadpix) {
243  fypix = BYM3;
244  lypix = -1;
245  for (i = 0; i < nclusy; ++i) {
246  ysum[i] = 0.f;
247  // Do preliminary cluster projection in y
248  for (j = 0; j < nclusx; ++j) {
249  ysum[i] += cluster[j][i];
250  }
251  if (ysum[i] > 0.f) {
252  // identify ends of cluster to determine what the missing charge should be
253  if (i < fypix) {
254  fypix = i;
255  }
256  if (i > lypix) {
257  lypix = i;
258  }
259  }
260  }
261 
262  // Now loop over dead pixel list and "fix" everything
263 
264  //First see if the cluster ends are redefined and that we have only one dead pixel per column
265  int nyzero[TYSIZE]{};
266  std::vector<std::pair<int, int> >::const_iterator zeroIter = zeropix.begin(), zeroEnd = zeropix.end();
267  for (; zeroIter != zeroEnd; ++zeroIter) {
268  i = zeroIter->second;
269  if (i < 0 || i > TYSIZE - 1) {
270  LOGERROR("SiPixelTemplateReco") << "dead pixel column y-index " << i << ", no reconstruction performed" << ENDL;
271  return 11;
272  }
273 
274  // count the number of dead pixels in each column
275  ++nyzero[i];
276  // allow them to redefine the cluster ends
277  if (i < fypix) {
278  fypix = i;
279  }
280  if (i > lypix) {
281  lypix = i;
282  }
283  }
284 
285  nypix = lypix - fypix + 1;
286 
287  // Now adjust the charge in the dead pixels to sum to 0.5*truncation value in the end columns and the truncation value in the interior columns
288 
289  for (zeroIter = zeropix.begin(); zeroIter != zeroEnd; ++zeroIter) {
290  i = zeroIter->second;
291  j = zeroIter->first;
292  if (j < 0 || j > TXSIZE - 1) {
293  LOGERROR("SiPixelTemplateReco") << "dead pixel column x-index " << j << ", no reconstruction performed" << ENDL;
294  return 12;
295  }
296  if ((i == fypix || i == lypix) && nypix > 1) {
297  maxpix = templ.symax() / 2.;
298  } else {
299  maxpix = templ.symax();
300  }
301  if (ydouble[i]) {
302  maxpix *= 2.;
303  }
304  if (nyzero[i] > 0 && nyzero[i] < 3) {
305  qpixel = (maxpix - ysum[i]) / (float)nyzero[i];
306  } else {
307  qpixel = 1.;
308  }
309  if (qpixel < 1.f) {
310  qpixel = 1.f;
311  }
312  cluster[j][i] = qpixel;
313  // Adjust the total cluster charge to reflect the charge of the "repaired" cluster
314  qtotal += qpixel;
315  }
316  // End of cluster repair section
317  }
318 
319  // Next, make y-projection of the cluster and copy the double pixel flags into a 25 element container
320 
321  for (i = 0; i < BYSIZE; ++i) {
322  ysum[i] = 0.f;
323  yd[i] = false;
324  }
325  k = 0;
326  anyyd = false;
327  for (i = 0; i < nclusy; ++i) {
328  for (j = 0; j < nclusx; ++j) {
329  ysum[k] += cluster[j][i];
330  }
331 
332  // If this is a double pixel, put 1/2 of the charge in 2 consective single pixels
333 
334  if (ydouble[i]) {
335  ysum[k] /= 2.f;
336  ysum[k + 1] = ysum[k];
337  yd[k] = true;
338  yd[k + 1] = false;
339  k = k + 2;
340  anyyd = true;
341  } else {
342  yd[k] = false;
343  ++k;
344  }
345  if (k > BYM1) {
346  break;
347  }
348  }
349 
350  // Next, make x-projection of the cluster and copy the double pixel flags into an 11 element container
351 
352  for (i = 0; i < BXSIZE; ++i) {
353  xsum[i] = 0.f;
354  xd[i] = false;
355  }
356  k = 0;
357  anyxd = false;
358  for (j = 0; j < nclusx; ++j) {
359  for (i = 0; i < nclusy; ++i) {
360  xsum[k] += cluster[j][i];
361  }
362 
363  // If this is a double pixel, put 1/2 of the charge in 2 consective single pixels
364 
365  if (xdouble[j]) {
366  xsum[k] /= 2.f;
367  xsum[k + 1] = xsum[k];
368  xd[k] = true;
369  xd[k + 1] = false;
370  k = k + 2;
371  anyxd = true;
372  } else {
373  xd[k] = false;
374  ++k;
375  }
376  if (k > BXM1) {
377  break;
378  }
379  }
380 
381  // next, identify the y-cluster ends, count total pixels, nypix, and logical pixels, logypx
382 
383  fypix = -1;
384  nypix = 0;
385  lypix = 0;
386  logypx = 0;
387  for (i = 0; i < BYSIZE; ++i) {
388  if (ysum[i] > 0.) {
389  if (fypix == -1) {
390  fypix = i;
391  }
392  if (!yd[i]) {
393  ysort[logypx] = ysum[i];
394  ++logypx;
395  }
396  ++nypix;
397  lypix = i;
398  }
399  }
400 
401  // Make sure cluster is continuous
402 
403  if ((lypix - fypix + 1) != nypix || nypix == 0) {
404  LOGDEBUG("SiPixelTemplateReco") << "y-length of pixel cluster doesn't agree with number of pixels above threshold"
405  << ENDL;
406  if (theVerboseLevel > 2) {
407  LOGDEBUG("SiPixelTemplateReco") << "ysum[] = ";
408  for (i = 0; i < BYSIZE - 1; ++i) {
409  LOGDEBUG("SiPixelTemplateReco") << ysum[i] << ", ";
410  }
411  LOGDEBUG("SiPixelTemplateReco") << ysum[BYSIZE - 1] << ENDL;
412  }
413 
414  return 1;
415  }
416 
417  // If cluster is longer than max template size, technique fails
418 
419  if (nypix > TYSIZE) {
420  LOGDEBUG("SiPixelTemplateReco") << "y-length of pixel cluster is larger than maximum template size" << ENDL;
421  if (theVerboseLevel > 2) {
422  LOGDEBUG("SiPixelTemplateReco") << "ysum[] = ";
423  for (i = 0; i < BYSIZE - 1; ++i) {
424  LOGDEBUG("SiPixelTemplateReco") << ysum[i] << ", ";
425  }
426  LOGDEBUG("SiPixelTemplateReco") << ysum[BYSIZE - 1] << ENDL;
427  }
428 
429  return 6;
430  }
431 
432  // next, center the cluster on template center if necessary
433 
434  midpix = (fypix + lypix) / 2;
435  // shifty = BHY - midpix;
436  shifty = templ.cytemp() - midpix;
437  if (shifty > 0) {
438  for (i = lypix; i >= fypix; --i) {
439  ysum[i + shifty] = ysum[i];
440  ysum[i] = 0.;
441  yd[i + shifty] = yd[i];
442  yd[i] = false;
443  }
444  } else if (shifty < 0) {
445  for (i = fypix; i <= lypix; ++i) {
446  ysum[i + shifty] = ysum[i];
447  ysum[i] = 0.;
448  yd[i + shifty] = yd[i];
449  yd[i] = false;
450  }
451  }
452  lypix += shifty;
453  fypix += shifty;
454 
455  // If the cluster boundaries are OK, add pesudopixels, otherwise quit
456 
457  if (fypix > 1 && fypix < BYM2) {
458  ysum[fypix - 1] = pseudopix;
459  ysum[fypix - 2] = 0.2f * pseudopix;
460  } else {
461  return 8;
462  }
463  if (lypix > 1 && lypix < BYM2) {
464  ysum[lypix + 1] = pseudopix;
465  ysum[lypix + 2] = 0.2f * pseudopix;
466  } else {
467  return 8;
468  }
469 
470  // finally, determine if pixel[0] is a double pixel and make an origin correction if it is
471 
472  if (ydouble[0]) {
473  originy = -0.5f;
474  } else {
475  originy = 0.f;
476  }
477 
478  // next, identify the x-cluster ends, count total pixels, nxpix, and logical pixels, logxpx
479 
480  fxpix = -1;
481  nxpix = 0;
482  lxpix = 0;
483  logxpx = 0;
484  for (i = 0; i < BXSIZE; ++i) {
485  if (xsum[i] > 0.) {
486  if (fxpix == -1) {
487  fxpix = i;
488  }
489  if (!xd[i]) {
490  xsort[logxpx] = xsum[i];
491  ++logxpx;
492  }
493  ++nxpix;
494  lxpix = i;
495  }
496  }
497 
498  // Make sure cluster is continuous
499 
500  if ((lxpix - fxpix + 1) != nxpix) {
501  LOGDEBUG("SiPixelTemplateReco") << "x-length of pixel cluster doesn't agree with number of pixels above threshold"
502  << ENDL;
503  if (theVerboseLevel > 2) {
504  LOGDEBUG("SiPixelTemplateReco") << "xsum[] = ";
505  for (i = 0; i < BXSIZE - 1; ++i) {
506  LOGDEBUG("SiPixelTemplateReco") << xsum[i] << ", ";
507  }
508  LOGDEBUG("SiPixelTemplateReco") << ysum[BXSIZE - 1] << ENDL;
509  }
510 
511  return 2;
512  }
513 
514  // If cluster is longer than max template size, technique fails
515 
516  if (nxpix > TXSIZE) {
517  LOGDEBUG("SiPixelTemplateReco") << "x-length of pixel cluster is larger than maximum template size" << ENDL;
518  if (theVerboseLevel > 2) {
519  LOGDEBUG("SiPixelTemplateReco") << "xsum[] = ";
520  for (i = 0; i < BXSIZE - 1; ++i) {
521  LOGDEBUG("SiPixelTemplateReco") << xsum[i] << ", ";
522  }
523  LOGDEBUG("SiPixelTemplateReco") << ysum[BXSIZE - 1] << ENDL;
524  }
525 
526  return 7;
527  }
528 
529  // next, center the cluster on template center if necessary
530 
531  midpix = (fxpix + lxpix) / 2;
532  // shiftx = BHX - midpix;
533  shiftx = templ.cxtemp() - midpix;
534  if (shiftx > 0) {
535  for (i = lxpix; i >= fxpix; --i) {
536  xsum[i + shiftx] = xsum[i];
537  xsum[i] = 0.f;
538  xd[i + shiftx] = xd[i];
539  xd[i] = false;
540  }
541  } else if (shiftx < 0) {
542  for (i = fxpix; i <= lxpix; ++i) {
543  xsum[i + shiftx] = xsum[i];
544  xsum[i] = 0.f;
545  xd[i + shiftx] = xd[i];
546  xd[i] = false;
547  }
548  }
549  lxpix += shiftx;
550  fxpix += shiftx;
551 
552  // If the cluster boundaries are OK, add pesudopixels, otherwise quit
553 
554  if (fxpix > 1 && fxpix < BXM2) {
555  xsum[fxpix - 1] = pseudopix;
556  xsum[fxpix - 2] = 0.2f * pseudopix;
557  } else {
558  return 9;
559  }
560  if (lxpix > 1 && lxpix < BXM2) {
561  xsum[lxpix + 1] = pseudopix;
562  xsum[lxpix + 2] = 0.2f * pseudopix;
563  } else {
564  return 9;
565  }
566 
567  // finally, determine if pixel[0] is a double pixel and make an origin correction if it is
568 
569  if (xdouble[0]) {
570  originx = -0.5f;
571  } else {
572  originx = 0.f;
573  }
574 
575  // uncertainty and final corrections depend upon total charge bin
576 
577  qavg = templ.qavg();
578  fq = qtotal / qavg;
579  if (fq > 3.0f) {
580  binq = 0;
581  } else {
582  if (fq > 2.0f) {
583  binq = 1;
584  } else {
585  if (fq > 1.70f) {
586  binq = 2;
587  } else {
588  binq = 3;
589  }
590  }
591  }
592 
593  // Calculate the Vavilov probability that the cluster charge is consistent with a merged cluster
594 
595  if (speed < 0) {
596  templ.vavilov2_pars(mpv, sigmaQ, kappa);
597 #ifndef SI_PIXEL_TEMPLATE_STANDALONE
598  if ((sigmaQ <= 0.) || (mpv <= 0.) || (kappa < 0.01) || (kappa > 9.9)) {
599  throw cms::Exception("DataCorrupt") << "SiPixelTemplateSplit::Vavilov parameters mpv/sigmaQ/kappa = " << mpv
600  << "/" << sigmaQ << "/" << kappa << std::endl;
601  }
602 #else
603  assert((sigmaQ > 0.) && (mpv > 0.) && (kappa > 0.01) && (kappa < 10.));
604 #endif
605  xvav = ((double)qtotal - mpv) / sigmaQ;
606  // VVIObj is a private port of CERNLIB VVIDIS
607  VVIObj vvidist(kappa);
608  prvav = vvidist.fcn(xvav);
609  prob2Q = 1. - prvav;
610  if (prob2Q < prob2Qmin) {
611  prob2Q = prob2Qmin;
612  }
613  } else {
614  prob2Q = -1.f;
615  }
616 
617  // Return the charge bin via the parameter list unless the charge is too small (then flag it)
618 
619  q2bin = binq;
620  if (!deadpix && qtotal < 1.9f * templ.qmin()) {
621  q2bin = 5;
622  } else {
623  if (!deadpix && qtotal < 1.9f * templ.qmin(1)) {
624  q2bin = 4;
625  }
626  }
627 
628  if (theVerboseLevel > 9) {
629  LOGDEBUG("SiPixelTemplateSplit") << "ID = " << id << " cot(alpha) = " << cotalpha << " cot(beta) = " << cotbeta
630  << " nclusx = " << nclusx << " nclusy = " << nclusy << ENDL;
631  }
632 
633  // Next, generate the 3d y- and x-templates
634 
635  templ.ytemp3d_int(nypix, nybin);
636 
637  ycbin = nybin / 2;
638 
639  templ.xtemp3d_int(nxpix, nxbin);
640 
641  // retrieve the number of x-bins
642 
643  xcbin = nxbin / 2;
644 
645  // First, decide on chi^2 min search parameters
646 
647 #ifndef SI_PIXEL_TEMPLATE_STANDALONE
648  if (speed < -1 || speed > 2) {
649  throw cms::Exception("DataCorrupt") << "SiPixelTemplateReco::PixelTempReco2D called with illegal speed = " << speed
650  << std::endl;
651  }
652 #else
653  assert(speed >= -1 && speed < 3);
654 #endif
655  fybin = 0;
656  lybin = nybin - 1;
657  fxbin = 0;
658  lxbin = nxbin - 1;
659  djy = 1;
660  djx = 1;
661  if (speed > 0) {
662  djy = 2;
663  djx = 2;
664  if (speed > 1) {
665  if (!anyyd) {
666  djy = 4;
667  }
668  if (!anyxd) {
669  djx = 4;
670  }
671  }
672  }
673 
674  if (theVerboseLevel > 9) {
675  LOGDEBUG("SiPixelTemplateReco") << "fypix " << fypix << " lypix = " << lypix << " fybin = " << fybin
676  << " lybin = " << lybin << " djy = " << djy << " logypx = " << logypx << ENDL;
677  LOGDEBUG("SiPixelTemplateReco") << "fxpix " << fxpix << " lxpix = " << lxpix << " fxbin = " << fxbin
678  << " lxbin = " << lxbin << " djx = " << djx << " logxpx = " << logxpx << ENDL;
679  }
680 
681  // Do the y-reconstruction first
682 
683  // Define the maximum signal to allow before de-weighting a pixel
684 
685  sythr = 2.1f * (templ.symax());
686 
687  // Make sure that there will be at least two pixels that are not de-weighted
688 
689  std::sort(&ysort[0], &ysort[logypx]);
690  if (logypx == 1) {
691  sythr = 1.01f * ysort[0];
692  } else {
693  if (ysort[1] > sythr) {
694  sythr = 1.01f * ysort[1];
695  }
696  }
697 
698  // Evaluate pixel-by-pixel uncertainties (weights) for the templ analysis
699 
700  // for(i=0; i<BYSIZE; ++i) { ysig2[i] = 0.;}
701  templ.ysigma2(fypix, lypix, sythr, ysum, ysig2);
702 
703  // Find the template bin that minimizes the Chi^2
704 
705  chi2ymin = 1.e15;
706  ss2 = 0.f;
707  for (i = fypix - 2; i <= lypix + 2; ++i) {
708  yw2[i] = 1.f / ysig2[i];
709  ysw[i] = ysum[i] * yw2[i];
710  ss2 += ysum[i] * ysw[i];
711  }
712  minbinj = -1;
713  minbink = -1;
714  deltaj = djy;
715  jmin = fybin;
716  jmax = lybin;
717  kmin = fybin;
718  kmax = lybin;
719  std::vector<float> ytemp(BYSIZE);
720  while (deltaj > 0) {
721  for (j = jmin; j < jmax; j += deltaj) {
722  km = std::min(kmax, j);
723  for (k = kmin; k <= km; k += deltaj) {
724  // Get the template for this set of indices
725 
726  templ.ytemp3d(j, k, ytemp);
727 
728  // Modify the template if double pixels are present
729 
730  if (nypix > logypx) {
731  i = fypix;
732  while (i < lypix) {
733  if (yd[i] && !yd[i + 1]) {
734  // Sum the adjacent cells and put the average signal in both
735 
736  sigavg = (ytemp[i] + ytemp[i + 1]) / 2.f;
737  ytemp[i] = sigavg;
738  ytemp[i + 1] = sigavg;
739  i += 2;
740  } else {
741  ++i;
742  }
743  }
744  }
745  ssa = 0.f;
746  sa2 = 0.f;
747  for (i = fypix - 2; i <= lypix + 2; ++i) {
748  ssa += ysw[i] * ytemp[i];
749  sa2 += ytemp[i] * ytemp[i] * yw2[i];
750  }
751  rat = ssa / ss2;
752  if (rat <= 0.) {
753  LOGERROR("SiPixelTemplateSplit") << "illegal chi2ymin normalization = " << rat << ENDL;
754  rat = 1.;
755  }
756  chi2y = ss2 - 2.f * ssa / rat + sa2 / (rat * rat);
757  if (chi2y < chi2ymin) {
758  chi2ymin = chi2y;
759  minbinj = j;
760  minbink = k;
761  }
762  }
763  }
764  deltaj /= 2;
765  if (minbinj > fybin) {
766  jmin = minbinj - deltaj;
767  } else {
768  jmin = fybin;
769  }
770  if (minbinj < lybin) {
771  jmax = minbinj + deltaj;
772  } else {
773  jmax = lybin;
774  }
775  if (minbink > fybin) {
776  kmin = minbink - deltaj;
777  } else {
778  kmin = fybin;
779  }
780  if (minbink < lybin) {
781  kmax = minbink + deltaj;
782  } else {
783  kmax = lybin;
784  }
785  }
786 
787  if (theVerboseLevel > 9) {
788  LOGDEBUG("SiPixelTemplateReco") << "minbins " << minbinj << "," << minbink << " chi2ymin = " << chi2ymin << ENDL;
789  }
790 
791  // Do not apply final template pass to 1-pixel clusters (use calibrated offset)
792 
793  if (logypx == 1) {
794  if (nypix == 1) {
795  delta = templ.dyone();
796  sigma = templ.syone();
797  } else {
798  delta = templ.dytwo();
799  sigma = templ.sytwo();
800  }
801 
802  yrec1 = 0.5f * (fypix + lypix - 2 * shifty + 2.f * originy) * ysize - delta;
803  yrec2 = yrec1;
804 
805  if (sigma <= 0.) {
806  sigmay = ysize / sqrt12;
807  } else {
808  sigmay = sigma;
809  }
810 
811  // Do probability calculation for one-pixel clusters
812 
813  chi21max = fmax(chi21min, (double)templ.chi2yminone());
814  chi2ymin -= chi21max;
815  if (chi2ymin < 0.) {
816  chi2ymin = 0.;
817  }
818  // prob2y = gsl_cdf_chisq_Q(chi2ymin, mean1pix);
819  meany = fmax(mean1pix, (double)templ.chi2yavgone());
820  hchi2 = chi2ymin / 2.;
821  hndof = meany / 2.;
822  prob2y = 1. - TMath::Gamma(hndof, hchi2);
823 
824  } else {
825  // For cluster > 1 pix, use chi^2 minimm to recontruct the two y-positions
826 
827  // at small eta, the templates won't actually work on two pixel y-clusters so just return the pixel centers
828 
829  if (logypx == 2 && fabsf(cotbeta) < 0.25f) {
830  switch (nypix) {
831  case 2:
832  // Both pixels are small
833  yrec1 = (fypix - shifty + originy) * ysize;
834  yrec2 = (lypix - shifty + originy) * ysize;
835  sigmay = ysize / sqrt12;
836  break;
837  case 3:
838  // One big pixel and one small pixel
839  if (yd[fypix]) {
840  yrec1 = (fypix + 0.5f - shifty + originy) * ysize;
841  yrec2 = (lypix - shifty + originy) * ysize;
842  sigmay = ysize / sqrt12;
843  } else {
844  yrec1 = (fypix - shifty + originy) * ysize;
845  yrec2 = (lypix - 0.5f - shifty + originy) * ysize;
846  sigmay = 1.5f * ysize / sqrt12;
847  }
848  break;
849  case 4:
850  // Two big pixels
851  yrec1 = (fypix + 0.5f - shifty + originy) * ysize;
852  yrec2 = (lypix - 0.5f - shifty + originy) * ysize;
853  sigmay = 2.f * ysize / sqrt12;
854  break;
855  default:
856  // Something is screwy ...
857  LOGERROR("SiPixelTemplateReco")
858  << "weird problem: logical y-pixels = " << logypx << ", total ysize in normal pixels = " << nypix << ENDL;
859  return 10;
860  }
861  } else {
862  // uncertainty and final correction depend upon charge bin
863 
864  bias = templ.yavgc2m(binq);
865  yrec1 = (0.125f * (minbink - ycbin) + BHY - (float)shifty + originy) * ysize - bias;
866  yrec2 = (0.125f * (minbinj - ycbin) + BHY - (float)shifty + originy) * ysize - bias;
867  sigmay = sqrt2y * templ.yrmsc2m(binq);
868  }
869 
870  // Do goodness of fit test in y
871 
872  if (chi2ymin < 0.0) {
873  chi2ymin = 0.0;
874  }
875  meany = templ.chi2yavgc2m(binq);
876  if (meany < 0.01) {
877  meany = 0.01;
878  }
879  // gsl function that calculates the chi^2 tail prob for non-integral dof
880  // prob2y = gsl_cdf_chisq_Q(chi2y, meany);
881  // prob2y = ROOT::Math::chisquared_cdf_c(chi2y, meany);
882  hchi2 = chi2ymin / 2.;
883  hndof = meany / 2.;
884  prob2y = 1. - TMath::Gamma(hndof, hchi2);
885  }
886 
887  // Do the x-reconstruction next
888 
889  // Define the maximum signal to allow before de-weighting a pixel
890 
891  sxthr = 2.1f * templ.sxmax();
892 
893  // Make sure that there will be at least two pixels that are not de-weighted
894  std::sort(&xsort[0], &xsort[logxpx]);
895  if (logxpx == 1) {
896  sxthr = 1.01f * xsort[0];
897  } else {
898  if (xsort[1] > sxthr) {
899  sxthr = 1.01f * xsort[1];
900  }
901  }
902 
903  // Evaluate pixel-by-pixel uncertainties (weights) for the templ analysis
904 
905  // for(i=0; i<BYSIZE; ++i) { xsig2[i] = 0.; }
906  templ.xsigma2(fxpix, lxpix, sxthr, xsum, xsig2);
907 
908  // Find the template bin that minimizes the Chi^2
909 
910  chi2xmin = 1.e15;
911  ss2 = 0.f;
912  for (i = fxpix - 2; i <= lxpix + 2; ++i) {
913  xw2[i] = 1.f / xsig2[i];
914  xsw[i] = xsum[i] * xw2[i];
915  ss2 += xsum[i] * xsw[i];
916  }
917  minbinj = -1;
918  minbink = -1;
919  deltaj = djx;
920  jmin = fxbin;
921  jmax = lxbin;
922  kmin = fxbin;
923  kmax = lxbin;
924  std::vector<float> xtemp(BXSIZE);
925  while (deltaj > 0) {
926  for (j = jmin; j < jmax; j += deltaj) {
927  km = std::min(kmax, j);
928  for (k = kmin; k <= km; k += deltaj) {
929  // Get the template for this set of indices
930 
931  templ.xtemp3d(j, k, xtemp);
932 
933  // Modify the template if double pixels are present
934 
935  if (nxpix > logxpx) {
936  i = fxpix;
937  while (i < lxpix) {
938  if (xd[i] && !xd[i + 1]) {
939  // Sum the adjacent cells and put the average signal in both
940 
941  sigavg = (xtemp[i] + xtemp[i + 1]) / 2.f;
942  xtemp[i] = sigavg;
943  xtemp[i + 1] = sigavg;
944  i += 2;
945  } else {
946  ++i;
947  }
948  }
949  }
950  ssa = 0.f;
951  sa2 = 0.f;
952  for (i = fxpix - 2; i <= lxpix + 2; ++i) {
953  ssa += xsw[i] * xtemp[i];
954  sa2 += xtemp[i] * xtemp[i] * xw2[i];
955  }
956  rat = ssa / ss2;
957  if (rat <= 0.f) {
958  LOGERROR("SiPixelTemplateSplit") << "illegal chi2xmin normalization = " << rat << ENDL;
959  rat = 1.;
960  }
961  chi2x = ss2 - 2.f * ssa / rat + sa2 / (rat * rat);
962  if (chi2x < chi2xmin) {
963  chi2xmin = chi2x;
964  minbinj = j;
965  minbink = k;
966  }
967  }
968  }
969  deltaj /= 2;
970  if (minbinj > fxbin) {
971  jmin = minbinj - deltaj;
972  } else {
973  jmin = fxbin;
974  }
975  if (minbinj < lxbin) {
976  jmax = minbinj + deltaj;
977  } else {
978  jmax = lxbin;
979  }
980  if (minbink > fxbin) {
981  kmin = minbink - deltaj;
982  } else {
983  kmin = fxbin;
984  }
985  if (minbink < lxbin) {
986  kmax = minbink + deltaj;
987  } else {
988  kmax = lxbin;
989  }
990  }
991 
992  if (theVerboseLevel > 9) {
993  LOGDEBUG("SiPixelTemplateSplit") << "minbinj/minbink " << minbinj << "/" << minbink << " chi2xmin = " << chi2xmin
994  << ENDL;
995  }
996 
997  // Do not apply final template pass to 1-pixel clusters (use calibrated offset)
998 
999  if (logxpx == 1) {
1000  if (nxpix == 1) {
1001  delta = templ.dxone();
1002  sigma = templ.sxone();
1003  } else {
1004  delta = templ.dxtwo();
1005  sigma = templ.sxtwo();
1006  }
1007  xrec1 = 0.5f * (fxpix + lxpix - 2 * shiftx + 2.f * originx) * xsize - delta;
1008  xrec2 = xrec1;
1009  if (sigma <= 0.f) {
1010  sigmax = xsize / sqrt12;
1011  } else {
1012  sigmax = sigma;
1013  }
1014 
1015  // Do probability calculation for one-pixel clusters
1016 
1017  chi21max = fmax(chi21min, (double)templ.chi2xminone());
1018  chi2xmin -= chi21max;
1019  if (chi2xmin < 0.) {
1020  chi2xmin = 0.;
1021  }
1022  meanx = fmax(mean1pix, (double)templ.chi2xavgone());
1023  hchi2 = chi2xmin / 2.;
1024  hndof = meanx / 2.;
1025  prob2x = 1. - TMath::Gamma(hndof, hchi2);
1026 
1027  } else {
1028  // For cluster > 1 pix, use chi^2 minimm to recontruct the two x-positions
1029 
1030  // uncertainty and final correction depend upon charge bin
1031 
1032  bias = templ.xavgc2m(binq);
1033  xrec1 = (0.125f * (minbink - xcbin) + BHX - (float)shiftx + originx) * xsize - bias;
1034  xrec2 = (0.125f * (minbinj - xcbin) + BHX - (float)shiftx + originx) * xsize - bias;
1035  sigmax = sqrt2x * templ.xrmsc2m(binq);
1036 
1037  // Do goodness of fit test in y
1038 
1039  if (chi2xmin < 0.0) {
1040  chi2xmin = 0.0;
1041  }
1042  meanx = templ.chi2xavgc2m(binq);
1043  if (meanx < 0.01) {
1044  meanx = 0.01;
1045  }
1046  hchi2 = chi2xmin / 2.;
1047  hndof = meanx / 2.;
1048  prob2x = 1. - TMath::Gamma(hndof, hchi2);
1049  }
1050 
1051  // Don't return exact zeros for the probability
1052 
1053  if (prob2y < probmin) {
1054  prob2y = probmin;
1055  }
1056  if (prob2x < probmin) {
1057  prob2x = probmin;
1058  }
1059 
1060  // New code: resolve the ambiguity if resolve is set to true
1061 
1062  dchisq = 0.;
1063  if (resolve) {
1064  // First copy the unexpanded cluster into a new working buffer
1065 
1066  for (i = 0; i < BYM2; ++i) {
1067  for (j = 0; j < BXM2; ++j) {
1068  if ((i > 0 && i < BYM3) && (j > 0 && j < BXM3)) {
1069  cluster2[j][i] = qscale * clust[j - 1][i - 1];
1070  } else {
1071  cluster2[j][i] = 0.f;
1072  }
1073  }
1074  }
1075 
1076  // Next, redefine the local coordinates to start at the lower LH corner of pixel[1][1];
1077 
1078  if (xdouble[0]) {
1079  x1p = xrec1 + xsize;
1080  x2p = xrec2 + xsize;
1081  } else {
1082  x1p = xrec1 + xsize / 2.f;
1083  x2p = xrec2 + xsize / 2.f;
1084  }
1085 
1086  if (ydouble[0]) {
1087  y1p = yrec1 + ysize;
1088  y2p = yrec2 + ysize;
1089  } else {
1090  y1p = yrec1 + ysize / 2.f;
1091  y2p = yrec2 + ysize / 2.f;
1092  }
1093 
1094  // Next, calculate 2-d templates for the (x1,y1)+(x2,y2) and the (x1,y2)+(x2,y1) hypotheses
1095 
1096  // First zero the two 2-d hypotheses
1097 
1098  for (i = 0; i < BYM2; ++i) {
1099  for (j = 0; j < BXM2; ++j) {
1100  temp2d1[j][i] = 0.f;
1101  temp2d2[j][i] = 0.f;
1102  }
1103  }
1104 
1105  // Add the two hits in the first hypothesis
1106 
1107  any2dfail = templ2D.xytemp(id, cotalpha, cotbeta, x1p, y1p, xdouble, ydouble, temp2d1) &&
1108  templ2D.xytemp(id, cotalpha, cotbeta, x2p, y2p, xdouble, ydouble, temp2d1);
1109 
1110  // And then the second hypothesis
1111 
1112  any2dfail = any2dfail && templ2D.xytemp(id, cotalpha, cotbeta, x1p, y2p, xdouble, ydouble, temp2d2);
1113 
1114  any2dfail = any2dfail && templ2D.xytemp(id, cotalpha, cotbeta, x2p, y1p, xdouble, ydouble, temp2d2);
1115 
1116  // If any of these have failed, use the simple templates instead
1117 
1118  if (!any2dfail) {
1119  // Rezero the two 2-d hypotheses
1120 
1121  for (i = 0; i < BYM2; ++i) {
1122  for (j = 0; j < BXM2; ++j) {
1123  temp2d1[j][i] = 0.f;
1124  temp2d2[j][i] = 0.f;
1125  }
1126  }
1127 
1128  // Add the two hits in the first hypothesis
1129 
1130  if (!templ.simpletemplate2D(x1p, y1p, xdouble, ydouble, temp2d1)) {
1131  return 1;
1132  }
1133 
1134  if (!templ.simpletemplate2D(x2p, y2p, xdouble, ydouble, temp2d1)) {
1135  return 1;
1136  }
1137 
1138  // And then the second hypothesis
1139 
1140  if (!templ.simpletemplate2D(x1p, y2p, xdouble, ydouble, temp2d2)) {
1141  return 1;
1142  }
1143 
1144  if (!templ.simpletemplate2D(x2p, y1p, xdouble, ydouble, temp2d2)) {
1145  return 1;
1146  }
1147  }
1148 
1149  // Keep lists of pixels and nearest neighbors
1150 
1151  std::list<std::pair<int, int> > pixellst;
1152 
1153  // Loop through the array and find non-zero elements
1154 
1155  for (i = 0; i < BYM2; ++i) {
1156  for (j = 0; j < BXM2; ++j) {
1157  if (cluster2[j][i] > 0.f || temp2d1[j][i] > 0.f || temp2d2[j][i] > 0.f) {
1158  pixel.first = j;
1159  pixel.second = i;
1160  pixellst.push_back(pixel);
1161  }
1162  }
1163  }
1164 
1165  // Now calculate the product of Landau probabilities (alpha probability)
1166 
1167  templ2D.landau_par(lanpar);
1168  loglike1 = 0.;
1169  loglike2 = 0.;
1170 
1171  // Now, for each neighbor, match it again the pixel list.
1172  // If found, delete it from the neighbor list
1173 
1174  std::list<std::pair<int, int> >::const_iterator pixIter, pixEnd;
1175  pixIter = pixellst.begin();
1176  pixEnd = pixellst.end();
1177  for (; pixIter != pixEnd; ++pixIter) {
1178  j = pixIter->first;
1179  i = pixIter->second;
1180  if ((i < BHY && cotbeta > 0.) || (i >= BHY && cotbeta < 0.)) {
1181  lparm = 0;
1182  } else {
1183  lparm = 1;
1184  }
1185  mpv1 = lanpar[lparm][0] + lanpar[lparm][1] * temp2d1[j][i];
1186  sigmal1 = lanpar[lparm][2] * mpv1;
1187  sigmal1 = sqrt(sigmal1 * sigmal1 + lanpar[lparm][3] * lanpar[lparm][3]);
1188  if (sigmal1 < q05)
1189  sigmal1 = q05;
1190  arg1 = (cluster2[j][i] - mpv1) / sigmal1 - 0.22278;
1191  mpv2 = lanpar[lparm][0] + lanpar[lparm][1] * temp2d2[j][i];
1192  sigmal2 = lanpar[lparm][2] * mpv2;
1193  sigmal2 = sqrt(sigmal2 * sigmal2 + lanpar[lparm][3] * lanpar[lparm][3]);
1194  if (sigmal2 < q05)
1195  sigmal2 = q05;
1196  arg2 = (cluster2[j][i] - mpv2) / sigmal2 - 0.22278;
1197  // like = ROOT::Math::landau_pdf(arg1)/sigmal1;
1198  like = ROOT::Math::landau_pdf(arg1);
1199  if (like < 1.e-30)
1200  like = 1.e-30;
1201  loglike1 += log(like);
1202  // like = ROOT::Math::landau_pdf(arg2)/sigmal2;
1203  like = ROOT::Math::landau_pdf(arg2);
1204  if (like < 1.e-30)
1205  like = 1.e-30;
1206  loglike2 += log(like);
1207  }
1208 
1209  // Calculate chisquare difference for the two hypotheses 9don't multiply by 2 for less inconvenient scaling
1210 
1211  deltachi2 = loglike1 - loglike2;
1212 
1213  if (deltachi2 < 0.) {
1214  // Flip the x1 and x2
1215 
1216  x1p = xrec1;
1217  xrec1 = xrec2;
1218  xrec2 = x1p;
1219  }
1220 
1221  // Return a positive definite value
1222 
1223  dchisq = fabs(deltachi2);
1224  }
1225 
1226  return 0;
1227 } // PixelTempSplit
1228 
1229 // *************************************************************************************************************************************
1252 // *************************************************************************************************************************************
1253 
1255  float cotalpha,
1256  float cotbeta,
1257  array_2d& cluster,
1258  std::vector<bool>& ydouble,
1259  std::vector<bool>& xdouble,
1260  SiPixelTemplate& templ,
1261  float& yrec1,
1262  float& yrec2,
1263  float& sigmay,
1264  float& prob2y,
1265  float& xrec1,
1266  float& xrec2,
1267  float& sigmax,
1268  float& prob2x,
1269  int& q2bin,
1270  float& prob2Q,
1271  bool resolve,
1272  int speed,
1273  float& dchisq,
1274  SiPixelTemplate2D& templ2D) {
1275  // Local variables
1276  const bool deadpix = false;
1277  std::vector<std::pair<int, int> > zeropix;
1278 
1280  cotalpha,
1281  cotbeta,
1282  cluster,
1283  ydouble,
1284  xdouble,
1285  templ,
1286  yrec1,
1287  yrec2,
1288  sigmay,
1289  prob2y,
1290  xrec1,
1291  xrec2,
1292  sigmax,
1293  prob2x,
1294  q2bin,
1295  prob2Q,
1296  resolve,
1297  speed,
1298  dchisq,
1299  deadpix,
1300  zeropix,
1301  templ2D);
1302 
1303 } // PixelTempSplit
1304 
1305 // *************************************************************************************************************************************
1328 // *************************************************************************************************************************************
1329 
1331  float cotalpha,
1332  float cotbeta,
1333  array_2d& cluster,
1334  std::vector<bool>& ydouble,
1335  std::vector<bool>& xdouble,
1336  SiPixelTemplate& templ,
1337  float& yrec1,
1338  float& yrec2,
1339  float& sigmay,
1340  float& prob2y,
1341  float& xrec1,
1342  float& xrec2,
1343  float& sigmax,
1344  float& prob2x,
1345  int& q2bin,
1346  float& prob2Q,
1347  bool resolve,
1348  float& dchisq,
1349  SiPixelTemplate2D& templ2D) {
1350  // Local variables
1351  const bool deadpix = false;
1352  std::vector<std::pair<int, int> > zeropix;
1353  const int speed = 1;
1354 
1356  cotalpha,
1357  cotbeta,
1358  cluster,
1359  ydouble,
1360  xdouble,
1361  templ,
1362  yrec1,
1363  yrec2,
1364  sigmay,
1365  prob2y,
1366  xrec1,
1367  xrec2,
1368  sigmax,
1369  prob2x,
1370  q2bin,
1371  prob2Q,
1372  resolve,
1373  speed,
1374  dchisq,
1375  deadpix,
1376  zeropix,
1377  templ2D);
1378 
1379 } // PixelTempSplit
1380 
1381 // *************************************************************************************************************************************
1402 // *************************************************************************************************************************************
1403 
1405  float cotalpha,
1406  float cotbeta,
1407  array_2d& cluster,
1408  std::vector<bool>& ydouble,
1409  std::vector<bool>& xdouble,
1410  SiPixelTemplate& templ,
1411  float& yrec1,
1412  float& yrec2,
1413  float& sigmay,
1414  float& prob2y,
1415  float& xrec1,
1416  float& xrec2,
1417  float& sigmax,
1418  float& prob2x,
1419  int& q2bin,
1420  float& prob2Q,
1421  SiPixelTemplate2D& templ2D) {
1422  // Local variables
1423  const bool deadpix = false;
1424  const bool resolve = true;
1425  float dchisq;
1426  std::vector<std::pair<int, int> > zeropix;
1427  const int speed = 1;
1428 
1430  cotalpha,
1431  cotbeta,
1432  cluster,
1433  ydouble,
1434  xdouble,
1435  templ,
1436  yrec1,
1437  yrec2,
1438  sigmay,
1439  prob2y,
1440  xrec1,
1441  xrec2,
1442  sigmax,
1443  prob2x,
1444  q2bin,
1445  prob2Q,
1446  resolve,
1447  speed,
1448  dchisq,
1449  deadpix,
1450  zeropix,
1451  templ2D);
1452 
1453 } // PixelTempSplit
1454 
1455 // *************************************************************************************************************************************
1475 // *************************************************************************************************************************************
1476 
1478  float cotalpha,
1479  float cotbeta,
1480  array_2d& cluster,
1481  std::vector<bool>& ydouble,
1482  std::vector<bool>& xdouble,
1483  SiPixelTemplate& templ,
1484  float& yrec1,
1485  float& yrec2,
1486  float& sigmay,
1487  float& prob2y,
1488  float& xrec1,
1489  float& xrec2,
1490  float& sigmax,
1491  float& prob2x,
1492  int& q2bin,
1493  SiPixelTemplate2D& templ2D) {
1494  // Local variables
1495  const bool deadpix = false;
1496  const bool resolve = true;
1497  float dchisq, prob2Q;
1498  std::vector<std::pair<int, int> > zeropix;
1499  const int speed = 1;
1500 
1502  cotalpha,
1503  cotbeta,
1504  cluster,
1505  ydouble,
1506  xdouble,
1507  templ,
1508  yrec1,
1509  yrec2,
1510  sigmay,
1511  prob2y,
1512  xrec1,
1513  xrec2,
1514  sigmax,
1515  prob2x,
1516  q2bin,
1517  prob2Q,
1518  resolve,
1519  speed,
1520  dchisq,
1521  deadpix,
1522  zeropix,
1523  templ2D);
1524 
1525 } // PixelTempSplit
float yrmsc2m(int i)
1st pass chi2 min search: average y-rms of reconstruction binned in 4 charge bins ...
void vavilov2_pars(double &mpv, double &sigma, double &kappa)
#define BXSIZE
float chi2xminone()
//!< minimum of x chi^2 for 1 pixel clusters
float chi2yavgc2m(int i)
1st pass chi2 min search: average y-chisq for merged clusters
bool interpolate(int id, float cotalpha, float cotbeta, float locBz, float locBx)
bool xytemp(float xhit, float yhit, bool ydouble[21+2], bool xdouble[13+2], float template2d[13+2][21+2], bool dervatives, float dpdx2d[2][13+2][21+2], float &QTemplate)
float symax()
average pixel signal for y-projection of cluster
int cytemp()
Return central pixel of y template pixels above readout threshold.
#define BYSIZE
void xsigma2(int fxpix, int lxpix, float sxthr, float xsum[13+4], float xsig2[13+4])
#define TXSIZE
#define LOGERROR(x)
#define BXM3
#define BXM1
bool simpletemplate2D(float xhitp, float yhitp, std::vector< bool > &ydouble, std::vector< bool > &xdouble, float template2d[13+2][21+2])
Make simple 2-D templates from track angles set in interpolate and hit position.
float qmin()
minimum cluster charge for valid hit (keeps 99.9% of simulated hits)
float xavgc2m(int i)
1st pass chi2 min search: average x-bias of reconstruction binned in 4 charge bins ...
static const int maxpix
const Int_t ysize
float sytwo()
rms for one double-pixel y-clusters
assert(be >=bs)
#define ENDL
float chi2yminone()
//!< minimum of y chi^2 for 1 pixel clusters
float sxone()
rms for one pixel x-clusters
#define BYM1
#define BXM2
int cxtemp()
Return central pixel of x-template pixels above readout threshold.
float qscale()
charge scaling factor
float chi2xavgc2m(int i)
1st pass chi2 min search: average x-chisq for merged clusters
float dxone()
mean offset/correction for one pixel x-clusters
T sqrt(T t)
Definition: SSEVec.h:23
#define BHX
void ytemp3d(int j, int k, std::vector< float > &ytemplate)
int PixelTempSplit(int id, float cotalpha, float cotbeta, array_2d &cluster, std::vector< bool > &ydouble, std::vector< bool > &xdouble, SiPixelTemplate &templ, float &yrec1, float &yrec2, float &sigmay, float &prob2y, float &xrec1, float &xrec2, float &sigmax, float &prob2x, int &q2bin, float &prob2Q, bool resolve, int speed, float &dchisq, bool deadpix, std::vector< std::pair< int, int > > &zeropix, SiPixelTemplate2D &templ2D)
#define LOGDEBUG(x)
float xsize()
pixel x-size (microns)
void ysigma2(int fypix, int lypix, float sythr, float ysum[21+4], float ysig2[21+4])
#define BYM2
double f[11][100]
float sxtwo()
rms for one double-pixel x-clusters
#define BYM3
float dytwo()
mean offset/correction for one double-pixel y-clusters
float s50()
1/2 of the pixel threshold signal in electrons
float yavgc2m(int i)
1st pass chi2 min search: average y-bias of reconstruction binned in 4 charge bins ...
void xtemp3d(int j, int k, std::vector< float > &xtemplate)
#define TYSIZE
float syone()
rms for one pixel y-clusters
void ytemp3d_int(int nypix, int &nybins)
float chi2yavgone()
//!< average y chi^2 for 1 pixel clusters
void xtemp3d_int(int nxpix, int &nxbins)
float qavg()
average cluster charge for this set of track angles
#define BHY
float sxmax()
average pixel signal for x-projection of cluster
double fcn(double x) const
Definition: VVIObj.cc:137
Definition: VVIObj.h:24
float chi2xavgone()
//!< average x chi^2 for 1 pixel clusters
float pixmax()
maximum pixel charge
void landau_par(float lanpar[2][5])
Return the Landau probability parameters for this set of cot(alpha, cot(beta)
static constexpr int theVerboseLevel
const Int_t xsize
float dyone()
mean offset/correction for one pixel y-clusters
float dxtwo()
mean offset/correction for one double-pixel x-clusters
boost::multi_array< float, 2 > array_2d
float ysize()
pixel y-size (microns)
float xrmsc2m(int i)
1st pass chi2 min search: average x-rms of reconstruction binned in 4 charge bins ...