SiPixelTemplate

SiPixelTemplateEntry

SiPixelTemplateHeader

SiPixelTemplateStore

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
//
//  SiPixelTemplate.h (v10.24)
//
//  Add goodness-of-fit info and spare entries to templates, version number in template header, more error checking
//  Add correction for (Q_F-Q_L)/(Q_F+Q_L) bias
//  Add cot(beta) reflection to reduce y-entries and more sophisticated x-interpolation
//  Fix small index searching bug in interpolate method
//  Change interpolation indexing to avoid complier complaining about possible un-initialized variables
//  Replace containers with static arrays in calls to ysigma2 and xsigma2
//  Add external threshold to calls to ysigma2 and xsigma2, fix parameter signal max for xsigma2
//  Return to 5 pixel spanning but adjust boundaries to use only when needed
//  Implement improved (faster) chi2min search that depends on pixel types
//  Fill template arrays in single calls to this object
//  Add qmin to the template
//  Add qscale to match charge scales
//  Small improvement to x-chisquare interpolation
//  Enlarge SiPixelTemplateStore to accommodate larger templates and increased alpha acceptance (reduce PT threshold to ~200 MeV)
//  Store x and y cluster sizes in fractional pixels to facilitate cluster splitting
//  Keep interpolated central 9 template bins in private storage and expand/shift in the getter functions (faster for speed=2/3) and easier to build 3d templates
//  Store error and bias information for the simple chi^2 min position analysis (no interpolation or Q_{FB} corrections) to use in cluster splitting
//  To save time, the gaussian centers and sigma are not interpolated right now (they aren't currently used).  They can be restored by un-commenting lines in the interpolate method.
//  Add a new method to calculate qbin for input cotbeta and cluster charge.  To be used for error estimation of merged clusters in PixelCPEGeneric.
//  Add bias info for Barrel and FPix separately in the header
//  Improve the charge estimation for larger cot(alpha) tracks
//  Change interpolate method to return false boolean if track angles are outside of range
//  Add template info and method for truncation information
//  Change to allow template sizes to be changed at compile time
//  Fix bug in track angle checking
//  Accommodate Dave's new DB pushfile which overloads the old method (file input)
//  Add CPEGeneric error information and expand qbin method to access useful info for PixelCPEGeneric
//  Fix large cot(alpha) bug in qmin interpolation
//  Add second qmin to allow a qbin=5 state
//  Use interpolated chi^2 info for one-pixel clusters
//  Separate BPix and FPix charge scales and thresholds
//  Fix DB pushfile version number checking bug.
//  Remove assert from qbin method
//  Replace asserts with exceptions in CMSSW
//  Change calling sequence to interpolate method to handle cot(beta)<0 for FPix cosmics
//  Add getter for pixelav Lorentz width estimates to qbin method
//  Add check on template size to interpolate and qbin methods
//  Add qbin population information, charge distribution information
//
//  V7.00 - Decouple BPix and FPix information into separate templates
//  Add methods to facilitate improved cluster splitting
//  Fix small charge scaling bug (affects FPix only)
//  Change y-slice used for the x-template to be closer to the actual cotalpha-cotbeta point
//  (there is some weak breakdown of x-y factorization in the FPix after irradiation)
//
//  V8.00 - Add method to calculate a simple 2D template
//  Reorganize the interpolate method to extract header info only once per ID
//  V8.01 - Improve simple template normalization
//  V8.05 - Change qbin normalization to work better after irradiation
//  V8.10 - Add Vavilov distribution interpolation
//  V8.11 - Renormalize the x-templates for Guofan's cluster size calculation
//  V8.12 - Technical fix to qavg issue.
//  V8.13 - Fix qbin and fastsim interpolaters to avoid changing class variables
//  V8.20 - Add methods to identify the central pixels in the x- and y-templates (to help align templates with clusters in radiation damaged detectors)
//          Rename class variables from pxxxx (private xxxx) to xxxx_ to follow standard convention.
//          Add compiler option to store the template entries in BOOST multiarrays of structs instead of simple c arrays
//          (allows dynamic resizing template storage and has bounds checking but costs ~10% in execution time).
//  V8.21 - Add new qbin method to use in cluster splitting
//  V8.23 - Replace chi-min position errors with merged cluster chi2 probability info
//  V8.25 - Incorporate VI's speed changes into the current version
//  V8.26 - Modify the Vavilov lookups to work better with the FPix (offset y-templates)
//  V8.30 - Change the splitting template generation and access to improve speed and eliminate triple index boost::multiarray
//  V8.31 - Add correction factor: measured/true charge
//  V8.31 - Fix version number bug in db object I/O (pushfile)
//  V8.32 - Check for illegal qmin during loading
//  V8.33 - Fix small type conversion warnings
//  V8.40 - Incorporate V.I. optimizations
//  V9.00 - Expand header to include multi and single dcol thresholds, LA biases, and (variable) Qbin definitions
//  V9.01 - Protect against negative error squared
//  V10.00 - Update to work with Phase 1 FPix.  Fix some code problems introduced by other maintainers.
//  V10.01 - Fix initialization style as suggested by S. Krutelyov
//  V10.10 - Add class variables and methods to correctly calculate the probabilities of single pixel clusters
//  V10.11 - Allow subdetector ID=5 for FPix R2P2 [allows better internal labeling of templates]
//  V10.12 - Enforce minimum signal size in pixel charge uncertainty calculation
//  V10.13 - Update the variable size [SI_PIXEL_TEMPLATE_USE_BOOST] option so that it works with VI's enhancements
//  V10.20 - Add directory path selection to the ascii pushfile method
//  V10.21 - Address runtime issues in pushfile() for gcc 7.X due to using tempfile as char string + misc. cleanup [Petar]
//  V10.22 - Move templateStore to the heap, fix variable name in pushfile() [Petar]
//  V10.24 - Add sideload() + associated gymnastics [Petar and Oz]

