CMS 3D CMS Logo

CandMatcher.h

Go to the documentation of this file.
00001 #ifndef CandUtils_CandMatcher_h
00002 #define CandUtils_CandMatcher_h
00003 /* class CandMatcher
00004  *
00005  * \author Luca Lista, INFN
00006  *
00007  */
00008 #include <set>
00009 #include "DataFormats/Candidate/interface/Candidate.h"
00010 #include "DataFormats/Common/interface/AssociationMap.h"
00011 #include "DataFormats/Common/interface/OneToOne.h"
00012 #include "FWCore/Utilities/interface/EDMException.h"
00013 #include "PhysicsTools/CandUtils/interface/CandMapTrait.h"
00014 
00015 template<typename C1, typename C2 = C1>
00016 class CandMatcherBase {
00017 public:
00019   typedef typename reco::helper::CandMapTrait<C1, C2>::type map_type;
00021   typedef typename reco::helper::CandRefTrait<C2>::ref_type ref_type;
00023   typedef typename reco::helper::CandRefTrait<C2>::refProd_type refProd_type;
00025   typedef std::vector<const map_type *> map_vector;
00027   typedef typename map_type::key_type reference_type;
00029   typedef typename reference_type::value_type value_type;
00031   explicit CandMatcherBase( const map_vector & maps );
00033   explicit CandMatcherBase( const map_type & map );
00035   virtual ~CandMatcherBase();
00037   ref_type operator()( const reco::Candidate & ) const;
00038 
00039 protected:
00041   virtual std::vector<const reco::Candidate *> getDaughters( const reco::Candidate * ) const = 0;
00043   virtual bool compositePreselect( const reco::Candidate & c, const reco::Candidate & m ) const = 0;
00045   void initMaps();
00046 
00047 protected:
00048   const std::vector<const map_type *> & maps() const { return maps_; }
00049 private:
00051   std::vector<const map_type *> maps_;
00053   refProd_type matched_;
00055   typedef std::map<const reco::Candidate *, reference_type> CandRefMap;
00057   typedef std::map<const reco::Candidate *, ref_type> MatchedRefMap;
00059   CandRefMap candRefs_;
00061   MatchedRefMap matchedRefs_;
00063   std::vector<std::set<size_t> > matchedMothers_;
00065   void init();
00066 };
00067 
00068 template<typename C1, typename C2 = C1>
00069 class CandMatcher : public CandMatcherBase<C1, C2> {
00070 public:
00072   explicit CandMatcher( const typename CandMatcherBase<C1, C2>::map_vector & maps );
00074   explicit CandMatcher( const typename CandMatcherBase<C1, C2>::map_type & map );
00076   virtual ~CandMatcher();
00077 
00078 protected:
00080   virtual std::vector<const reco::Candidate *> getDaughters( const reco::Candidate * ) const;
00082   virtual bool compositePreselect( const reco::Candidate & c, const reco::Candidate & m ) const;
00083 };
00084 
00085 #include <algorithm>
00086 #include <iterator>
00087 
00088 template<typename C1, typename C2>
00089 void CandMatcherBase<C1, C2>::init() {
00090   matched_ = maps_.front()->refProd().val;
00091   for( typename map_vector::const_iterator m = maps_.begin() + 1; 
00092        m != maps_.end(); ++ m ) {
00093     if( (*m)->refProd().val != matched_ )
00094       throw edm::Exception( edm::errors::InvalidReference )
00095         << "Multiple match maps specified matching different MC truth collections.\n"
00096         << "Please, specify maps all matching to the same MC truth collection.\n"
00097         << "In most of the cases you may want to match to genParticleCandidate.";
00098   }
00099 }
00100 
00101 template<typename C1, typename C2>
00102 CandMatcherBase<C1, C2>::CandMatcherBase( const typename CandMatcherBase<C1, C2>::map_vector & maps ):
00103   maps_( maps ) {
00104   init();
00105 }
00106 
00107 template<typename C1, typename C2>
00108 CandMatcherBase<C1, C2>::CandMatcherBase( const typename CandMatcherBase<C1, C2>::map_type & map ):
00109   maps_( 1, & map ) {
00110   init();
00111 }
00112 
00113 template<typename C1, typename C2>
00114 void CandMatcherBase<C1, C2>::initMaps() {
00115   using namespace reco;
00116   using namespace std;
00117   for( typename map_vector::const_iterator m = maps_.begin(); 
00118        m != maps_.end(); ++ m ) {
00119     typename CandMatcherBase<C1, C2>::map_type::ref_type::key_type cands = (*m)->refProd().key;
00120     for( size_t i = 0; i < cands->size(); ++ i ) {
00121       candRefs_[ & (*cands)[ i ] ] = reference_type( cands, i );
00122     } 
00123     const C2 & matched = * matched_;
00124     size_t matchedSize = matched.size();
00125     for( size_t i = 0; i < matchedSize; ++ i )
00126       matchedRefs_[ & matched[ i ] ] = ref_type( matched_, i );
00127     matchedMothers_.resize( matchedSize );
00128     for( size_t i = 0; i < matchedSize; ++ i ) {
00129       const Candidate & c = matched[ i ];
00130       for( Candidate::const_iterator d = c.begin(); d != c.end(); ++ d ) {
00131         vector<const Candidate *> daus = getDaughters( & * d );
00132         for( size_t j = 0; j < daus.size(); ++ j ) {
00133           const Candidate * daughter = daus[ j ];
00134           typename MatchedRefMap::const_iterator f = matchedRefs_.find( daughter );
00135           if ( f == matchedRefs_.end() ) continue;
00136           size_t k = f->second.key();
00137           assert( k < matchedMothers_.size() );
00138           matchedMothers_[ k ].insert( i );
00139         }
00140       }
00141     }
00142   }
00143 }
00144 
00145 template<typename C1, typename C2>
00146 CandMatcherBase<C1, C2>::~CandMatcherBase() {
00147 }
00148 
00149 template<typename C1, typename C2>
00150 typename CandMatcherBase<C1, C2>::ref_type CandMatcherBase<C1, C2>::operator()( const reco::Candidate & c ) const {
00151   using namespace reco;
00152   using namespace std;
00153   if ( c.hasMasterClone() )
00154     return (*this)( * c.masterClone() );
00155   unsigned int nDau = c.numberOfDaughters();
00156   const C2 & matched = * matched_;
00157   if ( nDau > 0 ) {
00158     // check for composite candidate c
00159     // navigate to daughters and find parent matches
00160     set<size_t> momsIntersection, momDaughters, tmp;
00161     for( Candidate::const_iterator d = c.begin(); d != c.end(); ++ d ) {
00162       // check here generically if status == 3, then descend down to one more level
00163       ref_type m = (*this)( * d );
00164       // if a daughter does not match, return a null ref.
00165       if ( m.isNull() ) return ref_type();
00166       // get matched mother indices (fetched previously)
00167       const set<size_t> & allMomDaughters = matchedMothers_[ m.key() ];
00168       momDaughters.clear();
00169       for( set<size_t>::const_iterator k = allMomDaughters.begin(); 
00170            k != allMomDaughters.end(); ++ k ) {
00171         size_t m = * k;
00172         if( compositePreselect( c, matched[ m ] ) )
00173           momDaughters.insert( m );
00174       }
00175       // if no mother was found return null reference
00176       if ( momDaughters.size() == 0 ) return ref_type();
00177       // the first time, momsIntersection is set to momDaughters
00178       if ( momsIntersection.size() == 0 ) momsIntersection = momDaughters;
00179       else {
00180         tmp.clear();
00181         set_intersection( momsIntersection.begin(), momsIntersection.end(),
00182                           momDaughters.begin(), momDaughters.end(),
00183                          inserter( tmp, tmp.begin() ) );
00184         swap( momsIntersection, tmp );
00185       }
00186       if ( momsIntersection.size() == 0 ) return ref_type();
00187     }
00188     // if multiple mothers are found, return a null reference
00189     if ( momsIntersection.size() > 1 ) return ref_type();
00190     // return a reference to the unique mother
00191     return ref_type( matched_, * momsIntersection.begin() );
00192   } else {
00193     // check for non-composite (leaf) candidate 
00194     // if one of the maps contains the candidate c
00195     for( typename std::vector<const map_type *>::const_iterator m = maps_.begin(); 
00196          m != maps_.end(); ++ m ) {
00197       typename CandRefMap::const_iterator f = candRefs_.find( & c );
00198       if ( f != candRefs_.end() ) {
00199         reference_type ref = f->second;
00200         typename map_type::const_iterator f = (*m)->find( ref );
00201         if ( f != (*m)->end() ) {
00202           return f->val;
00203         }
00204       }
00205     }
00206     return ref_type();
00207   }
00208 }
00209 
00210 template<typename C1, typename C2>
00211 CandMatcher<C1, C2>::CandMatcher( const typename CandMatcherBase<C1, C2>::map_vector & maps ) :
00212   CandMatcherBase<C1, C2>( maps ) {
00213   CandMatcherBase<C1, C2>::initMaps();
00214 }
00215 
00216 template<typename C1, typename C2>
00217 CandMatcher<C1, C2>::CandMatcher( const typename CandMatcherBase<C1, C2>::map_type & map ) :
00218   CandMatcherBase<C1, C2>( map ) {
00219   CandMatcherBase<C1, C2>::initMaps();
00220 }
00221 
00222 template<typename C1, typename C2>
00223 CandMatcher<C1, C2>::~CandMatcher() {
00224 }
00225 
00226 template<typename C1, typename C2>
00227 std::vector<const reco::Candidate *> CandMatcher<C1, C2>::getDaughters( const reco::Candidate * c ) const {
00228   std::vector<const reco::Candidate *> v;
00229   v.push_back( c );
00230   return v;
00231 }
00232 
00233 template<typename C1, typename C2>
00234 bool CandMatcher<C1, C2>::compositePreselect( const reco::Candidate & c, const reco::Candidate & m ) const {
00235   // By default, check that the number of daughters is identical
00236   return( c.numberOfDaughters() == m.numberOfDaughters() );
00237 }
00238 
00239 #endif

Generated on Tue Jun 9 17:40:58 2009 for CMSSW by  doxygen 1.5.4