32 #include <vimos_calib_impl.h>
40 #define vimos_calib_exit(message) \
42 if (message !=NULL ) cpl_msg_error(recipe, message); \
47 cpl_image_delete(bias); \
48 cpl_image_delete(master_bias); \
49 cpl_image_delete(coordinate); \
50 cpl_image_delete(checkwave); \
51 cpl_image_delete(flat); \
52 cpl_image_delete(master_flat); \
53 cpl_image_delete(norm_flat); \
54 cpl_image_delete(rainbow); \
55 cpl_image_delete(rectified); \
56 cpl_image_delete(residual); \
57 cpl_image_delete(smo_flat); \
58 cpl_image_delete(spatial); \
59 cpl_image_delete(spectra); \
60 cpl_image_delete(wavemap); \
61 cpl_image_delete(delta); \
62 cpl_mask_delete(refmask); \
63 cpl_propertylist_delete(header); \
64 cpl_propertylist_delete(save_header); \
65 cpl_propertylist_delete(qclist); \
66 cpl_table_delete(grism_table); \
67 cpl_table_delete(idscoeff); \
68 cpl_table_delete(restable); \
69 cpl_table_delete(maskslits); \
70 cpl_table_delete(overscans); \
71 cpl_table_delete(traces); \
72 cpl_table_delete(polytraces); \
73 cpl_table_delete(slits); \
74 cpl_table_delete(restab); \
75 cpl_table_delete(global); \
76 cpl_table_delete(wavelengths); \
77 cpl_vector_delete(lines); \
78 cpl_msg_indent_less(); \
82 #define vimos_calib_exit_memcheck(message) \
84 if (message !=NULL ) cpl_msg_info(recipe, message); \
85 printf("free instrume (%p)\n", instrume); \
87 printf("free pipefile (%p)\n", pipefile); \
89 printf("free fiterror (%p)\n", fiterror); \
91 printf("free fitlines (%p)\n", fitlines); \
93 printf("free bias (%p)\n", bias); \
94 cpl_image_delete(bias); \
95 printf("free master_bias (%p)\n", master_bias); \
96 cpl_image_delete(master_bias); \
97 printf("free coordinate (%p)\n", coordinate); \
98 cpl_image_delete(coordinate); \
99 printf("free checkwave (%p)\n", checkwave); \
100 cpl_image_delete(checkwave); \
101 printf("free flat (%p)\n", flat); \
102 cpl_image_delete(flat); \
103 printf("free master_flat (%p)\n", master_flat); \
104 cpl_image_delete(master_flat); \
105 printf("free norm_flat (%p)\n", norm_flat); \
106 cpl_image_delete(norm_flat); \
107 printf("free rainbow (%p)\n", rainbow); \
108 cpl_image_delete(rainbow); \
109 printf("free rectified (%p)\n", rectified); \
110 cpl_image_delete(rectified); \
111 printf("free residual (%p)\n", residual); \
112 cpl_image_delete(residual); \
113 printf("free smo_flat (%p)\n", smo_flat); \
114 cpl_image_delete(smo_flat); \
115 printf("free spatial (%p)\n", spatial); \
116 cpl_image_delete(spatial); \
117 printf("free spectra (%p)\n", spectra); \
118 cpl_image_delete(spectra); \
119 printf("free wavemap (%p)\n", wavemap); \
120 cpl_image_delete(wavemap); \
121 printf("free delta (%p)\n", delta); \
122 cpl_image_delete(delta); \
123 printf("free refmask (%p)\n", refmask); \
124 cpl_mask_delete(refmask); \
125 printf("free header (%p)\n", header); \
126 cpl_propertylist_delete(header); \
127 printf("free save_header (%p)\n", save_header); \
128 cpl_propertylist_delete(save_header); \
129 printf("free qclist (%p)\n", qclist); \
130 cpl_propertylist_delete(qclist); \
131 printf("free grism_table (%p)\n", grism_table); \
132 cpl_table_delete(grism_table); \
133 printf("free idscoeff (%p)\n", idscoeff); \
134 cpl_table_delete(idscoeff); \
135 printf("free restable (%p)\n", restable); \
136 cpl_table_delete(restable); \
137 printf("free maskslits (%p)\n", maskslits); \
138 cpl_table_delete(maskslits); \
139 printf("free overscans (%p)\n", overscans); \
140 cpl_table_delete(overscans); \
141 printf("free traces (%p)\n", traces); \
142 cpl_table_delete(traces); \
143 printf("free polytraces (%p)\n", polytraces); \
144 cpl_table_delete(polytraces); \
145 printf("free slits (%p)\n", slits); \
146 cpl_table_delete(slits); \
147 printf("free restab (%p)\n", restab); \
148 cpl_table_delete(restab); \
149 printf("free global (%p)\n", global); \
150 cpl_table_delete(global); \
151 printf("free wavelengths (%p)\n", wavelengths); \
152 cpl_table_delete(wavelengths); \
153 printf("free lines (%p)\n", lines); \
154 cpl_vector_delete(lines); \
155 cpl_msg_indent_less(); \
177 const char *recipe =
"vimos_calib";
184 double peakdetection;
192 double startwavelength;
193 double endwavelength;
207 cpl_imagelist *biases = NULL;
208 cpl_image *bias = NULL;
209 cpl_image *master_bias = NULL;
210 cpl_image *multi_bias = NULL;
211 cpl_image *flat = NULL;
212 cpl_image *master_flat = NULL;
213 cpl_image *smo_flat = NULL;
214 cpl_image *norm_flat = NULL;
215 cpl_image *spectra = NULL;
216 cpl_image *wavemap = NULL;
217 cpl_image *delta = NULL;
218 cpl_image *residual = NULL;
219 cpl_image *checkwave = NULL;
220 cpl_image *rectified = NULL;
221 cpl_image *dummy = NULL;
222 cpl_image *refimage = NULL;
223 cpl_image *coordinate = NULL;
224 cpl_image *rainbow = NULL;
225 cpl_image *spatial = NULL;
227 cpl_mask *refmask = NULL;
229 cpl_table *grism_table = NULL;
230 cpl_table *overscans = NULL;
231 cpl_table *wavelengths = NULL;
232 cpl_table *idscoeff = NULL;
233 cpl_table *restable = NULL;
234 cpl_table *slits = NULL;
235 cpl_table *positions = NULL;
236 cpl_table *maskslits = NULL;
237 cpl_table *traces = NULL;
238 cpl_table *polytraces = NULL;
239 cpl_table *restab = NULL;
240 cpl_table *global = NULL;
242 cpl_vector *lines = NULL;
244 cpl_propertylist *header = NULL;
245 cpl_propertylist *save_header = NULL;
246 cpl_propertylist *qclist = NULL;
252 cpl_table *idscoeff_lss = NULL;
255 const char *flat_tag;
256 const char *master_screen_flat_tag;
257 const char *master_norm_flat_tag;
258 const char *reduced_lamp_tag;
259 const char *disp_residuals_tag;
260 const char *disp_coeff_tag;
261 const char *wavelength_map_tag;
262 const char *spectra_detection_tag;
263 const char *spectral_resolution_tag;
264 const char *slit_map_tag;
265 const char *curv_traces_tag;
266 const char *curv_coeff_tag;
267 const char *spatial_map_tag;
268 const char *slit_location_tag;
269 const char *global_distortion_tag =
"GLOBAL_DISTORTION_TABLE";
270 const char *disp_residuals_table_tag;
271 const char *delta_image_tag;
272 const char *key_gris_name;
273 const char *key_gris_id;
274 const char *key_filt_name;
275 const char *key_filt_id;
276 const char *key_mask_id;
280 int treat_as_lss = 0;
285 double alltime, arctime;
290 double *fiterror = NULL;
291 int *fitlines = NULL;
294 int ccd_xsize, ccd_ysize;
296 int rotate_back = -1;
299 char *instrume = NULL;
300 char *pipefile = NULL;
304 snprintf(version, 80,
"%s-%s", PACKAGE, PACKAGE_VERSION);
306 cpl_msg_set_indentation(2);
313 cpl_msg_info(recipe,
"Recipe %s configuration parameters:", recipe);
314 cpl_msg_indent_more();
316 if (cpl_frameset_count_tags(frameset,
"GRISM_TABLE") > 1)
317 vimos_calib_exit(
"Too many in input: GRISM_TABLE");
322 "fors.vimos_calib.dispersion", grism_table);
324 if (dispersion <= 0.0)
325 vimos_calib_exit(
"Invalid spectral dispersion value");
328 "fors.vimos_calib.peakdetection", grism_table);
329 if (peakdetection <= 0.0)
330 vimos_calib_exit(
"Invalid peak detection level");
333 "fors.vimos_calib.wdegree", grism_table);
336 vimos_calib_exit(
"Invalid polynomial degree");
339 vimos_calib_exit(
"Max allowed polynomial degree is 5");
344 vimos_calib_exit(
"Invalid search radius");
347 "fors.vimos_calib.wreject", NULL);
350 vimos_calib_exit(
"Invalid rejection threshold");
354 if (wmode < 0 || wmode > 2)
355 vimos_calib_exit(
"Invalid wavelength solution interpolation mode");
358 "fors.vimos_calib.wcolumn", NULL);
361 "fors.vimos_calib.cdegree", grism_table);
364 vimos_calib_exit(
"Invalid polynomial degree");
367 vimos_calib_exit(
"Max allowed polynomial degree is 5");
371 if (cmode < 0 || cmode > 2)
372 vimos_calib_exit(
"Invalid curvature solution interpolation mode");
375 "fors.vimos_calib.startwavelength", grism_table);
376 if (startwavelength > 1.0)
377 if (startwavelength < 3000.0 || startwavelength > 13000.0)
378 vimos_calib_exit(
"Invalid wavelength");
381 "fors.vimos_calib.endwavelength", grism_table);
382 if (endwavelength > 1.0) {
383 if (endwavelength < 3000.0 || endwavelength > 13000.0)
384 vimos_calib_exit(
"Invalid wavelength");
385 if (startwavelength < 1.0)
386 vimos_calib_exit(
"Invalid wavelength interval");
389 if (startwavelength > 1.0)
390 if (endwavelength - startwavelength <= 0.0)
391 vimos_calib_exit(
"Invalid wavelength interval");
394 "fors.vimos_calib.reference", grism_table);
396 if (reference < startwavelength || reference > endwavelength)
397 vimos_calib_exit(
"Invalid reference wavelength");
400 "fors.vimos_calib.slit_ident", NULL);
407 if (sradius < 1 || dradius < 1)
408 vimos_calib_exit(
"Invalid smoothing box radius");
414 cpl_table_delete(grism_table); grism_table = NULL;
416 if (cpl_error_get_code())
417 vimos_calib_exit(
"Failure getting the configuration parameters");
424 cpl_msg_indent_less();
425 cpl_msg_info(recipe,
"Check input set-of-frames:");
426 cpl_msg_indent_more();
429 vimos_calib_exit(
"Input frames are not from the same quadrant");
431 mos = cpl_frameset_count_tags(frameset,
"MOS_ARC_SPECTRUM");
434 vimos_calib_exit(
"Missing input arc lamp frame");
437 vimos_calib_exit(
"Just one input arc lamp frame is allowed");
439 arc_tag =
"MOS_ARC_SPECTRUM";
440 flat_tag =
"MOS_SCREEN_FLAT";
441 master_screen_flat_tag =
"MOS_COMBINED_SCREEN_FLAT";
442 master_norm_flat_tag =
"MOS_MASTER_SCREEN_FLAT";
443 reduced_lamp_tag =
"MOS_ARC_SPECTRUM_EXTRACTED";
444 disp_residuals_tag =
"MOS_DISP_RESIDUALS";
445 disp_coeff_tag =
"MOS_DISP_COEFF";
446 wavelength_map_tag =
"MOS_WAVELENGTH_MAP";
447 spectra_detection_tag =
"MOS_SPECTRA_DETECTION";
448 spectral_resolution_tag =
"MOS_SPECTRAL_RESOLUTION";
449 slit_map_tag =
"MOS_SLIT_MAP";
450 curv_traces_tag =
"MOS_CURV_TRACES";
451 curv_coeff_tag =
"MOS_CURV_COEFF";
452 spatial_map_tag =
"MOS_SPATIAL_MAP";
453 slit_location_tag =
"MOS_SLIT_LOCATION";
454 disp_residuals_table_tag =
"MOS_DISP_RESIDUALS_TABLE";
455 delta_image_tag =
"MOS_DELTA_IMAGE";
458 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") == 0) {
459 if (cpl_frameset_count_tags(frameset,
"BIAS") == 0)
460 vimos_calib_exit(
"Missing required input: MASTER_BIAS or BIAS");
461 nbias = cpl_frameset_count_tags(frameset,
"BIAS");
464 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") > 1)
465 vimos_calib_exit(
"Too many in input: MASTER_BIAS");
467 if (cpl_frameset_count_tags(frameset,
"LINE_CATALOG") == 0)
468 vimos_calib_exit(
"Missing required input: LINE_CATALOG");
470 if (cpl_frameset_count_tags(frameset,
"LINE_CATALOG") > 1)
471 vimos_calib_exit(
"Too many in input: LINE_CATALOG");
473 nflats = cpl_frameset_count_tags(frameset, flat_tag);
476 cpl_msg_error(recipe,
"Missing required input: %s", flat_tag);
477 vimos_calib_exit(NULL);
480 cpl_msg_indent_less();
483 cpl_msg_info(recipe,
"Load %d flat field frames and sum them...",
486 cpl_msg_info(recipe,
"Load flat field exposure...");
488 cpl_msg_indent_more();
493 vimos_calib_exit(
"Cannot load flat field frame header");
495 alltime = cpl_propertylist_get_double(header,
"EXPTIME");
497 if (cpl_error_get_code() != CPL_ERROR_NONE)
498 vimos_calib_exit(
"Missing keyword EXPTIME in flat field frame header");
500 cpl_propertylist_delete(header);
502 for (i = 1; i < nflats; i++) {
507 vimos_calib_exit(
"Cannot load flat field frame header");
509 alltime += cpl_propertylist_get_double(header,
"EXPTIME");
511 if (cpl_error_get_code() != CPL_ERROR_NONE)
512 vimos_calib_exit(
"Missing keyword EXPTIME in flat field "
515 cpl_propertylist_delete(header);
519 master_flat =
dfs_load_image(frameset, flat_tag, CPL_TYPE_FLOAT, 0, 0);
521 if (master_flat == NULL)
522 vimos_calib_exit(
"Cannot load flat field");
524 for (i = 1; i < nflats; i++) {
527 cpl_image_add(master_flat, flat);
528 cpl_image_delete(flat); flat = NULL;
531 vimos_calib_exit(
"Cannot load flat field");
542 vimos_calib_exit(
"Cannot load arc lamp header");
544 instrume = (
char *)cpl_propertylist_get_string(header,
"INSTRUME");
545 if (instrume == NULL)
546 vimos_calib_exit(
"Missing keyword INSTRUME in arc lamp header");
547 instrume = cpl_strdup(instrume);
549 arctime = cpl_propertylist_get_double(header,
"EXPTIME");
551 quadrant = cpl_propertylist_get_int(header,
"ESO OCS CON QUAD");
555 key_gris_name =
"ESO INS GRIS1 NAME";
556 key_gris_id =
"ESO INS GRIS1 ID";
557 key_filt_name =
"ESO INS FILT1 NAME";
558 key_filt_id =
"ESO INS FILT1 ID";
559 key_mask_id =
"ESO INS MASK1 ID";
562 key_gris_name =
"ESO INS GRIS2 NAME";
563 key_gris_id =
"ESO INS GRIS2 ID";
564 key_filt_name =
"ESO INS FILT2 NAME";
565 key_filt_id =
"ESO INS FILT2 ID";
566 key_mask_id =
"ESO INS MASK2 ID";
569 key_gris_name =
"ESO INS GRIS3 NAME";
570 key_gris_id =
"ESO INS GRIS3 ID";
571 key_filt_name =
"ESO INS FILT3 NAME";
572 key_filt_id =
"ESO INS FILT3 ID";
573 key_mask_id =
"ESO INS MASK3 ID";
576 key_gris_name =
"ESO INS GRIS4 NAME";
577 key_gris_id =
"ESO INS GRIS4 ID";
578 key_filt_name =
"ESO INS FILT4 NAME";
579 key_filt_id =
"ESO INS FILT4 ID";
580 key_mask_id =
"ESO INS MASK4 ID";
584 grism = cpl_strdup(cpl_propertylist_get_string(header, key_gris_name));
586 if (cpl_error_get_code() != CPL_ERROR_NONE)
587 vimos_calib_exit(
"Missing keyword ESO INS GRISn NAME in arc lamp "
590 cpl_msg_info(recipe,
"The grism is: %s", grism);
600 gain = cpl_propertylist_get_double(header,
"ESO DET OUT1 CONAD");
602 if (cpl_error_get_code() != CPL_ERROR_NONE)
603 vimos_calib_exit(
"Missing keyword ESO DET OUT1 CONAD in arc lamp "
606 cpl_msg_info(recipe,
"The gain factor is: %.2f e-/ADU", gain);
608 cpl_msg_info(recipe,
"Produce mask slit position table...");
617 mxpos = cpl_table_get_column_median(maskslits,
"ytop");
618 xpos = cpl_table_get_data_double(maskslits,
"ytop");
619 nslits = cpl_table_get_nrow(maskslits);
622 for (i = 0; i < nslits; i++) {
623 if (fabs(mxpos-xpos[i]) > 0.01) {
630 cpl_msg_warning(recipe,
"All MOS slits have the same offset: %.2f\n"
631 "The long-slit data reduction strategy is applied!",
633 cpl_table_delete(maskslits); maskslits = NULL;
636 if (slit_ident == 0) {
637 cpl_table_delete(maskslits); maskslits = NULL;
654 cpl_msg_info(recipe,
"Generate the master from input raw biases...");
658 biases = cpl_imagelist_new();
663 vimos_calib_exit(
"Cannot load bias frame");
665 cpl_imagelist_set(biases, bias, 0); bias = NULL;
667 for (i = 1; i < nbias; i++) {
670 cpl_imagelist_set(biases, bias, i); bias = NULL;
673 vimos_calib_exit(
"Cannot load bias frame");
676 master_bias = cpl_imagelist_collapse_median_create(biases);
678 cpl_imagelist_delete(biases);
682 CPL_TYPE_FLOAT, 0, 1);
687 CPL_TYPE_FLOAT, 0, 1);
688 if (master_bias == NULL)
689 vimos_calib_exit(
"Cannot load master bias");
692 cpl_msg_info(recipe,
"Remove the master bias...");
695 cpl_propertylist_delete(header); header = NULL;
698 int xlow = cpl_table_get_int(overscans,
"xlow", 0, NULL);
699 int ylow = cpl_table_get_int(overscans,
"ylow", 0, NULL);
700 int xhig = cpl_table_get_int(overscans,
"xhig", 0, NULL);
701 int yhig = cpl_table_get_int(overscans,
"yhig", 0, NULL);
702 dummy = cpl_image_extract(master_bias, xlow+1, ylow+1, xhig, yhig);
703 cpl_image_delete(master_bias); master_bias = dummy;
706 NULL, parlist, recipe, version))
707 vimos_calib_exit(NULL);
711 multi_bias = cpl_image_multiply_scalar_create(master_bias, nflats);
713 cpl_image_delete(multi_bias);
718 cpl_image_delete(master_flat);
721 if (master_flat == NULL)
722 vimos_calib_exit(
"Cannot remove bias from flat field");
724 cpl_msg_indent_less();
725 cpl_msg_info(recipe,
"Load arc lamp exposure...");
726 cpl_msg_indent_more();
728 spectra =
dfs_load_image(frameset, arc_tag, CPL_TYPE_FLOAT, 0, 0);
731 vimos_calib_exit(
"Cannot load arc lamp exposure");
733 cpl_msg_info(recipe,
"Remove the master bias...");
736 cpl_table_delete(overscans); overscans = NULL;
737 cpl_image_delete(master_bias); master_bias = NULL;
738 cpl_image_delete(spectra); spectra = dummy;
741 vimos_calib_exit(
"Cannot remove bias from arc lamp exposure");
743 cpl_msg_indent_less();
744 cpl_msg_info(recipe,
"Load input line catalog...");
745 cpl_msg_indent_more();
749 if (wavelengths == NULL)
750 vimos_calib_exit(
"Cannot load line catalog");
757 nlines = cpl_table_get_nrow(wavelengths);
760 vimos_calib_exit(
"Empty input line catalog");
762 if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
763 cpl_msg_error(recipe,
"Missing column %s in input line catalog table",
765 vimos_calib_exit(NULL);
768 line = cpl_malloc(nlines *
sizeof(
double));
770 for (i = 0; i < nlines; i++)
771 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
773 cpl_table_delete(wavelengths); wavelengths = NULL;
775 lines = cpl_vector_wrap(nlines, line);
782 cpl_image_turn(spectra, rotate);
783 cpl_image_turn(master_flat, rotate);
785 ccd_xsize = nx = cpl_image_get_size_x(spectra);
786 ccd_ysize = ny = cpl_image_get_size_y(spectra);
796 cpl_msg_indent_less();
797 cpl_msg_info(recipe,
"Perform wavelength calibration...");
798 cpl_msg_indent_more();
800 wavemap = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
802 residual = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
804 fiterror = cpl_calloc(ny,
sizeof(
double));
805 fitlines = cpl_calloc(ny,
sizeof(
int));
806 idscoeff = cpl_table_new(ny);
807 refmask = cpl_mask_new(nx, ny);
810 vimos_calib_exit(
"Cannot process saturation");
813 vimos_calib_exit(
"Cannot subtract the background");
816 peakdetection, wradius,
817 wdegree, wreject, reference,
819 &endwavelength, fitlines,
820 fiterror, idscoeff, wavemap,
821 residual, NULL, refmask);
823 if (rectified == NULL)
824 vimos_calib_exit(
"Wavelength calibration failure.");
826 if (!cpl_table_has_valid(idscoeff,
"c0"))
827 vimos_calib_exit(
"Wavelength calibration failure.");
836 cpl_image_delete(rectified); rectified = NULL;
837 cpl_image_delete(wavemap); wavemap = NULL;
840 startwavelength, endwavelength);
843 endwavelength, dispersion,
847 cpl_table_wrap_double(idscoeff, fiterror,
"error"); fiterror = NULL;
848 cpl_table_set_column_unit(idscoeff,
"error",
"pixel");
849 cpl_table_wrap_int(idscoeff, fitlines,
"nlines"); fitlines = NULL;
851 for (i = 0; i < ny; i++)
852 if (!cpl_table_is_valid(idscoeff,
"c0", i))
853 cpl_table_set_invalid(idscoeff,
"error", i);
856 idscoeff_lss = idscoeff;
869 cpl_msg_indent_less();
870 cpl_msg_info(recipe,
"Detecting spectra on CCD...");
871 cpl_msg_indent_more();
873 ccd_xsize = nx = cpl_image_get_size_x(spectra);
874 ccd_ysize = ny = cpl_image_get_size_y(spectra);
876 refmask = cpl_mask_new(nx, ny);
879 vimos_calib_exit(
"Cannot process saturation");
882 vimos_calib_exit(
"Cannot subtract the background");
885 peakdetection, wradius,
886 wdegree, wreject, reference,
889 NULL, NULL, NULL, NULL,
890 NULL, NULL, refmask);
892 if (checkwave == NULL)
893 vimos_calib_exit(
"Wavelength calibration failure.");
899 header = cpl_propertylist_new();
900 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
901 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
902 cpl_propertylist_update_double(header,
"CRVAL1",
903 startwavelength + dispersion/2);
904 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
907 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
908 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
909 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
910 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
911 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
912 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
916 header, parlist, recipe, version))
917 vimos_calib_exit(NULL);
920 cpl_image_delete(checkwave); checkwave = NULL;
921 cpl_propertylist_delete(header); header = NULL;
925 cpl_msg_info(recipe,
"Locate slits at reference wavelength on CCD...");
929 cpl_msg_error(cpl_error_get_where(), cpl_error_get_message());
930 vimos_calib_exit(
"No slits could be detected!");
933 refimage = cpl_image_new_from_mask(refmask);
934 cpl_mask_delete(refmask); refmask = NULL;
938 cpl_image_turn(refimage, rotate_back);
940 parlist, recipe, version))
941 vimos_calib_exit(NULL);
942 cpl_propertylist_delete(save_header); save_header = NULL;
945 cpl_image_delete(refimage); refimage = NULL;
963 cpl_msg_indent_less();
964 cpl_msg_info(recipe,
"Attempt slit identification (optional)...");
965 cpl_msg_indent_more();
971 cpl_table_delete(slits);
978 cpl_table_and_selected_double(slits,
979 "ybottom", CPL_GREATER_THAN, ny-1);
980 cpl_table_or_selected_double(slits,
981 "ytop", CPL_LESS_THAN, 0);
982 cpl_table_erase_selected(slits);
984 nslits = cpl_table_get_nrow(slits);
987 vimos_calib_exit(
"No slits found on the CCD");
989 cpl_msg_info(recipe,
"%d slits are entirely or partially "
990 "contained in CCD", nslits);
995 cpl_msg_info(recipe,
"Global distortion model cannot be computed");
996 if (cpl_error_get_code() != CPL_ERROR_NONE) {
997 vimos_calib_exit(NULL);
1007 cpl_msg_indent_less();
1008 cpl_msg_info(recipe,
"Determining spectral curvature...");
1009 cpl_msg_indent_more();
1011 cpl_msg_info(recipe,
"Tracing master flat field spectra edges...");
1013 startwavelength, endwavelength, dispersion);
1016 vimos_calib_exit(
"Tracing failure");
1018 cpl_msg_info(recipe,
"Fitting flat field spectra edges...");
1022 vimos_calib_exit(
"Trace fitting failure");
1025 cpl_msg_info(recipe,
"Computing global spectral curvature model...");
1029 if (
dfs_save_table(frameset, traces, curv_traces_tag, NULL, parlist,
1031 vimos_calib_exit(NULL);
1033 cpl_table_delete(traces); traces = NULL;
1035 coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1037 startwavelength, endwavelength,
1038 dispersion, 0, coordinate);
1050 cpl_msg_indent_less();
1051 cpl_msg_info(recipe,
"Perform flat field normalisation...");
1052 cpl_msg_indent_more();
1054 norm_flat = cpl_image_duplicate(master_flat);
1057 reference, startwavelength, endwavelength,
1058 dispersion, dradius, ddegree);
1060 cpl_image_delete(smo_flat); smo_flat = NULL;
1063 cpl_propertylist_update_int(save_header,
"ESO PRO DATANCOM", nflats);
1065 cpl_image_turn(norm_flat, rotate_back);
1068 save_header, parlist, recipe, version))
1069 vimos_calib_exit(NULL);
1071 cpl_image_delete(norm_flat); norm_flat = NULL;
1081 double flux, flux_err;
1090 cpl_propertylist_delete(save_header);
1092 cpl_propertylist_update_int(save_header,
"ESO PRO DATANCOM", nflats);
1102 "Product category", instrume))
1103 vimos_calib_exit(
"Cannot write product category to QC log file");
1106 "Archive File Name", instrume))
1107 vimos_calib_exit(
"Missing keyword ARCFILE in flatfield frame");
1110 "Template signature ID", instrume))
1111 vimos_calib_exit(
"Missing keyword TPL ID in flatfield frame");
1114 "Quadrant", instrume))
1115 vimos_calib_exit(
"Missing keyword OCS CON QUAD in flatfield frame");
1118 "Filter", instrume)) {
1119 cpl_msg_error(recipe,
"Missing keyword %s in flatfield frame",
1121 vimos_calib_exit(NULL);
1125 "Grism", instrume)) {
1126 cpl_msg_error(recipe,
"Missing keyword %s in flatfield frame",
1128 vimos_calib_exit(NULL);
1132 "Mask", instrume)) {
1133 cpl_msg_error(recipe,
"Missing keyword %s in flatfield frame",
1135 vimos_calib_exit(NULL);
1138 cpl_propertylist_update_double(save_header,
1139 "ESO PRO WLEN CEN", reference);
1142 "Reference wavelength", instrume))
1143 vimos_calib_exit(
"Missing keyword PRO WLEN CEN in flatfield frame");
1168 pipefile = dfs_generate_filename_tfits(master_norm_flat_tag);
1170 "Pipeline product name", instrume))
1171 vimos_calib_exit(
"Cannot write PIPEFILE to QC log file");
1172 cpl_free(pipefile); pipefile = NULL;
1174 scale = cpl_propertylist_get_double(save_header,
"ESO TEL FOCU SCALE");
1176 if (cpl_error_get_code()) {
1179 cpl_msg_warning(recipe,
"Cannot read keyword TEL FOCU SCALE "
1180 "(defaulted to %f arcsec/mm)", scale);
1187 keyname =
"QC.MOS.SLIT.WIDTH";
1189 slit_width = scale * cpl_table_get(slits,
"ywidth", cslit, NULL);
1192 "Width of slit closest to center",
1194 vimos_calib_exit(
"Cannot write slit width to QC log file");
1199 flux_err /= alltime;
1202 cpl_msg_info(recipe,
1203 "Flux at wavelength %.2f: %.2f +/- %.2f ADU/mm^2/s\n",
1204 reference, flux, flux_err);
1206 keyname =
"QC.MOS.FLAT.FLUX";
1209 "Flux at reference wavelength",
1211 vimos_calib_exit(
"Cannot write QC.MOS.FLAT.FLUX to QC log file");
1214 keyname =
"QC.MOS.FLAT.FLUXERR";
1218 "Error on flux at reference wavelength",
1220 vimos_calib_exit(
"Cannot write QC.MOS.FLAT.FLUXERR to QC log file");
1227 cpl_image_turn(master_flat, rotate_back);
1228 if (
dfs_save_image(frameset, master_flat, master_screen_flat_tag,
1229 save_header, parlist, recipe, version))
1230 vimos_calib_exit(NULL);
1232 cpl_image_delete(master_flat); master_flat = NULL;
1234 cpl_propertylist_delete(save_header); save_header = NULL;
1242 cpl_msg_indent_less();
1243 cpl_msg_info(recipe,
"Perform final wavelength calibration...");
1244 cpl_msg_indent_more();
1246 nx = cpl_image_get_size_x(spatial);
1247 ny = cpl_image_get_size_y(spatial);
1249 idscoeff = cpl_table_new(ny);
1250 restable = cpl_table_new(nlines);
1251 rainbow = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1253 residual = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1254 fiterror = cpl_calloc(ny,
sizeof(
double));
1255 fitlines = cpl_calloc(ny,
sizeof(
int));
1258 dispersion, peakdetection,
1259 wradius, wdegree, wreject,
1260 reference, &startwavelength,
1261 &endwavelength, fitlines,
1262 fiterror, idscoeff, rainbow,
1263 residual, restable, NULL);
1265 if (rectified == NULL)
1266 vimos_calib_exit(
"Wavelength calibration failure.");
1268 if (
dfs_save_table(frameset, restable, disp_residuals_table_tag, NULL,
1269 parlist, recipe, version))
1270 vimos_calib_exit(NULL);
1272 cpl_table_delete(restable); restable = NULL;
1274 cpl_table_wrap_double(idscoeff, fiterror,
"error"); fiterror = NULL;
1275 cpl_table_set_column_unit(idscoeff,
"error",
"pixel");
1276 cpl_table_wrap_int(idscoeff, fitlines,
"nlines"); fitlines = NULL;
1280 const char *clab[6] = {
"c0",
"c1",
"c2",
"c3",
"c4",
"c5"};
1282 int *position = cpl_table_get_data_int (slits,
"position");
1283 int *length = cpl_table_get_data_int (slits,
"length");
1284 double *ytop = cpl_table_get_data_double(slits,
"ytop");
1285 double *ybottom = cpl_table_get_data_double(slits,
"ybottom");
1293 for (j = 0, i = ny - 1; i >= 0; i--) {
1294 if (i < position[j]) {
1297 dr = position[j] + length[j] - i - 1;
1298 irow = floor(ytop[j] - dr*(ytop[j] - ybottom[j])/length[j] + 0.5);
1299 for (k = 0; k <= wdegree; k++) {
1300 cpl_table_set_double(idscoeff, clab[k], i,
1301 cpl_table_get_double(idscoeff_lss, clab[k], irow, NULL));
1303 cpl_table_set_double(idscoeff,
"error", i,
1304 cpl_table_get_double(idscoeff_lss,
"error", irow, NULL));
1305 cpl_table_set_int(idscoeff,
"nlines", i,
1306 cpl_table_get_int(idscoeff_lss,
"nlines", irow, NULL));
1309 cpl_table_delete(idscoeff_lss);
1311 cpl_image_delete(rectified);
1314 startwavelength, endwavelength,
1315 dispersion, idscoeff, 0);
1318 for (i = 0; i < ny; i++)
1319 if (!cpl_table_is_valid(idscoeff,
"c0", i))
1320 cpl_table_set_invalid(idscoeff,
"error", i);
1323 cpl_image_delete(spatial); spatial = NULL;
1326 endwavelength, dispersion, 2);
1328 header = cpl_propertylist_new();
1329 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1330 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1331 cpl_propertylist_update_double(header,
"CRVAL1",
1332 startwavelength + dispersion/2);
1333 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1336 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
1337 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1338 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1339 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1340 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1341 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1344 header, parlist, recipe, version))
1345 vimos_calib_exit(NULL);
1347 cpl_image_delete(delta); delta = NULL;
1348 cpl_propertylist_delete(header); header = NULL;
1353 cpl_msg_info(recipe,
"Mean residual: %f pixel", mean_rms);
1355 mean_rms = cpl_table_get_column_mean(idscoeff,
"error");
1357 cpl_msg_info(recipe,
"Mean model accuracy: %f pixel (%f A)",
1358 mean_rms, mean_rms * dispersion);
1364 cpl_msg_info(recipe,
"Mean spectral resolution: %.2f",
1365 cpl_table_get_column_mean(restab,
"resolution"));
1366 cpl_msg_info(recipe,
"Mean reference lines FWHM: %.2f +/- %.2f pixel",
1367 cpl_table_get_column_mean(restab,
"fwhm") / dispersion,
1368 cpl_table_get_column_mean(restab,
"fwhm_rms") / dispersion);
1375 vimos_calib_exit(
"Cannot reload arc lamp header");
1377 qclist = cpl_propertylist_new();
1387 "Product category", instrume))
1388 vimos_calib_exit(
"Cannot write product category to "
1392 "DPR type", instrume))
1393 vimos_calib_exit(
"Missing keyword DPR TYPE in arc "
1397 "Template", instrume))
1398 vimos_calib_exit(
"Missing keyword TPL ID in arc "
1402 "Grism name", instrume)) {
1403 cpl_msg_error(recipe,
"Missing keyword %s in arc "
1404 "lamp header", key_gris_name);
1405 vimos_calib_exit(NULL);
1409 "Grism identifier", instrume)) {
1410 cpl_msg_error(recipe,
"Missing keyword %s in arc "
1411 "lamp header", key_gris_id);
1412 vimos_calib_exit(NULL);
1415 if (cpl_propertylist_has(header, key_filt_name))
1417 "Filter name", instrume);
1420 "Chip identifier", instrume))
1421 vimos_calib_exit(
"Missing keyword DET CHIP1 ID in arc "
1425 "Archive name of input data",
1427 vimos_calib_exit(
"Missing keyword ARCFILE in arc "
1430 cpl_propertylist_delete(header); header = NULL;
1432 pipefile = dfs_generate_filename_tfits(spectral_resolution_tag);
1434 "Pipeline product name", instrume))
1435 vimos_calib_exit(
"Cannot write PIPEFILE to QC log file");
1436 cpl_free(pipefile); pipefile = NULL;
1443 keyname =
"QC.MOS.RESOLUTION";
1446 cpl_table_get_column_mean(restab,
1450 "Mean spectral resolution",
1452 vimos_calib_exit(
"Cannot write mean spectral resolution to QC "
1456 keyname =
"QC.MOS.RESOLUTION.RMS";
1459 cpl_table_get_column_stdev(restab,
1461 "QC.MOS.RESOLUTION.RMS",
1463 "Scatter of spectral resolution",
1465 vimos_calib_exit(
"Cannot write spectral resolution scatter "
1469 keyname =
"QC.MOS.RESOLUTION.NLINES";
1471 if (fors_qc_write_qc_int(qclist, cpl_table_get_nrow(restab) -
1472 cpl_table_count_invalid(restab,
1474 "QC.MOS.RESOLUTION.NLINES",
1476 "Number of lines for spectral resolution "
1479 vimos_calib_exit(
"Cannot write number of lines used in "
1480 "spectral resolution computation "
1488 if (
dfs_save_table(frameset, restab, spectral_resolution_tag, qclist,
1489 parlist, recipe, version))
1490 vimos_calib_exit(NULL);
1492 cpl_propertylist_delete(qclist); qclist = NULL;
1496 vimos_calib_exit(
"Cannot compute the spectral resolution table");
1498 cpl_vector_delete(lines); lines = NULL;
1501 parlist, recipe, version))
1502 vimos_calib_exit(NULL);
1510 cpl_msg_info(recipe,
"Computing global distortions model");
1512 polytraces, reference);
1524 parlist, recipe, version))
1525 vimos_calib_exit(NULL);
1528 reference, startwavelength,
1529 endwavelength, dispersion,
1531 cpl_table_delete(ctest); ctest = NULL;
1532 cpl_image_delete(itest); itest = NULL;
1534 parlist, recipe, version))
1535 vimos_calib_exit(NULL);
1539 parlist, recipe, version))
1540 vimos_calib_exit(NULL);
1542 cpl_table_delete(dtest); dtest = NULL;
1543 cpl_table_delete(stest); stest = NULL;
1547 if (
dfs_save_table(frameset, global, global_distortion_tag, NULL,
1548 parlist, recipe, version))
1549 vimos_calib_exit(NULL);
1550 cpl_table_delete(global); global = NULL;
1554 cpl_table_delete(maskslits); maskslits = NULL;
1558 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1559 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1560 cpl_propertylist_update_double(header,
"CRVAL1",
1561 startwavelength + dispersion/2);
1562 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1565 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
1566 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1567 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1568 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1569 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1570 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1571 cpl_propertylist_update_int(header,
"ESO PRO DATANCOM", 1);
1583 double flux, flux_err, resol, resol_err;
1595 "Product category", instrume))
1596 vimos_calib_exit(
"Cannot write product category to QC log file");
1599 "Archive File Name", instrume))
1600 vimos_calib_exit(
"Missing keyword ARCFILE in arc lamp frame");
1603 "Template signature ID", instrume))
1604 vimos_calib_exit(
"Missing keyword TPL ID in arc lamp frame");
1607 "Quadrant", instrume))
1608 vimos_calib_exit(
"Missing keyword OCS CON QUAD in arc lamp frame");
1611 "Filter", instrume)) {
1612 cpl_msg_error(recipe,
"Missing keyword %s in arc lamp frame",
1614 vimos_calib_exit(NULL);
1618 "Grism", instrume)) {
1619 cpl_msg_error(recipe,
"Missing keyword %s in arc lamp frame",
1621 vimos_calib_exit(NULL);
1625 "Mask", instrume)) {
1626 cpl_msg_error(recipe,
"Missing keyword %s in arc lamp frame",
1628 vimos_calib_exit(NULL);
1631 cpl_propertylist_update_double(header,
1632 "ESO PRO WLEN CEN", reference);
1635 "Reference wavelength", instrume))
1636 vimos_calib_exit(
"Missing keyword PRO WLEN CEN in arc lamp frame");
1638 pipefile = dfs_generate_filename_tfits(master_norm_flat_tag);
1640 "Pipeline product name", instrume))
1641 vimos_calib_exit(
"Cannot write PIPEFILE to QC log file");
1642 cpl_free(pipefile); pipefile = NULL;
1644 scale = cpl_propertylist_get_double(header,
"ESO TEL FOCU SCALE");
1646 if (cpl_error_get_code()) {
1649 cpl_msg_warning(recipe,
"Cannot read keyword TEL FOCU SCALE "
1650 "(defaulted to %f arcsec/mm)", scale);
1657 keyname =
"QC.MOS.SLIT.WIDTH";
1659 slit_width = scale * cpl_table_get(slits,
"ywidth", cslit, NULL);
1662 "Width of slit closest to center",
1664 vimos_calib_exit(
"Cannot write slit width to QC log file");
1667 if (grism[0] ==
'L') {
1668 if (grism[3] ==
'r') {
1672 lambdaRed = 9122.97;
1673 lambdaYel = 7635.11;
1674 lambdaBlu = 5875.62;
1676 if (grism[3] ==
'b') {
1680 lambdaRed = 6598.95;
1681 lambdaYel = 5015.68;
1682 lambdaBlu = 3888.65;
1686 if (grism[0] ==
'M') {
1690 lambdaRed = 8264.521;
1691 lambdaYel = 6678.200;
1692 lambdaBlu = 5015.675;
1695 if (grism[0] ==
'H') {
1696 if (grism[3] ==
'r') {
1700 lambdaRed = 9122.966;
1701 lambdaYel = 7948.175;
1702 lambdaBlu = 6929.468;
1704 if (grism[3] ==
'o') {
1708 lambdaRed = 7948.175;
1709 lambdaYel = 6929.468;
1710 lambdaBlu = 5875.618;
1712 if (grism[3] ==
'b') {
1716 lambdaRed = 6598.953;
1717 lambdaYel = 5875.618;
1718 lambdaBlu = 5015.675;
1722 if (lambdaHe > 1.) {
1724 startwavelength, dispersion,
1725 4, gain, &flux, &flux_err);
1728 flux_err /= arctime;
1730 cpl_msg_info(recipe,
"Flux of He %.2f: %.2f +/- %.2f ADU/mm^2/s",
1731 lambdaHe, flux, flux_err);
1733 keyname =
"QC.MOS.HE.LAMBDA";
1736 "He arc lamp line for flux determination", instrume)) {
1737 vimos_calib_exit(
"Cannot write He arc line to QC log file");
1740 keyname =
"QC.MOS.HE.FLUX";
1743 "Flux at chosen He wavelength", instrume)) {
1744 vimos_calib_exit(
"Cannot write He flux to QC log file");
1747 keyname =
"QC.MOS.HE.FLUXERR";
1750 "Error on flux at chosen He wavelength", instrume)) {
1751 vimos_calib_exit(
"Cannot write He flux error to QC log file");
1755 cpl_msg_warning(recipe,
1756 "No He lines in %s spectral range: corresponding "
1757 "QC1 parameters are not computed.", grism);
1759 if (lambdaNe > 1.) {
1761 startwavelength, dispersion,
1762 4, gain, &flux, &flux_err);
1765 flux_err /= arctime;
1767 cpl_msg_info(recipe,
"Flux of Ne %.2f: %.2f +/- %.2f ADU/mm^2/s",
1768 lambdaNe, flux, flux_err);
1770 keyname =
"QC.MOS.NE.LAMBDA";
1773 "Ne arc lamp line for flux determination", instrume)) {
1774 vimos_calib_exit(
"Cannot write Ne arc line to QC log file");
1777 keyname =
"QC.MOS.NE.FLUX";
1780 "Flux at chosen Ne wavelength", instrume)) {
1781 vimos_calib_exit(
"Cannot write Ne flux to QC log file");
1784 keyname =
"QC.MOS.NE.FLUXERR";
1787 "Error on flux at chosen Ne wavelength", instrume)) {
1788 vimos_calib_exit(
"Cannot write Ne flux error to QC log file");
1792 cpl_msg_warning(recipe,
1793 "No Ne lines in %s spectral range: corresponding "
1794 "QC1 parameters are not computed.", grism);
1796 if (lambdaAr > 1.) {
1798 startwavelength, dispersion,
1799 4, gain, &flux, &flux_err);
1803 flux_err /= arctime;
1805 cpl_msg_info(recipe,
"Flux of Ar %.2f: %.2f +/- %.2f ADU/mm^2/s",
1806 lambdaAr, flux, flux_err);
1808 keyname =
"QC.MOS.AR.LAMBDA";
1811 "Ar arc lamp line for flux determination", instrume)) {
1812 vimos_calib_exit(
"Cannot write Ar arc line to QC log file");
1815 keyname =
"QC.MOS.AR.FLUX";
1818 "Flux at chosen Ar wavelength", instrume)) {
1819 vimos_calib_exit(
"Cannot write Ar flux to QC log file");
1822 keyname =
"QC.MOS.AR.FLUXERR";
1825 "Error on flux at chosen Ar wavelength", instrume)) {
1826 vimos_calib_exit(
"Cannot write Ar flux error to QC log file");
1830 cpl_msg_warning(recipe,
1831 "No Ar lines in %s spectral range: corresponding "
1832 "QC1 parameters are not computed.", grism);
1838 for (i = 0; i <= wdegree; i++) {
1839 char *label = cpl_sprintf(
"c%d", i);
1848 cslit, label, &mcoeff)) {
1854 keyname = cpl_sprintf(
"QC.MOS.WAVECAL.COEFF%d", i);
1858 unit = cpl_strdup(
"pixel");
1861 unit = cpl_strdup(
"pixel/Angstrom");
1864 unit = cpl_sprintf(
"pixel/Angstrom^%d", i);
1868 comment = cpl_sprintf(
"Median coefficient %d of IDS", i);
1871 unit, comment, instrume)) {
1872 vimos_calib_exit(
"Cannot write IDS coefficient to QC logfile");
1885 keyname =
"QC.MOS.REFWAVE.MEAN";
1888 "MEAN of CCD positions of reference wavelength", instrume)) {
1889 vimos_calib_exit(
"Cannot write QC.MOS.REFWAVE.MEAN to QC logfile");
1892 keyname =
"QC.MOS.REFWAVE.RMS";
1895 "RMS of CCD positions of reference wavelength", instrume)) {
1896 vimos_calib_exit(
"Cannot write QC.MOS.REFWAVE.RMS to QC logfile");
1905 keyname =
"QC.MOS.RESOLUTION1.LAMBDA";
1908 "Line used in spectral resolution determination", instrume)) {
1909 vimos_calib_exit(
"Cannot write arc line to QC log file");
1912 keyname =
"QC.MOS.RESOLUTION1";
1914 cpl_table_and_selected_double(restab,
"wavelength",
1915 CPL_GREATER_THAN, lambdaRed - 1.0);
1917 cpl_table_and_selected_double(restab,
"wavelength",
1918 CPL_LESS_THAN, lambdaRed + 1.0);
1920 if (selected == 1) {
1921 cpl_table *one_line = cpl_table_extract_selected(restab);
1923 resol = cpl_table_get_double(one_line,
1924 "resolution", 0, NULL);
1925 resol_err = cpl_table_get_double(one_line,
1926 "resolution_rms", 0, NULL);
1928 cpl_table_delete(one_line);
1935 cpl_table_select_all(restab);
1937 cpl_msg_info(recipe,
"Spectral resolution at %.2f: %.2f +/- %.2f",
1938 lambdaRed, resol, resol_err);
1941 "Mean spectral resolution at red end of spectrum", instrume)) {
1942 vimos_calib_exit(
"Cannot write spectral resolution "
1946 keyname =
"QC.MOS.RESOLUTION1.RMS";
1949 "Error on mean spectral resolution", instrume)) {
1950 vimos_calib_exit(
"Cannot write error on resolution "
1954 keyname =
"QC.MOS.RESOLUTION2.LAMBDA";
1957 "Line used in spectral resolution determination", instrume)) {
1958 vimos_calib_exit(
"Cannot write arc line to QC log file");
1961 keyname =
"QC.MOS.RESOLUTION2";
1963 cpl_table_and_selected_double(restab,
"wavelength",
1964 CPL_GREATER_THAN, lambdaYel - 1.0);
1966 cpl_table_and_selected_double(restab,
"wavelength",
1967 CPL_LESS_THAN, lambdaYel + 1.0);
1969 if (selected == 1) {
1970 cpl_table *one_line = cpl_table_extract_selected(restab);
1972 resol = cpl_table_get_double(one_line,
1973 "resolution", 0, NULL);
1974 resol_err = cpl_table_get_double(one_line,
1975 "resolution_rms", 0, NULL);
1977 cpl_table_delete(one_line);
1984 cpl_table_select_all(restab);
1986 cpl_msg_info(recipe,
"Spectral resolution at %.2f: %.2f +/- %.2f",
1987 lambdaYel, resol, resol_err);
1990 "Mean spectral resolution at center of spectrum", instrume)) {
1991 vimos_calib_exit(
"Cannot write spectral resolution "
1995 keyname =
"QC.MOS.RESOLUTION2.RMS";
1998 "Error on mean spectral resolution", instrume)) {
1999 vimos_calib_exit(
"Cannot write error on resolution "
2003 keyname =
"QC.MOS.RESOLUTION3.LAMBDA";
2006 "Line used in spectral resolution determination", instrume)) {
2007 vimos_calib_exit(
"Cannot write arc line to QC log file");
2010 keyname =
"QC.MOS.RESOLUTION3";
2012 cpl_table_and_selected_double(restab,
"wavelength",
2013 CPL_GREATER_THAN, lambdaBlu - 1.0);
2015 cpl_table_and_selected_double(restab,
"wavelength",
2016 CPL_LESS_THAN, lambdaBlu + 1.0);
2018 if (selected == 1) {
2019 cpl_table *one_line = cpl_table_extract_selected(restab);
2021 resol = cpl_table_get_double(one_line,
2022 "resolution", 0, NULL);
2023 resol_err = cpl_table_get_double(one_line,
2024 "resolution_rms", 0, NULL);
2026 cpl_table_delete(one_line);
2033 cpl_table_select_all(restab);
2035 cpl_msg_info(recipe,
"Spectral resolution at %.2f: %.2f +/- %.2f",
2036 lambdaBlu, resol, resol_err);
2039 "Mean spectral resolution at blue end of spectrum", instrume)) {
2040 vimos_calib_exit(
"Cannot write spectral resolution "
2044 keyname =
"QC.MOS.RESOLUTION3.RMS";
2047 "Error on mean spectral resolution", instrume)) {
2048 vimos_calib_exit(
"Cannot write error on resolution "
2052 keyname =
"QC.MOS.IDS.RMS";
2055 "Mean accuracy of dispersion solution", instrume)) {
2056 vimos_calib_exit(
"Cannot write mean accuracy of "
2057 "dispersion solution to QC log file");
2065 cpl_free(grism); grism = NULL;
2066 cpl_free(instrume); instrume = NULL;
2067 cpl_table_delete(restab); restab = NULL;
2068 cpl_table_delete(idscoeff); idscoeff = NULL;
2069 cpl_image_delete(spectra); spectra = NULL;
2071 if (
dfs_save_image(frameset, rectified, reduced_lamp_tag, header,
2072 parlist, recipe, version))
2073 vimos_calib_exit(NULL);
2075 cpl_image_delete(rectified); rectified = NULL;
2076 cpl_propertylist_delete(header); header = NULL;
2081 cpl_propertylist_update_double(save_header,
"CRPIX2", 1.0);
2082 cpl_propertylist_update_double(save_header,
"CRVAL2", 1.0);
2084 cpl_propertylist_update_double(save_header,
"CD1_1", 1.0);
2085 cpl_propertylist_update_double(save_header,
"CD1_2", 0.0);
2086 cpl_propertylist_update_double(save_header,
"CD2_1", 0.0);
2087 cpl_propertylist_update_double(save_header,
"CD2_2", 1.0);
2088 cpl_propertylist_update_string(save_header,
"CTYPE1",
"LINEAR");
2089 cpl_propertylist_update_string(save_header,
"CTYPE2",
"PIXEL");
2091 if (
dfs_save_image(frameset, residual, disp_residuals_tag, save_header,
2092 parlist, recipe, version))
2093 vimos_calib_exit(NULL);
2095 cpl_image_delete(residual); residual = NULL;
2096 cpl_propertylist_delete(save_header); save_header = NULL;
2099 if (!treat_as_lss) {
2106 polytraces, reference,
2107 startwavelength, endwavelength,
2110 cpl_image_delete(rainbow); rainbow = NULL;
2115 cpl_image_turn(wavemap, rotate_back);
2116 if (
dfs_save_image(frameset, wavemap, wavelength_map_tag, save_header,
2117 parlist, recipe, version))
2118 vimos_calib_exit(NULL);
2120 cpl_image_delete(wavemap); wavemap = NULL;
2122 cpl_image_turn(coordinate, rotate_back);
2123 if (
dfs_save_image(frameset, coordinate, spatial_map_tag, save_header,
2124 parlist, recipe, version))
2125 vimos_calib_exit(NULL);
2127 cpl_image_delete(coordinate); coordinate = NULL;
2128 cpl_propertylist_delete(save_header); save_header = NULL;
2131 parlist, recipe, version))
2132 vimos_calib_exit(NULL);
2134 cpl_table_delete(polytraces); polytraces = NULL;
2138 parlist, recipe, version))
2139 vimos_calib_exit(NULL);
2141 cpl_table_delete(slits); slits = NULL;
2143 if (cpl_error_get_code()) {
2144 cpl_msg_error(cpl_error_get_where(), cpl_error_get_message());
2145 vimos_calib_exit(NULL);
cpl_image * mos_spatial_calibration(cpl_image *spectra, cpl_table *slits, cpl_table *polytraces, double reference, double blue, double red, double dispersion, int flux, cpl_image *calibration)
Spatial remapping of CCD spectra eliminating the spectral curvature.
cpl_table * mos_build_disp_coeff(cpl_table *global, cpl_table *slits)
Build the IDS coefficients table from a global distortions table.
cpl_image * mos_map_pixel(cpl_table *idscoeff, double reference, double blue, double red, double dispersion, int trend)
Create a pixel map from an IDS coefficients table.
cpl_image * dfs_load_image(cpl_frameset *frameset, const char *category, cpl_type type, int ext, int calib)
Loading image data of given category.
const char * dfs_get_parameter_string(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe string parameter value.
cpl_error_code mos_interpolate_wavecalib(cpl_table *idscoeff, cpl_image *wavemap, int mode, int degree)
Interpolate LSS wavelength calibration.
cpl_image * mos_wavelength_calibration_raw(const cpl_image *image, cpl_vector *lines, double dispersion, float level, int sradius, int order, double reject, double refwave, double *wavestart, double *waveend, int *nlines, double *error, cpl_table *idscoeff, cpl_image *calibration, cpl_image *residuals, cpl_table *restable, cpl_mask *refmask, cpl_table *detected_lines)
Derive wavelength calibration from a raw arc lamp or sky exposure.
double mos_distortions_rms(cpl_image *rectified, cpl_vector *lines, double wavestart, double dispersion, int radius, int highres)
Estimate the spectral distortion modeling goodness.
cpl_propertylist * dfs_load_header(cpl_frameset *frameset, const char *category, int ext)
Loading header associated to data of given category.
cpl_image * mos_normalise_flat(cpl_image *flat, cpl_image *spatial, cpl_table *slits, cpl_table *polytraces, double reference, double blue, double red, double dispersion, int sradius, int polyorder)
Normalise a flat field exposure.
cpl_error_code fors_qc_write_qc_double(cpl_propertylist *header, double value, const char *name, const char *unit, const char *comment, const char *instrument)
Write an integer value to the active QC1 PAF object and to a header.
cpl_error_code mos_rotate_slits(cpl_table *slits, int rotation, int nx, int ny)
Rotate a slit location table.
cpl_image * mos_map_wavelengths(cpl_image *spatial, cpl_image *calibration, cpl_table *slits, cpl_table *polytraces, double reference, double blue, double red, double dispersion)
Remapping of spatially rectified wavelengths to original CCD pixels.
cpl_error_code fors_qc_keyword_to_paf(cpl_propertylist *header, const char *name, const char *unit, const char *comment, const char *instrument)
Copy a keyword value to the currently active QC1 PAF object.
cpl_image * mos_wavelength_calibration(cpl_image *image, double refwave, double firstLambda, double lastLambda, double dispersion, cpl_table *idscoeff, int flux)
Remap at constant wavelength step an image of rectified scientific spectra.
cpl_table * mos_identify_slits(cpl_table *slits, cpl_table *maskslits, cpl_table *global)
Identify slits listed in a slit location table.
cpl_error_code mos_subtract_background(cpl_image *image)
Subtract the background.
cpl_error_code fors_qc_start_group(cpl_propertylist *header, const char *qcdic_version, const char *instrument)
Initiate a new QC1 group.
cpl_image * mos_remove_bias(cpl_image *image, cpl_image *bias, cpl_table *overscans)
Subtract the bias from a CCD exposure.
cpl_table * mos_poly_trace(cpl_table *slits, cpl_table *traces, int order)
Fit spectral traces.
cpl_error_code fors_qc_write_string(const char *name, const char *value, const char *comment, const char *instrument)
Add string parameter to current QC1 group.
int dfs_get_parameter_bool(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe boolean parameter value.
int dfs_equal_keyword(cpl_frameset *frameset, const char *keyword)
Saving table data of given category.
cpl_error_code mos_extract_flux(cpl_image *image, cpl_table *slits, double xwidth, double ywidth, int dx, double gain, double *o_flux, double *o_err)
Measure flux from spectral interval on CCD.
cpl_error_code mos_global_trace(cpl_table *slits, cpl_table *polytraces, int mode)
Recompute tracing coefficients globally.
cpl_image * mos_map_idscoeff(cpl_table *idscoeff, int xsize, double reference, double blue, double red)
Create a wavelengths map from an IDS coefficients table.
int dfs_save_image(cpl_frameset *frameset, const cpl_image *image, const char *category, cpl_propertylist *header, const cpl_parameterlist *parlist, const char *recipename, const char *version)
Saving image data of given category.
cpl_table * dfs_load_table(cpl_frameset *frameset, const char *category, int ext)
Loading table data of given category.
cpl_table * mos_trace_flat(cpl_image *flat, cpl_table *slits, double reference, double blue, double red, double dispersion)
Trace flat field spectra.
cpl_image * mos_wavelength_calibration_final(cpl_image *image, cpl_table *slits, cpl_vector *lines, double dispersion, float level, int sradius, int order, double reject, double refwave, double *wavestart, double *waveend, int *nlines, double *error, cpl_table *idscoeff, cpl_image *calibration, cpl_image *residuals, cpl_table *restable, cpl_table *detected_lines)
Derive wavelength calibration from a rectified arc lamp or sky exposure.
int dfs_get_parameter_int(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe integer parameter value.
int dfs_save_table(cpl_frameset *frameset, const cpl_table *table, const char *category, cpl_propertylist *header, const cpl_parameterlist *parlist, const char *recipename, const char *version)
Saving table data of given category.
cpl_error_code fors_qc_end_group(void)
Close current QC1 PAF file.
cpl_error_code mos_refmask_find_gaps(cpl_mask *refmask, cpl_image *master_flat, double level)
Reconstruct the gaps required for slit location.
cpl_table * mos_global_distortion(cpl_table *slits, cpl_table *maskslits, cpl_table *ids, cpl_table *crv, double reference)
Determine all global distortions models.
cpl_table * mos_resolution_table(cpl_image *image, double startwave, double dispersion, int saturation, cpl_vector *lines)
Compute mean spectral resolution at a given arc lamp line.
cpl_table * mos_load_slits_vimos(cpl_propertylist *header)
Create slit location table from FITS header of VIMOS data.
cpl_table * mos_build_curv_coeff(cpl_table *global, cpl_table *maskslits, cpl_table *slits)
Build the curvature coefficients table from a global distortions table.
cpl_table * mos_locate_spectra(cpl_mask *mask)
Find the location of detected spectra on the CCD.
double dfs_get_parameter_double(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe double parameter value.
cpl_error_code mos_saturation_process(cpl_image *image)
Process saturation.
int mos_slit_closest_to_center(cpl_table *slits, int nx, int ny)
Return slit closest to CCD center.
int vimos_calib_impl(cpl_frameset *frameset, cpl_parameterlist *parlist)
Interpret the command line options and execute the data processing.
cpl_error_code mos_extract_flux_mapped(cpl_image *image, cpl_table *slits, double xwidth, double ywidth, double lambda, double startwave, double dispersion, int dx, double gain, double *o_flux, double *o_err)
Measure flux from spectral interval on remapped frame.
cpl_table * mos_load_overscans_vimos(const cpl_propertylist *header, int check_consistency)
Get the overscan positions from FITS header of VIMOS data.
int mos_median_in_slit(cpl_table *table, cpl_table *slits, int slit, char *label, double *mvalue)
Compute median from a table column section corresponding to a slit.
cpl_table * mos_build_slit_location(cpl_table *global, cpl_table *maskslits, int ysize)
Build the slit location table from a global distortions table.