// Created by Morris Swartz on 10/27/06.
//
//

// Build the template storage structure from several pieces

#ifndef SiPixelTemplate_h
#define SiPixelTemplate_h 1

#include "SiPixelTemplateDefs.h"

#include <vector>
#include <cassert>
#include "boost/multi_array.hpp"

#ifndef SI_PIXEL_TEMPLATE_STANDALONE
#include "CondFormats/SiPixelObjects/interface/SiPixelTemplateDBObject.h"
#include "FWCore/Utilities/interface/Exception.h"
#endif

struct SiPixelTemplateEntry {  //!< Basic template entry corresponding to a single set of track angles
  int runnum;                  //!< number of pixelav run used to generate this entry
  float alpha;                 //!< alpha track angle (defined in CMS CMS IN 2004/014)
  float cotalpha;              //!< cot(alpha) is proportional to cluster length in x and is basis of interpolation
  float beta;                  //!< beta track angle (defined in CMS CMS IN 2004/014)
  float cotbeta;               //!< cot(beta) is proportional to cluster length in y and is basis of interpolation
  float costrk[3];             //!< direction cosines of tracks used to generate this entry
  float qavg;                  //!< average cluster charge for this set of track angles (now includes threshold effects)
  float pixmax;                //!< maximum charge for individual pixels in cluster
  float symax;                 //!< average pixel signal for y-projection of cluster
  float dyone;                 //!< mean offset/correction for one pixel y-clusters
  float syone;                 //!< rms for one pixel y-clusters
  float sxmax;                 //!< average pixel signal for x-projection of cluster
  float dxone;                 //!< mean offset/correction for one pixel x-clusters
  float sxone;                 //!< rms for one pixel x-clusters
  float dytwo;                 //!< mean offset/correction for one double-pixel y-clusters
  float sytwo;                 //!< rms for one double-pixel y-clusters
  float dxtwo;                 //!< mean offset/correction for one double-pixel x-clusters
  float sxtwo;                 //!< rms for one double-pixel x-clusters
  float qmin;                  //!< minimum cluster charge for valid hit (keeps 99.9% of simulated hits)
  float qmin2;                 //!< tighter minimum cluster charge for valid hit (keeps 99.8% of simulated hits)
  float yavggen[4];            //!< generic algorithm: average y-bias of reconstruction binned in 4 charge bins
  float yrmsgen[4];            //!< generic algorithm: average y-rms of reconstruction binned in 4 charge bins
  float xavggen[4];            //!< generic algorithm: average x-bias of reconstruction binned in 4 charge bins
  float xrmsgen[4];            //!< generic algorithm: average x-rms of reconstruction binned in 4 charge bins

