36 #include "naco_recipe.h"
37 #include "irplib_distortion.h"
47 #define RECIPE_STRING "naco_spc_combine"
54 static cpl_error_code naco_spc_combine_qc(cpl_propertylist *,
56 const irplib_framelist *);
58 static cpl_error_code naco_spc_combine_save(cpl_frameset *,
59 const cpl_parameterlist *,
60 const cpl_propertylist *,
61 const cpl_propertylist *,
65 const cpl_imagelist *,
66 const irplib_framelist *);
68 static cpl_error_code naco_framelist_fill_onoff_offset(cpl_vector *,
70 const irplib_framelist *);
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",
77 " -- NACO Combination of spectroscopic science data.\n"
78 "The files listed in the Set Of Frames (sof-file) "
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 "
90 "For each " NACO_SPC_JITTER_RAW
" frame a "
91 "NACO-raw-file.fits " NACO_SPC_JITTER_SKY
"may be "
113 static int naco_spc_combine(cpl_frameset * framelist,
114 const cpl_parameterlist * parlist)
116 cpl_errorstate cleanstate = cpl_errorstate_get();
117 irplib_framelist * allframes = NULL;
118 irplib_framelist * rawframes = NULL;
119 irplib_framelist * skyframes = NULL;
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;
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);
152 skip_if(allframes == NULL);
156 NACO_SPC_JITTER_RAW
")$",
158 skip_if(rawframes == NULL);
161 IRPLIB_PFITS_WCS_REGEXP
"|"
162 NACO_PFITS_REGEXP_SPC_COMBINE_PAF
165 nx = irplib_pfits_get_int
167 ny = irplib_pfits_get_int
170 error_if(xtmax > nx, CPL_ERROR_ILLEGAL_INPUT,
171 "xtmax=%d exceeds the image size of %d", xtmax, nx);
174 NACO_PFITS_REGEXP_SPC_COMBINE
181 flatimg = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0);
182 skip_if (flatimg == NULL);
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);
192 if (cpl_frameset_find(framelist, NACO_SPC_JITTER_RAW)) {
196 skip_if (cpl_frameset_find(framelist, NACO_SPC_NOD_RAW));
198 if (skyframes == NULL) {
199 irplib_error_recover(cleanstate,
"No sky frames");
203 NACO_PFITS_REGEXP_SPC_COMBINE
212 skip_if (cpl_frameset_find(framelist, NACO_SPC_JITTER_RAW));
215 bug_if(cpl_propertylist_append_int(onoffkeys,
216 NACO_PFITS_DOUBLE_CUMOFFSETX, 1));
220 npairs = cpl_imagelist_get_size(objimages);
223 CPL_ERROR_ILLEGAL_INPUT,
224 "The %d frames contain only %d pair(s) of on/off frames",
227 cpl_msg_info(cpl_func,
"Loaded %d nodded images", npairs);
230 cpl_msg_info(cpl_func,
"Flat-fielding %d nodded images", npairs);
231 skip_if(cpl_imagelist_divide_image(objimages, flatimg));
236 offcorr = cpl_bivector_new(2 * npairs);
237 offcorx = cpl_bivector_get_x(offcorr);
238 offcory = cpl_bivector_get_y(offcorr);
241 skip_if(naco_framelist_fill_onoff_offset(offcorx, offcory, rawframes));
246 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
247 cpl_bivector_dump(offcorr, stdout);
257 if (cpl_msg_get_level() <= CPL_MSG_INFO) {
258 cpl_bivector_dump(offcorr, stdout);
262 bug_if(cpl_vector_set(offcorx, 0, 0.0));
263 bug_if(cpl_vector_set(offcory, 0, 0.0));
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);
273 cpl_errorstate prestate = cpl_errorstate_get();
274 cpl_image * img1d = cpl_image_collapse_window_create(saapair[0], xtmin, 1,
277 cpl_plot_image_col(
"set grid;",
"t '1D-Spectrum' w linespoints",
"",
280 cpl_image_delete(img1d);
282 img1d = cpl_image_collapse_window_create(saapair[0], xtmin, 1, xtmax,
285 cpl_plot_image_row(
"set grid;",
"t '1D-Profile' w linespoints",
"",
288 cpl_image_delete(img1d);
289 if (!cpl_errorstate_is_equal(prestate)) {
290 cpl_errorstate_set(prestate);
294 stats = cpl_stats_new_from_image(saapair[0], CPL_STATS_ALL);
295 bug_if(stats == NULL);
297 if (cpl_msg_get_level() <= CPL_MSG_INFO) {
298 cpl_stats_dump(stats, CPL_STATS_ALL, stdout);
301 skip_if(naco_spc_combine_qc(qclist, paflist, rawframes));
304 bug_if (cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
305 NACO_SPC_NOD_COMBINE));
307 skip_if(naco_spc_combine_save(framelist, parlist, qclist, paflist,
308 saapair[0], saapair[1], offcorr, objimages,
313 if (saapair != NULL) {
314 cpl_image_delete(saapair[0]);
315 cpl_image_delete(saapair[1]);
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);
326 cpl_propertylist_delete(onoffkeys);
327 cpl_propertylist_delete(qclist);
328 cpl_propertylist_delete(paflist);
330 return cpl_error_get_code();
343 static cpl_error_code naco_spc_combine_qc(cpl_propertylist * qclist,
344 cpl_propertylist * paflist,
345 const irplib_framelist * rawframes)
348 const cpl_propertylist * reflist
350 const char pafcopy[] =
"^(" NACO_PFITS_REGEXP_SPCWAVE_PAF
")$";
356 skip_if(filter == NULL);
358 bug_if(cpl_propertylist_append_string(qclist,
"ESO QC FILTER OBS", filter));
361 skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
363 skip_if (cpl_propertylist_append(paflist, qclist));
365 bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist,
"^("
366 IRPLIB_PFITS_WCS_REGEXP
"|"
367 IRPLIB_PFITS_REGEXP_RECAL_LAMP
371 return cpl_error_get_code();
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)
402 cpl_table * offtable = NULL;
403 cpl_propertylist * xtlist = cpl_propertylist_new();
406 bug_if(cpl_propertylist_append_string(xtlist,
"EXTNAME",
407 "Contribution Map"));
411 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
412 NACO_SPC_NOD_COMBINE, qclist, NULL,
413 naco_pipe_id, RECIPE_STRING CPL_DFS_FITS));
417 skip_if (cpl_image_save(contrib, RECIPE_STRING CPL_DFS_FITS,
418 CPL_BPP_16_UNSIGNED, xtlist, CPL_IO_EXTEND));
422 offtable = cpl_table_new(cpl_bivector_get_size(offcorr));
424 bug_if(cpl_table_wrap_double
425 (offtable, (
double*)cpl_bivector_get_x_data_const(offcorr),
428 bug_if(cpl_table_wrap_double
429 (offtable, (
double*)cpl_bivector_get_y_data_const(offcorr),
432 bug_if(cpl_table_set_column_unit(offtable,
"OFFSETX",
"pixel"));
433 bug_if(cpl_table_set_column_unit(offtable,
"OFFSETY",
"pixel"));
435 bug_if(cpl_propertylist_set_string(xtlist,
"EXTNAME",
436 "Image combination shifts"));
438 skip_if(cpl_table_save(offtable, NULL, xtlist, RECIPE_STRING CPL_DFS_FITS,
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));
455 skip_if (cpl_dfs_save_paf(
"NACO", RECIPE_STRING, paflist,
456 RECIPE_STRING CPL_DFS_PAF));
458 bug_if(paflist == NULL);
463 cpl_propertylist_delete(xtlist);
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);
472 return cpl_error_get_code();
494 cpl_error_code naco_framelist_fill_onoff_offset(cpl_vector * offset,
495 cpl_vector * offsety,
496 const irplib_framelist *
self)
503 skip_if (
self == NULL);
504 skip_if (offset == NULL);
507 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
509 bug_if(cpl_vector_set_size(offset, nframes));
511 if (offsety != NULL) {
513 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
514 bug_if(cpl_vector_set_size(offsety, nframes));
518 for (i = 0; i < nframes; i += 2) {
519 const cpl_propertylist * plist1
521 const cpl_propertylist * plist2
525 = irplib_pfits_get_double(plist1, NACO_PFITS_DOUBLE_CUMOFFSETX);
527 = irplib_pfits_get_double(plist2, NACO_PFITS_DOUBLE_CUMOFFSETX);
532 i1 = i/2 + nframes/2;
535 i0 = i/2 + nframes/2;
537 bug_if(cpl_vector_set(offset, i0, xoff1));
538 bug_if(cpl_vector_set(offset, i1, xoff2));
540 if (offsety != NULL) {
542 = irplib_pfits_get_double(plist1, NACO_PFITS_DOUBLE_CUMOFFSETY);
544 = irplib_pfits_get_double(plist2, NACO_PFITS_DOUBLE_CUMOFFSETY);
546 bug_if(cpl_vector_set(offsety, i0, yoff1));
547 bug_if(cpl_vector_set(offsety, i1, yoff2));
553 return cpl_error_get_code();
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.
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
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.
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.
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.
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.
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