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