Linuxpops  3.01.04
Spectral Anaysis Package for Single Dish Data
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gaussian_fit.c
Go to the documentation of this file.
1 /*
2 Copyright 2021 Arizona Board of Regents on behalf of the University of Arizona.
3 
4 For commercial uses, to obtain a license to sell and or sublicense copies of
5 the Software please contact the University of Arizona at Tech Launch Arizona:
6 lewish@tla.arizona.edu.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction for non-commercial use educational and
11 research purposes, including without limitation the rights to use, copy,
12 modify, merge, publish, distribute, and to permit persons to whom the Software
13 is furnished to do so, subject to the following conditions:
14 
15 The entire above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 SOFTWARE.
25 
26 1. Additional Required Provisions
27 
28 1.1. Arbitration. The parties agree that if a dispute arises between them
29 concerning this Agreement, the parties may be required to submit the matter to
30 arbitration pursuant to Arizona law.
31 
32 1.2. Applicable Law and Venue. This Agreement shall be interpreted pursuant
33 to the laws of the State of Arizona. Any arbitration or litigation between the
34 Parties shall be conducted in Pima County, ARIZONA, and LICENSEE hereby
35 submits to venue and jurisdiction in Pima County, ARIZONA.
36 
37 1.3. Non-Discrimination. The Parties agree to be bound by state and federal
38 laws and regulations governing equal opportunity and non-discrimination and
39 immigration.
40 
41 1.4. Appropriation of Funds. The Parties recognize that performance by
42 ARIZONA may depend upon appropriation of funds by the State Legislature of
43 ARIZONA. If the Legislature fails to appropriate the necessary funds, or if
44 ARIZONA’S appropriation is reduced during the fiscal year, ARIZONA may cancel
45 this Agreement without further duty or obligation. ARIZONA will notify
46 LICENSEE as soon as reasonably possible after it knows of the loss of funds.
47 
48 1.5. Conflict of Interest. This Agreement is subject to the provisions of
49 A.R.S. 38-511 and other conflict of interest regulations. Within three years
50 of the EFFECTIVE DATE, ARIZONA may cancel this Agreement if any person
51 significantly involved in initiating, negotiating, drafting, securing, or
52 creating this Agreement for or on behalf of ARIZONA becomes an employee or
53 consultant in any capacity of LICENSEE with respect to the subject matter of
54 this Agreement.
55 
56  */
57 
58 
59 #include "extern.h"
60 
61 struct data
62 {
63  double *t;
64  double *y;
65  size_t n;
66 };
67 
68 /* model function: a * exp( -1/2 * [ (t - b) / c ]^2 ) */
69 double
70 gaussian(const double a, const double b, const double c, const double t)
71 {
72  const double z = (t - b) / c;
73  return (a * exp(-0.5 * z * z));
74 }
75 
76 int
77 func_f (const gsl_vector * x, void *params, gsl_vector * f)
78 {
79  struct data *d = (struct data *) params;
80  double a = gsl_vector_get(x, 0);
81  double b = gsl_vector_get(x, 1);
82  double c = gsl_vector_get(x, 2);
83  size_t i;
84 
85  for (i = 0; i < d->n; ++i)
86  {
87  double ti = d->t[i];
88  double yi = d->y[i];
89  double y = gaussian(a, b, c, ti);
90 
91  gsl_vector_set(f, i, yi - y);
92  }
93 
94  return GSL_SUCCESS;
95 }
96 
97 int
98 func_df (const gsl_vector * x, void *params, gsl_matrix * J)
99 {
100  struct data *d = (struct data *) params;
101  double a = gsl_vector_get(x, 0);
102  double b = gsl_vector_get(x, 1);
103  double c = gsl_vector_get(x, 2);
104  size_t i;
105 
106  for (i = 0; i < d->n; ++i)
107  {
108  double ti = d->t[i];
109  double zi = (ti - b) / c;
110  double ei = exp(-0.5 * zi * zi);
111 
112  gsl_matrix_set(J, i, 0, -ei);
113  gsl_matrix_set(J, i, 1, -(a / c) * ei * zi);
114  gsl_matrix_set(J, i, 2, -(a / c) * ei * zi * zi);
115  }
116 
117  return GSL_SUCCESS;
118 }
119 
120 int
121 func_fvv (const gsl_vector * x, const gsl_vector * v,
122  void *params, gsl_vector * fvv)
123 {
124  struct data *d = (struct data *) params;
125  double a = gsl_vector_get(x, 0);
126  double b = gsl_vector_get(x, 1);
127  double c = gsl_vector_get(x, 2);
128  double va = gsl_vector_get(v, 0);
129  double vb = gsl_vector_get(v, 1);
130  double vc = gsl_vector_get(v, 2);
131  size_t i;
132 
133  for (i = 0; i < d->n; ++i)
134  {
135  double ti = d->t[i];
136  double zi = (ti - b) / c;
137  double ei = exp(-0.5 * zi * zi);
138  double Dab = -zi * ei / c;
139  double Dac = -zi * zi * ei / c;
140  double Dbb = a * ei / (c * c) * (1.0 - zi*zi);
141  double Dbc = a * zi * ei / (c * c) * (2.0 - zi*zi);
142  double Dcc = a * zi * zi * ei / (c * c) * (3.0 - zi*zi);
143  double sum;
144 
145  sum = 2.0 * va * vb * Dab +
146  2.0 * va * vc * Dac +
147  vb * vb * Dbb +
148  2.0 * vb * vc * Dbc +
149  vc * vc * Dcc;
150 
151  gsl_vector_set(fvv, i, sum);
152  }
153 
154  return GSL_SUCCESS;
155 }
156 
157 void
158 callback(const size_t iter, void *params,
159  const gsl_multifit_nlinear_workspace *w)
160 {
161  gsl_vector *f = gsl_multifit_nlinear_residual(w);
162  gsl_vector *x = gsl_multifit_nlinear_position(w);
163  double avratio = gsl_multifit_nlinear_avratio(w);
164  double rcond;
165 
166  (void) params; /* not used */
167 
168  /* compute reciprocal condition number of J(x) */
169  gsl_multifit_nlinear_rcond(&rcond, w);
170 
171  if(isSet(PF_V_FLAG))
172  {
173  fprintf(stderr, "iter %2zu: a = %.4f, b = %.4f, c = %.4f, |a|/|v| = %.4f cond(J) = %e, |f(x)| = %.4f\n",
174  iter,
175  gsl_vector_get(x, 0),
176  gsl_vector_get(x, 1),
177  gsl_vector_get(x, 2),
178  avratio,
179  1.0 / rcond,
180  gsl_blas_dnrm2(f));
181  }
182 }
183 
184 void
185 solve_system(gsl_vector *x, gsl_multifit_nlinear_fdf *fdf,
186  gsl_multifit_nlinear_parameters *params)
187 {
188  const gsl_multifit_nlinear_type *T = gsl_multifit_nlinear_trust;
189  const size_t max_iter = 200;
190  const double xtol = 1.0e-8;
191  const double gtol = 1.0e-8;
192  const double ftol = 1.0e-8;
193  const size_t n = fdf->n;
194  const size_t p = fdf->p;
195  gsl_multifit_nlinear_workspace *work = gsl_multifit_nlinear_alloc(T, params, n, p);
196  gsl_vector * f = gsl_multifit_nlinear_residual(work);
197  gsl_vector * y = gsl_multifit_nlinear_position(work);
198  int info;
199  double chisq0, chisq, rcond;
200 
201  /* initialize solver */
202  gsl_multifit_nlinear_init(x, fdf, work);
203 
204  /* store initial cost */
205  gsl_blas_ddot(f, f, &chisq0);
206 
207  /* iterate until convergence */
208  gsl_multifit_nlinear_driver(max_iter, xtol, gtol, ftol,
209  callback, NULL, &info, work);
210 
211  /* store final cost */
212  gsl_blas_ddot(f, f, &chisq);
213 
214  /* store cond(J(x)) */
215  gsl_multifit_nlinear_rcond(&rcond, work);
216 
217  gsl_vector_memcpy(x, y);
218 
219  /* print summary */
220 
221  if(isSet(PF_V_FLAG))
222  {
223  fprintf(stderr, "NITER = %zu\n", gsl_multifit_nlinear_niter(work));
224  fprintf(stderr, "NFEV = %zu\n", fdf->nevalf);
225  fprintf(stderr, "NJEV = %zu\n", fdf->nevaldf);
226  fprintf(stderr, "NAEV = %zu\n", fdf->nevalfvv);
227  fprintf(stderr, "chisq0 = %f\n", chisq0);
228  fprintf(stderr, "chisq = %f\n", chisq);
229  fprintf(stderr, "final = (%f, %f, %f)\n", gsl_vector_get(x, 0), gsl_vector_get(x, 1), gsl_vector_get(x, 2));
230  fprintf(stderr, "final cond(J) = %f\n", 1.0 / rcond);
231  }
232 
233  gsl_multifit_nlinear_free(work);
234 }
235 
236 
237 
238 /* main entry point */
239 int gaussian_fit_gsl(xd, yd, n, aa)
240 double *xd; /* X-data array */
241 double *yd; /* Y-data array */
242 const size_t n; /* number of data points to fit */
243 double *aa; /* amplitude, center & width guesses; returned results here */
244 {
245  const size_t p = 3; /* number of model parameters */
246  const gsl_rng_type * T = gsl_rng_default;
247  gsl_vector *f = gsl_vector_alloc(n);
248  gsl_vector *x = gsl_vector_alloc(p);
249  gsl_multifit_nlinear_fdf fdf;
250  gsl_multifit_nlinear_parameters fdf_params = gsl_multifit_nlinear_default_parameters();
251  struct data fit_data;
252  gsl_rng * r;
253  size_t i;
254 
255  gsl_rng_env_setup ();
256  r = gsl_rng_alloc (T);
257 
258  fit_data.t = malloc(n * sizeof(double));
259  fit_data.y = malloc(n * sizeof(double));
260  fit_data.n = n;
261 
262  /* load passed data into fit_data */
263  for(i=0;i<n;i++)
264  {
265  fit_data.t[i] = xd[i];
266  fit_data.y[i] = yd[i];
267  }
268 
269  /* define function to be minimized */
270  fdf.f = func_f;
271  fdf.df = func_df;
272  fdf.fvv = func_fvv;
273  fdf.n = n;
274  fdf.p = p;
275  fdf.params = &fit_data;
276 
277  /* starting point */
278  gsl_vector_set(x, 0, aa[0]);
279  gsl_vector_set(x, 1, aa[1]);
280  gsl_vector_set(x, 2, aa[2]);
281 
282  fdf_params.trs = gsl_multifit_nlinear_trs_lmaccel;
283  solve_system(x, &fdf, &fdf_params);
284 
285  /* Return results */
286  aa[0] = gsl_vector_get(x, 0); /* A */
287  aa[1] = gsl_vector_get(x, 1); /* B */
288  aa[2] = gsl_vector_get(x, 2); /* C */
289 
290  gsl_vector_free(f);
291  gsl_vector_free(x);
292  gsl_rng_free(r);
293 
294  return 0;
295 }
double * y
Definition: gaussian_fit.c:64
size_t n
Definition: gaussian_fit.c:65
int gaussian_fit_gsl(double *xd, double *yd, const size_t n, double *aa)
Definition: gaussian_fit.c:239
int func_fvv(const gsl_vector *x, const gsl_vector *v, void *params, gsl_vector *fvv)
Definition: gaussian_fit.c:121
int func_f(const gsl_vector *x, void *params, gsl_vector *f)
Definition: gaussian_fit.c:77
double gaussian(const double a, const double b, const double c, const double t)
Definition: gaussian_fit.c:70
double sum
Definition: beam.h:5
int isSet(int flag)
Definition: parse.c:646
double * t
Definition: gaussian_fit.c:63
void solve_system(gsl_vector *x, gsl_multifit_nlinear_fdf *fdf, gsl_multifit_nlinear_parameters *params)
Definition: gaussian_fit.c:185
void callback(const size_t iter, void *params, const gsl_multifit_nlinear_workspace *w)
Definition: gaussian_fit.c:158
int func_df(const gsl_vector *x, void *params, gsl_matrix *J)
Definition: gaussian_fit.c:98