ERIS Pipeline Reference Manual 1.8.15
eris_ifu_detlin.c
1/* $Id: eris_ifu_detlin.c,v 0.1 2019-06-11 08:13:17 06:06:06 agudo Exp $
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: agudo $
23 * $Date: 2018-06-11 06:06:06 $
24 * $Revision: 0.1 $
25 * $Name: not supported by cvs2svn $
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h> /* allows the program compilation */
30#endif
31
32/*-----------------------------------------------------------------------------
33 Includes
34 ----------------------------------------------------------------------------*/
35#include <strings.h>
36#include <string.h>
37#include <stdio.h>
38#include <math.h>
39
40#include <cpl.h>
41#include <hdrl.h>
42//#include <irplib_utils.h>
43
44#include "eris_ifu_dfs.h"
45#include "eris_ifu_error.h"
46#include "eris_ifu_functions.h"
47#include "eris_ifu_utils.h"
48#include "eris_ifu_detlin_static.h"
49
50/*-----------------------------------------------------------------------------
51 Static variables
52 ----------------------------------------------------------------------------*/
53static char eris_ifu_detlin_description[] = "\
54This recipe computes detector non linearities and a bad pixel map.\n\
55The input files are increasing intensity raw flats\n\
56\n\
57-----------------------------------------------------------------------------\n\
58Input files:\n\
59 DO CATG Explanation Required #Frames\n\
60 ------- ----------- -------- -------\n\
61 LINEARITY_LAMP Lamp exposures Y 3-n \n\
62\n\
63Output files:\n\
64 DO CATG Explanation\n\
65 ------- -----------\n\
66 BPM_DETLIN Badpixel frame\n\
67 BPM_DETLIN_FILT Filtered badpixel frame\n\
68-----------------------------------------------------------------------------\n\
69\n\
70Information on relevant parameters may be found with\n\
71 esorex --params "REC_NAME_DETLIN"\n\
72 esorex --help "REC_NAME_DETLIN"\n";
73
74/*-----------------------------------------------------------------------------
75 Private function prototypes
76 -----------------------------------------------------------------------------*/
77cpl_recipe_define(eris_ifu_detlin, ERIS_BINARY_VERSION, "Alex Agudo Berbel",
78 PACKAGE_BUGREPORT, "2020",
79 "Detector's linearity & non linear bad pixels determination.",
80 eris_ifu_detlin_description);
81
82/*-----------------------------------------------------------------------------
83 Functions code
84 ----------------------------------------------------------------------------*/
85
86/*---------------------------------------------------------------------------*/
94/*---------------------------------------------------------------------------*/
95static cpl_error_code eris_ifu_detlin_fill_parameterlist(cpl_parameterlist *pl)
96{
97 cpl_error_code err = CPL_ERROR_NONE;
98 cpl_parameter *p = NULL;
99 hdrl_parameter *hp = NULL;
100 cpl_parameterlist *pl_tmp = NULL;
101
102 cpl_ensure_code(pl, CPL_ERROR_NULL_INPUT);
103
104 TRY
105 {
107 eris_ifu_add_std_params(pl, REC_NAME_DETLIN));
108
110 hp = hdrl_bpm_fit_parameter_create_rel_chi(2, 8.0, 8.0));
111
113 pl_tmp = hdrl_bpm_fit_parameter_create_parlist(REC_NAME_DETLIN,
114 "", hp));
116 for (p = cpl_parameterlist_get_first(pl_tmp);
117 p != NULL;
118 p = cpl_parameterlist_get_next(pl_tmp))
119 {
121 cpl_parameterlist_append(pl, cpl_parameter_duplicate(p)));
122 }
124
126 p = cpl_parameter_new_value(REC_NAME_DETLIN".post-filter-x",
127 CPL_TYPE_INT,
128 "X Size of the post filtering kernel",
129 REC_NAME_DETLIN,
130 3));
132 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pfx"));
134 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV));
136 cpl_parameterlist_append(pl, p));
137
139 p = cpl_parameter_new_value(REC_NAME_DETLIN".post-filter-y",
140 CPL_TYPE_INT,
141 "Y Size of the post filtering kernel",
142 REC_NAME_DETLIN,
143 3));
145 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pfy"));
147 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV));
149 cpl_parameterlist_append(pl, p));
150
152 p = cpl_parameter_new_enum(REC_NAME_DETLIN".post-filter-mode",
153 CPL_TYPE_STRING,
154 "Post filtering mode",
155 REC_NAME_DETLIN,
156 "closing", 2,
157 "closing", "dilation"));
159 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pfm"));
161 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV));
163 cpl_parameterlist_append(pl, p));
164 }
165 CATCH
166 {
167 CATCH_MSGS();
168 err = cpl_error_get_code();
169 }
170
171 return err;
172}
173
174/*---------------------------------------------------------------------------*/
181/*---------------------------------------------------------------------------*/
182static int
183eris_ifu_detlin(cpl_frameset *frameset, const cpl_parameterlist *parlist)
184{
185 double p = 0.;
186 cpl_size n = 0.;
187 cpl_vector *vec_dit_on = NULL,
188 *vec_dit_off = NULL;
189 cpl_image *bpm = NULL,
190 *bpm_filtered = NULL;
191 cpl_mask *bpm_mask = NULL,
192 *bpm_mask_filtered = NULL;
193 cpl_propertylist *qc_list = NULL;
194 hdrl_imagelist *hdrl_imglist_on = NULL,
195 *hdrl_imglist_off = NULL;
196 double dit_on;
197 struct stdParamStruct stdParams = stdParamStructInit;
198
199 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
200 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
201 cpl_ensure_code(cpl_frameset_is_empty(frameset) == FALSE,
202 CPL_ERROR_NULL_INPUT);
203 cpl_ensure_code(cpl_frameset_count_tags(frameset, ERIS_IFU_RAW_LIN) > 2,
204 CPL_ERROR_ILLEGAL_INPUT);
205
206 TRY
207 {
208 /* -----------------------------------------------------------------
209 * Setup
210 * ----------------------------------------------------------------- */
211// /* --instrument */
212// BRK_IF_NULL(
213// instrument = cpl_parameter_get_string(
214// cpl_parameterlist_find_const(parlist,
215// "eris.eris_ifu_detlin.instrument")));
216// cpl_msg_info(cpl_func, "Processing %s frames", instrument);
217
218 /* Identify the RAW and CALIB frames in the input frameset */
219 eris_ifu_dfs_set_groups(frameset);
220 eris_ifu_fetch_std_param(parlist, REC_NAME_DETLIN, &stdParams);
221 qc_list = cpl_propertylist_new();
222
223 char* pipe_id = cpl_sprintf("%s%s%s", PACKAGE, "/", PACKAGE_VERSION);
224 cpl_propertylist *applist = cpl_propertylist_new();
225 cpl_propertylist_update_string(applist, CPL_DFS_PRO_CATG,
226 ERIS_IFU_PRO_DETLIN_GAIN_INFO);
227 cpl_table* gain_table = eris_compute_gain(frameset);
228 cpl_dfs_save_propertylist(frameset, NULL, parlist, frameset, NULL,
229 REC_NAME_DETLIN, applist, NULL,
230 pipe_id, ERIS_IFU_PRO_DETLIN_GAIN_INFO_FN);
231 cpl_table_save(gain_table, applist, applist,
232 ERIS_IFU_PRO_DETLIN_GAIN_INFO_FN, CPL_IO_EXTEND);
233 cpl_table_delete(gain_table);
234 cpl_propertylist_delete(applist);
235 cpl_free(pipe_id);
236// Search for static bad pixels in stacks of flatfield frames
237// with in/decreasing intensities. For each pixel position a curve is plotted
238// of the pixel intensity in each plane against the clean mean of the whole
239// plane.
240// A polynomial is fit and the found coefficients are stored sequentially in
241// a data cube. Then the deviation of the linear coefficients from the clean
242// mean is computed for each pixel and the pixel are declared bad if the
243// deviations exceed a threshold defined by a factor of the clean standard
244// deviation.
245// For the resting good pixels the non-linear coefficients are examined.
246// If one coefficients deviate more than a user given threshold the pixel
247// is also declared as bad. The data cubus with the fit results and
248// a bad pixel mask image is stored
249
250 cpl_msg_info(cpl_func, "Loading frames...");
251 eris_ifu_detlin_load_frames(frameset, stdParams.rawImageCorrectionMask,
252 &hdrl_imglist_on, &hdrl_imglist_off, &vec_dit_on, &vec_dit_off);
253
254 /* save optional output */
255 if ((stdParams.productDepth & 2) != 0) {
256 cpl_msg_info(cpl_func, "Save additional products ...");
257 eris_ifu_save_hdrl_imagelist_dbg(hdrl_imglist_on,
258 ERIS_IFU_PRO_DETLIN_DBG_CUBE_ON_FN, TRUE);
259 eris_ifu_save_hdrl_imagelist_dbg(hdrl_imglist_off,
260 ERIS_IFU_PRO_DETLIN_DBG_CUBE_OFF_FN, TRUE);
261 }
262 /* subtract on- and off-frames */
263 int onSize = (int) hdrl_imagelist_get_size(hdrl_imglist_on);
264 int offSize = (int) hdrl_imagelist_get_size(hdrl_imglist_off);
265 for (int ix=0; ix < onSize; ix++) {
266 dit_on = cpl_vector_get(vec_dit_on, ix);
267 int found = 0;
268 for (int ox=0; ox < offSize; ox++) {
269 if (dit_on == cpl_vector_get(vec_dit_off, ox)) {
270 found = 1;
271 hdrl_image_sub_image(hdrl_imagelist_get(hdrl_imglist_on, ix),
272 hdrl_imagelist_get_const(hdrl_imglist_off, ox));
273 break;
274 }
275 }
276 if (found == 0) {
277 cpl_msg_error(cpl_func, "No matching off-frame DIT found for"
278 "DIT %f", dit_on);
279 }
280 }
281 eris_ifu_free_hdrl_imagelist(&hdrl_imglist_off);
282 /* For some reason the bad pixel propagation generates a new bad pixel
283 * that is not properly flagged in the hdrl image. Therefore adding this
284 * lines synchronizes again the bpm of the data and error section. This
285 * could happen if there are invalid pixel in the error section that
286 * were not properly flagged at the beginning - like INFINITY */
287
288 for (int ix=0; ix < onSize; ix++) {
289 hdrl_image * himage = hdrl_imagelist_get(hdrl_imglist_on, ix);
290 cpl_image * cimage_data = hdrl_image_get_image(himage);
291 cpl_image * cimage_error = hdrl_image_get_error(himage);
292
293 cpl_mask * dbpm = cpl_image_get_bpm(cimage_data);
294 cpl_mask * ebpm = cpl_image_get_bpm(cimage_error);
295 cpl_mask_or(dbpm, ebpm);
296 cpl_mask_or(ebpm, dbpm);
297 }
298
299 /* save optional output */
300 if ((stdParams.productDepth & 2) != 0) {
301 cpl_msg_info(cpl_func, "Save additional products ...");
302 eris_ifu_save_hdrl_imagelist_dbg(hdrl_imglist_on,
303 ERIS_IFU_PRO_DETLIN_DBG_CUBE_SUB_FN, TRUE);
304 }
305
306 cpl_msg_info(cpl_func, "Generating bad pixel map...");
307 bpm = eris_ifu_detlin_compute_linearity(parlist, hdrl_imglist_on,
308 vec_dit_on, qc_list);
309
310 /* calc stats on bpm */
311 bpm_mask = cpl_mask_threshold_image_create(bpm, 0, INT_MAX);
312 n = cpl_mask_count(bpm_mask);
313 p = (double)n /
314 (double) (cpl_mask_get_size_x(bpm_mask) * cpl_mask_get_size_y(bpm_mask));
316 cpl_msg_info(cpl_func, " %lld bad pixels (%g%%)", n, p * 100.);
317
318 cpl_msg_info(cpl_func, "Filtering bad pixel map...");
319 bpm_mask_filtered = eris_ifu_detlin_filter_mask(bpm_mask, parlist);
320
321 cpl_msg_info(cpl_func, "Saving bad pixel maps...");
322 eris_ifu_save_image(frameset, qc_list, parlist, REC_NAME_DETLIN,
323 ERIS_IFU_PRO_DETLIN_BPM, ERIS_IFU_PRO_DETLIN_BPM_FN,
324 CPL_TYPE_USHORT, bpm);
325 cpl_propertylist_delete(qc_list);
326 qc_list = cpl_propertylist_new();
327 bpm_filtered = cpl_image_new_from_mask(bpm_mask_filtered);
328 eris_ifu_get_badpix_qc_from_ima(bpm_filtered, qc_list, "LINEARITY");
329 eris_ifu_save_image(frameset, qc_list, parlist, REC_NAME_DETLIN,
330 ERIS_IFU_PRO_DETLIN_BPM_FILT,
331 ERIS_IFU_PRO_DETLIN_BPM_FILT_FN, CPL_TYPE_USHORT,
332 bpm_filtered);
333 }
334 CATCH
335 {
336 CATCH_MSGS();
337 }
338
339 eris_ifu_free_hdrl_imagelist(&hdrl_imglist_on);
340 eris_ifu_free_vector(&vec_dit_on);
341 eris_ifu_free_vector(&vec_dit_off);
343 eris_ifu_free_mask(&bpm_mask);
344 eris_ifu_free_image(&bpm_filtered);
345 eris_ifu_free_mask(&bpm_mask_filtered);
347 eris_ifu_free_std_param(&stdParams);
348 if (cpl_memory_is_empty() == 0) {
349 cpl_memory_dump();
350 }
351
352 return (int) cpl_error_get_code();
353}
354
cpl_mask * eris_ifu_detlin_filter_mask(const cpl_mask *bpm, const cpl_parameterlist *parlist)
Apply morphological filtering to a bad pixel mask.
cpl_error_code eris_ifu_detlin_load_frames(const cpl_frameset *frameset, int exposureCorrectionMode, hdrl_imagelist **hdrl_imglist_on, hdrl_imagelist **hdrl_imglist_off, cpl_vector **vec_dit_on, cpl_vector **vec_dit_off)
Load linearity calibration frames from a frameset.
cpl_table * eris_compute_gain(cpl_frameset *frameset)
Compute detector gain from linearity frames.
cpl_image * eris_ifu_detlin_compute_linearity(const cpl_parameterlist *parlist, const hdrl_imagelist *imglist, const cpl_vector *vec_dit, cpl_propertylist *qclog)
Compute detector linearity bad pixel map.
cpl_error_code eris_ifu_dfs_set_groups(cpl_frameset *self)
Set the frame group (RAW, CALIB, or PRODUCT) for all frames in a frameset.
Definition: eris_ifu_dfs.c:89
#define BRK_IF_ERROR(function)
If function is or returns an error != CPL_ERROR_NONE, then the try-block is exited.
#define CHECK_ERROR_STATE(void)
Check the CPL error state, and exit the try-block if not CPL_ERROR_NONE.
#define TRY
Beginning of a TRY-block.
#define CATCH
End of a TRY-block, beginning of a CATCH-block.
#define BRK_IF_NULL(function)
If function is or returns a NULL pointer, then the try-block is exited.
#define CATCH_MSGS()
Displays an error message stack.
cpl_error_code eris_ifu_fetch_std_param(const cpl_parameterlist *parlist, const char *recipename, struct stdParamStruct *stdParams)
Fetch standard parameters from parameter list into structure.
void eris_ifu_free_std_param(struct stdParamStruct *stdParams)
Free memory allocated for stdParamStruct.
cpl_error_code eris_ifu_add_std_params(cpl_parameterlist *pl, const char *recipename)
Add standard recipe parameters to a parameter list.
void eris_ifu_free_propertylist(cpl_propertylist **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_get_badpix_qc_from_ima(const cpl_image *image, cpl_propertylist *qc_list, const char *prefix)
compute QC keyword with number of bad pixels and fraction to total
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)
void eris_ifu_free_image(cpl_image **item)
Free memory and set pointer to null.
void eris_ifu_free_mask(cpl_mask **item)
Free memory and set pointer to null.
void eris_ifu_free_parameterlist(cpl_parameterlist **item)
Free memory and set pointer to null.
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_parameterlist * hdrl_bpm_fit_parameter_create_parlist(const char *base_context, const char *prefix, const hdrl_parameter *defaults)
Create a parameter list for the BPM_FIT computation.
Definition: hdrl_bpm_fit.c:363
hdrl_parameter * hdrl_bpm_fit_parameter_create_rel_chi(int degree, double rel_chi_low, double rel_chi_high)
create bpm_fit parameter with relative chi bpm treshold
Definition: hdrl_bpm_fit.c:158
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_image * hdrl_image_get_error(hdrl_image *himg)
get error as cpl image
Definition: hdrl_image.c:131
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:105
const hdrl_image * hdrl_imagelist_get_const(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.