ERIS Pipeline Reference Manual 1.8.15
eris_nix_gain_linearity.c
1/* $Id$
2 *
3 * This file is part of the ERIS/NIX Pipeline
4 * Copyright (C) 2017 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 /*
22 * $Author$
23 * $Date$
24 * $Rev$
25 */
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31/*-----------------------------------------------------------------------------
32 Includes
33 -----------------------------------------------------------------------------*/
34
35#include <cpl.h>
36#include <string.h>
37
38#include "eris_nix_gain_linearity.h"
39#include "eris_nix_utils.h"
40
41/*-----------------------------------------------------------------------------
42 Static function declarations
43 -----------------------------------------------------------------------------*/
44
45static
46gain_linearity * engl_gain_linearity_create(cpl_imagelist *,
47 cpl_mask *,
48 double *,
49 const hdrl_value,
50 const double,
51 cpl_propertylist *)
52 CPL_ATTR_ALLOC;
53
54static
55double * engl_repack(const cpl_imagelist *)
56 CPL_ATTR_ALLOC;
57
58/*----------------------------------------------------------------------------*/
62/*----------------------------------------------------------------------------*/
63
66/*----------------------------------------------------------------------------*/
75/*----------------------------------------------------------------------------*/
76
77void engl_gain_linearity_delete(gain_linearity * gain_lin) {
78
79 if (gain_lin) {
80 cpl_imagelist_delete(gain_lin->lin_coeffs);
81 cpl_free(gain_lin->ordered_lin_coeffs);
82 cpl_mask_delete(gain_lin->bpm);
83 cpl_propertylist_delete(gain_lin->plist);
84 cpl_free(gain_lin);
85 }
86}
87
88
89/*----------------------------------------------------------------------------*/
102/*----------------------------------------------------------------------------*/
103
104gain_linearity * engl_gain_linearity_load_from_frameset(const cpl_frameset * frameset,
105 const char * gain_tag,
106 const char * coeffs_tag,
107 const char * bpm_tag,
108 const int required,
109 cpl_frameset * used) {
110
111 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
112
113 const cpl_frame * linbpmframe = NULL;
114 const cpl_frame * lincoeffsframe = NULL;
115 const cpl_frame * gainframe = NULL;
116 cpl_imagelist * lin_coeffs = NULL;
117 cpl_mask * lin_bpm = NULL;
118 double * ordered_lin_coeffs = NULL;
119 cpl_propertylist * plist = NULL;
120 double saturation_limit = -1.0;
121 gain_linearity * result = NULL;
122
123 /* check parameters */
124
125 cpl_ensure(frameset, CPL_ERROR_NULL_INPUT, NULL);
126 cpl_ensure(gain_tag, CPL_ERROR_NULL_INPUT, NULL);
127 cpl_ensure(coeffs_tag, CPL_ERROR_NULL_INPUT, NULL);
128 cpl_ensure(bpm_tag, CPL_ERROR_NULL_INPUT, NULL);
129
130 /* Look for gain, coeffs and bpm files in frameset */
131
132 gainframe = cpl_frameset_find_const(frameset, gain_tag);
133 lincoeffsframe = cpl_frameset_find_const(frameset, coeffs_tag);
134 linbpmframe = cpl_frameset_find_const(frameset, bpm_tag);
135
136 if (required) {
137 cpl_ensure(lincoeffsframe && linbpmframe && gainframe,
138 CPL_ERROR_DATA_NOT_FOUND, NULL);
139 } else if (!(lincoeffsframe && linbpmframe && gainframe)) {
140 cpl_msg_warning(cpl_func, "gain/linearity information not available");
141 }
142
143 if (lincoeffsframe && linbpmframe && gainframe) {
144
145 /* Read the gain from the gain file property list */
146
147 plist = cpl_propertylist_load(cpl_frame_get_filename(gainframe), 0);
148 double gain_data = cpl_propertylist_get_double(plist, "ESO QC GAIN");
149 double gain_err = 0.0;
150 hdrl_value gain = (hdrl_value){gain_data, gain_err};
151
152 /* look for saturation_limit in DETMON invocation parameters */
153
154 for (int ip = 1; ip < 100; ip++) {
155 char * pname = cpl_sprintf("ESO PRO REC1 PARAM%-2d NAME", ip);
156 if (cpl_propertylist_has(plist, pname)) {
157 if (strstr(cpl_propertylist_get_string(plist, pname),
158 "saturation_limit")) {
159 char * vname = cpl_sprintf("ESO PRO REC1 PARAM%-2d VALUE", ip);
160 const char * sat_limit = cpl_propertylist_get_string(plist, vname);
161 sscanf(sat_limit, "%lf", &saturation_limit);
162 cpl_free(vname);
163 }
164 }
165 cpl_free(pname);
166 if (saturation_limit > 0.0) break;
167 }
168 if (saturation_limit < 0.0) {
169 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
170 "failed to read saturation_limit");
171 } else {
172 cpl_msg_info(cpl_func, "gain/linearity saturation limit = %6.1f",
173 saturation_limit);
174 }
175
176 /* Read in the linearity coefficients. They are stored by detmon
177 using a call to cpl_dfs_save_imagelist with type
178 CPL_BPP_IEEE_FLOAT */
179
180 lin_coeffs = cpl_imagelist_load(
181 cpl_frame_get_filename(lincoeffsframe), CPL_TYPE_FLOAT, 0);
182
183 /* ..and the mask of non-linear pixels */
184
185 lin_bpm = cpl_mask_load(cpl_frame_get_filename(linbpmframe), 0, 0);
186
187 /* ..reorder the linearity coeffs for more efficient access during
188 linearizaion */
189
190 ordered_lin_coeffs = engl_repack(lin_coeffs);
191
192 /* create the structure */
193
194 result = engl_gain_linearity_create(lin_coeffs, lin_bpm,
195 ordered_lin_coeffs, gain,
196 saturation_limit, plist);
197
198 /* Update 'used' frameset */
199
200 cpl_frame * dup_lincoeffsframe = cpl_frame_duplicate(lincoeffsframe);
201 cpl_frameset_insert(used, dup_lincoeffsframe);
202 cpl_frame * dup_linbpmframe = cpl_frame_duplicate(linbpmframe);
203 cpl_frameset_insert(used, dup_linbpmframe);
204 cpl_frame * dup_gainframe = cpl_frame_duplicate(gainframe);
205 cpl_frameset_insert(used, dup_gainframe);
206
207 if (cpl_error_get_code() != CPL_ERROR_NONE) {
208 engl_gain_linearity_delete(result);
209 result = NULL;
210 }
211
212 /* tidy up */
213 }
214
215 return result;
216}
217
218
219/*----------------------------------------------------------------------------*/
236/*----------------------------------------------------------------------------*/
237static
238gain_linearity * engl_gain_linearity_create(cpl_imagelist * lin_coeffs,
239 cpl_mask * lin_bpm,
240 double * ordered_lin_coeffs,
241 const hdrl_value gain,
242 const double saturation_limit,
243 cpl_propertylist * plist) {
244
245 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
246
247 cpl_ensure(lin_coeffs && lin_bpm && plist, CPL_ERROR_NULL_INPUT, NULL);
248
249 gain_linearity * result = cpl_malloc(sizeof(gain_linearity));
250 result->lin_coeffs = lin_coeffs;
251 result->bpm = lin_bpm;
252 result->ordered_lin_coeffs = ordered_lin_coeffs;
253 result->gain = gain;
254 result->saturation_limit = saturation_limit;
255 result->plist = plist;
256
257 return result;
258}
259
260
261/*----------------------------------------------------------------------------*/
280/*----------------------------------------------------------------------------*/
281
282gain_linearity * engl_gain_linearity_test(const cpl_size nx,
283 const cpl_size ny,
284 const double coeff0,
285 const double coeff1,
286 const double coeff2,
287 const double coeff3,
288 const hdrl_value gain,
289 const double saturation) {
290
291 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
292
293 cpl_imagelist * coeffs_imagelist = cpl_imagelist_new();
294 cpl_image * c0 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
295 cpl_image_fill_window(c0, 1, 1, nx, ny, coeff0);
296 cpl_imagelist_set(coeffs_imagelist, c0, 0);
297 cpl_image * c1 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
298 cpl_image_fill_window(c1, 1, 1, nx, ny, coeff1);
299 cpl_imagelist_set(coeffs_imagelist, c1, 1);
300 cpl_image * c2 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
301 cpl_image_fill_window(c2, 1, 1, nx, ny, coeff2);
302 cpl_imagelist_set(coeffs_imagelist, c2, 2);
303 cpl_image * c3 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
304 cpl_image_fill_window(c3, 1, 1, nx, ny, coeff3);
305 cpl_imagelist_set(coeffs_imagelist, c3, 3);
306
307 cpl_mask * bpm = cpl_mask_new(nx, ny);
308 cpl_propertylist * lin_plist = cpl_propertylist_new();
309
310 double * ordered_coeffs = engl_repack(coeffs_imagelist);
311
312 gain_linearity * result = engl_gain_linearity_create(coeffs_imagelist,
313 bpm,
314 ordered_coeffs,
315 gain,
316 saturation,
317 lin_plist);
318
319 if (cpl_error_get_code() != CPL_ERROR_NONE) {
320 engl_gain_linearity_delete(result);
321 result = NULL;
322 }
323
324 /* tidy up */
325
326 return result;
327}
328
329
330/*----------------------------------------------------------------------------*/
339/*----------------------------------------------------------------------------*/
340static
341double * engl_repack(const cpl_imagelist * lin_coeffs) {
342
343 const cpl_size fit_order = cpl_imagelist_get_size(lin_coeffs);
344 const cpl_size nx =
345 cpl_image_get_size_x(cpl_imagelist_get_const(lin_coeffs, 0));
346 const cpl_size ny =
347 cpl_image_get_size_y(cpl_imagelist_get_const(lin_coeffs, 0));
348 double * result = NULL;
349 int j=0;
350
351 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
352 cpl_ensure(cpl_image_get_type(cpl_imagelist_get_const(lin_coeffs, 0)) ==
353 CPL_TYPE_FLOAT, CPL_ERROR_UNSUPPORTED_MODE, NULL);
354
355 result = cpl_malloc(fit_order * nx * ny * sizeof(*result));
356
357 /* set coeff[0]=0 to ensure curve goes through origin, otherwise
358 get oddities at low flux levels */
359 for (cpl_size ipos=0 ; ipos < nx * ny ; ipos++) {
360 const cpl_size ordered_pos = ipos * fit_order + j;
361 result[ordered_pos] = 0.0;
362 }
363 j++;
364
365 for (; j < fit_order; j++) {
366 const cpl_image * fit_coeff_image = cpl_imagelist_get_const(lin_coeffs,
367 j);
368 const float * fit_coeff_data = cpl_image_get_data_float_const(
369 fit_coeff_image);
370 for (cpl_size ipos=0 ; ipos < nx * ny ; ipos++) {
371 const cpl_size ordered_pos = ipos * fit_order + j;
372 result[ordered_pos] = fit_coeff_data[ipos];
373 }
374 }
375
376 return result;
377}
378