51#include <eris_utils.h>
52#include "eris_ifu_error.h"
53#include "eris_ifu_utils.h"
54#include "eris_ifu_functions.h"
55#include "eris_ifu_dfs.h"
56#include "eris_ifu_wavecal_static.h"
57#include "eris_ifu_debug.h"
85 cpl_frameset *arcFrames,
86 int exposureCorrectionMode,
88 hdrl_imagelist **arcImages,
91 ifsPreopticsScale *scale,
92 ifsInstrument *instrument,
93 double saturation_threshold,
96 cpl_error_code err = CPL_ERROR_NONE;
97 hdrl_imagelist *arcImagesLocal = NULL;
98 int *lampStatesLocal = NULL;
99 hdrl_image *image = NULL;
100 cpl_table *arcFrameTable = NULL;
101 cpl_table *darkTable = NULL;
102 cpl_table *litTable = NULL;
103 const cpl_frame *frame = NULL;
104 const char *filename;
105 cpl_propertylist *header = NULL;
111 ifsPreopticsScale currScale;
113 const int MaxLampStateSetSize = 16;
118 CPL_ERROR_NULL_INPUT,
119 "Null frameset (ARC frames)!");
121 ASSURE(arcImages != NULL, CPL_ERROR_NULL_INPUT,
"Null arcImages!");
123 ASSURE(qclog != NULL, CPL_ERROR_NULL_INPUT,
"Null qclog!");
124 int frameCnt = (int) cpl_frameset_get_size(arcFrames);
127 "input frameset (ARC frames) is empty");
130 lampStatesLocal = cpl_calloc(MaxLampStateSetSize,
sizeof(
int));
131 *lampStates = lampStatesLocal;
132 *band = UNDEFINED_BAND;
133 *instrument = UNSET_INSTRUMENT;
137 arcFrameTable = cpl_table_new(frameCnt));
138 cpl_table_new_column(arcFrameTable, ERIS_IFU_ARCFRAMR_IDX,
140 cpl_table_new_column(arcFrameTable, ERIS_IFU_ARCFRAME_LAMP,
142 cpl_table_new_column(arcFrameTable, ERIS_IFU_ARCFRAME_DIT,
144 cpl_table_new_column(arcFrameTable, ERIS_IFU_ARCFRAME_FILE,
148 for (
int i=0 ; i<frameCnt ; i++) {
149 frame = cpl_frameset_get_position_const(arcFrames, i);
150 cpl_msg_info(
"wavecal",
"Tag is %s",cpl_frame_get_tag(frame));
152 filename = cpl_frame_get_filename(frame));
154 header = cpl_propertylist_load(filename, 0));
157 if (*band == UNDEFINED_BAND) {
161 if (*band != currBand) {
163 "different instrument band settings"
167 if (*scale == UNDEFINED_SCALE) {
171 if (*scale != currScale) {
173 "different instrument pre-optics settings"
177 if (*instrument == UNSET_INSTRUMENT) {
181 cpl_table_set_int(arcFrameTable, ERIS_IFU_ARCFRAMR_IDX, i, i);
182 cpl_table_set_int(arcFrameTable, ERIS_IFU_ARCFRAME_LAMP, i, lamps);
183 cpl_table_set_float(arcFrameTable, ERIS_IFU_ARCFRAME_DIT, i, dit);
184 cpl_table_set_string(arcFrameTable, ERIS_IFU_ARCFRAME_FILE, i, filename);
189 cpl_propertylist *refList = NULL;
191 refList = cpl_propertylist_new());
193 cpl_propertylist_append_bool(refList,ERIS_IFU_ARCFRAME_LAMP,0));
195 cpl_propertylist_append_bool(refList,ERIS_IFU_ARCFRAME_DIT,0));
197 cpl_table_sort(arcFrameTable, refList));
198 cpl_propertylist_delete(refList);
199 cpl_msg_debug(cpl_func,
"Input arc/dark frames sorted by lamps/dit");
200 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
201 cpl_table_dump(arcFrameTable, 0, frameCnt, stdout);
206 cpl_table_unselect_all(arcFrameTable));
207 cpl_size nDarks = cpl_table_or_selected_int(arcFrameTable, ERIS_IFU_ARCFRAME_LAMP,
210 darkTable = cpl_table_extract_selected(arcFrameTable));
211 nLits = cpl_table_not_selected(arcFrameTable);
213 litTable = cpl_table_extract_selected(arcFrameTable));
214 cpl_table_dump(darkTable, 0, nDarks, stdout);
215 cpl_table_dump(litTable, 0, nLits, stdout);
223 cpl_table* qc_log_tmp;
225 for (
int i=0 ; i<nLits ; i++) {
226 lLampState = cpl_table_get_int(litTable, ERIS_IFU_ARCFRAME_LAMP, i, &isNull);
227 lDit = cpl_table_get_float(litTable, ERIS_IFU_ARCFRAME_DIT, i, &isNull);
228 if (lDit != nDit || lLampState != nLampState) {
229 nLampState = lLampState;
232 cpl_msg_info(cpl_func,
"New lamp/dit state: %d (%s) %f",
233 nLampState, lampString, nDit);
237 darkTable, litTable, lLampState, lDit,
238 exposureCorrectionMode, saturation_threshold, &qc_log_tmp));
242 *lampStatesLocal = lLampState;
245 cpl_size size = cpl_table_get_nrow(*qclog);
246 cpl_table_insert(*qclog, qc_log_tmp, size);
247 cpl_table_delete(qc_log_tmp);
254 err = cpl_error_get_code();
262 *arcImages = arcImagesLocal;
289 cpl_table *darkTable,
293 int exposureCorrectionMode,
297 hdrl_image *arcImage = NULL;
298 hdrl_image *tmpImage = NULL;
299 hdrl_image *litImage = NULL;
300 hdrl_image *darkImage = NULL;
301 hdrl_imagelist *litImageList = NULL;
302 hdrl_imagelist *darkImageList = NULL;
303 cpl_image *contribMap = NULL;
307 const char *filename;
308 hdrl_value mean = {0., 0.};
309 hdrl_value median = {0., 0.};
313 cpl_image* image = NULL;
320 ASSURE((darkTable != NULL) && (litTable != NULL),
321 CPL_ERROR_NULL_INPUT,
322 "One or both input tables are NULL");
324 cpl_table_unselect_all(darkTable));
326 cpl_table_unselect_all(litTable));
327 nDarks = cpl_table_or_selected_float(darkTable, ERIS_IFU_ARCFRAME_DIT,
329 nLits = cpl_table_or_selected_float(litTable, ERIS_IFU_ARCFRAME_DIT,
331 nLits = cpl_table_and_selected_int(litTable, ERIS_IFU_ARCFRAME_LAMP,
332 CPL_EQUAL_TO, lampState);
335 CPL_ERROR_DATA_NOT_FOUND,
336 "No frames with the lamp-on pattern %d found", lampState);
341 for (
int ix=0; ix<cpl_table_get_nrow(litTable); ix++) {
342 if (cpl_table_is_selected(litTable, ix)) {
343 filename = cpl_table_get_string(litTable, ERIS_IFU_ARCFRAME_FILE, ix);
346 exposureCorrectionMode, NULL));
352 cpl_image_threshold(image, threshold, threshold, 0, 1);
353 npixsat = (int) cpl_image_get_flux(image);
355 name = cpl_sprintf(
"QC FRMON%d MEANFLUX",ix);
357 cpl_free(name); name = cpl_sprintf(
"QC FRMON%d MEDIANFLUX",ix);
359 cpl_free(name); name = cpl_sprintf(
"QC FRMON%d MAXFLUX",ix);
361 cpl_free(name); name = cpl_sprintf(
"QC FRMON%d NPIXSAT",ix);
363 cpl_free(name); name = NULL;
368 cpl_image_delete(image);
373 for (
int ix=0; ix<cpl_table_get_nrow(darkTable); ix++) {
374 if (cpl_table_is_selected(darkTable, ix)) {
375 filename = cpl_table_get_string(darkTable, ERIS_IFU_ARCFRAME_FILE, ix);
384 exposureCorrectionMode, NULL));
390 cpl_image_threshold(image, threshold, threshold, 0, 1);
391 npixsat = (int) cpl_image_get_flux(image);
393 name = cpl_sprintf(
"QC FRMOFF%d MEANFLUX",ix);
395 cpl_free(name); name = cpl_sprintf(
"QC FRMOFF%d MEDIANFLUX",ix);
397 cpl_free(name); name = cpl_sprintf(
"QC FRMOFF%d MAXFLUX",ix);
399 cpl_free(name); name = cpl_sprintf(
"QC FRMOFF%d NPIXSAT",ix);
401 cpl_free(name); name = NULL;
405 cpl_image_delete(image);
413 }
else if (nLits >= 3) {
416 litImageList, &litImage, &contribMap));
420 litImageList, &litImage, &contribMap));
430 }
else if (nDarks >= 3) {
433 darkImageList, &darkImage, &contribMap));
437 darkImageList, &darkImage, &contribMap));
446 cpl_image_threshold(image, threshold, threshold, 0, 1);
447 npixsat = (int) cpl_image_get_flux(image);
449 name = cpl_sprintf(
"QC FRMDIFF MEANFLUX");
451 cpl_free(name); name = cpl_sprintf(
"QC FRMDIFF MEDIANFLUX");
453 cpl_free(name); name = cpl_sprintf(
"QC FRMDIFF MAXFLUX");
455 cpl_free(name); name = cpl_sprintf(
"QC FRMDIFF NPIXSAT");
457 cpl_free(name); name = NULL;
458 cpl_image_delete(image);
466 cpl_table_delete(*qclog);
595 hdrl_imagelist *arcImages,
598 ifsInstrument instrument,
599 struct waveSetupStruct waveSetup,
600 const char* refLineTableFileName,
601 const char* firstFitTableFileName,
602 cpl_bivector *slitPos,
603 struct waveTablesStruct *tables,
606 const cpl_parameterlist* parlist,
610 cpl_image *waveCalImg = NULL;
611 const cpl_image **dataImg = NULL;
612 cpl_bivector **refLines = NULL;
613 hdrl_image *arcImg = NULL;
615 double *slitletStart;
617 cpl_image **collapsedSpectra = NULL;
618 cpl_vector *collapsedSpectrum = NULL;
622 cpl_polynomial *firstFit = NULL;
623 cpl_table *firstFitTable = NULL;
624 cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y];
625 const hdrl_image *tmpImg;
626 enum multiArcModes {SUPERIMPOSE, SEPARATE};
627 int multiArcMode = SEPARATE;
631 for (
int ix=0; ix<ERIS_IFU_DETECTOR_SIZE_Y; ix++) {
644 if (multiArcMode == SUPERIMPOSE) {
647 arcImgCnt = arcImagesCnt;
651 dataImg = cpl_calloc(arcImgCnt,
sizeof(cpl_image *)));
653 refLines = cpl_calloc(arcImgCnt,
sizeof(cpl_bivector *)));
655 collapsedSpectra = cpl_calloc(arcImgCnt,
sizeof(cpl_image *)));
657 if (multiArcMode == SUPERIMPOSE) {
660 lampStatus = lampStates[0];
661 for (
int aix = 1; aix< arcImgCnt; aix++) {
662 lampStatus = lampStatus | lampStates[aix];
668 lampStates[0] = lampStatus;
674 for (
int ix = 0; ix < arcImgCnt; ix++) {
682 char* pipe_id = cpl_sprintf(
"%s%s%s", PACKAGE,
"/", PACKAGE_VERSION);
683 cpl_propertylist *applist = cpl_propertylist_new();
685 cpl_propertylist_update_string(applist, CPL_DFS_PRO_CATG,
686 ERIS_IFU_PRO_WAVE_LAMP_STACKED);
687 cpl_dfs_save_propertylist(fs, NULL, parlist, fs, NULL,
688 "eris_ifu_wavecal", applist, NULL,
689 pipe_id, ERIS_IFU_PRO_WAVE_LAMP_STACKED_FN);
694 for (
int ix = 0; ix < arcImgCnt; ix++) {
697 refLineTableFileName, instrument, lampStates[ix]));
700 ERIS_IFU_PRO_WAVE_LAMP_STACKED_FN,
701 CPL_IO_EXTEND, NULL);
703 cpl_propertylist_delete(applist);
705 nRows = cpl_image_get_size_y(dataImg[0]);
706 if (slitPos == NULL) {
708 slitletStart = cpl_calloc(SLITLET_CNT,
sizeof(
double)));
710 slitletEnd = cpl_calloc(SLITLET_CNT,
sizeof(
double)));
711 for (
int mx = 0; mx <SLITLET_CNT; mx++){
712 double tmp = (double) (SLITLET_WIDTH * mx);
713 slitletStart[mx] = tmp;
714 slitletEnd[mx] = tmp + SLITLET_WIDTH -1;
718 slitletStart = cpl_bivector_get_x_data(slitPos));
720 slitletEnd = cpl_bivector_get_y_data(slitPos));
723 for (
int aIdx = 0; aIdx < arcImgCnt; aIdx++) {
724 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
727 (slitletEnd[sIdx] - slitletStart[sIdx]) / 2.);
729 dataImg[aIdx], center);
731 collapsedSpectrum, sIdx, nRows,
732 lampStates[aIdx], band, instrument,
733 refLines[aIdx], productDepth);
740 firstFitTableFileName, instrument, band));
741 cpl_msg_debug(cpl_func,
"First fit table:");
742 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
743 cpl_table_dump(firstFitTable, 0,
744 cpl_table_get_nrow(firstFitTable), stdout);
748 int firstFitMasterOffset;
751 lampStates, arcImgCnt, 16, 0, &firstFitMasterOffset,
752 waveSetup, firstFitTable,
753 tables->slitletFitting, tables->slitletCoeff));
754 cpl_msg_info(__func__,
"FirstFit Master Offset %d", firstFitMasterOffset);
756 for (
int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
757 cpl_polynomial_delete(firstFit);
760 lampStates, arcImgCnt, sIdx, firstFitMasterOffset, &firstFitOffset,
761 waveSetup, firstFitTable,
762 tables->slitletFitting, tables->slitletCoeff));
765 arcImgCnt, dataImg, refLines,
766 waveSetup, firstFit, allFits,
767 tables->columnFitting, tables->columnCoeffRaw,
768 tables->columnCoeffSmoothed, tables->smoothingCoeff);
771 cpl_free(slitletEnd);
772 cpl_free(slitletStart);
777 waveCalImg = cpl_image_new(ERIS_IFU_DETECTOR_SIZE_X,
778 ERIS_IFU_DETECTOR_SIZE_Y, CPL_TYPE_DOUBLE));
779 cpl_image* waveCalErr = cpl_image_new(ERIS_IFU_DETECTOR_SIZE_X,
780 ERIS_IFU_DETECTOR_SIZE_Y, CPL_TYPE_DOUBLE);
783 for (
int col=0; col<ERIS_IFU_DETECTOR_SIZE_X; col++) {
784 for (
int row=0; row<ERIS_IFU_DETECTOR_SIZE_Y; row++) {
785 wave = cpl_polynomial_eval_1d(allFits[col], row, &errs);
787 cpl_image_set(waveCalImg, col+1, row+1, wave));
788 cpl_image_set(waveCalErr, col+1, row+1, errs);
792 cpl_image* img = cpl_image_extract(waveCalImg,1,1024,2048,1024);
794 cpl_image* err = cpl_image_extract(waveCalErr,1,1024,2048,1024);
796 double wcen = cpl_image_get_mean(img);
797 double werr = fabs(cpl_image_get_mean(err));
798 cpl_msg_warning(cpl_func,
"Central wave: %g, %g", wcen, werr);
799 cpl_image_delete(img);
800 cpl_image_delete(err);
801 char* key_name = NULL;
802 char* key_help = NULL;
803 key_name = cpl_sprintf(
"QC WCEN VALUE");
804 key_help = cpl_sprintf(
"[um] Central wavelength value");
810 key_name = cpl_sprintf(
"QC WCEN ERR");
811 key_help = cpl_sprintf(
"[um] Error on central wavelength value");
818 cpl_image_delete(waveCalErr);
825 lampStates, fs, parlist);
838 for (
int ix=0; ix<ERIS_IFU_DETECTOR_SIZE_Y; ix++) {
841 if (dataImg != NULL) {
844 if (refLines != NULL) {
845 for (
int ix=0; ix < arcImgCnt; ix++) {
850 if (collapsedSpectra != NULL) {
851 for (
int ix=0; ix < arcImgCnt; ix++) {
854 cpl_free(collapsedSpectra);
880 const char * refLineTableFileName,
881 ifsInstrument instrument,
884 cpl_bivector *refLines = NULL;
885 cpl_propertylist *header = NULL;
887 const char *instrumentHdr;
889 const char *instrString;
890 char lampString[9] =
"";
891 cpl_vector *wavelength = NULL;
892 cpl_vector *intensity = NULL;
893 cpl_table *refLineTable = NULL;
899 cpl_ensure(refLineTableFileName, CPL_ERROR_NULL_INPUT, NULL);
900 if (access(refLineTableFileName, F_OK)) {
901 cpl_msg_error(cpl_func,
"File %s was not found",
902 refLineTableFileName);
903 cpl_error_set(cpl_func, CPL_ERROR_FILE_NOT_FOUND);
904 cpl_ensure(CPL_FALSE, CPL_ERROR_FILE_NOT_FOUND, NULL);
910 instrString = ERIS_IFU_REFTABLE_SPIFFIER_VAL;
913 instrString = ERIS_IFU_REFTABLE_SPIFFI_VAL;
919 if ((lampState & AR_LAMP) != 0) {
920 strcat(lampString, ERIS_IFU_REFTABLE_ARGON_VAL);
922 if ((lampState & NE_LAMP) != 0) {
923 strcat(lampString, ERIS_IFU_REFTABLE_NEON_VAL);
925 if ((lampState & KR_LAMP) != 0) {
926 strcat(lampString, ERIS_IFU_REFTABLE_KRYPTON_VAL);
928 if ((lampState & XE_LAMP) != 0) {
929 strcat(lampString, ERIS_IFU_REFTABLE_XEON_VAL);
931 exCnt = cpl_fits_count_extensions(refLineTableFileName);
933 for (
int ex=1; ex<exCnt+1; ex++) {
935 header = cpl_propertylist_load(refLineTableFileName, ex));
937 instrumentHdr = cpl_propertylist_get_string(
938 header, ERIS_IFU_REFTABLE_INSTR_HDR));
940 lampHdr = cpl_propertylist_get_string(
941 header, ERIS_IFU_REFTABLE_LAMPS_HDR));
942 if ((strcmp(instrumentHdr, instrString) == 0) &&
943 (strcmp(lampHdr, lampString) == 0)) {
946 refLineTable = cpl_table_load(refLineTableFileName, ex, 0));
947 nRows = cpl_table_get_nrow(refLineTable);
949 wavelength = cpl_vector_new(nRows));
951 intensity = cpl_vector_new(nRows));
952 for (
int rx=0; rx<nRows; rx++) {
953 ignored = cpl_table_get_int(
954 refLineTable, ERIS_IFU_REFTABLE_IGNORED_COLUMN,
957 tmp = cpl_table_get_double(
958 refLineTable, ERIS_IFU_REFTABLE_LAMBDA_COLUMN, rx,
965 cpl_vector_set(wavelength, vx, tmp));
967 tmp = cpl_table_get_double(
968 refLineTable, ERIS_IFU_REFTABLE_INTENSITY_COLUMN,
972 cpl_vector_set(intensity, vx, tmp));
982 if (wavelength == NULL) {
984 "There is no extension in reference lines file %s "
985 "for instrument %s and lamps %s",
986 refLineTableFileName, instrString, lampString);
991 refLines = cpl_bivector_wrap_vectors(
992 cpl_vector_extract(wavelength, 0, vx-1, 1),
993 cpl_vector_extract(intensity, 0, vx-1, 1)));
1026 cpl_vector *spec = NULL;
1028 cpl_vector *slitletRow = NULL;
1029 double *slitletRowData = NULL;
1035 const int halfWidth = 10;
1037 startCol = center - halfWidth;
1038 endCol = center + halfWidth;
1041 nRows = cpl_image_get_size_y(dataImg);
1043 spec = cpl_vector_new(nRows));
1046 slitletRow = cpl_vector_new(halfWidth * 2 + 1));
1048 slitletRowData = cpl_vector_get_data(slitletRow));
1050 for (
int row=0; row<nRows; row++) {
1051 for (
int col=startCol; col<endCol+1; col++) {
1052 tmpData = cpl_image_get(dataImg, col+1, row+1, &isValid);
1057 slitletRowData[col-startCol] = tmpData;
1059 tmpData = cpl_vector_get_median(slitletRow);
1061 cpl_vector_set(spec, row, tmpData));
1100 cpl_image** spectra,
1106 struct waveSetupStruct waveSetup,
1107 cpl_table *firstFitTable,
1108 cpl_table *fittingDumpTable,
1109 cpl_table *coeffDumpTable)
1111 cpl_polynomial *fit = NULL;
1112 cpl_table *blockTable = NULL;
1113 cpl_table *tmpTable = NULL;
1115 cpl_vector *spectrum = NULL;
1119 const int fitLength = 40;
1120 double xData[fitLength];
1121 double yData[fitLength];
1123 struct gaussParStruct gaussPar;
1125 double ffOffsets = 0.;
1126 int ffOffsetCnt = 0;
1128 const int slitlet2collapsed[SLITLET_CNT] = {
1129 0, 15, 1, 16, 2, 17, 3, 18, 4, 19, 5, 20, 6, 21, 7,
1131 22, 8, 23, 9, 24, 10, 25, 11, 26, 12, 27, 13, 28, 14, 29};
1136 cpl_table_unselect_all(firstFitTable));
1138 rowCnt = cpl_table_or_selected_int(firstFitTable,
1139 ERIS_IFU_FIRSTFIT_BLOCK, CPL_EQUAL_TO, slitlet_block[slitlet]);
1143 "no records found in firstFits table with block %d",
1144 slitlet_block[slitlet]);
1146 blockTable = cpl_table_extract_selected(firstFitTable);
1150 for (
int aIdx = 0; aIdx < spectrumCnt; aIdx++) {
1153 cpl_table_unselect_all(blockTable));
1155 rowCnt = cpl_table_or_selected_string(blockTable,
1156 ERIS_IFU_FIRSTFIT_LAMPS, CPL_EQUAL_TO, lampString);
1157 cpl_free(lampString);
1158 tmpTable = cpl_table_extract_selected(blockTable);
1159 dumpRow = cpl_table_get_nrow(fittingDumpTable);
1160 cpl_table_set_size(fittingDumpTable, dumpRow+rowCnt);
1166 spectrum = cpl_vector_new_from_image_column(
1167 spectra[aIdx], slitlet2collapsed[slitlet]+1));
1169 for (
int rx = 0; rx < rowCnt; rx++) {
1170 position = cpl_table_get_int(tmpTable,
1171 ERIS_IFU_FIRSTFIT_POSITION, rx, &isValid);
1172 wavelength = cpl_table_get_double(tmpTable,
1173 ERIS_IFU_FIRSTFIT_WAVELENGTH, rx, &isValid);
1175 if (CPL_ERROR_NONE == eris_ifu_line_gauss_fit(
1176 spectrum, position+ffOffsetIn, waveSetup.s_range, &gaussPar)) {
1177 if ((gaussPar.x0 != 0.) &&
1178 (gaussPar.sigma < 3. || gaussPar.peak > 8000.)){
1179 if (fx < fitLength) {
1180 if (wavelength > 100.) {
1181 wavelength /= 1000.;
1183 xData[fx] = wavelength;
1184 yData[fx] = gaussPar.x0;
1187 ffOffsets += gaussPar.x0 - position;
1190 int range = waveSetup.s_range;
1191 int start = position-(range/2);
1192 if (range <= GAUSS_PAR_RANGE_MAX) {
1193 gaussPar.range = range;
1194 for (
int ix=0; ix<range; ix++) {
1195 gaussPar.xdata[ix] = start+ix;
1196 gaussPar.ydata[ix] = cpl_vector_get(spectrum,start+ix);
1200 const char *lamp = cpl_table_get_string(tmpTable,
1201 ERIS_IFU_FIRSTFIT_LAMPS, rx);
1202 cpl_msg_warning(__func__,
1203 "First line fit failed for "
1204 "slitlet %d at row %d wavelength %.3f for lamp %s",
1205 slitlet, position, wavelength, lamp);
1211 slitlet, slitlet_block[slitlet], aIdx,
1212 position, wavelength,
1218 *ffOffsetOut = (int) (ffOffsets/ffOffsetCnt + .5);
1235 cpl_table_unselect_all(firstFitTable));
1275 const char *recipe_name,
1277 const double *slitletStart,
1278 const double *slitletEnd,
1280 const cpl_image **dataImg,
1281 cpl_bivector **refLines,
1282 struct waveSetupStruct waveSetup,
1283 cpl_polynomial *firstFit,
1284 cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y],
1285 cpl_table *dumpTable,
1286 cpl_table *columnCoeffRawTable,
1287 cpl_table *columnCoeffSmoothedTable,
1288 cpl_table *smoothingCoeffTable)
1290 cpl_error_code err = CPL_ERROR_NONE;
1292 double s1, s2, e1, e2;
1293 cpl_vector *spectrum = NULL;
1294 double *refLinelambda;
1298 cpl_error_code fitErr;
1299 struct gaussParStruct gaussPar;
1300 cpl_size dumpRow = 0;
1301 const int fitLength = 2048;
1302 double xData[fitLength];
1303 double yData[fitLength];
1306 cpl_ensure_code(recipe_name, CPL_ERROR_NULL_INPUT);
1310 if (strcmp(recipe_name, REC_NAME_DISTORTION) == 0) {
1311 start = (int) slitletStart[sIdx];
1312 end = (int) slitletEnd[sIdx];
1314 s2 = slitletStart[sIdx];
1318 s1 = slitletEnd[sIdx-1];
1320 e1 = slitletEnd[sIdx];
1321 if (sIdx == SLITLET_CNT-1) {
1324 e2 = slitletStart[sIdx+1];
1331 start = (int) (((s1 + s2) / 2.0) + .5) + 1;
1333 if (sIdx == SLITLET_CNT-1) {
1336 end = (int) (((e1 + e2) / 2.0) + .5);
1338 cpl_msg_debug(cpl_func,
1339 "Slitlet %2d: start: %4d end: %4d (%7.2f - %7.2f ... %7.2f - %7.2f)",
1340 sIdx, start, end, s1, s2, e1, e2);
1343 for (
int cx = start; cx <= end; cx++) {
1345 for (
int ax = 0; ax< arcImgCnt; ax++) {
1346 nRefLines = cpl_bivector_get_size(refLines[ax]);
1347 refLinelambda = cpl_bivector_get_x_data(refLines[ax]);
1349 dumpRow = cpl_table_get_nrow(dumpTable);
1350 cpl_table_set_size(dumpTable, dumpRow + nRefLines);
1353 spectrum = cpl_vector_new_from_image_column(dataImg[ax], cx+1));
1354 nSpectrum = cpl_vector_get_size(spectrum);
1355 for (
int rx=0; rx<nRefLines; rx++) {
1356 firstGuessPos = (int) (0.5 +
1357 cpl_polynomial_eval_1d(firstFit, refLinelambda[rx], NULL));
1358 if (firstGuessPos > 4+waveSetup.c_range/2 &&
1359 firstGuessPos < (nSpectrum - 4 - waveSetup.c_range/2)) {
1360 fitErr = eris_ifu_line_gauss_fit(
1361 spectrum, firstGuessPos, waveSetup.c_range, &gaussPar);
1362 if ((fitErr == CPL_ERROR_NONE) &&
1363 (gaussPar.offset > -10. - gaussPar.peak / 300. ) &&
1364 (gaussPar.sigma < waveSetup.sigma) &&
1365 (fabs(gaussPar.x0 - firstGuessPos) < 5.01)) {
1366 yData[fx] = refLinelambda[rx];
1367 xData[fx] = gaussPar.x0;
1370 if (fitErr == CPL_ERROR_NONE) {
1371 gaussPar.errorCode = -2;
1376 gaussPar.errorCode = -1;
1378 gaussPar.sigma = 0.;
1380 gaussPar.offset = 0.;
1385 if (gaussPar.errorCode != -1) {
1388 sIdx, cx, ax, firstGuessPos, refLinelambda[rx],
1394 cpl_table_set_size(dumpTable, dumpRow);
1396 if (fx > COLUMN_FIT_DEGREE+1) {
1400 COLUMN_FIT_DEGREE));
1402 cpl_msg_warning(cpl_func,
1403 "Number of found lines (=%d) too small for column %d",
1406 allFits[cx] = cpl_polynomial_new(1);
1407 cpl_size tmpPower = 0;
1408 cpl_polynomial_set_coeff(allFits[cx], &tmpPower, 0.0);
1418 COLUMN_FIT_DEGREE, allFits,
1419 columnCoeffSmoothedTable, smoothingCoeffTable));
1460 cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y],
1461 cpl_table *columnCoeffSmoothedTable,
1462 cpl_table *smoothingCoeffTable)
1464 cpl_error_code retVal = CPL_ERROR_NONE;
1466 const int fitLength = 2048;
1467 double cData[fitLength];
1468 double xData[fitLength];
1469 double yData[fitLength];
1470 cpl_polynomial *smoothFit = NULL;
1471 cpl_size firstCoeff = 0;
1476 for (
int cx = start; cx <= end; cx++) {
1477 if (cpl_polynomial_get_coeff(allFits[cx], &firstCoeff) != 0.) {
1478 cData[nc] = cx + .1;
1479 yData[nc] = cpl_polynomial_eval_1d( allFits[cx], 1024., NULL);
1484 cpl_vector *xVec = cpl_vector_wrap(nc, cData);
1485 cpl_vector *yVec = cpl_vector_wrap(nc, yData);
1486 cpl_bivector *biVec = cpl_bivector_wrap_vectors(xVec, yVec);
1487 cpl_bivector_sort(biVec, biVec, CPL_SORT_ASCENDING, CPL_SORT_BY_Y);
1488 cpl_bivector_unwrap_vectors(biVec);
1489 cpl_vector_unwrap(xVec);
1490 cpl_vector_unwrap(yVec);
1492 for (cpl_size power = 0; power <= fitDegree; power++) {
1493 for (
int ix = 0; ix < nc; ix++) {
1494 int cx = (int) cData[ix];
1496 yData[ix] = cpl_polynomial_get_coeff(allFits[cx], &power);
1502 (COLUMN_FIT_DEGREE + 1) * sIdx + (
int) power,
1503 sIdx, (
int) power, smoothFit);
1504 for (
int cx = start; cx <= end; cx++) {
1505 cpl_polynomial_set_coeff(allFits[cx], &power,
1506 cpl_polynomial_eval_1d(smoothFit, (
double) cx, NULL));
1511 for (
int cx = start; cx <= end; cx++) {
1544 cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y],
1545 cpl_table *fitTable,
1548 cpl_error_code retVal = CPL_ERROR_NONE;
1556 for (cpl_size row=0; row<cpl_table_get_nrow(fitTable); row++) {
1557 if (cpl_table_get_int(fitTable, ERIS_IFU_FITTABLE_ERRORCODE, row, NULL) != 0) {
1560 col = cpl_table_get_int(fitTable,
"index", row, NULL);
1561 val = cpl_table_get_double(fitTable,
"x0", row, NULL);
1562 wave = cpl_polynomial_eval_1d(allFits[col], val, NULL);
1563 waveError = cpl_table_get_double(fitTable, ERIS_IFU_FITTABLE_WAVELENGTH, row, NULL)-
1565 cpl_table_set_double(fitTable,
"wavelengthFit", row, wave);
1566 cpl_table_set_double(fitTable,
"wavelengthError", row, waveError);
1571 double convFactor = 2. * sqrt(2. * log(2.));
1572 cpl_table_duplicate_column(fitTable,
"resol",fitTable,
"wavelengthFit");
1573 cpl_table_divide_columns(fitTable,
"resol",
"sigma");
1574 cpl_table_divide_scalar(fitTable,
"resol", dispersion);
1575 cpl_table_divide_scalar(fitTable,
"resol", convFactor);
1608 cpl_image **collapsedSpectra,
1610 cpl_vector *collapsedSpectrum,
1615 ifsInstrument instrument,
1616 cpl_bivector *refLines,
1619 const double *collapsedSpectrumData = NULL;
1620 static int slitletBlockIdx[SLITLET_BLOCK_CNT];
1634 if((productDepth & 1)) {
1635 cpl_image_save(NULL, ERIS_IFU_PRO_WAVE_COLLAP_SPECTR_FN,
1636 CPL_TYPE_DOUBLE,NULL,CPL_IO_CREATE);
1640 for (
int i=0; i<SLITLET_BLOCK_CNT; i++) {
1641 slitletBlockIdx[i] = 0;
1644 collapsedSpectra[aIdx] = cpl_image_new(SLITLET_CNT, nRows,
1647 collapsedSpectrumData =
1648 cpl_vector_get_data_const(collapsedSpectrum);
1649 switch (slitlet_block[sIdx]) {
1651 columnIdx = slitletBlockIdx[0];
1654 columnIdx = slitletBlockIdx[1] +
1658 columnIdx = slitletBlockIdx[2] +
1659 SLITLET_BLOCK0_CNT + SLITLET_BLOCK1_CNT;
1662 columnIdx = slitletBlockIdx[3] +
1663 SLITLET_BLOCK0_CNT + SLITLET_BLOCK1_CNT +SLITLET_BLOCK2_CNT;
1669 slitletBlockIdx[slitlet_block[sIdx]]++;
1670 for (
int row=0; row<nRows; row++) {
1672 cpl_image_set(collapsedSpectra[aIdx], columnIdx+1, row+1,
1673 collapsedSpectrumData[row]));
1675 if ((sIdx >= SLITLET_CNT-1) && ((productDepth & 1) != 0)) {
1676 const char *instrumentString;
1678 if (instrument == SPIFFI) {
1679 instrumentString =
"SINFONI";
1681 instrumentString =
"ERIS";
1683 cpl_propertylist *hdr = cpl_propertylist_new();
1685 cpl_propertylist_update_string(hdr, CPL_DFS_PRO_CATG,
1686 ERIS_IFU_PRO_WAVE_COLLAP_SPECTR ));
1687 cpl_propertylist_append_string(hdr,
"INSTRUME", instrumentString);
1689 cpl_propertylist_append_string(hdr,
"LAMPS", lampString);
1690 cpl_propertylist_append_string(hdr,
"BAND",
1692 cpl_image_save(collapsedSpectra[aIdx], ERIS_IFU_PRO_WAVE_COLLAP_SPECTR_FN,
1693 CPL_TYPE_UNSPECIFIED, hdr, CPL_IO_EXTEND);
1695 cpl_free(lampString);
1696 cpl_vector_save(cpl_bivector_get_x(refLines), ERIS_IFU_PRO_WAVE_COLLAP_SPECTR_FN,
1697 CPL_TYPE_DOUBLE, NULL, CPL_IO_EXTEND);
1698 cpl_vector_save(cpl_bivector_get_y(refLines), ERIS_IFU_PRO_WAVE_COLLAP_SPECTR_FN,
1699 CPL_TYPE_DOUBLE, NULL, CPL_IO_EXTEND);
1727 const char* firstFitTableFileName,
1728 ifsInstrument instrument,
1732 cpl_table *firstFitTable = NULL;
1733 cpl_table *fullTable = NULL;
1735 const char *instrumentString;
1736 const char* bandString;
1740 if (instrument == SPIFFI) {
1741 instrumentString =
"SINFONI";
1743 instrumentString =
"ERIS";
1748 fullTable = cpl_table_load(firstFitTableFileName, 1, 0));
1750 rowCnt = cpl_table_and_selected_string(fullTable,
1751 ERIS_IFU_FIRSTFIT_INSTRUMENT, CPL_EQUAL_TO, instrumentString);
1755 "no records found in firstFits table with instrument %s",
1759 char *regExp = cpl_sprintf(
"^%s$", bandString);
1760 rowCnt = cpl_table_and_selected_string(fullTable,
1761 ERIS_IFU_FIRSTFIT_BAND, CPL_EQUAL_TO, regExp);
1766 "no records found in firstFits table with band %s",
1769 firstFitTable = cpl_table_extract_selected(fullTable);
1776 return firstFitTable;
1799 *dispersion = DISPERSION_J_SPIFFI;
1802 *dispersion = DISPERSION_H_SPIFFI;
1805 *dispersion = DISPERSION_K_SPIFFI;
1808 *dispersion = DISPERSION_HK_SPIFFI;
1811 *dispersion = DISPERSION_J_LOW;
1814 *dispersion = DISPERSION_J_SHORT;
1817 *dispersion = DISPERSION_J_MIDDLE;
1820 *dispersion = DISPERSION_J_LONG;
1823 *dispersion = DISPERSION_H_LOW;
1826 *dispersion = DISPERSION_H_SHORT;
1829 *dispersion = DISPERSION_H_MIDDLE;
1832 *dispersion = DISPERSION_H_LONG;
1835 *dispersion = DISPERSION_K_LOW;
1838 *dispersion = DISPERSION_K_SHORT;
1841 *dispersion = DISPERSION_K_MIDDLE;
1844 *dispersion = DISPERSION_K_LONG;
1851 return cpl_error_get_code();
1855eris_ifu_get_central_lambda(ifsBand band,
double* centralLambda)
1860 *centralLambda = CENTRALLAMBDA_J_SPIFFI;
1863 *centralLambda = CENTRALLAMBDA_H_SPIFFI;
1866 *centralLambda = CENTRALLAMBDA_K_SPIFFI;
1869 *centralLambda = CENTRALLAMBDA_HK_SPIFFI;
1872 *centralLambda = CENTRALLAMBDA_J_LOW;
1875 *centralLambda = CENTRALLAMBDA_J_SHORT;
1878 *centralLambda = CENTRALLAMBDA_J_MIDDLE;
1881 *centralLambda = CENTRALLAMBDA_J_LONG;
1884 *centralLambda = CENTRALLAMBDA_H_LOW;
1887 *centralLambda = CENTRALLAMBDA_H_SHORT;
1890 *centralLambda = CENTRALLAMBDA_H_MIDDLE;
1893 *centralLambda = CENTRALLAMBDA_H_LONG;
1896 *centralLambda = CENTRALLAMBDA_K_LOW;
1899 *centralLambda = CENTRALLAMBDA_K_SHORT;
1902 *centralLambda = CENTRALLAMBDA_K_MIDDLE;
1905 *centralLambda = CENTRALLAMBDA_K_LONG;
1912 return cpl_error_get_code();
1946 const cpl_image *arcImg,
1947 const cpl_image *waveCalImg,
1951 cpl_propertylist *plist,
1954 cpl_image *resampledImage = NULL;
1955 cpl_vector *arcImgCol = NULL;
1956 cpl_vector *calImgCol = NULL;
1957 double dispersion =0;
1958 double centralLambda = 0;
1959 double *lambdaIn = NULL;
1960 double *lambdaOut = NULL;
1961 double *aduIn = NULL;
1962 double *aduOut = NULL;
1965 char *propName = NULL;
1970 CPL_ERROR_NULL_INPUT,
"no arc image provided");
1971 ASSURE(waveCalImg != NULL,
1972 CPL_ERROR_NULL_INPUT,
"no wavelength calibration image provided");
1973 origNx = cpl_image_get_size_x(arcImg);
1974 origNy = cpl_image_get_size_y(arcImg);
1975 ASSURE(cpl_image_get_size_x(waveCalImg) == origNx,
1976 CPL_ERROR_INCOMPATIBLE_INPUT,
1977 "arc and wavecal image have different size");
1978 ASSURE(cpl_image_get_size_y(waveCalImg) == origNy,
1979 CPL_ERROR_INCOMPATIBLE_INPUT,
1980 "arc and wavecal image have different size");
1983 eris_ifu_get_central_lambda(band, ¢ralLambda);
1985 cpl_size nRows = (cpl_size) ((maxLambda - minLambda) / dispersion + .5);
1986 cpl_size centerRow = nRows / 2;
1987 double startLambda = centralLambda - dispersion * (double) centerRow;
1990 resampledImage = cpl_image_new(origNx, nRows, CPL_TYPE_FLOAT));
1992 lambdaIn = cpl_malloc(
sizeof(
double) * origNy));
1994 aduIn = cpl_malloc(
sizeof(
double) * origNy));
1996 lambdaOut = cpl_malloc(
sizeof(
double) * nRows));
1998 aduOut = cpl_malloc(
sizeof(
double) * nRows));
2001 for (
int rx=0; rx<nRows; rx++) {
2002 lambdaOut[rx] = startLambda + dispersion * (double) rx;
2005 cpl_errorstate errorState;
2006 bool errorHappend =
false;
2008 for (
int cx=0; cx<origNx; cx++) {
2010 arcImgCol = cpl_vector_new_from_image_column(arcImg, cx+1);
2011 calImgCol = cpl_vector_new_from_image_column(waveCalImg, cx+1);
2012 double *arcImgColData = cpl_vector_get_data(arcImgCol);
2013 double *calImgColData = cpl_vector_get_data(calImgCol);
2014 for (
int rx=0; rx<origNy; rx++) {
2015 lambdaIn[rx] = calImgColData[origNy-rx-1];
2016 aduIn[rx] = arcImgColData[origNy-rx-1];
2025 errorState = cpl_errorstate_get();
2027 lambdaOut, aduOut, (
int) nRows, nDegree)
2028 != CPL_ERROR_NONE) {
2029 errorHappend =
true;
2030 cpl_errorstate_set(errorState);
2032 for (
int rx = 0; rx < nRows; rx++) {
2033 cpl_image_set(resampledImage, cx + 1, rx + 1, aduOut[rx]);
2039 cpl_msg_error(__func__,
2040 "One or more columns of the arc images could not be resampled");
2043 propName = cpl_sprintf(
"CTYPE%d", axisNumber);
2044 cpl_propertylist_update_string(plist, propName,
"WAVE");
2046 propName = cpl_sprintf(
"CUNIT%d", axisNumber);
2047 cpl_propertylist_update_string(plist, propName,
"um");
2049 propName = cpl_sprintf(
"CRPIX%d", axisNumber);
2050 cpl_propertylist_update_double(plist, propName, 1.);
2052 propName = cpl_sprintf(
"CRVAL%d", axisNumber);
2053 cpl_propertylist_update_double(plist, propName, lambdaOut[0]);
2055 propName = cpl_sprintf(
"CDELT%d", axisNumber);
2056 cpl_propertylist_update_double(plist, propName, dispersion);
2058 for (
int ix=1; ix<=axisNumber; ix++) {
2059 propName = cpl_sprintf(
"CD%d_%d", axisNumber, ix);
2060 if (ix == axisNumber) {
2061 cpl_propertylist_update_double(plist, propName, dispersion);
2063 cpl_propertylist_update_double(plist, propName, 0.);
2074 resampledImage = NULL;
2080 return resampledImage;
2107 const cpl_image **dataImg,
2108 const cpl_image *waveCalImg,
2111 cpl_frameset* frameset,
2112 const cpl_parameterlist* parlist) {
2114 cpl_error_code retVal = CPL_ERROR_NONE;
2115 cpl_propertylist *plist = NULL;
2116 cpl_image *resampledImg = NULL;
2117 cpl_image *tmpImg = NULL;
2118 double minLambda = 0.;
2119 double maxLambda = 0.;
2124 plist = cpl_propertylist_new());
2126 cpl_propertylist_update_string(plist, CPL_DFS_PRO_CATG,
2127 ERIS_IFU_PRO_WAVE_LAMP_RESAMPLED));
2136 tmpImg = cpl_image_new(1, 1, CPL_TYPE_INT));
2138 char* pipe_id = cpl_sprintf(
"%s%s%s", PACKAGE,
"/", PACKAGE_VERSION);
2139 cpl_dfs_save_image(frameset, NULL, parlist, frameset, NULL, tmpImg,
2140 CPL_TYPE_UNSPECIFIED, REC_NAME_WAVECAL, plist,
"RADECSYS",
2141 pipe_id, ERIS_IFU_PRO_WAVE_LAMP_RESAMPLED_FN);
2143 maxLambda = cpl_image_get_max(waveCalImg);
2144 minLambda = cpl_image_get_min(waveCalImg);
2146 for (
int ix = 0; ix < arcImgCnt; ix++) {
2152 waveCalImg, band, minLambda, maxLambda, plist, 2));
2154 cpl_propertylist_update_string(plist,
"CTYPE1",
"PIXEL");
2155 cpl_propertylist_update_string(plist,
"CUNIT1",
"PIXEL");
2156 cpl_propertylist_update_double(plist,
"CRPIX1", 1.);
2157 cpl_propertylist_update_double(plist,
"CRVAL1", 1.);
2158 cpl_propertylist_update_double(plist,
"CDELT1", 1.);
2160 cpl_propertylist_update_string(plist,
"LAMPS",lamp_string);
2161 cpl_free(lamp_string);
2163 ERIS_IFU_PRO_WAVE_LAMP_RESAMPLED_FN, CPL_IO_EXTEND,plist);
2170 retVal = cpl_error_get_code();
2201 const char* filename,
2203 struct waveSetupStruct *waveSetup)
2205 cpl_error_code retVal = CPL_ERROR_NONE;
2206 cpl_table *table = NULL;
2208 const char* bandName;
2209 const char* rowBandName;
2211 bool invalidColumnFound = FALSE;
2217 (void)memset(waveSetup, 0,
sizeof(*waveSetup));
2220 table = cpl_table_load(filename, 1, 0));
2221 for (row = 0; row<cpl_table_get_nrow(table); row++) {
2222 rowBandName = cpl_table_get_string(table,
"band", row);
2224 if (strcmp(bandName, rowBandName) == 0){
2227 "There are more than row in the WAVE_SETUP with "
2228 "the same band name %s", bandName);
2232 cpl_table_get_double(table,
"fwhm", row, &n);
2234 invalidColumnFound = TRUE;
2236 waveSetup->s_range =
2237 cpl_table_get_int(table,
"s_range", row, &n);
2239 invalidColumnFound = TRUE;
2241 waveSetup->c_range =
2242 cpl_table_get_int(table,
"c_range", row, &n);
2244 invalidColumnFound = TRUE;
2246 waveSetup->ri_dispersion =
2247 cpl_table_get_double(table,
"ri_dispersion", row, &n);
2249 invalidColumnFound = TRUE;
2251 waveSetup->ri_centralLambda =
2252 cpl_table_get_double(table,
"ri_centrallambda", row,&n);
2254 double convFactor = 2. * sqrt(2. * log(2.));
2255 waveSetup->sigma = waveSetup->fwhm / convFactor;
2260 "There is no row in the WAVE_SETUP with the band name %s",
2263 if (invalidColumnFound) {
2265 "There is an invalid column in the WAVE_SETUP "
2266 "with the band name %s",
2296 struct waveTablesStruct *tables)
2298 cpl_ensure_code(tables, CPL_ERROR_NULL_INPUT);
2299 cpl_error_code retVal = CPL_ERROR_NONE;
2303 tables->slitletFitting = NULL;
2304 tables->columnFitting = NULL;
2305 tables->slitletCoeff = NULL;
2306 tables->columnCoeffRaw = NULL;
2307 tables->columnCoeffSmoothed = NULL;
2308 tables->smoothingCoeff = NULL;
2313 SLITLET_CNT, FIRST_FIT_DEGREE);
2315 ERIS_IFU_DETECTOR_SIZE_X, COLUMN_FIT_DEGREE);
2317 ERIS_IFU_DETECTOR_SIZE_X, COLUMN_FIT_DEGREE);
2319 SLITLET_CNT * (COLUMN_FIT_DEGREE + 1), SMOOTH_FIT_DEGREE);
2348 cpl_table *table = NULL;
2353 table = cpl_table_new(0));
2354 cpl_table_new_column(table, ERIS_IFU_FITTABLE_SLITLET, CPL_TYPE_INT);
2355 cpl_table_new_column(table, ERIS_IFU_FITTABLE_INDEX, CPL_TYPE_INT);
2356 cpl_table_new_column(table,
"imgIdx", CPL_TYPE_INT);
2357 cpl_table_new_column(table, ERIS_IFU_FITTABLE_POSITION, CPL_TYPE_INT);
2358 cpl_table_new_column(table, ERIS_IFU_FITTABLE_WAVELENGTH, CPL_TYPE_DOUBLE);
2359 cpl_table_new_column(table, ERIS_IFU_FITTABLE_ERRORCODE, CPL_TYPE_INT);
2360 cpl_table_new_column(table,
"x0", CPL_TYPE_DOUBLE);
2361 cpl_table_new_column(table,
"sigma", CPL_TYPE_DOUBLE);
2362 cpl_table_new_column(table,
"area", CPL_TYPE_DOUBLE);
2363 cpl_table_new_column(table,
"offset", CPL_TYPE_DOUBLE);
2364 cpl_table_new_column(table,
"mse", CPL_TYPE_DOUBLE);
2365 cpl_table_new_column(table,
"wavelengthFit", CPL_TYPE_DOUBLE);
2366 cpl_table_new_column(table,
"wavelengthError", CPL_TYPE_DOUBLE);
2367 cpl_table_new_column(table,
"range", CPL_TYPE_INT);
2368 cpl_table_new_column_array(table,
"xdata", CPL_TYPE_DOUBLE,
2369 GAUSS_PAR_RANGE_MAX);
2370 cpl_table_new_column_array(table,
"ydata", CPL_TYPE_DOUBLE,
2371 GAUSS_PAR_RANGE_MAX);
2409 struct gaussParStruct *gaussPar)
2411 cpl_error_code retVal = CPL_ERROR_NONE;
2417 cpl_table_set_int(table, ERIS_IFU_FITTABLE_SLITLET, row, slitlet);
2418 cpl_table_set_int(table, ERIS_IFU_FITTABLE_INDEX, row, index);
2419 cpl_table_set_int(table,
"imgIdx", row, arcImgIdx);
2420 cpl_table_set_int(table, ERIS_IFU_FITTABLE_POSITION, row, position);
2421 cpl_table_set_double(table, ERIS_IFU_FITTABLE_WAVELENGTH, row, wavelength);
2422 cpl_table_set_int(table, ERIS_IFU_FITTABLE_ERRORCODE, row, gaussPar->errorCode);
2423 cpl_table_set_double(table,
"x0", row, gaussPar->x0);
2424 cpl_table_set_double(table,
"sigma", row, gaussPar->sigma);
2425 cpl_table_set_double(table,
"area", row, gaussPar->area);
2426 cpl_table_set_double(table,
"offset", row, gaussPar->offset);
2427 cpl_table_set_double(table,
"mse", row, gaussPar->mse);
2428 cpl_table_set_int(table,
"range", row, gaussPar->range);
2431 for (
int ix=gaussPar->range; ix<GAUSS_PAR_RANGE_MAX; ix++) {
2432 gaussPar->xdata[ix] = 0.0;
2433 gaussPar->ydata[ix] = 0.0;
2436 xArray = cpl_array_wrap_double(gaussPar->xdata,
2437 GAUSS_PAR_RANGE_MAX));
2439 yArray = cpl_array_wrap_double(gaussPar->ydata,
2440 GAUSS_PAR_RANGE_MAX));
2441 cpl_table_set_array(table,
"xdata", row, xArray);
2442 cpl_table_set_array(table,
"ydata", row, yArray);
2443 cpl_array_unwrap(xArray);
2444 cpl_array_unwrap(yArray);
2469 int size,
int polynomialDegree)
2472 cpl_table *table = NULL;
2477 table = cpl_table_new(size));
2478 cpl_table_new_column(table,
"slitlet", CPL_TYPE_INT);
2479 cpl_table_new_column(table,
"nlines", CPL_TYPE_INT);
2480 cpl_table_new_column(table,
"degree", CPL_TYPE_INT);
2481 cpl_table_new_column_array(table,
"coeffs", CPL_TYPE_DOUBLE,
2482 polynomialDegree+1);
2513 cpl_polynomial *polynomial)
2515 cpl_error_code retVal = CPL_ERROR_NONE;
2522 degree = cpl_polynomial_get_degree(polynomial);
2523 arrayDim = cpl_table_get_column_dimension (table,
"coeffs", 0);
2524 array = cpl_array_new(arrayDim, CPL_TYPE_DOUBLE);
2527 cpl_table_set_int(table,
"slitlet", row, idx);
2528 cpl_table_set_int(table,
"nlines", row, nLines);
2529 cpl_table_set_int(table,
"degree", row, (
int) degree);
2530 for (cpl_size ix=0; ix<=degree; ix++) {
2531 cpl_array_set_double(array, ix,
2532 cpl_polynomial_get_coeff(polynomial, &ix));
2534 cpl_table_set_array(table,
"coeffs", row, array);
2535 cpl_array_delete(array);
2573 struct waveTablesStruct *tables,
2574 ifsInstrument instrument,
2576 struct waveSetupStruct waveSetup,
2577 cpl_frameset* frameset,
2578 const cpl_parameterlist* parlist,
2579 const char* recipe_name)
2581 cpl_error_code retVal = CPL_ERROR_NONE;
2582 cpl_propertylist *phdr = NULL;
2583 cpl_propertylist *hdr = NULL;
2584 const char* filename = ERIS_IFU_PRO_WAVE_FIT_TABLES_FN;
2585 const char* extname =
"EXTNAME";
2586 const char *instrString;
2587 const char *bandString;
2588 int ioMode = CPL_IO_CREATE;
2592 switch (instrument) {
2594 instrString =
"ERIS";
2597 instrString =
"SINFONI";
2600 instrString =
"UNKNOWN";
2606 hdr = cpl_propertylist_new());
2608 phdr = cpl_propertylist_new());
2610 cpl_propertylist_update_string(phdr, CPL_DFS_PRO_CATG,
2611 ERIS_IFU_PRO_WAVE_FIT_TABLES));
2613 cpl_propertylist_update_string(phdr,
"INSTRUME", instrString));
2615 cpl_propertylist_update_string(phdr,
"BAND", bandString));
2617 cpl_propertylist_update_int(phdr,
"SRANGE", waveSetup.s_range));
2619 cpl_propertylist_update_int(phdr,
"CRANGE", waveSetup.c_range));
2621 eris_setup_product_header(filename, ERIS_IFU_PRO_WAVE_FIT_TABLES,
2622 CPL_FRAME_TYPE_IMAGE, recipe_name,
2623 frameset, parlist, phdr);
2625 if (tables->slitletFitting != NULL) {
2627 cpl_propertylist_update_string(
2628 hdr, extname,
"slitletFittingTable"));
2630 cpl_table_name_column(tables->slitletFitting,
"index",
"block"));
2632 cpl_table_save(tables->slitletFitting,
2633 phdr, hdr, filename, ioMode));
2634 ioMode = CPL_IO_EXTEND;
2637 if (tables->columnFitting != NULL) {
2639 cpl_propertylist_update_string(
2640 hdr, extname,
"columnFittingTable"));
2642 cpl_table_name_column(tables->columnFitting,
"index",
"column"));
2644 cpl_table_save(tables->columnFitting,
2645 phdr, hdr, filename, ioMode));
2646 ioMode = CPL_IO_EXTEND;
2649 if (tables->columnCoeffRaw != NULL) {
2651 cpl_propertylist_update_string(
2652 hdr, extname,
"slitletCoeff"));
2654 cpl_table_save(tables->slitletCoeff,
2655 phdr, hdr, filename, ioMode));
2658 cpl_propertylist_update_string(
2659 hdr, extname,
"columnCoeffRaw"));
2661 cpl_table_save(tables->columnCoeffRaw,
2662 phdr, hdr, filename, ioMode));
2663 ioMode = CPL_IO_EXTEND;
2666 if (tables->columnCoeffSmoothed != NULL) {
2668 cpl_propertylist_update_string(
2669 hdr, extname,
"columnCoeffSmoothed"));
2671 cpl_table_name_column(tables->columnCoeffSmoothed,
"nlines",
"dummy"));
2673 cpl_table_save(tables->columnCoeffSmoothed,
2674 phdr, hdr, filename, ioMode));
2675 ioMode = CPL_IO_EXTEND;
2678 if (tables->smoothingCoeff != NULL) {
2680 cpl_propertylist_update_string(
2681 hdr, extname,
"smoothingCoeff"));
2683 cpl_table_name_column(tables->smoothingCoeff,
"nlines",
"order"));
2685 cpl_table_save(tables->smoothingCoeff,
2686 phdr, hdr, filename, ioMode));
2687 ioMode = CPL_IO_EXTEND;
2691 if (ioMode == CPL_IO_CREATE) {
2694 cpl_image_save(NULL, filename, CPL_TYPE_FLOAT, phdr, ioMode));
2716 struct waveTablesStruct *tables)
2737 struct waveTablesStruct *tables)
2739 tables->slitletFitting = NULL;
2740 tables->columnFitting = NULL;
2741 tables->slitletCoeff = NULL;
2742 tables->columnCoeffRaw = NULL;
2743 tables->columnCoeffSmoothed = NULL;
2744 tables->smoothingCoeff = NULL;
cpl_error_code eris_ifu_get_dispersion(ifsBand band, double *dispersion)
Get spectral dispersion for instrument band.
cpl_polynomial * eris_ifu_get_first_fit(cpl_image **spectra, int *lampStates, int spectrumCnt, int slitlet, int ffOffsetIn, int *ffOffsetOut, struct waveSetupStruct waveSetup, cpl_table *firstFitTable, cpl_table *fittingDumpTable, cpl_table *coeffDumpTable)
Generate initial wavelength fit for a slitlet.
cpl_error_code eris_ifu_wave_fill_fitting_table(cpl_table *table, int row, int slitlet, int index, int arcImgIdx, int position, double wavelength, struct gaussParStruct *gaussPar)
Fill fitting table row with Gaussian fit results.
cpl_table * eris_ifu_wave_create_coeff_table(int size, int polynomialDegree)
Create coefficient table for polynomial fits.
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.
void eris_ifu_wave_save_spectrum(cpl_image **collapsedSpectra, int aIdx, cpl_vector *collapsedSpectrum, int sIdx, cpl_size nRows, int lampStatus, ifsBand band, ifsInstrument instrument, cpl_bivector *refLines, int productDepth)
Save collapsed spectrum to product file.
cpl_bivector * eris_ifu_wave_get_refLines(const char *refLineTableFileName, ifsInstrument instrument, int lampState)
Load reference arc line wavelengths for specified lamp configuration.
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.
hdrl_image * eris_ifu_wave_collapse_arc_images(cpl_table *darkTable, cpl_table *litTable, int lampState, float dit, int exposureCorrectionMode, double threshold, cpl_table **qclog)
Collapse multiple arc images with dark subtraction.
cpl_error_code eris_ifu_wave_smooth_coeffs(int sIdx, int start, int end, int fitDegree, cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y], cpl_table *columnCoeffSmoothedTable, cpl_table *smoothingCoeffTable)
Smooth polynomial coefficients across detector columns.
cpl_error_code eris_ifu_save_resampled_arc_images(int arcImgCnt, const cpl_image **dataImg, const cpl_image *waveCalImg, ifsBand band, int *lampStates, cpl_frameset *frameset, const cpl_parameterlist *parlist)
Save resampled arc images as FITS product.
cpl_table * eris_ifu_wave_create_fitting_table(void)
Create fitting table for line fit results.
cpl_error_code eris_ifu_wave_pos_err(cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y], cpl_table *fitTable, ifsBand band)
Compute wavelength errors and spectral resolution.
cpl_error_code eris_ifu_fit_all_lines(const char *recipe_name, int sIdx, const double *slitletStart, const double *slitletEnd, int arcImgCnt, const cpl_image **dataImg, cpl_bivector **refLines, struct waveSetupStruct waveSetup, cpl_polynomial *firstFit, cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y], cpl_table *dumpTable, cpl_table *columnCoeffRawTable, cpl_table *columnCoeffSmoothedTable, cpl_table *smoothingCoeffTable)
Fit all reference lines in a slitlet across detector columns.
void eris_ifu_wave_clear_tables(struct waveTablesStruct *tables)
Clear wavelength table pointers without freeing.
cpl_image * eris_ifu_wave_resampled_arc_image(const cpl_image *arcImg, const cpl_image *waveCalImg, ifsBand band, double minLambda, double maxLambda, cpl_propertylist *plist, int axisNumber)
Resample arc image to uniform wavelength grid.
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_vector * eris_ifu_wave_collapse_slitlet(const cpl_image *dataImg, int center)
Collapse slitlet spatially to create 1D spectrum.
cpl_error_code eris_ifu_read_wave_setup(const char *filename, ifsBand band, struct waveSetupStruct *waveSetup)
Read wavelength setup parameters from configuration file.
cpl_table * eris_ifu_wave_get_firstFitTable(const char *firstFitTableFileName, ifsInstrument instrument, ifsBand band)
Load first fit table for instrument and band.
cpl_error_code eris_ifu_wave_fill_coeff_table(cpl_table *table, int row, int idx, int nLines, cpl_polynomial *polynomial)
Fill coefficient table row with polynomial data.
ifsPreopticsScale eris_ifu_get_preopticsScale(cpl_propertylist *header)
Return the the pre-optics scaling.
float eris_ifu_get_dit(cpl_propertylist *header)
Get the detector integration time (DIT) from FITS header.
ifsInstrument eris_ifu_get_instrument(const cpl_propertylist *header)
Return the used instrument of the FITS file header.
int eris_ifu_get_callamp_status(cpl_propertylist *header)
Return a bit mask indicating which calibration lamps are turned on.
ifsBand eris_ifu_get_band(const cpl_propertylist *header)
Determine preoptic band.
#define ASSURE(condition, error,...)
error handling macro (from fors-pipeline)
#define SET_ERROR_MSG(code, msg)
Set a new error code together with a custom error message.
#define BRK_IF_ERROR(function)
If function is or returns an error != CPL_ERROR_NONE, then the try-block is exited.
#define RECOVER(void)
Recover the error state which was present during TRY (at the beginning of the try-block).
#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 CATCH_MSG()
Displays an error message.
#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_polynomial * eris_ifu_1d_polynomial_fit(int nPoints, double *xdata, double *ydata, int degree)
Fit a 1D polynomial to arrays of data points.
cpl_error_code eris_ifu_1d_interpolation(double *xIn, double *yIn, int nIn, double *xOut, double *yOut, int nOut, const int interType)
Perform 1D interpolation using GSL routines.
hdrl_image * eris_ifu_load_exposure_file(const char *filename, int exposureCorrectionMode, cpl_image *dqi)
Load a raw detector exposure from file with corrections and noise.
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.
char * eris_ifu_get_lampString(int lampStatus)
Convert lamp status bitmask to string.
void eris_ifu_free_double_array(double **item)
Free memory and set pointer to null.
cpl_table * eris_qclog_init(void)
Initialize QC table.
void eris_ifu_free_vector(cpl_vector **item)
Free memory and set pointer to null.
cpl_error_code eris_ifu_save_image_dbg(const cpl_image *img, const char *filename, int create, const cpl_propertylist *pl)
Save image for debugging (quick, no DFS overhead)
void eris_ifu_free_table(cpl_table **item)
Free memory and set pointer to null.
const char * eris_ifu_get_bandString(ifsBand band)
Convert band enum to string.
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.
cpl_error_code eris_qclog_add_double(cpl_table *table, const char *key_name, const double value, const char *key_help)
add QC double info to table
void eris_ifu_free_hdrl_imagelist(hdrl_imagelist **item)
Free memory and set pointer to null.
cpl_error_code eris_qclog_add_int(cpl_table *table, const char *key_name, const int value, const char *key_help)
add QC int info to table
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.
void eris_ifu_free_bivector(cpl_bivector **item)
Free memory and set pointer to null.
cpl_error_code hdrl_image_sub_image(hdrl_image *self, const hdrl_image *other)
Subtract two images, store the result in the first image.
hdrl_value hdrl_image_get_median(const hdrl_image *self)
computes the median and associated error of an image.
cpl_error_code hdrl_image_add_image(hdrl_image *self, const hdrl_image *other)
Add two images, store the result in the first image.
hdrl_image * hdrl_image_duplicate(const hdrl_image *himg)
copy hdrl_image
hdrl_value hdrl_image_get_mean(const hdrl_image *self)
computes mean pixel value and associated error of an image.
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
const cpl_image * hdrl_image_get_image_const(const hdrl_image *himg)
get data as cpl image
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
cpl_error_code hdrl_imagelist_collapse_mean(const hdrl_imagelist *himlist, hdrl_image **out, cpl_image **contrib)
Mean collapsing of image list.
cpl_error_code hdrl_imagelist_set(hdrl_imagelist *himlist, hdrl_image *himg, cpl_size pos)
Insert an image into an imagelist.
void hdrl_imagelist_delete(hdrl_imagelist *himlist)
Free all memory used by a hdrl_imagelist object including the images.
const hdrl_image * hdrl_imagelist_get_const(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
hdrl_imagelist * hdrl_imagelist_new(void)
Create an empty imagelist.
cpl_error_code hdrl_imagelist_collapse_median(const hdrl_imagelist *himlist, hdrl_image **out, cpl_image **contrib)
Median collapsing of image list.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.