IIINSTRUMENT Pipeline Reference Manual 6.2.5
isaac_img_jitter.c
1/* $Id: isaac_img_jitter.c,v 1.75 2013-03-12 08:06:48 llundin Exp $
2 *
3 * This file is part of the ISAAC 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: llundin $
23 * $Date: 2013-03-12 08:06:48 $
24 * $Revision: 1.75 $
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 <string.h>
37#include <math.h>
38#include <cpl.h>
39
40#include "irplib_plugin.h"
41#include "irplib_utils.h"
42#include "irplib_calib.h"
43
44#include "isaac_utils.h"
45#include "isaac_pfits.h"
46#include "isaac_dfs.h"
47
48/*-----------------------------------------------------------------------------
49 Define
50 -----------------------------------------------------------------------------*/
51
52#define RECIPE_STRING "isaac_img_jitter"
53
54#ifndef NEGLIG_OFF_DIFF
55#define NEGLIG_OFF_DIFF 0.1
56#endif
57
58#define SQR(x) ((x)*(x))
59
60#ifdef ISAAC_IMG_ERR_ESTIMATE
61#ifndef ISAAC_IMG_GAIN
62/* FIXME: Empirically determined. Use header info (arm dependent) */
63#define ISAAC_IMG_GAIN 4.5
64#endif
65
66#ifndef ISAAC_IMG_SATURATION_LEVEL
67/* FIXME: Empirically determined */
68#define ISAAC_IMG_SATURATION_LEVEL 40000.0
69#endif
70#endif
71
72
73/*-----------------------------------------------------------------------------
74 Private Function prototypes
75 -----------------------------------------------------------------------------*/
76
77static cpl_image ** isaac_img_jitter_reduce(cpl_frameset *,
78 const cpl_parameterlist *,
79 const cpl_frameset *,
80 const cpl_frameset *,
81 const char *, const char *,
82 const char *, cpl_vector **);
83static cpl_imagelist ** isaac_img_jitter_load(const cpl_frameset *,
84 const cpl_frameset *);
85static cpl_vector * isaac_img_jitter_sky(cpl_imagelist **, cpl_imagelist *);
86static cpl_vector * isaac_img_jitter_sky_running(cpl_imagelist **);
87static cpl_image ** isaac_img_jitter_saa_nochop(cpl_imagelist *,
88 const cpl_frameset *);
89static cpl_image ** isaac_img_jitter_saa_chop(cpl_imagelist *,
90 const cpl_frameset *);
91static int isaac_img_jitter_chopping_classif(cpl_bivector *, int **, int **);
92static cpl_error_code isaac_img_jitter_sub_row_median(cpl_image *);
93static cpl_table * isaac_img_jitter_qc(cpl_image *);
94static double isaac_img_jitter_get_mode(cpl_vector *);
95static cpl_error_code isaac_img_jitter_save(cpl_frameset *, const cpl_image *,
96 const cpl_image *,
97 const cpl_table *,
98 const cpl_vector *,
99 const cpl_parameterlist *);
100
101cpl_recipe_define(isaac_img_jitter, ISAAC_BINARY_VERSION,
102 "Lars Lundin", PACKAGE_BUGREPORT, "2008",
103 "ISAAC imaging jitter recipe",
104 RECIPE_STRING " -- ISAAC imaging jitter recipe.\n"
105 "The files listed in the Set Of Frames (sof-file) "
106 "must be tagged:\n"
107 "raw-file.fits " ISAAC_IMG_JITTER_OBJ_RAW " or\n"
108 "raw-file.fits " ISAAC_IMG_JITTER_SKY_RAW " or\n"
109 "raw-file.fits " ISAAC_IMG_JITTER_CHOP_RAW " or\n"
110 "flat-file.fits " ISAAC_CALIB_FLAT " or\n"
111 "bpm-file.fits " ISAAC_CALIB_BPM " or\n"
112 "dark-file.fits " ISAAC_CALIB_DARK "\n");
113
114/*-----------------------------------------------------------------------------
115 Static variables
116 -----------------------------------------------------------------------------*/
117
118static struct {
119 /* Inputs */
120 const char * offsets;
121 const char * objects;
122 int oddeven;
123 int sky_minnb;
124 int sky_halfw;
125 int sky_rejmin;
126 int sky_rejmax;
127 int sx;
128 int sy;
129 int mx;
130 int my;
131 cpl_geom_combine comb_meth;
132 int saa_refine;
133 int rej_low;
134 int rej_high;
135 int row_med;
136 int chopping;
137 /* Outputs */
138 double pixscale;
139 double dit;
140 int nb_obj_frames;
141 int nb_sky_frames;
142 int nb_rej_frames;
143 double iq;
144 int nbobjs;
145 double fwhm_pix;
146 double fwhm_arcsec;
147 double fwhm_mode;
148 double angle_med;
149 double ellip_med;
150} isaac_img_jitter_config;
151
152/*-----------------------------------------------------------------------------
153 Functions code
154 -----------------------------------------------------------------------------*/
155
156/*----------------------------------------------------------------------------*/
164/*----------------------------------------------------------------------------*/
165static
166cpl_error_code isaac_img_jitter_fill_parameterlist(cpl_parameterlist * self)
167{
168 const char * context = PACKAGE "." RECIPE_STRING;
169 cpl_error_code err;
170
171 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
172
173 /* Fill the parameters list */
174
175 /* --off */
176 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
177 "offsets", NULL, "off", context,
178 "An optional ASCII specification of the offsets "
179 "in case those in FITS-headers are missing or wrong. "
180 "The file must consist of one line per object FITS-"
181 "file and each line must consist of two "
182 "numbers which represent the shift in pixels of that "
183 "image relative to the first image. The first line "
184 "should thus comprise two zeros. Correct FITS-header "
185 "offsets mean that the i'th X offset can be gotten "
186 "from Xoffset_0 - Xoffset_i, where Xoffset_i is the "
187 "value of ESO SEQ CUMOFFSETX and likewise for Y.");
188 cpl_ensure_code(!err, err);
189
190 /* --objs */
191 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
192 "objects", NULL, "objs", context,
193 "objects file");
194 cpl_ensure_code(!err, err);
195
196 /* --oddeven */
197 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "oddeven",
198 CPL_FALSE, NULL, context, "Flag to "
199 "correct the oddeven column effect");
200 cpl_ensure_code(!err, err);
201
202 /* --sky_par */
203 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
204 "sky_par", "10,7,3,3", NULL, context,
205 "Rejection parameters for sky "
206 "filtering");
207 cpl_ensure_code(!err, err);
208
209 /* --xcorr */
210 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING, "xcorr",
211 "40,40,65,65", NULL, context, "Cross "
212 "correlation search and measure "
213 "sizes");
214 cpl_ensure_code(!err, err);
215
216 /* --comb_meth */
217 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
218 "comb_meth", "union", NULL, context,
219 "union / inter / first");
220 cpl_ensure_code(!err, err);
221
222 /* --saa_refine */
223 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
224 "saa_refine", CPL_TRUE, NULL, context,
225 "Flag to refine the offsets");
226 cpl_ensure_code(!err, err);
227
228 /* --rej */
229 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING, "rej",
230 "2,2", NULL, context, "Low and high "
231 "number of rejected values");
232 cpl_ensure_code(!err, err);
233
234 /* --row_med */
235 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
236 "row_med", CPL_TRUE, NULL, context,
237 "Flag to subtract the median of each "
238 "row");
239 cpl_ensure_code(!err, err);
240
241 return CPL_ERROR_NONE;
242}
243
244
245
246/*----------------------------------------------------------------------------*/
254/*----------------------------------------------------------------------------*/
255static int isaac_img_jitter(cpl_frameset * framelist,
256 const cpl_parameterlist * parlist)
257{
258 const char * sval;
259 const char * badpix;
260 const char * flat;
261 const char * dark;
262 cpl_frameset * objframes = NULL;
263 cpl_frameset * skyframes = NULL;
264 cpl_image ** combined = NULL;
265 cpl_table * objs_stats = NULL;
266 cpl_vector * sky_bg = NULL;
267
268 bug_if(0);
269
270 /* Initialise */
271 isaac_img_jitter_config.pixscale = -1.0;
272 isaac_img_jitter_config.dit = -1.0;
273 isaac_img_jitter_config.iq = -1.0;
274 isaac_img_jitter_config.nbobjs = -1;
275 isaac_img_jitter_config.fwhm_pix = -1.0;
276 isaac_img_jitter_config.fwhm_arcsec = -1.0;
277 isaac_img_jitter_config.fwhm_mode = -1.0;
278 isaac_img_jitter_config.offsets = NULL;
279 isaac_img_jitter_config.objects = NULL;
280 isaac_img_jitter_config.nb_obj_frames = 0;
281 isaac_img_jitter_config.nb_rej_frames = 0;
282 isaac_img_jitter_config.nb_sky_frames = 0;
283
284 /* Retrieve input parameters */
285 /* Offsets */
286 isaac_img_jitter_config.offsets
287 = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
288 "offsets");
289
290 /* Objects */
291 isaac_img_jitter_config.objects
292 = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
293 "objects");
294
295 /* Oddeven */
296 isaac_img_jitter_config.oddeven
297 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
298 "oddeven");
299
300 /* Rejection parameters for sky filtering */
301 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
302 "sky_par");
303
304 bug_if(sval == NULL);
305
306 skip_if (sscanf(sval, "%d,%d,%d,%d",
307 &isaac_img_jitter_config.sky_minnb,
308 &isaac_img_jitter_config.sky_halfw,
309 &isaac_img_jitter_config.sky_rejmin,
310 &isaac_img_jitter_config.sky_rejmax) != 4);
311
312 /* Cross correlation windows parameters */
313 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
314 "xcorr");
315 bug_if(sval == NULL);
316
317 skip_if (sscanf(sval, "%d,%d,%d,%d",
318 &isaac_img_jitter_config.sx,
319 &isaac_img_jitter_config.sy,
320 &isaac_img_jitter_config.mx,
321 &isaac_img_jitter_config.my) != 4);
322
323 /* --comb_meth */
324 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
325 "comb_meth");
326 bug_if(sval == NULL);
327 if (!strcmp(sval, "union"))
328 isaac_img_jitter_config.comb_meth = CPL_GEOM_UNION;
329 else if (!strcmp(sval, "inter"))
330 isaac_img_jitter_config.comb_meth = CPL_GEOM_INTERSECT;
331 else if (!strcmp(sval, "first"))
332 isaac_img_jitter_config.comb_meth = CPL_GEOM_FIRST;
333 else {
334 cpl_msg_error(cpl_func, "Invalid combine method specified");
335 skip_if(1);
336 }
337
338 /* Refine of offsets */
339 isaac_img_jitter_config.saa_refine
340 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
341 "saa_refine");
342
343 /* Number of rejected values in stacking */
344 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
345 "rej");
346 bug_if(sval == NULL);
347 skip_if (sscanf(sval, "%d,%d",
348 &isaac_img_jitter_config.rej_low,
349 &isaac_img_jitter_config.rej_high) != 2);
350
351 /* Row median */
352 isaac_img_jitter_config.row_med
353 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
354 "row_med");
355
356 /* Identify the RAW and CALIB frames in the input frameset */
357 skip_if (isaac_dfs_set_groups(framelist));
358
359 /* Retrieve calibration data */
360 flat = isaac_extract_filename(framelist, ISAAC_CALIB_FLAT);
361 dark = isaac_extract_filename(framelist, ISAAC_CALIB_DARK);
362 badpix = isaac_extract_filename(framelist, ISAAC_CALIB_BPM);
363
364 /* Retrieve raw frames */
365 if ((objframes = isaac_extract_frameset(framelist,
366 ISAAC_IMG_JITTER_OBJ_RAW)) != NULL) {
367 isaac_img_jitter_config.chopping = 0;
368 } else if ((objframes = isaac_extract_frameset(framelist,
369 ISAAC_IMG_JITTER_CHOP_RAW)) != NULL) {
370 isaac_img_jitter_config.chopping = 1;
371 } else {
372 cpl_msg_error(cpl_func, "Cannot find objs frames in the input list");
373 skip_if(1);
374 }
375 skyframes = isaac_extract_frameset(framelist, ISAAC_IMG_JITTER_SKY_RAW);
376
377 /* Apply the reduction */
378 cpl_msg_info(cpl_func, "Apply the data recombination");
379 cpl_msg_indent_more();
380 if ((combined = isaac_img_jitter_reduce(framelist, parlist, objframes,
381 skyframes, flat,
382 dark, badpix, &sky_bg)) == NULL) {
383 cpl_msg_error(cpl_func, "Cannot recombine the data");
384 cpl_msg_indent_less();
385 skip_if(1);
386 }
387 cpl_msg_indent_less();
388
389 /* Compute QC parameters from the combined image */
390 cpl_msg_info(cpl_func, "Compute QC parameters from the combined image");
391 cpl_msg_indent_more();
392 if ((objs_stats = isaac_img_jitter_qc(combined[0])) == NULL) {
393 cpl_msg_warning(cpl_func, "Cannot compute all parameters");
394 }
395 cpl_msg_indent_less();
396
397 /* Save the products */
398 cpl_msg_info(cpl_func, "Save the products");
399 skip_if (isaac_img_jitter_save(framelist, combined[0], combined[1],
400 objs_stats, sky_bg, parlist));
401
402 end_skip;
403
404 cpl_frameset_delete(objframes);
405 cpl_frameset_delete(skyframes);
406 if (combined != NULL) {
407 cpl_image_delete(combined[0]);
408 cpl_image_delete(combined[1]);
409 cpl_free(combined);
410 }
411 cpl_table_delete(objs_stats);
412 cpl_vector_delete(sky_bg);
413
414 return cpl_error_get_code();
415}
416
417/*----------------------------------------------------------------------------*/
428/*----------------------------------------------------------------------------*/
429static
430cpl_image ** isaac_img_jitter_reduce(cpl_frameset * frameset,
431 const cpl_parameterlist * parlist,
432 const cpl_frameset * obj,
433 const cpl_frameset * sky,
434 const char * flat,
435 const char * dark,
436 const char * bpm,
437 cpl_vector ** skybg)
438{
439#ifdef ISAAC_IMG_ERR_ESTIMATE
440 cpl_propertylist * qclist;
441 cpl_imagelist * err;
442#endif
443 cpl_imagelist ** in;
444 cpl_image ** combined;
445 cpl_imagelist * corrected;
446 cpl_image * cur_im;
447 int i;
448
449 cpl_ensure(frameset != NULL, CPL_ERROR_NULL_INPUT, NULL);
450 cpl_ensure(parlist != NULL, CPL_ERROR_NULL_INPUT, NULL);
451
452 /* Initialise */
453 *skybg = NULL;
454 combined = NULL;
455
456 /* Load the input data */
457 cpl_msg_info(cpl_func, "Load the input data");
458 cpl_msg_indent_more();
459 if ((in = isaac_img_jitter_load(obj, sky)) == NULL) {
460 cpl_msg_error(cpl_func, "Cannot load input data");
461 cpl_msg_indent_less();
462 return NULL;
463 }
464 cpl_msg_indent_less();
465
466 /* Apply the odd-even correction */
467 if (isaac_img_jitter_config.oddeven) {
468 cpl_msg_info(cpl_func, "Apply the odd-even effect correction");
469 cpl_msg_indent_more();
470 corrected = cpl_imagelist_new();
471 for (i=0; i<cpl_imagelist_get_size(in[0]); i++) {
472 cpl_msg_info(cpl_func, "Correct object frame nb %d", i+1);
473 if ((cur_im = isaac_oddeven_correct(
474 cpl_imagelist_get(in[0], i))) == NULL) {
475 cpl_msg_warning(cpl_func,"Problem in odd-even corr. %d",i+1);
476 cpl_imagelist_delete(corrected);
477 corrected = NULL;
478 break;
479 }
480 cpl_imagelist_set(corrected, cur_im, i);
481 }
482 /* Odd/even correction successfull */
483 if (corrected != NULL) {
484 cpl_imagelist_delete(in[0]);
485 in[0] = corrected;
486 }
487 cpl_msg_indent_less();
488 }
489
490#ifdef ISAAC_IMG_ERR_ESTIMATE
491 /*----------------------------------------------------------------------------*/
492 /* Save the imagelist before applying the correction */
493
494 err = cpl_imagelist_duplicate(in[0]);
495
496 /* Dark correction */
497 if (dark != NULL) {
498 cpl_image * dark_image;
499
500 cpl_msg_info(cpl_func, "Error propagation: Subtract the dark to the images");
501 /* Load the dark image */
502 if ((dark_image = cpl_image_load(dark, CPL_TYPE_FLOAT, 0, 0)) == NULL) {
503 cpl_msg_error(cpl_func, "Cannot load the dark %s", dark);
504 return NULL;
505 }
506 /* Apply the dark correction to the images */
507 if (cpl_imagelist_subtract_image(err, dark_image)!=CPL_ERROR_NONE) {
508 cpl_msg_error(cpl_func, "Cannot apply the dark to the images");
509 cpl_image_delete(dark_image);
510 return NULL;
511 }
512 cpl_image_delete(dark_image);
513 }
514
515
516 /* Apply the bad pixel mask requested */
517 if (bpm != NULL) {
518 cpl_image * bpm_im;
519 cpl_msg_info(cpl_func, "Error propagation: Correct the bad pixels in the images");
520 /* Load the bad pixels image - as double */
521 if ((bpm_im = cpl_image_load(bpm, CPL_TYPE_DOUBLE, 0, 0)) == NULL) {
522 cpl_msg_error(cpl_func, "Cannot load the bad pixel map %s", bpm);
523 return NULL;
524 }
525 /* Invert the map */
526 cpl_image_threshold(bpm_im, 0.4, 0.6, 1, 0);
527
528 cpl_imagelist_multiply_image(err, bpm_im);
529
530 /* cpl_image_save(bpm_im,"test.fits",CPL_BPP_IEEE_FLOAT,NULL,CPL_IO_CREATE);*/
531 cpl_image_delete(bpm_im);
532 }
533
534 cpl_imagelist_threshold(err, 1, ISAAC_IMG_SATURATION_LEVEL,
535 FLT_MAX, FLT_MAX);
536 cpl_imagelist_divide_scalar(err, ISAAC_IMG_GAIN);
537 cpl_imagelist_power(err, 0.5);
538
539 /* Flat-field correction */
540 if (flat != NULL) {
541 cpl_image * flat_image;
542 cpl_msg_info(cpl_func, "Error propagation: Divide the images by the flatfield");
543 /* Load the flat image */
544 if ((flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0)) == NULL) {
545 cpl_msg_error(cpl_func, "Cannot load the flat field %s", flat);
546 return NULL;
547 }
548 /* Apply the flatfield correction to the images */
549 if (cpl_imagelist_divide_image(err, flat_image)!=CPL_ERROR_NONE) {
550 cpl_msg_error(cpl_func, "Cannot apply the flatfield to the images");
551 cpl_image_delete(flat_image);
552 return NULL;
553 }
554 cpl_image_delete(flat_image);
555 }
556 cpl_imagelist_threshold(err, 1, ISAAC_IMG_SATURATION_LEVEL,
557 FLT_MAX, FLT_MAX);
558
559 /*----------------------------------------------------------------------------*/
560#endif
561
562 /* Apply the calibrations */
563 if (flat || dark || bpm) {
564 cpl_msg_info(cpl_func, "Apply the calibrations");
565 cpl_msg_indent_more();
566 if (irplib_flat_dark_bpm_calib(in[0], flat, dark, bpm) == -1) {
567 /* Calibrate the objects */
568 cpl_msg_error(cpl_func, "Cannot calibrate the objects");
569 cpl_imagelist_delete(in[0]);
570 if (in[1]) cpl_imagelist_delete(in[1]);
571 cpl_free(in);
572 cpl_msg_indent_less();
573 return NULL;
574 }
575 if (in[1]) {
576 if (irplib_flat_dark_bpm_calib(in[1], flat, dark, bpm) == -1) {
577 /* Calibrate the sky */
578 cpl_msg_error(cpl_func, "Cannot calibrate the sky");
579 cpl_imagelist_delete(in[0]);
580 if (in[1]) cpl_imagelist_delete(in[1]);
581 cpl_free(in);
582 cpl_msg_indent_less();
583 return NULL;
584 }
585 }
586 cpl_msg_indent_less();
587 }
588
589
590#ifdef ISAAC_IMG_ERR_ESTIMATE
591 /* Save the imagelist as intermediate product */
592
593 qclist = cpl_propertylist_new();
594
595 cpl_propertylist_update_string(qclist, CPL_DFS_PRO_CATG, "ISAAC_IMAGELIST");
596 if(cpl_dfs_save_imagelist(frameset,
597 NULL,
598 parlist,
599 frameset,
600 NULL,
601 in[0],
602 CPL_BPP_IEEE_FLOAT,
603 RECIPE_STRING,
604 qclist,
605 NULL,
606 PACKAGE "/" PACKAGE_VERSION,
607 "isaac_img_imagelist.fits")) {
608 /* Propagate the error */
609 (void)cpl_error_set_where(cpl_func);
610 }
611
612 cpl_propertylist_update_string(qclist, CPL_DFS_PRO_CATG, "ISAAC_IMAGELISTERR");
613 if(cpl_dfs_save_imagelist(frameset,
614 NULL,
615 parlist,
616 frameset,
617 NULL,
618 err,
619 CPL_BPP_IEEE_FLOAT,
620 RECIPE_STRING,
621 qclist,
622 NULL,
623 PACKAGE "/" PACKAGE_VERSION,
624 "isaac_img_imagelist_error.fits")) {
625 /* Propagate the error */
626 (void)cpl_error_set_where(cpl_func);
627 }
628
629 cpl_propertylist_delete(qclist);
630 cpl_imagelist_delete(err);
631#endif
632
633 /* Apply the sky correction only in jitter mode */
634 if (isaac_img_jitter_config.chopping == 0) {
635 cpl_msg_info(cpl_func, "Sky estimation and correction");
636 cpl_msg_indent_more();
637 if ((*skybg = isaac_img_jitter_sky(&(in[0]), in[1])) == NULL) {
638 cpl_msg_error(cpl_func, "Cannot estimate the sky");
639 cpl_imagelist_delete(in[0]);
640 if (in[1]) cpl_imagelist_delete(in[1]);
641 cpl_free(in);
642 cpl_msg_indent_less();
643 return NULL;
644 }
645 cpl_msg_indent_less();
646 }
647 isaac_img_jitter_config.nb_obj_frames = cpl_imagelist_get_size(in[0]);
648 if (in[1] != NULL)
649 isaac_img_jitter_config.nb_sky_frames = cpl_imagelist_get_size(in[1]);
650 if (in[1]) cpl_imagelist_delete(in[1]);
651 in[1] = NULL;
652
653 /* Apply the shift and add */
654 cpl_msg_info(cpl_func, "Shift and add");
655 cpl_msg_indent_more();
656 if (isaac_img_jitter_config.chopping == 0) {
657 combined = isaac_img_jitter_saa_nochop(in[0], obj);
658 } else if (isaac_img_jitter_config.chopping == 1) {
659 combined = isaac_img_jitter_saa_chop(in[0], obj);
660 }
661 if (combined == NULL) {
662 cpl_msg_error(cpl_func, "Cannot apply the shift and add");
663 cpl_imagelist_delete(in[0]);
664 cpl_free(in);
665 if (*skybg != NULL) cpl_vector_delete(*skybg);
666 *skybg = NULL;
667 cpl_msg_indent_less();
668 return NULL;
669 }
670 cpl_imagelist_delete(in[0]);
671 cpl_free(in);
672 cpl_msg_indent_less();
673
674 /* Post processing on the combined image */
675 if (isaac_img_jitter_config.row_med) {
676 cpl_msg_info(cpl_func, "Subtract the median from each row");
677 skip_if(isaac_img_jitter_sub_row_median(combined[0]));
678 }
679
680 end_skip;
681
682 return combined;
683}
684
685/*----------------------------------------------------------------------------*/
692/*----------------------------------------------------------------------------*/
693static cpl_imagelist ** isaac_img_jitter_load(
694 const cpl_frameset * obj,
695 const cpl_frameset * sky)
696{
697 cpl_imagelist ** isets;
698 cpl_imagelist * chop_b;
699 const cpl_frame * frame;
700 cpl_propertylist * plist;
701 const char * sval;
702
703 /* Test entries */
704 if (obj == NULL) return NULL;
705
706 /* Check if ok */
707 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
708
709 /* Get the frame type pixscale and DIT value */
710 frame = cpl_frameset_get_position_const(obj, 0);
711 cpl_ensure(frame != NULL, cpl_error_get_code(), NULL);
712
713 plist=cpl_propertylist_load(cpl_frame_get_filename(frame), 0);
714 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
715
716 isaac_img_jitter_config.pixscale = isaac_pfits_get_pixscale(plist);
717 isaac_img_jitter_config.dit = isaac_pfits_get_dit(plist);
718 sval = isaac_pfits_get_frame_type(plist);
719 if (sval == NULL) {
720 cpl_msg_error(cpl_func, "Could not get frame type for jitter");
721 cpl_propertylist_delete(plist);
722 return NULL;
723 } else if ((isaac_img_jitter_config.chopping==0) && strcmp(sval, "INT")) {
724 cpl_msg_error(cpl_func, "Wrong type for jitter: %s - Should be INT",
725 sval);
726 cpl_propertylist_delete(plist);
727 return NULL;
728 } else if ((isaac_img_jitter_config.chopping==1) && strcmp(sval, "CUBE1")) {
729 cpl_msg_error(cpl_func, "Wrong type for chopping: %s - Should be CUBE1",
730 sval);
731 cpl_propertylist_delete(plist);
732 return NULL;
733 }
734 cpl_propertylist_delete(plist);
735 if (cpl_error_get_code()) {
736 cpl_msg_error(cpl_func, "Missing keyword in FITS header");
737 return NULL;
738 }
739
740 /* Allocate the image sets */
741 isets = cpl_malloc(2 * sizeof(cpl_imagelist *));
742
743 /* Check if chop or nochop */
744 if (isaac_img_jitter_config.chopping == 0) {
745 isets[0] = cpl_imagelist_load_frameset(obj, CPL_TYPE_FLOAT, 1, 0);
746 if (sky != NULL)
747 isets[1] = cpl_imagelist_load_frameset(sky, CPL_TYPE_FLOAT, 1, 0);
748 else isets[1] = NULL;
749 } else if (isaac_img_jitter_config.chopping == 1) {
750 isets[1] = NULL;
751 isets[0] = cpl_imagelist_load_frameset(obj, CPL_TYPE_FLOAT, 1, 0);
752 chop_b = cpl_imagelist_load_frameset(obj, CPL_TYPE_FLOAT, 2, 0);
753 cpl_imagelist_subtract(isets[0], chop_b);
754 cpl_imagelist_delete(chop_b);
755 }
756
757 /* Check if at least the objects are there */
758 if (isets[0] == NULL) {
759 cpl_msg_error(cpl_func, "The objects frames could not be loaded");
760 if (isets[1] != NULL) cpl_imagelist_delete(isets[1]);
761 cpl_free(isets);
762 return NULL;
763 }
764 /* Return */
765 return isets;
766}
767
768/*----------------------------------------------------------------------------*/
775/*----------------------------------------------------------------------------*/
776static cpl_vector * isaac_img_jitter_sky(
777 cpl_imagelist ** objs,
778 cpl_imagelist * skys)
779{
780 cpl_image * sky;
781 cpl_vector * bg;
782 int sky_method;
783 int nframes, nskys;
784 double median;
785 cpl_image * cur_ima;
786 int i;
787
788 /* Initialise */
789 bg = NULL;
790 nframes = cpl_imagelist_get_size(*objs);
791
792 /* Decide the sky method */
793 if (isaac_img_jitter_config.sky_minnb > nframes) sky_method = 1;
794 else sky_method = 2;
795
796 /* Compute the sky frame */
797 if (skys != NULL) {
798 cpl_msg_info(cpl_func, "Median of sky images");
799 /* Get the median of the sky images */
800 nskys = cpl_imagelist_get_size(skys);
801 bg = cpl_vector_new(nskys);
802 for (i=0; i<nskys; i++) {
803 median = cpl_image_get_median(cpl_imagelist_get(skys, i));
804 cpl_vector_set(bg, i, median);
805 }
806 /* Use sky images */
807 if ((sky = cpl_imagelist_collapse_median_create(skys)) == NULL) {
808 cpl_msg_error(cpl_func, "Cannot compute the median of sky images");
809 cpl_vector_delete(bg);
810 return NULL;
811 }
812 /* Correct the objects images */
813 if (cpl_imagelist_subtract_image(*objs, sky) != CPL_ERROR_NONE) {
814 cpl_msg_error(cpl_func, "Cannot corr. the obj images from the sky");
815 cpl_image_delete(sky);
816 cpl_vector_delete(bg);
817 return NULL;
818 }
819 cpl_image_delete(sky);
820 /* Normalise the object planes */
821 for (i=0; i<nframes; i++) {
822 cur_ima = cpl_imagelist_get(*objs, i);
823 median = cpl_image_get_median(cur_ima);
824 cpl_image_subtract_scalar(cur_ima, median);
825 }
826 } else if (sky_method == 1) {
827 cpl_msg_info(cpl_func, "Median of object images");
828 /* Use objs images */
829 if ((sky = cpl_imagelist_collapse_median_create(*objs)) == NULL) {
830 cpl_msg_error(cpl_func, "Cannot compute the median of obj images");
831 return NULL;
832 }
833 /* Correct the objects images */
834 if (cpl_imagelist_subtract_image(*objs, sky) != CPL_ERROR_NONE) {
835 cpl_msg_error(cpl_func, "Cannot corr. the obj images from the sky");
836 cpl_image_delete(sky);
837 return NULL;
838 }
839 /* Create a 1 value vector */
840 bg = cpl_vector_new(1);
841 cpl_vector_set(bg, 0, cpl_image_get_median(sky));
842 cpl_image_delete(sky);
843 /* Normalise the object planes */
844 for (i=0; i<nframes; i++) {
845 cur_ima = cpl_imagelist_get(*objs, i);
846 median = cpl_image_get_median(cur_ima);
847 cpl_image_subtract_scalar(cur_ima, median);
848 }
849 } else if (sky_method == 2) {
850 cpl_msg_info(cpl_func, "Running filter on object images");
851 /* Use objects images */
852 if ((bg = isaac_img_jitter_sky_running(objs)) == NULL) {
853 cpl_msg_error(cpl_func,
854 "Cannot apply the running filter for the sky");
855 return NULL;
856 }
857 }
858 /* Free and return */
859 return bg;
860}
861
862/*----------------------------------------------------------------------------*/
881/*----------------------------------------------------------------------------*/
882static cpl_vector * isaac_img_jitter_sky_running(cpl_imagelist ** in)
883{
884 int rejmin, rejmax, halfw;
885 cpl_imagelist * filtres;
886 int ni, nx, ny, pos;
887 cpl_vector * medians;
888 cpl_image * cur_ima;
889 float * pcur_ima;
890 cpl_image * tmp_ima;
891 float * ptmp_ima;
892 cpl_vector * localwin;
893 int fr_p, to_p, n_curp;
894 cpl_vector * bg;
895 double bg_val, out;
896 float one_med;
897 int i, j, k;
898
899 /* Test entries */
900 if (in==NULL || *in == NULL) return NULL;
901
902 /* Initialise */
903 rejmin = isaac_img_jitter_config.sky_rejmin;
904 rejmax = isaac_img_jitter_config.sky_rejmax;
905 halfw = isaac_img_jitter_config.sky_halfw;
906 ni = cpl_imagelist_get_size(*in);
907 cur_ima = cpl_imagelist_get(*in, 0);
908 nx = cpl_image_get_size_x(cur_ima);
909 ny = cpl_image_get_size_y(cur_ima);
910
911 /* Tests on validity of rejection parameters */
912 if (((rejmin+rejmax)>=halfw) || (halfw<1) || (rejmin<0) || (rejmax<0)) {
913 cpl_msg_error(cpl_func, "cannot run filter with rej parms %d (%d-%d)",
914 halfw, rejmin, rejmax);
915 return NULL;
916 }
917 /* Pre-compute median value in each plane */
918 medians = cpl_vector_new(ni);
919 for (i=0; i<ni; i++) {
920 cur_ima = cpl_imagelist_get(*in, i);
921 cpl_vector_set(medians, i, cpl_image_get_median(cur_ima));
922 }
923 /* Allocate output cube */
924 filtres = cpl_imagelist_new();
925
926 /* Allocate output bg */
927 bg = cpl_vector_new(ni);
928
929 /* Main loop over input planes */
930 for (k=0; k<ni; k++) {
931 /* Allocate output plane */
932 tmp_ima = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
933 ptmp_ima = cpl_image_get_data_float(tmp_ima);
934 /* Compute border indices */
935 fr_p = k - halfw;
936 to_p = k + halfw;
937 if (fr_p<0) fr_p=0;
938 if (to_p>(ni-1)) to_p=ni-1;
939
940 /* Number of valid planes to consider after edge effects */
941 n_curp = to_p - fr_p;
942
943 /* Allocate local window */
944 localwin = cpl_vector_new(n_curp);
945
946 bg_val = 0.0;
947 /* Loop over all pixels */
948 for (pos=0; pos<nx*ny; pos++) {
949 /* Fill up local window */
950 j=0;
951 for (i=fr_p; i<=to_p; i++) {
952 if (i!=k) {
953 cur_ima = cpl_imagelist_get(*in, i);
954 pcur_ima = cpl_image_get_data_float(cur_ima);
955 cpl_vector_set(localwin, j,
956 (double)pcur_ima[pos]-cpl_vector_get(medians, i));
957 j++;
958 }
959 }
960 /* Sort window */
961 cpl_vector_sort(localwin, 1);
962 /* Reject min and max, accumulate other pixels */
963 out = 0.0;
964 for (i=rejmin; i<(n_curp-rejmax); i++) {
965 out += cpl_vector_get(localwin, i);
966 }
967 /* Take the mean */
968 out /= (double)(n_curp - rejmin - rejmax);
969 /* Assign value */
970 cur_ima = cpl_imagelist_get(*in, k);
971 pcur_ima = cpl_image_get_data_float(cur_ima);
972 ptmp_ima[pos] = pcur_ima[pos] -
973 (float)(out + cpl_vector_get(medians, k));
974
975 bg_val += (out+cpl_vector_get(medians, k));
976 }
977 cpl_vector_delete(localwin);
978 cpl_vector_set(bg, k, bg_val/(nx*ny));
979 cpl_imagelist_set(filtres, tmp_ima, k);
980 }
981 cpl_imagelist_delete(*in);
982 cpl_vector_delete(medians);
983
984 /* Subtract median from each frame */
985 for (i=0; i<ni; i++) {
986 cur_ima = cpl_imagelist_get(filtres, i);
987 one_med = cpl_image_get_median(cur_ima);
988 cpl_image_subtract_scalar(cur_ima, one_med);
989 }
990 *in = filtres;
991 return bg;
992}
993
994/*----------------------------------------------------------------------------*/
1001/*----------------------------------------------------------------------------*/
1002static cpl_image ** isaac_img_jitter_saa_nochop(
1003 cpl_imagelist * in,
1004 const cpl_frameset * objframes)
1005{
1006 const cpl_frame * frame;
1007 cpl_propertylist * plist;
1008 cpl_bivector * offsets_est;
1009 double * offsets_est_x;
1010 double * offsets_est_y;
1011 cpl_bivector * objs;
1012 double * objs_x;
1013 double * objs_y;
1014 cpl_apertures * aperts;
1015 cpl_image ** combined;
1016 cpl_vector * thresh_vect;
1017 cpl_image * diff;
1018 int nfiles;
1019 int nima;
1020 int refine =
1021 isaac_img_jitter_config.saa_refine ? 1 : 0;
1022 int i;
1023
1024 /* Get the number of images */
1025 nfiles = cpl_imagelist_get_size(in);
1026 if (cpl_frameset_get_size(objframes) != nfiles) {
1027 cpl_msg_error(cpl_func, "Invalid input objects sizes");
1028 return NULL;
1029 }
1030
1031 /* Get the offsets estimation of each input file pair */
1032 cpl_msg_info(cpl_func, "Get the offsets estimation");
1033 offsets_est = NULL;
1034 if (isaac_img_jitter_config.offsets &&
1035 isaac_img_jitter_config.offsets[0] != (char)0) {
1036 /* A file has been provided on the command line */
1037 offsets_est = cpl_bivector_read(isaac_img_jitter_config.offsets);
1038 if ((offsets_est==NULL)||(cpl_bivector_get_size(offsets_est)!=nfiles)) {
1039 cpl_msg_error(cpl_func, "Cannot get offsets from %s",
1040 isaac_img_jitter_config.offsets);
1041 return NULL;
1042 }
1043 } else {
1044 /* Get the offsets from the header */
1045 offsets_est = cpl_bivector_new(nfiles);
1046 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
1047 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
1048 for (i=0; i<nfiles; i++) {
1049 if (cpl_error_get_code()) {
1050 cpl_bivector_delete(offsets_est);
1051 offsets_est = NULL;
1052 break;
1053 }
1054 /* X and Y offsets */
1055 frame = cpl_frameset_get_position_const(objframes, i);
1056 plist=cpl_propertylist_load(cpl_frame_get_filename(frame),0);
1057 offsets_est_x[i] = -1.0 * isaac_pfits_get_cumoffsetx(plist);
1058 offsets_est_y[i] = -1.0 * isaac_pfits_get_cumoffsety(plist);
1059 cpl_propertylist_delete(plist);
1060 if (cpl_error_get_code()) {
1061 cpl_msg_warning(cpl_func, "Cannot get offsets from header");
1062 cpl_bivector_delete(offsets_est);
1063 offsets_est = NULL;
1064 break;
1065 }
1066 if (i > 0) {
1067 /* Subtract the first offset from all offsets */
1068 offsets_est_x[i] -= offsets_est_x[0];
1069 offsets_est_y[i] -= offsets_est_y[0];
1070 }
1071 }
1072 if (i == nfiles) {
1073 offsets_est_x[0] = offsets_est_y[0] = 0.0;
1074 }
1075 }
1076
1077 /* Read the provided objects file if provided */
1078 objs = NULL;
1079 if (isaac_img_jitter_config.objects &&
1080 isaac_img_jitter_config.objects[0] != (char)0) {
1081 cpl_msg_info(cpl_func, "Get the user provided correlation objects");
1082 /* A file has been provided on the command line */
1083 objs = cpl_bivector_read(isaac_img_jitter_config.objects);
1084 if (objs==NULL) {
1085 cpl_msg_error(cpl_func, "Cannot get objects from %s",
1086 isaac_img_jitter_config.objects);
1087 if (offsets_est) cpl_bivector_delete(offsets_est);
1088 return NULL;
1089 }
1090 }
1091
1092 /* Get a correlation point from the difference of the first images */
1093 if (objs == NULL) {
1094 cpl_msg_info(cpl_func, "Get a cross-correlation point");
1095 thresh_vect = cpl_vector_new(4);
1096 cpl_vector_set(thresh_vect, 0, 5.0);
1097 cpl_vector_set(thresh_vect, 1, 2.0);
1098 cpl_vector_set(thresh_vect, 2, 1.0);
1099 cpl_vector_set(thresh_vect, 3, 0.5);
1100 diff = cpl_image_subtract_create(cpl_imagelist_get(in, 0),
1101 cpl_imagelist_get(in, 1));
1102 if ((aperts = cpl_apertures_extract_window(diff, thresh_vect,
1103 200, 200, 800, 800, NULL)) == NULL) {
1104 cpl_msg_error(cpl_func, "Cannot find any cross-correlation point");
1105 if (offsets_est) cpl_bivector_delete(offsets_est);
1106 cpl_vector_delete(thresh_vect);
1107 cpl_image_delete(diff);
1108 return NULL;
1109 }
1110 cpl_image_delete(diff);
1111 cpl_vector_delete(thresh_vect);
1112 cpl_apertures_sort_by_npix(aperts);
1113 objs = cpl_bivector_new(1);
1114 objs_x = cpl_bivector_get_x_data(objs);
1115 objs_y = cpl_bivector_get_y_data(objs);
1116 objs_x[0] = cpl_apertures_get_pos_x(aperts, 1);
1117 objs_y[0] = cpl_apertures_get_pos_y(aperts, 1);
1118 cpl_apertures_delete(aperts);
1119 if (objs == NULL) {
1120 cpl_msg_error(cpl_func, "Cannot find any cross-correlation point");
1121 if (offsets_est) cpl_bivector_delete(offsets_est);
1122 return NULL;
1123 }
1124 cpl_msg_info(cpl_func,
1125 "Correlation point: %g %g\n", objs_x[0], objs_y[0]);
1126 }
1127
1128 /* Recombine the images */
1129 cpl_msg_info(cpl_func, "Recombine the images set");
1130 cpl_msg_indent_more();
1131 if ((combined = cpl_geom_img_offset_combine(in, offsets_est, refine, objs,
1132 NULL, NULL,
1133 isaac_img_jitter_config.sx,
1134 isaac_img_jitter_config.sy,
1135 isaac_img_jitter_config.mx,
1136 isaac_img_jitter_config.my,
1137 isaac_img_jitter_config.rej_low,
1138 isaac_img_jitter_config.rej_high,
1139 isaac_img_jitter_config.comb_meth)) == NULL) {
1140 cpl_msg_error(cpl_func, "Cannot recombine the images");
1141 if (offsets_est) cpl_bivector_delete(offsets_est);
1142 cpl_bivector_delete(objs);
1143 cpl_msg_indent_less();
1144 return NULL;
1145 }
1146 /* Update QC params */
1147 i = (int)(cpl_image_get_max(combined[1]));
1148 nima = cpl_imagelist_get_size(in);
1149 if ((nima > 3) && (nima>2*
1150 (isaac_img_jitter_config.rej_low+isaac_img_jitter_config.rej_high)))
1151 i += isaac_img_jitter_config.rej_low+isaac_img_jitter_config.rej_high;
1152 isaac_img_jitter_config.nb_rej_frames =
1153 isaac_img_jitter_config.nb_obj_frames - i;
1154 isaac_img_jitter_config.nb_obj_frames = i;
1155 cpl_msg_indent_less();
1156
1157 /* Free and return */
1158 if (offsets_est) cpl_bivector_delete(offsets_est);
1159 cpl_bivector_delete(objs);
1160 return combined;
1161}
1162
1163
1164/*----------------------------------------------------------------------------*/
1171/*----------------------------------------------------------------------------*/
1172static cpl_image ** isaac_img_jitter_saa_chop(
1173 cpl_imagelist * in,
1174 const cpl_frameset * objframes)
1175{
1176 const cpl_frame * frame;
1177 cpl_propertylist * plist;
1178 cpl_bivector * offsets_est;
1179 cpl_bivector * offsets_est_nod;
1180 double * offsets_est_x;
1181 double * offsets_est_y;
1182 double * offsets_est_nod_x;
1183 double * offsets_est_nod_y;
1184 cpl_bivector * objs;
1185 cpl_image ** combined;
1186 cpl_vector * thresh_vect;
1187 int nfiles, nb_chop;
1188 int * chop_a;
1189 int * chop_b;
1190 cpl_imagelist * nodded;
1191 cpl_image * tmp_ima;
1192 int refine =
1193 isaac_img_jitter_config.saa_refine ? 1 : 0;
1194 int i;
1195
1196 /* Get the number of images */
1197 nfiles = cpl_imagelist_get_size(in);
1198 if (cpl_frameset_get_size(objframes) != nfiles) {
1199 cpl_msg_error(cpl_func, "Invalid input objects sizes");
1200 return NULL;
1201 }
1202
1203 /* Get the offsets estimation of each input file pair */
1204 cpl_msg_info(cpl_func, "Get the offsets estimation");
1205 offsets_est = NULL;
1206 if (isaac_img_jitter_config.offsets &&
1207 isaac_img_jitter_config.offsets[0] != (char)0) {
1208 /* A file has been provided on the command line */
1209 offsets_est = cpl_bivector_read(isaac_img_jitter_config.offsets);
1210 if ((offsets_est==NULL) ||
1211 (cpl_bivector_get_size(offsets_est) != nfiles)) {
1212 cpl_msg_error(cpl_func, "Cannot get offsets from %s",
1213 isaac_img_jitter_config.offsets);
1214 return NULL;
1215 }
1216 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
1217 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
1218 } else {
1219 /* Get the offsets from the header */
1220 offsets_est = cpl_bivector_new(nfiles);
1221 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
1222 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
1223 for (i=0; i<nfiles; i++) {
1224 if (cpl_error_get_code()) {
1225 cpl_bivector_delete(offsets_est);
1226 return NULL;
1227 }
1228 /* X and Y offsets */
1229 frame = cpl_frameset_get_position_const(objframes, i);
1230 plist=cpl_propertylist_load(cpl_frame_get_filename(frame),0);
1231 offsets_est_x[i] = -1.0 * isaac_pfits_get_cumoffsetx(plist);
1232 offsets_est_y[i] = -1.0 * isaac_pfits_get_cumoffsety(plist);
1233 cpl_propertylist_delete(plist);
1234 if (cpl_error_get_code()) {
1235 cpl_msg_warning(cpl_func, "Cannot get offsets from header");
1236 cpl_bivector_delete(offsets_est);
1237 return NULL;
1238 }
1239 }
1240 /* Subtract the first offset to all offsets */
1241 for (i=1; i<nfiles; i++) {
1242 offsets_est_x[i] -= offsets_est_x[0];
1243 offsets_est_y[i] -= offsets_est_y[0];
1244 }
1245 offsets_est_x[0] = offsets_est_y[0] = 0.00;
1246 }
1247
1248 /* Classify the A and B nodding positions using the offsets */
1249 if ((nb_chop=isaac_img_jitter_chopping_classif(offsets_est,
1250 &chop_a, &chop_b)) == -1) {
1251 cpl_msg_error(cpl_func, "cannot classify chopped frames");
1252 cpl_bivector_delete(offsets_est);
1253 return NULL;
1254 }
1255
1256 /* Create the nodded frames chop_a-chop_b */
1257 nodded = cpl_imagelist_new();
1258 for (i=0; i<nb_chop; i++) {
1259 tmp_ima = cpl_image_subtract_create(
1260 cpl_imagelist_get(in, chop_a[i]),
1261 cpl_imagelist_get(in, chop_b[i]));
1262 cpl_imagelist_set(nodded, tmp_ima, i);
1263 }
1264
1265 /* Update the offsets estimations between the nodded frames */
1266 offsets_est_nod = cpl_bivector_new(nb_chop);
1267 offsets_est_nod_x = cpl_bivector_get_x_data(offsets_est_nod);
1268 offsets_est_nod_y = cpl_bivector_get_y_data(offsets_est_nod);
1269 for (i=0; i<nb_chop; i++) {
1270 offsets_est_nod_x[i] = offsets_est_x[chop_a[i]];
1271 offsets_est_nod_y[i] = offsets_est_y[chop_a[i]];
1272 }
1273 cpl_bivector_delete(offsets_est);
1274 cpl_free(chop_a);
1275 cpl_free(chop_b);
1276
1277 /* Read the provided objects file if provided */
1278 objs = NULL;
1279 if (isaac_img_jitter_config.objects &&
1280 isaac_img_jitter_config.objects[0] != (char)0) {
1281 cpl_msg_info(cpl_func, "Get the user provided correlation objects");
1282 /* A file has been provided on the command line */
1283 objs = cpl_bivector_read(isaac_img_jitter_config.objects);
1284 if (objs==NULL) {
1285 cpl_msg_error(cpl_func, "Cannot get objects from %s",
1286 isaac_img_jitter_config.objects);
1287 cpl_bivector_delete(offsets_est_nod);
1288 cpl_imagelist_delete(nodded);
1289 return NULL;
1290 }
1291 }
1292
1293 /* Create the vector for the detection thresholds */
1294 thresh_vect = cpl_vector_new(4);
1295 cpl_vector_set(thresh_vect, 0, 5.0);
1296 cpl_vector_set(thresh_vect, 1, 2.0);
1297 cpl_vector_set(thresh_vect, 2, 1.0);
1298 cpl_vector_set(thresh_vect, 3, 0.5);
1299
1300 /* Recombine the images */
1301 cpl_msg_info(cpl_func, "Recombine the images set");
1302 cpl_msg_indent_more();
1303 if ((combined = cpl_geom_img_offset_combine(nodded, offsets_est_nod,
1304 refine, objs, thresh_vect, NULL,
1305 isaac_img_jitter_config.sx,
1306 isaac_img_jitter_config.sy,
1307 isaac_img_jitter_config.mx,
1308 isaac_img_jitter_config.my,
1309 isaac_img_jitter_config.rej_low,
1310 isaac_img_jitter_config.rej_high,
1311 isaac_img_jitter_config.comb_meth)) == NULL) {
1312 cpl_msg_error(cpl_func, "Cannot recombine the images");
1313 cpl_bivector_delete(offsets_est_nod);
1314 cpl_imagelist_delete(nodded);
1315 if (objs) cpl_bivector_delete(objs);
1316 cpl_vector_delete(thresh_vect);
1317 cpl_msg_indent_less();
1318 return NULL;
1319 }
1320 /* Update QC params */
1321 i = (int)(cpl_image_get_max(combined[1]));
1322 isaac_img_jitter_config.nb_rej_frames =
1323 isaac_img_jitter_config.nb_obj_frames - i;
1324 isaac_img_jitter_config.nb_obj_frames = i;
1325 cpl_msg_indent_less();
1326
1327 /* Free and return */
1328 cpl_vector_delete(thresh_vect);
1329 cpl_bivector_delete(offsets_est_nod);
1330 cpl_imagelist_delete(nodded);
1331 if (objs) cpl_bivector_delete(objs);
1332 return combined;
1333}
1334
1335/*----------------------------------------------------------------------------*/
1343/*----------------------------------------------------------------------------*/
1344static int isaac_img_jitter_chopping_classif(
1345 cpl_bivector * offsets,
1346 int ** chop_a,
1347 int ** chop_b)
1348{
1349 int nb_obj;
1350 double * offsets_x;
1351 double * offsets_y;
1352 double throw_x,
1353 throw_y;
1354 double * dist;
1355 int * dcount;
1356 int max_count;
1357 int i_max, j_max;
1358 int classified;
1359 int i, j, k, l;
1360
1361 /* Test entries */
1362 if (offsets==NULL || chop_a==NULL || chop_b==NULL) return CPL_ERROR_UNSPECIFIED;
1363
1364 /* Initialise */
1365 *chop_a = *chop_b = NULL;
1366
1367 /* Find number of type_obj frames */
1368 nb_obj = cpl_bivector_get_size(offsets);
1369 offsets_x = cpl_bivector_get_x_data(offsets);
1370 offsets_y = cpl_bivector_get_y_data(offsets);
1371
1372 /* If no object frame, exit */
1373 if (nb_obj == 0) return CPL_ERROR_UNSPECIFIED;
1374
1375 /* Odd number of frames ? */
1376 if (nb_obj%2) {
1377 cpl_msg_error(cpl_func, "odd number of frames in input [%d]", nb_obj);
1378 return CPL_ERROR_UNSPECIFIED;
1379 }
1380
1381 /* Find all distances between offsets and count them */
1382 dist = cpl_calloc(nb_obj*nb_obj, sizeof(double));
1383 dcount = cpl_calloc(nb_obj*nb_obj, sizeof(int));
1384 for (i=0; i<nb_obj; i++) {
1385 for (j=0; j<nb_obj; j++) {
1386 dist[i+j*nb_obj] = sqrt(SQR(offsets_x[i] - offsets_x[j]) +
1387 SQR(offsets_y[i] - offsets_y[j]));
1388 }
1389 }
1390
1391 for (i=0; i<nb_obj*nb_obj; i++) {
1392 for (j=0; j<nb_obj*nb_obj; j++)
1393 if (fabs(dist[i]-dist[j]) <= NEGLIG_OFF_DIFF) dcount[i] ++;
1394 }
1395
1396 /* Find Chop offsets as the nonzero distance with maximal occurrence */
1397 max_count = 0;
1398 i_max = 0;
1399 j_max = 0;
1400 for (i=0; i<nb_obj; i++){
1401 for (j=0; j<nb_obj; j++) {
1402 if ((dcount[i+j*nb_obj]>max_count)&&(dist[i+j*nb_obj]>0.5)){
1403 max_count = dcount[i+j*nb_obj];
1404 i_max = i;
1405 j_max = j;
1406 }
1407 }
1408 }
1409
1410 /* Compute the throw */
1411 throw_x = offsets_x[j_max] - offsets_x[i_max];
1412 throw_y = offsets_y[j_max] - offsets_y[i_max];
1413
1414 cpl_msg_info(cpl_func, "Typical (%d) non-zero throw is (%g, %g) from %d "
1415 "(%g, %g) to %d (%g, %g)", max_count, throw_x, throw_y,
1416 i_max, offsets_x[i_max], offsets_y[i_max],
1417 j_max, offsets_x[j_max], offsets_y[j_max]);
1418
1419 /* Free */
1420 cpl_free(dist);
1421 cpl_free(dcount);
1422
1423 /* Test the throw */
1424 if ((throw_x == 0) && (throw_y == 0)) {
1425 cpl_msg_error(cpl_func, "Throw is equal to 0 - cannot classify");
1426 return CPL_ERROR_UNSPECIFIED;
1427 }
1428
1429 /* Allocate maximal possible nb of chop frames (worst case: abab)*/
1430 *chop_a = cpl_calloc(nb_obj/2, sizeof(int));
1431 *chop_b = cpl_calloc(nb_obj/2, sizeof(int));
1432
1433 k = l = 0;
1434 for (i=0; i<nb_obj-1; i++) {
1435 /* Consider the successive pairs of frames */
1436 /* AB ? */
1437 if ((fabs(offsets_x[i]-offsets_x[i+1]+throw_x) < NEGLIG_OFF_DIFF) &&
1438 (fabs(offsets_y[i]-offsets_y[i+1]+throw_y) < NEGLIG_OFF_DIFF)) {
1439 (*chop_a)[k++] = i;
1440 (*chop_b)[l++] = i+1;
1441 /* BA ? */
1442 } else if ((fabs(offsets_x[i]-offsets_x[i+1]-throw_x) <
1443 NEGLIG_OFF_DIFF) &&
1444 (fabs(offsets_y[i]-offsets_y[i+1]-throw_y) <
1445 NEGLIG_OFF_DIFF)) {
1446 (*chop_b)[l++] = i;
1447 (*chop_a)[k++] = i+1;
1448 /* AA or BB ? -> do nothing */
1449 }
1450 }
1451
1452 cpl_msg_info(cpl_func, "Found %d A- and %d B-frames (out of %d)", k, l,
1453 nb_obj);
1454
1455 /* Classify the frames not seen until here as rejected */
1456 for (i=0; i<nb_obj; i++) {
1457 classified = 0;
1458 /* For each frame, check if it has been classified */
1459 for (j=0; j < nb_obj/2; j++) {
1460 if ((*chop_a)[j] == i || (*chop_b)[j] == i) classified = 1;
1461 }
1462 if (classified == 0) {
1463 cpl_msg_error(cpl_func, "Frame %d cannot be classified", i+1);
1464 cpl_free(*chop_a);
1465 cpl_free(*chop_b);
1466 *chop_a = *chop_b = NULL;
1467 return CPL_ERROR_UNSPECIFIED;
1468 }
1469 }
1470
1471 /* There should be as much chop a as chop b frames */
1472 if (k != l) {
1473 cpl_free(*chop_a);
1474 cpl_free(*chop_b);
1475 *chop_a = *chop_b = NULL;
1476 return CPL_ERROR_UNSPECIFIED;
1477 }
1478 return k;
1479}
1480
1481/*----------------------------------------------------------------------------*/
1488/*----------------------------------------------------------------------------*/
1489static cpl_error_code isaac_img_jitter_sub_row_median(cpl_image * self)
1490{
1491 const int nx = cpl_image_get_size_x(self);
1492 const int ny = cpl_image_get_size_y(self);
1493 float * pself = cpl_image_get_data_float(self);
1494 int i, j;
1495
1496 bug_if(self == NULL);
1497 bug_if(cpl_image_get_type(self) != CPL_TYPE_FLOAT);
1498
1499
1500 for (j = 0; j < ny; j++, pself += nx) {
1501 cpl_errorstate prestate = cpl_errorstate_get();
1502 const double median = cpl_image_get_median_window(self, 1, j+1, nx, j+1);
1503
1504 if (cpl_errorstate_is_equal(prestate)) {
1505 for (i = 0; i < nx; i++) {
1506 pself[i] -= (float)median;
1507 }
1508 } else {
1509 cpl_msg_warning(cpl_func, "Could not subtract median from %d "
1510 "pixel(s) in row %d/%d (%d bad pixel(s))", nx, 1+j,
1511 ny, (int)cpl_image_count_rejected(self));
1512 cpl_errorstate_set(prestate);
1513 }
1514 }
1515
1516 end_skip;
1517
1518 return cpl_error_get_code();
1519}
1520
1521/*----------------------------------------------------------------------------*/
1527/*----------------------------------------------------------------------------*/
1528static cpl_table * isaac_img_jitter_qc(cpl_image * combined)
1529{
1530 cpl_vector * thresh_vec;
1531 cpl_apertures * aperts;
1532 int nb_objs;
1533 double angle;
1534 double * fwhms_x;
1535 double * fwhms_y;
1536 cpl_table * out_tab;
1537 cpl_bivector * iqe;
1538 int nb_good;
1539 cpl_vector * fwhms_good;
1540 double * fwhms_good_data;
1541 double f_min, f_max, fr, fx, fy;
1542 int i, j;
1543
1544 /* Initialise */
1545 double seeing_min_arcsec = 0.1;
1546 double seeing_max_arcsec = 5.0;
1547 double seeing_fwhm_var = 0.2;
1548
1549 /* Check entries */
1550 if (combined == NULL) return NULL;
1551
1552 /* Create the vector for the detection thresholds */
1553 thresh_vec = cpl_vector_new(4);
1554 cpl_vector_set(thresh_vec, 0, 5.0);
1555 cpl_vector_set(thresh_vec, 1, 2.0);
1556 cpl_vector_set(thresh_vec, 2, 1.0);
1557 cpl_vector_set(thresh_vec, 3, 0.5);
1558
1559 /* Detect apertures */
1560 if ((aperts = cpl_apertures_extract(combined, thresh_vec, NULL)) == NULL) {
1561 cpl_msg_error(cpl_func, "Cannot detect any aperture");
1562 cpl_vector_delete(thresh_vec);
1563 return NULL;
1564 }
1565 cpl_vector_delete(thresh_vec);
1566
1567 /* Number of detected objects */
1568 nb_objs = cpl_apertures_get_size(aperts);
1569 isaac_img_jitter_config.nbobjs = nb_objs;
1570 fwhms_x = cpl_malloc(nb_objs * sizeof(double));
1571 fwhms_y = cpl_malloc(nb_objs * sizeof(double));
1572
1573 /* Create the output table */
1574 out_tab = cpl_table_new(nb_objs);
1575 cpl_table_new_column(out_tab, "POS_X", CPL_TYPE_DOUBLE);
1576 cpl_table_new_column(out_tab, "POS_Y", CPL_TYPE_DOUBLE);
1577 cpl_table_new_column(out_tab, "ANGLE", CPL_TYPE_DOUBLE);
1578 cpl_table_new_column(out_tab, "FWHM_X", CPL_TYPE_DOUBLE);
1579 cpl_table_new_column(out_tab, "FWHM_Y", CPL_TYPE_DOUBLE);
1580 cpl_table_new_column(out_tab, "ELLIP", CPL_TYPE_DOUBLE);
1581 cpl_table_new_column(out_tab, "FLUX", CPL_TYPE_DOUBLE);
1582 for (i=0; i<nb_objs; i++) {
1583 /* Fill with the already known information */
1584 cpl_table_set_double(out_tab, "POS_X", i,
1585 cpl_apertures_get_centroid_x(aperts, i+1));
1586 cpl_table_set_double(out_tab, "POS_Y", i,
1587 cpl_apertures_get_centroid_y(aperts, i+1));
1588 cpl_table_set_double(out_tab, "FLUX", i,
1589 cpl_apertures_get_flux(aperts, i+1));
1590 /* Compute the FWHM informations */
1591 if ((iqe = cpl_image_iqe(combined,
1592 (int)cpl_apertures_get_centroid_x(aperts, i+1) - 10,
1593 (int)cpl_apertures_get_centroid_y(aperts, i+1) - 10,
1594 (int)cpl_apertures_get_centroid_x(aperts, i+1) + 10,
1595 (int)cpl_apertures_get_centroid_y(aperts, i+1) + 10))==NULL){
1596 cpl_error_reset();
1597 cpl_msg_warning(cpl_func, "Cannot get FWHM for obj at pos %g %g",
1598 cpl_apertures_get_centroid_x(aperts, i+1),
1599 cpl_apertures_get_centroid_y(aperts, i+1));
1600 fwhms_x[i] = -1.0;
1601 fwhms_y[i] = -1.0;
1602 angle = 0.0;
1603 } else {
1604 fwhms_x[i] = cpl_vector_get(cpl_bivector_get_x(iqe), 2);
1605 fwhms_y[i] = cpl_vector_get(cpl_bivector_get_x(iqe), 3);
1606 angle = cpl_vector_get(cpl_bivector_get_x(iqe), 4);
1607 cpl_bivector_delete(iqe);
1608 }
1609 cpl_table_set_double(out_tab, "ANGLE", i, angle);
1610 cpl_table_set_double(out_tab, "FWHM_X", i, fwhms_x[i]);
1611 cpl_table_set_double(out_tab, "FWHM_Y", i, fwhms_y[i]);
1612 if (fwhms_x[i] == 0.0) {
1613 cpl_msg_warning(cpl_func, "Infinite ELLIP for obj at pos %g %g",
1614 cpl_apertures_get_centroid_x(aperts, i+1),
1615 cpl_apertures_get_centroid_y(aperts, i+1));
1616 cpl_table_set_double(out_tab, "ELLIP", i, DBL_MAX);
1617 } else {
1618 cpl_table_set_double(out_tab, "ELLIP", i,
1619 fwhms_y[i] / fwhms_x[i]);
1620 }
1621 }
1622 cpl_apertures_delete(aperts);
1623
1624 /* Get the number of good values */
1625 nb_good = 0;
1626 for (i=0; i<nb_objs; i++) {
1627 if ((fwhms_x[i] > 0.0) && (fwhms_y[i] > 0.0)) nb_good++;
1628 }
1629 if (nb_good == 0) {
1630 cpl_table_delete(out_tab);
1631 cpl_free(fwhms_x);
1632 cpl_free(fwhms_y);
1633 return NULL;
1634 }
1635
1636 /* Get the good values */
1637 fwhms_good = cpl_vector_new(nb_good);
1638 fwhms_good_data = cpl_vector_get_data(fwhms_good);
1639 j=0;
1640 for (i=0; i<nb_objs; i++) {
1641 if ((fwhms_x[i] > 0.0) && (fwhms_y[i] > 0.0)) {
1642 fwhms_good_data[j] = (fwhms_x[i]+fwhms_y[i])/2.0;
1643 j++;
1644 }
1645 }
1646
1647 /* Compute the fwhm */
1648 if (nb_good < 3) {
1649 /* Too few values to compute the median */
1650 isaac_img_jitter_config.fwhm_pix = fwhms_good_data[0];
1651 } else {
1652 /* Compute the median */
1653 isaac_img_jitter_config.fwhm_pix = cpl_vector_get_median_const(fwhms_good);
1654 }
1655 isaac_img_jitter_config.fwhm_arcsec =
1656 isaac_img_jitter_config.fwhm_pix * isaac_img_jitter_config.pixscale;
1657
1658 /* Compute the mode of the FWHMs */
1659 if (nb_good > 5) {
1660 isaac_img_jitter_config.fwhm_mode=isaac_img_jitter_get_mode(fwhms_good);
1661 isaac_img_jitter_config.fwhm_mode *= isaac_img_jitter_config.pixscale;
1662 }
1663 cpl_vector_delete(fwhms_good);
1664
1665 /* IQ is the median of the (fwhm_x+fwhm_y/2) of the good stars */
1666 /* Compute f_min and f_max */
1667 f_min = seeing_min_arcsec / isaac_img_jitter_config.pixscale;
1668 f_max = seeing_max_arcsec / isaac_img_jitter_config.pixscale;
1669
1670 /* Get the number of good values */
1671 nb_good = 0;
1672 for (i=0; i<nb_objs; i++) {
1673 fx = fwhms_x[i];
1674 fy = fwhms_y[i];
1675 fr = 2.0 * fabs(fx-fy) / (fx+fy);
1676 if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) &&
1677 (fr < seeing_fwhm_var)) nb_good++;
1678 }
1679 if (nb_good == 0) {
1680 cpl_table_delete(out_tab);
1681 cpl_free(fwhms_x);
1682 cpl_free(fwhms_y);
1683 return NULL;
1684 }
1685
1686 /* Get the good values */
1687 fwhms_good = cpl_vector_new(nb_good);
1688 fwhms_good_data = cpl_vector_get_data(fwhms_good);
1689 j=0;
1690 for (i=0; i<nb_objs; i++) {
1691 fx = fwhms_x[i];
1692 fy = fwhms_y[i];
1693 fr = 2.0 * fabs(fx-fy) / (fx+fy);
1694 if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) &&
1695 (fr < seeing_fwhm_var)) {
1696 fwhms_good_data[j] = (fx + fy)/2.0;
1697 j++;
1698 }
1699 }
1700 cpl_free(fwhms_x);
1701 cpl_free(fwhms_y);
1702
1703 /* Compute the fwhm */
1704 if (nb_good < 3) {
1705 /* Too few values to compute the median */
1706 isaac_img_jitter_config.iq = fwhms_good_data[0];
1707 } else {
1708 /* Compute the median */
1709 isaac_img_jitter_config.iq = cpl_vector_get_median_const(fwhms_good);
1710 }
1711 cpl_vector_delete(fwhms_good);
1712 isaac_img_jitter_config.iq *= isaac_img_jitter_config.pixscale;
1713
1714 isaac_img_jitter_config.angle_med = cpl_table_get_column_median(out_tab,
1715 "ANGLE");
1716 isaac_img_jitter_config.ellip_med = cpl_table_get_column_median(out_tab,
1717 "ELLIP");
1718 return out_tab;
1719}
1720
1721/*----------------------------------------------------------------------------*/
1727/*----------------------------------------------------------------------------*/
1728static double isaac_img_jitter_get_mode(cpl_vector * vec)
1729{
1730 int nb;
1731 int nbins;
1732 double min, max;
1733 double bin_size;
1734 cpl_bivector * hist;
1735 cpl_vector * hist_x;
1736 cpl_vector * hist_y;
1737 double cur_val;
1738 int cur_bin;
1739 double max_val;
1740 int max_bin;
1741 double mode;
1742 int i;
1743
1744 /* Test entries */
1745 if (vec == NULL) return -1.0;
1746
1747 /* Initialise */
1748 nb = cpl_vector_get_size(vec);
1749
1750 /* Create the histogram */
1751 nbins = 10;
1752 min = cpl_vector_get_min(vec);
1753 max = cpl_vector_get_max(vec);
1754 bin_size = (max-min)/nbins;
1755 hist = cpl_bivector_new(nbins);
1756 hist_x = cpl_bivector_get_x(hist);
1757 hist_y = cpl_bivector_get_y(hist);
1758 cpl_vector_fill(hist_x, 0.0);
1759 cpl_vector_fill(hist_y, 0.0);
1760 for (i=0; i<nbins; i++) {
1761 cpl_vector_set(hist_x, i, min + i * bin_size);
1762 }
1763 for (i=0; i<nb; i++) {
1764 cur_val = cpl_vector_get(vec, i);
1765 cur_bin = (int)((cur_val - min) / bin_size);
1766 if (cur_bin >= nbins) cur_bin -= 1.0;
1767 cur_val = cpl_vector_get(hist_y, cur_bin);
1768 cur_val += 1.0;
1769 cpl_vector_set(hist_y, cur_bin, cur_val);
1770 }
1771
1772 /* Get the mode of the histogram */
1773 max_val = cpl_vector_get(hist_y, 0);
1774 max_bin = 0;
1775 for (i=0; i<nbins; i++) {
1776 cur_val = cpl_vector_get(hist_y, i);
1777 if (cur_val > max_val) {
1778 max_val = cur_val;
1779 max_bin = i;
1780 }
1781 }
1782 mode = cpl_vector_get(hist_x, max_bin);
1783 cpl_bivector_delete(hist);
1784 return mode;
1785}
1786
1787/*----------------------------------------------------------------------------*/
1799/*----------------------------------------------------------------------------*/
1800static
1801cpl_error_code isaac_img_jitter_save(cpl_frameset * set,
1802 const cpl_image * combined,
1803 const cpl_image * contrib,
1804 const cpl_table * objs_stats,
1805 const cpl_vector * sky_bg,
1806 const cpl_parameterlist * parlist)
1807{
1808 const cpl_frame * ref_frame
1809 = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
1810 const char * filename = cpl_frame_get_filename(ref_frame);
1811 const int sz_skybg = sky_bg ? cpl_vector_get_size(sky_bg) : 0;
1812 cpl_propertylist * plist = NULL;
1813 cpl_propertylist * qclist = cpl_propertylist_new();
1814 const char * wcs_reg = "(CRVAL|CRPIX|CTYPE)[0-9]+|(CD)[0-9]+_[0-9]+";
1815 cpl_table * sky_bg_tab = NULL;
1816 int i;
1817
1818 bug_if(0);
1819 bug_if(combined == NULL);
1820 bug_if(contrib == NULL);
1821 bug_if(parlist == NULL);
1822
1823 /* Get the QC params in qclist */
1824 if (isaac_img_jitter_config.chopping == 0) {
1825 const char * key = "ESO QC BACKGD INSTMAG";
1826 const double pscale = isaac_img_jitter_config.pixscale;
1827 const double dit = isaac_img_jitter_config.dit;
1828 const double bg_mean = cpl_vector_get_mean(sky_bg);
1829 const double bg_stdev = sz_skybg < 2 ? 0.0
1830 : cpl_vector_get_stdev(sky_bg);
1831
1832
1833 bug_if(cpl_propertylist_append_double(qclist, "ESO QC BACKGD MEAN",
1834 bg_mean));
1835 bug_if(cpl_propertylist_append_double(qclist, "ESO QC BACKGD STDEV",
1836 bg_stdev));
1837
1838 if (pscale * dit != 0.0 && bg_mean / (pscale * pscale * dit) > 0.0) {
1839 const double bg_instmag = -2.5 * log10(bg_mean/(pscale*pscale*dit));
1840
1841 bug_if(cpl_propertylist_append_double(qclist, key, bg_instmag));
1842 } else {
1843 cpl_msg_warning(cpl_func, "Could not compute %s: dit=%g, pscale=%g, "
1844 "bg_mean=%g", key, dit, pscale, bg_mean);
1845 }
1846 }
1847
1848 cpl_propertylist_append_int(qclist, "ESO QC NBOBJS",
1849 isaac_img_jitter_config.nbobjs);
1850 cpl_propertylist_append_double(qclist, "ESO QC IQ",
1851 isaac_img_jitter_config.iq);
1852 cpl_propertylist_append_double(qclist, "ESO QC FWHM PIX",
1853 isaac_img_jitter_config.fwhm_pix);
1854 cpl_propertylist_append_double(qclist, "ESO QC FWHM ARCSEC",
1855 isaac_img_jitter_config.fwhm_arcsec);
1856 cpl_propertylist_append_double(qclist, "ESO QC FWHM MODE",
1857 isaac_img_jitter_config.fwhm_mode);
1858 cpl_propertylist_append_int(qclist, "ESO QC NB_OBJ_F",
1859 isaac_img_jitter_config.nb_obj_frames);
1860 cpl_propertylist_append_int(qclist, "ESO QC NB_SKY_F",
1861 isaac_img_jitter_config.nb_sky_frames);
1862 cpl_propertylist_append_int(qclist, "ESO QC NB_REJ_F",
1863 isaac_img_jitter_config.nb_rej_frames);
1864 cpl_propertylist_append_double(qclist, "ESO QC ANGLE MED",
1865 isaac_img_jitter_config.angle_med);
1866 cpl_propertylist_append_double(qclist, "ESO QC ELLIP MED",
1867 isaac_img_jitter_config.ellip_med);
1868 bug_if(0);
1869
1870 /* Get FITS header from reference file */
1871 plist = cpl_propertylist_load(filename, 0);
1872 skip_if(plist == NULL);
1873
1874 /* Load the WCS keys */
1875 bug_if(cpl_propertylist_copy_property_regexp(qclist, plist, wcs_reg, 0));
1876
1877 /* Get the keywords for the paf file */
1878 (void)cpl_propertylist_erase_regexp(plist,
1879 "^(ARCFILE|MJD-OBS|INSTRUME"
1880 "|ESO TPL ID|ESO TPL NEXP"
1881 "|ESO DPR CATG"
1882 "|ESO DPR TECH|ESO DPR TYPE"
1883 "|DATE-OBS|ESO OBS ID"
1884 "|ESO INS PIXSCALE)$", 1);
1885
1886 /* Write the image */
1887 skip_if(irplib_dfs_save_image(set, parlist, set, combined,
1888 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
1889 ISAAC_IMG_JITTER_COMB, qclist, NULL,
1890 PACKAGE "/" PACKAGE_VERSION,
1891 RECIPE_STRING CPL_DFS_FITS));
1892 (void)cpl_propertylist_erase_regexp(qclist, wcs_reg, 0);
1893
1894 /* Append the contribution map */
1895 skip_if (cpl_image_save(contrib, RECIPE_STRING CPL_DFS_FITS,
1896 CPL_BPP_16_UNSIGNED, NULL, CPL_IO_EXTEND));
1897
1898 if (sky_bg != NULL) {
1899 /* Write the FITS background table */
1900
1901 /* First create the table from the vector */
1902 sky_bg_tab = cpl_table_new(sz_skybg);
1903
1904 cpl_table_new_column(sky_bg_tab, "SKY_BG", CPL_TYPE_DOUBLE);
1905
1906 for (i = 0; i < sz_skybg; i++) {
1907 cpl_table_set_double(sky_bg_tab, "SKY_BG", i,
1908 cpl_vector_get(sky_bg, i));
1909 }
1910
1911 skip_if(irplib_dfs_save_table(set, parlist, set, sky_bg_tab, NULL,
1912 RECIPE_STRING, ISAAC_IMG_JITTER_BG,
1913 qclist, NULL, PACKAGE "/" PACKAGE_VERSION,
1914 RECIPE_STRING "_bg" CPL_DFS_FITS));
1915 cpl_table_delete(sky_bg_tab);
1916 sky_bg_tab = NULL;
1917 }
1918
1919 /* Write the FITS table */
1920 if (objs_stats) {
1921 skip_if(irplib_dfs_save_table(set, parlist, set, objs_stats, NULL,
1922 RECIPE_STRING, ISAAC_IMG_JITTER_STARS,
1923 qclist, NULL, PACKAGE "/" PACKAGE_VERSION,
1924 RECIPE_STRING "_stars" CPL_DFS_FITS));
1925 }
1926
1927 bug_if(cpl_propertylist_append(plist, qclist));
1928 cpl_propertylist_empty(qclist);
1929
1930 /* PRO.CATG */
1931 cpl_propertylist_update_string(plist, CPL_DFS_PRO_CATG,
1932 ISAAC_IMG_JITTER_COMB);
1933
1934 /* Save the PAF file */
1935 skip_if (cpl_dfs_save_paf("ISAAC", RECIPE_STRING, plist,
1936 RECIPE_STRING CPL_DFS_PAF));
1937
1938 end_skip;
1939
1940 cpl_propertylist_delete(plist);
1941 cpl_propertylist_delete(qclist);
1942 cpl_table_delete(sky_bg_tab);
1943
1944 return cpl_error_get_code();
1945}
int isaac_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: isaac_dfs.c:60
double isaac_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
Definition: isaac_pfits.c:305
double isaac_pfits_get_pixscale(const cpl_propertylist *plist)
find out the pixel scale
Definition: isaac_pfits.c:745
double isaac_pfits_get_cumoffsety(const cpl_propertylist *plist)
find out the cumulative offset in Y
Definition: isaac_pfits.c:211
const char * isaac_pfits_get_frame_type(const cpl_propertylist *plist)
find out the frame type
Definition: isaac_pfits.c:286
double isaac_pfits_get_cumoffsetx(const cpl_propertylist *plist)
find out the cumulative offset in X
Definition: isaac_pfits.c:196
cpl_frameset * isaac_extract_frameset(const cpl_frameset *self, const char *tag)
Extract the frames with the given tag from a frameset.
Definition: isaac_utils.c:356
cpl_image * isaac_oddeven_correct(const cpl_image *in)
Correct the odd/even in an image.
Definition: isaac_utils.c:275
const char * isaac_extract_filename(const cpl_frameset *self, const char *tag)
Extract the filename of the first frame of the given tag.
Definition: isaac_utils.c:397