Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
FitHelpers.cxx
Go to the documentation of this file.
1/// \cond ROOFIT_INTERNAL
2
3/*
4 * Project: RooFit
5 * Authors:
6 * Jonas Rembser, CERN 2023
7 *
8 * Copyright (c) 2023, CERN
9 *
10 * Redistribution and use in source and binary forms,
11 * with or without modification, are permitted according to the terms
12 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
13 */
14
15#include "FitHelpers.h"
16
17#include <RooAbsData.h>
18#include <RooAbsPdf.h>
19#include <RooAbsReal.h>
20#include <RooAddition.h>
21#include <RooBatchCompute.h>
22#include <RooBinSamplingPdf.h>
23#include <RooCategory.h>
24#include <RooCmdConfig.h>
25#include <RooConstraintSum.h>
26#include <RooDataHist.h>
27#include <RooDataSet.h>
28#include <RooDerivative.h>
29#include <RooFit/Evaluator.h>
32#include <RooFitResult.h>
33#include <RooFuncWrapper.h>
34#include <RooLinkedList.h>
35#include <RooMinimizer.h>
36#include <RooRealVar.h>
37#include <RooSimultaneous.h>
38
39#include <Math/CholeskyDecomp.h>
40
41#include "ConstraintHelpers.h"
42#include "RooEvaluatorWrapper.h"
43#include "RooFitImplHelpers.h"
44#include "RooNLLVarNew.h"
45
46#ifdef ROOFIT_LEGACY_EVAL_BACKEND
47#include "RooChi2Var.h"
48#include "RooNLLVar.h"
49#include "RooXYChi2Var.h"
50#endif
51
52namespace {
53
54constexpr int extendedFitDefault = 2;
55
56////////////////////////////////////////////////////////////////////////////////
57/// Use the asymptotically correct approach to estimate errors in the presence of weights.
58/// This is slower but more accurate than `SumW2Error`. See also https://arxiv.org/abs/1911.01303).
59/// Applies the calculated covaraince matrix to the RooMinimizer and returns
60/// the quality of the covariance matrix.
61/// See also the documentation of RooAbsPdf::fitTo(), where this function is used.
62/// \param[in] minimizer The RooMinimizer to get the fit result from. The state
63/// of the minimizer will be altered by this function: the covariance
64/// matrix caltulated here will be applied to it via
65/// RooMinimizer::applyCovarianceMatrix().
66/// \param[in] data The dataset that was used for the fit.
67int calcAsymptoticCorrectedCovariance(RooAbsReal &pdf, RooMinimizer &minimizer, RooAbsData const &data)
68{
69 // Calculated corrected errors for weighted likelihood fits
70 std::unique_ptr<RooFitResult> rw(minimizer.save());
71 // Weighted inverse Hessian matrix
72 const TMatrixDSym &matV = rw->covarianceMatrix();
73 oocoutI(&pdf, Fitting)
74 << "RooAbsPdf::fitTo(" << pdf.GetName()
75 << ") Calculating covariance matrix according to the asymptotically correct approach. If you find this "
76 "method useful please consider citing https://arxiv.org/abs/1911.01303.\n";
77
78 // Initialise matrix containing first derivatives
79 int nFloatPars = rw->floatParsFinal().size();
80 TMatrixDSym num(nFloatPars);
81 for (int k = 0; k < nFloatPars; k++) {
82 for (int l = 0; l < nFloatPars; l++) {
83 num(k, l) = 0.0;
84 }
85 }
86 RooArgSet obs;
87 pdf.getObservables(data.get(), obs);
88 // Create derivative objects
89 std::vector<std::unique_ptr<RooDerivative>> derivatives;
90 const RooArgList &floated = rw->floatParsFinal();
91 std::unique_ptr<RooArgSet> floatingparams{
92 static_cast<RooArgSet *>(pdf.getParameters(data)->selectByAttrib("Constant", false))};
93 for (const auto paramresult : floated) {
94 auto paraminternal = static_cast<RooRealVar *>(floatingparams->find(*paramresult));
95 assert(floatingparams->find(*paramresult)->IsA() == RooRealVar::Class());
96 derivatives.emplace_back(pdf.derivative(*paraminternal, obs, 1));
97 }
98
99 // Loop over data
100 for (int j = 0; j < data.numEntries(); j++) {
101 // Sets obs to current data point, this is where the pdf will be evaluated
102 obs.assign(*data.get(j));
103 // Determine first derivatives
104 std::vector<double> diffs(floated.size(), 0.0);
105 for (std::size_t k = 0; k < floated.size(); k++) {
106 const auto paramresult = static_cast<RooRealVar *>(floated.at(k));
107 auto paraminternal = static_cast<RooRealVar *>(floatingparams->find(*paramresult));
108 // first derivative to parameter k at best estimate point for this measurement
109 double diff = derivatives[k]->getVal();
110 // need to reset to best fit point after differentiation
111 *paraminternal = paramresult->getVal();
112 diffs[k] = diff;
113 }
114 // Fill numerator matrix
115 double prob = pdf.getVal(&obs);
116 for (std::size_t k = 0; k < floated.size(); k++) {
117 for (std::size_t l = 0; l < floated.size(); l++) {
118 num(k, l) += data.weightSquared() * diffs[k] * diffs[l] / (prob * prob);
119 }
120 }
121 }
122 num.Similarity(matV);
123
124 // Propagate corrected errors to parameters objects
125 minimizer.applyCovarianceMatrix(num);
126
127 // The derivatives are found in RooFit and not with the minimizer (e.g.
128 // minuit), so the quality of the corrected covariance matrix corresponds to
129 // the quality of the original covariance matrix
130 return rw->covQual();
131}
132
133////////////////////////////////////////////////////////////////////////////////
134/// Apply correction to errors and covariance matrix. This uses two covariance
135/// matrices, one with the weights, the other with squared weights, to obtain
136/// the correct errors for weighted likelihood fits.
137/// Applies the calculated covaraince matrix to the RooMinimizer and returns
138/// the quality of the covariance matrix.
139/// See also the documentation of RooAbsPdf::fitTo(), where this function is used.
140/// \param[in] minimizer The RooMinimizer to get the fit result from. The state
141/// of the minimizer will be altered by this function: the covariance
142/// matrix caltulated here will be applied to it via
143/// RooMinimizer::applyCovarianceMatrix().
144/// \param[in] nll The NLL object that was used for the fit.
145int calcSumW2CorrectedCovariance(RooAbsReal const &pdf, RooMinimizer &minimizer, RooAbsReal &nll)
146{
147 // Calculated corrected errors for weighted likelihood fits
148 std::unique_ptr<RooFitResult> rw{minimizer.save()};
149 nll.applyWeightSquared(true);
150 oocoutI(&pdf, Fitting) << "RooAbsPdf::fitTo(" << pdf.GetName()
151 << ") Calculating sum-of-weights-squared correction matrix for covariance matrix\n";
152 minimizer.hesse();
153 std::unique_ptr<RooFitResult> rw2{minimizer.save()};
154 nll.applyWeightSquared(false);
155
156 // Apply correction matrix
157 const TMatrixDSym &matV = rw->covarianceMatrix();
158 TMatrixDSym matC = rw2->covarianceMatrix();
160 if (!decomp) {
161 oocoutE(&pdf, Fitting) << "RooAbsPdf::fitTo(" << pdf.GetName()
162 << ") ERROR: Cannot apply sum-of-weights correction to covariance matrix: correction "
163 "matrix calculated with weight-squared is singular\n";
164 return -1;
165 }
166
167 // replace C by its inverse
168 decomp.Invert(matC);
169 // the class lies about the matrix being symmetric, so fill in the
170 // part above the diagonal
171 for (int i = 0; i < matC.GetNrows(); ++i) {
172 for (int j = 0; j < i; ++j) {
173 matC(j, i) = matC(i, j);
174 }
175 }
176 matC.Similarity(matV);
177 // C now contains V C^-1 V
178 // Propagate corrected errors to parameters objects
179 minimizer.applyCovarianceMatrix(matC);
180
181 return std::min(rw->covQual(), rw2->covQual());
182}
183
184/// Configuration struct for RooAbsPdf::minimizeNLL with all the default values
185/// that also should be taked as the default values for RooAbsPdf::fitTo.
186struct MinimizerConfig {
187 double recoverFromNaN = 10.;
188 int optConst = 2;
189 int verbose = 0;
190 int doSave = 0;
191 int doTimer = 0;
192 int printLevel = 1;
193 int strategy = 1;
194 int initHesse = 0;
195 int hesse = 1;
196 int minos = 0;
197 int numee = 10;
198 int doEEWall = 1;
199 int doWarn = 1;
200 int doSumW2 = -1;
201 int doAsymptotic = -1;
202 int maxCalls = -1;
203 int doOffset = -1;
204 int parallelize = 0;
205 bool enableParallelGradient = true;
206 bool enableParallelDescent = false;
207 bool timingAnalysis = false;
208 const RooArgSet *minosSet = nullptr;
209 std::string minType;
210 std::string minAlg = "minuit";
211};
212
213bool interpretExtendedCmdArg(RooAbsPdf const &pdf, int extendedCmdArg)
214{
215 // Process automatic extended option
216 if (extendedCmdArg == extendedFitDefault) {
218 if (ext) {
219 oocoutI(&pdf, Minimization)
220 << "p.d.f. provides expected number of events, including extended term in likelihood." << std::endl;
221 }
222 return ext;
223 }
224 // If Extended(false) was explicitly set, but the pdf MUST be extended, then
225 // it's time to print an error. This happens when you're fitting a RooAddPdf
226 // with coefficient that represent yields, and without the additional
227 // constraint these coefficients are degenerate because the RooAddPdf
228 // normalizes itself. Nothing correct can come out of this.
229 if (extendedCmdArg == 0) {
231 std::string errMsg = "You used the Extended(false) option on a pdf where the fit MUST be extended! "
232 "The parameters are not well defined and you're getting nonsensical results.";
233 oocoutE(&pdf, InputArguments) << errMsg << std::endl;
234 }
235 }
236 return extendedCmdArg;
237}
238
239/// To set the fitrange attribute of the PDF and custom ranges for the
240/// observables so that RooPlot can automatically plot the fitting range.
241void resetFitrangeAttributes(RooAbsArg &pdf, RooAbsData const &data, std::string const &baseName, const char *rangeName,
242 bool splitRange)
243{
244 // Clear possible range attributes from previous fits.
245 pdf.removeStringAttribute("fitrange");
246
247 // No fitrange was specified, so we do nothing. Or "SplitRange" is used, and
248 // then there are no uniquely defined ranges for the observables (as they
249 // are different in each category).
250 if (!rangeName || splitRange)
251 return;
252
253 RooArgSet observables;
254 pdf.getObservables(data.get(), observables);
255
256 std::string fitrangeValue;
257 auto subranges = ROOT::Split(rangeName, ",");
258 for (auto const &subrange : subranges) {
259 if (subrange.empty())
260 continue;
261 std::string fitrangeValueSubrange = std::string("fit_") + baseName;
262 if (subranges.size() > 1) {
263 fitrangeValueSubrange += "_" + subrange;
264 }
265 fitrangeValue += fitrangeValueSubrange + ",";
266 for (RooAbsArg *arg : observables) {
267
268 if (arg->isCategory())
269 continue;
270 auto &observable = static_cast<RooRealVar &>(*arg);
271
272 observable.setRange(fitrangeValueSubrange.c_str(), observable.getMin(subrange.c_str()),
273 observable.getMax(subrange.c_str()));
274 }
275 }
276 pdf.setStringAttribute("fitrange", fitrangeValue.substr(0, fitrangeValue.size() - 1).c_str());
277}
278
279std::unique_ptr<RooAbsArg> createSimultaneousNLL(RooSimultaneous const &simPdf, bool isExtended,
280 std::string const &rangeName, RooFit::OffsetMode offset)
281{
282 RooAbsCategoryLValue const &simCat = simPdf.indexCat();
283
284 // Prepare the NLL terms for each component
285 RooArgList nllTerms;
286 for (auto const &catState : simCat) {
287 std::string const &catName = catState.first;
288 RooAbsCategory::value_type catIndex = catState.second;
289
290 // If the channel is not in the selected range of the category variable, we
291 // won't create an for NLL this channel.
292 if (!rangeName.empty()) {
293 // Only the RooCategory supports ranges, not the other
294 // RooAbsCategoryLValue-derived classes.
295 auto simCatAsRooCategory = dynamic_cast<RooCategory const *>(&simCat);
296 if (simCatAsRooCategory && !simCatAsRooCategory->isStateInRange(rangeName.c_str(), catIndex)) {
297 continue;
298 }
299 }
300
301 if (RooAbsPdf *pdf = simPdf.getPdf(catName.c_str())) {
302 auto name = std::string("nll_") + pdf->GetName();
303 std::unique_ptr<RooArgSet> observables(
304 static_cast<RooArgSet *>(std::unique_ptr<RooArgSet>(pdf->getVariables())->selectByAttrib("__obs__", true)));
305 auto nll = std::make_unique<RooNLLVarNew>(name.c_str(), name.c_str(), *pdf, *observables, isExtended, offset);
306 // Rename the special variables
307 nll->setPrefix(std::string("_") + catName + "_");
308 nllTerms.addOwned(std::move(nll));
309 }
310 }
311
312 for (auto *nll : static_range_cast<RooNLLVarNew *>(nllTerms)) {
313 nll->setSimCount(nllTerms.size());
314 }
315
316 // Time to sum the NLLs
317 auto nll = std::make_unique<RooAddition>("mynll", "mynll", nllTerms);
318 nll->addOwnedComponents(std::move(nllTerms));
319 return nll;
320}
321
322std::unique_ptr<RooAbsReal> createNLLNew(RooAbsPdf &pdf, RooAbsData &data, std::unique_ptr<RooAbsReal> &&constraints,
323 std::string const &rangeName, RooArgSet const &projDeps, bool isExtended,
324 double integrateOverBinsPrecision, RooFit::OffsetMode offset)
325{
326 if (constraints) {
327 // The computation graph for the constraints is very small, no need to do
328 // the tracking of clean and dirty nodes here.
329 constraints->setOperMode(RooAbsArg::ADirty);
330 }
331
332 RooArgSet observables;
333 pdf.getObservables(data.get(), observables);
334 observables.remove(projDeps, true, true);
335
336 oocxcoutI(&pdf, Fitting) << "RooAbsPdf::fitTo(" << pdf.GetName()
337 << ") fixing normalization set for coefficient determination to observables in data"
338 << "\n";
339 pdf.fixAddCoefNormalization(observables, false);
340
341 // Deal with the IntegrateBins argument
342 RooArgList binSamplingPdfs;
343 std::unique_ptr<RooAbsPdf> wrappedPdf = RooBinSamplingPdf::create(pdf, data, integrateOverBinsPrecision);
344 RooAbsPdf &finalPdf = wrappedPdf ? *wrappedPdf : pdf;
345 if (wrappedPdf) {
346 binSamplingPdfs.addOwned(std::move(wrappedPdf));
347 }
348 // Done dealing with the IntegrateBins option
349
350 RooArgList nllTerms;
351
352 auto simPdf = dynamic_cast<RooSimultaneous *>(&finalPdf);
353 if (simPdf) {
354 simPdf->wrapPdfsInBinSamplingPdfs(data, integrateOverBinsPrecision);
355 nllTerms.addOwned(createSimultaneousNLL(*simPdf, isExtended, rangeName, offset));
356 } else {
357 nllTerms.addOwned(
358 std::make_unique<RooNLLVarNew>("RooNLLVarNew", "RooNLLVarNew", finalPdf, observables, isExtended, offset));
359 }
360 if (constraints) {
361 nllTerms.addOwned(std::move(constraints));
362 }
363
364 std::string nllName = std::string("nll_") + pdf.GetName() + "_" + data.GetName();
365 auto nll = std::make_unique<RooAddition>(nllName.c_str(), nllName.c_str(), nllTerms);
366 nll->addOwnedComponents(std::move(binSamplingPdfs));
367 nll->addOwnedComponents(std::move(nllTerms));
368
369 return nll;
370}
371
372} // namespace
373
374namespace RooFit {
375namespace FitHelpers {
376
377void defineMinimizationOptions(RooCmdConfig &pc)
378{
379 // Default-initialized instance of MinimizerConfig to get the default
380 // minimizer parameter values.
381 MinimizerConfig minimizerDefaults;
382
383 pc.defineDouble("RecoverFromUndefinedRegions", "RecoverFromUndefinedRegions", 0, minimizerDefaults.recoverFromNaN);
384 pc.defineInt("optConst", "Optimize", 0, minimizerDefaults.optConst);
385 pc.defineInt("verbose", "Verbose", 0, minimizerDefaults.verbose);
386 pc.defineInt("doSave", "Save", 0, minimizerDefaults.doSave);
387 pc.defineInt("doTimer", "Timer", 0, minimizerDefaults.doTimer);
388 pc.defineInt("printLevel", "PrintLevel", 0, minimizerDefaults.printLevel);
389 pc.defineInt("strategy", "Strategy", 0, minimizerDefaults.strategy);
390 pc.defineInt("initHesse", "InitialHesse", 0, minimizerDefaults.initHesse);
391 pc.defineInt("hesse", "Hesse", 0, minimizerDefaults.hesse);
392 pc.defineInt("minos", "Minos", 0, minimizerDefaults.minos);
393 pc.defineInt("numee", "PrintEvalErrors", 0, minimizerDefaults.numee);
394 pc.defineInt("doEEWall", "EvalErrorWall", 0, minimizerDefaults.doEEWall);
395 pc.defineInt("doWarn", "Warnings", 0, minimizerDefaults.doWarn);
396 pc.defineInt("doSumW2", "SumW2Error", 0, minimizerDefaults.doSumW2);
397 pc.defineInt("doAsymptoticError", "AsymptoticError", 0, minimizerDefaults.doAsymptotic);
398 pc.defineInt("maxCalls", "MaxCalls", 0, minimizerDefaults.maxCalls);
399 pc.defineInt("doOffset", "OffsetLikelihood", 0, 0);
400 pc.defineInt("parallelize", "Parallelize", 0, 0); // Three parallelize arguments
401 pc.defineInt("enableParallelGradient", "ParallelGradientOptions", 0, 0);
402 pc.defineInt("enableParallelDescent", "ParallelDescentOptions", 0, 0);
403 pc.defineInt("timingAnalysis", "TimingAnalysis", 0, 0);
404 pc.defineString("mintype", "Minimizer", 0, minimizerDefaults.minType.c_str());
405 pc.defineString("minalg", "Minimizer", 1, minimizerDefaults.minAlg.c_str());
406 pc.defineSet("minosSet", "Minos", 0, minimizerDefaults.minosSet);
407}
408
409////////////////////////////////////////////////////////////////////////////////
410/// Minimizes a given NLL variable by finding the optimal parameters with the
411/// RooMinimzer. The NLL variable can be created with RooAbsPdf::createNLL.
412/// If you are looking for a function that combines likelihood creation with
413/// fitting, see RooAbsPdf::fitTo.
414/// \param[in] nll The negative log-likelihood variable to minimize.
415/// \param[in] data The dataset that was also used for the NLL. It's a necessary
416/// parameter because it is used in the asymptotic error correction.
417/// \param[in] cfg Configuration struct with all the configuration options for
418/// the RooMinimizer. These are a subset of the options that you can
419/// also pass to RooAbsPdf::fitTo via the RooFit command arguments.
420std::unique_ptr<RooFitResult> minimize(RooAbsReal &pdf, RooAbsReal &nll, RooAbsData const &data, RooCmdConfig const &pc)
421{
422 MinimizerConfig cfg;
423 cfg.recoverFromNaN = pc.getDouble("RecoverFromUndefinedRegions");
424 cfg.optConst = pc.getInt("optConst");
425 cfg.verbose = pc.getInt("verbose");
426 cfg.doSave = pc.getInt("doSave");
427 cfg.doTimer = pc.getInt("doTimer");
428 cfg.printLevel = pc.getInt("printLevel");
429 cfg.strategy = pc.getInt("strategy");
430 cfg.initHesse = pc.getInt("initHesse");
431 cfg.hesse = pc.getInt("hesse");
432 cfg.minos = pc.getInt("minos");
433 cfg.numee = pc.getInt("numee");
434 cfg.doEEWall = pc.getInt("doEEWall");
435 cfg.doWarn = pc.getInt("doWarn");
436 cfg.doSumW2 = pc.getInt("doSumW2");
437 cfg.doAsymptotic = pc.getInt("doAsymptoticError");
438 cfg.maxCalls = pc.getInt("maxCalls");
439 cfg.minosSet = pc.getSet("minosSet");
440 cfg.minType = pc.getString("mintype", "");
441 cfg.minAlg = pc.getString("minalg", "minuit");
442 cfg.doOffset = pc.getInt("doOffset");
443 cfg.parallelize = pc.getInt("parallelize");
444 cfg.enableParallelGradient = pc.getInt("enableParallelGradient");
445 cfg.enableParallelDescent = pc.getInt("enableParallelDescent");
446 cfg.timingAnalysis = pc.getInt("timingAnalysis");
447
448 // Determine if the dataset has weights
449 bool weightedData = data.isNonPoissonWeighted();
450
451 std::string msgPrefix = std::string{"RooAbsPdf::fitTo("} + pdf.GetName() + "): ";
452
453 // Warn user that a method to determine parameter uncertainties should be provided if weighted data is offered
454 if (weightedData && cfg.doSumW2 == -1 && cfg.doAsymptotic == -1) {
455 oocoutW(&pdf, InputArguments) << msgPrefix <<
456 R"(WARNING: a likelihood fit is requested of what appears to be weighted data.
457 While the estimated values of the parameters will always be calculated taking the weights into account,
458 there are multiple ways to estimate the errors of the parameters. You are advised to make an
459 explicit choice for the error calculation:
460 - Either provide SumW2Error(true), to calculate a sum-of-weights-corrected HESSE error matrix
461 (error will be proportional to the number of events in MC).
462 - Or provide SumW2Error(false), to return errors from original HESSE error matrix
463 (which will be proportional to the sum of the weights, i.e., a dataset with <sum of weights> events).
464 - Or provide AsymptoticError(true), to use the asymptotically correct expression
465 (for details see https://arxiv.org/abs/1911.01303)."
466)";
467 }
468
469 if (cfg.minos && (cfg.doSumW2 == 1 || cfg.doAsymptotic == 1)) {
470 oocoutE(&pdf, InputArguments)
471 << msgPrefix
472 << " sum-of-weights and asymptotic error correction do not work with MINOS errors. Not fitting.\n";
473 return nullptr;
474 }
475 if (cfg.doAsymptotic == 1 && cfg.minos) {
476 oocoutW(&pdf, InputArguments) << msgPrefix << "WARNING: asymptotic correction does not apply to MINOS errors\n";
477 }
478
479 // avoid setting both SumW2 and Asymptotic for uncertainty correction
480 if (cfg.doSumW2 == 1 && cfg.doAsymptotic == 1) {
481 oocoutE(&pdf, InputArguments) << msgPrefix
482 << "ERROR: Cannot compute both asymptotically correct and SumW2 errors.\n";
483 return nullptr;
484 }
485
486 // Instantiate RooMinimizer
487 RooMinimizer::Config minimizerConfig;
488 minimizerConfig.enableParallelGradient = cfg.enableParallelGradient;
489 minimizerConfig.enableParallelDescent = cfg.enableParallelDescent;
490 minimizerConfig.parallelize = cfg.parallelize;
491 minimizerConfig.timingAnalysis = cfg.timingAnalysis;
492 minimizerConfig.offsetting = cfg.doOffset;
493 RooMinimizer m(nll, minimizerConfig);
494
495 m.setMinimizerType(cfg.minType);
496 m.setEvalErrorWall(cfg.doEEWall);
497 m.setRecoverFromNaNStrength(cfg.recoverFromNaN);
498 m.setPrintEvalErrors(cfg.numee);
499 if (cfg.maxCalls > 0)
500 m.setMaxFunctionCalls(cfg.maxCalls);
501 if (cfg.printLevel != 1)
502 m.setPrintLevel(cfg.printLevel);
503 if (cfg.optConst)
504 m.optimizeConst(cfg.optConst); // Activate constant term optimization
505 if (cfg.verbose)
506 m.setVerbose(true); // Activate verbose options
507 if (cfg.doTimer)
508 m.setProfile(true); // Activate timer options
509 if (cfg.strategy != 1)
510 m.setStrategy(cfg.strategy); // Modify fit strategy
511 if (cfg.initHesse)
512 m.hesse(); // Initialize errors with hesse
513 m.minimize(cfg.minType.c_str(), cfg.minAlg.c_str()); // Minimize using chosen algorithm
514 if (cfg.hesse)
515 m.hesse(); // Evaluate errors with Hesse
516
517 int corrCovQual = -1;
518
519 if (m.getNPar() > 0) {
520 if (cfg.doAsymptotic == 1)
521 corrCovQual = calcAsymptoticCorrectedCovariance(pdf, m, data); // Asymptotically correct
522 if (cfg.doSumW2 == 1)
523 corrCovQual = calcSumW2CorrectedCovariance(pdf, m, nll);
524 }
525
526 if (cfg.minos)
527 cfg.minosSet ? m.minos(*cfg.minosSet) : m.minos(); // Evaluate errs with Minos
528
529 // Optionally return fit result
530 std::unique_ptr<RooFitResult> ret;
531 if (cfg.doSave) {
532 auto name = std::string("fitresult_") + pdf.GetName() + "_" + data.GetName();
533 auto title = std::string("Result of fit of p.d.f. ") + pdf.GetName() + " to dataset " + data.GetName();
534 ret = std::unique_ptr<RooFitResult>{m.save(name.c_str(), title.c_str())};
535 if ((cfg.doSumW2 == 1 || cfg.doAsymptotic == 1) && m.getNPar() > 0)
536 ret->setCovQual(corrCovQual);
537 }
538
539 if (cfg.optConst)
540 m.optimizeConst(0);
541 return ret;
542}
543
544std::unique_ptr<RooAbsReal> createNLL(RooAbsPdf &pdf, RooAbsData &data, const RooLinkedList &cmdList)
545{
546 auto baseName = std::string("nll_") + pdf.GetName() + "_" + data.GetName();
547
548 // Select the pdf-specific commands
549 RooCmdConfig pc("RooAbsPdf::createNLL(" + std::string(pdf.GetName()) + ")");
550
551 pc.defineString("rangeName", "RangeWithName", 0, "", true);
552 pc.defineString("addCoefRange", "SumCoefRange", 0, "");
553 pc.defineString("globstag", "GlobalObservablesTag", 0, "");
554 pc.defineString("globssource", "GlobalObservablesSource", 0, "data");
555 pc.defineDouble("rangeLo", "Range", 0, -999.);
556 pc.defineDouble("rangeHi", "Range", 1, -999.);
557 pc.defineInt("splitRange", "SplitRange", 0, 0);
558 pc.defineInt("ext", "Extended", 0, extendedFitDefault);
559 pc.defineInt("numcpu", "NumCPU", 0, 1);
560 pc.defineInt("interleave", "NumCPU", 1, 0);
561 pc.defineInt("verbose", "Verbose", 0, 0);
562 pc.defineInt("optConst", "Optimize", 0, 0);
563 pc.defineInt("cloneData", "CloneData", 0, 2);
564 pc.defineSet("projDepSet", "ProjectedObservables", 0, nullptr);
565 pc.defineSet("cPars", "Constrain", 0, nullptr);
566 pc.defineSet("glObs", "GlobalObservables", 0, nullptr);
567 pc.defineInt("doOffset", "OffsetLikelihood", 0, 0);
568 pc.defineSet("extCons", "ExternalConstraints", 0, nullptr);
569 pc.defineInt("EvalBackend", "EvalBackend", 0, static_cast<int>(RooFit::EvalBackend::defaultValue()));
570 pc.defineDouble("IntegrateBins", "IntegrateBins", 0, -1.);
571 pc.defineMutex("Range", "RangeWithName");
572 pc.defineMutex("GlobalObservables", "GlobalObservablesTag");
573 pc.defineInt("ModularL", "ModularL", 0, 0);
574
575 // New style likelihoods define parallelization through Parallelize(...) on fitTo or attributes on
576 // RooMinimizer::Config.
577 pc.defineMutex("ModularL", "NumCPU");
578
579 // New style likelihoods define offsetting on minimizer, not on likelihood
580 pc.defineMutex("ModularL", "OffsetLikelihood");
581
582 // Process and check varargs
583 pc.process(cmdList);
584 if (!pc.ok(true)) {
585 return nullptr;
586 }
587
588 if (pc.getInt("ModularL")) {
589 int lut[3] = {2, 1, 0};
591 static_cast<RooFit::TestStatistics::RooAbsL::Extended>(lut[pc.getInt("ext")])};
592
593 RooArgSet cParsSet;
594 RooArgSet extConsSet;
595 RooArgSet glObsSet;
596
597 if (auto tmp = pc.getSet("cPars"))
598 cParsSet.add(*tmp);
599
600 if (auto tmp = pc.getSet("extCons"))
601 extConsSet.add(*tmp);
602
603 if (auto tmp = pc.getSet("glObs"))
604 glObsSet.add(*tmp);
605
606 const std::string rangeName = pc.getString("globstag", "", false);
607
609 builder.Extended(ext)
610 .ConstrainedParameters(cParsSet)
611 .ExternalConstraints(extConsSet)
612 .GlobalObservables(glObsSet)
613 .GlobalObservablesTag(rangeName.c_str());
614
615 return std::make_unique<RooFit::TestStatistics::RooRealL>("likelihood", "", builder.build());
616 }
617
618 // Decode command line arguments
619 const char *rangeName = pc.getString("rangeName", nullptr, true);
620 const char *addCoefRangeName = pc.getString("addCoefRange", nullptr, true);
621 const bool ext = interpretExtendedCmdArg(pdf, pc.getInt("ext"));
622
623 int splitRange = pc.getInt("splitRange");
624 int optConst = pc.getInt("optConst");
625 int cloneData = pc.getInt("cloneData");
626 auto offset = static_cast<RooFit::OffsetMode>(pc.getInt("doOffset"));
627
628 // If no explicit cloneData command is specified, cloneData is set to true if optimization is activated
629 if (cloneData == 2) {
630 cloneData = optConst;
631 }
632
633 if (pc.hasProcessed("Range")) {
634 double rangeLo = pc.getDouble("rangeLo");
635 double rangeHi = pc.getDouble("rangeHi");
636
637 // Create range with name 'fit' with above limits on all observables
638 RooArgSet obs;
639 pdf.getObservables(data.get(), obs);
640 for (auto arg : obs) {
641 RooRealVar *rrv = dynamic_cast<RooRealVar *>(arg);
642 if (rrv)
643 rrv->setRange("fit", rangeLo, rangeHi);
644 }
645
646 // Set range name to be fitted to "fit"
647 rangeName = "fit";
648 }
649
650 // Set the fitrange attribute of th PDF, add observables ranges for plotting
651 resetFitrangeAttributes(pdf, data, baseName, rangeName, splitRange);
652
653 RooArgSet projDeps;
654 auto tmp = pc.getSet("projDepSet");
655 if (tmp) {
656 projDeps.add(*tmp);
657 }
658
659 const std::string globalObservablesSource = pc.getString("globssource", "data", false);
660 if (globalObservablesSource != "data" && globalObservablesSource != "model") {
661 std::string errMsg = "RooAbsPdf::fitTo: GlobalObservablesSource can only be \"data\" or \"model\"!";
662 oocoutE(&pdf, InputArguments) << errMsg << std::endl;
663 throw std::invalid_argument(errMsg);
664 }
665 const bool takeGlobalObservablesFromData = globalObservablesSource == "data";
666
667 // Lambda function to create the correct constraint term for a PDF. In old
668 // RooFit, we use this PDF itself as the argument, for the new BatchMode
669 // we're passing a clone.
670 auto createConstr = [&](bool removeConstraintsFromPdf = false) -> std::unique_ptr<RooAbsReal> {
671 return createConstraintTerm(baseName + "_constr", // name
672 pdf, // pdf
673 data, // data
674 pc.getSet("cPars"), // Constrain RooCmdArg
675 pc.getSet("extCons"), // ExternalConstraints RooCmdArg
676 pc.getSet("glObs"), // GlobalObservables RooCmdArg
677 pc.getString("globstag", nullptr, true), // GlobalObservablesTag RooCmdArg
678 takeGlobalObservablesFromData, // From GlobalObservablesSource RooCmdArg
679 removeConstraintsFromPdf);
680 };
681
682 auto evalBackend = static_cast<RooFit::EvalBackend::Value>(pc.getInt("EvalBackend"));
683
684 // Construct BatchModeNLL if requested
685 if (evalBackend != RooFit::EvalBackend::Value::Legacy) {
686
687 // Set the normalization range. We need to do it now, because it will be
688 // considered in `compileForNormSet`.
689 std::string oldNormRange;
690 if (pdf.normRange()) {
691 oldNormRange = pdf.normRange();
692 }
693 pdf.setNormRange(rangeName);
694
695 RooArgSet normSet;
696 pdf.getObservables(data.get(), normSet);
697 normSet.remove(projDeps, true, true);
698
699 pdf.setAttribute("SplitRange", splitRange);
700 pdf.setStringAttribute("RangeName", rangeName);
701
703 ctx.setLikelihoodMode(true);
704 std::unique_ptr<RooAbsArg> head = pdf.compileForNormSet(normSet, ctx);
705 std::unique_ptr<RooAbsPdf> pdfClone = std::unique_ptr<RooAbsPdf>{static_cast<RooAbsPdf *>(head.release())};
706
707 // reset attributes
708 pdf.setAttribute("SplitRange", false);
709 pdf.setStringAttribute("RangeName", nullptr);
710
711 // Reset the normalization range
712 pdf.setNormRange(oldNormRange.c_str());
713
714 if (addCoefRangeName) {
715 oocxcoutI(&pdf, Fitting) << "RooAbsPdf::fitTo(" << pdf.GetName()
716 << ") fixing interpretation of coefficients of any component to range "
717 << addCoefRangeName << "\n";
718 pdfClone->fixAddCoefRange(addCoefRangeName, false);
719 }
720
721 std::unique_ptr<RooAbsReal> compiledConstr;
722 if (std::unique_ptr<RooAbsReal> constr = createConstr()) {
723 compiledConstr = RooFit::Detail::compileForNormSet(*constr, *data.get());
724 compiledConstr->addOwnedComponents(std::move(constr));
725 }
726
727 auto nll = createNLLNew(*pdfClone, data, std::move(compiledConstr), rangeName ? rangeName : "", projDeps, ext,
728 pc.getDouble("IntegrateBins"), offset);
729
730 std::unique_ptr<RooAbsReal> nllWrapper;
731
732 if (evalBackend == RooFit::EvalBackend::Value::Codegen ||
734 bool createGradient = evalBackend == RooFit::EvalBackend::Value::Codegen;
735 auto simPdf = dynamic_cast<RooSimultaneous const *>(pdfClone.get());
736 nllWrapper = std::make_unique<RooFit::Experimental::RooFuncWrapper>("nll_func_wrapper", "nll_func_wrapper",
737 *nll, &data, simPdf, true);
738 if (createGradient)
739 static_cast<Experimental::RooFuncWrapper &>(*nllWrapper).createGradient();
740 } else {
741 nllWrapper = std::make_unique<RooEvaluatorWrapper>(
742 *nll, &data, evalBackend == RooFit::EvalBackend::Value::Cuda, rangeName ? rangeName : "", pdfClone.get(),
743 takeGlobalObservablesFromData);
744 }
745
746 nllWrapper->addOwnedComponents(std::move(nll));
747 nllWrapper->addOwnedComponents(std::move(pdfClone));
748 return nllWrapper;
749 }
750
751 std::unique_ptr<RooAbsReal> nll;
752
753#ifdef ROOFIT_LEGACY_EVAL_BACKEND
754 bool verbose = pc.getInt("verbose");
755
756 int numcpu = pc.getInt("numcpu");
757 int numcpu_strategy = pc.getInt("interleave");
758 // strategy 3 works only for RooSimultaneous.
759 if (numcpu_strategy == 3 && !pdf.InheritsFrom("RooSimultaneous")) {
760 oocoutW(&pdf, Minimization) << "Cannot use a NumCpu Strategy = 3 when the pdf is not a RooSimultaneous, "
761 "falling back to default strategy = 0"
762 << std::endl;
763 numcpu_strategy = 0;
764 }
765 RooFit::MPSplit interl = (RooFit::MPSplit)numcpu_strategy;
766
767 auto binnedLInfo = RooHelpers::getBinnedL(pdf);
768 RooAbsPdf &actualPdf = binnedLInfo.binnedPdf ? *binnedLInfo.binnedPdf : pdf;
769
770 // Construct NLL
773 cfg.addCoefRangeName = addCoefRangeName ? addCoefRangeName : "";
774 cfg.nCPU = numcpu;
775 cfg.interleave = interl;
776 cfg.verbose = verbose;
777 cfg.splitCutRange = static_cast<bool>(splitRange);
778 cfg.cloneInputData = static_cast<bool>(cloneData);
779 cfg.integrateOverBinsPrecision = pc.getDouble("IntegrateBins");
780 cfg.binnedL = binnedLInfo.isBinnedL;
781 cfg.takeGlobalObservablesFromData = takeGlobalObservablesFromData;
782 cfg.rangeName = rangeName ? rangeName : "";
783 auto nllVar = std::make_unique<RooNLLVar>(baseName.c_str(), "-log(likelihood)", actualPdf, data, projDeps, ext, cfg);
784 nllVar->enableBinOffsetting(offset == RooFit::OffsetMode::Bin);
785 nll = std::move(nllVar);
787
788 // Include constraints, if any, in likelihood
789 if (std::unique_ptr<RooAbsReal> constraintTerm = createConstr()) {
790
791 // Even though it is technically only required when the computation graph
792 // is changed because global observables are taken from data, it is safer
793 // to clone the constraint model in general to reset the normalization
794 // integral caches and avoid ASAN build failures (the PDF of the main
795 // measurement is cloned too anyway, so not much overhead). This can be
796 // reconsidered after the caching of normalization sets by pointer is changed
797 // to a more memory-safe solution.
798 constraintTerm = RooHelpers::cloneTreeWithSameParameters(*constraintTerm, data.get());
799
800 // Redirect the global observables to the ones from the dataset if applicable.
801 constraintTerm->setData(data, false);
802
803 // The computation graph for the constraints is very small, no need to do
804 // the tracking of clean and dirty nodes here.
805 constraintTerm->setOperMode(RooAbsArg::ADirty);
806
807 auto orignll = std::move(nll);
808 nll = std::make_unique<RooAddition>((baseName + "_with_constr").c_str(), "nllWithCons",
809 RooArgSet(*orignll, *constraintTerm));
810 nll->addOwnedComponents(std::move(orignll), std::move(constraintTerm));
811 }
812
813 if (optConst) {
814 nll->constOptimizeTestStatistic(RooAbsArg::Activate, optConst > 1);
815 }
816
818 nll->enableOffsetting(true);
819 }
820#else
821 throw std::runtime_error("RooFit was not built with the legacy evaluation backend");
822#endif
823
824 return nll;
825}
826
827std::unique_ptr<RooAbsReal> createChi2(RooAbsReal &real, RooAbsData &data, const RooLinkedList &cmdList)
828{
829#ifdef ROOFIT_LEGACY_EVAL_BACKEND
830 const bool isDataHist = dynamic_cast<RooDataHist const *>(&data);
831
832 RooCmdConfig pc("createChi2(" + std::string(real.GetName()) + ")");
833
834 pc.defineInt("numcpu", "NumCPU", 0, 1);
835 pc.defineInt("verbose", "Verbose", 0, 0);
836
838
839 if (isDataHist) {
840 // Construct Chi2
842 std::string baseName = "chi2_" + std::string(real.GetName()) + "_" + data.GetName();
843
844 // Clear possible range attributes from previous fits.
845 real.removeStringAttribute("fitrange");
846
847 pc.defineInt("etype", "DataError", 0, (Int_t)RooDataHist::Auto);
848 pc.defineInt("extended", "Extended", 0, extendedFitDefault);
849 pc.defineInt("split_range", "SplitRange", 0, 0);
850 pc.defineDouble("integrate_bins", "IntegrateBins", 0, -1);
851 pc.defineString("addCoefRange", "SumCoefRange", 0, "");
852 pc.allowUndefined();
853
854 pc.process(cmdList);
855 if (!pc.ok(true)) {
856 return nullptr;
857 }
858
859 bool extended = false;
860 if (auto pdf = dynamic_cast<RooAbsPdf const *>(&real)) {
861 extended = interpretExtendedCmdArg(*pdf, pc.getInt("extended"));
862 }
863
864 RooDataHist::ErrorType etype = static_cast<RooDataHist::ErrorType>(pc.getInt("etype"));
865
866 const char *rangeName = pc.getString("rangeName", nullptr, true);
867 const char *addCoefRangeName = pc.getString("addCoefRange", nullptr, true);
868
869 cfg.rangeName = rangeName ? rangeName : "";
870 cfg.nCPU = pc.getInt("numcpu");
872 cfg.verbose = static_cast<bool>(pc.getInt("verbose"));
873 cfg.cloneInputData = false;
874 cfg.integrateOverBinsPrecision = pc.getDouble("integrate_bins");
875 cfg.addCoefRangeName = addCoefRangeName ? addCoefRangeName : "";
876 cfg.splitCutRange = static_cast<bool>(pc.getInt("split_range"));
877 auto chi2 = std::make_unique<RooChi2Var>(baseName.c_str(), baseName.c_str(), real,
878 static_cast<RooDataHist &>(data), extended, etype, cfg);
879
881
882 return chi2;
883 } else {
884 pc.defineInt("integrate", "Integrate", 0, 0);
885 pc.defineObject("yvar", "YVar", 0, nullptr);
886 pc.defineString("rangeName", "RangeWithName", 0, "", true);
887 pc.defineInt("interleave", "NumCPU", 1, 0);
888
889 // Process and check varargs
890 pc.process(cmdList);
891 if (!pc.ok(true)) {
892 return nullptr;
893 }
894
895 // Decode command line arguments
896 bool integrate = pc.getInt("integrate");
897 RooRealVar *yvar = static_cast<RooRealVar *>(pc.getObject("yvar"));
898 const char *rangeName = pc.getString("rangeName", nullptr, true);
899 Int_t numcpu = pc.getInt("numcpu");
900 Int_t numcpu_strategy = pc.getInt("interleave");
901 // strategy 3 works only for RooSimultaneous.
902 if (numcpu_strategy == 3 && !real.InheritsFrom("RooSimultaneous")) {
903 oocoutW(&real, Minimization) << "Cannot use a NumCpu Strategy = 3 when the pdf is not a RooSimultaneous, "
904 "falling back to default strategy = 0"
905 << std::endl;
906 numcpu_strategy = 0;
907 }
908 RooFit::MPSplit interl = (RooFit::MPSplit)numcpu_strategy;
909 bool verbose = pc.getInt("verbose");
910
911 cfg.rangeName = rangeName ? rangeName : "";
912 cfg.nCPU = numcpu;
913 cfg.interleave = interl;
914 cfg.verbose = verbose;
915 cfg.verbose = false;
916
917 std::string name = "chi2_" + std::string(real.GetName()) + "_" + data.GetName();
918
919 return std::make_unique<RooXYChi2Var>(name.c_str(), name.c_str(), real, static_cast<RooDataSet &>(data), yvar,
920 integrate, cfg);
921 }
922#else
923 throw std::runtime_error("createChi2() is not supported without the legacy evaluation backend");
924 return nullptr;
925#endif
926}
927
928std::unique_ptr<RooFitResult> fitTo(RooAbsReal &real, RooAbsData &data, const RooLinkedList &cmdList, bool chi2)
929{
930 const bool isDataHist = dynamic_cast<RooDataHist const *>(&data);
931
932 RooCmdConfig pc("fitTo(" + std::string(real.GetName()) + ")");
933
934 RooLinkedList fitCmdList(cmdList);
935 std::string nllCmdListString;
936 if (!chi2) {
937 nllCmdListString = "ProjectedObservables,Extended,Range,"
938 "RangeWithName,SumCoefRange,NumCPU,SplitRange,Constrained,Constrain,ExternalConstraints,"
939 "CloneData,GlobalObservables,GlobalObservablesSource,GlobalObservablesTag,"
940 "EvalBackend,IntegrateBins,ModularL";
941
942 if (!cmdList.FindObject("ModularL") || static_cast<RooCmdArg *>(cmdList.FindObject("ModularL"))->getInt(0) == 0) {
943 nllCmdListString += ",OffsetLikelihood";
944 }
945 } else {
946 auto createChi2DataHistCmdArgs = "Range,RangeWithName,NumCPU,Optimize,IntegrateBins,ProjectedObservables,"
947 "AddCoefRange,SplitRange,DataError,Extended";
948 auto createChi2DataSetCmdArgs = "YVar,Integrate,RangeWithName,NumCPU,Verbose";
949 nllCmdListString += isDataHist ? createChi2DataHistCmdArgs : createChi2DataSetCmdArgs;
950 }
951
952 RooLinkedList nllCmdList = pc.filterCmdList(fitCmdList, nllCmdListString.c_str());
953
954 pc.defineDouble("prefit", "Prefit", 0, 0);
955 defineMinimizationOptions(pc);
956
957 // Process and check varargs
958 pc.process(fitCmdList);
959 if (!pc.ok(true)) {
960 return nullptr;
961 }
962
963 // TimingAnalysis works only for RooSimultaneous.
964 if (pc.getInt("timingAnalysis") && !real.InheritsFrom("RooSimultaneous")) {
965 oocoutW(&real, Minimization) << "The timingAnalysis feature was built for minimization with RooSimultaneous "
966 "and is not implemented for other PDF's. Please create a RooSimultaneous to "
967 "enable this feature."
968 << std::endl;
969 }
970
971 // Decode command line arguments
972 double prefit = pc.getDouble("prefit");
973
974 if (prefit != 0) {
975 size_t nEvents = static_cast<size_t>(prefit * data.numEntries());
976 if (prefit > 0.5 || nEvents < 100) {
977 oocoutW(&real, InputArguments) << "PrefitDataFraction should be in suitable range."
978 << "With the current PrefitDataFraction=" << prefit
979 << ", the number of events would be " << nEvents << " out of "
980 << data.numEntries() << ". Skipping prefit..." << std::endl;
981 } else {
982 size_t step = data.numEntries() / nEvents;
983
984 RooDataSet tiny("tiny", "tiny", *data.get(), data.isWeighted() ? RooFit::WeightVar() : RooCmdArg());
985
986 for (int i = 0; i < data.numEntries(); i += step) {
987 const RooArgSet *event = data.get(i);
988 tiny.add(*event, data.weight());
989 }
990 RooLinkedList tinyCmdList(cmdList);
991 pc.filterCmdList(tinyCmdList, "Prefit,Hesse,Minos,Verbose,Save,Timer");
992 RooCmdArg hesse_option = RooFit::Hesse(false);
993 RooCmdArg print_option = RooFit::PrintLevel(-1);
994
995 tinyCmdList.Add(&hesse_option);
996 tinyCmdList.Add(&print_option);
997
998 fitTo(real, tiny, tinyCmdList, chi2);
999 }
1000 }
1001
1002 RooCmdArg modularL_option;
1003 if (pc.getInt("parallelize") != 0 || pc.getInt("enableParallelGradient") || pc.getInt("enableParallelDescent")) {
1004 // Set to new style likelihood if parallelization is requested
1005 modularL_option = RooFit::ModularL(true);
1006 nllCmdList.Add(&modularL_option);
1007 }
1008
1009 std::unique_ptr<RooAbsReal> nll;
1010 if (chi2) {
1011 nll = std::unique_ptr<RooAbsReal>{isDataHist ? real.createChi2(static_cast<RooDataHist &>(data), nllCmdList)
1012 : real.createChi2(static_cast<RooDataSet &>(data), nllCmdList)};
1013 } else {
1014 nll = std::unique_ptr<RooAbsReal>{dynamic_cast<RooAbsPdf &>(real).createNLL(data, nllCmdList)};
1015 }
1016
1017 return RooFit::FitHelpers::minimize(real, *nll, data, pc);
1018}
1019
1020} // namespace FitHelpers
1021} // namespace RooFit
1022
1023/// \endcond
header file containing the templated implementation of matrix inversion routines for use with ROOT's ...
std::unique_ptr< RooAbsReal > createConstraintTerm(std::string const &name, RooAbsPdf const &pdf, RooAbsData const &data, RooArgSet const *constrainedParameters, RooArgSet const *externalConstraints, RooArgSet const *globalObservables, const char *globalObservablesTag, bool takeGlobalObservablesFromData, bool removeConstraintsFromPdf)
Create the parameter constraint sum to add to the negative log-likelihood.
ROOT::RRangeCast< T, false, Range_t > static_range_cast(Range_t &&coll)
#define oocoutW(o, a)
#define oocoutE(o, a)
#define oocoutI(o, a)
#define oocxcoutI(o, a)
int Int_t
Definition RtypesCore.h:45
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
char name[80]
Definition TGX11.cxx:110
class to compute the Cholesky decomposition of a matrix
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
void setOperMode(OperMode mode, bool recurseADirty=true)
Set the operation mode of this node.
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
RooFit::OwningPtr< RooArgSet > getParameters(const RooAbsData *data, bool stripDisconnected=true) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
RooFit::OwningPtr< RooArgSet > getObservables(const RooArgSet &set, bool valueOnly=true) const
Given a set of possible observables, return the observables that this PDF depends on.
bool addOwnedComponents(const RooAbsCollection &comps)
Take ownership of the contents of 'comps'.
void removeStringAttribute(const Text_t *key)
Delete a string attribute with a given key.
RooFit::OwningPtr< RooArgSet > getVariables(bool stripDisconnected=true) const
Return RooArgSet with all variables (tree leaf nodes of expression tree)
virtual void applyWeightSquared(bool flag)
Disables or enables the usage of squared weights.
void setAttribute(const Text_t *name, bool value=true)
Set (default) or clear a named boolean attribute of this object.
Abstract base class for objects that represent a discrete value that can be set from the outside,...
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
void assign(const RooAbsCollection &other) const
Sets the value, cache and constant attribute of any argument in our set that also appears in the othe...
Storage_t::size_type size() const
RooAbsArg * first() const
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:57
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const override
void setNormRange(const char *rangeName)
@ CanBeExtended
Definition RooAbsPdf.h:213
@ MustBeExtended
Definition RooAbsPdf.h:213
const char * normRange() const
Definition RooAbsPdf.h:251
virtual ExtendMode extendMode() const
Returns ability of PDF to provide extended likelihood terms.
Definition RooAbsPdf.h:217
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
virtual void fixAddCoefNormalization(const RooArgSet &addNormSet=RooArgSet(), bool force=true)
Fix the interpretation of the coefficient of any RooAddPdf component in the expression tree headed by...
RooDerivative * derivative(RooRealVar &obs, Int_t order=1, double eps=0.001)
Return function representing first, second or third order derivative of this function.
static void setEvalErrorLoggingMode(ErrorLoggingMode m)
Set evaluation error logging mode.
virtual RooFit::OwningPtr< RooAbsReal > createChi2(RooDataHist &data, const RooLinkedList &cmdList)
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition RooArgList.h:110
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:55
static std::unique_ptr< RooAbsPdf > create(RooAbsPdf &pdf, RooAbsData const &data, double precision)
Creates a wrapping RooBinSamplingPdf if appropriate.
Object to represent discrete states.
Definition RooCategory.h:28
Named container for two doubles, two integers two object points and three string pointers that can be...
Definition RooCmdArg.h:26
Int_t getInt(Int_t idx) const
Definition RooCmdArg.h:86
Configurable parser for RooCmdArg named arguments.
void defineMutex(const char *head, Args_t &&... tail)
Define arguments where any pair is mutually exclusive.
bool process(const RooCmdArg &arg)
Process given RooCmdArg.
bool hasProcessed(const char *cmdName) const
Return true if RooCmdArg with name 'cmdName' has been processed.
double getDouble(const char *name, double defaultValue=0.0) const
Return double property registered with name 'name'.
bool defineDouble(const char *name, const char *argName, int doubleNum, double defValue=0.0)
Define double property name 'name' mapped to double in slot 'doubleNum' in RooCmdArg with name argNam...
RooArgSet * getSet(const char *name, RooArgSet *set=nullptr) const
Return RooArgSet property registered with name 'name'.
bool defineSet(const char *name, const char *argName, int setNum, const RooArgSet *set=nullptr)
Define TObject property name 'name' mapped to object in slot 'setNum' in RooCmdArg with name argName ...
bool ok(bool verbose) const
Return true of parsing was successful.
bool defineObject(const char *name, const char *argName, int setNum, const TObject *obj=nullptr, bool isArray=false)
Define TObject property name 'name' mapped to object in slot 'setNum' in RooCmdArg with name argName ...
const char * getString(const char *name, const char *defaultValue="", bool convEmptyToNull=false) const
Return string property registered with name 'name'.
bool defineString(const char *name, const char *argName, int stringNum, const char *defValue="", bool appendMode=false)
Define double property name 'name' mapped to double in slot 'stringNum' in RooCmdArg with name argNam...
bool defineInt(const char *name, const char *argName, int intNum, int defValue=0)
Define integer property name 'name' mapped to integer in slot 'intNum' in RooCmdArg with name argName...
void allowUndefined(bool flag=true)
If flag is true the processing of unrecognized RooCmdArgs is not considered an error.
int getInt(const char *name, int defaultValue=0) const
Return integer property registered with name 'name'.
RooLinkedList filterCmdList(RooLinkedList &cmdInList, const char *cmdNameList, bool removeFromInList=true) const
Utility function to filter commands listed in cmdNameList from cmdInList.
TObject * getObject(const char *name, TObject *obj=nullptr) const
Return TObject property registered with name 'name'.
Container class to hold N-dimensional binned data.
Definition RooDataHist.h:39
Container class to hold unbinned data.
Definition RooDataSet.h:57
static Value & defaultValue()
Collection class for internal use, storing a collection of RooAbsArg pointers in a doubly linked list...
virtual void Add(TObject *arg)
TObject * FindObject(const char *name) const override
Return pointer to object with given name.
Wrapper class around ROOT::Fit:Fitter that provides a seamless interface between the minimizer functi...
RooFit::OwningPtr< RooFitResult > save(const char *name=nullptr, const char *title=nullptr)
Save and return a RooFitResult snapshot of current minimizer status.
int hesse()
Execute HESSE.
void applyCovarianceMatrix(TMatrixDSym const &V)
Apply results of given external covariance matrix.
Variable that can be changed from the outside.
Definition RooRealVar.h:37
static TClass * Class()
void setRange(const char *name, double min, double max)
Set a fit or plotting range.
Facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
RooAbsPdf * getPdf(RooStringView catName) const
Return the p.d.f associated with the given index category name.
void wrapPdfsInBinSamplingPdfs(RooAbsData const &data, double precision)
Wraps the components of this RooSimultaneous in RooBinSamplingPdfs.
const RooAbsCategoryLValue & indexCat() const
Int_t GetNrows() const
TMatrixTSym< Element > & Similarity(const TMatrixT< Element > &n)
Calculate B * (*this) * B^T , final matrix will be (nrowsb x nrowsb) This is a similarity transform w...
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:525
RooCmdArg WeightVar(const char *name="weight", bool reinterpretAsWeight=false)
RooCmdArg Hesse(bool flag=true)
RooCmdArg ModularL(bool flag=false)
RooCmdArg PrintLevel(Int_t code)
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
std::unique_ptr< T > compileForNormSet(T const &arg, RooArgSet const &normSet)
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition JSONIO.h:26
OffsetMode
For setting the offset mode with the Offset() command argument to RooAbsPdf::fitTo()
std::unique_ptr< T > cloneTreeWithSameParameters(T const &arg, RooArgSet const *observables=nullptr)
Clone RooAbsArg object and reattach to original parameters.
BinnedLOutput getBinnedL(RooAbsPdf const &pdf)
std::string rangeName
Stores the configuration parameters for RooAbsTestStatistic.
Config argument to RooMinimizer constructor.
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4