ERIS Pipeline Reference Manual 1.8.10
eris_ifu_flat_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
29#include "eris_ifu_error.h"
30#include "eris_ifu_utils.h"
31#include "eris_ifu_dfs.h"
32#include "eris_ifu_debug.h"
33#include "eris_ifu_flat_static.h"
34#include "eris_ifu_dark_static.h"
35#include "eris_ifu_functions.h"
36#include "eris_utils.h"
37
38/*----------------------------------------------------------------------------*/
49/*----------------------------------------------------------------------------*/
50cpl_error_code eris_ifu_flat_static(cpl_frameset *fs,
51 const cpl_parameterlist *parlist,
52 const flatMode mode,
53 int productDepth,
54 const char *procatg,
55 const char *recipe_name,
56 const char *procatg_prefix,
57 const char *instrument,
58 cpl_propertylist **qc_list,
59 hdrl_image **masterFlatHdrlImg_lo,
60 cpl_image **qualityImage)
61{
62 cpl_error_code ret = CPL_ERROR_NONE;
63 cpl_image *contrib_map = NULL;
64 cpl_mask *bpm2dMask = NULL,
65 *bpm3dMask = NULL;
66 hdrl_image *masterFlatHdrlImg_hi = NULL;
67 hdrl_imagelist *hdrl_imglist_on = NULL,
68 *hdrl_imglist_off = NULL;
69 const char *fn = NULL;
70 char *pc = NULL,
71 *tmp_str = NULL;
72 double cleanmean = 0.,
73 cleanstdev = 0.;
74
75 cpl_ensure_code(fs, CPL_ERROR_NULL_INPUT);
76 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
77 cpl_ensure_code(procatg, CPL_ERROR_NULL_INPUT);
78 cpl_ensure_code(recipe_name, CPL_ERROR_NULL_INPUT);
79 cpl_ensure_code(qc_list, CPL_ERROR_NULL_INPUT);
80 cpl_ensure_code(masterFlatHdrlImg_lo, CPL_ERROR_NULL_INPUT);
81 cpl_ensure_code(qualityImage, CPL_ERROR_NULL_INPUT);
82
83 TRY
84 {
85 /* Load flat frames and mask bad pixels */
86 double gain = 0., exptime = 0.;
87 eris_ifu_flat_load_frames(fs,
88 &gain, &exptime,
89 &hdrl_imglist_on,
90 &hdrl_imglist_off);
91
92 *qc_list = cpl_propertylist_new();
93
94 cpl_propertylist_append_string(*qc_list, CPL_DFS_PRO_CATG,
95 procatg);
96
97 /* calc QC before flat calculation*/
98 eris_ifu_flat_calc_qc_pre(parlist,
99 recipe_name,
100 hdrl_imglist_on,
101 hdrl_imglist_off,
102 *qc_list);
103
104 /* Performing data reduction */
105 /* we need the band ID to be able to set proper value of threshold to
106 * detect IFU slices
107 */
108 cpl_frame* raw_flat_lamp = NULL;
109
110 if (NULL != cpl_frameset_find(fs, ERIS_IFU_RAW_FLAT_LAMP)){
111 raw_flat_lamp = cpl_frameset_find(fs, ERIS_IFU_RAW_FLAT_LAMP);
112
113 } else if (cpl_frameset_count_tags(fs, ERIS_IFU_RAW_FLAT_LAMP_ON) > 0) {
114
115 raw_flat_lamp = cpl_frameset_find(fs, ERIS_IFU_RAW_FLAT_LAMP_ON);
116
117 } else if (NULL != cpl_frameset_find(fs, ERIS_IFU_RAW_FLAT_LAMP_ON)){
118 raw_flat_lamp = cpl_frameset_find(fs, ERIS_IFU_RAW_FLAT_LAMP_ON);
119
120 } else if (cpl_frameset_count_tags(fs, ERIS_IFU_RAW_FLAT_NS_ON) > 0) {
121
122 raw_flat_lamp = cpl_frameset_find(fs, ERIS_IFU_RAW_FLAT_NS_ON);
123 } else {
124 raw_flat_lamp = cpl_frameset_find(fs, ERIS_IFU_RAW_FLAT_NS);
125 }
126 const char* fname = cpl_frame_get_filename(raw_flat_lamp);
127 cpl_propertylist* header = cpl_propertylist_load(fname, 0);
128 ifsBand band = eris_ifu_get_band(header);
129 cpl_propertylist_delete(header);
130 eris_ifu_calc_flat(parlist,
131 recipe_name,
132 mode,
133 hdrl_imglist_on,
134 hdrl_imglist_off,
135 productDepth,
136 band,
137 masterFlatHdrlImg_lo,
138 &masterFlatHdrlImg_hi,
139 &contrib_map);
140
141 if (productDepth & 4) {
143 tmp_str = cpl_sprintf("%s_dbg_flat_masterflat.fits", recipe_name));
144 eris_ifu_save_hdrl_image_dbg(*masterFlatHdrlImg_lo,
145 "eris_ifu_distortion_dbg_flat_02_masterflat",
146 TRUE, NULL);
147 eris_ifu_free_string(&tmp_str);
148 }
149
150 // do this crappy bpm-calculation only if segemtn-mode hasn't been chosen
151 if (mode != FLAT_MODE_SEGMENT) {
152
153 // // check only for distortoin-recipe: if is (H or K) and 25mas
154 // fr = cpl_frameset_find_const(fs, ERIS_IFU_RAW_FLAT_NS);
155 // if (fr != NULL) {
156 // BRK_IF_NULL(
157 // header = cpl_propertylist_load(cpl_frame_get_filename(fr), 0));
158 // BRK_IF_NULL(
159 // tmp_band = cpl_propertylist_get_string(header, FHDR_E_GRATING_ID));
160 // BRK_IF_NULL(
161 // band = cpl_sprintf("%s", tmp_band));
162 // scaleId = eris_ifu_get_preopticsScale(header);
163 // CHECK_ERROR_STATE();
164 // eris_ifu_free_propertylist(&header);
165 // }
166 //
167 // if ((scaleId == S25MAS) && (strcmp(band, "K_low") == 0)) {
168 // //erw is_K_low_and_25mas = CPL_TRUE;
169 // }
170 // eris_ifu_free_string(&band);
171
172
173 /* Create & apply bad-pixel-mask */
174 //erw if ((strcmp(recipe_name, REC_NAME_DISTORTION) == 0) &&
175 // !is_K_low_and_25mas)
176 if (strcmp(recipe_name, REC_NAME_DISTORTION) == 0)
177 {
178 // only for distortion recipe (except K_low_25mas)
179 double maxcut = 50000.,
180 mincut = 0.1;
181 char *band_name = NULL;
182 cpl_frame *fr = NULL;
183// const char *fn = NULL;
184 cpl_propertylist *plist = NULL;
185
186 fr = cpl_frameset_find(fs, ERIS_IFU_RAW_FLAT_NS);
187 fn = cpl_frame_get_filename(fr);
188 plist = cpl_propertylist_load(fn, 0);
189
190 if (strcmp(instrument, INSTRUMENT_ERIS) == 0) {
191 // ERIS
192 const char *tmp_band = NULL;
193 tmp_band = cpl_propertylist_get_string(plist,
194 FHDR_E_FILTER_ID);
195 band_name = cpl_sprintf("%c", tmp_band[0]);
196 } else {
197 // SINFONI
198 band_name = cpl_sprintf("%s", cpl_propertylist_get_string(plist,
199 FHDR_S_FILTER_NAME));
200 }
201
202 // HDRL flatfielding can't handle slitlets with low illumination...
203 if (true/*(strcmp(instrument, INSTRUMENT_SINFONI) == 0) ||
204 ((strcmp(instrument, INSTRUMENT_ERIS) == 0) &&
205 (strcmp(band, "J") == 0))*/)
206 {
207 // distortion-recipe +
208 // either SINFONI-instrument
209 // or ERIS-Instrument and J-band
210
211 /* SINFONI-way to compute the BP-map*/
212 hdrl_image **med = NULL,
213 *original = NULL;
214 double sigma = 2.,
215 loReject = 0.1,
216 hiReject = 0.1;
217 int llx = 1350,
218 lly = 1000,
219 urx = 1390,
220 ury = 1200,
221 meanfactor = 999,
222 n_iter = 8;
223 double mjd_obs = 0.;
224
225 mjd_obs = cpl_propertylist_get_double(plist, FHDR_MJD_OBS);
227
228 /* special check in case of J band distortion data
229 * after 31/01/2018 */
230 if ((strcmp(band_name, "J") == 0) && (mjd_obs > 58150.)) {
231 mincut = 0.05;
232 }
233
234 original = hdrl_image_duplicate(*masterFlatHdrlImg_lo);
235
236 if (productDepth & 4) {
237 eris_ifu_save_hdrl_image_dbg(*masterFlatHdrlImg_lo,
238 "eris_ifu_distortion_dbg_flat_03_bad_medIm",
239 TRUE, NULL);
240 }
241 /* remove the intensity tilt from every column and compute the
242 * standard deviation on a rectangular zone */
243
244 /* update BP-mask and expand it by thresholding */
245 eris_ifu_flat_thresh_mask(*masterFlatHdrlImg_lo,
246 mincut, maxcut);
247
248 if (productDepth & 4) {
249 eris_ifu_save_hdrl_image_dbg(*masterFlatHdrlImg_lo,
250 "eris_ifu_distortion_dbg_flat_04_bad_medIm_cut",
251 TRUE, NULL);
252 }
253
254 eris_ifu_column_tilt(*masterFlatHdrlImg_lo, sigma);
255
256 if (productDepth & 4) {
257 eris_ifu_save_hdrl_image_dbg(*masterFlatHdrlImg_lo,
258 "eris_ifu_distortion_dbg_flat_05_bad_colImage",
259 TRUE, NULL);
260 }
261 eris_ifu_flat_stats_rectangle(*masterFlatHdrlImg_lo,
262 loReject, hiReject,
263 llx, lly, urx, ury,
264 &cleanmean,
265 &cleanstdev);
266
267 /* indicate pixels with great deviations from the clean mean as bad */
268 eris_ifu_flat_thresh_mask(*masterFlatHdrlImg_lo,
269 cleanmean - meanfactor*cleanstdev,
270 cleanmean + meanfactor*cleanstdev);
271 if (productDepth & 4) {
272 eris_ifu_save_hdrl_image_dbg(*masterFlatHdrlImg_lo,
273 "eris_ifu_distortion_dbg_flat_06_bad_threshIm",
274 TRUE, NULL);
275 }
276
277 med = (hdrl_image**)cpl_calloc(n_iter, sizeof(hdrl_image*));
278
279 med[0] = eris_ifu_flat_median_image(*masterFlatHdrlImg_lo,
280 -meanfactor*cleanstdev);
281
282 for (int i = 0; i< n_iter-1; i++) {
283 med[i+1] = eris_ifu_flat_median_image(med[i],
284 -meanfactor*cleanstdev);
285 }
286
287 /* compare the filtered image with the input image */
288 eris_ifu_sinfo_compare_images(*masterFlatHdrlImg_lo,
289 med[n_iter-1],
290 original);
291 if (productDepth & 4) {
293 "eris_ifu_distortion_dbg_flat_07_bad_compImage",
294 TRUE, NULL);
295 }
296
297 eris_ifu_free_hdrl_image(masterFlatHdrlImg_lo);
298 *masterFlatHdrlImg_lo = original;
299
300 for (int i = 0; i< n_iter; i++) {
302 }
303 cpl_free(med); med = NULL;
304 } else {
305 // distortion-recipe + ERIS-instrument
306
307 /* HDRL-way to compute the BP-map*/
308 eris_ifu_calc_bpm(parlist,
309 recipe_name,
310 *masterFlatHdrlImg_lo, // needed for 2dbpm
311 hdrl_imglist_on, // needed for 3dbpm
312 &bpm2dMask, &bpm3dMask); // return values
313
314 /* update BP-mask and expand it by thresholding */
315 eris_ifu_flat_thresh_mask(*masterFlatHdrlImg_lo,
316 mincut, maxcut);
317 }
318 eris_ifu_free_string(&band_name);
320 } else {
321 // not distortion-recipe + any instrument
322
323 /* HDRL-way to compute the BP-map*/
324 eris_ifu_calc_bpm(parlist,
325 recipe_name,
326 *masterFlatHdrlImg_lo, // needed for 2dbpm
327 hdrl_imglist_on, // needed for 3dbpm
328 &bpm2dMask, &bpm3dMask); // return values
329 }
330 } // if (mode != FLAT_MODE_SEGMENT)
331
332 /* calc QC after flat calculation*/
333 eris_ifu_flat_calc_qc_post(parlist,
334 recipe_name,
335 productDepth,
336 procatg_prefix,
337 masterFlatHdrlImg_hi,
338 *masterFlatHdrlImg_lo,
339 hdrl_imglist_on,
340 hdrl_imglist_off,
341 contrib_map,
342 // bpm2dImg,
343 // bpm3dImg,
344 bpm2dMask,
345 bpm3dMask,
346 fs,
347 *qc_list,
348 qualityImage);
349 } CATCH {
350 CATCH_MSGS();
351
352 ret = cpl_error_get_code();
353
355 eris_ifu_free_hdrl_image(masterFlatHdrlImg_lo);
356 eris_ifu_free_image(qualityImage);
357 }
358
359 eris_ifu_free_hdrl_image(&masterFlatHdrlImg_hi);
360 eris_ifu_free_hdrl_imagelist(&hdrl_imglist_on);
361 eris_ifu_free_hdrl_imagelist(&hdrl_imglist_off);
362 eris_ifu_free_image(&contrib_map);
363 // eris_ifu_free_image(&bpm2dImg);
364 // eris_ifu_free_image(&bpm3dImg);
365 eris_ifu_free_mask(&bpm2dMask);
366 eris_ifu_free_mask(&bpm3dMask);
367// eris_ifu_free_string(&fn);
369 eris_check_error_code("eris_ifu_flat_static");
370
371 return ret;
372}
373
374double eris_ifu_getThreshold(hdrl_image *img) {
375 cpl_ensure(img != NULL, CPL_ERROR_ILLEGAL_INPUT, NAN);
376 double val = 0.;
377 TRY {
378 val = .3 * hdrl_image_get_mean(img).data;
379 } CATCH {
380 CATCH_MSGS();
381 val = NAN;
382 }
383 eris_check_error_code("eris_ifu_getThreshold");
384 return val;
385}
386
387int eris_ifu_matchRow(int blocksize, int rx) {
388 cpl_ensure(blocksize > 0, CPL_ERROR_ILLEGAL_INPUT, -1);
389 cpl_ensure(rx >= 0, CPL_ERROR_ILLEGAL_INPUT, -1);
390 cpl_ensure(rx < ERIS_IFU_DETECTOR_SIZE_X, CPL_ERROR_ILLEGAL_INPUT, -1);
391
392 int val = 0;
393 TRY {
394 val = (int)((rx-4)/blocksize + 0.5);
395 } CATCH {
396 CATCH_MSGS();
397 val = -1;
398 }
399 eris_check_error_code("eris_ifu_matchRow");
400 return val;
401}
402
403
404void eris_ifu_free_structFlatData(struct structFlatData* sfd) {
405
406 if(sfd != NULL) {
407 if(sfd->ry != NULL) cpl_vector_delete(sfd->ry);
408 if(sfd->borderAleft != NULL) cpl_vector_delete(sfd->borderAleft);
409 if(sfd->borderAright != NULL) cpl_vector_delete(sfd->borderAright);
410 if(sfd->borderBleft != NULL) cpl_vector_delete(sfd->borderBleft);
411 if(sfd->borderBright != NULL) cpl_vector_delete(sfd->borderBright);
412 if(sfd->borderCleft != NULL) cpl_vector_delete(sfd->borderCleft);
413 if(sfd->borderCright != NULL) cpl_vector_delete(sfd->borderCright);
414 if(sfd->borderDleft != NULL) cpl_vector_delete(sfd->borderDleft);
415 if(sfd->borderDright != NULL) cpl_vector_delete(sfd->borderDright);
416 }
417 eris_check_error_code("eris_ifu_free_structFlatData");
418 return;
419}
420
421/*----------------------------------------------------------------------------*/
442/*----------------------------------------------------------------------------*/
443cpl_error_code eris_ifu_calc_flat(const cpl_parameterlist *parlist,
444 const char *recipe_name,
445 const flatMode mode,
446 const hdrl_imagelist *hdrl_imglist_on,
447 const hdrl_imagelist *hdrl_imglist_off,
448 int productDepth,
449 ifsBand band,
450 hdrl_image **masterFlatHdrlImg_lo,
451 hdrl_image **masterFlatHdrlImg_hi,
452 cpl_image **contrib_map)
453{
454 cpl_error_code ret = CPL_ERROR_NONE;
455 cpl_image *noiseImage = NULL;
456 hdrl_image *fastFlatImg = NULL;
457 hdrl_parameter *pHdrlCollapse = NULL,
458 *pHdrlFlat_lo = NULL,
459 *pHdrlFlat_hi = NULL;
460 hdrl_imagelist *tmp_hdrl_imglist = NULL,
461 *tmp_hdrl_imglist2 = NULL;
462 char *tmp_str = NULL;
463
464 cpl_ensure_code(hdrl_imglist_on, CPL_ERROR_NULL_INPUT);
465 cpl_ensure_code(recipe_name, CPL_ERROR_NULL_INPUT);
466 cpl_ensure_code(hdrl_imglist_off, CPL_ERROR_NULL_INPUT);
467 cpl_ensure_code(masterFlatHdrlImg_lo, CPL_ERROR_NULL_INPUT);
468 cpl_ensure_code(contrib_map, CPL_ERROR_NULL_INPUT);
469
470 TRY
471 {
472 cpl_msg_info(cpl_func, "Generating master flat image...");
473
474 /* load collapse parameters */
475 tmp_str = cpl_sprintf("eris.%s.collapse", recipe_name);
476 pHdrlCollapse = hdrl_collapse_parameter_parse_parlist(parlist,
477 tmp_str);
478 eris_ifu_free_string(&tmp_str);
479
480 if (mode == FLAT_MODE_FAST) {
481 /* just subtract on- and off-frames and collapse */
482 cpl_msg_info(cpl_func, " Fast-mode");
483
484 /*
485 * subtract and collapse flat images
486 */
487 tmp_hdrl_imglist = hdrl_imagelist_duplicate(hdrl_imglist_on);
488
489 hdrl_imagelist_sub_imagelist(tmp_hdrl_imglist, hdrl_imglist_off);
490
491 hdrl_imagelist_collapse(tmp_hdrl_imglist,
492 pHdrlCollapse,
493 masterFlatHdrlImg_lo,
494 contrib_map);
495
496 /*
497 * smoothen masterflat & restore bpm
498 */
499 cpl_image *tmpFilteredImg = cpl_image_new(
500 hdrl_image_get_size_x(*masterFlatHdrlImg_lo),
501 hdrl_image_get_size_y(*masterFlatHdrlImg_lo),
502 cpl_image_get_type(hdrl_image_get_image(*masterFlatHdrlImg_lo)));
503
504 cpl_matrix *filterKernel = cpl_matrix_new(5,3);
505 cpl_matrix_set(filterKernel, 0, 1 ,1.0);
506 cpl_matrix_set(filterKernel, 1, 1 ,2.0);
507 cpl_matrix_set(filterKernel, 2, 1 ,3.0);
508 cpl_matrix_set(filterKernel, 3, 1 ,2.0);
509 cpl_matrix_set(filterKernel, 4, 1 ,1.0);
510 cpl_matrix_set(filterKernel, 2, 0 ,1.5);
511 cpl_matrix_set(filterKernel, 2, 2 ,1.5);
512 cpl_image_filter(tmpFilteredImg,
513 hdrl_image_get_image(*masterFlatHdrlImg_lo),
514 filterKernel, CPL_FILTER_LINEAR, CPL_BORDER_FILTER);
515 cpl_image_reject_from_mask(tmpFilteredImg,
516 cpl_image_get_bpm(hdrl_image_get_error(*masterFlatHdrlImg_lo)));
517
518 fastFlatImg = hdrl_image_create(tmpFilteredImg,
519 hdrl_image_get_error(*masterFlatHdrlImg_lo));
520
521 hdrl_image_delete(*masterFlatHdrlImg_lo);
522 *masterFlatHdrlImg_lo = fastFlatImg;
523
524 if (productDepth & 4) {
525 tmp_str = cpl_sprintf("%s_dbg_flat_fast.fits", recipe_name);
526 eris_ifu_save_image_dbg(tmpFilteredImg, tmp_str, CPL_IO_CREATE, NULL);
527 eris_ifu_free_string(&tmp_str);
528 }
529
530 eris_ifu_free_image(&tmpFilteredImg);
531 eris_ifu_free_matrix(&filterKernel);
532
533 hdrl_image_div_scalar(*masterFlatHdrlImg_lo,
534 hdrl_image_get_median(*masterFlatHdrlImg_lo));
535 } else if (mode == FLAT_MODE_HDRL) {
536 /* the HDRL-way to create a masterflat (not well suited to
537 spectroscopic raw data) */
538 cpl_msg_info(cpl_func, " HDRL-mode");
539
540 /* load flat parameters */
541 tmp_str = cpl_sprintf("eris.%s.flat_lo", recipe_name);
542
543 pHdrlFlat_lo = hdrl_flat_parameter_parse_parlist(parlist, tmp_str);
544 eris_ifu_free_string(&tmp_str);
545
546 /* Do the actual flatfield computation, bp_mask has already been
547 applied when loading images */
548 tmp_hdrl_imglist = hdrl_imagelist_duplicate(hdrl_imglist_on);
549 if (hdrl_imagelist_get_size(tmp_hdrl_imglist) ==
550 hdrl_imagelist_get_size(hdrl_imglist_off))
551 {
552 hdrl_imagelist_sub_imagelist(tmp_hdrl_imglist,
553 hdrl_imglist_off);
554 } else {
555 cpl_msg_warning(cpl_func, "#off and #on frames isn't the same! "
556 "So no off-frames are subtracted at all.");
557 }
558
559 if (productDepth & 1) {
560 /* calculate as well hi-freq flatfield */
561 tmp_str = cpl_sprintf("eris.%s.flat_hi", recipe_name);
562 pHdrlFlat_hi = hdrl_flat_parameter_parse_parlist(parlist,
563 tmp_str);
564 eris_ifu_free_string(&tmp_str);
565
566 tmp_hdrl_imglist2 = hdrl_imagelist_duplicate(tmp_hdrl_imglist);
567 hdrl_flat_compute(tmp_hdrl_imglist2, NULL,
568 pHdrlCollapse, pHdrlFlat_hi,
569 masterFlatHdrlImg_hi, contrib_map);
570 eris_ifu_free_hdrl_imagelist(&tmp_hdrl_imglist2);
571 eris_ifu_free_image(contrib_map);
572 }
573
574 if (productDepth & 4) {
575 tmp_str = cpl_sprintf("eris_ifu_%s_dbg_flat_01_sub", recipe_name);
576 eris_ifu_save_hdrl_imagelist_dbg(hdrl_imglist_on,
577 tmp_str,
578 TRUE);
579 eris_ifu_free_string(&tmp_str);
580 }
581
582 /* hdrl_flat_compute() gives unnecessary warning with pHdrlFlat_lo */
583 cpl_msg_severity level = cpl_msg_get_level();
584 cpl_msg_set_level(CPL_MSG_ERROR);
585
586 /* calculate lo-freq flatfield */
587 hdrl_flat_compute(tmp_hdrl_imglist, NULL,
588 pHdrlCollapse, pHdrlFlat_lo,
589 masterFlatHdrlImg_lo, contrib_map);
590 cpl_msg_set_level(level);
591 eris_ifu_free_hdrl_imagelist(&tmp_hdrl_imglist);
592
594 hdrl_image_get_image(*masterFlatHdrlImg_lo),
595 false, NULL);
596 } else if (mode == FLAT_MODE_SEGMENT) {
597 /* do a segmented flat-calculation*/
598 cpl_msg_info(cpl_func, " Segment-mode");
599
600 hdrl_image *masterFlat = NULL,
601 *subImg = NULL,
602 *subImgA = NULL,
603 *subImgD = NULL,
604 *tmpImg = NULL;
605 int sx = 0,
606 sy = 0,
607 rej = 0,
608 blockSize = 40,
609 nLower = 0,
610 offset = 40,
611 leftEdgeA = 0,
612 leftEdgeB = 0,
613 leftEdgeC = 0,
614 leftEdgeD = 0,
615 rightEdgeA = 0,
616 rightEdgeB = 0,
617 rightEdgeC = 0,
618 rightEdgeD = 0;
619 double columnThreshold = .70, //70% of mean (65% for K band)
620 thresholdA = 0.,
621 thresholdD = 0.,
622 coldThreshold = 0.,
623 *pdnewcleanRowBC = NULL,
624 *pborders = NULL,
625 *psubImg = NULL;
626 const double *pcleanRow = NULL;
627 cpl_vector *cleanRow = NULL,
628 *dnewcleanRowBC = NULL,
629 *sample = NULL,
630 *sample2 = NULL,
631 *borders = NULL;
632 hdrl_value medianA,
633 medianD;
634 struct structFlatData Data;
635 if(band == K_LOW ||
636 band == K_SHORT ||
637 band == K_MIDDLE ||
638 band == K_LONG){
639 columnThreshold = .65;
640 }
641
642 /*
643 * just collapse flat-on images (don't even subtract flat_off-images)
644 */
645 hdrl_imagelist_collapse(hdrl_imglist_on,
646 pHdrlCollapse,
647 &masterFlat,
648 contrib_map);
649
650 eris_ifu_flat_data_init(&Data, blockSize);
651
652 // loop horizontal segments of height=blockSize (e.g. 40 rows)
653 // c-notation for ry (from 4 to 2040)
654 //
655 // get borders of blocks A, B, C, D
656 for(int ry = ERIS_IFU_DETECTOR_BP_BORDER;
657 ry < ERIS_IFU_DETECTOR_SIZE_Y-ERIS_IFU_DETECTOR_BP_BORDER;
658 ry += blockSize)
659 {
660 subImg = hdrl_image_extract(masterFlat,
661 1, ry+1,
662 ERIS_IFU_DETECTOR_SIZE_X,
663 ry+1+blockSize-1);
664 cleanRow = eris_ifu_image_collapse(
666 pcleanRow = cpl_vector_get_data_const(cleanRow);
667
668 // flat field image is sliced in 4 major columns
669 // col A (slitlet 9 ... 16) [1..15] (exposure: x=[50:900])
670 // cal B (slitlet 1) [16]
671 // col C (slitlet 32) [17]
672 // col D (slitlet 17 ... 24) [18..32]
673 subImgA = hdrl_image_extract(subImg, 50+1, 1,
674 900+1, blockSize);
675 // find right edge of cols A
676 medianA = hdrl_image_get_median(subImgA);
677 thresholdA = medianA.data * columnThreshold;
678 nLower = 0;
679 for (int cx = 920; cx <= 1100; cx++) {
680 if (pcleanRow[cx] < thresholdA) {
681 if (nLower == 0) rightEdgeA = cx;
682 nLower += 1;
683 if (nLower > 1) break;
684 } else {
685 nLower = 0;
686 }
687 }
688
689 // find left edge of cols A
690 nLower = 0;
691 leftEdgeA = 4;
692 for (int cx = 60; cx >= 4; cx--) {
693 if (pcleanRow[cx] < thresholdA) {
694 if (nLower == 0) leftEdgeA = cx;
695 nLower += 1;
696 if (nLower > 3) break;
697 } else {
698 nLower = 0;
699 leftEdgeA = 4;
700 }
701 }
702
703
704 int Dleft = 1150,
705 Dright = 2000;
706 subImgD = hdrl_image_extract(subImg, Dleft+1, 1,
707 Dright+1, blockSize);
708 // find right edge of cols D
709 medianD = hdrl_image_get_median(subImgD);
710 thresholdD = medianD.data * columnThreshold;
711 nLower = 0;
712 rightEdgeD = 2044;
713 for (int cx = 1980; cx <= 2047; cx++) {
714 if (pcleanRow[cx] < thresholdD) {
715 if (nLower == 0) rightEdgeD = cx;
716 nLower += 1;
717 if (nLower > 6) break;
718 } else {
719 nLower = 0;
720 rightEdgeD = 2044;
721 }
722 }
723
724 // find left edge of cols D
725 nLower = 0;
726 for (int cx = 1140; cx >= 1000; cx--) {
727 if (pcleanRow[cx] < thresholdD) {
728 if (nLower == 0) leftEdgeD = cx;
729 nLower += 1;
730 if (nLower > 3) break;
731 } else {
732 nLower = 0;
733 }
734 }
735 leftEdgeD -= 2;
736 // get the derivative
737 // and find the peak at beginning of col C (slitlet 32) [17]
738 // first mini peak of col B (slitlet 1) [16]
739 // the negative peak at the end of col C
740 dnewcleanRowBC = cpl_vector_new(ERIS_IFU_DETECTOR_SIZE_X);
741 pdnewcleanRowBC = cpl_vector_get_data(dnewcleanRowBC);
742 for (int i = 0; i < ERIS_IFU_DETECTOR_SIZE_X-1; i++) {
743 pdnewcleanRowBC[i] = pcleanRow[i+1]- pcleanRow[i];
744 }
745
746 int start = rightEdgeA + 1;
747 sample = cpl_vector_extract(dnewcleanRowBC, start, leftEdgeD-1, 1);
748 sample2 = cpl_vector_extract(sample, 40, cpl_vector_get_size(sample)-1, 1);
749 leftEdgeC = cpl_vector_get_maxpos(sample2) + offset + 1;
750 eris_ifu_free_vector(&sample2);
751
752 sample2 = cpl_vector_extract(sample, 0, leftEdgeC-10-1, 1);
753 leftEdgeB = cpl_vector_get_maxpos(sample2) - 4;
754 eris_ifu_free_vector(&sample2);
755 rightEdgeC = cpl_vector_get_minpos(sample);
756 rightEdgeB = leftEdgeC - 2;
757 leftEdgeC += start;
758 leftEdgeB += start;
759 rightEdgeC += start;
760 rightEdgeB += start;
761
762 eris_ifu_flat_data_setBorders(&Data, ry,
763 leftEdgeA, rightEdgeA,
764 leftEdgeB, rightEdgeB,
765 leftEdgeC, rightEdgeC,
766 leftEdgeD, rightEdgeD);
767
768 // free memory
770 eris_ifu_free_hdrl_image(&subImgA);
771 eris_ifu_free_hdrl_image(&subImgD);
772 eris_ifu_free_vector(&cleanRow);
773 eris_ifu_free_vector(&dnewcleanRowBC);
774 eris_ifu_free_vector(&sample);
775 } // end for ry
777
778 // interpolate borders of blocks A, B, C, D
779 for(int ry = ERIS_IFU_DETECTOR_BP_BORDER;
780 ry < ERIS_IFU_DETECTOR_SIZE_Y-ERIS_IFU_DETECTOR_BP_BORDER;
781 ry += blockSize)
782 {
783 subImg = hdrl_image_extract(masterFlat,
784 1, ry+1,
785 ERIS_IFU_DETECTOR_SIZE_X,
786 ry+1+blockSize-1);
787 psubImg = cpl_image_get_data(hdrl_image_get_image(subImg));
788
789 borders = eris_ifu_flat_data_getBorderInterpolated(&Data, ry);
790 pborders = cpl_vector_get_data(borders);
791
792 leftEdgeA = pborders[0];
793 rightEdgeA = pborders[1];
794 leftEdgeB = pborders[2];
795 rightEdgeB = pborders[3];
796 leftEdgeC = pborders[4];
797 rightEdgeC = pborders[5];
798 leftEdgeD = pborders[6];
799 rightEdgeD = pborders[7];
800
801 // mark columns between major columns A..D as bad
802 sx = hdrl_image_get_size_x(subImg);
803 sy = hdrl_image_get_size_y(subImg);
804 if (4+1 <= leftEdgeA+1) {
805 for (int x = 4; x <= leftEdgeA; x++) {
806 for (int y = 0; y < sy; y++) {
808 hdrl_image_reject(subImg, x+1, y+1));
809 }
810 }
811 }
812
813 for (int x = rightEdgeA; x < leftEdgeB; x++) {
814 for (int y = 0; y < sy; y++) {
816 hdrl_image_reject(subImg, x+1, y+1));
817 }
818 }
819
820 for (int x = rightEdgeB; x < leftEdgeC; x++) {
821 for (int y = 0; y < sy; y++) {
823 hdrl_image_reject(subImg, x+1, y+1));
824 }
825 }
826
827 for (int x = rightEdgeC; x < leftEdgeD; x++) {
828 for (int y = 0; y < sy; y++) {
830 hdrl_image_reject(subImg, x+1, y+1));
831 }
832 }
833
834 if (rightEdgeD+1<=2044) {
835 for (int x = rightEdgeD; x < 2044; x++) {
836 for (int y = 0; y < sy; y++) {
838 hdrl_image_reject(subImg, x+1, y+1));
839 }
840 }
841 }
842
843 // mark pixel lower than threshold as bad in cols A..B
845 tmpImg = hdrl_image_extract(subImg, leftEdgeA+1, 1, rightEdgeA+1+1, sy));
846 coldThreshold = eris_ifu_getThreshold(tmpImg);
847 for (int x = leftEdgeA; x < rightEdgeA+1; x++) {
848 for (int y = 0; y < sy; y++) {
849 if (psubImg[x+y*sx] < coldThreshold) {
851 hdrl_image_reject(subImg, x+1, y+1));
852 }
853 }
854 }
856
857 tmpImg = hdrl_image_extract(subImg, leftEdgeB+1, 1, rightEdgeB+1+1, sy);
858 coldThreshold = eris_ifu_getThreshold(tmpImg);
859 for (int x = leftEdgeB; x < rightEdgeB+1; x++) {
860 for (int y = 0; y < sy; y++) {
861 if (psubImg[x+y*sx] < coldThreshold) {
863 hdrl_image_reject(subImg, x+1, y+1));
864 }
865 }
866 }
868 //cpl_msg_warning(cpl_func,"leftEdgeC: %d rightEdgeC: %d",leftEdgeC,rightEdgeC);
869 tmpImg = hdrl_image_extract(subImg, leftEdgeC+1, 1, rightEdgeC+1+1, sy);
870 coldThreshold = eris_ifu_getThreshold(tmpImg);
871 for (int x = leftEdgeC; x < rightEdgeC+1; x++) {
872 for (int y = 0; y < sy; y++) {
873 if (psubImg[x+y*sx] < coldThreshold) {
875 hdrl_image_reject(subImg, x+1, y+1));
876 }
877 }
878 }
880
881 tmpImg = hdrl_image_extract(subImg, leftEdgeD+1, 1, rightEdgeD+1+1, sy);
882 coldThreshold = eris_ifu_getThreshold(tmpImg);
883 for (int x = leftEdgeD; x < rightEdgeD+1; x++) {
884 for (int y = 0; y < sy; y++) {
885 if (psubImg[x+y*sx] < coldThreshold) {
887 hdrl_image_reject(subImg, x+1, y+1));
888 }
889 }
890 }
892
893 // copy subImg back to masterFlat
894 for (int x = 1; x <= ERIS_IFU_DETECTOR_SIZE_X; x++) {
895 int y2 = 1;
896 for (int y = ry+1; y <= ry+1+blockSize-1; y++) {
897 hdrl_image_set_pixel(masterFlat, x, y, hdrl_image_get_pixel(subImg, x, y2++, &rej));
899 if (rej == 1) {
901 hdrl_image_reject(masterFlat, x, y));
902 }
903 }
904 }
905
906 // free memory
908 eris_ifu_free_vector(&borders);
909 } // end for ry
911
912 // more that 8 bad pixels in a row indicate an absorption line
913 const double *pleftA = cpl_vector_get_data_const(Data.borderAleft),
914 *prightD = cpl_vector_get_data_const(Data.borderDright);
915 for (int rx = 4; rx < 2044; rx++) {
916 bool lineCheck = false;
917 int bpCnt = 0,
918 startPos = 0,
919 rowIndex = eris_ifu_matchRow(blockSize, rx);
920
921 for (int colx = pleftA[rowIndex]; colx < prightD[rowIndex]+1; colx++) {
922 int rx_left = rx+3;
923 if (rx_left > 2044) {
924 rx_left = 2044;
925 }
926 int rx_right = rx-3;
927 if (rx_right < 4) {
928 rx_right = 4;
929 }
930 if (hdrl_image_is_rejected(masterFlat, rx+1, colx+1) &&
931 !hdrl_image_is_rejected(masterFlat, rx_left+1, colx+1) &&
932 !hdrl_image_is_rejected(masterFlat, rx_right+1, colx+1))
933 {
934 if (lineCheck == false) {
935 startPos = colx;
936 lineCheck = true;
937 }
938 bpCnt += 1;
939 } else {
940 if (lineCheck) {
941 double cPix = hdrl_image_get_pixel(masterFlat, rx+1, colx+1, &rej).data,
942 cPixBefore = hdrl_image_get_pixel(masterFlat, rx+1, colx+1-1, &rej).data,
943 cPixAfter = hdrl_image_get_pixel(masterFlat, rx+1, colx+1+1, &rej).data,
944 thresh = cPix * .2;
946 if ((fabs(cPix - cPixBefore) < thresh) &&
947 (fabs(cPix - cPixAfter) < thresh))
948 {
949 bpCnt += 1;
950 } else {
951 if (bpCnt > 8) {
952 for (int ax = startPos; ax < colx; ax++) {
954 hdrl_image_reject(masterFlat, rx+1, ax+1));
955 }
956 }
957 lineCheck = false;
958 bpCnt = 0;
959 }
960 }
961 }
962 }
963 }
964
965 // now finally normalize
966 hdrl_value a = hdrl_image_get_mean(masterFlat);
967 hdrl_image_div_scalar(masterFlat, a);
969
970 *masterFlatHdrlImg_lo = masterFlat;
971 eris_ifu_free_structFlatData(&Data);
972 } else {
973 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT, "Wrong mode provided.");
974 }
975 }
976 CATCH
977 {
978 eris_ifu_free_hdrl_image(masterFlatHdrlImg_lo);
979 eris_ifu_free_image(contrib_map);
980 if (productDepth & 1) {
981 eris_ifu_free_hdrl_image(masterFlatHdrlImg_hi);
982 }
983 ret = cpl_error_get_code();
984 }
985
986 eris_ifu_free_image(&noiseImage);
987 eris_ifu_free_hdrl_imagelist(&tmp_hdrl_imglist);
988 eris_ifu_free_hdrl_parameter(&pHdrlCollapse);
989 eris_ifu_free_hdrl_parameter(&pHdrlFlat_lo);
990 eris_ifu_free_hdrl_parameter(&pHdrlFlat_hi);
991 eris_ifu_free_string(&tmp_str);
992 eris_check_error_code("eris_ifu_calc_flat");
993 return ret;
994}
995
996/*----------------------------------------------------------------------------*/
1015/*----------------------------------------------------------------------------*/
1016cpl_error_code eris_ifu_flat_load_frames(const cpl_frameset *fs,
1017 double *gain,
1018 double *exptime,
1019 hdrl_imagelist **hdrl_imglist_on,
1020 hdrl_imagelist **hdrl_imglist_off)
1021{
1022 cpl_error_code err = CPL_ERROR_NONE;
1023 cpl_frameset *fs_extracted = NULL;
1024 cpl_frameset *fs_off = NULL;
1025 hdrl_image *tmp_img = NULL;
1026 cpl_propertylist *plist = NULL;
1027 cpl_mask *bpm_dark = NULL,
1028 *bpm_dist = NULL,
1029 *bpm_detlin = NULL;
1030 const cpl_frame *fr = NULL;
1031 const char *fn = NULL;
1032 char *tag = NULL;
1033 bool first_on = false;
1034 int nr_on = 0,
1035 nr_off = 0;
1036
1037 cpl_ensure_code(fs, CPL_ERROR_NULL_INPUT);
1038 cpl_ensure_code(hdrl_imglist_on, CPL_ERROR_NULL_INPUT);
1039 cpl_ensure_code(hdrl_imglist_off, CPL_ERROR_NULL_INPUT);
1040 cpl_ensure_code(gain, CPL_ERROR_NULL_INPUT);
1041 cpl_ensure_code(exptime, CPL_ERROR_NULL_INPUT);
1042
1043 TRY
1044 {
1045 /* Load the badpixel mask if present:
1046 flat: yes
1047 distortion: no
1048 */
1049 bpm_dark = eris_ifu_load_badpixel_mask(fs, ERIS_IFU_PRO_DARK_BPM, 0);
1050
1051 if (bpm_dark != NULL) {
1052 if (cpl_frameset_count_tags(fs, ERIS_IFU_PRO_DIST_BPM) == 1) {
1053 bpm_dist = eris_ifu_load_badpixel_mask(fs,
1054 ERIS_IFU_PRO_DIST_BPM, 0);
1055 cpl_mask_or(bpm_dark, bpm_dist);
1056 }
1057
1058 if (cpl_frameset_count_tags(fs, ERIS_IFU_PRO_DETLIN_BPM) == 1) {
1059 bpm_detlin = eris_ifu_load_badpixel_mask(fs,
1060 ERIS_IFU_PRO_DETLIN_BPM, 0);
1061 cpl_mask_or(bpm_dark, bpm_detlin);
1062 }
1063 }
1064
1065 cpl_msg_info(cpl_func, "Loading all flat frames...");
1066
1067 /* check if FLAT_LAMP or FLAT_NS frames exist */
1068 if (cpl_frameset_count_tags(fs, ERIS_IFU_RAW_FLAT_LAMP) > 0) {
1069 tag = cpl_sprintf("%s", ERIS_IFU_RAW_FLAT_LAMP);
1070 fs_extracted = eris_ifu_get_frameset_by_tag(fs, tag);
1071 } else if ( (cpl_frameset_count_tags(fs, ERIS_IFU_RAW_FLAT_LAMP_ON) > 0) &&
1072 (cpl_frameset_count_tags(fs, ERIS_IFU_RAW_FLAT_LAMP_OFF) > 0) ) {
1073
1074 fs_extracted = eris_ifu_get_frameset_by_tag(fs, ERIS_IFU_RAW_FLAT_LAMP_ON);
1075
1076 fs_off = eris_ifu_get_frameset_by_tag(fs, ERIS_IFU_RAW_FLAT_LAMP_OFF);
1077
1078 cpl_frameset_join(fs_extracted, fs_off);
1079 tag = cpl_sprintf("%s", ERIS_IFU_RAW_FLAT_LAMP_ON);
1080 } else if (cpl_frameset_count_tags(fs, ERIS_IFU_RAW_FLAT_NS) > 0) {
1081 tag = cpl_sprintf("%s", ERIS_IFU_RAW_FLAT_NS);
1082 fs_extracted = eris_ifu_get_frameset_by_tag(fs, tag);
1083 } else if ( (cpl_frameset_count_tags(fs, ERIS_IFU_RAW_FLAT_NS_ON) > 0) &&
1084 (cpl_frameset_count_tags(fs, ERIS_IFU_RAW_FLAT_NS_OFF) > 0) ) {
1085
1086 fs_extracted = eris_ifu_get_frameset_by_tag(fs, ERIS_IFU_RAW_FLAT_NS_ON);
1087
1088 fs_off = eris_ifu_get_frameset_by_tag(fs, ERIS_IFU_RAW_FLAT_NS_OFF);
1089
1090 cpl_frameset_join(fs_extracted, fs_off);
1091 tag = cpl_sprintf("%s", ERIS_IFU_RAW_FLAT_NS_ON);
1092
1093
1094 } else {
1095 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
1096 "Neither FLAT_LAMP or FLAT_NS "
1097 "frames present!");
1098 }
1099
1100 if (cpl_frameset_get_size(fs_extracted) < 1) {
1101 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
1102 "Not enough FLAT RAW frames!");
1103 }
1104
1105 *hdrl_imglist_on = hdrl_imagelist_new();
1106 *hdrl_imglist_off = hdrl_imagelist_new();
1107
1108 /*
1109 * Loop through all FLAT_LAMP frames and save on- and off-frames
1110 * accordingly in their cpl_imagelists
1111 */
1112 fr = cpl_frameset_find_const(fs_extracted, tag);
1113 cpl_size frameCnt = cpl_frameset_get_size(fs_extracted);
1114
1115 /* AMO: the following while need to be changed to scan all frames of the set not only the ones with frame tag tag */
1116 for (cpl_size i = 0 ; i < frameCnt ; i++) {
1117 fr = cpl_frameset_get_position_const(fs_extracted, i) ;
1118 fn = cpl_frame_get_filename(fr);
1119 eris_ifu_file_exists(fn);
1120
1121 /* If the frame has a tag we process it. Else it is an object and
1122 * is ignored */
1123 if (cpl_frame_get_tag(fr) != NULL) {
1124 tmp_img = eris_ifu_load_exposure_file(fn, 0, NULL);
1125 if (bpm_dark != NULL) {
1126 hdrl_image_reject_from_mask(tmp_img, bpm_dark);
1127 }
1128
1130 hdrl_imagelist_set(*hdrl_imglist_off, tmp_img,
1131 hdrl_imagelist_get_size(*hdrl_imglist_off));
1132 tmp_img = NULL;
1133 } else if (eris_ifu_frame_is_on(fr) == 1) {
1134 hdrl_imagelist_set(*hdrl_imglist_on, tmp_img,
1135 hdrl_imagelist_get_size(*hdrl_imglist_on));
1136 tmp_img = NULL;
1137 if (!first_on) {
1139 plist = cpl_propertylist_load(fn, 0));
1140 if (cpl_propertylist_has(plist, FHDR_DET_CHIP_GAIN)) {
1141 *gain = cpl_propertylist_get_double(plist,
1142 FHDR_DET_CHIP_GAIN);
1143 } else {
1144 *gain = 1.;
1145 }
1146 if (cpl_propertylist_has(plist, FHDR_EXPTIME)) {
1147 *exptime = cpl_propertylist_get_double(plist,
1148 FHDR_EXPTIME);
1149 } else {
1150 *exptime = 1.;
1151 }
1152 first_on = true;
1153 }
1154 }
1155 } else {
1156 /* if (tag == NULL) do nothing */
1157 }
1158 }
1159
1160 nr_on = (int)hdrl_imagelist_get_size(*hdrl_imglist_on);
1161 nr_off = (int)hdrl_imagelist_get_size(*hdrl_imglist_off);
1162 cpl_msg_info(cpl_func,"nr_on: %d nr_off: %d",nr_on, nr_off);
1163 if (nr_on != nr_off) {
1164 cpl_msg_warning(cpl_func,
1165 "Number obj/off frames differs (#obj= %d #off= %d)!",
1166 (int)hdrl_imagelist_get_size(*hdrl_imglist_on),
1167 (int)hdrl_imagelist_get_size(*hdrl_imglist_off));
1168 }
1169
1170 if (hdrl_imagelist_get_size(*hdrl_imglist_on) < 1) {
1171 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
1172 "No ON raw frame in input, something wrong!");
1173 }
1174
1175 if (hdrl_imagelist_get_size(*hdrl_imglist_on) <= 0) {
1176 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
1177 "input object list's size 0. Check"
1178 " your input data!");
1179 }
1180 }
1181 CATCH
1182 {
1183 CATCH_MSGS();
1184 eris_ifu_free_hdrl_imagelist(hdrl_imglist_on);
1185 eris_ifu_free_hdrl_imagelist(hdrl_imglist_off);
1186
1187 err = cpl_error_get_code();
1188 }
1189 eris_ifu_free_frameset(&fs_off);
1190 eris_ifu_free_frameset(&fs_extracted);
1193 cpl_mask_delete(bpm_dark);
1194 cpl_mask_delete(bpm_dist);
1195 cpl_mask_delete(bpm_detlin);
1196 hdrl_image_delete(tmp_img);
1197 eris_check_error_code("eris_ifu_flat_load_frames");
1198 return err;
1199}
1200
1201/*----------------------------------------------------------------------------*/
1216/*----------------------------------------------------------------------------*/
1217cpl_error_code eris_ifu_flat_calc_qc_pre(
1218 const cpl_parameterlist *parlist,
1219 const char *recipe_name,
1220 const hdrl_imagelist *hdrl_imglist_on,
1221 const hdrl_imagelist *hdrl_imglist_off,
1222 cpl_propertylist *qc_list)
1223{
1224 cpl_error_code err = CPL_ERROR_NONE;
1225 int qc_sat = 0;
1226 cpl_vector *vec_off = NULL;
1227 cpl_vector *vec_diff = NULL;
1228 const cpl_parameter *p =NULL;
1229 hdrl_parameter *param = NULL;
1230 const hdrl_image *img_on_const = NULL;
1231 const hdrl_image *img_off_const = NULL;
1232 hdrl_image *img_on = NULL;
1233 hdrl_image *img_off = NULL;
1234 hdrl_image *img = NULL;
1235 cpl_image *contrib = NULL;
1236 int nr_on = 0;
1237 int nr_off = 0;
1238 int nr_fr = 0;
1239 int xmin1 = 0;
1240 int xmax1 = 0;
1241 int ymin1 = 0;
1242 int ymax1 = 0;
1243 int xmin2 = 0;
1244 int xmax2 = 0;
1245 int ymin2 = 0;
1246 int ymax2 = 0;
1247 double fpn_stdev1 = 0.;
1248 double fpn_stdev2 = 0.;
1249 char *tmp_str = NULL;
1250
1251 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
1252 cpl_ensure_code(recipe_name, CPL_ERROR_NULL_INPUT);
1253 cpl_ensure_code(hdrl_imglist_on, CPL_ERROR_NULL_INPUT);
1254 cpl_ensure_code(hdrl_imglist_off, CPL_ERROR_NULL_INPUT);
1255 cpl_ensure_code(qc_list, CPL_ERROR_NULL_INPUT);
1256
1257 TRY
1258 {
1259 /* calc QC saturated pixels */
1260 qc_sat = eris_ifu_get_qc_saturated(hdrl_imglist_on);
1262
1263 eris_ifu_append_qc_int(qc_list, "FLAT SAT NCOUNTS", qc_sat,
1264 "nr. saturated pixels of master flat");
1265
1266 /* calc QC flux & counts */
1267 nr_on = hdrl_imagelist_get_size(hdrl_imglist_on);
1268 nr_off = hdrl_imagelist_get_size(hdrl_imglist_off);
1270 nr_fr = (nr_on <= nr_off) ? nr_on : nr_off;
1271
1272 if (nr_on != nr_off) {
1273 cpl_msg_warning(cpl_func,
1274 "Number obj/off frames differs (#obj= %d #off= %d)!",
1275 nr_on, nr_off);
1276 }
1277
1278 vec_off = cpl_vector_new(nr_fr);
1279 vec_diff = cpl_vector_new(nr_fr);
1280
1281 for (int i = 0; i < nr_fr; i++) {
1282 img_on_const = hdrl_imagelist_get_const(hdrl_imglist_on, i);
1283 img_off_const = hdrl_imagelist_get_const(hdrl_imglist_off, i);
1284
1285 img = hdrl_image_sub_image_create(img_on_const, img_off_const);
1286
1287 cpl_vector_set(vec_diff, i, hdrl_image_get_median(img).data);
1288 cpl_vector_set(vec_off, i, hdrl_image_get_median(img_off_const).data);
1289
1291
1293 }
1294
1295 eris_ifu_append_qc_double(qc_list, "SPECFLAT OFFFLUX",
1296 cpl_vector_get_mean(vec_off),
1297 "[ADU] average flux off frames");
1298 eris_ifu_append_qc_double(qc_list, "SPECFLAT NCNTSAVG",
1299 cpl_vector_get_mean(vec_diff),
1300 "[ADU] average counts");
1301 if(nr_fr > 1 ) {
1302 eris_ifu_append_qc_double(qc_list, "SPECFLAT NCNTSSTD",
1303 cpl_vector_get_stdev(vec_diff),
1304 "[ADU] stdev counts");
1305 }
1306
1307 /* calc fixed pattern noise */
1308 tmp_str = cpl_sprintf("eris.%s.qc.fpn.xmin1", recipe_name);
1309 p = cpl_parameterlist_find_const(parlist, tmp_str);
1310 xmin1 = cpl_parameter_get_int(p);
1311 eris_ifu_free_string(&tmp_str);
1313
1314 tmp_str = cpl_sprintf("eris.%s.qc.fpn.xmax1", recipe_name);
1315 p = cpl_parameterlist_find_const(parlist, tmp_str);
1316 xmax1 = cpl_parameter_get_int(p);
1317 eris_ifu_free_string(&tmp_str);
1319
1320 tmp_str = cpl_sprintf("eris.%s.qc.fpn.ymin1", recipe_name);
1321 p = cpl_parameterlist_find_const(parlist, tmp_str);
1322 ymin1 = cpl_parameter_get_int(p);
1323 eris_ifu_free_string(&tmp_str);
1325
1326 tmp_str = cpl_sprintf("eris.%s.qc.fpn.ymax1", recipe_name);
1327 p = cpl_parameterlist_find_const(parlist, tmp_str);
1328 ymax1 = cpl_parameter_get_int(p);
1329 eris_ifu_free_string(&tmp_str);
1331
1332 tmp_str = cpl_sprintf("eris.%s.qc.fpn.xmin2", recipe_name);
1333 p = cpl_parameterlist_find_const(parlist, tmp_str);
1334 xmin2 = cpl_parameter_get_int(p);
1335 eris_ifu_free_string(&tmp_str);
1337
1338 tmp_str = cpl_sprintf("eris.%s.qc.fpn.xmax2", recipe_name);
1339 p = cpl_parameterlist_find_const(parlist, tmp_str);
1340 xmax2 = cpl_parameter_get_int(p);
1341 eris_ifu_free_string(&tmp_str);
1343
1344 tmp_str = cpl_sprintf("eris.%s.qc.fpn.ymin2", recipe_name);
1345 p = cpl_parameterlist_find_const(parlist, tmp_str);
1346 ymin2 = cpl_parameter_get_int(p);
1347 eris_ifu_free_string(&tmp_str);
1349
1350 tmp_str = cpl_sprintf("eris.%s.qc.fpn.ymax2", recipe_name);
1351 p = cpl_parameterlist_find_const(parlist, tmp_str);
1352 ymax2 = cpl_parameter_get_int(p);
1353 eris_ifu_free_string(&tmp_str);
1355
1356 tmp_str = cpl_sprintf("eris.%s.collapse", recipe_name);
1357 param = hdrl_collapse_parameter_parse_parlist(parlist, tmp_str);
1358 eris_ifu_free_string(&tmp_str);
1359
1360 hdrl_imagelist_collapse(hdrl_imglist_on,
1361 param,
1362 &img_on,
1363 &contrib);
1364 eris_ifu_free_image(&contrib);
1365
1366 hdrl_imagelist_collapse(hdrl_imglist_off,
1367 param,
1368 &img_off,
1369 &contrib);
1370 eris_ifu_free_image(&contrib);
1371
1372 hdrl_image_sub_image(img_on, img_off);
1373 eris_ifu_free_hdrl_image(&img_off);
1374
1375 fpn_stdev1 = cpl_image_get_stdev_window(hdrl_image_get_image_const(img_on),
1376 xmin1, ymin1, xmax1, ymax1);
1378
1379 fpn_stdev2 = cpl_image_get_stdev_window(hdrl_image_get_image_const(img_on),
1380 xmin2, ymin2, xmax2, ymax2);
1382
1383 eris_ifu_free_hdrl_image(&img_on);
1384
1385 eris_ifu_append_qc_double(qc_list, "LFLAT FPN1", fpn_stdev1,
1386 "[ADU] Fixed Pattern Noise of combined frames");
1387
1388 eris_ifu_append_qc_double(qc_list, "LFLAT FPN2", fpn_stdev2,
1389 "[ADU] Fixed Pattern Noise of combined frames");
1390 }
1391 CATCH
1392 {
1393 CATCH_MSGS();
1394 err = cpl_error_get_code();
1395
1397 }
1398
1399 eris_ifu_free_vector(&vec_off);
1400 eris_ifu_free_vector(&vec_diff);
1402 eris_ifu_free_string(&tmp_str);
1403 eris_check_error_code("eris_ifu_flat_calc_qc_pre");
1404 return err;
1405}
1406
1407/*----------------------------------------------------------------------------*/
1424/*----------------------------------------------------------------------------*/
1425cpl_error_code eris_ifu_flat_calc_qc_post(const cpl_parameterlist *parlist,
1426 const char *recipe_name,
1427 const int productDepth,
1428 const char *procatg_prefix,
1429 const hdrl_image *masterFlatHdrlImg_hi,
1430 const hdrl_image *masterFlatHdrlImg_lo,
1431 const hdrl_imagelist *hdrl_imglist_on,
1432 const hdrl_imagelist *hdrl_imglist_off,
1433 const cpl_image *contrib_map,
1434 // const cpl_image *bpm2dImg,
1435 // const cpl_image *bpm3dImg,
1436 const cpl_mask *bpm2dMask,
1437 const cpl_mask *bpm3dMask,
1438 cpl_frameset *fs,
1439 cpl_propertylist *qc_list,
1440 cpl_image **qualityImage)
1441{
1442 cpl_error_code err = CPL_ERROR_NONE;
1443 //int nBadPix = 0;
1444 //double fracBadPix = 0;
1445
1446 char *fn = NULL,
1447 *pc = NULL;
1448 const cpl_mask *bp_mask_flat = NULL;
1449 cpl_image *tmpImg = NULL,
1450 *bpm2dImg = NULL,
1451 *bpm3dImg = NULL;
1452 //cpl_size sx = 0;
1453 //cpl_size sy = 0;
1454 //cpl_size npix = 0;
1455
1456 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
1457 cpl_ensure_code(recipe_name, CPL_ERROR_NULL_INPUT);
1458 cpl_ensure_code(procatg_prefix, CPL_ERROR_NULL_INPUT);
1459 // cpl_ensure_code(masterFlatHdrlImg_hi, CPL_ERROR_NULL_INPUT);
1460 cpl_ensure_code(masterFlatHdrlImg_lo, CPL_ERROR_NULL_INPUT);
1461 cpl_ensure_code(hdrl_imglist_on, CPL_ERROR_NULL_INPUT);
1462 cpl_ensure_code(hdrl_imglist_off, CPL_ERROR_NULL_INPUT);
1463 cpl_ensure_code(contrib_map, CPL_ERROR_NULL_INPUT);
1464 // cpl_ensure_code(bpm2dImg, CPL_ERROR_NULL_INPUT);
1465 // cpl_ensure_code(bpm3dImg, CPL_ERROR_NULL_INPUT);
1466 // cpl_ensure_code(bpm2dMask, CPL_ERROR_NULL_INPUT);
1467 // cpl_ensure_code(bpm3dMask, CPL_ERROR_NULL_INPUT);
1468 cpl_ensure_code(fs, CPL_ERROR_NULL_INPUT);
1469 cpl_ensure_code(qc_list, CPL_ERROR_NULL_INPUT);
1470 cpl_ensure_code(qualityImage, CPL_ERROR_NULL_INPUT);
1471
1472 TRY
1473 {
1474 /* fetch bad-pix-image */
1475 bp_mask_flat = hdrl_image_get_mask_const(masterFlatHdrlImg_lo);
1476 eris_ifu_get_badpix_qc_from_mask(bp_mask_flat, qc_list, "FLAT");
1477
1478 *qualityImage = cpl_image_new_from_mask(bp_mask_flat);
1479
1480 /* set "bad pixel flag" */
1481 cpl_image_multiply_scalar(*qualityImage, ERIS_DQI_BP);
1482
1483
1484 const cpl_image* ima = hdrl_image_get_image_const(masterFlatHdrlImg_lo);
1485
1486 double stdev = cpl_image_get_stdev(ima);
1487 double mean = cpl_image_get_mean(ima);
1488 double median = cpl_image_get_median(ima);
1489 char* key_name;
1490 char* key_comm;
1491
1492
1493 key_name = cpl_sprintf("ESO QC FLAT STDDEV");
1494 key_comm = cpl_sprintf("[ADU] Std deviation on flat image");
1495 cpl_propertylist_append_double(qc_list,key_name, stdev);
1496 cpl_propertylist_set_comment(qc_list, key_name, key_comm);
1497 cpl_free(key_name);
1498 cpl_free(key_comm);
1499
1500
1501 key_name = cpl_sprintf("ESO QC FLAT MEAN");
1502 key_comm = cpl_sprintf("[ADU] Mean value on flat image");
1503 cpl_propertylist_append_double(qc_list,key_name, mean);
1504 cpl_propertylist_set_comment(qc_list, key_name, key_comm);
1505 cpl_free(key_name);
1506 cpl_free(key_comm);
1507
1508 key_name = cpl_sprintf("ESO QC FLAT MEDIAN");
1509 key_comm = cpl_sprintf("[ADU] Median value on flat image");
1510 cpl_propertylist_append_double(qc_list,key_name, median);
1511 cpl_propertylist_set_comment(qc_list, key_name, key_comm);
1512 cpl_free(key_name);
1513 cpl_free(key_comm);
1514
1515
1516 if (bpm2dMask != NULL) {
1517 bpm2dImg = cpl_image_new_from_mask(bpm2dMask);
1518 tmpImg = cpl_image_duplicate(bpm2dImg);
1519 /* set "user defined flag1; outlier pixels" */
1520 cpl_image_multiply_scalar(tmpImg, ERIS_DQI_BP_BPM2D);
1521 cpl_image_add(*qualityImage, tmpImg);
1522 eris_ifu_free_image(&tmpImg);
1523 }
1524 if (bpm3dMask != NULL) {
1525 bpm3dImg = cpl_image_new_from_mask(bpm3dMask);
1526 tmpImg = cpl_image_duplicate(bpm3dImg);
1527 /* set "user defined flag1; noisy pixels" */
1528 cpl_image_multiply_scalar(tmpImg, ERIS_DQI_BP_BPM3D);
1529 cpl_image_add(*qualityImage, tmpImg);
1530 eris_ifu_free_image(&tmpImg);
1531 }
1532
1533 /* save optional images */
1534 if ((hdrl_imglist_on != NULL) && ((productDepth & 2) != 0)) {
1535 fn = cpl_sprintf("%s%s", recipe_name,
1536 ERIS_IFU_PRO_FLAT_DBG_CUBE_ON_FN);
1537 eris_ifu_save_hdrl_imagelist_dbg(hdrl_imglist_on, fn, TRUE);
1539 }
1540
1541 if ((hdrl_imglist_off != NULL) && ((productDepth & 2) != 0)) {
1542 fn = cpl_sprintf("%s%s", recipe_name,
1543 ERIS_IFU_PRO_FLAT_DBG_CUBE_OFF_FN);
1544 eris_ifu_save_hdrl_imagelist_dbg(hdrl_imglist_off, fn, TRUE);
1546 }
1547
1548 if ((contrib_map != NULL) && ((productDepth & 1) != 0)) {
1549 fn = cpl_sprintf("%s%s", recipe_name,
1550 ERIS_IFU_PRO_FLAT_DBG_CONTRIBMAP_FN);
1551 pc = cpl_sprintf("%s%s", procatg_prefix,
1552 ERIS_IFU_PRO_FLAT_DBG_CONTRIBMAP);
1553 eris_ifu_save_image(fs, qc_list, parlist, recipe_name,
1554 pc, fn, CPL_TYPE_USHORT, contrib_map);
1557 }
1558
1559 if ((masterFlatHdrlImg_hi != NULL) && ((productDepth & 1) != 0)) {
1560 fn = cpl_sprintf("%s%s", recipe_name,
1561 ERIS_IFU_PRO_FLAT_DBG_HI_FN);
1562 pc = cpl_sprintf("%s%s", procatg_prefix,
1563 ERIS_IFU_PRO_FLAT_DBG_HI);
1564 eris_ifu_save_image(fs, qc_list, parlist, recipe_name,
1565 pc, fn, CPL_TYPE_DOUBLE,
1566 hdrl_image_get_image_const(masterFlatHdrlImg_hi));
1569 }
1570
1571 if ((bpm2dMask != NULL) && ((productDepth & 1) != 0)) {
1572 eris_ifu_get_badpix_qc_from_mask(bpm2dMask, qc_list, "FLAT");
1573
1574 fn = cpl_sprintf("%s%s", recipe_name,
1575 ERIS_IFU_PRO_FLAT_DBG_BPM2D_FN);
1576 pc = cpl_sprintf("%s%s", procatg_prefix,
1577 ERIS_IFU_PRO_FLAT_DBG_BPM2D);
1578 eris_ifu_save_image(fs, qc_list, parlist, recipe_name,
1579 pc, fn, CPL_TYPE_USHORT, bpm2dImg);
1582 }
1583
1584 if ((bpm3dMask != NULL) && ((productDepth & 1) != 0)) {
1585 eris_ifu_get_badpix_qc_from_mask(bpm3dMask, qc_list, "FLAT");
1586
1587 fn = cpl_sprintf("%s%s", recipe_name,
1588 ERIS_IFU_PRO_FLAT_DBG_BPM3D_FN);
1589 pc = cpl_sprintf("%s%s", procatg_prefix,
1590 ERIS_IFU_PRO_FLAT_DBG_BPM3D);
1591 eris_ifu_save_image(fs, qc_list, parlist, recipe_name,
1592 pc, fn, CPL_TYPE_USHORT, bpm3dImg);
1595 }
1596 //cpl_propertylist_erase(qc_list, "ESO QC FLAT NBADPIX");
1598
1599 cpl_propertylist_update_string(qc_list, CPL_DFS_PRO_CATG, "");
1600 }
1601 CATCH
1602 {
1603 CATCH_MSGS();
1604 err = cpl_error_get_code();
1605 eris_ifu_free_image(qualityImage);
1606 }
1607
1608 eris_ifu_free_image(&bpm2dImg);
1609 eris_ifu_free_image(&bpm3dImg);
1610 eris_check_error_code("eris_ifu_flat_calc_qc_post");
1611 return err;
1612}
1613
1614/*----------------------------------------------------------------------------*/
1626/*----------------------------------------------------------------------------*/
1627int eris_ifu_get_qc_saturated(const hdrl_imagelist *dataHdrl)
1628{
1629 int saturated_pixels = 0,
1630 tmp_sat = 0;
1631 cpl_size nx = 0,
1632 ny = 0,
1633 nz = 0,
1634 sat_min = ERIS_IFU_FLAT_SAT_MIN;
1635 double threshold = ERIS_IFU_FLAT_SATURATED;
1636 const hdrl_image *curHdrlImg = NULL;
1637 const cpl_image *curImg = NULL;
1638 const double *pcur_img = NULL;
1639
1640 cpl_ensure_code(dataHdrl, CPL_ERROR_NULL_INPUT);
1641
1642 TRY
1643 {
1644 ASSURE((threshold > 0.0) &&
1645 (sat_min > 0),
1646 CPL_ERROR_ILLEGAL_INPUT,
1647 "threshold and sat_min must be greater than zero!");
1648
1649 curHdrlImg = hdrl_imagelist_get_const(dataHdrl, 0);
1650
1651 nx = hdrl_image_get_size_x(curHdrlImg);
1652 ny = hdrl_image_get_size_y(curHdrlImg);
1653 nz = hdrl_imagelist_get_size(dataHdrl);
1655
1656 if (nz >= sat_min) {
1657 /* Loop on the pixels of the data-image */
1658 int ix = 0, iy = 0, iz = 0;
1659 for (iy = 0; iy < ny; iy++) {
1660 for (ix = 0; ix < nx; ix++) {
1661 tmp_sat = 0;
1662 for (iz = 0; iz < nz; iz++) {
1663 curHdrlImg = hdrl_imagelist_get_const(dataHdrl, iz);
1664 curImg = hdrl_image_get_image_const(curHdrlImg);
1665 pcur_img = cpl_image_get_data_double_const(curImg);
1666
1667 if (!cpl_image_is_rejected(curImg, ix+1, iy+1) &&
1668 (pcur_img[ix+iy*nx] > threshold)) {
1669 tmp_sat++;
1670 }
1671 }
1672
1673 if (tmp_sat >= sat_min) {
1674 saturated_pixels++;
1675 }
1676 }
1677 }
1678 }
1679 }
1680 CATCH
1681 {
1682 CATCH_MSG();
1683 saturated_pixels = -1;
1684 }
1685 eris_check_error_code("eris_ifu_get_qc_saturated");
1686 return saturated_pixels;
1687}
1688
1715cpl_error_code eris_ifu_column_tilt(hdrl_image *hdrl_img, double sigma)
1716{
1717 cpl_error_code err = CPL_ERROR_NONE;
1718 cpl_image *img = NULL;
1719 cpl_binary *pmask = NULL;
1720 cpl_mask *mask = NULL;
1721 int mwt = 0,
1722 nx = 0,
1723 ny = 0,
1724 npix = 0,
1725 col_nr = 0,
1726 slope = 1000,
1727 saturation = 50000;
1728 double mean = 0.,
1729 sum = 0.,
1730 sum2 = 0.,
1731 sinfo_median= 0,
1732 noise = 0.,
1733 a = 0.,
1734 b = 0.,
1735 siga = 0.,
1736 sigb = 0.,
1737 chi2 = 0.,
1738 q = 0.,
1739 *sig = NULL,
1740 *dat = NULL,
1741 *column = NULL,
1742 *pimg = NULL;
1743
1744 cpl_ensure_code(hdrl_img, CPL_ERROR_NULL_INPUT);
1745 cpl_ensure_code(sigma > 0., CPL_ERROR_ILLEGAL_INPUT);
1746
1747 TRY
1748 {
1749 nx = hdrl_image_get_size_x(hdrl_img);
1750 ny = hdrl_image_get_size_y(hdrl_img);
1752
1753 img = hdrl_image_get_image(hdrl_img);
1754 mask = hdrl_image_get_mask(hdrl_img);
1755
1756 pimg = cpl_image_get_data_double(img);
1757 pmask = cpl_mask_get_data(mask);
1758
1759 /* go through the columns */
1760 for (int i = ERIS_IFU_DETECTOR_BP_BORDER;
1761 i < ERIS_IFU_DETECTOR_SIZE_X-ERIS_IFU_DETECTOR_BP_BORDER ;
1762 i++)
1763 {
1764 col_nr = 0;
1765 /* initialize the buffer variables for each column */
1766 column = (double*)cpl_calloc(ny, sizeof(double*));
1767 sig = (double*)cpl_calloc(ny, sizeof(double*));
1768 dat = (double*)cpl_calloc(ny, sizeof(double*));
1769
1770 /*select only non-NAN values of one column*/
1771 for(int j = 0; j < ny; j++) {
1772 if (pmask[i + j*nx] != BAD_PIX) {
1773 column[j] = pimg[i + j*nx];
1774 col_nr++;
1775 }
1776 }
1777
1778 if (col_nr < 10) {
1779 /* column %d has almost only blank pixels
1780 * and is set to blank", i+1 */
1781 for(int j = 0; j < ny; j++) {
1782 pmask[i + j*nx] = BAD_PIX;
1783 }
1784 } else {
1785 /* sort the data, clip off the extremes, determine the noise
1786 * and get the range for the valid data. It is assumed here
1787 * that most pixels are o.k.
1788 */
1789 eris_ifu_flat_pixel_qsort(column, col_nr);
1790
1791 for (int j = 0.1*col_nr + 1; j <= 0.9*col_nr; j++) {
1792 sum += column[j];
1793 sum2 += column[j] * column[j];
1794 npix++;
1795 }
1796
1797 if (npix <= 1) {
1798 noise = sigma * 1000.;
1799 } else {
1800 mean = sum/(double)npix;
1801 noise = sqrt((sum2 - sum*mean)/(double)(npix -1));
1802 noise *= sigma;
1803 }
1804
1805 /* determine sinfo_median if colnum is odd, sinfo_median will be
1806 * the colnum/2 th value, otherwise sinfo_median is the mean of
1807 * colnum/2-1 th and colnum/2 th value.
1808 */
1809
1810 if ((col_nr % 2 == 1) || (col_nr == 0)) {
1811 sinfo_median = column[col_nr/2];
1812 } else {
1813 sinfo_median = (column[col_nr/2 - 1] + column[col_nr/2])/2.;
1814 }
1815
1816 /* now select the pixels for the tilt calculation */
1817 col_nr = 0 ;
1818 for (int j = 0; j < ny; j++) {
1819 if ((pmask[i + j*nx] != BAD_PIX) &&
1820 (fabs((pimg[i+j*nx])-sinfo_median) <= noise))
1821 {
1822 column[col_nr] = pimg[i+j*nx];
1823 dat[col_nr] = (double)j;
1824 sig[col_nr] = 1.;
1825 col_nr++;
1826 }
1827 }
1828
1829 if (col_nr == 0) {
1830 a = NAN;
1831 b = NAN;
1832 } else {
1833 mwt = 0;
1834 eris_ifu_my_fit(dat, column, col_nr, sig, mwt, &a,
1835 &b, &siga, &sigb, &chi2, &q);
1836 }
1837
1838 if ((fabs(b) >= slope) || (fabs(a) >= saturation) ||
1839 isnan(b) || isnan(a))
1840 {
1841 cpl_msg_warning(cpl_func, "linear fit: slope is greater than "
1842 "limit: %f saturation level is "
1843 "reached: %f in column number %d ",
1844 b, a , i+1) ;
1845 }
1846
1847 /* subtract fit or sinfo_median from data */
1848 for (int j = 0; j < ny; j++) {
1849 if ((pmask[i + j*nx] != BAD_PIX) &&
1850 (fabs(b) < slope) &&
1851 (fabs(a) < saturation))
1852 {
1853 pimg[i+j*nx] = pimg[i+j*nx] - (a + b*(double)j);
1854 } else if (pmask[i + j*nx] == BAD_PIX) {
1855 pimg[i+j*nx] = NAN ;
1856 } else if (((fabs(b) >= slope) ||
1857 (fabs(a) >= saturation) ||
1858 isnan(a) || isnan(b)) &&
1859 (pmask[i + j*nx] != BAD_PIX))
1860 {
1861 pimg[i+j*nx] -= sinfo_median;
1862 } else {
1863 cpl_msg_error(cpl_func, " case is not possible! %f %f",
1864 b, a);
1865 }
1866 }
1867 }
1871 } // end: for i
1872 }
1873 CATCH
1874 {
1875 CATCH_MSGS();
1876 err = cpl_error_get_code();
1877 }
1878
1882 eris_check_error_code("eris_ifu_column_tilt");
1883 return err;
1884}
1885
1895cpl_error_code eris_ifu_flat_thresh_mask(hdrl_image* hdrl_img,
1896 double lo_cut,
1897 double hi_cut)
1898{
1899 int nx = 0,
1900 ny = 0;
1901 const double *pimg = NULL;
1902 cpl_image *img = NULL;
1903 cpl_mask *mask = NULL;
1904 cpl_binary *pmask = NULL;
1905 cpl_error_code err = CPL_ERROR_NONE;
1906
1907 cpl_ensure_code(hdrl_img, CPL_ERROR_NULL_INPUT);
1908
1909 TRY
1910 {
1911 nx = hdrl_image_get_size_x(hdrl_img);
1912 ny = hdrl_image_get_size_y(hdrl_img);
1914
1915 img = hdrl_image_get_image(hdrl_img);
1916 mask = hdrl_image_get_mask(hdrl_img);
1917
1918 pimg = cpl_image_get_data_double_const(img);
1919 pmask = cpl_mask_get_data(mask);
1920
1921 for (int x = ERIS_IFU_DETECTOR_BP_BORDER; x < nx-ERIS_IFU_DETECTOR_BP_BORDER; x++) {
1922 for (int y = ERIS_IFU_DETECTOR_BP_BORDER; y < ny-ERIS_IFU_DETECTOR_BP_BORDER; y++) {
1923 if ((pmask[x+nx*y] == GOOD_PIX) &&
1924 ((pimg[x+nx*y] > hi_cut) || (pimg[x+nx*y] < lo_cut)))
1925 {
1926 pmask[x+nx*y] = BAD_PIX;
1927 }
1928 }
1929 }
1930 }
1931 CATCH
1932 {
1933 CATCH_MSGS();
1934 err = cpl_error_get_code();
1935 }
1936 eris_check_error_code("eris_ifu_flat_thresh_mask");
1937 return err;
1938}
1939
1953#define PIX_SWAP(a,b) { double temp=(a); (a)=(b); (b)=temp; }
1954#define PIX_STACK_SIZE 50
1955
1956cpl_error_code eris_ifu_flat_pixel_qsort(double *pix_arr, int npix)
1957{
1958 int i, ir, j, k, l, j_stack;
1959 int i_stack[PIX_STACK_SIZE * sizeof(double)];
1960 double a = 0.;
1961
1962 cpl_error_code ret = CPL_ERROR_NONE;
1963
1964 cpl_ensure_code(pix_arr, CPL_ERROR_NULL_INPUT);
1965
1966 TRY
1967 {
1968 ir = npix;
1969 l = 1;
1970 j_stack = 0;
1971 for (;;) {
1972 if (ir - l < 7) {
1973 for (j = l + 1; j <= ir; j++) {
1974 a = pix_arr[j - 1];
1975 for (i = j - 1; i >= 1; i--) {
1976 if (pix_arr[i - 1] <= a)
1977 break;
1978 pix_arr[i] = pix_arr[i - 1];
1979 }
1980 pix_arr[i] = a;
1981 }
1982 if (j_stack == 0)
1983 break;
1984 ir = i_stack[j_stack-- - 1];
1985 l = i_stack[j_stack-- - 1];
1986 } else {
1987 k = (l + ir) >> 1;
1988 PIX_SWAP(pix_arr[k - 1], pix_arr[l])
1989 if (pix_arr[l] > pix_arr[ir - 1]) {
1990 PIX_SWAP(pix_arr[l], pix_arr[ir - 1])
1991 }
1992 if (pix_arr[l - 1] > pix_arr[ir - 1]) {
1993 PIX_SWAP(pix_arr[l - 1], pix_arr[ir - 1])
1994 }
1995 if (pix_arr[l] > pix_arr[l - 1]) {
1996 PIX_SWAP(pix_arr[l], pix_arr[l - 1])
1997 }
1998 i = l + 1;
1999 j = ir;
2000 a = pix_arr[l - 1];
2001 for (;;) {
2002 do
2003 i++;
2004 while (pix_arr[i - 1] < a);
2005 do
2006 j--;
2007 while (pix_arr[j - 1] > a);
2008 if (j < i)
2009 break;
2010 PIX_SWAP(pix_arr[i - 1], pix_arr[j - 1]);
2011 }
2012 pix_arr[l - 1] = pix_arr[j - 1];
2013 pix_arr[j - 1] = a;
2014 j_stack += 2;
2015 if (j_stack > PIX_STACK_SIZE) {
2016 BRK_WITH_ERROR_MSG(CPL_ERROR_UNSPECIFIED,
2017 "stack too small : aborting");
2018 }
2019 if (ir - i + 1 >= j - l) {
2020 i_stack[j_stack - 1] = ir;
2021 i_stack[j_stack - 2] = i;
2022 ir = j - 1;
2023 } else {
2024 i_stack[j_stack - 1] = j - 1;
2025 i_stack[j_stack - 2] = l;
2026 l = i;
2027 }
2028 }
2029 }
2030 }
2031 CATCH
2032 {
2033 CATCH_MSGS();
2034
2035 ret = cpl_error_get_code();
2036 }
2037 eris_check_error_code("eris_ifu_flat_pixel_qsort");
2038 return ret;
2039}
2040#undef PIX_STACK_SIZE
2041#undef PIX_SWAP
2042
2061void eris_ifu_my_fit(double x[], double y[], int ndata, double sig[], int mwt,
2062 double *a, double *b, double *siga, double *sigb, double *chi2,
2063 double *q)
2064{
2065 double t = 0.,
2066 sxoss = 0.,
2067 sx = 0.,
2068 sy = 0.,
2069 st2 = 0.,
2070 ss = 0.;
2071
2072 *b = 0.; /*accumulate sums ...*/
2073 if (mwt) {
2074 ss = 0.;
2075 for (int i = 0; i < ndata; i++) { /*... with weights*/
2076 double wt = 1./pow(sig[i], 2);
2077 ss += wt;
2078 sx += x[i]*wt;
2079 sy += y[i]*wt;
2080 }
2081 } else {
2082 for (int i = 0; i < ndata; i++) { /*... or without weights*/
2083 sx += x[i];
2084 sy += y[i];
2085 }
2086 ss = ndata;
2087 }
2088 sxoss = sx/ss;
2089
2090 if (mwt) {
2091 for (int i = 0; i < ndata; i++) {
2092 t = (x[i] - sxoss)/sig[i];
2093 st2 += t*t;
2094 *b += t*y[i]/sig[i];
2095 }
2096 } else {
2097 for (int i = 0; i < ndata; i++) {
2098 t = x[i] - sxoss;
2099 st2 += t*t;
2100 *b += t*y[i];
2101 }
2102 }
2103
2104 *b /= st2;
2105 *a = (sy - sx*(*b))/ss;
2106 *siga = sqrt ((1.0 + sx*sx/(ss*st2))/ss);
2107 *sigb = sqrt (1.0/st2);
2108 *chi2 = 0.0; /*calculate chi-square*/
2109 if (mwt == 0) {
2110 for (int i = 0 ; i < ndata ; i++) {
2111 *chi2 += pow((y[i] - (*a) - (*b)*x[i]), 2);
2112 }
2113 *q = 1.;
2114
2115 /* for unweighted data evaluate typical sig using chi2, and adjust
2116 * the standard deviation
2117 */
2118 double sigdat = sqrt ((*chi2)/(ndata - 2));
2119 *siga *= sigdat;
2120 *sigb *= sigdat;
2121 } else {
2122 for (int i = 0; i < ndata; i++) {
2123 *chi2 += pow(((y[i] - (*a) - (*b) * x[i])/sig[i]),2);
2124 }
2125 *q = 1.; /* delete rest of lines. q is not a good value */
2126 }
2127 eris_check_error_code("eris_ifu_my_fit");
2128 return;
2129}
2130
2146cpl_error_code eris_ifu_flat_stats_rectangle(const hdrl_image *hdrl_img,
2147 double loReject,
2148 double hiReject,
2149 int llx,
2150 int lly,
2151 int urx,
2152 int ury,
2153 double *cleanmean,
2154 double *cleanstdev)
2155{
2156 cpl_error_code ret = CPL_ERROR_NONE;
2157 const cpl_image *img = NULL;
2158 int n = 0,
2159 npix = 0,
2160 lo_n = 0,
2161 hi_n = 0,
2162 nx = 0,
2163 ny = 0;
2164 const double *pimg = NULL;
2165 double *pix_array = NULL,
2166 pix_sum = 0.,
2167 sqr_sum = 0.;
2168
2169 cpl_ensure_code(hdrl_img, CPL_ERROR_NULL_INPUT);
2170
2171 nx = hdrl_image_get_size_x(hdrl_img);
2172 ny = hdrl_image_get_size_y(hdrl_img);
2173
2174 cpl_ensure_code(loReject+hiReject < 100., CPL_ERROR_ILLEGAL_INPUT);
2175 cpl_ensure_code(loReject >= 0., CPL_ERROR_ILLEGAL_INPUT);
2176 cpl_ensure_code(loReject < 100., CPL_ERROR_ILLEGAL_INPUT);
2177 cpl_ensure_code(hiReject >= 0., CPL_ERROR_ILLEGAL_INPUT);
2178 cpl_ensure_code(hiReject < 100., CPL_ERROR_ILLEGAL_INPUT);
2179 cpl_ensure_code((llx >= 0) && (lly >= 0), CPL_ERROR_ILLEGAL_INPUT);
2180 cpl_ensure_code((urx >= 0) && (ury >= 0), CPL_ERROR_ILLEGAL_INPUT);
2181 cpl_ensure_code((llx < nx) && (lly < ny), CPL_ERROR_ILLEGAL_INPUT);
2182 cpl_ensure_code((urx < nx) && (ury < ny), CPL_ERROR_ILLEGAL_INPUT);
2183 cpl_ensure_code((ury > lly) && (urx > llx), CPL_ERROR_ILLEGAL_INPUT);
2184
2185 TRY
2186 {
2187 /* allocate memory */
2188 npix = (urx-llx+1) * (ury-lly+1);
2189 pix_array = (double*)cpl_calloc(npix, sizeof(double));
2190
2191 /* go through the rectangle and copy the pixel values into an array */
2192 img = hdrl_image_get_image_const(hdrl_img);
2193 pimg = cpl_image_get_data_double_const(img);
2194
2195 for (int row = lly; row <= ury; row++) {
2196 for (int col = llx; col <= urx; col++) {
2197 if (!isnan(pimg[col + row*nx])) {
2198 pix_array[n] = pimg[col + row*nx];
2199 n++;
2200 }
2201 }
2202 }
2203
2204 npix = n;
2205
2206 /* determining the clean mean is already done in the recipes */
2207 eris_ifu_flat_clean_mean(pix_array, npix, loReject, hiReject,
2208 cleanmean);
2209
2210 /* now the clean standard deviation must be calculated */
2211 /* initialize sums */
2212 lo_n = (int)(loReject / 100. * (double)npix);
2213 hi_n = (int)(hiReject / 100. * (double)npix);
2214 pix_sum = 0.;
2215 sqr_sum = 0.;
2216 n = 0;
2217 for (int i = lo_n; i <= npix - hi_n; i++) {
2218 pix_sum += (double)pix_array[i];
2219 sqr_sum += ((double)pix_array[i] * (double)pix_array[i]);
2220 n++;
2221 }
2222
2223
2224 if (n == 0) {
2225 BRK_WITH_ERROR_MSG(CPL_ERROR_UNSPECIFIED,
2226 "number of clean pixels is zero!");
2227 }
2228
2229 pix_sum /= (double)n;
2230 sqr_sum /= (double)n;
2231 *cleanstdev = sqrt(sqr_sum - pix_sum*pix_sum);
2232 }
2233 CATCH
2234 {
2235 CATCH_MSGS();
2236
2237 ret = cpl_error_get_code();
2238
2239 *cleanmean = -DBL_MAX;
2240 *cleanstdev = -DBL_MAX;
2241 }
2242
2243 cpl_free(pix_array);
2244 eris_check_error_code("eris_ifu_flat_stats_rectangle");
2245 return ret;
2246}
2247
2264cpl_error_code eris_ifu_flat_clean_mean(double *array,
2265 int n_elements,
2266 double throwaway_low,
2267 double throwaway_high,
2268 double *cleanmean)
2269{
2270 cpl_error_code ret = CPL_ERROR_NONE;
2271 int n = 0,
2272 lo_n = 0,
2273 hi_n = 0;
2274 double sum = 0.;
2275
2276 cpl_ensure_code(array, CPL_ERROR_NULL_INPUT);
2277 cpl_ensure_code(n_elements > 0, CPL_ERROR_ILLEGAL_INPUT);
2278 cpl_ensure_code(throwaway_low > 0., CPL_ERROR_ILLEGAL_INPUT);
2279 cpl_ensure_code(throwaway_high > 0., CPL_ERROR_ILLEGAL_INPUT);
2280 cpl_ensure_code(throwaway_low + throwaway_high < 100.,
2281 CPL_ERROR_ILLEGAL_INPUT);
2282
2283 TRY
2284 {
2285 lo_n = (int)(throwaway_low * (double)n_elements / 100.);
2286 hi_n = (int)(throwaway_high * (double)n_elements / 100.);
2287
2288 /* sort the array */
2289 eris_ifu_flat_pixel_qsort(array, n_elements);
2290
2291 for (int i = lo_n; i < n_elements - hi_n; i++) {
2292 if (!isnan(array[i])) {
2293 sum += array[i];
2294 n++;
2295 }
2296 }
2297 if (n == 0) {
2298 BRK_WITH_ERROR_MSG(CPL_ERROR_UNSPECIFIED,
2299 "zero values!");
2300 } else {
2301 *cleanmean = sum/(double)n;
2302 }
2303 }
2304 CATCH
2305 {
2306 CATCH_MSGS();
2307
2308 ret = cpl_error_get_code();
2309
2310 *cleanmean = -DBL_MAX;
2311 }
2312 eris_check_error_code("eris_ifu_flat_clean_mean");
2313 return ret;
2314}
2315
2339hdrl_image* eris_ifu_flat_median_image(const hdrl_image *hdrl_img_in,
2340 double fmedian)
2341{
2342 hdrl_image *hdrl_img_out = NULL;
2343 const cpl_image *img_in = NULL;
2344 cpl_image *img_out = NULL;
2345 const cpl_mask *mask_in = NULL;
2346 cpl_mask *mask_out = NULL;
2347 const cpl_binary *pmask_in = NULL;
2348 cpl_binary *pmask_out = NULL;
2349 int *position = NULL,
2350 nposition = 0,
2351 im_size = 0,
2352 nx = 0,
2353 ny = 0;
2354 double *value = NULL,
2355 my_med = 0,
2356 *pimg_out = NULL;
2357 const double *pimg_in = NULL;
2358
2359 cpl_ensure(hdrl_img_in, CPL_ERROR_NULL_INPUT, NULL);
2360
2361 TRY
2362 {
2363 nx = hdrl_image_get_size_x(hdrl_img_in);
2364 ny = hdrl_image_get_size_y(hdrl_img_in);
2365 im_size = nx*ny;
2367
2368 img_in = hdrl_image_get_image_const(hdrl_img_in);
2369 mask_in = hdrl_image_get_mask_const(hdrl_img_in);
2370 pimg_in = cpl_image_get_data_double_const(img_in);
2371 pmask_in = cpl_mask_get_data_const(mask_in);
2372
2373 hdrl_img_out = hdrl_image_duplicate(hdrl_img_in);
2374 img_out = hdrl_image_get_image(hdrl_img_out);
2375 mask_out = hdrl_image_get_mask(hdrl_img_out);
2376 pimg_out = cpl_image_get_data_double(img_out);
2377 pmask_out = cpl_mask_get_data(mask_out);
2378
2379 /* go through all pixels */
2380 for (int i = 0; i < im_size; i++) {
2381 /* blank pixels are not replaced */
2382 if (pmask_in[i] == BAD_PIX) {
2383 continue;
2384 }
2385
2386 /* initialize the buffer variables for the 8 nearest neighbors */
2387 value = (double*)cpl_calloc(8, sizeof(double*));
2388 position = (int*)cpl_calloc(8, sizeof(int*));
2389
2390 /* determine the pixel position of the 8 nearest neighbors
2391 */
2392 position[0] = i + nx - 1 ; /* upper left */
2393 position[1] = i + nx ; /* upper */
2394 position[2] = i + nx + 1 ; /* upper right */
2395 position[3] = i + 1 ; /* right */
2396 position[4] = i - nx + 1 ; /* lower right */
2397 position[5] = i - nx ; /* lower */
2398 position[6] = i - nx - 1 ; /* lower left */
2399 position[7] = i - 1 ; /* left */
2400
2401 /* determine the positions of the image margins, top positions are
2402 changed to low positions and vice versa. Right positions are
2403 changed to left positions and vice versa.
2404 */
2405 if ((i >= 0) && (i < nx)) {
2406 /* bottom line */
2407 position[4] += 2*nx;
2408 position[5] += 2*nx;
2409 position[6] += 2*nx;
2410 } else if ((i >= ((int)nx*ny - nx)) && (i < (int) nx*ny)) {
2411 /* top line */
2412 position[0] -= 2*nx;
2413 position[1] -= 2*nx;
2414 position[2] -= 2*nx;
2415 } else if (i % nx == 0) {
2416 /* left side */
2417 position[0] += 2;
2418 position[6] += 2;
2419 position[7] += 2;
2420 } else if ((i % nx) == (nx - 1)) {
2421 /* right side */
2422 position[2] -= 2;
2423 position[3] -= 2;
2424 position[4] -= 2;
2425 }
2426
2427 /* read the pixel values of the neighboring pixels,
2428 * blanks are not considered
2429 */
2430 nposition = 8;
2431 int n = 0;
2432 for (int j = 0; j < nposition; j++) {
2433 if((position[j] > -1) && (position[j] < im_size)) {
2434 if (pmask_in[position[j]] == GOOD_PIX) {
2435 value[n] = pimg_in[position[j]];
2436 n++;
2437 }
2438 }
2439 }
2440 nposition = n;
2441
2442 if (nposition <= 1) /* almost all neighbors are blank */
2443 {
2444 pmask_out[i] = BAD_PIX;
2446 eris_ifu_free_int_array(&position);
2447 continue;
2448 }
2449
2450 /* sort the values and determine the sinfo_median */
2452 eris_ifu_flat_pixel_qsort(value, nposition));
2453
2454 if (nposition % 2 == 1) {
2455 my_med = value[nposition/2];
2456 } else {
2457 my_med = (value [nposition/2 - 1] + value [nposition/2]) / 2.;
2458 }
2459
2460 /* replace the pixel value by the sinfo_median on conditions:
2461 * fmedian = 0: always replace with sinfo_median.
2462 * fmedian < 0: interpret as absolute condition:
2463 * if |pixel - sinfo_median| > -fmedian
2464 * replace with sinfo_median.
2465 * fmedian > 0: replace by sinfo_median (fmedian as a factor of
2466 * the square root of the sinfo_median itself)
2467 * if |pixel - sinfo_median| >= fmedian *
2468 sqrt ( sinfo_median )
2469 * considers a dependence on the pixel value.
2470 * This can be used to consider photon noise.
2471 */
2472 if (fmedian == 0) {
2473 pimg_out[i] = my_med;
2474 } else if ((fmedian < 0) && (fabs(my_med-pimg_in[i]) >= -fmedian)) {
2475 pimg_out[i] = my_med;
2476 } else if ((fmedian > 0) &&
2477 (fabs(my_med-pimg_in[i]) >=
2478 fmedian*sqrt(fabs(my_med))))
2479 {
2480 pimg_out[i] = my_med;
2481 } else {
2483 eris_ifu_free_int_array(&position);
2484 continue;
2485 }
2487 eris_ifu_free_int_array(&position);
2488 }
2489 }
2490 CATCH
2491 {
2492 CATCH_MSGS();
2493 eris_ifu_free_hdrl_image(&hdrl_img_out);
2494 }
2495
2497 eris_ifu_free_int_array(&position);
2498 eris_check_error_code("eris_ifu_flat_median_image");
2499 return hdrl_img_out;
2500}
2501
2515cpl_error_code eris_ifu_sinfo_compare_images(const hdrl_image *hdrl_img1,
2516 const hdrl_image *hdrl_img2,
2517 hdrl_image *hdrl_img_orig)
2518{
2519 const cpl_image *img1 = NULL,
2520 *img2 = NULL;
2521 const double *pimg1 = NULL;
2522 const double *pimg2 = NULL;
2523 const cpl_mask *mask_img1 = NULL,
2524 *mask_img2 = NULL;
2525 cpl_mask *mask_orig = NULL;
2526 const cpl_binary *pmask_img1 = NULL,
2527 *pmask_img2 = NULL;
2528 cpl_binary *pmask_orig = NULL;
2529 cpl_error_code err = CPL_ERROR_NONE;
2530 int nx1 = 0,
2531 ny1 = 0,
2532 nx2 = 0,
2533 ny2 = 0;
2534
2535 cpl_ensure_code(hdrl_img1, CPL_ERROR_NULL_INPUT);
2536 cpl_ensure_code(hdrl_img2, CPL_ERROR_NULL_INPUT);
2537 cpl_ensure_code(hdrl_img_orig, CPL_ERROR_NULL_INPUT);
2538
2539 nx1 = hdrl_image_get_size_x(hdrl_img1);
2540 ny1 = hdrl_image_get_size_y(hdrl_img1);
2541 nx2 = hdrl_image_get_size_x(hdrl_img2);
2542 ny2 = hdrl_image_get_size_y(hdrl_img2);
2543
2544 cpl_ensure_code(nx1 == nx2, CPL_ERROR_ILLEGAL_INPUT);
2545 cpl_ensure_code(ny1 == ny2, CPL_ERROR_ILLEGAL_INPUT);
2546
2547 TRY
2548 {
2549 img1 = hdrl_image_get_image_const(hdrl_img1);
2550 img2 = hdrl_image_get_image_const(hdrl_img2);
2551 pimg1=cpl_image_get_data_double_const(img1);
2552 pimg2=cpl_image_get_data_double_const(img2);
2553
2554 mask_img1 = hdrl_image_get_mask_const(hdrl_img1);
2555 mask_img2 = hdrl_image_get_mask_const(hdrl_img2);
2556 mask_orig = hdrl_image_get_mask(hdrl_img_orig);
2557 pmask_img1 = cpl_mask_get_data_const(mask_img1);
2558 pmask_img2 = cpl_mask_get_data_const(mask_img2);
2559 pmask_orig = cpl_mask_get_data(mask_orig);
2560
2561 for (int i = 0; i < nx1*ny1; i++) {
2562 if ((pmask_img1[i] == BAD_PIX) ||
2563 (pmask_img2[i] == BAD_PIX) ||
2564 (pimg1[i] != pimg2[i]))
2565 {
2566 pmask_orig[i] = BAD_PIX;
2567 }
2568 }
2569 }
2570 CATCH
2571 {
2572 CATCH_MSGS();
2573 err = cpl_error_get_code();
2574 }
2575 eris_check_error_code("eris_ifu_sinfo_compare_images");
2576 return err;
2577}
2578
2588cpl_error_code eris_ifu_flat_fast_bpm(hdrl_image *master_flat,
2589 const cpl_parameterlist *parlist,
2590 int productDepth)
2591{
2592 int llx = 0,
2593 lly = 0,
2594 urx = 0,
2595 ury = 0;
2596 cpl_error_code err = CPL_ERROR_NONE;
2597 cpl_mask *bpm = NULL;
2598 cpl_image *img = NULL;
2599 const cpl_image *data = NULL;
2600 cpl_binary *pbpm = NULL;
2601
2602 cpl_ensure_code(master_flat, CPL_ERROR_NULL_INPUT);
2603 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
2604
2605 TRY
2606 {
2607 // AA ToDo: implement as well right border handling
2608
2609 bpm = hdrl_image_get_mask(master_flat);
2610 pbpm = cpl_mask_get_data(bpm);
2611 data = hdrl_image_get_image_const(master_flat);
2612
2613 // check left side
2614 llx = 1,
2615 lly = 1,
2616 urx = ERIS_IFU_DETECTOR_BP_BORDER+SLITLET_WIDTH,
2617 ury = ERIS_IFU_DETECTOR_SIZE_Y;
2618
2620 img = cpl_image_extract(data, llx, lly, urx, ury));
2621 //eris_ifu_save_image_dbg(img, "sss_in.fits", CPL_IO_CREATE, NULL);
2622
2623 int nr_values = 21, //odd
2624 center_y = 0,
2625 height = 96; // even
2626 cpl_vector *profile_x = NULL;
2627 double left_edge_pos = 0.,
2628 right_edge_pos = 0.,
2629 *pprofile_x = NULL;
2630
2631 // for (int i = ERIS_IFU_DETECTOR_BP_BORDER;
2632 // y < ERIS_IFU_DETECTOR_SIZE_Y-ERIS_IFU_DETECTOR_BP_BORDER;
2633 // y++)
2634 // {
2635 for (int i = 0; i < nr_values; i++) {
2636 /* collapse image in y and convert to vector */
2637 center_y = ERIS_IFU_DETECTOR_BP_BORDER + i*height + height/2;
2639 img, center_y, height);
2640 // double *pimg = (double*)cpl_image_get_data_const(img);
2641 //eris_ifu_save_vector_dbg(profile_x, "sss_profx.fits", CPL_IO_CREATE);
2642
2643 pprofile_x = cpl_vector_get_data(profile_x);
2644
2645 cpl_image *imgg=NULL;
2646 imgg = cpl_image_wrap_double(cpl_vector_get_size(profile_x),1,
2647 pprofile_x);
2648
2649 imgg = cpl_image_wrap_double(cpl_image_get_size_x(img), 1,
2650 pprofile_x);
2651
2652 cpl_error_code status = eris_ifu_slitpos_gauss(imgg,
2653 &left_edge_pos,
2654 &right_edge_pos,
2655 0,
2656 productDepth);
2657
2658 if (status == CPL_ERROR_EOL) {
2659 RECOVER();
2660 continue;
2661 } else if (status != CPL_ERROR_NONE) {
2663 }
2664
2665 // erase bmp left
2666 for (int y = center_y-height/2; y < center_y+height/2; y++) {
2667 for (int x = 0; x <= (int)(left_edge_pos+.5); x++) {
2668 pbpm[x+y*ERIS_IFU_DETECTOR_SIZE_X] = BAD_PIX;
2669 } //end: for(x)
2670 } //end: for(y)
2671 //eris_ifu_save_hdrl_image_dbg(master_flat, "zzz", TRUE);
2672 //CHECK_ERROR_STATE();
2673 } // end: for(i)
2674
2675 // AA todo: fix
2676 for (int y = 2020; y < 2045; y++) {
2677 for (int x = 0; x <= (int)(left_edge_pos+.5); x++) {
2678 pbpm[x+y*ERIS_IFU_DETECTOR_SIZE_X] = BAD_PIX;
2679 } //end: for(x)
2680 } //end: for(y)
2681
2683 }
2684 CATCH
2685 {
2686 CATCH_MSGS();
2687 err = cpl_error_get_code();
2688 }
2689 eris_check_error_code("eris_ifu_flat_fast_bpm");
2690 return err;
2691}
2692
2693/* ---- Data collector ---- */
2694cpl_error_code eris_ifu_flat_data_init(struct structFlatData *self, int blocksize) {
2695 cpl_error_code err = CPL_ERROR_NONE;
2696
2697 cpl_ensure_code(blocksize > 0, CPL_ERROR_ILLEGAL_INPUT);
2698
2699 TRY
2700 {
2701 self->cnt = 0;
2702 self->blocksize = blocksize;
2703 int nr = ERIS_IFU_DETECTOR_SIZE_Y/blocksize; // is 51 for blocksize = 40
2704 self->ry = cpl_vector_new(nr);
2705 self->borderAleft = cpl_vector_new(nr);
2706 self->borderAright = cpl_vector_new(nr);
2707 self->borderBleft = cpl_vector_new(nr);
2708 self->borderBright = cpl_vector_new(nr);
2709 self->borderCleft = cpl_vector_new(nr);
2710 self->borderCright = cpl_vector_new(nr);
2711 self->borderDleft = cpl_vector_new(nr);
2712 self->borderDright = cpl_vector_new(nr);
2713 }
2714 CATCH
2715 {
2716 CATCH_MSGS();
2717 err = cpl_error_get_code();
2718 }
2719 eris_check_error_code("eris_ifu_flat_data_init");
2720 return err;
2721}
2722
2723cpl_error_code eris_ifu_flat_data_setBorders(struct structFlatData *self, int ry,
2724 int leftEdgeA, int rightEdgeA,
2725 int leftEdgeB, int rightEdgeB,
2726 int leftEdgeC, int rightEdgeC,
2727 int leftEdgeD, int rightEdgeD)
2728{
2729 cpl_error_code err = CPL_ERROR_NONE;
2730
2731 TRY
2732 {
2733 cpl_vector_set(self->ry, self->cnt, ry);
2734 cpl_vector_set(self->borderAleft, self->cnt, leftEdgeA);
2735 cpl_vector_set(self->borderAright, self->cnt, rightEdgeA);
2736 cpl_vector_set(self->borderBleft, self->cnt, leftEdgeB);
2737 cpl_vector_set(self->borderBright, self->cnt, rightEdgeB);
2738 cpl_vector_set(self->borderCleft, self->cnt, leftEdgeC);
2739 cpl_vector_set(self->borderCright, self->cnt, rightEdgeC);
2740 cpl_vector_set(self->borderDleft, self->cnt, leftEdgeD);
2741 cpl_vector_set(self->borderDright, self->cnt, rightEdgeD);
2742 self->cnt++;
2743 }
2744 CATCH
2745 {
2746 CATCH_MSGS();
2747 err = cpl_error_get_code();
2748 }
2749 eris_check_error_code("eris_ifu_flat_data_setBorders");
2750 return err;
2751}
2752
2753cpl_vector* eris_ifu_flat_data_getBorderInterpolated(struct structFlatData *self,
2754 int row)
2755{
2756 cpl_vector *borders = NULL,
2757 *fit_par = NULL;
2758 int degree = 2,
2759 rowx = 0;
2760 double *pfit_par = NULL,
2761 *pborders = NULL;
2762 TRY
2763 {
2764 rowx = row + self->blocksize/2.;
2765
2766 borders = cpl_vector_new(8);
2767 pborders = cpl_vector_get_data(borders);
2768
2769 fit_par = eris_ifu_polyfit_1d(self->ry, self->borderAleft, degree);
2770 pfit_par = cpl_vector_get_data(fit_par);
2771 pborders[0] = (int)(pfit_par[0] + pfit_par[1] * rowx + pfit_par[2] * pow(rowx, 2) + 0.5);
2772 eris_ifu_free_vector(&fit_par);
2773
2774 fit_par = eris_ifu_polyfit_1d(self->ry, self->borderAright, degree);
2775 pfit_par = cpl_vector_get_data(fit_par);
2776 pborders[1] = (int)(pfit_par[0] + pfit_par[1] * rowx + pfit_par[2] * pow(rowx, 2) + 0.5);
2777 eris_ifu_free_vector(&fit_par);
2778
2779 fit_par = eris_ifu_polyfit_1d(self->ry, self->borderBleft, degree);
2780 pfit_par = cpl_vector_get_data(fit_par);
2781 pborders[2] = (int)(pfit_par[0] + pfit_par[1] * rowx + pfit_par[2] * pow(rowx, 2) + 0.5);
2782 eris_ifu_free_vector(&fit_par);
2783
2784 fit_par = eris_ifu_polyfit_1d(self->ry, self->borderBright, degree);
2785 pfit_par = cpl_vector_get_data(fit_par);
2786 pborders[3] = (int)(pfit_par[0] + pfit_par[1] * rowx + pfit_par[2] * pow(rowx, 2) + 0.5);
2787 eris_ifu_free_vector(&fit_par);
2788
2789 fit_par = eris_ifu_polyfit_1d(self->ry, self->borderCleft, degree);
2790 pfit_par = cpl_vector_get_data(fit_par);
2791 pborders[4] = (int)(pfit_par[0] + pfit_par[1] * rowx + pfit_par[2] * pow(rowx, 2) + 0.5);
2792 eris_ifu_free_vector(&fit_par);
2793
2794 fit_par = eris_ifu_polyfit_1d(self->ry, self->borderCright, degree);
2795 pfit_par = cpl_vector_get_data(fit_par);
2796 pborders[5] = (int)(pfit_par[0] + pfit_par[1] * rowx + pfit_par[2] * pow(rowx, 2) + 0.5);
2797 eris_ifu_free_vector(&fit_par);
2798
2799 fit_par = eris_ifu_polyfit_1d(self->ry, self->borderDleft, degree);
2800 pfit_par = cpl_vector_get_data(fit_par);
2801 pborders[6] = (int)(pfit_par[0] + pfit_par[1] * rowx + pfit_par[2] * pow(rowx, 2) + 0.5);
2802 eris_ifu_free_vector(&fit_par);
2803
2804 fit_par = eris_ifu_polyfit_1d(self->ry, self->borderDright, degree);
2805 pfit_par = cpl_vector_get_data(fit_par);
2806 pborders[7] = (int)(pfit_par[0] + pfit_par[1] * rowx + pfit_par[2] * pow(rowx, 2) + 0.5);
2807 eris_ifu_free_vector(&fit_par);
2808 }
2809 CATCH
2810 {
2811 CATCH_MSGS();
2812 eris_ifu_free_vector(&borders);
2813 }
2814 eris_check_error_code("eris_ifu_flat_data_getBorderInterpolated");
2815 return borders;
2816}
cpl_error_code eris_ifu_append_qc_double(cpl_propertylist *pl, const char *name, double val, const char *comment)
Append a QC parameter of type DOUBLE to a property list.
bool eris_ifu_frame_is_sky(const cpl_frame *fr)
Determine if a frame is a Sky frame or not.
ifsBand eris_ifu_get_band(const cpl_propertylist *header)
Determine preoptic band.
cpl_error_code eris_ifu_append_qc_int(cpl_propertylist *pl, const char *name, int val, const char *comment)
Append a QC parameter of type INT to a property list.
bool eris_ifu_frame_is_on(const cpl_frame *fr)
Determine if a frame is obtained with lamps ON or OFF.
#define ASSURE(condition, error,...)
error handling macro (from fors-pipeline)
#define ERIS_IFU_TRY_EXIT(void)
The try-block is exited.
#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_slitpos_gauss(const cpl_image *profile_x, double *left_edge_pos, double *right_edge_pos, int llx, int productDepth)
eris_ifu_dist_slitpos_gauss
cpl_vector * eris_ifu_calc_centers_collapse_chunk(const cpl_image *img, int chunk_center, int height)
cpl_vector * eris_ifu_image_collapse(const cpl_image *img)
cpl_error_code eris_ifu_calc_bpm(const cpl_parameterlist *pl, const char *recipe_name, hdrl_image *master_img, const hdrl_imagelist *imglist_on, cpl_mask **bpm2dMask, cpl_mask **bpm3dMask)
Create and apply 2D and/or 3D Badpixel-Mask based on parameter.
cpl_error_code eris_ifu_add_badpix_border(cpl_image *data, cpl_boolean add_ones, cpl_image *dqi)
Add image border frame to bad pixel map.
cpl_vector * eris_ifu_polyfit_1d(const cpl_vector *x, const cpl_vector *y, const int degree)
An easy-to-handle wrapper to cpl_polynomial_fit() to fit a vector.
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_frameset(cpl_frameset **item)
free memory and set pointer to null
void eris_ifu_free_propertylist(cpl_propertylist **item)
free memory and set pointer to null
void eris_ifu_free_string(char **item)
free memory and set pointer to null
void eris_ifu_free_double_array(double **item)
free memory and set pointer to null
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
cpl_mask * eris_ifu_load_badpixel_mask(const cpl_frameset *frameset, const char *category, int ext)
‍**
void eris_ifu_free_int_array(int **item)
free memory and set pointer to null
void eris_ifu_free_hdrl_imagelist(hdrl_imagelist **item)
free memory and set pointer to null
cpl_error_code eris_ifu_save_hdrl_imagelist_dbg(const hdrl_imagelist *hdrl_img_list, const char *filename, int singlefile)
eris_ifu_save_hdrl_imagelist_dbg
cpl_error_code eris_ifu_save_hdrl_image_dbg(const hdrl_image *hdrl_img, const char *filename, int singlefile, const cpl_propertylist *pl)
save HDRL imagelist for debugging purposes
void eris_ifu_free_hdrl_image(hdrl_image **item)
free memory and set pointer to null
cpl_error_code eris_ifu_get_badpix_qc_from_mask(const cpl_mask *bp_mask, cpl_propertylist *qc_list, const char *prefix)
compute QC keyword with number of bad pixels and fraction to total
void eris_ifu_free_image(cpl_image **item)
free memory and set pointer to null
void eris_ifu_free_matrix(cpl_matrix **item)
free memory and set pointer to null
void eris_ifu_free_mask(cpl_mask **item)
free memory and set pointer to null
cpl_frameset * eris_ifu_get_frameset_by_tag(const cpl_frameset *frameset, const char *tag)
Get frames with given tag from frameset.
cpl_error_code eris_ifu_save_image(cpl_frameset *fs, const cpl_propertylist *plist, const cpl_parameterlist *parlist, const char *recipe, const char *procatg, const char *filename, cpl_type type, const cpl_image *image)
save image
void eris_ifu_free_hdrl_parameter(hdrl_parameter **item)
free memory and set pointer to null
cpl_error_code eris_check_error_code(const char *func_id)
handle CPL errors
Definition: eris_utils.c:56
hdrl_parameter * hdrl_collapse_parameter_parse_parlist(const cpl_parameterlist *parlist, const char *prefix)
parse parameterlist for imagelist reduction method
cpl_error_code hdrl_flat_compute(hdrl_imagelist *hdrl_data, const cpl_mask *stat_mask, const hdrl_parameter *collapse_params, hdrl_parameter *flat_params, hdrl_image **master, cpl_image **contrib_map)
compute high or low frequency master flat with median filtering
Definition: hdrl_flat.c:405
hdrl_parameter * hdrl_flat_parameter_parse_parlist(const cpl_parameterlist *parlist, const char *prefix)
Parse a parameterlist to create input parameters for the FLAT.
Definition: hdrl_flat.c:331
hdrl_value hdrl_image_get_pixel(const hdrl_image *self, cpl_size xpos, cpl_size ypos, int *pis_rejected)
get pixel values of hdrl_image
Definition: hdrl_image.c:559
int hdrl_image_is_rejected(hdrl_image *self, cpl_size xpos, cpl_size ypos)
return if pixel is marked bad
Definition: hdrl_image.c:445
cpl_error_code hdrl_image_set_pixel(hdrl_image *self, cpl_size xpos, cpl_size ypos, hdrl_value value)
set pixel values of hdrl_image
Definition: hdrl_image.c:594
cpl_error_code hdrl_image_sub_image(hdrl_image *self, const hdrl_image *other)
Subtract two images, store the result in the first image.
cpl_error_code hdrl_image_reject_from_mask(hdrl_image *self, const cpl_mask *map)
set bpm of hdrl_image
Definition: hdrl_image.c:407
cpl_error_code hdrl_image_div_scalar(hdrl_image *self, hdrl_value value)
Elementwise division of an image with a scalar.
hdrl_value hdrl_image_get_median(const hdrl_image *self)
computes the median and associated error of an image.
hdrl_image * hdrl_image_sub_image_create(const hdrl_image *self, const hdrl_image *other)
Subtract two images.
hdrl_image * hdrl_image_duplicate(const hdrl_image *himg)
copy hdrl_image
Definition: hdrl_image.c:391
cpl_mask * hdrl_image_get_mask(hdrl_image *himg)
get cpl bad pixel mask from image
Definition: hdrl_image.c:157
hdrl_image * hdrl_image_extract(const hdrl_image *self, cpl_size llx, cpl_size lly, cpl_size urx, cpl_size ury)
extract copy of window from image
Definition: hdrl_image.c:625
cpl_image * hdrl_image_get_error(hdrl_image *himg)
get error as cpl image
Definition: hdrl_image.c:131
hdrl_value hdrl_image_get_mean(const hdrl_image *self)
computes mean pixel value and associated error of an image.
cpl_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
Definition: hdrl_image.c:540
const cpl_mask * hdrl_image_get_mask_const(const hdrl_image *himg)
get cpl bad pixel mask from image
Definition: hdrl_image.c:175
cpl_size hdrl_image_get_size_x(const hdrl_image *self)
return size of X dimension of image
Definition: hdrl_image.c:525
hdrl_image * hdrl_image_create(const cpl_image *image, const cpl_image *error)
create a new hdrl_image from to existing images by copying them
Definition: hdrl_image.c:295
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:105
cpl_error_code hdrl_image_reject(hdrl_image *self, cpl_size xpos, cpl_size ypos)
mark pixel as bad
Definition: hdrl_image.c:427
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_set(hdrl_imagelist *himlist, hdrl_image *himg, cpl_size pos)
Insert an image into an imagelist.
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.
cpl_error_code hdrl_imagelist_collapse(const hdrl_imagelist *himlist, const hdrl_parameter *param, hdrl_image **out, cpl_image **contrib)
collapsing of image list
hdrl_imagelist * hdrl_imagelist_new(void)
Create an empty imagelist.
cpl_error_code hdrl_imagelist_sub_imagelist(hdrl_imagelist *himlist1, const hdrl_imagelist *himlist2)
Subtract two image lists, the first one is replaced by the result.
hdrl_imagelist * hdrl_imagelist_duplicate(const hdrl_imagelist *himlist)
Duplicate an image list.