File indexing completed on 2025-02-23 03:35:12
0001 /* 0002 File : XYFitCurve.h 0003 Project : LabPlot 0004 Description : A xy-curve defined by a fit model 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2014-2021 Alexander Semke <alexander.semke@web.de> 0007 SPDX-FileCopyrightText: 2016-2022 Stefan Gerlach <stefan.gerlach@uni.kn> 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #ifndef XYFITCURVE_H 0012 #define XYFITCURVE_H 0013 0014 #include "backend/lib/Range.h" 0015 #include "backend/worksheet/plots/cartesian/XYAnalysisCurve.h" 0016 0017 extern "C" { 0018 #include "backend/nsl/nsl_fit.h" 0019 } 0020 0021 class XYFitCurvePrivate; 0022 class Histogram; 0023 0024 #ifdef SDK 0025 #include "labplot_export.h" 0026 class LABPLOT_EXPORT XYFitCurve : public XYAnalysisCurve { 0027 #else 0028 class XYFitCurve : public XYAnalysisCurve { 0029 #endif 0030 Q_OBJECT 0031 0032 public: 0033 struct FitData { 0034 FitData() { 0035 } 0036 0037 nsl_fit_model_category modelCategory{nsl_fit_model_basic}; 0038 int modelType{0}; 0039 nsl_fit_weight_type xWeightsType{nsl_fit_weight_no}; 0040 nsl_fit_weight_type yWeightsType{nsl_fit_weight_no}; 0041 int degree{1}; 0042 QString model; 0043 QStringList paramNames; 0044 QStringList paramNamesUtf8; // Utf8 version of paramNames 0045 QVector<double> paramStartValues; 0046 QVector<double> paramLowerLimits; 0047 QVector<double> paramUpperLimits; 0048 QVector<bool> paramFixed; 0049 nsl_fit_algorithm algorithm{nsl_fit_algorithm_lm}; 0050 0051 int maxIterations{500}; 0052 double eps{1.e-4}; 0053 size_t evaluatedPoints{1000}; 0054 bool useDataErrors{true}; // use given data errors when fitting (default) 0055 bool useResults{true}; // use results as new start values (default) 0056 bool previewEnabled{true}; // preview fit function with given start parameters 0057 double confidenceInterval{95.}; // confidence interval for fit result 0058 0059 bool autoRange{true}; // use all data points? (default) 0060 bool autoEvalRange{true}; // evaluate fit function on full data range (default) 0061 Range<double> fitRange{0., 0.}; // x range of data to fit 0062 Range<double> evalRange{0., 0.}; // x range to evaluate fit function 0063 }; 0064 0065 struct FitResult : public XYAnalysisCurve::Result { 0066 FitResult() { 0067 } 0068 void calculateResult(size_t n, unsigned int np); // calculate depending results (uses dof, sse, sst) 0069 0070 int iterations{0}; 0071 double dof{0}; // degrees of freedom 0072 // residuals: r_i = y_i - Y_i 0073 double sse{0}; // sum of squared errors (SSE) / residual sum of squares (RSS) / sum of sq. residuals (SSR) / S = chi^2 = \sum_i^n r_i^2 0074 double sst{0}; // total sum of squares (SST) = \sum_i^n (y_i - <y>)^2 0075 double rms{0}; // residual mean square / reduced chi^2 = SSE/dof 0076 double rsd{0}; // residual standard deviation = sqrt(SSE/dof) 0077 double mse{0}; // mean squared error = SSE/n 0078 double rmse{0}; // root-mean squared error = \sqrt(mse) 0079 double mae{0}; // mean absolute error = \sum_i^n |r_i| 0080 double rsquare{0}; 0081 double rsquareAdj{0}; 0082 double chisq_p{0}; // chi^2 distribution p-value 0083 double fdist_F{0}; // F distribution F-value 0084 double fdist_p{0}; // F distribution p-value 0085 double logLik{0}; // log likelihood 0086 double aic{0}; // Akaike information criterion 0087 double bic{0}; // Schwarz Bayesian information criterion 0088 // see also https://www.originlab.com/doc/Origin-Help/NLFit-Theory 0089 QVector<double> paramValues; 0090 QVector<double> errorValues; 0091 QVector<double> tdist_tValues; 0092 QVector<double> tdist_pValues; 0093 QVector<double> marginValues; // lower confidence 0094 QVector<double> margin2Values; // upper confidence 0095 QVector<double> correlationMatrix; 0096 QString solverOutput; 0097 }; 0098 0099 explicit XYFitCurve(const QString& name); 0100 ~XYFitCurve() override; 0101 0102 POINTER_D_ACCESSOR_DECL(const Histogram, dataSourceHistogram, DataSourceHistogram) 0103 const QString& dataSourceHistogramPath() const; 0104 0105 void recalculate() override; 0106 void evaluate(bool preview); 0107 virtual const XYAnalysisCurve::Result& result() const override; 0108 void initStartValues(const XYCurve*); 0109 void initStartValues(XYFitCurve::FitData&, const XYCurve*); 0110 void initFitData(XYAnalysisCurve::AnalysisAction); 0111 static void initFitData(XYFitCurve::FitData&); 0112 void clearFitResult(); 0113 0114 QIcon icon() const override; 0115 void save(QXmlStreamWriter*) const override; 0116 bool load(XmlStreamReader*, bool preview) override; 0117 0118 const AbstractColumn* residualsColumn() const; 0119 POINTER_D_ACCESSOR_DECL(const AbstractColumn, xErrorColumn, XErrorColumn) 0120 POINTER_D_ACCESSOR_DECL(const AbstractColumn, yErrorColumn, YErrorColumn) 0121 const QString& xErrorColumnPath() const; 0122 const QString& yErrorColumnPath() const; 0123 0124 CLASS_D_ACCESSOR_DECL(FitData, fitData, FitData) 0125 const FitResult& fitResult() const; 0126 0127 typedef XYFitCurvePrivate Private; 0128 0129 protected: 0130 XYFitCurve(const QString& name, XYFitCurvePrivate* dd); 0131 0132 private: 0133 Q_DECLARE_PRIVATE(XYFitCurve) 0134 0135 Q_SIGNALS: 0136 void dataSourceHistogramChanged(const Histogram*); 0137 void xErrorColumnChanged(const AbstractColumn*); 0138 void yErrorColumnChanged(const AbstractColumn*); 0139 void fitDataChanged(const XYFitCurve::FitData&); 0140 }; 0141 0142 #endif