MOONS Pipeline Reference Manual 0.13.1
moo_wavesol.c
1/*
2 * This file is part of the MOONS Pipeline
3 * Copyright (C) 2002-2016 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26 -----------------------------------------------------------------------------*/
27#include <math.h>
28#include <string.h>
29#include <cpl.h>
30#include <hdrl.h>
31#include "moo_params.h"
32#include "moo_single.h"
33#include "moo_badpix.h"
34#include "moo_ext.h"
35#include "moo_ext_single.h"
36#include "moo_pfits.h"
37#include "moo_map.h"
38#include "moo_utils.h"
39#include "moo_qc.h"
40#include "moo_wavesol.h"
41#include "moo_fibres_table.h"
42#include "moo_line_table.h"
43#ifdef _OPENMP
44#include <omp.h>
45#endif
46/*----------------------------------------------------------------------------*/
51/*----------------------------------------------------------------------------*/
54/*-----------------------------------------------------------------------------
55 Function codes
56 -----------------------------------------------------------------------------*/
57
58static moo_tcheby2d_polynomial *
59_moo_wavesol_fit2d(moo_loc_single *loc,
60 cpl_image *res,
61 moo_spectral_format_info *info,
62 int degx,
63 int degy,
64 int niter,
65 double max_frac,
66 double kappa,
67 int *nb_sigclip,
68 int slit_idx,
69 cpl_table *line_table,
70 const char *xcolname,
71 const char *gfit_colname)
72{
73 moo_tcheby2d_polynomial *result = NULL;
74 cpl_array *seltab = NULL;
75 cpl_vector *vx = NULL;
76 cpl_vector *vy = NULL;
77 cpl_vector *vl = NULL;
78
79 cpl_ensure(loc != NULL, CPL_ERROR_NULL_INPUT, NULL);
80 cpl_ensure(info != NULL, CPL_ERROR_NULL_INPUT, NULL);
81
82 cpl_table_select_all(line_table);
83 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_SLITLET, CPL_EQUAL_TO,
84 slit_idx);
85 cpl_size line_table_size =
86 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_MFITTED,
87 CPL_EQUAL_TO, 1);
88
89 int min_size = (degx + 1) * (degy + 1) + 1;
90 moo_try_assure(line_table_size >= min_size, CPL_ERROR_ILLEGAL_INPUT,
91 "Not enough lines %lld (expected at least %d)",
92 line_table_size, min_size);
93
94 seltab = cpl_table_where_selected(line_table);
95
96 double *xpos = cpl_table_get_data_double(line_table, xcolname);
97 double *wave = cpl_table_get_data_double(line_table, MOO_LINE_TABLE_WAVE);
98 double *ypos = cpl_table_get_data_double(line_table, MOO_LINE_TABLE_YLOC);
99 double *fwhm = cpl_table_get_data_double(line_table, MOO_LINE_TABLE_FWHM);
100 int *indexext = cpl_table_get_data_int(line_table, MOO_LINE_TABLE_INDEXEXT);
101 int *fitted = cpl_table_get_data_int(line_table, MOO_LINE_TABLE_MFITTED);
102 int nx = cpl_image_get_size_x(res);
103 cpl_image *ycentroids = moo_loc_single_get_f_centroids(loc);
104 cpl_image_reject_value(ycentroids, CPL_VALUE_NAN);
105 double ny = cpl_image_get_max(ycentroids);
106 vx = cpl_vector_new(line_table_size);
107 vl = cpl_vector_new(line_table_size);
108 vy = cpl_vector_new(line_table_size);
109
110 for (int i = 0; i < line_table_size; i++) {
111 int idx = cpl_array_get_cplsize(seltab, i, NULL);
112 cpl_vector_set(vx, i, xpos[idx]);
113 cpl_vector_set(vy, i, ypos[idx]);
114 cpl_vector_set(vl, i, wave[idx]);
115 }
116
117 result = moo_tcheby2d_polynomial_fit(vx, degx, 1., (double)nx, vy, degy, 1.,
118 ny, vl, info->wmin, info->wmax);
119 int direction = info->direction;
120 int total_rejected = 0;
121 int size = line_table_size;
122 int i;
123 for (i = 1; i <= niter; i++) {
124 cpl_vector *vdiff = cpl_vector_new(size);
125 for (int j = 0; j < size; j++) {
126 int idx = cpl_array_get_cplsize(seltab, j, NULL);
127 double x = xpos[idx];
128 double y = ypos[idx];
129 double l = wave[idx];
130 double t = moo_tcheby2d_polynomial_eval(result, x, y);
131 double diff = l - t;
132
133 cpl_vector_set(vdiff, j, diff);
134 }
135
136 double stdev = cpl_vector_get_stdev(vdiff);
137 int nb_rejected = 0;
138
139 for (int j = 0; j < size; j++) {
140 double diff = cpl_vector_get(vdiff, j);
141 int idx = cpl_array_get_cplsize(seltab, j, NULL);
142 if (fabs(diff) >= kappa * stdev) {
143 fitted[idx] = 2;
144 nb_rejected++;
145 }
146 }
147 cpl_vector_delete(vdiff);
148
149 if (nb_rejected == size) {
150 break;
151 }
152
153 if (nb_rejected == 0) {
154 break;
155 }
156
157 double frac =
158 (double)(nb_rejected + total_rejected) / (double)line_table_size;
159
160 if (frac > max_frac) {
161 break;
162 }
163 total_rejected += nb_rejected;
164 moo_tcheby2d_polynomial_delete(result);
165 cpl_array_delete(seltab);
166
167 cpl_table_select_all(line_table);
168 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_SLITLET,
169 CPL_EQUAL_TO, slit_idx);
170 size = cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_MFITTED,
171 CPL_EQUAL_TO, 2);
172
173 seltab = cpl_table_where_selected(line_table);
174 for (int j = 0; j < size; j++) {
175 int idx = cpl_array_get_cplsize(seltab, j, NULL);
176 fitted[idx] = 0;
177 }
178 cpl_array_delete(seltab);
179
180 cpl_table_select_all(line_table);
181 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_SLITLET,
182 CPL_EQUAL_TO, slit_idx);
183 size = cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_MFITTED,
184 CPL_EQUAL_TO, 1);
185 seltab = cpl_table_where_selected(line_table);
186
187 cpl_vector_delete(vx);
188 cpl_vector_delete(vy);
189 cpl_vector_delete(vl);
190
191 vx = cpl_vector_new(size);
192 vl = cpl_vector_new(size);
193 vy = cpl_vector_new(size);
194
195 for (int j = 0; j < size; j++) {
196 cpl_size idx = cpl_array_get_cplsize(seltab, j, NULL);
197 cpl_vector_set(vx, j, xpos[idx]);
198 cpl_vector_set(vy, j, ypos[idx]);
199 cpl_vector_set(vl, j, wave[idx]);
200 }
201
202 result = moo_tcheby2d_polynomial_fit(vx, degx, 1, nx, vy, degy, 1, ny,
203 vl, info->wmin, info->wmax);
204 }
205
206 *nb_sigclip = size;
207 cpl_array_delete(seltab);
208 cpl_msg_debug(__func__, "Fit2d filtering data from %lld to %d",
209 line_table_size, size);
210
211 cpl_table_select_all(line_table);
212 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_SLITLET, CPL_EQUAL_TO,
213 slit_idx);
214 line_table_size =
215 cpl_table_and_selected_int(line_table, gfit_colname, CPL_EQUAL_TO, 1);
216 seltab = cpl_table_where_selected(line_table);
217
218 for (i = 0; i < line_table_size; i++) {
219 int rej;
220
221 int idx = cpl_array_get_cplsize(seltab, i, NULL);
222 double x = xpos[idx];
223 double y = ypos[idx];
224 int iy = indexext[idx];
225
226 double wavefit = moo_tcheby2d_polynomial_eval(result, x, y);
227
228 cpl_table_set_double(line_table, MOO_LINE_TABLE_WAVEFIT, idx, wavefit);
229
230 double fw = fwhm[idx] / 2.;
231
232 double x1 = x - fw;
233 double x2 = x + fw;
234
235 if (x1 >= 1 && x2 >= 1 && x1 <= nx && x2 <= nx) {
236 double y1 = moo_loc_single_eval_f_centroids(loc, x1, iy, &rej);
237 double y2 = moo_loc_single_eval_f_centroids(loc, x2, iy, &rej);
238
239 double wavefit1 = moo_tcheby2d_polynomial_eval(result, x1, y1);
240 double wavefit2 = moo_tcheby2d_polynomial_eval(result, x2, y2);
241
242 double resolution = wavefit / (wavefit2 - wavefit1) * direction;
243
244 cpl_table_set_double(line_table, MOO_LINE_TABLE_RESOLUTION, idx,
245 resolution);
246 }
247 else {
248 cpl_table_set_double(line_table, MOO_LINE_TABLE_RESOLUTION, idx,
249 NAN);
250 }
251 }
252
253moo_try_cleanup:
254 cpl_array_delete(seltab);
255 cpl_vector_delete(vx);
256 cpl_vector_delete(vy);
257 cpl_vector_delete(vl);
258
259 return result;
260}
261
262static cpl_error_code
263_moo_wavesol_fit1d(moo_loc_single *loc,
264 int degree,
265 int numfib,
266 cpl_image *res,
267 int niter,
268 double max_frac,
269 double kappa,
270 int *nb_sigclip,
271 cpl_table *result_table,
272 int indexext_idx,
274 cpl_table *line_table,
275 const char *xcolname)
276{
277 cpl_table_select_all(line_table);
278 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_INDEXEXT,
279 CPL_EQUAL_TO, numfib);
280 cpl_size line_table_size =
281 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_MFITTED,
282 CPL_EQUAL_TO, 1);
283
284 if (line_table_size > degree) {
285 int total_rejected = 0;
286 moo_tcheby_polynomial *poly = NULL;
287
288 cpl_image *ycentroids = moo_loc_single_get_f_centroids(loc);
289 cpl_image_reject_value(ycentroids, CPL_VALUE_NAN);
290 int nx = cpl_image_get_size_x(res);
291
292 cpl_array *seltab = cpl_table_where_selected(line_table);
293
294 double *xpos = cpl_table_get_data_double(line_table, xcolname);
295 double *wave =
296 cpl_table_get_data_double(line_table, MOO_LINE_TABLE_WAVE);
297 double *fwhm =
298 cpl_table_get_data_double(line_table, MOO_LINE_TABLE_FWHM);
299 int *fitted =
300 cpl_table_get_data_int(line_table, MOO_LINE_TABLE_MFITTED);
301
302 cpl_bivector *data = cpl_bivector_new(line_table_size);
303 cpl_vector *vx = cpl_bivector_get_x(data);
304 cpl_vector *vy = cpl_bivector_get_y(data);
305
306 for (int i = 0; i < line_table_size; i++) {
307 int idx = cpl_array_get_cplsize(seltab, i, NULL);
308 double x = xpos[idx];
309 double w = wave[idx];
310 cpl_vector_set(vx, i, x);
311 cpl_vector_set(vy, i, w);
312 }
313 poly = moo_tcheby_polynomial_fit(data, degree, 1, nx);
314 cpl_size size = line_table_size;
315
316 for (int i = 1; i <= niter; i++) {
317 cpl_msg_info(__func__,
318 "#%d iter %d / %d with %" CPL_SIZE_FORMAT
319 " data (total rejected %d)",
320 numfib, i, niter, size, total_rejected);
321 cpl_vector *vdiff = cpl_vector_new(size);
322
323 for (int j = 0; j < size; j++) {
324 double x = cpl_vector_get(vx, j);
325 double y = cpl_vector_get(vy, j);
326 double t = moo_tcheby_polynomial_eval(poly, x);
327 double diff = y - t;
328 cpl_vector_set(vdiff, j, diff);
329 }
330
331 double stdev = cpl_vector_get_stdev(vdiff);
332 int nb_rejected = 0;
333
334 for (int j = 0; j < size; j++) {
335 double diff = cpl_vector_get(vdiff, j);
336 if (fabs(diff) >= kappa * stdev) {
337 int idx = cpl_array_get_cplsize(seltab, j, NULL);
338 fitted[idx] = 0;
339 nb_rejected++;
340 }
341 }
342 cpl_vector_delete(vdiff);
343
344 if (nb_rejected == size) {
345 cpl_msg_info("test", "#%d all rejected", numfib);
346 break;
347 }
348
349 if (nb_rejected == 0) {
350 cpl_msg_info("test", "#%d no rejected", numfib);
351 break;
352 }
353 double frac = (double)(nb_rejected + total_rejected) /
354 (double)line_table_size;
355
356 if (frac > max_frac) {
357 cpl_msg_info(__func__, "max frac reached (%f > %f)", frac,
358 max_frac);
359 break;
360 }
361 total_rejected += nb_rejected;
362 moo_tcheby_polynomial_delete(poly);
363 cpl_array_delete(seltab);
364
365 cpl_table_select_all(line_table);
366 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_INDEXEXT,
367 CPL_EQUAL_TO, numfib);
368 size =
369 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_MFITTED,
370 CPL_EQUAL_TO, 1);
371 seltab = cpl_table_where_selected(line_table);
372
373 cpl_bivector_delete(data);
374 data = cpl_bivector_new(size);
375 vx = cpl_bivector_get_x(data);
376 vy = cpl_bivector_get_y(data);
377 for (int j = 0; j < size; j++) {
378 int idx = cpl_array_get_cplsize(seltab, j, NULL);
379 cpl_vector_set(vx, j, xpos[idx]);
380 cpl_vector_set(vy, j, wave[idx]);
381 }
382 poly = moo_tcheby_polynomial_fit(data, degree, 1, nx);
383 }
384 cpl_array_delete(seltab);
385 cpl_table_select_all(line_table);
386 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_INDEXEXT,
387 CPL_EQUAL_TO, numfib);
388 size = cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_MFITTED,
389 CPL_EQUAL_TO, 1);
390
391 int nb_points = size;
392 *nb_sigclip += nb_points;
393
394 cpl_table_select_all(line_table);
395 line_table_size =
396 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_INDEXEXT,
397 CPL_EQUAL_TO, numfib);
398 seltab = cpl_table_where_selected(line_table);
399
400 for (int i = 0; i < line_table_size; i++) {
401 int idx = cpl_array_get_cplsize(seltab, i, NULL);
402 double x = xpos[idx];
403 double wavefit = moo_tcheby_polynomial_eval(poly, x);
404 cpl_table_set_double(line_table, MOO_LINE_TABLE_WAVEFIT, idx,
405 wavefit);
406
407 double fw = fwhm[idx] / 2.;
408
409 double x1 = x - fw;
410 double x2 = x + fw;
411 if (x1 >= 1 && x2 >= 1) {
412 double wavefit1 = moo_tcheby_polynomial_eval(poly, x1);
413 double wavefit2 = moo_tcheby_polynomial_eval(poly, x2);
414 double resolution = wavefit / (wavefit2 - wavefit1);
415 cpl_table_set_double(line_table, MOO_LINE_TABLE_RESOLUTION, idx,
416 resolution);
417 }
418 else {
419 cpl_table_set_double(line_table, MOO_LINE_TABLE_RESOLUTION, i,
420 NAN);
421 }
422 }
423
424 for (int i = 1; i <= nx; i++) {
425 int rej;
426
427 cpl_image_get(ycentroids, i, numfib, &rej);
428
429 if (rej == 1) {
430 cpl_image_set(res, i, numfib, NAN);
431 }
432 else {
433 double t = moo_tcheby_polynomial_eval(poly, i);
434 cpl_image_set(res, i, numfib, t);
435 }
436 }
437
438 moo_fibres_table_set_rejectline(result_table, type, indexext_idx,
439 total_rejected);
440
441 moo_tcheby_polynomial_delete(poly);
442 cpl_bivector_delete(data);
443 cpl_array_delete(seltab);
444 }
445 return cpl_error_get_code();
446}
447
448static cpl_vector *
449_compute_slitlet_shift(cpl_table *slitlet_shift,
450 cpl_table *catalog_lines,
451 int slitlet_idx)
452{
453 cpl_vector *vxdiff = NULL;
454
455 cpl_ensure(catalog_lines != NULL, CPL_ERROR_NULL_INPUT, NULL);
456
457 const double *waves =
458 cpl_table_get_data_double_const(catalog_lines, MOO_ARCLINE_LIST_WAVE);
459 int nb_catalog_lines = cpl_table_get_nrow(catalog_lines);
460
461 vxdiff = cpl_vector_new(nb_catalog_lines);
462
463 if (slitlet_shift != NULL) {
464 int min = cpl_table_get_column_min(slitlet_shift,
465 MOO_SLITLET_SHIFT_TABLE_SLITLET);
466 int max = cpl_table_get_column_max(slitlet_shift,
467 MOO_SLITLET_SHIFT_TABLE_SLITLET);
468 double center = (min + max) / 2.;
469 for (int i = 0; i < nb_catalog_lines; i++) {
470 double waveref = waves[i];
471 cpl_table_select_all(slitlet_shift);
472 cpl_table_and_selected_int(slitlet_shift,
473 MOO_SLITLET_SHIFT_TABLE_SLITLET,
474 CPL_EQUAL_TO, slitlet_idx);
475 cpl_table_and_selected_double(slitlet_shift,
476 MOO_SLITLET_SHIFT_TABLE_WAVE,
477 CPL_EQUAL_TO, waveref);
478 cpl_array *sel = cpl_table_where_selected(slitlet_shift);
479 int slitletshift_idx = cpl_array_get(sel, 0, NULL);
480 double xdiff = cpl_table_get_double(slitlet_shift,
481 MOO_SLITLET_SHIFT_TABLE_XDIFF,
482 slitletshift_idx, NULL);
483 cpl_array_delete(sel);
484
485 if (isnan(xdiff)) {
486 cpl_table_select_all(slitlet_shift);
487 int next_slit = slitlet_idx + 1;
488 if (slitlet_idx > center) {
489 next_slit = slitlet_idx - 1;
490 }
491 cpl_table_and_selected_int(slitlet_shift,
492 MOO_SLITLET_SHIFT_TABLE_SLITLET,
493 CPL_EQUAL_TO, next_slit);
494 cpl_table_and_selected_double(slitlet_shift,
495 MOO_SLITLET_SHIFT_TABLE_WAVE,
496 CPL_EQUAL_TO, waveref);
497 sel = cpl_table_where_selected(slitlet_shift);
498 slitletshift_idx = cpl_array_get(sel, 0, NULL);
499 cpl_array_delete(sel);
500 xdiff = cpl_table_get_double(slitlet_shift,
501 MOO_SLITLET_SHIFT_TABLE_XDIFF,
502 slitletshift_idx, NULL);
503 if (isnan(xdiff)) {
504 xdiff = 0;
505 }
506 }
507 cpl_vector_set(vxdiff, i, xdiff);
508 }
509 }
510 else {
511 for (int i = 0; i < nb_catalog_lines; i++) {
512 cpl_vector_set(vxdiff, i, 0.0);
513 }
514 }
515 return vxdiff;
516}
517
518static cpl_table *
519_moo_wavesol_fibre_using_guess(cpl_image *data,
520 cpl_image *errs,
521 cpl_image *guess,
522 cpl_table *slitlet_shift,
523 int numfib,
524 cpl_table *catalog_lines,
525 int winhsize,
526 double sigma_min,
527 double sigma_max,
528 int slitlet_idx,
529 int indexext,
530 const char *extname,
531 const int spectro,
532 cpl_table **lline_table,
533 int *ldetected,
534 int *lfailed,
535 int *lfitted)
536{
537 cpl_table *detected_table = NULL;
538 cpl_table *ref_table = NULL;
539 cpl_vector *sol_w = NULL;
540 cpl_vector *sol_wx = NULL;
541 cpl_bivector *sol = NULL;
542
543 cpl_ensure(data != NULL, CPL_ERROR_NULL_INPUT, NULL);
544
545 int nx = cpl_image_get_size_x(data);
546 ref_table = cpl_table_new(nx);
547 cpl_table_new_column(ref_table, MOO_WAVESOL_REFTABLE_WAVE, CPL_TYPE_DOUBLE);
548 cpl_table_new_column(ref_table, MOO_WAVESOL_REFTABLE_X, CPL_TYPE_DOUBLE);
549
550 cpl_vector *vect = cpl_vector_new_from_image_row(data, numfib);
551 cpl_vector *verr = cpl_vector_new_from_image_row(errs, numfib);
552 cpl_vector *vsol = cpl_vector_new_from_image_row(guess, numfib);
553
554 for (int i = 0; i < nx; i++) {
555 double w = (float)cpl_vector_get(vsol, i);
556 int x = i + 1;
557 if (!isnan(w)) {
558 cpl_table_set(ref_table, MOO_WAVESOL_REFTABLE_WAVE, i, w);
559 cpl_table_set(ref_table, MOO_WAVESOL_REFTABLE_X, i, x);
560 }
561 else {
562 cpl_table_set_invalid(ref_table, MOO_WAVESOL_REFTABLE_WAVE, i);
563 }
564 }
565 cpl_vector_delete(vsol);
566
567 if (!cpl_table_has_valid(ref_table, MOO_WAVESOL_REFTABLE_WAVE)) {
568 cpl_msg_info("moo_wavesol", "#%d invalid guess data", numfib);
569 cpl_vector_delete(verr);
570 cpl_vector_delete(vect);
571 cpl_table_delete(ref_table);
572 return detected_table;
573 }
574
575 cpl_table_erase_invalid(ref_table);
576 int ref_size = cpl_table_get_nrow(ref_table);
577 double *refd_w =
578 cpl_table_get_data_double(ref_table, MOO_WAVESOL_REFTABLE_WAVE);
579 double *refd_wx =
580 cpl_table_get_data_double(ref_table, MOO_WAVESOL_REFTABLE_X);
581
582 sol_w = cpl_vector_wrap(ref_size, refd_w);
583 sol_wx = cpl_vector_wrap(ref_size, refd_wx);
584 sol = cpl_bivector_wrap_vectors(sol_w, sol_wx);
585
586 double wmin =
587 cpl_table_get_column_min(ref_table, MOO_WAVESOL_REFTABLE_WAVE);
588 double wmax =
589 cpl_table_get_column_max(ref_table, MOO_WAVESOL_REFTABLE_WAVE);
590
591 cpl_bivector *solx = cpl_bivector_new(ref_size);
592 cpl_vector *solx_x = cpl_bivector_get_x(solx);
593 cpl_vector *solx_y = cpl_bivector_get_y(solx);
594
595 for (int i = 0; i < ref_size; i++) {
596 double xv = cpl_vector_get(sol_wx, i);
597 cpl_vector_set(solx_x, i, xv);
598 double yv = cpl_vector_get(sol_w, i);
599 cpl_vector_set(solx_y, i, yv);
600 }
601
602 cpl_bivector_sort(sol, sol, CPL_SORT_ASCENDING, CPL_SORT_BY_X);
603
604 const double *waves =
605 cpl_table_get_data_double_const(catalog_lines, MOO_ARCLINE_LIST_WAVE);
606 int nb_catalog_lines = cpl_table_get_nrow(catalog_lines);
607 int nb_failed = 0;
608 int nb_detected = 0;
609 detected_table = moo_detected_table_new(nb_catalog_lines, 0);
610 cpl_vector *vxdiff =
611 _compute_slitlet_shift(slitlet_shift, catalog_lines, slitlet_idx);
612
613 for (int i = 0; i < nb_catalog_lines; i++) {
614 double waveref = waves[i];
615 cpl_table_set_int(detected_table, MOO_LINE_TABLE_INDEXEXT, i, indexext);
616 cpl_table_set_int(detected_table, MOO_LINE_TABLE_SLITLET, i,
617 slitlet_idx);
618 cpl_table_set_double(detected_table, MOO_LINE_TABLE_WAVE, i, waveref);
619 double xdiff = cpl_vector_get(vxdiff, i);
620
621 cpl_table_set_double(detected_table, MOO_LINE_TABLE_XDIFF, i, xdiff);
622 cpl_table_set_int(detected_table, MOO_DETECTED_TABLE_NOT_IN_RANGE, i,
623 1);
624 cpl_table_set_double(detected_table, MOO_LINE_TABLE_INTENSITY, i, NAN);
625 cpl_table_set_int(detected_table, MOO_LINE_TABLE_GFITTED, i, 0);
626 cpl_table_set_double(detected_table, MOO_LINE_TABLE_XGAUSS, i, NAN);
627 cpl_table_set_double(detected_table, MOO_LINE_TABLE_XBARY, i, NAN);
628 cpl_table_set_double(detected_table, MOO_LINE_TABLE_FWHM, i, NAN);
629 cpl_table_set_double(detected_table, MOO_LINE_TABLE_AMPLITUDE, i, NAN);
630 cpl_table_set_double(detected_table, MOO_LINE_TABLE_BACKGROUND, i, NAN);
631 cpl_table_set_double(detected_table, MOO_LINE_TABLE_FIT_FLUX, i, NAN);
632 cpl_table_set_double(detected_table, MOO_LINE_TABLE_FIT_ERR, i, NAN);
633 cpl_table_set_double(detected_table, MOO_LINE_TABLE_FIT_CHI2, i, NAN);
634 cpl_table_set_double(detected_table, MOO_LINE_TABLE_FIT_MSE, i, NAN);
635 cpl_table_set_double(detected_table, MOO_DETECTED_TABLE_WIN_CEN, i,
636 NAN);
637 cpl_table_set_double(detected_table, MOO_DETECTED_TABLE_WIN_MIN, i,
638 NAN);
639 cpl_table_set_double(detected_table, MOO_DETECTED_TABLE_WIN_MAX, i,
640 NAN);
641 cpl_table_set_int(detected_table, MOO_LINE_TABLE_FILTERED, i, -1);
642 cpl_table_set_double(detected_table, MOO_DETECTED_TABLE_WAVETH, i, NAN);
643 }
644
645 cpl_vector_delete(vxdiff);
646
647 cpl_table_select_all(detected_table);
648 cpl_table_and_selected_double(detected_table, MOO_LINE_TABLE_WAVE,
649 CPL_NOT_LESS_THAN, wmin);
650 int nb_lines =
651 cpl_table_and_selected_double(detected_table, MOO_LINE_TABLE_WAVE,
652 CPL_NOT_GREATER_THAN, wmax);
653
654 cpl_array *seltab = cpl_table_where_selected(detected_table);
655 nb_failed = nb_catalog_lines - nb_lines;
656
657 if (nb_lines > 0) {
658 cpl_vector *nwavepos_l = cpl_vector_new(nb_lines);
659 for (int i = 0; i < nb_lines; i++) {
660 int idx = cpl_array_get_cplsize(seltab, i, NULL);
661 double w = cpl_table_get_double(detected_table, MOO_LINE_TABLE_WAVE,
662 idx, NULL);
663 cpl_table_set_int(detected_table, MOO_DETECTED_TABLE_NOT_IN_RANGE,
664 idx, 0);
665 cpl_vector_set(nwavepos_l, i, w);
666 }
667
668 cpl_vector_sort(nwavepos_l, CPL_SORT_ASCENDING);
669 cpl_vector *nwavepos_x = cpl_vector_new(nb_lines);
670 cpl_bivector *nwavepos =
671 cpl_bivector_wrap_vectors(nwavepos_l, nwavepos_x);
672 cpl_bivector_interpolate_linear(nwavepos, sol);
673
674 for (int i = 0; i < nb_lines; i++) {
675 double xguess = (float)cpl_vector_get(nwavepos_x, i);
676
677 int idx = cpl_array_get_cplsize(seltab, i, NULL);
678
679 double xdiff =
680 cpl_table_get_double(detected_table, MOO_LINE_TABLE_XDIFF, idx,
681 NULL);
682 double win_cen = round(xguess - xdiff);
683 int size = winhsize * 2 + 1;
684 double win_min = win_cen - winhsize;
685 double win_max = win_cen + winhsize;
686 if (win_min <= 1) {
687 win_min = 1;
688 }
689 if (win_max >= nx) {
690 win_max = nx;
691 }
692 size = win_max - win_min + 1;
693 cpl_table_set_double(detected_table, MOO_LINE_TABLE_XGUESS, idx,
694 xguess);
695 cpl_table_set_double(detected_table, MOO_DETECTED_TABLE_WIN_MIN,
696 idx, win_min);
697 cpl_table_set_double(detected_table, MOO_DETECTED_TABLE_WIN_MAX,
698 idx, win_max);
699 cpl_table_set_double(detected_table, MOO_DETECTED_TABLE_WIN_CEN,
700 idx, win_cen);
701
702 cpl_bivector *points = cpl_bivector_new(size);
703 cpl_vector *x = cpl_bivector_get_x(points);
704 cpl_vector *y = cpl_bivector_get_y(points);
705 cpl_vector *yerr = cpl_vector_new(size);
706 nb_detected++;
707 for (int pos = win_min; pos <= win_max; pos++) {
708 cpl_vector_set(x, pos - win_min, pos);
709 cpl_vector_set(y, pos - win_min,
710 (float)cpl_vector_get(vect, pos - 1));
711 cpl_vector_set(yerr, pos - win_min,
712 (float)cpl_vector_get(verr, pos - 1));
713 }
714 double intensity = cpl_vector_get_max(y);
715 cpl_table_set_double(detected_table, MOO_LINE_TABLE_INTENSITY, idx,
716 intensity);
717
718 double centroid = NAN, background = NAN, area = NAN, sigma = NAN,
719 mse = 0, chi2 = 0;
720 cpl_errorstate prev_state = cpl_errorstate_get();
721 cpl_vector_fit_gaussian(x, NULL, y, NULL, CPL_FIT_ALL, &centroid,
722 &sigma, &area, &background, &mse, NULL,
723 NULL);
724 cpl_vector_delete(yerr);
725
726 if (centroid >= win_min && centroid <= win_max &&
727 cpl_errorstate_is_equal(prev_state)) {
728 int rej;
729 cpl_table_set_int(detected_table, MOO_LINE_TABLE_GFITTED, idx,
730 1);
731 double fit_flux =
732 cpl_image_get(data, round(centroid), numfib, &rej);
733 double fit_err =
734 cpl_image_get(errs, round(centroid), numfib, &rej);
735
736 cpl_table_set_double(detected_table,
737 MOO_DETECTED_TABLE_FIT_FLUX, idx,
738 fit_flux);
739 cpl_table_set_double(detected_table, MOO_DETECTED_TABLE_FIT_ERR,
740 idx, fit_err);
741
742 cpl_table_set_double(detected_table,
743 MOO_DETECTED_TABLE_FIT_CHI2, idx, chi2);
744 cpl_table_set_double(detected_table, MOO_DETECTED_TABLE_FIT_MSE,
745 idx, mse);
746
747 cpl_bivector *fout = cpl_bivector_new(1);
748 cpl_vector *fout_x = cpl_bivector_get_x(fout);
749 cpl_vector *fout_y = cpl_bivector_get_y(fout);
750 cpl_vector_set(fout_x, 0, centroid);
751
752 cpl_bivector_interpolate_linear(fout, solx);
753 double waveth = cpl_vector_get(fout_y, 0);
754
755 cpl_bivector_delete(fout);
756 cpl_table_set_double(detected_table, MOO_LINE_TABLE_XGAUSS, idx,
757 centroid);
758 cpl_table_set_double(detected_table, MOO_DETECTED_TABLE_WAVETH,
759 idx, waveth);
760
761 double amplitude = area / sqrt(CPL_MATH_2PI * sigma * sigma);
762 double fwhm = CPL_MATH_FWHM_SIG * sigma;
763 cpl_table_set_double(detected_table, MOO_LINE_TABLE_FWHM, idx,
764 fwhm);
765 cpl_table_set_double(detected_table, MOO_LINE_TABLE_AMPLITUDE,
766 idx, amplitude);
767 cpl_table_set_double(detected_table, MOO_LINE_TABLE_BACKGROUND,
768 idx, background);
769 double width_bary = 0;
770 double x_bary = 0;
771 moo_barycenter_fit(points, &x_bary, &width_bary);
772 cpl_table_set_double(detected_table, MOO_LINE_TABLE_XBARY, idx,
773 x_bary);
774 if (sigma >= sigma_min && sigma <= sigma_max) {
775 cpl_table_set_int(detected_table, MOO_LINE_TABLE_FILTERED,
776 idx, 0);
777 }
778 else if (sigma < sigma_min) {
779 cpl_table_set_int(detected_table, MOO_LINE_TABLE_FILTERED,
780 idx, 1);
781 }
782 else {
783 cpl_table_set_int(detected_table, MOO_LINE_TABLE_FILTERED,
784 idx, 2);
785 }
786 }
787 else {
788 nb_failed++;
789 cpl_errorstate_set(prev_state);
790 }
791 cpl_bivector_delete(points);
792 }
793 cpl_array_delete(seltab);
794
795 cpl_table_select_all(detected_table);
796 int nb_fitted =
797 cpl_table_and_selected_int(detected_table, MOO_LINE_TABLE_GFITTED,
798 CPL_EQUAL_TO, 1);
799
800 seltab = cpl_table_where_selected(detected_table);
801 *ldetected = nb_detected;
802 *lfailed = nb_failed;
803 *lfitted = nb_fitted;
804
805 cpl_msg_debug("moo_wavesol", "s%d #%d lines %d fitted %d", slitlet_idx,
806 numfib, nb_catalog_lines, nb_fitted);
807
808 *lline_table = moo_line_table_new(0);
809 cpl_table_set_size(*lline_table, nb_fitted);
810
811 for (int i = 0; i < nb_fitted; i++) {
812 int idx = cpl_array_get_cplsize(seltab, i, NULL);
813 double d_waveref =
814 cpl_table_get_double(detected_table, MOO_LINE_TABLE_WAVE, idx,
815 NULL);
816 double xgauss =
817 cpl_table_get_double(detected_table, MOO_LINE_TABLE_XGAUSS, idx,
818 NULL);
819 double xbary =
820 cpl_table_get_double(detected_table, MOO_LINE_TABLE_XBARY, idx,
821 NULL);
822 double fwhm = cpl_table_get_double(detected_table,
823 MOO_LINE_TABLE_FWHM, idx, NULL);
824 double intensity =
825 cpl_table_get_double(detected_table, MOO_LINE_TABLE_INTENSITY,
826 idx, NULL);
827 double amplitude =
828 cpl_table_get_double(detected_table, MOO_LINE_TABLE_AMPLITUDE,
829 idx, NULL);
830 double background =
831 cpl_table_get_double(detected_table, MOO_LINE_TABLE_BACKGROUND,
832 idx, NULL);
833 double fit_flux =
834 cpl_table_get_double(detected_table, MOO_LINE_TABLE_FIT_FLUX,
835 idx, NULL);
836 double fit_err =
837 cpl_table_get_double(detected_table, MOO_LINE_TABLE_FIT_ERR,
838 idx, NULL);
839 double fit_chi2 =
840 cpl_table_get_double(detected_table, MOO_LINE_TABLE_FIT_CHI2,
841 idx, NULL);
842 double fit_mse =
843 cpl_table_get_double(detected_table, MOO_LINE_TABLE_FIT_MSE,
844 idx, NULL);
845
846 double xguess =
847 cpl_table_get_double(detected_table, MOO_LINE_TABLE_XGUESS, idx,
848 NULL);
849 double waveth =
850 cpl_table_get_double(detected_table, MOO_DETECTED_TABLE_WAVETH,
851 idx, NULL);
852 int detected = cpl_table_get_int(detected_table,
853 MOO_LINE_TABLE_GFITTED, idx, NULL);
854 int filtered =
855 cpl_table_get_int(detected_table, MOO_LINE_TABLE_FILTERED, idx,
856 NULL);
857 int mfitted = 0;
858 if (filtered == 0) {
859 mfitted = 1;
860 }
861 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_INDEXEXT, i,
862 indexext);
863 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_SLITLET, i,
864 slitlet_idx);
865 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_WAVE, i,
866 d_waveref);
867 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_FLUX, i, NAN);
868 cpl_table_set_string(*lline_table, MOO_LINE_TABLE_NAME, i, "");
869 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_INDEXRBN, i, -1);
870 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_YLOC, i, NAN);
871 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_GFITTED, i,
872 detected);
873 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_INTENSITY, i,
874 intensity);
875 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_XGUESS, i,
876 xguess);
877 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_XGAUSS, i,
878 xgauss);
879 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_XDIFF, i,
880 xguess - xgauss);
881 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_WAVEDIFF, i,
882 d_waveref - waveth);
883 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_XBARY, i, xbary);
884 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_FWHM, i, fwhm);
885 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_AMPLITUDE, i,
886 amplitude);
887 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_BACKGROUND, i,
888 background);
889 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_FIT_FLUX, i,
890 fit_flux);
891 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_FIT_ERR, i,
892 fit_err);
893 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_FIT_CHI2, i,
894 fit_chi2);
895 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_FIT_MSE, i,
896 fit_mse);
897 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_FILTERED, i,
898 filtered);
899 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_MFITTED, i, mfitted);
900 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_WAVEFIT, i, NAN);
901 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_RESOLUTION, i,
902 NAN);
903 cpl_table_set_string(*lline_table, MOO_LINE_TABLE_DETECTOR, i,
904 extname);
905 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_SPECTRO, i, spectro);
906 }
907
908 cpl_array_delete(seltab);
909 cpl_bivector_unwrap_vectors(nwavepos);
910 cpl_vector_delete(nwavepos_l);
911 cpl_vector_delete(nwavepos_x);
912 }
913 else {
914 cpl_msg_info("moo_wavesol", "#%d No lines in solution range (%f,%f)",
915 numfib, wmin, wmax);
916 }
917 cpl_bivector_delete(solx);
918
919 cpl_bivector_unwrap_vectors(sol);
920 cpl_vector_unwrap(sol_w);
921 cpl_vector_unwrap(sol_wx);
922
923 cpl_table_delete(ref_table);
924
925 cpl_vector_delete(verr);
926 cpl_vector_delete(vect);
927 return detected_table;
928}
929
930static cpl_table *
931_moo_do_ppm_match(const double *waves,
932 int nb_lines,
933 cpl_table *detected_table,
934 int numfib,
935 double min_disp,
936 double max_disp,
937 double tolerance,
938 int direction,
939 const char *prefix)
940{
941 cpl_bivector *res = NULL;
942 cpl_table *ppm_table = NULL;
943
944 cpl_vector *clines = cpl_vector_new(nb_lines);
945 for (int i = 0; i < nb_lines; i++) {
946 double wa = waves[i] * direction;
947 cpl_vector_set(clines, i, wa * 10);
948 }
949 cpl_table_select_all(detected_table);
950 cpl_size size =
951 cpl_table_and_selected_int(detected_table, MOO_LINE_TABLE_FILTERED,
952 CPL_EQUAL_TO, 0);
953 if (size > 0) {
954 cpl_array *seltab = cpl_table_where_selected(detected_table);
955 cpl_vector *npeaks = cpl_vector_new(size);
956 for (int i = 0; i < size; i++) {
957 int idx = cpl_array_get_cplsize(seltab, i, NULL);
958 double xpos =
959 cpl_table_get_double(detected_table, MOO_LINE_TABLE_XGAUSS, idx,
960 NULL);
961 cpl_vector_set(npeaks, i, xpos);
962 }
963 cpl_array_delete(seltab);
964
965 cpl_vector_sort(npeaks, CPL_SORT_ASCENDING);
966#if MOO_DEBUG_WAVESOL_MATCHING
967 {
968 char *name =
969 cpl_sprintf("%s_ppmmatch_peaks_%d.txt", prefix, numfib);
970 FILE *test = fopen(name, "w");
971 cpl_vector_dump(npeaks, test);
972 fclose(test);
973 cpl_free(name);
974 }
975#endif
976 cpl_vector_sort(clines, CPL_SORT_ASCENDING);
977
978#if MOO_DEBUG_WAVESOL_MATCHING
979 {
980 char *name =
981 cpl_sprintf("%s_ppmmatch_lines_%d.txt", prefix, numfib);
982 FILE *test = fopen(name, "w");
983 cpl_vector_dump(clines, test);
984 fclose(test);
985 cpl_free(name);
986 }
987#endif
988
989 res = cpl_ppm_match_positions(npeaks, clines, min_disp * 10,
990 max_disp * 10, tolerance, NULL, NULL);
991 if (res != NULL) {
992 int rsize = cpl_bivector_get_size(res);
993 ppm_table = cpl_table_new(rsize);
994 cpl_table_new_column(ppm_table, MOO_PPM_TABLE_WAVE,
995 CPL_TYPE_DOUBLE);
996 cpl_table_new_column(ppm_table, MOO_PPM_TABLE_X, CPL_TYPE_DOUBLE);
997 cpl_table_new_column(ppm_table, MOO_PPM_TABLE_INDEXEXT,
998 CPL_TYPE_INT);
999 cpl_table_new_column(ppm_table, MOO_PPM_TABLE_DISP,
1000 CPL_TYPE_DOUBLE);
1001
1002 cpl_vector *x = cpl_bivector_get_x(res);
1003 cpl_vector *w = cpl_bivector_get_y(res);
1004
1005 for (int i = 0; i < rsize; i++) {
1006 double x1 = cpl_vector_get(x, i);
1007 double w1 = cpl_vector_get(w, i) / 10. * direction;
1008 cpl_table_set(ppm_table, MOO_PPM_TABLE_WAVE, i, w1);
1009 cpl_table_set(ppm_table, MOO_PPM_TABLE_X, i, x1);
1010 cpl_table_set_int(ppm_table, MOO_PPM_TABLE_INDEXEXT, i, numfib);
1011 }
1012 for (int i = 0; i < rsize - 1; i++) {
1013 double x1 = cpl_vector_get(x, i);
1014 double x2 = cpl_vector_get(x, i + 1);
1015 double w1 = cpl_vector_get(w, i) / 10 * direction;
1016 double w2 = cpl_vector_get(w, i + 1) / 10 * direction;
1017 double wdiff = (w2 - w1) * direction;
1018 double xdiff = x2 - x1;
1019 cpl_table_unselect_all(ppm_table);
1020 cpl_table_or_selected_double(ppm_table, MOO_PPM_TABLE_WAVE,
1021 CPL_EQUAL_TO, w1);
1022 int nb =
1023 cpl_table_or_selected_double(ppm_table, MOO_PPM_TABLE_WAVE,
1024 CPL_EQUAL_TO, w2);
1025 double disp = wdiff / xdiff;
1026 cpl_array *sel = cpl_table_where_selected(ppm_table);
1027 for (int j = 0; j < nb; j++) {
1028 int idx = cpl_array_get_cplsize(sel, j, NULL);
1029 int rej;
1030 double old =
1031 cpl_table_get(ppm_table, MOO_PPM_TABLE_DISP, idx, &rej);
1032 if (rej == 0) {
1033 disp = (disp + old) / 2.;
1034 }
1035 cpl_table_set(ppm_table, MOO_PPM_TABLE_DISP, idx, disp);
1036 }
1037 cpl_array_delete(sel);
1038 }
1039#if MOO_DEBUG_WAVESOL_MATCHING
1040 {
1041 char *name =
1042 cpl_sprintf("%s_ppmmatch_res_%d.fits", prefix, numfib);
1043 cpl_table_save(ppm_table, NULL, NULL, name, CPL_IO_CREATE);
1044 cpl_free(name);
1045 }
1046#endif
1047 }
1048 cpl_vector_delete(npeaks);
1049 }
1050 cpl_vector_delete(clines);
1051 cpl_bivector_delete(res);
1052 return ppm_table;
1053}
1054
1055static cpl_table *
1056_moo_wavesol_fibre(cpl_image *data,
1057 cpl_image *errs,
1058 int numfib,
1059 int nb_peaks_lines,
1060 int winhsize,
1061 double sigma_min,
1062 double sigma_max,
1063 double ref_snr,
1064 cpl_table *catalog_lines,
1065 double min_disp,
1066 double max_disp,
1067 double tolerance,
1068 int direction,
1069 const char *prefix,
1070 int degpoly,
1071 int slitlet_idx,
1072 int indexext_idx,
1073 const char *extname,
1074 const int spectro,
1075 cpl_table **lline_table,
1076 int *ldetected,
1077 int *lfailed,
1078 int *lfitted,
1079 int *lmatched)
1080{
1081 cpl_table *detected_table = NULL;
1082
1083 cpl_errorstate prestate = cpl_errorstate_get();
1084 cpl_image *idata = NULL;
1085 cpl_image *ierr = NULL;
1086
1087 cpl_ensure(data != NULL, CPL_ERROR_NULL_INPUT, NULL);
1088
1089 int nx = cpl_image_get_size_x(data);
1090 moo_try_check(idata = cpl_image_extract(data, 1, numfib, nx, numfib), " ");
1091 moo_try_check(ierr = cpl_image_extract(errs, 1, numfib, nx, numfib), " ");
1092 cpl_mask *imask = cpl_image_get_bpm(idata);
1093
1094 const double *waves =
1095 cpl_table_get_data_double_const(catalog_lines, MOO_ARCLINE_LIST_WAVE);
1096 int nb_catalog_lines = cpl_table_get_nrow(catalog_lines);
1097
1098 int nb_detected = 0;
1099 int nb_fitted = 0;
1100 int nb_failed = 0;
1101
1102 int current_detected = 0;
1103 detected_table = moo_detected_table_new(current_detected, 1);
1104
1105 while (nb_fitted < nb_peaks_lines) {
1106 int rej;
1107 cpl_size x, y;
1108 int nb_bad = cpl_mask_count(imask);
1109 if (nb_bad == nx) {
1110 break;
1111 }
1112 cpl_table_set_size(detected_table, nb_detected + 1);
1113 cpl_image_get_maxpos(idata, &x, &y);
1114 double intensity = cpl_image_get(idata, x, y, &rej);
1115 cpl_table_set_int(detected_table, MOO_LINE_TABLE_INDEXEXT, nb_detected,
1116 numfib);
1117 cpl_table_set_int(detected_table, MOO_LINE_TABLE_SLITLET, nb_detected,
1118 slitlet_idx);
1119 cpl_table_set_int(detected_table, MOO_DETECTED_TABLE_NGOOD, nb_detected,
1120 0);
1121 cpl_table_set_int(detected_table, MOO_DETECTED_TABLE_BADFIT,
1122 nb_detected, -1);
1123 cpl_table_set_int(detected_table, MOO_LINE_TABLE_FILTERED, nb_detected,
1124 -1);
1125 int min = x - winhsize;
1126 if (min < 1) {
1127 min = 1;
1128 }
1129 int max = x + winhsize;
1130 if (max >= nx) {
1131 max = nx;
1132 }
1133
1134 cpl_table_set_int(detected_table, MOO_DETECTED_TABLE_MIN, nb_detected,
1135 min);
1136 cpl_table_set_int(detected_table, MOO_DETECTED_TABLE_MAX, nb_detected,
1137 max);
1138 cpl_table_set_double(detected_table, MOO_DETECTED_TABLE_WIN_CEN,
1139 nb_detected, x);
1140
1141 cpl_vector *xv = NULL;
1142 cpl_vector *yv = NULL;
1143 cpl_vector *yerr = NULL;
1144 cpl_matrix *covariance = NULL;
1145
1146 int size = max - min + 1;
1147
1148 xv = cpl_vector_new(size);
1149 yv = cpl_vector_new(size);
1150 yerr = cpl_vector_new(size);
1151
1152 int ngood = 0;
1153 nb_bad = cpl_mask_count(imask);
1154
1155 for (int i = min; i <= max; i++) {
1156 double flux = cpl_image_get(idata, i, 1, &rej);
1157 if (rej == CPL_BINARY_0) {
1158 double flux_err = cpl_image_get(ierr, i, 1, &rej);
1159 cpl_vector_set(xv, ngood, i);
1160 cpl_vector_set(yv, ngood, (float)flux);
1161 cpl_vector_set(yerr, ngood, (float)flux_err);
1162 ngood++;
1163 }
1164 }
1165
1166 cpl_table_set_int(detected_table, MOO_DETECTED_TABLE_NGOOD, nb_detected,
1167 ngood);
1168
1169 if (ngood > 0) {
1170 cpl_vector_set_size(xv, ngood);
1171 cpl_vector_set_size(yv, ngood);
1172 cpl_vector_set_size(yerr, ngood);
1173 cpl_table_set_double(detected_table, MOO_LINE_TABLE_INTENSITY,
1174 nb_detected, intensity);
1175 double centroid = NAN, background = NAN, area = NAN, sigma = NAN,
1176 mse = NAN, chi2 = NAN;
1177 cpl_errorstate prev_state = cpl_errorstate_get();
1178
1179 cpl_vector_fit_gaussian(xv, NULL, yv, yerr, CPL_FIT_ALL, &centroid,
1180 &sigma, &area, &background, &mse, &chi2,
1181 NULL);
1182
1183 if (cpl_errorstate_is_equal(prev_state)) {
1184 double fit_flux =
1185 cpl_image_get(idata, round(centroid), 1, &rej);
1186 double fit_err = cpl_image_get(ierr, round(centroid), 1, &rej);
1187
1188 cpl_table_set_double(detected_table,
1189 MOO_DETECTED_TABLE_FIT_FLUX, nb_detected,
1190 fit_flux);
1191 cpl_table_set_double(detected_table, MOO_DETECTED_TABLE_FIT_ERR,
1192 nb_detected, fit_err);
1193 cpl_table_set_int(detected_table, MOO_DETECTED_TABLE_BADFIT,
1194 nb_detected, 0);
1195 cpl_table_set_double(detected_table, MOO_DETECTED_TABLE_FIT_MSE,
1196 nb_detected, mse);
1197 cpl_table_set_double(detected_table,
1198 MOO_DETECTED_TABLE_FIT_CHI2, nb_detected,
1199 chi2);
1200 cpl_table_set_double(detected_table,
1201 MOO_DETECTED_TABLE_FIT_BACKGROUND,
1202 nb_detected, background);
1203 cpl_table_set_double(detected_table, MOO_LINE_TABLE_XGAUSS,
1204 nb_detected, centroid);
1205 double amplitude = area / sqrt(CPL_MATH_2PI * sigma * sigma);
1206 double fwhm = CPL_MATH_FWHM_SIG * sigma;
1207 double fit_snr = amplitude / fit_err;
1208 cpl_table_set_double(detected_table, MOO_LINE_TABLE_FWHM,
1209 nb_detected, fwhm);
1210 cpl_table_set_double(detected_table, MOO_LINE_TABLE_AMPLITUDE,
1211 nb_detected, amplitude);
1212 cpl_table_set_double(detected_table, MOO_LINE_TABLE_BACKGROUND,
1213 nb_detected, background);
1214 double width_bary = 0;
1215 double x_bary = 0;
1216
1217 cpl_bivector *fitdata = cpl_bivector_wrap_vectors(xv, yv);
1218 moo_barycenter_fit(fitdata, &x_bary, &width_bary);
1219 cpl_bivector_unwrap_vectors(fitdata);
1220 cpl_table_set_double(detected_table, MOO_LINE_TABLE_XBARY,
1221 nb_detected, x_bary);
1222
1223 if (sigma >= sigma_min && sigma <= sigma_max) {
1224 if (fit_snr >= ref_snr && fit_flux > 0) {
1225 cpl_table_set_int(detected_table,
1226 MOO_LINE_TABLE_FILTERED, nb_detected,
1227 0);
1228 nb_fitted++;
1229 }
1230 else {
1231 cpl_table_set_int(detected_table,
1232 MOO_LINE_TABLE_FILTERED, nb_detected,
1233 3);
1234 }
1235 }
1236 else if (sigma < sigma_min) {
1237 cpl_table_set_int(detected_table, MOO_LINE_TABLE_FILTERED,
1238 nb_detected, 1);
1239 }
1240 else {
1241 cpl_table_set_int(detected_table, MOO_LINE_TABLE_FILTERED,
1242 nb_detected, 2);
1243 }
1244 }
1245 else {
1246 cpl_table_set_int(detected_table, MOO_DETECTED_TABLE_BADFIT,
1247 nb_detected, 1);
1248 cpl_errorstate_set(prev_state);
1249 }
1250 }
1251 cpl_matrix_delete(covariance);
1252 cpl_vector_delete(xv);
1253 cpl_vector_delete(yv);
1254 cpl_vector_delete(yerr);
1255
1256 for (int i = min; i <= max; i++) {
1257 cpl_mask_set(imask, i, 1, CPL_BINARY_1);
1258 }
1259 nb_detected++;
1260 }
1261 cpl_table *ppm_table =
1262 _moo_do_ppm_match(waves, nb_catalog_lines, detected_table, numfib,
1263 min_disp, max_disp, tolerance, direction, prefix);
1264 int nb_matched = 0;
1265 int ppm_table_nrow = 0;
1266
1267 if (ppm_table != NULL) {
1268 ppm_table_nrow = cpl_table_get_nrow(ppm_table);
1269 }
1270
1271 if (ppm_table_nrow <= 1) {
1272 cpl_msg_error("moo_wavesol",
1273 "#%d-%d Pattern matching failed with in input %d peaks "
1274 "fitted (%d peaks detected)",
1275 slitlet_idx, numfib, nb_fitted, nb_detected);
1276 }
1277 else {
1278 nb_matched = ppm_table_nrow;
1279 *lline_table = moo_line_table_new(1);
1280 cpl_table_set_size(*lline_table, nb_catalog_lines);
1281
1282 for (int i = 0; i < nb_catalog_lines; i++) {
1283 double nm = waves[i];
1284 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_WAVE, i, nm);
1285 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_INDEXEXT, i,
1286 indexext_idx);
1287 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_SLITLET, i,
1288 slitlet_idx);
1289 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_INDEXRBN, i, -1);
1290 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_XGAUSS, i, NAN);
1291 cpl_table_set_string(*lline_table, MOO_LINE_TABLE_DETECTOR, i,
1292 extname);
1293 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_SPECTRO, i, spectro);
1294 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_INTENSITY, i,
1295 NAN);
1296 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_XBARY, i, NAN);
1297 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_AMPLITUDE, i,
1298 NAN);
1299 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_BACKGROUND, i,
1300 NAN);
1301 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_FWHM, i, NAN);
1302 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_MATCHED, i, 0);
1303 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_MFITTED, i, 0);
1304 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_WAVEFIT, i, NAN);
1305 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_RESOLUTION, i,
1306 NAN);
1307 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_YLOC, i, NAN);
1308 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_FLUX, i, NAN);
1309 cpl_table_set_string(*lline_table, MOO_LINE_TABLE_NAME, i, "");
1310 }
1311
1312 for (int i = 0; i < nb_matched; i++) {
1313 double nm = cpl_table_get(ppm_table, MOO_PPM_TABLE_WAVE, i, NULL);
1314 double px = cpl_table_get(ppm_table, MOO_PPM_TABLE_X, i, NULL);
1315 double disp = cpl_table_get(ppm_table, MOO_PPM_TABLE_DISP, i, NULL);
1316
1317 cpl_table_select_all(*lline_table);
1318 /* due to operation on ppm wave can do EQUAL_TO operation on wave */
1319 int size =
1320 cpl_table_and_selected_double(*lline_table, MOO_LINE_TABLE_WAVE,
1321 CPL_LESS_THAN, nm + 1E-5);
1322 size =
1323 cpl_table_and_selected_double(*lline_table, MOO_LINE_TABLE_WAVE,
1324 CPL_GREATER_THAN, nm - 1E-5);
1325 if (size == 1) {
1326 cpl_array *lline_indexes =
1327 cpl_table_where_selected(*lline_table);
1328 cpl_size lline_idx =
1329 cpl_array_get_cplsize(lline_indexes, 0, NULL);
1330 cpl_array_delete(lline_indexes);
1331
1332 cpl_table_or_selected_double(detected_table,
1333 MOO_LINE_TABLE_XGAUSS,
1334 CPL_EQUAL_TO, px);
1335 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_INDEXEXT,
1336 lline_idx, slitlet_idx);
1337 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_INDEXEXT,
1338 lline_idx, indexext_idx);
1339 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_INDEXRBN,
1340 lline_idx, -1);
1341 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_XGAUSS,
1342 lline_idx, px);
1343 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_DISP,
1344 lline_idx, disp);
1345 cpl_table_set_string(*lline_table, MOO_LINE_TABLE_DETECTOR,
1346 lline_idx, extname);
1347 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_SPECTRO,
1348 lline_idx, spectro);
1349 cpl_table_unselect_all(detected_table);
1350 cpl_size detected_nb =
1351 cpl_table_or_selected_double(detected_table,
1352 MOO_LINE_TABLE_XGAUSS,
1353 CPL_EQUAL_TO, px);
1354 if (detected_nb == 1) {
1355 cpl_array *detected_indexes =
1356 cpl_table_where_selected(detected_table);
1357 cpl_size detected_idx =
1358 cpl_array_get_cplsize(detected_indexes, 0, NULL);
1359 double intensity =
1360 cpl_table_get_double(detected_table,
1361 MOO_LINE_TABLE_INTENSITY,
1362 detected_idx, NULL);
1363 double xbary = cpl_table_get_double(detected_table,
1364 MOO_LINE_TABLE_XBARY,
1365 detected_idx, NULL);
1366 double amplitude =
1367 cpl_table_get_double(detected_table,
1368 MOO_LINE_TABLE_AMPLITUDE,
1369 detected_idx, NULL);
1370 double background =
1371 cpl_table_get_double(detected_table,
1372 MOO_LINE_TABLE_BACKGROUND,
1373 detected_idx, NULL);
1374 double fit_flux =
1375 cpl_table_get_double(detected_table,
1376 MOO_LINE_TABLE_FIT_FLUX,
1377 detected_idx, NULL);
1378 double fit_err =
1379 cpl_table_get_double(detected_table,
1380 MOO_LINE_TABLE_FIT_ERR,
1381 detected_idx, NULL);
1382 double fit_chi2 =
1383 cpl_table_get_double(detected_table,
1384 MOO_LINE_TABLE_FIT_CHI2,
1385 detected_idx, NULL);
1386 double fit_mse =
1387 cpl_table_get_double(detected_table,
1388 MOO_LINE_TABLE_FIT_MSE,
1389 detected_idx, NULL);
1390 double fwhm = cpl_table_get_double(detected_table,
1391 MOO_LINE_TABLE_FWHM,
1392 detected_idx, NULL);
1393 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_INTENSITY,
1394 lline_idx, intensity);
1395 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_XBARY,
1396 lline_idx, xbary);
1397 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_AMPLITUDE,
1398 lline_idx, amplitude);
1399 cpl_table_set_double(*lline_table,
1400 MOO_LINE_TABLE_BACKGROUND, lline_idx,
1401 background);
1402 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_FWHM,
1403 lline_idx, fwhm);
1404
1405 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_FIT_FLUX,
1406 lline_idx, fit_flux);
1407 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_FIT_ERR,
1408 lline_idx, fit_err);
1409 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_FIT_CHI2,
1410 lline_idx, fit_chi2);
1411 cpl_table_set_double(*lline_table, MOO_LINE_TABLE_FIT_MSE,
1412 lline_idx, fit_mse);
1413 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_MATCHED,
1414 lline_idx, 1);
1415 cpl_table_set_int(*lline_table, MOO_LINE_TABLE_MFITTED,
1416 lline_idx, 1);
1417 cpl_array_delete(detected_indexes);
1418 }
1419 }
1420 else {
1421 cpl_msg_error("test", "the line %f is not find in LINE_TABLE",
1422 nm);
1423 }
1424 }
1425
1426 if (nb_matched <= degpoly) {
1427 cpl_msg_error("moo_wavesol",
1428 "#%d-%d Not enough matched lines (%d) to fit "
1429 "polynomial degree %d",
1430 slitlet_idx, numfib, nb_matched, degpoly);
1431 }
1432 else {
1433 cpl_msg_debug("moo_wavesol",
1434 "#%d-%d, %d peaks detected, %d fitted, %d matched / "
1435 "%d catlines",
1436 slitlet_idx, numfib, nb_detected, nb_fitted,
1437 nb_matched, nb_catalog_lines);
1438 }
1439 }
1440 cpl_table_delete(ppm_table);
1441 *ldetected = nb_detected;
1442 *lfitted = nb_fitted;
1443 *lfailed = nb_failed;
1444 *lmatched = nb_matched;
1445
1446moo_try_cleanup:
1447 cpl_image_delete(idata);
1448 cpl_image_delete(ierr);
1449
1450 // dump error from the state
1451 if (!cpl_errorstate_is_equal(prestate)) {
1452 cpl_msg_error(__func__, "#%d Error in wavesol pattern matching",
1453 numfib);
1454 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
1455 // Recover from the error(s) (Reset to prestate))
1456 cpl_errorstate_set(prestate);
1457 }
1458
1459 return detected_table;
1460}
1461
1462static cpl_error_code
1463_moo_wavecal_qc(cpl_propertylist *header, int nb_sigclip, cpl_table *line_table)
1464{
1465 cpl_table *extract_table = NULL;
1466 cpl_array *sel = NULL;
1467 cpl_vector *waveres = NULL;
1468 cpl_ensure_code(header != NULL, CPL_ERROR_NULL_INPUT);
1469 cpl_ensure_code(line_table != NULL, CPL_ERROR_NULL_INPUT);
1470
1471 moo_qc_set_wavecal_clipline(header, nb_sigclip);
1472
1473 cpl_table_select_all(line_table);
1474 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_MFITTED, CPL_EQUAL_TO,
1475 1);
1476 extract_table = cpl_table_extract_selected(line_table);
1477 double med_resol =
1478 cpl_table_get_column_median(extract_table, MOO_LINE_TABLE_RESOLUTION);
1479 cpl_table_delete(extract_table);
1480 extract_table = NULL;
1481 moo_qc_set_wavecal_resol_med(header, med_resol);
1482
1483 cpl_table_select_all(line_table);
1484 if (cpl_table_has_column(line_table, MOO_LINE_TABLE_FILTERED)) {
1485 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_FILTERED,
1486 CPL_EQUAL_TO, 0);
1487 }
1488 sel = cpl_table_where_selected(line_table);
1489 int size = cpl_array_get_size(sel);
1490 waveres = cpl_vector_new(size);
1491 for (int i = 0; i < size; i++) {
1492 int idx = cpl_array_get_cplsize(sel, i, NULL);
1493 double wave =
1494 cpl_table_get_double(line_table, MOO_LINE_TABLE_WAVE, idx, NULL);
1495 double wavefit =
1496 cpl_table_get_double(line_table, MOO_LINE_TABLE_WAVEFIT, idx, NULL);
1497 double res = wave - wavefit;
1498 cpl_vector_set(waveres, i, res);
1499 }
1500 double residwave_med = cpl_vector_get_median(waveres);
1501 double residwave_std = cpl_vector_get_stdev(waveres);
1502 moo_qc_set_wavecal_residwave_med(header, residwave_med);
1503 moo_qc_set_wavecal_residwave_std(header, residwave_std);
1504
1505 cpl_table_delete(extract_table);
1506 cpl_vector_delete(waveres);
1507 cpl_array_delete(sel);
1508 return CPL_ERROR_NONE;
1509}
1510
1511static cpl_image *
1512_moo_wavesol_single(moo_ext_single *ext,
1513 moo_loc_single *loc,
1514 cpl_array *indexes,
1515 const int *health,
1516 cpl_table *result_table,
1517 cpl_table *catalog_lines,
1518 double min_disp,
1519 double max_disp,
1520 double tolerance,
1521 int direction,
1522 cpl_image *guess,
1523 cpl_propertylist *guess_header,
1524 moo_map *wmap,
1525 int nb_peaks_lines,
1526 int winhsize,
1527 int linefit_recentre,
1528 int degx,
1529 int degy,
1530 moo_spectral_format_info *info,
1531 double sigma_min,
1532 double sigma_max,
1533 double ref_snr,
1534 cpl_propertylist *header,
1535 moo_wavesol_params *params,
1536 cpl_table **single_line_table)
1537
1538{
1539 cpl_image *res = NULL;
1540 cpl_table **all_detected = NULL;
1541 cpl_table **all_fitted = NULL;
1542 cpl_ensure(ext != NULL, CPL_ERROR_NULL_INPUT, NULL);
1543 cpl_ensure(loc != NULL, CPL_ERROR_NULL_INPUT, NULL);
1544 cpl_ensure(health != NULL, CPL_ERROR_NULL_INPUT, NULL);
1545 cpl_ensure(params != NULL, CPL_ERROR_NULL_INPUT, NULL);
1546
1547 const char *model = params->model;
1548 const char *linefit_method = params->linefit_method;
1549 const char *control = params->control;
1550 int niter = params->clip_niter;
1551 double max_frac = params->clip_frac;
1552 double kappa = params->clip_kappa;
1553
1554 cpl_table *line_table = moo_line_table_new(guess == NULL);
1555
1556 cpl_errorstate prestate = cpl_errorstate_get();
1557 moo_detector_type type = ext->type;
1558
1559 cpl_image *data = moo_ext_single_get_data(ext);
1560 cpl_image *errs = moo_ext_single_get_errs(ext);
1561
1562 int nb_fibres = cpl_image_get_size_y(data);
1563 cpl_size nb_index = cpl_array_get_size(indexes);
1564
1565 cpl_ensure(nb_index == nb_fibres, CPL_ERROR_ILLEGAL_INPUT, NULL);
1566
1567 int nx = cpl_image_get_size_x(data);
1568
1569 res = cpl_image_new(nx, nb_fibres, CPL_TYPE_DOUBLE);
1570
1571 all_detected = cpl_calloc(nb_fibres, sizeof(cpl_table *));
1572 all_fitted = cpl_calloc(nb_fibres, sizeof(cpl_table *));
1573
1574 cpl_propertylist_append_double(header, MOO_PFITS_CRPIX1, MOO_MAP_CRPIX1);
1575 cpl_propertylist_append_double(header, MOO_PFITS_CRPIX2, MOO_MAP_CRPIX2);
1576 cpl_propertylist_append_double(header, MOO_PFITS_CRVAL1, MOO_MAP_CRVAL1);
1577 cpl_propertylist_append_double(header, MOO_PFITS_CRVAL2, MOO_MAP_CRVAL2);
1578 cpl_propertylist_append_double(header, MOO_PFITS_CD1_1, MOO_MAP_CD1_1);
1579 cpl_propertylist_append_double(header, MOO_PFITS_CD1_2, 0.);
1580 cpl_propertylist_append_double(header, MOO_PFITS_CD2_1, 0.);
1581 cpl_propertylist_append_double(header, MOO_PFITS_CD2_2, MOO_MAP_CD2_2);
1582 cpl_propertylist_append_string(header, MOO_PFITS_CTYPE1, MOO_MAP_CTYPE1);
1583 cpl_propertylist_append_string(header, MOO_PFITS_CTYPE2, MOO_MAP_CTYPE2);
1584 cpl_propertylist_append_string(header, MOO_PFITS_BUNIT, MOO_MAP_BUNIT);
1585 int catline = cpl_table_get_nrow(catalog_lines);
1586 const char *extname = ext->extname;
1587 int spectro = moo_detector_get_spectro(ext->ntas);
1588
1589 int detectline = 0;
1590 int failedfit = 0;
1591 int fitline = 0;
1592 int matchline = 0;
1593 int validfibre = 0;
1594 const int *slitlet =
1595 cpl_table_get_data_int_const(result_table, MOO_FIBRES_TABLE_SLITLET);
1596 moo_try_assure(slitlet != NULL, CPL_ERROR_NULL_INPUT,
1597 "No slitlet column in fibre table");
1598
1599 const int *indexext =
1600 cpl_table_get_data_int_const(result_table, MOO_FIBRES_TABLE_INDEXEXT);
1601 if (guess != NULL) {
1602 cpl_msg_info("moo_wavesol", "Fit centroid lines using method %s",
1603 linefit_method);
1604#ifdef _OPENMP
1605#pragma omp parallel default(none) \
1606 shared(nb_fibres, indexes, health, result_table, type, all_detected, \
1607 all_fitted, extname, data, errs, guess, catalog_lines, \
1608 winhsize, degx, sigma_min, sigma_max, linefit_method, \
1609 line_table, indexext, slitlet) firstprivate(spectro) \
1610 reduction(+ : detectline, failedfit, fitline, validfibre)
1611 {
1612#pragma omp for
1613#endif
1614 for (int i = 1; i <= nb_fibres; i++) {
1615 // for(int i=20; i<=20; i++){
1616 int idx = cpl_array_get_cplsize(indexes, i - 1, NULL);
1617 int indexext_idx = indexext[idx];
1618 int slitlet_idx = slitlet[idx];
1619 int h = health[idx];
1620 if (h == 1) {
1621 int ldetected = 0;
1622 int lfailed = 0;
1623 int lfitted = 0;
1624 all_detected[i - 1] = _moo_wavesol_fibre_using_guess(
1625 data, errs, guess, NULL, i, catalog_lines, winhsize,
1626 sigma_min, sigma_max, slitlet_idx, indexext_idx,
1627 extname, spectro, &all_fitted[i - 1], &ldetected,
1628 &lfailed, &lfitted);
1629 moo_fibres_table_set_detectline(result_table, type, idx,
1630 ldetected);
1631 moo_fibres_table_set_failedfit(result_table, type, idx,
1632 lfailed);
1633 moo_fibres_table_set_fitline(result_table, type, idx,
1634 lfitted);
1635 moo_fibres_table_set_rejectline(result_table, type, idx,
1636 lfitted);
1637 detectline += ldetected;
1638 failedfit += lfailed;
1639 fitline += lfitted;
1640 validfibre++;
1641 }
1642 else {
1643 all_detected[i - 1] = NULL;
1644 all_fitted[i - 1] = NULL;
1645 }
1646 }
1647#ifdef _OPENMP
1648 }
1649#endif
1650 matchline = fitline;
1651 }
1652 else {
1653#ifdef _OPENMP
1654#pragma omp parallel default(none) \
1655 shared(nb_fibres, indexes, health, result_table, type, all_detected, \
1656 all_fitted, extname, data, errs, catalog_lines, min_disp, \
1657 max_disp, tolerance, direction, nb_peaks_lines, winhsize, ext, \
1658 degx, sigma_min, sigma_max, ref_snr, indexext, slitlet) \
1659 firstprivate(spectro) \
1660 reduction(+ : detectline, failedfit, fitline, matchline, validfibre)
1661 {
1662#pragma omp for
1663#endif
1664 for (int i = 1; i <= nb_fibres; i++) {
1665 int idx = cpl_array_get_cplsize(indexes, i - 1, NULL);
1666 int h = health[idx];
1667 int ldetected = 0;
1668 int lfailed = 0;
1669 int lfitted = 0;
1670 int lmatched = 0;
1671 int indexext_idx = indexext[idx];
1672
1673 int slitlet_idx = slitlet[idx];
1674 if (h == 1) {
1675 all_detected[i - 1] =
1676 _moo_wavesol_fibre(data, errs, i, nb_peaks_lines,
1677 winhsize, sigma_min, sigma_max,
1678 ref_snr, catalog_lines, min_disp,
1679 max_disp, tolerance, direction,
1680 ext->extname, degx, slitlet_idx,
1681 indexext_idx, extname, spectro,
1682 &all_fitted[i - 1], &ldetected,
1683 &lfailed, &lfitted, &lmatched);
1684
1685 detectline += ldetected;
1686 failedfit += lfailed;
1687 fitline += lfitted;
1688 matchline += lmatched;
1689 validfibre++;
1690 }
1691 else {
1692 cpl_msg_info("moo_wavesol",
1693 "Broken fibre indexext %d, slitlet %d",
1694 indexext_idx, slitlet_idx);
1695
1696 all_detected[i - 1] = NULL;
1697 }
1698 moo_fibres_table_set_detectline(result_table, type, idx,
1699 ldetected);
1700 moo_fibres_table_set_failedfit(result_table, type, idx,
1701 lfailed);
1702
1703 moo_fibres_table_set_fitline(result_table, type, idx, lfitted);
1704 moo_fibres_table_set_matchline(result_table, type, idx,
1705 lmatched);
1706 moo_fibres_table_set_rejectline(result_table, type, idx,
1707 lmatched);
1708 }
1709#ifdef _OPENMP
1710 }
1711#endif
1712 }
1713
1714
1715#if MOO_DEBUG_WAVESOL_DETECTED
1716 {
1717 cpl_table *test = moo_detected_table_new(0, guess == NULL);
1718 for (int i = 0; i < nb_fibres; i++) {
1719 cpl_table *t = all_detected[i];
1720 if (t != NULL) {
1721 moo_table_append(test, t);
1722 }
1723 }
1724 char *name = NULL;
1725
1726 if (guess == NULL) {
1727 name = cpl_sprintf("%s_ppm_detected.fits", ext->extname);
1728 }
1729 else {
1730 name = cpl_sprintf("%s_refit_lfwhs%d_detected.fits", ext->extname,
1731 winhsize);
1732 }
1733
1734 cpl_table_save(test, NULL, NULL, name, CPL_IO_CREATE);
1735 cpl_free(name);
1736 cpl_table_delete(test);
1737 }
1738#endif
1739 for (int i = 0; i < nb_fibres; i++) {
1740 cpl_table *t = all_fitted[i];
1741
1742 if (t != NULL) {
1743 moo_table_append(line_table, t);
1744 }
1745 }
1746 moo_qc_set_wavecal_catline(header, catline);
1747 moo_qc_set_wavecal_detectline(header, detectline);
1748 moo_qc_set_wavecal_failedfit(header, failedfit);
1749 moo_qc_set_wavecal_fitline(header, fitline);
1750 moo_qc_set_wavecal_matchline(header, matchline);
1751 moo_qc_set_wavecal_validfibre(header, validfibre);
1752
1753 int nb_sigclip = 0;
1754
1755 cpl_table_erase_invalid(line_table);
1756 int nb_line_table = cpl_table_get_nrow(line_table);
1757 cpl_msg_info(__func__, "line table size : %d fitline %d matchline %d",
1758 nb_line_table, fitline, matchline);
1759 const char *line_table_xfit = MOO_LINE_TABLE_XGAUSS;
1760 if (guess != NULL &&
1761 (strcmp(linefit_method, MOO_WAVESOL_LINEFIT_BARYCENTER) == 0)) {
1762 line_table_xfit = MOO_LINE_TABLE_XBARY;
1763 }
1764
1765 for (int i = 0; i < nb_line_table; i++) {
1766 int rej;
1767
1768 double x = cpl_table_get_double(line_table, line_table_xfit, i, NULL);
1769
1770 int indexext_idx =
1771 cpl_table_get_int(line_table, MOO_LINE_TABLE_INDEXEXT, i, NULL);
1772
1773 if (!isnan(x)) {
1774 double yc =
1775 moo_loc_single_eval_f_centroids(loc, x, indexext_idx, &rej);
1776
1777 cpl_table_set_double(line_table, MOO_LINE_TABLE_YLOC, i, yc);
1778 }
1779
1780 double nm =
1781 cpl_table_get_double(line_table, MOO_LINE_TABLE_WAVE, i, NULL);
1782
1783 cpl_table_unselect_all(catalog_lines);
1784 cpl_table_or_selected_double(catalog_lines, MOO_LINE_TABLE_WAVE,
1785 CPL_GREATER_THAN, nm - 1E-5);
1786 cpl_size cat_nb =
1787 cpl_table_and_selected_double(catalog_lines, MOO_LINE_TABLE_WAVE,
1788 CPL_LESS_THAN, nm + 1E-5);
1789
1790 if (cat_nb == 1) {
1791 cpl_array *cat_indexes = cpl_table_where_selected(catalog_lines);
1792 cpl_size cat_idx = cpl_array_get_cplsize(cat_indexes, 0, NULL);
1793 cpl_array_delete(cat_indexes);
1794 double cat_flux =
1795 cpl_table_get_double(catalog_lines, MOO_LINE_TABLE_FLUX,
1796 cat_idx, NULL);
1797 const char *cat_name =
1798 cpl_table_get_string(catalog_lines, MOO_LINE_TABLE_NAME,
1799 cat_idx);
1800 cpl_table_set_string(line_table, MOO_LINE_TABLE_NAME, i, cat_name);
1801 cpl_table_set_double(line_table, MOO_LINE_TABLE_FLUX, i, cat_flux);
1802 }
1803 }
1804
1805#if MOO_DEBUG_WAVESOL_DETECTED
1806 {
1807 char *name = NULL;
1808 if (guess == NULL) {
1809 name = cpl_sprintf("%s_ppm_lines.fits", ext->extname);
1810 }
1811 else {
1812 name = cpl_sprintf("%s_refit_lfwhs%d_lines.fits", ext->extname,
1813 winhsize);
1814 }
1815 cpl_table_save(line_table, NULL, NULL, name, CPL_IO_CREATE);
1816 cpl_free(name);
1817 }
1818#endif
1819 if (cpl_table_has_column(line_table, MOO_LINE_TABLE_DISP)) {
1820 double disp_min =
1821 cpl_table_get_column_min(line_table, MOO_LINE_TABLE_DISP);
1822 double disp_max =
1823 cpl_table_get_column_max(line_table, MOO_LINE_TABLE_DISP);
1824 moo_qc_set_wavecal_disp_min(header, disp_min);
1825 moo_qc_set_wavecal_disp_max(header, disp_max);
1826 }
1827 else if (guess_header != NULL) {
1828 cpl_propertylist_copy_property(header, guess_header,
1829 MOONS_QC_WAVECAL_DISP_MIN);
1830 cpl_propertylist_copy_property(header, guess_header,
1831 MOONS_QC_WAVECAL_DISP_MAX);
1832 }
1833
1834 if (guess != NULL && linefit_recentre) {
1835 cpl_msg_info("moo_wavesol", "RECENTRE : compute slitlet shift with %d",
1836 catline);
1837 int i = 1;
1838 int slit_idx = -1;
1839 cpl_table *slitlet_table_global = moo_slitlet_shift_table_new(0);
1840
1841 while (i <= nb_fibres) {
1842 int idx = cpl_array_get_cplsize(indexes, i - 1, NULL);
1843
1844 if (slit_idx != slitlet[idx]) {
1845 cpl_table *slitlet_table = moo_slitlet_shift_table_new(catline);
1846 slit_idx = slitlet[idx];
1847
1848 for (int j = 0; j < catline; j++) {
1849 double w =
1850 cpl_table_get_double(catalog_lines,
1851 MOO_ARCLINE_LIST_WAVE, j, NULL);
1852 cpl_table_set_int(slitlet_table,
1853 MOO_SLITLET_SHIFT_TABLE_SLITLET, j,
1854 slit_idx);
1855 cpl_table_set_double(slitlet_table,
1856 MOO_SLITLET_SHIFT_TABLE_WAVE, j, w);
1857 cpl_table_select_all(line_table);
1858 cpl_table_and_selected_int(line_table,
1859 MOO_LINE_TABLE_SLITLET,
1860 CPL_EQUAL_TO, slit_idx);
1861 cpl_table_and_selected_int(line_table,
1862 MOO_LINE_TABLE_FILTERED,
1863 CPL_EQUAL_TO, 0);
1864 int nblines =
1865 cpl_table_and_selected_double(line_table,
1866 MOO_LINE_TABLE_WAVE,
1867 CPL_EQUAL_TO, w);
1868 double median = NAN;
1869 if (nblines > 0) {
1870 cpl_table *sel = cpl_table_extract_selected(line_table);
1871 median =
1872 cpl_table_get_column_median(sel,
1873 MOO_LINE_TABLE_XDIFF);
1874 cpl_table_delete(sel);
1875 }
1876 cpl_table_set_double(slitlet_table,
1877 MOO_SLITLET_SHIFT_TABLE_XDIFF, j,
1878 median);
1879 }
1880 moo_table_append(slitlet_table_global, slitlet_table);
1881 cpl_table_delete(slitlet_table);
1882 }
1883 i++;
1884 }
1885
1886 int min_slitlet =
1887 cpl_table_get_column_min(slitlet_table_global,
1888 MOO_SLITLET_SHIFT_TABLE_SLITLET);
1889 int max_slitlet =
1890 cpl_table_get_column_max(slitlet_table_global,
1891 MOO_SLITLET_SHIFT_TABLE_SLITLET);
1892 double central_slitlet = (min_slitlet + max_slitlet) / 2.;
1893 int lo_central_slitlet = floor(central_slitlet) - 1;
1894 int up_central_slitlet = ceil(central_slitlet) + 1;
1895
1896 cpl_vector *vx = cpl_vector_new(catline);
1897 cpl_vector *vy = cpl_vector_new(catline);
1898 int vsize = 0;
1899
1900 for (int j = 0; j < catline; j++) {
1901 double w = cpl_table_get_double(catalog_lines,
1902 MOO_ARCLINE_LIST_WAVE, j, NULL);
1903 cpl_table_select_all(line_table);
1904 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_SLITLET,
1905 CPL_GREATER_THAN, lo_central_slitlet);
1906 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_SLITLET,
1907 CPL_LESS_THAN, up_central_slitlet);
1908 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_FILTERED,
1909 CPL_EQUAL_TO, 0);
1910 int nblines =
1911 cpl_table_and_selected_double(line_table, MOO_LINE_TABLE_WAVE,
1912 CPL_EQUAL_TO, w);
1913 if (nblines > 0) {
1914 cpl_table *sel = cpl_table_extract_selected(line_table);
1915 double median =
1916 cpl_table_get_column_median(sel, MOO_LINE_TABLE_XDIFF);
1917 cpl_table_delete(sel);
1918 cpl_vector_set(vx, vsize, w);
1919 cpl_vector_set(vy, vsize, median);
1920 vsize++;
1921 }
1922 }
1923 cpl_vector_set_size(vx, vsize);
1924 cpl_vector_set_size(vy, vsize);
1925 double wmin = cpl_vector_get(vx, 0);
1926 double wmin_xdiff = cpl_vector_get(vy, 0);
1927 double wmax = cpl_vector_get(vx, vsize - 1);
1928 double wmax_xdiff = cpl_vector_get(vy, vsize - 1);
1929 cpl_bivector *fref = cpl_bivector_wrap_vectors(vx, vy);
1930 cpl_bivector *fout = cpl_bivector_new(1);
1931 for (int j = 0; j < catline; j++) {
1932 double w = cpl_table_get_double(catalog_lines,
1933 MOO_ARCLINE_LIST_WAVE, j, NULL);
1934 double median;
1935 if (w < wmin) {
1936 median = wmin_xdiff;
1937 }
1938 else if (w > wmax) {
1939 median = wmax_xdiff;
1940 }
1941 else {
1942 cpl_vector *fout_x = cpl_bivector_get_x(fout);
1943 cpl_vector_set(fout_x, 0, w);
1944 cpl_vector *fout_y = cpl_bivector_get_y(fout);
1945 cpl_bivector_interpolate_linear(fout, fref);
1946 median = cpl_vector_get(fout_y, 0);
1947 }
1948 cpl_table_select_all(slitlet_table_global);
1949 cpl_table_and_selected_int(slitlet_table_global,
1950 MOO_SLITLET_SHIFT_TABLE_SLITLET,
1951 CPL_EQUAL_TO, lo_central_slitlet + 1);
1952 cpl_table_and_selected_double(slitlet_table_global,
1953 MOO_LINE_TABLE_WAVE, CPL_EQUAL_TO, w);
1954 cpl_array *sel = cpl_table_where_selected(slitlet_table_global);
1955 int idx = cpl_array_get_cplsize(sel, 0, NULL);
1956 cpl_array_delete(sel);
1957 cpl_table_set_double(slitlet_table_global,
1958 MOO_SLITLET_SHIFT_TABLE_XDIFF, idx, median);
1959
1960 cpl_table_select_all(slitlet_table_global);
1961 cpl_table_and_selected_int(slitlet_table_global,
1962 MOO_SLITLET_SHIFT_TABLE_SLITLET,
1963 CPL_EQUAL_TO, up_central_slitlet - 1);
1964 cpl_table_and_selected_double(slitlet_table_global,
1965 MOO_LINE_TABLE_WAVE, CPL_EQUAL_TO, w);
1966 sel = cpl_table_where_selected(slitlet_table_global);
1967 idx = cpl_array_get_cplsize(sel, 0, NULL);
1968 cpl_array_delete(sel);
1969 cpl_table_set_double(slitlet_table_global,
1970 MOO_SLITLET_SHIFT_TABLE_XDIFF, idx, median);
1971 }
1972 cpl_bivector_delete(fout);
1973 cpl_bivector_unwrap_vectors(fref);
1974 cpl_vector_delete(vx);
1975 cpl_vector_delete(vy);
1976#if MOO_DEBUG_WAVESOL_DETECTED
1977 {
1978 char *name = cpl_sprintf("%s_refit%d_slitlet.fits", ext->extname,
1979 params->isrefit);
1980 cpl_table_save(slitlet_table_global, NULL, NULL, name,
1981 CPL_IO_CREATE);
1982 cpl_free(name);
1983 }
1984#endif
1985
1986 cpl_table *detected_global_step2 =
1987 moo_detected_table_new(0, guess == NULL);
1988 cpl_table *lines_global_step2 = moo_line_table_new(0);
1989
1990 for (int s = lo_central_slitlet + 1; s >= min_slitlet; s--) {
1991 cpl_table_select_all(result_table);
1992 int nb = cpl_table_and_selected_int(result_table,
1993 MOO_FIBRES_TABLE_SLITLET,
1994 CPL_EQUAL_TO, s);
1995 nb = cpl_table_and_selected_int(result_table,
1996 MOO_FIBRES_TABLE_HEALTH,
1997 CPL_NOT_EQUAL_TO, 0);
1998 nb = cpl_table_and_selected_int(result_table,
1999 MOO_FIBRES_TABLE_SPECTRO,
2000 CPL_EQUAL_TO, spectro);
2001 cpl_msg_info("moo_wavesol", "do slitlet %d : MOONS%d %d", s,
2002 spectro, nb);
2003 cpl_array *slitlet_sel = cpl_table_where_selected(result_table);
2004 for (int isel = 0; isel < nb; isel++) {
2005 int idx = cpl_array_get_cplsize(slitlet_sel, isel, NULL);
2006 int indexext_idx =
2007 cpl_table_get_int(result_table, MOO_FIBRES_TABLE_INDEXEXT,
2008 idx, NULL);
2009 int slitlet_idx =
2010 cpl_table_get_int(result_table, MOO_FIBRES_TABLE_SLITLET,
2011 idx, NULL);
2012 int ldetected = 0;
2013 int lfailed = 0;
2014 int lfitted = 0;
2015
2016 cpl_table *tfitted = NULL;
2017 cpl_table *tdetected = _moo_wavesol_fibre_using_guess(
2018 data, errs, guess, slitlet_table_global, indexext_idx,
2019 catalog_lines, winhsize, sigma_min, sigma_max, slitlet_idx,
2020 indexext_idx, extname, spectro, &tfitted, &ldetected,
2021 &lfailed, &lfitted);
2022 moo_table_append(detected_global_step2, tdetected);
2023 moo_table_append(lines_global_step2, tfitted);
2024 cpl_table_delete(tdetected);
2025 cpl_table_delete(tfitted);
2026 /*
2027 moo_fibres_table_set_detectline(result_table,type,idx,ldetected);
2028 moo_fibres_table_set_failedfit(result_table,type,idx,lfailed);
2029 moo_fibres_table_set_fitline(result_table,type,idx,lfitted);
2030 moo_fibres_table_set_rejectline(result_table,type,idx,lfitted);
2031 detectline +=ldetected;
2032 failedfit += lfailed;
2033 fitline += lfitted;
2034 */
2035 }
2036 cpl_array_delete(slitlet_sel);
2037
2038 for (int j = 0; j < catline; j++) {
2039 double w = cpl_table_get_double(catalog_lines,
2040 MOO_ARCLINE_LIST_WAVE, j, NULL);
2041 cpl_table_select_all(lines_global_step2);
2042 int nblines = cpl_table_and_selected_int(lines_global_step2,
2043 MOO_LINE_TABLE_SLITLET,
2044 CPL_EQUAL_TO, s);
2045
2046 nblines = cpl_table_and_selected_int(lines_global_step2,
2047 MOO_LINE_TABLE_FILTERED,
2048 CPL_EQUAL_TO, 0);
2049 nblines = cpl_table_and_selected_double(lines_global_step2,
2050 MOO_LINE_TABLE_WAVE,
2051 CPL_EQUAL_TO, w);
2052 double median = NAN;
2053 if (nblines > 0) {
2054 cpl_table *sel =
2055 cpl_table_extract_selected(lines_global_step2);
2056 median =
2057 cpl_table_get_column_median(sel, MOO_LINE_TABLE_XDIFF);
2058 cpl_table_delete(sel);
2059 }
2060 cpl_table_select_all(slitlet_table_global);
2061 cpl_table_and_selected_int(slitlet_table_global,
2062 MOO_SLITLET_SHIFT_TABLE_SLITLET,
2063 CPL_EQUAL_TO, s);
2064 cpl_table_and_selected_double(slitlet_table_global,
2065 MOO_LINE_TABLE_WAVE, CPL_EQUAL_TO,
2066 w);
2067 cpl_array *sel = cpl_table_where_selected(slitlet_table_global);
2068 int idx = cpl_array_get_cplsize(sel, 0, NULL);
2069 cpl_array_delete(sel);
2070 cpl_table_set_double(slitlet_table_global,
2071 MOO_SLITLET_SHIFT_TABLE_XDIFF, idx,
2072 median);
2073 }
2074 }
2075 for (int s = up_central_slitlet - 1; s <= max_slitlet; s++) {
2076 cpl_table_select_all(result_table);
2077 int nb = cpl_table_and_selected_int(result_table,
2078 MOO_FIBRES_TABLE_SLITLET,
2079 CPL_EQUAL_TO, s);
2080 nb = cpl_table_and_selected_int(result_table,
2081 MOO_FIBRES_TABLE_HEALTH,
2082 CPL_NOT_EQUAL_TO, 0);
2083 nb = cpl_table_and_selected_int(result_table,
2084 MOO_FIBRES_TABLE_SPECTRO,
2085 CPL_EQUAL_TO, spectro);
2086 cpl_array *slitlet_sel = cpl_table_where_selected(result_table);
2087 cpl_msg_info("moo_wavesol", "do slitlet %d : MOONS%d %d", s,
2088 spectro, nb);
2089 for (int isel = 0; isel < nb; isel++) {
2090 int idx = cpl_array_get_cplsize(slitlet_sel, isel, NULL);
2091 int indexext_idx =
2092 cpl_table_get_int(result_table, MOO_FIBRES_TABLE_INDEXEXT,
2093 idx, NULL);
2094 int slitlet_idx =
2095 cpl_table_get_int(result_table, MOO_FIBRES_TABLE_SLITLET,
2096 idx, NULL);
2097 int ldetected = 0;
2098 int lfailed = 0;
2099 int lfitted = 0;
2100
2101 cpl_table *tfitted = NULL;
2102 cpl_table *tdetected = _moo_wavesol_fibre_using_guess(
2103 data, errs, guess, slitlet_table_global, indexext_idx,
2104 catalog_lines, winhsize, sigma_min, sigma_max, slitlet_idx,
2105 indexext_idx, extname, spectro, &tfitted, &ldetected,
2106 &lfailed, &lfitted);
2107 moo_table_append(detected_global_step2, tdetected);
2108 moo_table_append(lines_global_step2, tfitted);
2109 cpl_table_delete(tdetected);
2110 cpl_table_delete(tfitted);
2111 /*
2112 moo_fibres_table_set_detectline(result_table,type,idx,ldetected);
2113 moo_fibres_table_set_failedfit(result_table,type,idx,lfailed);
2114 moo_fibres_table_set_fitline(result_table,type,idx,lfitted);
2115 moo_fibres_table_set_rejectline(result_table,type,idx,lfitted);
2116 detectline +=ldetected;
2117 failedfit += lfailed;
2118 fitline += lfitted;
2119 */
2120 }
2121 cpl_array_delete(slitlet_sel);
2122 for (int j = 0; j < catline; j++) {
2123 double w = cpl_table_get_double(catalog_lines,
2124 MOO_ARCLINE_LIST_WAVE, j, NULL);
2125 cpl_table_select_all(lines_global_step2);
2126 cpl_table_and_selected_int(lines_global_step2,
2127 MOO_LINE_TABLE_SLITLET, CPL_EQUAL_TO,
2128 s);
2129 cpl_table_and_selected_int(lines_global_step2,
2130 MOO_LINE_TABLE_FILTERED,
2131 CPL_EQUAL_TO, 0);
2132 int nblines = cpl_table_and_selected_double(lines_global_step2,
2133 MOO_LINE_TABLE_WAVE,
2134 CPL_EQUAL_TO, w);
2135 double median = NAN;
2136 if (nblines > 0) {
2137 cpl_table *sel =
2138 cpl_table_extract_selected(lines_global_step2);
2139 median =
2140 cpl_table_get_column_median(sel, MOO_LINE_TABLE_XDIFF);
2141 cpl_table_delete(sel);
2142 }
2143 cpl_table_select_all(slitlet_table_global);
2144 cpl_table_and_selected_int(slitlet_table_global,
2145 MOO_SLITLET_SHIFT_TABLE_SLITLET,
2146 CPL_EQUAL_TO, s);
2147 cpl_table_and_selected_double(slitlet_table_global,
2148 MOO_LINE_TABLE_WAVE, CPL_EQUAL_TO,
2149 w);
2150 cpl_array *sel = cpl_table_where_selected(slitlet_table_global);
2151 int idx = cpl_array_get_cplsize(sel, 0, NULL);
2152 cpl_array_delete(sel);
2153 cpl_table_set_double(slitlet_table_global,
2154 MOO_SLITLET_SHIFT_TABLE_XDIFF, idx,
2155 median);
2156 }
2157 }
2158#if MOO_DEBUG_WAVESOL_DETECTED
2159 {
2160 char *name = cpl_sprintf("%s_slitlet_step2.fits", ext->extname);
2161 cpl_table_save(slitlet_table_global, NULL, NULL, name,
2162 CPL_IO_CREATE);
2163 cpl_free(name);
2164 }
2165 {
2166 char *name = cpl_sprintf("%s_refit%d_slitlet_step2.fits",
2167 ext->extname, params->isrefit);
2168 cpl_table_save(detected_global_step2, NULL, NULL, name,
2169 CPL_IO_CREATE);
2170 cpl_free(name);
2171 }
2172 {
2173 char *name = cpl_sprintf("%s_lines_step2.fits", ext->extname);
2174 cpl_table_save(lines_global_step2, NULL, NULL, name, CPL_IO_CREATE);
2175 cpl_free(name);
2176 }
2177#endif
2178 cpl_table_delete(line_table);
2179 line_table = lines_global_step2;
2180 nb_line_table = cpl_table_get_nrow(line_table);
2181
2182 for (i = 0; i < nb_line_table; i++) {
2183 int rej;
2184 double x =
2185 cpl_table_get_double(line_table, line_table_xfit, i, NULL);
2186 int indexext_idx =
2187 cpl_table_get_int(line_table, MOO_LINE_TABLE_INDEXEXT, i, NULL);
2188 if (!isnan(x)) {
2189 double yc =
2190 moo_loc_single_eval_f_centroids(loc, x, indexext_idx, &rej);
2191 cpl_table_set_double(line_table, MOO_LINE_TABLE_YLOC, i, yc);
2192 }
2193 double nm =
2194 cpl_table_get_double(line_table, MOO_LINE_TABLE_WAVE, i, NULL);
2195 cpl_table_unselect_all(catalog_lines);
2196 cpl_table_or_selected_double(catalog_lines, MOO_LINE_TABLE_WAVE,
2197 CPL_GREATER_THAN, nm - 1E-5);
2198 cpl_size cat_nb =
2199 cpl_table_and_selected_double(catalog_lines,
2200 MOO_LINE_TABLE_WAVE,
2201 CPL_LESS_THAN, nm + 1E-5);
2202
2203 if (cat_nb == 1) {
2204 cpl_array *cat_indexes =
2205 cpl_table_where_selected(catalog_lines);
2206 cpl_size cat_idx = cpl_array_get_cplsize(cat_indexes, 0, NULL);
2207 cpl_array_delete(cat_indexes);
2208 double cat_flux =
2209 cpl_table_get_double(catalog_lines, MOO_LINE_TABLE_FLUX,
2210 cat_idx, NULL);
2211 const char *cat_name =
2212 cpl_table_get_string(catalog_lines, MOO_LINE_TABLE_NAME,
2213 cat_idx);
2214 cpl_table_set_string(line_table, MOO_LINE_TABLE_NAME, i,
2215 cat_name);
2216 cpl_table_set_double(line_table, MOO_LINE_TABLE_FLUX, i,
2217 cat_flux);
2218 }
2219 }
2220 cpl_table_delete(slitlet_table_global);
2221 cpl_table_delete(detected_global_step2);
2222
2223 for (int f = 1; f <= nb_fibres; f++) {
2224 int idx = cpl_array_get_cplsize(indexes, f - 1, NULL);
2225 int h = health[idx];
2226 int indexext_idx = indexext[idx];
2227 if (h == 1) {
2228 cpl_table_select_all(line_table);
2229 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_INDEXEXT,
2230 CPL_EQUAL_TO, indexext_idx);
2231 cpl_size nb =
2232 cpl_table_and_selected_int(line_table,
2233 MOO_LINE_TABLE_FILTERED,
2234 CPL_EQUAL_TO, 0);
2235 if (nb > 0) {
2236 cpl_table *sel = cpl_table_extract_selected(line_table);
2237 double xdiff =
2238 cpl_table_get_column_median(sel, MOO_LINE_TABLE_XDIFF);
2239 cpl_table_delete(sel);
2240 moo_fibres_table_set_xdiff(result_table, type, idx, xdiff);
2241 }
2242 }
2243 }
2244 }
2245
2246 if ((strcmp(control, MOO_WAVESOL_CONTROL_CHECK) == 0) ||
2247 (strcmp(control, MOO_WAVESOL_CONTROL_UPDATE) == 0)) {
2248 cpl_table *all_guess_line_table = moo_map_get_line_table(wmap);
2249 if (!cpl_table_has_column(all_guess_line_table, MOO_LINE_TABLE_XDIFF)) {
2250 cpl_table_new_column(all_guess_line_table, MOO_LINE_TABLE_XDIFF,
2251 CPL_TYPE_DOUBLE);
2252 }
2253 if (!cpl_table_has_column(all_guess_line_table,
2254 MOO_LINE_TABLE_WAVEDIFF)) {
2255 cpl_table_new_column(all_guess_line_table, MOO_LINE_TABLE_WAVEDIFF,
2256 CPL_TYPE_DOUBLE);
2257 }
2258 cpl_table_select_all(all_guess_line_table);
2259 cpl_table_and_selected_string(all_guess_line_table,
2260 MOO_LINE_TABLE_DETECTOR, CPL_EQUAL_TO,
2261 ext->extname);
2262
2263 cpl_table *guess_line_table =
2264 cpl_table_extract_selected(all_guess_line_table);
2265 for (int i = 1; i <= nb_fibres; i++) {
2266 int idx = cpl_array_get_cplsize(indexes, i - 1, NULL);
2267 int h = health[idx];
2268 int indexext_idx = indexext[idx];
2269 if (h == 1) {
2270 int rej;
2271 double xdiff =
2272 moo_fibres_table_get_xdiff(result_table, type, idx);
2273 cpl_table_select_all(guess_line_table);
2274 cpl_table_and_selected_int(guess_line_table,
2275 MOO_LINE_TABLE_INDEXEXT,
2276 CPL_EQUAL_TO, indexext_idx);
2277 cpl_size nb =
2278 cpl_table_and_selected_int(guess_line_table,
2279 MOO_LINE_TABLE_FILTERED,
2280 CPL_EQUAL_TO, 0);
2281 if (nb > 0) {
2282 cpl_array *sel = cpl_table_where_selected(guess_line_table);
2283 for (int j = 0; j < nb; j++) {
2284 int sel_idx = cpl_array_get_cplsize(sel, j, NULL);
2285 double xgauss =
2286 cpl_table_get_double(guess_line_table,
2287 MOO_LINE_TABLE_XGAUSS, sel_idx,
2288 &rej);
2289 cpl_table_set_double(guess_line_table,
2290 MOO_LINE_TABLE_XGAUSS, sel_idx,
2291 xgauss - xdiff);
2292 }
2293 cpl_array_delete(sel);
2294 }
2295 }
2296 }
2297 moo_table_append(line_table, guess_line_table);
2298 cpl_table_select_all(line_table);
2299 cpl_size nb = cpl_table_and_selected_int(guess_line_table,
2300 MOO_LINE_TABLE_FILTERED,
2301 CPL_EQUAL_TO, 0);
2302 if (nb > 0) {
2303 cpl_array *sel = cpl_table_where_selected(line_table);
2304 for (int j = 0; j < nb; j++) {
2305 int sel_idx = cpl_array_get_cplsize(sel, j, NULL);
2306 cpl_table_set_int(line_table, MOO_LINE_TABLE_MFITTED, sel_idx,
2307 0);
2308 }
2309 cpl_array_delete(sel);
2310 }
2311 cpl_table_delete(guess_line_table);
2312 }
2313
2314 const char *line_table_gfit = MOO_LINE_TABLE_MATCHED;
2315 if (guess != NULL) {
2316 line_table_gfit = MOO_LINE_TABLE_GFITTED;
2317 }
2318
2319 if (strcmp(model, MOO_WAVESOL_MODEL_1D) == 0) {
2320 cpl_msg_info("moo_wavesol", "Do Polynomial %s fit with degree %d",
2321 model, degx);
2322 for (int i = 1; i <= nb_fibres; i++) {
2323 int idx = cpl_array_get_cplsize(indexes, i - 1, NULL);
2324 int h = health[idx];
2325 if (h == 1) {
2326 _moo_wavesol_fit1d(loc, degx, i, res, niter, max_frac, kappa,
2327 &nb_sigclip, result_table, idx, ext->type,
2328 line_table, line_table_xfit);
2329 }
2330 else {
2331 for (int x = 1; x <= nx; x++) {
2332 cpl_image_set(res, x, i, NAN);
2333 }
2334 }
2335 }
2336 }
2337 else {
2338 cpl_msg_info("moo_wavesol",
2339 "Do Polynomial %s fit with X degree %d and Y degree %d",
2340 model, degx, degy);
2341 int i = 1;
2342 int slit_idx = -1;
2343 moo_tcheby2d_polynomial *sol = NULL;
2344 while (i <= nb_fibres) {
2345 int idx = cpl_array_get_cplsize(indexes, i - 1, NULL);
2346 int h = health[idx];
2347 if (h == 1) {
2348 if (slit_idx != slitlet[idx]) {
2349 moo_tcheby2d_polynomial_delete(sol);
2350 slit_idx = slitlet[idx];
2351 cpl_msg_debug("moo_wavesol", "Do slitlet %d :", slit_idx);
2352 cpl_errorstate prestate_fit2d = cpl_errorstate_get();
2353 sol = _moo_wavesol_fit2d(loc, res, info, degx, degy, niter,
2354 max_frac, kappa, &nb_sigclip,
2355 slit_idx, line_table,
2356 line_table_xfit, line_table_gfit);
2357 if (!cpl_errorstate_is_equal(prestate_fit2d)) {
2358 moo_tcheby2d_polynomial_delete(sol);
2359 sol = NULL;
2360 cpl_errorstate_dump(prestate_fit2d, CPL_FALSE,
2361 cpl_errorstate_dump_one);
2362 cpl_errorstate_set(prestate_fit2d);
2363 }
2364 }
2365
2366 cpl_image *ycentroids = moo_loc_single_get_f_centroids(loc);
2367 for (int x = 1; x <= nx; x++) {
2368 int rej;
2369
2370 double y =
2371 cpl_image_get(ycentroids, x, indexext[idx], &rej);
2372
2373 if (rej == 1) {
2374 cpl_image_set(res, x, i, NAN);
2375 }
2376 else {
2377 double v = NAN;
2378 if (sol != NULL) {
2379 v = moo_tcheby2d_polynomial_eval(sol, x, y);
2380 }
2381 cpl_image_set(res, x, i, v);
2382 }
2383 }
2384 }
2385 else {
2386 for (int x = 1; x <= nx; x++) {
2387 cpl_image_set(res, x, i, NAN);
2388 }
2389 }
2390 i++;
2391 }
2392 moo_tcheby2d_polynomial_delete(sol);
2393
2394 for (i = 1; i < nb_fibres; i++) {
2395 cpl_table_select_all(line_table);
2396 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_MFITTED,
2397 CPL_EQUAL_TO, 0);
2398 cpl_size nblines =
2399 cpl_table_and_selected_int(line_table, MOO_LINE_TABLE_INDEXEXT,
2400 CPL_EQUAL_TO, i);
2401 int idx = cpl_array_get_cplsize(indexes, i - 1, NULL);
2402 moo_fibres_table_set_rejectline(result_table, type, idx, nblines);
2403 }
2404 }
2405 // QC compute
2406 _moo_wavecal_qc(header, nb_sigclip, line_table);
2407
2408 *single_line_table = line_table;
2409
2410moo_try_cleanup:
2411 if (all_detected != NULL) {
2412 for (int i = 0; i < nb_fibres; i++) {
2413 cpl_table_delete(all_detected[i]);
2414 }
2415 cpl_free(all_detected);
2416 }
2417 if (all_fitted != NULL) {
2418 for (int i = 0; i < nb_fibres; i++) {
2419 cpl_table_delete(all_fitted[i]);
2420 }
2421 cpl_free(all_fitted);
2422 }
2423 if (!cpl_errorstate_is_equal(prestate)) {
2424 cpl_image_delete(res);
2425 res = NULL;
2426 cpl_msg_error(__func__, "Error in wavesol for file %s", ext->filename);
2427 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
2428 // Recover from the error(s) (Reset to prestate))
2429 cpl_errorstate_set(prestate);
2430 }
2431 return res;
2432}
2433
2434static cpl_table *
2435_arclines_get_caliblines(cpl_table *table,
2436 moo_detector_type type,
2437 int isGuess,
2438 int isrefit)
2439{
2440 cpl_table *result = NULL;
2441 int size = 0;
2442
2443 cpl_errorstate prestate = cpl_errorstate_get();
2444
2445 cpl_ensure(table != NULL, CPL_ERROR_NULL_INPUT, NULL);
2446
2447 const char *typename = moo_detector_get_name(type);
2448 const char *wavecaltype = MOO_ARCLINE_LIST_USEFINAL;
2449 if (isGuess) {
2450 wavecaltype = MOO_ARCLINE_LIST_USEGUESS;
2451 }
2452 else if (isrefit) {
2453 wavecaltype = MOO_ARCLINE_LIST_USEGUESS_REFIT;
2454 }
2455
2456 cpl_table_select_all(table);
2457 moo_try_check(size = cpl_table_and_selected_string(table,
2458 MOO_ARCLINE_LIST_BAND,
2459 CPL_EQUAL_TO, typename),
2460 " ");
2461 moo_try_check(size = cpl_table_and_selected_int(table, wavecaltype,
2462 CPL_EQUAL_TO, 1),
2463 " ");
2464
2465 if (size == 0) {
2466 cpl_msg_warning(__func__, "ARC_LINE_LIST %s no arclines found",
2467 typename);
2468 }
2469 else {
2470 result = cpl_table_extract_selected(table);
2471 }
2472moo_try_cleanup:
2473 if (!cpl_errorstate_is_equal(prestate)) {
2474 cpl_table_delete(result);
2475 result = NULL;
2476 }
2477 return result;
2478}
2479
2480/*----------------------------------------------------------------------------*/
2502/*----------------------------------------------------------------------------*/
2503static moo_map *
2504_moo_wavesol_refit(moo_ext *arc_ext,
2505 const char *lineCatname,
2506 cpl_table *lines,
2507 moo_spectral_format *sformat,
2508 moo_loc *loc,
2509 moo_map *wmap,
2510 moo_wavesol_params *params)
2511{
2512 moo_map *result = NULL;
2513 cpl_array *indexes = NULL;
2514 int *wavemap_degx = NULL;
2515 int wavemap_degy = 0;
2516 int *line_winhsize = NULL;
2517 cpl_image *guess_tab[6];
2518 cpl_propertylist *guess_headers[6];
2519
2520 cpl_errorstate prestate = cpl_errorstate_get();
2521 cpl_ensure(arc_ext != NULL, CPL_ERROR_NULL_INPUT, NULL);
2522 cpl_ensure(lineCatname != NULL, CPL_ERROR_NULL_INPUT, NULL);
2523 cpl_ensure(sformat != NULL, CPL_ERROR_NULL_INPUT, NULL);
2524 cpl_ensure(loc != NULL, CPL_ERROR_NULL_INPUT, NULL);
2525 cpl_ensure(params != NULL, CPL_ERROR_NULL_INPUT, NULL);
2526
2527 unsigned int badpix_level =
2529
2530 cpl_table *fibres_table = moo_ext_get_fibre_table(arc_ext);
2531 cpl_ensure(fibres_table != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
2532
2533 result = moo_map_new();
2534 result->primary_header = cpl_propertylist_new();
2535 moo_try_check(cpl_propertylist_append_string(result->primary_header,
2536 MOO_PFITS_PRO_WAVESOL_MODEL,
2537 params->model),
2538 " ");
2539 char *degx_tag = NULL;
2540 degx_tag = cpl_sprintf("%d,%d,%d", params->wavemap_degx[0],
2541 params->wavemap_degx[1], params->wavemap_degx[2]);
2542 moo_try_check(cpl_propertylist_append_string(result->primary_header,
2543 MOO_PFITS_PRO_WAVESOL_DEGX,
2544 degx_tag),
2545 " ");
2546 cpl_free(degx_tag);
2547 if (strcmp(params->model, MOO_WAVESOL_MODEL_2D) == 0) {
2548 moo_try_check(cpl_propertylist_append_int(result->primary_header,
2549 MOO_PFITS_PRO_WAVESOL_DEGY,
2550 params->wavemap_degy),
2551 " ");
2552 }
2553 cpl_table *result_table = cpl_table_duplicate(fibres_table);
2554
2555 moo_map_set_fibre_table(result, result_table);
2557 int isGuess = (wmap == NULL);
2558 cpl_table *global_line_table = moo_line_table_new(isGuess);
2559 moo_map_set_line_table(result, global_line_table);
2560
2561 if (wmap != NULL) {
2562 if (params->isrefit) {
2563 }
2564 wavemap_degx = params->wavemap_degx;
2565 wavemap_degy = params->wavemap_degy;
2566 line_winhsize = params->linefit_winhsize;
2567 cpl_errorstate stateA = cpl_errorstate_get();
2568 const char *guess_model =
2569 moo_pfits_get_pro_wavesol_model(wmap->primary_header);
2570 cpl_errorstate_set(stateA);
2571 moo_try_check(moo_fibres_table_add_wavecal_cols(result_table,
2572 wmap->fibre_table,
2573 guess_model),
2574 " ");
2575 if (guess_model != NULL) {
2576 const char *degx =
2577 moo_pfits_get_pro_wavesol_degx(wmap->primary_header);
2578 char *tag = NULL;
2579 if (strcmp(guess_model, MOO_WAVESOL_MODEL_2D) == 0) {
2580 int degy = moo_pfits_get_pro_wavesol_degy(wmap->primary_header);
2581 tag = cpl_sprintf("%s_x%s_y%d", guess_model, degx, degy);
2582 }
2583 else {
2584 tag = cpl_sprintf("%s_x%s", guess_model, degx);
2585 }
2586 cpl_msg_info(__func__, "Compute wave solution using %s guess", tag);
2587 cpl_propertylist_append_string(result->primary_header,
2588 MOO_PFITS_PRO_WAVEMAP_GUESS, tag);
2589 cpl_free(tag);
2590 }
2591
2592 for (int i = 0; i < 6; i++) {
2593 guess_tab[i] = wmap->data[i];
2594 guess_headers[i] = wmap->data_header[i];
2595 }
2596 }
2597 else {
2598 params->isrefit++;
2599 wavemap_degx = params->ppm_wavemap_degx;
2600 wavemap_degy = params->ppm_wavemap_degy;
2601 line_winhsize = params->linedetect_winhsize;
2602
2604 cpl_msg_info(__func__, "Compute first wave solution");
2605 for (int i = 0; i < 6; i++) {
2606 guess_tab[i] = NULL;
2607 guess_headers[i] = NULL;
2608 }
2609 }
2610
2611 cpl_msg_indent_more();
2612
2613 for (int i = 1; i <= 2; i++) {
2614 cpl_table_unselect_all(result_table);
2615 indexes = moo_fibres_table_get_spectro_indexext(result_table, i);
2616 const int *health =
2617 cpl_table_get_data_int_const(result_table, MOO_FIBRES_TABLE_HEALTH);
2618
2619 if (health != NULL) {
2620 for (int j = 0; j < 3; j++) {
2621 int idx = (i - 1) * 3 + j;
2622 double tolerance = params->tolerance[idx];
2623 int winhsize = line_winhsize[idx];
2624 int degx = wavemap_degx[idx];
2625 int linefit_recentre = params->linefit_recentre[idx];
2626
2627 int linedetect_nlines = params->linedetect_nlines[idx];
2628 double sigma_min = params->fwhm_min[idx] * CPL_MATH_SIG_FWHM;
2629 double sigma_max = params->fwhm_max[idx] * CPL_MATH_SIG_FWHM;
2630 double min_snr = params->min_snr[idx];
2631 cpl_image *guess = guess_tab[(i - 1) * 3 + j];
2632 cpl_propertylist *guess_header = guess_headers[(i - 1) * 3 + j];
2633
2634 moo_ext_single *ext_single =
2635 moo_ext_load_single(arc_ext, j, i, badpix_level);
2636 moo_loc_single *loc_single = moo_loc_get_single(loc, j, i);
2637 cpl_image *wave_single = NULL;
2638
2639 if (ext_single != NULL && loc_single != NULL) {
2640 cpl_table *sellines = NULL;
2641 cpl_propertylist *header = NULL;
2642 cpl_msg_info(
2643 __func__,
2644 "Compute wave solution for extension %s, winhsize:%d "
2645 "fwhm:[%f,%f] min_snr:%f recentre:%d",
2646 moo_detector_get_extname(j, i), winhsize,
2647 params->fwhm_min[idx], params->fwhm_max[idx], min_snr,
2648 linefit_recentre);
2649 moo_try_check(sellines =
2650 _arclines_get_caliblines(lines, j,
2651 isGuess,
2652 params->isrefit),
2653 "Error for Line table %s", lineCatname);
2654 if (sellines != NULL) {
2655 moo_spectral_format_info *info =
2656 moo_spectral_format_get(sformat, j, i);
2657 header = cpl_propertylist_new();
2658 cpl_table *line_table = NULL;
2659
2660 wave_single =
2661 _moo_wavesol_single(ext_single, loc_single, indexes,
2662 health, result_table, sellines,
2663 info->dispmin, info->dispmax,
2664 tolerance, info->direction,
2665 guess, guess_header, wmap,
2666 linedetect_nlines, winhsize,
2667 linefit_recentre, degx,
2668 wavemap_degy, info, sigma_min,
2669 sigma_max, min_snr, header,
2670 params, &line_table);
2671 moo_table_append(result->line_table, line_table);
2672 cpl_table_delete(line_table);
2674 cpl_table_delete(sellines);
2675 }
2676 else if (guess != NULL) {
2677 header = cpl_propertylist_new();
2678 wave_single = cpl_image_cast(guess, CPL_TYPE_DOUBLE);
2679 }
2680 moo_map_set_data(result, j, i, wave_single, header);
2681 }
2682 }
2683 }
2684
2685 cpl_array_delete(indexes);
2686 indexes = NULL;
2687 }
2688
2689 cpl_msg_indent_less();
2690
2691moo_try_cleanup:
2692 if (!cpl_errorstate_is_equal(prestate)) {
2693 moo_map_delete(result);
2694 cpl_array_delete(indexes);
2695 result = NULL;
2696 cpl_msg_error(__func__, "Error in wavesolution for EXT %s LOC %s",
2697 arc_ext->filename, loc->filename);
2698 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
2699 // Recover from the error(s) (Reset to prestate))
2700 cpl_errorstate_set(prestate);
2701 }
2702 return result;
2703}
2704/*----------------------------------------------------------------------------*/
2726/*----------------------------------------------------------------------------*/
2727moo_map *
2728moo_wavesol(moo_ext *arc_ext,
2729 const char *lineCatname,
2730 moo_spectral_format *sformat,
2731 moo_loc *loc,
2732 moo_map *wmap,
2733 moo_wavesol_params *params)
2734{
2735 moo_map *result = NULL;
2736 cpl_table *lines = NULL;
2737 int dowavesol = 1;
2738
2739 cpl_ensure(lineCatname != NULL, CPL_ERROR_NULL_INPUT, NULL);
2740 cpl_ensure(sformat != NULL, CPL_ERROR_NULL_INPUT, NULL);
2741 cpl_ensure(params != NULL, CPL_ERROR_NULL_INPUT, NULL);
2742
2743 if (sformat->mode == MOO_MODE_LR) {
2744 lines = cpl_table_load(lineCatname, 1, 0);
2745 }
2746 else {
2747 lines = cpl_table_load(lineCatname, 2, 0);
2748 }
2749
2750 /* check i refit is needed */
2751 if (wmap != NULL) {
2752 if (params->isrefit > 0) {
2753 dowavesol = 0;
2754 const char *refit_colname = MOO_ARCLINE_LIST_USEGUESS;
2755
2756 if (params->isrefit == 1) {
2757 refit_colname = MOO_ARCLINE_LIST_USEGUESS_REFIT;
2758 }
2759 if (cpl_table_has_column(lines, refit_colname)) {
2760 cpl_table_select_all(lines);
2761 int size =
2762 cpl_table_and_selected_int(lines,
2763 MOO_ARCLINE_LIST_USEGUESS_REFIT,
2764 CPL_EQUAL_TO, 1);
2765 if (size > 0) {
2766 cpl_msg_info("moo_wavesol", "Try doing a refit using %s",
2767 refit_colname);
2768 dowavesol = 1;
2769 }
2770 }
2771 }
2772 }
2773
2774 if (dowavesol) {
2775 result = _moo_wavesol_refit(arc_ext, lineCatname, lines, sformat, loc,
2776 wmap, params);
2777 /* check result */
2778 moo_map_check(result, sformat);
2779 }
2780
2781 cpl_table_delete(lines);
2782
2783 return result;
2784}
#define MOO_BADPIX_OUTSIDE_DATA_RANGE
Definition: moo_badpix.h:62
#define MOO_BADPIX_HOT
Definition: moo_badpix.h:51
#define MOO_BADPIX_COSMETIC
Definition: moo_badpix.h:57
const char * moo_detector_get_name(moo_detector_type type)
Get the extension name of a detector.
Definition: moo_detector.c:183
int moo_detector_get_spectro(int ntas)
Get the spctro name for a ntas.
Definition: moo_detector.c:165
const char * moo_detector_get_extname(moo_detector_type type, int ntas)
Get the extension name of a detector.
Definition: moo_detector.c:137
enum _moo_detector_type_ moo_detector_type
The type code type.
Definition: moo_detector.h:64
cpl_image * moo_ext_single_get_errs(moo_ext_single *self)
Get image of errs.
cpl_image * moo_ext_single_get_data(moo_ext_single *self)
Get image of data.
moo_ext_single * moo_ext_load_single(moo_ext *self, moo_detector_type type, int num, unsigned int level)
Load the type part in EXT and return it.
Definition: moo_ext.c:156
cpl_table * moo_ext_get_fibre_table(moo_ext *self)
Get the FIBRE TABLE in EXT.
Definition: moo_ext.c:344
cpl_error_code moo_fibres_table_add_wavecalguess_cols(cpl_table *table)
add wavecal additional columns
cpl_error_code moo_fibres_table_add_wavecal_cols(cpl_table *table, cpl_table *guess, const char *model)
add wavecal additional columns
cpl_error_code moo_fibres_table_set_matchline(cpl_table *table, moo_detector_type type, cpl_size row, int value)
set the number of match lines for the given detector type
cpl_error_code moo_fibres_table_set_failedfit(cpl_table *table, moo_detector_type type, cpl_size row, int value)
set the number od failedfit lines for the given detector type
cpl_array * moo_fibres_table_get_spectro_indexext(cpl_table *table, int num)
get the index of a spectro in the fibre table sort by spetcro,indexext
cpl_error_code moo_fibres_table_set_fitline(cpl_table *table, moo_detector_type type, cpl_size row, int value)
set the number of fit lines for the given detector type
double moo_fibres_table_get_xdiff(cpl_table *table, moo_detector_type type, cpl_size row)
Get xdiff for the given detector type.
cpl_error_code moo_fibres_table_set_xdiff(cpl_table *table, moo_detector_type type, cpl_size row, double value)
set the xdiff for the given fibre and detector type
cpl_error_code moo_fibres_table_set_detectline(cpl_table *table, moo_detector_type type, cpl_size row, int value)
set the number od detectline for the given detector type
cpl_error_code moo_fibres_table_set_rejectline(cpl_table *table, moo_detector_type type, cpl_size row, int value)
set the number of rejected lines for the given detector type
cpl_error_code moo_fibres_table_erase_extract_cols(cpl_table *table)
erase extract additional columns
cpl_table * moo_line_table_new(int isGuess)
create a line table
double moo_loc_single_eval_f_centroids(moo_loc_single *self, double x, int indexext, int *rej)
Get the Y fit centroid for a x value.
cpl_image * moo_loc_single_get_f_centroids(moo_loc_single *self)
Get image of fit centroids.
moo_loc_single * moo_loc_get_single(moo_loc *self, moo_detector_type type, int ntas)
Get the type part in LOC and return it.
Definition: moo_loc.c:155
cpl_error_code moo_map_check(moo_map *self, moo_spectral_format *sformat)
Save a moo_map to a FITS file.
Definition: moo_map.c:320
moo_map * moo_map_new(void)
Create a new moo_map.
Definition: moo_map.c:68
cpl_table * moo_map_get_line_table(moo_map *self)
Get the LINE TABLE extension of a map.
Definition: moo_map.c:84
cpl_error_code moo_map_set_data(moo_map *self, moo_detector_type type, int ntas, cpl_image *data, cpl_propertylist *header)
set map data for relevant extension
Definition: moo_map.c:164
void moo_map_delete(moo_map *self)
Delete a moo_map.
Definition: moo_map.c:236
void moo_spectral_format_info_delete(moo_spectral_format_info *self)
Delete a moo_spectral_format_info.
moo_spectral_format_info * moo_spectral_format_get(moo_spectral_format *self, moo_detector_type type, int ntas)
Get the spectral format information for a given ARM.
moo_map * moo_wavesol(moo_ext *arc_ext, const char *lineCatname, moo_spectral_format *sformat, moo_loc *loc, moo_map *wmap, moo_wavesol_params *params)
Computes the wavelength solution from 1D extracted arc spectra.
Definition: moo_wavesol.c:2728
const char * moo_pfits_get_pro_wavesol_degx(const cpl_propertylist *plist)
find out the PRO.WAVESOL.DEGX value
Definition: moo_pfits.c:1432
const char * moo_pfits_get_pro_wavesol_model(const cpl_propertylist *plist)
find out the PRO.WAVESOL.MODEL value
Definition: moo_pfits.c:1370
int moo_pfits_get_pro_wavesol_degy(const cpl_propertylist *plist)
find out the PRO.WAVESOL.DEGY value
Definition: moo_pfits.c:1452
cpl_error_code moo_qc_set_wavecal_residwave_std(cpl_propertylist *plist, double val)
Set the QC.WAVECAL.RESIDWAVE.STD value.
Definition: moo_qc.c:2185
cpl_error_code moo_qc_set_wavecal_validfibre(cpl_propertylist *plist, int val)
Set the QC.WAVECAL.VALIDFIBRE value.
Definition: moo_qc.c:2030
cpl_error_code moo_qc_set_wavecal_catline(cpl_propertylist *plist, int val)
Set the QC.WAVECAL.CATLINE value.
Definition: moo_qc.c:1826
cpl_error_code moo_qc_set_wavecal_disp_max(cpl_propertylist *plist, double val)
Set the QC.WAVECAL.DISP.MAX value.
Definition: moo_qc.c:2092
cpl_error_code moo_qc_set_wavecal_matchline(cpl_propertylist *plist, int val)
Set the QC.WAVECAL.MATCHLINE value.
Definition: moo_qc.c:1942
cpl_error_code moo_qc_set_wavecal_failedfit(cpl_propertylist *plist, int val)
Set the QC.WAVECAL.FAILEDFIT value.
Definition: moo_qc.c:1884
cpl_error_code moo_qc_set_wavecal_clipline(cpl_propertylist *plist, int val)
Set the QC.WAVECAL.CLIPLINE value.
Definition: moo_qc.c:1971
cpl_error_code moo_qc_set_wavecal_residwave_med(cpl_propertylist *plist, double val)
Set the QC.WAVECAL.RESIDWAVE.MED value.
Definition: moo_qc.c:2154
cpl_error_code moo_qc_set_wavecal_disp_min(cpl_propertylist *plist, double val)
Set the QC.WAVECAL.DISP.MIN value.
Definition: moo_qc.c:2061
cpl_error_code moo_qc_set_wavecal_resol_med(cpl_propertylist *plist, double val)
Set the QC.WAVECAL.RESOL.MED value.
Definition: moo_qc.c:2123
cpl_error_code moo_qc_set_wavecal_detectline(cpl_propertylist *plist, int val)
Set the QC.WAVECAL.DETECTLINE value.
Definition: moo_qc.c:1855
cpl_error_code moo_qc_set_wavecal_fitline(cpl_propertylist *plist, int val)
Set the QC.WAVECAL.FITLINE value.
Definition: moo_qc.c:1913
moo_tcheby_polynomial * moo_tcheby_polynomial_fit(cpl_bivector *data, int degree, double xmin, double xmax)
Computes Tchebitchev transformation of data.
Definition: moo_utils.c:573
moo_tcheby2d_polynomial * moo_tcheby2d_polynomial_fit(cpl_vector *in_x, int xdegree, double xmin, double xmax, cpl_vector *in_y, int ydegree, double ymin, double ymax, cpl_vector *in_l, double lmin, double lmax)
Computes Tchebitchev transformation of data.
Definition: moo_utils.c:667
cpl_error_code moo_barycenter_fit(cpl_bivector *points, double *center, double *width)
Fit positions using weighted fluxes.
Definition: moo_utils.c:254