CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/Alignment/ReferenceTrajectories/src/ReferenceTrajectory.cc

Go to the documentation of this file.
00001 //  Author     : Gero Flucke (based on code by Edmund Widl replacing ORCA's TkReferenceTrack)
00002 //  date       : 2006/09/17
00003 //  last update: $Date: 2012/06/20 12:07:28 $
00004 //  by         : $Author: flucke $
00005 
00006 #include <memory>
00007 
00008 #include "Alignment/ReferenceTrajectories/interface/ReferenceTrajectory.h"
00009 
00010 #include "DataFormats/GeometrySurface/interface/Surface.h" 
00011 #include "DataFormats/GeometrySurface/interface/Plane.h"
00012 #include "DataFormats/GeometrySurface/interface/OpenBounds.h"
00013 
00014 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00015 
00016 #include "DataFormats/CLHEP/interface/AlgebraicObjects.h" 
00017 #include "DataFormats/GeometrySurface/interface/LocalError.h"
00018 #include "DataFormats/GeometryVector/interface/LocalPoint.h"
00019 #include "Geometry/CommonDetUnit/interface/GeomDet.h"
00020 
00021 #include "DataFormats/TrajectoryState/interface/LocalTrajectoryParameters.h"
00022 #include "DataFormats/TrackingRecHit/interface/KfComponentsHolder.h"
00023 
00024 #include "TrackingTools/AnalyticalJacobians/interface/AnalyticalCurvilinearJacobian.h"
00025 #include "TrackingTools/AnalyticalJacobians/interface/JacobianLocalToCurvilinear.h"
00026 #include "TrackingTools/AnalyticalJacobians/interface/JacobianCurvilinearToLocal.h"
00027 
00028 #include "TrackingTools/GeomPropagators/interface/AnalyticalPropagator.h"
00029 #include "TrackPropagation/RungeKutta/interface/RKTestPropagator.h"
00030 
00031 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00032 #include "TrackingTools/TrajectoryParametrization/interface/GlobalTrajectoryParameters.h"
00033 
00034 #include "TrackingTools/MaterialEffects/interface/MultipleScatteringUpdator.h"
00035 #include "TrackingTools/MaterialEffects/interface/EnergyLossUpdator.h"
00036 #include "TrackingTools/MaterialEffects/interface/CombinedMaterialEffectsUpdator.h"
00037 #include <TrackingTools/PatternTools/interface/TSCPBuilderNoMaterial.h>
00038 #include <TrackingTools/PatternTools/interface/TSCBLBuilderNoMaterial.h>
00039 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateClosestToPoint.h"
00040 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateClosestToBeamLine.h"
00041 
00042 #include "MagneticField/Engine/interface/MagneticField.h"
00043 
00044 #include "Alignment/ReferenceTrajectories/interface/BeamSpotTransientTrackingRecHit.h"
00045 #include "Alignment/ReferenceTrajectories/interface/BeamSpotGeomDet.h"
00046 
00047 //__________________________________________________________________________________
00048 
00049 ReferenceTrajectory::ReferenceTrajectory(const TrajectoryStateOnSurface &refTsos,
00050                                          const TransientTrackingRecHit::ConstRecHitContainer
00051                                          &recHits, bool hitsAreReverse,
00052                                          const MagneticField *magField, 
00053                                          MaterialEffects materialEffects,
00054                                          PropagationDirection propDir,
00055                                          double mass,
00056                                          bool useBeamSpot, const reco::BeamSpot &beamSpot) 
00057  : ReferenceTrajectoryBase( 
00058    (materialEffects >= brokenLinesCoarse) ? 1 : refTsos.localParameters().mixedFormatVector().kSize, 
00059    (useBeamSpot == true) ? recHits.size()+1 : recHits.size(),
00060    (materialEffects >= brokenLinesCoarse) ? 
00061        2*((useBeamSpot == true) ? recHits.size()+1 : recHits.size())   :
00062    ( (materialEffects == breakPoints) ? 2*((useBeamSpot == true) ? recHits.size()+1 : recHits.size())-2 : 0) , 
00063    (materialEffects >= brokenLinesCoarse) ? 
00064        2*((useBeamSpot == true) ? recHits.size()+1 : recHits.size())-4 : 
00065    ( (materialEffects == breakPoints) ? 2*((useBeamSpot == true) ? recHits.size()+1 : recHits.size())-2 : 0) )
00066 {
00067   // no check against magField == 0  
00068   theParameters = asHepVector<5>( refTsos.localParameters().mixedFormatVector() );
00069   
00070   if (hitsAreReverse) {
00071     TransientTrackingRecHit::ConstRecHitContainer fwdRecHits;
00072     fwdRecHits.reserve(recHits.size());
00073     for (TransientTrackingRecHit::ConstRecHitContainer::const_reverse_iterator it=recHits.rbegin();
00074          it != recHits.rend(); ++it) {
00075       fwdRecHits.push_back(*it);
00076     }
00077     theValidityFlag = this->construct(refTsos, fwdRecHits, mass, materialEffects,
00078                                       propDir, magField,
00079                                       useBeamSpot, beamSpot);
00080   } else {
00081     theValidityFlag = this->construct(refTsos, recHits, mass, materialEffects,
00082                                       propDir, magField,
00083                                       useBeamSpot, beamSpot);
00084   }
00085 }
00086 
00087 
00088 //__________________________________________________________________________________
00089 
00090 ReferenceTrajectory::ReferenceTrajectory( unsigned int nPar, unsigned int nHits,
00091                                           MaterialEffects materialEffects)
00092  : ReferenceTrajectoryBase( 
00093    (materialEffects >= brokenLinesCoarse) ? 1 : nPar, 
00094    nHits, 
00095    (materialEffects >= brokenLinesCoarse) ? 2*nHits   : ( (materialEffects == breakPoints) ? 2*nHits-2 : 0 ), 
00096    (materialEffects >= brokenLinesCoarse) ? 2*nHits-4 : ( (materialEffects == breakPoints) ? 2*nHits-2 : 0 ) )
00097 {}
00098 
00099 
00100 //__________________________________________________________________________________
00101 
00102 bool ReferenceTrajectory::construct(const TrajectoryStateOnSurface &refTsos, 
00103                                     const TransientTrackingRecHit::ConstRecHitContainer &recHits,
00104                                     double mass, MaterialEffects materialEffects,
00105                                     const PropagationDirection propDir,
00106                                     const MagneticField *magField,
00107                                     bool useBeamSpot,
00108                                     const reco::BeamSpot &beamSpot)
00109 {   
00110   TrajectoryStateOnSurface theRefTsos = refTsos;
00111 
00112   const SurfaceSide surfaceSide = this->surfaceSide(propDir);
00113   // auto_ptr to avoid memory leaks in case of not reaching delete at end of method:
00114   std::auto_ptr<MaterialEffectsUpdator> aMaterialEffectsUpdator
00115     (this->createUpdator(materialEffects, mass));
00116   if (!aMaterialEffectsUpdator.get()) return false; // empty auto_ptr
00117 
00118   AlgebraicMatrix                 fullJacobian(theParameters.num_row(), theParameters.num_row());
00119   std::vector<AlgebraicMatrix>    allJacobians; 
00120   allJacobians.reserve(theNumberOfHits);
00121 
00122   TransientTrackingRecHit::ConstRecHitPointer  previousHitPtr;
00123   TrajectoryStateOnSurface                     previousTsos;
00124   AlgebraicSymMatrix              previousChangeInCurvature(theParameters.num_row(), 1);
00125   std::vector<AlgebraicSymMatrix> allCurvatureChanges; 
00126   allCurvatureChanges.reserve(theNumberOfHits);
00127   
00128   const LocalTrajectoryError zeroErrors(0., 0., 0., 0., 0.);
00129 
00130   std::vector<AlgebraicMatrix> allProjections;
00131   allProjections.reserve(theNumberOfHits);
00132   std::vector<AlgebraicSymMatrix> allDeltaParameterCovs;
00133   allDeltaParameterCovs.reserve(theNumberOfHits);
00134 
00135   // CHK
00136   std::vector<AlgebraicMatrix> allLocalToCurv;
00137   allLocalToCurv.reserve(theNumberOfHits); 
00138   std::vector<double> allSteps;
00139   allSteps.reserve(theNumberOfHits); 
00140   std::vector<AlgebraicMatrix>    allCurvlinJacobians; 
00141   allCurvlinJacobians.reserve(theNumberOfHits);
00142   
00143   AlgebraicMatrix firstCurvlinJacobian(5, 5, 1);
00144   
00145   unsigned int iRow = 0;
00146 
00147   // local storage vector of all rechits (including rechit for beam spot in case it is used)
00148   TransientTrackingRecHit::ConstRecHitContainer allRecHits;
00149 
00150   if (useBeamSpot && propDir==alongMomentum) {
00151     
00152     GlobalPoint bs(beamSpot.x0(), beamSpot.y0(), beamSpot.z0());
00153     
00154     TrajectoryStateClosestToBeamLine tsctbl(TSCBLBuilderNoMaterial()(*(refTsos.freeState()), beamSpot));
00155     if (!tsctbl.isValid()) {
00156       edm::LogError("Alignment") << "@SUB=ReferenceTrajectory::construct" 
00157                                  << "TrajectoryStateClostestToBeamLine invalid. Skip track.";
00158       return false;
00159     }
00160 
00161     FreeTrajectoryState pcaFts = tsctbl.trackStateAtPCA();
00162     GlobalVector bd(beamSpot.dxdz(), beamSpot.dydz(), 1.0);
00163     
00164     //propagation FIXME: Should use same propagator everywhere...
00165     AnalyticalPropagator propagator(magField);
00166     std::pair< TrajectoryStateOnSurface, double > tsosWithPath =
00167       propagator.propagateWithPath(pcaFts, refTsos.surface());
00168     
00169     if (!tsosWithPath.first.isValid()) return false;
00170     
00171     GlobalVector momDir(pcaFts.momentum());
00172     GlobalVector perpDir(bd.cross(momDir));
00173     BoundPlane::RotationType rotation(perpDir, bd);
00174     
00175     BeamSpotGeomDet * bsGeom = new BeamSpotGeomDet(BoundPlane::build(bs, rotation, OpenBounds()));
00176 
00177     // There is also a constructor taking the magentic field. Use this one instead?
00178     theRefTsos = TrajectoryStateOnSurface(pcaFts, bsGeom->surface());
00179     
00180     TransientTrackingRecHit::ConstRecHitPointer bsRecHit = 
00181       new BeamSpotTransientTrackingRecHit(beamSpot,
00182                                           bsGeom,
00183                                           theRefTsos.freeState()->momentum().phi());
00184     allRecHits.push_back(bsRecHit);
00185 
00186   }
00187   
00188   // copy all rechits to the local storage vector
00189   TransientTrackingRecHit::ConstRecHitContainer::const_iterator itRecHit;
00190   for ( itRecHit = recHits.begin(); itRecHit != recHits.end(); ++itRecHit ) { 
00191     const TransientTrackingRecHit::ConstRecHitPointer &hitPtr = *itRecHit;
00192     allRecHits.push_back(hitPtr);
00193   }
00194 
00195   for ( itRecHit = allRecHits.begin(); itRecHit != allRecHits.end(); ++itRecHit ) { 
00196     
00197     const TransientTrackingRecHit::ConstRecHitPointer &hitPtr = *itRecHit;
00198     theRecHits.push_back(hitPtr);
00199 
00200     if (0 == iRow) {
00201 
00202       // compute the derivatives of the reference-track's parameters w.r.t. the initial ones
00203       // derivative of the initial reference-track parameters w.r.t. themselves is of course the identity 
00204       fullJacobian = AlgebraicMatrix(theParameters.num_row(), theParameters.num_row(), 1);
00205       allJacobians.push_back(fullJacobian);
00206       theTsosVec.push_back(theRefTsos);
00207       const JacobianLocalToCurvilinear startTrafo(hitPtr->det()->surface(), theRefTsos.localParameters(), *magField);
00208       const AlgebraicMatrix localToCurvilinear =  asHepMatrix<5>(startTrafo.jacobian());
00209       if (materialEffects <= breakPoints) {
00210          theInnerTrajectoryToCurvilinear = asHepMatrix<5>(startTrafo.jacobian());
00211          theInnerLocalToTrajectory = AlgebraicMatrix(5, 5, 1);
00212       }  
00213       allLocalToCurv.push_back(localToCurvilinear);
00214       allSteps.push_back(0.);
00215       allCurvlinJacobians.push_back(firstCurvlinJacobian);
00216 
00217     } else {
00218 
00219       AlgebraicMatrix nextJacobian;
00220       AlgebraicMatrix nextCurvlinJacobian;
00221       double nextStep = 0.;
00222       TrajectoryStateOnSurface nextTsos;
00223 
00224       if (!this->propagate(previousHitPtr->det()->surface(), previousTsos,
00225                            hitPtr->det()->surface(), nextTsos,
00226                            nextJacobian, nextCurvlinJacobian, nextStep, propDir, magField)) {
00227         return false; // stop if problem...// no delete aMaterialEffectsUpdator needed
00228       }
00229       
00230       allJacobians.push_back(nextJacobian);
00231       fullJacobian = nextJacobian * previousChangeInCurvature * fullJacobian;
00232       theTsosVec.push_back(nextTsos);
00233       
00234       const JacobianLocalToCurvilinear startTrafo(hitPtr->det()->surface(), nextTsos.localParameters(), *magField);
00235       const AlgebraicMatrix localToCurvilinear =  asHepMatrix<5>(startTrafo.jacobian());
00236       allLocalToCurv.push_back(localToCurvilinear);
00237       if (nextStep == 0.) { 
00238         edm::LogError("Alignment") << "@SUB=ReferenceTrajectory::construct"
00239                                    << "step 0. from id " << previousHitPtr->geographicalId()
00240                                    << " to " << hitPtr->det()->geographicalId() << ".";
00241         // brokenLinesFine will not work, brokenLinesCoarse combines close by layers
00242         if (materialEffects == brokenLinesFine) {
00243           edm::LogError("Alignment") << "@SUB=ReferenceTrajectory::construct" << "Skip track.";
00244           return false;
00245         }
00246       }
00247       allSteps.push_back(nextStep);
00248       allCurvlinJacobians.push_back(nextCurvlinJacobian);
00249 
00250     }
00251 
00252     // take material effects into account. since trajectory-state is constructed with errors equal zero,
00253     // the updated state contains only the uncertainties due to interactions in the current layer.
00254     const TrajectoryStateOnSurface tmpTsos(theTsosVec.back().localParameters(), zeroErrors,
00255                                            theTsosVec.back().surface(), magField, surfaceSide);
00256     const TrajectoryStateOnSurface updatedTsos = aMaterialEffectsUpdator->updateState(tmpTsos, propDir);
00257 
00258     if ( !updatedTsos.isValid() ) return false;// no delete aMaterialEffectsUpdator needed
00259     
00260     if ( theTsosVec.back().localParameters().charge() )
00261     {
00262       previousChangeInCurvature[0][0] = updatedTsos.localParameters().signedInverseMomentum() 
00263         / theTsosVec.back().localParameters().signedInverseMomentum();
00264     }
00265     
00266     // get multiple-scattering covariance-matrix
00267     allDeltaParameterCovs.push_back( asHepMatrix<5>(updatedTsos.localError().matrix()) );
00268     allCurvatureChanges.push_back(previousChangeInCurvature);
00269     
00270     // projection-matrix tsos-parameters -> measurement-coordinates
00271     allProjections.push_back(this->getHitProjectionMatrix(hitPtr));
00272     // set start-parameters for next propagation. trajectory-state without error
00273     //  - no error propagation needed here.
00274     previousHitPtr = hitPtr;
00275     previousTsos   = TrajectoryStateOnSurface(updatedTsos.globalParameters(),
00276                                               updatedTsos.surface(), surfaceSide);
00277     
00278     if (materialEffects < brokenLinesCoarse) {
00279       this->fillDerivatives(allProjections.back(), fullJacobian, iRow);
00280     }
00281 
00282     AlgebraicVector mixedLocalParams = asHepVector<5>(theTsosVec.back().localParameters().mixedFormatVector());
00283     this->fillTrajectoryPositions(allProjections.back(), mixedLocalParams, iRow);
00284     if ( useRecHit( hitPtr ) ) this->fillMeasurementAndError(hitPtr, iRow, updatedTsos);
00285 
00286     iRow += nMeasPerHit;
00287   } // end of loop on hits
00288 
00289   bool msOK = true;
00290   switch (materialEffects) {
00291   case none:
00292     break;
00293   case multipleScattering:
00294   case energyLoss:
00295   case combined:
00296     msOK = this->addMaterialEffectsCov(allJacobians, allProjections, allCurvatureChanges,
00297                                        allDeltaParameterCovs);
00298     break;
00299   case breakPoints:
00300     msOK = this->addMaterialEffectsBp(allJacobians, allProjections, allCurvatureChanges,
00301                                       allDeltaParameterCovs, allLocalToCurv);
00302     break;
00303   case brokenLinesCoarse:
00304     msOK = this->addMaterialEffectsBrl(allProjections, allDeltaParameterCovs, allLocalToCurv,
00305                                        allSteps, refTsos.globalParameters());
00306     break;
00307   case brokenLinesFine:
00308     msOK = this->addMaterialEffectsBrl(allCurvlinJacobians, allProjections, allCurvatureChanges,
00309                                        allDeltaParameterCovs, allLocalToCurv, refTsos.globalParameters());
00310   }
00311   if (!msOK) return false;
00312  
00313   if (refTsos.hasError()) {
00314     AlgebraicSymMatrix parameterCov = asHepMatrix<5>(refTsos.localError().matrix());
00315     AlgebraicMatrix  parDeriv;
00316     if (theNumberOfVirtualPars>0) { 
00317       parDeriv = theDerivatives.sub( 1, nMeasPerHit*allJacobians.size(), 1, theParameters.num_row() ); 
00318     } else {
00319       parDeriv = theDerivatives; 
00320     }
00321     theTrajectoryPositionCov = parameterCov.similarity(parDeriv);
00322   } else {
00323     theTrajectoryPositionCov = AlgebraicSymMatrix(theDerivatives.num_row(), 1);
00324   }
00325 
00326   return true;
00327 }
00328 
00329 //__________________________________________________________________________________
00330 
00331 MaterialEffectsUpdator*
00332 ReferenceTrajectory::createUpdator(MaterialEffects materialEffects, double mass) const
00333 {
00334   switch (materialEffects) {
00335     // MultipleScatteringUpdator doesn't change the trajectory-state
00336     // during update and can therefore be used if material effects should be ignored:
00337   case none:
00338   case multipleScattering: 
00339     return new MultipleScatteringUpdator(mass);
00340   case energyLoss:
00341     return new EnergyLossUpdator(mass);
00342   case combined:
00343     return new CombinedMaterialEffectsUpdator(mass);
00344   case breakPoints:
00345     return new CombinedMaterialEffectsUpdator(mass);
00346   case brokenLinesCoarse:
00347   case brokenLinesFine:
00348     return new CombinedMaterialEffectsUpdator(mass);
00349 }
00350 
00351   return 0;
00352 }
00353 
00354 //__________________________________________________________________________________
00355 
00356 bool ReferenceTrajectory::propagate(const BoundPlane &previousSurface, const TrajectoryStateOnSurface &previousTsos,
00357                                     const BoundPlane &newSurface, TrajectoryStateOnSurface &newTsos, AlgebraicMatrix &newJacobian, 
00358                                     AlgebraicMatrix &newCurvlinJacobian, double &nextStep,
00359                                     const PropagationDirection propDir, const MagneticField *magField) const
00360 {
00361   // propagate to next layer
00365   //AnalyticalPropagator aPropagator(magField, propDir);
00366   // Hard coded RungeKutta instead Analytical (avoid bias in TEC), but
00367   // work around TrackPropagation/RungeKutta/interface/RKTestPropagator.h and
00368   // http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9
00369   RKTestPropagator bPropagator(magField, propDir); //double tolerance = 5.e-5)
00370   Propagator &aPropagator = bPropagator;
00371   const std::pair<TrajectoryStateOnSurface, double> tsosWithPath =
00372     aPropagator.propagateWithPath(previousTsos, newSurface);
00373 
00374   // stop if propagation wasn't successful
00375   if (!tsosWithPath.first.isValid()) return false;
00376   
00377   nextStep = tsosWithPath.second;
00378   // calculate derivative of reference-track parameters on the actual layer w.r.t. the ones
00379   // on the previous layer (both in global coordinates)
00380   const AnalyticalCurvilinearJacobian aJacobian(previousTsos.globalParameters(), 
00381                                                 tsosWithPath.first.globalPosition(),
00382                                                 tsosWithPath.first.globalMomentum(),
00383                                                 tsosWithPath.second);
00384   const AlgebraicMatrix curvilinearJacobian = asHepMatrix<5,5>(aJacobian.jacobian());
00385 
00386   // jacobian of the track parameters on the previous layer for local->global transformation
00387   const JacobianLocalToCurvilinear startTrafo(previousSurface, previousTsos.localParameters(), *magField);
00388   const AlgebraicMatrix localToCurvilinear = asHepMatrix<5>(startTrafo.jacobian());
00389     
00390   // jacobian of the track parameters on the actual layer for global->local transformation
00391   const JacobianCurvilinearToLocal endTrafo(newSurface, tsosWithPath.first.localParameters(), *magField);
00392   const AlgebraicMatrix curvilinearToLocal = asHepMatrix<5>(endTrafo.jacobian());
00393   
00394   // compute derivative of reference-track parameters on the actual layer w.r.t. the ones on
00395   // the previous layer (both in their local representation)
00396   newCurvlinJacobian = curvilinearJacobian;
00397   newJacobian = curvilinearToLocal * curvilinearJacobian * localToCurvilinear;
00398   newTsos     = tsosWithPath.first;
00399 
00400   return true;
00401 }
00402 
00403 //__________________________________________________________________________________
00404 
00405 void ReferenceTrajectory::fillMeasurementAndError(const TransientTrackingRecHit::ConstRecHitPointer &hitPtr,
00406                                                   unsigned int iRow,
00407                                                   const TrajectoryStateOnSurface &updatedTsos)
00408 {
00409   // get the measurements and their errors, use information updated with tsos if improving
00410   // (GF: Also for measurements or only for errors or do the former not change?)
00411   // GF 10/2008: I doubt that it makes sense to update the hit with the tsos here:
00412   //             That is an analytical extrapolation and not the best guess of the real 
00413   //             track state on the module, but the latter should be better to get the best
00414   //             hit uncertainty estimate!
00415   TransientTrackingRecHit::ConstRecHitPointer newHitPtr(hitPtr->canImproveWithTrack() ?
00416                                                         hitPtr->clone(updatedTsos) : hitPtr);
00417 
00418   const LocalPoint localMeasurement    = newHitPtr->localPosition();
00419   const LocalError localMeasurementCov = newHitPtr->localPositionError();
00420   
00421   theMeasurements[iRow]   = localMeasurement.x();
00422   theMeasurements[iRow+1] = localMeasurement.y();
00423   theMeasurementsCov[iRow][iRow]     = localMeasurementCov.xx();
00424   theMeasurementsCov[iRow][iRow+1]   = localMeasurementCov.xy();
00425   theMeasurementsCov[iRow+1][iRow+1] = localMeasurementCov.yy();
00426   // GF: Should be a loop once the hit dimension is not hardcoded as nMeasPerHit (to be checked):
00427   // for (int i = 0; i < hitPtr->dimension(); ++i) {
00428   //   theMeasurements[iRow+i]   = hitPtr->parameters()[i]; // fixme: parameters() is by value!
00429   //   for (int j = i; j < hitPtr->dimension(); ++j) {
00430   //     theMeasurementsCov[iRow+i][iRow+j] = hitPtr->parametersError()[i][j];
00431   //   }
00432   // }
00433 }
00434 
00435 //__________________________________________________________________________________
00436 
00437 void ReferenceTrajectory::fillDerivatives(const AlgebraicMatrix &projection,
00438                                           const AlgebraicMatrix &fullJacobian,
00439                                           unsigned int iRow)
00440 {
00441   // derivatives of the local coordinates of the reference track w.r.t. to the inital track-parameters
00442   const AlgebraicMatrix projectedJacobian(projection * fullJacobian);
00443   for (int i = 0; i < parameters().num_row(); ++i) {
00444     theDerivatives[iRow  ][i] = projectedJacobian[0][i];
00445     theDerivatives[iRow+1][i] = projectedJacobian[1][i];
00446     // GF: Should be a loop once the hit dimension is not hardcoded as nMeasPerHit (to be checked):
00447     // for (int j = 0; j < projection.num_col(); ++j) {
00448     //   theDerivatives[iRow+j][i] = projectedJacobian[j][i];
00449     // }
00450   }
00451 }
00452 
00453 //__________________________________________________________________________________
00454 
00455 void ReferenceTrajectory::fillTrajectoryPositions(const AlgebraicMatrix &projection, 
00456                                                   const AlgebraicVector &mixedLocalParams, 
00457                                                   unsigned int iRow)
00458 {
00459   // get the local coordinates of the reference trajectory
00460   const AlgebraicVector localPosition(projection * mixedLocalParams);
00461   theTrajectoryPositions[iRow] = localPosition[0];
00462   theTrajectoryPositions[iRow+1] = localPosition[1];
00463   // GF: Should be a loop once the hit dimension is not hardcoded as nMeasPerHit (to be checked):
00464   // for (int j = 0; j < projection.num_col(); ++j) {
00465   //   theTrajectoryPositions[iRow+j] = localPosition[j];
00466   // }
00467 }
00468 
00469 //__________________________________________________________________________________
00470 
00471 bool ReferenceTrajectory::addMaterialEffectsCov(const std::vector<AlgebraicMatrix> &allJacobians, 
00472                                                 const std::vector<AlgebraicMatrix> &allProjections,
00473                                                 const std::vector<AlgebraicSymMatrix> &allCurvatureChanges,
00474                                                 const std::vector<AlgebraicSymMatrix> &allDeltaParameterCovs)
00475 {
00476   // the uncertainty due to multiple scattering is 'transferred' to the error matrix of the hits
00477 
00478   // GF: Needs update once hit dimension is not hardcoded as nMeasPerHit!
00479 
00480   AlgebraicSymMatrix materialEffectsCov(nMeasPerHit * allJacobians.size(), 0);
00481 
00482   // additional covariance-matrix of the measurements due to material-effects (single measurement)
00483   AlgebraicSymMatrix deltaMaterialEffectsCov;
00484 
00485   // additional covariance-matrix of the parameters due to material-effects
00486   AlgebraicSymMatrix paramMaterialEffectsCov(allDeltaParameterCovs[0]); //initialization
00487   // error-propagation to state after energy loss
00488   //GFback  paramMaterialEffectsCov = paramMaterialEffectsCov.similarity(allCurvatureChanges[0]);
00489 
00490   AlgebraicMatrix tempParameterCov;
00491   AlgebraicMatrix tempMeasurementCov;
00492 
00493   for (unsigned int k = 1; k < allJacobians.size(); ++k) {
00494     // error-propagation to next layer
00495     paramMaterialEffectsCov = paramMaterialEffectsCov.similarity(allJacobians[k]);
00496 
00497     // get dependences for the measurements
00498     deltaMaterialEffectsCov = paramMaterialEffectsCov.similarity(allProjections[k]);
00499     materialEffectsCov[nMeasPerHit*k  ][nMeasPerHit*k  ] = deltaMaterialEffectsCov[0][0];
00500     materialEffectsCov[nMeasPerHit*k  ][nMeasPerHit*k+1] = deltaMaterialEffectsCov[0][1];
00501     materialEffectsCov[nMeasPerHit*k+1][nMeasPerHit*k  ] = deltaMaterialEffectsCov[1][0];
00502     materialEffectsCov[nMeasPerHit*k+1][nMeasPerHit*k+1] = deltaMaterialEffectsCov[1][1];
00503 
00504     // GFback add uncertainties for the following layers due to scattering at this layer
00505     paramMaterialEffectsCov += allDeltaParameterCovs[k];
00506     // end GFback
00507     tempParameterCov = paramMaterialEffectsCov;
00508 
00509     // compute "inter-layer-dependencies"
00510     for (unsigned int l = k+1; l < allJacobians.size(); ++l) {
00511       tempParameterCov   = allJacobians[l]   * allCurvatureChanges[l] * tempParameterCov;
00512       tempMeasurementCov = allProjections[l] * tempParameterCov       * allProjections[k].T();
00513 
00514       materialEffectsCov[nMeasPerHit*l][nMeasPerHit*k] = tempMeasurementCov[0][0];
00515       materialEffectsCov[nMeasPerHit*k][nMeasPerHit*l] = tempMeasurementCov[0][0];
00516 
00517       materialEffectsCov[nMeasPerHit*l][nMeasPerHit*k+1] = tempMeasurementCov[0][1];
00518       materialEffectsCov[nMeasPerHit*k+1][nMeasPerHit*l] = tempMeasurementCov[0][1];
00519 
00520       materialEffectsCov[nMeasPerHit*l+1][nMeasPerHit*k] = tempMeasurementCov[1][0];
00521       materialEffectsCov[nMeasPerHit*k][nMeasPerHit*l+1] = tempMeasurementCov[1][0];
00522 
00523       materialEffectsCov[nMeasPerHit*l+1][nMeasPerHit*k+1] = tempMeasurementCov[1][1];
00524       materialEffectsCov[nMeasPerHit*k+1][nMeasPerHit*l+1] = tempMeasurementCov[1][1];
00525     } 
00526     // add uncertainties for the following layers due to scattering at this layer
00527     // GFback paramMaterialEffectsCov += allDeltaParameterCovs[k];    
00528     // error-propagation to state after energy loss
00529     paramMaterialEffectsCov = paramMaterialEffectsCov.similarity(allCurvatureChanges[k]);
00530      
00531   }
00532   theMeasurementsCov += materialEffectsCov;
00533 
00534   return true; // cannot fail
00535 }
00536 
00537 //__________________________________________________________________________________
00538 
00539 bool ReferenceTrajectory::addMaterialEffectsBp(const std::vector<AlgebraicMatrix> &allJacobians, 
00540                                                const std::vector<AlgebraicMatrix> &allProjections,
00541                                                const std::vector<AlgebraicSymMatrix> &allCurvatureChanges,
00542                                                const std::vector<AlgebraicSymMatrix> &allDeltaParameterCovs,
00543                                                const std::vector<AlgebraicMatrix> &allLocalToCurv)
00544 {
00545 //CHK: add material effects using break points
00546   int offsetPar = theNumberOfPars; 
00547   int offsetMeas = nMeasPerHit * allJacobians.size();
00548   int ierr = 0; 
00549 
00550   AlgebraicMatrix tempJacobian;
00551   AlgebraicMatrix MSprojection(2,5);
00552   MSprojection[0][1] = 1;
00553   MSprojection[1][2] = 1;
00554   AlgebraicSymMatrix tempMSCov; 
00555   AlgebraicSymMatrix tempMSCovProj;
00556   AlgebraicMatrix tempMSJacProj;   
00557 
00558   for (unsigned int k = 1; k < allJacobians.size(); ++k) {
00559 // CHK 
00560     int kbp = k-1;
00561     tempJacobian = allJacobians[k] * allCurvatureChanges[k];
00562     tempMSCov = allDeltaParameterCovs[k-1].similarity(allLocalToCurv[k-1]);
00563     tempMSCovProj = tempMSCov.similarity(MSprojection);
00564     theMeasurementsCov[offsetMeas+nMeasPerHit*kbp  ][offsetMeas+nMeasPerHit*kbp  ] = tempMSCovProj[0][0];
00565     theMeasurementsCov[offsetMeas+nMeasPerHit*kbp+1][offsetMeas+nMeasPerHit*kbp+1]=  tempMSCovProj[1][1];
00566     theDerivatives[offsetMeas+nMeasPerHit*kbp  ][offsetPar+2*kbp  ] = 1.0;
00567     theDerivatives[offsetMeas+nMeasPerHit*kbp+1][offsetPar+2*kbp+1] = 1.0 ; 
00568 
00569     tempMSJacProj = (allProjections[k] * ( tempJacobian * allLocalToCurv[k-1].inverse(ierr) )) * MSprojection.T();
00570     if (ierr) {
00571       edm::LogError("Alignment") << "@SUB=ReferenceTrajectory::addMaterialEffectsBp"
00572                                  << "Inversion 1 for break points failed: " << ierr;
00573       return false;
00574     }
00575     theDerivatives[nMeasPerHit*k  ][offsetPar+2*kbp  ] =  tempMSJacProj[0][0];  
00576     theDerivatives[nMeasPerHit*k  ][offsetPar+2*kbp+1] =  tempMSJacProj[0][1]; 
00577     theDerivatives[nMeasPerHit*k+1][offsetPar+2*kbp  ] =  tempMSJacProj[1][0];  
00578     theDerivatives[nMeasPerHit*k+1][offsetPar+2*kbp+1] =  tempMSJacProj[1][1];
00579               
00580     for (unsigned int l = k+1; l < allJacobians.size(); ++l) {
00581 // CHK    
00582       int kbp = k-1;
00583       tempJacobian = allJacobians[l] * allCurvatureChanges[l] * tempJacobian; 
00584       tempMSJacProj = (allProjections[l] * ( tempJacobian * allLocalToCurv[k-1].inverse(ierr) )) * MSprojection.T();
00585       if (ierr) {
00586         edm::LogError("Alignment") << "@SUB=ReferenceTrajectory::addMaterialEffectsBp"
00587                                    << "Inversion 2 for break points failed: " << ierr;
00588         return false;
00589       }
00590       theDerivatives[nMeasPerHit*l  ][offsetPar+2*kbp  ] =  tempMSJacProj[0][0];  
00591       theDerivatives[nMeasPerHit*l  ][offsetPar+2*kbp+1] =  tempMSJacProj[0][1]; 
00592       theDerivatives[nMeasPerHit*l+1][offsetPar+2*kbp  ] =  tempMSJacProj[1][0];  
00593       theDerivatives[nMeasPerHit*l+1][offsetPar+2*kbp+1] =  tempMSJacProj[1][1]; 
00594 
00595     }
00596 
00597   }
00598 
00599   return true;
00600 }
00601 
00602 //__________________________________________________________________________________
00603 
00604 bool ReferenceTrajectory::addMaterialEffectsBrl(const std::vector<AlgebraicMatrix> &allCurvlinJacobians, 
00605                                                 const std::vector<AlgebraicMatrix> &allProjections,
00606                                                 const std::vector<AlgebraicSymMatrix> &allCurvatureChanges,
00607                                                 const std::vector<AlgebraicSymMatrix> &allDeltaParameterCovs,
00608                                                 const std::vector<AlgebraicMatrix> &allLocalToCurv,
00609                                                 const GlobalTrajectoryParameters &gtp)
00610 {
00611 //CHK: add material effects using broken lines
00612 //fine: use exact Jacobians, all detectors  
00613 //broken lines: pair of offsets (u1,u2) = (xt,yt) (in curvilinear frame (q/p,lambda,phi,xt,yt)) at each layer
00614 //              scattering angles (alpha1,alpha2) = (cosLambda*dPhi, dLambda) (cosLambda cancels in Chi2)
00615 //              DU' = (dU'/dU)*DU + (dU'/dAlpha)*DAlpha + (dU'/dQbyp)*DQbyp (propagation of U)
00616 //                  = J*DU + S*DAlpha + d*DQbyp
00617 //           => DAlpha = S^-1 (DU' - J*DU - d*DQbyp)
00618 
00619   int offsetPar = theNumberOfPars;
00620   int offsetMeas = nMeasPerHit*allCurvlinJacobians.size();
00621   int ierr = 0;
00622 
00623   GlobalVector p = gtp.momentum();
00624   double cosLambda = sqrt((p.x()*p.x()+p.y()*p.y())/(p.x()*p.x()+p.y()*p.y()+p.z()*p.z()));
00625 
00626 // transformations Curvilinear <-> BrokenLines
00627   AlgebraicMatrix QbypToCurv(5,1);   // dCurv/dQbyp
00628   QbypToCurv[0][0] = 1.;             // dQbyp/dQbyp
00629   AlgebraicMatrix AngleToCurv(5,2);  // dCurv/dAlpha
00630   AngleToCurv[1][1] = 1.;            // dlambda/dalpha2
00631   AngleToCurv[2][0] = 1./cosLambda;  // dphi/dalpha1
00632   AlgebraicMatrix CurvToAngle(2,5);  // dAlpha/dCurv
00633   CurvToAngle[1][1] = 1.;            // dalpha2/dlambda
00634   CurvToAngle[0][2] = cosLambda;     // dalpha1/dphi
00635   AlgebraicMatrix OffsetToCurv(5,2); // dCurv/dU
00636   OffsetToCurv[3][0] = 1.;           // dxt/du1
00637   OffsetToCurv[4][1] = 1.;           // dyt/du2
00638   AlgebraicMatrix CurvToOffset(2,5); // dU/dCurv
00639   CurvToOffset[0][3] = 1.;           // du1/dxt
00640   CurvToOffset[1][4] = 1.;           // du2/dyt
00641 
00642 // transformations  trajectory to components (Qbyp, U1, U2)
00643   AlgebraicMatrix TrajToQbyp(1,5);
00644   TrajToQbyp[0][0] = 1.;
00645   AlgebraicMatrix TrajToOff1(2,5);
00646   TrajToOff1[0][1] = 1.;
00647   TrajToOff1[1][2] = 1.;
00648   AlgebraicMatrix TrajToOff2(2,5);
00649   TrajToOff2[0][3] = 1.;
00650   TrajToOff2[1][4] = 1.;
00651 
00652   AlgebraicMatrix JacOffsetToAngleC, JacQbypToAngleC;
00653   AlgebraicMatrix JacCurvToOffsetL, JacOffsetToOffsetL, JacAngleToOffsetL, JacQbypToOffsetL, JacOffsetToAngleL;
00654   AlgebraicMatrix JacCurvToOffsetN, JacOffsetToOffsetN, JacAngleToOffsetN, JacQbypToOffsetN, JacOffsetToAngleN;
00655 
00656 // transformation from trajectory to curvilinear parameters
00657 
00658   JacCurvToOffsetN = CurvToOffset * allCurvlinJacobians[1]; // (dU'/dCurv') * (dCurv'/dCurv) @ 2nd point
00659   JacOffsetToOffsetN = JacCurvToOffsetN * OffsetToCurv; // J: (dU'/dU)     = (dU'/dCurv') * (dCurv'/dCurv) * (dCurv/dU)
00660   JacAngleToOffsetN  = JacCurvToOffsetN * AngleToCurv;  // S: (dU'/dAlpha) = (dU'/dCurv') * (dCurv'/dCurv) * (dCurv/dAlpha)
00661   JacQbypToOffsetN   = JacCurvToOffsetN * QbypToCurv;   // d: (dU'/dQbyp)  = (dU'/dCurv') * (dCurv'/dCurv) * (dCurv/dQbyp)
00662   JacOffsetToAngleN  = JacAngleToOffsetN.inverse(ierr); // W
00663   if (ierr) {
00664      edm::LogError("Alignment") << "@SUB=ReferenceTrajectory::addMaterialEffectsBrl"
00665                                 << "Inversion 1 for fine broken lines failed: " << ierr;
00666      return false;
00667   }
00668   JacOffsetToAngleC = -(JacOffsetToAngleN * JacOffsetToOffsetN); // (dAlpha/dU)
00669   JacQbypToAngleC   = -(JacOffsetToAngleN * JacQbypToOffsetN);   // (dAlpha/dQbyp)
00670   // (dAlpha/dTraj) = (dAlpha/dQbyp) * (dQbyp/dTraj) + (dAlpha/dU1) * (dU1/dTraj) + (dAlpha/dU2) * (dU2/dTraj)
00671   AlgebraicMatrix JacTrajToAngle = JacQbypToAngleC * TrajToQbyp + JacOffsetToAngleC * TrajToOff1 + JacOffsetToAngleN * TrajToOff2;
00672   // (dCurv/dTraj) = (dCurv/dQbyp) * (dQbyp/dTraj) + (dCurv/dAlpha) * (dAlpha/dTraj) + (dCurv/dU) * (dU/dTraj)
00673   theInnerTrajectoryToCurvilinear = QbypToCurv * TrajToQbyp + AngleToCurv * JacTrajToAngle + OffsetToCurv * TrajToOff1;
00674   theInnerLocalToTrajectory = theInnerTrajectoryToCurvilinear.inverse(ierr) * allLocalToCurv[0];
00675   if (ierr) {
00676     edm::LogError("Alignment") << "@SUB=ReferenceTrajectory::addMaterialEffectsBrl"
00677                                << "Inversion 2 for fine broken lines failed: " << ierr;
00678     return false;
00679   }
00680 
00681   AlgebraicMatrix tempJacobian(allCurvatureChanges[0]);
00682   AlgebraicSymMatrix tempMSCov;
00683   AlgebraicSymMatrix tempMSCovProj;
00684   AlgebraicMatrix tempJacL, tempJacN;
00685   AlgebraicMatrix JacOffsetToMeas;
00686 
00687 // measurements from hits  
00688   for (unsigned int k = 0; k < allCurvlinJacobians.size(); ++k) {
00689 //  (dMeas/dU) = (dMeas/dLoc) * (dLoc/dCurv) * (dCurv/dU)
00690     JacOffsetToMeas = (allProjections[k] * allLocalToCurv[k].inverse(ierr) ) * OffsetToCurv;
00691     if (ierr) {
00692        edm::LogError("Alignment") << "@SUB=ReferenceTrajectory::addMaterialEffectsBrl"
00693                                    << "Inversion 3 for fine broken lines failed: " << ierr;
00694        return false;
00695     }
00696     theDerivatives[nMeasPerHit*k  ][offsetPar+2*k  ] =  JacOffsetToMeas[0][0];
00697     theDerivatives[nMeasPerHit*k  ][offsetPar+2*k+1] =  JacOffsetToMeas[0][1];
00698     theDerivatives[nMeasPerHit*k+1][offsetPar+2*k  ] =  JacOffsetToMeas[1][0];
00699     theDerivatives[nMeasPerHit*k+1][offsetPar+2*k+1] =  JacOffsetToMeas[1][1];
00700   }
00701 
00702 // measurement of MS kink  
00703   for (unsigned int k = 1; k < allCurvlinJacobians.size()-1; ++k) {
00704 // CHK 
00705     int iMsMeas = k-1; 
00706     int l    = k-1; // last hit
00707     int n    = k+1; // next hit
00708 
00709 // amount of multiple scattering in layer k  (angular error perp to direction)  
00710     tempMSCov = allDeltaParameterCovs[k].similarity(allLocalToCurv[k]);
00711     tempMSCovProj = tempMSCov.similarity(CurvToAngle);
00712     theMeasurementsCov[offsetMeas+nMeasPerHit*iMsMeas  ][offsetMeas+nMeasPerHit*iMsMeas  ] = tempMSCovProj[1][1];
00713     theMeasurementsCov[offsetMeas+nMeasPerHit*iMsMeas+1][offsetMeas+nMeasPerHit*iMsMeas+1] = tempMSCovProj[0][0];
00714 
00715 // transformation matices for offsets ( l <- k -> n )
00716     tempJacL = allCurvlinJacobians[k] * tempJacobian;
00717     JacCurvToOffsetL = CurvToOffset * tempJacL.inverse(ierr); // (dU'/dCurv') * (dCurv'/dCurv) @ last point
00718 
00719     if (ierr) {
00720        edm::LogError("Alignment") << "@SUB=ReferenceTrajectory::addMaterialEffectsBrl"
00721                                    << "Inversion 4 for fine broken lines failed: " << ierr;
00722        return false;
00723     }
00724     JacOffsetToOffsetL = JacCurvToOffsetL * OffsetToCurv; // J-: (dU'/dU)     = (dU'/dCurv') * (dCurv'/dCurv) * (dCurv/dU)
00725     JacAngleToOffsetL  = JacCurvToOffsetL * AngleToCurv;  // S-: (dU'/dAlpha) = (dU'/dCurv') * (dCurv'/dCurv) * (dCurv/dAlpha)
00726     JacQbypToOffsetL   = JacCurvToOffsetL * QbypToCurv;   // d-: (dU'/dQbyp)  = (dU'/dCurv') * (dCurv'/dCurv) * (dCurv/dQbyp)
00727     JacOffsetToAngleL  =-JacAngleToOffsetL.inverse(ierr); // W-
00728     if (ierr) {
00729        edm::LogError("Alignment") << "@SUB=ReferenceTrajectory::addMaterialEffectsBrl"
00730                                    << "Inversion 5 for fine broken lines failed: " << ierr;
00731        return false;
00732     }
00733     tempJacobian = tempJacobian * allCurvatureChanges[k];
00734     tempJacN = allCurvlinJacobians[n] * tempJacobian;
00735     JacCurvToOffsetN = CurvToOffset * tempJacN; // (dU'/dCurv') * (dCurv'/dCurv) @ next point
00736     JacOffsetToOffsetN = JacCurvToOffsetN * OffsetToCurv; // J+: (dU'/dU)     = (dU'/dCurv') * (dCurv'/dCurv) * (dCurv/dU)
00737     JacAngleToOffsetN  = JacCurvToOffsetN * AngleToCurv;  // S+: (dU'/dAlpha) = (dU'/dCurv') * (dCurv'/dCurv) * (dCurv/dAlpha)
00738     JacQbypToOffsetN   = JacCurvToOffsetN * QbypToCurv;   // d+: (dU'/dQbyp)  = (dU'/dCurv') * (dCurv'/dCurv) * (dCurv/dQbyp)
00739     JacOffsetToAngleN  = JacAngleToOffsetN.inverse(ierr); // W+
00740     if (ierr) {
00741        edm::LogError("Alignment") << "@SUB=ReferenceTrajectory::addMaterialEffectsBrl"
00742                                    << "Inversion 6 for fine broken lines failed: " << ierr;
00743        return false;
00744     }
00745     JacOffsetToAngleC = -(JacOffsetToAngleL * JacOffsetToOffsetL + JacOffsetToAngleN * JacOffsetToOffsetN);
00746     JacQbypToAngleC   = -(JacOffsetToAngleL * JacQbypToOffsetL   + JacOffsetToAngleN * JacQbypToOffsetN);
00747 
00748     // bending    
00749     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas  ][              0] = JacQbypToAngleC[0][0];
00750     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas+1][              0] = JacQbypToAngleC[1][0];
00751     // last layer
00752     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas  ][offsetPar+2*l  ] = JacOffsetToAngleL[0][0];
00753     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas  ][offsetPar+2*l+1] = JacOffsetToAngleL[0][1];
00754     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas+1][offsetPar+2*l  ] = JacOffsetToAngleL[1][0];
00755     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas+1][offsetPar+2*l+1] = JacOffsetToAngleL[1][1];
00756     // current layer
00757     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas  ][offsetPar+2*k  ] = JacOffsetToAngleC[0][0];
00758     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas  ][offsetPar+2*k+1] = JacOffsetToAngleC[0][1];
00759     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas+1][offsetPar+2*k  ] = JacOffsetToAngleC[1][0];
00760     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas+1][offsetPar+2*k+1] = JacOffsetToAngleC[1][1];
00761 
00762     // next layer
00763     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas  ][offsetPar+2*n  ] = JacOffsetToAngleN[0][0];
00764     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas  ][offsetPar+2*n+1] = JacOffsetToAngleN[0][1];
00765     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas+1][offsetPar+2*n  ] = JacOffsetToAngleN[1][0];
00766     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas+1][offsetPar+2*n+1] = JacOffsetToAngleN[1][1];
00767 
00768   }
00769 
00770   return true;
00771 }
00772 
00773 //__________________________________________________________________________________
00774 
00775 bool ReferenceTrajectory::addMaterialEffectsBrl(const std::vector<AlgebraicMatrix> &allProjections,
00776                                                 const std::vector<AlgebraicSymMatrix> &allDeltaParameterCovs,
00777                                                 const std::vector<AlgebraicMatrix> &allLocalToCurv,
00778                                                 const std::vector<double> &allSteps,
00779                                                 const GlobalTrajectoryParameters &gtp,
00780                                                 const double minStep)
00781 {
00782 //CHK: add material effects using broken lines
00783 //BrokenLinesCoarse: combine close by detectors, 
00784 //                   use approximate Jacobians from Steps (limit Qbyp -> 0),
00785 //                   bending only in RPhi (B=(0,0,Bz)), no energy loss correction
00786 
00787   int offsetPar = theNumberOfPars; 
00788   int offsetMeas = nMeasPerHit*allSteps.size();
00789   int ierr = 0;
00790 
00791   GlobalVector p = gtp.momentum();
00792   double cosLambda = sqrt((p.x()*p.x()+p.y()*p.y())/(p.x()*p.x()+p.y()*p.y()+p.z()*p.z()));
00793   double bFac = -gtp.magneticFieldInInverseGeV(gtp.position()).mag();
00794 
00795   // transformation from trajectory to curvilinear parameters at refTsos
00796   double delta (1.0/allSteps[1]);    
00797   theInnerTrajectoryToCurvilinear[0][0] = 1;
00798   theInnerTrajectoryToCurvilinear[1][2] = -delta;  
00799   theInnerTrajectoryToCurvilinear[1][4] =  delta;    
00800   theInnerTrajectoryToCurvilinear[2][0] = -0.5*bFac/delta;
00801   theInnerTrajectoryToCurvilinear[2][1] = -delta/cosLambda;
00802   theInnerTrajectoryToCurvilinear[2][3] =  delta/cosLambda;
00803   theInnerTrajectoryToCurvilinear[3][1] = 1;
00804   theInnerTrajectoryToCurvilinear[4][2] = 1;
00805   theInnerLocalToTrajectory = theInnerTrajectoryToCurvilinear.inverse(ierr) * allLocalToCurv[0];
00806   if (ierr) {
00807     edm::LogError("Alignment") << "@SUB=ReferenceTrajectory::addMaterialEffectsBrl"
00808                                << "Inversion 1 for coarse broken lines failed: " << ierr;
00809     return false;
00810   }
00811 
00812   AlgebraicMatrix CurvToAngle(2,5);  // dAlpha/dCurv
00813   CurvToAngle[1][1] = 1.;            // dalpha2/dlambda
00814   CurvToAngle[0][2] = cosLambda;     // dalpha1/dphi
00815   AlgebraicMatrix OffsetToCurv(5,2); // dCurv/dU
00816   OffsetToCurv[3][0] = 1.;           // dxt/du1
00817   OffsetToCurv[4][1] = 1.;           // dyt/du2
00818 
00819   AlgebraicSymMatrix tempMSCov;
00820   AlgebraicSymMatrix tempMSCovProj;
00821   AlgebraicMatrix JacOffsetToMeas;
00822 
00823   // combine closeby detectors into single plane
00824   std::vector<unsigned int> first(allSteps.size());
00825   std::vector<unsigned int> last (allSteps.size());
00826   std::vector<unsigned int> plane(allSteps.size());
00827   std::vector<double> sPlane(allSteps.size());
00828   unsigned int nPlane = 0;
00829   double sTot = 0;
00830 
00831   for (unsigned int k = 1; k < allSteps.size(); ++k) {
00832     sTot += allSteps[k];
00833     if (fabs(allSteps[k])>minStep) { nPlane += 1; first[nPlane] = k; }
00834     last[nPlane] = k;
00835     plane[k] = nPlane;
00836     sPlane[nPlane] += sTot;
00837   }
00838   if (nPlane < 2) return false; // pathological cases: need at least 2 planes
00839 
00840   theNumberOfVirtualPars = 2*(nPlane+1);
00841   theNumberOfVirtualMeas = 2*(nPlane-1);// unsigned underflow for nPlane == 0...
00842   for (unsigned int k = 0; k <= nPlane; ++k) { sPlane[k] /= (double) (last[k]-first[k]+1); }
00843 
00844   // measurements from hits
00845   sTot = 0; 
00846   for (unsigned int k = 0; k < allSteps.size(); ++k) {
00847     sTot += allSteps[k];
00848 //  (dMeas/dU) = (dMeas/dLoc) * (dLoc/dCurv) * (dCurv/dU)
00849     JacOffsetToMeas = (allProjections[k] * allLocalToCurv[k].inverse(ierr) ) * OffsetToCurv;
00850     if (ierr) {
00851       edm::LogError("Alignment") << "@SUB=ReferenceTrajectory::addMaterialEffectsBrl"
00852                                  << "Inversion 2 for coarse broken lines failed: " << ierr;
00853       return false;
00854     }
00855 
00856     unsigned int iPlane = plane[k];
00857     if (last[iPlane] == first[iPlane])
00858     { // single plane
00859       theDerivatives[nMeasPerHit*k  ][offsetPar+2*iPlane  ] =  JacOffsetToMeas[0][0];
00860       theDerivatives[nMeasPerHit*k  ][offsetPar+2*iPlane+1] =  JacOffsetToMeas[0][1];
00861       theDerivatives[nMeasPerHit*k+1][offsetPar+2*iPlane  ] =  JacOffsetToMeas[1][0];
00862       theDerivatives[nMeasPerHit*k+1][offsetPar+2*iPlane+1] =  JacOffsetToMeas[1][1];
00863     } else
00864     { // combined plane: (linear) interpolation
00865       unsigned int jPlane; // neighbor plane for interpolation
00866       if (fabs(sTot) < fabs(sPlane[iPlane])) { jPlane = (iPlane>0) ? iPlane - 1 : 1; }
00867       else  { jPlane = (iPlane<nPlane) ? iPlane + 1 : nPlane -1 ;}
00868       // interpolation weights
00869       double sDiff = sPlane[iPlane] - sPlane[jPlane];
00870       double iFrac = (sTot - sPlane[jPlane]) / sDiff;
00871       double jFrac = 1.0 - iFrac;
00872       theDerivatives[nMeasPerHit*k  ][offsetPar+2*iPlane  ] =  JacOffsetToMeas[0][0]*iFrac;
00873       theDerivatives[nMeasPerHit*k  ][offsetPar+2*iPlane+1] =  JacOffsetToMeas[0][1]*iFrac;
00874       theDerivatives[nMeasPerHit*k+1][offsetPar+2*iPlane  ] =  JacOffsetToMeas[1][0]*iFrac;
00875       theDerivatives[nMeasPerHit*k+1][offsetPar+2*iPlane+1] =  JacOffsetToMeas[1][1]*iFrac;
00876       theDerivatives[nMeasPerHit*k  ][offsetPar+2*jPlane  ] =  JacOffsetToMeas[0][0]*jFrac;
00877       theDerivatives[nMeasPerHit*k  ][offsetPar+2*jPlane+1] =  JacOffsetToMeas[0][1]*jFrac;
00878       theDerivatives[nMeasPerHit*k+1][offsetPar+2*jPlane  ] =  JacOffsetToMeas[1][0]*jFrac;
00879       theDerivatives[nMeasPerHit*k+1][offsetPar+2*jPlane+1] =  JacOffsetToMeas[1][1]*jFrac;
00880       // 2nd order neglected
00881       // theDerivatives[nMeasPerHit*k  ][                   0] = -0.5*bFac*sDiff*iFrac*sDiff*jFrac*cosLambda;
00882     }
00883   }
00884 
00885 // measurement of MS kink
00886   for (unsigned int i = 1; i < nPlane; ++i) {
00887 // CHK 
00888     int iMsMeas = i-1;
00889     int l    = i-1; // last hit
00890     int n    = i+1; // next hit
00891 
00892 // amount of multiple scattering in plane k
00893     for (unsigned int k = first[i]; k <= last[i]; ++k) {
00894       tempMSCov = allDeltaParameterCovs[k].similarity(allLocalToCurv[k]);
00895       tempMSCovProj = tempMSCov.similarity(CurvToAngle);
00896       theMeasurementsCov[offsetMeas+nMeasPerHit*iMsMeas  ][offsetMeas+nMeasPerHit*iMsMeas  ] += tempMSCovProj[0][0];
00897       theMeasurementsCov[offsetMeas+nMeasPerHit*iMsMeas+1][offsetMeas+nMeasPerHit*iMsMeas+1] += tempMSCovProj[1][1];
00898     }
00899 // broken line measurements for layer k, correlations between both planes neglected
00900     double stepK = sPlane[i] - sPlane[l];
00901     double stepN = sPlane[n] - sPlane[i];
00902     double deltaK (1.0/stepK);
00903     double deltaN (1.0/stepN);
00904     // bending (only in RPhi)
00905     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas  ][              0] = -0.5*bFac*(stepK+stepN)*cosLambda;
00906     // last layer
00907     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas  ][offsetPar+2*l  ] = deltaK;
00908     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas+1][offsetPar+2*l+1] = deltaK;
00909     // current layer
00910     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas  ][offsetPar+2*i  ] = -(deltaK + deltaN);
00911     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas+1][offsetPar+2*i+1] = -(deltaK + deltaN);
00912     // next layer
00913     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas  ][offsetPar+2*n  ] = deltaN;
00914     theDerivatives[offsetMeas+nMeasPerHit*iMsMeas+1][offsetPar+2*n+1] = deltaN;
00915   }
00916 
00917   return true;
00918 }
00919 
00920 //__________________________________________________________________________________
00921 
00922 AlgebraicMatrix
00923 ReferenceTrajectory::getHitProjectionMatrix
00924 (const TransientTrackingRecHit::ConstRecHitPointer &hitPtr) const
00925 {
00926   if (this->useRecHit(hitPtr)) {
00927     // check which templated non-member function to call:
00928     switch (hitPtr->dimension()) {
00929     case 1:
00930       return getHitProjectionMatrixT<1>(hitPtr);
00931     case 2:
00932       return getHitProjectionMatrixT<2>(hitPtr);
00933     case 3:
00934       return getHitProjectionMatrixT<3>(hitPtr);
00935     case 4:
00936       return getHitProjectionMatrixT<4>(hitPtr);
00937     case 5:
00938       return getHitProjectionMatrixT<5>(hitPtr);
00939     default:
00940       throw cms::Exception("ReferenceTrajectory::getHitProjectionMatrix")
00941         << "Unexpected hit dimension: " << hitPtr->dimension() << "\n";
00942     }
00943   }
00944   // invalid or (to please compiler) unknown dimension
00945   return AlgebraicMatrix(2, 5, 0); // get size from ???
00946 }
00947 
00948 //__________________________________________________________________________________
00949 
00950 template<unsigned int N>
00951 AlgebraicMatrix 
00952 ReferenceTrajectory::getHitProjectionMatrixT
00953 (const TransientTrackingRecHit::ConstRecHitPointer &hitPtr) const
00954 {
00955   // define variables that will be used to setup the KfComponentsHolder
00956   // (their allocated memory is needed by 'hitPtr->getKfComponents(..)'
00957   // ProjectMatrix<double,5,N>  pf; // not needed
00958   typename AlgebraicROOTObject<N,5>::Matrix H; 
00959   typename AlgebraicROOTObject<N>::Vector r, rMeas; 
00960   typename AlgebraicROOTObject<N,N>::SymMatrix V, VMeas;
00961   // input for the holder - but dummy is OK here to just get the projection matrix:
00962   const AlgebraicVector5 dummyPars;
00963   const AlgebraicSymMatrix55 dummyErr;
00964 
00965   // setup the holder with the correct dimensions and get the values
00966   KfComponentsHolder holder;
00967   holder.setup<N>(&r, &V, &H, /*&pf,*/ &rMeas, &VMeas, dummyPars, dummyErr);
00968   hitPtr->getKfComponents(holder);
00969 
00970   return asHepMatrix<N,5>(holder.projection<N>());
00971 }
00972