2#include <gsl/gsl_sf_erf.h>
6std::size_t count_total_points(
const Contour& c) {
8 for (
const auto& path : c.paths) {
20 std::shared_ptr<Profiler> profiler =
21 std::make_shared<Profiler>(
26 std::shared_ptr<IProfilingStrategy> strategy;
28 strategy = std::make_shared<SliceProfilingStrategy>(cfg.
x_id, cfg.
y_id, cfg.
fr);
30 strategy = std::make_shared<ProjectionProfilingStrategy>(cfg.
x_id, cfg.
y_id, cfg.
fr);
33 std::shared_ptr<ILikelihood> maybe_constrained_base = base;
35 std::vector<std::size_t> constrained_idx;
36 for (
size_t i = 0; i < cfg.
fr.
p_hat.size(); i++) {
38 constrained_idx.emplace_back(i);
41 maybe_constrained_base = std::make_shared<WithGaussianConstraints>(
43 this->build_constraints_distribution(),
51 this->extractor = std::make_shared<WithFallback>(
61 using clock = std::chrono::steady_clock;
62 const auto t0 = clock::now();
67 const double reference_nll =
70 auto cache = std::make_shared<std::map<Point, double>>();
72 ScalarField2D field = [
this, reference_nll, cache](
double x,
double y) {
75 auto it = cache->find(key);
76 if (it != cache->end()) {
81 const double val = std::isfinite(raw)
82 ? std::clamp(raw - reference_nll, -1e50, 1e50)
91 cr.
level = z * z / 2.0;
92 cr.
level = gsl_cdf_chisq_Pinv(gsl_sf_erf(z / std::sqrt(2.0)), 2) / 2.0;
99 defs[0].limits = std::make_pair(bounds[0], bounds[1]);
103 defs[1].limits = std::make_pair(bounds[2], bounds[3]);
112 ev.
message =
"Contour computation started";
117 Contour c = this->extractor->extract(field, cr);
124 ev.
n_points = count_total_points(c);
126 std::chrono::duration<double>(clock::now() - t0).count();
128 :
"Contour computation finished but contour is marked unsuccessful";
134 catch (
const std::exception& e) {
140 std::chrono::duration<double>(clock::now() - t0).count();
148std::shared_ptr<JointDistribution> ContourEngine::build_constraints_distribution() {
149 std::vector<std::unique_ptr<IMarginalDistribution>> fitted_marginals;
151 for (
size_t i = 0; i < cfg.
fr.
p_hat.size(); i++) {
153 fitted_marginals.emplace_back(std::move(std::make_unique<GaussianMarginal>(cfg.
fr.
p_hat[i], cfg.
fr.
p_hat_std[i])));
159 std::unique_ptr<ICopula> fitted_copula = std::make_unique<GaussianCopula>(std::random_device{}(), R_fitted);
161 return std::make_unique<JointDistribution>(std::move(fitted_marginals), std::move(fitted_copula));
164std::shared_ptr<IContourExtractor> ContourEngine::build_contour_extractor(
169 return std::make_shared<AMSContourExtractor>(cfg.
on_progress);
171 return std::make_shared<MnContourExtractor>();
173 throw std::invalid_argument(
"Unknown contouring algorithm.");
High-level engine for profiled two-dimensional likelihood contours.
ContourAlgorithm
Algorithm family used to extract contour paths from the profiled field.
@ AMS
Adaptive/marching-squares contour extractor.
@ MINUIT
Minuit contour extractor.
@ SLICE
Fix all fit parameters except nuisances; scan only the selected axes.
@ PRIOR_CONSTRAINED_PROJECTION
Profile remaining parameters with Gaussian constraints around the fit result.
@ Started
Contour computation has started.
@ Finished
Contour computation finished normally.
@ Failed
Contour computation failed and no valid result was produced.
ProfilerMode
Available algorithms for profiling free parameters.
ContourEngine(std::shared_ptr< ILikelihood > base, const ContourConfig &cfg)
Constructs a contour engine for a base likelihood.
Contour compute_contour(double z, std::array< double, 4 > bounds, std::size_t resolution)
Computes a profiled 2D contour for a requested significance.
Evaluates a profiled NLL as a function of two scan coordinates.
double profiled_nll(double px, double py)
Evaluates the profiled NLL at one 2D scan point.
std::array< fit_app::ParameterDefinition, 2 > get_param_defs() const
Returns the parameter definitions for the two scan coordinates.
void remove_row_and_column(std::size_t dim_idx)
Removes one row and one column with the same index.
std::function< double(double, double)> ScalarField2D
std::pair< double, double > Point
std::unique_ptr< IFitBackend > make_minuit_backend()
Configuration object for ContourEngine.
ProfilerMode profile_backend
Backend used to profile nuisance/free parameters.
ProfilingMethod profiling_method
Profiling strategy used for non-displayed parameters.
ContourProgressCallback on_progress
Optional progress callback invoked during contour computation.
std::size_t y_id
Indices of the two fit parameters displayed on the contour axes.
std::optional< ContourAlgorithm > fallback_contour_method
Optional fallback algorithm if the primary fails.
ContourAlgorithm primary_contour_method
Primary contour extraction algorithm.
FitResult fr
Global fit result used for central values, uncertainties, and correlations.
Payload passed to contour progress callbacks.
std::size_t n_points
Number of points produced so far or in total.
std::string message
Optional human-readable status message.
double level
Contour level associated with the event.
ContourProgressEventType type
Event category.
double elapsed_seconds
Wall-clock time elapsed since computation start.
std::size_t n_paths
Number of paths produced so far or in total.
Input configuration for a two-dimensional contour extraction.
std::size_t resolution
Requested grid or sampling resolution.
std::array< fit_app::ParameterDefinition, 2 > p_defs
Parameter definitions for the two scanned axes.
std::array< double, 4 > bounds
Extraction domain as {xmin, xmax, ymin, ymax}.
double level
Target scalar-field level to extract.
Output of a contour extraction algorithm.
bool success
Whether extraction produced a valid contour.
std::set< Path > paths
Extracted contour paths.
double level
Level actually targeted by the extraction.
std::vector< double > p_hat_std
Standard deviations of the parameters of interest.
std::vector< double > p_hat
Maximum-likelihood estimates for parameters of interest.
RealMatrix p_hat_correlations
Correlation matrix for the parameters of interest.