Search code examples
c#matlabcurve-fitting

How to calculate abcd fitting coefficients?


In the Matlab I have the following equation, which gives me a, b, c and d coefficients.

gaussEqn = 'a*exp(-((x-b)/c)^2)+d';

[fittedModel, gof] = fit(sensData(:, 1), sensData(:, 2), gaussEqn, 'Start', startPoints);
a = fittedModel.a;
b = fittedModel.b;
c = fittedModel.c;
d = fittedModel.d;

How can I do the same in C# using math libraries? The equation is not exactly gaussian, but contains an extra d coefficient. But I will be happy even to calculate a, b c only based on gaussian equation.


Solution

  • If you want to use MathNet to estimate the fit parameters in C#, as per Felix Castor's recommendation, you may use Fit.Curve functions.

    Using your model function, in order to test the fit, I started with some arbitrary parameters a0 = 2.1, b0 = 3.4, c0 = 1.35, d0 = 5.3. I generated n = 1000 equidistant x values and computed the function for them. I added some normally distributed random noise to the y values and used matlab's fit to retrieve the parameters (which are typically close to the "correct" values, a0, b0, c0, d0 if the initial guess is sufficiently close).

    I ended up with this matlab code:

    a0 = 2.1; b0 = 3.4; c0 = 1.35; d0 = 5.3;
    n = 1000;
    x = linspace(0, 2*b, n);
    y = a0 * exp(-((x - b0) / c0).^2) + d0 + randn(1, n)*0.05;
    
    startPoints = [2, 2, 1, 1];
    fittedModel = fit(x', y', 'a*exp(-((x-b)/c)^2)+d', 'Start', startPoints);
    a = fittedModel.a;
    b = fittedModel.b;
    c = fittedModel.c;
    d = fittedModel.d;
    
    fprintf("a = %f   b = %f   c = %f   d = %f", a, b, c, d);
    

    which I wrote in order to show its C# MathNet "translation":

    using MathNet.Numerics;
    using MathNet.Numerics.Distributions;
    
    double F0(double a, double b, double c, double d, double x)
    {
        return a * Math.Exp(-Math.Pow((x - b) / c, 2)) + d;
    }
    
    const int n = 1000;
    const double a0 = 2.1, b0 = 3.4, c0 = 1.35, d0 = 5.3; // "correct" parameters
    
    var x = Generate.LinearSpaced(n, 0, 2*b0);
    var rnd = new double[n];
    Normal.Samples(rnd, 0.0, 1.0);
    var y0 = Generate.Map(x, xi=>F0(a0, b0, c0, d0, xi));
    var y = Generate.Map2(y0, rnd, (yi, ri) => yi + ri * 0.05);
    
    var (a, b, c, d) = Fit.Curve(x, y, F0, 2.0, 2.0, 1.0, 1.0);
    Console.WriteLine($"a = {a} b = {b}  c = {c}  d = {d}");
    

    That being said, you have to be aware that MathNet's algorithms are different from those of matlab, with matlab's versions being more sophisticated and more likely to find the right solution in difficult/edge cases.