19 #define BOOST_TEST_MODULE ( HitAnaAlg_test )
20 #include "boost/test/unit_test.hpp"
21 #include "cetlib/pow.h"
25 #include "TFitResultPtr.h"
26 #include "TFitResult.h"
27 #ifdef GAUSFITCACHE_TEST_DEBUG
29 #endif // GAUSFITCACHE_TEST_DEBUG
39 double gaus(
double x,
double mean,
double sigma,
double amplitude) {
40 double const z = (x -
mean) / sigma;
41 return amplitude *
std::exp(-0.5*square(z));
47 BOOST_AUTO_TEST_SUITE( GausFitCacheSuite )
55 const auto gaus_func =
::gaus;
57 const double exp1sigma =
std::exp(-0.5*square(1.));
58 const double exp2sigma =
std::exp(-0.5*square(2.));
61 const double amplitude = 16.;
62 for (
double sigma = 0.5; sigma < 2.25; ++sigma) {
65 BOOST_TEST(gaus_func(-6.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
66 BOOST_TEST(gaus_func(-5.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
67 BOOST_TEST(gaus_func(-4.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
70 BOOST_TEST(gaus_func(-2.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp2sigma,
tol);
71 BOOST_TEST(gaus_func(-1.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp1sigma,
tol);
72 BOOST_TEST(gaus_func( 0.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude,
tol);
73 BOOST_TEST(gaus_func( 1.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp1sigma,
tol);
74 BOOST_TEST(gaus_func( 2.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp2sigma,
tol);
76 BOOST_TEST(gaus_func( 4.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
77 BOOST_TEST(gaus_func( 5.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
78 BOOST_TEST(gaus_func( 6.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
90 using Func_t = Double_t (*) (Double_t
const*, Double_t
const*);
95 (Double_t
const x, Double_t
mean, Double_t sigma, Double_t amplitude)
const
99 std::array<Double_t, 3> params = {{ amplitude,
mean, sigma }};
100 return func(&
x, params.data());
113 const double exp1sigma =
std::exp(-0.5*square(1.));
114 const double exp2sigma =
std::exp(-0.5*square(2.));
116 const double amplitude = 16.;
117 for (
double sigma = 0.5; sigma < 2.25; ++sigma) {
120 BOOST_TEST(gaus_func(-6.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
121 BOOST_TEST(gaus_func(-5.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
122 BOOST_TEST(gaus_func(-4.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
125 BOOST_TEST(gaus_func(-2.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp2sigma,
tol);
126 BOOST_TEST(gaus_func(-1.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp1sigma,
tol);
127 BOOST_TEST(gaus_func( 0.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude,
tol);
128 BOOST_TEST(gaus_func(+1.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp1sigma,
tol);
129 BOOST_TEST(gaus_func(+2.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp2sigma,
tol);
131 BOOST_TEST(gaus_func(+4.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
132 BOOST_TEST(gaus_func(+5.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
133 BOOST_TEST(gaus_func(+6.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
145 (hit::details::CompiledGausFitCacheBaseStruct::gaus_trunc<5>);
147 const double exp1sigma =
std::exp(-0.5*square(1.));
148 const double exp2sigma =
std::exp(-0.5*square(2.));
150 const double amplitude = 16.;
151 for (
double sigma = 0.5; sigma < 2.25; ++sigma) {
154 BOOST_TEST(gaus_func(-6.5 * sigma +
mean,
mean, sigma, amplitude) == 0.);
155 BOOST_TEST(gaus_func(-5.5 * sigma +
mean,
mean, sigma, amplitude) == 0.);
156 BOOST_TEST(gaus_func(-4.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
159 BOOST_TEST(gaus_func(-2.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp2sigma,
tol);
160 BOOST_TEST(gaus_func(-1.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp1sigma,
tol);
161 BOOST_TEST(gaus_func( 0.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude,
tol);
162 BOOST_TEST(gaus_func( 1.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp1sigma,
tol);
163 BOOST_TEST(gaus_func( 2.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp2sigma,
tol);
165 BOOST_TEST(gaus_func( 4.5 * sigma +
mean,
mean, sigma, amplitude) > 0.);
166 BOOST_TEST(gaus_func( 5.5 * sigma +
mean,
mean, sigma, amplitude) == 0.);
167 BOOST_TEST(gaus_func( 6.5 * sigma +
mean,
mean, sigma, amplitude) == 0.);
179 (hit::details::CompiledGausFitCacheBaseStruct::gaus_trunc<4>);
181 const double exp1sigma =
std::exp(-0.5*square(1.));
182 const double exp2sigma =
std::exp(-0.5*square(2.));
184 const double amplitude = 16.;
185 for (
double sigma = 0.5; sigma < 2.25; ++sigma) {
188 BOOST_TEST(gaus_func(-6.5 * sigma +
mean,
mean, sigma, amplitude) == 0.);
189 BOOST_TEST(gaus_func(-5.5 * sigma +
mean,
mean, sigma, amplitude) == 0.);
190 BOOST_TEST(gaus_func(-4.5 * sigma +
mean,
mean, sigma, amplitude) == 0.);
193 BOOST_TEST(gaus_func(-2.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp2sigma,
tol);
194 BOOST_TEST(gaus_func(-1.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp1sigma,
tol);
195 BOOST_TEST(gaus_func( 0.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude,
tol);
196 BOOST_TEST(gaus_func( 1.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp1sigma,
tol);
197 BOOST_TEST(gaus_func( 2.0 * sigma +
mean,
mean, sigma, amplitude) == amplitude * exp2sigma,
tol);
199 BOOST_TEST(gaus_func( 4.5 * sigma +
mean,
mean, sigma, amplitude) == 0.);
200 BOOST_TEST(gaus_func( 5.5 * sigma +
mean,
mean, sigma, amplitude) == 0.);
201 BOOST_TEST(gaus_func( 6.5 * sigma +
mean,
mean, sigma, amplitude) == 0.);
214 (Double_t
x,
const unsigned int nGaus, Double_t
const* params)
218 for (
unsigned int iGaus = 0; iGaus < nGaus; ++iGaus) {
220 res +=
gaus(x, params[1], params[2], params[0]);
229 (TF1
const* pFunc, Double_t
const* Params)
231 assert(pFunc->GetNpar() % 3 == 0);
233 const size_t nGaus = pFunc->GetNpar() / 3;
235 std::vector<size_t> BestMatch(nGaus, nGaus);
236 for (
size_t iGaus = 0; iGaus < nGaus; ++iGaus) {
237 double best_match_quality = std::numeric_limits<double>::max();
238 for (
size_t iFitGaus = 0; iFitGaus < nGaus; ++iFitGaus) {
240 const double match_quality
241 = square(Params[iGaus*3 + 0] - pFunc->GetParameter(iFitGaus*3 + 0))
242 + square(Params[iGaus*3 + 1] - pFunc->GetParameter(iFitGaus*3 + 1))
243 + square(Params[iGaus*3 + 2] - pFunc->GetParameter(iFitGaus*3 + 2))
245 if (match_quality < best_match_quality) {
246 best_match_quality = match_quality;
247 BestMatch[iGaus] = iFitGaus;
251 assert(BestMatch[iGaus] < nGaus);
253 for (
size_t i = 0; i < iGaus; ++i) {
255 assert(BestMatch[i] != BestMatch[iGaus]);
260 std::vector<Double_t> sorted_params(nGaus * 3);
261 for (
size_t iGaus = 0; iGaus < nGaus; ++iGaus) {
262 const size_t iBestFit = BestMatch[iGaus];
263 for (
size_t i = 0; i < 3; ++i)
264 sorted_params[iGaus*3 + i] = pFunc->GetParameter(iBestFit*3 + i);
266 return sorted_params;
275 constexpr
size_t nGaus = 3;
278 const Double_t Params[nGaus * 3] = {
287 (
"H3Gaus", (
"Three-Gaussian test - " + name).c_str(), 200, -10., 10.);
288 for (Int_t iBin = 1; iBin <= Hist.GetNbinsX(); ++iBin)
289 Hist.SetBinContent(iBin,
multi_gaus(Hist.GetBinCenter(iBin), nGaus, Params));
291 #ifdef GAUSFITCACHE_TEST_DEBUG
293 #endif // GAUSFITCACHE_TEST_DEBUG
296 TF1* pFunc = GausCache.
Get(nGaus);
299 const double MeanOffset = -((double(nGaus) - 1.) / 2.);
300 const double MeanStep = 1.;
301 for (
size_t iGaus = 0; iGaus < nGaus; ++iGaus) {
302 size_t BaseIndex = iGaus * 3;
303 pFunc->SetParameter(BaseIndex + 0, 1.);
304 pFunc->SetParameter(BaseIndex + 1, MeanOffset + iGaus * MeanStep);
305 pFunc->SetParameter(BaseIndex + 2, 1.);
309 pFunc->SetRange(Hist.GetBinCenter(1), Hist.GetBinCenter(Hist.GetNbinsX()));
311 #ifdef GAUSFITCACHE_TEST_DEBUG
312 TF1* pFCopy = pFunc->DrawCopy(
"L SAME");
313 pFCopy->SetLineStyle(kDashed);
314 pFCopy->SetLineColor(kCyan);
315 #endif // GAUSFITCACHE_TEST_DEBUG
318 TFitResultPtr fit_res = Hist.Fit(pFunc,
"WQ0NS");
319 BOOST_TEST(
int(fit_res) == 0);
321 #ifdef GAUSFITCACHE_TEST_DEBUG
322 pFCopy = pFunc->DrawCopy(
"L SAME");
323 pFCopy->SetLineWidth(1);
324 pFCopy->SetLineColor(kRed);
326 gPad->SaveAs((
"3GausTest_" + name +
".eps").c_str());
327 #endif // GAUSFITCACHE_TEST_DEBUG
334 for (
size_t iGaus = 0; iGaus < nGaus; ++iGaus) {
335 const size_t iParam = iGaus * 3;
338 BOOST_TEST(results[iParam + 0] == Params[iParam + 0], tol);
340 BOOST_TEST(results[iParam + 1] == Params[iParam + 1], tol);
342 BOOST_TEST(results[iParam + 2] == Params[iParam + 2], tol);
346 BOOST_WARN(pFunc->GetChisquare() < pFunc->GetNDF() / 2.);
348 #ifdef GAUSFITCACHE_TEST_DEBUG
351 #else // !GAUSFITCACHE_TEST_DEBUG
353 if ((
int(fit_res) != 0) || (pFunc->GetChisquare() >= pFunc->GetNDF() / 2.))
367 const Double_t Params[] = {
374 for (
double x = -10.; x <= +10.; x += 0.1) {
375 const Double_t expected =
multi_gaus(x, 3, Params);
377 const Double_t tested
378 = hit::details::CompiledGausFitCacheBaseStruct::ngaus<3>(&
x, Params);
380 BOOST_TEST(tested == expected, 0.001%
tolerance());
410 (
"CompiledTruncated5Gaussians");
421 (
"CompiledTruncated4Gaussians");
431 (
"CompiledTruncated3Gaussians");
436 BOOST_AUTO_TEST_SUITE_END()
process_name opflash particleana ie ie ie z
static Double_t gaus(Double_t const *x, Double_t const *params)
Single Gaussian function.
process_name opflash particleana ie x
void ThreeGaussianFitTest(hit::GausFitCache &GausCache, tolerance_t tol)
std::vector< Double_t > SortGaussianResults(TF1 const *pFunc, Double_t const *Params)
decltype(0.001%tolerance()) tolerance_t
A set of TF1 linear sum of base functions (Gaussians)
A set of TF1 linear sum of Gaussians.
A set of TF1 linear sum of truncated Gaussians.
Double_t(*)(Double_t const *, Double_t const *) Func_t
T gaus(T x, T amplitude, T mean, T sigma)
Tests GausssianFit object with a known input.
virtual TF1 * Get(size_t nFunc)
Returns a function sum of nFunc base functions.
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
Double_t multi_gaus(Double_t x, const unsigned int nGaus, Double_t const *params)
Expect for each Gaussian ROOT-like parameters: amplitude, mean, sigma.
Provide caches for TF1 functions to be used with ROOT fitters.
std::string GetName() const
Return the name of this cache.
RootGausFuncWrapper(Func_t f)