CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
SiStripTemplateReco.cc
Go to the documentation of this file.
1 //
2 // SiStripTemplateReco.cc Version 2.01 (V1.00 based on SiPixelTemplateReco Version 8.20)
3 //
4 // V1.05 - add VI optimizations from pixel reco
5 // V1.07 - Improve cluster centering
6 // V2.00 - Change to chi2min estimator and choose barycenter when errors/bias are large
7 // - Increase buffer size to avoid truncation
8 // - Change pseudo-strip weighting to accommodate asymmetric clusters (deco mode)
9 // - Remove obsolete sorting of signal for weighting (truncation makes it worthless)
10 // V2.01 - Add barycenter bias correction
11 //
12 //
13 //
14 // Created by Morris Swartz on 10/27/06.
15 //
16 //
17 
18 #include <math.h>
19 #include <algorithm>
20 #include <vector>
21 #include <utility>
22 #include <iostream>
23 // ROOT::Math has a c++ function that does the probability calc, but only in v5.12 and later
24 #include "TMath.h"
25 #include "Math/DistFunc.h"
26 // Use current version of gsl instead of ROOT::Math
27 //#include <gsl/gsl_cdf.h>
28 
29 #ifndef SI_PIXEL_TEMPLATE_STANDALONE
33 #define LOGERROR(x) edm::LogError(x)
34 #define LOGDEBUG(x) LogDebug(x)
36 #define ENDL " "
38 #else
39 #include "SiStripTemplateReco.h"
40 #include "VVIObj.h"
41 //static int theVerboseLevel = {2};
42 #define LOGERROR(x) std::cout << x << ": "
43 #define LOGDEBUG(x) std::cout << x << ": "
44 #define ENDL std::endl
45 #endif
46 
47 using namespace SiStripTemplateReco;
48 
49 // *************************************************************************************************************************************
83 // *************************************************************************************************************************************
84 int SiStripTemplateReco::StripTempReco1D(int id, float cotalpha, float cotbeta, float locBy, std::vector<float>& cluster,
85  SiStripTemplate& templ,
86  float& xrec, float& sigmax, float& probx, int& qbin, int speed, float& probQ)
87 
88 {
89  // Local variables
90  int i, j, minbin, binl, binh, binq, midpix;
91  int fxpix, nxpix, lxpix, logxpx, shiftx, ftpix, ltpix;
92  int nclusx;
93  int deltaj, jmin, jmax, fxbin, lxbin, djx;
94  float sxthr, rnorm, delta, sigma, pseudopix, qscale, q50, q100;
95  float ss2, ssa, sa2, ssba, saba, sba2, rat, fq, qtotal, barycenter, sigmaxbcn;
96  float originx, qfx, qlx, bias, biasbcn, maxpix;
97  double chi2x, meanx, chi2xmin, chi21max;
98  double hchi2, hndof, prvav, mpv, sigmaQ, kappa, xvav, beta2;
99  float xtemp[41][BSXSIZE], xsum[BSXSIZE];
100  float chi2xbin[41], xsig2[BSXSIZE];
101  float xw2[BSXSIZE], xsw[BSXSIZE];
102  bool calc_probQ, use_VVIObj;
103  float xsize;
104  const float probmin={1.110223e-16};
105  const float probQmin={1.e-5};
106 
107 // The minimum chi2 for a valid one pixel cluster = pseudopixel contribution only
108 
109  const double mean1pix={0.100}, chi21min={0.160};
110 
111 // First, interpolate the template needed to analyze this cluster
112 // check to see of the track direction is in the physical range of the loaded template
113 
114  if(!templ.interpolate(id, cotalpha, cotbeta, locBy)) {
115  if (theVerboseLevel > 2) {LOGDEBUG("SiStripTemplateReco") << "input cluster direction cot(alpha) = " << cotalpha << ", cot(beta) = " << cotbeta << ", local B_y = " << locBy << ", template ID = " << id << ", no reconstruction performed" << ENDL;}
116  return 20;
117  }
118 
119 // Check to see if Q probability is selected
120 
121  calc_probQ = false;
122  use_VVIObj = false;
123  if(speed < 0) {
124  calc_probQ = true;
125  if(speed < -1) use_VVIObj = true;
126  speed = 0;
127  }
128 
129  if(speed > 3) {
130  calc_probQ = true;
131  if(speed < 5) use_VVIObj = true;
132  speed = 3;
133  }
134 
135 // Get pixel dimensions from the template (to allow multiple detectors in the future)
136 
137  xsize = templ.xsize();
138 
139 // Define size of pseudopixel
140 
141  q50 = templ.s50();
142  q100 = 2.f * q50;
143  pseudopix = q50;
144 
145 // Get charge scaling factor
146 
147  qscale = templ.qscale();
148 
149 // enforce maximum size
150 
151  nclusx = (int)cluster.size();
152 
153  if(nclusx > TSXSIZE) {nclusx = TSXSIZE;}
154 
155 // First, rescale all strip charges, sum them and trunate the strip charges
156 
157  qtotal = 0.;
158  for(i=0; i<BSXSIZE; ++i) {xsum[i] = 0.f;}
159  maxpix = templ.sxmax();
160  barycenter = 0.f;
161  for(j=0; j<nclusx; ++j) {
162  xsum[j] = qscale*cluster[j];
163  qtotal += xsum[j];
164  barycenter += j*xsize*xsum[j];
165  if(xsum[j] > maxpix) {xsum[j] = maxpix;}
166  }
167 
168  barycenter = barycenter/qtotal - 0.5f*templ.lorxwidth();
169 
170 // next, identify the x-cluster ends, count total pixels, nxpix, and logical pixels, logxpx
171 
172  fxpix = -1;
173  ftpix = -1;
174  nxpix=0;
175  lxpix=0;
176  ltpix=0;
177  logxpx=0;
178  for(i=0; i<BSXSIZE; ++i) {
179  if(xsum[i] > 0.f) {
180  if(fxpix == -1) {fxpix = i;}
181  ++logxpx;
182  ++nxpix;
183  lxpix = i;
184  if(xsum[i] > q100) {
185  if(ftpix == -1) {ftpix = i;}
186  ltpix = i;
187  }
188  }
189  }
190 
191 
192 // dlengthx = (float)nxpix - templ.clslenx();
193 
194 // Make sure cluster is continuous
195 
196  if((lxpix-fxpix+1) != nxpix) {
197 
198  LOGDEBUG("SiStripTemplateReco") << "x-length of pixel cluster doesn't agree with number of pixels above threshold" << ENDL;
199  if (theVerboseLevel > 2) {
200  LOGDEBUG("SiStripTemplateReco") << "xsum[] = ";
201  for(i=0; i<BSXSIZE-1; ++i) {LOGDEBUG("SiStripTemplateReco") << xsum[i] << ", ";}
202  LOGDEBUG("SiStripTemplateReco") << ENDL;
203  }
204 
205  return 2;
206  }
207 
208 // If cluster is longer than max template size, technique fails
209 
210  if(nxpix > TSXSIZE) {
211 
212  LOGDEBUG("SiStripTemplateReco") << "x-length of pixel cluster is larger than maximum template size" << ENDL;
213  if (theVerboseLevel > 2) {
214  LOGDEBUG("SiStripTemplateReco") << "xsum[] = ";
215  for(i=0; i<BSXSIZE-1; ++i) {LOGDEBUG("SiStripTemplateReco") << xsum[i] << ", ";}
216  LOGDEBUG("SiStripTemplateReco") << ENDL;
217  }
218 
219  return 7;
220  }
221 
222 // next, center the cluster on template center if necessary
223 
224  midpix = (ftpix+ltpix)/2;
225  shiftx = templ.cxtemp() - midpix;
226 
227  if(shiftx > 0) {
228  for(i=lxpix; i>=fxpix; --i) {
229  xsum[i+shiftx] = xsum[i];
230  xsum[i] = 0.f;
231  }
232  } else if (shiftx < 0) {
233  for(i=fxpix; i<=lxpix; ++i) {
234  xsum[i+shiftx] = xsum[i];
235  xsum[i] = 0.f;
236  }
237  }
238  lxpix +=shiftx;
239  fxpix +=shiftx;
240 
241 // If the cluster boundaries are OK, add pesudopixels, otherwise quit
242 
243  if(fxpix > 1 && fxpix < BSXM2) {
244  xsum[fxpix-1] = pseudopix;
245  xsum[fxpix-2] = 0.2f*pseudopix;
246  } else {return 9;}
247  if(lxpix > 1 && lxpix < BSXM2) {
248  xsum[lxpix+1] = pseudopix;
249  xsum[lxpix+2] = 0.2f*pseudopix;
250  } else {return 9;}
251 
252 // finally, determine if pixel[0] is a double pixel and make an origin correction if it is
253 
254  originx = 0.f;
255 
256 // uncertainty and final corrections depend upon total charge bin
257 
258  fq = qtotal/templ.qavg();
259  if(fq > 1.5f) {
260  binq=0;
261  } else {
262  if(fq > 1.0f) {
263  binq=1;
264  } else {
265  if(fq > 0.85f) {
266  binq=2;
267  } else {
268  binq=3;
269  }
270  }
271  }
272 
273 // Return the charge bin via the parameter list unless the charge is too small (then flag it)
274 
275  qbin = binq;
276  if(qtotal < 0.95f*templ.qmin()) {qbin = 5;} else {
277  if(qtotal < 0.95f*templ.qmin(1)) {qbin = 4;}
278  }
279  if (theVerboseLevel > 9) {
280  LOGDEBUG("SiStripTemplateReco") <<
281  "ID = " << id <<
282  " cot(alpha) = " << cotalpha << " cot(beta) = " << cotbeta <<
283  " nclusx = " << nclusx << ENDL;
284  }
285 
286 
287 // Next, copy the y- and x-templates to local arrays
288 
289 // First, decide on chi^2 min search parameters
290 
291 #ifndef SI_PIXEL_TEMPLATE_STANDALONE
292  if(speed < 0 || speed > 3) {
293  throw cms::Exception("DataCorrupt") << "SiStripTemplateReco::StripTempReco2D called with illegal speed = " << speed << std::endl;
294  }
295 #else
296  assert(speed >= 0 && speed < 4);
297 #endif
298  fxbin = 2; lxbin = 38; djx = 1;
299  if(speed > 0) {
300  fxbin = 8; lxbin = 32;
301  }
302 
303  if(speed > 1) {
304  djx = 2;
305  if(speed > 2) {
306  djx = 4;
307  }
308  }
309 
310  if (theVerboseLevel > 9) {
311  LOGDEBUG("SiStripTemplateReco") <<
312  "fxpix " << fxpix << " lxpix = " << lxpix <<
313  " fxbin = " << fxbin << " lxbin = " << lxbin <<
314  " djx = " << djx << " logxpx = " << logxpx << ENDL;
315  }
316 
317 // Now do the copies
318 
319  templ.xtemp(fxbin, lxbin, xtemp);
320 
321 // Do the x-reconstruction next
322 
323 // Apply the first-pass template algorithm to all clusters
324 
325 // Modify the template if double pixels are present
326 
327 // Define the maximum signal to allow before de-weighting a pixel
328 
329  sxthr = 1.1f*maxpix;
330 
331 // Evaluate pixel-by-pixel uncertainties (weights) for the templ analysis
332 
333 // for(i=0; i<BSXSIZE; ++i) { xsig2[i] = 0.; }
334  templ.xsigma2(fxpix, lxpix, sxthr, xsum, xsig2);
335 
336 // Find the template bin that minimizes the Chi^2
337 
338  chi2xmin = 1.e15;
339  for(i=fxbin; i<=lxbin; ++i) { chi2xbin[i] = -1.e15f;}
340  ss2 = 0.f;
341  for(i=fxpix-2; i<=lxpix+2; ++i) {
342  xw2[i] = 1.f/xsig2[i];
343  xsw[i] = xsum[i]*xw2[i];
344  ss2 += xsum[i]*xsw[i];
345  }
346  minbin = -1;
347  deltaj = djx;
348  jmin = fxbin;
349  jmax = lxbin;
350  while(deltaj > 0) {
351  for(j=jmin; j<=jmax; j+=deltaj) {
352  if(chi2xbin[j] < -100.f) {
353  ssa = 0.f;
354  sa2 = 0.f;
355  for(i=fxpix-2; i<=lxpix+2; ++i) {
356  ssa += xsw[i]*xtemp[j][i];
357  sa2 += xtemp[j][i]*xtemp[j][i]*xw2[i];
358  }
359  rat=ssa/ss2;
360  if(rat <= 0.f) {LOGERROR("SiStripTemplateReco") << "illegal chi2xmin normalization (1) = " << rat << ENDL; rat = 1.;}
361  chi2xbin[j]=ss2-2.*ssa/rat+sa2/(rat*rat);
362  }
363  if(chi2xbin[j] < chi2xmin) {
364  chi2xmin = chi2xbin[j];
365  minbin = j;
366  }
367  }
368  deltaj /= 2;
369  if(minbin > fxbin) {jmin = minbin - deltaj;} else {jmin = fxbin;}
370  if(minbin < lxbin) {jmax = minbin + deltaj;} else {jmax = lxbin;}
371  }
372 
373  if (theVerboseLevel > 9) {
374  LOGDEBUG("SiStripTemplateReco") <<
375  "minbin " << minbin << " chi2xmin = " << chi2xmin << ENDL;
376  }
377 
378 // Do not apply final template pass to 1-pixel clusters (use calibrated offset)
379 
380  if(nxpix == 1) {
381 
382  delta = templ.dxone();
383  sigma = templ.sxone();
384  xrec = 0.5f*(fxpix+lxpix-2*shiftx+2.f*originx)*xsize-delta;
385  if(sigma <= 0.f) {
386  sigmax = 28.9f;
387  } else {
388  sigmax = sigma;
389  }
390 
391 // Do probability calculation for one-pixel clusters
392 
393  chi21max = fmax(chi21min, (double)templ.chi2xminone());
394  chi2xmin -=chi21max;
395  if(chi2xmin < 0.) {chi2xmin = 0.;}
396  meanx = fmax(mean1pix, (double)templ.chi2xavgone());
397  hchi2 = chi2xmin/2.; hndof = meanx/2.;
398  probx = 1. - TMath::Gamma(hndof, hchi2);
399 
400  } else {
401 
402 // Now make the second, interpolating pass with the templates
403 
404  binl = minbin - 1;
405  binh = binl + 2;
406  if(binl < fxbin) { binl = fxbin;}
407  if(binh > lxbin) { binh = lxbin;}
408  ssa = 0.;
409  sa2 = 0.;
410  ssba = 0.;
411  saba = 0.;
412  sba2 = 0.;
413  for(i=fxpix-2; i<=lxpix+2; ++i) {
414  ssa += xsw[i]*xtemp[binl][i];
415  sa2 += xtemp[binl][i]*xtemp[binl][i]*xw2[i];
416  ssba += xsw[i]*(xtemp[binh][i] - xtemp[binl][i]);
417  saba += xtemp[binl][i]*(xtemp[binh][i] - xtemp[binl][i])*xw2[i];
418  sba2 += (xtemp[binh][i] - xtemp[binl][i])*(xtemp[binh][i] - xtemp[binl][i])*xw2[i];
419  }
420 
421 // rat is the fraction of the "distance" from template a to template b
422 
423  rat=(ssba*ssa-ss2*saba)/(ss2*sba2-ssba*ssba);
424  if(rat < 0.f) {rat=0.f;}
425  if(rat > 1.f) {rat=1.0f;}
426  rnorm = (ssa+rat*ssba)/ss2;
427 
428 // Calculate the charges in the first and last pixels
429 
430  qfx = xsum[fxpix];
431  if(logxpx > 1) {
432  qlx=xsum[lxpix];
433  } else {
434  qlx = qfx;
435  }
436 
437 // Now calculate the mean bias correction and uncertainties
438 
439  float qxfrac = (qfx-qlx)/(qfx+qlx);
440  bias = templ.xflcorr(binq,qxfrac)+templ.xavg(binq);
441 
442 // uncertainty and final correction depend upon charge bin
443 
444  xrec = (0.125f*binl+BSHX-2.5f+rat*(binh-binl)*0.125f-(float)shiftx+originx)*xsize - bias;
445  sigmax = templ.xrms(binq);
446 
447 // Do goodness of fit test in x
448 
449  if(rnorm <= 0.f) {LOGERROR("SiStripTemplateReco") << "illegal chi2x normalization (2) = " << rnorm << ENDL; rnorm = 1.;}
450  chi2x=ss2-2.f/rnorm*ssa-2.f/rnorm*rat*ssba+(sa2+2.f*rat*saba+rat*rat*sba2)/(rnorm*rnorm)-templ.chi2xmin(binq);
451  if(chi2x < 0.0) {chi2x = 0.0;}
452  meanx = templ.chi2xavg(binq);
453  if(meanx < 0.01) {meanx = 0.01;}
454  // gsl function that calculates the chi^2 tail prob for non-integral dof
455  // probx = gsl_cdf_chisq_Q(chi2x, meanx);
456  // probx = ROOT::Math::chisquared_cdf_c(chi2x, meanx, trx0);
457  hchi2 = chi2x/2.; hndof = meanx/2.;
458  probx = 1. - TMath::Gamma(hndof, hchi2);
459 
460 // Now choose the better result
461 
462  bias = templ.xavg(binq);
463  biasbcn = templ.xavgbcn(binq);
464  sigmaxbcn = templ.xrmsbcn(binq);
465 
466  if((bias*bias+sigmax*sigmax) > (biasbcn*biasbcn+sigmaxbcn*sigmaxbcn)) {
467 
468  xrec = barycenter - biasbcn;
469  sigmax = sigmaxbcn;
470 
471  }
472 
473  }
474 
475 // Don't return exact zeros for the probability
476 
477  if(probx < probmin) {probx = probmin;}
478 
479 // Decide whether to generate a cluster charge probability
480 
481  if(calc_probQ) {
482 
483 // Calculate the Vavilov probability that the cluster charge is OK
484 
485  templ.vavilov_pars(mpv, sigmaQ, kappa);
486 #ifndef SI_PIXEL_TEMPLATE_STANDALONE
487  if((sigmaQ <=0.) || (mpv <= 0.) || (kappa < 0.01) || (kappa > 9.9)) {
488  throw cms::Exception("DataCorrupt") << "SiStripTemplateReco::Vavilov parameters mpv/sigmaQ/kappa = " << mpv << "/" << sigmaQ << "/" << kappa << std::endl;
489  }
490 #else
491  assert((sigmaQ > 0.) && (mpv > 0.) && (kappa > 0.01) && (kappa < 10.));
492 #endif
493  xvav = ((double)qtotal-mpv)/sigmaQ;
494  beta2 = 1.;
495  if(use_VVIObj) {
496 // VVIObj is a private port of CERNLIB VVIDIS
497  sistripvvi::VVIObj vvidist(kappa, beta2, 1);
498  prvav = vvidist.fcn(xvav);
499  } else {
500 // Use faster but less accurate TMath Vavilov distribution function
501  prvav = TMath::VavilovI(xvav, kappa, beta2);
502  }
503 // Change to upper tail probability
504 // if(prvav > 0.5) prvav = 1. - prvav;
505 // probQ = (float)(2.*prvav);
506  probQ = 1. - prvav;
507  if(probQ < probQmin) {probQ = probQmin;}
508  } else {
509  probQ = -1;
510  }
511 
512  return 0;
513 } // StripTempReco2D
514 
dbl * delta
Definition: mlp_gen.cc:36
int i
Definition: DBlmapReader.cc:9
void xsigma2(int fxstrp, int lxstrp, float sxthr, float xsum[BSXSIZE], float xsig2[BSXSIZE])
float chi2xavg(int i)
averaage x chi^2 in 4 charge bins
#define BSXSIZE
float xsize()
strip x-size (microns)
void vavilov_pars(double &mpv, double &sigma, double &kappa)
#define BSHX
float qavg()
average cluster charge for this set of track angles
float chi2xminone()
//!&lt; minimum of x chi^2 for 1 strip clusters
static const int maxpix
#define ENDL
float xrmsbcn(int i)
1st pass chi2 min search: average x-rms of reconstruction binned in 4 charge bins ...
float lorxwidth()
signed lorentz x-width (microns)
float xflcorr(int binq, float qflx)
float qmin()
minimum cluster charge for valid hit (keeps 99.9% of simulated hits)
double fcn(double x) const
Definition: VVIObj.cc:139
static int theVerboseLevel
int cxtemp()
Return central pixel of x-template pixels above readout threshold.
float xavg(int i)
average x-bias of reconstruction binned in 4 charge bins
float dxone()
mean offset/correction for one strip x-clusters
int StripTempReco1D(int id, float cotalpha, float cotbeta, float locBy, std::vector< float > &cluster, SiStripTemplate &templ, float &xrec, float &sigmax, float &probx, int &qbin, int speed, float &probQ)
int j
Definition: DBlmapReader.cc:9
double f[11][100]
float qscale()
charge scaling factor
float xavgbcn(int i)
1st pass chi2 min search: average x-bias of reconstruction binned in 4 charge bins ...
float chi2xavgone()
//!&lt; average x chi^2 for 1 strip clusters
float chi2xmin(int i)
minimum y chi^2 in 4 charge bins
float xrms(int i)
average x-rms of reconstruction binned in 4 charge bins
float s50()
1/2 of the strip threshold signal in electrons
float sxone()
rms for one strip x-clusters
float sxmax()
average strip signal for x-projection of cluster
dbl * Gamma
Definition: mlp_gen.cc:38
static const G4double kappa
#define LOGERROR(x)
bool interpolate(int id, float cotalpha, float cotbeta, float locBy)
#define LOGDEBUG(x)
void xtemp(int fxbin, int lxbin, float xtemplate[41][BSXSIZE])
#define constexpr
#define TSXSIZE
#define BSXM2