ERIS Pipeline Reference Manual 1.8.14
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/*----------------------------------------------------------------------------*/
43/*----------------------------------------------------------------------------*/
44
45/*----------------------------------------------------------------------------*/
60/*----------------------------------------------------------------------------*/
61cpl_polynomial *eris_ifu_lcorr_get(cpl_imagelist *cube, hdrl_imagelist *hdrlCube,
62 const cpl_propertylist *header,
63 cpl_vector *peaks,
64 const int pfit_order)
65{
66 cpl_polynomial *lcorr_coeffs = NULL;
67 cpl_imagelist *tmpCube = NULL;
68 cpl_image *tmpImg = NULL;
69 cpl_bivector *obj_spectrum = NULL,
70 *ref_spectrum = NULL;
71 int ic = 0;
72 const int format_width = 14,
73 max_coeffs = 6;
74 char *coeff_string = NULL,
75 coeff_dump[format_width * max_coeffs + 1];
76 cpl_size pows[1];
77 ifsBand bandId = UNDEFINED_BAND;
78 //const char *ref_filename = NULL;
79 //TODO: why we need filter_id, and later that is set, but never used?
80// const char *filter_id;
81
82 TRY
83 {
84 ASSURE(cube != NULL || hdrlCube != NULL,
85 CPL_ERROR_ILLEGAL_INPUT, "One of cube or hdrlCube must be not NULL");
86 ASSURE(!(cube != NULL && hdrlCube != NULL),
87 CPL_ERROR_ILLEGAL_INPUT, "One of cube or hdrlCube must be NULL");
88 ASSURE((peaks != NULL),
89 CPL_ERROR_NULL_INPUT, "Not all input data is provided!");
90
91 bandId = eris_ifu_get_band(header);
92// switch (bandId) {
93// case J_LOW:
94// case J_SHORT: case J_MIDDLE: case J_LONG:
95// case J_SPIFFI:
96// filter_id = "J";
97// break;
98// case H_LOW:
99// case H_SHORT: case H_MIDDLE: case H_LONG:
100// case H_SPIFFI:
101// filter_id = "H";
102// break;
103// case K_LOW:
104// case K_SHORT: case K_MIDDLE: case K_LONG:
105// case K_SPIFFI:
106// filter_id = "K";
107// break;
108// case HK_SPIFFI:
109// filter_id = "HK";
110// break;
111// default:
112// filter_id = "X";
113// break;
114// }
115
116 if (cube != NULL) {
117 tmpCube = cube;
118 } else {
119 tmpCube = cpl_imagelist_new();
120 for (cpl_size sx = 0; sx < hdrl_imagelist_get_size(hdrlCube); sx++) {
121 tmpImg = hdrl_image_get_image(hdrl_imagelist_get(hdrlCube, sx));
122 cpl_imagelist_set(tmpCube, cpl_image_duplicate(tmpImg), sx);
123 }
125 }
126
129
130
132 obj_spectrum = eris_ifu_lcorr_extract_spectrum(tmpCube, header, 0.8, NULL));
133 //clean memory from temporary object. TODO: generate seg fault. Why??
134 /*
135 if (cube == NULL) {
136 for (cpl_size sx = 0; sx < cpl_imagelist_get_size(tmpCube); sx++) {
137 cpl_imagelist_unset(tmpCube,sx);
138 }
139 }
140 */
141 cpl_imagelist_delete(tmpCube);
143 lcorr_coeffs = eris_ifu_lcorr_crosscorrelate_spectra(obj_spectrum,
144 peaks, bandId, pfit_order));
145
146 // debug stuff
147 coeff_dump[0] = 0;
148 for (ic = 0; ic <= cpl_polynomial_get_degree(lcorr_coeffs) && ic < max_coeffs; ic++) {
149 pows[0] = ic;
150 coeff_string = cpl_sprintf(" %*g,", format_width-2, cpl_polynomial_get_coeff(lcorr_coeffs,pows));
151 strncat(coeff_dump, coeff_string, format_width);
152 cpl_free(coeff_string); coeff_string = NULL;
153 }
154 cpl_msg_debug(cpl_func,"Lambda correction coeffs %s", coeff_dump);
155 }
156 CATCH
157 {
158 cpl_polynomial_delete(lcorr_coeffs); lcorr_coeffs = NULL;
159 }
160
161 cpl_bivector_delete(ref_spectrum); ref_spectrum = NULL;
162 cpl_bivector_delete(obj_spectrum); obj_spectrum = NULL;
163 cpl_free(coeff_string); coeff_string = NULL;
164
165 return lcorr_coeffs;
166}
167
168/*----------------------------------------------------------------------------*/
183/*----------------------------------------------------------------------------*/
184cpl_bivector *eris_ifu_lcorr_extract_spectrum (const cpl_imagelist *cube,
185 const cpl_propertylist *header,
186 const double min_frac,
187 const cpl_vector *range) {
188
189 cpl_bivector *result = NULL;
190 cpl_vector *spectrum = NULL,
191 *lambda = NULL;
192 cpl_image *obj_mask = NULL;
193 TRY
194 {
195 ASSURE(cube != NULL && header != NULL,
196 CPL_ERROR_NULL_INPUT,
197 "Not all input data is provided!");
198
200 lambda = eris_ifu_lcorr_create_lambda_vector(header));
201
202 if (range != NULL) {
204 obj_mask = eris_ifu_lcorr_create_object_mask(cube, min_frac, lambda, range));
205 } else {
207 obj_mask = eris_ifu_lcorr_create_object_mask(cube, min_frac, NULL, NULL));
208 }
209
211 eris_ifu_extract_spec(cube, NULL, obj_mask, &spectrum, NULL));
212
214 result = cpl_bivector_wrap_vectors(lambda, spectrum));
215 }
216 CATCH
217 {
218 CATCH_MSG();
219 }
220
221 if (obj_mask != NULL) {cpl_image_delete(obj_mask);}
222 if (result == NULL) {
223 if (lambda != NULL) {cpl_vector_delete(lambda);}
224 if (spectrum != NULL) {cpl_vector_delete(spectrum);}
225 }
226 return result;
227}
228
229/*----------------------------------------------------------------------------*/
257/*----------------------------------------------------------------------------*/
258cpl_image *eris_ifu_lcorr_create_object_mask (const cpl_imagelist *cube,
259 double min_frac,
260 const cpl_vector *lambda,
261 const cpl_vector *range) {
262
263 cpl_image *mask = NULL;
264 cpl_imagelist *rcube = NULL;
265 const cpl_image *slice = NULL;
266 cpl_imagelist *icube = NULL;
267 cpl_image *tmp_img = NULL,
268 *m_img = NULL;
269 cpl_vector *sum = NULL,
270 *m_vector = NULL,
271 *sorted_sum = NULL;
272 cpl_mask *empty_mask = NULL;
273
274 int x, y, z, r;
275 int nx, ny, nz, nr, px, cnz= 0;
276 int check4range = FALSE;
277 const double *lambda_data = NULL;
278 double l_low, l_up = 0.0;
279 double max_value = 0.0;
280 int *cnts = NULL;
281 double *m_data = NULL;
282 float *mask_data = NULL;
283
284 TRY
285 {
286 ASSURE(cube != NULL,
287 CPL_ERROR_NULL_INPUT,
288 "Not all input data is provided!");
289
290 ASSURE(((lambda != NULL) && (range != NULL)) ||
291 ((lambda == NULL) && (range == NULL)) ,
292 CPL_ERROR_NULL_INPUT,
293 "Not all input data is provided!");
294 if (range != NULL) {
295 check4range = TRUE;
296 ASSURE(cpl_vector_get_size(range)%2 == 0,
297 CPL_ERROR_ILLEGAL_INPUT,
298 "Range vector size must be a multiple of 2");
299
300 nr = cpl_vector_get_size(range) / 2;
301 }
302
303 if (lambda != NULL) {
304 ASSURE(cpl_vector_get_size(lambda) == cpl_imagelist_get_size(cube),
305 CPL_ERROR_ILLEGAL_INPUT,
306 "Size of lambda vector must be the number of images in the input cube");
308 lambda_data = cpl_vector_get_data_const(lambda));
309 }
310
312 slice = cpl_imagelist_get_const(cube, 0));
313 nx = cpl_image_get_size_x(slice);
314 ny = cpl_image_get_size_y(slice);
315 nz = cpl_imagelist_get_size(cube);
316
317 // if wavelength range are specified create a new imagelist holding only those lambdas
318 // otherwise take original input cube
319 if (check4range) {
320 cnz = 0;
322 rcube = cpl_imagelist_new());
323 for (z=0; z<nz; z++) {
324 int checkOK = FALSE;
325 for (r=0; r<nr; r++) {
326 l_low = cpl_vector_get(range, r*2);
327 l_up = cpl_vector_get(range, r*2+1);
328 if ((lambda_data[z] >= l_low) && (lambda_data[z] <= l_up)) {
329 checkOK = TRUE;
330 break;
331 }
332 }
333 if (checkOK) {
335 slice = cpl_imagelist_get_const(cube, z));
337 cpl_imagelist_set(rcube, cpl_image_duplicate(slice), cnz));
338 cnz++;
339 }
340 }
341 icube = rcube;
342 } else {
343 icube = (cpl_imagelist*) cube;
344 }
348 tmp_img = cpl_imagelist_collapse_median_create(icube));
350 m_img = cpl_image_cast(tmp_img, CPL_TYPE_DOUBLE));
352 m_data = cpl_image_get_data_double(m_img));
354 m_vector = cpl_vector_wrap(nx * ny, m_data));
356 sorted_sum = cpl_vector_duplicate(m_vector));
357 cpl_vector_sort(sorted_sum, CPL_SORT_ASCENDING);
358 max_value = cpl_vector_get(sorted_sum, nx*ny*min_frac);
359
360 mask = cpl_image_new(nx,ny,CPL_TYPE_FLOAT);
362 mask_data = cpl_image_get_data_float(mask));
363 for (x=0; x<nx; x++) {
364 for (y=0; y<ny; y++) {
365 px = x+y*nx;
366 if (m_data[px] <= max_value) {
367 mask_data[px] = 1.0;
368 } else {
369 mask_data[px] = 0.0;
370 }
371 }
372 }
373
374 }
375 CATCH
376 {
377 CATCH_MSG();
378 if (mask != NULL) {cpl_image_delete(mask);}
379 mask = NULL;
380 }
381 if (rcube != NULL) {cpl_imagelist_delete(rcube);}
382 if (tmp_img != NULL) {cpl_image_delete(tmp_img);}
383 if (m_img != NULL) {cpl_image_delete(m_img);}
384 if (m_vector != NULL) {cpl_vector_unwrap(m_vector);}
385 if (sum != NULL) {cpl_vector_delete(sum);}
386 if (cnts != NULL) {cpl_free(cnts);}
387 if (sorted_sum != NULL) {cpl_vector_delete(sorted_sum);}
388 if (empty_mask != NULL) {cpl_mask_delete(empty_mask);}
389
390 return mask;
391}
392
393/*----------------------------------------------------------------------------*/
406/*----------------------------------------------------------------------------*/
407
408cpl_vector *eris_ifu_lcorr_create_lambda_vector(const cpl_propertylist *header) {
409
410 cpl_vector *lambda_vector = NULL;
411 int naxis3, z = 0;
412 double crval3, cdelt3, crpix3 = 0.0;
413 double *lambda = NULL;
414
415 TRY {
416 ASSURE(header != NULL,
417 CPL_ERROR_NULL_INPUT,
418 "Not all input data is provided!");
419 ASSURE(cpl_propertylist_has(header,NAXIS3) &&
420 cpl_propertylist_has(header,CRVAL3) &&
421 cpl_propertylist_has(header,CDELT3) &&
422 cpl_propertylist_has(header,CRPIX3),
423 CPL_ERROR_ILLEGAL_INPUT,
424 "missing WCS keywords in header");
425
426 naxis3 = cpl_propertylist_get_int(header, NAXIS3);
427 crval3 = cpl_propertylist_get_double(header, CRVAL3);
428 cdelt3 = cpl_propertylist_get_double(header, CDELT3);
429 crpix3 = cpl_propertylist_get_double(header, CRPIX3);
430
432 lambda_vector = cpl_vector_new(naxis3));
434 lambda = cpl_vector_get_data(lambda_vector));
435
436 for (z=0; z<naxis3; z++) {
437 lambda[z] = (z+1 - crpix3) * cdelt3 + crval3;
438 }
439 }
440 CATCH
441 {
442 CATCH_MSG();
443 if (lambda_vector != NULL) {
444 cpl_vector_delete(lambda_vector);
445 lambda_vector = NULL;
446 }
447 }
448
449 return lambda_vector;
450}
451
452/*----------------------------------------------------------------------------*/
467/*----------------------------------------------------------------------------*/
468cpl_bivector *eris_ifu_lcorr_read_OH_reference_spectrum(const char *filename,
469 cpl_size ext_number) {
470
471 cpl_bivector *result = NULL;
472 cpl_vector *lambda = NULL,
473 *spec = NULL;
474 cpl_propertylist *header = NULL;
475 double *lambda_data = NULL;
476 double crpix, crval, cdelt = 0.0;
477 int naxis1 = 0;
478
479 TRY {
480 ASSURE(filename != NULL,
481 CPL_ERROR_NULL_INPUT,
482 "Not all input data is provided!");
483
484 cpl_msg_info(__func__,
485 "Using file %s as OH reference spectrum for lambda correction",
486 filename);
487
488 spec = cpl_vector_load(filename, ext_number);
489 if (cpl_error_get_code() != CPL_ERROR_NONE) {
490 if (cpl_error_get_code() == CPL_ERROR_FILE_IO) {
491 cpl_msg_error("", "File not found: %s", filename);
492 } else {
493 cpl_msg_error("", "Problem loading file '%s' (%s --> Code %d)",
494 filename, cpl_error_get_message(),
495 cpl_error_get_code());
496 }
497 }
498
500 header = cpl_propertylist_load(filename, ext_number));
501
502 naxis1 = cpl_propertylist_get_int(header, NAXIS1);
504 crval = cpl_propertylist_get_double(header, CRVAL1);
506 cdelt = cpl_propertylist_get_double(header, CDELT1);
508 switch (cpl_propertylist_get_type(header, CRPIX1)) {
509 case CPL_TYPE_INT:
510 crpix = cpl_propertylist_get_int(header, CRPIX1);
511 break;
512 case CPL_TYPE_DOUBLE:
513 crpix = cpl_propertylist_get_double(header, CRPIX1);
514 break;
515 case CPL_TYPE_FLOAT:
516 crpix = cpl_propertylist_get_float(header, CRPIX1);
517 break;
518 default:
519 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
520 "CRPIX1 is of wrong type!");
521 }
523
525 lambda = cpl_vector_new(naxis1));
527 lambda_data = cpl_vector_get_data(lambda));
528 int i = 0;
529 for (i = 0; i < naxis1; i++) {
530 lambda_data[i] = crval + (i + 1-crpix)*cdelt;
531 }
532
534 result = cpl_bivector_wrap_vectors(lambda, spec));
535 }
536 CATCH
537 {
538 CATCH_MSG();
539 }
540
541 if (header != NULL) {cpl_propertylist_delete(header);}
542
543 return result;
544
545}
546
547/*----------------------------------------------------------------------------*/
560/*----------------------------------------------------------------------------*/
561
562cpl_array *eris_ifu_lcorr_get_peak_positions(const cpl_bivector *spectrum,
563 double min_frac,
564 cpl_vector *range) {
565
566 cpl_array *positions = NULL;
567
568 cpl_vector *copied_spectrum = NULL;
569
570 int spec_size = 0,
571 peak_cnt = 0,
572 nr = 0,
573 i = 0,
574 r = 0;
575 double min = 0.0,
576 l_low = 0.0,
577 l_up = 0.0;
578 double *spec_data = NULL,
579 *diff_data = NULL;
580 const double *lambda_data = NULL;
581
582 TRY {
583 ASSURE(spectrum != NULL && cpl_bivector_get_y_const(spectrum) != NULL,
584 CPL_ERROR_NULL_INPUT,
585 "Not all input data is provided!");
586
587 if (range != NULL) {
588 ASSURE(cpl_bivector_get_x_const(spectrum) != NULL,
589 CPL_ERROR_NULL_INPUT,
590 "Not all input data is provided!");
591 ASSURE(cpl_vector_get_size(range)%2 == 0,
592 CPL_ERROR_ILLEGAL_INPUT,
593 "Range vector size must be a multiple of 2");
595 lambda_data = cpl_vector_get_data_const(cpl_bivector_get_x_const(spectrum)));
596 nr = cpl_vector_get_size(range) / 2;
597 }
598
600 copied_spectrum = cpl_vector_duplicate(cpl_bivector_get_y_const(spectrum)));
601
603 spec_data = cpl_vector_get_data(copied_spectrum));
604
605 spec_size = cpl_vector_get_size(copied_spectrum);
606
607 if (range != NULL) {
608 for (i = 0; i < (spec_size-1); i++) {
609 int checkOK = FALSE;
610 for (r = 0; r < nr; r++) {
611 l_low = cpl_vector_get(range, r*2);
612 l_up = cpl_vector_get(range, r*2+1);
613 if ((lambda_data[i] >= l_low) && (lambda_data[i] <= l_up)) {
614 checkOK = TRUE;
615 break;
616 }
617 }
618 if (! checkOK) {
619 spec_data[i] = 0.;
620 }
621 }
622 }
623
625 diff_data = cpl_malloc((spec_size-1) * sizeof(double)));
626
628 positions = cpl_array_new(spec_size, CPL_TYPE_INT));
629
630 min = cpl_vector_get_max(copied_spectrum) * min_frac;
631
632 if (spec_data[0] < min) {
633 spec_data[0] = 0.;
634 }
635 for (i = 0; i < (spec_size-1); i++) {
636 if (spec_data[i+1] < min) {
637 spec_data[i+1] = 0.;
638 }
639 diff_data[i] = spec_data[i+1] - spec_data[i];
640 }
641
642 peak_cnt = 0;
643 for (i = 0; i < (spec_size-2); i++) {
644 if ((diff_data[i] > 0) && (diff_data[i+1] < 0)) {
646 cpl_array_set_int(positions, peak_cnt, i+1));
647 peak_cnt++;
648 }
649 }
651 cpl_array_set_size(positions, peak_cnt));
652 }
653 CATCH
654 {
655 CATCH_MSG();
656 if (positions != NULL) {cpl_array_delete(positions);}
657 positions = NULL;
658 }
659
660 if (diff_data != NULL) {cpl_free(diff_data);}
661 if (copied_spectrum != NULL) {cpl_vector_delete(copied_spectrum);}
662
663 return positions;
664}
665
666/*----------------------------------------------------------------------------*/
679/*----------------------------------------------------------------------------*/
680cpl_vector *eris_ifu_lcorr_get_peak_lambdas (const cpl_bivector *spectrum,
681 double min_frac,
682 cpl_vector *range) {
683
684 cpl_vector *peaks = NULL,
685 *final_peaks = NULL;
686 cpl_array *positions = NULL;
687 cpl_size no_peaks = 0,
688 spec_size = 0;
689 const int *pos_data = NULL;
690 const double *spec_data = NULL;
691 double *lambda_data = NULL;
692
693 cpl_vector *ref_fit = NULL,
694 *sigma_fit = NULL,
695 *lambda_ref = NULL,
696 *lambda_tmp = NULL,
697 *sigma_tmp = NULL;
698 int *invalid_index = NULL;
699 cpl_size peak_idx = 0;
700 double delta_lambda = 0.0,
701 lambda_in = 0.0,
702 lambda_out = 0.0,
703 sigma = 0.0,
704 l_median = 0.0,
705 l_stdev = 0.0,
706 s_median = 0.0,
707 s_stdev = 0.0,
708 l_limit = 0.0,
709 s_limit = 0.0;
710 int validPeaksCnt = 0;
711 const char *stype;
712 const int halfwidth = 5;
713
714 TRY {
715 ASSURE(spectrum != NULL &&
716 cpl_bivector_get_x_const(spectrum) != NULL &&
717 cpl_bivector_get_y_const(spectrum) != NULL,
718 CPL_ERROR_NULL_INPUT,
719 "Not all input data is provided!");
720
722 positions = eris_ifu_lcorr_get_peak_positions(spectrum, min_frac, range));
723 no_peaks = cpl_array_get_size(positions);
724
726 peaks = cpl_vector_new(no_peaks));
727
729 pos_data = cpl_array_get_data_int_const(positions));
731 spec_data = cpl_vector_get_data_const(cpl_bivector_get_x_const(spectrum)));
733 lambda_data = cpl_vector_get_data(peaks));
734
735 spec_size = cpl_bivector_get_size(spectrum);
736
737 cpl_size i = 0;
738 for (i = 0; i < no_peaks; i++) {
739 if (pos_data[i] >= spec_size) {
740 BRK_WITH_ERROR(CPL_ERROR_ACCESS_OUT_OF_RANGE);
741 }
742 lambda_data[i] = spec_data[pos_data[i]];
743 }
744
745
747 invalid_index = cpl_calloc(no_peaks, sizeof(int)));
748 // scan for peaks which are too close
749
750 delta_lambda = 1.93 / 11200.;
751
752 for (i = 0; i < no_peaks-1; i++) {
753 if ((cpl_vector_get(peaks,i+1) - cpl_vector_get(peaks,i)) < 2. * delta_lambda) {
754 invalid_index[i] = 1;
755 invalid_index[i+1] = 1;
756 cpl_msg_debug(cpl_func,
757 "Pair of peaks are rejected because they are too close: %lld - %lld, %f - %f",
758 i, i+1, cpl_vector_get(peaks,i), cpl_vector_get(peaks,i+1));
759 }
760 }
761
762 // find exact peak location by fitting a gaussian
763 // detect and withdraw outliers
765 ref_fit = cpl_vector_new(no_peaks));
767 sigma_fit = cpl_vector_new(no_peaks));
769 lambda_ref = cpl_vector_new(no_peaks));
771 lambda_tmp = cpl_vector_new(no_peaks));
773 sigma_tmp = cpl_vector_new(no_peaks));
774
775 peak_idx = 0;
776 stype="reference";
777 if (IDL !=NULL ) fprintf(IDL, "%20s: %s\n", "xcorr spectrum type", stype);
778 for (i = 0 ; i < no_peaks; i++) {
779 lambda_in = cpl_vector_get(peaks,i);
780 sigma = 0.0;
781 lambda_out = fit_peak (spectrum, spec_size, lambda_in, halfwidth, &sigma);
782 if (invalid_index[i] == 0) {
783 if (lambda_out > 0.) {
785 cpl_vector_set(ref_fit, i, lambda_out));
787 cpl_vector_set(sigma_fit, i, sigma));
789 cpl_vector_set(lambda_ref, peak_idx, lambda_in));
791 cpl_vector_set(lambda_tmp, peak_idx, lambda_out));
793 cpl_vector_set(sigma_tmp, peak_idx, sigma));
794 peak_idx++;
795 } else {
796 invalid_index[i] = 2;
797 cpl_msg_debug(cpl_func,
798 "Gaussian fit failed for %s spectrum, wavelenght %f, peak index %lld",
799 stype, lambda_in, i);
800 }
801 }
802 }
804 cpl_vector_set_size(lambda_ref,peak_idx));
806 cpl_vector_set_size(lambda_tmp,peak_idx));
808 cpl_vector_set_size(sigma_tmp,peak_idx));
809 if (IDL !=NULL ) {
810 fprintf(IDL, "%20s: %lld ", "xcorr lambda_ref", peak_idx); cpl_vector_dump(lambda_ref, IDL);
811 fprintf(IDL, "%20s: %lld ", "xcorr lambda_tmp", peak_idx); cpl_vector_dump(lambda_tmp, IDL);
812 fprintf(IDL, "%20s: %lld ", "xcorr sigma_tmp", peak_idx); cpl_vector_dump(sigma_tmp, IDL);
813 }
814
816 cpl_vector_subtract(lambda_tmp,lambda_ref));
817 l_median = cpl_vector_get_median_const(lambda_tmp);
818 l_stdev = cpl_vector_get_stdev(lambda_tmp);
819 s_median = cpl_vector_get_median_const(sigma_tmp);
820 s_stdev = cpl_vector_get_stdev(sigma_tmp);
821 l_limit = 3. * l_stdev;
822 s_limit = 3. * s_stdev;
823 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);
824
825 for (i = 0; i < no_peaks; i++){
826 if (invalid_index[i] == 0) {
827 double tmp_lambda = cpl_vector_get(ref_fit,i) - cpl_vector_get(peaks,i);
828 double tmp_sigma = cpl_vector_get(sigma_fit,i);
829 if (fabs(tmp_lambda - l_median) > l_limit) {
830 invalid_index[i] = 3;
831 cpl_msg_debug(cpl_func,
832 "Peak rejected due lambda outlier, %s spectrum, wavelength %f, index %lld, limit %f, value %f",
833 stype, cpl_vector_get(peaks,i), i, l_limit, fabs(tmp_lambda - l_median));
834 } else if (fabs(tmp_sigma - s_median) > s_limit) {
835 cpl_msg_debug(cpl_func,
836 "Peak rejected due sigma outlier, %s spectrum, wavelength %f, index %lld, limit %f, value %f",
837 stype, cpl_vector_get(peaks,i), i, s_limit,fabs(tmp_sigma - s_median));
838 invalid_index[i] = 4;
839 }
840 }
841 }
842
843 validPeaksCnt = 0;
844 for (i = 0; i < no_peaks; i++) {
845 if (invalid_index[i] == 0) {
846 validPeaksCnt++;
847 }
848 }
849 final_peaks = cpl_vector_new(validPeaksCnt);
850 validPeaksCnt = 0;
851 for (i = 0; i < no_peaks; i++) {
852 if (invalid_index[i] == 0) {
853 cpl_vector_set(final_peaks, validPeaksCnt,
854 cpl_vector_get(ref_fit,i));
855 validPeaksCnt++;
856 }
857 }
859 }
860 CATCH
861 {
862 eris_ifu_free_vector(&final_peaks);
863 final_peaks = NULL;
864 }
865
866 if (positions != NULL) {cpl_array_delete(positions);}
867 eris_ifu_free_int_array(&invalid_index);
868 eris_ifu_free_vector(&peaks);
869 eris_ifu_free_vector(&ref_fit);
870 eris_ifu_free_vector(&sigma_fit);
871 eris_ifu_free_vector(&lambda_ref);
872 eris_ifu_free_vector(&lambda_tmp);
873 eris_ifu_free_vector(&sigma_tmp);
874 return final_peaks;
875
876}
877
878/*----------------------------------------------------------------------------*/
890/*----------------------------------------------------------------------------*/
891int gauss1d_fnc(const double x[], const double a[], double *result)
892{
893 double peak = a[0];
894 double mean = a[1];
895 double sigma = a[2];
896 double offset = a[3];
897
898 if (sigma == 0.0) {
899 return 1;
900 }
901 double z = (x[0]- mean)/sigma;
902 double ez = exp(-z*z/2.);
903 *result = offset + peak * ez;
904 return 0;
905}
906
907/*----------------------------------------------------------------------------*/
919/*----------------------------------------------------------------------------*/
920int gauss1d_fncd(const double x[], const double a[], double result[])
921{
922 double peak = a[0];
923 double mean = a[1];
924 double sigma = a[2];
925// double offset = a[3];
926
927 if (sigma == 0.0) {
928 return 1;
929 }
930 double z = (x[0]- mean)/sigma;
931 double ez = exp(-z*z/2.);
932
933 // derivative in peak
934 result[0] = ez;
935
936 // derivative in mean
937 result[1] = peak * ez * z/sigma;
938
939 // derivative in sigma
940 result[2] = result[1] * z;
941
942 // derivative in offset
943 result[3] = 1.;
944
945 return 0;
946}
947
948/*----------------------------------------------------------------------------*/
962/*----------------------------------------------------------------------------*/
963double fit_peak (const cpl_bivector *spectrum, const cpl_size size,
964 double lambda_in, int half_width, double *sigma_par) {
965
966 double error = -1.0;
967 double x0 = 0., sigma = 0., area = 0., offset = 0., mserr = 0.;
968 cpl_size pos_found = 0, low_bound = 0, high_bound = 0;
969 cpl_vector *vx = NULL,
970 *vy = NULL;
971 cpl_fit_mode fit_mode = CPL_FIT_ALL;
972 cpl_error_code cpl_err;
973
974 const double sqrt2pi = sqrt(2. * 3.14159265358979323846);
975
976 sigma = *sigma_par;
977 if (IDL !=NULL ) fprintf(IDL, "%20s: %f %d %lld %f\n", "fitpeak input", lambda_in, half_width, size, sigma);
978
979 if ((lambda_in < cpl_vector_get(cpl_bivector_get_x_const(spectrum), 0)) ||
980 (lambda_in > cpl_vector_get(cpl_bivector_get_x_const(spectrum),size-1))) {
981 return error;
982 }
983 pos_found = cpl_vector_find(cpl_bivector_get_x_const(spectrum), lambda_in);
984 if (pos_found < 0) {
985 return error;
986 }
987 low_bound = pos_found - half_width;
988 high_bound = pos_found + half_width;
989 if (low_bound < 0) {
990 low_bound = 0;
991 }
992 if (high_bound >= size) {
993 high_bound = size - 1;
994 }
995
996 vx = cpl_vector_extract(cpl_bivector_get_x_const(spectrum), low_bound, high_bound, 1);
997 vy = cpl_vector_extract(cpl_bivector_get_y_const(spectrum), low_bound, high_bound, 1);
998// printf("low: %5d high: %5d lamda_in: %f\n", low_bound, high_bound, lambda_in);
999 if (IDL !=NULL ) {
1000 fprintf(IDL, "%20s: %lld %lld %lld\n", "fitpeak selection", low_bound, high_bound, cpl_vector_get_size(vx));
1001 fprintf(IDL, "%20s: %lld", "fitpeak vx", cpl_vector_get_size(vx)); cpl_vector_dump(vx, IDL);
1002 fprintf(IDL, "%20s: %lld", "fitpeak vy", cpl_vector_get_size(vx)); cpl_vector_dump(vy, IDL);
1003 }
1004 if (high_bound-low_bound < 4) {
1005 if (vx != NULL) {cpl_vector_delete(vx);}
1006 if (vy != NULL) {cpl_vector_delete(vy);}
1007 return error;
1008 }
1009
1010 if (sigma == 0.0) {
1011 fit_mode = CPL_FIT_ALL;
1012 } else {
1013 fit_mode = CPL_FIT_CENTROID | CPL_FIT_AREA | CPL_FIT_OFFSET;
1014 }
1015
1016 cpl_err = cpl_vector_fit_gaussian(vx, NULL, vy, NULL,
1017 fit_mode, &x0, &sigma, &area, &offset, &mserr, NULL, NULL);
1018// printf("vector fit error: %d offset: %f x0: %f sigma: %f area: %f offset: %f mse: %f\n",
1019// cpl_err, lambda_in-x0, x0, sigma, area/sigma/sqrt2pi, offset, mse);
1020 if (cpl_err != CPL_ERROR_NONE) {
1021 cpl_error_reset();
1022 }
1023 if (IDL !=NULL ) fprintf(IDL, "%20s: %d %f %f %f %f\n", "fitpeak vectorfit", cpl_err, area/sigma/sqrt2pi, x0, sigma, offset);
1024
1025
1026 if (IDL !=NULL ) {
1027 cpl_matrix *mx = cpl_matrix_wrap(cpl_vector_get_size(vx), 1, cpl_vector_get_data(vx));
1028 cpl_vector *fit_par = cpl_vector_new(4);
1029 cpl_vector_set(fit_par,0,cpl_vector_get_max(vy));
1030 cpl_vector_set(fit_par,1,lambda_in);
1031 cpl_vector_set(fit_par,2,(cpl_vector_get(vx,cpl_vector_get_size(vx)-1)-cpl_vector_get(vx,0))/9.);
1032 cpl_vector_set(fit_par,3,cpl_vector_get_min(vy));
1033 cpl_error_code cpl_err_tmp = cpl_fit_lvmq(mx, NULL,
1034 vy, NULL,
1035 fit_par, NULL,
1037 CPL_FIT_LVMQ_TOLERANCE / 10000., // 0.01
1038 CPL_FIT_LVMQ_COUNT, // 5
1039 CPL_FIT_LVMQ_MAXITER * 1000, // 1000
1040 &mserr,
1041 NULL,
1042 NULL);
1043 if (cpl_err_tmp != CPL_ERROR_NONE) {
1044 cpl_error_reset();
1045 }
1046 // printf("lvmq fit error: %d offset: %f x0: %f sigma: %f peak: %f offset: %f mse: %f\n",
1047 // cpl_err,
1048 // lambda_in-cpl_vector_get(fit_par,1),
1049 // cpl_vector_get(fit_par,1),
1050 // cpl_vector_get(fit_par,2),
1051 // cpl_vector_get(fit_par,0),
1052 // cpl_vector_get(fit_par,3),
1053 // mse);
1054 fprintf(IDL, "%20s: %d %f %f %f %f\n", "fitpeak LVMQfit",
1055 cpl_err_tmp, cpl_vector_get(fit_par,0), cpl_vector_get(fit_par,1),
1056 cpl_vector_get(fit_par,2),cpl_vector_get(fit_par,3));
1057 if (mx != NULL) cpl_matrix_unwrap(mx);
1058 if (fit_par != NULL) cpl_vector_delete(fit_par);
1059 }
1060// printf("\n");
1061 cpl_vector_delete(vx);
1062 cpl_vector_delete(vy);
1063
1064 if (cpl_err != CPL_ERROR_NONE) {
1065 if (cpl_err != CPL_ERROR_CONTINUE) {
1066 cpl_msg_error("","%s\n",cpl_error_get_message_default(cpl_err));
1067 }
1068 return error;
1069 }
1070 *sigma_par = sigma;
1071 return x0;
1072
1073}
1074
1075/*----------------------------------------------------------------------------*/
1089/*----------------------------------------------------------------------------*/
1091 cpl_bivector *object,
1092 cpl_vector *peaks,
1093 ifsBand bandId,
1094 const int pfit_order) {
1095
1096 cpl_vector *lambda_fit = NULL,
1097 *ref_fit = NULL,
1098 *sigma_fit = NULL,
1099 *lambda_ref = NULL,
1100 *lambda_tmp = NULL,
1101 *sigma_tmp = NULL,
1102 *final_obj_in = NULL,
1103 *final_obj_fit = NULL,
1104 *final_obj_diff = NULL;
1105 cpl_polynomial *coeffs = NULL;
1106 cpl_matrix * samppos = NULL;
1107
1108 int halfwidth_obj = 0,
1109 i = 0;
1110 cpl_size obj_size = 0,
1111 no_peaks = 0,
1112 no_valid_peaks = 0,
1113 peak_idx = 0,
1114 v_idx = 0;
1115 int *invalid_index = NULL;
1116
1117 double lambda_in = 0.0,
1118 lambda_out = 0.0,
1119 sigma = 0.0,
1120 l_median = 0.0,
1121 l_stdev = 0.0,
1122 s_median = 0.0,
1123 s_stdev = 0.0,
1124 l_limit = 0.0,
1125 s_limit = 0.0,
1126 delta_lambda = 0.0,
1127 resolution;
1128
1129 const char *stype = NULL;
1130
1131 TRY {
1132 ASSURE(object != NULL &&
1133 peaks != NULL,
1134 CPL_ERROR_NULL_INPUT,
1135 "Not all input data is provided!");
1136
1137 resolution = eris_ifu_get_band_resolution(bandId);
1138
1139 obj_size = cpl_bivector_get_size(object);
1140 no_peaks = cpl_vector_get_size(peaks);
1141 if (IDL !=NULL ) {
1142 fprintf(IDL, "%20s: %lld %lld %f\n", "xcorr input", obj_size, no_peaks, resolution);
1143 fprintf(IDL, "%20s: %lld ", "xcorr object_l", obj_size); cpl_vector_dump(cpl_bivector_get_x_const(object), IDL);
1144 fprintf(IDL, "%20s: %lld ", "xcorr object_v", obj_size); cpl_vector_dump(cpl_bivector_get_y_const(object), IDL);
1145 fprintf(IDL, "%20s: %lld ", "xcorr peaks", no_peaks); cpl_vector_dump(peaks, IDL);
1146 }
1147
1148 ASSURE(obj_size > 1 && no_peaks > 1 ,
1149 CPL_ERROR_ILLEGAL_INPUT,
1150 "Input spectra must have more than one value");
1151
1153 invalid_index = cpl_calloc(no_peaks, sizeof(int)));
1154
1155 delta_lambda = 2. *
1156 cpl_vector_get(cpl_bivector_get_x_const(object), cpl_bivector_get_size(object) / 2) /
1157 resolution;
1158
1159
1160 halfwidth_obj = delta_lambda / (cpl_vector_get(cpl_bivector_get_x_const(object),1) -
1161 cpl_vector_get(cpl_bivector_get_x_const(object),0));
1162 //cpl_msg_info(cpl_func,"computed halfwidth_obj: %d",halfwidth_obj);
1163 halfwidth_obj = 8; // 8 pixels allows to recover also large line shifts (due to flexures) with poly order = 0
1164 //cpl_msg_info(cpl_func,"hard-coded halfwidth_obj: %d",halfwidth_obj);
1165 // second scan object spectrum
1166 // find exact peak location by fitting a gaussian
1167 // detect and withdraw outliers
1169 lambda_fit = cpl_vector_new(no_peaks));
1171 sigma_fit = cpl_vector_new(no_peaks));
1173 lambda_ref = cpl_vector_new(no_peaks));
1175 lambda_tmp = cpl_vector_new(no_peaks));
1177 sigma_tmp = cpl_vector_new(no_peaks));
1178
1179 peak_idx = 0;
1180 stype="object";
1181 if (IDL !=NULL ) fprintf(IDL, "%20s: %s\n", "xcorr spectrum type", stype);
1182 for (i = 0; i < no_peaks; i++) {
1183 lambda_in = cpl_vector_get(peaks,i);
1184 sigma = 0.0;
1185 lambda_out = fit_peak (object, obj_size, lambda_in, halfwidth_obj, &sigma);
1186 if (invalid_index[i] == 0) {
1187 if (lambda_out > 0.) {
1189 cpl_vector_set(lambda_fit, i, lambda_out));
1191 cpl_vector_set(sigma_fit, i, sigma));
1193 cpl_vector_set(lambda_ref, peak_idx, lambda_in));
1195 cpl_vector_set(lambda_tmp, peak_idx, lambda_out));
1197 cpl_vector_set(sigma_tmp, peak_idx, sigma));
1198 peak_idx++;
1199 } else {
1200 invalid_index[i] = 5;
1201 cpl_msg_debug(cpl_func,
1202 "Gaussian fit failed for %s spectrum, wavelenght %f, peak index %d",
1203 stype, lambda_in, i);
1204 }
1205 }
1206 }
1208 cpl_vector_set_size(lambda_ref,peak_idx));
1210 cpl_vector_set_size(lambda_tmp,peak_idx));
1212 cpl_vector_set_size(sigma_tmp,peak_idx));
1213 if (IDL !=NULL ) {
1214 fprintf(IDL, "%20s: %lld ", "xcorr lambda_ref", peak_idx); cpl_vector_dump(lambda_ref, IDL);
1215 fprintf(IDL, "%20s: %lld ", "xcorr lambda_tmp", peak_idx); cpl_vector_dump(lambda_tmp, IDL);
1216 fprintf(IDL, "%20s: %lld ", "xcorr sigma_tmp", peak_idx); cpl_vector_dump(sigma_tmp, IDL);
1217 }
1218
1220 cpl_vector_subtract(lambda_tmp,lambda_ref));
1221 l_median = cpl_vector_get_median_const(lambda_tmp);
1222 l_stdev = cpl_vector_get_stdev(lambda_tmp);
1223 s_median = cpl_vector_get_median_const(sigma_tmp);
1224 s_stdev = cpl_vector_get_stdev(sigma_tmp);
1225 l_limit = 2. * l_stdev;
1226 s_limit = 2. * s_stdev;
1227 cpl_vector_delete(lambda_ref);
1228 cpl_vector_delete(lambda_tmp);
1229 cpl_vector_delete(sigma_tmp);
1230 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);
1231
1232 for (i = 0; i < no_peaks; i++){
1233 if (invalid_index[i] == 0) {
1234 double tmp_lambda = cpl_vector_get(lambda_fit,i) - cpl_vector_get(peaks,i);
1235 double tmp_sigma = cpl_vector_get(sigma_fit,i);
1236 if (fabs(tmp_lambda - l_median) > l_limit) {
1237 invalid_index[i] = 6;
1238 cpl_msg_debug(cpl_func,
1239 "Peak rejected due lambda outlier, %s spectrum, wavelength %f, index %d, limit %f, value %f",
1240 stype, cpl_vector_get(peaks,i), i, l_limit, fabs(tmp_lambda - l_median));
1241 } else if (fabs(tmp_sigma - s_median) > s_limit) {
1242 cpl_msg_debug(cpl_func,
1243 "Peak rejected due sigma outlier, %s spectrum, wavelength %f, index %d, limit %f, value %f",
1244 stype, cpl_vector_get(peaks,i), i, s_limit,fabs(tmp_sigma - s_median));
1245 invalid_index[i] = 7;
1246 }
1247 }
1248 }
1249 cpl_vector_delete(sigma_fit);
1250
1251 no_valid_peaks = 0;
1252 char *dbg_msg;
1254 dbg_msg = cpl_malloc((no_peaks * 2 + 1) * sizeof(char)));
1255 dbg_msg[no_peaks*2] = '\0';
1256 if (IDL !=NULL ) fprintf(IDL, "%20s: %lld", "xcorr invalid peaks", no_peaks);
1257 for (i = 0; i < no_peaks; i++){
1258 sprintf(&dbg_msg[2*i], "%2d", invalid_index[i]);
1259 if (invalid_index[i] == 0) {
1260 no_valid_peaks++;
1261 }
1262 if (IDL !=NULL ) fprintf(IDL, " %d", invalid_index[i]);
1263 }
1264 if (IDL !=NULL ) {
1265 fprintf(IDL, "\n");
1266 }
1267 cpl_msg_debug(__func__,"%d valid ones of %d peaks: %s", (int) no_valid_peaks, (int) no_peaks, dbg_msg);
1268 cpl_free(dbg_msg);
1269
1270 if (no_valid_peaks == 0) {
1271 cpl_msg_error(cpl_func, " |-----------------------------------------------------|");
1272 cpl_msg_error(cpl_func, " | No OH lines could be fitted. Aborting. |");
1273 cpl_msg_error(cpl_func, " | Run again with parameter --skip_oh_align |");
1274 cpl_msg_error(cpl_func, " | |");
1275 cpl_msg_error(cpl_func, " | WARNING: the spectral calibration of the outputs |");
1276 cpl_msg_error(cpl_func, " | is expected to be off for several pixels |");
1277 cpl_msg_error(cpl_func, " | due to flexure of the instrument |");
1278 cpl_msg_error(cpl_func, " |-----------------------------------------------------|");
1279
1280 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT);
1282 }
1283
1285 final_obj_in = cpl_vector_new(no_valid_peaks));
1287 final_obj_fit = cpl_vector_new(no_valid_peaks));
1289 final_obj_diff = cpl_vector_new(no_valid_peaks));
1290 v_idx = 0;
1291 for (i = 0; i < no_peaks; i++){
1292 if (invalid_index[i] == 0) {
1293 double in = cpl_vector_get(peaks,i);
1294 double fit = cpl_vector_get(lambda_fit,i);
1296 cpl_vector_set(final_obj_in, v_idx, in));
1298 cpl_vector_set(final_obj_fit, v_idx, fit));
1300 cpl_vector_set(final_obj_diff, v_idx, fit-in));
1301 v_idx++;
1302 }
1303 }
1304 if (IDL !=NULL ) {
1305 fprintf(IDL, "%20s: %lld ", "xcorr final_obj_in", no_valid_peaks); cpl_vector_dump(final_obj_in, IDL);
1306 fprintf(IDL, "%20s: %lld ", "xcorr final_obj_fit", no_valid_peaks); cpl_vector_dump(final_obj_fit, IDL);
1307 fprintf(IDL, "%20s: %lld ", "xcorr final_obj_diff", no_valid_peaks); cpl_vector_dump(final_obj_diff, IDL);
1308 }
1309 /* poly fit deg can be changed by user.
1310 0 is better in K band to prevent divergence on OH corr due to extrapolation
1311 higher walues (was 3 in the past) may allow higher accuracy in H and J band
1312 with many lines.
1313 */
1314
1315 cpl_size degree[1] = {0}; //essentially taking the mean of final_obj_diff
1316 degree[0] = pfit_order;
1317 cpl_msg_info(cpl_func,"Use poly deg: %lld to determine OH correction",degree[0]);
1319 coeffs = cpl_polynomial_new(1));
1320
1321 if (cpl_vector_get_size(final_obj_in) > (degree[0] + 3)) {
1323 samppos = cpl_matrix_wrap(1,cpl_vector_get_size(final_obj_in),
1324 cpl_vector_get_data(final_obj_in)));
1326 cpl_polynomial_fit(coeffs, samppos, NULL, final_obj_diff, NULL, CPL_FALSE,
1327 degree, degree));
1328 } else {
1329 cpl_msg_warning(NULL,"Too few valid peaks for lambda correction using OH lines");
1330 // create polynomial a0=0
1331 cpl_size pows[1];
1332 pows[0] = 0;
1334 cpl_polynomial_set_coeff (coeffs, pows, 0.));
1335 }
1336
1337 if (IDL !=NULL ) {
1338 cpl_size pows[1];
1339 fprintf(IDL, "%20s: %lld", "xcorr polyfit", cpl_polynomial_get_degree(coeffs));
1340 for (i = 0; i <= cpl_polynomial_get_degree(coeffs); i++) {
1341 pows[0] = i;
1342 fprintf(IDL, " %f", cpl_polynomial_get_coeff(coeffs,pows));
1343 }
1344 fprintf(IDL, "\n");
1345 }
1346 }
1347 CATCH
1348 {
1349 CATCH_MSG();
1350 if (coeffs != NULL) {
1351 cpl_polynomial_delete(coeffs);
1352 coeffs = NULL;
1353 }
1354 }
1355
1356 if (ref_fit != NULL) cpl_vector_delete(ref_fit);
1357 if (lambda_fit != NULL) cpl_vector_delete(lambda_fit);
1358 if (final_obj_in != NULL) cpl_vector_delete(final_obj_in);
1359 if (final_obj_fit != NULL) cpl_vector_delete(final_obj_fit);
1360 if (final_obj_diff != NULL) cpl_vector_delete(final_obj_diff);
1361 if (invalid_index != NULL) cpl_free(invalid_index);
1362 if (samppos != NULL) cpl_matrix_unwrap(samppos);
1363
1364 return coeffs;
1365}
1366/*----------------------------------------------------------------------------*/
1373/*----------------------------------------------------------------------------*/
1374void eris_ifu_lcorr_open_debug_file (const char* filename) {
1375 IDL = fopen(filename,"w");
1376}
1377
1378/*----------------------------------------------------------------------------*/
1383/*----------------------------------------------------------------------------*/
1385 fclose(IDL);
1386 IDL = NULL;
1387}
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_image * eris_ifu_lcorr_create_object_mask(const cpl_imagelist *cube, double min_frac, const cpl_vector *lambda, const cpl_vector *range)
Creates a mask of the cube.
cpl_bivector * eris_ifu_lcorr_extract_spectrum(const cpl_imagelist *cube, const cpl_propertylist *header, const double min_frac, const cpl_vector *range)
Creates a vector containing the spectrum of all marked spaxels.
cpl_polynomial * eris_ifu_lcorr_get(cpl_imagelist *cube, hdrl_imagelist *hdrlCube, const cpl_propertylist *header, cpl_vector *peaks, const int pfit_order)
Main function to create the lcal-correction.
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)
Creates a wavelength vector from an input cube.
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)
Get peaks of position of lines used in wavelength calibration.
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)
Get peaks of position of lines used in wavelength calibration.
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)
Creates a spectrum bivector (x: lambda) from an input 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 in input data cube
double eris_ifu_get_band_resolution(ifsBand band)
eris_ifu_get_band_resolution
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.