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