|
44 | 44 | #include "Math/WrappedMultiTF1.h" |
45 | 45 | #include "Fit/BinData.h" |
46 | 46 | #include "Fit/UnBinData.h" |
47 | | -#include "HFitInterface.h" |
48 | 47 | #include "Fit/Fitter.h" |
49 | 48 | #include "TLatex.h" |
50 | 49 | #include "TStyle.h" |
@@ -72,7 +71,7 @@ MARMFitter::MARMFitter() |
72 | 71 | ROOT::Math::MinimizerOptions::SetDefaultMaxFunctionCalls(250000); |
73 | 72 |
|
74 | 73 | std::random_device RD; // <-- should use MEGAlib global |
75 | | - std::mt19937 m_MersenneTwister(RD()); |
| 74 | + m_MersenneTwister.seed(RD()); |
76 | 75 |
|
77 | 76 | m_NumberOfBins = 101; |
78 | 77 | m_MaxARMValue = 180; |
@@ -818,18 +817,31 @@ bool MARMFitter::PerformFit(unsigned int FitID, vector<double>& ARMValues) |
818 | 817 | ROOT::Fit::UnBinData UnbinnedData(CleanedData.size(), CleanedData.data(), Range); |
819 | 818 | Fitter.LikelihoodFit(UnbinnedData, true); |
820 | 819 | } else { |
821 | | - //cout<<"Binned fit"<<endl; |
822 | 820 | DataOptions.fIntegral = true; |
823 | | - DataOptions.fUseRange =true; |
824 | | - ROOT::Fit::BinData BinnedData(DataOptions, Range); |
825 | | - // Easiest option to fill the binned data set is via a histogram: |
826 | | - TH1D* D = new TH1D("", "", m_NumberOfBins, -m_MaxARMValue, m_MaxARMValue); |
827 | | - for (auto& V: CleanedData) D->Fill(V); |
828 | | - for (int b = 1; b <= D->GetNbinsX(); ++b) D->SetBinError(b, sqrt(D->GetBinContent(b))); |
829 | | - ROOT::Fit::FillData(BinnedData, D); |
830 | | - delete D; |
| 821 | + DataOptions.fUseRange = true; |
| 822 | + |
| 823 | + // Bin the data directly into a counts vector — one entry per bin over [-m_MaxARMValue, m_MaxARMValue] |
| 824 | + double BinWidth = 2.0 * m_MaxARMValue / m_NumberOfBins; |
| 825 | + vector<double> BinCounts(m_NumberOfBins, 0.0); |
| 826 | + for (auto& V: CleanedData) { |
| 827 | + int Bin = static_cast<int>((V + m_MaxARMValue) / BinWidth); |
| 828 | + if (Bin >= 0 && Bin < static_cast<int>(m_NumberOfBins)) { |
| 829 | + BinCounts[Bin]++; |
| 830 | + } |
| 831 | + } |
| 832 | + |
| 833 | + // Fill BinData directly: bin center, bin content, half-bin-width (required by fIntegral), Poisson error. |
| 834 | + // Empty bins are skipped, consistent with the default DataOptions.fUseEmpty = false. |
| 835 | + // kCoordError is required to store both x (bin half-width) and y (Poisson) errors, |
| 836 | + // which ROOT needs to integrate the fit function over each bin (fIntegral = true). |
| 837 | + ROOT::Fit::BinData BinnedData(DataOptions, Range, m_NumberOfBins, 1, ROOT::Fit::BinData::kCoordError); |
| 838 | + for (unsigned int b = 0; b < m_NumberOfBins; ++b) { |
| 839 | + if (BinCounts[b] == 0) continue; |
| 840 | + double BinCenter = -m_MaxARMValue + (b + 0.5) * BinWidth; |
| 841 | + BinnedData.Add(BinCenter, BinCounts[b], 0.5 * BinWidth, sqrt(BinCounts[b])); |
| 842 | + } |
| 843 | + |
831 | 844 | Fitter.LikelihoodFit(BinnedData, true); |
832 | | - //Fitter.LeastSquareFit(BinnedData); |
833 | 845 | } |
834 | 846 |
|
835 | 847 | // Retrieve results |
@@ -936,11 +948,13 @@ vector<double> MARMFitter::BootstrapARMValues() |
936 | 948 | { |
937 | 949 | std::uniform_int_distribution<> Distributor(0, m_OriginalARMValues.size() - 1); |
938 | 950 |
|
939 | | - // Bootstrapping: sample with replacement |
| 951 | + // Bootstrapping: sample with replacement. |
| 952 | + // m_MersenneTwister is shared across threads, so all draws must be made under the mutex. |
940 | 953 | vector<double> ARMValues; |
941 | 954 | ARMValues.reserve(m_OriginalARMValues.size()); |
942 | 955 | for (size_t i = 0; i < m_OriginalARMValues.size(); ++i) { |
943 | | - int D = Distributor(m_MersenneTwister); |
| 956 | + int D; |
| 957 | + { std::unique_lock<std::mutex> Lock(m_Mutex); D = Distributor(m_MersenneTwister); } |
944 | 958 | ARMValues.push_back(m_OriginalARMValues[D]); |
945 | 959 | } |
946 | 960 |
|
@@ -1162,6 +1176,7 @@ bool MARMFitter::Fit(unsigned int NumberOfFits) |
1162 | 1176 | double MaxX = Hist->GetBinCenter(Hist->GetMaximumBin()); |
1163 | 1177 | m_GuessMaximumLow = MaxX - 0.5*Hist->GetRMS(); |
1164 | 1178 | m_GuessMaximumHigh = MaxX + 0.5*Hist->GetRMS(); |
| 1179 | + delete Hist; |
1165 | 1180 |
|
1166 | 1181 |
|
1167 | 1182 | // Right size the result storage |
@@ -1298,7 +1313,7 @@ double MARMFitter::Get95p5PercentContainmentUsingAllData() const |
1298 | 1313 | //! Return the 99.7% containment for all events |
1299 | 1314 | double MARMFitter::Get99p7PercentContainmentUsingAllData() const |
1300 | 1315 | { |
1301 | | - return m_FitSuccessful ? m_Containment3SigmaUsingAllData : g_UnsignedIntNotDefined; |
| 1316 | + return m_FitSuccessful ? m_Containment3SigmaUsingAllData : g_DoubleNotDefined; |
1302 | 1317 | } |
1303 | 1318 |
|
1304 | 1319 |
|
|
0 commit comments