File indexing completed on 2024-04-06 12:25:00
0001
0002
0003
0004
0005
0006
0007
0008 #include "DataFormats/CaloRecHit/interface/CaloCluster.h"
0009 #include "DataFormats/CaloTowers/interface/CaloTowerCollection.h"
0010 #include "DataFormats/Common/interface/Handle.h"
0011 #include "DataFormats/Common/interface/View.h"
0012 #include "DataFormats/EgammaCandidates/interface/Conversion.h"
0013 #include "DataFormats/EgammaCandidates/interface/Photon.h"
0014 #include "DataFormats/EgammaReco/interface/SuperCluster.h"
0015 #include "DataFormats/EgammaTrackReco/interface/TrackCaloClusterAssociation.h"
0016 #include "DataFormats/TrackReco/interface/Track.h"
0017 #include "DataFormats/TrackReco/interface/TrackExtra.h"
0018 #include "DataFormats/VertexReco/interface/Vertex.h"
0019 #include "FWCore/Framework/interface/ConsumesCollector.h"
0020 #include "FWCore/Framework/interface/Event.h"
0021 #include "FWCore/Framework/interface/EventSetup.h"
0022 #include "FWCore/Framework/interface/stream/EDProducer.h"
0023 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0024 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0025 #include "FWCore/Utilities/interface/ESGetToken.h"
0026 #include "FWCore/Utilities/interface/Exception.h"
0027 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
0028 #include "Geometry/Records/interface/CaloGeometryRecord.h"
0029 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
0030 #include "MagneticField/Engine/interface/MagneticField.h"
0031 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
0032 #include "RecoEgamma/EgammaPhotonAlgos/interface/ConversionTrackEcalImpactPoint.h"
0033 #include "RecoEgamma/EgammaPhotonAlgos/interface/ConversionTrackPairFinder.h"
0034 #include "RecoEgamma/EgammaPhotonAlgos/interface/ConversionVertexFinder.h"
0035 #include "RecoEgamma/EgammaTools/interface/ConversionLikelihoodCalculator.h"
0036 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
0037 #include "TrackingTools/TransientTrack/interface/TrackTransientTrack.h"
0038 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
0039 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
0040 #include "RecoEgamma/EgammaElectronAlgos/interface/ElectronHcalHelper.h"
0041 #include "CondFormats/DataRecord/interface/HcalPFCutsRcd.h"
0042 #include "CondTools/Hcal/interface/HcalPFCutsHandler.h"
0043 #include "Geometry/CaloTopology/interface/HcalTopology.h"
0044
0045 #include <vector>
0046
0047 class ConvertedPhotonProducer : public edm::stream::EDProducer<> {
0048 public:
0049 ConvertedPhotonProducer(const edm::ParameterSet& ps);
0050
0051 void produce(edm::Event& evt, const edm::EventSetup& es) override;
0052
0053 private:
0054 void buildCollections(
0055 edm::EventSetup const& es,
0056 const edm::Handle<edm::View<reco::CaloCluster>>& scHandle,
0057 const edm::Handle<edm::View<reco::CaloCluster>>& bcHandle,
0058 ElectronHcalHelper const& hcalHelper,
0059 const edm::Handle<reco::TrackCollection>& trkHandle,
0060 std::map<std::vector<reco::TransientTrack>, reco::CaloClusterPtr, CompareTwoTracksVectors>& allPairs,
0061 reco::ConversionCollection& outputConvPhotonCollection);
0062 void cleanCollections(const edm::Handle<edm::View<reco::CaloCluster>>& scHandle,
0063 const edm::OrphanHandle<reco::ConversionCollection>& conversionHandle,
0064 reco::ConversionCollection& outputCollection);
0065
0066 std::vector<reco::ConversionRef> solveAmbiguity(const edm::OrphanHandle<reco::ConversionCollection>& conversionHandle,
0067 reco::CaloClusterPtr const& sc);
0068
0069 float calculateMinApproachDistance(const reco::TrackRef& track1, const reco::TrackRef& track2);
0070 void getCircleCenter(const reco::TrackRef& tk, double r, double& x0, double& y0);
0071
0072 edm::EDGetTokenT<reco::TrackCollection> conversionOITrackProducer_;
0073 edm::EDGetTokenT<reco::TrackCollection> conversionIOTrackProducer_;
0074
0075 edm::EDGetTokenT<reco::TrackCaloClusterPtrAssociation> outInTrackSCAssociationCollection_;
0076 edm::EDGetTokenT<reco::TrackCaloClusterPtrAssociation> inOutTrackSCAssociationCollection_;
0077
0078 edm::EDGetTokenT<reco::TrackCollection> generalTrackProducer_;
0079
0080 edm::ESGetToken<HcalPFCuts, HcalPFCutsRcd> hcalCutsToken_;
0081 bool cutsFromDB_;
0082 HcalPFCuts const* hcalCuts_ = nullptr;
0083
0084
0085 edm::EDPutTokenT<reco::ConversionCollection> convertedPhotonCollectionPutToken_;
0086 edm::EDPutTokenT<reco::ConversionCollection> cleanedConvertedPhotonCollectionPutToken_;
0087
0088 edm::EDGetTokenT<edm::View<reco::CaloCluster>> bcBarrelCollection_;
0089 edm::EDGetTokenT<edm::View<reco::CaloCluster>> bcEndcapCollection_;
0090 edm::EDGetTokenT<edm::View<reco::CaloCluster>> scHybridBarrelProducer_;
0091 edm::EDGetTokenT<edm::View<reco::CaloCluster>> scIslandEndcapProducer_;
0092 edm::EDGetTokenT<HBHERecHitCollection> hbheRecHits_;
0093
0094 MagneticField const* magneticField_;
0095 TransientTrackBuilder const* transientTrackBuilder_;
0096
0097 edm::ESGetToken<CaloGeometry, CaloGeometryRecord> caloGeomToken_;
0098 edm::ESGetToken<MagneticField, IdealMagneticFieldRecord> mFToken_;
0099 edm::ESGetToken<TransientTrackBuilder, TransientTrackRecord> transientTrackToken_;
0100
0101 ConversionTrackPairFinder trackPairFinder_;
0102 ConversionVertexFinder vertexFinder_;
0103 std::string algoName_;
0104
0105 double hOverEConeSize_;
0106 double maxHOverE_;
0107 double minSCEt_;
0108 bool recoverOneTrackCase_;
0109 double dRForConversionRecovery_;
0110 double deltaCotCut_;
0111 double minApproachDisCut_;
0112 int maxNumOfCandidates_;
0113 bool risolveAmbiguity_;
0114
0115 std::unique_ptr<ElectronHcalHelper> hcalHelper_;
0116
0117 ConversionLikelihoodCalculator likelihoodCalc_;
0118 std::string likelihoodWeights_;
0119
0120 math::XYZPointF toFConverterP(const math::XYZPoint& val) { return math::XYZPointF(val.x(), val.y(), val.z()); }
0121
0122 math::XYZVectorF toFConverterV(const math::XYZVector& val) { return math::XYZVectorF(val.x(), val.y(), val.z()); }
0123 };
0124
0125 #include "FWCore/Framework/interface/MakerMacros.h"
0126 DEFINE_FWK_MODULE(ConvertedPhotonProducer);
0127
0128 ConvertedPhotonProducer::ConvertedPhotonProducer(const edm::ParameterSet& config)
0129 : conversionOITrackProducer_{consumes(config.getParameter<std::string>("conversionOITrackProducer"))},
0130 conversionIOTrackProducer_{consumes(config.getParameter<std::string>("conversionIOTrackProducer"))},
0131 outInTrackSCAssociationCollection_{consumes({config.getParameter<std::string>("conversionOITrackProducer"),
0132 config.getParameter<std::string>("outInTrackSCAssociation")})},
0133 inOutTrackSCAssociationCollection_{consumes({config.getParameter<std::string>("conversionIOTrackProducer"),
0134 config.getParameter<std::string>("inOutTrackSCAssociation")})},
0135
0136 generalTrackProducer_{consumes(config.getParameter<edm::InputTag>("generalTracksSrc"))},
0137 convertedPhotonCollectionPutToken_{
0138 produces<reco::ConversionCollection>(config.getParameter<std::string>("convertedPhotonCollection"))},
0139 cleanedConvertedPhotonCollectionPutToken_{
0140 produces<reco::ConversionCollection>(config.getParameter<std::string>("cleanedConvertedPhotonCollection"))},
0141
0142 bcBarrelCollection_{consumes(config.getParameter<edm::InputTag>("bcBarrelCollection"))},
0143 bcEndcapCollection_{consumes(config.getParameter<edm::InputTag>("bcEndcapCollection"))},
0144 scHybridBarrelProducer_{consumes(config.getParameter<edm::InputTag>("scHybridBarrelProducer"))},
0145 scIslandEndcapProducer_{consumes(config.getParameter<edm::InputTag>("scIslandEndcapProducer"))},
0146 hbheRecHits_{consumes(config.getParameter<edm::InputTag>("hbheRecHits"))},
0147 caloGeomToken_{esConsumes()},
0148 mFToken_{esConsumes()},
0149 transientTrackToken_{esConsumes(edm::ESInputTag("", "TransientTrackBuilder"))},
0150 vertexFinder_{config},
0151 algoName_{config.getParameter<std::string>("AlgorithmName")},
0152
0153 hOverEConeSize_{config.getParameter<double>("hOverEConeSize")},
0154 maxHOverE_{config.getParameter<double>("maxHOverE")},
0155 minSCEt_{config.getParameter<double>("minSCEt")},
0156 recoverOneTrackCase_{config.getParameter<bool>("recoverOneTrackCase")},
0157 dRForConversionRecovery_{config.getParameter<double>("dRForConversionRecovery")},
0158 deltaCotCut_{config.getParameter<double>("deltaCotCut")},
0159 minApproachDisCut_{config.getParameter<double>("minApproachDisCut")},
0160
0161 maxNumOfCandidates_{config.getParameter<int>("maxNumOfCandidates")},
0162 risolveAmbiguity_{config.getParameter<bool>("risolveConversionAmbiguity")},
0163 likelihoodWeights_{config.getParameter<std::string>("MVA_weights_location")} {
0164
0165 likelihoodCalc_.setWeightsFile(edm::FileInPath{likelihoodWeights_.c_str()}.fullPath().c_str());
0166
0167 cutsFromDB_ = config.getParameter<bool>("usePFThresholdsFromDB");
0168 if (cutsFromDB_) {
0169 hcalCutsToken_ = esConsumes<HcalPFCuts, HcalPFCutsRcd>(edm::ESInputTag("", "withTopo"));
0170 }
0171
0172 ElectronHcalHelper::Configuration cfgCone;
0173 cfgCone.hOverEConeSize = hOverEConeSize_;
0174 if (cfgCone.hOverEConeSize > 0) {
0175 cfgCone.onlyBehindCluster = false;
0176 cfgCone.checkHcalStatus = false;
0177
0178 cfgCone.hbheRecHits = hbheRecHits_;
0179
0180 cfgCone.eThresHB = config.getParameter<EgammaHcalIsolation::arrayHB>("recHitEThresholdHB");
0181 cfgCone.maxSeverityHB = config.getParameter<int>("maxHcalRecHitSeverity");
0182 cfgCone.eThresHE = config.getParameter<EgammaHcalIsolation::arrayHE>("recHitEThresholdHE");
0183 cfgCone.maxSeverityHE = cfgCone.maxSeverityHB;
0184 }
0185
0186 hcalHelper_ = std::make_unique<ElectronHcalHelper>(cfgCone, consumesCollector());
0187 }
0188
0189 void ConvertedPhotonProducer::produce(edm::Event& theEvent, const edm::EventSetup& theEventSetup) {
0190 magneticField_ = &theEventSetup.getData(mFToken_);
0191
0192
0193 transientTrackBuilder_ = &theEventSetup.getData(transientTrackToken_);
0194
0195 if (cutsFromDB_) {
0196 hcalCuts_ = &theEventSetup.getData(hcalCutsToken_);
0197 }
0198
0199
0200
0201
0202
0203 reco::ConversionCollection outputConvPhotonCollection;
0204
0205 reco::ConversionCollection cleanedConversionCollection;
0206
0207
0208 bool validBarrelSCHandle = true;
0209 auto scBarrelHandle = theEvent.getHandle(scHybridBarrelProducer_);
0210 if (!scBarrelHandle.isValid()) {
0211 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the scHybridBarrelProducer";
0212 validBarrelSCHandle = false;
0213 }
0214
0215
0216 bool validEndcapSCHandle = true;
0217 edm::Handle<edm::View<reco::CaloCluster>> scEndcapHandle;
0218 theEvent.getByToken(scIslandEndcapProducer_, scEndcapHandle);
0219 if (!scEndcapHandle.isValid()) {
0220 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the scIslandEndcapProducer";
0221 validEndcapSCHandle = false;
0222 }
0223
0224
0225 bool validTrackInputs = true;
0226 auto outInTrkHandle = theEvent.getHandle(conversionOITrackProducer_);
0227 if (!outInTrkHandle.isValid()) {
0228
0229 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the conversionOITrack "
0230 << "\n";
0231 validTrackInputs = false;
0232 }
0233
0234
0235
0236 auto outInTrkSCAssocHandle = theEvent.getHandle(outInTrackSCAssociationCollection_);
0237 if (!outInTrkSCAssocHandle.isValid()) {
0238
0239 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the outInTrackSCAssociationCollection)";
0240 validTrackInputs = false;
0241 }
0242
0243
0244 auto inOutTrkHandle = theEvent.getHandle(conversionIOTrackProducer_);
0245 if (!inOutTrkHandle.isValid()) {
0246
0247 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the conversionIOTrack "
0248 << "\n";
0249 validTrackInputs = false;
0250 }
0251
0252
0253
0254
0255 edm::Handle<reco::TrackCollection> generalTrkHandle;
0256 if (recoverOneTrackCase_) {
0257 theEvent.getByToken(generalTrackProducer_, generalTrkHandle);
0258 if (!generalTrkHandle.isValid()) {
0259
0260 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the genralTracks "
0261 << "\n";
0262 }
0263 }
0264
0265
0266 auto inOutTrkSCAssocHandle = theEvent.getHandle(inOutTrackSCAssociationCollection_);
0267 if (!inOutTrkSCAssocHandle.isValid()) {
0268
0269 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the inOutTrackSCAssociationCollection_.c_str()";
0270 validTrackInputs = false;
0271 }
0272
0273
0274 edm::Handle<edm::View<reco::CaloCluster>> bcBarrelHandle;
0275 theEvent.getByToken(bcBarrelCollection_, bcBarrelHandle);
0276 if (!bcBarrelHandle.isValid()) {
0277 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the bcBarrelCollection";
0278 }
0279
0280
0281 edm::Handle<edm::View<reco::CaloCluster>> bcEndcapHandle;
0282 theEvent.getByToken(bcEndcapCollection_, bcEndcapHandle);
0283 if (!bcEndcapHandle.isValid()) {
0284 edm::LogError("ConvertedPhotonProducer") << "Error! Can't get the bcEndcapCollection";
0285 }
0286
0287 if (validTrackInputs) {
0288
0289 std::vector<reco::TransientTrack> t_outInTrk = transientTrackBuilder_->build(outInTrkHandle);
0290 std::vector<reco::TransientTrack> t_inOutTrk = transientTrackBuilder_->build(inOutTrkHandle);
0291
0292
0293 std::map<std::vector<reco::TransientTrack>, reco::CaloClusterPtr, CompareTwoTracksVectors> allPairs;
0294 allPairs = trackPairFinder_.run(
0295 t_outInTrk, outInTrkHandle, outInTrkSCAssocHandle, t_inOutTrk, inOutTrkHandle, inOutTrkSCAssocHandle);
0296
0297
0298 hcalHelper_->beginEvent(theEvent, theEventSetup);
0299
0300 buildCollections(theEventSetup,
0301 scBarrelHandle,
0302 bcBarrelHandle,
0303 *hcalHelper_,
0304 generalTrkHandle,
0305 allPairs,
0306 outputConvPhotonCollection);
0307 buildCollections(theEventSetup,
0308 scEndcapHandle,
0309 bcEndcapHandle,
0310 *hcalHelper_,
0311 generalTrkHandle,
0312 allPairs,
0313 outputConvPhotonCollection);
0314 }
0315
0316
0317 auto const conversionHandle =
0318 theEvent.emplace(convertedPhotonCollectionPutToken_, std::move(outputConvPhotonCollection));
0319
0320
0321 if (validBarrelSCHandle)
0322 cleanCollections(scBarrelHandle, conversionHandle, cleanedConversionCollection);
0323 if (validEndcapSCHandle)
0324 cleanCollections(scEndcapHandle, conversionHandle, cleanedConversionCollection);
0325
0326 theEvent.emplace(cleanedConvertedPhotonCollectionPutToken_, std::move(cleanedConversionCollection));
0327 }
0328
0329 void ConvertedPhotonProducer::buildCollections(
0330 edm::EventSetup const& es,
0331 const edm::Handle<edm::View<reco::CaloCluster>>& scHandle,
0332 const edm::Handle<edm::View<reco::CaloCluster>>& bcHandle,
0333 ElectronHcalHelper const& hcalHelper,
0334 const edm::Handle<reco::TrackCollection>& generalTrkHandle,
0335 std::map<std::vector<reco::TransientTrack>, reco::CaloClusterPtr, CompareTwoTracksVectors>& allPairs,
0336 reco::ConversionCollection& outputConvPhotonCollection)
0337
0338 {
0339
0340 ConversionTrackEcalImpactPoint theEcalImpactPositionFinder(magneticField_);
0341
0342 reco::Conversion::ConversionAlgorithm algo = reco::Conversion::algoByName(algoName_);
0343
0344 std::vector<reco::TransientTrack> t_generalTrk;
0345 if (recoverOneTrackCase_)
0346 t_generalTrk = transientTrackBuilder_->build(generalTrkHandle);
0347
0348
0349 reco::CaloClusterPtrVector scPtrVec;
0350 for (auto const& aClus : scHandle->ptrs()) {
0351
0352 if (aClus->energy() / cosh(aClus->eta()) <= minSCEt_)
0353 continue;
0354 const reco::CaloCluster* pClus = &(*aClus);
0355 auto const* sc = dynamic_cast<const reco::SuperCluster*>(pClus);
0356 double HoE = hcalHelper.hcalESum(*sc, 0, hcalCuts_) / sc->energy();
0357 if (HoE >= maxHOverE_)
0358 continue;
0359
0360
0361 std::vector<edm::Ref<reco::TrackCollection>> trackPairRef;
0362 std::vector<math::XYZPointF> trackInnPos;
0363 std::vector<math::XYZVectorF> trackPin;
0364 std::vector<math::XYZVectorF> trackPout;
0365 float minAppDist = -99;
0366
0367
0368
0369
0370 const reco::Particle::Point vtx(0, 0, 0);
0371
0372 math::XYZVector direction = aClus->position() - vtx;
0373 math::XYZVector momentum = direction.unit() * aClus->energy();
0374 const reco::Particle::LorentzVector p4(momentum.x(), momentum.y(), momentum.z(), aClus->energy());
0375
0376 if (!allPairs.empty()) {
0377 for (auto iPair = allPairs.begin(); iPair != allPairs.end(); ++iPair) {
0378 scPtrVec.clear();
0379
0380 reco::Vertex theConversionVertex;
0381 reco::CaloClusterPtr caloPtr = iPair->second;
0382 if (!(aClus == caloPtr))
0383 continue;
0384
0385 scPtrVec.push_back(aClus);
0386
0387 std::vector<math::XYZPointF> trkPositionAtEcal = theEcalImpactPositionFinder.find(iPair->first, bcHandle);
0388 std::vector<reco::CaloClusterPtr> matchingBC = theEcalImpactPositionFinder.matchingBC();
0389
0390 minAppDist = -99;
0391 const std::string metname = "ConvertedPhotons|ConvertedPhotonProducer";
0392 if ((iPair->first).size() > 1) {
0393 try {
0394 vertexFinder_.run(iPair->first, theConversionVertex);
0395
0396 } catch (cms::Exception& e) {
0397
0398 edm::LogWarning(metname) << "cms::Exception caught in ConvertedPhotonProducer::produce\n"
0399 << e.explainSelf();
0400 }
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415 trackPairRef.clear();
0416 trackInnPos.clear();
0417 trackPin.clear();
0418 trackPout.clear();
0419
0420 for (std::vector<reco::TransientTrack>::const_iterator iTk = (iPair->first).begin();
0421 iTk != (iPair->first).end();
0422 ++iTk) {
0423
0424
0425 auto const* ttt = dynamic_cast<const reco::TrackTransientTrack*>(iTk->basicTransientTrack());
0426 reco::TrackRef myTkRef = ttt->persistentTrackRef();
0427
0428
0429 if (myTkRef->extra().isNonnull()) {
0430 trackInnPos.push_back(toFConverterP(myTkRef->innerPosition()));
0431 trackPin.push_back(toFConverterV(myTkRef->innerMomentum()));
0432 trackPout.push_back(toFConverterV(myTkRef->outerMomentum()));
0433 }
0434 trackPairRef.push_back(myTkRef);
0435 }
0436
0437
0438
0439
0440
0441 if (theConversionVertex.isValid()) {
0442
0443 }
0444
0445
0446 minAppDist = calculateMinApproachDistance(trackPairRef[0], trackPairRef[1]);
0447
0448 double like = -999.;
0449 reco::Conversion newCandidate(scPtrVec,
0450 trackPairRef,
0451 trkPositionAtEcal,
0452 theConversionVertex,
0453 matchingBC,
0454 minAppDist,
0455 trackInnPos,
0456 trackPin,
0457 trackPout,
0458 like,
0459 algo);
0460 like = likelihoodCalc_.calculateLikelihood(newCandidate);
0461
0462 newCandidate.setMVAout(like);
0463 outputConvPhotonCollection.push_back(newCandidate);
0464
0465
0466
0467 } else {
0468
0469
0470
0471 trackPairRef.clear();
0472 trackInnPos.clear();
0473 trackPin.clear();
0474 trackPout.clear();
0475 std::vector<reco::TransientTrack>::const_iterator iTk = (iPair->first).begin();
0476
0477 auto const* ttt = dynamic_cast<const reco::TrackTransientTrack*>(iTk->basicTransientTrack());
0478 reco::TrackRef myTk = ttt->persistentTrackRef();
0479 if (myTk->extra().isNonnull()) {
0480 trackInnPos.push_back(toFConverterP(myTk->innerPosition()));
0481 trackPin.push_back(toFConverterV(myTk->innerMomentum()));
0482 trackPout.push_back(toFConverterV(myTk->outerMomentum()));
0483 }
0484 trackPairRef.push_back(myTk);
0485
0486
0487 if (recoverOneTrackCase_) {
0488 float theta1 = myTk->innerMomentum().Theta();
0489 float dCot = 999.;
0490 float dCotTheta = -999.;
0491 reco::TrackRef goodRef;
0492 for (auto const& tran : t_generalTrk) {
0493 auto const* ttt = dynamic_cast<const reco::TrackTransientTrack*>(tran.basicTransientTrack());
0494 reco::TrackRef trRef = ttt->persistentTrackRef();
0495 if (trRef->charge() * myTk->charge() > 0)
0496 continue;
0497 float dEta = trRef->eta() - myTk->eta();
0498 float dPhi = trRef->phi() - myTk->phi();
0499 if (sqrt(dEta * dEta + dPhi * dPhi) > dRForConversionRecovery_)
0500 continue;
0501 float theta2 = trRef->innerMomentum().Theta();
0502 dCotTheta = 1. / tan(theta1) - 1. / tan(theta2);
0503
0504 if (fabs(dCotTheta) < dCot) {
0505 dCot = fabs(dCotTheta);
0506 goodRef = trRef;
0507 }
0508 }
0509
0510 if (goodRef.isNonnull()) {
0511 minAppDist = calculateMinApproachDistance(myTk, goodRef);
0512
0513
0514 if (fabs(dCotTheta) < deltaCotCut_ && minAppDist > minApproachDisCut_) {
0515 trackInnPos.push_back(toFConverterP(goodRef->innerPosition()));
0516 trackPin.push_back(toFConverterV(goodRef->innerMomentum()));
0517 trackPout.push_back(toFConverterV(goodRef->outerMomentum()));
0518 trackPairRef.push_back(goodRef);
0519
0520
0521
0522 try {
0523 vertexFinder_.run(iPair->first, theConversionVertex);
0524
0525 } catch (cms::Exception& e) {
0526
0527 edm::LogWarning(metname) << "cms::Exception caught in ConvertedPhotonProducer::produce\n"
0528 << e.explainSelf();
0529 }
0530 }
0531 }
0532
0533 }
0534 const double like = -999.;
0535 outputConvPhotonCollection.emplace_back(scPtrVec,
0536 trackPairRef,
0537 trkPositionAtEcal,
0538 theConversionVertex,
0539 matchingBC,
0540 minAppDist,
0541 trackInnPos,
0542 trackPin,
0543 trackPout,
0544 like,
0545 algo);
0546 auto& newCandidate = outputConvPhotonCollection.back();
0547 newCandidate.setMVAout(likelihoodCalc_.calculateLikelihood(newCandidate));
0548
0549 }
0550 }
0551 }
0552 }
0553 }
0554
0555 void ConvertedPhotonProducer::cleanCollections(const edm::Handle<edm::View<reco::CaloCluster>>& scHandle,
0556 const edm::OrphanHandle<reco::ConversionCollection>& conversionHandle,
0557 reco::ConversionCollection& outputConversionCollection) {
0558 reco::Conversion* newCandidate = nullptr;
0559 for (auto const& aClus : scHandle->ptrs()) {
0560
0561 if (aClus->energy() / cosh(aClus->eta()) <= minSCEt_)
0562 continue;
0563
0564 if (conversionHandle.isValid()) {
0565 if (risolveAmbiguity_) {
0566 std::vector<reco::ConversionRef> bestRef = solveAmbiguity(conversionHandle, aClus);
0567
0568 for (std::vector<reco::ConversionRef>::iterator iRef = bestRef.begin(); iRef != bestRef.end(); iRef++) {
0569 if (iRef->isNonnull()) {
0570 newCandidate = (*iRef)->clone();
0571 outputConversionCollection.push_back(*newCandidate);
0572 delete newCandidate;
0573 }
0574 }
0575
0576 } else {
0577 for (unsigned int icp = 0; icp < conversionHandle->size(); icp++) {
0578 reco::ConversionRef cpRef(reco::ConversionRef(conversionHandle, icp));
0579 if (!(aClus.id() == cpRef->caloCluster()[0].id() && aClus.key() == cpRef->caloCluster()[0].key()))
0580 continue;
0581 if (!cpRef->isConverted())
0582 continue;
0583 if (cpRef->nTracks() < 2)
0584 continue;
0585 newCandidate = (&(*cpRef))->clone();
0586 outputConversionCollection.push_back(*newCandidate);
0587 delete newCandidate;
0588 }
0589
0590 }
0591 }
0592 }
0593 }
0594
0595 std::vector<reco::ConversionRef> ConvertedPhotonProducer::solveAmbiguity(
0596 const edm::OrphanHandle<reco::ConversionCollection>& conversionHandle, reco::CaloClusterPtr const& scRef) {
0597 std::multimap<double, reco::ConversionRef, std::greater<double>> convMap;
0598
0599 for (unsigned int icp = 0; icp < conversionHandle->size(); icp++) {
0600 reco::ConversionRef cpRef{conversionHandle, icp};
0601
0602
0603 if (!(scRef.id() == cpRef->caloCluster()[0].id() && scRef.key() == cpRef->caloCluster()[0].key()))
0604 continue;
0605 if (!cpRef->isConverted())
0606 continue;
0607 double like = cpRef->MVAout();
0608 if (cpRef->nTracks() < 2)
0609 continue;
0610
0611 convMap.emplace(like, cpRef);
0612 }
0613
0614
0615
0616 std::vector<reco::ConversionRef> bestRefs;
0617 for (auto iMap = convMap.begin(); iMap != convMap.end(); iMap++) {
0618
0619 bestRefs.push_back(iMap->second);
0620 if (int(bestRefs.size()) == maxNumOfCandidates_)
0621 break;
0622 }
0623
0624 return bestRefs;
0625 }
0626
0627 float ConvertedPhotonProducer::calculateMinApproachDistance(const reco::TrackRef& track1,
0628 const reco::TrackRef& track2) {
0629 double x1, x2, y1, y2;
0630 double xx_1 = track1->innerPosition().x(), yy_1 = track1->innerPosition().y(), zz_1 = track1->innerPosition().z();
0631 double xx_2 = track2->innerPosition().x(), yy_2 = track2->innerPosition().y(), zz_2 = track2->innerPosition().z();
0632 double radius1 =
0633 track1->innerMomentum().Rho() / (.3 * (magneticField_->inTesla(GlobalPoint(xx_1, yy_1, zz_1)).z())) * 100;
0634 double radius2 =
0635 track2->innerMomentum().Rho() / (.3 * (magneticField_->inTesla(GlobalPoint(xx_2, yy_2, zz_2)).z())) * 100;
0636 getCircleCenter(track1, radius1, x1, y1);
0637 getCircleCenter(track2, radius2, x2, y2);
0638
0639 return std::sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) - radius1 - radius2;
0640 }
0641
0642 void ConvertedPhotonProducer::getCircleCenter(const reco::TrackRef& tk, double r, double& x0, double& y0) {
0643 double x1, y1, phi;
0644 x1 = tk->innerPosition().x();
0645 y1 = tk->innerPosition().y();
0646 phi = tk->innerMomentum().phi();
0647 const int charge = tk->charge();
0648 x0 = x1 + r * sin(phi) * charge;
0649 y0 = y1 - r * cos(phi) * charge;
0650 }