00001 /* 00002 * CandViewRefRandomSelector 00003 * 00004 * Author: Evan K. Friis (UC Davis) 00005 * 00006 * Takes a collection of objects inheriting from Candidates and returns up to 00007 * N=<choose> candidates. The N output elements are selected randomly. If 00008 * the collection contains N or fewer elements, the entire collection is 00009 * returned. 00010 * 00011 */ 00012 00013 #include <vector> 00014 00015 #include "FWCore/Framework/interface/Frameworkfwd.h" 00016 #include "FWCore/Framework/interface/EDFilter.h" 00017 #include "FWCore/Framework/interface/Event.h" 00018 #include "FWCore/ParameterSet/interface/ParameterSet.h" 00019 00020 #include "DataFormats/Candidate/interface/Candidate.h" 00021 #include "DataFormats/Candidate/interface/CandidateFwd.h" 00022 00023 #include "TRandom3.h" 00024 00025 class CandViewRefRandomSelector : public edm::EDFilter { 00026 public: 00027 explicit CandViewRefRandomSelector(const edm::ParameterSet &pset); 00028 bool filter(edm::Event&, const edm::EventSetup&); 00029 private: 00030 edm::InputTag src_; 00031 unsigned int choose_; 00032 unsigned int seed_; 00033 bool filter_; 00034 TRandom3 randy_; 00035 }; 00036 00037 CandViewRefRandomSelector::CandViewRefRandomSelector( 00038 const edm::ParameterSet &pset) { 00039 src_ = pset.getParameter<edm::InputTag>("src"); 00040 choose_ = pset.getParameter<unsigned int>("choose"); 00041 filter_ = pset.getParameter<bool>("filter"); 00042 seed_ = pset.exists("seed") ? pset.getParameter<unsigned int>("seed") : 123; 00043 randy_ = TRandom3(seed_); 00044 produces<reco::CandidateBaseRefVector>(); 00045 } 00046 00047 bool CandViewRefRandomSelector::filter(edm::Event& evt, 00048 const edm::EventSetup& es) { 00049 edm::Handle<edm::View<reco::Candidate> > cands; 00050 evt.getByLabel(src_, cands); 00051 std::auto_ptr<reco::CandidateBaseRefVector> output( 00052 new reco::CandidateBaseRefVector(cands)); 00053 // If we don't have enough elements to select, just copy what we have 00054 const reco::CandidateBaseRefVector &inputRefs = cands->refVector(); 00055 if (inputRefs.size() <= choose_) { 00056 *output = inputRefs; 00057 } else { 00058 for (size_t i = 0; i < inputRefs.size() && output->size() < choose_; ++i) { 00059 // based on https://stackoverflow.com/questions/48087/ 00060 // select-a-random-n-elements-from-listt-in-c/48089#48089 00061 double selectionProb = 00062 (choose_ - output->size())*1.0/(inputRefs.size() - i); 00063 // throw a number to see if we select this element 00064 if (randy_.Rndm() < selectionProb) 00065 output->push_back(inputRefs[i]); 00066 } 00067 } 00068 size_t outputSize = output->size(); 00069 evt.put(output); 00070 return ( !filter_ || outputSize ); 00071 } 00072 00073 #include "FWCore/Framework/interface/MakerMacros.h" 00074 DEFINE_FWK_MODULE(CandViewRefRandomSelector);