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