diff --git a/Configuration/Applications/python/ConfigBuilder.py b/Configuration/Applications/python/ConfigBuilder.py
index b1ba1630e0594..adf1b21365c08 100644
--- a/Configuration/Applications/python/ConfigBuilder.py
+++ b/Configuration/Applications/python/ConfigBuilder.py
@@ -626,6 +626,7 @@ def doNotInlineEventContent(instance,label = "cms.untracked.vstring(process."+th
if self._options.timeoutOutput:
CppType='TimeoutPoolOutputModule'
if streamType=='DQM' and tier=='DQMIO': CppType='DQMRootOutputModule'
+ if "NANOAOD" in streamType and tier=='NANO': CppType='NanoAODOutputModule'
output = cms.OutputModule(CppType,
theEventContent,
fileName = cms.untracked.string(theFileName),
@@ -921,6 +922,7 @@ def define_Configs(self):
self.L1TrackTriggerDefaultCFF="Configuration/StandardSequences/L1TrackTrigger_cff"
self.RECODefaultCFF="Configuration/StandardSequences/Reconstruction_Data_cff"
self.PATDefaultCFF="Configuration/StandardSequences/PAT_cff"
+ self.NANODefaultCFF="PhysicsTools/NanoAOD/nano_cff"
self.EIDefaultCFF=None
self.SKIMDefaultCFF="Configuration/StandardSequences/Skims_cff"
self.POSTRECODefaultCFF="Configuration/StandardSequences/PostRecoGenerator_cff"
@@ -980,6 +982,7 @@ def define_Configs(self):
self.REPACKDefaultSeq='DigiToRawRepack'
self.PATDefaultSeq='miniAOD'
self.PATGENDefaultSeq='miniGEN'
+ self.NANODefaultSeq='nanoSequence'
self.EVTCONTDefaultCFF="Configuration/EventContent/EventContent_cff"
@@ -994,6 +997,7 @@ def define_Configs(self):
self.PATGENDefaultCFF="Configuration/StandardSequences/PATGEN_cff"
self.DQMOFFLINEDefaultCFF="DQMOffline/Configuration/DQMOfflineMC_cff"
self.ALCADefaultCFF="Configuration/StandardSequences/AlCaRecoStreamsMC_cff"
+ self.NANODefaultSeq='nanoSequenceMC'
else:
self._options.beamspot = None
@@ -1687,6 +1691,16 @@ def prepare_PATGEN(self, sequence = "miniGEN"):
raise Exception("PATGEN step can only run on MC")
return
+ def prepare_NANO(self, sequence = "nanoAOD"):
+ ''' Enrich the schedule with NANO '''
+ self.loadDefaultOrSpecifiedCFF(sequence,self.NANODefaultCFF)
+ self.scheduleSequence(sequence.split('.')[-1],'nanoAOD_step')
+ custom = "nanoAOD_customizeData" if self._options.isData else "nanoAOD_customizeMC"
+ if self._options.runUnscheduled:
+ self._options.customisation_file_unsch.insert(0,"PhysicsTools/NanoAOD/nano_cff."+custom)
+ else:
+ self._options.customisation_file.insert(0,"PhysicsTools/NanoAOD/nano_cff."+custom)
+
def prepare_EI(self, sequence = None):
''' Enrich the schedule with event interpretation '''
from Configuration.StandardSequences.EventInterpretation import EventInterpretation
diff --git a/Configuration/Applications/python/cmsDriverOptions.py b/Configuration/Applications/python/cmsDriverOptions.py
index 09b1ec27d7372..32151464d8969 100755
--- a/Configuration/Applications/python/cmsDriverOptions.py
+++ b/Configuration/Applications/python/cmsDriverOptions.py
@@ -101,6 +101,7 @@ def OptionsFromItems(items):
"HARVESTING":"RECO",
"ALCAHARVEST":"RECO",
"PAT":"RECO",
+ "NANO":"PAT",
"PATGEN":"GEN"}
trimmedEvtType=options.evt_type.split('/')[-1]
diff --git a/Configuration/Eras/python/Modifier_run2_nanoAOD_92X_cff.py b/Configuration/Eras/python/Modifier_run2_nanoAOD_92X_cff.py
new file mode 100644
index 0000000000000..fb23bdb06d796
--- /dev/null
+++ b/Configuration/Eras/python/Modifier_run2_nanoAOD_92X_cff.py
@@ -0,0 +1,3 @@
+import FWCore.ParameterSet.Config as cms
+
+run2_nanoAOD_92X = cms.Modifier()
diff --git a/Configuration/StandardSequences/python/Eras.py b/Configuration/StandardSequences/python/Eras.py
index 8da896789fbbe..7f4837606f7a6 100644
--- a/Configuration/StandardSequences/python/Eras.py
+++ b/Configuration/StandardSequences/python/Eras.py
@@ -41,7 +41,7 @@ def __init__(self):
'phase2_hgcal', 'phase2_muon', 'phase2_timing',
'phase2_timing_layer','phase2_hcal',
'trackingLowPU', 'trackingPhase1', 'trackingPhase1QuadProp', 'ctpps_2016', 'trackingPhase2PU140',
- 'tracker_apv_vfp30_2016', 'run2_miniAOD_80XLegacy',
+ 'tracker_apv_vfp30_2016', 'run2_miniAOD_80XLegacy', 'run2_nanoAOD_92X',
'hcalHardcodeConditions', 'hcalSkipPacker']
internalUseModChains = ['run2_2017_noTrackingModifier']
diff --git a/DataFormats/NanoAOD/BuildFile.xml b/DataFormats/NanoAOD/BuildFile.xml
new file mode 100644
index 0000000000000..02ec339df90e2
--- /dev/null
+++ b/DataFormats/NanoAOD/BuildFile.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/DataFormats/NanoAOD/interface/FlatTable.h b/DataFormats/NanoAOD/interface/FlatTable.h
new file mode 100644
index 0000000000000..8a1a5909dc13b
--- /dev/null
+++ b/DataFormats/NanoAOD/interface/FlatTable.h
@@ -0,0 +1,163 @@
+#ifndef DataFormats_NanoAOD_FlatTable_h
+#define DataFormats_NanoAOD_FlatTable_h
+
+#include
+#include
+#include
+#include
+#include "FWCore/Utilities/interface/Exception.h"
+#include "DataFormats/PatCandidates/interface/libminifloat.h"
+
+namespace nanoaod {
+
+namespace flatTableHelper {
+ template struct MaybeMantissaReduce {
+ MaybeMantissaReduce(int mantissaBits) {}
+ inline T one(const T &val) const { return val; }
+ inline void bulk(boost::sub_range> data) const { }
+ };
+ template<> struct MaybeMantissaReduce {
+ int bits_;
+ MaybeMantissaReduce(int mantissaBits) : bits_(mantissaBits) {}
+ inline float one(const float &val) const { return (bits_ > 0 ? MiniFloatConverter::reduceMantissaToNbitsRounding(val, bits_) : val); }
+ inline void bulk(boost::sub_range> data) const { if (bits_ > 0) MiniFloatConverter::reduceMantissaToNbitsRounding(bits_, data.begin(), data.end(), data.begin()); }
+ };
+}
+
+class FlatTable {
+ public:
+ enum ColumnType { FloatColumn, IntColumn, UInt8Column, BoolColumn }; // We could have other Float types with reduced mantissa, and similar
+
+ FlatTable() : size_(0) {}
+ FlatTable(unsigned int size, const std::string & name, bool singleton, bool extension=false) : size_(size), name_(name), singleton_(singleton), extension_(extension) {}
+ ~FlatTable() {}
+
+ unsigned int nColumns() const { return columns_.size(); };
+ unsigned int nRows() const { return size_; };
+ unsigned int size() const { return size_; }
+ bool singleton() const { return singleton_; }
+ bool extension() const { return extension_; }
+ const std::string & name() const { return name_; }
+
+ const std::string & columnName(unsigned int col) const { return columns_[col].name; }
+ int columnIndex(const std::string & name) const ;
+
+ ColumnType columnType(unsigned int col) const { return columns_[col].type; }
+
+ void setDoc(const std::string & doc) { doc_ = doc; }
+ const std::string & doc() const { return doc_; }
+ const std::string & columnDoc(unsigned int col) const { return columns_[col].doc; }
+
+ /// get a column by index (const)
+ template
+ boost::sub_range> columnData(unsigned int column) const {
+ auto begin = beginData(column);
+ return boost::sub_range>(begin, begin+size_);
+ }
+
+ /// get a column by index (non-const)
+ template
+ boost::sub_range> columnData(unsigned int column) {
+ auto begin = beginData(column);
+ return boost::sub_range>(begin, begin+size_);
+ }
+
+ /// get a column value for singleton (const)
+ template
+ const T & columValue(unsigned int column) const {
+ if (!singleton()) throw cms::Exception("LogicError", "columnValue works only for singleton tables");
+ return * beginData(column);
+ }
+
+ template>
+ void addColumn(const std::string & name, const C & values, const std::string & docString, ColumnType type = defaultColumnType(),int mantissaBits=-1) {
+ if (columnIndex(name) != -1) throw cms::Exception("LogicError", "Duplicated column: "+name);
+ if (values.size() != size()) throw cms::Exception("LogicError", "Mismatched size for "+name);
+ check_type(type); // throws if type is wrong
+ auto & vec = bigVector();
+ columns_.emplace_back(name,docString,type,vec.size());
+ vec.insert(vec.end(), values.begin(), values.end());
+ if (type == FloatColumn) {
+ flatTableHelper::MaybeMantissaReduce(mantissaBits).bulk(columnData(columns_.size()-1));
+ }
+ }
+ template
+ void addColumnValue(const std::string & name, const C & value, const std::string & docString, ColumnType type = defaultColumnType(),int mantissaBits=-1) {
+ if (!singleton()) throw cms::Exception("LogicError", "addColumnValue works only for singleton tables");
+ if (columnIndex(name) != -1) throw cms::Exception("LogicError", "Duplicated column: "+name);
+ check_type(type); // throws if type is wrong
+ auto & vec = bigVector();
+ columns_.emplace_back(name,docString,type,vec.size());
+ if (type == FloatColumn) {
+ vec.push_back( flatTableHelper::MaybeMantissaReduce(mantissaBits).one(value) );
+ } else {
+ vec.push_back( value );
+ }
+ }
+
+ template static ColumnType defaultColumnType() { throw cms::Exception("unsupported type"); }
+
+ // this below needs to be public for ROOT, but it is to be considered private otherwise
+ struct Column {
+ std::string name, doc;
+ ColumnType type;
+ unsigned int firstIndex;
+ Column() {} // for ROOT
+ Column(const std::string & aname, const std::string & docString, ColumnType atype, unsigned int anIndex) : name(aname), doc(docString), type(atype), firstIndex(anIndex) {}
+ };
+
+ private:
+
+ template
+ typename std::vector::const_iterator beginData(unsigned int column) const {
+ const Column & col = columns_[column];
+ check_type(col.type); // throws if type is wrong
+ return bigVector().begin() + col.firstIndex;
+ }
+ template
+ typename std::vector::iterator beginData(unsigned int column) {
+ const Column & col = columns_[column];
+ check_type(col.type); // throws if type is wrong
+ return bigVector().begin() + col.firstIndex;
+ }
+
+ template
+ const std::vector & bigVector() const { throw cms::Exception("unsupported type"); }
+ template
+ std::vector & bigVector() { throw cms::Exception("unsupported type"); }
+
+
+ unsigned int size_;
+ std::string name_, doc_;
+ bool singleton_, extension_;
+ std::vector columns_;
+ std::vector floats_;
+ std::vector ints_;
+ std::vector uint8s_;
+
+ template
+ static void check_type(FlatTable::ColumnType type) { throw cms::Exception("unsupported type"); }
+};
+
+template<> inline void FlatTable::check_type(FlatTable::ColumnType type) {
+ if (type != FlatTable::FloatColumn) throw cms::Exception("mismatched type");
+}
+template<> inline void FlatTable::check_type(FlatTable::ColumnType type) {
+ if (type != FlatTable::IntColumn) throw cms::Exception("mismatched type");
+}
+template<> inline void FlatTable::check_type(FlatTable::ColumnType type) {
+ if (type != FlatTable::UInt8Column && type != FlatTable::BoolColumn) throw cms::Exception("mismatched type");
+}
+
+
+
+template<> inline const std::vector & FlatTable::bigVector() const { return floats_; }
+template<> inline const std::vector & FlatTable::bigVector() const { return ints_; }
+template<> inline const std::vector & FlatTable::bigVector() const { return uint8s_; }
+template<> inline std::vector & FlatTable::bigVector() { return floats_; }
+template<> inline std::vector & FlatTable::bigVector() { return ints_; }
+template<> inline std::vector & FlatTable::bigVector() { return uint8s_; }
+
+} // nanoaod
+
+#endif
diff --git a/DataFormats/NanoAOD/interface/MergeableCounterTable.h b/DataFormats/NanoAOD/interface/MergeableCounterTable.h
new file mode 100644
index 0000000000000..cfd99d399b0b9
--- /dev/null
+++ b/DataFormats/NanoAOD/interface/MergeableCounterTable.h
@@ -0,0 +1,111 @@
+#ifndef DataFormats_NanoAOD_MergeableCounterTable_h
+#define DataFormats_NanoAOD_MergeableCounterTable_h
+
+#include "FWCore/Utilities/interface/Exception.h"
+#include
+#include
+
+namespace nanoaod {
+
+class MergeableCounterTable {
+ public:
+ MergeableCounterTable() {}
+ typedef long long int_accumulator; // we accumulate in long long int, to avoid overflow
+ typedef double float_accumulator; // we accumulate in double, to preserve precision
+
+ template
+ struct SingleColumn {
+ typedef T value_type;
+ SingleColumn() {}
+ SingleColumn(const std::string & aname, const std::string & adoc, T avalue = T()) : name(aname), doc(adoc), value(avalue) {}
+ std::string name, doc;
+ T value;
+ void operator+=(const SingleColumn & other) {
+ //// if one arrives here from tryMerge the checks are already done in the compatible() function before.
+ //// you may however want to enable these and remove the 'return false' in tryMerge in order to see what's incompatible between the tables.
+ //if (name != other.name) throw cms::Exception("LogicError", "Trying to merge "+name+" with "+other.name+"\n");
+ value += other.value;
+ }
+ bool compatible(const SingleColumn & other) {
+ return name == other.name; // we don't check the doc, not needed
+ }
+ };
+ typedef SingleColumn FloatColumn;
+ typedef SingleColumn IntColumn;
+
+ template
+ struct VectorColumn {
+ typedef T element_type;
+ VectorColumn() {}
+ VectorColumn(const std::string & aname, const std::string & adoc, unsigned int size) : name(aname), doc(adoc), values(size, T()) {}
+ VectorColumn(const std::string & aname, const std::string & adoc, const std::vector & somevalues) : name(aname), doc(adoc), values(somevalues) {}
+ std::string name, doc;
+ std::vector values;
+ void operator+=(const VectorColumn & other) {
+ //// if one arrives here from tryMerge the checks are already done in the compatible() function before.
+ //// you may however want to enable these and remove the 'return false' in tryMerge in order to see what's incompatible between the tables.
+ //if (name != other.name) throw cms::Exception("LogicError", "Trying to merge "+name+" with "+other.name+"\n");
+ //if (values.size() != other.values.size()) throw cms::Exception("LogicError", "Trying to merge "+name+" with different number of values!\n");
+ for (unsigned int i = 0, n = values.size(); i < n; ++i) {
+ values[i] += other.values[i];
+ }
+ }
+ bool compatible(const VectorColumn & other) {
+ return name == other.name && values.size() == other.values.size(); // we don't check the doc, not needed
+ }
+ };
+ typedef VectorColumn VFloatColumn;
+ typedef VectorColumn VIntColumn;
+
+ const std::vector & floatCols() const { return floatCols_; }
+ const std::vector & vfloatCols() const { return vfloatCols_; }
+ const std::vector & intCols() const { return intCols_; }
+ const std::vector & vintCols() const { return vintCols_; }
+
+ template
+ void addFloat(const std::string & name, const std::string & doc, F value) { floatCols_.push_back(FloatColumn(name, doc, value)); }
+
+ template
+ void addInt(const std::string & name, const std::string & doc, I value) { intCols_.push_back(IntColumn(name, doc, value)); }
+
+ template
+ void addVFloat(const std::string & name, const std::string & doc, const std::vector values) {
+ vfloatCols_.push_back(VFloatColumn(name, doc, values.size()));
+ std::copy(values.begin(), values.end(), vfloatCols_.back().values.begin());
+ }
+
+ template
+ void addVInt(const std::string & name, const std::string & doc, const std::vector values) {
+ vintCols_.push_back(VIntColumn(name, doc, values.size()));
+ std::copy(values.begin(), values.end(), vintCols_.back().values.begin());
+ }
+
+
+ bool mergeProduct(const MergeableCounterTable & other) {
+ if (!tryMerge(intCols_, other.intCols_)) return false;
+ if (!tryMerge(vintCols_, other.vintCols_)) return false;
+ if (!tryMerge(floatCols_, other.floatCols_)) return false;
+ if (!tryMerge(vfloatCols_, other.vfloatCols_)) return false;
+ return true;
+ }
+
+ private:
+ std::vector floatCols_;
+ std::vector vfloatCols_;
+ std::vector intCols_;
+ std::vector vintCols_;
+
+ template
+ bool tryMerge(std::vector & one, const std::vector & two) {
+ if (one.size() != two.size()) return false;
+ for (unsigned int i = 0, n = one.size(); i < n; ++i) {
+ if (!one[i].compatible(two[i])) return false;
+ one[i] += two[i];
+ }
+ return true;
+ }
+};
+
+} // namespace nanoaod
+
+#endif
diff --git a/DataFormats/NanoAOD/interface/UniqueString.h b/DataFormats/NanoAOD/interface/UniqueString.h
new file mode 100644
index 0000000000000..8f2ad35c1c56f
--- /dev/null
+++ b/DataFormats/NanoAOD/interface/UniqueString.h
@@ -0,0 +1,22 @@
+#ifndef PhysicsTools_NanoAOD_UniqueString_h
+#define PhysicsTools_NanoAOD_UniqueString_h
+
+#include
+
+namespace nanoaod {
+
+class UniqueString {
+ public:
+ UniqueString() {}
+ UniqueString(const std::string & str) : str_(str) {}
+ const std::string & str() const { return str_; }
+ bool operator==(const std::string & other) const { return str_ == other; }
+ bool operator==(const UniqueString & other) const { return str_ == other.str_; }
+ bool isProductEqual(const UniqueString & other) const { return (*this) == other; }
+ private:
+ std::string str_;
+};
+
+} // namespace nanoaod
+
+#endif
diff --git a/DataFormats/NanoAOD/src/FlatTable.cc b/DataFormats/NanoAOD/src/FlatTable.cc
new file mode 100644
index 0000000000000..bffa199ed8f95
--- /dev/null
+++ b/DataFormats/NanoAOD/src/FlatTable.cc
@@ -0,0 +1,8 @@
+#include "DataFormats/NanoAOD/interface/FlatTable.h"
+
+int nanoaod::FlatTable::columnIndex(const std::string & name) const {
+ for (unsigned int i = 0, n = columns_.size(); i < n; ++i) {
+ if (columns_[i].name == name) return i;
+ }
+ return -1;
+}
diff --git a/DataFormats/NanoAOD/src/MergeableCounterTable.cc b/DataFormats/NanoAOD/src/MergeableCounterTable.cc
new file mode 100644
index 0000000000000..198dc90966422
--- /dev/null
+++ b/DataFormats/NanoAOD/src/MergeableCounterTable.cc
@@ -0,0 +1 @@
+#include "DataFormats/NanoAOD/interface/MergeableCounterTable.h"
diff --git a/DataFormats/NanoAOD/src/classes.h b/DataFormats/NanoAOD/src/classes.h
new file mode 100644
index 0000000000000..cd21de1d1e072
--- /dev/null
+++ b/DataFormats/NanoAOD/src/classes.h
@@ -0,0 +1,15 @@
+#include "Rtypes.h"
+
+#include "DataFormats/NanoAOD/interface/FlatTable.h"
+#include "DataFormats/NanoAOD/interface/MergeableCounterTable.h"
+#include "DataFormats/NanoAOD/interface/UniqueString.h"
+#include "DataFormats/Common/interface/Wrapper.h"
+
+namespace DataFormats_NanoAOD {
+ struct dictionary {
+ nanoaod::FlatTable table;
+ edm::Wrapper w_table;
+ edm::Wrapper w_mtable;
+ edm::Wrapper w_ustr;
+ };
+}
diff --git a/DataFormats/NanoAOD/src/classes_def.xml b/DataFormats/NanoAOD/src/classes_def.xml
new file mode 100644
index 0000000000000..7c85fe046b919
--- /dev/null
+++ b/DataFormats/NanoAOD/src/classes_def.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DataFormats/PatCandidates/src/PackedCandidate.cc b/DataFormats/PatCandidates/src/PackedCandidate.cc
index b7c5addda4067..3669c6bcc7efe 100644
--- a/DataFormats/PatCandidates/src/PackedCandidate.cc
+++ b/DataFormats/PatCandidates/src/PackedCandidate.cc
@@ -150,7 +150,8 @@ float pat::PackedCandidate::dxy(const Point &p) const {
float pat::PackedCandidate::dz(const Point &p) const {
maybeUnpackBoth();
const float phi = float(p4_.load()->Phi())+dphi_;
- return (vertex_.load()->Z()-p.Z()) - ((vertex_.load()->X()-p.X()) * std::cos(phi) + (vertex_.load()->Y()-p.Y()) * std::sin(phi)) * p4_.load()->Pz()/p4_.load()->Pt();
+ const float pzpt = deta_ ? std::sinh(etaAtVtx()) : p4_.load()->Pz()/p4_.load()->Pt();
+ return (vertex_.load()->Z()-p.Z()) - ((vertex_.load()->X()-p.X()) * std::cos(phi) + (vertex_.load()->Y()-p.Y()) * std::sin(phi)) * pzpt;
}
void pat::PackedCandidate::unpackTrk() const {
@@ -298,11 +299,11 @@ bool pat::PackedCandidate::overlap( const reco::Candidate & o ) const {
}
const reco::Candidate * pat::PackedCandidate::daughter( size_type ) const {
- return 0;
+ return nullptr;
}
const reco::Candidate * pat::PackedCandidate::mother( size_type ) const {
- return 0;
+ return nullptr;
}
const reco::Candidate * pat::PackedCandidate::daughter(const std::string&) const {
@@ -320,7 +321,7 @@ reco::Candidate * pat::PackedCandidate::daughter(const std::string&) {
reco::Candidate * pat::PackedCandidate::daughter( size_type ) {
- return 0;
+ return nullptr;
}
double pat::PackedCandidate::vertexChi2() const {
diff --git a/PhysicsTools/HepMCCandAlgos/plugins/GenVisTauProducer.cc b/PhysicsTools/HepMCCandAlgos/plugins/GenVisTauProducer.cc
new file mode 100644
index 0000000000000..2da65fa1344f7
--- /dev/null
+++ b/PhysicsTools/HepMCCandAlgos/plugins/GenVisTauProducer.cc
@@ -0,0 +1,98 @@
+#include "FWCore/Framework/interface/global/EDProducer.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
+#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
+#include "DataFormats/Common/interface/View.h"
+#include "DataFormats/HepMCCandidate/interface/GenParticle.h"
+#include "DataFormats/HepMCCandidate/interface/GenParticleFwd.h"
+#include "DataFormats/JetReco/interface/GenJet.h"
+#include "DataFormats/JetReco/interface/GenJetCollection.h"
+#include "PhysicsTools/JetMCUtils/interface/JetMCTag.h"
+#include "DataFormats/TauReco/interface/PFTau.h"
+#include "DataFormats/Math/interface/deltaR.h"
+
+#include
+#include
+
+class GenVisTauProducer : public edm::global::EDProducer<>
+{
+ public:
+ GenVisTauProducer(const edm::ParameterSet& params)
+ : src_(consumes(params.getParameter("src")))
+ , srcGenParticles_(consumes(params.getParameter("srcGenParticles")))
+ {
+ produces();
+ }
+
+ ~GenVisTauProducer() override {}
+
+ void produce(edm::StreamID id, edm::Event& evt, const edm::EventSetup& es) const override
+ {
+ edm::Handle genTauJets;
+ evt.getByToken(src_, genTauJets);
+
+ edm::Handle genParticles;
+ evt.getByToken(srcGenParticles_, genParticles);
+ size_t numGenParticles = genParticles->size();
+
+ auto genVisTaus = std::make_unique();
+
+ for (const auto & genTauJet : *genTauJets) {
+ std::string decayMode_string = JetMCTagUtils::genTauDecayMode(genTauJet);
+ // CV: store hadronic tau decays only
+ if ( decayMode_string == "electron" || decayMode_string == "muon" ) continue;
+ int decayMode = reco::PFTau::kNull;
+ if ( decayMode_string == "oneProng0Pi0" ) decayMode = reco::PFTau::kOneProng0PiZero;
+ else if ( decayMode_string == "oneProng1Pi0" ) decayMode = reco::PFTau::kOneProng1PiZero;
+ else if ( decayMode_string == "oneProng2Pi0" ) decayMode = reco::PFTau::kOneProng2PiZero;
+ else if ( decayMode_string == "threeProng0Pi0" ) decayMode = reco::PFTau::kThreeProng0PiZero;
+ else if ( decayMode_string == "threeProng1Pi0" ) decayMode = reco::PFTau::kThreeProng1PiZero;
+ else decayMode = reco::PFTau::kRareDecayMode;
+
+ int pdgId = ( genTauJet.charge() > 0 ) ? -15 : +15;
+
+ // CV: store decayMode in status flag of GenParticle object
+ reco::GenParticle genVisTau(genTauJet.charge(), genTauJet.p4(), genTauJet.vertex(), pdgId, decayMode, true);
+
+ // CV: find tau lepton "mother" particle
+ for ( size_t idxGenParticle = 0; idxGenParticle < numGenParticles; ++idxGenParticle ) {
+ const reco::GenParticle & genTau = (*genParticles)[idxGenParticle];
+ if ( abs(genTau.pdgId()) == 15 && genTau.status() == 2 ) {
+ reco::Candidate::LorentzVector daughterVisP4;
+ for (const reco::GenParticleRef & daughter : genTau.daughterRefVector()) {
+ int abs_pdgId = abs(daughter->pdgId());
+ // CV: skip neutrinos
+ if ( abs_pdgId == 12 || abs_pdgId == 14 || abs_pdgId == 16 ) continue;
+ daughterVisP4 += daughter->p4();
+ }
+ double dR2 = deltaR2(daughterVisP4, genVisTau);
+ if ( dR2 < 1.e-4 ) {
+ genVisTau.addMother(reco::GenParticleRef(genParticles, idxGenParticle));
+ break;
+ }
+ }
+ }
+
+ genVisTaus->push_back(genVisTau);
+ }
+
+ evt.put(std::move(genVisTaus));
+ }
+
+ static void fillDescriptions(edm::ConfigurationDescriptions & descriptions) {
+ edm::ParameterSetDescription desc;
+ desc.add("src")->setComment("collection of visible gen taus (as reco::GenJetCollection)");
+ desc.add("srcGenParticles")->setComment("collections of gen particles");
+ descriptions.add("genVisTaus", desc);
+ }
+
+
+ private:
+ const edm::EDGetTokenT src_;
+ const edm::EDGetTokenT srcGenParticles_;
+};
+
+#include "FWCore/Framework/interface/MakerMacros.h"
+DEFINE_FWK_MODULE(GenVisTauProducer);
+
diff --git a/PhysicsTools/NanoAOD/BuildFile.xml b/PhysicsTools/NanoAOD/BuildFile.xml
new file mode 100644
index 0000000000000..c36ed4184624a
--- /dev/null
+++ b/PhysicsTools/NanoAOD/BuildFile.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/PhysicsTools/NanoAOD/interface/MatchingUtils.h b/PhysicsTools/NanoAOD/interface/MatchingUtils.h
new file mode 100644
index 0000000000000..886a710bb0e46
--- /dev/null
+++ b/PhysicsTools/NanoAOD/interface/MatchingUtils.h
@@ -0,0 +1,56 @@
+#ifndef NanoAOD_MatchingUtils_h
+#define NanoAOD_MatchingUtils_h
+
+/*#include
+#include
+#include "CommonTools/Utils/interface/StringCutObjectSelector.h"
+*/
+template
+bool matchByCommonSourceCandidatePtr(const C1 & c1, const C2 & c2) {
+ for(unsigned int i1 = 0 ; i1 < c1.numberOfSourceCandidatePtrs();i1++){
+ auto c1s=c1.sourceCandidatePtr(i1);
+ for(unsigned int i2 = 0 ; i2 < c2.numberOfSourceCandidatePtrs();i2++) {
+ if(c2.sourceCandidatePtr(i2)==c1s) return true;
+ }
+ }
+ return false;
+}
+
+template
+bool matchByCommonParentSuperClusterRef(const C1 & c1, const C2 & c2) {
+ auto c1s = c1.parentSuperCluster();
+ auto c2s = c2.parentSuperCluster();
+ return (c1s == c2s);
+}
+
+/*
+template
+std::pair bestMatch(auto item, auto targetColl,const StringCutObjectSelector & cut="1") {
+ float deltaR2Min = 9e99;
+ const I & bm;
+ for(const auto & t : targetColl){
+ if(cut(t)) {
+ float dR2 = deltaR2(item,t);
+ if(dR2 < deltaR2Min){
+ deltaR2Min = dR2;
+ bm = t;
+ }
+ }
+ }
+ return std::pair(bm, deltaR2Min);
+}
+
+
+template
+std::vector> matchCollections(auto coll, auto targetColl,const StringCutObjectSelector & cut="1") {
+ std::vector> pairs;
+ if(coll.empty()) return pairs;
+ for(auto & p : coll){
+ pairs.push_back(bestMatch(p,targetColl,cut));
+ }
+ return pairs;
+}
+
+*/
+
+#endif
diff --git a/PhysicsTools/NanoAOD/plugins/BJetEnergyRegressionMVA.cc b/PhysicsTools/NanoAOD/plugins/BJetEnergyRegressionMVA.cc
new file mode 100644
index 0000000000000..d32d0458953af
--- /dev/null
+++ b/PhysicsTools/NanoAOD/plugins/BJetEnergyRegressionMVA.cc
@@ -0,0 +1,109 @@
+//
+// Original Author: Andre Rizzi
+// Created: Mon, 07 Sep 2017 09:18:03 GMT
+//
+//
+
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/stream/EDProducer.h"
+
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/Utilities/interface/StreamID.h"
+
+
+#include "DataFormats/PatCandidates/interface/Muon.h"
+#include "DataFormats/PatCandidates/interface/Electron.h"
+#include "DataFormats/PatCandidates/interface/Jet.h"
+
+#include "DataFormats/VertexReco/interface/Vertex.h"
+#include "DataFormats/Candidate/interface/VertexCompositePtrCandidate.h"
+
+#include "RecoVertex/VertexTools/interface/VertexDistance3D.h"
+#include "RecoVertex/VertexPrimitives/interface/ConvertToFromReco.h"
+#include "RecoVertex/VertexPrimitives/interface/VertexState.h"
+
+#include "PhysicsTools/PatAlgos/plugins/BaseMVAValueMapProducer.h"
+#include
+
+class BJetEnergyRegressionMVA : public BaseMVAValueMapProducer {
+ public:
+ explicit BJetEnergyRegressionMVA(const edm::ParameterSet &iConfig):
+ BaseMVAValueMapProducer(iConfig),
+ pvsrc_(edm::stream::EDProducer<>::consumes>(iConfig.getParameter("pvsrc"))),
+ svsrc_(edm::stream::EDProducer<>::consumes> (iConfig.getParameter("svsrc")))
+
+ {
+
+
+ }
+ void readAdditionalCollections(edm::Event&iEvent, const edm::EventSetup&) override {
+ iEvent.getByToken(pvsrc_, pvs_);
+ iEvent.getByToken(svsrc_, svs_);
+ }
+
+ void fillAdditionalVariables(const pat::Jet&j) override {
+ this->setValue("nPVs",pvs_->size());
+ BaseMVAValueMapProducer::setValue("Jet_leptonPtRel",0);
+
+ if(!j.overlaps("muons").empty()) {
+ const auto *lep=dynamic_cast(&*j.overlaps("muons")[0]);
+ if(lep!=nullptr) {BaseMVAValueMapProducer::setValue("Jet_leptonPtRel",lep->userFloat("ptRel"));}
+ }
+ else if(!j.overlaps("electrons").empty()) {
+ const auto *lep=dynamic_cast(&*j.overlaps("electrons")[0]);
+ if(lep!=nullptr) {BaseMVAValueMapProducer::setValue("Jet_leptonPtRel",lep->userFloat("ptRel"));}
+ }
+
+ float ptMax=0;
+ for(const auto & d : j.daughterPtrVector()){if(d->pt()>ptMax) ptMax=d->pt();}
+ BaseMVAValueMapProducer::setValue("Jet_leadTrackPt",ptMax);
+
+ //Fill vertex properties
+ VertexDistance3D vdist;
+ float maxFoundSignificance=0;
+ const auto & pv = (*pvs_)[0];
+ this->setValue("Jet_vtxPt",0);
+ this->setValue("Jet_vtxMass",0);
+ this->setValue("Jet_vtx3dL",0);
+ this->setValue("Jet_vtx3deL",0);
+ this->setValue("Jet_vtxNtrk",0);
+
+ for(const auto &sv: *svs_){
+ GlobalVector flightDir(sv.vertex().x() - pv.x(), sv.vertex().y() - pv.y(),sv.vertex().z() - pv.z());
+ GlobalVector jetDir(j.px(),j.py(),j.pz());
+ if( Geom::deltaR2( flightDir, jetDir ) < 0.09 ){
+ Measurement1D dl= vdist.distance(pv,VertexState(RecoVertex::convertPos(sv.position()),RecoVertex::convertError(sv.error())));
+ if(dl.significance() > maxFoundSignificance){
+ maxFoundSignificance=dl.significance();
+ this->setValue("Jet_vtxPt",sv.pt());
+ this->setValue("Jet_vtxMass",sv.p4().M());
+ this->setValue("Jet_vtx3dL",dl.value());
+ this->setValue("Jet_vtx3deL",dl.error());
+ this->setValue("Jet_vtxNtrk",sv.numberOfSourceCandidatePtrs());
+ }
+ }
+ }
+
+ }
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ edm::ParameterSetDescription desc = BaseMVAValueMapProducer::getDescription();
+ desc.add("pvsrc")->setComment("primary vertices input collection");
+ desc.add("svsrc")->setComment("secondary vertices input collection");
+ descriptions.add("BJetEnergyRegressionMVA",desc);
+ }
+
+ private:
+ const edm::EDGetTokenT> pvsrc_;
+ edm::Handle> pvs_;
+ const edm::EDGetTokenT > svsrc_;
+ edm::Handle> svs_;
+
+};
+
+//define this as a plug-in
+DEFINE_FWK_MODULE(BJetEnergyRegressionMVA);
+
diff --git a/PhysicsTools/NanoAOD/plugins/BuildFile.xml b/PhysicsTools/NanoAOD/plugins/BuildFile.xml
new file mode 100644
index 0000000000000..1125b15bc0007
--- /dev/null
+++ b/PhysicsTools/NanoAOD/plugins/BuildFile.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PhysicsTools/NanoAOD/plugins/CandMCMatchTableProducer.cc b/PhysicsTools/NanoAOD/plugins/CandMCMatchTableProducer.cc
new file mode 100644
index 0000000000000..e0de5e212ae47
--- /dev/null
+++ b/PhysicsTools/NanoAOD/plugins/CandMCMatchTableProducer.cc
@@ -0,0 +1,151 @@
+#include "FWCore/Framework/interface/global/EDProducer.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
+#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
+#include "DataFormats/NanoAOD/interface/FlatTable.h"
+#include "DataFormats/Common/interface/View.h"
+#include "DataFormats/Candidate/interface/Candidate.h"
+#include "DataFormats/HepMCCandidate/interface/GenParticle.h"
+
+#include
+#include
+
+
+class CandMCMatchTableProducer : public edm::global::EDProducer<> {
+ public:
+ CandMCMatchTableProducer( edm::ParameterSet const & params ) :
+ objName_(params.getParameter("objName")),
+ branchName_(params.getParameter("branchName")),
+ doc_(params.getParameter("docString")),
+ src_(consumes(params.getParameter("src"))),
+ candMap_(consumes>(params.getParameter("mcMap")))
+ {
+ produces();
+ const std::string & type = params.getParameter("objType");
+ if (type == "Muon") type_ = MMuon;
+ else if (type == "Electron") type_ = MElectron;
+ else if (type == "Tau") type_ = MTau;
+ else if (type == "Photon") type_ = MPhoton;
+ else if (type == "Other") type_ = MOther;
+ else throw cms::Exception("Configuration", "Unsupported objType '"+type+"'\n");
+
+ switch(type_) {
+ case MMuon: flavDoc_ = "1 = prompt muon (including gamma*->mu mu), 15 = muon from prompt tau, " // continues below
+ "5 = muon from b, 4 = muon from c, 3 = muon from light or unknown, 0 = unmatched"; break;
+ case MElectron: flavDoc_ = "1 = prompt electron (including gamma*->mu mu), 15 = electron from prompt tau, 22 = prompt photon (likely conversion), " // continues below
+ "5 = electron from b, 4 = electron from c, 3 = electron from light or unknown, 0 = unmatched"; break;
+ case MPhoton: flavDoc_ = "1 = prompt photon, 13 = prompt electron, 0 = unknown or unmatched"; break;
+ case MTau: flavDoc_ = "1 = prompt electron, 2 = prompt muon, 3 = tau->e decay, 4 = tau->mu decay, 5 = hadronic tau decay, 0 = unknown or unmatched"; break;
+ case MOther: flavDoc_ = "1 = from hard scatter, 0 = unknown or unmatched"; break;
+ }
+
+ if ( type_ == MTau ) {
+ candMapVisTau_ = consumes>(params.getParameter("mcMapVisTau"));
+ }
+ }
+
+ ~CandMCMatchTableProducer() override {}
+
+ void produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const override {
+
+ edm::Handle cands;
+ iEvent.getByToken(src_, cands);
+ unsigned int ncand = cands->size();
+
+ auto tab = std::make_unique(ncand, objName_, false, true);
+
+ edm::Handle> map;
+ iEvent.getByToken(candMap_, map);
+
+ edm::Handle> mapVisTau;
+ if ( type_ == MTau ) {
+ iEvent.getByToken(candMapVisTau_, mapVisTau);
+ }
+
+ std::vector key(ncand, -1), flav(ncand, 0);
+ for (unsigned int i = 0; i < ncand; ++i) {
+ //std::cout << "cand #" << i << ": pT = " << cands->ptrAt(i)->pt() << ", eta = " << cands->ptrAt(i)->eta() << ", phi = " << cands->ptrAt(i)->phi() << std::endl;
+ reco::GenParticleRef match = (*map)[cands->ptrAt(i)];
+ reco::GenParticleRef matchVisTau;
+ if ( type_ == MTau ) {
+ matchVisTau = (*mapVisTau)[cands->ptrAt(i)];
+ }
+ if ( match.isNonnull() ) key[i] = match.key();
+ else if ( matchVisTau.isNonnull() ) key[i] = matchVisTau.key();
+ else continue;
+ switch(type_) {
+ case MMuon:
+ if (match->isPromptFinalState()) flav[i] = 1; // prompt
+ else if (match->isDirectPromptTauDecayProductFinalState()) flav[i] = 15; // tau
+ else flav[i] = getParentHadronFlag(match); // 3 = light, 4 = charm, 5 = b
+ break;
+ case MElectron:
+ if (match->isPromptFinalState()) flav[i] = (match->pdgId() == 22 ? 22 : 1); // prompt electron or photon
+ else if (match->isDirectPromptTauDecayProductFinalState()) flav[i] = 15; // tau
+ else flav[i] = getParentHadronFlag(match); // 3 = light, 4 = charm, 5 = b
+ break;
+ case MPhoton:
+ if (match->isPromptFinalState()) flav[i] = (match->pdgId() == 22 ? 1 : 13); // prompt electron or photon
+ break;
+ case MTau:
+ // CV: assignment of status codes according to https://twiki.cern.ch/twiki/bin/viewauth/CMS/HiggsToTauTauWorking2016#MC_Matching
+ if ( match.isNonnull() && match->isPromptFinalState() && abs(match->pdgId()) == 11 ) flav[i] = 1;
+ else if ( match.isNonnull() && match->isPromptFinalState() && abs(match->pdgId()) == 13 ) flav[i] = 2;
+ else if ( match.isNonnull() && match->isDirectPromptTauDecayProductFinalState() && abs(match->pdgId()) == 11 ) flav[i] = 3;
+ else if ( match.isNonnull() && match->isDirectPromptTauDecayProductFinalState() && abs(match->pdgId()) == 13 ) flav[i] = 4;
+ else if ( matchVisTau.isNonnull() ) flav[i] = 5;
+ break;
+ default:
+ flav[i] = match->statusFlags().fromHardProcess();
+ };
+ }
+
+ tab->addColumn(branchName_+"Idx", key, "Index into genParticle list for "+doc_, nanoaod::FlatTable::IntColumn);
+ tab->addColumn(branchName_+"Flav", flav, "Flavour of genParticle for "+doc_+": "+flavDoc_, nanoaod::FlatTable::UInt8Column);
+
+ iEvent.put(std::move(tab));
+ }
+
+ static int getParentHadronFlag(const reco::GenParticleRef match) {
+ bool has4 = false;
+ for (unsigned int im = 0, nm = match->numberOfMothers(); im < nm; ++im) {
+ reco::GenParticleRef mom = match->motherRef(im);
+ assert(mom.isNonnull() && mom.isAvailable()); // sanity
+ if (mom.key() >= match.key()) continue; // prevent circular refs
+ int id = std::abs(mom->pdgId());
+ if (id / 1000 == 5 || id / 100 == 5 || id == 5) return 5;
+ if (id / 1000 == 4 || id / 100 == 4 || id == 4) has4 = true;
+ if (mom->status() == 2) {
+ id = getParentHadronFlag(mom);
+ if (id == 5) return 5;
+ else if (id == 4) has4 = true;
+ }
+ }
+ return has4 ? 4 : 3;
+ }
+
+ static void fillDescriptions(edm::ConfigurationDescriptions & descriptions) {
+ edm::ParameterSetDescription desc;
+ desc.add("objName")->setComment("name of the nanoaod::FlatTable to extend with this table");
+ desc.add("branchName")->setComment("name of the column to write (the final branch in the nanoaod will be _Idx and _Flav");
+ desc.add("docString")->setComment("documentation to forward to the output");
+ desc.add("src")->setComment("physics object collection for the reconstructed objects (e.g. leptons)");
+ desc.add("mcMap")->setComment("tag to an edm::Association mapping src to gen, such as the one produced by MCMatcher");
+ desc.add("objType")->setComment("type of object to match (Muon, Electron, Tau, Photon, Other), taylors what's in t Flav branch");
+ desc.addOptional("mcMapVisTau")->setComment("as mcMap, but pointing to the visible gen taus (only if objType == Tau)");
+ descriptions.add("candMcMatchTable", desc);
+ }
+
+ protected:
+ const std::string objName_, branchName_, doc_;
+ const edm::EDGetTokenT src_;
+ const edm::EDGetTokenT> candMap_;
+ edm::EDGetTokenT> candMapVisTau_;
+ enum MatchType { MMuon, MElectron, MTau, MPhoton, MOther } type_;
+ std::string flavDoc_;
+};
+
+#include "FWCore/Framework/interface/MakerMacros.h"
+DEFINE_FWK_MODULE(CandMCMatchTableProducer);
+
diff --git a/PhysicsTools/NanoAOD/plugins/EGMEnergyVarProducer.cc b/PhysicsTools/NanoAOD/plugins/EGMEnergyVarProducer.cc
new file mode 100644
index 0000000000000..44c9114f69f45
--- /dev/null
+++ b/PhysicsTools/NanoAOD/plugins/EGMEnergyVarProducer.cc
@@ -0,0 +1,131 @@
+// -*- C++ -*-
+//
+// Package: PhysicsTools/NanoAOD
+// Class: EGMEnergyVarProducer
+//
+/**\class EGMEnergyVarProducer EGMEnergyVarProducer.cc PhysicsTools/NanoAOD/plugins/EGMEnergyVarProducer.cc
+ Description: [one line class summary]
+ Implementation:
+ [Notes on implementation]
+*/
+//
+// Original Author: Emanuele Di Marco
+// Created: Wed, 06 Sep 2017 12:34:38 GMT
+//
+//
+
+
+// system include files
+#include
+
+// user include files
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/global/EDProducer.h"
+
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/Utilities/interface/StreamID.h"
+
+#include "DataFormats/PatCandidates/interface/Electron.h"
+#include "DataFormats/PatCandidates/interface/Photon.h"
+
+#include "TLorentzVector.h"
+#include "DataFormats/Common/interface/View.h"
+
+#include "PhysicsTools/NanoAOD/interface/MatchingUtils.h"
+
+//
+// class declaration
+//
+
+template
+class EGMEnergyVarProducer : public edm::global::EDProducer<> {
+public:
+ explicit EGMEnergyVarProducer(const edm::ParameterSet &iConfig):
+ srcRaw_(consumes>(iConfig.getParameter("srcRaw"))),
+ srcCorr_(consumes>(iConfig.getParameter("srcCorr")))
+ {
+ produces>("eCorr");
+ }
+ ~EGMEnergyVarProducer() override {};
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override;
+
+ // ----------member data ---------------------------
+
+ edm::EDGetTokenT> srcRaw_;
+ edm::EDGetTokenT> srcCorr_;
+};
+
+//
+// constants, enums and typedefs
+//
+
+
+//
+// static data member definitions
+//
+
+//
+// member functions
+//
+
+// ------------ method called to produce the data ------------
+template
+void
+EGMEnergyVarProducer::produce(edm::StreamID streamID, edm::Event& iEvent, const edm::EventSetup& iSetup) const
+{
+ edm::Handle> srcRaw;
+ iEvent.getByToken(srcRaw_, srcRaw);
+ edm::Handle> srcCorr;
+ iEvent.getByToken(srcCorr_, srcCorr);
+
+ unsigned nSrcRaw = srcRaw->size();
+ unsigned nSrcCorr = srcCorr->size();
+
+ std::vector eCorr(nSrcCorr,-1);
+
+ for (unsigned int ir = 0; irptrAt(ir);
+ for (unsigned int ic = 0; icptrAt(ic);
+ if(matchByCommonParentSuperClusterRef(*egm_raw,*egm_corr)){
+ eCorr[ir] = egm_corr->energy()/egm_raw->energy();
+ break;
+ }
+ }
+ }
+
+ std::unique_ptr> eCorrV(new edm::ValueMap());
+ edm::ValueMap::Filler fillerCorr(*eCorrV);
+ fillerCorr.insert(srcRaw,eCorr.begin(),eCorr.end());
+ fillerCorr.fill();
+ iEvent.put(std::move(eCorrV),"eCorr");
+
+}
+
+// ------------ method fills 'descriptions' with the allowed parameters for the module ------------
+template
+void
+EGMEnergyVarProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ edm::ParameterSetDescription desc;
+ desc.add("srcRaw")->setComment("input raw physics object collection");
+ desc.add("srcCorr")->setComment("input corrected physics object collection");
+ std::string modname;
+ if (typeid(T) == typeid(pat::Electron)) modname+="Electron";
+ else if (typeid(T) == typeid(pat::Photon)) modname+="Photon";
+ modname+="EnergyVarProducer";
+ descriptions.add(modname,desc);
+}
+
+typedef EGMEnergyVarProducer ElectronEnergyVarProducer;
+typedef EGMEnergyVarProducer PhotonEnergyVarProducer;
+
+//define this as a plug-in
+DEFINE_FWK_MODULE(ElectronEnergyVarProducer);
+DEFINE_FWK_MODULE(PhotonEnergyVarProducer);
diff --git a/PhysicsTools/NanoAOD/plugins/FilterValueMapWrapper.h b/PhysicsTools/NanoAOD/plugins/FilterValueMapWrapper.h
new file mode 100644
index 0000000000000..4c13752d5faa1
--- /dev/null
+++ b/PhysicsTools/NanoAOD/plugins/FilterValueMapWrapper.h
@@ -0,0 +1,61 @@
+#ifndef PhysicsTools_UtilAlgos_interface_EDFilterValueMapWrapper_h
+#define PhysicsTools_UtilAlgos_interface_EDFilterValueMapWrapper_h
+
+/**
+ This is derived from EDFilterValueMapWrapper but rather than filtering it just stores a valuemap with the result
+*/
+
+#include "DataFormats/Common/interface/ValueMap.h"
+#include "FWCore/Framework/interface/stream/EDProducer.h"
+#include "FWCore/Common/interface/EventBase.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include
+
+namespace edm {
+
+ template
+ class FilterValueMapWrapper : public edm::stream::EDProducer<> {
+
+ public:
+ /// some convenient typedefs. Recall that C is a container class.
+ typename C::iterator iterator;
+ typename C::const_iterator const_iterator;
+
+ /// default contructor. Declares the output (type "C") and the filter (of type T, operates on C::value_type)
+ FilterValueMapWrapper(const edm::ParameterSet& cfg) : src_( consumes(cfg.getParameter("src")))
+ {
+ filter_ = boost::shared_ptr( new T(cfg.getParameter("filterParams")) );
+ produces>();
+ }
+ /// default destructor
+ ~FilterValueMapWrapper() override{}
+ /// everything which has to be done during the event loop. NOTE: We can't use the eventSetup in FWLite so ignore it
+ void produce(edm::Event& event, const edm::EventSetup& eventSetup) override {
+ // create a collection of the objects to put into the event
+ auto objsToPut = std::make_unique();
+ // get the handle to the objects in the event.
+ edm::Handle h_c;
+ event.getByToken( src_, h_c );
+ std::vector bitOut;
+ // loop through and add passing value_types to the output vector
+ for ( typename C::const_iterator ibegin = h_c->begin(), iend = h_c->end(), i = ibegin; i != iend; ++i ){
+ bitOut.push_back((*filter_)(*i));
+ }
+ std::unique_ptr> o(new edm::ValueMap());
+ edm::ValueMap::Filler filler(*o);
+ filler.insert(h_c,bitOut.begin(),bitOut.end());
+ filler.fill();
+ event.put(std::move(o));
+ }
+
+ protected:
+ /// InputTag of the input source
+ edm::EDGetTokenT src_;
+ /// shared pointer to analysis class of type BasicAnalyzer
+ boost::shared_ptr filter_;
+ };
+
+}
+
+#endif
diff --git a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc
new file mode 100644
index 0000000000000..08e812ee4447b
--- /dev/null
+++ b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc
@@ -0,0 +1,409 @@
+#include "FWCore/Framework/interface/global/EDProducer.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/Run.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "DataFormats/NanoAOD/interface/FlatTable.h"
+#include "DataFormats/NanoAOD/interface/MergeableCounterTable.h"
+#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
+#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
+#include "SimDataFormats/GeneratorProducts/interface/GenEventInfoProduct.h"
+#include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h"
+#include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h"
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+
+#include
+#include
+#include
+
+namespace {
+ /// ---- Cache object for running sums of weights ----
+ struct Counter {
+ Counter() :
+ num(0), sumw(0), sumw2(0), sumPDF(), sumScale(), sumNamed() {}
+
+ // the counters
+ long long num;
+ long double sumw;
+ long double sumw2;
+ std::vector sumPDF, sumScale, sumNamed;
+
+ void clear() {
+ num = 0; sumw = 0; sumw2 = 0;
+ sumPDF.clear(); sumScale.clear(); sumNamed.clear();
+ }
+
+ // inc the counters
+ void incGenOnly(double w) {
+ num++; sumw += w; sumw2 += (w*w);
+ }
+ void incLHE(double w0, const std::vector & wScale, const std::vector & wPDF, const std::vector & wNamed) {
+ // add up weights
+ incGenOnly(w0);
+ // then add up variations
+ if (!wScale.empty()) {
+ if (sumScale.empty()) sumScale.resize(wScale.size(), 0);
+ for (unsigned int i = 0, n = wScale.size(); i < n; ++i) sumScale[i] += (w0 * wScale[i]);
+ }
+ if (!wPDF.empty()) {
+ if (sumPDF.empty()) sumPDF.resize(wPDF.size(), 0);
+ for (unsigned int i = 0, n = wPDF.size(); i < n; ++i) sumPDF[i] += (w0 * wPDF[i]);
+ }
+ if (!wNamed.empty()) {
+ if (sumNamed.empty()) sumNamed.resize(wNamed.size(), 0);
+ for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) sumNamed[i] += (w0 * wNamed[i]);
+ }
+ }
+
+ void merge(const Counter & other) {
+ num += other.num; sumw += other.sumw; sumw2 += other.sumw2;
+ if (sumScale.empty() && !other.sumScale.empty()) sumScale.resize(other.sumScale.size(),0);
+ if (sumPDF.empty() && !other.sumPDF.empty()) sumPDF.resize(other.sumPDF.size(),0);
+ if (sumNamed.empty() && !other.sumNamed.empty()) sumNamed.resize(other.sumNamed.size(),0);
+ for (unsigned int i = 0, n = sumScale.size(); i < n; ++i) sumScale[i] += other.sumScale[i];
+ for (unsigned int i = 0, n = sumPDF.size(); i < n; ++i) sumPDF[i] += other.sumPDF[i];
+ for (unsigned int i = 0, n = sumNamed.size(); i < n; ++i) sumNamed[i] += other.sumNamed[i];
+ }
+ };
+
+ /// ---- RunCache object for dynamic choice of LHE IDs ----
+ struct DynamicWeightChoice {
+ // choice of LHE weights
+ // ---- scale ----
+ std::vector scaleWeightIDs;
+ std::string scaleWeightsDoc;
+ // ---- pdf ----
+ std::vector pdfWeightIDs;
+ std::string pdfWeightsDoc;
+ };
+
+ /// -------------- temporary objects --------------
+ struct ScaleVarWeight {
+ std::string wid, label;
+ std::pair scales;
+ ScaleVarWeight(const std::string & id, const std::string & text, const std::string & muR, const std::string & muF) :
+ wid(id), label(text), scales(std::stof(muR), std::stof(muF)) {}
+ bool operator<(const ScaleVarWeight & other) { return (scales == other.scales ? wid < other.wid : scales < other.scales); }
+ };
+ struct PDFSetWeights {
+ std::vector wids;
+ std::pair lhaIDs;
+ PDFSetWeights(const std::string & wid, unsigned int lhaID) : wids(1,wid), lhaIDs(lhaID,lhaID) {}
+ bool operator<(const PDFSetWeights & other) const { return lhaIDs < other.lhaIDs; }
+ bool maybe_add(const std::string & wid, unsigned int lhaID) {
+ if (lhaID == lhaIDs.second+1) {
+ lhaIDs.second++;
+ wids.push_back(wid);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ };
+}
+
+class GenWeightsTableProducer : public edm::global::EDProducer, edm::RunCache, edm::RunSummaryCache, edm::EndRunProducer> {
+ public:
+ GenWeightsTableProducer( edm::ParameterSet const & params ) :
+ genTag_(consumes(params.getParameter("genEvent"))),
+ lheLabel_(params.getParameter("lheInfo")),
+ lheTag_(consumes(lheLabel_)),
+ lheRunTag_(consumes(lheLabel_)),
+ preferredPDFLHAIDs_(params.getParameter>("preferredPDFs")),
+ namedWeightIDs_(params.getParameter>("namedWeightIDs")),
+ namedWeightLabels_(params.getParameter>("namedWeightLabels")),
+ lheWeightPrecision_(params.getParameter("lheWeightPrecision")),
+ maxPdfWeights_(params.getParameter("maxPdfWeights")),
+ debug_(params.getUntrackedParameter("debug",false)), debugRun_(debug_.load()),
+ hasIssuedWarning_(false)
+ {
+ produces();
+ produces("LHEScale");
+ produces("LHEPdf");
+ produces("LHENamed");
+ produces();
+ if (namedWeightIDs_.size() != namedWeightLabels_.size()) {
+ throw cms::Exception("Configuration", "Size mismatch between namedWeightIDs & namedWeightLabels");
+ }
+ }
+
+ ~GenWeightsTableProducer() override {}
+
+ void produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const override {
+ // get my counter for weights
+ Counter * counter = streamCache(id);
+
+ // generator information (always available)
+ edm::Handle genInfo;
+ iEvent.getByToken(genTag_, genInfo);
+ double weight = genInfo->weight();
+
+ // table for gen info, always available
+ auto out = std::make_unique(1, "genWeight", true);
+ out->setDoc("generator weight");
+ out->addColumnValue("", weight, "generator weight", nanoaod::FlatTable::FloatColumn);
+ iEvent.put(std::move(out));
+
+ // tables for LHE weights, may not be filled
+ std::unique_ptr lheScaleTab, lhePdfTab, lheNamedTab;
+
+ edm::Handle lheInfo;
+ if (iEvent.getByToken(lheTag_, lheInfo)) {
+ // get the dynamic choice of weights
+ const DynamicWeightChoice * weightChoice = runCache(iEvent.getRun().index());
+ // go fill tables
+ fillLHEWeightTables(counter, weightChoice, weight, *lheInfo, lheScaleTab, lhePdfTab, lheNamedTab);
+ } else {
+ // minimal book-keeping of weights
+ counter->incGenOnly(weight);
+ // make dummy values
+ lheScaleTab.reset(new nanoaod::FlatTable(1, "LHEScaleWeights", true));
+ lhePdfTab.reset(new nanoaod::FlatTable(1, "LHEPdfWeights", true));
+ lheNamedTab.reset(new nanoaod::FlatTable(1, "LHENamedWeights", true));
+ if (!hasIssuedWarning_.exchange(true)) {
+ edm::LogWarning("LHETablesProducer") << "No LHEEventProduct, so there will be no LHE Tables\n";
+ }
+ }
+
+ iEvent.put(std::move(lheScaleTab), "LHEScale");
+ iEvent.put(std::move(lhePdfTab), "LHEPdf");
+ iEvent.put(std::move(lheNamedTab), "LHENamed");
+ }
+
+ void fillLHEWeightTables(
+ Counter * counter,
+ const DynamicWeightChoice * weightChoice,
+ double genWeight,
+ const LHEEventProduct & lheProd,
+ std::unique_ptr