CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
MVAComputer.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <sstream>
3 #include <fstream>
4 #include <algorithm>
5 #include <iterator>
6 #include <cstddef>
7 #include <cstring>
8 #include <vector>
9 #include <set>
10 
11 // ROOT version magic to support TMVA interface changes in newer ROOT
12 #include <RVersion.h>
13 
14 #include <TBufferFile.h>
15 #include <TClass.h>
16 
18 
20 
26 
27 // #define DEBUG_EVAL
28 
29 #ifdef DEBUG_EVAL
31 #endif
32 
33 #define STANDALONE_HEADER "MVAComputer calibration\n"
34 
35 namespace PhysicsTools {
36 
38  nVars(0), output(0)
39 {
40  setup(calib);
41 }
42 
44  nVars(0), output(0)
45 {
46  if (owned)
47  this->owned.reset(calib);
48  setup(calib);
49 }
50 
52  nVars(0), output(0), owned(readCalibration(filename))
53 {
54  setup(owned.get());
55 }
56 
57 MVAComputer::MVAComputer(std::istream &is) :
58  nVars(0), output(0), owned(readCalibration(is))
59 {
60  setup(owned.get());
61 }
62 
64 {
65 
66  nVars = calib->inputSet.size();
67  output = calib->output;
68 
69  std::vector<Variable::Flags> flags(nVars, Variable::FLAG_ALL);
70  const TrainMVAComputerCalibration *trainCalib =
71  dynamic_cast<const TrainMVAComputerCalibration*>(calib);
72  if (trainCalib)
73  trainCalib->initFlags(flags);
74 
76  std::vector<Calibration::VarProcessor*> processors =
77  calib->getProcessors();
78 
79  for(std::vector<Calibration::VarProcessor*>::const_iterator iter =
80  processors.begin();
81  iter != processors.end(); ++iter) {
82  std::string name = (*iter)->getInstanceName();
83  VarProcessor *processor =
84  VarProcessor::create(name.c_str(), *iter, this);
85  if (!processor)
86  throw cms::Exception("UnknownProcessor")
87  << name << " could not be instantiated."
88  << std::endl;
89 
90  VarProcessor::ConfigCtx::iterator::difference_type pos =
91  config.end() - config.begin();
92  processor->configure(config);
93  unsigned int nOutput = (config.end() - config.begin()) - pos;
94  if (!nOutput)
95  throw cms::Exception("InvalidProcessor")
96  << name << " rejected input variable "
97  "configuration" << std::endl;
98 
99  varProcessors.push_back(Processor(processor, nOutput));
100  }
101 
102  for(VarProcessor::ConfigCtx::iterator iter = config.begin() + nVars;
103  iter != config.end(); iter++) {
104  VarProcessor::Config *origin = &config[iter->origin];
105  if (iter->origin >= nVars)
106  iter->origin = origin->origin;
107 
108  if (iter->mask & Variable::FLAG_MULTIPLE) {
109  iter->mask = (Variable::Flags)(iter->mask &
110  origin->mask);
111  config[iter->origin].origin++;
112  }
113  }
114 
115  nVars = config.size();
116 
117  if (output >= nVars)
118  // FIXME || config[output].mask != Variable::FLAG_NONE)
119  throw cms::Exception("InvalidOutput")
120  << "Output variable at index " << output
121  << " invalid." << std::endl;
122 
123  std::set<InputVar> variables;
124  unsigned int i = 0;
125  for(std::vector<Calibration::Variable>::const_iterator iter = calib->inputSet.begin(); iter != calib->inputSet.end(); ++iter, i++) {
126  InputVar var;
127  var.var = Variable(iter->name, config[i].mask);
128  var.index = i;
129  var.multiplicity = 0;
130  variables.insert(var);
131  }
132 
133  inputVariables.resize(i);
134 
135  std::copy(variables.begin(), variables.end(), inputVariables.begin());
136 
137  for(unsigned int j = 0; j < i; j++)
138  inputVariables[j].multiplicity = config[j].origin;
139 
140 }
141 
143 {
144 }
145 
147 {
148 
149  std::vector<InputVar>::const_iterator pos = std::lower_bound(inputVariables.begin(), inputVariables.end(), name);
150 
151  if (pos == inputVariables.end() || pos->var.getName() != name)
152  throw cms::Exception("InvalidVariable")
153  << "Input variable " << (const char*)name
154  << " not found." << std::endl;
155 
156  return pos->index;
157 }
158 
159 template<class T>
160 void MVAComputer::evalInternal(T &ctx) const
161 {
162 
163  double *output = ctx.values() + ctx.n();
164  int *outConf = ctx.conf() + inputVariables.size();
165 
166 #ifdef DEBUG_EVAL
167  std::cout << "Input" << std::endl;
168  double *v = ctx.values();
169  for(int *o = ctx.conf(); o < outConf; o++) {
170  std::cout << "\tVar " << (o - ctx.conf()) << std::endl;
171  for(int i = o[0]; i < o[1]; i++)
172  std::cout << "\t\t" << *v++ << std::endl;
173  }
174 #endif
175  std::vector<Processor>::const_iterator iter = varProcessors.begin();
176  while(iter != varProcessors.end()) {
177  std::vector<Processor>::const_iterator loop = iter;
178  int *loopOutConf = outConf;
179  int *loopStart = 0;
180  double *loopOutput = output;
181 
183  unsigned int offset = 0;
184  while(status != VarProcessor::kStop) {
185  std::vector<Processor>::const_iterator next = iter + 1;
186  unsigned int nextOutput = (next != varProcessors.end())
187  ? next->nOutput : 0;
188 
189 #ifdef DEBUG_EVAL
190  std::string demangledName;
191  edm::typeDemangle(typeid(*iter->processor).name(), demangledName);
192  std::cout << demangledName << std::endl;
193 #endif
194  if (status != VarProcessor::kSkip)
195  ctx.eval(&*iter->processor, outConf, output,
196  loopStart ? loopStart : loopOutConf,
197  offset, iter->nOutput);
198 
199 #ifdef DEBUG_EVAL
200  for(unsigned int i = 0; i < iter->nOutput;
201  i++, outConf++) {
202  std::cout << "\tVar " << (outConf - ctx.conf())
203  << std::endl;
204  for(int j = outConf[0]; j < outConf[1]; j++)
205  std::cout << "\t\t" << *output++
206  << std::endl;
207  }
208 #else
209  int orig = *outConf;
210  outConf += iter->nOutput;
211  output += *outConf - orig;
212 #endif
213 
214  status = loop->processor->loop(output, outConf,
215  nextOutput, offset);
216 
217  if (status == VarProcessor::kReset) {
218  outConf = loopOutConf;
219  output = loopOutput;
220  loopStart = 0;
221  offset = 0;
222  iter = loop;
223  } else {
224  if (loop == iter)
225  loopStart = outConf;
226  iter = next;
227  }
228  }
229  }
230 }
231 
233 {
234  std::ifstream file(filename);
235  return readCalibration(file);
236 }
237 
239 {
240  if (!is.good())
241  throw cms::Exception("InvalidFileState")
242  << "Stream passed to MVAComputer::readCalibration "
243  "has an invalid state." << std::endl;
244 
245  char header[sizeof STANDALONE_HEADER - 1] = { 0, };
246  if (is.readsome(header, sizeof header) != sizeof header ||
247  std::memcmp(header, STANDALONE_HEADER, sizeof header) != 0)
248  throw cms::Exception("InvalidFileFormat")
249  << "Stream passed to MVAComputer::readCalibration "
250  "is not a valid calibration file." << std::endl;
251 
252  TClass *rootClass =
253  TClass::GetClass("PhysicsTools::Calibration::MVAComputer");
254  if (!rootClass)
255  throw cms::Exception("DictionaryMissing")
256  << "CondFormats dictionary for "
257  "PhysicsTools::Calibration::MVAComputer missing"
258  << std::endl;
259 
260  ext::izstream izs(&is);
261  std::ostringstream ss;
262  ss << izs.rdbuf();
263  std::string buf = ss.str();
264 
265  TBufferFile buffer(TBuffer::kRead, buf.size(), const_cast<void*>(
266  static_cast<const void*>(buf.c_str())), kFALSE);
267  buffer.InitMap();
268 
269  std::auto_ptr<Calibration::MVAComputer> calib(
271  buffer.StreamObject(static_cast<void*>(calib.get()), rootClass);
272 
273  return calib.release();
274 }
275 
278 {
279  std::ofstream file(filename);
280  writeCalibration(file, calib);
281 }
282 
283 void MVAComputer::writeCalibration(std::ostream &os,
285 {
286  if (!os.good())
287  throw cms::Exception("InvalidFileState")
288  << "Stream passed to MVAComputer::writeCalibration "
289  "has an invalid state." << std::endl;
290 
291  os << STANDALONE_HEADER;
292 
293  TClass *rootClass =
294  TClass::GetClass("PhysicsTools::Calibration::MVAComputer");
295  if (!rootClass)
296  throw cms::Exception("DictionaryMissing")
297  << "CondFormats dictionary for "
298  "PhysicsTools::Calibration::MVAComputer missing"
299  << std::endl;
300 
301  TBufferFile buffer(TBuffer::kWrite);
302  buffer.StreamObject(const_cast<void*>(static_cast<const void*>(calib)),
303  rootClass);
304 
305  ext::ozstream ozs(&os);
306  ozs.write(buffer.Buffer(), buffer.Length());
307  ozs.flush();
308 }
309 
310 // instantiate use cases fo MVAComputer::evalInternal
311 
313  const VarProcessor *proc, int *outConf, double *output,
314  int *loop, unsigned int offset, unsigned int out) const
315 {
316  proc->deriv(values(), conf(), output, outConf,
317  loop, offset, n(), out, deriv_);
318 }
319 
321  std::vector<double> &derivs) const
322 {
323  derivs.clear();
324  derivs.reserve(n_);
325 
326  int pos = conf_[output];
327  if (pos >= (int)n_)
328  std::copy(&deriv_.front() + n_ * (pos - n_),
329  &deriv_.front() + n_ * (pos - n_ + 1),
330  std::back_inserter(derivs));
331  else {
332  derivs.resize(n_);
333  derivs[pos] = 1.;
334  }
335 
336  return values_[pos];
337 }
338 
339 template void MVAComputer::evalInternal(EvalContext &ctx) const;
340 template void MVAComputer::evalInternal(DerivContext &ctx) const;
341 
342 } // namespace PhysicsTools
int i
Definition: DBlmapReader.cc:9
virtual std::vector< VarProcessor * > getProcessors() const
Definition: MVAComputer.cc:111
double output(unsigned int output, std::vector< double > &derivs) const
Definition: MVAComputer.cc:320
input variable configuration object
Definition: MVAComputer.h:100
TrainProcessor *const proc
Definition: MVATrainer.cc:101
unsigned int multiplicity
number of times each appearance of that variable can appear while computing the discriminator ...
Definition: MVAComputer.h:108
void configure(ConfigCtx &config)
called from the discriminator computer to configure processor
Definition: VarProcessor.cc:53
Class describing an input variable.
Definition: Variable.h:34
for internal use by MVATrainer
Definition: Calibration.h:11
std::vector< Variable::Flags > flags
Definition: MVATrainer.cc:135
void deriv(double *input, int *conf, double *output, int *outConf, int *loop, unsigned int offset, unsigned int in, unsigned int out, std::vector< double > &deriv) const
run the processor evaluation pass on this processor and compute derivatives
std::vector< InputVar > inputVariables
vector of input variables
Definition: MVAComputer.h:189
std::auto_ptr< Calibration::MVAComputer > owned
in case calibration object is owned by the MVAComputer
Definition: MVAComputer.h:201
static Calibration::MVAComputer * readCalibration(const char *filename)
read calibration object from plain file
Definition: MVAComputer.cc:232
Cheap generic unique keyword identifier class.
Definition: AtomicId.h:32
unsigned int nVars
total number of variables to expect while computing discriminator
Definition: MVAComputer.h:195
std::string demangledName(const std::type_info &typeInfo)
Definition: ClassUtils.cc:82
unsigned int output
index of the variable in the &quot;conf&quot; array to return as result
Definition: MVAComputer.h:198
void typeDemangle(char const *mangledName, std::string &demangledName)
MVATrainerComputer * calib
Definition: MVATrainer.cc:64
void eval(const VarProcessor *proc, int *outConf, double *output, int *loop, unsigned int offset, unsigned int out) const
Definition: MVAComputer.cc:312
static void writeCalibration(const char *filename, const Calibration::MVAComputer *calib)
write calibration object to file
Definition: MVAComputer.cc:276
int j
Definition: DBlmapReader.cc:9
unsigned int offset(bool)
virtual void initFlags(std::vector< Variable::Flags > &flags) const =0
variable processor container
Definition: MVAComputer.h:120
tuple out
Definition: dbtoconf.py:99
#define STANDALONE_HEADER
Definition: MVAComputer.cc:33
static Base_t * create(const char *name, const CalibBase_t *calib, Parent_t *parent=0)
ZIStreamBuf_t * rdbuf()
Definition: zstream.h:122
std::vector< Variable > inputSet
Definition: MVAComputer.h:177
MVAComputer(const Calibration::MVAComputer *calib)
construct a discriminator computer from a const calibation object
Definition: MVAComputer.cc:37
std::vector< Processor > varProcessors
vector of variable processors
Definition: MVAComputer.h:192
void evalInternal(T &ctx) const
evaluate discriminator from flattened variable array
Definition: MVAComputer.cc:160
tuple filename
Definition: lut2db_cfg.py:20
unsigned int index
variable index in fixed-position evaluation array
Definition: MVAComputer.h:105
tuple cout
Definition: gather_cfg.py:121
Variable var
generic variable information (name, ...)
Definition: MVAComputer.h:102
tuple status
Definition: ntuplemaker.py:245
long double T
Helper class for discriminator computer set-up procedure.
Definition: VarProcessor.h:53
unsigned int getVariableId(AtomicId name) const
map variable identifier name to the numerical position in the array
Definition: MVAComputer.cc:146
mathSSE::Vec4< T > v
Common base class for variable processors.
Definition: VarProcessor.h:39
void setup(const Calibration::MVAComputer *calib)
construct processors from calibration and setup variables
Definition: MVAComputer.cc:63
const_iterator begin() const
Definition: VarProcessor.h:77