ERIS Pipeline Reference Manual 1.8.10
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
21#include <string.h>
22#include "eris_ifu_distortion_static.h"
23#include "eris_ifu_wavecal_static.h"
24#include "eris_ifu_dfs.h"
25#include "eris_ifu_error.h"
26#include "eris_ifu_utils.h"
27#include "eris_ifu_debug.h"
28#include "eris_utils.h"
38cpl_vector* eris_ifu_dist_calc_centers_profile(const cpl_vector* profile,
39 cpl_boolean lowerCutLevel)
40{
41 int cnt = 0,
42 est_cnt = 0;
43 cpl_size nx;
44 double mean = 0.,
45 cut_level = 0.,
46 cut_factor = 1.4,
47 left = 0.,
48 right = 0.,
49 width = 0.,
50 *ppos = NULL,
51 *pheight = NULL;
52 const double *pprofile = NULL;
53 cpl_vector *pos = NULL,
54 *height = NULL,
55 *cen_estimates = NULL;
56
57 cpl_ensure(profile != NULL, CPL_ERROR_NULL_INPUT, NULL);
58
59 TRY
60 {
61 nx = cpl_vector_get_size(profile);
62
63 if (lowerCutLevel) {
64 cut_factor = 1.0;
65 }
66 /* determine the mean of the row data, multiply scalar to get a
67 * level around half-max just to be sure to omit low-level outliers */
68 eris_ifu_vector *collapsed_vec2 = eris_ifu_vector_create(profile);
69 mean = eris_ifu_vector_get_mean(collapsed_vec2);
70 cut_level = cut_factor * mean;
71
72 //cut_level = 2 * eris_ifu_vector_get_mean(collapsed_vec2) * 0.8;
73 eris_ifu_free_ifu_vector(&collapsed_vec2);
74
75 /* search for left/right edge of slitlet,
76 * subtract to get center and store
77 * (ignoring bad-pix-border on left and right side of detector)
78 * (max. size would be 3*SLITLET_CNT, but allow for more to prevent seg. fault)
79 */
81 pos = cpl_vector_new(3*SLITLET_CNT+20));
83 height = cpl_vector_new(3*SLITLET_CNT+20));
84 BRK_IF_ERROR(cpl_vector_multiply_scalar(height, 0.0));
86 ppos = cpl_vector_get_data(pos));
88 pheight = cpl_vector_get_data(height));
89
91 pprofile = cpl_vector_get_data_const(profile));
92
93 for (cut_factor = 1.4; cut_factor > .1; cut_factor -= 0.2) {
94 cut_level = cut_factor * mean;
95 cnt = 0;
96
97 for (int i = ERIS_IFU_DETECTOR_BP_BORDER;
98 i < nx-ERIS_IFU_DETECTOR_BP_BORDER;
99 i++)
100 {
101 /* find left edge */
102 if ((left == 0) && (pprofile[i] > cut_level)) {
103 left = i;
104 }
105 /* find right edge */
106 if (((left != 0) && (right == 0)) &&
107 ((pprofile[i] < cut_level) || (i == nx-ERIS_IFU_DETECTOR_BP_BORDER-1))) {
108 right = i-1;
109 }
110 /* found left/right-edge, calc center, reset & continue */
111 if ((left != 0) && (right != 0)) {
112 width = right-left+1;
113 ppos[cnt] = (double)left + width/2.0;
114 pheight[cnt] = pprofile[(int) (ppos[cnt]+.5) ];
115 cnt++;
116 left = 0;
117 right = 0;
118 }
119 if (cnt >= cpl_vector_get_size(pos)) {
120 break;
121 }
122 }
123 if (cnt == SLITLET_CNT || cnt == 3 * SLITLET_CNT) {
124 est_cnt = cnt;
125 break;
126 }
127 if (cnt > SLITLET_CNT && cnt < SLITLET_CNT + 20) {
128 est_cnt = SLITLET_CNT;
129 break;
130 }
131 if (cnt > 3 * SLITLET_CNT) {
132 est_cnt = 3 * SLITLET_CNT;
133 break;
134 }
135 }
136
137 // if there are too many peaks, sort the arrays to remove the lowest peaks
138 if (cnt > est_cnt) {
139 cpl_bivector *toBeSorted = NULL;
140 BRK_IF_NULL(toBeSorted = cpl_bivector_wrap_vectors(pos, height));
141 BRK_IF_ERROR(cpl_bivector_sort(toBeSorted, toBeSorted,
142 CPL_SORT_DESCENDING, CPL_SORT_BY_Y));
143 cpl_bivector_unwrap_vectors(toBeSorted);
144 cnt = est_cnt;
145 }
146
147 /* now we know the number of detected traces, extract the significant
148 * part of the vector to return */
150 cen_estimates = cpl_vector_extract(pos, 0, cnt-1, 1));
151 //
152 BRK_IF_ERROR(cpl_vector_sort(cen_estimates, CPL_SORT_ASCENDING));
153
154// cpl_msg_debug(cpl_func," est. profile: cutlevel: %g, #peaks: %d", cut_level, (int)cpl_vector_get_size(cen_estimates));
155 }
156 CATCH
157 {
158 CATCH_MSGS();
159 eris_ifu_free_vector(&cen_estimates);
160 }
161
163 eris_ifu_free_vector(&height);
164
165 return cen_estimates;
166}
167
173cpl_vector* eris_ifu_dist_estimate_low_slitlet(const cpl_vector *est_centers)
174{
175 cpl_vector *est_new = NULL,
176 *est_new2 = NULL;
177 double *pest_new = NULL;
178 const double *pest_centers = NULL;
179 cpl_size cnt = 0,
180 ind = 0;
181
182 cpl_ensure(est_centers, CPL_ERROR_NULL_INPUT, NULL);
183
184 TRY
185 {
187 pest_centers = cpl_vector_get_data_const(est_centers));
188
189 cnt = cpl_vector_get_size(est_centers);
190 if ((cnt == SLITLET_CNT) || (cnt == 3*SLITLET_CNT)) {
191 // all slitlet seem to be detected correctly
193 est_new = cpl_vector_duplicate(est_centers));
194 return est_new;
195 } else if (cnt < SLITLET_CNT) {
196 // 25mas: slitlet missing
198 est_new = cpl_vector_new(SLITLET_CNT));
199 cpl_vector_fill(est_new, 0.);
200 } else if ((cnt > SLITLET_CNT+10) && (cnt < 3*SLITLET_CNT)) {
201 // 100mas/250mas: slitlet missing
203 est_new = cpl_vector_new(3*SLITLET_CNT));
204 cpl_vector_fill(est_new, 0.);
205 } else {
206 // more than 3*32 slitlets or 33-43 slitlets
207 // there are too many slitlets, handle elsewhere
209 est_new = cpl_vector_duplicate(est_centers));
210 return est_new;
211 }
213 cpl_vector_multiply_scalar(est_new, 0.));
215 pest_new = cpl_vector_get_data(est_new));
216
217 if (cnt < SLITLET_CNT) {
218 // 25mas
219 ind = 11;
220
221 // locate position of missing slitlet (not always on pos. 15 because a slitlet could be cut off on left of right of detector)
222 // because of this look up to 3 slitlets to left and right
223 while ((fabs(pest_centers[ind+1]-pest_centers[ind]-2*SLITLET_WIDTH) > 10) && (ind < 18)) {
224 ind++;
225
226 }
227
228 for (int i = 0; i < ind+1; i++) {
229 pest_new[i] = pest_centers[i];
230 }
231 // add in missing value
232 pest_new[15] = (pest_centers[ind+1] - pest_centers[ind])/2 + pest_centers[ind];
233 for (cpl_size i = ind+1; i < SLITLET_CNT; i++) {
234 pest_new[i+1] = pest_centers[i];
235 }
236 } else {
237 // 100mas or 250mas
238 // start checking from slitlet #5 on until #18 (#14 and #16 are bad)
239 int start_slit = 5,
240 end_slit = 18;
241 ind = 3*start_slit;
242 cpl_size i = 0;
243 // just copy, don't check
244 for (i = 0; i < ind+1; i++) {
245 pest_new[i] = pest_centers[i];
246 }
247
248 // check distances, if correct: copy, if not: estimate & copy
249 ind = 3*start_slit + 1;
250 i = ind;
251 cpl_boolean found = CPL_FALSE;
252 int decr_found = 0,
253 est_trace_distance = 20;
254 while (ind < 3*end_slit) {
255 double val = fabs(pest_centers[ind]-pest_centers[ind-3]-SLITLET_WIDTH);
256 if (found && (decr_found > 0)) {
257 val -= est_trace_distance;
258 decr_found--;
259 }
260 if (val < 5) {
261 // position is correct
262 pest_new[i++] = pest_centers[ind++];
263 } else {
264 // position is missing
265 pest_new[i] = pest_centers[ind-3]+SLITLET_WIDTH;
266 i++;
267 pest_new[i] = pest_centers[ind++];
268 i++;
269 found = CPL_TRUE;
270 decr_found = 2;
271 }
272 }
273
274 // just copy, don't check
275 for (; i < 3*SLITLET_CNT; i++) {
276 if (ind < cnt) {
277 pest_new[i] = pest_centers[ind++];
278 }
279 }
280 }
281
282 // check if there are trailing zeros.
283 // If yes cut them. This is indicating that the profile is cut off at the left or right border
284 cnt = cpl_vector_get_size(est_new);
285 ind = cnt-1;
286 while (pest_new[ind] < 0.0001 && ind > 0) {
287 ind--;
288 }
289 if (ind != cnt-1) {
291 est_new2 = cpl_vector_extract(est_new, 0, ind, 1));
292 eris_ifu_free_vector(&est_new);
293 est_new = est_new2;
294 }
295 }
296 CATCH
297 {
298 CATCH_MSGS();
299 eris_ifu_free_vector(&est_new);
300 }
301
302 return est_new;
303}
304
322cpl_vector* eris_ifu_dist_calc_centers_fit(const cpl_vector *profile,
323 const cpl_vector *est_centers,
324 cpl_boolean do_fix_cnt)
325{
326 int cnt = 0,
327 cnt2 = 0,
328 cen = 0,
329 start = 0,
330 end = 0,
331 j = 0;
332 double med = 0.,
333 std = 0.,
334 thresh1 = 1.5,
335 thresh2 = 2.5,
336 lastValidOffset = 0.,
337 *pfit_centers = NULL,
338 *pfit_peaks = NULL;
339 cpl_vector *fit_centers = NULL,
340 *fit_peaks = NULL,
341 *est_centers2 = NULL;
342 cpl_boolean fix_cnt = FALSE;
343 struct gaussParStruct gaussPar;
344 eris_ifu_vector *v = NULL,
345 *ve = NULL;
346
347 cpl_ensure(profile, CPL_ERROR_NULL_INPUT, NULL);
348 cpl_ensure(cpl_vector_get_size(profile) == ERIS_IFU_DETECTOR_SIZE,
349 CPL_ERROR_ILLEGAL_INPUT, NULL);
350 cpl_ensure(est_centers, CPL_ERROR_NULL_INPUT, NULL);
351
352 TRY
353 {
355 est_centers2 = eris_ifu_dist_estimate_low_slitlet(est_centers));
356
357 cnt = (int) cpl_vector_get_size(est_centers2);
358
359 if (do_fix_cnt) {
360 // check if less than 32 traces
361 if (cnt < SLITLET_CNT) {
362 cpl_msg_error(cpl_func, "Detected %d traces instead of at least %d!",
363 cnt2, SLITLET_CNT);
364 SET_ERROR(CPL_ERROR_ILLEGAL_INPUT);
365 }
366
367 // check if less than 96 traces (and more than 32 of course)
368 if ((cnt > 2*SLITLET_CNT) && (cnt < 3*SLITLET_CNT)) {
369 cpl_msg_error(cpl_func, "Detected %d traces instead of at least %d!",
370 cnt2, 3*SLITLET_CNT);
371 SET_ERROR(CPL_ERROR_ILLEGAL_INPUT);
372 }
373 }
374
375 // we have more than 32 or 96 traces, has to fixed!
376 if (do_fix_cnt && (cnt != SLITLET_CNT) && (cnt != 3*SLITLET_CNT)) {
377 fix_cnt = CPL_TRUE;
378 }
379
380 // fit gaussians to all estimated centers in order to get position and
381 // amplitude. If needed we fix the number of detected traces using
382 // statistics on the amplitude
384 fit_centers = cpl_vector_new(cnt));
386 pfit_centers = cpl_vector_get_data(fit_centers));
387 if (fix_cnt) {
389 fit_peaks = cpl_vector_new(cnt));
391 pfit_peaks = cpl_vector_get_data(fit_peaks));
392 }
393
394 for (int i = 0; i < cnt; i++) {
395 cen = (int) (cpl_vector_get(est_centers2, i) + 0.5);
397 eris_ifu_line_gauss_fit(profile, cen,
398 NS_EST_SLIT_DIST/3, &gaussPar));
399
400 if (gaussPar.errorCode == 0) {
401 pfit_centers[i] = gaussPar.x0;
402 lastValidOffset =
403 pfit_centers[i] - cpl_vector_get(est_centers2, i);
404 } else if (i != 0) {
405 pfit_centers[i] = cpl_vector_get(est_centers2, i) +
406 lastValidOffset;
407 }
408 if (fix_cnt) {
409 pfit_peaks[i] = gaussPar.area
410 / sqrt(2*CPL_MATH_PI*pow(gaussPar.sigma,2))
411 + gaussPar.offset;
412 }
413 }
414
415 if (fix_cnt) {
417 v = eris_ifu_vector_create(fit_peaks));
418
419 // check if there are any outliers on the left side of detector
420 // (especially some wrong edge on the very left border,
421 // therefore check the leftmost slitlets)
422 start = 0;
423 end = cnt/10*2;
425 ve = eris_ifu_vector_extract(v, start, end));
426 med = eris_ifu_vector_get_median(ve, ERIS_IFU_ARITHMETIC);
428 if (std > 0.1) {
429 // reject only if stddev is significant
430 j = 0;
431 for (int i = start; i <= end; i++) {
432 double val = eris_ifu_vector_get(ve, j++);
433 if ((val < med-thresh1*std) || (val > med+thresh1*std)) {
435 }
436 }
437 }
439
440 // check if there are any outliers on the right side of detector
441 start = cnt-1-cnt/10*2;
442 end = cnt-1;
444 ve = eris_ifu_vector_extract(v, start, end));
445 med = eris_ifu_vector_get_median(ve, ERIS_IFU_ARITHMETIC);
447 if (std > 0.1) {
448 // reject only if stddev is significant
449 j = 0;
450 for (int i = start; i <= end; i++) {
451 double val = eris_ifu_vector_get(ve, j++);
452 if ((val < med-thresh1*std) || (val > med+thresh1*std)) {
454 }
455 }
456 }
458
459 // still too many slitlets ?
461 if ((cnt2 != SLITLET_CNT) && (cnt2 != 3*SLITLET_CNT)) {
462 // now do a median across whole array and reject
463 med = eris_ifu_vector_get_median(v, ERIS_IFU_ARITHMETIC);
465 for (int i = 0; i <= end; i++) {
466 if (!eris_ifu_vector_is_rejected(v, i)) {
467 double val = eris_ifu_vector_get(v, i);
468 if ((val < med-thresh2*std) || (val > med+thresh2*std)) {
470 }
471 }
472 }
473 }
474
475 // last check
477 if ((cnt2 != SLITLET_CNT) && (cnt2 != 3*SLITLET_CNT)) {
478 int cnt3 = 0;
479 if (abs(SLITLET_CNT-cnt2) < 10) {
480 cnt3 = SLITLET_CNT;
481 }
482 if (abs(3*SLITLET_CNT-cnt2) < 10) {
483 cnt3 = 3*SLITLET_CNT;
484 }
485
486 cpl_msg_error(cpl_func, "Detected %d traces instead of %d!", cnt2, cnt3);
487 SET_ERROR(CPL_ERROR_ILLEGAL_OUTPUT);
488 } else {
489 // we have now 32 or 3*32 traces!
490 cpl_vector *fit_centers2 = NULL;
491 double *pfit_centers2 = NULL;
493 fit_centers2 = cpl_vector_new(cnt2));
495 pfit_centers2 = cpl_vector_get_data(fit_centers2));
496 j = 0;
497 for (int i = 0; i < cnt; i++) {
498 if (!eris_ifu_vector_is_rejected(v, i)) {
499 pfit_centers2[j++] = pfit_centers[i];
500 }
501 }
502 cpl_vector_delete(fit_centers);
503 fit_centers = fit_centers2;
504 }
505 } // end: fix_cnt
506 }
507 CATCH
508 {
509 CATCH_MSGS();
510 eris_ifu_free_vector(&fit_centers);
511 }
512
513 eris_ifu_free_vector(&est_centers2);
516 eris_ifu_free_vector(&fit_peaks);
517
518 return fit_centers;
519}
520
525cpl_error_code eris_ifu_dist_calc_centers_copy(const cpl_vector *fit_centers,
526 int y_index,
527 double y_value,
528 cpl_table **cen_array)
529{
530 int actual_size = 0,
531 index_to_compare = 0,
532 tmp = 0;
533 double last_val = 0.,
534 actual_val = 0.;
535 cpl_error_code err = CPL_ERROR_NONE;
536 const double *pfit_centers = NULL;
537
538 cpl_ensure_code(fit_centers, CPL_ERROR_NULL_INPUT);
539 cpl_ensure_code(cen_array, CPL_ERROR_NULL_INPUT);
540
541 TRY
542 {
543 actual_size = (int) cpl_vector_get_size(fit_centers);
545 pfit_centers = cpl_vector_get_data_const(fit_centers));
546
547 if (actual_size == SLITLET_CNT) {
548 for (int i = 0; i < SLITLET_CNT; i++) {
550 cpl_table_set_double(cen_array[i], "y", y_index, y_value));
552 cpl_table_set_double(cen_array[i], "x", y_index, pfit_centers[i]));
553 }
554 } else if (actual_size == 3*SLITLET_CNT) {
555 for (int i = 0; i < SLITLET_CNT; i++) {
557 cpl_table_set_double(cen_array[i], "y", y_index, y_value));
558
559 // process 1st line
561 cpl_table_set_double(cen_array[i], "x_l", y_index, pfit_centers[3*i]));
562
563 // process 2nd line
565 cpl_table_set_double(cen_array[i], "x", y_index, pfit_centers[3*i+1]));
566
567 // process 3rd line
569 cpl_table_set_double(cen_array[i], "x_r", y_index, pfit_centers[3*i+2]));
570 }
571 } else {
572 cpl_boolean special_handling = CPL_FALSE;
573
574 if (y_index < cpl_table_get_nrow(cen_array[0])/2) {
575 // lower detector part: compare more to the middle
576 index_to_compare = y_index+1;
577 } else {
578 // higher detector part: compare more to the middle
579 index_to_compare = y_index-1;
580 }
581
582 if (!special_handling && (actual_size < 3*SLITLET_CNT)) {
583 // check if left edge is cut off from image
584 last_val = cpl_table_get_double(cen_array[0], "x_l", index_to_compare, &tmp);
585 actual_val = pfit_centers[0];
586 if (!special_handling && (fabs(last_val-actual_val) < 5.)) {
587 // left edge is here!
588 // fill from left to right until end of vector with actual_vals is reached
589 // (it is supposed that max 1-2 traces are missing)
590 tmp = 0;
591 for (int i = 0; i < SLITLET_CNT; i++) {
593 cpl_table_set_double(cen_array[i], "y", y_index, y_value));
594
595 // process 1st line
597 cpl_table_set_double(cen_array[i], "x_l", y_index, pfit_centers[3*i]));
598 if (++tmp == actual_size) break;
599
600 // process 2nd line
602 cpl_table_set_double(cen_array[i], "x", y_index, pfit_centers[3*i+1]));
603 if (++tmp == actual_size) break;
604
605 // process 3rd line
607 cpl_table_set_double(cen_array[i], "x_r", y_index, pfit_centers[3*i+2]));
608 if (++tmp == actual_size) break;
609 }
610 special_handling = CPL_TRUE;
611 }
612
613 // check if right edge is cut off from image
614 last_val = cpl_table_get_double(cen_array[SLITLET_CNT-1], "x_r", index_to_compare, &tmp);
615 actual_val = pfit_centers[actual_size-1];
616 if (!special_handling && (fabs(last_val-actual_val) < 5.)) {
617 // right edge is here!
618 // fill from rihgt to left until end of vector with actual_vals is reached
619 // (it is supposed that max 1-2 traces are missing)
620 tmp = actual_size;
621 for (int i = SLITLET_CNT-1; i >= 0; i--) {
623 cpl_table_set_double(cen_array[i], "y", y_index, y_value));
624
625 // process 3rd line
627 cpl_table_set_double(cen_array[i], "x_r", y_index, pfit_centers[tmp-1]));
628 if (--tmp == actual_size) break;
629
630 // process 2nd line
632 cpl_table_set_double(cen_array[i], "x", y_index, pfit_centers[tmp-1]));
633 if (--tmp == actual_size) break;
634
635 // process 1st line
637 cpl_table_set_double(cen_array[i], "x_l", y_index, pfit_centers[tmp-1]));
638 if (--tmp == actual_size) break;
639 }
640 special_handling = CPL_TRUE;
641 }
642 } // if (actual_size < 3*SLITLET_CNT)
643
644 if (!special_handling && (actual_size < SLITLET_CNT)) {
645 // check if left edge is cut off from image
646 last_val = cpl_table_get_double(cen_array[0], "x", index_to_compare, &tmp);
647 actual_val = pfit_centers[0];
648 if (!special_handling && (fabs(last_val-actual_val) < 5.)) {
649 // left edge is here!
650 // fill from left to right until end of vector with actual_vals is reached
651 // (it is supposed that max 1-2 traces are missing)
652 tmp = 0;
653 for (int i = 0; i < SLITLET_CNT; i++) {
655 cpl_table_set_double(cen_array[i], "y", y_index, y_value));
657 cpl_table_set_double(cen_array[i], "x", y_index, pfit_centers[i]));
658 if (++tmp == actual_size) break;
659 }
660 special_handling = CPL_TRUE;
661 }
662
663 // check if right edge is cut off from image
664 last_val = cpl_table_get_double(cen_array[SLITLET_CNT-1], "x", index_to_compare, &tmp);
665 actual_val = pfit_centers[actual_size-1];
666 if (!special_handling && (fabs(last_val-actual_val) < 5.)) {
667 // right edge is here!
668 // fill from right to left until end of vector with actual_vals is reached
669 // (it is supposed that max 1-2 traces are missing)
670 tmp = actual_size;
671 for (int i = SLITLET_CNT-1; i >= 0; i--) {
673 cpl_table_set_double(cen_array[i], "y", y_index, y_value));
675 cpl_table_set_double(cen_array[i], "x", y_index, pfit_centers[tmp-1]));
676 if (--tmp == actual_size) break;
677 }
678 special_handling = CPL_TRUE;
679 }
680 } // if (actual_size < SLITLET_CNT)
681
682 if (!special_handling) {
683 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_OUTPUT,
684 "Handling of trace running out of "
685 "detector image failed!!!");
686 }
687 } // if actual_size = ...
688 }
689 CATCH
690 {
691 CATCH_MSGS();
692 for (int j = 0; j < SLITLET_CNT; j++) {
693 cpl_table_set_double(cen_array[j], "x", y_index, 0.);
694 cpl_table_set_double(cen_array[j], "y", y_index, 0.);
695 }
696
697 err = cpl_error_get_code();
698 }
699
700 return err;
701}
702
703cpl_table** eris_ifu_dist_calc_centers(const hdrl_image* fibre_div,
704 const hdrl_image *fibre_on,
705// cpl_boolean is25mas,
706// cpl_boolean isK,
707 int productDepth)
708{
709 int cnt = 0,
710 nr_values = 21, //odd
711 // ny = 0,
712 center_y = 0,
713 height = 96, // even
714// ix_middle = nr_values / 2 + 1;
715 ix_middle = 9;
716 const cpl_image *img = NULL,
717 *img_div = NULL,
718 *img_on = NULL;
719 cpl_vector *profile_x = NULL,
720 *profile_x_div = NULL,
721 *profile_x_on = NULL,
722 *est_centers = NULL,
723 *est_centers_div = NULL,
724 *est_centers_on = NULL,
725 *fit_centers = NULL,
726 *fit_centers_middle = NULL;
727 cpl_table **cen_array = NULL;
728
729
730 cpl_ensure(fibre_div, CPL_ERROR_NULL_INPUT, NULL);
731 cpl_ensure(fibre_on, CPL_ERROR_NULL_INPUT, NULL);
732 // nr_values should be odd, since we process first the middle value
733 // and the the lower part resp. upper part
734 cpl_ensure(nr_values % 2 == 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
735 cpl_ensure(height % 2 == 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
736
737 TRY
738 {
739
741 img_on = hdrl_image_get_image_const(fibre_on));
743 img_div = hdrl_image_get_image_const(fibre_div));
744
745// ny = (int) cpl_image_get_size_y(img_div);
746
748 cen_array = cpl_calloc(SLITLET_CNT, sizeof(cpl_table*)));
749
750 /* - take horizontal chunk of height 96 in the middle of detector in x
751 * - collapse in y
752 * - get profile
753 * - estimate centers
754 * - allocate arrays accordingly (32 or 3*32 tables)
755 * - fit centers
756 * - store in the middle line of whole array
757 */
758 center_y = ERIS_IFU_DETECTOR_BP_BORDER + ix_middle*height + height/2;
761 img_div, center_y, height));
764 img_on, center_y, height));
765
767 est_centers_div = eris_ifu_dist_calc_centers_profile(profile_x_div, CPL_FALSE));
769 est_centers_on = eris_ifu_dist_calc_centers_profile(profile_x_on, CPL_FALSE));
770
771 // will return a vector with 32 or 3*32 center values (errors are catched)
773 fit_centers_middle = eris_ifu_dist_calc_centers_fit(
774 profile_x_on, est_centers_on, CPL_TRUE));
775
776 if (productDepth & 4) {
777 cpl_propertylist *pl = NULL;
779 pl = cpl_propertylist_new());
780 eris_ifu_save_vector_dbg(NULL, ERIS_IFU_DIST_DBG_FN, CPL_IO_CREATE, pl);
782 cpl_propertylist_update_string(pl, "EXTNAME", "profile_x_div"));
783 eris_ifu_save_vector_dbg(profile_x_div,
784 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
786 cpl_propertylist_update_string(pl, "EXTNAME", "profile_x_on"));
787 eris_ifu_save_vector_dbg(profile_x_on,
788 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
790 cpl_propertylist_update_string(pl, "EXTNAME", "est_centers_div"));
791 eris_ifu_save_vector_dbg(est_centers_div,
792 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
794 cpl_propertylist_update_string(pl, "EXTNAME", "est_centers_on"));
795 eris_ifu_save_vector_dbg(est_centers_on,
796 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND,pl );
798 cpl_propertylist_update_string(pl, "EXTNAME", "fit_centers_middle"));
799 eris_ifu_save_vector_dbg(fit_centers_middle,
800 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND,pl);
802 }
803 eris_ifu_free_vector(&profile_x_div);
804 eris_ifu_free_vector(&profile_x_on);
805 eris_ifu_free_vector(&est_centers_div);
806 eris_ifu_free_vector(&est_centers_on);
807 eris_ifu_free_vector(&fit_centers);
808
809 /* in the 1st iteration we know now the number of fibre traces
810 * (one or three per slitlet)
811 * --> Allocate images to hold all centers*/
812 cnt = (int) cpl_vector_get_size(fit_centers_middle);
813
814 if (cnt == SLITLET_CNT) {
815 // one trace per slitlet
816 for (int j = 0; j < SLITLET_CNT; j++) {
818 cen_array[j] = cpl_table_new(nr_values));
820 cpl_table_new_column(cen_array[j], "x", CPL_TYPE_DOUBLE));
822 cpl_table_new_column(cen_array[j], "y", CPL_TYPE_DOUBLE));
823 for (int i = 0; i < nr_values; i++) {
824 // init to NaN
825 cpl_table_set(cen_array[j], "x", i, NAN);
826 cpl_table_set(cen_array[j], "y", i, NAN);
827 }
828 }
829 } else {
830 // three traces per slitlet
831 for (int j = 0; j < SLITLET_CNT; j++) {
833 cen_array[j] = cpl_table_new(nr_values));
835 cpl_table_new_column(cen_array[j], "x_l", CPL_TYPE_DOUBLE));
837 cpl_table_new_column(cen_array[j], "x", CPL_TYPE_DOUBLE));
839 cpl_table_new_column(cen_array[j], "x_r", CPL_TYPE_DOUBLE));
841 cpl_table_new_column(cen_array[j], "y", CPL_TYPE_DOUBLE));
842 for (int i = 0; i < nr_values; i++) {
843 // init to NaN
844 cpl_table_set(cen_array[j], "x_l", i, NAN);
845 cpl_table_set(cen_array[j], "x", i, NAN);
846 cpl_table_set(cen_array[j], "x_r", i, NAN);
847 cpl_table_set(cen_array[j], "y", i, NAN);
848 }
849 }
850 }
851
852//erw if (isK/*25mas*/) {
853 if (CPL_TRUE) {
854 img = img_on;
855 } else {
856 img = img_div;
857 }
858 // now do the same for the whole detectors in two blocks
859 // center to top and center to bottom
861 BRK_IF_NULL(est_centers = cpl_vector_duplicate(fit_centers_middle));
862 for (int i = ix_middle; i < nr_values; i++) {
863 center_y = ERIS_IFU_DETECTOR_BP_BORDER + i*height + height/2;
864 /* collapse image in y and convert to vector */
867 img, center_y, height));
868 /* do least square fit using a Gaussian in order to get exact centers */
870 fit_centers = eris_ifu_dist_calc_centers_fit(profile_x, est_centers, CPL_FALSE));
871
872 /* copy all values into image-array to hold all values */
874 eris_ifu_dist_calc_centers_copy(fit_centers, i, center_y,
875 cen_array));
876
877 if ((productDepth & 4) != 0) {
878 char *extname = NULL;
879 cpl_propertylist *pl = NULL;
881 pl = cpl_propertylist_new());
882 extname = cpl_sprintf("Sx_%02d profile_x", i+1);
883 cpl_propertylist_update_string(pl, "EXTNAME", extname);
884 eris_ifu_free_string(&extname);
885 eris_ifu_save_vector_dbg(profile_x,
886 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
887 extname = cpl_sprintf("Sx_%02d est_centers", i+1);
888 cpl_propertylist_update_string(pl, "EXTNAME", extname);
889 eris_ifu_free_string(&extname);
890 eris_ifu_save_vector_dbg(est_centers,
891 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
892 extname = cpl_sprintf("Sx_%02d fit_centers", i+1);
893 cpl_propertylist_update_string(pl, "EXTNAME", extname);
894 eris_ifu_free_string(&extname);
895 eris_ifu_save_vector_dbg(fit_centers,
896 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND ,pl);
898 }
899
900 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
901 eris_ifu_free_vector(&profile_x);
902 eris_ifu_free_vector(&fit_centers);
903 } // end: i = nr_values
904
905 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers_middle));
906 for (int i = ix_middle-1; i >= 0; i--) {
907 center_y = ERIS_IFU_DETECTOR_BP_BORDER + i*height + height/2;
908 /* collapse image in y and convert to vector */
911 img, center_y, height));
912 /* do least square fit using a Gaussian in order to get exact centers */
914 fit_centers = eris_ifu_dist_calc_centers_fit(profile_x, est_centers, CPL_FALSE));
915
916 /* copy all values into image-array to hold all values */
918 eris_ifu_dist_calc_centers_copy(fit_centers, i, center_y,
919 cen_array));
920
921 if ((productDepth & 4) != 0) {
922 char *extname = NULL;
923 cpl_propertylist *pl = NULL;
925 pl = cpl_propertylist_new());
926 extname = cpl_sprintf("Sx_%02d profile_x", i+1);
927 cpl_propertylist_update_string(pl, "EXTNAME", extname);
928 eris_ifu_free_string(&extname);
929 eris_ifu_save_vector_dbg(profile_x,
930 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
931 extname = cpl_sprintf("Sx_%02d est_centers", i+1);
932 cpl_propertylist_update_string(pl, "EXTNAME", extname);
933 eris_ifu_free_string(&extname);
934 eris_ifu_save_vector_dbg(est_centers,
935 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
936 extname = cpl_sprintf("Sx_%02d fit_centers", i+1);
937 cpl_propertylist_update_string(pl, "EXTNAME", extname);
938 eris_ifu_free_string(&extname);
939 eris_ifu_save_vector_dbg(fit_centers,
940 ERIS_IFU_DIST_DBG_FN, CPL_IO_EXTEND, pl);
942 }
943
944 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
945 eris_ifu_free_vector(&profile_x);
946 eris_ifu_free_vector(&fit_centers);
947 } // end: i = nr_values
948
949 if (productDepth & 4) {
950 /* save centers */
952 cpl_propertylist_save(NULL, "eris_ifu_distortion_dbg_centers_fitted.fits", CPL_IO_CREATE));
954 cpl_propertylist_save(NULL, "eris_ifu_distortion_dbg_centers_fitted_visual.fits", CPL_IO_CREATE));
955 for (int j = 0; j < SLITLET_CNT; j++) {
956 cpl_table_save(cen_array[j], NULL, NULL, "eris_ifu_distortion_dbg_centers_fitted.fits", CPL_IO_EXTEND);
957 }
958 }
959 }
960 CATCH
961 {
962 CATCH_MSGS();
963 for (int i = 0; i < SLITLET_CNT; i++) {
964 eris_ifu_free_table(&cen_array[i]);
965 }
966 cpl_free(cen_array); cen_array = NULL;
967 }
968
969 eris_ifu_free_vector(&profile_x_div);
970 eris_ifu_free_vector(&profile_x_on);
971 eris_ifu_free_vector(&est_centers_div);
972 eris_ifu_free_vector(&est_centers_on);
973 eris_ifu_free_vector(&est_centers);
974 eris_ifu_free_vector(&fit_centers);
975 eris_ifu_free_vector(&fit_centers_middle);
976
977 return cen_array;
978}
979
980int eris_ifu_distortion_calc_y(int n, int i) {
981 // split ERIS_IFU_DETECTOR_SIZE_Y in n parts
982 // shift every point half down
983 // round to int with adding 0.5 for proper rounding
984 return (int)((double)ERIS_IFU_DETECTOR_SIZE_Y/n*(i+.5)+.5);
985}
986
987int eris_ifu_distortion_target_left_edge(int i) {
988 return i * SLITLET_WIDTH/* + 1*/;
989}
990int eris_ifu_distortion_target_right_edge(int i) {
991 return (i + 1) * SLITLET_WIDTH - 1;
992}
993
994int eris_ifu_distortion_get_narcs(int i,
995 cpl_boolean triple_traces ,
996 cpl_boolean cut_off_left,
997 cpl_boolean cut_off_right)
998{
999 int n_arcs = 0;
1000 // get number of vertical traces (arcs) to process
1001 if (triple_traces) {
1002 n_arcs = 5; // left + right edge + 3x center line
1003 } else {
1004 n_arcs = 3; // left + right edge + 1x center line
1005 }
1006
1007 if (((i == 0) && cut_off_left) ||
1008 ((i == SLITLET_CNT-1) && cut_off_right))
1009 {
1010 // if left or right edge is cut off, omit it
1011 n_arcs--;
1012 }
1013 return n_arcs;
1014}
1015
1016// includes center line
1017cpl_polynomial** eris_ifu_dist_calc_distortion(cpl_table **slit_edges,
1018 cpl_table **centers,
1019 int productDepth,
1020 cpl_boolean cut_off_left,
1021 cpl_boolean cut_off_right,
1022 cpl_table **minmax_borders,
1023 cpl_propertylist ***qc,
1024 cpl_propertylist *pl,
1025 cpl_frameset* frameset,
1026 const cpl_parameterlist* parlist)
1027{
1028 int n_arcs = 0,
1029 n_calib_wave = 0,
1030 n_calib_cen = 0,
1031 n_size = 100,
1032// AA expect results that are more forgiving
1033// fit_order = 3,
1034 fit_order = 2,
1035 arc_cnt = 0,
1036 pos = 0;
1037 double o_l5 = 0.,
1038 o_c5 = 0.,
1039 o_r5 = 0.,
1040 o_l = 0.,
1041 o_c = 0.,
1042 o_r = 0.,
1043 o_c_l = 0.,
1044 o_c_r = 0.,
1045 t_o = 0,
1046 t_l = 0,
1047 t_r = 0,
1048 t_c = 0,
1049 t_c_l = 0,
1050 t_c_r = 0,
1051 m_c = 0,
1052 m_c_l = 0,
1053 m_c_r = 0,
1054// m_t_t = 0,
1055 std = 0.,
1056 median = 0.,
1057 l_min = 0.,
1058 *py = NULL;
1059 const double *pwave_y = NULL,
1060 *pcenter_y = NULL;
1061 cpl_polynomial **poly_u = NULL;
1062 cpl_bivector *grid = NULL;
1063 cpl_vector *val_to_fit = NULL,
1064 *tmp_vec = NULL,
1065 *y = NULL;
1066 eris_ifu_vector *y_wave = NULL,
1067 *y_cen = NULL,
1068 *t = NULL;
1069 cpl_boolean triple_traces = FALSE;
1070 cpl_table *tbl = NULL,
1071 *dbg_polynomials = NULL;
1072 struct arcstruct *arc_tbl = NULL;
1073
1074
1075 cpl_ensure(slit_edges, CPL_ERROR_NULL_INPUT, NULL);
1076 cpl_ensure(centers, CPL_ERROR_NULL_INPUT, NULL);
1077 cpl_ensure(minmax_borders, CPL_ERROR_NULL_INPUT, NULL);
1078
1079 TRY
1080 {
1081 BRK_IF_NULL( dbg_polynomials = cpl_table_new(SLITLET_CNT));
1082 cpl_table_new_column(dbg_polynomials, ERIS_IFU_DIST_DBG_SLITLET, CPL_TYPE_INT);
1083 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_EDGE_LEFT, CPL_TYPE_DOUBLE, fit_order+1);
1084 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_EDGE_RIGHT, CPL_TYPE_DOUBLE, fit_order+1);
1085 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER_LEFT, CPL_TYPE_DOUBLE, fit_order+1);
1086 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER, CPL_TYPE_DOUBLE, fit_order+1);
1087 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER_RIGHT, CPL_TYPE_DOUBLE, fit_order+1);
1089
1091 *minmax_borders = cpl_table_new(SLITLET_CNT));
1093 cpl_table_new_column(*minmax_borders, ERIS_IFU_POLY_EDGE_L, CPL_TYPE_DOUBLE));
1095 cpl_table_new_column(*minmax_borders, ERIS_IFU_POLY_EDGE_R, CPL_TYPE_DOUBLE));
1096
1098 poly_u = cpl_calloc(SLITLET_CNT, sizeof(cpl_polynomial*)));
1099
1100 if (cpl_table_get_ncol(centers[5]) > 2) {
1101 triple_traces = TRUE;
1102 }
1103
1104 if (productDepth & 1) {
1105 cpl_propertylist_append_string(pl, CPL_DFS_PRO_CATG,
1106 "DIST_FIT_TABLE");
1107 cpl_propertylist_save(pl, ERIS_IFU_PRO_DIST_QC_FIT_FN,
1108 CPL_IO_CREATE);
1109 eris_setup_product_header(ERIS_IFU_PRO_DIST_QC_FIT_FN,
1110 "DIST_FIT_TABLE", CPL_FRAME_TYPE_TABLE,
1111 "eris_ifu_distortion", frameset, parlist, pl);
1112 }
1114 arc_tbl = cpl_calloc(SLITLET_CNT, sizeof(struct arcstruct)));
1115
1116 // calculate all slitlets that are not cut off
1117 for (int i = 0; i < SLITLET_CNT; i++) {
1118 //cpl_msg_debug(cpl_func, "i: %d\n", i);
1119 // get number of vertical traces (arcs) to process
1120 n_arcs = eris_ifu_distortion_get_narcs(i, triple_traces,
1121 cut_off_left, cut_off_right);
1122 // get number of detected wave_calib-lines
1123 n_calib_wave = (int) cpl_table_get_nrow(slit_edges[i]);
1124 // get number of centerpoints
1125 n_calib_cen = (int) cpl_table_get_nrow(centers[i]);
1126
1127 // get y-coordinates
1129 pwave_y = cpl_table_get_data_double_const(
1130 slit_edges[i], "y_pos"));
1132 pcenter_y = cpl_table_get_data_double_const(
1133 centers[i], "y"));
1135 y_wave = eris_ifu_vector_new_wrap(n_calib_wave, pwave_y));
1137 y_cen = eris_ifu_vector_new_wrap(n_calib_cen, pcenter_y));
1138
1139 // fit all edges (left, right, centers)
1140 if (!((i == 0) && cut_off_left)) {
1141 // process only if it is not the 1st slitlet and cutoff
1143 arc_tbl[i].fit_l = eris_ifu_dist_calc_distortion_fitedge(
1144 slit_edges[i], "edge_left", y_wave,
1145 n_calib_wave, n_size, fit_order,
1146 i, dbg_polynomials));
1147 }
1148 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1149 // process only if it is not the last slitlet and cutoff
1151 arc_tbl[i].fit_r = eris_ifu_dist_calc_distortion_fitedge(
1152 slit_edges[i], "edge_right", y_wave,
1153 n_calib_wave, n_size, fit_order,
1154 i, dbg_polynomials));
1155 }
1157 arc_tbl[i].fit_c = eris_ifu_dist_calc_distortion_fitedge(
1158 centers[i], "x", y_cen,
1159 n_calib_cen, n_size, fit_order,
1160 i, dbg_polynomials));
1161 if (triple_traces) {
1162 if (!((i == 0) && cut_off_left)) {
1163 // process if it is not the 1st slitlet and not cutoff
1165 arc_tbl[i].fit_c_l = eris_ifu_dist_calc_distortion_fitedge(
1166 centers[i], "x_l", y_cen,
1167 n_calib_cen, n_size, fit_order,
1168 i, dbg_polynomials));
1169 } else {
1170 // if it is the last slitlet and cutoff, then
1171 // check first if, and how many, values are nan
1172 // If there are too many NaN's do nothing and copy the shape of c to c_l
1173 if (cpl_table_count_invalid(centers[i], "x_l") <= 0.1 * n_calib_cen) {
1174 // calculate fitted edge only if less tahn 10% of the values are NaN
1176 arc_tbl[i].fit_c_l = eris_ifu_dist_calc_distortion_fitedge(
1177 centers[i], "x_l", y_cen,
1178 n_calib_cen, n_size, fit_order,
1179 i, dbg_polynomials));
1180 }
1181 }
1182
1183 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1184 // process if it is not the last slitlet and not cutoff
1186 arc_tbl[i].fit_c_r = eris_ifu_dist_calc_distortion_fitedge(
1187 centers[i], "x_r", y_cen,
1188 n_calib_cen, n_size, fit_order,
1189 i, dbg_polynomials));
1190 } else {
1191 // if it is the last slitlet and cutoff, then
1192 // check first if, and how many, values are nan
1193 // If there are too many NaN's do nothing and copy the shape of c to c_r
1194 if (cpl_table_count_invalid(centers[i], "x_r") <= 0.1 * n_calib_cen) {
1195 // calculate fitted edge only if less than 10% of the values are NaN
1197 arc_tbl[i].fit_c_r = eris_ifu_dist_calc_distortion_fitedge(
1198 centers[i], "x_r", y_cen,
1199 n_calib_cen, n_size, fit_order,
1200 i, dbg_polynomials));
1201 }
1202 }
1203 } // end: if (triple_traces)
1204 eris_ifu_free_ifu_vector(&y_wave);
1206 } // end: i = SLITLET_CNT
1207
1208 BRK_IF_ERROR( cpl_table_save(dbg_polynomials, NULL, NULL,
1209 "eris_ifu_distortion_dbg_polynomials.fits", CPL_IO_CREATE));
1210
1212 *qc = cpl_calloc(SLITLET_CNT, sizeof(cpl_propertylist*)));
1213 for (int i = 0; i < SLITLET_CNT; i++) {
1215 (*qc)[i] = cpl_propertylist_new());
1216 }
1217
1218 // estimate positions of cut off edges with neighbouring slitlet width
1219 if (cut_off_left) {
1220 if (arc_tbl[0].fit_l == NULL) {
1221 /* The leftmost edge of slitlet #0 is cut off. Therefore subtract the
1222 * width of slitlet #1 from the right edge of slitlet #0
1223 */
1225 cpl_propertylist_append_string((*qc)[0],
1226 "ESO EDGE L", "artificial"));
1228 arc_tbl[0].fit_l = eris_ifu_vector_duplicate(arc_tbl[0].fit_r));
1230 eris_ifu_vector_subtract(arc_tbl[0].fit_l, arc_tbl[1].fit_r));
1232 eris_ifu_vector_add(arc_tbl[0].fit_l, arc_tbl[1].fit_l));
1233 }
1234 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_l == NULL)) {
1235 /* The c_l-edge of slitlet #0 is cut off. Therefore subtract the
1236 * width of c-c_l of slitlet #31 to the left edge of slitlet #32
1237 */
1239 cpl_propertylist_append_string((*qc)[0],
1240 "ESO EDGE C-L", "artificial"));
1242 arc_tbl[0].fit_c_l = eris_ifu_vector_duplicate(arc_tbl[0].fit_c));
1244 eris_ifu_vector_subtract(arc_tbl[0].fit_c_l, arc_tbl[1].fit_c));
1246 eris_ifu_vector_add(arc_tbl[0].fit_c_l, arc_tbl[1].fit_c_l));
1247 }
1248 cut_off_left = CPL_FALSE;
1249 }
1250
1251 if (cut_off_right) {
1252 if (arc_tbl[SLITLET_CNT-1].fit_r == NULL) {
1253 /* The rightmost edge of slitlet #32 is cut off. Therefore add the
1254 * width of slitlet #31 to the left edge of slitlet #32
1255 */
1257 cpl_propertylist_append_string((*qc)[SLITLET_CNT-1],
1258 "ESO EDGE R", "artificial"));
1260 arc_tbl[SLITLET_CNT-1].fit_r = eris_ifu_vector_duplicate(arc_tbl[SLITLET_CNT-1].fit_l));
1262 eris_ifu_vector_add(arc_tbl[SLITLET_CNT-1].fit_r, arc_tbl[SLITLET_CNT-2].fit_r));
1264 eris_ifu_vector_subtract(arc_tbl[SLITLET_CNT-1].fit_r, arc_tbl[SLITLET_CNT-2].fit_l));
1265 }
1266 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_r == NULL)) {
1267 /* The c_r-edge of slitlet #32 is cut off. Therefore add the
1268 * width of c_r-c of slitlet #31 to the left center edge of slitlet #32
1269 */
1271 cpl_propertylist_append_string((*qc)[0],
1272 "ESO EDGE C-R", "artificial"));
1274 arc_tbl[SLITLET_CNT-1].fit_c_r = eris_ifu_vector_duplicate(arc_tbl[SLITLET_CNT-1].fit_c));
1276 eris_ifu_vector_add(arc_tbl[SLITLET_CNT-1].fit_c_r, arc_tbl[SLITLET_CNT-2].fit_c_r));
1278 eris_ifu_vector_subtract(arc_tbl[SLITLET_CNT-1].fit_c_r, arc_tbl[SLITLET_CNT-2].fit_c));
1279 }
1280 cut_off_right = CPL_FALSE;
1281 }
1282
1283 // take fifth slitlet as master one
1284 int ms = 4;
1285 o_l5 = eris_ifu_vector_get_mean(arc_tbl[ms].fit_l);
1286 o_c5 = eris_ifu_vector_get_mean(arc_tbl[ms].fit_c);
1287 o_r5 = eris_ifu_vector_get_mean(arc_tbl[ms].fit_r);
1288 m_c = 64. * (o_c5 - o_l5) / (o_r5 - o_l5);
1289 if (triple_traces) {
1290 o_c_l = eris_ifu_vector_get_mean(arc_tbl[ms].fit_c_l);
1291 o_c_r = eris_ifu_vector_get_mean(arc_tbl[ms].fit_c_r);
1292 m_c_l = 64. * (o_c_l - o_l5) / (o_r5 - o_l5);
1293 m_c_r = 64. * (o_c_r - o_l5) / (o_r5 - o_l5);
1294// m_t_t = (o_c_r - o_c_l) / (m_c_r - m_c_l);
1295// printf("REF: %6.1f %6.1f %6.1f %6.1f %6.1f width: %.1f r: %.1f %.1f %.1f %.1f\n",
1296// 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);
1297 } else {
1298// printf("REF: %.1f %.1f %.1f width: %.1f r: %.1f\n",
1299// o_l5, o_c5, o_r5, o_r5-o_l5, m_c);
1300 }
1301
1302 if (productDepth >= PD_DEBUG) {
1304 cpl_propertylist_update_string(pl, CPL_DFS_PRO_CATG,
1305 ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID));
1307 cpl_image_save(NULL, ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID_FN,
1308 CPL_TYPE_FLOAT, pl, CPL_IO_CREATE));
1309 }
1310
1311 // estimate mean origin positions of the arc-lines and calculate
1312 // target positions for the edges, fill the grid, perform polynomial-fit
1313 for (int i = 0; i < SLITLET_CNT; i++) {
1314 cpl_msg_debug(cpl_func, "i: %d", i);
1315 // get number of vertical traces (arcs) to process
1316 n_arcs = eris_ifu_distortion_get_narcs(i, triple_traces,
1317 cut_off_left, cut_off_right);
1318
1319 /*
1320 * estimate mean origin positions of the arc-lines (left, center, right)
1321 */
1322 o_l = eris_ifu_vector_get_mean(arc_tbl[i].fit_l);
1323 o_c = eris_ifu_vector_get_mean(arc_tbl[i].fit_c);
1324 o_r = eris_ifu_vector_get_mean(arc_tbl[i].fit_r);
1325
1326// 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);
1327// 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);
1328 if (triple_traces) {
1329 o_c_l = eris_ifu_vector_get_mean(arc_tbl[i].fit_c_l);
1330 o_c_r = eris_ifu_vector_get_mean(arc_tbl[i].fit_c_r);
1331 cpl_msg_debug(cpl_func, " o_l: %g, o_c_l: %g, o_c: %g, o_c_r: %g, o_r: %g", o_l, o_c_l, o_c, o_c_r, o_r);
1332 ASSURE(o_c_l < o_c, CPL_ERROR_ILLEGAL_OUTPUT, "Slitlet #%d: o_c_l >= o_c (o_c_l: %g, o_c: %g)", i+1, o_c_l, o_c);
1333 ASSURE(o_c < o_c_r, CPL_ERROR_ILLEGAL_OUTPUT, "Slitlet #%d: o_c >= o_c_r (o_c: %g, o_c_r: %g)", i+1, o_c, o_c_r);
1334 } else {
1335 cpl_msg_debug(cpl_func, " o_l: %g, o_c: %g, o_r: %g", o_l, o_c, o_r);
1336 }
1337
1338 /*
1339 * from these estimates define target positions for the arc-lines (left, center, right)
1340 */
1341 // left+right edge are simple: a slitlet should have 64pix width
1342 t_o = eris_ifu_distortion_target_left_edge(i);
1343 t_l = eris_ifu_distortion_target_left_edge(i);
1344 t_r = eris_ifu_distortion_target_right_edge(i);
1345 t_l = t_o + m_c - (o_c-o_l) / (o_c5-o_l5) * m_c;
1346// t_l = t_o + m_c_r - (o_c_r - o_l) / m_t_t;
1347 // the center positions are calculated with the sentence of three...
1348 t_c = (int)((o_c-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1349 t_c = t_o + m_c;
1350 if (triple_traces) {
1351 t_c_l = (int)((o_c_l-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1352 t_c_r = (int)((o_c_r-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1353 t_c_l = t_o + m_c_l;
1354 t_c_r = t_o + m_c_r;
1355 cpl_msg_debug(cpl_func, " t_l: %f, t_c_l: %f, t_c: %f, t_c_r: %f, t_r: %f", t_l, t_c_l, t_c, t_c_r, t_r);
1356 } else {
1357 cpl_msg_debug(cpl_func, " t_l: %f, t_c: %f, t_r: %f", t_l, t_c, t_r);
1358 }
1359 if (i == 0) {
1360 t_r -= 2.7;
1361 } else if (i == 1){
1362 t_r -= 1.5;
1363 }
1364 double tx = t_o;
1365// printf(" %2.2d: %6.1f %6.1f %6.1f %6.1f %6.1f width: %.1f t_o: %6.1f t %6.1f %6.1f %6.1f %6.1f %6.1f tg %6.1f %6.1f %6.1f %6.1f %6.1f\n",
1366// i, o_l, o_c_l, o_c, o_r, o_c_r, o_r-o_l, t_o, t_l, t_c_l, t_c, t_c_r, t_r, t_l-tx, t_c_l-tx, t_c-tx, t_c_r-tx, t_r-tx);
1367// cpl_msg_debug(cpl_func, "i: %02d, o_l: %7.2f, o_c_l: %7.2f,"
1368// "o_c: %7.2f, o_c_r: %7.2f, o_r: %7.2f",
1369// i, o_l, o_c_l, o_c, o_c_r, o_r);
1370// cpl_msg_debug(cpl_func, " t_l: %04d , t_c_l: %04d ,"
1371// " t_c: %04d , t_c_r: %04d , t_r: %04d",
1372// t_l, t_c_l, t_c, t_c_r, t_r);
1373 // create grid to fit to (contains target-coordinates)
1374 BRK_IF_NULL(
1375 grid = cpl_bivector_new(n_arcs * n_size));
1376
1377 // create vector with values to fit (contains origin-coordinates)
1378 BRK_IF_NULL(
1379 val_to_fit = cpl_vector_new(n_arcs * n_size));
1380
1381 arc_cnt = 0;
1382 // fill in edges and subtract always in a manner that destination_x(target) is 0 for left edge
1383 // fill in left edge
1384 BRK_IF_ERROR(
1385 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_l, val_to_fit,
1386 t_l-tx, n_size, arc_cnt++));
1387 if (triple_traces) {
1388 // fill in center_l
1389 BRK_IF_ERROR(
1390 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c_l, val_to_fit,
1391 t_c_l-tx, n_size, arc_cnt++));
1392 }
1393 // fill in center
1394//cpl_msg_debug(cpl_func, ">>> %d", i);
1395//if (i==31) {
1396// int a=0;
1397//}
1398 BRK_IF_ERROR(
1399 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c, val_to_fit,
1400 t_c-tx, n_size, arc_cnt++));
1401 if (triple_traces) {
1402 // fill in center_l
1403 BRK_IF_ERROR(
1404 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c_r, val_to_fit,
1405 t_c_r-tx, n_size, arc_cnt++));
1406 }
1407 // fill in right edge
1408 BRK_IF_ERROR(
1409 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_r, val_to_fit,
1410 t_r-tx, n_size, arc_cnt++));
1411
1412 // save l_min and r_max
1413 l_min = floor(eris_ifu_vector_get_min(arc_tbl[i].fit_l, &pos));
1414 BRK_IF_ERROR(
1415 cpl_table_set_double(*minmax_borders, ERIS_IFU_POLY_EDGE_L, i,
1416 l_min));
1417 BRK_IF_ERROR(
1418 cpl_table_set_double(*minmax_borders, ERIS_IFU_POLY_EDGE_R, i,
1419 ceil(eris_ifu_vector_get_max(arc_tbl[i].fit_r, &pos))));
1420
1421 // fill in edges and subtract always in a manner that destination_x(measured) is 0.0 for left edge at beginning
1422 BRK_IF_ERROR(
1423 cpl_vector_subtract_scalar(val_to_fit, l_min));
1424
1425 if (productDepth >= PD_DEBUG) {
1426 char *extName;
1427 extName = cpl_sprintf("GRIDX_%2.2d", i);
1428 BRK_IF_ERROR(
1429 cpl_propertylist_update_string(pl, "EXTNAME", extName));
1430 BRK_IF_ERROR(
1431 cpl_vector_save(cpl_bivector_get_x(grid),
1432 ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID_FN,
1433 CPL_TYPE_FLOAT, pl, CPL_IO_EXTEND));
1434 cpl_free(extName);
1435 extName = cpl_sprintf("GRIDY_%2.2d", i);
1436 BRK_IF_ERROR(
1437 cpl_propertylist_update_string(pl, "EXTNAME", extName));
1438 BRK_IF_ERROR(
1439 cpl_vector_save(cpl_bivector_get_y(grid),
1440 ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID_FN,
1441 CPL_TYPE_FLOAT, pl, CPL_IO_EXTEND));
1442 cpl_free(extName);
1443 extName = cpl_sprintf("VAL2FIT_%2.2d", i);
1444 BRK_IF_ERROR(
1445 cpl_propertylist_update_string(pl, "EXTNAME", extName));
1446 BRK_IF_ERROR(
1447 cpl_vector_save(val_to_fit,
1448 ERIS_IFU_PRO_DIST_DBG_DIST_FIT_GRID_FN,
1449 CPL_TYPE_FLOAT, pl, CPL_IO_EXTEND));
1450 cpl_free(extName);
1451 }
1452//if (i==16) {
1453// int aa=0;
1454//}
1455 /* Perform the fit */
1456 BRK_IF_NULL(
1457 poly_u[i] = eris_ifu_dist_poly_fit_2d_create(grid, val_to_fit, NULL));
1458
1459 eris_ifu_free_bivector(&grid);
1460 eris_ifu_free_vector(&val_to_fit);
1461 } // end: i = SLITLET_CNT
1462
1463 // save values of all fitted edges and some stats
1464 if (productDepth & 1) {
1465 // for the ease of stats: create the y-vector with the used values
1466 BRK_IF_NULL(
1467 y = cpl_vector_new(n_size));
1468 BRK_IF_NULL(
1469 py = cpl_vector_get_data(y));
1470 for (int j = 0; j < n_size; j++) {
1471 py[j] = eris_ifu_distortion_calc_y(n_size, j);
1472 }
1473 char* keyname;
1474 char* keycomm;
1475 for (int i = 0; i < SLITLET_CNT; i++) {
1476
1477 tbl = cpl_table_new(n_size);
1478 if (arc_tbl[i].fit_l != NULL) {
1479
1480 cpl_table_new_column(tbl, "l", CPL_TYPE_DOUBLE);
1481 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_l);
1482 cpl_table_copy_data_double(tbl, "l", cpl_vector_get_data_const(tmp_vec));
1483 eris_ifu_free_vector(&tmp_vec);
1484 }
1485 if (arc_tbl[i].fit_c_l != NULL) {
1486 cpl_table_new_column(tbl, "c_l", CPL_TYPE_DOUBLE);
1487 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_c_l);
1488 cpl_table_copy_data_double(tbl, "c_l", cpl_vector_get_data_const(tmp_vec));
1489 eris_ifu_free_vector(&tmp_vec);
1490 }
1491 if (arc_tbl[i].fit_c != NULL) {
1492 std = eris_ifu_vector_get_stdev(arc_tbl[i].fit_c);
1493 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C STDEV",i);
1494 keycomm = cpl_sprintf("[pix] center slitlet %2.2d",i);
1495 if (!eris_ifu_is_nan_or_inf(std)) {
1496 cpl_propertylist_append_double((*qc)[i], keyname, std);
1497 } else {
1498 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1499 }
1500 cpl_propertylist_set_comment((*qc)[i], keyname,keycomm);
1501 cpl_free(keyname);
1502 cpl_free(keycomm);
1503 cpl_table_new_column(tbl, "c", CPL_TYPE_DOUBLE);
1504 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_c);
1505 cpl_table_copy_data_double(tbl, "c", cpl_vector_get_data_const(tmp_vec));
1506 eris_ifu_free_vector(&tmp_vec);
1507 }
1508 if (arc_tbl[i].fit_c_r != NULL) {
1509 cpl_table_new_column(tbl, "c_r", CPL_TYPE_DOUBLE);
1510 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_c_r);
1511 cpl_table_copy_data_double(tbl, "c_r", cpl_vector_get_data_const(tmp_vec));
1512 eris_ifu_free_vector(&tmp_vec);
1513 }
1514 if (arc_tbl[i].fit_r != NULL) {
1515 cpl_table_new_column(tbl, "r", CPL_TYPE_DOUBLE);
1516 tmp_vec = eris_ifu_vector_get_data(arc_tbl[i].fit_r);
1517 cpl_table_copy_data_double(tbl, "r", cpl_vector_get_data_const(tmp_vec));
1518 eris_ifu_free_vector(&tmp_vec);
1519 }
1520
1521 // calc stddev of differences of distances between single traces
1522 if ((arc_tbl[i].fit_l != NULL) && (arc_tbl[i].fit_r != NULL)) {
1523 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_r);
1524 eris_ifu_vector_subtract(t, arc_tbl[i].fit_l);
1525 std = eris_ifu_vector_get_stdev(t);
1526 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-L STDEV",i);
1527 keycomm = cpl_sprintf("[pix] right-left distance slitlet %2.2d",i);
1528 if (!eris_ifu_is_nan_or_inf(std)) {
1529 cpl_propertylist_append_double((*qc)[i], keyname, std);
1530 } else {
1531 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1532 }
1533 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1534 cpl_free(keyname);
1535 cpl_free(keycomm);
1536
1537 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1538 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-L MEDIAN",i);
1539 keycomm = cpl_sprintf("[pix] right-left distance median slitlet %2.2d",i);
1540 if (!eris_ifu_is_nan_or_inf(median)) {
1541 cpl_propertylist_append_double((*qc)[i], keyname, median);
1542 } else {
1543 cpl_propertylist_append_string((*qc)[i], "MEDIAN R-L", "NaN");
1544 }
1545 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1546 cpl_free(keyname);
1547 cpl_free(keycomm);
1548
1549 // for the ease of stats: save the slit-width & y
1550 cpl_table_new_column(tbl, "slit_width", CPL_TYPE_DOUBLE);
1551 tmp_vec = eris_ifu_vector_get_data(t);
1552 cpl_table_copy_data_double(tbl, "slit_width", cpl_vector_get_data_const(tmp_vec));
1553 cpl_table_new_column(tbl, "y", CPL_TYPE_DOUBLE);
1554 cpl_table_copy_data_double(tbl, "y", cpl_vector_get_data_const(y));
1555 eris_ifu_free_vector(&tmp_vec);
1556 eris_ifu_free_ifu_vector(&t);
1557 }
1558 if ((arc_tbl[i].fit_l != NULL) && (arc_tbl[i].fit_c != NULL)) {
1559 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c);
1560 eris_ifu_vector_subtract(t, arc_tbl[i].fit_l);
1561 std = eris_ifu_vector_get_stdev(t);
1562 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-L STDEV",i);
1563 keycomm = cpl_sprintf("[pix] center-left distance stdev slitlet %2.2d",i);
1564 if (!eris_ifu_is_nan_or_inf(std)) {
1565 cpl_propertylist_append_double((*qc)[i], keyname, std);
1566 } else {
1567 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1568 }
1569 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1570 cpl_free(keyname);
1571 cpl_free(keycomm);
1572 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1573 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-L MEDIAN",i);
1574 keycomm = cpl_sprintf("[pix] center-left distance median slitlet %2.2d",i);
1575 if (!eris_ifu_is_nan_or_inf(median)) {
1576 cpl_propertylist_append_double((*qc)[i], keyname, median);
1577 } else {
1578 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1579 }
1580 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1581 cpl_free(keyname);
1582 cpl_free(keycomm);
1583 eris_ifu_free_ifu_vector(&t);
1584 }
1585 if ((arc_tbl[i].fit_c != NULL) && (arc_tbl[i].fit_r != NULL)) {
1586 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_r);
1587 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c);
1588 std = eris_ifu_vector_get_stdev(t);
1589 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-C STDEV",i);
1590 keycomm = cpl_sprintf("[pix] right-center distance stdev slitlet %2.2d",i);
1591 if (!eris_ifu_is_nan_or_inf(std)) {
1592 cpl_propertylist_append_double((*qc)[i], keyname, std);
1593 } else {
1594 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1595 }
1596 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1597 cpl_free(keyname);
1598 cpl_free(keycomm);
1599 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1600 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-C MEDIAN",i);
1601 keycomm = cpl_sprintf("[pix] right-center distance median slitlet %2.2d",i);
1602 if (!eris_ifu_is_nan_or_inf(median)) {
1603 cpl_propertylist_append_double((*qc)[i], keyname, median);
1604 } else {
1605 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1606 }
1607 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1608 cpl_free(keyname);
1609 cpl_free(keycomm);
1610 eris_ifu_free_ifu_vector(&t);
1611 }
1612 if ((arc_tbl[i].fit_c != NULL) && (arc_tbl[i].fit_c_l != NULL)) {
1613 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c);
1614 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c_l);
1615 std = eris_ifu_vector_get_stdev(t);
1616 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-CL STDEV",i);
1617 keycomm = cpl_sprintf("[pix] center-centerleft distance stdev slitlet %2.2d",i);
1618 if (!eris_ifu_is_nan_or_inf(std)) {
1619 cpl_propertylist_append_double((*qc)[i], keyname, std);
1620 } else {
1621 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1622 }
1623 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1624 cpl_free(keyname);
1625 cpl_free(keycomm);
1626 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1627 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-CL MEDIAN",i);
1628 keycomm = cpl_sprintf("[pix] center-centerleft distance median slitlet %2.2d",i);
1629 if (!eris_ifu_is_nan_or_inf(median)) {
1630 cpl_propertylist_append_double((*qc)[i], keyname, median);
1631 } else {
1632 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1633 }
1634 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1635 cpl_free(keyname);
1636 cpl_free(keycomm);
1637 eris_ifu_free_ifu_vector(&t);
1638 }
1639 if ((arc_tbl[i].fit_c_r != NULL) && (arc_tbl[i].fit_c != NULL)) {
1640 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c_r);
1641 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c);
1642 std = eris_ifu_vector_get_stdev(t);
1643 keyname = cpl_sprintf("ESO QC SLITLET%2.2d CR-C STDEV",i);
1644 keycomm = cpl_sprintf("[pix] centerright-center distance stdev slitlet %2.2d",i);
1645 if (!eris_ifu_is_nan_or_inf(std)) {
1646 cpl_propertylist_append_double((*qc)[i], keyname, std);
1647 } else {
1648 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1649 }
1650 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1651 cpl_free(keyname);
1652 cpl_free(keycomm);
1653 median = eris_ifu_vector_get_median(t, ERIS_IFU_ARITHMETIC);
1654 keyname = cpl_sprintf("ESO QC SLITLET%2.2d CR-C MEDIAN",i);
1655 keycomm = cpl_sprintf("[pix] centerright-center distance median slitlet %2.2d",i);
1656 if (!eris_ifu_is_nan_or_inf(median)) {
1657 cpl_propertylist_append_double((*qc)[i], keyname, median);
1658 } else {
1659 cpl_propertylist_append_string((*qc)[i], keyname, "NaN");
1660 }
1661 cpl_propertylist_set_comment((*qc)[i], keyname, keycomm);
1662 cpl_free(keyname);
1663 cpl_free(keycomm);
1664 eris_ifu_free_ifu_vector(&t);
1665 }
1666 BRK_IF_ERROR(
1667 cpl_table_save(tbl, NULL, (*qc)[i], ERIS_IFU_PRO_DIST_QC_FIT_FN, CPL_IO_EXTEND));
1668
1669 eris_ifu_free_table(&tbl);
1670 } // end: i = SLITLET_CNT
1671 } // end: if (productDepth & 1)
1672 }
1673 CATCH
1674 {
1675 CATCH_MSGS();
1676 for (int j = 0; j < SLITLET_CNT; j++) {
1677 cpl_polynomial_delete(poly_u[j]); poly_u[j] = NULL;
1678 }
1679 cpl_free(poly_u); poly_u = NULL;
1680
1681 eris_ifu_free_table(minmax_borders);
1682
1683 if (*qc != NULL && **qc != NULL) {
1684 for (int i = 0; i < SLITLET_CNT; i++) {
1685 eris_ifu_free_propertylist(&(*qc)[i]);
1686 }
1687 }
1688 if (*qc != NULL) {
1689 cpl_free(**qc); **qc = NULL;
1690 }
1691 }
1692 eris_ifu_free_table(&dbg_polynomials);
1693 eris_ifu_free_bivector(&grid);
1694 eris_ifu_free_vector(&val_to_fit);
1695 eris_ifu_free_vector(&y);
1696 eris_ifu_free_ifu_vector(&y_wave);
1697 for (int i = 0; i < SLITLET_CNT; i++) {
1698 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_l);
1699 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c);
1700 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c_l);
1701 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c_r);
1702 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_r);
1703 }
1704 cpl_free(arc_tbl); arc_tbl = NULL;
1705 eris_check_error_code("eris_ifu_dist_calc_distortion");
1706 return poly_u;
1707}
1708
1709// includes center line
1710cpl_polynomial** eris_ifu_dist_calc_distortion_full(cpl_table **slit_edges,
1711 cpl_table **centers,
1712 int productDepth,
1713 cpl_boolean cut_off_left,
1714 cpl_boolean cut_off_right)
1715{
1716 int n_arcs = 0,
1717 n_calib_wave = 0,
1718 n_calib_cen = 0,
1719 n_size = 100,
1720 fit_order = 3,
1721 t_l = 0,
1722 t_r = 0,
1723 t_c = 0,
1724 t_c_l = 0,
1725 t_c_r = 0,
1726 arc_cnt = 0;
1727 double o_l = 0.,
1728 o_c = 0.,
1729 o_r = 0.,
1730 o_c_l = 0.,
1731 o_c_r = 0.,
1732 std = 0.;
1733 const double *pwave_y = NULL,
1734 *pcenter_y = NULL;
1735 cpl_polynomial **poly_u = NULL;
1736 cpl_bivector *grid = NULL;
1737 cpl_vector *val_to_fit = NULL,
1738 *tt = NULL;
1739 eris_ifu_vector *y_wave = NULL,
1740 *y_cen = NULL,
1741 *t = NULL;
1742 cpl_boolean triple_traces = FALSE;
1743 cpl_table *tbl = NULL,
1744 *dbg_polynomials = NULL;
1745 cpl_propertylist **pl = NULL;
1746 struct arcstruct *arc_tbl = NULL;
1747
1748 cpl_ensure(slit_edges, CPL_ERROR_NULL_INPUT, NULL);
1749 cpl_ensure(centers, CPL_ERROR_NULL_INPUT, NULL);
1750
1751 TRY
1752 {
1753 BRK_IF_NULL( dbg_polynomials = cpl_table_new(SLITLET_CNT));
1754 cpl_table_new_column(dbg_polynomials, ERIS_IFU_DIST_DBG_SLITLET, CPL_TYPE_INT);
1755 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_EDGE_LEFT, CPL_TYPE_DOUBLE, fit_order+1);
1756 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_EDGE_RIGHT, CPL_TYPE_DOUBLE, fit_order+1);
1757 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER_LEFT, CPL_TYPE_DOUBLE, fit_order+1);
1758 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER, CPL_TYPE_DOUBLE, fit_order+1);
1759 cpl_table_new_column_array(dbg_polynomials, ERIS_IFU_DIST_DBG_CENTER_RIGHT, CPL_TYPE_DOUBLE, fit_order+1);
1760 CHECK_ERROR_STATE();
1761
1762 BRK_IF_NULL(
1763 poly_u = cpl_calloc(SLITLET_CNT, sizeof(cpl_polynomial*)));
1764
1765 if (cpl_table_get_ncol(centers[5]) > 2) {
1766 triple_traces = TRUE;
1767 }
1768
1769 BRK_IF_ERROR(
1770 cpl_propertylist_save(NULL, ERIS_IFU_PRO_DIST_QC_FIT_FN, CPL_IO_CREATE));
1771
1772 BRK_IF_NULL(
1773 arc_tbl = cpl_calloc(SLITLET_CNT, sizeof(struct arcstruct)));
1774
1775 // calculate all slitlets taht are not cut off
1776 for (int i = 0; i < SLITLET_CNT; i++) {
1777 //cpl_msg_debug(cpl_func, "i: %d\n", i);
1778 // get number of vertical traces (arcs) to process
1779 n_arcs = eris_ifu_distortion_get_narcs(i, triple_traces,
1780 cut_off_left, cut_off_right);
1781 // get number of detected wave_calib-lines
1782 n_calib_wave = (int) cpl_table_get_nrow(slit_edges[i]);
1783 // get number of centerpoints
1784 n_calib_cen = (int) cpl_table_get_nrow(centers[i]);
1785
1786 // get y-coordinates
1787 BRK_IF_NULL(
1788 pwave_y = cpl_table_get_data_double_const(
1789 slit_edges[i], "y_pos"));
1790 BRK_IF_NULL(
1791 pcenter_y = cpl_table_get_data_double_const(
1792 centers[i], "y"));
1793 BRK_IF_NULL(
1794 y_wave = eris_ifu_vector_new_wrap(n_calib_wave, pwave_y));
1795 BRK_IF_NULL(
1796 y_cen = eris_ifu_vector_new_wrap(n_calib_cen, pcenter_y));
1797
1798 // fit all edges (left, right, centers)
1799 if (!((i == 0) && cut_off_left)) {
1800 // process only if it is not the 1st slitlet and cutoff
1801 BRK_IF_NULL(
1802 arc_tbl[i].fit_l = eris_ifu_dist_calc_distortion_fitedge(
1803 slit_edges[i], "edge_left", y_wave,
1804 n_calib_wave, n_size, fit_order,
1805 i, dbg_polynomials));
1806 }
1807 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1808 // process only if it is not the last slitlet and cutoff
1809 BRK_IF_NULL(
1810 arc_tbl[i].fit_r = eris_ifu_dist_calc_distortion_fitedge(
1811 slit_edges[i], "edge_right", y_wave,
1812 n_calib_wave, n_size, fit_order,
1813 i, dbg_polynomials));
1814 }
1815 BRK_IF_NULL(
1816 arc_tbl[i].fit_c = eris_ifu_dist_calc_distortion_fitedge(
1817 centers[i], "x", y_cen,
1818 n_calib_cen, n_size, fit_order,
1819 i, dbg_polynomials));
1820 if (triple_traces) {
1821 if (!((i == 0) && cut_off_left)) {
1822 // process if it is not the 1st slitlet and not cutoff
1823 BRK_IF_NULL(
1824 arc_tbl[i].fit_c_l = eris_ifu_dist_calc_distortion_fitedge(
1825 centers[i], "x_l", y_cen,
1826 n_calib_cen, n_size, fit_order,
1827 i, dbg_polynomials));
1828 } else {
1829 // if it is the last slitlet and cutoff, then
1830 // check first if, and how many, values are nan
1831 // If there are too many NaN's do nothing and copy the shape of c to c_l
1832 if (cpl_table_count_invalid(centers[i], "x_l") <= 0.1 * n_calib_cen) {
1833 // calculate fitted edge only if less tahn 10% of the values are NaN
1834 BRK_IF_NULL(
1835 arc_tbl[i].fit_c_l = eris_ifu_dist_calc_distortion_fitedge(
1836 centers[i], "x_l", y_cen,
1837 n_calib_cen, n_size, fit_order,
1838 i, dbg_polynomials));
1839 }
1840 }
1841
1842 if (!((i == SLITLET_CNT-1) && cut_off_right)) {
1843 // process if it is not the last slitlet and not cutoff
1844 BRK_IF_NULL(
1845 arc_tbl[i].fit_c_r = eris_ifu_dist_calc_distortion_fitedge(
1846 centers[i], "x_r", y_cen,
1847 n_calib_cen, n_size, fit_order,
1848 i, dbg_polynomials));
1849 } else {
1850 // if it is the last slitlet and cutoff, then
1851 // check first if, and how many, values are nan
1852 // If there are too many NaN's do nothing and copy the shape of c to c_r
1853 if (cpl_table_count_invalid(centers[i], "x_r") <= 0.1 * n_calib_cen) {
1854 // calculate fitted edge only if less than 10% of the values are NaN
1855 BRK_IF_NULL(
1856 arc_tbl[i].fit_c_r = eris_ifu_dist_calc_distortion_fitedge(
1857 centers[i], "x_r", y_cen,
1858 n_calib_cen, n_size, fit_order,
1859 i, dbg_polynomials));
1860 }
1861 }
1862 } // end: if (triple_traces)
1863 eris_ifu_free_ifu_vector(&y_wave);
1864 eris_ifu_free_ifu_vector(&y_cen);
1865 } // end: i = SLITLET_CNT
1866
1867 BRK_IF_NULL(
1868 pl = cpl_calloc(SLITLET_CNT, sizeof(cpl_propertylist*)));
1869 for (int i = 0; i < SLITLET_CNT; i++) {
1870 BRK_IF_NULL(
1871 pl[i] = cpl_propertylist_new());
1872 }
1873
1874 // estimate positions of cut off edges with neighbouring slitlet width
1875 if (cut_off_left) {
1876 BRK_IF_ERROR(
1877 cpl_propertylist_append_string(pl[0],
1878 "EDGE L", "artificial"));
1879 if (arc_tbl[0].fit_l == NULL) {
1880 /* The leftmost edge of slitlet #0 is cut off. Therefore subtract the
1881 * width of slitlet #1 from the right edge of slitlet #0
1882 */
1883 BRK_IF_NULL(
1884 arc_tbl[0].fit_l = eris_ifu_vector_duplicate(arc_tbl[0].fit_r));
1885 BRK_IF_ERROR(
1886 eris_ifu_vector_subtract(arc_tbl[0].fit_l, arc_tbl[1].fit_r));
1887 BRK_IF_ERROR(
1888 eris_ifu_vector_add(arc_tbl[0].fit_l, arc_tbl[1].fit_l));
1889 }
1890 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_l == NULL)) {
1891 /* The c_l-edge of slitlet #0 is cut off. Therefore subtract the
1892 * width of c-c_l of slitlet #31 to the left edge of slitlet #32
1893 */
1894 BRK_IF_NULL(
1895 arc_tbl[0].fit_c_l = eris_ifu_vector_duplicate(arc_tbl[0].fit_c));
1896 BRK_IF_ERROR(
1897 eris_ifu_vector_subtract(arc_tbl[0].fit_c_l, arc_tbl[1].fit_c));
1898 BRK_IF_ERROR(
1899 eris_ifu_vector_add(arc_tbl[0].fit_c_l, arc_tbl[1].fit_c_l));
1900 }
1901 cut_off_left = CPL_FALSE;
1902 }
1903
1904 if (cut_off_right) {
1905 BRK_IF_ERROR(
1906 cpl_propertylist_append_string(pl[SLITLET_CNT-1],
1907 "EDGE R", "artificial"));
1908 if (arc_tbl[SLITLET_CNT-1].fit_r == NULL) {
1909 /* The rightmost edge of slitlet #32 is cut off. Therefore add the
1910 * width of slitlet #31 to the left edge of slitlet #32
1911 */
1912 BRK_IF_NULL(
1913 arc_tbl[SLITLET_CNT-1].fit_r = eris_ifu_vector_duplicate(arc_tbl[SLITLET_CNT-1].fit_l));
1914 BRK_IF_ERROR(
1915 eris_ifu_vector_add(arc_tbl[SLITLET_CNT-1].fit_r, arc_tbl[SLITLET_CNT-2].fit_r));
1916 BRK_IF_ERROR(
1917 eris_ifu_vector_subtract(arc_tbl[SLITLET_CNT-1].fit_r, arc_tbl[SLITLET_CNT-2].fit_l));
1918 }
1919 if (triple_traces && (arc_tbl[SLITLET_CNT-1].fit_c_r == NULL)) {
1920 /* The c_r-edge of slitlet #32 is cut off. Therefore add the
1921 * width of c_r-c of slitlet #31 to the left center edge of slitlet #32
1922 */
1923 BRK_IF_NULL(
1924 arc_tbl[SLITLET_CNT-1].fit_c_r = eris_ifu_vector_duplicate(arc_tbl[SLITLET_CNT-1].fit_c));
1925 BRK_IF_ERROR(
1926 eris_ifu_vector_add(arc_tbl[SLITLET_CNT-1].fit_c_r, arc_tbl[SLITLET_CNT-2].fit_c_r));
1927 BRK_IF_ERROR(
1928 eris_ifu_vector_subtract(arc_tbl[SLITLET_CNT-1].fit_c_r, arc_tbl[SLITLET_CNT-2].fit_c));
1929 }
1930 cut_off_right = CPL_FALSE;
1931 }
1932
1933 const char *fn = "eris_ifu_distortion_dbg_calcdistor_grid_xy_val2fit.fits";
1934 if (productDepth & 4) {
1935 eris_ifu_save_vector_dbg(NULL, fn, CPL_IO_CREATE, NULL);
1936 }
1937 // estimate mean origin positions of the arc-lines and calculate
1938 // target positions for the edges, fill the grid, perform polynomial-fit
1939 for (int i = 0; i < SLITLET_CNT; i++) {
1940 // get number of vertical traces (arcs) to process
1941 n_arcs = eris_ifu_distortion_get_narcs(i, triple_traces,
1942 cut_off_left, cut_off_right);
1943
1944 /*
1945 * estimate mean origin positions of the arc-lines (left, center, right)
1946 */
1947 o_l = eris_ifu_vector_get_mean(arc_tbl[i].fit_l);
1948 o_c = eris_ifu_vector_get_mean(arc_tbl[i].fit_c);
1949 o_r = eris_ifu_vector_get_mean(arc_tbl[i].fit_r);
1950 if (triple_traces) {
1951 o_c_l = eris_ifu_vector_get_mean(arc_tbl[i].fit_c_l);
1952 o_c_r = eris_ifu_vector_get_mean(arc_tbl[i].fit_c_r);
1953 }
1954
1955 /*
1956 * from these estimates define target positions for the arc-lines (left, center, right)
1957 */
1958 // left+right edge are simple: a slitlet should have 64pix width
1959 t_l = eris_ifu_distortion_target_left_edge(i);
1960 t_r = eris_ifu_distortion_target_right_edge(i);
1961
1962 // the center positions are calculated with the sentence of three...
1963 t_c = (int)((o_c-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1964 if (triple_traces) {
1965 t_c_l = (int)((o_c_l-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1966 t_c_r = (int)((o_c_r-o_l)*(t_r-t_l)/(o_r-o_l) + t_l + .5);
1967 }
1968
1969// cpl_msg_debug(cpl_func, "i: %02d, o_l: %7.2f, o_c_l: %7.2f,"
1970// "o_c: %7.2f, o_c_r: %7.2f, o_r: %7.2f",
1971// i, o_l, o_c_l, o_c, o_c_r, o_r);
1972// cpl_msg_debug(cpl_func, " t_l: %04d , t_c_l: %04d ,"
1973// " t_c: %04d , t_c_r: %04d , t_r: %04d",
1974// t_l, t_c_l, t_c, t_c_r, t_r);
1975 // create grid to fit to (contains target-coordinates)
1976 BRK_IF_NULL(
1977 grid = cpl_bivector_new(n_arcs * n_size));
1978
1979 // create vector with values to fit (contains origin-coordinates)
1980 BRK_IF_NULL(
1981 val_to_fit = cpl_vector_new(n_arcs * n_size));
1982
1983 arc_cnt = 0;
1984 // fill in left edge
1985 BRK_IF_ERROR(
1986 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_l, val_to_fit,
1987 t_l, n_size, arc_cnt++));
1988 if (triple_traces) {
1989 // fill in center_l
1990 BRK_IF_ERROR(
1991 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c_l, val_to_fit,
1992 t_c_l, n_size, arc_cnt++));
1993 }
1994 // fill in center
1995 BRK_IF_ERROR(
1996 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c, val_to_fit,
1997 t_c, n_size, arc_cnt++));
1998 if (triple_traces) {
1999 // fill in center_l
2000 BRK_IF_ERROR(
2001 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_c_r, val_to_fit,
2002 t_c_r, n_size, arc_cnt++));
2003 }
2004 // fill in right edge
2005 BRK_IF_ERROR(
2006 eris_ifu_dist_calc_distortion_fillgrid(grid, arc_tbl[i].fit_r, val_to_fit,
2007 t_r, n_size, arc_cnt++));
2008
2009 if (productDepth & 4) {
2010// cpl_propertylist *pl = NULL;
2011// BRK_IF_NULL(
2012// pl = cpl_propertylist_new());
2013 char *extname = NULL;
2014
2015 extname = cpl_sprintf("xVector Sx_%02d", i+1);
2016 cpl_propertylist_update_string(pl[i], "EXTNAME", extname);
2017 eris_ifu_free_string(&extname);
2018 eris_ifu_save_vector_dbg(cpl_bivector_get_x(grid), fn, CPL_IO_EXTEND, pl[i]);
2019
2020 extname = cpl_sprintf("yVector Sx_%02d", i+1);
2021 cpl_propertylist_update_string(pl[i], "EXTNAME", extname);
2022 eris_ifu_free_string(&extname);
2023 eris_ifu_save_vector_dbg(cpl_bivector_get_y(grid), fn, CPL_IO_EXTEND, pl[i]);
2024
2025 extname = cpl_sprintf("val2fit Sx_%02d", i+1);
2026 cpl_propertylist_update_string(pl[i], "EXTNAME", extname);
2027 eris_ifu_free_string(&extname);
2028 eris_ifu_save_vector_dbg(val_to_fit, fn, CPL_IO_EXTEND, pl[i]);
2029
2030// eris_ifu_free_propertylist(&pl);
2031 }
2032
2033 /* Apply the fitting */
2034 BRK_IF_NULL(
2035 poly_u[i] = eris_ifu_dist_poly_fit_2d_create(grid, val_to_fit, NULL));
2036
2037 eris_ifu_free_bivector(&grid);
2038 eris_ifu_free_vector(&val_to_fit);
2039 } // end: i = SLITLET_CNT
2040
2041 // save values of all fitted edges and some stats
2042 if (productDepth & 2) {
2043 for (int i = 0; i < SLITLET_CNT; i++) {
2044 BRK_IF_NULL(
2045 tbl = cpl_table_new(n_size));
2046 if (arc_tbl[i].fit_l != NULL) {
2047 BRK_IF_ERROR(
2048 cpl_table_new_column(tbl, "l", CPL_TYPE_DOUBLE));
2049 BRK_IF_NULL(
2050 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_l));
2051 BRK_IF_ERROR(
2052 cpl_table_copy_data_double(tbl, "l", cpl_vector_get_data_const(tt)));
2053 eris_ifu_free_vector(&tt);
2054 }
2055 if (arc_tbl[i].fit_c_l != NULL) {
2056 BRK_IF_ERROR(
2057 cpl_table_new_column(tbl, "c_l", CPL_TYPE_DOUBLE));
2058 BRK_IF_NULL(
2059 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_c_l));
2060 BRK_IF_ERROR(
2061 cpl_table_copy_data_double(tbl, "c_l", cpl_vector_get_data_const(tt)));
2062 eris_ifu_free_vector(&tt);
2063 }
2064 if (arc_tbl[i].fit_c != NULL) {
2065 BRK_IF_ERROR(
2066 cpl_table_new_column(tbl, "c", CPL_TYPE_DOUBLE));
2067 BRK_IF_NULL(
2068 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_c));
2069 BRK_IF_ERROR(
2070 cpl_table_copy_data_double(tbl, "c", cpl_vector_get_data_const(tt)));
2071 eris_ifu_free_vector(&tt);
2072 }
2073 if (arc_tbl[i].fit_c_r != NULL) {
2074 BRK_IF_ERROR(
2075 cpl_table_new_column(tbl, "c_r", CPL_TYPE_DOUBLE));
2076 BRK_IF_NULL(
2077 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_c_r));
2078 BRK_IF_ERROR(
2079 cpl_table_copy_data_double(tbl, "c_r", cpl_vector_get_data_const(tt)));
2080 eris_ifu_free_vector(&tt);
2081 }
2082 if (arc_tbl[i].fit_r != NULL) {
2083 BRK_IF_ERROR(
2084 cpl_table_new_column(tbl, "r", CPL_TYPE_DOUBLE));
2085 BRK_IF_NULL(
2086 tt = eris_ifu_vector_get_data(arc_tbl[i].fit_r));
2087 BRK_IF_ERROR(
2088 cpl_table_copy_data_double(tbl, "r", cpl_vector_get_data_const(tt)));
2089 eris_ifu_free_vector(&tt);
2090 }
2091
2092 // calc stddev of differences of distances between single traces
2093 if ((arc_tbl[i].fit_l != NULL) && (arc_tbl[i].fit_r != NULL)) {
2094 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_r);
2095 BRK_IF_ERROR(
2096 eris_ifu_vector_subtract(t, arc_tbl[i].fit_l));
2097 std = eris_ifu_vector_get_stdev(t);
2098 if (!eris_ifu_is_nan_or_inf(std)) {
2099 BRK_IF_ERROR(
2100 cpl_propertylist_append_double(pl[i], "STDEV R-L", std));
2101 } else {
2102 BRK_IF_ERROR(
2103 cpl_propertylist_append_string(pl[i], "STDEV R-L", "NaN"));
2104 }
2105
2106 // for the ease of stats: save the slit-width
2107 BRK_IF_ERROR(
2108 cpl_table_new_column(tbl, "slit_width", CPL_TYPE_DOUBLE));
2109 BRK_IF_NULL(
2110 tt = eris_ifu_vector_get_data(t));
2111 BRK_IF_ERROR(
2112 cpl_table_copy_data_double(tbl, "slit_width", cpl_vector_get_data_const(tt)));
2113
2114 eris_ifu_free_vector(&tt);
2115 eris_ifu_free_ifu_vector(&t);
2116 }
2117 if ((arc_tbl[i].fit_l != NULL) && (arc_tbl[i].fit_c != NULL)) {
2118 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c);
2119 BRK_IF_ERROR(
2120 eris_ifu_vector_subtract(t, arc_tbl[i].fit_l));
2121 std = eris_ifu_vector_get_stdev(t);
2122 if (!eris_ifu_is_nan_or_inf(std)) {
2123 BRK_IF_ERROR(
2124 cpl_propertylist_append_double(pl[i], "STDEV C-L", std));
2125 } else {
2126 BRK_IF_ERROR(
2127 cpl_propertylist_append_string(pl[i], "STDEV C-L", "NaN"));
2128 }
2129 eris_ifu_free_ifu_vector(&t);
2130 }
2131 if ((arc_tbl[i].fit_c != NULL) && (arc_tbl[i].fit_r != NULL)) {
2132 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_r);
2133 BRK_IF_ERROR(
2134 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c));
2135 std = eris_ifu_vector_get_stdev(t);
2136 if (!eris_ifu_is_nan_or_inf(std)) {
2137 BRK_IF_ERROR(
2138 cpl_propertylist_append_double(pl[i], "STDEV R-C", std));
2139 } else {
2140 BRK_IF_ERROR(
2141 cpl_propertylist_append_string(pl[i], "STDEV R-C", "NaN"));
2142 }
2143 eris_ifu_free_ifu_vector(&t);
2144 }
2145 if ((arc_tbl[i].fit_c != NULL) && (arc_tbl[i].fit_c_l != NULL)) {
2146 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c);
2147 BRK_IF_ERROR(
2148 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c_l));
2149 std = eris_ifu_vector_get_stdev(t);
2150 if (!eris_ifu_is_nan_or_inf(std)) {
2151 BRK_IF_ERROR(
2152 cpl_propertylist_append_double(pl[i], "STDEV C-CL", std));
2153 } else {
2154 BRK_IF_ERROR(
2155 cpl_propertylist_append_string(pl[i], "STDEV C-CL", "NaN"));
2156 }
2157 eris_ifu_free_ifu_vector(&t);
2158 }
2159 if ((arc_tbl[i].fit_c_r != NULL) && (arc_tbl[i].fit_c != NULL)) {
2160 t = eris_ifu_vector_duplicate(arc_tbl[i].fit_c_r);
2161 BRK_IF_ERROR(
2162 eris_ifu_vector_subtract(t, arc_tbl[i].fit_c));
2163 std = eris_ifu_vector_get_stdev(t);
2164 if (!eris_ifu_is_nan_or_inf(std)) {
2165 BRK_IF_ERROR(
2166 cpl_propertylist_append_double(pl[i], "STDEV CR-C", std));
2167 } else {
2168 BRK_IF_ERROR(
2169 cpl_propertylist_append_string(pl[i], "STDEV CR-C", "NaN"));
2170 }
2171 eris_ifu_free_ifu_vector(&t);
2172 }
2173 if ((productDepth & 2) != 0) {
2174 BRK_IF_ERROR(
2175 cpl_table_save(tbl, NULL, pl[i], ERIS_IFU_PRO_DIST_QC_FIT_FN, CPL_IO_EXTEND));
2176 }
2177
2178 eris_ifu_free_table(&tbl);
2179 } // end: i = SLITLET_CNT
2180 } // end: if (productDepth & 2)
2181 }
2182 CATCH
2183 {
2184 CATCH_MSGS();
2185 for (int j = 0; j < SLITLET_CNT; j++) {
2186 cpl_polynomial_delete(poly_u[j]); poly_u[j] = NULL;
2187 }
2188 cpl_free(poly_u); poly_u = NULL;
2189 }
2190
2191 eris_ifu_free_bivector(&grid);
2192 eris_ifu_free_vector(&val_to_fit);
2193 eris_ifu_free_ifu_vector(&y_wave);
2194 for (int i = 0; i < SLITLET_CNT; i++) {
2195 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_l);
2196 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c);
2197 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c_l);
2198 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_c_r);
2199 eris_ifu_free_ifu_vector(&arc_tbl[i].fit_r);
2200 }
2201 if (pl != NULL) {
2202 for (int i = 0; i < SLITLET_CNT; i++) {
2203 eris_ifu_free_propertylist(&pl[i]);
2204 }
2205 }
2206 cpl_free(arc_tbl); arc_tbl = NULL;
2207 cpl_free(pl); pl = NULL;
2208
2209 return poly_u;
2210}
2211
2212//n_calib: size of input
2213// n_size: size of output
2214eris_ifu_vector* eris_ifu_dist_calc_distortion_fitedge(const cpl_table *edge,
2215 const char *col_name,
2216 const eris_ifu_vector *y,
2217 int n_calib,
2218 int n_size,
2219 int fit_order,
2220 int slitlet,
2221 cpl_table *dbg_tbl)
2222{
2223 const double *px = NULL;
2224 double *pfit_par = NULL;
2225 eris_ifu_vector *x = NULL,
2226 *fit = NULL;
2227 cpl_vector *fit_par = NULL;
2228 cpl_array *tmp_array = NULL;
2229
2230 cpl_ensure(edge, CPL_ERROR_NULL_INPUT, NULL);
2231 cpl_ensure(col_name, CPL_ERROR_NULL_INPUT, NULL);
2232 cpl_ensure(y, CPL_ERROR_NULL_INPUT, NULL);
2233 cpl_ensure(n_calib > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2234 cpl_ensure(n_size > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2235 cpl_ensure(fit_order > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2236
2237 TRY
2238 {
2239 BRK_IF_NULL(
2240 px = cpl_table_get_data_double_const(edge, col_name));
2241
2242 BRK_IF_NULL(
2243 x = eris_ifu_vector_new_wrap(n_calib, px));
2244
2245 // fit polynomial to edge
2246 BRK_IF_NULL(
2247 fit_par = eris_ifu_polyfit_edge(y, x, fit_order));
2248 eris_ifu_free_ifu_vector(&x);
2249
2250 BRK_IF_NULL(
2251 pfit_par = cpl_vector_get_data(fit_par));
2252
2253 // save polynomials to table to support remote debugging
2254 tmp_array = cpl_array_wrap_double(pfit_par, cpl_vector_get_size(fit_par));
2255 cpl_table_set_int(dbg_tbl, ERIS_IFU_DIST_DBG_SLITLET, slitlet, slitlet);
2256 cpl_table_set_array(dbg_tbl, col_name, slitlet, tmp_array);
2257 cpl_array_unwrap(tmp_array);
2258 CHECK_ERROR_STATE();
2259
2260 // create vector with fitted values
2261 BRK_IF_NULL(
2262 fit = eris_ifu_vector_new(n_size));
2263 for (int j = 0; j < n_size; j++) {
2264 int yy = eris_ifu_distortion_calc_y(n_size, j);
2265 double v = pfit_par[0] +
2266 pfit_par[1] * yy +
2267 pfit_par[2] * pow(yy, 2);
2268// + pfit_par[3] * pow(yy, 3);
2269 BRK_IF_ERROR(
2270 eris_ifu_vector_set(fit, j, v));
2271 }
2272 }
2273 CATCH
2274 {
2275 CATCH_MSGS();
2276 eris_ifu_free_ifu_vector(&fit);
2277 }
2278 eris_ifu_free_vector(&fit_par);
2279
2280 return fit;
2281}
2282
2283cpl_error_code eris_ifu_dist_calc_distortion_fillgrid(cpl_bivector *grid,
2284 const eris_ifu_vector *data,
2285 cpl_vector *val_to_fit,
2286 double x_pos,
2287 int n_size,
2288 int arc_cnt)
2289{
2290 cpl_error_code err = CPL_ERROR_NONE;
2291 double *pgridx = NULL,
2292 *pgridy = NULL,
2293 *pval_to_fit = NULL;
2294
2295 cpl_ensure_code(grid, CPL_ERROR_NULL_INPUT);
2296 cpl_ensure_code(data, CPL_ERROR_NULL_INPUT);
2297 cpl_ensure_code(val_to_fit, CPL_ERROR_NULL_INPUT);
2298 if (x_pos == -1){
2299 x_pos=0;
2300 }
2301 cpl_ensure_code(x_pos >= -64, CPL_ERROR_ILLEGAL_INPUT);
2302 cpl_ensure_code(arc_cnt >= 0, CPL_ERROR_ILLEGAL_INPUT);
2303 cpl_ensure_code(n_size >= 0, CPL_ERROR_ILLEGAL_INPUT);
2304
2305 TRY
2306 {
2307 BRK_IF_NULL(
2308 pgridx = cpl_bivector_get_x_data(grid));
2309 BRK_IF_NULL(
2310 pgridy = cpl_bivector_get_y_data(grid));
2311 BRK_IF_NULL(
2312 pval_to_fit = cpl_vector_get_data(val_to_fit));
2313
2314 for (int j = arc_cnt*n_size; j < (arc_cnt+1)*n_size; j++) {
2315 ASSURE(j < cpl_bivector_get_size(grid),
2316 CPL_ERROR_ILLEGAL_INPUT,
2317 "index overrun");
2318
2319 int jj = j % n_size;
2320
2321 // same target-x for all y-positions
2322 pgridx[j] = x_pos;
2323
2324 // calc target-y
2325 pgridy[j] = eris_ifu_distortion_calc_y(n_size, jj);
2326
2327 // insert fitted x-value at y-position
2328 if (eris_ifu_vector_is_rejected(data, jj)) {
2329 pval_to_fit[j] = NAN;
2330 } else {
2331 pval_to_fit[j] = eris_ifu_vector_get(data, jj);
2332 }
2333 }
2334 }
2335 CATCH
2336 {
2337 CATCH_MSGS();
2338 err = cpl_error_get_code();
2339 }
2340
2341 return err;
2342}
2343
2344cpl_polynomial* eris_ifu_dist_poly_fit_2d_create(cpl_bivector *xy_pos,
2345 const cpl_vector *values,
2346 double *msee)
2347{
2348 int xy_size = 0;
2349 double rechisq = 0.,
2350 value = 0.;
2351 cpl_size degree = NS_FIT_DEGREE;
2352 cpl_matrix *samppos2d = NULL;
2353 cpl_vector *fitresidual = NULL;
2354 cpl_polynomial *fit2d = NULL;
2355
2356 typedef double* (*get_data)(cpl_bivector*);
2357 get_data data_extractor[2] = { &cpl_bivector_get_x_data,
2358 &cpl_bivector_get_y_data };
2359
2360 cpl_ensure(xy_pos, CPL_ERROR_NULL_INPUT, NULL);
2361 cpl_ensure(values, CPL_ERROR_NULL_INPUT, NULL);
2362 cpl_ensure(degree > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2363
2364 TRY
2365 {
2366 xy_size = (int) cpl_bivector_get_size(xy_pos);
2367 CHECK_ERROR_STATE();
2368
2369 BRK_IF_NULL(
2370 fit2d = cpl_polynomial_new(2));
2371 BRK_IF_NULL(
2372 samppos2d = cpl_matrix_new(2, xy_size));
2373
2374 for (int i = 0; i < 2; i++) {
2375 for (int j = 0; j < xy_size; j++) {
2376 value = data_extractor[i](xy_pos)[j];
2377 BRK_IF_ERROR(
2378 cpl_matrix_set(samppos2d, i, j, value));
2379 }
2380 }
2381 const cpl_size maxdeg2d[] = {2,3};
2382 BRK_IF_ERROR(
2383 cpl_polynomial_fit(fit2d, samppos2d, NULL, values, NULL, CPL_TRUE,
2384 NULL, maxdeg2d));
2385// BRK_IF_ERROR(
2386// cpl_polynomial_fit(fit2d, samppos2d, NULL, values, NULL, CPL_FALSE,
2387// NULL, &degree));
2388
2389 BRK_IF_NULL(
2390 fitresidual = cpl_vector_new(xy_size));
2391 BRK_IF_ERROR(
2392 cpl_vector_fill_polynomial_fit_residual(fitresidual, values, NULL,
2393 fit2d, samppos2d, &rechisq));
2394 if (msee) {
2395 *msee = cpl_vector_product(fitresidual, fitresidual)
2396 / (double) cpl_vector_get_size(fitresidual);
2397 }
2398 }
2399 CATCH
2400 {
2401 CATCH_MSGS();
2402 eris_ifu_free_polynomial(&fit2d);
2403 }
2404
2405 eris_ifu_free_matrix(&samppos2d);
2406 eris_ifu_free_vector(&fitresidual);
2407
2408 return fit2d;
2409}
2410
2411cpl_error_code eris_ifu_dist_save_distortion(cpl_polynomial **poly2d,
2412 const cpl_table *minmax_borders,
2413 const char *fn,
2414 cpl_frameset *frameset,
2415 const cpl_parameterlist *parlist,
2416 cpl_propertylist **qc)
2417{
2418 double coeff/*,
2419 xshift = 0.*/;
2420// char key_name[FILE_NAME_SZ];
2421 cpl_size max_degree;
2422 cpl_size coef_pow[2];
2423 cpl_table *poly_tbl = NULL;
2424 cpl_error_code err = CPL_ERROR_NONE;
2425
2426 cpl_ensure_code(poly2d, CPL_ERROR_NULL_INPUT);
2427 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
2428 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
2429 char* extname;
2430 TRY
2431 {
2432 for (int i = 0; i < SLITLET_CNT; i++) {
2433 if (poly2d[i] == NULL) {
2434 cpl_propertylist_save(NULL, fn, CPL_IO_EXTEND);
2435 } else {
2436 max_degree = cpl_polynomial_get_degree(poly2d[i]);
2437 BRK_IF_NULL(
2438 poly_tbl = cpl_table_new(max_degree * max_degree));
2439 BRK_IF_ERROR(
2440 cpl_table_new_column(poly_tbl,"degx", CPL_TYPE_INT));
2441 BRK_IF_ERROR(
2442 cpl_table_new_column(poly_tbl,"degy", CPL_TYPE_INT));
2443 BRK_IF_ERROR(
2444 cpl_table_new_column(poly_tbl,"coeff", CPL_TYPE_DOUBLE));
2445
2446 cpl_size tx = 0;
2447 for (cpl_size cy=0; cy < max_degree; cy++) {
2448 for (cpl_size cx=0; cx < max_degree; cx++) {
2449 coef_pow[0]=cx;
2450 coef_pow[1]=cy;
2451 coeff = cpl_polynomial_get_coeff(poly2d[i], coef_pow);
2452 if (fabs(coeff) > 1e-30) { //Here DBL_ZERO_TOLERANCE 1e-10 is too high
2453 BRK_IF_ERROR(
2454 cpl_table_set_int(poly_tbl,"degx",tx,(int) cx));
2455 BRK_IF_ERROR(
2456 cpl_table_set_int(poly_tbl,"degy",tx,(int) cy));
2457 BRK_IF_ERROR(
2458 cpl_table_set_double(poly_tbl,"coeff", tx,
2459 coeff));
2460 tx++;
2461 }
2462 }
2463 }
2464 BRK_IF_ERROR(
2465 cpl_table_set_size(poly_tbl, tx));
2466
2467// /* QC LOG */
2468// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 0, 0);
2469// BRK_IF_ERROR(
2470// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][0],
2471// "Polynomial distortion coefficient"));
2472//
2473// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 1,0);
2474// BRK_IF_ERROR(
2475// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[1][0],
2476// "Polynomial distortion coefficient"));
2477//
2478// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 0, 1);
2479// BRK_IF_ERROR(
2480// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][1],
2481// "Polynomial distortion coefficient"));
2482//
2483// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 1, 1);
2484// BRK_IF_ERROR(
2485// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[1][1],
2486// "Polynomial distortion coefficient"));
2487//
2488// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 2, 0);
2489// BRK_IF_ERROR(
2490// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[2][0],
2491// "Polynomial distortion coefficient"));
2492//
2493// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 0, 2);
2494// BRK_IF_ERROR(
2495// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][2],
2496// "Polynomial distortion coefficient"));
2497//
2498// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 2, 1);
2499// BRK_IF_ERROR(
2500// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[2][1],
2501// "Polynomial distortion coefficient"));
2502//
2503// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d", "QC COEFF", 1, 2);
2504// BRK_IF_ERROR(
2505// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[1][2],
2506// "Polynpoly2domial distortion coefficient"));
2507//
2508// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d","QC COEFF", 3, 0);
2509// BRK_IF_ERROR(
2510// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[3][0],
2511// "Polynomial distortion coefficient"));
2512//
2513// snprintf(key_name, FILE_NAME_SZ-1, "%s%d%d","QC COEFF", 0, 3);
2514// BRK_IF_ERROR(
2515// eris_ifu_dist_qclog_add_double(qc[i], key_name, pcf[0][3],
2516// "Polynomial distortion coefficient"));
2517//
2518// xshift = eris_ifu_dist_compute_shift( x_c, y_c,
2519// pcf[0][0], pcf[1][0], pcf[0][1],
2520// pcf[1][1], pcf[2][0], pcf[0][2],
2521// pcf[2][1], pcf[1][2], pcf[3][0], pcf[0][3]);
2522// BRK_IF_ERROR(
2523// eris_ifu_dist_qclog_add_double(qc[i], "QC XSHIFT CC", xshift,
2524// "X shift in x_c,y_c"));
2525//
2526// xshift = eris_ifu_dist_compute_shift( x_l, y_l,
2527// pcf[0][0], pcf[1][0], pcf[0][1],
2528// pcf[1][1], pcf[2][0], pcf[0][2],
2529// pcf[2][1], pcf[1][2], pcf[3][0], pcf[0][3]);
2530// BRK_IF_ERROR(
2531// eris_ifu_dist_qclog_add_double(qc[i], "QC XSHIFT LL", xshift,
2532// "X shift in x_l,y_l"));
2533//
2534// xshift = eris_ifu_dist_compute_shift(x_l,y_u,pcf[0][0],pcf[1][0],pcf[0][1],
2535// pcf[1][1],pcf[2][0],pcf[0][2],
2536// pcf[2][1],pcf[1][2],pcf[3][0],pcf[0][3]);
2537// BRK_IF_ERROR(
2538// eris_ifu_dist_qclog_add_double(qc[i],"QC XSHIFT UL",xshift,
2539// "X shift in x_l,y_u"));
2540//
2541// xshift = eris_ifu_dist_compute_shift(x_u,y_u,pcf[0][0],pcf[1][0],pcf[0][1],
2542// pcf[1][1],pcf[2][0],pcf[0][2],
2543// pcf[2][1],pcf[1][2],pcf[3][0],pcf[0][3]);
2544// BRK_IF_ERROR(
2545// eris_ifu_dist_qclog_add_double(qc[i],"QC XSHIFT UR",xshift,
2546// "X shift in x_u,y_u"));
2547//
2548// xshift = eris_ifu_dist_compute_shift(x_u,y_l,pcf[0][0],pcf[1][0],pcf[0][1],
2549// pcf[1][1],pcf[2][0],pcf[0][2],
2550// pcf[2][1],pcf[1][2],pcf[3][0],pcf[0][3]);
2551// BRK_IF_ERROR(
2552// eris_ifu_dist_qclog_add_double(qc[i],"QC XSHIFT LR",xshift,
2553// "X shift in x_u,y_l"));
2554
2555 extname = cpl_sprintf("SLITLET%2.2d",i);
2556 cpl_propertylist_append_string(qc[i],"EXTNAME",extname);
2557 if (i == 0) {
2558 BRK_IF_ERROR(
2559 eris_ifu_save_table(frameset, NULL, parlist, frameset, NULL,
2560 REC_NAME_DISTORTION,
2561 ERIS_IFU_PRO_DIST_DISTORTION,
2562 qc[i], "EXTNAME",
2563 fn,
2564 poly_tbl));
2565 } else {
2566 BRK_IF_ERROR(
2567 cpl_table_save(poly_tbl, NULL, qc[i], fn, CPL_IO_EXTEND));
2568 }
2569 cpl_free(extname);
2570 eris_ifu_free_table(&poly_tbl);
2571 } // if (poly2d[ii] != NULL)
2572 } // end: i = SLITLET_CNT
2573
2574 cpl_propertylist* ext = cpl_propertylist_new();
2575 extname = cpl_sprintf("SLITLET%2.2d",SLITLET_CNT);
2576 cpl_propertylist_append_string(ext,"EXTNAME",extname);
2577 // save minmax borders as well
2578 BRK_IF_ERROR(
2579 cpl_table_save(minmax_borders, NULL, ext, fn, CPL_IO_EXTEND));
2580 cpl_propertylist_delete(ext);
2581 cpl_free(extname);
2582 }
2583 CATCH
2584 {
2585 CATCH_MSGS();
2586 err = cpl_error_get_code();
2587 }
2588
2589 return err;
2590}
2591
2592hdrl_image* eris_ifu_dist_warp_image_full(const hdrl_image *hdrl_img_in,
2593 cpl_polynomial **poly_u,
2594 int productDepth)
2595{
2596 cpl_size pows[2];
2597 cpl_image *img_warped = NULL,
2598 *img_warped_extr = NULL;
2599 hdrl_image *hdrl_img_warped = NULL,
2600 *hdrl_img_warped_extr = NULL;
2601 cpl_polynomial *poly_v = NULL;
2602 char *fn = NULL;
2603
2604 cpl_ensure(hdrl_img_in, CPL_ERROR_NULL_INPUT, NULL);
2605 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2606
2607 TRY
2608 {
2609 BRK_IF_NULL(
2610 poly_v = cpl_polynomial_new(2));
2611
2612 pows[0] = 0;
2613 pows[1] = 0;
2614 BRK_IF_ERROR(
2615 cpl_polynomial_set_coeff(poly_v, pows, 0.0));
2616 pows[0] = 0;
2617 pows[1] = 1;
2618 BRK_IF_ERROR(
2619 cpl_polynomial_set_coeff(poly_v, pows, 1.0));
2620
2621 BRK_IF_NULL(
2622 hdrl_img_warped = hdrl_image_new(hdrl_image_get_size_x(hdrl_img_in),
2623 hdrl_image_get_size_y(hdrl_img_in)));
2624
2625 BRK_IF_NULL(
2626 img_warped = hdrl_image_get_image(hdrl_img_warped));
2627
2628 for (int i = 0; i < SLITLET_CNT; i++) {
2629 if (poly_u[i] != NULL) {
2630// cpl_msg_info(cpl_func, "Warp slitlet #%02d", i+1);
2631
2632 BRK_IF_NULL(
2633 hdrl_img_warped_extr = eris_ifu_warp_polynomial_image(hdrl_img_in,
2634 poly_u[i], poly_v));
2635
2636 // target left + right edge
2637 int t_l = eris_ifu_distortion_target_left_edge(i),
2638 t_r = eris_ifu_distortion_target_right_edge(i);
2639 BRK_IF_NULL(
2640 img_warped_extr = hdrl_image_get_image(hdrl_img_warped_extr));
2641
2642 if (productDepth & 8) {
2643 // save warped intermediate images uncut
2644 fn = cpl_sprintf("eris_ifu_distortion_dbg_warp_out_%02d.fits", i+1);
2645 BRK_IF_ERROR(
2646 eris_ifu_save_image_dbg(img_warped_extr, fn,
2647 CPL_IO_CREATE, NULL));
2648 }
2649
2650 if (i != 0) {
2651 // set to zero left of slitlet (except for first slitlet)
2652 BRK_IF_ERROR(
2653 cpl_image_fill_window(img_warped_extr, 1, 1, t_l,
2654 ERIS_IFU_DETECTOR_SIZE_Y, 0.));
2655 }
2656 if (i != SLITLET_CNT-1) {
2657 // set to zero right of slitlet (except for last slitlet)
2658 BRK_IF_ERROR(
2659 cpl_image_fill_window(img_warped_extr, t_r+2, 1,
2660 ERIS_IFU_DETECTOR_SIZE_X,
2661 ERIS_IFU_DETECTOR_SIZE_Y, 0.));
2662 }
2663
2664 if (productDepth & 8) {
2665 // save warped intermediate images cut
2666 BRK_IF_ERROR(
2667 eris_ifu_save_image_dbg(img_warped_extr, fn,
2668 CPL_IO_EXTEND, NULL));
2669 cpl_free(fn); fn = NULL;
2670 }
2671
2672 BRK_IF_ERROR(
2673 cpl_image_add(img_warped, img_warped_extr));
2674
2675 eris_ifu_free_hdrl_image(&hdrl_img_warped_extr);
2676 }
2677 } // end: i = SLITLET_CNT
2678 }
2679 CATCH
2680 {
2681 CATCH_MSGS();
2682 eris_ifu_free_hdrl_image(&hdrl_img_warped);
2683 }
2684
2685 eris_ifu_free_polynomial(&poly_v);
2686
2687 return hdrl_img_warped;
2688}
2689
2690hdrl_image* eris_ifu_dist_warp_slitlet(const hdrl_image *imgIn,
2691 const cpl_polynomial *poly_u,
2692 const cpl_polynomial *poly_v,
2693 double l_min,
2694 double r_max,
2695 int slitletNr)
2696{
2697 int llx = 0,
2698 urx = 0;
2699 hdrl_image *imgOutSlit = NULL,
2700 *imgInSlit = NULL,
2701 *imgOutSlitTrim = NULL;
2702
2703 cpl_ensure(imgIn, CPL_ERROR_NULL_INPUT, NULL);
2704 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2705 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2706
2707
2708 TRY
2709 {
2710 // get left and right nominal border of slitlet
2711 llx = (int)(l_min)+1;
2712 urx = (int)(r_max)+1;
2713
2714 if ((llx > 0) && (urx <= ERIS_IFU_DETECTOR_SIZE_X)) {
2715 BRK_IF_NULL(
2716 imgInSlit = hdrl_image_extract(imgIn,
2717 llx, 1,
2718 urx, ERIS_IFU_DETECTOR_SIZE_Y));
2719 } else {
2720 BRK_IF_NULL(
2721 imgInSlit = hdrl_image_new(urx-llx+1, ERIS_IFU_DETECTOR_SIZE_Y));
2722 // mask all pixel as bad, the good ones will be flagged later
2723 cpl_mask *tmpMask;
2724 BRK_IF_NULL(
2725 tmpMask = cpl_mask_threshold_image_create(
2726 hdrl_image_get_image(imgInSlit),-1,1));
2727 hdrl_image_reject_from_mask(imgInSlit, tmpMask);
2728 cpl_mask_delete(tmpMask);
2729 hdrl_image *tmpImg;
2730 if (llx < 1) {
2731 BRK_IF_NULL(
2732 tmpImg = hdrl_image_extract(imgIn,
2733 1, 1, urx, ERIS_IFU_DETECTOR_SIZE_Y));
2734 int pos1 = -llx + 2;
2735 BRK_IF_ERROR(
2736 hdrl_image_copy(imgInSlit,tmpImg, pos1, 1));
2737 } else {
2738 BRK_IF_NULL(
2739 tmpImg = hdrl_image_extract(imgIn,
2740 llx, 1, ERIS_IFU_DETECTOR_SIZE_X, ERIS_IFU_DETECTOR_SIZE_Y));
2741 BRK_IF_ERROR(
2742 hdrl_image_copy(imgInSlit,tmpImg, 1, 1));
2743 }
2744 eris_ifu_free_hdrl_image(&tmpImg);
2745 }
2746
2747 BRK_IF_NULL(
2748 imgOutSlit = eris_ifu_warp_polynomial_image(imgInSlit,
2749 poly_u, poly_v));
2750
2751 if (hdrl_image_get_size_x(imgOutSlit) > SLITLET_WIDTH) {
2752 // extract left 64 pixels of slitlet (all data to the right is invalid)
2753 BRK_IF_NULL(
2754 imgOutSlitTrim = hdrl_image_extract(imgOutSlit,
2755 1, 1,
2756 SLITLET_WIDTH,
2757 ERIS_IFU_DETECTOR_SIZE_Y));
2758 } else {
2759 // if slitlet is less than 64 pix wide, paste it into a slitlet of 64pix width
2760 cpl_msg_warning(cpl_func, "Slitlet #%d: width only %d pix !!!", slitletNr+1, (int)hdrl_image_get_size_x(imgOutSlit));
2761 BRK_IF_NULL(
2762 imgOutSlitTrim = hdrl_image_new(SLITLET_WIDTH, ERIS_IFU_DETECTOR_SIZE_Y));
2763 // will be aligned to the right side --> better
2764 int offset = SLITLET_WIDTH - (int) hdrl_image_get_size_x(imgOutSlit);
2765 // will be aligned to the left side --> worse
2766 //int offset = 0;
2767 BRK_IF_ERROR(
2768 eris_ifu_image_add_slit(imgOutSlitTrim, imgOutSlit, offset));
2769 }
2770 }
2771 CATCH
2772 {
2773 CATCH_MSGS();
2774 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
2775 }
2776
2777 eris_ifu_free_hdrl_image(&imgOutSlit);
2778 eris_ifu_free_hdrl_image(&imgInSlit);
2779
2780 return imgOutSlitTrim;
2781}
2782
2783hdrl_image* eris_ifu_dist_warp_image(const hdrl_image *imgIn,
2784 cpl_polynomial **poly_u,
2785 const cpl_table *borders)
2786{
2787 int tmp = 0;
2788 cpl_size pows[2];
2789 cpl_polynomial *poly_v = NULL;
2790 hdrl_image *imgOut = NULL,
2791 *imgOutSlitTrim = NULL;
2792
2793 cpl_ensure(imgIn, CPL_ERROR_NULL_INPUT, NULL);
2794 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2795 cpl_ensure(borders, CPL_ERROR_NULL_INPUT, NULL);
2796
2797 TRY
2798 {
2799 BRK_IF_NULL(
2800 poly_v = cpl_polynomial_new(2));
2801 pows[0] = 0; pows[1] = 0;
2802 BRK_IF_ERROR(
2803 cpl_polynomial_set_coeff(poly_v, pows, 0.0));
2804 pows[0] = 0; pows[1] = 1;
2805 BRK_IF_ERROR(
2806 cpl_polynomial_set_coeff(poly_v, pows, 1.0));
2807
2808 BRK_IF_NULL(
2809 imgOut = hdrl_image_new(hdrl_image_get_size_x(imgIn),
2810 hdrl_image_get_size_y(imgIn)));
2811
2812 for (int i = 0; i < SLITLET_CNT; i++) {
2813 if (poly_u[i] != NULL) {
2814// cpl_msg_debug(cpl_func, "Warp slitlet #%02d", i+1);
2815
2816 // Extract, warp and trim slitlet
2817 // (can be parallelized)
2818 BRK_IF_NULL(
2819 imgOutSlitTrim = eris_ifu_dist_warp_slitlet(imgIn,
2820 poly_u[i],
2821 poly_v,
2822 cpl_table_get_double(borders, ERIS_IFU_POLY_EDGE_L, i, &tmp),
2823 cpl_table_get_double(borders, ERIS_IFU_POLY_EDGE_R, i, &tmp),
2824 i));
2825
2826 // add- in slitlet to synthetic full warped image
2827 // (can be parallelized)
2828 BRK_IF_ERROR(
2829 eris_ifu_image_add_slit(imgOut,
2830 imgOutSlitTrim,
2831 eris_ifu_distortion_target_left_edge(i)));
2832
2833 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
2834
2835 }
2836 } // end: i = SLITLET_CNT
2837 }
2838 CATCH
2839 {
2840 CATCH_MSGS();
2841 eris_ifu_free_hdrl_image(&imgOut);
2842 }
2843 eris_ifu_free_polynomial(&poly_v);
2844 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
2845
2846 return imgOut;
2847}
2848
2857hdrl_image* eris_ifu_dist_warp_bpm(const hdrl_image *bpmIn,
2858 cpl_polynomial **poly_u,
2859 const cpl_table *borders,
2860 productDepthType productDepth)
2861{
2862 int tmp = 0;
2863 cpl_size pows[2];
2864 cpl_polynomial *poly_v = NULL;
2865 hdrl_image *bpmOut = NULL,
2866 *imgOutSlitTrim = NULL;
2867
2868 cpl_ensure(bpmIn, CPL_ERROR_NULL_INPUT, NULL);
2869 cpl_ensure(poly_u, CPL_ERROR_NULL_INPUT, NULL);
2870 cpl_ensure(borders, CPL_ERROR_NULL_INPUT, NULL);
2871
2872 /* Create contribution map */
2873 cpl_size size_x = hdrl_image_get_size_x(bpmIn);
2874 cpl_size size_y = hdrl_image_get_size_y(bpmIn);
2875
2876 hdrl_image *col_hmap = hdrl_image_new(size_x, size_y);
2877
2878 //Initialize each pixel to its column number; start from 1.
2879 for (cpl_size i = 1; i <= size_x; i++){
2880 hdrl_value col_num;
2881 col_num.data = i * 1.0;
2882 col_num.error = 0.0;
2883 for (cpl_size j = 1; j <= size_y; j++){
2884 hdrl_image_set_pixel(col_hmap, i, j,col_num);
2885 }
2886 }
2887 if (productDepth >= PD_DEBUG) {
2888 eris_ifu_save_hdrl_image_dbg(col_hmap, "eris_ifu_distortion_dbg_col_hmap", 1, NULL);
2889 }
2890 poly_v = cpl_polynomial_new(2);
2891 pows[0] = 0; pows[1] = 0;
2892 cpl_polynomial_set_coeff(poly_v, pows, 0.0);
2893 pows[0] = 0; pows[1] = 1;
2894 cpl_polynomial_set_coeff(poly_v, pows, 1.0);
2895
2896 /* Warp the contribution map */
2897 hdrl_image *col_hmap_warped = hdrl_image_new(size_x, size_y);
2898 for (int i = 0; i < SLITLET_CNT; i++) {
2899 // Extract, warp and trim slitlet
2900 imgOutSlitTrim = eris_ifu_dist_warp_slitlet(col_hmap,
2901 poly_u[i],
2902 poly_v,
2903 cpl_table_get_double(borders, ERIS_IFU_POLY_EDGE_L, i, &tmp),
2904 cpl_table_get_double(borders, ERIS_IFU_POLY_EDGE_R, i, &tmp),
2905 i);
2906
2907 // add-in slitlet to synthetic full warped image
2908 eris_ifu_image_add_slit(col_hmap_warped,
2909 imgOutSlitTrim,
2910 eris_ifu_distortion_target_left_edge(i));
2911
2912 eris_ifu_free_hdrl_image(&imgOutSlitTrim);
2913
2914 }
2915 hdrl_image_delete(col_hmap);
2916
2917 if (productDepth >= PD_DEBUG) {
2918 eris_ifu_save_hdrl_image_dbg(col_hmap_warped, "eris_ifu_distortion_dbg_col_hmap_warped", 1, NULL);
2919 }
2920
2921 /* Interpolate the bpm according to the contribution*/
2922 // TODO: do this on slitlet-wise, do mask columns beyond l_max, r_max.
2923 bpmOut = hdrl_image_new(size_x, size_y);
2924 int slitwidth = 0;
2925 cpl_size col_n_0 = 0;
2926 /* TODO: AMO: limit the loop to SLITLET_CNT -1 as the last iteration generates infinite loop processing science data */
2927 for (cpl_size k = 0; k < SLITLET_CNT; k++){
2928 if (k + 1 == 1) //slitlet 1
2929 slitwidth = 61;
2930 else if (k + 1 == 2)
2931 slitwidth = 62;
2932 else if (k + 1== 10)
2933 slitwidth = 63;
2934 else
2935 slitwidth = SLITLET_WIDTH;
2936
2937 for (cpl_size y = 1; y <= size_y; y++){
2938 bool fake_col_n_0 = false;
2939 for (cpl_size x = 1; x <= SLITLET_WIDTH; x++){
2940 if (x >= SLITLET_WIDTH/2) {
2941 // We are already at the right side of the slitlet and don't expect that there will
2942 // be any bad pixels/zero- or NaN-values at the left border.
2943 // But there could still be such bad pixels at the right side. In this case we WILL NOT calculate a fake_col_n_0.
2944 // So we set it to true and we will step over the calculation of it
2945 fake_col_n_0 = true;
2946 }
2947 hdrl_value pix_contr = hdrl_image_get_pixel(col_hmap_warped, x+k*SLITLET_WIDTH, y, NULL);
2948 cpl_size col_n = (cpl_size) pix_contr.data;
2949 double contri_n = pix_contr.data - col_n;
2950 if (((pix_contr.data == 0) || hdrl_image_is_rejected(col_hmap_warped, x+k*SLITLET_WIDTH, y)) && !fake_col_n_0) {
2951 col_n = -1;
2952 // try to extrapolate a reasonable col_n_0
2953 // go as log to the right until we get a valid pixel, keep this value
2954 // get the pixel right of this one, subtract and then subtract as often
2955 int g = x+1;
2956 hdrl_value ggg = hdrl_image_get_pixel(col_hmap_warped, g+k*SLITLET_WIDTH, y, NULL);
2957 while (isnan(ggg.data) || (ggg.data == 0)) {
2958 g++;
2959 ggg = hdrl_image_get_pixel(col_hmap_warped, g+k*SLITLET_WIDTH, y, NULL);
2960 }
2961 // go even one more to the right, because the first difference is smaller than the other differences
2962 g++;
2963 ggg = hdrl_image_get_pixel(col_hmap_warped, g+k*SLITLET_WIDTH, y, NULL);
2964 hdrl_value kkk = hdrl_image_get_pixel(col_hmap_warped, (g+1)+k*SLITLET_WIDTH, y, NULL);
2965 double diff = kkk.data - ggg.data;
2966 col_n_0 = ggg.data-(g-1)*diff;
2967 // we had to calculate a fake/estimated col_n_0, set a flag accordingly
2968 fake_col_n_0 = true;
2969 }
2970 if ((x==1) && !fake_col_n_0)
2971 col_n_0 = col_n;
2972 hdrl_value pix_bpm;
2973 if ((col_n < 1) || isnan(contri_n))
2974 {
2975 // either left border
2976 // or pix_contr.data is nan
2977 pix_bpm.data = 1;
2978 pix_bpm.error = 1;
2979 } else if (col_n > ERIS_IFU_DETECTOR_SIZE_X || col_n-col_n_0+1 > slitwidth+2) //right border or right edge
2980 {
2981 pix_bpm.data = 1;
2982 pix_bpm.error = 1;
2983 } else if (col_n == ERIS_IFU_DETECTOR_SIZE_X || col_n-col_n_0+1 == slitwidth+2)
2984 {
2985 pix_bpm.data = hdrl_image_get_pixel(bpmIn, col_n, y, NULL).data * contri_n + 1.0 * (1.0-contri_n);
2986 }
2987 else {
2988 pix_bpm.data = hdrl_image_get_pixel(bpmIn, col_n, y, NULL).data * contri_n +
2989 hdrl_image_get_pixel(bpmIn, col_n+1, y, NULL).data * (1.0-contri_n);
2990 }
2991
2992 hdrl_image_set_pixel(bpmOut, x+k*SLITLET_WIDTH, y, pix_bpm);
2993 }
2994 }
2995 }
2996
2997 hdrl_image_delete(col_hmap_warped);
2998
2999 eris_ifu_free_polynomial(&poly_v);
3000
3001 return bpmOut;
3002}
3003
3004
3016hdrl_imagelist* eris_ifu_stack_warped(const hdrl_image *imgIn,
3017 const int *rowIx)
3018{
3019 cpl_ensure(imgIn, CPL_ERROR_NULL_INPUT, NULL);
3020
3021 int cnt = 0;
3022 double *pImgTmpData = NULL,
3023 *pImgTmpErr = NULL;
3024 const double *pImgInData = NULL,
3025 *pImgInErr = NULL;
3026 hdrl_image *imgTmp = NULL;
3027 hdrl_imagelist *cube = NULL;
3028
3029 TRY
3030 {
3031 BRK_IF_NULL(
3032 cube = hdrl_imagelist_new());
3033
3034 BRK_IF_NULL(
3035 pImgInData = cpl_image_get_data_double_const(hdrl_image_get_image_const(imgIn)));
3036 BRK_IF_NULL(
3037 pImgInErr = cpl_image_get_data_double_const(hdrl_image_get_error_const(imgIn)));
3038
3039
3040 for (int z = 0; z < ERIS_IFU_DETECTOR_SIZE_Y; z++) {
3041 // a slitlet is 64pix wide, but we have only 32 slitlets
3042 // In order to get a square cube, at the end each slitlet is doubled in y-direction...
3043 BRK_IF_NULL(
3044 imgTmp = hdrl_image_new(SLITLET_WIDTH, SLITLET_CNT));
3045 BRK_IF_NULL(
3046 pImgTmpData = cpl_image_get_data_double(hdrl_image_get_image(imgTmp)));
3047 BRK_IF_NULL(
3048 pImgTmpErr = cpl_image_get_data_double(hdrl_image_get_error(imgTmp)));
3049
3050
3051 for (int y = 0; y < SLITLET_CNT; y++) {
3052 for (int x = 0; x < SLITLET_WIDTH; x++) {
3053 pImgTmpData[x+rowIx[y]*SLITLET_WIDTH] = pImgInData[cnt++];
3054 }
3055 }
3056 BRK_IF_ERROR(
3057 hdrl_imagelist_set(cube, imgTmp, z));
3058 }
3059 }
3060 CATCH
3061 {
3062 CATCH_MSGS();
3063 eris_ifu_free_hdrl_imagelist(&cube);
3064 }
3065
3066 return cube;
3067}
3068
3077cpl_error_code eris_ifu_dist_warp_stats(const hdrl_image *hdrlWarpedImg,
3078 cpl_propertylist *qc_list,
3079 cpl_propertylist *pl,
3080 cpl_frameset* frameset,
3081 const cpl_parameterlist* parlist)
3082{
3083 int nr_values = 21, //odd
3084 height = 90, //even
3085 center_y = 0,
3086 actual_size = 0,
3087// ix_middle = nr_values / 2 + 1;
3088 ix_middle = 9;
3089 const double *pfit_centers = NULL;
3090 cpl_error_code err = CPL_ERROR_NONE;
3091 cpl_vector *profile_x = NULL,
3092 *est_centers = NULL,
3093 *fit_centers = NULL,
3094 *fit_centers_middle = NULL;
3095 const cpl_image *warpedImg = NULL;
3096 cpl_table **arr = NULL;
3097 cpl_propertylist *pl_my = NULL;
3098 double swidth = 64;
3099 cpl_ensure_code(hdrlWarpedImg, CPL_ERROR_NULL_INPUT);
3100 cpl_ensure_code(qc_list, CPL_ERROR_NULL_INPUT);
3101 cpl_ensure_code(pl, CPL_ERROR_NULL_INPUT);
3102 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
3103 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
3104
3105 TRY
3106 {
3107 BRK_IF_NULL(
3108 arr = cpl_calloc(SLITLET_CNT, sizeof(cpl_table*)));
3109
3110 BRK_IF_NULL(
3111 warpedImg = hdrl_image_get_image_const(hdrlWarpedImg));
3112
3113 // find out number of fibre-tarces per slitlet (one or three)
3114 center_y = ERIS_IFU_DETECTOR_BP_BORDER + ix_middle*height + height/2;
3115 BRK_IF_NULL(
3116 profile_x = eris_ifu_calc_centers_collapse_chunk(
3117 warpedImg, center_y, height));
3118//AA: evtl instead of CPL_FALSE put in (isK & !is25mas)
3119 BRK_IF_NULL(
3120 est_centers = eris_ifu_dist_calc_centers_profile(profile_x, CPL_FALSE));
3121 // will return a vector with 32 or 3*32 center values (errors are catched)
3122 BRK_IF_NULL(
3123 fit_centers_middle = eris_ifu_dist_calc_centers_fit(
3124 profile_x, est_centers, CPL_TRUE));
3125 actual_size = (int) cpl_vector_get_size(est_centers);
3126 eris_ifu_free_vector(&profile_x);
3127 eris_ifu_free_vector(&est_centers);
3128
3129 // create table to hold values
3130 if (actual_size <= SLITLET_CNT) {
3131 for (int i = 0; i < SLITLET_CNT; i++) {
3132 arr[i] = cpl_table_new(nr_values);
3133 cpl_table_new_column(arr[i], "c", CPL_TYPE_DOUBLE);
3134 cpl_table_new_column(arr[i], "left", CPL_TYPE_DOUBLE);
3135 cpl_table_new_column(arr[i], "right", CPL_TYPE_DOUBLE);
3136 }
3137 } else {
3138 for (int i = 0; i < SLITLET_CNT; i++) {
3139 arr[i] = cpl_table_new(nr_values);
3140 cpl_table_new_column(arr[i], "c_l", CPL_TYPE_DOUBLE);
3141 cpl_table_new_column(arr[i], "c", CPL_TYPE_DOUBLE);
3142 cpl_table_new_column(arr[i], "c_r", CPL_TYPE_DOUBLE);
3143 cpl_table_new_column(arr[i], "r_l", CPL_TYPE_DOUBLE);
3144 cpl_table_new_column(arr[i], "c_l/r_l", CPL_TYPE_DOUBLE);
3145 cpl_table_new_column(arr[i], "left", CPL_TYPE_DOUBLE);
3146 cpl_table_new_column(arr[i], "right", CPL_TYPE_DOUBLE);
3147
3148 cpl_table_new_column(arr[i], "slitlet_tl", CPL_TYPE_DOUBLE);
3149 cpl_table_new_column(arr[i], "slitlet_tc", CPL_TYPE_DOUBLE);
3150 cpl_table_new_column(arr[i], "slitlet_tr", CPL_TYPE_DOUBLE);
3151 }
3152 }
3153
3154 // now do the same for the whole detectors in two blocks
3155 // center to top and center to bottom
3156 CHECK_ERROR_STATE();
3157 est_centers = cpl_vector_duplicate(fit_centers_middle);
3158 for (int j = ix_middle; j < nr_values; j++) {
3159 center_y = ERIS_IFU_DETECTOR_BP_BORDER + j*height + height/2;
3160 /* collapse image in y and convert to vector */
3161 profile_x = eris_ifu_calc_centers_collapse_chunk(warpedImg, center_y,
3162 height);
3163 /* do least square fit using a Gaussian in order to get exact centers */
3164 fit_centers = eris_ifu_dist_calc_centers_fit(profile_x, est_centers,
3165 CPL_FALSE);
3166
3167 /* copy values into table */
3168 actual_size = (int) cpl_vector_get_size(fit_centers);
3169 pfit_centers = cpl_vector_get_data_const(fit_centers);
3170
3171 if (actual_size == SLITLET_CNT) {
3172 // one trace per slitlet
3173 for (int i = 0; i < actual_size; i++) {
3174 cpl_table_set_double(arr[i], "c", j, pfit_centers[i]);
3175 if (i > 0) {
3176 cpl_table_set_double(arr[i], "left", j, (i-1) * swidth);
3177 cpl_table_set_double(arr[i], "left", j, i * swidth);
3178 }
3179 }
3180 } else {
3181 // three traces per slitlet
3182 int ii = 0;
3183 for (int i = 0; i < actual_size; i+=3) {
3184 if (i >= 3*SLITLET_CNT) {
3185 cpl_msg_warning(cpl_func, "Detected more than 96 traces (%d). Please check output!", actual_size);
3186 } else {
3187 cpl_table_set_double(arr[ii], "left", j, ii * swidth);
3188 cpl_table_set_double(arr[ii], "right", j, (ii+1) * swidth);
3189 cpl_table_set_double(arr[ii], "c_l", j, pfit_centers[i+1]-ii * swidth);
3190 cpl_table_set_double(arr[ii], "c", j, pfit_centers[i+1]);
3191 cpl_table_set_double(arr[ii], "c_r", j, (ii+1) * swidth - pfit_centers[i+1]);
3192 cpl_table_set_double(arr[ii], "r_l", j, swidth);
3193 cpl_table_set_double(arr[ii], "c_l/r_l", j,
3194 (pfit_centers[i+1]-ii * swidth)/swidth);
3195 /* OLD code */
3196 cpl_table_set_double(arr[ii], "slitlet_tl", j, pfit_centers[i]);
3197 cpl_table_set_double(arr[ii], "slitlet_tc", j, pfit_centers[i+1]);
3198 cpl_table_set_double(arr[ii], "slitlet_tr", j, pfit_centers[i+2]);
3199 /* end old code */
3200 ii++;
3201 }
3202 }
3203 }
3204 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
3205 eris_ifu_free_vector(&profile_x);
3206 eris_ifu_free_vector(&fit_centers);
3207 }
3208
3209 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers_middle));
3210 for (int j = ix_middle-1; j >= 0; j--) {
3211 center_y = ERIS_IFU_DETECTOR_BP_BORDER + j*height + height/2;
3212 /* collapse image in y and convert to vector */
3213 BRK_IF_NULL(
3214 profile_x = eris_ifu_calc_centers_collapse_chunk(
3215 warpedImg, center_y, height));
3216 /* do least square fit using a Gaussian in order to get exact centers */
3217 BRK_IF_NULL(
3218 fit_centers = eris_ifu_dist_calc_centers_fit(profile_x, est_centers, CPL_FALSE));
3219
3220 BRK_IF_NULL(
3221 pfit_centers = cpl_vector_get_data_const(fit_centers));
3222
3223 /* copy values into table */
3224 if (actual_size == SLITLET_CNT) {
3225 // one trace per slitlet
3226 for (int i = 0; i < actual_size; i++) {
3227 cpl_table_set_double(arr[i], "c", j, pfit_centers[i]);
3228 }
3229 } else {
3230 // three traces per slitlet
3231 int ii = 0;
3232 for (int i = 0; i < actual_size; i+=3) {
3233 if (i >= 3*SLITLET_CNT) {
3234 cpl_msg_warning(cpl_func, "Detected more than 96 traces (%d). Please check output!", actual_size);
3235 } else {
3236 cpl_table_set_double(arr[ii], "left", j, ii * swidth);
3237 cpl_table_set_double(arr[ii], "right", j, (ii+1) * swidth);
3238 cpl_table_set_double(arr[ii], "c_l", j, pfit_centers[i+1]-ii * swidth);
3239 cpl_table_set_double(arr[ii], "c", j, pfit_centers[i+1]);
3240 cpl_table_set_double(arr[ii], "c_r", j, (ii+1) * swidth - pfit_centers[i+1]);
3241 cpl_table_set_double(arr[ii], "r_l", j, swidth);
3242 cpl_table_set_double(arr[ii], "c_l/r_l", j,
3243 (pfit_centers[i+1]-ii * swidth) / swidth);
3244
3245 /* OLD code */
3246 cpl_table_set_double(arr[ii], "slitlet_tl", j, pfit_centers[i]);
3247 cpl_table_set_double(arr[ii], "slitlet_tc", j, pfit_centers[i+1]);
3248 cpl_table_set_double(arr[ii], "slitlet_tr", j, pfit_centers[i+2]);
3249 /* end old code */
3250 ii++;
3251 }
3252 }
3253 }
3254 BRK_IF_ERROR(cpl_vector_copy(est_centers, fit_centers));
3255 eris_ifu_free_vector(&profile_x);
3256 eris_ifu_free_vector(&fit_centers);
3257
3258 }
3259
3260 char* extname;
3261 char* keyname;
3262 char* keycomm;
3263
3264 // Save warped image as final product
3265 cpl_propertylist_append_string(pl, CPL_DFS_PRO_CATG,
3266 ERIS_IFU_PRO_DIST_DBG_WARPED_FIT);
3267 cpl_propertylist_set_string(pl,"PIPEFILE",
3268 ERIS_IFU_PRO_DIST_QC_WARPED_FIT_FN);
3269 cpl_propertylist_save(pl, ERIS_IFU_PRO_DIST_QC_WARPED_FIT_FN,
3270 CPL_IO_CREATE);
3271
3272 eris_setup_product_header(ERIS_IFU_PRO_DIST_QC_WARPED_FIT_FN,
3273 ERIS_IFU_PRO_DIST_DBG_WARPED_FIT, CPL_FRAME_TYPE_TABLE,
3274 "eris_ifu_distortion", frameset, parlist, pl);
3275
3276
3277
3278
3279 for (int i = 0; i < SLITLET_CNT; i++) {
3280
3281 BRK_IF_NULL(
3282 pl_my = cpl_propertylist_new());
3283 extname = cpl_sprintf("SLITLET%2.2d",i);
3284 cpl_propertylist_append_string(pl_my,"EXTNAME",extname);
3285// if (cpl_table_get_ncol(arr[i]) == 1) {
3286 if (actual_size <= SLITLET_CNT) {
3287 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C STDEV",i);
3288 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "c"));
3289 keycomm = cpl_sprintf("[pix] center stdev");
3290 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3291 cpl_free(keyname);
3292 cpl_free(keycomm);
3293
3294
3295 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C MEDIAN",i);
3296 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "c"));
3297 keycomm = cpl_sprintf("[pix] center median");
3298 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3299 cpl_free(keyname);
3300 cpl_free(keycomm);
3301 } else {
3302 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-L STDEV",i);
3303 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "r_l"));
3304 keycomm = cpl_sprintf("[pix] center-left stdev");
3305 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3306 cpl_free(keyname);
3307 cpl_free(keycomm);
3308
3309 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-L MEDIAN",i);
3310 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "r_l"));
3311 keycomm = cpl_sprintf("[pix] center-left median");
3312 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3313 cpl_free(keyname);
3314 cpl_free(keycomm);
3315
3316 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-L STDEV",i);
3317 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "c_l"));
3318 keycomm = cpl_sprintf("[pix] center stdev");
3319 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3320 cpl_free(keyname);
3321 cpl_free(keycomm);
3322
3323 keyname = cpl_sprintf("ESO QC SLITLET%2.2d C-L MEDIAN",i);
3324 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "c_l"));
3325 keycomm = cpl_sprintf("[pix] center median");
3326 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3327 cpl_free(keyname);
3328 cpl_free(keycomm);
3329
3330 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-C STDEV",i);
3331 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "c_r"));
3332 keycomm = cpl_sprintf("[pix] center-right stdev");
3333 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3334 cpl_free(keyname);
3335 cpl_free(keycomm);
3336
3337 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TL MEDIAN",i);
3338 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "slitlet_tl"));
3339 keycomm = cpl_sprintf("[pix] trace left median");
3340 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3341 cpl_free(keyname);
3342 cpl_free(keycomm);
3343
3344 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TL STDEV",i);
3345 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "slitlet_tl"));
3346 keycomm = cpl_sprintf("[pix] trace left stdev");
3347 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3348 cpl_free(keyname);
3349 cpl_free(keycomm);
3350
3351 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TC MEDIAN",i);
3352 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "slitlet_tc"));
3353 keycomm = cpl_sprintf("[pix] trace center median");
3354 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3355 cpl_free(keyname);
3356 cpl_free(keycomm);
3357
3358 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TC STDEV",i);
3359 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "slitlet_tc"));
3360 keycomm = cpl_sprintf("[pix] trace center stdev");
3361 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3362 cpl_free(keyname);
3363 cpl_free(keycomm);
3364
3365 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TR MEDIAN",i);
3366 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "slitlet_tr"));
3367 keycomm = cpl_sprintf("[pix] trace right median");
3368 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3369 cpl_free(keyname);
3370 cpl_free(keycomm);
3371
3372 keyname = cpl_sprintf("ESO QC SLITLET%2.2d TR STDEV",i);
3373 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_stdev(arr[i], "slitlet_tr"));
3374 keycomm = cpl_sprintf("[pix] trace right stdev");
3375 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3376 cpl_free(keyname);
3377 cpl_free(keycomm);
3378
3379 keyname = cpl_sprintf("ESO QC SLITLET%2.2d CL_RL FRAC",i);
3380 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "c_l/r_l"));
3381 keycomm = cpl_sprintf("(center-left)/(right-left) ratio");
3382 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3383 cpl_free(keyname);
3384 cpl_free(keycomm);
3385
3386 keyname = cpl_sprintf("ESO QC SLITLET%2.2d R-C MEDIAN",i);
3387 cpl_propertylist_append_double(pl_my, keyname, cpl_table_get_column_median(arr[i], "c_r"));
3388 keycomm = cpl_sprintf("[pix] center-right median");
3389 cpl_propertylist_set_comment(pl_my,keyname,keycomm);
3390 cpl_free(keyname);
3391 cpl_free(keycomm);
3392
3393
3394 }
3395
3396 BRK_IF_ERROR(
3397 cpl_table_save(arr[i], NULL, pl_my,
3398 ERIS_IFU_PRO_DIST_QC_WARPED_FIT_FN,
3399 CPL_IO_EXTEND));
3400 eris_ifu_free_propertylist(&pl_my);
3401 cpl_free(extname);
3402 }
3403 }
3404 CATCH
3405 {
3406 CATCH_MSGS();
3407 err = cpl_error_get_code();
3408 }
3409
3410 for (int i = 0; i < SLITLET_CNT; i++) {
3411 eris_ifu_free_table(&arr[i]);
3412 }
3413 cpl_free(arr); arr = NULL;
3414 eris_ifu_free_vector(&profile_x);
3415 eris_ifu_free_vector(&est_centers);
3416 eris_ifu_free_vector(&fit_centers);
3417 eris_ifu_free_vector(&fit_centers_middle);
3418 eris_ifu_free_propertylist(&pl_my);
3419 eris_check_error_code("eris_ifu_dist_warp_stats");
3420 return err;
3421}
3422
3432cpl_error_code eris_ifu_image_add_slit(hdrl_image *hdrlImgFull,
3433 const hdrl_image *hdrlImgSlit,
3434 int offset)
3435{
3436 cpl_error_code err = CPL_ERROR_NONE;
3437 cpl_image *tmpImgFull = NULL;
3438 const cpl_image *tmpImgSlit = NULL;
3439 cpl_mask *tmpMaskFull = NULL;
3440 const cpl_mask *tmpMaskSlit = NULL;
3441 double *pimgFullData = NULL,
3442 *pimgFullErr = NULL;
3443 const double *pimgSlitData = NULL,
3444 *pimgSlitErr = NULL;
3445 cpl_binary *pimgFullMask = NULL;
3446 const cpl_binary *pimgSlitMask = NULL;
3447 int widthFull = 0,
3448 widthSlit = 0;
3449
3450 cpl_ensure_code(hdrlImgFull, CPL_ERROR_NULL_INPUT);
3451 cpl_ensure_code(hdrlImgSlit, CPL_ERROR_NULL_INPUT);
3452 cpl_ensure_code(hdrl_image_get_size_y(hdrlImgFull) == ERIS_IFU_DETECTOR_SIZE_Y,
3453 CPL_ERROR_ILLEGAL_INPUT);
3454 cpl_ensure_code(hdrl_image_get_size_y(hdrlImgSlit) == ERIS_IFU_DETECTOR_SIZE_Y,
3455 CPL_ERROR_ILLEGAL_INPUT);
3456 cpl_ensure_code(hdrl_image_get_size_x(hdrlImgFull) >= hdrl_image_get_size_x(hdrlImgSlit),
3457 CPL_ERROR_ILLEGAL_INPUT);
3458 cpl_ensure_code(offset >= 0, CPL_ERROR_ILLEGAL_INPUT);
3459
3460 TRY
3461 {
3462 tmpImgFull = hdrl_image_get_image(hdrlImgFull);
3463 tmpMaskFull = cpl_image_get_bpm(tmpImgFull);
3464 BRK_IF_NULL(
3465 pimgFullData = cpl_image_get_data(tmpImgFull));
3466 BRK_IF_NULL(
3467 pimgFullErr = cpl_image_get_data(hdrl_image_get_error(hdrlImgFull)));
3468 if (tmpMaskFull != NULL) {
3469 BRK_IF_NULL(
3470 pimgFullMask = cpl_mask_get_data(tmpMaskFull));
3471 }
3472 widthFull = (int) hdrl_image_get_size_x(hdrlImgFull);
3473
3474 tmpImgSlit = hdrl_image_get_image_const(hdrlImgSlit);
3475 tmpMaskSlit = cpl_image_get_bpm_const(tmpImgSlit);
3476 BRK_IF_NULL(
3477 pimgSlitData = cpl_image_get_data_const(tmpImgSlit));
3478 BRK_IF_NULL(
3479 pimgSlitErr = cpl_image_get_data_const(hdrl_image_get_error_const(hdrlImgSlit)));
3480 if (tmpMaskSlit != NULL) {
3481 BRK_IF_NULL(
3482 pimgSlitMask = cpl_mask_get_data_const(tmpMaskSlit));
3483 }
3484
3485 widthSlit = (int) hdrl_image_get_size_x(hdrlImgSlit);
3486
3487 for (int y = 0; y < ERIS_IFU_DETECTOR_SIZE_Y; y++) {
3488 for (int x = 0; x < widthSlit; x++) {
3489 pimgFullData[x+offset+y*widthFull] = pimgSlitData[x+y*widthSlit];
3490 pimgFullErr[x+offset+y*widthFull] = pimgSlitErr[x+y*widthSlit];
3491 if ((tmpMaskFull != NULL) && (tmpMaskSlit != NULL)) {
3492 pimgFullMask[x+offset+y*widthFull] = pimgSlitMask[x+y*widthSlit];
3493 }
3494 }
3495 }
3496 }
3497 CATCH
3498 {
3499 CATCH_MSGS();
3500 err = cpl_error_get_code();
3501 }
3502
3503 return err;
3504}
3505
3516cpl_table** eris_ifu_dist_calc_slitpos(cpl_image **arcImg,
3517 cpl_table **centers_array,
3518 cpl_table *valid_arc_lines,
3519 int productDepth,
3520 cpl_boolean *cut_off_left,
3521 cpl_boolean *cut_off_right,
3522 const cpl_frameset* frameset,
3523 const cpl_parameterlist* parlist)
3524{
3525 int max_lines = 200,
3526 middle = 0,
3527 half_height =0,
3528 urx, ury, llx, lly = 0;
3529// max_pos = 0;
3530 double arc_center = 0.,
3531 percentage = 0.,
3532// cut_level = 0.,
3533// max = -DBL_MAX,
3534 median = 0,
3535 stddev = 0.,
3536// *pprofile_y = NULL,
3537 *pleft_edge_tmp = NULL,
3538 *pright_edge_tmp= NULL,
3539 *pypos_tmp = NULL,
3540 *pleft_edge = NULL,
3541 *pright_edge = NULL,
3542 *pypos = NULL;
3543 char *extname = NULL;
3544 const char *fn = "eris_ifu_distortion_dbg_slitpos_slit_width.fits";
3545 const char *fnx = "eris_ifu_distortion_dbg_slitpos_profile_xy.fits";
3546// cpl_boolean cut_off_fully = CPL_FALSE;
3547 cpl_image *profile_x = NULL;
3548// *img_data = NULL;
3549 cpl_table **tbl = NULL,
3550 *valid_arc_lines_slitlet = NULL;
3551 cpl_vector *left_edge_tmp = NULL,
3552 *right_edge_tmp = NULL,
3553 *ypos_tmp = NULL,
3554 *left_edge = NULL,
3555 *right_edge = NULL,
3556 *ypos = NULL;
3557 cpl_propertylist *pl_tbl = NULL;
3558 eris_ifu_vector *slit_width = NULL,
3559 *slit_width_rej = NULL,
3560 *left_edge_rej = 0,
3561 *right_edge_rej = 0;
3562
3563 cpl_ensure(arcImg, CPL_ERROR_NULL_INPUT, NULL);
3564 cpl_ensure(*centers_array, CPL_ERROR_NULL_INPUT, NULL);
3565
3566 TRY
3567 {
3568 *cut_off_right = FALSE;
3569 *cut_off_right = FALSE;
3570
3571 BRK_IF_NULL(
3572 left_edge_tmp = cpl_vector_new(max_lines));
3573 BRK_IF_NULL(
3574 right_edge_tmp = cpl_vector_new(max_lines));
3575 BRK_IF_NULL(
3576 ypos_tmp = cpl_vector_new(max_lines));
3577
3578 BRK_IF_NULL(
3579 pleft_edge_tmp = cpl_vector_get_data(left_edge_tmp));
3580 BRK_IF_NULL(
3581 pright_edge_tmp = cpl_vector_get_data(right_edge_tmp));
3582 BRK_IF_NULL(
3583 pypos_tmp = cpl_vector_get_data(ypos_tmp));
3584
3585 /* write empty header */
3586 cpl_frameset* fs = (cpl_frameset*) frameset;
3587 char* pipe_id = cpl_sprintf("%s%s%s", PACKAGE, "/", PACKAGE_VERSION);
3588 cpl_propertylist *applist = cpl_propertylist_new();
3589 cpl_propertylist_update_string(applist, CPL_DFS_PRO_CATG,
3590 ERIS_IFU_PRO_DIST_SLIT_POS);
3591 cpl_dfs_save_propertylist(fs, NULL, parlist, frameset, NULL,
3592 REC_NAME_DISTORTION, applist, NULL, pipe_id,
3593 ERIS_IFU_PRO_DIST_SLIT_POS_FN);
3594 cpl_propertylist_delete(applist);
3595 cpl_free(pipe_id);
3596 CHECK_ERROR_STATE();
3597 // BRK_IF_ERROR(
3598 // cpl_propertylist_save(pl_tbl, ERIS_IFU_PRO_DIST_SLIT_POS_FN, CPL_IO_CREATE));
3599
3600 BRK_IF_NULL(
3601 tbl = cpl_calloc(SLITLET_CNT, sizeof(cpl_table*)));
3602
3603 if (productDepth & 8) {
3604 eris_ifu_save_image_dbg(NULL, fn, CPL_IO_CREATE, NULL);
3605 eris_ifu_save_image_dbg(NULL, fnx, CPL_IO_CREATE, NULL);
3606 }
3607 /* loop all slitlets */
3608 for (int i = 0; i < SLITLET_CNT; i++) {
3609 cpl_msg_debug(cpl_func, "i: %d", i);
3610 int ttt = 0;
3611 // take middle value from "x"
3612 middle = (int) cpl_table_get_nrow(centers_array[i])/2;
3613 arc_center = cpl_table_get_double(centers_array[i], "x", middle, &ttt);
3614 CHECK_ERROR_STATE();
3615
3616 if ((productDepth & 3) != 0) {
3617 cpl_msg_debug(cpl_func, " Slitlet #%i: center pos: %g", i+1,
3618 arc_center);
3619 }
3620
3621 /* extract list of valid lines */
3622 if (valid_arc_lines != NULL) {
3623 cpl_table_unselect_all(valid_arc_lines);
3624 cpl_table_or_selected_int(valid_arc_lines, ERIS_IFU_FITTABLE_SLITLET, CPL_EQUAL_TO, i);
3625 valid_arc_lines_slitlet = cpl_table_extract_selected(valid_arc_lines);
3626 }
3627 /* loop all lines (brighter than a tenth of the brightest line)
3628 * in vertical profile and detect edges */
3629 int y = 0,
3630 arcImgIx = 0,
3631 nr_lines = 0;
3632// while (y < ERIS_IFU_DETECTOR_SIZE_Y) {
3633 for (int iii = 0; iii < cpl_table_get_nrow(valid_arc_lines_slitlet); iii++) {
3634// AA simplify all this!
3635 y = (int) ( 0.5 + cpl_table_get_double(
3636 valid_arc_lines_slitlet, "x0", iii, NULL));
3637 arcImgIx = cpl_table_get_int(
3638 valid_arc_lines_slitlet, "imgIdx", iii, NULL);
3639// if (pprofile_y[y] > cut_level) {
3640 pypos_tmp[nr_lines] = y;
3641
3642 /* create horizontal profile at bright line
3643 * (height ~5pix, width 64 + 15pix left and right) */
3644 llx = (int) (arc_center+0.5) -64/2-25+1,
3645 urx = (int) (arc_center+0.5) +64/2+25+1;
3646//AA check if better for bad Lines
3647 {
3648 //old
3649 // int half_height = 3 / 2;
3650 half_height = 5 / 2,
3651 lly = y - half_height + 1,
3652 ury = y + half_height + 1;
3653 // y ist the first value, that is above the threshold
3654 //HIER in y gaussfit, evtl am besten entlang llx-urx
3655
3656 if (llx < 1)
3657 llx = 1;
3658 if (urx > 2048)
3659 urx = 2048;
3660
3661 BRK_IF_NULL(
3662 profile_x = cpl_image_collapse_window_create(arcImg[arcImgIx],
3663 llx, lly,
3664 urx, ury, 0));
3665 }
3666// {//new
3667// // identify actual ypos in valid_lines2
3668// int valid_line = 0;
3669// if (a > 0) {
3670// valid_line = y;
3671// } else if (b > 0){
3672// valid_line = y+1;
3673// }
3674//
3675// // get leftmost and rightmost column of this slitlet
3676// cpl_table_unselect_all(valid_arc_lines_slitlet);
3677// cpl_table_or_selected_int(valid_arc_lines_slitlet, ERIS_IFU_FITTABLE_POSITION, CPL_EQUAL_TO, valid_line);
3679//
3682//
3683//
3684// // get the according y-values
3685//
3686// // create a line accross the detector from llx to urx
3687//
3688// // create a profile in a way that +/-3or5 pix vertically around the line are averaged and put into profile_x
3689// }
3690
3691 cpl_error_code status = eris_ifu_slitpos_gauss(
3692 profile_x,
3693 &(pleft_edge_tmp[nr_lines]),
3694 &(pright_edge_tmp[nr_lines]),
3695 llx-1,
3696 productDepth);
3697 if (status == CPL_ERROR_EOL) {
3698 RECOVER();
3699 }
3700
3701 pleft_edge_tmp[nr_lines] -= 1.;
3702 pright_edge_tmp[nr_lines] -= 1.;
3703
3704 if (productDepth & 8) {
3705 cpl_propertylist *pl_line = NULL;
3706 BRK_IF_NULL(
3707 pl_line = cpl_propertylist_new());
3708 extname = cpl_sprintf("Sx_%02d Lx_%02d", i+1, nr_lines+1);
3709 cpl_propertylist_append_string(pl_line, "EXTNAME", extname);
3710 eris_ifu_free_string(&extname);
3711 cpl_propertylist_append_double(pl_line, "lineypos", y);
3712 cpl_propertylist_append_double(pl_line, "llx", llx);
3713 cpl_propertylist_append_double(pl_line, "lly", lly);
3714 cpl_propertylist_append_double(pl_line, "urx", urx);
3715 cpl_propertylist_append_double(pl_line, "ury", ury);
3716 cpl_propertylist_append_double(pl_line, "edge_l", pleft_edge_tmp[nr_lines]);
3717 cpl_propertylist_append_double(pl_line, "edge_r", pright_edge_tmp[nr_lines]);
3718 eris_ifu_save_image_dbg(profile_x, fnx, CPL_IO_EXTEND, pl_line);
3719 eris_ifu_free_propertylist(&pl_line);
3720 }
3721 eris_ifu_free_image(&profile_x);
3722
3723 if (status == CPL_ERROR_EOL) {
3724 continue;
3725 } else if (status != CPL_ERROR_NONE) {
3726 ERIS_IFU_TRY_EXIT();
3727 }
3728 nr_lines++;
3729 if (nr_lines >= max_lines) {
3730 SET_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
3731 "more than 100 lines detected!");
3732/*erw
3733 // double est_pos = pleft_edge[nr_lines] + (pright_edge[nr_lines]-pleft_edge[nr_lines])/2.0;
3734 // cpl_msg_debug(cpl_func, " left_pos: %g, right_pos: %g", pleft_edge[nr_lines], pright_edge[nr_lines]);
3735 // cpl_msg_debug(cpl_func, " est. pos: %g", est_pos);
3736 // // this is the eff. offset from slitlet center to fibre-center
3737 // cpl_msg_debug(cpl_func, " diff: %g", arc_center-est_pos);
3738
3739 eris_ifu_free_image(&profile_x);
3740
3741 // get off surroundings of already processed line
3742 y+=5;
3743 // found line
3744 nr_lines++;
3745 if (nr_lines >= max_lines) {
3746 SET_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
3747 "more than 100 lines detected!");
3748*/
3749 }
3750
3751// } // end: if detected line
3752// y++;
3753 } // end: while y
3754
3755 eris_ifu_free_table(&valid_arc_lines_slitlet);
3756
3757 /* cut vectors to their correct length */
3758 BRK_IF_NULL(
3759 left_edge = cpl_vector_extract(left_edge_tmp, 0, nr_lines-1, 1));
3760 BRK_IF_NULL(
3761 right_edge = cpl_vector_extract(right_edge_tmp, 0, nr_lines-1, 1));
3762 BRK_IF_NULL(
3763 ypos = cpl_vector_extract(ypos_tmp, 0, nr_lines-1, 1));
3764 BRK_IF_NULL(
3765 pleft_edge = cpl_vector_get_data(left_edge));
3766 BRK_IF_NULL(
3767 pright_edge = cpl_vector_get_data(right_edge));
3768 BRK_IF_NULL(
3769 pypos = cpl_vector_get_data(ypos));
3770
3771 slit_width = eris_ifu_vector_new(nr_lines);
3772 for (int ty = 0; ty < nr_lines; ty++) {
3773 eris_ifu_vector_set(slit_width, ty, pright_edge[ty]-pleft_edge[ty]);
3774 }
3775
3776 /*
3777 * omit outliers in a multi process step
3778 */
3779 BRK_IF_NULL(
3780 pl_tbl = cpl_propertylist_new());
3781
3782 /* status before rejecting */
3783 median = eris_ifu_vector_get_median(slit_width, ERIS_IFU_ARITHMETIC);
3784 stddev = eris_ifu_vector_get_stdev_median(slit_width);
3785 CHECK_ERROR_STATE();
3786 BRK_IF_ERROR(
3787 cpl_propertylist_append_double(pl_tbl, "bef_med", median));
3788 BRK_IF_ERROR(
3789 cpl_propertylist_append_double(pl_tbl, "bef_sdv", stddev));
3790 cpl_msg_debug(cpl_func, "before: median: %g, stddev: %g", median, stddev);
3791 if (productDepth & 8) {
3792 cpl_propertylist *pl = NULL;
3793 BRK_IF_NULL(
3794 pl = cpl_propertylist_new());
3795 extname = cpl_sprintf("Sx_%02d ypos", i+1);
3796 cpl_propertylist_append_string(pl, "EXTNAME", extname);
3797 eris_ifu_free_string(&extname);
3798 BRK_IF_ERROR(
3799 eris_ifu_save_vector_dbg(ypos, fn, CPL_IO_EXTEND, pl));
3800 extname = cpl_sprintf("Sx_%02d left_edge", i+1);
3801 cpl_propertylist_append_string(pl, "EXTNAME", extname);
3802 eris_ifu_free_string(&extname);
3803 BRK_IF_ERROR(
3804 eris_ifu_save_vector_dbg(left_edge, fn, CPL_IO_EXTEND, pl));
3805 extname = cpl_sprintf("Sx_%02d right_edge", i+1);
3806 cpl_propertylist_append_string(pl, "EXTNAME", extname);
3807 eris_ifu_free_string(&extname);
3808 BRK_IF_ERROR(
3809 eris_ifu_save_vector_dbg(right_edge, fn, CPL_IO_EXTEND, pl));
3810 extname = cpl_sprintf("Sx_%02d slit_width", i+1);
3811 cpl_propertylist_append_string(pl_tbl, "EXTNAME", extname);
3812 eris_ifu_free_string(&extname);
3813 BRK_IF_ERROR(
3814 eris_ifu_vector_save(slit_width, fn, CPL_TYPE_DOUBLE,
3815 pl_tbl, CPL_IO_EXTEND, 70));
3816 eris_ifu_free_propertylist(&pl);
3817 }
3818
3819 BRK_IF_NULL(
3820 left_edge_rej = eris_ifu_vector_create(left_edge));
3821 BRK_IF_NULL(
3822 right_edge_rej = eris_ifu_vector_create(right_edge));
3823 BRK_IF_NULL(
3824 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
3825
3826 if ((median < 58) && (stddev > 3) &&
3827 ((i == 0) || (i == SLITLET_CNT-1)))
3828 {
3829 // median is obviously so wrong, that many values indicate that slitlet is cut off!
3830 // reject values < SLITLET_WIDTH-stddev
3831 for (int ty = 0; ty < nr_lines; ty++) {
3832 double val = eris_ifu_vector_get(slit_width_rej, ty);
3833 if (val < SLITLET_WIDTH-stddev) {
3834 eris_ifu_vector_reject(slit_width_rej, ty);
3835 eris_ifu_vector_reject(left_edge_rej, ty);
3836 eris_ifu_vector_reject(right_edge_rej, ty);
3837 }
3838 }
3839if (eris_ifu_vector_count_non_rejected(slit_width_rej) <= 1) {
3840// cut_off_fully = CPL_TRUE;
3841 eris_ifu_free_ifu_vector(&left_edge_rej);
3842 eris_ifu_free_ifu_vector(&right_edge_rej);
3843 eris_ifu_free_ifu_vector(&slit_width_rej);
3844 BRK_IF_NULL(
3845 left_edge_rej = eris_ifu_vector_create(left_edge));
3846 BRK_IF_NULL(
3847 right_edge_rej = eris_ifu_vector_create(right_edge));
3848 BRK_IF_NULL(
3849 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
3850} else {
3851 median = eris_ifu_vector_get_median(slit_width_rej, ERIS_IFU_ARITHMETIC);
3852 stddev = eris_ifu_vector_get_stdev_median(slit_width_rej);
3853 CHECK_ERROR_STATE();
3854
3855 BRK_IF_ERROR(
3856 cpl_propertylist_append_double(pl_tbl, "med_rej1", median));
3857 BRK_IF_ERROR(
3858 cpl_propertylist_append_double(pl_tbl, "sdv_rej1", stddev));
3859 cpl_msg_debug(cpl_func, "median: %g, stddev: %g", median, stddev);
3860 if (productDepth & 8) {
3861 extname = cpl_sprintf("Sx_%02d slit_width_rej", i+1);
3862 cpl_propertylist_append_string(pl_tbl, "EXTNAME", extname);
3863 eris_ifu_free_string(&extname);
3864 BRK_IF_ERROR(
3865 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl, CPL_IO_EXTEND, 70));
3866 }
3867}
3868 if (i == 0) {
3869 *cut_off_left = CPL_TRUE;
3870 BRK_IF_ERROR(
3871 cpl_propertylist_append_string(pl_tbl, "cutoff", "left"));
3872 }
3873 if (i == SLITLET_CNT-1) {
3874 *cut_off_right = CPL_TRUE;
3875 BRK_IF_ERROR(
3876 cpl_propertylist_append_string(pl_tbl, "cutoff", "right"));
3877 }
3878 }
3879
3880 /* omit outliers devying more than 2% (15% for problematic slitlet #16)*/
3881 percentage = 1.02;
3882 if (i == 15 || i == 17) {
3883 percentage = 1.15;
3884 }
3885 for (int ty = 0; ty < nr_lines; ty++) {
3886 double val = eris_ifu_vector_get(slit_width_rej, ty);
3887 if ((val > median*percentage) || (val < median/percentage)) {
3888 eris_ifu_vector_reject(slit_width_rej, ty);
3889 eris_ifu_vector_reject(left_edge_rej, ty);
3890 eris_ifu_vector_reject(right_edge_rej, ty);
3891 }
3892 }
3893
3894 median = eris_ifu_vector_get_median(slit_width_rej, ERIS_IFU_ARITHMETIC);
3895 BRK_IF_ERROR(
3896 cpl_propertylist_append_double(pl_tbl, "aft_med", median));
3897 if (eris_ifu_vector_count_non_rejected(slit_width_rej) >= 3) {
3898 stddev = eris_ifu_vector_get_stdev_median(slit_width_rej);
3899 BRK_IF_ERROR(
3900 cpl_propertylist_append_double(pl_tbl, "aft_sdv", stddev));
3901 }
3902 CHECK_ERROR_STATE();
3903 cpl_msg_debug(cpl_func, "after: median: %g, stddev: %g", median, stddev);
3904 if (productDepth & 8) {
3905 extname = cpl_sprintf("Sx_%02d slit_width_rej2", i+1);
3906 cpl_propertylist_append_string(pl_tbl, "EXTNAME", extname);
3907 eris_ifu_free_string(&extname);
3908 BRK_IF_ERROR(
3909 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl, CPL_IO_EXTEND, 70));
3910 }
3911
3912 /*
3913 * check if first or last slitlet is off detector (partially cut off)
3914 * (2nd test)
3915 */
3916 if ((i == 0) && ((*cut_off_left == CPL_TRUE) ||
3917 (eris_ifu_vector_get_min(left_edge_rej, NULL) < ERIS_IFU_DETECTOR_BP_BORDER)))
3918 {
3919 *cut_off_left = CPL_TRUE;
3920 if (!cpl_propertylist_has(pl_tbl, "cutoff")) {
3921 BRK_IF_ERROR(
3922 cpl_propertylist_append_string(pl_tbl, "cutoff", "left"));
3923 }
3924
3925 // reset slit_width
3926 eris_ifu_free_ifu_vector(&slit_width_rej);
3927 BRK_IF_NULL(
3928 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
3929
3930 eris_ifu_vector *x = NULL;
3931 x = eris_ifu_vector_duplicate(slit_width_rej);
3932 for (int j = 0; j < nr_lines; j++) {
3933 eris_ifu_vector_set(x, j, j+1);
3934 }
3935 cpl_vector *fff = eris_ifu_polyfit_edge(x, slit_width_rej, 1);
3936 eris_ifu_free_ifu_vector(&x);
3937
3938 double fp0 = cpl_vector_get(fff, 0),
3939 fp1 = cpl_vector_get(fff, 1);
3940 eris_ifu_free_vector(&fff);
3941 stddev = eris_ifu_vector_get_stdev_median(slit_width_rej);
3942 for (int ty = 0; ty < nr_lines; ty++) {
3943 double val = eris_ifu_vector_get(slit_width_rej, ty);
3944 double val_calc = fp0+fp1*(ty+1);
3945 if (fabs(val - val_calc) > stddev*0.7) { // stddev is a bit too high
3946 eris_ifu_vector_reject(slit_width_rej, ty);
3947 }
3948 }
3949 if (productDepth & 8) {
3950 extname = cpl_sprintf("Sx_%02d slit_width_rej3", i+1);
3951 cpl_propertylist_append_string(pl_tbl, "EXTNAME", extname);
3952 eris_ifu_free_string(&extname);
3953 BRK_IF_ERROR(
3954 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl,
3955 CPL_IO_EXTEND, 70));
3956 }
3957 } // if left_edge cut off
3958
3959 if ((i == SLITLET_CNT-1) && ((*cut_off_right == CPL_TRUE) ||
3960 (eris_ifu_vector_get_max(right_edge_rej, NULL) > ERIS_IFU_DETECTOR_SIZE_X-ERIS_IFU_DETECTOR_BP_BORDER)))
3961 {
3962 *cut_off_right = TRUE;
3963 if (!cpl_propertylist_has(pl_tbl, "cutoff")) {
3964 BRK_IF_ERROR(
3965 cpl_propertylist_append_string(pl_tbl, "cutoff", "right"));
3966 }
3967
3968 // reset slit_width
3969 eris_ifu_free_ifu_vector(&slit_width_rej);
3970 BRK_IF_NULL(
3971 slit_width_rej = eris_ifu_vector_duplicate(slit_width));
3972
3973 eris_ifu_vector *x = NULL;
3974 x = eris_ifu_vector_duplicate(slit_width_rej);
3975 for (int j = 0; j < nr_lines; j++) {
3976 eris_ifu_vector_set(x, j, j+1);
3977 }
3978 cpl_vector *fff = eris_ifu_polyfit_edge(x, slit_width_rej, 1);
3979 eris_ifu_free_ifu_vector(&x);
3980
3981 double fp0 = cpl_vector_get(fff, 0),
3982 fp1 = cpl_vector_get(fff, 1);
3983 eris_ifu_free_vector(&fff);
3984 stddev = eris_ifu_vector_get_stdev_median(slit_width_rej);
3985 CHECK_ERROR_STATE();
3986 for (int ty = 0; ty < nr_lines; ty++) {
3987 double val = eris_ifu_vector_get(slit_width_rej, ty);
3988 double val_calc = fp0+fp1*(ty+1);
3989 if (fabs(val - val_calc) > stddev*0.7) { // stddev is a bit too high
3990 BRK_IF_ERROR(
3991 eris_ifu_vector_reject(slit_width_rej, ty));
3992 }
3993 }
3994 if (productDepth & 8) {
3995 extname = cpl_sprintf("Sx_%02d slit_width_rej4", i+1);
3996 cpl_propertylist_append_string(pl_tbl, "EXTNAME", extname);
3997 eris_ifu_free_string(&extname);
3998 BRK_IF_ERROR(
3999 eris_ifu_vector_save(slit_width_rej, fn, CPL_TYPE_DOUBLE, pl_tbl,
4000 CPL_IO_EXTEND, 70));
4001 }
4002 } // if right_edge cut off
4003
4004 eris_ifu_free_ifu_vector(&left_edge_rej);
4005 eris_ifu_free_ifu_vector(&right_edge_rej);
4006 CHECK_ERROR_STATE();
4007
4008 /* setup table to save */
4009 BRK_IF_NULL(
4010 tbl[i] = cpl_table_new(eris_ifu_vector_count_non_rejected(slit_width_rej)));
4011 BRK_IF_ERROR(
4012 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_EDGE_L, CPL_TYPE_DOUBLE));
4013 BRK_IF_ERROR(
4014 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_EDGE_R, CPL_TYPE_DOUBLE));
4015 BRK_IF_ERROR(
4016 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_SLIT, CPL_TYPE_DOUBLE));
4017 BRK_IF_ERROR(
4018 cpl_table_new_column(tbl[i], ERIS_IFU_DIST_YPOS, CPL_TYPE_DOUBLE));
4019
4020 // copy vectors to table
4021 int cnt = 0;
4022 for (int ty = 0; ty < cpl_vector_get_size(ypos); ty++) {
4023 if (!eris_ifu_vector_is_rejected(slit_width_rej, ty)) {
4024 // add to table only if line hasn't been rejected
4025 BRK_IF_ERROR(
4026 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_YPOS, cnt, pypos[ty]));
4027 BRK_IF_ERROR(
4028 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_L, cnt, pleft_edge[ty]));
4029 BRK_IF_ERROR(
4030 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_R, cnt, pright_edge[ty]));
4031 BRK_IF_ERROR(
4032 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_SLIT, cnt, eris_ifu_vector_get(slit_width_rej, ty)));
4033
4034 if ((i == 0) && (*cut_off_left == TRUE)) {
4035 // set invalid values to nan on left side
4036 if (pleft_edge[ty] < ERIS_IFU_DETECTOR_BP_BORDER) {
4037 BRK_IF_ERROR(
4038 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_L, cnt, NAN));
4039 BRK_IF_ERROR(
4040 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_SLIT, cnt, pright_edge[ty]-ERIS_IFU_DETECTOR_BP_BORDER));
4041 }
4042 }
4043 if ((i == SLITLET_CNT-1) && (*cut_off_right == TRUE)) {
4044 // set invalid values to nan on right side
4045 if (pright_edge[ty] > ERIS_IFU_DETECTOR_SIZE_X-ERIS_IFU_DETECTOR_BP_BORDER) {
4046 BRK_IF_ERROR(
4047 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_EDGE_R, cnt, NAN));
4048 BRK_IF_ERROR(
4049 cpl_table_set_double(tbl[i], ERIS_IFU_DIST_SLIT, cnt, ERIS_IFU_DETECTOR_SIZE_X - ERIS_IFU_DETECTOR_BP_BORDER - pleft_edge[ty]));
4050 }
4051 }
4052
4053 cnt++;
4054 }
4055 }
4056
4057 extname = cpl_sprintf("Sx_%02d", i+1);
4058 cpl_propertylist_append_string(pl_tbl, "EXTNAME", extname);
4059 eris_ifu_free_string(&extname);
4060 BRK_IF_ERROR(
4061 cpl_table_save(tbl[i], NULL, pl_tbl, ERIS_IFU_PRO_DIST_SLIT_POS_FN, CPL_IO_EXTEND));
4062
4063 eris_ifu_free_propertylist(&pl_tbl);
4064 eris_ifu_free_ifu_vector(&slit_width);
4065 eris_ifu_free_ifu_vector(&slit_width_rej);
4066 eris_ifu_free_vector(&left_edge);
4067 eris_ifu_free_vector(&right_edge);
4068 eris_ifu_free_vector(&ypos);
4069 } // end: for i = SLITLET_CNT
4070 }
4071 CATCH
4072 {
4073 CATCH_MSGS();
4074
4075 eris_ifu_free_image(&profile_x);
4076 for (int i = 0; i < SLITLET_CNT; i++) {
4077 eris_ifu_free_table(&tbl[i]);
4078 }
4079 cpl_free(tbl); tbl = NULL;
4080 }
4081
4082 eris_ifu_free_vector(&left_edge_tmp);
4083 eris_ifu_free_vector(&right_edge_tmp);
4084 eris_ifu_free_vector(&ypos_tmp);
4085 eris_ifu_free_vector(&left_edge);
4086 eris_ifu_free_vector(&right_edge);
4087 eris_ifu_free_vector(&ypos);
4088 eris_ifu_free_propertylist(&pl_tbl);
4089 eris_ifu_free_ifu_vector(&left_edge_rej);
4090 eris_ifu_free_ifu_vector(&right_edge_rej);
4091
4092 return tbl;
4093}
4094
4119cpl_error_code eris_ifu_fit_gauss(const cpl_vector *x,
4120 const cpl_vector *y,
4121 double *x0,
4122 double *sigma,
4123 double *area,
4124 double *offset)
4125{
4126 cpl_error_code ret_error = CPL_ERROR_NONE,
4127 fit_error = CPL_ERROR_NONE;
4128
4129
4130 cpl_ensure_code(x, CPL_ERROR_NULL_INPUT);
4131 cpl_ensure_code(y, CPL_ERROR_NULL_INPUT);
4132 cpl_ensure_code(x0, CPL_ERROR_NULL_INPUT);
4133 cpl_ensure_code(area, CPL_ERROR_NULL_INPUT);
4134 cpl_ensure_code(sigma, CPL_ERROR_NULL_INPUT);
4135 cpl_ensure_code(offset, CPL_ERROR_NULL_INPUT);
4136
4137 TRY
4138 {
4139 *x0 = 0.;
4140 *sigma = 0.;
4141 *area = 0.;
4142 *offset = 0.;
4143
4144 fit_error = cpl_vector_fit_gaussian(x, NULL, y, NULL,
4145 CPL_FIT_ALL,
4146 x0,
4147 sigma,
4148 area,
4149 offset,
4150 NULL, NULL, NULL);
4151
4152// cpl_msg_debug(cpl_func, " --- 1st FIT ---------------------"
4153// "-------------");
4154// cpl_msg_debug(cpl_func, " center: %g (sigma: %g, area: %g,"
4155// " offset: %g)", *x0, *sigma, *area, *offset);
4156
4157 // this happens only once in obscure test data...
4158 if ((fit_error == CPL_ERROR_NONE) &&
4159 (cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX))
4160 {
4161 cpl_error_reset();
4162 fit_error = CPL_ERROR_CONTINUE;
4163 }
4164
4165 if (fit_error == CPL_ERROR_CONTINUE) {
4166 // if first fit doesn't convert, try it again with fixed
4167 // area- and sigma-parameter
4168 RECOVER();
4169
4170 fit_error = cpl_vector_fit_gaussian(x, NULL, y, NULL,
4171 CPL_FIT_CENTROID | CPL_FIT_OFFSET,
4172 x0,
4173 sigma,
4174 area,
4175 offset,
4176 NULL, NULL, NULL);
4177
4178// cpl_msg_debug(cpl_func, " --- 2nd FIT -----------------"
4179// "-----------------");
4180// cpl_msg_debug(cpl_func, " center: %g (sigma: %g, "
4181// "area: %g, offset: %g)",
4182// *x0, *sigma, *area, *offset);
4183
4184 if (fit_error == CPL_ERROR_CONTINUE) {
4185 // if it didn't convert again, give up and take the
4186 // estimated value
4187 RECOVER();
4188 }
4189 }
4190 CHECK_ERROR_STATE();
4191 }
4192 CATCH
4193 {
4194 ret_error = cpl_error_get_code();
4195
4196 *x0 = -1;
4197 *sigma = -1;
4198 *area = -1;
4199 *offset = -1;
4200 }
4201
4202 return ret_error;
4203}
4204
4205/*----------------------------------------------------------------------------*/
4226/*----------------------------------------------------------------------------*/
4227cpl_vector* eris_ifu_polyfit_edge(const eris_ifu_vector *x,
4228 const eris_ifu_vector *y,
4229 int fit_order)
4230{
4231 eris_ifu_vector *x_dup = NULL,
4232 *y_dup = NULL,
4233 *fit_vec = NULL;
4234 cpl_vector *fit_par = NULL,
4235 *x_good = NULL,
4236 *y_good = NULL;
4237 double *pfit_par = NULL,
4238 *pfdata = NULL,
4239 *pfmask = NULL,
4240 stddev = 0.0,
4241 median = 0.0,
4242 *pxdata = NULL,
4243 *pxmask = NULL,
4244 *pymask = NULL;
4245 int size = 0,
4246 iter = 3,
4247 i = 0,
4248 j = 0;
4249
4250 cpl_ensure(x, CPL_ERROR_NULL_INPUT, NULL);
4251 cpl_ensure(y, CPL_ERROR_NULL_INPUT, NULL);
4252 cpl_ensure(fit_order >= 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
4253 cpl_ensure(cpl_vector_get_size(x->data) == cpl_vector_get_size(y->data), CPL_ERROR_ILLEGAL_INPUT, NULL);
4254
4255 TRY
4256 {
4257 // assert that rejected values in x are also rejected in y and vice versa
4258 BRK_IF_NULL(
4259 x_dup = eris_ifu_vector_duplicate(x));
4260 BRK_IF_NULL(
4261 y_dup = eris_ifu_vector_duplicate(y));
4262 BRK_IF_ERROR(
4263 eris_ifu_vector_adapt_rejected(x_dup, y_dup));
4264
4265 size = (int) cpl_vector_get_size(x_dup->data);
4266
4267 BRK_IF_NULL(
4268 pxdata = cpl_vector_get_data(x_dup->data));
4269 BRK_IF_NULL(
4270 pxmask = cpl_vector_get_data(x_dup->mask));
4271 BRK_IF_NULL(
4272 pymask = cpl_vector_get_data(y_dup->mask));
4273
4274 BRK_IF_NULL(
4275 fit_vec = eris_ifu_vector_new(size));
4276 BRK_IF_NULL(
4277 pfdata = cpl_vector_get_data(fit_vec->data));
4278 BRK_IF_NULL(
4279 pfmask = cpl_vector_get_data(fit_vec->mask));
4280
4281 // iterate fitting
4282 for (i = 0; i < iter; i++)
4283 {
4284 cpl_vector_delete(fit_par); fit_par = NULL;
4285
4286 // fit
4287 BRK_IF_NULL(
4288 x_good = eris_ifu_vector_create_non_rejected(x_dup));
4289 BRK_IF_NULL(
4290 y_good = eris_ifu_vector_create_non_rejected(y_dup));
4291
4292 BRK_IF_NULL(
4293 fit_par = eris_ifu_polyfit_1d(x_good, y_good, fit_order));
4294 BRK_IF_NULL(
4295 pfit_par = cpl_vector_get_data(fit_par));
4296
4297 eris_ifu_free_vector(&x_good);
4298 eris_ifu_free_vector(&y_good);
4299
4300 // create fitted vector
4301 for (j = 0; j < size; j++) {
4302 if (eris_ifu_vector_is_rejected(x_dup, j)) {
4303 BRK_IF_ERROR(
4304 eris_ifu_vector_reject(fit_vec, j));
4305 } else {
4306 double fit_val = -pfit_par[0];
4307 if (fit_order >= 1) {
4308 fit_val -= pfit_par[1] * pxdata[j];
4309 }
4310 if (fit_order >= 2) {
4311 fit_val -= pfit_par[2] * pow(pxdata[j], 2);
4312 }
4313 if (fit_order >= 3) {
4314 fit_val -= pfit_par[3] * pow(pxdata[j], 3);
4315 }
4316
4317 BRK_IF_ERROR(
4318 eris_ifu_vector_set(fit_vec, j, fit_val));
4319 }
4320 }
4321
4322 // fit_vec = y_good - fit_vec
4323 BRK_IF_ERROR(
4324 eris_ifu_vector_add(fit_vec, y_dup));
4325
4326 median = eris_ifu_vector_get_median(fit_vec, ERIS_IFU_ARITHMETIC);
4327 stddev = eris_ifu_vector_get_stdev(fit_vec);
4328 CHECK_ERROR_STATE();
4329
4330 BRK_IF_ERROR(
4331 eris_ifu_vector_abs(fit_vec));
4332
4333 // clip values larger than median + 5 * stddev
4334 double clip_val = median + 5 * stddev;
4335 for (j = 0; j < size; j++) {
4336 if ((pfmask[j] >= 0.5) && (pfdata[j] > clip_val)) {
4337 pfmask[j] = 0.;
4338 pxmask[j] = 0.;
4339 pymask[j] = 0.;
4340 }
4341 }
4342 } // for i = iter
4343 }
4344 CATCH
4345 {
4346 CATCH_MSGS();
4347 eris_ifu_free_vector(&fit_par);
4348 }
4349
4350 eris_ifu_free_ifu_vector(&fit_vec);
4351 eris_ifu_free_ifu_vector(&x_dup);
4352 eris_ifu_free_ifu_vector(&y_dup);
4353 eris_ifu_free_vector(&x_good);
4354 eris_ifu_free_vector(&y_good);
4355
4356 return fit_par;
4357}
4358
4359#include "eris_ifu_wavecal_static.h"
4360
4361cpl_error_code eris_ifu_wavecal_processSof_dist(
4362 cpl_frameset* frames,
4363 int exposureCorrectionMode,
4364 int *arcImgCnt,
4365 hdrl_imagelist **arcImages,
4366 int **lampStates,
4367 ifsBand *band,
4368 ifsPreopticsScale *scale,
4369 ifsInstrument *instrument,
4370 double saturation_threhold,
4371 cpl_table** qclog
4372 )
4373{
4374 cpl_frame *frame = NULL;
4375
4376 TRY
4377 {
4378 if (frames == NULL) {
4379 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
4380 "missing frameset");
4381 }
4382 if (cpl_frameset_is_empty(frames)) {
4383 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
4384 "SOF file is empty or missing");
4385 }
4386 CHECK_ERROR_STATE();
4387
4388//AA only change: ERIS_IFU_RAW_WAVE_NS instead of ERIS_IFU_RAW_WAVE_LAMP
4389 // get arc lamp image
4390 cpl_frameset *arcFrames = NULL;
4391 if (cpl_frameset_count_tags(frames, ERIS_IFU_RAW_WAVE_NS) > 0) {
4392 arcFrames = eris_ifu_get_frameset_by_tag(frames, ERIS_IFU_RAW_WAVE_NS);
4393 } else if ( (cpl_frameset_count_tags(frames, ERIS_IFU_RAW_WAVE_NS_ON) > 0) &&
4394 (cpl_frameset_count_tags(frames, ERIS_IFU_RAW_WAVE_NS_OFF) > 0) ) {
4395 cpl_frameset *arcFrames_off = NULL;
4396 arcFrames = eris_ifu_get_frameset_by_tag(frames, ERIS_IFU_RAW_WAVE_NS_ON);
4397
4398 arcFrames_off = eris_ifu_get_frameset_by_tag(frames, ERIS_IFU_RAW_WAVE_NS_OFF);
4399
4400 cpl_frameset_join(arcFrames, arcFrames_off);
4401
4402 cpl_frameset_delete(arcFrames_off);
4403 }
4404 BRK_IF_ERROR(
4405 eris_ifu_wave_get_arc_images(arcFrames,
4406 exposureCorrectionMode,
4407 arcImgCnt,
4408 arcImages,
4409 lampStates,
4410 band,
4411 scale,
4412 instrument,
4413 saturation_threhold,
4414 qclog));
4415 cpl_frameset_delete(arcFrames);
4416
4417 // get reference lines
4418 frame = cpl_frameset_find(frames, ERIS_IFU_CALIB_REF_LINES);
4419 CHECK_ERROR_STATE();
4420 if (frame == NULL) {
4421 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
4422 "missing \"%s\" tag in the SOF, arc lamp reference lines",
4423 ERIS_IFU_CALIB_REF_LINES);
4424 }
4425 } CATCH
4426 {
4427// CATCH_MSGS();
4428 }
4429
4430 return cpl_error_get_code();
4431}
4432
4439cpl_error_code eris_ifu_distortion_reduce_lines(cpl_table *tbl,
4440 ifsBand band,
4441 int nr_cols)
4442{
4443 cpl_error_code err = CPL_ERROR_NONE;
4444 int cut_level_area = 0,
4445 cut_level_intensity = 0;
4446 const char *bandStr = NULL;
4447
4448 cpl_ensure_code(tbl != NULL, CPL_ERROR_NULL_INPUT);
4449
4450 TRY
4451 {
4453 bandStr = eris_ifu_get_bandString(band));
4454
4455
4456// // cut again lower (at a tenth) for slitlet #16
4457// CHECK_ERROR_STATE();
4458//
4459// CHECK_ERROR_STATE();
4460
4461 // get rid of lines where for a specific wavelength in all columns the fit is bad
4462 cpl_table *tSlit = NULL,
4463 *tCol = NULL,
4464 *tPos = NULL;
4465 cpl_msg_debug(cpl_func, "Removing bad lines");
4466 for (int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4467cpl_msg_debug(cpl_func, " sIdx: %d", sIdx);
4468
4469 // get rid of lines where area is smaller than a band- and slitlet specific cut-level
4470 if ('J' == bandStr[0]) {
4471 if (sIdx != 16-1) {
4472 cut_level_area = 1000;
4473 cut_level_intensity = 600;
4474 } else {
4475 cut_level_area = 90; // ??
4476 cut_level_intensity = 30; // ??
4477 }
4478 } else if ('H' == bandStr[0]) {
4479 if (sIdx != 16-1) {
4480 cut_level_area = 300; // ??
4481 cut_level_intensity = 150; // ??
4482 } else {
4483 cut_level_area = 300/10; // ??
4484 cut_level_intensity = 150/10; // ??
4485 }
4486 } else if ('K' == bandStr[0]) {
4487 if (sIdx != 16-1) {
4488 cut_level_area = 200; // ??
4489 cut_level_intensity = 100; // ??
4490 } else {
4491 cut_level_area = 200/10; // ??
4492 cut_level_intensity = 100/10; // ??
4493 }
4494 } else {
4495 SET_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT, "Band must be H, K or J");
4496 }
4497
4498 cpl_table_unselect_all(tbl);
4499 cpl_table_or_selected_int(tbl, "slitlet", CPL_EQUAL_TO, sIdx);
4500 cpl_table_and_selected_double(tbl, "area", CPL_LESS_THAN, cut_level_area);
4501 cpl_table_erase_selected(tbl);
4502
4503 cpl_table_unselect_all(tbl);
4504 cpl_table_or_selected_int(tbl, "slitlet", CPL_EQUAL_TO, sIdx);
4505 cpl_table_and_selected_double(tbl, "intensity", CPL_LESS_THAN, cut_level_intensity);
4506 cpl_table_erase_selected(tbl);
4507
4508 // now get subtable width slitlet #sIdx
4509 cpl_table_unselect_all(tbl);
4510 cpl_table_or_selected_int(tbl, "slitlet", CPL_EQUAL_TO, sIdx);
4513 tSlit = cpl_table_extract_selected(tbl));
4514
4515 // get subtable of 1st column
4516 int index_first = cpl_table_get_int(tSlit, "index", 0, NULL);
4517 cpl_table_unselect_all(tSlit);
4518 cpl_table_or_selected_int(tSlit, "index", CPL_EQUAL_TO, index_first);
4521 tCol = cpl_table_extract_selected(tSlit));
4522
4523 // loop through all positions in 1st column and check if a position has been fitted mostly bad or not
4524 // > 50% bad fits --> reject
4525 for (int i = 0; i < cpl_table_get_nrow(tCol); i++) {
4526//cpl_msg_debug(cpl_func, " pos: %d", i);
4527 int pos = cpl_table_get_int(tCol, "position", i, NULL);
4528 cpl_table_unselect_all(tSlit);
4529 cpl_table_or_selected_int(tSlit, "position", CPL_EQUAL_TO, pos);
4532 tPos = cpl_table_extract_selected(tSlit));
4533 int good = 0;
4534 if (cpl_table_get_nrow(tPos) == nr_cols) {
4535 for (int j = 0; j < cpl_table_get_nrow(tPos); j++) {
4536 int code = cpl_table_get_int(tPos, "errorcode", j, NULL);
4538 if (code == 0) {
4539 good++;
4540 }
4541 }
4542 }
4543 if (good < cpl_table_get_nrow(tPos)/2) {
4544 // reject position
4545 cpl_table_unselect_all(tbl);
4546 cpl_table_or_selected_int(tbl, "slitlet", CPL_EQUAL_TO, sIdx);
4547 cpl_table_and_selected_int(tbl, "position", CPL_EQUAL_TO, pos);
4548 cpl_table_erase_selected(tbl);
4550 }
4551
4552 eris_ifu_free_table(&tPos);
4553 }
4554
4555 // check for errors on positions which exist only once, delete them
4556 eris_ifu_free_table(&tSlit);
4557 cpl_table_unselect_all(tbl);
4558 cpl_table_or_selected_int(tbl, "slitlet", CPL_EQUAL_TO, sIdx);
4561 tSlit = cpl_table_extract_selected(tbl));
4562
4563 cpl_table_unselect_all(tSlit);
4564 cpl_table_or_selected_int(tSlit, "errorcode", CPL_NOT_EQUAL_TO, 0);
4567 tPos = cpl_table_extract_selected(tSlit));
4568
4569 for (int i = 0; i < cpl_table_get_nrow(tPos); i++) {
4570 cpl_table_unselect_all(tSlit);
4571 int pos_bad = cpl_table_get_int(tPos, "position", i, NULL);
4572 cpl_table_or_selected_int(tSlit, "position", CPL_EQUAL_TO, pos_bad);
4573 if (cpl_table_count_selected(tSlit) == 1) {
4574 cpl_table_unselect_all(tbl);
4575 cpl_table_or_selected_int(tbl, "slitlet", CPL_EQUAL_TO, sIdx);
4576 cpl_table_and_selected_int(tbl, "position", CPL_EQUAL_TO, pos_bad);
4577 cpl_table_erase_selected(tbl);
4578 }
4579 }
4580
4581 eris_ifu_free_table(&tPos);
4582 eris_ifu_free_table(&tSlit);
4583 eris_ifu_free_table(&tCol);
4584 }
4586
4587 // // now get rid of lines which have been bad at least once
4588 // cpl_table_select_all(tbl);
4589 // while (cpl_table_get_column_mean(tbl, ERIS_IFU_FITTABLE_ERRORCODE) < 0.) {
4590 // // there is still some errorcode (line) to eliminate
4591
4592 // // search 1st error
4593 // int ii = 0;
4594 // int n = 0;
4595 // cpl_boolean found = CPL_FALSE;
4596 // while (ii < cpl_table_get_nrow(tbl) && !found) {
4597 // if (cpl_table_is_selected(tbl, ii) &&
4598 // (cpl_table_get_int(tbl, ERIS_IFU_FITTABLE_ERRORCODE, ii, &n) == 0))
4599 // {
4600 // ii++;
4601 // } else {
4602 // found = CPL_TRUE;
4603 // }
4604 // }
4605
4606 // if (found) {
4607 // double wavelength = cpl_table_get_double(tbl, ERIS_IFU_FITTABLE_WAVELENGTH, ii, &n);
4608 // // mark the entries with this wavelength to be eliminated
4609 // cpl_table_and_selected_double(tbl, ERIS_IFU_FITTABLE_WAVELENGTH, CPL_NOT_EQUAL_TO, wavelength);
4610 // }
4611
4612 // cpl_table_not_selected(tbl);
4613 // cpl_table_erase_selected(tbl);
4614 // cpl_table_select_all(tbl);
4615 // }
4616
4617 // we have multiple columns per slitlet. Get rid of all except the center one
4618 for (int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4619 // get subtable width slitlet #sIdx
4620 cpl_table_unselect_all(tbl);
4621 cpl_table_or_selected_int(tbl, "slitlet", CPL_EQUAL_TO, sIdx);
4624 tSlit = cpl_table_extract_selected(tbl));
4625
4626 // get index of first column
4627 int index_first = cpl_table_get_int(tSlit, "index", 0, NULL);
4628 cpl_table_and_selected_int(tbl, "index", CPL_NOT_EQUAL_TO, index_first+nr_cols/2);
4629 cpl_table_erase_selected(tbl);
4631
4632 eris_ifu_free_table(&tSlit);
4633 }
4635
4636 // get rid of last errors
4637 cpl_table_unselect_all(tbl);
4638 cpl_table_or_selected_int(tbl, "errorcode", CPL_NOT_EQUAL_TO, 0);
4639 cpl_table_erase_selected(tbl);
4641
4642 // delete unneeded columns
4643// cpl_table_erase_column(tbl, "index");
4644 cpl_table_erase_column(tbl, "imgIdx");
4645// cpl_table_erase_column(tbl, ERIS_IFU_FITTABLE_WAVELENGTH);
4646// cpl_table_erase_column(tbl, ERIS_IFU_FITTABLE_ERRORCODE);
4647// cpl_table_erase_column(tbl, "x0");
4648// cpl_table_erase_column(tbl, "sigma");
4649// cpl_table_erase_column(tbl, "area");
4650// cpl_table_erase_column(tbl, "offset");
4651 cpl_table_erase_column(tbl, "mse");
4652 cpl_table_erase_column(tbl, "wavelengthFit");
4653 cpl_table_erase_column(tbl, "wavelengthError");
4654 cpl_table_erase_column(tbl, "range");
4655 cpl_table_erase_column(tbl, "xdata");
4656 cpl_table_erase_column(tbl, "ydata");
4658 }
4659 CATCH
4660 {
4661 CATCH_MSGS();
4662 }
4663 return err;
4664}
4665
4672cpl_error_code eris_ifu_distortion_reduce_identical_lines(cpl_table *tbl)
4673{
4674 cpl_error_code err = CPL_ERROR_NONE;
4675 cpl_table *tSlit = NULL;
4676
4677 TRY
4678 {
4679 cpl_msg_debug(cpl_func, "Removing identical/overlapping lines");
4680 for (int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4681 cpl_msg_debug(cpl_func, " sIdx: %d", sIdx);
4682
4683 // get subtable of slitlet
4684 cpl_table_unselect_all(tbl);
4685 cpl_table_or_selected_int(tbl, "slitlet", CPL_EQUAL_TO, sIdx);
4688 tSlit = cpl_table_extract_selected(tbl));
4689
4690 for (int i = 0; i < cpl_table_get_nrow(tSlit)-1; i++) {
4691 double wl1 = cpl_table_get_double(tSlit, "wavelength", i+1, NULL),
4692 wl2 = cpl_table_get_double(tSlit, "wavelength", i, NULL);
4694 if (wl1-wl2 < 0.001) {
4695 cpl_msg_debug(cpl_func, "Remove:");
4696 cpl_msg_debug(cpl_func, " wl: %g, x0: %g, sigma: %g, area: %g, offset: %g", wl1, cpl_table_get_double(tSlit, "x0", i+1, NULL), cpl_table_get_double(tSlit, "sigma", i+1, NULL), cpl_table_get_double(tSlit, "area", i+1, NULL), cpl_table_get_double(tSlit, "offset", i+1, NULL));
4697 cpl_msg_debug(cpl_func, " wl: %g, x0: %g, sigma: %g, area: %g, offset: %g", wl2, cpl_table_get_double(tSlit, "x0", i, NULL), cpl_table_get_double(tSlit, "sigma", i, NULL), cpl_table_get_double(tSlit, "area", i, NULL), cpl_table_get_double(tSlit, "offset", i, NULL));
4698
4699 int pos1 = cpl_table_get_int(tSlit, "position", i+1, NULL),
4700 pos2 = cpl_table_get_int(tSlit, "position", i, NULL);
4702 cpl_table_and_selected_int(tbl, "position", CPL_EQUAL_TO, pos1);
4703 cpl_table_erase_selected(tbl);
4705 cpl_table_unselect_all(tbl);
4706 cpl_table_or_selected_int(tbl, "slitlet", CPL_EQUAL_TO, sIdx);
4707 cpl_table_and_selected_int(tbl, "position", CPL_EQUAL_TO, pos2);
4708 cpl_table_erase_selected(tbl);
4710 }
4712 }
4713
4714 eris_ifu_free_table(&tSlit);
4715 }
4716
4718 }
4719 CATCH
4720 {
4721 CATCH_MSGS();
4722 }
4723 return err;
4724}
4725
4734cpl_table* eris_ifu_dist_wave(cpl_frameset *fs,
4735 cpl_table **centers_fitted,
4736 int productDepth,
4737 cpl_image ***arcImgs,
4738 int *imgCnt,
4739 const cpl_parameterlist* parlist,
4740 cpl_table** qclog)
4741{
4742
4743 int corrMask = LINE_EXPOSURE_CORRECTION | COLUMN_EXPOSURE_CORRECTION,
4744 arcImgCnt = 0,
4745 *lampStates = NULL,
4746// nr_cols = 3,
4747 center = 0;
4748 cpl_size nRows = 0;
4749 ifsBand band = UNDEFINED_BAND;
4750 ifsPreopticsScale scale = UNDEFINED_SCALE;
4751 ifsInstrument instrument = UNSET_INSTRUMENT;
4752 cpl_image **dataImg = NULL;
4753 const hdrl_image *tmpImg = NULL;
4754 hdrl_imagelist *arcImages = NULL;
4755 cpl_image **collapsedImgDetOrder = NULL;
4756 cpl_propertylist *pl = NULL;
4757 cpl_image **collapsedSpectra = NULL;
4758 cpl_vector *collapsedSpectrum = NULL,
4759 *centerss = NULL;
4760 cpl_bivector **refLines = NULL;
4761 const char *refLineTableFileName = NULL,
4762 *firstFitTableFileName = NULL,
4763 *waveSetupFileName = NULL;
4764 cpl_table *firstFitTable = NULL;
4765 cpl_polynomial *firstFit = NULL;
4766 cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y];
4767 struct waveTablesStruct tables;
4768 struct waveSetupStruct waveSetup;
4769 double saturation_threshold = 0;
4770 TRY
4771 {
4772 // make sure there is no nonsense in the table structure
4773 // in case it is written before filled properly
4774 eris_ifu_wave_clear_tables(&tables);
4775
4776 for (int ix=0; ix<ERIS_IFU_DETECTOR_SIZE_Y; ix++) {
4777 allFits[ix] = NULL;
4778 }
4779
4780 saturation_threshold = cpl_parameter_get_double(
4781 cpl_parameterlist_find_const(parlist, "eris.eris_ifu_distortion.pixel_saturation"));
4782
4783 // preparations
4785 eris_ifu_wavecal_processSof_dist(
4786 fs,
4787 corrMask,
4788 &arcImgCnt,
4789 &arcImages,
4790 &lampStates,
4791 &band,
4792 &scale,
4793 &instrument,
4794 saturation_threshold,
4795 qclog));
4796
4797 // allocations
4799 refLines = cpl_calloc(arcImgCnt, sizeof(cpl_bivector *)));
4801 collapsedSpectra = cpl_calloc(arcImgCnt, sizeof(cpl_image *)));
4803 dataImg = cpl_calloc(arcImgCnt, sizeof(cpl_image *)));
4804 *imgCnt = arcImgCnt;
4805
4806 // load arc images
4807 for (int i = 0; i < arcImgCnt; i++) {
4809 tmpImg = hdrl_imagelist_get_const(arcImages, i));
4811 dataImg[i] = cpl_image_duplicate(
4813 }
4814 nRows = cpl_image_get_size_y(dataImg[0]);
4815
4816 // load reference lines
4817 refLineTableFileName = cpl_frame_get_filename(
4818 cpl_frameset_find(fs, ERIS_IFU_CALIB_REF_LINES));
4819 for (int ix = 0; ix < arcImgCnt; ix++) {
4821 refLines[ix] = eris_ifu_wave_get_refLines(
4822 refLineTableFileName, instrument,
4823 lampStates[ix]));
4824 }
4825
4826 // prepare centers-vector
4827 // we need a vector of length SLITLET_CNT with one averaged center value
4828 centerss = cpl_vector_new(SLITLET_CNT);
4829 for (int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4830 // get a sensible center value (mean of the center in this slit)
4831 cpl_table *centers = centers_fitted[sIdx];
4832 double *dd = cpl_table_get_data_double(centers, "x");
4833 cpl_vector *vcen = cpl_vector_wrap (cpl_table_get_nrow(centers), dd);
4834 double ddd = cpl_vector_get_mean(vcen);
4835 cpl_vector_set(centerss,sIdx, ddd);
4836 cpl_vector_unwrap(vcen);
4837 }
4838
4839 // prepare slitletStart/End-vectors
4840 // width from center add/subtract number of pixels
4841// cpl_vector *vStart = cpl_vector_duplicate(centerss);
4842// cpl_vector_subtract_scalar(vStart, 1.);
4843// cpl_vector *vEnd = cpl_vector_duplicate(centerss);
4844// cpl_vector_add_scalar(vEnd, 1.);
4845// const double *slitletStart = cpl_vector_get_data_const(vStart);
4846// const double *slitletEnd = cpl_vector_get_data_const(vEnd);
4847
4848 //
4849 for (int aIdx = 0; aIdx < arcImgCnt; aIdx++) {
4850 for (int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4851 center = (int) cpl_vector_get (centerss, sIdx);
4852 // collapse along y at center-pos (in x)
4853 collapsedSpectrum = eris_ifu_wave_collapse_slitlet(
4854 dataImg[aIdx], center);
4855
4856 eris_ifu_wave_save_spectrum(collapsedSpectra, aIdx,
4857 collapsedSpectrum, sIdx, nRows,
4858 lampStates[aIdx], band, instrument,
4859 refLines[aIdx], productDepth);
4860
4861 eris_ifu_free_vector(&collapsedSpectrum);
4862 }
4863 }
4864
4865 // load first-fit-file
4866 firstFitTableFileName = cpl_frame_get_filename(
4867 cpl_frameset_find(fs, ERIS_IFU_CALIB_FIRST_FIT));
4868 if (firstFitTableFileName == NULL) {
4869 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
4870 "missing \"ERIS_IFU_CALIB_FIRST_FIT\" tag in the SOF, wavecal first fit table");
4871 }
4873 firstFitTable = eris_ifu_wave_get_firstFitTable(
4874 firstFitTableFileName, instrument, band));
4875
4876 waveSetupFileName = cpl_frame_get_filename(
4877 cpl_frameset_find(fs, ERIS_IFU_CALIB_WAVE_SETUP));
4878 if (waveSetupFileName == NULL) {
4879 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
4880 "missing \"ERIS_IFU_CALIB_WAVE_SETUP\" tag in the SOF, wavecal setup table");
4881 }
4883 eris_ifu_wave_init_tables(&tables));
4885 eris_ifu_read_wave_setup(waveSetupFileName, band, &waveSetup));
4886
4887 const int slitlet2collapsed[SLITLET_CNT] = {
4888 0, 15, 1, 16, 2, 17, 3, 18, 4, 19, 5, 20, 6, 21, 7,
4889 30, 31,
4890 22, 8, 23, 9, 24, 10, 25, 11, 26, 12, 27, 13, 28, 14, 29};
4891
4892 collapsedImgDetOrder =
4893 cpl_calloc(arcImgCnt, sizeof(cpl_image *));
4894 for (int aIdx = 0; aIdx < arcImgCnt; aIdx++) {
4895 cpl_size xSize = cpl_image_get_size_x(collapsedSpectra[aIdx]);
4896 cpl_size ySize = cpl_image_get_size_y(collapsedSpectra[aIdx]);
4897 collapsedImgDetOrder[aIdx] =
4898 cpl_image_new(xSize, ySize, CPL_TYPE_DOUBLE);
4899 double *in = cpl_image_get_data_double(collapsedSpectra[aIdx]);
4900 double *out = cpl_image_get_data_double(collapsedImgDetOrder[aIdx]);
4901 for (int sx=0; sx < SLITLET_CNT; sx++) {
4902 int ix = slitlet2collapsed[sx];
4903 for (int iy = 0; iy < ySize; iy++){
4904 out[sx+iy*xSize] = in[ix+iy*xSize];
4905 }
4906 }
4907
4908 }
4909
4910 int firstFitOffset;
4911 int firstFitMasterOffset = 0;
4913 firstFit = eris_ifu_get_first_fit(collapsedSpectra,
4914 lampStates, arcImgCnt, 16, 0, &firstFitMasterOffset,
4915 waveSetup, firstFitTable,
4916 tables.slitletFitting, tables.slitletCoeff));
4917 cpl_msg_info(__func__,"FirstFit Master Offset %d", firstFitMasterOffset);
4918 eris_ifu_free_polynomial(&firstFit);
4919 for (int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4921 firstFit = eris_ifu_get_first_fit(collapsedSpectra,
4922 lampStates, arcImgCnt, sIdx, firstFitMasterOffset, &firstFitOffset,
4923 waveSetup, firstFitTable,
4924 tables.slitletFitting, tables.slitletCoeff));
4925
4926// eris_ifu_fit_all_lines(REC_NAME_DISTORTION, sIdx, slitletStart, slitletEnd,
4927// arcImgCnt, dataImg, refLines,
4928// waveSetup, firstFit, allFits,
4929// tables.columnFitting, tables.columnCoeffRaw,
4930// tables.columnCoeffSmoothed, tables.smoothingCoeff);
4931 const double column[] = {0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,
4932 10.,11.,12.,13.,14.,15.,16.,17.,18.,19.,
4933 20.,21.,22.,23.,24.,25.,26.,27.,28.,29.,30.,31,};
4935 eris_ifu_fit_all_lines(REC_NAME_DISTORTION, sIdx, column, column,
4936 arcImgCnt, (const cpl_image **) collapsedImgDetOrder, refLines,
4937 waveSetup, firstFit, allFits,
4938 tables.columnFitting, tables.columnCoeffRaw,
4939 tables.columnCoeffSmoothed, tables.smoothingCoeff));
4941 cpl_table_unselect_all(tables.columnFitting);
4942 cpl_table_or_selected_int(tables.columnFitting, ERIS_IFU_FITTABLE_SLITLET, CPL_EQUAL_TO, sIdx);
4943 for (int rx = 0; rx < cpl_table_get_nrow(tables.columnFitting); rx++) {
4944 if (cpl_table_is_selected(tables.columnFitting, rx) == 1) {
4945 cpl_table_set_int(tables.columnFitting, ERIS_IFU_FITTABLE_INDEX, rx, (int) cpl_vector_get (centerss, sIdx));
4946 }
4947 }
4948
4949 eris_ifu_free_polynomial(&firstFit);
4950 }
4951 if (productDepth > 3 ) {
4953 eris_ifu_wave_save_fitting_tables(&tables, instrument, band,
4954 waveSetup, fs, parlist,
4955 "eris_ifu_distortion"));
4956 }
4957 cpl_table_unselect_all(tables.columnFitting);
4958 cpl_table_or_selected_int(tables.columnFitting, ERIS_IFU_FITTABLE_ERRORCODE, CPL_NOT_EQUAL_TO, 0);
4959 BRK_IF_ERROR(cpl_table_erase_selected(tables.columnFitting));
4960
4961 // add intensity of lines
4962 cpl_table_unselect_all(tables.columnFitting);
4963 cpl_table_new_column(tables.columnFitting, "intensity", CPL_TYPE_DOUBLE);
4964 for (int i = 0; i < cpl_table_get_nrow(tables.columnFitting); i++) {
4965 double sigma = cpl_table_get_double(tables.columnFitting, "sigma", i, NULL),
4966 area = cpl_table_get_double(tables.columnFitting, "area", i, NULL),
4967 offset = cpl_table_get_double(tables.columnFitting, "offset", i, NULL);
4968
4969 double inten = area / sqrt(2.*(double)CX_PI*pow(sigma,2)) + offset;
4970 if ((inten - offset) > 20. && sigma < 2.) {
4971// if ((inten - offset) > 20.) {
4972 cpl_table_set_double(tables.columnFitting, "intensity", i, inten);
4973 } else {
4974 //printf("Deleted due less intensity: %7.1f %f\n", offset, inten);
4975 cpl_table_or_selected_window(tables.columnFitting, i, 1);
4976 }
4978 }
4979 BRK_IF_ERROR(cpl_table_erase_selected(tables.columnFitting));
4980
4981//erw BRK_IF_ERROR(
4982// eris_ifu_distortion_reduce_lines(tables.columnFitting, band, nr_cols));
4983
4984 // sort positions
4986 pl = cpl_propertylist_new());
4988 cpl_propertylist_append_bool(pl, "position", CPL_TRUE));
4990 cpl_table_sort(tables.columnFitting, pl));
4991
4992//erw BRK_IF_ERROR(
4993// eris_ifu_distortion_reduce_identical_lines(tables.columnFitting));
4994
4995 if ((productDepth & 3) != 0) {
4996 int c = 0;
4997 for (int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
4998 cpl_table_unselect_all(tables.columnFitting);
4999 cpl_table_or_selected_int(tables.columnFitting, ERIS_IFU_FITTABLE_SLITLET, CPL_EQUAL_TO, sIdx);
5000 cpl_table *t = cpl_table_extract_selected(tables.columnFitting);
5001 if (sIdx == 0) {
5002 c = CPL_IO_CREATE;
5003 } else {
5004 c = CPL_IO_EXTEND;
5005 }
5007 cpl_table_save(t, NULL, NULL, "eris_ifu_distortion_dbg_wave_fit_lines.fits", c));
5009 }
5010 }
5011 }
5012 CATCH
5013 {
5014// eris_ifu_free_table(&tbl);
5015 }
5016 cpl_free(lampStates);
5017 eris_ifu_free_vector(&centerss);
5019 eris_ifu_free_hdrl_imagelist(&arcImages);
5020 for (int ix=0; ix<arcImgCnt; ix++) {
5021 eris_ifu_free_bivector(&refLines[ix]);
5022 eris_ifu_free_image(&collapsedSpectra[ix]);
5023 eris_ifu_free_image(&collapsedImgDetOrder[ix]);
5024 }
5025 cpl_free(refLines);
5026 cpl_free(collapsedSpectra);
5027 cpl_free(collapsedImgDetOrder);
5028 for (int ix=0; ix<ERIS_IFU_DETECTOR_SIZE_Y; ix++) {
5029 eris_ifu_free_polynomial(&allFits[ix]);
5030 }
5031 eris_ifu_free_table(&firstFitTable);
5032 eris_ifu_free_table(&tables.slitletFitting);
5033 eris_ifu_free_table(&tables.slitletCoeff);
5034 eris_ifu_free_table(&tables.columnCoeffRaw);
5035 eris_ifu_free_table(&tables.columnCoeffSmoothed);
5036 eris_ifu_free_table(&tables.smoothingCoeff);
5037 *arcImgs = dataImg;
5038 return tables.columnFitting;
5039}
#define ASSURE(condition, error,...)
error handling macro (from fors-pipeline)
#define SET_ERROR_MSG(code, msg)
Set a new error code together with a custom error message.
#define BRK_IF_ERROR(function)
If function is or returns an error != CPL_ERROR_NONE, then the try-block is exited.
#define CHECK_ERROR_STATE(void)
Check the CPL error state, and exit the try-block if not CPL_ERROR_NONE.
#define BRK_WITH_ERROR_MSG(code,...)
Set a new CPL error, and exit the try-block.
#define SET_ERROR(code)
Set a new error code.
#define TRY
Beginning of a TRY-block.
#define CATCH
End of a TRY-block, beginning of a CATCH-block.
#define BRK_IF_NULL(function)
If function is or returns a NULL pointer, then the try-block is exited.
#define CATCH_MSGS()
Displays an error message stack.
cpl_vector * eris_ifu_calc_centers_collapse_chunk(const cpl_image *img, int chunk_center, int height)
void eris_ifu_free_propertylist(cpl_propertylist **item)
free memory and set pointer to null
void eris_ifu_free_string(char **item)
free memory and set pointer to null
void eris_ifu_free_vector(cpl_vector **item)
free memory and set pointer to null
cpl_error_code eris_ifu_save_vector_dbg(const cpl_vector *vec, const char *filename, int create, const cpl_propertylist *pl)
save vector
void eris_ifu_free_table(cpl_table **item)
free memory and set pointer to null
const char * eris_ifu_get_bandString(ifsBand band)
eris_ifu_get_bandString
void eris_ifu_free_ifu_vector(eris_ifu_vector **item)
free memory and set pointer to null
void eris_ifu_free_polynomial(cpl_polynomial **item)
free memory and set pointer to null
void eris_ifu_free_hdrl_imagelist(hdrl_imagelist **item)
free memory and set pointer to null
void eris_ifu_free_image(cpl_image **item)
free memory and set pointer to null
void eris_ifu_free_bivector(cpl_bivector **item)
free memory and set pointer to null
double eris_ifu_vector_get_stdev_median(const eris_ifu_vector *ev)
Compute the bias-corrected standard deviation of a vectors elements using median.
eris_ifu_vector * eris_ifu_vector_extract(const eris_ifu_vector *ev, int istart, int istop)
Extract a sub_vector from a eris_ifu_vector.
cpl_error_code eris_ifu_vector_subtract(eris_ifu_vector *kv1, const eris_ifu_vector *kv2)
Subtract two eris_ifu_vectors.
int eris_ifu_vector_is_rejected(const eris_ifu_vector *ev, int n)
Test if a value is good or bad.
eris_ifu_vector * eris_ifu_vector_new_wrap(int n, const double *data)
Create a new eris_ifu_vector from a vector (duplicated).
double eris_ifu_vector_get_mean(const eris_ifu_vector *ev)
Compute the mean value of non-rejected eris_ifu_vector elements.
eris_ifu_vector * eris_ifu_vector_duplicate(const eris_ifu_vector *ev)
This function duplicates an existing eris_ifu_vector and allocates memory.
int eris_ifu_vector_count_non_rejected(const eris_ifu_vector *ev)
Count the number of non-rejected elements in a eris_ifu_vector.
double eris_ifu_vector_get(const eris_ifu_vector *ev, int pos)
Get an element of the eris_ifu_vector.
cpl_error_code eris_ifu_vector_add(eris_ifu_vector *kv1, const eris_ifu_vector *kv2)
Add a eris_ifu_vector to another.
eris_ifu_vector * eris_ifu_vector_create(const cpl_vector *data)
Create a new eris_ifu_vector out of a data cpl_vector.
cpl_error_code eris_ifu_vector_reject(eris_ifu_vector *ev, int n)
Set a value as rejected in a eris_ifu_vector.
double eris_ifu_vector_get_median(const eris_ifu_vector *ev, const enum medianType type)
Compute the median of the elements of a vector.
const cpl_image * hdrl_image_get_image_const(const hdrl_image *himg)
get data as cpl image
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.