IIINSTRUMENT Pipeline Reference Manual 6.2.5
isaac_img_detlin.c
1/* $Id: isaac_img_detlin.c,v 1.31 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.31 $
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 <math.h>
37#include <cpl.h>
38
39#include "irplib_utils.h"
40
41#include "isaac_utils.h"
42#include "isaac_pfits.h"
43#include "isaac_dfs.h"
44#include "isaac_fit.h"
45
46/*-----------------------------------------------------------------------------
47 Functions prototypes
48 -----------------------------------------------------------------------------*/
49
50static int isaac_img_detlin_create(cpl_plugin *);
51static int isaac_img_detlin_exec(cpl_plugin *);
52static int isaac_img_detlin_destroy(cpl_plugin *);
53static int isaac_img_detlin(cpl_parameterlist *, cpl_frameset *);
54
55static cpl_imagelist * isaac_img_detlin_load(cpl_frameset *, cpl_frameset *,
56 double **);
57static int isaac_img_detlin_save(cpl_imagelist *, cpl_parameterlist *,
58 cpl_frameset *);
59
60/*-----------------------------------------------------------------------------
61 Static variables
62 -----------------------------------------------------------------------------*/
63
64static struct {
65 /* Inputs */
66 int force_flag;
67
68 /* Outputs */
69 double lamp_stability;
70} isaac_img_detlin_config;
71
72static char isaac_img_detlin_description[] =
73"isaac_img_detlin -- ISAAC imaging detector linearity recipe.\n"
74"The files listed in the Set Of Frames (sof-file) must be tagged:\n"
75"raw-file.fits "ISAAC_IMG_DETLIN_LAMP_RAW" or\n"
76"raw-file.fits "ISAAC_IMG_DETLIN_DARK_RAW"\n";
77
78/*-----------------------------------------------------------------------------
79 Functions code
80 -----------------------------------------------------------------------------*/
81
82/*----------------------------------------------------------------------------*/
90/*----------------------------------------------------------------------------*/
91int cpl_plugin_get_info(cpl_pluginlist * list)
92{
93 cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe));
94 cpl_plugin * plugin = &recipe->interface;
95
96 cpl_plugin_init(plugin,
97 CPL_PLUGIN_API,
98 ISAAC_BINARY_VERSION,
99 CPL_PLUGIN_TYPE_RECIPE,
100 "isaac_img_detlin",
101 "Detector linearity recipe",
102 isaac_img_detlin_description,
103 "Lars Lundin",
104 PACKAGE_BUGREPORT,
106 isaac_img_detlin_create,
107 isaac_img_detlin_exec,
108 isaac_img_detlin_destroy);
109
110 cpl_pluginlist_append(list, plugin);
111
112 return 0;
113}
114
115/*----------------------------------------------------------------------------*/
124/*----------------------------------------------------------------------------*/
125static int isaac_img_detlin_create(cpl_plugin * plugin)
126{
127 cpl_recipe * recipe;
128 cpl_parameter * p;
129
130 /* Get the recipe out of the plugin */
131 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
132 recipe = (cpl_recipe *)plugin;
133 else return CPL_ERROR_UNSPECIFIED;
134
135 /* Create the parameters list in the cpl_recipe object */
136 recipe->parameters = cpl_parameterlist_new();
137
138 /* Fill the parameters list */
139 /* --force */
140 p = cpl_parameter_new_value("isaac.isaac_img_detlin.force", CPL_TYPE_BOOL,
141 "flag to force th computation", "isaac.isaac_img_detlin",
142 FALSE);
143 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "force");
144 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
145 cpl_parameterlist_append(recipe->parameters, p);
146
147 /* Return */
148 return 0;
149}
150
151/*----------------------------------------------------------------------------*/
157/*----------------------------------------------------------------------------*/
158static int isaac_img_detlin_exec(cpl_plugin * plugin)
159{
160 cpl_recipe * recipe;
161
162 /* Get the recipe out of the plugin */
163 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
164 recipe = (cpl_recipe *)plugin;
165 else return CPL_ERROR_UNSPECIFIED;
166
167 return isaac_img_detlin(recipe->parameters, recipe->frames);
168}
169
170/*----------------------------------------------------------------------------*/
176/*----------------------------------------------------------------------------*/
177static int isaac_img_detlin_destroy(cpl_plugin * plugin)
178{
179 cpl_recipe * recipe;
180
181 /* Get the recipe out of the plugin */
182 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
183 recipe = (cpl_recipe *)plugin;
184 else return CPL_ERROR_UNSPECIFIED;
185
186 cpl_parameterlist_delete(recipe->parameters);
187 return 0;
188}
189
190/*----------------------------------------------------------------------------*/
197/*----------------------------------------------------------------------------*/
198static int isaac_img_detlin(
199 cpl_parameterlist * parlist,
200 cpl_frameset * framelist)
201{
202 cpl_parameter * par;
203 cpl_frameset * darkframes;
204 cpl_frameset * lampframes;
205 cpl_imagelist * iset;
206 double * ditval;
207 cpl_imagelist * fitres;
208
209 /* Initialise */
210 par = NULL;
211
212 /* Retrieve input parameters */
213 /* Force flag */
214 par = cpl_parameterlist_find(parlist, "isaac.isaac_img_detlin.force");
215 isaac_img_detlin_config.force_flag = cpl_parameter_get_bool(par);
216
217 /* Identify the RAW and CALIB frames in the input frameset */
218 if (isaac_dfs_set_groups(framelist)) {
219 cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
220 return CPL_ERROR_UNSPECIFIED;
221 }
222
223 /* Retrieve raw frames */
224 if ((lampframes = isaac_extract_frameset(framelist,
225 ISAAC_IMG_DETLIN_LAMP_RAW)) == NULL) {
226 cpl_msg_error(cpl_func, "Cannot find any lamp frame in input");
227 return CPL_ERROR_UNSPECIFIED;
228 }
229 if ((darkframes = isaac_extract_frameset(framelist,
230 ISAAC_IMG_DETLIN_DARK_RAW)) == NULL) {
231 cpl_msg_error(cpl_func, "Cannot find any dark frame in input");
232 cpl_frameset_delete(lampframes);
233 return CPL_ERROR_UNSPECIFIED;
234 }
235
236 /* Load the data and check the DIT consistency */
237 cpl_msg_info(cpl_func, "Load the data");
238 cpl_msg_indent_more();
239 if ((iset = isaac_img_detlin_load(lampframes, darkframes, &ditval))==NULL) {
240 cpl_msg_error(cpl_func, "Cannot load the data");
241 cpl_frameset_delete(lampframes);
242 cpl_frameset_delete(darkframes);
243 cpl_msg_indent_less();
244 return CPL_ERROR_UNSPECIFIED;
245 }
246 cpl_frameset_delete(lampframes);
247 cpl_frameset_delete(darkframes);
248 cpl_msg_indent_less();
249
250 /* Compute the linearity coefficients */
251 cpl_msg_info(cpl_func, "Compute the linearity coefficients");
252 cpl_msg_indent_more();
253 if ((fitres = isaac_imagelist_fit_polynomial(iset, ditval, 3)) == NULL) {
254 cpl_msg_error(cpl_func, "Cannot compute the linearity coefficients");
255 cpl_imagelist_delete(iset);
256 cpl_free(ditval);
257 cpl_msg_indent_less();
258 return CPL_ERROR_UNSPECIFIED;
259 }
260 cpl_msg_indent_less();
261 cpl_free(ditval);
262 cpl_imagelist_delete(iset);
263
264 /* Save the products */
265 cpl_msg_info(cpl_func, "Save the products");
266 cpl_msg_indent_more();
267 if (isaac_img_detlin_save(fitres, parlist, framelist)==-1) {
268 cpl_msg_error(cpl_func, "Cannot save the products");
269 cpl_imagelist_delete(fitres);
270 cpl_msg_indent_less();
271 return CPL_ERROR_UNSPECIFIED;
272 }
273 cpl_msg_indent_less();
274
275 /* Free and return */
276 cpl_imagelist_delete(fitres);
277 return 0;
278}
279
280/*----------------------------------------------------------------------------*/
288/*----------------------------------------------------------------------------*/
289static cpl_imagelist * isaac_img_detlin_load(
290 cpl_frameset * lamps,
291 cpl_frameset * darks,
292 double ** ditvals)
293{
294 int nb_lamps;
295 cpl_vector * selection;
296 cpl_frame * frame;
297 cpl_propertylist * propertylist;
298 double dit_lamp, dit_dark;
299 int dit_stab;
300 cpl_imagelist * lamps_data;
301 cpl_imagelist * darks_data;
302 double * stab_levels;
303 double * dit_purged;
304 int i, j;
305
306 /* Check that there are as many lamp as darks */
307 if ((nb_lamps = cpl_frameset_get_size(lamps)) < 3) return NULL;
308 if (cpl_frameset_get_size(darks) != nb_lamps) return NULL;
309
310 /* Check out that they have consistent integration times */
311 cpl_msg_info(cpl_func, "Checking DIT consistency");
312 selection = cpl_vector_new(nb_lamps);
313 *ditvals = cpl_malloc(nb_lamps * sizeof(double));
314 dit_stab = 0;
315 for (i=0; i<nb_lamps; i++) {
316 /* Check if ok */
317 if (cpl_error_get_code()) {
318 cpl_vector_delete(selection);
319 cpl_free(*ditvals);
320 return NULL;
321 }
322 /* DIT from LAMP */
323 frame = cpl_frameset_get_position(lamps, i);
324 propertylist=cpl_propertylist_load(cpl_frame_get_filename(frame), 0);
325 dit_lamp = (double)isaac_pfits_get_dit(propertylist);
326 cpl_propertylist_delete(propertylist);
327 if (cpl_error_get_code()) {
328 cpl_msg_error(cpl_func, "Cannot get DIT");
329 cpl_vector_delete(selection);
330 cpl_free(*ditvals);
331 return NULL;
332 }
333 /* DIT from DARK */
334 frame = cpl_frameset_get_position(darks, i);
335 propertylist=cpl_propertylist_load(cpl_frame_get_filename(frame), 0);
336 dit_dark = (double)isaac_pfits_get_dit(propertylist);
337 cpl_propertylist_delete(propertylist);
338 if (cpl_error_get_code()) {
339 cpl_msg_error(cpl_func, "Cannot get DIT");
340 cpl_vector_delete(selection);
341 cpl_free(*ditvals);
342 return NULL;
343 }
344 /* Check consistency */
345 if (fabs(dit_dark-dit_lamp) > 1e-3) {
346 cpl_msg_error(cpl_func, "DIT not consistent between LAMP and DARK");
347 cpl_vector_delete(selection);
348 cpl_free(*ditvals);
349 return NULL;
350 }
351 (*ditvals)[i] = dit_lamp;
352 /* Set selection */
353 if (i==0) {
354 cpl_vector_set(selection, i, -1.0);
355 dit_stab ++;
356 } else {
357 if (fabs(dit_lamp - (*ditvals)[0]) < 1e-5) {
358 cpl_vector_set(selection, i, -1.0);
359 dit_stab ++;
360 } else {
361 cpl_vector_set(selection, i, 1.0);
362 }
363 }
364 }
365
366 /* Check if there are enough DITs for stability check */
367 if (dit_stab < 2) {
368 cpl_msg_error(cpl_func, "Not enough frames for stability check");
369 cpl_vector_delete(selection);
370 cpl_free(*ditvals);
371 return NULL;
372 }
373
374 /* Load the data and compute lamp-dark */
375 cpl_msg_info(cpl_func, "Compute the differences lamp - dark");
376 lamps_data = cpl_imagelist_load_frameset(lamps, CPL_TYPE_FLOAT, 1, 0);
377 darks_data = cpl_imagelist_load_frameset(darks, CPL_TYPE_FLOAT, 1, 0);
378 if (cpl_imagelist_subtract(lamps_data,darks_data) != CPL_ERROR_NONE) {
379 cpl_msg_error(cpl_func, "Cannot subtract the 2 image lists");
380 cpl_vector_delete(selection);
381 cpl_free(*ditvals);
382 if (lamps_data) cpl_imagelist_delete(lamps_data);
383 if (darks_data) cpl_imagelist_delete(darks_data);
384 return NULL;
385 }
386 cpl_imagelist_delete(darks_data);
387
388 /* Check the lamp stability */
389 cpl_msg_info(cpl_func, "Check the lamp stability");
390 stab_levels = cpl_malloc(dit_stab * sizeof(double));
391 j = 0;
392 for (i=0; i<nb_lamps; i++) {
393 if (cpl_vector_get(selection, i) < 0) {
394 stab_levels[j] =
395 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
396 j++;
397 }
398 }
399
400 /* Compute the lamp stability */
401 isaac_img_detlin_config.lamp_stability = 0.0;
402 for (i=1; i<dit_stab; i++) {
403 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
404 isaac_img_detlin_config.lamp_stability)
405 isaac_img_detlin_config.lamp_stability =
406 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
407 }
408 cpl_free(stab_levels);
409
410 /* Check the lamp stability */
411 if (isaac_img_detlin_config.lamp_stability > 0.01) {
412 if (isaac_img_detlin_config.force_flag == 1) {
413 cpl_msg_warning(cpl_func,
414 "level difference #%d too high - proceed anyway",i+1);
415 } else {
416 cpl_msg_error(cpl_func, "level difference #%d too high", i+1);
417 cpl_vector_delete(selection);
418 cpl_free(*ditvals);
419 cpl_imagelist_delete(lamps_data);
420 return NULL;
421 }
422 }
423
424 /* Purge the stability check data and DITs */
425 if (cpl_imagelist_erase(lamps_data, selection) != CPL_ERROR_NONE) {
426 cpl_msg_error(cpl_func, "cannot discard stability frames");
427 cpl_vector_delete(selection);
428 cpl_free(*ditvals);
429 cpl_imagelist_delete(lamps_data);
430 return NULL;
431 }
432 dit_purged = cpl_malloc(cpl_imagelist_get_size(lamps_data)*sizeof(double));
433 j = 0;
434 for (i=0; i<nb_lamps; i++) {
435 if (cpl_vector_get(selection, i) > 0) {
436 dit_purged[j] = (*ditvals)[i];
437 j++;
438 }
439 }
440 cpl_free(*ditvals);
441 *ditvals = dit_purged;
442
443 /* Free and eturn */
444 cpl_vector_delete(selection);
445 return lamps_data;
446}
447
448/*----------------------------------------------------------------------------*/
456/*----------------------------------------------------------------------------*/
457static int isaac_img_detlin_save(
458 cpl_imagelist * fitres,
459 cpl_parameterlist * parlist,
460 cpl_frameset * set)
461{
462 const cpl_frame * ref_frame;
463 cpl_propertylist * plist;
464 cpl_propertylist * qclist;
465 cpl_propertylist * paflist;
466 double qc_meda, qc_medb, qc_medc, qc_medq;
467
468 /* Compute the QC params */
469 qc_meda = cpl_image_get_median(cpl_imagelist_get(fitres, 0));
470 qc_medb = cpl_image_get_median(cpl_imagelist_get(fitres, 1));
471 qc_medc = cpl_image_get_median(cpl_imagelist_get(fitres, 2));
472 qc_medq = cpl_image_get_median(cpl_imagelist_get(fitres, 3));
473
474 /* Get the QC params in qclist */
475 qclist = cpl_propertylist_new();
476 cpl_propertylist_append_double(qclist, "ESO QC DETLIN MEDA", qc_meda);
477 cpl_propertylist_append_double(qclist, "ESO QC DETLIN MEDB", qc_medb);
478 cpl_propertylist_append_double(qclist, "ESO QC DETLIN MEDC", qc_medc);
479 cpl_propertylist_append_double(qclist, "ESO QC DETLIN MEDQ", qc_medq);
480 cpl_propertylist_append_double(qclist, "ESO QC DETLIN LAMP",
481 isaac_img_detlin_config.lamp_stability );
482
483 /* Write the _A FITS FILE */
484 irplib_dfs_save_image(set,
485 parlist,
486 set,
487 cpl_imagelist_get(fitres, 0),
488 CPL_BPP_IEEE_FLOAT,
489 "isaac_img_detlin",
490 ISAAC_IMG_DETLIN_A,
491 qclist,
492 NULL,
493 PACKAGE "/" PACKAGE_VERSION,
494 "isaac_img_detlin_A.fits");
495
496 /* Write the _B FITS FILE */
497 irplib_dfs_save_image(set,
498 parlist,
499 set,
500 cpl_imagelist_get(fitres, 1),
501 CPL_BPP_IEEE_FLOAT,
502 "isaac_img_detlin",
503 ISAAC_IMG_DETLIN_B,
504 qclist,
505 NULL,
506 PACKAGE "/" PACKAGE_VERSION,
507 "isaac_img_detlin_B.fits");
508
509 /* Write the _C FITS FILE */
510 irplib_dfs_save_image(set,
511 parlist,
512 set,
513 cpl_imagelist_get(fitres, 2),
514 CPL_BPP_IEEE_FLOAT,
515 "isaac_img_detlin",
516 ISAAC_IMG_DETLIN_C,
517 qclist,
518 NULL,
519 PACKAGE "/" PACKAGE_VERSION,
520 "isaac_img_detlin_C.fits");
521
522 /* Write the _Q FITS FILE */
523 irplib_dfs_save_image(set,
524 parlist,
525 set,
526 cpl_imagelist_get(fitres, 3),
527 CPL_BPP_IEEE_FLOAT,
528 "isaac_img_detlin",
529 ISAAC_IMG_DETLIN_Q,
530 qclist,
531 NULL,
532 PACKAGE "/" PACKAGE_VERSION,
533 "isaac_img_detlin_Q.fits");
534
535 /* Get the reference frame */
536 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
537
538 /* Get FITS header from reference file */
539 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
540 0)) == NULL) {
541 cpl_msg_error(cpl_func, "getting header from reference frame");
542 cpl_propertylist_delete(qclist);
543 return CPL_ERROR_UNSPECIFIED;
544 }
545
546 /* Get the keywords for the paf file */
547 paflist = cpl_propertylist_new();
548 cpl_propertylist_copy_property_regexp(paflist, plist,
549 "^(ARCFILE|MJD-OBS|ESO TPL ID|DATE-OBS|ESO DET DIT|"
550 "ESO DET NDIT|ESO DET NCORRS|ESO DET MODE NAME)$", 0);
551 cpl_propertylist_delete(plist);
552
553 /* Copy the QC in paflist */
554 cpl_propertylist_copy_property_regexp(paflist, qclist, ".", 0);
555 cpl_propertylist_delete(qclist);
556
557 /* PRO.CATG */
558 cpl_propertylist_update_string(paflist, CPL_DFS_PRO_CATG,
559 ISAAC_IMG_DETLIN_A);
560
561 /* Save the PAF file */
562 cpl_dfs_save_paf("ISAAC",
563 "isaac_img_detlin",
564 paflist,
565 "isaac_img_detlin_QC.paf");
566 cpl_propertylist_delete(paflist);
567 return 0;
568}
569
int isaac_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: isaac_dfs.c:60
cpl_imagelist * isaac_imagelist_fit_polynomial(const cpl_imagelist *ilist, const double *dit, int deg)
Compute the non linearity of the detector.
Definition: isaac_fit.c:78
double isaac_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
Definition: isaac_pfits.c:305
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
const char * isaac_get_license(void)
Get the pipeline copyright and license.
Definition: isaac_utils.c:62