CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/PhysicsTools/MVAComputer/src/VarProcessor.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     MVAComputer
00004 // Class  :     VarProcessor
00005 // 
00006 
00007 // Implementation:
00008 //     Base class for variable processors. Basically only passes calls
00009 //     through to virtual methods in the actual implementation daughter class.
00010 //
00011 // Author:      Christophe Saout
00012 // Created:     Sat Apr 24 15:18 CEST 2007
00013 // $Id: VarProcessor.cc,v 1.8 2011/03/11 20:33:54 kukartse Exp $
00014 //
00015 
00016 #include "FWCore/Utilities/interface/Exception.h"
00017 
00018 #include "FWCore/PluginManager/interface/PluginManager.h"
00019 #include "FWCore/PluginManager/interface/PluginFactory.h"
00020 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00021 
00022 #include "PhysicsTools/MVAComputer/interface/VarProcessor.h"
00023 #include "PhysicsTools/MVAComputer/interface/Calibration.h"
00024 #include "PhysicsTools/MVAComputer/interface/BitSet.h"
00025 
00026 // #define DEBUG_DERIV
00027 
00028 #ifdef DEBUG_DERIV
00029 #       include <Reflex/Tools.h>
00030 #endif
00031 
00032 EDM_REGISTER_PLUGINFACTORY(PhysicsTools::VarProcessor::PluginFactory,
00033                            "PhysicsToolsMVAComputer");
00034 
00035 namespace PhysicsTools {
00036 
00037 VarProcessor::VarProcessor(const char *name,
00038                            const Calibration::VarProcessor *calib,
00039                            const MVAComputer *computer) :
00040         computer(computer),
00041         inputVars(Calibration::convert(calib->inputVars)),
00042         nInputVars(inputVars.bits())
00043 {
00044 }
00045 
00046 VarProcessor::~VarProcessor()
00047 {
00048         inputVars = BitSet(0);
00049         nInputVars = 0;
00050 }
00051 
00052 void VarProcessor::configure(ConfigCtx &config)
00053 {
00054         ConfigCtx::size_type pos = config.size();
00055         if (pos != inputVars.size())
00056                 return;
00057 
00058         ConfIterator iter(inputVars.iter(), config);
00059         configure(iter, nInputVars);
00060 
00061         VarProcessor *loop = config.loop ? config.loop : this;
00062         ConfigCtx::Context *ctx =
00063                 loop->configureLoop(config.ctx, config.begin(),
00064                                     config.begin() + pos, config.end());
00065 
00066         if (ctx != config.ctx) {
00067                 delete config.ctx;
00068                 config.ctx = ctx;
00069         }
00070 
00071         if (config.loop && !ctx)
00072                 config.loop = 0;
00073         else if (!config.loop && ctx)
00074                 config.loop = this;
00075 }
00076 
00077 VarProcessor::ConfigCtx::ConfigCtx(std::vector<Variable::Flags> flags) :
00078         loop(0), ctx(0)
00079 {
00080         for(std::vector<Variable::Flags>::const_iterator iter = flags.begin();
00081             iter != flags.end(); ++iter)
00082                 configs.push_back(Config(*iter, 1));
00083 }
00084 
00085 VarProcessor::ConfigCtx::Context *
00086 VarProcessor::configureLoop(ConfigCtx::Context *ctx, ConfigCtx::iterator begin,
00087                             ConfigCtx::iterator cur, ConfigCtx::iterator end)
00088 {
00089         return 0;
00090 }
00091 
00092 template<>
00093 VarProcessor *ProcessRegistry<VarProcessor, Calibration::VarProcessor,
00094                               const MVAComputer>::Factory::create(
00095                 const char *name, const Calibration::VarProcessor *calib,
00096                 const MVAComputer *parent)
00097 {
00098         VarProcessor *result = ProcessRegistry::create(name, calib, parent);
00099         if (!result) {
00100                 // try to load the shared library and retry
00101                 try {
00102                         delete VarProcessor::PluginFactory::get()->create(
00103                                         std::string("VarProcessor/") + name);
00104                         result = ProcessRegistry::create(name, calib, parent);
00105                 } catch(const cms::Exception &e) {
00106                         // caller will have to deal with the null pointer
00107                         // in principle this will just give a slightly more
00108                         // descriptive error message (and will rethrow anyhow)
00109 
00110                   edm::LogError("CannotBuildMVAProc")
00111                     << "Caught exception when building processor: "
00112                     << name << " message: " << std::endl
00113                     << e.what() << std::endl;
00114                   throw e;
00115                 }
00116         }
00117         return result;
00118 }
00119 
00120 void VarProcessor::deriv(double *input, int *conf, double *output,
00121                          int *outConf, int *loop, unsigned int offset,
00122                          unsigned int in, unsigned int out_,
00123                          std::vector<double> &deriv) const
00124 {
00125         ValueIterator iter(inputVars.iter(), input, conf,
00126                            output, outConf, loop, offset);
00127 
00128         eval(iter, nInputVars);
00129 
00130         std::vector<double> matrix = this->deriv(iter, nInputVars);
00131 
00132         unsigned int size = 0;
00133         while(iter)
00134                 size += (iter++).size();
00135         unsigned int out = matrix.empty() ? 0 : (matrix.size() / size);
00136 
00137         if (matrix.size() != out * size ||
00138             (out > 1 && (int)out != outConf[out_] - outConf[0]))
00139                 throw cms::Exception("VarProcessor")
00140                         << "Derivative matrix implausible size in "
00141                         << typeid(*this).name() << "."
00142                         << std::endl;
00143 
00144 #ifdef DEBUG_DERIV
00145         if (!matrix.empty()) {
00146                 std::cout << "---------------- "
00147                           << ROOT::Reflex::Tools::Demangle(typeid(*this))
00148                           << std::endl;
00149                 for(unsigned int i = 0; i < out; i++) {
00150                         for(unsigned int j = 0; j < size; j++)
00151                                 std::cout << matrix.at(i*size+j) << "\t";
00152                         std::cout << std::endl;
00153                 }
00154                 std::cout << "----------------" << std::endl;
00155         }
00156 
00157         std::cout << "======= in = " << in << ", size = " << size
00158                   << ", out = " << out << ", matrix = " << matrix.size()
00159                   << std::endl;
00160 #endif
00161 
00162         unsigned int sz = (outConf[out_] - in) * in;
00163         unsigned int oldSz = deriv.size();
00164         if (oldSz < sz)
00165                 deriv.resize(sz);
00166 
00167         double *begin = &deriv.front() + (outConf[0] - in + offset) * in;
00168         double *end = begin + out * in;
00169         if (begin < &deriv.front() + oldSz)
00170                 std::fill(begin, end, 0.0);
00171 
00172         if (matrix.empty())
00173                 return;
00174 
00175         double *m0 = &matrix.front();
00176         BitSet::Iterator cur = inputVars.iter();
00177         for(unsigned int i = 0; i < nInputVars; i++, ++cur) {
00178 #ifdef DEBUG_DERIV
00179                 std::cout << " inputvar " << i << std::endl;
00180 #endif
00181                 int *curConf = conf + cur();
00182                 unsigned int pos = *curConf;
00183 #ifdef DEBUG_DERIV
00184                 std::cout << " -> cur = " << cur() << ", pos = "
00185                           << pos << std::endl;
00186 #endif
00187                 if (loop && curConf >= loop) {
00188                         pos += offset;
00189                         loop = 0;
00190                 }
00191 
00192                 unsigned int n = loop ? (curConf[1] - curConf[0]) : 1;
00193                 for(unsigned int j = 0; j < n; m0++, j++, pos++) {
00194 #ifdef DEBUG_DERIV
00195                         std::cout << "  multip " << j << std::endl;
00196 #endif
00197                         double *p = begin;
00198                         if (pos >= in) {
00199 #ifdef DEBUG_DERIV
00200                                 std::cout << "   deriv " << (pos - in)
00201                                           << std::endl;
00202 #endif
00203                                 const double *q = &deriv.front() +
00204                                                   (pos - in) * in;
00205                                 for(const double *m = m0; p < end;
00206                                     m += size, q -= in)
00207                                         for(unsigned int k = 0; k < in; k++)
00208                                                 *p++ += *m * *q++;
00209                         } else {
00210 #ifdef DEBUG_DERIV
00211                                 std::cout << "   in " << pos << std::endl;
00212 #endif
00213                                 for(const double *m = m0; p < end;
00214                                     m += size, p += in)
00215                                         p[pos] += *m;
00216                         }
00217                 }
00218         }
00219 
00220 #ifdef DEBUG_DERIV
00221         std::cout << "================" << std::endl;
00222         for(const double *p = &deriv.front();
00223             p != &deriv.front() + deriv.size();) {
00224                 for(unsigned int j = 0; j < in; j++)
00225                         std::cout << *p++ << "\t";
00226                 std::cout << std::endl;
00227         }
00228         std::cout << "================" << std::endl;
00229 #endif
00230 }
00231 
00232 } // namespace PhysicsTools