Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #ifndef PhysicsTools_MVAComputer_MVAComputer_h
0002 #define PhysicsTools_MVAComputer_MVAComputer_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     MVAComputer
0006 // Class  :     MVAComputer
0007 //
0008 
0009 //
0010 // Author:  Christophe Saout <christophe.saout@cern.ch>
0011 // Created:     Sat Apr 24 15:18 CEST 2007
0012 //
0013 
0014 #include <iostream>
0015 #include <vector>
0016 #include <memory>
0017 
0018 #include "PhysicsTools/MVAComputer/interface/CalibrationFwd.h"
0019 #include "PhysicsTools/MVAComputer/interface/VarProcessor.h"
0020 #include "PhysicsTools/MVAComputer/interface/Variable.h"
0021 #include "PhysicsTools/MVAComputer/interface/AtomicId.h"
0022 
0023 namespace PhysicsTools {
0024 
0025   /** \class MVAComputer
0026  *
0027  * \short Main interface class to the generic discriminator computer framework.
0028  *
0029  * The MVAComputer class represents an instance of the modular
0030  * discriminator computer. It is constructed from a "calibration" object
0031  * which contains all the required histograms, matrices and other trainina
0032  * data required for computing the discriminator. The calibration data also
0033  * defines the names and properties of variables that can passed to that
0034  * instance of the discriminator computer. The evaluation methods then
0035  * calculates the discriminator from a applicable set of input variables,
0036  * i.e. vector of key-value pairs.
0037  *
0038  ************************************************************/
0039   class MVAComputer {
0040   public:
0041     /// construct a discriminator computer from a const calibation object
0042     MVAComputer(const Calibration::MVAComputer *calib);
0043 
0044     /// construct a discriminator computer from a calibation object
0045     MVAComputer(Calibration::MVAComputer *calib, bool owned = false);
0046 
0047     ~MVAComputer();
0048 
0049     /// evaluate variables given by a range of iterators given by \a first and \a last
0050     template <typename Iterator_t>
0051     double eval(Iterator_t first, Iterator_t last) const;
0052 
0053     template <typename Iterator_t>
0054     double deriv(Iterator_t first, Iterator_t last) const;
0055 
0056     /// evaluate variables in iterable container \a values
0057     template <typename Container_t>
0058     inline double eval(const Container_t &values) const {
0059       typedef typename Container_t::const_iterator Iterator_t;
0060       return this->template eval<Iterator_t>(values.begin(), values.end());
0061     }
0062 
0063     template <typename Container_t>
0064     inline double deriv(Container_t &values) const {
0065       typedef typename Container_t::iterator Iterator_t;
0066       return this->template deriv<Iterator_t>(values.begin(), values.end());
0067     }
0068 
0069     /* various methods for standalone use of calibration files */
0070 
0071     /// read calibration object from plain file
0072     static Calibration::MVAComputer *readCalibration(const char *filename);
0073 
0074     /// read calibration object from plain C++ input stream
0075     static Calibration::MVAComputer *readCalibration(std::istream &is);
0076 
0077     /// write calibration object to file
0078     static void writeCalibration(const char *filename, const Calibration::MVAComputer *calib);
0079 
0080     /// write calibration object to pain C++ output stream
0081     static void writeCalibration(std::ostream &os, const Calibration::MVAComputer *calib);
0082 
0083     /// construct a discriminator computer from a calibration file
0084     MVAComputer(const char *filename);
0085 
0086     /// construct a discriminator computer from C++ input stream
0087     MVAComputer(std::istream &is);
0088 
0089     /** \class InputVar
0090      * \short input variable configuration object
0091      */
0092     struct InputVar {
0093       /// generic variable information (name, ...)
0094       Variable var;
0095 
0096       /// variable index in fixed-position evaluation array
0097       unsigned int index;
0098 
0099       /// number of times each appearance of that variable can appear while computing the discriminator
0100       unsigned int multiplicity;
0101 
0102       bool operator<(AtomicId id) const { return var.getName() < id; }
0103 
0104       bool operator<(const InputVar &other) const { return var.getName() < other.var.getName(); }
0105     };
0106 
0107     /** \class Processor
0108      * \short variable processor container
0109      */
0110     struct Processor {
0111       inline Processor(VarProcessor *processor, unsigned int nOutput) : processor(processor), nOutput(nOutput) {}
0112 
0113       inline Processor(const Processor &orig) {
0114         processor = std::move(orig.processor);
0115         nOutput = orig.nOutput;
0116       }
0117 
0118       inline Processor &operator=(const Processor &orig) {
0119         processor = std::move(orig.processor);
0120         nOutput = orig.nOutput;
0121         return *this;
0122       }
0123 
0124       /// owned variable processor instance
0125       mutable std::unique_ptr<VarProcessor> processor;
0126 
0127       /// number of output variables
0128       unsigned int nOutput;
0129     };
0130 
0131     struct EvalContext {
0132       EvalContext(double *values, int *conf, unsigned int n) : values_(values), conf_(conf), n_(n) {}
0133 
0134       inline void eval(const VarProcessor *proc,
0135                        int *outConf,
0136                        double *output,
0137                        int *loop,
0138                        VarProcessor::LoopCtx &ctx,
0139                        unsigned int offset,
0140                        unsigned int out) const {
0141         proc->eval(values_, conf_, output, outConf, loop, ctx, offset);
0142       }
0143 
0144       inline double output(unsigned int output) const { return values_[conf_[output]]; }
0145 
0146       inline double *values() const { return values_; }
0147       inline int *conf() const { return conf_; }
0148       inline unsigned int n() const { return n_; }
0149 
0150       double *values_;
0151       int *conf_;
0152       unsigned int n_;
0153     };
0154 
0155     struct DerivContext {
0156       DerivContext() : n_(0) {}
0157 
0158       void eval(const VarProcessor *proc,
0159                 int *outConf,
0160                 double *output,
0161                 int *loop,
0162                 VarProcessor::LoopCtx &ctx,
0163                 unsigned int offset,
0164                 unsigned int out) const;
0165 
0166       double output(unsigned int output, std::vector<double> &derivs) const;
0167 
0168       inline double *values() const { return &values_.front(); }
0169       inline int *conf() const { return &conf_.front(); }
0170       inline unsigned int n() const { return n_; }
0171 
0172       mutable std::vector<double> values_;
0173       mutable std::vector<double> deriv_;
0174       mutable std::vector<int> conf_;
0175       unsigned int n_;
0176     };
0177 
0178   private:
0179     /// construct processors from calibration and setup variables
0180     void setup(const Calibration::MVAComputer *calib);
0181 
0182     /// map variable identifier \a name to the numerical position in the array
0183     int getVariableId(AtomicId name) const;
0184 
0185     /// evaluate discriminator from flattened variable array
0186     template <class T>
0187     void evalInternal(T &ctx) const;
0188 
0189     /// vector of input variables
0190     std::vector<InputVar> inputVariables;
0191 
0192     /// vector of variable processors
0193     std::vector<Processor> varProcessors;
0194 
0195     /// total number of variables to expect while computing discriminator
0196     unsigned int nVars;
0197 
0198     /// index of the variable in the "conf" array to return as result
0199     unsigned int output;
0200 
0201     /// in case calibration object is owned by the MVAComputer
0202     std::unique_ptr<Calibration::MVAComputer> owned;
0203   };
0204 
0205 }  // namespace PhysicsTools
0206 
0207 #include "PhysicsTools/MVAComputer/interface/MVAComputer.icc"
0208 
0209 #endif  // PhysicsTools_MVAComputer_MVAComputer_h