22#include "eris_ifu_distortion_static.h"
23#include "eris_ifu_wavecal_static.h"
24#include "eris_ifu_dfs.h"
25#include "eris_ifu_error.h"
26#include "eris_ifu_utils.h"
27#include "eris_ifu_debug.h"
28#include "eris_utils.h"
38cpl_vector* eris_ifu_dist_calc_centers_profile(
const cpl_vector* profile,
39 cpl_boolean lowerCutLevel)
52 const double *pprofile = NULL;
53 cpl_vector *pos = NULL,
55 *cen_estimates = NULL;
57 cpl_ensure(profile != NULL, CPL_ERROR_NULL_INPUT, NULL);
61 nx = cpl_vector_get_size(profile);
70 cut_level = cut_factor * mean;
81 pos = cpl_vector_new(3*SLITLET_CNT+20));
83 height = cpl_vector_new(3*SLITLET_CNT+20));
86 ppos = cpl_vector_get_data(pos));
88 pheight = cpl_vector_get_data(height));
91 pprofile = cpl_vector_get_data_const(profile));
93 for (cut_factor = 1.4; cut_factor > .1; cut_factor -= 0.2) {
94 cut_level = cut_factor * mean;
97 for (
int i = ERIS_IFU_DETECTOR_BP_BORDER;
98 i < nx-ERIS_IFU_DETECTOR_BP_BORDER;
102 if ((left == 0) && (pprofile[i] > cut_level)) {
106 if (((left != 0) && (right == 0)) &&
107 ((pprofile[i] < cut_level) || (i == nx-ERIS_IFU_DETECTOR_BP_BORDER-1))) {
111 if ((left != 0) && (right != 0)) {
112 width = right-left+1;
113 ppos[cnt] = (double)left + width/2.0;
114 pheight[cnt] = pprofile[(int) (ppos[cnt]+.5) ];
119 if (cnt >= cpl_vector_get_size(pos)) {
123 if (cnt == SLITLET_CNT || cnt == 3 * SLITLET_CNT) {
127 if (cnt > SLITLET_CNT && cnt < SLITLET_CNT + 20) {
128 est_cnt = SLITLET_CNT;
131 if (cnt > 3 * SLITLET_CNT) {
132 est_cnt = 3 * SLITLET_CNT;
139 cpl_bivector *toBeSorted = NULL;
140 BRK_IF_NULL(toBeSorted = cpl_bivector_wrap_vectors(pos, height));
142 CPL_SORT_DESCENDING, CPL_SORT_BY_Y));
143 cpl_bivector_unwrap_vectors(toBeSorted);
150 cen_estimates = cpl_vector_extract(pos, 0, cnt-1, 1));
152 BRK_IF_ERROR(cpl_vector_sort(cen_estimates, CPL_SORT_ASCENDING));
165 return cen_estimates;
173cpl_vector* eris_ifu_dist_estimate_low_slitlet(
const cpl_vector *est_centers)
175 cpl_vector *est_new = NULL,
177 double *pest_new = NULL;
178 const double *pest_centers = NULL;
182 cpl_ensure(est_centers, CPL_ERROR_NULL_INPUT, NULL);
187 pest_centers = cpl_vector_get_data_const(est_centers));
189 cnt = cpl_vector_get_size(est_centers);
190 if ((cnt == SLITLET_CNT) || (cnt == 3*SLITLET_CNT)) {
193 est_new = cpl_vector_duplicate(est_centers));
195 }
else if (cnt < SLITLET_CNT) {
198 est_new = cpl_vector_new(SLITLET_CNT));
199 cpl_vector_fill(est_new, 0.);
200 }
else if ((cnt > SLITLET_CNT+10) && (cnt < 3*SLITLET_CNT)) {
203 est_new = cpl_vector_new(3*SLITLET_CNT));
204 cpl_vector_fill(est_new, 0.);
209 est_new = cpl_vector_duplicate(est_centers));
213 cpl_vector_multiply_scalar(est_new, 0.));
215 pest_new = cpl_vector_get_data(est_new));
217 if (cnt < SLITLET_CNT) {
223 while ((fabs(pest_centers[ind+1]-pest_centers[ind]-2*SLITLET_WIDTH) > 10) && (ind < 18)) {
228 for (
int i = 0; i < ind+1; i++) {
229 pest_new[i] = pest_centers[i];
232 pest_new[15] = (pest_centers[ind+1] - pest_centers[ind])/2 + pest_centers[ind];
233 for (cpl_size i = ind+1; i < SLITLET_CNT; i++) {
234 pest_new[i+1] = pest_centers[i];
244 for (i = 0; i < ind+1; i++) {
245 pest_new[i] = pest_centers[i];
249 ind = 3*start_slit + 1;
251 cpl_boolean found = CPL_FALSE;
253 est_trace_distance = 20;
254 while (ind < 3*end_slit) {
255 double val = fabs(pest_centers[ind]-pest_centers[ind-3]-SLITLET_WIDTH);
256 if (found && (decr_found > 0)) {
257 val -= est_trace_distance;
262 pest_new[i++] = pest_centers[ind++];
265 pest_new[i] = pest_centers[ind-3]+SLITLET_WIDTH;
267 pest_new[i] = pest_centers[ind++];
275 for (; i < 3*SLITLET_CNT; i++) {
277 pest_new[i] = pest_centers[ind++];
284 cnt = cpl_vector_get_size(est_new);
286 while (pest_new[ind] < 0.0001 && ind > 0) {
291 est_new2 = cpl_vector_extract(est_new, 0, ind, 1));
322cpl_vector* eris_ifu_dist_calc_centers_fit(
const cpl_vector *profile,
323 const cpl_vector *est_centers,
324 cpl_boolean do_fix_cnt)
336 lastValidOffset = 0.,
337 *pfit_centers = NULL,
339 cpl_vector *fit_centers = NULL,
341 *est_centers2 = NULL;
342 cpl_boolean fix_cnt = FALSE;
343 struct gaussParStruct gaussPar;
344 eris_ifu_vector *v = NULL,
347 cpl_ensure(profile, CPL_ERROR_NULL_INPUT, NULL);
348 cpl_ensure(cpl_vector_get_size(profile) == ERIS_IFU_DETECTOR_SIZE,
349 CPL_ERROR_ILLEGAL_INPUT, NULL);
350 cpl_ensure(est_centers, CPL_ERROR_NULL_INPUT, NULL);
355 est_centers2 = eris_ifu_dist_estimate_low_slitlet(est_centers));
357 cnt = (int) cpl_vector_get_size(est_centers2);
361 if (cnt < SLITLET_CNT) {
362 cpl_msg_error(cpl_func,
"Detected %d traces instead of at least %d!",
368 if ((cnt > 2*SLITLET_CNT) && (cnt < 3*SLITLET_CNT)) {
369 cpl_msg_error(cpl_func,
"Detected %d traces instead of at least %d!",
370 cnt2, 3*SLITLET_CNT);
376 if (do_fix_cnt && (cnt != SLITLET_CNT) && (cnt != 3*SLITLET_CNT)) {
384 fit_centers = cpl_vector_new(cnt));
386 pfit_centers = cpl_vector_get_data(fit_centers));
389 fit_peaks = cpl_vector_new(cnt));
391 pfit_peaks = cpl_vector_get_data(fit_peaks));
394 for (
int i = 0; i < cnt; i++) {
395 cen = (int) (cpl_vector_get(est_centers2, i) + 0.5);
397 eris_ifu_line_gauss_fit(profile, cen,
398 NS_EST_SLIT_DIST/3, &gaussPar));
400 if (gaussPar.errorCode == 0) {
401 pfit_centers[i] = gaussPar.x0;
403 pfit_centers[i] - cpl_vector_get(est_centers2, i);
405 pfit_centers[i] = cpl_vector_get(est_centers2, i) +
409 pfit_peaks[i] = gaussPar.area
410 / sqrt(2*CPL_MATH_PI*pow(gaussPar.sigma,2))
431 for (
int i = start; i <= end; i++) {
433 if ((val < med-thresh1*std) || (val > med+thresh1*std)) {
441 start = cnt-1-cnt/10*2;
450 for (
int i = start; i <= end; i++) {
452 if ((val < med-thresh1*std) || (val > med+thresh1*std)) {
461 if ((cnt2 != SLITLET_CNT) && (cnt2 != 3*SLITLET_CNT)) {
465 for (
int i = 0; i <= end; i++) {
468 if ((val < med-thresh2*std) || (val > med+thresh2*std)) {
477 if ((cnt2 != SLITLET_CNT) && (cnt2 != 3*SLITLET_CNT)) {
479 if (abs(SLITLET_CNT-cnt2) < 10) {
482 if (abs(3*SLITLET_CNT-cnt2) < 10) {
483 cnt3 = 3*SLITLET_CNT;
486 cpl_msg_error(cpl_func,
"Detected %d traces instead of %d!", cnt2, cnt3);
490 cpl_vector *fit_centers2 = NULL;
491 double *pfit_centers2 = NULL;
493 fit_centers2 = cpl_vector_new(cnt2));
495 pfit_centers2 = cpl_vector_get_data(fit_centers2));
497 for (
int i = 0; i < cnt; i++) {
499 pfit_centers2[j++] = pfit_centers[i];
502 cpl_vector_delete(fit_centers);
503 fit_centers = fit_centers2;
525cpl_error_code eris_ifu_dist_calc_centers_copy(
const cpl_vector *fit_centers,
528 cpl_table **cen_array)
531 index_to_compare = 0,
533 double last_val = 0.,
535 cpl_error_code err = CPL_ERROR_NONE;
536 const double *pfit_centers = NULL;
538 cpl_ensure_code(fit_centers, CPL_ERROR_NULL_INPUT);
539 cpl_ensure_code(cen_array, CPL_ERROR_NULL_INPUT);
543 actual_size = (int) cpl_vector_get_size(fit_centers);
545 pfit_centers = cpl_vector_get_data_const(fit_centers));
547 if (actual_size == SLITLET_CNT) {
548 for (
int i = 0; i < SLITLET_CNT; i++) {
550 cpl_table_set_double(cen_array[i],
"y", y_index, y_value));
552 cpl_table_set_double(cen_array[i],
"x", y_index, pfit_centers[i]));
554 }
else if (actual_size == 3*SLITLET_CNT) {
555 for (
int i = 0; i < SLITLET_CNT; i++) {
557 cpl_table_set_double(cen_array[i],
"y", y_index, y_value));
561 cpl_table_set_double(cen_array[i],
"x_l", y_index, pfit_centers[3*i]));
565 cpl_table_set_double(cen_array[i],
"x", y_index, pfit_centers[3*i+1]));
569 cpl_table_set_double(cen_array[i],
"x_r", y_index, pfit_centers[3*i+2]));
572 cpl_boolean special_handling = CPL_FALSE;
574 if (y_index < cpl_table_get_nrow(cen_array[0])/2) {
576 index_to_compare = y_index+1;
579 index_to_compare = y_index-1;
582 if (!special_handling && (actual_size < 3*SLITLET_CNT)) {
584 last_val = cpl_table_get_double(cen_array[0],
"x_l", index_to_compare, &tmp);
585 actual_val = pfit_centers[0];
586 if (!special_handling && (fabs(last_val-actual_val) < 5.)) {
591 for (
int i = 0; i < SLITLET_CNT; i++) {
593 cpl_table_set_double(cen_array[i],
"y", y_index, y_value));
597 cpl_table_set_double(cen_array[i],
"x_l", y_index, pfit_centers[3*i]));
598 if (++tmp == actual_size)
break;
602 cpl_table_set_double(cen_array[i],
"x", y_index, pfit_centers[3*i+1]));
603 if (++tmp == actual_size)
break;
607 cpl_table_set_double(cen_array[i],
"x_r", y_index, pfit_centers[3*i+2]));
608 if (++tmp == actual_size)
break;
610 special_handling = CPL_TRUE;
614 last_val = cpl_table_get_double(cen_array[SLITLET_CNT-1],
"x_r", index_to_compare, &tmp);
615 actual_val = pfit_centers[actual_size-1];
616 if (!special_handling && (fabs(last_val-actual_val) < 5.)) {
621 for (
int i = SLITLET_CNT-1; i >= 0; i--) {
623 cpl_table_set_double(cen_array[i],
"y", y_index, y_value));
627 cpl_table_set_double(cen_array[i],
"x_r", y_index, pfit_centers[tmp-1]));
628 if (--tmp == actual_size)
break;
632 cpl_table_set_double(cen_array[i],
"x", y_index, pfit_centers[tmp-1]));
633 if (--tmp == actual_size)
break;
637 cpl_table_set_double(cen_array[i],
"x_l", y_index, pfit_centers[tmp-1]));
638 if (--tmp == actual_size)
break;
640 special_handling = CPL_TRUE;
644 if (!special_handling && (actual_size < SLITLET_CNT)) {
646 last_val = cpl_table_get_double(cen_array[0],
"x", index_to_compare, &tmp);
647 actual_val = pfit_centers[0];
648 if (!special_handling && (fabs(last_val-actual_val) < 5.)) {
653 for (
int i = 0; i < SLITLET_CNT; i++) {
655 cpl_table_set_double(cen_array[i],
"y", y_index, y_value));
657 cpl_table_set_double(cen_array[i],
"x", y_index, pfit_centers[i]));
658 if (++tmp == actual_size)
break;
660 special_handling = CPL_TRUE;
664 last_val = cpl_table_get_double(cen_array[SLITLET_CNT-1],
"x", index_to_compare, &tmp);
665 actual_val = pfit_centers[actual_size-1];
666 if (!special_handling && (fabs(last_val-actual_val) < 5.)) {
671 for (
int i = SLITLET_CNT-1; i >= 0; i--) {
673 cpl_table_set_double(cen_array[i],
"y", y_index, y_value));
675 cpl_table_set_double(cen_array[i],
"x", y_index, pfit_centers[tmp-1]));
676 if (--tmp == actual_size)
break;
678 special_handling = CPL_TRUE;
682 if (!special_handling) {
684 "Handling of trace running out of "
685 "detector image failed!!!");
692 for (
int j = 0; j < SLITLET_CNT; j++) {
693 cpl_table_set_double(cen_array[j],
"x", y_index, 0.);
694 cpl_table_set_double(cen_array[j],
"y", y_index, 0.);
697 err = cpl_error_get_code();
703cpl_table** eris_ifu_dist_calc_centers(
const hdrl_image* fibre_div,
704 const hdrl_image *fibre_on,
716 const cpl_image *img = NULL,
719 cpl_vector *profile_x = NULL,
720 *profile_x_div = NULL,
721 *profile_x_on = NULL,
723 *est_centers_div = NULL,
724 *est_centers_on = NULL,
726 *fit_centers_middle = NULL;
727 cpl_table **cen_array = NULL;
730 cpl_ensure(fibre_div, CPL_ERROR_NULL_INPUT, NULL);
731 cpl_ensure(fibre_on, CPL_ERROR_NULL_INPUT, NULL);
734 cpl_ensure(nr_values % 2 == 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
735 cpl_ensure(height % 2 == 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
748 cen_array = cpl_calloc(SLITLET_CNT,
sizeof(cpl_table*)));
758 center_y = ERIS_IFU_DETECTOR_BP_BORDER + ix_middle*height + height/2;
761 img_div, center_y, height));
764 img_on, center_y, height));
767 est_centers_div = eris_ifu_dist_calc_centers_profile(profile_x_div, CPL_FALSE));
769 est_centers_on = eris_ifu_dist_calc_centers_profile(profile_x_on, CPL_FALSE));
773 fit_centers_middle = eris_ifu_dist_calc_centers_fit(
774 profile_x_on, est_centers_on, CPL_TRUE));
776 if (productDepth & 4) {
777 cpl_propertylist *pl = NULL;
779 pl = cpl_propertylist_new());
782 cpl_propertylist_update_string(pl,
"EXTNAME",
"profile_x_div"));
784 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
786 cpl_propertylist_update_string(pl,
"EXTNAME",
"profile_x_on"));
788 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
790 cpl_propertylist_update_string(pl,
"EXTNAME",
"est_centers_div"));
792 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
794 cpl_propertylist_update_string(pl,
"EXTNAME",
"est_centers_on"));
796 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND,pl );
798 cpl_propertylist_update_string(pl,
"EXTNAME",
"fit_centers_middle"));
800 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND,pl);
812 cnt = (int) cpl_vector_get_size(fit_centers_middle);
814 if (cnt == SLITLET_CNT) {
816 for (
int j = 0; j < SLITLET_CNT; j++) {
818 cen_array[j] = cpl_table_new(nr_values));
820 cpl_table_new_column(cen_array[j],
"x", CPL_TYPE_DOUBLE));
822 cpl_table_new_column(cen_array[j],
"y", CPL_TYPE_DOUBLE));
823 for (
int i = 0; i < nr_values; i++) {
825 cpl_table_set(cen_array[j],
"x", i, NAN);
826 cpl_table_set(cen_array[j],
"y", i, NAN);
831 for (
int j = 0; j < SLITLET_CNT; j++) {
833 cen_array[j] = cpl_table_new(nr_values));
835 cpl_table_new_column(cen_array[j],
"x_l", CPL_TYPE_DOUBLE));
837 cpl_table_new_column(cen_array[j],
"x", CPL_TYPE_DOUBLE));
839 cpl_table_new_column(cen_array[j],
"x_r", CPL_TYPE_DOUBLE));
841 cpl_table_new_column(cen_array[j],
"y", CPL_TYPE_DOUBLE));
842 for (
int i = 0; i < nr_values; i++) {
844 cpl_table_set(cen_array[j],
"x_l", i, NAN);
845 cpl_table_set(cen_array[j],
"x", i, NAN);
846 cpl_table_set(cen_array[j],
"x_r", i, NAN);
847 cpl_table_set(cen_array[j],
"y", i, NAN);
861 BRK_IF_NULL(est_centers = cpl_vector_duplicate(fit_centers_middle));
862 for (
int i = ix_middle; i < nr_values; i++) {
863 center_y = ERIS_IFU_DETECTOR_BP_BORDER + i*height + height/2;
867 img, center_y, height));
870 fit_centers = eris_ifu_dist_calc_centers_fit(profile_x, est_centers, CPL_FALSE));
874 eris_ifu_dist_calc_centers_copy(fit_centers, i, center_y,
877 if ((productDepth & 4) != 0) {
878 char *extname = NULL;
879 cpl_propertylist *pl = NULL;
881 pl = cpl_propertylist_new());
882 extname = cpl_sprintf(
"Sx_%02d profile_x", i+1);
883 cpl_propertylist_update_string(pl,
"EXTNAME", extname);
886 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
887 extname = cpl_sprintf(
"Sx_%02d est_centers", i+1);
888 cpl_propertylist_update_string(pl,
"EXTNAME", extname);
891 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
892 extname = cpl_sprintf(
"Sx_%02d fit_centers", i+1);
893 cpl_propertylist_update_string(pl,
"EXTNAME", extname);
896 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND ,pl);
900 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
905 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers_middle));
906 for (
int i = ix_middle-1; i >= 0; i--) {
907 center_y = ERIS_IFU_DETECTOR_BP_BORDER + i*height + height/2;
911 img, center_y, height));
914 fit_centers = eris_ifu_dist_calc_centers_fit(profile_x, est_centers, CPL_FALSE));
918 eris_ifu_dist_calc_centers_copy(fit_centers, i, center_y,
921 if ((productDepth & 4) != 0) {
922 char *extname = NULL;
923 cpl_propertylist *pl = NULL;
925 pl = cpl_propertylist_new());
926 extname = cpl_sprintf(
"Sx_%02d profile_x", i+1);
927 cpl_propertylist_update_string(pl,
"EXTNAME", extname);
930 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
931 extname = cpl_sprintf(
"Sx_%02d est_centers", i+1);
932 cpl_propertylist_update_string(pl,
"EXTNAME", extname);
935 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
936 extname = cpl_sprintf(
"Sx_%02d fit_centers", i+1);
937 cpl_propertylist_update_string(pl,
"EXTNAME", extname);
940 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
944 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
949 if (productDepth & 4) {
952 cpl_propertylist_save(NULL,
"eris_ifu_distortion_dbg_centers_fitted.fits", CPL_IO_CREATE));
954 cpl_propertylist_save(NULL,
"eris_ifu_distortion_dbg_centers_fitted_visual.fits", CPL_IO_CREATE));
955 for (
int j = 0; j < SLITLET_CNT; j++) {
956 cpl_table_save(cen_array[j], NULL, NULL,
"eris_ifu_distortion_dbg_centers_fitted.fits", CPL_IO_EXTEND);
963 for (
int i = 0; i < SLITLET_CNT; i++) {
966 cpl_free(cen_array); cen_array = NULL;
980int eris_ifu_distortion_calc_y(
int n,
int i) {
984 return (
int)((double)ERIS_IFU_DETECTOR_SIZE_Y/n*(i+.5)+.5);
987int eris_ifu_distortion_target_left_edge(
int i) {
988 return i * SLITLET_WIDTH;
990int eris_ifu_distortion_target_right_edge(
int i) {
991 return (i + 1) * SLITLET_WIDTH - 1;
994int eris_ifu_distortion_get_narcs(
int i,
995 cpl_boolean triple_traces ,
996 cpl_boolean cut_off_left,
997 cpl_boolean cut_off_right)
1001 if (triple_traces) {
1007 if (((i == 0) && cut_off_left) ||
1008 ((i == SLITLET_CNT-1) && cut_off_right))
1017cpl_polynomial** eris_ifu_dist_calc_distortion(cpl_table **slit_edges,
1018 cpl_table **centers,
1020 cpl_boolean cut_off_left,
1021 cpl_boolean cut_off_right,
1022 cpl_table **minmax_borders,
1023 cpl_propertylist ***qc,
1024 cpl_propertylist *pl,
1025 cpl_frameset* frameset,
1026 const cpl_parameterlist* parlist)
1059 const double *pwave_y = NULL,
1061 cpl_polynomial **poly_u = NULL;
1062 cpl_bivector *grid = NULL;
1063 cpl_vector *val_to_fit = NULL,
1066 eris_ifu_vector *y_wave = NULL,
1069 cpl_boolean triple_traces = FALSE;
1070 cpl_table *tbl = NULL,
1071 *dbg_polynomials = NULL;
1072 struct arcstruct *arc_tbl = NULL;
1075 cpl_ensure(slit_edges, CPL_ERROR_NULL_INPUT, NULL);
1076 cpl_ensure(centers, CPL_ERROR_NULL_INPUT, NULL);
1077 cpl_ensure(minmax_borders, CPL_ERROR_NULL_INPUT, NULL);
1081 BRK_IF_NULL( dbg_polynomials = cpl_table_new(SLITLET_CNT));
1082 cpl_table_new_column(dbg_polynomials, ERIS_IFU_DIST_DBG_SLITLET, CPL_TYPE_INT);
1083 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_EDGE_LEFT, CPL_TYPE_DOUBLE, fit_order+1);
1084 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_EDGE_RIGHT, CPL_TYPE_DOUBLE, fit_order+1);
1085 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER_LEFT, CPL_TYPE_DOUBLE, fit_order+1);
1086 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER, CPL_TYPE_DOUBLE, fit_order+1);
1087 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER_RIGHT, CPL_TYPE_DOUBLE, fit_order+1);
1091 *minmax_borders = cpl_table_new(SLITLET_CNT));
1093 cpl_table_new_column(*minmax_borders, ERIS_IFU_POLY_EDGE_L, CPL_TYPE_DOUBLE));
1095 cpl_table_new_column(*minmax_borders, ERIS_IFU_POLY_EDGE_R, CPL_TYPE_DOUBLE));
1098 poly_u = cpl_calloc(SLITLET_CNT,
sizeof(cpl_polynomial*)));
1100 if (cpl_table_get_ncol(centers[5]) > 2) {
1101 triple_traces = TRUE;
1104 if (productDepth & 1) {
1105 cpl_propertylist_append_string(pl, CPL_DFS_PRO_CATG,
1107 cpl_propertylist_save(pl, ERIS_IFU_PRO_DIST_QC_FIT_FN,
1109 eris_setup_product_header(ERIS_IFU_PRO_DIST_QC_FIT_FN,
1110 "DIST_FIT_TABLE", CPL_FRAME_TYPE_TABLE,
1111 "eris_ifu_distortion", frameset, parlist, pl);
1114 arc_tbl = cpl_calloc(SLITLET_CNT,
sizeof(
struct arcstruct)));
1117 for (
int i = 0; i < SLITLET_CNT; i++) {
1120 n_arcs = eris_ifu_distortion_get_narcs(i, triple_traces,
1121 cut_off_left, cut_off_right);
1123 n_calib_wave = (int) cpl_table_get_nrow(slit_edges[i]);
1125 n_calib_cen = (int) cpl_table_get_nrow(centers[i]);
1129 pwave_y = cpl_table_get_data_double_const(
1130 slit_edges[i],
"y_pos"));
1132 pcenter_y = cpl_table_get_data_double_const(
1140 if (!((i == 0) && cut_off_left)) {
1143 arc_tbl[i].fit_l = eris_ifu_dist_calc_distortion_fitedge(
1144 slit_edges[i],
"edge_left", y_wave,
1145 n_calib_wave, n_size, fit_order,
1146 i, dbg_polynomials));
1148 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1151 arc_tbl[i].fit_r = eris_ifu_dist_calc_distortion_fitedge(
1152 slit_edges[i],
"edge_right", y_wave,
1153 n_calib_wave, n_size, fit_order,
1154 i, dbg_polynomials));
1157 arc_tbl[i].fit_c = eris_ifu_dist_calc_distortion_fitedge(
1158 centers[i],
"x", y_cen,
1159 n_calib_cen, n_size, fit_order,
1160 i, dbg_polynomials));
1161 if (triple_traces) {
1162 if (!((i == 0) && cut_off_left)) {
1165 arc_tbl[i].fit_c_l = eris_ifu_dist_calc_distortion_fitedge(
1166 centers[i],
"x_l", y_cen,
1167 n_calib_cen, n_size, fit_order,
1168 i, dbg_polynomials));
1173 if (cpl_table_count_invalid(centers[i],
"x_l") <= 0.1 * n_calib_cen) {
1176 arc_tbl[i].fit_c_l = eris_ifu_dist_calc_distortion_fitedge(
1177 centers[i],
"x_l", y_cen,
1178 n_calib_cen, n_size, fit_order,
1179 i, dbg_polynomials));
1183 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1186 arc_tbl[i].fit_c_r = eris_ifu_dist_calc_distortion_fitedge(
1187 centers[i],
"x_r", y_cen,
1188 n_calib_cen, n_size, fit_order,
1189 i, dbg_polynomials));
1194 if (cpl_table_count_invalid(centers[i],
"x_r") <= 0.1 * n_calib_cen) {
1197 arc_tbl[i].fit_c_r = eris_ifu_dist_calc_distortion_fitedge(
1198 centers[i],
"x_r", y_cen,
1199 n_calib_cen, n_size, fit_order,
1200 i, dbg_polynomials));
1208 BRK_IF_ERROR( cpl_table_save(dbg_polynomials, NULL, NULL,
1209 "eris_ifu_distortion_dbg_polynomials.fits", CPL_IO_CREATE));
1212 *qc = cpl_calloc(SLITLET_CNT,
sizeof(cpl_propertylist*)));
1213 for (
int i = 0; i < SLITLET_CNT; i++) {
1215 (*qc)[i] = cpl_propertylist_new());
1220 if (arc_tbl[0].fit_l == NULL) {
1225 cpl_propertylist_append_string((*qc)[0],
1226 "ESO EDGE L",
"artificial"));
1234 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_l == NULL)) {
1239 cpl_propertylist_append_string((*qc)[0],
1240 "ESO EDGE C-L",
"artificial"));
1248 cut_off_left = CPL_FALSE;
1251 if (cut_off_right) {
1252 if (arc_tbl[SLITLET_CNT-1].fit_r == NULL) {
1257 cpl_propertylist_append_string((*qc)[SLITLET_CNT-1],
1258 "ESO EDGE R",
"artificial"));
1266 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_r == NULL)) {
1271 cpl_propertylist_append_string((*qc)[0],
1272 "ESO EDGE C-R",
"artificial"));
1280 cut_off_right = CPL_FALSE;
1288 m_c = 64. * (o_c5 - o_l5) / (o_r5 - o_l5);
1289 if (triple_traces) {
1292 m_c_l = 64. * (o_c_l - o_l5) / (o_r5 - o_l5);
1293 m_c_r = 64. * (o_c_r - o_l5) / (o_r5 - o_l5);
1302 if (productDepth >= PD_DEBUG) {
1304 cpl_propertylist_update_string(pl, CPL_DFS_PRO_CATG,
1305 ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID));
1307 cpl_image_save(NULL, ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID_FN,
1308 CPL_TYPE_FLOAT, pl, CPL_IO_CREATE));
1313 for (
int i = 0; i < SLITLET_CNT; i++) {
1314 cpl_msg_debug(cpl_func,
"i: %d", i);
1316 n_arcs = eris_ifu_distortion_get_narcs(i, triple_traces,
1317 cut_off_left, cut_off_right);
1328 if (triple_traces) {
1331 cpl_msg_debug(cpl_func,
" o_l: %g, o_c_l: %g, o_c: %g, o_c_r: %g, o_r: %g", o_l, o_c_l, o_c, o_c_r, o_r);
1332 ASSURE(o_c_l < o_c, CPL_ERROR_ILLEGAL_OUTPUT, "Slitlet #%d: o_c_l >= o_c (o_c_l: %g, o_c: %g)
", i+1, o_c_l, o_c);
1333 ASSURE(o_c < o_c_r, CPL_ERROR_ILLEGAL_OUTPUT, "Slitlet #%d: o_c >= o_c_r (o_c: %g, o_c_r: %g)
", i+1, o_c, o_c_r);
1335 cpl_msg_debug(cpl_func, " o_l: %g, o_c: %g, o_r: %g
", o_l, o_c, o_r);
1339 * from these estimates define target positions for the arc-lines (left, center, right)
1341 // left+right edge are simple: a slitlet should have 64pix width
1342 t_o = eris_ifu_distortion_target_left_edge(i);
1343 t_l = eris_ifu_distortion_target_left_edge(i);
1344 t_r = eris_ifu_distortion_target_right_edge(i);
1345 t_l = t_o + m_c - (o_c-o_l) / (o_c5-o_l5) * m_c;
1346// t_l = t_o + m_c_r - (o_c_r - o_l) / m_t_t;
1347 // the center positions are calculated with the sentence of three...
1348 t_c = (int)((o_c-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1350 if (triple_traces) {
1351 t_c_l = (int)((o_c_l-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1352 t_c_r = (int)((o_c_r-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1353 t_c_l = t_o + m_c_l;
1354 t_c_r = t_o + m_c_r;
1355 cpl_msg_debug(cpl_func, " t_l: %f, t_c_l: %f, t_c: %f, t_c_r: %f, t_r: %f
", t_l, t_c_l, t_c, t_c_r, t_r);
1357 cpl_msg_debug(cpl_func, " t_l: %f, t_c: %f, t_r: %f
", t_l, t_c, t_r);
1365// printf(" %2.2d: %6.1f %6.1f %6.1f %6.1f %6.1f width: %.1f t_o: %6.1f t %6.1f %6.1f %6.1f %6.1f %6.1f tg %6.1f %6.1f %6.1f %6.1f %6.1f\n
",
1366// i, o_l, o_c_l, o_c, o_r, o_c_r, o_r-o_l, t_o, t_l, t_c_l, t_c, t_c_r, t_r, t_l-tx, t_c_l-tx, t_c-tx, t_c_r-tx, t_r-tx);
1367// cpl_msg_debug(cpl_func, "i: %02d, o_l: %7.2f, o_c_l: %7.2f,
"
1368// "o_c: %7.2f, o_c_r: %7.2f, o_r: %7.2f
",
1369// i, o_l, o_c_l, o_c, o_c_r, o_r);
1370// cpl_msg_debug(cpl_func, " t_l: %04d , t_c_l: %04d ,
"
1371// " t_c: %04d , t_c_r: %04d , t_r: %04d
",
1372// t_l, t_c_l, t_c, t_c_r, t_r);
1373 // create grid to fit to (contains target-coordinates)
1375 grid = cpl_bivector_new(n_arcs * n_size));
1377 // create vector with values to fit (contains origin-coordinates)
1379 val_to_fit = cpl_vector_new(n_arcs * n_size));
1382 // fill in edges and subtract always in a manner that destination_x(target) is 0 for left edge
1383 // fill in left edge
1385 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_l, val_to_fit,
1386 t_l-tx, n_size, arc_cnt++));
1387 if (triple_traces) {
1390 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c_l, val_to_fit,
1391 t_c_l-tx, n_size, arc_cnt++));
1394//cpl_msg_debug(cpl_func, ">>> %d
", i);
1399 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c, val_to_fit,
1400 t_c-tx, n_size, arc_cnt++));
1401 if (triple_traces) {
1404 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c_r, val_to_fit,
1405 t_c_r-tx, n_size, arc_cnt++));
1407 // fill in right edge
1409 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_r, val_to_fit,
1410 t_r-tx, n_size, arc_cnt++));
1412 // save l_min and r_max
1413 l_min = floor(eris_ifu_vector_get_min(arc_tbl[i].fit_l, &pos));
1415 cpl_table_set_double(*minmax_borders, ERIS_IFU_POLY_EDGE_L, i,
1418 cpl_table_set_double(*minmax_borders, ERIS_IFU_POLY_EDGE_R, i,
1419 ceil(eris_ifu_vector_get_max(arc_tbl[i].fit_r, &pos))));
1421 // fill in edges and subtract always in a manner that destination_x(measured) is 0.0 for left edge at beginning
1423 cpl_vector_subtract_scalar(val_to_fit, l_min));
1425 if (productDepth >= PD_DEBUG) {
1427 extName = cpl_sprintf("GRIDX_%2.2d
", i);
1429 cpl_propertylist_update_string(pl, "EXTNAME
", extName));
1431 cpl_vector_save(cpl_bivector_get_x(grid),
1432 ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID_FN,
1433 CPL_TYPE_FLOAT, pl, CPL_IO_EXTEND));
1435 extName = cpl_sprintf("GRIDY_%2.2d
", i);
1437 cpl_propertylist_update_string(pl, "EXTNAME
", extName));
1439 cpl_vector_save(cpl_bivector_get_y(grid),
1440 ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID_FN,
1441 CPL_TYPE_FLOAT, pl, CPL_IO_EXTEND));
1443 extName = cpl_sprintf("VAL2FIT_%2.2d
", i);
1445 cpl_propertylist_update_string(pl, "EXTNAME
", extName));
1447 cpl_vector_save(val_to_fit,
1448 ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID_FN,
1449 CPL_TYPE_FLOAT, pl, CPL_IO_EXTEND));
1455 /* Perform the fit */
1457 poly_u[i] = eris_ifu_dist_poly_fit_2d_create(grid, val_to_fit, NULL));
1459 eris_ifu_free_bivector(&grid);
1460 eris_ifu_free_vector(&val_to_fit);
1461 } // end: i = SLITLET_CNT
1463 // save values of all fitted edges and some stats
1464 if (productDepth & 1) {
1465 // for the ease of stats: create the y-vector with the used values
1467 y = cpl_vector_new(n_size));
1469 py = cpl_vector_get_data(y));
1470 for (int j = 0; j < n_size; j++) {
1471 py[j] = eris_ifu_distortion_calc_y(n_size, j);
1475 for (int i = 0; i < SLITLET_CNT; i++) {
1477 tbl = cpl_table_new(n_size);
1478 if (arc_tbl[i].fit_l != NULL) {
1480 cpl_table_new_column(tbl, "l
", CPL_TYPE_DOUBLE);
1481 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_l);
1482 cpl_table_copy_data_double(tbl, "l
", cpl_vector_get_data_const(tmp_vec));
1483 eris_ifu_free_vector(&tmp_vec);
1485 if (arc_tbl[i].fit_c_l != NULL) {
1486 cpl_table_new_column(tbl, "c_l
", CPL_TYPE_DOUBLE);
1487 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_c_l);
1488 cpl_table_copy_data_double(tbl, "c_l
", cpl_vector_get_data_const(tmp_vec));
1489 eris_ifu_free_vector(&tmp_vec);
1491 if (arc_tbl[i].fit_c != NULL) {
1492 std = eris_ifu_vector_get_stdev(arc_tbl[i].fit_c);
1493 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C STDEV
",i);
1494 keycomm = cpl_sprintf("[pix] center slitlet %2.2d
",i);
1495 if (!eris_ifu_is_nan_or_inf(std)) {
1496 cpl_propertylist_append_double((*qc)[i], keyname, std);
1498 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1500 cpl_propertylist_set_comment((*qc)[i], keyname,keycomm);
1503 cpl_table_new_column(tbl, "c
", CPL_TYPE_DOUBLE);
1504 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_c);
1505 cpl_table_copy_data_double(tbl, "c
", cpl_vector_get_data_const(tmp_vec));
1506 eris_ifu_free_vector(&tmp_vec);
1508 if (arc_tbl[i].fit_c_r != NULL) {
1509 cpl_table_new_column(tbl, "c_r
", CPL_TYPE_DOUBLE);
1510 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_c_r);
1511 cpl_table_copy_data_double(tbl, "c_r
", cpl_vector_get_data_const(tmp_vec));
1512 eris_ifu_free_vector(&tmp_vec);
1514 if (arc_tbl[i].fit_r != NULL) {
1515 cpl_table_new_column(tbl, "r
", CPL_TYPE_DOUBLE);
1516 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_r);
1517 cpl_table_copy_data_double(tbl, "r
", cpl_vector_get_data_const(tmp_vec));
1518 eris_ifu_free_vector(&tmp_vec);
1521 // calc stddev of differences of distances between single traces
1522 if ((arc_tbl[i].fit_l != NULL) && (arc_tbl[i].fit_r != NULL)) {
1523 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_r);
1524 eris_ifu_vector_subtract(t, arc_tbl[i].fit_l);
1525 std = eris_ifu_vector_get_stdev(t);
1526 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-L STDEV
",i);
1527 keycomm = cpl_sprintf("[pix] right-left distance slitlet %2.2d
",i);
1528 if (!eris_ifu_is_nan_or_inf(std)) {
1529 cpl_propertylist_append_double((*qc)[i], keyname, std);
1531 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1533 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1537 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1538 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-L MEDIAN
",i);
1539 keycomm = cpl_sprintf("[pix] right-left distance median slitlet %2.2d
",i);
1540 if (!eris_ifu_is_nan_or_inf(median)) {
1541 cpl_propertylist_append_double((*qc)[i], keyname, median);
1543 cpl_propertylist_append_string((*qc)[i], "MEDIAN R-L
", "NaN
");
1545 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1549 // for the ease of stats: save the slit-width & y
1550 cpl_table_new_column(tbl, "slit_width
", CPL_TYPE_DOUBLE);
1551 tmp_vec = eris_ifu_vector_get_data(t);
1552 cpl_table_copy_data_double(tbl, "slit_width
", cpl_vector_get_data_const(tmp_vec));
1553 cpl_table_new_column(tbl, "y
", CPL_TYPE_DOUBLE);
1554 cpl_table_copy_data_double(tbl, "y
", cpl_vector_get_data_const(y));
1555 eris_ifu_free_vector(&tmp_vec);
1556 eris_ifu_free_ifu_vector(&t);
1558 if ((arc_tbl[i].fit_l != NULL) && (arc_tbl[i].fit_c != NULL)) {
1559 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c);
1560 eris_ifu_vector_subtract(t, arc_tbl[i].fit_l);
1561 std = eris_ifu_vector_get_stdev(t);
1562 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-L STDEV
",i);
1563 keycomm = cpl_sprintf("[pix] center-left distance stdev slitlet %2.2d
",i);
1564 if (!eris_ifu_is_nan_or_inf(std)) {
1565 cpl_propertylist_append_double((*qc)[i], keyname, std);
1567 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1569 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1572 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1573 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-L MEDIAN
",i);
1574 keycomm = cpl_sprintf("[pix] center-left distance median slitlet %2.2d
",i);
1575 if (!eris_ifu_is_nan_or_inf(median)) {
1576 cpl_propertylist_append_double((*qc)[i], keyname, median);
1578 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1580 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1583 eris_ifu_free_ifu_vector(&t);
1585 if ((arc_tbl[i].fit_c != NULL) && (arc_tbl[i].fit_r != NULL)) {
1586 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_r);
1587 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c);
1588 std = eris_ifu_vector_get_stdev(t);
1589 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-C STDEV
",i);
1590 keycomm = cpl_sprintf("[pix] right-center distance stdev slitlet %2.2d
",i);
1591 if (!eris_ifu_is_nan_or_inf(std)) {
1592 cpl_propertylist_append_double((*qc)[i], keyname, std);
1594 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1596 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1599 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1600 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-C MEDIAN
",i);
1601 keycomm = cpl_sprintf("[pix] right-center distance median slitlet %2.2d
",i);
1602 if (!eris_ifu_is_nan_or_inf(median)) {
1603 cpl_propertylist_append_double((*qc)[i], keyname, median);
1605 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1607 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1610 eris_ifu_free_ifu_vector(&t);
1612 if ((arc_tbl[i].fit_c != NULL) && (arc_tbl[i].fit_c_l != NULL)) {
1613 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c);
1614 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c_l);
1615 std = eris_ifu_vector_get_stdev(t);
1616 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-CL STDEV
",i);
1617 keycomm = cpl_sprintf("[pix] center-centerleft distance stdev slitlet %2.2d
",i);
1618 if (!eris_ifu_is_nan_or_inf(std)) {
1619 cpl_propertylist_append_double((*qc)[i], keyname, std);
1621 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1623 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1626 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1627 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-CL MEDIAN
",i);
1628 keycomm = cpl_sprintf("[pix] center-centerleft distance median slitlet %2.2d
",i);
1629 if (!eris_ifu_is_nan_or_inf(median)) {
1630 cpl_propertylist_append_double((*qc)[i], keyname, median);
1632 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1634 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1637 eris_ifu_free_ifu_vector(&t);
1639 if ((arc_tbl[i].fit_c_r != NULL) && (arc_tbl[i].fit_c != NULL)) {
1640 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c_r);
1641 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c);
1642 std = eris_ifu_vector_get_stdev(t);
1643 keyname = cpl_sprintf("ESO QC SLITLET%2.2d CR-C STDEV
",i);
1644 keycomm = cpl_sprintf("[pix] centerright-center distance stdev slitlet %2.2d
",i);
1645 if (!eris_ifu_is_nan_or_inf(std)) {
1646 cpl_propertylist_append_double((*qc)[i], keyname, std);
1648 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1650 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1653 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1654 keyname = cpl_sprintf("ESO QC SLITLET%2.2d CR-C MEDIAN
",i);
1655 keycomm = cpl_sprintf("[pix] centerright-center distance median slitlet %2.2d
",i);
1656 if (!eris_ifu_is_nan_or_inf(median)) {
1657 cpl_propertylist_append_double((*qc)[i], keyname, median);
1659 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1661 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1664 eris_ifu_free_ifu_vector(&t);
1667 cpl_table_save(tbl, NULL, (*qc)[i], ERIS_IFU_PRO_DIST_QC_FIT_FN, CPL_IO_EXTEND));
1669 eris_ifu_free_table(&tbl);
1670 } // end: i = SLITLET_CNT
1671 } // end: if (productDepth & 1)
1676 for (int j = 0; j < SLITLET_CNT; j++) {
1677 cpl_polynomial_delete(poly_u[j]); poly_u[j] = NULL;
1679 cpl_free(poly_u); poly_u = NULL;
1681 eris_ifu_free_table(minmax_borders);
1683 if (*qc != NULL && **qc != NULL) {
1684 for (int i = 0; i < SLITLET_CNT; i++) {
1685 eris_ifu_free_propertylist(&(*qc)[i]);
1689 cpl_free(**qc); **qc = NULL;
1692 eris_ifu_free_table(&dbg_polynomials);
1693 eris_ifu_free_bivector(&grid);
1694 eris_ifu_free_vector(&val_to_fit);
1695 eris_ifu_free_vector(&y);
1696 eris_ifu_free_ifu_vector(&y_wave);
1697 for (int i = 0; i < SLITLET_CNT; i++) {
1698 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_l);
1699 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c);
1700 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c_l);
1701 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c_r);
1702 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_r);
1704 cpl_free(arc_tbl); arc_tbl = NULL;
1705 eris_check_error_code("eris_ifu_dist_calc_distortion
");
1709// includes center line
1710cpl_polynomial** eris_ifu_dist_calc_distortion_full(cpl_table **slit_edges,
1711 cpl_table **centers,
1713 cpl_boolean cut_off_left,
1714 cpl_boolean cut_off_right)
1733 const double *pwave_y = NULL,
1735 cpl_polynomial **poly_u = NULL;
1736 cpl_bivector *grid = NULL;
1737 cpl_vector *val_to_fit = NULL,
1739 eris_ifu_vector *y_wave = NULL,
1742 cpl_boolean triple_traces = FALSE;
1743 cpl_table *tbl = NULL,
1744 *dbg_polynomials = NULL;
1745 cpl_propertylist **pl = NULL;
1746 struct arcstruct *arc_tbl = NULL;
1748 cpl_ensure(slit_edges, CPL_ERROR_NULL_INPUT, NULL);
1749 cpl_ensure(centers, CPL_ERROR_NULL_INPUT, NULL);
1753 BRK_IF_NULL( dbg_polynomials = cpl_table_new(SLITLET_CNT));
1754 cpl_table_new_column(dbg_polynomials, ERIS_IFU_DIST_DBG_SLITLET, CPL_TYPE_INT);
1755 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_EDGE_LEFT, CPL_TYPE_DOUBLE, fit_order+1);
1756 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_EDGE_RIGHT, CPL_TYPE_DOUBLE, fit_order+1);
1757 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER_LEFT, CPL_TYPE_DOUBLE, fit_order+1);
1758 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER, CPL_TYPE_DOUBLE, fit_order+1);
1759 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER_RIGHT, CPL_TYPE_DOUBLE, fit_order+1);
1760 CHECK_ERROR_STATE();
1763 poly_u = cpl_calloc(SLITLET_CNT, sizeof(cpl_polynomial*)));
1765 if (cpl_table_get_ncol(centers[5]) > 2) {
1766 triple_traces = TRUE;
1770 cpl_propertylist_save(NULL, ERIS_IFU_PRO_DIST_QC_FIT_FN, CPL_IO_CREATE));
1773 arc_tbl = cpl_calloc(SLITLET_CNT, sizeof(struct arcstruct)));
1775 // calculate all slitlets taht are not cut off
1776 for (int i = 0; i < SLITLET_CNT; i++) {
1777 //cpl_msg_debug(cpl_func, "i: %d\n
", i);
1778 // get number of vertical traces (arcs) to process
1779 n_arcs = eris_ifu_distortion_get_narcs(i, triple_traces,
1780 cut_off_left, cut_off_right);
1781 // get number of detected wave_calib-lines
1782 n_calib_wave = (int) cpl_table_get_nrow(slit_edges[i]);
1783 // get number of centerpoints
1784 n_calib_cen = (int) cpl_table_get_nrow(centers[i]);
1786 // get y-coordinates
1788 pwave_y = cpl_table_get_data_double_const(
1789 slit_edges[i], "y_pos
"));
1791 pcenter_y = cpl_table_get_data_double_const(
1794 y_wave = eris_ifu_vector_new_wrap(n_calib_wave, pwave_y));
1796 y_cen = eris_ifu_vector_new_wrap(n_calib_cen, pcenter_y));
1798 // fit all edges (left, right, centers)
1799 if (!((i == 0) && cut_off_left)) {
1800 // process only if it is not the 1st slitlet and cutoff
1802 arc_tbl[i].fit_l = eris_ifu_dist_calc_distortion_fitedge(
1803 slit_edges[i], "edge_left
", y_wave,
1804 n_calib_wave, n_size, fit_order,
1805 i, dbg_polynomials));
1807 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1808 // process only if it is not the last slitlet and cutoff
1810 arc_tbl[i].fit_r = eris_ifu_dist_calc_distortion_fitedge(
1811 slit_edges[i], "edge_right
", y_wave,
1812 n_calib_wave, n_size, fit_order,
1813 i, dbg_polynomials));
1816 arc_tbl[i].fit_c = eris_ifu_dist_calc_distortion_fitedge(
1817 centers[i], "x
", y_cen,
1818 n_calib_cen, n_size, fit_order,
1819 i, dbg_polynomials));
1820 if (triple_traces) {
1821 if (!((i == 0) && cut_off_left)) {
1822 // process if it is not the 1st slitlet and not cutoff
1824 arc_tbl[i].fit_c_l = eris_ifu_dist_calc_distortion_fitedge(
1825 centers[i], "x_l
", y_cen,
1826 n_calib_cen, n_size, fit_order,
1827 i, dbg_polynomials));
1829 // if it is the last slitlet and cutoff, then
1830 // check first if, and how many, values are nan
1831 // If there are too many NaN's do nothing and copy the shape of c to c_l
1832 if (cpl_table_count_invalid(centers[i], "x_l
") <= 0.1 * n_calib_cen) {
1833 // calculate fitted edge only if less tahn 10% of the values are NaN
1835 arc_tbl[i].fit_c_l = eris_ifu_dist_calc_distortion_fitedge(
1836 centers[i], "x_l
", y_cen,
1837 n_calib_cen, n_size, fit_order,
1838 i, dbg_polynomials));
1842 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1843 // process if it is not the last slitlet and not cutoff
1845 arc_tbl[i].fit_c_r = eris_ifu_dist_calc_distortion_fitedge(
1846 centers[i], "x_r
", y_cen,
1847 n_calib_cen, n_size, fit_order,
1848 i, dbg_polynomials));
1850 // if it is the last slitlet and cutoff, then
1851 // check first if, and how many, values are nan
1852 // If there are too many NaN's do nothing and copy the shape of c to c_r
1853 if (cpl_table_count_invalid(centers[i], "x_r
") <= 0.1 * n_calib_cen) {
1854 // calculate fitted edge only if less than 10% of the values are NaN
1856 arc_tbl[i].fit_c_r = eris_ifu_dist_calc_distortion_fitedge(
1857 centers[i], "x_r
", y_cen,
1858 n_calib_cen, n_size, fit_order,
1859 i, dbg_polynomials));
1862 } // end: if (triple_traces)
1863 eris_ifu_free_ifu_vector(&y_wave);
1864 eris_ifu_free_ifu_vector(&y_cen);
1865 } // end: i = SLITLET_CNT
1868 pl = cpl_calloc(SLITLET_CNT, sizeof(cpl_propertylist*)));
1869 for (int i = 0; i < SLITLET_CNT; i++) {
1871 pl[i] = cpl_propertylist_new());
1874 // estimate positions of cut off edges with neighbouring slitlet width
1877 cpl_propertylist_append_string(pl[0],
1878 "EDGE L
", "artificial
"));
1879 if (arc_tbl[0].fit_l == NULL) {
1880 /* The leftmost edge of slitlet #0 is cut off. Therefore subtract the
1881 * width of slitlet #1 from the right edge of slitlet #0
1884 arc_tbl[0].fit_l = eris_ifu_vector_duplicate(arc_tbl[0].fit_r));
1886 eris_ifu_vector_subtract(arc_tbl[0].fit_l, arc_tbl[1].fit_r));
1888 eris_ifu_vector_add(arc_tbl[0].fit_l, arc_tbl[1].fit_l));
1890 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_l == NULL)) {
1891 /* The c_l-edge of slitlet #0 is cut off. Therefore subtract the
1892 * width of c-c_l of slitlet #31 to the left edge of slitlet #32
1895 arc_tbl[0].fit_c_l = eris_ifu_vector_duplicate(arc_tbl[0].fit_c));
1897 eris_ifu_vector_subtract(arc_tbl[0].fit_c_l, arc_tbl[1].fit_c));
1899 eris_ifu_vector_add(arc_tbl[0].fit_c_l, arc_tbl[1].fit_c_l));
1901 cut_off_left = CPL_FALSE;
1904 if (cut_off_right) {
1906 cpl_propertylist_append_string(pl[SLITLET_CNT-1],
1907 "EDGE R
", "artificial
"));
1908 if (arc_tbl[SLITLET_CNT-1].fit_r == NULL) {
1909 /* The rightmost edge of slitlet #32 is cut off. Therefore add the
1910 * width of slitlet #31 to the left edge of slitlet #32
1913 arc_tbl[SLITLET_CNT-1].fit_r = eris_ifu_vector_duplicate(arc_tbl[SLITLET_CNT-1].fit_l));
1915 eris_ifu_vector_add(arc_tbl[SLITLET_CNT-1].fit_r, arc_tbl[SLITLET_CNT-2].fit_r));
1917 eris_ifu_vector_subtract(arc_tbl[SLITLET_CNT-1].fit_r, arc_tbl[SLITLET_CNT-2].fit_l));
1919 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_r == NULL)) {
1920 /* The c_r-edge of slitlet #32 is cut off. Therefore add the
1921 * width of c_r-c of slitlet #31 to the left center edge of slitlet #32
1924 arc_tbl[SLITLET_CNT-1].fit_c_r = eris_ifu_vector_duplicate(arc_tbl[SLITLET_CNT-1].fit_c));
1926 eris_ifu_vector_add(arc_tbl[SLITLET_CNT-1].fit_c_r, arc_tbl[SLITLET_CNT-2].fit_c_r));
1928 eris_ifu_vector_subtract(arc_tbl[SLITLET_CNT-1].fit_c_r, arc_tbl[SLITLET_CNT-2].fit_c));
1930 cut_off_right = CPL_FALSE;
1933 const char *fn = "eris_ifu_distortion_dbg_calcdistor_grid_xy_val2fit.fits
";
1934 if (productDepth & 4) {
1935 eris_ifu_save_vector_dbg(NULL, fn, CPL_IO_CREATE, NULL);
1937 // estimate mean origin positions of the arc-lines and calculate
1938 // target positions for the edges, fill the grid, perform polynomial-fit
1939 for (int i = 0; i < SLITLET_CNT; i++) {
1940 // get number of vertical traces (arcs) to process
1941 n_arcs = eris_ifu_distortion_get_narcs(i, triple_traces,
1942 cut_off_left, cut_off_right);
1945 * estimate mean origin positions of the arc-lines (left, center, right)
1947 o_l = eris_ifu_vector_get_mean(arc_tbl[i].fit_l);
1948 o_c = eris_ifu_vector_get_mean(arc_tbl[i].fit_c);
1949 o_r = eris_ifu_vector_get_mean(arc_tbl[i].fit_r);
1950 if (triple_traces) {
1951 o_c_l = eris_ifu_vector_get_mean(arc_tbl[i].fit_c_l);
1952 o_c_r = eris_ifu_vector_get_mean(arc_tbl[i].fit_c_r);
1956 * from these estimates define target positions for the arc-lines (left, center, right)
1958 // left+right edge are simple: a slitlet should have 64pix width
1959 t_l = eris_ifu_distortion_target_left_edge(i);
1960 t_r = eris_ifu_distortion_target_right_edge(i);
1962 // the center positions are calculated with the sentence of three...
1963 t_c = (int)((o_c-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1964 if (triple_traces) {
1965 t_c_l = (int)((o_c_l-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1966 t_c_r = (int)((o_c_r-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1969// cpl_msg_debug(cpl_func, "i: %02d, o_l: %7.2f, o_c_l: %7.2f,
"
1970// "o_c: %7.2f, o_c_r: %7.2f, o_r: %7.2f
",
1971// i, o_l, o_c_l, o_c, o_c_r, o_r);
1972// cpl_msg_debug(cpl_func, " t_l: %04d , t_c_l: %04d ,
"
1973// " t_c: %04d , t_c_r: %04d , t_r: %04d
",
1974// t_l, t_c_l, t_c, t_c_r, t_r);
1975 // create grid to fit to (contains target-coordinates)
1977 grid = cpl_bivector_new(n_arcs * n_size));
1979 // create vector with values to fit (contains origin-coordinates)
1981 val_to_fit = cpl_vector_new(n_arcs * n_size));
1984 // fill in left edge
1986 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_l, val_to_fit,
1987 t_l, n_size, arc_cnt++));
1988 if (triple_traces) {
1991 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c_l, val_to_fit,
1992 t_c_l, n_size, arc_cnt++));
1996 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c, val_to_fit,
1997 t_c, n_size, arc_cnt++));
1998 if (triple_traces) {
2001 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c_r, val_to_fit,
2002 t_c_r, n_size, arc_cnt++));
2004 // fill in right edge
2006 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_r, val_to_fit,
2007 t_r, n_size, arc_cnt++));
2009 if (productDepth & 4) {
2010// cpl_propertylist *pl = NULL;
2012// pl = cpl_propertylist_new());
2013 char *extname = NULL;
2015 extname = cpl_sprintf("xVector Sx_%02d
", i+1);
2016 cpl_propertylist_update_string(pl[i], "EXTNAME
", extname);
2017 eris_ifu_free_string(&extname);
2018 eris_ifu_save_vector_dbg(cpl_bivector_get_x(grid), fn, CPL_IO_EXTEND, pl[i]);
2020 extname = cpl_sprintf("yVector Sx_%02d
", i+1);
2021 cpl_propertylist_update_string(pl[i], "EXTNAME
", extname);
2022 eris_ifu_free_string(&extname);
2023 eris_ifu_save_vector_dbg(cpl_bivector_get_y(grid), fn, CPL_IO_EXTEND, pl[i]);
2025 extname = cpl_sprintf("val2fit Sx_%02d
", i+1);
2026 cpl_propertylist_update_string(pl[i], "EXTNAME
", extname);
2027 eris_ifu_free_string(&extname);
2028 eris_ifu_save_vector_dbg(val_to_fit, fn, CPL_IO_EXTEND, pl[i]);
2030// eris_ifu_free_propertylist(&pl);
2033 /* Apply the fitting */
2035 poly_u[i] = eris_ifu_dist_poly_fit_2d_create(grid, val_to_fit, NULL));
2037 eris_ifu_free_bivector(&grid);
2038 eris_ifu_free_vector(&val_to_fit);
2039 } // end: i = SLITLET_CNT
2041 // save values of all fitted edges and some stats
2042 if (productDepth & 2) {
2043 for (int i = 0; i < SLITLET_CNT; i++) {
2045 tbl = cpl_table_new(n_size));
2046 if (arc_tbl[i].fit_l != NULL) {
2048 cpl_table_new_column(tbl, "l
", CPL_TYPE_DOUBLE));
2050 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_l));
2052 cpl_table_copy_data_double(tbl, "l
", cpl_vector_get_data_const(tt)));
2053 eris_ifu_free_vector(&tt);
2055 if (arc_tbl[i].fit_c_l != NULL) {
2057 cpl_table_new_column(tbl, "c_l
", CPL_TYPE_DOUBLE));
2059 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_c_l));
2061 cpl_table_copy_data_double(tbl, "c_l
", cpl_vector_get_data_const(tt)));
2062 eris_ifu_free_vector(&tt);
2064 if (arc_tbl[i].fit_c != NULL) {
2066 cpl_table_new_column(tbl, "c
", CPL_TYPE_DOUBLE));
2068 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_c));
2070 cpl_table_copy_data_double(tbl, "c
", cpl_vector_get_data_const(tt)));
2071 eris_ifu_free_vector(&tt);
2073 if (arc_tbl[i].fit_c_r != NULL) {
2075 cpl_table_new_column(tbl, "c_r
", CPL_TYPE_DOUBLE));
2077 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_c_r));
2079 cpl_table_copy_data_double(tbl, "c_r
", cpl_vector_get_data_const(tt)));
2080 eris_ifu_free_vector(&tt);
2082 if (arc_tbl[i].fit_r != NULL) {
2084 cpl_table_new_column(tbl, "r
", CPL_TYPE_DOUBLE));
2086 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_r));
2088 cpl_table_copy_data_double(tbl, "r
", cpl_vector_get_data_const(tt)));
2089 eris_ifu_free_vector(&tt);
2092 // calc stddev of differences of distances between single traces
2093 if ((arc_tbl[i].fit_l != NULL) && (arc_tbl[i].fit_r != NULL)) {
2094 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_r);
2096 eris_ifu_vector_subtract(t, arc_tbl[i].fit_l));
2097 std = eris_ifu_vector_get_stdev(t);
2098 if (!eris_ifu_is_nan_or_inf(std)) {
2100 cpl_propertylist_append_double(pl[i], "STDEV R-L
", std));
2103 cpl_propertylist_append_string(pl[i], "STDEV R-L
", "NaN
"));
2106 // for the ease of stats: save the slit-width
2108 cpl_table_new_column(tbl, "slit_width
", CPL_TYPE_DOUBLE));
2110 tt = eris_ifu_vector_get_data(t));
2112 cpl_table_copy_data_double(tbl, "slit_width
", cpl_vector_get_data_const(tt)));
2114 eris_ifu_free_vector(&tt);
2115 eris_ifu_free_ifu_vector(&t);
2117 if ((arc_tbl[i].fit_l != NULL) && (arc_tbl[i].fit_c != NULL)) {
2118 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c);
2120 eris_ifu_vector_subtract(t, arc_tbl[i].fit_l));
2121 std = eris_ifu_vector_get_stdev(t);
2122 if (!eris_ifu_is_nan_or_inf(std)) {
2124 cpl_propertylist_append_double(pl[i], "STDEV C-L
", std));
2127 cpl_propertylist_append_string(pl[i], "STDEV C-L
", "NaN
"));
2129 eris_ifu_free_ifu_vector(&t);
2131 if ((arc_tbl[i].fit_c != NULL) && (arc_tbl[i].fit_r != NULL)) {
2132 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_r);
2134 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c));
2135 std = eris_ifu_vector_get_stdev(t);
2136 if (!eris_ifu_is_nan_or_inf(std)) {
2138 cpl_propertylist_append_double(pl[i], "STDEV R-C
", std));
2141 cpl_propertylist_append_string(pl[i], "STDEV R-C
", "NaN
"));
2143 eris_ifu_free_ifu_vector(&t);
2145 if ((arc_tbl[i].fit_c != NULL) && (arc_tbl[i].fit_c_l != NULL)) {
2146 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c);
2148 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c_l));
2149 std = eris_ifu_vector_get_stdev(t);
2150 if (!eris_ifu_is_nan_or_inf(std)) {
2152 cpl_propertylist_append_double(pl[i], "STDEV C-CL
", std));
2155 cpl_propertylist_append_string(pl[i], "STDEV C-CL
", "NaN
"));
2157 eris_ifu_free_ifu_vector(&t);
2159 if ((arc_tbl[i].fit_c_r != NULL) && (arc_tbl[i].fit_c != NULL)) {
2160 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c_r);
2162 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c));
2163 std = eris_ifu_vector_get_stdev(t);
2164 if (!eris_ifu_is_nan_or_inf(std)) {
2166 cpl_propertylist_append_double(pl[i], "STDEV CR-C
", std));
2169 cpl_propertylist_append_string(pl[i], "STDEV CR-C
", "NaN
"));
2171 eris_ifu_free_ifu_vector(&t);
2173 if ((productDepth & 2) != 0) {
2175 cpl_table_save(tbl, NULL, pl[i], ERIS_IFU_PRO_DIST_QC_FIT_FN, CPL_IO_EXTEND));
2178 eris_ifu_free_table(&tbl);
2179 } // end: i = SLITLET_CNT
2180 } // end: if (productDepth & 2)
2185 for (int j = 0; j < SLITLET_CNT; j++) {
2186 cpl_polynomial_delete(poly_u[j]); poly_u[j] = NULL;
2188 cpl_free(poly_u); poly_u = NULL;
2191 eris_ifu_free_bivector(&grid);
2192 eris_ifu_free_vector(&val_to_fit);
2193 eris_ifu_free_ifu_vector(&y_wave);
2194 for (int i = 0; i < SLITLET_CNT; i++) {
2195 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_l);
2196 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c);
2197 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c_l);
2198 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c_r);
2199 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_r);
2202 for (int i = 0; i < SLITLET_CNT; i++) {
2203 eris_ifu_free_propertylist(&pl[i]);
2206 cpl_free(arc_tbl); arc_tbl = NULL;
2207 cpl_free(pl); pl = NULL;
2212//n_calib: size of input
2213// n_size: size of output
2214eris_ifu_vector* eris_ifu_dist_calc_distortion_fitedge(const cpl_table *edge,
2215 const char *col_name,
2216 const eris_ifu_vector *y,
2223 const double *px = NULL;
2224 double *pfit_par = NULL;
2225 eris_ifu_vector *x = NULL,
2227 cpl_vector *fit_par = NULL;
2228 cpl_array *tmp_array = NULL;
2230 cpl_ensure(edge, CPL_ERROR_NULL_INPUT, NULL);
2231 cpl_ensure(col_name, CPL_ERROR_NULL_INPUT, NULL);
2232 cpl_ensure(y, CPL_ERROR_NULL_INPUT, NULL);
2233 cpl_ensure(n_calib > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2234 cpl_ensure(n_size > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2235 cpl_ensure(fit_order > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2240 px = cpl_table_get_data_double_const(edge, col_name));
2243 x = eris_ifu_vector_new_wrap(n_calib, px));
2245 // fit polynomial to edge
2247 fit_par = eris_ifu_polyfit_edge(y, x, fit_order));
2248 eris_ifu_free_ifu_vector(&x);
2251 pfit_par = cpl_vector_get_data(fit_par));
2253 // save polynomials to table to support remote debugging
2254 tmp_array = cpl_array_wrap_double(pfit_par, cpl_vector_get_size(fit_par));
2255 cpl_table_set_int(dbg_tbl, ERIS_IFU_DIST_DBG_SLITLET, slitlet, slitlet);
2256 cpl_table_set_array(dbg_tbl, col_name, slitlet, tmp_array);
2257 cpl_array_unwrap(tmp_array);
2258 CHECK_ERROR_STATE();
2260 // create vector with fitted values
2262 fit = eris_ifu_vector_new(n_size));
2263 for (int j = 0; j < n_size; j++) {
2264 int yy = eris_ifu_distortion_calc_y(n_size, j);
2265 double v = pfit_par[0] +
2267 pfit_par[2] * pow(yy, 2);
2268// + pfit_par[3] * pow(yy, 3);
2270 eris_ifu_vector_set(fit, j, v));
2276 eris_ifu_free_ifu_vector(&fit);
2278 eris_ifu_free_vector(&fit_par);
2283cpl_error_code eris_ifu_dist_calc_distortion_fillgrid(cpl_bivector *grid,
2284 const eris_ifu_vector *data,
2285 cpl_vector *val_to_fit,
2290 cpl_error_code err = CPL_ERROR_NONE;
2291 double *pgridx = NULL,
2293 *pval_to_fit = NULL;
2295 cpl_ensure_code(grid, CPL_ERROR_NULL_INPUT);
2296 cpl_ensure_code(data, CPL_ERROR_NULL_INPUT);
2297 cpl_ensure_code(val_to_fit, CPL_ERROR_NULL_INPUT);
2301 cpl_ensure_code(x_pos >= -64, CPL_ERROR_ILLEGAL_INPUT);
2302 cpl_ensure_code(arc_cnt >= 0, CPL_ERROR_ILLEGAL_INPUT);
2303 cpl_ensure_code(n_size >= 0, CPL_ERROR_ILLEGAL_INPUT);
2308 pgridx = cpl_bivector_get_x_data(grid));
2310 pgridy = cpl_bivector_get_y_data(grid));
2312 pval_to_fit = cpl_vector_get_data(val_to_fit));
2314 for (int j = arc_cnt*n_size; j < (arc_cnt+1)*n_size; j++) {
2315 ASSURE(j < cpl_bivector_get_size(grid),
2316 CPL_ERROR_ILLEGAL_INPUT,
2319 int jj = j % n_size;
2321 // same target-x for all y-positions
2325 pgridy[j] = eris_ifu_distortion_calc_y(n_size, jj);
2327 // insert fitted x-value at y-position
2328 if (eris_ifu_vector_is_rejected(data, jj)) {
2329 pval_to_fit[j] = NAN;
2331 pval_to_fit[j] = eris_ifu_vector_get(data, jj);
2338 err = cpl_error_get_code();
2344cpl_polynomial* eris_ifu_dist_poly_fit_2d_create(cpl_bivector *xy_pos,
2345 const cpl_vector *values,
2349 double rechisq = 0.,
2351 cpl_size degree = NS_FIT_DEGREE;
2352 cpl_matrix *samppos2d = NULL;
2353 cpl_vector *fitresidual = NULL;
2354 cpl_polynomial *fit2d = NULL;
2356 typedef double* (*get_data)(cpl_bivector*);
2357 get_data data_extractor[2] = { &cpl_bivector_get_x_data,
2358 &cpl_bivector_get_y_data };
2360 cpl_ensure(xy_pos, CPL_ERROR_NULL_INPUT, NULL);
2361 cpl_ensure(values, CPL_ERROR_NULL_INPUT, NULL);
2362 cpl_ensure(degree > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2366 xy_size = (int) cpl_bivector_get_size(xy_pos);
2367 CHECK_ERROR_STATE();
2370 fit2d = cpl_polynomial_new(2));
2372 samppos2d = cpl_matrix_new(2, xy_size));
2374 for (int i = 0; i < 2; i++) {
2375 for (int j = 0; j < xy_size; j++) {
2376 value = data_extractor[i](xy_pos)[j];
2378 cpl_matrix_set(samppos2d, i, j, value));
2381 const cpl_size maxdeg2d[] = {2,3};
2383 cpl_polynomial_fit(fit2d, samppos2d, NULL, values, NULL, CPL_TRUE,
2386// cpl_polynomial_fit(fit2d, samppos2d, NULL, values, NULL, CPL_FALSE,
2390 fitresidual = cpl_vector_new(xy_size));
2392 cpl_vector_fill_polynomial_fit_residual(fitresidual, values, NULL,
2393 fit2d, samppos2d, &rechisq));
2395 *msee = cpl_vector_product(fitresidual, fitresidual)
2396 / (double) cpl_vector_get_size(fitresidual);
2402 eris_ifu_free_polynomial(&fit2d);
2405 eris_ifu_free_matrix(&samppos2d);
2406 eris_ifu_free_vector(&fitresidual);
2411cpl_error_code eris_ifu_dist_save_distortion(cpl_polynomial **poly2d,
2412 const cpl_table *minmax_borders,
2414 cpl_frameset *frameset,
2415 const cpl_parameterlist *parlist,
2416 cpl_propertylist **qc)
2420// char key_name[FILE_NAME_SZ];
2421 cpl_size max_degree;
2422 cpl_size coef_pow[2];
2423 cpl_table *poly_tbl = NULL;
2424 cpl_error_code err = CPL_ERROR_NONE;
2426 cpl_ensure_code(poly2d, CPL_ERROR_NULL_INPUT);
2427 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
2428 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
2432 for (int i = 0; i < SLITLET_CNT; i++) {
2433 if (poly2d[i] == NULL) {
2434 cpl_propertylist_save(NULL, fn, CPL_IO_EXTEND);
2436 max_degree = cpl_polynomial_get_degree(poly2d[i]);
2438 poly_tbl = cpl_table_new(max_degree * max_degree));
2440 cpl_table_new_column(poly_tbl,"degx
", CPL_TYPE_INT));
2442 cpl_table_new_column(poly_tbl,"degy
", CPL_TYPE_INT));
2444 cpl_table_new_column(poly_tbl,"coeff
", CPL_TYPE_DOUBLE));
2447 for (cpl_size cy=0; cy < max_degree; cy++) {
2448 for (cpl_size cx=0; cx < max_degree; cx++) {
2451 coeff = cpl_polynomial_get_coeff(poly2d[i], coef_pow);
2452 if (fabs(coeff) > 1e-30) { //Here DBL_ZERO_TOLERANCE 1e-10 is too high
2454 cpl_table_set_int(poly_tbl,"degx
",tx,(int) cx));
2456 cpl_table_set_int(poly_tbl,"degy
",tx,(int) cy));
2458 cpl_table_set_double(poly_tbl,"coeff
", tx,
2465 cpl_table_set_size(poly_tbl, tx));
2468// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 0, 0);
2470// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][0],
2471// "Polynomial distortion coefficient
"));
2473// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 1,0);
2475// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[1][0],
2476// "Polynomial distortion coefficient
"));
2478// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 0, 1);
2480// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][1],
2481// "Polynomial distortion coefficient
"));
2483// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 1, 1);
2485// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[1][1],
2486// "Polynomial distortion coefficient
"));
2488// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 2, 0);
2490// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[2][0],
2491// "Polynomial distortion coefficient
"));
2493// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 0, 2);
2495// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][2],
2496// "Polynomial distortion coefficient
"));
2498// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 2, 1);
2500// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[2][1],
2501// "Polynomial distortion coefficient
"));
2503// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 1, 2);
2505// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[1][2],
2506// "Polynpoly2domial distortion coefficient
"));
2508// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
","QC COEFF
", 3, 0);
2510// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[3][0],
2511// "Polynomial distortion coefficient
"));
2513// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
","QC COEFF
", 0, 3);
2515// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][3],
2516// "Polynomial distortion coefficient
"));
2518// xshift = eris_ifu_dist_compute_shift( x_c, y_c,
2519// pcf[0][0], pcf[1][0], pcf[0][1],
2520// pcf[1][1], pcf[2][0], pcf[0][2],
2521// pcf[2][1], pcf[1][2], pcf[3][0], pcf[0][3]);
2523// eris_ifu_dist_qclog_add_double(qc[i], "QC XSHIFT CC
", xshift,
2524// "X shift in x_c,y_c
"));
2526// xshift = eris_ifu_dist_compute_shift( x_l, y_l,
2527// pcf[0][0], pcf[1][0], pcf[0][1],
2528// pcf[1][1], pcf[2][0], pcf[0][2],
2529// pcf[2][1], pcf[1][2], pcf[3][0], pcf[0][3]);
2531// eris_ifu_dist_qclog_add_double(qc[i], "QC XSHIFT LL
", xshift,
2532// "X shift in x_l,y_l
"));
2534// xshift = eris_ifu_dist_compute_shift(x_l,y_u,pcf[0][0],pcf[1][0],pcf[0][1],
2535// pcf[1][1],pcf[2][0],pcf[0][2],
2536// pcf[2][1],pcf[1][2],pcf[3][0],pcf[0][3]);
2538// eris_ifu_dist_qclog_add_double(qc[i],"QC XSHIFT UL
",xshift,
2539// "X shift in x_l,y_u
"));
2541// xshift = eris_ifu_dist_compute_shift(x_u,y_u,pcf[0][0],pcf[1][0],pcf[0][1],
2542// pcf[1][1],pcf[2][0],pcf[0][2],
2543// pcf[2][1],pcf[1][2],pcf[3][0],pcf[0][3]);
2545// eris_ifu_dist_qclog_add_double(qc[i],"QC XSHIFT UR
",xshift,
2546// "X shift in x_u,y_u
"));
2548// xshift = eris_ifu_dist_compute_shift(x_u,y_l,pcf[0][0],pcf[1][0],pcf[0][1],
2549// pcf[1][1],pcf[2][0],pcf[0][2],
2550// pcf[2][1],pcf[1][2],pcf[3][0],pcf[0][3]);
2552// eris_ifu_dist_qclog_add_double(qc[i],"QC XSHIFT LR
",xshift,
2553// "X shift in x_u,y_l
"));
2555 extname = cpl_sprintf("SLITLET%2.2d
",i);
2556 cpl_propertylist_append_string(qc[i],"EXTNAME
",extname);
2559 eris_ifu_save_table(frameset, NULL, parlist, frameset, NULL,
2560 REC_NAME_DISTORTION,
2561 ERIS_IFU_PRO_DIST_DISTORTION,
2567 cpl_table_save(poly_tbl, NULL, qc[i], fn, CPL_IO_EXTEND));
2570 eris_ifu_free_table(&poly_tbl);
2571 } // if (poly2d[ii] != NULL)
2572 } // end: i = SLITLET_CNT
2574 cpl_propertylist* ext = cpl_propertylist_new();
2575 extname = cpl_sprintf("SLITLET%2.2d
",SLITLET_CNT);
2576 cpl_propertylist_append_string(ext,"EXTNAME
",extname);
2577 // save minmax borders as well
2579 cpl_table_save(minmax_borders, NULL, ext, fn, CPL_IO_EXTEND));
2580 cpl_propertylist_delete(ext);
2586 err = cpl_error_get_code();
2592hdrl_image* eris_ifu_dist_warp_image_full(const hdrl_image *hdrl_img_in,
2593 cpl_polynomial **poly_u,
2597 cpl_image *img_warped = NULL,
2598 *img_warped_extr = NULL;
2599 hdrl_image *hdrl_img_warped = NULL,
2600 *hdrl_img_warped_extr = NULL;
2601 cpl_polynomial *poly_v = NULL;
2604 cpl_ensure(hdrl_img_in, CPL_ERROR_NULL_INPUT, NULL);
2605 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2610 poly_v = cpl_polynomial_new(2));
2615 cpl_polynomial_set_coeff(poly_v, pows, 0.0));
2619 cpl_polynomial_set_coeff(poly_v, pows, 1.0));
2622 hdrl_img_warped = hdrl_image_new(hdrl_image_get_size_x(hdrl_img_in),
2623 hdrl_image_get_size_y(hdrl_img_in)));
2626 img_warped = hdrl_image_get_image(hdrl_img_warped));
2628 for (int i = 0; i < SLITLET_CNT; i++) {
2629 if (poly_u[i] != NULL) {
2630// cpl_msg_info(cpl_func, "Warp slitlet #%02d
", i+1);
2633 hdrl_img_warped_extr = eris_ifu_warp_polynomial_image(hdrl_img_in,
2634 poly_u[i], poly_v));
2636 // target left + right edge
2637 int t_l = eris_ifu_distortion_target_left_edge(i),
2638 t_r = eris_ifu_distortion_target_right_edge(i);
2640 img_warped_extr = hdrl_image_get_image(hdrl_img_warped_extr));
2642 if (productDepth & 8) {
2643 // save warped intermediate images uncut
2644 fn = cpl_sprintf("eris_ifu_distortion_dbg_warp_out_%02d.fits
", i+1);
2646 eris_ifu_save_image_dbg(img_warped_extr, fn,
2647 CPL_IO_CREATE, NULL));
2651 // set to zero left of slitlet (except for first slitlet)
2653 cpl_image_fill_window(img_warped_extr, 1, 1, t_l,
2654 ERIS_IFU_DETECTOR_SIZE_Y, 0.));
2656 if (i != SLITLET_CNT-1) {
2657 // set to zero right of slitlet (except for last slitlet)
2659 cpl_image_fill_window(img_warped_extr, t_r+2, 1,
2660 ERIS_IFU_DETECTOR_SIZE_X,
2661 ERIS_IFU_DETECTOR_SIZE_Y, 0.));
2664 if (productDepth & 8) {
2665 // save warped intermediate images cut
2667 eris_ifu_save_image_dbg(img_warped_extr, fn,
2668 CPL_IO_EXTEND, NULL));
2669 cpl_free(fn); fn = NULL;
2673 cpl_image_add(img_warped, img_warped_extr));
2675 eris_ifu_free_hdrl_image(&hdrl_img_warped_extr);
2677 } // end: i = SLITLET_CNT
2682 eris_ifu_free_hdrl_image(&hdrl_img_warped);
2685 eris_ifu_free_polynomial(&poly_v);
2687 return hdrl_img_warped;
2690hdrl_image* eris_ifu_dist_warp_slitlet(const hdrl_image *imgIn,
2691 const cpl_polynomial *poly_u,
2692 const cpl_polynomial *poly_v,
2699 hdrl_image *imgOutSlit = NULL,
2701 *imgOutSlitTrim = NULL;
2703 cpl_ensure(imgIn, CPL_ERROR_NULL_INPUT, NULL);
2704 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2705 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2710 // get left and right nominal border of slitlet
2711 llx = (int)(l_min)+1;
2712 urx = (int)(r_max)+1;
2714 if ((llx > 0) && (urx <= ERIS_IFU_DETECTOR_SIZE_X)) {
2716 imgInSlit = hdrl_image_extract(imgIn,
2718 urx, ERIS_IFU_DETECTOR_SIZE_Y));
2721 imgInSlit = hdrl_image_new(urx-llx+1, ERIS_IFU_DETECTOR_SIZE_Y));
2722 // mask all pixel as bad, the good ones will be flagged later
2725 tmpMask = cpl_mask_threshold_image_create(
2726 hdrl_image_get_image(imgInSlit),-1,1));
2727 hdrl_image_reject_from_mask(imgInSlit, tmpMask);
2728 cpl_mask_delete(tmpMask);
2732 tmpImg = hdrl_image_extract(imgIn,
2733 1, 1, urx, ERIS_IFU_DETECTOR_SIZE_Y));
2734 int pos1 = -llx + 2;
2736 hdrl_image_copy(imgInSlit,tmpImg, pos1, 1));
2739 tmpImg = hdrl_image_extract(imgIn,
2740 llx, 1, ERIS_IFU_DETECTOR_SIZE_X, ERIS_IFU_DETECTOR_SIZE_Y));
2742 hdrl_image_copy(imgInSlit,tmpImg, 1, 1));
2744 eris_ifu_free_hdrl_image(&tmpImg);
2748 imgOutSlit = eris_ifu_warp_polynomial_image(imgInSlit,
2751 if (hdrl_image_get_size_x(imgOutSlit) > SLITLET_WIDTH) {
2752 // extract left 64 pixels of slitlet (all data to the right is invalid)
2754 imgOutSlitTrim = hdrl_image_extract(imgOutSlit,
2757 ERIS_IFU_DETECTOR_SIZE_Y));
2759 // if slitlet is less than 64 pix wide, paste it into a slitlet of 64pix width
2760 cpl_msg_warning(cpl_func, "Slitlet #%d: width only %d pix !!!
", slitletNr+1, (int)hdrl_image_get_size_x(imgOutSlit));
2762 imgOutSlitTrim = hdrl_image_new(SLITLET_WIDTH, ERIS_IFU_DETECTOR_SIZE_Y));
2763 // will be aligned to the right side --> better
2764 int offset = SLITLET_WIDTH - (int) hdrl_image_get_size_x(imgOutSlit);
2765 // will be aligned to the left side --> worse
2768 eris_ifu_image_add_slit(imgOutSlitTrim, imgOutSlit, offset));
2774 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
2777 eris_ifu_free_hdrl_image(&imgOutSlit);
2778 eris_ifu_free_hdrl_image(&imgInSlit);
2780 return imgOutSlitTrim;
2783hdrl_image* eris_ifu_dist_warp_image(const hdrl_image *imgIn,
2784 cpl_polynomial **poly_u,
2785 const cpl_table *borders)
2789 cpl_polynomial *poly_v = NULL;
2790 hdrl_image *imgOut = NULL,
2791 *imgOutSlitTrim = NULL;
2793 cpl_ensure(imgIn, CPL_ERROR_NULL_INPUT, NULL);
2794 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2795 cpl_ensure(borders, CPL_ERROR_NULL_INPUT, NULL);
2800 poly_v = cpl_polynomial_new(2));
2801 pows[0] = 0; pows[1] = 0;
2803 cpl_polynomial_set_coeff(poly_v, pows, 0.0));
2804 pows[0] = 0; pows[1] = 1;
2806 cpl_polynomial_set_coeff(poly_v, pows, 1.0));
2809 imgOut = hdrl_image_new(hdrl_image_get_size_x(imgIn),
2810 hdrl_image_get_size_y(imgIn)));
2812 for (int i = 0; i < SLITLET_CNT; i++) {
2813 if (poly_u[i] != NULL) {
2814// cpl_msg_debug(cpl_func, "Warp slitlet #%02d
", i+1);
2816 // Extract, warp and trim slitlet
2817 // (can be parallelized)
2819 imgOutSlitTrim = eris_ifu_dist_warp_slitlet(imgIn,
2822 cpl_table_get_double(borders, ERIS_IFU_POLY_EDGE_L, i, &tmp),
2823 cpl_table_get_double(borders, ERIS_IFU_POLY_EDGE_R, i, &tmp),
2826 // add- in slitlet to synthetic full warped image
2827 // (can be parallelized)
2829 eris_ifu_image_add_slit(imgOut,
2831 eris_ifu_distortion_target_left_edge(i)));
2833 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
2836 } // end: i = SLITLET_CNT
2841 eris_ifu_free_hdrl_image(&imgOut);
2843 eris_ifu_free_polynomial(&poly_v);
2844 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
2857hdrl_image* eris_ifu_dist_warp_bpm(const hdrl_image *bpmIn,
2858 cpl_polynomial **poly_u,
2859 const cpl_table *borders,
2860 productDepthType productDepth)
2864 cpl_polynomial *poly_v = NULL;
2865 hdrl_image *bpmOut = NULL,
2866 *imgOutSlitTrim = NULL;
2868 cpl_ensure(bpmIn, CPL_ERROR_NULL_INPUT, NULL);
2869 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2870 cpl_ensure(borders, CPL_ERROR_NULL_INPUT, NULL);
2872 /* Create contribution map */
2873 cpl_size size_x = hdrl_image_get_size_x(bpmIn);
2874 cpl_size size_y = hdrl_image_get_size_y(bpmIn);
2876 hdrl_image *col_hmap = hdrl_image_new(size_x, size_y);
2878 //Initialize each pixel to its column number; start from 1.
2879 for (cpl_size i = 1; i <= size_x; i++){
2881 col_num.data = i * 1.0;
2882 col_num.error = 0.0;
2883 for (cpl_size j = 1; j <= size_y; j++){
2884 hdrl_image_set_pixel(col_hmap, i, j,col_num);
2887 if (productDepth >= PD_DEBUG) {
2888 eris_ifu_save_hdrl_image_dbg(col_hmap, "eris_ifu_distortion_dbg_col_hmap
", 1, NULL);
2890 poly_v = cpl_polynomial_new(2);
2891 pows[0] = 0; pows[1] = 0;
2892 cpl_polynomial_set_coeff(poly_v, pows, 0.0);
2893 pows[0] = 0; pows[1] = 1;
2894 cpl_polynomial_set_coeff(poly_v, pows, 1.0);
2896 /* Warp the contribution map */
2897 hdrl_image *col_hmap_warped = hdrl_image_new(size_x, size_y);
2898 for (int i = 0; i < SLITLET_CNT; i++) {
2899 // Extract, warp and trim slitlet
2900 imgOutSlitTrim = eris_ifu_dist_warp_slitlet(col_hmap,
2903 cpl_table_get_double(borders, ERIS_IFU_POLY_EDGE_L, i, &tmp),
2904 cpl_table_get_double(borders, ERIS_IFU_POLY_EDGE_R, i, &tmp),
2907 // add-in slitlet to synthetic full warped image
2908 eris_ifu_image_add_slit(col_hmap_warped,
2910 eris_ifu_distortion_target_left_edge(i));
2912 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
2915 hdrl_image_delete(col_hmap);
2917 if (productDepth >= PD_DEBUG) {
2918 eris_ifu_save_hdrl_image_dbg(col_hmap_warped, "eris_ifu_distortion_dbg_col_hmap_warped
", 1, NULL);
2921 /* Interpolate the bpm according to the contribution*/
2922 // TODO: do this on slitlet-wise, do mask columns beyond l_max, r_max.
2923 bpmOut = hdrl_image_new(size_x, size_y);
2925 cpl_size col_n_0 = 0;
2926 /* TODO: AMO: limit the loop to SLITLET_CNT -1 as the last iteration generates infinite loop processing science data */
2927 for (cpl_size k = 0; k < SLITLET_CNT; k++){
2928 if (k + 1 == 1) //slitlet 1
2930 else if (k + 1 == 2)
2932 else if (k + 1== 10)
2935 slitwidth = SLITLET_WIDTH;
2937 for (cpl_size y = 1; y <= size_y; y++){
2938 bool fake_col_n_0 = false;
2939 for (cpl_size x = 1; x <= SLITLET_WIDTH; x++){
2940 if (x >= SLITLET_WIDTH/2) {
2941 // We are already at the right side of the slitlet and don't expect that there will
2942 // be any bad pixels/zero- or NaN-values at the left border.
2943 // But there could still be such bad pixels at the right side. In this case we WILL NOT calculate a fake_col_n_0.
2944 // So we set it to true and we will step over the calculation of it
2945 fake_col_n_0 = true;
2947 hdrl_value pix_contr = hdrl_image_get_pixel(col_hmap_warped, x+k*SLITLET_WIDTH, y, NULL);
2948 cpl_size col_n = (cpl_size) pix_contr.data;
2949 double contri_n = pix_contr.data - col_n;
2950 if (((pix_contr.data == 0) || hdrl_image_is_rejected(col_hmap_warped, x+k*SLITLET_WIDTH, y)) && !fake_col_n_0) {
2952 // try to extrapolate a reasonable col_n_0
2953 // go as log to the right until we get a valid pixel, keep this value
2954 // get the pixel right of this one, subtract and then subtract as often
2956 hdrl_value ggg = hdrl_image_get_pixel(col_hmap_warped, g+k*SLITLET_WIDTH, y, NULL);
2957 while (isnan(ggg.data) || (ggg.data == 0)) {
2959 ggg = hdrl_image_get_pixel(col_hmap_warped, g+k*SLITLET_WIDTH, y, NULL);
2961 // go even one more to the right, because the first difference is smaller than the other differences
2963 ggg = hdrl_image_get_pixel(col_hmap_warped, g+k*SLITLET_WIDTH, y, NULL);
2964 hdrl_value kkk = hdrl_image_get_pixel(col_hmap_warped, (g+1)+k*SLITLET_WIDTH, y, NULL);
2965 double diff = kkk.data - ggg.data;
2966 col_n_0 = ggg.data-(g-1)*diff;
2967 // we had to calculate a fake/estimated col_n_0, set a flag accordingly
2968 fake_col_n_0 = true;
2970 if ((x==1) && !fake_col_n_0)
2973 if ((col_n < 1) || isnan(contri_n))
2975 // either left border
2976 // or pix_contr.data is nan
2979 } else if (col_n > ERIS_IFU_DETECTOR_SIZE_X || col_n-col_n_0+1 > slitwidth+2) //right border or right edge
2983 } else if (col_n == ERIS_IFU_DETECTOR_SIZE_X || col_n-col_n_0+1 == slitwidth+2)
2985 pix_bpm.data = hdrl_image_get_pixel(bpmIn, col_n, y, NULL).data * contri_n + 1.0 * (1.0-contri_n);
2988 pix_bpm.data = hdrl_image_get_pixel(bpmIn, col_n, y, NULL).data * contri_n +
2989 hdrl_image_get_pixel(bpmIn, col_n+1, y, NULL).data * (1.0-contri_n);
2992 hdrl_image_set_pixel(bpmOut, x+k*SLITLET_WIDTH, y, pix_bpm);
2997 hdrl_image_delete(col_hmap_warped);
2999 eris_ifu_free_polynomial(&poly_v);
3016hdrl_imagelist* eris_ifu_stack_warped(const hdrl_image *imgIn,
3019 cpl_ensure(imgIn, CPL_ERROR_NULL_INPUT, NULL);
3022 double *pImgTmpData = NULL,
3024 const double *pImgInData = NULL,
3026 hdrl_image *imgTmp = NULL;
3027 hdrl_imagelist *cube = NULL;
3032 cube = hdrl_imagelist_new());
3035 pImgInData = cpl_image_get_data_double_const(hdrl_image_get_image_const(imgIn)));
3037 pImgInErr = cpl_image_get_data_double_const(hdrl_image_get_error_const(imgIn)));
3040 for (int z = 0; z < ERIS_IFU_DETECTOR_SIZE_Y; z++) {
3041 // a slitlet is 64pix wide, but we have only 32 slitlets
3042 // In order to get a square cube, at the end each slitlet is doubled in y-direction...
3044 imgTmp = hdrl_image_new(SLITLET_WIDTH, SLITLET_CNT));
3046 pImgTmpData = cpl_image_get_data_double(hdrl_image_get_image(imgTmp)));
3048 pImgTmpErr = cpl_image_get_data_double(hdrl_image_get_error(imgTmp)));
3051 for (int y = 0; y < SLITLET_CNT; y++) {
3052 for (int x = 0; x < SLITLET_WIDTH; x++) {
3053 pImgTmpData[x+rowIx[y]*SLITLET_WIDTH] = pImgInData[cnt++];
3057 hdrl_imagelist_set(cube, imgTmp, z));
3063 eris_ifu_free_hdrl_imagelist(&cube);
3077cpl_error_code eris_ifu_dist_warp_stats(const hdrl_image *hdrlWarpedImg,
3078 cpl_propertylist *qc_list,
3079 cpl_propertylist *pl,
3080 cpl_frameset* frameset,
3081 const cpl_parameterlist* parlist)
3083 int nr_values = 21, //odd
3087// ix_middle = nr_values / 2 + 1;
3089 const double *pfit_centers = NULL;
3090 cpl_error_code err = CPL_ERROR_NONE;
3091 cpl_vector *profile_x = NULL,
3092 *est_centers = NULL,
3093 *fit_centers = NULL,
3094 *fit_centers_middle = NULL;
3095 const cpl_image *warpedImg = NULL;
3096 cpl_table **arr = NULL;
3097 cpl_propertylist *pl_my = NULL;
3099 cpl_ensure_code(hdrlWarpedImg, CPL_ERROR_NULL_INPUT);
3100 cpl_ensure_code(qc_list, CPL_ERROR_NULL_INPUT);
3101 cpl_ensure_code(pl, CPL_ERROR_NULL_INPUT);
3102 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
3103 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
3108 arr = cpl_calloc(SLITLET_CNT, sizeof(cpl_table*)));
3111 warpedImg = hdrl_image_get_image_const(hdrlWarpedImg));
3113 // find out number of fibre-tarces per slitlet (one or three)
3114 center_y = ERIS_IFU_DETECTOR_BP_BORDER + ix_middle*height + height/2;
3116 profile_x = eris_ifu_calc_centers_collapse_chunk(
3117 warpedImg, center_y, height));
3118//AA: evtl instead of CPL_FALSE put in (isK & !is25mas)
3120 est_centers = eris_ifu_dist_calc_centers_profile(profile_x, CPL_FALSE));
3121 // will return a vector with 32 or 3*32 center values (errors are catched)
3123 fit_centers_middle = eris_ifu_dist_calc_centers_fit(
3124 profile_x, est_centers, CPL_TRUE));
3125 actual_size = (int) cpl_vector_get_size(est_centers);
3126 eris_ifu_free_vector(&profile_x);
3127 eris_ifu_free_vector(&est_centers);
3129 // create table to hold values
3130 if (actual_size <= SLITLET_CNT) {
3131 for (int i = 0; i < SLITLET_CNT; i++) {
3132 arr[i] = cpl_table_new(nr_values);
3133 cpl_table_new_column(arr[i], "c
", CPL_TYPE_DOUBLE);
3134 cpl_table_new_column(arr[i], "left
", CPL_TYPE_DOUBLE);
3135 cpl_table_new_column(arr[i], "right
", CPL_TYPE_DOUBLE);
3138 for (int i = 0; i < SLITLET_CNT; i++) {
3139 arr[i] = cpl_table_new(nr_values);
3140 cpl_table_new_column(arr[i], "c_l
", CPL_TYPE_DOUBLE);
3141 cpl_table_new_column(arr[i], "c
", CPL_TYPE_DOUBLE);
3142 cpl_table_new_column(arr[i], "c_r
", CPL_TYPE_DOUBLE);
3143 cpl_table_new_column(arr[i], "r_l
", CPL_TYPE_DOUBLE);
3144 cpl_table_new_column(arr[i], "c_l/r_l
", CPL_TYPE_DOUBLE);
3145 cpl_table_new_column(arr[i], "left
", CPL_TYPE_DOUBLE);
3146 cpl_table_new_column(arr[i], "right
", CPL_TYPE_DOUBLE);
3148 cpl_table_new_column(arr[i], "slitlet_tl
", CPL_TYPE_DOUBLE);
3149 cpl_table_new_column(arr[i], "slitlet_tc
", CPL_TYPE_DOUBLE);
3150 cpl_table_new_column(arr[i], "slitlet_tr
", CPL_TYPE_DOUBLE);
3154 // now do the same for the whole detectors in two blocks
3155 // center to top and center to bottom
3156 CHECK_ERROR_STATE();
3157 est_centers = cpl_vector_duplicate(fit_centers_middle);
3158 for (int j = ix_middle; j < nr_values; j++) {
3159 center_y = ERIS_IFU_DETECTOR_BP_BORDER + j*height + height/2;
3160 /* collapse image in y and convert to vector */
3161 profile_x = eris_ifu_calc_centers_collapse_chunk(warpedImg, center_y,
3163 /* do least square fit using a Gaussian in order to get exact centers */
3164 fit_centers = eris_ifu_dist_calc_centers_fit(profile_x, est_centers,
3167 /* copy values into table */
3168 actual_size = (int) cpl_vector_get_size(fit_centers);
3169 pfit_centers = cpl_vector_get_data_const(fit_centers);
3171 if (actual_size == SLITLET_CNT) {
3172 // one trace per slitlet
3173 for (int i = 0; i < actual_size; i++) {
3174 cpl_table_set_double(arr[i], "c
", j, pfit_centers[i]);
3176 cpl_table_set_double(arr[i], "left
", j, (i-1) * swidth);
3177 cpl_table_set_double(arr[i], "left
", j, i * swidth);
3181 // three traces per slitlet
3183 for (int i = 0; i < actual_size; i+=3) {
3184 if (i >= 3*SLITLET_CNT) {
3185 cpl_msg_warning(cpl_func, "Detected more than 96 traces (%d). Please check output!
", actual_size);
3187 cpl_table_set_double(arr[ii], "left
", j, ii * swidth);
3188 cpl_table_set_double(arr[ii], "right
", j, (ii+1) * swidth);
3189 cpl_table_set_double(arr[ii], "c_l
", j, pfit_centers[i+1]-ii * swidth);
3190 cpl_table_set_double(arr[ii], "c
", j, pfit_centers[i+1]);
3191 cpl_table_set_double(arr[ii], "c_r
", j, (ii+1) * swidth - pfit_centers[i+1]);
3192 cpl_table_set_double(arr[ii], "r_l
", j, swidth);
3193 cpl_table_set_double(arr[ii], "c_l/r_l
", j,
3194 (pfit_centers[i+1]-ii * swidth)/swidth);
3196 cpl_table_set_double(arr[ii], "slitlet_tl
", j, pfit_centers[i]);
3197 cpl_table_set_double(arr[ii], "slitlet_tc
", j, pfit_centers[i+1]);
3198 cpl_table_set_double(arr[ii], "slitlet_tr
", j, pfit_centers[i+2]);
3204 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
3205 eris_ifu_free_vector(&profile_x);
3206 eris_ifu_free_vector(&fit_centers);
3209 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers_middle));
3210 for (int j = ix_middle-1; j >= 0; j--) {
3211 center_y = ERIS_IFU_DETECTOR_BP_BORDER + j*height + height/2;
3212 /* collapse image in y and convert to vector */
3214 profile_x = eris_ifu_calc_centers_collapse_chunk(
3215 warpedImg, center_y, height));
3216 /* do least square fit using a Gaussian in order to get exact centers */
3218 fit_centers = eris_ifu_dist_calc_centers_fit(profile_x, est_centers, CPL_FALSE));
3221 pfit_centers = cpl_vector_get_data_const(fit_centers));
3223 /* copy values into table */
3224 if (actual_size == SLITLET_CNT) {
3225 // one trace per slitlet
3226 for (int i = 0; i < actual_size; i++) {
3227 cpl_table_set_double(arr[i], "c
", j, pfit_centers[i]);
3230 // three traces per slitlet
3232 for (int i = 0; i < actual_size; i+=3) {
3233 if (i >= 3*SLITLET_CNT) {
3234 cpl_msg_warning(cpl_func, "Detected more than 96 traces (%d). Please check output!
", actual_size);
3236 cpl_table_set_double(arr[ii], "left
", j, ii * swidth);
3237 cpl_table_set_double(arr[ii], "right
", j, (ii+1) * swidth);
3238 cpl_table_set_double(arr[ii], "c_l
", j, pfit_centers[i+1]-ii * swidth);
3239 cpl_table_set_double(arr[ii], "c
", j, pfit_centers[i+1]);
3240 cpl_table_set_double(arr[ii], "c_r
", j, (ii+1) * swidth - pfit_centers[i+1]);
3241 cpl_table_set_double(arr[ii], "r_l
", j, swidth);
3242 cpl_table_set_double(arr[ii], "c_l/r_l
", j,
3243 (pfit_centers[i+1]-ii * swidth) / swidth);
3246 cpl_table_set_double(arr[ii], "slitlet_tl
", j, pfit_centers[i]);
3247 cpl_table_set_double(arr[ii], "slitlet_tc
", j, pfit_centers[i+1]);
3248 cpl_table_set_double(arr[ii], "slitlet_tr
", j, pfit_centers[i+2]);
3254 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
3255 eris_ifu_free_vector(&profile_x);
3256 eris_ifu_free_vector(&fit_centers);
3264 // Save warped image as final product
3265 cpl_propertylist_append_string(pl, CPL_DFS_PRO_CATG,
3266 ERIS_IFU_PRO_DIST_DBG_WARPED_FIT);
3267 cpl_propertylist_set_string(pl,"PIPEFILE
",
3268 ERIS_IFU_PRO_DIST_QC_WARPED_FIT_FN);
3269 cpl_propertylist_save(pl, ERIS_IFU_PRO_DIST_QC_WARPED_FIT_FN,
3272 eris_setup_product_header(ERIS_IFU_PRO_DIST_QC_WARPED_FIT_FN,
3273 ERIS_IFU_PRO_DIST_DBG_WARPED_FIT, CPL_FRAME_TYPE_TABLE,
3274 "eris_ifu_distortion
", frameset, parlist, pl);
3279 for (int i = 0; i < SLITLET_CNT; i++) {
3282 pl_my = cpl_propertylist_new());
3283 extname = cpl_sprintf("SLITLET%2.2d
",i);
3284 cpl_propertylist_append_string(pl_my,"EXTNAME
",extname);
3285// if (cpl_table_get_ncol(arr[i]) == 1) {
3286 if (actual_size <= SLITLET_CNT) {
3287 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C STDEV
",i);
3288 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "c
"));
3289 keycomm = cpl_sprintf("[pix] center stdev
");
3290 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3295 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C MEDIAN
",i);
3296 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "c
"));
3297 keycomm = cpl_sprintf("[pix] center median
");
3298 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3302 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-L STDEV
",i);
3303 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "r_l
"));
3304 keycomm = cpl_sprintf("[pix] center-left stdev
");
3305 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3309 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-L MEDIAN
",i);
3310 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "r_l
"));
3311 keycomm = cpl_sprintf("[pix] center-left median
");
3312 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3316 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-L STDEV
",i);
3317 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "c_l
"));
3318 keycomm = cpl_sprintf("[pix] center stdev
");
3319 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3323 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-L MEDIAN
",i);
3324 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "c_l
"));
3325 keycomm = cpl_sprintf("[pix] center median
");
3326 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3330 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-C STDEV
",i);
3331 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "c_r
"));
3332 keycomm = cpl_sprintf("[pix] center-right stdev
");
3333 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3337 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TL MEDIAN
",i);
3338 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "slitlet_tl
"));
3339 keycomm = cpl_sprintf("[pix] trace left median
");
3340 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3344 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TL STDEV
",i);
3345 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "slitlet_tl
"));
3346 keycomm = cpl_sprintf("[pix] trace left stdev
");
3347 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3351 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TC MEDIAN
",i);
3352 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "slitlet_tc
"));
3353 keycomm = cpl_sprintf("[pix] trace center median
");
3354 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3358 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TC STDEV
",i);
3359 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "slitlet_tc
"));
3360 keycomm = cpl_sprintf("[pix] trace center stdev
");
3361 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3365 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TR MEDIAN
",i);
3366 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "slitlet_tr
"));
3367 keycomm = cpl_sprintf("[pix] trace right median
");
3368 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3372 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TR STDEV
",i);
3373 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "slitlet_tr
"));
3374 keycomm = cpl_sprintf("[pix] trace right stdev
");
3375 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3379 keyname = cpl_sprintf("ESO QC SLITLET%2.2d CL_RL FRAC
",i);
3380 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "c_l/r_l
"));
3381 keycomm = cpl_sprintf("(center-left)/(right-left) ratio
");
3382 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3386 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-C MEDIAN
",i);
3387 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "c_r
"));
3388 keycomm = cpl_sprintf("[pix] center-right median
");
3389 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3397 cpl_table_save(arr[i], NULL, pl_my,
3398 ERIS_IFU_PRO_DIST_QC_WARPED_FIT_FN,
3400 eris_ifu_free_propertylist(&pl_my);
3407 err = cpl_error_get_code();
3410 for (int i = 0; i < SLITLET_CNT; i++) {
3411 eris_ifu_free_table(&arr[i]);
3413 cpl_free(arr); arr = NULL;
3414 eris_ifu_free_vector(&profile_x);
3415 eris_ifu_free_vector(&est_centers);
3416 eris_ifu_free_vector(&fit_centers);
3417 eris_ifu_free_vector(&fit_centers_middle);
3418 eris_ifu_free_propertylist(&pl_my);
3419 eris_check_error_code("eris_ifu_dist_warp_stats
");
3432cpl_error_code eris_ifu_image_add_slit(hdrl_image *hdrlImgFull,
3433 const hdrl_image *hdrlImgSlit,
3436 cpl_error_code err = CPL_ERROR_NONE;
3437 cpl_image *tmpImgFull = NULL;
3438 const cpl_image *tmpImgSlit = NULL;
3439 cpl_mask *tmpMaskFull = NULL;
3440 const cpl_mask *tmpMaskSlit = NULL;
3441 double *pimgFullData = NULL,
3442 *pimgFullErr = NULL;
3443 const double *pimgSlitData = NULL,
3444 *pimgSlitErr = NULL;
3445 cpl_binary *pimgFullMask = NULL;
3446 const cpl_binary *pimgSlitMask = NULL;
3450 cpl_ensure_code(hdrlImgFull, CPL_ERROR_NULL_INPUT);
3451 cpl_ensure_code(hdrlImgSlit, CPL_ERROR_NULL_INPUT);
3452 cpl_ensure_code(hdrl_image_get_size_y(hdrlImgFull) == ERIS_IFU_DETECTOR_SIZE_Y,
3453 CPL_ERROR_ILLEGAL_INPUT);
3454 cpl_ensure_code(hdrl_image_get_size_y(hdrlImgSlit) == ERIS_IFU_DETECTOR_SIZE_Y,
3455 CPL_ERROR_ILLEGAL_INPUT);
3456 cpl_ensure_code(hdrl_image_get_size_x(hdrlImgFull) >= hdrl_image_get_size_x(hdrlImgSlit),
3457 CPL_ERROR_ILLEGAL_INPUT);
3458 cpl_ensure_code(offset >= 0, CPL_ERROR_ILLEGAL_INPUT);
3462 tmpImgFull = hdrl_image_get_image(hdrlImgFull);
3463 tmpMaskFull = cpl_image_get_bpm(tmpImgFull);
3465 pimgFullData = cpl_image_get_data(tmpImgFull));
3467 pimgFullErr = cpl_image_get_data(hdrl_image_get_error(hdrlImgFull)));
3468 if (tmpMaskFull != NULL) {
3470 pimgFullMask = cpl_mask_get_data(tmpMaskFull));
3472 widthFull = (int) hdrl_image_get_size_x(hdrlImgFull);
3474 tmpImgSlit = hdrl_image_get_image_const(hdrlImgSlit);
3475 tmpMaskSlit = cpl_image_get_bpm_const(tmpImgSlit);
3477 pimgSlitData = cpl_image_get_data_const(tmpImgSlit));
3479 pimgSlitErr = cpl_image_get_data_const(hdrl_image_get_error_const(hdrlImgSlit)));
3480 if (tmpMaskSlit != NULL) {
3482 pimgSlitMask = cpl_mask_get_data_const(tmpMaskSlit));
3485 widthSlit = (int) hdrl_image_get_size_x(hdrlImgSlit);
3487 for (int y = 0; y < ERIS_IFU_DETECTOR_SIZE_Y; y++) {
3488 for (int x = 0; x < widthSlit; x++) {
3489 pimgFullData[x+offset+y*widthFull] = pimgSlitData[x+y*widthSlit];
3490 pimgFullErr[x+offset+y*widthFull] = pimgSlitErr[x+y*widthSlit];
3491 if ((tmpMaskFull != NULL) && (tmpMaskSlit != NULL)) {
3492 pimgFullMask[x+offset+y*widthFull] = pimgSlitMask[x+y*widthSlit];
3500 err = cpl_error_get_code();
3516cpl_table** eris_ifu_dist_calc_slitpos(cpl_image **arcImg,
3517 cpl_table **centers_array,
3518 cpl_table *valid_arc_lines,
3520 cpl_boolean *cut_off_left,
3521 cpl_boolean *cut_off_right,
3522 const cpl_frameset* frameset,
3523 const cpl_parameterlist* parlist)
3525 int max_lines = 200,
3528 urx, ury, llx, lly = 0;
3530 double arc_center = 0.,
3536// *pprofile_y = NULL,
3537 *pleft_edge_tmp = NULL,
3538 *pright_edge_tmp= NULL,
3541 *pright_edge = NULL,
3543 char *extname = NULL;
3544 const char *fn = "eris_ifu_distortion_dbg_slitpos_slit_width.fits
";
3545 const char *fnx = "eris_ifu_distortion_dbg_slitpos_profile_xy.fits
";
3546// cpl_boolean cut_off_fully = CPL_FALSE;
3547 cpl_image *profile_x = NULL;
3549 cpl_table **tbl = NULL,
3550 *valid_arc_lines_slitlet = NULL;
3551 cpl_vector *left_edge_tmp = NULL,
3552 *right_edge_tmp = NULL,
3557 cpl_propertylist *pl_tbl = NULL;
3558 eris_ifu_vector *slit_width = NULL,
3559 *slit_width_rej = NULL,
3561 *right_edge_rej = 0;
3563 cpl_ensure(arcImg, CPL_ERROR_NULL_INPUT, NULL);
3564 cpl_ensure(*centers_array, CPL_ERROR_NULL_INPUT, NULL);
3568 *cut_off_right = FALSE;
3569 *cut_off_right = FALSE;
3572 left_edge_tmp = cpl_vector_new(max_lines));
3574 right_edge_tmp = cpl_vector_new(max_lines));
3576 ypos_tmp = cpl_vector_new(max_lines));
3579 pleft_edge_tmp = cpl_vector_get_data(left_edge_tmp));
3581 pright_edge_tmp = cpl_vector_get_data(right_edge_tmp));
3583 pypos_tmp = cpl_vector_get_data(ypos_tmp));
3585 /* write empty header */
3586 cpl_frameset* fs = (cpl_frameset*) frameset;
3587 char* pipe_id = cpl_sprintf("%s%s%s
", PACKAGE, "/
", PACKAGE_VERSION);
3588 cpl_propertylist *applist = cpl_propertylist_new();
3589 cpl_propertylist_update_string(applist, CPL_DFS_PRO_CATG,
3590 ERIS_IFU_PRO_DIST_SLIT_POS);
3591 cpl_dfs_save_propertylist(fs, NULL, parlist, frameset, NULL,
3592 REC_NAME_DISTORTION, applist, NULL, pipe_id,
3593 ERIS_IFU_PRO_DIST_SLIT_POS_FN);
3594 cpl_propertylist_delete(applist);
3596 CHECK_ERROR_STATE();
3598 // cpl_propertylist_save(pl_tbl, ERIS_IFU_PRO_DIST_SLIT_POS_FN, CPL_IO_CREATE));
3601 tbl = cpl_calloc(SLITLET_CNT, sizeof(cpl_table*)));
3603 if (productDepth & 8) {
3604 eris_ifu_save_image_dbg(NULL, fn, CPL_IO_CREATE, NULL);
3605 eris_ifu_save_image_dbg(NULL, fnx, CPL_IO_CREATE, NULL);
3607 /* loop all slitlets */
3608 for (int i = 0; i < SLITLET_CNT; i++) {
3609 cpl_msg_debug(cpl_func, "i: %d
", i);
3611 // take middle value from "x
"
3612 middle = (int) cpl_table_get_nrow(centers_array[i])/2;
3613 arc_center = cpl_table_get_double(centers_array[i], "x
", middle, &ttt);
3614 CHECK_ERROR_STATE();
3616 if ((productDepth & 3) != 0) {
3617 cpl_msg_debug(cpl_func, " Slitlet #%i: center pos: %g
", i+1,
3621 /* extract list of valid lines */
3622 if (valid_arc_lines != NULL) {
3623 cpl_table_unselect_all(valid_arc_lines);
3624 cpl_table_or_selected_int(valid_arc_lines, ERIS_IFU_FITTABLE_SLITLET, CPL_EQUAL_TO, i);
3625 valid_arc_lines_slitlet = cpl_table_extract_selected(valid_arc_lines);
3627 /* loop all lines (brighter than a tenth of the brightest line)
3628 * in vertical profile and detect edges */
3632// while (y < ERIS_IFU_DETECTOR_SIZE_Y) {
3633 for (int iii = 0; iii < cpl_table_get_nrow(valid_arc_lines_slitlet); iii++) {
3634// AA simplify all this!
3635 y = (int) ( 0.5 + cpl_table_get_double(
3636 valid_arc_lines_slitlet, "x0
", iii, NULL));
3637 arcImgIx = cpl_table_get_int(
3638 valid_arc_lines_slitlet, "imgIdx
", iii, NULL);
3639// if (pprofile_y[y] > cut_level) {
3640 pypos_tmp[nr_lines] = y;
3642 /* create horizontal profile at bright line
3643 * (height ~5pix, width 64 + 15pix left and right) */
3644 llx = (int) (arc_center+0.5) -64/2-25+1,
3645 urx = (int) (arc_center+0.5) +64/2+25+1;
3646//AA check if better for bad Lines
3649 // int half_height = 3 / 2;
3650 half_height = 5 / 2,
3651 lly = y - half_height + 1,
3652 ury = y + half_height + 1;
3653 // y ist the first value, that is above the threshold
3654 //HIER in y gaussfit, evtl am besten entlang llx-urx
3662 profile_x = cpl_image_collapse_window_create(arcImg[arcImgIx],
3667// // identify actual ypos in valid_lines2
3668// int valid_line = 0;
3671// } else if (b > 0){
3675// // get leftmost and rightmost column of this slitlet
3676// cpl_table_unselect_all(valid_arc_lines_slitlet);
3677// cpl_table_or_selected_int(valid_arc_lines_slitlet, ERIS_IFU_FITTABLE_POSITION, CPL_EQUAL_TO, valid_line);
3684// // get the according y-values
3686// // create a line accross the detector from llx to urx
3688// // create a profile in a way that +/-3or5 pix vertically around the line are averaged and put into profile_x
3691 cpl_error_code status = eris_ifu_slitpos_gauss(
3693 &(pleft_edge_tmp[nr_lines]),
3694 &(pright_edge_tmp[nr_lines]),
3697 if (status == CPL_ERROR_EOL) {
3701 pleft_edge_tmp[nr_lines] -= 1.;
3702 pright_edge_tmp[nr_lines] -= 1.;
3704 if (productDepth & 8) {
3705 cpl_propertylist *pl_line = NULL;
3707 pl_line = cpl_propertylist_new());
3708 extname = cpl_sprintf("Sx_%02d Lx_%02d
", i+1, nr_lines+1);
3709 cpl_propertylist_append_string(pl_line, "EXTNAME
", extname);
3710 eris_ifu_free_string(&extname);
3711 cpl_propertylist_append_double(pl_line, "lineypos
", y);
3712 cpl_propertylist_append_double(pl_line, "llx
", llx);
3713 cpl_propertylist_append_double(pl_line, "lly
", lly);
3714 cpl_propertylist_append_double(pl_line, "urx
", urx);
3715 cpl_propertylist_append_double(pl_line, "ury
", ury);
3716 cpl_propertylist_append_double(pl_line, "edge_l
", pleft_edge_tmp[nr_lines]);
3717 cpl_propertylist_append_double(pl_line, "edge_r
", pright_edge_tmp[nr_lines]);
3718 eris_ifu_save_image_dbg(profile_x, fnx, CPL_IO_EXTEND, pl_line);
3719 eris_ifu_free_propertylist(&pl_line);
3721 eris_ifu_free_image(&profile_x);
3723 if (status == CPL_ERROR_EOL) {
3725 } else if (status != CPL_ERROR_NONE) {
3726 ERIS_IFU_TRY_EXIT();
3729 if (nr_lines >= max_lines) {
3730 SET_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
3731 "more than 100 lines detected!
");
3733 // double est_pos = pleft_edge[nr_lines] + (pright_edge[nr_lines]-pleft_edge[nr_lines])/2.0;
3734 // cpl_msg_debug(cpl_func, " left_pos: %g, right_pos: %g
", pleft_edge[nr_lines], pright_edge[nr_lines]);
3735 // cpl_msg_debug(cpl_func, " est. pos: %g
", est_pos);
3736 // // this is the eff. offset from slitlet center to fibre-center
3737 // cpl_msg_debug(cpl_func, " diff: %g
", arc_center-est_pos);
3739 eris_ifu_free_image(&profile_x);
3741 // get off surroundings of already processed line
3745 if (nr_lines >= max_lines) {
3746 SET_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
3747 "more than 100 lines detected!
");
3751// } // end: if detected line
3755 eris_ifu_free_table(&valid_arc_lines_slitlet);
3757 /* cut vectors to their correct length */
3759 left_edge = cpl_vector_extract(left_edge_tmp, 0, nr_lines-1, 1));
3761 right_edge = cpl_vector_extract(right_edge_tmp, 0, nr_lines-1, 1));
3763 ypos = cpl_vector_extract(ypos_tmp, 0, nr_lines-1, 1));
3765 pleft_edge = cpl_vector_get_data(left_edge));
3767 pright_edge = cpl_vector_get_data(right_edge));
3769 pypos = cpl_vector_get_data(ypos));
3771 slit_width = eris_ifu_vector_new(nr_lines);
3772 for (int ty = 0; ty < nr_lines; ty++) {
3773 eris_ifu_vector_set(slit_width, ty, pright_edge[ty]-pleft_edge[ty]);
3777 * omit outliers in a multi process step
3780 pl_tbl = cpl_propertylist_new());
3782 /* status before rejecting */
3783 median = eris_ifu_vector_get_median(slit_width, ERIS_IFU_ARITHMETIC);
3784 stddev = eris_ifu_vector_get_stdev_median(slit_width);
3785 CHECK_ERROR_STATE();
3787 cpl_propertylist_append_double(pl_tbl, "bef_med
", median));
3789 cpl_propertylist_append_double(pl_tbl, "bef_sdv
", stddev));
3790 cpl_msg_debug(cpl_func, "before: median: %g, stddev: %g
", median, stddev);
3791 if (productDepth & 8) {
3792 cpl_propertylist *pl = NULL;
3794 pl = cpl_propertylist_new());
3795 extname = cpl_sprintf("Sx_%02d ypos
", i+1);
3796 cpl_propertylist_append_string(pl, "EXTNAME
", extname);
3797 eris_ifu_free_string(&extname);
3799 eris_ifu_save_vector_dbg(ypos, fn, CPL_IO_EXTEND, pl));
3800 extname = cpl_sprintf("Sx_%02d left_edge
", i+1);
3801 cpl_propertylist_append_string(pl, "EXTNAME
", extname);
3802 eris_ifu_free_string(&extname);
3804 eris_ifu_save_vector_dbg(left_edge, fn, CPL_IO_EXTEND, pl));
3805 extname = cpl_sprintf("Sx_%02d right_edge
", i+1);
3806 cpl_propertylist_append_string(pl, "EXTNAME
", extname);
3807 eris_ifu_free_string(&extname);
3809 eris_ifu_save_vector_dbg(right_edge, fn, CPL_IO_EXTEND, pl));
3810 extname = cpl_sprintf("Sx_%02d slit_width
", i+1);
3811 cpl_propertylist_append_string(pl_tbl, "EXTNAME
", extname);
3812 eris_ifu_free_string(&extname);
3814 eris_ifu_vector_save(slit_width, fn, CPL_TYPE_DOUBLE,
3815 pl_tbl, CPL_IO_EXTEND, 70));
3816 eris_ifu_free_propertylist(&pl);
3820 left_edge_rej = eris_ifu_vector_create(left_edge));
3822 right_edge_rej = eris_ifu_vector_create(right_edge));
3824 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
3826 if ((median < 58) && (stddev > 3) &&
3827 ((i == 0) || (i == SLITLET_CNT-1)))
3829 // median is obviously so wrong, that many values indicate that slitlet is cut off!
3830 // reject values < SLITLET_WIDTH-stddev
3831 for (int ty = 0; ty < nr_lines; ty++) {
3832 double val = eris_ifu_vector_get(slit_width_rej, ty);
3833 if (val < SLITLET_WIDTH-stddev) {
3834 eris_ifu_vector_reject(slit_width_rej, ty);
3835 eris_ifu_vector_reject(left_edge_rej, ty);
3836 eris_ifu_vector_reject(right_edge_rej, ty);
3839if (eris_ifu_vector_count_non_rejected(slit_width_rej) <= 1) {
3840// cut_off_fully = CPL_TRUE;
3841 eris_ifu_free_ifu_vector(&left_edge_rej);
3842 eris_ifu_free_ifu_vector(&right_edge_rej);
3843 eris_ifu_free_ifu_vector(&slit_width_rej);
3845 left_edge_rej = eris_ifu_vector_create(left_edge));
3847 right_edge_rej = eris_ifu_vector_create(right_edge));
3849 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
3851 median = eris_ifu_vector_get_median(slit_width_rej, ERIS_IFU_ARITHMETIC);
3852 stddev = eris_ifu_vector_get_stdev_median(slit_width_rej);
3853 CHECK_ERROR_STATE();
3856 cpl_propertylist_append_double(pl_tbl, "med_rej1
", median));
3858 cpl_propertylist_append_double(pl_tbl, "sdv_rej1
", stddev));
3859 cpl_msg_debug(cpl_func, "median: %g, stddev: %g
", median, stddev);
3860 if (productDepth & 8) {
3861 extname = cpl_sprintf("Sx_%02d slit_width_rej
", i+1);
3862 cpl_propertylist_append_string(pl_tbl, "EXTNAME
", extname);
3863 eris_ifu_free_string(&extname);
3865 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl, CPL_IO_EXTEND, 70));
3869 *cut_off_left = CPL_TRUE;
3871 cpl_propertylist_append_string(pl_tbl, "cutoff
", "left
"));
3873 if (i == SLITLET_CNT-1) {
3874 *cut_off_right = CPL_TRUE;
3876 cpl_propertylist_append_string(pl_tbl, "cutoff
", "right
"));
3880 /* omit outliers devying more than 2% (15% for problematic slitlet #16)*/
3882 if (i == 15 || i == 17) {
3885 for (int ty = 0; ty < nr_lines; ty++) {
3886 double val = eris_ifu_vector_get(slit_width_rej, ty);
3887 if ((val > median*percentage) || (val < median/percentage)) {
3888 eris_ifu_vector_reject(slit_width_rej, ty);
3889 eris_ifu_vector_reject(left_edge_rej, ty);
3890 eris_ifu_vector_reject(right_edge_rej, ty);
3894 median = eris_ifu_vector_get_median(slit_width_rej, ERIS_IFU_ARITHMETIC);
3896 cpl_propertylist_append_double(pl_tbl, "aft_med
", median));
3897 if (eris_ifu_vector_count_non_rejected(slit_width_rej) >= 3) {
3898 stddev = eris_ifu_vector_get_stdev_median(slit_width_rej);
3900 cpl_propertylist_append_double(pl_tbl, "aft_sdv
", stddev));
3902 CHECK_ERROR_STATE();
3903 cpl_msg_debug(cpl_func, "after: median: %g, stddev: %g
", median, stddev);
3904 if (productDepth & 8) {
3905 extname = cpl_sprintf("Sx_%02d slit_width_rej2
", i+1);
3906 cpl_propertylist_append_string(pl_tbl, "EXTNAME
", extname);
3907 eris_ifu_free_string(&extname);
3909 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl, CPL_IO_EXTEND, 70));
3913 * check if first or last slitlet is off detector (partially cut off)
3916 if ((i == 0) && ((*cut_off_left == CPL_TRUE) ||
3917 (eris_ifu_vector_get_min(left_edge_rej, NULL) < ERIS_IFU_DETECTOR_BP_BORDER)))
3919 *cut_off_left = CPL_TRUE;
3920 if (!cpl_propertylist_has(pl_tbl, "cutoff
")) {
3922 cpl_propertylist_append_string(pl_tbl, "cutoff
", "left
"));
3926 eris_ifu_free_ifu_vector(&slit_width_rej);
3928 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
3930 eris_ifu_vector *x = NULL;
3931 x = eris_ifu_vector_duplicate(slit_width_rej);
3932 for (int j = 0; j < nr_lines; j++) {
3933 eris_ifu_vector_set(x, j, j+1);
3935 cpl_vector *fff = eris_ifu_polyfit_edge(x, slit_width_rej, 1);
3936 eris_ifu_free_ifu_vector(&x);
3938 double fp0 = cpl_vector_get(fff, 0),
3939 fp1 = cpl_vector_get(fff, 1);
3940 eris_ifu_free_vector(&fff);
3941 stddev = eris_ifu_vector_get_stdev_median(slit_width_rej);
3942 for (int ty = 0; ty < nr_lines; ty++) {
3943 double val = eris_ifu_vector_get(slit_width_rej, ty);
3944 double val_calc = fp0+fp1*(ty+1);
3945 if (fabs(val - val_calc) > stddev*0.7) { // stddev is a bit too high
3946 eris_ifu_vector_reject(slit_width_rej, ty);
3949 if (productDepth & 8) {
3950 extname = cpl_sprintf("Sx_%02d slit_width_rej3
", i+1);
3951 cpl_propertylist_append_string(pl_tbl, "EXTNAME
", extname);
3952 eris_ifu_free_string(&extname);
3954 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl,
3955 CPL_IO_EXTEND, 70));
3957 } // if left_edge cut off
3959 if ((i == SLITLET_CNT-1) && ((*cut_off_right == CPL_TRUE) ||
3960 (eris_ifu_vector_get_max(right_edge_rej, NULL) > ERIS_IFU_DETECTOR_SIZE_X-ERIS_IFU_DETECTOR_BP_BORDER)))
3962 *cut_off_right = TRUE;
3963 if (!cpl_propertylist_has(pl_tbl, "cutoff
")) {
3965 cpl_propertylist_append_string(pl_tbl, "cutoff
", "right
"));
3969 eris_ifu_free_ifu_vector(&slit_width_rej);
3971 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
3973 eris_ifu_vector *x = NULL;
3974 x = eris_ifu_vector_duplicate(slit_width_rej);
3975 for (int j = 0; j < nr_lines; j++) {
3976 eris_ifu_vector_set(x, j, j+1);
3978 cpl_vector *fff = eris_ifu_polyfit_edge(x, slit_width_rej, 1);
3979 eris_ifu_free_ifu_vector(&x);
3981 double fp0 = cpl_vector_get(fff, 0),
3982 fp1 = cpl_vector_get(fff, 1);
3983 eris_ifu_free_vector(&fff);
3984 stddev = eris_ifu_vector_get_stdev_median(slit_width_rej);
3985 CHECK_ERROR_STATE();
3986 for (int ty = 0; ty < nr_lines; ty++) {
3987 double val = eris_ifu_vector_get(slit_width_rej, ty);
3988 double val_calc = fp0+fp1*(ty+1);
3989 if (fabs(val - val_calc) > stddev*0.7) { // stddev is a bit too high
3991 eris_ifu_vector_reject(slit_width_rej, ty));
3994 if (productDepth & 8) {
3995 extname = cpl_sprintf("Sx_%02d slit_width_rej4
", i+1);
3996 cpl_propertylist_append_string(pl_tbl, "EXTNAME
", extname);
3997 eris_ifu_free_string(&extname);
3999 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl,
4000 CPL_IO_EXTEND, 70));
4002 } // if right_edge cut off
4004 eris_ifu_free_ifu_vector(&left_edge_rej);
4005 eris_ifu_free_ifu_vector(&right_edge_rej);
4006 CHECK_ERROR_STATE();
4008 /* setup table to save */
4010 tbl[i] = cpl_table_new(eris_ifu_vector_count_non_rejected(slit_width_rej)));
4012 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_EDGE_L, CPL_TYPE_DOUBLE));
4014 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_EDGE_R, CPL_TYPE_DOUBLE));
4016 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_SLIT, CPL_TYPE_DOUBLE));
4018 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_YPOS, CPL_TYPE_DOUBLE));
4020 // copy vectors to table
4022 for (int ty = 0; ty < cpl_vector_get_size(ypos); ty++) {
4023 if (!eris_ifu_vector_is_rejected(slit_width_rej, ty)) {
4024 // add to table only if line hasn't been rejected
4026 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_YPOS, cnt, pypos[ty]));
4028 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_L, cnt, pleft_edge[ty]));
4030 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_R, cnt, pright_edge[ty]));
4032 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_SLIT, cnt, eris_ifu_vector_get(slit_width_rej, ty)));
4034 if ((i == 0) && (*cut_off_left == TRUE)) {
4035 // set invalid values to nan on left side
4036 if (pleft_edge[ty] < ERIS_IFU_DETECTOR_BP_BORDER) {
4038 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_L, cnt, NAN));
4040 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_SLIT, cnt, pright_edge[ty]-ERIS_IFU_DETECTOR_BP_BORDER));
4043 if ((i == SLITLET_CNT-1) && (*cut_off_right == TRUE)) {
4044 // set invalid values to nan on right side
4045 if (pright_edge[ty] > ERIS_IFU_DETECTOR_SIZE_X-ERIS_IFU_DETECTOR_BP_BORDER) {
4047 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_R, cnt, NAN));
4049 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_SLIT, cnt, ERIS_IFU_DETECTOR_SIZE_X - ERIS_IFU_DETECTOR_BP_BORDER - pleft_edge[ty]));
4057 extname = cpl_sprintf("Sx_%02d
", i+1);
4058 cpl_propertylist_append_string(pl_tbl, "EXTNAME
", extname);
4059 eris_ifu_free_string(&extname);
4061 cpl_table_save(tbl[i], NULL, pl_tbl, ERIS_IFU_PRO_DIST_SLIT_POS_FN, CPL_IO_EXTEND));
4063 eris_ifu_free_propertylist(&pl_tbl);
4064 eris_ifu_free_ifu_vector(&slit_width);
4065 eris_ifu_free_ifu_vector(&slit_width_rej);
4066 eris_ifu_free_vector(&left_edge);
4067 eris_ifu_free_vector(&right_edge);
4068 eris_ifu_free_vector(&ypos);
4069 } // end: for i = SLITLET_CNT
4075 eris_ifu_free_image(&profile_x);
4076 for (int i = 0; i < SLITLET_CNT; i++) {
4077 eris_ifu_free_table(&tbl[i]);
4079 cpl_free(tbl); tbl = NULL;
4082 eris_ifu_free_vector(&left_edge_tmp);
4083 eris_ifu_free_vector(&right_edge_tmp);
4084 eris_ifu_free_vector(&ypos_tmp);
4085 eris_ifu_free_vector(&left_edge);
4086 eris_ifu_free_vector(&right_edge);
4087 eris_ifu_free_vector(&ypos);
4088 eris_ifu_free_propertylist(&pl_tbl);
4089 eris_ifu_free_ifu_vector(&left_edge_rej);
4090 eris_ifu_free_ifu_vector(&right_edge_rej);
4119cpl_error_code eris_ifu_fit_gauss(const cpl_vector *x,
4120 const cpl_vector *y,
4126 cpl_error_code ret_error = CPL_ERROR_NONE,
4127 fit_error = CPL_ERROR_NONE;
4130 cpl_ensure_code(x, CPL_ERROR_NULL_INPUT);
4131 cpl_ensure_code(y, CPL_ERROR_NULL_INPUT);
4132 cpl_ensure_code(x0, CPL_ERROR_NULL_INPUT);
4133 cpl_ensure_code(area, CPL_ERROR_NULL_INPUT);
4134 cpl_ensure_code(sigma, CPL_ERROR_NULL_INPUT);
4135 cpl_ensure_code(offset, CPL_ERROR_NULL_INPUT);
4144 fit_error = cpl_vector_fit_gaussian(x, NULL, y, NULL,
4152// cpl_msg_debug(cpl_func, " --- 1st FIT ---------------------
"
4154// cpl_msg_debug(cpl_func, " center: %g (sigma: %g, area: %g,
"
4155// " offset: %g)
", *x0, *sigma, *area, *offset);
4157 // this happens only once in obscure test data...
4158 if ((fit_error == CPL_ERROR_NONE) &&
4159 (cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX))
4162 fit_error = CPL_ERROR_CONTINUE;
4165 if (fit_error == CPL_ERROR_CONTINUE) {
4166 // if first fit doesn't convert, try it again with fixed
4167 // area- and sigma-parameter
4170 fit_error = cpl_vector_fit_gaussian(x, NULL, y, NULL,
4171 CPL_FIT_CENTROID | CPL_FIT_OFFSET,
4178// cpl_msg_debug(cpl_func, " --- 2nd FIT -----------------
"
4179// "-----------------
");
4180// cpl_msg_debug(cpl_func, " center: %g (sigma: %g,
"
4181// "area: %g, offset: %g)
",
4182// *x0, *sigma, *area, *offset);
4184 if (fit_error == CPL_ERROR_CONTINUE) {
4185 // if it didn't convert again, give up and take the
4190 CHECK_ERROR_STATE();
4194 ret_error = cpl_error_get_code();
4205/*----------------------------------------------------------------------------*/
4226/*----------------------------------------------------------------------------*/
4227cpl_vector* eris_ifu_polyfit_edge(const eris_ifu_vector *x,
4228 const eris_ifu_vector *y,
4231 eris_ifu_vector *x_dup = NULL,
4234 cpl_vector *fit_par = NULL,
4237 double *pfit_par = NULL,
4250 cpl_ensure(x, CPL_ERROR_NULL_INPUT, NULL);
4251 cpl_ensure(y, CPL_ERROR_NULL_INPUT, NULL);
4252 cpl_ensure(fit_order >= 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
4253 cpl_ensure(cpl_vector_get_size(x->data) == cpl_vector_get_size(y->data), CPL_ERROR_ILLEGAL_INPUT, NULL);
4257 // assert that rejected values in x are also rejected in y and vice versa
4259 x_dup = eris_ifu_vector_duplicate(x));
4261 y_dup = eris_ifu_vector_duplicate(y));
4263 eris_ifu_vector_adapt_rejected(x_dup, y_dup));
4265 size = (int) cpl_vector_get_size(x_dup->data);
4268 pxdata = cpl_vector_get_data(x_dup->data));
4270 pxmask = cpl_vector_get_data(x_dup->mask));
4272 pymask = cpl_vector_get_data(y_dup->mask));
4275 fit_vec = eris_ifu_vector_new(size));
4277 pfdata = cpl_vector_get_data(fit_vec->data));
4279 pfmask = cpl_vector_get_data(fit_vec->mask));
4282 for (i = 0; i < iter; i++)
4284 cpl_vector_delete(fit_par); fit_par = NULL;
4288 x_good = eris_ifu_vector_create_non_rejected(x_dup));
4290 y_good = eris_ifu_vector_create_non_rejected(y_dup));
4293 fit_par = eris_ifu_polyfit_1d(x_good, y_good, fit_order));
4295 pfit_par = cpl_vector_get_data(fit_par));
4297 eris_ifu_free_vector(&x_good);
4298 eris_ifu_free_vector(&y_good);
4300 // create fitted vector
4301 for (j = 0; j < size; j++) {
4302 if (eris_ifu_vector_is_rejected(x_dup, j)) {
4304 eris_ifu_vector_reject(fit_vec, j));
4306 double fit_val = -pfit_par[0];
4307 if (fit_order >= 1) {
4308 fit_val -= pfit_par[1] * pxdata[j];
4310 if (fit_order >= 2) {
4311 fit_val -= pfit_par[2] * pow(pxdata[j], 2);
4313 if (fit_order >= 3) {
4314 fit_val -= pfit_par[3] * pow(pxdata[j], 3);
4318 eris_ifu_vector_set(fit_vec, j, fit_val));
4322 // fit_vec = y_good - fit_vec
4324 eris_ifu_vector_add(fit_vec, y_dup));
4326 median = eris_ifu_vector_get_median(fit_vec, ERIS_IFU_ARITHMETIC);
4327 stddev = eris_ifu_vector_get_stdev(fit_vec);
4328 CHECK_ERROR_STATE();
4331 eris_ifu_vector_abs(fit_vec));
4333 // clip values larger than median + 5 * stddev
4334 double clip_val = median + 5 * stddev;
4335 for (j = 0; j < size; j++) {
4336 if ((pfmask[j] >= 0.5) && (pfdata[j] > clip_val)) {
4347 eris_ifu_free_vector(&fit_par);
4350 eris_ifu_free_ifu_vector(&fit_vec);
4351 eris_ifu_free_ifu_vector(&x_dup);
4352 eris_ifu_free_ifu_vector(&y_dup);
4353 eris_ifu_free_vector(&x_good);
4354 eris_ifu_free_vector(&y_good);
4359#include "eris_ifu_wavecal_static.h
"
4361cpl_error_code eris_ifu_wavecal_processSof_dist(
4362 cpl_frameset* frames,
4363 int exposureCorrectionMode,
4365 hdrl_imagelist **arcImages,
4368 ifsPreopticsScale *scale,
4369 ifsInstrument *instrument,
4370 double saturation_threhold,
4374 cpl_frame *frame = NULL;
4378 if (frames == NULL) {
4379 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
4380 "missing frameset
");
4382 if (cpl_frameset_is_empty(frames)) {
4383 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
4384 "SOF file is empty or missing
");
4386 CHECK_ERROR_STATE();
4388//AA only change: ERIS_IFU_RAW_WAVE_NS instead of ERIS_IFU_RAW_WAVE_LAMP
4389 // get arc lamp image
4390 cpl_frameset *arcFrames = NULL;
4391 if (cpl_frameset_count_tags(frames, ERIS_IFU_RAW_WAVE_NS) > 0) {
4392 arcFrames = eris_ifu_get_frameset_by_tag(frames, ERIS_IFU_RAW_WAVE_NS);
4393 } else if ( (cpl_frameset_count_tags(frames, ERIS_IFU_RAW_WAVE_NS_ON) > 0) &&
4394 (cpl_frameset_count_tags(frames, ERIS_IFU_RAW_WAVE_NS_OFF) > 0) ) {
4395 cpl_frameset *arcFrames_off = NULL;
4396 arcFrames = eris_ifu_get_frameset_by_tag(frames, ERIS_IFU_RAW_WAVE_NS_ON);
4398 arcFrames_off = eris_ifu_get_frameset_by_tag(frames, ERIS_IFU_RAW_WAVE_NS_OFF);
4400 cpl_frameset_join(arcFrames, arcFrames_off);
4402 cpl_frameset_delete(arcFrames_off);
4405 eris_ifu_wave_get_arc_images(arcFrames,
4406 exposureCorrectionMode,
4413 saturation_threhold,
4415 cpl_frameset_delete(arcFrames);
4417 // get reference lines
4418 frame = cpl_frameset_find(frames, ERIS_IFU_CALIB_REF_LINES);
4419 CHECK_ERROR_STATE();
4420 if (frame == NULL) {
4421 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
4422 "missing \
"%s\" tag in the SOF, arc lamp reference lines",
4423 ERIS_IFU_CALIB_REF_LINES);
4430 return cpl_error_get_code();
4439cpl_error_code eris_ifu_distortion_reduce_lines(cpl_table *tbl,
4443 cpl_error_code err = CPL_ERROR_NONE;
4444 int cut_level_area = 0,
4445 cut_level_intensity = 0;
4446 const char *bandStr = NULL;
4448 cpl_ensure_code(tbl != NULL, CPL_ERROR_NULL_INPUT);
4462 cpl_table *tSlit = NULL,
4465 cpl_msg_debug(cpl_func,
"Removing bad lines");
4466 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4467cpl_msg_debug(cpl_func,
" sIdx: %d", sIdx);
4470 if (
'J' == bandStr[0]) {
4472 cut_level_area = 1000;
4473 cut_level_intensity = 600;
4475 cut_level_area = 90;
4476 cut_level_intensity = 30;
4478 }
else if (
'H' == bandStr[0]) {
4480 cut_level_area = 300;
4481 cut_level_intensity = 150;
4483 cut_level_area = 300/10;
4484 cut_level_intensity = 150/10;
4486 }
else if (
'K' == bandStr[0]) {
4488 cut_level_area = 200;
4489 cut_level_intensity = 100;
4491 cut_level_area = 200/10;
4492 cut_level_intensity = 100/10;
4495 SET_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
"Band must be H, K or J");
4498 cpl_table_unselect_all(tbl);
4499 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4500 cpl_table_and_selected_double(tbl,
"area", CPL_LESS_THAN, cut_level_area);
4501 cpl_table_erase_selected(tbl);
4503 cpl_table_unselect_all(tbl);
4504 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4505 cpl_table_and_selected_double(tbl,
"intensity", CPL_LESS_THAN, cut_level_intensity);
4506 cpl_table_erase_selected(tbl);
4509 cpl_table_unselect_all(tbl);
4510 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4513 tSlit = cpl_table_extract_selected(tbl));
4516 int index_first = cpl_table_get_int(tSlit,
"index", 0, NULL);
4517 cpl_table_unselect_all(tSlit);
4518 cpl_table_or_selected_int(tSlit,
"index", CPL_EQUAL_TO, index_first);
4521 tCol = cpl_table_extract_selected(tSlit));
4525 for (
int i = 0; i < cpl_table_get_nrow(tCol); i++) {
4527 int pos = cpl_table_get_int(tCol,
"position", i, NULL);
4528 cpl_table_unselect_all(tSlit);
4529 cpl_table_or_selected_int(tSlit,
"position", CPL_EQUAL_TO, pos);
4532 tPos = cpl_table_extract_selected(tSlit));
4534 if (cpl_table_get_nrow(tPos) == nr_cols) {
4535 for (
int j = 0; j < cpl_table_get_nrow(tPos); j++) {
4536 int code = cpl_table_get_int(tPos,
"errorcode", j, NULL);
4543 if (good < cpl_table_get_nrow(tPos)/2) {
4545 cpl_table_unselect_all(tbl);
4546 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4547 cpl_table_and_selected_int(tbl,
"position", CPL_EQUAL_TO, pos);
4548 cpl_table_erase_selected(tbl);
4557 cpl_table_unselect_all(tbl);
4558 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4561 tSlit = cpl_table_extract_selected(tbl));
4563 cpl_table_unselect_all(tSlit);
4564 cpl_table_or_selected_int(tSlit,
"errorcode", CPL_NOT_EQUAL_TO, 0);
4567 tPos = cpl_table_extract_selected(tSlit));
4569 for (
int i = 0; i < cpl_table_get_nrow(tPos); i++) {
4570 cpl_table_unselect_all(tSlit);
4571 int pos_bad = cpl_table_get_int(tPos,
"position", i, NULL);
4572 cpl_table_or_selected_int(tSlit,
"position", CPL_EQUAL_TO, pos_bad);
4573 if (cpl_table_count_selected(tSlit) == 1) {
4574 cpl_table_unselect_all(tbl);
4575 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4576 cpl_table_and_selected_int(tbl,
"position", CPL_EQUAL_TO, pos_bad);
4577 cpl_table_erase_selected(tbl);
4618 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4620 cpl_table_unselect_all(tbl);
4621 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4624 tSlit = cpl_table_extract_selected(tbl));
4627 int index_first = cpl_table_get_int(tSlit,
"index", 0, NULL);
4628 cpl_table_and_selected_int(tbl,
"index", CPL_NOT_EQUAL_TO, index_first+nr_cols/2);
4629 cpl_table_erase_selected(tbl);
4637 cpl_table_unselect_all(tbl);
4638 cpl_table_or_selected_int(tbl,
"errorcode", CPL_NOT_EQUAL_TO, 0);
4639 cpl_table_erase_selected(tbl);
4644 cpl_table_erase_column(tbl,
"imgIdx");
4651 cpl_table_erase_column(tbl,
"mse");
4652 cpl_table_erase_column(tbl,
"wavelengthFit");
4653 cpl_table_erase_column(tbl,
"wavelengthError");
4654 cpl_table_erase_column(tbl,
"range");
4655 cpl_table_erase_column(tbl,
"xdata");
4656 cpl_table_erase_column(tbl,
"ydata");
4672cpl_error_code eris_ifu_distortion_reduce_identical_lines(cpl_table *tbl)
4674 cpl_error_code err = CPL_ERROR_NONE;
4675 cpl_table *tSlit = NULL;
4679 cpl_msg_debug(cpl_func,
"Removing identical/overlapping lines");
4680 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4681 cpl_msg_debug(cpl_func,
" sIdx: %d", sIdx);
4684 cpl_table_unselect_all(tbl);
4685 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4688 tSlit = cpl_table_extract_selected(tbl));
4690 for (
int i = 0; i < cpl_table_get_nrow(tSlit)-1; i++) {
4691 double wl1 = cpl_table_get_double(tSlit,
"wavelength", i+1, NULL),
4692 wl2 = cpl_table_get_double(tSlit,
"wavelength", i, NULL);
4694 if (wl1-wl2 < 0.001) {
4695 cpl_msg_debug(cpl_func,
"Remove:");
4696 cpl_msg_debug(cpl_func,
" wl: %g, x0: %g, sigma: %g, area: %g, offset: %g", wl1, cpl_table_get_double(tSlit,
"x0", i+1, NULL), cpl_table_get_double(tSlit,
"sigma", i+1, NULL), cpl_table_get_double(tSlit,
"area", i+1, NULL), cpl_table_get_double(tSlit,
"offset", i+1, NULL));
4697 cpl_msg_debug(cpl_func,
" wl: %g, x0: %g, sigma: %g, area: %g, offset: %g", wl2, cpl_table_get_double(tSlit,
"x0", i, NULL), cpl_table_get_double(tSlit,
"sigma", i, NULL), cpl_table_get_double(tSlit,
"area", i, NULL), cpl_table_get_double(tSlit,
"offset", i, NULL));
4699 int pos1 = cpl_table_get_int(tSlit,
"position", i+1, NULL),
4700 pos2 = cpl_table_get_int(tSlit,
"position", i, NULL);
4702 cpl_table_and_selected_int(tbl,
"position", CPL_EQUAL_TO, pos1);
4703 cpl_table_erase_selected(tbl);
4705 cpl_table_unselect_all(tbl);
4706 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4707 cpl_table_and_selected_int(tbl,
"position", CPL_EQUAL_TO, pos2);
4708 cpl_table_erase_selected(tbl);
4734cpl_table* eris_ifu_dist_wave(cpl_frameset *fs,
4735 cpl_table **centers_fitted,
4737 cpl_image ***arcImgs,
4739 const cpl_parameterlist* parlist,
4743 int corrMask = LINE_EXPOSURE_CORRECTION | COLUMN_EXPOSURE_CORRECTION,
4749 ifsBand band = UNDEFINED_BAND;
4750 ifsPreopticsScale scale = UNDEFINED_SCALE;
4751 ifsInstrument instrument = UNSET_INSTRUMENT;
4752 cpl_image **dataImg = NULL;
4753 const hdrl_image *tmpImg = NULL;
4754 hdrl_imagelist *arcImages = NULL;
4755 cpl_image **collapsedImgDetOrder = NULL;
4756 cpl_propertylist *pl = NULL;
4757 cpl_image **collapsedSpectra = NULL;
4758 cpl_vector *collapsedSpectrum = NULL,
4760 cpl_bivector **refLines = NULL;
4761 const char *refLineTableFileName = NULL,
4762 *firstFitTableFileName = NULL,
4763 *waveSetupFileName = NULL;
4764 cpl_table *firstFitTable = NULL;
4765 cpl_polynomial *firstFit = NULL;
4766 cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y];
4767 struct waveTablesStruct tables;
4768 struct waveSetupStruct waveSetup;
4769 double saturation_threshold = 0;
4774 eris_ifu_wave_clear_tables(&tables);
4776 for (
int ix=0; ix<ERIS_IFU_DETECTOR_SIZE_Y; ix++) {
4780 saturation_threshold = cpl_parameter_get_double(
4781 cpl_parameterlist_find_const(parlist,
"eris.eris_ifu_distortion.pixel_saturation"));
4785 eris_ifu_wavecal_processSof_dist(
4794 saturation_threshold,
4799 refLines = cpl_calloc(arcImgCnt,
sizeof(cpl_bivector *)));
4801 collapsedSpectra = cpl_calloc(arcImgCnt,
sizeof(cpl_image *)));
4803 dataImg = cpl_calloc(arcImgCnt,
sizeof(cpl_image *)));
4804 *imgCnt = arcImgCnt;
4807 for (
int i = 0; i < arcImgCnt; i++) {
4811 dataImg[i] = cpl_image_duplicate(
4814 nRows = cpl_image_get_size_y(dataImg[0]);
4817 refLineTableFileName = cpl_frame_get_filename(
4818 cpl_frameset_find(fs, ERIS_IFU_CALIB_REF_LINES));
4819 for (
int ix = 0; ix < arcImgCnt; ix++) {
4821 refLines[ix] = eris_ifu_wave_get_refLines(
4822 refLineTableFileName, instrument,
4828 centerss = cpl_vector_new(SLITLET_CNT);
4829 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4831 cpl_table *centers = centers_fitted[sIdx];
4832 double *dd = cpl_table_get_data_double(centers,
"x");
4833 cpl_vector *vcen = cpl_vector_wrap (cpl_table_get_nrow(centers), dd);
4834 double ddd = cpl_vector_get_mean(vcen);
4835 cpl_vector_set(centerss,sIdx, ddd);
4836 cpl_vector_unwrap(vcen);
4849 for (
int aIdx = 0; aIdx < arcImgCnt; aIdx++) {
4850 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4851 center = (int) cpl_vector_get (centerss, sIdx);
4853 collapsedSpectrum = eris_ifu_wave_collapse_slitlet(
4854 dataImg[aIdx], center);
4856 eris_ifu_wave_save_spectrum(collapsedSpectra, aIdx,
4857 collapsedSpectrum, sIdx, nRows,
4858 lampStates[aIdx], band, instrument,
4859 refLines[aIdx], productDepth);
4866 firstFitTableFileName = cpl_frame_get_filename(
4867 cpl_frameset_find(fs, ERIS_IFU_CALIB_FIRST_FIT));
4868 if (firstFitTableFileName == NULL) {
4870 "missing \"ERIS_IFU_CALIB_FIRST_FIT\" tag in the SOF, wavecal first fit table");
4873 firstFitTable = eris_ifu_wave_get_firstFitTable(
4874 firstFitTableFileName, instrument, band));
4876 waveSetupFileName = cpl_frame_get_filename(
4877 cpl_frameset_find(fs, ERIS_IFU_CALIB_WAVE_SETUP));
4878 if (waveSetupFileName == NULL) {
4880 "missing \"ERIS_IFU_CALIB_WAVE_SETUP\" tag in the SOF, wavecal setup table");
4883 eris_ifu_wave_init_tables(&tables));
4885 eris_ifu_read_wave_setup(waveSetupFileName, band, &waveSetup));
4887 const int slitlet2collapsed[SLITLET_CNT] = {
4888 0, 15, 1, 16, 2, 17, 3, 18, 4, 19, 5, 20, 6, 21, 7,
4890 22, 8, 23, 9, 24, 10, 25, 11, 26, 12, 27, 13, 28, 14, 29};
4892 collapsedImgDetOrder =
4893 cpl_calloc(arcImgCnt,
sizeof(cpl_image *));
4894 for (
int aIdx = 0; aIdx < arcImgCnt; aIdx++) {
4895 cpl_size xSize = cpl_image_get_size_x(collapsedSpectra[aIdx]);
4896 cpl_size ySize = cpl_image_get_size_y(collapsedSpectra[aIdx]);
4897 collapsedImgDetOrder[aIdx] =
4898 cpl_image_new(xSize, ySize, CPL_TYPE_DOUBLE);
4899 double *in = cpl_image_get_data_double(collapsedSpectra[aIdx]);
4900 double *out = cpl_image_get_data_double(collapsedImgDetOrder[aIdx]);
4901 for (
int sx=0; sx < SLITLET_CNT; sx++) {
4902 int ix = slitlet2collapsed[sx];
4903 for (
int iy = 0; iy < ySize; iy++){
4904 out[sx+iy*xSize] = in[ix+iy*xSize];
4911 int firstFitMasterOffset = 0;
4913 firstFit = eris_ifu_get_first_fit(collapsedSpectra,
4914 lampStates, arcImgCnt, 16, 0, &firstFitMasterOffset,
4915 waveSetup, firstFitTable,
4916 tables.slitletFitting, tables.slitletCoeff));
4917 cpl_msg_info(__func__,
"FirstFit Master Offset %d", firstFitMasterOffset);
4919 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4921 firstFit = eris_ifu_get_first_fit(collapsedSpectra,
4922 lampStates, arcImgCnt, sIdx, firstFitMasterOffset, &firstFitOffset,
4923 waveSetup, firstFitTable,
4924 tables.slitletFitting, tables.slitletCoeff));
4931 const double column[] = {0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,
4932 10.,11.,12.,13.,14.,15.,16.,17.,18.,19.,
4933 20.,21.,22.,23.,24.,25.,26.,27.,28.,29.,30.,31,};
4935 eris_ifu_fit_all_lines(REC_NAME_DISTORTION, sIdx, column, column,
4936 arcImgCnt, (
const cpl_image **) collapsedImgDetOrder, refLines,
4937 waveSetup, firstFit, allFits,
4938 tables.columnFitting, tables.columnCoeffRaw,
4939 tables.columnCoeffSmoothed, tables.smoothingCoeff));
4941 cpl_table_unselect_all(tables.columnFitting);
4942 cpl_table_or_selected_int(tables.columnFitting, ERIS_IFU_FITTABLE_SLITLET, CPL_EQUAL_TO, sIdx);
4943 for (
int rx = 0; rx < cpl_table_get_nrow(tables.columnFitting); rx++) {
4944 if (cpl_table_is_selected(tables.columnFitting, rx) == 1) {
4945 cpl_table_set_int(tables.columnFitting, ERIS_IFU_FITTABLE_INDEX, rx, (
int) cpl_vector_get (centerss, sIdx));
4951 if (productDepth > 3 ) {
4953 eris_ifu_wave_save_fitting_tables(&tables, instrument, band,
4954 waveSetup, fs, parlist,
4955 "eris_ifu_distortion"));
4957 cpl_table_unselect_all(tables.columnFitting);
4958 cpl_table_or_selected_int(tables.columnFitting, ERIS_IFU_FITTABLE_ERRORCODE, CPL_NOT_EQUAL_TO, 0);
4959 BRK_IF_ERROR(cpl_table_erase_selected(tables.columnFitting));
4962 cpl_table_unselect_all(tables.columnFitting);
4963 cpl_table_new_column(tables.columnFitting,
"intensity", CPL_TYPE_DOUBLE);
4964 for (
int i = 0; i < cpl_table_get_nrow(tables.columnFitting); i++) {
4965 double sigma = cpl_table_get_double(tables.columnFitting,
"sigma", i, NULL),
4966 area = cpl_table_get_double(tables.columnFitting,
"area", i, NULL),
4967 offset = cpl_table_get_double(tables.columnFitting,
"offset", i, NULL);
4969 double inten = area / sqrt(2.*(
double)CX_PI*pow(sigma,2)) + offset;
4970 if ((inten - offset) > 20. && sigma < 2.) {
4972 cpl_table_set_double(tables.columnFitting,
"intensity", i, inten);
4975 cpl_table_or_selected_window(tables.columnFitting, i, 1);
4979 BRK_IF_ERROR(cpl_table_erase_selected(tables.columnFitting));
4986 pl = cpl_propertylist_new());
4988 cpl_propertylist_append_bool(pl,
"position", CPL_TRUE));
4990 cpl_table_sort(tables.columnFitting, pl));
4995 if ((productDepth & 3) != 0) {
4997 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4998 cpl_table_unselect_all(tables.columnFitting);
4999 cpl_table_or_selected_int(tables.columnFitting, ERIS_IFU_FITTABLE_SLITLET, CPL_EQUAL_TO, sIdx);
5000 cpl_table *t = cpl_table_extract_selected(tables.columnFitting);
5007 cpl_table_save(t, NULL, NULL,
"eris_ifu_distortion_dbg_wave_fit_lines.fits", c));
5016 cpl_free(lampStates);
5020 for (
int ix=0; ix<arcImgCnt; ix++) {
5026 cpl_free(collapsedSpectra);
5027 cpl_free(collapsedImgDetOrder);
5028 for (
int ix=0; ix<ERIS_IFU_DETECTOR_SIZE_Y; ix++) {
5038 return tables.columnFitting;
#define ASSURE(condition, error,...)
error handling macro (from fors-pipeline)
#define SET_ERROR_MSG(code, msg)
Set a new error code together with a custom error message.
#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 SET_ERROR(code)
Set a new error code.
#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.
#define CATCH_MSGS()
Displays an error message stack.
cpl_vector * eris_ifu_calc_centers_collapse_chunk(const cpl_image *img, int chunk_center, int height)
void eris_ifu_free_propertylist(cpl_propertylist **item)
free memory and set pointer to null
void eris_ifu_free_string(char **item)
free memory and set pointer to null
void eris_ifu_free_vector(cpl_vector **item)
free memory and set pointer to null
cpl_error_code eris_ifu_save_vector_dbg(const cpl_vector *vec, const char *filename, int create, const cpl_propertylist *pl)
save vector
void eris_ifu_free_table(cpl_table **item)
free memory and set pointer to null
const char * eris_ifu_get_bandString(ifsBand band)
eris_ifu_get_bandString
void eris_ifu_free_ifu_vector(eris_ifu_vector **item)
free memory and set pointer to null
void eris_ifu_free_polynomial(cpl_polynomial **item)
free memory and set pointer to null
void eris_ifu_free_hdrl_imagelist(hdrl_imagelist **item)
free memory and set pointer to null
void eris_ifu_free_image(cpl_image **item)
free memory and set pointer to null
void eris_ifu_free_bivector(cpl_bivector **item)
free memory and set pointer to null
double eris_ifu_vector_get_stdev_median(const eris_ifu_vector *ev)
Compute the bias-corrected standard deviation of a vectors elements using median.
eris_ifu_vector * eris_ifu_vector_extract(const eris_ifu_vector *ev, int istart, int istop)
Extract a sub_vector from a eris_ifu_vector.
cpl_error_code eris_ifu_vector_subtract(eris_ifu_vector *kv1, const eris_ifu_vector *kv2)
Subtract two eris_ifu_vectors.
int eris_ifu_vector_is_rejected(const eris_ifu_vector *ev, int n)
Test if a value is good or bad.
eris_ifu_vector * eris_ifu_vector_new_wrap(int n, const double *data)
Create a new eris_ifu_vector from a vector (duplicated).
double eris_ifu_vector_get_mean(const eris_ifu_vector *ev)
Compute the mean value of non-rejected eris_ifu_vector elements.
eris_ifu_vector * eris_ifu_vector_duplicate(const eris_ifu_vector *ev)
This function duplicates an existing eris_ifu_vector and allocates memory.
int eris_ifu_vector_count_non_rejected(const eris_ifu_vector *ev)
Count the number of non-rejected elements in a eris_ifu_vector.
double eris_ifu_vector_get(const eris_ifu_vector *ev, int pos)
Get an element of the eris_ifu_vector.
cpl_error_code eris_ifu_vector_add(eris_ifu_vector *kv1, const eris_ifu_vector *kv2)
Add a eris_ifu_vector to another.
eris_ifu_vector * eris_ifu_vector_create(const cpl_vector *data)
Create a new eris_ifu_vector out of a data cpl_vector.
cpl_error_code eris_ifu_vector_reject(eris_ifu_vector *ev, int n)
Set a value as rejected in a eris_ifu_vector.
double eris_ifu_vector_get_median(const eris_ifu_vector *ev, const enum medianType type)
Compute the median of the elements of a vector.
const cpl_image * hdrl_image_get_image_const(const hdrl_image *himg)
get data as cpl image
const hdrl_image * hdrl_imagelist_get_const(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.