ATLAS Offline Software
NeutralParticleParameterCalculator.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 /*********************************************************************
6  NeutralParticleParameterCalculator.cxx - Description in header file
7 *********************************************************************/
8 
14 
17 
18 
19 // #define IMPACTPOINT3DESTIMATOR_DEBUG
20 
21 namespace Trk
22 {
23 
24  NeutralParticleParameterCalculator::NeutralParticleParameterCalculator(const std::string& t, const std::string& n, const IInterface* p) :
25  AthAlgTool(t,n,p),
26  m_LinearizedTrackFactory("Trk::FullLinearizedTrackFactory/FullLinearizedTrackFactory"),
27  m_linearizedTrackFactoryIsAvailable(false)
28  {
29  declareProperty("LinearizedTrackFactory",m_LinearizedTrackFactory);
30  declareInterface<INeutralParticleParameterCalculator>(this);
31  }
32 
34 
36  {
37  ATH_CHECK(m_LinearizedTrackFactory.retrieve( DisableTool{ m_LinearizedTrackFactory.empty() } ));
39 
40  return StatusCode::SUCCESS;
41  }
42 
43 
45  (const xAOD::Vertex & myVertex) const
46  {
47 
48  if (myVertex.nTrackParticles()!=2)
49  {
50  msg(MSG::WARNING) << " More or less than 2 tracks in Vertex. No Neutral Perigee could be created" << endmsg;
51  return nullptr;
52  }
53 
54  if ( !myVertex.trackParticleLinks()[0].isValid() || !myVertex.trackParticleLinks()[1].isValid() )
55  {
56  msg(MSG::WARNING) << " Track Particle Element link is not valid" << endmsg;
57  return nullptr;
58 
59  }
60  const xAOD::TrackParticle * myFirstTrack= myVertex.trackParticle( 0 );
61  const xAOD::TrackParticle * mySecondTrack=myVertex.trackParticle( 1 );
62 
63  const Trk::Perigee& myFirstPerigee = myFirstTrack->perigeeParameters();
64  const Trk::Perigee& mySecondPerigee = mySecondTrack->perigeeParameters();
65 
66  const AmgMatrix(3,3)& vrt_cov = myVertex.covariancePosition();
67  AmgMatrix(3,3) vrt_weight = myVertex.covariancePosition().inverse().eval();
68 
69  //need to recalculate the refitted covariance matrix of the tracks (yes, we don't have it yet)
70  std::pair<AmgMatrix(3,3),AmgMatrix(3,3)> PosMomAndMomCovFirstTrack;
71  std::pair<AmgMatrix(3,3),AmgMatrix(3,3)> PosMomAndMomCovSecondTrack;
72 
73 
74  //check if the linearizedTrackFactory is available...
76  msg(MSG::ERROR) << " No LinearizedTrackFactory is defined and no ExtendedVxCandidate is provided. Cannot obtain covariance matrix of neutral particle. Failed... " << endmsg;
77  return nullptr;
78  }
79 
80 
82 
83  const Trk::LinearizedTrack * myFirstLinearizedTrack = m_LinearizedTrackFactory->linearizedTrack(&myFirstPerigee, myVertex.position() );
84  const Trk::LinearizedTrack * mySecondLinearizedTrack= m_LinearizedTrackFactory->linearizedTrack(&mySecondPerigee, myVertex.position() );
85 
86  if (myFirstLinearizedTrack==nullptr||mySecondLinearizedTrack==nullptr)
87  {
88  msg(MSG::WARNING) << " Could not find one of the linearized tracks. No Neutral Perigee could be created" << endmsg;
89  if (myFirstLinearizedTrack) delete myFirstLinearizedTrack;
90  if (mySecondLinearizedTrack) delete mySecondLinearizedTrack;
91  return nullptr;
92  }
93 
94  PosMomAndMomCovFirstTrack=getPosMomentumAndMomentumCovMatrix(myFirstLinearizedTrack,
95  vrt_cov,
96  vrt_weight);
97 
98  PosMomAndMomCovSecondTrack=getPosMomentumAndMomentumCovMatrix(mySecondLinearizedTrack,
99  vrt_cov,
100  vrt_weight);
101 
102  delete myFirstLinearizedTrack;
103  delete mySecondLinearizedTrack;
104  } else {
105  msg(MSG::WARNING) << " getPosMomentumAndMomentumCovMatrix method failed " << endmsg;
106  return nullptr;
107  }
108 
109  const AmgVector(5) & myFirstPerigeeParameters=myFirstPerigee.parameters();
110  const AmgVector(5) & mySecondPerigeeParameters=mySecondPerigee.parameters();
111 
112  AmgMatrix(3,3) FirstJacobianToPxPyPz=getPhiThetaQOverPToPxPyPzJacobian(myFirstPerigeeParameters[Trk::qOverP],
113  myFirstPerigeeParameters[Trk::theta],
114  myFirstPerigeeParameters[Trk::phi0]);
115 
116  AmgMatrix(3,3) SecondJacobianToPxPyPz=getPhiThetaQOverPToPxPyPzJacobian(mySecondPerigeeParameters[Trk::qOverP],
117  mySecondPerigeeParameters[Trk::theta],
118  mySecondPerigeeParameters[Trk::phi0]);
119 
120 
121 
122  AmgMatrix(3,3) posMomentumCovFirst=PosMomAndMomCovFirstTrack.first*FirstJacobianToPxPyPz.transpose();
123  AmgMatrix(3,3) posMomentumCovSecond=PosMomAndMomCovSecondTrack.first*SecondJacobianToPxPyPz.transpose();
124 
125  AmgMatrix(3,3) momentumCovFirst=PosMomAndMomCovFirstTrack.second.similarity(FirstJacobianToPxPyPz);
126  AmgMatrix(3,3) momentumCovSecond=PosMomAndMomCovSecondTrack.second.similarity(SecondJacobianToPxPyPz);
127 
128 
129  //P1 P2 covariance matrix
130  AmgMatrix(3,3) covP1P2; covP1P2.setZero();
131 
132 
133  covP1P2=posMomentumCovFirst.transpose()*vrt_weight*posMomentumCovSecond;
134 
135  // no distinction between symmetric and non-symmetric square matrices in new EDM, drop checks.
136  // AmgMatrix(3,3) nonSymCovNewP = momentumCovFirst+momentumCovSecond+covP1P2+covP1P2.transpose();
137  AmgMatrix(3,3) covNewP = momentumCovFirst+momentumCovSecond+covP1P2+covP1P2.transpose();
138 
139  AmgMatrix(3,3) covNewXP=posMomentumCovFirst+posMomentumCovSecond;
140 
141  //now covNewP and covNewXP are the new covariance matrices with the new momentum
142  //calculate also new momentum
143  Amg::Vector3D newMomentum=myFirstPerigee.momentum()+mySecondPerigee.momentum();
144 
145  ATH_MSG_VERBOSE(" new momentum " << newMomentum << " new cov Momentum " << covNewP);
146  ATH_MSG_VERBOSE(" position " << myVertex.position() << " cov Pos - Momentum " << covNewXP);
147  ATH_MSG_VERBOSE(" old cov position " << vrt_cov);
148 
149  //Now you need to create the new neutral tracks
150  //NOT trivial, since no global representation exists...
151  //now you need first to go back with the momentum (px,py,pz -> phi,theta,q/p)
152 
153  Trk::JacobianPxyzToPhiThetaQoverPspherical JacobianToPhiThetaQOverP(newMomentum.phi(),
154  newMomentum.theta(),
155  1./newMomentum.mag());
156 
157  AmgMatrix(3,3) finalCovNewP=covNewP.similarity(JacobianToPhiThetaQOverP);
158  AmgMatrix(3,3) finalCovNewXP=covNewXP*JacobianToPhiThetaQOverP.transpose();
159 
160  double phi=newMomentum.phi();
161  double theta=newMomentum.theta();
162  double qOverP=1./newMomentum.mag();
163 
164  ATH_MSG_VERBOSE(" new phi: " << phi << " +/- " << sqrt(finalCovNewP(0,0)));
165  ATH_MSG_VERBOSE(" new theta: " << theta << " +/- " << sqrt(finalCovNewP(1,1)));
166  ATH_MSG_VERBOSE(" new P: " << 1./qOverP << " +/- " << 1./qOverP/qOverP*sqrt(finalCovNewP(2,2)));
167 
168  //now you still have 6 parameters! need to reduce them to 5!
169  //
170  //create the jacobian for a neutral particle
171 
172  double sin_phi_v=sin(phi);
173  double cos_phi_v=cos(phi);
174  double tan_th=tan(theta);
175 
176  //jacobian elements
177  AmgMatrix(5,6) globalNeutralJacobian; globalNeutralJacobian.setZero();
178  globalNeutralJacobian(0,0) = -sin_phi_v;
179  globalNeutralJacobian(0,1) = +cos_phi_v;
180  globalNeutralJacobian(1,0) = -cos_phi_v/tan_th;
181  globalNeutralJacobian(1,1) = -sin_phi_v/tan_th;
182  globalNeutralJacobian(1,2) = 1.;
183  globalNeutralJacobian(2,3) = 1.;
184  globalNeutralJacobian(3,4) = 1.;
185  globalNeutralJacobian(4,5) = 1.;
186 
187  AmgMatrix(6,6) fullTrkCov; fullTrkCov.setZero();
188  fullTrkCov.block<3,3>(0,3) = finalCovNewXP; // was .sub(1,4, finalCovNewXP);
189  fullTrkCov.block<3,3>(3,0) = finalCovNewXP.transpose(); // was .sub(4,1, finalCovNewXP.T());
190  fullTrkCov.block<3,3>(0,0) = vrt_cov; // was .sub(1,1, vrt_cov);
191  fullTrkCov.block<3,3>(3,3) = finalCovNewP; // was .sub(4,4, finalCovNewP);
192 
193  // no mechanism in new EDM: CLHEP::HepSymMatrix symFullTrkCov;
194  // no mechanism in new EDM: symFullTrkCov.assign(fullTrkCov);
195 
196  Trk::PerigeeSurface perSurface(myVertex.position());
197  AmgSymMatrix(5) covNeutral = AmgSymMatrix(5)(globalNeutralJacobian*fullTrkCov*globalNeutralJacobian.transpose());
198 
199  return new Trk::NeutralPerigee(0,0,phi,theta,qOverP,perSurface,std::move(covNeutral));
200  }
201 
202 
203 
204 
206  (const Trk::LinearizedTrack* linTrack,
207  const AmgMatrix(3,3) & vrt_cov,
208  const AmgMatrix(3,3) & vrt_weight) const
209  {
210 
211  const AmgMatrix(5,3) & A = linTrack->positionJacobian();
212  const AmgMatrix(5,3) & B = linTrack->momentumJacobian();
213  const AmgSymMatrix(5) & trkParametersWeight = linTrack->expectedWeightAtPCA();
214 
215  AmgSymMatrix(3) Sm = B.transpose()*(trkParametersWeight*B);
216  // same maths, but doesn't compile: AmgSymMatrix(3) Sm = trkParametersWeight.similarityT(B);
217  if (Sm.determinant() == 0.0) {
218  ATH_MSG_WARNING("S matrix can not be inverted, new type of check as part of Eigen, please monitor."
219  << endmsg << "Matrix Sm = " << Sm);
220  ATH_MSG_WARNING("This track is returned not refitted");
221  // throw std::string("Inversion of S matrix fails in track parameters refit");
222  }
223  Sm = Sm.inverse().eval();
224  AmgMatrix(3,3) posMomentumCovariance = -vrt_cov * A.transpose() * trkParametersWeight * B *Sm;
225  AmgMatrix(3,3) momentumCovariance = Sm + vrt_weight.similarityT(posMomentumCovariance);
226 
227  return std::pair<AmgMatrix(3,3),AmgMatrix(3,3)>(posMomentumCovariance,momentumCovariance);
228  }
229 
230 
231  AmgMatrix(3,3) NeutralParticleParameterCalculator::getPhiThetaQOverPToPxPyPzJacobian
232  (double qOverP,double theta,double phi) {
233  AmgMatrix(3,3) transform; transform.setZero();
234  transform(0,0)=-1./fabs(qOverP)*sin(theta)*sin(phi);
235  transform(0,1)=1./fabs(qOverP)*sin(theta)*cos(phi);
236  transform(0,2)=0.;
237  transform(1,0)=1./fabs(qOverP)*cos(theta)*cos(phi);
238  transform(1,1)=1./fabs(qOverP)*cos(theta)*sin(phi);
239  transform(1,2)=-1./fabs(qOverP)*sin(theta);
240  transform(2,0)=-1./qOverP/fabs(qOverP)*sin(theta)*cos(phi);
241  transform(2,1)=-1./qOverP/fabs(qOverP)*sin(theta)*sin(phi);
242  transform(2,2)=-1./qOverP/fabs(qOverP)*cos(theta);
243  return transform.transpose().eval();
244  }
245 
246 }
Trk::NeutralParticleParameterCalculator::theta
static double theta
Definition: NeutralParticleParameterCalculator.h:69
Trk::NeutralParticleParameterCalculator::initialize
virtual StatusCode initialize() override
Definition: NeutralParticleParameterCalculator.cxx:37
Trk::AmgMatrix
AmgMatrix(3, 3) NeutralParticleParameterCalculator
Definition: NeutralParticleParameterCalculator.cxx:233
Trk::NeutralParticleParameterCalculator::m_linearizedTrackFactoryIsAvailable
bool m_linearizedTrackFactoryIsAvailable
Definition: NeutralParticleParameterCalculator.h:72
xAOD::Vertex_v1::nTrackParticles
size_t nTrackParticles() const
Get the number of tracks associated with this vertex.
Definition: Vertex_v1.cxx:270
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
Trk::NeutralPerigee
ParametersT< 5, Neutral, PerigeeSurface > NeutralPerigee
Definition: NeutralParameters.h:30
Trk::PerigeeSurface
Definition: PerigeeSurface.h:43
Trk::ParametersT
Dummy class used to allow special convertors to be called for surfaces owned by a detector element.
Definition: EMErrorDetail.h:25
xAOD::Vertex_v1::trackParticleLinks
const TrackParticleLinks_t & trackParticleLinks() const
Get all the particles associated with the vertex.
xAOD::Vertex_v1::position
const Amg::Vector3D & position() const
Returns the 3-pos.
Trk::NeutralParticleParameterCalculator::m_LinearizedTrackFactory
ToolHandle< Trk::IVertexLinearizedTrackFactory > m_LinearizedTrackFactory
Definition: NeutralParticleParameterCalculator.h:71
Trk::NeutralParticleParameterCalculator::getPosMomentumAndMomentumCovMatrix
std::pair< AmgMatrix(3, 3), AmgMatrix(3, 3)> getPosMomentumAndMomentumCovMatrix(const Trk::LinearizedTrack *linTrack, const AmgMatrix(3, 3) &vrt_cov, const AmgMatrix(3, 3) &vrt_weight) const
Definition: NeutralParticleParameterCalculator.cxx:208
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Trk::NeutralParticleParameterCalculator::AmgMatrix
static AmgMatrix(3, 3) getPhiThetaQOverPToPxPyPzJacobian(double qOverP
Trk::AmgSymMatrix
AmgSymMatrix(5) &GXFTrackState
Definition: GXFTrackState.h:156
xAOD::TrackParticle_v1::perigeeParameters
const Trk::Perigee & perigeeParameters() const
Returns the Trk::MeasuredPerigee track parameters.
Definition: TrackParticle_v1.cxx:485
beamspotman.n
n
Definition: beamspotman.py:731
Trk::theta
@ theta
Definition: ParamDefs.h:72
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
AmgVector
AmgVector(4) T2BSTrackFilterTool
Definition: T2BSTrackFilterTool.cxx:114
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
VxTrackAtVertex.h
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Trk::JacobianPxyzToPhiThetaQoverPspherical
Jacobian in spherical coordinates for the transformation of momentum in Cartesian coordinates to mom...
Definition: JacobianPxyzToPhiThetaQoverPspherical.h:38
Trk::NeutralParticleParameterCalculator::NeutralParticleParameterCalculator
NeutralParticleParameterCalculator(const std::string &t, const std::string &n, const IInterface *p)
Default constructor due to Athena interface.
Definition: NeutralParticleParameterCalculator.cxx:26
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
xAOD::Vertex_v1::trackParticle
const TrackParticle * trackParticle(size_t i) const
Get the pointer to a given track that was used in vertex reco.
Definition: Vertex_v1.cxx:249
JacobianPxyzToPhiThetaQoverPspherical.h
Trk::NeutralParticleParameterCalculator
Definition: NeutralParticleParameterCalculator.h:44
Trk
Ensure that the ATLAS eigen extensions are properly loaded.
Definition: FakeTrackBuilder.h:9
Trk::NeutralParticleParameterCalculator::phi
static double double phi
Definition: NeutralParticleParameterCalculator.h:69
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
NeutralParticleParameterCalculator.h
TrackParticle.h
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
Trk::NeutralParticleParameterCalculator::createNeutralTrackFromVertex
virtual NeutralPerigee * createNeutralTrackFromVertex(const xAOD::Vertex &) const override
method that makes the parameters of a V0 or photon before decay to two tracks
Definition: NeutralParticleParameterCalculator.cxx:47
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Trk::NeutralParticleParameterCalculator::~NeutralParticleParameterCalculator
~NeutralParticleParameterCalculator()
Destructor.
IVertexLinearizedTrackFactory.h
AthCommonMsg< AlgTool >::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
Trk::qOverP
@ qOverP
perigee
Definition: ParamDefs.h:73
declareProperty
#define declareProperty(n, p, h)
Definition: BaseFakeBkgTool.cxx:15
Trk::phi
@ phi
Definition: ParamDefs.h:81
LinearizedTrack.h
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
AthAlgTool
Definition: AthAlgTool.h:26
Trk::phi0
@ phi0
Definition: ParamDefs.h:71
TrackParticleContainer.h
Trk::LinearizedTrack
Definition: LinearizedTrack.h:43