rivet is hosted by Hepforge, IPPP Durham
InvMassFinalState.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Projections/InvMassFinalState.hh"
00003 
00004 namespace Rivet {
00005 
00006 
00007   InvMassFinalState::InvMassFinalState(const FinalState& fsp,
00008                                        const pair<PdgId, PdgId>& idpair, // pair of decay products
00009                                        double minmass, // min inv mass
00010                                        double maxmass, // max inv mass
00011                                        double masstarget)
00012     : _minmass(minmass), _maxmass(maxmass), _masstarget(masstarget), _useTransverseMass(false)
00013   {
00014     setName("InvMassFinalState");
00015     addProjection(fsp, "FS");
00016     _decayids.push_back(idpair);
00017   }
00018 
00019 
00020   InvMassFinalState::InvMassFinalState(const FinalState& fsp,
00021                                        const vector<pair<PdgId, PdgId> >& idpairs,  // vector of pairs of decay products
00022                                        double minmass, // min inv mass
00023                                        double maxmass, // max inv mass
00024                                        double masstarget)
00025     : _decayids(idpairs), _minmass(minmass), _maxmass(maxmass), _masstarget(masstarget), _useTransverseMass(false)
00026   {
00027     setName("InvMassFinalState");
00028     addProjection(fsp, "FS");
00029   }
00030 
00031 
00032   InvMassFinalState::InvMassFinalState(const pair<PdgId, PdgId>& idpair, // pair of decay products
00033                                        double minmass, // min inv mass
00034                                        double maxmass, // max inv mass
00035                                        double masstarget)
00036     : _minmass(minmass), _maxmass(maxmass), _masstarget(masstarget), _useTransverseMass(false)
00037   {
00038     setName("InvMassFinalState");
00039     _decayids.push_back(idpair);
00040   }
00041 
00042 
00043   InvMassFinalState::InvMassFinalState(const vector<pair<PdgId, PdgId> >& idpairs,  // vector of pairs of decay products
00044                                        double minmass, // min inv mass
00045                                        double maxmass, // max inv mass
00046                                        double masstarget)
00047     : _decayids(idpairs), _minmass(minmass), _maxmass(maxmass), _masstarget(masstarget), _useTransverseMass(false)
00048   {
00049     setName("InvMassFinalState");
00050   }
00051 
00052 
00053   int InvMassFinalState::compare(const Projection& p) const {
00054     // First compare the final states we are running on
00055     int fscmp = mkNamedPCmp(p, "FS");
00056     if (fscmp != EQUIVALENT) return fscmp;
00057 
00058     // Then compare the two as final states
00059     const InvMassFinalState& other = dynamic_cast<const InvMassFinalState&>(p);
00060     fscmp = FinalState::compare(other);
00061     if (fscmp != EQUIVALENT) return fscmp;
00062 
00063     // Compare the mass limits
00064     int masstypecmp = cmp(_useTransverseMass, other._useTransverseMass);
00065     if (masstypecmp != EQUIVALENT) return masstypecmp;
00066     int massllimcmp = cmp(_minmass, other._minmass);
00067     if (massllimcmp != EQUIVALENT) return massllimcmp;
00068     int masshlimcmp = cmp(_maxmass, other._maxmass);
00069     if (masshlimcmp != EQUIVALENT) return masshlimcmp;
00070 
00071     // Compare the decay species
00072     int decaycmp = cmp(_decayids, other._decayids);
00073     if (decaycmp != EQUIVALENT) return decaycmp;
00074 
00075     // Finally compare them as final states
00076     return FinalState::compare(other);
00077   }
00078 
00079 
00080   void InvMassFinalState::project(const Event& e) {
00081     const FinalState& fs = applyProjection<FinalState>(e, "FS");
00082     calc(fs.particles());
00083   }
00084 
00085 
00086   void InvMassFinalState::calc(const Particles& inparticles) {
00087     _theParticles.clear();
00088     _particlePairs.clear();
00089 
00090     // Containers for the particles of type specified in the pair
00091     vector<const Particle*> type1;
00092     vector<const Particle*> type2;
00093     // Get all the particles of the type specified in the pair from the particle list
00094     foreach (const Particle& ipart, inparticles) {
00095       // Loop around possible particle pairs (typedef needed to keep BOOST_FOREACH happy)
00096       foreach (const PdgIdPair& ipair, _decayids) {
00097         if (ipart.pdgId() == ipair.first) {
00098           if (accept(ipart)) {
00099             type1 += &ipart;
00100           }
00101         } else if (ipart.pdgId() == ipair.second) {
00102           if (accept(ipart)) {
00103             type2 += &ipart;
00104           }
00105         }
00106       }
00107     }
00108     if (type1.empty() || type2.empty()) return;
00109 
00110     // Temporary container of selected particles iterators
00111     // Useful to compare iterators and avoid double occurrences of the same
00112     // particle in case it matches with more than another particle
00113     vector<const Particle*> tmp;
00114 
00115     // Now calculate the inv mass
00116     pair<double, pair<Particle, Particle> > closestPair;
00117     closestPair.first = 1e30;
00118     foreach (const Particle* i1, type1) {
00119       foreach (const Particle* i2, type2) {
00120         // Check this is actually a pair
00121         // (if more than one pair in vector particles can be unrelated)
00122         bool found = false;
00123         foreach (const PdgIdPair& ipair, _decayids) {
00124           if (i1->pdgId() == ipair.first && i2->pdgId() == ipair.second) {
00125             found = true;
00126             break;
00127           }
00128         }
00129         if (!found) continue;
00130 
00131         FourMomentum v4 = i1->momentum() + i2->momentum();
00132         if (v4.mass2() < 0) {
00133           MSG_DEBUG("Constructed negative inv mass2: skipping!");
00134           continue;
00135         }
00136         bool passedMassCut = false;
00137         if (_useTransverseMass) {
00138           passedMassCut = inRange(massT(i1->momentum(), i2->momentum()), _minmass, _maxmass);
00139         } else {
00140           passedMassCut = inRange(v4.mass(), _minmass, _maxmass);
00141         }
00142 
00143         if (passedMassCut) {
00144           MSG_DEBUG("Selecting particles with IDs " << i1->pdgId() << " & " << i2->pdgId()
00145                     << " and mass = " << v4.mass()/GeV << " GeV");
00146           // Store accepted particles, avoiding duplicates
00147           if (find(tmp.begin(), tmp.end(), i1) == tmp.end()) {
00148             tmp.push_back(i1);
00149             _theParticles += *i1;
00150           }
00151           if (find(tmp.begin(), tmp.end(), i2) == tmp.end()) {
00152             tmp.push_back(i2);
00153             _theParticles += *i2;
00154           }
00155           // Store accepted particle pairs
00156           _particlePairs += make_pair(*i1, *i2);
00157           if (_masstarget>0.0) {
00158             double diff=fabs(v4.mass()-_masstarget);
00159             if (diff<closestPair.first) {
00160               closestPair.first=diff;
00161               closestPair.second=make_pair(*i1, *i2);
00162             }
00163           }
00164         }
00165       }
00166     }
00167     if (_masstarget > 0.0 && closestPair.first < 1e30) {
00168       _theParticles.clear();
00169       _particlePairs.clear();
00170       _theParticles += closestPair.second.first;
00171       _theParticles += closestPair.second.second;
00172       _particlePairs += closestPair.second;
00173     }
00174 
00175     MSG_DEBUG("Selected " << _theParticles.size() << " particles " << "(" << _particlePairs.size() << " pairs)");
00176     if (getLog().isActive(Log::TRACE)) {
00177       foreach (const Particle& p, _theParticles) {
00178         MSG_TRACE("ID: " << p.pdgId() << ", barcode: " << p.genParticle()->barcode());
00179       }
00180     }
00181   }
00182 
00183 
00184   /// Constituent pairs
00185   const std::vector<std::pair<Particle, Particle> >& InvMassFinalState::particlePairs() const {
00186     return _particlePairs;
00187   }
00188 
00189 
00190 }