ERIS Pipeline Reference Manual 1.8.15
eris_ifu_lambda_corr.c
1/*
2 * This file is part of the KMOS Pipeline
3 * Copyright (C) 2002,2003 European Southern Observatory
4 *
5 * This program 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 program 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 program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 * Includes
26 *----------------------------------------------------------------------------*/
27
28#include <math.h>
29#include <stdio.h>
30
31#include <cpl.h>
32
33#include "eris_ifu_lambda_corr.h"
34#include "eris_ifu_jitter_static.h"
35#include "eris_ifu_error.h"
36
37FILE *IDL = NULL;
38/*----------------------------------------------------------------------------*/
58/*----------------------------------------------------------------------------*/
59
60/*----------------------------------------------------------------------------*/
83/*----------------------------------------------------------------------------*/
84cpl_polynomial *eris_ifu_lcorr_get(cpl_imagelist *cube, hdrl_imagelist *hdrlCube,
85 const cpl_propertylist *header,
86 cpl_vector *peaks,
87 const int pfit_order)
88{
89 cpl_polynomial *lcorr_coeffs = NULL;
90 cpl_imagelist *tmpCube = NULL;
91 cpl_image *tmpImg = NULL;
92 cpl_bivector *obj_spectrum = NULL,
93 *ref_spectrum = NULL;
94 int ic = 0;
95 const int format_width = 14,
96 max_coeffs = 6;
97 char *coeff_string = NULL,
98 coeff_dump[format_width * max_coeffs + 1];
99 cpl_size pows[1];
100 ifsBand bandId = UNDEFINED_BAND;
101 //const char *ref_filename = NULL;
102 //TODO: why we need filter_id, and later that is set, but never used?
103// const char *filter_id;
104
105 TRY
106 {
107 ASSURE(cube != NULL || hdrlCube != NULL,
108 CPL_ERROR_ILLEGAL_INPUT, "One of cube or hdrlCube must be not NULL");
109 ASSURE(!(cube != NULL && hdrlCube != NULL),
110 CPL_ERROR_ILLEGAL_INPUT, "One of cube or hdrlCube must be NULL");
111 ASSURE((peaks != NULL),
112 CPL_ERROR_NULL_INPUT, "Not all input data is provided!");
113
114 bandId = eris_ifu_get_band(header);
115// switch (bandId) {
116// case J_LOW:
117// case J_SHORT: case J_MIDDLE: case J_LONG:
118// case J_SPIFFI:
119// filter_id = "J";
120// break;
121// case H_LOW:
122// case H_SHORT: case H_MIDDLE: case H_LONG:
123// case H_SPIFFI:
124// filter_id = "H";
125// break;
126// case K_LOW:
127// case K_SHORT: case K_MIDDLE: case K_LONG:
128// case K_SPIFFI:
129// filter_id = "K";
130// break;
131// case HK_SPIFFI:
132// filter_id = "HK";
133// break;
134// default:
135// filter_id = "X";
136// break;
137// }
138
139 if (cube != NULL) {
140 tmpCube = cube;
141 } else {
142 tmpCube = cpl_imagelist_new();
143 for (cpl_size sx = 0; sx < hdrl_imagelist_get_size(hdrlCube); sx++) {
144 tmpImg = hdrl_image_get_image(hdrl_imagelist_get(hdrlCube, sx));
145 cpl_imagelist_set(tmpCube, cpl_image_duplicate(tmpImg), sx);
146 }
148 }
149
152
153
155 obj_spectrum = eris_ifu_lcorr_extract_spectrum(tmpCube, header, 0.8, NULL));
156 //clean memory from temporary object. TODO: generate seg fault. Why??
157 /*
158 if (cube == NULL) {
159 for (cpl_size sx = 0; sx < cpl_imagelist_get_size(tmpCube); sx++) {
160 cpl_imagelist_unset(tmpCube,sx);
161 }
162 }
163 */
164 cpl_imagelist_delete(tmpCube);
166 lcorr_coeffs = eris_ifu_lcorr_crosscorrelate_spectra(obj_spectrum,
167 peaks, bandId, pfit_order));
168
169 // debug stuff
170 coeff_dump[0] = 0;
171 for (ic = 0; ic <= cpl_polynomial_get_degree(lcorr_coeffs) && ic < max_coeffs; ic++) {
172 pows[0] = ic;
173 coeff_string = cpl_sprintf(" %*g,", format_width-2, cpl_polynomial_get_coeff(lcorr_coeffs,pows));
174 strncat(coeff_dump, coeff_string, format_width);
175 cpl_free(coeff_string); coeff_string = NULL;
176 }
177 cpl_msg_debug(cpl_func,"Lambda correction coeffs %s", coeff_dump);
178 }
179 CATCH
180 {
181 cpl_polynomial_delete(lcorr_coeffs); lcorr_coeffs = NULL;
182 }
183
184 cpl_bivector_delete(ref_spectrum); ref_spectrum = NULL;
185 cpl_bivector_delete(obj_spectrum); obj_spectrum = NULL;
186 cpl_free(coeff_string); coeff_string = NULL;
187
188 return lcorr_coeffs;
189}
190
191/*----------------------------------------------------------------------------*/
212/*----------------------------------------------------------------------------*/
213cpl_bivector *eris_ifu_lcorr_extract_spectrum (const cpl_imagelist *cube,
214 const cpl_propertylist *header,
215 const double min_frac,
216 const cpl_vector *range) {
217
218 cpl_bivector *result = NULL;
219 cpl_vector *spectrum = NULL,
220 *lambda = NULL;
221 cpl_image *obj_mask = NULL;
222 TRY
223 {
224 ASSURE(cube != NULL && header != NULL,
225 CPL_ERROR_NULL_INPUT,
226 "Not all input data is provided!");
227
229 lambda = eris_ifu_lcorr_create_lambda_vector(header));
230
231 if (range != NULL) {
233 obj_mask = eris_ifu_lcorr_create_object_mask(cube, min_frac, lambda, range));
234 } else {
236 obj_mask = eris_ifu_lcorr_create_object_mask(cube, min_frac, NULL, NULL));
237 }
238
240 eris_ifu_extract_spec(cube, NULL, obj_mask, &spectrum, NULL));
241
243 result = cpl_bivector_wrap_vectors(lambda, spectrum));
244 }
245 CATCH
246 {
247 CATCH_MSG();
248 }
249
250 if (obj_mask != NULL) {cpl_image_delete(obj_mask);}
251 if (result == NULL) {
252 if (lambda != NULL) {cpl_vector_delete(lambda);}
253 if (spectrum != NULL) {cpl_vector_delete(spectrum);}
254 }
255 return result;
256}
257
258/*----------------------------------------------------------------------------*/
282/*----------------------------------------------------------------------------*/
283cpl_image *eris_ifu_lcorr_create_object_mask (const cpl_imagelist *cube,
284 double min_frac,
285 const cpl_vector *lambda,
286 const cpl_vector *range) {
287
288 cpl_image *mask = NULL;
289 cpl_imagelist *rcube = NULL;
290 const cpl_image *slice = NULL;
291 cpl_imagelist *icube = NULL;
292 cpl_image *tmp_img = NULL,
293 *m_img = NULL;
294 cpl_vector *sum = NULL,
295 *m_vector = NULL,
296 *sorted_sum = NULL;
297 cpl_mask *empty_mask = NULL;
298
299 int x, y, z, r;
300 int nx, ny, nz, nr, px, cnz= 0;
301 int check4range = FALSE;
302 const double *lambda_data = NULL;
303 double l_low, l_up = 0.0;
304 double max_value = 0.0;
305 int *cnts = NULL;
306 double *m_data = NULL;
307 float *mask_data = NULL;
308
309 TRY
310 {
311 ASSURE(cube != NULL,
312 CPL_ERROR_NULL_INPUT,
313 "Not all input data is provided!");
314
315 ASSURE(((lambda != NULL) && (range != NULL)) ||
316 ((lambda == NULL) && (range == NULL)) ,
317 CPL_ERROR_NULL_INPUT,
318 "Not all input data is provided!");
319 if (range != NULL) {
320 check4range = TRUE;
321 ASSURE(cpl_vector_get_size(range)%2 == 0,
322 CPL_ERROR_ILLEGAL_INPUT,
323 "Range vector size must be a multiple of 2");
324
325 nr = cpl_vector_get_size(range) / 2;
326 }
327
328 if (lambda != NULL) {
329 ASSURE(cpl_vector_get_size(lambda) == cpl_imagelist_get_size(cube),
330 CPL_ERROR_ILLEGAL_INPUT,
331 "Size of lambda vector must be the number of images in the input cube");
333 lambda_data = cpl_vector_get_data_const(lambda));
334 }
335
337 slice = cpl_imagelist_get_const(cube, 0));
338 nx = cpl_image_get_size_x(slice);
339 ny = cpl_image_get_size_y(slice);
340 nz = cpl_imagelist_get_size(cube);
341
342 // if wavelength range are specified create a new imagelist holding only those lambdas
343 // otherwise take original input cube
344 if (check4range) {
345 cnz = 0;
347 rcube = cpl_imagelist_new());
348 for (z=0; z<nz; z++) {
349 int checkOK = FALSE;
350 for (r=0; r<nr; r++) {
351 l_low = cpl_vector_get(range, r*2);
352 l_up = cpl_vector_get(range, r*2+1);
353 if ((lambda_data[z] >= l_low) && (lambda_data[z] <= l_up)) {
354 checkOK = TRUE;
355 break;
356 }
357 }
358 if (checkOK) {
360 slice = cpl_imagelist_get_const(cube, z));
362 cpl_imagelist_set(rcube, cpl_image_duplicate(slice), cnz));
363 cnz++;
364 }
365 }
366 icube = rcube;
367 } else {
368 icube = (cpl_imagelist*) cube;
369 }
373 tmp_img = cpl_imagelist_collapse_median_create(icube));
375 m_img = cpl_image_cast(tmp_img, CPL_TYPE_DOUBLE));
377 m_data = cpl_image_get_data_double(m_img));
379 m_vector = cpl_vector_wrap(nx * ny, m_data));
381 sorted_sum = cpl_vector_duplicate(m_vector));
382 cpl_vector_sort(sorted_sum, CPL_SORT_ASCENDING);
383 max_value = cpl_vector_get(sorted_sum, nx*ny*min_frac);
384
385 mask = cpl_image_new(nx,ny,CPL_TYPE_FLOAT);
387 mask_data = cpl_image_get_data_float(mask));
388 for (x=0; x<nx; x++) {
389 for (y=0; y<ny; y++) {
390 px = x+y*nx;
391 if (m_data[px] <= max_value) {
392 mask_data[px] = 1.0;
393 } else {
394 mask_data[px] = 0.0;
395 }
396 }
397 }
398
399 }
400 CATCH
401 {
402 CATCH_MSG();
403 if (mask != NULL) {cpl_image_delete(mask);}
404 mask = NULL;
405 }
406 if (rcube != NULL) {cpl_imagelist_delete(rcube);}
407 if (tmp_img != NULL) {cpl_image_delete(tmp_img);}
408 if (m_img != NULL) {cpl_image_delete(m_img);}
409 if (m_vector != NULL) {cpl_vector_unwrap(m_vector);}
410 if (sum != NULL) {cpl_vector_delete(sum);}
411 if (cnts != NULL) {cpl_free(cnts);}
412 if (sorted_sum != NULL) {cpl_vector_delete(sorted_sum);}
413 if (empty_mask != NULL) {cpl_mask_delete(empty_mask);}
414
415 return mask;
416}
417
418/*----------------------------------------------------------------------------*/
434/*----------------------------------------------------------------------------*/
435
436cpl_vector *eris_ifu_lcorr_create_lambda_vector(const cpl_propertylist *header) {
437
438 cpl_vector *lambda_vector = NULL;
439 int naxis3, z = 0;
440 double crval3, cdelt3, crpix3 = 0.0;
441 double *lambda = NULL;
442
443 TRY {
444 ASSURE(header != NULL,
445 CPL_ERROR_NULL_INPUT,
446 "Not all input data is provided!");
447 ASSURE(cpl_propertylist_has(header,NAXIS3) &&
448 cpl_propertylist_has(header,CRVAL3) &&
449 cpl_propertylist_has(header,CDELT3) &&
450 cpl_propertylist_has(header,CRPIX3),
451 CPL_ERROR_ILLEGAL_INPUT,
452 "missing WCS keywords in header");
453
454 naxis3 = cpl_propertylist_get_int(header, NAXIS3);
455 crval3 = cpl_propertylist_get_double(header, CRVAL3);
456 cdelt3 = cpl_propertylist_get_double(header, CDELT3);
457 crpix3 = cpl_propertylist_get_double(header, CRPIX3);
458
460 lambda_vector = cpl_vector_new(naxis3));
462 lambda = cpl_vector_get_data(lambda_vector));
463
464 for (z=0; z<naxis3; z++) {
465 lambda[z] = (z+1 - crpix3) * cdelt3 + crval3;
466 }
467 }
468 CATCH
469 {
470 CATCH_MSG();
471 if (lambda_vector != NULL) {
472 cpl_vector_delete(lambda_vector);
473 lambda_vector = NULL;
474 }
475 }
476
477 return lambda_vector;
478}
479
480/*----------------------------------------------------------------------------*/
498/*----------------------------------------------------------------------------*/
499cpl_bivector *eris_ifu_lcorr_read_OH_reference_spectrum(const char *filename,
500 cpl_size ext_number) {
501
502 cpl_bivector *result = NULL;
503 cpl_vector *lambda = NULL,
504 *spec = NULL;
505 cpl_propertylist *header = NULL;
506 double *lambda_data = NULL;
507 double crpix, crval, cdelt = 0.0;
508 int naxis1 = 0;
509
510 TRY {
511 ASSURE(filename != NULL,
512 CPL_ERROR_NULL_INPUT,
513 "Not all input data is provided!");
514
515 cpl_msg_info(__func__,
516 "Using file %s as OH reference spectrum for lambda correction",
517 filename);
518
519 spec = cpl_vector_load(filename, ext_number);
520 if (cpl_error_get_code() != CPL_ERROR_NONE) {
521 if (cpl_error_get_code() == CPL_ERROR_FILE_IO) {
522 cpl_msg_error("", "File not found: %s", filename);
523 } else {
524 cpl_msg_error("", "Problem loading file '%s' (%s --> Code %d)",
525 filename, cpl_error_get_message(),
526 cpl_error_get_code());
527 }
528 }
529
531 header = cpl_propertylist_load(filename, ext_number));
532
533 naxis1 = cpl_propertylist_get_int(header, NAXIS1);
535 crval = cpl_propertylist_get_double(header, CRVAL1);
537 cdelt = cpl_propertylist_get_double(header, CDELT1);
539 switch (cpl_propertylist_get_type(header, CRPIX1)) {
540 case CPL_TYPE_INT:
541 crpix = cpl_propertylist_get_int(header, CRPIX1);
542 break;
543 case CPL_TYPE_DOUBLE:
544 crpix = cpl_propertylist_get_double(header, CRPIX1);
545 break;
546 case CPL_TYPE_FLOAT:
547 crpix = cpl_propertylist_get_float(header, CRPIX1);
548 break;
549 default:
550 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
551 "CRPIX1 is of wrong type!");
552 }
554
556 lambda = cpl_vector_new(naxis1));
558 lambda_data = cpl_vector_get_data(lambda));
559 int i = 0;
560 for (i = 0; i < naxis1; i++) {
561 lambda_data[i] = crval + (i + 1-crpix)*cdelt;
562 }
563
565 result = cpl_bivector_wrap_vectors(lambda, spec));
566 }
567 CATCH
568 {
569 CATCH_MSG();
570 }
571
572 if (header != NULL) {cpl_propertylist_delete(header);}
573
574 return result;
575
576}
577
578/*----------------------------------------------------------------------------*/
600/*----------------------------------------------------------------------------*/
601
602cpl_array *eris_ifu_lcorr_get_peak_positions(const cpl_bivector *spectrum,
603 double min_frac,
604 cpl_vector *range) {
605
606 cpl_array *positions = NULL;
607
608 cpl_vector *copied_spectrum = NULL;
609
610 int spec_size = 0,
611 peak_cnt = 0,
612 nr = 0,
613 i = 0,
614 r = 0;
615 double min = 0.0,
616 l_low = 0.0,
617 l_up = 0.0;
618 double *spec_data = NULL,
619 *diff_data = NULL;
620 const double *lambda_data = NULL;
621
622 TRY {
623 ASSURE(spectrum != NULL && cpl_bivector_get_y_const(spectrum) != NULL,
624 CPL_ERROR_NULL_INPUT,
625 "Not all input data is provided!");
626
627 if (range != NULL) {
628 ASSURE(cpl_bivector_get_x_const(spectrum) != NULL,
629 CPL_ERROR_NULL_INPUT,
630 "Not all input data is provided!");
631 ASSURE(cpl_vector_get_size(range)%2 == 0,
632 CPL_ERROR_ILLEGAL_INPUT,
633 "Range vector size must be a multiple of 2");
635 lambda_data = cpl_vector_get_data_const(cpl_bivector_get_x_const(spectrum)));
636 nr = cpl_vector_get_size(range) / 2;
637 }
638
640 copied_spectrum = cpl_vector_duplicate(cpl_bivector_get_y_const(spectrum)));
641
643 spec_data = cpl_vector_get_data(copied_spectrum));
644
645 spec_size = cpl_vector_get_size(copied_spectrum);
646
647 if (range != NULL) {
648 for (i = 0; i < (spec_size-1); i++) {
649 int checkOK = FALSE;
650 for (r = 0; r < nr; r++) {
651 l_low = cpl_vector_get(range, r*2);
652 l_up = cpl_vector_get(range, r*2+1);
653 if ((lambda_data[i] >= l_low) && (lambda_data[i] <= l_up)) {
654 checkOK = TRUE;
655 break;
656 }
657 }
658 if (! checkOK) {
659 spec_data[i] = 0.;
660 }
661 }
662 }
663
665 diff_data = cpl_malloc((spec_size-1) * sizeof(double)));
666
668 positions = cpl_array_new(spec_size, CPL_TYPE_INT));
669
670 min = cpl_vector_get_max(copied_spectrum) * min_frac;
671
672 if (spec_data[0] < min) {
673 spec_data[0] = 0.;
674 }
675 for (i = 0; i < (spec_size-1); i++) {
676 if (spec_data[i+1] < min) {
677 spec_data[i+1] = 0.;
678 }
679 diff_data[i] = spec_data[i+1] - spec_data[i];
680 }
681
682 peak_cnt = 0;
683 for (i = 0; i < (spec_size-2); i++) {
684 if ((diff_data[i] > 0) && (diff_data[i+1] < 0)) {
686 cpl_array_set_int(positions, peak_cnt, i+1));
687 peak_cnt++;
688 }
689 }
691 cpl_array_set_size(positions, peak_cnt));
692 }
693 CATCH
694 {
695 CATCH_MSG();
696 if (positions != NULL) {cpl_array_delete(positions);}
697 positions = NULL;
698 }
699
700 if (diff_data != NULL) {cpl_free(diff_data);}
701 if (copied_spectrum != NULL) {cpl_vector_delete(copied_spectrum);}
702
703 return positions;
704}
705
706/*----------------------------------------------------------------------------*/
728/*----------------------------------------------------------------------------*/
729cpl_vector *eris_ifu_lcorr_get_peak_lambdas (const cpl_bivector *spectrum,
730 double min_frac,
731 cpl_vector *range) {
732
733 cpl_vector *peaks = NULL,
734 *final_peaks = NULL;
735 cpl_array *positions = NULL;
736 cpl_size no_peaks = 0,
737 spec_size = 0;
738 const int *pos_data = NULL;
739 const double *spec_data = NULL;
740 double *lambda_data = NULL;
741
742 cpl_vector *ref_fit = NULL,
743 *sigma_fit = NULL,
744 *lambda_ref = NULL,
745 *lambda_tmp = NULL,
746 *sigma_tmp = NULL;
747 int *invalid_index = NULL;
748 cpl_size peak_idx = 0;
749 double delta_lambda = 0.0,
750 lambda_in = 0.0,
751 lambda_out = 0.0,
752 sigma = 0.0,
753 l_median = 0.0,
754 l_stdev = 0.0,
755 s_median = 0.0,
756 s_stdev = 0.0,
757 l_limit = 0.0,
758 s_limit = 0.0;
759 int validPeaksCnt = 0;
760 const char *stype;
761 const int halfwidth = 5;
762
763 TRY {
764 ASSURE(spectrum != NULL &&
765 cpl_bivector_get_x_const(spectrum) != NULL &&
766 cpl_bivector_get_y_const(spectrum) != NULL,
767 CPL_ERROR_NULL_INPUT,
768 "Not all input data is provided!");
769
771 positions = eris_ifu_lcorr_get_peak_positions(spectrum, min_frac, range));
772 no_peaks = cpl_array_get_size(positions);
773
775 peaks = cpl_vector_new(no_peaks));
776
778 pos_data = cpl_array_get_data_int_const(positions));
780 spec_data = cpl_vector_get_data_const(cpl_bivector_get_x_const(spectrum)));
782 lambda_data = cpl_vector_get_data(peaks));
783
784 spec_size = cpl_bivector_get_size(spectrum);
785
786 cpl_size i = 0;
787 for (i = 0; i < no_peaks; i++) {
788 if (pos_data[i] >= spec_size) {
789 BRK_WITH_ERROR(CPL_ERROR_ACCESS_OUT_OF_RANGE);
790 }
791 lambda_data[i] = spec_data[pos_data[i]];
792 }
793
794
796 invalid_index = cpl_calloc(no_peaks, sizeof(int)));
797 // scan for peaks which are too close
798
799 delta_lambda = 1.93 / 11200.;
800
801 for (i = 0; i < no_peaks-1; i++) {
802 if ((cpl_vector_get(peaks,i+1) - cpl_vector_get(peaks,i)) < 2. * delta_lambda) {
803 invalid_index[i] = 1;
804 invalid_index[i+1] = 1;
805 cpl_msg_debug(cpl_func,
806 "Pair of peaks are rejected because they are too close: %lld - %lld, %f - %f",
807 i, i+1, cpl_vector_get(peaks,i), cpl_vector_get(peaks,i+1));
808 }
809 }
810
811 // find exact peak location by fitting a gaussian
812 // detect and withdraw outliers
814 ref_fit = cpl_vector_new(no_peaks));
816 sigma_fit = cpl_vector_new(no_peaks));
818 lambda_ref = cpl_vector_new(no_peaks));
820 lambda_tmp = cpl_vector_new(no_peaks));
822 sigma_tmp = cpl_vector_new(no_peaks));
823
824 peak_idx = 0;
825 stype="reference";
826 if (IDL !=NULL ) fprintf(IDL, "%20s: %s\n", "xcorr spectrum type", stype);
827 for (i = 0 ; i < no_peaks; i++) {
828 lambda_in = cpl_vector_get(peaks,i);
829 sigma = 0.0;
830 lambda_out = fit_peak (spectrum, spec_size, lambda_in, halfwidth, &sigma);
831 if (invalid_index[i] == 0) {
832 if (lambda_out > 0.) {
834 cpl_vector_set(ref_fit, i, lambda_out));
836 cpl_vector_set(sigma_fit, i, sigma));
838 cpl_vector_set(lambda_ref, peak_idx, lambda_in));
840 cpl_vector_set(lambda_tmp, peak_idx, lambda_out));
842 cpl_vector_set(sigma_tmp, peak_idx, sigma));
843 peak_idx++;
844 } else {
845 invalid_index[i] = 2;
846 cpl_msg_debug(cpl_func,
847 "Gaussian fit failed for %s spectrum, wavelenght %f, peak index %lld",
848 stype, lambda_in, i);
849 }
850 }
851 }
853 cpl_vector_set_size(lambda_ref,peak_idx));
855 cpl_vector_set_size(lambda_tmp,peak_idx));
857 cpl_vector_set_size(sigma_tmp,peak_idx));
858 if (IDL !=NULL ) {
859 fprintf(IDL, "%20s: %lld ", "xcorr lambda_ref", peak_idx); cpl_vector_dump(lambda_ref, IDL);
860 fprintf(IDL, "%20s: %lld ", "xcorr lambda_tmp", peak_idx); cpl_vector_dump(lambda_tmp, IDL);
861 fprintf(IDL, "%20s: %lld ", "xcorr sigma_tmp", peak_idx); cpl_vector_dump(sigma_tmp, IDL);
862 }
863
865 cpl_vector_subtract(lambda_tmp,lambda_ref));
866 l_median = cpl_vector_get_median_const(lambda_tmp);
867 l_stdev = cpl_vector_get_stdev(lambda_tmp);
868 s_median = cpl_vector_get_median_const(sigma_tmp);
869 s_stdev = cpl_vector_get_stdev(sigma_tmp);
870 l_limit = 3. * l_stdev;
871 s_limit = 3. * s_stdev;
872 if (IDL !=NULL ) fprintf(IDL, "%20s: %f %f %f %f %f %f\n", "xcorr limits", l_median, l_stdev, l_limit, s_median, s_stdev, s_limit);
873
874 for (i = 0; i < no_peaks; i++){
875 if (invalid_index[i] == 0) {
876 double tmp_lambda = cpl_vector_get(ref_fit,i) - cpl_vector_get(peaks,i);
877 double tmp_sigma = cpl_vector_get(sigma_fit,i);
878 if (fabs(tmp_lambda - l_median) > l_limit) {
879 invalid_index[i] = 3;
880 cpl_msg_debug(cpl_func,
881 "Peak rejected due lambda outlier, %s spectrum, wavelength %f, index %lld, limit %f, value %f",
882 stype, cpl_vector_get(peaks,i), i, l_limit, fabs(tmp_lambda - l_median));
883 } else if (fabs(tmp_sigma - s_median) > s_limit) {
884 cpl_msg_debug(cpl_func,
885 "Peak rejected due sigma outlier, %s spectrum, wavelength %f, index %lld, limit %f, value %f",
886 stype, cpl_vector_get(peaks,i), i, s_limit,fabs(tmp_sigma - s_median));
887 invalid_index[i] = 4;
888 }
889 }
890 }
891
892 validPeaksCnt = 0;
893 for (i = 0; i < no_peaks; i++) {
894 if (invalid_index[i] == 0) {
895 validPeaksCnt++;
896 }
897 }
898 final_peaks = cpl_vector_new(validPeaksCnt);
899 validPeaksCnt = 0;
900 for (i = 0; i < no_peaks; i++) {
901 if (invalid_index[i] == 0) {
902 cpl_vector_set(final_peaks, validPeaksCnt,
903 cpl_vector_get(ref_fit,i));
904 validPeaksCnt++;
905 }
906 }
908 }
909 CATCH
910 {
911 eris_ifu_free_vector(&final_peaks);
912 final_peaks = NULL;
913 }
914
915 if (positions != NULL) {cpl_array_delete(positions);}
916 eris_ifu_free_int_array(&invalid_index);
917 eris_ifu_free_vector(&peaks);
918 eris_ifu_free_vector(&ref_fit);
919 eris_ifu_free_vector(&sigma_fit);
920 eris_ifu_free_vector(&lambda_ref);
921 eris_ifu_free_vector(&lambda_tmp);
922 eris_ifu_free_vector(&sigma_tmp);
923 return final_peaks;
924
925}
926
927/*----------------------------------------------------------------------------*/
939/*----------------------------------------------------------------------------*/
940int gauss1d_fnc(const double x[], const double a[], double *result)
941{
942 double peak = a[0];
943 double mean = a[1];
944 double sigma = a[2];
945 double offset = a[3];
946
947 if (sigma == 0.0) {
948 return 1;
949 }
950 double z = (x[0]- mean)/sigma;
951 double ez = exp(-z*z/2.);
952 *result = offset + peak * ez;
953 return 0;
954}
955
956/*----------------------------------------------------------------------------*/
968/*----------------------------------------------------------------------------*/
969int gauss1d_fncd(const double x[], const double a[], double result[])
970{
971 double peak = a[0];
972 double mean = a[1];
973 double sigma = a[2];
974// double offset = a[3];
975
976 if (sigma == 0.0) {
977 return 1;
978 }
979 double z = (x[0]- mean)/sigma;
980 double ez = exp(-z*z/2.);
981
982 // derivative in peak
983 result[0] = ez;
984
985 // derivative in mean
986 result[1] = peak * ez * z/sigma;
987
988 // derivative in sigma
989 result[2] = result[1] * z;
990
991 // derivative in offset
992 result[3] = 1.;
993
994 return 0;
995}
996
997/*----------------------------------------------------------------------------*/
1011/*----------------------------------------------------------------------------*/
1012double fit_peak (const cpl_bivector *spectrum, const cpl_size size,
1013 double lambda_in, int half_width, double *sigma_par) {
1014
1015 double error = -1.0;
1016 double x0 = 0., sigma = 0., area = 0., offset = 0., mserr = 0.;
1017 cpl_size pos_found = 0, low_bound = 0, high_bound = 0;
1018 cpl_vector *vx = NULL,
1019 *vy = NULL;
1020 cpl_fit_mode fit_mode = CPL_FIT_ALL;
1021 cpl_error_code cpl_err;
1022
1023 const double sqrt2pi = sqrt(2. * 3.14159265358979323846);
1024
1025 sigma = *sigma_par;
1026 if (IDL !=NULL ) fprintf(IDL, "%20s: %f %d %lld %f\n", "fitpeak input", lambda_in, half_width, size, sigma);
1027
1028 if ((lambda_in < cpl_vector_get(cpl_bivector_get_x_const(spectrum), 0)) ||
1029 (lambda_in > cpl_vector_get(cpl_bivector_get_x_const(spectrum),size-1))) {
1030 return error;
1031 }
1032 pos_found = cpl_vector_find(cpl_bivector_get_x_const(spectrum), lambda_in);
1033 if (pos_found < 0) {
1034 return error;
1035 }
1036 low_bound = pos_found - half_width;
1037 high_bound = pos_found + half_width;
1038 if (low_bound < 0) {
1039 low_bound = 0;
1040 }
1041 if (high_bound >= size) {
1042 high_bound = size - 1;
1043 }
1044
1045 vx = cpl_vector_extract(cpl_bivector_get_x_const(spectrum), low_bound, high_bound, 1);
1046 vy = cpl_vector_extract(cpl_bivector_get_y_const(spectrum), low_bound, high_bound, 1);
1047// printf("low: %5d high: %5d lamda_in: %f\n", low_bound, high_bound, lambda_in);
1048 if (IDL !=NULL ) {
1049 fprintf(IDL, "%20s: %lld %lld %lld\n", "fitpeak selection", low_bound, high_bound, cpl_vector_get_size(vx));
1050 fprintf(IDL, "%20s: %lld", "fitpeak vx", cpl_vector_get_size(vx)); cpl_vector_dump(vx, IDL);
1051 fprintf(IDL, "%20s: %lld", "fitpeak vy", cpl_vector_get_size(vx)); cpl_vector_dump(vy, IDL);
1052 }
1053 if (high_bound-low_bound < 4) {
1054 if (vx != NULL) {cpl_vector_delete(vx);}
1055 if (vy != NULL) {cpl_vector_delete(vy);}
1056 return error;
1057 }
1058
1059 if (sigma == 0.0) {
1060 fit_mode = CPL_FIT_ALL;
1061 } else {
1062 fit_mode = CPL_FIT_CENTROID | CPL_FIT_AREA | CPL_FIT_OFFSET;
1063 }
1064
1065 cpl_err = cpl_vector_fit_gaussian(vx, NULL, vy, NULL,
1066 fit_mode, &x0, &sigma, &area, &offset, &mserr, NULL, NULL);
1067// printf("vector fit error: %d offset: %f x0: %f sigma: %f area: %f offset: %f mse: %f\n",
1068// cpl_err, lambda_in-x0, x0, sigma, area/sigma/sqrt2pi, offset, mse);
1069 if (cpl_err != CPL_ERROR_NONE) {
1070 cpl_error_reset();
1071 }
1072 if (IDL !=NULL ) fprintf(IDL, "%20s: %d %f %f %f %f\n", "fitpeak vectorfit", cpl_err, area/sigma/sqrt2pi, x0, sigma, offset);
1073
1074
1075 if (IDL !=NULL ) {
1076 cpl_matrix *mx = cpl_matrix_wrap(cpl_vector_get_size(vx), 1, cpl_vector_get_data(vx));
1077 cpl_vector *fit_par = cpl_vector_new(4);
1078 cpl_vector_set(fit_par,0,cpl_vector_get_max(vy));
1079 cpl_vector_set(fit_par,1,lambda_in);
1080 cpl_vector_set(fit_par,2,(cpl_vector_get(vx,cpl_vector_get_size(vx)-1)-cpl_vector_get(vx,0))/9.);
1081 cpl_vector_set(fit_par,3,cpl_vector_get_min(vy));
1082 cpl_error_code cpl_err_tmp = cpl_fit_lvmq(mx, NULL,
1083 vy, NULL,
1084 fit_par, NULL,
1086 CPL_FIT_LVMQ_TOLERANCE / 10000., // 0.01
1087 CPL_FIT_LVMQ_COUNT, // 5
1088 CPL_FIT_LVMQ_MAXITER * 1000, // 1000
1089 &mserr,
1090 NULL,
1091 NULL);
1092 if (cpl_err_tmp != CPL_ERROR_NONE) {
1093 cpl_error_reset();
1094 }
1095 // printf("lvmq fit error: %d offset: %f x0: %f sigma: %f peak: %f offset: %f mse: %f\n",
1096 // cpl_err,
1097 // lambda_in-cpl_vector_get(fit_par,1),
1098 // cpl_vector_get(fit_par,1),
1099 // cpl_vector_get(fit_par,2),
1100 // cpl_vector_get(fit_par,0),
1101 // cpl_vector_get(fit_par,3),
1102 // mse);
1103 fprintf(IDL, "%20s: %d %f %f %f %f\n", "fitpeak LVMQfit",
1104 cpl_err_tmp, cpl_vector_get(fit_par,0), cpl_vector_get(fit_par,1),
1105 cpl_vector_get(fit_par,2),cpl_vector_get(fit_par,3));
1106 if (mx != NULL) cpl_matrix_unwrap(mx);
1107 if (fit_par != NULL) cpl_vector_delete(fit_par);
1108 }
1109// printf("\n");
1110 cpl_vector_delete(vx);
1111 cpl_vector_delete(vy);
1112
1113 if (cpl_err != CPL_ERROR_NONE) {
1114 if (cpl_err != CPL_ERROR_CONTINUE) {
1115 cpl_msg_error("","%s\n",cpl_error_get_message_default(cpl_err));
1116 }
1117 return error;
1118 }
1119 *sigma_par = sigma;
1120 return x0;
1121
1122}
1123
1124/*----------------------------------------------------------------------------*/
1138/*----------------------------------------------------------------------------*/
1140 cpl_bivector *object,
1141 cpl_vector *peaks,
1142 ifsBand bandId,
1143 const int pfit_order) {
1144
1145 cpl_vector *lambda_fit = NULL,
1146 *ref_fit = NULL,
1147 *sigma_fit = NULL,
1148 *lambda_ref = NULL,
1149 *lambda_tmp = NULL,
1150 *sigma_tmp = NULL,
1151 *final_obj_in = NULL,
1152 *final_obj_fit = NULL,
1153 *final_obj_diff = NULL;
1154 cpl_polynomial *coeffs = NULL;
1155 cpl_matrix * samppos = NULL;
1156
1157 int halfwidth_obj = 0,
1158 i = 0;
1159 cpl_size obj_size = 0,
1160 no_peaks = 0,
1161 no_valid_peaks = 0,
1162 peak_idx = 0,
1163 v_idx = 0;
1164 int *invalid_index = NULL;
1165
1166 double lambda_in = 0.0,
1167 lambda_out = 0.0,
1168 sigma = 0.0,
1169 l_median = 0.0,
1170 l_stdev = 0.0,
1171 s_median = 0.0,
1172 s_stdev = 0.0,
1173 l_limit = 0.0,
1174 s_limit = 0.0,
1175 delta_lambda = 0.0,
1176 resolution;
1177
1178 const char *stype = NULL;
1179
1180 TRY {
1181 ASSURE(object != NULL &&
1182 peaks != NULL,
1183 CPL_ERROR_NULL_INPUT,
1184 "Not all input data is provided!");
1185
1186 resolution = eris_ifu_get_band_resolution(bandId);
1187
1188 obj_size = cpl_bivector_get_size(object);
1189 no_peaks = cpl_vector_get_size(peaks);
1190 if (IDL !=NULL ) {
1191 fprintf(IDL, "%20s: %lld %lld %f\n", "xcorr input", obj_size, no_peaks, resolution);
1192 fprintf(IDL, "%20s: %lld ", "xcorr object_l", obj_size); cpl_vector_dump(cpl_bivector_get_x_const(object), IDL);
1193 fprintf(IDL, "%20s: %lld ", "xcorr object_v", obj_size); cpl_vector_dump(cpl_bivector_get_y_const(object), IDL);
1194 fprintf(IDL, "%20s: %lld ", "xcorr peaks", no_peaks); cpl_vector_dump(peaks, IDL);
1195 }
1196
1197 ASSURE(obj_size > 1 && no_peaks > 1 ,
1198 CPL_ERROR_ILLEGAL_INPUT,
1199 "Input spectra must have more than one value");
1200
1202 invalid_index = cpl_calloc(no_peaks, sizeof(int)));
1203
1204 delta_lambda = 2. *
1205 cpl_vector_get(cpl_bivector_get_x_const(object), cpl_bivector_get_size(object) / 2) /
1206 resolution;
1207
1208
1209 halfwidth_obj = delta_lambda / (cpl_vector_get(cpl_bivector_get_x_const(object),1) -
1210 cpl_vector_get(cpl_bivector_get_x_const(object),0));
1211 //cpl_msg_info(cpl_func,"computed halfwidth_obj: %d",halfwidth_obj);
1212 halfwidth_obj = 8; // 8 pixels allows to recover also large line shifts (due to flexures) with poly order = 0
1213 //cpl_msg_info(cpl_func,"hard-coded halfwidth_obj: %d",halfwidth_obj);
1214 // second scan object spectrum
1215 // find exact peak location by fitting a gaussian
1216 // detect and withdraw outliers
1218 lambda_fit = cpl_vector_new(no_peaks));
1220 sigma_fit = cpl_vector_new(no_peaks));
1222 lambda_ref = cpl_vector_new(no_peaks));
1224 lambda_tmp = cpl_vector_new(no_peaks));
1226 sigma_tmp = cpl_vector_new(no_peaks));
1227
1228 peak_idx = 0;
1229 stype="object";
1230 if (IDL !=NULL ) fprintf(IDL, "%20s: %s\n", "xcorr spectrum type", stype);
1231 for (i = 0; i < no_peaks; i++) {
1232 lambda_in = cpl_vector_get(peaks,i);
1233 sigma = 0.0;
1234 lambda_out = fit_peak (object, obj_size, lambda_in, halfwidth_obj, &sigma);
1235 if (invalid_index[i] == 0) {
1236 if (lambda_out > 0.) {
1238 cpl_vector_set(lambda_fit, i, lambda_out));
1240 cpl_vector_set(sigma_fit, i, sigma));
1242 cpl_vector_set(lambda_ref, peak_idx, lambda_in));
1244 cpl_vector_set(lambda_tmp, peak_idx, lambda_out));
1246 cpl_vector_set(sigma_tmp, peak_idx, sigma));
1247 peak_idx++;
1248 } else {
1249 invalid_index[i] = 5;
1250 cpl_msg_debug(cpl_func,
1251 "Gaussian fit failed for %s spectrum, wavelenght %f, peak index %d",
1252 stype, lambda_in, i);
1253 }
1254 }
1255 }
1257 cpl_vector_set_size(lambda_ref,peak_idx));
1259 cpl_vector_set_size(lambda_tmp,peak_idx));
1261 cpl_vector_set_size(sigma_tmp,peak_idx));
1262 if (IDL !=NULL ) {
1263 fprintf(IDL, "%20s: %lld ", "xcorr lambda_ref", peak_idx); cpl_vector_dump(lambda_ref, IDL);
1264 fprintf(IDL, "%20s: %lld ", "xcorr lambda_tmp", peak_idx); cpl_vector_dump(lambda_tmp, IDL);
1265 fprintf(IDL, "%20s: %lld ", "xcorr sigma_tmp", peak_idx); cpl_vector_dump(sigma_tmp, IDL);
1266 }
1267
1269 cpl_vector_subtract(lambda_tmp,lambda_ref));
1270 l_median = cpl_vector_get_median_const(lambda_tmp);
1271 l_stdev = cpl_vector_get_stdev(lambda_tmp);
1272 s_median = cpl_vector_get_median_const(sigma_tmp);
1273 s_stdev = cpl_vector_get_stdev(sigma_tmp);
1274 l_limit = 2. * l_stdev;
1275 s_limit = 2. * s_stdev;
1276 cpl_vector_delete(lambda_ref);
1277 cpl_vector_delete(lambda_tmp);
1278 cpl_vector_delete(sigma_tmp);
1279 if (IDL !=NULL ) fprintf(IDL, "%20s: %f %f %f %f %f %f\n", "xcorr limits", l_median, l_stdev, l_limit, s_median, s_stdev, s_limit);
1280
1281 for (i = 0; i < no_peaks; i++){
1282 if (invalid_index[i] == 0) {
1283 double tmp_lambda = cpl_vector_get(lambda_fit,i) - cpl_vector_get(peaks,i);
1284 double tmp_sigma = cpl_vector_get(sigma_fit,i);
1285 if (fabs(tmp_lambda - l_median) > l_limit) {
1286 invalid_index[i] = 6;
1287 cpl_msg_debug(cpl_func,
1288 "Peak rejected due lambda outlier, %s spectrum, wavelength %f, index %d, limit %f, value %f",
1289 stype, cpl_vector_get(peaks,i), i, l_limit, fabs(tmp_lambda - l_median));
1290 } else if (fabs(tmp_sigma - s_median) > s_limit) {
1291 cpl_msg_debug(cpl_func,
1292 "Peak rejected due sigma outlier, %s spectrum, wavelength %f, index %d, limit %f, value %f",
1293 stype, cpl_vector_get(peaks,i), i, s_limit,fabs(tmp_sigma - s_median));
1294 invalid_index[i] = 7;
1295 }
1296 }
1297 }
1298 cpl_vector_delete(sigma_fit);
1299
1300 no_valid_peaks = 0;
1301 char *dbg_msg;
1303 dbg_msg = cpl_malloc((no_peaks * 2 + 1) * sizeof(char)));
1304 dbg_msg[no_peaks*2] = '\0';
1305 if (IDL !=NULL ) fprintf(IDL, "%20s: %lld", "xcorr invalid peaks", no_peaks);
1306 for (i = 0; i < no_peaks; i++){
1307 sprintf(&dbg_msg[2*i], "%2d", invalid_index[i]);
1308 if (invalid_index[i] == 0) {
1309 no_valid_peaks++;
1310 }
1311 if (IDL !=NULL ) fprintf(IDL, " %d", invalid_index[i]);
1312 }
1313 if (IDL !=NULL ) {
1314 fprintf(IDL, "\n");
1315 }
1316 cpl_msg_debug(__func__,"%d valid ones of %d peaks: %s", (int) no_valid_peaks, (int) no_peaks, dbg_msg);
1317 cpl_free(dbg_msg);
1318
1319 if (no_valid_peaks == 0) {
1320 cpl_msg_error(cpl_func, " |-----------------------------------------------------|");
1321 cpl_msg_error(cpl_func, " | No OH lines could be fitted. Aborting. |");
1322 cpl_msg_error(cpl_func, " | Run again with parameter --skip_oh_align |");
1323 cpl_msg_error(cpl_func, " | |");
1324 cpl_msg_error(cpl_func, " | WARNING: the spectral calibration of the outputs |");
1325 cpl_msg_error(cpl_func, " | is expected to be off for several pixels |");
1326 cpl_msg_error(cpl_func, " | due to flexure of the instrument |");
1327 cpl_msg_error(cpl_func, " |-----------------------------------------------------|");
1328
1329 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT);
1331 }
1332
1334 final_obj_in = cpl_vector_new(no_valid_peaks));
1336 final_obj_fit = cpl_vector_new(no_valid_peaks));
1338 final_obj_diff = cpl_vector_new(no_valid_peaks));
1339 v_idx = 0;
1340 for (i = 0; i < no_peaks; i++){
1341 if (invalid_index[i] == 0) {
1342 double in = cpl_vector_get(peaks,i);
1343 double fit = cpl_vector_get(lambda_fit,i);
1345 cpl_vector_set(final_obj_in, v_idx, in));
1347 cpl_vector_set(final_obj_fit, v_idx, fit));
1349 cpl_vector_set(final_obj_diff, v_idx, fit-in));
1350 v_idx++;
1351 }
1352 }
1353 if (IDL !=NULL ) {
1354 fprintf(IDL, "%20s: %lld ", "xcorr final_obj_in", no_valid_peaks); cpl_vector_dump(final_obj_in, IDL);
1355 fprintf(IDL, "%20s: %lld ", "xcorr final_obj_fit", no_valid_peaks); cpl_vector_dump(final_obj_fit, IDL);
1356 fprintf(IDL, "%20s: %lld ", "xcorr final_obj_diff", no_valid_peaks); cpl_vector_dump(final_obj_diff, IDL);
1357 }
1358 /* poly fit deg can be changed by user.
1359 0 is better in K band to prevent divergence on OH corr due to extrapolation
1360 higher walues (was 3 in the past) may allow higher accuracy in H and J band
1361 with many lines.
1362 */
1363
1364 cpl_size degree[1] = {0}; //essentially taking the mean of final_obj_diff
1365 degree[0] = pfit_order;
1366 cpl_msg_info(cpl_func,"Use poly deg: %lld to determine OH correction",degree[0]);
1368 coeffs = cpl_polynomial_new(1));
1369
1370 if (cpl_vector_get_size(final_obj_in) > (degree[0] + 3)) {
1372 samppos = cpl_matrix_wrap(1,cpl_vector_get_size(final_obj_in),
1373 cpl_vector_get_data(final_obj_in)));
1375 cpl_polynomial_fit(coeffs, samppos, NULL, final_obj_diff, NULL, CPL_FALSE,
1376 degree, degree));
1377 } else {
1378 cpl_msg_warning(NULL,"Too few valid peaks for lambda correction using OH lines");
1379 // create polynomial a0=0
1380 cpl_size pows[1];
1381 pows[0] = 0;
1383 cpl_polynomial_set_coeff (coeffs, pows, 0.));
1384 }
1385
1386 if (IDL !=NULL ) {
1387 cpl_size pows[1];
1388 fprintf(IDL, "%20s: %lld", "xcorr polyfit", cpl_polynomial_get_degree(coeffs));
1389 for (i = 0; i <= cpl_polynomial_get_degree(coeffs); i++) {
1390 pows[0] = i;
1391 fprintf(IDL, " %f", cpl_polynomial_get_coeff(coeffs,pows));
1392 }
1393 fprintf(IDL, "\n");
1394 }
1395 }
1396 CATCH
1397 {
1398 CATCH_MSG();
1399 if (coeffs != NULL) {
1400 cpl_polynomial_delete(coeffs);
1401 coeffs = NULL;
1402 }
1403 }
1404
1405 if (ref_fit != NULL) cpl_vector_delete(ref_fit);
1406 if (lambda_fit != NULL) cpl_vector_delete(lambda_fit);
1407 if (final_obj_in != NULL) cpl_vector_delete(final_obj_in);
1408 if (final_obj_fit != NULL) cpl_vector_delete(final_obj_fit);
1409 if (final_obj_diff != NULL) cpl_vector_delete(final_obj_diff);
1410 if (invalid_index != NULL) cpl_free(invalid_index);
1411 if (samppos != NULL) cpl_matrix_unwrap(samppos);
1412
1413 return coeffs;
1414}
1415/*----------------------------------------------------------------------------*/
1422/*----------------------------------------------------------------------------*/
1423void eris_ifu_lcorr_open_debug_file (const char* filename) {
1424 IDL = fopen(filename,"w");
1425}
1426
1427/*----------------------------------------------------------------------------*/
1432/*----------------------------------------------------------------------------*/
1434 fclose(IDL);
1435 IDL = NULL;
1436}
ifsBand eris_ifu_get_band(const cpl_propertylist *header)
Determine preoptic band.
#define BRK_WITH_ERROR(code)
Set a new CPL error, and exit the try-block.
#define ASSURE(condition, error,...)
error handling macro (from fors-pipeline)
#define BRK_IF_ERROR(function)
If function is or returns an error != CPL_ERROR_NONE, then the try-block is exited.
#define CHECK_ERROR_STATE(void)
Check the CPL error state, and exit the try-block if not CPL_ERROR_NONE.
#define BRK_WITH_ERROR_MSG(code,...)
Set a new CPL error, and exit the try-block.
#define CATCH_MSG()
Displays an error message.
#define TRY
Beginning of a TRY-block.
#define CATCH
End of a TRY-block, beginning of a CATCH-block.
#define BRK_IF_NULL(function)
If function is or returns a NULL pointer, then the try-block is exited.
cpl_error_code eris_ifu_extract_spec(const cpl_imagelist *data_in, const cpl_imagelist *noise_in, cpl_image *mask, cpl_vector **spec_data_out, cpl_vector **spec_noise_out)
Extract a spectrum from 3D data cube.
cpl_image * eris_ifu_lcorr_create_object_mask(const cpl_imagelist *cube, double min_frac, const cpl_vector *lambda, const cpl_vector *range)
Create spaxel selection mask for spectrum extraction.
cpl_bivector * eris_ifu_lcorr_extract_spectrum(const cpl_imagelist *cube, const cpl_propertylist *header, const double min_frac, const cpl_vector *range)
Extract integrated spectrum from IFU cube for brightest spaxels.
cpl_polynomial * eris_ifu_lcorr_get(cpl_imagelist *cube, hdrl_imagelist *hdrlCube, const cpl_propertylist *header, cpl_vector *peaks, const int pfit_order)
Create wavelength correction polynomial from IFU cube using OH lines.
void eris_ifu_lcorr_close_debug_file(void)
close ASCII file that hold debug results
cpl_vector * eris_ifu_lcorr_create_lambda_vector(const cpl_propertylist *header)
Create wavelength vector from FITS header WCS keywords.
void eris_ifu_lcorr_open_debug_file(const char *filename)
open ASCII file to hold debug results
cpl_array * eris_ifu_lcorr_get_peak_positions(const cpl_bivector *spectrum, double min_frac, cpl_vector *range)
Detect emission line peak positions in a spectrum.
int gauss1d_fncd(const double x[], const double a[], double result[])
define a Gaussian profile
cpl_vector * eris_ifu_lcorr_get_peak_lambdas(const cpl_bivector *spectrum, double min_frac, cpl_vector *range)
Detect and refine emission line peak wavelengths using Gaussian fitting.
double fit_peak(const cpl_bivector *spectrum, const cpl_size size, double lambda_in, int half_width, double *sigma_par)
fit a peak
int gauss1d_fnc(const double x[], const double a[], double *result)
define a Gaussian profile
cpl_polynomial * eris_ifu_lcorr_crosscorrelate_spectra(cpl_bivector *object, cpl_vector *peaks, ifsBand bandId, const int pfit_order)
cross-correlate two input spectra
cpl_bivector * eris_ifu_lcorr_read_OH_reference_spectrum(const char *filename, cpl_size ext_number)
Read OH reference spectrum from FITS file.
void eris_ifu_free_vector(cpl_vector **item)
Free memory and set pointer to null.
void eris_ifu_free_int_array(int **item)
Free memory and set pointer to null.
cpl_error_code eris_ifu_mask_nans_in_cube(cpl_imagelist *cube)
Mask NaNs and Infs in CPL imagelist (cube)
double eris_ifu_get_band_resolution(ifsBand band)
Get nominal spectral resolution for a given band.
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:105
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.