CMS 3D CMS Logo

ProcLikelihood.cc
Go to the documentation of this file.
1 #include <algorithm>
2 #include <iostream>
3 #include <numeric>
4 #include <iomanip>
5 #include <cstring>
6 #include <vector>
7 #include <string>
8 #include <memory>
9 #include <map>
10 
11 #include <xercesc/dom/DOM.hpp>
12 
13 #include <TH1.h>
14 
16 
18 
24 
26 
27 using namespace PhysicsTools;
28 
29 namespace { // anonymous
30 
31 class ProcLikelihood : public TrainProcessor {
32  public:
34 
35  ProcLikelihood(const char *name, const AtomicId *id,
36  MVATrainer *trainer);
37  ~ProcLikelihood() override;
38 
39  void configure(DOMElement *elem) override;
40  Calibration::VarProcessor *getCalibration() const override;
41 
42  void trainBegin() override;
43  void trainData(const std::vector<double> *values,
44  bool target, double weight) override;
45  void trainEnd() override;
46 
47  bool load() override;
48  void save() override;
49 
50  struct PDF {
51  std::vector<double> distr;
53  };
54 
55  private:
56  enum Iteration {
57  ITER_EMPTY,
58  ITER_RANGE,
59  ITER_FILL,
60  ITER_DONE
61  };
62 
63  struct SigBkg {
64  PDF signal;
65  PDF background;
66  unsigned int smooth;
67  Iteration iteration;
68  };
69 
70  std::vector<SigBkg> pdfs;
71  std::vector<double> sigSum;
72  std::vector<double> bkgSum;
73  std::vector<double> bias;
74  int categoryIdx;
75  bool logOutput;
76  bool individual;
77  bool neverUndefined;
78  bool keepEmpty;
79  unsigned int nCategories;
80  bool doCategoryBias;
81  bool doGivenBias;
82  bool doGlobalBias;
83  Iteration iteration;
84 };
85 
86 ProcLikelihood::Registry registry("ProcLikelihood");
87 
88 ProcLikelihood::ProcLikelihood(const char *name, const AtomicId *id,
89  MVATrainer *trainer) :
90  TrainProcessor(name, id, trainer),
91  categoryIdx(-1),
92  logOutput(false),
93  individual(false),
94  neverUndefined(true),
95  keepEmpty(false),
96  nCategories(1),
97  doCategoryBias(false),
98  doGivenBias(false),
99  doGlobalBias(false),
100  iteration(ITER_FILL)
101 {
102 }
103 
104 ProcLikelihood::~ProcLikelihood()
105 {
106 }
107 
108 void ProcLikelihood::configure(DOMElement *elem)
109 {
110  int i = 0;
111  bool first = true;
112  for(DOMNode *node = elem->getFirstChild();
113  node; node = node->getNextSibling()) {
114  if (node->getNodeType() != DOMNode::ELEMENT_NODE)
115  continue;
116 
117  DOMElement *elem = static_cast<DOMElement*>(node);
118 
119  XMLSimpleStr nodeName(node->getNodeName());
120 
121  if (std::strcmp(nodeName, "general") == 0) {
122  if (!first)
123  throw cms::Exception("ProcLikelihood")
124  << "Config tag general needs to come "
125  "first." << std::endl;
126 
127  if (XMLDocument::hasAttribute(elem, "bias")) {
128  double globalBias =
129  XMLDocument::readAttribute<double>(
130  elem, "bias");
131  bias.push_back(globalBias);
132  doGivenBias = true;
133  } else
134  doGivenBias = false;
135 
136  doCategoryBias = XMLDocument::readAttribute<bool>(
137  elem, "category_bias", false);
138  doGlobalBias = XMLDocument::readAttribute<bool>(
139  elem, "global_bias", false);
140  logOutput = XMLDocument::readAttribute<bool>(
141  elem, "log", false);
142  individual = XMLDocument::readAttribute<bool>(
143  elem, "individual", false);
144  neverUndefined = !XMLDocument::readAttribute<bool>(
145  elem, "strict", false);
146  keepEmpty = !XMLDocument::readAttribute<bool>(
147  elem, "ignore_empty", true);
148 
149  first = false;
150  continue;
151  }
152  first = false;
153 
154  if (std::strcmp(nodeName, "bias_table") == 0) {
155  if (!bias.empty())
156  throw cms::Exception("ProcLikelihood")
157  << "Bias can be only specified once."
158  << std::endl;
159 
160  for(DOMNode *subNode = node->getFirstChild();
161  subNode; subNode = subNode->getNextSibling()) {
162  if (subNode->getNodeType() !=
163  DOMNode::ELEMENT_NODE)
164  continue;
165 
166  if (std::strcmp(XMLSimpleStr(
167  subNode->getNodeName()),
168  "bias") != 0)
169  throw cms::Exception("ProcLikelihood")
170  << "Expected bias tag in "
171  "config." << std::endl;
172 
173  bias.push_back(
174  XMLDocument::readContent<double>(
175  subNode));
176  }
177 
178  continue;
179  }
180 
181  if (std::strcmp(nodeName, "category") != 0) {
182  i++;
183  continue;
184  }
185 
186  if (categoryIdx >= 0)
187  throw cms::Exception("ProcLikelihood")
188  << "More than one category variable given."
189  << std::endl;
190 
191 
192  unsigned int count = XMLDocument::readAttribute<unsigned int>(
193  elem, "count");
194 
195  categoryIdx = i;
196  nCategories = count;
197  }
198 
199  for(DOMNode *node = elem->getFirstChild();
200  node; node = node->getNextSibling()) {
201  if (node->getNodeType() != DOMNode::ELEMENT_NODE)
202  continue;
203 
204  XMLSimpleStr nodeName(node->getNodeName());
205  if (std::strcmp(nodeName, "general") == 0 ||
206  std::strcmp(nodeName, "bias_table") == 0 ||
207  std::strcmp(nodeName, "category") == 0)
208  continue;
209 
210  if (std::strcmp(nodeName, "sigbkg") != 0)
211  throw cms::Exception("ProcLikelihood")
212  << "Expected sigbkg tag in config section."
213  << std::endl;
214  elem = static_cast<DOMElement*>(node);
215 
216  SigBkg pdf;
217 
218  unsigned int size = XMLDocument::readAttribute<unsigned int>(
219  elem, "size", 50);
220  pdf.signal.distr.resize(size);
221  pdf.background.distr.resize(size);
222 
223  pdf.smooth = XMLDocument::readAttribute<unsigned int>(
224  elem, "smooth", 0);
225 
226  if (XMLDocument::hasAttribute(elem, "lower") &&
227  XMLDocument::hasAttribute(elem, "upper")) {
228  pdf.signal.range.min =
229  XMLDocument::readAttribute<double>(
230  elem, "lower");
231  pdf.signal.range.max =
232  XMLDocument::readAttribute<double>(
233  elem, "upper");
234  pdf.background.range = pdf.signal.range;
235  pdf.iteration = ITER_FILL;
236  } else
237  pdf.iteration = ITER_EMPTY;
238 
239  for(unsigned int i = 0; i < nCategories; i++)
240  pdfs.push_back(pdf);
241  }
242 
243  unsigned int nInputs = getInputs().size();
244  if (categoryIdx >= 0)
245  nInputs--;
246 
247  sigSum.resize(nCategories);
248  bkgSum.resize(nCategories);
249 
250  if (!doGivenBias && !bias.empty()) {
251  doGivenBias = true;
252  if (bias.size() != nCategories)
253  throw cms::Exception("ProcLikelihood")
254  << "Invalid number of category bias entries."
255  << std::endl;
256  }
257  while (doGivenBias && bias.size() < nCategories)
258  bias.push_back(bias.front());
259 
260  if (pdfs.size() != nInputs * nCategories)
261  throw cms::Exception("ProcLikelihood")
262  << "Got " << (pdfs.size() / nCategories)
263  << " pdf configs for " << nInputs
264  << " input variables." << std::endl;
265 }
266 
267 Calibration::VarProcessor *ProcLikelihood::getCalibration() const
268 {
269  typedef Calibration::ProcLikelihood Calib;
270 
272 
273  std::vector<unsigned int> pdfMap;
274  for(unsigned int i = 0; i < nCategories; i++)
275  for(unsigned int j = i; j < pdfs.size(); j += nCategories)
276  pdfMap.push_back(j);
277 
278  double totalSig = std::accumulate(sigSum.begin(), sigSum.end(), 0.0);
279  double totalBkg = std::accumulate(bkgSum.begin(), bkgSum.end(), 0.0);
280 
281  for(unsigned int i = 0; i < pdfs.size(); i++) {
282  const SigBkg *iter = &pdfs[pdfMap[i]];
284 
285  pdf.signal = Calibration::HistogramF(iter->signal.distr.size(),
286  iter->signal.range);
287  double factor = std::accumulate(iter->signal.distr.begin(),
288  iter->signal.distr.end(), 0.0);
289  if (factor < 1e-20)
290  factor = 1.0;
291  else
292  factor = 1.0 / factor;
293  std::vector<double> values(iter->signal.distr.size() + 2);
294  std::transform(iter->signal.distr.begin(),
295  iter->signal.distr.end(),
296  values.begin() + 1,
297  [&](auto const& c) {return c * factor;});
298  pdf.signal.setValues(values);
299 
300  pdf.background =
301  Calibration::HistogramF(iter->background.distr.size(),
302  iter->background.range.min,
303  iter->background.range.max);
304  factor = std::accumulate(iter->background.distr.begin(),
305  iter->background.distr.end(), 0.0);
306  if (factor < 1e-20)
307  factor = 1.0;
308  else
309  factor = 1.0 / factor;
310  std::transform(iter->background.distr.begin(),
311  iter->background.distr.end(),
312  values.begin() + 1,
313  [&](auto const& c){return c * factor;});
315 
316  pdf.useSplines = true;
317 
318  calib->pdfs.push_back(pdf);
319  }
320 
321  calib->categoryIdx = categoryIdx;
322  calib->logOutput = logOutput;
323  calib->individual = individual;
324  calib->neverUndefined = neverUndefined;
325  calib->keepEmpty = keepEmpty;
326 
327  if (doGlobalBias || doCategoryBias || doGivenBias) {
328  for(unsigned int i = 0; i < nCategories; i++) {
329  double bias = doGlobalBias
330  ? totalSig / totalBkg
331  : 1.0;
332  if (doGivenBias)
333  bias *= this->bias[i];
334  if (doCategoryBias)
335  bias *= (sigSum[i] / totalSig) /
336  (bkgSum[i] / totalBkg);
337  calib->bias.push_back(bias);
338  }
339  }
340 
341  return calib;
342 }
343 
344 void ProcLikelihood::trainBegin()
345 {
346 }
347 
348 void ProcLikelihood::trainData(const std::vector<double> *values,
349  bool target, double weight)
350 {
351  int category = 0;
352  if (categoryIdx >= 0)
353  category = (int)values[categoryIdx].front();
354  if (category < 0 || category >= (int)nCategories)
355  return;
356 
357  if (iteration == ITER_FILL) {
358  if (target)
359  sigSum[category] += weight;
360  else
361  bkgSum[category] += weight;
362  }
363 
364  int i = 0;
365  for(std::vector<SigBkg>::iterator iter = pdfs.begin() + category;
366  iter < pdfs.end(); iter += nCategories, values++) {
367  if (i++ == categoryIdx)
368  values++;
369 
370  switch(iter->iteration) {
371  case ITER_EMPTY:
372  for(std::vector<double>::const_iterator value =
373  values->begin();
374  value != values->end(); value++) {
375  iter->signal.range.min =
376  iter->signal.range.max = *value;
377  iter->iteration = ITER_RANGE;
378  break;
379  }
380  case ITER_RANGE:
381  for(std::vector<double>::const_iterator value =
382  values->begin();
383  value != values->end(); value++) {
384  iter->signal.range.min =
385  std::min(iter->signal.range.min,
386  *value);
387  iter->signal.range.max =
388  std::max(iter->signal.range.max,
389  *value);
390  }
391  continue;
392  case ITER_FILL:
393  break;
394  default:
395  continue;
396  }
397 
398  PDF &pdf = target ? iter->signal : iter->background;
399  unsigned int n = pdf.distr.size() - 1;
400  double mult = 1.0 / pdf.range.width();
401 
402  for(std::vector<double>::const_iterator value =
403  values->begin(); value != values->end(); value++) {
404  double x = (*value - pdf.range.min) * mult;
405  if (x < 0.0)
406  x = 0.0;
407  else if (x >= 1.0)
408  x = 1.0;
409 
410  pdf.distr[(unsigned int)(x * n + 0.5)] += weight;
411  }
412  }
413 }
414 
415 void smoothArray(unsigned int n, double *values, unsigned int nTimes)
416 {
417  for(unsigned int iter = 0; iter < nTimes; iter++) {
418  double hold = n > 0 ? values[0] : 0.0;
419  for(unsigned int i = 0; i < n; i++) {
420  double delta = hold * 0.1;
421  double rem = 0.0;
422  if (i > 0) {
423  values[i - 1] += delta;
424  rem -= delta;
425  }
426  if (i < n - 1) {
427  hold = values[i + 1];
428  values[i + 1] += delta;
429  rem -= delta;
430  }
431  values[i] += rem;
432  }
433  }
434 }
435 
436 void ProcLikelihood::trainEnd()
437 {
438  bool done = true;
439  if (iteration == ITER_FILL)
440  iteration = ITER_DONE;
441 
442  for(std::vector<SigBkg>::iterator iter = pdfs.begin();
443  iter != pdfs.end(); iter++) {
444  switch(iter->iteration) {
445  case ITER_EMPTY:
446  case ITER_RANGE:
447  iter->background.range = iter->signal.range;
448  iter->iteration = ITER_FILL;
449  done = false;
450  break;
451  case ITER_FILL:
452  iter->signal.distr.front() *= 2;
453  iter->signal.distr.back() *= 2;
454  smoothArray(iter->signal.distr.size(),
455  &iter->signal.distr.front(),
456  iter->smooth);
457 
458  iter->background.distr.front() *= 2;
459  iter->background.distr.back() *= 2;
460  smoothArray(iter->background.distr.size(),
461  &iter->background.distr.front(),
462  iter->smooth);
463 
464  iter->iteration = ITER_DONE;
465  break;
466  default:
467  /* shut up */;
468  }
469  }
470 
471  if (done)
472  trained = true;
473 
474  if (done && monitoring) {
475  std::vector<SourceVariable*> inputs = getInputs().get();
476  if (categoryIdx >= 0)
477  inputs.erase(inputs.begin() + categoryIdx);
478 
479  for(std::vector<SigBkg>::iterator iter = pdfs.begin();
480  iter != pdfs.end(); iter++) {
481  unsigned int idx = iter - pdfs.begin();
482  unsigned int catIdx = idx % nCategories;
483  unsigned int varIdx = idx / nCategories;
484  SourceVariable *var = inputs[varIdx];
485  std::string name =
486  (const char*)var->getSource()->getName()
487  + std::string("_")
488  + (const char*)var->getName();
490  if (categoryIdx >= 0) {
491  name += Form("_CAT%d", catIdx);
492  title += Form(" (cat. %d)", catIdx);
493  }
494 
495  unsigned int n = iter->signal.distr.size() - 1;
496  double min = iter->signal.range.min -
497  0.5 * iter->signal.range.width() / n;
498  double max = iter->signal.range.max +
499  0.5 * iter->signal.range.width() / n;
500  TH1F *histo = monitoring->book<TH1F>(name + "_sig",
501  (name + "_sig").c_str(),
502  (title + " signal").c_str(), n + 1, min, max);
503  for(unsigned int i = 0; i < n; i++)
504  histo->SetBinContent(
505  i + 1, iter->signal.distr[i]);
506 
507  n = iter->background.distr.size() - 1;
508  min = iter->background.range.min -
509  0.5 * iter->background.range.width() / n;
510  max = iter->background.range.max +
511  0.5 * iter->background.range.width() / n;
512  histo = monitoring->book<TH1F>(name + "_bkg",
513  (name + "_bkg").c_str(),
514  (title + " background").c_str(),
515  n + 1, min, max);
516  for(unsigned int i = 0; i < n; i++)
517  histo->SetBinContent(
518  i + 1, iter->background.distr[i]);
519  }
520  }
521 }
522 
523 void xmlParsePDF(ProcLikelihood::PDF &pdf, DOMElement *elem)
524 {
525  if (!elem ||
526  std::strcmp(XMLSimpleStr(elem->getNodeName()), "pdf") != 0)
527  throw cms::Exception("ProcLikelihood")
528  << "Expected pdf tag in sigbkg train data."
529  << std::endl;
530 
531  pdf.range.min = XMLDocument::readAttribute<double>(elem, "lower");
532  pdf.range.max = XMLDocument::readAttribute<double>(elem, "upper");
533 
534  pdf.distr.clear();
535  for(DOMNode *node = elem->getFirstChild();
536  node; node = node->getNextSibling()) {
537  if (node->getNodeType() != DOMNode::ELEMENT_NODE)
538  continue;
539 
540  if (std::strcmp(XMLSimpleStr(node->getNodeName()),
541  "value") != 0)
542  throw cms::Exception("ProcLikelihood")
543  << "Expected value tag in train file."
544  << std::endl;
545 
546  pdf.distr.push_back(XMLDocument::readContent<double>(node));
547  }
548 }
549 
550 namespace {
551  struct Id {
553  AtomicId name;
554  unsigned int category;
555 
556  inline Id(AtomicId source, AtomicId name,
557  unsigned int category) :
558  source(source), name(name), category(category) {}
559 
560  inline bool operator == (const Id &other) const
561  {
562  return source == other.source &&
563  name == other.name &&
564  category == other.category;
565  }
566 
567  inline bool operator < (const Id &other) const
568  {
569  if (source < other.source)
570  return true;
571  if (!(source == other.source))
572  return false;
573  if (name < other.name)
574  return true;
575  if (!(name == other.name))
576  return false;
577  return category < other.category;
578  }
579  };
580 }
581 
583 {
584  std::string filename = trainer->trainFileName(this, "xml");
585  if (!exists(filename))
586  return false;
587 
588  XMLDocument xml(filename);
589  DOMElement *elem = xml.getRootNode();
590  if (std::strcmp(XMLSimpleStr(elem->getNodeName()),
591  "ProcLikelihood") != 0)
592  throw cms::Exception("ProcLikelihood")
593  << "XML training data file has bad root node."
594  << std::endl;
595 
596  unsigned int version = XMLDocument::readAttribute<unsigned int>(
597  elem, "version", 1);
598 
599  if (version < 1 || version > 2)
600  throw cms::Exception("ProcLikelihood")
601  << "Unsupported version " << version
602  << "in train file." << std::endl;
603 
604  DOMNode *node;
605  for(node = elem->getFirstChild();
606  node; node = node->getNextSibling()) {
607  if (node->getNodeType() != DOMNode::ELEMENT_NODE)
608  continue;
609 
610  if (std::strcmp(XMLSimpleStr(node->getNodeName()),
611  "categories") != 0)
612  throw cms::Exception("ProcLikelihood")
613  << "Expected categories tag in train file."
614  << std::endl;
615 
616  unsigned int i = 0;
617  for(DOMNode *subNode = node->getFirstChild();
618  subNode; subNode = subNode->getNextSibling()) {
619  if (subNode->getNodeType() != DOMNode::ELEMENT_NODE)
620  continue;
621 
622  if (i >= nCategories)
623  throw cms::Exception("ProcLikelihood")
624  << "Too many categories in train "
625  "file." << std::endl;
626 
627  if (std::strcmp(XMLSimpleStr(subNode->getNodeName()),
628  "category") != 0)
629  throw cms::Exception("ProcLikelihood")
630  << "Expected category tag in train "
631  "file." << std::endl;
632 
633  elem = static_cast<DOMElement*>(subNode);
634 
635  sigSum[i] = XMLDocument::readAttribute<double>(
636  elem, "signal");
637  bkgSum[i] = XMLDocument::readAttribute<double>(
638  elem, "background");
639  i++;
640  }
641  if (i < nCategories)
642  throw cms::Exception("ProcLikelihood")
643  << "Too few categories in train file."
644  << std::endl;
645 
646  break;
647  }
648 
649  std::map<Id, SigBkg*> pdfMap;
650 
651  for(std::vector<SigBkg>::iterator iter = pdfs.begin();
652  iter != pdfs.end(); ++iter) {
653  SigBkg *ptr = &*iter;
654  unsigned int idx = iter - pdfs.begin();
655  unsigned int catIdx = idx % nCategories;
656  unsigned int varIdx = idx / nCategories;
657  if (categoryIdx >= 0 && (int)varIdx >= categoryIdx)
658  varIdx++;
659  const SourceVariable *var = getInputs().get()[varIdx];
660  Id id(var->getSource()->getName(), var->getName(), catIdx);
661 
662  pdfMap[id] = ptr;
663  }
664 
665  std::vector<SigBkg>::iterator cur = pdfs.begin();
666 
667  for(node = node->getNextSibling();
668  node; node = node->getNextSibling()) {
669  if (node->getNodeType() != DOMNode::ELEMENT_NODE)
670  continue;
671 
672  if (std::strcmp(XMLSimpleStr(node->getNodeName()),
673  "sigbkg") != 0)
674  throw cms::Exception("ProcLikelihood")
675  << "Expected sigbkg tag in train file."
676  << std::endl;
677  elem = static_cast<DOMElement*>(node);
678 
679  SigBkg *pdf = nullptr;
680  switch(version) {
681  case 1:
682  if (cur == pdfs.end())
683  throw cms::Exception("ProcLikelihood")
684  << "Superfluous SigBkg in train data."
685  << std::endl;
686  pdf = &*cur++;
687  break;
688  case 2: {
689  Id id(XMLDocument::readAttribute<std::string>(
690  elem, "source"),
691  XMLDocument::readAttribute<std::string>(
692  elem, "name"),
693  XMLDocument::readAttribute<unsigned int>(
694  elem, "category", 0));
695  std::map<Id, SigBkg*>::const_iterator pos =
696  pdfMap.find(id);
697  if (pos == pdfMap.end())
698  continue;
699  else
700  pdf = pos->second;
701  } break;
702  }
703 
704  for(node = elem->getFirstChild();
705  node && node->getNodeType() != DOMNode::ELEMENT_NODE;
706  node = node->getNextSibling());
707  DOMElement *elemSig =
708  node ? static_cast<DOMElement*>(node) : nullptr;
709 
710  for(node = node->getNextSibling();
711  node && node->getNodeType() != DOMNode::ELEMENT_NODE;
712  node = node->getNextSibling());
713  while(node && node->getNodeType() != DOMNode::ELEMENT_NODE)
714  node = node->getNextSibling();
715  DOMElement *elemBkg =
716  node ? static_cast<DOMElement*>(node) : nullptr;
717 
718  for(node = node->getNextSibling();
719  node && node->getNodeType() != DOMNode::ELEMENT_NODE;
720  node = node->getNextSibling());
721  if (node)
722  throw cms::Exception("ProcLikelihood")
723  << "Superfluous tags in sigbkg train data."
724  << std::endl;
725 
726  xmlParsePDF(pdf->signal, elemSig);
727  xmlParsePDF(pdf->background, elemBkg);
728 
729  pdf->iteration = ITER_DONE;
730 
731  node = elem;
732  }
733 
734  if (version == 1 && cur != pdfs.end())
735  throw cms::Exception("ProcLikelihood")
736  << "Missing SigBkg in train data." << std::endl;
737 
738  iteration = ITER_DONE;
739  trained = true;
740  for(std::vector<SigBkg>::const_iterator iter = pdfs.begin();
741  iter != pdfs.end(); ++iter) {
742  if (iter->iteration != ITER_DONE) {
743  trained = false;
744  break;
745  }
746  }
747 
748  return true;
749 }
750 
751 DOMElement *xmlStorePDF(DOMDocument *doc,
752  const ProcLikelihood::PDF &pdf)
753 {
754  DOMElement *elem = doc->createElement(XMLUniStr("pdf"));
755 
756  XMLDocument::writeAttribute(elem, "lower", pdf.range.min);
757  XMLDocument::writeAttribute(elem, "upper", pdf.range.max);
758 
759  for(std::vector<double>::const_iterator iter =
760  pdf.distr.begin(); iter != pdf.distr.end(); iter++) {
761  DOMElement *value = doc->createElement(XMLUniStr("value"));
762  elem->appendChild(value);
763 
764  XMLDocument::writeContent<double>(value, doc, *iter);
765  }
766 
767  return elem;
768 }
769 
771 {
772  XMLDocument xml(trainer->trainFileName(this, "xml"), true);
773  DOMDocument *doc = xml.createDocument("ProcLikelihood");
774  XMLDocument::writeAttribute(doc->getDocumentElement(), "version", 2);
775 
776  DOMElement *elem = doc->createElement(XMLUniStr("categories"));
777  xml.getRootNode()->appendChild(elem);
778  for(unsigned int i = 0; i < nCategories; i++) {
779  DOMElement *category = doc->createElement(XMLUniStr("category"));
780  elem->appendChild(category);
781  XMLDocument::writeAttribute(category, "signal", sigSum[i]);
782  XMLDocument::writeAttribute(category, "background", bkgSum[i]);
783  }
784 
785  for(std::vector<SigBkg>::const_iterator iter = pdfs.begin();
786  iter != pdfs.end(); iter++) {
787  elem = doc->createElement(XMLUniStr("sigbkg"));
788  xml.getRootNode()->appendChild(elem);
789 
790  unsigned int idx = iter - pdfs.begin();
791  unsigned int catIdx = idx % nCategories;
792  unsigned int varIdx = idx / nCategories;
793  if (categoryIdx >= 0 && (int)varIdx >= categoryIdx)
794  varIdx++;
795  const SourceVariable *var = getInputs().get()[varIdx];
796  XMLDocument::writeAttribute(elem, "source",
797  (const char*)var->getSource()->getName());
798  XMLDocument::writeAttribute(elem, "name",
799  (const char*)var->getName());
800  if (categoryIdx >= 0)
801  XMLDocument::writeAttribute(elem, "category", catIdx);
802 
803  elem->appendChild(xmlStorePDF(doc, iter->signal));
804  elem->appendChild(xmlStorePDF(doc, iter->background));
805  }
806 }
807 
808 } // anonymous namespace
size
Write out results.
dbl * delta
Definition: mlp_gen.cc:36
Histogram< float > HistogramF
Definition: Histogram.h:120
Source * getSource() const
Definition: weight.py:1
template to generate a registry singleton for a type.
Cheap generic unique keyword identifier class.
Definition: AtomicId.h:31
MVATrainerComputer * calib
Definition: MVATrainer.cc:64
static bool hasAttribute(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *elem, const char *name)
Definition: XMLDocument.cc:305
const AtomicId getName() const
Definition: Variable.h:143
bool operator==(const QGLikelihoodParameters &lhs, const QGLikelihoodCategory &rhs)
Test if parameters are compatible with category.
Definition: value.py:1
T min(T a, T b)
Definition: MathUtil.h:58
static void writeAttribute(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *elem, const char *name, const T &value)
def elem(elemtype, innerHTML='', html_class='', kwargs)
Definition: HTMLExport.py:19
def load(fileName)
Definition: svgfig.py:547
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * createDocument(const std::string &root)
Definition: XMLDocument.cc:268
bool operator<(DTCELinkId const &lhs, DTCELinkId const &rhs)
Definition: DTCELinkId.h:73
AtomicId getName() const
Definition: Source.h:19
void setValues(const std::vector< Value_t > &values)
static Interceptor::Registry registry("Interceptor")
static std::string const source
Definition: EdmProvDump.cc:47
save
Definition: cuy.py:1165