CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/PhysicsTools/HepMCCandAlgos/plugins/GenParticlePruner.cc

Go to the documentation of this file.
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);