IIINSTRUMENT Pipeline Reference Manual  6.2.2
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 
57 static int isaac_spc_flat_create(cpl_plugin *);
58 static int isaac_spc_flat_exec(cpl_plugin *);
59 static int isaac_spc_flat_destroy(cpl_plugin *);
60 static int isaac_spc_flat(cpl_parameterlist *, cpl_frameset *);
61 static cpl_image * isaac_spc_flat_reduce(cpl_frameset *);
62 static cpl_imagelist * isaac_spc_flat_diffs(cpl_frameset *);
63 static cpl_image * isaac_spc_flat_divide_fit(cpl_image *, int, int, int);
64 static int isaac_spc_flat_save(cpl_image *, int, cpl_frameset *,
65  cpl_parameterlist *, cpl_frameset *);
66 static int isaac_spc_flat_compare(const cpl_frame *, const cpl_frame *);
67 
68 /*-----------------------------------------------------------------------------
69  Static variables
70  -----------------------------------------------------------------------------*/
71 
72 static 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 
88 static 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 /*----------------------------------------------------------------------------*/
106 int 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 /*----------------------------------------------------------------------------*/
140 static 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 /*----------------------------------------------------------------------------*/
197 static 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 /*----------------------------------------------------------------------------*/
216 static 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 /*----------------------------------------------------------------------------*/
237 static 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 /*----------------------------------------------------------------------------*/
360 static 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 /*----------------------------------------------------------------------------*/
476 static 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 /*----------------------------------------------------------------------------*/
528 static 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 /*----------------------------------------------------------------------------*/
660 static 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 /*----------------------------------------------------------------------------*/
779 static 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_opti1_id(const cpl_propertylist *plist)
find out the OPTI1.ID key
Definition: isaac_pfits.c:700
double isaac_pfits_get_wlen(const cpl_propertylist *plist)
find out the central wavelength
Definition: isaac_pfits.c:865
const char * isaac_pfits_get_arm(const cpl_propertylist *plist)
find out the arm which is active
Definition: isaac_pfits.c:106
const char * isaac_pfits_get_resolution(const cpl_propertylist *plist)
find out the resolution
Definition: isaac_pfits.c:775
const char * isaac_pfits_get_filter(const cpl_propertylist *plist)
find out the filter
Definition: isaac_pfits.c:880
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