I am trying to fit a Lorentzian curve on my data in c#. I am using the Math.Net library (version 5.0.0). Unfortunately, the results I get lead to a curve that is upside down compared to the input data.
My input data is:
double[] xData = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
double[] yData = [5.1, 5.3, 5.8, 6.0, 5.8, 5.3, 5.1];
with initial guesses: [x0Guess: 4.0, AGuess: 5.0, gammaGuess: 2.0]
The code is:
public static Tuple<double, double, double> FitLorentzian(double[] xDataInput, double[] yDataInput, double x0Guess, double AGuess, double gammaGuess)
{
if (xDataInput.Length != yDataInput.Length || xDataInput.Length < 3)
{
throw new ArgumentException("Input data arrays must have the same length and at least 3 points.");
}
var xData = new DenseVector(xDataInput);
var yData = new DenseVector(yDataInput);
Vector<double> initialGuess = Vector<double>.Build.Dense([x0Guess, AGuess, gammaGuess]);
IObjectiveModel objective = ObjectiveFunction.NonlinearModel(Model, xData, yData);
var minimizer = new LevenbergMarquardtMinimizer(initialMu: 0.001, gradientTolerance: 1E-15, stepTolerance: 1E-15, functionTolerance: 1E-15, maximumIterations: 100);
Vector<double> lowerBound = Vector<double>.Build.Dense([0, 0, 0]);
NonlinearMinimizationResult optimizationResult = minimizer.FindMinimum(objective, initialGuess, lowerBound);
if (optimizationResult.ReasonForExit == ExitCondition.Converged || optimizationResult.ReasonForExit == ExitCondition.RelativePoints || optimizationResult.ReasonForExit == ExitCondition.RelativeGradient)
{
return Tuple.Create(optimizationResult.MinimizingPoint[0], optimizationResult.MinimizingPoint[1], optimizationResult.MinimizingPoint[2]);
}
else
{
return Tuple.Create(double.NaN, double.NaN, double.NaN);
}
}
private static Vector<double> Model(Vector<double> parameters, Vector<double> xData)
{
double x0 = parameters[0];
double A = parameters[1];
double gamma = parameters[2];
Vector<double> result = CreateVector.Dense<double>(xData.Count);
for (int i = 0; i < xData.Count; i++)
{
result[i] = (A / Math.PI) * (gamma / 2.0) / (Math.Pow(xData[i] - x0, 2) + Math.Pow(gamma / 2.0, 2));
}
return result;
}
I am trying to fit a Lorentzian curve on my data in c#. I am using the Math.Net library (version 5.0.0). Unfortunately, the results I get lead to a curve that is upside down compared to the input data.
My input data is:
double[] xData = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
double[] yData = [5.1, 5.3, 5.8, 6.0, 5.8, 5.3, 5.1];
with initial guesses: [x0Guess: 4.0, AGuess: 5.0, gammaGuess: 2.0]
The code is:
public static Tuple<double, double, double> FitLorentzian(double[] xDataInput, double[] yDataInput, double x0Guess, double AGuess, double gammaGuess)
{
if (xDataInput.Length != yDataInput.Length || xDataInput.Length < 3)
{
throw new ArgumentException("Input data arrays must have the same length and at least 3 points.");
}
var xData = new DenseVector(xDataInput);
var yData = new DenseVector(yDataInput);
Vector<double> initialGuess = Vector<double>.Build.Dense([x0Guess, AGuess, gammaGuess]);
IObjectiveModel objective = ObjectiveFunction.NonlinearModel(Model, xData, yData);
var minimizer = new LevenbergMarquardtMinimizer(initialMu: 0.001, gradientTolerance: 1E-15, stepTolerance: 1E-15, functionTolerance: 1E-15, maximumIterations: 100);
Vector<double> lowerBound = Vector<double>.Build.Dense([0, 0, 0]);
NonlinearMinimizationResult optimizationResult = minimizer.FindMinimum(objective, initialGuess, lowerBound);
if (optimizationResult.ReasonForExit == ExitCondition.Converged || optimizationResult.ReasonForExit == ExitCondition.RelativePoints || optimizationResult.ReasonForExit == ExitCondition.RelativeGradient)
{
return Tuple.Create(optimizationResult.MinimizingPoint[0], optimizationResult.MinimizingPoint[1], optimizationResult.MinimizingPoint[2]);
}
else
{
return Tuple.Create(double.NaN, double.NaN, double.NaN);
}
}
private static Vector<double> Model(Vector<double> parameters, Vector<double> xData)
{
double x0 = parameters[0];
double A = parameters[1];
double gamma = parameters[2];
Vector<double> result = CreateVector.Dense<double>(xData.Count);
for (int i = 0; i < xData.Count; i++)
{
result[i] = (A / Math.PI) * (gamma / 2.0) / (Math.Pow(xData[i] - x0, 2) + Math.Pow(gamma / 2.0, 2));
}
return result;
}
Share
Improve this question
asked Mar 31 at 16:12
AlexAlex
511 silver badge6 bronze badges
3
- Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Bot Commented Mar 31 at 16:13
- 1 Can you confirm ( i.e. you did check and double check ) that your maths are correct? Is it a sign error somewhere? If so, it wouldn't be a coding problem. – Fildor Commented Mar 31 at 16:38
- Thanks guys, you were right. The math in my excel sheet was wrong. I added the answer at the bottom. – Alex Commented Apr 1 at 6:48
1 Answer
Reset to default 0Found the issue.. I inserted the y values into the final lorentzian function and plotted this in the excel sheet instead of inserting the x values. Plots look good now.