IIINSTRUMENT Pipeline Reference Manual 6.2.5
isaac_spc_flat.c
1/* $Id: isaac_spc_flat.c,v 1.40 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.40 $
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_utils.h"
41
42#include "isaac_utils.h"
43#include "isaac_pfits.h"
44#include "isaac_dfs.h"
45
46/*-----------------------------------------------------------------------------
47 Defines
48 -----------------------------------------------------------------------------*/
49
50#define MEDIAN_XSIZE 200
51#define MEDIAN_YSIZE 200
52
53/*-----------------------------------------------------------------------------
54 Functions prototypes
55 -----------------------------------------------------------------------------*/
56
57static int isaac_spc_flat_create(cpl_plugin *);
58static int isaac_spc_flat_exec(cpl_plugin *);
59static int isaac_spc_flat_destroy(cpl_plugin *);
60static int isaac_spc_flat(cpl_parameterlist *, cpl_frameset *);
61static cpl_image * isaac_spc_flat_reduce(cpl_frameset *);
62static cpl_imagelist * isaac_spc_flat_diffs(cpl_frameset *);
63static cpl_image * isaac_spc_flat_divide_fit(cpl_image *, int, int, int);
64static int isaac_spc_flat_save(cpl_image *, int, cpl_frameset *,
65 cpl_parameterlist *, cpl_frameset *);
66static int isaac_spc_flat_compare(const cpl_frame *, const cpl_frame *);
67
68/*-----------------------------------------------------------------------------
69 Static variables
70 -----------------------------------------------------------------------------*/
71
72static struct {
73 /* Inputs */
74 double low_thresh;
75 double high_thresh;
76 int fit_order;
77 int fit_size;
78 int offset;
79 int llx;
80 int lly;
81 int urx;
82 int ury;
83 /* Outputs */
84 double med_stdev;
85 double med_avg;
86} isaac_spc_flat_config;
87
88static char isaac_spc_flat_description[] =
89"isaac_spc_flat -- ISAAC spectro flat-field creation.\n"
90"The files listed in the Set Of Frames (sof-file) must be tagged:\n"
91"raw-file.fits "ISAAC_SPC_FLAT_RAW"\n";
92
93/*-----------------------------------------------------------------------------
94 Functions code
95 -----------------------------------------------------------------------------*/
96
97/*----------------------------------------------------------------------------*/
105/*----------------------------------------------------------------------------*/
106int cpl_plugin_get_info(cpl_pluginlist * list)
107{
108 cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe));
109 cpl_plugin * plugin = &recipe->interface;
110
111 cpl_plugin_init(plugin,
112 CPL_PLUGIN_API,
113 ISAAC_BINARY_VERSION,
114 CPL_PLUGIN_TYPE_RECIPE,
115 "isaac_spc_flat",
116 "Spectro flat recipe",
117 isaac_spc_flat_description,
118 "Lars Lundin",
119 PACKAGE_BUGREPORT,
121 isaac_spc_flat_create,
122 isaac_spc_flat_exec,
123 isaac_spc_flat_destroy);
124
125 cpl_pluginlist_append(list, plugin);
126
127 return 0;
128}
129
130/*----------------------------------------------------------------------------*/
139/*----------------------------------------------------------------------------*/
140static int isaac_spc_flat_create(cpl_plugin * plugin)
141{
142 cpl_recipe * recipe;
143 cpl_parameter * p;
144
145 /* Get the recipe out of the plugin */
146 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
147 recipe = (cpl_recipe *)plugin;
148 else return CPL_ERROR_UNSPECIFIED;
149
150 /* Create the parameters list in the cpl_recipe object */
151 recipe->parameters = cpl_parameterlist_new();
152
153 /* Fill the parameters list */
154 /* --thresholds */
155 p = cpl_parameter_new_value("isaac.isaac_spc_flat.thresholds",
156 CPL_TYPE_STRING, "Low and high thresholds", "isaac.isaac_spc_flat",
157 "0.01,3.0");
158 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "thresholds");
159 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
160 cpl_parameterlist_append(recipe->parameters, p);
161 /* --fit_order */
162 p = cpl_parameter_new_value("isaac.isaac_spc_flat.fit_order", CPL_TYPE_INT,
163 "Order for the fit", "isaac.isaac_spc_flat", 3);
164 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fit_order");
165 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
166 cpl_parameterlist_append(recipe->parameters, p);
167 /* --fit_size */
168 p = cpl_parameter_new_value("isaac.isaac_spc_flat.fit_size", CPL_TYPE_INT,
169 "Size for the fit", "isaac.isaac_spc_flat", 200);
170 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fit_size");
171 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
172 cpl_parameterlist_append(recipe->parameters, p);
173 /* --offset */
174 p = cpl_parameter_new_value("isaac.isaac_spc_flat.offset", CPL_TYPE_INT,
175 "Offset", "isaac.isaac_spc_flat", 40);
176 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "offset");
177 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
178 cpl_parameterlist_append(recipe->parameters, p);
179 /* --zone */
180 p = cpl_parameter_new_value("isaac.isaac_spc_flat.zone",
181 CPL_TYPE_STRING, "Zone to consider", "isaac.isaac_spc_flat",
182 "256,256,768,768");
183 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "zone");
184 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
185 cpl_parameterlist_append(recipe->parameters, p);
186 /* Return */
187 return 0;
188}
189
190/*----------------------------------------------------------------------------*/
196/*----------------------------------------------------------------------------*/
197static int isaac_spc_flat_exec(cpl_plugin * plugin)
198{
199 cpl_recipe * recipe;
200
201 /* Get the recipe out of the plugin */
202 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
203 recipe = (cpl_recipe *)plugin;
204 else return CPL_ERROR_UNSPECIFIED;
205
206 return isaac_spc_flat(recipe->parameters, recipe->frames);
207}
208
209/*----------------------------------------------------------------------------*/
215/*----------------------------------------------------------------------------*/
216static int isaac_spc_flat_destroy(cpl_plugin * plugin)
217{
218 cpl_recipe * recipe;
219
220 /* Get the recipe out of the plugin */
221 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
222 recipe = (cpl_recipe *)plugin;
223 else return CPL_ERROR_UNSPECIFIED;
224
225 cpl_parameterlist_delete(recipe->parameters);
226 return 0;
227}
228
229/*----------------------------------------------------------------------------*/
236/*----------------------------------------------------------------------------*/
237static int isaac_spc_flat(
238 cpl_parameterlist * parlist,
239 cpl_frameset * framelist)
240{
241 const char * sval;
242 cpl_parameter * par;
243 cpl_size * labels;
244 cpl_size nlabels;
245 cpl_frameset * flatframes;
246 cpl_frameset * flat_one;
247 cpl_image * spflat;
248 int i;
249 cpl_boolean did_reduce = CPL_FALSE;
250
251 /* Initialise */
252 par = NULL;
253 isaac_spc_flat_config.med_stdev = 0.0;
254 isaac_spc_flat_config.med_avg = 0.0;
255
256 /* Retrieve input parameters */
257 /* --thresholds */
258 par = cpl_parameterlist_find(parlist, "isaac.isaac_spc_flat.thresholds");
259 sval = cpl_parameter_get_string(par);
260 if (sscanf(sval, "%lg,%lg",
261 &isaac_spc_flat_config.low_thresh,
262 &isaac_spc_flat_config.high_thresh)!=2) {
263 return CPL_ERROR_UNSPECIFIED;
264 }
265 /* --fit_order */
266 par = cpl_parameterlist_find(parlist, "isaac.isaac_spc_flat.fit_order");
267 isaac_spc_flat_config.fit_order = cpl_parameter_get_int(par);
268 /* --fit_size */
269 par = cpl_parameterlist_find(parlist, "isaac.isaac_spc_flat.fit_size");
270 isaac_spc_flat_config.fit_size = cpl_parameter_get_int(par);
271 /* --offset */
272 par = cpl_parameterlist_find(parlist, "isaac.isaac_spc_flat.offset");
273 isaac_spc_flat_config.offset = cpl_parameter_get_int(par);
274 /* --zone */
275 par = cpl_parameterlist_find(parlist, "isaac.isaac_spc_flat.zone");
276 sval = cpl_parameter_get_string(par);
277 if (sscanf(sval, "%d,%d,%d,%d",
278 &isaac_spc_flat_config.llx,
279 &isaac_spc_flat_config.lly,
280 &isaac_spc_flat_config.urx,
281 &isaac_spc_flat_config.ury)!=4) {
282 return CPL_ERROR_UNSPECIFIED;
283 }
284
285 /* Identify the RAW and CALIB frames in the input frameset */
286 if (isaac_dfs_set_groups(framelist)) {
287 cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
288 return CPL_ERROR_UNSPECIFIED;
289 }
290
291 /* Retrieve raw frames */
292 if ((flatframes = isaac_extract_frameset(framelist,
293 ISAAC_SPC_FLAT_RAW)) == NULL) {
294 cpl_msg_error(cpl_func, "Cannot find flat frames in the input list");
295 return CPL_ERROR_UNSPECIFIED;
296 }
297
298 /* The number of frames must be even */
299 if (cpl_frameset_get_size(flatframes) % 2) {
300 cpl_msg_error(cpl_func, "An even nb of frames expected in input");
301 cpl_frameset_delete(flatframes);
302 return CPL_ERROR_UNSPECIFIED;
303 }
304
305 /* Labelise all input frames */
306 if ((labels = cpl_frameset_labelise(flatframes, isaac_spc_flat_compare,
307 &nlabels)) == NULL) {
308 cpl_msg_error(cpl_func, "Cannot labelise input frames");
309 cpl_frameset_delete(flatframes);
310 return CPL_ERROR_UNSPECIFIED;
311 }
312
313 /* Extract settings and reduce each of them */
314 for (i=0; i<nlabels; i++) {
315 cpl_errorstate prestate = cpl_errorstate_get();
316
317 /* Reduce data set nb i */
318 cpl_msg_info(cpl_func, "Reduce data set no %d out of %d", i+1,
319 (int)nlabels);
320 cpl_msg_indent_more();
321 flat_one = cpl_frameset_extract(flatframes, labels, i);
322 spflat = isaac_spc_flat_reduce(flat_one);
323 cpl_msg_indent_less();
324
325 /* Save the products */
326 cpl_msg_info(cpl_func, "Save the products");
327 cpl_msg_indent_more();
328 if (!cpl_errorstate_is_equal(prestate)) {
329 cpl_image_delete(spflat);
330 irplib_error_recover(prestate, "Could not reduce set %d/%d", 1+i,
331 (int)nlabels);
332 } else if (spflat == NULL) {
333 cpl_msg_warning(cpl_func, "Cannot reduce set nb %d", i+1);
334 } else {
335 isaac_spc_flat_save(spflat, i+1, flat_one, parlist, framelist);
336 cpl_image_delete(spflat);
337 did_reduce = CPL_TRUE;
338 }
339 cpl_msg_indent_less();
340 cpl_frameset_delete(flat_one);
341 }
342
343 /* Free and return */
344 cpl_frameset_delete(flatframes);
345 cpl_free(labels);
346
347 cpl_ensure_code(did_reduce, CPL_ERROR_ILLEGAL_INPUT);
348
349 return cpl_error_set_where(cpl_func); /* Propagate error, if any */
350}
351
352/*----------------------------------------------------------------------------*/
359/*----------------------------------------------------------------------------*/
360static cpl_image * isaac_spc_flat_reduce(cpl_frameset * flatframes)
361{
362 cpl_imagelist * diffs;
363 cpl_vector * medians;
364 double med, mean;
365 cpl_image * avg_ima;
366 cpl_image * fitted;
367 int nima, nx, ny;
368 int i;
369
370 /* Test entries */
371 if (flatframes == NULL) return NULL;
372
373 /* Load input image set */
374 cpl_msg_info(cpl_func, "Compute the difference images");
375 if ((diffs = isaac_spc_flat_diffs(flatframes)) == NULL) {
376 cpl_msg_error(cpl_func, "Cannot create the difference images");
377 return NULL;
378 }
379 nima = cpl_imagelist_get_size(diffs);
380 nx = cpl_image_get_size_x(cpl_imagelist_get(diffs, 0));
381 ny = cpl_image_get_size_y(cpl_imagelist_get(diffs, 0));
382
383 /* Compute medians on diff images */
384 cpl_msg_info(cpl_func, "Compute statistics on images");
385 cpl_msg_indent_more();
386 medians = cpl_vector_new(nima);
387
388 /* Compute some stats on input images */
389 for (i=0; i<nima; i++) {
390 med = cpl_image_get_median_window(cpl_imagelist_get(diffs, i),
391 (nx-MEDIAN_XSIZE)/2.0, (ny-MEDIAN_YSIZE)/2.0,
392 (nx+MEDIAN_XSIZE)/2.0, (ny+MEDIAN_YSIZE)/2.0);
393 if (cpl_vector_set(medians, i, med) != CPL_ERROR_NONE) {
394 cpl_msg_error(cpl_func, "Cannot compute the medians");
395 cpl_vector_delete(medians);
396 cpl_imagelist_delete(diffs);
397 cpl_msg_indent_less();
398 return NULL;
399 }
400 }
401
402 /* Compute stdev and mean of the medians */
403 isaac_spc_flat_config.med_avg = cpl_vector_get_mean(medians);
404 if (nima >= 2)
405 isaac_spc_flat_config.med_stdev=cpl_vector_get_stdev(medians);
406 cpl_vector_delete(medians);
407 cpl_msg_info(cpl_func, "Average of the medians: %g",
408 isaac_spc_flat_config.med_avg);
409 cpl_msg_info(cpl_func, "Standard deviation of the medians: %g",
410 isaac_spc_flat_config.med_stdev);
411 cpl_msg_indent_less();
412
413 /* Divide by the mean in the vig in the difference image */
414 cpl_msg_info(cpl_func, "Normalise the images");
415 for (i=0; i<nima; i++) {
416
417 /* Support for window readout */
418 if ((nx != 1024) || (ny != 1024)) {
419 mean = cpl_image_get_mean(cpl_imagelist_get(diffs, i));
420 } else {
421 mean = cpl_image_get_mean_window(cpl_imagelist_get(diffs, i),
422 isaac_spc_flat_config.llx, isaac_spc_flat_config.lly,
423 isaac_spc_flat_config.urx, isaac_spc_flat_config.ury);
424 }
425 if (cpl_image_divide_scalar(cpl_imagelist_get(diffs, i), mean) !=
426 CPL_ERROR_NONE) {
427 cpl_msg_error(cpl_func, "Cannot normalise the image");
428 cpl_imagelist_delete(diffs);
429 return NULL;
430 }
431 }
432
433 /* Replace by 0 the pixels whose value is <low and >high */
434 for (i=0; i<nima; i++) {
435 if (cpl_image_threshold(cpl_imagelist_get(diffs, i),
436 isaac_spc_flat_config.low_thresh,
437 isaac_spc_flat_config.high_thresh,
438 0.0, 0.0) != CPL_ERROR_NONE) {
439 cpl_msg_error(cpl_func, "Cannot threshold the image");
440 cpl_imagelist_delete(diffs);
441 return NULL;
442 }
443 }
444
445 /* Average the image list to one image */
446 cpl_msg_info(cpl_func, "Stack the images");
447 if ((avg_ima = cpl_imagelist_collapse_create(diffs)) == NULL) {
448 cpl_msg_error(cpl_func, "Cannot collapse the image list");
449 cpl_imagelist_delete(diffs);
450 return NULL;
451 }
452 cpl_imagelist_delete(diffs);
453
454 /* Divide the output image by the fit */
455 cpl_msg_info(cpl_func, "Divide by a fit");
456 if ((fitted = isaac_spc_flat_divide_fit(avg_ima,
457 isaac_spc_flat_config.fit_order,
458 isaac_spc_flat_config.fit_size,
459 isaac_spc_flat_config.offset)) == NULL) {
460 cpl_msg_error(cpl_func, "Cannot collapse the image list");
461 cpl_image_delete(avg_ima);
462 return NULL;
463 }
464 cpl_image_delete(avg_ima);
465
466 return fitted;
467}
468
469/*----------------------------------------------------------------------------*/
475/*----------------------------------------------------------------------------*/
476static cpl_imagelist * isaac_spc_flat_diffs(cpl_frameset * in)
477{
478 int nima;
479 cpl_imagelist * out;
480 cpl_image * in1;
481 cpl_image * in2;
482 cpl_frame * cur_frame;
483 int i;
484
485 /* Initialise */
486 nima = cpl_frameset_get_size(in);
487
488 /* Expect an even number of frames */
489 if (nima % 2) {
490 cpl_msg_error(cpl_func, "Odd nb of frames");
491 return NULL;
492 }
493
494 /* Create the output image list */
495 out = cpl_imagelist_new();
496
497 /* Loop on all pairs */
498 for (i=0; i<nima/2; i++) {
499 cur_frame = cpl_frameset_get_position(in, 2*i);
500 if ((in1 = cpl_image_load(cpl_frame_get_filename(cur_frame),
501 CPL_TYPE_FLOAT, 0, 0)) == NULL) {
502 cpl_msg_error(cpl_func, "Cannot load the image %d", 2*i);
503 cpl_imagelist_delete(out);
504 return NULL;
505 }
506 cur_frame = cpl_frameset_get_position(in, 2*i+1);
507 if ((in2 = cpl_image_load(cpl_frame_get_filename(cur_frame),
508 CPL_TYPE_FLOAT, 0, 0)) == NULL) {
509 cpl_msg_error(cpl_func, "Cannot load the image %d", 2*i+1);
510 cpl_image_delete(in1);
511 cpl_imagelist_delete(out);
512 return NULL;
513 }
514 cpl_image_subtract(in1, in2);
515 cpl_image_delete(in2);
516 cpl_imagelist_set(out, in1, i);
517 }
518 return out;
519}
520
521/*----------------------------------------------------------------------------*/
527/*----------------------------------------------------------------------------*/
528static cpl_image * isaac_spc_flat_divide_fit(
529 cpl_image * in,
530 int order,
531 int xsize,
532 int offset)
533{
534 int nx, ny;
535 int xstart, xend, ystart, yend;
536 cpl_image * collapsed;
537 float * pcollapsed;
538 cpl_image * extracted;
539 float * pextracted;
540 int nb_samples;
541 cpl_matrix * xvec;
542 cpl_vector * yvec;
543 cpl_polynomial * poly_fit;
544 cpl_polynomial * poly_2d;
545 cpl_image * fit_image;
546 cpl_image * out;
547 cpl_size power[2];
548 int i;
549 const cpl_size maxdeg1d = order - 1;
550 const cpl_boolean sampsym = CPL_TRUE; /* xvec is symmetric */
551
552 /* Test entries */
553 if (in == NULL) return NULL;
554
555 /* Initialise */
556 nx = cpl_image_get_size_x(in);
557 ny = cpl_image_get_size_y(in);
558
559 /* Determine the zone to extract */
560 xstart = (int)((nx - xsize)/2) + 1;
561 xend = xstart + xsize - 1;
562 if ((xstart<1) || (xend>nx)) {
563 cpl_msg_error(cpl_func, "bad X size specified");
564 return NULL;
565 }
566
567 /* Extract the central zone and collapse it */
568 if ((collapsed = cpl_image_collapse_window_create(in, xstart, 1, xend, ny,
569 1)) == NULL) {
570 cpl_msg_error(cpl_func, "Cannot collpase a part of the image");
571 return NULL;
572 }
573 pcollapsed = cpl_image_get_data_float(collapsed);
574
575 /* Find the 'valid' zone in the 1D image */
576 ystart = 1;
577 while ((fabs(pcollapsed[ystart-1]) < 1e-4) && (ystart < nx)) ystart++;
578 ystart += offset;
579
580 yend = ny;
581 while ((fabs(pcollapsed[yend-1]) <1e-4) && (yend > 1)) yend--;
582 yend -= offset;
583
584 if (ystart > yend) {
585 cpl_msg_error(cpl_func, "invalid coordinates of the zone to extract");
586 cpl_image_delete(collapsed);
587 return NULL;
588 }
589
590 /* Extract the 1D signal to fit */
591 if ((extracted = cpl_image_extract(collapsed, 1, ystart, 1, yend))==NULL) {
592 cpl_msg_error(cpl_func, "cannot extract 1D image");
593 cpl_image_delete(collapsed);
594 return NULL;
595 }
596 cpl_image_delete(collapsed);
597 pextracted = cpl_image_get_data_float(extracted);
598
599 /* Fit the polynomial */
600 nb_samples = cpl_image_get_size_y(extracted);
601 xvec = cpl_matrix_new(1, nb_samples);
602 yvec = cpl_vector_new(nb_samples);
603 for (i=0; i<nb_samples; i++) {
604 cpl_matrix_set(xvec, 0, i, (double)(ystart + i));
605 cpl_vector_set(yvec, i, (double)(pextracted[i] / xsize));
606 }
607 cpl_image_delete(extracted);
608 poly_fit = cpl_polynomial_new(1);
609 if (cpl_polynomial_fit(poly_fit, xvec, &sampsym, yvec, NULL, CPL_FALSE,
610 NULL, &maxdeg1d)) {
611 cpl_msg_error(cpl_func, "cannot fit the 1D signal");
612 cpl_matrix_delete(xvec);
613 cpl_vector_delete(yvec);
614 cpl_polynomial_delete(poly_fit);
615 return NULL;
616 }
617 cpl_matrix_delete(xvec);
618 cpl_vector_delete(yvec);
619
620 /* The polynomial for image generation must be 2d */
621 poly_2d = cpl_polynomial_new(2);
622 power[0] = 0; power[1] = 0;
623 cpl_polynomial_set_coeff(poly_2d, power,
624 cpl_polynomial_get_coeff(poly_fit, power + 1));
625 power[0] = 0; power[1] = 1;
626 cpl_polynomial_set_coeff(poly_2d, power,
627 cpl_polynomial_get_coeff(poly_fit, power + 1));
628 power[0] = 0; power[1] = 2;
629 cpl_polynomial_set_coeff(poly_2d, power,
630 cpl_polynomial_get_coeff(poly_fit, power + 1));
631 cpl_polynomial_delete(poly_fit);
632
633 /* Create the fit image */
634 fit_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
635 cpl_image_fill_polynomial(fit_image, poly_2d, 1.0, 1.0, 1.0, 1.0);
636 cpl_polynomial_delete(poly_2d);
637
638 /* Divide the input image by the polynomial image */
639 if ((out = cpl_image_divide_create(in, fit_image)) == NULL) {
640 cpl_msg_error(cpl_func, "cannot divide the images");
641 cpl_image_delete(fit_image);
642 return NULL;
643 }
644 cpl_image_delete(fit_image);
645
646 return out;
647}
648
649/*----------------------------------------------------------------------------*/
659/*----------------------------------------------------------------------------*/
660static int isaac_spc_flat_save(
661 cpl_image * flat,
662 int set_nb,
663 cpl_frameset * set,
664 cpl_parameterlist * parlist,
665 cpl_frameset * set_tot)
666{
667 cpl_propertylist * plist;
668 cpl_propertylist * qclist;
669 cpl_propertylist * paflist;
670 const cpl_frame * ref_frame;
671 const char * sval;
672 int arm;
673 const char * procat;
674 char * filename;
675
676 /* Get the QC params in qclist */
677 qclist = cpl_propertylist_new();
678
679 /* Get the reference frame */
680 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
681 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
682 0)) == NULL) {
683 cpl_msg_error(cpl_func, "getting header from reference frame");
684 cpl_propertylist_delete(qclist);
685 return CPL_ERROR_UNSPECIFIED;
686 }
687 /* Test the status */
688 if (cpl_error_get_code()) {
689 cpl_propertylist_delete(qclist);
690 cpl_propertylist_delete(plist);
691 return CPL_ERROR_UNSPECIFIED;
692 }
693 /* Get the arm used */
694 sval = isaac_pfits_get_arm(plist);
695 if (sval==NULL) {
696 cpl_msg_error(cpl_func, "Cannot get the arm used");
697 cpl_propertylist_delete(plist);
698 cpl_propertylist_delete(qclist);
699 return CPL_ERROR_UNSPECIFIED;
700 }
701 if (sval[0] == 'S') arm = 1;
702 else if (sval[0] == 'L') arm = 2;
703 else {
704 cpl_msg_error(cpl_func, "Unsupported arm");
705 cpl_propertylist_delete(plist);
706 cpl_propertylist_delete(qclist);
707 return CPL_ERROR_UNSPECIFIED;
708 }
709 sval = isaac_pfits_get_filter(plist);
710 if (cpl_error_get_code()) cpl_error_reset();
711 else cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS", sval);
712 cpl_propertylist_delete(plist);
713 cpl_propertylist_append_double(qclist, "ESO QC SPECFLAT NCOUNTS",
714 isaac_spc_flat_config.med_avg);
715 cpl_propertylist_append_double(qclist, "ESO QC SPECFLAT STDEV",
716 isaac_spc_flat_config.med_stdev);
717
718 /* Write the flat image */
719 procat = arm == 1 ? ISAAC_SPC_FLAT_SW_RES : ISAAC_SPC_FLAT_LW_RES;
720 filename = cpl_sprintf("isaac_spc_flat_set%02d.fits", set_nb);
721 irplib_dfs_save_image(set_tot,
722 parlist,
723 set,
724 flat,
725 CPL_BPP_IEEE_FLOAT,
726 "isaac_spc_flat",
727 procat,
728 qclist,
729 NULL,
730 PACKAGE "/" PACKAGE_VERSION,
731 filename);
732 cpl_free(filename);
733
734 /* Get the reference frame */
735 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
736
737 /* Get FITS header from reference file */
738 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
739 0)) == NULL) {
740 cpl_msg_error(cpl_func, "getting header from reference frame");
741 cpl_propertylist_delete(qclist);
742 return CPL_ERROR_UNSPECIFIED;
743 }
744
745 /* Get the keywords for the paf file */
746 paflist = cpl_propertylist_new();
747 cpl_propertylist_copy_property_regexp(paflist, plist,
748 "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
749 "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME|"
750 "ESO INS GRAT WLEN|ESO INS OPTI1 ID|ESO DET DIT|ESO INS LAMP3 SET)$",0);
751 cpl_propertylist_delete(plist);
752
753 /* Copy the QC in paflist */
754 cpl_propertylist_copy_property_regexp(paflist, qclist, ".", 0);
755 cpl_propertylist_delete(qclist);
756
757 /* PRO.CATG */
758 cpl_propertylist_update_string(paflist, CPL_DFS_PRO_CATG, procat);
759
760 /* Save the PAF file */
761 filename = cpl_sprintf("isaac_spc_flat_set%02d.paf", set_nb);
762 cpl_dfs_save_paf("ISAAC",
763 "isaac_spc_flat",
764 paflist,
765 filename);
766 cpl_free(filename);
767 cpl_propertylist_delete(paflist);
768 return 0;
769}
770
771/*----------------------------------------------------------------------------*/
778/*----------------------------------------------------------------------------*/
779static int isaac_spc_flat_compare(
780 const cpl_frame * frame1,
781 const cpl_frame * frame2)
782{
783 int comparison;
784 cpl_propertylist * plist1;
785 cpl_propertylist * plist2;
786 const char * sval1,
787 * sval2;
788 double dval1, dval2;
789
790 /* Test entries */
791 if (frame1==NULL || frame2==NULL) return CPL_ERROR_UNSPECIFIED;
792
793 /* Get property lists */
794 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),
795 0)) == NULL) {
796 cpl_msg_error(cpl_func, "getting header from reference frame");
797 return CPL_ERROR_UNSPECIFIED;
798 }
799 if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),
800 0)) == NULL) {
801 cpl_msg_error(cpl_func, "getting header from reference frame");
802 cpl_propertylist_delete(plist1);
803 return CPL_ERROR_UNSPECIFIED;
804 }
805
806 /* Test status */
807 if (cpl_error_get_code()) {
808 cpl_propertylist_delete(plist1);
809 cpl_propertylist_delete(plist2);
810 return CPL_ERROR_UNSPECIFIED;
811 }
812
813 comparison = 1;
814
815 /* Compare the slit used */
816 sval1 = isaac_pfits_get_opti1_id(plist1);
817 sval2 = isaac_pfits_get_opti1_id(plist2);
818 if (cpl_error_get_code()) {
819 cpl_msg_error(cpl_func, "cannot get the slit used");
820 cpl_propertylist_delete(plist1);
821 cpl_propertylist_delete(plist2);
822 return CPL_ERROR_UNSPECIFIED;
823 }
824 if (strcmp(sval1, sval2)) comparison = 0;
825
826 /* Compare the resolution */
827 sval1 = isaac_pfits_get_resolution(plist1);
828 sval2 = isaac_pfits_get_resolution(plist2);
829 if (cpl_error_get_code()) {
830 cpl_msg_error(cpl_func, "cannot get the resolution");
831 cpl_propertylist_delete(plist1);
832 cpl_propertylist_delete(plist2);
833 return CPL_ERROR_UNSPECIFIED;
834 }
835 if (strcmp(sval1, sval2)) comparison = 0;
836
837 /* Compare the central wavelength */
838 dval1 = isaac_pfits_get_wlen(plist1);
839 dval2 = isaac_pfits_get_wlen(plist2);
840 if (cpl_error_get_code()) {
841 cpl_msg_error(cpl_func, "cannot get the central wavelength");
842 cpl_propertylist_delete(plist1);
843 cpl_propertylist_delete(plist2);
844 return CPL_ERROR_UNSPECIFIED;
845 }
846 if (fabs(dval1-dval2) > 1e-4) comparison = 0;
847
848 cpl_propertylist_delete(plist1);
849 cpl_propertylist_delete(plist2);
850 return comparison;
851}
852
853
int isaac_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: isaac_dfs.c:60
const char * isaac_pfits_get_filter(const cpl_propertylist *plist)
find out the filter
Definition: isaac_pfits.c:880
const char * isaac_pfits_get_arm(const cpl_propertylist *plist)
find out the arm which is active
Definition: isaac_pfits.c:106
double isaac_pfits_get_wlen(const cpl_propertylist *plist)
find out the central wavelength
Definition: isaac_pfits.c:865
const char * isaac_pfits_get_opti1_id(const cpl_propertylist *plist)
find out the OPTI1.ID key
Definition: isaac_pfits.c:700
const char * isaac_pfits_get_resolution(const cpl_propertylist *plist)
find out the resolution
Definition: isaac_pfits.c:775
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