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 <cpl.h>
00037
00038 #include "irplib_plugin.h"
00039 #include "irplib_utils.h"
00040 #include "irplib_stdstar.h"
00041 #include "irplib_spectrum.h"
00042
00043 #include "isaac_utils.h"
00044 #include "isaac_wavelength.h"
00045 #include "isaac_physicalmodel.h"
00046 #include "isaac_pfits.h"
00047 #include "isaac_dfs.h"
00048
00049 #include <string.h>
00050 #include <math.h>
00051
00052
00053
00054
00055
00056 #define RECIPE_STRING "isaac_spc_jitter"
00057
00058 #define ISAAC_SPC_JITTER_OFFSET_ERR 10
00059
00060 #define KEYSIZE 512
00061
00062 #define CENT_WL_BAND_Z 0.9
00063 #define CENT_WL_BAND_SZ 1.06
00064 #define CENT_WL_BAND_J 1.25
00065 #define CENT_WL_BAND_H 1.65
00066 #define CENT_WL_BAND_K 2.2
00067 #define CENT_WL_BAND_SL 3.78
00068 #define CENT_WL_BAND_M 4.78
00069
00070 #define ISAAC_MIN(A,B) ((A) < (B) ? (A) : (B))
00071
00072 #define isaac_plot_manpage \
00073 "The recipe can produce a number of predefined plots. " \
00074 "Zero means that none of the plots are produced, while " \
00075 "increasing values (e.g. 1 or 2) increases the number " \
00076 "of plots produced. If the plotting fails a warning is " \
00077 "produced, and the recipe continues. " \
00078 "The default behaviour of the plotting is to use " \
00079 "gnuplot (with option -persist). The recipe currently " \
00080 "produces 1D-plots using gnuplot commands. The recipe " \
00081 "user can control the actual plotting-command used by " \
00082 "the recipe to create the plot by setting the " \
00083 "environment variable CPL_PLOTTER. Currently, if " \
00084 "CPL_PLOTTER " \
00085 "is set it must contain the string 'gnuplot'. Setting " \
00086 "it to 'cat > my_gnuplot_$$.txt' causes a number of " \
00087 "ASCII-files to be created, which each produce a plot " \
00088 "when given as standard input to gnuplot (e.g. later " \
00089 "or on a different computer). A finer control of the " \
00090 "plotting options can be obtained by writing an " \
00091 "executable script, e.g. my_gnuplot.pl, that " \
00092 "executes gnuplot after setting the desired gnuplot " \
00093 "options (e.g. set terminal pslatex color) " \
00094 "and then setting CPL_PLOTTER to my_gnuplot.pl. " \
00095 "The predefined plots include plotting of images. " \
00096 "Images can be plotted not only with gnuplot, but also " \
00097 "using the pnm format. This is controlled with the " \
00098 "environment variable CPL_IMAGER. If CPL_IMAGER " \
00099 "is set to a string that does not contain the word " \
00100 "gnuplot, the recipe will generate the plot in pnm " \
00101 "format. E.g. setting CPL_IMAGER to " \
00102 "'display - &' will produce a gray-scale image " \
00103 "using the image viewer display."
00104
00105
00106
00107
00108
00109
00110
00111 static cpl_image ** isaac_spc_jitter_combine(const cpl_frameset *, const char *,
00112 const char *, const char *, const char *);
00113 static cpl_imagelist * isaac_spc_jitter_load(const cpl_frameset *);
00114 static cpl_vector * isaac_spc_jitter_get_offsets(const cpl_frameset *);
00115 static int * isaac_spc_jitter_classif(const cpl_vector *, int *);
00116 static int off_comp(double, double, double);
00117 static cpl_imagelist * isaac_spc_jitter_saa_groups(cpl_imagelist *,
00118 cpl_vector *, int *, int, cpl_vector **);
00119 static int isaac_spc_jitter_wavecal(const char *, const cpl_image *,
00120 const char *, const cpl_frameset *);
00121 static cpl_imagelist * isaac_spc_jitter_nodded(cpl_imagelist *, cpl_vector *,
00122 cpl_vector **);
00123 static cpl_imagelist * isaac_spc_jitter_distor(cpl_imagelist *, const char *,
00124 const char *);
00125 static double isaac_spc_jitter_refine_offset(const cpl_image *,
00126 const cpl_image *);
00127 static cpl_table * isaac_spc_jitter_extract(const cpl_image *);
00128 static int isaac_spc_jitter_std(const char *, const char *, const cpl_frame *,
00129 cpl_table *, double);
00130 static cpl_error_code isaac_spc_jitter_flat(cpl_imagelist *, const char *);
00131 static cpl_error_code isaac_spc_jitter_save(cpl_frameset *, const cpl_image *,
00132 const cpl_image *,
00133 const cpl_table *,
00134 const cpl_parameterlist *);
00135
00136 cpl_recipe_define(isaac_spc_jitter, ISAAC_BINARY_VERSION,
00137 "Lars Lundin", PACKAGE_BUGREPORT, "2002,2003, 2008",
00138 "ISAAC Spectro jitter recipe",
00139 RECIPE_STRING " -- ISAAC spectro jitter recipe\n"
00140 "The files listed in the Set Of Frames (sof-file) "
00141 "must be tagged:\n"
00142 "Observation in nodding mode:\n"
00143 "\traw-file.fits "ISAAC_SPC_JITTER_NODOBJ_RAW" or\n"
00144 "\traw-file.fits "ISAAC_SPC_JITTER_NODSKY_RAW"\n"
00145 "Observation in chopping mode:\n"
00146 "\traw-file.fits "ISAAC_SPC_JITTER_CHOP_RAW" or\n"
00147 "Calibration (standard star) in nodding mode:\n"
00148 "\traw-file.fits "ISAAC_SPC_RESPFUNC_RAW" or\n"
00149 "\traw-file.fits "ISAAC_SPC_RESPFUNC_OBJ_RAW" or\n"
00150 "\traw-file.fits "ISAAC_SPC_RESPFUNC_SKY_RAW"\n"
00151 "\traw-file.fits "ISAAC_SPC_RESPFUNC_FLUX_RAW"\n"
00152 "Calibration (standard star) in chopping mode:\n"
00153 "\traw-file.fits "ISAAC_SPC_JITTER_CHOP_CAL_RAW"\n"
00154 "Calibration files:\n"
00155 "\toh.fits "ISAAC_CALPRO_OH_CAT" or\n"
00156 "\tflat-file.fits "ISAAC_CALIB_SPFLAT" or\n"
00157 "\tflat-file.fits "ISAAC_CALIB_LW_SPFLAT" or\n"
00158 "\tarc-file.fits "ISAAC_CALIB_ARC" or\n"
00159 "\tarc-file.fits "ISAAC_CALIB_LW_ARC" or\n"
00160 "\tstartrace-file.fits "ISAAC_CALIB_STARTRACE" or\n"
00161 "\tstartrace-file.fits "ISAAC_CALIB_LW_STARTRACE" or\n"
00162 "\tsed-file.fits "ISAAC_CALIB_SED" or\n"
00163 "\tstdstars-file.fits "ISAAC_CALIB_STDSTARS"\n");
00164
00165
00166
00167
00168
00169 static struct {
00170
00171 int arm;
00172 int plot;
00173 int oddeven;
00174
00175 int wavecal_in;
00176 int wavecal_rej_bottom;
00177 int wavecal_rej_top;
00178 int wavecal_rej_left;
00179 int wavecal_rej_right;
00180 int max_offset;
00181 int saa_refine;
00182 double saa_rej_high;
00183 double saa_rej_low;
00184 int extr_spec_pos;
00185 int extr_spec_width;
00186 int extr_sky_hi_width;
00187 int extr_sky_lo_width;
00188 int extr_sky_hi_dist;
00189 int extr_sky_lo_dist;
00190 int std_mode;
00191 double std_magnitude;
00192
00193
00194 int chopping;
00195 cpl_vector * throws;
00196 cpl_vector * intensities;
00197 char filter[KEYSIZE];
00198 char filter_ref[KEYSIZE];
00199 char * starname;
00200 char * sptype;
00201 int wavecal_out;
00202 double wavecal_cc;
00203 double wavecal_a0;
00204 double wavecal_a1;
00205 double wavecal_a2;
00206 double wavecal_a3;
00207 } isaac_spc_jitter_config;
00208
00209
00210
00211
00212
00213
00214
00222
00223 static
00224 cpl_error_code isaac_spc_jitter_fill_parameterlist(cpl_parameterlist * self)
00225 {
00226 const char * context = PACKAGE "." RECIPE_STRING;
00227 cpl_error_code err;
00228
00229 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00230
00231
00232
00233
00234
00235 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
00236 "oddeven", CPL_FALSE, NULL, context,
00237 "Flag to correct the oddeven column "
00238 "effect");
00239 cpl_ensure_code(!err, err);
00240
00241
00242 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00243 "wavecal", "sky", NULL, context,
00244 "Wavelength calibration method: "
00245 "sky, phy or arc");
00246 cpl_ensure_code(!err, err);
00247
00248
00249 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00250 "wavecal_rej", "-1,-1,50,50",
00251 "wc_rej", context,
00252 "left right bottom top rejections");
00253 cpl_ensure_code(!err, err);
00254
00255
00256 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00257 "max_offset", 50, NULL, context,
00258 "Maximum allowed offset from the "
00259 "physical model [pixel]");
00260 cpl_ensure_code(!err, err);
00261
00262
00263 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
00264 "saa_refine", CPL_TRUE, NULL, context,
00265 "Flag to refine the offsets");
00266 cpl_ensure_code(!err, err);
00267
00268
00269 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00270 "saa_rej", "0.1,0.1", NULL, context,
00271 "Low and high rejection fractions "
00272 "(rounded down)");
00273 cpl_ensure_code(!err, err);
00274
00275
00276 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00277 "spec_pos", -1, NULL, context,
00278 "Spectrum position");
00279 cpl_ensure_code(!err, err);
00280
00281
00282 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00283 "spec_width", 10, NULL, context,
00284 "Spectrum width");
00285 cpl_ensure_code(!err, err);
00286
00287
00288 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00289 "sky_hi_width", 10, NULL, context,
00290 "Sky width above the spectrum");
00291 cpl_ensure_code(!err, err);
00292
00293
00294 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00295 "sky_lo_width", 10, NULL, context,
00296 "Sky width below the spectrum");
00297 cpl_ensure_code(!err, err);
00298
00299
00300 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00301 "sky_hi_dist", -1, NULL, context,
00302 "Sky distance above the spectrum");
00303 cpl_ensure_code(!err, err);
00304
00305
00306 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00307 "sky_lo_dist", -1, NULL, context,
00308 "Sky distance below the spectrum");
00309 cpl_ensure_code(!err, err);
00310
00311
00312 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
00313 "display", CPL_FALSE, NULL, context,
00314 "Ignored. Use --plot instead");
00315 cpl_ensure_code(!err, err);
00316
00317
00318 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00319 "plot", 0, NULL, context,
00320 isaac_plot_manpage);
00321 cpl_ensure_code(!err, err);
00322
00323
00324 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
00325 "std_mode", CPL_FALSE, "std", context,
00326 "Flag for standard star");
00327 cpl_ensure_code(!err, err);
00328
00329
00330 err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING,
00331 "std_magnitude", -1.0, "mag",
00332 context, "Standard star magnitude");
00333 cpl_ensure_code(!err, err);
00334
00335 return CPL_ERROR_NONE;
00336 }
00337
00338
00339
00347
00348 static int isaac_spc_jitter(cpl_frameset * framelist,
00349 const cpl_parameterlist * parlist)
00350 {
00351 cpl_errorstate prestate = cpl_errorstate_get();
00352 const char * sval;
00353 const char * flat;
00354 const char * arc;
00355 const char * startrace;
00356 const char * sed;
00357 const char * stdstars;
00358 const char * oh;
00359 const cpl_frame * cur_frame;
00360 cpl_frameset * rawframes = NULL;
00361 cpl_propertylist * plist = NULL;
00362 cpl_image ** combined = NULL;
00363 cpl_table * extracted = NULL;
00364
00365 bug_if(0);
00366
00367
00368 isaac_spc_jitter_config.chopping = -1;
00369 isaac_spc_jitter_config.wavecal_out = -1;
00370 isaac_spc_jitter_config.wavecal_cc = -1.0;
00371 isaac_spc_jitter_config.throws = NULL;
00372 isaac_spc_jitter_config.intensities = NULL;
00373 isaac_spc_jitter_config.filter[0] = (char)0;
00374 isaac_spc_jitter_config.filter_ref[0] = (char)0;
00375 isaac_spc_jitter_config.starname = NULL;
00376 isaac_spc_jitter_config.sptype = NULL;
00377 isaac_spc_jitter_config.wavecal_in = -1;
00378 isaac_spc_jitter_config.arm = -1;
00379
00380
00381
00382 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00383 "wavecal");
00384 bug_if(sval == NULL);
00385
00386 if (!strcmp(sval, "phy")) isaac_spc_jitter_config.wavecal_in = 0;
00387 else if (!strcmp(sval, "sky")) isaac_spc_jitter_config.wavecal_in = 1;
00388 else if (!strcmp(sval, "arc")) isaac_spc_jitter_config.wavecal_in = 2;
00389
00390 error_if(isaac_spc_jitter_config.wavecal_in < 0,
00391 CPL_ERROR_UNSUPPORTED_MODE, "Invalid value for wavecal option: "
00392 "%s", sval);
00393
00394
00395 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00396 "wavecal_rej");
00397 bug_if(sval == NULL);
00398
00399 skip_if (sscanf(sval, "%d,%d,%d,%d",
00400 &isaac_spc_jitter_config.wavecal_rej_left,
00401 &isaac_spc_jitter_config.wavecal_rej_right,
00402 &isaac_spc_jitter_config.wavecal_rej_bottom,
00403 &isaac_spc_jitter_config.wavecal_rej_top) != 4);
00404
00405
00406 isaac_spc_jitter_config.max_offset
00407 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00408 "max_offset");
00409
00410
00411 isaac_spc_jitter_config.oddeven
00412 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00413 "oddeven");
00414
00415
00416 isaac_spc_jitter_config.saa_refine
00417 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00418 "saa_refine");
00419
00420
00421 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00422 "saa_rej");
00423 bug_if(sval == NULL);
00424
00425 skip_if (sscanf(sval, "%lg,%lg",
00426 &isaac_spc_jitter_config.saa_rej_low,
00427 &isaac_spc_jitter_config.saa_rej_high) != 2);
00428
00429
00430 isaac_spc_jitter_config.extr_spec_pos
00431 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00432 "spec_pos");
00433
00434 isaac_spc_jitter_config.extr_spec_width
00435 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00436 "spec_width");
00437
00438 isaac_spc_jitter_config.extr_sky_hi_width
00439 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00440 "sky_hi_width");
00441
00442 isaac_spc_jitter_config.extr_sky_lo_width
00443 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00444 "sky_lo_width");
00445
00446 isaac_spc_jitter_config.extr_sky_hi_dist
00447 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00448 "sky_hi_dist");
00449
00450 isaac_spc_jitter_config.extr_sky_lo_dist
00451 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00452 "sky_lo_dist");
00453
00454 isaac_spc_jitter_config.plot
00455 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00456 "plot");
00457
00458 isaac_spc_jitter_config.std_mode
00459 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00460 "std_mode");
00461
00462 isaac_spc_jitter_config.std_magnitude
00463 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
00464 "std_magnitude");
00465
00466
00467 skip_if (isaac_dfs_set_groups(framelist));
00468
00469
00470 if ((rawframes = isaac_extract_frameset(framelist,
00471 ISAAC_SPC_JITTER_CHOP_RAW)) != NULL) {
00472 } else if ((rawframes = isaac_extract_frameset(framelist,
00473 ISAAC_SPC_JITTER_CHOP_CAL_RAW)) != NULL) {
00474 } else if ((rawframes = isaac_extract_frameset(framelist,
00475 ISAAC_SPC_JITTER_NODOBJ_RAW)) != NULL) {
00476 } else if ((rawframes = isaac_extract_frameset(framelist,
00477 ISAAC_SPC_RESPFUNC_RAW)) != NULL) {
00478 isaac_spc_jitter_config.std_mode = 1;
00479 } else if ((rawframes = isaac_extract_frameset(framelist,
00480 ISAAC_SPC_RESPFUNC_OBJ_RAW)) != NULL) {
00481 isaac_spc_jitter_config.std_mode = 1;
00482 } else if ((rawframes = isaac_extract_frameset(framelist,
00483 ISAAC_SPC_RESPFUNC_FLUX_RAW)) != NULL) {
00484 isaac_spc_jitter_config.std_mode = 1;
00485 } else {
00486
00487
00488
00489 error_if (cpl_frameset_find_const(framelist,
00490 ISAAC_SPC_JITTER_NODSKY_RAW),
00491 CPL_ERROR_UNSUPPORTED_MODE, "Cannot reduce "
00492 ISAAC_SPC_JITTER_NODSKY_RAW "-frames without object frames");
00493
00494 error_if (cpl_frameset_find_const(framelist,
00495 ISAAC_SPC_RESPFUNC_SKY_RAW),
00496 CPL_ERROR_UNSUPPORTED_MODE, "Cannot reduce "
00497 ISAAC_SPC_RESPFUNC_SKY_RAW "-frames without object frames");
00498
00499 }
00500
00501 error_if (rawframes == NULL, CPL_ERROR_DATA_NOT_FOUND,
00502 "Cannot find the raw frames in the input list");
00503
00504
00505 cur_frame = cpl_frameset_get_frame_const(framelist, 0);
00506 skip_if(cur_frame == NULL);
00507 plist = cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
00508 skip_if(plist == NULL);
00509 sval = isaac_pfits_get_arm(plist);
00510 error_if (sval == NULL, CPL_ERROR_DATA_NOT_FOUND, "cannot get the arm");
00511
00512 if (sval[0] == 'S') isaac_spc_jitter_config.arm = 1;
00513 else if (sval[0] == 'L') isaac_spc_jitter_config.arm = 2;
00514
00515 error_if (isaac_spc_jitter_config.arm < 0, CPL_ERROR_UNSUPPORTED_MODE,
00516 "Unsupported arm: %s", sval);
00517
00518
00519 sval = isaac_pfits_get_filter(plist);
00520 if (sval == NULL) {
00521 cpl_error_reset();
00522 } else {
00523 (void)strncpy(isaac_spc_jitter_config.filter, sval, KEYSIZE);
00524 isaac_spc_jitter_config.filter[KEYSIZE-1] = (char)0;
00525 }
00526 cpl_propertylist_empty(plist);
00527
00528
00529 arc = isaac_extract_filename(framelist, ISAAC_CALIB_ARC);
00530 if (arc == NULL)
00531 arc = isaac_extract_filename(framelist, ISAAC_CALIB_LW_ARC);
00532 flat = isaac_extract_filename(framelist, ISAAC_CALIB_SPFLAT);
00533 if (flat == NULL)
00534 flat = isaac_extract_filename(framelist, ISAAC_CALIB_LW_SPFLAT);
00535 startrace = isaac_extract_filename(framelist, ISAAC_CALIB_STARTRACE);
00536 if (startrace == NULL)
00537 startrace = isaac_extract_filename(framelist, ISAAC_CALIB_LW_STARTRACE);
00538 sed = isaac_extract_filename(framelist, ISAAC_CALIB_SED);
00539 stdstars = isaac_extract_filename(framelist, ISAAC_CALIB_STDSTARS);
00540 oh = isaac_extract_filename(framelist, ISAAC_CALPRO_OH_CAT);
00541
00542
00543 error_if (arc == NULL && isaac_spc_jitter_config.wavecal_in == 2,
00544 CPL_ERROR_DATA_NOT_FOUND, "Missing an arc file for the "
00545 "arc-based wavelength calibration");
00546
00547 cpl_msg_info(cpl_func, "Create the combined image");
00548 combined = isaac_spc_jitter_combine(rawframes, oh, flat, arc,
00549 startrace);
00550 skip_if (combined == NULL);
00551
00552 cpl_msg_info(cpl_func, "Extract the spectrum");
00553 extracted = isaac_spc_jitter_extract(combined[0]);
00554 if (extracted == NULL || !cpl_errorstate_is_equal(prestate)) {
00555 cpl_msg_warning(cpl_func, "Cannot extract the spectrum");
00556 if (!cpl_errorstate_is_equal(prestate)) {
00557 cpl_errorstate_dump(prestate, CPL_FALSE,
00558 irplib_errorstate_dump_warning);
00559 cpl_errorstate_set(prestate);
00560 }
00561 } else if (isaac_spc_jitter_config.std_mode) {
00562
00563 cpl_msg_info(cpl_func, "Compute flux calibration");
00564 cur_frame = cpl_frameset_get_frame_const(framelist, 0);
00565 if (isaac_spc_jitter_std(sed, stdstars, cur_frame, extracted,
00566 isaac_spc_jitter_config.std_magnitude)) {
00567 cpl_msg_warning(cpl_func, "Cannot compute the flux calibration");
00568 if (!cpl_errorstate_is_equal(prestate)) {
00569 cpl_errorstate_dump(prestate, CPL_FALSE,
00570 irplib_errorstate_dump_warning);
00571 cpl_errorstate_set(prestate);
00572 }
00573 }
00574 }
00575
00576
00577 cpl_msg_info(cpl_func, "Save the products");
00578 skip_if (isaac_spc_jitter_save(framelist, combined[0], combined[1],
00579 extracted, parlist));
00580
00581 end_skip;
00582
00583 if (combined != NULL) {
00584 cpl_image_delete(combined[0]);
00585 cpl_image_delete(combined[1]);
00586 cpl_free(combined);
00587 }
00588
00589 cpl_table_delete(extracted);
00590
00591 cpl_vector_delete(isaac_spc_jitter_config.intensities);
00592 cpl_vector_delete(isaac_spc_jitter_config.throws);
00593
00594 cpl_free(isaac_spc_jitter_config.starname);
00595 cpl_free(isaac_spc_jitter_config.sptype);
00596
00597 cpl_propertylist_delete(plist);
00598
00599 cpl_frameset_delete(rawframes);
00600
00601 return cpl_error_get_code();
00602 }
00603
00604
00615
00616 static cpl_image ** isaac_spc_jitter_combine(const cpl_frameset * rawframes,
00617 const char * oh,
00618 const char * flat,
00619 const char * arc,
00620 const char * startrace)
00621 {
00622 int nilist;
00623 cpl_imagelist * ilist = NULL;
00624 cpl_vector * offsets = NULL;
00625 int * groups = NULL;
00626 int ngroups = 0;
00627 cpl_imagelist * abba = NULL;
00628 cpl_vector * abba_off = NULL;
00629 cpl_imagelist * nodded = NULL;
00630 cpl_vector * nodded_off_y = NULL;
00631 double throw;
00632 cpl_vector * nodded_off_x = NULL;
00633 cpl_bivector * nodded_offsets = NULL;
00634 cpl_image ** combined = NULL;
00635 int nima;
00636 int i;
00637
00638 bug_if (rawframes == NULL);
00639
00640
00641 cpl_msg_info(cpl_func, "Load the data");
00642 ilist = isaac_spc_jitter_load(rawframes);
00643 skip_if (ilist == NULL);
00644
00645 nilist = cpl_imagelist_get_size(ilist);
00646
00647
00648 if (isaac_spc_jitter_config.oddeven) {
00649 cpl_errorstate prestate = cpl_errorstate_get();
00650 cpl_imagelist * corrected = cpl_imagelist_new();
00651
00652 cpl_msg_info(cpl_func, "Apply the odd-even effect correction");
00653 for (i=0; i < nilist; i++) {
00654 cpl_image * cur_im
00655 = isaac_oddeven_correct(cpl_imagelist_get(ilist, i));
00656
00657 cpl_msg_info(cpl_func, "Correcting frame %d/%d", i+1, nilist);
00658
00659 if (cur_im == NULL) break;
00660 (void)cpl_imagelist_set(corrected, cur_im, i);
00661 }
00662
00663 if (i == nilist) {
00664
00665 cpl_imagelist_delete(ilist);
00666 ilist = corrected;
00667 } else {
00668 cpl_msg_warning(cpl_func, "Odd/even correction failed for "
00669 "image %d/%d", i+1, nilist);
00670 cpl_imagelist_delete(corrected);
00671 if (!cpl_errorstate_is_equal(prestate)) {
00672 cpl_errorstate_dump(prestate, CPL_FALSE,
00673 irplib_errorstate_dump_warning);
00674 cpl_errorstate_set(prestate);
00675 }
00676 }
00677 }
00678
00679
00680 if (isaac_spc_jitter_config.plot > 0) {
00681 cpl_plot_image("", "", "", cpl_imagelist_get(ilist, 0));
00682 }
00683
00684
00685 if (flat != NULL) {
00686 cpl_errorstate prestate = cpl_errorstate_get();
00687 cpl_msg_info(cpl_func, "Apply the flatfield correction");
00688 if (isaac_spc_jitter_flat(ilist, flat)) {
00689 cpl_msg_warning(cpl_func, "cannot apply the flat field");
00690 if (!cpl_errorstate_is_equal(prestate)) {
00691 cpl_errorstate_dump(prestate, CPL_FALSE,
00692 irplib_errorstate_dump_warning);
00693 cpl_errorstate_set(prestate);
00694 }
00695 }
00696 }
00697
00698 if (isaac_spc_jitter_config.plot > 0) {
00699 cpl_plot_image("", "", "", cpl_imagelist_get(ilist, 0));
00700 }
00701
00702 cpl_msg_info(cpl_func, "Get the %d offsets", nilist);
00703 offsets = isaac_spc_jitter_get_offsets(rawframes);
00704
00705 error_if (offsets == NULL, cpl_error_get_code(),
00706 "Could not get the offsets");
00707
00708
00709 cpl_msg_info(cpl_func, "Classify in groups");
00710 groups = isaac_spc_jitter_classif(offsets, &ngroups);
00711 error_if (groups == NULL, cpl_error_get_code(),
00712 "Could not classify the data");
00713
00714
00715 cpl_msg_info(cpl_func, "Shift and add each group to one image");
00716 abba = isaac_spc_jitter_saa_groups(ilist, offsets, groups,
00717 ngroups, &abba_off);
00718 error_if (abba == NULL, cpl_error_get_code(), "Could not shift and add "
00719 "groups");
00720
00721
00722 cpl_msg_info(cpl_func, "Compute the wavelength calibration");
00723 error_if (isaac_spc_jitter_wavecal(arc, cpl_imagelist_get(abba, 0), oh,
00724 rawframes),
00725 cpl_error_get_code(), "Wavelength calibration failed");
00726
00727
00728 cpl_msg_info(cpl_func, "Create the nodded images");
00729 nodded = isaac_spc_jitter_nodded(abba, abba_off, &nodded_off_y);
00730 cpl_imagelist_delete(abba);
00731 abba = NULL;
00732
00733 skip_if (nodded == NULL);
00734
00735
00736 nima = cpl_imagelist_get_size(nodded);
00737 isaac_spc_jitter_config.throws = cpl_vector_new(nima);
00738 if (isaac_spc_jitter_config.chopping == 0) {
00739 for (i=0; i<nima/2; i++) {
00740 throw = fabs( (cpl_vector_get(abba_off, 2*i))-
00741 (cpl_vector_get(abba_off, 2*i+1)));
00742 cpl_vector_set(isaac_spc_jitter_config.throws, 2*i, throw);
00743 cpl_vector_set(isaac_spc_jitter_config.throws, 2*i+1, throw);
00744 }
00745 } else {
00746 for (i=0; i<nima; i++) {
00747 throw = fabs( (cpl_vector_get(abba_off, 2*i))-
00748 (cpl_vector_get(abba_off, 2*i+1)));
00749 cpl_vector_set(isaac_spc_jitter_config.throws, i, throw);
00750 }
00751 }
00752 cpl_vector_delete(abba_off);
00753 abba_off = NULL;
00754
00755
00756 cpl_msg_info(cpl_func, "Compute the spectra intensities");
00757 cpl_msg_indent_more();
00758 isaac_spc_jitter_config.intensities = cpl_vector_new(nima);
00759 for (i=0; i<nima; i++) {
00760 cpl_errorstate prestate = cpl_errorstate_get();
00761 cpl_table * extracted
00762 = isaac_spc_jitter_extract(cpl_imagelist_get(nodded, i));
00763 double intensity;
00764
00765
00766 if (extracted == NULL || !cpl_errorstate_is_equal(prestate)) {
00767 cpl_msg_warning(cpl_func,"Cannot extract the spectrum from "
00768 "nodded image %d", i+1);
00769 cpl_errorstate_dump(prestate, CPL_FALSE,
00770 irplib_errorstate_dump_warning);
00771 cpl_errorstate_set(prestate);
00772 intensity = -1.0;
00773 } else {
00774 intensity = cpl_table_get_column_mean(extracted,
00775 "Extracted_spectrum_value");
00776 intensity *= cpl_table_get_nrow(extracted);
00777 cpl_table_delete(extracted);
00778 cpl_msg_info(cpl_func, "Spectrum intensity %d: %g", i+1,
00779 intensity);
00780 }
00781 cpl_vector_set(isaac_spc_jitter_config.intensities, i, intensity);
00782 }
00783 cpl_msg_indent_less();
00784
00785 if (arc || startrace) {
00786 cpl_imagelist * nodded_warped;
00787 cpl_msg_info(cpl_func, "Correct the distortion on nodded images");
00788 cpl_msg_indent_more();
00789 nodded_warped = isaac_spc_jitter_distor(nodded, arc, startrace);
00790 cpl_msg_indent_less();
00791
00792 skip_if (nodded_warped == NULL);
00793
00794 cpl_imagelist_delete(nodded);
00795 nodded = nodded_warped;
00796 nima = cpl_imagelist_get_size(nodded);
00797 }
00798
00799
00800
00801 if (isaac_spc_jitter_config.saa_refine) {
00802 double * pnodded_off_y = cpl_vector_get_data(nodded_off_y);
00803 cpl_msg_info(cpl_func, "Refine the %d offsets", nima);
00804 for (i=0; i < nima; i++) {
00805 const double new_offset
00806 = isaac_spc_jitter_refine_offset(cpl_imagelist_get(nodded, 0),
00807 cpl_imagelist_get(nodded, i));
00808 if (new_offset > 5000) {
00809 cpl_msg_debug(cpl_func, "cannot refine the offset - keep %g",
00810 pnodded_off_y[i]);
00811 } else if (fabs(new_offset-pnodded_off_y[i]) <
00812 ISAAC_SPC_JITTER_OFFSET_ERR) {
00813 cpl_msg_debug(cpl_func, "refined offset : %g (old was %g)",
00814 new_offset, pnodded_off_y[i]);
00815 pnodded_off_y[i] = new_offset;
00816 } else {
00817 cpl_msg_debug(cpl_func,
00818 "refined offset %g too different - keep %g",
00819 new_offset, pnodded_off_y[i]);
00820 }
00821 }
00822 }
00823
00824
00825
00826
00827 nodded_off_x = cpl_vector_new(nima);
00828 bug_if(cpl_vector_fill(nodded_off_x, 0.0));
00829 nodded_offsets = cpl_bivector_wrap_vectors(nodded_off_x, nodded_off_y);
00830
00831 if (nima == 1) {
00832
00833 combined = cpl_malloc(2 * sizeof(cpl_image*));
00834 combined[1] = NULL;
00835
00836 combined[0] = cpl_imagelist_unset(nodded, 0);
00837 bug_if (combined[0] == NULL);
00838
00839 combined[1] = cpl_image_new(cpl_image_get_size_x(combined[0]),
00840 cpl_image_get_size_y(combined[0]),
00841 CPL_TYPE_INT);
00842 bug_if (combined[1] == NULL);
00843
00844
00845 bug_if(cpl_image_threshold(combined[1], 1.0, 1.0, 1.0, 1.0));
00846
00847 } else {
00848
00849 const int nrejlo = (int)(nima * isaac_spc_jitter_config.saa_rej_low);
00850 const int nrejhi = (int)(nima * isaac_spc_jitter_config.saa_rej_high);
00851
00852 cpl_msg_info(cpl_func, "Apply the shift and add on the %d nodded "
00853 "frames (Rejecting %d lowermost, %d uppermost)", nima,
00854 nrejlo, nrejhi);
00855 combined = cpl_geom_img_offset_saa(nodded, nodded_offsets,
00856 CPL_KERNEL_DEFAULT, nrejlo, nrejhi,
00857 CPL_GEOM_FIRST, NULL, NULL);
00858 }
00859
00860 skip_if(combined == NULL);
00861
00862 end_skip;
00863
00864 cpl_free(groups);
00865 cpl_imagelist_delete(ilist);
00866 cpl_vector_delete(offsets);
00867 cpl_imagelist_delete(abba);
00868 cpl_vector_delete(abba_off);
00869 cpl_imagelist_delete(nodded);
00870 cpl_bivector_unwrap_vectors(nodded_offsets);
00871 cpl_vector_delete(nodded_off_x);
00872 cpl_vector_delete(nodded_off_y);
00873
00874 return combined;
00875 }
00876
00877
00885
00886 static cpl_error_code isaac_spc_jitter_flat(cpl_imagelist * self,
00887 const char * flat)
00888 {
00889 cpl_image * fim = NULL;
00890 cpl_image * big_fim = NULL;
00891 const int mx = cpl_image_get_size_x(cpl_imagelist_get(self, 0));
00892 const int my = cpl_image_get_size_y(cpl_imagelist_get(self, 0));
00893 int nx, ny;
00894
00895 bug_if (self == NULL);
00896 bug_if (flat == NULL);
00897
00898
00899 fim = cpl_image_load(flat, CPL_TYPE_UNSPECIFIED, 0, 0);
00900 error_if(fim == NULL, cpl_error_get_code(), "Could not load the flat "
00901 "field from %s", flat);
00902
00903
00904 nx = cpl_image_get_size_x(fim);
00905 ny = cpl_image_get_size_y(fim);
00906
00907 error_if(ny != my, CPL_ERROR_INCOMPATIBLE_INPUT, "Flat field Y-size "
00908 "%d is incompatible with image Y-size %d", ny, my);
00909
00910
00911 if (nx != mx) {
00912 cpl_propertylist * plist
00913 = cpl_propertylist_load_regexp(flat, 0, "ESO DET WIN STARTX", 0);
00914 const int lx = (int)isaac_pfits_get_win_startx(plist);
00915
00916 cpl_propertylist_delete(plist);
00917 skip_if (0);
00918
00919 cpl_msg_info(cpl_func, "Windowing mode: flat between pixels %d "
00920 "and %d", lx, ISAAC_MIN(mx, lx + nx - 1));
00921
00922 if (lx > mx || lx < 1) {
00923 cpl_msg_warning(cpl_func, "Cannot apply out of bounds flat field, "
00924 "lx=%d > mx=%d", lx, mx);
00925 cpl_image_delete(fim);
00926 fim = NULL;
00927 } else {
00928
00929
00930 big_fim = cpl_image_new(mx, my, cpl_image_get_type(fim));
00931
00932
00933 bug_if(cpl_image_threshold(big_fim, 1.0, 1.0, 1.0, 1.0));
00934
00935
00936 bug_if (cpl_image_copy(big_fim, fim, lx, 1));
00937
00938 cpl_image_delete(fim);
00939 fim = big_fim;
00940 big_fim = NULL;
00941 }
00942 }
00943
00944 if (fim != NULL) {
00945
00946
00947
00948 bug_if(cpl_image_threshold(fim, sqrt(FLT_MIN), sqrt(FLT_MAX),
00949 1.0, 1.0));
00950
00951
00952 error_if (cpl_imagelist_divide_image(self, fim),
00953 cpl_error_get_code(), "Could not apply the flat field");
00954 }
00955
00956 end_skip;
00957
00958 cpl_image_delete(fim);
00959 cpl_image_delete(big_fim);
00960
00961 return 0;
00962 }
00963
00964
00971
00972 static cpl_imagelist * isaac_spc_jitter_load(const cpl_frameset * rawframes)
00973 {
00974
00975 const cpl_frame * cur_frame = cpl_frameset_get_frame_const(rawframes, 0);
00976 cpl_propertylist * plist
00977 = cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
00978 const char * sval;
00979 cpl_imagelist * self = NULL;
00980
00981
00982 skip_if (plist == NULL);
00983
00984 sval = isaac_pfits_get_frame_type(plist);
00985 skip_if (sval == NULL);
00986
00987 if (!strcmp(sval, "INT")) isaac_spc_jitter_config.chopping = 0;
00988 else if (!strcmp(sval, "CUBE1")) isaac_spc_jitter_config.chopping = 1;
00989 else {
00990 error_if(1, CPL_ERROR_UNSUPPORTED_MODE, "Unsupported frame type: %s",
00991 sval);
00992 }
00993
00994 cpl_propertylist_empty(plist);
00995
00996
00997 self = cpl_imagelist_load_frameset(rawframes, CPL_TYPE_FLOAT, 1, 0);
00998
00999 if (isaac_spc_jitter_config.chopping == 1) {
01000 cpl_imagelist * self_tmp
01001 = cpl_imagelist_load_frameset(rawframes, CPL_TYPE_FLOAT, 2, 0);
01002 const cpl_error_code error = cpl_imagelist_subtract(self, self_tmp);
01003
01004 cpl_imagelist_delete(self_tmp);
01005 skip_if(error);
01006 }
01007
01008 end_skip;
01009
01010 cpl_propertylist_delete(plist);
01011
01012 if (cpl_error_get_code()) {
01013 cpl_imagelist_delete(self);
01014 self = NULL;
01015 }
01016
01017 return self;
01018 }
01019
01020
01027
01028 static
01029 cpl_vector * isaac_spc_jitter_get_offsets(const cpl_frameset * rawframes)
01030 {
01031 const int nraw = cpl_frameset_get_size(rawframes);
01032 cpl_vector * offsets = cpl_vector_new(nraw);
01033 cpl_propertylist * plist = NULL;
01034 int i;
01035
01036 bug_if (rawframes == NULL);
01037 bug_if (nraw == 0);
01038
01039
01040
01041 for (i=0; i < nraw; i++) {
01042 const cpl_frame * cur_frame
01043 = cpl_frameset_get_frame_const(rawframes, i);
01044 const char * filename = cpl_frame_get_filename(cur_frame);
01045 double yoff;
01046
01047 skip_if(filename == NULL);
01048
01049 cpl_propertylist_delete(plist);
01050 plist = cpl_propertylist_load_regexp(filename, 0,
01051 "ESO SEQ CUMOFFSETY", 0);
01052
01053 any_if("Could not load propertylist from %s", filename);
01054
01055 yoff = cpl_propertylist_get_double(plist, "ESO SEQ CUMOFFSETY");
01056
01057 any_if("Could not get the offset from %s", filename);
01058
01059 bug_if(cpl_vector_set(offsets, i, yoff));
01060 }
01061
01062 end_skip;
01063
01064 cpl_propertylist_delete(plist);
01065
01066 if (cpl_error_get_code()) {
01067 cpl_vector_delete(offsets);
01068 offsets = NULL;
01069 }
01070
01071 return offsets;
01072 }
01073
01074
01113
01114 static int * isaac_spc_jitter_classif(const cpl_vector * offsets,
01115 int * pngroups)
01116 {
01117 const int nraw = cpl_vector_get_size(offsets);
01118 const double * pvect = cpl_vector_get_data_const(offsets);
01119 const double offmin = cpl_vector_get_min(offsets);
01120 const double offmax = cpl_vector_get_max(offsets);
01121 const double offset_thresh = 0.5 * (offmin + offmax);
01122 int * groups = cpl_calloc(nraw, sizeof(int));
01123 int last_group;
01124 int i = 0;
01125
01126
01127 bug_if(offsets == NULL);
01128 bug_if(pngroups == NULL);
01129 *pngroups = 0;
01130
01131
01132 error_if (offmin >= offmax, CPL_ERROR_DATA_NOT_FOUND,
01133 "The %d offset(s) all have the same value: %g", nraw, pvect[0]);
01134
01135
01136
01137
01138 while (i < nraw) {
01139 int j = 0;
01140
01141 while ((i+j < nraw) &&
01142 (!off_comp(pvect[i], pvect[i+j], offset_thresh))) j++;
01143
01144 if (i+j >= nraw) i = nraw;
01145 else {
01146 int l, k = 0;
01147
01148 while ((i+j+k < nraw)
01149 && (!off_comp(pvect[i+j], pvect[i+j+k], offset_thresh))
01150 && (k<j)) k++;
01151 last_group = 1;
01152 if (i+j+k < nraw) {
01153 for (l=i+j+k; l<nraw; l++) {
01154 if (off_comp(pvect[i+j], pvect[l], offset_thresh)) {
01155 last_group = 0;
01156 break;
01157 }
01158 }
01159 }
01160 if (last_group == 0) {
01161 for (l=0; l<j; l++) groups[i+l] = *pngroups + 1;
01162 for (l=0; l<k; l++) groups[i+j+l] = *pngroups + 2;
01163 *pngroups += 2;
01164 i += j+k;
01165 } else {
01166 for (l=0; l<j; l++) groups[i+l] = *pngroups + 1;
01167 for (l=0; l<nraw - (i+j); l++) groups[i+j+l] = *pngroups + 2;
01168 *pngroups += 2;
01169 i = nraw;
01170 }
01171 }
01172 }
01173
01174
01175 error_if (*pngroups & 1, CPL_ERROR_ILLEGAL_INPUT, "Found an odd number "
01176 "(%d) of groups in the %d offsets", *pngroups, nraw);
01177
01178 end_skip;
01179
01180 if (cpl_error_get_code()) {
01181 cpl_free(groups);
01182 groups = NULL;
01183 }
01184
01185 return groups;
01186 }
01187
01188
01220
01221 static cpl_imagelist * isaac_spc_jitter_saa_groups(
01222 cpl_imagelist * ilist,
01223 cpl_vector * offsets,
01224 int * groups,
01225 int ngroups,
01226 cpl_vector ** abba_off)
01227 {
01228 cpl_imagelist * abba;
01229 cpl_imagelist * group_list;
01230 cpl_image * tmp_ima;
01231 cpl_image ** combined;
01232 cpl_bivector * group_off;
01233 double * pgroup_off;
01234 double * poffsets;
01235 double * pabba_off;
01236 int nima;
01237 int saa;
01238 int i, j, k;
01239
01240
01241 if ((ilist == NULL) || (offsets == NULL) || (groups == NULL)) return NULL;
01242
01243
01244 nima = cpl_imagelist_get_size(ilist);
01245 poffsets = cpl_vector_get_data(offsets);
01246
01247
01248 abba = cpl_imagelist_new();
01249 *abba_off = cpl_vector_new(ngroups);
01250 pabba_off = cpl_vector_get_data(*abba_off);
01251
01252
01253 for (i=0; i<ngroups; i++) {
01254
01255 saa = 0;
01256
01257 group_list = cpl_imagelist_new();
01258 k = 0;
01259 for (j=0; j<nima; j++) {
01260 if (i+1 == groups[j]) {
01261
01262 if (k==0) pabba_off[i] = poffsets[j];
01263
01264 if (fabs(pabba_off[i]-poffsets[j]) > 1e-3) saa = 1;
01265
01266 tmp_ima = cpl_image_duplicate(cpl_imagelist_get(ilist, j));
01267 cpl_imagelist_set(group_list, tmp_ima, k);
01268 tmp_ima = NULL;
01269 k++;
01270 }
01271 }
01272
01273 if (saa) {
01274
01275 group_off = cpl_bivector_new(k);
01276 cpl_vector_fill(cpl_bivector_get_x(group_off), 0.0);
01277 pgroup_off = cpl_bivector_get_y_data(group_off);
01278 k = 0;
01279 for (j=0; j<nima; j++) {
01280 if (i+1 == groups[j]) {
01281 pgroup_off[k] = poffsets[j];
01282 k++;
01283 }
01284 }
01285 cpl_vector_subtract_scalar(cpl_bivector_get_y(group_off),
01286 pabba_off[i]);
01287
01288 cpl_msg_debug(cpl_func, "Apply shift-and-add for group %d", i+1);
01289 if ((combined = cpl_geom_img_offset_saa(group_list,
01290 group_off, CPL_KERNEL_DEFAULT, 0, 0,
01291 CPL_GEOM_FIRST, NULL, NULL)) == NULL) {
01292 cpl_msg_error(cpl_func, "Cannot shift and add group nb %d", i+1);
01293 cpl_imagelist_delete(group_list);
01294 cpl_bivector_delete(group_off);
01295 cpl_imagelist_delete(abba);
01296 cpl_vector_delete(*abba_off);
01297 return NULL;
01298 }
01299 cpl_bivector_delete(group_off);
01300 cpl_image_delete(combined[1]);
01301 cpl_imagelist_set(abba, combined[0], i);
01302 cpl_free(combined);
01303 } else {
01304
01305 cpl_msg_debug(cpl_func, "Apply averaging for group %d", i+1);
01306 if ((tmp_ima = cpl_imagelist_collapse_create(group_list)) == NULL) {
01307 cpl_msg_error(cpl_func, "Cannot average group nb %d", i+1);
01308 cpl_imagelist_delete(group_list);
01309 cpl_imagelist_delete(abba);
01310 cpl_vector_delete(*abba_off);
01311 return NULL;
01312 }
01313 cpl_imagelist_set(abba, tmp_ima, i);
01314 }
01315 cpl_imagelist_delete(group_list);
01316 }
01317 return abba;
01318 }
01319
01320
01330
01331 static int isaac_spc_jitter_wavecal(const char * arc,
01332 const cpl_image * ima,
01333 const char * oh,
01334 const cpl_frameset * raw)
01335 {
01336 cpl_table * arc_tab;
01337 double * phdisprel;
01338 const cpl_frame * cur_frame;
01339 const char * cur_fname;
01340 computed_disprel * disprel;
01341 int order;
01342 double slit_width;
01343
01344
01345 if (isaac_spc_jitter_config.wavecal_in == 2) {
01346 if (arc == NULL) {
01347 cpl_msg_error(cpl_func,
01348 "Missing arc for the wavelength calibration");
01349 return -1;
01350 }
01351 cpl_msg_info(cpl_func, "Get the wavelength from the ARC file");
01352 if ((arc_tab = cpl_table_load(arc, 1, 0)) == NULL) {
01353 cpl_msg_error(cpl_func, "Cannot load the arc table");
01354 isaac_spc_jitter_config.wavecal_out = -1;
01355 return -1;
01356 }
01357 isaac_spc_jitter_config.wavecal_a0 =
01358 cpl_table_get_double(arc_tab, "WL_coefficients", 0, NULL);
01359 isaac_spc_jitter_config.wavecal_a1 =
01360 cpl_table_get_double(arc_tab, "WL_coefficients", 1, NULL);
01361 isaac_spc_jitter_config.wavecal_a2 =
01362 cpl_table_get_double(arc_tab, "WL_coefficients", 2, NULL);
01363 isaac_spc_jitter_config.wavecal_a3 =
01364 cpl_table_get_double(arc_tab, "WL_coefficients", 3, NULL);
01365 cpl_table_delete(arc_tab);
01366 isaac_spc_jitter_config.wavecal_out = 2;
01367 isaac_spc_jitter_config.wavecal_cc = -1.0;
01368 return 0;
01369 }
01370
01371
01372 cur_frame = cpl_frameset_get_frame_const(raw, 0);
01373 cur_fname = cpl_frame_get_filename(cur_frame);
01374
01375
01376 cpl_msg_info(cpl_func, "Compute the physical model");
01377 cpl_msg_indent_more();
01378 if ((phdisprel = isaac_get_disprel_estimate(cur_fname, 3)) == NULL) {
01379 cpl_msg_error(cpl_func, "cannot compute the physical model");
01380 isaac_spc_jitter_config.wavecal_out = -1;
01381 cpl_msg_indent_less();
01382 return -1;
01383 }
01384 cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3",
01385 phdisprel[0], phdisprel[1], phdisprel[2], phdisprel[3]);
01386 isaac_spc_jitter_config.wavecal_a0 = phdisprel[0];
01387 isaac_spc_jitter_config.wavecal_a1 = phdisprel[1];
01388 isaac_spc_jitter_config.wavecal_a2 = phdisprel[2];
01389 isaac_spc_jitter_config.wavecal_a3 = phdisprel[3];
01390 isaac_spc_jitter_config.wavecal_cc = -1.0;
01391 isaac_spc_jitter_config.wavecal_out = 0;
01392 cpl_msg_indent_less();
01393
01394
01395 if (isaac_spc_jitter_config.wavecal_in == 1) {
01396
01397 if ((slit_width = isaac_get_slitwidth(cur_fname)) == -1) {
01398 cpl_msg_warning(cpl_func, "cannot get the slit width");
01399 cpl_free(phdisprel);
01400 return 0;
01401 }
01402
01403 if ((order = isaac_find_order(cur_fname)) == -1) {
01404 cpl_msg_warning(cpl_func, "cannot get the order");
01405 cpl_free(phdisprel);
01406 return 0;
01407 }
01408
01409 cpl_msg_info(cpl_func, "Compute the wavelength with the sky lines");
01410 cpl_msg_indent_more();
01411 if ((disprel = spectro_compute_disprel(ima,
01412 isaac_spc_jitter_config.wavecal_rej_bottom,
01413 isaac_spc_jitter_config.wavecal_rej_top,
01414 isaac_spc_jitter_config.wavecal_rej_left,
01415 isaac_spc_jitter_config.wavecal_rej_right,
01416 isaac_spc_jitter_config.max_offset,
01417 isaac_has_thermal(cur_fname) > 0,
01418 "oh", oh, NULL, NULL, slit_width, order,
01419 (int)(cpl_msg_get_level() == CPL_MSG_DEBUG),
01420 phdisprel)) == NULL) {
01421 cpl_msg_error(cpl_func, "cannot compute the dispersion relation");
01422 cpl_free(phdisprel);
01423 cpl_msg_indent_less();
01424 return 0;
01425 }
01426 cpl_msg_info(cpl_func, "Cross correlation factor: %g", disprel->cc);
01427 cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3",
01428 disprel->poly[0], disprel->poly[1], disprel->poly[2],
01429 disprel->poly[3]);
01430 isaac_spc_jitter_config.wavecal_a0 = disprel->poly[0];
01431 isaac_spc_jitter_config.wavecal_a1 = disprel->poly[1];
01432 isaac_spc_jitter_config.wavecal_a2 = disprel->poly[2];
01433 isaac_spc_jitter_config.wavecal_a3 = disprel->poly[3];
01434 isaac_spc_jitter_config.wavecal_cc = disprel->cc;
01435 isaac_spc_jitter_config.wavecal_out = 1;
01436 if (disprel->poly != NULL) cpl_free(disprel->poly);
01437 cpl_free(disprel);
01438 cpl_msg_indent_less();
01439 }
01440 cpl_free(phdisprel);
01441 return 0;
01442 }
01443
01444
01477
01478 static cpl_imagelist * isaac_spc_jitter_nodded(cpl_imagelist * abba,
01479 cpl_vector * abba_off,
01480 cpl_vector ** nodded_off)
01481 {
01482 cpl_imagelist * nodded;
01483 cpl_image * tmp_ima;
01484 int nima;
01485 double * pabba_off;
01486 double * pnodded_off;
01487 double ref_off;
01488 int i;
01489
01490
01491 if ((abba == NULL) || (abba_off == NULL)) return NULL;
01492
01493
01494 nima = cpl_imagelist_get_size(abba);
01495 if (nima % 2) {
01496 cpl_msg_error(cpl_func, "Number of images should be even");
01497 return NULL;
01498 }
01499
01500
01501 if (isaac_spc_jitter_config.chopping == 0) {
01502
01503 *nodded_off = cpl_vector_duplicate(abba_off);
01504
01505 nodded = cpl_imagelist_new();
01506 for (i=0; i<(nima/2); i++) {
01507
01508 tmp_ima = cpl_image_duplicate(cpl_imagelist_get(abba, 2*i));
01509 cpl_image_subtract(tmp_ima, cpl_imagelist_get(abba, 2*i+1));
01510 cpl_imagelist_set(nodded, tmp_ima, 2*i);
01511
01512 tmp_ima = cpl_image_duplicate(cpl_imagelist_get(abba, 2*i+1));
01513 cpl_image_subtract(tmp_ima, cpl_imagelist_get(abba, 2*i));
01514 cpl_imagelist_set(nodded, tmp_ima, 2*i+1);
01515 }
01516
01517 } else if (isaac_spc_jitter_config.chopping == 1) {
01518
01519 *nodded_off = cpl_vector_new(nima/2);
01520 pnodded_off = cpl_vector_get_data(*nodded_off);
01521 pabba_off = cpl_vector_get_data(abba_off);
01522
01523 nodded = cpl_imagelist_new();
01524 for (i=0; i<nima/2; i++) {
01525 if ((pabba_off[0]-pabba_off[1])*(pabba_off[2*i]-pabba_off[2*i+1])
01526 > 0) {
01527
01528 pnodded_off[i] = pabba_off[2*i];
01529 tmp_ima = cpl_image_duplicate(cpl_imagelist_get(abba, 2*i));
01530 cpl_image_subtract(tmp_ima, cpl_imagelist_get(abba, 2*i+1));
01531 cpl_image_divide_scalar(tmp_ima, 2.0);
01532 cpl_imagelist_set(nodded, tmp_ima, i);
01533 } else {
01534
01535 pnodded_off[i] = pabba_off[2*i+1];
01536 tmp_ima = cpl_image_duplicate(cpl_imagelist_get(abba, 2*i+1));
01537 cpl_image_subtract(tmp_ima, cpl_imagelist_get(abba, 2*i));
01538 cpl_image_divide_scalar(tmp_ima, 2.0);
01539 cpl_imagelist_set(nodded, tmp_ima, i);
01540 }
01541 }
01542 } else {
01543 cpl_msg_error(cpl_func, "Unsupported chopping mode");
01544 return NULL;
01545 }
01546
01547
01548 ref_off = cpl_vector_get(*nodded_off, 0);
01549 cpl_vector_subtract_scalar(*nodded_off, ref_off);
01550 return nodded;
01551 }
01552
01553
01562
01563 static cpl_imagelist * isaac_spc_jitter_distor(
01564 cpl_imagelist * ilist,
01565 const char * arc,
01566 const char * startrace)
01567 {
01568 cpl_polynomial * arc_poly;
01569 cpl_polynomial * sttr_poly;
01570 cpl_table * tab;
01571 cpl_size power[2];
01572 cpl_vector * profile;
01573 cpl_imagelist * warped_list;
01574 cpl_image * warped;
01575 int i;
01576
01577
01578 if (ilist == NULL) return NULL;
01579 if ((arc == NULL) && (startrace == NULL)) return NULL;
01580
01581
01582 arc_poly = cpl_polynomial_new(2);
01583 if (arc != NULL) {
01584 cpl_msg_info(cpl_func, "Get the arc distortion from the file");
01585 if ((tab = cpl_table_load(arc, 1, 0)) == NULL) {
01586 cpl_msg_error(cpl_func, "cannot load the arc table");
01587 cpl_polynomial_delete(arc_poly);
01588 return NULL;
01589 }
01590 for (i=0; i<cpl_table_get_nrow(tab); i++) {
01591 if (cpl_table_get_column_type(tab, "Degree_of_x") == CPL_TYPE_INT) {
01592 power[0] = cpl_table_get_int(tab, "Degree_of_x", i, NULL);
01593 power[1] = cpl_table_get_int(tab, "Degree_of_y", i, NULL);
01594 } else {
01595 power[0] = cpl_table_get_double(tab, "Degree_of_x", i, NULL);
01596 power[1] = cpl_table_get_double(tab, "Degree_of_y", i, NULL);
01597 }
01598 cpl_polynomial_set_coeff(arc_poly, power,
01599 cpl_table_get_double(tab, "poly2d_coef", i, NULL));
01600 }
01601 cpl_table_delete(tab);
01602 } else {
01603 cpl_msg_info(cpl_func, "Use the ID polynomial for the arc dist");
01604 power[0] = 1;
01605 power[1] = 0;
01606 cpl_polynomial_set_coeff(arc_poly, power, 1.0);
01607 }
01608
01609
01610 sttr_poly = cpl_polynomial_new(2);
01611 if (startrace != NULL) {
01612 cpl_msg_info(cpl_func, "Get the startrace distortion from the file");
01613 if ((tab = cpl_table_load(startrace, 1, 0)) == NULL) {
01614 cpl_msg_error(cpl_func, "cannot load the startrace table");
01615 cpl_polynomial_delete(arc_poly);
01616 cpl_polynomial_delete(sttr_poly);
01617 return NULL;
01618 }
01619 for (i=0; i<cpl_table_get_nrow(tab); i++) {
01620
01621 if (cpl_table_get_column_type(tab, "Degree_of_x") == CPL_TYPE_INT) {
01622 power[0] = cpl_table_get_int(tab, "Degree_of_x", i, NULL);
01623 power[1] = cpl_table_get_int(tab, "Degree_of_y", i, NULL);
01624 } else {
01625 power[0] = cpl_table_get_double(tab, "Degree_of_x", i, NULL);
01626 power[1] = cpl_table_get_double(tab, "Degree_of_y", i, NULL);
01627 }
01628 cpl_polynomial_set_coeff(sttr_poly, power,
01629 cpl_table_get_double(tab, "poly2d_coef", i, NULL));
01630 }
01631 cpl_table_delete(tab);
01632 } else {
01633 cpl_msg_info(cpl_func, "Use the ID polynomial for the startrace dist");
01634 power[0] = 0;
01635 power[1] = 1;
01636 cpl_polynomial_set_coeff(sttr_poly, power, 1.0);
01637 }
01638
01639
01640 profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES);
01641 cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_DEFAULT,
01642 CPL_KERNEL_DEF_WIDTH);
01643
01644
01645 warped_list = cpl_imagelist_new();
01646 for (i=0; i<cpl_imagelist_get_size(ilist); i++) {
01647 warped = cpl_image_duplicate(cpl_imagelist_get(ilist, i));
01648 if (cpl_image_warp_polynomial(warped, cpl_imagelist_get(ilist, i),
01649 arc_poly, sttr_poly, profile, CPL_KERNEL_DEF_WIDTH, profile,
01650 CPL_KERNEL_DEF_WIDTH) != CPL_ERROR_NONE) {
01651 cpl_msg_error(cpl_func, "cannot correct the distortion");
01652 cpl_image_delete(warped);
01653 cpl_polynomial_delete(arc_poly);
01654 cpl_polynomial_delete(sttr_poly);
01655 cpl_vector_delete(profile);
01656 return NULL;
01657 }
01658 cpl_imagelist_set(warped_list, warped, i);
01659 }
01660 cpl_vector_delete(profile);
01661 cpl_polynomial_delete(arc_poly);
01662 cpl_polynomial_delete(sttr_poly);
01663 return warped_list;
01664 }
01665
01666
01674
01675 static double isaac_spc_jitter_refine_offset(const cpl_image * ima1,
01676 const cpl_image * ima2)
01677 {
01678 double pos1, pos2;
01679
01680
01681 if (ima1 == NULL) return 10000.0;
01682 if (ima2 == NULL) return 10000.0;
01683
01684
01685 if (irplib_spectrum_find_brightest(ima1, 0.0, NO_SHADOW, 0.0, 0,
01686 &pos1) == -1){
01687 return 10000.0;
01688 }
01689 if (irplib_spectrum_find_brightest(ima2, 0.0, NO_SHADOW, 0.0, 0,
01690 &pos2) == -1){
01691 return 10000.0;
01692 }
01693 return pos1-pos2;
01694 }
01695
01696
01703
01704 static cpl_table * isaac_spc_jitter_extract(const cpl_image * combined)
01705 {
01706 int lo_dist, hi_dist, lo_width, hi_width, spec_pos;
01707 int nx, ny;
01708 double pos;
01709 int low_side, up_side;
01710 int sky_pos[4];
01711 cpl_vector * sky;
01712 cpl_vector * spec;
01713 cpl_vector * wl;
01714 cpl_image * colfluximg;
01715 double * pspec;
01716 double * psky;
01717 double * pwl;
01718 cpl_table * out;
01719 cpl_bivector * toplot;
01720 int i;
01721
01722
01723 if (combined == NULL) return NULL;
01724
01725
01726 nx = cpl_image_get_size_x(combined);
01727 ny = cpl_image_get_size_y(combined);
01728 lo_dist = isaac_spc_jitter_config.extr_sky_lo_dist;
01729 hi_dist = isaac_spc_jitter_config.extr_sky_hi_dist;
01730 lo_width = isaac_spc_jitter_config.extr_sky_lo_width;
01731 hi_width = isaac_spc_jitter_config.extr_sky_hi_width;
01732 spec_pos = isaac_spc_jitter_config.extr_spec_pos;
01733
01734
01735 if (spec_pos < 0) {
01736 const int nthrow = cpl_vector_get_size(isaac_spc_jitter_config.throws);
01737
01738 if (nthrow < 1) {
01739 cpl_msg_error(cpl_func,
01740 "Need a throw value to detect the spectra !!");
01741 cpl_ensure(0, CPL_ERROR_DATA_NOT_FOUND, NULL);
01742 }
01743
01744 for (i=0; i < nthrow; i++){
01745 const int throw = (int)cpl_vector_get(isaac_spc_jitter_config.throws,
01746 i);
01747 if (irplib_spectrum_find_brightest(combined, throw, TWO_SHADOWS,
01748 0.0, 0, &pos) == 0) break;
01749 if (irplib_spectrum_find_brightest(combined, throw, ONE_SHADOW,
01750 0.0, 0, &pos) == 0) break;
01751 }
01752 if (i == nthrow) {
01753 cpl_msg_error(cpl_func, "Could not detect the spectrum using %d "
01754 "throw(s):", i);
01755 #if 0
01756 cpl_vector_dump(isaac_spc_jitter_config.throws, stderr);
01757 cpl_plot_image("", "", "", combined);
01758 #endif
01759 cpl_ensure(0, CPL_ERROR_DATA_NOT_FOUND, NULL);
01760 }
01761 spec_pos = (int)pos;
01762 cpl_msg_info(cpl_func, "Spectrum detected at y = %d", spec_pos);
01763 }
01764
01765
01766
01767
01768 low_side = spec_pos - (int)(isaac_spc_jitter_config.extr_spec_width/2);
01769 up_side = low_side + isaac_spc_jitter_config.extr_spec_width;
01770 if (up_side < low_side) {
01771 (void)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01772 "Spectrum zone invalid: low=%d > up=%d",
01773 low_side, up_side);
01774 return NULL;
01775 }
01776 if (low_side < 1) {
01777 (void)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01778 "Spectrum zone lower limit too low: "
01779 "%d < 1", low_side);
01780 return NULL;
01781 }
01782 if (up_side > ny) {
01783 (void)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01784 "Spectrum zone upper limit too high: "
01785 "%d > ny=%d", up_side, ny);
01786 return NULL;
01787 }
01788
01789
01790 colfluximg = cpl_image_collapse_window_create(combined, 1, low_side,
01791 nx, up_side, 0);
01792
01793 if (cpl_image_count_rejected(colfluximg) == up_side - low_side + 1) {
01794 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
01795 "Combined image has undefined flux "
01796 "from column %d to %d", low_side, up_side);
01797 cpl_image_delete(colfluximg);
01798 return NULL;
01799 }
01800
01801
01802 if (lo_dist < 0) lo_dist = 2*isaac_spc_jitter_config.extr_spec_width;
01803 if (hi_dist < 0) hi_dist = 2*isaac_spc_jitter_config.extr_spec_width;
01804 sky_pos[1] = spec_pos - lo_dist;
01805 sky_pos[0] = sky_pos[1] - lo_width;
01806 sky_pos[2] = spec_pos + hi_dist;
01807 sky_pos[3] = sky_pos[2] + hi_width;
01808
01809
01810 sky = cpl_vector_new(nx);
01811 psky = cpl_vector_get_data(sky);
01812 if (((sky_pos[0] < 1) || (lo_width == 0)) &&
01813 ((sky_pos[3] <= ny) && (hi_width > 0))) {
01814 for (i=0; i<nx; i++) {
01815 psky[i] = cpl_image_get_median_window(combined, i+1,
01816 sky_pos[2], i+1, sky_pos[3]);
01817 }
01818 } else if (((sky_pos[3] > ny) || (hi_width == 0))
01819 && ((sky_pos[0] > 0) && (lo_width > 0))) {
01820 for (i=0; i<nx; i++) {
01821 psky[i] = cpl_image_get_median_window(combined, i+1,
01822 sky_pos[0], i+1, sky_pos[1]);
01823 }
01824 } else if ((lo_width != 0) && (hi_width != 0)
01825 && (sky_pos[0] > 0) && (sky_pos[3] <= ny)) {
01826 for (i=0; i<nx; i++) {
01827 psky[i] = cpl_image_get_median_window(combined, i+1,
01828 sky_pos[2], i+1, sky_pos[3]);
01829 psky[i] += cpl_image_get_median_window(combined, i+1,
01830 sky_pos[0], i+1, sky_pos[1]);
01831 psky[i] /= 2.0;
01832 }
01833 } else {
01834 for (i=0; i<nx; i++) psky[i] = 0.0;
01835 }
01836
01837
01838 spec = cpl_vector_new(nx);
01839 pspec = cpl_vector_get_data(spec);
01840 for (i=0; i<nx; i++) {
01841 int is_bad = 0;
01842 const double colflux = cpl_image_get(colfluximg, i+1, 1, &is_bad);
01843
01844 if (is_bad) {
01845 pspec[i] = 0.0;
01846 cpl_msg_warning(cpl_func, "Combined image has undefined flux in "
01847 "column %d", i+1);
01848 } else {
01849 pspec[i] = colflux
01850 - psky[i] * isaac_spc_jitter_config.extr_spec_width;
01851 }
01852 }
01853 cpl_image_delete(colfluximg);
01854
01855
01856 wl = cpl_vector_new(nx);
01857 pwl = cpl_vector_get_data(wl);
01858 for (i=0; i<nx; i++) {
01859 pwl[i] = isaac_spc_jitter_config.wavecal_a0 +
01860 isaac_spc_jitter_config.wavecal_a1 * (i+1) +
01861 isaac_spc_jitter_config.wavecal_a2 * (i+1) * (i+1) +
01862 isaac_spc_jitter_config.wavecal_a3 * (i+1) * (i+1) * (i+1);
01863 }
01864
01865
01866 if (isaac_spc_jitter_config.plot > 0) {
01867 toplot = cpl_bivector_wrap_vectors(wl, spec);
01868 cpl_plot_bivector(NULL, "t 'Spectrum' w lines", NULL, toplot);
01869 cpl_bivector_unwrap_vectors(toplot);
01870 toplot = cpl_bivector_wrap_vectors(wl, sky);
01871 cpl_plot_bivector(NULL, "t 'Sky' w lines", NULL, toplot);
01872 cpl_bivector_unwrap_vectors(toplot);
01873 }
01874
01875
01876 out = cpl_table_new(nx);
01877 cpl_table_new_column(out, "X_coordinate", CPL_TYPE_DOUBLE);
01878 cpl_table_new_column(out, "Extracted_spectrum_value", CPL_TYPE_DOUBLE);
01879 cpl_table_new_column(out, "Sky_spectrum", CPL_TYPE_DOUBLE);
01880 for (i=0; i<nx; i++) {
01881 cpl_table_set_double(out, "X_coordinate", i, pwl[i]);
01882 cpl_table_set_double(out, "Extracted_spectrum_value", i, pspec[i]);
01883 cpl_table_set_double(out, "Sky_spectrum", i, psky[i]);
01884 }
01885 cpl_vector_delete(wl);
01886 cpl_vector_delete(spec);
01887 cpl_vector_delete(sky);
01888 return out;
01889 }
01890
01891
01902
01903 static int isaac_spc_jitter_std(const char * seds_file,
01904 const char * stdstars,
01905 const cpl_frame * frame,
01906 cpl_table * tab,
01907 double mag)
01908 {
01909 double surface = CPL_MATH_PI * 400 * 400;
01910 cpl_propertylist * plist;
01911 double dit, ra, dec, magnitude, cent_wl;
01912 isaac_band band;
01913 const int nelem = cpl_table_get_nrow(tab);
01914 cpl_vector * wl;
01915 cpl_vector * spec;
01916 cpl_bivector * spec_biv;
01917 cpl_bivector * sed;
01918 cpl_vector * efficiency;
01919 cpl_vector * mag_zero;
01920 cpl_vector * conversion;
01921 int i;
01922
01923
01924 if (seds_file == NULL) return -1;
01925 if (stdstars == NULL) return -1;
01926 if (frame == NULL) return -1;
01927 if (tab == NULL) return -1;
01928 if (cpl_error_get_code()) return -1;
01929
01930
01931 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(frame),0))==NULL) {
01932 cpl_msg_error(cpl_func, "Cannot load the property list");
01933 return -1;
01934 }
01935
01936
01937 dit = isaac_pfits_get_dit(plist);
01938 if (cpl_error_get_code()) {
01939 cpl_msg_error(cpl_func, "Cannot get DIT");
01940 cpl_propertylist_delete(plist);
01941 return -1;
01942 }
01943 cpl_msg_info(cpl_func, "DIT: %g", dit);
01944
01945
01946 if ((band = isaac_get_associated_filter(isaac_spc_jitter_config.filter))
01947 == ISAAC_BAND_UNKNOWN) {
01948 cpl_msg_error(cpl_func, "Cannot associate the filter to a BB one");
01949 cpl_propertylist_delete(plist);
01950 return -1;
01951 }
01952 cpl_msg_info(cpl_func, "Band : %s", isaac_std_band_name(band));
01953
01954
01955 ra = isaac_pfits_get_ra(plist);
01956 dec = isaac_pfits_get_dec(plist);
01957 if (cpl_error_get_code()) {
01958 cpl_msg_error(cpl_func, "Cannot get star position");
01959 cpl_propertylist_delete(plist);
01960 return -1;
01961 }
01962 cpl_msg_info(cpl_func, "RA: %g DEC: %g", ra, dec);
01963
01964
01965 if (mag < 0) {
01966
01967 if (irplib_stdstar_find_star(stdstars, ra, dec,
01968 isaac_std_band_name(isaac_get_bbfilter(isaac_spc_jitter_config.filter)),
01969 "all", &magnitude,
01970 &isaac_spc_jitter_config.starname,
01971 &isaac_spc_jitter_config.sptype,
01972 NULL, NULL, NULL, 2.0)) {
01973 cpl_msg_error(cpl_func, "Cannot find the star in catalogs");
01974 cpl_propertylist_delete(plist);
01975 return -1;
01976 }
01977 } else {
01978 magnitude = mag;
01979 }
01980 cpl_propertylist_delete(plist);
01981 (void)strncpy(isaac_spc_jitter_config.filter_ref,
01982 isaac_std_band_name(isaac_get_bbfilter
01983 (isaac_spc_jitter_config.filter)),
01984 KEYSIZE-1);
01985 cpl_msg_info(cpl_func, "Magnitude: %g", magnitude);
01986 isaac_spc_jitter_config.std_magnitude = magnitude;
01987
01988
01989 switch (band) {
01990 case ISAAC_BAND_Z: cent_wl = CENT_WL_BAND_Z; break;
01991 case ISAAC_BAND_SZ: cent_wl = CENT_WL_BAND_SZ; break;
01992 case ISAAC_BAND_J: cent_wl = CENT_WL_BAND_J; break;
01993 case ISAAC_BAND_JBLOCK: cent_wl = CENT_WL_BAND_J; break;
01994 case ISAAC_BAND_SH: cent_wl = CENT_WL_BAND_H; break;
01995 case ISAAC_BAND_SK: cent_wl = CENT_WL_BAND_K; break;
01996 case ISAAC_BAND_SL: cent_wl = CENT_WL_BAND_SL; break;
01997 case ISAAC_BAND_M: cent_wl = CENT_WL_BAND_M; break;
01998 default:
01999 cpl_msg_error(cpl_func, "Unsupported band: %s",
02000 isaac_std_band_name(band));
02001 return -1;
02002 }
02003 cpl_msg_info(cpl_func, "Center of band : %g microns", cent_wl);
02004
02005
02006 sed = irplib_stdstar_get_sed(seds_file, isaac_spc_jitter_config.sptype);
02007 if (sed == NULL) {
02008 cpl_msg_error(cpl_func, "Cannot get the SED");
02009 return -1;
02010 }
02011
02012
02013 wl = cpl_vector_wrap(nelem, cpl_table_get_data_double(tab,
02014 "X_coordinate"));
02015 spec = cpl_vector_wrap(nelem, cpl_table_get_data_double(tab,
02016 "Extracted_spectrum_value"));
02017 spec_biv = cpl_bivector_wrap_vectors(wl, spec);
02018
02019
02020 if ((conversion = irplib_stdstar_get_conversion(spec_biv, dit, surface,
02021 4.5, magnitude)) == NULL) {
02022 cpl_msg_error(cpl_func, "Cannot get the conversion");
02023 cpl_bivector_unwrap_vectors(spec_biv);
02024 cpl_vector_unwrap(spec);
02025 cpl_vector_unwrap(wl);
02026 cpl_bivector_delete(sed);
02027 return -1;
02028 }
02029
02030
02031 if ((mag_zero = irplib_stdstar_get_mag_zero(sed,
02032 cpl_bivector_get_x(spec_biv), cent_wl)) == NULL) {
02033 cpl_msg_error(cpl_func, "Cannot get the 0 magnitude spectrum");
02034 cpl_bivector_unwrap_vectors(spec_biv);
02035 cpl_vector_unwrap(spec);
02036 cpl_vector_unwrap(wl);
02037 cpl_bivector_delete(sed);
02038 cpl_vector_delete(conversion);
02039 return -1;
02040 }
02041 cpl_bivector_unwrap_vectors(spec_biv);
02042 cpl_vector_unwrap(spec);
02043 cpl_vector_unwrap(wl);
02044 cpl_bivector_delete(sed);
02045
02046
02047 for (i=0; i<cpl_vector_get_size(mag_zero); i++) {
02048 if (cpl_vector_get(mag_zero, i) < 1e-19) {
02049 cpl_vector_set(mag_zero, i, 1.0);
02050 }
02051 }
02052
02053
02054 efficiency = cpl_vector_duplicate(conversion);
02055 if (cpl_vector_divide(efficiency, mag_zero) != CPL_ERROR_NONE) {
02056 cpl_msg_error(cpl_func, "Missing SED info in this wavelength range");
02057 cpl_vector_delete(conversion);
02058 cpl_vector_delete(mag_zero);
02059 cpl_vector_delete(efficiency);
02060 return -1;
02061 }
02062
02063
02064 for (i=0; i<cpl_vector_get_size(mag_zero); i++) {
02065 if (cpl_vector_get(mag_zero, i) == 1.0) {
02066 cpl_vector_set(efficiency, i, 0.0);
02067 }
02068 }
02069 cpl_vector_delete(mag_zero);
02070
02071
02072 cpl_table_wrap_double(tab, cpl_vector_get_data(efficiency), "Efficiency");
02073 cpl_table_wrap_double(tab, cpl_vector_get_data(conversion), "Conversion");
02074 cpl_vector_unwrap(efficiency);
02075 cpl_vector_unwrap(conversion);
02076
02077
02078 if (isaac_spc_jitter_config.plot > 0) {
02079 wl = cpl_vector_wrap(nelem, cpl_table_get_data_double(tab,
02080 "X_coordinate"));
02081 spec = cpl_vector_wrap(nelem, cpl_table_get_data_double(tab,
02082 "Conversion"));
02083 spec_biv = cpl_bivector_wrap_vectors(wl, spec);
02084 cpl_plot_bivector(NULL, "t 'Conversion' w lines",
02085 NULL, spec_biv);
02086 cpl_bivector_unwrap_vectors(spec_biv);
02087 cpl_vector_unwrap(spec);
02088 spec = cpl_vector_wrap(nelem, cpl_table_get_data_double(tab,
02089 "Efficiency"));
02090 spec_biv = cpl_bivector_wrap_vectors(wl, spec);
02091 cpl_plot_bivector(NULL, "t 'Efficiency' w lines", NULL, spec_biv);
02092 cpl_bivector_unwrap_vectors(spec_biv);
02093 cpl_vector_unwrap(spec);
02094 cpl_vector_unwrap(wl);
02095 }
02096
02097 return 0;
02098 }
02099
02100
02111
02112 static
02113 cpl_error_code isaac_spc_jitter_save(cpl_frameset * set,
02114 const cpl_image * ima,
02115 const cpl_image * contrib,
02116 const cpl_table * tab,
02117 const cpl_parameterlist * parlist)
02118 {
02119
02120 cpl_propertylist * qclist = cpl_propertylist_new();
02121 cpl_propertylist * paflist = NULL;
02122 const cpl_frame * ref_frame;
02123 char * qc_str = NULL;
02124 const char * procat;
02125 const int nintens
02126 = cpl_vector_get_size(isaac_spc_jitter_config.intensities);
02127 int i;
02128
02129 bug_if(contrib == NULL);
02130
02131
02132
02133 if (isaac_spc_jitter_config.filter[0] != (char)0)
02134 bug_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS",
02135 isaac_spc_jitter_config.filter));
02136
02137 bug_if(cpl_propertylist_append_double(qclist, "ESO QC DISPCO1",
02138 isaac_spc_jitter_config.wavecal_a0));
02139 cpl_propertylist_append_double(qclist, "ESO QC DISPCO2",
02140 isaac_spc_jitter_config.wavecal_a1);
02141 cpl_propertylist_append_double(qclist, "ESO QC DISPCO3",
02142 isaac_spc_jitter_config.wavecal_a2);
02143 cpl_propertylist_append_double(qclist, "ESO QC DISPCO4",
02144 isaac_spc_jitter_config.wavecal_a3);
02145 cpl_propertylist_append_double(qclist, "ESO QC WLEN",
02146 isaac_spc_jitter_config.wavecal_a0 +
02147 isaac_spc_jitter_config.wavecal_a1 * 512 +
02148 isaac_spc_jitter_config.wavecal_a2 * 512 *
02149 512 +
02150 isaac_spc_jitter_config.wavecal_a3 * 512 *
02151 512 * 512);
02152 bug_if(cpl_propertylist_append_double(qclist, "ESO QC DISP XCORR",
02153 isaac_spc_jitter_config.wavecal_cc));
02154 if (isaac_spc_jitter_config.wavecal_out == 0) {
02155 cpl_propertylist_append_string(qclist, "ESO QC WLMETHOD",
02156 "physical model");
02157 } else if (isaac_spc_jitter_config.wavecal_out == 1) {
02158 cpl_propertylist_append_string(qclist, "ESO QC WLMETHOD",
02159 "sky lines");
02160 } else if (isaac_spc_jitter_config.wavecal_out == 2) {
02161 cpl_propertylist_append_string(qclist, "ESO QC WLMETHOD",
02162 "arc file");
02163 }
02164 for (i = 0; i < nintens; i++) {
02165 const double intens
02166 = cpl_vector_get(isaac_spc_jitter_config.intensities, i);
02167
02168 qc_str = cpl_sprintf("ESO QC SPEC INTENS%d", i+1);
02169 cpl_propertylist_append_double(qclist, qc_str, intens);
02170 cpl_free(qc_str);
02171 qc_str = NULL;
02172 }
02173
02174
02175 if (isaac_spc_jitter_config.std_mode == 1) {
02176 bug_if(cpl_propertylist_append_string(qclist, "ESO QC STDNAME",
02177 isaac_spc_jitter_config.starname ?
02178 isaac_spc_jitter_config.starname :
02179 ""));
02180 bug_if(cpl_propertylist_append_string(qclist, "ESO QC SPECTYPE",
02181 isaac_spc_jitter_config.sptype ?
02182 isaac_spc_jitter_config.sptype :
02183 ""));
02184 cpl_propertylist_append_double(qclist, "ESO QC STARMAG",
02185 isaac_spc_jitter_config.std_magnitude);
02186 if (isaac_spc_jitter_config.filter_ref[0] != (char)0)
02187 cpl_propertylist_append_string(qclist, "ESO QC FILTER REF",
02188 isaac_spc_jitter_config.filter_ref);
02189 }
02190
02191
02192 cpl_propertylist_update_double(qclist, "CRVAL1",
02193 isaac_spc_jitter_config.wavecal_a0);
02194 cpl_propertylist_update_double(qclist, "CRVAL2", 1.0);
02195 cpl_propertylist_update_double(qclist, "CRPIX1", 1.0);
02196 cpl_propertylist_update_double(qclist, "CRPIX2", 1.0);
02197 cpl_propertylist_update_double(qclist, "CDELT1",
02198 isaac_spc_jitter_config.wavecal_a1);
02199 cpl_propertylist_update_double(qclist, "CDELT2", 1.0);
02200 cpl_propertylist_update_string(qclist, "CTYPE1", "LINEAR");
02201 cpl_propertylist_update_string(qclist, "CTYPE2", "LINEAR");
02202 if (cpl_propertylist_has(qclist, "CD1_1")) {
02203 cpl_propertylist_update_double(qclist, "CD1_1",
02204 isaac_spc_jitter_config.wavecal_a1);
02205 } else {
02206 cpl_propertylist_insert_after_double(qclist, "CTYPE2", "CD1_1",
02207 isaac_spc_jitter_config.wavecal_a1);
02208 }
02209 if (cpl_propertylist_has(qclist, "CD2_2")) {
02210 cpl_propertylist_update_double(qclist, "CD2_2", 1.0);
02211 } else {
02212 cpl_propertylist_insert_after_double(qclist, "CD1_1", "CD2_2", 1.0);
02213 }
02214
02215
02216 procat = isaac_spc_jitter_config.std_mode == 1 ?
02217 ISAAC_SPC_JITTER_COMB_STD : ISAAC_SPC_JITTER_COMB;
02218
02219 irplib_dfs_save_image(set, parlist, set, ima, CPL_BPP_IEEE_FLOAT,
02220 RECIPE_STRING, procat, qclist, NULL,
02221 PACKAGE "/" PACKAGE_VERSION,
02222 RECIPE_STRING "_combined" CPL_DFS_FITS);
02223
02224
02225 skip_if (cpl_image_save(contrib, RECIPE_STRING "_combined" CPL_DFS_FITS,
02226 CPL_BPP_16_UNSIGNED, NULL, CPL_IO_EXTEND));
02227
02228
02229 if (tab != NULL) {
02230 const char * procatt = isaac_spc_jitter_config.std_mode == 1 ?
02231 ISAAC_SPC_JITTER_EXTR_STD : ISAAC_SPC_JITTER_EXTR;
02232
02233 irplib_dfs_save_table(set, parlist, set, tab, NULL, RECIPE_STRING,
02234 procatt, qclist, NULL,
02235 PACKAGE "/" PACKAGE_VERSION,
02236 RECIPE_STRING "_extracted" CPL_DFS_FITS);
02237 }
02238
02239
02240 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
02241
02242
02243 paflist = cpl_propertylist_load_regexp(cpl_frame_get_filename(ref_frame),
02244 0, "^(ARCFILE|MJD-OBS|INSTRUME"
02245 "|ESO TPL ID|ESO TPL NEXP"
02246 "|ESO DPR CATG|ESO DPR TECH"
02247 "|ESO DPR TYPE|DATE-OBS"
02248 "|ESO INS GRAT NAME"
02249 "|ESO INS GRAT WLEN"
02250 "|ESO INS OPTI1 ID|ESO OBS ID"
02251 "|ESO OBS TARG NAME)$", 0);
02252 skip_if (paflist == NULL);
02253
02254
02255 bug_if(cpl_propertylist_append(paflist, qclist));
02256 cpl_propertylist_empty(qclist);
02257
02258
02259 cpl_propertylist_update_string(paflist, CPL_DFS_PRO_CATG, procat);
02260
02261
02262 skip_if(cpl_dfs_save_paf("ISAAC", RECIPE_STRING, paflist,
02263 RECIPE_STRING CPL_DFS_PAF));
02264
02265 end_skip;
02266
02267 cpl_propertylist_delete(paflist);
02268 cpl_propertylist_delete(qclist);
02269 cpl_free(qc_str);
02270
02271 return CPL_ERROR_NONE;
02272 }
02273
02274
02283
02284 static int off_comp(double off1, double off2, double thresh)
02285 {
02286 return (off1 > thresh && off2 < thresh) || (off1 < thresh && off2 > thresh)
02287 ? 1 : 0;
02288 }
02289