CR2RE Pipeline Reference Manual 1.6.8
cr2res_cal_detlin.c
1/*
2 * This file is part of the CR2RES Pipeline
3 * Copyright (C) 2002,2003 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26 -----------------------------------------------------------------------------*/
27
28#include <string.h>
29#include <cpl.h>
30
31#include "cr2res_utils.h"
32#include "cr2res_calib.h"
33#include "cr2res_detlin.h"
34#include "cr2res_pfits.h"
35#include "cr2res_trace.h"
36#include "cr2res_qc.h"
37#include "cr2res_dfs.h"
38#include "cr2res_bpm.h"
39#include "cr2res_io.h"
40
41/*-----------------------------------------------------------------------------
42 Define
43 -----------------------------------------------------------------------------*/
44
45#define RECIPE_STRING "cr2res_cal_detlin"
46
47/*-----------------------------------------------------------------------------
48 Plugin registration
49 -----------------------------------------------------------------------------*/
50
51int cpl_plugin_get_info(cpl_pluginlist * list);
52
53/*-----------------------------------------------------------------------------
54 Private function prototypes
55 -----------------------------------------------------------------------------*/
56 #ifdef CR2RES_UNUSED
57static int cr2res_cal_detlin_update(
58 cpl_image * new_bpm,
59 hdrl_imagelist * new_coeffs,
60 cpl_image ** global_bpm,
61 hdrl_imagelist ** global_coeffs);
62#endif
63static int cr2res_cal_detlin_update_simplified(
64 cpl_image * new_bpm,
65 hdrl_imagelist * new_coeffs,
66 cpl_image ** global_bpm,
67 hdrl_imagelist ** global_coeffs);
68static int cr2res_cal_detlin_compare(
69 const cpl_frame * frame1,
70 const cpl_frame * frame2) ;
71static int cr2res_cal_detlin_reduce(
72 const cpl_frameset * rawframes,
73 const cpl_frameset * darkframes,
74 int trace_degree,
75 int trace_min_cluster,
76 int trace_smooth_x,
77 int trace_smooth_y,
78 double trace_threshold,
79 int trace_opening,
80 int trace_collapse,
81 int reduce_det,
82 int plotx,
83 int ploty,
84 hdrl_imagelist ** coeffs,
85 cpl_image ** bpm,
86 cpl_propertylist ** ext_plist) ;
87static int cr2res_cal_detlin_create(cpl_plugin *);
88static int cr2res_cal_detlin_exec(cpl_plugin *);
89static int cr2res_cal_detlin_destroy(cpl_plugin *);
90static int cr2res_cal_detlin(cpl_frameset *, const cpl_parameterlist *);
91
92/*-----------------------------------------------------------------------------
93 Static variables
94 -----------------------------------------------------------------------------*/
95
96static char cr2res_cal_detlin_description[] = "\
97Detector Linearity \n\
98 Measure the pixels non-linearity \n\
99 \n\
100 Inputs \n\
101 raw.fits " CR2RES_DETLIN_DARK_RAW " [3 to n] \n\
102 or raw.fits " CR2RES_DETLIN_LAMP_RAW " [3 to n] \n\
103 \n\
104 Outputs \n\
105 cr2res_cal_detlin_coeffs.fits " CR2RES_CAL_DETLIN_COEFFS_PROCATG " \n\
106 cr2res_cal_detlin_bpm.fits " CR2RES_CAL_DETLIN_BPM_PROCATG " \n\
107 \n\
108 Algorithm \n\
109 group the input raw frames by different settings \n\
110 loop on groups g: \n\
111 loop on detectors d: \n\
112 cr2res_cal_detlin_reduce() computes bpm(g, d) and coeffs(g, d) \n\
113 fill global_bpm(d) with bpm(g, d) \n\
114 fill global_coeffs(d) with coeffs(g, d) \n\
115 \n\
116 if (--single_settings) \n\
117 save bpm(g) file \n\
118 save coeffs(g) file \n\
119 save global_bpm file \n\
120 save global_coeffs file \n\
121 \n\
122 cr2res_cal_detlin_reduce() \n\
123 load input imlist and dits \n\
124 compute the traces (from 1. image, or collapsed if --trace_collapse)\n\
125 use cr2res_trace(--trace_smooth, --trace_degree, \n\
126 --trace_min_cluster, --trace_opening) \n\
127 loop on the detector pixels pix: \n\
128 if the pixel is within a trace: \n\
129 cr2res_detlin_compute() computes polynomial(pix) and errors(pix)\n\
130 use the coeffs for the bpm computation \n\
131 set the bad pixel coefficients as NaN \n\
132 store the qc parameters in the returned property list \n\
133 \n\
134 Library Functions used \n\
135 cr2res_trace() \n\
136 cr2res_detlin_compute() \n\
137 cr2res_qc_detlin_gain() \n\
138 cr2res_qc_detlin_median() \n\
139 cr2res_qc_detlin_min_max_level() \n\
140 cr2res_io_save_BPM() \n\
141 cr2res_io_save_DETLIN_COEFFS() \n\
142" ;
143
144/*-----------------------------------------------------------------------------
145 Function code
146 -----------------------------------------------------------------------------*/
147
148/*----------------------------------------------------------------------------*/
158/*----------------------------------------------------------------------------*/
159int cpl_plugin_get_info(cpl_pluginlist * list)
160{
161 cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
162 cpl_plugin * plugin = &recipe->interface;
163
164 if (cpl_plugin_init(plugin,
165 CPL_PLUGIN_API,
166 CR2RES_BINARY_VERSION,
167 CPL_PLUGIN_TYPE_RECIPE,
168 RECIPE_STRING,
169 "Detector Linearity recipe",
170 cr2res_cal_detlin_description,
171 CR2RES_PIPELINE_AUTHORS,
172 PACKAGE_BUGREPORT,
174 cr2res_cal_detlin_create,
175 cr2res_cal_detlin_exec,
176 cr2res_cal_detlin_destroy)) {
177 cpl_msg_error(cpl_func, "Plugin initialization failed");
178 (void)cpl_error_set_where(cpl_func);
179 return 1;
180 }
181
182 if (cpl_pluginlist_append(list, plugin)) {
183 cpl_msg_error(cpl_func, "Error adding plugin to list");
184 (void)cpl_error_set_where(cpl_func);
185 return 1;
186 }
187
188 return 0;
189}
190
191/*----------------------------------------------------------------------------*/
199/*----------------------------------------------------------------------------*/
200static int cr2res_cal_detlin_create(cpl_plugin * plugin)
201{
202 cpl_recipe * recipe ;
203 cpl_parameter * p ;
204 char * tmpstring;
205
206 /* Check that the plugin is part of a valid recipe */
207 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
208 recipe = (cpl_recipe *)plugin;
209 else
210 return -1;
211
212 /* Create the parameters list in the cpl_recipe object */
213 recipe->parameters = cpl_parameterlist_new();
214
215 /* Fill the parameters list */
216 tmpstring = cpl_sprintf("BPM threshold, max %% non-linear at %d ADU",
217 CR2RES_NONLIN_LEVEL);
218 p = cpl_parameter_new_value("cr2res.cr2res_cal_detlin.bpm_thresh",
219 CPL_TYPE_DOUBLE, tmpstring, "cr2res.cr2res_cal_detlin", 15.0);
220 cpl_free(tmpstring);
221 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "bpm_thresh");
222 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
223 cpl_parameterlist_append(recipe->parameters, p);
224
225 p = cpl_parameter_new_value("cr2res.cr2res_cal_detlin.trace_degree",
226 CPL_TYPE_INT, "polynomial degree for the fit to the orders",
227 "cr2res.cr2res_cal_detlin", 2);
228 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "trace_degree");
229 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
230 cpl_parameterlist_append(recipe->parameters, p);
231
232 p = cpl_parameter_new_value("cr2res.cr2res_cal_detlin.trace_min_cluster",
233 CPL_TYPE_INT, "size in pixels of the smallest allowed cluster",
234 "cr2res.cr2res_cal_detlin", 5000);
235 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "trace_min_cluster");
236 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
237 cpl_parameterlist_append(recipe->parameters, p);
238
239 p = cpl_parameter_new_value("cr2res.cr2res_cal_detlin.trace_smooth_x",
240 CPL_TYPE_INT, "Length of the smoothing kernel in x",
241 "cr2res.cr2res_cal_detlin", 111);
242 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "trace_smooth_x");
243 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
244 cpl_parameterlist_append(recipe->parameters, p);
245
246 p = cpl_parameter_new_value("cr2res.cr2res_cal_detlin.trace_smooth_y",
247 CPL_TYPE_INT, "Length of the smoothing kernel in y",
248 "cr2res.cr2res_cal_detlin", 480);
249 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "trace_smooth_y");
250 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
251 cpl_parameterlist_append(recipe->parameters, p);
252
253 p = cpl_parameter_new_value("cr2res.cr2res_cal_detlin.trace_threshold",
254 CPL_TYPE_DOUBLE, "Detection Threshold",
255 "cr2res.cr2res_cal_detlin", 1.0);
256 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "trace_threshold");
257 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
258 cpl_parameterlist_append(recipe->parameters, p);
259
260 p = cpl_parameter_new_value("cr2res.cr2res_cal_detlin.trace_opening",
261 CPL_TYPE_BOOL, "Use a morphological opening to rejoin clusters",
262 "cr2res.cr2res_cal_detlin", TRUE);
263 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "trace_opening");
264 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
265 cpl_parameterlist_append(recipe->parameters, p);
266
267 p = cpl_parameter_new_value("cr2res.cr2res_cal_detlin.single_settings",
268 CPL_TYPE_BOOL, "Create the products for each setting",
269 "cr2res.cr2res_cal_detlin", FALSE);
270 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "single_settings");
271 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
272 cpl_parameterlist_append(recipe->parameters, p);
273
274 p = cpl_parameter_new_value("cr2res.cr2res_cal_detlin.trace_collapse",
275 CPL_TYPE_BOOL, "Collapse the input frames for the trace analysis",
276 "cr2res.cr2res_cal_detlin", TRUE);
277 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "trace_collapse");
278 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
279 cpl_parameterlist_append(recipe->parameters, p);
280
281 p = cpl_parameter_new_value("cr2res.cr2res_cal_detlin.detector",
282 CPL_TYPE_INT, "Only reduce the specified detector",
283 "cr2res.cr2res_cal_detlin", 0);
284 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "detector");
285 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
286 cpl_parameterlist_append(recipe->parameters, p);
287
288 p = cpl_parameter_new_value("cr2res.cr2res_cal_detlin.plot_x",
289 CPL_TYPE_INT, "X position for the plot",
290 "cr2res.cr2res_cal_detlin", 0);
291 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "plot_x");
292 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
293 cpl_parameterlist_append(recipe->parameters, p);
294
295 p = cpl_parameter_new_value("cr2res.cr2res_cal_detlin.plot_y",
296 CPL_TYPE_INT, "Y position for the plot",
297 "cr2res.cr2res_cal_detlin", 0);
298 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "plot_y");
299 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
300 cpl_parameterlist_append(recipe->parameters, p);
301
302 return 0;
303}
304
305/*----------------------------------------------------------------------------*/
311/*----------------------------------------------------------------------------*/
312static int cr2res_cal_detlin_exec(cpl_plugin * plugin)
313{
314 cpl_recipe *recipe;
315
316 /* Get the recipe out of the plugin */
317 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
318 recipe = (cpl_recipe *)plugin;
319 else return -1;
320
321 return cr2res_cal_detlin(recipe->frames, recipe->parameters);
322}
323
324/*----------------------------------------------------------------------------*/
330/*----------------------------------------------------------------------------*/
331static int cr2res_cal_detlin_destroy(cpl_plugin * plugin)
332{
333 cpl_recipe *recipe;
334
335 /* Get the recipe out of the plugin */
336 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
337 recipe = (cpl_recipe *)plugin;
338 else return -1 ;
339
340 cpl_parameterlist_delete(recipe->parameters);
341 return 0 ;
342}
343
344/*----------------------------------------------------------------------------*/
351/*----------------------------------------------------------------------------*/
352static int cr2res_cal_detlin(
353 cpl_frameset * frameset,
354 const cpl_parameterlist * parlist)
355{
356 const cpl_parameter * param ;
357 int trace_degree, trace_min_cluster, trace_collapse,
358 trace_opening, single_settings, reduce_det,
359 trace_smooth_x, trace_smooth_y, plot_x, plot_y ;
360 double bpm_thresh, trace_threshold;
361 double qc_median, qc_min_level, qc_max_level;
362 cpl_size qc_nb_bad;
363 cpl_frameset * rawframes ;
364 cpl_frameset * darkframes ;
365 cpl_size * labels ;
366 cpl_size nlabels ;
367 hdrl_imagelist * coeffs_merged[CR2RES_NB_DETECTORS] ;
368 cpl_image * bpm_merged[CR2RES_NB_DETECTORS] ;
369 cpl_propertylist * ext_plist_merged[CR2RES_NB_DETECTORS] ;
370 hdrl_imagelist * coeffs[CR2RES_NB_DETECTORS] ;
371 cpl_image * bpm[CR2RES_NB_DETECTORS] ;
372 cpl_propertylist * ext_plist[CR2RES_NB_DETECTORS] ;
373 char * out_file;
374 int l, det_nr;
375 cpl_mask * cur_mask;
376 cpl_propertylist * qc_main ;
377 double meda, medb, medc, medq ;
378
379 /* Initialise */
380
381 /* RETRIEVE INPUT PARAMETERS */
382 param = cpl_parameterlist_find_const(parlist,
383 "cr2res.cr2res_cal_detlin.bpm_thresh");
384 bpm_thresh = cpl_parameter_get_double(param);
385 param = cpl_parameterlist_find_const(parlist,
386 "cr2res.cr2res_cal_detlin.trace_degree");
387 trace_degree = cpl_parameter_get_int(param);
388 param = cpl_parameterlist_find_const(parlist,
389 "cr2res.cr2res_cal_detlin.trace_min_cluster");
390 trace_min_cluster = cpl_parameter_get_int(param);
391 param = cpl_parameterlist_find_const(parlist,
392 "cr2res.cr2res_cal_detlin.trace_smooth_x");
393 trace_smooth_x = cpl_parameter_get_int(param);
394 param = cpl_parameterlist_find_const(parlist,
395 "cr2res.cr2res_cal_detlin.trace_smooth_y");
396 trace_smooth_y = cpl_parameter_get_int(param);
397 param = cpl_parameterlist_find_const(parlist,
398 "cr2res.cr2res_cal_detlin.trace_threshold");
399 trace_threshold = cpl_parameter_get_double(param);
400 param = cpl_parameterlist_find_const(parlist,
401 "cr2res.cr2res_cal_detlin.trace_opening");
402 trace_opening = cpl_parameter_get_bool(param);
403 param = cpl_parameterlist_find_const(parlist,
404 "cr2res.cr2res_cal_detlin.single_settings");
405 single_settings = cpl_parameter_get_bool(param);
406 param = cpl_parameterlist_find_const(parlist,
407 "cr2res.cr2res_cal_detlin.trace_collapse");
408 trace_collapse = cpl_parameter_get_bool(param);
409 param = cpl_parameterlist_find_const(parlist,
410 "cr2res.cr2res_cal_detlin.detector");
411 reduce_det = cpl_parameter_get_int(param);
412 param = cpl_parameterlist_find_const(parlist,
413 "cr2res.cr2res_cal_detlin.plot_x");
414 plot_x = cpl_parameter_get_int(param);
415 param = cpl_parameterlist_find_const(parlist,
416 "cr2res.cr2res_cal_detlin.plot_y");
417 plot_y = cpl_parameter_get_int(param);
418
419 /* Identify the RAW and CALIB frames in the input frameset */
420 if (cr2res_dfs_set_groups(frameset)) {
421 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
422 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
423 return -1 ;
424 }
425
426 /* Get Calibration frames */
427
428 /* Extract RAW frames */
429 rawframes = cr2res_extract_frameset(frameset, CR2RES_DETLIN_LAMP_RAW) ;
430 if (rawframes==NULL || cpl_frameset_get_size(rawframes) <= 0) {
431 cpl_msg_error(__func__, "Cannot find any RAW file") ;
432 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND) ;
433 return -1 ;
434 }
435 /* Extract DARK frames */
436 darkframes = cr2res_extract_frameset(frameset, CR2RES_DETLIN_DARK_RAW) ;
437
438 /* Labelise the raw frames with the different settings*/
439 if ((labels = cpl_frameset_labelise(rawframes, cr2res_cal_detlin_compare,
440 &nlabels)) == NULL) {
441 cpl_msg_error(__func__, "Cannot labelise input frames") ;
442 cpl_frameset_delete(rawframes) ;
443 if (darkframes!= NULL) cpl_frameset_delete(darkframes) ;
444 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
445 return -1 ;
446 }
447
448 /* Initialise */
449 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
450 coeffs_merged[det_nr-1] = NULL ;
451 bpm_merged[det_nr-1] = NULL ;
452 ext_plist_merged[det_nr-1] = NULL ;
453 }
454
455 /* Loop on the settings */
456 for (l=0 ; l<(int)nlabels ; l++) {
457
458 cpl_frameset * raw_one ;
459 char * setting_id ;
460 cpl_propertylist * plist ;
461 /* Get the frames for the current setting */
462 raw_one = cpl_frameset_extract(rawframes, labels, (cpl_size)l) ;
463
464 /* Get the current setting */
465 plist = cpl_propertylist_load(cpl_frame_get_filename(
466 cpl_frameset_get_position(raw_one, 0)), 0) ;
467 setting_id = cpl_strdup(cr2res_pfits_get_wlen_id(plist)) ;
468 cr2res_format_setting(setting_id) ;
469 cpl_propertylist_delete(plist) ;
470
471 cpl_msg_info(__func__, "Process SETTING %s", setting_id) ;
472 cpl_msg_indent_more() ;
473
474
475
476
477 /* Loop on the detectors */
478 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
479 cpl_msg_info(__func__, "Process Detector %d", det_nr) ;
480
481 /* Initialise */
482 coeffs[det_nr-1] = NULL ;
483 bpm[det_nr-1] = NULL ;
484 ext_plist[det_nr-1] = NULL ;
485
486 /* Compute only one detector */
487 if (reduce_det != 0 && det_nr != reduce_det) continue ;
488
489
490 /* Call the reduction function */
491 cpl_msg_indent_more() ;
492 if (cr2res_cal_detlin_reduce(raw_one, darkframes,
493 trace_degree, trace_min_cluster, trace_smooth_x,
494 trace_smooth_y, trace_threshold, trace_opening,
495 trace_collapse, det_nr, plot_x, plot_y,
496 &(coeffs[det_nr-1]),
497 &(bpm[det_nr-1]),
498 &(ext_plist[det_nr-1])) == -1) {
499 cpl_msg_warning(__func__,
500 "Failed to reduce SETTING %s / det %d",
501 setting_id, det_nr);
502 cpl_error_reset() ;
503 }
504 cpl_msg_indent_less() ;
505
506
507 /*
508 if (coeffs[det_nr-1] != NULL)
509 hdrl_imagelist_delete(coeffs[det_nr-1]) ;
510 if (bpm[det_nr-1] != NULL)
511 cpl_image_delete(bpm[det_nr-1]) ;
512 if (ext_plist[det_nr-1] != NULL)
513 cpl_propertylist_delete(ext_plist[det_nr-1]) ;
514 cpl_free(setting_id) ;
515 cpl_frameset_delete(rawframes) ;
516 cpl_frameset_delete(raw_one) ;
517 if (darkframes!= NULL) cpl_frameset_delete(darkframes) ;
518 cpl_free(labels);
519 return 0 ;
520 */
521
522 /* Merge the products */
523 if (ext_plist[det_nr-1] != NULL && coeffs[det_nr-1] != NULL
524 && bpm[det_nr-1] != NULL) {
525 /* Take the first header as it is */
526 if (ext_plist_merged[det_nr-1] == NULL) {
527 ext_plist_merged[det_nr-1] =
528 cpl_propertylist_duplicate(ext_plist[det_nr-1]) ;
529 }
530
531 /* Merge */
532 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
533 cpl_image_save(
535 hdrl_imagelist_get(coeffs[det_nr-1], 0)),
536 "debug_coeffs_before_merge.fits",
537 CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
538 }
539
540 cr2res_cal_detlin_update_simplified(bpm[det_nr - 1],
541 coeffs[det_nr - 1], &bpm_merged[det_nr - 1],
542 &coeffs_merged[det_nr - 1]);
543
544 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
545 cpl_image_save(
547 hdrl_imagelist_get(coeffs_merged[det_nr-1], 0)),
548 "debug_coeffs_after_merge.fits",
549 CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
550 }
551 }
552 }
553
554 /* Save the products */
555 if (single_settings) {
556 /* BPM */
557 out_file = cpl_sprintf("%s_%s_bpm.fits", RECIPE_STRING,
558 setting_id) ;
559
560 /* Save only the used RAW ? : raw_one instead of 2nd frameset */
561 /* Beware that the calibration PRO RECi CAL will be missing */
562
563 cr2res_io_save_BPM(out_file, frameset, frameset, parlist, bpm,
564 NULL, ext_plist, CR2RES_CAL_DETLIN_BPM_PROCATG,
565 RECIPE_STRING) ;
566 cpl_free(out_file);
567
568 /* COEFFS */
569 out_file = cpl_sprintf("%s_%s_coeffs.fits", RECIPE_STRING,
570 setting_id) ;
571 /* Save only the used RAW ? : raw_one instead of 2nd frameset */
572 /* Beware that the calibration PRO RECi CAL will be missing */
573
574 cr2res_io_save_DETLIN_COEFFS(out_file, frameset, frameset, parlist,
575 coeffs, NULL, ext_plist, CR2RES_CAL_DETLIN_COEFFS_PROCATG,
576 RECIPE_STRING) ;
577 cpl_free(out_file);
578 }
579
580 /* Free */
581 cpl_frameset_delete(raw_one) ;
582 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
583 if (coeffs[det_nr-1] != NULL)
584 hdrl_imagelist_delete(coeffs[det_nr-1]) ;
585 if (bpm[det_nr-1] != NULL)
586 cpl_image_delete(bpm[det_nr-1]) ;
587 if (ext_plist[det_nr-1] != NULL)
588 cpl_propertylist_delete(ext_plist[det_nr-1]) ;
589 }
590 cpl_free(setting_id) ;
591 cpl_msg_indent_less() ;
592 }
593 cpl_free(labels);
594
595 for (det_nr = 1; det_nr <= CR2RES_NB_DETECTORS; det_nr++) {
596 if (reduce_det != 0 && det_nr != reduce_det)
597 continue ;
598
599 // Complete the merging
600 // This completes the weighted mean as described in
601 // cr2res_cal_detlin_update
602 // TODO - Why not in the merging function ?? -> REVIEW !!!
603 /*
604 for (i=0; i < hdrl_imagelist_get_size(coeffs_merged[det_nr - 1]); i++) {
605 img = hdrl_imagelist_get(coeffs_merged[det_nr - 1], i);
606 for (x = 0; x < hdrl_image_get_size_x(img); x++) {
607 for (y = 0; y < hdrl_image_get_size_y(img); y++) {
608 pixel = hdrl_image_get_pixel(img, x + 1, y + 1, NULL);
609 pixel.data /= pixel.error;
610 pixel.error = sqrt(1.0 / pixel.error);
611 hdrl_image_set_pixel(img, x + 1, y + 1, pixel);
612 }
613 }
614 hdrl_image_reject_value(img, CPL_VALUE_NAN);
615 }
616 */
617
618 /* Compute the QC parameters */
619 cpl_msg_info(__func__, "BPM detection & QCs") ;
620 qc_median = cr2res_qc_detlin(coeffs_merged[det_nr -1],
621 bpm_thresh, &cur_mask, &qc_min_level, &qc_max_level) ;
622 if (qc_median == -1.0) continue;
623
624 if (cpl_msg_get_level() == CPL_MSG_DEBUG)
625 cpl_mask_save( cur_mask, "debug_qcmask.fits", NULL, CPL_IO_CREATE);
626
627 /* Apply mask */
628 cr2res_bpm_add_mask(bpm_merged[det_nr -1], cur_mask, CR2RES_BPM_DETLIN);
629 qc_nb_bad = cpl_mask_count(cur_mask);
630 cpl_mask_delete(cur_mask);
631
632 meda = medb = medc = medq = 0.0 ;
633 cr2res_qc_detlin_stat(coeffs_merged[det_nr -1], &meda,
634 &medb, &medc, &medq) ;
635
636 /* Store the QC parameters in the plist */
637 cpl_propertylist_append_double(ext_plist_merged[det_nr-1],
638 CR2RES_HEADER_QC_DETLIN_MEDA, meda) ;
639 cpl_propertylist_append_double(ext_plist_merged[det_nr-1],
640 CR2RES_HEADER_QC_DETLIN_MEDB, medb) ;
641 cpl_propertylist_append_double(ext_plist_merged[det_nr-1],
642 CR2RES_HEADER_QC_DETLIN_MEDC, medc) ;
643 cpl_propertylist_append_double(ext_plist_merged[det_nr-1],
644 CR2RES_HEADER_QC_DETLIN_MEDQ, medq) ;
645 cpl_propertylist_append_int(ext_plist_merged[det_nr-1],
646 CR2RES_HEADER_QC_DETLIN_NBAD, qc_nb_bad) ;
647 cpl_propertylist_append_double(ext_plist_merged[det_nr-1],
648 CR2RES_HEADER_QC_DETLIN_MEDIAN, qc_median) ;
649 cpl_propertylist_append_double(ext_plist_merged[det_nr-1],
650 CR2RES_HEADER_QC_DETLIN_MINLEVEL, qc_min_level) ;
651 cpl_propertylist_append_double(ext_plist_merged[det_nr-1],
652 CR2RES_HEADER_QC_DETLIN_MAXLEVEL, qc_max_level) ;
653
654 } // End loop on detectors
655
656 /* Compute Global QCs (primary header) */
657 qc_main = NULL ;
658 if (reduce_det == 0) {
659
660 cpl_vector * qc_nbfailed,
661 * qc_nbsuccess,
662 * qc_nbad,
663 * qc_med,
664 * qc_min,
665 * qc_max,
666 * qc_meda,
667 * qc_medb,
668 * qc_medc,
669 * qc_medq ;
670
671 qc_nbfailed = cpl_vector_new(CR2RES_NB_DETECTORS) ;
672 qc_nbsuccess = cpl_vector_new(CR2RES_NB_DETECTORS) ;
673 qc_nbad = cpl_vector_new(CR2RES_NB_DETECTORS) ;
674 qc_med = cpl_vector_new(CR2RES_NB_DETECTORS) ;
675 qc_min = cpl_vector_new(CR2RES_NB_DETECTORS) ;
676 qc_max = cpl_vector_new(CR2RES_NB_DETECTORS) ;
677 qc_meda = cpl_vector_new(CR2RES_NB_DETECTORS) ;
678 qc_medb = cpl_vector_new(CR2RES_NB_DETECTORS) ;
679 qc_medc = cpl_vector_new(CR2RES_NB_DETECTORS) ;
680 qc_medq = cpl_vector_new(CR2RES_NB_DETECTORS) ;
681 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
682 cpl_vector_set(qc_nbfailed, det_nr-1,
683 (double)cpl_propertylist_get_int(ext_plist_merged[det_nr-1],
684 CR2RES_HEADER_QC_DETLIN_NBFAILED)) ;
685 cpl_vector_set(qc_nbsuccess, det_nr-1,
686 (double)cpl_propertylist_get_int(ext_plist_merged[det_nr-1],
687 CR2RES_HEADER_QC_DETLIN_NBSUCCESS)) ;
688 cpl_vector_set(qc_nbad, det_nr-1,
689 (double)cpl_propertylist_get_int(ext_plist_merged[det_nr-1],
690 CR2RES_HEADER_QC_DETLIN_NBAD)) ;
691 cpl_vector_set(qc_med, det_nr-1,
692 cpl_propertylist_get_double(ext_plist_merged[det_nr-1],
693 CR2RES_HEADER_QC_DETLIN_MEDIAN)) ;
694 cpl_vector_set(qc_min, det_nr-1,
695 cpl_propertylist_get_double(ext_plist_merged[det_nr-1],
696 CR2RES_HEADER_QC_DETLIN_MINLEVEL)) ;
697 cpl_vector_set(qc_max, det_nr-1,
698 cpl_propertylist_get_double(ext_plist_merged[det_nr-1],
699 CR2RES_HEADER_QC_DETLIN_MAXLEVEL)) ;
700 cpl_vector_set(qc_meda, det_nr-1,
701 cpl_propertylist_get_double(ext_plist_merged[det_nr-1],
702 CR2RES_HEADER_QC_DETLIN_MEDA)) ;
703 cpl_vector_set(qc_medb, det_nr-1,
704 cpl_propertylist_get_double(ext_plist_merged[det_nr-1],
705 CR2RES_HEADER_QC_DETLIN_MEDB)) ;
706 cpl_vector_set(qc_medc, det_nr-1,
707 cpl_propertylist_get_double(ext_plist_merged[det_nr-1],
708 CR2RES_HEADER_QC_DETLIN_MEDC)) ;
709 cpl_vector_set(qc_medq, det_nr-1,
710 cpl_propertylist_get_double(ext_plist_merged[det_nr-1],
711 CR2RES_HEADER_QC_DETLIN_MEDQ)) ;
712 }
713
714 qc_main = cpl_propertylist_new() ;
715 cpl_propertylist_append_double(qc_main,
716 CR2RES_HEADER_QC_DETLIN_NBFAILED_AVG,
717 cpl_vector_get_mean(qc_nbfailed)) ;
718 cpl_propertylist_append_double(qc_main,
719 CR2RES_HEADER_QC_DETLIN_NBFAILED_RMS,
720 cpl_vector_get_stdev(qc_nbfailed)) ;
721 cpl_propertylist_append_double(qc_main,
722 CR2RES_HEADER_QC_DETLIN_NBSUCCESS_AVG,
723 cpl_vector_get_mean(qc_nbsuccess)) ;
724 cpl_propertylist_append_double(qc_main,
725 CR2RES_HEADER_QC_DETLIN_NBSUCCESS_RMS,
726 cpl_vector_get_stdev(qc_nbsuccess)) ;
727 cpl_propertylist_append_double(qc_main,
728 CR2RES_HEADER_QC_DETLIN_NBAD_AVG,
729 cpl_vector_get_mean(qc_nbad)) ;
730 cpl_propertylist_append_double(qc_main,
731 CR2RES_HEADER_QC_DETLIN_NBAD_RMS,
732 cpl_vector_get_stdev(qc_nbad)) ;
733 cpl_propertylist_append_double(qc_main,
734 CR2RES_HEADER_QC_DETLIN_MEDIAN_AVG,
735 cpl_vector_get_mean(qc_med)) ;
736 cpl_propertylist_append_double(qc_main,
737 CR2RES_HEADER_QC_DETLIN_MEDIAN_RMS,
738 cpl_vector_get_stdev(qc_med)) ;
739 cpl_propertylist_append_double(qc_main,
740 CR2RES_HEADER_QC_DETLIN_MINLEVEL_AVG,
741 cpl_vector_get_mean(qc_min)) ;
742 cpl_propertylist_append_double(qc_main,
743 CR2RES_HEADER_QC_DETLIN_MINLEVEL_RMS,
744 cpl_vector_get_stdev(qc_min)) ;
745 cpl_propertylist_append_double(qc_main,
746 CR2RES_HEADER_QC_DETLIN_MAXLEVEL_AVG,
747 cpl_vector_get_mean(qc_max)) ;
748 cpl_propertylist_append_double(qc_main,
749 CR2RES_HEADER_QC_DETLIN_MAXLEVEL_RMS,
750 cpl_vector_get_stdev(qc_max)) ;
751 cpl_propertylist_append_double(qc_main,
752 CR2RES_HEADER_QC_DETLIN_MEDA_AVG,
753 cpl_vector_get_mean(qc_meda)) ;
754 cpl_propertylist_append_double(qc_main,
755 CR2RES_HEADER_QC_DETLIN_MEDA_RMS,
756 cpl_vector_get_stdev(qc_meda)) ;
757 cpl_propertylist_append_double(qc_main,
758 CR2RES_HEADER_QC_DETLIN_MEDB_AVG,
759 cpl_vector_get_mean(qc_medb)) ;
760 cpl_propertylist_append_double(qc_main,
761 CR2RES_HEADER_QC_DETLIN_MEDB_RMS,
762 cpl_vector_get_stdev(qc_medb)) ;
763 cpl_propertylist_append_double(qc_main,
764 CR2RES_HEADER_QC_DETLIN_MEDC_AVG,
765 cpl_vector_get_mean(qc_medc)) ;
766 cpl_propertylist_append_double(qc_main,
767 CR2RES_HEADER_QC_DETLIN_MEDC_RMS,
768 cpl_vector_get_stdev(qc_medc)) ;
769 cpl_propertylist_append_double(qc_main,
770 CR2RES_HEADER_QC_DETLIN_MEDQ_AVG,
771 cpl_vector_get_mean(qc_medq)) ;
772 cpl_propertylist_append_double(qc_main,
773 CR2RES_HEADER_QC_DETLIN_MEDQ_RMS,
774 cpl_vector_get_stdev(qc_medq)) ;
775 cpl_vector_delete(qc_nbfailed) ;
776 cpl_vector_delete(qc_nbsuccess) ;
777 cpl_vector_delete(qc_nbad) ;
778 cpl_vector_delete(qc_med) ;
779 cpl_vector_delete(qc_min) ;
780 cpl_vector_delete(qc_max) ;
781 cpl_vector_delete(qc_meda) ;
782 cpl_vector_delete(qc_medb) ;
783 cpl_vector_delete(qc_medc) ;
784 cpl_vector_delete(qc_medq) ;
785 }
786
787 /* Save the merged products */
788 /* BPM */
789 if(darkframes != NULL) cpl_frameset_join(rawframes, darkframes) ;
790 out_file = cpl_sprintf("%s_bpm.fits", RECIPE_STRING) ;
791 cr2res_io_save_BPM(out_file, frameset, rawframes, parlist, bpm_merged,
792 qc_main, ext_plist_merged, CR2RES_CAL_DETLIN_BPM_PROCATG,
793 RECIPE_STRING) ;
794 cpl_free(out_file);
795
796 /* COEFFS */
797 out_file = cpl_sprintf("%s_coeffs.fits", RECIPE_STRING) ;
798 cr2res_io_save_DETLIN_COEFFS(out_file, frameset, rawframes, parlist,
799 coeffs_merged, qc_main, ext_plist_merged,
800 CR2RES_CAL_DETLIN_COEFFS_PROCATG, RECIPE_STRING) ;
801 cpl_free(out_file);
802
803 if (qc_main != NULL) cpl_propertylist_delete(qc_main) ;
804 if (darkframes!= NULL) cpl_frameset_delete(darkframes) ;
805 cpl_frameset_delete(rawframes) ;
806 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
807 if (coeffs_merged[det_nr-1] != NULL)
808 hdrl_imagelist_delete(coeffs_merged[det_nr-1]) ;
809 if (bpm_merged[det_nr-1] != NULL)
810 cpl_image_delete(bpm_merged[det_nr-1]) ;
811 if (ext_plist_merged[det_nr-1] != NULL)
812 cpl_propertylist_delete(ext_plist_merged[det_nr-1]) ;
813 }
814
815 return (int)cpl_error_get_code();
816}
817
818/*----------------------------------------------------------------------------*/
836/*----------------------------------------------------------------------------*/
837static int cr2res_cal_detlin_reduce(
838 const cpl_frameset * rawframes,
839 const cpl_frameset * darkframes,
840 int trace_degree,
841 int trace_min_cluster,
842 int trace_smooth_x,
843 int trace_smooth_y,
844 double trace_threshold,
845 int trace_opening,
846 int trace_collapse,
847 int reduce_det,
848 int plotx,
849 int ploty,
850 hdrl_imagelist ** coeffs,
851 cpl_image ** bpm,
852 cpl_propertylist ** ext_plist)
853{
854 cpl_frameset * sorted_frames ;
855 const char * first_file ;
856 hdrl_imagelist * imlist ;
857 hdrl_image * cur_im ;
858 double * pcur_im ;
859 cpl_vector * dits ;
860 hdrl_image * collapsed ;
861 cpl_image * contrib ;
862 cpl_table * traces ;
863 cpl_imagelist * coeffs_loc ;
864 cpl_image * cur_coeffs ;
865 double * pcur_coeffs ;
866 cpl_imagelist * errors_loc ;
867 cpl_image * cur_errors ;
868 double * pcur_errors ;
869 cpl_propertylist * plist ;
870 cpl_image * bpm_loc ;
871 int * pbpm_loc ;
872 cpl_image * trace_image ;
873 int * pti ;
874 cpl_polynomial * fitted_poly ;
875 cpl_vector * fitted_errors ;
876 cpl_vector * fitvals ;
877 cpl_vector * aduPsec ;
878 cpl_mask * bpm_mask ;
879 int i, j, k, idx, ext_nr_data, nx, ny;
880 cpl_size max_degree, l ;
881 int qc_nbfailed, qc_nbsuccess ;
882
883 /* Check Inputs */
884 if (rawframes == NULL) return -1 ;
885
886 /* Sort the frames by increasing DIT */
887 if ((sorted_frames = cr2res_detlin_sort_frames(rawframes)) == NULL) {
888 cpl_msg_error(__func__, "Failed sorting frames by increasing DITs") ;
889 return -1 ;
890 }
891
892 /* Initialise */
893 max_degree = 2 ;
894
895 /* Get the Extension number */
896 first_file = cpl_frame_get_filename(
897 cpl_frameset_get_position_const(sorted_frames, 0)) ;
898 ext_nr_data = cr2res_io_get_ext_idx(first_file, reduce_det, 1) ;
899
900 /* Load the extension header for saving */
901 plist = cpl_propertylist_load(first_file, ext_nr_data) ;
902 if (plist == NULL) {
903 cpl_frameset_delete(sorted_frames) ;
904 return -1 ;
905 }
906
907 /* Load the image list */
908 if ((imlist = cr2res_io_load_image_list_from_set(sorted_frames,
909 reduce_det)) == NULL) {
910 cpl_propertylist_delete(plist);
911 cpl_frameset_delete(sorted_frames) ;
912 cpl_msg_error(__func__, "Failed to Load the images") ;
913 return -1 ;
914 }
915
916 /* Apply the dark correction */
917 if (darkframes != NULL &&
918 cpl_frameset_get_size(darkframes)==cpl_frameset_get_size(rawframes)) {
919
920 cpl_frameset * sorted_darkframes ;
921 /* Sort the frames by increasing DIT */
922 if ((sorted_darkframes=cr2res_detlin_sort_frames(darkframes)) == NULL) {
923 cpl_msg_warning(__func__,
924 "Failed sorting dark frames by increasing DITs - skip") ;
925 } else {
926
927 hdrl_imagelist * darklist ;
928 /* Load the image list */
929 if ((darklist=cr2res_io_load_image_list_from_set(sorted_darkframes,
930 reduce_det)) == NULL) {
931 cpl_msg_warning(__func__, "Failed to Load the darks - skip") ;
932 } else {
933 /* Apply correction */
934 if (hdrl_imagelist_sub_imagelist(imlist, darklist)) {
935 cpl_msg_warning(__func__,
936 "Failed to Subtract the darks - skip") ;
937 cpl_error_reset() ;
938 }
939 hdrl_imagelist_delete(darklist) ;
940 cpl_frameset_delete(sorted_darkframes);
941 }
942 }
943 }
944
945 /* Load the DITs */
946 if ((dits = cr2res_io_read_dits(sorted_frames)) == NULL) {
947 hdrl_imagelist_delete(imlist) ;
948 cpl_propertylist_delete(plist);
949 cpl_frameset_delete(sorted_frames) ;
950 cpl_msg_error(__func__, "Failed to Load the DIT values") ;
951 return -1 ;
952 }
953 cpl_frameset_delete(sorted_frames) ;
954
955/*
956 hdrl_imagelist_delete(imlist) ;
957 cpl_vector_delete(dits);
958 cpl_propertylist_delete(plist);
959 return -1 ;
960*/
961
962 /* Collapse all input images for the traces detection (only if wished) */
963 if (trace_collapse) {
964 cpl_msg_info(__func__, "Collapse the input images") ;
965 cpl_msg_indent_more() ;
966 if (hdrl_imagelist_collapse_mean(imlist, &collapsed, &contrib) !=
967 CPL_ERROR_NONE) {
968 cpl_msg_error(__func__, "Failed to Collapse") ;
969 cpl_propertylist_delete(plist);
970 hdrl_imagelist_delete(imlist) ;
971 cpl_vector_delete(dits);
972 cpl_msg_indent_less() ;
973 return -1 ;
974 }
975 cpl_msg_indent_less() ;
976 } else {
977 /* Only use the first image */
978 collapsed = hdrl_image_duplicate(hdrl_imagelist_get(imlist, 0)) ;
979 contrib = NULL ;
980 }
981
982/*
983 printf("-- %s\n", cpl_error_get_where()) ;
984 hdrl_image_delete(collapsed) ;
985 if (contrib != NULL) cpl_image_delete(contrib);
986
987 hdrl_imagelist_delete(imlist) ;
988 cpl_vector_delete(dits);
989 cpl_propertylist_delete(plist);
990
991 return -1 ;
992*/
993
994 /* Compute traces */
995 cpl_msg_info(__func__, "Compute the traces") ;
996 cpl_msg_indent_more() ;
997 nx = hdrl_image_get_size_x(collapsed) ;
998 ny = hdrl_image_get_size_y(collapsed) ;
999 if ((traces = cr2res_trace(hdrl_image_get_image(collapsed),
1000 trace_smooth_x, trace_smooth_y, trace_threshold,
1001 trace_opening, trace_degree, trace_min_cluster)) == NULL) {
1002 cpl_msg_error(__func__, "Failed compute the traces") ;
1003 hdrl_imagelist_delete(imlist) ;
1004 cpl_vector_delete(dits);
1005 cpl_propertylist_delete(plist);
1006 hdrl_image_delete(collapsed) ;
1007 cpl_image_delete(contrib);
1008 cpl_msg_indent_less() ;
1009 return -1 ;
1010 }
1011 hdrl_image_delete(collapsed) ;
1012 cpl_image_delete(contrib);
1013 cpl_msg_indent_less() ;
1014
1015 /* Allocate */
1016 bpm_loc = cpl_image_new(nx, ny, CPL_TYPE_INT) ;
1017 pbpm_loc = cpl_image_get_data_int(bpm_loc) ;
1018 coeffs_loc = cpl_imagelist_new() ;
1019 errors_loc = cpl_imagelist_new() ;
1020
1021 /* Initialise the coeffs cube */
1022 for (l=0 ; l<=max_degree ; l++) {
1023 cpl_imagelist_set(coeffs_loc, cpl_image_new(nx, ny,CPL_TYPE_DOUBLE),l) ;
1024 cpl_imagelist_set(errors_loc, cpl_image_new(nx, ny,CPL_TYPE_DOUBLE),l) ;
1025 }
1026
1027 /* Create the trace image */
1028 trace_image = cr2res_trace_gen_image(traces, nx, ny) ;
1029 pti = cpl_image_get_data_int(trace_image) ;
1030 cpl_table_delete(traces) ;
1031
1032 /* Loop over the traces and compute the non-linearity */
1033 cpl_msg_info(__func__, "Compute Non Linearity") ;
1034 cpl_msg_indent_more() ;
1035
1036 /* Loop on the traces pixels */
1037 qc_nbfailed = 0 ;
1038 qc_nbsuccess = 0 ;
1039 for (j=0 ; j<ny ; j++) {
1040 for (i=0 ; i<nx ; i++) {
1041 idx = i + j*nx ;
1042 if (pti[idx] > 0) {
1043 /* Prepare values to fit */
1044 fitvals = cpl_vector_new(cpl_vector_get_size(dits)) ;
1045 for (k=0 ; k<cpl_vector_get_size(dits) ; k++) {
1046 cur_im = hdrl_imagelist_get(imlist, k) ;
1047 pcur_im = cpl_image_get_data_double(
1048 hdrl_image_get_image(cur_im)) ;
1049 cpl_vector_set(fitvals, k, (float)(pcur_im[idx])) ;
1050 }
1051
1052 /* We are in a trace, let's compute the linearity */
1053 if (cr2res_detlin_compute(dits, fitvals, max_degree,
1054 &fitted_poly, &fitted_errors) == -1) {
1055 qc_nbfailed++ ;
1056 /* Store the null Coefficients in the output image list */
1057 pbpm_loc[idx] = CR2RES_BPM_DETLIN ;
1058 for (l=0 ; l<=max_degree ; l++) {
1059 cur_coeffs = cpl_imagelist_get(coeffs_loc, l) ;
1060 pcur_coeffs = cpl_image_get_data_double(cur_coeffs) ;
1061 pcur_coeffs[idx] = NAN ;
1062 cur_errors = cpl_imagelist_get(errors_loc, l) ;
1063 pcur_errors = cpl_image_get_data_double(cur_errors) ;
1064 pcur_errors[idx] = NAN ;
1065 }
1066 } else {
1067 qc_nbsuccess++ ;
1068
1069 /* Plot the values and the fit */
1070 if (plotx==i+1 && ploty==j+1) {
1071 aduPsec = cpl_vector_duplicate(fitvals);
1072 cpl_vector * fitvals_loc1=cpl_vector_duplicate(fitvals);
1073 cpl_vector_divide(aduPsec, dits);
1074 cpl_bivector * toplot_measure =
1075 cpl_bivector_wrap_vectors(fitvals_loc1,aduPsec) ;
1076
1077 cpl_vector * poly_eval = cr2res_polynomial_eval_vector(
1078 fitted_poly, fitvals_loc1) ;
1079 cpl_vector * fitvals_loc2=cpl_vector_duplicate(fitvals);
1080 cpl_bivector * toplot_fitted =
1081 cpl_bivector_wrap_vectors(fitvals_loc2, poly_eval) ;
1082 cpl_plot_bivector(
1083 "set grid;set xlabel 'ADU';set ylabel 'ADU/s';",
1084 "t 'Measured ADU/s' w lines", "", toplot_measure);
1085 cpl_plot_bivector(
1086 "set grid;set xlabel 'ADU';set ylabel 'Corr. fact';",
1087 "t 'Fit' w lines", "", toplot_fitted);
1088 cpl_bivector_delete(toplot_fitted) ;
1089 cpl_bivector_delete(toplot_measure) ;
1090 }
1091
1092 /* Store the Coefficients in the output image list */
1093 pbpm_loc[idx] = 0 ;
1094 for (l=0 ; l<=max_degree ; l++) {
1095 cur_coeffs = cpl_imagelist_get(coeffs_loc, l) ;
1096 pcur_coeffs = cpl_image_get_data_double(cur_coeffs) ;
1097 pcur_coeffs[idx] =
1098 cpl_polynomial_get_coeff(fitted_poly, &l) ;
1099 cur_errors = cpl_imagelist_get(errors_loc, l) ;
1100 pcur_errors = cpl_image_get_data_double(cur_errors) ;
1101
1102 /* Store error */
1103 if (fitted_errors != NULL) {
1104 pcur_errors[idx] =
1105 fabs(cpl_vector_get(fitted_errors, l));
1106 } else {
1107 pcur_errors[idx] = 0.0 ;
1108 }
1109 }
1110 if (fitted_errors != NULL) cpl_vector_delete(fitted_errors);
1111 cpl_polynomial_delete(fitted_poly) ;
1112 }
1113 cpl_vector_delete(fitvals) ;
1114 } else {
1115 /* Outside the orders */
1116 /* Set the values as NaNs */
1117 for (l=0 ; l<=max_degree ; l++) {
1118 cur_coeffs = cpl_imagelist_get(coeffs_loc, l) ;
1119 pcur_coeffs = cpl_image_get_data_double(cur_coeffs) ;
1120 pcur_coeffs[idx] = NAN ;
1121 cur_errors = cpl_imagelist_get(errors_loc, l) ;
1122 pcur_errors = cpl_image_get_data_double(cur_errors) ;
1123 pcur_errors[idx] = NAN ;
1124 }
1125 /* Set the BPM as bad */
1126 pbpm_loc[idx] = CR2RES_BPM_OUTOFORDER ;
1127 }
1128 }
1129 }
1130 cpl_msg_info(__func__, "%d pix success, %d failed",qc_nbsuccess,
1131 qc_nbfailed);
1132 cpl_msg_indent_less() ;
1133 cpl_image_delete(trace_image) ;
1134 hdrl_imagelist_delete(imlist) ;
1135 cpl_vector_delete(dits);
1136
1137 /* Reject the bad pixels in the image lists */
1138 /* Get Mask */
1139 bpm_mask = cpl_mask_threshold_image_create(bpm_loc,-0.5,0.5) ;
1140 cpl_mask_not(bpm_mask) ;
1141
1142 /* Set the Bad pixels in coeffs */
1143 for (l=0 ; l<=max_degree ; l++) {
1144 cur_coeffs = cpl_imagelist_get(coeffs_loc, l) ;
1145 cpl_image_reject_from_mask(cur_coeffs, bpm_mask) ;
1146 }
1147 cpl_mask_delete(bpm_mask);
1148
1149 /* Save the QC that make sense for each setting */
1150 /* Note that these get overwritten for each setting in final product */
1151 /* but remains in outputs with --save_settings */
1152 cpl_propertylist_append_int(plist, CR2RES_HEADER_QC_DETLIN_NBFAILED,
1153 qc_nbfailed) ;
1154 cpl_propertylist_append_int(plist, CR2RES_HEADER_QC_DETLIN_NBSUCCESS,
1155 qc_nbsuccess) ;
1156
1157 /* Return the results */
1158 *coeffs = hdrl_imagelist_create(coeffs_loc, errors_loc) ;
1159 cpl_imagelist_delete(coeffs_loc) ;
1160 cpl_imagelist_delete(errors_loc) ;
1161 *ext_plist = plist ;
1162 *bpm = bpm_loc ;
1163 return 0 ;
1164}
1165
1166/*----------------------------------------------------------------------------*/
1173/*----------------------------------------------------------------------------*/
1174static int cr2res_cal_detlin_compare(
1175 const cpl_frame * frame1,
1176 const cpl_frame * frame2)
1177{
1178 int comparison ;
1179 cpl_propertylist * plist1 ;
1180 cpl_propertylist * plist2 ;
1181 const char * sval1 ;
1182 const char * sval2 ;
1183
1184 /* Test entries */
1185 if (frame1==NULL || frame2==NULL) return -1 ;
1186
1187 /* Get property lists */
1188 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),0))==NULL){
1189 cpl_msg_error(__func__, "getting header from reference frame");
1190 return -1 ;
1191 }
1192 if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),0))==NULL){
1193 cpl_msg_error(__func__, "getting header from reference frame");
1194 cpl_propertylist_delete(plist1) ;
1195 return -1 ;
1196 }
1197
1198 /* Test status */
1199 if (cpl_error_get_code()) {
1200 cpl_propertylist_delete(plist1) ;
1201 cpl_propertylist_delete(plist2) ;
1202 return -1 ;
1203 }
1204
1205 comparison = 1 ;
1206
1207 /* Compare the SETTING used */
1208 sval1 = cr2res_pfits_get_wlen_id(plist1) ;
1209 sval2 = cr2res_pfits_get_wlen_id(plist2) ;
1210 if (cpl_error_get_code()) {
1211 cpl_msg_error(__func__, "Cannot get the reference wavelength");
1212 cpl_propertylist_delete(plist1) ;
1213 cpl_propertylist_delete(plist2) ;
1214 return -1 ;
1215 }
1216 if (strcmp(sval1, sval2)) comparison = 0 ;
1217
1218 cpl_propertylist_delete(plist1) ;
1219 cpl_propertylist_delete(plist2) ;
1220 return comparison ;
1221}
1222
1223/*----------------------------------------------------------------------------*/
1239/*----------------------------------------------------------------------------*/
1240static int cr2res_cal_detlin_update_simplified(
1241 cpl_image * new_bpm,
1242 hdrl_imagelist * new_coeffs,
1243 cpl_image ** global_bpm,
1244 hdrl_imagelist ** global_coeffs)
1245{
1246 cpl_size i, j, k, nx, ny, ni, idx;
1247 int * pglobal_bpm;
1248 int * pnew_bpm;
1249 hdrl_image * global_coeffs_ima;
1250 hdrl_image * new_coeffs_ima;
1251
1252 /* Check Inputs */
1253 if (new_bpm == NULL || new_coeffs == NULL) return 0;
1254
1255 /* Initialise */
1256 nx = cpl_image_get_size_x(new_bpm);
1257 ny = cpl_image_get_size_y(new_bpm);
1258 ni = hdrl_imagelist_get_size(new_coeffs);
1259
1260 if (*global_bpm != NULL && *global_coeffs != NULL){
1261 if (cpl_image_get_size_x(*global_bpm) != nx ||
1262 cpl_image_get_size_y(*global_bpm) != ny ||
1263 hdrl_imagelist_get_size(*global_coeffs) != ni) {
1264 return -1;
1265 }
1266 } else {
1267 /* First non-null solution encountered */
1268 *global_coeffs = hdrl_imagelist_duplicate(new_coeffs);
1269 *global_bpm = cpl_image_duplicate(new_bpm);
1270 return 0;
1271 }
1272
1273 pglobal_bpm = cpl_image_get_data_int(*global_bpm);
1274 pnew_bpm = cpl_image_get_data_int(new_bpm);
1275
1276 /* Loop on the pixels */
1277 for (j = 0; j < ny; j++) {
1278 for (i = 0; i < nx; i++) {
1279 idx = i + j * nx;
1280 // Only the new values exist
1281 if (pnew_bpm[idx] == 0) {
1282 pglobal_bpm[idx] = 0 ;
1283 for (k = 0; k < ni; k++) {
1284 global_coeffs_ima = hdrl_imagelist_get(*global_coeffs, k);
1285 new_coeffs_ima = hdrl_imagelist_get(new_coeffs, k);
1286 /*new_value = hdrl_image_get_pixel(new_coeffs_ima, i + 1,
1287 j + 1, NULL);*/
1288 hdrl_image_set_pixel(global_coeffs_ima, i + 1, j + 1,
1289 hdrl_image_get_pixel(new_coeffs_ima, i + 1, j + 1,
1290 NULL)) ;
1291 }
1292 } else if (pglobal_bpm[idx] == CR2RES_BPM_OUTOFORDER
1293 && pnew_bpm[idx] != CR2RES_BPM_OUTOFORDER) {
1294 // Update the BPM mask if it was Out of order
1295 // even if it still is a bad pixel
1296 pglobal_bpm[idx] = pnew_bpm[idx];
1297 }
1298 }
1299 }
1300 return 0 ;
1301}
1302#ifdef CR2RES_UNUSED
1303/*----------------------------------------------------------------------------*/
1319/*----------------------------------------------------------------------------*/
1320static int cr2res_cal_detlin_update(
1321 cpl_image * new_bpm,
1322 hdrl_imagelist * new_coeffs,
1323 cpl_image ** global_bpm,
1324 hdrl_imagelist ** global_coeffs)
1325{
1326 cpl_size i, j, k, nx, ny, ni, idx;
1327 int * pglobal_bpm;
1328 int * pnew_bpm;
1329 hdrl_image * global_coeffs_ima;
1330 hdrl_image * new_coeffs_ima;
1331 hdrl_value new_value, global_value, pixel;
1332 double tmp;
1333 cpl_size x, y;
1334
1335 /* Check Inputs */
1336 if (new_bpm == NULL || new_coeffs == NULL)
1337 return 0;
1338
1339 /* Initialise */
1340 nx = cpl_image_get_size_x(new_bpm);
1341 ny = cpl_image_get_size_y(new_bpm);
1342 ni = hdrl_imagelist_get_size(new_coeffs);
1343
1344 if (*global_bpm != NULL && *global_coeffs != NULL){
1345 if (cpl_image_get_size_x(*global_bpm) != nx ||
1346 cpl_image_get_size_y(*global_bpm) != ny ||
1347 hdrl_imagelist_get_size(*global_coeffs) != ni)
1348 {
1349 return -1;
1350 }
1351 } else {
1352 /* First non-null solution encountered */
1353 *global_coeffs = hdrl_imagelist_duplicate(new_coeffs);
1354 *global_bpm = cpl_image_duplicate(new_bpm);
1355
1356 for (i = 0; i < hdrl_imagelist_get_size(*global_coeffs); i++)
1357 {
1358 hdrl_image * img;
1359 img = hdrl_imagelist_get(*global_coeffs, i);
1360 for (x = 0; x < hdrl_image_get_size_x(img); x++)
1361 {
1362 for (y = 0; y < hdrl_image_get_size_y(img); y++)
1363 {
1364 pixel = hdrl_image_get_pixel(img, x + 1, y + 1, NULL);
1365 pixel.data /= pixel.error * pixel.error;
1366 pixel.error = 1 / (pixel.error * pixel.error);
1367 hdrl_image_set_pixel(img, x + 1, y + 1, pixel);
1368 }
1369 }
1370 }
1371 return 0;
1372 }
1373
1374
1375 pglobal_bpm = cpl_image_get_data_int(*global_bpm);
1376 pnew_bpm = cpl_image_get_data_int(new_bpm);
1377
1378 /* Loop on the pixels */
1379 for (j = 0; j < ny; j++)
1380 {
1381 for (i = 0; i < nx; i++)
1382 {
1383 idx = i + j * nx;
1384 // Only the new values exist
1385 if (pglobal_bpm[idx] != 0 && pnew_bpm[idx] == 0)
1386 {
1387 pglobal_bpm[idx] = pnew_bpm[idx];
1388 for (k = 0; k < ni; k++)
1389 {
1390 global_coeffs_ima = hdrl_imagelist_get(*global_coeffs, k);
1391 new_coeffs_ima = hdrl_imagelist_get(new_coeffs, k);
1392 new_value = hdrl_image_get_pixel(new_coeffs_ima, i + 1, j + 1, NULL);
1393
1394 tmp = new_value.error * new_value.error;
1395 new_value.data /= tmp;
1396 new_value.error = 1.0 / tmp;
1397
1398 hdrl_image_set_pixel(global_coeffs_ima, i + 1, j + 1,
1399 new_value);
1400 }
1401 }
1402 else if (pglobal_bpm[idx] == 0 && pnew_bpm[idx] == 0)
1403 {
1404 // Both old and new values exist
1405 /* Put the new value */
1406 pglobal_bpm[idx] = pnew_bpm[idx];
1407 for (k = 0; k < ni; k++)
1408 {
1409 global_coeffs_ima = hdrl_imagelist_get(*global_coeffs, k);
1410 new_coeffs_ima = hdrl_imagelist_get(new_coeffs, k);
1411 new_value = hdrl_image_get_pixel(new_coeffs_ima, i + 1, j + 1, NULL);
1412 global_value = hdrl_image_get_pixel(global_coeffs_ima, i + 1, j + 1, NULL);
1413
1414 tmp = new_value.error * new_value.error;
1415 global_value.data += new_value.data / tmp;
1416 global_value.error += 1.0 / tmp;
1417
1418 hdrl_image_set_pixel(global_coeffs_ima, i + 1, j + 1,
1419 global_value);
1420 }
1421 } else if(pglobal_bpm[idx] == CR2RES_BPM_OUTOFORDER
1422 && pnew_bpm[idx] != CR2RES_BPM_OUTOFORDER){
1423 // Update the BPM mask if it was Out of order
1424 // even if it still is a bad pixel
1425 pglobal_bpm[idx] = pnew_bpm[idx];
1426 }
1427 }
1428 }
1429 return 0 ;
1430}
1431#endif
int cr2res_bpm_add_mask(cpl_image *bpm_ima, cpl_mask *bpm, int bpm_code)
Add a mask to a BPM image with a dedicated code
Definition: cr2res_bpm.c:287
cpl_frameset * cr2res_detlin_sort_frames(const cpl_frameset *in)
Sort the frames by increasing DIT.
int cr2res_detlin_compute(const cpl_vector *dits, const cpl_vector *adus, cpl_size max_degree, cpl_polynomial **fitted, cpl_vector **error)
Fits the response of a given pixel to the illumination increase.
cpl_error_code cr2res_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: cr2res_dfs.c:53
cpl_vector * cr2res_io_read_dits(const cpl_frameset *in)
Get the DITS from a frame set.
Definition: cr2res_io.c:432
hdrl_imagelist * cr2res_io_load_image_list_from_set(const cpl_frameset *in, int detector)
Load an hdrl image list from an images frameset.
Definition: cr2res_io.c:808
int cr2res_io_save_DETLIN_COEFFS(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, hdrl_imagelist **coeffs, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a DETLIN COEFFS.
Definition: cr2res_io.c:1523
int cr2res_io_get_ext_idx(const char *filename, int detector, int data)
Get the wished extension number for a detector.
Definition: cr2res_io.c:644
int cr2res_io_save_BPM(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, cpl_image **bpms, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a BPM.
Definition: cr2res_io.c:1555
const char * cr2res_pfits_get_wlen_id(const cpl_propertylist *plist)
find out the Setting
Definition: cr2res_pfits.c:137
int cr2res_qc_detlin_stat(const hdrl_imagelist *hdrl_coeffs, double *meda, double *medb, double *medc, double *meda_err)
Computes the detlin coeffs statѕ
Definition: cr2res_qc.c:111
double cr2res_qc_detlin(const hdrl_imagelist *hdrl_coeffs, double bpm_thresh, cpl_mask **outmask, double *min_level, double *max_level)
Computes the detlin median non linearity.
Definition: cr2res_qc.c:156
cpl_image * cr2res_trace_gen_image(cpl_table *trace, int nx, int ny)
Make an image out of the trace solution.
Definition: cr2res_trace.c:362
cpl_table * cr2res_trace(cpl_image *ima, int smooth_x, int smooth_y, double threshold, int opening, int degree, int min_cluster)
Main function for running all parts of the trace algorithm.
Definition: cr2res_trace.c:163
int cr2res_format_setting(char *setting_id)
Format the setting.
Definition: cr2res_utils.c:152
cpl_vector * cr2res_polynomial_eval_vector(const cpl_polynomial *poly, const cpl_vector *vec)
Evaluate a polynomial on a vector.
cpl_frameset * cr2res_extract_frameset(const cpl_frameset *in, const char *tag)
Extract the frames with the given tag from a frameset.
const char * cr2res_get_license(void)
Get the pipeline copyright and license.
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
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
hdrl_image * hdrl_image_duplicate(const hdrl_image *himg)
copy hdrl_image
Definition: hdrl_image.c:391
cpl_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
Definition: hdrl_image.c:540
cpl_size hdrl_image_get_size_x(const hdrl_image *self)
return size of X dimension of image
Definition: hdrl_image.c:525
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:105
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
Definition: hdrl_image.c:379
cpl_error_code hdrl_imagelist_collapse_mean(const hdrl_imagelist *himlist, hdrl_image **out, cpl_image **contrib)
Mean collapsing of image list.
hdrl_imagelist * hdrl_imagelist_create(cpl_imagelist *imlist, cpl_imagelist *errlist)
Create an hdrl_imagelist out of 2 cpl_imagelist.
void hdrl_imagelist_delete(hdrl_imagelist *himlist)
Free all memory used by a hdrl_imagelist object including the images.
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the 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.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.