00001 #include <algorithm>
00002 #include <cmath>
00003 #include <vector>
00004
00005 #include "FWCore/Framework/interface/ESHandle.h"
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007
00008 #include "DataFormats/RecoCandidate/interface/RecoCandidate.h"
00009 #include "DataFormats/RecoCandidate/interface/RecoChargedCandidate.h"
00010
00011 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
00012 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
00013
00014 #include "RecoVertex/KalmanVertexFit/interface/KalmanVertexFitter.h"
00015 #include "RecoVertex/VertexPrimitives/interface/TransientVertex.h"
00016 #include "DataFormats/VertexReco/interface/Vertex.h"
00017 #include "DataFormats/VertexReco/interface/VertexFwd.h"
00018 #include "DataFormats/HLTReco/interface/TriggerFilterObjectWithRefs.h"
00019
00020 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
00021
00022 #include "DataFormats/Math/interface/deltaPhi.h"
00023
00024 #include "HLTmmkFilter.h"
00025
00026 using namespace edm;
00027 using namespace reco;
00028 using namespace std;
00029 using namespace trigger;
00030
00031
00032
00033 HLTmmkFilter::HLTmmkFilter(const edm::ParameterSet& iConfig):thirdTrackMass_(iConfig.getParameter<double>("ThirdTrackMass")),
00034 maxEta_(iConfig.getParameter<double>("MaxEta")),
00035 minPt_(iConfig.getParameter<double>("MinPt")),
00036 minInvMass_(iConfig.getParameter<double>("MinInvMass")),
00037 maxInvMass_(iConfig.getParameter<double>("MaxInvMass")),
00038 maxNormalisedChi2_(iConfig.getParameter<double>("MaxNormalisedChi2")),
00039 minLxySignificance_(iConfig.getParameter<double>("MinLxySignificance")),
00040 minCosinePointingAngle_(iConfig.getParameter<double>("MinCosinePointingAngle")),
00041 fastAccept_(iConfig.getParameter<bool>("FastAccept")),
00042 saveTag_ (iConfig.getUntrackedParameter<bool> ("SaveTag",false)),
00043 beamSpotTag_ (iConfig.getParameter<edm::InputTag> ("BeamSpotTag")){
00044
00045 muCandLabel_ = iConfig.getParameter<edm::InputTag>("MuCand");
00046 trkCandLabel_ = iConfig.getParameter<edm::InputTag>("TrackCand");
00047
00048 produces<VertexCollection>();
00049 produces<CandidateCollection>();
00050 produces<trigger::TriggerFilterObjectWithRefs>();
00051
00052 }
00053
00054
00055
00056 HLTmmkFilter::~HLTmmkFilter() {
00057
00058 }
00059
00060
00061
00062 void HLTmmkFilter::beginJob() {
00063
00064 }
00065
00066
00067
00068 void HLTmmkFilter::endJob() {
00069
00070 }
00071
00072
00073
00074 bool HLTmmkFilter::filter(edm::Event& iEvent, const edm::EventSetup& iSetup) {
00075
00076 const double MuMass(0.106);
00077 const double MuMass2(MuMass*MuMass);
00078
00079 const double thirdTrackMass2(thirdTrackMass_*thirdTrackMass_);
00080
00081
00082 auto_ptr<TriggerFilterObjectWithRefs> filterobject (new TriggerFilterObjectWithRefs(path(),module()));
00083
00084 auto_ptr<CandidateCollection> output(new CandidateCollection());
00085 auto_ptr<VertexCollection> vertexCollection(new VertexCollection());
00086
00087
00088 edm::ESHandle<TransientTrackBuilder> theB;
00089 iSetup.get<TransientTrackRecord>().get("TransientTrackBuilder",theB);
00090
00091
00092 edm::Handle<reco::BeamSpot> recoBeamSpotHandle;
00093 iEvent.getByLabel(beamSpotTag_,recoBeamSpotHandle);
00094 const reco::BeamSpot& vertexBeamSpot = *recoBeamSpotHandle;
00095
00096
00097 RecoChargedCandidateRef refMu1;
00098 RecoChargedCandidateRef refMu2;
00099 RecoChargedCandidateRef refTrk;
00100
00101
00102 Handle<RecoChargedCandidateCollection> mucands;
00103 iEvent.getByLabel (muCandLabel_,mucands);
00104
00105
00106 Handle<RecoChargedCandidateCollection> trkcands;
00107 iEvent.getByLabel (trkCandLabel_,trkcands);
00108
00109 if(saveTag_){
00110 filterobject->addCollectionTag(muCandLabel_);
00111 filterobject->addCollectionTag(trkCandLabel_);
00112 }
00113
00114 double e1,e2,e3;
00115 Particle::LorentzVector p,p1,p2,p3;
00116
00117
00118 vector<TrackRef> trkMuCands;
00119
00120
00121 vector<bool> isUsedCand(trkcands->size(),false);
00122
00123 int counter = 0;
00124
00125
00126 for (RecoChargedCandidateCollection::const_iterator mucand1=mucands->begin(), endCand1=mucands->end(); mucand1!=endCand1; ++mucand1) {
00127
00128 if ( mucands->size()<2) break;
00129 if ( trkcands->size()<3) break;
00130
00131 TrackRef trk1 = mucand1->get<TrackRef>();
00132 LogDebug("HLTDisplacedMumukFilter") << " 1st muon: q*pt= " << trk1->charge()*trk1->pt() << ", eta= " << trk1->eta() << ", hits= " << trk1->numberOfValidHits();
00133
00134
00135 if (fabs(trk1->eta()) > maxEta_) continue;
00136
00137
00138 if (trk1->pt() < minPt_) continue;
00139
00140 RecoChargedCandidateCollection::const_iterator mucand2 = mucand1; ++mucand2;
00141
00142 for (RecoChargedCandidateCollection::const_iterator endCand2=mucands->end(); mucand2!=endCand2; ++mucand2) {
00143
00144 TrackRef trk2 = mucand2->get<TrackRef>();
00145
00146 LogDebug("HLTDisplacedMumukFilter") << " 2nd muon: q*pt= " << trk2->charge()*trk2->pt() << ", eta= " << trk2->eta() << ", hits= " << trk2->numberOfValidHits();
00147
00148
00149 if (fabs(trk2->eta()) > maxEta_) continue;
00150
00151
00152 if (trk2->pt() < minPt_) continue;
00153
00154 RecoChargedCandidateCollection::const_iterator trkcand, endCandTrk;
00155
00156 std::vector<bool>::iterator isUsedIter, endIsUsedCand;
00157
00158
00159 for ( trkcand = trkcands->begin(), endCandTrk=trkcands->end(), isUsedIter = isUsedCand.begin(), endIsUsedCand = isUsedCand.end(); trkcand != endCandTrk && isUsedIter != endIsUsedCand; ++trkcand, ++isUsedIter) {
00160 TrackRef trk3 = trkcand->get<TrackRef>();
00161
00162
00163 if (overlap(*mucand1,*trkcand)) {
00164 trkMuCands.push_back(trk3);
00165 *isUsedIter = true;
00166 continue;
00167 }
00168 else if (overlap(*mucand2,*trkcand)){
00169 trkMuCands.push_back(trk3);
00170 *isUsedIter = true;
00171 continue;
00172 }
00173
00174 if(trkMuCands.size()==2) break;
00175 }
00176
00177
00178 if (trkMuCands.size()!=2) continue;
00179
00180
00181 for ( trkcand = trkcands->begin(), endCandTrk=trkcands->end(), isUsedIter = isUsedCand.begin(), endIsUsedCand = isUsedCand.end(); trkcand != endCandTrk && isUsedIter != endIsUsedCand; ++trkcand, ++isUsedIter) {
00182
00183 TrackRef trk3 = trkcand->get<TrackRef>();
00184
00185 LogDebug("HLTDisplacedMumukFilter") << " 3rd track: q*pt= " << trk3->charge()*trk3->pt() << ", eta= " << trk3->eta() << ", hits= " << trk3->numberOfValidHits();
00186
00187
00188 if(trk3==trkMuCands.at(0) || trk3==trkMuCands.at(1)) continue;
00189
00190
00191 if(*isUsedIter) continue;
00192
00193
00194 if (fabs(trk3->eta()) > maxEta_) continue;
00195
00196
00197 if (trk3->pt() < minPt_) continue;
00198
00199
00200 e1 = sqrt(trk1->momentum().Mag2()+MuMass2);
00201 e2 = sqrt(trk2->momentum().Mag2()+MuMass2);
00202 e3 = sqrt(trk3->momentum().Mag2()+thirdTrackMass2);
00203
00204 p1 = Particle::LorentzVector(trk1->px(),trk1->py(),trk1->pz(),e1);
00205 p2 = Particle::LorentzVector(trk2->px(),trk2->py(),trk2->pz(),e2);
00206 p3 = Particle::LorentzVector(trk3->px(),trk3->py(),trk3->pz(),e3);
00207
00208 p = p1+p2+p3;
00209
00210
00211 double invmass = abs(p.mass());
00212
00213 LogDebug("HLTDisplacedMumukFilter") << " Invmass= " << invmass;
00214
00215 if (invmass>maxInvMass_ || invmass<minInvMass_) continue;
00216
00217
00218 vector<TransientTrack> t_tks;
00219 t_tks.push_back((*theB).build(&trk1));
00220 t_tks.push_back((*theB).build(&trk2));
00221 t_tks.push_back((*theB).build(&trk3));
00222
00223 if (t_tks.size()!=3) continue;
00224
00225 KalmanVertexFitter kvf;
00226 TransientVertex tv = kvf.vertex(t_tks);
00227
00228 if (!tv.isValid()) continue;
00229
00230 Vertex vertex = tv;
00231
00232
00233 GlobalPoint secondaryVertex = tv.position();
00234 GlobalError err = tv.positionError();
00235
00236
00237 GlobalPoint displacementFromBeamspot( -1*((vertexBeamSpot.x0() -secondaryVertex.x()) + (secondaryVertex.z() - vertexBeamSpot.z0()) * vertexBeamSpot.dxdz()), -1*((vertexBeamSpot.y0() - secondaryVertex.y())+ (secondaryVertex.z() -vertexBeamSpot.z0()) * vertexBeamSpot.dydz()), 0);
00238
00239 float lxy = displacementFromBeamspot.perp();
00240 float lxyerr = sqrt(err.rerr(displacementFromBeamspot));
00241
00242
00243 float normChi2 = tv.normalisedChiSquared();
00244
00245
00246 Vertex::Point vperp(displacementFromBeamspot.x(),displacementFromBeamspot.y(),0.);
00247 math::XYZVector pperp(p.x(),p.y(),0.);
00248
00249 float cosAlpha = vperp.Dot(pperp)/(vperp.R()*pperp.R());
00250
00251 LogDebug("HLTDisplacedMumukFilter") << " vertex fit normalised chi2: " << normChi2 << ", Lxy significance: " << lxy/lxyerr << ", cosine pointing angle: " << cosAlpha;
00252
00253
00254 vertexCollection->push_back(vertex);
00255
00256 if (normChi2 > maxNormalisedChi2_) continue;
00257 if (lxy/lxyerr < minLxySignificance_) continue;
00258 if(cosAlpha < minCosinePointingAngle_) continue;
00259
00260 LogDebug("HLTDisplacedMumukFilter") << " Event passed!";
00261
00262
00263 ++counter;
00264
00265
00266 bool i1done = false;
00267 bool i2done = false;
00268 bool i3done = false;
00269 vector<RecoChargedCandidateRef> vref;
00270 filterobject->getObjects(TriggerMuon,vref);
00271 for (unsigned int i=0; i<vref.size(); i++) {
00272 RecoChargedCandidateRef candref = RecoChargedCandidateRef(vref[i]);
00273 TrackRef trktmp = candref->get<TrackRef>();
00274 if (trktmp==trk1) {
00275 i1done = true;
00276 } else if (trktmp==trk2) {
00277 i2done = true;
00278 } else if (trktmp==trk3) {
00279 i3done = true;
00280 }
00281 if (i1done && i2done && i3done) break;
00282 }
00283
00284 if (!i1done) {
00285 refMu1=RecoChargedCandidateRef( Ref<RecoChargedCandidateCollection> (mucands,distance(mucands->begin(), mucand1)));
00286 filterobject->addObject(TriggerMuon,refMu1);
00287 }
00288 if (!i2done) {
00289 refMu2=RecoChargedCandidateRef( Ref<RecoChargedCandidateCollection> (mucands,distance(mucands->begin(),mucand2)));
00290 filterobject->addObject(TriggerMuon,refMu2);
00291 }
00292 if (!i3done) {
00293 refTrk=RecoChargedCandidateRef( Ref<RecoChargedCandidateCollection> (trkcands,distance(trkcands->begin(),trkcand)));
00294 filterobject->addObject(TriggerTrack,refTrk);
00295 }
00296
00297 if (fastAccept_) break;
00298 }
00299
00300 trkMuCands.clear();
00301 }
00302 }
00303
00304
00305 const bool accept (counter >= 1);
00306
00307 LogDebug("HLTDisplacedMumukFilter") << " >>>>> Result of HLTDisplacedMumukFilter is "<< accept << ", number of muon pairs passing thresholds= " << counter;
00308
00309
00310 iEvent.put(filterobject);
00311 iEvent.put(vertexCollection);
00312
00313 return accept;
00314 }
00315
00316
00317 int HLTmmkFilter::overlap(const reco::Candidate &a, const reco::Candidate &b) {
00318
00319 double eps(1.0e-5);
00320
00321 double dpt = a.pt() - b.pt();
00322 dpt *= dpt;
00323
00324 double dphi = deltaPhi(a.phi(), b.phi());
00325 dphi *= dphi;
00326
00327 double deta = a.eta() - b.eta();
00328 deta *= deta;
00329
00330 if ((dpt + dphi + deta) < eps) {
00331 return 1;
00332 }
00333
00334 return 0;
00335
00336 }
00337