14 #include "GaudiKernel/SmartDataPtr.h"
36 const std::string &
name,
39 , m_trackTypeCounter(
AlignTrack::NTrackTypes,0)
41 declareInterface<IAlignTrackPreProcessor>(
this);
51 ATH_MSG_INFO(
"BeamspotVertexPreProcessor::initialize()");
65 return StatusCode::FAILURE;
73 return StatusCode::FAILURE;
81 return StatusCode::FAILURE;
89 return StatusCode::FAILURE;
101 ATH_MSG_FATAL(
"Requested BeamSpot track selection but Track Selector not configured");
102 return StatusCode::FAILURE;
106 return StatusCode::FAILURE;
114 ATH_MSG_FATAL(
"Requested beam-spot constraint but RefitTracks is False.");
115 return StatusCode::FAILURE;
121 return StatusCode::FAILURE;
126 ATH_MSG_INFO(
"************************************************************************");
128 ATH_MSG_INFO(
"* You have requested the Full Vertex Constraint option. *");
129 ATH_MSG_INFO(
"* It is your duty to assure that all detector elements *");
130 ATH_MSG_INFO(
"* used for track fitting are also loaded in the alignment framework!!! *");
132 ATH_MSG_INFO(
"* Also make sure the accurate track covariance matrix *");
133 ATH_MSG_INFO(
"* is returned by the GlobalChi2Fitter! *");
135 ATH_MSG_INFO(
"************************************************************************");
139 return StatusCode::SUCCESS;
147 if(!linkToTrackParticle)
return false;
154 if(
m_method.find(
"compareAddress") != std::string::npos){
159 if(
m_method.find(
"comparePerigee") != std::string::npos){
162 if(! (measPer1 && measPer2 ))
equal =
false;
164 float diff = std::abs(std::numeric_limits<float>::epsilon());
165 if( ( std::abs(measPer1->parameters()[
Trk::d0] - measPer2->parameters()[
Trk::d0]) >
diff)
166 || ( std::abs(measPer1->parameters()[
Trk::z0] - measPer2->parameters()[
Trk::z0]) >
diff)
181 ATH_MSG_DEBUG(
"this primary vertex has been rejected as type dummy");
185 ATH_MSG_WARNING(
" VERY STRANGE!!!, this primary vertex has been rejected as non-positive DoF "<< vtx->
numberDoF() <<
" the type of this vertex: "<< vtx->
vertexType() );
199 ATH_MSG_WARNING(
" VERY STRANGE!!! , the updated vertex has been rejected as non-positive DoF: "<< vtx->
numberDoF() <<
" the type of this vertex:"<< vtx->
vertexType() );
208 if ((vtx->covariancePosition())(0,0)<=0 ||
209 (vtx->covariancePosition())(1,1)<=0 ||
210 (vtx->covariancePosition())(2,2)<=0){
211 ATH_MSG_WARNING(
" VERY STRANGE!!! , this updated vertex has been rejected as negative diagonal error matrix ");
220 if(!vertices)
return false;
223 if (vtx->vertexType() != 1)
break;
236 std::vector<VxTrackAtVertex > vertexTracks =
vertex->vxTrackAtVertex();
239 std::vector<VxTrackAtVertex >::const_iterator iVxTrackBegin = vertexTracks.begin();
240 std::vector<VxTrackAtVertex >::const_iterator iVxTrackEnd = vertexTracks.end();
242 std::vector<VxTrackAtVertex>::const_iterator findResult = std::find_if(iVxTrackBegin, iVxTrackEnd, thisCompare);
244 return findResult != iVxTrackEnd;
253 const EventContext& ctx = Gaudi::Hive::currentContext();
258 ATH_MSG_DEBUG(
"this vertex did not pass the primary vertex selection...");
261 if (vtx->vxTrackAtVertexAvailable()){
262 std::vector<VxTrackAtVertex> vtxTracks = vtx->vxTrackAtVertex();
266 ATH_MSG_DEBUG(
"this vertex did not pass the vxTrackAtVertexAvailable() call...");
280 auto iVxTrackBegin = thisPair.second.begin();
281 auto iVxTrackEnd = thisPair.second.end();
284 auto findResult = std::find_if(iVxTrackBegin, iVxTrackEnd, thisCompare);
286 if(findResult != iVxTrackEnd){
288 findVxCandidate = thisPair.first;
293 return findVxCandidate;
299 const EventContext& ctx = Gaudi::Hive::currentContext();
308 if (!(
nullptr==findVtx) ) {
325 ATH_MSG_DEBUG(
" updated Vertex by KalmanVertexUpdator: "<<updatedVtx);
330 const Perigee* perigee =
nullptr;
331 std::unique_ptr<const Trk::TrackParameters>
tmp =
335 perigee =
static_cast<const Perigee*
> (
tmp.release());
338 const Perigee * trackPerigee =
track->perigeeParameters();
340 perigee = trackPerigee->
clone();
345 if (updatedVtx!= tmpVtx)
delete updatedVtx;
357 double ptInv = 1./perigee->momentum().perp();
358 Jacobian(0,0) = -ptInv*perigee->momentum().y();
359 Jacobian(0,1) = ptInv*perigee->momentum().x();
362 ATH_MSG_DEBUG(
" Jacobian matrix from Cartesian to Perigee: "<< Jacobian);
364 AmgSymMatrix(3) vtxCov = updatedVtx->covariancePosition();
371 tmpCov(0,0) = 1.e-10 ;
372 tmpCov(1,1) = 1.e-10;
373 tmpCov(2,2) = 1.e-10;
374 errorMatrix =
Amg::MatrixX( tmpCov.similarity(Jacobian) );
376 errorMatrix =
Amg::MatrixX( vtxCov.similarity(Jacobian) );
384 if (tmpVtx != updatedVtx){
394 vot =
new VertexOnTrack(std::move(localParams), std::move(errorMatrix), surface);
395 ATH_MSG_DEBUG(
"the VertexOnTrack created from vertex: "<<*vot);
406 const EventContext& ctx = Gaudi::Hive::currentContext();
411 float beamSpotX = bpos.x();
412 float beamSpotY = bpos.y();
413 float beamSpotZ = bpos.z();
414 float beamTiltX = beamSpotHandle->beamTilt(0);
415 float beamTiltY = beamSpotHandle->beamTilt(1);
422 float beamX = beamSpotX +
std::tan(beamTiltX) * (
z0-beamSpotZ);
423 float beamY = beamSpotY +
std::tan(beamTiltY) * (
z0-beamSpotZ);
425 ATH_MSG_DEBUG(
"constructing beam point (x,y,z) = ( "<<beamX<<
" , "<<beamY<<
" , "<<
z0<<
" )");
426 std::optional<PerigeeSurface> surface = std::nullopt;
432 beamSpotCov.setZero();
433 beamSpotCov(0,0) = beamSigmaX * beamSigmaX;
434 beamSpotCov(1,1) = beamSigmaY * beamSigmaY;
439 surface.emplace(globPos);
446 const Perigee* perigee =
nullptr;
447 std::unique_ptr<const Trk::TrackParameters>
tmp =
451 perigee =
static_cast<const Perigee*
>(
tmp.release());
455 const Perigee * trackPerigee =
track->perigeeParameters();
457 perigee = trackPerigee->
clone();
464 Eigen::Matrix<double,1,2> jacobian;
467 double ptInv = 1./perigee->momentum().perp();
468 jacobian(0,0) = -ptInv * perigee->momentum().y();
469 jacobian(0,1) = ptInv * perigee->momentum().x();
471 errorMatrix =
Amg::MatrixX( jacobian*(beamSpotCov*jacobian.transpose()));
472 if( errorMatrix.cols() != 1 )
478 std::move(errorMatrix),
484 ATH_MSG_DEBUG(
" the VertexOnTrack objects created from BeamSpot are " << *vot);
496 float beamSpotX = bpos.x();
497 float beamSpotY = bpos.y();
498 float beamSpotZ = bpos.z();
499 float beamTiltX = beamSpotHandle->beamTilt(0);
500 float beamTiltY = beamSpotHandle->beamTilt(1);
505 float z0 =
b->originalPosition()->z();
506 (*v)(0) = beamSpotX +
std::tan(beamTiltX) * (
z0-beamSpotZ);
507 (*v)(1) = beamSpotY +
std::tan(beamTiltY) * (
z0-beamSpotZ);
509 (*q)(0,0) = beamSigmaX*beamSigmaX;
510 (*q)(1,1) = beamSigmaY*beamSigmaY;
511 (*q)(2,2) = beamSigmaZ*beamSigmaZ;
513 ATH_MSG_DEBUG(
"VTX constraint point (x,y,z) = ( "<< (*
v)[0] <<
" , "<< (*
v)[1] <<
" , "<< (*
v)[2] <<
" )");
514 ATH_MSG_DEBUG(
"VTX constraint size (x,y,z) = ( "<< beamSigmaX <<
" , "<< beamSigmaY <<
" , "<< beamSigmaZ <<
" )");
519 ToolHandle<Trk::IGlobalTrackFitter>&
fitter,
524 const EventContext& ctx = Gaudi::Hive::currentContext();
525 const Track* newTrack =
nullptr;
529 std::vector<const MeasurementBase *> measurementCollection;
530 measurementCollection.push_back(vot);
532 const auto &measurements = *(
track->measurementsOnTrack());
534 measurementCollection.push_back(meas);
539 ATH_MSG_DEBUG(
" Track reference surface will be: " << surface);
543 newTrack = (
fitter->
fit(ctx, measurementCollection,
548 measurementCollection, *(
track->trackParameters()->front()),
560 bool haveVertex =
false;
565 const EventContext& ctx = Gaudi::Hive::currentContext();
571 vertices = vtxReadHandle.
cptr();
574 ATH_MSG_DEBUG(
"Primary vertex collection for this event has "<<vertices->
size()<<
" vertices");
575 if (vertices->
size()<2){
576 ATH_MSG_DEBUG(
"Only Dummy vertex present, no Primary vertices.");
583 ATH_MSG_DEBUG(
"Could not retrieve primary vertex collection from the StoreGate");
598 const double qoverP = perigee->parameters()[
Trk::qOverP] * 1000.;
607 ATH_MSG_DEBUG(
"this track passes the beamspot track selection, will do beamspot constraint on it ");
617 const Track* newTrack =
nullptr;
635 if( !vot )
ATH_MSG_INFO(
"VoT not found for this track! ");
636 if( !vtx )
ATH_MSG_INFO(
"VTX pointer not found for this track! ");
724 if( (ivtx->originalVertex())==vtx ) {
734 ATH_MSG_DEBUG(
" The Beam Spot constraint will be added to the vertex.." );
738 (qtemp)(2,2) = 1000000.0;
763 ATH_MSG_DEBUG(
"BeamspotVertexPreProcessor::processTrackCollection()");
765 if( !tracks || (tracks->
empty()) )
781 for (
const auto*
track : *tracks){
785 if (not
track)
continue;
802 if( !(alignTrack->
getVtx()) ) {
811 ATH_MSG_DEBUG(
"No Track refit for track " <<
index <<
" --> building new aligntrack");
817 if (alignTrack) newTrks->
push_back(alignTrack);
820 ATH_MSG_INFO(
"Processing of input track collection completed (size: " << tracks->size() <<
"). Size of the alignTrack collection: " << newTrks->
size() );
822 if (newTrks->
empty()) {
839 ATH_MSG_DEBUG(
"This alignTrack is not associated to any vertex -> return. ");
847 const std::vector<AlignModuleDerivatives> * ptrDerivs = alignTrack->
derivatives();
850 if (!ptrWeights || !ptrWeightsFD || !ptrResiduals || !ptrDerivs) {
853 if (!ptrWeightsFD)
ATH_MSG_ERROR(
"no weights for first deriv!");
861 std::vector<AlignModuleDerivatives> derivatives = *ptrDerivs;
870 ATH_MSG_DEBUG(
"accumulateVTX: The derivative vector size is " << derivatives.size() );
872 std::vector<const Amg::VectorX*> allDerivatives[3];
874 const int WSize(
weights.cols());
876 std::vector<AlignModuleVertexDerivatives> derivX;
878 for (
const auto& deriv : derivatives) {
885 const std::vector<Amg::VectorX>& deriv_vec = deriv.second;
886 ATH_MSG_VERBOSE(
"accumulateVTX: The deriv_vec size is " << deriv_vec.size() );
888 int nModPars = alignPars->
size();
889 if ((nModPars+3) != std::ssize(deriv_vec)) {
890 ATH_MSG_ERROR(
"accumulateVTX: Derivatives w.r.t. the vertex seem to be missing");
893 for (
int i=0;
i<3;
i++) {
894 allDerivatives[
i].push_back(&deriv_vec[nModPars+
i]);
895 for (
int j=0;j<WSize;j++) {
896 F(
i,j) = deriv_vec[nModPars+
i][j];
904 ATH_MSG_ERROR(
"accumulateVTX: Derivatives do not have a valid pointer to the module.");
911 for (
const auto& deriv : derivatives) {
917 const std::vector<Amg::VectorX>& deriv_vec = deriv.second;
918 std::vector<Amg::VectorX> drdaWF;
920 << deriv_vec.size());
922 int nModPars = alignPars->
size();
923 if ((nModPars + 3) != std::ssize(deriv_vec)) {
925 "accumulateVTX: Derivatives w.r.t. the vertex seem to be missing");
928 drdaWF.reserve(nModPars);
929 for (
int i = 0;
i < nModPars;
i++) {
930 drdaWF.emplace_back(2.0 * WF * deriv_vec[
i]);
932 ATH_MSG_DEBUG(
"accumulateVTX: derivX incremented by: " << drdaWF);
934 derivX.emplace_back(
module,std::move(drdaWF));
937 ATH_MSG_ERROR(
"accumulateVTX: Derivatives do not have a valid pointer to the module.");
943 int nmodules = allDerivatives[0].size();
944 ATH_MSG_DEBUG(
"accumulateVTX: allDerivatives size is " << nmodules);
945 for(
int ii=0; ii<3; ++ii ) {
946 VTXDerivatives[ii] = (*(allDerivatives[ii])[0]);
947 for(
int jj=1; jj<nmodules; ++jj ) {
948 VTXDerivatives[ii] += (*(allDerivatives[ii])[jj]);
958 for (
int ipar=0;ipar<3;ipar++) {
961 Amg::MatrixX derivativesT = (VTXDerivatives[ipar]).transpose();
962 ATH_MSG_DEBUG(
"derivativesT (size "<<derivativesT.cols()<<
"): "<<derivativesT);
965 vtxV[ipar] = tempV(0,0);
967 for (
int jpar=ipar;jpar<3;jpar++) {
973 vtxM(ipar,jpar) = tempM(0,0);
995 if( ivtx->Ntracks()>1 ) {
998 ATH_MSG_WARNING(
"This vertex contains " << ivtx->Ntracks() <<
" tracks. No solution possible.");
1001 ATH_MSG_DEBUG(
"This vertex contains " << ivtx->Ntracks() <<
" tracks.");
1012 *
m_logStream<<
"*************************************************************"<<std::endl;
1013 *
m_logStream<<
"****** BeamspotVertexPreProcessor summary ******"<<std::endl;
1017 *
m_logStream<<
"* --------------------------------------------"<<std::endl;
1034 ATH_MSG_INFO(
"BeamspotVertexPreProcessor::finalize()");
1036 return StatusCode::SUCCESS;