File indexing completed on 2026-08-26 08:20:24
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Utilities/Histogram.hpp"
0012 #include "Acts/Utilities/Logger.hpp"
0013
0014 #include <array>
0015 #include <functional>
0016 #include <optional>
0017 #include <string>
0018 #include <tuple>
0019 #include <utility>
0020
0021 namespace ActsExamples {
0022
0023
0024
0025
0026
0027
0028 using HistogramFitResult = std::tuple<double, double, double, double>;
0029
0030
0031 using HistogramFitRange = std::pair<double, double>;
0032
0033
0034
0035
0036
0037 using HistogramFitFunction = std::function<std::optional<HistogramFitResult>(
0038 const Acts::Experimental::Histogram1&, std::optional<HistogramFitRange>)>;
0039
0040
0041
0042
0043
0044 template <std::size_t Dim>
0045 struct MeanWidthProfiles {
0046
0047 Acts::Experimental::Histogram<Dim> mean;
0048
0049 Acts::Experimental::Histogram<Dim> width;
0050
0051 double fitFailureFraction{};
0052 };
0053
0054
0055 using MeanWidthProfiles1 = MeanWidthProfiles<1>;
0056
0057 using MeanWidthProfiles2 = MeanWidthProfiles<2>;
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 std::optional<HistogramFitResult> iterativeFit(
0072 const HistogramFitFunction& fitFn,
0073 const Acts::Experimental::Histogram1& hist, double sigmaRange,
0074 int iterations, const Acts::Logger& logger = Acts::getDummyLogger());
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 template <std::size_t Dim>
0094 MeanWidthProfiles<Dim - 1> extractMeanWidthProfiles(
0095 const HistogramFitFunction& fitFn,
0096 const Acts::Experimental::Histogram<Dim>& hist, const std::string& meanName,
0097 const std::string& widthName, int minEntriesForFit = 5,
0098 double sigmaRange = 3.0, int iterations = 3,
0099 const Acts::Logger& logger = Acts::getDummyLogger()) {
0100 constexpr std::size_t OuterDim = Dim - 1;
0101
0102 std::array<Acts::Experimental::AxisVariant, OuterDim> axes{};
0103 std::array<int, OuterDim> outerSizes{};
0104 int totalOuterBins = 1;
0105 for (std::size_t d = 0; d < OuterDim; ++d) {
0106 axes[d] = hist.histogram().axis(d);
0107 outerSizes[d] = hist.histogram().axis(d).size();
0108 totalOuterBins *= outerSizes[d];
0109 }
0110
0111 MeanWidthProfiles<OuterDim> profiles{
0112 Acts::Experimental::Histogram<OuterDim>(meanName, hist.title() + " mean",
0113 axes),
0114 Acts::Experimental::Histogram<OuterDim>(widthName,
0115 hist.title() + " width", axes),
0116 0.0};
0117
0118
0119
0120
0121 const auto unravel = [&](int flat) {
0122 std::array<int, OuterDim> outerBins{};
0123 int remaining = flat;
0124 for (std::size_t d = OuterDim; d-- > 0;) {
0125 outerBins[d] = remaining % outerSizes[d];
0126 remaining /= outerSizes[d];
0127 }
0128 return outerBins;
0129 };
0130
0131 int fitFailures = 0;
0132 for (int flat = 0; flat < totalOuterBins; ++flat) {
0133 const std::array<int, OuterDim> outerBins = unravel(flat);
0134 const Acts::Experimental::Histogram1 slice = hist.sliceLastAxis(outerBins);
0135 if (slice.totalContent() < minEntriesForFit) {
0136
0137 continue;
0138 }
0139
0140 const std::optional<HistogramFitResult> result =
0141 iterativeFit(fitFn, slice, sigmaRange, iterations, logger);
0142 if (!result.has_value()) {
0143 ++fitFailures;
0144 continue;
0145 }
0146
0147 const auto& [mean, sigma, meanError, sigmaError] = *result;
0148 profiles.mean.setBin(outerBins, mean, meanError);
0149 profiles.width.setBin(outerBins, sigma, sigmaError);
0150 }
0151
0152 profiles.fitFailureFraction =
0153 (totalOuterBins > 0) ? static_cast<double>(fitFailures) / totalOuterBins
0154 : 0;
0155
0156 return profiles;
0157 }
0158
0159 }