00001 #ifndef PhysicsTools_PatUtils_ShiftedParticleProducerT_h 00002 #define PhysicsTools_PatUtils_ShiftedParticleProducerT_h 00003 00019 #include "FWCore/Framework/interface/EDProducer.h" 00020 #include "FWCore/Framework/interface/Event.h" 00021 #include "FWCore/Framework/interface/EventSetup.h" 00022 #include "FWCore/ParameterSet/interface/ParameterSet.h" 00023 #include "FWCore/Utilities/interface/InputTag.h" 00024 00025 #include "CommonTools/Utils/interface/StringCutObjectSelector.h" 00026 #include "DataFormats/Candidate/interface/Candidate.h" 00027 00028 #include <string> 00029 #include <vector> 00030 00031 template <typename T> 00032 class ShiftedParticleProducerT : public edm::EDProducer 00033 { 00034 typedef std::vector<T> ParticleCollection; 00035 00036 public: 00037 00038 explicit ShiftedParticleProducerT(const edm::ParameterSet& cfg) 00039 : moduleLabel_(cfg.getParameter<std::string>("@module_label")) 00040 { 00041 src_ = cfg.getParameter<edm::InputTag>("src"); 00042 00043 shiftBy_ = cfg.getParameter<double>("shiftBy"); 00044 00045 if ( cfg.exists("binning") ) { 00046 typedef std::vector<edm::ParameterSet> vParameterSet; 00047 vParameterSet cfgBinning = cfg.getParameter<vParameterSet>("binning"); 00048 for ( vParameterSet::const_iterator cfgBinningEntry = cfgBinning.begin(); 00049 cfgBinningEntry != cfgBinning.end(); ++cfgBinningEntry ) { 00050 binning_.push_back(new binningEntryType(*cfgBinningEntry)); 00051 } 00052 } else { 00053 double uncertainty = cfg.getParameter<double>("uncertainty"); 00054 binning_.push_back(new binningEntryType(uncertainty)); 00055 } 00056 00057 produces<ParticleCollection>(); 00058 } 00059 ~ShiftedParticleProducerT() 00060 { 00061 for ( typename std::vector<binningEntryType*>::const_iterator it = binning_.begin(); 00062 it != binning_.end(); ++it ) { 00063 delete (*it); 00064 } 00065 } 00066 00067 private: 00068 00069 void produce(edm::Event& evt, const edm::EventSetup& es) 00070 { 00071 edm::Handle<ParticleCollection> originalParticles; 00072 evt.getByLabel(src_, originalParticles); 00073 00074 std::auto_ptr<ParticleCollection> shiftedParticles(new ParticleCollection); 00075 00076 for ( typename ParticleCollection::const_iterator originalParticle = originalParticles->begin(); 00077 originalParticle != originalParticles->end(); ++originalParticle ) { 00078 00079 double uncertainty = 0.; 00080 for ( typename std::vector<binningEntryType*>::iterator binningEntry = binning_.begin(); 00081 binningEntry != binning_.end(); ++binningEntry ) { 00082 if ( (!(*binningEntry)->binSelection_) || (*(*binningEntry)->binSelection_)(*originalParticle) ) { 00083 uncertainty = (*binningEntry)->binUncertainty_; 00084 break; 00085 } 00086 } 00087 00088 double shift = shiftBy_*uncertainty; 00089 00090 reco::Candidate::LorentzVector shiftedParticleP4 = originalParticle->p4(); 00091 shiftedParticleP4 *= (1. + shift); 00092 00093 T shiftedParticle(*originalParticle); 00094 shiftedParticle.setP4(shiftedParticleP4); 00095 00096 shiftedParticles->push_back(shiftedParticle); 00097 } 00098 00099 evt.put(shiftedParticles); 00100 } 00101 00102 std::string moduleLabel_; 00103 00104 edm::InputTag src_; 00105 00106 struct binningEntryType 00107 { 00108 binningEntryType(double uncertainty) 00109 : binSelection_(0), 00110 binUncertainty_(uncertainty) 00111 {} 00112 binningEntryType(const edm::ParameterSet& cfg) 00113 : binSelection_(new StringCutObjectSelector<T>(cfg.getParameter<std::string>("binSelection"))), 00114 binUncertainty_(cfg.getParameter<double>("binUncertainty")) 00115 {} 00116 ~binningEntryType() 00117 { 00118 delete binSelection_; 00119 } 00120 StringCutObjectSelector<T>* binSelection_; 00121 double binUncertainty_; 00122 }; 00123 std::vector<binningEntryType*> binning_; 00124 00125 double shiftBy_; // set to +1.0/-1.0 for up/down variation of energy scale 00126 }; 00127 00128 #endif 00129 00130 00131 00132