  float clsleny;   //!< cluster y-length in pixels at signal height symax/2
  float clslenx;   //!< cluster x-length in pixels at signal height sxmax/2
  float mpvvav;    //!< most probable charge in Vavilov distribution (not actually for larger kappa)
  float sigmavav;  //!< "sigma" scale fctor for Vavilov distribution
  float kappavav;  //!< kappa parameter for Vavilov distribution
  float mpvvav2;  //!< most probable charge in Vavilov distribution for 2 merged clusters (not actually for larger kappa)
  float sigmavav2;         //!< "sigma" scale fctor for Vavilov distribution for 2 merged clusters
  float kappavav2;         //!< kappa parameter for Vavilov distribution for 2 merged clusters
  float ypar[2][5];        //!< projected y-pixel uncertainty parameterization
  float ytemp[9][TYSIZE];  //!< templates for y-reconstruction (binned over 1 central pixel)
  float xpar[2][5];        //!< projected x-pixel uncertainty parameterization
  float xtemp[9][TXSIZE];  //!< templates for x-reconstruction (binned over 1 central pixel)
  float yavg[4];           //!< average y-bias of reconstruction binned in 4 charge bins
  float yrms[4];           //!< average y-rms of reconstruction binned in 4 charge bins
  float ygx0[4];           //!< average y0 from Gaussian fit binned in 4 charge bins
  float ygsig[4];          //!< average sigma_y from Gaussian fit binned in 4 charge bins
  float yflpar[4][6];      //!< Aqfl-parameterized y-correction in 4 charge bins
  float xavg[4];           //!< average x-bias of reconstruction binned in 4 charge bins
  float xrms[4];           //!< average x-rms of reconstruction binned in 4 charge bins
  float xgx0[4];           //!< average x0 from Gaussian fit binned in 4 charge bins
  float xgsig[4];          //!< average sigma_x from Gaussian fit binned in 4 charge bins
  float xflpar[4][6];      //!< Aqfl-parameterized x-correction in 4 charge bins
  float chi2yavg[4];       //!< average y chi^2 in 4 charge bins
  float chi2ymin[4];       //!< minimum of y chi^2 in 4 charge bins
  float chi2xavg[4];       //!< average x chi^2 in 4 charge bins
  float chi2xmin[4];       //!< minimum of x chi^2 in 4 charge bins
  float chi2yavgone;       //!< average y chi^2 for 1 pixel clusters
  float chi2yminone;       //!< minimum of y chi^2 for 1 pixel clusters
  float chi2xavgone;       //!< average x chi^2 for 1 pixel clusters
  float chi2xminone;       //!< minimum of x chi^2 for 1 pixel clusters
  float yavgc2m[4];        //!< 1st pass chi2 min search: average y-bias of reconstruction binned in 4 charge bins
  float yrmsc2m[4];        //!< 1st pass chi2 min search: average y-rms of reconstruction binned in 4 charge bins
  float chi2yavgc2m[4];    //!< 1st pass chi2 min search: average y chi^2 in 4 charge bins (merged clusters)
  float chi2yminc2m[4];    //!< 1st pass chi2 min search: minimum of y chi^2 in 4 charge bins (merged clusters)
  float xavgc2m[4];        //!< 1st pass chi2 min search: average x-bias of reconstruction binned in 4 charge bins
  float xrmsc2m[4];        //!< 1st pass chi2 min search: average x-rms of reconstruction binned in 4 charge bins
  float chi2xavgc2m[4];    //!< 1st pass chi2 min search: average x chi^2 in 4 charge bins (merged clusters)
  float chi2xminc2m[4];    //!< 1st pass chi2 min search: minimum of x chi^2 in 4 charge bins (merged clusters)
  float ygx0gen[4];        //!< generic algorithm: average y0 from Gaussian fit binned in 4 charge bins
  float ygsiggen[4];       //!< generic algorithm: average sigma_y from Gaussian fit binned in 4 charge bins
  float xgx0gen[4];        //!< generic algorithm: average x0 from Gaussian fit binned in 4 charge bins
  float xgsiggen[4];       //!< generic algorithm: average sigma_x from Gaussian fit binned in 4 charge bins
  float qbfrac[3];         //!< fraction of sample in qbin = 0-2 (>=3 is the complement)
  float fracyone;          //!< fraction of sample with ysize = 1
  float fracxone;          //!< fraction of sample with xsize = 1
  float fracytwo;          //!< fraction of double pixel sample with ysize = 1
  float fracxtwo;          //!< fraction of double pixel sample with xsize = 1
  float qavg_avg;       //!< average cluster charge of clusters that are less than qavg (normalize 2-D simple templates)
  float r_qMeas_qTrue;  //!< ratio of measured to true cluster charge
  float spare[1];
};

struct SiPixelTemplateHeader {  //!< template header structure
  int ID;                       //!< template ID number
  int NTy;                      //!< number of Template y entries
  int NTyx;                     //!< number of Template y-slices of x entries
  int NTxx;                     //!< number of Template x-entries in each slice
  int Dtype;                    //!< detector type (0=BPix, 1=FPix)
  float qscale;                 //!< Charge scaling to match cmssw and pixelav
  float lorywidth;              //!< estimate of y-lorentz width for optimal resolution
  float lorxwidth;              //!< estimate of x-lorentz width for optimal resolution
  float lorybias;               //!< estimate of y-lorentz bias
  float lorxbias;               //!< estimate of x-lorentz bias
  float Vbias;                  //!< detector bias potential in Volts
  float temperature;            //!< detector temperature in deg K
  float fluence;                //!< radiation fluence in n_eq/cm^2
  float s50;                    //!< 1/2 of the multihit dcol threshold in electrons
  float ss50;                   //!< 1/2 of the single hit dcol threshold in electrons
  char title[80];               //!< template title
  int templ_version;            //!< Version number of the template to ensure code compatibility
  float Bfield;                 //!< Bfield in Tesla
  float fbin[3];                //!< The QBin definitions in Q_clus/Q_avg
  float xsize;                  //!< pixel size (for future use in upgraded geometry)
  float ysize;                  //!< pixel size (for future use in upgraded geometry)
  float zsize;                  //!< pixel size (for future use in upgraded geometry)
};

