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 #include <vimos_calib_impl.h>
00033
00034 #include <math.h>
00035 #include <cpl.h>
00036 #include <moses.h>
00037 #include <fors_dfs.h>
00038 #include <fors_qc.h>
00039
00040 #define vimos_calib_exit(message) \
00041 { \
00042 if (message) cpl_msg_error(recipe, message); \
00043 cpl_free(instrume); \
00044 cpl_free(pipefile); \
00045 cpl_free(fiterror); \
00046 cpl_free(fitlines); \
00047 cpl_image_delete(bias); \
00048 cpl_image_delete(master_bias); \
00049 cpl_image_delete(coordinate); \
00050 cpl_image_delete(checkwave); \
00051 cpl_image_delete(flat); \
00052 cpl_image_delete(master_flat); \
00053 cpl_image_delete(norm_flat); \
00054 cpl_image_delete(rainbow); \
00055 cpl_image_delete(rectified); \
00056 cpl_image_delete(residual); \
00057 cpl_image_delete(smo_flat); \
00058 cpl_image_delete(spatial); \
00059 cpl_image_delete(spectra); \
00060 cpl_image_delete(wavemap); \
00061 cpl_image_delete(delta); \
00062 cpl_mask_delete(refmask); \
00063 cpl_propertylist_delete(header); \
00064 cpl_propertylist_delete(save_header); \
00065 cpl_propertylist_delete(qclist); \
00066 cpl_table_delete(grism_table); \
00067 cpl_table_delete(idscoeff); \
00068 cpl_table_delete(restable); \
00069 cpl_table_delete(maskslits); \
00070 cpl_table_delete(overscans); \
00071 cpl_table_delete(traces); \
00072 cpl_table_delete(polytraces); \
00073 cpl_table_delete(slits); \
00074 cpl_table_delete(restab); \
00075 cpl_table_delete(global); \
00076 cpl_table_delete(wavelengths); \
00077 cpl_vector_delete(lines); \
00078 cpl_msg_indent_less(); \
00079 return -1; \
00080 }
00081
00082 #define vimos_calib_exit_memcheck(message) \
00083 { \
00084 if (message) cpl_msg_info(recipe, message); \
00085 printf("free instrume (%p)\n", instrume); \
00086 cpl_free(instrume); \
00087 printf("free pipefile (%p)\n", pipefile); \
00088 cpl_free(pipefile); \
00089 printf("free fiterror (%p)\n", fiterror); \
00090 cpl_free(fiterror); \
00091 printf("free fitlines (%p)\n", fitlines); \
00092 cpl_free(fitlines); \
00093 printf("free bias (%p)\n", bias); \
00094 cpl_image_delete(bias); \
00095 printf("free master_bias (%p)\n", master_bias); \
00096 cpl_image_delete(master_bias); \
00097 printf("free coordinate (%p)\n", coordinate); \
00098 cpl_image_delete(coordinate); \
00099 printf("free checkwave (%p)\n", checkwave); \
00100 cpl_image_delete(checkwave); \
00101 printf("free flat (%p)\n", flat); \
00102 cpl_image_delete(flat); \
00103 printf("free master_flat (%p)\n", master_flat); \
00104 cpl_image_delete(master_flat); \
00105 printf("free norm_flat (%p)\n", norm_flat); \
00106 cpl_image_delete(norm_flat); \
00107 printf("free rainbow (%p)\n", rainbow); \
00108 cpl_image_delete(rainbow); \
00109 printf("free rectified (%p)\n", rectified); \
00110 cpl_image_delete(rectified); \
00111 printf("free residual (%p)\n", residual); \
00112 cpl_image_delete(residual); \
00113 printf("free smo_flat (%p)\n", smo_flat); \
00114 cpl_image_delete(smo_flat); \
00115 printf("free spatial (%p)\n", spatial); \
00116 cpl_image_delete(spatial); \
00117 printf("free spectra (%p)\n", spectra); \
00118 cpl_image_delete(spectra); \
00119 printf("free wavemap (%p)\n", wavemap); \
00120 cpl_image_delete(wavemap); \
00121 printf("free delta (%p)\n", delta); \
00122 cpl_image_delete(delta); \
00123 printf("free refmask (%p)\n", refmask); \
00124 cpl_mask_delete(refmask); \
00125 printf("free header (%p)\n", header); \
00126 cpl_propertylist_delete(header); \
00127 printf("free save_header (%p)\n", save_header); \
00128 cpl_propertylist_delete(save_header); \
00129 printf("free qclist (%p)\n", qclist); \
00130 cpl_propertylist_delete(qclist); \
00131 printf("free grism_table (%p)\n", grism_table); \
00132 cpl_table_delete(grism_table); \
00133 printf("free idscoeff (%p)\n", idscoeff); \
00134 cpl_table_delete(idscoeff); \
00135 printf("free restable (%p)\n", restable); \
00136 cpl_table_delete(restable); \
00137 printf("free maskslits (%p)\n", maskslits); \
00138 cpl_table_delete(maskslits); \
00139 printf("free overscans (%p)\n", overscans); \
00140 cpl_table_delete(overscans); \
00141 printf("free traces (%p)\n", traces); \
00142 cpl_table_delete(traces); \
00143 printf("free polytraces (%p)\n", polytraces); \
00144 cpl_table_delete(polytraces); \
00145 printf("free slits (%p)\n", slits); \
00146 cpl_table_delete(slits); \
00147 printf("free restab (%p)\n", restab); \
00148 cpl_table_delete(restab); \
00149 printf("free global (%p)\n", global); \
00150 cpl_table_delete(global); \
00151 printf("free wavelengths (%p)\n", wavelengths); \
00152 cpl_table_delete(wavelengths); \
00153 printf("free lines (%p)\n", lines); \
00154 cpl_vector_delete(lines); \
00155 cpl_msg_indent_less(); \
00156 return 0; \
00157 }
00158
00174 int vimos_calib_impl(cpl_frameset *frameset, cpl_parameterlist *parlist)
00175 {
00176
00177 const char *recipe = "vimos_calib";
00178
00179
00180
00181
00182
00183 double dispersion;
00184 double peakdetection;
00185 int wdegree;
00186 int wradius;
00187 double wreject;
00188 int wmode;
00189 const char *wcolumn;
00190 int cdegree;
00191 int cmode;
00192 double startwavelength;
00193 double endwavelength;
00194 double reference;
00195 int slit_ident;
00196 int sdegree;
00197 int ddegree;
00198 int sradius;
00199 int dradius;
00200 int qc;
00201 int check;
00202
00203
00204
00205
00206
00207 cpl_imagelist *biases = NULL;
00208 cpl_image *bias = NULL;
00209 cpl_image *master_bias = NULL;
00210 cpl_image *multi_bias = NULL;
00211 cpl_image *flat = NULL;
00212 cpl_image *master_flat = NULL;
00213 cpl_image *smo_flat = NULL;
00214 cpl_image *norm_flat = NULL;
00215 cpl_image *spectra = NULL;
00216 cpl_image *wavemap = NULL;
00217 cpl_image *delta = NULL;
00218 cpl_image *residual = NULL;
00219 cpl_image *checkwave = NULL;
00220 cpl_image *rectified = NULL;
00221 cpl_image *dummy = NULL;
00222 cpl_image *refimage = NULL;
00223 cpl_image *coordinate = NULL;
00224 cpl_image *rainbow = NULL;
00225 cpl_image *spatial = NULL;
00226
00227 cpl_mask *refmask = NULL;
00228
00229 cpl_table *grism_table = NULL;
00230 cpl_table *overscans = NULL;
00231 cpl_table *wavelengths = NULL;
00232 cpl_table *idscoeff = NULL;
00233 cpl_table *restable = NULL;
00234 cpl_table *slits = NULL;
00235 cpl_table *positions = NULL;
00236 cpl_table *maskslits = NULL;
00237 cpl_table *traces = NULL;
00238 cpl_table *polytraces = NULL;
00239 cpl_table *restab = NULL;
00240 cpl_table *global = NULL;
00241
00242 cpl_vector *lines = NULL;
00243
00244 cpl_propertylist *header = NULL;
00245 cpl_propertylist *save_header = NULL;
00246 cpl_propertylist *qclist = NULL;
00247
00248
00249
00250
00251
00252 cpl_table *idscoeff_lss = NULL;
00253 char version[80];
00254 const char *arc_tag;
00255 const char *flat_tag;
00256 const char *master_screen_flat_tag;
00257 const char *master_norm_flat_tag;
00258 const char *reduced_lamp_tag;
00259 const char *disp_residuals_tag;
00260 const char *disp_coeff_tag;
00261 const char *wavelength_map_tag;
00262 const char *spectra_detection_tag;
00263 const char *spectral_resolution_tag;
00264 const char *slit_map_tag;
00265 const char *curv_traces_tag;
00266 const char *curv_coeff_tag;
00267 const char *spatial_map_tag;
00268 const char *slit_location_tag;
00269 const char *global_distortion_tag = "GLOBAL_DISTORTION_TABLE";
00270 const char *disp_residuals_table_tag;
00271 const char *delta_image_tag;
00272 const char *key_gris_name;
00273 const char *key_gris_id;
00274 const char *key_filt_name;
00275 const char *key_filt_id;
00276 const char *key_mask_id;
00277 char *keyname;
00278 int quadrant;
00279 int mos;
00280 int treat_as_lss = 0;
00281 int nslits;
00282 double *xpos;
00283 double mxpos;
00284 double mean_rms;
00285 double alltime, arctime;
00286 int nflats;
00287 int nbias;
00288 int nlines;
00289 double *line;
00290 double *fiterror = NULL;
00291 int *fitlines = NULL;
00292 int nx, ny;
00293 double gain;
00294 int ccd_xsize, ccd_ysize;
00295 int rotate = 1;
00296 int rotate_back = -1;
00297 int i;
00298
00299 char *instrume = NULL;
00300 char *pipefile = NULL;
00301 char *grism;
00302
00303
00304 snprintf(version, 80, "%s-%s", PACKAGE, PACKAGE_VERSION);
00305
00306 cpl_msg_set_indentation(2);
00307
00308 if (dfs_files_dont_exist(frameset))
00309 vimos_calib_exit(NULL);
00310
00311
00312
00313
00314
00315
00316 cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
00317 cpl_msg_indent_more();
00318
00319 if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1)
00320 vimos_calib_exit("Too many in input: GRISM_TABLE");
00321
00322 grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
00323
00324 dispersion = dfs_get_parameter_double(parlist,
00325 "fors.vimos_calib.dispersion", grism_table);
00326
00327 if (dispersion <= 0.0)
00328 vimos_calib_exit("Invalid spectral dispersion value");
00329
00330 peakdetection = dfs_get_parameter_double(parlist,
00331 "fors.vimos_calib.peakdetection", grism_table);
00332 if (peakdetection <= 0.0)
00333 vimos_calib_exit("Invalid peak detection level");
00334
00335 wdegree = dfs_get_parameter_int(parlist,
00336 "fors.vimos_calib.wdegree", grism_table);
00337
00338 if (wdegree < 1)
00339 vimos_calib_exit("Invalid polynomial degree");
00340
00341 if (wdegree > 5)
00342 vimos_calib_exit("Max allowed polynomial degree is 5");
00343
00344 wradius = dfs_get_parameter_int(parlist, "fors.vimos_calib.wradius", NULL);
00345
00346 if (wradius < 0)
00347 vimos_calib_exit("Invalid search radius");
00348
00349 wreject = dfs_get_parameter_double(parlist,
00350 "fors.vimos_calib.wreject", NULL);
00351
00352 if (wreject <= 0.0)
00353 vimos_calib_exit("Invalid rejection threshold");
00354
00355 wmode = dfs_get_parameter_int(parlist, "fors.vimos_calib.wmode", NULL);
00356
00357 if (wmode < 0 || wmode > 2)
00358 vimos_calib_exit("Invalid wavelength solution interpolation mode");
00359
00360 wcolumn = dfs_get_parameter_string(parlist,
00361 "fors.vimos_calib.wcolumn", NULL);
00362
00363 cdegree = dfs_get_parameter_int(parlist,
00364 "fors.vimos_calib.cdegree", grism_table);
00365
00366 if (cdegree < 1)
00367 vimos_calib_exit("Invalid polynomial degree");
00368
00369 if (cdegree > 5)
00370 vimos_calib_exit("Max allowed polynomial degree is 5");
00371
00372 cmode = dfs_get_parameter_int(parlist, "fors.vimos_calib.cmode", NULL);
00373
00374 if (cmode < 0 || cmode > 2)
00375 vimos_calib_exit("Invalid curvature solution interpolation mode");
00376
00377 startwavelength = dfs_get_parameter_double(parlist,
00378 "fors.vimos_calib.startwavelength", grism_table);
00379 if (startwavelength > 1.0)
00380 if (startwavelength < 3000.0 || startwavelength > 13000.0)
00381 vimos_calib_exit("Invalid wavelength");
00382
00383 endwavelength = dfs_get_parameter_double(parlist,
00384 "fors.vimos_calib.endwavelength", grism_table);
00385 if (endwavelength > 1.0) {
00386 if (endwavelength < 3000.0 || endwavelength > 13000.0)
00387 vimos_calib_exit("Invalid wavelength");
00388 if (startwavelength < 1.0)
00389 vimos_calib_exit("Invalid wavelength interval");
00390 }
00391
00392 if (startwavelength > 1.0)
00393 if (endwavelength - startwavelength <= 0.0)
00394 vimos_calib_exit("Invalid wavelength interval");
00395
00396 reference = dfs_get_parameter_double(parlist,
00397 "fors.vimos_calib.reference", grism_table);
00398
00399 if (reference < startwavelength || reference > endwavelength)
00400 vimos_calib_exit("Invalid reference wavelength");
00401
00402 slit_ident = dfs_get_parameter_bool(parlist,
00403 "fors.vimos_calib.slit_ident", NULL);
00404
00405 sdegree = dfs_get_parameter_int(parlist, "fors.vimos_calib.sdegree", NULL);
00406 ddegree = dfs_get_parameter_int(parlist, "fors.vimos_calib.ddegree", NULL);
00407 sradius = dfs_get_parameter_int(parlist, "fors.vimos_calib.sradius", NULL);
00408 dradius = dfs_get_parameter_int(parlist, "fors.vimos_calib.dradius", NULL);
00409
00410 if (sradius < 1 || dradius < 1)
00411 vimos_calib_exit("Invalid smoothing box radius");
00412
00413 qc = dfs_get_parameter_bool(parlist, "fors.vimos_calib.qc", NULL);
00414
00415 check = dfs_get_parameter_bool(parlist, "fors.vimos_calib.check", NULL);
00416
00417 cpl_table_delete(grism_table); grism_table = NULL;
00418
00419 if (cpl_error_get_code())
00420 vimos_calib_exit("Failure getting the configuration parameters");
00421
00422
00423
00424
00425
00426
00427 cpl_msg_indent_less();
00428 cpl_msg_info(recipe, "Check input set-of-frames:");
00429 cpl_msg_indent_more();
00430
00431 if (!dfs_equal_keyword(frameset, "ESO OCS CON QUAD"))
00432 vimos_calib_exit("Input frames are not from the same quadrant");
00433
00434 mos = cpl_frameset_count_tags(frameset, "MOS_ARC_SPECTRUM");
00435
00436 if (mos == 0)
00437 vimos_calib_exit("Missing input arc lamp frame");
00438
00439 if (mos > 1)
00440 vimos_calib_exit("Just one input arc lamp frame is allowed");
00441
00442 arc_tag = "MOS_ARC_SPECTRUM";
00443 flat_tag = "MOS_SCREEN_FLAT";
00444 master_screen_flat_tag = "MOS_COMBINED_SCREEN_FLAT";
00445 master_norm_flat_tag = "MOS_MASTER_SCREEN_FLAT";
00446 reduced_lamp_tag = "MOS_ARC_SPECTRUM_EXTRACTED";
00447 disp_residuals_tag = "MOS_DISP_RESIDUALS";
00448 disp_coeff_tag = "MOS_DISP_COEFF";
00449 wavelength_map_tag = "MOS_WAVELENGTH_MAP";
00450 spectra_detection_tag = "MOS_SPECTRA_DETECTION";
00451 spectral_resolution_tag = "MOS_SPECTRAL_RESOLUTION";
00452 slit_map_tag = "MOS_SLIT_MAP";
00453 curv_traces_tag = "MOS_CURV_TRACES";
00454 curv_coeff_tag = "MOS_CURV_COEFF";
00455 spatial_map_tag = "MOS_SPATIAL_MAP";
00456 slit_location_tag = "MOS_SLIT_LOCATION";
00457 disp_residuals_table_tag = "MOS_DISP_RESIDUALS_TABLE";
00458 delta_image_tag = "MOS_DELTA_IMAGE";
00459
00460 nbias = 0;
00461 if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") == 0) {
00462 if (cpl_frameset_count_tags(frameset, "BIAS") == 0)
00463 vimos_calib_exit("Missing required input: MASTER_BIAS or BIAS");
00464 nbias = cpl_frameset_count_tags(frameset, "BIAS");
00465 }
00466
00467 if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") > 1)
00468 vimos_calib_exit("Too many in input: MASTER_BIAS");
00469
00470 if (cpl_frameset_count_tags(frameset, "LINE_CATALOG") == 0)
00471 vimos_calib_exit("Missing required input: LINE_CATALOG");
00472
00473 if (cpl_frameset_count_tags(frameset, "LINE_CATALOG") > 1)
00474 vimos_calib_exit("Too many in input: LINE_CATALOG");
00475
00476 nflats = cpl_frameset_count_tags(frameset, flat_tag);
00477
00478 if (nflats < 1) {
00479 cpl_msg_error(recipe, "Missing required input: %s", flat_tag);
00480 vimos_calib_exit(NULL);
00481 }
00482
00483 cpl_msg_indent_less();
00484
00485 if (nflats > 1)
00486 cpl_msg_info(recipe, "Load %d flat field frames and sum them...",
00487 nflats);
00488 else
00489 cpl_msg_info(recipe, "Load flat field exposure...");
00490
00491 cpl_msg_indent_more();
00492
00493 header = dfs_load_header(frameset, flat_tag, 0);
00494
00495 if (header == NULL)
00496 vimos_calib_exit("Cannot load flat field frame header");
00497
00498 alltime = cpl_propertylist_get_double(header, "EXPTIME");
00499
00500 if (cpl_error_get_code() != CPL_ERROR_NONE)
00501 vimos_calib_exit("Missing keyword EXPTIME in flat field frame header");
00502
00503 cpl_propertylist_delete(header);
00504
00505 for (i = 1; i < nflats; i++) {
00506
00507 header = dfs_load_header(frameset, NULL, 0);
00508
00509 if (header == NULL)
00510 vimos_calib_exit("Cannot load flat field frame header");
00511
00512 alltime += cpl_propertylist_get_double(header, "EXPTIME");
00513
00514 if (cpl_error_get_code() != CPL_ERROR_NONE)
00515 vimos_calib_exit("Missing keyword EXPTIME in flat field "
00516 "frame header");
00517
00518 cpl_propertylist_delete(header);
00519
00520 }
00521
00522 master_flat = dfs_load_image(frameset, flat_tag, CPL_TYPE_FLOAT, 0, 0);
00523
00524 if (master_flat == NULL)
00525 vimos_calib_exit("Cannot load flat field");
00526
00527 for (i = 1; i < nflats; i++) {
00528 flat = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0);
00529 if (flat) {
00530 cpl_image_add(master_flat, flat);
00531 cpl_image_delete(flat); flat = NULL;
00532 }
00533 else
00534 vimos_calib_exit("Cannot load flat field");
00535 }
00536
00537
00538
00539
00540
00541
00542 header = dfs_load_header(frameset, arc_tag, 0);
00543
00544 if (header == NULL)
00545 vimos_calib_exit("Cannot load arc lamp header");
00546
00547 instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
00548 if (instrume == NULL)
00549 vimos_calib_exit("Missing keyword INSTRUME in arc lamp header");
00550 instrume = cpl_strdup(instrume);
00551
00552 arctime = cpl_propertylist_get_double(header, "EXPTIME");
00553
00554 quadrant = cpl_propertylist_get_int(header, "ESO OCS CON QUAD");
00555
00556 switch (quadrant) {
00557 case 1:
00558 key_gris_name = "ESO INS GRIS1 NAME";
00559 key_gris_id = "ESO INS GRIS1 ID";
00560 key_filt_name = "ESO INS FILT1 NAME";
00561 key_filt_id = "ESO INS FILT1 ID";
00562 key_mask_id = "ESO INS MASK1 ID";
00563 break;
00564 case 2:
00565 key_gris_name = "ESO INS GRIS2 NAME";
00566 key_gris_id = "ESO INS GRIS2 ID";
00567 key_filt_name = "ESO INS FILT2 NAME";
00568 key_filt_id = "ESO INS FILT2 ID";
00569 key_mask_id = "ESO INS MASK2 ID";
00570 break;
00571 case 3:
00572 key_gris_name = "ESO INS GRIS3 NAME";
00573 key_gris_id = "ESO INS GRIS3 ID";
00574 key_filt_name = "ESO INS FILT3 NAME";
00575 key_filt_id = "ESO INS FILT3 ID";
00576 key_mask_id = "ESO INS MASK3 ID";
00577 break;
00578 case 4:
00579 key_gris_name = "ESO INS GRIS4 NAME";
00580 key_gris_id = "ESO INS GRIS4 ID";
00581 key_filt_name = "ESO INS FILT4 NAME";
00582 key_filt_id = "ESO INS FILT4 ID";
00583 key_mask_id = "ESO INS MASK4 ID";
00584 break;
00585 }
00586
00587 grism = cpl_strdup(cpl_propertylist_get_string(header, key_gris_name));
00588
00589 if (cpl_error_get_code() != CPL_ERROR_NONE)
00590 vimos_calib_exit("Missing keyword ESO INS GRISn NAME in arc lamp "
00591 "frame header");
00592
00593 cpl_msg_info(recipe, "The grism is: %s", grism);
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD");
00604
00605 if (cpl_error_get_code() != CPL_ERROR_NONE)
00606 vimos_calib_exit("Missing keyword ESO DET OUT1 CONAD in arc lamp "
00607 "frame header");
00608
00609 cpl_msg_info(recipe, "The gain factor is: %.2f e-/ADU", gain);
00610
00611 cpl_msg_info(recipe, "Produce mask slit position table...");
00612
00613 maskslits = mos_load_slits_vimos(header);
00614
00615
00616
00617
00618
00619
00620 mxpos = cpl_table_get_column_median(maskslits, "ytop");
00621 xpos = cpl_table_get_data_double(maskslits, "ytop");
00622 nslits = cpl_table_get_nrow(maskslits);
00623
00624 treat_as_lss = 1;
00625 for (i = 0; i < nslits; i++) {
00626 if (fabs(mxpos-xpos[i]) > 0.01) {
00627 treat_as_lss = 0;
00628 break;
00629 }
00630 }
00631
00632 if (treat_as_lss) {
00633 cpl_msg_warning(recipe, "All MOS slits have the same offset: %.2f\n"
00634 "The long-slit data reduction strategy is applied!",
00635 mxpos);
00636 cpl_table_delete(maskslits); maskslits = NULL;
00637 }
00638
00639 if (slit_ident == 0) {
00640 cpl_table_delete(maskslits); maskslits = NULL;
00641 }
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 if (nbias) {
00652
00653
00654
00655
00656
00657 cpl_msg_info(recipe, "Generate the master from input raw biases...");
00658
00659 if (nbias > 1) {
00660
00661 biases = cpl_imagelist_new();
00662
00663 bias = dfs_load_image(frameset, "BIAS", CPL_TYPE_FLOAT, 0, 0);
00664
00665 if (bias == NULL)
00666 vimos_calib_exit("Cannot load bias frame");
00667
00668 cpl_imagelist_set(biases, bias, 0); bias = NULL;
00669
00670 for (i = 1; i < nbias; i++) {
00671 bias = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0);
00672 if (bias) {
00673 cpl_imagelist_set(biases, bias, i); bias = NULL;
00674 }
00675 else
00676 vimos_calib_exit("Cannot load bias frame");
00677 }
00678
00679 master_bias = cpl_imagelist_collapse_median_create(biases);
00680
00681 cpl_imagelist_delete(biases);
00682 }
00683 else
00684 master_bias = dfs_load_image(frameset, "BIAS",
00685 CPL_TYPE_FLOAT, 0, 1);
00686
00687 }
00688 else {
00689 master_bias = dfs_load_image(frameset, "MASTER_BIAS",
00690 CPL_TYPE_FLOAT, 0, 1);
00691 if (master_bias == NULL)
00692 vimos_calib_exit("Cannot load master bias");
00693 }
00694
00695 cpl_msg_info(recipe, "Remove the master bias...");
00696
00697 overscans = mos_load_overscans_vimos(header, 1);
00698 cpl_propertylist_delete(header); header = NULL;
00699
00700 if (nbias) {
00701 int xlow = cpl_table_get_int(overscans, "xlow", 0, NULL);
00702 int ylow = cpl_table_get_int(overscans, "ylow", 0, NULL);
00703 int xhig = cpl_table_get_int(overscans, "xhig", 0, NULL);
00704 int yhig = cpl_table_get_int(overscans, "yhig", 0, NULL);
00705 dummy = cpl_image_extract(master_bias, xlow+1, ylow+1, xhig, yhig);
00706 cpl_image_delete(master_bias); master_bias = dummy;
00707
00708 if (dfs_save_image(frameset, master_bias, "MASTER_BIAS",
00709 NULL, parlist, recipe, version))
00710 vimos_calib_exit(NULL);
00711 }
00712
00713 if (nflats > 1) {
00714 multi_bias = cpl_image_multiply_scalar_create(master_bias, nflats);
00715 dummy = mos_remove_bias(master_flat, multi_bias, overscans);
00716 cpl_image_delete(multi_bias);
00717 }
00718 else {
00719 dummy = mos_remove_bias(master_flat, master_bias, overscans);
00720 }
00721 cpl_image_delete(master_flat);
00722 master_flat = dummy;
00723
00724 if (master_flat == NULL)
00725 vimos_calib_exit("Cannot remove bias from flat field");
00726
00727 cpl_msg_indent_less();
00728 cpl_msg_info(recipe, "Load arc lamp exposure...");
00729 cpl_msg_indent_more();
00730
00731 spectra = dfs_load_image(frameset, arc_tag, CPL_TYPE_FLOAT, 0, 0);
00732
00733 if (spectra == NULL)
00734 vimos_calib_exit("Cannot load arc lamp exposure");
00735
00736 cpl_msg_info(recipe, "Remove the master bias...");
00737
00738 dummy = mos_remove_bias(spectra, master_bias, overscans);
00739 cpl_table_delete(overscans); overscans = NULL;
00740 cpl_image_delete(master_bias); master_bias = NULL;
00741 cpl_image_delete(spectra); spectra = dummy;
00742
00743 if (spectra == NULL)
00744 vimos_calib_exit("Cannot remove bias from arc lamp exposure");
00745
00746 cpl_msg_indent_less();
00747 cpl_msg_info(recipe, "Load input line catalog...");
00748 cpl_msg_indent_more();
00749
00750 wavelengths = dfs_load_table(frameset, "LINE_CATALOG", 1);
00751
00752 if (wavelengths == NULL)
00753 vimos_calib_exit("Cannot load line catalog");
00754
00755
00756
00757
00758
00759
00760 nlines = cpl_table_get_nrow(wavelengths);
00761
00762 if (nlines == 0)
00763 vimos_calib_exit("Empty input line catalog");
00764
00765 if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
00766 cpl_msg_error(recipe, "Missing column %s in input line catalog table",
00767 wcolumn);
00768 vimos_calib_exit(NULL);
00769 }
00770
00771 line = cpl_malloc(nlines * sizeof(double));
00772
00773 for (i = 0; i < nlines; i++)
00774 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
00775
00776 cpl_table_delete(wavelengths); wavelengths = NULL;
00777
00778 lines = cpl_vector_wrap(nlines, line);
00779
00780
00781
00782
00783
00784
00785 cpl_image_turn(spectra, rotate);
00786 cpl_image_turn(master_flat, rotate);
00787
00788 ccd_xsize = nx = cpl_image_get_size_x(spectra);
00789 ccd_ysize = ny = cpl_image_get_size_y(spectra);
00790
00791 if (treat_as_lss) {
00792
00793
00794
00795
00796
00797
00798
00799 cpl_msg_indent_less();
00800 cpl_msg_info(recipe, "Perform wavelength calibration...");
00801 cpl_msg_indent_more();
00802
00803 wavemap = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00804 if (check)
00805 residual = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00806
00807 fiterror = cpl_calloc(ny, sizeof(double));
00808 fitlines = cpl_calloc(ny, sizeof(int));
00809 idscoeff = cpl_table_new(ny);
00810 refmask = cpl_mask_new(nx, ny);
00811
00812 if (mos_saturation_process(spectra))
00813 vimos_calib_exit("Cannot process saturation");
00814
00815 if (mos_subtract_background(spectra))
00816 vimos_calib_exit("Cannot subtract the background");
00817
00818 rectified = mos_wavelength_calibration_raw(spectra, lines, dispersion,
00819 peakdetection, wradius,
00820 wdegree, wreject, reference,
00821 &startwavelength,
00822 &endwavelength, fitlines,
00823 fiterror, idscoeff, wavemap,
00824 residual, NULL, refmask);
00825
00826 if (rectified == NULL)
00827 vimos_calib_exit("Wavelength calibration failure.");
00828
00829 if (!cpl_table_has_valid(idscoeff, "c0"))
00830 vimos_calib_exit("Wavelength calibration failure.");
00831
00832
00833
00834
00835
00836 mos_refmask_find_gaps(refmask, master_flat, 1000.);
00837
00838 if (wmode) {
00839 cpl_image_delete(rectified); rectified = NULL;
00840 cpl_image_delete(wavemap); wavemap = NULL;
00841 mos_interpolate_wavecalib(idscoeff, wavemap, wmode);
00842 wavemap = mos_map_idscoeff(idscoeff, nx, reference,
00843 startwavelength, endwavelength);
00844 rectified = mos_wavelength_calibration(spectra, reference,
00845 startwavelength,
00846 endwavelength, dispersion,
00847 idscoeff, 0);
00848 }
00849
00850 cpl_table_wrap_double(idscoeff, fiterror, "error"); fiterror = NULL;
00851 cpl_table_set_column_unit(idscoeff, "error", "pixel");
00852 cpl_table_wrap_int(idscoeff, fitlines, "nlines"); fitlines = NULL;
00853
00854 for (i = 0; i < ny; i++)
00855 if (!cpl_table_is_valid(idscoeff, "c0", i))
00856 cpl_table_set_invalid(idscoeff, "error", i);
00857
00858 slit_ident = 0;
00859 idscoeff_lss = idscoeff;
00860
00861 }
00862 else {
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 cpl_msg_indent_less();
00873 cpl_msg_info(recipe, "Detecting spectra on CCD...");
00874 cpl_msg_indent_more();
00875
00876 ccd_xsize = nx = cpl_image_get_size_x(spectra);
00877 ccd_ysize = ny = cpl_image_get_size_y(spectra);
00878
00879 refmask = cpl_mask_new(nx, ny);
00880
00881 if (mos_saturation_process(spectra))
00882 vimos_calib_exit("Cannot process saturation");
00883
00884 if (mos_subtract_background(spectra))
00885 vimos_calib_exit("Cannot subtract the background");
00886
00887 checkwave = mos_wavelength_calibration_raw(spectra, lines, dispersion,
00888 peakdetection, wradius,
00889 wdegree, wreject, reference,
00890 &startwavelength,
00891 &endwavelength,
00892 NULL, NULL, NULL, NULL,
00893 NULL, NULL, refmask);
00894
00895 if (checkwave == NULL)
00896 vimos_calib_exit("Wavelength calibration failure.");
00897
00898
00899
00900
00901
00902 header = cpl_propertylist_new();
00903 cpl_propertylist_update_double(header, "CRPIX1", 1.0);
00904 cpl_propertylist_update_double(header, "CRPIX2", 1.0);
00905 cpl_propertylist_update_double(header, "CRVAL1",
00906 startwavelength + dispersion/2);
00907 cpl_propertylist_update_double(header, "CRVAL2", 1.0);
00908
00909
00910 cpl_propertylist_update_double(header, "CD1_1", dispersion);
00911 cpl_propertylist_update_double(header, "CD1_2", 0.0);
00912 cpl_propertylist_update_double(header, "CD2_1", 0.0);
00913 cpl_propertylist_update_double(header, "CD2_2", 1.0);
00914 cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
00915 cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
00916
00917 if (check) {
00918 if (dfs_save_image(frameset, checkwave, spectra_detection_tag,
00919 header, parlist, recipe, version))
00920 vimos_calib_exit(NULL);
00921 }
00922
00923 cpl_image_delete(checkwave); checkwave = NULL;
00924 cpl_propertylist_delete(header); header = NULL;
00925
00926 }
00927
00928 cpl_msg_info(recipe, "Locate slits at reference wavelength on CCD...");
00929 slits = mos_locate_spectra(refmask);
00930
00931 if (!slits) {
00932 cpl_msg_error(cpl_error_get_where(), cpl_error_get_message());
00933 vimos_calib_exit("No slits could be detected!");
00934 }
00935
00936 refimage = cpl_image_new_from_mask(refmask);
00937 cpl_mask_delete(refmask); refmask = NULL;
00938
00939 if (check) {
00940 save_header = dfs_load_header(frameset, arc_tag, 0);
00941 cpl_image_turn(refimage, rotate_back);
00942 if (dfs_save_image(frameset, refimage, slit_map_tag, NULL,
00943 parlist, recipe, version))
00944 vimos_calib_exit(NULL);
00945 cpl_propertylist_delete(save_header); save_header = NULL;
00946 }
00947
00948 cpl_image_delete(refimage); refimage = NULL;
00949
00950 if (slit_ident) {
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 cpl_msg_indent_less();
00967 cpl_msg_info(recipe, "Attempt slit identification (optional)...");
00968 cpl_msg_indent_more();
00969
00970 mos_rotate_slits(maskslits, -rotate, 0, 0);
00971 positions = mos_identify_slits(slits, maskslits, NULL);
00972
00973 if (positions) {
00974 cpl_table_delete(slits);
00975 slits = positions;
00976
00977
00978
00979
00980
00981 cpl_table_and_selected_double(slits,
00982 "ybottom", CPL_GREATER_THAN, ny-1);
00983 cpl_table_or_selected_double(slits,
00984 "ytop", CPL_LESS_THAN, 0);
00985 cpl_table_erase_selected(slits);
00986
00987 nslits = cpl_table_get_nrow(slits);
00988
00989 if (nslits == 0)
00990 vimos_calib_exit("No slits found on the CCD");
00991
00992 cpl_msg_info(recipe, "%d slits are entirely or partially "
00993 "contained in CCD", nslits);
00994
00995 }
00996 else {
00997 slit_ident = 0;
00998 cpl_msg_info(recipe, "Global distortion model cannot be computed");
00999 if (cpl_error_get_code() != CPL_ERROR_NONE) {
01000 vimos_calib_exit(NULL);
01001 }
01002 }
01003 }
01004
01005
01006
01007
01008
01009
01010 cpl_msg_indent_less();
01011 cpl_msg_info(recipe, "Determining spectral curvature...");
01012 cpl_msg_indent_more();
01013
01014 cpl_msg_info(recipe, "Tracing master flat field spectra edges...");
01015 traces = mos_trace_flat(master_flat, slits, reference,
01016 startwavelength, endwavelength, dispersion);
01017
01018 if (!traces)
01019 vimos_calib_exit("Tracing failure");
01020
01021 cpl_msg_info(recipe, "Fitting flat field spectra edges...");
01022 polytraces = mos_poly_trace(slits, traces, cdegree);
01023
01024 if (!polytraces)
01025 vimos_calib_exit("Trace fitting failure");
01026
01027 if (cmode) {
01028 cpl_msg_info(recipe, "Computing global spectral curvature model...");
01029 mos_global_trace(slits, polytraces, cmode);
01030 }
01031
01032 if (dfs_save_table(frameset, traces, curv_traces_tag, NULL, parlist,
01033 recipe, version))
01034 vimos_calib_exit(NULL);
01035
01036 cpl_table_delete(traces); traces = NULL;
01037
01038 coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01039 spatial = mos_spatial_calibration(spectra, slits, polytraces, reference,
01040 startwavelength, endwavelength,
01041 dispersion, 0, coordinate);
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053 cpl_msg_indent_less();
01054 cpl_msg_info(recipe, "Perform flat field normalisation...");
01055 cpl_msg_indent_more();
01056
01057 norm_flat = cpl_image_duplicate(master_flat);
01058
01059 smo_flat = mos_normalise_flat(norm_flat, coordinate, slits, polytraces,
01060 reference, startwavelength, endwavelength,
01061 dispersion, dradius, ddegree);
01062
01063 cpl_image_delete(smo_flat); smo_flat = NULL;
01064
01065 save_header = dfs_load_header(frameset, flat_tag, 0);
01066 cpl_propertylist_update_int(save_header, "ESO PRO DATANCOM", nflats);
01067
01068 cpl_image_turn(norm_flat, rotate_back);
01069
01070 if (dfs_save_image(frameset, norm_flat, master_norm_flat_tag,
01071 save_header, parlist, recipe, version))
01072 vimos_calib_exit(NULL);
01073
01074 cpl_image_delete(norm_flat); norm_flat = NULL;
01075
01076
01077
01078
01079
01080
01081 if (qc) {
01082 double scale;
01083 double slit_width;
01084 double flux, flux_err;
01085 int cslit = mos_slit_closest_to_center(slits, nx, ny);
01086
01087
01088
01089
01090
01091
01092
01093 cpl_propertylist_delete(save_header);
01094 save_header = dfs_load_header(frameset, flat_tag, 0);
01095 cpl_propertylist_update_int(save_header, "ESO PRO DATANCOM", nflats);
01096
01097
01098
01099
01100
01101
01102 fors_qc_start_group(save_header, "1.1", instrume);
01103
01104 if (fors_qc_write_string("PRO.CATG", master_norm_flat_tag,
01105 "Product category", instrume))
01106 vimos_calib_exit("Cannot write product category to QC log file");
01107
01108 if (fors_qc_keyword_to_paf(save_header, "ARCFILE", NULL,
01109 "Archive File Name", instrume))
01110 vimos_calib_exit("Missing keyword ARCFILE in flatfield frame");
01111
01112 if (fors_qc_keyword_to_paf(save_header, "ESO TPL ID", NULL,
01113 "Template signature ID", instrume))
01114 vimos_calib_exit("Missing keyword TPL ID in flatfield frame");
01115
01116 if (fors_qc_keyword_to_paf(save_header, "ESO OCS CON QUAD", NULL,
01117 "Quadrant", instrume))
01118 vimos_calib_exit("Missing keyword OCS CON QUAD in flatfield frame");
01119
01120 if (fors_qc_keyword_to_paf(save_header, key_filt_name, NULL,
01121 "Filter", instrume)) {
01122 cpl_msg_error(recipe, "Missing keyword %s in flatfield frame",
01123 key_filt_name);
01124 vimos_calib_exit(NULL);
01125 }
01126
01127 if (fors_qc_keyword_to_paf(save_header, key_gris_name, NULL,
01128 "Grism", instrume)) {
01129 cpl_msg_error(recipe, "Missing keyword %s in flatfield frame",
01130 key_gris_name);
01131 vimos_calib_exit(NULL);
01132 }
01133
01134 if (fors_qc_keyword_to_paf(save_header, key_mask_id, NULL,
01135 "Mask", instrume)) {
01136 cpl_msg_error(recipe, "Missing keyword %s in flatfield frame",
01137 key_mask_id);
01138 vimos_calib_exit(NULL);
01139 }
01140
01141 cpl_propertylist_update_double(save_header,
01142 "ESO PRO WLEN CEN", reference);
01143
01144 if (fors_qc_keyword_to_paf(save_header, "ESO PRO WLEN CEN", "Angstrom",
01145 "Reference wavelength", instrume))
01146 vimos_calib_exit("Missing keyword PRO WLEN CEN in flatfield frame");
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171 pipefile = dfs_generate_filename_tfits(master_norm_flat_tag);
01172 if (fors_qc_write_string("PIPEFILE", pipefile,
01173 "Pipeline product name", instrume))
01174 vimos_calib_exit("Cannot write PIPEFILE to QC log file");
01175 cpl_free(pipefile); pipefile = NULL;
01176
01177 scale = cpl_propertylist_get_double(save_header, "ESO TEL FOCU SCALE");
01178
01179 if (cpl_error_get_code()) {
01180 cpl_error_reset();
01181 scale = 1.718;
01182 cpl_msg_warning(recipe, "Cannot read keyword TEL FOCU SCALE "
01183 "(defaulted to %f arcsec/mm)", scale);
01184 }
01185
01186
01187
01188
01189
01190 keyname = "QC.MOS.SLIT.WIDTH";
01191
01192 slit_width = scale * cpl_table_get(slits, "ywidth", cslit, NULL);
01193
01194 if (fors_qc_write_qc_double(save_header, slit_width, keyname, "arcsec",
01195 "Width of slit closest to center",
01196 instrume)) {
01197 vimos_calib_exit("Cannot write slit width to QC log file");
01198 }
01199
01200 mos_extract_flux(master_flat, slits, 2, gain, &flux, &flux_err);
01201
01202 flux_err /= alltime;
01203 flux /= alltime;
01204
01205 cpl_msg_info(recipe,
01206 "Flux at wavelength %.2f: %.2f +/- %.2f ADU/mm^2/s\n",
01207 reference, flux, flux_err);
01208
01209 keyname = "QC.MOS.FLAT.FLUX";
01210
01211 if (fors_qc_write_qc_double(save_header, flux, keyname, "ADU/mm^2/s",
01212 "Flux at reference wavelength",
01213 instrume)) {
01214 vimos_calib_exit("Cannot write QC.MOS.FLAT.FLUX to QC log file");
01215 }
01216
01217 keyname = "QC.MOS.FLAT.FLUXERR";
01218
01219 if (fors_qc_write_qc_double(save_header, flux_err, keyname,
01220 "ADU/mm^2/s",
01221 "Error on flux at reference wavelength",
01222 instrume)) {
01223 vimos_calib_exit("Cannot write QC.MOS.FLAT.FLUXERR to QC log file");
01224 }
01225
01226 fors_qc_end_group();
01227
01228 }
01229
01230 cpl_image_turn(master_flat, rotate_back);
01231 if (dfs_save_image(frameset, master_flat, master_screen_flat_tag,
01232 save_header, parlist, recipe, version))
01233 vimos_calib_exit(NULL);
01234
01235 cpl_image_delete(master_flat); master_flat = NULL;
01236
01237 cpl_propertylist_delete(save_header); save_header = NULL;
01238
01239
01240
01241
01242
01243
01244
01245 cpl_msg_indent_less();
01246 cpl_msg_info(recipe, "Perform final wavelength calibration...");
01247 cpl_msg_indent_more();
01248
01249 nx = cpl_image_get_size_x(spatial);
01250 ny = cpl_image_get_size_y(spatial);
01251
01252 idscoeff = cpl_table_new(ny);
01253 restable = cpl_table_new(nlines);
01254 rainbow = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01255 if (check)
01256 residual = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01257 fiterror = cpl_calloc(ny, sizeof(double));
01258 fitlines = cpl_calloc(ny, sizeof(int));
01259
01260 rectified = mos_wavelength_calibration_final(spatial, slits, lines,
01261 dispersion, peakdetection,
01262 wradius, wdegree, wreject,
01263 reference, &startwavelength,
01264 &endwavelength, fitlines,
01265 fiterror, idscoeff, rainbow,
01266 residual, restable);
01267
01268 if (rectified == NULL)
01269 vimos_calib_exit("Wavelength calibration failure.");
01270
01271 if (dfs_save_table(frameset, restable, disp_residuals_table_tag, NULL,
01272 parlist, recipe, version))
01273 vimos_calib_exit(NULL);
01274
01275 cpl_table_delete(restable); restable = NULL;
01276
01277 cpl_table_wrap_double(idscoeff, fiterror, "error"); fiterror = NULL;
01278 cpl_table_set_column_unit(idscoeff, "error", "pixel");
01279 cpl_table_wrap_int(idscoeff, fitlines, "nlines"); fitlines = NULL;
01280
01281 if (treat_as_lss) {
01282
01283 const char *clab[6] = {"c0", "c1", "c2", "c3", "c4", "c5"};
01284
01285 int *position = cpl_table_get_data_int (slits, "position");
01286 int *length = cpl_table_get_data_int (slits, "length");
01287 double *ytop = cpl_table_get_data_double(slits, "ytop");
01288 double *ybottom = cpl_table_get_data_double(slits, "ybottom");
01289
01290 int j, k, dr, irow;
01291
01292
01293
01294
01295
01296 for (j = 0, i = ny - 1; i >= 0; i--) {
01297 if (i < position[j]) {
01298 ++j;
01299 }
01300 dr = position[j] + length[j] - i - 1;
01301 irow = floor(ytop[j] - dr*(ytop[j] - ybottom[j])/length[j] + 0.5);
01302 for (k = 0; k <= wdegree; k++) {
01303 cpl_table_set_double(idscoeff, clab[k], i,
01304 cpl_table_get_double(idscoeff_lss, clab[k], irow, NULL));
01305 }
01306 cpl_table_set_double(idscoeff, "error", i,
01307 cpl_table_get_double(idscoeff_lss, "error", irow, NULL));
01308 cpl_table_set_int(idscoeff, "nlines", i,
01309 cpl_table_get_int(idscoeff_lss, "nlines", irow, NULL));
01310 }
01311
01312 cpl_table_delete(idscoeff_lss);
01313
01314 cpl_image_delete(rectified);
01315
01316 rectified = mos_wavelength_calibration(spatial, reference,
01317 startwavelength, endwavelength,
01318 dispersion, idscoeff, 0);
01319 }
01320 else {
01321 for (i = 0; i < ny; i++)
01322 if (!cpl_table_is_valid(idscoeff, "c0", i))
01323 cpl_table_set_invalid(idscoeff, "error", i);
01324 }
01325
01326 cpl_image_delete(spatial); spatial = NULL;
01327
01328 delta = mos_map_pixel(idscoeff, reference, startwavelength,
01329 endwavelength, dispersion, 2);
01330
01331 header = cpl_propertylist_new();
01332 cpl_propertylist_update_double(header, "CRPIX1", 1.0);
01333 cpl_propertylist_update_double(header, "CRPIX2", 1.0);
01334 cpl_propertylist_update_double(header, "CRVAL1",
01335 startwavelength + dispersion/2);
01336 cpl_propertylist_update_double(header, "CRVAL2", 1.0);
01337
01338
01339 cpl_propertylist_update_double(header, "CD1_1", dispersion);
01340 cpl_propertylist_update_double(header, "CD1_2", 0.0);
01341 cpl_propertylist_update_double(header, "CD2_1", 0.0);
01342 cpl_propertylist_update_double(header, "CD2_2", 1.0);
01343 cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
01344 cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
01345
01346 if (dfs_save_image(frameset, delta, delta_image_tag,
01347 header, parlist, recipe, version))
01348 vimos_calib_exit(NULL);
01349
01350 cpl_image_delete(delta); delta = NULL;
01351 cpl_propertylist_delete(header); header = NULL;
01352
01353 mean_rms = mos_distortions_rms(rectified, lines, startwavelength,
01354 dispersion, 6, 0);
01355
01356 cpl_msg_info(recipe, "Mean residual: %f pixel", mean_rms);
01357
01358 mean_rms = cpl_table_get_column_mean(idscoeff, "error");
01359
01360 cpl_msg_info(recipe, "Mean model accuracy: %f pixel (%f A)",
01361 mean_rms, mean_rms * dispersion);
01362
01363 restab = mos_resolution_table(rectified, startwavelength, dispersion,
01364 60000, lines);
01365
01366 if (restab) {
01367 cpl_msg_info(recipe, "Mean spectral resolution: %.2f",
01368 cpl_table_get_column_mean(restab, "resolution"));
01369 cpl_msg_info(recipe, "Mean reference lines FWHM: %.2f +/- %.2f pixel",
01370 cpl_table_get_column_mean(restab, "fwhm") / dispersion,
01371 cpl_table_get_column_mean(restab, "fwhm_rms") / dispersion);
01372
01373 if (qc) {
01374
01375 header = dfs_load_header(frameset, arc_tag, 0);
01376
01377 if (header == NULL)
01378 vimos_calib_exit("Cannot reload arc lamp header");
01379
01380 qclist = cpl_propertylist_new();
01381
01382 fors_qc_start_group(qclist, "1.1", instrume);
01383
01384
01385
01386
01387
01388
01389 if (fors_qc_write_string("PRO.CATG", spectral_resolution_tag,
01390 "Product category", instrume))
01391 vimos_calib_exit("Cannot write product category to "
01392 "QC log file");
01393
01394 if (fors_qc_keyword_to_paf(header, "ESO DPR TYPE", NULL,
01395 "DPR type", instrume))
01396 vimos_calib_exit("Missing keyword DPR TYPE in arc "
01397 "lamp header");
01398
01399 if (fors_qc_keyword_to_paf(header, "ESO TPL ID", NULL,
01400 "Template", instrume))
01401 vimos_calib_exit("Missing keyword TPL ID in arc "
01402 "lamp header");
01403
01404 if (fors_qc_keyword_to_paf(header, key_gris_name, NULL,
01405 "Grism name", instrume)) {
01406 cpl_msg_error(recipe, "Missing keyword %s in arc "
01407 "lamp header", key_gris_name);
01408 vimos_calib_exit(NULL);
01409 }
01410
01411 if (fors_qc_keyword_to_paf(header, key_gris_id, NULL,
01412 "Grism identifier", instrume)) {
01413 cpl_msg_error(recipe, "Missing keyword %s in arc "
01414 "lamp header", key_gris_id);
01415 vimos_calib_exit(NULL);
01416 }
01417
01418 if (cpl_propertylist_has(header, key_filt_name))
01419 fors_qc_keyword_to_paf(header, key_filt_name, NULL,
01420 "Filter name", instrume);
01421
01422 if (fors_qc_keyword_to_paf(header, "ESO DET CHIP1 ID", NULL,
01423 "Chip identifier", instrume))
01424 vimos_calib_exit("Missing keyword DET CHIP1 ID in arc "
01425 "lamp header");
01426
01427 if (fors_qc_keyword_to_paf(header, "ARCFILE", NULL,
01428 "Archive name of input data",
01429 instrume))
01430 vimos_calib_exit("Missing keyword ARCFILE in arc "
01431 "lamp header");
01432
01433 cpl_propertylist_delete(header); header = NULL;
01434
01435 pipefile = dfs_generate_filename_tfits(spectral_resolution_tag);
01436 if (fors_qc_write_string("PIPEFILE", pipefile,
01437 "Pipeline product name", instrume))
01438 vimos_calib_exit("Cannot write PIPEFILE to QC log file");
01439 cpl_free(pipefile); pipefile = NULL;
01440
01441
01442
01443
01444
01445
01446 keyname = "QC.MOS.RESOLUTION";
01447
01448 if (fors_qc_write_qc_double(qclist,
01449 cpl_table_get_column_mean(restab,
01450 "resolution"),
01451 keyname,
01452 "Angstrom",
01453 "Mean spectral resolution",
01454 instrume)) {
01455 vimos_calib_exit("Cannot write mean spectral resolution to QC "
01456 "log file");
01457 }
01458
01459 keyname = "QC.MOS.RESOLUTION.RMS";
01460
01461 if (fors_qc_write_qc_double(qclist,
01462 cpl_table_get_column_stdev(restab,
01463 "resolution"),
01464 "QC.MOS.RESOLUTION.RMS",
01465 "Angstrom",
01466 "Scatter of spectral resolution",
01467 instrume)) {
01468 vimos_calib_exit("Cannot write spectral resolution scatter "
01469 "to QC log file");
01470 }
01471
01472 keyname = "QC.MOS.RESOLUTION.NLINES";
01473
01474 if (fors_qc_write_qc_int(qclist, cpl_table_get_nrow(restab) -
01475 cpl_table_count_invalid(restab,
01476 "resolution"),
01477 "QC.MOS.RESOLUTION.NLINES",
01478 NULL,
01479 "Number of lines for spectral resolution "
01480 "computation",
01481 instrume)) {
01482 vimos_calib_exit("Cannot write number of lines used in "
01483 "spectral resolution computation "
01484 "to QC log file");
01485 }
01486
01487 fors_qc_end_group();
01488
01489 }
01490
01491 if (dfs_save_table(frameset, restab, spectral_resolution_tag, qclist,
01492 parlist, recipe, version))
01493 vimos_calib_exit(NULL);
01494
01495 cpl_propertylist_delete(qclist); qclist = NULL;
01496
01497 }
01498 else
01499 vimos_calib_exit("Cannot compute the spectral resolution table");
01500
01501 cpl_vector_delete(lines); lines = NULL;
01502
01503 if (dfs_save_table(frameset, idscoeff, disp_coeff_tag, NULL,
01504 parlist, recipe, version))
01505 vimos_calib_exit(NULL);
01506
01507
01508
01509
01510
01511 if (slit_ident) {
01512
01513 cpl_msg_info(recipe, "Computing global distortions model");
01514 global = mos_global_distortion(slits, maskslits, idscoeff,
01515 polytraces, reference);
01516
01517 if (global && 0) {
01518 cpl_table *stest;
01519 cpl_table *ctest;
01520 cpl_table *dtest;
01521 cpl_image *itest;
01522
01523 stest = mos_build_slit_location(global, maskslits, ccd_ysize);
01524
01525 ctest = mos_build_curv_coeff(global, maskslits, stest);
01526 if (dfs_save_table(frameset, ctest, "CURVS", NULL,
01527 parlist, recipe, version))
01528 vimos_calib_exit(NULL);
01529
01530 itest = mos_spatial_calibration(spectra, stest, ctest,
01531 reference, startwavelength,
01532 endwavelength, dispersion,
01533 0, NULL);
01534 cpl_table_delete(ctest); ctest = NULL;
01535 cpl_image_delete(itest); itest = NULL;
01536 if (dfs_save_table(frameset, stest, "SLITS", NULL,
01537 parlist, recipe, version))
01538 vimos_calib_exit(NULL);
01539
01540 dtest = mos_build_disp_coeff(global, stest);
01541 if (dfs_save_table(frameset, dtest, "DISPS", NULL,
01542 parlist, recipe, version))
01543 vimos_calib_exit(NULL);
01544
01545 cpl_table_delete(dtest); dtest = NULL;
01546 cpl_table_delete(stest); stest = NULL;
01547 }
01548
01549 if (global) {
01550 if (dfs_save_table(frameset, global, global_distortion_tag, NULL,
01551 parlist, recipe, version))
01552 vimos_calib_exit(NULL);
01553 cpl_table_delete(global); global = NULL;
01554 }
01555
01556
01557 cpl_table_delete(maskslits); maskslits = NULL;
01558 }
01559
01560 header = dfs_load_header(frameset, arc_tag, 0);
01561 cpl_propertylist_update_double(header, "CRPIX1", 1.0);
01562 cpl_propertylist_update_double(header, "CRPIX2", 1.0);
01563 cpl_propertylist_update_double(header, "CRVAL1",
01564 startwavelength + dispersion/2);
01565 cpl_propertylist_update_double(header, "CRVAL2", 1.0);
01566
01567
01568 cpl_propertylist_update_double(header, "CD1_1", dispersion);
01569 cpl_propertylist_update_double(header, "CD1_2", 0.0);
01570 cpl_propertylist_update_double(header, "CD2_1", 0.0);
01571 cpl_propertylist_update_double(header, "CD2_2", 1.0);
01572 cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
01573 cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
01574 cpl_propertylist_update_int(header, "ESO PRO DATANCOM", 1);
01575
01576 if (qc) {
01577
01578 double scale;
01579 double slit_width;
01580 float lambdaHe;
01581 float lambdaNe;
01582 float lambdaAr;
01583 float lambdaRed;
01584 float lambdaYel;
01585 float lambdaBlu;
01586 double flux, flux_err, resol, resol_err;
01587 int selected;
01588 int cslit = mos_slit_closest_to_center(slits, nx, ny);
01589
01590
01591
01592
01593
01594
01595 fors_qc_start_group(header, "1.1", instrume);
01596
01597 if (fors_qc_write_string("PRO.CATG", master_norm_flat_tag,
01598 "Product category", instrume))
01599 vimos_calib_exit("Cannot write product category to QC log file");
01600
01601 if (fors_qc_keyword_to_paf(header, "ARCFILE", NULL,
01602 "Archive File Name", instrume))
01603 vimos_calib_exit("Missing keyword ARCFILE in arc lamp frame");
01604
01605 if (fors_qc_keyword_to_paf(header, "ESO TPL ID", NULL,
01606 "Template signature ID", instrume))
01607 vimos_calib_exit("Missing keyword TPL ID in arc lamp frame");
01608
01609 if (fors_qc_keyword_to_paf(header, "ESO OCS CON QUAD", NULL,
01610 "Quadrant", instrume))
01611 vimos_calib_exit("Missing keyword OCS CON QUAD in arc lamp frame");
01612
01613 if (fors_qc_keyword_to_paf(header, key_filt_name, NULL,
01614 "Filter", instrume)) {
01615 cpl_msg_error(recipe, "Missing keyword %s in arc lamp frame",
01616 key_filt_name);
01617 vimos_calib_exit(NULL);
01618 }
01619
01620 if (fors_qc_keyword_to_paf(header, key_gris_name, NULL,
01621 "Grism", instrume)) {
01622 cpl_msg_error(recipe, "Missing keyword %s in arc lamp frame",
01623 key_gris_name);
01624 vimos_calib_exit(NULL);
01625 }
01626
01627 if (fors_qc_keyword_to_paf(header, key_mask_id, NULL,
01628 "Mask", instrume)) {
01629 cpl_msg_error(recipe, "Missing keyword %s in arc lamp frame",
01630 key_mask_id);
01631 vimos_calib_exit(NULL);
01632 }
01633
01634 cpl_propertylist_update_double(header,
01635 "ESO PRO WLEN CEN", reference);
01636
01637 if (fors_qc_keyword_to_paf(header, "ESO PRO WLEN CEN", "Angstrom",
01638 "Reference wavelength", instrume))
01639 vimos_calib_exit("Missing keyword PRO WLEN CEN in arc lamp frame");
01640
01641 pipefile = dfs_generate_filename_tfits(master_norm_flat_tag);
01642 if (fors_qc_write_string("PIPEFILE", pipefile,
01643 "Pipeline product name", instrume))
01644 vimos_calib_exit("Cannot write PIPEFILE to QC log file");
01645 cpl_free(pipefile); pipefile = NULL;
01646
01647 scale = cpl_propertylist_get_double(header, "ESO TEL FOCU SCALE");
01648
01649 if (cpl_error_get_code()) {
01650 cpl_error_reset();
01651 scale = 1.718;
01652 cpl_msg_warning(recipe, "Cannot read keyword TEL FOCU SCALE "
01653 "(defaulted to %f arcsec/mm)", scale);
01654 }
01655
01656
01657
01658
01659
01660 keyname = "QC.MOS.SLIT.WIDTH";
01661
01662 slit_width = scale * cpl_table_get(slits, "ywidth", cslit, NULL);
01663
01664 if (fors_qc_write_qc_double(header, slit_width, keyname, "arcsec",
01665 "Width of slit closest to center",
01666 instrume)) {
01667 vimos_calib_exit("Cannot write slit width to QC log file");
01668 }
01669
01670 if (grism[0] == 'L') {
01671 if (grism[3] == 'r') {
01672 lambdaHe = 7065.19;
01673 lambdaNe = 0.0;
01674 lambdaAr = 7723.80;
01675 lambdaRed = 9122.97;
01676 lambdaYel = 7635.11;
01677 lambdaBlu = 5875.62;
01678 }
01679 if (grism[3] == 'b') {
01680 lambdaHe = 5015.68;
01681 lambdaNe = 6598.96;
01682 lambdaAr = 0.0;
01683 lambdaRed = 6598.95;
01684 lambdaYel = 5015.68;
01685 lambdaBlu = 3888.65;
01686 }
01687 }
01688
01689 if (grism[0] == 'M') {
01690 lambdaHe = 7065.19;
01691 lambdaNe = 7032.41;
01692 lambdaAr = 7723.80;
01693 lambdaRed = 8264.521;
01694 lambdaYel = 6678.200;
01695 lambdaBlu = 5015.675;
01696 }
01697
01698 if (grism[0] == 'H') {
01699 if (grism[3] == 'r') {
01700 lambdaHe = 7065.19;
01701 lambdaNe = 7032.41;
01702 lambdaAr = 7723.80;
01703 lambdaRed = 9122.966;
01704 lambdaYel = 7948.175;
01705 lambdaBlu = 6929.468;
01706 }
01707 if (grism[3] == 'o') {
01708 lambdaHe = 7065.19;
01709 lambdaNe = 7032.41;
01710 lambdaAr = 7723.80;
01711 lambdaRed = 7948.175;
01712 lambdaYel = 6929.468;
01713 lambdaBlu = 5875.618;
01714 }
01715 if (grism[3] == 'b') {
01716 lambdaHe = 5015.68;
01717 lambdaNe = 5944.83;
01718 lambdaAr = 0.0;
01719 lambdaRed = 6598.953;
01720 lambdaYel = 5875.618;
01721 lambdaBlu = 5015.675;
01722 }
01723 }
01724
01725 if (lambdaHe > 1.) {
01726 mos_extract_flux_mapped(rectified, slits, lambdaHe,
01727 startwavelength, dispersion,
01728 4, gain, &flux, &flux_err);
01729
01730 flux /= arctime;
01731 flux_err /= arctime;
01732
01733 cpl_msg_info(recipe, "Flux of He %.2f: %.2f +/- %.2f ADU/mm^2/s",
01734 lambdaHe, flux, flux_err);
01735
01736 keyname = "QC.MOS.HE.LAMBDA";
01737
01738 if (fors_qc_write_qc_double(header, lambdaHe, keyname, "Angstrom",
01739 "He arc lamp line for flux determination", instrume)) {
01740 vimos_calib_exit("Cannot write He arc line to QC log file");
01741 }
01742
01743 keyname = "QC.MOS.HE.FLUX";
01744
01745 if (fors_qc_write_qc_double(header, flux, keyname, "ADU/mm^2/s",
01746 "Flux at chosen He wavelength", instrume)) {
01747 vimos_calib_exit("Cannot write He flux to QC log file");
01748 }
01749
01750 keyname = "QC.MOS.HE.FLUXERR";
01751
01752 if (fors_qc_write_qc_double(header, flux_err, keyname, "ADU/mm^2/s",
01753 "Error on flux at chosen He wavelength", instrume)) {
01754 vimos_calib_exit("Cannot write He flux error to QC log file");
01755 }
01756 }
01757 else
01758 cpl_msg_warning(recipe,
01759 "No He lines in %s spectral range: corresponding "
01760 "QC1 parameters are not computed.", grism);
01761
01762 if (lambdaNe > 1.) {
01763 mos_extract_flux_mapped(rectified, slits, lambdaNe,
01764 startwavelength, dispersion,
01765 4, gain, &flux, &flux_err);
01766
01767 flux /= arctime;
01768 flux_err /= arctime;
01769
01770 cpl_msg_info(recipe, "Flux of Ne %.2f: %.2f +/- %.2f ADU/mm^2/s",
01771 lambdaNe, flux, flux_err);
01772
01773 keyname = "QC.MOS.NE.LAMBDA";
01774
01775 if (fors_qc_write_qc_double(header, lambdaNe, keyname, "Angstrom",
01776 "Ne arc lamp line for flux determination", instrume)) {
01777 vimos_calib_exit("Cannot write Ne arc line to QC log file");
01778 }
01779
01780 keyname = "QC.MOS.NE.FLUX";
01781
01782 if (fors_qc_write_qc_double(header, flux, keyname, "ADU/mm^2/s",
01783 "Flux at chosen Ne wavelength", instrume)) {
01784 vimos_calib_exit("Cannot write Ne flux to QC log file");
01785 }
01786
01787 keyname = "QC.MOS.NE.FLUXERR";
01788
01789 if (fors_qc_write_qc_double(header, flux_err, keyname, "ADU/mm^2/s",
01790 "Error on flux at chosen Ne wavelength", instrume)) {
01791 vimos_calib_exit("Cannot write Ne flux error to QC log file");
01792 }
01793 }
01794 else
01795 cpl_msg_warning(recipe,
01796 "No Ne lines in %s spectral range: corresponding "
01797 "QC1 parameters are not computed.", grism);
01798
01799 if (lambdaAr > 1.) {
01800 mos_extract_flux_mapped(rectified, slits, lambdaAr,
01801 startwavelength, dispersion,
01802 4, gain, &flux, &flux_err);
01803
01804
01805 flux /= arctime;
01806 flux_err /= arctime;
01807
01808 cpl_msg_info(recipe, "Flux of Ar %.2f: %.2f +/- %.2f ADU/mm^2/s",
01809 lambdaAr, flux, flux_err);
01810
01811 keyname = "QC.MOS.AR.LAMBDA";
01812
01813 if (fors_qc_write_qc_double(header, lambdaAr, keyname, "Angstrom",
01814 "Ar arc lamp line for flux determination", instrume)) {
01815 vimos_calib_exit("Cannot write Ar arc line to QC log file");
01816 }
01817
01818 keyname = "QC.MOS.AR.FLUX";
01819
01820 if (fors_qc_write_qc_double(header, flux, keyname, "ADU/mm^2/s",
01821 "Flux at chosen Ar wavelength", instrume)) {
01822 vimos_calib_exit("Cannot write Ar flux to QC log file");
01823 }
01824
01825 keyname = "QC.MOS.AR.FLUXERR";
01826
01827 if (fors_qc_write_qc_double(header, flux_err, keyname, "ADU/mm^2/s",
01828 "Error on flux at chosen Ar wavelength", instrume)) {
01829 vimos_calib_exit("Cannot write Ar flux error to QC log file");
01830 }
01831 }
01832 else
01833 cpl_msg_warning(recipe,
01834 "No Ar lines in %s spectral range: corresponding "
01835 "QC1 parameters are not computed.", grism);
01836
01837
01838
01839
01840
01841 for (i = 0; i <= wdegree; i++) {
01842 char *label = cpl_sprintf("c%d", i);
01843 char *unit;
01844 char *comment;
01845 double mcoeff;
01846
01847
01848 mcoeff = 0.0;
01849 if (i) {
01850 if (mos_median_in_slit(idscoeff, slits,
01851 cslit, label, &mcoeff)) {
01852 cpl_free(label);
01853 break;
01854 }
01855 }
01856
01857 keyname = cpl_sprintf("QC.MOS.WAVECAL.COEFF%d", i);
01858
01859 switch (i) {
01860 case 0:
01861 unit = cpl_strdup("pixel");
01862 break;
01863 case 1:
01864 unit = cpl_strdup("pixel/Angstrom");
01865 break;
01866 default:
01867 unit = cpl_sprintf("pixel/Angstrom^%d", i);
01868 break;
01869 }
01870
01871 comment = cpl_sprintf("Median coefficient %d of IDS", i);
01872
01873 if (fors_qc_write_qc_double(header, mcoeff, keyname,
01874 unit, comment, instrume)) {
01875 vimos_calib_exit("Cannot write IDS coefficient to QC logfile");
01876 }
01877
01878 cpl_free(keyname);
01879 cpl_free(comment);
01880 cpl_free(unit);
01881 cpl_free(label);
01882 }
01883
01884
01885
01886
01887
01888 keyname = "QC.MOS.REFWAVE.MEAN";
01889
01890 if (fors_qc_write_qc_double(header, 0.0, keyname, "pixel",
01891 "MEAN of CCD positions of reference wavelength", instrume)) {
01892 vimos_calib_exit("Cannot write QC.MOS.REFWAVE.MEAN to QC logfile");
01893 }
01894
01895 keyname = "QC.MOS.REFWAVE.RMS";
01896
01897 if (fors_qc_write_qc_double(header, 0.0, keyname, "pixel",
01898 "RMS of CCD positions of reference wavelength", instrume)) {
01899 vimos_calib_exit("Cannot write QC.MOS.REFWAVE.RMS to QC logfile");
01900 }
01901
01902 if (restab) {
01903
01904
01905
01906
01907
01908 keyname = "QC.MOS.RESOLUTION1.LAMBDA";
01909
01910 if (fors_qc_write_qc_double(header, lambdaRed, keyname, "Angstrom",
01911 "Line used in spectral resolution determination", instrume)) {
01912 vimos_calib_exit("Cannot write arc line to QC log file");
01913 }
01914
01915 keyname = "QC.MOS.RESOLUTION1";
01916
01917 cpl_table_and_selected_double(restab, "wavelength",
01918 CPL_GREATER_THAN, lambdaRed - 1.0);
01919 selected =
01920 cpl_table_and_selected_double(restab, "wavelength",
01921 CPL_LESS_THAN, lambdaRed + 1.0);
01922
01923 if (selected == 1) {
01924 cpl_table *one_line = cpl_table_extract_selected(restab);
01925
01926 resol = cpl_table_get_double(one_line,
01927 "resolution", 0, NULL);
01928 resol_err = cpl_table_get_double(one_line,
01929 "resolution_rms", 0, NULL);
01930
01931 cpl_table_delete(one_line);
01932 }
01933 else {
01934 resol = 0.0;
01935 resol_err = 0.0;
01936 }
01937
01938 cpl_table_select_all(restab);
01939
01940 cpl_msg_info(recipe, "Spectral resolution at %.2f: %.2f +/- %.2f",
01941 lambdaRed, resol, resol_err);
01942
01943 if (fors_qc_write_qc_double(header, resol, keyname, NULL,
01944 "Mean spectral resolution at red end of spectrum", instrume)) {
01945 vimos_calib_exit("Cannot write spectral resolution "
01946 "to QC log file");
01947 }
01948
01949 keyname = "QC.MOS.RESOLUTION1.RMS";
01950
01951 if (fors_qc_write_qc_double(header, resol_err, keyname, NULL,
01952 "Error on mean spectral resolution", instrume)) {
01953 vimos_calib_exit("Cannot write error on resolution "
01954 "to QC log file");
01955 }
01956
01957 keyname = "QC.MOS.RESOLUTION2.LAMBDA";
01958
01959 if (fors_qc_write_qc_double(header, lambdaYel, keyname, "Angstrom",
01960 "Line used in spectral resolution determination", instrume)) {
01961 vimos_calib_exit("Cannot write arc line to QC log file");
01962 }
01963
01964 keyname = "QC.MOS.RESOLUTION2";
01965
01966 cpl_table_and_selected_double(restab, "wavelength",
01967 CPL_GREATER_THAN, lambdaYel - 1.0);
01968 selected =
01969 cpl_table_and_selected_double(restab, "wavelength",
01970 CPL_LESS_THAN, lambdaYel + 1.0);
01971
01972 if (selected == 1) {
01973 cpl_table *one_line = cpl_table_extract_selected(restab);
01974
01975 resol = cpl_table_get_double(one_line,
01976 "resolution", 0, NULL);
01977 resol_err = cpl_table_get_double(one_line,
01978 "resolution_rms", 0, NULL);
01979
01980 cpl_table_delete(one_line);
01981 }
01982 else {
01983 resol = 0.0;
01984 resol_err = 0.0;
01985 }
01986
01987 cpl_table_select_all(restab);
01988
01989 cpl_msg_info(recipe, "Spectral resolution at %.2f: %.2f +/- %.2f",
01990 lambdaYel, resol, resol_err);
01991
01992 if (fors_qc_write_qc_double(header, resol, keyname, NULL,
01993 "Mean spectral resolution at center of spectrum", instrume)) {
01994 vimos_calib_exit("Cannot write spectral resolution "
01995 "to QC log file");
01996 }
01997
01998 keyname = "QC.MOS.RESOLUTION2.RMS";
01999
02000 if (fors_qc_write_qc_double(header, resol_err, keyname, NULL,
02001 "Error on mean spectral resolution", instrume)) {
02002 vimos_calib_exit("Cannot write error on resolution "
02003 "to QC log file");
02004 }
02005
02006 keyname = "QC.MOS.RESOLUTION3.LAMBDA";
02007
02008 if (fors_qc_write_qc_double(header, lambdaBlu, keyname, "Angstrom",
02009 "Line used in spectral resolution determination", instrume)) {
02010 vimos_calib_exit("Cannot write arc line to QC log file");
02011 }
02012
02013 keyname = "QC.MOS.RESOLUTION3";
02014
02015 cpl_table_and_selected_double(restab, "wavelength",
02016 CPL_GREATER_THAN, lambdaBlu - 1.0);
02017 selected =
02018 cpl_table_and_selected_double(restab, "wavelength",
02019 CPL_LESS_THAN, lambdaBlu + 1.0);
02020
02021 if (selected == 1) {
02022 cpl_table *one_line = cpl_table_extract_selected(restab);
02023
02024 resol = cpl_table_get_double(one_line,
02025 "resolution", 0, NULL);
02026 resol_err = cpl_table_get_double(one_line,
02027 "resolution_rms", 0, NULL);
02028
02029 cpl_table_delete(one_line);
02030 }
02031 else {
02032 resol = 0.0;
02033 resol_err = 0.0;
02034 }
02035
02036 cpl_table_select_all(restab);
02037
02038 cpl_msg_info(recipe, "Spectral resolution at %.2f: %.2f +/- %.2f",
02039 lambdaBlu, resol, resol_err);
02040
02041 if (fors_qc_write_qc_double(header, resol, keyname, NULL,
02042 "Mean spectral resolution at blue end of spectrum", instrume)) {
02043 vimos_calib_exit("Cannot write spectral resolution "
02044 "to QC log file");
02045 }
02046
02047 keyname = "QC.MOS.RESOLUTION3.RMS";
02048
02049 if (fors_qc_write_qc_double(header, resol_err, keyname, NULL,
02050 "Error on mean spectral resolution", instrume)) {
02051 vimos_calib_exit("Cannot write error on resolution "
02052 "to QC log file");
02053 }
02054
02055 keyname = "QC.MOS.IDS.RMS";
02056
02057 if (fors_qc_write_qc_double(header, mean_rms, keyname, "pixel",
02058 "Mean accuracy of dispersion solution", instrume)) {
02059 vimos_calib_exit("Cannot write mean accuracy of "
02060 "dispersion solution to QC log file");
02061 }
02062 }
02063
02064 fors_qc_end_group();
02065
02066 }
02067
02068 cpl_free(grism); grism = NULL;
02069 cpl_free(instrume); instrume = NULL;
02070 cpl_table_delete(restab); restab = NULL;
02071 cpl_table_delete(idscoeff); idscoeff = NULL;
02072 cpl_image_delete(spectra); spectra = NULL;
02073
02074 if (dfs_save_image(frameset, rectified, reduced_lamp_tag, header,
02075 parlist, recipe, version))
02076 vimos_calib_exit(NULL);
02077
02078 cpl_image_delete(rectified); rectified = NULL;
02079 cpl_propertylist_delete(header); header = NULL;
02080
02081 if (check) {
02082 save_header = dfs_load_header(frameset, arc_tag, 0);
02083
02084 cpl_propertylist_update_double(save_header, "CRPIX2", 1.0);
02085 cpl_propertylist_update_double(save_header, "CRVAL2", 1.0);
02086
02087 cpl_propertylist_update_double(save_header, "CD1_1", 1.0);
02088 cpl_propertylist_update_double(save_header, "CD1_2", 0.0);
02089 cpl_propertylist_update_double(save_header, "CD2_1", 0.0);
02090 cpl_propertylist_update_double(save_header, "CD2_2", 1.0);
02091 cpl_propertylist_update_string(save_header, "CTYPE1", "LINEAR");
02092 cpl_propertylist_update_string(save_header, "CTYPE2", "PIXEL");
02093
02094 if (dfs_save_image(frameset, residual, disp_residuals_tag, save_header,
02095 parlist, recipe, version))
02096 vimos_calib_exit(NULL);
02097
02098 cpl_image_delete(residual); residual = NULL;
02099 cpl_propertylist_delete(save_header); save_header = NULL;
02100 }
02101
02102 if (!treat_as_lss) {
02103
02104
02105
02106
02107
02108 wavemap = mos_map_wavelengths(coordinate, rainbow, slits,
02109 polytraces, reference,
02110 startwavelength, endwavelength,
02111 dispersion);
02112
02113 cpl_image_delete(rainbow); rainbow = NULL;
02114 }
02115
02116 save_header = dfs_load_header(frameset, arc_tag, 0);
02117
02118 cpl_image_turn(wavemap, rotate_back);
02119 if (dfs_save_image(frameset, wavemap, wavelength_map_tag, save_header,
02120 parlist, recipe, version))
02121 vimos_calib_exit(NULL);
02122
02123 cpl_image_delete(wavemap); wavemap = NULL;
02124
02125 cpl_image_turn(coordinate, rotate_back);
02126 if (dfs_save_image(frameset, coordinate, spatial_map_tag, save_header,
02127 parlist, recipe, version))
02128 vimos_calib_exit(NULL);
02129
02130 cpl_image_delete(coordinate); coordinate = NULL;
02131 cpl_propertylist_delete(save_header); save_header = NULL;
02132
02133 if (dfs_save_table(frameset, polytraces, curv_coeff_tag, NULL,
02134 parlist, recipe, version))
02135 vimos_calib_exit(NULL);
02136
02137 cpl_table_delete(polytraces); polytraces = NULL;
02138
02139 mos_rotate_slits(slits, rotate, ccd_ysize, ccd_xsize);
02140 if (dfs_save_table(frameset, slits, slit_location_tag, NULL,
02141 parlist, recipe, version))
02142 vimos_calib_exit(NULL);
02143
02144 cpl_table_delete(slits); slits = NULL;
02145
02146 if (cpl_error_get_code()) {
02147 cpl_msg_error(cpl_error_get_where(), cpl_error_get_message());
02148 vimos_calib_exit(NULL);
02149 }
02150
02151 return 0;
02152 }