IIINSTRUMENT Pipeline Reference Manual 4.4.13
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
54static cpl_error_code naco_spc_combine_qc(cpl_propertylist *,
55 cpl_propertylist *,
56 const irplib_framelist *);
57
58static 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
68static cpl_error_code naco_framelist_fill_onoff_offset(cpl_vector *,
69 cpl_vector *,
70 const irplib_framelist *);
71
72NACO_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/*----------------------------------------------------------------------------*/
113static 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 {
201 skip_if(irplib_framelist_load_propertylist_all
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/*----------------------------------------------------------------------------*/
343static 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
349 = irplib_framelist_get_propertylist_const(rawframes, 0);
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/*----------------------------------------------------------------------------*/
389static 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/*----------------------------------------------------------------------------*/
493static
494cpl_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
520 = irplib_framelist_get_propertylist_const(self, i);
521 const cpl_propertylist * plist2
522 = irplib_framelist_get_propertylist_const(self, i+1);
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
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: naco_dfs.c:62
int naco_parameterlist_get_int(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO integer parameter.
const char * naco_pfits_get_filter(const cpl_propertylist *self)
find out the filter
Definition: naco_pfits.c:167
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
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 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