Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:23:37

0001 #ifndef PhysicsTools_MVAComputer_VarProcessor_h
0002 #define PhysicsTools_MVAComputer_VarProcessor_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     MVAComputer
0006 // Class  :     VarProcessor
0007 //
0008 
0009 //
0010 // Author:  Christophe Saout <christophe.saout@cern.ch>
0011 // Created:     Sat Apr 24 15:18 CEST 2007
0012 //
0013 
0014 #include <algorithm>
0015 #include <vector>
0016 
0017 #include "PhysicsTools/MVAComputer/interface/ProcessRegistry.h"
0018 #include "PhysicsTools/MVAComputer/interface/CalibrationFwd.h"
0019 #include "PhysicsTools/MVAComputer/interface/Variable.h"
0020 #include "PhysicsTools/MVAComputer/interface/BitSet.h"
0021 
0022 namespace PhysicsTools {
0023 
0024   // forward declaration
0025   class MVAComputer;
0026 
0027   /** \class VarProcessor
0028  *
0029  * \short Common base class for variable processors.
0030  *
0031  * This base class for variable processors manages the common
0032  * interface to the global discriminator class and how the individual
0033  * variable processors are interconnected.
0034  *
0035  ************************************************************/
0036   class VarProcessor : public ProcessRegistry<VarProcessor, Calibration::VarProcessor, const MVAComputer>::Factory {
0037   public:
0038     /** \class Config
0039      *
0040      * \short Helper class for discriminator computer set-up procedure
0041      *
0042      * This type is used to configure the variable processor and
0043      * inter-processor passing of variables. The required variable
0044      * flags are computed an the origin of multi-value variables tracked.
0045      *
0046      ************************************************************/
0047     struct Config {
0048       inline Config() : mask(Variable::FLAG_NONE), origin(0) {}
0049       inline Config(Variable::Flags mask, unsigned int origin) : mask(mask), origin(origin) {}
0050 
0051       Variable::Flags mask;
0052       unsigned int origin;
0053     };
0054 
0055     class ConfigCtx {
0056     public:
0057       typedef std::vector<Config> Config_t;
0058 
0059       typedef Config_t::value_type value_type;
0060       typedef Config_t::size_type size_type;
0061       typedef Config_t::iterator iterator;
0062       typedef Config_t::const_iterator const_iterator;
0063 
0064       struct Context {
0065         virtual ~Context() {}
0066       };
0067 
0068       ConfigCtx(const std::vector<Variable::Flags> &flags);
0069       ~ConfigCtx() { delete ctx; }
0070 
0071       inline size_type size() const { return configs.size(); }
0072       inline const_iterator begin() const { return configs.begin(); }
0073       inline iterator begin() { return configs.begin(); }
0074       inline const_iterator end() const { return configs.end(); }
0075       inline iterator end() { return configs.end(); }
0076       inline void push_back(const Config &config) { configs.push_back(config); }
0077       inline Config &operator[](size_type i) { return configs[i]; }
0078 
0079     private:
0080       friend class VarProcessor;
0081 
0082       Config_t configs;
0083       VarProcessor *loop;
0084       Context *ctx;
0085     };
0086 
0087     /** \class LoopCtx
0088      *
0089      * \short Hold context information for looping processors
0090      *
0091      * VarProcessor instances which allow looping need to keep
0092      * track of the state of the loop between calls.
0093      *
0094      ************************************************************/
0095     class LoopCtx {
0096     public:
0097       LoopCtx() : index_(0), offset_(0), size_(0) {}
0098       inline unsigned int &index() { return index_; }
0099       inline unsigned int &offset() { return offset_; }
0100       inline unsigned int &size() { return size_; }
0101 
0102     private:
0103       unsigned int index_;
0104       unsigned int offset_;
0105       unsigned int size_;
0106     };
0107 
0108     virtual ~VarProcessor();
0109 
0110     /// called from the discriminator computer to configure processor
0111     void configure(ConfigCtx &config);
0112 
0113     /// run the processor evaluation pass on this processor
0114     inline void eval(
0115         double *input, int *conf, double *output, int *outConf, int *loop, LoopCtx &loopCtx, unsigned int offset) const {
0116       ValueIterator iter(inputVars.iter(), input, conf, output, outConf, loop, loopCtx, offset);
0117       eval(iter, nInputVars);
0118     }
0119 
0120     /// run the processor evaluation pass on this processor and compute derivatives
0121     void deriv(double *input,
0122                int *conf,
0123                double *output,
0124                int *outConf,
0125                int *loop,
0126                LoopCtx &ctx,
0127                unsigned int offset,
0128                unsigned int in,
0129                unsigned int out,
0130                std::vector<double> &deriv) const;
0131 
0132     enum LoopStatus { kStop, kNext, kReset, kSkip };
0133 
0134     virtual LoopStatus loop(
0135         double *output, int *outConf, unsigned int nOutput, LoopCtx &ctx, unsigned int &nOffset) const {
0136       return kStop;
0137     }
0138 
0139     //used to create a PluginFactory
0140     struct Dummy {};
0141     typedef Dummy *PluginFunctionPrototype();
0142 
0143   protected:
0144     /** \class ConfIterator
0145      *
0146      * \short Iterator to loop over the input/output variable configuration
0147      *
0148      ************************************************************/
0149     struct ConfIterator {
0150     public:
0151       /// apply property flags mask to variable at current position
0152       ConfIterator &operator()(Variable::Flags mask) {
0153         config[cur()].mask = (Variable::Flags)(config[cur()].mask & mask);
0154         return *this;
0155       }
0156 
0157       /// add a new output variable configuration \a config_
0158       ConfIterator &operator<<(Config config_) {
0159         config.push_back(config_);
0160         return *this;
0161       }
0162 
0163       /// add a new output variable configuration with mask \a mask
0164       ConfIterator &operator<<(Variable::Flags mask) { return *this << Config(mask, 0); }
0165 
0166       /// add a new output variable that inherits values from \a origin
0167       ConfIterator &operator<<(const ConfIterator &origin) {
0168         return *this << Config(config[origin.cur()].mask, origin.cur());
0169       }
0170 
0171       /// return the current input variable flags
0172       Variable::Flags operator*() const { return config[cur()].mask; }
0173 
0174       /// test for end of iterator
0175       inline operator bool() const { return cur; }
0176 
0177       /// move to next input variable
0178       ConfIterator &operator++() {
0179         ++cur;
0180         return *this;
0181       }
0182 
0183       /// move to next input variable
0184       inline ConfIterator operator++(int dummy) {
0185         ConfIterator orig = *this;
0186         operator++();
0187         return orig;
0188       }
0189 
0190     protected:
0191       friend class VarProcessor;
0192 
0193       ConfIterator(BitSet::Iterator cur, ConfigCtx &config) : cur(cur), config(config) {}
0194 
0195     private:
0196       BitSet::Iterator cur;
0197       ConfigCtx &config;
0198     };
0199 
0200     /** \class ConfIterator
0201      *
0202      * \short Iterator to loop over the input/output variable values
0203      *
0204      ************************************************************/
0205     struct ValueIterator {
0206     public:
0207       /// number of values for current input variable
0208       inline unsigned int size() const { return loop ? (conf[1] - conf[0]) : 1; }
0209 
0210       /// begin of value array for current input variable
0211       inline double *begin() const { return values; }
0212 
0213       /// end of value array for current input variable
0214       inline double *end() const { return values + size(); }
0215 
0216       /// checks for existence of values for current input variable
0217       inline bool empty() const { return begin() == end(); }
0218 
0219       /// the (first or only) value for the current input variable
0220       inline double operator*() { return *values; }
0221 
0222       /// value \a idx of current input variable
0223       inline double operator[](unsigned int idx) { return values[idx]; }
0224 
0225       /// add computed value to current output variable
0226       inline ValueIterator &operator<<(double value) {
0227         *output++ = value;
0228         return *this;
0229       }
0230 
0231       /// finish current output variable, move to next slot
0232       inline void operator()() {
0233         int pos = output - start;
0234         if (*++outConf > pos)
0235           output = start + *outConf;
0236         else
0237           *outConf = pos;
0238       }
0239 
0240       /// add \a value as output variable and move to next slot
0241       inline void operator()(double value) {
0242         *this << value;
0243         (*this)();
0244       }
0245 
0246       /// test for end of input variable iterator
0247       inline operator bool() const { return cur; }
0248 
0249       inline LoopCtx &loopCtx() { return ctx; }
0250 
0251       /// move to next input variable
0252       ValueIterator &operator++() {
0253         BitSet::size_t orig = cur();
0254         if (++cur) {
0255           unsigned int prev = *conf;
0256           conf += cur() - orig;
0257           values += *conf - prev;
0258           if (loop && conf >= loop) {
0259             values += offset;
0260             loop = nullptr;
0261           }
0262         }
0263         return *this;
0264       }
0265 
0266       /// move to next input variable
0267       inline ValueIterator operator++(int dummy) {
0268         ValueIterator orig = *this;
0269         operator++();
0270         return orig;
0271       }
0272 
0273     protected:
0274       friend class VarProcessor;
0275 
0276       ValueIterator(BitSet::Iterator cur,
0277                     double *values,
0278                     int *conf,
0279                     double *output,
0280                     int *outConf,
0281                     int *loop,
0282                     LoopCtx &ctx,
0283                     unsigned int offset)
0284           : cur(cur),
0285             ctx(ctx),
0286             offset(offset),
0287             start(values + offset),
0288             values(values),
0289             conf(conf),
0290             loop(loop),
0291             output(output + offset),
0292             outConf(outConf) {
0293         this->conf += cur();
0294         this->values += *this->conf;
0295         if (loop && this->conf >= loop) {
0296           this->values += offset;
0297           this->loop = nullptr;
0298         }
0299       }
0300 
0301     private:
0302       BitSet::Iterator cur;
0303       LoopCtx &ctx;
0304       const unsigned int offset;
0305       double *const start;
0306       double *values;
0307       const int *conf;
0308       const int *loop;
0309       double *output;
0310       int *outConf;
0311     };
0312 
0313     typedef ProcessRegistry<VarProcessor, Calibration::VarProcessor, const MVAComputer> Registry;
0314 
0315     VarProcessor(const char *name, const Calibration::VarProcessor *calib, const MVAComputer *computer);
0316 
0317     /// virtual configure method, implemented in actual processor
0318     virtual void configure(ConfIterator iter, unsigned int n) = 0;
0319 
0320     /// virtual loop configure method
0321     virtual ConfigCtx::Context *configureLoop(ConfigCtx::Context *ctx,
0322                                               ConfigCtx::iterator begin,
0323                                               ConfigCtx::iterator cur,
0324                                               ConfigCtx::iterator end);
0325 
0326     /// virtual evaluation method, implemented in actual processor
0327     virtual void eval(ValueIterator iter, unsigned int n) const = 0;
0328 
0329     /// virtual derivative evaluation method, implemented in actual processor
0330     virtual std::vector<double> deriv(ValueIterator iter, unsigned int n) const { return std::vector<double>(); }
0331 
0332   protected:
0333     const MVAComputer *computer;
0334 
0335   private:
0336     /// bit set to select the input variables to be passed to this processor
0337     BitSet inputVars;
0338     unsigned int nInputVars;
0339   };
0340 
0341   template <>
0342   VarProcessor *ProcessRegistry<VarProcessor, Calibration::VarProcessor, const MVAComputer>::Factory::create(
0343       const char *, const Calibration::VarProcessor *, const MVAComputer *);
0344 
0345 }  // namespace PhysicsTools
0346 
0347 #endif  // PhysicsTools_MVAComputer_VarProcessor_h