CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
DualKalmanTrajectory.cc
Go to the documentation of this file.
1 
11 
15 
18 
23 
25 
28 
31 
32 //-----------------------------------------------------------------------------------------------
34  const TrajectoryStateOnSurface &referenceTsos,
35  const std::vector<unsigned int> &forwardRecHitNums,
36  const std::vector<unsigned int> &backwardRecHitNums,
37  const MagneticField *magField,
38  MaterialEffects materialEffects,
39  PropagationDirection propDir,
40  double mass,
41  bool useBeamSpot, const reco::BeamSpot &beamSpot,
42  int residualMethod)
43  : ReferenceTrajectoryBase(referenceTsos.localParameters().mixedFormatVector().kSize,
44  forwardRecHitNums.size() + backwardRecHitNums.size() - 1, 0, 0)
45 {
46  theValidityFlag = this->construct(trajMeasurements, referenceTsos,
47  forwardRecHitNums, backwardRecHitNums,
48  mass, materialEffects, propDir, magField,
49  useBeamSpot, beamSpot, residualMethod);
50 }
51 
52 
53 
54 //-----------------------------------------------------------------------------------------------
55 DualKalmanTrajectory::DualKalmanTrajectory(unsigned int nPar, unsigned int nHits)
56  : ReferenceTrajectoryBase(nPar, nHits, 0, 0)
57 {}
58 
59 
60 //-----------------------------------------------------------------------------------------------
62  const TrajectoryStateOnSurface &refTsos,
63  const std::vector<unsigned int> &forwardRecHitNums,
64  const std::vector<unsigned int> &backwardRecHitNums,
65  double mass, MaterialEffects materialEffects,
66  const PropagationDirection propDir,
67  const MagneticField *magField,
68  bool useBeamSpot, const reco::BeamSpot &beamSpot,
69  int residualMethod)
70 {
71 
72  ReferenceTrajectoryPtr fwdTraj = this->construct(trajMeasurements, refTsos, forwardRecHitNums,
73  mass, materialEffects,
74  propDir, magField, useBeamSpot, beamSpot);
75 
76  ReferenceTrajectoryPtr bwdTraj = this->construct(trajMeasurements, refTsos, backwardRecHitNums,
77  mass, materialEffects,
78  this->oppositeDirection(propDir), magField,
79  useBeamSpot, beamSpot);
80 
81  // edm::LogError("Alignment") << "@SUB=DualKalmanTrajectory::construct"
82  // << "valid fwd/bwd " << fwdTraj->isValid()
83  // << "/" << bwdTraj->isValid();
84 
85  if (!fwdTraj->isValid() || !bwdTraj->isValid()) {
86  return false;
87  }
88 
89  //
90  // Combine both reference trajactories to a dual reference trajectory
91  //
92 
93 // const std::vector<TrajectoryStateOnSurface>& fwdTsosVec = fwdTraj->trajectoryStates();
94 // const std::vector<TrajectoryStateOnSurface>& bwdTsosVec = bwdTraj->trajectoryStates();
95 // theTsosVec.insert( theTsosVec.end(), fwdTsosVec.begin(), fwdTsosVec.end() );
96 // theTsosVec.insert( theTsosVec.end(), ++bwdTsosVec.begin(), bwdTsosVec.end() );
97 
98  // Take hits as they come from the Kalman fit.
99  const ConstRecHitContainer &fwdRecHits = fwdTraj->recHits();
100  const ConstRecHitContainer &bwdRecHits = bwdTraj->recHits();
101  theRecHits.insert(theRecHits.end(), fwdRecHits.begin(), fwdRecHits.end());
102  theRecHits.insert(theRecHits.end(), ++bwdRecHits.begin(), bwdRecHits.end());
103 
104  theParameters = this->extractParameters(refTsos);
105 
106  unsigned int nParam = theParameters.num_row();
107  unsigned int nFwdMeas = nMeasPerHit * fwdTraj->numberOfHits();
108  unsigned int nBwdMeas = nMeasPerHit * bwdTraj->numberOfHits();
109 
110 // theMeasurements.sub( 1, fwdTraj->measurements() );
111 // theMeasurements.sub( nFwdMeas+1, bwdTraj->measurements().sub( nMeasPerHit+1, nBwdMeas ) );
112 
113 // theMeasurementsCov.sub( 1, fwdTraj->measurementErrors() );
114 // theMeasurementsCov.sub( nFwdMeas+1, bwdTraj->measurementErrors().sub( nMeasPerHit+1, nBwdMeas ) );
115 
116 // theTrajectoryPositions.sub( 1, fwdTraj->trajectoryPositions() );
117 // theTrajectoryPositions.sub( nFwdMeas+1, bwdTraj->trajectoryPositions().sub( nMeasPerHit+1, nBwdMeas ) );
118 
119 // theTrajectoryPositionCov.sub( 1, fwdTraj->trajectoryPositionErrors() );
120 // theTrajectoryPositionCov.sub( nFwdMeas+1, bwdTraj->trajectoryPositionErrors().sub( nMeasPerHit+1, nBwdMeas ) );
121 
122  theDerivatives.sub(1, 1, fwdTraj->derivatives());
123  theDerivatives.sub(nFwdMeas+1, 1,
124  bwdTraj->derivatives().sub(nMeasPerHit+1, nBwdMeas, 1, nParam));
125 
126  // FIXME: next lines stolen from ReferenceTrajectory, no idea whether OK or not...
127  if (refTsos.hasError()) {
128  AlgebraicSymMatrix parameterCov = asHepMatrix<5>(refTsos.localError().matrix());
129  theTrajectoryPositionCov = parameterCov.similarity(theDerivatives);
130  } else {
132  }
133 
134  // Fill Kalman part, first for forward, then for backward part.
135  return this->fillKalmanPart(trajMeasurements, forwardRecHitNums, true, 0, residualMethod)
136  && this->fillKalmanPart(trajMeasurements, backwardRecHitNums, false,
137  forwardRecHitNums.size(), residualMethod);
138 }
139 
140 
141 //-----------------------------------------------------------------------------------------------
144  const TrajectoryStateOnSurface &referenceTsos,
145  const std::vector<unsigned int> &recHitNums,
146  double mass, MaterialEffects materialEffects,
147  const PropagationDirection propDir,
148  const MagneticField *magField,
149  bool useBeamSpot, const reco::BeamSpot &beamSpot) const
150 {
151 
153  recHits.reserve(recHitNums.size());
154  for (unsigned int i = 0; i < recHitNums.size(); ++i) {
155  recHits.push_back(trajMeasurements[recHitNums[i]].recHit());
156  }
157 
158  return new ReferenceTrajectory(referenceTsos, recHits, false, // hits are already ordered
159  magField, materialEffects, propDir, mass,
160  useBeamSpot, beamSpot);
161 }
162 
163 //-----------------------------------------------------------------------------------------------
165  const std::vector<unsigned int> &recHitNums,
166  bool startFirst, unsigned int iNextHit,
167  int residualMethod)
168 {
169  // startFirst==false: skip first hit of recHitNums
170  // iNextHit: first hit number to fill data members with
171  //
172  // Three approaches, choosen by 'residualMethod':
173  // 0: Just take hit error and the updated state as millepede needs it to redo the last fit step.
174  // 1: Use the unbiased residuals as for residual monitoring.
175  // 2: Use the _updated_ state and calculate the sigma that is part of
176  // the pull as sqrt(sigma_hit^2 - sigma_tsos^2).
177  // This should lead to the pull as defined on p. 236 of Blobel's book.
178  // Not sure whether this is 100% applicable/correct here, at least it might lead to
179  // numerical instabilities, cf.:
180  // https://hypernews.cern.ch/HyperNews/CMS/get/recoTracking/517/1/1/1/1/1.html
181 
182  for (unsigned int iMeas = (startFirst ? 0 : 1); iMeas < recHitNums.size(); ++iMeas, ++iNextHit) {
183  const TrajectoryMeasurement &trajMeasurement = trajMeasurements[recHitNums[iMeas]];
184 
185  TrajectoryStateOnSurface tsos; // depends on method
186  switch (residualMethod) {
187  case 0:
188  tsos = this->fillMeasurementAndError2(trajMeasurement.recHit(), iNextHit, trajMeasurement,
189  false); // plain hit error, not pull
190  break;
191  case 1:
192  tsos = this->fillMeasurementAndError1(trajMeasurement.recHit(), iNextHit, trajMeasurement);
193  break;
194  case 2:
195  tsos = this->fillMeasurementAndError2(trajMeasurement.recHit(), iNextHit, trajMeasurement,
196  true); // error of pull
197  break;
198  default:
199  throw cms::Exception("BadConfig")
200  << "[DualKalmanTrajectory::fillKalmanPart] expect residualMethod == 0, 1 or 2, not "
201  << residualMethod << ".";
202  }
203 
204  if (!tsos.isValid()) return false;
205  theTsosVec.push_back(tsos);
206 
207  this->fillTrajectoryPositions(trajMeasurement.recHit()->projectionMatrix(),
208  tsos, iNextHit);
209  }
210 
211  return true;
212 }
213 
214 //-----------------------------------------------------------------------------------------------
217  unsigned int iHit,
218  const TrajectoryMeasurement &trajMeasurement)
219 {
220  // Get the measurements and their errors.
221  // We have to add error from hit and that tsos that is combination of fwd and bwd state.
222 
223  TrajectoryStateCombiner tsosComb;
224  const TrajectoryStateOnSurface tsos = tsosComb(trajMeasurement.forwardPredictedState(),
225  trajMeasurement.backwardPredictedState());
226  if (tsos.isValid()) {
227  // No update of hit with tsos: it comes already from fwd+bwd tsos combination.
228  // See also https://hypernews.cern.ch/HyperNews/CMS/get/recoTracking/517/1.html .
229  // ConstRecHitPointer newHitPtr(hitPtr->canImproveWithTrack() ? hitPtr->clone(tsos) : hitPtr);
230 
231  const LocalPoint localMeasurement(hitPtr->localPosition());
232  const LocalError hitErr(this->hitErrorWithAPE(hitPtr));
233  // tsos prediction includes APE of other hits:
234  const LocalError tsosErr(tsos.localError().positionError());
235  const LocalError localMeasurementCov(hitErr.xx() + tsosErr.xx(),
236  hitErr.xy() + tsosErr.xy(),
237  hitErr.yy() + tsosErr.yy());
238 
239  theMeasurements[nMeasPerHit*iHit] = localMeasurement.x();
240  theMeasurements[nMeasPerHit*iHit+1] = localMeasurement.y();
241  theMeasurementsCov[nMeasPerHit*iHit] [nMeasPerHit*iHit] = localMeasurementCov.xx();
242  theMeasurementsCov[nMeasPerHit*iHit] [nMeasPerHit*iHit+1] = localMeasurementCov.xy();
243  theMeasurementsCov[nMeasPerHit*iHit+1][nMeasPerHit*iHit+1] = localMeasurementCov.yy();
244  }
245 
246  return tsos;
247 }
248 
249 //-----------------------------------------------------------------------------------------------
252  unsigned int iHit,
253  const TrajectoryMeasurement &trajMeasurement,
254  bool doPull)
255 {
256  // Get the measurements and their errors.
257  // We have to subtract error of updated tsos from hit.
258 
259  const TrajectoryStateOnSurface tsos = trajMeasurement.updatedState();
260  if (tsos.isValid()) {
261  // No further update of hit:
262  // - The Kalman fit used hitPtr as it comes here (besides APE, see below).
263  // - If the hit errors improve, we might get (rare) problems of negative diagonal elements, see below.
264  // ConstRecHitPointer newHitPtr(hitPtr->canImproveWithTrack() ? hitPtr->clone(tsos) : hitPtr);
265 
266  const LocalPoint localMeasurement(hitPtr->localPosition());
267  // Add APE manually to avoid that the hit error might be smaller than tsos error:
268  // - hit local errors are always without APE,
269  // - the tsos errors include APE since they come from track fit.
270  const LocalError hitErr(this->hitErrorWithAPE(hitPtr));
271 
272  LocalError localMeasurementCov(hitErr.xx(), hitErr.xy(), hitErr.yy());
273  if (doPull) {
274  const LocalError tsosErr(tsos.localError().positionError());
275  // Should not be possible to become negative if all is correct - see above.
276  if (hitErr.xx() < tsosErr.xx() || hitErr.yy() < tsosErr.yy()) {
277  edm::LogError("Alignment") << "@SUB=DualKalmanTrajectory::fillMeasurementAndError2"
278  << "not OK in subdet " << hitPtr->geographicalId().subdetId()
279  << "\ns_x " << sqrt(hitErr.xx()) << " " << sqrt(tsosErr.xx())
280  << "\ns_xy " << hitErr.xy() << " " << tsosErr.xy()
281  << "\ns_y " << sqrt(hitErr.yy()) << " " << sqrt(tsosErr.yy());
282  return TrajectoryStateOnSurface(); // is invalid state
283  }
284  // cf. Blobel/Lohrmann, p. 236:
285  // But numerical stability? Should we return false if difference very small compared to values?
286  localMeasurementCov = LocalError(hitErr.xx() - tsosErr.xx(), // tsos puts correlation in,
287  hitErr.xy() - tsosErr.xy(), // even for 1D strip!
288  hitErr.yy() - tsosErr.yy());
289  }
290 
291  theMeasurements[nMeasPerHit*iHit] = localMeasurement.x();
292  theMeasurements[nMeasPerHit*iHit+1] = localMeasurement.y();
293  theMeasurementsCov[nMeasPerHit*iHit] [nMeasPerHit*iHit] = localMeasurementCov.xx();
294  theMeasurementsCov[nMeasPerHit*iHit] [nMeasPerHit*iHit+1] = localMeasurementCov.xy();
295  theMeasurementsCov[nMeasPerHit*iHit+1][nMeasPerHit*iHit+1] = localMeasurementCov.yy();
296  }
297 
298  return tsos;
299 }
300 
301 //-----------------------------------------------------------------------------------------------
303  const TrajectoryStateOnSurface &tsos,
304  unsigned int iHit)
305 {
306  // get the local coordinates of the reference trajectory
307  // (~copied from ReferenceTrajectory::fillTrajectoryPositions)
308  AlgebraicVector mixedLocalParams = asHepVector<5>(tsos.localParameters().mixedFormatVector());
309  const AlgebraicVector localPosition(projection * mixedLocalParams);
310 
311  theTrajectoryPositions[nMeasPerHit*iHit] = localPosition[0];
312  theTrajectoryPositions[nMeasPerHit*iHit+1] = localPosition[1];
313 }
314 
315 //-----------------------------------------------------------------------------------------------
317 {
318  if (hitPtr->det() && hitPtr->det()->alignmentPositionError()) {
320  const AlgebraicSymMatrix errMat(help.parError(hitPtr->localPositionError(), *(hitPtr->det())));
321  return LocalError(errMat[0][0], errMat[0][1], errMat[1][1]);
322  } else {
323  return hitPtr->localPositionError();
324  }
325 }
326 
327 //-----------------------------------------------------------------------------------------------
330 {
331  return asHepVector<5>( referenceTsos.localParameters().mixedFormatVector() );
332 }
const PropagationDirection oppositeDirection(const PropagationDirection propDir) const
void fillTrajectoryPositions(const AlgebraicMatrix &projection, const TrajectoryStateOnSurface &tsos, unsigned int iHit)
fill trajectoryPositions
int i
Definition: DBlmapReader.cc:9
TrajectoryStateOnSurface fillMeasurementAndError1(const TransientTrackingRecHit::ConstRecHitPointer &hitPtr, unsigned int iHit, const TrajectoryMeasurement &trajMeasurement)
helper for &#39;unbiased residual&#39; method (i.e. returns merged fwd/bwd states)
bool fillKalmanPart(const Trajectory::DataContainer &trajMeasurements, const std::vector< unsigned int > &recHitNums, bool startFirst, unsigned int iNextHit, int residualMethod)
Fill that part of data members that is different from DualReferenceTrajectory.
const LocalTrajectoryParameters & localParameters() const
virtual AlgebraicVector extractParameters(const TrajectoryStateOnSurface &referenceTsos) const
TrajectoryStateOnSurface forwardPredictedState() const
Access to forward predicted state (from fitter or builder)
static const unsigned int nMeasPerHit
const TransientTrackingRecHit::ConstRecHitContainer & recHits() const
ConstRecHitPointer recHit() const
PropagationDirection
TrajectoryStateOnSurface fillMeasurementAndError2(const TransientTrackingRecHit::ConstRecHitPointer &hitPtr, unsigned int iHit, const TrajectoryMeasurement &trajMeasurement, bool doPull)
LocalError positionError() const
TransientTrackingRecHit::ConstRecHitPointer ConstRecHitPointer
AlgebraicSymMatrix theTrajectoryPositionCov
std::vector< TrajectoryMeasurement > DataContainer
Definition: Trajectory.h:42
CLHEP::HepMatrix AlgebraicMatrix
T sqrt(T t)
Definition: SSEVec.h:28
TrajectoryStateOnSurface updatedState() const
const AlgebraicSymMatrix55 & matrix() const
const LocalTrajectoryError & localError() const
TransientTrackingRecHit::ConstRecHitContainer theRecHits
AlgebraicSymMatrix theMeasurementsCov
LocalError hitErrorWithAPE(const TransientTrackingRecHit::ConstRecHitPointer &hitPtr) const
local error including APE if APE is on
std::vector< ConstRecHitPointer > ConstRecHitContainer
CLHEP::HepVector AlgebraicVector
virtual bool construct(const Trajectory::DataContainer &trajMeasurements, const TrajectoryStateOnSurface &referenceTsos, const std::vector< unsigned int > &forwardRecHitNums, const std::vector< unsigned int > &backwardRecHitNums, double mass, MaterialEffects materialEffects, const PropagationDirection propDir, const MagneticField *magField, bool useBeamSpot, const reco::BeamSpot &beamSpot, int residualMethod)
calculate members
AlgebraicVector5 mixedFormatVector() const
CLHEP::HepSymMatrix AlgebraicSymMatrix
std::vector< TrajectoryStateOnSurface > theTsosVec
TransientTrackingRecHit::ConstRecHitContainer ConstRecHitContainer
tuple size
Write out results.
TrajectoryStateOnSurface backwardPredictedState() const
Access to backward predicted state (from smoother)
DualKalmanTrajectory(const Trajectory::DataContainer &trajMeasurements, const TrajectoryStateOnSurface &referenceTsos, const std::vector< unsigned int > &forwardRecHitNums, const std::vector< unsigned int > &backwardRecHitNums, const MagneticField *magField, MaterialEffects materialEffects, PropagationDirection propDir, double mass, bool useBeamSpot, const reco::BeamSpot &beamSpot, int residualMethod)
static AlgebraicSymMatrix parError(const LocalError &le, const GeomDet &det)