41 #include "irplib_plugin.h"
42 #include "irplib_utils.h"
43 #include "irplib_distortion.h"
44 #include "irplib_wlxcorr.h"
46 #include "sofi_utils.h"
47 #include "sofi_wavelength.h"
48 #include "sofi_pfits.h"
55 #define RECIPE_STRING "sofi_spc_arc"
57 #define SOFI_ARC_SATURATION 20000
63 static cpl_error_code sofi_spc_arc_reduce(cpl_frameset *,
64 const cpl_parameterlist *,
65 const char *,
const char *,
68 static cpl_table * sofi_spc_arc_compute(
const cpl_image *,
const char *,
69 const char *,
const char *,
const char *, cpl_table **, cpl_image **);
70 static cpl_error_code sofi_spc_arc_save(cpl_frameset *,
const cpl_table *,
72 const cpl_image *,
const char *,
74 const cpl_parameterlist *);
75 static int sofi_spc_arc_compare(
const cpl_frame *,
const cpl_frame *);
76 static int * sofi_spc_arc_find_lamps(
const cpl_frameset *);
77 static int sofi_is_xenon_lamp_active(
const cpl_propertylist *);
78 static int sofi_is_neon_lamp_active(
const cpl_propertylist *);
80 cpl_recipe_define(sofi_spc_arc, SOFI_BINARY_VERSION,
81 "Lars Lundin", PACKAGE_BUGREPORT,
"2002,2003,2009",
82 "SOFI Spectro arc recipe",
83 RECIPE_STRING
" -- SOFI Spectro arc recipe.\n"
84 "The files listed in the Set Of Frames (sof-file) "
86 "raw-file.fits "SOFI_SPC_ARC_RAW
" or\n"
87 "xe-cat.fits "SOFI_CALPRO_XE_CAT
" or\n"
88 "ne-cat.fits "SOFI_CALPRO_NE_CAT
"\n");
114 } sofi_spc_arc_config;
130 cpl_error_code sofi_spc_arc_fill_parameterlist(cpl_parameterlist *
self)
132 const char * context = PACKAGE
"." RECIPE_STRING;
135 cpl_ensure_code(
self, CPL_ERROR_NULL_INPUT);
140 err = irplib_parameterlist_set_string(
self, PACKAGE, RECIPE_STRING,
141 "rejected",
"100,100",
"rej", context,
142 "Left, right rejections [pixel]");
143 cpl_ensure_code(!err, err);
146 err = irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
"subdark",
147 CPL_FALSE, NULL, context,
148 "Enable dark subtraction");
149 cpl_ensure_code(!err, err);
152 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
"arc_max_w",
153 33, NULL, context,
"Maximum supported "
154 "arc width [pixel]");
155 cpl_ensure_code(!err, err);
158 err = irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
"out_corr",
159 CPL_FALSE, NULL, context,
160 "Enable correction of output images");
161 cpl_ensure_code(!err, err);
164 err = irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
"display",
165 CPL_FALSE, NULL, context,
167 cpl_ensure_code(!err, err);
170 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
"degree",
171 2, NULL, context,
"Degree of the "
172 "wavelength dispersion polynomial");
173 cpl_ensure_code(!err, err);
176 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
177 "wl_nsamples", 100, NULL, context,
178 "Number of samples for the wavelength "
180 cpl_ensure_code(!err, err);
183 err = irplib_parameterlist_set_double(
self, PACKAGE, RECIPE_STRING,
184 "wl_err", 1000.0, NULL, context,
185 "The wavelength error [Angstrom]");
186 cpl_ensure_code(!err, err);
189 err = irplib_parameterlist_set_string(
self, PACKAGE, RECIPE_STRING,
190 "lines", NULL, NULL, context,
192 cpl_ensure_code(!err, err);
195 err = irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
"ppm",
196 CPL_FALSE, NULL, context,
197 "Enable Point Pattern Matching");
198 cpl_ensure_code(!err, err);
200 return CPL_ERROR_NONE;
212 static int sofi_spc_arc(cpl_frameset * framelist,
213 const cpl_parameterlist * parlist)
215 cpl_errorstate prestate = cpl_errorstate_get();
217 cpl_size * labels = NULL;
219 const int nframes = cpl_frameset_get_size(framelist);
223 cpl_frameset * arcframes = NULL;
224 cpl_frameset * arc_one = NULL;
228 sofi_spc_arc_config.lines = NULL;
233 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
235 bug_if(sval == NULL);
237 skip_if (sscanf(sval,
"%d,%d",
238 &sofi_spc_arc_config.rej_left,
239 &sofi_spc_arc_config.rej_right) != 2);
242 sofi_spc_arc_config.out_corr
243 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
246 sofi_spc_arc_config.subdark
247 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
250 sofi_spc_arc_config.ppm
251 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
254 sofi_spc_arc_config.degree
255 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
259 sofi_spc_arc_config.wl_nsamples
260 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
264 sofi_spc_arc_config.wl_err
265 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
269 sofi_spc_arc_config.arc_max_w
270 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
274 sofi_spc_arc_config.display
275 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
279 sofi_spc_arc_config.lines
280 = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
288 error_if (arcframes == NULL, CPL_ERROR_DATA_NOT_FOUND,
289 "Cannot find arc frames in the input frame set");
291 narcs = cpl_frameset_get_size(arcframes);
298 labels = cpl_frameset_labelise(arcframes, sofi_spc_arc_compare, &nlabels);
299 error_if (labels == NULL, CPL_ERROR_ILLEGAL_INPUT,
300 "Cannot labelise the input frames");
303 for (i=0; i < nlabels; i++) {
306 cpl_msg_info(cpl_func,
"Reducing set %d/%d", i+1, (
int)nlabels);
308 sofi_spc_arc_config.set_nb = i+1;
310 cpl_frameset_delete(arc_one);
311 arc_one = cpl_frameset_extract(arcframes, labels, i);
314 if (sofi_spc_arc_reduce(framelist, parlist, xe, ne, arc_one, prestate))
315 (void)cpl_error_set_message(cpl_func, cpl_error_get_code(),
"Could "
316 "not reduce set %d of %d with %d arc "
317 "frame(s)", i+1, (int)nlabels,
318 (
int)cpl_frameset_get_size(arc_one));
321 error_if (cpl_frameset_get_size(framelist) == nframes,
322 CPL_ERROR_ILLEGAL_INPUT,
"No products produced from %d arc "
323 "frames grouped into %d set(s)", narcs, (
int)nlabels);
327 cpl_frameset_delete(arcframes);
328 cpl_frameset_delete(arc_one);
331 return cpl_error_get_code();
347 static cpl_error_code sofi_spc_arc_reduce(cpl_frameset * set_tot,
348 const cpl_parameterlist * parlist,
351 const cpl_frameset * arcframes,
352 cpl_errorstate prestate)
359 int * lamps = sofi_spc_arc_find_lamps(arcframes);
360 const int nframes = cpl_frameset_get_size(arcframes);
361 char lines_table[16];
362 const cpl_frame * cur_frame;
363 const char * cur_fname;
364 cpl_image * xenon = NULL;
365 cpl_image * neon = NULL;
366 cpl_image * xe_ne = NULL;
367 cpl_image * dark = NULL;
368 cpl_image * to_compute;
369 cpl_table * arcs_fwhm;
370 cpl_image * out_corr;
371 cpl_table * out_table;
375 sofi_spc_arc_config.frame_nb = 0;
377 if (lamps == NULL)
return cpl_error_set_where(cpl_func);
380 for (i=0; i<nframes; i++) {
381 cur_frame = cpl_frameset_get_position_const(arcframes, i);
382 cur_fname = cpl_frame_get_filename(cur_frame);
383 if ((lamps[i] == 0) && (dark == NULL)) {
384 cpl_msg_info(cpl_func,
"Dark image: [%s]", cur_fname);
385 dark = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
386 }
else if ((lamps[i] == 1) && (xenon == NULL)) {
387 cpl_msg_info(cpl_func,
"Xenon lamp: [%s]", cur_fname);
388 xenon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
389 }
else if ((lamps[i] == 2) && (neon == NULL)) {
390 cpl_msg_info(cpl_func,
"Neon lamp: [%s]", cur_fname);
391 neon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
392 }
else if ((lamps[i] == 3) && (xe_ne == NULL)) {
393 cpl_msg_info(cpl_func,
"Xenon+Neon lamp: [%s]", cur_fname);
394 xe_ne = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
400 if (!xenon && !neon && !xe_ne) {
401 cpl_image_delete(dark);
402 return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
403 "Neither xenon nor neon lamp activated");
407 cur_frame = cpl_frameset_get_position_const(arcframes, 0);
408 cur_fname = cpl_frame_get_filename(cur_frame);
412 if (!cpl_errorstate_is_equal(prestate)) {
413 cpl_msg_warning(cpl_func,
"Resetting CPL error before reducing "
415 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
416 cpl_errorstate_set(prestate);
418 if (dark) to_compute = cpl_image_subtract_create(xenon, dark);
419 else to_compute = cpl_image_duplicate(xenon);
420 cpl_image_delete(xenon);
421 strcpy(lines_table,
"Xe");
424 cpl_msg_info(cpl_func,
"Apply the reduction");
425 sofi_spc_arc_config.frame_nb ++;
426 cpl_msg_indent_more();
427 if ((out_table = sofi_spc_arc_compute(to_compute, cur_fname,
428 lines_table, xe, ne, &arcs_fwhm, &out_corr)) == NULL) {
429 cpl_msg_error(cpl_func,
"arc reduction computation failed");
430 cpl_image_delete(to_compute);
433 cpl_image_delete(to_compute);
434 cpl_msg_info(cpl_func,
"Save the products");
435 sofi_spc_arc_save(set_tot, out_table, arcs_fwhm, out_corr,
436 lines_table, arcframes, parlist);
437 cpl_table_delete(out_table);
438 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
439 if (out_corr) cpl_image_delete(out_corr);
441 cpl_msg_indent_less();
446 if (!cpl_errorstate_is_equal(prestate)) {
447 cpl_msg_warning(cpl_func,
"Resetting CPL error before reducing "
449 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
450 cpl_errorstate_set(prestate);
452 if (dark) to_compute = cpl_image_subtract_create(neon, dark);
453 else to_compute = cpl_image_duplicate(neon);
454 cpl_image_delete(neon);
455 strcpy(lines_table,
"Ne");
458 cpl_msg_info(cpl_func,
"Apply the reduction");
459 sofi_spc_arc_config.frame_nb ++;
460 cpl_msg_indent_more();
461 if ((out_table = sofi_spc_arc_compute(to_compute, cur_fname,
462 lines_table, xe, ne, &arcs_fwhm, &out_corr)) == NULL) {
463 cpl_msg_error(cpl_func,
"arc reduction computation failed");
464 cpl_image_delete(to_compute);
467 cpl_image_delete(to_compute);
468 cpl_msg_info(cpl_func,
"Save the products");
469 sofi_spc_arc_save(set_tot, out_table, arcs_fwhm, out_corr,
470 lines_table, arcframes, parlist);
471 cpl_table_delete(out_table);
472 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
473 if (out_corr) cpl_image_delete(out_corr);
475 cpl_msg_indent_less();
481 if (!cpl_errorstate_is_equal(prestate)) {
482 cpl_msg_warning(cpl_func,
"Resetting CPL error before reducing "
484 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
485 cpl_errorstate_set(prestate);
487 if (dark) to_compute = cpl_image_subtract_create(xe_ne, dark);
488 else to_compute = cpl_image_duplicate(xe_ne);
489 cpl_image_delete(xe_ne);
490 strcpy(lines_table,
"Xe+Ne");
493 cpl_msg_info(cpl_func,
"Apply the reduction");
494 sofi_spc_arc_config.frame_nb ++;
495 cpl_msg_indent_more();
496 if ((out_table = sofi_spc_arc_compute(to_compute, cur_fname,
497 lines_table, xe, ne, &arcs_fwhm, &out_corr)) == NULL) {
498 cpl_msg_error(cpl_func,
"arc reduction computation failed");
499 cpl_image_delete(to_compute);
502 cpl_image_delete(to_compute);
503 cpl_msg_info(cpl_func,
"Save the products");
504 sofi_spc_arc_save(set_tot, out_table, arcs_fwhm, out_corr,
505 lines_table, arcframes, parlist);
506 cpl_table_delete(out_table);
507 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
508 if (out_corr) cpl_image_delete(out_corr);
510 cpl_msg_indent_less();
512 cpl_image_delete(dark);
514 return cpl_error_get_code();
531 static cpl_table * sofi_spc_arc_compute(
532 const cpl_image * in,
533 const char * in_name,
534 const char * lines_table,
537 cpl_table ** arcs_fwhm,
538 cpl_image ** out_corr)
542 int xmin, ymin, xmax, ymax;
544 cpl_mask * saturation_map;
546 cpl_polynomial * distor_poly_flipped;
547 cpl_polynomial * distor_poly;
548 cpl_polynomial * poly2d_id;
549 cpl_vector * profile;
551 cpl_apertures * arcs;
552 cpl_polynomial * phdisprel;
553 cpl_polynomial * disprel;
556 double a, b, c, d, e, xc;
557 cpl_size power_flipped[2];
558 double fwhm_x, fwhm_y;
559 cpl_vector * fwhm_valid;
563 nx = cpl_image_get_size_x(in);
564 ny = cpl_image_get_size_y(in);
569 xmin = sofi_spc_arc_config.rej_left + 1;
570 xmax = nx - sofi_spc_arc_config.rej_right;
575 saturation_map = cpl_mask_threshold_image_create(in,
576 SOFI_ARC_SATURATION, DBL_MAX);
577 if (saturation_map != NULL) {
578 sofi_spc_arc_config.nb_saturated = cpl_mask_count(saturation_map);
579 cpl_mask_delete(saturation_map);
581 sofi_spc_arc_config.nb_saturated = 0;
585 cpl_msg_info(cpl_func,
"Estimate the distortion");
586 cpl_msg_indent_more();
588 flipped = cpl_image_duplicate(in);
589 cpl_image_flip(flipped, 1);
590 if ((distor_poly_flipped = irplib_distortion_estimate(flipped,
591 ymin, xmin, ymax, xmax,
592 sofi_spc_arc_config.subdark, SOFI_ARC_SATURATION,
593 sofi_spc_arc_config.arc_max_w, 0.33,2,&arcs)) == NULL) {
594 cpl_msg_error(cpl_func,
"cannot estimage distortion");
595 cpl_image_delete(flipped);
596 cpl_msg_indent_less();
599 cpl_image_delete(flipped);
600 cpl_msg_indent_less();
603 distor_poly = cpl_polynomial_duplicate(distor_poly_flipped);
604 power[0] = 1; power[1] = 0; power_flipped[0] = 0; power_flipped[1] = 1;
605 cpl_polynomial_set_coeff(distor_poly, power,
606 cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
608 power[0] = 2; power[1] = 0; power_flipped[0] = 0; power_flipped[1] = 2;
609 cpl_polynomial_set_coeff(distor_poly, power,
610 cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
612 power[0] = 0; power[1] = 1; power_flipped[0] = 1; power_flipped[1] = 0;
613 cpl_polynomial_set_coeff(distor_poly, power,
614 cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
616 power[0] = 0; power[1] = 2; power_flipped[0] = 2; power_flipped[1] = 0;
617 cpl_polynomial_set_coeff(distor_poly, power,
618 cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
619 cpl_polynomial_delete(distor_poly_flipped);
622 cpl_msg_info(cpl_func,
"Correct the distortion");
623 cpl_msg_indent_more();
624 in_corr = cpl_image_duplicate(in);
627 poly2d_id = cpl_polynomial_new(2);
628 power[0] = 1; power[1] = 0;
629 cpl_polynomial_set_coeff(poly2d_id, power, 1.0);
632 profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES);
633 cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_DEFAULT,
634 CPL_KERNEL_DEF_WIDTH);
637 if (cpl_image_warp_polynomial(in_corr, in, poly2d_id, distor_poly,
638 profile, CPL_KERNEL_DEF_WIDTH, profile,
639 CPL_KERNEL_DEF_WIDTH) != CPL_ERROR_NONE) {
640 cpl_msg_error(cpl_func,
"cannot correct the distortion");
641 cpl_image_delete(in_corr);
642 cpl_polynomial_delete(poly2d_id);
643 cpl_polynomial_delete(distor_poly);
644 cpl_vector_delete(profile);
645 cpl_msg_indent_less();
648 cpl_polynomial_delete(poly2d_id);
649 cpl_vector_delete(profile);
650 cpl_msg_indent_less();
653 cpl_msg_info(cpl_func,
"Compute the FWHM of the detected arcs");
655 *arcs_fwhm = cpl_table_new(cpl_apertures_get_size(arcs));
656 cpl_table_new_column(*arcs_fwhm,
"POS", CPL_TYPE_DOUBLE);
657 cpl_table_new_column(*arcs_fwhm,
"FWHM", CPL_TYPE_DOUBLE);
658 cpl_table_new_column(*arcs_fwhm,
"FLUX", CPL_TYPE_DOUBLE);
660 sofi_spc_arc_config.fwhm_good = 0;
661 for (i=0; i<cpl_apertures_get_size(arcs); i++) {
662 cpl_table_set_double(*arcs_fwhm,
"POS", i,
663 cpl_apertures_get_centroid_x(arcs, i+1));
664 cpl_table_set_double(*arcs_fwhm,
"FLUX", i,
665 cpl_apertures_get_flux(arcs, i+1));
666 if (cpl_image_get_fwhm(in_corr, cpl_apertures_get_centroid_x(arcs, i+1),
667 512, &fwhm_x, &fwhm_y) != CPL_ERROR_NONE) {
668 cpl_msg_warning(cpl_func,
"Cannot get the FWHM");
671 cpl_table_set_double(*arcs_fwhm,
"FWHM", i, fwhm_x);
672 if (fwhm_x > 0) sofi_spc_arc_config.fwhm_good ++;
674 cpl_apertures_delete(arcs);
677 if (sofi_spc_arc_config.fwhm_good > 0) {
678 fwhm_valid = cpl_vector_new(sofi_spc_arc_config.fwhm_good);
679 sofi_spc_arc_config.fwhm_good = 0;
680 for (i=0; i<cpl_table_get_nrow(*arcs_fwhm); i++) {
681 fwhm_x = cpl_table_get_double(*arcs_fwhm,
"FWHM", i, NULL);
683 cpl_vector_set(fwhm_valid, sofi_spc_arc_config.fwhm_good,
685 sofi_spc_arc_config.fwhm_good ++;
688 sofi_spc_arc_config.fwhm_med = cpl_vector_get_median_const(fwhm_valid);
689 cpl_vector_delete(fwhm_valid);
690 }
else sofi_spc_arc_config.fwhm_med = 0.0;
696 cpl_msg_error(cpl_func,
"cannot get the slit width");
697 cpl_polynomial_delete(distor_poly);
698 cpl_image_delete(in_corr);
699 cpl_table_delete(*arcs_fwhm);
705 cpl_msg_info(cpl_func,
"Get the dispersion estimation");
706 cpl_msg_indent_more();
708 cpl_msg_error(cpl_func,
"cannot estimate the dispersion relation");
709 cpl_polynomial_delete(distor_poly);
710 cpl_image_delete(in_corr);
711 cpl_table_delete(*arcs_fwhm);
713 cpl_msg_indent_less();
716 power[0] = 0; power[1] = 1;
717 a = cpl_polynomial_get_coeff(phdisprel, power);
718 b = cpl_polynomial_get_coeff(phdisprel, power + 1);
719 cpl_msg_info(cpl_func,
"f(x)=%g + %g*x", a, b);
720 cpl_msg_indent_less();
723 cpl_msg_info(cpl_func,
"Compute the dispersion relation");
724 cpl_msg_indent_more();
726 phdisprel, slit_width, sofi_spc_arc_config.degree,
727 sofi_spc_arc_config.wl_err,
728 sofi_spc_arc_config.wl_nsamples,
729 sofi_spc_arc_config.ppm, sofi_spc_arc_config.display,
731 cpl_msg_error(cpl_func,
"cannot compute the dispersion relation");
732 cpl_polynomial_delete(distor_poly);
733 cpl_image_delete(in_corr);
734 cpl_polynomial_delete(phdisprel);
735 cpl_table_delete(*arcs_fwhm);
737 cpl_msg_indent_less();
740 if (sofi_spc_arc_config.out_corr) {
744 cpl_image_delete(in_corr);
748 if (sofi_spc_arc_config.display && sofi_spc_arc_config.lines != NULL &&
749 sofi_spc_arc_config.lines[0] != (
char)0) {
751 cpl_bivector * lines_biv
752 = cpl_bivector_read(sofi_spc_arc_config.lines);
753 const int nlines = cpl_bivector_get_size(lines_biv);
755 if (nlines > sofi_spc_arc_config.degree) {
759 = cpl_matrix_wrap(1, nlines, cpl_bivector_get_x_data(lines_biv));
760 cpl_polynomial * poly_sol = cpl_polynomial_new(1);
762 if (!cpl_polynomial_fit(poly_sol, xpos, NULL,
763 cpl_bivector_get_y(lines_biv), NULL,
765 &(sofi_spc_arc_config.degree))) {
766 irplib_wlxcorr_plot_solution(phdisprel, disprel, poly_sol, 1,
769 (void)cpl_matrix_unwrap(xpos);
770 cpl_polynomial_delete(poly_sol);
772 cpl_bivector_delete(lines_biv);
774 cpl_polynomial_delete(phdisprel);
775 cpl_msg_info(cpl_func,
"Cross correlation factor: %g", xc);
776 power[0] = 0; power[1] = 1; power[2] = 2; power[3] = 3; power[4] = 4;
777 a = b = c = d = e = 0.0;
778 degree = cpl_polynomial_get_degree(disprel);
779 a = cpl_polynomial_get_coeff(disprel, power);
780 if (degree > 0) b = cpl_polynomial_get_coeff(disprel, power + 1);
781 if (degree > 1) c = cpl_polynomial_get_coeff(disprel, power + 2);
782 if (degree > 2) d = cpl_polynomial_get_coeff(disprel, power + 3);
783 if (degree > 3) e = cpl_polynomial_get_coeff(disprel, power + 4);
784 cpl_polynomial_delete(disprel);
786 cpl_msg_info(cpl_func,
"f(x)=%g", a);
788 cpl_msg_info(cpl_func,
"f(x)=%g + %g*x", a, b);
790 cpl_msg_info(cpl_func,
"f(x)=%g + %g*x + %g*x^2", a, b, c);
792 cpl_msg_info(cpl_func,
"f(x)=%g + %g*x + %g*x^2 + %g*x^3", a, b, c, d);
794 cpl_msg_info(cpl_func,
"f(x)=%g + %g*x + %g*x^2 + %g*x^3 + %g*x^4",
796 cpl_msg_indent_less();
799 out_tab = cpl_table_new(6);
802 cpl_table_new_column(out_tab,
"Degree_of_x", CPL_TYPE_INT);
803 cpl_table_new_column(out_tab,
"Degree_of_y", CPL_TYPE_INT);
804 cpl_table_new_column(out_tab,
"poly2d_coef", CPL_TYPE_DOUBLE);
805 power[0] = 0; power[1] = 0;
806 cpl_table_set_int(out_tab,
"Degree_of_x", 0, power[0]);
807 cpl_table_set_int(out_tab,
"Degree_of_y", 0, power[1]);
808 cpl_table_set_double(out_tab,
"poly2d_coef", 0,
809 cpl_polynomial_get_coeff(distor_poly, power));
810 power[0] = 1; power[1] = 0;
811 cpl_table_set_int(out_tab,
"Degree_of_x", 1, power[0]);
812 cpl_table_set_int(out_tab,
"Degree_of_y", 1, power[1]);
813 cpl_table_set_double(out_tab,
"poly2d_coef", 1,
814 cpl_polynomial_get_coeff(distor_poly, power));
815 power[0] = 0; power[1] = 1;
816 cpl_table_set_int(out_tab,
"Degree_of_x", 2, power[0]);
817 cpl_table_set_int(out_tab,
"Degree_of_y", 2, power[1]);
818 cpl_table_set_double(out_tab,
"poly2d_coef", 2,
819 cpl_polynomial_get_coeff(distor_poly, power));
820 power[0] = 1; power[1] = 1;
821 cpl_table_set_int(out_tab,
"Degree_of_x", 3, power[0]);
822 cpl_table_set_int(out_tab,
"Degree_of_y", 3, power[1]);
823 cpl_table_set_double(out_tab,
"poly2d_coef", 3,
824 cpl_polynomial_get_coeff(distor_poly, power));
825 power[0] = 2; power[1] = 0;
826 cpl_table_set_int(out_tab,
"Degree_of_x", 4, power[0]);
827 cpl_table_set_int(out_tab,
"Degree_of_y", 4, power[1]);
828 cpl_table_set_double(out_tab,
"poly2d_coef", 4,
829 cpl_polynomial_get_coeff(distor_poly, power));
830 power[0] = 0; power[1] = 2;
831 cpl_table_set_int(out_tab,
"Degree_of_x", 5, power[0]);
832 cpl_table_set_int(out_tab,
"Degree_of_y", 5, power[1]);
833 cpl_table_set_double(out_tab,
"poly2d_coef", 5,
834 cpl_polynomial_get_coeff(distor_poly, power));
837 cpl_table_new_column(out_tab,
"WL_coefficients", CPL_TYPE_DOUBLE);
838 cpl_table_set_double(out_tab,
"WL_coefficients", 0, a);
839 cpl_table_set_double(out_tab,
"WL_coefficients", 1, b);
840 cpl_table_set_double(out_tab,
"WL_coefficients", 2, c);
841 cpl_table_set_double(out_tab,
"WL_coefficients", 3, d);
842 cpl_table_set_double(out_tab,
"WL_coefficients", 4, e);
843 cpl_table_set_double(out_tab,
"WL_coefficients", 5, 0.0);
844 sofi_spc_arc_config.disprel_cc = xc;
847 cpl_polynomial_delete(distor_poly);
864 static cpl_error_code sofi_spc_arc_save(cpl_frameset * set_tot,
865 const cpl_table * tab,
866 const cpl_table * fwhms,
867 const cpl_image * corr,
868 const char * lines_table,
869 const cpl_frameset * set,
870 const cpl_parameterlist * parlist)
872 cpl_propertylist * plist;
873 cpl_propertylist * qclist;
874 cpl_propertylist * paflist;
875 const cpl_frame * ref_frame;
882 qclist = cpl_propertylist_new();
885 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
886 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
888 cpl_msg_error(cpl_func,
"getting header from reference frame");
889 cpl_propertylist_delete(qclist);
890 return cpl_error_set_where(cpl_func);
893 if (cpl_error_get_code()) {
894 cpl_propertylist_delete(qclist);
895 cpl_propertylist_delete(plist);
896 return cpl_error_set_where(cpl_func);
899 if (cpl_error_get_code()) cpl_error_reset();
900 else cpl_propertylist_append_string(qclist,
"ESO QC FILTER OBS", sval);
901 cpl_propertylist_delete(plist);
902 cpl_propertylist_append_string(qclist,
"ESO QC LAMP", lines_table);
903 cpl_propertylist_append_double(qclist,
"ESO QC DISP XCORR",
904 sofi_spc_arc_config.disprel_cc);
905 cpl_propertylist_append_double(qclist,
"ESO QC DISPCO1",
906 cpl_table_get_double(tab,
"WL_coefficients", 0, NULL));
907 cpl_propertylist_append_double(qclist,
"ESO QC DISPCO2",
908 cpl_table_get_double(tab,
"WL_coefficients", 1, NULL));
909 cpl_propertylist_append_double(qclist,
"ESO QC DISPCO3",
910 cpl_table_get_double(tab,
"WL_coefficients", 2, NULL));
911 cpl_propertylist_append_double(qclist,
"ESO QC DISPCO4",
912 cpl_table_get_double(tab,
"WL_coefficients", 3, NULL));
913 cpl_propertylist_append_double(qclist,
"ESO QC DISPCO5",
914 cpl_table_get_double(tab,
"WL_coefficients", 4, NULL));
915 cpl_propertylist_append_double(qclist,
"ESO QC DIST1",
916 cpl_table_get_double(tab,
"poly2d_coef", 0, NULL));
917 cpl_propertylist_append_double(qclist,
"ESO QC DISTX",
918 cpl_table_get_double(tab,
"poly2d_coef", 1, NULL));
919 cpl_propertylist_append_double(qclist,
"ESO QC DISTY",
920 cpl_table_get_double(tab,
"poly2d_coef", 2, NULL));
921 cpl_propertylist_append_double(qclist,
"ESO QC DISTXY",
922 cpl_table_get_double(tab,
"poly2d_coef", 3, NULL));
923 cpl_propertylist_append_double(qclist,
"ESO QC DISTXX",
924 cpl_table_get_double(tab,
"poly2d_coef", 4, NULL));
925 cpl_propertylist_append_double(qclist,
"ESO QC DISTYY",
926 cpl_table_get_double(tab,
"poly2d_coef", 5, NULL));
927 cpl_propertylist_append_int(qclist,
"ESO QC SATUR NBPIX",
928 sofi_spc_arc_config.nb_saturated);
929 cpl_propertylist_append_double(qclist,
"ESO QC WLEN",
930 (
double)(cpl_table_get_double(tab,
"WL_coefficients", 0, NULL) +
931 512.0*cpl_table_get_double(tab,
"WL_coefficients", 1, NULL) +
932 512.0*512.0*cpl_table_get_double(tab,
"WL_coefficients", 2, NULL) +
933 512.0*512.0*512.0*cpl_table_get_double(tab,
"WL_coefficients", 3, NULL) +
934 512.0*512.0*512.0*512.0*cpl_table_get_double(tab,
"WL_coefficients", 4, NULL)));
937 cpl_propertylist_append_int(qclist,
"ESO QC ARCS NUM",
938 cpl_table_get_nrow(fwhms));
939 for(i=0; i<cpl_table_get_nrow(fwhms); i++) {
940 sprintf(qc_str,
"ESO QC ARCS%d XPOS", i+1);
941 cpl_propertylist_append_double(qclist, qc_str,
942 cpl_table_get_double(fwhms,
"POS", i, NULL));
943 sprintf(qc_str,
"ESO QC ARCS%d FWHM", i+1);
944 cpl_propertylist_append_double(qclist, qc_str,
945 cpl_table_get_double(fwhms,
"FWHM", i, NULL));
946 sprintf(qc_str,
"ESO QC ARCS%d FLUX", i+1);
947 cpl_propertylist_append_double(qclist, qc_str,
948 cpl_table_get_double(fwhms,
"FLUX", i, NULL));
950 cpl_propertylist_append_int(qclist,
"ESO QC ARCS NUMGOOD",
951 sofi_spc_arc_config.fwhm_good);
952 cpl_propertylist_append_double(qclist,
"ESO QC FWHM MED",
953 sofi_spc_arc_config.fwhm_med);
957 filename = cpl_sprintf(
"sofi_spc_arc_set%d_frame%d.fits",
958 sofi_spc_arc_config.set_nb, sofi_spc_arc_config.frame_nb);
959 irplib_dfs_save_table(set_tot,
968 PACKAGE
"/" PACKAGE_VERSION,
974 filename = cpl_sprintf(
"sofi_spc_arc_set%d_frame%d_corr.fits",
975 sofi_spc_arc_config.set_nb, sofi_spc_arc_config.frame_nb);
976 irplib_dfs_save_image(set_tot,
985 PACKAGE
"/" PACKAGE_VERSION,
991 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
994 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
996 cpl_msg_error(cpl_func,
"getting header from reference frame");
997 cpl_propertylist_delete(qclist);
998 return cpl_error_set_where(cpl_func);
1002 paflist = cpl_propertylist_new();
1003 cpl_propertylist_copy_property_regexp(paflist, plist,
1004 "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
1005 "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME|"
1006 "ESO INS GRAT WLEN|ESO INS GRAT ORDER|ESO INS MODE|"
1007 "ESO INS OPTI1 ID)$", 0);
1008 cpl_propertylist_delete(plist);
1011 cpl_propertylist_copy_property_regexp(paflist, qclist,
".", 0);
1012 cpl_propertylist_delete(qclist);
1015 filename = cpl_sprintf(
"sofi_spc_arc_set%d_frame%d.paf",
1016 sofi_spc_arc_config.set_nb, sofi_spc_arc_config.frame_nb);
1017 cpl_dfs_save_paf(
"SOFI",
1022 cpl_propertylist_delete(paflist);
1024 return cpl_error_get_code();
1035 static int sofi_spc_arc_compare(
1036 const cpl_frame * frame1,
1037 const cpl_frame * frame2)
1040 cpl_propertylist * plist1;
1041 cpl_propertylist * plist2;
1046 if (frame1==NULL || frame2==NULL)
return CPL_ERROR_UNSPECIFIED;
1049 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),
1051 cpl_msg_error(cpl_func,
"getting header from reference frame");
1052 return CPL_ERROR_UNSPECIFIED;
1054 if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),
1056 cpl_msg_error(cpl_func,
"getting header from reference frame");
1057 cpl_propertylist_delete(plist1);
1058 return CPL_ERROR_UNSPECIFIED;
1062 if (cpl_error_get_code()) {
1063 cpl_propertylist_delete(plist1);
1064 cpl_propertylist_delete(plist2);
1065 return CPL_ERROR_UNSPECIFIED;
1073 if (cpl_error_get_code()) {
1074 cpl_msg_error(cpl_func,
"cannot get the slit used");
1075 cpl_propertylist_delete(plist1);
1076 cpl_propertylist_delete(plist2);
1077 return CPL_ERROR_UNSPECIFIED;
1079 if (strcmp(sval1, sval2)) comparison = 0;
1084 if (cpl_error_get_code()) {
1085 cpl_msg_error(cpl_func,
"cannot get the mode");
1086 cpl_propertylist_delete(plist1);
1087 cpl_propertylist_delete(plist2);
1088 return CPL_ERROR_UNSPECIFIED;
1090 if (strcmp(sval1, sval2)) comparison = 0;
1092 cpl_propertylist_delete(plist1);
1093 cpl_propertylist_delete(plist2);
1105 static int * sofi_spc_arc_find_lamps(
const cpl_frameset * fset)
1107 const int nframes = cpl_frameset_get_size(fset);
1111 cpl_ensure(nframes > 0, CPL_ERROR_UNSPECIFIED, NULL);
1114 lamps = (
int*)cpl_malloc(nframes *
sizeof(
int));
1116 for (i=0; i<nframes; i++) {
1117 const cpl_frame * cur_frame = cpl_frameset_get_position_const(fset, i);
1118 cpl_propertylist * plist
1119 = cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
1120 const int xenon = sofi_is_xenon_lamp_active(plist);
1121 const int neon = sofi_is_neon_lamp_active(plist);
1123 cpl_propertylist_delete(plist);
1124 if ((neon != 0 && neon != 1) || (xenon != 0 && xenon != 1)) {
1126 (void)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1127 "Cannot check which lamp is on for "
1132 if (neon == 1) lamps[i] = 3;
1133 else if (neon == 0) lamps[i] = 1;
1134 }
else if (xenon == 0 ) {
1135 if (neon == 1) lamps[i] = 2;
1136 else if (neon == 0) lamps[i] = 0;
1150 static int sofi_is_neon_lamp_active(
const cpl_propertylist * plist)
1156 if (cpl_error_get_code())
return CPL_ERROR_UNSPECIFIED;
1162 if (!strcmp(lamp,
"Neon")) {
1164 if (cpl_error_get_code()) {
1168 if (status == 1)
return 1;
1180 static int sofi_is_xenon_lamp_active(
const cpl_propertylist * plist)
1186 if (cpl_error_get_code())
return CPL_ERROR_UNSPECIFIED;
1192 if (!strcmp(lamp,
"Xenon")) {
1194 if (cpl_error_get_code()) {
1198 if (status == 1)
return 1;