33#include "eris_ifu_lambda_corr.h"
34#include "eris_ifu_jitter_static.h"
35#include "eris_ifu_error.h"
85 const cpl_propertylist *header,
89 cpl_polynomial *lcorr_coeffs = NULL;
90 cpl_imagelist *tmpCube = NULL;
91 cpl_image *tmpImg = NULL;
92 cpl_bivector *obj_spectrum = NULL,
95 const int format_width = 14,
97 char *coeff_string = NULL,
98 coeff_dump[format_width * max_coeffs + 1];
100 ifsBand bandId = UNDEFINED_BAND;
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");
112 CPL_ERROR_NULL_INPUT,
"Not all input data is provided!");
142 tmpCube = cpl_imagelist_new();
145 cpl_imagelist_set(tmpCube, cpl_image_duplicate(tmpImg), sx);
164 cpl_imagelist_delete(tmpCube);
167 peaks, bandId, pfit_order));
171 for (ic = 0; ic <= cpl_polynomial_get_degree(lcorr_coeffs) && ic < max_coeffs; 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;
177 cpl_msg_debug(cpl_func,
"Lambda correction coeffs %s", coeff_dump);
181 cpl_polynomial_delete(lcorr_coeffs); lcorr_coeffs = NULL;
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;
214 const cpl_propertylist *header,
215 const double min_frac,
216 const cpl_vector *range) {
218 cpl_bivector *result = NULL;
219 cpl_vector *spectrum = NULL,
221 cpl_image *obj_mask = NULL;
224 ASSURE(cube != NULL && header != NULL,
225 CPL_ERROR_NULL_INPUT,
226 "Not all input data is provided!");
243 result = cpl_bivector_wrap_vectors(lambda, spectrum));
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);}
285 const cpl_vector *lambda,
286 const cpl_vector *range) {
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,
294 cpl_vector *sum = NULL,
297 cpl_mask *empty_mask = NULL;
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;
306 double *m_data = NULL;
307 float *mask_data = NULL;
312 CPL_ERROR_NULL_INPUT,
313 "Not all input data is provided!");
315 ASSURE(((lambda != NULL) && (range != NULL)) ||
316 ((lambda == NULL) && (range == NULL)) ,
317 CPL_ERROR_NULL_INPUT,
318 "Not all input data is provided!");
321 ASSURE(cpl_vector_get_size(range)%2 == 0,
322 CPL_ERROR_ILLEGAL_INPUT,
323 "Range vector size must be a multiple of 2");
325 nr = cpl_vector_get_size(range) / 2;
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));
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);
347 rcube = cpl_imagelist_new());
348 for (z=0; z<nz; z++) {
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)) {
360 slice = cpl_imagelist_get_const(cube, z));
362 cpl_imagelist_set(rcube, cpl_image_duplicate(slice), cnz));
368 icube = (cpl_imagelist*) cube;
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);
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++) {
391 if (m_data[px] <= max_value) {
403 if (mask != NULL) {cpl_image_delete(mask);}
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);}
438 cpl_vector *lambda_vector = NULL;
440 double crval3, cdelt3, crpix3 = 0.0;
441 double *lambda = 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");
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);
460 lambda_vector = cpl_vector_new(naxis3));
462 lambda = cpl_vector_get_data(lambda_vector));
464 for (z=0; z<naxis3; z++) {
465 lambda[z] = (z+1 - crpix3) * cdelt3 + crval3;
471 if (lambda_vector != NULL) {
472 cpl_vector_delete(lambda_vector);
473 lambda_vector = NULL;
477 return lambda_vector;
500 cpl_size ext_number) {
502 cpl_bivector *result = NULL;
503 cpl_vector *lambda = NULL,
505 cpl_propertylist *header = NULL;
506 double *lambda_data = NULL;
507 double crpix, crval, cdelt = 0.0;
512 CPL_ERROR_NULL_INPUT,
513 "Not all input data is provided!");
515 cpl_msg_info(__func__,
516 "Using file %s as OH reference spectrum for lambda correction",
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);
524 cpl_msg_error(
"",
"Problem loading file '%s' (%s --> Code %d)",
525 filename, cpl_error_get_message(),
526 cpl_error_get_code());
531 header = cpl_propertylist_load(filename, ext_number));
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)) {
541 crpix = cpl_propertylist_get_int(header, CRPIX1);
543 case CPL_TYPE_DOUBLE:
544 crpix = cpl_propertylist_get_double(header, CRPIX1);
547 crpix = cpl_propertylist_get_float(header, CRPIX1);
551 "CRPIX1 is of wrong type!");
556 lambda = cpl_vector_new(naxis1));
558 lambda_data = cpl_vector_get_data(lambda));
560 for (i = 0; i < naxis1; i++) {
561 lambda_data[i] = crval + (i + 1-crpix)*cdelt;
565 result = cpl_bivector_wrap_vectors(lambda, spec));
572 if (header != NULL) {cpl_propertylist_delete(header);}
606 cpl_array *positions = NULL;
608 cpl_vector *copied_spectrum = NULL;
618 double *spec_data = NULL,
620 const double *lambda_data = NULL;
623 ASSURE(spectrum != NULL && cpl_bivector_get_y_const(spectrum) != NULL,
624 CPL_ERROR_NULL_INPUT,
625 "Not all input data is provided!");
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;
640 copied_spectrum = cpl_vector_duplicate(cpl_bivector_get_y_const(spectrum)));
643 spec_data = cpl_vector_get_data(copied_spectrum));
645 spec_size = cpl_vector_get_size(copied_spectrum);
648 for (i = 0; i < (spec_size-1); i++) {
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)) {
665 diff_data = cpl_malloc((spec_size-1) *
sizeof(
double)));
668 positions = cpl_array_new(spec_size, CPL_TYPE_INT));
670 min = cpl_vector_get_max(copied_spectrum) * min_frac;
672 if (spec_data[0] < min) {
675 for (i = 0; i < (spec_size-1); i++) {
676 if (spec_data[i+1] < min) {
679 diff_data[i] = spec_data[i+1] - spec_data[i];
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));
691 cpl_array_set_size(positions, peak_cnt));
696 if (positions != NULL) {cpl_array_delete(positions);}
700 if (diff_data != NULL) {cpl_free(diff_data);}
701 if (copied_spectrum != NULL) {cpl_vector_delete(copied_spectrum);}
733 cpl_vector *peaks = NULL,
735 cpl_array *positions = NULL;
736 cpl_size no_peaks = 0,
738 const int *pos_data = NULL;
739 const double *spec_data = NULL;
740 double *lambda_data = NULL;
742 cpl_vector *ref_fit = NULL,
747 int *invalid_index = NULL;
748 cpl_size peak_idx = 0;
749 double delta_lambda = 0.0,
759 int validPeaksCnt = 0;
761 const int halfwidth = 5;
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!");
772 no_peaks = cpl_array_get_size(positions);
775 peaks = cpl_vector_new(no_peaks));
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));
784 spec_size = cpl_bivector_get_size(spectrum);
787 for (i = 0; i < no_peaks; i++) {
788 if (pos_data[i] >= spec_size) {
791 lambda_data[i] = spec_data[pos_data[i]];
796 invalid_index = cpl_calloc(no_peaks,
sizeof(
int)));
799 delta_lambda = 1.93 / 11200.;
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));
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));
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);
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));
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);
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));
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);
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);
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;
893 for (i = 0; i < no_peaks; i++) {
894 if (invalid_index[i] == 0) {
898 final_peaks = cpl_vector_new(validPeaksCnt);
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));
915 if (positions != NULL) {cpl_array_delete(positions);}
940int gauss1d_fnc(
const double x[],
const double a[],
double *result)
945 double offset = a[3];
950 double z = (x[0]- mean)/sigma;
951 double ez = exp(-z*z/2.);
952 *result = offset + peak * ez;
979 double z = (x[0]- mean)/sigma;
980 double ez = exp(-z*z/2.);
986 result[1] = peak * ez * z/sigma;
989 result[2] = result[1] * z;
1012double fit_peak (
const cpl_bivector *spectrum,
const cpl_size size,
1013 double lambda_in,
int half_width,
double *sigma_par) {
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,
1020 cpl_fit_mode fit_mode = CPL_FIT_ALL;
1021 cpl_error_code cpl_err;
1023 const double sqrt2pi = sqrt(2. * 3.14159265358979323846);
1026 if (IDL !=NULL ) fprintf(IDL,
"%20s: %f %d %lld %f\n",
"fitpeak input", lambda_in, half_width, size, sigma);
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))) {
1032 pos_found = cpl_vector_find(cpl_bivector_get_x_const(spectrum), lambda_in);
1033 if (pos_found < 0) {
1036 low_bound = pos_found - half_width;
1037 high_bound = pos_found + half_width;
1038 if (low_bound < 0) {
1041 if (high_bound >= size) {
1042 high_bound = size - 1;
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);
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);
1053 if (high_bound-low_bound < 4) {
1054 if (vx != NULL) {cpl_vector_delete(vx);}
1055 if (vy != NULL) {cpl_vector_delete(vy);}
1060 fit_mode = CPL_FIT_ALL;
1062 fit_mode = CPL_FIT_CENTROID | CPL_FIT_AREA | CPL_FIT_OFFSET;
1065 cpl_err = cpl_vector_fit_gaussian(vx, NULL, vy, NULL,
1066 fit_mode, &x0, &sigma, &area, &offset, &mserr, NULL, NULL);
1069 if (cpl_err != CPL_ERROR_NONE) {
1072 if (IDL !=NULL ) fprintf(IDL,
"%20s: %d %f %f %f %f\n",
"fitpeak vectorfit", cpl_err, area/sigma/sqrt2pi, x0, sigma, offset);
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,
1086 CPL_FIT_LVMQ_TOLERANCE / 10000.,
1088 CPL_FIT_LVMQ_MAXITER * 1000,
1092 if (cpl_err_tmp != CPL_ERROR_NONE) {
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);
1110 cpl_vector_delete(vx);
1111 cpl_vector_delete(vy);
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));
1140 cpl_bivector *
object,
1143 const int pfit_order) {
1145 cpl_vector *lambda_fit = 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;
1157 int halfwidth_obj = 0,
1159 cpl_size obj_size = 0,
1164 int *invalid_index = NULL;
1166 double lambda_in = 0.0,
1178 const char *stype = NULL;
1183 CPL_ERROR_NULL_INPUT,
1184 "Not all input data is provided!");
1188 obj_size = cpl_bivector_get_size(
object);
1189 no_peaks = cpl_vector_get_size(peaks);
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);
1197 ASSURE(obj_size > 1 && no_peaks > 1 ,
1198 CPL_ERROR_ILLEGAL_INPUT,
1199 "Input spectra must have more than one value");
1202 invalid_index = cpl_calloc(no_peaks,
sizeof(
int)));
1205 cpl_vector_get(cpl_bivector_get_x_const(
object), cpl_bivector_get_size(
object) / 2) /
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));
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));
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);
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));
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);
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));
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);
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);
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;
1298 cpl_vector_delete(sigma_fit);
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) {
1311 if (IDL !=NULL ) fprintf(IDL,
" %d", invalid_index[i]);
1316 cpl_msg_debug(__func__,
"%d valid ones of %d peaks: %s", (
int) no_valid_peaks, (
int) no_peaks, dbg_msg);
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,
" |-----------------------------------------------------|");
1329 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT);
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));
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));
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);
1364 cpl_size degree[1] = {0};
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));
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,
1378 cpl_msg_warning(NULL,
"Too few valid peaks for lambda correction using OH lines");
1383 cpl_polynomial_set_coeff (coeffs, pows, 0.));
1388 fprintf(IDL,
"%20s: %lld",
"xcorr polyfit", cpl_polynomial_get_degree(coeffs));
1389 for (i = 0; i <= cpl_polynomial_get_degree(coeffs); i++) {
1391 fprintf(IDL,
" %f", cpl_polynomial_get_coeff(coeffs,pows));
1399 if (coeffs != NULL) {
1400 cpl_polynomial_delete(coeffs);
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);
1424 IDL = fopen(filename,
"w");
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
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.