00001
00002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00003
00004 #include "FWCore/Framework/interface/Event.h"
00005 #include "FWCore/Utilities/interface/EDMException.h"
00006
00007
00008 #include <DataFormats/TrackReco/interface/Track.h>
00009 #include <DataFormats/METReco/interface/CaloMET.h>
00010 #include <DataFormats/Math/interface/deltaPhi.h>
00011
00012
00013 #include <math.h>
00014
00015 #include "TLorentzVector.h"
00016
00017 #include "Alignment/CommonAlignmentProducer/interface/AlignmentTwoBodyDecayTrackSelector.h"
00018
00019 using namespace std;
00020 using namespace edm;
00021
00022
00023 AlignmentTwoBodyDecayTrackSelector::AlignmentTwoBodyDecayTrackSelector(const edm::ParameterSet & cfg) :
00024 theMissingETSource("met")
00025 {
00026 LogDebug("Alignment") << "> applying two body decay Trackfilter ...";
00027 theMassrangeSwitch = cfg.getParameter<bool>( "applyMassrangeFilter" );
00028 if (theMassrangeSwitch){
00029 theMinMass = cfg.getParameter<double>( "minXMass" );
00030 theMaxMass = cfg.getParameter<double>( "maxXMass" );
00031 theDaughterMass = cfg.getParameter<double>( "daughterMass" );
00032 theCandNumber = cfg.getParameter<unsigned int>( "numberOfCandidates" );
00033 secThrBool = cfg.getParameter<bool> ( "applySecThreshold" );
00034 thesecThr = cfg.getParameter<double>( "secondThreshold" );
00035 LogDebug("Alignment") << "> Massrange min,max : " << theMinMass << "," << theMaxMass
00036 << "\n> Mass of daughter Particle : " << theDaughterMass;
00037
00038 }else{
00039 theMinMass = 0;
00040 theMaxMass = 0;
00041 theDaughterMass = 0;
00042 }
00043 theChargeSwitch = cfg.getParameter<bool>( "applyChargeFilter" );
00044 if(theChargeSwitch){
00045 theCharge = cfg.getParameter<int>( "charge" );
00046 theUnsignedSwitch = cfg.getParameter<bool>( "useUnsignedCharge" );
00047 if(theUnsignedSwitch)
00048 theCharge=std::abs(theCharge);
00049 LogDebug("Alignment") << "> Desired Charge, unsigned: "<<theCharge<<" , "<<theUnsignedSwitch;
00050 }else{
00051 theCharge =0;
00052 theUnsignedSwitch = true;
00053 }
00054 theMissingETSwitch = cfg.getParameter<bool>( "applyMissingETFilter" );
00055 if(theMissingETSwitch){
00056 theMissingETSource = cfg.getParameter<InputTag>( "missingETSource" );
00057 LogDebug("Alignment") << "> missing Et Source: "<< theMissingETSource;
00058 }
00059 theAcoplanarityFilterSwitch = cfg.getParameter<bool>( "applyAcoplanarityFilter" );
00060 if(theAcoplanarityFilterSwitch){
00061 theAcoplanarDistance = cfg.getParameter<double>( "acoplanarDistance" );
00062 LogDebug("Alignment") << "> Acoplanar Distance: "<<theAcoplanarDistance;
00063 }
00064
00065 }
00066
00067
00068
00069 AlignmentTwoBodyDecayTrackSelector::~AlignmentTwoBodyDecayTrackSelector()
00070 {}
00071
00072
00074 bool AlignmentTwoBodyDecayTrackSelector::useThisFilter()
00075 {
00076 return theMassrangeSwitch || theChargeSwitch || theAcoplanarityFilterSwitch;
00077 }
00078
00079
00080
00081 AlignmentTwoBodyDecayTrackSelector::Tracks
00082 AlignmentTwoBodyDecayTrackSelector::select(const Tracks& tracks, const edm::Event& iEvent, const edm::EventSetup& iSetup)
00083 {
00084 Tracks result = tracks;
00085
00086 if (theMassrangeSwitch) {
00087 if (theMissingETSwitch)
00088 result = checkMETMass(result,iEvent);
00089 else
00090 result = checkMass(result);
00091 }
00092
00093 LogDebug("Alignment") << "> TwoBodyDecay tracks all,kept: " << tracks.size() << "," << result.size();
00094 return result;
00095 }
00096
00097 template<class T>
00098 struct higherTwoBodyDecayPt : public std::binary_function<T,T,bool>
00099 {
00100 bool operator()( const T& a, const T& b )
00101 {
00102 return a.first > b.first ;
00103 }
00104 };
00105
00107 AlignmentTwoBodyDecayTrackSelector::Tracks
00108 AlignmentTwoBodyDecayTrackSelector::checkMass(const Tracks& cands) const
00109 {
00110 Tracks result;
00111
00112 LogDebug("Alignment") <<"> cands size : "<< cands.size();
00113
00114 if (cands.size()<2) return result;
00115
00116 TLorentzVector track0;
00117 TLorentzVector track1;
00118 TLorentzVector mother;
00119 typedef pair<const reco::Track*,const reco::Track*> constTrackPair;
00120 typedef pair<double,constTrackPair> candCollectionItem;
00121 vector<candCollectionItem> candCollection;
00122
00123 for (unsigned int iCand = 0; iCand < cands.size(); iCand++) {
00124
00125 track0.SetXYZT(cands.at(iCand)->px(),
00126 cands.at(iCand)->py(),
00127 cands.at(iCand)->pz(),
00128 sqrt( cands.at(iCand)->p()*cands.at(iCand)->p() + theDaughterMass*theDaughterMass ));
00129
00130 for (unsigned int jCand = iCand+1; jCand < cands.size(); jCand++) {
00131
00132 track1.SetXYZT(cands.at(jCand)->px(),
00133 cands.at(jCand)->py(),
00134 cands.at(jCand)->pz(),
00135 sqrt( cands.at(jCand)->p()*cands.at(jCand)->p() + theDaughterMass*theDaughterMass ));
00136 if (secThrBool==true && track1.Pt() < thesecThr && track0.Pt()< thesecThr) continue;
00137 mother = track0 + track1;
00138
00139 const reco::Track *trk1 = cands.at(iCand);
00140 const reco::Track *trk2 = cands.at(jCand);
00141
00142 bool correctCharge = true;
00143 if (theChargeSwitch) correctCharge = this->checkCharge(trk1, trk2);
00144
00145 bool acoplanarTracks = true;
00146 if (theAcoplanarityFilterSwitch) acoplanarTracks = this->checkAcoplanarity(trk1, trk2);
00147
00148 if (mother.M() > theMinMass &&
00149 mother.M() < theMaxMass &&
00150 correctCharge &&
00151 acoplanarTracks) {
00152 candCollection.push_back(candCollectionItem(mother.Pt(),
00153 constTrackPair(trk1, trk2)));
00154 }
00155 }
00156 }
00157
00158 if (candCollection.size()==0) return result;
00159
00160 sort(candCollection.begin(), candCollection.end(),
00161 higherTwoBodyDecayPt<candCollectionItem>());
00162
00163 std::map<const reco::Track*,unsigned int> uniqueTrackIndex;
00164 std::map<const reco::Track*,unsigned int>::iterator it;
00165 for (unsigned int i=0;
00166 i<candCollection.size() && i<theCandNumber;
00167 i++) {
00168 constTrackPair & trackPair = candCollection[i].second;
00169
00170 it = uniqueTrackIndex.find(trackPair.first);
00171 if (it==uniqueTrackIndex.end()) {
00172 result.push_back(trackPair.first);
00173 uniqueTrackIndex[trackPair.first] = i;
00174 }
00175
00176 it = uniqueTrackIndex.find(trackPair.second);
00177 if (it==uniqueTrackIndex.end()) {
00178 result.push_back(trackPair.second);
00179 uniqueTrackIndex[trackPair.second] = i;
00180 }
00181 }
00182
00183 return result;
00184 }
00185
00187 AlignmentTwoBodyDecayTrackSelector::Tracks
00188 AlignmentTwoBodyDecayTrackSelector::checkMETMass(const Tracks& cands,const edm::Event& iEvent) const
00189 {
00190 Tracks result;
00191
00192 LogDebug("Alignment") <<"> cands size : "<< cands.size();
00193
00194 if (cands.size()==0) return result;
00195
00196 TLorentzVector track;
00197 TLorentzVector met4;
00198 TLorentzVector mother;
00199
00200 Handle<reco::CaloMETCollection> missingET;
00201 iEvent.getByLabel(theMissingETSource ,missingET);
00202 if (!missingET.isValid()) {
00203 LogError("Alignment")<< "@SUB=AlignmentTwoBodyDecayTrackSelector::checkMETMass"
00204 << "> could not optain missingET Collection!";
00205 return result;
00206 }
00207
00208 typedef pair<double,const reco::Track*> candCollectionItem;
00209 vector<candCollectionItem> candCollection;
00210
00211 for (reco::CaloMETCollection::const_iterator itMET = missingET->begin();
00212 itMET != missingET->end();
00213 ++itMET) {
00214
00215 met4.SetXYZT((*itMET).px(),
00216 (*itMET).py(),
00217 (*itMET).pz(),
00218 (*itMET).p());
00219
00220 for (unsigned int iCand = 0; iCand < cands.size(); iCand++) {
00221
00222 track.SetXYZT(cands.at(iCand)->px(),
00223 cands.at(iCand)->py(),
00224 cands.at(iCand)->pz(),
00225 sqrt( cands.at(iCand)->p()*cands.at(iCand)->p() + theDaughterMass*theDaughterMass ));
00226
00227 mother = track + met4;
00228
00229 const reco::Track *trk = cands.at(iCand);
00230 const reco::CaloMET *met = &(*itMET);
00231
00232 bool correctCharge = true;
00233 if (theChargeSwitch) correctCharge = this->checkCharge(trk);
00234
00235 bool acoplanarTracks = true;
00236 if (theAcoplanarityFilterSwitch) acoplanarTracks = this->checkMETAcoplanarity(trk, met);
00237
00238 if (mother.M() > theMinMass &&
00239 mother.M() < theMaxMass &&
00240 correctCharge &&
00241 acoplanarTracks) {
00242 candCollection.push_back(candCollectionItem(mother.Pt(), trk));
00243 }
00244 }
00245 }
00246
00247 if (candCollection.size()==0) return result;
00248
00249 sort(candCollection.begin(), candCollection.end(),
00250 higherTwoBodyDecayPt<candCollectionItem>());
00251
00252 std::map<const reco::Track*,unsigned int> uniqueTrackIndex;
00253 std::map<const reco::Track*,unsigned int>::iterator it;
00254 for (unsigned int i=0;
00255 i<candCollection.size() && i<theCandNumber;
00256 i++) {
00257 it = uniqueTrackIndex.find(candCollection[i].second);
00258 if (it==uniqueTrackIndex.end()) {
00259 result.push_back(candCollection[i].second);
00260 uniqueTrackIndex[candCollection[i].second] = i;
00261 }
00262 }
00263
00264 return result;
00265 }
00266
00268 bool
00269 AlignmentTwoBodyDecayTrackSelector::checkCharge(const reco::Track* trk1, const reco::Track* trk2)const
00270 {
00271 int sumCharge = trk1->charge();
00272 if (trk2) sumCharge += trk2->charge();
00273 if (theUnsignedSwitch) sumCharge = std::abs(sumCharge);
00274 if (sumCharge == theCharge) return true;
00275 return false;
00276 }
00277
00279 bool
00280 AlignmentTwoBodyDecayTrackSelector::checkAcoplanarity(const reco::Track* trk1, const reco::Track* trk2)const
00281 {
00282 if (fabs(deltaPhi(trk1->phi(),trk2->phi()-M_PI)) < theAcoplanarDistance) return true;
00283 return false;
00284 }
00285
00287 bool
00288 AlignmentTwoBodyDecayTrackSelector::checkMETAcoplanarity(const reco::Track* trk1, const reco::CaloMET* met)const
00289 {
00290 if (fabs(deltaPhi(trk1->phi(),met->phi()-M_PI)) < theAcoplanarDistance) return true;
00291 return false;
00292 }
00293
00294
00295
00297 void AlignmentTwoBodyDecayTrackSelector::printTracks(const Tracks& col) const
00298 {
00299 int count = 0;
00300 LogDebug("Alignment") << ">......................................";
00301 for(Tracks::const_iterator it = col.begin();it < col.end();++it,++count){
00302 LogDebug("Alignment")
00303 <<"> Track No. "<< count <<": p = ("<<(*it)->px()<<","<<(*it)->py()<<","<<(*it)->pz()<<")\n"
00304 <<"> pT = "<<(*it)->pt()<<" eta = "<<(*it)->eta()<<" charge = "<<(*it)->charge();
00305 }
00306 LogDebug("Alignment") << ">......................................";
00307 }
00308
00309