Vespucci  1.0.0
nonlinleastsq.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright (C) 2014-2016 Wright State University - All Rights Reserved
3  Daniel P. Foose - Maintainer/Lead Developer
4 
5  This file is part of Vespucci.
6 
7  Vespucci is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  Vespucci is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with Vespucci. If not, see <http://www.gnu.org/licenses/>.
19 *******************************************************************************/
22 //#include <lmcurve.h>
24 #include <limits>
31 double GaussianFn(double t, const double *p)
32 {
33  return p[0]*std::exp(-0.5*std::pow(t-p[1], 2)/std::pow(p[2], 2));
34 }
35 
42 double LorentzianFn(double t, const double *p)
43 {
44  return p[0] * std::pow(p[1], 2)/(std::pow(t - p[2], 2) + std::pow(p[1], 2));
45 }
46 
53 double VoigtFn(double t, const double *p)
54 {
55  const std::complex<double> i(0.0, 1.0);
56  std::complex<double> z = (t - p[1] + i*p[3]) / (p[2] * arma::datum::sqrt2);
57  return p[0] * Faddeeva::w(z).real() / (p[2] * arma::datum::sqrt2);
58 }
59 
66 arma::vec Vespucci::Math::NonLinLeastSq::EstimateGaussParams(arma::vec x, arma::vec y)
67 {
68  arma::vec logy = arma::log(y);
69  arma::mat vdm = Vespucci::Math::LinLeastSq::Vandermonde(x, 2);
70  arma::vec quad_params = Vespucci::Math::LinLeastSq::OrdinaryLeastSquares(vdm, logy);
71 
72  double A = std::exp(quad_params(0) - (0.25*std::pow(quad_params(1), 2)/quad_params(2)));
73  double sigma = (quad_params(2) < 0 ? std::sqrt(-0.5/quad_params(2)) : arma::stddev(y));
74  double mu = -0.5*quad_params(1)/quad_params(2);
75 
76  return arma::vec({A, mu, sigma});
77 }
78 
79 arma::vec Vespucci::Math::NonLinLeastSq::EstimateLorentzParams(arma::vec x, arma::vec y)
80 {
81  arma::vec invy = y.transform([](const double t){return (t != 0 ? 1.0/t : std::numeric_limits<double>::max());});
82  arma::mat vdm = Vespucci::Math::LinLeastSq::Vandermonde(x, 2);
83  arma::vec quad_params = Vespucci::Math::LinLeastSq::OrdinaryLeastSquares(vdm, invy);
84  double x0 = -0.5 * quad_params(1) / quad_params(0);
85  double inside_sqrt = (quad_params(2) - std::pow(x0, 1)) / quad_params(0);
86  double gamma = (inside_sqrt >= 0 ? std::sqrt(inside_sqrt) : arma::stddev(y));
87  double I = 1.0 / (quad_params(0) * gamma);
88  return arma::vec({I, gamma, x0});
89 }
96 arma::vec Vespucci::Math::NonLinLeastSq::FitGaussian(arma::vec x, arma::vec y)
97 {
98  /*
99  if (x.n_rows != y.n_rows) throw(std::invalid_argument("FitGaussian: x and y must be same size!"));
100  lm_control_struct control = lm_control_double;
101  lm_status_struct status;
102  control.verbosity = 7;
103  arma::vec params = Vespucci::Math::NonLinLeastSq::EstimateGaussParams(x, y);
104  //lmcurve(3, params.memptr(), x.n_rows, x.memptr(), y.memptr(), GaussianFn, &control, &status);
105  return params;
106 */ return arma::vec();
107 }
108 
109 arma::vec Vespucci::Math::NonLinLeastSq::FitLorentzian(arma::vec x, arma::vec y)
110 {
111 /*
112  if (x.n_rows != y.n_rows) throw(std::invalid_argument("FittLorentzian: x and y must be same size!"));
113  lm_control_struct control = lm_control_double;
114  lm_status_struct status;
115  control.verbosity = 7;
116  arma::vec params = Vespucci::Math::NonLinLeastSq::EstimateLorentzParams(x, y);
117  lmcurve(3, params.memptr(), x.n_rows, x.memptr(), y.memptr(), LorentzianFn, &control, &status);
118  return params;
119  */return arma::vec();
120 }
121 
122 
123 
124 arma::vec Vespucci::Math::NonLinLeastSq::FitVoigt(arma::vec x, arma::vec y)
125 {
126  /*
127  if (x.n_rows != y.n_rows) throw(std::invalid_argument("FittLorentzian: x and y must be same size!"));
128  lm_control_struct control = lm_control_double;
129  lm_status_struct status;
130  control.verbosity = 7;
131  arma::vec lorentz_params = Vespucci::Math::NonLinLeastSq::EstimateLorentzParams(x, y);
132  arma::vec gauss_params = Vespucci::Math::NonLinLeastSq::EstimateGaussParams(x, y);
133  arma::vec params({gauss_params(0), gauss_params(1), gauss_params(2), lorentz_params(1)});
134  lmcurve(4, params.memptr(), x.n_rows, x.memptr(), y.memptr(), VoigtFn, &control, &status);
135  return params;
136  */return arma::vec();
137 }
double GaussianFn(double t, const double *p)
Gaussian.
VESPUCCI_EXPORT arma::vec FitLorentzian(arma::vec x, arma::vec y)
double VoigtFn(double t, const double *p)
VoigtFn.
VESPUCCI_EXPORT arma::uword max(arma::uword a, arma::uword b)
Vespucci::Math::max.
Definition: accessory.cpp:237
VESPUCCI_EXPORT arma::vec EstimateGaussParams(arma::vec x, arma::vec y)
Vespucci::Math::NonLinLeastSq::EstimateGaussParams.
VESPUCCI_EXPORT arma::vec EstimateLorentzParams(arma::vec x, arma::vec y)
VESPUCCI_EXPORT arma::vec FitGaussian(arma::vec x, arma::vec y)
Vespucci::Math::NonLinLeastSq::FitGaussian.
double LorentzianFn(double t, const double *p)
Lorentzian.
std::complex< double > w(std::complex< double > z, double relerr=0)
VESPUCCI_EXPORT arma::mat Vandermonde(const arma::vec &x, const int poly_order)
Vespucci::Math::LinLeastSq::Vandermonde Build a Vandermonde matrix for OLS.
Definition: linleastsq.cpp:162
VESPUCCI_EXPORT arma::mat OrdinaryLeastSquares(const arma::mat &X, const arma::mat &y)
Vespucci::Math::LinLeastSq::OrdinaryLeastSquares Perform Squares.
Definition: linleastsq.cpp:149
VESPUCCI_EXPORT arma::vec FitVoigt(arma::vec x, arma::vec y)