Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-11-14 04:15:50

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