00001 #ifndef UtilAlgos_PhysObjectMatcher_h
00002 #define UtilAlgos_PhysObjectMatcher_h
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "FWCore/Framework/interface/EDProducer.h"
00014 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00015 #include "FWCore/Utilities/interface/InputTag.h"
00016 #include "CommonTools/UtilAlgos/interface/DeltaR.h"
00017 #include "CommonTools/UtilAlgos/interface/MasterCollectionHelper.h"
00018 #include "FWCore/Framework/interface/Event.h"
00019 #include "DataFormats/Common/interface/Handle.h"
00020 #include "DataFormats/Common/interface/Association.h"
00021 #include "CommonTools/UtilAlgos/interface/MatchByDR.h"
00022
00023
00024
00025 namespace reco {
00026
00027 namespace helper {
00029 template<typename D, typename C1, typename C2> class LessByMatchDistance {
00030 public:
00031 LessByMatchDistance (const edm::ParameterSet& cfg,
00032 const C1& c1, const C2& c2) :
00033 distance_(reco::modules::make<D>(cfg)), c1_(c1), c2_(c2) {}
00034 bool operator() (const std::pair<size_t,size_t>& p1,
00035 const std::pair<size_t,size_t>& p2) const {
00036 return
00037 distance_(c1_[p1.first],c2_[p1.second])<
00038 distance_(c1_[p2.first],c2_[p2.second]);
00039 }
00040 private:
00041 D distance_;
00042 const C1& c1_;
00043 const C2& c2_;
00044 };
00045 }
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 template<typename C1, typename C2, typename S,
00056 typename D = reco::MatchByDR<typename C1::value_type,
00057 typename C2::value_type>,
00058 typename Q =
00059 helper::LessByMatchDistance< DeltaR<typename C1::value_type,
00060 typename C2::value_type>,
00061 C1, C2 >
00062 >
00063 class PhysObjectMatcher : public edm::EDProducer {
00064 public:
00065 PhysObjectMatcher(const edm::ParameterSet & cfg);
00066 ~PhysObjectMatcher();
00067 private:
00068 typedef typename C1::value_type T1;
00069 typedef typename C2::value_type T2;
00070 typedef edm::Association<C2> MatchMap;
00071 typedef std::pair<size_t, size_t> IndexPair;
00072 typedef std::vector<IndexPair> MatchContainer;
00073 void produce(edm::Event&, const edm::EventSetup&) override;
00074 edm::ParameterSet config_;
00075 edm::InputTag src_;
00076 edm::InputTag matched_;
00077 bool resolveAmbiguities_;
00078
00079 bool resolveByMatchQuality_;
00080
00081
00082 bool select(const T1 & c1, const T2 & c2) const {
00083 return select_(c1, c2);
00084 }
00085 S select_;
00086 D distance_;
00087
00088 };
00089
00090 template<typename C1, typename C2, typename S, typename D, typename Q>
00091 PhysObjectMatcher<C1, C2, S, D, Q>::PhysObjectMatcher(const edm::ParameterSet & cfg) :
00092 config_(cfg),
00093 src_(cfg.template getParameter<edm::InputTag>("src")),
00094 matched_(cfg.template getParameter<edm::InputTag>("matched")),
00095 resolveAmbiguities_(cfg.template getParameter<bool>("resolveAmbiguities")),
00096 resolveByMatchQuality_(cfg.template getParameter<bool>("resolveByMatchQuality")),
00097 select_(reco::modules::make<S>(cfg)),
00098 distance_(reco::modules::make<D>(cfg)) {
00099
00100 produces<MatchMap>();
00101
00102 resolveByMatchQuality_ = resolveByMatchQuality_ && resolveAmbiguities_;
00103 }
00104
00105 template<typename C1, typename C2, typename S, typename D, typename Q>
00106 PhysObjectMatcher<C1, C2, S, D, Q>::~PhysObjectMatcher() { }
00107
00108 template<typename C1, typename C2, typename S, typename D, typename Q>
00109 void PhysObjectMatcher<C1, C2, S, D, Q>::produce(edm::Event& evt, const edm::EventSetup&) {
00110 using namespace edm;
00111 using namespace std;
00112 typedef std::pair<size_t, size_t> IndexPair;
00113 typedef std::vector<IndexPair> MatchContainer;
00114
00115 Handle<C2> matched;
00116 evt.getByLabel(matched_, matched);
00117 Handle<C1> cands;
00118 evt.getByLabel(src_, cands);
00119
00120 auto_ptr<MatchMap> matchMap(new MatchMap(matched));
00121 size_t size = cands->size();
00122 if( size != 0 ) {
00123
00124
00125
00126 Q comparator(config_,*cands,*matched);
00127 typename MatchMap::Filler filler(*matchMap);
00128 ::helper::MasterCollection<C1> master(cands);
00129 vector<int> indices(master.size(), -1);
00130 vector<bool> mLock(matched->size(),false);
00131 MatchContainer matchPairs;
00132
00133 for(size_t c = 0; c != size; ++ c) {
00134 const T1 & cand = (*cands)[c];
00135
00136 if ( !resolveByMatchQuality_ ) matchPairs.clear();
00137
00138 for(size_t m = 0; m != matched->size(); ++m) {
00139 const T2 & match = (* matched)[m];
00140
00141 if ( !mLock[m] && select(cand, match)) {
00142
00143
00144
00145
00146
00147 if ( distance_(cand,match) ) matchPairs.push_back(make_pair(c,m));
00148 }
00149 }
00150
00151 if ( matchPairs.size()>0 && !resolveByMatchQuality_ ) {
00152
00153 size_t idx = master.index(c);
00154 assert(idx < indices.size());
00155 size_t index = min_element(matchPairs.begin(), matchPairs.end(), comparator)->second;
00156 indices[idx] = index;
00157
00158
00159 if ( resolveAmbiguities_ ) mLock[index] = true;
00160
00161
00162
00163
00164
00165
00166 }
00167 }
00168
00169 if ( resolveByMatchQuality_ ) {
00170
00171 sort(matchPairs.begin(),matchPairs.end(),comparator);
00172 vector<bool> cLock(master.size(),false);
00173
00174 for ( MatchContainer::const_iterator i=matchPairs.begin();
00175 i!=matchPairs.end(); ++i ) {
00176 size_t c = (*i).first;
00177 size_t m = (*i).second;
00178
00179
00180 if ( mLock[m] || cLock[c] ) continue;
00181
00182 size_t idx = master.index(c);
00183 assert(idx < indices.size());
00184 indices[idx] = m;
00185 mLock[m] = true;
00186 cLock[c] = true;
00187 }
00188 }
00189 filler.insert(master.get(), indices.begin(), indices.end());
00190 filler.fill();
00191 }
00192 evt.put(matchMap);
00193 }
00194
00195 }
00196
00197 #endif