17 #include "GaudiKernel/SmartDataPtr.h"
41 #include <ext/algorithm>
49 const std::string &
name,
52 , m_trackFitter(
"Trk::GlobalChi2Fitter/InDetTrackFitter")
54 , m_extrapolator(
"Trk::Extrapolator/AtlasExtrapolator")
56 , m_BSTrackSelector(
"")
57 , m_alignModuleTool(
"Trk::AlignModuleTool/AlignModuleTool")
58 , m_PVContainerName(
"PrimaryVertices")
59 , m_runOutlierRemoval(false)
60 , m_selectVertices(true)
62 , m_doTrkSelection (true)
63 , m_doBSTrackSelection(false)
64 , m_doAssociatedToPVSelection(true)
66 , m_compareMethod(
"compareAddress")
67 , m_doBeamspotConstraint(true)
68 , m_doPrimaryVertexConstraint(false)
69 , m_doFullVertexConstraint(false)
70 , m_doNormalRefit(true)
73 , m_storeFitMatrices(true)
74 , m_useSingleFitter(false)
75 , m_BSScalingFactor(1.)
76 , m_PVScalingFactor(1.)
79 , m_trackTypeCounter(
AlignTrack::NTrackTypes,0)
80 , m_nFailedNormalRefits(0)
81 , m_nFailedBSRefits(0)
82 , m_nFailedPVRefits(0)
84 declareInterface<IAlignTrackPreProcessor>(
this);
102 declareProperty(
"DoFullVertex",
m_doFullVertexConstraint ,
"Full 3D vertex constraint. Note DoPVConstraint needs to be set to true to use this option. If DoBSConstraint vertex position will be constrained to the BS" );
112 std::vector<std::string> defaultInterestedVertexContainers;
113 defaultInterestedVertexContainers.emplace_back(
"PrimaryVertices");
127 ATH_MSG_INFO(
"BeamspotVertexPreProcessor::initialize()");
141 return StatusCode::FAILURE;
149 return StatusCode::FAILURE;
157 return StatusCode::FAILURE;
165 return StatusCode::FAILURE;
176 msg(
MSG::FATAL) <<
"Requested BeamSpot track selection but Track Selector not configured"<<
endmsg;
177 return StatusCode::FAILURE;
181 return StatusCode::FAILURE;
190 return StatusCode::FAILURE;
196 return StatusCode::FAILURE;
201 ATH_MSG_INFO(
"************************************************************************");
203 ATH_MSG_INFO(
"* You have requested the Full Vertex Constraint option. *");
204 ATH_MSG_INFO(
"* It is your duty to assure that all detector elements *");
205 ATH_MSG_INFO(
"* used for track fitting are also loaded in the alignment framework!!! *");
207 ATH_MSG_INFO(
"* Also make sure the accurate track covariance matrix *");
208 ATH_MSG_INFO(
"* is returned by the GlobalChi2Fitter! *");
210 ATH_MSG_INFO(
"************************************************************************");
214 return StatusCode::SUCCESS;
222 if(!linkToTrackParticle)
return false;
229 if(
m_method.find(
"compareAddress") != std::string::npos){
235 if(
m_method.find(
"comparePerigee") != std::string::npos){
238 if(! (measPer1 && measPer2 ))
equal =
false;
240 float diff = std::abs(std::numeric_limits<float>::epsilon());
241 if( ( std::abs(measPer1->parameters()[
Trk::d0] - measPer2->parameters()[
Trk::d0]) >
diff)
242 || ( std::abs(measPer1->parameters()[
Trk::z0] - measPer2->parameters()[
Trk::z0]) >
diff)
258 ATH_MSG_DEBUG(
"this primary vertex has been rejected as type dummy");
262 ATH_MSG_WARNING(
" VERY STRANGE!!!, this primary vertex has been rejected as non-positive DoF "<< vtx->
numberDoF() <<
" the type of this vertex: "<< vtx->
vertexType() );
276 ATH_MSG_WARNING(
" VERY STRANGE!!! , the updated vertex has been rejected as non-positive DoF: "<< vtx->
numberDoF() <<
" the type of this vertex:"<< vtx->
vertexType() );
285 if ((vtx->covariancePosition())(0,0)<=0 ||
286 (vtx->covariancePosition())(1,1)<=0 ||
287 (vtx->covariancePosition())(2,2)<=0){
288 ATH_MSG_WARNING(
" VERY STRANGE!!! , this updated vertex has been rejected as negative diagonal error matrix ");
303 for ( ; vtxIter != vtxEnd && (*vtxIter)->vertexType() == 1; ++vtxIter ){
316 std::vector<VxTrackAtVertex > vertexTracks =
vertex->vxTrackAtVertex();
319 std::vector<VxTrackAtVertex >::const_iterator iVxTrackBegin = vertexTracks.begin();
320 std::vector<VxTrackAtVertex >::const_iterator iVxTrackEnd = vertexTracks.end();
322 std::vector<VxTrackAtVertex>::const_iterator findResult = std::find_if(iVxTrackBegin, iVxTrackEnd, thisCompare);
324 return findResult != iVxTrackEnd;
337 for(; strs_iter != strs_end; ++strs_iter){
339 if (
evtStore()->contains<xAOD::VertexContainer>(*strs_iter)) {
341 ATH_MSG_DEBUG (
"Could not retrieve xAOD vertex container with key "+(*strs_iter));
349 for(; vtxIter != vtxEnd; ++vtxIter){
351 ATH_MSG_DEBUG(
"this vertex did not pass the primary vertex selection...");
355 if ((*vtxIter)->vxTrackAtVertexAvailable()){
357 std::vector<VxTrackAtVertex> vtxTracks = (*vtxIter)->vxTrackAtVertex();
361 ATH_MSG_DEBUG(
"this vertex did not pass the vxTrackAtVertexAvailable() call...");
377 std::vector< std::pair< const xAOD::Vertex*, std::vector<VxTrackAtVertex> > >::const_iterator iter =
m_allTracksVector.begin();
378 std::vector< std::pair< const xAOD::Vertex*, std::vector<VxTrackAtVertex> > >::const_iterator iterEnd =
m_allTracksVector.end();
380 for(; iter != iterEnd; ++iter){
381 std::pair< const xAOD::Vertex*, std::vector<VxTrackAtVertex> > thisPair = *iter;
390 if(findResult != iVxTrackEnd){
392 findVxCandidate = thisPair.first;
401 return findVxCandidate;
407 const EventContext& ctx = Gaudi::Hive::currentContext();
416 if (!(
nullptr==findVtx) ) {
435 ATH_MSG_DEBUG(
" updated Vertex by KalmanVertexUpdator: "<<updatedVtx);
441 const Perigee* perigee =
nullptr;
442 std::unique_ptr<const Trk::TrackParameters>
tmp =
446 perigee =
static_cast<const Perigee*
> (
tmp.release());
449 const Perigee * trackPerigee =
track->perigeeParameters();
451 perigee = trackPerigee->
clone();
456 if (updatedVtx!= tmpVtx)
delete updatedVtx;
468 double ptInv = 1./perigee->momentum().perp();
469 Jacobian(0,0) = -ptInv*perigee->momentum().y();
470 Jacobian(0,1) = ptInv*perigee->momentum().x();
473 ATH_MSG_DEBUG(
" Jacobian matrix from Cartesian to Perigee: "<< Jacobian);
475 AmgSymMatrix(3) vtxCov = updatedVtx->covariancePosition();
485 tmpCov(0,0) = 1.e-10 ;
486 tmpCov(1,1) = 1.e-10;
487 tmpCov(2,2) = 1.e-10;
488 errorMatrix =
Amg::MatrixX( tmpCov.similarity(Jacobian) );
490 errorMatrix =
Amg::MatrixX( vtxCov.similarity(Jacobian) );
498 if (tmpVtx != updatedVtx){
508 vot =
new VertexOnTrack(std::move(localParams), std::move(errorMatrix), surface);
509 ATH_MSG_DEBUG(
"the VertexOnTrack created from vertex: "<<*vot);
520 const EventContext& ctx = Gaudi::Hive::currentContext();
525 float beamSpotX = bpos.x();
526 float beamSpotY = bpos.y();
527 float beamSpotZ = bpos.z();
528 float beamTiltX = beamSpotHandle->beamTilt(0);
529 float beamTiltY = beamSpotHandle->beamTilt(1);
538 float beamX = beamSpotX +
std::tan(beamTiltX) * (
z0-beamSpotZ);
539 float beamY = beamSpotY +
std::tan(beamTiltY) * (
z0-beamSpotZ);
541 ATH_MSG_DEBUG(
"constructing beam point (x,y,z) = ( "<<beamX<<
" , "<<beamY<<
" , "<<
z0<<
" )");
542 std::optional<PerigeeSurface> surface = std::nullopt;
548 beamSpotCov.setZero();
549 beamSpotCov(0,0) = beamSigmaX * beamSigmaX;
550 beamSpotCov(1,1) = beamSigmaY * beamSigmaY;
555 surface.emplace(globPos);
562 const Perigee* perigee =
nullptr;
563 std::unique_ptr<const Trk::TrackParameters>
tmp =
567 perigee =
static_cast<const Perigee*
>(
tmp.release());
571 const Perigee * trackPerigee =
track->perigeeParameters();
573 perigee = trackPerigee->
clone();
582 Eigen::Matrix<double,1,2> jacobian;
585 double ptInv = 1./perigee->momentum().perp();
586 jacobian(0,0) = -ptInv * perigee->momentum().y();
587 jacobian(0,1) = ptInv * perigee->momentum().x();
590 errorMatrix =
Amg::MatrixX( jacobian*(beamSpotCov*jacobian.transpose()));
591 if( errorMatrix.cols() != 1 )
597 std::move(errorMatrix),
603 ATH_MSG_DEBUG(
" the VertexOnTrack objects created from BeamSpot are " << *vot);
615 float beamSpotX = bpos.x();
616 float beamSpotY = bpos.y();
617 float beamSpotZ = bpos.z();
618 float beamTiltX = beamSpotHandle->beamTilt(0);
619 float beamTiltY = beamSpotHandle->beamTilt(1);
625 float z0 =
b->originalPosition()->z();
626 (*v)(0) = beamSpotX +
std::tan(beamTiltX) * (
z0-beamSpotZ);
627 (*v)(1) = beamSpotY +
std::tan(beamTiltY) * (
z0-beamSpotZ);
629 (*q)(0,0) = beamSigmaX*beamSigmaX;
630 (*q)(1,1) = beamSigmaY*beamSigmaY;
631 (*q)(2,2) = beamSigmaZ*beamSigmaZ;
633 ATH_MSG_DEBUG(
"VTX constraint point (x,y,z) = ( "<< (*
v)[0] <<
" , "<< (*
v)[1] <<
" , "<< (*
v)[2] <<
" )");
634 ATH_MSG_DEBUG(
"VTX constraint size (x,y,z) = ( "<< beamSigmaX <<
" , "<< beamSigmaY <<
" , "<< beamSigmaZ <<
" )");
639 ToolHandle<Trk::IGlobalTrackFitter>&
fitter,
644 const EventContext& ctx = Gaudi::Hive::currentContext();
645 const Track* newTrack =
nullptr;
649 std::vector<const MeasurementBase *> measurementCollection;
650 measurementCollection.push_back(vot);
654 for ( ; imeas != imeas_end ; ++imeas) measurementCollection.push_back(*imeas);
659 ATH_MSG_DEBUG(
" Track reference surface will be: " << surface);
663 newTrack = (
fitter->
fit(ctx, measurementCollection,
668 measurementCollection, *(
track->trackParameters()->front()),
681 bool haveVertex =
false;
692 ATH_MSG_DEBUG(
"Primary vertex collection for this event has "<<vertices->
size()<<
" vertices");
693 if (vertices->
size()<2){
694 ATH_MSG_DEBUG(
"Only Dummy vertex present, no Primary vertices.");
701 ATH_MSG_DEBUG(
"Could not retrieve primary vertex collection from the StoreGate");
716 const double qoverP = perigee->parameters()[
Trk::qOverP] * 1000.;
724 ATH_MSG_DEBUG(
"this track passes the beamspot track selection, will do beamspot constraint on it ");
734 const Track* newTrack =
nullptr;
752 if( !vot )
ATH_MSG_INFO(
"VoT not found for this track! ");
753 if( !vtx )
ATH_MSG_INFO(
"VTX pointer not found for this track! ");
760 msg(MSG::ERROR)<<
"VertexConstraint track refit failed! "<<
endmsg;
773 msg(MSG::ERROR)<<
"BSConstraint track refit failed! "<<
endmsg;
805 msg(MSG::ERROR)<<
"Normal track refit failed! "<<
endmsg;
843 if( (ivtx->originalVertex())==vtx ) {
853 ATH_MSG_DEBUG(
" The Beam Spot constraint will be added to the vertex.." );
857 (qtemp)(2,2) = 1000000.0;
882 ATH_MSG_DEBUG(
"BeamspotVertexPreProcessor::processTrackCollection()");
884 if( !tracks || (tracks->
empty()) )
904 for ( ; itr != itr_end; ++itr, ++
index) {
908 if (not
track)
continue;
925 if( !(alignTrack->
getVtx()) ) {
934 ATH_MSG_DEBUG(
"No Track refit for track " <<
index <<
" --> building new aligntrack");
940 if (alignTrack) newTrks->
push_back(alignTrack);
943 ATH_MSG_INFO(
"Processing of input track collection completed (size: " << tracks->
size() <<
"). Size of the alignTrack collection: " << newTrks->
size() );
945 if (newTrks->
empty()) {
962 ATH_MSG_DEBUG(
"This alignTrack is not associated to any vertex -> return. ");
970 const std::vector<AlignModuleDerivatives> * ptrDerivs = alignTrack->
derivatives();
973 if (!ptrWeights || !ptrWeightsFD || !ptrResiduals || !ptrDerivs) {
974 msg(MSG::ERROR)<<
"something missing from alignTrack!"<<
endmsg;
975 if (!ptrWeights)
msg(MSG::ERROR)<<
"no weights!"<<
endmsg;
976 if (!ptrWeightsFD)
msg(MSG::ERROR)<<
"no weights for first deriv!"<<
endmsg;
977 if (!ptrResiduals)
msg(MSG::ERROR)<<
"no residuals!"<<
endmsg;
978 if (!ptrDerivs)
msg(MSG::ERROR)<<
"no derivatives!"<<
endmsg;
984 std::vector<AlignModuleDerivatives> derivatives = *ptrDerivs;
993 ATH_MSG_DEBUG(
"accumulateVTX: The derivative vector size is " << derivatives.size() );
997 std::vector<Amg::VectorX*> allDerivatives[3];
1000 const int WSize(
weights.cols());
1002 std::vector<AlignModuleVertexDerivatives> derivX;
1004 for ( ; derivIt!=derivIt_end ; ++derivIt) {
1013 std::vector<Amg::VectorX>& deriv_vec = derivIt->second;
1014 ATH_MSG_VERBOSE(
"accumulateVTX: The deriv_vec size is " << deriv_vec.size() );
1016 int nModPars = alignPars->
size();
1017 if ((nModPars+3) != (
int)deriv_vec.size() ) {
1018 ATH_MSG_ERROR(
"accumulateVTX: Derivatives w.r.t. the vertex seem to be missing");
1021 for (
int i=0;
i<3;
i++) {
1022 allDerivatives[
i].push_back(&deriv_vec[nModPars+
i]);
1023 for (
int j=0;j<WSize;j++) {
1024 F(
i,j) = deriv_vec[nModPars+
i][j];
1032 ATH_MSG_ERROR(
"accumulateVTX: Derivatives do not have a valid pointer to the module.");
1039 derivIt = derivatives.begin();
1040 for ( ; derivIt!=derivIt_end ; ++derivIt) {
1048 std::vector<Amg::VectorX>& deriv_vec = derivIt->second;
1049 std::vector<Amg::VectorX> drdaWF;
1051 << deriv_vec.size());
1053 int nModPars = alignPars->
size();
1054 if ((nModPars + 3) != (
int)deriv_vec.size()) {
1056 "accumulateVTX: Derivatives w.r.t. the vertex seem to be missing");
1059 drdaWF.reserve(nModPars);
1060 for (
int i = 0;
i < nModPars;
i++) {
1061 drdaWF.emplace_back(2.0 * (WF)*deriv_vec[
i]);
1063 ATH_MSG_DEBUG(
"accumulateVTX: derivX incremented by: " << drdaWF);
1065 derivX.emplace_back(
module,std::move(drdaWF));
1068 ATH_MSG_ERROR(
"accumulateVTX: Derivatives do not have a valid pointer to the module.");
1076 int nmodules = allDerivatives[0].size();
1078 for(
int ii=0; ii<3; ++ii ) {
1079 VTXDerivatives[ii] = (*(allDerivatives[ii])[0]);
1080 for(
int jj=1; jj<nmodules; ++jj ) {
1081 VTXDerivatives[ii] += (*(allDerivatives[ii])[jj]);
1092 for (
int ipar=0;ipar<3;ipar++) {
1096 Amg::MatrixX derivativesT = (VTXDerivatives[ipar]).transpose();
1097 ATH_MSG_DEBUG(
"derivativesT (size "<<derivativesT.cols()<<
"): "<<derivativesT);
1100 vtxV[ipar] = tempV(0,0);
1102 for (
int jpar=ipar;jpar<3;jpar++) {
1108 vtxM(ipar,jpar) = tempM(0,0);
1130 if( ivtx->Ntracks()>1 ) {
1133 msg(MSG::WARNING) <<
"This vertex contains " << ivtx->Ntracks() <<
" tracks. No solution possible." <<
endmsg;
1136 ATH_MSG_DEBUG(
"This vertex contains " << ivtx->Ntracks() <<
" tracks.");
1147 *
m_logStream<<
"*************************************************************"<<std::endl;
1148 *
m_logStream<<
"****** BeamspotVertexPreProcessor summary ******"<<std::endl;
1152 *
m_logStream<<
"* --------------------------------------------"<<std::endl;
1169 ATH_MSG_INFO(
"BeamspotVertexPreProcessor::finalize()");
1171 return StatusCode::SUCCESS;