File indexing completed on 2024-04-06 12:28:30
0001 #include "RecoTracker/PixelLowPtUtilities/interface/StripSubClusterShapeTrajectoryFilter.h"
0002
0003 #include <map>
0004 #include <set>
0005 #include <algorithm>
0006
0007 #include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
0008 #include "DataFormats/TrackerRecHit2D/interface/ProjectedSiStripRecHit2D.h"
0009 #include "DataFormats/TrackerRecHit2D/interface/SiPixelRecHit.h"
0010 #include "DataFormats/TrackerRecHit2D/interface/SiStripMatchedRecHit2D.h"
0011 #include "DataFormats/TrackerRecHit2D/interface/SiStripRecHit2D.h"
0012 #include "DataFormats/TrackingRecHit/interface/TrackingRecHit.h"
0013 #include "DataFormats/SiStripCommon/interface/ConstantsForHardwareSystems.h"
0014 #include "FWCore/Framework/interface/ESHandle.h"
0015 #include "FWCore/Framework/interface/EventSetup.h"
0016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0017 #include "FWCore/ServiceRegistry/interface/Service.h"
0018 #include "Geometry/CommonDetUnit/interface/GeomDetType.h"
0019 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
0020 #include "Geometry/TrackerGeometryBuilder/interface/StripGeomDetUnit.h"
0021 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
0022 #include "Geometry/Records/interface/TrackerTopologyRcd.h"
0023 #include "MagneticField/Engine/interface/MagneticField.h"
0024 #include "RecoTracker/PixelLowPtUtilities/interface/ClusterShapeHitFilter.h"
0025 #include "RecoTracker/Record/interface/CkfComponentsRecord.h"
0026 #include "RecoTracker/MeasurementDet/interface/MeasurementTrackerEvent.h"
0027 #include "TrackingTools/PatternTools/interface/TempTrajectory.h"
0028 #include "TrackingTools/PatternTools/interface/Trajectory.h"
0029 #include "FWCore/Framework/interface/ConsumesCollector.h"
0030 #include "RecoTracker/TkSeedGenerator/interface/FastHelix.h"
0031 #include "RecoTracker/TkSeedingLayers/interface/SeedingHitSet.h"
0032 #include "DataFormats/SiStripDetId/interface/SiStripDetId.h"
0033
0034 #ifdef StripSubClusterShapeFilterBase_COUNTERS
0035 #define INC_COUNTER(X) X++;
0036 #else
0037 #define INC_COUNTER(X)
0038 #endif
0039 namespace {
0040 class SlidingPeakFinder {
0041 public:
0042 SlidingPeakFinder(unsigned int size) : size_(size), half_((size + 1) / 2) {}
0043
0044 template <typename Test>
0045 bool apply(const uint8_t *x,
0046 const uint8_t *begin,
0047 const uint8_t *end,
0048 const Test &test,
0049 bool verbose = false,
0050 int firststrip = 0) {
0051 const uint8_t *ileft = (x != begin) ? std::min_element(x - 1, x + half_) : begin - 1;
0052 const uint8_t *iright = ((x + size_) < end) ? std::min_element(x + half_, std::min(x + size_ + 1, end)) : end;
0053 uint8_t left = (ileft < begin ? 0 : *ileft);
0054 uint8_t right = (iright >= end ? 0 : *iright);
0055 uint8_t center = *std::max_element(x, std::min(x + size_, end));
0056 uint8_t maxmin = std::max(left, right);
0057 if (maxmin < center) {
0058 bool ret = test(center, maxmin);
0059 if (ret) {
0060 ret = test(ileft, iright, begin, end);
0061 }
0062 return ret;
0063 } else {
0064 return false;
0065 }
0066 }
0067
0068 template <typename V, typename Test>
0069 bool apply(const V &ls, const Test &test, bool verbose = false, int firststrip = 0) {
0070 const uint8_t *begin = &*ampls.begin();
0071 const uint8_t *end = &*ampls.end();
0072 for (const uint8_t *x = begin; x < end - (half_ - 1); ++x) {
0073 if (apply(x, begin, end, test, verbose, firststrip)) {
0074 return true;
0075 }
0076 }
0077 return false;
0078 }
0079
0080 private:
0081 unsigned int size_, half_;
0082 };
0083
0084 struct PeakFinderTest {
0085 PeakFinderTest(float mip,
0086 uint32_t detid,
0087 uint32_t firstStrip,
0088 const SiStripNoises *theNoise,
0089 float seedCutMIPs,
0090 float seedCutSN,
0091 float subclusterCutMIPs,
0092 float subclusterCutSN)
0093 : mip_(mip),
0094 detid_(detid),
0095 firstStrip_(firstStrip),
0096 noiseObj_(theNoise),
0097 noises_(theNoise->getRange(detid)),
0098 subclusterCutMIPs_(subclusterCutMIPs),
0099 sumCut_(subclusterCutMIPs_ * mip_),
0100 subclusterCutSN2_(subclusterCutSN * subclusterCutSN) {
0101 cut_ = std::min<float>(seedCutMIPs * mip, seedCutSN * noiseObj_->getNoise(firstStrip + 1, noises_));
0102 }
0103
0104 bool operator()(uint8_t max, uint8_t min) const { return max - min > cut_; }
0105 bool operator()(const uint8_t *left, const uint8_t *right, const uint8_t *begin, const uint8_t *end) const {
0106 int yleft = (left < begin ? 0 : *left);
0107 int yright = (right >= end ? 0 : *right);
0108 float sum = 0.0;
0109 int maxval = 0;
0110 float noise = 0;
0111 for (const uint8_t *x = left + 1; x < right; ++x) {
0112 int baseline = (yleft * int(right - x) + yright * int(x - left)) / int(right - left);
0113 sum += int(*x) - baseline;
0114 noise += std::pow(noiseObj_->getNoise(firstStrip_ + int(x - begin), noises_), 2);
0115 maxval = std::max(maxval, int(*x) - baseline);
0116 }
0117 if (sum > sumCut_ && sum * sum > noise * subclusterCutSN2_)
0118 return true;
0119 return false;
0120 }
0121
0122 private:
0123 float mip_;
0124 unsigned int detid_;
0125 int firstStrip_;
0126 const SiStripNoises *noiseObj_;
0127 SiStripNoises::Range noises_;
0128 uint8_t cut_;
0129 float subclusterCutMIPs_, sumCut_, subclusterCutSN2_;
0130 };
0131
0132 }
0133
0134 StripSubClusterShapeFilterBase::StripSubClusterShapeFilterBase(const edm::ParameterSet &iCfg,
0135 edm::ConsumesCollector &iC)
0136 : topoToken_(iC.esConsumes<TrackerTopology, TrackerTopologyRcd>()),
0137 csfToken_(
0138 iC.esConsumes<ClusterShapeHitFilter, CkfComponentsRecord>(edm::ESInputTag("", "ClusterShapeHitFilter"))),
0139 geomToken_(iC.esConsumes<TrackerGeometry, TrackerDigiGeometryRecord>()),
0140 stripNoiseToken_(iC.esConsumes<SiStripNoises, SiStripNoisesRcd>()),
0141 label_(iCfg.getUntrackedParameter<std::string>("label", "")),
0142 maxNSat_(iCfg.getParameter<uint32_t>("maxNSat")),
0143 trimMaxADC_(iCfg.getParameter<double>("trimMaxADC")),
0144 trimMaxFracTotal_(iCfg.getParameter<double>("trimMaxFracTotal")),
0145 trimMaxFracNeigh_(iCfg.getParameter<double>("trimMaxFracNeigh")),
0146 maxTrimmedSizeDiffPos_(iCfg.getParameter<double>("maxTrimmedSizeDiffPos")),
0147 maxTrimmedSizeDiffNeg_(iCfg.getParameter<double>("maxTrimmedSizeDiffNeg")),
0148 subclusterWindow_(iCfg.getParameter<double>("subclusterWindow")),
0149 seedCutMIPs_(iCfg.getParameter<double>("seedCutMIPs")),
0150 seedCutSN_(iCfg.getParameter<double>("seedCutSN")),
0151 subclusterCutMIPs_(iCfg.getParameter<double>("subclusterCutMIPs")),
0152 subclusterCutSN_(iCfg.getParameter<double>("subclusterCutSN"))
0153 #ifdef StripSubClusterShapeFilterBase_COUNTERS
0154 ,
0155 called_(0),
0156 saturated_(0),
0157 test_(0),
0158 passTrim_(0),
0159 failTooLarge_(0),
0160 passSC_(0),
0161 failTooNarrow_(0)
0162 #endif
0163 {
0164 const edm::ParameterSet &iLM = iCfg.getParameter<edm::ParameterSet>("layerMask");
0165 if (not iLM.empty()) {
0166 const char *ndets[4] = {"TIB", "TID", "TOB", "TEC"};
0167 const int idets[4] = {3, 4, 5, 6};
0168 for (unsigned int i = 0; i < 4; ++i) {
0169 if (iLM.existsAs<bool>(ndets[i])) {
0170 std::fill(layerMask_[idets[i]].begin(), layerMask_[idets[i]].end(), iLM.getParameter<bool>(ndets[i]));
0171 } else {
0172 layerMask_[idets[i]][0] = 2;
0173 std::fill(layerMask_[idets[i]].begin() + 1, layerMask_[idets[i]].end(), 0);
0174 for (uint32_t lay : iLM.getParameter<std::vector<uint32_t>>(ndets[i])) {
0175 layerMask_[idets[i]][lay] = 1;
0176 }
0177 }
0178 }
0179 } else {
0180 for (auto &arr : layerMask_) {
0181 std::fill(arr.begin(), arr.end(), 1);
0182 }
0183 }
0184 }
0185
0186 StripSubClusterShapeFilterBase::~StripSubClusterShapeFilterBase() {
0187 #if 0
0188 std::cout << "StripSubClusterShapeFilterBase " << label_ << ": called " << called_ << std::endl;
0189 std::cout << "StripSubClusterShapeFilterBase " << label_ << ": saturated " << saturated_ << std::endl;
0190 std::cout << "StripSubClusterShapeFilterBase " << label_ << ": test " << test_ << std::endl;
0191 std::cout << "StripSubClusterShapeFilterBase " << label_ << ": failTooNarrow " << failTooNarrow_ << std::endl;
0192 std::cout << "StripSubClusterShapeFilterBase " << label_ << ": passTrim " << passTrim_ << std::endl;
0193 std::cout << "StripSubClusterShapeFilterBase " << label_ << ": passSC " << passSC_ << std::endl;
0194 std::cout << "StripSubClusterShapeFilterBase " << label_ << ": failTooLarge " << failTooLarge_ << std::endl;
0195 #endif
0196 }
0197
0198 void StripSubClusterShapeFilterBase::fillPSetDescription(edm::ParameterSetDescription &iDesc) {
0199 iDesc.addUntracked<std::string>("label", "");
0200 iDesc.add<uint32_t>("maxNSat", 3);
0201 iDesc.add<double>("trimMaxADC", 30.);
0202 iDesc.add<double>("trimMaxFracTotal", .15);
0203 iDesc.add<double>("trimMaxFracNeigh", .25);
0204 iDesc.add<double>("maxTrimmedSizeDiffPos", .7);
0205 iDesc.add<double>("maxTrimmedSizeDiffNeg", 1.);
0206 iDesc.add<double>("subclusterWindow", .7);
0207 iDesc.add<double>("seedCutMIPs", .35);
0208 iDesc.add<double>("seedCutSN", 7.);
0209 iDesc.add<double>("subclusterCutMIPs", .45);
0210 iDesc.add<double>("subclusterCutSN", 12.);
0211
0212 edm::ParameterSetDescription psdLM;
0213 psdLM.setAllowAnything();
0214 iDesc.add<edm::ParameterSetDescription>("layerMask", psdLM);
0215 }
0216
0217 bool StripSubClusterShapeFilterBase::testLastHit(const TrackingRecHit *hit,
0218 const TrajectoryStateOnSurface &tsos,
0219 bool mustProject) const {
0220 return testLastHit(hit, tsos.globalPosition(), tsos.globalDirection(), mustProject);
0221 }
0222 bool StripSubClusterShapeFilterBase::testLastHit(const TrackingRecHit *hit,
0223 const GlobalPoint &gpos,
0224 const GlobalVector &gdir,
0225 bool mustProject) const {
0226 const TrackerSingleRecHit *stripHit = nullptr;
0227 if (typeid(*hit) == typeid(SiStripMatchedRecHit2D)) {
0228 const SiStripMatchedRecHit2D &mhit = static_cast<const SiStripMatchedRecHit2D &>(*hit);
0229 SiStripRecHit2D mono = mhit.monoHit();
0230 SiStripRecHit2D stereo = mhit.stereoHit();
0231 return testLastHit(&mono, gpos, gdir, true) && testLastHit(&stereo, gpos, gdir, true);
0232 } else if (typeid(*hit) == typeid(ProjectedSiStripRecHit2D)) {
0233 const ProjectedSiStripRecHit2D &mhit = static_cast<const ProjectedSiStripRecHit2D &>(*hit);
0234 const SiStripRecHit2D &orig = mhit.originalHit();
0235 return testLastHit(&orig, gpos, gdir, true);
0236 } else if ((stripHit = dynamic_cast<const TrackerSingleRecHit *>(hit)) != nullptr) {
0237 DetId detId = hit->geographicalId();
0238
0239 if (layerMask_[detId.subdetId()][0] == 0) {
0240 return true;
0241 } else if (layerMask_[detId.subdetId()][0] == 2) {
0242 unsigned int ilayer = theTopology->layer(detId);
0243 if (layerMask_[detId.subdetId()][ilayer] == 0) {
0244 return true;
0245 }
0246 }
0247
0248 const GeomDet *det = theTracker->idToDet(detId);
0249 LocalVector ldir = det->toLocal(gdir);
0250 LocalPoint lpos = det->toLocal(gpos);
0251 if (mustProject) {
0252 lpos -= ldir * lpos.z() / ldir.z();
0253 }
0254 int hitStrips;
0255 float hitPredPos;
0256 const SiStripCluster &cluster = stripHit->stripCluster();
0257 bool usable = theFilter->getSizes(detId, cluster, lpos, ldir, hitStrips, hitPredPos);
0258 if (!usable)
0259 return true;
0260
0261 INC_COUNTER(called_)
0262 const auto &ls = cluster.amplitudes();
0263
0264
0265 if (std::abs(hitPredPos) < 1.5f && hitStrips <= 2) {
0266 return true;
0267 }
0268
0269 if (!cluster.isFromApprox()) {
0270
0271
0272 unsigned int thisSat = (ampls[0] >= 254), maxSat = thisSat;
0273 for (unsigned int i = 1, n = ampls.size(); i < n; ++i) {
0274 if (ampls[i] >= 254) {
0275 thisSat++;
0276 } else if (thisSat > 0) {
0277 maxSat = std::max<int>(maxSat, thisSat);
0278 thisSat = 0;
0279 }
0280 }
0281 if (thisSat > 0) {
0282 maxSat = std::max<int>(maxSat, thisSat);
0283 }
0284 if (maxSat >= maxNSat_) {
0285 INC_COUNTER(saturated_)
0286 return true;
0287 }
0288
0289
0290 INC_COUNTER(test_)
0291 unsigned int hitStripsTrim = ampls.size();
0292 int sum = std::accumulate(ampls.begin(), ampls.end(), 0);
0293 uint8_t trimCut = std::min<uint8_t>(trimMaxADC_, std::floor(trimMaxFracTotal_ * sum));
0294 auto begin = ampls.begin();
0295 auto last = ampls.end() - 1;
0296 while (hitStripsTrim > 1 && (*begin < std::max<uint8_t>(trimCut, trimMaxFracNeigh_ * (*(begin + 1))))) {
0297 hitStripsTrim--;
0298 ++begin;
0299 }
0300 while (hitStripsTrim > 1 && (*last < std::max<uint8_t>(trimCut, trimMaxFracNeigh_ * (*(last - 1))))) {
0301 hitStripsTrim--;
0302 --last;
0303 }
0304
0305 if (hitStripsTrim < std::floor(std::abs(hitPredPos) - maxTrimmedSizeDiffNeg_)) {
0306 INC_COUNTER(failTooNarrow_)
0307 return false;
0308 } else if (hitStripsTrim <= std::ceil(std::abs(hitPredPos) + maxTrimmedSizeDiffPos_)) {
0309 INC_COUNTER(passTrim_)
0310 return true;
0311 }
0312
0313 const StripGeomDetUnit *stripDetUnit = dynamic_cast<const StripGeomDetUnit *>(det);
0314 if (det == nullptr) {
0315 edm::LogError("Strip not a StripGeomDetUnit?") << " on " << detId.rawId() << "\n";
0316 return true;
0317 }
0318
0319 float mip = 3.9 / (sistrip::MeVperADCStrip /
0320 stripDetUnit->surface().bounds().thickness());
0321 float mipnorm = mip / std::abs(ldir.z());
0322 ::SlidingPeakFinder pf(std::max<int>(2, std::ceil(std::abs(hitPredPos) + subclusterWindow_)));
0323 ::PeakFinderTest test(mipnorm,
0324 detId(),
0325 cluster.firstStrip(),
0326 &*theNoise,
0327 seedCutMIPs_,
0328 seedCutSN_,
0329 subclusterCutMIPs_,
0330 subclusterCutSN_);
0331 if (pf.apply(cluster.amplitudes(), test)) {
0332 INC_COUNTER(passSC_)
0333 return true;
0334 } else {
0335 INC_COUNTER(failTooLarge_)
0336 return false;
0337 }
0338 } else {
0339 return cluster.filter();
0340 }
0341 }
0342 return true;
0343 }
0344
0345 void StripSubClusterShapeFilterBase::setEventBase(const edm::Event &event, const edm::EventSetup &es) {
0346
0347 theTracker = es.getHandle(geomToken_);
0348 theFilter = es.getHandle(csfToken_);
0349
0350
0351 theTopology = es.getHandle(topoToken_);
0352 theNoise = es.getHandle(stripNoiseToken_);
0353 }
0354
0355
0356 bool StripSubClusterShapeTrajectoryFilter::toBeContinued(Trajectory &trajectory) const {
0357 throw cms::Exception("toBeContinued(Traj) instead of toBeContinued(TempTraj)");
0358 }
0359
0360
0361 bool StripSubClusterShapeTrajectoryFilter::testLastHit(const TrajectoryMeasurement &last) const {
0362 const TrackingRecHit *hit = last.recHit()->hit();
0363 if (!last.updatedState().isValid())
0364 return true;
0365 if (hit == nullptr || !hit->isValid())
0366 return true;
0367 if (hit->geographicalId().subdetId() < SiStripDetId::TIB)
0368 return true;
0369 return testLastHit(hit, last.updatedState(), false);
0370 }
0371
0372
0373 bool StripSubClusterShapeTrajectoryFilter::toBeContinued(TempTrajectory &trajectory) const {
0374 const TempTrajectory::DataContainer &tms = trajectory.measurements();
0375 return testLastHit(*tms.rbegin());
0376 }
0377
0378
0379 bool StripSubClusterShapeTrajectoryFilter::qualityFilter(const Trajectory &trajectory) const {
0380 const Trajectory::DataContainer &tms = trajectory.measurements();
0381 return testLastHit(*tms.rbegin());
0382 }
0383
0384
0385 bool StripSubClusterShapeTrajectoryFilter::qualityFilter(const TempTrajectory &trajectory) const {
0386 const TempTrajectory::DataContainer &tms = trajectory.measurements();
0387 return testLastHit(*tms.rbegin());
0388 }
0389
0390
0391 StripSubClusterShapeSeedFilter::StripSubClusterShapeSeedFilter(const edm::ParameterSet &iConfig,
0392 edm::ConsumesCollector &iC)
0393 : StripSubClusterShapeFilterBase(iConfig, iC),
0394 filterAtHelixStage_(iConfig.getParameter<bool>("FilterAtHelixStage"))
0395
0396 {
0397 if (filterAtHelixStage_)
0398 edm::LogError("Configuration")
0399 << "StripSubClusterShapeSeedFilter: FilterAtHelixStage is not yet working correctly.\n";
0400 }
0401
0402
0403 bool StripSubClusterShapeSeedFilter::compatible(const TrajectoryStateOnSurface &tsos,
0404 SeedingHitSet::ConstRecHitPointer thit) const {
0405 if (filterAtHelixStage_)
0406 return true;
0407 const TrackingRecHit *hit = thit->hit();
0408 if (hit == nullptr || !hit->isValid())
0409 return true;
0410 if (hit->geographicalId().subdetId() < SiStripDetId::TIB)
0411 return true;
0412 return testLastHit(hit, tsos, false);
0413 }
0414
0415 bool StripSubClusterShapeSeedFilter::compatible(const SeedingHitSet &hits,
0416 const GlobalTrajectoryParameters &helixStateAtVertex,
0417 const FastHelix &helix) const {
0418 if (!filterAtHelixStage_)
0419 return true;
0420
0421 if (!helix.isValid()
0422 && !helix.circle().isLine())
0423 edm::LogWarning("InvalidHelix") << "StripSubClusterShapeSeedFilter helix is not valid, result is bad";
0424
0425 float xc = helix.circle().x0(), yc = helix.circle().y0();
0426
0427 GlobalPoint vertex = helixStateAtVertex.position();
0428 GlobalVector momvtx = helixStateAtVertex.momentum();
0429 float x0 = vertex.x(), y0 = vertex.y();
0430 for (unsigned int i = 0, n = hits.size(); i < n; ++i) {
0431 auto const &hit = *hits[i];
0432 if (hit.geographicalId().subdetId() < SiStripDetId::TIB)
0433 continue;
0434
0435 GlobalPoint pos = hit.globalPosition();
0436 float x1 = pos.x(), y1 = pos.y(), dx1 = x1 - xc, dy1 = y1 - yc;
0437
0438
0439 float perpx = -dy1, perpy = dx1;
0440 if (perpx * (x1 - x0) + perpy * (y1 - y0) < 0) {
0441 perpy = -perpy;
0442 perpx = -perpx;
0443 }
0444
0445
0446 float pnorm = 1.0 / std::sqrt(perpx * perpx + perpy * perpy + 1);
0447 GlobalVector gdir(perpx * pnorm, perpy * pnorm, (momvtx.z() > 0 ? pnorm : -pnorm));
0448
0449 if (!testLastHit(&hit, pos, gdir)) {
0450 return false;
0451 }
0452 }
0453 return true;
0454 }