00001
00002
00003
00004
00005
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <memory>
00023 #include <map>
00024
00025
00026 #include "RecoEgamma/EgammaPhotonProducers/interface/TrackerOnlyConversionProducer.h"
00027 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00028 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00029 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00030 #include "DataFormats/TrajectoryState/interface/PTrajectoryStateOnDet.h"
00031
00032 #include "TrackingTools/GeomPropagators/interface/AnalyticalPropagator.h"
00033 #include "TrackingTools/MaterialEffects/interface/PropagatorWithMaterial.h"
00034 #include "DataFormats/TrackingRecHit/interface/TrackingRecHit.h"
00035 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00036
00037 #include "TrackingTools/TransientTrack/interface/TrackTransientTrack.h"
00038 #include "DataFormats/EgammaTrackReco/interface/ConversionTrack.h"
00039
00040
00041 #include "DataFormats/VertexReco/interface/Vertex.h"
00042 #include "DataFormats/VertexReco/interface/VertexFwd.h"
00043 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
00044 #include "DataFormats/GsfTrackReco/interface/GsfTrackFwd.h"
00045
00046 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
00047 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
00048 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
00049
00050 #include "TrackingTools/PatternTools/interface/ClosestApproachInRPhi.h"
00051 #include "TrackingTools/PatternTools/interface/TwoTrackMinimumDistance.h"
00052
00053 #include "CommonTools/Statistics/interface/ChiSquaredProbability.h"
00054 #include "DataFormats/Math/interface/deltaPhi.h"
00055 #include "RecoEgamma/EgammaPhotonAlgos/interface/ConversionVertexFinder.h"
00056 #include "TrackingTools/PatternTools/interface/Trajectory.h"
00057 #include "RecoEgamma/EgammaPhotonAlgos/interface/TangentApproachInRPhi.h"
00058 #include "RecoEgamma/EgammaPhotonAlgos/interface/ConversionHitChecker.h"
00059
00060
00061
00062 #include "RecoVertex/KinematicFitPrimitives/interface/ParticleMass.h"
00063 #include "RecoVertex/KinematicFitPrimitives/interface/MultiTrackKinematicConstraint.h"
00064 #include <RecoVertex/KinematicFitPrimitives/interface/KinematicParticleFactoryFromTransientTrack.h>
00065 #include "RecoVertex/KinematicFit/interface/KinematicConstrainedVertexFitter.h"
00066 #include "RecoVertex/KinematicFit/interface/TwoTrackMassKinematicConstraint.h"
00067 #include "RecoVertex/KinematicFit/interface/KinematicParticleVertexFitter.h"
00068 #include "RecoVertex/KinematicFit/interface/KinematicParticleFitter.h"
00069 #include "RecoVertex/KinematicFit/interface/MassKinematicConstraint.h"
00070 #include "RecoVertex/KinematicFit/interface/ColinearityKinematicConstraint.h"
00071
00072
00073
00074 TrackerOnlyConversionProducer::TrackerOnlyConversionProducer(const edm::ParameterSet& iConfig):
00075 theVertexFinder_(0)
00076
00077 {
00078 algoName_ = iConfig.getParameter<std::string>( "AlgorithmName" );
00079
00080 src_ = iConfig.getParameter<edm::InputTag>("src");
00081 maxNumOfTrackInPU_ = iConfig.getParameter<int>("maxNumOfTrackInPU");
00082 allowTrackBC_ = iConfig.getParameter<bool>("AllowTrackBC");
00083 allowD0_ = iConfig.getParameter<bool>("AllowD0");
00084 allowDeltaPhi_ = iConfig.getParameter<bool>("AllowDeltaPhi");
00085 allowDeltaCot_ = iConfig.getParameter<bool>("AllowDeltaCot");
00086 allowMinApproach_ = iConfig.getParameter<bool>("AllowMinApproach");
00087 allowOppCharge_ = iConfig.getParameter<bool>("AllowOppCharge");
00088
00089 allowVertex_ = iConfig.getParameter<bool>("AllowVertex");
00090
00091 halfWayEta_ = iConfig.getParameter<double>("HalfwayEta");
00092
00093 if (allowD0_)
00094 d0Cut_ = iConfig.getParameter<double>("d0");
00095
00096 usePvtx_ = iConfig.getParameter<bool>("UsePvtx");
00097
00098 if (usePvtx_){
00099 vertexProducer_ = iConfig.getParameter<std::string>("primaryVertexProducer");
00100 }
00101
00102 if (allowTrackBC_) {
00103
00104 dEtaTkBC_ = iConfig.getParameter<double>("dEtaTrackBC");
00105 dPhiTkBC_ = iConfig.getParameter<double>("dPhiTrackBC");
00106
00107 bcBarrelCollection_ = iConfig.getParameter<edm::InputTag>("bcBarrelCollection");
00108 bcEndcapCollection_ = iConfig.getParameter<edm::InputTag>("bcEndcapCollection");
00109
00110 energyBC_ = iConfig.getParameter<double>("EnergyBC");
00111 energyTotalBC_ = iConfig.getParameter<double>("EnergyTotalBC");
00112
00113 }
00114
00115
00116
00117
00118 maxChi2Left_ = iConfig.getParameter<double>("MaxChi2Left");
00119 maxChi2Right_ = iConfig.getParameter<double>("MaxChi2Right");
00120 minHitsLeft_ = iConfig.getParameter<int>("MinHitsLeft");
00121 minHitsRight_ = iConfig.getParameter<int>("MinHitsRight");
00122
00123
00124 if (allowDeltaCot_)
00125 deltaCotTheta_ = iConfig.getParameter<double>("DeltaCotTheta");
00126 if (allowDeltaPhi_)
00127 deltaPhi_ = iConfig.getParameter<double>("DeltaPhi");
00128 if (allowMinApproach_){
00129 minApproachLow_ = iConfig.getParameter<double>("MinApproachLow");
00130 minApproachHigh_ = iConfig.getParameter<double>("MinApproachHigh");
00131 }
00132
00133
00134 allowSingleLeg_ = iConfig.getParameter<bool>("AllowSingleLeg");
00135 rightBC_ = iConfig.getParameter<bool>("AllowRightBC");
00136
00137
00138 dzCut_ = iConfig.getParameter<double>("dz");
00139
00140 r_cut = iConfig.getParameter<double>("rCut");
00141 vtxChi2_ = iConfig.getParameter<double>("vtxChi2");
00142
00143
00144 theVertexFinder_ = new ConversionVertexFinder ( iConfig );
00145
00146 thettbuilder_ = 0;
00147
00148
00149 ConvertedPhotonCollection_ = iConfig.getParameter<std::string>("convertedPhotonCollection");
00150
00151 produces< reco::ConversionCollection >(ConvertedPhotonCollection_);
00152
00153 }
00154
00155
00156 TrackerOnlyConversionProducer::~TrackerOnlyConversionProducer()
00157 {
00158
00159
00160
00161 delete theVertexFinder_;
00162 }
00163
00164
00165
00166 void
00167 TrackerOnlyConversionProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup)
00168 {
00169 using namespace edm;
00170
00171 reco::ConversionCollection outputConvPhotonCollection;
00172 std::auto_ptr<reco::ConversionCollection> outputConvPhotonCollection_p(new reco::ConversionCollection);
00173
00174
00175
00176
00177 edm::Handle<reco::ConversionTrackCollection> trackCollectionHandle;
00178 iEvent.getByLabel(src_,trackCollectionHandle);
00179
00180 edm::Handle<edm::View<reco::CaloCluster> > bcBarrelHandle;
00181 edm::Handle<edm::View<reco::CaloCluster> > bcEndcapHandle;
00182 if (allowTrackBC_){
00183 iEvent.getByLabel( bcBarrelCollection_, bcBarrelHandle);
00184 iEvent.getByLabel( bcEndcapCollection_, bcEndcapHandle);
00185 }
00186
00187 edm::Handle<reco::VertexCollection> vertexHandle;
00188 reco::VertexCollection vertexCollection;
00189 if (usePvtx_){
00190 iEvent.getByLabel(vertexProducer_, vertexHandle);
00191 if (!vertexHandle.isValid()) {
00192 edm::LogError("TrackerOnlyConversionProducer") << "Error! Can't get the product primary Vertex Collection "<< "\n";
00193 usePvtx_ = false;
00194 }
00195 if (usePvtx_)
00196 vertexCollection = *(vertexHandle.product());
00197 }
00198
00199 edm::ESHandle<TransientTrackBuilder> hTransientTrackBuilder;
00200 iSetup.get<TransientTrackRecord>().get("TransientTrackBuilder",hTransientTrackBuilder);
00201 thettbuilder_ = hTransientTrackBuilder.product();
00202
00203 reco::Vertex the_pvtx;
00204
00205 if (!vertexCollection.empty())
00206 the_pvtx = *(vertexCollection.begin());
00207
00208 if (trackCollectionHandle->size()> maxNumOfTrackInPU_ ){
00209 iEvent.put( outputConvPhotonCollection_p, ConvertedPhotonCollection_);
00210 return;
00211 }
00212
00213
00214
00215 std::multimap<double, reco::CaloClusterPtr> basicClusterPtrs;
00216 edm::Handle<edm::View<reco::CaloCluster> > bcHandle = bcBarrelHandle;
00217
00218 if (allowTrackBC_){
00219 for (unsigned jj = 0; jj < 2; ++jj ){
00220 for (unsigned ii = 0; ii < bcHandle->size(); ++ii ) {
00221 if (bcHandle->ptrAt(ii)->energy()>energyBC_)
00222 basicClusterPtrs.insert(std::make_pair(bcHandle->ptrAt(ii)->position().eta(), bcHandle->ptrAt(ii)));
00223 }
00224 bcHandle = bcEndcapHandle;
00225 }
00226 }
00227
00228 buildCollection( iEvent, iSetup, *trackCollectionHandle.product(), basicClusterPtrs, the_pvtx, outputConvPhotonCollection);
00229
00230 outputConvPhotonCollection_p->assign(outputConvPhotonCollection.begin(), outputConvPhotonCollection.end());
00231 iEvent.put( outputConvPhotonCollection_p, ConvertedPhotonCollection_);
00232
00233 }
00234
00235
00236
00237
00238 void TrackerOnlyConversionProducer::buildCollection(edm::Event& iEvent, const edm::EventSetup& iSetup,
00239 const reco::ConversionTrackCollection& allTracks,
00240 const std::multimap<double, reco::CaloClusterPtr>& basicClusterPtrs,
00241 const reco::Vertex& the_pvtx,
00242 reco::ConversionCollection & outputConvPhotonCollection){
00243
00244
00245 edm::ESHandle<TrackerGeometry> trackerGeomHandle;
00246 edm::ESHandle<MagneticField> magFieldHandle;
00247 iSetup.get<TrackerDigiGeometryRecord>().get( trackerGeomHandle );
00248 iSetup.get<IdealMagneticFieldRecord>().get( magFieldHandle );
00249
00250 const TrackerGeometry* trackerGeom = trackerGeomHandle.product();
00251 const MagneticField* magField = magFieldHandle.product();;
00252
00253 std::vector<math::XYZPoint> trackImpactPosition;
00254 trackImpactPosition.reserve(allTracks.size());
00255 std::vector<bool> trackValidECAL;
00256 trackValidECAL.assign(allTracks.size(), false);
00257
00258 std::vector<reco::CaloClusterPtr> trackMatchedBC;
00259 reco::CaloClusterPtr empty_bc;
00260 trackMatchedBC.assign(allTracks.size(), empty_bc);
00261
00262 std::vector<int> bcHandleId;
00263 bcHandleId.assign(allTracks.size(), -1);
00264
00265 std::multimap<double, int> trackInnerEta;
00266
00267
00268 ConversionHitChecker hitChecker;
00269
00270
00271
00272 for (reco::ConversionTrackCollection::const_iterator tk_ref = allTracks.begin(); tk_ref != allTracks.end(); ++tk_ref ){
00273 const reco::Track* tk = tk_ref->trackRef().get() ;
00274
00275
00276 trackInnerEta.insert(std::make_pair(tk->innerMomentum().eta(), tk_ref-allTracks.begin()));
00277
00278 if (allowTrackBC_){
00279
00280 math::XYZPoint ew;
00281 if ( getTrackImpactPosition(tk, trackerGeom, magField, ew) ){
00282 trackImpactPosition.push_back(ew);
00283
00284 reco::CaloClusterPtr closest_bc;
00285
00286 if ( getMatchedBC(basicClusterPtrs, ew, closest_bc) ){
00287 trackMatchedBC[tk_ref-allTracks.begin()] = closest_bc;
00288 trackValidECAL[tk_ref-allTracks.begin()] = true;
00289 bcHandleId[tk_ref-allTracks.begin()] = (fabs(closest_bc->position().eta())>1.479)?1:0;
00290 }
00291 } else {
00292 trackImpactPosition.push_back(ew);
00293 continue;
00294 }
00295
00296 }
00297 }
00298
00299
00300
00301
00302
00303
00304
00305 for(reco::ConversionTrackCollection::const_iterator ll = allTracks.begin(); ll != allTracks.end(); ++ ll ) {
00306 bool track1HighPurity=true;
00307
00308 const edm::RefToBase<reco::Track> & left = ll->trackRef();
00309
00310
00311
00312
00313 reco::TransientTrack ttk_l;
00314 if (dynamic_cast<const reco::GsfTrack*>(left.get())) {
00315 ttk_l = thettbuilder_->build(left.castTo<reco::GsfTrackRef>());
00316 }
00317 else {
00318 ttk_l = thettbuilder_->build(left.castTo<reco::TrackRef>());
00319 }
00320
00321
00322 if ((allowTrackBC_ && !trackValidECAL[ll-allTracks.begin()]) )
00323 continue;
00324
00325 if (the_pvtx.isValid()){
00326 if (!(trackD0Cut(left, the_pvtx))) track1HighPurity=false;
00327 } else {
00328 if (!(trackD0Cut(left))) track1HighPurity=false;
00329 }
00330
00331 std::vector<int> right_candidates;
00332 std::vector<double> right_candidate_theta, right_candidate_approach;
00333 std::vector<std::pair<bool, reco::Vertex> > vertex_candidates;
00334
00335
00336 for (reco::ConversionTrackCollection::const_iterator rr = ll+1; rr != allTracks.end(); ++ rr ) {
00337 bool track2HighPurity = true;
00338 bool highPurityPair = true;
00339
00340 const edm::RefToBase<reco::Track> & right = rr->trackRef();
00341
00342
00343 reco::TransientTrack ttk_r;
00344 if (dynamic_cast<const reco::GsfTrack*>(right.get())) {
00345 ttk_r = thettbuilder_->build(right.castTo<reco::GsfTrackRef>());
00346 }
00347 else {
00348 ttk_r = thettbuilder_->build(right.castTo<reco::TrackRef>());
00349 }
00350
00351
00352
00353
00354
00355
00356 if ( allowOppCharge_ && (left->charge()*right->charge() > 0) )
00357 continue;
00358
00359 if ( (allowTrackBC_ && !trackValidECAL[rr-allTracks.begin()] && rightBC_) )
00360 continue;
00361
00362
00363 double approachDist = -999.;
00364
00365 if (!preselectTrackPair(ttk_l,ttk_r, approachDist) && left->algo()!=29 && right->algo()!=29) {
00366 continue;
00367 }
00368
00369
00370 reco::Vertex theConversionVertex;
00371 bool goodVertex = checkVertex(ttk_l, ttk_r, magField, theConversionVertex);
00372
00373
00374 if (!goodVertex) {
00375 continue;
00376 }
00377
00378
00379
00380
00381 if ( !( (trackQualityFilter(left, true) && trackQualityFilter(right, false))
00382 || (trackQualityFilter(left, false) && trackQualityFilter(right, true)) ) ) {
00383 highPurityPair=false;
00384 }
00385
00386 if (the_pvtx.isValid()){
00387 if (!(trackD0Cut(right, the_pvtx))) track2HighPurity=false;
00388 } else {
00389 if (!(trackD0Cut(right))) track2HighPurity=false;
00390 }
00391
00392
00393 const std::pair<edm::RefToBase<reco::Track>, reco::CaloClusterPtr> the_left = std::make_pair(left, trackMatchedBC[ll-allTracks.begin()]);
00394 const std::pair<edm::RefToBase<reco::Track>, reco::CaloClusterPtr> the_right = std::make_pair(right, trackMatchedBC[rr-allTracks.begin()]);
00395
00396
00397
00398
00399 highPurityPair= highPurityPair && track1HighPurity && track2HighPurity && checkTrackPair(the_left, the_right) ;
00400 highPurityPair = highPurityPair && goodVertex && checkPhi(left, right, trackerGeom, magField, theConversionVertex) ;
00401
00402
00403 std::vector<edm::RefToBase<reco::Track> > trackPairRef;
00404 trackPairRef.push_back(left);
00405 trackPairRef.push_back(right);
00406
00407 std::vector<math::XYZVector> trackPin;
00408 std::vector<math::XYZVector> trackPout;
00409 std::vector<math::XYZPoint> trackInnPos;
00410 std::vector<uint8_t> nHitsBeforeVtx;
00411 std::vector<Measurement1DFloat> dlClosestHitToVtx;
00412
00413 if (left->extra().isNonnull() && right->extra().isNonnull()){
00414 trackInnPos.push_back( left->innerPosition());
00415 trackInnPos.push_back( right->innerPosition());
00416 trackPin.push_back(left->innerMomentum());
00417 trackPin.push_back(right->innerMomentum());
00418 trackPout.push_back(left->outerMomentum());
00419 trackPout.push_back(right->outerMomentum());
00420 }
00421
00422 if (ll->trajRef().isNonnull() && rr->trajRef().isNonnull()) {
00423 std::pair<uint8_t,Measurement1DFloat> leftWrongHits = hitChecker.nHitsBeforeVtx(*ll->trajRef().get(),theConversionVertex);
00424 std::pair<uint8_t,Measurement1DFloat> rightWrongHits = hitChecker.nHitsBeforeVtx(*rr->trajRef().get(),theConversionVertex);
00425 nHitsBeforeVtx.push_back(leftWrongHits.first);
00426 nHitsBeforeVtx.push_back(rightWrongHits.first);
00427 dlClosestHitToVtx.push_back(leftWrongHits.second);
00428 dlClosestHitToVtx.push_back(rightWrongHits.second);
00429 }
00430
00431 uint8_t nSharedHits = hitChecker.nSharedHits(*left.get(),*right.get());
00432
00433 reco::CaloClusterPtrVector scPtrVec;
00434
00435 if (theConversionVertex.isValid()){
00436 const float chi2Prob = ChiSquaredProbability(theConversionVertex.chi2(), theConversionVertex.ndof());
00437 if (chi2Prob<vtxChi2_) highPurityPair=false;
00438 }
00439
00440
00441 std::vector<math::XYZPoint> trkPositionAtEcal;
00442 std::vector<reco::CaloClusterPtr> matchingBC;
00443
00444 if (allowTrackBC_){
00445 const int lbc_handle = bcHandleId[ll-allTracks.begin()],
00446 rbc_handle = bcHandleId[rr-allTracks.begin()];
00447
00448 trkPositionAtEcal.push_back(trackImpactPosition[ll-allTracks.begin()]);
00449 if (trackValidECAL[rr-allTracks.begin()])
00450 trkPositionAtEcal.push_back(trackImpactPosition[rr-allTracks.begin()]);
00451
00452 matchingBC.push_back(trackMatchedBC[ll-allTracks.begin()]);
00453 scPtrVec.push_back(trackMatchedBC[ll-allTracks.begin()]);
00454 if (trackValidECAL[rr-allTracks.begin()]){
00455 matchingBC.push_back(trackMatchedBC[rr-allTracks.begin()]);
00456 if (!(trackMatchedBC[rr-allTracks.begin()] == trackMatchedBC[ll-allTracks.begin()])
00457 && lbc_handle == rbc_handle )
00458 scPtrVec.push_back(trackMatchedBC[rr-allTracks.begin()]);
00459 }
00460 }
00461 const float minAppDist = approachDist;
00462
00463 reco::Conversion::ConversionAlgorithm algo = reco::Conversion::algoByName(algoName_);
00464 float dummy=0;
00465 reco::Conversion newCandidate(scPtrVec, trackPairRef, trkPositionAtEcal, theConversionVertex, matchingBC, minAppDist, trackInnPos, trackPin, trackPout, nHitsBeforeVtx, dlClosestHitToVtx, nSharedHits, dummy, algo );
00466 newCandidate.setQuality(reco::Conversion::highPurity, highPurityPair);
00467
00468 bool generalTracksOnly = ll->isTrackerOnly() && rr->isTrackerOnly() && !dynamic_cast<const reco::GsfTrack*>(ll->trackRef().get()) && !dynamic_cast<const reco::GsfTrack*>(rr->trackRef().get());
00469 bool arbitratedEcalSeeded = ll->isArbitratedEcalSeeded() && rr->isArbitratedEcalSeeded();
00470 bool arbitratedMerged = ll->isArbitratedMerged() && rr->isArbitratedMerged();
00471 bool arbitratedMergedEcalGeneral = ll->isArbitratedMergedEcalGeneral() && rr->isArbitratedMergedEcalGeneral();
00472
00473 newCandidate.setQuality(reco::Conversion::generalTracksOnly, generalTracksOnly);
00474 newCandidate.setQuality(reco::Conversion::arbitratedEcalSeeded, arbitratedEcalSeeded);
00475 newCandidate.setQuality(reco::Conversion::arbitratedMerged, arbitratedMerged);
00476 newCandidate.setQuality(reco::Conversion::arbitratedMergedEcalGeneral, arbitratedMergedEcalGeneral);
00477
00478 outputConvPhotonCollection.push_back(newCandidate);
00479
00480 }
00481
00482 }
00483
00484
00485
00486
00487
00488
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499 inline bool TrackerOnlyConversionProducer::trackQualityFilter(const edm::RefToBase<reco::Track>& ref, bool isLeft){
00500 bool pass = true;
00501 if (isLeft){
00502 pass = (ref->normalizedChi2() < maxChi2Left_ && ref->found() >= minHitsLeft_);
00503 } else {
00504 pass = (ref->normalizedChi2() < maxChi2Right_ && ref->found() >= minHitsRight_);
00505 }
00506
00507 return pass;
00508 }
00509
00510 inline bool TrackerOnlyConversionProducer::trackD0Cut(const edm::RefToBase<reco::Track>& ref){
00511
00512 return ((!allowD0_) || !(ref->d0()*ref->charge()/ref->d0Error()<d0Cut_));
00513 }
00514
00515 inline bool TrackerOnlyConversionProducer::trackD0Cut(const edm::RefToBase<reco::Track>& ref, const reco::Vertex& the_pvtx){
00516
00517 return ((!allowD0_) || !(-ref->dxy(the_pvtx.position())*ref->charge()/ref->dxyError()<d0Cut_));
00518 }
00519
00520
00521 bool TrackerOnlyConversionProducer::getTrackImpactPosition(const reco::Track* tk_ref,
00522 const TrackerGeometry* trackerGeom, const MagneticField* magField,
00523 math::XYZPoint& ew){
00524
00525 PropagatorWithMaterial propag( alongMomentum, 0.000511, magField );
00526 TrajectoryStateTransform transformer;
00527 ReferenceCountingPointer<Surface> ecalWall(
00528 new BoundCylinder( GlobalPoint(0.,0.,0.), TkRotation<float>(),
00529 SimpleCylinderBounds( 129, 129, -320.5, 320.5 ) ) );
00530 const float epsilon = 0.001;
00531 Surface::RotationType rot;
00532 const float barrelRadius = 129.f;
00533 const float barrelHalfLength = 270.9f;
00534 const float endcapRadius = 171.1f;
00535 const float endcapZ = 320.5f;
00536 ReferenceCountingPointer<BoundCylinder> theBarrel_(new BoundCylinder( Surface::PositionType(0,0,0), rot,
00537 SimpleCylinderBounds( barrelRadius-epsilon, barrelRadius+epsilon, -barrelHalfLength, barrelHalfLength)));
00538 ReferenceCountingPointer<BoundDisk> theNegativeEtaEndcap_(
00539 new BoundDisk( Surface::PositionType( 0, 0, -endcapZ), rot,
00540 SimpleDiskBounds( 0, endcapRadius, -epsilon, epsilon)));
00541 ReferenceCountingPointer<BoundDisk> thePositiveEtaEndcap_(
00542 new BoundDisk( Surface::PositionType( 0, 0, endcapZ), rot,
00543 SimpleDiskBounds( 0, endcapRadius, -epsilon, epsilon)));
00544
00545
00546 const TrajectoryStateOnSurface myTSOS = transformer.outerStateOnSurface(*tk_ref, *trackerGeom, magField);
00547 TrajectoryStateOnSurface stateAtECAL;
00548 stateAtECAL = propag.propagate(myTSOS, *theBarrel_);
00549 if (!stateAtECAL.isValid() || ( stateAtECAL.isValid() && fabs(stateAtECAL.globalPosition().eta() ) >1.479 ) ) {
00550
00551 if (myTSOS.globalPosition().eta() > 0.) {
00552 stateAtECAL = propag.propagate(myTSOS, *thePositiveEtaEndcap_);
00553 } else {
00554 stateAtECAL = propag.propagate(myTSOS, *theNegativeEtaEndcap_);
00555 }
00556 }
00557 if (stateAtECAL.isValid()){
00558 ew = stateAtECAL.globalPosition();
00559 return true;
00560 }
00561 else
00562 return false;
00563 }
00564
00565 bool TrackerOnlyConversionProducer::getMatchedBC(const std::multimap<double, reco::CaloClusterPtr>& bcMap,
00566 const math::XYZPoint& trackImpactPosition,
00567 reco::CaloClusterPtr& closestBC){
00568 const double track_eta = trackImpactPosition.eta();
00569 const double track_phi = trackImpactPosition.phi();
00570
00571 double min_eta = 999., min_phi = 999.;
00572 reco::CaloClusterPtr closest_bc;
00573 for (std::multimap<double, reco::CaloClusterPtr>::const_iterator bc = bcMap.lower_bound(track_eta - halfWayEta_);
00574 bc != bcMap.upper_bound(track_eta + halfWayEta_); ++bc){
00575 const reco::CaloClusterPtr& ebc = bc->second;
00576 const double delta_eta = track_eta-(ebc->position().eta());
00577 const double delta_phi = reco::deltaPhi(track_phi, (ebc->position().phi()));
00578 if (fabs(delta_eta)<dEtaTkBC_ && fabs(delta_phi)<dPhiTkBC_){
00579 if (fabs(min_eta)>fabs(delta_eta) && fabs(min_phi)>fabs(delta_phi)){
00580 min_eta = delta_eta;
00581 min_phi = delta_phi;
00582 closest_bc = bc->second;
00583
00584 }
00585 }
00586 }
00587
00588 if (min_eta < 999.){
00589 closestBC = closest_bc;
00590 return true;
00591 } else
00592 return false;
00593 }
00594
00595 bool TrackerOnlyConversionProducer::getMatchedBC(const reco::CaloClusterPtrVector& bcMap,
00596 const math::XYZPoint& trackImpactPosition,
00597 reco::CaloClusterPtr& closestBC){
00598 const double track_eta = trackImpactPosition.eta();
00599 const double track_phi = trackImpactPosition.phi();
00600
00601 double min_eta = 999., min_phi = 999.;
00602 reco::CaloClusterPtr closest_bc;
00603 for (reco::CaloClusterPtrVector::const_iterator bc = bcMap.begin();
00604 bc != bcMap.end(); ++bc){
00605 const reco::CaloClusterPtr& ebc = (*bc);
00606 const double delta_eta = track_eta-(ebc->position().eta());
00607 const double delta_phi = reco::deltaPhi(track_phi, (ebc->position().phi()));
00608 if (fabs(delta_eta)<dEtaTkBC_ && fabs(delta_phi)<dPhiTkBC_){
00609 if (fabs(min_eta)>fabs(delta_eta) && fabs(min_phi)>fabs(delta_phi)){
00610 min_eta = delta_eta;
00611 min_phi = delta_phi;
00612 closest_bc = ebc;
00613
00614 }
00615 }
00616 }
00617
00618 if (min_eta < 999.){
00619 closestBC = closest_bc;
00620 return true;
00621 } else
00622 return false;
00623 }
00624
00625
00626 bool TrackerOnlyConversionProducer::checkPhi(const edm::RefToBase<reco::Track>& tk_l, const edm::RefToBase<reco::Track>& tk_r,
00627 const TrackerGeometry* trackerGeom, const MagneticField* magField,
00628 const reco::Vertex& vtx){
00629 if (!allowDeltaPhi_)
00630 return true;
00631
00632
00633
00634 if (tk_l->extra().isNonnull() && tk_r->extra().isNonnull()){
00635 double iphi1 = tk_l->innerMomentum().phi(), iphi2 = tk_r->innerMomentum().phi();
00636 if (vtx.isValid()){
00637 PropagatorWithMaterial propag( anyDirection, 0.000511, magField );
00638 TrajectoryStateTransform transformer;
00639 double recoPhoR = vtx.position().Rho();
00640 Surface::RotationType rot;
00641 ReferenceCountingPointer<BoundCylinder> theBarrel_(new BoundCylinder( Surface::PositionType(0,0,0), rot,
00642 SimpleCylinderBounds( recoPhoR-0.001, recoPhoR+0.001, -fabs(vtx.position().z()), fabs(vtx.position().z()))));
00643 ReferenceCountingPointer<BoundDisk> theDisk_(
00644 new BoundDisk( Surface::PositionType( 0, 0, vtx.position().z()), rot,
00645 SimpleDiskBounds( 0, recoPhoR, -0.001, 0.001)));
00646
00647 const TrajectoryStateOnSurface myTSOS1 = transformer.innerStateOnSurface(*tk_l, *trackerGeom, magField);
00648 const TrajectoryStateOnSurface myTSOS2 = transformer.innerStateOnSurface(*tk_r, *trackerGeom, magField);
00649 TrajectoryStateOnSurface stateAtVtx1, stateAtVtx2;
00650 stateAtVtx1 = propag.propagate(myTSOS1, *theBarrel_);
00651 if (!stateAtVtx1.isValid() ) {
00652 stateAtVtx1 = propag.propagate(myTSOS1, *theDisk_);
00653 }
00654 if (stateAtVtx1.isValid()){
00655 iphi1 = stateAtVtx1.globalDirection().phi();
00656 }
00657 stateAtVtx2 = propag.propagate(myTSOS2, *theBarrel_);
00658 if (!stateAtVtx2.isValid() ) {
00659 stateAtVtx2 = propag.propagate(myTSOS2, *theDisk_);
00660 }
00661 if (stateAtVtx2.isValid()){
00662 iphi2 = stateAtVtx2.globalDirection().phi();
00663 }
00664 }
00665 const double dPhi = reco::deltaPhi(iphi1, iphi2);
00666 return (fabs(dPhi) < deltaPhi_);
00667 } else {
00668 return true;
00669 }
00670 }
00671
00672 bool TrackerOnlyConversionProducer::preselectTrackPair(const reco::TransientTrack &ttk_l, const reco::TransientTrack &ttk_r,
00673 double& appDist) {
00674
00675
00676 double dCotTheta = 1./tan(ttk_l.track().innerMomentum().theta()) - 1./tan(ttk_r.track().innerMomentum().theta());
00677 if (allowDeltaCot_ && (std::abs(dCotTheta) > deltaCotTheta_)) {
00678 return false;
00679 }
00680
00681
00682 ClosestApproachInRPhi closest;
00683 closest.calculate(ttk_l.innermostMeasurementState(),ttk_r.innermostMeasurementState());
00684 if (!closest.status()) {
00685 return false;
00686 }
00687
00688 if (closest.crossingPoint().perp() < r_cut) {
00689 return false;
00690 }
00691
00692
00693
00694 TangentApproachInRPhi tangent;
00695 tangent.calculate(ttk_l.innermostMeasurementState(),ttk_r.innermostMeasurementState());
00696 if (!tangent.status()) {
00697 return false;
00698 }
00699
00700 GlobalPoint tangentPoint = tangent.crossingPoint();
00701 double rho = tangentPoint.perp();
00702
00703
00704 if (rho > 120.0) {
00705 return false;
00706 }
00707
00708 if (std::abs(tangentPoint.z()) > 300.0) {
00709 return false;
00710 }
00711
00712 std::pair<GlobalTrajectoryParameters,GlobalTrajectoryParameters> trajs = tangent.trajectoryParameters();
00713
00714
00715 if (std::abs(trajs.first.position().z() - trajs.second.position().z()) > dzCut_) {
00716 return false;
00717 }
00718
00719
00720 float minApproach = tangent.perpdist();
00721 appDist = minApproach;
00722
00723 if (allowMinApproach_ && (minApproach < minApproachLow_ || minApproach > minApproachHigh_) ) {
00724 return false;
00725 }
00726
00727 return true;
00728
00729
00730 }
00731
00732 bool TrackerOnlyConversionProducer::checkTrackPair(const std::pair<edm::RefToBase<reco::Track>, reco::CaloClusterPtr>& ll,
00733 const std::pair<edm::RefToBase<reco::Track>, reco::CaloClusterPtr>& rr){
00734
00735 const reco::CaloClusterPtr& bc_l = ll.second;
00736 const reco::CaloClusterPtr& bc_r = rr.second;
00737
00738
00739 if (allowTrackBC_){
00740
00741 double total_e_bc = 0;
00742 if (bc_l.isNonnull()) total_e_bc += bc_l->energy();
00743 if (rightBC_)
00744 if (bc_r.isNonnull())
00745 total_e_bc += bc_r->energy();
00746
00747 if (total_e_bc < energyTotalBC_) return false;
00748 }
00749
00750 return true;
00751 }
00752
00753
00754
00755
00756 bool TrackerOnlyConversionProducer::checkVertex(const reco::TransientTrack &ttk_l, const reco::TransientTrack &ttk_r,
00757 const MagneticField* magField,
00758 reco::Vertex& the_vertex){
00759 bool found = false;
00760
00761 std::vector<reco::TransientTrack> pair;
00762 pair.push_back(ttk_l);
00763 pair.push_back(ttk_r);
00764
00765 found = theVertexFinder_->run(pair, the_vertex);
00766
00767
00768
00769 return found;
00770 }
00771
00772