ERIS Pipeline Reference Manual 1.8.10
eris_ifu_wavecal_static.c
1/* $Id$
2 *
3 * This file is part of the ERIS Pipeline
4 * Copyright (C) 2002,2003 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
25#include <stdbool.h>
26#include <string.h>
27#include <math.h>
28#include <eris_utils.h>
29#include "eris_ifu_error.h"
30#include "eris_ifu_utils.h"
31#include "eris_ifu_functions.h"
32#include "eris_ifu_dfs.h"
33#include "eris_ifu_wavecal_static.h"
34#include "eris_ifu_debug.h"
35
36cpl_error_code eris_ifu_wave_get_arc_images (
37 cpl_frameset *arcFrames,
38 int exposureCorrectionMode,
39 int *arcImgCnt,
40 hdrl_imagelist **arcImages,
41 int **lampStates,
42 ifsBand *band,
43 ifsPreopticsScale *scale,
44 ifsInstrument *instrument,
45 double saturation_threshold,
46 cpl_table** qclog)
47{
48 cpl_error_code err = CPL_ERROR_NONE;
49 hdrl_imagelist *arcImagesLocal = NULL;
50 int *lampStatesLocal = NULL;
51 hdrl_image *image = NULL;
52 cpl_table *arcFrameTable = NULL;
53 cpl_table *darkTable = NULL;
54 cpl_table *litTable = NULL;
55 const cpl_frame *frame = NULL;
56 const char *filename;
57 cpl_propertylist *header = NULL;
58 int lamps = 0;
59 float dit;
60// cpl_size nDarks;
61 cpl_size nLits;
62 ifsBand currBand;
63 ifsPreopticsScale currScale;
64 // four different lamps make a maximum number of 16 different states
65 const int MaxLampStateSetSize = 16;
66
67 TRY
68 {
69 ASSURE(arcFrames != NULL,
70 CPL_ERROR_NULL_INPUT,
71 "Null frameset (ARC frames)!");
72
73 ASSURE(arcImages != NULL, CPL_ERROR_NULL_INPUT, "Null arcImages!");
74
75 ASSURE(qclog != NULL, CPL_ERROR_NULL_INPUT, "Null qclog!");
76 int frameCnt = (int) cpl_frameset_get_size(arcFrames);
77 if (frameCnt == 0) {
78 SET_ERROR_MSG(CPL_ERROR_NULL_INPUT,
79 "input frameset (ARC frames) is empty");
80 }
81 BRK_IF_NULL(arcImagesLocal = hdrl_imagelist_new());
82 lampStatesLocal = cpl_calloc(MaxLampStateSetSize, sizeof(int));
83 *lampStates = lampStatesLocal;
84 *band = UNDEFINED_BAND;
85 *instrument = UNSET_INSTRUMENT;
86
87 // Create table
89 arcFrameTable = cpl_table_new(frameCnt));
90 cpl_table_new_column(arcFrameTable, ERIS_IFU_ARCFRAMR_IDX,
91 CPL_TYPE_INT);
92 cpl_table_new_column(arcFrameTable, ERIS_IFU_ARCFRAME_LAMP,
93 CPL_TYPE_INT);
94 cpl_table_new_column(arcFrameTable, ERIS_IFU_ARCFRAME_DIT,
95 CPL_TYPE_FLOAT);
96 cpl_table_new_column(arcFrameTable, ERIS_IFU_ARCFRAME_FILE,
97 CPL_TYPE_STRING);
99
100 for (int i=0 ; i<frameCnt ; i++) {
101 frame = cpl_frameset_get_position_const(arcFrames, i);
102 cpl_msg_info("wavecal","Tag is %s",cpl_frame_get_tag(frame));
104 filename = cpl_frame_get_filename(frame));
106 header = cpl_propertylist_load(filename, 0));
107 lamps = eris_ifu_get_callamp_status(header);
108 dit = eris_ifu_get_dit(header);
109 if (*band == UNDEFINED_BAND) {
110 *band = eris_ifu_get_band(header);
111 } else {
112 currBand = eris_ifu_get_band(header);
113 if (*band != currBand) {
114 BRK_WITH_ERROR_MSG(CPL_ERROR_BAD_FILE_FORMAT,
115 "different instrument band settings"
116 " in ARC frames");
117 }
118 }
119 if (*scale == UNDEFINED_SCALE) {
120 *scale = eris_ifu_get_preopticsScale(header);
121 } else {
122 currScale = eris_ifu_get_preopticsScale(header);
123 if (*scale != currScale) {
124 BRK_WITH_ERROR_MSG(CPL_ERROR_BAD_FILE_FORMAT,
125 "different instrument pre-optics settings"
126 " in ARC frames");
127 }
128 }
129 if (*instrument == UNSET_INSTRUMENT) {
130 *instrument = eris_ifu_get_instrument(header);
131 }
133 cpl_table_set_int(arcFrameTable, ERIS_IFU_ARCFRAMR_IDX, i, i);
134 cpl_table_set_int(arcFrameTable, ERIS_IFU_ARCFRAME_LAMP, i, lamps);
135 cpl_table_set_float(arcFrameTable, ERIS_IFU_ARCFRAME_DIT, i, dit);
136 cpl_table_set_string(arcFrameTable, ERIS_IFU_ARCFRAME_FILE, i, filename);
139 }
140
141 cpl_propertylist *refList = NULL;
143 refList = cpl_propertylist_new());
145 cpl_propertylist_append_bool(refList,ERIS_IFU_ARCFRAME_LAMP,0));
147 cpl_propertylist_append_bool(refList,ERIS_IFU_ARCFRAME_DIT,0));
149 cpl_table_sort(arcFrameTable, refList));
150 cpl_propertylist_delete(refList);
151 cpl_msg_debug(cpl_func, "Input arc/dark frames sorted by lamps/dit");
152 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
153 cpl_table_dump(arcFrameTable, 0, frameCnt, stdout);
154 }
156
158 cpl_table_unselect_all(arcFrameTable));
159 cpl_size nDarks = cpl_table_or_selected_int(arcFrameTable, ERIS_IFU_ARCFRAME_LAMP,
160 CPL_EQUAL_TO, 0);
162 darkTable = cpl_table_extract_selected(arcFrameTable));
163 nLits = cpl_table_not_selected(arcFrameTable);
165 litTable = cpl_table_extract_selected(arcFrameTable));
166 cpl_table_dump(darkTable, 0, nDarks, stdout);
167 cpl_table_dump(litTable, 0, nLits, stdout);
169
170 float nDit = -1.;
171 float lDit;
172 int nLampState = 0;
173 int lLampState;
174 int isNull;
175 cpl_table* qc_log_tmp;
176 *qclog = eris_qclog_init();
177 for (int i=0 ; i<nLits ; i++) {
178 lLampState = cpl_table_get_int(litTable, ERIS_IFU_ARCFRAME_LAMP, i, &isNull);
179 lDit = cpl_table_get_float(litTable, ERIS_IFU_ARCFRAME_DIT, i, &isNull);
180 if (lDit != nDit || lLampState != nLampState) {
181 nLampState = lLampState;
182 nDit = lDit;
183 char *lampString = eris_ifu_get_lampString(nLampState);
184 cpl_msg_info(cpl_func,"New lamp/dit state: %d (%s) %f",
185 nLampState, lampString, nDit);
186 eris_ifu_free_string(&lampString);
188 image = eris_ifu_wave_collapse_arc_images(
189 darkTable, litTable, lLampState, lDit,
190 exposureCorrectionMode, saturation_threshold, &qc_log_tmp));
192 hdrl_imagelist_set(arcImagesLocal, image,
193 hdrl_imagelist_get_size(arcImagesLocal)));
194 *lampStatesLocal = lLampState;
195 lampStatesLocal++;
196
197 cpl_size size = cpl_table_get_nrow(*qclog);
198 cpl_table_insert(*qclog, qc_log_tmp, size);
199 cpl_table_delete(qc_log_tmp);
200 }
201 }
202 //hdrl_imagelist_delete(arcImagesLocal);
203 }
204 CATCH
205 {
206 err = cpl_error_get_code();
208 hdrl_imagelist_delete(arcImagesLocal);
209 }
210 eris_ifu_free_table(&arcFrameTable);
211 eris_ifu_free_table(&darkTable);
212 eris_ifu_free_table(&litTable);
213
214 *arcImages = arcImagesLocal;
215 *arcImgCnt = (int) hdrl_imagelist_get_size(arcImagesLocal);
216 return err;
217}
218hdrl_image *eris_ifu_wave_collapse_arc_images(
219 cpl_table *darkTable,
220 cpl_table *litTable,
221 int lampState,
222 float dit,
223 int exposureCorrectionMode,
224 double threshold,
225 cpl_table** qclog)
226{
227 hdrl_image *arcImage = NULL;
228 hdrl_image *tmpImage = NULL;
229 hdrl_image *litImage = NULL;
230 hdrl_image *darkImage = NULL;
231 hdrl_imagelist *litImageList = NULL;
232 hdrl_imagelist *darkImageList = NULL;
233 cpl_image *contribMap = NULL;
234 char* name = NULL;
235 cpl_size nDarks;
236 cpl_size nLits;
237 const char *filename;
238 hdrl_value mean = {0., 0.};
239 hdrl_value median = {0., 0.};
240 double maximum = 0.;
241 int npixsat = 0;
242 //double threshold = 18000.;
243 cpl_image* image = NULL;
244
245
246
247 TRY
248 {
249 *qclog = NULL;
250 ASSURE((darkTable != NULL) && (litTable != NULL),
251 CPL_ERROR_NULL_INPUT,
252 "One or both input tables are NULL");
254 cpl_table_unselect_all(darkTable));
256 cpl_table_unselect_all(litTable));
257 nDarks = cpl_table_or_selected_float(darkTable, ERIS_IFU_ARCFRAME_DIT,
258 CPL_EQUAL_TO, dit);
259 nLits = cpl_table_or_selected_float(litTable, ERIS_IFU_ARCFRAME_DIT,
260 CPL_EQUAL_TO, dit);
261 nLits = cpl_table_and_selected_int(litTable, ERIS_IFU_ARCFRAME_LAMP,
262 CPL_EQUAL_TO, lampState);
264 ASSURE(nLits != 0,
265 CPL_ERROR_DATA_NOT_FOUND,
266 "No frames with the lamp-on pattern %d found", lampState);
267
269 litImageList = hdrl_imagelist_new());
270 *qclog = eris_qclog_init();
271 for (int ix=0; ix<cpl_table_get_nrow(litTable); ix++) {
272 if (cpl_table_is_selected(litTable, ix)) {
273 filename = cpl_table_get_string(litTable, ERIS_IFU_ARCFRAME_FILE, ix);
275 tmpImage = eris_ifu_load_exposure_file(filename,
276 exposureCorrectionMode, NULL));
277
278 mean = hdrl_image_get_mean(tmpImage);
279 median = hdrl_image_get_median(tmpImage);
280 maximum = cpl_image_get_max(hdrl_image_get_image(tmpImage));
281 image = cpl_image_duplicate(hdrl_image_get_image(tmpImage));
282 cpl_image_threshold(image, threshold, threshold, 0, 1);
283 npixsat = (int) cpl_image_get_flux(image);
284
285 name = cpl_sprintf("QC FRMON%d MEANFLUX",ix);
286 eris_qclog_add_double(*qclog, name, mean.data, "[ADU] Average of flux");
287 cpl_free(name); name = cpl_sprintf("QC FRMON%d MEDIANFLUX",ix);
288 eris_qclog_add_double(*qclog, name, median.data, "[ADU] Median of flux");
289 cpl_free(name); name = cpl_sprintf("QC FRMON%d MAXFLUX",ix);
290 eris_qclog_add_double(*qclog, name, maximum, "[ADU] Max of flux");
291 cpl_free(name); name = cpl_sprintf("QC FRMON%d NPIXSAT",ix);
292 eris_qclog_add_int(*qclog, name, npixsat, "Number of saturated pixels");
293 cpl_free(name); name = NULL;
294
296 hdrl_imagelist_set(litImageList, tmpImage,
297 hdrl_imagelist_get_size(litImageList)));
298 cpl_image_delete(image);
299 }
300 }
302 darkImageList = hdrl_imagelist_new());
303 for (int ix=0; ix<cpl_table_get_nrow(darkTable); ix++) {
304 if (cpl_table_is_selected(darkTable, ix)) {
305 filename = cpl_table_get_string(darkTable, ERIS_IFU_ARCFRAME_FILE, ix);
306/*
307 BRK_IF_NULL(
308 image = cpl_image_load(filename, CPL_TYPE_DOUBLE, 0, 0));
309 BRK_IF_NULL(
310 tmpImage = eris_ifu_raw_hdrl_image(image));
311*/
313 tmpImage = eris_ifu_load_exposure_file(filename,
314 exposureCorrectionMode, NULL));
315
316 mean = hdrl_image_get_mean(tmpImage);
317 median = hdrl_image_get_median(tmpImage);
318 maximum = cpl_image_get_max(hdrl_image_get_image(tmpImage));
319 image = cpl_image_duplicate(hdrl_image_get_image(tmpImage));
320 cpl_image_threshold(image, threshold, threshold, 0, 1);
321 npixsat = (int) cpl_image_get_flux(image);
322
323 name = cpl_sprintf("QC FRMOFF%d MEANFLUX",ix);
324 eris_qclog_add_double(*qclog, name, mean.data, "[ADU] Average of flux");
325 cpl_free(name); name = cpl_sprintf("QC FRMOFF%d MEDIANFLUX",ix);
326 eris_qclog_add_double(*qclog, name, median.data, "[ADU] Median of flux");
327 cpl_free(name); name = cpl_sprintf("QC FRMOFF%d MAXFLUX",ix);
328 eris_qclog_add_double(*qclog, name, maximum, "[ADU] Max of flux");
329 cpl_free(name); name = cpl_sprintf("QC FRMOFF%d NPIXSAT",ix);
330 eris_qclog_add_int(*qclog, name, npixsat, "Number of saturated pixels");
331 cpl_free(name); name = NULL;
333 hdrl_imagelist_set(darkImageList, tmpImage,
334 hdrl_imagelist_get_size(darkImageList)));
335 cpl_image_delete(image);
336 }
337 }
338
339 if (nLits == 1) {
341 litImage = hdrl_image_duplicate(
342 hdrl_imagelist_get(litImageList, 0)));
343 } else if (nLits >= 3) {
346 litImageList, &litImage, &contribMap));
347 } else {
350 litImageList, &litImage, &contribMap));
351 }
352
353 arcImage = litImage;
354 litImage = NULL;
355 if (nDarks != 0) {
356 if (nDarks == 1) {
358 darkImage = hdrl_image_duplicate(
359 hdrl_imagelist_get(darkImageList, 0)));
360 } else if (nDarks >= 3) {
363 darkImageList, &darkImage, &contribMap));
364 } else {
367 darkImageList, &darkImage, &contribMap));
368 }
370 hdrl_image_sub_image(arcImage, darkImage));
371
372 mean = hdrl_image_get_mean(arcImage);
373 median = hdrl_image_get_median(arcImage);
374 maximum = cpl_image_get_max(hdrl_image_get_image(arcImage));
375 image = cpl_image_duplicate(hdrl_image_get_image(arcImage));
376 cpl_image_threshold(image, threshold, threshold, 0, 1);
377 npixsat = (int) cpl_image_get_flux(image);
378
379 name = cpl_sprintf("QC FRMDIFF MEANFLUX");
380 eris_qclog_add_double(*qclog, name, mean.data, "[ADU] Average of flux");
381 cpl_free(name); name = cpl_sprintf("QC FRMDIFF MEDIANFLUX");
382 eris_qclog_add_double(*qclog, name, median.data, "[ADU] Median of flux");
383 cpl_free(name); name = cpl_sprintf("QC FRMDIFF MAXFLUX");
384 eris_qclog_add_double(*qclog, name, maximum, "[ADU] Max of flux");
385 cpl_free(name); name = cpl_sprintf("QC FRMDIFF NPIXSAT");
386 eris_qclog_add_int(*qclog, name, npixsat, "Number of saturated pixels");
387 cpl_free(name); name = NULL;
388 cpl_image_delete(image);
389 }
390
391 }
392 CATCH
393 {
394 cpl_free(name);
395 hdrl_image_delete(litImage);
396 cpl_table_delete(*qclog);
397 *qclog = NULL;
398 hdrl_image_delete(arcImage);
399 arcImage = NULL;
400 }
401 eris_ifu_free_hdrl_imagelist(&litImageList);
402 eris_ifu_free_hdrl_imagelist(&darkImageList);
403 eris_ifu_free_hdrl_image(&darkImage);
404 return arcImage;
405}
406
407//static cpl_error_code
408//eris_compute_residuals_fit(cpl_table* tab, cpl_table* qclog)
409//{
410// /* compute QC parameters */
411// cpl_table* xtab = NULL;
412// double mean = 0;
413// double median = 0;
414// double stddev = 0;
415// double min = 0;
416// double max = 0;
417// const char* key_name;
418// const char* key_help;
419
420// for (int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
421// cpl_table_and_selected_int(tab, "slitlet", CPL_EQUAL_TO, sIdx );
422// xtab = cpl_table_extract_selected(tab);
423
424// mean = cpl_table_get_column_mean(xtab, "wavelengthError");
425// key_name = cpl_sprintf("QC WFIT SLICE%d MEAN",sIdx);
426// key_help = cpl_sprintf("[um] Mean error of wave fit for slice %d",sIdx);
427// eris_qclog_add_double(qclog, key_name, mean, key_help);
428
429
430// median = cpl_table_get_column_median(xtab, "wavelengthError");
431// key_name = cpl_sprintf("QC WFIT SLICE%d MEDIAN",sIdx);
432// key_help = cpl_sprintf("[um] Median error of wave fit for slice %d",sIdx);
433// eris_qclog_add_double(qclog, key_name, median, key_help);
434
435// stddev = cpl_table_get_column_stdev(xtab, "wavelengthError");
436// key_name = cpl_sprintf("QC WFIT SLICE%d STDEV",sIdx);
437// key_help = cpl_sprintf("[um] Stdev error of wave fit for slice %d",sIdx);
438// eris_qclog_add_double(qclog, key_name, stddev, key_help);
439
440
441// min = cpl_table_get_column_min(xtab, "wavelengthError");
442// key_name = cpl_sprintf("QC WFIT SLICE%d MIN",sIdx);
443// key_help = cpl_sprintf("[um] Minimum error of wave fit for slice %d",sIdx);
444// eris_qclog_add_double(qclog, key_name, min, key_help);
445
446
447// max = cpl_table_get_column_max(xtab, "wavelengthError");
448// key_name = cpl_sprintf("QC WFIT SLICE%d MAX",sIdx);
449// key_help = cpl_sprintf("[um] Maximum error of wave fit for slice %d",sIdx);
450// eris_qclog_add_double(qclog, key_name, max, key_help);
451
452// cpl_table_select_all(tab);
453// cpl_table_delete(xtab);
454
455// }
456// cpl_table_select_all(tab);
457// mean = cpl_table_get_column_mean(tab, "wavelengthError");
458// key_name = cpl_sprintf("QC WFIT MEAN");
459// key_help = cpl_sprintf("[um] Mean error of wave fit");
460// eris_qclog_add_double(qclog, key_name, mean, key_help);
461
462
463// median = cpl_table_get_column_median(tab, "wavelengthError");
464// key_name = cpl_sprintf("QC WFIT MEDIAN");
465// key_help = cpl_sprintf("[um] Median error of wave fit");
466// eris_qclog_add_double(qclog, key_name, median, key_help);
467
468
469// stddev = cpl_table_get_column_stdev(tab, "wavelengthError");
470// key_name = cpl_sprintf("QC WFIT STDEV");
471// key_help = cpl_sprintf("[um] Stdev error of wave fit");
472// eris_qclog_add_double(qclog, key_name, stddev, key_help);
473
474// min = cpl_table_get_column_min(tab, "wavelengthError");
475// key_name = cpl_sprintf("QC WFIT MIN");
476// key_help = cpl_sprintf("[um] Minimum error of wave fit");
477// eris_qclog_add_double(qclog, key_name, min, key_help);
478
479// max = cpl_table_get_column_max(tab, "wavelengthError");
480// key_name = cpl_sprintf("QC WFIT MAX");
481// key_help = cpl_sprintf("[um] Maximum error of wave fit");
482// eris_qclog_add_double(qclog, key_name, max, key_help);
483// cpl_table_save(qclog,NULL, NULL, "qclog.fits", CPL_IO_CREATE);
484
485// return cpl_error_get_code();
486//}
487
488cpl_image * eris_ifu_wave_get_calImg(
489 int arcImagesCnt,
490 hdrl_imagelist *arcImages,
491 int *lampStates,
492 ifsBand band,
493 ifsInstrument instrument,
494 struct waveSetupStruct waveSetup,
495 const char* refLineTableFileName,
496 const char* firstFitTableFileName,
497 cpl_bivector *slitPos,
498 struct waveTablesStruct *tables,
499 int productDepth,
500 cpl_frameset *fs,
501 const cpl_parameterlist* parlist,
502 cpl_table* qclog)
503{
504 int arcImgCnt;
505 cpl_image *waveCalImg = NULL;
506 const cpl_image **dataImg = NULL;
507 cpl_bivector **refLines = NULL;
508 hdrl_image *arcImg = NULL;
509 int lampStatus = 0;
510 double *slitletStart;
511 double *slitletEnd;
512 cpl_image **collapsedSpectra = NULL;
513 cpl_vector *collapsedSpectrum = NULL;
514// const double *collapsedSpectrumData;
515 cpl_size nRows;
516 int center;
517 cpl_polynomial *firstFit = NULL;
518 cpl_table *firstFitTable = NULL;
519 cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y];
520 const hdrl_image *tmpImg;
521 enum multiArcModes {SUPERIMPOSE, SEPARATE};
522 int multiArcMode = SEPARATE;
523
524 TRY
525 {
526 for (int ix=0; ix<ERIS_IFU_DETECTOR_SIZE_Y; ix++) {
527 allFits[ix] = NULL;
528 }
529
530
531 // If there are more than one arc images two possibilities exist:
532 // a) superimpose all arc images as they were illuminated by a
533 // combination of all lamp states. This can be used if the
534 // different lamps intensities need different DITs but no severe
535 // line blending occurs.
536 // b) work on each arc image independent and combine the lambda/pos
537 // fits at the end.
538
539 if (multiArcMode == SUPERIMPOSE) {
540 arcImgCnt = 1;
541 } else { // SEPARATE
542 arcImgCnt = arcImagesCnt;
543 }
544
546 dataImg = cpl_calloc(arcImgCnt, sizeof(cpl_image *)));
548 refLines = cpl_calloc(arcImgCnt, sizeof(cpl_bivector *)));
550 collapsedSpectra = cpl_calloc(arcImgCnt, sizeof(cpl_image *)));
551
552 if (multiArcMode == SUPERIMPOSE) { //option a)
554 arcImg = hdrl_imagelist_get(arcImages, 0));
555 lampStatus = lampStates[0];
556 for (int aix = 1; aix< arcImgCnt; aix++) {
557 lampStatus = lampStatus | lampStates[aix];
559 tmpImg = hdrl_imagelist_get_const(arcImages, aix));
561 hdrl_image_add_image(arcImg, tmpImg));
562 }
563 lampStates[0] = lampStatus;
564
566 dataImg[0] = hdrl_image_get_image(arcImg));
567
568 } else { // SEPARATE
569 for (int ix = 0; ix < arcImgCnt; ix++) {
571 tmpImg = hdrl_imagelist_get_const(arcImages, ix));
573 dataImg[ix] = hdrl_image_get_image_const(tmpImg));
574 }
575 }
576
577 char* pipe_id = cpl_sprintf("%s%s%s", PACKAGE, "/", PACKAGE_VERSION);
578 cpl_propertylist *applist = cpl_propertylist_new();
579 eris_pfits_put_qc(applist, qclog);
580 cpl_propertylist_update_string(applist, CPL_DFS_PRO_CATG,
581 ERIS_IFU_PRO_WAVE_LAMP_STACKED);
582 cpl_dfs_save_propertylist(fs, NULL, parlist, fs, NULL,
583 "eris_ifu_wavecal", applist, NULL,
584 pipe_id, ERIS_IFU_PRO_WAVE_LAMP_STACKED_FN);
585
586 //BRK_IF_ERROR(
587 // cpl_image_save(NULL,ERIS_IFU_PRO_WAVE_LAMP_STACKED_FN,
588 // CPL_TYPE_DOUBLE,NULL,CPL_IO_CREATE));
589 for (int ix = 0; ix < arcImgCnt; ix++) {
591 refLines[ix] = eris_ifu_wave_get_refLines(
592 refLineTableFileName, instrument, lampStates[ix]));
593 /* AMo: save as final product as requested by QC: PIPE-10189 */
594 eris_ifu_save_image_dbg(dataImg[ix],
595 ERIS_IFU_PRO_WAVE_LAMP_STACKED_FN,
596 CPL_IO_EXTEND, NULL);
597 }
598 cpl_propertylist_delete(applist);
599 cpl_free(pipe_id);
600 nRows = cpl_image_get_size_y(dataImg[0]);
601 if (slitPos == NULL) {
603 slitletStart = cpl_calloc(SLITLET_CNT, sizeof(double)));
605 slitletEnd = cpl_calloc(SLITLET_CNT, sizeof(double)));
606 for (int mx = 0; mx <SLITLET_CNT; mx++){
607 double tmp = (double) (SLITLET_WIDTH * mx);
608 slitletStart[mx] = tmp;
609 slitletEnd[mx] = tmp + SLITLET_WIDTH -1;
610 }
611 } else {
613 slitletStart = cpl_bivector_get_x_data(slitPos));
615 slitletEnd = cpl_bivector_get_y_data(slitPos));
616 }
617
618 for (int aIdx = 0; aIdx < arcImgCnt; aIdx++) {
619 for (int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
620 center = (int) (
621 slitletStart[sIdx] +
622 (slitletEnd[sIdx] - slitletStart[sIdx]) / 2.);
623 collapsedSpectrum = eris_ifu_wave_collapse_slitlet(
624 dataImg[aIdx], center);
625 eris_ifu_wave_save_spectrum(collapsedSpectra, aIdx,
626 collapsedSpectrum, sIdx, nRows,
627 lampStates[aIdx], band, instrument,
628 refLines[aIdx], productDepth);
629 eris_ifu_free_vector(&collapsedSpectrum);
630 }
631 }
632
634 firstFitTable = eris_ifu_wave_get_firstFitTable(
635 firstFitTableFileName, instrument, band));
636 cpl_msg_debug(cpl_func, "First fit table:");
637 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
638 cpl_table_dump(firstFitTable, 0,
639 cpl_table_get_nrow(firstFitTable), stdout);
640 }
641
642 int firstFitOffset;
643 int firstFitMasterOffset;
645 firstFit = eris_ifu_get_first_fit(collapsedSpectra,
646 lampStates, arcImgCnt, 16, 0, &firstFitMasterOffset,
647 waveSetup, firstFitTable,
648 tables->slitletFitting, tables->slitletCoeff));
649 cpl_msg_info(__func__,"FirstFit Master Offset %d", firstFitMasterOffset);
650
651 for (int sIdx = 0; sIdx < SLITLET_CNT; sIdx++) {
652 cpl_polynomial_delete(firstFit);
654 firstFit = eris_ifu_get_first_fit(collapsedSpectra,
655 lampStates, arcImgCnt, sIdx, firstFitMasterOffset, &firstFitOffset,
656 waveSetup, firstFitTable,
657 tables->slitletFitting, tables->slitletCoeff));
658
659 eris_ifu_fit_all_lines(REC_NAME_WAVECAL, sIdx, slitletStart, slitletEnd,
660 arcImgCnt, dataImg, refLines,
661 waveSetup, firstFit, allFits,
662 tables->columnFitting, tables->columnCoeffRaw,
663 tables->columnCoeffSmoothed, tables->smoothingCoeff);
664
665 }
666 cpl_free(slitletEnd);
667 cpl_free(slitletStart);
668 BRK_IF_NULL(firstFitTable);
669
670 // create wave cal image
672 waveCalImg = cpl_image_new(ERIS_IFU_DETECTOR_SIZE_X,
673 ERIS_IFU_DETECTOR_SIZE_Y, CPL_TYPE_DOUBLE));
674 cpl_image* waveCalErr = cpl_image_new(ERIS_IFU_DETECTOR_SIZE_X,
675 ERIS_IFU_DETECTOR_SIZE_Y, CPL_TYPE_DOUBLE);
676 double errs = 0;
677 double wave = 0;
678 for (int col=0; col<ERIS_IFU_DETECTOR_SIZE_X; col++) {
679 for (int row=0; row<ERIS_IFU_DETECTOR_SIZE_Y; row++) {
680 wave = cpl_polynomial_eval_1d(allFits[col], row, &errs);
682 cpl_image_set(waveCalImg, col+1, row+1, wave));
683 cpl_image_set(waveCalErr, col+1, row+1, errs);
684 }
685 }
686
687 cpl_image* img = cpl_image_extract(waveCalImg,1,1024,2048,1024);
688
689 cpl_image* err = cpl_image_extract(waveCalErr,1,1024,2048,1024);
690
691 double wcen = cpl_image_get_mean(img);
692 double werr = fabs(cpl_image_get_mean(err));
693 cpl_msg_warning(cpl_func,"Central wave: %g, %g", wcen, werr);
694 cpl_image_delete(img);
695 cpl_image_delete(err);
696 char* key_name = NULL;
697 char* key_help = NULL;
698 key_name = cpl_sprintf("QC WCEN VALUE");
699 key_help = cpl_sprintf("[um] Central wavelength value");
700 eris_qclog_add_double(qclog, key_name, wcen, key_help);
701
702 cpl_free(key_name);
703 cpl_free(key_help);
704
705 key_name = cpl_sprintf("QC WCEN ERR");
706 key_help = cpl_sprintf("[um] Error on central wavelength value");
707 eris_qclog_add_double(qclog, key_name, werr, key_help);
708 cpl_free(key_name);
709 cpl_free(key_help);
710
711
712 //cpl_image_save(waveCalErr,"waveCalErr.fits",CPL_TYPE_DOUBLE,NULL,CPL_IO_DEFAULT);
713 cpl_image_delete(waveCalErr);
714 /* AMo: save as final product as requested by QC: PIPE-10189 */
715 eris_ifu_save_resampled_arc_images(
716 arcImgCnt,
717 dataImg,
718 waveCalImg,
719 band,
720 lampStates, fs, parlist);
721
722 // calculate position errors and store them in FIT table
724 eris_ifu_wave_pos_err(allFits, tables->columnFitting, band));
725 /* TODO: temporarily commented out as seems same infor is computed elsewhere
726 eris_compute_residuals_fit(tables->columnFitting,qclog);
727 */
728 }
729 CATCH
730 {
731 waveCalImg = NULL;
732 }
733 for (int ix=0; ix<ERIS_IFU_DETECTOR_SIZE_Y; ix++) {
734 eris_ifu_free_polynomial(&allFits[ix]);
735 }
736 if (dataImg != NULL) {
737 cpl_free(dataImg);
738 }
739 if (refLines != NULL) {
740 for (int ix=0; ix < arcImgCnt; ix++) {
741 eris_ifu_free_bivector(&refLines[ix]);
742 }
743 cpl_free(refLines);
744 }
745 if (collapsedSpectra != NULL) {
746 for (int ix=0; ix < arcImgCnt; ix++) {
747 eris_ifu_free_image(&collapsedSpectra[ix]);
748 }
749 cpl_free(collapsedSpectra);
750 }
751 eris_ifu_free_vector(&collapsedSpectrum);
752 eris_ifu_free_polynomial(&firstFit);
753 eris_ifu_free_table(&firstFitTable);
754 return waveCalImg;
755}
756
757cpl_bivector *eris_ifu_wave_get_refLines(
758 const char * refLineTableFileName,
759 ifsInstrument instrument,
760 int lampState)
761{
762 cpl_bivector *refLines = NULL;
763 cpl_propertylist *header = NULL;
764 cpl_size exCnt = 0;
765 const char *instrumentHdr;
766 const char *lampHdr;
767 const char *instrString;
768 char lampString[9] = "";
769 cpl_vector *wavelength = NULL;
770 cpl_vector *intensity = NULL;
771 cpl_table *refLineTable = NULL;
772 cpl_size nRows;
773 int ignored;
774 int vx=0;
775 double tmp;
776
777 cpl_ensure(refLineTableFileName, CPL_ERROR_NULL_INPUT, NULL);
778 if (access(refLineTableFileName, F_OK)) {
779 cpl_msg_error(cpl_func, "File %s was not found",
780 refLineTableFileName);
781 cpl_error_set(cpl_func, CPL_ERROR_FILE_NOT_FOUND);
782 cpl_ensure(CPL_FALSE, CPL_ERROR_FILE_NOT_FOUND, NULL);
783 }
784 TRY
785 {
786 switch(instrument) {
787 case SPIFFIER:
788 instrString = ERIS_IFU_REFTABLE_SPIFFIER_VAL;
789 break;
790 case SPIFFI:
791 instrString = ERIS_IFU_REFTABLE_SPIFFI_VAL;
792 break;
793 default:
794 instrString = "";
795 break;
796 }
797 if ((lampState & AR_LAMP) != 0) {
798 strcat(lampString, ERIS_IFU_REFTABLE_ARGON_VAL);
799 }
800 if ((lampState & NE_LAMP) != 0) {
801 strcat(lampString, ERIS_IFU_REFTABLE_NEON_VAL);
802 }
803 if ((lampState & KR_LAMP) != 0) {
804 strcat(lampString, ERIS_IFU_REFTABLE_KRYPTON_VAL);
805 }
806 if ((lampState & XE_LAMP) != 0) {
807 strcat(lampString, ERIS_IFU_REFTABLE_XEON_VAL);
808 }
809 exCnt = cpl_fits_count_extensions(refLineTableFileName);
811 for (int ex=1; ex<exCnt+1; ex++) {
813 header = cpl_propertylist_load(refLineTableFileName, ex));
815 instrumentHdr = cpl_propertylist_get_string(
816 header, ERIS_IFU_REFTABLE_INSTR_HDR));
818 lampHdr = cpl_propertylist_get_string(
819 header, ERIS_IFU_REFTABLE_LAMPS_HDR));
820 if ((strcmp(instrumentHdr, instrString) == 0) &&
821 (strcmp(lampHdr, lampString) == 0)) {
822
824 refLineTable = cpl_table_load(refLineTableFileName, ex, 0));
825 nRows = cpl_table_get_nrow(refLineTable);
827 wavelength = cpl_vector_new(nRows));
829 intensity = cpl_vector_new(nRows));
830 for (int rx=0; rx<nRows; rx++) {
831 ignored = cpl_table_get_int(
832 refLineTable, ERIS_IFU_REFTABLE_IGNORED_COLUMN,
833 rx, NULL);
834 if (ignored == 0) {
835 tmp = cpl_table_get_double(
836 refLineTable, ERIS_IFU_REFTABLE_LAMBDA_COLUMN, rx,
837 NULL);
839 if (tmp > 100.) {
840 tmp /= 1000.;
841 }
843 cpl_vector_set(wavelength, vx, tmp));
844
845 tmp = cpl_table_get_double(
846 refLineTable, ERIS_IFU_REFTABLE_INTENSITY_COLUMN,
847 rx, NULL);
850 cpl_vector_set(intensity, vx, tmp));
851
852 vx++;
853 }
854 }
856 break;
857 }
859 }
860 if (wavelength == NULL) {
861 BRK_WITH_ERROR_MSG(CPL_ERROR_BAD_FILE_FORMAT,
862 "There is no extension in reference lines file %s "
863 "for instrument %s and lamps %s",
864 refLineTableFileName, instrString, lampString);
865
866 }
867 if (vx > 0) {
869 refLines = cpl_bivector_wrap_vectors(
870 cpl_vector_extract(wavelength, 0, vx-1, 1),
871 cpl_vector_extract(intensity, 0, vx-1, 1)));
872 }
873 }
874 CATCH
875 {
876 refLines = NULL;
878 }
879 eris_ifu_free_vector(&wavelength);
880 eris_ifu_free_vector(&intensity);
881 eris_ifu_free_table(&refLineTable);
882
883 return refLines;
884}
885
886cpl_vector * eris_ifu_wave_collapse_slitlet(const cpl_image *dataImg,
887 int center)
888{
889 cpl_vector *spec = NULL;
890 cpl_size nRows;
891 cpl_vector *slitletRow = NULL;
892 double *slitletRowData = NULL;
893 int isValid;
894 int startCol;
895 int endCol;
896 double tmpData;
897
898 const int halfWidth = 10;
899
900 startCol = center - halfWidth;
901 endCol = center + halfWidth;
902 TRY
903 {
904 nRows = cpl_image_get_size_y(dataImg);
906 spec = cpl_vector_new(nRows));
907
909 slitletRow = cpl_vector_new(halfWidth * 2 + 1));
911 slitletRowData = cpl_vector_get_data(slitletRow));
912
913 for (int row=0; row<nRows; row++) {
914 for (int col=startCol; col<endCol+1; col++) {
915 tmpData = cpl_image_get(dataImg, col+1, row+1, &isValid);
917 if (isValid != 0) {
918 tmpData = 0;
919 }
920 slitletRowData[col-startCol] = tmpData;
921 }
922 tmpData = cpl_vector_get_median(slitletRow);
924 cpl_vector_set(spec, row, tmpData));
925 }
926 }
927 CATCH
928 {
929 spec = NULL;
930 }
931 eris_ifu_free_vector(&slitletRow);
932 return spec;
933}
934
935cpl_polynomial * eris_ifu_get_first_fit(
936 cpl_image** spectra,
937 int *lampStates,
938 int spectrumCnt,
939 int slitlet,
940 int ffOffsetIn,
941 int *ffOffsetOut,
942 struct waveSetupStruct waveSetup,
943 cpl_table *firstFitTable,
944 cpl_table *fittingDumpTable,
945 cpl_table *coeffDumpTable)
946{
947 cpl_polynomial *fit = NULL;
948 cpl_table *blockTable = NULL;
949 cpl_table *tmpTable = NULL;
950 cpl_size rowCnt;
951 cpl_vector *spectrum = NULL;
952 int isValid;
953 int position;
954 double wavelength;
955 const int fitLength = 40;
956 double xData[fitLength];
957 double yData[fitLength];
958 int fx;
959 struct gaussParStruct gaussPar;
960 cpl_size dumpRow;
961 double ffOffsets = 0.;
962 int ffOffsetCnt = 0;
963
964 const int slitlet2collapsed[SLITLET_CNT] = {
965 0, 15, 1, 16, 2, 17, 3, 18, 4, 19, 5, 20, 6, 21, 7,
966 30, 31,
967 22, 8, 23, 9, 24, 10, 25, 11, 26, 12, 27, 13, 28, 14, 29};
968
969 TRY
970 {
972 cpl_table_unselect_all(firstFitTable));
973
974 rowCnt = cpl_table_or_selected_int(firstFitTable,
975 ERIS_IFU_FIRSTFIT_BLOCK, CPL_EQUAL_TO, slitlet_block[slitlet]);
977 if (rowCnt < 1) {
978 BRK_WITH_ERROR_MSG(CPL_ERROR_DATA_NOT_FOUND,
979 "no records found in firstFits table with block %d",
980 slitlet_block[slitlet]);
981 }
982 blockTable = cpl_table_extract_selected(firstFitTable);
983
984 fx = 0;
985
986 for (int aIdx = 0; aIdx < spectrumCnt; aIdx++) {
987
989 cpl_table_unselect_all(blockTable));
990 char* lampString = eris_ifu_get_lampString(lampStates[aIdx]);
991 rowCnt = cpl_table_or_selected_string(blockTable,
992 ERIS_IFU_FIRSTFIT_LAMPS, CPL_EQUAL_TO, lampString);
993 cpl_free(lampString);
994 tmpTable = cpl_table_extract_selected(blockTable);
995 dumpRow = cpl_table_get_nrow(fittingDumpTable);
996 cpl_table_set_size(fittingDumpTable, dumpRow+rowCnt);
997
998 if (slitlet < 15) {
999
1000 }
1002 spectrum = cpl_vector_new_from_image_column(
1003 spectra[aIdx], slitlet2collapsed[slitlet]+1));
1004
1005 for (int rx = 0; rx < rowCnt; rx++) {
1006 position = cpl_table_get_int(tmpTable,
1007 ERIS_IFU_FIRSTFIT_POSITION, rx, &isValid);
1008 wavelength = cpl_table_get_double(tmpTable,
1009 ERIS_IFU_FIRSTFIT_WAVELENGTH, rx, &isValid);
1010
1011 if (CPL_ERROR_NONE == eris_ifu_line_gauss_fit(
1012 spectrum, position+ffOffsetIn, waveSetup.s_range, &gaussPar)) {
1013 if ((gaussPar.x0 != 0.) &&
1014 (gaussPar.sigma < 3. || gaussPar.peak > 8000.)){
1015 if (fx < fitLength) {
1016 if (wavelength > 100.) {
1017 wavelength /= 1000.;
1018 }
1019 xData[fx] = wavelength;
1020 yData[fx] = gaussPar.x0;
1021 fx++;
1022 }
1023 ffOffsets += gaussPar.x0 - position;
1024 ffOffsetCnt++;
1025 } else {
1026 int range = waveSetup.s_range;
1027 int start = position-(range/2);
1028 if (range <= GAUSS_PAR_RANGE_MAX) {
1029 gaussPar.range = range;
1030 for (int ix=0; ix<range; ix++) {
1031 gaussPar.xdata[ix] = start+ix;
1032 gaussPar.ydata[ix] = cpl_vector_get(spectrum,start+ix);
1033 }
1034 }
1035
1036 const char *lamp = cpl_table_get_string(tmpTable,
1037 ERIS_IFU_FIRSTFIT_LAMPS, rx);
1038 cpl_msg_warning(__func__,
1039 "First line fit failed for "
1040 "slitlet %d at row %d wavelength %.3f for lamp %s",
1041 slitlet, position, wavelength, lamp);
1042 }
1043 }
1045 eris_ifu_wave_fill_fitting_table(fittingDumpTable,
1046 (int) dumpRow,
1047 slitlet, slitlet_block[slitlet], aIdx,
1048 position, wavelength,
1049 &gaussPar));
1050 dumpRow++;
1051 }
1052 eris_ifu_free_vector(&spectrum);
1053 eris_ifu_free_table(&tmpTable);
1054 *ffOffsetOut = (int) (ffOffsets/ffOffsetCnt + .5);
1055 }
1057 fit = eris_ifu_1d_polynomial_fit(fx, xData, yData,
1058 FIRST_FIT_DEGREE));
1059 eris_ifu_wave_fill_coeff_table(coeffDumpTable, slitlet, slitlet, fx,
1060 fit);
1061 }
1062
1063 CATCH
1064 {
1065 fit = NULL;
1066 }
1067 eris_ifu_free_table(&tmpTable);
1068 eris_ifu_free_table(&blockTable);
1069 eris_ifu_free_vector(&spectrum);
1071 cpl_table_unselect_all(firstFitTable));
1072 return fit;
1073}
1074
1075cpl_error_code eris_ifu_fit_all_lines(
1076 const char *recipe_name,
1077 int sIdx,
1078 const double *slitletStart,
1079 const double *slitletEnd,
1080 int arcImgCnt,
1081 const cpl_image **dataImg,
1082 cpl_bivector **refLines,
1083 struct waveSetupStruct waveSetup,
1084 cpl_polynomial *firstFit,
1085 cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y],
1086 cpl_table *dumpTable,
1087 cpl_table *columnCoeffRawTable,
1088 cpl_table *columnCoeffSmoothedTable,
1089 cpl_table *smoothingCoeffTable)
1090{
1091 cpl_error_code err = CPL_ERROR_NONE;
1092 int start, end;
1093 double s1, s2, e1, e2;
1094 cpl_vector *spectrum = NULL;
1095 double *refLinelambda;
1096 int firstGuessPos;
1097 cpl_size nRefLines;
1098 cpl_size nSpectrum;
1099 cpl_error_code fitErr;
1100 struct gaussParStruct gaussPar;
1101 cpl_size dumpRow = 0;
1102 const int fitLength = 2048;
1103 double xData[fitLength];
1104 double yData[fitLength];
1105 int fx;
1106
1107 cpl_ensure_code(recipe_name, CPL_ERROR_NULL_INPUT);
1108
1109 TRY
1110 {
1111 if (strcmp(recipe_name, REC_NAME_DISTORTION) == 0) {
1112 start = (int) slitletStart[sIdx];
1113 end = (int) slitletEnd[sIdx];
1114 } else {
1115 s2 = slitletStart[sIdx];
1116 if (sIdx == 0) {
1117 s1 = -.5;
1118 } else {
1119 s1 = slitletEnd[sIdx-1];
1120 }
1121 e1 = slitletEnd[sIdx];
1122 if (sIdx == SLITLET_CNT-1) {
1123 e2 = 2047.;
1124 } else {
1125 e2 = slitletStart[sIdx+1];
1126 }
1127 // start = 1 + (int) floor(((s1 + s2) /2.0));
1128 // end = (int) ((e1 + e2) /2.0);
1129 if (sIdx == 0) {
1130 start = 0;
1131 } else {
1132 start = (int) (((s1 + s2) / 2.0) + .5) + 1;
1133 }
1134 if (sIdx == SLITLET_CNT-1) {
1135 end = 2047;
1136 } else {
1137 end = (int) (((e1 + e2) / 2.0) + .5);
1138 }
1139 cpl_msg_debug(cpl_func,
1140 "Slitlet %2d: start: %4d end: %4d (%7.2f - %7.2f ... %7.2f - %7.2f)",
1141 sIdx, start, end, s1, s2, e1, e2);
1142 }
1143
1144 for (int cx = start; cx <= end; cx++) {
1145 fx = 0;
1146 for (int ax = 0; ax< arcImgCnt; ax++) {
1147 nRefLines = cpl_bivector_get_size(refLines[ax]);
1148 refLinelambda = cpl_bivector_get_x_data(refLines[ax]);
1149
1150 dumpRow = cpl_table_get_nrow(dumpTable);
1151 cpl_table_set_size(dumpTable, dumpRow + nRefLines);
1152
1154 spectrum = cpl_vector_new_from_image_column(dataImg[ax], cx+1));
1155 nSpectrum = cpl_vector_get_size(spectrum);
1156 for (int rx=0; rx<nRefLines; rx++) {
1157 firstGuessPos = (int) (0.5 +
1158 cpl_polynomial_eval_1d(firstFit, refLinelambda[rx], NULL));
1159 if (firstGuessPos > 4+waveSetup.c_range/2 &&
1160 firstGuessPos < (nSpectrum - 4 - waveSetup.c_range/2)) {
1161 fitErr = eris_ifu_line_gauss_fit(
1162 spectrum, firstGuessPos, waveSetup.c_range, &gaussPar);
1163 if ((fitErr == CPL_ERROR_NONE) &&
1164 (gaussPar.offset > -10. - gaussPar.peak / 300. ) &&
1165 (gaussPar.sigma < waveSetup.sigma) &&
1166 (fabs(gaussPar.x0 - firstGuessPos) < 5.01)) {
1167 yData[fx] = refLinelambda[rx];
1168 xData[fx] = gaussPar.x0;
1169 fx++;
1170 } else {
1171 if (fitErr == CPL_ERROR_NONE) { //wierd looking fit
1172 gaussPar.errorCode = -2; //for dump table only
1173 }
1174 }
1175 } else {
1176 // search outside spectra
1177 gaussPar.errorCode = -1;
1178 gaussPar.x0 = 0.;
1179 gaussPar.sigma = 0.;
1180 gaussPar.area = 0.;
1181 gaussPar.offset = 0.;
1182 gaussPar.peak = 0.;
1183 gaussPar.mse = 0.;
1184 gaussPar.range = 0;
1185 }
1186 if (gaussPar.errorCode != -1) {
1188 eris_ifu_wave_fill_fitting_table(dumpTable, (int) dumpRow,
1189 sIdx, cx, ax, firstGuessPos, refLinelambda[rx],
1190 &gaussPar));
1191 dumpRow++;
1192 }
1193 }
1194 eris_ifu_free_vector(&spectrum);
1195 cpl_table_set_size(dumpTable, dumpRow);
1196 }
1197 if (fx > COLUMN_FIT_DEGREE+1) {
1198 //if (fx > (/2)) {
1200 allFits[cx] = eris_ifu_1d_polynomial_fit(fx, xData, yData,
1201 COLUMN_FIT_DEGREE));
1202 } else {
1203 cpl_msg_warning(cpl_func,
1204 "Number of found lines (=%d) too small for column %d",
1205 fx, cx);
1206 //mark fit as failed
1207 allFits[cx] = cpl_polynomial_new(1);
1208 cpl_size tmpPower = 0;
1209 cpl_polynomial_set_coeff(allFits[cx], &tmpPower, 0.0);
1210 }
1211 eris_ifu_wave_fill_coeff_table(columnCoeffRawTable, cx, cx,
1212 fx, allFits[cx]);
1213
1214 eris_ifu_free_vector(&spectrum);
1215 }
1216
1218 eris_ifu_wave_smooth_coeffs(sIdx, start, end,
1219 COLUMN_FIT_DEGREE, allFits,
1220 columnCoeffSmoothedTable, smoothingCoeffTable));
1221 }
1222 CATCH
1223 {
1224 }
1225 return err;
1226
1227}
1228
1229cpl_error_code eris_ifu_wave_smooth_coeffs(
1230 int sIdx,
1231 int start,
1232 int end,
1233 int fitDegree,
1234 cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y],
1235 cpl_table *columnCoeffSmoothedTable,
1236 cpl_table *smoothingCoeffTable)
1237{
1238 cpl_error_code retVal = CPL_ERROR_NONE;
1239 int nc;
1240 const int fitLength = 2048;
1241 double cData[fitLength];
1242 double xData[fitLength];
1243 double yData[fitLength];
1244 cpl_polynomial *smoothFit = NULL;
1245 cpl_size firstCoeff = 0;
1246
1247 TRY
1248 {
1249 nc = 0;
1250 for (int cx = start; cx <= end; cx++) {
1251 if (cpl_polynomial_get_coeff(allFits[cx], &firstCoeff) != 0.) {
1252 cData[nc] = cx + .1;
1253 yData[nc] = cpl_polynomial_eval_1d( allFits[cx], 1024., NULL);
1254 nc++;
1255 }
1256 }
1257 //sort cData/yData pairs by yData values
1258 cpl_vector *xVec = cpl_vector_wrap(nc, cData);
1259 cpl_vector *yVec = cpl_vector_wrap(nc, yData);
1260 cpl_bivector *biVec = cpl_bivector_wrap_vectors(xVec, yVec);
1261 cpl_bivector_sort(biVec, biVec, CPL_SORT_ASCENDING, CPL_SORT_BY_Y);
1262 cpl_bivector_unwrap_vectors(biVec);
1263 cpl_vector_unwrap(xVec);
1264 cpl_vector_unwrap(yVec);
1265
1266 for (cpl_size power = 0; power <= fitDegree; power++) {
1267 for (int ix = 0; ix < nc; ix++) {
1268 int cx = (int) cData[ix];
1269 xData[ix] = cx;
1270 yData[ix] = cpl_polynomial_get_coeff(allFits[cx], &power);
1271 }
1272 // reject outliers
1273 smoothFit = eris_ifu_1d_polynomial_fit(nc - 4, &xData[2], &yData[2],
1274 SMOOTH_FIT_DEGREE);
1275 eris_ifu_wave_fill_coeff_table(smoothingCoeffTable,
1276 (COLUMN_FIT_DEGREE + 1) * sIdx + (int) power,
1277 sIdx, (int) power, smoothFit);
1278 for (int cx = start; cx <= end; cx++) {
1279 cpl_polynomial_set_coeff(allFits[cx], &power,
1280 cpl_polynomial_eval_1d(smoothFit, (double) cx, NULL));
1281 }
1282 eris_ifu_free_polynomial(&smoothFit);
1283 }
1284
1285 for (int cx = start; cx <= end; cx++) {
1286 eris_ifu_wave_fill_coeff_table(columnCoeffSmoothedTable, cx, cx, 0,
1287 allFits[cx]);
1288 }
1289 }
1290 CATCH {
1291 }
1292
1293 return retVal;
1294}
1295
1296cpl_error_code eris_ifu_wave_pos_err(
1297 cpl_polynomial *allFits[ERIS_IFU_DETECTOR_SIZE_Y],
1298 cpl_table *fitTable,
1299 ifsBand band)
1300{
1301 cpl_error_code retVal = CPL_ERROR_NONE;
1302 int col;
1303 double val;
1304 double wave;
1305 double waveError;
1306
1307 TRY
1308 {
1309 for (cpl_size row=0; row<cpl_table_get_nrow(fitTable); row++) {
1310 if (cpl_table_get_int(fitTable, ERIS_IFU_FITTABLE_ERRORCODE, row, NULL) != 0) {
1311 continue;
1312 }
1313 col = cpl_table_get_int(fitTable, "index", row, NULL);
1314 val = cpl_table_get_double(fitTable, "x0", row, NULL);
1315 wave = cpl_polynomial_eval_1d(allFits[col], val, NULL);
1316 waveError = cpl_table_get_double(fitTable, ERIS_IFU_FITTABLE_WAVELENGTH, row, NULL)-
1317 wave;
1318 cpl_table_set_double(fitTable, "wavelengthFit", row, wave);
1319 cpl_table_set_double(fitTable, "wavelengthError", row, waveError);
1321 }
1322 double dispersion;
1323 eris_ifu_get_dispersion(band, &dispersion);
1324 double convFactor = 2. * sqrt(2. * log(2.));
1325 cpl_table_duplicate_column(fitTable,"resol",fitTable,"wavelengthFit");
1326 cpl_table_divide_columns(fitTable,"resol","sigma");
1327 cpl_table_divide_scalar(fitTable,"resol", dispersion);
1328 cpl_table_divide_scalar(fitTable,"resol", convFactor);
1329
1330 }
1331 CATCH {
1332 }
1333 return retVal;
1334
1335}
1336
1337void eris_ifu_wave_save_spectrum(
1338 cpl_image **collapsedSpectra,
1339 int aIdx,
1340 cpl_vector *collapsedSpectrum,
1341 int sIdx,
1342 cpl_size nRows,
1343 int lampStatus,
1344 ifsBand band,
1345 ifsInstrument instrument,
1346 cpl_bivector *refLines,
1347 int productDepth)
1348{
1349 const double *collapsedSpectrumData = NULL;
1350 static int slitletBlockIdx[SLITLET_BLOCK_CNT];
1351 int columnIdx = 0;
1352
1353 TRY
1354 {
1355 if (aIdx == 0) {
1356 /* TODO: One should save product in standard way.
1357 * But this is not yet working
1358 *
1359 cpl_dfs_save_propertylist(fs, NULL, parlist, fs,
1360 NULL, "eris_ifu_wavecal", NULL, NULL,
1361 PACKAGE "/" PACKAGE_VERSION,
1362 ERIS_IFU_PRO_WAVE_COLLAP_SPECTR_FN);
1363 */
1364 if((productDepth & 1)) {
1365 cpl_image_save(NULL, ERIS_IFU_PRO_WAVE_COLLAP_SPECTR_FN,
1366 CPL_TYPE_DOUBLE,NULL,CPL_IO_CREATE);
1367 }
1368 }
1369 if (sIdx == 0) {
1370 for (int i=0; i<SLITLET_BLOCK_CNT; i++) {
1371 slitletBlockIdx[i] = 0;
1372 }
1374 collapsedSpectra[aIdx] = cpl_image_new(SLITLET_CNT, nRows,
1375 CPL_TYPE_DOUBLE));
1376 }
1377 collapsedSpectrumData =
1378 cpl_vector_get_data_const(collapsedSpectrum);
1379 switch (slitlet_block[sIdx]) {
1380 case 0:
1381 columnIdx = slitletBlockIdx[0];
1382 break;
1383 case 1:
1384 columnIdx = slitletBlockIdx[1] +
1385 SLITLET_BLOCK0_CNT;
1386 break;
1387 case 2:
1388 columnIdx = slitletBlockIdx[2] +
1389 SLITLET_BLOCK0_CNT + SLITLET_BLOCK1_CNT;
1390 break;
1391 case 3:
1392 columnIdx = slitletBlockIdx[3] +
1393 SLITLET_BLOCK0_CNT + SLITLET_BLOCK1_CNT +SLITLET_BLOCK2_CNT;
1394 break;
1395 default:
1396 columnIdx = -1;
1397 break;
1398 }
1399 slitletBlockIdx[slitlet_block[sIdx]]++;
1400 for (int row=0; row<nRows; row++) {
1402 cpl_image_set(collapsedSpectra[aIdx], columnIdx+1, row+1,
1403 collapsedSpectrumData[row]));
1404 }
1405 if ((sIdx >= SLITLET_CNT-1) && ((productDepth & 1) != 0)) {
1406 const char *instrumentString;
1407 char *lampString;
1408 if (instrument == SPIFFI) {
1409 instrumentString = "SINFONI";
1410 } else {
1411 instrumentString = "ERIS";
1412 }
1413 cpl_propertylist *hdr = cpl_propertylist_new();
1415 cpl_propertylist_update_string(hdr, CPL_DFS_PRO_CATG,
1416 ERIS_IFU_PRO_WAVE_COLLAP_SPECTR ));
1417 cpl_propertylist_append_string(hdr,"INSTRUME", instrumentString);
1418 lampString = eris_ifu_get_lampString(lampStatus);
1419 cpl_propertylist_append_string(hdr,"LAMPS", lampString);
1420 cpl_propertylist_append_string(hdr,"BAND",
1422 cpl_image_save(collapsedSpectra[aIdx], ERIS_IFU_PRO_WAVE_COLLAP_SPECTR_FN,
1423 CPL_TYPE_UNSPECIFIED, hdr, CPL_IO_EXTEND);
1425 cpl_free(lampString);
1426 cpl_vector_save(cpl_bivector_get_x(refLines), ERIS_IFU_PRO_WAVE_COLLAP_SPECTR_FN,
1427 CPL_TYPE_DOUBLE, NULL, CPL_IO_EXTEND);
1428 cpl_vector_save(cpl_bivector_get_y(refLines), ERIS_IFU_PRO_WAVE_COLLAP_SPECTR_FN,
1429 CPL_TYPE_DOUBLE, NULL, CPL_IO_EXTEND);
1430 }
1431 }
1432 CATCH
1433 {
1434
1435 }
1436 return;
1437}
1438
1439cpl_table *eris_ifu_wave_get_firstFitTable(
1440 const char* firstFitTableFileName,
1441 ifsInstrument instrument,
1442// int lampStatus,
1443 ifsBand band)
1444{
1445 cpl_table *firstFitTable = NULL;
1446 cpl_table *fullTable = NULL;
1447 cpl_size rowCnt;
1448 const char *instrumentString;
1449 const char* bandString;
1450
1451 TRY
1452 {
1453 if (instrument == SPIFFI) {
1454 instrumentString = "SINFONI";
1455 } else {
1456 instrumentString = "ERIS";
1457 }
1458 bandString = eris_ifu_get_bandString(band);
1459
1461 fullTable = cpl_table_load(firstFitTableFileName, 1, 0));
1462
1463 rowCnt = cpl_table_and_selected_string(fullTable,
1464 ERIS_IFU_FIRSTFIT_INSTRUMENT, CPL_EQUAL_TO, instrumentString);
1466 if (rowCnt < 1) {
1467 BRK_WITH_ERROR_MSG(CPL_ERROR_DATA_NOT_FOUND,
1468 "no records found in firstFits table with instrument %s",
1469 instrumentString);
1470 }
1471
1472 char *regExp = cpl_sprintf("^%s$", bandString);
1473 rowCnt = cpl_table_and_selected_string(fullTable,
1474 ERIS_IFU_FIRSTFIT_BAND, CPL_EQUAL_TO, regExp);
1476 eris_ifu_free_string(&regExp);
1477 if (rowCnt < 1) {
1478 BRK_WITH_ERROR_MSG(CPL_ERROR_DATA_NOT_FOUND,
1479 "no records found in firstFits table with band %s",
1480 bandString);
1481 }
1482 firstFitTable = cpl_table_extract_selected(fullTable);
1483 }
1484 CATCH
1485 {
1486 }
1487 eris_ifu_free_table(&fullTable);
1488
1489 return firstFitTable;
1490}
1491
1492cpl_error_code
1493eris_ifu_get_dispersion(ifsBand band, double* dispersion)
1494{
1495
1496 switch (band) {
1497 case J_SPIFFI:
1498 *dispersion = DISPERSION_J_SPIFFI;
1499 break;
1500 case H_SPIFFI:
1501 *dispersion = DISPERSION_H_SPIFFI;
1502 break;
1503 case K_SPIFFI:
1504 *dispersion = DISPERSION_K_SPIFFI;
1505 break;
1506 case HK_SPIFFI:
1507 *dispersion = DISPERSION_HK_SPIFFI;
1508 break;
1509 case J_LOW:
1510 *dispersion = DISPERSION_J_LOW;
1511 break;
1512 case J_SHORT:
1513 *dispersion = DISPERSION_J_SHORT;
1514 break;
1515 case J_MIDDLE:
1516 *dispersion = DISPERSION_J_MIDDLE;
1517 break;
1518 case J_LONG:
1519 *dispersion = DISPERSION_J_LONG;
1520 break;
1521 case H_LOW:
1522 *dispersion = DISPERSION_H_LOW;
1523 break;
1524 case H_SHORT:
1525 *dispersion = DISPERSION_H_SHORT;
1526 break;
1527 case H_MIDDLE:
1528 *dispersion = DISPERSION_H_MIDDLE;
1529 break;
1530 case H_LONG:
1531 *dispersion = DISPERSION_H_LONG;
1532 break;
1533 case K_LOW:
1534 *dispersion = DISPERSION_K_LOW;
1535 break;
1536 case K_SHORT:
1537 *dispersion = DISPERSION_K_SHORT;
1538 break;
1539 case K_MIDDLE:
1540 *dispersion = DISPERSION_K_MIDDLE;
1541 break;
1542 case K_LONG:
1543 *dispersion = DISPERSION_K_LONG;
1544 break;
1545 default:
1546
1547 break;
1548 }
1549
1550 return cpl_error_get_code();
1551}
1552
1553cpl_error_code
1554eris_ifu_get_central_lambda(ifsBand band, double* centralLambda)
1555{
1556
1557 switch (band) {
1558 case J_SPIFFI:
1559 *centralLambda = CENTRALLAMBDA_J_SPIFFI;
1560 break;
1561 case H_SPIFFI:
1562 *centralLambda = CENTRALLAMBDA_H_SPIFFI;
1563 break;
1564 case K_SPIFFI:
1565 *centralLambda = CENTRALLAMBDA_K_SPIFFI;
1566 break;
1567 case HK_SPIFFI:
1568 *centralLambda = CENTRALLAMBDA_HK_SPIFFI;
1569 break;
1570 case J_LOW:
1571 *centralLambda = CENTRALLAMBDA_J_LOW;
1572 break;
1573 case J_SHORT:
1574 *centralLambda = CENTRALLAMBDA_J_SHORT;
1575 break;
1576 case J_MIDDLE:
1577 *centralLambda = CENTRALLAMBDA_J_MIDDLE;
1578 break;
1579 case J_LONG:
1580 *centralLambda = CENTRALLAMBDA_J_LONG;
1581 break;
1582 case H_LOW:
1583 *centralLambda = CENTRALLAMBDA_H_LOW;
1584 break;
1585 case H_SHORT:
1586 *centralLambda = CENTRALLAMBDA_H_SHORT;
1587 break;
1588 case H_MIDDLE:
1589 *centralLambda = CENTRALLAMBDA_H_MIDDLE;
1590 break;
1591 case H_LONG:
1592 *centralLambda = CENTRALLAMBDA_H_LONG;
1593 break;
1594 case K_LOW:
1595 *centralLambda = CENTRALLAMBDA_K_LOW;
1596 break;
1597 case K_SHORT:
1598 *centralLambda = CENTRALLAMBDA_K_SHORT;
1599 break;
1600 case K_MIDDLE:
1601 *centralLambda = CENTRALLAMBDA_K_MIDDLE;
1602 break;
1603 case K_LONG:
1604 *centralLambda = CENTRALLAMBDA_K_LONG;
1605 break;
1606 default:
1607
1608 break;
1609 }
1610
1611 return cpl_error_get_code();
1612}
1613
1614
1615cpl_image *eris_ifu_wave_resampled_arc_image(
1616 const cpl_image *arcImg,
1617 const cpl_image *waveCalImg,
1618 ifsBand band,
1619 double minLambda,
1620 double maxLambda,
1621 cpl_propertylist *plist,
1622 int axisNumber)
1623{
1624 cpl_image *resampledImage = NULL;
1625 cpl_vector *arcImgCol = NULL;
1626 cpl_vector *calImgCol = NULL;
1627 double dispersion =0;
1628 double centralLambda = 0;
1629 double *lambdaIn = NULL;
1630 double *lambdaOut = NULL;
1631 double *aduIn = NULL;
1632 double *aduOut = NULL;
1633 cpl_size origNx;
1634 cpl_size origNy;
1635 char *propName = NULL;
1636
1637 TRY
1638 {
1639 ASSURE(arcImg != NULL,
1640 CPL_ERROR_NULL_INPUT, "no arc image provided");
1641 ASSURE(waveCalImg != NULL,
1642 CPL_ERROR_NULL_INPUT, "no wavelength calibration image provided");
1643 origNx = cpl_image_get_size_x(arcImg);
1644 origNy = cpl_image_get_size_y(arcImg);
1645 ASSURE(cpl_image_get_size_x(waveCalImg) == origNx,
1646 CPL_ERROR_INCOMPATIBLE_INPUT,
1647 "arc and wavecal image have different size");
1648 ASSURE(cpl_image_get_size_y(waveCalImg) == origNy,
1649 CPL_ERROR_INCOMPATIBLE_INPUT,
1650 "arc and wavecal image have different size");
1651
1652 eris_ifu_get_dispersion(band, &dispersion);
1653 eris_ifu_get_central_lambda(band, &centralLambda);
1654
1655 cpl_size nRows = (cpl_size) ((maxLambda - minLambda) / dispersion + .5);
1656 cpl_size centerRow = nRows / 2;
1657 double startLambda = centralLambda - dispersion * (double) centerRow;
1658
1660 resampledImage = cpl_image_new(origNx, nRows, CPL_TYPE_FLOAT));
1662 lambdaIn = cpl_malloc(sizeof(double) * origNy));
1664 aduIn = cpl_malloc(sizeof(double) * origNy));
1666 lambdaOut = cpl_malloc(sizeof(double) * nRows));
1668 aduOut = cpl_malloc(sizeof(double) * nRows));
1669
1670 // populate wavelength axis for resampled image
1671 for (int rx=0; rx<nRows; rx++) {
1672 lambdaOut[rx] = startLambda + dispersion * (double) rx;
1673 }
1674
1675 cpl_errorstate errorState;
1676 bool errorHappend = false;
1677
1678 for (int cx=0; cx<origNx; cx++) {
1679 // copy arc and wavecal columns and swap the columns
1680 arcImgCol = cpl_vector_new_from_image_column(arcImg, cx+1);
1681 calImgCol = cpl_vector_new_from_image_column(waveCalImg, cx+1);
1682 double *arcImgColData = cpl_vector_get_data(arcImgCol);
1683 double *calImgColData = cpl_vector_get_data(calImgCol);
1684 for (int rx=0; rx<origNy; rx++) {
1685 lambdaIn[rx] = calImgColData[origNy-rx-1];
1686 aduIn[rx] = arcImgColData[origNy-rx-1];
1687 }
1688
1689 int nDegree = -5;
1690/*
1691 BRK_IF_ERROR(
1692 eris_ifu_1d_interpolation(lambdaIn, aduIn, (int) origNy,
1693 lambdaOut, aduOut, (int) nRows, nDegree));
1694*/
1695 errorState = cpl_errorstate_get();
1696 if (eris_ifu_1d_interpolation(lambdaIn, aduIn, (int) origNy,
1697 lambdaOut, aduOut, (int) nRows, nDegree)
1698 != CPL_ERROR_NONE) {
1699 errorHappend = true;
1700 cpl_errorstate_set(errorState);
1701 }
1702 for (int rx = 0; rx < nRows; rx++) {
1703 cpl_image_set(resampledImage, cx + 1, rx + 1, aduOut[rx]);
1704 }
1705 eris_ifu_free_vector(&arcImgCol);
1706 eris_ifu_free_vector(&calImgCol);
1707 }
1708 if (errorHappend) {
1709 cpl_msg_error(__func__,
1710 "One or more columns of the arc images could not be resampled");
1711 }
1712
1713 propName = cpl_sprintf("CTYPE%d", axisNumber);
1714 cpl_propertylist_update_string(plist, propName, "WAVE");
1715 eris_ifu_free_string(&propName);
1716 propName = cpl_sprintf("CUNIT%d", axisNumber);
1717 cpl_propertylist_update_string(plist, propName, "um");
1718 eris_ifu_free_string(&propName);
1719 propName = cpl_sprintf("CRPIX%d", axisNumber);
1720 cpl_propertylist_update_double(plist, propName, 1.);
1721 eris_ifu_free_string(&propName);
1722 propName = cpl_sprintf("CRVAL%d", axisNumber);
1723 cpl_propertylist_update_double(plist, propName, lambdaOut[0]);
1724 eris_ifu_free_string(&propName);
1725 propName = cpl_sprintf("CDELT%d", axisNumber);
1726 cpl_propertylist_update_double(plist, propName, dispersion);
1727 eris_ifu_free_string(&propName);
1728 for (int ix=1; ix<=axisNumber; ix++) {
1729 propName = cpl_sprintf("CD%d_%d", axisNumber, ix);
1730 if (ix == axisNumber) {
1731 cpl_propertylist_update_double(plist, propName, dispersion);
1732 } else {
1733 cpl_propertylist_update_double(plist, propName, 0.);
1734 }
1735 eris_ifu_free_string(&propName);
1736 }
1738
1739 }
1740 CATCH
1741 {
1742 eris_ifu_free_vector(&arcImgCol);
1743 eris_ifu_free_vector(&calImgCol);
1744 resampledImage = NULL;
1745 }
1746 eris_ifu_free_double_array(&lambdaIn);
1748 eris_ifu_free_double_array(&lambdaOut);
1750 return resampledImage;
1751}
1752cpl_error_code eris_ifu_save_resampled_arc_images(
1753 int arcImgCnt,
1754 const cpl_image **dataImg,
1755 const cpl_image *waveCalImg,
1756 ifsBand band,
1757 int *lampStates,
1758 cpl_frameset* frameset,
1759 const cpl_parameterlist* parlist) {
1760
1761 cpl_error_code retVal = CPL_ERROR_NONE;
1762 cpl_propertylist *plist = NULL;
1763 cpl_image *resampledImg = NULL;
1764 cpl_image *tmpImg = NULL;
1765 double minLambda = 0.;
1766 double maxLambda = 0.;
1767
1768 TRY
1769 {
1771 plist = cpl_propertylist_new());
1773 cpl_propertylist_update_string(plist, CPL_DFS_PRO_CATG,
1774 ERIS_IFU_PRO_WAVE_LAMP_RESAMPLED));
1775
1776 /* AMO: not necessary as header is set later by cpl_dfs_save_image , else one duplicate products
1777 eris_setup_product_header(ERIS_IFU_PRO_WAVE_LAMP_RESAMPLED_FN,
1778 ERIS_IFU_PRO_WAVE_LAMP_RESAMPLED,
1779 CPL_FRAME_TYPE_IMAGE, "eris_ifu_wavecal",
1780 frameset, parlist, plist);
1781 */
1783 tmpImg = cpl_image_new(1, 1, CPL_TYPE_INT));
1784 /* Save ERIS_IFU_PRO_WAVE_LAMP_RESAMPLED_FN as final product (PIPE-10189) */
1785 char* pipe_id = cpl_sprintf("%s%s%s", PACKAGE, "/", PACKAGE_VERSION);
1786 cpl_dfs_save_image(frameset, NULL, parlist, frameset, NULL, tmpImg,
1787 CPL_TYPE_UNSPECIFIED, REC_NAME_WAVECAL, plist, "RADECSYS",
1788 pipe_id, ERIS_IFU_PRO_WAVE_LAMP_RESAMPLED_FN);
1789 cpl_free(pipe_id);
1790 maxLambda = cpl_image_get_max(waveCalImg);
1791 minLambda = cpl_image_get_min(waveCalImg);
1792
1793 for (int ix = 0; ix < arcImgCnt; ix++) {
1794
1795 // create resampled arc image
1797 resampledImg =
1798 eris_ifu_wave_resampled_arc_image(dataImg[ix],
1799 waveCalImg, band, minLambda, maxLambda, plist, 2));
1800
1801 cpl_propertylist_update_string(plist, "CTYPE1", "PIXEL");
1802 cpl_propertylist_update_string(plist, "CUNIT1", "PIXEL");
1803 cpl_propertylist_update_double(plist, "CRPIX1", 1.);
1804 cpl_propertylist_update_double(plist, "CRVAL1", 1.);
1805 cpl_propertylist_update_double(plist, "CDELT1", 1.);
1806 char* lamp_string = eris_ifu_get_lampString(lampStates[ix]);
1807 cpl_propertylist_update_string(plist, "LAMPS",lamp_string);
1808 cpl_free(lamp_string);
1809 eris_ifu_save_image_dbg(resampledImg,
1810 ERIS_IFU_PRO_WAVE_LAMP_RESAMPLED_FN, CPL_IO_EXTEND,plist);
1811 eris_ifu_free_image(&resampledImg);
1812 }
1813
1814 }
1815 CATCH
1816 {
1817 retVal = cpl_error_get_code();
1818 CATCH_MSG();
1819 CATCH_MSGS();
1820 RECOVER();
1821 }
1822
1823 eris_ifu_free_image(&tmpImg);
1824 //eris_ifu_free_image(&resampledImg);
1826
1827 return retVal;
1828}
1829
1830cpl_error_code eris_ifu_read_wave_setup(
1831 const char* filename,
1832 ifsBand band,
1833 struct waveSetupStruct *waveSetup)
1834{
1835 cpl_error_code retVal = CPL_ERROR_NONE;
1836 cpl_table *table = NULL;
1837 cpl_size row;
1838 const char* bandName;
1839 const char* rowBandName;
1840 bool found = FALSE;
1841 bool invalidColumnFound = FALSE;
1842 int n;
1843
1844 TRY
1845 {
1846 /* Rough init in case table load fails */
1847 (void)memset(waveSetup, 0, sizeof(*waveSetup));
1848 bandName = eris_ifu_get_bandString(band);
1850 table = cpl_table_load(filename, 1, 0));
1851 for (row = 0; row<cpl_table_get_nrow(table); row++) {
1852 rowBandName = cpl_table_get_string(table, "band", row);
1854 if (strcmp(bandName, rowBandName) == 0){
1855 if (found) {
1856 BRK_WITH_ERROR_MSG(CPL_ERROR_BAD_FILE_FORMAT,
1857 "There are more than row in the WAVE_SETUP with "
1858 "the same band name %s", bandName);
1859 }
1860 found = TRUE;
1861 waveSetup->fwhm =
1862 cpl_table_get_double(table, "fwhm", row, &n);
1863 if (n == 1) {
1864 invalidColumnFound = TRUE;
1865 }
1866 waveSetup->s_range =
1867 cpl_table_get_int(table, "s_range", row, &n);
1868 if (n == 1) {
1869 invalidColumnFound = TRUE;
1870 }
1871 waveSetup->c_range =
1872 cpl_table_get_int(table, "c_range", row, &n);
1873 if (n == 1) {
1874 invalidColumnFound = TRUE;
1875 }
1876 waveSetup->ri_dispersion =
1877 cpl_table_get_double(table, "ri_dispersion", row, &n);
1878 if (n == 1) {
1879 invalidColumnFound = TRUE;
1880 }
1881 waveSetup->ri_centralLambda =
1882 cpl_table_get_double(table, "ri_centrallambda", row,&n);
1884 double convFactor = 2. * sqrt(2. * log(2.));
1885 waveSetup->sigma = waveSetup->fwhm / convFactor;
1886 }
1887 }
1888 if (! found) {
1889 BRK_WITH_ERROR_MSG(CPL_ERROR_BAD_FILE_FORMAT,
1890 "There is no row in the WAVE_SETUP with the band name %s",
1891 bandName);
1892 }
1893 if (invalidColumnFound) {
1894 BRK_WITH_ERROR_MSG(CPL_ERROR_BAD_FILE_FORMAT,
1895 "There is an invalid column in the WAVE_SETUP "
1896 "with the band name %s",
1897 bandName);
1898 }
1899 }
1900 CATCH
1901 {
1902 }
1903 eris_ifu_free_table(&table);
1904 return retVal;
1905}
1906
1907cpl_error_code eris_ifu_wave_init_tables(
1908 struct waveTablesStruct *tables)
1909{
1910 cpl_ensure_code(tables, CPL_ERROR_NULL_INPUT);
1911 cpl_error_code retVal = CPL_ERROR_NONE;
1912
1913 TRY
1914 {
1915 tables->slitletFitting = NULL;
1916 tables->columnFitting = NULL;
1917 tables->slitletCoeff = NULL;
1918 tables->columnCoeffRaw = NULL;
1919 tables->columnCoeffSmoothed = NULL;
1920 tables->smoothingCoeff = NULL;
1921
1922 tables->slitletFitting = eris_ifu_wave_create_fitting_table();
1923 tables->columnFitting = eris_ifu_wave_create_fitting_table();
1924 tables->slitletCoeff = eris_ifu_wave_create_coeff_table(
1925 SLITLET_CNT, FIRST_FIT_DEGREE);
1926 tables->columnCoeffRaw = eris_ifu_wave_create_coeff_table(
1927 ERIS_IFU_DETECTOR_SIZE_X, COLUMN_FIT_DEGREE);
1928 tables->columnCoeffSmoothed = eris_ifu_wave_create_coeff_table(
1929 ERIS_IFU_DETECTOR_SIZE_X, COLUMN_FIT_DEGREE);
1930 tables->smoothingCoeff = eris_ifu_wave_create_coeff_table(
1931 SLITLET_CNT * (COLUMN_FIT_DEGREE + 1), SMOOTH_FIT_DEGREE);
1933
1934 }
1935 CATCH
1936 {
1937 }
1938 return retVal;
1939}
1940
1941cpl_table *eris_ifu_wave_create_fitting_table(void)
1942{
1943
1944 cpl_table *table = NULL;
1945
1946 TRY
1947 {
1949 table = cpl_table_new(0));
1950 cpl_table_new_column(table, ERIS_IFU_FITTABLE_SLITLET, CPL_TYPE_INT);
1951 cpl_table_new_column(table, ERIS_IFU_FITTABLE_INDEX, CPL_TYPE_INT);
1952 cpl_table_new_column(table, "imgIdx", CPL_TYPE_INT);
1953 cpl_table_new_column(table, ERIS_IFU_FITTABLE_POSITION, CPL_TYPE_INT);
1954 cpl_table_new_column(table, ERIS_IFU_FITTABLE_WAVELENGTH, CPL_TYPE_DOUBLE);
1955 cpl_table_new_column(table, ERIS_IFU_FITTABLE_ERRORCODE, CPL_TYPE_INT);
1956 cpl_table_new_column(table, "x0", CPL_TYPE_DOUBLE);
1957 cpl_table_new_column(table, "sigma", CPL_TYPE_DOUBLE);
1958 cpl_table_new_column(table, "area", CPL_TYPE_DOUBLE);
1959 cpl_table_new_column(table, "offset", CPL_TYPE_DOUBLE);
1960 cpl_table_new_column(table, "mse", CPL_TYPE_DOUBLE);
1961 cpl_table_new_column(table, "wavelengthFit", CPL_TYPE_DOUBLE);
1962 cpl_table_new_column(table, "wavelengthError", CPL_TYPE_DOUBLE);
1963 cpl_table_new_column(table, "range", CPL_TYPE_INT);
1964 cpl_table_new_column_array(table, "xdata", CPL_TYPE_DOUBLE,
1965 GAUSS_PAR_RANGE_MAX);
1966 cpl_table_new_column_array(table, "ydata", CPL_TYPE_DOUBLE,
1967 GAUSS_PAR_RANGE_MAX);
1969 }
1970 CATCH
1971 {
1972
1973 }
1974 return table;
1975
1976}
1977
1978cpl_error_code eris_ifu_wave_fill_fitting_table(
1979 cpl_table *table,
1980 int row,
1981 int slitlet,
1982 int index,
1983 int arcImgIdx,
1984 int position,
1985 double wavelength,
1986 struct gaussParStruct *gaussPar)
1987{
1988 cpl_error_code retVal = CPL_ERROR_NONE;
1989 cpl_array *xArray;
1990 cpl_array *yArray;
1991
1992 TRY
1993 {
1994 cpl_table_set_int(table, ERIS_IFU_FITTABLE_SLITLET, row, slitlet);
1995 cpl_table_set_int(table, ERIS_IFU_FITTABLE_INDEX, row, index);
1996 cpl_table_set_int(table, "imgIdx", row, arcImgIdx);
1997 cpl_table_set_int(table, ERIS_IFU_FITTABLE_POSITION, row, position);
1998 cpl_table_set_double(table, ERIS_IFU_FITTABLE_WAVELENGTH, row, wavelength);
1999 cpl_table_set_int(table, ERIS_IFU_FITTABLE_ERRORCODE, row, gaussPar->errorCode);
2000 cpl_table_set_double(table, "x0", row, gaussPar->x0);
2001 cpl_table_set_double(table, "sigma", row, gaussPar->sigma);
2002 cpl_table_set_double(table, "area", row, gaussPar->area);
2003 cpl_table_set_double(table, "offset", row, gaussPar->offset);
2004 cpl_table_set_double(table, "mse", row, gaussPar->mse);
2005 cpl_table_set_int(table, "range", row, gaussPar->range);
2007 // clear data beyond range to allow reference testing;
2008 for (int ix=gaussPar->range; ix<GAUSS_PAR_RANGE_MAX; ix++) {
2009 gaussPar->xdata[ix] = 0.0;
2010 gaussPar->ydata[ix] = 0.0;
2011 }
2013 xArray = cpl_array_wrap_double(gaussPar->xdata,
2014 GAUSS_PAR_RANGE_MAX));
2016 yArray = cpl_array_wrap_double(gaussPar->ydata,
2017 GAUSS_PAR_RANGE_MAX));
2018 cpl_table_set_array(table, "xdata", row, xArray);
2019 cpl_table_set_array(table, "ydata", row, yArray);
2020 cpl_array_unwrap(xArray);
2021 cpl_array_unwrap(yArray);
2022
2023 }
2024 CATCH
2025 {
2026
2027 }
2028 return retVal;
2029}
2030cpl_table *eris_ifu_wave_create_coeff_table(
2031 int size, int polynomialDegree)
2032{
2033
2034 cpl_table *table = NULL;
2035
2036 TRY
2037 {
2039 table = cpl_table_new(size));
2040 cpl_table_new_column(table, "slitlet", CPL_TYPE_INT);
2041 cpl_table_new_column(table, "nlines", CPL_TYPE_INT);
2042 cpl_table_new_column(table, "degree", CPL_TYPE_INT);
2043 cpl_table_new_column_array(table, "coeffs", CPL_TYPE_DOUBLE,
2044 polynomialDegree+1);
2046 }
2047 CATCH
2048 {
2049
2050 }
2051 return table;
2052
2053}
2054
2055
2056cpl_error_code eris_ifu_wave_fill_coeff_table(
2057 cpl_table *table,
2058 int row,
2059 int idx,
2060 int nLines,
2061 cpl_polynomial *polynomial)
2062{
2063 cpl_error_code retVal = CPL_ERROR_NONE;
2064 cpl_array *array;
2065 cpl_size arrayDim;
2066 cpl_size degree;
2067
2068 TRY
2069 {
2070 degree = cpl_polynomial_get_degree(polynomial);
2071 arrayDim = cpl_table_get_column_dimension (table, "coeffs", 0);
2072 array = cpl_array_new(arrayDim, CPL_TYPE_DOUBLE);
2074
2075 cpl_table_set_int(table, "slitlet", row, idx);
2076 cpl_table_set_int(table, "nlines", row, nLines);
2077 cpl_table_set_int(table, "degree", row, (int) degree);
2078 for (cpl_size ix=0; ix<=degree; ix++) {
2079 cpl_array_set_double(array, ix,
2080 cpl_polynomial_get_coeff(polynomial, &ix));
2081 }
2082 cpl_table_set_array(table, "coeffs", row, array);
2083 cpl_array_delete(array);
2084
2085 }CATCH {
2086 CATCH_MSGS();
2087 }
2088 return retVal;
2089}
2090
2091cpl_error_code eris_ifu_wave_save_fitting_tables(
2092 struct waveTablesStruct *tables,
2093 ifsInstrument instrument,
2094 ifsBand band,
2095 struct waveSetupStruct waveSetup,
2096 cpl_frameset* frameset,
2097 const cpl_parameterlist* parlist,
2098 const char* recipe_name)
2099{
2100 cpl_error_code retVal = CPL_ERROR_NONE;
2101 cpl_propertylist *phdr = NULL;
2102 cpl_propertylist *hdr = NULL;
2103 const char* filename = ERIS_IFU_PRO_WAVE_FIT_TABLES_FN;
2104 const char* extname = "EXTNAME";
2105 const char *instrString;
2106 const char *bandString;
2107 int ioMode = CPL_IO_CREATE;
2108
2109 TRY
2110 {
2111 switch (instrument) {
2112 case SPIFFIER:
2113 instrString = "ERIS";
2114 break;
2115 case SPIFFI:
2116 instrString = "SINFONI";
2117 break;
2118 default:
2119 instrString = "UNKNOWN";
2120 break;
2121 }
2122 bandString = eris_ifu_get_bandString(band);
2123
2125 hdr = cpl_propertylist_new());
2127 phdr = cpl_propertylist_new());
2129 cpl_propertylist_update_string(phdr, CPL_DFS_PRO_CATG,
2130 ERIS_IFU_PRO_WAVE_FIT_TABLES));
2132 cpl_propertylist_update_string(phdr, "INSTRUME", instrString));
2134 cpl_propertylist_update_string(phdr, "BAND", bandString));
2136 cpl_propertylist_update_int(phdr, "SRANGE", waveSetup.s_range));
2138 cpl_propertylist_update_int(phdr, "CRANGE", waveSetup.c_range));
2139 /* AMO added to have proper FITS header */
2140 eris_setup_product_header(filename, ERIS_IFU_PRO_WAVE_FIT_TABLES,
2141 CPL_FRAME_TYPE_IMAGE, recipe_name,
2142 frameset, parlist, phdr);
2143
2144 if (tables->slitletFitting != NULL) {
2146 cpl_propertylist_update_string(
2147 hdr, extname, "slitletFittingTable"));
2149 cpl_table_name_column(tables->slitletFitting, "index", "block"));
2151 cpl_table_save(tables->slitletFitting,
2152 phdr, hdr, filename, ioMode));
2153 ioMode = CPL_IO_EXTEND;
2154 }
2155
2156 if (tables->columnFitting != NULL) {
2158 cpl_propertylist_update_string(
2159 hdr, extname, "columnFittingTable"));
2161 cpl_table_name_column(tables->columnFitting, "index", "column"));
2163 cpl_table_save(tables->columnFitting,
2164 phdr, hdr, filename, ioMode));
2165 ioMode = CPL_IO_EXTEND;
2166 }
2167
2168 if (tables->columnCoeffRaw != NULL) {
2170 cpl_propertylist_update_string(
2171 hdr, extname, "slitletCoeff"));
2173 cpl_table_save(tables->slitletCoeff,
2174 phdr, hdr, filename, ioMode));
2175
2177 cpl_propertylist_update_string(
2178 hdr, extname, "columnCoeffRaw"));
2180 cpl_table_save(tables->columnCoeffRaw,
2181 phdr, hdr, filename, ioMode));
2182 ioMode = CPL_IO_EXTEND;
2183 }
2184
2185 if (tables->columnCoeffSmoothed != NULL) {
2187 cpl_propertylist_update_string(
2188 hdr, extname, "columnCoeffSmoothed"));
2190 cpl_table_name_column(tables->columnCoeffSmoothed, "nlines", "dummy"));
2192 cpl_table_save(tables->columnCoeffSmoothed,
2193 phdr, hdr, filename, ioMode));
2194 ioMode = CPL_IO_EXTEND;
2195 }
2196
2197 if (tables->smoothingCoeff != NULL) {
2199 cpl_propertylist_update_string(
2200 hdr, extname, "smoothingCoeff"));
2202 cpl_table_name_column(tables->smoothingCoeff, "nlines", "order"));
2204 cpl_table_save(tables->smoothingCoeff,
2205 phdr, hdr, filename, ioMode));
2206 ioMode = CPL_IO_EXTEND;
2207 }
2208
2209 // check whether no table was written
2210 if (ioMode == CPL_IO_CREATE) {
2211 // create an "empty" FITS file
2213 cpl_image_save(NULL, filename, CPL_TYPE_FLOAT, phdr, ioMode));
2214 }
2215
2216 }
2217 CATCH
2218 {
2219
2220 }
2223 return retVal;
2224}
2225
2226void eris_ifu_wave_free_tables(
2227 struct waveTablesStruct *tables)
2228{
2229 eris_ifu_free_table(&tables->slitletFitting);
2230 eris_ifu_free_table(&tables->columnFitting);
2231 eris_ifu_free_table(&tables->slitletCoeff);
2232 eris_ifu_free_table(&tables->columnCoeffRaw);
2233 eris_ifu_free_table(&tables->columnCoeffSmoothed);
2234 eris_ifu_free_table(&tables->smoothingCoeff);
2235 return;
2236}
2237
2238void eris_ifu_wave_clear_tables(
2239 struct waveTablesStruct *tables)
2240{
2241 tables->slitletFitting = NULL;
2242 tables->columnFitting = NULL;
2243 tables->slitletCoeff = NULL;
2244 tables->columnCoeffRaw = NULL;
2245 tables->columnCoeffSmoothed = NULL;
2246 tables->smoothingCoeff = NULL;
2247 return;
2248}
2249
2250
2251
ifsPreopticsScale eris_ifu_get_preopticsScale(cpl_propertylist *header)
Return the the pre-optics scaling.
float eris_ifu_get_dit(cpl_propertylist *header)
Determine if a frame is a Sky frame or not.
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_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)
Read a raw detector exposure, perform some correction, add noise data.
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)
eris_ifu_get_lampString
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)
eris_ifu_save_image_dbg
void eris_ifu_free_table(cpl_table **item)
free memory and set pointer to null
const char * eris_ifu_get_bandString(ifsBand band)
eris_ifu_get_bandString
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
Definition: hdrl_image.c:391
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
Definition: hdrl_image.c:105
const cpl_image * hdrl_image_get_image_const(const hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:118
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
Definition: hdrl_image.c:379
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.