File indexing completed on 2024-04-06 12:28:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <memory>
0011
0012 #include "FWCore/Framework/interface/Frameworkfwd.h"
0013 #include "FWCore/Framework/interface/global/EDProducer.h"
0014 #include "FWCore/Framework/interface/Event.h"
0015 #include "FWCore/Framework/interface/MakerMacros.h"
0016 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0017 #include "FWCore/Utilities/interface/InputTag.h"
0018
0019 #include "Geometry/Records/interface/GlobalTrackingGeometryRecord.h"
0020 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
0021
0022 #include "DataFormats/TrackReco/interface/Track.h"
0023 #include "DataFormats/TrackReco/interface/TrackFwd.h"
0024
0025 #include "TrackingTools/PatternTools/interface/TrackConstraintAssociation.h"
0026
0027 #include "Alignment/TwoBodyDecay/interface/TwoBodyDecay.h"
0028 #include "Alignment/TwoBodyDecay/interface/TwoBodyDecayModel.h"
0029 #include "Alignment/TwoBodyDecay/interface/TwoBodyDecayFitter.h"
0030 #include "Alignment/TwoBodyDecay/interface/TwoBodyDecayVirtualMeasurement.h"
0031 #include "Alignment/ReferenceTrajectories/interface/TwoBodyDecayTrajectoryState.h"
0032
0033
0034
0035
0036
0037
0038
0039
0040 class TwoBodyDecayMomConstraintProducer : public edm::global::EDProducer<> {
0041 public:
0042 explicit TwoBodyDecayMomConstraintProducer(const edm::ParameterSet&);
0043 ~TwoBodyDecayMomConstraintProducer() override = default;
0044
0045 private:
0046 void produce(edm::StreamID streamid, edm::Event&, const edm::EventSetup&) const override;
0047
0048 std::pair<double, double> momentaAtVertex(const TwoBodyDecay& tbd) const;
0049
0050 std::pair<double, double> momentaAtInnermostSurface(const TwoBodyDecay& tbd,
0051 const std::vector<reco::TransientTrack>& ttracks,
0052 const MagneticField* magField) const;
0053
0054 std::pair<bool, TrajectoryStateOnSurface> innermostState(const reco::TransientTrack& ttrack) const;
0055 bool match(const TrajectoryStateOnSurface& newTsos, const TrajectoryStateOnSurface& oldTsos) const;
0056
0057 const edm::InputTag srcTag_;
0058 const edm::InputTag bsSrcTag_;
0059
0060 const TwoBodyDecayFitter tbdFitter_;
0061
0062 const double primaryMass_;
0063 const double primaryWidth_;
0064 const double secondaryMass_;
0065
0066 const double sigmaPositionCutValue_;
0067 const double chi2CutValue_;
0068 const double fixedMomentumError_;
0069
0070 enum MomentumForRefitting { atVertex, atInnermostSurface };
0071 const MomentumForRefitting momentumForRefitting_;
0072
0073 static MomentumForRefitting momentumForRefittingFromString(std::string momentumForRefittingString);
0074
0075 edm::EDGetTokenT<reco::TrackCollection> trackCollToken_;
0076 edm::EDGetTokenT<reco::BeamSpot> bsToken_;
0077
0078 const edm::ESGetToken<MagneticField, IdealMagneticFieldRecord> magFieldToken_;
0079 const edm::ESGetToken<GlobalTrackingGeometry, GlobalTrackingGeometryRecord> trackingGeometryToken_;
0080
0081
0082 };
0083
0084 TwoBodyDecayMomConstraintProducer::TwoBodyDecayMomConstraintProducer(const edm::ParameterSet& iConfig)
0085 : srcTag_(iConfig.getParameter<edm::InputTag>("src")),
0086 bsSrcTag_(iConfig.getParameter<edm::InputTag>("beamSpot")),
0087 tbdFitter_(iConfig),
0088 primaryMass_(iConfig.getParameter<double>("primaryMass")),
0089 primaryWidth_(iConfig.getParameter<double>("primaryWidth")),
0090 secondaryMass_(iConfig.getParameter<double>("secondaryMass")),
0091 sigmaPositionCutValue_(iConfig.getParameter<double>("sigmaPositionCut")),
0092 chi2CutValue_(iConfig.getParameter<double>("chi2Cut")),
0093 fixedMomentumError_(iConfig.getParameter<double>("fixedMomentumError")),
0094 momentumForRefitting_(momentumForRefittingFromString(iConfig.getParameter<std::string>("momentumForRefitting"))),
0095 magFieldToken_(esConsumes()),
0096 trackingGeometryToken_(esConsumes()) {
0097 trackCollToken_ = consumes<reco::TrackCollection>(edm::InputTag(srcTag_));
0098 bsToken_ = consumes<reco::BeamSpot>(edm::InputTag(bsSrcTag_));
0099
0100 produces<std::vector<MomentumConstraint> >();
0101 produces<TrackMomConstraintAssociationCollection>();
0102
0103
0104
0105
0106
0107
0108
0109 }
0110
0111 void TwoBodyDecayMomConstraintProducer::produce(edm::StreamID streamid,
0112 edm::Event& iEvent,
0113 const edm::EventSetup& iSetup) const {
0114 using namespace edm;
0115
0116 Handle<reco::TrackCollection> trackColl;
0117 iEvent.getByToken(trackCollToken_, trackColl);
0118
0119 Handle<reco::BeamSpot> beamSpot;
0120 iEvent.getByToken(bsToken_, beamSpot);
0121
0122 auto const* magField = &iSetup.getData(magFieldToken_);
0123
0124 auto trackingGeometry = iSetup.getHandle(trackingGeometryToken_);
0125
0126 edm::RefProd<std::vector<MomentumConstraint> > rPairs = iEvent.getRefBeforePut<std::vector<MomentumConstraint> >();
0127 std::unique_ptr<std::vector<MomentumConstraint> > pairs(new std::vector<MomentumConstraint>);
0128 std::unique_ptr<TrackMomConstraintAssociationCollection> output(
0129 new TrackMomConstraintAssociationCollection(trackColl, rPairs));
0130
0131 if (trackColl->size() == 2) {
0132
0133 TwoBodyDecayVirtualMeasurement vm(primaryMass_, primaryWidth_, secondaryMass_, *beamSpot.product());
0134
0135
0136 std::vector<reco::TransientTrack> ttracks(2);
0137 ttracks[0] = reco::TransientTrack(reco::TrackRef(trackColl, 0), magField);
0138 ttracks[0].setTrackingGeometry(trackingGeometry);
0139 ttracks[1] = reco::TransientTrack(reco::TrackRef(trackColl, 1), magField);
0140 ttracks[1].setTrackingGeometry(trackingGeometry);
0141
0142
0143 TwoBodyDecay tbd = tbdFitter_.estimate(ttracks, vm);
0144
0145 if (!tbd.isValid() or (tbd.chi2() > chi2CutValue_))
0146 return;
0147
0148 std::pair<double, double> fitMomenta;
0149 if (momentumForRefitting_ == atVertex) {
0150 fitMomenta = momentaAtVertex(tbd);
0151 } else if (momentumForRefitting_ == atInnermostSurface) {
0152 fitMomenta = momentaAtInnermostSurface(tbd, ttracks, magField);
0153 }
0154
0155 if ((fitMomenta.first > 0.) and (fitMomenta.second > 0.)) {
0156
0157 MomentumConstraint constraint1(fitMomenta.first, fixedMomentumError_);
0158 pairs->push_back(constraint1);
0159 output->insert(reco::TrackRef(trackColl, 0), edm::Ref<std::vector<MomentumConstraint> >(rPairs, 0));
0160
0161
0162 MomentumConstraint constraint2(fitMomenta.second, fixedMomentumError_);
0163 pairs->push_back(constraint2);
0164 output->insert(reco::TrackRef(trackColl, 1), edm::Ref<std::vector<MomentumConstraint> >(rPairs, 1));
0165 }
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186 }
0187
0188 iEvent.put(std::move(pairs));
0189 iEvent.put(std::move(output));
0190 }
0191
0192 std::pair<double, double> TwoBodyDecayMomConstraintProducer::momentaAtVertex(const TwoBodyDecay& tbd) const {
0193
0194 TwoBodyDecayModel tbdDecayModel(tbd[TwoBodyDecayParameters::mass], secondaryMass_);
0195 std::pair<AlgebraicVector, AlgebraicVector> secondaryMomenta = tbdDecayModel.cartesianSecondaryMomenta(tbd);
0196
0197 return std::make_pair(secondaryMomenta.first.norm(), secondaryMomenta.second.norm());
0198 }
0199
0200 std::pair<double, double> TwoBodyDecayMomConstraintProducer::momentaAtInnermostSurface(
0201 const TwoBodyDecay& tbd, const std::vector<reco::TransientTrack>& ttracks, const MagneticField* magField) const {
0202 std::pair<double, double> result = std::make_pair(-1., -1.);
0203
0204
0205 std::pair<bool, TrajectoryStateOnSurface> oldInnermostState1 = innermostState(ttracks[0]);
0206 std::pair<bool, TrajectoryStateOnSurface> oldInnermostState2 = innermostState(ttracks[1]);
0207 if (!oldInnermostState1.second.isValid() || !oldInnermostState2.second.isValid())
0208 return result;
0209
0210
0211 TwoBodyDecayTrajectoryState::TsosContainer trackTsos(oldInnermostState1.second, oldInnermostState2.second);
0212 TwoBodyDecayTrajectoryState tbdTrajState(trackTsos, tbd, secondaryMass_, magField, true);
0213 if (!tbdTrajState.isValid())
0214 return result;
0215
0216
0217 bool match1 = match(tbdTrajState.trajectoryStates(true).first, oldInnermostState1.second);
0218 bool match2 = match(tbdTrajState.trajectoryStates(true).second, oldInnermostState2.second);
0219 if (!match1 || !match2)
0220 return result;
0221
0222 result = std::make_pair(fabs(1. / tbdTrajState.trajectoryStates(true).first.localParameters().qbp()),
0223 fabs(1. / tbdTrajState.trajectoryStates(true).second.localParameters().qbp()));
0224 return result;
0225 }
0226
0227 std::pair<bool, TrajectoryStateOnSurface> TwoBodyDecayMomConstraintProducer::innermostState(
0228 const reco::TransientTrack& ttrack) const {
0229 double outerR = ttrack.outermostMeasurementState().globalPosition().perp();
0230 double innerR = ttrack.innermostMeasurementState().globalPosition().perp();
0231 bool insideOut = (outerR > innerR);
0232 return std::make_pair(insideOut, insideOut ? ttrack.innermostMeasurementState() : ttrack.outermostMeasurementState());
0233 }
0234
0235 bool TwoBodyDecayMomConstraintProducer::match(const TrajectoryStateOnSurface& newTsos,
0236 const TrajectoryStateOnSurface& oldTsos) const {
0237 LocalPoint lp1 = newTsos.localPosition();
0238 LocalPoint lp2 = oldTsos.localPosition();
0239
0240 double deltaX = lp1.x() - lp2.x();
0241 double deltaY = lp1.y() - lp2.y();
0242
0243 return ((fabs(deltaX) < sigmaPositionCutValue_) && (fabs(deltaY) < sigmaPositionCutValue_));
0244 }
0245
0246 TwoBodyDecayMomConstraintProducer::MomentumForRefitting
0247 TwoBodyDecayMomConstraintProducer::momentumForRefittingFromString(std::string strMomentumForRefitting) {
0248 if (strMomentumForRefitting == "atVertex") {
0249 return atVertex;
0250 } else if (strMomentumForRefitting == "atInnermostSurface") {
0251 return atInnermostSurface;
0252 } else {
0253 throw cms::Exception("TwoBodyDecayMomConstraintProducer") << "value of config variable 'momentumForRefitting': "
0254 << "has to be 'atVertex' or 'atInnermostSurface'";
0255 }
0256 }
0257
0258
0259 DEFINE_FWK_MODULE(TwoBodyDecayMomConstraintProducer);