37#include "eris_utils.h"
38#include "eris_pfits.h"
40#include "eris_ifu_dfs.h"
41#include "eris_ifu_utils.h"
42#include "eris_ifu_error.h"
43#include "eris_ifu_wavecal_static.h"
44#include "eris_ifu_distortion_static.h"
49static const char eris_ifu_wavecal_description[] =
"\
50This recipe performs ERIS/SPIFFIER wavelength calibration data reduction.\n\
52-----------------------------------------------------------------------------\n\
54 DO CATG Explanation Required #Frames\n\
55 ------- ----------- -------- -------\n\
56 WAVE_LAMP Arclamp on/off exposures Y 2 \n\
57 DISTORTION Table with distortion correction parameters Y 1 \n\
58 REF_LINE_ARC Band-specific reference arc line list Y 1 \n\
59 WAVE_SETUP Table to configure wave calibration Y 1 \n\
60 FIRST_WAVE_FIT Table for the first attempt to fit ARClines Y 1 \n\
61 SLITLET_POS Table with slitlet edge positions N [0,1]\n\
62 MASTER_FLAT Optional master flat image N [0,1]\n\
65 DO CATG Explanation\n\
66 ------- -----------\n\
67 WAVE_MAP Wavelength calibrarion map\n\
68----------------------------------------------------------------------------\n\
70Information on relevant parameters may be found with\n\
71 esorex --params "REC_NAME_WAVECAL
"\n\
72 esorex --help "REC_NAME_WAVECAL
"\n";
78cpl_recipe_define(eris_ifu_wavecal, ERIS_BINARY_VERSION,
"Erich Wiezorrek",
79 PACKAGE_BUGREPORT,
"2018",
80 "This recipe performs the wavelength calibration",
81 eris_ifu_wavecal_description);
83cpl_error_code eris_ifu_wavecal_fetch_params(
84 const cpl_parameterlist * parlist,
85 struct stdParamStruct *stdParams );
87cpl_error_code eris_ifu_wavecal_processSof(
89 int exposureCorrectionMode,
90 double saturation_threhold,
92 hdrl_imagelist **arcImages,
95 ifsPreopticsScale *scale,
96 ifsInstrument *instrument,
97 cpl_bivector **slitPos,
101static cpl_propertylist * eris_ifu_wave_get_qc_params(
const ifsBand band,
102 cpl_table* qclog,
struct waveTablesStruct *tables);
104cpl_error_code eris_ifu_wave_save_products(
105 cpl_image *waveCalImg,
106 cpl_propertylist *applist,
107 cpl_frameset *frameset,
108 const cpl_parameterlist *parlist);
123static cpl_error_code eris_ifu_wavecal_fill_parameterlist(cpl_parameterlist *pl)
125 cpl_error_code err = CPL_ERROR_NONE;
133 err = cpl_error_get_code();
147static int eris_ifu_wavecal(cpl_frameset * frameset,
148 const cpl_parameterlist * parlist)
151 int *lampStates = NULL;
152 ifsBand band = UNDEFINED_BAND;
153 ifsPreopticsScale scale = UNDEFINED_SCALE;
154 ifsInstrument instrument = UNSET_INSTRUMENT;
155 struct stdParamStruct stdParams = stdParamStructInit;
157 hdrl_imagelist *arcImages = NULL;
158 const char *refLineTableFileName = NULL;
159 const char *firstFitTableFileName = NULL;
160 const char *waveSetupFileName = NULL;
161 cpl_bivector *slitPos = NULL;
162 cpl_image *waveCalImg = NULL;
163 cpl_propertylist *applist = NULL;
164 struct waveTablesStruct tables;
165 struct waveSetupStruct waveSetup;
166 cpl_table* qclog = NULL;
167 double saturation_threshold = 0;
188 const int nopt_tags = 1;
189 const char* optional_tags[1] = {ERIS_IFU_CALIB_FLATFIELD
191 eris_dfs_check_input_tags(frameset, optional_tags, nopt_tags, 0);
200 cpl_msg_info(cpl_func,
"Reading recipe parameters");
202 eris_ifu_wavecal_fetch_params(parlist, &stdParams));
203 cpl_msg_info(cpl_func,
204 "Instrument is %d, requested product level is %d",
205 stdParams.instrument, stdParams.productDepth);
207 eris_print_rec_status(0);
208 saturation_threshold = cpl_parameter_get_double(
209 cpl_parameterlist_find_const(parlist,
"eris.eris_ifu_wavecal.pixel_saturation"));
210 eris_print_rec_status(1);
212 eris_ifu_wavecal_processSof(
214 stdParams.rawImageCorrectionMask,
215 saturation_threshold,
226 refLineTableFileName = cpl_frame_get_filename(
227 cpl_frameset_find(frameset, ERIS_IFU_CALIB_REF_LINES));
228 firstFitTableFileName = cpl_frame_get_filename(
229 cpl_frameset_find(frameset, ERIS_IFU_CALIB_FIRST_FIT));
230 waveSetupFileName = cpl_frame_get_filename(
231 cpl_frameset_find(frameset, ERIS_IFU_CALIB_WAVE_SETUP));
247 refLineTableFileName,
248 firstFitTableFileName,
251 stdParams.productDepth,
257 if ((stdParams.productDepth & 1) != 0) {
260 waveSetup, frameset, parlist,
261 "eris_ifu_wavecal"));
265 applist = eris_ifu_wave_get_qc_params(band, qclog, &tables);
267 eris_ifu_wave_save_products(waveCalImg, applist, frameset, parlist);
272 if ((stdParams.productDepth & 1) != 0) {
274 waveSetup, frameset, parlist,
279 cpl_table_delete(qclog);
288 return (
int)cpl_error_get_code();
302cpl_error_code eris_ifu_wavecal_fetch_params(
303 const cpl_parameterlist * parlist,
304 struct stdParamStruct *stdParams )
315 return cpl_error_get_code();
336cpl_error_code eris_ifu_wavecal_processSof(
337 cpl_frameset* frames,
338 int exposureCorrectionMode,
339 double saturation_threhold,
341 hdrl_imagelist **arcImages,
344 ifsPreopticsScale *scale,
345 ifsInstrument *instrument,
346 cpl_bivector **slitPos,
350 cpl_frame *frame = NULL;
351 hdrl_image *flatfieldImage = NULL;
352 cpl_image *flatfieldMask;
353 cpl_polynomial *poly_u = NULL;
354 cpl_polynomial *poly_v = NULL;
358 if (frames == NULL) {
362 if (cpl_frameset_is_empty(frames)) {
364 "SOF file is empty or missing");
372 cpl_frameset *arcFrames = NULL;
374 if (cpl_frameset_count_tags(frames, ERIS_IFU_RAW_ARC_LAMP) > 0) {
376 ERIS_IFU_RAW_ARC_LAMP);
377 }
else if ( (cpl_frameset_count_tags(frames, ERIS_IFU_RAW_ARC_LAMP_ON) > 0) &&
378 (cpl_frameset_count_tags(frames, ERIS_IFU_RAW_ARC_LAMP_OFF) > 0) ) {
380 cpl_frameset* arcFrames_off = NULL;
385 cpl_frameset_join(arcFrames, arcFrames_off);
386 cpl_frameset_delete(arcFrames_off);
391 exposureCorrectionMode,
400 cpl_frameset_delete(arcFrames);
403 frame = cpl_frameset_find(frames, ERIS_IFU_CALIB_REF_LINES);
407 "missing \"%s\" tag in the SOF, arc lamp reference lines",
408 ERIS_IFU_CALIB_REF_LINES);
412 frame = cpl_frameset_find(frames, ERIS_IFU_CALIB_FLATFIELD);
414 deqQualityType qualityType;
417 *band, *scale, &flatfieldMask, &qualityType));
418 cpl_msg_info(cpl_func,
"Apply master flat to each input arc frame");
425 frame = cpl_frameset_find(frames, ERIS_IFU_CALIB_DISTORTION);
429 "missing \"%s\" tag in the SOF, distortion polynomials",
430 ERIS_IFU_CALIB_DISTORTION);
432 if (cpl_fits_count_extensions(cpl_frame_get_filename(frame)) > 2) {
433 cpl_polynomial **distortion;
437 cpl_frame_get_filename(frame),
438 &distortion, &borders));
439 cpl_msg_info(cpl_func,
"Correct distortions on each input arc frame");
440 for (cpl_size pos=0; pos<*arcImgCnt; pos++) {
443 inImage, distortion, borders);
447 for (cpl_size sc=0; sc < SLITLET_CNT; sc++) {
448 cpl_polynomial_delete(distortion[sc]);
450 cpl_free(distortion);
451 cpl_table_delete(borders);
456 cpl_frame_get_filename(frame), &poly_u, &poly_v));
459 for (cpl_size pos=0; pos<*arcImgCnt; pos++) {
464 inImage, poly_u, poly_v);
471 frame = cpl_frameset_find(frames, ERIS_IFU_PRO_DIST_SLIT_POS);
475 cpl_frame_get_filename(frame)));
484 return cpl_error_get_code();
497static cpl_propertylist * eris_ifu_wave_get_qc_params(
const ifsBand band,
498 cpl_table* qclog,
struct waveTablesStruct *tables)
500 cpl_propertylist *appList = NULL;
501 const cpl_array *tmpArray = NULL;
502 cpl_vector *coeffVec = NULL;
503 cpl_size coeffDim = 0;
505 char * qcName = NULL;
510 appList = cpl_propertylist_new();
514 coeffDim = cpl_table_get_int(tables->columnCoeffSmoothed,
"degree", 0,
517 nRow = cpl_table_get_nrow(tables->columnCoeffSmoothed);
519 coeffVec = cpl_vector_new(nRow));
520 for (cpl_size ix=0; ix<=coeffDim; ix++) {
521 for (cpl_size row=0; row<nRow; row++) {
522 tmpArray = cpl_table_get_array(
523 tables->columnCoeffSmoothed,
"coeffs", row);
526 cpl_vector_set(coeffVec, row,
527 cpl_array_get_double(tmpArray, ix, NULL));
530 qcName = cpl_sprintf(
"COEF%lld AVG", ix);
533 cpl_vector_get_mean(coeffVec),
534 "Average wavecal Coef");
537 qcName = cpl_sprintf(
"COEF%lld MED", ix);
540 cpl_vector_get_median(coeffVec),
541 "Median wavecal Coef");
547 cpl_table_unselect_all(tables->columnFitting);
549 nRow = cpl_table_or_selected_int(tables->columnFitting, ERIS_IFU_FITTABLE_ERRORCODE,
555 tmpTable= cpl_table_extract_selected(tables->columnFitting);
557 double sigmaMed = cpl_table_get_column_median(tmpTable,
"sigma");
558 double sigmaAvg = cpl_table_get_column_mean(tmpTable,
"sigma");
559 double sigmaRms = cpl_table_get_column_stdev(tmpTable,
"sigma");
560 double resolMed = cpl_table_get_column_median(tmpTable,
"resol");
561 double resolAvg = cpl_table_get_column_mean(tmpTable,
"resol");
562 double resolRms = cpl_table_get_column_stdev(tmpTable,
"resol");
563 cpl_size nRows = cpl_table_get_nrow(tmpTable);
566 double convFactor = 2. * sqrt(2. * log(2.));
569 sigmaAvg * convFactor,
570 "[pix] Average FWHM of found lines");
573 sigmaMed * convFactor,
574 "[pix] Median FWHM of found lines");
577 sigmaRms * convFactor,
578 "[pix] Stdev FWHM of found lines");
581 "Number of lines used tor the fit");
582 double centralLambda = 0;
583 eris_ifu_get_central_lambda(band, ¢ralLambda);
584 double dispersion = 0;
598 "average resolution power");
600 "median resolution power");
602 "stdev resolution power");
605 for(cpl_size i = 0; i < 32; i++) {
609 cpl_table_and_selected_int(tmpTable,
"slitlet", CPL_EQUAL_TO, i);
611 extTable = cpl_table_extract_selected(tmpTable);
612 resolMed = cpl_table_get_column_median(extTable,
"resol");
613 resolAvg = cpl_table_get_column_mean(extTable,
"resol");
614 sigmaMed = cpl_table_get_column_median(extTable,
"sigma");
615 sigmaAvg = cpl_table_get_column_mean(extTable,
"sigma");
616 nRows = cpl_table_get_nrow(extTable);
619 resolRms = cpl_table_get_column_stdev(extTable,
"resol");
620 sigmaRms = cpl_table_get_column_stdev(extTable,
"sigma");
626 keyname = cpl_sprintf(
"SLITLET%lld FWHM AVG", i);
627 keycomm = cpl_sprintf(
"[pix] Average FWHM of found lines on slitlet %lld" ,i);
630 cpl_free(keyname); cpl_free(keycomm);
631 keyname = cpl_sprintf(
"SLITLET%lld FWHM MED", i);
632 keycomm = cpl_sprintf(
"[pix] Median FWHM of found lines on slitlet %lld" ,i);
635 cpl_free(keyname); cpl_free(keycomm);
636 keyname = cpl_sprintf(
"SLITLET%lld FWHM STD", i);
637 keycomm = cpl_sprintf(
"[pix] Stdev FWHM of found lines on slitlet %lld" ,i);
640 cpl_free(keyname); cpl_free(keycomm);
641 keyname = cpl_sprintf(
"SLITLET%lld NFITLINES", i);
642 keycomm = cpl_sprintf(
"Number of lines used for the fit on slitlet %lld" ,i);
644 cpl_free(keyname); cpl_free(keycomm);
668 keyname = cpl_sprintf(
"SLITLET%lld RESOL AVG", i);
669 keycomm = cpl_sprintf(
"average resolution power");
671 cpl_free(keyname); cpl_free(keycomm);
672 keyname = cpl_sprintf(
"SLITLET%lld RESOL MED", i);
673 keycomm = cpl_sprintf(
"median resolution power");
675 cpl_free(keyname); cpl_free(keycomm);
676 keyname = cpl_sprintf(
"SLITLET%lld RESOL STD", i);
677 keycomm = cpl_sprintf(
"stdev resolution power");
679 cpl_free(keyname); cpl_free(keycomm);
681 cpl_table_delete(extTable);
682 cpl_table_select_all(tmpTable);
684 cpl_table_delete(tmpTable);
691 tmpTable= cpl_table_extract_selected(tables->columnFitting));
692 cpl_vector *tWavePosErr =cpl_vector_wrap(nRow,
693 cpl_table_get_data_double(tmpTable,
"wavelengthError"));
694 cpl_vector *vWavePosErr =cpl_vector_duplicate(tWavePosErr);
695 cpl_vector_unwrap(tWavePosErr);
699 cpl_vector_sort(vWavePosErr, CPL_SORT_ASCENDING);
700 double *data = cpl_vector_get_data(vWavePosErr);
701 cpl_vector *cvWavePosErr = cpl_vector_wrap(
702 (cpl_size) ((
double)nRow * .8),
703 &data[(
int) ((
double)nRow * .1)]);
704 double wavePosErrAvg = cpl_vector_get_mean(vWavePosErr);
705 double wavePosErrMed = cpl_vector_get_median(vWavePosErr);
706 double cwavePosErrAvg = cpl_vector_get_mean(cvWavePosErr);
707 double cwavePosErrMed = cpl_vector_get_median(cvWavePosErr);
709 double *vdata = cpl_vector_get_data(vWavePosErr);
710 for (cpl_size ix=0; ix<cpl_vector_get_size(vWavePosErr); ix++) {
711 vdata[ix] =fabs(vdata[ix]);
713 vdata = cpl_vector_get_data(cvWavePosErr);
714 for (cpl_size ix=0; ix<cpl_vector_get_size(cvWavePosErr); ix++) {
715 vdata[ix] =fabs(vdata[ix]);
717 double wavePosErrAvgAbs = cpl_vector_get_mean(vWavePosErr);
718 double wavePosErrMedAbs = cpl_vector_get_median(vWavePosErr);
719 double cwavePosErrAvgAbs = cpl_vector_get_mean(cvWavePosErr);
720 double cwavePosErrMedAbs = cpl_vector_get_median(cvWavePosErr);
723 cpl_vector_unwrap(cvWavePosErr);
724 cpl_vector_delete(vWavePosErr);
728 "[um] Average of reference line position errors");
732 "[um] Median of reference line position errors");
736 "[um] Clean average of reference line position errors");
740 "[um] Clean median of reference line position errors");
744 "[um] Average of reference line position absolute errors");
748 "[um] Median of reference line position absolute errors");
752 "[um] Clean average of reference line position absolute errors");
756 "[um] Clean median of reference line position absolute errors");
781cpl_error_code eris_ifu_wave_save_products(
782 cpl_image *waveCalImg,
783 cpl_propertylist *applist,
784 cpl_frameset *frameset,
785 const cpl_parameterlist *parlist)
791 ERIS_IFU_PRO_WAVE_MAP, ERIS_IFU_PRO_WAVE_MAP_FN,
792 CPL_TYPE_UNSPECIFIED, waveCalImg));
798 return cpl_error_get_code();
cpl_error_code eris_ifu_get_dispersion(ifsBand band, double *dispersion)
Get spectral dispersion for instrument band.
cpl_error_code eris_ifu_wave_get_arc_images(cpl_frameset *arcFrames, int exposureCorrectionMode, int *arcImgCnt, hdrl_imagelist **arcImages, int **lampStates, ifsBand *band, ifsPreopticsScale *scale, ifsInstrument *instrument, double saturation_threshold, cpl_table **qclog)
Load and preprocess arc lamp images for wavelength calibration.
cpl_image * eris_ifu_wave_get_calImg(int arcImagesCnt, hdrl_imagelist *arcImages, int *lampStates, ifsBand band, ifsInstrument instrument, struct waveSetupStruct waveSetup, const char *refLineTableFileName, const char *firstFitTableFileName, cpl_bivector *slitPos, struct waveTablesStruct *tables, int productDepth, cpl_frameset *fs, const cpl_parameterlist *parlist, cpl_table *qclog)
Generate wavelength calibration image from arc lamp data.
void eris_ifu_wave_free_tables(struct waveTablesStruct *tables)
Free all wavelength fitting tables.
void eris_ifu_wave_clear_tables(struct waveTablesStruct *tables)
Clear wavelength table pointers without freeing.
cpl_error_code eris_ifu_wave_init_tables(struct waveTablesStruct *tables)
Initialize wavelength fitting tables.
cpl_error_code eris_ifu_wave_save_fitting_tables(struct waveTablesStruct *tables, ifsInstrument instrument, ifsBand band, struct waveSetupStruct waveSetup, cpl_frameset *frameset, const cpl_parameterlist *parlist, const char *recipe_name)
Save all wavelength fitting tables to FITS file.
cpl_error_code eris_ifu_read_wave_setup(const char *filename, ifsBand band, struct waveSetupStruct *waveSetup)
Read wavelength setup parameters from configuration file.
cpl_error_code eris_ifu_append_qc_double(cpl_propertylist *pl, const char *name, double val, const char *comment)
Append a QC parameter of type DOUBLE to a property list.
cpl_bivector * eris_ifu_load_slit_positions(const char *filename)
Load slitlet position bivector from a table.
cpl_error_code eris_ifu_load_distortion_polynomials(const char *filename, cpl_polynomial ***polynomials, cpl_table **borders)
Load distortion polynomials and slitlet borders from a table.
hdrl_image * eris_ifu_load_cal_image_frame(const cpl_frame *frame, ifsBand band, ifsPreopticsScale scale, cpl_image **qualImage, deqQualityType *qualType)
Load a calibration image from a frame.
cpl_error_code eris_ifu_dfs_set_groups(cpl_frameset *self)
Set the frame group (RAW, CALIB, or PRODUCT) for all frames in a frameset.
cpl_error_code eris_ifu_append_qc_int(cpl_propertylist *pl, const char *name, int val, const char *comment)
Append a QC parameter of type INT to a property list.
cpl_error_code eris_ifu_load_distortion_polynomials_old(const char *filename, cpl_polynomial **poly_u, cpl_polynomial **poly_v)
Load old-format distortion polynomials from a table.
hdrl_image * eris_ifu_dist_warp_image(const hdrl_image *imgIn, cpl_polynomial **poly_u, const cpl_table *borders)
Warp full detector image by warping each slitlet.
#define BRK_IF_ERROR(function)
If function is or returns an error != CPL_ERROR_NONE, then the try-block is exited.
#define CHECK_ERROR_STATE(void)
Check the CPL error state, and exit the try-block if not CPL_ERROR_NONE.
#define BRK_WITH_ERROR_MSG(code,...)
Set a new CPL error, and exit the try-block.
#define TRY
Beginning of a TRY-block.
#define CATCH
End of a TRY-block, beginning of a CATCH-block.
#define BRK_IF_NULL(function)
If function is or returns a NULL pointer, then the try-block is exited.
#define CATCH_MSGS()
Displays an error message stack.
cpl_error_code eris_ifu_fetch_std_param(const cpl_parameterlist *parlist, const char *recipename, struct stdParamStruct *stdParams)
Fetch standard parameters from parameter list into structure.
void eris_ifu_free_std_param(struct stdParamStruct *stdParams)
Free memory allocated for stdParamStruct.
cpl_error_code eris_ifu_add_std_params(cpl_parameterlist *pl, const char *recipename)
Add standard recipe parameters to a parameter list.
hdrl_image * eris_ifu_warp_polynomial_image(const hdrl_image *hdrlInImg, const cpl_polynomial *poly_u, const cpl_polynomial *poly_v)
Warp an HDRL image using 2D polynomial transformations.
void eris_ifu_free_propertylist(cpl_propertylist **item)
Free memory and set pointer to null.
void eris_ifu_free_string(char **item)
Free memory and set pointer to null.
void eris_ifu_free_vector(cpl_vector **item)
Free memory and set pointer to null.
void eris_ifu_free_table(cpl_table **item)
Free memory and set pointer to null.
cpl_error_code eris_pfits_put_qc(cpl_propertylist *plist, cpl_table *qclog)
convert table with QC parameter information to a propertylist
void eris_ifu_free_polynomial(cpl_polynomial **item)
Free memory and set pointer to null.
void eris_ifu_free_int_array(int **item)
Free memory and set pointer to null.
void eris_ifu_free_hdrl_imagelist(hdrl_imagelist **item)
Free memory and set pointer to null.
void eris_ifu_free_hdrl_image(hdrl_image **item)
Free memory and set pointer to null.
void eris_ifu_free_image(cpl_image **item)
Free memory and set pointer to null.
cpl_frameset * eris_ifu_get_frameset_by_tag(const cpl_frameset *frameset, const char *tag)
Get frames with given tag from frameset.
cpl_error_code eris_ifu_save_image(cpl_frameset *fs, const cpl_propertylist *plist, const cpl_parameterlist *parlist, const char *recipe, const char *procatg, const char *filename, cpl_type type, const cpl_image *image)
Save image with DFS compliance.
void eris_ifu_free_bivector(cpl_bivector **item)
Free memory and set pointer to null.
cpl_error_code hdrl_imagelist_set(hdrl_imagelist *himlist, hdrl_image *himg, cpl_size pos)
Insert an image into an imagelist.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
cpl_error_code hdrl_imagelist_div_image(hdrl_imagelist *himlist, const hdrl_image *himg)
Divide an image from an image list.