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"
37#include "cr2res_dfs.h"
38#include "cr2res_bpm.h"
45#define RECIPE_STRING "cr2res_cal_detlin"
51int cpl_plugin_get_info(cpl_pluginlist * list);
57static int cr2res_cal_detlin_update(
59 hdrl_imagelist * new_coeffs,
60 cpl_image ** global_bpm,
61 hdrl_imagelist ** global_coeffs);
63static int cr2res_cal_detlin_update_simplified(
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,
75 int trace_min_cluster,
78 double trace_threshold,
84 hdrl_imagelist ** coeffs,
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 *);
96static char cr2res_cal_detlin_description[] =
"\
98 Measure the pixels non-linearity \n\
101 raw.fits " CR2RES_DETLIN_DARK_RAW
" [3 to n] \n\
102 or raw.fits " CR2RES_DETLIN_LAMP_RAW
" [3 to n] \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\
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\
116 if (--single_settings) \n\
118 save coeffs(g) file \n\
119 save global_bpm file \n\
120 save global_coeffs file \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\
134 Library Functions used \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\
159int cpl_plugin_get_info(cpl_pluginlist * list)
161 cpl_recipe * recipe = cpl_calloc(1,
sizeof *recipe );
162 cpl_plugin * plugin = &recipe->interface;
164 if (cpl_plugin_init(plugin,
166 CR2RES_BINARY_VERSION,
167 CPL_PLUGIN_TYPE_RECIPE,
169 "Detector Linearity recipe",
170 cr2res_cal_detlin_description,
171 CR2RES_PIPELINE_AUTHORS,
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);
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);
200static int cr2res_cal_detlin_create(cpl_plugin * plugin)
202 cpl_recipe * recipe ;
207 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
208 recipe = (cpl_recipe *)plugin;
213 recipe->parameters = cpl_parameterlist_new();
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
312static int cr2res_cal_detlin_exec(cpl_plugin * plugin)
317 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
318 recipe = (cpl_recipe *)plugin;
321 return cr2res_cal_detlin(recipe->frames, recipe->parameters);
331static int cr2res_cal_detlin_destroy(cpl_plugin * plugin)
336 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
337 recipe = (cpl_recipe *)plugin;
340 cpl_parameterlist_delete(recipe->parameters);
352static int cr2res_cal_detlin(
353 cpl_frameset * frameset,
354 const cpl_parameterlist * parlist)
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;
363 cpl_frameset * rawframes ;
364 cpl_frameset * darkframes ;
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] ;
376 cpl_propertylist * qc_main ;
377 double meda, medb, medc, medq ;
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);
421 cpl_msg_error(__func__,
"Cannot identify RAW and CALIB frames") ;
422 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
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) ;
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) ;
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 ;
456 for (l=0 ; l<(int)nlabels ; l++) {
458 cpl_frameset * raw_one ;
460 cpl_propertylist * plist ;
462 raw_one = cpl_frameset_extract(rawframes, labels, (cpl_size)l) ;
465 plist = cpl_propertylist_load(cpl_frame_get_filename(
466 cpl_frameset_get_position(raw_one, 0)), 0) ;
469 cpl_propertylist_delete(plist) ;
471 cpl_msg_info(__func__,
"Process SETTING %s", setting_id) ;
472 cpl_msg_indent_more() ;
478 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
479 cpl_msg_info(__func__,
"Process Detector %d", det_nr) ;
482 coeffs[det_nr-1] = NULL ;
483 bpm[det_nr-1] = NULL ;
484 ext_plist[det_nr-1] = NULL ;
487 if (reduce_det != 0 && det_nr != reduce_det) continue ;
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,
498 &(ext_plist[det_nr-1])) == -1) {
499 cpl_msg_warning(__func__,
500 "Failed to reduce SETTING %s / det %d",
504 cpl_msg_indent_less() ;
523 if (ext_plist[det_nr-1] != NULL && coeffs[det_nr-1] != NULL
524 && bpm[det_nr-1] != NULL) {
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]) ;
532 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
536 "debug_coeffs_before_merge.fits",
537 CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
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]);
544 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
548 "debug_coeffs_after_merge.fits",
549 CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
555 if (single_settings) {
557 out_file = cpl_sprintf(
"%s_%s_bpm.fits", RECIPE_STRING,
564 NULL, ext_plist, CR2RES_CAL_DETLIN_BPM_PROCATG,
569 out_file = cpl_sprintf(
"%s_%s_coeffs.fits", RECIPE_STRING,
575 coeffs, NULL, ext_plist, CR2RES_CAL_DETLIN_COEFFS_PROCATG,
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)
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]) ;
590 cpl_free(setting_id) ;
591 cpl_msg_indent_less() ;
595 for (det_nr = 1; det_nr <= CR2RES_NB_DETECTORS; det_nr++) {
596 if (reduce_det != 0 && det_nr != reduce_det)
619 cpl_msg_info(__func__,
"BPM detection & QCs") ;
621 bpm_thresh, &cur_mask, &qc_min_level, &qc_max_level) ;
622 if (qc_median == -1.0)
continue;
624 if (cpl_msg_get_level() == CPL_MSG_DEBUG)
625 cpl_mask_save( cur_mask,
"debug_qcmask.fits", NULL, CPL_IO_CREATE);
629 qc_nb_bad = cpl_mask_count(cur_mask);
630 cpl_mask_delete(cur_mask);
632 meda = medb = medc = medq = 0.0 ;
634 &medb, &medc, &medq) ;
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) ;
658 if (reduce_det == 0) {
660 cpl_vector * qc_nbfailed,
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)) ;
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) ;
789 if(darkframes != NULL) cpl_frameset_join(rawframes, darkframes) ;
790 out_file = cpl_sprintf(
"%s_bpm.fits", RECIPE_STRING) ;
792 qc_main, ext_plist_merged, CR2RES_CAL_DETLIN_BPM_PROCATG,
797 out_file = cpl_sprintf(
"%s_coeffs.fits", RECIPE_STRING) ;
799 coeffs_merged, qc_main, ext_plist_merged,
800 CR2RES_CAL_DETLIN_COEFFS_PROCATG, RECIPE_STRING) ;
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)
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]) ;
815 return (
int)cpl_error_get_code();
837static int cr2res_cal_detlin_reduce(
838 const cpl_frameset * rawframes,
839 const cpl_frameset * darkframes,
841 int trace_min_cluster,
844 double trace_threshold,
850 hdrl_imagelist ** coeffs,
852 cpl_propertylist ** ext_plist)
854 cpl_frameset * sorted_frames ;
855 const char * first_file ;
856 hdrl_imagelist * imlist ;
857 hdrl_image * cur_im ;
860 hdrl_image * collapsed ;
861 cpl_image * contrib ;
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 ;
872 cpl_image * trace_image ;
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 ;
884 if (rawframes == NULL)
return -1 ;
888 cpl_msg_error(__func__,
"Failed sorting frames by increasing DITs") ;
896 first_file = cpl_frame_get_filename(
897 cpl_frameset_get_position_const(sorted_frames, 0)) ;
901 plist = cpl_propertylist_load(first_file, ext_nr_data) ;
903 cpl_frameset_delete(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") ;
917 if (darkframes != NULL &&
918 cpl_frameset_get_size(darkframes)==cpl_frameset_get_size(rawframes)) {
920 cpl_frameset * sorted_darkframes ;
923 cpl_msg_warning(__func__,
924 "Failed sorting dark frames by increasing DITs - skip") ;
927 hdrl_imagelist * darklist ;
930 reduce_det)) == NULL) {
931 cpl_msg_warning(__func__,
"Failed to Load the darks - skip") ;
935 cpl_msg_warning(__func__,
936 "Failed to Subtract the darks - skip") ;
940 cpl_frameset_delete(sorted_darkframes);
948 cpl_propertylist_delete(plist);
949 cpl_frameset_delete(sorted_frames) ;
950 cpl_msg_error(__func__,
"Failed to Load the DIT values") ;
953 cpl_frameset_delete(sorted_frames) ;
963 if (trace_collapse) {
964 cpl_msg_info(__func__,
"Collapse the input images") ;
965 cpl_msg_indent_more() ;
968 cpl_msg_error(__func__,
"Failed to Collapse") ;
969 cpl_propertylist_delete(plist);
971 cpl_vector_delete(dits);
972 cpl_msg_indent_less() ;
975 cpl_msg_indent_less() ;
995 cpl_msg_info(__func__,
"Compute the traces") ;
996 cpl_msg_indent_more() ;
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") ;
1004 cpl_vector_delete(dits);
1005 cpl_propertylist_delete(plist);
1007 cpl_image_delete(contrib);
1008 cpl_msg_indent_less() ;
1012 cpl_image_delete(contrib);
1013 cpl_msg_indent_less() ;
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() ;
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) ;
1029 pti = cpl_image_get_data_int(trace_image) ;
1030 cpl_table_delete(traces) ;
1033 cpl_msg_info(__func__,
"Compute Non Linearity") ;
1034 cpl_msg_indent_more() ;
1039 for (j=0 ; j<ny ; j++) {
1040 for (i=0 ; i<nx ; i++) {
1044 fitvals = cpl_vector_new(cpl_vector_get_size(dits)) ;
1045 for (k=0 ; k<cpl_vector_get_size(dits) ; k++) {
1047 pcur_im = cpl_image_get_data_double(
1049 cpl_vector_set(fitvals, k, (
float)(pcur_im[idx])) ;
1054 &fitted_poly, &fitted_errors) == -1) {
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 ;
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) ;
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) ;
1083 "set grid;set xlabel 'ADU';set ylabel 'ADU/s';",
1084 "t 'Measured ADU/s' w lines",
"", toplot_measure);
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) ;
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) ;
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) ;
1103 if (fitted_errors != NULL) {
1105 fabs(cpl_vector_get(fitted_errors, l));
1107 pcur_errors[idx] = 0.0 ;
1110 if (fitted_errors != NULL) cpl_vector_delete(fitted_errors);
1111 cpl_polynomial_delete(fitted_poly) ;
1113 cpl_vector_delete(fitvals) ;
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 ;
1126 pbpm_loc[idx] = CR2RES_BPM_OUTOFORDER ;
1130 cpl_msg_info(__func__,
"%d pix success, %d failed",qc_nbsuccess,
1132 cpl_msg_indent_less() ;
1133 cpl_image_delete(trace_image) ;
1135 cpl_vector_delete(dits);
1139 bpm_mask = cpl_mask_threshold_image_create(bpm_loc,-0.5,0.5) ;
1140 cpl_mask_not(bpm_mask) ;
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) ;
1147 cpl_mask_delete(bpm_mask);
1152 cpl_propertylist_append_int(plist, CR2RES_HEADER_QC_DETLIN_NBFAILED,
1154 cpl_propertylist_append_int(plist, CR2RES_HEADER_QC_DETLIN_NBSUCCESS,
1159 cpl_imagelist_delete(coeffs_loc) ;
1160 cpl_imagelist_delete(errors_loc) ;
1161 *ext_plist = plist ;
1174static int cr2res_cal_detlin_compare(
1175 const cpl_frame * frame1,
1176 const cpl_frame * frame2)
1179 cpl_propertylist * plist1 ;
1180 cpl_propertylist * plist2 ;
1181 const char * sval1 ;
1182 const char * sval2 ;
1185 if (frame1==NULL || frame2==NULL)
return -1 ;
1188 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),0))==NULL){
1189 cpl_msg_error(__func__,
"getting header from reference frame");
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) ;
1199 if (cpl_error_get_code()) {
1200 cpl_propertylist_delete(plist1) ;
1201 cpl_propertylist_delete(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) ;
1216 if (strcmp(sval1, sval2)) comparison = 0 ;
1218 cpl_propertylist_delete(plist1) ;
1219 cpl_propertylist_delete(plist2) ;
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)
1246 cpl_size i, j, k, nx, ny, ni, idx;
1249 hdrl_image * global_coeffs_ima;
1250 hdrl_image * new_coeffs_ima;
1253 if (new_bpm == NULL || new_coeffs == NULL)
return 0;
1256 nx = cpl_image_get_size_x(new_bpm);
1257 ny = cpl_image_get_size_y(new_bpm);
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 ||
1269 *global_bpm = cpl_image_duplicate(new_bpm);
1273 pglobal_bpm = cpl_image_get_data_int(*global_bpm);
1274 pnew_bpm = cpl_image_get_data_int(new_bpm);
1277 for (j = 0; j < ny; j++) {
1278 for (i = 0; i < nx; i++) {
1281 if (pnew_bpm[idx] == 0) {
1282 pglobal_bpm[idx] = 0 ;
1283 for (k = 0; k < ni; k++) {
1292 }
else if (pglobal_bpm[idx] == CR2RES_BPM_OUTOFORDER
1293 && pnew_bpm[idx] != CR2RES_BPM_OUTOFORDER) {
1296 pglobal_bpm[idx] = pnew_bpm[idx];
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)
1326 cpl_size i, j, k, nx, ny, ni, idx;
1329 hdrl_image * global_coeffs_ima;
1330 hdrl_image * new_coeffs_ima;
1331 hdrl_value new_value, global_value, pixel;
1336 if (new_bpm == NULL || new_coeffs == NULL)
1340 nx = cpl_image_get_size_x(new_bpm);
1341 ny = cpl_image_get_size_y(new_bpm);
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 ||
1354 *global_bpm = cpl_image_duplicate(new_bpm);
1365 pixel.data /= pixel.error * pixel.error;
1366 pixel.error = 1 / (pixel.error * pixel.error);
1375 pglobal_bpm = cpl_image_get_data_int(*global_bpm);
1376 pnew_bpm = cpl_image_get_data_int(new_bpm);
1379 for (j = 0; j < ny; j++)
1381 for (i = 0; i < nx; i++)
1385 if (pglobal_bpm[idx] != 0 && pnew_bpm[idx] == 0)
1387 pglobal_bpm[idx] = pnew_bpm[idx];
1388 for (k = 0; k < ni; k++)
1394 tmp = new_value.error * new_value.error;
1395 new_value.data /= tmp;
1396 new_value.error = 1.0 / tmp;
1402 else if (pglobal_bpm[idx] == 0 && pnew_bpm[idx] == 0)
1406 pglobal_bpm[idx] = pnew_bpm[idx];
1407 for (k = 0; k < ni; k++)
1414 tmp = new_value.error * new_value.error;
1415 global_value.data += new_value.data / tmp;
1416 global_value.error += 1.0 / tmp;
1421 }
else if(pglobal_bpm[idx] == CR2RES_BPM_OUTOFORDER
1422 && pnew_bpm[idx] != CR2RES_BPM_OUTOFORDER){
1425 pglobal_bpm[idx] = pnew_bpm[idx];
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
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.
cpl_vector * cr2res_io_read_dits(const cpl_frameset *in)
Get the DITS from a frame set.
hdrl_imagelist * cr2res_io_load_image_list_from_set(const cpl_frameset *in, int detector)
Load an hdrl image list from an images frameset.
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.
int cr2res_io_get_ext_idx(const char *filename, int detector, int data)
Get the wished extension number for a detector.
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.
const char * cr2res_pfits_get_wlen_id(const cpl_propertylist *plist)
find out the Setting
int cr2res_qc_detlin_stat(const hdrl_imagelist *hdrl_coeffs, double *meda, double *medb, double *medc, double *meda_err)
Computes the detlin coeffs statѕ
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.
cpl_image * cr2res_trace_gen_image(cpl_table *trace, int nx, int ny)
Make an image out of the trace solution.
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.
int cr2res_format_setting(char *setting_id)
Format the setting.
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
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
hdrl_image * hdrl_image_duplicate(const hdrl_image *himg)
copy hdrl_image
cpl_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
cpl_size hdrl_image_get_size_x(const hdrl_image *self)
return size of X dimension of image
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
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.