Hammer  1.0.0
Helicity Amplitude Module for Matrix Element Reweighting
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Histogram.cc
Go to the documentation of this file.
1 ///
2 /// @file Histogram.cc
3 /// @brief Hammer histogram class
4 ///
5 
6 //**** This file is a part of the HAMMER library
7 //**** Copyright (C) 2016 - 2020 The HAMMER Collaboration
8 //**** HAMMER is licensed under version 3 of the GPL; see COPYING for details
9 //**** Please note the MCnet academic guidelines; see GUIDELINES for details
10 
11 // -*- C++ -*-
12 #include "Hammer/Math/Histogram.hh"
13 #include "Hammer/Exceptions.hh"
16 #include "Hammer/Math/Tensor.hh"
18 
19 using namespace std;
20 
21 namespace Hammer {
22 
23  namespace MD = MultiDimensional;
24 
25  Histogram::Bin::Bin(const Tensor& t, bool withErrors) : _NEvents{0}, _withErrors{withErrors} {
26  _weight = t;
27  _weight.clearData();
28  if(withErrors) {
29  _weight2 = t;
30  _weight2.outerSquare();
31  _weight2.clearData();
32  }
33  else {
34  _weight2 = Tensor{};
35  }
36  }
37 
38  Histogram::Bin::Bin(const Serial::FBTensor* w, const Serial::FBTensor* w2, size_t num) {
39  _weight.read(w);
40  if(w2 != nullptr) {
41  _weight2.read(w2);
42  }
43  else {
44  _weight2 = Tensor{};
45  }
46  _NEvents = num;
47  }
48 
50  _weight = Tensor{};
51  _weight2 = Tensor{};
52  _NEvents = 0;
53  }
54 
56  _weight += t;
57  ++_NEvents;
58  if(_withErrors) {
59  _weight2 += outerSquare(t);
60  }
61  }
62 
64  return _weight;
65  }
66 
68  return _weight2;
69  }
70 
72  return _NEvents;
73  }
74 
76  if(other._NEvents != 0) {
77  if(_NEvents == 0) {
78  _weight = other._weight;
79  if(other._weight2.rank() > 0) {
80  _weight2 = other._weight2;
81  }
82  _NEvents = other._NEvents;
83  }
84  else {
85  _weight += other._weight;
86  if(_weight2.rank() > 0 && other._weight2.rank() > 0) {
87  _weight2 += other._weight2;
88  }
89  _NEvents += other._NEvents;
90  }
91  }
92  return (*this);
93  }
94 
95  Histogram::Histogram() : _definition{nullptr}, _data{},
96  _name{"Histogram"}, _defaultTensorName{"Bin"}, _initialized{false} {
97  }
98 
100  clear();
101  }
102 
103  void Histogram::setName(const string& name) {
104  _name = name;
105  }
106 
108  _definition = &def;
109  }
110 
112  return _data.begin();
113  }
114 
116  return _data.begin();
117  }
118 
120  return _data.end();
121  }
122 
124  return _data.end();
125  }
126 
128  return _data[pos];
129  }
130 
132  return _data[pos];
133  }
134 
135  size_t Histogram::numValues() const {
136  return _definition->getIndexing().numValues();
137  }
138 
139  size_t Histogram::rank() const {
140  return _definition->getIndexing().rank();
141  }
142 
144  return _definition->getIndexing().dim(index);
145  }
146 
147  const IndexList& Histogram::dims() const {
148  return _definition->getIndexing().dims();
149  }
150 
151  const string& Histogram::name() const {
152  return _name;
153  }
154 
155  void Histogram::setDefaultValue(const Tensor& value) {
156  if(value.rank() > 0) {
158  }
159  _defaultTensorName = value.name();
160  _initialized = false;
161  }
162 
163  void Histogram::setDefaultValue(const IndexList& defaultDims, const LabelsList& defaultLabels) {
164  if(defaultDims.size() > 0) {
166  _defaultTensorName = "";
167  }
168  _initialized = false;
169  }
170 
172  _data.clear();
173  _definition = nullptr;
174  _name = "";
175  }
176 
178  return Log::getLog("Hammer.Histogram");
179  }
180 
181  void Histogram::fillBin(const Tensor& value, const IndexList& position) {
182  try {
183  element(position).addWeight(value);
184  } catch (RangeError& e) {
185  MSG_ERROR(string("Error setting element: ") + e.what() + string(" Element not set."));
186  }
187  }
188 
190  if (indices.size() < _definition->getIndexing().rank()) {
191  throw RangeError("Not enough indices (" + to_string(indices.size()) + ") for tensor '" + _name +
192  "' of rank " + to_string(_definition->getIndexing().rank()) +
193  ": all your base are belong to us.");
194  } else {
195  return _data[_definition->getIndexing().indicesToPos(indices)];
196  }
197  }
198 
199  const Histogram::Bin& Histogram::element(const IndexList& indices) const {
200  if (indices.size() < _definition->getIndexing().rank()) {
201  throw RangeError("Not enough indices (" + to_string(indices.size()) + ") for tensor '" + _name +
202  "' of rank " + to_string(_definition->getIndexing().rank()) +
203  ": all your base are belong to us.");
204  } else {
205  return _data[_definition->getIndexing().indicesToPos(indices)];
206  }
207  }
208 
210  if(!_initialized) {
211  clearData();
212  _initialized = true;
213  }
214  }
215 
218  if(_defaultTensorIndexing.rank() > 0) {
220  }
221  vector<Bin> newvec(numValues(), Bin(r, _definition->shouldKeepErrors()));
222  _data.swap(newvec);
223  }
224 
225  unique_ptr<Serial::FBHistogramBuilder> Histogram::write(flatbuffers::FlatBufferBuilder* msgwriter) const {
226  vector<flatbuffers::Offset<Serial::FBTensor>> weightbins;
227  vector<flatbuffers::Offset<Serial::FBTensor>> weightbins2;
228  vector<uint16_t> poslist;
229  vector<uint64_t> nEvs;
230  weightbins.reserve(_data.size());
231  nEvs.reserve(_data.size());
232  poslist.reserve(_data.size());
233  if (_data.size() > 65535ul) {
234  MSG_ERROR("Error saving binary histogram: too many entries!");
235  }
237  weightbins2.reserve(_data.size());
238  }
239  for (size_t i = 0; i< _data.size(); ++i) {
240  if(_data[i].getNumEvents() > 0) {
242  _data[i].getWeight().write(msgwriter, &val);
243  weightbins.push_back(val);
244  nEvs.push_back(_data[i].getNumEvents());
245  poslist.push_back(static_cast<uint16_t>(i));
248  _data[i].getSquaredWeight().write(msgwriter, &val2);
249  weightbins2.push_back(val2);
250  }
251  }
252  }
253  auto serialW = msgwriter->CreateVector(weightbins);
254  auto serialW2 = msgwriter->CreateVector(weightbins2);
255  auto serialPos = msgwriter->CreateVector(poslist);
256  auto serialNEvs = msgwriter->CreateVector(nEvs);
257  auto name = msgwriter->CreateString(_name);
258 
259  unique_ptr<Serial::FBHistogramBuilder> serialHisto{new Serial::FBHistogramBuilder{*msgwriter}};
260  serialHisto->add_w(serialW);
261  serialHisto->add_w2(serialW2);
262  serialHisto->add_n(serialNEvs);
263  serialHisto->add_pos(serialPos);
264  serialHisto->add_name(name);
265  return serialHisto;
266  }
267 
268 
269  void Histogram::read(const Serial::FBHistogram* msgreader, const HistogramDefinition& def) {
270  _definition = &def;
271  if (msgreader != nullptr) {
272  auto w = msgreader->w();
273  auto w2 = msgreader->w2();
274  auto num = msgreader->n();
275  auto pos = msgreader->pos();
276  // bool keepErrors = (w2->size() > 0);
277  bool keepErrors = _definition->shouldKeepErrors();
278  _name = msgreader->name()->c_str();
279  _data.clear();
280  size_t fullSize = _definition->getIndexing().numValues();
281  _data.reserve(fullSize);
282  size_t currentIndex = 0ul;
283  bool firstread = true;
284  Tensor empty;
285  for (unsigned int i = 0; i < w->size(); ++i) {
286  auto elemW = w->Get(i);
287  auto elemN = num->Get(i);
288  auto elemPos = pos->Get(i);
289  const Serial::FBTensor* elemW2 = nullptr;
290  if(keepErrors) {
291  elemW2 = w2->Get(i);
292  }
293  Bin bin(elemW,elemW2,elemN);
294  if(firstread) {
296  LabelsList defaultLabels = bin.getWeight().labels();
297  IndexList defaultDimensions = bin.getWeight().dims();
298  if(defaultDimensions.size() > 0) {
299  _defaultTensorIndexing = MD::LabeledIndexing<MD::AlignedIndexing>{defaultDimensions, defaultLabels};
301  }
302  else {
304  }
305  firstread = false;
306  }
307  if(elemPos > currentIndex) {
308  _data.insert(_data.end(), elemPos-currentIndex, Bin(empty, keepErrors));
309  currentIndex = elemPos;
310  }
311  _data.push_back(bin);
312  ++currentIndex;
313  }
314  size_t currentSize = _data.size();
315  _data.insert(_data.end(), fullSize - currentSize, Bin(empty, keepErrors));
316  }
317  }
318 
321  for (size_t i = 0; i < _data.size(); ++i) {
322  _data[i] += other._data[i];
323  }
324  return (*this);
325  }
326  throw Error("Histogram dimension/sizes/binning do not match");
327  }
328 
331  }
332 
333  IOHistogram Histogram::evalToList(const Tensor& externalData) const {
334  IOHistogram results;
335  // map<size_t, size_t> necessary; //Deals with events weights containing multiple tensors with same indices,
336  // auto labsd = _defaultTensorIndexing.labels();
337  // multiset<IndexLabel> defaultTensorLabels(labsd.begin(), labsd.end());
338  // for(size_t i=0; i< externalData.size(); ++i) {
339  // auto labsi = externalData[i].labels();
340  // set<IndexLabel> externalDataLabels(labsi.begin(), labsi.end());
341  // if(includes(defaultTensorLabels.begin(),defaultTensorLabels.end(),
342  // externalDataLabels.begin(), externalDataLabels.end())) {
343  // size_t n = static_cast<size_t>(count(defaultTensorLabels.begin(), defaultTensorLabels.end(), *externalDataLabels.begin()));
344  // necessary.insert(make_pair(i,n));
345  // }
346  // }
347  for(auto& elem: _data) {
348  size_t num = elem.getNumEvents();
349  double wVal = 0.;
350  double w2Val = 0.;
351  if (num > 0) {
352  Tensor w = elem.getWeight();
353  w.dot(externalData);
354  if(w.rank() != 0) {
355  MSG_ERROR("Invalid rank, " + to_string(w.rank()) + ", at end of evaluation.");
356  }
357  wVal = w.element().real();
359  Tensor w2 = elem.getSquaredWeight();
360  auto externalData2 = outerSquare(externalData);
361  w2.dot(externalData2);
362  // w2.dot(externalData).dot(externalData);
363  if(w2.rank() != 0) {
364  MSG_ERROR("Invalid rank at end of evaluation");
365  }
366  w2Val = w2.element().real();
367  }
368  }
369  results.push_back(BinContents{wVal, w2Val, num});
370  }
371  return results;
372  }
373 
374 
375  unique_ptr<Histogram> Histogram::collapseIntoNew(const string& newName, const HistogramDefinition& newDef, const set<uint16_t>& collapsedIndexPositions) const {
376  auto strides = _definition->getIndexing().getBinStrides(collapsedIndexPositions);
377  unique_ptr<Histogram> result{new Histogram{}};
378  result->_definition = &newDef;
379  result->_defaultTensorIndexing = _defaultTensorIndexing;
380  result->_defaultTensorName = _defaultTensorName;
381  result->_name = newName;
382  result->initHistogram();
383  for (size_t i = 0; i < _data.size(); ++i) {
384  if(_data[i].getNumEvents() == 0) {
385  continue;
386  }
387  auto pospairs = _definition->getIndexing().splitPosition(i, strides);
388  (result->_data)[pospairs.first] += _data[i];
389  }
390  return result;
391  }
392 
393  unique_ptr<Histogram> makeHistogram(const string& name, const HistogramDefinition& def, const Tensor& defaultValue) {
394  unique_ptr<Histogram> res(new Histogram{});
395  res->setName(name);
396  res->setDefinition(def);
397  res->setDefaultValue(defaultValue);
398  res->initHistogram();
399  return res;
400  }
401 
402  unique_ptr<Histogram> makeHistogram(const string& name, const HistogramDefinition& def,
403  const IndexList& defaultTensorDims, const LabelsList& defaultTensorLabels) {
404  unique_ptr<Histogram> res(new Histogram{});
405  res->setName(name);
406  res->setDefinition(def);
407  res->setDefaultValue(defaultTensorDims, defaultTensorLabels);
408  res->initHistogram();
409  return res;
410  }
411 
412  Histogram operator+(const Histogram& first, const Histogram& second) {
413  Histogram result(first);
414  result += second;
415  return result;
416  }
417 
418 } // namespace Hammer
void initHistogram()
allocate and initialize the histogram
Definition: Histogram.cc:209
const std::string & name() const
get the histogram name
Definition: Histogram.cc:151
void setDefinition(const HistogramDefinition &def)
set the dimensions of the various coordinates
Definition: Histogram.cc:107
Tensor _weight
tensor sum of weights
Definition: Histogram.hh:93
BasicIndexing::StrideMap getBinStrides(const UniqueIndexList &positions) const
TensorData makeEmptySparse(const IndexList &dimensions, const LabelsList &labels)
std::complex< double > & element(const IndexList &indices={})
access an element given its indices
Definition: Tensor.cc:67
const IndexList & dims() const
get the dimensions of all the coordinates at once
Definition: Histogram.cc:147
const MD::BinnedIndexing< MD::SequentialIndexing > & getIndexing() const
Bin class with Tensor contents.
Definition: Histogram.hh:47
reference operator[](PositionType pos)
Definition: Histogram.cc:127
Multidimensional histogram class with Tensor as cell bins.
Definition: Histogram.hh:39
LabelsList labels() const
get the labels of all the indices at once
Definition: Tensor.cc:83
const std::string & name() const
get the tensor name
Definition: Tensor.cc:102
Tensor outerSquare(const Tensor &first)
creates a tensor with twice the rank by multiplying the tensor with it&#39;s hermitean conjugate ...
Definition: Tensor.cc:316
size_t getNumEvents(Args...rest) const
get the value of a histogram bin based on an index of the bin
void clear()
reset the histogram
Definition: Histogram.cc:171
size_t PositionType
void setDefaultValue(const Tensor &value)
set the value to be used for out-of-bounds coordinates if extrapolation is off
Definition: Histogram.cc:155
iterator begin()
Definition: Histogram.cc:111
std::string _name
Definition: Histogram.hh:270
const IndexList & dims() const
get the dimensions of all the indices at once
std::vector< BinContents > IOHistogram
Definition: IOTypes.hh:132
size_t getNumEvents() const
the number of entries in the bin (number of times addWeight has been called)
Definition: Histogram.cc:71
IOHistogram evalToList(const Tensor &externalData) const
Definition: Histogram.cc:333
bool isSameBinShape(const BinEdgeList &otherEdges, const IndexList &otherIndices, bool otherUnderOverFlow) const
void clear()
clears the contents of the bin (including the shapes of the tensors)
Definition: Histogram.cc:49
uint16_t IndexType
PositionPair splitPosition(PositionType position, const StrideMap &conversion) const
const LabelsList & labels() const
get the labels of all the indices at once
Histogram & operator+=(const Histogram &other)
Definition: Histogram.cc:319
PositionType indicesToPos(const IndexList &indices) const
convert the indices into the position indicizing a sparse tensor container organized as row-major ...
unique_ptr< Histogram > makeHistogram(const string &name, const HistogramDefinition &def, const Tensor &defaultValue)
Definition: Histogram.cc:393
size_t rank() const
rank of the tensor
Definition: Tensor.cc:75
static Log & getLog(const std::string &name)
Get a logger with the given name.
Definition: Logging.cc:139
const Tensor & getWeight() const
the sum of tensor weights contained in the bin
Definition: Histogram.cc:63
size_t rank() const
rank of the tensor
Bin(const Tensor &t, bool withErrors=false)
constructor based on a tensor (for determining shape and labels)
Definition: Histogram.cc:25
void addWeight(const Tensor &t)
add the values of a tensor to the current bin.
Definition: Histogram.cc:55
Hammer exception definitions.
size_t rank() const
rank of the tensor
Hammer histogram class.
std::unique_ptr< Histogram > collapseIntoNew(const std::string &newName, const HistogramDefinition &newDef, const std::set< uint16_t > &collapsedIndexPositions) const
Definition: Histogram.cc:375
Sparse tensor data container.
std::vector< IndexType > IndexList
std::unique_ptr< Serial::FBHistogramBuilder > write(flatbuffers::FlatBufferBuilder *msgwriter) const
write the contents of the histogram for serialization
Definition: Histogram.cc:225
Order-0 tensor data container.
Logging class.
Definition: Logging.hh:33
IndexType dim(IndexType index) const
dimension of a specific coordinate
Definition: Histogram.cc:143
Bin & element(const IndexList &indices)
convert the indices into the position in the flattened contents into vector organized as row-major ...
Definition: Histogram.cc:189
const Tensor & getSquaredWeight() const
the sum of (outer) squared tensor weights contained in the bin, or an empty tensor if the errors are ...
Definition: Histogram.cc:67
Multidimensional tensor class with complex numbers as elements.
Definition: Tensor.hh:33
Generic error class.
Definition: Exceptions.hh:23
contents of a histogram bin after full contraction (real weights) to be used to export the histogram ...
Definition: IOTypes.hh:126
size_t numValues() const
the number of elements (product of all the dimensions)
Definition: Histogram.cc:135
IndexType dim(IndexType index) const
dimension of a specific component
PositionType numValues() const
the number of elements (product of all the dimensions)
Histogram()
constructor
Definition: Histogram.cc:95
DataType::iterator iterator
Definition: Histogram.hh:125
Bin & operator+=(const Bin &other)
Definition: Histogram.cc:75
size_t _NEvents
number of entries
Definition: Histogram.hh:95
MultiDimensional::LabeledIndexing< MultiDimensional::AlignedIndexing > _defaultTensorIndexing
Definition: Histogram.hh:272
std::vector< IndexLabel > LabelsList
void clearData()
reset the histogram contents but not the shape of the histogram
Definition: Histogram.cc:216
Tensor _weight2
tensor sum of squared weights (in the outer square sense)
Definition: Histogram.hh:94
std::string _defaultTensorName
Definition: Histogram.hh:273
void read(const Serial::FBHistogram *msgreader, const HistogramDefinition &def)
read the contents of the histogram for serialization
Definition: Histogram.cc:269
Tensor & dot(const Tensor &other, const UniqueLabelsList &indices={})
contract this tensor with another and stores the result in this tensor
Definition: Tensor.cc:114
#define MSG_ERROR(x)
Definition: Logging.hh:367
IndexList dims() const
get the dimensions of all the indices at once
Definition: Tensor.cc:79
void fillBin(const Tensor &value, Args...rest)
set the value of a histogram bin based on the bin indices
DataType::const_iterator const_iterator
Definition: Histogram.hh:126
const HistogramDefinition * _definition
Definition: Histogram.hh:267
Log & getLog() const
logging facility
Definition: Histogram.cc:177
iterator end()
Definition: Histogram.cc:119
Out-of-range error class.
Definition: Exceptions.hh:49
size_t rank() const
dimensionality of the histograms
Definition: Histogram.cc:139
Histogram operator+(const Histogram &first, const Histogram &second)
Definition: Histogram.cc:412
Hammer tensor class.
Serialization related typedefs and includes.
const LabelsList & getLabelVector() const
Definition: Histogram.cc:329
bool _initialized
whether the grid is initialized
Definition: Histogram.hh:276
virtual ~Histogram()
destructor
Definition: Histogram.cc:99
void setName(const std::string &name)
give the histogram a name
Definition: Histogram.cc:103