41 #include "irplib_plugin.h"
42 #include "irplib_utils.h"
43 #include "irplib_distortion.h"
45 #include "isaac_utils.h"
46 #include "isaac_wavelength.h"
47 #include "isaac_physicalmodel.h"
48 #include "isaac_pfits.h"
49 #include "isaac_dfs.h"
55 #define RECIPE_STRING "isaac_spc_arc"
57 #define ISAAC_ARC_SATURATION 20000
63 static int isaac_spc_arc_reduce_sw(cpl_frameset *,
const cpl_parameterlist *,
64 const char *,
const char *, cpl_frameset *);
65 static int isaac_spc_arc_reduce_lw(cpl_frameset *,
const cpl_parameterlist *,
66 const char *,
const char *, cpl_frameset *);
67 static cpl_table * isaac_spc_arc_compute(
const cpl_image *,
const char *,
68 const char *,
const char *,
const char *, cpl_table **, cpl_image **);
69 static int isaac_spc_arc_save(
const cpl_table *,
const cpl_table *,
70 const cpl_image *,
const char *, cpl_frameset *,
71 const cpl_parameterlist *, cpl_frameset *);
72 static int isaac_spc_arc_compare(
const cpl_frame *,
const cpl_frame *);
73 static int * isaac_spc_arc_find_lamps(cpl_frameset *);
74 static int isaac_is_xenon_lamp_active(
const cpl_propertylist *);
75 static int isaac_is_argon_lamp_active(
const cpl_propertylist *);
78 cpl_recipe_define(isaac_spc_arc, ISAAC_BINARY_VERSION,
79 "Lars Lundin", PACKAGE_BUGREPORT,
"2002, 2003, 2008",
80 "ISAAC Spectro arc recipe",
81 RECIPE_STRING
" -- ISAAC Spectro arc recipe\n"
82 "The files listed in the Set Of Frames (sof-file) "
84 "raw-file.fits "ISAAC_SPC_ARC_RAW
" or\n"
85 "xe-cat.fits "ISAAC_CALPRO_XE_CAT
" or\n"
86 "ar-cat.fits "ISAAC_CALPRO_AR_CAT
"\n");
114 double disprel_offset;
117 } isaac_spc_arc_config;
133 cpl_error_code isaac_spc_arc_fill_parameterlist(cpl_parameterlist *
self)
135 const char * context = PACKAGE
"." RECIPE_STRING;
138 cpl_ensure_code(
self, CPL_ERROR_NULL_INPUT);
143 err = irplib_parameterlist_set_string(
self, PACKAGE, RECIPE_STRING,
144 "rejected",
"-1,-1,100,100",
"rej",
146 "left right bottom top rejections");
147 cpl_ensure_code(!err, err);
150 err = irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
151 "subdark", CPL_FALSE, NULL, context,
152 "Flag to subtract the dark");
153 cpl_ensure_code(!err, err);
156 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
157 "arc_max_w", 33, NULL, context,
158 "Maximum arc width allowed in pixels");
159 cpl_ensure_code(!err, err);
162 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
163 "max_offset", 50, NULL, context,
164 "Maximum offset from the physical "
165 "model allowed in pixels");
166 cpl_ensure_code(!err, err);
169 err = irplib_parameterlist_set_double(
self, PACKAGE, RECIPE_STRING,
170 "arc_kappa", 0.33, NULL, context,
171 "kappa for the threshold used for "
173 cpl_ensure_code(!err, err);
176 err = irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
177 "out_corr", CPL_FALSE, NULL, context,
178 "Flag to output corrected images");
179 cpl_ensure_code(!err, err);
181 return CPL_ERROR_NONE;
192 static int isaac_spc_arc(cpl_frameset * framelist,
193 const cpl_parameterlist * parlist)
196 cpl_size * labels = NULL;
197 cpl_size nlabels = 0;
200 cpl_propertylist * plist = NULL;
201 cpl_frameset * arcframes = NULL;
202 cpl_frameset * arc_one = NULL;
207 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
209 skip_if(sval == NULL);
210 error_if (sscanf(sval,
"%d,%d,%d,%d",
211 &isaac_spc_arc_config.rej_left,
212 &isaac_spc_arc_config.rej_right,
213 &isaac_spc_arc_config.rej_bottom,
214 &isaac_spc_arc_config.rej_top) != 4,
215 CPL_ERROR_DATA_NOT_FOUND,
"Parameter not in format %s: %s",
216 "%d,%d,%d,%d", sval);
219 isaac_spc_arc_config.out_corr
220 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
223 isaac_spc_arc_config.sub_dark
224 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
228 isaac_spc_arc_config.arc_max_width
229 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
233 isaac_spc_arc_config.max_offset
234 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
237 isaac_spc_arc_config.arc_kappa
238 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
246 error_if (arcframes == NULL, CPL_ERROR_DATA_NOT_FOUND,
247 "No frames are tagged %s", ISAAC_SPC_ARC_RAW);
251 error_if (xe == NULL, CPL_ERROR_DATA_NOT_FOUND,
252 "Xe catalogue not found");
255 error_if (ar == NULL, CPL_ERROR_DATA_NOT_FOUND,
256 "Ar catalogue not found");
259 labels = cpl_frameset_labelise(arcframes, isaac_spc_arc_compare, &nlabels);
260 any_if (
"Could not labelise input frames (nlabels=%d)", (
int)nlabels);
263 for (i=0; i < nlabels; i++) {
264 const cpl_frame * cur_frame;
265 const char * filename;
269 cpl_msg_info(cpl_func,
"Reducing data set %d of %d", i+1, (
int)nlabels);
270 isaac_spc_arc_config.set_nb = i+1;
271 cpl_frameset_delete(arc_one);
272 arc_one = cpl_frameset_extract(arcframes, labels, i);
275 cur_frame = cpl_frameset_get_position(arc_one, 0);
276 filename = cpl_frame_get_filename(cur_frame);
277 cpl_propertylist_delete(plist);
278 plist = cpl_propertylist_load(filename, 0);
280 any_if (
"Could not get the arm from %s in set %d of %d", filename,
283 if (sval[0] ==
'S') {
284 isaac_spc_arc_config.arm = 1;
285 }
else if (sval[0] ==
'L') {
286 isaac_spc_arc_config.arm = 2;
288 isaac_spc_arc_config.arm = 0;
289 error_if(1, CPL_ERROR_UNSUPPORTED_MODE,
290 "Unsupported arm in %s in set %d of %d: %s", filename,
291 i+1, (
int)nlabels, sval);
296 any_if (
"Could not get the resolution from %s in set %d of %d",
297 filename, i+1, (
int)nlabels);
299 if (sval[0]==
'L') isaac_spc_arc_config.resol =
'L';
300 else if (sval[0]==
'M') isaac_spc_arc_config.resol =
'M';
301 else isaac_spc_arc_config.resol =
'U';
302 cpl_propertylist_empty(plist);
304 error = isaac_spc_arc_config.arm == 1 ?
306 isaac_spc_arc_reduce_sw(arc_one, parlist, ar, xe, framelist) :
308 isaac_spc_arc_reduce_lw(arc_one, parlist, ar, xe, framelist);
310 error_if(error, cpl_error_get_code(),
311 "Could not reduce set %d of %d", i+1, (
int)nlabels);
316 cpl_frameset_delete(arc_one);
317 cpl_frameset_delete(arcframes);
319 cpl_propertylist_delete(plist);
321 return cpl_error_get_code();
335 static int isaac_spc_arc_reduce_sw(
336 cpl_frameset * arcframes,
337 const cpl_parameterlist * parlist,
340 cpl_frameset * set_tot)
344 char lines_table[16];
345 cpl_frame * cur_frame;
346 const char * cur_fname;
351 cpl_image * to_compute;
352 cpl_table * arcs_fwhm;
353 cpl_image * out_corr;
354 cpl_table * out_table;
358 nframes = cpl_frameset_get_size(arcframes);
359 isaac_spc_arc_config.pair_nb = 0;
367 if ((lamps=isaac_spc_arc_find_lamps(arcframes)) == NULL) {
368 cpl_msg_error(cpl_func,
"in finding the activated lamps");
369 return CPL_ERROR_UNSPECIFIED;
373 xenon = argon = xe_ar = dark = NULL;
374 for (i=0; i<nframes; i++) {
375 cur_frame = cpl_frameset_get_position(arcframes, i);
376 cur_fname = cpl_frame_get_filename(cur_frame);
377 if ((lamps[i] == 0) && (dark == NULL)) {
378 cpl_msg_info(cpl_func,
"Dark image: [%s]", cur_fname);
379 dark = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
380 }
else if ((lamps[i] == 1) && (xenon == NULL)) {
381 cpl_msg_info(cpl_func,
"Xenon lamp: [%s]", cur_fname);
382 xenon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
383 }
else if ((lamps[i] == 2) && (argon == NULL)) {
384 cpl_msg_info(cpl_func,
"Argon lamp: [%s]", cur_fname);
385 argon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
386 }
else if ((lamps[i] == 3) && (xe_ar == NULL)) {
387 cpl_msg_info(cpl_func,
"Xenon+Argon lamp: [%s]", cur_fname);
388 xe_ar = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
394 if (!xenon && !argon && !xe_ar) {
395 cpl_msg_error(cpl_func,
"neither xenon nor argon lamp activated");
396 if (dark) cpl_image_delete(dark);
397 return CPL_ERROR_UNSPECIFIED;
401 cur_frame = cpl_frameset_get_position(arcframes, 0);
402 cur_fname = cpl_frame_get_filename(cur_frame);
405 if (isaac_spc_arc_config.resol ==
'L') {
406 cpl_msg_info(cpl_func,
"Low resolution");
410 if (dark) to_compute = cpl_image_subtract_create(xenon, dark);
411 else to_compute = cpl_image_duplicate(xenon);
412 cpl_image_delete(xenon);
413 strcpy(lines_table,
"Xe");
416 cpl_msg_info(cpl_func,
"Apply the reduction");
417 isaac_spc_arc_config.pair_nb ++;
418 cpl_msg_indent_more();
419 if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname,
420 lines_table, ar, xe, &arcs_fwhm,
421 &out_corr)) == NULL) {
422 cpl_msg_error(cpl_func,
"arc reduction computation failed");
423 cpl_image_delete(to_compute);
426 cpl_image_delete(to_compute);
427 cpl_msg_info(cpl_func,
"Save the products");
428 isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table,
429 arcframes, parlist, set_tot);
430 cpl_table_delete(out_table);
431 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
432 if (out_corr) cpl_image_delete(out_corr);
434 cpl_msg_indent_less();
439 if (dark) to_compute = cpl_image_subtract_create(argon, dark);
440 else to_compute = cpl_image_duplicate(argon);
441 cpl_image_delete(argon);
442 strcpy(lines_table,
"Ar");
445 cpl_msg_info(cpl_func,
"Apply the reduction");
446 isaac_spc_arc_config.pair_nb ++;
447 cpl_msg_indent_more();
448 if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname,
449 lines_table, ar, xe, &arcs_fwhm,
450 &out_corr)) == NULL) {
451 cpl_msg_error(cpl_func,
"arc reduction computation failed");
452 cpl_image_delete(to_compute);
455 cpl_image_delete(to_compute);
456 cpl_msg_info(cpl_func,
"Save the products");
457 isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table,
458 arcframes, parlist, set_tot);
459 cpl_table_delete(out_table);
460 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
461 if (out_corr) cpl_image_delete(out_corr);
463 cpl_msg_indent_less();
468 if (dark) to_compute = cpl_image_subtract_create(xe_ar, dark);
469 else to_compute = cpl_image_duplicate(xe_ar);
470 cpl_image_delete(xe_ar);
471 strcpy(lines_table,
"Xe+Ar");
474 cpl_msg_info(cpl_func,
"Apply the reduction");
475 isaac_spc_arc_config.pair_nb ++;
476 cpl_msg_indent_more();
477 if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname,
478 lines_table, ar, xe, &arcs_fwhm,
479 &out_corr)) == NULL) {
480 cpl_msg_error(cpl_func,
"arc reduction computation failed");
481 cpl_image_delete(to_compute);
484 cpl_image_delete(to_compute);
485 cpl_msg_info(cpl_func,
"Save the products");
486 isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table,
487 arcframes, parlist, set_tot);
488 cpl_table_delete(out_table);
489 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
490 if (out_corr) cpl_image_delete(out_corr);
492 cpl_msg_indent_less();
495 }
else if (isaac_spc_arc_config.resol ==
'M') {
496 cpl_msg_info(cpl_func,
"Medium resolution");
498 if (xenon && argon) {
500 cpl_image_subtract(xenon, dark);
501 cpl_image_subtract(argon, dark);
502 to_compute = cpl_image_add_create(xenon, argon);
503 }
else to_compute = cpl_image_add_create(xenon, argon);
504 cpl_image_delete(xenon);
505 cpl_image_delete(argon);
506 strcpy(lines_table,
"Xe+Ar");
508 if (dark) to_compute = cpl_image_subtract_create(xenon, dark);
509 else to_compute = cpl_image_duplicate(xenon);
510 cpl_image_delete(xenon);
511 strcpy(lines_table,
"Xe");
513 if (dark) to_compute = cpl_image_subtract_create(argon, dark);
514 else to_compute = cpl_image_duplicate(argon);
515 cpl_image_delete(argon);
516 strcpy(lines_table,
"Ar");
518 if (dark) to_compute = cpl_image_subtract_create(xe_ar, dark);
519 else to_compute = cpl_image_duplicate(xe_ar);
520 cpl_image_delete(xe_ar);
521 strcpy(lines_table,
"Xe+Ar");
525 cpl_msg_info(cpl_func,
"Apply the reduction");
526 isaac_spc_arc_config.pair_nb ++;
527 cpl_msg_indent_more();
528 if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname,
529 lines_table, ar, xe, &arcs_fwhm,
530 &out_corr)) == NULL) {
531 cpl_msg_error(cpl_func,
"arc reduction computation failed");
532 cpl_image_delete(to_compute);
535 cpl_image_delete(to_compute);
536 cpl_msg_info(cpl_func,
"Save the products");
537 isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table,
538 arcframes, parlist, set_tot);
539 cpl_table_delete(out_table);
540 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
541 if (out_corr) cpl_image_delete(out_corr);
543 cpl_msg_indent_less();
546 if (dark) cpl_image_delete(dark);
562 static int isaac_spc_arc_reduce_lw(
563 cpl_frameset * arcframes,
564 const cpl_parameterlist * parlist,
567 cpl_frameset * set_tot)
571 char lines_table[16];
572 cpl_frame * cur_frame;
573 const char * cur_fname;
574 cpl_image * to_compute;
576 cpl_table * arcs_fwhm;
577 cpl_image * out_corr;
578 cpl_table * out_table;
579 cpl_boolean did_reduce = CPL_FALSE;
583 nframes = cpl_frameset_get_size(arcframes);
587 cpl_msg_error(cpl_func,
"An even nb of frames expected in input %d",
589 return CPL_ERROR_UNSPECIFIED;
597 if ((lamps=isaac_spc_arc_find_lamps(arcframes)) == NULL) {
598 cpl_msg_error(cpl_func,
"in finding the activated lamps");
599 return CPL_ERROR_UNSPECIFIED;
603 for (i=0; i<nframes/2; i++) {
604 isaac_spc_arc_config.pair_nb = i+1;
606 cur_frame = cpl_frameset_get_position(arcframes, 2*i);
607 cur_fname = cpl_frame_get_filename(cur_frame);
608 if ((to_compute = cpl_image_load(cur_fname,CPL_TYPE_FLOAT,0,0))==NULL){
609 cpl_msg_error(cpl_func,
"Could not load frame %s", cur_fname);
612 cpl_msg_info(cpl_func,
"Pair %d: Lamp and dark identification", i+1);
613 switch (lamps[2*i]) {
616 strcpy(lines_table,
"Xe");
617 cpl_msg_info(cpl_func,
"Xenon lamp: [%s]", cur_fname);
621 strcpy(lines_table,
"Ar");
622 cpl_msg_info(cpl_func,
"Argon lamp: [%s]", cur_fname);
626 strcpy(lines_table,
"Xe+Ar");
627 cpl_msg_info(cpl_func,
"Xenon+Argon lamp: [%s]", cur_fname);
630 cpl_image_delete(to_compute);
631 cpl_msg_info(cpl_func,
"Lamps are off. Next pair...");
636 if (lamps[2*i+1] == 0) {
637 cur_frame = cpl_frameset_get_position(arcframes, 2*i+1);
638 cur_fname = cpl_frame_get_filename(cur_frame);
639 dark = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
640 cpl_image_subtract(to_compute, dark);
641 cpl_image_delete(dark);
642 cpl_msg_info(cpl_func,
"Dark frame : [%s]", cur_fname);
644 cpl_msg_info(cpl_func,
"No dark frame");
648 cur_frame = cpl_frameset_get_position(arcframes, 2*i);
649 cur_fname = cpl_frame_get_filename(cur_frame);
652 cpl_msg_info(cpl_func,
"Apply the reduction");
653 cpl_msg_indent_more();
654 if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname,
655 lines_table, ar, xe, &arcs_fwhm,
656 &out_corr)) == NULL) {
657 cpl_msg_error(cpl_func,
"arc reduction computation failed");
658 cpl_image_delete(to_compute);
661 cpl_image_delete(to_compute);
662 cpl_msg_info(cpl_func,
"Save the products");
663 isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table,
664 arcframes, parlist, set_tot);
665 cpl_table_delete(out_table);
666 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
667 if (out_corr) cpl_image_delete(out_corr);
668 if (!cpl_error_get_code()) did_reduce = CPL_TRUE;
670 cpl_msg_indent_less();
675 cpl_ensure_code(did_reduce, CPL_ERROR_ILLEGAL_INPUT);
677 return cpl_error_set_where(cpl_func);
694 static cpl_table * isaac_spc_arc_compute(
695 const cpl_image * in,
696 const char * in_name,
697 const char * lines_table,
700 cpl_table ** arcs_fwhm,
701 cpl_image ** out_corr)
704 int xmin, ymin, xmax, ymax;
706 cpl_mask * saturation_map;
709 cpl_polynomial * distor_poly;
710 cpl_polynomial * poly2d_id;
711 cpl_vector * profile;
713 cpl_apertures * arcs;
715 computed_disprel * disprel;
717 double fwhm_x, fwhm_y;
718 cpl_vector * fwhm_valid;
722 nx = cpl_image_get_size_x(in);
723 ny = cpl_image_get_size_y(in);
730 ymin = isaac_spc_arc_config.rej_bottom + 1;
731 ymax = ny - isaac_spc_arc_config.rej_top;
734 saturation_map = cpl_mask_threshold_image_create(in, ISAAC_ARC_SATURATION,
736 if (saturation_map != NULL) {
737 isaac_spc_arc_config.nb_saturated = cpl_mask_count(saturation_map);
738 cpl_mask_delete(saturation_map);
740 isaac_spc_arc_config.nb_saturated = 0;
744 cpl_msg_info(cpl_func,
"Estimate the distortion");
745 cpl_msg_indent_more();
746 if ((distor_poly = irplib_distortion_estimate(in, xmin, ymin, xmax, ymax,
747 isaac_spc_arc_config.sub_dark, ISAAC_ARC_SATURATION,
748 isaac_spc_arc_config.arc_max_width,
749 isaac_spc_arc_config.arc_kappa, 2, &arcs)) == NULL) {
750 cpl_msg_error(cpl_func,
"Could not estimage distortion");
751 cpl_msg_indent_less();
754 cpl_msg_indent_less();
757 cpl_msg_info(cpl_func,
"Correct the distortion");
758 cpl_msg_indent_more();
759 in_corr = cpl_image_duplicate(in);
762 poly2d_id = cpl_polynomial_new(2);
763 power[0] = 0; power[1] = 1;
764 cpl_polynomial_set_coeff(poly2d_id, power, 1.0);
767 profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES);
768 cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_DEFAULT,
769 CPL_KERNEL_DEF_WIDTH);
772 if (cpl_image_warp_polynomial(in_corr, in, distor_poly,
773 poly2d_id, profile, CPL_KERNEL_DEF_WIDTH, profile,
774 CPL_KERNEL_DEF_WIDTH) != CPL_ERROR_NONE) {
775 cpl_msg_error(cpl_func,
"Could not correct the distortion");
776 cpl_image_delete(in_corr);
777 cpl_polynomial_delete(poly2d_id);
778 cpl_polynomial_delete(distor_poly);
779 cpl_vector_delete(profile);
780 cpl_msg_indent_less();
783 cpl_polynomial_delete(poly2d_id);
784 cpl_vector_delete(profile);
785 cpl_msg_indent_less();
788 cpl_msg_info(cpl_func,
"Compute the FWHM of the detected arcs");
790 *arcs_fwhm = cpl_table_new(cpl_apertures_get_size(arcs));
791 cpl_table_new_column(*arcs_fwhm,
"XPOS", CPL_TYPE_DOUBLE);
792 cpl_table_new_column(*arcs_fwhm,
"FWHM", CPL_TYPE_DOUBLE);
793 cpl_table_new_column(*arcs_fwhm,
"FLUX", CPL_TYPE_DOUBLE);
795 isaac_spc_arc_config.fwhm_good = 0;
796 for (i=0; i<cpl_apertures_get_size(arcs); i++) {
797 cpl_table_set_double(*arcs_fwhm,
"XPOS", i,
798 cpl_apertures_get_centroid_x(arcs, i+1));
799 cpl_table_set_double(*arcs_fwhm,
"FLUX", i,
800 cpl_apertures_get_flux(arcs, i+1));
801 if (cpl_image_get_fwhm(in_corr, cpl_apertures_get_centroid_x(arcs, i+1),
802 512, &fwhm_x, &fwhm_y) != CPL_ERROR_NONE) {
803 cpl_msg_warning(cpl_func,
"Could not get the FWHM");
806 cpl_table_set_double(*arcs_fwhm,
"FWHM", i, fwhm_x);
807 if (fwhm_x > 0) isaac_spc_arc_config.fwhm_good ++;
809 cpl_apertures_delete(arcs);
812 if (isaac_spc_arc_config.fwhm_good > 0) {
813 fwhm_valid = cpl_vector_new(isaac_spc_arc_config.fwhm_good);
814 isaac_spc_arc_config.fwhm_good = 0;
815 for (i=0; i<cpl_table_get_nrow(*arcs_fwhm); i++) {
816 fwhm_x = cpl_table_get_double(*arcs_fwhm,
"FWHM", i, NULL);
818 cpl_vector_set(fwhm_valid, isaac_spc_arc_config.fwhm_good,
820 isaac_spc_arc_config.fwhm_good ++;
823 isaac_spc_arc_config.fwhm_med = cpl_vector_get_median_const(fwhm_valid);
824 cpl_vector_delete(fwhm_valid);
825 }
else isaac_spc_arc_config.fwhm_med = 0.0;
830 if ((slit_width = isaac_get_slitwidth(in_name)) == -1) {
831 cpl_msg_error(cpl_func,
"Could not get the slit width");
832 cpl_polynomial_delete(distor_poly);
833 cpl_image_delete(in_corr);
834 cpl_table_delete(*arcs_fwhm);
840 if ((order = isaac_find_order(in_name)) == -1) {
841 cpl_msg_error(cpl_func,
"Could not get the order");
842 cpl_polynomial_delete(distor_poly);
843 cpl_image_delete(in_corr);
844 cpl_table_delete(*arcs_fwhm);
850 cpl_msg_info(cpl_func,
"Compute the physical model");
851 cpl_msg_indent_more();
853 cpl_msg_error(cpl_func,
"Could not estimate the dispersion relation");
854 cpl_polynomial_delete(distor_poly);
855 cpl_image_delete(in_corr);
856 cpl_table_delete(*arcs_fwhm);
858 cpl_msg_indent_less();
861 cpl_msg_info(cpl_func,
"f(x)=%g + %g*x + %g*x^2 + %g*x^3",
862 phdisprel[0], phdisprel[1], phdisprel[2], phdisprel[3]);
863 cpl_msg_indent_less();
866 cpl_msg_info(cpl_func,
"Compute the dispersion relation");
867 cpl_msg_indent_more();
868 if ((disprel = spectro_compute_disprel(in_corr,
869 isaac_spc_arc_config.rej_bottom,
870 isaac_spc_arc_config.rej_top,
871 isaac_spc_arc_config.rej_left,
872 isaac_spc_arc_config.rej_right,
873 isaac_spc_arc_config.max_offset,
874 isaac_has_thermal(in_name) > 0,
875 lines_table, NULL, ar, xe, slit_width, order,
876 (
int)(cpl_msg_get_level() == CPL_MSG_DEBUG),
877 phdisprel)) == NULL) {
878 cpl_msg_error(cpl_func,
"Could not compute the dispersion relation");
879 cpl_polynomial_delete(distor_poly);
880 cpl_image_delete(in_corr);
882 cpl_table_delete(*arcs_fwhm);
884 cpl_msg_indent_less();
887 if (isaac_spc_arc_config.out_corr) {
891 cpl_image_delete(in_corr);
894 cpl_msg_info(cpl_func,
"Cross correlation factor: %g", disprel->cc);
895 cpl_msg_info(cpl_func,
"f(x)=%g + %g*x + %g*x^2 + %g*x^3",
896 disprel->poly[0], disprel->poly[1], disprel->poly[2],
898 cpl_msg_indent_less();
901 out_tab = cpl_table_new(6);
904 cpl_table_new_column(out_tab,
"Degree_of_x", CPL_TYPE_INT);
905 cpl_table_new_column(out_tab,
"Degree_of_y", CPL_TYPE_INT);
906 cpl_table_new_column(out_tab,
"poly2d_coef", CPL_TYPE_DOUBLE);
907 power[0] = 0; power[1] = 0;
908 cpl_table_set_int(out_tab,
"Degree_of_x", 0, power[0]);
909 cpl_table_set_int(out_tab,
"Degree_of_y", 0, power[1]);
910 cpl_table_set_double(out_tab,
"poly2d_coef", 0,
911 cpl_polynomial_get_coeff(distor_poly, power));
912 power[0] = 1; power[1] = 0;
913 cpl_table_set_int(out_tab,
"Degree_of_x", 1, power[0]);
914 cpl_table_set_int(out_tab,
"Degree_of_y", 1, power[1]);
915 cpl_table_set_double(out_tab,
"poly2d_coef", 1,
916 cpl_polynomial_get_coeff(distor_poly, power));
917 power[0] = 0; power[1] = 1;
918 cpl_table_set_int(out_tab,
"Degree_of_x", 2, power[0]);
919 cpl_table_set_int(out_tab,
"Degree_of_y", 2, power[1]);
920 cpl_table_set_double(out_tab,
"poly2d_coef", 2,
921 cpl_polynomial_get_coeff(distor_poly, power));
922 power[0] = 1; power[1] = 1;
923 cpl_table_set_int(out_tab,
"Degree_of_x", 3, power[0]);
924 cpl_table_set_int(out_tab,
"Degree_of_y", 3, power[1]);
925 cpl_table_set_double(out_tab,
"poly2d_coef", 3,
926 cpl_polynomial_get_coeff(distor_poly, power));
927 power[0] = 2; power[1] = 0;
928 cpl_table_set_int(out_tab,
"Degree_of_x", 4, power[0]);
929 cpl_table_set_int(out_tab,
"Degree_of_y", 4, power[1]);
930 cpl_table_set_double(out_tab,
"poly2d_coef", 4,
931 cpl_polynomial_get_coeff(distor_poly, power));
932 power[0] = 0; power[1] = 2;
933 cpl_table_set_int(out_tab,
"Degree_of_x", 5, power[0]);
934 cpl_table_set_int(out_tab,
"Degree_of_y", 5, power[1]);
935 cpl_table_set_double(out_tab,
"poly2d_coef", 5,
936 cpl_polynomial_get_coeff(distor_poly, power));
939 cpl_table_new_column(out_tab,
"WL_coefficients", CPL_TYPE_DOUBLE);
940 cpl_table_set_double(out_tab,
"WL_coefficients", 0, disprel->poly[0]);
941 cpl_table_set_double(out_tab,
"WL_coefficients", 1, disprel->poly[1]);
942 cpl_table_set_double(out_tab,
"WL_coefficients", 2, disprel->poly[2]);
943 cpl_table_set_double(out_tab,
"WL_coefficients", 3, disprel->poly[3]);
944 cpl_table_set_double(out_tab,
"WL_coefficients", 4, 0.0);
945 cpl_table_set_double(out_tab,
"WL_coefficients", 5, 0.0);
946 isaac_spc_arc_config.disprel_cc = disprel->cc;
947 isaac_spc_arc_config.disprel_clines = disprel->clines;
948 isaac_spc_arc_config.disprel_dlines = disprel->dlines;
949 isaac_spc_arc_config.disprel_rms = disprel->rms;
950 isaac_spc_arc_config.disprel_offset = disprel->offset;
953 cpl_polynomial_delete(distor_poly);
954 if (disprel->poly != NULL) cpl_free(disprel->poly);
972 static int isaac_spc_arc_save(
973 const cpl_table * tab,
974 const cpl_table * fwhms,
975 const cpl_image * corr,
976 const char * lines_table,
978 const cpl_parameterlist * parlist,
979 cpl_frameset * set_tot)
981 cpl_propertylist * plist;
982 cpl_propertylist * qclist;
983 cpl_propertylist * paflist;
984 const cpl_frame * ref_frame;
987 const char * procat = isaac_spc_arc_config.arm == 1
988 ? ISAAC_SPC_ARC_SW_RES : ISAAC_SPC_ARC_LW_RES;
994 qclist = cpl_propertylist_new();
997 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
998 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
1000 cpl_msg_error(cpl_func,
"getting header from reference frame");
1001 cpl_propertylist_delete(qclist);
1002 return CPL_ERROR_UNSPECIFIED;
1005 if (cpl_error_get_code()) {
1006 cpl_propertylist_delete(qclist);
1007 cpl_propertylist_delete(plist);
1008 return CPL_ERROR_UNSPECIFIED;
1011 if (cpl_error_get_code()) cpl_error_reset();
1012 else cpl_propertylist_append_string(qclist,
"ESO QC FILTER OBS", sval);
1013 cpl_propertylist_delete(plist);
1014 cpl_propertylist_append_string(qclist,
"ESO QC LAMP", lines_table);
1015 cpl_propertylist_append_double(qclist,
"ESO QC DISP XCORR",
1016 isaac_spc_arc_config.disprel_cc);
1017 cpl_propertylist_append_int(qclist,
"ESO QC DISP NUMCAT",
1018 isaac_spc_arc_config.disprel_clines);
1019 cpl_propertylist_append_int(qclist,
"ESO QC DISP NUMMATCH",
1020 isaac_spc_arc_config.disprel_dlines);
1021 cpl_propertylist_append_double(qclist,
"ESO QC DISP STDEV",
1022 isaac_spc_arc_config.disprel_rms);
1023 cpl_propertylist_append_double(qclist,
"ESO QC DISP OFFSET",
1024 isaac_spc_arc_config.disprel_offset);
1025 cpl_propertylist_append_double(qclist,
"ESO QC DISPCO1",
1026 cpl_table_get_double(tab,
"WL_coefficients", 0, NULL));
1027 cpl_propertylist_append_double(qclist,
"ESO QC DISPCO2",
1028 cpl_table_get_double(tab,
"WL_coefficients", 1, NULL));
1029 cpl_propertylist_append_double(qclist,
"ESO QC DISPCO3",
1030 cpl_table_get_double(tab,
"WL_coefficients", 2, NULL));
1031 cpl_propertylist_append_double(qclist,
"ESO QC DISPCO4",
1032 cpl_table_get_double(tab,
"WL_coefficients", 3, NULL));
1033 cpl_propertylist_append_double(qclist,
"ESO QC DIST1",
1034 cpl_table_get_double(tab,
"poly2d_coef", 0, NULL));
1035 cpl_propertylist_append_double(qclist,
"ESO QC DISTX",
1036 cpl_table_get_double(tab,
"poly2d_coef", 1, NULL));
1037 cpl_propertylist_append_double(qclist,
"ESO QC DISTY",
1038 cpl_table_get_double(tab,
"poly2d_coef", 2, NULL));
1039 cpl_propertylist_append_double(qclist,
"ESO QC DISTXY",
1040 cpl_table_get_double(tab,
"poly2d_coef", 3, NULL));
1041 cpl_propertylist_append_double(qclist,
"ESO QC DISTXX",
1042 cpl_table_get_double(tab,
"poly2d_coef", 4, NULL));
1043 cpl_propertylist_append_double(qclist,
"ESO QC DISTYY",
1044 cpl_table_get_double(tab,
"poly2d_coef", 5, NULL));
1045 cpl_propertylist_append_int(qclist,
"ESO QC SATUR NBPIX",
1046 isaac_spc_arc_config.nb_saturated);
1047 cpl_propertylist_append_double(qclist,
"ESO QC WLEN",
1048 (
double)(cpl_table_get_double(tab,
"WL_coefficients", 0, NULL) +
1049 512*cpl_table_get_double(tab,
"WL_coefficients", 1, NULL) +
1050 512*512*cpl_table_get_double(tab,
"WL_coefficients", 2, NULL) +
1051 512*512*512*cpl_table_get_double(tab,
"WL_coefficients", 3, NULL)));
1054 cpl_propertylist_append_int(qclist,
"ESO QC ARCS NUM",
1055 cpl_table_get_nrow(fwhms));
1056 for(i=0; i<cpl_table_get_nrow(fwhms); i++) {
1057 sprintf(qc_str,
"ESO QC ARCS%d XPOS", i+1);
1058 cpl_propertylist_append_double(qclist, qc_str,
1059 cpl_table_get_double(fwhms,
"XPOS", i, NULL));
1060 sprintf(qc_str,
"ESO QC ARCS%d FWHM", i+1);
1061 cpl_propertylist_append_double(qclist, qc_str,
1062 cpl_table_get_double(fwhms,
"FWHM", i, NULL));
1063 sprintf(qc_str,
"ESO QC ARCS%d FLUX", i+1);
1064 cpl_propertylist_append_double(qclist, qc_str,
1065 cpl_table_get_double(fwhms,
"FLUX", i, NULL));
1067 cpl_propertylist_append_int(qclist,
"ESO QC ARCS NUMGOOD",
1068 isaac_spc_arc_config.fwhm_good);
1069 cpl_propertylist_append_double(qclist,
"ESO QC FWHM MED",
1070 isaac_spc_arc_config.fwhm_med);
1075 filename = cpl_sprintf(
"isaac_spc_arc_set%d_pair%d.fits",
1076 isaac_spc_arc_config.set_nb, isaac_spc_arc_config.pair_nb);
1077 irplib_dfs_save_table(set_tot,
1086 PACKAGE
"/" PACKAGE_VERSION,
1092 const char * procatc = isaac_spc_arc_config.arm == 1
1093 ? ISAAC_SPC_ARC_SW_CORR : ISAAC_SPC_ARC_LW_CORR;
1094 filename = cpl_sprintf(
"isaac_spc_arc_set%d_pair%d_corr.fits",
1095 isaac_spc_arc_config.set_nb, isaac_spc_arc_config.pair_nb);
1096 irplib_dfs_save_image(set_tot,
1105 PACKAGE
"/" PACKAGE_VERSION,
1111 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
1114 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
1116 cpl_msg_error(cpl_func,
"getting header from reference frame");
1117 cpl_propertylist_delete(qclist);
1118 return CPL_ERROR_UNSPECIFIED;
1122 paflist = cpl_propertylist_new();
1123 cpl_propertylist_copy_property_regexp(paflist, plist,
1124 "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
1125 "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME|"
1126 "ESO INS GRAT WLEN|ESO INS GRAT ORDER|ESO INS MODE|"
1127 "ESO INS OPTI1 ID)$", 0);
1128 cpl_propertylist_delete(plist);
1131 cpl_propertylist_copy_property_regexp(paflist, qclist,
".", 0);
1132 cpl_propertylist_delete(qclist);
1135 cpl_propertylist_update_string(paflist, CPL_DFS_PRO_CATG, procat);
1138 filename = cpl_sprintf(
"isaac_spc_arc_set%d_pair%d.paf",
1139 isaac_spc_arc_config.set_nb, isaac_spc_arc_config.pair_nb);
1140 cpl_dfs_save_paf(
"ISAAC",
1145 cpl_propertylist_delete(paflist);
1157 static int isaac_spc_arc_compare(
const cpl_frame * frame1,
1158 const cpl_frame * frame2)
1161 const char * file1 = cpl_frame_get_filename(frame1);
1162 const char * file2 = cpl_frame_get_filename(frame2);
1163 cpl_propertylist * plist1 = NULL;
1164 cpl_propertylist * plist2 = NULL;
1167 double dval1, dval2;
1169 bug_if(frame1 == NULL);
1170 bug_if(frame2 == NULL);
1173 plist1 = cpl_propertylist_load(file1, 0);
1174 any_if(
"Could not load header from 1st frame %s", file1);
1176 plist2 = cpl_propertylist_load(file2, 0);
1177 any_if(
"Could not load header from 2nd frame %s", file2);
1181 any_if(
"Could not get slit from 1st frame %s", file1);
1184 any_if(
"Could not get slit from 2nd frame %s", file2);
1186 if (strcmp(sval1, sval2)) comparison = 0;
1190 any_if(
"Could not get resolution from 1st frame %s", file1);
1193 any_if(
"Could not get resolution from 2nd frame %s", file2);
1195 if (strcmp(sval1, sval2)) comparison = 0;
1199 any_if(
"Could not get wavelength from 1st frame %s", file1);
1202 any_if(
"Could not get wavelength from 2nd frame %s", file2);
1204 if (fabs(dval1-dval2) > 1e-4) comparison = 0;
1208 cpl_propertylist_delete(plist1);
1209 cpl_propertylist_delete(plist2);
1211 return cpl_error_get_code() ? -1 : comparison;
1222 static int * isaac_spc_arc_find_lamps(cpl_frameset * fset)
1226 cpl_frame * cur_frame;
1227 cpl_propertylist * plist;
1232 if (fset == NULL)
return NULL;
1235 nframes = cpl_frameset_get_size(fset);
1239 lamps = cpl_malloc(nframes *
sizeof(
int));
1241 for (i=0; i<nframes; i++) {
1242 cur_frame = cpl_frameset_get_position(fset, i);
1243 plist=cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
1244 xenon = isaac_is_xenon_lamp_active(plist);
1245 argon = isaac_is_argon_lamp_active(plist);
1246 cpl_propertylist_delete(plist);
1247 if ((argon != 0 && argon != 1) || (xenon != 0 && xenon != 1)) {
1248 cpl_msg_error(cpl_func,
"Could not check which lamp is on");
1253 if (argon == 1) lamps[i] = 3;
1254 else if (argon == 0) lamps[i] = 1;
1255 }
else if (xenon == 0 ) {
1256 if (argon == 1) lamps[i] = 2;
1257 else if (argon == 0) lamps[i] = 0;
1272 static int isaac_is_argon_lamp_active(
const cpl_propertylist * plist)
1274 int status1, status2;
1277 if (cpl_error_get_code())
return CPL_ERROR_UNSPECIFIED;
1279 if (cpl_error_get_code())
return CPL_ERROR_UNSPECIFIED;
1283 if (cpl_error_get_code()) {
1287 if (status2 == 1)
return 1;
1299 static int isaac_is_xenon_lamp_active(
const cpl_propertylist * plist)
1301 int status1, status2;
1304 if (cpl_error_get_code())
return CPL_ERROR_UNSPECIFIED;
1306 if (cpl_error_get_code())
return CPL_ERROR_UNSPECIFIED;
1310 if (cpl_error_get_code()) {
1314 if (status2 == 1)
return 1;
int isaac_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
int isaac_pfits_get_lamp1_status(const cpl_propertylist *plist)
find out the lamp1 status
int isaac_pfits_get_lamp2_status(const cpl_propertylist *plist)
find out the lamp2 status
const char * isaac_pfits_get_opti1_id(const cpl_propertylist *plist)
find out the OPTI1.ID key
int isaac_pfits_get_calshut_status(const cpl_propertylist *plist)
find out the shutter status
double isaac_pfits_get_wlen(const cpl_propertylist *plist)
find out the central wavelength
const char * isaac_pfits_get_arm(const cpl_propertylist *plist)
find out the arm which is active
const char * isaac_pfits_get_resolution(const cpl_propertylist *plist)
find out the resolution
const char * isaac_pfits_get_filter(const cpl_propertylist *plist)
find out the filter
double * isaac_get_disprel_estimate(const char *filename, cpl_size poly_deg)
Estimate the instrument wavelength range.
const char * isaac_extract_filename(const cpl_frameset *self, const char *tag)
Extract the filename of the first frame of the given tag.
cpl_frameset * isaac_extract_frameset(const cpl_frameset *self, const char *tag)
Extract the frames with the given tag from a frameset.