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