00001 #include "FWCore/Framework/interface/EDProducer.h" 00002 #include "FWCore/Utilities/interface/InputTag.h" 00003 #include "FWCore/ParameterSet/interface/ParameterSet.h" 00004 #include "FWCore/Framework/interface/Event.h" 00005 #include "DataFormats/Common/interface/Handle.h" 00006 #include "DataFormats/HepMCCandidate/interface/GenParticle.h" 00007 #include "CommonTools/Utils/interface/StringCutObjectSelector.h" 00008 #include "FWCore/Utilities/interface/EDMException.h" 00009 #include "PhysicsTools/HepMCCandAlgos/interface/PdgEntryReplacer.h" 00010 00011 namespace helper { 00012 struct SelectCode { 00013 enum KeepOrDrop { kKeep, kDrop }; 00014 enum FlagDepth { kNone, kFirst, kAll }; 00015 KeepOrDrop keepOrDrop_; 00016 FlagDepth daughtersDepth_, mothersDepth_; 00017 bool all_; 00018 }; 00019 } 00020 00021 class GenParticlePruner : public edm::EDProducer { 00022 public: 00023 GenParticlePruner(const edm::ParameterSet&); 00024 private: 00025 void produce(edm::Event&, const edm::EventSetup&); 00026 bool firstEvent_; 00027 edm::InputTag src_; 00028 int keepOrDropAll_; 00029 std::vector<std::string> selection_; 00030 std::vector<std::pair<StringCutObjectSelector<reco::GenParticle>, helper::SelectCode> > select_; 00031 std::vector<int> flags_; 00032 std::vector<size_t> indices_; 00033 void parse(const std::string & selection, helper::SelectCode & code, std::string & cut) const; 00034 void flagDaughters(const reco::GenParticle &, int); 00035 void flagMothers(const reco::GenParticle &, int); 00036 void recursiveFlagDaughters(size_t, const reco::GenParticleCollection &, int); 00037 void recursiveFlagMothers(size_t, const reco::GenParticleCollection &, int); 00038 void addDaughterRefs(reco::GenParticle&, reco::GenParticleRefProd, const reco::GenParticleRefVector&) const; 00039 void addMotherRefs(reco::GenParticle&, reco::GenParticleRefProd, const reco::GenParticleRefVector&) const; 00040 }; 00041 00042 using namespace edm; 00043 using namespace std; 00044 using namespace reco; 00045 00046 const int keep = 1, drop = -1; 00047 00048 void GenParticlePruner::parse(const std::string & selection, ::helper::SelectCode & code, std::string & cut) const { 00049 using namespace ::helper; 00050 size_t f = selection.find_first_not_of(' '); 00051 size_t n = selection.size(); 00052 string command; 00053 char c; 00054 for(; (c = selection[f]) != ' ' && f < n; ++f) { 00055 command.push_back(c); 00056 } 00057 if(command[0] == '+') { 00058 command.erase(0, 1); 00059 if(command[0] == '+') { 00060 command.erase(0, 1); 00061 code.mothersDepth_ = SelectCode::kAll; 00062 } else { 00063 code.mothersDepth_ = SelectCode::kFirst; 00064 } 00065 } else 00066 code.mothersDepth_ = SelectCode::kNone; 00067 00068 if(command[command.size() - 1] == '+') { 00069 command.erase(command.size() - 1); 00070 if(command[command.size()-1] == '+') { 00071 command.erase(command.size() - 1); 00072 code.daughtersDepth_ = SelectCode::kAll; 00073 } else { 00074 code.daughtersDepth_ = SelectCode::kFirst; 00075 } 00076 } else 00077 code.daughtersDepth_ = SelectCode::kNone; 00078 00079 if(command == "keep") code.keepOrDrop_ = SelectCode::kKeep; 00080 else if(command == "drop") code.keepOrDrop_ = SelectCode::kDrop; 00081 else { 00082 throw Exception(errors::Configuration) 00083 << "invalid selection command: " << command << "\n" << endl; 00084 } 00085 for(; f < n; ++f) { 00086 if(selection[f] != ' ') break; 00087 } 00088 cut = string(selection, f); 00089 if(cut[0] == '*') 00090 cut = string(cut, 0, cut.find_first_of(' ')); 00091 code.all_ = cut == "*"; 00092 } 00093 00094 GenParticlePruner::GenParticlePruner(const ParameterSet& cfg) : 00095 firstEvent_(true), 00096 src_(cfg.getParameter<InputTag>("src")), keepOrDropAll_(drop), 00097 selection_(cfg.getParameter<vector<string> >("select")) { 00098 using namespace ::helper; 00099 produces<GenParticleCollection>(); 00100 } 00101 00102 void GenParticlePruner::flagDaughters(const reco::GenParticle & gen, int keepOrDrop) { 00103 GenParticleRefVector daughters = gen.daughterRefVector(); 00104 for(GenParticleRefVector::const_iterator i = daughters.begin(); i != daughters.end(); ++i) 00105 flags_[i->key()] = keepOrDrop; 00106 } 00107 00108 void GenParticlePruner::flagMothers(const reco::GenParticle & gen, int keepOrDrop) { 00109 GenParticleRefVector mothers = gen.motherRefVector(); 00110 for(GenParticleRefVector::const_iterator i = mothers.begin(); i != mothers.end(); ++i) 00111 flags_[i->key()] = keepOrDrop; 00112 } 00113 00114 void GenParticlePruner::recursiveFlagDaughters(size_t index, const reco::GenParticleCollection & src, int keepOrDrop) { 00115 GenParticleRefVector daughters = src[index].daughterRefVector(); 00116 for(GenParticleRefVector::const_iterator i = daughters.begin(); i != daughters.end(); ++i) { 00117 index = i->key(); 00118 flags_[index] = keepOrDrop; 00119 recursiveFlagDaughters(index, src, keepOrDrop); 00120 } 00121 } 00122 00123 void GenParticlePruner::recursiveFlagMothers(size_t index, const reco::GenParticleCollection & src, int keepOrDrop) { 00124 GenParticleRefVector mothers = src[index].motherRefVector(); 00125 for(GenParticleRefVector::const_iterator i = mothers.begin(); i != mothers.end(); ++i) { 00126 index = i->key(); 00127 flags_[index] = keepOrDrop; 00128 recursiveFlagMothers(index, src, keepOrDrop); 00129 } 00130 } 00131 00132 void GenParticlePruner::produce(Event& evt, const EventSetup& es) { 00133 if (firstEvent_) { 00134 PdgEntryReplacer rep(es); 00135 for(vector<string>::const_iterator i = selection_.begin(); i != selection_.end(); ++i) { 00136 string cut; 00137 ::helper::SelectCode code; 00138 parse(*i, code, cut); 00139 if(code.all_) { 00140 if(i != selection_.begin()) 00141 throw Exception(errors::Configuration) 00142 << "selections \"keep *\" and \"drop *\" can be used only as first options. Here used in position # " 00143 << (i - selection_.begin()) + 1 << "\n" << endl; 00144 switch(code.keepOrDrop_) { 00145 case ::helper::SelectCode::kDrop : 00146 keepOrDropAll_ = drop; break; 00147 case ::helper::SelectCode::kKeep : 00148 keepOrDropAll_ = keep; 00149 }; 00150 } else { 00151 cut = rep.replace(cut); 00152 select_.push_back(make_pair(StringCutObjectSelector<GenParticle>(cut), code)); 00153 } 00154 } 00155 firstEvent_ = false; 00156 } 00157 00158 using namespace ::helper; 00159 Handle<GenParticleCollection> src; 00160 evt.getByLabel(src_, src); 00161 const size_t n = src->size(); 00162 flags_.clear(); 00163 flags_.resize(n, keepOrDropAll_); 00164 for(size_t j = 0; j < select_.size(); ++j) { 00165 const pair<StringCutObjectSelector<GenParticle>, SelectCode> & sel = select_[j]; 00166 SelectCode code = sel.second; 00167 const StringCutObjectSelector<GenParticle> & cut = sel.first; 00168 for(size_t i = 0; i < n; ++i) { 00169 const GenParticle & p = (*src)[i]; 00170 if(cut(p)) { 00171 int keepOrDrop = keep; 00172 switch(code.keepOrDrop_) { 00173 case SelectCode::kKeep: 00174 keepOrDrop = keep; break; 00175 case SelectCode::kDrop: 00176 keepOrDrop = drop; 00177 }; 00178 flags_[i] = keepOrDrop; 00179 switch(code.daughtersDepth_) { 00180 case SelectCode::kAll : 00181 recursiveFlagDaughters(i, *src, keepOrDrop); break; 00182 case SelectCode::kFirst : 00183 flagDaughters(p, keepOrDrop); break; 00184 case SelectCode::kNone: 00185 ; 00186 }; 00187 switch(code.mothersDepth_) { 00188 case SelectCode::kAll : 00189 recursiveFlagMothers(i, *src, keepOrDrop); break; 00190 case SelectCode::kFirst : 00191 flagMothers(p, keepOrDrop); break; 00192 case SelectCode::kNone: 00193 ; 00194 }; 00195 } 00196 } 00197 } 00198 indices_.clear(); 00199 int counter = 0; 00200 for(size_t i = 0; i < n; ++i) { 00201 if(flags_[i] == keep) { 00202 indices_.push_back(i); 00203 flags_[i] = counter++; 00204 } 00205 } 00206 00207 auto_ptr<GenParticleCollection> out(new GenParticleCollection); 00208 GenParticleRefProd outRef = evt.getRefBeforePut<GenParticleCollection>(); 00209 out->reserve(counter); 00210 for(vector<size_t>::const_iterator i = indices_.begin(); i != indices_.end(); ++i) { 00211 size_t index = *i; 00212 const GenParticle & gen = (*src)[index]; 00213 const LeafCandidate & part = gen; 00214 out->push_back(GenParticle(part)); 00215 GenParticle & newGen = out->back(); 00216 addDaughterRefs(newGen, outRef, gen.daughterRefVector()); 00217 addMotherRefs(newGen, outRef, gen.motherRefVector()); 00218 } 00219 00220 evt.put(out); 00221 } 00222 00223 00224 void GenParticlePruner::addDaughterRefs(GenParticle& newGen, GenParticleRefProd outRef, 00225 const GenParticleRefVector& daughters) const { 00226 for(GenParticleRefVector::const_iterator j = daughters.begin(); 00227 j != daughters.end(); ++j) { 00228 GenParticleRef dau = *j; 00229 int idx = flags_[dau.key()]; 00230 if(idx > 0) { 00231 GenParticleRef newDau(outRef, static_cast<size_t>(idx)); 00232 newGen.addDaughter(newDau); 00233 } else { 00234 const GenParticleRefVector daus = dau->daughterRefVector(); 00235 if(daus.size()>0) 00236 addDaughterRefs(newGen, outRef, daus); 00237 } 00238 } 00239 } 00240 00241 void GenParticlePruner::addMotherRefs(GenParticle& newGen, GenParticleRefProd outRef, 00242 const GenParticleRefVector& mothers) const { 00243 for(GenParticleRefVector::const_iterator j = mothers.begin(); 00244 j != mothers.end(); ++j) { 00245 GenParticleRef mom = *j; 00246 int idx = flags_[mom.key()]; 00247 if(idx > 0) { 00248 GenParticleRef newMom(outRef, static_cast<size_t>(idx)); 00249 newGen.addMother(newMom); 00250 } else { 00251 const GenParticleRefVector moms = mom->motherRefVector(); 00252 if(moms.size()>0) 00253 addMotherRefs(newGen, outRef, moms); 00254 } 00255 } 00256 } 00257 00258 #include "FWCore/Framework/interface/MakerMacros.h" 00259 00260 DEFINE_FWK_MODULE(GenParticlePruner);