IIINSTRUMENT Pipeline Reference Manual 4.4.3
visir_util_undistort.c
1/* $Id: visir_util_undistort.c,v 1.30 2013-05-13 16:05:04 jtaylor Exp $
2 *
3 * This file is part of the VISIR Pipeline
4 * Copyright (C) 2002,2003 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-13 16:05:04 $
24 * $Revision: 1.30 $
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
38#include "visir_spc_distortion.h"
39#include "visir_cpl_compat.h"
40#include "visir_utils.h"
41#include <cxlist.h>
42#ifdef _OPENMP
43#include <omp.h>
44#endif
45
46/*-----------------------------------------------------------------------------
47 Defines
48 -----------------------------------------------------------------------------*/
49
50#define RECIPE_STRING "visir_util_undistort"
51
52/*-----------------------------------------------------------------------------
53 Private Functions prototypes
54 -----------------------------------------------------------------------------*/
55
56#ifdef VISIR_CHAIN
57#define cpl_plugin_get_info visir_util_undistort_get_info
58#endif
59cpl_recipe_define(visir_util_undistort, VISIR_BINARY_VERSION,
60 "Lars Lundin", PACKAGE_BUGREPORT, "2011",
61 "Correct the distortion in spectral data",
62 "The files listed in the Set Of Frames (sof-file) "
63 "must be tagged:\n"
64 "VISIR-chopnod-corrected-file.fits " VISIR_UTIL_UNDISTORT_RAW
65 "\nOptionally, a bad pixel map may be provided:\n"
66 "VISIR-bpm-file.fits " VISIR_CALIB_STATIC_MASK "\n"
67 "\nThe product(s) will have a FITS card\n"
68 "'HIERARCH ESO PRO CATG' with a value of:\n"
69 VISIR_UTIL_UNDISTORT_PROCATG "\n"
70#ifdef VISIR_UTIL_UNDISTORT_AUTO_REJECT
71 "If no bad pixel map is provided, the recipe will "
72 "automatically flag input intensities greater than or equal "
73 "to 32767 as bad.\n"
74#endif
75 "The recipe default values for the transformation are only "
76 "valid for spectral data taken in Low resolution mode");
77
78/*----------------------------------------------------------------------------*/
82/*----------------------------------------------------------------------------*/
83
84/*-----------------------------------------------------------------------------
85 Functions code
86 -----------------------------------------------------------------------------*/
87
88
89/*----------------------------------------------------------------------------*/
97/*----------------------------------------------------------------------------*/
98static cpl_error_code
99visir_util_undistort_fill_parameterlist(cpl_parameterlist * self)
100{
101 cpl_error_code err;
102 const char * context = PACKAGE "." RECIPE_STRING;
103
104 /* --bkgcorrect */
105 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
106 "bkgcorrect", CPL_TRUE, NULL, context,
107 "Cho-nod correct the data");
108 cpl_ensure_code(!err, err);
109
110 /* --xl */
111 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
112 "xl", 117, NULL, context,
113 "Coordinate in spatial direction. "
114 "Together with yl it defines the "
115 "lower point of a rectangle containing "
116 "only skylines for the "
117 "wavelength shift detection");
118 cpl_ensure_code(!err, err);
119
120 /* --yl */
121 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
122 "yl", 110, NULL, context,
123 "Coordinate in wavelength direction. "
124 "See xl");
125 cpl_ensure_code(!err, err);
126
127 /* --xh */
128 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
129 "xh", 125, NULL, context,
130 "Coordinate in spatial direction. "
131 "Together with yl it defines the "
132 "higher point of a rectangle containing "
133 "only skylines for the "
134 "wavelength shift detection");
135 cpl_ensure_code(!err, err);
136
137 /* --yh */
138 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
139 "yh", 150, NULL, context,
140 "Coordinate in wavelength direction. "
141 "See xh");
142 cpl_ensure_code(!err, err);
143
144 return visir_parameter_set(self, RECIPE_STRING, VISIR_PARAM_SLITSKEW |
145 VISIR_PARAM_SPECSKEW | VISIR_PARAM_VERTARC |
146 VISIR_PARAM_HORIARC)
147 ? cpl_error_set_where(cpl_func) : CPL_ERROR_NONE;
148}
149
150/*----------------------------------------------------------------------------*/
160/*----------------------------------------------------------------------------*/
161static void
162shift_data(double * out, const double * in, size_t n, double shift)
163{
164 /* FIXME: larger smoothing kernel would be better for this purpose */
165 if (shift < 0) {
166 out[0] = in[0];
167 for (size_t i = 1; i < n; i++)
168 out[i] = (in[i] - in[i - 1]) * shift + in[i];
169 }
170 else {
171 out[n - 1] = in[n - 1];
172 for (size_t i = 0; i < n - 1; i++)
173 out[i] = (in[i + 1] - in[i]) * shift + in[i];
174 }
175}
176
177/*----------------------------------------------------------------------------*/
199/*----------------------------------------------------------------------------*/
200static double
201get_grating_shift(const cpl_image * a, const cpl_image * b,
202 cpl_size xl, cpl_size yl, cpl_size xh, cpl_size yh)
203{
204 cpl_image * aslice = cpl_image_extract(a, xl, yl, xh, yh);
205 cpl_image * bslice = cpl_image_extract(b, xl, yl, xh, yh);
206 const size_t n = yh - yl;
207 double adata[n];
208 double bdata[n];
209 cpl_vector * vb;
210 cpl_vector * va;
211 double minsum = DBL_MAX;
212 double best_shift = 0;
213 const int step = 5000;
214 /* +- shift search range */
215 const double range = 1;
216
217 /* extract median of the rows */
218 for (size_t i = 0; i < n; i++) {
219 va = cpl_vector_new_from_image_row(aslice, i + 1);
220 vb = cpl_vector_new_from_image_row(bslice, i + 1);
221 adata[i] = cpl_vector_get_median(va);
222 bdata[i] = cpl_vector_get_median(vb);
223 cpl_vector_delete(va);
224 cpl_vector_delete(vb);
225 }
226 va = cpl_vector_wrap(n, adata);
227 vb = cpl_vector_wrap(n, bdata);
228 /* correct for intensity offsets */
229 cpl_vector_subtract_scalar(va, cpl_vector_get_median_const(va));
230 cpl_vector_subtract_scalar(vb, cpl_vector_get_median_const(vb));
231
232 /* real subtraction */
233 cpl_vector_subtract(vb, va);
234
235 /* FIXME: can be speed up by doing a coarse grain search first */
236 /* brute force search for the best shift */
237 for (int i = 0; i < step; i++) {
238 const double shift = (double)(i - (step / 2)) / step * range * 2;
239 double ashifted[n];
240 double sum = 0.;
241
242 shift_data(ashifted, adata, n, shift);
243
244 /* compare squared difference of shifted to real subtraction */
245 for (size_t j = 0; j < n; j++) {
246 const double tmp = (ashifted[j] - adata[j]) - bdata[j];
247 sum += tmp * tmp;
248 }
249
250 if (sum < minsum) {
251 best_shift = shift;
252 minsum = sum;
253 }
254 }
255
256 cpl_vector_unwrap(va);
257 cpl_vector_unwrap(vb);
258 cpl_image_delete(aslice);
259 cpl_image_delete(bslice);
260
261 cpl_msg_info(cpl_func, "Grating shift: %.3f", best_shift);
262
263 return best_shift;
264}
265
266static void
267vimglist_append(visir_imglist * a, visir_imglist * b)
268{
269 for (cpl_size i = 0; i < visir_imglist_get_size(b); i++) {
270 visir_imglist_append(a, visir_imglist_get_img(b, i),
271 visir_imglist_get_data(b, i));
272 }
273 visir_imglist_unwrap(b, NULL);
274}
275
276static visir_imglist *
277load_images(cpl_frame * frame, const cpl_mask * bpm, const char * keyword)
278{
279 const char * kword = keyword ? keyword : "ESO DRS CUMOFFSET.";
280 const int next = cpl_frame_get_nextensions(frame);
281 const char * filename = cpl_frame_get_filename(frame);
282 cpl_image * img = NULL;
283 visir_imglist * res = visir_imglist_new(next, NULL);
284 cpl_propertylist * plist = cpl_propertylist_load_regexp(filename, 0, kword,
285 CPL_FALSE);
286 for (int iext = 0; iext < next + 1; iext++) {
287 cpl_errorstate prestate = cpl_errorstate_get();
288
289 img = cpl_image_load(filename, CPL_TYPE_FLOAT, 0, iext);
290 if (img == NULL) {
291 cpl_msg_debug(cpl_func, "No image-data in extension %d", iext);
292 cpl_errorstate_set(prestate);
293 continue;
294 }
295
296 if (bpm != NULL) {
297 skip_if(cpl_image_reject_from_mask(img, bpm));
298 visir_interpolate_rejected(img, NULL, NULL);
299 }
300
301 visir_imglist_append(res, img, cpl_propertylist_duplicate(plist));
302 }
303
304 end_skip;
305
306 cpl_propertylist_delete(plist);
307
308 return res;
309}
310
311
312/*----------------------------------------------------------------------------*/
320/*----------------------------------------------------------------------------*/
321static cpl_error_code
322overscan_correct(cpl_image * img)
323{
324 const cpl_size nx = cpl_image_get_size_x(img);
325 const cpl_size ny = cpl_image_get_size_y(img);
326
327 /* FIXME: remove hardcoding, maybe use window keys from fits */
328 cpl_image * top = cpl_image_extract(img, 1, ny - 7, nx, ny);
329 cpl_image * bot = cpl_image_extract(img, 1, 7, nx, 13);
330
331 for (cpl_size x = 1; x < nx + 1; x++) {
332 cpl_vector * t = cpl_vector_new_from_image_column(top, x);
333 cpl_vector * b = cpl_vector_new_from_image_column(bot, x);
334 double topmed = cpl_vector_get_median(t);
335 double botmed = cpl_vector_get_median(b);
336 for (cpl_size y = 1; y < ny / 2 + 1; y++) {
337 int d;
338 cpl_image_set(img, x, y, cpl_image_get(img, x, y, &d) - botmed);
339 }
340 for (cpl_size y = ny / 2 + 1; y < ny + 1; y++) {
341 int d;
342 cpl_image_set(img, x, y, cpl_image_get(img, x, y, &d) - topmed);
343 }
344 cpl_vector_delete(t);
345 cpl_vector_delete(b);
346 }
347
348 cpl_image_delete(top);
349 cpl_image_delete(bot);
350
351 return cpl_error_get_code();
352}
353
354
355static cpl_error_code
356handle_images(visir_imglist * list, const cpl_image * base,
357 cpl_size xl, cpl_size yl, cpl_size xh, cpl_size yh,
358 double phi, double ksi, double eps, double delta,
359 const visir_data_type dtype)
360{
361 const cpl_size n = visir_imglist_get_size(list);
362 const cpl_size nx = cpl_image_get_size_x(visir_imglist_get_img(list, 0));
363 const cpl_size ny = cpl_image_get_size_y(visir_imglist_get_img(list, 0));
364 error_if(xh > nx || yh > ny, CPL_ERROR_ILLEGAL_INPUT,
365 "Sky region %d/%d larger than image %d/%d", (int)xh, (int)yh,
366 (int)nx, (int)ny);
367
368#ifdef _OPENMP
369#pragma omp parallel for
370#endif
371 for (cpl_size i = 0; i < n; i++) {
372 cpl_image * img = visir_imglist_get_img(list, i);
373
374 /* undistort only average for aquarius
375 * FIXME: correction required? */
376 if (visir_data_is_drs(dtype)) {
377 double shift = get_grating_shift(base, img, xl, yl, xh, yh);
378 visir_spc_det_warp(&img, 1, 0., shift, phi, ksi, eps, delta);
379 }
380 else {
381 overscan_correct(img);
382 cpl_propertylist * plist = visir_imglist_get_data(list, i);
383 double dx = cpl_propertylist_get_double(plist,
384 VISIR_DRS_CUMOFFSETX);
385 double dy = cpl_propertylist_get_double(plist,
386 VISIR_DRS_CUMOFFSETY);
387 visir_spc_det_warp(&img, 1, -dx, -dy, phi, ksi, eps, delta);
388 }
389 }
390
391 end_skip;
392
393 return cpl_error_get_code();
394}
395
396
397static cpl_error_code
398save_images(visir_imglist * imgs, cpl_frameset * products,
399 cpl_frameset * usedframes, const cpl_propertylist * plist,
400 const cpl_parameterlist * parlist)
401{
402 static int j = 0;
403 char * proname = cpl_sprintf(RECIPE_STRING "_%03d" CPL_DFS_FITS, j++);
404
405 skip_if(irplib_dfs_save_propertylist(products, parlist, usedframes,
406 RECIPE_STRING,
407 VISIR_UTIL_UNDISTORT_PROCATG,
408 plist, NULL,
409 visir_pipe_id, proname));
410 for (cpl_size i = 0; i < visir_imglist_get_size(imgs); i++) {
411 cpl_image * img = visir_imglist_get_img(imgs, i);
412 cpl_image_save(img, proname, CPL_BPP_IEEE_FLOAT, NULL, CPL_IO_EXTEND);
413 }
414
415 end_skip;
416 cpl_free(proname);
417
418 return cpl_error_get_code();
419}
420
421static inline int
422comp_expno(cpl_frame * a, cpl_frame * b)
423{
424 const char * fna = cpl_frame_get_filename(a);
425 const char * fnb = cpl_frame_get_filename(b);
426 cpl_propertylist * alist = cpl_propertylist_load(fna, 0);
427 cpl_propertylist * blist = cpl_propertylist_load(fnb, 0);
428
429 int expa = cpl_propertylist_get_int(alist, "ESO TPL EXPNO");
430 int expb = cpl_propertylist_get_int(blist, "ESO TPL EXPNO");
431 int ret = 0;
432
433 if (expa < expb)
434 ret = -1;
435 if (expa > expb)
436 ret = 1;
437
438 cpl_propertylist_delete(alist);
439 cpl_propertylist_delete(blist);
440 return ret;
441}
442
443static cx_list *
444sort_framelist(irplib_framelist * allframes, const char * tag)
445{
446 irplib_framelist * on =
447 irplib_framelist_extract_regexp(allframes, tag, CPL_FALSE);
448 cx_list * frames = cx_list_new();
449
450 for (int i = irplib_framelist_get_size(on); i-- > 0;)
451 cx_list_push_back(frames, irplib_framelist_unset(on, i, NULL));
452
453 /* FIXME: optimize */
454 cx_list_sort(frames, (cx_compare_func)comp_expno);
455
456 irplib_framelist_delete(on);
457
458 return frames;
459}
460
461
462cpl_error_code
463check_rawframes(const irplib_framelist * rawframes,
464 cpl_propertylist * plist)
465{
466 cpl_errorstate cleanstate = cpl_errorstate_get();
467 const char * dit_key = VISIR_PFITS_DOUBLE_DIT;
468 if (cpl_propertylist_has(plist, VISIR_PFITS_DOUBLE_SEQ1_DIT))
469 dit_key = VISIR_PFITS_DOUBLE_SEQ1_DIT;
470
471 /* DIT must be present every where */
472 skip_if(irplib_framelist_contains(rawframes, dit_key,
473 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
474 if(irplib_framelist_contains(rawframes, dit_key,
475 CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5)) {
476 /* Allow 0.1 ms difference - or warn */
477 /* FIXME: The recipe does not properly handle non-uniform DITSs */
478 visir_error_reset("DIT differs by more than %g", 1e-5);
479 }
480
481 /* FIXME: Verify the angular distance */
482 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_RA,
483 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
484
485 /* FIXME: Allow 1 degree difference */
486 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DEC,
487 CPL_TYPE_DOUBLE, CPL_TRUE, 1.0));
488
489 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_CHOP_NCYCLES,
490 CPL_TYPE_INT, CPL_TRUE, 0.0));
491
492 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NDIT,
493 CPL_TYPE_INT, CPL_TRUE, 0.0));
494
495 if (irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_STARNAME,
496 CPL_TYPE_STRING, CPL_TRUE, 0.0)) {
497 visir_error_reset("Rawframe(s) missing standard star name");
498 }
499
500 int nnod = irplib_framelist_get_size(rawframes);
501 /* frames not chop corrected, so divide the chop factor away again */
502 double exptime = visir_utils_get_exptime(nnod, plist) / 2.;
503 skip_if(0);
504
505 cpl_propertylist_append_double(plist, "ESO QC EXPTIME", exptime);
506
507 end_skip;
508
509 return cpl_error_get_code();
510}
511
512
513static void update_exectime(const cpl_frame * frm, double * t_min_obsstart,
514 double * t_max_filewrite)
515{
516 cpl_propertylist * plist = cpl_propertylist_load(cpl_frame_get_filename(frm), 0);
517 if (plist == NULL || !cpl_propertylist_has(plist, "ESO DRS DATE") ||
518 !cpl_propertylist_has(plist, "ESO DRS DATE-OBS")) {
519 cpl_propertylist_delete(plist);
520 return;
521 }
522 *t_max_filewrite =
523 CX_MAX(cpl_propertylist_get_double(plist, "ESO DRS DATE"),
524 *t_max_filewrite);
525 *t_min_obsstart =
526 CX_MIN(cpl_propertylist_get_double(plist, "ESO DRS DATE-OBS"),
527 *t_min_obsstart);
528 cpl_propertylist_delete(plist);
529}
530
531static void vimglist_delete(visir_imglist * list)
532{
533 visir_imglist_delete(list, (visir_free)&cpl_propertylist_delete);
534}
535
536/*----------------------------------------------------------------------------*/
543/*----------------------------------------------------------------------------*/
544static int visir_util_undistort(cpl_frameset * framelist,
545 const cpl_parameterlist * parlist)
546{
547 cpl_errorstate cleanstate = cpl_errorstate_get();
548 const cpl_frame * bpmframe = cpl_frameset_find_const
549 (framelist, VISIR_CALIB_STATIC_MASK);
550 irplib_framelist * allframes = NULL;
551 irplib_framelist * rawframes = NULL;
552 irplib_framelist * rawframes_a = NULL;
553 irplib_framelist * rawframes_b = NULL;
554 cpl_image * imbpm = NULL;
555 cpl_mask * bpm = NULL;
556
557#ifdef _OPENMP
558 omp_set_num_threads(visir_get_num_threads(CPL_FALSE));
559#endif
560
561 const cpl_boolean bkgcorrect =
562 irplib_parameterlist_get_bool(parlist, PACKAGE,
563 RECIPE_STRING, "bkgcorrect");
564
565 /* The angles are given in degrees and then converted to radians */
566
567 double ksi = visir_parameterlist_get_double(parlist, RECIPE_STRING,
568 VISIR_PARAM_SPECSKEW)
569 * CPL_MATH_RAD_DEG;
570 double eps = visir_parameterlist_get_double(parlist, RECIPE_STRING,
571 VISIR_PARAM_VERTARC);
572 double delta = visir_parameterlist_get_double(parlist, RECIPE_STRING,
573 VISIR_PARAM_HORIARC);
574 double phi = visir_parameterlist_get_double(parlist, RECIPE_STRING,
575 VISIR_PARAM_SLITSKEW)
576 * CPL_MATH_RAD_DEG;
577
578 const cpl_size xl = irplib_parameterlist_get_int(parlist, PACKAGE,
579 RECIPE_STRING, "xl");
580 const cpl_size yl = irplib_parameterlist_get_int(parlist, PACKAGE,
581 RECIPE_STRING, "yl");
582 const cpl_size xh = irplib_parameterlist_get_int(parlist, PACKAGE,
583 RECIPE_STRING, "xh");
584 const cpl_size yh = irplib_parameterlist_get_int(parlist, PACKAGE,
585 RECIPE_STRING, "yh");
586
587 visir_imglist * aon = visir_imglist_new(100, NULL);
588 visir_imglist * aoff = visir_imglist_new(100, NULL);
589 visir_imglist * bon = visir_imglist_new(100, NULL);
590 visir_imglist * boff = visir_imglist_new(100, NULL);
591
592 cpl_frameset * usedframes = cpl_frameset_new();
593 cpl_image * base = NULL;
594 cpl_propertylist * plist = NULL;
595 visir_spc_resol resol;
596 visir_data_type data_type;
597 double wlen;
598
599 /* Identify the RAW and CALIB frames in the input frameset */
600 skip_if (visir_dfs_set_groups(framelist));
601
602 error_if(xl < 1 || yl < 1, CPL_ERROR_ILLEGAL_INPUT,
603 "Sky region %d/%d must be larger than 1", (int)xl, (int)yl);
604
605 /* Objects observation */
606 allframes = irplib_framelist_cast(framelist);
607 skip_if(allframes == NULL);
608
609 rawframes = irplib_framelist_extract_regexp(allframes, "^("
610 VISIR_UTIL_REPACK_A_ON_PROCATG "|"
611 VISIR_UTIL_REPACK_A_OFF_PROCATG "|"
612 VISIR_UTIL_REPACK_B_ON_PROCATG "|"
613 VISIR_UTIL_REPACK_B_OFF_PROCATG
614 ")$", CPL_FALSE);
615 skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, ".*", 0));
616 plist = irplib_framelist_get_propertylist(rawframes, 0);
617 skip_if(check_rawframes(rawframes, plist));
618
619 {
620 double pslitw, ptemp, pfwhm;
621 const cpl_frame * frm = irplib_framelist_get_const(rawframes, 0);
622 skip_if(visir_get_data_type(frm, plist, &data_type, NULL));
623 resol = visir_spc_get_res_wl(rawframes, &wlen, &pslitw, &ptemp, &pfwhm,
624 visir_data_is_aqu(data_type));
625 skip_if(0);
626 }
627
628 if (visir_data_is_drs(data_type)) {
629 /* if parameters are (aqu) defaults and drs data use old parameters */
630 const cpl_parameter * par =
631 cpl_parameterlist_find_const(parlist, PACKAGE "." RECIPE_STRING ".ksi");
632 if (ksi == cpl_parameter_get_default_double(par) * CPL_MATH_RAD_DEG) {
633 ksi = VISIR_DRS_DIST_KSI;
634 }
635 par = cpl_parameterlist_find_const(parlist, PACKAGE "." RECIPE_STRING ".eps");
636 if (eps == cpl_parameter_get_default_double(par)) {
637 eps = VISIR_DRS_DIST_EPS;
638 }
639 par = cpl_parameterlist_find_const(parlist, PACKAGE "." RECIPE_STRING ".delta");
640 if (delta == cpl_parameter_get_default_double(par)) {
641 delta = VISIR_DRS_DIST_DELTA;
642 }
643 par = cpl_parameterlist_find_const(parlist, PACKAGE "." RECIPE_STRING ".phi");
644 if (phi == cpl_parameter_get_default_double(par) * CPL_MATH_RAD_DEG) {
645 phi = VISIR_DRS_DIST_PHI;
646 }
647 }
648
649 rawframes_a = irplib_framelist_extract_regexp(allframes, "^("
650 VISIR_UTIL_REPACK_A_ON_PROCATG "|"
651 VISIR_UTIL_REPACK_A_OFF_PROCATG
652 ")$", CPL_FALSE);
653 cpl_errorstate_set(cleanstate);
654
655 rawframes_b = irplib_framelist_extract_regexp(allframes, "^("
656 VISIR_UTIL_REPACK_B_ON_PROCATG "|"
657 VISIR_UTIL_REPACK_B_OFF_PROCATG
658 ")$", CPL_FALSE);
659 cpl_errorstate_set(cleanstate);
660
661 error_if (rawframes_a == NULL && rawframes_b == NULL,
662 CPL_ERROR_DATA_NOT_FOUND, "No frames with tags "
663 VISIR_UTIL_REPACK_A_ON_PROCATG "|"
664 VISIR_UTIL_REPACK_A_OFF_PROCATG "|"
665 VISIR_UTIL_REPACK_B_ON_PROCATG "|"
666 VISIR_UTIL_REPACK_B_OFF_PROCATG " found");
667
668 if (bpmframe != NULL) {
669 /* Load any static mask here to avoid that the file is loaded
670 multiple times */
671 const char * badpix = cpl_frame_get_filename(bpmframe);
672
673
674 bpm = cpl_mask_load(badpix, 0, 0);
675 skip_if (bpm == NULL);
676 }
677
678 double t_min_obsstart = 1e300;
679 double t_max_filewrite = 0;
680 if (rawframes_a) {
681 cx_list * on_frames = sort_framelist(rawframes_a, "^("
682 VISIR_UTIL_REPACK_A_ON_PROCATG
683 ")$");
684 cx_list * off_frames = sort_framelist(rawframes_a, "^("
685 VISIR_UTIL_REPACK_A_OFF_PROCATG
686 ")$");
687 FOR_EACH_T(cpl_frame * frm, on_frames) {
688 update_exectime(frm, &t_min_obsstart, &t_max_filewrite);
689 vimglist_append(aon, load_images(frm, bpm, NULL));
690 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
691 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
692 }
693 cx_list_destroy(on_frames, (visir_free)cpl_frame_delete);
694 FOR_EACH_T(cpl_frame * frm, off_frames) {
695 update_exectime(frm, &t_min_obsstart, &t_max_filewrite);
696 vimglist_append(aoff, load_images(frm, bpm, NULL));
697 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
698 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
699 }
700 cx_list_destroy(off_frames, (visir_free)cpl_frame_delete);
701
702 base = cpl_image_duplicate(visir_imglist_get_img(aoff, 0));
703 if (visir_data_is_aqu(data_type))
704 overscan_correct(base);
705 skip_if(handle_images(aon, base, xl, yl, xh, yh,
706 phi, ksi, eps, delta, data_type));
707 skip_if(handle_images(aoff, base, xl, yl, xh, yh,
708 phi, ksi, eps, delta, data_type));
709 }
710 if (rawframes_b){
711 cx_list * on_frames = sort_framelist(rawframes_b, "^("
712 VISIR_UTIL_REPACK_B_ON_PROCATG
713 ")$");
714 cx_list * off_frames = sort_framelist(rawframes_b, "^("
715 VISIR_UTIL_REPACK_B_OFF_PROCATG
716 ")$");
717 FOR_EACH_T(cpl_frame * frm, on_frames) {
718 update_exectime(frm, &t_min_obsstart, &t_max_filewrite);
719 vimglist_append(bon, load_images(frm, bpm, NULL));
720 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
721 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
722 }
723 cx_list_destroy(on_frames, (visir_free)cpl_frame_delete);
724 FOR_EACH_T(cpl_frame * frm, off_frames) {
725 update_exectime(frm, &t_min_obsstart, &t_max_filewrite);
726 vimglist_append(boff, load_images(frm, bpm, NULL));
727 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
728 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
729 }
730 cx_list_destroy(off_frames, (visir_free)cpl_frame_delete);
731
732 if (base == NULL) {
733 base = cpl_image_duplicate(visir_imglist_get_img(boff, 0));
734 if (visir_data_is_aqu(data_type))
735 overscan_correct(base);
736 }
737
738 skip_if(handle_images(bon, base, xl, yl, xh, yh,
739 phi, ksi, eps, delta, data_type));
740 skip_if(handle_images(boff, base, xl, yl, xh, yh,
741 phi, ksi, eps, delta, data_type));
742 }
743
744 if (bkgcorrect && rawframes_a && rawframes_b) {
745 cpl_imagelist * laon = visir_imglist_get_imglist(aon);
746 cpl_imagelist * laoff = visir_imglist_get_imglist(aoff);
747 cpl_imagelist_subtract(laon, laoff);
748
749 cpl_imagelist * lbon = visir_imglist_get_imglist(bon);
750 cpl_imagelist * lboff = visir_imglist_get_imglist(boff);
751 cpl_imagelist_subtract(lbon, lboff);
752
753 cpl_imagelist_subtract(laon, lbon);
754
755 visir_imglist * l = visir_imglist_new(100, NULL);
756
757 {
758 cpl_image * img = cpl_imagelist_collapse_create(laon);
759 cpl_image * flipped = visir_spc_flip(img, wlen, resol, data_type,
760 NULL);
761 cpl_image_delete(img);
762 img = flipped;
763
764 visir_imglist_append(l, img, NULL);
765 }
766
767 cpl_propertylist_append_double(plist, "ESO QC EXECTIME",
768 (t_max_filewrite - t_min_obsstart) * 24 * 3600);
769 save_images(l, framelist, usedframes, plist, parlist);
770 vimglist_delete(l);
771 skip_if(0);
772 }
773 else {
774 bug_if(bkgcorrect); /* FIXME */
775 save_images(aon, framelist, usedframes, plist, parlist);
776 save_images(aoff, framelist, usedframes, plist, parlist);
777 save_images(bon, framelist, usedframes, plist, parlist);
778 save_images(boff, framelist, usedframes, plist, parlist);
779 }
780
781 {
782 cpl_frame * frm = cpl_frameset_find(framelist, VISIR_CALIB_LIN);
783 if (visir_data_is_aqu(data_type) && frm) {
784 cpl_msg_info(cpl_func, "Correcting linearity of skyframe");
785 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
786 cpl_bivector * lintable = visir_load_lintable(frm, CPL_TRUE);
787 if (lintable) {
788 cpl_image * dvals = cpl_image_cast(base, CPL_TYPE_DOUBLE);
789 /* ugly, revert normalization done by repack */
790 cpl_image_multiply_scalar(dvals, visir_pfits_get_dit(plist));
791 cpl_image * corvals = visir_linintp_values(dvals, lintable);
792 cpl_image_divide(base, corvals);
793 cpl_bivector_delete(lintable);
794 cpl_image_delete(dvals);
795 cpl_image_delete(corvals);
796 }
797 }
798
799 skip_if(visir_spc_det_warp(&base, 1, 0., 0., phi, ksi, eps, delta));
800 cpl_image * flipped = visir_spc_flip(base, wlen, resol, data_type,
801 NULL);
802 cpl_image_delete(base);
803 base = flipped;
804 }
805 skip_if(irplib_dfs_save_image(framelist, parlist, usedframes,
806 base, CPL_TYPE_UNSPECIFIED,
807 RECIPE_STRING,
808 "SPEC_OBS_LMR_SKYFRAME", NULL, NULL,
809 visir_pipe_id, "skyframe.fits"));
810
811 end_skip;
812
813 irplib_framelist_delete(allframes);
814 irplib_framelist_delete(rawframes);
815 irplib_framelist_delete(rawframes_a);
816 irplib_framelist_delete(rawframes_b);
817 cpl_image_delete(imbpm);
818 cpl_mask_delete(bpm);
819 cpl_image_delete(base);
820 vimglist_delete(aon);
821 vimglist_delete(aoff);
822 vimglist_delete(bon);
823 vimglist_delete(boff);
824 cpl_frameset_delete(usedframes);
825
826 return cpl_error_get_code();
827}
int visir_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: visir_dfs.c:72
cpl_bivector * visir_load_lintable(cpl_frame *linframe, cpl_boolean is_spec)
load and normalize linearity table into a bivector
Definition: visir_inputs.c:549
cpl_error_code visir_parameter_set(cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Define the specified parameters.
double visir_parameterlist_get_double(const cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Retrieve the value of a VISIR parameter of type double.
double visir_pfits_get_dit(const cpl_propertylist *self)
The DIT.
Definition: visir_pfits.c:325