23 struct KFFittingSmootherParam {
25 : theEstimateCut(conf.getParameter<double>(
"EstimateCut")),
26 theMaxFractionOutliers(conf.getParameter<double>(
"MaxFractionOutliers")),
27 theMaxNumberOfOutliers(conf.getParameter<
int>(
"MaxNumberOfOutliers")),
28 theNoOutliersBeginEnd(conf.getParameter<
bool>(
"NoOutliersBeginEnd")),
29 theMinDof(conf.getParameter<
int>(
"MinDof")),
30 theMinNumberOfHits(conf.getParameter<
int>(
"MinNumberOfHits")),
31 rejectTracksFlag(conf.getParameter<
bool>(
"RejectTracks")),
32 breakTrajWith2ConsecutiveMissing(conf.getParameter<
bool>(
"BreakTrajWith2ConsecutiveMissing")),
33 noInvalidHitsBeginEnd(conf.getParameter<
bool>(
"NoInvalidHitsBeginEnd")) {}
35 double theEstimateCut;
37 float theMaxFractionOutliers;
38 int theMaxNumberOfOutliers;
39 bool theNoOutliersBeginEnd;
42 int theMinNumberOfHits;
43 bool rejectTracksFlag;
44 bool breakTrajWith2ConsecutiveMissing;
45 bool noInvalidHitsBeginEnd;
48 class KFFittingSmoother final :
public TrajectoryFitter,
private KFFittingSmootherParam {
50 ~KFFittingSmoother()
override {}
55 : KFFittingSmootherParam(conf), theFitter(aFitter.
clone()), theSmoother(aSmoother.
clone()) {}
59 desc.add<
double>(
"EstimateCut", -1);
60 desc.add<
double>(
"MaxFractionOutliers", 0.3);
61 desc.add<
int>(
"MaxNumberOfOutliers", 3);
62 desc.add<
int>(
"MinDof", 2);
63 desc.add<
bool>(
"NoOutliersBeginEnd",
false);
64 desc.add<
int>(
"MinNumberOfHits", 5);
65 desc.add<
bool>(
"RejectTracks",
true);
66 desc.add<
bool>(
"BreakTrajWith2ConsecutiveMissing",
true);
67 desc.add<
bool>(
"NoInvalidHitsBeginEnd",
true);
68 desc.add<
double>(
"LogPixelProbabilityCut", 0);
73 const RecHitContainer&
hits,
81 std::unique_ptr<TrajectoryFitter>
clone()
const override {
82 return std::unique_ptr<TrajectoryFitter>(
new KFFittingSmoother(*theFitter, *theSmoother, *
this));
86 theFitter->setHitCloner(hc);
87 theSmoother->setHitCloner(hc);
92 KFFittingSmootherParam
const&
other)
93 : KFFittingSmootherParam(
other), theFitter(aFitter.
clone()), theSmoother(aSmoother.
clone()) {}
96 if (theEstimateCut > 0) {
99 !fitted.empty() && fitted.foundHits() >= theMinNumberOfHits &&
100 (!fitted.lastMeasurement().recHitR().isValid() || (fitted.lastMeasurement().recHitR().det() !=
nullptr &&
101 fitted.lastMeasurement().estimate() > theEstimateCut)))
103 if (fitted.foundHits() < theMinNumberOfHits)
106 return theSmoother->trajectory(fitted);
110 const std::unique_ptr<TrajectoryFitter> theFitter;
111 const std::unique_ptr<TrajectorySmoother> theSmoother;
114 static bool checkForNans(
const Trajectory& theTraj);
116 friend class KFFittingSmootherESProducer;
122 #define DPRINT(x) std::cout << x << ": "
123 #define PRINT std::cout
125 #define DPRINT(x) LogTrace(x)
126 #define PRINT LogTrace("")
132 return smoothingStep(theFitter->fitOne(
t,
type));
135 bool KFFittingSmoother::checkForNans(
const Trajectory& theTraj) {
139 for (
auto const& tm : vtm) {
142 auto const&
v = tm.updatedState().localParameters().vector();
143 for (
int i = 0;
i < 5; ++
i)
146 if (!tm.updatedState().curvilinearError().posDef())
148 auto const&
m = tm.updatedState().curvilinearError().matrix();
149 for (
int i = 0;
i < 5; ++
i)
150 for (
int j = 0;
j < (
i + 1); ++
j)
166 const RecHitContainer&
hits,
169 LogDebug(
"TrackFitters") <<
"In KFFittingSmoother::fit";
171 print(
"firstPred ", firstPredTsos);
176 RecHitContainer myHits =
hits;
180 Trajectory smoothed = smoothingStep(theFitter->fitOne(aSeed, myHits, firstPredTsos));
185 for (
unsigned int j = 0;
j < myHits.size();
j++) {
186 if (myHits[
j]->det())
187 LogTrace(
"TrackFitters") <<
"hit #:" <<
j + 1 <<
" rawId=" << myHits[
j]->det()->geographicalId().rawId()
188 <<
" validity=" << myHits[
j]->isValid();
190 LogTrace(
"TrackFitters") <<
"hit #:" <<
j + 1 <<
" Hit with no Det information";
194 #if defined(VI_DEBUG) || defined(EDM_ML_DEBUG)
202 if (!smoothed.
isValid() || (hasNaN = !checkForNans(smoothed)) || (smoothed.
foundHits() < theMinNumberOfHits)) {
204 edm::LogWarning(
"TrackNaN") <<
"Track has NaN or the cov is not pos-definite";
205 if (smoothed.
foundHits() < theMinNumberOfHits)
206 LogTrace(
"TrackFitters") <<
"smoothed.foundHits()<theMinNumberOfHits";
207 DPRINT(
"TrackFitters") <<
"smoothed invalid => trajectory rejected with nhits/chi2 " << smoothed.
foundHits()
209 if (rejectTracksFlag) {
213 DPRINT(
"TrackFitters") <<
"smoothed invalid => returning orignal trajectory with nhits/chi2 "
220 LogTrace(
"TrackFitters") <<
"dump hits after smoothing";
222 for (Trajectory::DataContainer::iterator it = meas.begin(); it != meas.end(); ++it) {
223 LogTrace(
"TrackFitters") <<
"hit #" << meas.end() - it - 1 <<
" validity=" << it->recHit()->isValid()
224 <<
" det=" << it->recHit()->geographicalId().rawId();
230 DPRINT(
"TrackFitters") <<
"lost hits. before/after: " << myHits.size() <<
'/' << smoothed.
measurements().size()
233 if (theEstimateCut <= 0)
240 unsigned int nbad = 0;
241 unsigned int ind = 0;
242 unsigned int lastValid = smoothed.
measurements().size();
244 if (tm.estimate() > theEstimateCut &&
245 tm.recHitR().det() !=
nullptr
248 if (ind < lastValid && tm.recHitR().det() !=
nullptr && tm.recHitR().isValid())
256 DPRINT(
"TrackFitters") <<
"size/found/outliers list " << smoothed.
measurements().size() <<
'/'
257 << smoothed.
foundHits() <<
' ' << nbad <<
": ";
258 for (
auto i = 0
U;
i < nbad; ++
i)
264 int(nbad) > theMaxNumberOfOutliers ||
float(nbad) > theMaxFractionOutliers *
float(smoothed.
foundHits())) {
265 DPRINT(
"TrackFitters") <<
"smoothed low quality => trajectory with nhits/chi2 " << smoothed.
foundHits() <<
'/'
267 PRINT <<
"try to remove " << lastValid << std::endl;
283 bad[nbad++] = lastValid;
295 auto NHits = myHits.size();
299 for (
auto i = 0
U;
i < nbad; ++
i) {
302 auto removedHit = myHits[
j];
304 smoothedCand[
i] = smoothingStep(theFitter->fitOne(aSeed, myHits, firstPredTsos));
305 myHits[
j] = removedHit;
307 minChi2 = smoothedCand[
i].chiSquared();
313 DPRINT(
"TrackFitters") <<
"New trajectories all invalid"
325 PRINT << tm.recHitR().geographicalId() <<
'/' << tm.estimate() <<
' ';
327 for (
auto const& tm : smoothedCand[loc].measurements())
328 PRINT << tm.recHitR().geographicalId() <<
'/' << tm.estimate() <<
' ';
341 DPRINT(
"TrackFitters") <<
"new trajectory with nhits/chi2 " << smoothed.
foundHits() <<
'/'
345 if (breakTrajWith2ConsecutiveMissing) {
346 unsigned int firstinvalid = myHits.size();
347 for (
unsigned int j = 0;
j < myHits.size() - 1; ++
j) {
350 ((myHits[
j]->geographicalId().rawId() & (~3)) !=
351 (myHits[
j + 1]->geographicalId().rawId() & (~3)))
354 DPRINT(
"TrackFitters") <<
"Found two consecutive missing hits. First invalid: " << firstinvalid <<
"\n";
361 if (firstinvalid != myHits.size()) {
362 myHits.erase(myHits.begin() + firstinvalid, myHits.end());
363 smoothed = smoothingStep(theFitter->fitOne(aSeed, myHits, firstPredTsos));
373 if (noInvalidHitsBeginEnd && !smoothed.
empty()
377 LogTrace(
"TrackFitters") <<
"Last measurement is invalid";
384 LogTrace(
"TrackFitters") <<
"First measurement is in`valid";
387 auto it = meas.begin();
388 for (; it != meas.end(); ++it)
389 if (it->recHitR().isValid())
394 for (
auto itt = it + 1; itt != meas.end(); ++itt)
403 LogTrace(
"TrackFitters") <<
"end: returning smoothed trajectory with chi2=" << smoothed.
chiSquared();
418 "KFFittingSmoother::fit(TrajectorySeed, <TransientTrackingRecHit>) not implemented");