Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed sign in pat::Muon::dB() to match one obtained from the best track definition #28753

Merged
merged 7 commits into from
Feb 7, 2020
Merged
11 changes: 11 additions & 0 deletions DataFormats/TrackReco/interface/TrackBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,12 @@ namespace reco {
/// error on beta
double betaError() const;

/// error on dxy with respect to a user-given reference point + uncertainty (i.e. reco::Vertex position)
double dxyError(Point const &vtx, math::Error<3>::type const &vertexCov) const;

/// error on dxy with respect to a user-given beamspot
double dxyError(const BeamSpot &theBeamSpot) const;

/// fill SMatrix
CovarianceMatrix &fill(CovarianceMatrix &v) const;

Expand Down Expand Up @@ -736,6 +742,11 @@ namespace reco {
// error on beta
inline double TrackBase::betaError() const { return std::sqrt(covbetabeta_); }

// error on dxy with respect to a given beamspot
inline double TrackBase::dxyError(const BeamSpot &theBeamSpot) const {
return dxyError(theBeamSpot.position(vz()), theBeamSpot.rotatedCovariance3D());
}

// number of valid hits found
inline unsigned short TrackBase::numberOfValidHits() const { return hitPattern_.numberOfValidHits(); }

Expand Down
13 changes: 13 additions & 0 deletions DataFormats/TrackReco/src/TrackBase.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,16 @@ TrackBase::TrackAlgorithm TrackBase::algoByName(const std::string &name) {
// cast
return TrackAlgorithm(index);
}

double TrackBase::dxyError(Point const &vtx, math::Error<3>::type const &vertexCov) const {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the proposed way to propagate uncertainties properly for the dxy measurement with respect to a given PV.

Going from the original frame (dxy) to the new frame (dxy') translated from PV coordinates (xv, yv) it uses the transformation:
dxy' = dxy + x_vsin(phi) - y_vcos(phi)

And propagates accordingly using the track and vertex covariance matrices plus gradients

(0,0,xvcos(phi) + yvsin(phi), 1, 0) (gradient with respect to the track parameters in the curvilinear basis)

(sin(phi), -cos(phi), 0) (gradient with respect to the vertex parameters)

// Gradient of TrackBase::dxy(const Point &myBeamSpot) with respect to track parameters. Using unrolled expressions to avoid calling for higher dimension matrices
// ( 0, 0, x_vert * cos(phi) + y_vert * sin(phi), 1, 0 )
// Gradient with respect to point parameters
// ( sin(phi), -cos(phi))
// Propagate covariance assuming cross-terms of the covariance between track and vertex parameters are 0
return std::sqrt((vtx.x() * px() + vtx.y() * py()) * (vtx.x() * px() + vtx.y() * py()) / (pt() * pt()) *
covariance(i_phi, i_phi) +
2 * (vtx.x() * px() + vtx.y() * py()) / pt() * covariance(i_phi, i_dxy) + covariance(i_dxy, i_dxy) +
py() * py() / (pt() * pt()) * vertexCov(0, 0) - 2 * py() * px() / (pt() * pt()) * vertexCov(0, 1) +
px() * px() / (pt() * pt()) * vertexCov(1, 1));
}
23 changes: 10 additions & 13 deletions PhysicsTools/PatAlgos/plugins/PATMuonProducer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1097,27 +1097,24 @@ void PATMuonProducer::embedHighLevel(pat::Muon& aMuon,
// Correct to PV

// PV2D
aMuon.setDB(track->dxy(primaryVertex.position()),
track->dxyError(primaryVertex.position(), primaryVertex.covariance()),
pat::Muon::PV2D);

// PV3D
std::pair<bool, Measurement1D> result =
IPTools::signedTransverseImpactParameter(tt, GlobalVector(track->px(), track->py(), track->pz()), primaryVertex);
IPTools::signedImpactParameter3D(tt, GlobalVector(track->px(), track->py(), track->pz()), primaryVertex);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't the 3D also have the same problem as the 2D case?
Also, does this agree (in a linear approximation) with the reco::Track::dsz ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the difference in the sign between that of the best track and the one obtained by IPTools remains. Nonetheless, the sign itself is not used elsewhere as that of the 2D version is. I understand that using track information would be preferred from the usage of computational resources point of view?

From a quick set of tests I see, surprisingly, that in most cases (~90%) both computations of the 3D IP agree, but there is a significant set of deviations between the tracks' dsz and iptools' value for ~10% of the events. This seems to be correlated with the linear approximation but not completely caused by it (i.e. it happens for several cases in which vertex ~ (0,0,0) and with relatively high pT/low bending).

The sip3D = abs(d3d)/error(d3d) variable is used down the line in terms of ID criteria. I.e. for the prompt MVA discriminant (

double dB3D = muon.dB(pat::Muon::PV3D);
). This deserves further studies in terms of muon selection optimality before changing it which goes slightly out of scope for this PR. Should we put it as a separate issue?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we put it as a separate issue?

OK.
Thank you for checking.

double d0_corr = result.second.value();
double d0_err = primaryVertexIsValid ? result.second.error() : -1.0;
aMuon.setDB(d0_corr, d0_err, pat::Muon::PV2D);

// PV3D
result = IPTools::signedImpactParameter3D(tt, GlobalVector(track->px(), track->py(), track->pz()), primaryVertex);
d0_corr = result.second.value();
d0_err = primaryVertexIsValid ? result.second.error() : -1.0;
aMuon.setDB(d0_corr, d0_err, pat::Muon::PV3D);

// Correct to beam spot
// make a fake vertex out of beam spot
reco::Vertex vBeamspot(beamspot.position(), beamspot.rotatedCovariance3D());

// BS2D
result = IPTools::signedTransverseImpactParameter(tt, GlobalVector(track->px(), track->py(), track->pz()), vBeamspot);
d0_corr = result.second.value();
d0_err = beamspotIsValid ? result.second.error() : -1.0;
aMuon.setDB(d0_corr, d0_err, pat::Muon::BS2D);
aMuon.setDB(track->dxy(beamspot), track->dxyError(beamspot), pat::Muon::BS2D);

// make a fake vertex out of beam spot
reco::Vertex vBeamspot(beamspot.position(), beamspot.rotatedCovariance3D());

// BS3D
result = IPTools::signedImpactParameter3D(tt, GlobalVector(track->px(), track->py(), track->pz()), vBeamspot);
Expand Down