struct SiPixelTemplateStore {  //!< template storage structure
  SiPixelTemplateHeader head;
#ifndef SI_PIXEL_TEMPLATE_USE_BOOST
  std::array<float, TEMP_ENTRY_SIZEY> cotbetaY;
  std::array<float, TEMP_ENTRY_SIZEX_B> cotbetaX;
  std::array<float, TEMP_ENTRY_SIZEX_A> cotalphaX;
  //!< 60 y templates spanning cluster lengths from 0px to +18px
  SiPixelTemplateEntry enty[TEMP_ENTRY_SIZEY];
  //!< 60 Barrel x templates spanning cluster lengths from -6px (-1.125Rad) to +6px (+1.125Rad) in each of 60 slices
  SiPixelTemplateEntry entx[TEMP_ENTRY_SIZEX_B][TEMP_ENTRY_SIZEX_A];
#else
  std::vector<float> cotbetaY;
  std::vector<float> cotbetaX;
  std::vector<float> cotalphaX;
  boost::multi_array<SiPixelTemplateEntry, 1> enty;  //!< use 1d entry to store [60] entries
  //!< use 2d entry to store [60][60] entries
  boost::multi_array<SiPixelTemplateEntry, 2> entx;
#endif
};

// ******************************************************************************************
//! \class SiPixelTemplate
//!
//!  A template management class.  SiPixelTemplate contains thePixelTemp
//!  (a std::vector  of SiPixelTemplateStore, each of which is a collection of many
//!  SiPixelTemplateEntries).  Each SiPixelTemplateStore corresponds to a given detector
//!  condition, and is valid for a range of runs.  We allow more than one Store since the
//!  may change over time.
//!
//!  This class reads templates from files via pushfile() method.
//!
//!  The main functionality of SiPixelTemplate is interpolate(), which produces a template
//!  on the fly, given a specific track's alpha and beta.  The results are kept in data
//!  members and accessed via inline getters.
//!
//!  The resulting template is then used by PixelTempReco2D() (a global function) which
//!  get the reference for SiPixelTemplate & templ and uses the current template to
//!  reconstruct the SiPixelRecHit.
// ******************************************************************************************
class SiPixelTemplate {
public:
  SiPixelTemplate(const std::vector<SiPixelTemplateStore>& thePixelTemp) : thePixelTemp_(thePixelTemp) {
    id_current_ = -1;
    index_id_ = -1;
    cota_current_ = 0.;
    cotb_current_ = 0.;
    entry_sideloaded_ = nullptr;
  }  //!< Constructor for cases in which template store already exists

// Load the private store with info from the file with the index (int) filenum from directory dir:
//   ${dir}template_summary_zp${filenum}.out
#ifdef SI_PIXEL_TEMPLATE_STANDALONE
  static bool pushfile(int filenum, std::vector<SiPixelTemplateStore>& pixelTemp, std::string dir = "");

  // For calibrations only: load precalculated values -- no interpolation.
  void sideload(SiPixelTemplateEntry* entry,
                int iDtype,
                float locBx,
                float locBz,
                float lorwdy,
                float lorwdx,
                float q50,
                float fbin[3],
                float xsize,
                float ysize,
                float zsize);

#else
  static bool pushfile(int filenum,
                       std::vector<SiPixelTemplateStore>& pixelTemp,
                       // *&^%$#@!  Different default dir -- remove once FastSim is updated.
                       std::string dir = "CalibTracker/SiPixelESProducers/data/");

  //load from DB (default in CMSSW)
  static bool pushfile(const SiPixelTemplateDBObject& dbobject,
                       std::vector<SiPixelTemplateStore>& pixelTemp);  // load the private store with info from db
#endif

  // initialize the rest;
  static void postInit(std::vector<SiPixelTemplateStore>& thePixelTemp_);

  // Interpolate input alpha and beta angles to produce a working template for each individual hit.
  bool interpolate(int id, float cotalpha, float cotbeta, float locBz, float locBx);

  // Interpolate input alpha and beta angles to produce a working template for each individual hit.
  bool interpolate(int id, float cotalpha, float cotbeta, float locBz);

  // overload for compatibility.
  bool interpolate(int id, float cotalpha, float cotbeta);

  // retreive interpolated templates.
  void ytemp(int fybin, int lybin, float ytemplate[41][BYSIZE]);

  void xtemp(int fxbin, int lxbin, float xtemplate[41][BXSIZE]);

  //Method to estimate the central pixel of the interpolated y-template
  int cytemp();

  //Method to estimate the central pixel of the interpolated x-template
  int cxtemp();

  //Methods to build templates from two interpolated clusters (for splitting)
  void ytemp3d_int(int nypix, int& nybins);

  void ytemp3d(int j, int k, std::vector<float>& ytemplate);

  void xtemp3d_int(int nxpix, int& nxbins);

  void xtemp3d(int j, int k, std::vector<float>& xtemplate);

  // Convert vector of projected signals into uncertainties for fitting.
  void ysigma2(int fypix, int lypix, float sythr, float ysum[BYSIZE], float ysig2[BYSIZE]);

  void ysigma2(float qpixel, int index, float& ysig2);

  void xsigma2(int fxpix, int lxpix, float sxthr, float xsum[BXSIZE], float xsig2[BXSIZE]);

  // Interpolate qfl correction in y.
  float yflcorr(int binq, float qfly);

  // Interpolate qfl correction in x.
  float xflcorr(int binq, float qflx);

