00001 #ifndef CandUtils_CandMatcher_h
00002 #define CandUtils_CandMatcher_h
00003
00004
00005
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
00159
00160 set<size_t> momsIntersection, momDaughters, tmp;
00161 for( Candidate::const_iterator d = c.begin(); d != c.end(); ++ d ) {
00162
00163 ref_type m = (*this)( * d );
00164
00165 if ( m.isNull() ) return ref_type();
00166
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
00176 if ( momDaughters.size() == 0 ) return ref_type();
00177
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
00189 if ( momsIntersection.size() > 1 ) return ref_type();
00190
00191 return ref_type( matched_, * momsIntersection.begin() );
00192 } else {
00193
00194
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
00236 return( c.numberOfDaughters() == m.numberOfDaughters() );
00237 }
00238
00239 #endif