31 throw std::runtime_error(
32 "A systematic variation was requested for a custom Fill action, but the type of the object to be filled does "
33 "not implement a Reset method, so we cannot safely re-initialize variations of the result. Aborting.");
38 h->SetDirectory(
nullptr);
42CountHelper::CountHelper(
const std::shared_ptr<ULong64_t> &resultCount,
const unsigned int nSlots)
43 : fResultCount(resultCount), fCounts(nSlots, 0)
47void CountHelper::Exec(
unsigned int slot)
52void CountHelper::Finalize()
55 for (
auto &
c : fCounts) {
60ULong64_t &CountHelper::PartialUpdate(
unsigned int slot)
65void BufferedFillHelper::UpdateMinMax(
unsigned int slot,
double v)
67 auto &thisMin = fMin[slot * CacheLineStep<BufEl_t>()];
68 auto &thisMax = fMax[slot * CacheLineStep<BufEl_t>()];
69 thisMin = std::min(thisMin,
v);
70 thisMax = std::max(thisMax,
v);
73BufferedFillHelper::BufferedFillHelper(
const std::shared_ptr<Hist_t> &
h,
const unsigned int nSlots)
74 : fResultHist(
h), fNSlots(nSlots), fBufSize(fgTotalBufSize / nSlots), fPartialHists(fNSlots),
75 fMin(nSlots *
CacheLineStep<BufEl_t>(), std::numeric_limits<BufEl_t>::max()),
76 fMax(nSlots *
CacheLineStep<BufEl_t>(), std::numeric_limits<BufEl_t>::lowest())
78 fBuffers.reserve(fNSlots);
79 fWBuffers.reserve(fNSlots);
80 for (
unsigned int i = 0; i < fNSlots; ++i) {
83 fBuffers.emplace_back(
v);
84 fWBuffers.emplace_back(
v);
88void BufferedFillHelper::Exec(
unsigned int slot,
double v)
90 UpdateMinMax(slot,
v);
91 fBuffers[slot].emplace_back(
v);
94void BufferedFillHelper::Exec(
unsigned int slot,
double v,
double w)
96 UpdateMinMax(slot,
v);
97 fBuffers[slot].emplace_back(
v);
98 fWBuffers[slot].emplace_back(
w);
101Hist_t &BufferedFillHelper::PartialUpdate(
unsigned int slot)
103 auto &partialHist = fPartialHists[slot];
106 partialHist = std::make_unique<Hist_t>(*fResultHist);
107 auto weights = fWBuffers[slot].empty() ? nullptr : fWBuffers[slot].data();
108 partialHist->FillN(fBuffers[slot].
size(), fBuffers[slot].
data(), weights);
112void BufferedFillHelper::Finalize()
114 for (
unsigned int i = 0; i < fNSlots; ++i) {
115 if (!fWBuffers[i].empty() && fBuffers[i].
size() != fWBuffers[i].
size()) {
116 throw std::runtime_error(
"Cannot fill weighted histogram with values in containers of different sizes.");
120 BufEl_t globalMin = *std::min_element(fMin.begin(), fMin.end());
121 BufEl_t globalMax = *std::max_element(fMax.begin(), fMax.end());
123 if (fResultHist->CanExtendAllAxes() && globalMin != std::numeric_limits<BufEl_t>::max() &&
124 globalMax != std::numeric_limits<BufEl_t>::lowest()) {
125 fResultHist->SetBins(fResultHist->GetNbinsX(), globalMin, globalMax);
128 for (
unsigned int i = 0; i < fNSlots; ++i) {
129 auto weights = fWBuffers[i].empty() ? nullptr : fWBuffers[i].data();
130 fResultHist->FillN(fBuffers[i].
size(), fBuffers[i].
data(), weights);
134MeanHelper::MeanHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots)
135 : fResultMean(meanVPtr), fCounts(nSlots, 0), fSums(nSlots, 0), fPartialMeans(nSlots), fCompensations(nSlots)
139void MeanHelper::Exec(
unsigned int slot,
double v)
143 double y =
v - fCompensations[slot];
144 double t = fSums[slot] +
y;
145 fCompensations[slot] = (t - fSums[slot]) -
y;
149void MeanHelper::Finalize()
151 double sumOfSums = 0;
153 double compensation(0);
156 for (
auto &
m : fSums) {
157 y =
m - compensation;
159 compensation = (t - sumOfSums) -
y;
163 for (
auto &
c : fCounts)
165 *fResultMean = sumOfSums / (sumOfCounts > 0 ? sumOfCounts : 1);
168double &MeanHelper::PartialUpdate(
unsigned int slot)
170 fPartialMeans[slot] = fSums[slot] / fCounts[slot];
171 return fPartialMeans[slot];
174StdDevHelper::StdDevHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots)
175 : fNSlots(nSlots), fResultStdDev(meanVPtr), fCounts(nSlots, 0), fMeans(nSlots, 0), fDistancesfromMean(nSlots, 0)
179void StdDevHelper::Exec(
unsigned int slot,
double v)
182 auto count = ++fCounts[slot];
183 auto delta =
v - fMeans[slot];
184 auto mean = fMeans[slot] + delta / count;
185 auto delta2 =
v - mean;
186 auto distance = fDistancesfromMean[slot] + delta * delta2;
188 fCounts[slot] = count;
190 fDistancesfromMean[slot] = distance;
193void StdDevHelper::Finalize()
196 double totalElements = 0;
197 for (
auto c : fCounts) {
200 if (totalElements == 0 || totalElements == 1) {
206 double overallMean = 0;
207 for (
unsigned int i = 0; i < fNSlots; ++i) {
208 overallMean += fCounts[i] * fMeans[i];
210 overallMean = overallMean / totalElements;
213 for (
unsigned int i = 0; i < fNSlots; ++i) {
214 if (fCounts[i] == 0) {
217 auto setVariance = fDistancesfromMean[i] / (fCounts[i]);
218 variance += (fCounts[i]) * (setVariance + std::pow((fMeans[i] - overallMean), 2));
221 variance = variance / (totalElements - 1);
222 *fResultStdDev = std::sqrt(variance);
225MedianHelper::MedianHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots)
226 : fResult(meanVPtr), fBuffers(nSlots, std::vector<
double>())
230void MedianHelper::Exec(
unsigned int slot,
double v)
232 fBuffers[slot].push_back(
v);
235void MedianHelper::Finalize()
237 std::vector<double> fullBuffer;
238 std::size_t fullBufferSize = 0;
239 for (
const auto &buffer : fBuffers) {
240 fullBufferSize += buffer.size();
243 if (fullBufferSize == 0) {
244 *fResult = std::numeric_limits<double>::signaling_NaN();
248 fullBuffer.reserve(fullBufferSize);
250 for (
const auto &buffer : fBuffers)
251 fullBuffer.insert(fullBuffer.end(), buffer.begin(), buffer.end());
253 const std::size_t k = fullBufferSize / 2;
254 std::nth_element(fullBuffer.begin(), fullBuffer.begin() + k, fullBuffer.end());
255 const double upper = fullBuffer[k];
257 if (fullBuffer.size() % 2) {
260 const double lower = *std::max_element(fullBuffer.begin(), fullBuffer.begin() + k);
261 *fResult = 0.5 * (lower + upper);
267template class TakeHelper<bool, bool, std::vector<bool>>;
268template class TakeHelper<unsigned int, unsigned int, std::vector<unsigned int>>;
269template class TakeHelper<unsigned long, unsigned long, std::vector<unsigned long>>;
270template class TakeHelper<unsigned long long, unsigned long long, std::vector<unsigned long long>>;
271template class TakeHelper<int, int, std::vector<int>>;
272template class TakeHelper<long, long, std::vector<long>>;
273template class TakeHelper<long long, long long, std::vector<long long>>;
274template class TakeHelper<float, float, std::vector<float>>;
275template class TakeHelper<double, double, std::vector<double>>;
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
Basic types used by ROOT and required by TInterpreter.
unsigned long long ULong64_t
Portable unsigned long integer 8 bytes.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
TH1 is the base class of all histogram classes in ROOT.
Statistical variable, defined by its mean and variance (RMS).
void ResetIfPossible(TStatistic *h)
constexpr std::size_t CacheLineStep()
Stepping through CacheLineStep<T> values in a vector<T> brings you to a new cache line.
void UnsetDirectoryIfPossible(TH1 *h)