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