  int qbin(int id,
           float cotalpha,
           float cotbeta,
           float locBz,
           float locBx,
           float qclus,
           float& pixmx,
           float& sigmay,
           float& deltay,
           float& sigmax,
           float& deltax,
           float& sy1,
           float& dy1,
           float& sy2,
           float& dy2,
           float& sx1,
           float& dx1,
           float& sx2,
           float& dx2);

  int qbin(int id,
           float cotalpha,
           float cotbeta,
           float locBz,
           float qclus,
           float& pixmx,
           float& sigmay,
           float& deltay,
           float& sigmax,
           float& deltax,
           float& sy1,
           float& dy1,
           float& sy2,
           float& dy2,
           float& sx1,
           float& dx1,
           float& sx2,
           float& dx2);

  // Overload to use for cluster splitting
  int qbin(int id, float cotalpha, float cotbeta, float qclus);

  // Overload to keep legacy interface
  int qbin(int id, float cotbeta, float qclus);

  // Method to return template errors for fastsim
  void temperrors(int id,
                  float cotalpha,
                  float cotbeta,
                  int qBin,
                  float& sigmay,
                  float& sigmax,
                  float& sy1,
                  float& sy2,
                  float& sx1,
                  float& sx2);

  //Method to return qbin and size probabilities for fastsim
  void qbin_dist(int id,
                 float cotalpha,
                 float cotbeta,
                 float qbin_frac[4],
                 float& ny1_frac,
                 float& ny2_frac,
                 float& nx1_frac,
                 float& nx2_frac);

  //Method to calculate simple 2D templates
  bool simpletemplate2D(
      float xhitp, float yhitp, std::vector<bool>& ydouble, std::vector<bool>& xdouble, float template2d[BXM2][BYM2]);

  //Method to interpolate Vavilov distribution parameters
  void vavilov_pars(double& mpv, double& sigma, double& kappa);

  //Method to interpolate 2-cluster Vavilov distribution parameters
  void vavilov2_pars(double& mpv, double& sigma, double& kappa);

  float qavg() { return qavg_; }      //!< average cluster charge for this set of track angles
  float pixmax() { return pixmax_; }  //!< maximum pixel charge
  float qscale() { return qscale_; }  //!< charge scaling factor
  float s50() { return s50_; }        //!< 1/2 of the pixel threshold signal in electrons
  float ss50() { return ss50_; }      //!< 1/2 of the single pixel per double column threshold in electrons
  float symax() { return symax_; }    //!< average pixel signal for y-projection of cluster
  float dyone() { return dyone_; }    //!< mean offset/correction for one pixel y-clusters
  float syone() { return syone_; }    //!< rms for one pixel y-clusters
  float dytwo() { return dytwo_; }    //!< mean offset/correction for one double-pixel y-clusters
  float sytwo() { return sytwo_; }    //!< rms for one double-pixel y-clusters
  float sxmax() { return sxmax_; }    //!< average pixel signal for x-projection of cluster
  float dxone() { return dxone_; }    //!< mean offset/correction for one pixel x-clusters
  float sxone() { return sxone_; }    //!< rms for one pixel x-clusters
  float dxtwo() { return dxtwo_; }    //!< mean offset/correction for one double-pixel x-clusters
  float sxtwo() { return sxtwo_; }    //!< rms for one double-pixel x-clusters
  float qmin() { return qmin_; }      //!< minimum cluster charge for valid hit (keeps 99.9% of simulated hits)
  float qmin(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 1) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::qmin called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 2);
