36#include "visir_recipe.h"
46#define RECIPE_STRING "visir_util_apply_calib"
53cpl_recipe_define(visir_util_apply_calib, VISIR_BINARY_VERSION,
54 "Julian Taylor", PACKAGE_BUGREPORT,
"2012",
55 "Attempt to remove stripes in spectral data",
56 "The files listed in the Set Of Frames (sof-file) "
58 "VISIR-chopnod-corrected-file.fits "
59 "\nThe product(s) will have a FITS card\n"
60 "'HIERARCH ESO PRO CATG' with a value of:\n");
72static inline cpl_boolean
73plist_strcmp(
const cpl_propertylist * plist,
74 const char * key,
const char * val)
76 if (!cpl_propertylist_has(plist, key))
78 return strcmp(cpl_propertylist_get_string(plist, key), val) == 0;
92visir_util_apply_calib_fill_parameterlist(cpl_parameterlist * self)
95 return CPL_ERROR_NONE;
100get_img_conv(
double * conv,
double * error,
101 irplib_framelist * phot_frames)
103 cpl_vector * v = NULL;
105 cpl_errorstate cleanstate = cpl_errorstate_get();
106 irplib_framelist * one_frames = NULL;
107 irplib_framelist * cmb_frames = NULL;
108 cpl_frameset * usedframes = cpl_frameset_new();
109 cpl_propertylist * cmb_plist;
111 cpl_ensure(conv, CPL_ERROR_NULL_INPUT, NULL);
113 skip_if(irplib_framelist_load_propertylist_all(phot_frames, 0,
116 cmb_frames = irplib_framelist_extract(phot_frames,
117 VISIR_IMG_PHOT_COMBINED_PROCATG);
119 skip_if(irplib_framelist_contains(cmb_frames,
"ESO QC CONVER",
120 CPL_TYPE_DOUBLE, CPL_FALSE, 0.));
121 cmb_plist = irplib_framelist_get_propertylist(cmb_frames, 0);
122 cpl_frameset_insert(usedframes,
123 cpl_frame_duplicate(irplib_framelist_get(cmb_frames, 0)));
125 one_frames = irplib_framelist_extract(phot_frames,
126 VISIR_IMG_PHOT_ONEBEAM_PROCATG);
127 if (one_frames == NULL)
128 cpl_errorstate_set(cleanstate);
131 skip_if(irplib_framelist_contains(one_frames,
"ESO QC CONVER",
132 CPL_TYPE_DOUBLE, CPL_FALSE, 0.));
134 v = cpl_vector_new(irplib_framelist_get_size(one_frames));
136 for (
int i = 0; i < irplib_framelist_get_size(one_frames); i++) {
137 const cpl_propertylist * plist =
138 irplib_framelist_get_propertylist_const(one_frames, i);
139 double conver = cpl_propertylist_get_double(plist,
"ESO QC CONVER");
142 cpl_vector_set(v, i, conver);
146 *conv = cpl_propertylist_get_double(cmb_plist,
"ESO QC CONVER");
149 cpl_msg_info(cpl_func,
"Conversion factor: %g +- %g", *conv, derror);
151 cpl_msg_info(cpl_func,
"Conversion factor: %g", *conv);
158 cpl_vector_delete(v);
159 irplib_framelist_delete(cmb_frames);
160 irplib_framelist_delete(one_frames);
161 if (cpl_error_get_code()) {
162 cpl_frameset_delete(usedframes);
169update_error(cpl_image * eimg_,
const cpl_image * img_,
170 const double conv,
const double cerror)
172 cpl_image * img = cpl_image_cast(img_, CPL_TYPE_DOUBLE);
173 cpl_image * eimg = cpl_image_cast(eimg_, CPL_TYPE_DOUBLE);
174 size_t nx = cpl_image_get_size_x(img);
175 size_t npix = nx * cpl_image_get_size_y(img);
176 double * eimgd = cpl_image_get_data_double(eimg);
177 const double * imgd = cpl_image_get_data_double_const(img);
179 cpl_ensure_code(conv != 0. && cerror >= 0., CPL_ERROR_ILLEGAL_INPUT);
180 skip_if(imgd == NULL || eimgd == NULL);
182 for (
size_t i = 0; i < npix; i++) {
184 double da = eimgd[i] / conv;
185 double db = cerror * imgd[i] / (conv * conv);
186 cpl_image_set(eimg_, i % nx + 1, i / nx + 1, hypot(da, db));
190 cpl_image_delete(img);
191 cpl_image_delete(eimg);
193 return cpl_error_get_code();
199 cpl_propertylist * plist;
203visir_plane_new(cpl_image * img, cpl_table * tbl, cpl_propertylist * plist)
205 visir_plane * pl = cpl_calloc(1,
sizeof(visir_plane));
212static void visir_plane_delete(visir_plane * pl)
215 cpl_image_delete(pl->img);
216 cpl_table_delete(pl->tbl);
217 cpl_propertylist_delete(pl->plist);
224planelist_from_frame(
const cpl_frame * frame)
226 cpl_size next = cpl_frame_get_nextensions(frame);
227 const char * fn = cpl_frame_get_filename(frame);
228 cpl_errorstate cleanstate = cpl_errorstate_get();
229 cx_list * planelist = NULL;
230 cpl_propertylist * plist = NULL;
231 cpl_image * img = NULL;
232 cpl_table * tbl = NULL;
234 plist = cpl_propertylist_load(fn, 0);
235 skip_if(plist == NULL);
237 visir_dfs_update_header(plist);
238 planelist = cx_list_new();
240 img = cpl_image_load(fn, CPL_TYPE_UNSPECIFIED, 0, 0);
242 cpl_errorstate_set(cleanstate);
244 cx_list_push_back(planelist, visir_plane_new(img, NULL, plist));
249 for (cpl_size e = 1; e < next + 1; e++) {
250 img = cpl_image_load(fn, CPL_TYPE_UNSPECIFIED, 0, e);
252 cpl_errorstate_set(cleanstate);
253 tbl = cpl_table_load(fn, e, 0);
256 plist = cpl_propertylist_load(fn, e);
257 skip_if(plist == NULL);
259 visir_dfs_update_header(plist);
260 cx_list_push_back(planelist, visir_plane_new(img, tbl, plist));
267 cpl_image_delete(img);
268 cpl_propertylist_delete(plist);
270 if (cpl_error_get_code() != CPL_ERROR_NONE) {
271 cx_list_destroy(planelist, (visir_free)visir_plane_delete);
280apply_img_calib(cpl_frameset *framelist,
const cpl_parameterlist * parlist,
281 irplib_framelist * objects,
282 const double conv,
const double error,
283 cpl_frameset * calibframes)
285 cpl_frameset * usedframes = cpl_frameset_new();
286 cx_list * planes = NULL;
288 for (
int i = 0; i < irplib_framelist_get_size(objects); i++) {
289 cpl_frame * frm = irplib_framelist_get(objects, i);
290 cpl_image * eimg = NULL;
292 visir_plane * skip[] = {NULL, NULL};
294 planes = planelist_from_frame(frm);
295 skip_if(planes == NULL);
297 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
299 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
300 FOR_EACH_FRAMESET(cfrm, calibframes) {
301 cpl_frame_set_group(cfrm, CPL_FRAME_GROUP_RAW);
302 cpl_frameset_insert(usedframes, cpl_frame_duplicate(cfrm));
306 visir_plane * first = cx_list_front(planes);
308 cpl_image_multiply_scalar_create(first->img, 1. / conv);
309 skip_if(simg == NULL);
310 cpl_propertylist_update_string(first->plist,
"BUNIT",
"Jy");
312 sprintf(buffer,
"visir_calibrated_%03d.fits", i + 1);
313 irplib_dfs_save_image(framelist, parlist, usedframes, simg,
314 CPL_TYPE_FLOAT, RECIPE_STRING,
315 VISIR_IMG_OBJ_CALIBRATED_PROCATG, first->plist,
316 NULL, visir_pipe_id, buffer);
317 cpl_image_delete(simg);
321 FOR_EACH_T(visir_plane * pl, planes) {
322 if (plist_strcmp(pl->plist,
"EXTNAME", VISIR_EXTN_ERROR)) {
325 update_error(eimg, first->img, conv, error);
326 cpl_propertylist_update_string(pl->plist,
"BUNIT",
"Jy");
328 cpl_image_save(eimg, buffer, CPL_TYPE_FLOAT,
329 pl->plist, CPL_IO_EXTEND);
335 FOR_EACH_T(visir_plane * pl, planes) {
336 if (plist_strcmp(pl->plist,
"EXTNAME", VISIR_EXTN_WEIGHT)) {
337 cpl_image * wgt = cpl_image_power_create(eimg, -2);
338 cpl_image_fill_rejected(wgt, 0);
340 cpl_image_save(wgt, buffer, CPL_TYPE_FLOAT,
341 pl->plist, CPL_IO_EXTEND);
342 cpl_image_delete(wgt);
348 FOR_EACH_T(visir_plane * pl, planes) {
349 if (pl == first || pl == skip[0] || pl == skip[1])
353 cpl_image_save(pl->img, buffer, CPL_TYPE_UNSPECIFIED,
354 pl->plist, CPL_IO_EXTEND);
356 cpl_table_save(pl->tbl, NULL, pl->plist, buffer,
359 cpl_propertylist_save(pl->plist, buffer, CPL_IO_EXTEND);
362 cx_list_destroy(planes, (visir_free)visir_plane_delete);
367 cx_list_destroy(planes, (visir_free)visir_plane_delete);
369 cpl_frameset_delete(usedframes);
371 return cpl_error_get_code();
375propagate_all(cpl_frameset * framelist,
const cpl_parameterlist * parlist,
376 irplib_framelist * allframes)
378 cpl_frameset * usedframes = cpl_frameset_new();
379 cx_list * planes = NULL;
381 for (
int i = 0; i < irplib_framelist_get_size(allframes); i++) {
382 cpl_frame * frm = irplib_framelist_get(allframes, i);
384 sprintf(buffer,
"visir_result_%03d.fits", i + 1);
386 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
387 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
389 planes = planelist_from_frame(frm);
390 skip_if(planes == NULL);
391 visir_plane * first = cx_list_front(planes);
394 irplib_dfs_save_image(framelist, parlist, usedframes, first->img,
395 CPL_TYPE_UNSPECIFIED, RECIPE_STRING,
396 cpl_frame_get_tag(frm), first->plist,
397 NULL, visir_pipe_id, buffer);
399 irplib_dfs_save_propertylist(framelist, parlist, usedframes,
401 cpl_frame_get_tag(frm),
403 visir_pipe_id, buffer);
406 FOR_EACH_T(visir_plane * pl, planes) {
410 cpl_image_save(pl->img, buffer, CPL_TYPE_UNSPECIFIED,
411 pl->plist, CPL_IO_EXTEND);
413 cpl_table_save(pl->tbl, NULL, pl->plist, buffer,
416 cpl_propertylist_save(pl->plist, buffer, CPL_IO_EXTEND);
420 cx_list_destroy(planes, (visir_free)visir_plane_delete);
425 cpl_frameset_delete(usedframes);
426 cx_list_destroy(planes, (visir_free)visir_plane_delete);
428 return cpl_error_get_code();
433calibrate_frame(
const cpl_frame * frm,
const int ext,
434 const cpl_bivector * std,
const cpl_bivector * stde)
436 const char * dfn = cpl_frame_get_filename(frm);
437 const cpl_vector * swlen = cpl_bivector_get_x_const(std);
438 cpl_bivector * intstd = NULL;
439 cpl_bivector * intstde = NULL;
440 cpl_table * obj = cpl_table_load(dfn, ext, 0);
441 skip_if(obj == NULL);
442 const size_t n = cpl_table_get_nrow(obj);
446 cpl_vector_wrap(n, cpl_table_get_data_double(obj,
"WLEN"));
448 const double smin = cpl_vector_get(swlen, 0);
449 const double smax = cpl_vector_get(swlen, cpl_vector_get_size(swlen) - 1);
450 const size_t l = visir_lower_bound(objv, smin);
451 const size_t u = visir_upper_bound(objv, smax);
454 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
455 "Calibration data has no wavelength overlap "
457 cpl_vector_unwrap(objv);
460 cpl_msg_info(cpl_func,
"Overlapping wavelength: %.4g [mu] (%zu) to "
461 "%.4g [mu] (%zu)", cpl_vector_get(objv, l) * 1e6, l,
462 cpl_vector_get(objv, u - 1) * 1e6, u);
463 cpl_vector_unwrap(objv);
467 intstd = cpl_bivector_new(u - l);
468 intstde = cpl_bivector_new(u - l);
469 skip_if(intstd == NULL);
470 skip_if(intstde == NULL);
472 memcpy(cpl_bivector_get_x_data(intstd),
473 cpl_table_get_data_double_const(obj,
"WLEN") + l,
474 sizeof(
double) * (u - l));
475 memcpy(cpl_bivector_get_x_data(intstde),
476 cpl_table_get_data_double_const(obj,
"WLEN") + l,
477 sizeof(
double) * (u - l));
480 skip_if(cpl_bivector_interpolate_linear(intstd, std));
481 skip_if(cpl_bivector_interpolate_linear(intstde, stde));
487 cpl_table_duplicate_column(obj,
"SPC_CALIBRATED",
488 obj,
"SPC_EXTRACTED");
491 double * d = cpl_table_get_data_double(obj,
"SPC_CALIBRATED");
492 double * v = cpl_vector_get_data(cpl_bivector_get_y(intstd));
493 for (
size_t i = 0; i < n; i++) {
495 cpl_table_set_invalid(obj,
"SPC_CALIBRATED", i);
501 cpl_table_new_column(obj,
"SPC_CALIBRATED_ERROR", CPL_TYPE_DOUBLE);
505 double * ed = cpl_table_get_data_double(obj,
"SPC_ERROR");
506 double * vd = cpl_table_get_data_double(obj,
"SPC_EXTRACTED");
507 double * svd = cpl_bivector_get_y_data(intstd);
508 double * sed = cpl_bivector_get_y_data(intstde);
509 for (
size_t j = 0; j < n; j++) {
511 cpl_table_set_invalid(obj,
"SPC_CALIBRATED_ERROR", j);
513 double da = ed[j] / svd[j - l];
514 double db = sed[j - l] * vd[j] / (svd[j - l] * svd[j - l]);
515 cpl_table_set_double(obj,
"SPC_CALIBRATED_ERROR",
525 cpl_bivector_delete(intstd);
526 cpl_bivector_delete(intstde);
532get_spec_std(cpl_frameset * framelist,
533 const irplib_framelist * stdtab,
534 const irplib_framelist * objtab,
535 const cpl_parameterlist * parlist,
536 const char * procatg)
538 const cpl_frame * frm;
539 cpl_bivector * std = NULL;
540 cpl_bivector * stde = NULL;
542 const char* std_fn = NULL;
543 skip_if(stdtab == NULL);
544 skip_if(objtab == NULL);
546 cpl_ensure_code(irplib_framelist_get_size(stdtab) == 1,
547 CPL_ERROR_UNSUPPORTED_MODE);
549 cpl_ensure_code(irplib_framelist_get_size(objtab) > 0,
550 CPL_ERROR_UNSUPPORTED_MODE);
553 frm = irplib_framelist_get_const(stdtab, 0);
554 skip_if(frm == NULL);
555 n_std_ext = cpl_frame_get_nextensions(frm);
556 std_fn = cpl_frame_get_filename(frm);
559 for (
int i = 0; i < irplib_framelist_get_size(objtab); i++) {
562 cpl_frame_duplicate(irplib_framelist_get_const(objtab, i));
563 sprintf(buffer,
"visir_calibrated_%03d.fits", i + 1);
567 const int next = cpl_frame_get_nextensions(ofrm);
568 const char * fn = cpl_frame_get_filename(ofrm);
570 cpl_ensure_code(next == n_std_ext, CPL_ERROR_ILLEGAL_INPUT);
573 cpl_frame * sfrm = cpl_frame_duplicate(frm);
574 cpl_frameset * usedframes = cpl_frameset_new();
575 cpl_frame_set_group(sfrm, CPL_FRAME_GROUP_CALIB);
576 cpl_frame_set_group(ofrm, CPL_FRAME_GROUP_RAW);
577 cpl_frameset_insert(usedframes, sfrm);
578 cpl_frameset_insert(usedframes, ofrm);
580 cpl_propertylist * phu = cpl_propertylist_load(fn, 0);
583 for (
int j=1; j<=next; j++) {
585 cpl_propertylist * plist = cpl_propertylist_load(fn, j);
586 const char * xt = cpl_propertylist_get_string(plist,
"XTENSION");
587 cpl_msg_info(cpl_func,
"object %s extension %d is %s", fn, j, xt);
589 visir_dfs_update_header(plist);
590 if (!strcmp(xt,
"BINTABLE")) {
593 cpl_bivector * model = visir_bivector_load_fits(std_fn,
"WLEN",
594 "STD_STAR_MODEL", j);
595 std = visir_bivector_load_fits(std_fn,
"WLEN",
"SPC_EXTRACTED", j);
596 stde = visir_bivector_load_fits(std_fn,
"WLEN",
"SPC_ERROR", j);
598 cpl_vector_divide(cpl_bivector_get_y(std), cpl_bivector_get_y(model));
599 cpl_vector_divide(cpl_bivector_get_y(stde), cpl_bivector_get_y(model));
600 cpl_bivector_delete(model);
603 cpl_table * obj = calibrate_frame(ofrm, j, std, stde);
608 irplib_dfs_save_table(framelist, parlist, usedframes, obj,
609 plist, RECIPE_STRING, procatg, phu,
610 NULL, visir_pipe_id, buffer);
613 cpl_table_save(obj, NULL, plist, buffer, CPL_IO_EXTEND);
615 cpl_bivector_delete(std);
616 cpl_bivector_delete(stde);
618 }
else if (!strcmp(xt,
"IMAGE")) {
621 cpl_image * img = cpl_image_load(fn, CPL_TYPE_UNSPECIFIED, 0, j);
622 cpl_image_save(img, buffer, CPL_TYPE_UNSPECIFIED, plist, CPL_IO_EXTEND);
623 cpl_image_delete(img);
626 cpl_msg_warning(cpl_func,
"Cannot process %s extension %d of unknown type %s", fn, j, xt);
628 cpl_propertylist_delete(plist);
630 cpl_propertylist_delete(phu);
632 cpl_frameset_delete(usedframes);
638 return cpl_error_get_code();
650static int visir_util_apply_calib(cpl_frameset * framelist,
651 const cpl_parameterlist * parlist)
653 irplib_framelist * allframes = irplib_framelist_cast(framelist);
654 cpl_errorstate cleanstate = cpl_errorstate_get();
656 irplib_framelist * others = NULL;
657 irplib_framelist * objects =
658 irplib_framelist_extract_regexp(allframes,
".*OBJ.*", CPL_FALSE);
659 irplib_framelist * specobs =
660 irplib_framelist_extract_regexp(allframes,
".*SPC_OBS.*", CPL_FALSE);
662 if (irplib_framelist_get_size(allframes) > 0)
663 cpl_errorstate_set(cleanstate);
666 if (objects && irplib_framelist_get_size(objects) <
667 irplib_framelist_get_size(allframes)) {
668 double conv = 1., error = 0.;
669 cpl_msg_info(cpl_func,
"Applying conversion factor");
670 cpl_frameset * calibframes = get_img_conv(&conv, &error, allframes);
671 skip_if(calibframes == NULL);
672 skip_if(apply_img_calib(framelist, parlist, objects, conv, error, calibframes));
673 others = irplib_framelist_extract_regexp(allframes,
".*OBJ.*", CPL_TRUE);
674 skip_if(propagate_all(framelist, parlist, others));
676 else if (specobs && irplib_framelist_get_size(specobs) <
677 irplib_framelist_get_size(allframes)) {
678 irplib_framelist * stdtab =
679 irplib_framelist_extract_regexp(allframes,
".*PHOT.*TAB", CPL_FALSE);
680 irplib_framelist * objtab =
681 irplib_framelist_extract_regexp(allframes,
".*OBS.*TAB", CPL_FALSE);
682 cpl_msg_info(cpl_func,
"Removing telluric lines");
683 skip_if(get_spec_std(framelist, stdtab, objtab,
684 parlist,
"SPC_OBS_LMR_TAB"));
685 others = irplib_framelist_extract_regexp(allframes,
".*OBS.*TAB", CPL_TRUE);
686 propagate_all(framelist, parlist, others);
687 irplib_framelist_delete(objtab);
688 irplib_framelist_delete(stdtab);
692 cpl_msg_info(cpl_func,
"No calibration data to apply, doing nothing");
693 skip_if(propagate_all(framelist, parlist, allframes));
697 irplib_framelist_delete(allframes);
698 irplib_framelist_delete(objects);
699 irplib_framelist_delete(specobs);
700 irplib_framelist_delete(others);
702 return cpl_error_get_code();