IIINSTRUMENT Pipeline Reference Manual 4.6.1
visir_util_apply_calib.c
1/* $Id: visir_util_apply_calib.c,v 1.3 2013-05-23 14:34:43 jtaylor Exp $
2 *
3 * This file is part of the VISIR Pipeline
4 * Copyright (C) 2012 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: jtaylor $
23 * $Date: 2013-05-23 14:34:43 $
24 * $Revision: 1.3 $
25 * $Name: not supported by cvs2svn $
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31
32/*-----------------------------------------------------------------------------
33 Includes
34 -----------------------------------------------------------------------------*/
35
36#include "visir_recipe.h"
37#include <cxlist.h>
38
39#include <string.h>
40
41
42/*-----------------------------------------------------------------------------
43 Defines
44 -----------------------------------------------------------------------------*/
45
46#define RECIPE_STRING "visir_util_apply_calib"
47
48/*-----------------------------------------------------------------------------
49 Private Functions prototypes
50 -----------------------------------------------------------------------------*/
51
52// FIXME:
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) "
57 "must be tagged:\n"
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");
61
62/*----------------------------------------------------------------------------*/
66/*----------------------------------------------------------------------------*/
67
68/*-----------------------------------------------------------------------------
69 Functions code
70 -----------------------------------------------------------------------------*/
71
72static inline cpl_boolean
73plist_strcmp(const cpl_propertylist * plist,
74 const char * key, const char * val)
75{
76 if (!cpl_propertylist_has(plist, key))
77 return CPL_FALSE;
78 return strcmp(cpl_propertylist_get_string(plist, key), val) == 0;
79}
80
81
82/*----------------------------------------------------------------------------*/
90/*----------------------------------------------------------------------------*/
91static cpl_error_code
92visir_util_apply_calib_fill_parameterlist(cpl_parameterlist * self)
93{
94 if (self) {}
95 return CPL_ERROR_NONE;
96}
97
98
99static cpl_frameset *
100get_img_conv(double * conv, double * error,
101 irplib_framelist * phot_frames)
102{
103 cpl_vector * v = NULL;
104 double derror = 0.;
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;
110
111 cpl_ensure(conv, CPL_ERROR_NULL_INPUT, NULL);
112
113 skip_if(irplib_framelist_load_propertylist_all(phot_frames, 0,
114 "ESO QC", 0));
115
116 cmb_frames = irplib_framelist_extract(phot_frames,
117 VISIR_IMG_PHOT_COMBINED_PROCATG);
118
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)));
124
125 one_frames = irplib_framelist_extract(phot_frames,
126 VISIR_IMG_PHOT_ONEBEAM_PROCATG);
127 if (one_frames == NULL)
128 cpl_errorstate_set(cleanstate);
129 else {
130 /* TODO unused */
131 skip_if(irplib_framelist_contains(one_frames, "ESO QC CONVER",
132 CPL_TYPE_DOUBLE, CPL_FALSE, 0.));
133
134 v = cpl_vector_new(irplib_framelist_get_size(one_frames));
135
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");
140 skip_if(0);
141
142 cpl_vector_set(v, i, conver);
143 }
144 }
145
146 *conv = cpl_propertylist_get_double(cmb_plist, "ESO QC CONVER");
147
148 if (derror >= 0)
149 cpl_msg_info(cpl_func, "Conversion factor: %g +- %g", *conv, derror);
150 else
151 cpl_msg_info(cpl_func, "Conversion factor: %g", *conv);
152
153 if (error)
154 *error = derror;
155
156 end_skip;
157
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);
163 }
164
165 return usedframes;
166}
167
168static cpl_error_code
169update_error(cpl_image * eimg_, const cpl_image * img_,
170 const double conv, const double cerror)
171{
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);
178
179 cpl_ensure_code(conv != 0. && cerror >= 0., CPL_ERROR_ILLEGAL_INPUT);
180 skip_if(imgd == NULL || eimgd == NULL);
181
182 for (size_t i = 0; i < npix; i++) {
183 /* gaussian propagation */
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));
187 }
188
189 end_skip;
190 cpl_image_delete(img);
191 cpl_image_delete(eimg);
192
193 return cpl_error_get_code();
194}
195
196typedef struct {
197 cpl_image * img;
198 cpl_table * tbl;
199 cpl_propertylist * plist;
200} visir_plane;
201
202static visir_plane *
203visir_plane_new(cpl_image * img, cpl_table * tbl, cpl_propertylist * plist)
204{
205 visir_plane * pl = cpl_calloc(1, sizeof(visir_plane));
206 pl->img = img;
207 pl->tbl = tbl;
208 pl->plist = plist;
209 return pl;
210}
211
212static void visir_plane_delete(visir_plane * pl)
213{
214 if (pl) {
215 cpl_image_delete(pl->img);
216 cpl_table_delete(pl->tbl);
217 cpl_propertylist_delete(pl->plist);
218 cpl_free(pl);
219 }
220}
221
222
223static cx_list *
224planelist_from_frame(const cpl_frame * frame)
225{
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;
233
234 plist = cpl_propertylist_load(fn, 0);
235 skip_if(plist == NULL);
236 // Remove/rename keywords as required
237 visir_dfs_update_header(plist);
238 planelist = cx_list_new();
239
240 img = cpl_image_load(fn, CPL_TYPE_UNSPECIFIED, 0, 0);
241 if (img == NULL)
242 cpl_errorstate_set(cleanstate);
243
244 cx_list_push_back(planelist, visir_plane_new(img, NULL, plist));
245 img = NULL;
246 tbl = NULL;
247 plist = NULL;
248
249 for (cpl_size e = 1; e < next + 1; e++) {
250 img = cpl_image_load(fn, CPL_TYPE_UNSPECIFIED, 0, e);
251 if (img == 0) {
252 cpl_errorstate_set(cleanstate);
253 tbl = cpl_table_load(fn, e, 0);
254 }
255 skip_if(0);
256 plist = cpl_propertylist_load(fn, e);
257 skip_if(plist == NULL);
258 // Remove/rename keywords as required
259 visir_dfs_update_header(plist);
260 cx_list_push_back(planelist, visir_plane_new(img, tbl, plist));
261 img = NULL;
262 tbl = NULL;
263 plist = NULL;
264 }
265
266 end_skip;
267 cpl_image_delete(img);
268 cpl_propertylist_delete(plist);
269
270 if (cpl_error_get_code() != CPL_ERROR_NONE) {
271 cx_list_destroy(planelist, (visir_free)visir_plane_delete);
272 return NULL;
273 }
274 else
275 return planelist;
276}
277
278
279static cpl_error_code
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)
284{
285 cpl_frameset * usedframes = cpl_frameset_new();
286 cx_list * planes = NULL;
287
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;
291 char buffer[300];
292 visir_plane * skip[] = {NULL, NULL};
293
294 planes = planelist_from_frame(frm);
295 skip_if(planes == NULL);
296
297 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
298
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));
303 }
304 skip_if(0);
305
306 visir_plane * first = cx_list_front(planes);
307 cpl_image * simg =
308 cpl_image_multiply_scalar_create(first->img, 1. / conv);
309 skip_if(simg == NULL);
310 cpl_propertylist_update_string(first->plist, "BUNIT", "Jy");
311
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);
318 skip_if(0);
319
320 /* propagate the error */
321 FOR_EACH_T(visir_plane * pl, planes) {
322 if (plist_strcmp(pl->plist, "EXTNAME", VISIR_EXTN_ERROR)) {
323 eimg = pl->img;
324
325 update_error(eimg, first->img, conv, error);
326 cpl_propertylist_update_string(pl->plist, "BUNIT", "Jy");
327
328 cpl_image_save(eimg, buffer, CPL_TYPE_FLOAT,
329 pl->plist, CPL_IO_EXTEND);
330 skip[0] = pl;
331 }
332 skip_if(0);
333 }
334 /* fix the weight map */
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);
339
340 cpl_image_save(wgt, buffer, CPL_TYPE_FLOAT,
341 pl->plist, CPL_IO_EXTEND);
342 cpl_image_delete(wgt);
343 skip[1] = pl;
344 }
345 skip_if(0);
346 }
347 /* propagate the rest */
348 FOR_EACH_T(visir_plane * pl, planes) {
349 if (pl == first || pl == skip[0] || pl == skip[1])
350 continue;
351
352 if (pl->img)
353 cpl_image_save(pl->img, buffer, CPL_TYPE_UNSPECIFIED,
354 pl->plist, CPL_IO_EXTEND);
355 else if (pl->tbl)
356 cpl_table_save(pl->tbl, NULL, pl->plist, buffer,
357 CPL_IO_EXTEND);
358 else
359 cpl_propertylist_save(pl->plist, buffer, CPL_IO_EXTEND);
360 skip_if(0);
361 }
362 cx_list_destroy(planes, (visir_free)visir_plane_delete);
363 planes = NULL;
364 }
365
366 end_skip;
367 cx_list_destroy(planes, (visir_free)visir_plane_delete);
368
369 cpl_frameset_delete(usedframes);
370
371 return cpl_error_get_code();
372}
373
374static cpl_error_code
375propagate_all(cpl_frameset * framelist, const cpl_parameterlist * parlist,
376 irplib_framelist * allframes)
377{
378 cpl_frameset * usedframes = cpl_frameset_new();
379 cx_list * planes = NULL;
380
381 for (int i = 0; i < irplib_framelist_get_size(allframes); i++) {
382 cpl_frame * frm = irplib_framelist_get(allframes, i);
383 char buffer[300];
384 sprintf(buffer, "visir_result_%03d.fits", i + 1);
385
386 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
387 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
388
389 planes = planelist_from_frame(frm);
390 skip_if(planes == NULL);
391 visir_plane * first = cx_list_front(planes);
392
393 if (first->img)
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);
398 else
399 irplib_dfs_save_propertylist(framelist, parlist, usedframes,
400 RECIPE_STRING,
401 cpl_frame_get_tag(frm),
402 first->plist, NULL,
403 visir_pipe_id, buffer);
404 skip_if(0);
405
406 FOR_EACH_T(visir_plane * pl, planes) {
407 if (pl == first)
408 continue;
409 if (pl->img)
410 cpl_image_save(pl->img, buffer, CPL_TYPE_UNSPECIFIED,
411 pl->plist, CPL_IO_EXTEND);
412 else if (pl->tbl)
413 cpl_table_save(pl->tbl, NULL, pl->plist, buffer,
414 CPL_IO_EXTEND);
415 else
416 cpl_propertylist_save(pl->plist, buffer, CPL_IO_EXTEND);
417 skip_if(0);
418 }
419
420 cx_list_destroy(planes, (visir_free)visir_plane_delete);
421 planes = NULL;
422 }
423
424 end_skip;
425 cpl_frameset_delete(usedframes);
426 cx_list_destroy(planes, (visir_free)visir_plane_delete);
427
428 return cpl_error_get_code();
429}
430
431
432static cpl_table *
433calibrate_frame(const cpl_frame * frm, const int ext,
434 const cpl_bivector * std, const cpl_bivector * stde)
435{
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);
443
444 /* get region where calib and object wavelength overlap */
445 cpl_vector * objv =
446 cpl_vector_wrap(n, cpl_table_get_data_double(obj, "WLEN"));
447
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);
452
453 if (u - l == 0) {
454 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
455 "Calibration data has no wavelength overlap "
456 "with object");
457 cpl_vector_unwrap(objv);
458 skip_if(1);
459 }
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);
464
465 {
466 /* prepare data and error on same grid as object */
467 intstd = cpl_bivector_new(u - l);
468 intstde = cpl_bivector_new(u - l);
469 skip_if(intstd == NULL);
470 skip_if(intstde == NULL);
471 /* copy object wavelength grid */
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));
478
479 /* interpolate standard star data to object wavelength grid */
480 skip_if(cpl_bivector_interpolate_linear(intstd, std));
481 skip_if(cpl_bivector_interpolate_linear(intstde, stde));
482 }
483
484 skip_if(0);
485
486 /* calibrate the data, marking out of bound as invalid */
487 cpl_table_duplicate_column(obj, "SPC_CALIBRATED",
488 obj, "SPC_EXTRACTED");
489 skip_if(0);
490 {
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++) {
494 if (i < l || i >= u)
495 cpl_table_set_invalid(obj, "SPC_CALIBRATED", i);
496 else
497 d[i] /= v[i - l];
498 }
499 }
500
501 cpl_table_new_column(obj, "SPC_CALIBRATED_ERROR", CPL_TYPE_DOUBLE);
502 skip_if(0);
503
504 {
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++) {
510 if (j < l || j >= u)
511 cpl_table_set_invalid(obj, "SPC_CALIBRATED_ERROR", j);
512 else {
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",
516 j, hypot(da, db));
517 }
518 }
519 }
520
521 skip_if(0);
522
523 end_skip;
524
525 cpl_bivector_delete(intstd);
526 cpl_bivector_delete(intstde);
527
528 return obj;
529}
530
531static cpl_error_code
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)
537{
538 const cpl_frame * frm;
539 cpl_bivector * std = NULL;
540 cpl_bivector * stde = NULL;
541 int n_std_ext = 0;
542 const char* std_fn = NULL;
543 skip_if(stdtab == NULL);
544 skip_if(objtab == NULL);
545 /* Check there is only one standard frame supplied */
546 cpl_ensure_code(irplib_framelist_get_size(stdtab) == 1,
547 CPL_ERROR_UNSUPPORTED_MODE);
548 /* Check that there is at least one object frame */
549 cpl_ensure_code(irplib_framelist_get_size(objtab) > 0,
550 CPL_ERROR_UNSUPPORTED_MODE);
551
552 /* Get the standard frame */
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);
557 // cpl_msg_info(cpl_func, "standard %s has %d extensions", std_fn, n_std_ext);
558
559 for (int i = 0; i < irplib_framelist_get_size(objtab); i++) {
560 char buffer[300];
561 cpl_frame * ofrm =
562 cpl_frame_duplicate(irplib_framelist_get_const(objtab, i));
563 sprintf(buffer, "visir_calibrated_%03d.fits", i + 1);
564 /* Keep track of whether the first extension has been written for this new file */
565 int is_saved = 0;
566
567 const int next = cpl_frame_get_nextensions(ofrm);
568 const char * fn = cpl_frame_get_filename(ofrm);
569 /* Ensure that the standard and the object have the same number of extensions */
570 cpl_ensure_code(next == n_std_ext, CPL_ERROR_ILLEGAL_INPUT);
571 // cpl_msg_info(cpl_func, "object %s has %d extensions", fn, next);
572
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);
579
580 cpl_propertylist * phu = cpl_propertylist_load(fn, 0);
581
582 /* Iterate over all the available extensions */
583 for (int j=1; j<=next; j++) {
584 /* Load the FITS header to determine what this extension is */
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);
588 // Remove/rename keywords as required
589 visir_dfs_update_header(plist);
590 if (!strcmp(xt, "BINTABLE")) {
591 /* A table extension will contain the extracted spectrum */
592 /* Load the associated std spectrum */
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);
597 /* calibrate std spectrum, FIXME: do in spc_obs? */
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);
601
602 /* calibrate object spectrum */
603 cpl_table * obj = calibrate_frame(ofrm, j, std, stde);
604
605 /* Save this as the first extension if required, otherwise extend
606 * the existing file */
607 if (!is_saved) {
608 irplib_dfs_save_table(framelist, parlist, usedframes, obj,
609 plist, RECIPE_STRING, procatg, phu,
610 NULL, visir_pipe_id, buffer);
611 is_saved = 1;
612 } else {
613 cpl_table_save(obj, NULL, plist, buffer, CPL_IO_EXTEND);
614 }
615 cpl_bivector_delete(std);
616 cpl_bivector_delete(stde);
617
618 } else if (!strcmp(xt, "IMAGE")) {
619 /* Copy across IMAGE extensions unchanged.
620 * They are the trimmed image and associated extraction weights */
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);
624 } else {
625 /* Give a warning for unknown extensions - should not happen */
626 cpl_msg_warning(cpl_func, "Cannot process %s extension %d of unknown type %s", fn, j, xt);
627 }
628 cpl_propertylist_delete(plist);
629 }
630 cpl_propertylist_delete(phu);
631
632 cpl_frameset_delete(usedframes);
633 skip_if(0);
634 }
635
636 end_skip;
637
638 return cpl_error_get_code();
639}
640
641
642/*----------------------------------------------------------------------------*/
649/*----------------------------------------------------------------------------*/
650static int visir_util_apply_calib(cpl_frameset * framelist,
651 const cpl_parameterlist * parlist)
652{
653 irplib_framelist * allframes = irplib_framelist_cast(framelist);
654 cpl_errorstate cleanstate = cpl_errorstate_get();
655
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);
661
662 if (irplib_framelist_get_size(allframes) > 0)
663 cpl_errorstate_set(cleanstate);
664
665 /* no objects or only objects -> nothing to apply */
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));
675 }
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);
689 skip_if(0);
690 }
691 else {
692 cpl_msg_info(cpl_func, "No calibration data to apply, doing nothing");
693 skip_if(propagate_all(framelist, parlist, allframes));
694 }
695
696 end_skip;
697 irplib_framelist_delete(allframes);
698 irplib_framelist_delete(objects);
699 irplib_framelist_delete(specobs);
700 irplib_framelist_delete(others);
701
702 return cpl_error_get_code();
703}