Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:28:11

0001 #include "TkGluedMeasurementDet.h"
0002 #include "TrackingTools/MeasurementDet/interface/MeasurementDetException.h"
0003 #include "RecoTracker/TransientTrackingRecHit/interface/TSiStripMatchedRecHit.h"
0004 #include "Geometry/CommonDetUnit/interface/GluedGeomDet.h"
0005 #include "RecoLocalTracker/SiStripRecHitConverter/interface/SiStripRecHitMatcher.h"
0006 #include "NonPropagatingDetMeasurements.h"
0007 #include "TrackingTools/PatternTools/interface/TrajectoryMeasurement.h"
0008 #include "TrackingTools/TransientTrackingRecHit/interface/TrackingRecHitProjector.h"
0009 #include "RecoTracker/TransientTrackingRecHit/interface/ProjectedRecHit2D.h"
0010 #include "RecHitPropagator.h"
0011 #include "TrackingTools/TransientTrackingRecHit/interface/InvalidTransientRecHit.h"
0012 #include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
0013 
0014 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0015 
0016 #include <functional>
0017 #include <iostream>
0018 #include <memory>
0019 #include <typeinfo>
0020 
0021 namespace {
0022   inline std::pair<LocalPoint, LocalError> projectedPos(const TrackingRecHit& hit,
0023                                                         const GeomDet& det,
0024                                                         const GlobalVector& gdir,
0025                                                         const StripClusterParameterEstimator* cpe) {
0026     const BoundPlane& gluedPlane = det.surface();
0027     const BoundPlane& hitPlane = hit.det()->surface();
0028 
0029     // check if the planes are parallel
0030     //const float epsilon = 1.e-7; // corresponds to about 0.3 miliradian but cannot be reduced
0031     // because of float precision
0032 
0033     //if (fabs(gluedPlane.normalVector().dot( hitPlane.normalVector())) < 1-epsilon) {
0034     //       std::cout << "TkGluedMeasurementDet plane not parallel to DetUnit plane: dot product is "
0035     //     << gluedPlane.normalVector().dot( hitPlane.normalVector()) << endl;
0036     // FIXME: throw the appropriate exception here...
0037     //throw MeasurementDetException("TkGluedMeasurementDet plane not parallel to DetUnit plane");
0038     //}
0039 
0040     double delta = gluedPlane.localZ(hitPlane.position());
0041     LocalVector ldir = gluedPlane.toLocal(gdir);
0042     LocalPoint lhitPos = gluedPlane.toLocal(hit.globalPosition());
0043     LocalPoint projectedHitPos = lhitPos - ldir * delta / ldir.z();
0044 
0045     LocalVector hitXAxis = gluedPlane.toLocal(hitPlane.toGlobal(LocalVector(1, 0, 0)));
0046     LocalError hitErr = hit.localPositionError();
0047     if (gluedPlane.normalVector().dot(hitPlane.normalVector()) < 0) {
0048       // the two planes are inverted, and the correlation element must change sign
0049       hitErr = LocalError(hitErr.xx(), -hitErr.xy(), hitErr.yy());
0050     }
0051     LocalError rotatedError = hitErr.rotate(hitXAxis.x(), hitXAxis.y());
0052 
0053     return std::make_pair(projectedHitPos, rotatedError);
0054   }
0055 }  // namespace
0056 
0057 // #include "TrackingTools/KalmanUpdators/interface/Chi2MeasurementEstimator.h"
0058 #include "TrackingTools/PatternTools/interface/TrajMeasLessEstim.h"
0059 
0060 using namespace std;
0061 
0062 TkGluedMeasurementDet::TkGluedMeasurementDet(const GluedGeomDet* gdet,
0063                                              const SiStripRecHitMatcher* matcher,
0064                                              const StripClusterParameterEstimator* cpe)
0065     : MeasurementDet(gdet),
0066       theMatcher(matcher),
0067       theCPE(cpe),
0068       theMonoDet(nullptr),
0069       theStereoDet(nullptr),
0070       theTopology(nullptr) {}
0071 
0072 void TkGluedMeasurementDet::init(const MeasurementDet* monoDet,
0073                                  const MeasurementDet* stereoDet,
0074                                  const TrackerTopology* tTopo) {
0075   theMonoDet = dynamic_cast<const TkStripMeasurementDet*>(monoDet);
0076   theStereoDet = dynamic_cast<const TkStripMeasurementDet*>(stereoDet);
0077   theTopology = tTopo;
0078 
0079   if ((theMonoDet == nullptr) || (theStereoDet == nullptr)) {
0080     throw MeasurementDetException(
0081         "TkGluedMeasurementDet ERROR: Trying to glue a det which is not a TkStripMeasurementDet");
0082   }
0083 }
0084 
0085 TkGluedMeasurementDet::RecHitContainer TkGluedMeasurementDet::recHits(const TrajectoryStateOnSurface& ts,
0086                                                                       const MeasurementTrackerEvent& data) const {
0087   RecHitContainer result;
0088   HitCollectorForRecHits collector(&fastGeomDet(), theMatcher, theCPE, result);
0089   collectRecHits(ts, data, collector);
0090   return result;
0091 }
0092 
0093 // simple hits
0094 bool TkGluedMeasurementDet::recHits(SimpleHitContainer& result,
0095                                     const TrajectoryStateOnSurface& stateOnThisDet,
0096                                     const MeasurementEstimator& est,
0097                                     const MeasurementTrackerEvent& data) const {
0098   if UNLIKELY ((!theMonoDet->isActive(data)) && (!theStereoDet->isActive(data)))
0099     return false;
0100   auto oldSize = result.size();
0101   HitCollectorForSimpleHits collector(&fastGeomDet(), theMatcher, theCPE, stateOnThisDet, est, result);
0102   collectRecHits(stateOnThisDet, data, collector);
0103 
0104   return result.size() > oldSize;
0105 }
0106 
0107 bool TkGluedMeasurementDet::measurements(const TrajectoryStateOnSurface& stateOnThisDet,
0108                                          const MeasurementEstimator& est,
0109                                          const MeasurementTrackerEvent& data,
0110                                          TempMeasurements& result) const {
0111   if UNLIKELY ((!theMonoDet->isActive(data)) && (!theStereoDet->isActive(data))) {
0112     //     LogDebug("TkStripMeasurementDet") << " DetID " << geomDet().geographicalId().rawId() << " (glued) fully inactive";
0113     result.add(theInactiveHit, 0.F);
0114     return true;
0115   }
0116 
0117   auto oldSize = result.size();
0118 
0119   HitCollectorForFastMeasurements collector(&fastGeomDet(), theMatcher, theCPE, stateOnThisDet, est, result);
0120   collectRecHits(stateOnThisDet, data, collector);
0121 
0122   if (result.size() > oldSize)
0123     return true;
0124 
0125   auto id = geomDet().geographicalId().subdetId() - 3;
0126   auto l = theTopology->tobLayer(geomDet().geographicalId());
0127   bool killHIP = (1 == l) && (2 == id);  //TOB1
0128   killHIP &= stateOnThisDet.globalMomentum().perp2() > est.minPt2ForHitRecoveryInGluedDet();
0129   if (killHIP) {
0130     result.add(theInactiveHit, 0.F);
0131     return true;
0132   }
0133 
0134   //LogDebug("TkStripMeasurementDet") << "No hit found on TkGlued. Testing strips...  ";
0135   const BoundPlane& gluedPlane = geomDet().surface();
0136   if (  // sorry for the big IF, but I want to exploit short-circuiting of logic
0137       stateOnThisDet.hasError() &&
0138       (/* do this only if the state has uncertainties, otherwise it will throw 
0139                      (states without uncertainties are passed to this code from seeding */
0140        (theMonoDet->isActive(data) &&
0141         (theMonoDet->hasAllGoodChannels() || testStrips(stateOnThisDet, gluedPlane, *theMonoDet))) /*Mono OK*/
0142        &&                                                                                          // was ||
0143        (theStereoDet->isActive(data) &&
0144         (theStereoDet->hasAllGoodChannels() || testStrips(stateOnThisDet, gluedPlane, *theStereoDet))) /*Stereo OK*/
0145        ) /* State has errors */
0146   ) {
0147     result.add(theMissingHit, 0.F);
0148     return false;
0149   }
0150   result.add(theInactiveHit, 0.F);
0151   return true;
0152 }
0153 
0154 struct take_address {
0155   template <typename T>
0156   const T* operator()(const T& val) const {
0157     return &val;
0158   }
0159 };
0160 
0161 #ifdef DOUBLE_MATCH
0162 template <typename Collector>
0163 void TkGluedMeasurementDet::collectRecHits(const TrajectoryStateOnSurface& ts,
0164                                            const MeasurementTrackerEvent& data,
0165                                            Collector& collector) const {
0166   doubleMatch(ts, data, collector);
0167 }
0168 #else
0169 template <typename Collector>
0170 void TkGluedMeasurementDet::collectRecHits(const TrajectoryStateOnSurface& ts,
0171                                            const MeasurementTrackerEvent& data,
0172                                            Collector& collector) const {
0173   //------ WARNING: here ts is used as it is on the mono/stereo surface.
0174   //-----           A further propagation is necessary.
0175   //-----           To limit the problem, the SimpleCPE should be used
0176   RecHitContainer monoHits = theMonoDet->recHits(ts, data);
0177   GlobalVector glbDir = (ts.isValid() ? ts.globalParameters().momentum() : position() - GlobalPoint(0, 0, 0));
0178 
0179   //edm::LogWarning("TkGluedMeasurementDet::recHits") << "Query-for-detid-" << theGeomDet->geographicalId().rawId();
0180 
0181   //checkProjection(ts, monoHits, stereoHits);
0182 
0183   if (monoHits.empty()) {
0184     // make stereo TTRHs and project them
0185     projectOnGluedDet(collector, theStereoDet->recHits(ts, data), glbDir);
0186   } else {
0187     // collect simple stereo hits
0188     std::vector<SiStripRecHit2D> simpleSteroHitsByValue;
0189     theStereoDet->simpleRecHits(ts, data, simpleSteroHitsByValue);
0190 
0191     if (simpleSteroHitsByValue.empty()) {
0192       projectOnGluedDet(collector, monoHits, glbDir);
0193     } else {
0194       LocalVector tkDir = (ts.isValid() ? ts.localDirection() : surface().toLocal(position() - GlobalPoint(0, 0, 0)));
0195       SiStripRecHitMatcher::SimpleHitCollection vsStereoHits;
0196       vsStereoHits.resize(simpleSteroHitsByValue.size());
0197       std::transform(
0198           simpleSteroHitsByValue.begin(), simpleSteroHitsByValue.end(), vsStereoHits.begin(), take_address());
0199 
0200       // convert mono hits to type expected by matcher
0201       for (RecHitContainer::const_iterator monoHit = monoHits.begin(); monoHit != monoHits.end(); ++monoHit) {
0202         const TrackingRecHit* tkhit = (**monoHit).hit();
0203         const SiStripRecHit2D* verySpecificMonoHit = reinterpret_cast<const SiStripRecHit2D*>(tkhit);
0204         theMatcher->match(verySpecificMonoHit,
0205                           vsStereoHits.begin(),
0206                           vsStereoHits.end(),
0207                           collector.collector(),
0208                           &specificGeomDet(),
0209                           tkDir);
0210 
0211         if (collector.hasNewMatchedHits()) {
0212           collector.clearNewMatchedHitsFlag();
0213         } else {
0214           collector.addProjected(**monoHit, glbDir);
0215         }
0216       }  // loop on mono hit
0217     }
0218     //GIO// std::cerr << "TkGluedMeasurementDet hits " << monoHits.size() << "/" << stereoHits.size() << " => " << result.size() << std::endl;
0219   }
0220 }
0221 #endif
0222 
0223 #include <cstdint>
0224 #ifdef VI_STAT
0225 #include <cstdio>
0226 #endif
0227 namespace {
0228   struct Stat {
0229 #ifdef VI_STAT
0230     double totCall = 0;
0231     double totMono = 0;
0232     double totStereo = 0;
0233     double totComb = 0;
0234     double totMatched = 0;
0235     double filtMono = 0;
0236     double filtStereo = 0;
0237     double filtComb = 0;
0238     double matchT = 0;
0239     double matchF = 0;
0240     double singleF = 0;
0241     double zeroM = 0;
0242     double zeroS = 0;
0243 
0244     void match(uint64_t t) {
0245       if (t != 0)
0246         ++matchT;
0247       totMatched += t;
0248     }
0249     void operator()(uint64_t m, uint64_t s, uint64_t fm, uint64_t fs) {
0250       ++totCall;
0251       totMono += m;
0252       totStereo += s;
0253       totComb += m * s;
0254       filtMono += fm;
0255       filtStereo += fs;
0256       filtComb += fm * fs;
0257       if (fm == 0)
0258         ++zeroM;
0259       if (fs == 0)
0260         ++zeroS;
0261       if (fm != 0 && fs != 0)
0262         ++matchF;
0263       if (fm != 0 || fs != 0)
0264         ++singleF;
0265     }
0266     ~Stat() {
0267       if (totCall > 0)
0268         printf("Matches:%d/%d/%d/%d/%d/%d : %f/%f/%f/%f/%f/%f/%f\n",
0269                int(totCall),
0270                int(matchF),
0271                int(singleF - matchF),
0272                int(matchT),
0273                int(zeroM),
0274                int(zeroS),
0275                totMono / totCall,
0276                totStereo / totCall,
0277                totComb / totCall,
0278                totMatched / matchT,
0279                filtMono / totCall,
0280                filtStereo / totCall,
0281                filtComb / matchF);
0282     }
0283 #else
0284     Stat() {}
0285     void match(uint64_t) const {}
0286     void operator()(uint64_t, uint64_t, uint64_t, uint64_t) const {}
0287 #endif
0288   };
0289 #ifndef VI_STAT
0290   const
0291 #endif
0292       Stat stat;
0293 }  // namespace
0294 
0295 TkGluedMeasurementDet::RecHitContainer TkGluedMeasurementDet::projectOnGluedDet(
0296     const RecHitContainer& hits, const TrajectoryStateOnSurface& ts) const {
0297   RecHitContainer result;
0298   for (auto const& hit : hits) {
0299     auto&& vl = projectedPos(*hit, fastGeomDet(), ts.globalParameters().momentum(), theCPE);
0300     auto&& phit = std::make_shared<ProjectedSiStripRecHit2D>(
0301         vl.first, vl.second, fastGeomDet(), static_cast<SiStripRecHit2D const&>(*hit));
0302     result.push_back(std::move(phit));
0303   }
0304   return result;
0305 }
0306 
0307 template <typename Collector>
0308 void TkGluedMeasurementDet::projectOnGluedDet(Collector& collector,
0309                                               const RecHitContainer& hits,
0310                                               const GlobalVector& gdir) const {
0311   for (RecHitContainer::const_iterator ihit = hits.begin(); ihit != hits.end(); ihit++) {
0312     collector.addProjected(**ihit, gdir);
0313   }
0314 }
0315 
0316 TkGluedMeasurementDet::RecHitContainer TkGluedMeasurementDet::projectOnGluedDet(
0317     std::vector<SiStripRecHit2D> const& hits, const TrajectoryStateOnSurface& ts) const {
0318   RecHitContainer result;
0319   for (auto const& hit : hits) {
0320     auto&& vl = projectedPos(hit, fastGeomDet(), ts.globalParameters().momentum(), theCPE);
0321     auto&& phit = std::make_shared<ProjectedSiStripRecHit2D>(
0322         vl.first, vl.second, fastGeomDet(), static_cast<SiStripRecHit2D const&>(hit));
0323     result.push_back(std::move(phit));
0324   }
0325   return result;
0326 }
0327 
0328 template <typename Collector>
0329 void TkGluedMeasurementDet::projectOnGluedDet(Collector& collector,
0330                                               std::vector<SiStripRecHit2D> const& hits,
0331                                               const GlobalVector& gdir) const {
0332   for (auto const& hit : hits)
0333     collector.addProjected(hit, gdir);
0334 }
0335 
0336 void TkGluedMeasurementDet::checkProjection(const TrajectoryStateOnSurface& ts,
0337                                             const RecHitContainer& monoHits,
0338                                             const RecHitContainer& stereoHits) const {
0339   for (RecHitContainer::const_iterator i = monoHits.begin(); i != monoHits.end(); ++i) {
0340     checkHitProjection(**i, ts, fastGeomDet());
0341   }
0342   for (RecHitContainer::const_iterator i = stereoHits.begin(); i != stereoHits.end(); ++i) {
0343     checkHitProjection(**i, ts, fastGeomDet());
0344   }
0345 }
0346 
0347 void TkGluedMeasurementDet::checkHitProjection(const TrackingRecHit& hit,
0348                                                const TrajectoryStateOnSurface& ts,
0349                                                const GeomDet& det) const {
0350   auto&& vl = projectedPos(hit, det, ts.globalParameters().momentum(), theCPE);
0351   ProjectedSiStripRecHit2D projectedHit(vl.first, vl.second, det, static_cast<SiStripRecHit2D const&>(hit));
0352 
0353   RecHitPropagator prop;
0354   TrajectoryStateOnSurface propState = prop.propagate(hit, det.surface(), ts);
0355 
0356   if ((projectedHit.localPosition() - propState.localPosition()).mag() > 0.0001f) {
0357     std::cout << "PROBLEM: projected and propagated hit positions differ by "
0358               << (projectedHit.localPosition() - propState.localPosition()).mag() << std::endl;
0359   }
0360 
0361   LocalError le1 = projectedHit.localPositionError();
0362   LocalError le2 = propState.localError().positionError();
0363   double eps = 1.e-5;
0364   double cutoff = 1.e-4;  // if element below cutoff, use absolute instead of relative accuracy
0365   double maxdiff = std::max(
0366       std::max(fabs(le1.xx() - le2.xx()) / (cutoff + le1.xx()), fabs(le1.xy() - le2.xy()) / (cutoff + fabs(le1.xy()))),
0367       fabs(le1.yy() - le2.yy()) / (cutoff + le1.xx()));
0368   if (maxdiff > eps) {
0369     std::cout << "PROBLEM: projected and propagated hit errors differ by " << maxdiff << std::endl;
0370   }
0371 }
0372 
0373 bool TkGluedMeasurementDet::testStrips(const TrajectoryStateOnSurface& tsos,
0374                                        const BoundPlane& gluedPlane,
0375                                        const TkStripMeasurementDet& mdet) const {
0376   // from TrackingRecHitProjector
0377   const GeomDet& det = mdet.fastGeomDet();
0378   const BoundPlane& stripPlane = det.surface();
0379 
0380   //LocalPoint glp = tsos.localPosition();
0381   LocalError err = tsos.localError().positionError();
0382   /*LogDebug("TkStripMeasurementDet") << 
0383     "Testing local pos glued: " << glp << 
0384     " local err glued: " << tsos.localError().positionError() << 
0385       " in? " << gluedPlane.bounds().inside(glp) <<
0386       " in(3s)? " << gluedPlane.bounds().inside(glp, err, 3.0f);*/
0387 
0388   GlobalVector gdir = tsos.globalParameters().momentum();
0389 
0390   LocalPoint slp = stripPlane.toLocal(tsos.globalPosition());
0391   LocalVector sld = stripPlane.toLocal(gdir);
0392 
0393   double delta = stripPlane.localZ(tsos.globalPosition());
0394   LocalPoint pos = slp - sld * delta / sld.z();
0395 
0396   // now the error
0397   LocalVector hitXAxis = stripPlane.toLocal(gluedPlane.toGlobal(LocalVector(1, 0, 0)));
0398   if (stripPlane.normalVector().dot(gluedPlane.normalVector()) < 0) {
0399     // the two planes are inverted, and the correlation element must change sign
0400     err = LocalError(err.xx(), -err.xy(), err.yy());
0401   }
0402   LocalError rotatedError = err.rotate(hitXAxis.x(), hitXAxis.y());
0403 
0404   /* // This is probably meaningless 
0405       LogDebug("TkStripMeasurementDet") << 
0406       "Testing local pos on strip (SLP): " << slp << 
0407       " in? :" << stripPlane.bounds().inside(slp) <<
0408       " in(3s)? :" << stripPlane.bounds().inside(slp, rotatedError, 3.0f);
0409       // but it helps to test bugs in the formula for POS */
0410   /*LogDebug("TkStripMeasurementDet") << 
0411      "Testing local pos strip: " << pos << 
0412      " in? " << stripPlane.bounds().inside(pos) <<
0413      " in(3s)? " << stripPlane.bounds().inside(pos, rotatedError, 3.0f);*/
0414 
0415   // now we need to convert to MeasurementFrame
0416   const StripTopology& topo = mdet.specificGeomDet().specificTopology();
0417   float utraj = topo.measurementPosition(pos).x();
0418   float uerr = std::sqrt(topo.measurementError(pos, rotatedError).uu());
0419   return mdet.testStrips(utraj, uerr);
0420 }
0421 
0422 TkGluedMeasurementDet::HitCollectorForRecHits::HitCollectorForRecHits(const GeomDet* geomDet,
0423                                                                       const SiStripRecHitMatcher* matcher,
0424                                                                       const StripClusterParameterEstimator* cpe,
0425                                                                       RecHitContainer& target)
0426     : geomDet_(geomDet),
0427       matcher_(matcher),
0428       cpe_(cpe),
0429       target_(target),
0430       collector_(std::bind(&HitCollectorForRecHits::add, std::ref(*this), std::placeholders::_1)),
0431       hasNewHits_(false) {}
0432 
0433 TkGluedMeasurementDet::HitCollectorForSimpleHits::HitCollectorForSimpleHits(
0434     const GeomDet* geomDet,
0435     const SiStripRecHitMatcher* matcher,
0436     const StripClusterParameterEstimator* cpe,
0437     const TrajectoryStateOnSurface& stateOnThisDet,
0438     const MeasurementEstimator& est,
0439     SimpleHitContainer& target)
0440     : geomDet_(geomDet),
0441       matcher_(matcher),
0442       cpe_(cpe),
0443       stateOnThisDet_(stateOnThisDet),
0444       est_(est),
0445       target_(target),
0446       collector_(std::bind(&HitCollectorForSimpleHits::add, std::ref(*this), std::placeholders::_1)),
0447       hasNewHits_(false) {}
0448 
0449 void TkGluedMeasurementDet::HitCollectorForRecHits::addProjected(const TrackingRecHit& hit, const GlobalVector& gdir) {
0450   auto&& vl = projectedPos(hit, *geomDet_, gdir, cpe_);
0451   auto&& phit = std::make_shared<ProjectedSiStripRecHit2D>(
0452       vl.first, vl.second, *geomDet_, static_cast<SiStripRecHit2D const&>(hit));
0453   target_.push_back(std::move(phit));
0454 }
0455 
0456 void TkGluedMeasurementDet::HitCollectorForSimpleHits::add(SiStripMatchedRecHit2D const& hit2d) {
0457   hasNewHits_ = true;  //FIXME: see also what happens moving this within testAndPush   // consistent with previous code
0458   if (!est_.preFilter(stateOnThisDet_,
0459                       ClusterFilterPayload(hit2d.geographicalId(), &hit2d.monoCluster(), &hit2d.stereoCluster())))
0460     return;
0461   hasNewHits_ = true;  //FIXME: see also what happens moving this within testAndPush
0462 
0463   std::pair<bool, double> diffEst = est_.estimate(stateOnThisDet_, hit2d);
0464   if (diffEst.first)
0465     target_.emplace_back(new SiStripMatchedRecHit2D(hit2d));  // fix to use move (really needed???)
0466 }
0467 
0468 void TkGluedMeasurementDet::HitCollectorForSimpleHits::addProjected(const TrackingRecHit& hit,
0469                                                                     const GlobalVector& gdir) {
0470   auto const& thit = reinterpret_cast<TrackerSingleRecHit const&>(hit);
0471   if (!est_.preFilter(stateOnThisDet_, ClusterFilterPayload(hit.geographicalId(), &thit.stripCluster())))
0472     return;
0473 
0474   // here we're ok with some extra casual new's and delete's
0475   auto&& vl = projectedPos(hit, *geomDet_, gdir, cpe_);
0476   std::unique_ptr<ProjectedSiStripRecHit2D> phit(
0477       new ProjectedSiStripRecHit2D(vl.first, vl.second, *geomDet_, static_cast<SiStripRecHit2D const&>(hit)));
0478   std::pair<bool, double> diffEst = est_.estimate(stateOnThisDet_, *phit);
0479   if (diffEst.first) {
0480     target_.emplace_back(phit.release());
0481   }
0482 }
0483 
0484 TkGluedMeasurementDet::HitCollectorForFastMeasurements::HitCollectorForFastMeasurements(
0485     const GeomDet* geomDet,
0486     const SiStripRecHitMatcher* matcher,
0487     const StripClusterParameterEstimator* cpe,
0488     const TrajectoryStateOnSurface& stateOnThisDet,
0489     const MeasurementEstimator& est,
0490     TempMeasurements& target)
0491     : geomDet_(geomDet),
0492       matcher_(matcher),
0493       cpe_(cpe),
0494       stateOnThisDet_(stateOnThisDet),
0495       est_(est),
0496       target_(target),
0497       collector_(std::bind(&HitCollectorForFastMeasurements::add, std::ref(*this), std::placeholders::_1)),
0498       hasNewHits_(false) {}
0499 
0500 void TkGluedMeasurementDet::HitCollectorForFastMeasurements::add(SiStripMatchedRecHit2D const& hit2d) {
0501   //FIXME: see also what happens moving this within testAndPush  // consistent with previous code...
0502   hasNewHits_ = true;
0503   if (!est_.preFilter(stateOnThisDet_,
0504                       ClusterFilterPayload(hit2d.geographicalId(), &hit2d.monoCluster(), &hit2d.stereoCluster())))
0505     return;
0506   hasNewHits_ = true;  //FIXME: see also what happens moving this within testAndPush
0507 
0508   std::pair<bool, double> diffEst = est_.estimate(stateOnThisDet_, hit2d);
0509   if (diffEst.first)
0510     target_.add(hit2d.cloneSH(), diffEst.second);
0511 }
0512 
0513 void TkGluedMeasurementDet::HitCollectorForFastMeasurements::addProjected(const TrackingRecHit& hit,
0514                                                                           const GlobalVector& gdir) {
0515   auto const& thit = reinterpret_cast<TrackerSingleRecHit const&>(hit);
0516   if (!est_.preFilter(stateOnThisDet_, ClusterFilterPayload(hit.geographicalId(), &thit.stripCluster())))
0517     return;
0518 
0519   // here we're ok with some extra casual new's and delete's
0520   auto&& vl = projectedPos(hit, *geomDet_, gdir, cpe_);
0521   auto&& phit = std::make_shared<ProjectedSiStripRecHit2D>(
0522       vl.first, vl.second, *geomDet_, static_cast<SiStripRecHit2D const&>(hit));
0523 
0524   std::pair<bool, double> diffEst = est_.estimate(stateOnThisDet_, *phit);
0525   if (diffEst.first) {
0526     target_.add(phit, diffEst.second);
0527   }
0528 }
0529 
0530 #ifdef DOUBLE_MATCH
0531 #include "doubleMatch.icc"
0532 #endif