#endif
    if (i == 0) {
      return qmin_;
    } else {
      return qmin2_;
    }
  }  //!< minimum cluster charge for valid hit (keeps 99.9% or 99.8% of simulated hits)
  float clsleny() { return clsleny_; }  //!< y-size of smaller interpolated template in pixels
  float clslenx() { return clslenx_; }  //!< x-size of smaller interpolated template in pixels
  float yratio() { return yratio_; }    //!< fractional distance in y between cotbeta templates
  float yxratio() { return yxratio_; }  //!< fractional distance in y between cotalpha templates slices
  float xxratio() { return xxratio_; }  //!< fractional distance in x between cotalpha templates
  float yavg(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::yavg called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return yavg_[i];
  }  //!< average y-bias of reconstruction binned in 4 charge bins
  float yrms(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::yrms called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return yrms_[i];
  }  //!< average y-rms of reconstruction binned in 4 charge bins
  float ygx0(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::ygx0 called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return ygx0_[i];
  }  //!< average y0 from Gaussian fit binned in 4 charge bins
  float ygsig(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::ygsig called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return ygsig_[i];
  }  //!< average sigma_y from Gaussian fit binned in 4 charge bins
  float xavg(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::xavg called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return xavg_[i];
  }  //!< average x-bias of reconstruction binned in 4 charge bins
  float xrms(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::xrms called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return xrms_[i];
  }  //!< average x-rms of reconstruction binned in 4 charge bins
  float xgx0(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::xgx0 called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return xgx0_[i];
  }  //!< average x0 from Gaussian fit binned in 4 charge bins
  float xgsig(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::xgsig called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return xgsig_[i];
  }  //!< average sigma_x from Gaussian fit binned in 4 charge bins
  float chi2yavg(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::chi2yavg called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return chi2yavg_[i];
  }  //!< average y chi^2 in 4 charge bins
  float chi2ymin(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::chi2ymin called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return chi2ymin_[i];
  }  //!< minimum y chi^2 in 4 charge bins
  float chi2xavg(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::chi2xavg called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return chi2xavg_[i];
  }  //!< averaage x chi^2 in 4 charge bins
  float chi2xmin(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::chi2xmin called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return chi2xmin_[i];
  }  //!< minimum y chi^2 in 4 charge bins
  float yavgc2m(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::yavgc2m called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return yavgc2m_[i];
  }  //!< 1st pass chi2 min search: average y-bias of reconstruction binned in 4 charge bins
  float yrmsc2m(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::yrmsc2m called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return yrmsc2m_[i];
  }  //!< 1st pass chi2 min search: average y-rms of reconstruction binned in 4 charge bins
  float chi2yavgc2m(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt")
          << "SiPixelTemplate::chi2yavgc2m called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return chi2yavgc2m_[i];
  }  //!< 1st pass chi2 min search: average y-chisq for merged clusters
  float chi2yminc2m(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt")
          << "SiPixelTemplate::chi2yminc2m called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return chi2yminc2m_[i];
  }  //!< 1st pass chi2 min search: minimum y-chisq for merged clusters
  float xavgc2m(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::xavgc2m called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return xavgc2m_[i];
  }  //!< 1st pass chi2 min search: average x-bias of reconstruction binned in 4 charge bins
  float xrmsc2m(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::xrmsc2m called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return xrmsc2m_[i];
  }  //!< 1st pass chi2 min search: average x-rms of reconstruction binned in 4 charge bins
  float chi2xavgc2m(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt")
          << "SiPixelTemplate::chi2xavgc2m called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return chi2xavgc2m_[i];
  }  //!< 1st pass chi2 min search: average x-chisq for merged clusters
  float chi2xminc2m(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 3) {
      throw cms::Exception("DataCorrupt")
          << "SiPixelTemplate::chi2xminc2m called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 4);
#endif
    return chi2xminc2m_[i];
  }  //!< 1st pass chi2 min search: minimum x-chisq for merged clusters
  float fbin(int i) {
#ifndef SI_PIXEL_TEMPLATE_STANDALONE
    if (i < 0 || i > 2) {
      throw cms::Exception("DataCorrupt") << "SiPixelTemplate::fbin called with illegal index = " << i << std::endl;
    }
#else
    assert(i >= 0 && i < 3);
#endif
    return fbin_[i];
  }  //!< Return lower bound of Qbin definition

  float chi2yavgone() { return chi2yavgone_; }  //!< //!< average y chi^2 for 1 pixel clusters
  float chi2yminone() { return chi2yminone_; }  //!< //!< minimum of y chi^2 for 1 pixel clusters
  float chi2xavgone() { return chi2xavgone_; }  //!< //!< average x chi^2 for 1 pixel clusters
  float chi2xminone() { return chi2xminone_; }  //!< //!< minimum of x chi^2 for 1 pixel clusters
  float lorywidth() { return lorywidth_; }      //!< signed lorentz y-width (microns)
  float lorxwidth() { return lorxwidth_; }      //!< signed lorentz x-width (microns)
  //float lorybias() {return lorywidth_;}                            //!< signed lorentz y-width (microns)
  //float lorxbias() {return lorxwidth_;}                            //!< signed lorentz x-width (microns)
  float lorybias() { return lorybias_; }  //!< signed lorentz y-width (microns)
  float lorxbias() { return lorxbias_; }  //!< signed lorentz x-width (microns)
  float mpvvav() { return mpvvav_; }  //!< most probable charge in Vavilov distribution (not actually for larger kappa)
  float sigmavav() { return sigmavav_; }  //!< "sigma" scale fctor for Vavilov distribution
  float kappavav() { return kappavav_; }  //!< kappa parameter for Vavilov distribution
  float mpvvav2() {
    return mpvvav2_;
  }  //!< most probable charge in 2-cluster Vavilov distribution (not actually for larger kappa)
  float sigmavav2() { return sigmavav2_; }          //!< "sigma" scale fctor for 2-cluster Vavilov distribution
  float kappavav2() { return kappavav2_; }          //!< kappa parameter for 2-cluster Vavilov distribution
  float xsize() { return xsize_; }                  //!< pixel x-size (microns)
  float ysize() { return ysize_; }                  //!< pixel y-size (microns)
  float zsize() { return zsize_; }                  //!< pixel z-size or thickness (microns)
  float r_qMeas_qTrue() { return r_qMeas_qTrue_; }  //!< ratio of measured to true cluster charge
  float fracyone() { return fracyone_; }            //!< The simulated fraction of single pixel y-clusters
  float fracxone() { return fracxone_; }            //!< The simulated fraction of single pixel x-clusters
  float fracytwo() { return fracytwo_; }            //!< The simulated fraction of single double-size pixel y-clusters
  float fracxtwo() { return fracxtwo_; }            //!< The simulated fraction of single double-size pixel x-clusters
  //  float yspare(int i) {assert(i>=0 && i<5); return pyspare[i];}    //!< vector of 5 spares interpolated in beta only
  //  float xspare(int i) {assert(i>=0 && i<10); return pxspare[i];}    //!< vector of 10 spares interpolated in alpha and beta

