Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
Histograms.cc
Go to the documentation of this file.
1
9#include "Helpers/XmlHelper.h"
10
11#include "Objects/Histograms.h"
12
13#include "Pandora/StatusCodes.h"
14
15#include "Xml/tinyxml.h"
16
17#include <cmath>
18#include <limits>
19
20namespace pandora
21{
22
23Histogram::Histogram(const unsigned int nBinsX, const float xLow, const float xHigh) :
24 m_nBinsX(nBinsX),
25 m_xLow(xLow),
26 m_xHigh(xHigh)
27{
28 if ((0 >= nBinsX) || (xHigh - xLow < std::numeric_limits<float>::epsilon()))
29 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
30
31 m_xBinWidth = (xHigh - xLow) / static_cast<float>(nBinsX);
32
33 // ATTN Protect against cast to int wrapping to negative numbers if there are very many bins
34 if (static_cast<int>((m_xHigh - m_xLow) / m_xBinWidth) < 0)
35 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
36}
37
38//------------------------------------------------------------------------------------------------------------------------------------------
39
40Histogram::Histogram(const TiXmlHandle *const pXmlHandle, const std::string &xmlElementName) :
41 m_nBinsX(0),
42 m_xLow(0.f),
43 m_xHigh(0.f)
44{
45 TiXmlElement *const pXmlElement(pXmlHandle->FirstChild(xmlElementName).Element());
46
47 if (!pXmlElement)
48 {
49 std::cout << "Construct Histogram from xml: cannot find xml element with name " << xmlElementName << std::endl;
50 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
51 }
52
53 const TiXmlHandle xmlHandle(pXmlElement);
54 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "NBinsX", m_nBinsX));
55 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "XLow", m_xLow));
56 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "XHigh", m_xHigh));
57
58 if ((0 >= m_nBinsX) || (m_xHigh - m_xLow < std::numeric_limits<float>::epsilon()))
59 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
60
61 m_xBinWidth = (m_xHigh - m_xLow) / static_cast<float>(m_nBinsX);
62
63 FloatVector orderedBinContents;
64 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "BinContents", orderedBinContents));
65
66 if (orderedBinContents.size() != static_cast<unsigned int>(m_nBinsX) + 2)
67 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
68
69 for (int binX = this->GetUnderflowBinNumber(), endBinX = this->GetOverflowBinNumber(); binX <= endBinX; ++binX)
70 {
71 const float value(orderedBinContents[binX + 1]);
72
73 if (std::fabs(value) > std::numeric_limits<float>::epsilon())
74 m_histogramMap[binX] = value;
75 }
76}
77
78//------------------------------------------------------------------------------------------------------------------------------------------
79
81 m_histogramMap(rhs.m_histogramMap),
82 m_nBinsX(rhs.m_nBinsX),
83 m_xLow(rhs.m_xLow),
84 m_xHigh(rhs.m_xHigh),
85 m_xBinWidth(rhs.m_xBinWidth)
86{
87}
88
89//------------------------------------------------------------------------------------------------------------------------------------------
90
91float Histogram::GetBinContent(const int binX) const
92{
93 HistogramMap::const_iterator iter = m_histogramMap.find(binX);
94
95 if (m_histogramMap.end() == iter)
96 return 0.f;
97
98 return iter->second;
99}
100
101//------------------------------------------------------------------------------------------------------------------------------------------
102
103int Histogram::GetBinNumber(const float valueX) const
104{
105 if (m_xHigh < valueX)
106 {
107 return this->GetOverflowBinNumber();
108 }
109 else if (m_xLow > valueX)
110 {
111 return this->GetUnderflowBinNumber();
112 }
113 else
114 {
115 return static_cast<int>((valueX - m_xLow) / m_xBinWidth);
116 }
117}
118
119//------------------------------------------------------------------------------------------------------------------------------------------
120
121float Histogram::GetCumulativeSum(const int xLowBin, const int xHighBin) const
122{
123 float sumEntries(0.f);
124
125 for (int xBin = std::max(this->GetUnderflowBinNumber(), xLowBin), xBinEnd = std::min(xHighBin, this->GetOverflowBinNumber()); xBin <= xBinEnd; ++xBin)
126 {
127 HistogramMap::const_iterator iterX = m_histogramMap.find(xBin);
128
129 if (m_histogramMap.end() == iterX)
130 continue;
131
132 sumEntries += iterX->second;
133 }
134
135 return sumEntries;
136}
137
138//------------------------------------------------------------------------------------------------------------------------------------------
139
140void Histogram::GetMaximum(const int xLowBin, const int xHighBin, float &maximumValue, int &maximumBinX) const
141{
142 maximumValue = 0.f;
143 maximumBinX = this->GetUnderflowBinNumber();
144
145 for (int xBin = std::max(this->GetUnderflowBinNumber(), xLowBin), xBinEnd = std::min(xHighBin, this->GetOverflowBinNumber()); xBin <= xBinEnd; ++xBin)
146 {
147 HistogramMap::const_iterator iterX = m_histogramMap.find(xBin);
148
149 if (m_histogramMap.end() == iterX)
150 continue;
151
152 const float binContents(iterX->second);
153
154 if (binContents > maximumValue)
155 {
156 maximumValue = binContents;
157 maximumBinX = iterX->first;
158 }
159 }
160}
161
162//------------------------------------------------------------------------------------------------------------------------------------------
163
164float Histogram::GetMeanX(const int xLowBin, const int xHighBin) const
165{
166 float sumEntries(0.f), sumXEntries(0.f);
167 const float firstBinCenter(m_xLow + (0.5f * m_xBinWidth));
168
169 for (int xBin = std::max(this->GetMinBinNumber(), xLowBin), xBinEnd = std::min(xHighBin, this->GetMaxBinNumber()); xBin <= xBinEnd; ++xBin)
170 {
171 HistogramMap::const_iterator iterX = m_histogramMap.find(xBin);
172
173 if (m_histogramMap.end() == iterX)
174 continue;
175
176 const float binCenter(firstBinCenter + (m_xBinWidth * static_cast<float>(iterX->first)));
177 const float binContents(iterX->second);
178
179 sumEntries += binContents;
180 sumXEntries += binContents * binCenter;
181 }
182
183 if (std::fabs(sumEntries) < std::numeric_limits<float>::epsilon())
184 return 0.f;
185
186 return (sumXEntries / sumEntries);
187}
188
189//------------------------------------------------------------------------------------------------------------------------------------------
190
191float Histogram::GetStandardDeviationX(const int xLowBin, const int xHighBin) const
192{
193 float sumEntries(0.f), sumXEntries(0.f), sumXXEntries(0.f);
194 const float firstBinCenter(m_xLow + (0.5f * m_xBinWidth));
195
196 for (int xBin = std::max(this->GetMinBinNumber(), xLowBin), xBinEnd = std::min(xHighBin, this->GetMaxBinNumber()); xBin <= xBinEnd; ++xBin)
197 {
198 HistogramMap::const_iterator iterX = m_histogramMap.find(xBin);
199
200 if (m_histogramMap.end() == iterX)
201 continue;
202
203 const float binCenter(firstBinCenter + (m_xBinWidth * static_cast<float>(iterX->first)));
204 const float binContents(iterX->second);
205
206 sumEntries += binContents;
207 sumXEntries += binContents * binCenter;
208 sumXXEntries += binContents * binCenter * binCenter;
209 }
210
211 if (std::fabs(sumEntries) < std::numeric_limits<float>::epsilon())
212 return 0.f;
213
214 const float meanX(sumXEntries / sumEntries);
215 const float meanXX(sumXXEntries / sumEntries);
216
217 return std::sqrt(meanXX - (meanX * meanX));
218}
219
220//------------------------------------------------------------------------------------------------------------------------------------------
221
222void Histogram::SetBinContent(const int binX, const float value)
223{
224 if ((binX < this->GetUnderflowBinNumber()) || (binX > this->GetOverflowBinNumber()))
225 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
226
227 m_histogramMap[binX] = value;
228}
229
230//------------------------------------------------------------------------------------------------------------------------------------------
231
232void Histogram::Fill(const float valueX, const float weight)
233{
234 const int binX(this->GetBinNumber(valueX));
235
236 HistogramMap::iterator iter = m_histogramMap.find(binX);
237
238 if (m_histogramMap.end() != iter)
239 {
240 iter->second += weight;
241 }
242 else
243 {
244 if (!m_histogramMap.insert(HistogramMap::value_type(binX, weight)).second)
245 throw StatusCodeException(STATUS_CODE_FAILURE);
246 }
247}
248
249//------------------------------------------------------------------------------------------------------------------------------------------
250
251void Histogram::Scale(const float scaleFactor)
252{
253 for (HistogramMap::value_type &mapEntry : m_histogramMap)
254 {
255 mapEntry.second = (mapEntry.second * scaleFactor);
256 }
257}
258
259//------------------------------------------------------------------------------------------------------------------------------------------
260
261void Histogram::WriteToXml(TiXmlDocument *const pTiXmlDocument, const std::string &histogramXmlKey) const
262{
263 TiXmlElement *const pHistogramElement = new TiXmlElement(histogramXmlKey);
264
265 TiXmlElement *const pNBinsXElement = new TiXmlElement("NBinsX");
266 pNBinsXElement->LinkEndChild(new TiXmlText(TypeToString(m_nBinsX)));
267 pHistogramElement->LinkEndChild(pNBinsXElement);
268
269 TiXmlElement *const pXLowElement = new TiXmlElement("XLow");
270 pXLowElement->LinkEndChild(new TiXmlText(TypeToString(m_xLow)));
271 pHistogramElement->LinkEndChild(pXLowElement);
272
273 TiXmlElement *const pXHighElement = new TiXmlElement("XHigh");
274 pXHighElement->LinkEndChild(new TiXmlText(TypeToString(m_xHigh)));
275 pHistogramElement->LinkEndChild(pXHighElement);
276
277 std::string binContentsString;
278 for (int binX = this->GetUnderflowBinNumber(), endBinX = this->GetOverflowBinNumber(); binX <= endBinX; ++binX)
279 {
280 binContentsString += TypeToString(this->GetBinContent(binX)) + " ";
281 }
282
283 TiXmlElement *const pBinContentsElement = new TiXmlElement("BinContents");
284 pBinContentsElement->LinkEndChild(new TiXmlText(binContentsString));
285 pHistogramElement->LinkEndChild(pBinContentsElement);
286
287 pTiXmlDocument->LinkEndChild(pHistogramElement);
288}
289
290//------------------------------------------------------------------------------------------------------------------------------------------
291//------------------------------------------------------------------------------------------------------------------------------------------
292
293TwoDHistogram::TwoDHistogram(const unsigned int nBinsX, const float xLow, const float xHigh, const unsigned int nBinsY, const float yLow,
294 const float yHigh) :
295 m_nBinsX(nBinsX),
296 m_xLow(xLow),
297 m_xHigh(xHigh),
298 m_nBinsY(nBinsY),
299 m_yLow(yLow),
300 m_yHigh(yHigh)
301{
302 if ((0 >= nBinsX) || (xHigh - xLow < std::numeric_limits<float>::epsilon()) || (0 >= nBinsY) || (yHigh - yLow < std::numeric_limits<float>::epsilon()))
303 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
304
305 m_xBinWidth = (xHigh - xLow) / static_cast<float>(nBinsX);
306 m_yBinWidth = (yHigh - yLow) / static_cast<float>(nBinsY);
307
308 // ATTN Protect against cast to int wrapping to negative numbers if there are very many bins
309 if ((static_cast<int>((m_xHigh - m_xLow) / m_xBinWidth) < 0) || (static_cast<int>((m_yHigh - m_yLow) / m_yBinWidth) < 0))
310 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
311}
312
313//------------------------------------------------------------------------------------------------------------------------------------------
314
315TwoDHistogram::TwoDHistogram(const TiXmlHandle *const pXmlHandle, const std::string &xmlElementName) :
316 m_nBinsX(0),
317 m_xLow(0.f),
318 m_xHigh(0.f),
319 m_nBinsY(0),
320 m_yLow(0.f),
321 m_yHigh(0.f)
322{
323 TiXmlElement *const pXmlElement(pXmlHandle->FirstChild(xmlElementName).Element());
324
325 if (!pXmlElement)
326 {
327 std::cout << "Construct Histogram from xml: cannot find xml element with name " << xmlElementName << std::endl;
328 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
329 }
330
331 const TiXmlHandle xmlHandle(pXmlElement);
332 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "NBinsX", m_nBinsX));
333 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "XLow", m_xLow));
334 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "XHigh", m_xHigh));
335
336 if ((0 >= m_nBinsX) || (m_xHigh - m_xLow < std::numeric_limits<float>::epsilon()))
337 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
338
339 m_xBinWidth = (m_xHigh - m_xLow) / static_cast<float>(m_nBinsX);
340
341 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "NBinsY", m_nBinsY));
342 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "YLow", m_yLow));
343 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "YHigh", m_yHigh));
344
345 if ((0 >= m_nBinsY) || (m_yHigh - m_yLow < std::numeric_limits<float>::epsilon()))
346 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
347
348 m_yBinWidth = (m_yHigh - m_yLow) / static_cast<float>(m_nBinsY);
349
350 typedef std::vector<FloatVector> HistogramEntryList;
351 HistogramEntryList histogramEntryList;
352 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::Read2DVectorOfValues(xmlHandle, "BinContents", "Row", histogramEntryList));
353
354 if (histogramEntryList.size() != static_cast<unsigned int>(m_nBinsY) + 2)
355 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
356
357 for (int binY = this->GetUnderflowBinNumberY(), endBinY = this->GetOverflowBinNumberY(); binY <= endBinY; ++binY)
358 {
359 const FloatVector &orderedBinContents(histogramEntryList[binY + 1]);
360
361 if (orderedBinContents.size() != static_cast<unsigned int>(m_nBinsX) + 2)
362 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
363
364 for (int binX = this->GetUnderflowBinNumberX(), endBinX = this->GetOverflowBinNumberX(); binX <= endBinX; ++binX)
365 {
366 const float value(orderedBinContents[binX + 1]);
367 if (std::fabs(value) > std::numeric_limits<float>::epsilon())
368 {
369 m_yxHistogramMap[binY][binX] = value;
370 m_xyHistogramMap[binX][binY] = value;
371 }
372 }
373 }
374}
375
376//------------------------------------------------------------------------------------------------------------------------------------------
377
379 m_xyHistogramMap(rhs.m_xyHistogramMap),
380 m_yxHistogramMap(rhs.m_yxHistogramMap),
381 m_nBinsX(rhs.m_nBinsX),
382 m_xLow(rhs.m_xLow),
383 m_xHigh(rhs.m_xHigh),
384 m_xBinWidth(rhs.m_xBinWidth),
385 m_nBinsY(rhs.m_nBinsY),
386 m_yLow(rhs.m_yLow),
387 m_yHigh(rhs.m_yHigh),
388 m_yBinWidth(rhs.m_yBinWidth)
389{
390}
391
392//------------------------------------------------------------------------------------------------------------------------------------------
393
394float TwoDHistogram::GetBinContent(const int binX, const int binY) const
395{
396 TwoDHistogramMap::const_iterator iterX = m_xyHistogramMap.find(binX);
397
398 if (m_xyHistogramMap.end() == iterX)
399 return 0.f;
400
401 HistogramMap::const_iterator iterXY = iterX->second.find(binY);
402
403 if (iterX->second.end() == iterXY)
404 return 0.f;
405
406 return iterXY->second;
407}
408//------------------------------------------------------------------------------------------------------------------------------------------
409
410int TwoDHistogram::GetBinNumberX(const float valueX) const
411{
412 if (m_xHigh < valueX)
413 {
414 return this->GetOverflowBinNumberX();
415 }
416 else if (m_xLow > valueX)
417 {
418 return this->GetUnderflowBinNumberX();
419 }
420 else
421 {
422 return static_cast<int>((valueX - m_xLow) / m_xBinWidth);
423 }
424}
425//------------------------------------------------------------------------------------------------------------------------------------------
426
427int TwoDHistogram::GetBinNumberY(const float valueY) const
428{
429 if (m_yHigh < valueY)
430 {
431 return this->GetOverflowBinNumberY();
432 }
433 else if (m_yLow > valueY)
434 {
435 return this->GetUnderflowBinNumberY();
436 }
437 else
438 {
439 return static_cast<int>((valueY - m_yLow) / m_yBinWidth);
440 }
441}
442
443//------------------------------------------------------------------------------------------------------------------------------------------
444
445float TwoDHistogram::GetCumulativeSum(const int xLowBin, const int xHighBin, const int yLowBin, const int yHighBin) const
446{
447 float sumEntries(0.f);
448
449 for (int yBin = std::max(this->GetUnderflowBinNumberY(), yLowBin), yBinEnd = std::min(yHighBin, this->GetOverflowBinNumberY()); yBin <= yBinEnd; ++yBin)
450 {
451 TwoDHistogramMap::const_iterator iterY = m_yxHistogramMap.find(yBin);
452
453 if (m_yxHistogramMap.end() == iterY)
454 continue;
455
456 for (int xBin = std::max(this->GetUnderflowBinNumberX(), xLowBin), xBinEnd = std::min(xHighBin, this->GetOverflowBinNumberX()); xBin <= xBinEnd; ++xBin)
457 {
458 HistogramMap::const_iterator iterX = iterY->second.find(xBin);
459
460 if (iterY->second.end() == iterX)
461 continue;
462
463 sumEntries += iterX->second;
464 }
465 }
466
467 return sumEntries;
468}
469
470//------------------------------------------------------------------------------------------------------------------------------------------
471
472void TwoDHistogram::GetMaximum(const int xLowBin, const int xHighBin, const int yLowBin, const int yHighBin, float &maximumValue,
473 int &maximumBinX, int &maximumBinY) const
474{
475 maximumValue = 0.f;
476 maximumBinX = this->GetUnderflowBinNumberX(); maximumBinY = this->GetUnderflowBinNumberY();
477
478 for (int yBin = std::max(this->GetUnderflowBinNumberY(), yLowBin), yBinEnd = std::min(yHighBin, this->GetOverflowBinNumberY()); yBin <= yBinEnd; ++yBin)
479 {
480 TwoDHistogramMap::const_iterator iterY = m_yxHistogramMap.find(yBin);
481
482 if (m_yxHistogramMap.end() == iterY)
483 continue;
484
485 for (int xBin = std::max(this->GetUnderflowBinNumberX(), xLowBin), xBinEnd = std::min(xHighBin, this->GetOverflowBinNumberX()); xBin <= xBinEnd; ++xBin)
486 {
487 HistogramMap::const_iterator iterX = iterY->second.find(xBin);
488
489 if (iterY->second.end() == iterX)
490 continue;
491
492 const float binContents(iterX->second);
493
494 if (binContents > maximumValue)
495 {
496 maximumValue = binContents;
497 maximumBinX = iterX->first;
498 maximumBinY = iterY->first;
499 }
500 }
501 }
502}
503
504//------------------------------------------------------------------------------------------------------------------------------------------
505
506float TwoDHistogram::GetMeanX(const int xLowBin, const int xHighBin, const int yLowBin, const int yHighBin) const
507{
508 float sumEntries(0.f), sumXEntries(0.f);
509 const float firstBinXCenter(m_xLow + (0.5f * m_xBinWidth));
510
511 for (int yBin = std::max(this->GetMinBinNumberY(), yLowBin), yBinEnd = std::min(yHighBin, this->GetMaxBinNumberY()); yBin <= yBinEnd; ++yBin)
512 {
513 TwoDHistogramMap::const_iterator iterY = m_yxHistogramMap.find(yBin);
514
515 if (m_yxHistogramMap.end() == iterY)
516 continue;
517
518 for (int xBin = std::max(this->GetMinBinNumberX(), xLowBin), xBinEnd = std::min(xHighBin, this->GetMaxBinNumberX()); xBin <= xBinEnd; ++xBin)
519 {
520 HistogramMap::const_iterator iterX = iterY->second.find(xBin);
521
522 if (iterY->second.end() == iterX)
523 continue;
524
525 const float binXCenter(firstBinXCenter + (m_xBinWidth * static_cast<float>(iterX->first)));
526 const float binContents(iterX->second);
527
528 sumEntries += binContents;
529 sumXEntries += binContents * binXCenter;
530 }
531 }
532
533 if (std::fabs(sumEntries) < std::numeric_limits<float>::epsilon())
534 return 0.f;
535
536 return (sumXEntries / sumEntries);
537}
538
539//------------------------------------------------------------------------------------------------------------------------------------------
540
541float TwoDHistogram::GetStandardDeviationX(const int xLowBin, const int xHighBin, const int yLowBin, const int yHighBin) const
542{
543 float sumEntries(0.f), sumXEntries(0.f), sumXXEntries(0.f);
544 const float firstBinXCenter(m_xLow + (0.5f * m_xBinWidth));
545
546 for (int yBin = std::max(this->GetMinBinNumberY(), yLowBin), yBinEnd = std::min(yHighBin, this->GetMaxBinNumberY()); yBin <= yBinEnd; ++yBin)
547 {
548 TwoDHistogramMap::const_iterator iterY = m_yxHistogramMap.find(yBin);
549
550 if (m_yxHistogramMap.end() == iterY)
551 continue;
552
553 for (int xBin = std::max(this->GetMinBinNumberX(), xLowBin), xBinEnd = std::min(xHighBin, this->GetMaxBinNumberX()); xBin <= xBinEnd; ++xBin)
554 {
555 HistogramMap::const_iterator iterX = iterY->second.find(xBin);
556
557 if (iterY->second.end() == iterX)
558 continue;
559
560 const float binXCenter(firstBinXCenter + (m_xBinWidth * static_cast<float>(iterX->first)));
561 const float binContents(iterX->second);
562
563 sumEntries += binContents;
564 sumXEntries += binContents * binXCenter;
565 sumXXEntries += binContents * binXCenter * binXCenter;
566 }
567 }
568
569 if (std::fabs(sumEntries) < std::numeric_limits<float>::epsilon())
570 return 0.f;
571
572 const float meanX(sumXEntries / sumEntries);
573 const float meanXX(sumXXEntries / sumEntries);
574
575 return std::sqrt(meanXX - (meanX * meanX));
576}
577
578//------------------------------------------------------------------------------------------------------------------------------------------
579
580float TwoDHistogram::GetMeanY(const int xLowBin, const int xHighBin, const int yLowBin, const int yHighBin) const
581{
582 float sumEntries(0.f), sumYEntries(0.f);
583 const float firstBinYCenter(m_yLow + (0.5f * m_yBinWidth));
584
585 for (int xBin = std::max(this->GetMinBinNumberX(), xLowBin), xBinEnd = std::min(xHighBin, this->GetMaxBinNumberX()); xBin <= xBinEnd; ++xBin)
586 {
587 TwoDHistogramMap::const_iterator iterX = m_xyHistogramMap.find(xBin);
588
589 if (m_xyHistogramMap.end() == iterX)
590 continue;
591
592 for (int yBin = std::max(this->GetMinBinNumberY(), yLowBin), yBinEnd = std::min(yHighBin, this->GetMaxBinNumberY()); yBin <= yBinEnd; ++yBin)
593 {
594 HistogramMap::const_iterator iterY = iterX->second.find(yBin);
595
596 if (iterX->second.end() == iterY)
597 continue;
598
599 const float binYCenter(firstBinYCenter + (m_yBinWidth * static_cast<float>(iterY->first)));
600 const float binContents(iterY->second);
601
602 sumEntries += binContents;
603 sumYEntries += binContents * binYCenter;
604 }
605 }
606
607 if (std::fabs(sumEntries) < std::numeric_limits<float>::epsilon())
608 return 0.f;
609
610 return (sumYEntries / sumEntries);
611}
612
613//------------------------------------------------------------------------------------------------------------------------------------------
614
615float TwoDHistogram::GetStandardDeviationY(const int xLowBin, const int xHighBin, const int yLowBin, const int yHighBin) const
616{
617 float sumEntries(0.f), sumYEntries(0.f), sumYYEntries(0.f);
618 const float firstBinYCenter(m_yLow + (0.5f * m_yBinWidth));
619
620 for (int xBin = std::max(this->GetMinBinNumberX(), xLowBin), xBinEnd = std::min(xHighBin, this->GetMaxBinNumberX()); xBin <= xBinEnd; ++xBin)
621 {
622 TwoDHistogramMap::const_iterator iterX = m_xyHistogramMap.find(xBin);
623
624 if (m_xyHistogramMap.end() == iterX)
625 continue;
626
627 for (int yBin = std::max(this->GetMinBinNumberY(), yLowBin), yBinEnd = std::min(yHighBin, this->GetMaxBinNumberY()); yBin <= yBinEnd; ++yBin)
628 {
629 HistogramMap::const_iterator iterY = iterX->second.find(yBin);
630
631 if (iterX->second.end() == iterY)
632 continue;
633
634 const float binYCenter(firstBinYCenter + (m_yBinWidth * static_cast<float>(iterY->first)));
635 const float binContents(iterY->second);
636
637 sumEntries += binContents;
638 sumYEntries += binContents * binYCenter;
639 sumYYEntries += binContents * binYCenter * binYCenter;
640 }
641 }
642
643 if (std::fabs(sumEntries) < std::numeric_limits<float>::epsilon())
644 return 0.f;
645
646 const float meanY(sumYEntries / sumEntries);
647 const float meanYY(sumYYEntries / sumEntries);
648
649 return std::sqrt(meanYY - (meanY * meanY));
650}
651
652//------------------------------------------------------------------------------------------------------------------------------------------
653
654void TwoDHistogram::SetBinContent(const int binX, const int binY, const float value)
655{
656 if ((binX < this->GetUnderflowBinNumberX()) || (binX > this->GetOverflowBinNumberX()) || (binY < this->GetUnderflowBinNumberY()) || (binY > this->GetOverflowBinNumberY()))
657 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
658
659 m_xyHistogramMap[binX][binY] = value;
660 m_yxHistogramMap[binY][binX] = value;
661}
662
663//------------------------------------------------------------------------------------------------------------------------------------------
664
665void TwoDHistogram::Fill(const float valueX, const float valueY, const float weight)
666{
667 const int binX(this->GetBinNumberX(valueX));
668 const int binY(this->GetBinNumberY(valueY));
669
670 HistogramMap &yHistogramMap(m_xyHistogramMap[binX]);
671 HistogramMap::iterator iter = yHistogramMap.find(binY);
672
673 if (yHistogramMap.end() != iter)
674 {
675 iter->second += weight;
676 }
677 else
678 {
679 if (!yHistogramMap.insert(HistogramMap::value_type(binY, weight)).second)
680 throw StatusCodeException(STATUS_CODE_FAILURE);
681 }
682
683 m_yxHistogramMap[binY][binX] = yHistogramMap[binY];
684}
685
686//------------------------------------------------------------------------------------------------------------------------------------------
687
688void TwoDHistogram::Scale(const float scaleFactor)
689{
690 for (TwoDHistogramMap::value_type &mapEntryX : m_xyHistogramMap)
691 {
692 for (HistogramMap::value_type &mapEntryY : mapEntryX.second)
693 {
694 mapEntryY.second = (mapEntryY.second * scaleFactor);
695 }
696 }
697
698 for (TwoDHistogramMap::value_type &mapEntryY : m_yxHistogramMap)
699 {
700 for (HistogramMap::value_type &mapEntryX : mapEntryY.second)
701 {
702 mapEntryX.second = (mapEntryX.second * scaleFactor);
703 }
704 }
705}
706
707//------------------------------------------------------------------------------------------------------------------------------------------
708
709void TwoDHistogram::WriteToXml(TiXmlDocument *const pTiXmlDocument, const std::string &histogramXmlKey) const
710{
711 TiXmlElement *const pHistogramElement = new TiXmlElement(histogramXmlKey);
712
713 TiXmlElement *const pNBinsXElement = new TiXmlElement("NBinsX");
714 pNBinsXElement->LinkEndChild(new TiXmlText(TypeToString(m_nBinsX)));
715 pHistogramElement->LinkEndChild(pNBinsXElement);
716
717 TiXmlElement *const pXLowElement = new TiXmlElement("XLow");
718 pXLowElement->LinkEndChild(new TiXmlText(TypeToString(m_xLow)));
719 pHistogramElement->LinkEndChild(pXLowElement);
720
721 TiXmlElement *const pXHighElement = new TiXmlElement("XHigh");
722 pXHighElement->LinkEndChild(new TiXmlText(TypeToString(m_xHigh)));
723 pHistogramElement->LinkEndChild(pXHighElement);
724
725 TiXmlElement *const pNBinsYElement = new TiXmlElement("NBinsY");
726 pNBinsYElement->LinkEndChild(new TiXmlText(TypeToString(m_nBinsY)));
727 pHistogramElement->LinkEndChild(pNBinsYElement);
728
729 TiXmlElement *const pYLowElement = new TiXmlElement("YLow");
730 pYLowElement->LinkEndChild(new TiXmlText(TypeToString(m_yLow)));
731 pHistogramElement->LinkEndChild(pYLowElement);
732
733 TiXmlElement *const pYHighElement = new TiXmlElement("YHigh");
734 pYHighElement->LinkEndChild(new TiXmlText(TypeToString(m_yHigh)));
735 pHistogramElement->LinkEndChild(pYHighElement);
736
737 TiXmlElement *const pBinContentsElement = new TiXmlElement("BinContents");
738
739 for (int binY = this->GetUnderflowBinNumberY(), endBinY = this->GetOverflowBinNumberY(); binY <= endBinY; ++binY)
740 {
741 std::string binContentsString;
742
743 for (int binX = this->GetUnderflowBinNumberX(), endBinX = this->GetOverflowBinNumberX(); binX <= endBinX; ++binX)
744 {
745 binContentsString += TypeToString(this->GetBinContent(binX, binY)) + " ";
746 }
747
748 TiXmlElement *const pRowElement = new TiXmlElement("Row");
749 pRowElement->LinkEndChild(new TiXmlText(binContentsString));
750 pBinContentsElement->LinkEndChild(pRowElement);
751 }
752
753 pHistogramElement->LinkEndChild(pBinContentsElement);
754
755 pTiXmlDocument->LinkEndChild(pHistogramElement);
756}
757
758} // namespace pandora
Header file for histogram classes.
Header file defining status codes and relevant preprocessor macros.
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:43
Header file for the xml helper class.
Histogram class.
Definition Histograms.h:25
float GetCumulativeSum() const
Get the cumulative sum of bin entries in the histogram (ignores overflow and underflow bins)
Definition Histograms.h:667
float GetMeanX() const
Get the mean x value of entries in the histogram (ignores overflow and underflow bins)
Definition Histograms.h:681
void GetMaximum(float &maximumValue, int &maximumBinX) const
Get the maximum value in the histogram and the corresponding bin number (ignores overflow and underfl...
Definition Histograms.h:674
int GetBinNumber(const float valueX) const
Get the bin number for a specified value.
void Fill(const float valueX, const float weight=1.f)
Add an entry to the histogram.
Histogram(const unsigned int nBinsX, const float xLow, const float xHigh)
Constructor.
Definition Histograms.cc:23
float m_xBinWidth
The x bin width.
Definition Histograms.h:243
int GetOverflowBinNumber() const
Get the overflow bin number of the histogram.
Definition Histograms.h:660
int GetMinBinNumber() const
Get the min bin number of the histogram (ignores overflow and underflow bins)
Definition Histograms.h:639
void SetBinContent(const int binX, const float value)
Set the contents of a specified bin.
float m_xHigh
The max binned x value.
Definition Histograms.h:242
float GetStandardDeviationX() const
Get the standard deviation of entries in the histogram (ignores overflow and underflow bins)
Definition Histograms.h:688
int GetMaxBinNumber() const
Get the max bin number of the histogram (ignores overflow and underflow bins)
Definition Histograms.h:646
void WriteToXml(TiXmlDocument *const pTiXmlDocument, const std::string &xmlElementName) const
Write the histogram to an xml document.
int m_nBinsX
The number of x bins.
Definition Histograms.h:240
float GetBinContent(const int binX) const
Get the content of a specified bin.
Definition Histograms.cc:91
HistogramMap m_histogramMap
The histogram map.
Definition Histograms.h:238
int GetUnderflowBinNumber() const
Get the underflow bin number of the histogram.
Definition Histograms.h:653
float m_xLow
The min binned x value.
Definition Histograms.h:241
void Scale(const float scaleFactor)
Scale contents of all histogram bins by a specified factor.
StatusCodeException class.
TiXmlElement * Element() const
Definition tinyxml.h:1710
TiXmlHandle FirstChild() const
Return a handle to the first child node.
Definition tinyxml.cc:1635
TiXmlNode * LinkEndChild(TiXmlNode *addThis)
Definition tinyxml.cc:189
TwoDHistogram class.
Definition Histograms.h:253
int GetOverflowBinNumberY() const
Get the overflow y bin number of the histogram.
Definition Histograms.h:799
TwoDHistogramMap m_yxHistogramMap
The y->x->value 2d histogram map.
Definition Histograms.h:595
int GetOverflowBinNumberX() const
Get the overflow x bin number of the histogram.
Definition Histograms.h:772
int m_nBinsX
The number of x bins.
Definition Histograms.h:597
int m_nBinsY
The number of y bins.
Definition Histograms.h:602
float GetBinContent(const int binX, const int binY) const
Get the content of a specified bin.
std::map< int, float > HistogramMap
Definition Histograms.h:591
float m_xLow
The min binned x value.
Definition Histograms.h:598
TwoDHistogram(const unsigned int nBinsX, const float xLow, const float xHigh, const unsigned int nBinsY, const float yLow, const float yHigh)
Constructor.
int GetUnderflowBinNumberY() const
Get the underflow y bin number of the histogram.
Definition Histograms.h:792
float GetCumulativeSum() const
Get the cumulative sum of bin entries in the histogram (ignores overflow and underflow bins)
Definition Histograms.h:806
float GetMeanX() const
Get the mean x value of entries in the histogram (ignores overflow and underflow bins)
Definition Histograms.h:820
int GetBinNumberY(const float valueY) const
Get the y bin number for a specified value.
float m_yHigh
The max binned y value.
Definition Histograms.h:604
float m_yLow
The min binned y value.
Definition Histograms.h:603
float GetStandardDeviationY() const
Get the standard deviation of y entries in the histogram (ignores overflow and underflow bins)
Definition Histograms.h:841
void GetMaximum(float &maximumValue, int &maximumBinX, int &maximumBinY) const
Get the maximum value in the histogram and the corresponding bin numbers (ignores overflow and underf...
Definition Histograms.h:813
int GetMaxBinNumberY() const
Get the max y bin number of the histogram (ignores overflow and underflow bins)
Definition Histograms.h:785
int GetBinNumberX(const float valueX) const
Get the x bin number for a specified x value.
void SetBinContent(const int binX, const int binY, const float value)
Set the contents of a specified bin.
TwoDHistogramMap m_xyHistogramMap
The x->y->value 2d histogram map.
Definition Histograms.h:594
float GetStandardDeviationX() const
Get the standard deviation of x entries in the histogram (ignores overflow and underflow bins)
Definition Histograms.h:827
float m_xHigh
The max binned x value.
Definition Histograms.h:599
int GetUnderflowBinNumberX() const
Get the underflow x bin number of the histogram.
Definition Histograms.h:765
void WriteToXml(TiXmlDocument *const pTiXmlDocument, const std::string &xmlElementName) const
Write the histogram to an xml document.
float GetMeanY() const
Get the mean y value of entries in the histogram (ignores overflow and underflow bins)
Definition Histograms.h:834
int GetMinBinNumberY() const
Get the min y bin number of the histogram (ignores overflow and underflow bins)
Definition Histograms.h:778
float m_yBinWidth
The y bin width.
Definition Histograms.h:605
void Fill(const float valueX, const float valueY, const float weight=1.f)
Add an entry to the histogram.
void Scale(const float scaleFactor)
Scale contents of all histogram bins by a specified factor.
int GetMinBinNumberX() const
Get the min x bin number of the histogram (ignores overflow and underflow bins)
Definition Histograms.h:751
float m_xBinWidth
The x bin width.
Definition Histograms.h:600
int GetMaxBinNumberX() const
Get the max x bin number of the histogram (ignores overflow and underflow bins)
Definition Histograms.h:758
static StatusCode ReadVectorOfValues(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, std::vector< T > &vector)
Read a vector of values from a (space separated) list in an xml element.
Definition XmlHelper.h:229
static StatusCode Read2DVectorOfValues(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, const std::string &rowName, std::vector< std::vector< T > > &vector)
Read a two-dimensional array of values into a vector of vectors. Each row of values must be contained...
Definition XmlHelper.h:255
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
Definition XmlHelper.h:136
std::vector< float > FloatVector
std::string TypeToString(const T &t)