00001
00002
00003
00004
00005
00013
00014
00015
00016
00017
00018
00019
00020 #include "RecoVertex/V0Producer/interface/V0Fitter.h"
00021 #include "PhysicsTools/CandUtils/interface/AddFourMomenta.h"
00022
00023 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
00024 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
00025 #include "Geometry/CommonDetUnit/interface/GlobalTrackingGeometry.h"
00026
00027 #include <typeinfo>
00028
00029
00030
00031 const double piMass = 0.13957018;
00032 const double piMassSquared = piMass*piMass;
00033
00034
00035 V0Fitter::V0Fitter(const edm::ParameterSet& theParameters,
00036 const edm::Event& iEvent, const edm::EventSetup& iSetup) :
00037 recoAlg(theParameters.getUntrackedParameter("trackRecoAlgorithm",
00038 std::string("ctfWithMaterialTracks"))) {
00039 using std::string;
00040
00041
00042
00043
00044
00045 useRefTrax = theParameters.getParameter<bool>(string("useSmoothing"));
00046 storeRefTrax = theParameters.getParameter<bool>(
00047 string("storeSmoothedTracksInRecoVertex"));
00048
00049
00050 doKshorts = theParameters.getParameter<bool>(string("selectKshorts"));
00051
00052 doLambdas = theParameters.getParameter<bool>(string("selectLambdas"));
00053
00054
00055 doPostFitCuts = theParameters.getParameter<bool>(string("doPostFitCuts"));
00056 doTkQualCuts =
00057 theParameters.getParameter<bool>(string("doTrackQualityCuts"));
00058
00059
00060 chi2Cut = theParameters.getParameter<double>(string("vtxChi2Cut"));
00061 tkChi2Cut = theParameters.getParameter<double>(string("tkChi2Cut"));
00062 tkNhitsCut = theParameters.getParameter<int>(string("tkNhitsCut"));
00063 rVtxCut = theParameters.getParameter<double>(string("rVtxCut"));
00064 vtxSigCut = theParameters.getParameter<double>(string("vtxSignificanceCut"));
00065 collinCut = theParameters.getParameter<double>(string("collinearityCut"));
00066 kShortMassCut = theParameters.getParameter<double>(string("kShortMassCut"));
00067 lambdaMassCut = theParameters.getParameter<double>(string("lambdaMassCut"));
00068
00069
00070
00071
00072
00073
00074
00075 fitAll(iEvent, iSetup);
00076
00077
00078
00079
00080
00081 }
00082
00083 V0Fitter::~V0Fitter() {
00084 }
00085
00086
00087 void V0Fitter::fitAll(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
00088
00089 using std::vector;
00090 using reco::Track;
00091 using reco::TransientTrack;
00092 using reco::TrackRef;
00093 using namespace edm;
00094
00095
00096
00097 vector<TrackRef> theTrackRefs_;
00098 vector<Track> theTracks;
00099 vector<TrackRef> theTrackRefs;
00100 vector<TransientTrack> theTransTracks;
00101
00102
00103 Handle<reco::TrackCollection> theTrackHandle;
00104 ESHandle<MagneticField> bFieldHandle;
00105 ESHandle<TrackerGeometry> trackerGeomHandle;
00106 ESHandle<GlobalTrackingGeometry> globTkGeomHandle;
00107
00108
00109
00110
00111 iEvent.getByLabel(recoAlg, theTrackHandle);
00112 if( !theTrackHandle->size() ) return;
00113 iSetup.get<IdealMagneticFieldRecord>().get(bFieldHandle);
00114 iSetup.get<TrackerDigiGeometryRecord>().get(trackerGeomHandle);
00115 iSetup.get<GlobalTrackingGeometryRecord>().get(globTkGeomHandle);
00116
00117
00118
00119
00120 trackerGeom = trackerGeomHandle.product();
00121 magField = bFieldHandle.product();
00122
00123
00124 for(unsigned int indx = 0; indx < theTrackHandle->size(); indx++) {
00125 TrackRef tmpRef( theTrackHandle, indx );
00126 theTrackRefs_.push_back( tmpRef );
00127 }
00128
00129
00130
00131 reco::TrackBase::Point beamSpot(0,0,0);
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 for( unsigned int indx2 = 0; indx2 < theTrackRefs_.size(); indx2++ ) {
00145 TransientTrack tmpTk( *(theTrackRefs_[indx2]), &(*bFieldHandle), globTkGeomHandle );
00146
00147
00148
00149
00150
00151
00152 theTrackRefs.push_back( theTrackRefs_[indx2] );
00153 theTracks.push_back( *(theTrackRefs_[indx2]) );
00154 theTransTracks.push_back( tmpTk );
00155
00156 }
00157
00158
00159
00160
00161 for(unsigned int trdx1 = 0; trdx1 < theTracks.size(); trdx1++) {
00162
00163 if( doTkQualCuts
00164 && theTrackRefs[trdx1]->normalizedChi2() > tkChi2Cut )
00165 continue;
00166
00167 if( doTkQualCuts && theTrackRefs[trdx1]->recHitsSize() ) {
00168 trackingRecHit_iterator tk1HitIt = theTrackRefs[trdx1]->recHitsBegin();
00169 int nHits1 = 0;
00170 for( ; tk1HitIt < theTrackRefs[trdx1]->recHitsEnd(); tk1HitIt++) {
00171 if( (*tk1HitIt)->isValid() ) nHits1++;
00172 }
00173 if( nHits1 < tkNhitsCut ) continue;
00174 }
00175
00176 for(unsigned int trdx2 = trdx1 + 1; trdx2 < theTracks.size(); trdx2++) {
00177
00178 if( doTkQualCuts
00179 && theTrackRefs[trdx2]->normalizedChi2() > tkChi2Cut ) continue;
00180
00181 if( doTkQualCuts && theTrackRefs[trdx2]->recHitsSize() ) {
00182 trackingRecHit_iterator tk2HitIt = theTrackRefs[trdx2]->recHitsBegin();
00183 int nHits2 = 0;
00184 for( ; tk2HitIt < theTrackRefs[trdx2]->recHitsEnd(); tk2HitIt++) {
00185 if( (*tk2HitIt)->isValid() ) nHits2++;
00186 }
00187 if( nHits2 < tkNhitsCut ) continue;
00188 }
00189
00190 vector<TransientTrack> transTracks;
00191
00192 TrackRef positiveTrackRef;
00193 TrackRef negativeTrackRef;
00194 Track* positiveIter = 0;
00195 Track* negativeIter = 0;
00196 TransientTrack* posTransTkPtr = 0;
00197 TransientTrack* negTransTkPtr = 0;
00198
00199
00200
00201
00202 if(theTrackRefs[trdx1]->charge() < 0. &&
00203 theTrackRefs[trdx2]->charge() > 0.) {
00204 negativeTrackRef = theTrackRefs[trdx1];
00205 positiveTrackRef = theTrackRefs[trdx2];
00206 negativeIter = &theTracks[trdx1];
00207 positiveIter = &theTracks[trdx2];
00208 negTransTkPtr = &theTransTracks[trdx1];
00209 posTransTkPtr = &theTransTracks[trdx2];
00210 }
00211 else if(theTrackRefs[trdx1]->charge() > 0. &&
00212 theTrackRefs[trdx2]->charge() < 0.) {
00213 negativeTrackRef = theTrackRefs[trdx2];
00214 positiveTrackRef = theTrackRefs[trdx1];
00215 negativeIter = &theTracks[trdx2];
00216 positiveIter = &theTracks[trdx1];
00217 negTransTkPtr = &theTransTracks[trdx2];
00218 posTransTkPtr = &theTransTracks[trdx1];
00219 }
00220
00221
00222 else continue;
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 transTracks.push_back(*posTransTkPtr);
00259 transTracks.push_back(*negTransTkPtr);
00260
00261
00262 positiveIter = negativeIter = 0;
00263
00264
00265 KalmanVertexFitter theFitter(useRefTrax == 0 ? false : true);
00266
00267
00268
00269 TransientVertex theRecoVertex;
00270 theRecoVertex = theFitter.vertex(transTracks);
00271
00272 bool continue_ = true;
00273
00274
00275
00276
00277 if( !theRecoVertex.isValid() ) {
00278 continue_ = false;
00279 }
00280
00281 if( continue_ ) {
00282 if(theRecoVertex.totalChiSquared() > 20.
00283 || theRecoVertex.totalChiSquared() < 0.) {
00284 continue_ = false;
00285 }
00286 }
00287
00288
00289 if( continue_ ) {
00290
00291 reco::Vertex theVtx = theRecoVertex;
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 vector<TransientTrack> refittedTrax;
00302 if( theRecoVertex.hasRefittedTracks() ) {
00303 refittedTrax = theRecoVertex.refittedTracks();
00304 }
00305
00306 vector<TransientTrack>::iterator traxIter = refittedTrax.begin(),
00307 traxEnd = refittedTrax.end();
00308
00309
00310
00311 TransientTrack* thePositiveRefTrack = 0;
00312 TransientTrack* theNegativeRefTrack = 0;
00313
00314
00315
00316
00317 for( ; traxIter != traxEnd; traxIter++) {
00318 if( traxIter->track().charge() > 0. ) {
00319 thePositiveRefTrack = new TransientTrack(*traxIter);
00320 }
00321 else if (traxIter->track().charge() < 0.) {
00322 theNegativeRefTrack = new TransientTrack(*traxIter);
00323 }
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 GlobalPoint vtxPos(theVtx.x(), theVtx.y(), theVtx.z());
00340
00341 TrajectoryStateClosestToPoint* trajPlus;
00342 TrajectoryStateClosestToPoint* trajMins;
00343
00344 if(useRefTrax && refittedTrax.size() > 1) {
00345 trajPlus = new TrajectoryStateClosestToPoint(
00346 thePositiveRefTrack->trajectoryStateClosestToPoint(vtxPos));
00347 trajMins = new TrajectoryStateClosestToPoint(
00348 theNegativeRefTrack->trajectoryStateClosestToPoint(vtxPos));
00349 }
00350 else {
00351 trajPlus = new TrajectoryStateClosestToPoint(
00352 posTransTkPtr->trajectoryStateClosestToPoint(vtxPos));
00353 trajMins = new TrajectoryStateClosestToPoint(
00354 negTransTkPtr->trajectoryStateClosestToPoint(vtxPos));
00355
00356 }
00357
00358 posTransTkPtr = negTransTkPtr = 0;
00359
00360
00361
00362
00363
00364 GlobalVector positiveP(trajPlus->momentum());
00365 GlobalVector negativeP(trajMins->momentum());
00366 GlobalVector totalP(positiveP + negativeP);
00367 double piMassSq = 0.019479835;
00368 double protonMassSq = 0.880354402;
00369
00370
00371 delete trajPlus;
00372 delete trajMins;
00373 trajPlus = trajMins = 0;
00374 delete thePositiveRefTrack;
00375 delete theNegativeRefTrack;
00376 thePositiveRefTrack = theNegativeRefTrack = 0;
00377
00378
00379
00380 double piPlusE = sqrt(positiveP.x()*positiveP.x()
00381 + positiveP.y()*positiveP.y()
00382 + positiveP.z()*positiveP.z()
00383 + piMassSq);
00384 double piMinusE = sqrt(negativeP.x()*negativeP.x()
00385 + negativeP.y()*negativeP.y()
00386 + negativeP.z()*negativeP.z()
00387 + piMassSq);
00388 double protonE = sqrt(positiveP.x()*positiveP.x()
00389 + positiveP.y()*positiveP.y()
00390 + positiveP.z()*positiveP.z()
00391 + protonMassSq);
00392 double antiProtonE = sqrt(negativeP.x()*negativeP.x()
00393 + negativeP.y()*negativeP.y()
00394 + negativeP.z()*negativeP.z()
00395 + protonMassSq);
00396 double kShortETot = piPlusE + piMinusE;
00397 double lambdaEtot = protonE + piMinusE;
00398 double lambdaBarEtot = antiProtonE + piPlusE;
00399
00400 using namespace reco;
00401
00402
00403 const Particle::LorentzVector kShortP4(totalP.x(),
00404 totalP.y(), totalP.z(),
00405 kShortETot);
00406 const Particle::LorentzVector lambdaP4(totalP.x(),
00407 totalP.y(), totalP.z(),
00408 lambdaEtot);
00409 const Particle::LorentzVector lambdaBarP4(totalP.x(),
00410 totalP.y(), totalP.z(),
00411 lambdaBarEtot);
00412 Particle::Point vtx(theVtx.x(), theVtx.y(), theVtx.z());
00413 const Vertex::CovarianceMatrix vtxCov(theVtx.covariance());
00414 double vtxChi2(theVtx.chi2());
00415 double vtxNdof(theVtx.ndof());
00416
00417
00418 VertexCompositeCandidate
00419 theKshort(0, kShortP4, vtx, vtxCov, vtxChi2, vtxNdof);
00420 VertexCompositeCandidate
00421 theLambda(0, lambdaP4, vtx, vtxCov, vtxChi2, vtxNdof);
00422 VertexCompositeCandidate
00423 theLambdaBar(0, lambdaBarP4, vtx, vtxCov, vtxChi2, vtxNdof);
00424
00425
00426 RecoChargedCandidate
00427 thePiPlusCand(1, Particle::LorentzVector(positiveP.x(),
00428 positiveP.y(), positiveP.z(),
00429 piPlusE), vtx);
00430 thePiPlusCand.setTrack(positiveTrackRef);
00431
00432 RecoChargedCandidate
00433 thePiMinusCand(-1, Particle::LorentzVector(negativeP.x(),
00434 negativeP.y(), negativeP.z(),
00435 piMinusE), vtx);
00436 thePiMinusCand.setTrack(negativeTrackRef);
00437
00438
00439 RecoChargedCandidate
00440 theProtonCand(1, Particle::LorentzVector(positiveP.x(),
00441 positiveP.y(), positiveP.z(),
00442 protonE), vtx);
00443 theProtonCand.setTrack(positiveTrackRef);
00444
00445 RecoChargedCandidate
00446 theAntiProtonCand(-1, Particle::LorentzVector(negativeP.x(),
00447 negativeP.y(), negativeP.z(),
00448 antiProtonE), vtx);
00449 theAntiProtonCand.setTrack(negativeTrackRef);
00450
00451
00452
00453 theKshort.addDaughter(thePiPlusCand);
00454 theKshort.addDaughter(thePiMinusCand);
00455
00456 theLambda.addDaughter(theProtonCand);
00457 theLambda.addDaughter(thePiMinusCand);
00458
00459 theLambdaBar.addDaughter(theAntiProtonCand);
00460 theLambdaBar.addDaughter(thePiPlusCand);
00461
00462 theKshort.setPdgId(310);
00463 theLambda.setPdgId(3122);
00464 theLambdaBar.setPdgId(-3122);
00465
00466 AddFourMomenta addp4;
00467 addp4.set( theKshort );
00468 addp4.set( theLambda );
00469 addp4.set( theLambdaBar );
00470
00471
00472 if(doKshorts)
00473 preCutCands.push_back(theKshort);
00474 if(doLambdas) {
00475 preCutCands.push_back(theLambda);
00476 preCutCands.push_back(theLambdaBar);
00477 }
00478
00479
00480 }
00481 }
00482 }
00483
00484
00485
00486 if( preCutCands.size() )
00487 applyPostFitCuts();
00488
00489 }
00490
00491
00492
00493 const reco::VertexCompositeCandidateCollection& V0Fitter::getKshorts() const {
00494 return theKshorts;
00495 }
00496
00497 const reco::VertexCompositeCandidateCollection& V0Fitter::getLambdas() const {
00498 return theLambdas;
00499 }
00500
00501 const reco::VertexCompositeCandidateCollection& V0Fitter::getLambdaBars() const {
00502 return theLambdaBars;
00503 }
00504
00505
00506
00507 void V0Fitter::applyPostFitCuts() {
00508
00509
00510
00511
00512
00513 for(reco::VertexCompositeCandidateCollection::iterator theIt = preCutCands.begin();
00514 theIt != preCutCands.end(); theIt++) {
00515 bool writeVee = false;
00516 double rVtxMag = sqrt( theIt->vertex().x()*theIt->vertex().x() +
00517 theIt->vertex().y()*theIt->vertex().y() );
00518
00519
00520 double x_ = theIt->vertex().x();
00521 double y_ = theIt->vertex().y();
00522
00523 double sig00 = theIt->vertexCovariance(0,0);
00524 double sig11 = theIt->vertexCovariance(1,1);
00525
00526 double sig01 = theIt->vertexCovariance(0,1);
00527
00528
00529
00530
00531
00532
00533
00534 double sigmaRvtxMag =
00535 sqrt( sig00*(x_*x_) + sig11*(y_*y_) + 2*sig01*(x_*y_) ) / rVtxMag;
00536
00537
00538
00539 std::vector<reco::RecoChargedCandidate> v0daughters;
00540 std::vector<reco::TrackRef> theVtxTrax;
00541 for(unsigned int ii = 0; ii < theIt->numberOfDaughters(); ii++) {
00542 v0daughters.push_back( *(dynamic_cast<reco::RecoChargedCandidate *>
00543 (theIt->daughter(ii))) );
00544 }
00545 for(unsigned int jj = 0; jj < v0daughters.size(); jj++) {
00546 theVtxTrax.push_back(v0daughters[jj].track());
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 using namespace reco;
00561
00562
00563
00564
00565 bool hitsOkay = true;
00566
00567 if( theVtxTrax.size() == 2 && doPostFitCuts) {
00568 if( theVtxTrax[0]->innerOk() ) {
00569 reco::Vertex::Point tk1HitPosition = theVtxTrax[0]->innerPosition();
00570 if( sqrt(tk1HitPosition.Perp2()) < (rVtxMag - sigmaRvtxMag*4.0) ) {
00571 hitsOkay = false;
00572 }
00573 }
00574 if( theVtxTrax[1]->innerOk() && hitsOkay) {
00575 reco::Vertex::Point tk2HitPosition = theVtxTrax[1]->innerPosition();
00576 if( sqrt(tk2HitPosition.Perp2()) < (rVtxMag - sigmaRvtxMag*4.0) ) {
00577 hitsOkay = false;
00578 }
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 }
00615
00616
00617 if( theIt->vertexChi2() < chi2Cut &&
00618 rVtxMag > rVtxCut &&
00619 rVtxMag/sigmaRvtxMag > vtxSigCut &&
00620 hitsOkay) {
00621 writeVee = true;
00622 }
00623 const double kShortMass = 0.49767;
00624 const double lambdaMass = 1.1156;
00625
00626 if( theIt->mass() < kShortMass + kShortMassCut &&
00627 theIt->mass() > kShortMass - kShortMassCut && writeVee &&
00628 doKshorts && doPostFitCuts) {
00629 if(theIt->pdgId() == 310) {
00630 theKshorts.push_back( *theIt );
00631 }
00632 }
00633 else if( !doPostFitCuts && theIt->pdgId() == 310 && doKshorts ) {
00634 theKshorts.push_back( *theIt );
00635 }
00636
00637
00638 else if( theIt->mass() < lambdaMass + lambdaMassCut &&
00639 theIt->mass() > lambdaMass - lambdaMassCut && writeVee &&
00640 doLambdas && doPostFitCuts ) {
00641 if(theIt->pdgId() == 3122) {
00642 theLambdas.push_back( *theIt );
00643 }
00644 else if(theIt->pdgId() == -3122) {
00645 theLambdaBars.push_back( *theIt );
00646 }
00647 }
00648 else if ( !doPostFitCuts && theIt->pdgId() == 3122 && doLambdas ) {
00649 theLambdas.push_back( *theIt );
00650 }
00651 else if ( !doPostFitCuts && theIt->pdgId() == -3122 && doLambdas ) {
00652 theLambdaBars.push_back( *theIt );
00653 }
00654 }
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665 }
00666