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