CMS 3D CMS Logo

StripSubClusterShapeTrajectoryFilter.cc
Go to the documentation of this file.
2 
3 #include <map>
4 #include <set>
5 #include <algorithm>
6 
33 
36 
37 #ifdef StripSubClusterShapeFilterBase_COUNTERS
38 #define INC_COUNTER(X) X++;
39 #else
40 #define INC_COUNTER(X)
41 #endif
42 namespace {
43  class SlidingPeakFinder {
44  public:
45  SlidingPeakFinder(unsigned int size) :
46  size_(size), half_((size+1)/2) {}
47 
48  template<typename Test>
49  bool apply(const uint8_t *x, const uint8_t *begin, const uint8_t *end, const Test & test, bool verbose=false, int firststrip=0) {
50  const uint8_t * ileft = (x != begin) ? std::min_element(x-1,x+half_) : begin - 1;
51  const uint8_t * iright = ((x+size_) < end) ? std::min_element(x+half_,std::min(x+size_+1,end)) : end;
52  uint8_t left = (ileft < begin ? 0 : *ileft );
53  uint8_t right = (iright >= end ? 0 : *iright);
54  uint8_t center = *std::max_element(x, std::min(x+size_,end));
55  uint8_t maxmin = std::max(left,right);
56  if (maxmin < center) {
57  bool ret = test(center, maxmin);
58  if (ret) {
59  ret = test(ileft,iright,begin,end);
60  }
61  return ret;
62  } else {
63  return false;
64  }
65  }
66 
67  template<typename V, typename Test>
68  bool apply(const V & ampls, const Test & test, bool verbose=false, int firststrip=0) {
69  const uint8_t *begin = &*ampls.begin();
70  const uint8_t *end = &*ampls.end();
71  for (const uint8_t *x = begin; x < end - (half_-1); ++x) {
72  if (apply(x,begin,end,test,verbose,firststrip)) {
73  return true;
74  }
75  }
76  return false;
77  }
78 
79  private:
80  unsigned int size_, half_;
81 
82  };
83 
84  struct PeakFinderTest {
85  PeakFinderTest(float mip, uint32_t detid, uint32_t firstStrip, const SiStripNoises *theNoise,
86  float seedCutMIPs, float seedCutSN,
87  float subclusterCutMIPs, float subclusterCutSN) :
88  mip_(mip), detid_(detid), firstStrip_(firstStrip), noiseObj_(theNoise), noises_(theNoise->getRange(detid)),
89  subclusterCutMIPs_(subclusterCutMIPs), sumCut_(subclusterCutMIPs_*mip_), subclusterCutSN2_(subclusterCutSN*subclusterCutSN)
90  {
91  cut_ = std::min<float>(seedCutMIPs*mip, seedCutSN*noiseObj_->getNoise(firstStrip+1, noises_));
92  }
93 
94  bool operator()(uint8_t max, uint8_t min) const {
95  return max-min > cut_;
96  }
97  bool operator()(const uint8_t *left, const uint8_t *right, const uint8_t *begin, const uint8_t *end) const {
98  int yleft = (left < begin ? 0 : *left);
99  int yright = (right >= end ? 0 : *right);
100  float sum = 0.0;
101  int maxval = 0; float noise = 0;
102  for (const uint8_t *x = left+1; x < right; ++x) {
103  int baseline = (yleft * int(right-x) + yright * int(x-left)) / int(right-left);
104  sum += int(*x) - baseline;
105  noise += std::pow(noiseObj_->getNoise(firstStrip_ + int(x-begin), noises_), 2);
106  maxval = std::max(maxval, int(*x) - baseline);
107  }
108  if (sum > sumCut_ && sum*sum > noise*subclusterCutSN2_) return true;
109  return false;
110  }
111 
112  private:
113  float mip_;
114  unsigned int detid_; int firstStrip_;
115  const SiStripNoises *noiseObj_;
116  SiStripNoises::Range noises_;
117  uint8_t cut_;
118  float subclusterCutMIPs_, sumCut_, subclusterCutSN2_;
119  };
120 
121 }
122 
123 /*****************************************************************************/
126  label_(iCfg.getUntrackedParameter<std::string>("label","")),
127  maxNSat_(iCfg.getParameter<uint32_t>("maxNSat")),
128  trimMaxADC_(iCfg.getParameter<double>("trimMaxADC")),
129  trimMaxFracTotal_(iCfg.getParameter<double>("trimMaxFracTotal")),
130  trimMaxFracNeigh_(iCfg.getParameter<double>("trimMaxFracNeigh")),
131  maxTrimmedSizeDiffPos_(iCfg.getParameter<double>("maxTrimmedSizeDiffPos")),
132  maxTrimmedSizeDiffNeg_(iCfg.getParameter<double>("maxTrimmedSizeDiffNeg")),
133  subclusterWindow_(iCfg.getParameter<double>("subclusterWindow")),
134  seedCutMIPs_(iCfg.getParameter<double>("seedCutMIPs")),
135  seedCutSN_(iCfg.getParameter<double>("seedCutSN")),
136  subclusterCutMIPs_(iCfg.getParameter<double>("subclusterCutMIPs")),
137  subclusterCutSN_(iCfg.getParameter<double>("subclusterCutSN"))
138 #ifdef StripSubClusterShapeFilterBase_COUNTERS
139  ,called_(0),saturated_(0),test_(0),passTrim_(0),failTooLarge_(0),passSC_(0),failTooNarrow_(0)
140 #endif
141 {
142  if (iCfg.exists("layerMask")) {
143  const edm::ParameterSet &iLM = iCfg.getParameter<edm::ParameterSet>("layerMask");
144  const char *ndets[4] = { "TIB", "TID", "TOB", "TEC" };
145  const int idets[4] = { 3, 4, 5, 6 };
146  for (unsigned int i = 0; i < 4; ++i) {
147  if (iLM.existsAs<bool>(ndets[i])) {
148  std::fill(layerMask_[idets[i]].begin(), layerMask_[idets[i]].end(), iLM.getParameter<bool>(ndets[i]));
149  } else {
150  layerMask_[idets[i]][0] = 2;
151  std::fill(layerMask_[idets[i]].begin()+1, layerMask_[idets[i]].end(), 0);
152  for (uint32_t lay : iLM.getParameter<std::vector<uint32_t>>(ndets[i])) {
153  layerMask_[idets[i]][lay] = 1;
154  }
155  }
156  }
157  } else {
158  for (auto & arr : layerMask_) {
159  std::fill(arr.begin(), arr.end(), 1);
160  }
161  }
162 }
163 
164 /*****************************************************************************/
166 {
167 #if 0
168  std::cout << "StripSubClusterShapeFilterBase " << label_ <<": called " << called_ << std::endl;
169  std::cout << "StripSubClusterShapeFilterBase " << label_ <<": saturated " << saturated_ << std::endl;
170  std::cout << "StripSubClusterShapeFilterBase " << label_ <<": test " << test_ << std::endl;
171  std::cout << "StripSubClusterShapeFilterBase " << label_ <<": failTooNarrow " << failTooNarrow_ << std::endl;
172  std::cout << "StripSubClusterShapeFilterBase " << label_ <<": passTrim " << passTrim_ << std::endl;
173  std::cout << "StripSubClusterShapeFilterBase " << label_ <<": passSC " << passSC_ << std::endl;
174  std::cout << "StripSubClusterShapeFilterBase " << label_ <<": failTooLarge " << failTooLarge_ << std::endl;
175 #endif
176 }
177 
178 
180  (const TrackingRecHit *hit, const TrajectoryStateOnSurface &tsos, bool mustProject) const
181 {
182  return testLastHit(hit, tsos.globalPosition(), tsos.globalDirection(), mustProject);
183 
184 }
186  (const TrackingRecHit *hit, const GlobalPoint &gpos, const GlobalVector &gdir, bool mustProject) const
187 {
188  const TrackerSingleRecHit *stripHit = nullptr;
189  if (typeid(*hit) == typeid(SiStripMatchedRecHit2D)) {
190  const SiStripMatchedRecHit2D & mhit = static_cast<const SiStripMatchedRecHit2D &>(*hit);
191  SiStripRecHit2D mono = mhit.monoHit();
192  SiStripRecHit2D stereo = mhit.stereoHit();
193  return testLastHit(&mono, gpos, gdir, true) && testLastHit(&stereo, gpos, gdir, true);
194  } else if (typeid(*hit) == typeid(ProjectedSiStripRecHit2D)) {
195  const ProjectedSiStripRecHit2D & mhit = static_cast<const ProjectedSiStripRecHit2D &>(*hit);
196  const SiStripRecHit2D &orig = mhit.originalHit();
197  return testLastHit(&orig, gpos, gdir, true);
198  } else if ((stripHit = dynamic_cast<const TrackerSingleRecHit *>(hit)) != nullptr) {
199  DetId detId = hit->geographicalId();
200 
201  if (layerMask_[detId.subdetId()][0] == 0) {
202  return true; // no filtering here
203  } else if (layerMask_[detId.subdetId()][0] == 2) {
204  unsigned int ilayer = theTopology->layer(detId);
205  if (layerMask_[detId.subdetId()][ilayer] == 0) {
206  return true; // no filtering here
207  }
208  }
209 
210  const GeomDet *det = theTracker->idToDet(detId);
211  LocalVector ldir = det->toLocal(gdir);
212  LocalPoint lpos = det->toLocal(gpos);
213  if (mustProject) {
214  lpos -= ldir * lpos.z()/ldir.z();
215  }
216  int hitStrips; float hitPredPos;
217  const SiStripCluster &cluster = stripHit->stripCluster();
218  bool usable = theFilter->getSizes(detId, cluster, lpos, ldir, hitStrips, hitPredPos);
219  if (!usable) return true;
220 
221  INC_COUNTER(called_)
222  const auto &ampls = cluster.amplitudes();
223 
224  // pass-through of trivial case
225  if (std::abs(hitPredPos) < 1.5f && hitStrips <= 2) {
226  return true;
227  }
228 
229 
230  // compute number of consecutive saturated strips
231  // (i.e. with adc count >= 254, see SiStripCluster class for documentation)
232  unsigned int thisSat = (ampls[0] >= 254), maxSat = thisSat;
233  for (unsigned int i = 1, n = ampls.size(); i < n; ++i) {
234  if (ampls[i] >= 254) {
235  thisSat++;
236  } else if (thisSat > 0) {
237  maxSat = std::max<int>(maxSat, thisSat);
238  thisSat = 0;
239  }
240  }
241  if (thisSat > 0) {
242  maxSat = std::max<int>(maxSat, thisSat);
243  }
244  if (maxSat >= maxNSat_) {
245  INC_COUNTER(saturated_)
246  return true;
247  }
248 
249  // trimming
250  INC_COUNTER(test_)
251  unsigned int hitStripsTrim = ampls.size();
252  int sum = std::accumulate(ampls.begin(), ampls.end(), 0);
253  uint8_t trimCut = std::min<uint8_t>(trimMaxADC_, std::floor(trimMaxFracTotal_ * sum));
254  auto begin = ampls.begin();
255  auto last = ampls.end()-1;
256  while (hitStripsTrim > 1 && (*begin < std::max<uint8_t>(trimCut, trimMaxFracNeigh_*(*(begin+1)))) ) { hitStripsTrim--; ++begin; }
257  while (hitStripsTrim > 1 && (*last < std::max<uint8_t>(trimCut, trimMaxFracNeigh_*(*(last -1)))) ) { hitStripsTrim--; --last; }
258 
259  if (hitStripsTrim < std::floor(std::abs(hitPredPos)-maxTrimmedSizeDiffNeg_)) {
260  INC_COUNTER(failTooNarrow_)
261  return false;
262  } else if (hitStripsTrim <= std::ceil(std::abs(hitPredPos)+maxTrimmedSizeDiffPos_)) {
263  INC_COUNTER(passTrim_)
264  return true;
265  }
266 
267  const StripGeomDetUnit* stripDetUnit = dynamic_cast<const StripGeomDetUnit *>(det);
268  if (det == nullptr) { edm::LogError("Strip not a StripGeomDetUnit?") << " on " << detId.rawId() << "\n"; return true; }
269 
270  float MeVperADCStrip = 9.5665E-4; // conversion constant from ADC counts to MeV for the SiStrip detector
271  float mip = 3.9 / ( MeVperADCStrip/stripDetUnit->surface().bounds().thickness() ); // 3.9 MeV/cm = ionization in silicon
272  float mipnorm = mip/std::abs(ldir.z());
273  ::SlidingPeakFinder pf(std::max<int>(2,std::ceil(std::abs(hitPredPos)+subclusterWindow_)));
274  ::PeakFinderTest test(mipnorm, detId(), cluster.firstStrip(), &*theNoise, seedCutMIPs_, seedCutSN_, subclusterCutMIPs_, subclusterCutSN_);
275  if (pf.apply(cluster.amplitudes(), test)) {
276  INC_COUNTER(passSC_)
277  return true;
278  } else {
279  INC_COUNTER(failTooLarge_)
280  return false;
281  }
282 
283  }
284  return true;
285 }
286 
288  (const edm::Event &event, const edm::EventSetup &es)
289 {
290  // Get tracker geometry
291  es.get<TrackerDigiGeometryRecord>().get(theTracker);
292 
293  es.get<CkfComponentsRecord>().get("ClusterShapeHitFilter",theFilter);
294 
295  //Retrieve tracker topology from geometry
296  es.get<TrackerTopologyRcd>().get(theTopology);
297 
298  es.get<SiStripNoisesRcd>().get(theNoise);
299 
300 }
301 
302 /*****************************************************************************/
304 (Trajectory& trajectory) const
305 {
306  throw cms::Exception("toBeContinued(Traj) instead of toBeContinued(TempTraj)");
307 }
308 
309 /*****************************************************************************/
311 {
312  const TrackingRecHit* hit = last.recHit()->hit();
313  if (!last.updatedState().isValid()) return true;
314  if (hit == nullptr || !hit->isValid()) return true;
315  if (hit->geographicalId().subdetId() < SiStripDetId::TIB) return true; // we look only at strips for now
316  return testLastHit(hit, last.updatedState(), false);
317 
318 }
319 
320 /*****************************************************************************/
322 (TempTrajectory& trajectory) const
323 {
324  const TempTrajectory::DataContainer & tms = trajectory.measurements();
325  return testLastHit(*tms.rbegin());
326 }
327 
328 /*****************************************************************************/
330  (const Trajectory& trajectory) const
331 {
332  const Trajectory::DataContainer & tms = trajectory.measurements();
333  return testLastHit(*tms.rbegin());
334 }
335 
336 /*****************************************************************************/
338  (const TempTrajectory& trajectory) const
339 {
340  const TempTrajectory::DataContainer & tms = trajectory.measurements();
341  return testLastHit(*tms.rbegin());
342 }
343 
344 
345 /*****************************************************************************/
348  StripSubClusterShapeFilterBase(iConfig,iC),
349  filterAtHelixStage_(iConfig.getParameter<bool>("FilterAtHelixStage"))
350 
351 {
352  if (filterAtHelixStage_) edm::LogError("Configuration") << "StripSubClusterShapeSeedFilter: FilterAtHelixStage is not yet working correctly.\n";
353 }
354 
355 
356 /*****************************************************************************/
359 {
360  if (filterAtHelixStage_) return true;
361  const TrackingRecHit* hit = thit->hit();
362  if (hit == nullptr || !hit->isValid()) return true;
363  if (hit->geographicalId().subdetId() < SiStripDetId::TIB) return true; // we look only at strips for now
364  return testLastHit(hit, tsos, false);
365 }
366 
368  (const SeedingHitSet &hits, const GlobalTrajectoryParameters &helixStateAtVertex, const FastHelix &helix) const
369 {
370  if (!filterAtHelixStage_) return true;
371 
372  if (!helix.isValid() //check still if it's a straight line, which are OK
373  && !helix.circle().isLine())//complain if it's not even a straight line
374  edm::LogWarning("InvalidHelix") << "StripSubClusterShapeSeedFilter helix is not valid, result is bad";
375 
376  float xc = helix.circle().x0(), yc = helix.circle().y0();
377 
378  GlobalPoint vertex = helixStateAtVertex.position();
379  GlobalVector momvtx = helixStateAtVertex.momentum();
380  float x0 = vertex.x(), y0 = vertex.y();
381  for (unsigned int i = 0, n = hits.size(); i < n; ++i) {
382  auto const & hit = *hits[i];
383  if (hit.geographicalId().subdetId() < SiStripDetId::TIB) continue;
384 
386  float x1 = pos.x(), y1 = pos.y(), dx1 = x1 - xc, dy1 = y1 - yc;
387 
388  // now figure out the proper tangent vector
389  float perpx = -dy1, perpy = dx1;
390  if (perpx * (x1-x0) + perpy * (y1 - y0) < 0) {
391  perpy = -perpy; perpx = -perpx;
392  }
393 
394  // now normalize (perpx, perpy, 1.0) to unity
395  float pnorm = 1.0/std::sqrt(perpx*perpx + perpy*perpy + 1);
396  GlobalVector gdir(perpx*pnorm, perpy*pnorm, (momvtx.z() > 0 ? pnorm : -pnorm));
397 
398  if (!testLastHit(&hit, pos, gdir)) {
399  return false; // not yet
400  }
401  }
402  return true;
403 }
404 
size
Write out results.
bool toBeContinued(TempTrajectory &) const override
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
bool isValid() const
Definition: FastHelix.h:63
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:161
ConstRecHitPointer const & recHit() const
double x0() const
Definition: FastCircle.h:50
bool isLine() const
Definition: FastCircle.h:58
const DataContainer & measurements() const
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:50
T y() const
Definition: PV3DBase.h:63
bool exists(std::string const &parameterName) const
checks if a parameter exists
GlobalPoint globalPosition() const
LocalPoint toLocal(const GlobalPoint &gp) const
Conversion to the R.F. of the GeomDet.
Definition: GeomDet.h:69
const Bounds & bounds() const
Definition: Surface.h:120
uint16_t firstStrip() const
const FastCircle & circle() const
Definition: FastHelix.h:67
virtual GlobalPoint globalPosition() const
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:42
DataContainer const & measurements() const
Definition: Trajectory.h:196
BaseTrackerRecHit const * ConstRecHitPointer
Definition: SeedingHitSet.h:11
std::vector< TrajectoryMeasurement > DataContainer
Definition: Trajectory.h:44
T sqrt(T t)
Definition: SSEVec.h:18
T z() const
Definition: PV3DBase.h:64
bool qualityFilter(const TempTrajectory &) const override
constexpr int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:41
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
bool testLastHit(const TrackingRecHit *hit, const TrajectoryStateOnSurface &tsos, bool mustProject=false) const
#define end
Definition: vmac.h:39
T min(T a, T b)
Definition: MathUtil.h:58
StripSubClusterShapeFilterBase(const edm::ParameterSet &iConfig, edm::ConsumesCollector &iC)
const_iterator rbegin() const
Definition: bqueue.h:163
void setEventBase(const edm::Event &, const edm::EventSetup &)
SiStripRecHit2D originalHit() const
Definition: DetId.h:18
virtual TrackingRecHit const * hit() const
SiStripRecHit2D stereoHit() const
virtual float thickness() const =0
SiStripCluster const & stripCluster() const
bool isValid() const
SiStripRecHit2D monoHit() const
double y0() const
Definition: FastCircle.h:52
#define begin
Definition: vmac.h:32
bool compatible(const TrajectoryStateOnSurface &tsos, SeedingHitSet::ConstRecHitPointer hit) const override
const Range getRange(const uint32_t detID) const
T get() const
Definition: EventSetup.h:71
unsigned int size() const
Definition: SeedingHitSet.h:46
TrajectoryStateOnSurface const & updatedState() const
DetId geographicalId() const
bool testLastHit(const TrajectoryMeasurement &last) const
std::pair< ContainerIterator, ContainerIterator > Range
Definition: SiStripNoises.h:50
T x() const
Definition: PV3DBase.h:62
const std::vector< uint8_t > & amplitudes() const
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
Vec apply(Vec v, F f)
Definition: ExtVec.h:83
Definition: event.py:1
GlobalVector globalDirection() const
StripSubClusterShapeSeedFilter(const edm::ParameterSet &iConfig, edm::ConsumesCollector &iC)