ERIS Pipeline Reference Manual 1.9.2
eris_ifu_distortion_static.c
1/* $Id$
2 *
3 * This file is part of the ERIS Pipeline
4 * Copyright (C) 2002,2003 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
47#include <string.h>
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"
55
73cpl_vector* eris_ifu_dist_calc_centers_profile(const cpl_vector* profile,
74 cpl_boolean lowerCutLevel)
75{
76 int cnt = 0,
77 est_cnt = 0;
78 cpl_size nx;
79 double mean = 0.,
80 cut_level = 0.,
81 cut_factor = 1.4,
82 left = 0.,
83 right = 0.,
84 width = 0.,
85 *ppos = NULL,
86 *pheight = NULL;
87 const double *pprofile = NULL;
88 cpl_vector *pos = NULL,
89 *height = NULL,
90 *cen_estimates = NULL;
91
92 cpl_ensure(profile != NULL, CPL_ERROR_NULL_INPUT, NULL);
93
94 TRY
95 {
96 nx = cpl_vector_get_size(profile);
97
98 if (lowerCutLevel) {
99 cut_factor = 1.0;
100 }
101 /* determine the mean of the row data, multiply scalar to get a
102 * level around half-max just to be sure to omit low-level outliers */
103 eris_ifu_vector *collapsed_vec2 = eris_ifu_vector_create(profile);
104 mean = eris_ifu_vector_get_mean(collapsed_vec2);
105 cut_level = cut_factor * mean;
106
107 //cut_level = 2 * eris_ifu_vector_get_mean(collapsed_vec2) * 0.8;
108 eris_ifu_free_ifu_vector(&collapsed_vec2);
109
110 /* search for left/right edge of slitlet,
111 * subtract to get center and store
112 * (ignoring bad-pix-border on left and right side of detector)
113 * (max. size would be 3*SLITLET_CNT, but allow for more to prevent seg. fault)
114 */
116 pos = cpl_vector_new(3*SLITLET_CNT+20));
118 height = cpl_vector_new(3*SLITLET_CNT+20));
119 BRK_IF_ERROR(cpl_vector_multiply_scalar(height, 0.0));
121 ppos = cpl_vector_get_data(pos));
123 pheight = cpl_vector_get_data(height));
124
126 pprofile = cpl_vector_get_data_const(profile));
127
128 for (cut_factor = 1.4; cut_factor > .1; cut_factor -= 0.2) {
129 cut_level = cut_factor * mean;
130 cnt = 0;
131
132 for (int i = ERIS_IFU_DETECTOR_BP_BORDER;
133 i < nx-ERIS_IFU_DETECTOR_BP_BORDER;
134 i++)
135 {
136 /* find left edge */
137 if ((left == 0) && (pprofile[i] > cut_level)) {
138 left = i;
139 }
140 /* find right edge */
141 if (((left != 0) && (right == 0)) &&
142 ((pprofile[i] < cut_level) || (i == nx-ERIS_IFU_DETECTOR_BP_BORDER-1))) {
143 right = i-1;
144 }
145 /* found left/right-edge, calc center, reset & continue */
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) ];
150 cnt++;
151 left = 0;
152 right = 0;
153 }
154 if (cnt >= cpl_vector_get_size(pos)) {
155 break;
156 }
157 }
158 if (cnt == SLITLET_CNT || cnt == 3 * SLITLET_CNT) {
159 est_cnt = cnt;
160 break;
161 }
162 if (cnt > SLITLET_CNT && cnt < SLITLET_CNT + 20) {
163 est_cnt = SLITLET_CNT;
164 break;
165 }
166 if (cnt > 3 * SLITLET_CNT) {
167 est_cnt = 3 * SLITLET_CNT;
168 break;
169 }
170 }
171
172 // if there are too many peaks, sort the arrays to remove the lowest peaks
173 if (cnt > est_cnt) {
174 cpl_bivector *toBeSorted = NULL;
175 BRK_IF_NULL(toBeSorted = cpl_bivector_wrap_vectors(pos, height));
176 BRK_IF_ERROR(cpl_bivector_sort(toBeSorted, toBeSorted,
177 CPL_SORT_DESCENDING, CPL_SORT_BY_Y));
178 cpl_bivector_unwrap_vectors(toBeSorted);
179 cnt = est_cnt;
180 }
181
182 /* now we know the number of detected traces, extract the significant
183 * part of the vector to return */
185 cen_estimates = cpl_vector_extract(pos, 0, cnt-1, 1));
186 //
187 BRK_IF_ERROR(cpl_vector_sort(cen_estimates, CPL_SORT_ASCENDING));
188
189// cpl_msg_debug(cpl_func," est. profile: cutlevel: %g, #peaks: %d", cut_level, (int)cpl_vector_get_size(cen_estimates));
190 }
191 CATCH
192 {
193 CATCH_MSGS();
194 eris_ifu_free_vector(&cen_estimates);
195 }
196
198 eris_ifu_free_vector(&height);
199
200 return cen_estimates;
201}
202
218cpl_vector* eris_ifu_dist_estimate_low_slitlet(const cpl_vector *est_centers)
219{
220 cpl_vector *est_new = NULL,
221 *est_new2 = NULL;
222 double *pest_new = NULL;
223 const double *pest_centers = NULL;
224 cpl_size cnt = 0,
225 ind = 0;
226
227 cpl_ensure(est_centers, CPL_ERROR_NULL_INPUT, NULL);
228
229 TRY
230 {
232 pest_centers = cpl_vector_get_data_const(est_centers));
233
234 cnt = cpl_vector_get_size(est_centers);
235 if ((cnt == SLITLET_CNT) || (cnt == 3*SLITLET_CNT)) {
236 // all slitlet seem to be detected correctly
238 est_new = cpl_vector_duplicate(est_centers));
239 return est_new;
240 } else if (cnt < SLITLET_CNT) {
241 // 25mas: slitlet missing
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)) {
246 // 100mas/250mas: slitlet missing
248 est_new = cpl_vector_new(3*SLITLET_CNT));
249 cpl_vector_fill(est_new, 0.);
250 } else {
251 // more than 3*32 slitlets or 33-43 slitlets
252 // there are too many slitlets, handle elsewhere
254 est_new = cpl_vector_duplicate(est_centers));
255 return est_new;
256 }
258 cpl_vector_multiply_scalar(est_new, 0.));
260 pest_new = cpl_vector_get_data(est_new));
261
262 if (cnt < SLITLET_CNT) {
263 // 25mas
264 ind = 11;
265
266 // locate position of missing slitlet (not always on pos. 15 because a slitlet could be cut off on left of right of detector)
267 // because of this look up to 3 slitlets to left and right
268 while ((fabs(pest_centers[ind+1]-pest_centers[ind]-2*SLITLET_WIDTH) > 10) && (ind < 18)) {
269 ind++;
270
271 }
272
273 for (int i = 0; i < ind+1; i++) {
274 pest_new[i] = pest_centers[i];
275 }
276 // add in missing value
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];
280 }
281 } else {
282 // 100mas or 250mas
283 // start checking from slitlet #5 on until #18 (#14 and #16 are bad)
284 int start_slit = 5,
285 end_slit = 18;
286 ind = 3*start_slit;
287 cpl_size i = 0;
288 // just copy, don't check
289 for (i = 0; i < ind+1; i++) {
290 pest_new[i] = pest_centers[i];
291 }
292
293 // check distances, if correct: copy, if not: estimate & copy
294 ind = 3*start_slit + 1;
295 i = ind;
296 cpl_boolean found = CPL_FALSE;
297 int decr_found = 0,
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;
303 decr_found--;
304 }
305 if (val < 5) {
306 // position is correct
307 pest_new[i++] = pest_centers[ind++];
308 } else {
309 // position is missing
310 pest_new[i] = pest_centers[ind-3]+SLITLET_WIDTH;
311 i++;
312 pest_new[i] = pest_centers[ind++];
313 i++;
314 found = CPL_TRUE;
315 decr_found = 2;
316 }
317 }
318
319 // just copy, don't check
320 for (; i < 3*SLITLET_CNT; i++) {
321 if (ind < cnt) {
322 pest_new[i] = pest_centers[ind++];
323 }
324 }
325 }
326
327 // check if there are trailing zeros.
328 // If yes cut them. This is indicating that the profile is cut off at the left or right border
329 cnt = cpl_vector_get_size(est_new);
330 ind = cnt-1;
331 while (pest_new[ind] < 0.0001 && ind > 0) {
332 ind--;
333 }
334 if (ind != cnt-1) {
336 est_new2 = cpl_vector_extract(est_new, 0, ind, 1));
337 eris_ifu_free_vector(&est_new);
338 est_new = est_new2;
339 }
340 }
341 CATCH
342 {
343 CATCH_MSGS();
344 eris_ifu_free_vector(&est_new);
345 }
346
347 return est_new;
348}
349
371cpl_vector* eris_ifu_dist_calc_centers_fit(const cpl_vector *profile,
372 const cpl_vector *est_centers,
373 cpl_boolean do_fix_cnt)
374{
375 int cnt = 0,
376 cnt2 = 0,
377 cen = 0,
378 start = 0,
379 end = 0,
380 j = 0;
381 double med = 0.,
382 std = 0.,
383 thresh1 = 1.5,
384 thresh2 = 2.5,
385 lastValidOffset = 0.,
386 *pfit_centers = NULL,
387 *pfit_peaks = NULL;
388 cpl_vector *fit_centers = NULL,
389 *fit_peaks = NULL,
390 *est_centers2 = NULL;
391 cpl_boolean fix_cnt = FALSE;
392 struct gaussParStruct gaussPar;
393 eris_ifu_vector *v = NULL,
394 *ve = NULL;
395
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);
400
401 TRY
402 {
404 est_centers2 = eris_ifu_dist_estimate_low_slitlet(est_centers));
405
406 cnt = (int) cpl_vector_get_size(est_centers2);
407
408 if (do_fix_cnt) {
409 // check if less than 32 traces
410 if (cnt < SLITLET_CNT) {
411 cpl_msg_error(cpl_func, "Detected %d traces instead of at least %d!",
412 cnt2, SLITLET_CNT);
413 SET_ERROR(CPL_ERROR_ILLEGAL_INPUT);
414 }
415
416 // check if less than 96 traces (and more than 32 of course)
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);
420 SET_ERROR(CPL_ERROR_ILLEGAL_INPUT);
421 }
422 }
423
424 // we have more than 32 or 96 traces, has to fixed!
425 if (do_fix_cnt && (cnt != SLITLET_CNT) && (cnt != 3*SLITLET_CNT)) {
426 fix_cnt = CPL_TRUE;
427 }
428
429 // fit gaussians to all estimated centers in order to get position and
430 // amplitude. If needed we fix the number of detected traces using
431 // statistics on the amplitude
433 fit_centers = cpl_vector_new(cnt));
435 pfit_centers = cpl_vector_get_data(fit_centers));
436 if (fix_cnt) {
438 fit_peaks = cpl_vector_new(cnt));
440 pfit_peaks = cpl_vector_get_data(fit_peaks));
441 }
442
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));
448
449 if (gaussPar.errorCode == 0) {
450 pfit_centers[i] = gaussPar.x0;
451 lastValidOffset =
452 pfit_centers[i] - cpl_vector_get(est_centers2, i);
453 } else if (i != 0) {
454 pfit_centers[i] = cpl_vector_get(est_centers2, i) +
455 lastValidOffset;
456 }
457 if (fix_cnt) {
458 pfit_peaks[i] = gaussPar.area
459 / sqrt(2*CPL_MATH_PI*pow(gaussPar.sigma,2))
460 + gaussPar.offset;
461 }
462 }
463
464 if (fix_cnt) {
466 v = eris_ifu_vector_create(fit_peaks));
467
468 // check if there are any outliers on the left side of detector
469 // (especially some wrong edge on the very left border,
470 // therefore check the leftmost slitlets)
471 start = 0;
472 end = cnt/10*2;
474 ve = eris_ifu_vector_extract(v, start, end));
475 med = eris_ifu_vector_get_median(ve, ERIS_IFU_ARITHMETIC);
477 if (std > 0.1) {
478 // reject only if stddev is significant
479 j = 0;
480 for (int i = start; i <= end; i++) {
481 double val = eris_ifu_vector_get(ve, j++);
482 if ((val < med-thresh1*std) || (val > med+thresh1*std)) {
484 }
485 }
486 }
488
489 // check if there are any outliers on the right side of detector
490 start = cnt-1-cnt/10*2;
491 end = cnt-1;
493 ve = eris_ifu_vector_extract(v, start, end));
494 med = eris_ifu_vector_get_median(ve, ERIS_IFU_ARITHMETIC);
496 if (std > 0.1) {
497 // reject only if stddev is significant
498 j = 0;
499 for (int i = start; i <= end; i++) {
500 double val = eris_ifu_vector_get(ve, j++);
501 if ((val < med-thresh1*std) || (val > med+thresh1*std)) {
503 }
504 }
505 }
507
508 // still too many slitlets ?
510 if ((cnt2 != SLITLET_CNT) && (cnt2 != 3*SLITLET_CNT)) {
511 // now do a median across whole array and reject
512 med = eris_ifu_vector_get_median(v, ERIS_IFU_ARITHMETIC);
514 for (int i = 0; i <= end; i++) {
515 if (!eris_ifu_vector_is_rejected(v, i)) {
516 double val = eris_ifu_vector_get(v, i);
517 if ((val < med-thresh2*std) || (val > med+thresh2*std)) {
519 }
520 }
521 }
522 }
523
524 // last check
526 if ((cnt2 != SLITLET_CNT) && (cnt2 != 3*SLITLET_CNT)) {
527 int cnt3 = 0;
528 if (abs(SLITLET_CNT-cnt2) < 10) {
529 cnt3 = SLITLET_CNT;
530 }
531 if (abs(3*SLITLET_CNT-cnt2) < 10) {
532 cnt3 = 3*SLITLET_CNT;
533 }
534
535 cpl_msg_error(cpl_func, "Detected %d traces instead of %d!", cnt2, cnt3);
536 SET_ERROR(CPL_ERROR_ILLEGAL_OUTPUT);
537 } else {
538 // we have now 32 or 3*32 traces!
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));
545 j = 0;
546 for (int i = 0; i < cnt; i++) {
547 if (!eris_ifu_vector_is_rejected(v, i)) {
548 pfit_centers2[j++] = pfit_centers[i];
549 }
550 }
551 cpl_vector_delete(fit_centers);
552 fit_centers = fit_centers2;
553 }
554 } // end: fix_cnt
555 }
556 CATCH
557 {
558 CATCH_MSGS();
559 eris_ifu_free_vector(&fit_centers);
560 }
561
562 eris_ifu_free_vector(&est_centers2);
565 eris_ifu_free_vector(&fit_peaks);
566
567 return fit_centers;
568}
569
586cpl_error_code eris_ifu_dist_calc_centers_copy(const cpl_vector *fit_centers,
587 int y_index,
588 double y_value,
589 cpl_table **cen_array)
590{
591 int actual_size = 0,
592 index_to_compare = 0,
593 tmp = 0;
594 double last_val = 0.,
595 actual_val = 0.;
596 cpl_error_code err = CPL_ERROR_NONE;
597 const double *pfit_centers = NULL;
598
599 cpl_ensure_code(fit_centers, CPL_ERROR_NULL_INPUT);
600 cpl_ensure_code(cen_array, CPL_ERROR_NULL_INPUT);
601
602 TRY
603 {
604 actual_size = (int) cpl_vector_get_size(fit_centers);
606 pfit_centers = cpl_vector_get_data_const(fit_centers));
607
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]));
614 }
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));
619
620 // process 1st line
622 cpl_table_set_double(cen_array[i], "x_l", y_index, pfit_centers[3*i]));
623
624 // process 2nd line
626 cpl_table_set_double(cen_array[i], "x", y_index, pfit_centers[3*i+1]));
627
628 // process 3rd line
630 cpl_table_set_double(cen_array[i], "x_r", y_index, pfit_centers[3*i+2]));
631 }
632 } else {
633 cpl_boolean special_handling = CPL_FALSE;
634
635 if (y_index < cpl_table_get_nrow(cen_array[0])/2) {
636 // lower detector part: compare more to the middle
637 index_to_compare = y_index+1;
638 } else {
639 // higher detector part: compare more to the middle
640 index_to_compare = y_index-1;
641 }
642
643 if (!special_handling && (actual_size < 3*SLITLET_CNT)) {
644 // check if left edge is cut off from image
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.)) {
648 // left edge is here!
649 // fill from left to right until end of vector with actual_vals is reached
650 // (it is supposed that max 1-2 traces are missing)
651 tmp = 0;
652 for (int i = 0; i < SLITLET_CNT; i++) {
654 cpl_table_set_double(cen_array[i], "y", y_index, y_value));
655
656 // process 1st line
658 cpl_table_set_double(cen_array[i], "x_l", y_index, pfit_centers[3*i]));
659 if (++tmp == actual_size) break;
660
661 // process 2nd line
663 cpl_table_set_double(cen_array[i], "x", y_index, pfit_centers[3*i+1]));
664 if (++tmp == actual_size) break;
665
666 // process 3rd line
668 cpl_table_set_double(cen_array[i], "x_r", y_index, pfit_centers[3*i+2]));
669 if (++tmp == actual_size) break;
670 }
671 special_handling = CPL_TRUE;
672 }
673
674 // check if right edge is cut off from image
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.)) {
678 // right edge is here!
679 // fill from rihgt to left until end of vector with actual_vals is reached
680 // (it is supposed that max 1-2 traces are missing)
681 tmp = actual_size;
682 for (int i = SLITLET_CNT-1; i >= 0; i--) {
684 cpl_table_set_double(cen_array[i], "y", y_index, y_value));
685
686 // process 3rd line
688 cpl_table_set_double(cen_array[i], "x_r", y_index, pfit_centers[tmp-1]));
689 if (--tmp == actual_size) break;
690
691 // process 2nd line
693 cpl_table_set_double(cen_array[i], "x", y_index, pfit_centers[tmp-1]));
694 if (--tmp == actual_size) break;
695
696 // process 1st line
698 cpl_table_set_double(cen_array[i], "x_l", y_index, pfit_centers[tmp-1]));
699 if (--tmp == actual_size) break;
700 }
701 special_handling = CPL_TRUE;
702 }
703 } // if (actual_size < 3*SLITLET_CNT)
704
705 if (!special_handling && (actual_size < SLITLET_CNT)) {
706 // check if left edge is cut off from image
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.)) {
710 // left edge is here!
711 // fill from left to right until end of vector with actual_vals is reached
712 // (it is supposed that max 1-2 traces are missing)
713 tmp = 0;
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;
720 }
721 special_handling = CPL_TRUE;
722 }
723
724 // check if right edge is cut off from image
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.)) {
728 // right edge is here!
729 // fill from right to left until end of vector with actual_vals is reached
730 // (it is supposed that max 1-2 traces are missing)
731 tmp = actual_size;
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;
738 }
739 special_handling = CPL_TRUE;
740 }
741 } // if (actual_size < SLITLET_CNT)
742
743 if (!special_handling) {
744 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_OUTPUT,
745 "Handling of trace running out of "
746 "detector image failed!!!");
747 }
748 } // if actual_size = ...
749 }
750 CATCH
751 {
752 CATCH_MSGS();
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.);
756 }
757
758 err = cpl_error_get_code();
759 }
760
761 return err;
762}
763
785cpl_table** eris_ifu_dist_calc_centers(const hdrl_image* fibre_div,
786 const hdrl_image *fibre_on,
787// cpl_boolean is25mas,
788// cpl_boolean isK,
789 int productDepth)
790{
791 int cnt = 0,
792 nr_values = 21, //odd
793 // ny = 0,
794 center_y = 0,
795 height = 96, // even
796// ix_middle = nr_values / 2 + 1;
797 ix_middle = 9;
798 const cpl_image *img = NULL,
799 *img_div = NULL,
800 *img_on = NULL;
801 cpl_vector *profile_x = NULL,
802 *profile_x_div = NULL,
803 *profile_x_on = NULL,
804 *est_centers = NULL,
805 *est_centers_div = NULL,
806 *est_centers_on = NULL,
807 *fit_centers = NULL,
808 *fit_centers_middle = NULL;
809 cpl_table **cen_array = NULL;
810
811
812 cpl_ensure(fibre_div, CPL_ERROR_NULL_INPUT, NULL);
813 cpl_ensure(fibre_on, CPL_ERROR_NULL_INPUT, NULL);
814 // nr_values should be odd, since we process first the middle value
815 // and the the lower part resp. upper part
816 cpl_ensure(nr_values % 2 == 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
817 cpl_ensure(height % 2 == 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
818
819 TRY
820 {
821
823 img_on = hdrl_image_get_image_const(fibre_on));
825 img_div = hdrl_image_get_image_const(fibre_div));
826
827// ny = (int) cpl_image_get_size_y(img_div);
828
830 cen_array = cpl_calloc(SLITLET_CNT, sizeof(cpl_table*)));
831
832 /* - take horizontal chunk of height 96 in the middle of detector in x
833 * - collapse in y
834 * - get profile
835 * - estimate centers
836 * - allocate arrays accordingly (32 or 3*32 tables)
837 * - fit centers
838 * - store in the middle line of whole array
839 */
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));
847
849 est_centers_div = eris_ifu_dist_calc_centers_profile(profile_x_div, CPL_FALSE));
851 est_centers_on = eris_ifu_dist_calc_centers_profile(profile_x_on, CPL_FALSE));
852
853 // will return a vector with 32 or 3*32 center values (errors are catched)
855 fit_centers_middle = eris_ifu_dist_calc_centers_fit(
856 profile_x_on, est_centers_on, CPL_TRUE));
857
858 if (productDepth & 4) {
859 cpl_propertylist *pl = NULL;
861 pl = cpl_propertylist_new());
862 eris_ifu_save_vector_dbg(NULL, ERIS_IFU_DIST_DBG_FN, CPL_IO_CREATE, pl);
864 cpl_propertylist_update_string(pl, "EXTNAME", "profile_x_div"));
865 eris_ifu_save_vector_dbg(profile_x_div,
866 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
868 cpl_propertylist_update_string(pl, "EXTNAME", "profile_x_on"));
869 eris_ifu_save_vector_dbg(profile_x_on,
870 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
872 cpl_propertylist_update_string(pl, "EXTNAME", "est_centers_div"));
873 eris_ifu_save_vector_dbg(est_centers_div,
874 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
876 cpl_propertylist_update_string(pl, "EXTNAME", "est_centers_on"));
877 eris_ifu_save_vector_dbg(est_centers_on,
878 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND,pl );
880 cpl_propertylist_update_string(pl, "EXTNAME", "fit_centers_middle"));
881 eris_ifu_save_vector_dbg(fit_centers_middle,
882 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND,pl);
884 }
885 eris_ifu_free_vector(&profile_x_div);
886 eris_ifu_free_vector(&profile_x_on);
887 eris_ifu_free_vector(&est_centers_div);
888 eris_ifu_free_vector(&est_centers_on);
889 eris_ifu_free_vector(&fit_centers);
890
891 /* in the 1st iteration we know now the number of fibre traces
892 * (one or three per slitlet)
893 * --> Allocate images to hold all centers*/
894 cnt = (int) cpl_vector_get_size(fit_centers_middle);
895
896 if (cnt == SLITLET_CNT) {
897 // one trace per slitlet
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++) {
906 // init to NaN
907 cpl_table_set(cen_array[j], "x", i, NAN);
908 cpl_table_set(cen_array[j], "y", i, NAN);
909 }
910 }
911 } else {
912 // three traces per slitlet
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++) {
925 // init to NaN
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);
930 }
931 }
932 }
933
934//erw if (isK/*25mas*/) {
935 if (CPL_TRUE) {
936 img = img_on;
937 } else {
938 img = img_div;
939 }
940 // now do the same for the whole detectors in two blocks
941 // center to top and center to bottom
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;
946 /* collapse image in y and convert to vector */
949 img, center_y, height));
950 /* do least square fit using a Gaussian in order to get exact centers */
952 fit_centers = eris_ifu_dist_calc_centers_fit(profile_x, est_centers, CPL_FALSE));
953
954 /* copy all values into image-array to hold all values */
956 eris_ifu_dist_calc_centers_copy(fit_centers, i, center_y,
957 cen_array));
958
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);
966 eris_ifu_free_string(&extname);
967 eris_ifu_save_vector_dbg(profile_x,
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);
971 eris_ifu_free_string(&extname);
972 eris_ifu_save_vector_dbg(est_centers,
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);
976 eris_ifu_free_string(&extname);
977 eris_ifu_save_vector_dbg(fit_centers,
978 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND ,pl);
980 }
981
982 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
983 eris_ifu_free_vector(&profile_x);
984 eris_ifu_free_vector(&fit_centers);
985 } // end: i = nr_values
986
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;
990 /* collapse image in y and convert to vector */
993 img, center_y, height));
994 /* do least square fit using a Gaussian in order to get exact centers */
996 fit_centers = eris_ifu_dist_calc_centers_fit(profile_x, est_centers, CPL_FALSE));
997
998 /* copy all values into image-array to hold all values */
1000 eris_ifu_dist_calc_centers_copy(fit_centers, i, center_y,
1001 cen_array));
1002
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);
1010 eris_ifu_free_string(&extname);
1011 eris_ifu_save_vector_dbg(profile_x,
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);
1015 eris_ifu_free_string(&extname);
1016 eris_ifu_save_vector_dbg(est_centers,
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);
1020 eris_ifu_free_string(&extname);
1021 eris_ifu_save_vector_dbg(fit_centers,
1022 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
1024 }
1025
1026 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
1027 eris_ifu_free_vector(&profile_x);
1028 eris_ifu_free_vector(&fit_centers);
1029 } // end: i = nr_values
1030
1031 if (productDepth & 4) {
1032 /* save centers */
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);
1039 }
1040 }
1041 }
1042 CATCH
1043 {
1044 CATCH_MSGS();
1045 for (int i = 0; i < SLITLET_CNT; i++) {
1046 eris_ifu_free_table(&cen_array[i]);
1047 }
1048 cpl_free(cen_array); cen_array = NULL;
1049 }
1050
1051 eris_ifu_free_vector(&profile_x_div);
1052 eris_ifu_free_vector(&profile_x_on);
1053 eris_ifu_free_vector(&est_centers_div);
1054 eris_ifu_free_vector(&est_centers_on);
1055 eris_ifu_free_vector(&est_centers);
1056 eris_ifu_free_vector(&fit_centers);
1057 eris_ifu_free_vector(&fit_centers_middle);
1058
1059 return cen_array;
1060}
1061
1062int eris_ifu_distortion_calc_y(int n, int i) {
1063 // split ERIS_IFU_DETECTOR_SIZE_Y in n parts
1064 // shift every point half down
1065 // round to int with adding 0.5 for proper rounding
1066 return (int)((double)ERIS_IFU_DETECTOR_SIZE_Y/n*(i+.5)+.5);
1067}
1068
1069int eris_ifu_distortion_target_left_edge(int i) {
1070 return i * SLITLET_WIDTH/* + 1*/;
1071}
1072int eris_ifu_distortion_target_right_edge(int i) {
1073 return (i + 1) * SLITLET_WIDTH - 1;
1074}
1075
1088 cpl_boolean triple_traces ,
1089 cpl_boolean cut_off_left,
1090 cpl_boolean cut_off_right)
1091{
1092 int n_arcs = 0;
1093 // get number of vertical traces (arcs) to process
1094 if (triple_traces) {
1095 n_arcs = 5; // left + right edge + 3x center line
1096 } else {
1097 n_arcs = 3; // left + right edge + 1x center line
1098 }
1099
1100 if (((i == 0) && cut_off_left) ||
1101 ((i == SLITLET_CNT-1) && cut_off_right))
1102 {
1103 // if left or right edge is cut off, omit it
1104 n_arcs--;
1105 }
1106 return n_arcs;
1107}
1108
1136cpl_polynomial** eris_ifu_dist_calc_distortion(cpl_table **slit_edges,
1137 cpl_table **centers,
1138 int productDepth,
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)
1146{
1147 int n_arcs = 0,
1148 n_calib_wave = 0,
1149 n_calib_cen = 0,
1150 n_size = 100,
1151// AA expect results that are more forgiving
1152// fit_order = 3,
1153 fit_order = 2,
1154 arc_cnt = 0,
1155 pos = 0;
1156 double o_l5 = 0.,
1157 o_c5 = 0.,
1158 o_r5 = 0.,
1159 o_l = 0.,
1160 o_c = 0.,
1161 o_r = 0.,
1162 o_c_l = 0.,
1163 o_c_r = 0.,
1164 t_o = 0,
1165 t_l = 0,
1166 t_r = 0,
1167 t_c = 0,
1168 t_c_l = 0,
1169 t_c_r = 0,
1170 m_c = 0,
1171 m_c_l = 0,
1172 m_c_r = 0,
1173// m_t_t = 0,
1174 std = 0.,
1175 median = 0.,
1176 l_min = 0.,
1177 *py = NULL;
1178 const double *pwave_y = NULL,
1179 *pcenter_y = NULL;
1180 cpl_polynomial **poly_u = NULL;
1181 cpl_bivector *grid = NULL;
1182 cpl_vector *val_to_fit = NULL,
1183 *tmp_vec = NULL,
1184 *y = NULL;
1185 eris_ifu_vector *y_wave = NULL,
1186 *y_cen = NULL,
1187 *t = NULL;
1188 cpl_boolean triple_traces = FALSE;
1189 cpl_table *tbl = NULL,
1190 *dbg_polynomials = NULL;
1191 struct arcstruct *arc_tbl = NULL;
1192
1193
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);
1197
1198 TRY
1199 {
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);
1208
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));
1215
1217 poly_u = cpl_calloc(SLITLET_CNT, sizeof(cpl_polynomial*)));
1218
1219 if (cpl_table_get_ncol(centers[5]) > 2) {
1220 triple_traces = TRUE;
1221 }
1222
1223 if (productDepth & 1) {
1224 cpl_propertylist_append_string(pl, CPL_DFS_PRO_CATG,
1225 "DIST_FIT_TABLE");
1226 cpl_propertylist_save(pl, ERIS_IFU_PRO_DIST_QC_FIT_FN,
1227 CPL_IO_CREATE);
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);
1231 }
1233 arc_tbl = cpl_calloc(SLITLET_CNT, sizeof(struct arcstruct)));
1234
1235 // calculate all slitlets that are not cut off
1236 for (int i = 0; i < SLITLET_CNT; i++) {
1237 //cpl_msg_debug(cpl_func, "i: %d\n", i);
1238 // get number of vertical traces (arcs) to process
1239 n_arcs = eris_ifu_distortion_get_narcs(i, triple_traces,
1240 cut_off_left, cut_off_right);
1241 // get number of detected wave_calib-lines
1242 n_calib_wave = (int) cpl_table_get_nrow(slit_edges[i]);
1243 // get number of centerpoints
1244 n_calib_cen = (int) cpl_table_get_nrow(centers[i]);
1245
1246 // get y-coordinates
1248 pwave_y = cpl_table_get_data_double_const(
1249 slit_edges[i], "y_pos"));
1251 pcenter_y = cpl_table_get_data_double_const(
1252 centers[i], "y"));
1254 y_wave = eris_ifu_vector_new_wrap(n_calib_wave, pwave_y));
1256 y_cen = eris_ifu_vector_new_wrap(n_calib_cen, pcenter_y));
1257
1258 // fit all edges (left, right, centers)
1259 if (!((i == 0) && cut_off_left)) {
1260 // process only if it is not the 1st slitlet and cutoff
1262 arc_tbl[i].fit_l = eris_ifu_dist_calc_distortion_fitedge(
1263 slit_edges[i], "edge_left", y_wave,
1264 n_calib_wave, n_size, fit_order,
1265 i, dbg_polynomials));
1266 }
1267 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1268 // process only if it is not the last slitlet and cutoff
1270 arc_tbl[i].fit_r = eris_ifu_dist_calc_distortion_fitedge(
1271 slit_edges[i], "edge_right", y_wave,
1272 n_calib_wave, n_size, fit_order,
1273 i, dbg_polynomials));
1274 }
1276 arc_tbl[i].fit_c = eris_ifu_dist_calc_distortion_fitedge(
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)) {
1282 // process if it is not the 1st slitlet and not cutoff
1284 arc_tbl[i].fit_c_l = eris_ifu_dist_calc_distortion_fitedge(
1285 centers[i], "x_l", y_cen,
1286 n_calib_cen, n_size, fit_order,
1287 i, dbg_polynomials));
1288 } else {
1289 // if it is the last slitlet and cutoff, then
1290 // check first if, and how many, values are nan
1291 // If there are too many NaN's do nothing and copy the shape of c to c_l
1292 if (cpl_table_count_invalid(centers[i], "x_l") <= 0.1 * n_calib_cen) {
1293 // calculate fitted edge only if less tahn 10% of the values are NaN
1295 arc_tbl[i].fit_c_l = eris_ifu_dist_calc_distortion_fitedge(
1296 centers[i], "x_l", y_cen,
1297 n_calib_cen, n_size, fit_order,
1298 i, dbg_polynomials));
1299 }
1300 }
1301
1302 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1303 // process if it is not the last slitlet and not cutoff
1305 arc_tbl[i].fit_c_r = eris_ifu_dist_calc_distortion_fitedge(
1306 centers[i], "x_r", y_cen,
1307 n_calib_cen, n_size, fit_order,
1308 i, dbg_polynomials));
1309 } else {
1310 // if it is the last slitlet and cutoff, then
1311 // check first if, and how many, values are nan
1312 // If there are too many NaN's do nothing and copy the shape of c to c_r
1313 if (cpl_table_count_invalid(centers[i], "x_r") <= 0.1 * n_calib_cen) {
1314 // calculate fitted edge only if less than 10% of the values are NaN
1316 arc_tbl[i].fit_c_r = eris_ifu_dist_calc_distortion_fitedge(
1317 centers[i], "x_r", y_cen,
1318 n_calib_cen, n_size, fit_order,
1319 i, dbg_polynomials));
1320 }
1321 }
1322 } // end: if (triple_traces)
1323 eris_ifu_free_ifu_vector(&y_wave);
1325 } // end: i = SLITLET_CNT
1326
1327 BRK_IF_ERROR( cpl_table_save(dbg_polynomials, NULL, NULL,
1328 "eris_ifu_distortion_dbg_polynomials.fits", CPL_IO_CREATE));
1329
1331 *qc = cpl_calloc(SLITLET_CNT, sizeof(cpl_propertylist*)));
1332 for (int i = 0; i < SLITLET_CNT; i++) {
1334 (*qc)[i] = cpl_propertylist_new());
1335 }
1336
1337 // estimate positions of cut off edges with neighbouring slitlet width
1338 if (cut_off_left) {
1339 if (arc_tbl[0].fit_l == NULL) {
1340 /* The leftmost edge of slitlet #0 is cut off. Therefore subtract the
1341 * width of slitlet #1 from the right edge of slitlet #0
1342 */
1344 cpl_propertylist_append_string((*qc)[0],
1345 "ESO EDGE L", "artificial"));
1347 arc_tbl[0].fit_l = eris_ifu_vector_duplicate(arc_tbl[0].fit_r));
1349 eris_ifu_vector_subtract(arc_tbl[0].fit_l, arc_tbl[1].fit_r));
1351 eris_ifu_vector_add(arc_tbl[0].fit_l, arc_tbl[1].fit_l));
1352 }
1353 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_l == NULL)) {
1354 /* The c_l-edge of slitlet #0 is cut off. Therefore subtract the
1355 * width of c-c_l of slitlet #31 to the left edge of slitlet #32
1356 */
1358 cpl_propertylist_append_string((*qc)[0],
1359 "ESO EDGE C-L", "artificial"));
1361 arc_tbl[0].fit_c_l = eris_ifu_vector_duplicate(arc_tbl[0].fit_c));
1363 eris_ifu_vector_subtract(arc_tbl[0].fit_c_l, arc_tbl[1].fit_c));
1365 eris_ifu_vector_add(arc_tbl[0].fit_c_l, arc_tbl[1].fit_c_l));
1366 }
1367 cut_off_left = CPL_FALSE;
1368 }
1369
1370 if (cut_off_right) {
1371 if (arc_tbl[SLITLET_CNT-1].fit_r == NULL) {
1372 /* The rightmost edge of slitlet #32 is cut off. Therefore add the
1373 * width of slitlet #31 to the left edge of slitlet #32
1374 */
1376 cpl_propertylist_append_string((*qc)[SLITLET_CNT-1],
1377 "ESO EDGE R", "artificial"));
1379 arc_tbl[SLITLET_CNT-1].fit_r = eris_ifu_vector_duplicate(arc_tbl[SLITLET_CNT-1].fit_l));
1381 eris_ifu_vector_add(arc_tbl[SLITLET_CNT-1].fit_r, arc_tbl[SLITLET_CNT-2].fit_r));
1383 eris_ifu_vector_subtract(arc_tbl[SLITLET_CNT-1].fit_r, arc_tbl[SLITLET_CNT-2].fit_l));
1384 }
1385 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_r == NULL)) {
1386 /* The c_r-edge of slitlet #32 is cut off. Therefore add the
1387 * width of c_r-c of slitlet #31 to the left center edge of slitlet #32
1388 */
1390 cpl_propertylist_append_string((*qc)[0],
1391 "ESO EDGE C-R", "artificial"));
1393 arc_tbl[SLITLET_CNT-1].fit_c_r = eris_ifu_vector_duplicate(arc_tbl[SLITLET_CNT-1].fit_c));
1395 eris_ifu_vector_add(arc_tbl[SLITLET_CNT-1].fit_c_r, arc_tbl[SLITLET_CNT-2].fit_c_r));
1397 eris_ifu_vector_subtract(arc_tbl[SLITLET_CNT-1].fit_c_r, arc_tbl[SLITLET_CNT-2].fit_c));
1398 }
1399 cut_off_right = CPL_FALSE;
1400 }
1401
1402 // take fifth slitlet as master one
1403 int ms = 4;
1404 o_l5 = eris_ifu_vector_get_mean(arc_tbl[ms].fit_l);
1405 o_c5 = eris_ifu_vector_get_mean(arc_tbl[ms].fit_c);
1406 o_r5 = eris_ifu_vector_get_mean(arc_tbl[ms].fit_r);
1407 m_c = 64. * (o_c5 - o_l5) / (o_r5 - o_l5);
1408 if (triple_traces) {
1409 o_c_l = eris_ifu_vector_get_mean(arc_tbl[ms].fit_c_l);
1410 o_c_r = eris_ifu_vector_get_mean(arc_tbl[ms].fit_c_r);
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);
1413// m_t_t = (o_c_r - o_c_l) / (m_c_r - m_c_l);
1414// printf("REF: %6.1f %6.1f %6.1f %6.1f %6.1f width: %.1f r: %.1f %.1f %.1f %.1f\n",
1415// o_l5, o_c_l, o_c5, o_r5, o_c_r, o_r5-o_l5, m_c_l, m_c, m_c_r, m_t_t);
1416 } else {
1417// printf("REF: %.1f %.1f %.1f width: %.1f r: %.1f\n",
1418// o_l5, o_c5, o_r5, o_r5-o_l5, m_c);
1419 }
1420
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));
1428 }
1429
1430 // estimate mean origin positions of the arc-lines and calculate
1431 // target positions for the edges, fill the grid, perform polynomial-fit
1432 for (int i = 0; i < SLITLET_CNT; i++) {
1433 cpl_msg_debug(cpl_func, "i: %d", i);
1434 // get number of vertical traces (arcs) to process
1435 n_arcs = eris_ifu_distortion_get_narcs(i, triple_traces,
1436 cut_off_left, cut_off_right);
1437
1438 /*
1439 * estimate mean origin positions of the arc-lines (left, center, right)
1440 */
1441 o_l = eris_ifu_vector_get_mean(arc_tbl[i].fit_l);
1442 o_c = eris_ifu_vector_get_mean(arc_tbl[i].fit_c);
1443 o_r = eris_ifu_vector_get_mean(arc_tbl[i].fit_r);
1444
1445// ASSURE(o_c_l < o_c, CPL_ERROR_ILLEGAL_OUTPUT, "Slitlet #%d: o_l >= o_c (o_l: %g, o_c: %g)", i+1, o_l, o_c);
1446// ASSURE(o_c_l < o_c, CPL_ERROR_ILLEGAL_OUTPUT, "Slitlet #%d: o_c >= o_r (o_c: %g, o_r: %g)", i+1, o_c, o_r);
1447 if (triple_traces) {
1448 o_c_l = eris_ifu_vector_get_mean(arc_tbl[i].fit_c_l);
1449 o_c_r = eris_ifu_vector_get_mean(arc_tbl[i].fit_c_r);
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);
1453 } else {
1454 cpl_msg_debug(cpl_func, " o_l: %g, o_c: %g, o_r: %g", o_l, o_c, o_r);
1455 }
1456
1457 /*
1458 * from these estimates define target positions for the arc-lines (left, center, right)
1459 */
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);
1468 t_c = t_o + m_c;
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);
1475 } else {
1476 cpl_msg_debug(cpl_func, " t_l: %f, t_c: %f, t_r: %f", t_l, t_c, t_r);
1477 }
1478 if (i == 0) {
1479 t_r -= 2.7;
1480 } else if (i == 1){
1481 t_r -= 1.5;
1482 }
1483 double tx = t_o;
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)
1493 BRK_IF_NULL(
1494 grid = cpl_bivector_new(n_arcs * n_size));
1495
1496 // create vector with values to fit (contains origin-coordinates)
1497 BRK_IF_NULL(
1498 val_to_fit = cpl_vector_new(n_arcs * n_size));
1499
1500 arc_cnt = 0;
1501 // fill in edges and subtract always in a manner that destination_x(target) is 0 for left edge
1502 // fill in left edge
1503 BRK_IF_ERROR(
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) {
1507 // fill in center_l
1508 BRK_IF_ERROR(
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++));
1511 }
1512 // fill in center
1513//cpl_msg_debug(cpl_func, ">>> %d", i);
1514//if (i==31) {
1515// int a=0;
1516//}
1517 BRK_IF_ERROR(
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) {
1521 // fill in center_l
1522 BRK_IF_ERROR(
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++));
1525 }
1526 // fill in right edge
1527 BRK_IF_ERROR(
1528 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_r, val_to_fit,
1529 t_r-tx, n_size, arc_cnt++));
1530
1531 // save l_min and r_max
1532 l_min = floor(eris_ifu_vector_get_min(arc_tbl[i].fit_l, &pos));
1533 BRK_IF_ERROR(
1534 cpl_table_set_double(*minmax_borders, ERIS_IFU_POLY_EDGE_L, i,
1535 l_min));
1536 BRK_IF_ERROR(
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))));
1539
1540 // fill in edges and subtract always in a manner that destination_x(measured) is 0.0 for left edge at beginning
1541 BRK_IF_ERROR(
1542 cpl_vector_subtract_scalar(val_to_fit, l_min));
1543
1544 if (productDepth >= PD_DEBUG) {
1545 char *extName;
1546 extName = cpl_sprintf("GRIDX_%2.2d", i);
1547 BRK_IF_ERROR(
1548 cpl_propertylist_update_string(pl, "EXTNAME", extName));
1549 BRK_IF_ERROR(
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));
1553 cpl_free(extName);
1554 extName = cpl_sprintf("GRIDY_%2.2d", i);
1555 BRK_IF_ERROR(
1556 cpl_propertylist_update_string(pl, "EXTNAME", extName));
1557 BRK_IF_ERROR(
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));
1561 cpl_free(extName);
1562 extName = cpl_sprintf("VAL2FIT_%2.2d", i);
1563 BRK_IF_ERROR(
1564 cpl_propertylist_update_string(pl, "EXTNAME", extName));
1565 BRK_IF_ERROR(
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));
1569 cpl_free(extName);
1570 }
1571//if (i==16) {
1572// int aa=0;
1573//}
1574 /* Perform the fit */
1575 BRK_IF_NULL(
1576 poly_u[i] = eris_ifu_dist_poly_fit_2d_create(grid, val_to_fit, NULL));
1577
1578 eris_ifu_free_bivector(&grid);
1579 eris_ifu_free_vector(&val_to_fit);
1580 } // end: i = SLITLET_CNT
1581
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
1585 BRK_IF_NULL(
1586 y = cpl_vector_new(n_size));
1587 BRK_IF_NULL(
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);
1591 }
1592 char* keyname;
1593 char* keycomm;
1594 for (int i = 0; i < SLITLET_CNT; i++) {
1595
1596 tbl = cpl_table_new(n_size);
1597 if (arc_tbl[i].fit_l != NULL) {
1598
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);
1603 }
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);
1609 }
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);
1616 } else {
1617 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1618 }
1619 cpl_propertylist_set_comment((*qc)[i], keyname,keycomm);
1620 cpl_free(keyname);
1621 cpl_free(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);
1626 }
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);
1632 }
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);
1638 }
1639
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);
1649 } else {
1650 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1651 }
1652 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1653 cpl_free(keyname);
1654 cpl_free(keycomm);
1655
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);
1661 } else {
1662 cpl_propertylist_append_string((*qc)[i], "MEDIAN R-L", "NaN");
1663 }
1664 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1665 cpl_free(keyname);
1666 cpl_free(keycomm);
1667
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);
1676 }
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);
1685 } else {
1686 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1687 }
1688 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1689 cpl_free(keyname);
1690 cpl_free(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);
1696 } else {
1697 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1698 }
1699 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1700 cpl_free(keyname);
1701 cpl_free(keycomm);
1702 eris_ifu_free_ifu_vector(&t);
1703 }
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);
1712 } else {
1713 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1714 }
1715 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1716 cpl_free(keyname);
1717 cpl_free(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);
1723 } else {
1724 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1725 }
1726 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1727 cpl_free(keyname);
1728 cpl_free(keycomm);
1729 eris_ifu_free_ifu_vector(&t);
1730 }
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);
1739 } else {
1740 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1741 }
1742 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1743 cpl_free(keyname);
1744 cpl_free(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);
1750 } else {
1751 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1752 }
1753 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1754 cpl_free(keyname);
1755 cpl_free(keycomm);
1756 eris_ifu_free_ifu_vector(&t);
1757 }
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);
1766 } else {
1767 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1768 }
1769 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1770 cpl_free(keyname);
1771 cpl_free(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);
1777 } else {
1778 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1779 }
1780 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1781 cpl_free(keyname);
1782 cpl_free(keycomm);
1783 eris_ifu_free_ifu_vector(&t);
1784 }
1785 BRK_IF_ERROR(
1786 cpl_table_save(tbl, NULL, (*qc)[i], ERIS_IFU_PRO_DIST_QC_FIT_FN, CPL_IO_EXTEND));
1787
1788 eris_ifu_free_table(&tbl);
1789 } // end: i = SLITLET_CNT
1790 } // end: if (productDepth & 1)
1791 }
1792 CATCH
1793 {
1794 CATCH_MSGS();
1795 for (int j = 0; j < SLITLET_CNT; j++) {
1796 cpl_polynomial_delete(poly_u[j]); poly_u[j] = NULL;
1797 }
1798 cpl_free(poly_u); poly_u = NULL;
1799
1800 eris_ifu_free_table(minmax_borders);
1801
1802 if (*qc != NULL && **qc != NULL) {
1803 for (int i = 0; i < SLITLET_CNT; i++) {
1804 eris_ifu_free_propertylist(&(*qc)[i]);
1805 }
1806 }
1807 if (*qc != NULL) {
1808 cpl_free(**qc); **qc = NULL;
1809 }
1810 }
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);
1822 }
1823 cpl_free(arc_tbl); arc_tbl = NULL;
1824 eris_check_error_code("eris_ifu_dist_calc_distortion");
1825 return poly_u;
1826}
1827
1844cpl_polynomial** eris_ifu_dist_calc_distortion_full(cpl_table **slit_edges,
1845 cpl_table **centers,
1846 int productDepth,
1847 cpl_boolean cut_off_left,
1848 cpl_boolean cut_off_right)
1849{
1850 int n_arcs = 0,
1851 n_calib_wave = 0,
1852 n_calib_cen = 0,
1853 n_size = 100,
1854 fit_order = 3,
1855 t_l = 0,
1856 t_r = 0,
1857 t_c = 0,
1858 t_c_l = 0,
1859 t_c_r = 0,
1860 arc_cnt = 0;
1861 double o_l = 0.,
1862 o_c = 0.,
1863 o_r = 0.,
1864 o_c_l = 0.,
1865 o_c_r = 0.,
1866 std = 0.;
1867 const double *pwave_y = NULL,
1868 *pcenter_y = NULL;
1869 cpl_polynomial **poly_u = NULL;
1870 cpl_bivector *grid = NULL;
1871 cpl_vector *val_to_fit = NULL,
1872 *tt = NULL;
1873 eris_ifu_vector *y_wave = NULL,
1874 *y_cen = NULL,
1875 *t = 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;
1881
1882 cpl_ensure(slit_edges, CPL_ERROR_NULL_INPUT, NULL);
1883 cpl_ensure(centers, CPL_ERROR_NULL_INPUT, NULL);
1884
1885 TRY
1886 {
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();
1895
1896 BRK_IF_NULL(
1897 poly_u = cpl_calloc(SLITLET_CNT, sizeof(cpl_polynomial*)));
1898
1899 if (cpl_table_get_ncol(centers[5]) > 2) {
1900 triple_traces = TRUE;
1901 }
1902
1903 BRK_IF_ERROR(
1904 cpl_propertylist_save(NULL, ERIS_IFU_PRO_DIST_QC_FIT_FN, CPL_IO_CREATE));
1905
1906 BRK_IF_NULL(
1907 arc_tbl = cpl_calloc(SLITLET_CNT, sizeof(struct arcstruct)));
1908
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]);
1919
1920 // get y-coordinates
1921 BRK_IF_NULL(
1922 pwave_y = cpl_table_get_data_double_const(
1923 slit_edges[i], "y_pos"));
1924 BRK_IF_NULL(
1925 pcenter_y = cpl_table_get_data_double_const(
1926 centers[i], "y"));
1927 BRK_IF_NULL(
1928 y_wave = eris_ifu_vector_new_wrap(n_calib_wave, pwave_y));
1929 BRK_IF_NULL(
1930 y_cen = eris_ifu_vector_new_wrap(n_calib_cen, pcenter_y));
1931
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
1935 BRK_IF_NULL(
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));
1940 }
1941 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1942 // process only if it is not the last slitlet and cutoff
1943 BRK_IF_NULL(
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));
1948 }
1949 BRK_IF_NULL(
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
1957 BRK_IF_NULL(
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));
1962 } else {
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
1968 BRK_IF_NULL(
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));
1973 }
1974 }
1975
1976 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1977 // process if it is not the last slitlet and not cutoff
1978 BRK_IF_NULL(
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));
1983 } else {
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
1989 BRK_IF_NULL(
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));
1994 }
1995 }
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
2000
2001 BRK_IF_NULL(
2002 pl = cpl_calloc(SLITLET_CNT, sizeof(cpl_propertylist*)));
2003 for (int i = 0; i < SLITLET_CNT; i++) {
2004 BRK_IF_NULL(
2005 pl[i] = cpl_propertylist_new());
2006 }
2007
2008 // estimate positions of cut off edges with neighbouring slitlet width
2009 if (cut_off_left) {
2010 BRK_IF_ERROR(
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
2016 */
2017 BRK_IF_NULL(
2018 arc_tbl[0].fit_l = eris_ifu_vector_duplicate(arc_tbl[0].fit_r));
2019 BRK_IF_ERROR(
2020 eris_ifu_vector_subtract(arc_tbl[0].fit_l, arc_tbl[1].fit_r));
2021 BRK_IF_ERROR(
2022 eris_ifu_vector_add(arc_tbl[0].fit_l, arc_tbl[1].fit_l));
2023 }
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
2027 */
2028 BRK_IF_NULL(
2029 arc_tbl[0].fit_c_l = eris_ifu_vector_duplicate(arc_tbl[0].fit_c));
2030 BRK_IF_ERROR(
2031 eris_ifu_vector_subtract(arc_tbl[0].fit_c_l, arc_tbl[1].fit_c));
2032 BRK_IF_ERROR(
2033 eris_ifu_vector_add(arc_tbl[0].fit_c_l, arc_tbl[1].fit_c_l));
2034 }
2035 cut_off_left = CPL_FALSE;
2036 }
2037
2038 if (cut_off_right) {
2039 BRK_IF_ERROR(
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
2045 */
2046 BRK_IF_NULL(
2047 arc_tbl[SLITLET_CNT-1].fit_r = eris_ifu_vector_duplicate(arc_tbl[SLITLET_CNT-1].fit_l));
2048 BRK_IF_ERROR(
2049 eris_ifu_vector_add(arc_tbl[SLITLET_CNT-1].fit_r, arc_tbl[SLITLET_CNT-2].fit_r));
2050 BRK_IF_ERROR(
2051 eris_ifu_vector_subtract(arc_tbl[SLITLET_CNT-1].fit_r, arc_tbl[SLITLET_CNT-2].fit_l));
2052 }
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
2056 */
2057 BRK_IF_NULL(
2058 arc_tbl[SLITLET_CNT-1].fit_c_r = eris_ifu_vector_duplicate(arc_tbl[SLITLET_CNT-1].fit_c));
2059 BRK_IF_ERROR(
2060 eris_ifu_vector_add(arc_tbl[SLITLET_CNT-1].fit_c_r, arc_tbl[SLITLET_CNT-2].fit_c_r));
2061 BRK_IF_ERROR(
2062 eris_ifu_vector_subtract(arc_tbl[SLITLET_CNT-1].fit_c_r, arc_tbl[SLITLET_CNT-2].fit_c));
2063 }
2064 cut_off_right = CPL_FALSE;
2065 }
2066
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);
2070 }
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);
2077
2078 /*
2079 * estimate mean origin positions of the arc-lines (left, center, right)
2080 */
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);
2087 }
2088
2089 /*
2090 * from these estimates define target positions for the arc-lines (left, center, right)
2091 */
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);
2095
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);
2101 }
2102
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)
2110 BRK_IF_NULL(
2111 grid = cpl_bivector_new(n_arcs * n_size));
2112
2113 // create vector with values to fit (contains origin-coordinates)
2114 BRK_IF_NULL(
2115 val_to_fit = cpl_vector_new(n_arcs * n_size));
2116
2117 arc_cnt = 0;
2118 // fill in left edge
2119 BRK_IF_ERROR(
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) {
2123 // fill in center_l
2124 BRK_IF_ERROR(
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++));
2127 }
2128 // fill in center
2129 BRK_IF_ERROR(
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) {
2133 // fill in center_l
2134 BRK_IF_ERROR(
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++));
2137 }
2138 // fill in right edge
2139 BRK_IF_ERROR(
2140 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_r, val_to_fit,
2141 t_r, n_size, arc_cnt++));
2142
2143 if (productDepth & 4) {
2144// cpl_propertylist *pl = NULL;
2145// BRK_IF_NULL(
2146// pl = cpl_propertylist_new());
2147 char *extname = NULL;
2148
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]);
2153
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]);
2158
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]);
2163
2164// eris_ifu_free_propertylist(&pl);
2165 }
2166
2167 /* Apply the fitting */
2168 BRK_IF_NULL(
2169 poly_u[i] = eris_ifu_dist_poly_fit_2d_create(grid, val_to_fit, NULL));
2170
2171 eris_ifu_free_bivector(&grid);
2172 eris_ifu_free_vector(&val_to_fit);
2173 } // end: i = SLITLET_CNT
2174
2175 // save values of all fitted edges and some stats
2176 if (productDepth & 2) {
2177 for (int i = 0; i < SLITLET_CNT; i++) {
2178 BRK_IF_NULL(
2179 tbl = cpl_table_new(n_size));
2180 if (arc_tbl[i].fit_l != NULL) {
2181 BRK_IF_ERROR(
2182 cpl_table_new_column(tbl, "l", CPL_TYPE_DOUBLE));
2183 BRK_IF_NULL(
2184 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_l));
2185 BRK_IF_ERROR(
2186 cpl_table_copy_data_double(tbl, "l", cpl_vector_get_data_const(tt)));
2187 eris_ifu_free_vector(&tt);
2188 }
2189 if (arc_tbl[i].fit_c_l != NULL) {
2190 BRK_IF_ERROR(
2191 cpl_table_new_column(tbl, "c_l", CPL_TYPE_DOUBLE));
2192 BRK_IF_NULL(
2193 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_c_l));
2194 BRK_IF_ERROR(
2195 cpl_table_copy_data_double(tbl, "c_l", cpl_vector_get_data_const(tt)));
2196 eris_ifu_free_vector(&tt);
2197 }
2198 if (arc_tbl[i].fit_c != NULL) {
2199 BRK_IF_ERROR(
2200 cpl_table_new_column(tbl, "c", CPL_TYPE_DOUBLE));
2201 BRK_IF_NULL(
2202 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_c));
2203 BRK_IF_ERROR(
2204 cpl_table_copy_data_double(tbl, "c", cpl_vector_get_data_const(tt)));
2205 eris_ifu_free_vector(&tt);
2206 }
2207 if (arc_tbl[i].fit_c_r != NULL) {
2208 BRK_IF_ERROR(
2209 cpl_table_new_column(tbl, "c_r", CPL_TYPE_DOUBLE));
2210 BRK_IF_NULL(
2211 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_c_r));
2212 BRK_IF_ERROR(
2213 cpl_table_copy_data_double(tbl, "c_r", cpl_vector_get_data_const(tt)));
2214 eris_ifu_free_vector(&tt);
2215 }
2216 if (arc_tbl[i].fit_r != NULL) {
2217 BRK_IF_ERROR(
2218 cpl_table_new_column(tbl, "r", CPL_TYPE_DOUBLE));
2219 BRK_IF_NULL(
2220 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_r));
2221 BRK_IF_ERROR(
2222 cpl_table_copy_data_double(tbl, "r", cpl_vector_get_data_const(tt)));
2223 eris_ifu_free_vector(&tt);
2224 }
2225
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);
2229 BRK_IF_ERROR(
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)) {
2233 BRK_IF_ERROR(
2234 cpl_propertylist_append_double(pl[i], "STDEV R-L", std));
2235 } else {
2236 BRK_IF_ERROR(
2237 cpl_propertylist_append_string(pl[i], "STDEV R-L", "NaN"));
2238 }
2239
2240 // for the ease of stats: save the slit-width
2241 BRK_IF_ERROR(
2242 cpl_table_new_column(tbl, "slit_width", CPL_TYPE_DOUBLE));
2243 BRK_IF_NULL(
2244 tt = eris_ifu_vector_get_data(t));
2245 BRK_IF_ERROR(
2246 cpl_table_copy_data_double(tbl, "slit_width", cpl_vector_get_data_const(tt)));
2247
2248 eris_ifu_free_vector(&tt);
2249 eris_ifu_free_ifu_vector(&t);
2250 }
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);
2253 BRK_IF_ERROR(
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)) {
2257 BRK_IF_ERROR(
2258 cpl_propertylist_append_double(pl[i], "STDEV C-L", std));
2259 } else {
2260 BRK_IF_ERROR(
2261 cpl_propertylist_append_string(pl[i], "STDEV C-L", "NaN"));
2262 }
2263 eris_ifu_free_ifu_vector(&t);
2264 }
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);
2267 BRK_IF_ERROR(
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)) {
2271 BRK_IF_ERROR(
2272 cpl_propertylist_append_double(pl[i], "STDEV R-C", std));
2273 } else {
2274 BRK_IF_ERROR(
2275 cpl_propertylist_append_string(pl[i], "STDEV R-C", "NaN"));
2276 }
2277 eris_ifu_free_ifu_vector(&t);
2278 }
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);
2281 BRK_IF_ERROR(
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)) {
2285 BRK_IF_ERROR(
2286 cpl_propertylist_append_double(pl[i], "STDEV C-CL", std));
2287 } else {
2288 BRK_IF_ERROR(
2289 cpl_propertylist_append_string(pl[i], "STDEV C-CL", "NaN"));
2290 }
2291 eris_ifu_free_ifu_vector(&t);
2292 }
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);
2295 BRK_IF_ERROR(
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)) {
2299 BRK_IF_ERROR(
2300 cpl_propertylist_append_double(pl[i], "STDEV CR-C", std));
2301 } else {
2302 BRK_IF_ERROR(
2303 cpl_propertylist_append_string(pl[i], "STDEV CR-C", "NaN"));
2304 }
2305 eris_ifu_free_ifu_vector(&t);
2306 }
2307 if ((productDepth & 2) != 0) {
2308 BRK_IF_ERROR(
2309 cpl_table_save(tbl, NULL, pl[i], ERIS_IFU_PRO_DIST_QC_FIT_FN, CPL_IO_EXTEND));
2310 }
2311
2312 eris_ifu_free_table(&tbl);
2313 } // end: i = SLITLET_CNT
2314 } // end: if (productDepth & 2)
2315 }
2316 CATCH
2317 {
2318 CATCH_MSGS();
2319 for (int j = 0; j < SLITLET_CNT; j++) {
2320 cpl_polynomial_delete(poly_u[j]); poly_u[j] = NULL;
2321 }
2322 cpl_free(poly_u); poly_u = NULL;
2323 }
2324
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);
2334 }
2335 if (pl != NULL) {
2336 for (int i = 0; i < SLITLET_CNT; i++) {
2337 eris_ifu_free_propertylist(&pl[i]);
2338 }
2339 }
2340 cpl_free(arc_tbl); arc_tbl = NULL;
2341 cpl_free(pl); pl = NULL;
2342
2343 return poly_u;
2344}
2345
2363eris_ifu_vector* eris_ifu_dist_calc_distortion_fitedge(const cpl_table *edge,
2364 const char *col_name,
2365 const eris_ifu_vector *y,
2366 int n_calib,
2367 int n_size,
2368 int fit_order,
2369 int slitlet,
2370 cpl_table *dbg_tbl)
2371{
2372 const double *px = NULL;
2373 double *pfit_par = NULL;
2374 eris_ifu_vector *x = NULL,
2375 *fit = NULL;
2376 cpl_vector *fit_par = NULL;
2377 cpl_array *tmp_array = NULL;
2378
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);
2385
2386 TRY
2387 {
2388 BRK_IF_NULL(
2389 px = cpl_table_get_data_double_const(edge, col_name));
2390
2391 BRK_IF_NULL(
2392 x = eris_ifu_vector_new_wrap(n_calib, px));
2393
2394 // fit polynomial to edge
2395 BRK_IF_NULL(
2396 fit_par = eris_ifu_polyfit_edge(y, x, fit_order));
2397 eris_ifu_free_ifu_vector(&x);
2398
2399 BRK_IF_NULL(
2400 pfit_par = cpl_vector_get_data(fit_par));
2401
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();
2408
2409 // create vector with fitted values
2410 BRK_IF_NULL(
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] +
2415 pfit_par[1] * yy +
2416 pfit_par[2] * pow(yy, 2);
2417// + pfit_par[3] * pow(yy, 3);
2418 BRK_IF_ERROR(
2419 eris_ifu_vector_set(fit, j, v));
2420 }
2421 }
2422 CATCH
2423 {
2424 CATCH_MSGS();
2425 eris_ifu_free_ifu_vector(&fit);
2426 }
2427 eris_ifu_free_vector(&fit_par);
2428
2429 return fit;
2430}
2431
2449cpl_error_code eris_ifu_dist_calc_distortion_fillgrid(cpl_bivector *grid,
2450 const eris_ifu_vector *data,
2451 cpl_vector *val_to_fit,
2452 double x_pos,
2453 int n_size,
2454 int arc_cnt)
2455{
2456 cpl_error_code err = CPL_ERROR_NONE;
2457 double *pgridx = NULL,
2458 *pgridy = NULL,
2459 *pval_to_fit = NULL;
2460
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);
2464 if (x_pos == -1){
2465 x_pos=0;
2466 }
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);
2470
2471 TRY
2472 {
2473 BRK_IF_NULL(
2474 pgridx = cpl_bivector_get_x_data(grid));
2475 BRK_IF_NULL(
2476 pgridy = cpl_bivector_get_y_data(grid));
2477 BRK_IF_NULL(
2478 pval_to_fit = cpl_vector_get_data(val_to_fit));
2479
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,
2483 "index overrun");
2484
2485 int jj = j % n_size;
2486
2487 // same target-x for all y-positions
2488 pgridx[j] = x_pos;
2489
2490 // calc target-y
2491 pgridy[j] = eris_ifu_distortion_calc_y(n_size, jj);
2492
2493 // insert fitted x-value at y-position
2494 if (eris_ifu_vector_is_rejected(data, jj)) {
2495 pval_to_fit[j] = NAN;
2496 } else {
2497 pval_to_fit[j] = eris_ifu_vector_get(data, jj);
2498 }
2499 }
2500 }
2501 CATCH
2502 {
2503 CATCH_MSGS();
2504 err = cpl_error_get_code();
2505 }
2506
2507 return err;
2508}
2509
2526cpl_polynomial* eris_ifu_dist_poly_fit_2d_create(cpl_bivector *xy_pos,
2527 const cpl_vector *values,
2528 double *msee)
2529{
2530 int xy_size = 0;
2531 double rechisq = 0.,
2532 value = 0.;
2533 cpl_size degree = NS_FIT_DEGREE;
2534 cpl_matrix *samppos2d = NULL;
2535 cpl_vector *fitresidual = NULL;
2536 cpl_polynomial *fit2d = NULL;
2537
2538 typedef double* (*get_data)(cpl_bivector*);
2539 get_data data_extractor[2] = { &cpl_bivector_get_x_data,
2540 &cpl_bivector_get_y_data };
2541
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);
2545
2546 TRY
2547 {
2548 xy_size = (int) cpl_bivector_get_size(xy_pos);
2549 CHECK_ERROR_STATE();
2550
2551 BRK_IF_NULL(
2552 fit2d = cpl_polynomial_new(2));
2553 BRK_IF_NULL(
2554 samppos2d = cpl_matrix_new(2, xy_size));
2555
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];
2559 BRK_IF_ERROR(
2560 cpl_matrix_set(samppos2d, i, j, value));
2561 }
2562 }
2563 const cpl_size maxdeg2d[] = {2,3};
2564 BRK_IF_ERROR(
2565 cpl_polynomial_fit(fit2d, samppos2d, NULL, values, NULL, CPL_TRUE,
2566 NULL, maxdeg2d));
2567// BRK_IF_ERROR(
2568// cpl_polynomial_fit(fit2d, samppos2d, NULL, values, NULL, CPL_FALSE,
2569// NULL, &degree));
2570
2571 BRK_IF_NULL(
2572 fitresidual = cpl_vector_new(xy_size));
2573 BRK_IF_ERROR(
2574 cpl_vector_fill_polynomial_fit_residual(fitresidual, values, NULL,
2575 fit2d, samppos2d, &rechisq));
2576 if (msee) {
2577 *msee = cpl_vector_product(fitresidual, fitresidual)
2578 / (double) cpl_vector_get_size(fitresidual);
2579 }
2580 }
2581 CATCH
2582 {
2583 CATCH_MSGS();
2584 eris_ifu_free_polynomial(&fit2d);
2585 }
2586
2587 eris_ifu_free_matrix(&samppos2d);
2588 eris_ifu_free_vector(&fitresidual);
2589
2590 return fit2d;
2591}
2592
2611cpl_error_code eris_ifu_dist_save_distortion(cpl_polynomial **poly2d,
2612 const cpl_table *minmax_borders,
2613 const char *fn,
2614 cpl_frameset *frameset,
2615 const cpl_parameterlist *parlist,
2616 cpl_propertylist **qc)
2617{
2618 double coeff/*,
2619 xshift = 0.*/;
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;
2625
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);
2629 char* extname;
2630 TRY
2631 {
2632 for (int i = 0; i < SLITLET_CNT; i++) {
2633 if (poly2d[i] == NULL) {
2634 cpl_propertylist_save(NULL, fn, CPL_IO_EXTEND);
2635 } else {
2636 max_degree = cpl_polynomial_get_degree(poly2d[i]);
2637 BRK_IF_NULL(
2638 poly_tbl = cpl_table_new(max_degree * max_degree));
2639 BRK_IF_ERROR(
2640 cpl_table_new_column(poly_tbl,"degx", CPL_TYPE_INT));
2641 BRK_IF_ERROR(
2642 cpl_table_new_column(poly_tbl,"degy", CPL_TYPE_INT));
2643 BRK_IF_ERROR(
2644 cpl_table_new_column(poly_tbl,"coeff", CPL_TYPE_DOUBLE));
2645
2646 cpl_size tx = 0;
2647 for (cpl_size cy=0; cy < max_degree; cy++) {
2648 for (cpl_size cx=0; cx < max_degree; cx++) {
2649 coef_pow[0]=cx;
2650 coef_pow[1]=cy;
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
2653 BRK_IF_ERROR(
2654 cpl_table_set_int(poly_tbl,"degx",tx,(int) cx));
2655 BRK_IF_ERROR(
2656 cpl_table_set_int(poly_tbl,"degy",tx,(int) cy));
2657 BRK_IF_ERROR(
2658 cpl_table_set_double(poly_tbl,"coeff", tx,
2659 coeff));
2660 tx++;
2661 }
2662 }
2663 }
2664 BRK_IF_ERROR(
2665 cpl_table_set_size(poly_tbl, tx));
2666
2667// /* QC LOG */
2668// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 0, 0);
2669// BRK_IF_ERROR(
2670// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][0],
2671// "Polynomial distortion coefficient"));
2672//
2673// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 1,0);
2674// BRK_IF_ERROR(
2675// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[1][0],
2676// "Polynomial distortion coefficient"));
2677//
2678// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 0, 1);
2679// BRK_IF_ERROR(
2680// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][1],
2681// "Polynomial distortion coefficient"));
2682//
2683// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 1, 1);
2684// BRK_IF_ERROR(
2685// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[1][1],
2686// "Polynomial distortion coefficient"));
2687//
2688// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 2, 0);
2689// BRK_IF_ERROR(
2690// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[2][0],
2691// "Polynomial distortion coefficient"));
2692//
2693// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 0, 2);
2694// BRK_IF_ERROR(
2695// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][2],
2696// "Polynomial distortion coefficient"));
2697//
2698// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 2, 1);
2699// BRK_IF_ERROR(
2700// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[2][1],
2701// "Polynomial distortion coefficient"));
2702//
2703// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 1, 2);
2704// BRK_IF_ERROR(
2705// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[1][2],
2706// "Polynpoly2domial distortion coefficient"));
2707//
2708// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d","QC COEFF", 3, 0);
2709// BRK_IF_ERROR(
2710// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[3][0],
2711// "Polynomial distortion coefficient"));
2712//
2713// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d","QC COEFF", 0, 3);
2714// BRK_IF_ERROR(
2715// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][3],
2716// "Polynomial distortion coefficient"));
2717//
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]);
2722// BRK_IF_ERROR(
2723// eris_ifu_dist_qclog_add_double(qc[i], "QC XSHIFT CC", xshift,
2724// "X shift in x_c,y_c"));
2725//
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]);
2730// BRK_IF_ERROR(
2731// eris_ifu_dist_qclog_add_double(qc[i], "QC XSHIFT LL", xshift,
2732// "X shift in x_l,y_l"));
2733//
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]);
2737// BRK_IF_ERROR(
2738// eris_ifu_dist_qclog_add_double(qc[i],"QC XSHIFT UL",xshift,
2739// "X shift in x_l,y_u"));
2740//
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]);
2744// BRK_IF_ERROR(
2745// eris_ifu_dist_qclog_add_double(qc[i],"QC XSHIFT UR",xshift,
2746// "X shift in x_u,y_u"));
2747//
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]);
2751// BRK_IF_ERROR(
2752// eris_ifu_dist_qclog_add_double(qc[i],"QC XSHIFT LR",xshift,
2753// "X shift in x_u,y_l"));
2754
2755 extname = cpl_sprintf("SLITLET%2.2d",i);
2756 cpl_propertylist_append_string(qc[i],"EXTNAME",extname);
2757 if (i == 0) {
2758 BRK_IF_ERROR(
2759 eris_ifu_save_table(frameset, NULL, parlist, frameset, NULL,
2760 REC_NAME_DISTORTION,
2761 ERIS_IFU_PRO_DIST_DISTORTION,
2762 qc[i], "EXTNAME",
2763 fn,
2764 poly_tbl));
2765 } else {
2766 BRK_IF_ERROR(
2767 cpl_table_save(poly_tbl, NULL, qc[i], fn, CPL_IO_EXTEND));
2768 }
2769 cpl_free(extname);
2770 eris_ifu_free_table(&poly_tbl);
2771 } // if (poly2d[ii] != NULL)
2772 } // end: i = SLITLET_CNT
2773
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
2778 BRK_IF_ERROR(
2779 cpl_table_save(minmax_borders, NULL, ext, fn, CPL_IO_EXTEND));
2780 cpl_propertylist_delete(ext);
2781 cpl_free(extname);
2782 }
2783 CATCH
2784 {
2785 CATCH_MSGS();
2786 err = cpl_error_get_code();
2787 }
2788
2789 return err;
2790}
2791
2805hdrl_image* eris_ifu_dist_warp_image_full(const hdrl_image *hdrl_img_in,
2806 cpl_polynomial **poly_u,
2807 int productDepth)
2808{
2809 cpl_size pows[2];
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;
2815 char *fn = NULL;
2816
2817 cpl_ensure(hdrl_img_in, CPL_ERROR_NULL_INPUT, NULL);
2818 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2819
2820 TRY
2821 {
2822 BRK_IF_NULL(
2823 poly_v = cpl_polynomial_new(2));
2824
2825 pows[0] = 0;
2826 pows[1] = 0;
2827 BRK_IF_ERROR(
2828 cpl_polynomial_set_coeff(poly_v, pows, 0.0));
2829 pows[0] = 0;
2830 pows[1] = 1;
2831 BRK_IF_ERROR(
2832 cpl_polynomial_set_coeff(poly_v, pows, 1.0));
2833
2834 BRK_IF_NULL(
2835 hdrl_img_warped = hdrl_image_new(hdrl_image_get_size_x(hdrl_img_in),
2836 hdrl_image_get_size_y(hdrl_img_in)));
2837
2838 BRK_IF_NULL(
2839 img_warped = hdrl_image_get_image(hdrl_img_warped));
2840
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);
2844
2845 BRK_IF_NULL(
2846 hdrl_img_warped_extr = eris_ifu_warp_polynomial_image(hdrl_img_in,
2847 poly_u[i], poly_v));
2848
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);
2852 BRK_IF_NULL(
2853 img_warped_extr = hdrl_image_get_image(hdrl_img_warped_extr));
2854
2855 if (productDepth & 8) {
2856 // save warped intermediate images uncut
2857 fn = cpl_sprintf("eris_ifu_distortion_dbg_warp_out_%02d.fits", i+1);
2858 BRK_IF_ERROR(
2859 eris_ifu_save_image_dbg(img_warped_extr, fn,
2860 CPL_IO_CREATE, NULL));
2861 }
2862
2863 if (i != 0) {
2864 // set to zero left of slitlet (except for first slitlet)
2865 BRK_IF_ERROR(
2866 cpl_image_fill_window(img_warped_extr, 1, 1, t_l,
2867 ERIS_IFU_DETECTOR_SIZE_Y, 0.));
2868 }
2869 if (i != SLITLET_CNT-1) {
2870 // set to zero right of slitlet (except for last slitlet)
2871 BRK_IF_ERROR(
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.));
2875 }
2876
2877 if (productDepth & 8) {
2878 // save warped intermediate images cut
2879 BRK_IF_ERROR(
2880 eris_ifu_save_image_dbg(img_warped_extr, fn,
2881 CPL_IO_EXTEND, NULL));
2882 cpl_free(fn); fn = NULL;
2883 }
2884
2885 BRK_IF_ERROR(
2886 cpl_image_add(img_warped, img_warped_extr));
2887
2888 eris_ifu_free_hdrl_image(&hdrl_img_warped_extr);
2889 }
2890 } // end: i = SLITLET_CNT
2891 }
2892 CATCH
2893 {
2894 CATCH_MSGS();
2895 eris_ifu_free_hdrl_image(&hdrl_img_warped);
2896 }
2897
2898 eris_ifu_free_polynomial(&poly_v);
2899
2900 return hdrl_img_warped;
2901}
2902
2923hdrl_image* eris_ifu_dist_warp_slitlet(const hdrl_image *imgIn,
2924 const cpl_polynomial *poly_u,
2925 const cpl_polynomial *poly_v,
2926 double l_min,
2927 double r_max,
2928 int slitletNr)
2929{
2930 int llx = 0,
2931 urx = 0;
2932 hdrl_image *imgOutSlit = NULL,
2933 *imgInSlit = NULL,
2934 *imgOutSlitTrim = NULL;
2935
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);
2939
2940
2941 TRY
2942 {
2943 // get left and right nominal border of slitlet
2944 llx = (int)(l_min)+1;
2945 urx = (int)(r_max)+1;
2946
2947 if ((llx > 0) && (urx <= ERIS_IFU_DETECTOR_SIZE_X)) {
2948 BRK_IF_NULL(
2949 imgInSlit = hdrl_image_extract(imgIn,
2950 llx, 1,
2951 urx, ERIS_IFU_DETECTOR_SIZE_Y));
2952 } else {
2953 BRK_IF_NULL(
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
2956 cpl_mask *tmpMask;
2957 BRK_IF_NULL(
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);
2962 hdrl_image *tmpImg;
2963 if (llx < 1) {
2964 BRK_IF_NULL(
2965 tmpImg = hdrl_image_extract(imgIn,
2966 1, 1, urx, ERIS_IFU_DETECTOR_SIZE_Y));
2967 int pos1 = -llx + 2;
2968 BRK_IF_ERROR(
2969 hdrl_image_copy(imgInSlit,tmpImg, pos1, 1));
2970 } else {
2971 BRK_IF_NULL(
2972 tmpImg = hdrl_image_extract(imgIn,
2973 llx, 1, ERIS_IFU_DETECTOR_SIZE_X, ERIS_IFU_DETECTOR_SIZE_Y));
2974 BRK_IF_ERROR(
2975 hdrl_image_copy(imgInSlit,tmpImg, 1, 1));
2976 }
2977 eris_ifu_free_hdrl_image(&tmpImg);
2978 }
2979
2980 BRK_IF_NULL(
2981 imgOutSlit = eris_ifu_warp_polynomial_image(imgInSlit,
2982 poly_u, poly_v));
2983
2984 if (hdrl_image_get_size_x(imgOutSlit) > SLITLET_WIDTH) {
2985 // extract left 64 pixels of slitlet (all data to the right is invalid)
2986 BRK_IF_NULL(
2987 imgOutSlitTrim = hdrl_image_extract(imgOutSlit,
2988 1, 1,
2989 SLITLET_WIDTH,
2990 ERIS_IFU_DETECTOR_SIZE_Y));
2991 } else {
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));
2994 BRK_IF_NULL(
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
2999 //int offset = 0;
3000 BRK_IF_ERROR(
3001 eris_ifu_image_add_slit(imgOutSlitTrim, imgOutSlit, offset));
3002 }
3003 }
3004 CATCH
3005 {
3006 CATCH_MSGS();
3007 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
3008 }
3009
3010 eris_ifu_free_hdrl_image(&imgOutSlit);
3011 eris_ifu_free_hdrl_image(&imgInSlit);
3012
3013 return imgOutSlitTrim;
3014}
3015
3034hdrl_image* eris_ifu_dist_warp_image(const hdrl_image *imgIn,
3035 cpl_polynomial **poly_u,
3036 const cpl_table *borders)
3037{
3038 int tmp = 0;
3039 cpl_size pows[2];
3040 cpl_polynomial *poly_v = NULL;
3041 hdrl_image *imgOut = NULL,
3042 *imgOutSlitTrim = NULL;
3043
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);
3047
3048 TRY
3049 {
3050 BRK_IF_NULL(
3051 poly_v = cpl_polynomial_new(2));
3052 pows[0] = 0; pows[1] = 0;
3053 BRK_IF_ERROR(
3054 cpl_polynomial_set_coeff(poly_v, pows, 0.0));
3055 pows[0] = 0; pows[1] = 1;
3056 BRK_IF_ERROR(
3057 cpl_polynomial_set_coeff(poly_v, pows, 1.0));
3058
3059 BRK_IF_NULL(
3060 imgOut = hdrl_image_new(hdrl_image_get_size_x(imgIn),
3061 hdrl_image_get_size_y(imgIn)));
3062
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);
3066
3067 // Extract, warp and trim slitlet
3068 // (can be parallelized)
3069 BRK_IF_NULL(
3070 imgOutSlitTrim = eris_ifu_dist_warp_slitlet(imgIn,
3071 poly_u[i],
3072 poly_v,
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),
3075 i));
3076
3077 // add- in slitlet to synthetic full warped image
3078 // (can be parallelized)
3079 BRK_IF_ERROR(
3080 eris_ifu_image_add_slit(imgOut,
3081 imgOutSlitTrim,
3082 eris_ifu_distortion_target_left_edge(i)));
3083
3084 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
3085
3086 }
3087 } // end: i = SLITLET_CNT
3088 }
3089 CATCH
3090 {
3091 CATCH_MSGS();
3092 eris_ifu_free_hdrl_image(&imgOut);
3093 }
3094 eris_ifu_free_polynomial(&poly_v);
3095 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
3096
3097 return imgOut;
3098}
3099
3119hdrl_image* eris_ifu_dist_warp_bpm(const hdrl_image *bpmIn,
3120 cpl_polynomial **poly_u,
3121 const cpl_table *borders,
3122 productDepthType productDepth)
3123{
3124 int tmp = 0;
3125 cpl_size pows[2];
3126 cpl_polynomial *poly_v = NULL;
3127 hdrl_image *bpmOut = NULL,
3128 *imgOutSlitTrim = NULL;
3129
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);
3133
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);
3137
3138 hdrl_image *col_hmap = hdrl_image_new(size_x, size_y);
3139
3140 //Initialize each pixel to its column number; start from 1.
3141 for (cpl_size i = 1; i <= size_x; i++){
3142 hdrl_value col_num;
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);
3147 }
3148 }
3149 if (productDepth >= PD_DEBUG) {
3150 eris_ifu_save_hdrl_image_dbg(col_hmap, "eris_ifu_distortion_dbg_col_hmap", 1, NULL);
3151 }
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);
3157
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,
3163 poly_u[i],
3164 poly_v,
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),
3167 i);
3168
3169 // add-in slitlet to synthetic full warped image
3170 eris_ifu_image_add_slit(col_hmap_warped,
3171 imgOutSlitTrim,
3172 eris_ifu_distortion_target_left_edge(i));
3173
3174 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
3175
3176 }
3177 hdrl_image_delete(col_hmap);
3178
3179 if (productDepth >= PD_DEBUG) {
3180 eris_ifu_save_hdrl_image_dbg(col_hmap_warped, "eris_ifu_distortion_dbg_col_hmap_warped", 1, NULL);
3181 }
3182
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);
3186 int slitwidth = 0;
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
3191 slitwidth = 61;
3192 else if (k + 1 == 2)
3193 slitwidth = 62;
3194 else if (k + 1== 10)
3195 slitwidth = 63;
3196 else
3197 slitwidth = SLITLET_WIDTH;
3198
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;
3208 }
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) {
3213 col_n = -1;
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
3217 int g = x+1;
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)) {
3220 g++;
3221 ggg = hdrl_image_get_pixel(col_hmap_warped, g+k*SLITLET_WIDTH, y, NULL);
3222 }
3223 // go even one more to the right, because the first difference is smaller than the other differences
3224 g++;
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;
3231 }
3232 if ((x==1) && !fake_col_n_0)
3233 col_n_0 = col_n;
3234 hdrl_value pix_bpm;
3235 if ((col_n < 1) || isnan(contri_n))
3236 {
3237 // either left border
3238 // or pix_contr.data is nan
3239 pix_bpm.data = 1;
3240 pix_bpm.error = 1;
3241 } else if (col_n > ERIS_IFU_DETECTOR_SIZE_X || col_n-col_n_0+1 > slitwidth+2) //right border or right edge
3242 {
3243 pix_bpm.data = 1;
3244 pix_bpm.error = 1;
3245 } else if (col_n == ERIS_IFU_DETECTOR_SIZE_X || col_n-col_n_0+1 == slitwidth+2)
3246 {
3247 pix_bpm.data = hdrl_image_get_pixel(bpmIn, col_n, y, NULL).data * contri_n + 1.0 * (1.0-contri_n);
3248 }
3249 else {
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);
3252 }
3253
3254 hdrl_image_set_pixel(bpmOut, x+k*SLITLET_WIDTH, y, pix_bpm);
3255 }
3256 }
3257 }
3258
3259 hdrl_image_delete(col_hmap_warped);
3260
3261 eris_ifu_free_polynomial(&poly_v);
3262
3263 return bpmOut;
3264}
3265
3280hdrl_imagelist* eris_ifu_stack_warped(const hdrl_image *imgIn,
3281 const int *rowIx)
3282{
3283 cpl_ensure(imgIn, CPL_ERROR_NULL_INPUT, NULL);
3284
3285 int cnt = 0;
3286 double *pImgTmpData = NULL,
3287 *pImgTmpErr = NULL;
3288 const double *pImgInData = NULL,
3289 *pImgInErr = NULL;
3290 hdrl_image *imgTmp = NULL;
3291 hdrl_imagelist *cube = NULL;
3292
3293 TRY
3294 {
3295 BRK_IF_NULL(
3296 cube = hdrl_imagelist_new());
3297
3298 BRK_IF_NULL(
3299 pImgInData = cpl_image_get_data_double_const(hdrl_image_get_image_const(imgIn)));
3300 BRK_IF_NULL(
3301 pImgInErr = cpl_image_get_data_double_const(hdrl_image_get_error_const(imgIn)));
3302
3303
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...
3307 BRK_IF_NULL(
3308 imgTmp = hdrl_image_new(SLITLET_WIDTH, SLITLET_CNT));
3309 BRK_IF_NULL(
3310 pImgTmpData = cpl_image_get_data_double(hdrl_image_get_image(imgTmp)));
3311 BRK_IF_NULL(
3312 pImgTmpErr = cpl_image_get_data_double(hdrl_image_get_error(imgTmp)));
3313
3314
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++];
3318 }
3319 }
3320 BRK_IF_ERROR(
3321 hdrl_imagelist_set(cube, imgTmp, z));
3322 }
3323 }
3324 CATCH
3325 {
3326 CATCH_MSGS();
3327 eris_ifu_free_hdrl_imagelist(&cube);
3328 }
3329
3330 return cube;
3331}
3332
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)
3361{
3362 int nr_values = 21, //odd
3363 height = 90, //even
3364 center_y = 0,
3365 actual_size = 0,
3366// ix_middle = nr_values / 2 + 1;
3367 ix_middle = 9;
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;
3377 double swidth = 64;
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);
3383
3384 TRY
3385 {
3386 BRK_IF_NULL(
3387 arr = cpl_calloc(SLITLET_CNT, sizeof(cpl_table*)));
3388
3389 BRK_IF_NULL(
3390 warpedImg = hdrl_image_get_image_const(hdrlWarpedImg));
3391
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;
3394 BRK_IF_NULL(
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)
3398 BRK_IF_NULL(
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)
3401 BRK_IF_NULL(
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);
3407
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);
3415 }
3416 } else {
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);
3426
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);
3430 }
3431 }
3432
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,
3441 height);
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,
3444 CPL_FALSE);
3445
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);
3449
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]);
3454 if (i > 0) {
3455 cpl_table_set_double(arr[i], "left", j, (i-1) * swidth);
3456 cpl_table_set_double(arr[i], "left", j, i * swidth);
3457 }
3458 }
3459 } else {
3460 // three traces per slitlet
3461 int ii = 0;
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);
3465 } else {
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);
3474 /* OLD code */
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]);
3478 /* end old code */
3479 ii++;
3480 }
3481 }
3482 }
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);
3486 }
3487
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 */
3492 BRK_IF_NULL(
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 */
3496 BRK_IF_NULL(
3497 fit_centers = eris_ifu_dist_calc_centers_fit(profile_x, est_centers, CPL_FALSE));
3498
3499 BRK_IF_NULL(
3500 pfit_centers = cpl_vector_get_data_const(fit_centers));
3501
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]);
3507 }
3508 } else {
3509 // three traces per slitlet
3510 int ii = 0;
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);
3514 } else {
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);
3523
3524 /* OLD code */
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]);
3528 /* end old code */
3529 ii++;
3530 }
3531 }
3532 }
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);
3536
3537 }
3538
3539 char* extname;
3540 char* keyname;
3541 char* keycomm;
3542
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,
3549 CPL_IO_CREATE);
3550
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);
3554
3555
3556
3557
3558 for (int i = 0; i < SLITLET_CNT; i++) {
3559
3560 BRK_IF_NULL(
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);
3570 cpl_free(keyname);
3571 cpl_free(keycomm);
3572
3573
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);
3578 cpl_free(keyname);
3579 cpl_free(keycomm);
3580 } else {
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);
3585 cpl_free(keyname);
3586 cpl_free(keycomm);
3587
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);
3592 cpl_free(keyname);
3593 cpl_free(keycomm);
3594
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);
3599 cpl_free(keyname);
3600 cpl_free(keycomm);
3601
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);
3606 cpl_free(keyname);
3607 cpl_free(keycomm);
3608
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);
3613 cpl_free(keyname);
3614 cpl_free(keycomm);
3615
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);
3620 cpl_free(keyname);
3621 cpl_free(keycomm);
3622
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);
3627 cpl_free(keyname);
3628 cpl_free(keycomm);
3629
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);
3634 cpl_free(keyname);
3635 cpl_free(keycomm);
3636
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);
3641 cpl_free(keyname);
3642 cpl_free(keycomm);
3643
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);
3648 cpl_free(keyname);
3649 cpl_free(keycomm);
3650
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);
3655 cpl_free(keyname);
3656 cpl_free(keycomm);
3657
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);
3662 cpl_free(keyname);
3663 cpl_free(keycomm);
3664
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);
3669 cpl_free(keyname);
3670 cpl_free(keycomm);
3671
3672
3673 }
3674
3675 BRK_IF_ERROR(
3676 cpl_table_save(arr[i], NULL, pl_my,
3677 ERIS_IFU_PRO_DIST_QC_WARPED_FIT_FN,
3678 CPL_IO_EXTEND));
3679 eris_ifu_free_propertylist(&pl_my);
3680 cpl_free(extname);
3681 }
3682 }
3683 CATCH
3684 {
3685 CATCH_MSGS();
3686 err = cpl_error_get_code();
3687 }
3688
3689 for (int i = 0; i < SLITLET_CNT; i++) {
3690 eris_ifu_free_table(&arr[i]);
3691 }
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);
3698 eris_check_error_code("eris_ifu_dist_warp_stats");
3699 return err;
3700}
3701
3715cpl_error_code eris_ifu_image_add_slit(hdrl_image *hdrlImgFull,
3716 const hdrl_image *hdrlImgSlit,
3717 int offset)
3718{
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;
3730 int widthFull = 0,
3731 widthSlit = 0;
3732
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);
3742
3743 TRY
3744 {
3745 tmpImgFull = hdrl_image_get_image(hdrlImgFull);
3746 tmpMaskFull = cpl_image_get_bpm(tmpImgFull);
3747 BRK_IF_NULL(
3748 pimgFullData = cpl_image_get_data(tmpImgFull));
3749 BRK_IF_NULL(
3750 pimgFullErr = cpl_image_get_data(hdrl_image_get_error(hdrlImgFull)));
3751 if (tmpMaskFull != NULL) {
3752 BRK_IF_NULL(
3753 pimgFullMask = cpl_mask_get_data(tmpMaskFull));
3754 }
3755 widthFull = (int) hdrl_image_get_size_x(hdrlImgFull);
3756
3757 tmpImgSlit = hdrl_image_get_image_const(hdrlImgSlit);
3758 tmpMaskSlit = cpl_image_get_bpm_const(tmpImgSlit);
3759 BRK_IF_NULL(
3760 pimgSlitData = cpl_image_get_data_const(tmpImgSlit));
3761 BRK_IF_NULL(
3762 pimgSlitErr = cpl_image_get_data_const(hdrl_image_get_error_const(hdrlImgSlit)));
3763 if (tmpMaskSlit != NULL) {
3764 BRK_IF_NULL(
3765 pimgSlitMask = cpl_mask_get_data_const(tmpMaskSlit));
3766 }
3767
3768 widthSlit = (int) hdrl_image_get_size_x(hdrlImgSlit);
3769
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];
3776 }
3777 }
3778 }
3779 }
3780 CATCH
3781 {
3782 CATCH_MSGS();
3783 err = cpl_error_get_code();
3784 }
3785
3786 return err;
3787}
3788
3818cpl_table** eris_ifu_dist_calc_slitpos(cpl_image **arcImg,
3819 cpl_table **centers_array,
3820 cpl_table *valid_arc_lines,
3821 int productDepth,
3822 cpl_boolean *cut_off_left,
3823 cpl_boolean *cut_off_right,
3824 const cpl_frameset* frameset,
3825 const cpl_parameterlist* parlist)
3826{
3827 int max_lines = 200,
3828 middle = 0,
3829 half_height =0,
3830 urx, ury, llx, lly = 0;
3831// max_pos = 0;
3832 double arc_center = 0.,
3833 percentage = 0.,
3834// cut_level = 0.,
3835// max = -DBL_MAX,
3836 median = 0,
3837 stddev = 0.,
3838// *pprofile_y = NULL,
3839 *pleft_edge_tmp = NULL,
3840 *pright_edge_tmp= NULL,
3841 *pypos_tmp = NULL,
3842 *pleft_edge = NULL,
3843 *pright_edge = NULL,
3844 *pypos = 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;
3850// *img_data = NULL;
3851 cpl_table **tbl = NULL,
3852 *valid_arc_lines_slitlet = NULL;
3853 cpl_vector *left_edge_tmp = NULL,
3854 *right_edge_tmp = NULL,
3855 *ypos_tmp = NULL,
3856 *left_edge = NULL,
3857 *right_edge = NULL,
3858 *ypos = NULL;
3859 cpl_propertylist *pl_tbl = NULL;
3860 eris_ifu_vector *slit_width = NULL,
3861 *slit_width_rej = NULL,
3862 *left_edge_rej = 0,
3863 *right_edge_rej = 0;
3864
3865 cpl_ensure(arcImg, CPL_ERROR_NULL_INPUT, NULL);
3866 cpl_ensure(*centers_array, CPL_ERROR_NULL_INPUT, NULL);
3867
3868 TRY
3869 {
3870 *cut_off_right = FALSE;
3871 *cut_off_right = FALSE;
3872
3873 BRK_IF_NULL(
3874 left_edge_tmp = cpl_vector_new(max_lines));
3875 BRK_IF_NULL(
3876 right_edge_tmp = cpl_vector_new(max_lines));
3877 BRK_IF_NULL(
3878 ypos_tmp = cpl_vector_new(max_lines));
3879
3880 BRK_IF_NULL(
3881 pleft_edge_tmp = cpl_vector_get_data(left_edge_tmp));
3882 BRK_IF_NULL(
3883 pright_edge_tmp = cpl_vector_get_data(right_edge_tmp));
3884 BRK_IF_NULL(
3885 pypos_tmp = cpl_vector_get_data(ypos_tmp));
3886
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);
3897 cpl_free(pipe_id);
3898 CHECK_ERROR_STATE();
3899 // BRK_IF_ERROR(
3900 // cpl_propertylist_save(pl_tbl, ERIS_IFU_PRO_DIST_SLIT_POS_FN, CPL_IO_CREATE));
3901
3902 BRK_IF_NULL(
3903 tbl = cpl_calloc(SLITLET_CNT, sizeof(cpl_table*)));
3904
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);
3908 }
3909 /* loop all slitlets */
3910 for (int i = 0; i < SLITLET_CNT; i++) {
3911 cpl_msg_debug(cpl_func, "i: %d", i);
3912 int ttt = 0;
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();
3917
3918 if ((productDepth & 3) != 0) {
3919 cpl_msg_debug(cpl_func, " Slitlet #%i: center pos: %g", i+1,
3920 arc_center);
3921 }
3922
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);
3928 }
3929 /* loop all lines (brighter than a tenth of the brightest line)
3930 * in vertical profile and detect edges */
3931 int y = 0,
3932 arcImgIx = 0,
3933 nr_lines = 0;
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;
3943
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
3949 {
3950 //old
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
3957
3958 if (llx < 1)
3959 llx = 1;
3960 if (urx > 2048)
3961 urx = 2048;
3962
3963 BRK_IF_NULL(
3964 profile_x = cpl_image_collapse_window_create(arcImg[arcImgIx],
3965 llx, lly,
3966 urx, ury, 0));
3967 }
3968// {//new
3969// // identify actual ypos in valid_lines2
3970// int valid_line = 0;
3971// if (a > 0) {
3972// valid_line = y;
3973// } else if (b > 0){
3974// valid_line = y+1;
3975// }
3976//
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);
3981//
3984//
3985//
3986// // get the according y-values
3987//
3988// // create a line accross the detector from llx to urx
3989//
3990// // create a profile in a way that +/-3or5 pix vertically around the line are averaged and put into profile_x
3991// }
3992
3993 cpl_error_code status = eris_ifu_slitpos_gauss(
3994 profile_x,
3995 &(pleft_edge_tmp[nr_lines]),
3996 &(pright_edge_tmp[nr_lines]),
3997 llx-1,
3998 productDepth);
3999 if (status == CPL_ERROR_EOL) {
4000 RECOVER();
4001 }
4002
4003 pleft_edge_tmp[nr_lines] -= 1.;
4004 pright_edge_tmp[nr_lines] -= 1.;
4005
4006 if (productDepth & 8) {
4007 cpl_propertylist *pl_line = NULL;
4008 BRK_IF_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);
4022 }
4023 eris_ifu_free_image(&profile_x);
4024
4025 if (status == CPL_ERROR_EOL) {
4026 continue;
4027 } else if (status != CPL_ERROR_NONE) {
4028 ERIS_IFU_TRY_EXIT();
4029 }
4030 nr_lines++;
4031 if (nr_lines >= max_lines) {
4032 SET_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
4033 "more than 100 lines detected!");
4034/*erw
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);
4040
4041 eris_ifu_free_image(&profile_x);
4042
4043 // get off surroundings of already processed line
4044 y+=5;
4045 // found line
4046 nr_lines++;
4047 if (nr_lines >= max_lines) {
4048 SET_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
4049 "more than 100 lines detected!");
4050*/
4051 }
4052
4053// } // end: if detected line
4054// y++;
4055 } // end: while y
4056
4057 eris_ifu_free_table(&valid_arc_lines_slitlet);
4058
4059 /* cut vectors to their correct length */
4060 BRK_IF_NULL(
4061 left_edge = cpl_vector_extract(left_edge_tmp, 0, nr_lines-1, 1));
4062 BRK_IF_NULL(
4063 right_edge = cpl_vector_extract(right_edge_tmp, 0, nr_lines-1, 1));
4064 BRK_IF_NULL(
4065 ypos = cpl_vector_extract(ypos_tmp, 0, nr_lines-1, 1));
4066 BRK_IF_NULL(
4067 pleft_edge = cpl_vector_get_data(left_edge));
4068 BRK_IF_NULL(
4069 pright_edge = cpl_vector_get_data(right_edge));
4070 BRK_IF_NULL(
4071 pypos = cpl_vector_get_data(ypos));
4072
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]);
4076 }
4077
4078 /*
4079 * omit outliers in a multi process step
4080 */
4081 BRK_IF_NULL(
4082 pl_tbl = cpl_propertylist_new());
4083
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();
4088 BRK_IF_ERROR(
4089 cpl_propertylist_append_double(pl_tbl, "bef_med", median));
4090 BRK_IF_ERROR(
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;
4095 BRK_IF_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);
4100 BRK_IF_ERROR(
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);
4105 BRK_IF_ERROR(
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);
4110 BRK_IF_ERROR(
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);
4115 BRK_IF_ERROR(
4116 eris_ifu_vector_save(slit_width, fn, CPL_TYPE_DOUBLE,
4117 pl_tbl, CPL_IO_EXTEND, 70));
4118 eris_ifu_free_propertylist(&pl);
4119 }
4120
4121 BRK_IF_NULL(
4122 left_edge_rej = eris_ifu_vector_create(left_edge));
4123 BRK_IF_NULL(
4124 right_edge_rej = eris_ifu_vector_create(right_edge));
4125 BRK_IF_NULL(
4126 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
4127
4128 if ((median < 58) && (stddev > 3) &&
4129 ((i == 0) || (i == SLITLET_CNT-1)))
4130 {
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);
4139 }
4140 }
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);
4146 BRK_IF_NULL(
4147 left_edge_rej = eris_ifu_vector_create(left_edge));
4148 BRK_IF_NULL(
4149 right_edge_rej = eris_ifu_vector_create(right_edge));
4150 BRK_IF_NULL(
4151 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
4152} else {
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();
4156
4157 BRK_IF_ERROR(
4158 cpl_propertylist_append_double(pl_tbl, "med_rej1", median));
4159 BRK_IF_ERROR(
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);
4166 BRK_IF_ERROR(
4167 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl, CPL_IO_EXTEND, 70));
4168 }
4169}
4170 if (i == 0) {
4171 *cut_off_left = CPL_TRUE;
4172 BRK_IF_ERROR(
4173 cpl_propertylist_append_string(pl_tbl, "cutoff", "left"));
4174 }
4175 if (i == SLITLET_CNT-1) {
4176 *cut_off_right = CPL_TRUE;
4177 BRK_IF_ERROR(
4178 cpl_propertylist_append_string(pl_tbl, "cutoff", "right"));
4179 }
4180 }
4181
4182 /* omit outliers devying more than 2% (15% for problematic slitlet #16)*/
4183 percentage = 1.02;
4184 if (i == 15 || i == 17) {
4185 percentage = 1.15;
4186 }
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);
4193 }
4194 }
4195
4196 median = eris_ifu_vector_get_median(slit_width_rej, ERIS_IFU_ARITHMETIC);
4197 BRK_IF_ERROR(
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);
4201 BRK_IF_ERROR(
4202 cpl_propertylist_append_double(pl_tbl, "aft_sdv", stddev));
4203 }
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);
4210 BRK_IF_ERROR(
4211 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl, CPL_IO_EXTEND, 70));
4212 }
4213
4214 /*
4215 * check if first or last slitlet is off detector (partially cut off)
4216 * (2nd test)
4217 */
4218 if ((i == 0) && ((*cut_off_left == CPL_TRUE) ||
4219 (eris_ifu_vector_get_min(left_edge_rej, NULL) < ERIS_IFU_DETECTOR_BP_BORDER)))
4220 {
4221 *cut_off_left = CPL_TRUE;
4222 if (!cpl_propertylist_has(pl_tbl, "cutoff")) {
4223 BRK_IF_ERROR(
4224 cpl_propertylist_append_string(pl_tbl, "cutoff", "left"));
4225 }
4226
4227 // reset slit_width
4228 eris_ifu_free_ifu_vector(&slit_width_rej);
4229 BRK_IF_NULL(
4230 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
4231
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);
4236 }
4237 cpl_vector *fff = eris_ifu_polyfit_edge(x, slit_width_rej, 1);
4238 eris_ifu_free_ifu_vector(&x);
4239
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);
4249 }
4250 }
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);
4255 BRK_IF_ERROR(
4256 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl,
4257 CPL_IO_EXTEND, 70));
4258 }
4259 } // if left_edge cut off
4260
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)))
4263 {
4264 *cut_off_right = TRUE;
4265 if (!cpl_propertylist_has(pl_tbl, "cutoff")) {
4266 BRK_IF_ERROR(
4267 cpl_propertylist_append_string(pl_tbl, "cutoff", "right"));
4268 }
4269
4270 // reset slit_width
4271 eris_ifu_free_ifu_vector(&slit_width_rej);
4272 BRK_IF_NULL(
4273 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
4274
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);
4279 }
4280 cpl_vector *fff = eris_ifu_polyfit_edge(x, slit_width_rej, 1);
4281 eris_ifu_free_ifu_vector(&x);
4282
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
4292 BRK_IF_ERROR(
4293 eris_ifu_vector_reject(slit_width_rej, ty));
4294 }
4295 }
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);
4300 BRK_IF_ERROR(
4301 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl,
4302 CPL_IO_EXTEND, 70));
4303 }
4304 } // if right_edge cut off
4305
4306 eris_ifu_free_ifu_vector(&left_edge_rej);
4307 eris_ifu_free_ifu_vector(&right_edge_rej);
4308 CHECK_ERROR_STATE();
4309
4310 /* setup table to save */
4311 BRK_IF_NULL(
4312 tbl[i] = cpl_table_new(eris_ifu_vector_count_non_rejected(slit_width_rej)));
4313 BRK_IF_ERROR(
4314 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_EDGE_L, CPL_TYPE_DOUBLE));
4315 BRK_IF_ERROR(
4316 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_EDGE_R, CPL_TYPE_DOUBLE));
4317 BRK_IF_ERROR(
4318 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_SLIT, CPL_TYPE_DOUBLE));
4319 BRK_IF_ERROR(
4320 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_YPOS, CPL_TYPE_DOUBLE));
4321
4322 // copy vectors to table
4323 int cnt = 0;
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
4327 BRK_IF_ERROR(
4328 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_YPOS, cnt, pypos[ty]));
4329 BRK_IF_ERROR(
4330 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_L, cnt, pleft_edge[ty]));
4331 BRK_IF_ERROR(
4332 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_R, cnt, pright_edge[ty]));
4333 BRK_IF_ERROR(
4334 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_SLIT, cnt, eris_ifu_vector_get(slit_width_rej, ty)));
4335
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) {
4339 BRK_IF_ERROR(
4340 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_L, cnt, NAN));
4341 BRK_IF_ERROR(
4342 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_SLIT, cnt, pright_edge[ty]-ERIS_IFU_DETECTOR_BP_BORDER));
4343 }
4344 }
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) {
4348 BRK_IF_ERROR(
4349 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_R, cnt, NAN));
4350 BRK_IF_ERROR(
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]));
4352 }
4353 }
4354
4355 cnt++;
4356 }
4357 }
4358
4359 extname = cpl_sprintf("Sx_%02d", i+1);
4360 cpl_propertylist_append_string(pl_tbl, "EXTNAME", extname);
4361 eris_ifu_free_string(&extname);
4362 BRK_IF_ERROR(
4363 cpl_table_save(tbl[i], NULL, pl_tbl, ERIS_IFU_PRO_DIST_SLIT_POS_FN, CPL_IO_EXTEND));
4364
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
4372 }
4373 CATCH
4374 {
4375 CATCH_MSGS();
4376
4377 eris_ifu_free_image(&profile_x);
4378 for (int i = 0; i < SLITLET_CNT; i++) {
4379 eris_ifu_free_table(&tbl[i]);
4380 }
4381 cpl_free(tbl); tbl = NULL;
4382 }
4383
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);
4393
4394 return tbl;
4395}
4396
4417cpl_error_code eris_ifu_fit_gauss(const cpl_vector *x,
4418 const cpl_vector *y,
4419 double *x0,
4420 double *sigma,
4421 double *area,
4422 double *offset)
4423{
4424 cpl_error_code ret_error = CPL_ERROR_NONE,
4425 fit_error = CPL_ERROR_NONE;
4426
4427
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);
4434
4435 TRY
4436 {
4437 *x0 = 0.;
4438 *sigma = 0.;
4439 *area = 0.;
4440 *offset = 0.;
4441
4442 fit_error = cpl_vector_fit_gaussian(x, NULL, y, NULL,
4443 CPL_FIT_ALL,
4444 x0,
4445 sigma,
4446 area,
4447 offset,
4448 NULL, NULL, NULL);
4449
4450// cpl_msg_debug(cpl_func, " --- 1st FIT ---------------------"
4451// "-------------");
4452// cpl_msg_debug(cpl_func, " center: %g (sigma: %g, area: %g,"
4453// " offset: %g)", *x0, *sigma, *area, *offset);
4454
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))
4458 {
4459 cpl_error_reset();
4460 fit_error = CPL_ERROR_CONTINUE;
4461 }
4462
4463 if (fit_error == CPL_ERROR_CONTINUE) {
4464 // if first fit doesn't convert, try it again with fixed
4465 // area- and sigma-parameter
4466 RECOVER();
4467
4468 fit_error = cpl_vector_fit_gaussian(x, NULL, y, NULL,
4469 CPL_FIT_CENTROID | CPL_FIT_OFFSET,
4470 x0,
4471 sigma,
4472 area,
4473 offset,
4474 NULL, NULL, NULL);
4475
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);
4481
4482 if (fit_error == CPL_ERROR_CONTINUE) {
4483 // if it didn't convert again, give up and take the
4484 // estimated value
4485 RECOVER();
4486 }
4487 }
4488 CHECK_ERROR_STATE();
4489 }
4490 CATCH
4491 {
4492 ret_error = cpl_error_get_code();
4493
4494 *x0 = -1;
4495 *sigma = -1;
4496 *area = -1;
4497 *offset = -1;
4498 }
4499
4500 return ret_error;
4501}
4502
4522cpl_vector* eris_ifu_polyfit_edge(const eris_ifu_vector *x,
4523 const eris_ifu_vector *y,
4524 int fit_order)
4525{
4526 eris_ifu_vector *x_dup = NULL,
4527 *y_dup = NULL,
4528 *fit_vec = NULL;
4529 cpl_vector *fit_par = NULL,
4530 *x_good = NULL,
4531 *y_good = NULL;
4532 double *pfit_par = NULL,
4533 *pfdata = NULL,
4534 *pfmask = NULL,
4535 stddev = 0.0,
4536 median = 0.0,
4537 *pxdata = NULL,
4538 *pxmask = NULL,
4539 *pymask = NULL;
4540 int size = 0,
4541 iter = 3,
4542 i = 0,
4543 j = 0;
4544
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);
4549
4550 TRY
4551 {
4552 // assert that rejected values in x are also rejected in y and vice versa
4553 BRK_IF_NULL(
4554 x_dup = eris_ifu_vector_duplicate(x));
4555 BRK_IF_NULL(
4556 y_dup = eris_ifu_vector_duplicate(y));
4557 BRK_IF_ERROR(
4558 eris_ifu_vector_adapt_rejected(x_dup, y_dup));
4559
4560 size = (int) cpl_vector_get_size(x_dup->data);
4561
4562 BRK_IF_NULL(
4563 pxdata = cpl_vector_get_data(x_dup->data));
4564 BRK_IF_NULL(
4565 pxmask = cpl_vector_get_data(x_dup->mask));
4566 BRK_IF_NULL(
4567 pymask = cpl_vector_get_data(y_dup->mask));
4568
4569 BRK_IF_NULL(
4570 fit_vec = eris_ifu_vector_new(size));
4571 BRK_IF_NULL(
4572 pfdata = cpl_vector_get_data(fit_vec->data));
4573 BRK_IF_NULL(
4574 pfmask = cpl_vector_get_data(fit_vec->mask));
4575
4576 // iterate fitting
4577 for (i = 0; i < iter; i++)
4578 {
4579 cpl_vector_delete(fit_par); fit_par = NULL;
4580
4581 // fit
4582 BRK_IF_NULL(
4583 x_good = eris_ifu_vector_create_non_rejected(x_dup));
4584 BRK_IF_NULL(
4585 y_good = eris_ifu_vector_create_non_rejected(y_dup));
4586
4587 BRK_IF_NULL(
4588 fit_par = eris_ifu_polyfit_1d(x_good, y_good, fit_order));
4589 BRK_IF_NULL(
4590 pfit_par = cpl_vector_get_data(fit_par));
4591
4592 eris_ifu_free_vector(&x_good);
4593 eris_ifu_free_vector(&y_good);
4594
4595 // create fitted vector
4596 for (j = 0; j < size; j++) {
4597 if (eris_ifu_vector_is_rejected(x_dup, j)) {
4598 BRK_IF_ERROR(
4599 eris_ifu_vector_reject(fit_vec, j));
4600 } else {
4601 double fit_val = -pfit_par[0];
4602 if (fit_order >= 1) {
4603 fit_val -= pfit_par[1] * pxdata[j];
4604 }
4605 if (fit_order >= 2) {
4606 fit_val -= pfit_par[2] * pow(pxdata[j], 2);
4607 }
4608 if (fit_order >= 3) {
4609 fit_val -= pfit_par[3] * pow(pxdata[j], 3);
4610 }
4611
4612 BRK_IF_ERROR(
4613 eris_ifu_vector_set(fit_vec, j, fit_val));
4614 }
4615 }
4616
4617 // fit_vec = y_good - fit_vec
4618 BRK_IF_ERROR(
4619 eris_ifu_vector_add(fit_vec, y_dup));
4620
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();
4624
4625 BRK_IF_ERROR(
4626 eris_ifu_vector_abs(fit_vec));
4627
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)) {
4632 pfmask[j] = 0.;
4633 pxmask[j] = 0.;
4634 pymask[j] = 0.;
4635 }
4636 }
4637 } // for i = iter
4638 }
4639 CATCH
4640 {
4641 CATCH_MSGS();
4642 eris_ifu_free_vector(&fit_par);
4643 }
4644
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);
4650
4651 return fit_par;
4652}
4653
4677cpl_error_code eris_ifu_wavecal_processSof_dist(
4678 cpl_frameset* frames,
4679 int exposureCorrectionMode,
4680 int *arcImgCnt,
4681 hdrl_imagelist **arcImages,
4682 int **lampStates,
4683 ifsBand *band,
4684 ifsPreopticsScale *scale,
4685 ifsInstrument *instrument,
4686 double saturation_threhold,
4687 cpl_table** qclog
4688 )
4689{
4690 cpl_frame *frame = NULL;
4691
4692 TRY
4693 {
4694 if (frames == NULL) {
4695 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
4696 "missing frameset");
4697 }
4698 if (cpl_frameset_is_empty(frames)) {
4699 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
4700 "SOF file is empty or missing");
4701 }
4702 CHECK_ERROR_STATE();
4703
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);
4713
4714 arcFrames_off = eris_ifu_get_frameset_by_tag(frames, ERIS_IFU_RAW_WAVE_NS_OFF);
4715
4716 cpl_frameset_join(arcFrames, arcFrames_off);
4717
4718 cpl_frameset_delete(arcFrames_off);
4719 }
4720 BRK_IF_ERROR(
4721 eris_ifu_wave_get_arc_images(arcFrames,
4722 exposureCorrectionMode,
4723 arcImgCnt,
4724 arcImages,
4725 lampStates,
4726 band,
4727 scale,
4728 instrument,
4729 saturation_threhold,
4730 qclog));
4731 cpl_frameset_delete(arcFrames);
4732
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);
4740 }
4741 } CATCH
4742 {
4743// CATCH_MSGS();
4744 }
4745
4746 return cpl_error_get_code();
4747}
4748
4767cpl_error_code eris_ifu_distortion_reduce_lines(cpl_table *tbl,
4768 ifsBand band,
4769 int nr_cols)
4770{
4771 cpl_error_code err = CPL_ERROR_NONE;
4772 int cut_level_area = 0,
4773 cut_level_intensity = 0;
4774 const char *bandStr = NULL;
4775
4776 cpl_ensure_code(tbl != NULL, CPL_ERROR_NULL_INPUT);
4777
4778 TRY
4779 {
4781 bandStr = eris_ifu_get_bandString(band));
4782
4783
4784// // cut again lower (at a tenth) for slitlet #16
4785// CHECK_ERROR_STATE();
4786//
4787// CHECK_ERROR_STATE();
4788
4789 // get rid of lines where for a specific wavelength in all columns the fit is bad
4790 cpl_table *tSlit = NULL,
4791 *tCol = NULL,
4792 *tPos = 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);
4796
4797 // get rid of lines where area is smaller than a band- and slitlet specific cut-level
4798 if ('J' == bandStr[0]) {
4799 if (sIdx != 16-1) {
4800 cut_level_area = 1000;
4801 cut_level_intensity = 600;
4802 } else {
4803 cut_level_area = 90; // ??
4804 cut_level_intensity = 30; // ??
4805 }
4806 } else if ('H' == bandStr[0]) {
4807 if (sIdx != 16-1) {
4808 cut_level_area = 300; // ??
4809 cut_level_intensity = 150; // ??
4810 } else {
4811 cut_level_area = 300/10; // ??
4812 cut_level_intensity = 150/10; // ??
4813 }
4814 } else if ('K' == bandStr[0]) {
4815 if (sIdx != 16-1) {
4816 cut_level_area = 200; // ??
4817 cut_level_intensity = 100; // ??
4818 } else {
4819 cut_level_area = 200/10; // ??
4820 cut_level_intensity = 100/10; // ??
4821 }
4822 } else {
4823 SET_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT, "Band must be H, K or J");
4824 }
4825
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);
4830
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);
4835
4836 // now get subtable width slitlet #sIdx
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));
4842
4843 // get subtable of 1st column
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));
4850
4851 // loop through all positions in 1st column and check if a position has been fitted mostly bad or not
4852 // > 50% bad fits --> reject
4853 for (int i = 0; i < cpl_table_get_nrow(tCol); i++) {
4854//cpl_msg_debug(cpl_func, " pos: %d", 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));
4861 int good = 0;
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);
4866 if (code == 0) {
4867 good++;
4868 }
4869 }
4870 }
4871 if (good < cpl_table_get_nrow(tPos)/2) {
4872 // reject position
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);
4878 }
4879
4880 eris_ifu_free_table(&tPos);
4881 }
4882
4883 // check for errors on positions which exist only once, delete them
4884 eris_ifu_free_table(&tSlit);
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));
4890
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));
4896
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);
4906 }
4907 }
4908
4909 eris_ifu_free_table(&tPos);
4910 eris_ifu_free_table(&tSlit);
4911 eris_ifu_free_table(&tCol);
4912 }
4914
4915 // // now get rid of lines which have been bad at least once
4916 // cpl_table_select_all(tbl);
4917 // while (cpl_table_get_column_mean(tbl, ERIS_IFU_FITTABLE_ERRORCODE) < 0.) {
4918 // // there is still some errorcode (line) to eliminate
4919
4920 // // search 1st error
4921 // int ii = 0;
4922 // int n = 0;
4923 // cpl_boolean found = CPL_FALSE;
4924 // while (ii < cpl_table_get_nrow(tbl) && !found) {
4925 // if (cpl_table_is_selected(tbl, ii) &&
4926 // (cpl_table_get_int(tbl, ERIS_IFU_FITTABLE_ERRORCODE, ii, &n) == 0))
4927 // {
4928 // ii++;
4929 // } else {
4930 // found = CPL_TRUE;
4931 // }
4932 // }
4933
4934 // if (found) {
4935 // double wavelength = cpl_table_get_double(tbl, ERIS_IFU_FITTABLE_WAVELENGTH, ii, &n);
4936 // // mark the entries with this wavelength to be eliminated
4937 // cpl_table_and_selected_double(tbl, ERIS_IFU_FITTABLE_WAVELENGTH, CPL_NOT_EQUAL_TO, wavelength);
4938 // }
4939
4940 // cpl_table_not_selected(tbl);
4941 // cpl_table_erase_selected(tbl);
4942 // cpl_table_select_all(tbl);
4943 // }
4944
4945 // we have multiple columns per slitlet. Get rid of all except the center one
4946 for (int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4947 // get subtable width slitlet #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));
4953
4954 // get index of first column
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);
4959
4960 eris_ifu_free_table(&tSlit);
4961 }
4963
4964 // get rid of last errors
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);
4969
4970 // delete unneeded columns
4971// cpl_table_erase_column(tbl, "index");
4972 cpl_table_erase_column(tbl, "imgIdx");
4973// cpl_table_erase_column(tbl, ERIS_IFU_FITTABLE_WAVELENGTH);
4974// cpl_table_erase_column(tbl, ERIS_IFU_FITTABLE_ERRORCODE);
4975// cpl_table_erase_column(tbl, "x0");
4976// cpl_table_erase_column(tbl, "sigma");
4977// cpl_table_erase_column(tbl, "area");
4978// cpl_table_erase_column(tbl, "offset");
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");
4986 }
4987 CATCH
4988 {
4989 CATCH_MSGS();
4990 }
4991 return err;
4992}
4993
5006{
5007 cpl_error_code err = CPL_ERROR_NONE;
5008 cpl_table *tSlit = NULL;
5009
5010 TRY
5011 {
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);
5015
5016 // get subtable of slitlet
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));
5022
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));
5031
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);
5043 }
5045 }
5046
5047 eris_ifu_free_table(&tSlit);
5048 }
5049
5051 }
5052 CATCH
5053 {
5054 CATCH_MSGS();
5055 }
5056 return err;
5057}
5058
5083cpl_table* eris_ifu_dist_wave(cpl_frameset *fs,
5084 cpl_table **centers_fitted,
5085 int productDepth,
5086 cpl_image ***arcImgs,
5087 int *imgCnt,
5088 const cpl_parameterlist* parlist,
5089 cpl_table** qclog)
5090{
5091
5092 int corrMask = LINE_EXPOSURE_CORRECTION | COLUMN_EXPOSURE_CORRECTION,
5093 arcImgCnt = 0,
5094 *lampStates = NULL,
5095// nr_cols = 3,
5096 center = 0;
5097 cpl_size nRows = 0;
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,
5108 *centerss = 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;
5119 TRY
5120 {
5121 // make sure there is no nonsense in the table structure
5122 // in case it is written before filled properly
5124
5125 for (int ix=0; ix<ERIS_IFU_DETECTOR_SIZE_Y; ix++) {
5126 allFits[ix] = NULL;
5127 }
5128
5129 saturation_threshold = cpl_parameter_get_double(
5130 cpl_parameterlist_find_const(parlist, "eris.eris_ifu_distortion.pixel_saturation"));
5131
5132 // preparations
5135 fs,
5136 corrMask,
5137 &arcImgCnt,
5138 &arcImages,
5139 &lampStates,
5140 &band,
5141 &scale,
5142 &instrument,
5143 saturation_threshold,
5144 qclog));
5145
5146 // allocations
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;
5154
5155 // load arc images
5156 for (int i = 0; i < arcImgCnt; i++) {
5158 tmpImg = hdrl_imagelist_get_const(arcImages, i));
5160 dataImg[i] = cpl_image_duplicate(
5162 }
5163 nRows = cpl_image_get_size_y(dataImg[0]);
5164
5165 // load reference lines
5166 refLineTableFileName = cpl_frame_get_filename(
5167 cpl_frameset_find(fs, ERIS_IFU_CALIB_REF_LINES));
5168 for (int ix = 0; ix < arcImgCnt; ix++) {
5170 refLines[ix] = eris_ifu_wave_get_refLines(
5171 refLineTableFileName, instrument,
5172 lampStates[ix]));
5173 }
5174
5175 // prepare centers-vector
5176 // we need a vector of length SLITLET_CNT with one averaged center value
5177 centerss = cpl_vector_new(SLITLET_CNT);
5178 for (int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
5179 // get a sensible center value (mean of the center in this slit)
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);
5186 }
5187
5188 // prepare slitletStart/End-vectors
5189 // width from center add/subtract number of pixels
5190// cpl_vector *vStart = cpl_vector_duplicate(centerss);
5191// cpl_vector_subtract_scalar(vStart, 1.);
5192// cpl_vector *vEnd = cpl_vector_duplicate(centerss);
5193// cpl_vector_add_scalar(vEnd, 1.);
5194// const double *slitletStart = cpl_vector_get_data_const(vStart);
5195// const double *slitletEnd = cpl_vector_get_data_const(vEnd);
5196
5197 //
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);
5201 // collapse along y at center-pos (in x)
5202 collapsedSpectrum = eris_ifu_wave_collapse_slitlet(
5203 dataImg[aIdx], center);
5204
5205 eris_ifu_wave_save_spectrum(collapsedSpectra, aIdx,
5206 collapsedSpectrum, sIdx, nRows,
5207 lampStates[aIdx], band, instrument,
5208 refLines[aIdx], productDepth);
5209
5210 eris_ifu_free_vector(&collapsedSpectrum);
5211 }
5212 }
5213
5214 // load first-fit-file
5215 firstFitTableFileName = cpl_frame_get_filename(
5216 cpl_frameset_find(fs, ERIS_IFU_CALIB_FIRST_FIT));
5217 if (firstFitTableFileName == NULL) {
5218 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
5219 "missing \"ERIS_IFU_CALIB_FIRST_FIT\" tag in the SOF, wavecal first fit table");
5220 }
5222 firstFitTable = eris_ifu_wave_get_firstFitTable(
5223 firstFitTableFileName, instrument, band));
5224
5225 waveSetupFileName = cpl_frame_get_filename(
5226 cpl_frameset_find(fs, ERIS_IFU_CALIB_WAVE_SETUP));
5227 if (waveSetupFileName == NULL) {
5228 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
5229 "missing \"ERIS_IFU_CALIB_WAVE_SETUP\" tag in the SOF, wavecal setup table");
5230 }
5232 eris_ifu_wave_init_tables(&tables));
5234 eris_ifu_read_wave_setup(waveSetupFileName, band, &waveSetup));
5235
5236 const int slitlet2collapsed[SLITLET_CNT] = {
5237 0, 15, 1, 16, 2, 17, 3, 18, 4, 19, 5, 20, 6, 21, 7,
5238 30, 31,
5239 22, 8, 23, 9, 24, 10, 25, 11, 26, 12, 27, 13, 28, 14, 29};
5240
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];
5254 }
5255 }
5256
5257 }
5258
5259 int firstFitOffset;
5260 int firstFitMasterOffset = 0;
5262 firstFit = eris_ifu_get_first_fit(collapsedSpectra,
5263 lampStates, arcImgCnt, 16, 0, &firstFitMasterOffset,
5264 waveSetup, firstFitTable,
5265 tables.slitletFitting, tables.slitletCoeff));
5266 cpl_msg_info(__func__,"FirstFit Master Offset %d", firstFitMasterOffset);
5267 eris_ifu_free_polynomial(&firstFit);
5268 for (int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
5270 firstFit = eris_ifu_get_first_fit(collapsedSpectra,
5271 lampStates, arcImgCnt, sIdx, firstFitMasterOffset, &firstFitOffset,
5272 waveSetup, firstFitTable,
5273 tables.slitletFitting, tables.slitletCoeff));
5274
5275// eris_ifu_fit_all_lines(REC_NAME_DISTORTION, sIdx, slitletStart, slitletEnd,
5276// arcImgCnt, dataImg, refLines,
5277// waveSetup, firstFit, allFits,
5278// tables.columnFitting, tables.columnCoeffRaw,
5279// tables.columnCoeffSmoothed, tables.smoothingCoeff);
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,};
5284 eris_ifu_fit_all_lines(REC_NAME_DISTORTION, sIdx, column, column,
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));
5295 }
5296 }
5297
5298 eris_ifu_free_polynomial(&firstFit);
5299 }
5300 if (productDepth > 3 ) {
5302 eris_ifu_wave_save_fitting_tables(&tables, instrument, band,
5303 waveSetup, fs, parlist,
5304 "eris_ifu_distortion"));
5305 }
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));
5309
5310 // add intensity of lines
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);
5317
5318 double inten = area / sqrt(2.*(double)CX_PI*pow(sigma,2)) + offset;
5319 if ((inten - offset) > 20. && sigma < 2.) {
5320// if ((inten - offset) > 20.) {
5321 cpl_table_set_double(tables.columnFitting, "intensity", i, inten);
5322 } else {
5323 //printf("Deleted due less intensity: %7.1f %f\n", offset, inten);
5324 cpl_table_or_selected_window(tables.columnFitting, i, 1);
5325 }
5327 }
5328 BRK_IF_ERROR(cpl_table_erase_selected(tables.columnFitting));
5329
5330//erw BRK_IF_ERROR(
5331// eris_ifu_distortion_reduce_lines(tables.columnFitting, band, nr_cols));
5332
5333 // sort positions
5335 pl = cpl_propertylist_new());
5337 cpl_propertylist_append_bool(pl, "position", CPL_TRUE));
5339 cpl_table_sort(tables.columnFitting, pl));
5340
5341//erw BRK_IF_ERROR(
5342// eris_ifu_distortion_reduce_identical_lines(tables.columnFitting));
5343
5344 if ((productDepth & 3) != 0) {
5345 int c = 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);
5350 if (sIdx == 0) {
5351 c = CPL_IO_CREATE;
5352 } else {
5353 c = CPL_IO_EXTEND;
5354 }
5356 cpl_table_save(t, NULL, NULL, "eris_ifu_distortion_dbg_wave_fit_lines.fits", c));
5358 }
5359 }
5360 }
5361 CATCH
5362 {
5363// eris_ifu_free_table(&tbl);
5364 }
5365 cpl_free(lampStates);
5366 eris_ifu_free_vector(&centerss);
5368 eris_ifu_free_hdrl_imagelist(&arcImages);
5369 for (int ix=0; ix<arcImgCnt; ix++) {
5370 eris_ifu_free_bivector(&refLines[ix]);
5371 eris_ifu_free_image(&collapsedSpectra[ix]);
5372 eris_ifu_free_image(&collapsedImgDetOrder[ix]);
5373 }
5374 cpl_free(refLines);
5375 cpl_free(collapsedSpectra);
5376 cpl_free(collapsedImgDetOrder);
5377 for (int ix=0; ix<ERIS_IFU_DETECTOR_SIZE_Y; ix++) {
5378 eris_ifu_free_polynomial(&allFits[ix]);
5379 }
5380 eris_ifu_free_table(&firstFitTable);
5381 eris_ifu_free_table(&tables.slitletFitting);
5382 eris_ifu_free_table(&tables.slitletCoeff);
5383 eris_ifu_free_table(&tables.columnCoeffRaw);
5384 eris_ifu_free_table(&tables.columnCoeffSmoothed);
5385 eris_ifu_free_table(&tables.smoothingCoeff);
5386 *arcImgs = dataImg;
5387 return tables.columnFitting;
5388}
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
Definition: hdrl_image.c:118
const hdrl_image * hdrl_imagelist_get_const(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.