00001 #ifndef RecoBTau_BTauComputer_GenericMVAComputer_h 00002 #define RecoBTau_BTauComputer_GenericMVAComputer_h 00003 00004 #include <iterator> 00005 #include <vector> 00006 00007 #include "DataFormats/BTauReco/interface/TaggingVariable.h" 00008 #include "PhysicsTools/MVAComputer/interface/AtomicId.h" 00009 #include "PhysicsTools/MVAComputer/interface/Calibration.h" 00010 #include "PhysicsTools/MVAComputer/interface/MVAComputer.h" 00011 00012 // overload MVAComputer and replace eval() methods to work on TaggingVariable 00013 class GenericMVAComputer : public PhysicsTools::MVAComputer { 00014 public: 00015 // forward declarations; 00016 template<typename Iter_t> class TaggingVariableIterator; 00017 class TaggingVariableMapping; 00018 00019 GenericMVAComputer(const PhysicsTools::Calibration::MVAComputer *calib) : 00020 PhysicsTools::MVAComputer(calib) {} 00021 00022 // create wrapping iterator 00023 template<typename Iter_t> 00024 inline TaggingVariableIterator<Iter_t> iterator(Iter_t iter) const 00025 { return TaggingVariableIterator<Iter_t>(&mapping, iter); } 00026 00027 // overload eval method to work on containers of TaggingVariable 00028 template<typename Iter_t> 00029 inline double eval(Iter_t first, Iter_t last) const 00030 { 00031 typedef TaggingVariableIterator<Iter_t> Wrapped_t; 00032 return PhysicsTools::MVAComputer::template eval<Wrapped_t>( 00033 iterator<Iter_t>(first), iterator<Iter_t>(last)); 00034 } 00035 00036 template<typename Container_t> 00037 inline double eval(const Container_t &values) const 00038 { 00039 typedef typename Container_t::const_iterator Iter_t; 00040 return this->template eval<Iter_t>(values.begin(), values.end()); 00041 } 00042 00043 // iterator wrapper with on-the-fly TaggingVariableName -> AtomicId mapping 00044 // 00045 // Notice that this tells the computer to completely inline it 00046 // this is reasonable since inlining it means that the optimizer 00047 // will not produce any additional code for the wrapper 00048 // (it is entirely optimized away), except for the actual mapping 00049 // which is no more than a simple array lookup. 00050 // 00051 // The result will be inlined into the eval() template of MVAComputer 00052 // which will be instantiated as one single tightly-integrated 00053 // function. 00054 template<typename Iter_t> 00055 class TaggingVariableIterator { 00056 public: 00057 // class implementing MVAComputer::Variable::Value interface 00058 struct Value { 00059 public: 00060 // the actual operator doing the mapping 00061 inline PhysicsTools::AtomicId getName() const 00062 { return mapping->getAtomicId(iter->first); } 00063 00064 inline double getValue() const 00065 { return iter->second; } 00066 00067 operator PhysicsTools::Variable::Value() const 00068 { 00069 return PhysicsTools::Variable::Value( 00070 getName(), getValue()); 00071 } 00072 00073 protected: 00074 friend class TaggingVariableIterator; 00075 00076 inline Value(TaggingVariableMapping *mapping, 00077 const Iter_t &iter) : 00078 mapping(mapping), iter(iter) {} 00079 00080 private: 00081 // pointer to the current mapping 00082 TaggingVariableMapping *mapping; 00083 // iterator to reco::TaggingVariable in orig. container 00084 Iter_t iter; 00085 }; 00086 00087 typedef std::forward_iterator_tag iterator_category; 00088 typedef Value value_type; 00089 typedef typename std::iterator_traits<Iter_t>::difference_type difference_type; 00090 typedef const Value *pointer; 00091 typedef const Value &reference; 00092 00093 inline ~TaggingVariableIterator() {} 00094 00095 // methods to make class a standard forward iterator 00096 00097 inline const Value &operator * () const { return value; } 00098 inline Value &operator * () { return value; } 00099 00100 inline const Value *operator -> () const { return &value; } 00101 inline Value *operator -> () { return &value; } 00102 00103 inline bool operator == (const TaggingVariableIterator &other) const 00104 { return value.iter == other.value.iter; } 00105 inline bool operator != (const TaggingVariableIterator &other) const 00106 { return value.iter != other.value.iter; } 00107 inline bool operator < (const TaggingVariableIterator &other) const 00108 { return value.iter < other.value.iter; } 00109 00110 inline TaggingVariableIterator &operator ++ () 00111 { ++value.iter; return *this; } 00112 00113 inline TaggingVariableIterator operator ++ (int dummy) 00114 { TaggingVariableIterator orig = *this; ++value.iter; return orig; } 00115 00116 protected: 00117 friend class GenericMVAComputer; 00118 inline TaggingVariableIterator(TaggingVariableMapping *mapping, 00119 const Iter_t &iter) : 00120 value(mapping, iter) {} 00121 00122 private: 00123 // holds the current "value" 00124 // it's really only an iterator that points the original 00125 // current TaggingVariable plus required methods 00126 Value value; 00127 }; 00128 00129 // TaggingVariableName -> PhysicsTools::AtomicId mapping 00130 class TaggingVariableMapping { 00131 public: 00132 typedef PhysicsTools::AtomicId AtomicId; 00133 typedef reco::TaggingVariableName TaggingName; 00134 00135 TaggingVariableMapping(); 00136 ~TaggingVariableMapping() {} 00137 00138 inline AtomicId getAtomicId(TaggingName taggingName) const 00139 { return taggingVarToAtomicId[taggingName]; } 00140 00141 private: 00142 std::vector<AtomicId> taggingVarToAtomicId; 00143 }; 00144 00145 private: 00146 static TaggingVariableMapping mapping; 00147 }; 00148 00149 #endif // RecoBTau_BTauComputer_GenericMVAComputer_h