00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include <string.h>
00037 #include <math.h>
00038 #include <float.h>
00039 #include <cpl.h>
00040
00041 #include "irplib_plugin.h"
00042 #include "irplib_utils.h"
00043 #include "irplib_distortion.h"
00044 #include "irplib_wlxcorr.h"
00045
00046 #include "sofi_utils.h"
00047 #include "sofi_wavelength.h"
00048 #include "sofi_pfits.h"
00049 #include "sofi_dfs.h"
00050
00051
00052
00053
00054
00055 #define RECIPE_STRING "sofi_spc_arc"
00056
00057 #define SOFI_ARC_SATURATION 20000
00058
00059
00060
00061
00062
00063 static cpl_error_code sofi_spc_arc_reduce(cpl_frameset *,
00064 const cpl_parameterlist *,
00065 const char *, const char *,
00066 const cpl_frameset *,
00067 cpl_errorstate);
00068 static cpl_table * sofi_spc_arc_compute(const cpl_image *, const char *,
00069 const char *, const char *, const char *, cpl_table **, cpl_image **);
00070 static cpl_error_code sofi_spc_arc_save(cpl_frameset *, const cpl_table *,
00071 const cpl_table *,
00072 const cpl_image *, const char *,
00073 const cpl_frameset *,
00074 const cpl_parameterlist *);
00075 static int sofi_spc_arc_compare(const cpl_frame *, const cpl_frame *);
00076 static int * sofi_spc_arc_find_lamps(const cpl_frameset *);
00077 static int sofi_is_xenon_lamp_active(const cpl_propertylist *);
00078 static int sofi_is_neon_lamp_active(const cpl_propertylist *);
00079
00080 cpl_recipe_define(sofi_spc_arc, SOFI_BINARY_VERSION,
00081 "Lars Lundin", PACKAGE_BUGREPORT, "2002,2003,2009",
00082 "SOFI Spectro arc recipe",
00083 RECIPE_STRING " -- SOFI Spectro arc recipe.\n"
00084 "The files listed in the Set Of Frames (sof-file) "
00085 "must be tagged:\n"
00086 "raw-file.fits "SOFI_SPC_ARC_RAW" or\n"
00087 "xe-cat.fits "SOFI_CALPRO_XE_CAT" or\n"
00088 "ne-cat.fits "SOFI_CALPRO_NE_CAT"\n");
00089
00090
00091
00092
00093
00094 static struct {
00095
00096 int display;
00097 int rej_left;
00098 int rej_right;
00099 int subdark;
00100 int arc_max_w;
00101 int out_corr;
00102 cpl_size degree;
00103 double wl_err;
00104 int wl_nsamples;
00105 int ppm;
00106 const char * lines;
00107
00108 int set_nb;
00109 int frame_nb;
00110 int nb_saturated;
00111 double disprel_cc;
00112 double fwhm_med;
00113 int fwhm_good;
00114 } sofi_spc_arc_config;
00115
00116
00117
00118
00119
00120
00128
00129 static
00130 cpl_error_code sofi_spc_arc_fill_parameterlist(cpl_parameterlist * self)
00131 {
00132 const char * context = PACKAGE "." RECIPE_STRING;
00133 cpl_error_code err;
00134
00135 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00136
00137
00138
00139
00140 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00141 "rejected", "100,100", "rej", context,
00142 "Left, right rejections [pixel]");
00143 cpl_ensure_code(!err, err);
00144
00145
00146 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "subdark",
00147 CPL_FALSE, NULL, context,
00148 "Enable dark subtraction");
00149 cpl_ensure_code(!err, err);
00150
00151
00152 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "arc_max_w",
00153 33, NULL, context, "Maximum supported "
00154 "arc width [pixel]");
00155 cpl_ensure_code(!err, err);
00156
00157
00158 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "out_corr",
00159 CPL_FALSE, NULL, context,
00160 "Enable correction of output images");
00161 cpl_ensure_code(!err, err);
00162
00163
00164 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "display",
00165 CPL_FALSE, NULL, context,
00166 "Enable plotting");
00167 cpl_ensure_code(!err, err);
00168
00169
00170 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "degree",
00171 2, NULL, context, "Degree of the "
00172 "wavelength dispersion polynomial");
00173 cpl_ensure_code(!err, err);
00174
00175
00176 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00177 "wl_nsamples", 100, NULL, context,
00178 "Number of samples for the wavelength "
00179 "calibration");
00180 cpl_ensure_code(!err, err);
00181
00182
00183 err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING,
00184 "wl_err", 1000.0, NULL, context,
00185 "The wavelength error [Angstrom]");
00186 cpl_ensure_code(!err, err);
00187
00188
00189 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00190 "lines", NULL, NULL, context,
00191 "Lines ASCII-file");
00192 cpl_ensure_code(!err, err);
00193
00194
00195 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "ppm",
00196 CPL_FALSE, NULL, context,
00197 "Enable Point Pattern Matching");
00198 cpl_ensure_code(!err, err);
00199
00200 return CPL_ERROR_NONE;
00201 }
00202
00203
00204
00211
00212 static int sofi_spc_arc(cpl_frameset * framelist,
00213 const cpl_parameterlist * parlist)
00214 {
00215 cpl_errorstate prestate = cpl_errorstate_get();
00216 const char * sval;
00217 cpl_size * labels = NULL;
00218 cpl_size nlabels;
00219 const int nframes = cpl_frameset_get_size(framelist);
00220 int narcs;
00221 const char * xe;
00222 const char * ne;
00223 cpl_frameset * arcframes = NULL;
00224 cpl_frameset * arc_one = NULL;
00225 int i;
00226
00227
00228 sofi_spc_arc_config.lines = NULL;
00229
00230
00231
00232
00233 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00234 "rejected");
00235 bug_if(sval == NULL);
00236
00237 skip_if (sscanf(sval, "%d,%d",
00238 &sofi_spc_arc_config.rej_left,
00239 &sofi_spc_arc_config.rej_right) != 2);
00240
00241
00242 sofi_spc_arc_config.out_corr
00243 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00244 "out_corr");
00245
00246 sofi_spc_arc_config.subdark
00247 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00248 "subdark");
00249
00250 sofi_spc_arc_config.ppm
00251 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00252 "ppm");
00253
00254 sofi_spc_arc_config.degree
00255 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00256 "degree");
00257
00258
00259 sofi_spc_arc_config.wl_nsamples
00260 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00261 "wl_nsamples");
00262
00263
00264 sofi_spc_arc_config.wl_err
00265 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
00266 "wl_err");
00267
00268
00269 sofi_spc_arc_config.arc_max_w
00270 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00271 "arc_max_w");
00272
00273
00274 sofi_spc_arc_config.display
00275 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00276 "display");
00277
00278
00279 sofi_spc_arc_config.lines
00280 = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00281 "lines");
00282
00283
00284 skip_if (sofi_dfs_set_groups(framelist));
00285
00286
00287 arcframes = sofi_extract_frameset(framelist, SOFI_SPC_ARC_RAW);
00288 error_if (arcframes == NULL, CPL_ERROR_DATA_NOT_FOUND,
00289 "Cannot find arc frames in the input frame set");
00290
00291 narcs = cpl_frameset_get_size(arcframes);
00292
00293
00294 xe = sofi_extract_filename(framelist, SOFI_CALPRO_XE_CAT);
00295 ne = sofi_extract_filename(framelist, SOFI_CALPRO_NE_CAT);
00296
00297
00298 labels = cpl_frameset_labelise(arcframes, sofi_spc_arc_compare, &nlabels);
00299 error_if (labels == NULL, CPL_ERROR_ILLEGAL_INPUT,
00300 "Cannot labelise the input frames");
00301
00302
00303 for (i=0; i < nlabels; i++) {
00304
00305
00306 cpl_msg_info(cpl_func, "Reducing set %d/%d", i+1, (int)nlabels);
00307
00308 sofi_spc_arc_config.set_nb = i+1;
00309
00310 cpl_frameset_delete(arc_one);
00311 arc_one = cpl_frameset_extract(arcframes, labels, i);
00312
00313
00314 if (sofi_spc_arc_reduce(framelist, parlist, xe, ne, arc_one, prestate))
00315 (void)cpl_error_set_message(cpl_func, cpl_error_get_code(), "Could "
00316 "not reduce set %d of %d with %d arc "
00317 "frame(s)", i+1, (int)nlabels,
00318 (int)cpl_frameset_get_size(arc_one));
00319 }
00320
00321 error_if (cpl_frameset_get_size(framelist) == nframes,
00322 CPL_ERROR_ILLEGAL_INPUT, "No products produced from %d arc "
00323 "frames grouped into %d set(s)", narcs, (int)nlabels);
00324
00325 end_skip;
00326
00327 cpl_frameset_delete(arcframes);
00328 cpl_frameset_delete(arc_one);
00329 cpl_free(labels);
00330
00331 return cpl_error_get_code();
00332 }
00333
00334
00346
00347 static cpl_error_code sofi_spc_arc_reduce(cpl_frameset * set_tot,
00348 const cpl_parameterlist * parlist,
00349 const char * xe,
00350 const char * ne,
00351 const cpl_frameset * arcframes,
00352 cpl_errorstate prestate)
00353 {
00354
00355
00356
00357
00358
00359 int * lamps = sofi_spc_arc_find_lamps(arcframes);
00360 const int nframes = cpl_frameset_get_size(arcframes);
00361 char lines_table[16];
00362 const cpl_frame * cur_frame;
00363 const char * cur_fname;
00364 cpl_image * xenon = NULL;
00365 cpl_image * neon = NULL;
00366 cpl_image * xe_ne = NULL;
00367 cpl_image * dark = NULL;
00368 cpl_image * to_compute;
00369 cpl_table * arcs_fwhm;
00370 cpl_image * out_corr;
00371 cpl_table * out_table;
00372 int i;
00373
00374
00375 sofi_spc_arc_config.frame_nb = 0;
00376
00377 if (lamps == NULL) return cpl_error_set_where(cpl_func);
00378
00379
00380 for (i=0; i<nframes; i++) {
00381 cur_frame = cpl_frameset_get_frame_const(arcframes, i);
00382 cur_fname = cpl_frame_get_filename(cur_frame);
00383 if ((lamps[i] == 0) && (dark == NULL)) {
00384 cpl_msg_info(cpl_func, "Dark image: [%s]", cur_fname);
00385 dark = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
00386 } else if ((lamps[i] == 1) && (xenon == NULL)) {
00387 cpl_msg_info(cpl_func, "Xenon lamp: [%s]", cur_fname);
00388 xenon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
00389 } else if ((lamps[i] == 2) && (neon == NULL)) {
00390 cpl_msg_info(cpl_func, "Neon lamp: [%s]", cur_fname);
00391 neon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
00392 } else if ((lamps[i] == 3) && (xe_ne == NULL)) {
00393 cpl_msg_info(cpl_func, "Xenon+Neon lamp: [%s]", cur_fname);
00394 xe_ne = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
00395 }
00396 }
00397 cpl_free(lamps);
00398
00399
00400 if (!xenon && !neon && !xe_ne) {
00401 cpl_image_delete(dark);
00402 return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00403 "Neither xenon nor neon lamp activated");
00404 }
00405
00406
00407 cur_frame = cpl_frameset_get_frame_const(arcframes, 0);
00408 cur_fname = cpl_frame_get_filename(cur_frame);
00409
00410
00411 if (xenon) {
00412 if (!cpl_errorstate_is_equal(prestate)) {
00413 cpl_msg_warning(cpl_func, "Resetting CPL error before reducing "
00414 "Xenon data:");
00415 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
00416 cpl_errorstate_set(prestate);
00417 }
00418 if (dark) to_compute = cpl_image_subtract_create(xenon, dark);
00419 else to_compute = cpl_image_duplicate(xenon);
00420 cpl_image_delete(xenon);
00421 strcpy(lines_table, "Xe");
00422
00423
00424 cpl_msg_info(cpl_func, "Apply the reduction");
00425 sofi_spc_arc_config.frame_nb ++;
00426 cpl_msg_indent_more();
00427 if ((out_table = sofi_spc_arc_compute(to_compute, cur_fname,
00428 lines_table, xe, ne, &arcs_fwhm, &out_corr)) == NULL) {
00429 cpl_msg_error(cpl_func, "arc reduction computation failed");
00430 cpl_image_delete(to_compute);
00431 } else {
00432
00433 cpl_image_delete(to_compute);
00434 cpl_msg_info(cpl_func, "Save the products");
00435 sofi_spc_arc_save(set_tot, out_table, arcs_fwhm, out_corr,
00436 lines_table, arcframes, parlist);
00437 cpl_table_delete(out_table);
00438 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
00439 if (out_corr) cpl_image_delete(out_corr);
00440 }
00441 cpl_msg_indent_less();
00442 }
00443
00444
00445 if (neon) {
00446 if (!cpl_errorstate_is_equal(prestate)) {
00447 cpl_msg_warning(cpl_func, "Resetting CPL error before reducing "
00448 "Neon data:");
00449 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
00450 cpl_errorstate_set(prestate);
00451 }
00452 if (dark) to_compute = cpl_image_subtract_create(neon, dark);
00453 else to_compute = cpl_image_duplicate(neon);
00454 cpl_image_delete(neon);
00455 strcpy(lines_table, "Ne");
00456
00457
00458 cpl_msg_info(cpl_func, "Apply the reduction");
00459 sofi_spc_arc_config.frame_nb ++;
00460 cpl_msg_indent_more();
00461 if ((out_table = sofi_spc_arc_compute(to_compute, cur_fname,
00462 lines_table, xe, ne, &arcs_fwhm, &out_corr)) == NULL) {
00463 cpl_msg_error(cpl_func, "arc reduction computation failed");
00464 cpl_image_delete(to_compute);
00465 } else {
00466
00467 cpl_image_delete(to_compute);
00468 cpl_msg_info(cpl_func, "Save the products");
00469 sofi_spc_arc_save(set_tot, out_table, arcs_fwhm, out_corr,
00470 lines_table, arcframes, parlist);
00471 cpl_table_delete(out_table);
00472 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
00473 if (out_corr) cpl_image_delete(out_corr);
00474 }
00475 cpl_msg_indent_less();
00476 }
00477
00478
00479
00480 if (xe_ne) {
00481 if (!cpl_errorstate_is_equal(prestate)) {
00482 cpl_msg_warning(cpl_func, "Resetting CPL error before reducing "
00483 "Xenon+Neon data:");
00484 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
00485 cpl_errorstate_set(prestate);
00486 }
00487 if (dark) to_compute = cpl_image_subtract_create(xe_ne, dark);
00488 else to_compute = cpl_image_duplicate(xe_ne);
00489 cpl_image_delete(xe_ne);
00490 strcpy(lines_table, "Xe+Ne");
00491
00492
00493 cpl_msg_info(cpl_func, "Apply the reduction");
00494 sofi_spc_arc_config.frame_nb ++;
00495 cpl_msg_indent_more();
00496 if ((out_table = sofi_spc_arc_compute(to_compute, cur_fname,
00497 lines_table, xe, ne, &arcs_fwhm, &out_corr)) == NULL) {
00498 cpl_msg_error(cpl_func, "arc reduction computation failed");
00499 cpl_image_delete(to_compute);
00500 } else {
00501
00502 cpl_image_delete(to_compute);
00503 cpl_msg_info(cpl_func, "Save the products");
00504 sofi_spc_arc_save(set_tot, out_table, arcs_fwhm, out_corr,
00505 lines_table, arcframes, parlist);
00506 cpl_table_delete(out_table);
00507 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
00508 if (out_corr) cpl_image_delete(out_corr);
00509 }
00510 cpl_msg_indent_less();
00511 }
00512 cpl_image_delete(dark);
00513
00514 return cpl_error_get_code();
00515 }
00516
00517
00530
00531 static cpl_table * sofi_spc_arc_compute(
00532 const cpl_image * in,
00533 const char * in_name,
00534 const char * lines_table,
00535 const char * xe,
00536 const char * ne,
00537 cpl_table ** arcs_fwhm,
00538 cpl_image ** out_corr)
00539 {
00540 cpl_image * flipped;
00541 cpl_table * out_tab;
00542 int xmin, ymin, xmax, ymax;
00543 int nx, ny;
00544 cpl_mask * saturation_map;
00545 double slit_width;
00546 cpl_polynomial * distor_poly_flipped;
00547 cpl_polynomial * distor_poly;
00548 cpl_polynomial * poly2d_id;
00549 cpl_vector * profile;
00550 cpl_image * in_corr;
00551 cpl_apertures * arcs;
00552 cpl_polynomial * phdisprel;
00553 cpl_polynomial * disprel;
00554 cpl_size power[5];
00555 int degree;
00556 double a, b, c, d, e, xc;
00557 cpl_size power_flipped[2];
00558 double fwhm_x, fwhm_y;
00559 cpl_vector * fwhm_valid;
00560 int i;
00561
00562
00563 nx = cpl_image_get_size_x(in);
00564 ny = cpl_image_get_size_y(in);
00565 *arcs_fwhm = NULL;
00566 *out_corr = NULL;
00567
00568
00569 xmin = sofi_spc_arc_config.rej_left + 1;
00570 xmax = nx - sofi_spc_arc_config.rej_right;
00571 ymin = 1;
00572 ymax = ny;
00573
00574
00575 saturation_map = cpl_mask_threshold_image_create(in,
00576 SOFI_ARC_SATURATION, DBL_MAX);
00577 if (saturation_map != NULL) {
00578 sofi_spc_arc_config.nb_saturated = cpl_mask_count(saturation_map);
00579 cpl_mask_delete(saturation_map);
00580 } else {
00581 sofi_spc_arc_config.nb_saturated = 0;
00582 }
00583
00584
00585 cpl_msg_info(cpl_func, "Estimate the distortion");
00586 cpl_msg_indent_more();
00587
00588 flipped = cpl_image_duplicate(in);
00589 cpl_image_flip(flipped, 1);
00590 if ((distor_poly_flipped = irplib_distortion_estimate(flipped,
00591 ymin, xmin, ymax, xmax,
00592 sofi_spc_arc_config.subdark, SOFI_ARC_SATURATION,
00593 sofi_spc_arc_config.arc_max_w, 0.33,2,&arcs)) == NULL) {
00594 cpl_msg_error(cpl_func, "cannot estimage distortion");
00595 cpl_image_delete(flipped);
00596 cpl_msg_indent_less();
00597 return NULL;
00598 }
00599 cpl_image_delete(flipped);
00600 cpl_msg_indent_less();
00601
00602
00603 distor_poly = cpl_polynomial_duplicate(distor_poly_flipped);
00604 power[0] = 1; power[1] = 0; power_flipped[0] = 0; power_flipped[1] = 1;
00605 cpl_polynomial_set_coeff(distor_poly, power,
00606 cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
00607
00608 power[0] = 2; power[1] = 0; power_flipped[0] = 0; power_flipped[1] = 2;
00609 cpl_polynomial_set_coeff(distor_poly, power,
00610 cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
00611
00612 power[0] = 0; power[1] = 1; power_flipped[0] = 1; power_flipped[1] = 0;
00613 cpl_polynomial_set_coeff(distor_poly, power,
00614 cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
00615
00616 power[0] = 0; power[1] = 2; power_flipped[0] = 2; power_flipped[1] = 0;
00617 cpl_polynomial_set_coeff(distor_poly, power,
00618 cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
00619 cpl_polynomial_delete(distor_poly_flipped);
00620
00621
00622 cpl_msg_info(cpl_func, "Correct the distortion");
00623 cpl_msg_indent_more();
00624 in_corr = cpl_image_duplicate(in);
00625
00626
00627 poly2d_id = cpl_polynomial_new(2);
00628 power[0] = 1; power[1] = 0;
00629 cpl_polynomial_set_coeff(poly2d_id, power, 1.0);
00630
00631
00632 profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES);
00633 cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_DEFAULT,
00634 CPL_KERNEL_DEF_WIDTH);
00635
00636
00637 if (cpl_image_warp_polynomial(in_corr, in, poly2d_id, distor_poly,
00638 profile, CPL_KERNEL_DEF_WIDTH, profile,
00639 CPL_KERNEL_DEF_WIDTH) != CPL_ERROR_NONE) {
00640 cpl_msg_error(cpl_func, "cannot correct the distortion");
00641 cpl_image_delete(in_corr);
00642 cpl_polynomial_delete(poly2d_id);
00643 cpl_polynomial_delete(distor_poly);
00644 cpl_vector_delete(profile);
00645 cpl_msg_indent_less();
00646 return NULL;
00647 }
00648 cpl_polynomial_delete(poly2d_id);
00649 cpl_vector_delete(profile);
00650 cpl_msg_indent_less();
00651
00652
00653 cpl_msg_info(cpl_func, "Compute the FWHM of the detected arcs");
00654
00655 *arcs_fwhm = cpl_table_new(cpl_apertures_get_size(arcs));
00656 cpl_table_new_column(*arcs_fwhm, "POS", CPL_TYPE_DOUBLE);
00657 cpl_table_new_column(*arcs_fwhm, "FWHM", CPL_TYPE_DOUBLE);
00658 cpl_table_new_column(*arcs_fwhm, "FLUX", CPL_TYPE_DOUBLE);
00659
00660 sofi_spc_arc_config.fwhm_good = 0;
00661 for (i=0; i<cpl_apertures_get_size(arcs); i++) {
00662 cpl_table_set_double(*arcs_fwhm, "POS", i,
00663 cpl_apertures_get_centroid_x(arcs, i+1));
00664 cpl_table_set_double(*arcs_fwhm, "FLUX", i,
00665 cpl_apertures_get_flux(arcs, i+1));
00666 if (cpl_image_get_fwhm(in_corr, cpl_apertures_get_centroid_x(arcs, i+1),
00667 512, &fwhm_x, &fwhm_y) != CPL_ERROR_NONE) {
00668 cpl_msg_warning(cpl_func, "Cannot get the FWHM");
00669 cpl_error_reset();
00670 }
00671 cpl_table_set_double(*arcs_fwhm, "FWHM", i, fwhm_x);
00672 if (fwhm_x > 0) sofi_spc_arc_config.fwhm_good ++;
00673 }
00674 cpl_apertures_delete(arcs);
00675
00676
00677 if (sofi_spc_arc_config.fwhm_good > 0) {
00678 fwhm_valid = cpl_vector_new(sofi_spc_arc_config.fwhm_good);
00679 sofi_spc_arc_config.fwhm_good = 0;
00680 for (i=0; i<cpl_table_get_nrow(*arcs_fwhm); i++) {
00681 fwhm_x = cpl_table_get_double(*arcs_fwhm, "FWHM", i, NULL);
00682 if (fwhm_x > 0) {
00683 cpl_vector_set(fwhm_valid, sofi_spc_arc_config.fwhm_good,
00684 fwhm_x);
00685 sofi_spc_arc_config.fwhm_good ++;
00686 }
00687 }
00688 sofi_spc_arc_config.fwhm_med = cpl_vector_get_median_const(fwhm_valid);
00689 cpl_vector_delete(fwhm_valid);
00690 } else sofi_spc_arc_config.fwhm_med = 0.0;
00691
00692
00693
00694
00695 if ((slit_width = sofi_get_slitwidth(in_name)) == -1) {
00696 cpl_msg_error(cpl_func, "cannot get the slit width");
00697 cpl_polynomial_delete(distor_poly);
00698 cpl_image_delete(in_corr);
00699 cpl_table_delete(*arcs_fwhm);
00700 *arcs_fwhm = NULL;
00701 return NULL;
00702 }
00703
00704
00705 cpl_msg_info(cpl_func, "Get the dispersion estimation");
00706 cpl_msg_indent_more();
00707 if ((phdisprel = sofi_get_disprel_estimate(in_name, 1)) == NULL) {
00708 cpl_msg_error(cpl_func, "cannot estimate the dispersion relation");
00709 cpl_polynomial_delete(distor_poly);
00710 cpl_image_delete(in_corr);
00711 cpl_table_delete(*arcs_fwhm);
00712 *arcs_fwhm = NULL;
00713 cpl_msg_indent_less();
00714 return NULL;
00715 }
00716 power[0] = 0; power[1] = 1;
00717 a = cpl_polynomial_get_coeff(phdisprel, power);
00718 b = cpl_polynomial_get_coeff(phdisprel, power + 1);
00719 cpl_msg_info(cpl_func, "f(x)=%g + %g*x", a, b);
00720 cpl_msg_indent_less();
00721
00722
00723 cpl_msg_info(cpl_func, "Compute the dispersion relation");
00724 cpl_msg_indent_more();
00725 if ((disprel = sofi_wavelength_engine(in_corr, lines_table, NULL, xe, ne,
00726 phdisprel, slit_width, sofi_spc_arc_config.degree,
00727 sofi_spc_arc_config.wl_err,
00728 sofi_spc_arc_config.wl_nsamples,
00729 sofi_spc_arc_config.ppm, sofi_spc_arc_config.display,
00730 &xc)) == NULL) {
00731 cpl_msg_error(cpl_func, "cannot compute the dispersion relation");
00732 cpl_polynomial_delete(distor_poly);
00733 cpl_image_delete(in_corr);
00734 cpl_polynomial_delete(phdisprel);
00735 cpl_table_delete(*arcs_fwhm);
00736 *arcs_fwhm = NULL;
00737 cpl_msg_indent_less();
00738 return NULL;
00739 }
00740 if (sofi_spc_arc_config.out_corr) {
00741 *out_corr = in_corr;
00742 in_corr = NULL;
00743 } else {
00744 cpl_image_delete(in_corr);
00745 }
00746
00747
00748 if (sofi_spc_arc_config.display && sofi_spc_arc_config.lines != NULL &&
00749 sofi_spc_arc_config.lines[0] != (char)0) {
00750
00751 cpl_bivector * lines_biv
00752 = cpl_bivector_read(sofi_spc_arc_config.lines);
00753 const int nlines = cpl_bivector_get_size(lines_biv);
00754
00755 if (nlines > sofi_spc_arc_config.degree) {
00756
00757
00758 cpl_matrix * xpos
00759 = cpl_matrix_wrap(1, nlines, cpl_bivector_get_x_data(lines_biv));
00760 cpl_polynomial * poly_sol = cpl_polynomial_new(1);
00761
00762 if (!cpl_polynomial_fit(poly_sol, xpos, NULL,
00763 cpl_bivector_get_y(lines_biv), NULL,
00764 CPL_FALSE, NULL,
00765 &(sofi_spc_arc_config.degree))) {
00766 irplib_wlxcorr_plot_solution(phdisprel, disprel, poly_sol, 1,
00767 1024);
00768 }
00769 (void)cpl_matrix_unwrap(xpos);
00770 cpl_polynomial_delete(poly_sol);
00771 }
00772 cpl_bivector_delete(lines_biv);
00773 }
00774 cpl_polynomial_delete(phdisprel);
00775 cpl_msg_info(cpl_func, "Cross correlation factor: %g", xc);
00776 power[0] = 0; power[1] = 1; power[2] = 2; power[3] = 3; power[4] = 4;
00777 a = b = c = d = e = 0.0;
00778 degree = cpl_polynomial_get_degree(disprel);
00779 a = cpl_polynomial_get_coeff(disprel, power);
00780 if (degree > 0) b = cpl_polynomial_get_coeff(disprel, power + 1);
00781 if (degree > 1) c = cpl_polynomial_get_coeff(disprel, power + 2);
00782 if (degree > 2) d = cpl_polynomial_get_coeff(disprel, power + 3);
00783 if (degree > 3) e = cpl_polynomial_get_coeff(disprel, power + 4);
00784 cpl_polynomial_delete(disprel);
00785 if (degree == 0)
00786 cpl_msg_info(cpl_func, "f(x)=%g", a);
00787 if (degree == 1)
00788 cpl_msg_info(cpl_func, "f(x)=%g + %g*x", a, b);
00789 if (degree == 2)
00790 cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2", a, b, c);
00791 if (degree == 3)
00792 cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3", a, b, c, d);
00793 if (degree == 4)
00794 cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3 + %g*x^4",
00795 a, b, c, d, e);
00796 cpl_msg_indent_less();
00797
00798
00799 out_tab = cpl_table_new(6);
00800
00801
00802 cpl_table_new_column(out_tab, "Degree_of_x", CPL_TYPE_INT);
00803 cpl_table_new_column(out_tab, "Degree_of_y", CPL_TYPE_INT);
00804 cpl_table_new_column(out_tab, "poly2d_coef", CPL_TYPE_DOUBLE);
00805 power[0] = 0; power[1] = 0;
00806 cpl_table_set_int(out_tab, "Degree_of_x", 0, power[0]);
00807 cpl_table_set_int(out_tab, "Degree_of_y", 0, power[1]);
00808 cpl_table_set_double(out_tab, "poly2d_coef", 0,
00809 cpl_polynomial_get_coeff(distor_poly, power));
00810 power[0] = 1; power[1] = 0;
00811 cpl_table_set_int(out_tab, "Degree_of_x", 1, power[0]);
00812 cpl_table_set_int(out_tab, "Degree_of_y", 1, power[1]);
00813 cpl_table_set_double(out_tab, "poly2d_coef", 1,
00814 cpl_polynomial_get_coeff(distor_poly, power));
00815 power[0] = 0; power[1] = 1;
00816 cpl_table_set_int(out_tab, "Degree_of_x", 2, power[0]);
00817 cpl_table_set_int(out_tab, "Degree_of_y", 2, power[1]);
00818 cpl_table_set_double(out_tab, "poly2d_coef", 2,
00819 cpl_polynomial_get_coeff(distor_poly, power));
00820 power[0] = 1; power[1] = 1;
00821 cpl_table_set_int(out_tab, "Degree_of_x", 3, power[0]);
00822 cpl_table_set_int(out_tab, "Degree_of_y", 3, power[1]);
00823 cpl_table_set_double(out_tab, "poly2d_coef", 3,
00824 cpl_polynomial_get_coeff(distor_poly, power));
00825 power[0] = 2; power[1] = 0;
00826 cpl_table_set_int(out_tab, "Degree_of_x", 4, power[0]);
00827 cpl_table_set_int(out_tab, "Degree_of_y", 4, power[1]);
00828 cpl_table_set_double(out_tab, "poly2d_coef", 4,
00829 cpl_polynomial_get_coeff(distor_poly, power));
00830 power[0] = 0; power[1] = 2;
00831 cpl_table_set_int(out_tab, "Degree_of_x", 5, power[0]);
00832 cpl_table_set_int(out_tab, "Degree_of_y", 5, power[1]);
00833 cpl_table_set_double(out_tab, "poly2d_coef", 5,
00834 cpl_polynomial_get_coeff(distor_poly, power));
00835
00836
00837 cpl_table_new_column(out_tab, "WL_coefficients", CPL_TYPE_DOUBLE);
00838 cpl_table_set_double(out_tab, "WL_coefficients", 0, a);
00839 cpl_table_set_double(out_tab, "WL_coefficients", 1, b);
00840 cpl_table_set_double(out_tab, "WL_coefficients", 2, c);
00841 cpl_table_set_double(out_tab, "WL_coefficients", 3, d);
00842 cpl_table_set_double(out_tab, "WL_coefficients", 4, e);
00843 cpl_table_set_double(out_tab, "WL_coefficients", 5, 0.0);
00844 sofi_spc_arc_config.disprel_cc = xc;
00845
00846
00847 cpl_polynomial_delete(distor_poly);
00848 return out_tab;
00849 }
00850
00851
00863
00864 static cpl_error_code sofi_spc_arc_save(cpl_frameset * set_tot,
00865 const cpl_table * tab,
00866 const cpl_table * fwhms,
00867 const cpl_image * corr,
00868 const char * lines_table,
00869 const cpl_frameset * set,
00870 const cpl_parameterlist * parlist)
00871 {
00872 cpl_propertylist * plist;
00873 cpl_propertylist * qclist;
00874 cpl_propertylist * paflist;
00875 const cpl_frame * ref_frame;
00876 const char * sval;
00877 char qc_str[128];
00878 char * filename;
00879 int i;
00880
00881
00882 qclist = cpl_propertylist_new();
00883
00884
00885 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
00886 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
00887 0)) == NULL) {
00888 cpl_msg_error(cpl_func, "getting header from reference frame");
00889 cpl_propertylist_delete(qclist);
00890 return cpl_error_set_where(cpl_func);
00891 }
00892
00893 if (cpl_error_get_code()) {
00894 cpl_propertylist_delete(qclist);
00895 cpl_propertylist_delete(plist);
00896 return cpl_error_set_where(cpl_func);
00897 }
00898 sval = sofi_pfits_get_filter(plist);
00899 if (cpl_error_get_code()) cpl_error_reset();
00900 else cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS", sval);
00901 cpl_propertylist_delete(plist);
00902 cpl_propertylist_append_string(qclist, "ESO QC LAMP", lines_table);
00903 cpl_propertylist_append_double(qclist, "ESO QC DISP XCORR",
00904 sofi_spc_arc_config.disprel_cc);
00905 cpl_propertylist_append_double(qclist, "ESO QC DISPCO1",
00906 cpl_table_get_double(tab, "WL_coefficients", 0, NULL));
00907 cpl_propertylist_append_double(qclist, "ESO QC DISPCO2",
00908 cpl_table_get_double(tab, "WL_coefficients", 1, NULL));
00909 cpl_propertylist_append_double(qclist, "ESO QC DISPCO3",
00910 cpl_table_get_double(tab, "WL_coefficients", 2, NULL));
00911 cpl_propertylist_append_double(qclist, "ESO QC DISPCO4",
00912 cpl_table_get_double(tab, "WL_coefficients", 3, NULL));
00913 cpl_propertylist_append_double(qclist, "ESO QC DISPCO5",
00914 cpl_table_get_double(tab, "WL_coefficients", 4, NULL));
00915 cpl_propertylist_append_double(qclist, "ESO QC DIST1",
00916 cpl_table_get_double(tab, "poly2d_coef", 0, NULL));
00917 cpl_propertylist_append_double(qclist, "ESO QC DISTX",
00918 cpl_table_get_double(tab, "poly2d_coef", 1, NULL));
00919 cpl_propertylist_append_double(qclist, "ESO QC DISTY",
00920 cpl_table_get_double(tab, "poly2d_coef", 2, NULL));
00921 cpl_propertylist_append_double(qclist, "ESO QC DISTXY",
00922 cpl_table_get_double(tab, "poly2d_coef", 3, NULL));
00923 cpl_propertylist_append_double(qclist, "ESO QC DISTXX",
00924 cpl_table_get_double(tab, "poly2d_coef", 4, NULL));
00925 cpl_propertylist_append_double(qclist, "ESO QC DISTYY",
00926 cpl_table_get_double(tab, "poly2d_coef", 5, NULL));
00927 cpl_propertylist_append_int(qclist, "ESO QC SATUR NBPIX",
00928 sofi_spc_arc_config.nb_saturated);
00929 cpl_propertylist_append_double(qclist, "ESO QC WLEN",
00930 (double)(cpl_table_get_double(tab, "WL_coefficients", 0, NULL) +
00931 512.0*cpl_table_get_double(tab, "WL_coefficients", 1, NULL) +
00932 512.0*512.0*cpl_table_get_double(tab, "WL_coefficients", 2, NULL) +
00933 512.0*512.0*512.0*cpl_table_get_double(tab, "WL_coefficients", 3, NULL) +
00934 512.0*512.0*512.0*512.0*cpl_table_get_double(tab, "WL_coefficients", 4, NULL)));
00935
00936 if (fwhms) {
00937 cpl_propertylist_append_int(qclist, "ESO QC ARCS NUM",
00938 cpl_table_get_nrow(fwhms));
00939 for(i=0; i<cpl_table_get_nrow(fwhms); i++) {
00940 sprintf(qc_str, "ESO QC ARCS%d XPOS", i+1);
00941 cpl_propertylist_append_double(qclist, qc_str,
00942 cpl_table_get_double(fwhms, "POS", i, NULL));
00943 sprintf(qc_str, "ESO QC ARCS%d FWHM", i+1);
00944 cpl_propertylist_append_double(qclist, qc_str,
00945 cpl_table_get_double(fwhms, "FWHM", i, NULL));
00946 sprintf(qc_str, "ESO QC ARCS%d FLUX", i+1);
00947 cpl_propertylist_append_double(qclist, qc_str,
00948 cpl_table_get_double(fwhms, "FLUX", i, NULL));
00949 }
00950 cpl_propertylist_append_int(qclist, "ESO QC ARCS NUMGOOD",
00951 sofi_spc_arc_config.fwhm_good);
00952 cpl_propertylist_append_double(qclist, "ESO QC FWHM MED",
00953 sofi_spc_arc_config.fwhm_med);
00954 }
00955
00956
00957 filename = cpl_sprintf("sofi_spc_arc_set%d_frame%d.fits",
00958 sofi_spc_arc_config.set_nb, sofi_spc_arc_config.frame_nb);
00959 irplib_dfs_save_table(set_tot,
00960 parlist,
00961 set,
00962 tab,
00963 NULL,
00964 "sofi_spc_arc",
00965 SOFI_SPC_ARC_RES,
00966 qclist,
00967 NULL,
00968 PACKAGE "/" PACKAGE_VERSION,
00969 filename);
00970 cpl_free(filename);
00971
00972
00973 if (corr) {
00974 filename = cpl_sprintf("sofi_spc_arc_set%d_frame%d_corr.fits",
00975 sofi_spc_arc_config.set_nb, sofi_spc_arc_config.frame_nb);
00976 irplib_dfs_save_image(set_tot,
00977 parlist,
00978 set,
00979 corr,
00980 CPL_BPP_IEEE_FLOAT,
00981 "sofi_spc_arc",
00982 SOFI_SPC_ARC_CORR,
00983 qclist,
00984 NULL,
00985 PACKAGE "/" PACKAGE_VERSION,
00986 filename);
00987 cpl_free(filename);
00988 }
00989
00990
00991 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
00992
00993
00994 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
00995 0)) == NULL) {
00996 cpl_msg_error(cpl_func, "getting header from reference frame");
00997 cpl_propertylist_delete(qclist);
00998 return cpl_error_set_where(cpl_func);
00999 }
01000
01001
01002 paflist = cpl_propertylist_new();
01003 cpl_propertylist_copy_property_regexp(paflist, plist,
01004 "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
01005 "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME|"
01006 "ESO INS GRAT WLEN|ESO INS GRAT ORDER|ESO INS MODE|"
01007 "ESO INS OPTI1 ID)$", 0);
01008 cpl_propertylist_delete(plist);
01009
01010
01011 cpl_propertylist_copy_property_regexp(paflist, qclist, "", 0);
01012 cpl_propertylist_delete(qclist);
01013
01014
01015 filename = cpl_sprintf("sofi_spc_arc_set%d_frame%d.paf",
01016 sofi_spc_arc_config.set_nb, sofi_spc_arc_config.frame_nb);
01017 cpl_dfs_save_paf("SOFI",
01018 "sofi_spc_arc",
01019 paflist,
01020 filename);
01021 cpl_free(filename);
01022 cpl_propertylist_delete(paflist);
01023
01024 return cpl_error_get_code();
01025 }
01026
01027
01034
01035 static int sofi_spc_arc_compare(
01036 const cpl_frame * frame1,
01037 const cpl_frame * frame2)
01038 {
01039 int comparison;
01040 cpl_propertylist * plist1;
01041 cpl_propertylist * plist2;
01042 const char * sval1,
01043 * sval2;
01044
01045
01046 if (frame1==NULL || frame2==NULL) return -1;
01047
01048
01049 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),
01050 0)) == NULL) {
01051 cpl_msg_error(cpl_func, "getting header from reference frame");
01052 return -1;
01053 }
01054 if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),
01055 0)) == NULL) {
01056 cpl_msg_error(cpl_func, "getting header from reference frame");
01057 cpl_propertylist_delete(plist1);
01058 return -1;
01059 }
01060
01061
01062 if (cpl_error_get_code()) {
01063 cpl_propertylist_delete(plist1);
01064 cpl_propertylist_delete(plist2);
01065 return -1;
01066 }
01067
01068 comparison = 1;
01069
01070
01071 sval1 = sofi_pfits_get_opti1_id(plist1);
01072 sval2 = sofi_pfits_get_opti1_id(plist2);
01073 if (cpl_error_get_code()) {
01074 cpl_msg_error(cpl_func, "cannot get the slit used");
01075 cpl_propertylist_delete(plist1);
01076 cpl_propertylist_delete(plist2);
01077 return -1;
01078 }
01079 if (strcmp(sval1, sval2)) comparison = 0;
01080
01081
01082 sval1 = sofi_pfits_get_mode(plist1);
01083 sval2 = sofi_pfits_get_mode(plist2);
01084 if (cpl_error_get_code()) {
01085 cpl_msg_error(cpl_func, "cannot get the mode");
01086 cpl_propertylist_delete(plist1);
01087 cpl_propertylist_delete(plist2);
01088 return -1;
01089 }
01090 if (strcmp(sval1, sval2)) comparison = 0;
01091
01092 cpl_propertylist_delete(plist1);
01093 cpl_propertylist_delete(plist2);
01094 return comparison;
01095 }
01096
01097
01104
01105 static int * sofi_spc_arc_find_lamps(const cpl_frameset * fset)
01106 {
01107 const int nframes = cpl_frameset_get_size(fset);
01108 int * lamps;
01109 int i;
01110
01111 cpl_ensure(nframes > 0, CPL_ERROR_UNSPECIFIED, NULL);
01112
01113
01114 lamps = (int*)cpl_malloc(nframes * sizeof(int));
01115
01116 for (i=0; i<nframes; i++) {
01117 const cpl_frame * cur_frame = cpl_frameset_get_frame_const(fset, i);
01118 cpl_propertylist * plist
01119 = cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
01120 const int xenon = sofi_is_xenon_lamp_active(plist);
01121 const int neon = sofi_is_neon_lamp_active(plist);
01122
01123 cpl_propertylist_delete(plist);
01124 if ((neon != 0 && neon != 1) || (xenon != 0 && xenon != 1)) {
01125 cpl_free(lamps);
01126 (void)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01127 "Cannot check which lamp is on for "
01128 "frame %d", i+1);
01129 return NULL;
01130 }
01131 if (xenon == 1) {
01132 if (neon == 1) lamps[i] = 3;
01133 else if (neon == 0) lamps[i] = 1;
01134 } else if (xenon == 0 ) {
01135 if (neon == 1) lamps[i] = 2;
01136 else if (neon == 0) lamps[i] = 0;
01137 }
01138 }
01139
01140 return lamps;
01141 }
01142
01143
01149
01150 static int sofi_is_neon_lamp_active(const cpl_propertylist * plist)
01151 {
01152 int status;
01153 const char * lamp;
01154
01155
01156 if (cpl_error_get_code()) return -1;
01157
01158 if ((lamp=sofi_pfits_get_lamp2_name(plist)) == NULL) {
01159 cpl_error_reset();
01160 return 0;
01161 }
01162 if (!strcmp(lamp, "Neon")) {
01163 status = sofi_pfits_get_lamp2_status(plist);
01164 if (cpl_error_get_code()) {
01165 cpl_error_reset();
01166 return 0;
01167 }
01168 if (status == 1) return 1;
01169 }
01170 return 0;
01171 }
01172
01173
01179
01180 static int sofi_is_xenon_lamp_active(const cpl_propertylist * plist)
01181 {
01182 int status;
01183 const char * lamp;
01184
01185
01186 if (cpl_error_get_code()) return -1;
01187
01188 if ((lamp=sofi_pfits_get_lamp1_name(plist)) == NULL) {
01189 cpl_error_reset();
01190 return 0;
01191 }
01192 if (!strcmp(lamp, "Xenon")) {
01193 status = sofi_pfits_get_lamp1_status(plist);
01194 if (cpl_error_get_code()) {
01195 cpl_error_reset();
01196 return 0;
01197 }
01198 if (status == 1) return 1;
01199 }
01200 return 0;
01201 }