43#include "kmos_pfits.h"
44#include "kmo_functions.h"
45#include "kmo_priv_wave_cal.h"
46#include "kmo_priv_functions.h"
47#include "kmo_cpl_extensions.h"
50#include "kmo_constants.h"
57static int kmos_wave_cal_check_inputs(cpl_frameset *,
int *,
int *,
int *,
58 double *,
int *, lampConfiguration *);
60static int kmos_wave_cal_create(cpl_plugin *);
61static int kmos_wave_cal_exec(cpl_plugin *);
62static int kmos_wave_cal_destroy(cpl_plugin *);
63static int kmos_wave_cal(cpl_parameterlist *, cpl_frameset *);
69static char kmos_wave_cal_description[] =
70"This recipe creates the wavelength calibration frame needed for all three\n"
71"detectors. It must be called after the kmo_flat recipe, which generates the\n"
72"two spatial calibration frames needed in this recipe. As input a lamp-on \n"
73"frame, a lamp-off frame, the spatial calibration frames and the list with \n"
74"the reference arclines are required.\n"
75"An additional output frame is the resampled image of the reconstructed arc\n"
76"frame. All slitlets of all IFUs are aligned one next to the other. This \n"
77"frame serves for quality control. One can immediately see if the \n"
78"calibration was successful.\n"
79"The lists of reference arclines are supposed to contain the lines for both\n"
80"available calibration arc-lamps, i.e. Argon and Neon. The list is supposed\n"
81"to be a F2L KMOS FITS file with three columns:\n"
82"\t1. Reference wavelength\n"
83"\t2. Relative strength\n"
84"\t3. String either containing “Ar” or “Ne”\n"
85"The recipe extracts, based on the header keywords, either the applying\n"
86"argon and/or neon emission lines. Below are the plots of the emission lines\n"
87"for both argon and neon. The marked lines are the ones used for wavelength \n"
90"Furthermore frames can be provided for several rotator angles. In this case\n"
91"the resulting calibration frames for each detector are repeatedly saved as \n"
92"extension for every angle.\n"
97"The polynomial order to use for the fit of the wavelength solution.\n"
98"0: (default) The appropriate order is choosen automatically depending on\n"
99"the waveband (4 for IZ band, 5 for HK, 6 for the others)\n"
101"ADVANCED PARAMETERS\n"
102"-------------------\n"
104"The number of samples in spectral direction for the reconstructed cube.\n"
105"Ideally this number should be greater than 2048, the detector size.\n"
107"--suppress_extension\n"
108"If set to TRUE, the arbitrary filename extensions are supressed. If\n"
109"multiple products with the same category are produced, they will be numered\n"
110"consecutively starting from 0.\n"
112"--lines_estimation\n"
113"If set to TRUE, the lines estimation method is used\n"
115"----------------------------------------------------------------------------\n"
118" DO category Type Explanation Required #Frames\n"
119" ----------- ----- ----------- -------- -------\n"
120" ARC_ON RAW Arclamp-on exposure Y >=1\n"
121" ARC_OFF RAW Arclamp-off exposure Y 1\n"
122" XCAL F2D x calibration frame Y 1\n"
123" YCAL F2D y calibration frame Y 1\n"
124" ARC_LIST F2L List of arclines Y 1\n"
125" FLAT_EDGE F2L Fitted edge parameters Y 1\n"
126" REF_LINES F2L Reference line table Y 1\n"
127" WAVE_BAND F2L Table with start-/end-wavelengths Y 1\n"
131" DO category Type Explanation\n"
132" ----------- ----- -----------\n"
133" LCAL F2D Wavelength calibration frame\n"
135" DET_IMG_WAVE F2D reconstructed arclamp-on exposure\n"
136" (4 extensions: 3 detector images + \n"
137" the arclines list table)\n"
138"----------------------------------------------------------------------------\n"
163 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
164 cpl_plugin *plugin = &recipe->interface;
166 cpl_plugin_init(plugin,
169 CPL_PLUGIN_TYPE_RECIPE,
171 "Create a wavelength calibration frame",
172 kmos_wave_cal_description,
173 "Alex Agudo Berbel, Yves Jung",
174 "https://support.eso.org/",
176 kmos_wave_cal_create,
178 kmos_wave_cal_destroy);
179 cpl_pluginlist_append(list, plugin);
193static int kmos_wave_cal_create(cpl_plugin *plugin)
199 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
200 recipe = (cpl_recipe *)plugin;
205 recipe->parameters = cpl_parameterlist_new();
208 p = cpl_parameter_new_range(
"kmos.kmos_wave_cal.order", CPL_TYPE_INT,
209 "The fitting polynomial order used for the wavelength solution. "
210 "By default, 4 for IZ band, 5 for HK, 6 for the others",
211 "kmos.kmos_wave_cal", 0, 0, 7);
212 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"order");
213 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
214 cpl_parameterlist_append(recipe->parameters, p);
217 p = cpl_parameter_new_value(
"kmos.kmos_wave_cal.suppress_extension",
218 CPL_TYPE_BOOL,
"Suppress arbitrary filename extension",
219 "kmos.kmos_wave_cal", FALSE);
220 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"suppress_extension");
221 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
222 cpl_parameterlist_append(recipe->parameters, p);
225 p = cpl_parameter_new_value(
"kmos.kmos_wave_cal.lines_estimation",
226 CPL_TYPE_BOOL,
"Trigger lines estimation method",
227 "kmos.kmos_wave_cal", FALSE);
228 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lines_estimation");
229 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
230 cpl_parameterlist_append(recipe->parameters, p);
233 kmos_band_pars_create(recipe->parameters,
"kmos.kmos_wave_cal");
236 p = cpl_parameter_new_value(
"kmos.kmos_wave_cal.detector",
237 CPL_TYPE_INT,
"Only reduce the specified detector",
238 "kmos.kmos_wave_cal", 0);
239 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"det");
240 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
241 cpl_parameterlist_append(recipe->parameters, p);
244 p = cpl_parameter_new_value(
"kmos.kmos_wave_cal.angle",
245 CPL_TYPE_DOUBLE,
"Only reduce the specified angle",
246 "kmos.kmos_wave_cal", 370.0);
247 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"angle");
248 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
249 cpl_parameterlist_append(recipe->parameters, p);
261static int kmos_wave_cal_exec(cpl_plugin *plugin)
266 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
267 recipe = (cpl_recipe *)plugin;
270 return kmos_wave_cal(recipe->parameters, recipe->frames);
280static int kmos_wave_cal_destroy(cpl_plugin *plugin)
285 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
286 recipe = (cpl_recipe *)plugin;
289 cpl_parameterlist_delete(recipe->parameters);
308static int kmos_wave_cal(cpl_parameterlist *parlist, cpl_frameset *frameset)
310 const cpl_parameter * par ;
311 int suppress_extension, fit_order_par, fit_order ;
312 int nx, ny, next, reduce_det, lines_estimation ;
313 double exptime, gain, angle_found, reduce_angle ;
315 cpl_propertylist * mh_on ;
316 cpl_propertylist * plist ;
318 lampConfiguration lamp_config;
324 cpl_propertylist ** stored_sub_headers_lcal ;
325 cpl_propertylist ** stored_sub_headers_det_img ;
326 cpl_image ** stored_lcal ;
327 cpl_image ** stored_det_img ;
328 int * stored_qc_arc_sat ;
329 double * stored_qc_ar_eff ;
330 double * stored_qc_ne_eff ;
331 int * stored_qc_wave_fail ;
332 cpl_table * detector_edges[KMOS_IFUS_PER_DETECTOR] ;
336 cpl_image * det_lamp_on ;
337 cpl_image * det_lamp_off ;
338 cpl_image * det_lamp_on_copy ;
340 cpl_table * arclines ;
341 cpl_table * reflines ;
342 cpl_bivector * lines ;
344 cpl_image * bad_pix_mask ;
345 float * pbad_pix_mask ;
352 cpl_propertylist * qc_header ;
354 cpl_array ** unused_ifus_before ;
355 cpl_array ** unused_ifus_after ;
359 const char * tmp_str ;
363 if (kmos_check_and_set_groups(frameset) != CPL_ERROR_NONE) {
364 return cpl_error_get_code();
368 par = cpl_parameterlist_find_const(parlist,
"kmos.kmos_wave_cal.order");
369 fit_order_par = cpl_parameter_get_int(par);
370 par=cpl_parameterlist_find_const(parlist,
371 "kmos.kmos_wave_cal.lines_estimation");
372 lines_estimation = cpl_parameter_get_bool(par);
373 par=cpl_parameterlist_find_const(parlist,
374 "kmos.kmos_wave_cal.suppress_extension");
375 suppress_extension = cpl_parameter_get_bool(par);
376 par = cpl_parameterlist_find_const(parlist,
"kmos.kmos_wave_cal.angle");
377 reduce_angle = cpl_parameter_get_double(par);
378 par = cpl_parameterlist_find_const(parlist,
"kmos.kmos_wave_cal.detector");
379 reduce_det = cpl_parameter_get_int(par);
381 kmos_band_pars_load(parlist,
"kmos.kmos_wave_cal");
384 if (fit_order_par < 0 || fit_order_par > 7) {
385 cpl_msg_error(__func__,
"Fitting Order must be in [0,7]") ;
386 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
389 if (reduce_det < 0 || reduce_det > 3) {
390 cpl_msg_error(__func__,
"detector must be in [1,3]") ;
391 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
396 if (kmos_wave_cal_check_inputs(frameset, &nx, &ny, &next, &exptime,
397 &non_dest_rom, &lamp_config) != 1) {
398 cpl_msg_error(__func__,
"Input frameset is not consistent") ;
399 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
404 suffix = kmo_dfs_get_suffix(kmo_dfs_get_frame(frameset, XCAL), TRUE, FALSE);
405 cpl_msg_info(__func__,
"Detected instrument setup: %s", suffix+1);
409 frame = kmo_dfs_get_frame(frameset, ARC_ON);
410 mh_on = cpl_propertylist_load(cpl_frame_get_filename(frame), 0);
411 filter_ids = kmo_get_filter_setup(mh_on, next, TRUE) ;
412 cpl_propertylist_delete(mh_on);
413 if (filter_ids == NULL) {
415 cpl_msg_error(__func__,
"Cannot get Filter informations") ;
416 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
421 if ((angles_array = kmos_get_angles(frameset, &nb_angles, ARC_ON)) == NULL){
422 cpl_msg_error(__func__,
"Cannot get Angles informations") ;
423 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
424 for (i = 0; i < next ; i++) cpl_free(filter_ids[i]);
425 cpl_free(filter_ids);
431 frame = kmo_dfs_get_frame(frameset, ARC_LIST);
432 plist = cpl_propertylist_load(cpl_frame_get_filename(frame), 0);
433 tmp_str = cpl_propertylist_get_string(plist, FILT_ID);
434 if (strcmp(filter_ids[0], tmp_str) != 0) {
435 cpl_msg_error(__func__,
"Wrong ARC_LIST filter") ;
436 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
437 for (i = 0; i < next ; i++) cpl_free(filter_ids[i]);
438 cpl_free(filter_ids);
439 cpl_free(angles_array);
440 cpl_propertylist_delete(plist);
443 cpl_propertylist_delete(plist);
446 arclines = kmo_dfs_load_table(frameset, ARC_LIST, 1, 0);
447 lines = kmos_get_lines(arclines, lamp_config);
448 cpl_table_delete(arclines);
450 cpl_msg_info(__func__,
"Arc lines: %lld", cpl_bivector_get_size(lines));
453 if ((reflines = kmo_dfs_load_table(frameset, REF_LINES, 1, 0)) == NULL) {
454 cpl_msg_error(__func__,
"Missing REF_LINES calibration file") ;
455 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
456 for (i = 0; i < next ; i++) cpl_free(filter_ids[i]);
457 cpl_free(filter_ids);
458 cpl_free(angles_array);
459 cpl_bivector_delete(lines) ;
464 unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0);
465 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before);
466 kmo_print_unused_ifus(unused_ifus_before, FALSE);
467 if (unused_ifus_before != NULL) kmo_free_unused_ifus(unused_ifus_before);
470 if (getenv(
"KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE") != NULL) {
471 last_env = getenv(
"KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE");
475 setenv(
"KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE",
"NONE",1);
480 stored_lcal = (cpl_image**)cpl_calloc(next * nb_angles,
sizeof(cpl_image*));
481 stored_det_img = (cpl_image**)cpl_calloc(next*nb_angles,
sizeof(cpl_image*));
482 stored_sub_headers_lcal = (cpl_propertylist**)cpl_calloc(next * nb_angles,
483 sizeof(cpl_propertylist*));
484 stored_sub_headers_det_img = (cpl_propertylist**)cpl_calloc(next*nb_angles,
485 sizeof(cpl_propertylist*));
486 stored_qc_arc_sat = (
int*)cpl_calloc(next, nb_angles *
sizeof(
int));
487 stored_qc_ar_eff=(
double*)cpl_calloc(next, nb_angles *
sizeof(
double));
488 stored_qc_ne_eff=(
double*)cpl_calloc(next, nb_angles *
sizeof(
double));
489 stored_qc_wave_fail =(
int*)cpl_malloc(next*
sizeof(
int));
492 for (a = 0; a < nb_angles; a++) {
494 if (reduce_angle <= 360 && angles_array[a] != reduce_angle) continue ;
496 cpl_msg_info(__func__,
"Processing rotator angle %d -> %d degree",
498 cpl_msg_indent_more();
499 for (i = 1; i <= next ; i++) {
500 stored_qc_wave_fail[i-1] = 0;
502 if (reduce_det != 0 && i != reduce_det) continue ;
504 cpl_msg_info(__func__,
"Processing detector No. %d", i);
505 cpl_msg_indent_more();
508 frame=kmo_dfs_get_frame(frameset, FLAT_EDGE);
509 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
510 detector_edges[j] = kmclipm_cal_table_load(
511 cpl_frame_get_filename(frame),
512 (i-1) * KMOS_IFUS_PER_DETECTOR + j + 1,
513 angles_array[a], 0, &angle_found);
516 if (cpl_error_get_code() == CPL_ERROR_ILLEGAL_INPUT) {
522 if (fit_order_par == 0) {
524 if ((strcmp(filter_ids[i-1],
"H") == 0) ||
525 (strcmp(filter_ids[i-1],
"K") == 0) ||
526 (strcmp(filter_ids[i-1],
"YJ") == 0)) {
528 }
else if (strcmp(filter_ids[i-1],
"IZ") == 0) {
533 cpl_msg_info(__func__,
534 "Order of wavelength spectrum fit for %s-band: %d",
535 filter_ids[i-1], fit_order);
537 fit_order = fit_order_par;
541 frame = kmos_get_angle_frame(frameset, angles_array[a], ARC_ON);
542 det_lamp_on = kmo_dfs_load_image_frame(frame,i,FALSE, TRUE,&nr_sat);
543 int sx = a * next + (i - 1);
547 stored_qc_arc_sat[sx] = nr_sat;
549 stored_qc_arc_sat[sx] = kmo_image_get_saturated(det_lamp_on,
552 det_lamp_on_copy = cpl_image_duplicate(det_lamp_on);
555 frame = kmo_dfs_get_frame(frameset, ARC_OFF);
556 det_lamp_off = kmo_dfs_load_image_frame(frame, i, FALSE, FALSE,
560 cpl_image_subtract(det_lamp_on, det_lamp_off);
563 xcal = kmo_dfs_load_cal_image(frameset, XCAL, i, 0,
564 (
double)angles_array[a], FALSE, NULL, &angle_found, -1,0,0);
565 ycal = kmo_dfs_load_cal_image(frameset, YCAL, i, 0,
566 (
double)angles_array[a], FALSE, NULL, &angle_found, -1,0,0);
567 if (xcal == NULL || ycal == NULL) {
570 stored_det_img[sx] = NULL ;
571 stored_lcal[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
572 kmo_image_fill(stored_lcal[sx], 0.0);
573 if (xcal != NULL) cpl_image_delete(xcal) ;
574 if (ycal != NULL) cpl_image_delete(ycal) ;
575 cpl_image_delete(det_lamp_on_copy) ;
576 cpl_image_delete(det_lamp_on) ;
577 cpl_image_delete(det_lamp_off) ;
582 bad_pix_mask = cpl_image_duplicate(xcal);
583 pbad_pix_mask = cpl_image_get_data_float(bad_pix_mask);
584 for (x = 0; x < nx; x++) {
585 for (y = 0; y < ny; y++) {
586 if (isnan(pbad_pix_mask[x+nx*y])) {
587 pbad_pix_mask[x+nx*y] = 0.;
589 pbad_pix_mask[x+nx*y] = 1.;
595 err = kmos_calc_wave_calib(det_lamp_on, bad_pix_mask,
596 filter_ids[i-1], lamp_config, i, unused_ifus_after[i-1],
597 detector_edges, lines, reflines, &lcal,
598 &(stored_qc_ar_eff[sx]), &(stored_qc_ne_eff[sx]), fit_order,
600 cpl_image_delete(det_lamp_on);
601 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
602 cpl_table_delete(detector_edges[j]);
604 if (err == CPL_ERROR_NONE) {
606 if (stored_qc_ar_eff[sx] != -1.0)
607 stored_qc_ar_eff[sx] /= exptime;
608 if (stored_qc_ne_eff[sx] != -1.0)
609 stored_qc_ne_eff[sx] /= exptime;
612 cpl_image_multiply(lcal, bad_pix_mask);
613 kmo_image_reject_from_mask(lcal, bad_pix_mask);
616 stored_lcal[sx] = lcal;
617 }
else if (err == CPL_ERROR_UNSPECIFIED) {
621 stored_lcal[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
622 kmo_image_fill(stored_lcal[sx], 0.0);
623 stored_qc_wave_fail[i-1]++;
626 cpl_msg_warning(__func__,
627 "Couldn't identify any line - Check the line list");
628 cpl_msg_warning(__func__,
629 "Band defined in header of detector %d: %s",
631 cpl_msg_warning(__func__,
"Arc line file defined: %s",
632 cpl_frame_get_filename(kmo_dfs_get_frame(frameset,
635 cpl_image_delete(bad_pix_mask);
638 stored_det_img[sx] = kmo_reconstructed_arc_image(frameset,
639 det_lamp_on_copy, det_lamp_off, xcal, ycal, stored_lcal[sx],
640 unused_ifus_after[i-1], FALSE, i, suffix, filter_ids[i-1],
641 lamp_config, &qc_header);
642 cpl_image_delete(det_lamp_on_copy);
643 cpl_image_delete(det_lamp_off);
644 cpl_image_delete(xcal);
645 cpl_image_delete(ycal);
646 if (cpl_error_get_code() != CPL_ERROR_NONE) {
647 cpl_msg_error(__func__,
"Cannot reconstruct IFUs on detector %d",
653 stored_sub_headers_lcal[sx] = kmo_dfs_load_sub_header(frameset,
656 extname = kmo_extname_creator(detector_frame, i, EXT_DATA);
657 kmclipm_update_property_string(stored_sub_headers_lcal[sx], EXTNAME,
658 extname,
"FITS extension name");
661 kmclipm_update_property_int(stored_sub_headers_lcal[sx], EXTVER,
662 sx+1,
"FITS extension ver");
665 kmclipm_update_property_int(stored_sub_headers_lcal[sx],
666 QC_ARC_SAT, stored_qc_arc_sat[sx],
667 "[] nr. saturated pixels of arc exp.");
669 gain=kmo_dfs_get_property_double(stored_sub_headers_lcal[sx],GAIN);
671 if (stored_qc_ar_eff[sx] != -1.0) {
672 kmclipm_update_property_double(stored_sub_headers_lcal[sx],
673 QC_ARC_AR_EFF, stored_qc_ar_eff[sx]/gain,
674 "[e-/s] Argon lamp efficiency");
677 if (stored_qc_ne_eff[sx] != -1.0) {
678 kmclipm_update_property_double(stored_sub_headers_lcal[sx],
679 QC_ARC_NE_EFF, stored_qc_ne_eff[sx]/gain,
680 "[e-/s] Neon lamp efficiency");
683 kmclipm_update_property_double(stored_sub_headers_lcal[sx],
684 CAL_ROTANGLE, ((
double) angles_array[a]),
685 "[deg] Rotator relative to nasmyth");
689 kmclipm_update_property_int(stored_sub_headers_lcal[sx], QC_WAVE_FAIL, stored_qc_wave_fail[i-1],
690 "[] rot. angles with empty extensions ");
694 cpl_propertylist_append(stored_sub_headers_lcal[sx], qc_header);
695 cpl_propertylist_delete(qc_header);
698 stored_sub_headers_det_img[sx]=cpl_propertylist_duplicate(
699 stored_sub_headers_lcal[sx]);
700 cpl_propertylist_erase(stored_sub_headers_det_img[sx], CD1_1);
701 cpl_propertylist_erase(stored_sub_headers_det_img[sx], CD1_2);
702 cpl_propertylist_erase(stored_sub_headers_det_img[sx], CD2_1);
703 cpl_propertylist_erase(stored_sub_headers_det_img[sx], CD2_2);
704 cpl_propertylist_erase(stored_sub_headers_det_img[sx], CTYPE2) ;
705 cpl_propertylist_update_string(stored_sub_headers_det_img[sx],
707 cpl_propertylist_update_string(stored_sub_headers_det_img[sx],
709 cpl_propertylist_update_string(stored_sub_headers_det_img[sx],
713 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL1);
714 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL2);
715 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE1);
716 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE2);
717 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT1);
718 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT2);
720 cpl_msg_indent_less();
722 cpl_msg_indent_less() ;
726 cpl_free(angles_array) ;
727 for (i = 0; i < next; i++) cpl_free(filter_ids[i]);
728 cpl_free(filter_ids);
729 cpl_bivector_delete(lines);
731 cpl_free(stored_qc_arc_sat);
732 cpl_free(stored_qc_ar_eff);
733 cpl_free(stored_qc_ne_eff);
734 cpl_table_delete(reflines);
737 cpl_msg_info(__func__,
"Saving data...");
740 if (!suppress_extension) fn_suffix = cpl_sprintf(
"%s", suffix);
741 else fn_suffix = cpl_sprintf(
"%s",
"");
745 frame = kmo_dfs_get_frame(frameset, ARC_ON);
746 mh_on = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0);
747 kmo_set_unused_ifus(unused_ifus_after, mh_on,
"kmos_wave_cal");
748 kmo_dfs_save_main_header(frameset, LCAL, fn_suffix, frame, mh_on, parlist,
750 kmo_dfs_save_main_header(frameset, DET_IMG_WAVE, fn_suffix, frame, mh_on,
752 cpl_propertylist_delete(mh_on);
755 for (a = 0; a < nb_angles; a++) {
756 for (i = 1; i <= next ; i++) {
757 int sx = a * next + (i - 1);
759 kmo_dfs_save_image(stored_lcal[sx], LCAL, fn_suffix,
760 stored_sub_headers_lcal[sx], 0./0.);
763 kmo_dfs_save_image(stored_det_img[sx], DET_IMG_WAVE, fn_suffix,
764 stored_sub_headers_det_img[sx], 0./0.);
770 for (i = 0; i < next * nb_angles; i++) {
771 cpl_image_delete(stored_lcal[i]);
772 cpl_image_delete(stored_det_img[i]);
773 cpl_propertylist_delete(stored_sub_headers_lcal[i]);
774 cpl_propertylist_delete(stored_sub_headers_det_img[i]);
776 cpl_free(stored_lcal);
777 cpl_free(stored_det_img);
778 cpl_free(stored_sub_headers_lcal);
779 cpl_free(stored_sub_headers_det_img);
782 kmo_print_unused_ifus(unused_ifus_after, TRUE);
783 if (unused_ifus_after != NULL) kmo_free_unused_ifus(unused_ifus_after);
785 if (last_env != NULL) {
786 setenv(
"KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE",last_env,1);
788 unsetenv(
"KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE");
808static int kmos_wave_cal_check_inputs(
809 cpl_frameset * frameset,
815 lampConfiguration * lamp_config)
817 const cpl_frame * frame_off ;
818 const cpl_frame * frame_on ;
819 cpl_propertylist * mh_off ;
820 cpl_propertylist * mh_on ;
821 cpl_propertylist * eh_off ;
822 cpl_propertylist * eh_on ;
826 double ndit_off, ndit_on, exptime_off, exptime_on ;
827 const char * readmode_off ;
828 const char * readmode_on ;
833 if (nx == NULL || ny == NULL || next == NULL || frameset == NULL)
return -1;
836 frame_on = kmo_dfs_get_frame(frameset, ARC_ON);
837 mh_on = cpl_propertylist_load(cpl_frame_get_filename(frame_on), 0);
838 if ((kmo_check_lamp(mh_on, INS_LAMP1_ST) == TRUE) &&
839 (kmo_check_lamp(mh_on, INS_LAMP2_ST) == FALSE)) {
840 *lamp_config = ARGON;
841 cpl_msg_info(__func__,
"Arc lamp: Argon");
842 }
else if ((kmo_check_lamp(mh_on, INS_LAMP1_ST) == FALSE) &&
843 (kmo_check_lamp(mh_on, INS_LAMP2_ST) == TRUE)) {
845 cpl_msg_info(__func__,
"Arc lamp: Neon");
846 }
else if ((kmo_check_lamp(mh_on, INS_LAMP1_ST) == TRUE) &&
847 (kmo_check_lamp(mh_on, INS_LAMP2_ST) == TRUE)) {
848 *lamp_config = ARGON_NEON;
849 cpl_msg_info(__func__,
"Arc lamp: Argon + Neon");
852 cpl_msg_warning(__func__,
"Arc lamp: UNDEFINED");
856 readmode_on = kmos_pfits_get_readmode(mh_on);
857 if (!readmode_on)
return -1;
859 if (!strcmp(readmode_on,
"Nondest")) {
864 cpl_propertylist_delete(mh_on);
867 frame_off = kmo_dfs_get_frame(frameset, ARC_OFF);
868 if (frame_off == NULL) {
869 cpl_msg_error(__func__,
"No ARC_OFF frame found") ;
874 next_off = cpl_frame_get_nextensions(frame_off);
875 mh_off = cpl_propertylist_load(cpl_frame_get_filename(frame_off), 0);
876 ndit_off = kmos_pfits_get_ndit(mh_off) ;
877 exptime_off = kmos_pfits_get_exptime(mh_off) ;
878 readmode_off = kmos_pfits_get_readmode(mh_off);
881 frame_on = kmo_dfs_get_frame(frameset, ARC_ON);
882 if (frame_on == NULL) {
883 cpl_msg_error(__func__,
"No ARC_ON frame found") ;
884 cpl_propertylist_delete(mh_off);
887 while (frame_on != NULL) {
889 next_on = cpl_frame_get_nextensions(frame_on);
890 mh_on = cpl_propertylist_load(cpl_frame_get_filename(frame_on), 0);
891 ndit_on = kmos_pfits_get_ndit(mh_on) ;
892 exptime_on = kmos_pfits_get_exptime(mh_on) ;
893 readmode_on = kmos_pfits_get_readmode(mh_on);
896 if (ndit_on != ndit_off || strcmp(readmode_on, readmode_off) ||
897 fabs(exptime_on-exptime_off) > 0.01 || next_off != next_on) {
898 cpl_msg_warning(__func__,
"Inconsistency for frame %s",
899 cpl_frame_get_filename(frame_on)) ;
900 cpl_propertylist_delete(mh_off);
901 cpl_propertylist_delete(mh_on);
904 cpl_propertylist_delete(mh_on);
907 frame_on = kmo_dfs_get_frame(frameset, NULL);
909 cpl_propertylist_delete(mh_off);
916 for (ext = 1; ext <= next_off ; ext++) {
917 eh_off = cpl_propertylist_load(cpl_frame_get_filename(frame_off), ext);
918 nx_off = kmos_pfits_get_naxis1(eh_off) ;
919 ny_off = kmos_pfits_get_naxis2(eh_off) ;
921 frame_on = kmo_dfs_get_frame(frameset, ARC_ON);
922 while (frame_on != NULL) {
923 eh_on = cpl_propertylist_load(cpl_frame_get_filename(frame_on),ext);
924 nx_on = kmos_pfits_get_naxis1(eh_on) ;
925 ny_on = kmos_pfits_get_naxis2(eh_on) ;
927 if (nx_on != nx_off || ny_off != ny_on) {
928 cpl_msg_warning(__func__,
"Inconsistency for frame %s",
929 cpl_frame_get_filename(frame_on)) ;
930 cpl_propertylist_delete(eh_off);
931 cpl_propertylist_delete(eh_on);
934 cpl_propertylist_delete(eh_on);
937 frame_on = kmo_dfs_get_frame(frameset, NULL);
939 cpl_propertylist_delete(eh_off);
943 frame_on = kmo_dfs_get_frame(frameset, FLAT_EDGE);
944 if (cpl_frame_get_nextensions(frame_on) % 24 != 0) {
945 cpl_msg_warning(__func__,
"FLAT_EDGE frame is not consistent") ;
950 kmo_check_frame_setup(frameset, ARC_ON, XCAL, TRUE, FALSE, FALSE);
951 kmo_check_frame_setup(frameset, ARC_ON, YCAL, TRUE, FALSE, FALSE);
952 kmo_check_frame_setup_md5_xycal(frameset);
953 if (cpl_error_get_code() != CPL_ERROR_NONE) {
954 cpl_msg_warning(__func__,
"XCAL / YCAL checks failed") ;
962 *exptime = exptime_off ;
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.