00001
00002 #include "Rivet/Projections/InvMassFinalState.hh"
00003 #include "Rivet/Tools/Logging.hh"
00004 #include "Rivet/Cmp.hh"
00005
00006 namespace Rivet {
00007
00008
00009 InvMassFinalState::InvMassFinalState(const FinalState& fsp,
00010 const pair<PdgId, PdgId>& idpair,
00011 double minmass,
00012 double maxmass,
00013 double masstarget)
00014 : _minmass(minmass), _maxmass(maxmass), _masstarget(masstarget), _useTransverseMass(false)
00015 {
00016 setName("InvMassFinalState");
00017 addProjection(fsp, "FS");
00018 _decayids.push_back(idpair);
00019 }
00020
00021
00022 InvMassFinalState::InvMassFinalState(const FinalState& fsp,
00023 const vector<pair<PdgId, PdgId> >& idpairs,
00024 double minmass,
00025 double maxmass,
00026 double masstarget)
00027 : _decayids(idpairs), _minmass(minmass), _maxmass(maxmass), _masstarget(masstarget), _useTransverseMass(false)
00028 {
00029 setName("InvMassFinalState");
00030 addProjection(fsp, "FS");
00031 }
00032
00033
00034 int InvMassFinalState::compare(const Projection& p) const {
00035
00036 int fscmp = mkNamedPCmp(p, "FS");
00037 if (fscmp != EQUIVALENT) return fscmp;
00038
00039
00040 const InvMassFinalState& other = dynamic_cast<const InvMassFinalState&>(p);
00041 fscmp = FinalState::compare(other);
00042 if (fscmp != EQUIVALENT) return fscmp;
00043
00044
00045 int masstypecmp = cmp(_useTransverseMass, other._useTransverseMass);
00046 if (masstypecmp != EQUIVALENT) return masstypecmp;
00047 int massllimcmp = cmp(_minmass, other._minmass);
00048 if (massllimcmp != EQUIVALENT) return massllimcmp;
00049 int masshlimcmp = cmp(_maxmass, other._maxmass);
00050 if (masshlimcmp != EQUIVALENT) return masshlimcmp;
00051
00052
00053 int decaycmp = cmp(_decayids, other._decayids);
00054 if (decaycmp != EQUIVALENT) return decaycmp;
00055
00056
00057 return FinalState::compare(other);
00058 }
00059
00060
00061
00062 void InvMassFinalState::project(const Event& e) {
00063 const FinalState& fs = applyProjection<FinalState>(e, "FS");
00064 calc(fs.particles());
00065 }
00066
00067 void InvMassFinalState::calc(const ParticleVector& inparticles) {
00068 _theParticles.clear();
00069 _particlePairs.clear();
00070
00071
00072 vector<const Particle*> type1;
00073 vector<const Particle*> type2;
00074
00075 foreach (const Particle& ipart, inparticles) {
00076
00077 foreach (const PdgIdPair& ipair, _decayids) {
00078 if (ipart.pdgId() == ipair.first) {
00079 if (accept(ipart)) {
00080 type1 += &ipart;
00081 }
00082 } else if (ipart.pdgId() == ipair.second) {
00083 if (accept(ipart)) {
00084 type2 += &ipart;
00085 }
00086 }
00087 }
00088 }
00089 if(type1.empty() || type2.empty()) return;
00090
00091
00092
00093
00094 vector<const Particle*> tmp;
00095
00096
00097 pair<double, pair<Particle, Particle> > closestPair;
00098 closestPair.first = 1e30;
00099 foreach (const Particle* i1, type1) {
00100 foreach (const Particle* i2, type2) {
00101
00102
00103 bool found = false;
00104 foreach (const PdgIdPair& ipair, _decayids) {
00105 if (i1->pdgId() == ipair.first && i2->pdgId() == ipair.second) {
00106 found = true;
00107 break;
00108 }
00109 }
00110 if (!found) continue;
00111
00112 FourMomentum v4 = i1->momentum() + i2->momentum();
00113 if (v4.mass2() < 0) {
00114 MSG_DEBUG("Constructed negative inv mass2: skipping!");
00115 continue;
00116 }
00117 bool passedMassCut = false;
00118 if (_useTransverseMass) {
00119 passedMassCut = inRange(v4.massT(), _minmass, _maxmass);
00120 } else {
00121 passedMassCut = inRange(v4.mass(), _minmass, _maxmass);
00122 }
00123
00124 if (passedMassCut) {
00125 MSG_DEBUG("Selecting particles with IDs " << i1->pdgId() << " & " << i2->pdgId()
00126 << " and mass = " << v4.mass()/GeV << " GeV");
00127
00128 if (find(tmp.begin(), tmp.end(), i1) == tmp.end()) {
00129 tmp.push_back(i1);
00130 _theParticles += *i1;
00131 }
00132 if (find(tmp.begin(), tmp.end(), i2) == tmp.end()) {
00133 tmp.push_back(i2);
00134 _theParticles += *i2;
00135 }
00136
00137 _particlePairs += make_pair(*i1, *i2);
00138 if (_masstarget>0.0) {
00139 double diff=fabs(v4.mass()-_masstarget);
00140 if (diff<closestPair.first) {
00141 closestPair.first=diff;
00142 closestPair.second=make_pair(*i1, *i2);
00143 }
00144 }
00145 }
00146 }
00147 }
00148 if (_masstarget > 0.0 && closestPair.first < 1e30) {
00149 _theParticles.clear();
00150 _particlePairs.clear();
00151 _theParticles += closestPair.second.first;
00152 _theParticles += closestPair.second.second;
00153 _particlePairs += closestPair.second;
00154 }
00155
00156 MSG_DEBUG("Selected " << _theParticles.size() << " particles " << "(" << _particlePairs.size() << " pairs)");
00157 if (getLog().isActive(Log::TRACE)) {
00158 foreach (const Particle& p, _theParticles) {
00159 MSG_TRACE("ID: " << p.pdgId() << ", barcode: " << p.genParticle().barcode());
00160 }
00161 }
00162 }
00163
00164
00165
00166 const std::vector<std::pair<Particle, Particle> >& InvMassFinalState::particlePairs() const {
00167 return _particlePairs;
00168 }
00169
00170
00171 }