private:
  // Keep current template interpolaion parameters

  int id_current_;      //!< current id
  int index_id_;        //!< current index
  float cota_current_;  //!< current cot alpha
  float cotb_current_;  //!< current cot beta
  float abs_cotb_;      //!< absolute value of cot beta
  int dtype_;           //!< flags BPix (=0) or FPix (=1)
  bool flip_y_;         //!< flip y sign-sensitive quantities
  bool flip_x_;         //!< flip x sign-sensitive quantities
  bool success_;        //!< true if cotalpha, cotbeta are inside of the acceptance (dynamically loaded)

  // Keep results of last interpolation to return through member functions

  float qavg_;        //!< average cluster charge for this set of track angles
  float pixmax_;      //!< maximum pixel charge
  float qscale_;      //!< charge scaling factor
  float s50_;         //!< 1/2 of the pixel single col threshold signal in electrons
  float ss50_;        //!< 1/2 of the pixel double col threshold signal in electrons
  float symax_;       //!< average pixel signal for y-projection of cluster
  float syparmax_;    //!< maximum pixel signal for parameterization of y uncertainties
  float dyone_;       //!< mean offset/correction for one pixel y-clusters
  float syone_;       //!< rms for one pixel y-clusters
  float dytwo_;       //!< mean offset/correction for one double-pixel y-clusters
  float sytwo_;       //!< rms for one double-pixel y-clusters
  float sxmax_;       //!< average pixel signal for x-projection of cluster
  float sxparmax_;    //!< maximum pixel signal for parameterization of x uncertainties
  float dxone_;       //!< mean offset/correction for one pixel x-clusters
  float sxone_;       //!< rms for one pixel x-clusters
  float dxtwo_;       //!< mean offset/correction for one double-pixel x-clusters
  float sxtwo_;       //!< rms for one double-pixel x-clusters
  float qmin_;        //!< minimum cluster charge for valid hit (keeps 99.9% of simulated hits)
  float clsleny_;     //!< y-cluster length of smaller interpolated template in pixels
  float clslenx_;     //!< x-cluster length of smaller interpolated template in pixels
  float scalexavg_;   //!< average x-error scale factor
  float scaleyavg_;   //!< average y-error scale factor
  float delyavg_;     //!< average difference between clsleny_ and cluster length [with threshold effects]
  float delysig_;     //!< rms of difference between clsleny_ and cluster length [with threshold effects]
  float scalex_[4];   //!< x-error scale factor in charge bins
  float scaley_[4];   //!< y-error scale factor in charge bins
  float offsetx_[4];  //!< x-offset in charge bins
  float offsety_[4];  //!< y-offset in charge bins

  float yratio_;            //!< fractional distance in y between cotbeta templates
  float yparl_[2][5];       //!< projected y-pixel uncertainty parameterization for smaller cotbeta
  float yparh_[2][5];       //!< projected y-pixel uncertainty parameterization for larger cotbeta
  float xparly0_[2][5];     //!< projected x-pixel uncertainty parameterization for smaller cotbeta (central alpha)
  float xparhy0_[2][5];     //!< projected x-pixel uncertainty parameterization for larger cotbeta (central alpha)
  float ytemp_[9][BYSIZE];  //!< templates for y-reconstruction (binned over 5 central pixels)
  float yxratio_;           //!< fractional distance in y between x-slices of cotalpha templates
  float xxratio_;           //!< fractional distance in x between cotalpha templates
  float xpar0_[2][5];       //!< projected x-pixel uncertainty parameterization for central cotalpha
  float xparl_[2][5];       //!< projected x-pixel uncertainty parameterization for smaller cotalpha
  float xparh_[2][5];       //!< projected x-pixel uncertainty parameterization for larger cotalpha
  float xtemp_[9][BXSIZE];  //!< templates for x-reconstruction (binned over 5 central pixels)
  float yavg_[4];           //!< average y-bias of reconstruction binned in 4 charge bins
  float yrms_[4];           //!< average y-rms of reconstruction binned in 4 charge bins
  float ygx0_[4];           //!< average y0 from Gaussian fit binned in 4 charge bins
  float ygsig_[4];          //!< average sigma_y from Gaussian fit binned in 4 charge bins
  float yflparl_[4][6];     //!< Aqfl-parameterized y-correction in 4 charge bins for smaller cotbeta
  float yflparh_[4][6];     //!< Aqfl-parameterized y-correction in 4 charge bins for larger cotbeta
  float xavg_[4];           //!< average x-bias of reconstruction binned in 4 charge bins
  float xrms_[4];           //!< average x-rms of reconstruction binned in 4 charge bins
  float xgx0_[4];           //!< average x0 from Gaussian fit binned in 4 charge bins
  float xgsig_[4];          //!< sigma from Gaussian fit binned in 4 charge bins
  float xflparll_[4][6];    //!< Aqfl-parameterized x-correction in 4 charge bins for smaller cotbeta, cotalpha
  float xflparlh_[4][6];    //!< Aqfl-parameterized x-correction in 4 charge bins for smaller cotbeta, larger cotalpha
  float xflparhl_[4][6];    //!< Aqfl-parameterized x-correction in 4 charge bins for larger cotbeta, smaller cotalpha
  float xflparhh_[4][6];    //!< Aqfl-parameterized x-correction in 4 charge bins for larger cotbeta, cotalpha
  float chi2yavg_[4];       //!< average y chi^2 in 4 charge bins
  float chi2ymin_[4];       //!< minimum of y chi^2 in 4 charge bins
  float chi2xavg_[4];       //!< average x chi^2 in 4 charge bins
  float chi2xmin_[4];       //!< minimum of x chi^2 in 4 charge bins
  float yavgc2m_[4];        //!< 1st pass chi2 min search: average y-bias of reconstruction binned in 4 charge bins
  float yrmsc2m_[4];        //!< 1st pass chi2 min search: average y-rms of reconstruction binned in 4 charge bins
  float chi2yavgc2m_[4];    //!< 1st pass chi2 min search: average y-chisq for merged clusters
  float chi2yminc2m_[4];    //!< 1st pass chi2 min search: minimum y-chisq for merged clusters
  float xavgc2m_[4];        //!< 1st pass chi2 min search: average x-bias of reconstruction binned in 4 charge bins
  float xrmsc2m_[4];        //!< 1st pass chi2 min search: average x-rms of reconstruction binned in 4 charge bins
  float chi2xavgc2m_[4];    //!< 1st pass chi2 min search: average x-chisq for merged clusters
  float chi2xminc2m_[4];    //!< 1st pass chi2 min search: minimum x-chisq for merged clusters
  float chi2yavgone_;       //!< average y chi^2 for 1 pixel clusters
  float chi2yminone_;       //!< minimum of y chi^2 for 1 pixel clusters
  float chi2xavgone_;       //!< average x chi^2 for 1 pixel clusters
  float chi2xminone_;       //!< minimum of x chi^2 for 1 pixel clusters
  float qmin2_;             //!< tighter minimum cluster charge for valid hit (keeps 99.8% of simulated hits)
  float mpvvav_;            //!< most probable charge in Vavilov distribution (not actually for larger kappa)
  float sigmavav_;          //!< "sigma" scale fctor for Vavilov distribution
  float kappavav_;          //!< kappa parameter for Vavilov distribution
  float mpvvav2_;           //!< most probable charge in 2-cluster Vavilov distribution (not actually for larger kappa)
  float sigmavav2_;         //!< "sigma" scale fctor for 2-cluster Vavilov distribution
  float kappavav2_;         //!< kappa parameter for 2-cluster Vavilov distribution
  float lorywidth_;         //!< Lorentz y-width (sign corrected for fpix frame)
  float lorxwidth_;         //!< Lorentz x-width
  float lorybias_;          //!< Lorentz y-bias
  float lorxbias_;          //!< Lorentz x-bias
  float xsize_;             //!< Pixel x-size
  float ysize_;             //!< Pixel y-size
  float zsize_;             //!< Pixel z-size (thickness)
  float qavg_avg_;          //!< average of cluster charge less than qavg
  float nybins_;            //!< number of bins in each dimension of the y-splitting template
  float nxbins_;            //!< number of bins in each dimension of the x-splitting template
  float r_qMeas_qTrue_;     //!< ratio of measured to true cluster charges
  float fbin_[3];           //!< The QBin definitions in Q_clus/Q_avg
  float fracyone_;          //!< The simulated fraction of single pixel y-clusters
  float fracxone_;          //!< The simulated fraction of single pixel x-clusters
  float fracytwo_;          //!< The simulated fraction of single double-size pixel y-clusters
  float fracxtwo_;          //!< The simulated fraction of single double-size pixel x-clusters
  boost::multi_array<float, 2> temp2dy_;  //!< 2d-primitive for spltting 3-d template
  boost::multi_array<float, 2> temp2dx_;  //!< 2d-primitive for spltting 3-d template

  // Pointers to presently interpolated point:
  const SiPixelTemplateEntry* enty0_;  // enty[ilow]
  const SiPixelTemplateEntry* enty1_;  // enty[iylow][ilow]

  const SiPixelTemplateEntry* entx00_;  // entx[iylow][ilow]
  const SiPixelTemplateEntry* entx02_;
  const SiPixelTemplateEntry* entx20_;
  const SiPixelTemplateEntry* entx22_;
  const SiPixelTemplateEntry* entx21_;

  // Pointer to the sideloaded Entry: use this one if set.
  const SiPixelTemplateEntry* entry_sideloaded_;

  // The actual template store is a std::vector container
  const std::vector<SiPixelTemplateStore>& thePixelTemp_;
};

#endif