00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include "naco_recipe.h"
00037 #include "irplib_distortion.h"
00038
00039 #include "naco_spc.h"
00040
00041 #include <string.h>
00042
00043
00044
00045
00046
00047 #define RECIPE_STRING "naco_spc_combine"
00048
00049
00050
00051
00052
00053
00054 static cpl_error_code naco_spc_combine_qc(cpl_propertylist *,
00055 cpl_propertylist *,
00056 const irplib_framelist *);
00057
00058 static cpl_error_code naco_spc_combine_save(cpl_frameset *,
00059 const cpl_parameterlist *,
00060 const cpl_propertylist *,
00061 const cpl_propertylist *,
00062 const cpl_image *,
00063 const cpl_image *,
00064 const cpl_bivector *,
00065 const cpl_imagelist *,
00066 const irplib_framelist *);
00067
00068 static cpl_error_code naco_framelist_fill_onoff_offset(cpl_vector *,
00069 cpl_vector *,
00070 const irplib_framelist *);
00071
00072 NACO_RECIPE_DEFINE(naco_spc_combine,
00073 NACO_PARAM_XTMIN | NACO_PARAM_XTMAX |
00074 NACO_PARAM_PLOT | NACO_PARAM_SAVE,
00075 "Combination of spectroscopic science data",
00076 RECIPE_STRING
00077 " -- NACO Combination of spectroscopic science data.\n"
00078 "The files listed in the Set Of Frames (sof-file) "
00079 "must be tagged:\n"
00080 "NACO-raw-file.fits " NACO_SPC_NOD_RAW " or\n"
00081 "NACO-flat-file.fits " NACO_CALIB_SPCFLAT " (optional).\n"
00082 "For nodded frames (" NACO_SPC_NOD_RAW ") there must be "
00083 "an identical number of exposures on each side of the "
00084 "center, these pairs of nodded exposures should preferably "
00085 "be taken with one immediately after the other. More "
00086 "precisely, the i'th A-FRAME will be paired with the i'th "
00087 "B-frame");
00088
00089 #if 0
00090 "For each " NACO_SPC_JITTER_RAW " frame a "
00091 "NACO-raw-file.fits " NACO_SPC_JITTER_SKY "may be "
00092 "provided as well.\n"
00093 #endif
00094
00095
00099
00100
00101
00102
00103
00104
00105
00112
00113 static int naco_spc_combine(cpl_frameset * framelist,
00114 const cpl_parameterlist * parlist)
00115 {
00116 cpl_errorstate cleanstate = cpl_errorstate_get();
00117 irplib_framelist * allframes = NULL;
00118 irplib_framelist * rawframes = NULL;
00119 irplib_framelist * skyframes = NULL;
00120 const char * flat;
00121 cpl_image * flatimg = NULL;
00122 cpl_propertylist * qclist = cpl_propertylist_new();
00123 cpl_propertylist * paflist = cpl_propertylist_new();
00124 cpl_propertylist * onoffkeys = cpl_propertylist_new();
00125 cpl_imagelist * objimages = cpl_imagelist_new();
00126 cpl_imagelist * offimages = cpl_imagelist_new();
00127 cpl_stats * stats = NULL;
00128 cpl_bivector * offcorr = NULL;
00129 cpl_image ** saapair = NULL;
00130 cpl_vector * offcorx;
00131 cpl_vector * offcory;
00132 int npairs;
00133 int nx, ny;
00134 const int nplot
00135 = naco_parameterlist_get_int(parlist, RECIPE_STRING, NACO_PARAM_PLOT);
00136 const int xtmin
00137 = naco_parameterlist_get_int(parlist, RECIPE_STRING, NACO_PARAM_XTMIN);
00138 const int xtmax
00139 = naco_parameterlist_get_int(parlist, RECIPE_STRING, NACO_PARAM_XTMAX);
00140
00141
00142 skip_if(0);
00143 error_if(xtmin < 1, CPL_ERROR_ILLEGAL_INPUT,
00144 "xtmin=%d is less than 1", xtmin);
00145 error_if(xtmin > xtmax, CPL_ERROR_ILLEGAL_INPUT,
00146 "xtmin = %d is greater than xtmax=%d", xtmin, xtmax);
00147
00148
00149 skip_if (naco_dfs_set_groups(framelist));
00150
00151 allframes = irplib_framelist_cast(framelist);
00152 skip_if(allframes == NULL);
00153
00154 rawframes = irplib_framelist_extract_regexp(allframes, "^("
00155 NACO_SPC_NOD_RAW "|"
00156 NACO_SPC_JITTER_RAW ")$",
00157 CPL_FALSE);
00158 skip_if(rawframes == NULL);
00159
00160 skip_if(irplib_framelist_load_propertylist(rawframes, 0, 0, "^("
00161 IRPLIB_PFITS_WCS_REGEXP "|"
00162 NACO_PFITS_REGEXP_SPC_COMBINE_PAF
00163 ")$", CPL_FALSE));
00164
00165 nx = irplib_pfits_get_int
00166 (irplib_framelist_get_propertylist_const(rawframes, 0), "NAXIS1");
00167 ny = irplib_pfits_get_int
00168 (irplib_framelist_get_propertylist_const(rawframes, 0), "NAXIS2");
00169
00170 error_if(xtmax > nx, CPL_ERROR_ILLEGAL_INPUT,
00171 "xtmax=%d exceeds the image size of %d", xtmax, nx);
00172
00173 skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
00174 NACO_PFITS_REGEXP_SPC_COMBINE
00175 ")$", CPL_FALSE));
00176
00177
00178 flat = irplib_frameset_find_file(framelist, NACO_CALIB_SPCFLAT);
00179
00180 if (flat != NULL) {
00181 flatimg = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0);
00182 skip_if (flatimg == NULL);
00183
00184 error_if(cpl_image_get_size_x(flatimg) != nx,
00185 CPL_ERROR_INCOMPATIBLE_INPUT, "Flat image has NAXIS1=%d, not "
00186 "%d", (int)cpl_image_get_size_x(flatimg), nx);
00187 error_if(cpl_image_get_size_y(flatimg) != ny,
00188 CPL_ERROR_INCOMPATIBLE_INPUT, "Flat image has NAXIS2=%d, not "
00189 "%d", (int)cpl_image_get_size_y(flatimg), ny);
00190 }
00191
00192 if (cpl_frameset_find(framelist, NACO_SPC_JITTER_RAW)) {
00193
00194
00195
00196 skip_if (cpl_frameset_find(framelist, NACO_SPC_NOD_RAW));
00197 skyframes = irplib_framelist_extract(allframes, NACO_SPC_JITTER_SKY);
00198 if (skyframes == NULL) {
00199 irplib_error_recover(cleanstate, "No sky frames");
00200 } else {
00201 skip_if(irplib_framelist_load_propertylist_all
00202 (skyframes, 0, "^("
00203 NACO_PFITS_REGEXP_SPC_COMBINE
00204 ")$", CPL_FALSE));
00205 }
00206
00207 bug_if(1);
00208 } else {
00209
00210
00211
00212 skip_if (cpl_frameset_find(framelist, NACO_SPC_JITTER_RAW));
00213
00214
00215 bug_if(cpl_propertylist_append_int(onoffkeys,
00216 NACO_PFITS_DOUBLE_CUMOFFSETX, 1));
00217
00218 skip_if(naco_imagelist_load_diff(objimages, rawframes, onoffkeys));
00219
00220 npairs = cpl_imagelist_get_size(objimages);
00221
00222 error_if(2 * npairs < irplib_framelist_get_size(rawframes),
00223 CPL_ERROR_ILLEGAL_INPUT,
00224 "The %d frames contain only %d pair(s) of on/off frames",
00225 irplib_framelist_get_size(rawframes), npairs);
00226
00227 cpl_msg_info(cpl_func, "Loaded %d nodded images", npairs);
00228
00229 if (flatimg) {
00230 cpl_msg_info(cpl_func, "Flat-fielding %d nodded images", npairs);
00231 skip_if(cpl_imagelist_divide_image(objimages, flatimg));
00232 }
00233
00234 bug_if(naco_imagelist_append_invert(objimages));
00235
00236 offcorr = cpl_bivector_new(2 * npairs);
00237 offcorx = cpl_bivector_get_x(offcorr);
00238 offcory = cpl_bivector_get_y(offcorr);
00239
00240
00241 skip_if(naco_framelist_fill_onoff_offset(offcorx, offcory, rawframes));
00242
00243
00244 }
00245
00246 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00247 cpl_bivector_dump(offcorr, stdout);
00248 }
00249
00250 skip_if(naco_vector_correlate_imagelist_1d(offcorx, offcorx, CPL_FALSE,
00251 objimages));
00252
00253 skip_if(naco_vector_correlate_imagelist_1d(offcory, offcory, CPL_TRUE,
00254 objimages));
00255
00256
00257 if (cpl_msg_get_level() <= CPL_MSG_INFO) {
00258 cpl_bivector_dump(offcorr, stdout);
00259 }
00260
00261
00262 bug_if(cpl_vector_set(offcorx, 0, 0.0));
00263 bug_if(cpl_vector_set(offcory, 0, 0.0));
00264
00265 saapair = cpl_geom_img_offset_saa(objimages, offcorr, CPL_KERNEL_DEFAULT,
00266 0, 0, CPL_GEOM_FIRST, NULL, NULL);
00267 skip_if(saapair == NULL);
00268
00269
00270
00271
00272 if (nplot > 0) {
00273 cpl_errorstate prestate = cpl_errorstate_get();
00274 cpl_image * img1d = cpl_image_collapse_window_create(saapair[0], xtmin, 1,
00275 xtmax, ny, 1);
00276
00277 cpl_plot_image_col("set grid;", "t '1D-Spectrum' w linespoints", "",
00278 img1d, 1, 1, 1);
00279
00280 cpl_image_delete(img1d);
00281
00282 img1d = cpl_image_collapse_window_create(saapair[0], xtmin, 1, xtmax,
00283 ny, 0);
00284
00285 cpl_plot_image_row("set grid;", "t '1D-Profile' w linespoints", "",
00286 img1d, 1, 1, 1);
00287
00288 cpl_image_delete(img1d);
00289 if (!cpl_errorstate_is_equal(prestate)) {
00290 cpl_errorstate_set(prestate);
00291 }
00292 }
00293
00294 stats = cpl_stats_new_from_image(saapair[0], CPL_STATS_ALL);
00295 bug_if(stats == NULL);
00296
00297 if (cpl_msg_get_level() <= CPL_MSG_INFO) {
00298 cpl_stats_dump(stats, CPL_STATS_ALL, stdout);
00299 }
00300
00301 skip_if(naco_spc_combine_qc(qclist, paflist, rawframes));
00302
00303
00304 bug_if (cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
00305 NACO_SPC_NOD_COMBINE));
00306
00307 skip_if(naco_spc_combine_save(framelist, parlist, qclist, paflist,
00308 saapair[0], saapair[1], offcorr, objimages,
00309 rawframes));
00310
00311 end_skip;
00312
00313 if (saapair != NULL) {
00314 cpl_image_delete(saapair[0]);
00315 cpl_image_delete(saapair[1]);
00316 cpl_free(saapair);
00317 }
00318 cpl_bivector_delete(offcorr);
00319 cpl_stats_delete(stats);
00320 cpl_imagelist_delete(objimages);
00321 cpl_imagelist_delete(offimages);
00322 cpl_image_delete(flatimg);
00323 irplib_framelist_delete(allframes);
00324 irplib_framelist_delete(rawframes);
00325 irplib_framelist_delete(skyframes);
00326 cpl_propertylist_delete(onoffkeys);
00327 cpl_propertylist_delete(qclist);
00328 cpl_propertylist_delete(paflist);
00329
00330 return cpl_error_get_code();
00331 }
00332
00333
00334
00342
00343 static cpl_error_code naco_spc_combine_qc(cpl_propertylist * qclist,
00344 cpl_propertylist * paflist,
00345 const irplib_framelist * rawframes)
00346 {
00347
00348 const cpl_propertylist * reflist
00349 = irplib_framelist_get_propertylist_const(rawframes, 0);
00350 const char pafcopy[] = "^(" NACO_PFITS_REGEXP_SPCWAVE_PAF ")$";
00351 const char * filter;
00352
00353 bug_if (0);
00354
00355 filter = naco_pfits_get_filter(reflist);
00356 skip_if(filter == NULL);
00357
00358 bug_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS", filter));
00359
00360
00361 skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
00362 0));
00363 skip_if (cpl_propertylist_append(paflist, qclist));
00364
00365 bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
00366 IRPLIB_PFITS_WCS_REGEXP "|"
00367 IRPLIB_PFITS_REGEXP_RECAL_LAMP
00368 ")$", 0));
00369 end_skip;
00370
00371 return cpl_error_get_code();
00372 }
00373
00374
00388
00389 static cpl_error_code naco_spc_combine_save(cpl_frameset * set_tot,
00390 const cpl_parameterlist* parlist,
00391 const cpl_propertylist * qclist,
00392 const cpl_propertylist * paflist,
00393 const cpl_image * combined,
00394 const cpl_image * contrib,
00395 const cpl_bivector * offcorr,
00396 const cpl_imagelist * objimages,
00397 const irplib_framelist * rawframes)
00398 {
00399 const int nsave
00400 = naco_parameterlist_get_int(parlist, RECIPE_STRING, NACO_PARAM_SAVE);
00401 cpl_frameset * proframes = irplib_frameset_cast(rawframes);
00402 cpl_table * offtable = NULL;
00403 cpl_propertylist * xtlist = cpl_propertylist_new();
00404
00405
00406 bug_if(cpl_propertylist_append_string(xtlist, "EXTNAME",
00407 "Contribution Map"));
00408
00409
00410 skip_if (irplib_dfs_save_image(set_tot, parlist, proframes, combined,
00411 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00412 NACO_SPC_NOD_COMBINE, qclist, NULL,
00413 naco_pipe_id, RECIPE_STRING CPL_DFS_FITS));
00414
00415
00416
00417 skip_if (cpl_image_save(contrib, RECIPE_STRING CPL_DFS_FITS,
00418 CPL_BPP_16_UNSIGNED, xtlist, CPL_IO_EXTEND));
00419
00420
00421
00422 offtable = cpl_table_new(cpl_bivector_get_size(offcorr));
00423 bug_if(0);
00424 bug_if(cpl_table_wrap_double
00425 (offtable, (double*)cpl_bivector_get_x_data_const(offcorr),
00426 "OFFSETX"));
00427
00428 bug_if(cpl_table_wrap_double
00429 (offtable, (double*)cpl_bivector_get_y_data_const(offcorr),
00430 "OFFSETY"));
00431
00432 bug_if(cpl_table_set_column_unit(offtable, "OFFSETX", "pixel"));
00433 bug_if(cpl_table_set_column_unit(offtable, "OFFSETY", "pixel"));
00434
00435 bug_if(cpl_propertylist_set_string(xtlist, "EXTNAME",
00436 "Image combination shifts"));
00437
00438 skip_if(cpl_table_save(offtable, NULL, xtlist, RECIPE_STRING CPL_DFS_FITS,
00439 CPL_IO_EXTEND));
00440
00441 if (nsave > 0) {
00442
00443 skip_if(irplib_dfs_save_imagelist(set_tot, parlist, proframes, objimages,
00444 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00445 NACO_SPC_NOD_SUBTRACT, qclist, NULL,
00446 naco_pipe_id, RECIPE_STRING
00447 "_subtracted" CPL_DFS_FITS));
00448
00449
00450 }
00451
00452
00453 #ifdef NACO_SAVE_PAF
00454
00455 skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, paflist,
00456 RECIPE_STRING CPL_DFS_PAF));
00457 #else
00458 bug_if(paflist == NULL);
00459 #endif
00460
00461 end_skip;
00462
00463 cpl_propertylist_delete(xtlist);
00464
00465 cpl_frameset_delete(proframes);
00466 if (offtable != NULL) {
00467 (void)cpl_table_unwrap(offtable, "OFFSETX");
00468 (void)cpl_table_unwrap(offtable, "OFFSETY");
00469 cpl_table_delete(offtable);
00470 }
00471
00472 return cpl_error_get_code();
00473
00474 }
00475
00476
00477
00492
00493 static
00494 cpl_error_code naco_framelist_fill_onoff_offset(cpl_vector * offset,
00495 cpl_vector * offsety,
00496 const irplib_framelist * self)
00497 {
00498 const int nframes = irplib_framelist_get_size(self);
00499 int i;
00500
00501
00502 skip_if (0);
00503 skip_if (self == NULL);
00504 skip_if (offset == NULL);
00505
00506 skip_if (irplib_framelist_contains(self, NACO_PFITS_DOUBLE_CUMOFFSETX,
00507 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00508
00509 bug_if(cpl_vector_set_size(offset, nframes));
00510
00511 if (offsety != NULL) {
00512 skip_if (irplib_framelist_contains(self, NACO_PFITS_DOUBLE_CUMOFFSETY,
00513 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00514 bug_if(cpl_vector_set_size(offsety, nframes));
00515 }
00516
00517
00518 for (i = 0; i < nframes; i += 2) {
00519 const cpl_propertylist * plist1
00520 = irplib_framelist_get_propertylist_const(self, i);
00521 const cpl_propertylist * plist2
00522 = irplib_framelist_get_propertylist_const(self, i+1);
00523
00524 const double xoff1
00525 = irplib_pfits_get_double(plist1, NACO_PFITS_DOUBLE_CUMOFFSETX);
00526 const double xoff2
00527 = irplib_pfits_get_double(plist2, NACO_PFITS_DOUBLE_CUMOFFSETX);
00528 int i0, i1;
00529
00530 if (xoff1 > xoff2) {
00531 i0 = i/2;
00532 i1 = i/2 + nframes/2;
00533 } else {
00534 i1 = i/2;
00535 i0 = i/2 + nframes/2;
00536 }
00537 bug_if(cpl_vector_set(offset, i0, xoff1));
00538 bug_if(cpl_vector_set(offset, i1, xoff2));
00539
00540 if (offsety != NULL) {
00541 const double yoff1
00542 = irplib_pfits_get_double(plist1, NACO_PFITS_DOUBLE_CUMOFFSETY);
00543 const double yoff2
00544 = irplib_pfits_get_double(plist2, NACO_PFITS_DOUBLE_CUMOFFSETY);
00545
00546 bug_if(cpl_vector_set(offsety, i0, yoff1));
00547 bug_if(cpl_vector_set(offsety, i1, yoff2));
00548 }
00549 }
00550
00551 end_skip;
00552
00553 return cpl_error_get_code();
00554
00555 }
00556