NACO Pipeline Reference Manual  4.4.0
naco_spc_combine.c
1 /* $Id: naco_spc_combine.c,v 1.28 2011-12-22 11:21:03 llundin Exp $
2  *
3  * This file is part of the NACO 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: 2011-12-22 11:21:03 $
24  * $Revision: 1.28 $
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 "naco_recipe.h"
37 #include "irplib_distortion.h"
38 
39 #include "naco_spc.h"
40 
41 #include <string.h>
42 
43 /*-----------------------------------------------------------------------------
44  Recipe defines
45  -----------------------------------------------------------------------------*/
46 
47 #define RECIPE_STRING "naco_spc_combine"
48 
49 /*-----------------------------------------------------------------------------
50  Private Functions prototypes
51  -----------------------------------------------------------------------------*/
52 
53 
54 static cpl_error_code naco_spc_combine_qc(cpl_propertylist *,
55  cpl_propertylist *,
56  const irplib_framelist *);
57 
58 static cpl_error_code naco_spc_combine_save(cpl_frameset *,
59  const cpl_parameterlist *,
60  const cpl_propertylist *,
61  const cpl_propertylist *,
62  const cpl_image *,
63  const cpl_image *,
64  const cpl_bivector *,
65  const cpl_imagelist *,
66  const irplib_framelist *);
67 
68 static cpl_error_code naco_framelist_fill_onoff_offset(cpl_vector *,
69  cpl_vector *,
70  const irplib_framelist *);
71 
72 NACO_RECIPE_DEFINE(naco_spc_combine,
73  NACO_PARAM_XTMIN | NACO_PARAM_XTMAX |
74  NACO_PARAM_PLOT | NACO_PARAM_SAVE,
75  "Combination of spectroscopic science data",
76  RECIPE_STRING
77  " -- NACO Combination of spectroscopic science data.\n"
78  "The files listed in the Set Of Frames (sof-file) "
79  "must be tagged:\n"
80  "NACO-raw-file.fits " NACO_SPC_NOD_RAW " or\n"
81  "NACO-flat-file.fits " NACO_CALIB_SPCFLAT " (optional).\n"
82  "For nodded frames (" NACO_SPC_NOD_RAW ") there must be "
83  "an identical number of exposures on each side of the "
84  "center, these pairs of nodded exposures should preferably "
85  "be taken with one immediately after the other. More "
86  "precisely, the i'th A-FRAME will be paired with the i'th "
87  "B-frame");
88 
89 #if 0
90  "For each " NACO_SPC_JITTER_RAW " frame a "
91  "NACO-raw-file.fits " NACO_SPC_JITTER_SKY "may be "
92  "provided as well.\n"
93 #endif
94 
95 /*----------------------------------------------------------------------------*/
99 /*----------------------------------------------------------------------------*/
100 
101 /*-----------------------------------------------------------------------------
102  Functions code
103  -----------------------------------------------------------------------------*/
104 
105 /*----------------------------------------------------------------------------*/
112 /*----------------------------------------------------------------------------*/
113 static int naco_spc_combine(cpl_frameset * framelist,
114  const cpl_parameterlist * parlist)
115 {
116  cpl_errorstate cleanstate = cpl_errorstate_get();
117  irplib_framelist * allframes = NULL;
118  irplib_framelist * rawframes = NULL;
119  irplib_framelist * skyframes = NULL;
120  const char * flat;
121  cpl_image * flatimg = NULL;
122  cpl_propertylist * qclist = cpl_propertylist_new();
123  cpl_propertylist * paflist = cpl_propertylist_new();
124  cpl_propertylist * onoffkeys = cpl_propertylist_new();
125  cpl_imagelist * objimages = cpl_imagelist_new();
126  cpl_imagelist * offimages = cpl_imagelist_new();
127  cpl_stats * stats = NULL;
128  cpl_bivector * offcorr = NULL;
129  cpl_image ** saapair = NULL;
130  cpl_vector * offcorx;
131  cpl_vector * offcory;
132  int npairs;
133  int nx, ny;
134  const int nplot
135  = naco_parameterlist_get_int(parlist, RECIPE_STRING, NACO_PARAM_PLOT);
136  const int xtmin
137  = naco_parameterlist_get_int(parlist, RECIPE_STRING, NACO_PARAM_XTMIN);
138  const int xtmax
139  = naco_parameterlist_get_int(parlist, RECIPE_STRING, NACO_PARAM_XTMAX);
140 
141 
142  skip_if(0);
143  error_if(xtmin < 1, CPL_ERROR_ILLEGAL_INPUT,
144  "xtmin=%d is less than 1", xtmin);
145  error_if(xtmin > xtmax, CPL_ERROR_ILLEGAL_INPUT,
146  "xtmin = %d is greater than xtmax=%d", xtmin, xtmax);
147 
148  /* Identify the RAW and CALIB frames in the input frameset */
149  skip_if (naco_dfs_set_groups(framelist));
150 
151  allframes = irplib_framelist_cast(framelist);
152  skip_if(allframes == NULL);
153 
154  rawframes = irplib_framelist_extract_regexp(allframes, "^("
155  NACO_SPC_NOD_RAW "|"
156  NACO_SPC_JITTER_RAW ")$",
157  CPL_FALSE);
158  skip_if(rawframes == NULL);
159 
160  skip_if(irplib_framelist_load_propertylist(rawframes, 0, 0, "^("
161  IRPLIB_PFITS_WCS_REGEXP "|"
162  NACO_PFITS_REGEXP_SPC_COMBINE_PAF
163  ")$", CPL_FALSE));
164 
165  nx = irplib_pfits_get_int
166  (irplib_framelist_get_propertylist_const(rawframes, 0), "NAXIS1");
167  ny = irplib_pfits_get_int
168  (irplib_framelist_get_propertylist_const(rawframes, 0), "NAXIS2");
169 
170  error_if(xtmax > nx, CPL_ERROR_ILLEGAL_INPUT,
171  "xtmax=%d exceeds the image size of %d", xtmax, nx);
172 
173  skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
174  NACO_PFITS_REGEXP_SPC_COMBINE
175  ")$", CPL_FALSE));
176 
177  /* Optional flatfield calibration file */
178  flat = irplib_frameset_find_file(framelist, NACO_CALIB_SPCFLAT);
179 
180  if (flat != NULL) {
181  flatimg = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0);
182  skip_if (flatimg == NULL);
183 
184  error_if(cpl_image_get_size_x(flatimg) != nx,
185  CPL_ERROR_INCOMPATIBLE_INPUT, "Flat image has NAXIS1=%d, not "
186  "%d", (int)cpl_image_get_size_x(flatimg), nx);
187  error_if(cpl_image_get_size_y(flatimg) != ny,
188  CPL_ERROR_INCOMPATIBLE_INPUT, "Flat image has NAXIS2=%d, not "
189  "%d", (int)cpl_image_get_size_y(flatimg), ny);
190  }
191 
192  if (cpl_frameset_find(framelist, NACO_SPC_JITTER_RAW)) {
193 
194  /* Jittered frames processed here */
195 
196  skip_if (cpl_frameset_find(framelist, NACO_SPC_NOD_RAW));
197  skyframes = irplib_framelist_extract(allframes, NACO_SPC_JITTER_SKY);
198  if (skyframes == NULL) {
199  irplib_error_recover(cleanstate, "No sky frames");
200  } else {
202  (skyframes, 0, "^("
203  NACO_PFITS_REGEXP_SPC_COMBINE
204  ")$", CPL_FALSE));
205  }
206 
207  bug_if(1);
208  } else {
209 
210  /* Nodded frames processed here */
211 
212  skip_if (cpl_frameset_find(framelist, NACO_SPC_JITTER_RAW));
213 
214  /* On-frames have positive CUMOFFSETX, off-frames have negative */
215  bug_if(cpl_propertylist_append_int(onoffkeys,
216  NACO_PFITS_DOUBLE_CUMOFFSETX, 1));
217 
218  skip_if(naco_imagelist_load_diff(objimages, rawframes, onoffkeys));
219 
220  npairs = cpl_imagelist_get_size(objimages);
221 
222  error_if(2 * npairs < irplib_framelist_get_size(rawframes),
223  CPL_ERROR_ILLEGAL_INPUT,
224  "The %d frames contain only %d pair(s) of on/off frames",
225  irplib_framelist_get_size(rawframes), npairs);
226 
227  cpl_msg_info(cpl_func, "Loaded %d nodded images", npairs);
228 
229  if (flatimg) {
230  cpl_msg_info(cpl_func, "Flat-fielding %d nodded images", npairs);
231  skip_if(cpl_imagelist_divide_image(objimages, flatimg));
232  }
233 
234  bug_if(naco_imagelist_append_invert(objimages));
235 
236  offcorr = cpl_bivector_new(2 * npairs);
237  offcorx = cpl_bivector_get_x(offcorr);
238  offcory = cpl_bivector_get_y(offcorr);
239 
240  /* The same reordering is done for the offsets */
241  skip_if(naco_framelist_fill_onoff_offset(offcorx, offcory, rawframes));
242 
243 
244  }
245 
246  if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
247  cpl_bivector_dump(offcorr, stdout);
248  }
249 
250  skip_if(naco_vector_correlate_imagelist_1d(offcorx, offcorx, CPL_FALSE,
251  objimages));
252 
253  skip_if(naco_vector_correlate_imagelist_1d(offcory, offcory, CPL_TRUE,
254  objimages));
255 
256 
257  if (cpl_msg_get_level() <= CPL_MSG_INFO) {
258  cpl_bivector_dump(offcorr, stdout);
259  }
260 
261  /* The offset are relative to the 1st frame */
262  bug_if(cpl_vector_set(offcorx, 0, 0.0));
263  bug_if(cpl_vector_set(offcory, 0, 0.0));
264 
265  saapair = cpl_geom_img_offset_saa(objimages, offcorr, CPL_KERNEL_DEFAULT,
266  0, 0, CPL_GEOM_FIRST, NULL, NULL);
267  skip_if(saapair == NULL);
268 
269 
270  /* bug_if(cpl_image_threshold(saapair[0], 0.0, FLT_MAX, 0.0, 0.0)); */
271 
272  if (nplot > 0) {
273  cpl_errorstate prestate = cpl_errorstate_get();
274  cpl_image * img1d = cpl_image_collapse_window_create(saapair[0], xtmin, 1,
275  xtmax, ny, 1);
276 
277  cpl_plot_image_col("set grid;", "t '1D-Spectrum' w linespoints", "",
278  img1d, 1, 1, 1);
279 
280  cpl_image_delete(img1d);
281 
282  img1d = cpl_image_collapse_window_create(saapair[0], xtmin, 1, xtmax,
283  ny, 0);
284 
285  cpl_plot_image_row("set grid;", "t '1D-Profile' w linespoints", "",
286  img1d, 1, 1, 1);
287 
288  cpl_image_delete(img1d);
289  if (!cpl_errorstate_is_equal(prestate)) {
290  cpl_errorstate_set(prestate);
291  }
292  }
293 
294  stats = cpl_stats_new_from_image(saapair[0], CPL_STATS_ALL);
295  bug_if(stats == NULL);
296 
297  if (cpl_msg_get_level() <= CPL_MSG_INFO) {
298  cpl_stats_dump(stats, CPL_STATS_ALL, stdout);
299  }
300 
301  skip_if(naco_spc_combine_qc(qclist, paflist, rawframes));
302 
303  /* PRO.CATG */
304  bug_if (cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
305  NACO_SPC_NOD_COMBINE));
306 
307  skip_if(naco_spc_combine_save(framelist, parlist, qclist, paflist,
308  saapair[0], saapair[1], offcorr, objimages,
309  rawframes));
310 
311  end_skip;
312 
313  if (saapair != NULL) {
314  cpl_image_delete(saapair[0]);
315  cpl_image_delete(saapair[1]);
316  cpl_free(saapair);
317  }
318  cpl_bivector_delete(offcorr);
319  cpl_stats_delete(stats);
320  cpl_imagelist_delete(objimages);
321  cpl_imagelist_delete(offimages);
322  cpl_image_delete(flatimg);
323  irplib_framelist_delete(allframes);
324  irplib_framelist_delete(rawframes);
325  irplib_framelist_delete(skyframes);
326  cpl_propertylist_delete(onoffkeys);
327  cpl_propertylist_delete(qclist);
328  cpl_propertylist_delete(paflist);
329 
330  return cpl_error_get_code();
331 }
332 
333 
334 /*----------------------------------------------------------------------------*/
342 /*----------------------------------------------------------------------------*/
343 static cpl_error_code naco_spc_combine_qc(cpl_propertylist * qclist,
344  cpl_propertylist * paflist,
345  const irplib_framelist * rawframes)
346 {
347 
348  const cpl_propertylist * reflist
350  const char pafcopy[] = "^(" NACO_PFITS_REGEXP_SPCWAVE_PAF ")$";
351  const char * filter;
352 
353  bug_if (0);
354 
355  filter = naco_pfits_get_filter(reflist);
356  skip_if(filter == NULL);
357 
358  bug_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS", filter));
359 
360  /* THE PAF FILE FOR QC PARAMETERS */
361  skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
362  0));
363  skip_if (cpl_propertylist_append(paflist, qclist));
364 
365  bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
366  IRPLIB_PFITS_WCS_REGEXP "|"
367  IRPLIB_PFITS_REGEXP_RECAL_LAMP
368  ")$", 0));
369  end_skip;
370 
371  return cpl_error_get_code();
372 }
373 
374 /*----------------------------------------------------------------------------*/
388 /*----------------------------------------------------------------------------*/
389 static cpl_error_code naco_spc_combine_save(cpl_frameset * set_tot,
390  const cpl_parameterlist* parlist,
391  const cpl_propertylist * qclist,
392  const cpl_propertylist * paflist,
393  const cpl_image * combined,
394  const cpl_image * contrib,
395  const cpl_bivector * offcorr,
396  const cpl_imagelist * objimages,
397  const irplib_framelist * rawframes)
398 {
399  const int nsave
400  = naco_parameterlist_get_int(parlist, RECIPE_STRING, NACO_PARAM_SAVE);
401  cpl_frameset * proframes = irplib_frameset_cast(rawframes);
402  cpl_table * offtable = NULL;
403  cpl_propertylist * xtlist = cpl_propertylist_new();
404 
405  /* This will catch rawframes == NULL */
406  bug_if(cpl_propertylist_append_string(xtlist, "EXTNAME",
407  "Contribution Map"));
408 
409  /* The combined image */
410  skip_if (irplib_dfs_save_image(set_tot, parlist, proframes, combined,
411  CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
412  NACO_SPC_NOD_COMBINE, qclist, NULL,
413  naco_pipe_id, RECIPE_STRING CPL_DFS_FITS));
414 
415 
416  /* Append the contribution map */
417  skip_if (cpl_image_save(contrib, RECIPE_STRING CPL_DFS_FITS,
418  CPL_BPP_16_UNSIGNED, xtlist, CPL_IO_EXTEND));
419 
420 
421  /* Append the combination offsets as a table */
422  offtable = cpl_table_new(cpl_bivector_get_size(offcorr));
423  bug_if(0);
424  bug_if(cpl_table_wrap_double
425  (offtable, (double*)cpl_bivector_get_x_data_const(offcorr),
426  "OFFSETX"));
427 
428  bug_if(cpl_table_wrap_double
429  (offtable, (double*)cpl_bivector_get_y_data_const(offcorr),
430  "OFFSETY"));
431 
432  bug_if(cpl_table_set_column_unit(offtable, "OFFSETX", "pixel"));
433  bug_if(cpl_table_set_column_unit(offtable, "OFFSETY", "pixel"));
434 
435  bug_if(cpl_propertylist_set_string(xtlist, "EXTNAME",
436  "Image combination shifts"));
437 
438  skip_if(cpl_table_save(offtable, NULL, xtlist, RECIPE_STRING CPL_DFS_FITS,
439  CPL_IO_EXTEND));
440 
441  if (nsave > 0) {
442 
443  skip_if(irplib_dfs_save_imagelist(set_tot, parlist, proframes, objimages,
444  CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
445  NACO_SPC_NOD_SUBTRACT, qclist, NULL,
446  naco_pipe_id, RECIPE_STRING
447  "_subtracted" CPL_DFS_FITS));
448 
449 
450  }
451 
452 
453 #ifdef NACO_SAVE_PAF
454  /* The PAF */
455  skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, paflist,
456  RECIPE_STRING CPL_DFS_PAF));
457 #else
458  bug_if(paflist == NULL);
459 #endif
460 
461  end_skip;
462 
463  cpl_propertylist_delete(xtlist);
464 
465  cpl_frameset_delete(proframes);
466  if (offtable != NULL) {
467  (void)cpl_table_unwrap(offtable, "OFFSETX");
468  (void)cpl_table_unwrap(offtable, "OFFSETY");
469  cpl_table_delete(offtable);
470  }
471 
472  return cpl_error_get_code();
473 
474 }
475 
476 
477 /*----------------------------------------------------------------------------*/
492 /*----------------------------------------------------------------------------*/
493 static
494 cpl_error_code naco_framelist_fill_onoff_offset(cpl_vector * offset,
495  cpl_vector * offsety,
496  const irplib_framelist * self)
497 {
498  const int nframes = irplib_framelist_get_size(self);
499  int i;
500 
501 
502  skip_if (0);
503  skip_if (self == NULL);
504  skip_if (offset == NULL);
505 
506  skip_if (irplib_framelist_contains(self, NACO_PFITS_DOUBLE_CUMOFFSETX,
507  CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
508 
509  bug_if(cpl_vector_set_size(offset, nframes));
510 
511  if (offsety != NULL) {
512  skip_if (irplib_framelist_contains(self, NACO_PFITS_DOUBLE_CUMOFFSETY,
513  CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
514  bug_if(cpl_vector_set_size(offsety, nframes));
515  }
516 
517 
518  for (i = 0; i < nframes; i += 2) {
519  const cpl_propertylist * plist1
521  const cpl_propertylist * plist2
523 
524  const double xoff1
525  = irplib_pfits_get_double(plist1, NACO_PFITS_DOUBLE_CUMOFFSETX);
526  const double xoff2
527  = irplib_pfits_get_double(plist2, NACO_PFITS_DOUBLE_CUMOFFSETX);
528  int i0, i1;
529 
530  if (xoff1 > xoff2) {
531  i0 = i/2;
532  i1 = i/2 + nframes/2;
533  } else {
534  i1 = i/2;
535  i0 = i/2 + nframes/2;
536  }
537  bug_if(cpl_vector_set(offset, i0, xoff1));
538  bug_if(cpl_vector_set(offset, i1, xoff2));
539 
540  if (offsety != NULL) {
541  const double yoff1
542  = irplib_pfits_get_double(plist1, NACO_PFITS_DOUBLE_CUMOFFSETY);
543  const double yoff2
544  = irplib_pfits_get_double(plist2, NACO_PFITS_DOUBLE_CUMOFFSETY);
545 
546  bug_if(cpl_vector_set(offsety, i0, yoff1));
547  bug_if(cpl_vector_set(offsety, i1, yoff2));
548  }
549  }
550 
551  end_skip;
552 
553  return cpl_error_get_code();
554 
555 }
556 
cpl_frameset * irplib_frameset_cast(const irplib_framelist *self)
Create a CPL frameset from an irplib_framelist.
cpl_error_code naco_vector_correlate_imagelist_1d(cpl_vector *offset, const cpl_vector *goffset, cpl_boolean do_wave, const cpl_imagelist *self)
Use 1D cross-correlation to recompute the offsets in one direction.
Definition: naco_spc.c:96
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: naco_dfs.c:62
irplib_framelist * irplib_framelist_extract_regexp(const irplib_framelist *self, const char *regexp, cpl_boolean invert)
Extract the frames with the given tag from a framelist.
int naco_parameterlist_get_int(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO integer parameter.
const cpl_propertylist * irplib_framelist_get_propertylist_const(const irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
cpl_error_code naco_imagelist_append_invert(cpl_imagelist *self)
Fo each image append also its inverted.
Definition: naco_spc.c:300
cpl_error_code irplib_dfs_save_image(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_image *image, cpl_type_bpp bpp, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save an image as a DFS-compliant pipeline product.
Definition: irplib_utils.c:208
cpl_error_code irplib_framelist_load_propertylist_all(irplib_framelist *self, int ind, const char *regexp, cpl_boolean invert)
Load the propertylists of all frames in the framelist.
irplib_framelist * irplib_framelist_extract(const irplib_framelist *self, const char *tag)
Extract the frames with the given tag from a framelist.
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
cpl_error_code irplib_framelist_contains(const irplib_framelist *self, const char *key, cpl_type type, cpl_boolean is_equal, double fp_tol)
Verify that a property is present for all frames.
const char * irplib_frameset_find_file(const cpl_frameset *self, const char *tag)
Find the filename with the given tag in a frame set.
cpl_error_code naco_imagelist_load_diff(cpl_imagelist *self, const irplib_framelist *onofflist, const cpl_propertylist *onoffkeys)
Fill the list of difference images from on/off frames.
Definition: naco_spc.c:482
cpl_error_code irplib_framelist_load_propertylist(irplib_framelist *self, int pos, int ind, const char *regexp, cpl_boolean invert)
Load the propertylist of the specified frame in the framelist.
irplib_framelist * irplib_framelist_cast(const cpl_frameset *frameset)
Create an irplib_framelist from a cpl_framelist.
cpl_error_code irplib_dfs_save_imagelist(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_imagelist *imagelist, cpl_type_bpp bpp, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save an imagelist as a DFS-compliant pipeline product.
Definition: irplib_utils.c:303
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.
const char * naco_pfits_get_filter(const cpl_propertylist *self)
find out the filter
Definition: naco_pfits.c:167