48#include "eris_ifu_distortion_static.h"
49#include "eris_ifu_wavecal_static.h"
50#include "eris_ifu_dfs.h"
51#include "eris_ifu_error.h"
52#include "eris_ifu_utils.h"
53#include "eris_ifu_debug.h"
54#include "eris_utils.h"
74 cpl_boolean lowerCutLevel)
87 const double *pprofile = NULL;
88 cpl_vector *pos = NULL,
90 *cen_estimates = NULL;
92 cpl_ensure(profile != NULL, CPL_ERROR_NULL_INPUT, NULL);
96 nx = cpl_vector_get_size(profile);
105 cut_level = cut_factor * mean;
116 pos = cpl_vector_new(3*SLITLET_CNT+20));
118 height = cpl_vector_new(3*SLITLET_CNT+20));
121 ppos = cpl_vector_get_data(pos));
123 pheight = cpl_vector_get_data(height));
126 pprofile = cpl_vector_get_data_const(profile));
128 for (cut_factor = 1.4; cut_factor > .1; cut_factor -= 0.2) {
129 cut_level = cut_factor * mean;
132 for (
int i = ERIS_IFU_DETECTOR_BP_BORDER;
133 i < nx-ERIS_IFU_DETECTOR_BP_BORDER;
137 if ((left == 0) && (pprofile[i] > cut_level)) {
141 if (((left != 0) && (right == 0)) &&
142 ((pprofile[i] < cut_level) || (i == nx-ERIS_IFU_DETECTOR_BP_BORDER-1))) {
146 if ((left != 0) && (right != 0)) {
147 width = right-left+1;
148 ppos[cnt] = (double)left + width/2.0;
149 pheight[cnt] = pprofile[(int) (ppos[cnt]+.5) ];
154 if (cnt >= cpl_vector_get_size(pos)) {
158 if (cnt == SLITLET_CNT || cnt == 3 * SLITLET_CNT) {
162 if (cnt > SLITLET_CNT && cnt < SLITLET_CNT + 20) {
163 est_cnt = SLITLET_CNT;
166 if (cnt > 3 * SLITLET_CNT) {
167 est_cnt = 3 * SLITLET_CNT;
174 cpl_bivector *toBeSorted = NULL;
175 BRK_IF_NULL(toBeSorted = cpl_bivector_wrap_vectors(pos, height));
177 CPL_SORT_DESCENDING, CPL_SORT_BY_Y));
178 cpl_bivector_unwrap_vectors(toBeSorted);
185 cen_estimates = cpl_vector_extract(pos, 0, cnt-1, 1));
187 BRK_IF_ERROR(cpl_vector_sort(cen_estimates, CPL_SORT_ASCENDING));
200 return cen_estimates;
220 cpl_vector *est_new = NULL,
222 double *pest_new = NULL;
223 const double *pest_centers = NULL;
227 cpl_ensure(est_centers, CPL_ERROR_NULL_INPUT, NULL);
232 pest_centers = cpl_vector_get_data_const(est_centers));
234 cnt = cpl_vector_get_size(est_centers);
235 if ((cnt == SLITLET_CNT) || (cnt == 3*SLITLET_CNT)) {
238 est_new = cpl_vector_duplicate(est_centers));
240 }
else if (cnt < SLITLET_CNT) {
243 est_new = cpl_vector_new(SLITLET_CNT));
244 cpl_vector_fill(est_new, 0.);
245 }
else if ((cnt > SLITLET_CNT+10) && (cnt < 3*SLITLET_CNT)) {
248 est_new = cpl_vector_new(3*SLITLET_CNT));
249 cpl_vector_fill(est_new, 0.);
254 est_new = cpl_vector_duplicate(est_centers));
258 cpl_vector_multiply_scalar(est_new, 0.));
260 pest_new = cpl_vector_get_data(est_new));
262 if (cnt < SLITLET_CNT) {
268 while ((fabs(pest_centers[ind+1]-pest_centers[ind]-2*SLITLET_WIDTH) > 10) && (ind < 18)) {
273 for (
int i = 0; i < ind+1; i++) {
274 pest_new[i] = pest_centers[i];
277 pest_new[15] = (pest_centers[ind+1] - pest_centers[ind])/2 + pest_centers[ind];
278 for (cpl_size i = ind+1; i < SLITLET_CNT; i++) {
279 pest_new[i+1] = pest_centers[i];
289 for (i = 0; i < ind+1; i++) {
290 pest_new[i] = pest_centers[i];
294 ind = 3*start_slit + 1;
296 cpl_boolean found = CPL_FALSE;
298 est_trace_distance = 20;
299 while (ind < 3*end_slit) {
300 double val = fabs(pest_centers[ind]-pest_centers[ind-3]-SLITLET_WIDTH);
301 if (found && (decr_found > 0)) {
302 val -= est_trace_distance;
307 pest_new[i++] = pest_centers[ind++];
310 pest_new[i] = pest_centers[ind-3]+SLITLET_WIDTH;
312 pest_new[i] = pest_centers[ind++];
320 for (; i < 3*SLITLET_CNT; i++) {
322 pest_new[i] = pest_centers[ind++];
329 cnt = cpl_vector_get_size(est_new);
331 while (pest_new[ind] < 0.0001 && ind > 0) {
336 est_new2 = cpl_vector_extract(est_new, 0, ind, 1));
372 const cpl_vector *est_centers,
373 cpl_boolean do_fix_cnt)
385 lastValidOffset = 0.,
386 *pfit_centers = NULL,
388 cpl_vector *fit_centers = NULL,
390 *est_centers2 = NULL;
391 cpl_boolean fix_cnt = FALSE;
392 struct gaussParStruct gaussPar;
393 eris_ifu_vector *v = NULL,
396 cpl_ensure(profile, CPL_ERROR_NULL_INPUT, NULL);
397 cpl_ensure(cpl_vector_get_size(profile) == ERIS_IFU_DETECTOR_SIZE,
398 CPL_ERROR_ILLEGAL_INPUT, NULL);
399 cpl_ensure(est_centers, CPL_ERROR_NULL_INPUT, NULL);
406 cnt = (int) cpl_vector_get_size(est_centers2);
410 if (cnt < SLITLET_CNT) {
411 cpl_msg_error(cpl_func,
"Detected %d traces instead of at least %d!",
417 if ((cnt > 2*SLITLET_CNT) && (cnt < 3*SLITLET_CNT)) {
418 cpl_msg_error(cpl_func,
"Detected %d traces instead of at least %d!",
419 cnt2, 3*SLITLET_CNT);
425 if (do_fix_cnt && (cnt != SLITLET_CNT) && (cnt != 3*SLITLET_CNT)) {
433 fit_centers = cpl_vector_new(cnt));
435 pfit_centers = cpl_vector_get_data(fit_centers));
438 fit_peaks = cpl_vector_new(cnt));
440 pfit_peaks = cpl_vector_get_data(fit_peaks));
443 for (
int i = 0; i < cnt; i++) {
444 cen = (int) (cpl_vector_get(est_centers2, i) + 0.5);
446 eris_ifu_line_gauss_fit(profile, cen,
447 NS_EST_SLIT_DIST/3, &gaussPar));
449 if (gaussPar.errorCode == 0) {
450 pfit_centers[i] = gaussPar.x0;
452 pfit_centers[i] - cpl_vector_get(est_centers2, i);
454 pfit_centers[i] = cpl_vector_get(est_centers2, i) +
458 pfit_peaks[i] = gaussPar.area
459 / sqrt(2*CPL_MATH_PI*pow(gaussPar.sigma,2))
480 for (
int i = start; i <= end; i++) {
482 if ((val < med-thresh1*std) || (val > med+thresh1*std)) {
490 start = cnt-1-cnt/10*2;
499 for (
int i = start; i <= end; i++) {
501 if ((val < med-thresh1*std) || (val > med+thresh1*std)) {
510 if ((cnt2 != SLITLET_CNT) && (cnt2 != 3*SLITLET_CNT)) {
514 for (
int i = 0; i <= end; i++) {
517 if ((val < med-thresh2*std) || (val > med+thresh2*std)) {
526 if ((cnt2 != SLITLET_CNT) && (cnt2 != 3*SLITLET_CNT)) {
528 if (abs(SLITLET_CNT-cnt2) < 10) {
531 if (abs(3*SLITLET_CNT-cnt2) < 10) {
532 cnt3 = 3*SLITLET_CNT;
535 cpl_msg_error(cpl_func,
"Detected %d traces instead of %d!", cnt2, cnt3);
539 cpl_vector *fit_centers2 = NULL;
540 double *pfit_centers2 = NULL;
542 fit_centers2 = cpl_vector_new(cnt2));
544 pfit_centers2 = cpl_vector_get_data(fit_centers2));
546 for (
int i = 0; i < cnt; i++) {
548 pfit_centers2[j++] = pfit_centers[i];
551 cpl_vector_delete(fit_centers);
552 fit_centers = fit_centers2;
589 cpl_table **cen_array)
592 index_to_compare = 0,
594 double last_val = 0.,
596 cpl_error_code err = CPL_ERROR_NONE;
597 const double *pfit_centers = NULL;
599 cpl_ensure_code(fit_centers, CPL_ERROR_NULL_INPUT);
600 cpl_ensure_code(cen_array, CPL_ERROR_NULL_INPUT);
604 actual_size = (int) cpl_vector_get_size(fit_centers);
606 pfit_centers = cpl_vector_get_data_const(fit_centers));
608 if (actual_size == SLITLET_CNT) {
609 for (
int i = 0; i < SLITLET_CNT; i++) {
611 cpl_table_set_double(cen_array[i],
"y", y_index, y_value));
613 cpl_table_set_double(cen_array[i],
"x", y_index, pfit_centers[i]));
615 }
else if (actual_size == 3*SLITLET_CNT) {
616 for (
int i = 0; i < SLITLET_CNT; i++) {
618 cpl_table_set_double(cen_array[i],
"y", y_index, y_value));
622 cpl_table_set_double(cen_array[i],
"x_l", y_index, pfit_centers[3*i]));
626 cpl_table_set_double(cen_array[i],
"x", y_index, pfit_centers[3*i+1]));
630 cpl_table_set_double(cen_array[i],
"x_r", y_index, pfit_centers[3*i+2]));
633 cpl_boolean special_handling = CPL_FALSE;
635 if (y_index < cpl_table_get_nrow(cen_array[0])/2) {
637 index_to_compare = y_index+1;
640 index_to_compare = y_index-1;
643 if (!special_handling && (actual_size < 3*SLITLET_CNT)) {
645 last_val = cpl_table_get_double(cen_array[0],
"x_l", index_to_compare, &tmp);
646 actual_val = pfit_centers[0];
647 if (!special_handling && (fabs(last_val-actual_val) < 5.)) {
652 for (
int i = 0; i < SLITLET_CNT; i++) {
654 cpl_table_set_double(cen_array[i],
"y", y_index, y_value));
658 cpl_table_set_double(cen_array[i],
"x_l", y_index, pfit_centers[3*i]));
659 if (++tmp == actual_size)
break;
663 cpl_table_set_double(cen_array[i],
"x", y_index, pfit_centers[3*i+1]));
664 if (++tmp == actual_size)
break;
668 cpl_table_set_double(cen_array[i],
"x_r", y_index, pfit_centers[3*i+2]));
669 if (++tmp == actual_size)
break;
671 special_handling = CPL_TRUE;
675 last_val = cpl_table_get_double(cen_array[SLITLET_CNT-1],
"x_r", index_to_compare, &tmp);
676 actual_val = pfit_centers[actual_size-1];
677 if (!special_handling && (fabs(last_val-actual_val) < 5.)) {
682 for (
int i = SLITLET_CNT-1; i >= 0; i--) {
684 cpl_table_set_double(cen_array[i],
"y", y_index, y_value));
688 cpl_table_set_double(cen_array[i],
"x_r", y_index, pfit_centers[tmp-1]));
689 if (--tmp == actual_size)
break;
693 cpl_table_set_double(cen_array[i],
"x", y_index, pfit_centers[tmp-1]));
694 if (--tmp == actual_size)
break;
698 cpl_table_set_double(cen_array[i],
"x_l", y_index, pfit_centers[tmp-1]));
699 if (--tmp == actual_size)
break;
701 special_handling = CPL_TRUE;
705 if (!special_handling && (actual_size < SLITLET_CNT)) {
707 last_val = cpl_table_get_double(cen_array[0],
"x", index_to_compare, &tmp);
708 actual_val = pfit_centers[0];
709 if (!special_handling && (fabs(last_val-actual_val) < 5.)) {
714 for (
int i = 0; i < SLITLET_CNT; i++) {
716 cpl_table_set_double(cen_array[i],
"y", y_index, y_value));
718 cpl_table_set_double(cen_array[i],
"x", y_index, pfit_centers[i]));
719 if (++tmp == actual_size)
break;
721 special_handling = CPL_TRUE;
725 last_val = cpl_table_get_double(cen_array[SLITLET_CNT-1],
"x", index_to_compare, &tmp);
726 actual_val = pfit_centers[actual_size-1];
727 if (!special_handling && (fabs(last_val-actual_val) < 5.)) {
732 for (
int i = SLITLET_CNT-1; i >= 0; i--) {
734 cpl_table_set_double(cen_array[i],
"y", y_index, y_value));
736 cpl_table_set_double(cen_array[i],
"x", y_index, pfit_centers[tmp-1]));
737 if (--tmp == actual_size)
break;
739 special_handling = CPL_TRUE;
743 if (!special_handling) {
745 "Handling of trace running out of "
746 "detector image failed!!!");
753 for (
int j = 0; j < SLITLET_CNT; j++) {
754 cpl_table_set_double(cen_array[j],
"x", y_index, 0.);
755 cpl_table_set_double(cen_array[j],
"y", y_index, 0.);
758 err = cpl_error_get_code();
786 const hdrl_image *fibre_on,
798 const cpl_image *img = NULL,
801 cpl_vector *profile_x = NULL,
802 *profile_x_div = NULL,
803 *profile_x_on = NULL,
805 *est_centers_div = NULL,
806 *est_centers_on = NULL,
808 *fit_centers_middle = NULL;
809 cpl_table **cen_array = NULL;
812 cpl_ensure(fibre_div, CPL_ERROR_NULL_INPUT, NULL);
813 cpl_ensure(fibre_on, CPL_ERROR_NULL_INPUT, NULL);
816 cpl_ensure(nr_values % 2 == 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
817 cpl_ensure(height % 2 == 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
830 cen_array = cpl_calloc(SLITLET_CNT,
sizeof(cpl_table*)));
840 center_y = ERIS_IFU_DETECTOR_BP_BORDER + ix_middle*height + height/2;
843 img_div, center_y, height));
846 img_on, center_y, height));
856 profile_x_on, est_centers_on, CPL_TRUE));
858 if (productDepth & 4) {
859 cpl_propertylist *pl = NULL;
861 pl = cpl_propertylist_new());
864 cpl_propertylist_update_string(pl,
"EXTNAME",
"profile_x_div"));
866 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
868 cpl_propertylist_update_string(pl,
"EXTNAME",
"profile_x_on"));
870 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
872 cpl_propertylist_update_string(pl,
"EXTNAME",
"est_centers_div"));
874 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
876 cpl_propertylist_update_string(pl,
"EXTNAME",
"est_centers_on"));
878 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND,pl );
880 cpl_propertylist_update_string(pl,
"EXTNAME",
"fit_centers_middle"));
882 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND,pl);
894 cnt = (int) cpl_vector_get_size(fit_centers_middle);
896 if (cnt == SLITLET_CNT) {
898 for (
int j = 0; j < SLITLET_CNT; j++) {
900 cen_array[j] = cpl_table_new(nr_values));
902 cpl_table_new_column(cen_array[j],
"x", CPL_TYPE_DOUBLE));
904 cpl_table_new_column(cen_array[j],
"y", CPL_TYPE_DOUBLE));
905 for (
int i = 0; i < nr_values; i++) {
907 cpl_table_set(cen_array[j],
"x", i, NAN);
908 cpl_table_set(cen_array[j],
"y", i, NAN);
913 for (
int j = 0; j < SLITLET_CNT; j++) {
915 cen_array[j] = cpl_table_new(nr_values));
917 cpl_table_new_column(cen_array[j],
"x_l", CPL_TYPE_DOUBLE));
919 cpl_table_new_column(cen_array[j],
"x", CPL_TYPE_DOUBLE));
921 cpl_table_new_column(cen_array[j],
"x_r", CPL_TYPE_DOUBLE));
923 cpl_table_new_column(cen_array[j],
"y", CPL_TYPE_DOUBLE));
924 for (
int i = 0; i < nr_values; i++) {
926 cpl_table_set(cen_array[j],
"x_l", i, NAN);
927 cpl_table_set(cen_array[j],
"x", i, NAN);
928 cpl_table_set(cen_array[j],
"x_r", i, NAN);
929 cpl_table_set(cen_array[j],
"y", i, NAN);
943 BRK_IF_NULL(est_centers = cpl_vector_duplicate(fit_centers_middle));
944 for (
int i = ix_middle; i < nr_values; i++) {
945 center_y = ERIS_IFU_DETECTOR_BP_BORDER + i*height + height/2;
949 img, center_y, height));
959 if ((productDepth & 4) != 0) {
960 char *extname = NULL;
961 cpl_propertylist *pl = NULL;
963 pl = cpl_propertylist_new());
964 extname = cpl_sprintf(
"Sx_%02d profile_x", i+1);
965 cpl_propertylist_update_string(pl,
"EXTNAME", extname);
968 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
969 extname = cpl_sprintf(
"Sx_%02d est_centers", i+1);
970 cpl_propertylist_update_string(pl,
"EXTNAME", extname);
973 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
974 extname = cpl_sprintf(
"Sx_%02d fit_centers", i+1);
975 cpl_propertylist_update_string(pl,
"EXTNAME", extname);
978 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND ,pl);
982 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
987 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers_middle));
988 for (
int i = ix_middle-1; i >= 0; i--) {
989 center_y = ERIS_IFU_DETECTOR_BP_BORDER + i*height + height/2;
993 img, center_y, height));
1003 if ((productDepth & 4) != 0) {
1004 char *extname = NULL;
1005 cpl_propertylist *pl = NULL;
1007 pl = cpl_propertylist_new());
1008 extname = cpl_sprintf(
"Sx_%02d profile_x", i+1);
1009 cpl_propertylist_update_string(pl,
"EXTNAME", extname);
1012 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
1013 extname = cpl_sprintf(
"Sx_%02d est_centers", i+1);
1014 cpl_propertylist_update_string(pl,
"EXTNAME", extname);
1017 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
1018 extname = cpl_sprintf(
"Sx_%02d fit_centers", i+1);
1019 cpl_propertylist_update_string(pl,
"EXTNAME", extname);
1022 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
1026 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
1031 if (productDepth & 4) {
1034 cpl_propertylist_save(NULL,
"eris_ifu_distortion_dbg_centers_fitted.fits", CPL_IO_CREATE));
1036 cpl_propertylist_save(NULL,
"eris_ifu_distortion_dbg_centers_fitted_visual.fits", CPL_IO_CREATE));
1037 for (
int j = 0; j < SLITLET_CNT; j++) {
1038 cpl_table_save(cen_array[j], NULL, NULL,
"eris_ifu_distortion_dbg_centers_fitted.fits", CPL_IO_EXTEND);
1045 for (
int i = 0; i < SLITLET_CNT; i++) {
1048 cpl_free(cen_array); cen_array = NULL;
1062int eris_ifu_distortion_calc_y(
int n,
int i) {
1066 return (
int)((double)ERIS_IFU_DETECTOR_SIZE_Y/n*(i+.5)+.5);
1069int eris_ifu_distortion_target_left_edge(
int i) {
1070 return i * SLITLET_WIDTH;
1072int eris_ifu_distortion_target_right_edge(
int i) {
1073 return (i + 1) * SLITLET_WIDTH - 1;
1088 cpl_boolean triple_traces ,
1089 cpl_boolean cut_off_left,
1090 cpl_boolean cut_off_right)
1094 if (triple_traces) {
1100 if (((i == 0) && cut_off_left) ||
1101 ((i == SLITLET_CNT-1) && cut_off_right))
1137 cpl_table **centers,
1139 cpl_boolean cut_off_left,
1140 cpl_boolean cut_off_right,
1141 cpl_table **minmax_borders,
1142 cpl_propertylist ***qc,
1143 cpl_propertylist *pl,
1144 cpl_frameset* frameset,
1145 const cpl_parameterlist* parlist)
1178 const double *pwave_y = NULL,
1180 cpl_polynomial **poly_u = NULL;
1181 cpl_bivector *grid = NULL;
1182 cpl_vector *val_to_fit = NULL,
1185 eris_ifu_vector *y_wave = NULL,
1188 cpl_boolean triple_traces = FALSE;
1189 cpl_table *tbl = NULL,
1190 *dbg_polynomials = NULL;
1191 struct arcstruct *arc_tbl = NULL;
1194 cpl_ensure(slit_edges, CPL_ERROR_NULL_INPUT, NULL);
1195 cpl_ensure(centers, CPL_ERROR_NULL_INPUT, NULL);
1196 cpl_ensure(minmax_borders, CPL_ERROR_NULL_INPUT, NULL);
1200 BRK_IF_NULL( dbg_polynomials = cpl_table_new(SLITLET_CNT));
1201 cpl_table_new_column(dbg_polynomials, ERIS_IFU_DIST_DBG_SLITLET, CPL_TYPE_INT);
1202 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_EDGE_LEFT, CPL_TYPE_DOUBLE, fit_order+1);
1203 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_EDGE_RIGHT, CPL_TYPE_DOUBLE, fit_order+1);
1204 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER_LEFT, CPL_TYPE_DOUBLE, fit_order+1);
1205 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER, CPL_TYPE_DOUBLE, fit_order+1);
1206 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER_RIGHT, CPL_TYPE_DOUBLE, fit_order+1);
1210 *minmax_borders = cpl_table_new(SLITLET_CNT));
1212 cpl_table_new_column(*minmax_borders, ERIS_IFU_POLY_EDGE_L, CPL_TYPE_DOUBLE));
1214 cpl_table_new_column(*minmax_borders, ERIS_IFU_POLY_EDGE_R, CPL_TYPE_DOUBLE));
1217 poly_u = cpl_calloc(SLITLET_CNT,
sizeof(cpl_polynomial*)));
1219 if (cpl_table_get_ncol(centers[5]) > 2) {
1220 triple_traces = TRUE;
1223 if (productDepth & 1) {
1224 cpl_propertylist_append_string(pl, CPL_DFS_PRO_CATG,
1226 cpl_propertylist_save(pl, ERIS_IFU_PRO_DIST_QC_FIT_FN,
1228 eris_setup_product_header(ERIS_IFU_PRO_DIST_QC_FIT_FN,
1229 "DIST_FIT_TABLE", CPL_FRAME_TYPE_TABLE,
1230 "eris_ifu_distortion", frameset, parlist, pl);
1233 arc_tbl = cpl_calloc(SLITLET_CNT,
sizeof(
struct arcstruct)));
1236 for (
int i = 0; i < SLITLET_CNT; i++) {
1240 cut_off_left, cut_off_right);
1242 n_calib_wave = (int) cpl_table_get_nrow(slit_edges[i]);
1244 n_calib_cen = (int) cpl_table_get_nrow(centers[i]);
1248 pwave_y = cpl_table_get_data_double_const(
1249 slit_edges[i],
"y_pos"));
1251 pcenter_y = cpl_table_get_data_double_const(
1259 if (!((i == 0) && cut_off_left)) {
1263 slit_edges[i],
"edge_left", y_wave,
1264 n_calib_wave, n_size, fit_order,
1265 i, dbg_polynomials));
1267 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1271 slit_edges[i],
"edge_right", y_wave,
1272 n_calib_wave, n_size, fit_order,
1273 i, dbg_polynomials));
1277 centers[i],
"x", y_cen,
1278 n_calib_cen, n_size, fit_order,
1279 i, dbg_polynomials));
1280 if (triple_traces) {
1281 if (!((i == 0) && cut_off_left)) {
1285 centers[i],
"x_l", y_cen,
1286 n_calib_cen, n_size, fit_order,
1287 i, dbg_polynomials));
1292 if (cpl_table_count_invalid(centers[i],
"x_l") <= 0.1 * n_calib_cen) {
1296 centers[i],
"x_l", y_cen,
1297 n_calib_cen, n_size, fit_order,
1298 i, dbg_polynomials));
1302 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1306 centers[i],
"x_r", y_cen,
1307 n_calib_cen, n_size, fit_order,
1308 i, dbg_polynomials));
1313 if (cpl_table_count_invalid(centers[i],
"x_r") <= 0.1 * n_calib_cen) {
1317 centers[i],
"x_r", y_cen,
1318 n_calib_cen, n_size, fit_order,
1319 i, dbg_polynomials));
1327 BRK_IF_ERROR( cpl_table_save(dbg_polynomials, NULL, NULL,
1328 "eris_ifu_distortion_dbg_polynomials.fits", CPL_IO_CREATE));
1331 *qc = cpl_calloc(SLITLET_CNT,
sizeof(cpl_propertylist*)));
1332 for (
int i = 0; i < SLITLET_CNT; i++) {
1334 (*qc)[i] = cpl_propertylist_new());
1339 if (arc_tbl[0].fit_l == NULL) {
1344 cpl_propertylist_append_string((*qc)[0],
1345 "ESO EDGE L",
"artificial"));
1353 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_l == NULL)) {
1358 cpl_propertylist_append_string((*qc)[0],
1359 "ESO EDGE C-L",
"artificial"));
1367 cut_off_left = CPL_FALSE;
1370 if (cut_off_right) {
1371 if (arc_tbl[SLITLET_CNT-1].fit_r == NULL) {
1376 cpl_propertylist_append_string((*qc)[SLITLET_CNT-1],
1377 "ESO EDGE R",
"artificial"));
1385 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_r == NULL)) {
1390 cpl_propertylist_append_string((*qc)[0],
1391 "ESO EDGE C-R",
"artificial"));
1399 cut_off_right = CPL_FALSE;
1407 m_c = 64. * (o_c5 - o_l5) / (o_r5 - o_l5);
1408 if (triple_traces) {
1411 m_c_l = 64. * (o_c_l - o_l5) / (o_r5 - o_l5);
1412 m_c_r = 64. * (o_c_r - o_l5) / (o_r5 - o_l5);
1421 if (productDepth >= PD_DEBUG) {
1423 cpl_propertylist_update_string(pl, CPL_DFS_PRO_CATG,
1424 ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID));
1426 cpl_image_save(NULL, ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID_FN,
1427 CPL_TYPE_FLOAT, pl, CPL_IO_CREATE));
1432 for (
int i = 0; i < SLITLET_CNT; i++) {
1433 cpl_msg_debug(cpl_func,
"i: %d", i);
1436 cut_off_left, cut_off_right);
1447 if (triple_traces) {
1450 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);
1451 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);
1452 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);
1454 cpl_msg_debug(cpl_func, " o_l: %g, o_c: %g, o_r: %g
", o_l, o_c, o_r);
1458 * from these estimates define target positions for the arc-lines (left, center, right)
1460 // left+right edge are simple: a slitlet should have 64pix width
1461 t_o = eris_ifu_distortion_target_left_edge(i);
1462 t_l = eris_ifu_distortion_target_left_edge(i);
1463 t_r = eris_ifu_distortion_target_right_edge(i);
1464 t_l = t_o + m_c - (o_c-o_l) / (o_c5-o_l5) * m_c;
1465// t_l = t_o + m_c_r - (o_c_r - o_l) / m_t_t;
1466 // the center positions are calculated with the sentence of three...
1467 t_c = (int)((o_c-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1469 if (triple_traces) {
1470 t_c_l = (int)((o_c_l-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1471 t_c_r = (int)((o_c_r-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1472 t_c_l = t_o + m_c_l;
1473 t_c_r = t_o + m_c_r;
1474 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);
1476 cpl_msg_debug(cpl_func, " t_l: %f, t_c: %f, t_r: %f
", t_l, t_c, t_r);
1484// 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
",
1485// 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);
1486// cpl_msg_debug(cpl_func, "i: %02d, o_l: %7.2f, o_c_l: %7.2f,
"
1487// "o_c: %7.2f, o_c_r: %7.2f, o_r: %7.2f
",
1488// i, o_l, o_c_l, o_c, o_c_r, o_r);
1489// cpl_msg_debug(cpl_func, " t_l: %04d , t_c_l: %04d ,
"
1490// " t_c: %04d , t_c_r: %04d , t_r: %04d
",
1491// t_l, t_c_l, t_c, t_c_r, t_r);
1492 // create grid to fit to (contains target-coordinates)
1494 grid = cpl_bivector_new(n_arcs * n_size));
1496 // create vector with values to fit (contains origin-coordinates)
1498 val_to_fit = cpl_vector_new(n_arcs * n_size));
1501 // fill in edges and subtract always in a manner that destination_x(target) is 0 for left edge
1502 // fill in left edge
1504 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_l, val_to_fit,
1505 t_l-tx, n_size, arc_cnt++));
1506 if (triple_traces) {
1509 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c_l, val_to_fit,
1510 t_c_l-tx, n_size, arc_cnt++));
1513//cpl_msg_debug(cpl_func, ">>> %d
", i);
1518 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c, val_to_fit,
1519 t_c-tx, n_size, arc_cnt++));
1520 if (triple_traces) {
1523 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c_r, val_to_fit,
1524 t_c_r-tx, n_size, arc_cnt++));
1526 // fill in right edge
1528 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_r, val_to_fit,
1529 t_r-tx, n_size, arc_cnt++));
1531 // save l_min and r_max
1532 l_min = floor(eris_ifu_vector_get_min(arc_tbl[i].fit_l, &pos));
1534 cpl_table_set_double(*minmax_borders, ERIS_IFU_POLY_EDGE_L, i,
1537 cpl_table_set_double(*minmax_borders, ERIS_IFU_POLY_EDGE_R, i,
1538 ceil(eris_ifu_vector_get_max(arc_tbl[i].fit_r, &pos))));
1540 // fill in edges and subtract always in a manner that destination_x(measured) is 0.0 for left edge at beginning
1542 cpl_vector_subtract_scalar(val_to_fit, l_min));
1544 if (productDepth >= PD_DEBUG) {
1546 extName = cpl_sprintf("GRIDX_%2.2d
", i);
1548 cpl_propertylist_update_string(pl, "EXTNAME
", extName));
1550 cpl_vector_save(cpl_bivector_get_x(grid),
1551 ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID_FN,
1552 CPL_TYPE_FLOAT, pl, CPL_IO_EXTEND));
1554 extName = cpl_sprintf("GRIDY_%2.2d
", i);
1556 cpl_propertylist_update_string(pl, "EXTNAME
", extName));
1558 cpl_vector_save(cpl_bivector_get_y(grid),
1559 ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID_FN,
1560 CPL_TYPE_FLOAT, pl, CPL_IO_EXTEND));
1562 extName = cpl_sprintf("VAL2FIT_%2.2d
", i);
1564 cpl_propertylist_update_string(pl, "EXTNAME
", extName));
1566 cpl_vector_save(val_to_fit,
1567 ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID_FN,
1568 CPL_TYPE_FLOAT, pl, CPL_IO_EXTEND));
1574 /* Perform the fit */
1576 poly_u[i] = eris_ifu_dist_poly_fit_2d_create(grid, val_to_fit, NULL));
1578 eris_ifu_free_bivector(&grid);
1579 eris_ifu_free_vector(&val_to_fit);
1580 } // end: i = SLITLET_CNT
1582 // save values of all fitted edges and some stats
1583 if (productDepth & 1) {
1584 // for the ease of stats: create the y-vector with the used values
1586 y = cpl_vector_new(n_size));
1588 py = cpl_vector_get_data(y));
1589 for (int j = 0; j < n_size; j++) {
1590 py[j] = eris_ifu_distortion_calc_y(n_size, j);
1594 for (int i = 0; i < SLITLET_CNT; i++) {
1596 tbl = cpl_table_new(n_size);
1597 if (arc_tbl[i].fit_l != NULL) {
1599 cpl_table_new_column(tbl, "l
", CPL_TYPE_DOUBLE);
1600 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_l);
1601 cpl_table_copy_data_double(tbl, "l
", cpl_vector_get_data_const(tmp_vec));
1602 eris_ifu_free_vector(&tmp_vec);
1604 if (arc_tbl[i].fit_c_l != NULL) {
1605 cpl_table_new_column(tbl, "c_l
", CPL_TYPE_DOUBLE);
1606 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_c_l);
1607 cpl_table_copy_data_double(tbl, "c_l
", cpl_vector_get_data_const(tmp_vec));
1608 eris_ifu_free_vector(&tmp_vec);
1610 if (arc_tbl[i].fit_c != NULL) {
1611 std = eris_ifu_vector_get_stdev(arc_tbl[i].fit_c);
1612 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C STDEV
",i);
1613 keycomm = cpl_sprintf("[pix] center slitlet %2.2d
",i);
1614 if (!eris_ifu_is_nan_or_inf(std)) {
1615 cpl_propertylist_append_double((*qc)[i], keyname, std);
1617 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1619 cpl_propertylist_set_comment((*qc)[i], keyname,keycomm);
1622 cpl_table_new_column(tbl, "c
", CPL_TYPE_DOUBLE);
1623 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_c);
1624 cpl_table_copy_data_double(tbl, "c
", cpl_vector_get_data_const(tmp_vec));
1625 eris_ifu_free_vector(&tmp_vec);
1627 if (arc_tbl[i].fit_c_r != NULL) {
1628 cpl_table_new_column(tbl, "c_r
", CPL_TYPE_DOUBLE);
1629 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_c_r);
1630 cpl_table_copy_data_double(tbl, "c_r
", cpl_vector_get_data_const(tmp_vec));
1631 eris_ifu_free_vector(&tmp_vec);
1633 if (arc_tbl[i].fit_r != NULL) {
1634 cpl_table_new_column(tbl, "r
", CPL_TYPE_DOUBLE);
1635 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_r);
1636 cpl_table_copy_data_double(tbl, "r
", cpl_vector_get_data_const(tmp_vec));
1637 eris_ifu_free_vector(&tmp_vec);
1640 // calc stddev of differences of distances between single traces
1641 if ((arc_tbl[i].fit_l != NULL) && (arc_tbl[i].fit_r != NULL)) {
1642 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_r);
1643 eris_ifu_vector_subtract(t, arc_tbl[i].fit_l);
1644 std = eris_ifu_vector_get_stdev(t);
1645 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-L STDEV
",i);
1646 keycomm = cpl_sprintf("[pix] right-left distance slitlet %2.2d
",i);
1647 if (!eris_ifu_is_nan_or_inf(std)) {
1648 cpl_propertylist_append_double((*qc)[i], keyname, std);
1650 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1652 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1656 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1657 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-L MEDIAN
",i);
1658 keycomm = cpl_sprintf("[pix] right-left distance median slitlet %2.2d
",i);
1659 if (!eris_ifu_is_nan_or_inf(median)) {
1660 cpl_propertylist_append_double((*qc)[i], keyname, median);
1662 cpl_propertylist_append_string((*qc)[i], "MEDIAN R-L
", "NaN
");
1664 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1668 // for the ease of stats: save the slit-width & y
1669 cpl_table_new_column(tbl, "slit_width
", CPL_TYPE_DOUBLE);
1670 tmp_vec = eris_ifu_vector_get_data(t);
1671 cpl_table_copy_data_double(tbl, "slit_width
", cpl_vector_get_data_const(tmp_vec));
1672 cpl_table_new_column(tbl, "y
", CPL_TYPE_DOUBLE);
1673 cpl_table_copy_data_double(tbl, "y
", cpl_vector_get_data_const(y));
1674 eris_ifu_free_vector(&tmp_vec);
1675 eris_ifu_free_ifu_vector(&t);
1677 if ((arc_tbl[i].fit_l != NULL) && (arc_tbl[i].fit_c != NULL)) {
1678 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c);
1679 eris_ifu_vector_subtract(t, arc_tbl[i].fit_l);
1680 std = eris_ifu_vector_get_stdev(t);
1681 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-L STDEV
",i);
1682 keycomm = cpl_sprintf("[pix] center-left distance stdev slitlet %2.2d
",i);
1683 if (!eris_ifu_is_nan_or_inf(std)) {
1684 cpl_propertylist_append_double((*qc)[i], keyname, std);
1686 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1688 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1691 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1692 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-L MEDIAN
",i);
1693 keycomm = cpl_sprintf("[pix] center-left distance median slitlet %2.2d
",i);
1694 if (!eris_ifu_is_nan_or_inf(median)) {
1695 cpl_propertylist_append_double((*qc)[i], keyname, median);
1697 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1699 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1702 eris_ifu_free_ifu_vector(&t);
1704 if ((arc_tbl[i].fit_c != NULL) && (arc_tbl[i].fit_r != NULL)) {
1705 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_r);
1706 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c);
1707 std = eris_ifu_vector_get_stdev(t);
1708 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-C STDEV
",i);
1709 keycomm = cpl_sprintf("[pix] right-center distance stdev slitlet %2.2d
",i);
1710 if (!eris_ifu_is_nan_or_inf(std)) {
1711 cpl_propertylist_append_double((*qc)[i], keyname, std);
1713 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1715 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1718 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1719 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-C MEDIAN
",i);
1720 keycomm = cpl_sprintf("[pix] right-center distance median slitlet %2.2d
",i);
1721 if (!eris_ifu_is_nan_or_inf(median)) {
1722 cpl_propertylist_append_double((*qc)[i], keyname, median);
1724 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1726 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1729 eris_ifu_free_ifu_vector(&t);
1731 if ((arc_tbl[i].fit_c != NULL) && (arc_tbl[i].fit_c_l != NULL)) {
1732 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c);
1733 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c_l);
1734 std = eris_ifu_vector_get_stdev(t);
1735 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-CL STDEV
",i);
1736 keycomm = cpl_sprintf("[pix] center-centerleft distance stdev slitlet %2.2d
",i);
1737 if (!eris_ifu_is_nan_or_inf(std)) {
1738 cpl_propertylist_append_double((*qc)[i], keyname, std);
1740 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1742 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1745 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1746 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-CL MEDIAN
",i);
1747 keycomm = cpl_sprintf("[pix] center-centerleft distance median slitlet %2.2d
",i);
1748 if (!eris_ifu_is_nan_or_inf(median)) {
1749 cpl_propertylist_append_double((*qc)[i], keyname, median);
1751 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1753 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1756 eris_ifu_free_ifu_vector(&t);
1758 if ((arc_tbl[i].fit_c_r != NULL) && (arc_tbl[i].fit_c != NULL)) {
1759 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c_r);
1760 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c);
1761 std = eris_ifu_vector_get_stdev(t);
1762 keyname = cpl_sprintf("ESO QC SLITLET%2.2d CR-C STDEV
",i);
1763 keycomm = cpl_sprintf("[pix] centerright-center distance stdev slitlet %2.2d
",i);
1764 if (!eris_ifu_is_nan_or_inf(std)) {
1765 cpl_propertylist_append_double((*qc)[i], keyname, std);
1767 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1769 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1772 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1773 keyname = cpl_sprintf("ESO QC SLITLET%2.2d CR-C MEDIAN
",i);
1774 keycomm = cpl_sprintf("[pix] centerright-center distance median slitlet %2.2d
",i);
1775 if (!eris_ifu_is_nan_or_inf(median)) {
1776 cpl_propertylist_append_double((*qc)[i], keyname, median);
1778 cpl_propertylist_append_string((*qc)[i], keyname, "NaN
");
1780 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1783 eris_ifu_free_ifu_vector(&t);
1786 cpl_table_save(tbl, NULL, (*qc)[i], ERIS_IFU_PRO_DIST_QC_FIT_FN, CPL_IO_EXTEND));
1788 eris_ifu_free_table(&tbl);
1789 } // end: i = SLITLET_CNT
1790 } // end: if (productDepth & 1)
1795 for (int j = 0; j < SLITLET_CNT; j++) {
1796 cpl_polynomial_delete(poly_u[j]); poly_u[j] = NULL;
1798 cpl_free(poly_u); poly_u = NULL;
1800 eris_ifu_free_table(minmax_borders);
1802 if (*qc != NULL && **qc != NULL) {
1803 for (int i = 0; i < SLITLET_CNT; i++) {
1804 eris_ifu_free_propertylist(&(*qc)[i]);
1808 cpl_free(**qc); **qc = NULL;
1811 eris_ifu_free_table(&dbg_polynomials);
1812 eris_ifu_free_bivector(&grid);
1813 eris_ifu_free_vector(&val_to_fit);
1814 eris_ifu_free_vector(&y);
1815 eris_ifu_free_ifu_vector(&y_wave);
1816 for (int i = 0; i < SLITLET_CNT; i++) {
1817 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_l);
1818 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c);
1819 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c_l);
1820 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c_r);
1821 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_r);
1823 cpl_free(arc_tbl); arc_tbl = NULL;
1844cpl_polynomial** eris_ifu_dist_calc_distortion_full(cpl_table **slit_edges,
1845 cpl_table **centers,
1847 cpl_boolean cut_off_left,
1848 cpl_boolean cut_off_right)
1867 const double *pwave_y = NULL,
1869 cpl_polynomial **poly_u = NULL;
1870 cpl_bivector *grid = NULL;
1871 cpl_vector *val_to_fit = NULL,
1873 eris_ifu_vector *y_wave = NULL,
1876 cpl_boolean triple_traces = FALSE;
1877 cpl_table *tbl = NULL,
1878 *dbg_polynomials = NULL;
1879 cpl_propertylist **pl = NULL;
1880 struct arcstruct *arc_tbl = NULL;
1882 cpl_ensure(slit_edges, CPL_ERROR_NULL_INPUT, NULL);
1883 cpl_ensure(centers, CPL_ERROR_NULL_INPUT, NULL);
1887 BRK_IF_NULL( dbg_polynomials = cpl_table_new(SLITLET_CNT));
1888 cpl_table_new_column(dbg_polynomials, ERIS_IFU_DIST_DBG_SLITLET, CPL_TYPE_INT);
1889 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_EDGE_LEFT, CPL_TYPE_DOUBLE, fit_order+1);
1890 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_EDGE_RIGHT, CPL_TYPE_DOUBLE, fit_order+1);
1891 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER_LEFT, CPL_TYPE_DOUBLE, fit_order+1);
1892 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER, CPL_TYPE_DOUBLE, fit_order+1);
1893 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER_RIGHT, CPL_TYPE_DOUBLE, fit_order+1);
1894 CHECK_ERROR_STATE();
1897 poly_u = cpl_calloc(SLITLET_CNT, sizeof(cpl_polynomial*)));
1899 if (cpl_table_get_ncol(centers[5]) > 2) {
1900 triple_traces = TRUE;
1904 cpl_propertylist_save(NULL, ERIS_IFU_PRO_DIST_QC_FIT_FN, CPL_IO_CREATE));
1907 arc_tbl = cpl_calloc(SLITLET_CNT, sizeof(struct arcstruct)));
1909 // calculate all slitlets taht are not cut off
1910 for (int i = 0; i < SLITLET_CNT; i++) {
1911 //cpl_msg_debug(cpl_func, "i: %d\n
", i);
1912 // get number of vertical traces (arcs) to process
1913 n_arcs = eris_ifu_distortion_get_narcs(i, triple_traces,
1914 cut_off_left, cut_off_right);
1915 // get number of detected wave_calib-lines
1916 n_calib_wave = (int) cpl_table_get_nrow(slit_edges[i]);
1917 // get number of centerpoints
1918 n_calib_cen = (int) cpl_table_get_nrow(centers[i]);
1920 // get y-coordinates
1922 pwave_y = cpl_table_get_data_double_const(
1923 slit_edges[i], "y_pos
"));
1925 pcenter_y = cpl_table_get_data_double_const(
1928 y_wave = eris_ifu_vector_new_wrap(n_calib_wave, pwave_y));
1930 y_cen = eris_ifu_vector_new_wrap(n_calib_cen, pcenter_y));
1932 // fit all edges (left, right, centers)
1933 if (!((i == 0) && cut_off_left)) {
1934 // process only if it is not the 1st slitlet and cutoff
1936 arc_tbl[i].fit_l = eris_ifu_dist_calc_distortion_fitedge(
1937 slit_edges[i], "edge_left
", y_wave,
1938 n_calib_wave, n_size, fit_order,
1939 i, dbg_polynomials));
1941 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1942 // process only if it is not the last slitlet and cutoff
1944 arc_tbl[i].fit_r = eris_ifu_dist_calc_distortion_fitedge(
1945 slit_edges[i], "edge_right
", y_wave,
1946 n_calib_wave, n_size, fit_order,
1947 i, dbg_polynomials));
1950 arc_tbl[i].fit_c = eris_ifu_dist_calc_distortion_fitedge(
1951 centers[i], "x
", y_cen,
1952 n_calib_cen, n_size, fit_order,
1953 i, dbg_polynomials));
1954 if (triple_traces) {
1955 if (!((i == 0) && cut_off_left)) {
1956 // process if it is not the 1st slitlet and not cutoff
1958 arc_tbl[i].fit_c_l = eris_ifu_dist_calc_distortion_fitedge(
1959 centers[i], "x_l
", y_cen,
1960 n_calib_cen, n_size, fit_order,
1961 i, dbg_polynomials));
1963 // if it is the last slitlet and cutoff, then
1964 // check first if, and how many, values are nan
1965 // If there are too many NaN's do nothing and copy the shape of c to c_l
1966 if (cpl_table_count_invalid(centers[i], "x_l
") <= 0.1 * n_calib_cen) {
1967 // calculate fitted edge only if less tahn 10% of the values are NaN
1969 arc_tbl[i].fit_c_l = eris_ifu_dist_calc_distortion_fitedge(
1970 centers[i], "x_l
", y_cen,
1971 n_calib_cen, n_size, fit_order,
1972 i, dbg_polynomials));
1976 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1977 // process if it is not the last slitlet and not cutoff
1979 arc_tbl[i].fit_c_r = eris_ifu_dist_calc_distortion_fitedge(
1980 centers[i], "x_r
", y_cen,
1981 n_calib_cen, n_size, fit_order,
1982 i, dbg_polynomials));
1984 // if it is the last slitlet and cutoff, then
1985 // check first if, and how many, values are nan
1986 // If there are too many NaN's do nothing and copy the shape of c to c_r
1987 if (cpl_table_count_invalid(centers[i], "x_r
") <= 0.1 * n_calib_cen) {
1988 // calculate fitted edge only if less than 10% of the values are NaN
1990 arc_tbl[i].fit_c_r = eris_ifu_dist_calc_distortion_fitedge(
1991 centers[i], "x_r
", y_cen,
1992 n_calib_cen, n_size, fit_order,
1993 i, dbg_polynomials));
1996 } // end: if (triple_traces)
1997 eris_ifu_free_ifu_vector(&y_wave);
1998 eris_ifu_free_ifu_vector(&y_cen);
1999 } // end: i = SLITLET_CNT
2002 pl = cpl_calloc(SLITLET_CNT, sizeof(cpl_propertylist*)));
2003 for (int i = 0; i < SLITLET_CNT; i++) {
2005 pl[i] = cpl_propertylist_new());
2008 // estimate positions of cut off edges with neighbouring slitlet width
2011 cpl_propertylist_append_string(pl[0],
2012 "EDGE L
", "artificial
"));
2013 if (arc_tbl[0].fit_l == NULL) {
2014 /* The leftmost edge of slitlet #0 is cut off. Therefore subtract the
2015 * width of slitlet #1 from the right edge of slitlet #0
2018 arc_tbl[0].fit_l = eris_ifu_vector_duplicate(arc_tbl[0].fit_r));
2020 eris_ifu_vector_subtract(arc_tbl[0].fit_l, arc_tbl[1].fit_r));
2022 eris_ifu_vector_add(arc_tbl[0].fit_l, arc_tbl[1].fit_l));
2024 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_l == NULL)) {
2025 /* The c_l-edge of slitlet #0 is cut off. Therefore subtract the
2026 * width of c-c_l of slitlet #31 to the left edge of slitlet #32
2029 arc_tbl[0].fit_c_l = eris_ifu_vector_duplicate(arc_tbl[0].fit_c));
2031 eris_ifu_vector_subtract(arc_tbl[0].fit_c_l, arc_tbl[1].fit_c));
2033 eris_ifu_vector_add(arc_tbl[0].fit_c_l, arc_tbl[1].fit_c_l));
2035 cut_off_left = CPL_FALSE;
2038 if (cut_off_right) {
2040 cpl_propertylist_append_string(pl[SLITLET_CNT-1],
2041 "EDGE R
", "artificial
"));
2042 if (arc_tbl[SLITLET_CNT-1].fit_r == NULL) {
2043 /* The rightmost edge of slitlet #32 is cut off. Therefore add the
2044 * width of slitlet #31 to the left edge of slitlet #32
2047 arc_tbl[SLITLET_CNT-1].fit_r = eris_ifu_vector_duplicate(arc_tbl[SLITLET_CNT-1].fit_l));
2049 eris_ifu_vector_add(arc_tbl[SLITLET_CNT-1].fit_r, arc_tbl[SLITLET_CNT-2].fit_r));
2051 eris_ifu_vector_subtract(arc_tbl[SLITLET_CNT-1].fit_r, arc_tbl[SLITLET_CNT-2].fit_l));
2053 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_r == NULL)) {
2054 /* The c_r-edge of slitlet #32 is cut off. Therefore add the
2055 * width of c_r-c of slitlet #31 to the left center edge of slitlet #32
2058 arc_tbl[SLITLET_CNT-1].fit_c_r = eris_ifu_vector_duplicate(arc_tbl[SLITLET_CNT-1].fit_c));
2060 eris_ifu_vector_add(arc_tbl[SLITLET_CNT-1].fit_c_r, arc_tbl[SLITLET_CNT-2].fit_c_r));
2062 eris_ifu_vector_subtract(arc_tbl[SLITLET_CNT-1].fit_c_r, arc_tbl[SLITLET_CNT-2].fit_c));
2064 cut_off_right = CPL_FALSE;
2067 const char *fn = "eris_ifu_distortion_dbg_calcdistor_grid_xy_val2fit.fits
";
2068 if (productDepth & 4) {
2069 eris_ifu_save_vector_dbg(NULL, fn, CPL_IO_CREATE, NULL);
2071 // estimate mean origin positions of the arc-lines and calculate
2072 // target positions for the edges, fill the grid, perform polynomial-fit
2073 for (int i = 0; i < SLITLET_CNT; i++) {
2074 // get number of vertical traces (arcs) to process
2075 n_arcs = eris_ifu_distortion_get_narcs(i, triple_traces,
2076 cut_off_left, cut_off_right);
2079 * estimate mean origin positions of the arc-lines (left, center, right)
2081 o_l = eris_ifu_vector_get_mean(arc_tbl[i].fit_l);
2082 o_c = eris_ifu_vector_get_mean(arc_tbl[i].fit_c);
2083 o_r = eris_ifu_vector_get_mean(arc_tbl[i].fit_r);
2084 if (triple_traces) {
2085 o_c_l = eris_ifu_vector_get_mean(arc_tbl[i].fit_c_l);
2086 o_c_r = eris_ifu_vector_get_mean(arc_tbl[i].fit_c_r);
2090 * from these estimates define target positions for the arc-lines (left, center, right)
2092 // left+right edge are simple: a slitlet should have 64pix width
2093 t_l = eris_ifu_distortion_target_left_edge(i);
2094 t_r = eris_ifu_distortion_target_right_edge(i);
2096 // the center positions are calculated with the sentence of three...
2097 t_c = (int)((o_c-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
2098 if (triple_traces) {
2099 t_c_l = (int)((o_c_l-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
2100 t_c_r = (int)((o_c_r-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
2103// cpl_msg_debug(cpl_func, "i: %02d, o_l: %7.2f, o_c_l: %7.2f,
"
2104// "o_c: %7.2f, o_c_r: %7.2f, o_r: %7.2f
",
2105// i, o_l, o_c_l, o_c, o_c_r, o_r);
2106// cpl_msg_debug(cpl_func, " t_l: %04d , t_c_l: %04d ,
"
2107// " t_c: %04d , t_c_r: %04d , t_r: %04d
",
2108// t_l, t_c_l, t_c, t_c_r, t_r);
2109 // create grid to fit to (contains target-coordinates)
2111 grid = cpl_bivector_new(n_arcs * n_size));
2113 // create vector with values to fit (contains origin-coordinates)
2115 val_to_fit = cpl_vector_new(n_arcs * n_size));
2118 // fill in left edge
2120 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_l, val_to_fit,
2121 t_l, n_size, arc_cnt++));
2122 if (triple_traces) {
2125 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c_l, val_to_fit,
2126 t_c_l, n_size, arc_cnt++));
2130 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c, val_to_fit,
2131 t_c, n_size, arc_cnt++));
2132 if (triple_traces) {
2135 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c_r, val_to_fit,
2136 t_c_r, n_size, arc_cnt++));
2138 // fill in right edge
2140 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_r, val_to_fit,
2141 t_r, n_size, arc_cnt++));
2143 if (productDepth & 4) {
2144// cpl_propertylist *pl = NULL;
2146// pl = cpl_propertylist_new());
2147 char *extname = NULL;
2149 extname = cpl_sprintf("xVector Sx_%02d
", i+1);
2150 cpl_propertylist_update_string(pl[i], "EXTNAME
", extname);
2151 eris_ifu_free_string(&extname);
2152 eris_ifu_save_vector_dbg(cpl_bivector_get_x(grid), fn, CPL_IO_EXTEND, pl[i]);
2154 extname = cpl_sprintf("yVector Sx_%02d
", i+1);
2155 cpl_propertylist_update_string(pl[i], "EXTNAME
", extname);
2156 eris_ifu_free_string(&extname);
2157 eris_ifu_save_vector_dbg(cpl_bivector_get_y(grid), fn, CPL_IO_EXTEND, pl[i]);
2159 extname = cpl_sprintf("val2fit Sx_%02d
", i+1);
2160 cpl_propertylist_update_string(pl[i], "EXTNAME
", extname);
2161 eris_ifu_free_string(&extname);
2162 eris_ifu_save_vector_dbg(val_to_fit, fn, CPL_IO_EXTEND, pl[i]);
2164// eris_ifu_free_propertylist(&pl);
2167 /* Apply the fitting */
2169 poly_u[i] = eris_ifu_dist_poly_fit_2d_create(grid, val_to_fit, NULL));
2171 eris_ifu_free_bivector(&grid);
2172 eris_ifu_free_vector(&val_to_fit);
2173 } // end: i = SLITLET_CNT
2175 // save values of all fitted edges and some stats
2176 if (productDepth & 2) {
2177 for (int i = 0; i < SLITLET_CNT; i++) {
2179 tbl = cpl_table_new(n_size));
2180 if (arc_tbl[i].fit_l != NULL) {
2182 cpl_table_new_column(tbl, "l
", CPL_TYPE_DOUBLE));
2184 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_l));
2186 cpl_table_copy_data_double(tbl, "l
", cpl_vector_get_data_const(tt)));
2187 eris_ifu_free_vector(&tt);
2189 if (arc_tbl[i].fit_c_l != NULL) {
2191 cpl_table_new_column(tbl, "c_l
", CPL_TYPE_DOUBLE));
2193 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_c_l));
2195 cpl_table_copy_data_double(tbl, "c_l
", cpl_vector_get_data_const(tt)));
2196 eris_ifu_free_vector(&tt);
2198 if (arc_tbl[i].fit_c != NULL) {
2200 cpl_table_new_column(tbl, "c
", CPL_TYPE_DOUBLE));
2202 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_c));
2204 cpl_table_copy_data_double(tbl, "c
", cpl_vector_get_data_const(tt)));
2205 eris_ifu_free_vector(&tt);
2207 if (arc_tbl[i].fit_c_r != NULL) {
2209 cpl_table_new_column(tbl, "c_r
", CPL_TYPE_DOUBLE));
2211 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_c_r));
2213 cpl_table_copy_data_double(tbl, "c_r
", cpl_vector_get_data_const(tt)));
2214 eris_ifu_free_vector(&tt);
2216 if (arc_tbl[i].fit_r != NULL) {
2218 cpl_table_new_column(tbl, "r
", CPL_TYPE_DOUBLE));
2220 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_r));
2222 cpl_table_copy_data_double(tbl, "r
", cpl_vector_get_data_const(tt)));
2223 eris_ifu_free_vector(&tt);
2226 // calc stddev of differences of distances between single traces
2227 if ((arc_tbl[i].fit_l != NULL) && (arc_tbl[i].fit_r != NULL)) {
2228 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_r);
2230 eris_ifu_vector_subtract(t, arc_tbl[i].fit_l));
2231 std = eris_ifu_vector_get_stdev(t);
2232 if (!eris_ifu_is_nan_or_inf(std)) {
2234 cpl_propertylist_append_double(pl[i], "STDEV R-L
", std));
2237 cpl_propertylist_append_string(pl[i], "STDEV R-L
", "NaN
"));
2240 // for the ease of stats: save the slit-width
2242 cpl_table_new_column(tbl, "slit_width
", CPL_TYPE_DOUBLE));
2244 tt = eris_ifu_vector_get_data(t));
2246 cpl_table_copy_data_double(tbl, "slit_width
", cpl_vector_get_data_const(tt)));
2248 eris_ifu_free_vector(&tt);
2249 eris_ifu_free_ifu_vector(&t);
2251 if ((arc_tbl[i].fit_l != NULL) && (arc_tbl[i].fit_c != NULL)) {
2252 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c);
2254 eris_ifu_vector_subtract(t, arc_tbl[i].fit_l));
2255 std = eris_ifu_vector_get_stdev(t);
2256 if (!eris_ifu_is_nan_or_inf(std)) {
2258 cpl_propertylist_append_double(pl[i], "STDEV C-L
", std));
2261 cpl_propertylist_append_string(pl[i], "STDEV C-L
", "NaN
"));
2263 eris_ifu_free_ifu_vector(&t);
2265 if ((arc_tbl[i].fit_c != NULL) && (arc_tbl[i].fit_r != NULL)) {
2266 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_r);
2268 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c));
2269 std = eris_ifu_vector_get_stdev(t);
2270 if (!eris_ifu_is_nan_or_inf(std)) {
2272 cpl_propertylist_append_double(pl[i], "STDEV R-C
", std));
2275 cpl_propertylist_append_string(pl[i], "STDEV R-C
", "NaN
"));
2277 eris_ifu_free_ifu_vector(&t);
2279 if ((arc_tbl[i].fit_c != NULL) && (arc_tbl[i].fit_c_l != NULL)) {
2280 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c);
2282 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c_l));
2283 std = eris_ifu_vector_get_stdev(t);
2284 if (!eris_ifu_is_nan_or_inf(std)) {
2286 cpl_propertylist_append_double(pl[i], "STDEV C-CL
", std));
2289 cpl_propertylist_append_string(pl[i], "STDEV C-CL
", "NaN
"));
2291 eris_ifu_free_ifu_vector(&t);
2293 if ((arc_tbl[i].fit_c_r != NULL) && (arc_tbl[i].fit_c != NULL)) {
2294 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c_r);
2296 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c));
2297 std = eris_ifu_vector_get_stdev(t);
2298 if (!eris_ifu_is_nan_or_inf(std)) {
2300 cpl_propertylist_append_double(pl[i], "STDEV CR-C
", std));
2303 cpl_propertylist_append_string(pl[i], "STDEV CR-C
", "NaN
"));
2305 eris_ifu_free_ifu_vector(&t);
2307 if ((productDepth & 2) != 0) {
2309 cpl_table_save(tbl, NULL, pl[i], ERIS_IFU_PRO_DIST_QC_FIT_FN, CPL_IO_EXTEND));
2312 eris_ifu_free_table(&tbl);
2313 } // end: i = SLITLET_CNT
2314 } // end: if (productDepth & 2)
2319 for (int j = 0; j < SLITLET_CNT; j++) {
2320 cpl_polynomial_delete(poly_u[j]); poly_u[j] = NULL;
2322 cpl_free(poly_u); poly_u = NULL;
2325 eris_ifu_free_bivector(&grid);
2326 eris_ifu_free_vector(&val_to_fit);
2327 eris_ifu_free_ifu_vector(&y_wave);
2328 for (int i = 0; i < SLITLET_CNT; i++) {
2329 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_l);
2330 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c);
2331 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c_l);
2332 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c_r);
2333 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_r);
2336 for (int i = 0; i < SLITLET_CNT; i++) {
2337 eris_ifu_free_propertylist(&pl[i]);
2340 cpl_free(arc_tbl); arc_tbl = NULL;
2341 cpl_free(pl); pl = NULL;
2363eris_ifu_vector* eris_ifu_dist_calc_distortion_fitedge(const cpl_table *edge,
2364 const char *col_name,
2365 const eris_ifu_vector *y,
2372 const double *px = NULL;
2373 double *pfit_par = NULL;
2374 eris_ifu_vector *x = NULL,
2376 cpl_vector *fit_par = NULL;
2377 cpl_array *tmp_array = NULL;
2379 cpl_ensure(edge, CPL_ERROR_NULL_INPUT, NULL);
2380 cpl_ensure(col_name, CPL_ERROR_NULL_INPUT, NULL);
2381 cpl_ensure(y, CPL_ERROR_NULL_INPUT, NULL);
2382 cpl_ensure(n_calib > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2383 cpl_ensure(n_size > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2384 cpl_ensure(fit_order > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2389 px = cpl_table_get_data_double_const(edge, col_name));
2392 x = eris_ifu_vector_new_wrap(n_calib, px));
2394 // fit polynomial to edge
2396 fit_par = eris_ifu_polyfit_edge(y, x, fit_order));
2397 eris_ifu_free_ifu_vector(&x);
2400 pfit_par = cpl_vector_get_data(fit_par));
2402 // save polynomials to table to support remote debugging
2403 tmp_array = cpl_array_wrap_double(pfit_par, cpl_vector_get_size(fit_par));
2404 cpl_table_set_int(dbg_tbl, ERIS_IFU_DIST_DBG_SLITLET, slitlet, slitlet);
2405 cpl_table_set_array(dbg_tbl, col_name, slitlet, tmp_array);
2406 cpl_array_unwrap(tmp_array);
2407 CHECK_ERROR_STATE();
2409 // create vector with fitted values
2411 fit = eris_ifu_vector_new(n_size));
2412 for (int j = 0; j < n_size; j++) {
2413 int yy = eris_ifu_distortion_calc_y(n_size, j);
2414 double v = pfit_par[0] +
2416 pfit_par[2] * pow(yy, 2);
2417// + pfit_par[3] * pow(yy, 3);
2419 eris_ifu_vector_set(fit, j, v));
2425 eris_ifu_free_ifu_vector(&fit);
2427 eris_ifu_free_vector(&fit_par);
2449cpl_error_code eris_ifu_dist_calc_distortion_fillgrid(cpl_bivector *grid,
2450 const eris_ifu_vector *data,
2451 cpl_vector *val_to_fit,
2456 cpl_error_code err = CPL_ERROR_NONE;
2457 double *pgridx = NULL,
2459 *pval_to_fit = NULL;
2461 cpl_ensure_code(grid, CPL_ERROR_NULL_INPUT);
2462 cpl_ensure_code(data, CPL_ERROR_NULL_INPUT);
2463 cpl_ensure_code(val_to_fit, CPL_ERROR_NULL_INPUT);
2467 cpl_ensure_code(x_pos >= -64, CPL_ERROR_ILLEGAL_INPUT);
2468 cpl_ensure_code(arc_cnt >= 0, CPL_ERROR_ILLEGAL_INPUT);
2469 cpl_ensure_code(n_size >= 0, CPL_ERROR_ILLEGAL_INPUT);
2474 pgridx = cpl_bivector_get_x_data(grid));
2476 pgridy = cpl_bivector_get_y_data(grid));
2478 pval_to_fit = cpl_vector_get_data(val_to_fit));
2480 for (int j = arc_cnt*n_size; j < (arc_cnt+1)*n_size; j++) {
2481 ASSURE(j < cpl_bivector_get_size(grid),
2482 CPL_ERROR_ILLEGAL_INPUT,
2485 int jj = j % n_size;
2487 // same target-x for all y-positions
2491 pgridy[j] = eris_ifu_distortion_calc_y(n_size, jj);
2493 // insert fitted x-value at y-position
2494 if (eris_ifu_vector_is_rejected(data, jj)) {
2495 pval_to_fit[j] = NAN;
2497 pval_to_fit[j] = eris_ifu_vector_get(data, jj);
2504 err = cpl_error_get_code();
2526cpl_polynomial* eris_ifu_dist_poly_fit_2d_create(cpl_bivector *xy_pos,
2527 const cpl_vector *values,
2531 double rechisq = 0.,
2533 cpl_size degree = NS_FIT_DEGREE;
2534 cpl_matrix *samppos2d = NULL;
2535 cpl_vector *fitresidual = NULL;
2536 cpl_polynomial *fit2d = NULL;
2538 typedef double* (*get_data)(cpl_bivector*);
2539 get_data data_extractor[2] = { &cpl_bivector_get_x_data,
2540 &cpl_bivector_get_y_data };
2542 cpl_ensure(xy_pos, CPL_ERROR_NULL_INPUT, NULL);
2543 cpl_ensure(values, CPL_ERROR_NULL_INPUT, NULL);
2544 cpl_ensure(degree > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2548 xy_size = (int) cpl_bivector_get_size(xy_pos);
2549 CHECK_ERROR_STATE();
2552 fit2d = cpl_polynomial_new(2));
2554 samppos2d = cpl_matrix_new(2, xy_size));
2556 for (int i = 0; i < 2; i++) {
2557 for (int j = 0; j < xy_size; j++) {
2558 value = data_extractor[i](xy_pos)[j];
2560 cpl_matrix_set(samppos2d, i, j, value));
2563 const cpl_size maxdeg2d[] = {2,3};
2565 cpl_polynomial_fit(fit2d, samppos2d, NULL, values, NULL, CPL_TRUE,
2568// cpl_polynomial_fit(fit2d, samppos2d, NULL, values, NULL, CPL_FALSE,
2572 fitresidual = cpl_vector_new(xy_size));
2574 cpl_vector_fill_polynomial_fit_residual(fitresidual, values, NULL,
2575 fit2d, samppos2d, &rechisq));
2577 *msee = cpl_vector_product(fitresidual, fitresidual)
2578 / (double) cpl_vector_get_size(fitresidual);
2584 eris_ifu_free_polynomial(&fit2d);
2587 eris_ifu_free_matrix(&samppos2d);
2588 eris_ifu_free_vector(&fitresidual);
2611cpl_error_code eris_ifu_dist_save_distortion(cpl_polynomial **poly2d,
2612 const cpl_table *minmax_borders,
2614 cpl_frameset *frameset,
2615 const cpl_parameterlist *parlist,
2616 cpl_propertylist **qc)
2620// char key_name[FILE_NAME_SZ];
2621 cpl_size max_degree;
2622 cpl_size coef_pow[2];
2623 cpl_table *poly_tbl = NULL;
2624 cpl_error_code err = CPL_ERROR_NONE;
2626 cpl_ensure_code(poly2d, CPL_ERROR_NULL_INPUT);
2627 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
2628 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
2632 for (int i = 0; i < SLITLET_CNT; i++) {
2633 if (poly2d[i] == NULL) {
2634 cpl_propertylist_save(NULL, fn, CPL_IO_EXTEND);
2636 max_degree = cpl_polynomial_get_degree(poly2d[i]);
2638 poly_tbl = cpl_table_new(max_degree * max_degree));
2640 cpl_table_new_column(poly_tbl,"degx
", CPL_TYPE_INT));
2642 cpl_table_new_column(poly_tbl,"degy
", CPL_TYPE_INT));
2644 cpl_table_new_column(poly_tbl,"coeff
", CPL_TYPE_DOUBLE));
2647 for (cpl_size cy=0; cy < max_degree; cy++) {
2648 for (cpl_size cx=0; cx < max_degree; cx++) {
2651 coeff = cpl_polynomial_get_coeff(poly2d[i], coef_pow);
2652 if (fabs(coeff) > 1e-30) { //Here DBL_ZERO_TOLERANCE 1e-10 is too high
2654 cpl_table_set_int(poly_tbl,"degx
",tx,(int) cx));
2656 cpl_table_set_int(poly_tbl,"degy
",tx,(int) cy));
2658 cpl_table_set_double(poly_tbl,"coeff
", tx,
2665 cpl_table_set_size(poly_tbl, tx));
2668// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 0, 0);
2670// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][0],
2671// "Polynomial distortion coefficient
"));
2673// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 1,0);
2675// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[1][0],
2676// "Polynomial distortion coefficient
"));
2678// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 0, 1);
2680// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][1],
2681// "Polynomial distortion coefficient
"));
2683// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 1, 1);
2685// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[1][1],
2686// "Polynomial distortion coefficient
"));
2688// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 2, 0);
2690// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[2][0],
2691// "Polynomial distortion coefficient
"));
2693// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 0, 2);
2695// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][2],
2696// "Polynomial distortion coefficient
"));
2698// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 2, 1);
2700// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[2][1],
2701// "Polynomial distortion coefficient
"));
2703// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
", "QC COEFF
", 1, 2);
2705// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[1][2],
2706// "Polynpoly2domial distortion coefficient
"));
2708// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
","QC COEFF
", 3, 0);
2710// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[3][0],
2711// "Polynomial distortion coefficient
"));
2713// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d
","QC COEFF
", 0, 3);
2715// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][3],
2716// "Polynomial distortion coefficient
"));
2718// xshift = eris_ifu_dist_compute_shift( x_c, y_c,
2719// pcf[0][0], pcf[1][0], pcf[0][1],
2720// pcf[1][1], pcf[2][0], pcf[0][2],
2721// pcf[2][1], pcf[1][2], pcf[3][0], pcf[0][3]);
2723// eris_ifu_dist_qclog_add_double(qc[i], "QC XSHIFT CC
", xshift,
2724// "X shift in x_c,y_c
"));
2726// xshift = eris_ifu_dist_compute_shift( x_l, y_l,
2727// pcf[0][0], pcf[1][0], pcf[0][1],
2728// pcf[1][1], pcf[2][0], pcf[0][2],
2729// pcf[2][1], pcf[1][2], pcf[3][0], pcf[0][3]);
2731// eris_ifu_dist_qclog_add_double(qc[i], "QC XSHIFT LL
", xshift,
2732// "X shift in x_l,y_l
"));
2734// xshift = eris_ifu_dist_compute_shift(x_l,y_u,pcf[0][0],pcf[1][0],pcf[0][1],
2735// pcf[1][1],pcf[2][0],pcf[0][2],
2736// pcf[2][1],pcf[1][2],pcf[3][0],pcf[0][3]);
2738// eris_ifu_dist_qclog_add_double(qc[i],"QC XSHIFT UL
",xshift,
2739// "X shift in x_l,y_u
"));
2741// xshift = eris_ifu_dist_compute_shift(x_u,y_u,pcf[0][0],pcf[1][0],pcf[0][1],
2742// pcf[1][1],pcf[2][0],pcf[0][2],
2743// pcf[2][1],pcf[1][2],pcf[3][0],pcf[0][3]);
2745// eris_ifu_dist_qclog_add_double(qc[i],"QC XSHIFT UR
",xshift,
2746// "X shift in x_u,y_u
"));
2748// xshift = eris_ifu_dist_compute_shift(x_u,y_l,pcf[0][0],pcf[1][0],pcf[0][1],
2749// pcf[1][1],pcf[2][0],pcf[0][2],
2750// pcf[2][1],pcf[1][2],pcf[3][0],pcf[0][3]);
2752// eris_ifu_dist_qclog_add_double(qc[i],"QC XSHIFT LR
",xshift,
2753// "X shift in x_u,y_l
"));
2755 extname = cpl_sprintf("SLITLET%2.2d
",i);
2756 cpl_propertylist_append_string(qc[i],"EXTNAME
",extname);
2759 eris_ifu_save_table(frameset, NULL, parlist, frameset, NULL,
2760 REC_NAME_DISTORTION,
2761 ERIS_IFU_PRO_DIST_DISTORTION,
2767 cpl_table_save(poly_tbl, NULL, qc[i], fn, CPL_IO_EXTEND));
2770 eris_ifu_free_table(&poly_tbl);
2771 } // if (poly2d[ii] != NULL)
2772 } // end: i = SLITLET_CNT
2774 cpl_propertylist* ext = cpl_propertylist_new();
2775 extname = cpl_sprintf("SLITLET%2.2d
",SLITLET_CNT);
2776 cpl_propertylist_append_string(ext,"EXTNAME
",extname);
2777 // save minmax borders as well
2779 cpl_table_save(minmax_borders, NULL, ext, fn, CPL_IO_EXTEND));
2780 cpl_propertylist_delete(ext);
2786 err = cpl_error_get_code();
2805hdrl_image* eris_ifu_dist_warp_image_full(const hdrl_image *hdrl_img_in,
2806 cpl_polynomial **poly_u,
2810 cpl_image *img_warped = NULL,
2811 *img_warped_extr = NULL;
2812 hdrl_image *hdrl_img_warped = NULL,
2813 *hdrl_img_warped_extr = NULL;
2814 cpl_polynomial *poly_v = NULL;
2817 cpl_ensure(hdrl_img_in, CPL_ERROR_NULL_INPUT, NULL);
2818 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2823 poly_v = cpl_polynomial_new(2));
2828 cpl_polynomial_set_coeff(poly_v, pows, 0.0));
2832 cpl_polynomial_set_coeff(poly_v, pows, 1.0));
2835 hdrl_img_warped = hdrl_image_new(hdrl_image_get_size_x(hdrl_img_in),
2836 hdrl_image_get_size_y(hdrl_img_in)));
2839 img_warped = hdrl_image_get_image(hdrl_img_warped));
2841 for (int i = 0; i < SLITLET_CNT; i++) {
2842 if (poly_u[i] != NULL) {
2843// cpl_msg_info(cpl_func, "Warp slitlet #%02d
", i+1);
2846 hdrl_img_warped_extr = eris_ifu_warp_polynomial_image(hdrl_img_in,
2847 poly_u[i], poly_v));
2849 // target left + right edge
2850 int t_l = eris_ifu_distortion_target_left_edge(i),
2851 t_r = eris_ifu_distortion_target_right_edge(i);
2853 img_warped_extr = hdrl_image_get_image(hdrl_img_warped_extr));
2855 if (productDepth & 8) {
2856 // save warped intermediate images uncut
2857 fn = cpl_sprintf("eris_ifu_distortion_dbg_warp_out_%02d.fits
", i+1);
2859 eris_ifu_save_image_dbg(img_warped_extr, fn,
2860 CPL_IO_CREATE, NULL));
2864 // set to zero left of slitlet (except for first slitlet)
2866 cpl_image_fill_window(img_warped_extr, 1, 1, t_l,
2867 ERIS_IFU_DETECTOR_SIZE_Y, 0.));
2869 if (i != SLITLET_CNT-1) {
2870 // set to zero right of slitlet (except for last slitlet)
2872 cpl_image_fill_window(img_warped_extr, t_r+2, 1,
2873 ERIS_IFU_DETECTOR_SIZE_X,
2874 ERIS_IFU_DETECTOR_SIZE_Y, 0.));
2877 if (productDepth & 8) {
2878 // save warped intermediate images cut
2880 eris_ifu_save_image_dbg(img_warped_extr, fn,
2881 CPL_IO_EXTEND, NULL));
2882 cpl_free(fn); fn = NULL;
2886 cpl_image_add(img_warped, img_warped_extr));
2888 eris_ifu_free_hdrl_image(&hdrl_img_warped_extr);
2890 } // end: i = SLITLET_CNT
2895 eris_ifu_free_hdrl_image(&hdrl_img_warped);
2898 eris_ifu_free_polynomial(&poly_v);
2900 return hdrl_img_warped;
2923hdrl_image* eris_ifu_dist_warp_slitlet(const hdrl_image *imgIn,
2924 const cpl_polynomial *poly_u,
2925 const cpl_polynomial *poly_v,
2932 hdrl_image *imgOutSlit = NULL,
2934 *imgOutSlitTrim = NULL;
2936 cpl_ensure(imgIn, CPL_ERROR_NULL_INPUT, NULL);
2937 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2938 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2943 // get left and right nominal border of slitlet
2944 llx = (int)(l_min)+1;
2945 urx = (int)(r_max)+1;
2947 if ((llx > 0) && (urx <= ERIS_IFU_DETECTOR_SIZE_X)) {
2949 imgInSlit = hdrl_image_extract(imgIn,
2951 urx, ERIS_IFU_DETECTOR_SIZE_Y));
2954 imgInSlit = hdrl_image_new(urx-llx+1, ERIS_IFU_DETECTOR_SIZE_Y));
2955 // mask all pixel as bad, the good ones will be flagged later
2958 tmpMask = cpl_mask_threshold_image_create(
2959 hdrl_image_get_image(imgInSlit),-1,1));
2960 hdrl_image_reject_from_mask(imgInSlit, tmpMask);
2961 cpl_mask_delete(tmpMask);
2965 tmpImg = hdrl_image_extract(imgIn,
2966 1, 1, urx, ERIS_IFU_DETECTOR_SIZE_Y));
2967 int pos1 = -llx + 2;
2969 hdrl_image_copy(imgInSlit,tmpImg, pos1, 1));
2972 tmpImg = hdrl_image_extract(imgIn,
2973 llx, 1, ERIS_IFU_DETECTOR_SIZE_X, ERIS_IFU_DETECTOR_SIZE_Y));
2975 hdrl_image_copy(imgInSlit,tmpImg, 1, 1));
2977 eris_ifu_free_hdrl_image(&tmpImg);
2981 imgOutSlit = eris_ifu_warp_polynomial_image(imgInSlit,
2984 if (hdrl_image_get_size_x(imgOutSlit) > SLITLET_WIDTH) {
2985 // extract left 64 pixels of slitlet (all data to the right is invalid)
2987 imgOutSlitTrim = hdrl_image_extract(imgOutSlit,
2990 ERIS_IFU_DETECTOR_SIZE_Y));
2992 // if slitlet is less than 64 pix wide, paste it into a slitlet of 64pix width
2993 cpl_msg_warning(cpl_func, "Slitlet #%d: width only %d pix !!!
", slitletNr+1, (int)hdrl_image_get_size_x(imgOutSlit));
2995 imgOutSlitTrim = hdrl_image_new(SLITLET_WIDTH, ERIS_IFU_DETECTOR_SIZE_Y));
2996 // will be aligned to the right side --> better
2997 int offset = SLITLET_WIDTH - (int) hdrl_image_get_size_x(imgOutSlit);
2998 // will be aligned to the left side --> worse
3001 eris_ifu_image_add_slit(imgOutSlitTrim, imgOutSlit, offset));
3007 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
3010 eris_ifu_free_hdrl_image(&imgOutSlit);
3011 eris_ifu_free_hdrl_image(&imgInSlit);
3013 return imgOutSlitTrim;
3034hdrl_image* eris_ifu_dist_warp_image(const hdrl_image *imgIn,
3035 cpl_polynomial **poly_u,
3036 const cpl_table *borders)
3040 cpl_polynomial *poly_v = NULL;
3041 hdrl_image *imgOut = NULL,
3042 *imgOutSlitTrim = NULL;
3044 cpl_ensure(imgIn, CPL_ERROR_NULL_INPUT, NULL);
3045 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
3046 cpl_ensure(borders, CPL_ERROR_NULL_INPUT, NULL);
3051 poly_v = cpl_polynomial_new(2));
3052 pows[0] = 0; pows[1] = 0;
3054 cpl_polynomial_set_coeff(poly_v, pows, 0.0));
3055 pows[0] = 0; pows[1] = 1;
3057 cpl_polynomial_set_coeff(poly_v, pows, 1.0));
3060 imgOut = hdrl_image_new(hdrl_image_get_size_x(imgIn),
3061 hdrl_image_get_size_y(imgIn)));
3063 for (int i = 0; i < SLITLET_CNT; i++) {
3064 if (poly_u[i] != NULL) {
3065// cpl_msg_debug(cpl_func, "Warp slitlet #%02d
", i+1);
3067 // Extract, warp and trim slitlet
3068 // (can be parallelized)
3070 imgOutSlitTrim = eris_ifu_dist_warp_slitlet(imgIn,
3073 cpl_table_get_double(borders, ERIS_IFU_POLY_EDGE_L, i, &tmp),
3074 cpl_table_get_double(borders, ERIS_IFU_POLY_EDGE_R, i, &tmp),
3077 // add- in slitlet to synthetic full warped image
3078 // (can be parallelized)
3080 eris_ifu_image_add_slit(imgOut,
3082 eris_ifu_distortion_target_left_edge(i)));
3084 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
3087 } // end: i = SLITLET_CNT
3092 eris_ifu_free_hdrl_image(&imgOut);
3094 eris_ifu_free_polynomial(&poly_v);
3095 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
3119hdrl_image* eris_ifu_dist_warp_bpm(const hdrl_image *bpmIn,
3120 cpl_polynomial **poly_u,
3121 const cpl_table *borders,
3122 productDepthType productDepth)
3126 cpl_polynomial *poly_v = NULL;
3127 hdrl_image *bpmOut = NULL,
3128 *imgOutSlitTrim = NULL;
3130 cpl_ensure(bpmIn, CPL_ERROR_NULL_INPUT, NULL);
3131 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
3132 cpl_ensure(borders, CPL_ERROR_NULL_INPUT, NULL);
3134 /* Create contribution map */
3135 cpl_size size_x = hdrl_image_get_size_x(bpmIn);
3136 cpl_size size_y = hdrl_image_get_size_y(bpmIn);
3138 hdrl_image *col_hmap = hdrl_image_new(size_x, size_y);
3140 //Initialize each pixel to its column number; start from 1.
3141 for (cpl_size i = 1; i <= size_x; i++){
3143 col_num.data = i * 1.0;
3144 col_num.error = 0.0;
3145 for (cpl_size j = 1; j <= size_y; j++){
3146 hdrl_image_set_pixel(col_hmap, i, j,col_num);
3149 if (productDepth >= PD_DEBUG) {
3150 eris_ifu_save_hdrl_image_dbg(col_hmap, "eris_ifu_distortion_dbg_col_hmap
", 1, NULL);
3152 poly_v = cpl_polynomial_new(2);
3153 pows[0] = 0; pows[1] = 0;
3154 cpl_polynomial_set_coeff(poly_v, pows, 0.0);
3155 pows[0] = 0; pows[1] = 1;
3156 cpl_polynomial_set_coeff(poly_v, pows, 1.0);
3158 /* Warp the contribution map */
3159 hdrl_image *col_hmap_warped = hdrl_image_new(size_x, size_y);
3160 for (int i = 0; i < SLITLET_CNT; i++) {
3161 // Extract, warp and trim slitlet
3162 imgOutSlitTrim = eris_ifu_dist_warp_slitlet(col_hmap,
3165 cpl_table_get_double(borders, ERIS_IFU_POLY_EDGE_L, i, &tmp),
3166 cpl_table_get_double(borders, ERIS_IFU_POLY_EDGE_R, i, &tmp),
3169 // add-in slitlet to synthetic full warped image
3170 eris_ifu_image_add_slit(col_hmap_warped,
3172 eris_ifu_distortion_target_left_edge(i));
3174 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
3177 hdrl_image_delete(col_hmap);
3179 if (productDepth >= PD_DEBUG) {
3180 eris_ifu_save_hdrl_image_dbg(col_hmap_warped, "eris_ifu_distortion_dbg_col_hmap_warped
", 1, NULL);
3183 /* Interpolate the bpm according to the contribution*/
3184 // TODO: do this on slitlet-wise, do mask columns beyond l_max, r_max.
3185 bpmOut = hdrl_image_new(size_x, size_y);
3187 cpl_size col_n_0 = 0;
3188 /* TODO: AMO: limit the loop to SLITLET_CNT -1 as the last iteration generates infinite loop processing science data */
3189 for (cpl_size k = 0; k < SLITLET_CNT; k++){
3190 if (k + 1 == 1) //slitlet 1
3192 else if (k + 1 == 2)
3194 else if (k + 1== 10)
3197 slitwidth = SLITLET_WIDTH;
3199 for (cpl_size y = 1; y <= size_y; y++){
3200 bool fake_col_n_0 = false;
3201 for (cpl_size x = 1; x <= SLITLET_WIDTH; x++){
3202 if (x >= SLITLET_WIDTH/2) {
3203 // We are already at the right side of the slitlet and don't expect that there will
3204 // be any bad pixels/zero- or NaN-values at the left border.
3205 // But there could still be such bad pixels at the right side. In this case we WILL NOT calculate a fake_col_n_0.
3206 // So we set it to true and we will step over the calculation of it
3207 fake_col_n_0 = true;
3209 hdrl_value pix_contr = hdrl_image_get_pixel(col_hmap_warped, x+k*SLITLET_WIDTH, y, NULL);
3210 cpl_size col_n = (cpl_size) pix_contr.data;
3211 double contri_n = pix_contr.data - col_n;
3212 if (((pix_contr.data == 0) || hdrl_image_is_rejected(col_hmap_warped, x+k*SLITLET_WIDTH, y)) && !fake_col_n_0) {
3214 // try to extrapolate a reasonable col_n_0
3215 // go as log to the right until we get a valid pixel, keep this value
3216 // get the pixel right of this one, subtract and then subtract as often
3218 hdrl_value ggg = hdrl_image_get_pixel(col_hmap_warped, g+k*SLITLET_WIDTH, y, NULL);
3219 while (isnan(ggg.data) || (ggg.data == 0)) {
3221 ggg = hdrl_image_get_pixel(col_hmap_warped, g+k*SLITLET_WIDTH, y, NULL);
3223 // go even one more to the right, because the first difference is smaller than the other differences
3225 ggg = hdrl_image_get_pixel(col_hmap_warped, g+k*SLITLET_WIDTH, y, NULL);
3226 hdrl_value kkk = hdrl_image_get_pixel(col_hmap_warped, (g+1)+k*SLITLET_WIDTH, y, NULL);
3227 double diff = kkk.data - ggg.data;
3228 col_n_0 = ggg.data-(g-1)*diff;
3229 // we had to calculate a fake/estimated col_n_0, set a flag accordingly
3230 fake_col_n_0 = true;
3232 if ((x==1) && !fake_col_n_0)
3235 if ((col_n < 1) || isnan(contri_n))
3237 // either left border
3238 // or pix_contr.data is nan
3241 } else if (col_n > ERIS_IFU_DETECTOR_SIZE_X || col_n-col_n_0+1 > slitwidth+2) //right border or right edge
3245 } else if (col_n == ERIS_IFU_DETECTOR_SIZE_X || col_n-col_n_0+1 == slitwidth+2)
3247 pix_bpm.data = hdrl_image_get_pixel(bpmIn, col_n, y, NULL).data * contri_n + 1.0 * (1.0-contri_n);
3250 pix_bpm.data = hdrl_image_get_pixel(bpmIn, col_n, y, NULL).data * contri_n +
3251 hdrl_image_get_pixel(bpmIn, col_n+1, y, NULL).data * (1.0-contri_n);
3254 hdrl_image_set_pixel(bpmOut, x+k*SLITLET_WIDTH, y, pix_bpm);
3259 hdrl_image_delete(col_hmap_warped);
3261 eris_ifu_free_polynomial(&poly_v);
3280hdrl_imagelist* eris_ifu_stack_warped(const hdrl_image *imgIn,
3283 cpl_ensure(imgIn, CPL_ERROR_NULL_INPUT, NULL);
3286 double *pImgTmpData = NULL,
3288 const double *pImgInData = NULL,
3290 hdrl_image *imgTmp = NULL;
3291 hdrl_imagelist *cube = NULL;
3296 cube = hdrl_imagelist_new());
3299 pImgInData = cpl_image_get_data_double_const(hdrl_image_get_image_const(imgIn)));
3301 pImgInErr = cpl_image_get_data_double_const(hdrl_image_get_error_const(imgIn)));
3304 for (int z = 0; z < ERIS_IFU_DETECTOR_SIZE_Y; z++) {
3305 // a slitlet is 64pix wide, but we have only 32 slitlets
3306 // In order to get a square cube, at the end each slitlet is doubled in y-direction...
3308 imgTmp = hdrl_image_new(SLITLET_WIDTH, SLITLET_CNT));
3310 pImgTmpData = cpl_image_get_data_double(hdrl_image_get_image(imgTmp)));
3312 pImgTmpErr = cpl_image_get_data_double(hdrl_image_get_error(imgTmp)));
3315 for (int y = 0; y < SLITLET_CNT; y++) {
3316 for (int x = 0; x < SLITLET_WIDTH; x++) {
3317 pImgTmpData[x+rowIx[y]*SLITLET_WIDTH] = pImgInData[cnt++];
3321 hdrl_imagelist_set(cube, imgTmp, z));
3327 eris_ifu_free_hdrl_imagelist(&cube);
3356cpl_error_code eris_ifu_dist_warp_stats(const hdrl_image *hdrlWarpedImg,
3357 cpl_propertylist *qc_list,
3358 cpl_propertylist *pl,
3359 cpl_frameset* frameset,
3360 const cpl_parameterlist* parlist)
3362 int nr_values = 21, //odd
3366// ix_middle = nr_values / 2 + 1;
3368 const double *pfit_centers = NULL;
3369 cpl_error_code err = CPL_ERROR_NONE;
3370 cpl_vector *profile_x = NULL,
3371 *est_centers = NULL,
3372 *fit_centers = NULL,
3373 *fit_centers_middle = NULL;
3374 const cpl_image *warpedImg = NULL;
3375 cpl_table **arr = NULL;
3376 cpl_propertylist *pl_my = NULL;
3378 cpl_ensure_code(hdrlWarpedImg, CPL_ERROR_NULL_INPUT);
3379 cpl_ensure_code(qc_list, CPL_ERROR_NULL_INPUT);
3380 cpl_ensure_code(pl, CPL_ERROR_NULL_INPUT);
3381 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
3382 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
3387 arr = cpl_calloc(SLITLET_CNT, sizeof(cpl_table*)));
3390 warpedImg = hdrl_image_get_image_const(hdrlWarpedImg));
3392 // find out number of fibre-tarces per slitlet (one or three)
3393 center_y = ERIS_IFU_DETECTOR_BP_BORDER + ix_middle*height + height/2;
3395 profile_x = eris_ifu_calc_centers_collapse_chunk(
3396 warpedImg, center_y, height));
3397//AA: evtl instead of CPL_FALSE put in (isK & !is25mas)
3399 est_centers = eris_ifu_dist_calc_centers_profile(profile_x, CPL_FALSE));
3400 // will return a vector with 32 or 3*32 center values (errors are catched)
3402 fit_centers_middle = eris_ifu_dist_calc_centers_fit(
3403 profile_x, est_centers, CPL_TRUE));
3404 actual_size = (int) cpl_vector_get_size(est_centers);
3405 eris_ifu_free_vector(&profile_x);
3406 eris_ifu_free_vector(&est_centers);
3408 // create table to hold values
3409 if (actual_size <= SLITLET_CNT) {
3410 for (int i = 0; i < SLITLET_CNT; i++) {
3411 arr[i] = cpl_table_new(nr_values);
3412 cpl_table_new_column(arr[i], "c
", CPL_TYPE_DOUBLE);
3413 cpl_table_new_column(arr[i], "left
", CPL_TYPE_DOUBLE);
3414 cpl_table_new_column(arr[i], "right
", CPL_TYPE_DOUBLE);
3417 for (int i = 0; i < SLITLET_CNT; i++) {
3418 arr[i] = cpl_table_new(nr_values);
3419 cpl_table_new_column(arr[i], "c_l
", CPL_TYPE_DOUBLE);
3420 cpl_table_new_column(arr[i], "c
", CPL_TYPE_DOUBLE);
3421 cpl_table_new_column(arr[i], "c_r
", CPL_TYPE_DOUBLE);
3422 cpl_table_new_column(arr[i], "r_l
", CPL_TYPE_DOUBLE);
3423 cpl_table_new_column(arr[i], "c_l/r_l
", CPL_TYPE_DOUBLE);
3424 cpl_table_new_column(arr[i], "left
", CPL_TYPE_DOUBLE);
3425 cpl_table_new_column(arr[i], "right
", CPL_TYPE_DOUBLE);
3427 cpl_table_new_column(arr[i], "slitlet_tl
", CPL_TYPE_DOUBLE);
3428 cpl_table_new_column(arr[i], "slitlet_tc
", CPL_TYPE_DOUBLE);
3429 cpl_table_new_column(arr[i], "slitlet_tr
", CPL_TYPE_DOUBLE);
3433 // now do the same for the whole detectors in two blocks
3434 // center to top and center to bottom
3435 CHECK_ERROR_STATE();
3436 est_centers = cpl_vector_duplicate(fit_centers_middle);
3437 for (int j = ix_middle; j < nr_values; j++) {
3438 center_y = ERIS_IFU_DETECTOR_BP_BORDER + j*height + height/2;
3439 /* collapse image in y and convert to vector */
3440 profile_x = eris_ifu_calc_centers_collapse_chunk(warpedImg, center_y,
3442 /* do least square fit using a Gaussian in order to get exact centers */
3443 fit_centers = eris_ifu_dist_calc_centers_fit(profile_x, est_centers,
3446 /* copy values into table */
3447 actual_size = (int) cpl_vector_get_size(fit_centers);
3448 pfit_centers = cpl_vector_get_data_const(fit_centers);
3450 if (actual_size == SLITLET_CNT) {
3451 // one trace per slitlet
3452 for (int i = 0; i < actual_size; i++) {
3453 cpl_table_set_double(arr[i], "c
", j, pfit_centers[i]);
3455 cpl_table_set_double(arr[i], "left
", j, (i-1) * swidth);
3456 cpl_table_set_double(arr[i], "left
", j, i * swidth);
3460 // three traces per slitlet
3462 for (int i = 0; i < actual_size; i+=3) {
3463 if (i >= 3*SLITLET_CNT) {
3464 cpl_msg_warning(cpl_func, "Detected more than 96 traces (%d). Please check output!
", actual_size);
3466 cpl_table_set_double(arr[ii], "left
", j, ii * swidth);
3467 cpl_table_set_double(arr[ii], "right
", j, (ii+1) * swidth);
3468 cpl_table_set_double(arr[ii], "c_l
", j, pfit_centers[i+1]-ii * swidth);
3469 cpl_table_set_double(arr[ii], "c
", j, pfit_centers[i+1]);
3470 cpl_table_set_double(arr[ii], "c_r
", j, (ii+1) * swidth - pfit_centers[i+1]);
3471 cpl_table_set_double(arr[ii], "r_l
", j, swidth);
3472 cpl_table_set_double(arr[ii], "c_l/r_l
", j,
3473 (pfit_centers[i+1]-ii * swidth)/swidth);
3475 cpl_table_set_double(arr[ii], "slitlet_tl
", j, pfit_centers[i]);
3476 cpl_table_set_double(arr[ii], "slitlet_tc
", j, pfit_centers[i+1]);
3477 cpl_table_set_double(arr[ii], "slitlet_tr
", j, pfit_centers[i+2]);
3483 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
3484 eris_ifu_free_vector(&profile_x);
3485 eris_ifu_free_vector(&fit_centers);
3488 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers_middle));
3489 for (int j = ix_middle-1; j >= 0; j--) {
3490 center_y = ERIS_IFU_DETECTOR_BP_BORDER + j*height + height/2;
3491 /* collapse image in y and convert to vector */
3493 profile_x = eris_ifu_calc_centers_collapse_chunk(
3494 warpedImg, center_y, height));
3495 /* do least square fit using a Gaussian in order to get exact centers */
3497 fit_centers = eris_ifu_dist_calc_centers_fit(profile_x, est_centers, CPL_FALSE));
3500 pfit_centers = cpl_vector_get_data_const(fit_centers));
3502 /* copy values into table */
3503 if (actual_size == SLITLET_CNT) {
3504 // one trace per slitlet
3505 for (int i = 0; i < actual_size; i++) {
3506 cpl_table_set_double(arr[i], "c
", j, pfit_centers[i]);
3509 // three traces per slitlet
3511 for (int i = 0; i < actual_size; i+=3) {
3512 if (i >= 3*SLITLET_CNT) {
3513 cpl_msg_warning(cpl_func, "Detected more than 96 traces (%d). Please check output!
", actual_size);
3515 cpl_table_set_double(arr[ii], "left
", j, ii * swidth);
3516 cpl_table_set_double(arr[ii], "right
", j, (ii+1) * swidth);
3517 cpl_table_set_double(arr[ii], "c_l
", j, pfit_centers[i+1]-ii * swidth);
3518 cpl_table_set_double(arr[ii], "c
", j, pfit_centers[i+1]);
3519 cpl_table_set_double(arr[ii], "c_r
", j, (ii+1) * swidth - pfit_centers[i+1]);
3520 cpl_table_set_double(arr[ii], "r_l
", j, swidth);
3521 cpl_table_set_double(arr[ii], "c_l/r_l
", j,
3522 (pfit_centers[i+1]-ii * swidth) / swidth);
3525 cpl_table_set_double(arr[ii], "slitlet_tl
", j, pfit_centers[i]);
3526 cpl_table_set_double(arr[ii], "slitlet_tc
", j, pfit_centers[i+1]);
3527 cpl_table_set_double(arr[ii], "slitlet_tr
", j, pfit_centers[i+2]);
3533 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
3534 eris_ifu_free_vector(&profile_x);
3535 eris_ifu_free_vector(&fit_centers);
3543 // Save warped image as final product
3544 cpl_propertylist_append_string(pl, CPL_DFS_PRO_CATG,
3545 ERIS_IFU_PRO_DIST_DBG_WARPED_FIT);
3546 cpl_propertylist_set_string(pl,"PIPEFILE
",
3547 ERIS_IFU_PRO_DIST_QC_WARPED_FIT_FN);
3548 cpl_propertylist_save(pl, ERIS_IFU_PRO_DIST_QC_WARPED_FIT_FN,
3551 eris_setup_product_header(ERIS_IFU_PRO_DIST_QC_WARPED_FIT_FN,
3552 ERIS_IFU_PRO_DIST_DBG_WARPED_FIT, CPL_FRAME_TYPE_TABLE,
3553 "eris_ifu_distortion
", frameset, parlist, pl);
3558 for (int i = 0; i < SLITLET_CNT; i++) {
3561 pl_my = cpl_propertylist_new());
3562 extname = cpl_sprintf("SLITLET%2.2d
",i);
3563 cpl_propertylist_append_string(pl_my,"EXTNAME
",extname);
3564// if (cpl_table_get_ncol(arr[i]) == 1) {
3565 if (actual_size <= SLITLET_CNT) {
3566 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C STDEV
",i);
3567 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "c
"));
3568 keycomm = cpl_sprintf("[pix] center stdev
");
3569 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3574 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C MEDIAN
",i);
3575 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "c
"));
3576 keycomm = cpl_sprintf("[pix] center median
");
3577 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3581 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-L STDEV
",i);
3582 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "r_l
"));
3583 keycomm = cpl_sprintf("[pix] center-left stdev
");
3584 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3588 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-L MEDIAN
",i);
3589 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "r_l
"));
3590 keycomm = cpl_sprintf("[pix] center-left median
");
3591 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3595 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-L STDEV
",i);
3596 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "c_l
"));
3597 keycomm = cpl_sprintf("[pix] center stdev
");
3598 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3602 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-L MEDIAN
",i);
3603 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "c_l
"));
3604 keycomm = cpl_sprintf("[pix] center median
");
3605 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3609 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-C STDEV
",i);
3610 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "c_r
"));
3611 keycomm = cpl_sprintf("[pix] center-right stdev
");
3612 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3616 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TL MEDIAN
",i);
3617 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "slitlet_tl
"));
3618 keycomm = cpl_sprintf("[pix] trace left median
");
3619 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3623 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TL STDEV
",i);
3624 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "slitlet_tl
"));
3625 keycomm = cpl_sprintf("[pix] trace left stdev
");
3626 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3630 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TC MEDIAN
",i);
3631 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "slitlet_tc
"));
3632 keycomm = cpl_sprintf("[pix] trace center median
");
3633 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3637 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TC STDEV
",i);
3638 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "slitlet_tc
"));
3639 keycomm = cpl_sprintf("[pix] trace center stdev
");
3640 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3644 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TR MEDIAN
",i);
3645 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "slitlet_tr
"));
3646 keycomm = cpl_sprintf("[pix] trace right median
");
3647 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3651 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TR STDEV
",i);
3652 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "slitlet_tr
"));
3653 keycomm = cpl_sprintf("[pix] trace right stdev
");
3654 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3658 keyname = cpl_sprintf("ESO QC SLITLET%2.2d CL_RL FRAC
",i);
3659 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "c_l/r_l
"));
3660 keycomm = cpl_sprintf("(center-left)/(right-left) ratio
");
3661 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3665 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-C MEDIAN
",i);
3666 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "c_r
"));
3667 keycomm = cpl_sprintf("[pix] center-right median
");
3668 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3676 cpl_table_save(arr[i], NULL, pl_my,
3677 ERIS_IFU_PRO_DIST_QC_WARPED_FIT_FN,
3679 eris_ifu_free_propertylist(&pl_my);
3686 err = cpl_error_get_code();
3689 for (int i = 0; i < SLITLET_CNT; i++) {
3690 eris_ifu_free_table(&arr[i]);
3692 cpl_free(arr); arr = NULL;
3693 eris_ifu_free_vector(&profile_x);
3694 eris_ifu_free_vector(&est_centers);
3695 eris_ifu_free_vector(&fit_centers);
3696 eris_ifu_free_vector(&fit_centers_middle);
3697 eris_ifu_free_propertylist(&pl_my);
3715cpl_error_code eris_ifu_image_add_slit(hdrl_image *hdrlImgFull,
3716 const hdrl_image *hdrlImgSlit,
3719 cpl_error_code err = CPL_ERROR_NONE;
3720 cpl_image *tmpImgFull = NULL;
3721 const cpl_image *tmpImgSlit = NULL;
3722 cpl_mask *tmpMaskFull = NULL;
3723 const cpl_mask *tmpMaskSlit = NULL;
3724 double *pimgFullData = NULL,
3725 *pimgFullErr = NULL;
3726 const double *pimgSlitData = NULL,
3727 *pimgSlitErr = NULL;
3728 cpl_binary *pimgFullMask = NULL;
3729 const cpl_binary *pimgSlitMask = NULL;
3733 cpl_ensure_code(hdrlImgFull, CPL_ERROR_NULL_INPUT);
3734 cpl_ensure_code(hdrlImgSlit, CPL_ERROR_NULL_INPUT);
3735 cpl_ensure_code(hdrl_image_get_size_y(hdrlImgFull) == ERIS_IFU_DETECTOR_SIZE_Y,
3736 CPL_ERROR_ILLEGAL_INPUT);
3737 cpl_ensure_code(hdrl_image_get_size_y(hdrlImgSlit) == ERIS_IFU_DETECTOR_SIZE_Y,
3738 CPL_ERROR_ILLEGAL_INPUT);
3739 cpl_ensure_code(hdrl_image_get_size_x(hdrlImgFull) >= hdrl_image_get_size_x(hdrlImgSlit),
3740 CPL_ERROR_ILLEGAL_INPUT);
3741 cpl_ensure_code(offset >= 0, CPL_ERROR_ILLEGAL_INPUT);
3745 tmpImgFull = hdrl_image_get_image(hdrlImgFull);
3746 tmpMaskFull = cpl_image_get_bpm(tmpImgFull);
3748 pimgFullData = cpl_image_get_data(tmpImgFull));
3750 pimgFullErr = cpl_image_get_data(hdrl_image_get_error(hdrlImgFull)));
3751 if (tmpMaskFull != NULL) {
3753 pimgFullMask = cpl_mask_get_data(tmpMaskFull));
3755 widthFull = (int) hdrl_image_get_size_x(hdrlImgFull);
3757 tmpImgSlit = hdrl_image_get_image_const(hdrlImgSlit);
3758 tmpMaskSlit = cpl_image_get_bpm_const(tmpImgSlit);
3760 pimgSlitData = cpl_image_get_data_const(tmpImgSlit));
3762 pimgSlitErr = cpl_image_get_data_const(hdrl_image_get_error_const(hdrlImgSlit)));
3763 if (tmpMaskSlit != NULL) {
3765 pimgSlitMask = cpl_mask_get_data_const(tmpMaskSlit));
3768 widthSlit = (int) hdrl_image_get_size_x(hdrlImgSlit);
3770 for (int y = 0; y < ERIS_IFU_DETECTOR_SIZE_Y; y++) {
3771 for (int x = 0; x < widthSlit; x++) {
3772 pimgFullData[x+offset+y*widthFull] = pimgSlitData[x+y*widthSlit];
3773 pimgFullErr[x+offset+y*widthFull] = pimgSlitErr[x+y*widthSlit];
3774 if ((tmpMaskFull != NULL) && (tmpMaskSlit != NULL)) {
3775 pimgFullMask[x+offset+y*widthFull] = pimgSlitMask[x+y*widthSlit];
3783 err = cpl_error_get_code();
3818cpl_table** eris_ifu_dist_calc_slitpos(cpl_image **arcImg,
3819 cpl_table **centers_array,
3820 cpl_table *valid_arc_lines,
3822 cpl_boolean *cut_off_left,
3823 cpl_boolean *cut_off_right,
3824 const cpl_frameset* frameset,
3825 const cpl_parameterlist* parlist)
3827 int max_lines = 200,
3830 urx, ury, llx, lly = 0;
3832 double arc_center = 0.,
3838// *pprofile_y = NULL,
3839 *pleft_edge_tmp = NULL,
3840 *pright_edge_tmp= NULL,
3843 *pright_edge = NULL,
3845 char *extname = NULL;
3846 const char *fn = "eris_ifu_distortion_dbg_slitpos_slit_width.fits
";
3847 const char *fnx = "eris_ifu_distortion_dbg_slitpos_profile_xy.fits
";
3848// cpl_boolean cut_off_fully = CPL_FALSE;
3849 cpl_image *profile_x = NULL;
3851 cpl_table **tbl = NULL,
3852 *valid_arc_lines_slitlet = NULL;
3853 cpl_vector *left_edge_tmp = NULL,
3854 *right_edge_tmp = NULL,
3859 cpl_propertylist *pl_tbl = NULL;
3860 eris_ifu_vector *slit_width = NULL,
3861 *slit_width_rej = NULL,
3863 *right_edge_rej = 0;
3865 cpl_ensure(arcImg, CPL_ERROR_NULL_INPUT, NULL);
3866 cpl_ensure(*centers_array, CPL_ERROR_NULL_INPUT, NULL);
3870 *cut_off_right = FALSE;
3871 *cut_off_right = FALSE;
3874 left_edge_tmp = cpl_vector_new(max_lines));
3876 right_edge_tmp = cpl_vector_new(max_lines));
3878 ypos_tmp = cpl_vector_new(max_lines));
3881 pleft_edge_tmp = cpl_vector_get_data(left_edge_tmp));
3883 pright_edge_tmp = cpl_vector_get_data(right_edge_tmp));
3885 pypos_tmp = cpl_vector_get_data(ypos_tmp));
3887 /* write empty header */
3888 cpl_frameset* fs = (cpl_frameset*) frameset;
3889 char* pipe_id = cpl_sprintf("%s%s%s
", PACKAGE, "/
", PACKAGE_VERSION);
3890 cpl_propertylist *applist = cpl_propertylist_new();
3891 cpl_propertylist_update_string(applist, CPL_DFS_PRO_CATG,
3892 ERIS_IFU_PRO_DIST_SLIT_POS);
3893 cpl_dfs_save_propertylist(fs, NULL, parlist, frameset, NULL,
3894 REC_NAME_DISTORTION, applist, NULL, pipe_id,
3895 ERIS_IFU_PRO_DIST_SLIT_POS_FN);
3896 cpl_propertylist_delete(applist);
3898 CHECK_ERROR_STATE();
3900 // cpl_propertylist_save(pl_tbl, ERIS_IFU_PRO_DIST_SLIT_POS_FN, CPL_IO_CREATE));
3903 tbl = cpl_calloc(SLITLET_CNT, sizeof(cpl_table*)));
3905 if (productDepth & 8) {
3906 eris_ifu_save_image_dbg(NULL, fn, CPL_IO_CREATE, NULL);
3907 eris_ifu_save_image_dbg(NULL, fnx, CPL_IO_CREATE, NULL);
3909 /* loop all slitlets */
3910 for (int i = 0; i < SLITLET_CNT; i++) {
3911 cpl_msg_debug(cpl_func, "i: %d
", i);
3913 // take middle value from "x
"
3914 middle = (int) cpl_table_get_nrow(centers_array[i])/2;
3915 arc_center = cpl_table_get_double(centers_array[i], "x
", middle, &ttt);
3916 CHECK_ERROR_STATE();
3918 if ((productDepth & 3) != 0) {
3919 cpl_msg_debug(cpl_func, " Slitlet #%i: center pos: %g
", i+1,
3923 /* extract list of valid lines */
3924 if (valid_arc_lines != NULL) {
3925 cpl_table_unselect_all(valid_arc_lines);
3926 cpl_table_or_selected_int(valid_arc_lines, ERIS_IFU_FITTABLE_SLITLET, CPL_EQUAL_TO, i);
3927 valid_arc_lines_slitlet = cpl_table_extract_selected(valid_arc_lines);
3929 /* loop all lines (brighter than a tenth of the brightest line)
3930 * in vertical profile and detect edges */
3934// while (y < ERIS_IFU_DETECTOR_SIZE_Y) {
3935 for (int iii = 0; iii < cpl_table_get_nrow(valid_arc_lines_slitlet); iii++) {
3936// AA simplify all this!
3937 y = (int) ( 0.5 + cpl_table_get_double(
3938 valid_arc_lines_slitlet, "x0
", iii, NULL));
3939 arcImgIx = cpl_table_get_int(
3940 valid_arc_lines_slitlet, "imgIdx
", iii, NULL);
3941// if (pprofile_y[y] > cut_level) {
3942 pypos_tmp[nr_lines] = y;
3944 /* create horizontal profile at bright line
3945 * (height ~5pix, width 64 + 15pix left and right) */
3946 llx = (int) (arc_center+0.5) -64/2-25+1,
3947 urx = (int) (arc_center+0.5) +64/2+25+1;
3948//AA check if better for bad Lines
3951 // int half_height = 3 / 2;
3952 half_height = 5 / 2,
3953 lly = y - half_height + 1,
3954 ury = y + half_height + 1;
3955 // y ist the first value, that is above the threshold
3956 //HIER in y gaussfit, evtl am besten entlang llx-urx
3964 profile_x = cpl_image_collapse_window_create(arcImg[arcImgIx],
3969// // identify actual ypos in valid_lines2
3970// int valid_line = 0;
3973// } else if (b > 0){
3977// // get leftmost and rightmost column of this slitlet
3978// cpl_table_unselect_all(valid_arc_lines_slitlet);
3979// cpl_table_or_selected_int(valid_arc_lines_slitlet, ERIS_IFU_FITTABLE_POSITION, CPL_EQUAL_TO, valid_line);
3986// // get the according y-values
3988// // create a line accross the detector from llx to urx
3990// // create a profile in a way that +/-3or5 pix vertically around the line are averaged and put into profile_x
3993 cpl_error_code status = eris_ifu_slitpos_gauss(
3995 &(pleft_edge_tmp[nr_lines]),
3996 &(pright_edge_tmp[nr_lines]),
3999 if (status == CPL_ERROR_EOL) {
4003 pleft_edge_tmp[nr_lines] -= 1.;
4004 pright_edge_tmp[nr_lines] -= 1.;
4006 if (productDepth & 8) {
4007 cpl_propertylist *pl_line = NULL;
4009 pl_line = cpl_propertylist_new());
4010 extname = cpl_sprintf("Sx_%02d Lx_%02d
", i+1, nr_lines+1);
4011 cpl_propertylist_append_string(pl_line, "EXTNAME
", extname);
4012 eris_ifu_free_string(&extname);
4013 cpl_propertylist_append_double(pl_line, "lineypos
", y);
4014 cpl_propertylist_append_double(pl_line, "llx
", llx);
4015 cpl_propertylist_append_double(pl_line, "lly
", lly);
4016 cpl_propertylist_append_double(pl_line, "urx
", urx);
4017 cpl_propertylist_append_double(pl_line, "ury
", ury);
4018 cpl_propertylist_append_double(pl_line, "edge_l
", pleft_edge_tmp[nr_lines]);
4019 cpl_propertylist_append_double(pl_line, "edge_r
", pright_edge_tmp[nr_lines]);
4020 eris_ifu_save_image_dbg(profile_x, fnx, CPL_IO_EXTEND, pl_line);
4021 eris_ifu_free_propertylist(&pl_line);
4023 eris_ifu_free_image(&profile_x);
4025 if (status == CPL_ERROR_EOL) {
4027 } else if (status != CPL_ERROR_NONE) {
4028 ERIS_IFU_TRY_EXIT();
4031 if (nr_lines >= max_lines) {
4032 SET_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
4033 "more than 100 lines detected!
");
4035 // double est_pos = pleft_edge[nr_lines] + (pright_edge[nr_lines]-pleft_edge[nr_lines])/2.0;
4036 // cpl_msg_debug(cpl_func, " left_pos: %g, right_pos: %g
", pleft_edge[nr_lines], pright_edge[nr_lines]);
4037 // cpl_msg_debug(cpl_func, " est. pos: %g
", est_pos);
4038 // // this is the eff. offset from slitlet center to fibre-center
4039 // cpl_msg_debug(cpl_func, " diff: %g
", arc_center-est_pos);
4041 eris_ifu_free_image(&profile_x);
4043 // get off surroundings of already processed line
4047 if (nr_lines >= max_lines) {
4048 SET_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
4049 "more than 100 lines detected!
");
4053// } // end: if detected line
4057 eris_ifu_free_table(&valid_arc_lines_slitlet);
4059 /* cut vectors to their correct length */
4061 left_edge = cpl_vector_extract(left_edge_tmp, 0, nr_lines-1, 1));
4063 right_edge = cpl_vector_extract(right_edge_tmp, 0, nr_lines-1, 1));
4065 ypos = cpl_vector_extract(ypos_tmp, 0, nr_lines-1, 1));
4067 pleft_edge = cpl_vector_get_data(left_edge));
4069 pright_edge = cpl_vector_get_data(right_edge));
4071 pypos = cpl_vector_get_data(ypos));
4073 slit_width = eris_ifu_vector_new(nr_lines);
4074 for (int ty = 0; ty < nr_lines; ty++) {
4075 eris_ifu_vector_set(slit_width, ty, pright_edge[ty]-pleft_edge[ty]);
4079 * omit outliers in a multi process step
4082 pl_tbl = cpl_propertylist_new());
4084 /* status before rejecting */
4085 median = eris_ifu_vector_get_median(slit_width, ERIS_IFU_ARITHMETIC);
4086 stddev = eris_ifu_vector_get_stdev_median(slit_width);
4087 CHECK_ERROR_STATE();
4089 cpl_propertylist_append_double(pl_tbl, "bef_med
", median));
4091 cpl_propertylist_append_double(pl_tbl, "bef_sdv
", stddev));
4092 cpl_msg_debug(cpl_func, "before: median: %g, stddev: %g
", median, stddev);
4093 if (productDepth & 8) {
4094 cpl_propertylist *pl = NULL;
4096 pl = cpl_propertylist_new());
4097 extname = cpl_sprintf("Sx_%02d ypos
", i+1);
4098 cpl_propertylist_append_string(pl, "EXTNAME
", extname);
4099 eris_ifu_free_string(&extname);
4101 eris_ifu_save_vector_dbg(ypos, fn, CPL_IO_EXTEND, pl));
4102 extname = cpl_sprintf("Sx_%02d left_edge
", i+1);
4103 cpl_propertylist_append_string(pl, "EXTNAME
", extname);
4104 eris_ifu_free_string(&extname);
4106 eris_ifu_save_vector_dbg(left_edge, fn, CPL_IO_EXTEND, pl));
4107 extname = cpl_sprintf("Sx_%02d right_edge
", i+1);
4108 cpl_propertylist_append_string(pl, "EXTNAME
", extname);
4109 eris_ifu_free_string(&extname);
4111 eris_ifu_save_vector_dbg(right_edge, fn, CPL_IO_EXTEND, pl));
4112 extname = cpl_sprintf("Sx_%02d slit_width
", i+1);
4113 cpl_propertylist_append_string(pl_tbl, "EXTNAME
", extname);
4114 eris_ifu_free_string(&extname);
4116 eris_ifu_vector_save(slit_width, fn, CPL_TYPE_DOUBLE,
4117 pl_tbl, CPL_IO_EXTEND, 70));
4118 eris_ifu_free_propertylist(&pl);
4122 left_edge_rej = eris_ifu_vector_create(left_edge));
4124 right_edge_rej = eris_ifu_vector_create(right_edge));
4126 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
4128 if ((median < 58) && (stddev > 3) &&
4129 ((i == 0) || (i == SLITLET_CNT-1)))
4131 // median is obviously so wrong, that many values indicate that slitlet is cut off!
4132 // reject values < SLITLET_WIDTH-stddev
4133 for (int ty = 0; ty < nr_lines; ty++) {
4134 double val = eris_ifu_vector_get(slit_width_rej, ty);
4135 if (val < SLITLET_WIDTH-stddev) {
4136 eris_ifu_vector_reject(slit_width_rej, ty);
4137 eris_ifu_vector_reject(left_edge_rej, ty);
4138 eris_ifu_vector_reject(right_edge_rej, ty);
4141if (eris_ifu_vector_count_non_rejected(slit_width_rej) <= 1) {
4142// cut_off_fully = CPL_TRUE;
4143 eris_ifu_free_ifu_vector(&left_edge_rej);
4144 eris_ifu_free_ifu_vector(&right_edge_rej);
4145 eris_ifu_free_ifu_vector(&slit_width_rej);
4147 left_edge_rej = eris_ifu_vector_create(left_edge));
4149 right_edge_rej = eris_ifu_vector_create(right_edge));
4151 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
4153 median = eris_ifu_vector_get_median(slit_width_rej, ERIS_IFU_ARITHMETIC);
4154 stddev = eris_ifu_vector_get_stdev_median(slit_width_rej);
4155 CHECK_ERROR_STATE();
4158 cpl_propertylist_append_double(pl_tbl, "med_rej1
", median));
4160 cpl_propertylist_append_double(pl_tbl, "sdv_rej1
", stddev));
4161 cpl_msg_debug(cpl_func, "median: %g, stddev: %g
", median, stddev);
4162 if (productDepth & 8) {
4163 extname = cpl_sprintf("Sx_%02d slit_width_rej
", i+1);
4164 cpl_propertylist_append_string(pl_tbl, "EXTNAME
", extname);
4165 eris_ifu_free_string(&extname);
4167 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl, CPL_IO_EXTEND, 70));
4171 *cut_off_left = CPL_TRUE;
4173 cpl_propertylist_append_string(pl_tbl, "cutoff
", "left
"));
4175 if (i == SLITLET_CNT-1) {
4176 *cut_off_right = CPL_TRUE;
4178 cpl_propertylist_append_string(pl_tbl, "cutoff
", "right
"));
4182 /* omit outliers devying more than 2% (15% for problematic slitlet #16)*/
4184 if (i == 15 || i == 17) {
4187 for (int ty = 0; ty < nr_lines; ty++) {
4188 double val = eris_ifu_vector_get(slit_width_rej, ty);
4189 if ((val > median*percentage) || (val < median/percentage)) {
4190 eris_ifu_vector_reject(slit_width_rej, ty);
4191 eris_ifu_vector_reject(left_edge_rej, ty);
4192 eris_ifu_vector_reject(right_edge_rej, ty);
4196 median = eris_ifu_vector_get_median(slit_width_rej, ERIS_IFU_ARITHMETIC);
4198 cpl_propertylist_append_double(pl_tbl, "aft_med
", median));
4199 if (eris_ifu_vector_count_non_rejected(slit_width_rej) >= 3) {
4200 stddev = eris_ifu_vector_get_stdev_median(slit_width_rej);
4202 cpl_propertylist_append_double(pl_tbl, "aft_sdv
", stddev));
4204 CHECK_ERROR_STATE();
4205 cpl_msg_debug(cpl_func, "after: median: %g, stddev: %g
", median, stddev);
4206 if (productDepth & 8) {
4207 extname = cpl_sprintf("Sx_%02d slit_width_rej2
", i+1);
4208 cpl_propertylist_append_string(pl_tbl, "EXTNAME
", extname);
4209 eris_ifu_free_string(&extname);
4211 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl, CPL_IO_EXTEND, 70));
4215 * check if first or last slitlet is off detector (partially cut off)
4218 if ((i == 0) && ((*cut_off_left == CPL_TRUE) ||
4219 (eris_ifu_vector_get_min(left_edge_rej, NULL) < ERIS_IFU_DETECTOR_BP_BORDER)))
4221 *cut_off_left = CPL_TRUE;
4222 if (!cpl_propertylist_has(pl_tbl, "cutoff
")) {
4224 cpl_propertylist_append_string(pl_tbl, "cutoff
", "left
"));
4228 eris_ifu_free_ifu_vector(&slit_width_rej);
4230 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
4232 eris_ifu_vector *x = NULL;
4233 x = eris_ifu_vector_duplicate(slit_width_rej);
4234 for (int j = 0; j < nr_lines; j++) {
4235 eris_ifu_vector_set(x, j, j+1);
4237 cpl_vector *fff = eris_ifu_polyfit_edge(x, slit_width_rej, 1);
4238 eris_ifu_free_ifu_vector(&x);
4240 double fp0 = cpl_vector_get(fff, 0),
4241 fp1 = cpl_vector_get(fff, 1);
4242 eris_ifu_free_vector(&fff);
4243 stddev = eris_ifu_vector_get_stdev_median(slit_width_rej);
4244 for (int ty = 0; ty < nr_lines; ty++) {
4245 double val = eris_ifu_vector_get(slit_width_rej, ty);
4246 double val_calc = fp0+fp1*(ty+1);
4247 if (fabs(val - val_calc) > stddev*0.7) { // stddev is a bit too high
4248 eris_ifu_vector_reject(slit_width_rej, ty);
4251 if (productDepth & 8) {
4252 extname = cpl_sprintf("Sx_%02d slit_width_rej3
", i+1);
4253 cpl_propertylist_append_string(pl_tbl, "EXTNAME
", extname);
4254 eris_ifu_free_string(&extname);
4256 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl,
4257 CPL_IO_EXTEND, 70));
4259 } // if left_edge cut off
4261 if ((i == SLITLET_CNT-1) && ((*cut_off_right == CPL_TRUE) ||
4262 (eris_ifu_vector_get_max(right_edge_rej, NULL) > ERIS_IFU_DETECTOR_SIZE_X-ERIS_IFU_DETECTOR_BP_BORDER)))
4264 *cut_off_right = TRUE;
4265 if (!cpl_propertylist_has(pl_tbl, "cutoff
")) {
4267 cpl_propertylist_append_string(pl_tbl, "cutoff
", "right
"));
4271 eris_ifu_free_ifu_vector(&slit_width_rej);
4273 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
4275 eris_ifu_vector *x = NULL;
4276 x = eris_ifu_vector_duplicate(slit_width_rej);
4277 for (int j = 0; j < nr_lines; j++) {
4278 eris_ifu_vector_set(x, j, j+1);
4280 cpl_vector *fff = eris_ifu_polyfit_edge(x, slit_width_rej, 1);
4281 eris_ifu_free_ifu_vector(&x);
4283 double fp0 = cpl_vector_get(fff, 0),
4284 fp1 = cpl_vector_get(fff, 1);
4285 eris_ifu_free_vector(&fff);
4286 stddev = eris_ifu_vector_get_stdev_median(slit_width_rej);
4287 CHECK_ERROR_STATE();
4288 for (int ty = 0; ty < nr_lines; ty++) {
4289 double val = eris_ifu_vector_get(slit_width_rej, ty);
4290 double val_calc = fp0+fp1*(ty+1);
4291 if (fabs(val - val_calc) > stddev*0.7) { // stddev is a bit too high
4293 eris_ifu_vector_reject(slit_width_rej, ty));
4296 if (productDepth & 8) {
4297 extname = cpl_sprintf("Sx_%02d slit_width_rej4
", i+1);
4298 cpl_propertylist_append_string(pl_tbl, "EXTNAME
", extname);
4299 eris_ifu_free_string(&extname);
4301 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl,
4302 CPL_IO_EXTEND, 70));
4304 } // if right_edge cut off
4306 eris_ifu_free_ifu_vector(&left_edge_rej);
4307 eris_ifu_free_ifu_vector(&right_edge_rej);
4308 CHECK_ERROR_STATE();
4310 /* setup table to save */
4312 tbl[i] = cpl_table_new(eris_ifu_vector_count_non_rejected(slit_width_rej)));
4314 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_EDGE_L, CPL_TYPE_DOUBLE));
4316 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_EDGE_R, CPL_TYPE_DOUBLE));
4318 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_SLIT, CPL_TYPE_DOUBLE));
4320 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_YPOS, CPL_TYPE_DOUBLE));
4322 // copy vectors to table
4324 for (int ty = 0; ty < cpl_vector_get_size(ypos); ty++) {
4325 if (!eris_ifu_vector_is_rejected(slit_width_rej, ty)) {
4326 // add to table only if line hasn't been rejected
4328 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_YPOS, cnt, pypos[ty]));
4330 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_L, cnt, pleft_edge[ty]));
4332 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_R, cnt, pright_edge[ty]));
4334 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_SLIT, cnt, eris_ifu_vector_get(slit_width_rej, ty)));
4336 if ((i == 0) && (*cut_off_left == TRUE)) {
4337 // set invalid values to nan on left side
4338 if (pleft_edge[ty] < ERIS_IFU_DETECTOR_BP_BORDER) {
4340 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_L, cnt, NAN));
4342 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_SLIT, cnt, pright_edge[ty]-ERIS_IFU_DETECTOR_BP_BORDER));
4345 if ((i == SLITLET_CNT-1) && (*cut_off_right == TRUE)) {
4346 // set invalid values to nan on right side
4347 if (pright_edge[ty] > ERIS_IFU_DETECTOR_SIZE_X-ERIS_IFU_DETECTOR_BP_BORDER) {
4349 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_R, cnt, NAN));
4351 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_SLIT, cnt, ERIS_IFU_DETECTOR_SIZE_X - ERIS_IFU_DETECTOR_BP_BORDER - pleft_edge[ty]));
4359 extname = cpl_sprintf("Sx_%02d
", i+1);
4360 cpl_propertylist_append_string(pl_tbl, "EXTNAME
", extname);
4361 eris_ifu_free_string(&extname);
4363 cpl_table_save(tbl[i], NULL, pl_tbl, ERIS_IFU_PRO_DIST_SLIT_POS_FN, CPL_IO_EXTEND));
4365 eris_ifu_free_propertylist(&pl_tbl);
4366 eris_ifu_free_ifu_vector(&slit_width);
4367 eris_ifu_free_ifu_vector(&slit_width_rej);
4368 eris_ifu_free_vector(&left_edge);
4369 eris_ifu_free_vector(&right_edge);
4370 eris_ifu_free_vector(&ypos);
4371 } // end: for i = SLITLET_CNT
4377 eris_ifu_free_image(&profile_x);
4378 for (int i = 0; i < SLITLET_CNT; i++) {
4379 eris_ifu_free_table(&tbl[i]);
4381 cpl_free(tbl); tbl = NULL;
4384 eris_ifu_free_vector(&left_edge_tmp);
4385 eris_ifu_free_vector(&right_edge_tmp);
4386 eris_ifu_free_vector(&ypos_tmp);
4387 eris_ifu_free_vector(&left_edge);
4388 eris_ifu_free_vector(&right_edge);
4389 eris_ifu_free_vector(&ypos);
4390 eris_ifu_free_propertylist(&pl_tbl);
4391 eris_ifu_free_ifu_vector(&left_edge_rej);
4392 eris_ifu_free_ifu_vector(&right_edge_rej);
4417cpl_error_code eris_ifu_fit_gauss(const cpl_vector *x,
4418 const cpl_vector *y,
4424 cpl_error_code ret_error = CPL_ERROR_NONE,
4425 fit_error = CPL_ERROR_NONE;
4428 cpl_ensure_code(x, CPL_ERROR_NULL_INPUT);
4429 cpl_ensure_code(y, CPL_ERROR_NULL_INPUT);
4430 cpl_ensure_code(x0, CPL_ERROR_NULL_INPUT);
4431 cpl_ensure_code(area, CPL_ERROR_NULL_INPUT);
4432 cpl_ensure_code(sigma, CPL_ERROR_NULL_INPUT);
4433 cpl_ensure_code(offset, CPL_ERROR_NULL_INPUT);
4442 fit_error = cpl_vector_fit_gaussian(x, NULL, y, NULL,
4450// cpl_msg_debug(cpl_func, " --- 1st FIT ---------------------
"
4452// cpl_msg_debug(cpl_func, " center: %g (sigma: %g, area: %g,
"
4453// " offset: %g)
", *x0, *sigma, *area, *offset);
4455 // this happens only once in obscure test data...
4456 if ((fit_error == CPL_ERROR_NONE) &&
4457 (cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX))
4460 fit_error = CPL_ERROR_CONTINUE;
4463 if (fit_error == CPL_ERROR_CONTINUE) {
4464 // if first fit doesn't convert, try it again with fixed
4465 // area- and sigma-parameter
4468 fit_error = cpl_vector_fit_gaussian(x, NULL, y, NULL,
4469 CPL_FIT_CENTROID | CPL_FIT_OFFSET,
4476// cpl_msg_debug(cpl_func, " --- 2nd FIT -----------------
"
4477// "-----------------
");
4478// cpl_msg_debug(cpl_func, " center: %g (sigma: %g,
"
4479// "area: %g, offset: %g)
",
4480// *x0, *sigma, *area, *offset);
4482 if (fit_error == CPL_ERROR_CONTINUE) {
4483 // if it didn't convert again, give up and take the
4488 CHECK_ERROR_STATE();
4492 ret_error = cpl_error_get_code();
4522cpl_vector* eris_ifu_polyfit_edge(const eris_ifu_vector *x,
4523 const eris_ifu_vector *y,
4526 eris_ifu_vector *x_dup = NULL,
4529 cpl_vector *fit_par = NULL,
4532 double *pfit_par = NULL,
4545 cpl_ensure(x, CPL_ERROR_NULL_INPUT, NULL);
4546 cpl_ensure(y, CPL_ERROR_NULL_INPUT, NULL);
4547 cpl_ensure(fit_order >= 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
4548 cpl_ensure(cpl_vector_get_size(x->data) == cpl_vector_get_size(y->data), CPL_ERROR_ILLEGAL_INPUT, NULL);
4552 // assert that rejected values in x are also rejected in y and vice versa
4554 x_dup = eris_ifu_vector_duplicate(x));
4556 y_dup = eris_ifu_vector_duplicate(y));
4558 eris_ifu_vector_adapt_rejected(x_dup, y_dup));
4560 size = (int) cpl_vector_get_size(x_dup->data);
4563 pxdata = cpl_vector_get_data(x_dup->data));
4565 pxmask = cpl_vector_get_data(x_dup->mask));
4567 pymask = cpl_vector_get_data(y_dup->mask));
4570 fit_vec = eris_ifu_vector_new(size));
4572 pfdata = cpl_vector_get_data(fit_vec->data));
4574 pfmask = cpl_vector_get_data(fit_vec->mask));
4577 for (i = 0; i < iter; i++)
4579 cpl_vector_delete(fit_par); fit_par = NULL;
4583 x_good = eris_ifu_vector_create_non_rejected(x_dup));
4585 y_good = eris_ifu_vector_create_non_rejected(y_dup));
4588 fit_par = eris_ifu_polyfit_1d(x_good, y_good, fit_order));
4590 pfit_par = cpl_vector_get_data(fit_par));
4592 eris_ifu_free_vector(&x_good);
4593 eris_ifu_free_vector(&y_good);
4595 // create fitted vector
4596 for (j = 0; j < size; j++) {
4597 if (eris_ifu_vector_is_rejected(x_dup, j)) {
4599 eris_ifu_vector_reject(fit_vec, j));
4601 double fit_val = -pfit_par[0];
4602 if (fit_order >= 1) {
4603 fit_val -= pfit_par[1] * pxdata[j];
4605 if (fit_order >= 2) {
4606 fit_val -= pfit_par[2] * pow(pxdata[j], 2);
4608 if (fit_order >= 3) {
4609 fit_val -= pfit_par[3] * pow(pxdata[j], 3);
4613 eris_ifu_vector_set(fit_vec, j, fit_val));
4617 // fit_vec = y_good - fit_vec
4619 eris_ifu_vector_add(fit_vec, y_dup));
4621 median = eris_ifu_vector_get_median(fit_vec, ERIS_IFU_ARITHMETIC);
4622 stddev = eris_ifu_vector_get_stdev(fit_vec);
4623 CHECK_ERROR_STATE();
4626 eris_ifu_vector_abs(fit_vec));
4628 // clip values larger than median + 5 * stddev
4629 double clip_val = median + 5 * stddev;
4630 for (j = 0; j < size; j++) {
4631 if ((pfmask[j] >= 0.5) && (pfdata[j] > clip_val)) {
4642 eris_ifu_free_vector(&fit_par);
4645 eris_ifu_free_ifu_vector(&fit_vec);
4646 eris_ifu_free_ifu_vector(&x_dup);
4647 eris_ifu_free_ifu_vector(&y_dup);
4648 eris_ifu_free_vector(&x_good);
4649 eris_ifu_free_vector(&y_good);
4677cpl_error_code eris_ifu_wavecal_processSof_dist(
4678 cpl_frameset* frames,
4679 int exposureCorrectionMode,
4681 hdrl_imagelist **arcImages,
4684 ifsPreopticsScale *scale,
4685 ifsInstrument *instrument,
4686 double saturation_threhold,
4690 cpl_frame *frame = NULL;
4694 if (frames == NULL) {
4695 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
4696 "missing frameset
");
4698 if (cpl_frameset_is_empty(frames)) {
4699 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
4700 "SOF file is empty or missing
");
4702 CHECK_ERROR_STATE();
4704//AA only change: ERIS_IFU_RAW_WAVE_NS instead of ERIS_IFU_RAW_WAVE_LAMP
4705 // get arc lamp image
4706 cpl_frameset *arcFrames = NULL;
4707 if (cpl_frameset_count_tags(frames, ERIS_IFU_RAW_WAVE_NS) > 0) {
4708 arcFrames = eris_ifu_get_frameset_by_tag(frames, ERIS_IFU_RAW_WAVE_NS);
4709 } else if ( (cpl_frameset_count_tags(frames, ERIS_IFU_RAW_WAVE_NS_ON) > 0) &&
4710 (cpl_frameset_count_tags(frames, ERIS_IFU_RAW_WAVE_NS_OFF) > 0) ) {
4711 cpl_frameset *arcFrames_off = NULL;
4712 arcFrames = eris_ifu_get_frameset_by_tag(frames, ERIS_IFU_RAW_WAVE_NS_ON);
4714 arcFrames_off = eris_ifu_get_frameset_by_tag(frames, ERIS_IFU_RAW_WAVE_NS_OFF);
4716 cpl_frameset_join(arcFrames, arcFrames_off);
4718 cpl_frameset_delete(arcFrames_off);
4721 eris_ifu_wave_get_arc_images(arcFrames,
4722 exposureCorrectionMode,
4729 saturation_threhold,
4731 cpl_frameset_delete(arcFrames);
4733 // get reference lines
4734 frame = cpl_frameset_find(frames, ERIS_IFU_CALIB_REF_LINES);
4735 CHECK_ERROR_STATE();
4736 if (frame == NULL) {
4737 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
4738 "missing \
"%s\" tag in the SOF, arc lamp reference lines",
4739 ERIS_IFU_CALIB_REF_LINES);
4746 return cpl_error_get_code();
4771 cpl_error_code err = CPL_ERROR_NONE;
4772 int cut_level_area = 0,
4773 cut_level_intensity = 0;
4774 const char *bandStr = NULL;
4776 cpl_ensure_code(tbl != NULL, CPL_ERROR_NULL_INPUT);
4790 cpl_table *tSlit = NULL,
4793 cpl_msg_debug(cpl_func,
"Removing bad lines");
4794 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4795cpl_msg_debug(cpl_func,
" sIdx: %d", sIdx);
4798 if (
'J' == bandStr[0]) {
4800 cut_level_area = 1000;
4801 cut_level_intensity = 600;
4803 cut_level_area = 90;
4804 cut_level_intensity = 30;
4806 }
else if (
'H' == bandStr[0]) {
4808 cut_level_area = 300;
4809 cut_level_intensity = 150;
4811 cut_level_area = 300/10;
4812 cut_level_intensity = 150/10;
4814 }
else if (
'K' == bandStr[0]) {
4816 cut_level_area = 200;
4817 cut_level_intensity = 100;
4819 cut_level_area = 200/10;
4820 cut_level_intensity = 100/10;
4823 SET_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
"Band must be H, K or J");
4826 cpl_table_unselect_all(tbl);
4827 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4828 cpl_table_and_selected_double(tbl,
"area", CPL_LESS_THAN, cut_level_area);
4829 cpl_table_erase_selected(tbl);
4831 cpl_table_unselect_all(tbl);
4832 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4833 cpl_table_and_selected_double(tbl,
"intensity", CPL_LESS_THAN, cut_level_intensity);
4834 cpl_table_erase_selected(tbl);
4837 cpl_table_unselect_all(tbl);
4838 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4841 tSlit = cpl_table_extract_selected(tbl));
4844 int index_first = cpl_table_get_int(tSlit,
"index", 0, NULL);
4845 cpl_table_unselect_all(tSlit);
4846 cpl_table_or_selected_int(tSlit,
"index", CPL_EQUAL_TO, index_first);
4849 tCol = cpl_table_extract_selected(tSlit));
4853 for (
int i = 0; i < cpl_table_get_nrow(tCol); i++) {
4855 int pos = cpl_table_get_int(tCol,
"position", i, NULL);
4856 cpl_table_unselect_all(tSlit);
4857 cpl_table_or_selected_int(tSlit,
"position", CPL_EQUAL_TO, pos);
4860 tPos = cpl_table_extract_selected(tSlit));
4862 if (cpl_table_get_nrow(tPos) == nr_cols) {
4863 for (
int j = 0; j < cpl_table_get_nrow(tPos); j++) {
4864 int code = cpl_table_get_int(tPos,
"errorcode", j, NULL);
4871 if (good < cpl_table_get_nrow(tPos)/2) {
4873 cpl_table_unselect_all(tbl);
4874 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4875 cpl_table_and_selected_int(tbl,
"position", CPL_EQUAL_TO, pos);
4876 cpl_table_erase_selected(tbl);
4885 cpl_table_unselect_all(tbl);
4886 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4889 tSlit = cpl_table_extract_selected(tbl));
4891 cpl_table_unselect_all(tSlit);
4892 cpl_table_or_selected_int(tSlit,
"errorcode", CPL_NOT_EQUAL_TO, 0);
4895 tPos = cpl_table_extract_selected(tSlit));
4897 for (
int i = 0; i < cpl_table_get_nrow(tPos); i++) {
4898 cpl_table_unselect_all(tSlit);
4899 int pos_bad = cpl_table_get_int(tPos,
"position", i, NULL);
4900 cpl_table_or_selected_int(tSlit,
"position", CPL_EQUAL_TO, pos_bad);
4901 if (cpl_table_count_selected(tSlit) == 1) {
4902 cpl_table_unselect_all(tbl);
4903 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4904 cpl_table_and_selected_int(tbl,
"position", CPL_EQUAL_TO, pos_bad);
4905 cpl_table_erase_selected(tbl);
4946 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4948 cpl_table_unselect_all(tbl);
4949 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
4952 tSlit = cpl_table_extract_selected(tbl));
4955 int index_first = cpl_table_get_int(tSlit,
"index", 0, NULL);
4956 cpl_table_and_selected_int(tbl,
"index", CPL_NOT_EQUAL_TO, index_first+nr_cols/2);
4957 cpl_table_erase_selected(tbl);
4965 cpl_table_unselect_all(tbl);
4966 cpl_table_or_selected_int(tbl,
"errorcode", CPL_NOT_EQUAL_TO, 0);
4967 cpl_table_erase_selected(tbl);
4972 cpl_table_erase_column(tbl,
"imgIdx");
4979 cpl_table_erase_column(tbl,
"mse");
4980 cpl_table_erase_column(tbl,
"wavelengthFit");
4981 cpl_table_erase_column(tbl,
"wavelengthError");
4982 cpl_table_erase_column(tbl,
"range");
4983 cpl_table_erase_column(tbl,
"xdata");
4984 cpl_table_erase_column(tbl,
"ydata");
5007 cpl_error_code err = CPL_ERROR_NONE;
5008 cpl_table *tSlit = NULL;
5012 cpl_msg_debug(cpl_func,
"Removing identical/overlapping lines");
5013 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
5014 cpl_msg_debug(cpl_func,
" sIdx: %d", sIdx);
5017 cpl_table_unselect_all(tbl);
5018 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
5021 tSlit = cpl_table_extract_selected(tbl));
5023 for (
int i = 0; i < cpl_table_get_nrow(tSlit)-1; i++) {
5024 double wl1 = cpl_table_get_double(tSlit,
"wavelength", i+1, NULL),
5025 wl2 = cpl_table_get_double(tSlit,
"wavelength", i, NULL);
5027 if (wl1-wl2 < 0.001) {
5028 cpl_msg_debug(cpl_func,
"Remove:");
5029 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));
5030 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));
5032 int pos1 = cpl_table_get_int(tSlit,
"position", i+1, NULL),
5033 pos2 = cpl_table_get_int(tSlit,
"position", i, NULL);
5035 cpl_table_and_selected_int(tbl,
"position", CPL_EQUAL_TO, pos1);
5036 cpl_table_erase_selected(tbl);
5038 cpl_table_unselect_all(tbl);
5039 cpl_table_or_selected_int(tbl,
"slitlet", CPL_EQUAL_TO, sIdx);
5040 cpl_table_and_selected_int(tbl,
"position", CPL_EQUAL_TO, pos2);
5041 cpl_table_erase_selected(tbl);
5084 cpl_table **centers_fitted,
5086 cpl_image ***arcImgs,
5088 const cpl_parameterlist* parlist,
5092 int corrMask = LINE_EXPOSURE_CORRECTION | COLUMN_EXPOSURE_CORRECTION,
5098 ifsBand band = UNDEFINED_BAND;
5099 ifsPreopticsScale scale = UNDEFINED_SCALE;
5100 ifsInstrument instrument = UNSET_INSTRUMENT;
5101 cpl_image **dataImg = NULL;
5102 const hdrl_image *tmpImg = NULL;
5103 hdrl_imagelist *arcImages = NULL;
5104 cpl_image **collapsedImgDetOrder = NULL;
5105 cpl_propertylist *pl = NULL;
5106 cpl_image **collapsedSpectra = NULL;
5107 cpl_vector *collapsedSpectrum = NULL,
5109 cpl_bivector **refLines = NULL;
5110 const char *refLineTableFileName = NULL,
5111 *firstFitTableFileName = NULL,
5112 *waveSetupFileName = NULL;
5113 cpl_table *firstFitTable = NULL;
5114 cpl_polynomial *firstFit = NULL;
5115 cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y];
5116 struct waveTablesStruct tables;
5117 struct waveSetupStruct waveSetup;
5118 double saturation_threshold = 0;
5125 for (
int ix=0; ix<ERIS_IFU_DETECTOR_SIZE_Y; ix++) {
5129 saturation_threshold = cpl_parameter_get_double(
5130 cpl_parameterlist_find_const(parlist,
"eris.eris_ifu_distortion.pixel_saturation"));
5143 saturation_threshold,
5148 refLines = cpl_calloc(arcImgCnt,
sizeof(cpl_bivector *)));
5150 collapsedSpectra = cpl_calloc(arcImgCnt,
sizeof(cpl_image *)));
5152 dataImg = cpl_calloc(arcImgCnt,
sizeof(cpl_image *)));
5153 *imgCnt = arcImgCnt;
5156 for (
int i = 0; i < arcImgCnt; i++) {
5160 dataImg[i] = cpl_image_duplicate(
5163 nRows = cpl_image_get_size_y(dataImg[0]);
5166 refLineTableFileName = cpl_frame_get_filename(
5167 cpl_frameset_find(fs, ERIS_IFU_CALIB_REF_LINES));
5168 for (
int ix = 0; ix < arcImgCnt; ix++) {
5171 refLineTableFileName, instrument,
5177 centerss = cpl_vector_new(SLITLET_CNT);
5178 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
5180 cpl_table *centers = centers_fitted[sIdx];
5181 double *dd = cpl_table_get_data_double(centers,
"x");
5182 cpl_vector *vcen = cpl_vector_wrap (cpl_table_get_nrow(centers), dd);
5183 double ddd = cpl_vector_get_mean(vcen);
5184 cpl_vector_set(centerss,sIdx, ddd);
5185 cpl_vector_unwrap(vcen);
5198 for (
int aIdx = 0; aIdx < arcImgCnt; aIdx++) {
5199 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
5200 center = (int) cpl_vector_get (centerss, sIdx);
5203 dataImg[aIdx], center);
5206 collapsedSpectrum, sIdx, nRows,
5207 lampStates[aIdx], band, instrument,
5208 refLines[aIdx], productDepth);
5215 firstFitTableFileName = cpl_frame_get_filename(
5216 cpl_frameset_find(fs, ERIS_IFU_CALIB_FIRST_FIT));
5217 if (firstFitTableFileName == NULL) {
5219 "missing \"ERIS_IFU_CALIB_FIRST_FIT\" tag in the SOF, wavecal first fit table");
5223 firstFitTableFileName, instrument, band));
5225 waveSetupFileName = cpl_frame_get_filename(
5226 cpl_frameset_find(fs, ERIS_IFU_CALIB_WAVE_SETUP));
5227 if (waveSetupFileName == NULL) {
5229 "missing \"ERIS_IFU_CALIB_WAVE_SETUP\" tag in the SOF, wavecal setup table");
5236 const int slitlet2collapsed[SLITLET_CNT] = {
5237 0, 15, 1, 16, 2, 17, 3, 18, 4, 19, 5, 20, 6, 21, 7,
5239 22, 8, 23, 9, 24, 10, 25, 11, 26, 12, 27, 13, 28, 14, 29};
5241 collapsedImgDetOrder =
5242 cpl_calloc(arcImgCnt,
sizeof(cpl_image *));
5243 for (
int aIdx = 0; aIdx < arcImgCnt; aIdx++) {
5244 cpl_size xSize = cpl_image_get_size_x(collapsedSpectra[aIdx]);
5245 cpl_size ySize = cpl_image_get_size_y(collapsedSpectra[aIdx]);
5246 collapsedImgDetOrder[aIdx] =
5247 cpl_image_new(xSize, ySize, CPL_TYPE_DOUBLE);
5248 double *in = cpl_image_get_data_double(collapsedSpectra[aIdx]);
5249 double *out = cpl_image_get_data_double(collapsedImgDetOrder[aIdx]);
5250 for (
int sx=0; sx < SLITLET_CNT; sx++) {
5251 int ix = slitlet2collapsed[sx];
5252 for (
int iy = 0; iy < ySize; iy++){
5253 out[sx+iy*xSize] = in[ix+iy*xSize];
5260 int firstFitMasterOffset = 0;
5263 lampStates, arcImgCnt, 16, 0, &firstFitMasterOffset,
5264 waveSetup, firstFitTable,
5265 tables.slitletFitting, tables.slitletCoeff));
5266 cpl_msg_info(__func__,
"FirstFit Master Offset %d", firstFitMasterOffset);
5268 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
5271 lampStates, arcImgCnt, sIdx, firstFitMasterOffset, &firstFitOffset,
5272 waveSetup, firstFitTable,
5273 tables.slitletFitting, tables.slitletCoeff));
5280 const double column[] = {0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,
5281 10.,11.,12.,13.,14.,15.,16.,17.,18.,19.,
5282 20.,21.,22.,23.,24.,25.,26.,27.,28.,29.,30.,31,};
5285 arcImgCnt, (
const cpl_image **) collapsedImgDetOrder, refLines,
5286 waveSetup, firstFit, allFits,
5287 tables.columnFitting, tables.columnCoeffRaw,
5288 tables.columnCoeffSmoothed, tables.smoothingCoeff));
5290 cpl_table_unselect_all(tables.columnFitting);
5291 cpl_table_or_selected_int(tables.columnFitting, ERIS_IFU_FITTABLE_SLITLET, CPL_EQUAL_TO, sIdx);
5292 for (
int rx = 0; rx < cpl_table_get_nrow(tables.columnFitting); rx++) {
5293 if (cpl_table_is_selected(tables.columnFitting, rx) == 1) {
5294 cpl_table_set_int(tables.columnFitting, ERIS_IFU_FITTABLE_INDEX, rx, (
int) cpl_vector_get (centerss, sIdx));
5300 if (productDepth > 3 ) {
5303 waveSetup, fs, parlist,
5304 "eris_ifu_distortion"));
5306 cpl_table_unselect_all(tables.columnFitting);
5307 cpl_table_or_selected_int(tables.columnFitting, ERIS_IFU_FITTABLE_ERRORCODE, CPL_NOT_EQUAL_TO, 0);
5308 BRK_IF_ERROR(cpl_table_erase_selected(tables.columnFitting));
5311 cpl_table_unselect_all(tables.columnFitting);
5312 cpl_table_new_column(tables.columnFitting,
"intensity", CPL_TYPE_DOUBLE);
5313 for (
int i = 0; i < cpl_table_get_nrow(tables.columnFitting); i++) {
5314 double sigma = cpl_table_get_double(tables.columnFitting,
"sigma", i, NULL),
5315 area = cpl_table_get_double(tables.columnFitting,
"area", i, NULL),
5316 offset = cpl_table_get_double(tables.columnFitting,
"offset", i, NULL);
5318 double inten = area / sqrt(2.*(
double)CX_PI*pow(sigma,2)) + offset;
5319 if ((inten - offset) > 20. && sigma < 2.) {
5321 cpl_table_set_double(tables.columnFitting,
"intensity", i, inten);
5324 cpl_table_or_selected_window(tables.columnFitting, i, 1);
5328 BRK_IF_ERROR(cpl_table_erase_selected(tables.columnFitting));
5335 pl = cpl_propertylist_new());
5337 cpl_propertylist_append_bool(pl,
"position", CPL_TRUE));
5339 cpl_table_sort(tables.columnFitting, pl));
5344 if ((productDepth & 3) != 0) {
5346 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
5347 cpl_table_unselect_all(tables.columnFitting);
5348 cpl_table_or_selected_int(tables.columnFitting, ERIS_IFU_FITTABLE_SLITLET, CPL_EQUAL_TO, sIdx);
5349 cpl_table *t = cpl_table_extract_selected(tables.columnFitting);
5356 cpl_table_save(t, NULL, NULL,
"eris_ifu_distortion_dbg_wave_fit_lines.fits", c));
5365 cpl_free(lampStates);
5369 for (
int ix=0; ix<arcImgCnt; ix++) {
5375 cpl_free(collapsedSpectra);
5376 cpl_free(collapsedImgDetOrder);
5377 for (
int ix=0; ix<ERIS_IFU_DETECTOR_SIZE_Y; ix++) {
5387 return tables.columnFitting;
cpl_polynomial * eris_ifu_get_first_fit(cpl_image **spectra, int *lampStates, int spectrumCnt, int slitlet, int ffOffsetIn, int *ffOffsetOut, struct waveSetupStruct waveSetup, cpl_table *firstFitTable, cpl_table *fittingDumpTable, cpl_table *coeffDumpTable)
Generate initial wavelength fit for a slitlet.
void eris_ifu_wave_save_spectrum(cpl_image **collapsedSpectra, int aIdx, cpl_vector *collapsedSpectrum, int sIdx, cpl_size nRows, int lampStatus, ifsBand band, ifsInstrument instrument, cpl_bivector *refLines, int productDepth)
Save collapsed spectrum to product file.
cpl_bivector * eris_ifu_wave_get_refLines(const char *refLineTableFileName, ifsInstrument instrument, int lampState)
Load reference arc line wavelengths for specified lamp configuration.
cpl_error_code eris_ifu_fit_all_lines(const char *recipe_name, int sIdx, const double *slitletStart, const double *slitletEnd, int arcImgCnt, const cpl_image **dataImg, cpl_bivector **refLines, struct waveSetupStruct waveSetup, cpl_polynomial *firstFit, cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y], cpl_table *dumpTable, cpl_table *columnCoeffRawTable, cpl_table *columnCoeffSmoothedTable, cpl_table *smoothingCoeffTable)
Fit all reference lines in a slitlet across detector columns.
void eris_ifu_wave_clear_tables(struct waveTablesStruct *tables)
Clear wavelength table pointers without freeing.
cpl_error_code eris_ifu_wave_init_tables(struct waveTablesStruct *tables)
Initialize wavelength fitting tables.
cpl_error_code eris_ifu_wave_save_fitting_tables(struct waveTablesStruct *tables, ifsInstrument instrument, ifsBand band, struct waveSetupStruct waveSetup, cpl_frameset *frameset, const cpl_parameterlist *parlist, const char *recipe_name)
Save all wavelength fitting tables to FITS file.
cpl_vector * eris_ifu_wave_collapse_slitlet(const cpl_image *dataImg, int center)
Collapse slitlet spatially to create 1D spectrum.
cpl_error_code eris_ifu_read_wave_setup(const char *filename, ifsBand band, struct waveSetupStruct *waveSetup)
Read wavelength setup parameters from configuration file.
cpl_table * eris_ifu_wave_get_firstFitTable(const char *firstFitTableFileName, ifsInstrument instrument, ifsBand band)
Load first fit table for instrument and band.
cpl_error_code eris_ifu_dist_warp_stats(const hdrl_image *hdrlWarpedImg, cpl_propertylist *qc_list, cpl_propertylist *pl, cpl_frameset *frameset, const cpl_parameterlist *parlist)
Compute QC statistics on warped image.
cpl_error_code eris_ifu_wavecal_processSof_dist(cpl_frameset *frames, int exposureCorrectionMode, int *arcImgCnt, hdrl_imagelist **arcImages, int **lampStates, ifsBand *band, ifsPreopticsScale *scale, ifsInstrument *instrument, double saturation_threhold, cpl_table **qclog)
Process arc lamp images for distortion calibration.
cpl_vector * eris_ifu_dist_estimate_low_slitlet(const cpl_vector *est_centers)
Estimate position of missing low slitlet.
cpl_table ** eris_ifu_dist_calc_centers(const hdrl_image *fibre_div, const hdrl_image *fibre_on, int productDepth)
Calculate slitlet centers across the detector.
cpl_polynomial ** eris_ifu_dist_calc_distortion(cpl_table **slit_edges, cpl_table **centers, int productDepth, cpl_boolean cut_off_left, cpl_boolean cut_off_right, cpl_table **minmax_borders, cpl_propertylist ***qc, cpl_propertylist *pl, cpl_frameset *frameset, const cpl_parameterlist *parlist)
Calculate distortion polynomials for all slitlets.
cpl_error_code eris_ifu_distortion_reduce_identical_lines(cpl_table *tbl)
Remove duplicate or overlapping arc lines.
eris_ifu_vector * eris_ifu_dist_calc_distortion_fitedge(const cpl_table *edge, const char *col_name, const eris_ifu_vector *y, int n_calib, int n_size, int fit_order, int slitlet, cpl_table *dbg_tbl)
Fit polynomial to single edge as function of Y.
int eris_ifu_distortion_get_narcs(int i, cpl_boolean triple_traces, cpl_boolean cut_off_left, cpl_boolean cut_off_right)
Determine number of arc traces to process for a slitlet.
cpl_error_code eris_ifu_distortion_reduce_lines(cpl_table *tbl, ifsBand band, int nr_cols)
Filter valid arc lines by intensity and fit quality.
cpl_table * eris_ifu_dist_wave(cpl_frameset *fs, cpl_table **centers_fitted, int productDepth, cpl_image ***arcImgs, int *imgCnt, const cpl_parameterlist *parlist, cpl_table **qclog)
Perform wavelength calibration to identify valid arc lines.
cpl_vector * eris_ifu_dist_calc_centers_fit(const cpl_vector *profile, const cpl_vector *est_centers, cpl_boolean do_fix_cnt)
Fit Gaussian profiles to refine center positions.
cpl_vector * eris_ifu_dist_calc_centers_profile(const cpl_vector *profile, cpl_boolean lowerCutLevel)
Detect peak positions from a collapsed profile.
cpl_error_code eris_ifu_dist_calc_centers_copy(const cpl_vector *fit_centers, int y_index, double y_value, cpl_table **cen_array)
Copy fitted centers to the output table array.
#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 for debugging (quick, no DFS overhead)
void eris_ifu_free_table(cpl_table **item)
Free memory and set pointer to null.
const char * eris_ifu_get_bandString(ifsBand band)
Convert band enum to string.
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 using median instead of mean.
int eris_ifu_vector_count_non_rejected(const eris_ifu_vector *ev)
Count the number of non-rejected elements in a eris_ifu_vector.
int eris_ifu_vector_is_rejected(const eris_ifu_vector *ev, int n)
Test if a value is good or bad.
cpl_error_code eris_ifu_vector_subtract(eris_ifu_vector *kv1, const eris_ifu_vector *kv2)
Subtract two eris_ifu_vectors.
eris_ifu_vector * eris_ifu_vector_duplicate(const eris_ifu_vector *ev)
This function duplicates an existing eris_ifu_vector and allocates memory.
eris_ifu_vector * eris_ifu_vector_new_wrap(int n, const double *data)
Create a new eris_ifu_vector from a C array (duplicated).
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.
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_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.
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.
double eris_ifu_vector_get_mean(const eris_ifu_vector *ev)
Compute the mean value of non-rejected eris_ifu_vector elements.
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.