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
00037
00038
00039
00040
00041
00042
00043 #include <math.h>
00044 #include <cpl.h>
00045
00046 #include "irplib_utils.h"
00047 #include "irplib_std.h"
00048 #include "irplib_spectrum.h"
00049
00050 #include "naco_utils.h"
00051 #include "naco_physicalmodel.h"
00052 #include "naco_wavelength.h"
00053 #include "naco_pfits.h"
00054 #include "naco_dfs.h"
00055
00056
00057
00058
00059
00060 #define NACO_SPC_JITTER_OFFSET_ERR 10
00061
00062
00063
00064
00065
00066 static int naco_spc_jitter_create(cpl_plugin *);
00067 static int naco_spc_jitter_exec(cpl_plugin *);
00068 static int naco_spc_jitter_destroy(cpl_plugin *);
00069 static int naco_spc_jitter(cpl_parameterlist *, cpl_frameset *);
00070 static cpl_image ** naco_spc_jitter_combine(cpl_frameset *, char *, char *,
00071 char *);
00072 static cpl_vector * naco_spc_jitter_get_offsets(cpl_frameset *);
00073 static int * naco_spc_jitter_classif(cpl_vector *, int *);
00074 static int off_comp(double, double, double);
00075 static cpl_imagelist * naco_spc_jitter_saa_groups(cpl_imagelist *,
00076 cpl_vector *, int *, int, cpl_vector **);
00077 static int naco_spc_jitter_wavecal(char *, cpl_image *, cpl_frameset *);
00078 static cpl_imagelist * naco_spc_jitter_nodded(cpl_imagelist *, cpl_vector *,
00079 cpl_vector **);
00080 static cpl_imagelist * naco_spc_jitter_distor(cpl_imagelist *, char *);
00081 static double naco_spc_jitter_refine_offset(cpl_image *, cpl_image *);
00082 static cpl_table * naco_spc_jitter_extract(cpl_image *);
00083 static int naco_spc_jitter_save(const cpl_image *, const cpl_table *,
00084 cpl_parameterlist *, cpl_frameset *);
00085
00086
00087
00088
00089
00090 static struct {
00091
00092 int display;
00093
00094 int wavecal_in;
00095 int wavecal_rej_bottom;
00096 int wavecal_rej_top;
00097 int wavecal_rej_left;
00098 int wavecal_rej_right;
00099 int saa_refine;
00100 double saa_rej_high;
00101 double saa_rej_low;
00102 int extr_spec_pos;
00103 int extr_spec_width;
00104 int extr_sky_ri_width;
00105 int extr_sky_le_width;
00106 int extr_sky_ri_dist;
00107 int extr_sky_le_dist;
00108
00109
00110 cpl_vector * throws;
00111 int wavecal_out;
00112 double wavecal_cc;
00113 double wavecal_a0;
00114 double wavecal_a1;
00115 double wavecal_a2;
00116 double wavecal_a3;
00117 } naco_spc_jitter_config;
00118
00119 static char naco_spc_jitter_description[] =
00120 "naco_spc_jitter -- NACO spectro jitter recipe\n"
00121 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
00122 "raw-file.fits "NACO_SPC_JITTER_RAW" or\n"
00123 "flat-file.fits "NACO_CALIB_SPFLAT" or\n"
00124 "arc-file.fits "NACO_CALIB_ARC" or\n"
00125 "arc_wl-file.fits "NACO_CALIB_ARC_WL"\n";
00126
00127
00131
00132
00133
00134
00135
00136
00137
00145
00146 int cpl_plugin_get_info(cpl_pluginlist * list)
00147 {
00148 cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe));
00149 cpl_plugin * plugin = &recipe->interface;
00150
00151 cpl_plugin_init(plugin,
00152 CPL_PLUGIN_API,
00153 NACO_BINARY_VERSION,
00154 CPL_PLUGIN_TYPE_RECIPE,
00155 "naco_spc_jitter",
00156 "Spectro jitter recipe",
00157 naco_spc_jitter_description,
00158 "Yves Jung",
00159 "yjung@eso.org",
00160 cpl_get_license(PACKAGE_NAME, "2002, 2003, 2005"),
00161 naco_spc_jitter_create,
00162 naco_spc_jitter_exec,
00163 naco_spc_jitter_destroy);
00164
00165 cpl_pluginlist_append(list, plugin);
00166
00167 return 0;
00168 }
00169
00170
00179
00180 static int naco_spc_jitter_create(cpl_plugin * plugin)
00181 {
00182 cpl_recipe * recipe;
00183 cpl_parameter * p;
00184
00185
00186 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00187 recipe = (cpl_recipe *)plugin;
00188 else return -1;
00189
00190
00191 recipe->parameters = cpl_parameterlist_new();
00192
00193
00194
00195 p = cpl_parameter_new_value("naco.naco_spc_jitter.wavecal",
00196 CPL_TYPE_STRING, "Wavelength method: phy or sky",
00197 "naco.naco_spc_jitter", "sky");
00198 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wavecal");
00199 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00200 cpl_parameterlist_append(recipe->parameters, p);
00201
00202 p = cpl_parameter_new_value("naco.naco_spc_jitter.wavecal_rej",
00203 CPL_TYPE_STRING, "left right bottom top rejections",
00204 "naco.naco_spc_jitter", "-1 -1 50 50");
00205 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wc_rej");
00206 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00207 cpl_parameterlist_append(recipe->parameters, p);
00208
00209 p = cpl_parameter_new_value("naco.naco_spc_jitter.saa_refine",
00210 CPL_TYPE_BOOL, "flag to refine the offsets",
00211 "naco.naco_spc_jitter", TRUE);
00212 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "saa_refine");
00213 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00214 cpl_parameterlist_append(recipe->parameters, p);
00215
00216 p = cpl_parameter_new_value("naco.naco_spc_jitter.saa_rej",
00217 CPL_TYPE_STRING, "low and high rejections in percent",
00218 "naco.naco_spc_jitter", "0.1 0.1");
00219 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "saa_rej");
00220 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00221 cpl_parameterlist_append(recipe->parameters, p);
00222
00223 p = cpl_parameter_new_value("naco.naco_spc_jitter.spec_pos",
00224 CPL_TYPE_INT, "spectrum position", "naco.naco_spc_jitter", -1);
00225 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "spec_pos");
00226 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00227 cpl_parameterlist_append(recipe->parameters, p);
00228
00229 p = cpl_parameter_new_value("naco.naco_spc_jitter.spec_width",
00230 CPL_TYPE_INT, "spectrum width", "naco.naco_spc_jitter", 10);
00231 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "spec_width");
00232 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00233 cpl_parameterlist_append(recipe->parameters, p);
00234
00235 p = cpl_parameter_new_value("naco.naco_spc_jitter.sky_ri_width",
00236 CPL_TYPE_INT, "sky width right to the spectrum",
00237 "naco.naco_spc_jitter", 10);
00238 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky_ri_width");
00239 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00240 cpl_parameterlist_append(recipe->parameters, p);
00241
00242 p = cpl_parameter_new_value("naco.naco_spc_jitter.sky_le_width",
00243 CPL_TYPE_INT, "sky width left to the spectrum",
00244 "naco.naco_spc_jitter", 10);
00245 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky_le_width");
00246 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00247 cpl_parameterlist_append(recipe->parameters, p);
00248
00249 p = cpl_parameter_new_value("naco.naco_spc_jitter.sky_ri_dist",
00250 CPL_TYPE_INT, "sky distance right to the spectrum",
00251 "naco.naco_spc_jitter", -1);
00252 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky_ri_dist");
00253 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00254 cpl_parameterlist_append(recipe->parameters, p);
00255
00256 p = cpl_parameter_new_value("naco.naco_spc_jitter.sky_le_dist",
00257 CPL_TYPE_INT, "sky distance left to the spectrum",
00258 "naco.naco_spc_jitter", -1);
00259 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky_le_dist");
00260 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00261 cpl_parameterlist_append(recipe->parameters, p);
00262
00263 p = cpl_parameter_new_value("naco.naco_spc_jitter.display",
00264 CPL_TYPE_BOOL, "flag to make plots", "naco.naco_spc_jitter",
00265 FALSE);
00266 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "display");
00267 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00268 cpl_parameterlist_append(recipe->parameters, p);
00269 return 0;
00270 }
00271
00272
00278
00279 static int naco_spc_jitter_exec(cpl_plugin * plugin)
00280 {
00281 cpl_recipe * recipe;
00282
00283
00284 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00285 recipe = (cpl_recipe *)plugin;
00286 else return -1;
00287
00288 return naco_spc_jitter(recipe->parameters, recipe->frames);
00289 }
00290
00291
00297
00298 static int naco_spc_jitter_destroy(cpl_plugin * plugin)
00299 {
00300 cpl_recipe * recipe;
00301
00302
00303 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00304 recipe = (cpl_recipe *)plugin;
00305 else return -1;
00306
00307 cpl_parameterlist_delete(recipe->parameters);
00308 return 0;
00309 }
00310
00311
00318
00319 static int naco_spc_jitter(
00320 cpl_parameterlist * parlist,
00321 cpl_frameset * framelist)
00322 {
00323 const char * fctid = "naco_spc_jitter";
00324 cpl_parameter * par;
00325 cpl_propertylist * plist;
00326 const char * sval;
00327 int * labels;
00328 int nlabels;
00329 cpl_frameset * rawframes;
00330 char * flat;
00331 char * arc;
00332 char * arc_wl;
00333 cpl_frame * cur_frame;
00334 char * tag;
00335 cpl_frameset * cur_set;
00336 cpl_image ** combined;
00337 cpl_table * extracted;
00338 int i;
00339
00340
00341 par = NULL;
00342 rawframes = NULL;
00343 arc = NULL;
00344 arc_wl = NULL;
00345 flat = NULL;
00346 naco_spc_jitter_config.wavecal_out = -1;
00347 naco_spc_jitter_config.wavecal_cc = -1.0;
00348 naco_spc_jitter_config.throws = NULL;
00349
00350
00351
00352 par = cpl_parameterlist_find(parlist, "naco.naco_spc_jitter.wavecal");
00353 sval = cpl_parameter_get_string(par);
00354 if (!strcmp(sval, "phy")) naco_spc_jitter_config.wavecal_in = 0;
00355 else if (!strcmp(sval, "sky")) naco_spc_jitter_config.wavecal_in = 1;
00356 else {
00357 cpl_msg_error(fctid, "Invalid value for wavecal option");
00358 return -1;
00359 }
00360
00361 par = cpl_parameterlist_find(parlist, "naco.naco_spc_jitter.wavecal_rej");
00362 sval = cpl_parameter_get_string(par);
00363 if (sscanf(sval, "%d %d %d %d",
00364 &naco_spc_jitter_config.wavecal_rej_left,
00365 &naco_spc_jitter_config.wavecal_rej_right,
00366 &naco_spc_jitter_config.wavecal_rej_bottom,
00367 &naco_spc_jitter_config.wavecal_rej_top) != 4) {
00368 return -1;
00369 }
00370
00371 par = cpl_parameterlist_find(parlist, "naco.naco_spc_jitter.saa_refine");
00372 naco_spc_jitter_config.saa_refine = cpl_parameter_get_bool(par);
00373
00374
00375 par = cpl_parameterlist_find(parlist, "naco.naco_spc_jitter.saa_rej");
00376 sval = cpl_parameter_get_string(par);
00377 if (sscanf(sval, "%lg %lg",
00378 &naco_spc_jitter_config.saa_rej_low,
00379 &naco_spc_jitter_config.saa_rej_high) != 2) {
00380 return -1;
00381 }
00382
00383
00384 par=cpl_parameterlist_find(parlist,"naco.naco_spc_jitter.spec_pos");
00385 naco_spc_jitter_config.extr_spec_pos = cpl_parameter_get_int(par);
00386
00387 par=cpl_parameterlist_find(parlist,"naco.naco_spc_jitter.spec_width");
00388 naco_spc_jitter_config.extr_spec_width = cpl_parameter_get_int(par);
00389
00390 par=cpl_parameterlist_find(parlist,"naco.naco_spc_jitter.sky_ri_width");
00391 naco_spc_jitter_config.extr_sky_ri_width = cpl_parameter_get_int(par);
00392
00393 par=cpl_parameterlist_find(parlist,"naco.naco_spc_jitter.sky_le_width");
00394 naco_spc_jitter_config.extr_sky_le_width = cpl_parameter_get_int(par);
00395
00396 par=cpl_parameterlist_find(parlist,"naco.naco_spc_jitter.sky_ri_dist");
00397 naco_spc_jitter_config.extr_sky_ri_dist = cpl_parameter_get_int(par);
00398
00399 par=cpl_parameterlist_find(parlist,"naco.naco_spc_jitter.sky_le_dist");
00400 naco_spc_jitter_config.extr_sky_le_dist = cpl_parameter_get_int(par);
00401
00402 par = cpl_parameterlist_find(parlist, "naco.naco_spc_jitter.display");
00403 naco_spc_jitter_config.display = cpl_parameter_get_bool(par);
00404
00405
00406 if (naco_dfs_set_groups(framelist)) {
00407 cpl_msg_error(fctid, "Cannot identify RAW and CALIB frames");
00408 return -1;
00409 }
00410
00411
00412 if ((labels = cpl_frameset_labelise(framelist, irplib_compare_tags,
00413 &nlabels)) == NULL) {
00414 cpl_msg_error(fctid, "Cannot labelise the input frames");
00415 return -1;
00416 }
00417
00418
00419 for (i=0 ; i<nlabels ; i++) {
00420 cur_set = cpl_frameset_extract(framelist, labels, i);
00421 cur_frame = cpl_frameset_get_frame(cur_set, 0);
00422 tag = (char*)cpl_frame_get_tag(cur_frame);
00423 if (!strcmp(tag, NACO_SPC_JITTER_RAW)) {
00424
00425 rawframes = cpl_frameset_duplicate(cur_set);
00426 } else if (!strcmp(tag, NACO_CALIB_SPFLAT)) {
00427
00428 if (flat == NULL)
00429 flat = cpl_strdup(cpl_frame_get_filename(cur_frame));
00430 } else if (!strcmp(tag, NACO_CALIB_ARC)) {
00431
00432 if (arc == NULL)
00433 arc = cpl_strdup(cpl_frame_get_filename(cur_frame));
00434 } else if (!strcmp(tag, NACO_CALIB_ARC_WL)) {
00435
00436 naco_spc_jitter_config.wavecal_in = 2;
00437 if (arc_wl == NULL)
00438 arc_wl = cpl_strdup(cpl_frame_get_filename(cur_frame));
00439 }
00440 cpl_frameset_delete(cur_set);
00441 }
00442 cpl_free(labels);
00443
00444
00445 if (rawframes == NULL) {
00446 cpl_msg_error(fctid, "Cannot find the raw frames in the input list");
00447 if (flat) cpl_free(flat);
00448 if (arc) cpl_free(arc);
00449 if (arc_wl) cpl_free(arc_wl);
00450 return -1;
00451 }
00452
00453
00454 cpl_msg_info(fctid, "Create the combined image");
00455 cpl_msg_indent_more();
00456 if ((combined = naco_spc_jitter_combine(rawframes, flat, arc,
00457 arc_wl)) == NULL) {
00458 cpl_msg_error(fctid, "Cannot combine the images");
00459 if (flat) cpl_free(flat);
00460 if (arc) cpl_free(arc);
00461 if (arc_wl) cpl_free(arc_wl);
00462 cpl_frameset_delete(rawframes);
00463 if (naco_spc_jitter_config.throws)
00464 cpl_vector_delete(naco_spc_jitter_config.throws);
00465 cpl_msg_indent_less();
00466 return -1;
00467 }
00468 cpl_frameset_delete(rawframes);
00469 if (flat) cpl_free(flat);
00470 if (arc) cpl_free(arc);
00471 if (arc_wl) cpl_free(arc_wl);
00472 cpl_msg_indent_less();
00473
00474
00475 cpl_msg_info(fctid, "Extract the spectrum");
00476 cpl_msg_indent_more();
00477 if ((extracted = naco_spc_jitter_extract(combined[0])) == NULL) {
00478 cpl_msg_error(fctid, "Cannot extract the spectrum");
00479 }
00480 if (naco_spc_jitter_config.throws)
00481 cpl_vector_delete(naco_spc_jitter_config.throws);
00482 cpl_msg_indent_less();
00483
00484
00485 cpl_msg_info(fctid, "Save the products");
00486 cpl_msg_indent_more();
00487 if (naco_spc_jitter_save(combined[0], extracted, parlist,
00488 framelist) == -1) {
00489 cpl_msg_error(fctid, "Cannot save the products");
00490 cpl_image_delete(combined[0]);
00491 cpl_image_delete(combined[1]);
00492 cpl_free(combined);
00493 cpl_table_delete(extracted);
00494 cpl_msg_indent_less();
00495 return -1;
00496 }
00497 cpl_table_delete(extracted);
00498 cpl_image_delete(combined[0]);
00499 cpl_image_delete(combined[1]);
00500 cpl_free(combined);
00501 cpl_msg_indent_less();
00502
00503 return 0;
00504 }
00505
00506
00515
00516 static cpl_image ** naco_spc_jitter_combine(
00517 cpl_frameset * rawframes,
00518 char * flat,
00519 char * arc,
00520 char * arc_wl)
00521 {
00522 const char * fctid = "naco_spc_jitter_combine";
00523 cpl_imagelist * ilist;
00524 cpl_imagelist * corrected;
00525 cpl_image * cur_im;
00526 cpl_image * tmp_im;
00527 cpl_vector * offsets;
00528 int * groups;
00529 int ngroups;
00530 cpl_imagelist * abba;
00531 cpl_vector * abba_off;
00532 cpl_imagelist * nodded;
00533 cpl_vector * nodded_off_x;
00534 cpl_vector * nodded_off_y;
00535 double throw;
00536 cpl_table * extracted;
00537 double intensity;
00538 double * pnodded_off_x;
00539 cpl_imagelist * nodded_warped;
00540 cpl_bivector * nodded_offsets;
00541 cpl_image ** combined;
00542 int nima;
00543 double new_offset;
00544 int i;
00545
00546
00547 if (rawframes == NULL) return NULL;
00548
00549
00550 cpl_msg_info(fctid, "Load the data");
00551 cpl_msg_indent_more();
00552 if ((ilist = cpl_imagelist_load_frameset(rawframes, CPL_TYPE_FLOAT,
00553 1, 0)) == NULL) {
00554 cpl_msg_error(fctid, "cannot load the data");
00555 cpl_msg_indent_less();
00556 return NULL;
00557 }
00558 cpl_msg_indent_less();
00559
00560
00561 if (flat != NULL) {
00562 cpl_msg_info(fctid, "Apply the flatfield correction");
00563 if ((tmp_im = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0)) == NULL) {
00564 cpl_msg_warning(fctid, "cannot load the flat field");
00565 } else {
00566 if (cpl_imagelist_divide_image(ilist, tmp_im) != CPL_ERROR_NONE) {
00567 cpl_msg_warning(fctid, "cannot apply the flat field");
00568 }
00569 cpl_image_delete(tmp_im);
00570 }
00571 }
00572
00573
00574 cpl_msg_info(fctid, "Get the offsets");
00575 if ((offsets = naco_spc_jitter_get_offsets(rawframes)) == NULL) {
00576 cpl_msg_error(fctid, "cannot get the offsets");
00577 cpl_imagelist_delete(ilist);
00578 return NULL;
00579 }
00580
00581
00582 cpl_msg_info(fctid, "Classify in groups");
00583 cpl_msg_indent_more();
00584 if ((groups = naco_spc_jitter_classif(offsets, &ngroups)) == NULL) {
00585 cpl_msg_error(fctid, "cannot classify the data");
00586 cpl_imagelist_delete(ilist);
00587 cpl_vector_delete(offsets);
00588 cpl_msg_indent_less();
00589 return NULL;
00590 }
00591 cpl_msg_indent_less();
00592
00593
00594 cpl_msg_info(fctid, "Shift and add each group to one image");
00595 cpl_msg_indent_more();
00596 if ((abba = naco_spc_jitter_saa_groups(ilist, offsets, groups,
00597 ngroups, &abba_off)) == NULL) {
00598 cpl_msg_error(fctid, "cannot shift and add groups");
00599 cpl_imagelist_delete(ilist);
00600 cpl_vector_delete(offsets);
00601 cpl_free(groups);
00602 cpl_msg_indent_less();
00603 return NULL;
00604 }
00605 cpl_imagelist_delete(ilist);
00606 cpl_free(groups);
00607 cpl_vector_delete(offsets);
00608 cpl_msg_indent_less();
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 cpl_msg_info(fctid, "Create the nodded images");
00627 cpl_msg_indent_more();
00628 if ((nodded = naco_spc_jitter_nodded(abba, abba_off,
00629 &nodded_off_x))==NULL) {
00630 cpl_msg_error(fctid, "cannot create the nodded images");
00631 cpl_imagelist_delete(abba);
00632 cpl_vector_delete(abba_off);
00633 cpl_msg_indent_less();
00634 return NULL;
00635 }
00636 cpl_imagelist_delete(abba);
00637 cpl_msg_indent_less();
00638
00639
00640 nima = cpl_imagelist_get_size(nodded);
00641 naco_spc_jitter_config.throws = cpl_vector_new(nima);
00642 for (i=0 ; i<nima/2 ; i++) {
00643 throw = fabs( (cpl_vector_get(abba_off, 2*i))-
00644 (cpl_vector_get(abba_off, 2*i+1)));
00645 cpl_vector_set(naco_spc_jitter_config.throws, 2*i, throw);
00646 cpl_vector_set(naco_spc_jitter_config.throws, 2*i+1, throw);
00647 }
00648 cpl_vector_delete(abba_off);
00649
00650
00651 if (arc) {
00652 cpl_msg_info(fctid, "Correct the distortion on nodded images");
00653 cpl_msg_indent_more();
00654 if ((nodded_warped = naco_spc_jitter_distor(nodded, arc)) == NULL) {
00655 cpl_msg_error(fctid, "cannot correct the distortion");
00656 cpl_imagelist_delete(nodded);
00657 cpl_vector_delete(nodded_off_x);
00658 cpl_msg_indent_less();
00659 return NULL;
00660 }
00661 cpl_imagelist_delete(nodded);
00662 nodded = nodded_warped;
00663 cpl_msg_indent_less();
00664 }
00665
00666
00667 if (naco_spc_jitter_config.saa_refine) {
00668 cpl_msg_info(fctid, "Refine the offsets");
00669 pnodded_off_x = cpl_vector_get_data(nodded_off_x);
00670 for (i=0 ; i<cpl_imagelist_get_size(nodded) ; i++) {
00671 new_offset = naco_spc_jitter_refine_offset(
00672 cpl_imagelist_get(nodded, 0),
00673 cpl_imagelist_get(nodded, i));
00674 if (new_offset > 5000) {
00675 cpl_msg_debug(fctid, "cannot refine the offset - keep %g",
00676 pnodded_off_x[i]);
00677 } else {
00678 if (fabs(new_offset-pnodded_off_x[i]) <
00679 NACO_SPC_JITTER_OFFSET_ERR) {
00680 cpl_msg_debug(fctid, "refined offset : %g (old was %g)",
00681 new_offset, pnodded_off_x[i]);
00682 pnodded_off_x[i] = new_offset;
00683 } else {
00684 cpl_msg_debug(fctid,
00685 "refined offset %g too different - keep %g",
00686 new_offset, pnodded_off_x[i]);
00687 }
00688 }
00689 }
00690 }
00691
00692
00693
00694 nodded_off_y = cpl_vector_duplicate(nodded_off_x);
00695 cpl_vector_fill(nodded_off_y, 0.0);
00696 nodded_offsets = cpl_bivector_wrap_vectors(nodded_off_x, nodded_off_y);
00697
00698 cpl_msg_info(fctid, "Apply the shift and add on the nodded frames");
00699 nima = cpl_imagelist_get_size(nodded);
00700 if ((combined = cpl_geom_img_offset_saa(nodded, nodded_offsets,
00701 CPL_KERNEL_DEFAULT,
00702 (int)(naco_spc_jitter_config.saa_rej_low * nima),
00703 (int)(naco_spc_jitter_config.saa_rej_high * nima),
00704 CPL_GEOM_FIRST, NULL, NULL)) == NULL) {
00705 cpl_msg_error(fctid, "Cannot shift and add group");
00706 cpl_imagelist_delete(nodded);
00707 cpl_bivector_unwrap_vectors(nodded_offsets);
00708 cpl_vector_delete(nodded_off_x);
00709 cpl_vector_delete(nodded_off_y);
00710 return NULL;
00711 }
00712 cpl_imagelist_delete(nodded);
00713 cpl_bivector_unwrap_vectors(nodded_offsets);
00714 cpl_vector_delete(nodded_off_x);
00715 cpl_vector_delete(nodded_off_y);
00716 return combined;
00717 }
00718
00719
00725
00726 static cpl_vector * naco_spc_jitter_get_offsets(cpl_frameset * rawframes)
00727 {
00728 const char * fctid = "naco_spc_jitter_get_offsets";
00729 cpl_vector * offsets;
00730 double * pvect;
00731 int nraw;
00732 cpl_frame * cur_frame;
00733 cpl_propertylist * plist;
00734 int i;
00735
00736
00737 if (rawframes == NULL) return NULL;
00738
00739
00740 nraw = cpl_frameset_get_size(rawframes);
00741
00742
00743 offsets = cpl_vector_new(nraw);
00744 pvect = cpl_vector_get_data(offsets);
00745 for (i=0 ; i<nraw ; i++) {
00746 cur_frame = cpl_frameset_get_frame(rawframes, i);
00747 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(cur_frame),
00748 0)) == NULL) {
00749 cpl_msg_error(fctid, "cannot get property list");
00750 cpl_vector_delete(offsets);
00751 return NULL;
00752 }
00753 pvect[i] = -1 * naco_pfits_get_cumoffsetx(plist);
00754 if (cpl_error_get_code()) {
00755 cpl_msg_error(fctid, "cannot get the offset from the header");
00756 cpl_vector_delete(offsets);
00757 cpl_propertylist_delete(plist);
00758 return NULL;
00759 }
00760 cpl_propertylist_delete(plist);
00761 }
00762 return offsets;
00763 }
00764
00765
00803
00804 static int * naco_spc_jitter_classif(
00805 cpl_vector * offsets,
00806 int * ngroups)
00807 {
00808 const char * fctid = "naco_spc_jitter_classif";
00809 double * pvect;
00810 int nraw;
00811 double offset_thresh;
00812 cpl_vector * tmp_vec;
00813 int * groups;
00814 int last_group;
00815 int i, j, k, l;
00816
00817
00818 if (offsets == NULL) return NULL;
00819
00820
00821 nraw = cpl_vector_get_size(offsets);
00822
00823
00824 tmp_vec = cpl_vector_duplicate(offsets);
00825 cpl_vector_sort(tmp_vec, 1);
00826 pvect = cpl_vector_get_data(tmp_vec);
00827 if (pvect[0] == pvect[nraw-1]) {
00828 cpl_msg_error(fctid, "Only one offset in the list - abort");
00829 cpl_vector_delete(tmp_vec);
00830 return NULL;
00831 }
00832 offset_thresh = (pvect[0] + pvect[nraw-1]) / 2.0;
00833 cpl_vector_delete(tmp_vec);
00834
00835
00836 pvect = cpl_vector_get_data(offsets);
00837 *ngroups = 0;
00838 groups = cpl_calloc(nraw, sizeof(int));
00839
00840
00841 i = 0;
00842 while (i < nraw) {
00843 j = 0;
00844
00845 while ((i+j<nraw) &&
00846 (!off_comp(pvect[i], pvect[i+j], offset_thresh))) j++;
00847
00848 if (i+j >= nraw) i = nraw;
00849 else {
00850 k = 0;
00851
00852 while ((i+j+k < nraw)
00853 && (!off_comp(pvect[i+j], pvect[i+j+k], offset_thresh))
00854 && (k<j)) k++;
00855 last_group = 1;
00856 if (i+j+k < nraw) {
00857 for (l=i+j+k ; l<nraw ; l++) {
00858 if (off_comp(pvect[i+j], pvect[l], offset_thresh)) {
00859 last_group = 0;
00860 break;
00861 }
00862 }
00863 }
00864 if (last_group == 0) {
00865 for (l=0 ; l<j ; l++) groups[i+l] = *ngroups + 1;
00866 for (l=0 ; l<k ; l++) groups[i+j+l] = *ngroups + 2;
00867 *ngroups += 2;
00868 i += j+k;
00869 } else {
00870 for (l=0 ; l<j ; l++) groups[i+l] = *ngroups + 1;
00871 for (l=0 ; l<nraw - (i+j) ; l++) groups[i+j+l] =*ngroups + 2;
00872 *ngroups += 2;
00873 i = nraw;
00874 }
00875 }
00876 }
00877
00878
00879 if (*ngroups % 2) {
00880 cpl_msg_error(fctid, "Odd number of groups found");
00881 cpl_free(groups);
00882 return NULL;
00883 }
00884
00885 return groups;
00886 }
00887
00888
00919
00920 static cpl_imagelist * naco_spc_jitter_saa_groups(
00921 cpl_imagelist * ilist,
00922 cpl_vector * offsets,
00923 int * groups,
00924 int ngroups,
00925 cpl_vector ** abba_off)
00926 {
00927 const char * fctid = "naco_spc_jitter_saa_groups";
00928 cpl_imagelist * abba;
00929 cpl_imagelist * group_list;
00930 cpl_image * tmp_ima;
00931 cpl_image ** combined;
00932 cpl_bivector * group_off;
00933 double * pgroup_off;
00934 double * poffsets;
00935 double * pabba_off;
00936 int nima;
00937 int saa;
00938 int i, j, k;
00939
00940
00941 if ((ilist == NULL) || (offsets == NULL) || (groups == NULL)) return NULL;
00942
00943
00944 nima = cpl_imagelist_get_size(ilist);
00945 poffsets = cpl_vector_get_data(offsets);
00946
00947
00948 abba = cpl_imagelist_new();
00949 *abba_off = cpl_vector_new(ngroups);
00950 pabba_off = cpl_vector_get_data(*abba_off);
00951
00952
00953 for (i=0 ; i<ngroups ; i++) {
00954
00955 saa = 0;
00956
00957 group_list = cpl_imagelist_new();
00958 k = 0;
00959 for (j=0 ; j<nima ; j++) {
00960 if (i+1 == groups[j]) {
00961
00962 if (k==0) pabba_off[i] = poffsets[j];
00963
00964 if (fabs(pabba_off[i]-poffsets[j]) > 1e-3) saa = 1;
00965
00966 tmp_ima = cpl_image_duplicate(cpl_imagelist_get(ilist, j));
00967 cpl_imagelist_set(group_list, tmp_ima, k);
00968 tmp_ima = NULL;
00969 k++;
00970 }
00971 }
00972
00973 if (saa) {
00974
00975 group_off = cpl_bivector_new(k);
00976 cpl_vector_fill(cpl_bivector_get_y(group_off), 0.0);
00977 pgroup_off = cpl_bivector_get_x_data(group_off);
00978 k = 0;
00979 for (j=0 ; j<nima ; j++) {
00980 if (i+1 == groups[j]) {
00981 pgroup_off[k] = poffsets[j];
00982 k++;
00983 }
00984 }
00985 cpl_vector_subtract_scalar(cpl_bivector_get_x(group_off),
00986 pabba_off[i]);
00987
00988 cpl_msg_debug(fctid, "Apply shift-and-add for group %d", i+1);
00989 if ((combined = cpl_geom_img_offset_saa(group_list,
00990 group_off, CPL_KERNEL_DEFAULT, 0, 0,
00991 CPL_GEOM_FIRST)) == NULL) {
00992 cpl_msg_error(fctid, "Cannot shift and add group nb %d", i+1);
00993 cpl_imagelist_delete(group_list);
00994 cpl_bivector_delete(group_off);
00995 cpl_imagelist_delete(abba);
00996 cpl_vector_delete(*abba_off);
00997 return NULL;
00998 }
00999 cpl_bivector_delete(group_off);
01000 cpl_image_delete(combined[1]);
01001 cpl_imagelist_set(abba, combined[0], i);
01002 cpl_free(combined);
01003 } else {
01004
01005 cpl_msg_debug(fctid, "Apply averaging for group %d", i+1);
01006 if ((tmp_ima = cpl_imagelist_collapse_create(group_list)) == NULL) {
01007 cpl_msg_error(fctid, "Cannot average group nb %d", i+1);
01008 cpl_imagelist_delete(group_list);
01009 cpl_imagelist_delete(abba);
01010 cpl_vector_delete(*abba_off);
01011 return NULL;
01012 }
01013 cpl_imagelist_set(abba, tmp_ima, i);
01014 }
01015 cpl_imagelist_delete(group_list);
01016 }
01017 return abba;
01018 }
01019
01020
01028
01029 static int naco_spc_jitter_wavecal(
01030 char * arc,
01031 cpl_image * ima,
01032 cpl_frameset * raw)
01033 {
01034 const char * fctid = "naco_spc_jitter_wavecal";
01035 cpl_table * arc_tab;
01036 double * phdisprel;
01037 cpl_frame * cur_frame;
01038 const char * cur_fname;
01039 computed_disprel * disprel;
01040 int order;
01041 double slit_width;
01042
01043
01044 if (arc) {
01045 cpl_msg_info(fctid, "Get the wavelength from the ARC file");
01046 if ((arc_tab = cpl_table_load(arc, 1, 0)) == NULL) {
01047 cpl_msg_error(fctid, "Cannot load the arc table");
01048 naco_spc_jitter_config.wavecal_out = -1;
01049 return -1;
01050 }
01051 naco_spc_jitter_config.wavecal_a0 =
01052 cpl_table_get_double(arc_tab, "WL_coefficients", 0, NULL);
01053 naco_spc_jitter_config.wavecal_a1 =
01054 cpl_table_get_double(arc_tab, "WL_coefficients", 1, NULL);
01055 naco_spc_jitter_config.wavecal_a2 =
01056 cpl_table_get_double(arc_tab, "WL_coefficients", 2, NULL);
01057 naco_spc_jitter_config.wavecal_a3 =
01058 cpl_table_get_double(arc_tab, "WL_coefficients", 3, NULL);
01059 cpl_table_delete(arc_tab);
01060 naco_spc_jitter_config.wavecal_out = 2;
01061 naco_spc_jitter_config.wavecal_cc = -1.0;
01062 return 0;
01063 }
01064
01065
01066 cur_frame = cpl_frameset_get_frame(raw, 0);
01067 cur_fname = cpl_frame_get_filename(cur_frame);
01068
01069
01070 cpl_msg_info(fctid, "Compute the physical model");
01071 cpl_msg_indent_more();
01072 if ((phdisprel = naco_get_disprel_estimate(cur_fname, 3)) == NULL) {
01073 cpl_msg_error(fctid, "cannot compute the physical model");
01074 naco_spc_jitter_config.wavecal_out = -1;
01075 cpl_msg_indent_less();
01076 return -1;
01077 }
01078 cpl_msg_info(fctid, "f(x)=%g + %g*x + %g*x^2 + %g*x^3",
01079 phdisprel[0], phdisprel[1], phdisprel[2], phdisprel[3]);
01080 naco_spc_jitter_config.wavecal_a0 = phdisprel[0];
01081 naco_spc_jitter_config.wavecal_a1 = phdisprel[1];
01082 naco_spc_jitter_config.wavecal_a2 = phdisprel[2];
01083 naco_spc_jitter_config.wavecal_a3 = phdisprel[3];
01084 naco_spc_jitter_config.wavecal_cc = -1.0;
01085 naco_spc_jitter_config.wavecal_out = 0;
01086 cpl_msg_indent_less();
01087
01088
01089 if (naco_spc_jitter_config.wavecal_in == 1) {
01090
01091 if ((slit_width = naco_get_slitwidth(cur_fname)) == -1) {
01092 cpl_msg_warning(fctid, "cannot get the slit width");
01093 cpl_free(phdisprel);
01094 return 0;
01095 }
01096
01097 if ((order = naco_find_order(cur_fname)) == -1) {
01098 cpl_msg_warning(fctid, "cannot get the order");
01099 cpl_free(phdisprel);
01100 return 0;
01101 }
01102
01103 cpl_msg_info(fctid, "Compute the wavelength with the sky lines");
01104 cpl_msg_indent_more();
01105 if ((disprel = naco_spectro_compute_disprel(ima,
01106 naco_spc_jitter_config.wavecal_rej_bottom,
01107 naco_spc_jitter_config.wavecal_rej_top,
01108 naco_spc_jitter_config.wavecal_rej_left,
01109 naco_spc_jitter_config.wavecal_rej_right,
01110 naco_has_thermal(cur_fname) > 0,
01111 "oh", slit_width, order,
01112 (int)(cpl_msg_get_level() == CPL_MSG_DEBUG),
01113 phdisprel)) == NULL) {
01114 cpl_msg_error(fctid, "cannot compute the dispersion relation");
01115 cpl_free(phdisprel);
01116 cpl_msg_indent_less();
01117 return 0;
01118 }
01119 cpl_msg_info(fctid, "Cross correlation factor: %g", disprel->cc);
01120 cpl_msg_info(fctid, "f(x)=%g + %g*x + %g*x^2 + %g*x^3",
01121 disprel->poly[0], disprel->poly[1], disprel->poly[2],
01122 disprel->poly[3]);
01123 naco_spc_jitter_config.wavecal_a0 = disprel->poly[0];
01124 naco_spc_jitter_config.wavecal_a1 = disprel->poly[1];
01125 naco_spc_jitter_config.wavecal_a2 = disprel->poly[2];
01126 naco_spc_jitter_config.wavecal_a3 = disprel->poly[3];
01127 naco_spc_jitter_config.wavecal_cc = disprel->cc;
01128 naco_spc_jitter_config.wavecal_out = 1;
01129 if (disprel->poly != NULL) cpl_free(disprel->poly);
01130 cpl_free(disprel);
01131 cpl_msg_indent_less();
01132 }
01133 cpl_free(phdisprel);
01134 return 0;
01135 }
01136
01137
01169
01170 static cpl_imagelist * naco_spc_jitter_nodded(
01171 cpl_imagelist * abba,
01172 cpl_vector * abba_off,
01173 cpl_vector ** nodded_off)
01174 {
01175 const char * fctid = "naco_spc_jitter_nodded";
01176 cpl_imagelist * nodded;
01177 cpl_image * tmp_ima;
01178 int nima;
01179 double * pabba_off;
01180 double * pnodded_off;
01181 double ref_off;
01182 int i;
01183
01184
01185 if ((abba == NULL) || (abba_off == NULL)) return NULL;
01186
01187
01188 nima = cpl_imagelist_get_size(abba);
01189 if (nima % 2) {
01190 cpl_msg_error(fctid, "Number of images should be even");
01191 return NULL;
01192 }
01193
01194
01195 *nodded_off = cpl_vector_duplicate(abba_off);
01196
01197 nodded = cpl_imagelist_new();
01198 for (i=0 ; i<(nima/2) ; i++) {
01199
01200 tmp_ima = cpl_image_duplicate(cpl_imagelist_get(abba, 2*i));
01201 cpl_image_subtract(tmp_ima, cpl_imagelist_get(abba, 2*i+1));
01202 cpl_imagelist_set(nodded, tmp_ima, 2*i);
01203
01204 tmp_ima = cpl_image_duplicate(cpl_imagelist_get(abba, 2*i+1));
01205 cpl_image_subtract(tmp_ima, cpl_imagelist_get(abba, 2*i));
01206 cpl_imagelist_set(nodded, tmp_ima, 2*i+1);
01207 }
01208
01209
01210 ref_off = cpl_vector_get(*nodded_off, 0);
01211 cpl_vector_subtract_scalar(*nodded_off, ref_off);
01212 return nodded;
01213 }
01214
01215
01222
01223 static cpl_imagelist * naco_spc_jitter_distor(
01224 cpl_imagelist * ilist,
01225 char * arc)
01226 {
01227 const char * fctid = "naco_spc_jitter_distor";
01228 cpl_polynomial * arc_poly;
01229 cpl_polynomial * sttr_poly;
01230 cpl_table * tab;
01231 int pow[2];
01232 cpl_vector * profile;
01233 cpl_imagelist * warped_list;
01234 cpl_image * warped;
01235 int i;
01236
01237
01238 if (ilist == NULL) return NULL;
01239 if (arc == NULL) return NULL;
01240
01241
01242 arc_poly = cpl_polynomial_new(2);
01243 if (arc != NULL) {
01244 cpl_msg_info(fctid, "Get the arc distortion from the file");
01245 if ((tab = cpl_table_load(arc, 1, 0)) == NULL) {
01246 cpl_msg_error(fctid, "cannot load the arc table");
01247 cpl_polynomial_delete(arc_poly);
01248 return NULL;
01249 }
01250 for (i=0 ; i<cpl_table_get_nrow(tab) ; i++) {
01251 pow[0] = cpl_table_get_int(tab, "Degree_of_x", i, NULL);
01252 pow[1] = cpl_table_get_int(tab, "Degree_of_y", i, NULL);
01253 cpl_polynomial_set_coeff(arc_poly, pow,
01254 cpl_table_get_double(tab, "poly2d_coef", i, NULL));
01255 }
01256 cpl_table_delete(tab);
01257 } else {
01258 cpl_msg_info(fctid, "Use the ID polynomial for the arc dist");
01259 pow[0] = 1;
01260 pow[1] = 0;
01261 cpl_polynomial_set_coeff(arc_poly, pow, 1.0);
01262 }
01263
01264
01265 sttr_poly = cpl_polynomial_new(2);
01266 cpl_msg_info(fctid, "Use the ID polynomial for the startrace dist");
01267 pow[0] = 0;
01268 pow[1] = 1;
01269 cpl_polynomial_set_coeff(sttr_poly, pow, 1.0);
01270
01271
01272 profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES);
01273 cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_DEFAULT,
01274 CPL_KERNEL_DEF_WIDTH);
01275
01276
01277 warped_list = cpl_imagelist_new();
01278 for (i=0 ; i<cpl_imagelist_get_size(ilist) ; i++) {
01279 warped = cpl_image_duplicate(cpl_imagelist_get(ilist, i));
01280 if (cpl_image_warp_polynomial(warped, cpl_imagelist_get(ilist, i),
01281 arc_poly, sttr_poly, profile, CPL_KERNEL_DEF_WIDTH, profile,
01282 CPL_KERNEL_DEF_WIDTH) != CPL_ERROR_NONE) {
01283 cpl_msg_error(fctid, "cannot correct the distortion");
01284 cpl_image_delete(warped);
01285 cpl_polynomial_delete(arc_poly);
01286 cpl_polynomial_delete(sttr_poly);
01287 cpl_vector_delete(profile);
01288 return NULL;
01289 }
01290 cpl_imagelist_set(warped_list, warped, i);
01291 }
01292 cpl_vector_delete(profile);
01293 cpl_polynomial_delete(arc_poly);
01294 cpl_polynomial_delete(sttr_poly);
01295 return warped_list;
01296 }
01297
01298
01305
01306 static double naco_spc_jitter_refine_offset(
01307 cpl_image * ima1,
01308 cpl_image * ima2)
01309 {
01310 double pos1, pos2;
01311
01312
01313 if (ima1 == NULL) return 10000.0;
01314 if (ima2 == NULL) return 10000.0;
01315
01316
01317 if (irplib_spectrum_find_brightest(ima1, 0.0, NO_SHADOW, 0.0, 1,
01318 &pos1) == -1){
01319 return 10000.0;
01320 }
01321 if (irplib_spectrum_find_brightest(ima2, 0.0, NO_SHADOW, 0.0, 1,
01322 &pos2) == -1){
01323 return 10000.0;
01324 }
01325 return pos1-pos2;
01326 }
01327
01328
01334
01335 static cpl_table * naco_spc_jitter_extract(cpl_image * combined)
01336 {
01337 const char * fctid = "naco_spc_jitter_extract";
01338 int le_dist, ri_dist, le_width, ri_width, spec_pos;
01339 int nx, ny;
01340 double pos;
01341 int le_side, ri_side;
01342 int sky_pos[4];
01343 cpl_vector * sky;
01344 cpl_vector * spec;
01345 cpl_vector * wl;
01346 double * pspec;
01347 double * psky;
01348 double * pwl;
01349 cpl_table * out;
01350 cpl_bivector * toplot;
01351 int throw;
01352 int res;
01353 int i;
01354
01355
01356 if (combined == NULL) return NULL;
01357
01358
01359 nx = cpl_image_get_size_x(combined);
01360 ny = cpl_image_get_size_y(combined);
01361 le_dist = naco_spc_jitter_config.extr_sky_le_dist;
01362 ri_dist = naco_spc_jitter_config.extr_sky_ri_dist;
01363 le_width = naco_spc_jitter_config.extr_sky_le_width;
01364 ri_width = naco_spc_jitter_config.extr_sky_ri_width;
01365 spec_pos = naco_spc_jitter_config.extr_spec_pos;
01366
01367
01368 if (spec_pos < 0) {
01369 if (naco_spc_jitter_config.throws == NULL) {
01370 cpl_msg_error(fctid, "Need a throw value to detect the spectra !!");
01371 return NULL;
01372 }
01373
01374 for (i=0 ; i<cpl_vector_get_size(naco_spc_jitter_config.throws) ; i++){
01375 throw = (int)cpl_vector_get(naco_spc_jitter_config.throws, i);
01376 if ((res = irplib_spectrum_find_brightest(combined, throw,
01377 TWO_SHADOWS, 0.0, 1, &pos)) == 0) break;
01378 if ((res = irplib_spectrum_find_brightest(combined, throw,
01379 ONE_SHADOW, 0.0, 1, &pos)) == 0) break;
01380 }
01381 if (res != 0) {
01382 cpl_msg_error(fctid, "Cannot detect the spectrum");
01383 return NULL;
01384 }
01385 spec_pos = (int)pos;
01386 cpl_msg_info(fctid, "Spectrum detected at x = %d", spec_pos);
01387 }
01388
01389
01390
01391
01392 le_side = spec_pos - (int)(naco_spc_jitter_config.extr_spec_width/2);
01393 ri_side = le_side + naco_spc_jitter_config.extr_spec_width;
01394 if ((le_side < 1) || (ri_side > nx)) {
01395 cpl_msg_error(fctid, "Spectrum zone falls outside the image");
01396 return NULL;
01397 }
01398
01399 if (le_dist < 0) le_dist = 2 * naco_spc_jitter_config.extr_spec_width;
01400 if (ri_dist < 0) ri_dist = 2 * naco_spc_jitter_config.extr_spec_width;
01401 sky_pos[1] = spec_pos - le_dist;
01402 sky_pos[0] = sky_pos[1] - le_width;
01403 sky_pos[2] = spec_pos + ri_dist;
01404 sky_pos[3] = sky_pos[2] + ri_width;
01405
01406
01407 sky = cpl_vector_new(nx);
01408 psky = cpl_vector_get_data(sky);
01409 if (((sky_pos[0] < 1) || (le_width == 0)) &&
01410 ((sky_pos[3] <= nx) && (ri_width > 0))) {
01411 for (i=0 ; i<ny ; i++) {
01412 psky[i] = cpl_image_get_median_window(combined, sky_pos[2], i+1,
01413 sky_pos[3], i+1);
01414 }
01415 } else if (((sky_pos[3] > nx) || (ri_width == 0))
01416 && ((sky_pos[0] > 0) && (le_width > 0))) {
01417 for (i=0 ; i<ny ; i++) {
01418 psky[i] = cpl_image_get_median_window(combined, sky_pos[0], i+1,
01419 sky_pos[1], i+1);
01420 }
01421 } else if ((le_width != 0) && (ri_width != 0)
01422 && (sky_pos[0] > 0) && (sky_pos[3] <= nx)) {
01423 for (i=0 ; i<ny ; i++) {
01424 psky[i] = cpl_image_get_median_window(combined, sky_pos[2], i+1,
01425 sky_pos[3], i+1);
01426 psky[i] += cpl_image_get_median_window(combined, sky_pos[0], i+1,
01427 sky_pos[1], i+1);
01428 psky[i] /= 2.0;
01429 }
01430 } else {
01431 psky[i] = 0.0;
01432 }
01433
01434
01435 spec = cpl_vector_new(ny);
01436 pspec = cpl_vector_get_data(spec);
01437 for (i=0 ; i<ny ; i++) {
01438 pspec[i] = cpl_image_get_flux_window(combined, le_side, i+1, ri_side,
01439 i+1);
01440 pspec[i] -= psky[i] * naco_spc_jitter_config.extr_spec_width;
01441 }
01442
01443
01444 wl = cpl_vector_new(ny);
01445 pwl = cpl_vector_get_data(wl);
01446 for (i=0 ; i<ny ; i++) {
01447 pwl[i] = i+1;
01448
01449
01450
01451
01452
01453
01454 }
01455
01456
01457 if (naco_spc_jitter_config.display) {
01458 toplot = cpl_bivector_wrap_vectors(wl, spec);
01459 cpl_plot_bivector(NULL, "t 'Spectrum' w lines", NULL, toplot);
01460 cpl_bivector_unwrap_vectors(toplot);
01461 toplot = cpl_bivector_wrap_vectors(wl, sky);
01462 cpl_plot_bivector(NULL, "t 'Sky' w lines", NULL, toplot);
01463 cpl_bivector_unwrap_vectors(toplot);
01464 }
01465
01466
01467 out = cpl_table_new(nx);
01468 cpl_table_new_column(out, "Y_coordinate", CPL_TYPE_DOUBLE);
01469 cpl_table_new_column(out, "Extracted_spectrum_value", CPL_TYPE_DOUBLE);
01470 cpl_table_new_column(out, "Sky_spectrum", CPL_TYPE_DOUBLE);
01471 for (i=0 ; i<nx ; i++) {
01472 cpl_table_set_double(out, "Y_coordinate", i, pwl[i]);
01473 cpl_table_set_double(out, "Extracted_spectrum_value", i, pspec[i]);
01474 cpl_table_set_double(out, "Sky_spectrum", i, psky[i]);
01475 }
01476 cpl_vector_delete(wl);
01477 cpl_vector_delete(spec);
01478 cpl_vector_delete(sky);
01479 return out;
01480 }
01481
01482
01491
01492 static int naco_spc_jitter_save(
01493 const cpl_image * ima,
01494 const cpl_table * tab,
01495 cpl_parameterlist * parlist,
01496 cpl_frameset * set)
01497 {
01498 const char * fctid = "naco_spc_jitter_save";
01499 char name_o[512];
01500 FILE * paf;
01501 cpl_propertylist * plist;
01502 cpl_propertylist * qclist;
01503 cpl_propertylist * paflist;
01504 cpl_frame * ref_frame;
01505 cpl_frame * product_frame;
01506 char qc_str[128];
01507 int i;
01508
01509
01510 ref_frame = cpl_frameset_get_frame(set, 0);
01511
01512
01513
01514
01515
01516 sprintf(name_o, "naco_spc_jitter_combined.fits");
01517 cpl_msg_info(fctid, "Writing %s" , name_o);
01518
01519
01520 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
01521 0)) == NULL) {
01522 cpl_msg_error(fctid, "getting header from reference frame");
01523 return -1;
01524 }
01525
01526
01527 paflist = cpl_propertylist_new();
01528 cpl_propertylist_copy_property_regexp(paflist, plist,
01529 "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
01530 "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME|"
01531 "ESO INS GRAT WLEN|ESO INS OPTI1 ID|ESO OBS ID|ESO OBS TARG NAME)$", 0);
01532
01533
01534 product_frame = cpl_frame_new();
01535 cpl_frame_set_filename(product_frame, name_o);
01536 cpl_frame_set_tag(product_frame, NACO_SPC_JITTER_COMB);
01537 cpl_frame_set_type(product_frame, CPL_FRAME_TYPE_IMAGE);
01538 cpl_frame_set_group(product_frame, CPL_FRAME_GROUP_PRODUCT);
01539 cpl_frame_set_level(product_frame, CPL_FRAME_LEVEL_FINAL);
01540
01541
01542 if (cpl_dfs_setup_product_header(plist, product_frame, set, parlist,
01543 "naco_spc_jitter", PACKAGE "/" PACKAGE_VERSION,
01544 "PRO-1.15") != CPL_ERROR_NONE) {
01545 cpl_msg_warning(fctid, "Problem in the product DFS-compliance");
01546 cpl_error_reset();
01547 }
01548
01549
01550 cpl_propertylist_append_double(plist, "ESO QC DISPCO1",
01551 naco_spc_jitter_config.wavecal_a0);
01552 cpl_propertylist_append_double(plist, "ESO QC DISPCO2",
01553 naco_spc_jitter_config.wavecal_a1);
01554 cpl_propertylist_append_double(plist, "ESO QC DISPCO3",
01555 naco_spc_jitter_config.wavecal_a2);
01556 cpl_propertylist_append_double(plist, "ESO QC DISPCO4",
01557 naco_spc_jitter_config.wavecal_a3);
01558 cpl_propertylist_append_double(plist, "ESO QC WLEN",
01559 naco_spc_jitter_config.wavecal_a0 +
01560 naco_spc_jitter_config.wavecal_a1 * 512 +
01561 naco_spc_jitter_config.wavecal_a2 * 512 * 512 +
01562 naco_spc_jitter_config.wavecal_a3 * 512 * 512 * 512);
01563 cpl_propertylist_append_double(plist, "ESO QC DISP XCORR",
01564 naco_spc_jitter_config.wavecal_cc);
01565 if (naco_spc_jitter_config.wavecal_out == 0) {
01566 cpl_propertylist_append_string(plist, "ESO QC WLMETHOD",
01567 "physical model");
01568 } else if (naco_spc_jitter_config.wavecal_out == 1) {
01569 cpl_propertylist_append_string(plist, "ESO QC WLMETHOD",
01570 "sky lines");
01571 } else if (naco_spc_jitter_config.wavecal_out == 2) {
01572 cpl_propertylist_append_string(plist, "ESO QC WLMETHOD",
01573 "arc file");
01574 }
01575
01576
01577 qclist = cpl_propertylist_new();
01578 cpl_propertylist_copy_property_regexp(qclist, plist, "ESO QC", 0);
01579
01580
01581 cpl_propertylist_update_double(plist, "CRVAL1",
01582 naco_spc_jitter_config.wavecal_a0);
01583 cpl_propertylist_update_double(plist, "CRVAL2", 1.0);
01584 cpl_propertylist_update_double(plist, "CRPIX1", 1.0);
01585 cpl_propertylist_update_double(plist, "CRPIX2", 1.0);
01586 cpl_propertylist_update_double(plist, "CDELT1",
01587 naco_spc_jitter_config.wavecal_a1);
01588 cpl_propertylist_update_double(plist, "CDELT2", 1.0);
01589 cpl_propertylist_update_string(plist, "CTYPE1", "LINEAR");
01590 cpl_propertylist_update_string(plist, "CTYPE2", "LINEAR");
01591 cpl_propertylist_insert_after_double(plist, "CTYPE2", "CD1_1",
01592 naco_spc_jitter_config.wavecal_a1);
01593 cpl_propertylist_insert_after_double(plist, "CD1_1", "CD1_2", 1.0);
01594
01595
01596 cpl_image_save(ima, name_o, CPL_BPP_DEFAULT, plist, CPL_IO_DEFAULT);
01597 cpl_propertylist_delete(plist);
01598
01599
01600 cpl_frameset_insert(set, product_frame);
01601
01602 if (tab != NULL) {
01603
01604
01605
01606
01607 sprintf(name_o, "naco_spc_jitter_extracted.tfits");
01608 cpl_msg_info(fctid, "Writing %s" , name_o);
01609
01610
01611 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
01612 0)) == NULL) {
01613 cpl_msg_error(fctid, "getting header from reference frame");
01614 cpl_propertylist_delete(paflist);
01615 cpl_propertylist_delete(qclist);
01616 return -1;
01617 }
01618
01619
01620 product_frame = cpl_frame_new();
01621 cpl_frame_set_filename(product_frame, name_o);
01622 cpl_frame_set_tag(product_frame, NACO_SPC_JITTER_EXTR);
01623 cpl_frame_set_type(product_frame, CPL_FRAME_TYPE_TABLE);
01624 cpl_frame_set_group(product_frame, CPL_FRAME_GROUP_PRODUCT);
01625 cpl_frame_set_level(product_frame, CPL_FRAME_LEVEL_FINAL);
01626
01627
01628 if (cpl_dfs_setup_product_header(plist, product_frame, set, parlist,
01629 "naco_spc_jitter", PACKAGE "/" PACKAGE_VERSION,
01630 "PRO-1.15") != CPL_ERROR_NONE){
01631 cpl_msg_warning(fctid, "Problem in the product DFS-compliance");
01632 cpl_error_reset();
01633 }
01634
01635
01636 cpl_table_save(tab, plist, NULL, name_o, CPL_IO_DEFAULT);
01637 cpl_propertylist_delete(plist);
01638
01639
01640 cpl_frameset_insert(set, product_frame);
01641 }
01642
01643
01644
01645
01646
01647
01648 sprintf(name_o, "naco_spc_jitter.paf");
01649 cpl_msg_info(fctid, "Writing %s" , name_o);
01650
01651
01652 if ((paf = irplib_paf_print_header(name_o,
01653 "NACO/naco_spc_jitter",
01654 "QC file")) == NULL) {
01655 cpl_msg_error(fctid, "cannot open file [%s] for output", name_o);
01656 cpl_propertylist_delete(paflist);
01657 cpl_propertylist_delete(qclist);
01658 return -1;
01659 }
01660
01661
01662 if (irplib_propertylist_dump_paf(paflist, paf) != CPL_ERROR_NONE) {
01663 cpl_msg_error(fctid, "cannot dump the keys in PAF file");
01664 cpl_propertylist_delete(paflist);
01665 cpl_propertylist_delete(qclist);
01666 fclose(paf);
01667 return -1;
01668 }
01669 cpl_propertylist_delete(paflist);
01670
01671
01672 if (irplib_propertylist_dump_paf(qclist, paf) != CPL_ERROR_NONE) {
01673 cpl_msg_error(fctid, "cannot dump the QC keys in PAF file");
01674 cpl_propertylist_delete(qclist);
01675 fclose(paf);
01676 return -1;
01677 }
01678 cpl_propertylist_delete(qclist);
01679 fclose(paf);
01680
01681
01682 return 0;
01683 }
01684
01685
01693
01694 static int off_comp(double off1, double off2, double thresh)
01695 {
01696 if (((off1>thresh) && (off2<thresh)) || ((off1<thresh) && (off2>thresh)))
01697 return 1;
01698 else return 0;
01699 }