ERIS Pipeline Reference Manual 1.9.2
sc_weights.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_weights.h>
43
44
45/*****************************************************************************
46 * CODE *
47 ****************************************************************************/
48
49cpl_error_code sc_weights(cpl_table *skyspec, cpl_table *fitpar,
50 cpl_table *groups, cpl_parameterlist *parlist)
51{
73 /* Create table of fit parameters */
74 sc_weights_initfitpar(fitpar, parlist, groups);
75
76 /* Write info message */
77// cpl_msg_debug(cpl_func, "Derive line group weights for each pixel "
78// "of the sky spectrum");
79
80 /* Calculate spectrum for each line group and get group contributions to
81 each pixel of the input sky spectrum */
82 sc_weights_getpixcontrib(skyspec, fitpar, groups, parlist);
83
84 return CPL_ERROR_NONE;
85}
86
87
88cpl_error_code sc_weights_initfitpar(cpl_table *fitpar,
89 cpl_parameterlist *parlist,
90 const cpl_table *groups)
91{
128 cpl_parameter *p;
129 int nlin = 0, i = 0, groupa = 0, groupb = 0, maxa = 0, maxb = 0, minb = 0;
130 int deg = 0, ncoef = 0, npar = 0, j = 0, group = 0, syst = 0;
131
132 /* Create CPL table columns */
133 cpl_table_new_column(fitpar, "type", CPL_TYPE_STRING);
134 cpl_table_new_column(fitpar, "N", CPL_TYPE_INT);
135 cpl_table_new_column(fitpar, "system", CPL_TYPE_INT);
136 cpl_table_new_column(fitpar, "relevance", CPL_TYPE_INT);
137 cpl_table_new_column(fitpar, "fit", CPL_TYPE_INT);
138 cpl_table_new_column(fitpar, "value", CPL_TYPE_DOUBLE);
139 cpl_table_new_column(fitpar, "err_fit", CPL_TYPE_DOUBLE);
140 cpl_table_new_column(fitpar, "err_est", CPL_TYPE_DOUBLE);
141 cpl_table_new_column(fitpar, "N_lin", CPL_TYPE_INT);
142
143 /* Get number of airglow lines */
144 nlin = cpl_table_get_nrow(groups);
145
146 /* Find maximum group numbers for both group types and minimum number for
147 B groups (= number of systems) */
148 for (i = 0; i < nlin; i++) {
149 groupa = cpl_table_get(groups, "groupA", i, NULL);
150 groupb = cpl_table_get(groups, "groupB", i, NULL);
151 if (groupa > maxa) {
152 maxa = groupa;
153 }
154 if (groupb > maxb) {
155 maxb = groupb;
156 }
157 if (groupb < minb) {
158 minb = groupb;
159 }
160 }
161
162 /* Write group numbers into general parameter list */
163 p = cpl_parameter_new_value("n_groupA", CPL_TYPE_INT, "", "", maxa);
164 cpl_parameterlist_append(parlist, p);
165 p = cpl_parameter_new_value("n_groupB", CPL_TYPE_INT, "", "", maxb);
166 cpl_parameterlist_append(parlist, p);
167 p = cpl_parameter_new_value("n_system", CPL_TYPE_INT, "", "", -minb);
168 cpl_parameterlist_append(parlist, p);
169
170 /* Get maximum number of coefficients of the Chebyshev polynomial for the
171 wavelength grid correction */
172 p = cpl_parameterlist_find(parlist, "cheby_max");
173 deg = cpl_parameter_get_int(p);
174 if (deg < 0) {
175 ncoef = 0;
176 } else if (deg == 0) {
177 /* Constant term is not sufficient to reproduce input wavelength
178 grid */
179 ncoef = 2;
180 } else {
181 ncoef = deg + 1;
182 }
183
184 /* Resize fit parameter table */
185 npar = maxa + maxb + ncoef;
186 cpl_table_set_size(fitpar, npar);
187
188 /* Put parameter type, number, and initial value into table */
189
190 for (j = 0; j < npar; j++) {
191
192 if (j >= maxa + maxb) {
193 cpl_table_set_string(fitpar, "type", j, "w");
194 if (j == maxa + maxb) {
195 p = cpl_parameterlist_find(parlist, "cheby_const");
196 cpl_table_set(fitpar, "value", j,
197 cpl_parameter_get_double(p));
198 } else if (j == maxa + maxb + 1) {
199 cpl_table_set(fitpar, "value", j, 1.);
200 } else {
201 cpl_table_set(fitpar, "value", j, 0.);
202 }
203 } else {
204 if (j < maxa) {
205 cpl_table_set_string(fitpar, "type", j, "A");
206 } else {
207 cpl_table_set_string(fitpar, "type", j, "B");
208 }
209 cpl_table_set(fitpar, "value", j, 1.);
210 }
211
212 if (j == maxa + maxb) {
213 group = 0;
214 } else if (j == maxa) {
215 group = 1;
216 } else {
217 group++;
218 }
219 cpl_table_set_int(fitpar, "N", j, group);
220
221 }
222
223 /* Set all relevance and fit flags to 1 for 'A' and 'B' parameters and to
224 0 for 'w' parameters */
225 cpl_table_fill_column_window(fitpar, "relevance", 0, maxa + maxb, 1);
226 cpl_table_fill_column_window(fitpar, "fit", 0, maxa + maxb, 1);
227 cpl_table_fill_column_window(fitpar, "relevance", maxa + maxb, ncoef, 0);
228 cpl_table_fill_column_window(fitpar, "fit", maxa + maxb, ncoef, 0);
229
230 /* Get system flags from line list */
231 cpl_table_fill_column_window(fitpar, "system", 0, npar, 0);
232 for (i = 0; i < nlin; i++) {
233 syst = cpl_table_get(groups, "system", i, NULL);
234 groupa = cpl_table_get(groups, "groupA", i, NULL);
235 groupb = cpl_table_get(groups, "groupB", i, NULL);
236 cpl_table_set_int(fitpar, "system", groupa - 1, syst);
237 if (groupb >= 0) {
238 cpl_table_set_int(fitpar, "system", maxa + groupb - 1, syst);
239 }
240 }
241
242 /* Set the two error columns to 0 */
243 cpl_table_fill_column_window(fitpar, "err_fit", 0, npar, 0.);
244 cpl_table_fill_column_window(fitpar, "err_est", 0, npar, 0.);
245
246 /* Set number of lines for each group to 0 */
247 cpl_table_fill_column_window(fitpar, "N_lin", 0, npar, 0);
248
249 return CPL_ERROR_NONE;
250}
251
252
253cpl_error_code sc_weights_getpixcontrib(cpl_table *skyspec, cpl_table *fitpar,
254 cpl_table *groups,
255 const cpl_parameterlist *parlist)
256{
280 const cpl_parameter *p;
281 cpl_array *array;
282 cpl_table *groupspec;
283 char grouptype[2] = "AB", ncolname[SC_LENLINE+1], wcolname[SC_LENLINE+1];
284 char dcolname[SC_LENLINE+1], grouppar[SC_LENLINE+1];
285 int nrow = 0, varfwhm = 0, i = 0, ngroup = 0, mingroup = 0, group = 0;
286 double lcut = 0., ucut = 0., fwhm = 0., speedpar = 0., meanlam = 0.;
287
288 /* Create temporary columns for fluxes of selected group and all groups */
289 nrow = cpl_table_get_nrow(skyspec);
290 cpl_table_new_column(skyspec, "f_group", CPL_TYPE_DOUBLE);
291 cpl_table_new_column(skyspec, "f_all", CPL_TYPE_DOUBLE);
292
293 /* Create wavelength grid for temporary line group spectra */
294 groupspec = cpl_table_new(0);
295 sc_weights_createwavegrid(groupspec, skyspec);
296
297 /* Erase lines of the line table at wavelengths outside the range of the
298 line group spectrum */
299 cpl_table_unselect_all(groups);
300 lcut = cpl_table_get(groupspec, "minlam", 0, NULL);
301 cpl_table_or_selected_double(groups, "lambda", CPL_LESS_THAN, lcut);
302 cpl_table_erase_selected(groups);
303 cpl_table_unselect_all(groups);
304 ucut = cpl_table_get(groupspec, "minlam", cpl_table_get_nrow(groupspec)-1,
305 NULL);
306 cpl_table_or_selected_double(groups, "lambda", CPL_GREATER_THAN, ucut);
307 cpl_table_erase_selected(groups);
308 cpl_table_select_all(groups);
309
310 /* Get FWHM for mean wavelength from parameter list in pixels
311 (consider oversampling in group spectrum) */
312 p = cpl_parameterlist_find_const(parlist, "fwhm");
313 fwhm = cpl_parameter_get_double(p) * SC_SAMPFAC;
314
315 /* Gaussian kernel: linearly increasing with wavelength or constant? */
316 p = cpl_parameterlist_find_const(parlist, "varfwhm");
317 varfwhm = cpl_parameter_get_int(p);
318 if (varfwhm == 1) {
319 /* variable kernel */
320 speedpar = SC_LIMRELLAMVAR;
321 } else {
322 /* constant kernel */
323 speedpar = HUGE_VAL;
324 }
325
326 /* Get mean wavelength */
327 p = cpl_parameterlist_find_const(parlist, "meanlam");
328 meanlam = cpl_parameter_get_double(p);
329
330 /* Calculate pixel-specific group contributions for each group type */
331
332 for (i = 0; i < 2; i++) {
333
334 /* Initialise temporary flux columns in sky spectrum with 0 */
335 cpl_table_fill_column_window(skyspec, "f_group", 0, nrow, 0.);
336 cpl_table_fill_column_window(skyspec, "f_all", 0, nrow, 0.);
337
338 /* Create new table columns for line group IDs, weights, and IDs of
339 dominating line groups */
340 sprintf(ncolname, "ng%c", grouptype[i]);
341 cpl_table_new_column_array(skyspec, ncolname, CPL_TYPE_DOUBLE,
343 sprintf(wcolname, "wg%c", grouptype[i]);
344 cpl_table_new_column_array(skyspec, wcolname, CPL_TYPE_DOUBLE,
346 sprintf(dcolname, "dg%c", grouptype[i]);
347 cpl_table_new_column(skyspec, dcolname, CPL_TYPE_INT);
348
349 /* Initialise new array table columns with arrays of SC_COLDEPTH
350 invalid elements */
351 array = cpl_array_new(SC_COLDEPTH, CPL_TYPE_DOUBLE);
352 cpl_array_fill_window_invalid(array, 0, SC_COLDEPTH);
353 cpl_table_fill_column_window_array(skyspec, ncolname, 0, nrow, array);
354 cpl_table_fill_column_window_array(skyspec, wcolname, 0, nrow, array);
355 cpl_array_delete(array);
356
357 /* Get number of line groups */
358 sprintf(grouppar, "n_group%c", grouptype[i]);
359 p = cpl_parameterlist_find_const(parlist, grouppar);
360 ngroup = cpl_parameter_get_int(p);
361
362 /* Skip group type if number of groups is zero */
363 if (ngroup == 0) {
364 continue;
365 }
366
367 /* Get minimum group number */
368 if (i == 1) {
369 /* n_system negative B group numbers */
370 p = cpl_parameterlist_find_const(parlist, "n_system");
371 mingroup = -cpl_parameter_get_int(p);
372 } else {
373 mingroup = 0;
374 }
375
376 /* Get pixel contributions for each group */
377
378 for (group = mingroup; group <= ngroup; group++) {
379
380 /* Write group lines into temporary spectrum and update group fit
381 flags */
382 sc_weights_getgrouplines(groupspec, fitpar, groups, parlist,
383 grouptype[i], group);
384
385 /* Convolve temporary spectrum with Gaussian kernel */
386 sc_weights_convolve(groupspec, fwhm, meanlam, speedpar);
387
388 /* Rebin temporary line group spectrum to wavelength grid of input
389 sky spectrum */
390 sc_weights_rebinspec(skyspec, groupspec);
391
392 /* Write group contributions into pixel-specific arrays */
393 sc_weights_fillgrouparrays(skyspec, grouptype[i], group);
394
395 }
396
397 /* Divide group flux by flux sum for each pixel to get weights */
398 sc_weights_normpixcontrib(skyspec, grouptype[i]);
399
400 /* Get dominating group for each pixel */
401 sc_weights_getdomgroups(skyspec, parlist, grouptype[i]);
402
403 }
404
405 /* Free allocated memory */
406 cpl_table_delete(groupspec);
407
408 /* Delete temporary columns */
409 cpl_table_erase_column(skyspec, "f_group");
410 cpl_table_erase_column(skyspec, "f_all");
411
412 return CPL_ERROR_NONE;
413}
414
415
416cpl_error_code sc_weights_createwavegrid(cpl_table *groupspec,
417 const cpl_table *skyspec)
418{
437 int nrow = 0, npix = 0, i = 0, j = 0, k = 0;
438 double llam = 0., clam = 0., ulam = 0., dlam = 0., llim = 0., lam = 0.;
439
440 /* Create columns of CPL table for line group spectra */
441 cpl_table_new_column(groupspec, "lam", CPL_TYPE_DOUBLE);
442 cpl_table_new_column(groupspec, "minlam", CPL_TYPE_DOUBLE);
443 cpl_table_new_column(groupspec, "flux", CPL_TYPE_DOUBLE);
444
445 /* Get number of pixels by considering extra pixels at the margins and a
446 sampling factor that causes a split-up of each intial pixel */
447 nrow = cpl_table_get_nrow(skyspec);
448 npix = (nrow + 2 * SC_EXTRACOVER) * SC_SAMPFAC + 1;
449 cpl_table_set_size(groupspec, npix);
450
451 /* Set values of flux column = 0 */
452 cpl_table_fill_column_window(groupspec, "flux", 0, npix, 0.);
453
454 /* Derive wavelength grid from input sky spectrum */
455
456 for (i = 1; i < nrow - 1; i++) {
457
458 /* Get wavelengths of sky spectrum pixels i-1, i, and i+1 */
459
460 if (i == 1) {
461 llam = cpl_table_get(skyspec, "lambda", i - 1, NULL);
462 clam = cpl_table_get(skyspec, "lambda", i, NULL);
463 } else {
464 llam = clam;
465 clam = ulam;
466 }
467
468 ulam = cpl_table_get(skyspec, "lambda", i + 1, NULL);
469
470 /* Handle pixels of lower margin */
471
472 if (i == 1) {
473
474 j = -1;
475 dlam = (clam - llam) / SC_SAMPFAC;
476 llim = (llam + clam) / 2
477 - dlam * (SC_EXTRACOVER + 1) * SC_SAMPFAC;
478 lam = llim + dlam / 2;
479
480 for (k = 0; k < (SC_EXTRACOVER + 1) * SC_SAMPFAC; k++) {
481 j++;
482 cpl_table_set(groupspec, "lam", j, lam);
483 cpl_table_set(groupspec, "minlam", j, llim);
484 lam += dlam;
485 llim += dlam;
486 }
487
488 }
489
490 /* Handle regular pixels */
491
492 dlam = (ulam - llam) / (2 * SC_SAMPFAC);
493 llim = (llam + clam) / 2;
494 lam = llim + dlam / 2;
495
496 for (k = 0; k < SC_SAMPFAC; k++) {
497 j++;
498 cpl_table_set(groupspec, "lam", j, lam);
499 cpl_table_set(groupspec, "minlam", j, llim);
500 lam += dlam;
501 llim += dlam;
502 }
503
504 /* Handle pixels of upper margin */
505
506 if (i == nrow - 2) {
507
508 dlam = (ulam - clam) / SC_SAMPFAC;
509 llim = (clam + ulam) / 2;
510 lam = llim + dlam / 2;
511
512 for (k = 0; k < (SC_EXTRACOVER + 1) * SC_SAMPFAC + 1; k++) {
513 j++;
514 cpl_table_set(groupspec, "lam", j, lam);
515 cpl_table_set(groupspec, "minlam", j, llim);
516 lam += dlam;
517 llim += dlam;
518 }
519
520 }
521
522 }
523
524 return CPL_ERROR_NONE;
525}
526
527
528cpl_error_code sc_weights_getgrouplines(cpl_table *groupspec,
529 cpl_table *fitpar, cpl_table *groups,
530 const cpl_parameterlist *parlist,
531 const char grouptype, const int group)
532{
558 const cpl_parameter *p;
559 char groupcol[SC_LENLINE+1];
560 cpl_boolean found = CPL_FALSE;
561 int nsel = 0, npix = 0, row = 0, i = 0, j = 0;
562 double llim = 0., lam = 0., lflux = 0., ulim = 0., dlam = 0., pflux = 0.;
563
564 /* Select rows that belong to given line group */
565 cpl_table_unselect_all(groups);
566 sprintf(groupcol, "group%c", grouptype);
567 nsel = cpl_table_or_selected_int(groups, groupcol, CPL_EQUAL_TO, group);
568
569 /* Set flux in group spectrum to zero */
570 npix = cpl_table_get_nrow(groupspec);
571 cpl_table_fill_column_window(groupspec, "flux", 0, npix, 0);
572
573 /* Change fit flag to 0 and return if desired group could not be found */
574 if (nsel <= 0) {
575 if (grouptype == 'B') {
576 p = cpl_parameterlist_find_const(parlist, "n_groupA");
577 row = cpl_parameter_get_int(p) + group - 1;
578 } else {
579 row = group - 1;
580 }
581 if (group > 0) {
582 cpl_table_set(fitpar, "relevance", row, 0);
583 cpl_table_set(fitpar, "fit", row, 0);
584 }
585 return CPL_ERROR_NONE;
586 }
587
588 /* Find lines of selected group and enter their fluxes in rows of the
589 output table that cover the wavelengths of these lines */
590 llim = cpl_table_get(groupspec, "lam", 0, NULL);
591 for (i = 0; i < cpl_table_get_nrow(groups); i++) {
592 if (cpl_table_is_selected(groups, i) == 1) {
593 lam = cpl_table_get(groups, "lambda", i, NULL);
594 lflux = cpl_table_get(groups, "flux", i, NULL);
595 found = CPL_FALSE;
596 do {
597 if (j >= npix - 1) break; // strange behaviour of 'while'
598 ulim = cpl_table_get(groupspec, "lam", j+1, NULL);
599 if (lam >= llim && lam < ulim) {
600 found = CPL_TRUE;
601 dlam = ulim - llim;
602 pflux = cpl_table_get(groupspec, "flux", j, NULL);
603 pflux += lflux / dlam;
604 cpl_table_set(groupspec, "flux", j, pflux);
605 } else {
606 llim = ulim;
607 j++;
608 }
609 } while (found == CPL_FALSE && j < npix - 1);
610 }
611 }
612
613 /* Cancel row selection */
614 cpl_table_select_all(groups);
615
616 return CPL_ERROR_NONE;
617}
618
619
620cpl_error_code sc_weights_convolve(cpl_table *groupspec, const double fwhm,
621 const double reflam, const double speedpar)
622{
647 cpl_array *flux = NULL, *convflux = NULL, *kernel = NULL;
648 char errtxt[SC_MAXLEN];
649 int m = 0, range[2] = {0, 0}, i = 0;
650 double llam = 0., ulam = 0., clam = 0., cfwhm = 0.;
651 double *vec, *lam;
652
653 /* Check number of data points in spectrum */
654 m = cpl_table_get_nrow(groupspec);
655 if (m <= 0) {
656 sprintf(errtxt, "%s: cpl_table *groupspec", SC_ERROR_NDA_TXT);
657 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_NDA, "%s", errtxt);
658 }
659
660 /* Check for invalid input parameters */
661 if (fwhm < 0.) {
662 sprintf(errtxt, "%s: fwhm < 0", SC_ERROR_IIP_TXT);
663 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IIP, "%s", errtxt);
664 }
665 if (reflam <= 0.) {
666 sprintf(errtxt, "%s: reflam <= 0", SC_ERROR_IIP_TXT);
667 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IIP, "%s", errtxt);
668 }
669 if (speedpar < 0.) {
670 sprintf(errtxt, "%s: speedpar < 0", SC_ERROR_IIP_TXT);
671 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IIP, "%s", errtxt);
672 }
673
674 /* Check existence of 'lambda' and 'flux' columns */
675 if (cpl_table_has_column(groupspec, "lam") != 1) {
676 sprintf(errtxt, "%s: cpl_table *groupspec (no 'lam' column)",
677 SC_ERROR_IOS_TXT);
678 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IOS, "%s", errtxt);
679 }
680 if (cpl_table_has_column(groupspec, "flux") != 1) {
681 sprintf(errtxt, "%s: cpl_table *groupspec (no 'flux' column)",
682 SC_ERROR_IOS_TXT);
683 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IOS, "%s", errtxt);
684 }
685
686 /* Copy flux column into CPL array */
687 vec = cpl_table_get_data_double(groupspec, "flux");
688 flux = cpl_array_new(m, CPL_TYPE_DOUBLE);
689 cpl_array_copy_data_double(flux, vec);
690
691 /* Create CPL array for convolved flux */
692 convflux = cpl_array_new(m, CPL_TYPE_DOUBLE);
693 cpl_array_fill_window_double(convflux, 0, m, 0.);
694
695 /* Get pointer to wavelength */
696 lam = cpl_table_get_data_double(groupspec, "lam");
697
698 /* CPL array for kernel */
699 kernel = cpl_array_new(0, CPL_TYPE_DOUBLE);
700
701 /* Convolve spectral ranges with kernel */
702
703 do {
704
705 /* Get lower and upper wavelengths of range */
706 llam = lam[range[0]];
707 ulam = llam * (1 + speedpar);
708
709 /* Find upper range pixel */
710 i = range[0];
711 while (i < m && lam[i] < ulam) {
712 i++;
713 }
714 if (i == m) {
715 range[1] = m-1;
716 } else {
717 range[1] = i;
718 }
719
720 /* Get central wavelength of range */
721 ulam = lam[range[1]];
722 clam = (ulam + llam) / 2;
723
724 /* Scale FWHM of kernel if variable kernel is requested */
725 if (speedpar == HUGE_VAL) {
726 cfwhm = fwhm;
727 } else {
728 cfwhm = fwhm * clam / reflam;
729 }
730
731 /* Calculate Gaussian kernel */
732 sc_weights_calckernel(kernel, cfwhm);
733
734 /* Convolve spectrum with Gaussian kernel */
735 sc_basic_convolvewindow(convflux, flux, range, kernel);
736
737 /* Set next lower range pixel */
738 range[0] = range[1] + 1;
739
740 } while (range[0] < m);
741
742 /* Copy resulting flux array into "flux" column of input CPL table */
743 vec = cpl_array_get_data_double(convflux);
744 cpl_table_copy_data_double(groupspec, "flux", vec);
745
746 /* Free memory */
747 cpl_array_delete(flux);
748 cpl_array_delete(convflux);
749 cpl_array_delete(kernel);
750
751 return CPL_ERROR_NONE;
752}
753
754
755cpl_error_code sc_weights_calckernel(cpl_array *kernel, const double fwhm)
756{
773 char errtxt[SC_MAXLEN];
774 int nkpix = 0, k = 0, nx = 0, refpix = 0, i = 0;
775 double *kern;
776 double sigma = 0, xmax = 0, xmin = 0, dx = 0, x = 0, sum = 0;
777
778 /* Check FWHM */
779 if (fwhm < 0.) {
780 kernel = NULL;
781 sprintf(errtxt, "%s: fwhm < 0", SC_ERROR_IIP_TXT);
782 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IIP, "%s", errtxt);
783 }
784
785 /* sigma of Gaussian */
786 sigma = fwhm / CPL_MATH_FWHM_SIG;
787
788 /* Number of kernel pixels */
789 nkpix = 2 * ceil(fwhm * SC_KERNFAC / 2 - 0.5) + 1;
790 cpl_array_set_size(kernel, nkpix);
791
792 /* Kernel with one pixel only */
793 if (nkpix == 1) {
794 cpl_array_set(kernel, 0, 1.);
795 return CPL_ERROR_NONE;
796 }
797
798 /* Get pointer to CPL array */
799 cpl_array_fill_window_double(kernel, 0, nkpix, 0.);
800 kern = cpl_array_get_data_double(kernel);
801
802 /* Integration limits for upper bin */
803 xmax = 0.5 * nkpix;
804 xmin = xmax - 1;
805
806 /* Number of wavelengths for integration of Gaussian */
807 nx = ceil(SC_BINS_PER_FWHM / fwhm);
808
809 /* Wavelength step for integration of Gaussian */
810 dx = 1. / nx;
811
812 /* Reference pixel for mirroring of kernel values */
813 refpix = floor(nkpix / 2.);
814
815 /* Calculate kernel up to reference pixel */
816
817 for (k = nkpix - 1; k >= refpix; k--) {
818
819 if (xmax <= 0.) {
820
821 /* Skip integration */
822 kern[k] = 1.;
823
824 } else {
825
826 /* First relative wavelength for integration */
827 x = xmin + dx / 2;
828
829 /* Perform integration */
830
831 kern[k] = 0.;
832
833 for (i = 0; i < nx; i++) {
834 kern[k] += exp(-0.5 * pow(x / sigma, 2));
835 x += dx;
836 }
837
838 kern[k] /= (double) nx;
839
840 }
841
842 /* Shift integration limits for next bin */
843 xmax = xmin;
844 xmin = xmax - 1;
845
846 }
847
848 /* Mirror right wing of kernel */
849 for (k = refpix - 1; k >= 0; k--) {
850 kern[k] = kern[nkpix - k - 1];
851 }
852
853
854 /* Add all kernel values */
855 for (k = 0; k < nkpix; k++) {
856 if (kern[k] < 0.) {
857 kern[k] = 0.;
858 }
859 sum += kern[k];
860 }
861
862 /* Normalise kernel values */
863 for (k = 0; k < nkpix; k++) {
864 kern[k] /= sum;
865 }
866
867 return CPL_ERROR_NONE;
868}
869
870
871cpl_error_code sc_weights_rebinspec(cpl_table *skyspec,
872 const cpl_table *groupspec)
873{
892 char errtxt[SC_MAXLEN];
893 int nrow = 0, npix = 0, jmin = 0, jmax = 0, jrow = 0, j = 0, k = 0, i = 0;
894 double flux = 0.;
895 const double * g_flux = NULL;
896
897 /* Get number of pixels in input and output spectrum */
898 nrow = cpl_table_get_nrow(skyspec);
899 npix = cpl_table_get_nrow(groupspec);
900
901 /* Get limiting pixels and check number of pixels */
902 jmin = SC_EXTRACOVER * SC_SAMPFAC;
903 jmax = npix - SC_EXTRACOVER * SC_SAMPFAC - 2;
904 jrow = (jmax - jmin + 1) / SC_SAMPFAC;
905 if (jrow != nrow) {
906 sprintf(errtxt, "%s: cpl_table *groupspec (unexpected pixel number)",
907 SC_ERROR_IOS_TXT);
908 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IOS, "%s", errtxt);
909 }
910
911 /* Sum up fluxes in line group spectrum to get pixel-specific fluxes in
912 sky spectrum */
913 if (cpl_table_count_invalid(groupspec, "flux") == 0)
914 g_flux = cpl_table_get_data_double_const(groupspec, "flux");
915 for (j = jmin; j <= jmax; j++) {
916 if (k < SC_SAMPFAC) {
917 flux += g_flux ?
918 g_flux[j] : cpl_table_get(groupspec, "flux", j, NULL);
919 k++;
920 }
921 if (k == SC_SAMPFAC) {
922 cpl_table_set(skyspec, "f_group", i, flux);
923 flux = 0.;
924 k = 0;
925 i++;
926 }
927 }
928
929 /* Add line group fluxes to total airglow flux */
930 cpl_table_add_columns(skyspec, "f_all", "f_group");
931
932 return CPL_ERROR_NONE;
933}
934
935
936cpl_error_code sc_weights_fillgrouparrays(cpl_table *skyspec,
937 const char grouptype,
938 const int group)
939{
960 cpl_array *narray = NULL, *warray = NULL;
961 char ncolname[SC_LENLINE+1], wcolname[SC_LENLINE+1];
962 int nrow = 0, i = 0, size = 0, nfree = 0, ngroup = 0;
963 double flux = 0.;
964
965 /* Build table column names */
966 sprintf(ncolname, "ng%c", grouptype);
967 sprintf(wcolname, "wg%c", grouptype);
968
969 /* Get number of table rows */
970 nrow = cpl_table_get_nrow(skyspec);
971
972 /* Fill the array columns with group IDs and line fluxes */
973
974 for (i = 0; i < nrow; i++) {
975
976 flux = cpl_table_get(skyspec, "f_group", i, NULL);
977
978 if (flux > 0) {
979
980 /* Get arrays */
981 narray = cpl_array_duplicate(cpl_table_get_array(skyspec,
982 ncolname, i));
983 warray = cpl_array_duplicate(cpl_table_get_array(skyspec,
984 wcolname, i));
985
986 /* Number of unfilled array elements */
987 size = cpl_array_get_size(narray);
988 if (size == 0) {
989 nfree = 0;
990 } else {
991 nfree = cpl_array_count_invalid(narray);
992 }
993
994 /* Resize array columns if more groups contribute to a pixel than
995 allowed by the set depth of the array table columns in the sky
996 spectrum */
997 if (nfree == 0) {
998 cpl_table_set_column_depth(skyspec, ncolname, size+1);
999 cpl_table_set_column_depth(skyspec, wcolname, size+1);
1000 cpl_array_set_size(narray, size+1);
1001 cpl_array_set_size(warray, size+1);
1002 }
1003
1004 /* New number of groups in the array */
1005 ngroup = size - nfree + 1;
1006
1007 /* Add ID and flux of given group */
1008 cpl_array_set(narray, ngroup-1, group);
1009 cpl_array_set(warray, ngroup-1, flux);
1010
1011 /* Fill table columns with modified arrays */
1012 cpl_table_set_array(skyspec, ncolname, i, narray);
1013 cpl_table_set_array(skyspec, wcolname, i, warray);
1014
1015 /* Delete arrays */
1016 cpl_array_delete(narray);
1017 cpl_array_delete(warray);
1018
1019 }
1020
1021 }
1022
1023 return CPL_ERROR_NONE;
1024}
1025
1026
1027cpl_error_code sc_weights_normpixcontrib(cpl_table *skyspec,
1028 const char grouptype)
1029{
1047 cpl_array *warray = NULL;
1048 char wcolname[SC_LENLINE+1];
1049 int nrow = 0, i = 0;
1050 double sumflux = 0.;
1051
1052 /* Build weight column name */
1053 sprintf(wcolname, "wg%c", grouptype);
1054
1055 /* Get number of table rows */
1056 nrow = cpl_table_get_nrow(skyspec);
1057
1058 /* Normalise fluxes in arrays by total flux */
1059
1060 for (i = 0; i < nrow; i++) {
1061
1062 sumflux = cpl_table_get(skyspec, "f_all", i, NULL);
1063
1064 if (sumflux > 0) {
1065
1066 /* Get flux array for pixel i */
1067 warray = cpl_array_duplicate(cpl_table_get_array(skyspec,
1068 wcolname, i));
1069 /* Divide fluxes by total flux */
1070 cpl_array_divide_scalar(warray, sumflux);
1071
1072 //printf("type %c: pixel %d:\n", grouptype, i+1);
1073 //cpl_array_dump(warray, 0, cpl_array_get_size(warray), NULL);
1074
1075 /* Fill weight column with corrected array */
1076 cpl_table_set_array(skyspec, wcolname, i, warray);
1077
1078 /* Delete array */
1079 cpl_array_delete(warray);
1080
1081 }
1082
1083 }
1084
1085 return CPL_ERROR_NONE;
1086}
1087
1088
1089cpl_error_code sc_weights_getdomgroups(cpl_table *skyspec,
1090 const cpl_parameterlist *parlist,
1091 const char grouptype)
1092{
1113 const cpl_parameter *p;
1114 cpl_array *narray = NULL, *warray = NULL;
1115 char ncolname[SC_LENLINE+1], wcolname[SC_LENLINE+1];
1116 char dcolname[SC_LENLINE+1];
1117 int nrow = 0, initid = -99, depth = 0, i = 0, n = 0, j = 0, group = 0;
1118 int mgroup = 0;
1119 double weightlim = 0., mwgroup = 0., wgroup = 0.;
1120
1121 /* Build column names */
1122 sprintf(ncolname, "ng%c", grouptype);
1123 sprintf(wcolname, "wg%c", grouptype);
1124 sprintf(dcolname, "dg%c", grouptype);
1125
1126 /* Get number of table rows */
1127 nrow = cpl_table_get_nrow(skyspec);
1128
1129 /* Initialise column for dominating groups with initid */
1130 cpl_table_fill_column_window(skyspec, dcolname, 0, nrow, initid);
1131
1132 /* Get depth of line group column */
1133 depth = cpl_table_get_column_depth(skyspec, ncolname);
1134
1135 /* No groups -> return */
1136 if (depth == 0) {
1137 return CPL_ERROR_NONE;
1138 }
1139
1140 /* Get weight limit from parameter list */
1141 p = cpl_parameterlist_find_const(parlist, "weightlim");
1142 weightlim = cpl_parameter_get_double(p);
1143
1144 /* Get numbers of pixel-dominating groups */
1145
1146 for (i = 0; i < nrow; i++) {
1147
1148 /* Get arrays */
1149 narray = cpl_array_duplicate(cpl_table_get_array(skyspec, ncolname,
1150 i));
1151 warray = cpl_array_duplicate(cpl_table_get_array(skyspec, wcolname,
1152 i));
1153
1154 /* Get number of contributing line groups */
1155 n = depth - cpl_array_count_invalid(narray);
1156
1157 /* Skip pixel if no line group contributes */
1158 if (n == 0) {
1159 cpl_array_delete(narray);
1160 cpl_array_delete(warray);
1161 continue;
1162 }
1163
1164 /* Find group with highest weight for given pixel */
1165 for (mwgroup = 0., j = 0; j < n; j++) {
1166 group = cpl_array_get(narray, j, NULL);
1167 wgroup = cpl_array_get(warray, j, NULL);
1168 if (wgroup > mwgroup) {
1169 mgroup = group;
1170 mwgroup = wgroup;
1171 }
1172 }
1173
1174 /* Write number of strongest group in dgA or dgB column
1175 if weight >= weightlim from general parameter list */
1176 if (mwgroup >= weightlim) {
1177 cpl_table_set(skyspec, dcolname, i, mgroup);
1178 }
1179
1180 /* Delete arrays */
1181 cpl_array_delete(narray);
1182 cpl_array_delete(warray);
1183
1184 }
1185
1186 return CPL_ERROR_NONE;
1187}
1188
#define SC_MAXLEN
Definition: sc_basic.h:94
#define SC_LENLINE
Definition: sc_basic.h:92
cpl_error_code sc_basic_convolvewindow(cpl_array *convflux, const cpl_array *flux, const int range[2], const cpl_array *kernel)
Definition: sc_basic.c:564
cpl_error_code sc_weights_fillgrouparrays(cpl_table *skyspec, const char grouptype, const int group)
Definition: sc_weights.c:936
cpl_error_code sc_weights_createwavegrid(cpl_table *groupspec, const cpl_table *skyspec)
Definition: sc_weights.c:416
cpl_error_code sc_weights_calckernel(cpl_array *kernel, const double fwhm)
Definition: sc_weights.c:755
cpl_error_code sc_weights_normpixcontrib(cpl_table *skyspec, const char grouptype)
Definition: sc_weights.c:1027
cpl_error_code sc_weights(cpl_table *skyspec, cpl_table *fitpar, cpl_table *groups, cpl_parameterlist *parlist)
Definition: sc_weights.c:49
cpl_error_code sc_weights_getgrouplines(cpl_table *groupspec, cpl_table *fitpar, cpl_table *groups, const cpl_parameterlist *parlist, const char grouptype, const int group)
Definition: sc_weights.c:528
cpl_error_code sc_weights_getpixcontrib(cpl_table *skyspec, cpl_table *fitpar, cpl_table *groups, const cpl_parameterlist *parlist)
Definition: sc_weights.c:253
cpl_error_code sc_weights_rebinspec(cpl_table *skyspec, const cpl_table *groupspec)
Definition: sc_weights.c:871
cpl_error_code sc_weights_getdomgroups(cpl_table *skyspec, const cpl_parameterlist *parlist, const char grouptype)
Definition: sc_weights.c:1089
cpl_error_code sc_weights_initfitpar(cpl_table *fitpar, cpl_parameterlist *parlist, const cpl_table *groups)
Definition: sc_weights.c:88
cpl_error_code sc_weights_convolve(cpl_table *groupspec, const double fwhm, const double reflam, const double speedpar)
Definition: sc_weights.c:620
#define SC_EXTRACOVER
Definition: sc_weights.h:67
#define SC_KERNFAC
Definition: sc_weights.h:76
#define SC_COLDEPTH
Definition: sc_weights.h:64
#define SC_SAMPFAC
Definition: sc_weights.h:69
#define SC_LIMRELLAMVAR
Definition: sc_weights.h:72
#define SC_BINS_PER_FWHM
Definition: sc_weights.h:74