File indexing completed on 2026-08-14 09:28:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef ROOT_Fit_Fitter
0012 #define ROOT_Fit_Fitter
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include "Fit/BinData.h"
0026 #include "Fit/FitConfig.h"
0027 #include "Fit/FitResult.h"
0028 #include "Fit/UnBinData.h"
0029 #include "Math/IParamFunction.h"
0030 #include "Math/WrappedFunction.h"
0031 #include "ROOT/EExecutionPolicy.hxx"
0032
0033 #include <memory>
0034
0035 namespace ROOT::Math {
0036
0037 class Minimizer;
0038
0039
0040 template <class FunctionType>
0041 class BasicFitMethodFunction;
0042
0043
0044 typedef BasicFitMethodFunction<ROOT::Math::IMultiGenFunction> FitMethodFunction;
0045 typedef BasicFitMethodFunction<ROOT::Math::IMultiGradFunction> FitMethodGradFunction;
0046
0047 }
0048
0049
0050
0051
0052
0053
0054 namespace ROOT::Fit {
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 class Fitter {
0079
0080 public:
0081
0082 typedef ROOT::Math::IParamMultiFunction IModelFunction;
0083 template <class T>
0084 using IModelFunctionTempl = ROOT::Math::IParamMultiFunctionTempl<T>;
0085 #ifdef R__HAS_STD_EXPERIMENTAL_SIMD
0086 typedef ROOT::Math::IParametricFunctionMultiDimTempl<ROOT::Double_v> IModelFunction_v;
0087 typedef ROOT::Math::IParamMultiGradFunctionTempl<ROOT::Double_v> IGradModelFunction_v;
0088 #else
0089 typedef ROOT::Math::IParamMultiFunction IModelFunction_v;
0090 typedef ROOT::Math::IParamMultiGradFunction IGradModelFunction_v;
0091 #endif
0092 typedef ROOT::Math::IParamMultiGradFunction IGradModelFunction;
0093 typedef ROOT::Math::IParamFunction IModel1DFunction;
0094 typedef ROOT::Math::IParamGradFunction IGradModel1DFunction;
0095
0096 typedef ROOT::Math::IMultiGenFunction BaseFunc;
0097 typedef ROOT::Math::IMultiGradFunction BaseGradFunc;
0098
0099
0100
0101
0102
0103 Fitter () {}
0104
0105
0106
0107
0108 Fitter (const std::shared_ptr<FitResult> & result);
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 virtual ~Fitter () {}
0119
0120
0121
0122
0123 Fitter(const Fitter &) = delete;
0124
0125
0126
0127
0128 Fitter & operator = (const Fitter &) = delete;
0129
0130
0131 public:
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141 template <class Data, class Function,
0142 class cond = typename std::enable_if<!(std::is_same<Function, ROOT::EExecutionPolicy>::value ||
0143 std::is_same<Function, int>::value),
0144 Function>::type>
0145 bool Fit(const Data &data, const Function &func,
0146 const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential)
0147 {
0148 SetFunction(func);
0149 return Fit(data, executionPolicy);
0150 }
0151
0152
0153
0154
0155
0156
0157
0158 bool Fit(const BinData & data, const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential) {
0159 return LeastSquareFit(data, executionPolicy);
0160 }
0161
0162
0163
0164
0165
0166 bool Fit(const std::shared_ptr<BinData> & data, const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential) {
0167 return LeastSquareFit(data, executionPolicy);
0168 }
0169
0170
0171
0172
0173 bool LeastSquareFit(const BinData & data, const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential) {
0174 SetData(data);
0175 return DoLeastSquareFit(executionPolicy);
0176 }
0177
0178
0179
0180 bool LeastSquareFit(const std::shared_ptr<BinData> & data, const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential) {
0181 SetData(data);
0182 return DoLeastSquareFit(executionPolicy);
0183 }
0184
0185
0186
0187
0188
0189 bool Fit(const UnBinData & data, bool extended = false, const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential) {
0190 return LikelihoodFit(data, extended, executionPolicy);
0191 }
0192
0193
0194
0195
0196 bool Fit(const std::shared_ptr<UnBinData> & data, bool extended = false, const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential) {
0197 return LikelihoodFit(data, extended, executionPolicy);
0198 }
0199
0200
0201
0202
0203
0204 bool LikelihoodFit(const BinData &data, bool extended = true,
0205 const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential) {
0206 SetData(data);
0207 return DoBinnedLikelihoodFit(extended, executionPolicy);
0208 }
0209
0210
0211
0212
0213 bool LikelihoodFit(const std::shared_ptr<BinData> &data, bool extended = true,
0214 const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential) {
0215 SetData(data);
0216 return DoBinnedLikelihoodFit(extended, executionPolicy);
0217 }
0218
0219
0220
0221
0222 bool LikelihoodFit(const UnBinData & data, bool extended = false, const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential) {
0223 SetData(data);
0224 return DoUnbinnedLikelihoodFit(extended, executionPolicy);
0225 }
0226
0227
0228
0229
0230 bool LikelihoodFit(const std::shared_ptr<UnBinData> & data, bool extended = false, const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential) {
0231 SetData(data);
0232 return DoUnbinnedLikelihoodFit(extended, executionPolicy);
0233 }
0234
0235
0236
0237
0238
0239 template < class Data , class Function>
0240 bool LikelihoodFit( const Data & data, const Function & func, bool extended) {
0241 SetFunction(func);
0242 return LikelihoodFit(data, extended);
0243 }
0244
0245
0246
0247
0248 bool LinearFit(const BinData & data) {
0249 SetData(data);
0250 return DoLinearFit();
0251 }
0252
0253
0254
0255 bool LinearFit(const std::shared_ptr<BinData> & data) {
0256 SetData(data);
0257 return DoLinearFit();
0258 }
0259
0260
0261
0262
0263
0264
0265
0266 template <class Function>
0267 bool FitFCN(unsigned int npar, Function & fcn, const double * params = nullptr, unsigned int dataSize = 0, int fitType = 0) {
0268 return DoSetFCN(false, ROOT::Math::WrappedMultiFunction<Function &>{fcn, npar}, params, dataSize, fitType) ? FitFCN() : false;
0269 }
0270
0271
0272
0273
0274
0275
0276
0277 template <class Function>
0278 bool SetFCN(unsigned int npar, Function & fcn, const double * params = nullptr, unsigned int dataSize = 0, int fitType = 0) {
0279 return DoSetFCN(false, ROOT::Math::WrappedMultiFunction<Function &>{fcn, npar}, params, dataSize, fitType);
0280 }
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295 bool FitFCN(const ROOT::Math::IMultiGenFunction &fcn, const double *params = nullptr, unsigned int dataSize = 0, int fitType = 0);
0296
0297
0298
0299
0300
0301 bool FitFCN(const ROOT::Math::FitMethodFunction & fcn, const double *params = nullptr);
0302
0303
0304
0305
0306
0307
0308 bool SetFCN(const ROOT::Math::IMultiGenFunction &fcn, const double *params = nullptr, unsigned int dataSize = 0, int fitType = 0);
0309
0310
0311
0312
0313
0314
0315
0316
0317 bool SetFCN(const ROOT::Math::IMultiGenFunction &fcn, const IModelFunction & func, const double *params = nullptr,
0318 unsigned int dataSize = 0, int fitType = 0);
0319
0320
0321
0322
0323
0324 bool SetFCN(const ROOT::Math::FitMethodFunction & fcn, const double *params = nullptr);
0325
0326
0327
0328
0329
0330 bool FitFCN(const ROOT::Math::FitMethodGradFunction & fcn, const double *params = nullptr);
0331
0332
0333
0334
0335
0336 bool SetFCN(const ROOT::Math::FitMethodGradFunction & fcn, const double *params = nullptr);
0337
0338
0339
0340
0341
0342
0343
0344 typedef void (* MinuitFCN_t )(int &npar, double *gin, double &f, double *u, int flag);
0345 bool FitFCN( MinuitFCN_t fcn, int npar = 0, const double *params = nullptr, unsigned int dataSize = 0, int fitType = 0);
0346
0347
0348
0349
0350
0351
0352 bool SetFCN( MinuitFCN_t fcn, int npar = 0, const double *params = nullptr, unsigned int dataSize = 0, int fitType = 0);
0353
0354
0355
0356
0357 bool FitFCN();
0358
0359
0360
0361
0362 bool EvalFCN();
0363
0364
0365
0366
0367
0368
0369
0370 void SetFunction(const IModelFunction & func, bool useGradient = false);
0371
0372
0373
0374
0375 #ifdef R__HAS_STD_EXPERIMENTAL_SIMD
0376 template <class NotCompileIfScalarBackend = std::enable_if<!(std::is_same<double, ROOT::Double_v>::value)>>
0377 void SetFunction(const IModelFunction_v &func, bool useGradient = false);
0378
0379 template <class NotCompileIfScalarBackend = std::enable_if<!(std::is_same<double, ROOT::Double_v>::value)>>
0380 void SetFunction(const IGradModelFunction_v &func, bool useGradient = true);
0381 #endif
0382
0383
0384
0385 void SetFunction(const IModel1DFunction & func, bool useGradient = false);
0386
0387
0388
0389
0390 void SetFunction(const IGradModelFunction & func, bool useGradient = true);
0391
0392
0393
0394 void SetFunction(const IGradModel1DFunction & func, bool useGradient = true);
0395
0396
0397
0398
0399
0400 const FitResult & Result() const {
0401 assert( fResult.get() );
0402 return *fResult;
0403 }
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413 bool CalculateHessErrors();
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423 bool CalculateMinosErrors();
0424
0425
0426
0427
0428 const FitConfig & Config() const { return fConfig; }
0429
0430
0431
0432
0433 FitConfig & Config() { return fConfig; }
0434
0435
0436
0437
0438
0439 bool IsBinFit() const { return fBinFit; }
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450 ROOT::Math::Minimizer * GetMinimizer() const { return fMinimizer.get(); }
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461 ROOT::Math::IMultiGenFunction * GetFCN() const {
0462 return fObjFunction.get();
0463 }
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474 bool ApplyWeightCorrection(const ROOT::Math::IMultiGenFunction & loglw2, bool minimizeW2L=false);
0475
0476
0477
0478 void SetNumberOfFitPoints(unsigned int npoints) {
0479 if (fExtObjFunction) fDataSize = npoints;
0480 if (!fResult->IsEmpty()) fResult->SetChi2AndNdf(-1,npoints);
0481 }
0482
0483
0484
0485
0486
0487 void SetFitType(int type) {
0488 if (fExtObjFunction) fFitType = type;
0489 }
0490
0491
0492 protected:
0493
0494
0495
0496 bool DoLeastSquareFit(const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential);
0497
0498 bool DoBinnedLikelihoodFit(bool extended = true, const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential);
0499
0500 bool DoUnbinnedLikelihoodFit( bool extended = false, const ROOT::EExecutionPolicy &executionPolicy = ROOT::EExecutionPolicy::kSequential);
0501
0502 bool DoLinearFit();
0503
0504 bool DoSetFCN(bool useExtFCN, const ROOT::Math::IMultiGenFunction &fcn, const double *params, unsigned int dataSize,
0505 int fitType);
0506
0507
0508 bool DoInitMinimizer();
0509
0510 template<class ObjFunc_t>
0511 bool DoMinimization(std::unique_ptr<ObjFunc_t> f, const ROOT::Math::IMultiGenFunction * chifunc = nullptr);
0512
0513 template<class ObjFunc_t>
0514 bool DoWeightMinimization(std::unique_ptr<ObjFunc_t> f, const ROOT::Math::IMultiGenFunction * chifunc = nullptr);
0515
0516 bool DoMinimization(const ROOT::Math::IMultiGenFunction * chifunc = nullptr);
0517
0518 void DoUpdateFitConfig();
0519
0520 bool DoUpdateMinimizerOptions(bool canDifferentMinim = true);
0521
0522 int GetNCallsFromFCN();
0523
0524
0525 template <class Data>
0526 void SetData(const std::shared_ptr<Data> & data) {
0527 fData = std::static_pointer_cast<Data>(data);
0528 }
0529
0530
0531 template <class Data>
0532 void SetData(const Data & data) {
0533 SetData(std::make_shared<Data>(data));
0534 }
0535
0536
0537
0538 template <class ObjFuncType>
0539 bool GetDataFromFCN() {
0540 if (const ObjFuncType *objfunc = dynamic_cast<const ObjFuncType *>(ObjFunction())) {
0541 fFunc = objfunc->ModelFunctionPtr();
0542 fData = objfunc->DataPtr();
0543 return true;
0544 }
0545 return false;
0546 }
0547
0548
0549
0550
0551 const ROOT::Math::IBaseFunctionMultiDimTempl<double> * ObjFunction() const {
0552
0553
0554 return fExtObjFunction ? fExtObjFunction : fObjFunction.get();
0555 }
0556
0557 private:
0558
0559 bool fUseGradient = false;
0560 bool fBinFit = false;
0561
0562
0563 int fFitType = 0;
0564 int fDataSize = 0;
0565 FitConfig fConfig;
0566 std::shared_ptr<IModelFunction_v> fFunc_v;
0567 std::shared_ptr<IModelFunction> fFunc;
0568 std::shared_ptr<ROOT::Fit::FitResult> fResult;
0569 std::shared_ptr<ROOT::Math::Minimizer> fMinimizer;
0570 std::shared_ptr<ROOT::Fit::FitData> fData;
0571 std::shared_ptr<ROOT::Math::IMultiGenFunction> fObjFunction;
0572 const ROOT::Math::IMultiGenFunction *fExtObjFunction = nullptr;
0573 };
0574
0575 #ifdef R__HAS_STD_EXPERIMENTAL_SIMD
0576 template <class NotCompileIfScalarBackend>
0577 void Fitter::SetFunction(const IModelFunction_v &func, bool useGradient)
0578 {
0579 fUseGradient = useGradient;
0580 if (fUseGradient) {
0581 const IGradModelFunction_v *gradFunc = dynamic_cast<const IGradModelFunction_v *>(&func);
0582 if (gradFunc) {
0583 SetFunction(*gradFunc, true);
0584 return;
0585 } else {
0586 MATH_WARN_MSG("Fitter::SetFunction",
0587 "Requested function does not provide gradient - use it as non-gradient function ");
0588 }
0589 }
0590
0591
0592
0593 fUseGradient = false;
0594 fFunc_v = std::shared_ptr<IModelFunction_v>(dynamic_cast<IModelFunction_v *>(func.Clone()));
0595 assert(fFunc_v);
0596
0597
0598 fConfig.CreateParamsSettings(*fFunc_v);
0599 fFunc.reset();
0600 }
0601
0602 template <class NotCompileIfScalarBackend>
0603 void Fitter::SetFunction(const IGradModelFunction_v &func, bool useGradient)
0604 {
0605 fUseGradient = useGradient;
0606
0607
0608 fFunc_v = std::shared_ptr<IModelFunction_v>(dynamic_cast<IGradModelFunction_v *>(func.Clone()));
0609 assert(fFunc_v);
0610
0611
0612 fConfig.CreateParamsSettings(*fFunc_v);
0613 fFunc.reset();
0614 }
0615 #endif
0616
0617 }
0618
0619 #endif