Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-07-03 00:42:37

0001 #include <alpaka/alpaka.hpp>
0002 
0003 #include "CondFormats/SiPixelTransient/interface/SiPixelGenError.h"
0004 #include "DataFormats/GeometrySurface/interface/SOARotation.h"
0005 #include "DataFormats/SiPixelClusterSoA/interface/ClusteringConstants.h"
0006 #include "DataFormats/TrackingRecHitSoA/interface/SiPixelHitStatus.h"
0007 #include "Geometry/CommonTopologies/interface/SimplePixelTopology.h"
0008 #include "HeterogeneousCore/AlpakaInterface/interface/CopyToDevice.h"
0009 #include "HeterogeneousCore/AlpakaInterface/interface/config.h"
0010 #include "HeterogeneousCore/AlpakaInterface/interface/memory.h"
0011 #include "RecoLocalTracker/SiPixelRecHits/interface/PixelCPEFastParamsHost.h"
0012 
0013 // #define ONLY_TRIPLETS_IN_HOLE
0014 //-----------------------------------------------------------------------------
0015 //!  The constructor.
0016 //-----------------------------------------------------------------------------
0017 template <typename TrackerTraits>
0018 PixelCPEFastParamsHost<TrackerTraits>::PixelCPEFastParamsHost(edm::ParameterSet const& conf,
0019                                                               const MagneticField* mag,
0020                                                               const TrackerGeometry& geom,
0021                                                               const TrackerTopology& ttopo,
0022                                                               const SiPixelLorentzAngle* lorentzAngle,
0023                                                               const SiPixelGenErrorDBObject* genErrorDBObject,
0024                                                               const SiPixelLorentzAngle* lorentzAngleWidth)
0025     : PixelCPEGenericBase(conf, mag, geom, ttopo, lorentzAngle, genErrorDBObject, lorentzAngleWidth),
0026       buffer_(cms::alpakatools::make_host_buffer<pixelCPEforDevice::ParamsOnDeviceT<TrackerTraits>>()) {
0027   // Use errors from templates or from GenError
0028   if (useErrorsFromTemplates_) {
0029     if (!SiPixelGenError::pushfile(*genErrorDBObject_, this->thePixelGenError_))
0030       throw cms::Exception("InvalidCalibrationLoaded")
0031           << "ERROR: GenErrors not filled correctly. Check the sqlite file. Using SiPixelTemplateDBObject version "
0032           << (*genErrorDBObject_).version();
0033   }
0034 
0035   fillParamsForDevice();
0036 }
0037 
0038 template <typename TrackerTraits>
0039 void PixelCPEFastParamsHost<TrackerTraits>::fillParamsForDevice() {
0040   // this code executes only once per job, computation inefficiency is not an issue
0041   // many code blocks are repeated: better keep the computation local and self consistent as blocks may in future move around, be deleted ...
0042   // It is valid only for Phase1 and the version of GenError in DB used in late 2018 and in 2021
0043 
0044   buffer_->commonParams().theThicknessB = m_DetParams.front().theThickness;
0045   buffer_->commonParams().theThicknessE = m_DetParams.back().theThickness;
0046 
0047   LogDebug("PixelCPEFastParamsHost") << "thickness " << buffer_->commonParams().theThicknessB << ' '
0048                                      << buffer_->commonParams().theThicknessE;
0049 
0050 #ifdef ONLY_TRIPLETS_IN_HOLE
0051   // zero average geometry
0052   memset(&buffer_->averageGeometry(), 0, sizeof(pixelTopology::AverageGeometryT<TrackerTraits>));
0053 #endif
0054 
0055   assert(m_DetParams.size() <= TrackerTraits::numberOfModules);
0056 
0057   for (auto i = 0U; i < m_DetParams.size(); ++i) {
0058     auto& p = m_DetParams[i];
0059     auto& g = buffer_->detParams(i);
0060 
0061     g.nRowsRoc = p.theDet->specificTopology().rowsperroc();
0062     g.nColsRoc = p.theDet->specificTopology().colsperroc();
0063     g.nRows = p.theDet->specificTopology().rocsX() * g.nRowsRoc;
0064     g.nCols = p.theDet->specificTopology().rocsY() * g.nColsRoc;
0065 
0066     g.numPixsInModule = g.nRows * g.nCols;
0067 
0068     assert(p.theDet->index() == int(i));
0069 
0070     g.isBarrel = GeomDetEnumerators::isBarrel(p.thePart);
0071     g.isPosZ = p.theDet->surface().position().z() > 0;
0072     g.layer = ttopo_.layer(p.theDet->geographicalId());
0073     g.index = i;  // better be!
0074     g.rawId = p.theDet->geographicalId();
0075     auto thickness = g.isBarrel ? buffer_->commonParams().theThicknessB : buffer_->commonParams().theThicknessE;
0076     assert(thickness == p.theThickness);
0077 
0078     g.shiftX = 0.5f * p.lorentzShiftInCmX;
0079     g.shiftY = 0.5f * p.lorentzShiftInCmY;
0080     g.chargeWidthX = p.lorentzShiftInCmX * p.widthLAFractionX;
0081     g.chargeWidthY = p.lorentzShiftInCmY * p.widthLAFractionY;
0082 
0083     g.x0 = p.theOrigin.x();
0084     g.y0 = p.theOrigin.y();
0085     g.z0 = p.theOrigin.z();
0086 
0087     g.thePitchX = p.thePitchX;
0088     g.thePitchY = p.thePitchY;
0089 
0090     auto vv = p.theDet->surface().position();
0091     auto rr = pixelCPEforDevice::Rotation(p.theDet->surface().rotation());
0092     g.frame = pixelCPEforDevice::Frame(vv.x(), vv.y(), vv.z(), rr);
0093 
0094     // errors .....
0095     ClusterParamGeneric cp;
0096 
0097     cp.with_track_angle = false;
0098 
0099     auto lape = p.theDet->localAlignmentError();
0100     if (lape.invalid())
0101       lape = LocalError();  // zero....
0102 
0103     g.apeXX = lape.xx();
0104     g.apeYY = lape.yy();
0105 
0106     auto toMicron = [&](float x) { return std::min(511, int(x * 1.e4f + 0.5f)); };
0107 
0108     // average angle
0109     auto gvx = p.theOrigin.x() + 40.f * p.thePitchX;
0110     auto gvy = p.theOrigin.y();
0111     auto gvz = 1.f / p.theOrigin.z();
0112     //--- Note that the normalization is not required as only the ratio used
0113 
0114     {
0115       // calculate angles (fed into errorFromTemplates)
0116       cp.cotalpha = gvx * gvz;
0117       cp.cotbeta = gvy * gvz;
0118 
0119       errorFromTemplates(p, cp, 20000.);
0120     }
0121 
0122 #ifdef EDM_ML_DEBUG
0123     auto m = 10000.f;
0124     for (float qclus = 15000; qclus < 35000; qclus += 15000) {
0125       errorFromTemplates(p, cp, qclus);
0126       LogDebug("PixelCPEFastParamsHost") << i << ' ' << qclus << ' ' << cp.pixmx << ' ' << m * cp.sigmax << ' '
0127                                          << m * cp.sx1 << ' ' << m * cp.sx2 << ' ' << m * cp.sigmay << ' ' << m * cp.sy1
0128                                          << ' ' << m * cp.sy2;
0129     }
0130     LogDebug("PixelCPEFastParamsHost") << i << ' ' << m * std::sqrt(lape.xx()) << ' ' << m * std::sqrt(lape.yy());
0131 #endif  // EDM_ML_DEBUG
0132 
0133     g.pixmx = std::max(0, cp.pixmx);
0134     g.sx2 = toMicron(cp.sx2);
0135     g.sy1 = std::max(21, toMicron(cp.sy1));  // for some angles sy1 is very small
0136     g.sy2 = std::max(55, toMicron(cp.sy2));  // sometimes sy2 is smaller than others (due to angle?)
0137 
0138     //sample xerr as function of position
0139     // moduleOffsetX is the definition of TrackerTraits::xOffset,
0140     // needs to be calculated because for Phase2 the modules are not uniform
0141     float moduleOffsetX = -(0.5f * float(g.nRows) + TrackerTraits::bigPixXCorrection);
0142     auto const xoff = moduleOffsetX * g.thePitchX;
0143 
0144     for (int ix = 0; ix < pixelCPEforDevice::kNumErrorBins; ++ix) {
0145       auto x = xoff * (1.f - (0.5f + float(ix)) / 8.f);
0146       auto gvx = p.theOrigin.x() - x;
0147       auto gvy = p.theOrigin.y();
0148       auto gvz = 1.f / p.theOrigin.z();
0149       cp.cotbeta = gvy * gvz;
0150       cp.cotalpha = gvx * gvz;
0151       errorFromTemplates(p, cp, 20000.f);
0152       g.sigmax[ix] = toMicron(cp.sigmax);
0153       g.sigmax1[ix] = toMicron(cp.sx1);
0154       LogDebug("PixelCPEFastParamsHost") << "sigmax vs x " << i << ' ' << x << ' ' << cp.cotalpha << ' '
0155                                          << int(g.sigmax[ix]) << ' ' << int(g.sigmax1[ix]) << ' ' << 10000.f * cp.sigmay
0156                                          << std::endl;
0157     }
0158 #ifdef EDM_ML_DEBUG
0159     // sample yerr as function of position
0160     // moduleOffsetY is the definition of TrackerTraits::yOffset (removed)
0161     float moduleOffsetY = 0.5f * float(g.nCols) + TrackerTraits::bigPixYCorrection;
0162     auto const yoff = -moduleOffsetY * p.thePitchY;
0163 
0164     for (int ix = 0; ix < pixelCPEforDevice::kNumErrorBins; ++ix) {
0165       auto y = yoff * (1.f - (0.5f + float(ix)) / 8.f);
0166       auto gvx = p.theOrigin.x() + 40.f * p.thePitchY;
0167       auto gvy = p.theOrigin.y() - y;
0168       auto gvz = 1.f / p.theOrigin.z();
0169       cp.cotbeta = gvy * gvz;
0170       cp.cotalpha = gvx * gvz;
0171       errorFromTemplates(p, cp, 20000.f);
0172       LogDebug("PixelCPEFastParamsHost") << "sigmay vs y " << i << ' ' << y << ' ' << cp.cotbeta << ' '
0173                                          << 10000.f * cp.sigmay << std::endl;
0174     }
0175 #endif  // EDM_ML_DEBUG
0176 
0177     // calculate angles (repeated)
0178     cp.cotalpha = gvx * gvz;
0179     cp.cotbeta = gvy * gvz;
0180     auto aveCB = cp.cotbeta;
0181 
0182     // sample x by charge
0183     int qbin = pixelCPEforDevice::kGenErrorQBins;  // low charge
0184     int k = 0;
0185     int qClusIncrement = 100;
0186     for (int qclus = 100; k < pixelCPEforDevice::kGenErrorQBins; qclus += qClusIncrement) {
0187       errorFromTemplates(p, cp, qclus);
0188       if (cp.qBin_ == qbin) {
0189         continue;
0190       }
0191 
0192       // Check if we have skipped a qBin
0193       if (cp.qBin_ < qbin - 1) {
0194         //qBin=4 (second lowest charge) sometimes may get skipped
0195         //In that case, set its threshold at halfway to threshold of qBin=3 and fill with sigmax/y values of qBin=5
0196         //In reality, it does not really matter because we will not encounter this qBin for any cluster (otherwise we would not have skipped it)
0197         qbin += 1;
0198         qclus -= qClusIncrement;
0199         errorFromTemplates(p, cp, qclus);
0200         g.xfact[k] = cp.sigmax;
0201         g.yfact[k] = cp.sigmay;
0202         g.minCh[k++] = qclus / 2;
0203         continue;
0204       }
0205 
0206       qbin = cp.qBin_;
0207 
0208       //The difference in charge between first two qBins is small, so for other steps we can have a larger increment
0209       if (qbin < pixelCPEforDevice::kGenErrorQBins) {
0210         qClusIncrement = 1000;
0211       }
0212 
0213       g.xfact[k] = cp.sigmax;
0214       g.yfact[k] = cp.sigmay;
0215       g.minCh[k++] = qclus;
0216 #ifdef EDM_ML_DEBUG
0217       LogDebug("PixelCPEFastParamsHost") << i << ' ' << g.rawId << ' ' << cp.cotalpha << ' ' << qclus << ' ' << cp.qBin_
0218                                          << ' ' << cp.pixmx << ' ' << m * cp.sigmax << ' ' << m * cp.sx1 << ' '
0219                                          << m * cp.sx2 << ' ' << m * cp.sigmay << ' ' << m * cp.sy1 << ' ' << m * cp.sy2
0220                                          << std::endl;
0221 #endif  // EDM_ML_DEBUG
0222     }  //for (int qclus = 100; k < pixelCPEforDevice::kGenErrorQBins; qclus += qClusIncrement) {
0223 
0224     assert(k <= pixelCPEforDevice::kGenErrorQBins);
0225 
0226     // fill the rest  (sometimes bin 4 is missing)
0227     for (int kk = k; kk < pixelCPEforDevice::kGenErrorQBins; ++kk) {
0228       g.xfact[kk] = g.xfact[k - 1];
0229       g.yfact[kk] = g.yfact[k - 1];
0230       g.minCh[kk] = g.minCh[k - 1];
0231     }
0232     auto detx = 1.f / g.xfact[0];
0233     auto dety = 1.f / g.yfact[0];
0234     for (int kk = 0; kk < pixelCPEforDevice::kGenErrorQBins; ++kk) {
0235       g.xfact[kk] *= detx;
0236       g.yfact[kk] *= dety;
0237     }
0238     // sample y in "angle"  (estimated from cluster size)
0239     float ys = 8.f - 4.f;  // apperent bias of half pixel (see plot)
0240     // plot: https://indico.cern.ch/event/934821/contributions/3974619/attachments/2091853/3515041/DigilessReco.pdf page 25
0241     // sample yerr as function of "size"
0242     for (int iy = 0; iy < pixelCPEforDevice::kNumErrorBins; ++iy) {
0243       ys += 1.f;  // first bin 0 is for size 9  (and size is in fixed point 2^3)
0244       if (pixelCPEforDevice::kNumErrorBins - 1 == iy)
0245         ys += 8.f;  // last bin for "overflow"
0246       // cp.cotalpha = ys*(g.thePitchX/(8.f*thickness));  //  use this to print sampling in "x"  (and comment the line below)
0247       cp.cotbeta = std::copysign(ys * (g.thePitchY / (8.f * thickness)), aveCB);
0248       errorFromTemplates(p, cp, 20000.f);
0249       g.sigmay[iy] = toMicron(cp.sigmay);
0250       LogDebug("PixelCPEFastParamsHost") << "sigmax/sigmay " << i << ' ' << (ys + 4.f) / 8.f << ' ' << cp.cotalpha
0251                                          << '/' << cp.cotbeta << ' ' << 10000.f * cp.sigmax << '/' << int(g.sigmay[iy])
0252                                          << std::endl;
0253     }
0254   }  // loop over det
0255 
0256 #ifdef ONLY_TRIPLETS_IN_HOLE
0257   // compute ladder baricenter (only in global z) for the barrel
0258 
0259   constexpr int numberOfModulesInLadder = TrackerTraits::numberOfModulesInLadder;
0260   constexpr int numberOfLaddersInBarrel = TrackerTraits::numberOfLaddersInBarrel;
0261   constexpr int numberOfModulesInBarrel = TrackerTraits::numberOfModulesInBarrel;
0262 
0263   constexpr float ladderFactor = 1.f / float(numberOfModulesInLadder);
0264 
0265   constexpr int firstEndcapPos = TrackerTraits::firstEndcapPos;
0266   constexpr int firstEndcapNeg = TrackerTraits::firstEndcapNeg;
0267 
0268   auto& aveGeom = buffer_->averageGeometry();
0269   int il = 0;
0270   for (int im = 0, nm = numberOfModulesInBarrel; im < nm; ++im) {
0271     auto const& g = buffer_->detParams(im);
0272     il = im / numberOfModulesInLadder;
0273     assert(il < int(numberOfLaddersInBarrel));
0274     auto z = g.frame.z();
0275     aveGeom.ladderZ[il] += ladderFactor * z;
0276     aveGeom.ladderMinZ[il] = std::min(aveGeom.ladderMinZ[il], z);
0277     aveGeom.ladderMaxZ[il] = std::max(aveGeom.ladderMaxZ[il], z);
0278     aveGeom.ladderX[il] += ladderFactor * g.frame.x();
0279     aveGeom.ladderY[il] += ladderFactor * g.frame.y();
0280     aveGeom.ladderR[il] += ladderFactor * sqrt(g.frame.x() * g.frame.x() + g.frame.y() * g.frame.y());
0281   }
0282   assert(il + 1 == int(numberOfLaddersInBarrel));
0283   // add half_module and tollerance
0284   constexpr float moduleLength = TrackerTraits::moduleLength;
0285   constexpr float module_tolerance = 0.2f;
0286   for (int il = 0, nl = numberOfLaddersInBarrel; il < nl; ++il) {
0287     aveGeom.ladderMinZ[il] -= (0.5f * moduleLength - module_tolerance);
0288     aveGeom.ladderMaxZ[il] += (0.5f * moduleLength - module_tolerance);
0289   }
0290 
0291   // compute "max z" for first layer in endcap (should we restrict to the outermost ring?)
0292   for (auto im = TrackerTraits::layerStart[firstEndcapPos]; im < TrackerTraits::layerStart[firstEndcapPos + 1]; ++im) {
0293     auto const& g = buffer_->detParams(im);
0294     aveGeom.endCapZ[0] = std::max(aveGeom.endCapZ[0], g.frame.z());
0295   }
0296   for (auto im = TrackerTraits::layerStart[firstEndcapNeg]; im < TrackerTraits::layerStart[firstEndcapNeg + 1]; ++im) {
0297     auto const& g = buffer_->detParams(im);
0298     aveGeom.endCapZ[1] = std::min(aveGeom.endCapZ[1], g.frame.z());
0299   }
0300   // correct for outer ring being closer
0301   aveGeom.endCapZ[0] -= TrackerTraits::endcapCorrection;
0302   aveGeom.endCapZ[1] += TrackerTraits::endcapCorrection;
0303 
0304 #ifdef EDM_ML_DEBUG
0305   for (int jl = 0, nl = numberOfLaddersInBarrel; jl < nl; ++jl) {
0306     LogDebug("PixelCPEFastParamsHost") << jl << ':' << aveGeom.ladderR[jl] << '/'
0307                                        << std::sqrt(aveGeom.ladderX[jl] * aveGeom.ladderX[jl] +
0308                                                     aveGeom.ladderY[jl] * aveGeom.ladderY[jl])
0309                                        << ',' << aveGeom.ladderZ[jl] << ',' << aveGeom.ladderMinZ[jl] << ','
0310                                        << aveGeom.ladderMaxZ[jl] << '\n';
0311   }
0312   LogDebug("PixelCPEFastParamsHost") << aveGeom.endCapZ[0] << ' ' << aveGeom.endCapZ[1];
0313 #endif  // EDM_ML_DEBUG
0314 #endif  //ONLY_TRIPLETS_IN_HOLE
0315 }
0316 
0317 template <typename TrackerTraits>
0318 void PixelCPEFastParamsHost<TrackerTraits>::errorFromTemplates(DetParam const& theDetParam,
0319                                                                ClusterParamGeneric& theClusterParam,
0320                                                                float qclus) const {
0321   float locBz = theDetParam.bz;
0322   float locBx = theDetParam.bx;
0323   LogDebug("PixelCPEFastParamsHost") << "PixelCPEFastParamsHost::localPosition(...) : locBz = " << locBz;
0324 
0325   theClusterParam.pixmx = std::numeric_limits<int>::max();  // max pixel charge for truncation of 2-D cluster
0326 
0327   theClusterParam.sigmay = -999.9;  // CPE Generic y-error for multi-pixel cluster
0328   theClusterParam.sigmax = -999.9;  // CPE Generic x-error for multi-pixel cluster
0329   theClusterParam.sy1 = -999.9;     // CPE Generic y-error for single single-pixel
0330   theClusterParam.sy2 = -999.9;     // CPE Generic y-error for single double-pixel cluster
0331   theClusterParam.sx1 = -999.9;     // CPE Generic x-error for single single-pixel cluster
0332   theClusterParam.sx2 = -999.9;     // CPE Generic x-error for single double-pixel cluster
0333 
0334   float dummy;
0335 
0336   SiPixelGenError gtempl(this->thePixelGenError_);
0337   int gtemplID = theDetParam.detTemplateId;
0338 
0339   theClusterParam.qBin_ = gtempl.qbin(gtemplID,
0340                                       theClusterParam.cotalpha,
0341                                       theClusterParam.cotbeta,
0342                                       locBz,
0343                                       locBx,
0344                                       qclus,
0345                                       false,
0346                                       theClusterParam.pixmx,
0347                                       theClusterParam.sigmay,
0348                                       dummy,
0349                                       theClusterParam.sigmax,
0350                                       dummy,
0351                                       theClusterParam.sy1,
0352                                       dummy,
0353                                       theClusterParam.sy2,
0354                                       dummy,
0355                                       theClusterParam.sx1,
0356                                       dummy,
0357                                       theClusterParam.sx2,
0358                                       dummy);
0359 
0360   theClusterParam.sigmax = theClusterParam.sigmax * pixelCPEforDevice::micronsToCm;
0361   theClusterParam.sx1 = theClusterParam.sx1 * pixelCPEforDevice::micronsToCm;
0362   theClusterParam.sx2 = theClusterParam.sx2 * pixelCPEforDevice::micronsToCm;
0363 
0364   theClusterParam.sigmay = theClusterParam.sigmay * pixelCPEforDevice::micronsToCm;
0365   theClusterParam.sy1 = theClusterParam.sy1 * pixelCPEforDevice::micronsToCm;
0366   theClusterParam.sy2 = theClusterParam.sy2 * pixelCPEforDevice::micronsToCm;
0367 }
0368 
0369 //-----------------------------------------------------------------------------
0370 //! Hit position in the local frame (in cm).  Unlike other CPE's, this
0371 //! one converts everything from the measurement frame (in channel numbers)
0372 //! into the local frame (in centimeters).
0373 //-----------------------------------------------------------------------------
0374 template <typename TrackerTraits>
0375 LocalPoint PixelCPEFastParamsHost<TrackerTraits>::localPosition(DetParam const& theDetParam,
0376                                                                 ClusterParam& theClusterParamBase) const {
0377   ClusterParamGeneric& theClusterParam = static_cast<ClusterParamGeneric&>(theClusterParamBase);
0378 
0379   if (useErrorsFromTemplates_) {
0380     errorFromTemplates(theDetParam, theClusterParam, theClusterParam.theCluster->charge());
0381   } else {
0382     theClusterParam.qBin_ = 0;
0383   }
0384 
0385   int q_f_X;  //!< Q of the first  pixel  in X
0386   int q_l_X;  //!< Q of the last   pixel  in X
0387   int q_f_Y;  //!< Q of the first  pixel  in Y
0388   int q_l_Y;  //!< Q of the last   pixel  in Y
0389   collect_edge_charges(theClusterParam, q_f_X, q_l_X, q_f_Y, q_l_Y, useErrorsFromTemplates_ && truncatePixelCharge_);
0390 
0391   // do GPU like ...
0392   pixelCPEforDevice::ClusParams cp;
0393 
0394   cp.minRow[0] = theClusterParam.theCluster->minPixelRow();
0395   cp.maxRow[0] = theClusterParam.theCluster->maxPixelRow();
0396   cp.minCol[0] = theClusterParam.theCluster->minPixelCol();
0397   cp.maxCol[0] = theClusterParam.theCluster->maxPixelCol();
0398 
0399   cp.q_f_X[0] = q_f_X;
0400   cp.q_l_X[0] = q_l_X;
0401   cp.q_f_Y[0] = q_f_Y;
0402   cp.q_l_Y[0] = q_l_Y;
0403 
0404   cp.charge[0] = theClusterParam.theCluster->charge();
0405 
0406   auto ind = theDetParam.theDet->index();
0407   pixelCPEforDevice::position<TrackerTraits>(buffer_->commonParams(), buffer_->detParams(ind), cp, 0);
0408   auto xPos = cp.xpos[0];
0409   auto yPos = cp.ypos[0];
0410 
0411   // set the error  (mind ape....)
0412   pixelCPEforDevice::errorFromDB<TrackerTraits>(buffer_->commonParams(), buffer_->detParams(ind), cp, 0);
0413   theClusterParam.sigmax = cp.xerr[0];
0414   theClusterParam.sigmay = cp.yerr[0];
0415 
0416   LogDebug("PixelCPEFastParamsHost") << " in PixelCPEFastParamsHost:localPosition - pos = " << xPos << " " << yPos
0417                                      << " size " << cp.maxRow[0] - cp.minRow[0] << ' ' << cp.maxCol[0] - cp.minCol[0];
0418 
0419   //--- Now put the two together
0420   LocalPoint pos_in_local(xPos, yPos);
0421   return pos_in_local;
0422 }
0423 
0424 //==============  INFLATED ERROR AND ERRORS FROM DB BELOW  ================
0425 
0426 //-------------------------------------------------------------------------
0427 //  Hit error in the local frame
0428 //-------------------------------------------------------------------------
0429 template <typename TrackerTraits>
0430 LocalError PixelCPEFastParamsHost<TrackerTraits>::localError(DetParam const& theDetParam,
0431                                                              ClusterParam& theClusterParamBase) const {
0432   ClusterParamGeneric& theClusterParam = static_cast<ClusterParamGeneric&>(theClusterParamBase);
0433 
0434   auto xerr = theClusterParam.sigmax;
0435   auto yerr = theClusterParam.sigmay;
0436 
0437   LogDebug("PixelCPEFastParamsHost") << " errors  " << xerr << " " << yerr;
0438 
0439   auto xerr_sq = xerr * xerr;
0440   auto yerr_sq = yerr * yerr;
0441 
0442   return LocalError(xerr_sq, 0, yerr_sq);
0443 }
0444 
0445 template <typename TrackerTraits>
0446 void PixelCPEFastParamsHost<TrackerTraits>::fillPSetDescription(edm::ParameterSetDescription& desc) {
0447   // call PixelCPEGenericBase fillPSetDescription to add common rechit errors
0448   PixelCPEGenericBase::fillPSetDescription(desc);
0449 }
0450 
0451 template class PixelCPEFastParamsHost<pixelTopology::Phase1>;
0452 template class PixelCPEFastParamsHost<pixelTopology::Phase2>;
0453 template class PixelCPEFastParamsHost<pixelTopology::HIonPhase1>;