InvMassFinalState.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
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, // pair of decay products
00011                                        double minmass, // min inv mass
00012                                        double maxmass, // max inv mass
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,  // vector of pairs of decay products
00024                                        double minmass, // min inv mass
00025                                        double maxmass, // max inv mass
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     // First compare the final states we are running on
00036     int fscmp = mkNamedPCmp(p, "FS");
00037     if (fscmp != EQUIVALENT) return fscmp;
00038 
00039     // Then compare the two as final states
00040     const InvMassFinalState& other = dynamic_cast<const InvMassFinalState&>(p);
00041     fscmp = FinalState::compare(other);
00042     if (fscmp != EQUIVALENT) return fscmp;
00043 
00044     // Compare the mass limits
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     // Compare the decay species
00053     int decaycmp = cmp(_decayids, other._decayids);
00054     if (decaycmp != EQUIVALENT) return decaycmp;
00055 
00056     // Finally compare them as final states
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     // Containers for the particles of type specified in the pair
00072     vector<const Particle*> type1;
00073     vector<const Particle*> type2;
00074     // Get all the particles of the type specified in the pair from the particle list
00075     foreach (const Particle& ipart, inparticles) {
00076       // Loop around possible particle pairs (typedef needed to keep BOOST_FOREACH happy)
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     // Temporary container of selected particles iterators
00092     // Useful to compare iterators and avoid double occurrences of the same
00093     // particle in case it matches with more than another particle
00094     vector<const Particle*> tmp;
00095 
00096     // Now calculate the inv mass
00097     pair<double, pair<Particle, Particle> > closestPair;
00098     closestPair.first = 1e30;
00099     foreach (const Particle* i1, type1) {
00100       foreach (const Particle* i2, type2) {
00101         // check this is actually a pair
00102         // (if more than one pair in vector particles can be unrelated)
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           // Store accepted particles, avoiding duplicates
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           // Store accepted particle pairs
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   /// Constituent pairs
00166   const std::vector<std::pair<Particle, Particle> >& InvMassFinalState::particlePairs() const {
00167     return _particlePairs;
00168   }
00169 
00170 
00171 }