ERIS Pipeline Reference Manual 1.9.2
sc_fwhmest.c
Go to the documentation of this file.
1/*
2 * This file is part of the SKYCORR software package.
3 * Copyright (C) 2009-2013 European Southern Observatory
4 *
5 * This programme is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This programme is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this programme. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
38/*****************************************************************************
39 * INCLUDES *
40 ****************************************************************************/
41
42#include <sc_fwhmest.h>
43
44
45/*****************************************************************************
46 * CODE *
47 ****************************************************************************/
48
49cpl_error_code sc_fwhmest(double *fwhm, double *rms,
50 cpl_table *spec, cpl_table *lines,
51 const cpl_parameterlist *parlist)
52{
95 cpl_error_code err_code = CPL_ERROR_NONE;
96
97 cpl_array *fwhm_arr = cpl_array_new(0, CPL_TYPE_DOUBLE),
98 *iso_arr = cpl_array_new(0, CPL_TYPE_DOUBLE);
99
100 const cpl_parameter *p;
101
102 int status; // MPFIT status
103 int npar = 3; // Number of parameters for Gauss fit
104 cpl_size maxpos;
105 double pars[3]; // User parameters
106
107 long i, j, // loop variables
108 n_lines, // number of lines in line list
109 i_start = 0, // start of line
110 i_end = 0, // end of line
111 nline = 0, // number of pixels in current line
112 niso = 0; // number of isolated lines
113
114 int varfwhm = 0; // wavelength-dependent FWHM?
115 double meanlam = 0; // mean wavelength
116 double total = 0; // total flux in current line
117 double width = 0; // line width
118
119 scxydata data; // data for Gauss fit
120
121 char msg[SC_MAXLEN];
122
123 /* Variable FWHM (linear change with wavelength)? */
124 p = cpl_parameterlist_find_const(parlist, "varfwhm");
125 varfwhm = cpl_parameter_get_int(p);
126
127 /* Get mean wavelength */
128 p = cpl_parameterlist_find_const(parlist, "meanlam");
129 meanlam = cpl_parameter_get_double(p);
130
131 /* Initialise data array */
132 data.x = cpl_array_new(0, CPL_TYPE_DOUBLE);
133 data.y = cpl_array_new(0, CPL_TYPE_DOUBLE);
134 data.y_err = cpl_array_new(0, CPL_TYPE_DOUBLE);
135
136 /* Get number of lines in line list */
137 n_lines = cpl_table_get_nrow(lines);
138
139 /* Loop over all lines */
140
141 for (i = 0; i < n_lines; i++) {
142
143 /* Use isolated lines for FWHM estimate using Gauss fit */
144 if (cpl_table_get_int(lines, "isol_flag", i, NULL) == 1) {
145
146 i_start = cpl_table_get_int(lines, "line_px_start", i, NULL);
147 i_end = cpl_table_get_int(lines, "line_px_end", i, NULL);
148
149 /* Number of line pixels */
150 nline = i_end - i_start;
151
152 /* Copy data to xydata structure */
153 cpl_array_set_size(data.x, nline);
154 cpl_array_set_size(data.y_err, nline);
155 cpl_array_set_size(data.y, nline);
156
157 /* Fill private data structure to pointers with user data */
158 cpl_array_copy_data_double(data.y,
159 cpl_table_get_data_double(spec, "lflux")+i_start);
160 for (j = 0, total = 0; j < nline; j++) {
161 cpl_array_set_double(data.x, j, (double) (i_start + j));
162 cpl_array_set_double(data.y_err, j, 1.);
163 total += cpl_array_get_double(data.y, j, NULL);
164 }
165
166 /* Get initial FWHM from line list */
167 width = cpl_table_get_double(lines, "fwhm", i, NULL);
168 if (width == 0.) {
169 /* First iteration */
170 width = (double) cpl_table_get_int(lines, "width", i, NULL);
171 } else {
172 /* Correct FWHM if line width is wavelength dependent */
173 if (varfwhm == 1) {
174 width *= cpl_table_get_double(lines, "peak_lam", i,
175 NULL) / meanlam;
176 }
177 }
178
179 /* Call mpfit() */
180 pars[0] = total;
181 pars[1] = cpl_table_get_int(lines, "peak_loc", i, NULL);
182 pars[2] = width / CPL_MATH_FWHM_SIG;
183 status = mpfit(sc_fwhmest_gaussfunc, nline, npar, pars, 0, 0,
184 (void *) &data, 0);
185
186 sc_basic_status2txt(msg, status);
187 //printf("status: %s, npar: %i, p0: %lf, p1: %lf, p2: %lf, "
188 // "FWHM: %lf\n", msg, npar, pars[0], pars[1],
189 // pars[2]*CPL_MATH_FWHM_SIG, fwhm);
190
191 /* If fit was successful, overwrite result from crude estimate */
192 if (status == MP_OK_CHI ||
193 status == MP_OK_PAR ||
194 status == MP_OK_BOTH ||
195 status == MP_OK_DIR) {
196 width = pars[2] * CPL_MATH_FWHM_SIG;
197 }
198
199 /* Count isolated lines */
200 niso++;
201
202 /* Correct FWHM if line width is wavelength dependent */
203 if (varfwhm == 1) {
204 width *= meanlam / cpl_table_get_double(lines, "peak_lam", i,
205 NULL);
206 }
207
208 /* Set FWHM in line list */
209 cpl_table_set_double(lines, "fwhm", i, width);
210
211 /* Store FWHM values in CPL array */
212 cpl_array_set_size(fwhm_arr, niso);
213 cpl_array_set_double(fwhm_arr, niso-1, width);
214
215 /* Store FWHM value in array for isolated lines */
216 cpl_array_set_size(iso_arr, niso);
217 cpl_array_set_double(iso_arr, niso-1, width);
218
219 }
220
221 }
222
223 /* Calculate mean FWHM and RMS depending on number of isolated lines */
224
225 switch (niso) {
226 case 0:
227 *fwhm = 0;
228 *rms = HUGE_VAL;
229 break;
230 case 1:
231 *fwhm = cpl_array_get_double(iso_arr, 0, NULL);
232 *rms = HUGE_VAL;
233 break;
234 case 2:
235 *fwhm = cpl_array_get_min(iso_arr);
236 *rms = HUGE_VAL;
237 break;
238 case 3:
239 *fwhm = cpl_array_get_median(iso_arr);
240 *rms = HUGE_VAL;
241 break;
242 case 4:
243 cpl_array_get_maxpos(iso_arr, &maxpos);
244 cpl_array_set_invalid(iso_arr, maxpos);
245 *fwhm = cpl_array_get_median(iso_arr);
246 *rms = HUGE_VAL;
247 break;
248 default:
249 /* Calculate mean/RMS of FWHM array */
250 sc_basic_clipmean(fwhm, rms, fwhm_arr, CPL_FALSE);
251 break;
252 }
253
254 /* Clean-up */
255 cpl_array_delete(fwhm_arr);
256 cpl_array_delete(iso_arr);
257 cpl_array_delete(data.x);
258 cpl_array_delete(data.y);
259 cpl_array_delete(data.y_err);
260
261 return err_code;
262}
263
264
265int sc_fwhmest_gaussfunc(int n_data, int n_pars, double *p, double *deviates,
266 double **derivs, void *pdata)
267{
286 int i;
287
288 scxydata *data = (scxydata *) pdata;
289
290 double *fgauss;
291
292 if (n_pars) {};
293 if (derivs) {};
294
295 fgauss = (double *) malloc(n_data * sizeof(double));
296 sc_basic_gaussfunc(fgauss, cpl_array_get_data_double(data->x), n_data, p);
297
298 /* Compute function deviates */
299 for (i = 0; i < n_data; i++) {
300 deviates[i] = (cpl_array_get_double(data->y, i, NULL) - fgauss[i]) /
301 cpl_array_get_double(data->y_err, i, NULL);
302 }
303
304 free(fgauss);
305
306 return 0;
307}
308
#define SC_MAXLEN
Definition: sc_basic.h:94
int sc_basic_gaussfunc(double *fgauss, const double *xgauss, const int n_data, const double *par)
Definition: sc_basic.c:2473
cpl_error_code sc_basic_clipmean(double *mean, double *rms, cpl_array *arr, const cpl_boolean clip)
Definition: sc_basic.c:1539
cpl_error_code sc_fwhmest(double *fwhm, double *rms, cpl_table *spec, cpl_table *lines, const cpl_parameterlist *parlist)
Definition: sc_fwhmest.c:49
int sc_fwhmest_gaussfunc(int n_data, int n_pars, double *p, double *deviates, double **derivs, void *pdata)
Definition: sc_fwhmest.c:265