40#include "eris_utils.h"
44#include "detmon_utils.h"
45#include "detmon_lg_impl.h"
47#include "irplib_ksigma_clip.h"
48#include "irplib_utils.h"
49#include "irplib_hist.h"
61#ifdef DETMON_USE_DETECTOR_SHOTNOISE_MODEL
63detmon_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
64 const double ron, cpl_image ** ima_errs);
78typedef enum _FPN_METHOD FPN_METHOD;
118 cpl_boolean wholechip;
119 cpl_boolean autocorr;
120 cpl_boolean intermediate;
121 cpl_boolean collapse;
128 const char * pafname;
133 double lamp_stability;
136 int (* load_fset) (
const cpl_frameset *, cpl_type, cpl_imagelist *);
137 cpl_imagelist * (* load_fset_wrp) (
const cpl_frameset *, cpl_type, int);
138 FPN_METHOD fpn_method;
140 double saturation_limit;
141 double gain_threshold;
142 cpl_boolean split_coeffs;
153detmon_lg_retrieve_parlist(
const char *,
154 const char *,
const cpl_parameterlist *,
159detmon_lg_split_onoff(
const cpl_frameset *,
162 const char *,
const char * );
165detmon_lg_reduce(
const cpl_frameset *,
166 const cpl_frameset *,
167 int* index_on,
int* index_off,
168 double* exptime_on,
double* exptime_off,
169 int *next_index_on,
int* next_index_off,
180 int (* load_fset) (
const cpl_frameset *,
183 const cpl_boolean,
int);
189detmon_lin_table_fill_row(cpl_table *,
double,
191 const cpl_imagelist *,
192 const cpl_imagelist *,
199detmon_gain_table_fill_row(cpl_table * gain_table,
200 double c_dit,
int c_ndit,
201 cpl_imagelist * autocorr_images,
202 cpl_imagelist * diff_flats,
203 const cpl_imagelist * ons,
204 const cpl_imagelist * offs,
205 double kappa,
int nclip,
206 int llx,
int lly,
int urx,
int ury,
208 double gain_threshold,
209 int pos,
unsigned mode,
int* rows_affected);
213detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
214 cpl_imagelist * diff_flats,
215 const cpl_imagelist * ons,
216 double kappa,
int nclip,
217 int llx,
int lly,
int urx,
int ury,
218 double saturation_limit,
219 const int pos,
unsigned mode,
220 int* rows_linear_affected);
223detmon_lg_save(
const cpl_parameterlist *,
228 const cpl_propertylist *,
229 const cpl_propertylist *,
230 const cpl_propertylist *,
231 const cpl_propertylist *,
232 const cpl_propertylist *,
233 const cpl_propertylist *,
245 const int,
const int,
const cpl_frameset *,
249detmon_lg_qc_ptc(
const cpl_table *,
250 cpl_propertylist *,
unsigned,
int);
253detmon_lg_qc_med(
const cpl_table *,
254 cpl_propertylist *,
int);
258detmon_pfits_get_dit(
const cpl_propertylist *);
261detmon_pfits_get_dit_opt(
const cpl_propertylist *);
263irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
264 const char* prop_name);
266static cpl_image * detmon_bpixs(
const cpl_imagelist *,
267 cpl_boolean,
const double,
int *);
270detmon_autocorr_factor(
const cpl_image *,
271 cpl_image **,
int,
int);
276detmon_opt_contamination(
const cpl_imagelist *,
277 const cpl_imagelist *,
278 unsigned mode, cpl_propertylist *);
281detmon_opt_lampcr(cpl_frameset *,
int);
285detmon_lg_dfs_set_groups(cpl_frameset *,
const char *,
const char *);
288detmon_lg_reduce_all(
const cpl_table *,
295 const cpl_imagelist *,
296 const cpl_table *,
int, cpl_boolean,
300detmon_lg_check_defaults(
const cpl_image *);
303detmon_lg_rescale(cpl_imagelist *);
306detmon_lg_reduce_init(cpl_table *,
313detmon_add_adl_column(cpl_table *, cpl_boolean);
316detmon_lg_lamp_stab(
const cpl_frameset *,
317 const cpl_frameset *,
322detmon_lg_reduce_dit(
const cpl_frameset * set_on,
323 int* index_on,
double* exptime_on,
326 const cpl_frameset * set_off,
327 int * index_off,
double* exptime_off,
328 int* next_on,
int* next_off,
329 cpl_table * linear_table,
330 cpl_table * gain_table,
331 cpl_imagelist * linearity_inputs,
332 cpl_propertylist * qclist,
334 cpl_imagelist * autocorr_images,
335 cpl_imagelist * diff_flats,
336 cpl_imagelist * opt_offs,
338 int * rows_linear_affected,
339 int * rows_gain_affected);
342detmon_lg_core(cpl_frameset * cur_fset_on,
343 cpl_frameset * cur_fset_off,
347 double * exptime_off,
350 const char * recipe_name,
351 const char * pipeline_name,
352 const char * pafregexp,
353 const cpl_propertylist * pro_lintbl,
354 const cpl_propertylist * pro_gaintbl,
355 const cpl_propertylist * pro_coeffscube,
356 const cpl_propertylist * pro_bpm,
357 const cpl_propertylist * pro_corr,
358 const cpl_propertylist * pro_diff,
359 const char * package,
360 int (* load_fset) (
const cpl_frameset *,
363 int nsets, cpl_boolean opt_nir,
364 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
365 cpl_frameset * cur_fset);
368detmon_lg_lineff(
double *, cpl_propertylist *,
int,
int);
376detmon_gain_table_create(cpl_table *,
381detmon_lin_table_create(cpl_table *,
385detmon_lg_find_dits(
const cpl_vector *,
389detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
390 const cpl_vector * vec_ndits,
392 cpl_vector** diff_dits,
393 cpl_vector** diff_ndits);
396detmon_fpn_compute(
const cpl_frameset *set_on,
398 int last_linear_best,
399 cpl_propertylist *lint_qclist,
406 FPN_METHOD fpn_method,
408static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain,
409 FPN_METHOD fpn_method,
int,
double* mse);
410static double irplib_calculate_total_noise(
const cpl_image* pimage);
412static cpl_imagelist* irplib_load_fset_wrp(
const cpl_frameset *,
413 cpl_type,
int whichext);
414static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset *,
417static cpl_error_code irplib_table_create_column(cpl_table* ptable,
418 cpl_propertylist* plist);
419static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
420 cpl_propertylist* plist,
424detmon_pair_extract_next(
const cpl_frameset * set,
430 cpl_frameset ** pair,
433detmon_single_extract_next(
const cpl_frameset * set,
437 cpl_frameset ** pair);
444static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code);
445static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos);
446static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y);
455static int irplib_pfits_get_ndit(
const cpl_propertylist * plist)
457 return cpl_propertylist_get_int(plist,
"ESO DET NDIT");
500#ifdef DETMON_USE_DETECTOR_SHOTNOISE_MODEL
524hdrldemo_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
525 const double ron, cpl_image ** ima_errs)
527 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
528 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
529 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
530 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
532 *ima_errs = cpl_image_duplicate(ima_data);
534 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
538 cpl_image_divide_scalar(*ima_errs, gain);
539 cpl_image_add_scalar(*ima_errs, ron * ron);
540 cpl_image_power(*ima_errs, 0.5);
542 return cpl_error_get_code();
547detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
550 const char * tag_off,
551 const char * recipe_name,
552 const char * pipeline_name,
553 const char * pafregexp,
554 const cpl_propertylist * pro_lintbl,
555 const cpl_propertylist * pro_gaintbl,
556 const cpl_propertylist * pro_coeffscube,
557 const cpl_propertylist * pro_bpm,
558 const cpl_propertylist * pro_corr,
559 const cpl_propertylist * pro_diff,
560 const char * package,
562 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
563 const cpl_boolean opt_nir,
564 const cpl_parameterlist * parlist,
567static double irplib_compute_err(
double gain,
double ron,
double photon_noise);
570detmon_lg_dfs_save_imagelist(cpl_frameset * frameset,
571 const cpl_parameterlist * parlist,
572 const cpl_frameset *usedframes,
573 const cpl_imagelist *coeffs,
574 const char *recipe_name,
575 const cpl_propertylist *mypro_coeffscube,
576 const char * package,
577 const char * name_o);
580static void irplib_free(
char** pointer){
582 if(pointer && *pointer) {
589detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
int nsets,
591 const char * tag_off,
592 const char * recipe_name,
593 const char * pipeline_name,
594 const char * pafregexp,
595 const cpl_propertylist * pro_lintbl,
596 const cpl_propertylist * pro_gaintbl,
597 const cpl_propertylist * pro_coeffscube,
598 const cpl_propertylist * pro_bpm,
599 const cpl_propertylist * pro_corr,
600 const cpl_propertylist * pro_diff,
601 const char * package,
603 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
604 const cpl_boolean opt_nir,
605 const cpl_parameterlist * parlist,
610 int nexts = detmon_lg_config.nb_extensions;
612 double* exptime_on = 0;
613 double* exptime_off = 0;
616 cpl_frameset * cur_fset = NULL;
617 cpl_frameset* cur_fset_on = 0;
618 cpl_frameset* cur_fset_off = 0;
623 cpl_frameset_duplicate(frameset) : cpl_frameset_extract(frameset, selection, i);
626 skip_if(cur_fset == NULL);
629 cur_fset_on = cpl_frameset_new();
630 cur_fset_off = cpl_frameset_new();
631 cpl_msg_info(cpl_func,
"Splitting into ON and OFF sub-framesets");
632 skip_if (detmon_lg_split_onoff(cur_fset,
633 cur_fset_on, cur_fset_off,
635 if (cpl_frameset_get_size(cur_fset_on) == 0)
637 cpl_msg_error(cpl_func,
"No lamp frames in input");
641 if (cpl_frameset_get_size(cur_fset_off) == 0)
643 cpl_msg_error(cpl_func,
"No dark / bias frames in input");
646 cpl_msg_info(cpl_func,
"found on-frames[%" CPL_SIZE_FORMAT
"] off-frames[%" CPL_SIZE_FORMAT
"]",cpl_frameset_get_size(cur_fset_on), cpl_frameset_get_size(cur_fset_off));
654 exptime_on = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_on));
655 exptime_off = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_off));
657 index_on = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_on));
658 index_off = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_off));
659 irplib_frameset_sort(cur_fset_on, index_on, exptime_on);
660 irplib_frameset_sort(cur_fset_off, index_off, exptime_off);
673 skip_if(detmon_check_order(exptime_on, cpl_frameset_get_size(cur_fset_on), detmon_lg_config.tolerance, detmon_lg_config.order));
675 if(detmon_lg_config.exts >= 0)
683 if (detmon_lg_config.lamp_ok) {
684 skip_if(detmon_opt_lampcr(cur_fset, 0));
687 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
692 detmon_lg_config.exts,
694 recipe_name, pipeline_name, pafregexp,
695 pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff,
696 package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
698 for(j = 1; j <= nexts; j++) {
705 if (detmon_lg_config.lamp_ok) {
706 skip_if(detmon_opt_lampcr(cur_fset, j));
710 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
715 j, i, recipe_name, pipeline_name,pafregexp, pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff, package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
720 cpl_frameset_delete(cur_fset);
721 cpl_frameset_delete(cur_fset_on);
722 cpl_frameset_delete(cur_fset_off);
725 cpl_free(exptime_on);
726 cpl_free(exptime_off);
727 return cpl_error_get_code();
805detmon_lg(cpl_frameset * frameset,
806 const cpl_parameterlist * parlist,
808 const char * tag_off,
809 const char * recipe_name,
810 const char * pipeline_name,
811 const char * pafregexp,
812 const cpl_propertylist * pro_lintbl,
813 const cpl_propertylist * pro_gaintbl,
814 const cpl_propertylist * pro_coeffscube,
815 const cpl_propertylist * pro_bpm,
816 const cpl_propertylist * pro_corr,
817 const cpl_propertylist * pro_diff,
818 const char * package,
819 int (* compare) (
const cpl_frame *,
821 int (* load_fset) (
const cpl_frameset *,
824 const cpl_boolean opt_nir)
826 cpl_errorstate cleanstate = cpl_errorstate_get();
828 cpl_size * selection = NULL;
829 cpl_frame * first = NULL;
830 cpl_image * reference = NULL;
837 cpl_frameset * cur_fset = NULL;
838 cpl_frameset * cur_fset_on = NULL;
839 cpl_frameset * cur_fset_off = NULL;
842 cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
843 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
844 cpl_ensure_code(tag_on != NULL, CPL_ERROR_NULL_INPUT);
845 cpl_ensure_code(tag_off != NULL, CPL_ERROR_NULL_INPUT);
846 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
847 cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
848 cpl_ensure_code(pro_lintbl != NULL, CPL_ERROR_NULL_INPUT);
849 cpl_ensure_code(pro_gaintbl != NULL, CPL_ERROR_NULL_INPUT);
850 cpl_ensure_code(pro_coeffscube != NULL, CPL_ERROR_NULL_INPUT);
851 cpl_ensure_code(pro_bpm != NULL, CPL_ERROR_NULL_INPUT);
852 cpl_ensure_code(pro_corr != NULL, CPL_ERROR_NULL_INPUT);
853 cpl_ensure_code(pro_diff != NULL, CPL_ERROR_NULL_INPUT);
854 cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
856 cpl_msg_info(cpl_func,
"frameset size [%" CPL_SIZE_FORMAT
"]", cpl_frameset_get_size(frameset));
859 skip_if (detmon_lg_dfs_set_groups(frameset, tag_on, tag_off));
866 skip_if (detmon_lg_retrieve_parlist(pipeline_name, recipe_name,
874 first = cpl_frameset_get_position(frameset, 0);
875 irplib_ensure (first != NULL, CPL_ERROR_ILLEGAL_INPUT,
"Empty data set! Provide %s and %s input frames",tag_on,tag_off);
877 detmon_lg_config.load_fset = load_fset;
878 detmon_lg_config.load_fset_wrp = load_fset ? irplib_load_fset_wrp_ext : irplib_load_fset_wrp;
881 detmon_lg_config.nb_extensions = 1;
882 if (detmon_lg_config.exts < 0) {
884 detmon_lg_config.nb_extensions = cpl_frame_get_nextensions(first);
885 while (reference == NULL && i <= detmon_lg_config.nb_extensions) {
886 reference = cpl_image_load(cpl_frame_get_filename(first),
887 CPL_TYPE_FLOAT, 0, i);
888 if (reference == NULL) {
889 cpl_msg_warning(cpl_func,
"Extension %d empty, skipping", i);
890 cpl_errorstate_set(cleanstate);
894 cpl_errorstate_set(cleanstate);
895 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
896 "No data found in any extension");
897 cpl_msg_info(cpl_func,
"Using extension %d as reference", i - 1);
899 if (load_fset != NULL) {
900 cpl_frameset *
new = cpl_frameset_new();
901 cpl_imagelist * p = cpl_imagelist_new();
902 cpl_frameset_insert(
new, cpl_frame_duplicate(first));
903 (*load_fset)(
new, CPL_TYPE_FLOAT, p);
904 reference = cpl_image_duplicate(cpl_imagelist_get(p, 0));
905 cpl_imagelist_delete(p);
906 cpl_frameset_delete(
new);
908 cpl_msg_info(cpl_func,
"name=%s",cpl_frame_get_filename(first));
909 reference = cpl_image_load(cpl_frame_get_filename(first),
910 CPL_TYPE_FLOAT, 0, detmon_lg_config.exts);
912 cpl_errorstate_set(cleanstate);
913 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
914 "No data found in requested extension %d",
915 detmon_lg_config.exts);
917 skip_if (reference == NULL);
919 skip_if (detmon_lg_check_defaults(reference));
928 if (compare == NULL) {
931 cpl_msg_info(cpl_func,
"Identifying different settings");
932 selection = cpl_frameset_labelise(frameset, compare, &nsets);
933 skip_if (selection == NULL);
937 for(
int i = 0; i < nsets; i++)
939 int fr_size = cpl_frameset_get_size(frameset);
941 cpl_msg_info(cpl_func,
"Reduce data set nb %d out of %" CPL_SIZE_FORMAT
"",
943 skip_if(detmon_lg_reduce_set(i, frameset, nsets, tag_on, tag_off,
958 fr_size_new = cpl_frameset_get_size(frameset);
964 if (fr_size_new > fr_size)
966 selection = cpl_realloc(selection, fr_size_new *
sizeof(selection[0]));
967 memset(selection + fr_size, -1, (fr_size_new - fr_size) *
sizeof(selection[0]));
973 cpl_frameset_delete(cur_fset);
974 cpl_frameset_delete(cur_fset_on);
975 cpl_frameset_delete(cur_fset_off);
977 cpl_image_delete(reference);
979 return cpl_error_get_code();
1015static cpl_error_code
1016detmon_lg_core(cpl_frameset * cur_fset_on,
1017 cpl_frameset * cur_fset_off,
1020 double * exptime_on,
1021 double * exptime_off,
1024 const char * recipe_name,
1025 const char * pipeline_name,
1026 const char * pafregexp,
1027 const cpl_propertylist * pro_lintbl,
1028 const cpl_propertylist * pro_gaintbl,
1029 const cpl_propertylist * pro_coeffscube,
1030 const cpl_propertylist * pro_bpm,
1031 const cpl_propertylist * pro_corr,
1032 const cpl_propertylist * pro_diff,
1033 const char * package,
1034 int (* load_fset) (
const cpl_frameset *,
1037 int nsets, cpl_boolean opt_nir,
1038 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
1039 cpl_frameset * cur_fset)
1041 cpl_table * gain_table = cpl_table_new(
1042 cpl_frameset_get_size(cur_fset_on) / 2);
1043 cpl_table * linear_table = cpl_table_new(
1044 cpl_frameset_get_size(cur_fset_on) / 2);
1045 cpl_imagelist * coeffs = NULL;
1046 cpl_image * bpm = NULL;
1047 cpl_imagelist * autocorr_images = NULL;
1048 cpl_imagelist * diff_flats = NULL;
1049 cpl_propertylist * gaint_qclist = NULL;
1050 cpl_propertylist * lint_qclist = NULL;
1051 cpl_propertylist * linc_qclist = NULL;
1052 cpl_propertylist * bpm_qclist = NULL;
1054 int next_index_on = 0;
1055 int next_index_off = 0;
1058 cpl_msg_info(cpl_func,
"Reduce extension nb %d ", whichext);
1062 if (detmon_lg_config.intermediate) {
1063 autocorr_images = cpl_imagelist_new();
1064 diff_flats = cpl_imagelist_new();
1067 gaint_qclist = cpl_propertylist_new();
1068 lint_qclist = cpl_propertylist_new();
1069 linc_qclist = cpl_propertylist_new();
1070 bpm_qclist = cpl_propertylist_new();
1073 cpl_msg_info(cpl_func,
"Starting data reduction");
1074 if (detmon_lg_reduce(cur_fset_on, cur_fset_off,
1075 index_on, index_off, exptime_on, exptime_off,
1076 &next_index_on, &next_index_off,
1077 &coeffs, gain_table,
1078 linear_table, &bpm, autocorr_images,
1079 diff_flats, gaint_qclist, lint_qclist,
1080 linc_qclist, bpm_qclist, load_fset,
1081 opt_nir, whichext) == CPL_ERROR_CONTINUE) {
1082 cpl_msg_info(cpl_func,
"Empty extension %d", whichext);
1086 cpl_msg_info(cpl_func,
"Saving the products");
1089 detmon_lg_save(parlist, frameset, recipe_name,
1090 pipeline_name, pafregexp,
1091 pro_lintbl, pro_gaintbl,
1092 pro_coeffscube, pro_bpm,
1093 pro_corr, pro_diff, package,
1094 coeffs, gain_table, linear_table,
1095 bpm, autocorr_images, diff_flats,
1096 gaint_qclist, lint_qclist, linc_qclist,
1097 bpm_qclist, 0, 0, cur_fset, whichext));
1100 detmon_lg_save(parlist, frameset, recipe_name,
1101 pipeline_name, pafregexp,
1102 pro_lintbl, pro_gaintbl,
1103 pro_coeffscube, pro_bpm,
1104 pro_corr, pro_diff, package,
1105 coeffs, gain_table, linear_table,
1106 bpm, autocorr_images, diff_flats,
1107 gaint_qclist, lint_qclist, linc_qclist,
1108 bpm_qclist, 1, whichset+ 1, cur_fset,
1116 cpl_table_delete(gain_table);
1117 cpl_table_delete(linear_table);
1118 cpl_imagelist_delete(coeffs);
1119 cpl_propertylist_delete(gaint_qclist);
1120 cpl_propertylist_delete(lint_qclist);
1121 cpl_propertylist_delete(linc_qclist);
1122 if(bpm_qclist != NULL) cpl_propertylist_delete(bpm_qclist);
1123 cpl_image_delete(bpm);
1124 cpl_imagelist_delete(autocorr_images);
1125 cpl_imagelist_delete(diff_flats);
1127 return cpl_error_get_code();
1152detmon_image_correlate(
const cpl_image * image1,
1153 const cpl_image * image2,
1154 const int m,
const int n)
1156 cpl_image *image1_padded = NULL;
1157 cpl_image *image2_padded = NULL;
1161 cpl_image *corr_image_window = NULL;
1163 cpl_image* image_ri1 = NULL;
1164 cpl_image* image_ri2 = NULL;
1165 cpl_error_code err = CPL_ERROR_NONE;
1168 cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1169 cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1171 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1172 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1174 nx = cpl_image_get_size_x(image1);
1175 ny = cpl_image_get_size_y(image1);
1177 nx2 = cpl_image_get_size_x(image2);
1178 ny2 = cpl_image_get_size_y(image2);
1181 cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
1184 image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1185 cpl_image_copy(image1_padded, image1, m + 1, n + 1);
1187 image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1188 cpl_image_copy(image2_padded, image2, m + 1, n + 1);
1194 image_ri1 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
1195 image_ri2 = cpl_image_new(nx, ny , CPL_TYPE_FLOAT_COMPLEX);
1197 cpl_fft_image(image_ri1, image1_padded, CPL_FFT_FORWARD);
1198 cpl_fft_image(image_ri2, image2_padded, CPL_FFT_FORWARD);
1199 err = cpl_error_get_code();
1200 cpl_image_delete(image1_padded);
1201 image1_padded = NULL;
1202 cpl_image_delete(image2_padded);
1203 image2_padded = NULL;
1204 if (err == CPL_ERROR_NONE)
1207 cpl_image * corr_image = NULL;
1208 cpl_image * reorganised= NULL;
1209 cpl_image * image_ri_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1210 cpl_image * image_in_inv = cpl_image_new(nx, ny,
1211 CPL_TYPE_FLOAT_COMPLEX);
1214 for (i = 1; i <= nx; i++)
1216 for (j = 1; j <= ny; j++)
1219 double complex value1, value2, value;
1220 value1 = cpl_image_get_complex(image_ri1, i, j, &rej);
1221 value2 = cpl_image_get_complex(image_ri2, i, j, &rej);;
1222 value = conj(value1) * value2;
1223 cpl_image_set_complex(image_in_inv, i, j, value);
1226 cpl_image_delete(image_ri1);
1228 cpl_image_delete(image_ri2);
1231 err = cpl_error_get_code();
1232 if (err == CPL_ERROR_NONE)
1236 cpl_fft_image(image_ri_inv, image_in_inv,CPL_FFT_BACKWARD);
1237 cpl_image_delete(image_in_inv);
1240 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1241 for (i = 1; i <= nx; i++)
1243 for (j = 1; j <= ny; j++)
1247 value = cpl_image_get(image_ri_inv, i, j, &rej);
1248 cpl_image_set(corr_image, i, j, value);
1251 cpl_image_delete(image_ri_inv);
1252 err = cpl_error_get_code();
1253 if (err == CPL_ERROR_NONE)
1257 cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
1258 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1260 cpl_image_copy(reorganised, image, 1, 1);
1261 cpl_image_delete(image);
1262 image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
1263 cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
1264 cpl_image_delete(image);
1266 cpl_image_delete(corr_image);
1268 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1269 image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
1270 cpl_image_copy(corr_image, image, 1, 1);
1271 cpl_image_delete(image);
1273 image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
1274 cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
1275 cpl_image_delete(image);
1277 corr_image_window = cpl_image_extract(corr_image,
1280 nx / 2 + 1 + m, ny / 2 + 1 + n);
1285 cpl_image_delete(reorganised);
1286 cpl_image_delete(corr_image);
1288 if(cpl_image_divide_scalar(corr_image_window,
1289 cpl_image_get_max(corr_image_window))) {
1290 cpl_image_delete(corr_image_window);
1294 cpl_image_delete (image_ri1);
1295 cpl_image_delete (image_ri2);
1296 cpl_image_delete (image1_padded);
1297 cpl_image_delete (image2_padded);
1298 return corr_image_window;
1321detmon_autocorrelate(
const cpl_image * input2,
const int m,
1324 cpl_image *im_re = NULL;
1325 cpl_image *im_im = NULL;
1327 cpl_image *ifft_re = NULL;
1328 cpl_image *ifft_im = NULL;
1329 cpl_image *autocorr = NULL;
1330 cpl_image *autocorr_norm_double = NULL;
1331 cpl_image *autocorr_norm = NULL;
1332 cpl_image *reorganised = NULL;
1333 cpl_image *image = NULL;
1335 cpl_error_code error;
1338 cpl_ensure(input2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1340 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1341 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1343 nx = cpl_image_get_size_x(input2) + 2 * m;
1344 ny = cpl_image_get_size_y(input2) + 2 * n;
1347 while(nx > p || ny > p) {
1351 input = cpl_image_cast(input2, CPL_TYPE_DOUBLE);
1353 im_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1354 error = cpl_image_copy(im_re, input, 1, 1);
1355 cpl_image_delete(input);
1357 cpl_ensure(!error, error, NULL);
1359 im_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1361 error = cpl_image_fft(im_re, im_im, CPL_FFT_DEFAULT);
1362 cpl_ensure(!error, error, NULL);
1364 ifft_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1365 error = cpl_image_power(im_re, 2);
1366 cpl_ensure(!error, error, NULL);
1368 error = cpl_image_add(ifft_re, im_re);
1369 cpl_ensure(!error, error, NULL);
1371 cpl_image_delete(im_re);
1373 error = cpl_image_power(im_im, 2);
1374 cpl_ensure(!error, error, NULL);
1376 error = cpl_image_add(ifft_re, im_im);
1377 cpl_ensure(!error, error, NULL);
1379 cpl_image_delete(im_im);
1381 ifft_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1383 error = cpl_image_fft(ifft_re, ifft_im, CPL_FFT_INVERSE);
1384 cpl_ensure(!error, error, NULL);
1386 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1388 error = cpl_image_power(ifft_re, 2);
1389 cpl_ensure(!error, error, NULL);
1391 error = cpl_image_add(autocorr, ifft_re);
1392 cpl_ensure(!error, error, NULL);
1394 cpl_image_delete(ifft_re);
1396 error = cpl_image_power(ifft_im, 2);
1397 cpl_ensure(!error, error, NULL);
1399 error = cpl_image_add(autocorr, ifft_im);
1400 cpl_ensure(!error, error, NULL);
1402 cpl_image_delete(ifft_im);
1405 reorganised = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1407 image = cpl_image_extract(autocorr, p / 2 + 1, 1, p, p);
1408 cpl_image_copy(reorganised, image, 1, 1);
1409 cpl_image_delete(image);
1411 image = cpl_image_extract(autocorr, 1, 1, p / 2, p);
1412 cpl_image_copy(reorganised, image, p / 2 + 1, 1);
1413 cpl_image_delete(image);
1415 cpl_image_delete(autocorr);
1417 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1419 image = cpl_image_extract(reorganised, 1, p / 2 + 1, p, p);
1420 cpl_image_copy(autocorr, image, 1, 1);
1421 cpl_image_delete(image);
1423 image = cpl_image_extract(reorganised, 1, 1, p, p / 2);
1424 cpl_image_copy(autocorr, image, 1, p / 2 + 1);
1425 cpl_image_delete(image);
1427 cpl_image_delete(reorganised);
1429 autocorr_norm_double =
1430 cpl_image_extract(autocorr, p / 2 + 1 - m, p / 2 + 1 - n,
1431 p / 2 + 1 + m, p / 2 + 1 + n);
1433 cpl_image_delete(autocorr);
1435 if(cpl_image_divide_scalar(autocorr_norm_double,
1436 cpl_image_get_max(autocorr_norm_double))) {
1437 cpl_image_delete(autocorr_norm_double);
1438 cpl_ensure(0, cpl_error_get_code(), NULL);
1442 autocorr_norm = cpl_image_cast(autocorr_norm_double, CPL_TYPE_FLOAT);
1443 cpl_image_delete(autocorr_norm_double);
1445 return autocorr_norm;
1461detmon_lg_fill_parlist_nir_default(cpl_parameterlist * parlist,
1462 const char *recipe_name,
1463 const char *pipeline_name)
1465 const cpl_error_code error =
1466 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1512 cpl_ensure_code(!error, error);
1514 return cpl_error_get_code();
1530detmon_lg_fill_parlist_opt_default(cpl_parameterlist * parlist,
1531 const char *recipe_name,
1532 const char *pipeline_name)
1534 const cpl_error_code error =
1535 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1580 cpl_ensure_code(!error, error);
1582 return cpl_error_get_code();
1585static cpl_error_code
1586detmon_lg_fill_parlist_default_mr(cpl_parameterlist * parlist,
1587 const char *recipe_name,
1588 const char *pipeline_name)
1590 char * group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1591 char * par_name = cpl_sprintf(
"%s.%s", group_name,
"regions-file");
1592 cpl_parameter * p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1593 "File containing regions, "
1594 "four comma separated points "
1597 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions-file");
1598 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1599 cpl_parameterlist_append(parlist, p);
1601 cpl_free(group_name);
1603 group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1604 par_name = cpl_sprintf(
"%s.%s", group_name,
"regions");
1605 p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1606 "Colon separated list of regions, four "
1607 "points each, comma separated: "
1608 "llx,lly,urx,ury:llx,...",
1610 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions");
1611 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1612 cpl_parameterlist_append(parlist, p);
1614 cpl_free(group_name);
1616 return cpl_error_get_code();
1620detmon_lg_fill_parlist_opt_default_mr(cpl_parameterlist * parlist,
1621 const char *recipe_name,
1622 const char *pipeline_name)
1624 detmon_lg_fill_parlist_opt_default(parlist, recipe_name, pipeline_name);
1625 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1626 return cpl_error_get_code();
1630detmon_lg_fill_parlist_nir_default_mr(cpl_parameterlist * parlist,
1631 const char *recipe_name,
1632 const char *pipeline_name)
1634 detmon_lg_fill_parlist_nir_default(parlist, recipe_name, pipeline_name);
1635 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1637 return cpl_error_get_code();
1697detmon_lg_fill_parlist(cpl_parameterlist * parlist,
1698 const char *recipe_name,
const char *pipeline_name,
1708 const char *intermediate,
1709 const char *autocorr,
1710 const char *collapse,
1711 const char *rescale,
1712 const char *pix2pix,
1719 const char * pafname,
1736 int llx5,
int lly5,
int urx5,
int ury5,
int exts,
1737 cpl_boolean opt_nir)
1739 const cpl_error_code error =
1740 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 26,
1742 "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
1743 "CPL_TYPE_STRING", method,
1746 "Polynomial order for the fit (Linearity)",
1747 "CPL_TYPE_INT", order,
1749 "Kappa value for the kappa-sigma clipping (Gain)",
1750 "CPL_TYPE_DOUBLE", kappa,
1752 "Number of iterations to compute rms (Gain)",
1753 "CPL_TYPE_INT", niter,
1755 "x coordinate of the lower-left "
1756 "point of the region of interest. If not modified, default value will be 1.",
1757 "CPL_TYPE_INT", llx,
1759 "y coordinate of the lower-left "
1760 "point of the region of interest. If not modified, default value will be 1.",
1761 "CPL_TYPE_INT", lly,
1763 "x coordinate of the upper-right "
1764 "point of the region of interest. If not modified, default value will be X dimension of the input image.",
1765 "CPL_TYPE_INT", urx,
1767 "y coordinate of the upper-right "
1768 "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
1769 "CPL_TYPE_INT", ury,
1771 "User reference level",
1772 "CPL_TYPE_INT", ref_level,
1774 "De-/Activate intermediate products",
1775 "CPL_TYPE_BOOL", intermediate,
1778 "De-/Activate the autocorr option",
1779 "CPL_TYPE_BOOL", autocorr,
1782 "De-/Activate the collapse option",
1783 "CPL_TYPE_BOOL", collapse,
1785 "De-/Activate the image rescale option",
1786 "CPL_TYPE_BOOL", rescale,
1788 "De-/Activate the computation with pixel to pixel accuracy",
1789 "CPL_TYPE_BOOL", pix2pix,
1791 "De-/Activate the binary bpm option",
1792 "CPL_TYPE_BOOL", bpmbin,
1794 "Maximum x-shift for the autocorr",
1797 "Upper limit of Median flux to be filtered",
1798 "CPL_TYPE_INT", filter,
1800 "Maximum y-shift for the autocorr",
1803 "Tolerance for pair discrimination",
1804 "CPL_TYPE_DOUBLE", tolerance,
1807 "Generate PAF file",
1808 "CPL_TYPE_BOOL", pafgen,
1810 "Specific name for PAF file",
1811 "CPL_TYPE_STRING", pafname,
1815 "Activate the multi-exts option. Choose -1 to process all extensions. Choose an extension number"
1816 " to process the appropriate extension.",
1817 "CPL_TYPE_INT", exts,
1820 "Method for computing Fixed Pattern Noise (SMOOTH or HISTOGRAM)",
1821 "CPL_TYPE_STRING",
"HISTOGRAM",
1824 "template size in pixels for smoothing during FPN computation (only for SMOOTH method)",
1828 "all frames with mean saturation above the limit would not be used in linearity calculation",
1829 "CPL_TYPE_DOUBLE", 65535.0,
1832 "all frames with mean flux above the threshold would not be used in gain calculation",
1833 "CPL_TYPE_DOUBLE", 65535.0
1836 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 1,
1837 "coeffs_cube_split",
1838 "if TRUE, the recipe writes as many "
1839 "COEFFS_CUBE_Pi (i=0..order) as the value of "
1840 "the order parameter in a separate file",
1841 "CPL_TYPE_BOOL",
"CPL_FALSE");
1843 if(opt_nir == FALSE) {
1844 const cpl_error_code erroropt =
1845 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
1847 "x coord of the lower-left point of the first "
1848 "field used for contamination measurement. If not modified, default value will be 1.",
1849 "CPL_TYPE_INT", llx1,
1851 "y coord of the lower-left point of the first "
1852 "field used for contamination measurement. If not modified, default value will be 1.",
1853 "CPL_TYPE_INT", lly1,
1855 "x coord of the upper-right point of the first "
1856 "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
1857 "CPL_TYPE_INT", urx1,
1859 "y coord of the upper-right point of the first "
1860 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1861 "CPL_TYPE_INT", ury1,
1863 "x coord of the lower-left point of the second "
1864 "field used for contamination measurement. If not modified, default value will be 1.",
1865 "CPL_TYPE_INT", llx2,
1867 "y coord of the lower-left point of the second "
1868 "field used for contamination measurement. If not modified, default value will be 1.",
1869 "CPL_TYPE_INT", lly2,
1871 "x coord of the upper-right point of the second "
1872 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1873 "CPL_TYPE_INT", urx2,
1875 "y coord of the upper-right point of the second "
1876 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1877 "CPL_TYPE_INT", ury2,
1879 "x coord of the lower-left point of the third "
1880 "field used for contamination measurement. If not modified, default value will be 1.",
1881 "CPL_TYPE_INT", llx3,
1883 "y coord of the lower-left point of the third "
1884 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1885 "CPL_TYPE_INT", lly3,
1887 "x coord of the upper-right point of the third "
1888 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1889 "CPL_TYPE_INT", urx3,
1891 "y coord of the upper-right point of the third "
1892 "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
1893 "CPL_TYPE_INT", ury3,
1895 "x coord of the lower-left point of the fourth "
1896 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1897 "CPL_TYPE_INT", llx4,
1899 "y coord of the lower-left point of the fourth "
1900 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1901 "CPL_TYPE_INT", lly4,
1903 "x coord of the upper-right point of the fourth "
1904 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1905 "CPL_TYPE_INT", urx4,
1907 "y coord of the upper-right point of the fourth "
1908 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1909 "CPL_TYPE_INT", ury4,
1911 "x coord of the lower-left point of the fifth "
1912 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1913 "CPL_TYPE_INT", llx5,
1915 "y coord of the lower-left point of the fifth "
1916 "field used for contamination measurement. If not modified, default value will be 1.",
1917 "CPL_TYPE_INT", lly5,
1919 "x coord of the upper-right point of the fifth "
1920 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1921 "CPL_TYPE_INT", urx5,
1924 "y coord of the upper-right point of the fifth "
1925 "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
1926 "CPL_TYPE_INT", ury5);
1929 cpl_ensure_code(!erroropt, erroropt);
1932 cpl_ensure_code(!error, error);
1934 return cpl_error_get_code();
1947static cpl_error_code
1948detmon_lg_retrieve_parlist(
const char * pipeline_name,
1949 const char * recipe_name,
1950 const cpl_parameterlist * parlist,
1951 cpl_boolean opt_nir)
1955 const cpl_parameter * par;
1958 par_name = cpl_sprintf(
"%s.%s.method", pipeline_name, recipe_name);
1959 assert(par_name != NULL);
1960 par = cpl_parameterlist_find_const(parlist, par_name);
1961 detmon_lg_config.method = cpl_parameter_get_string(par);
1965 detmon_lg_config.order =
1966 detmon_retrieve_par_int(
"order", pipeline_name, recipe_name,
1970 detmon_lg_config.kappa =
1971 detmon_retrieve_par_double(
"kappa", pipeline_name, recipe_name,
1975 detmon_lg_config.niter =
1976 detmon_retrieve_par_int(
"niter", pipeline_name, recipe_name,
1980 detmon_lg_config.llx =
1981 detmon_retrieve_par_int(
"llx", pipeline_name, recipe_name,
1985 detmon_lg_config.lly =
1986 detmon_retrieve_par_int(
"lly", pipeline_name, recipe_name,
1990 detmon_lg_config.urx =
1991 detmon_retrieve_par_int(
"urx", pipeline_name, recipe_name,
1995 detmon_lg_config.ury =
1996 detmon_retrieve_par_int(
"ury", pipeline_name, recipe_name,
2000 detmon_lg_config.ref_level =
2001 detmon_retrieve_par_int(
"ref_level", pipeline_name, recipe_name,
2006 cpl_sprintf(
"%s.%s.intermediate", pipeline_name, recipe_name);
2007 assert(par_name != NULL);
2008 par = cpl_parameterlist_find_const(parlist, par_name);
2009 detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
2013 par_name = cpl_sprintf(
"%s.%s.autocorr", pipeline_name, recipe_name);
2014 assert(par_name != NULL);
2015 par = cpl_parameterlist_find_const(parlist, par_name);
2016 detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
2020 par_name = cpl_sprintf(
"%s.%s.coeffs_cube_split", pipeline_name, recipe_name);
2021 assert(par_name != NULL);
2022 par = cpl_parameterlist_find_const(parlist, par_name);
2023 detmon_lg_config.split_coeffs = cpl_parameter_get_bool(par);
2027 par_name = cpl_sprintf(
"%s.%s.collapse", pipeline_name, recipe_name);
2028 assert(par_name != NULL);
2029 par = cpl_parameterlist_find_const(parlist, par_name);
2030 detmon_lg_config.collapse = cpl_parameter_get_bool(par);
2034 par_name = cpl_sprintf(
"%s.%s.rescale", pipeline_name, recipe_name);
2035 assert(par_name != NULL);
2036 par = cpl_parameterlist_find_const(parlist, par_name);
2037 detmon_lg_config.rescale = cpl_parameter_get_bool(par);
2041 par_name = cpl_sprintf(
"%s.%s.pix2pix", pipeline_name, recipe_name);
2042 assert(par_name != NULL);
2043 par = cpl_parameterlist_find_const(parlist, par_name);
2044 detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
2048 par_name = cpl_sprintf(
"%s.%s.bpmbin", pipeline_name, recipe_name);
2049 assert(par_name != NULL);
2050 par = cpl_parameterlist_find_const(parlist, par_name);
2051 detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
2055 detmon_lg_config.filter =
2056 detmon_retrieve_par_int(
"filter", pipeline_name,
2057 recipe_name, parlist);
2060 detmon_lg_config.m =
2061 detmon_retrieve_par_int(
"m", pipeline_name, recipe_name, parlist);
2064 detmon_lg_config.n =
2065 detmon_retrieve_par_int(
"n", pipeline_name, recipe_name, parlist);
2068 par_name = cpl_sprintf(
"%s.%s.tolerance", pipeline_name, recipe_name);
2069 assert(par_name != NULL);
2070 par = cpl_parameterlist_find_const(parlist, par_name);
2071 detmon_lg_config.tolerance = cpl_parameter_get_double(par);
2076 par_name = cpl_sprintf(
"%s.%s.pafgen", pipeline_name, recipe_name);
2077 assert(par_name != NULL);
2078 par = cpl_parameterlist_find_const(parlist, par_name);
2079 detmon_lg_config.pafgen = cpl_parameter_get_bool(par);
2083 par_name = cpl_sprintf(
"%s.%s.pafname", pipeline_name, recipe_name);
2084 assert(par_name != NULL);
2085 par = cpl_parameterlist_find_const(parlist, par_name);
2086 detmon_lg_config.pafname = cpl_parameter_get_string(par);
2089 if(opt_nir == OPT) {
2091 detmon_lg_config.llx1 =
2092 detmon_retrieve_par_int(
"llx1", pipeline_name, recipe_name,
2096 detmon_lg_config.lly1 =
2097 detmon_retrieve_par_int(
"lly1", pipeline_name, recipe_name,
2101 detmon_lg_config.urx1 =
2102 detmon_retrieve_par_int(
"urx1", pipeline_name, recipe_name,
2106 detmon_lg_config.ury1 =
2107 detmon_retrieve_par_int(
"ury1", pipeline_name, recipe_name,
2111 detmon_lg_config.llx2 =
2112 detmon_retrieve_par_int(
"llx2", pipeline_name, recipe_name,
2116 detmon_lg_config.lly2 =
2117 detmon_retrieve_par_int(
"lly2", pipeline_name, recipe_name,
2121 detmon_lg_config.urx2 =
2122 detmon_retrieve_par_int(
"urx2", pipeline_name, recipe_name,
2126 detmon_lg_config.ury2 =
2127 detmon_retrieve_par_int(
"ury2", pipeline_name, recipe_name,
2131 detmon_lg_config.llx3 =
2132 detmon_retrieve_par_int(
"llx3", pipeline_name, recipe_name,
2136 detmon_lg_config.lly3 =
2137 detmon_retrieve_par_int(
"lly3", pipeline_name, recipe_name,
2141 detmon_lg_config.urx3 =
2142 detmon_retrieve_par_int(
"urx3", pipeline_name, recipe_name,
2146 detmon_lg_config.ury3 =
2147 detmon_retrieve_par_int(
"ury3", pipeline_name, recipe_name,
2151 detmon_lg_config.llx4 =
2152 detmon_retrieve_par_int(
"llx4", pipeline_name, recipe_name,
2156 detmon_lg_config.lly4 =
2157 detmon_retrieve_par_int(
"lly4", pipeline_name, recipe_name,
2161 detmon_lg_config.urx4 =
2162 detmon_retrieve_par_int(
"urx4", pipeline_name, recipe_name,
2166 detmon_lg_config.ury4 =
2167 detmon_retrieve_par_int(
"ury4", pipeline_name, recipe_name,
2171 detmon_lg_config.llx5 =
2172 detmon_retrieve_par_int(
"llx5", pipeline_name, recipe_name,
2176 detmon_lg_config.lly5 =
2177 detmon_retrieve_par_int(
"lly5", pipeline_name, recipe_name,
2181 detmon_lg_config.urx5 =
2182 detmon_retrieve_par_int(
"urx5", pipeline_name, recipe_name,
2186 detmon_lg_config.ury5 =
2187 detmon_retrieve_par_int(
"ury5", pipeline_name, recipe_name,
2192 detmon_lg_config.exts =
2193 detmon_retrieve_par_int(
"exts", pipeline_name, recipe_name,
2197 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2199 cpl_sprintf(
"%s.%s.fpn_method", pipeline_name, recipe_name);
2200 assert(par_name != NULL);
2201 par = cpl_parameterlist_find_const(parlist, par_name);
2204 const char * str_method = cpl_parameter_get_string(par);
2205 if (strcmp(str_method,
"SMOOTH") == 0)
2207 detmon_lg_config.fpn_method = FPN_SMOOTH;
2209 else if (strcmp(str_method,
"HISTOGRAM") == 0)
2211 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2217 detmon_lg_config.fpn_smooth =
2218 detmon_retrieve_par_int(
"fpn_smooth", pipeline_name, recipe_name,
2222 detmon_lg_config.saturation_limit = 65535;
2224 cpl_sprintf(
"%s.%s.saturation_limit", pipeline_name, recipe_name);
2225 assert(par_name != NULL);
2226 par = cpl_parameterlist_find_const(parlist, par_name);
2229 detmon_lg_config.saturation_limit = cpl_parameter_get_double(par);
2236 detmon_lg_config.gain_threshold = 0;
2238 cpl_sprintf(
"%s.%s.gain_threshold", pipeline_name, recipe_name);
2239 assert(par_name != NULL);
2240 par = cpl_parameterlist_find_const(parlist, par_name);
2243 detmon_lg_config.gain_threshold = cpl_parameter_get_double(par);
2248 if(cpl_error_get_code())
2250 cpl_msg_error(cpl_func,
"Failed to retrieve the input parameters");
2251 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
2255 return cpl_error_get_code();
2265static cpl_error_code
2266detmon_lg_check_defaults(
const cpl_image * reference)
2268 const int nx = cpl_image_get_size_x(reference);
2269 const int ny = cpl_image_get_size_y(reference);
2271 detmon_lg_config.nx = nx;
2272 detmon_lg_config.ny = ny;
2274 detmon_lg_config.wholechip = CPL_FALSE;
2276 if(detmon_lg_config.llx == -1)
2277 detmon_lg_config.llx = 1;
2278 if(detmon_lg_config.lly == -1)
2279 detmon_lg_config.lly = 1;
2280 if(detmon_lg_config.urx == -1)
2281 detmon_lg_config.urx = nx;
2282 if(detmon_lg_config.ury == -1)
2283 detmon_lg_config.ury = ny;
2285 if (detmon_lg_config.llx == 1 &&
2286 detmon_lg_config.lly == 1 &&
2287 detmon_lg_config.urx == nx &&
2288 detmon_lg_config.ury == ny)
2289 detmon_lg_config.wholechip = CPL_TRUE;
2291 if(detmon_lg_config.llx1 == -1)
2292 detmon_lg_config.llx1 = 1;
2293 if(detmon_lg_config.lly1 == -1)
2294 detmon_lg_config.lly1 = 1;
2295 if(detmon_lg_config.urx1 == -1)
2296 detmon_lg_config.urx1 = nx;
2297 if(detmon_lg_config.ury1 == -1)
2298 detmon_lg_config.ury1 = ny;
2300 if(detmon_lg_config.llx2 == -1)
2301 detmon_lg_config.llx2 = 1;
2302 if(detmon_lg_config.lly2 == -1)
2303 detmon_lg_config.lly2 = 1;
2304 if(detmon_lg_config.urx2 == -1)
2305 detmon_lg_config.urx2 = nx / 2;
2306 if(detmon_lg_config.ury2 == -1)
2307 detmon_lg_config.ury2 = ny / 2;
2309 if(detmon_lg_config.llx3 == -1)
2310 detmon_lg_config.llx3 = 1;
2311 if(detmon_lg_config.lly3 == -1)
2312 detmon_lg_config.lly3 = ny / 2;
2313 if(detmon_lg_config.urx3 == -1)
2314 detmon_lg_config.urx3 = nx / 2;
2315 if(detmon_lg_config.ury3 == -1)
2316 detmon_lg_config.ury3 = ny;
2318 if(detmon_lg_config.llx4 == -1)
2319 detmon_lg_config.llx4 = nx / 2;
2320 if(detmon_lg_config.lly4 == -1)
2321 detmon_lg_config.lly4 = ny / 2;
2322 if(detmon_lg_config.urx4 == -1)
2323 detmon_lg_config.urx4 = nx;
2324 if(detmon_lg_config.ury4 == -1)
2325 detmon_lg_config.ury4 = ny;
2327 if(detmon_lg_config.llx5 == -1)
2328 detmon_lg_config.llx5 = nx / 2;
2329 if(detmon_lg_config.lly5 == -1)
2330 detmon_lg_config.lly5 = 1;
2331 if(detmon_lg_config.urx5 == -1)
2332 detmon_lg_config.urx5 = nx;
2333 if(detmon_lg_config.ury5 == -1)
2334 detmon_lg_config.ury5 = ny / 2;
2336 if(detmon_lg_config.intermediate == TRUE) {
2337 cpl_msg_warning(cpl_func,
"PLEASE NOTE: The --intermediate option saves the difference and correlation images produced during autocorrelation computation. Therefore, --autocorr option has been automatically activated. If you didn't want to run this, please abort and rerun.");
2338 detmon_lg_config.autocorr = TRUE;
2342 detmon_lg_config.lamp_stability = 0.0;
2344 detmon_lg_config.lamp_ok = FALSE;
2346 detmon_lg_config.cr = 0.0;
2348 return cpl_error_get_code();
2363static cpl_error_code
2364detmon_lg_split_onoff(
const cpl_frameset * cur_fset,
2365 cpl_frameset * cur_fset_on,
2366 cpl_frameset * cur_fset_off,
2368 const char *tag_off)
2373 cpl_frame * cur_frame_dup = NULL;
2376 const cpl_frame * first;
2377 const cpl_frame * second;
2378 const char * first_tag;
2379 const char * second_tag;
2380 skip_if((first = cpl_frameset_get_position_const(cur_fset, 0)) == NULL);
2381 skip_if((second = cpl_frameset_get_position_const(cur_fset, 1)) == NULL);
2383 skip_if((first_tag = cpl_frame_get_tag(first)) == NULL);
2384 skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
2385 if (opt_nir == OPT &&
2386 ((!strcmp(first_tag, tag_on ) && !strcmp(second_tag, tag_off)) ||
2387 (!strcmp(first_tag, tag_off) && !strcmp(second_tag, tag_on )))) {
2388 detmon_lg_config.lamp_ok = TRUE;
2392 nframes = cpl_frameset_get_size(cur_fset);
2393 for(i = detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
2394 const cpl_frame * cur_frame =
2395 cpl_frameset_get_position_const(cur_fset, i);
2399 cur_frame_dup = cpl_frame_duplicate(cur_frame);
2400 tag = (
char *) cpl_frame_get_tag(cur_frame_dup);
2403 if(!strcmp(tag, tag_on)) {
2404 skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
2405 }
else if(!strcmp(tag, tag_off)) {
2406 skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
2408 cpl_frame_delete(cur_frame_dup);
2409 cur_frame_dup = NULL;
2412 cur_frame_dup = NULL;
2416 cpl_frame_delete(cur_frame_dup);
2418 return cpl_error_get_code();
2445static cpl_error_code
2446detmon_lg_reduce(
const cpl_frameset * set_on,
2447 const cpl_frameset * set_off,
2448 int* index_on,
int* index_off,
2449 double* exptime_on,
double* exptime_off,
2450 int *next_index_on,
int* next_index_off,
2451 cpl_imagelist ** coeffs_ptr,
2452 cpl_table * gain_table,
2453 cpl_table * linear_table,
2454 cpl_image ** bpm_ptr,
2455 cpl_imagelist * autocorr_images,
2456 cpl_imagelist * diff_flats,
2457 cpl_propertylist * gaint_qclist,
2458 cpl_propertylist * lint_qclist,
2459 cpl_propertylist * linc_qclist,
2460 cpl_propertylist * bpm_qclist,
2461 int (* load_fset) (
const cpl_frameset *,
2464 const cpl_boolean opt_nir,
2467 cpl_errorstate prestate = cpl_errorstate_get();
2468 const double D_INVALID_VALUE = -999;
2470 cpl_imagelist * linearity_inputs = NULL;
2471 cpl_imagelist * opt_offs = NULL;
2473 cpl_propertylist * reflist = NULL;
2475 int rows_linear_affected = 1;
2476 int rows_gain_affected = 1;
2477 int last_linear_best = 0;
2479 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2480 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2482 nsets = cpl_frameset_get_size(set_on) / 2;
2484 detmon_lg_config.load_fset = load_fset;
2485 const cpl_frame *frame = cpl_frameset_get_position_const(set_on, 0);
2486 const char* fname = cpl_frame_get_filename(frame);
2487 cpl_propertylist* plist = cpl_propertylist_load(fname, 0);
2490 if(cpl_propertylist_has(plist,
"ESO DET CHIP RON")) {
2491 ron = cpl_propertylist_get_double(plist,
"ESO DET CHIP RON");
2494 cpl_msg_info(cpl_func,
"Nominal ron (from FITS header): %g",ron);
2495 cpl_propertylist_delete(plist);
2497 if(detmon_lg_config.collapse) {
2504 const cpl_frame *first = cpl_frameset_get_position_const(set_off, 0);
2505 cpl_frame *dup_first = cpl_frame_duplicate(first);
2507 const cpl_frame *second = cpl_frameset_get_position_const(set_off, 1);
2508 cpl_frame *dup_second = cpl_frame_duplicate(second);
2510 cpl_frameset *raw_offs = cpl_frameset_new();
2512 skip_if(cpl_frameset_insert(raw_offs, dup_first));
2513 skip_if(cpl_frameset_insert(raw_offs, dup_second));
2515 opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
2518 cpl_frameset_delete(raw_offs);
2519 if (opt_offs == NULL) {
2520 cpl_errorstate_set(prestate);
2521 return CPL_ERROR_CONTINUE;
2525 skip_if(detmon_lg_reduce_init(gain_table,
2537 if(detmon_lg_lamp_stab(set_on, set_off,
2538 opt_nir, whichext)) {
2539 cpl_errorstate_set(prestate);
2542 if(!detmon_lg_config.collapse)
2546 skip_if(cpl_table_unselect_all(linear_table));
2547 skip_if(cpl_table_unselect_all(gain_table));
2551 for(i = 0; i < nsets ; i++)
2553 skip_if(detmon_lg_reduce_dit(set_on,
2554 index_on, exptime_on,
2558 index_off, exptime_off,
2559 next_index_on, next_index_off,
2561 gain_table, linearity_inputs,
2562 lint_qclist, opt_nir,
2563 autocorr_images, diff_flats,
2565 &rows_linear_affected,&rows_gain_affected));
2569 if (rows_linear_affected == 0)
2571 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2572 "into linear calculation, check the messages above");
2573 cpl_table_select_row(linear_table, i);
2577 last_linear_best = i;
2580 if (rows_gain_affected == 0)
2582 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2583 "into gain calculation, check the messages above");
2584 cpl_table_select_row(gain_table, i);
2591 skip_if(detmon_add_adl_column(linear_table, opt_nir));
2597 skip_if(cpl_table_erase_selected(gain_table));
2598 skip_if(cpl_table_erase_selected(linear_table));
2601 reflist = cpl_propertylist_new();
2602 skip_if(cpl_propertylist_append_bool(reflist,
"ADU", FALSE));
2603 skip_if(cpl_table_sort(gain_table, reflist));
2609 skip_if(detmon_lg_reduce_all(linear_table,
2610 gaint_qclist, lint_qclist, linc_qclist,
2611 bpm_qclist, coeffs_ptr, bpm_ptr,
2613 gain_table, whichext, opt_nir, ron));
2616 gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
2619 cpl_error_code cplerr = cpl_error_get_code();
2620 if (cplerr != CPL_ERROR_NONE || (gain == 0.0))
2622 cpl_msg_warning(cpl_func,
"Cannot read gain from QC parameters - "
2623 "FPN will not be computed");
2628 detmon_fpn_compute(set_on, index_on, last_linear_best, lint_qclist,
2629 detmon_lg_config.llx,
2630 detmon_lg_config.lly,
2631 detmon_lg_config.urx,
2632 detmon_lg_config.ury,
2635 detmon_lg_config.fpn_method,
2636 detmon_lg_config.fpn_smooth);
2641 detmon_table_fill_invalid(gain_table, D_INVALID_VALUE);
2643 cpl_imagelist_delete(linearity_inputs);
2644 cpl_imagelist_delete(opt_offs);
2645 cpl_propertylist_delete(reflist);
2647 return cpl_error_get_code();
2650static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code)
2652 int ncols = cpl_table_get_ncol(ptable);
2653 cpl_array* pnames = cpl_table_get_column_names(ptable);
2654 int nrows = cpl_table_get_nrow(ptable);
2656 for (i=0; i < ncols; i++)
2659 for (j = 0; j< nrows; j++)
2661 const char* colname = cpl_array_get_data_string_const(pnames)[i];
2663 cpl_type type = cpl_table_get_column_type(ptable, colname);
2664 cpl_table_get(ptable, colname, j, &isnull);
2667 if (type == CPL_TYPE_DOUBLE)
2669 cpl_table_set(ptable,colname,j, code);
2671 else if (type == CPL_TYPE_FLOAT)
2673 cpl_table_set_float(ptable,colname,j, (
float)code);
2678 cpl_array_delete(pnames);
2679 return cpl_error_get_code();
2682static cpl_error_code
2683detmon_fpn_compute(
const cpl_frameset *set_on,
2685 int last_linear_best,
2686 cpl_propertylist *lint_qclist,
2693 FPN_METHOD fpn_method,
2697 const cpl_image* im1 = 0;
2699 cpl_imagelist* ons = 0;
2700 cpl_frameset * pair_on = 0;
2701 int nsets_extracted = cpl_frameset_get_size(set_on);
2702 cpl_size * selection = NULL;
2711 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
2712 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
2714 selection[index_on[last_linear_best*2 + 0] ] = 1;
2715 selection[index_on[last_linear_best*2 + 1] ] = 1;
2716 pair_on = cpl_frameset_extract(set_on, selection, 1);
2717 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2719 skip_if(ons == NULL);
2720 skip_if((im1 = cpl_imagelist_get_const(ons, 0)) == NULL);
2722 fpn = irplib_fpn_lg(im1, range, gain, fpn_method, smooth_size, &mse);
2723 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_FPN,
2725 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_GAIN_ERR,
2727 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_GAIN_ERR,
2728 DETMON_QC_GAIN_ERR_C));
2730 cpl_frameset_delete(pair_on);
2731 cpl_imagelist_delete(ons);
2732 cpl_free(selection);
2733 return cpl_error_get_code();
2745static cpl_error_code
2746detmon_lg_lamp_stab(
const cpl_frameset * lamps,
2747 const cpl_frameset * darks,
2748 cpl_boolean opt_nir,
2761 cpl_vector * selection = NULL;
2762 cpl_propertylist * plist;
2763 double dit_lamp, dit_dark;
2765 cpl_imagelist * lamps_data = NULL;
2766 cpl_imagelist * darks_data = NULL;
2767 double * stab_levels = NULL;
2769 double * ditvals = NULL;
2773 cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
2774 CPL_ERROR_ILLEGAL_INPUT);
2780 cpl_msg_info(__func__,
"Checking DIT consistency");
2781 selection = cpl_vector_new(nb_lamps);
2782 ditvals = cpl_malloc(nb_lamps *
sizeof(
double));
2784 for (i = 0; i < nb_lamps; i++) {
2785 const cpl_frame * c_lamp;
2786 const cpl_frame * c_dark;
2788 skip_if (cpl_error_get_code());
2791 c_lamp = cpl_frameset_get_position_const(lamps, i);
2792 plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
2794 dit_lamp = (double)detmon_pfits_get_dit(plist);
2796 dit_lamp = (double)detmon_pfits_get_dit_opt(plist);
2797 cpl_propertylist_delete(plist);
2798 skip_if (cpl_error_get_code());
2801 c_dark = cpl_frameset_get_position_const(darks, i);
2802 plist = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
2804 dit_dark = (double)detmon_pfits_get_dit(plist);
2806 dit_dark = (double)detmon_pfits_get_dit_opt(plist);
2807 cpl_propertylist_delete(plist);
2808 skip_if (cpl_error_get_code());
2811 if (fabs(dit_dark-dit_lamp) > 1e-3) {
2812 cpl_msg_error(__func__,
"DIT not consistent between LAMP and DARK, skip lamp stability computation");
2817 ditvals[i] = dit_lamp;
2820 cpl_vector_set(selection, i, -1.0);
2828 if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
2829 cpl_vector_set(selection, i, -1.0);
2833 cpl_vector_set(selection, i, 1.0);
2840 cpl_msg_info(__func__,
"Not enough frames for stability check");
2844 cpl_msg_info(__func__,
"Compute the differences lamp - dark");
2847 lamps_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2849 detmon_lg_config.llx,
2850 detmon_lg_config.lly,
2851 detmon_lg_config.urx,
2852 detmon_lg_config.ury,
2855 darks_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2857 detmon_lg_config.llx,
2858 detmon_lg_config.lly,
2859 detmon_lg_config.urx,
2860 detmon_lg_config.ury,
2863 nb_darks=cpl_imagelist_get_size(darks_data);
2864 if(nb_darks==nb_lamps) {
2865 skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
2867 cpl_image* master_dark=cpl_imagelist_collapse_median_create(darks_data);
2868 cpl_imagelist_subtract_image(lamps_data,master_dark);
2869 cpl_image_delete(master_dark);
2872 cpl_msg_info(__func__,
"Check the lamp stability");
2873 stab_levels = cpl_malloc(dit_stab *
sizeof(
double));
2875 for (i=0; i<nb_lamps; i++) {
2876 if (cpl_vector_get(selection, i) < 0) {
2878 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
2884 for (i=1; i<dit_stab; i++) {
2885 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
2886 detmon_lg_config.lamp_stability)
2887 detmon_lg_config.lamp_stability =
2888 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
2893 if (detmon_lg_config.lamp_stability > 0.01) {
2894 cpl_msg_warning(__func__,
2895 "Lamp stability level %g difference too high - proceed anyway",detmon_lg_config.lamp_stability);
2902 cpl_vector_delete(selection);
2903 cpl_imagelist_delete(lamps_data);
2904 cpl_imagelist_delete(darks_data);
2905 cpl_free(stab_levels);
2907 return cpl_error_get_code();
2934static cpl_error_code
2935detmon_lg_reduce_dit(
const cpl_frameset * set_on,
2936 int* index_on,
double* exptime_on,
2939 const cpl_frameset * set_off,
2940 int * index_off,
double* exptime_off,
2941 int* next_on,
int* next_off,
2942 cpl_table * linear_table,
2943 cpl_table * gain_table,
2944 cpl_imagelist * linearity_inputs,
2945 cpl_propertylist * qclist,
2946 cpl_boolean opt_nir,
2947 cpl_imagelist * autocorr_images,
2948 cpl_imagelist * diff_flats,
2949 cpl_imagelist * opt_offs,
2951 int* rows_linear_affected,
2952 int* rows_gain_affected)
2954 cpl_frameset * pair_on = NULL;
2955 cpl_frameset * pair_off = NULL;
2956 cpl_imagelist * ons = NULL;
2957 cpl_imagelist * offs = NULL;
2958 cpl_boolean follow = CPL_TRUE;
2959 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
2963 double current_dit = 0;
2965 const char * filename;
2967 cpl_propertylist * plist = NULL;
2968 cpl_propertylist* pDETlist = NULL;
2970 mode = detmon_lg_config.collapse ?
2971 mode | IRPLIB_GAIN_COLLAPSE | IRPLIB_LIN_COLLAPSE:
2972 mode | IRPLIB_GAIN_NO_COLLAPSE | IRPLIB_LIN_NO_COLLAPSE;
2973 mode = detmon_lg_config.pix2pix ?
2974 mode | IRPLIB_LIN_PIX2PIX : mode;
2976 mode | IRPLIB_GAIN_NIR | IRPLIB_LIN_NIR :
2977 mode | IRPLIB_GAIN_OPT | IRPLIB_LIN_OPT ;
2981 skip_if(detmon_pair_extract_next(set_on, index_on, next_on, exptime_on, &pair_on, detmon_lg_config.tolerance));
2982 current_dit = exptime_on[*next_on - 1];
2985 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2986 skip_if(ons == NULL);
2987 cpl_msg_debug(cpl_func,
" Loaded ON images: %" CPL_SIZE_FORMAT
2988 ", exptime[%f]",cpl_imagelist_get_size(ons), current_dit );
2989 if(cpl_imagelist_get_size(ons) != 2)
2991 cpl_msg_error(cpl_func,
"cannot take ON pair, number of images[%"
2992 CPL_SIZE_FORMAT
"]", cpl_imagelist_get_size(ons));
2995 if(detmon_lg_config.filter > 0)
2998 cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
2999 detmon_lg_config.llx,
3000 detmon_lg_config.lly,
3001 detmon_lg_config.urx,
3002 detmon_lg_config.ury);
3004 cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
3005 detmon_lg_config.llx,
3006 detmon_lg_config.lly,
3007 detmon_lg_config.urx,
3008 detmon_lg_config.ury);
3012 if ( med1 > (
double)detmon_lg_config.filter ||
3013 med2 > (
double)detmon_lg_config.filter)
3016 cpl_table_select_row(gain_table, dit_nb);
3017 cpl_table_select_row(linear_table, dit_nb);
3019 cpl_msg_warning(cpl_func,
"Frames of EXPTIME nb %d "
3020 "will not be taken into account for computation "
3021 "as the median of the on frames computed on the "
3022 "user defined region [%d,%d,%d,%d] are above "
3023 "--filter threshold (%d)",
3025 detmon_lg_config.llx,
3026 detmon_lg_config.lly,
3027 detmon_lg_config.urx,
3028 detmon_lg_config.ury,
3029 detmon_lg_config.filter);
3033 if (follow || detmon_lg_config.filter < 0)
3041 if(!detmon_lg_config.collapse)
3058 if (!strcmp(detmon_lg_config.method,
"MED") ||
3059 cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
3061 skip_if(detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off, detmon_lg_config.tolerance));
3065 skip_if(detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
3068 cpl_msg_debug(cpl_func,
" Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
3069 offs = detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
3071 skip_if(offs == NULL);
3072 skip_if(cpl_error_get_code());
3075 offs = (cpl_imagelist *) opt_offs;
3079 if(detmon_lg_config.rescale)
3081 skip_if(detmon_lg_rescale(ons));
3082 if (!detmon_lg_config.collapse &&
3083 !strcmp(detmon_lg_config.method,
"MED"))
3084 skip_if(detmon_lg_rescale(offs));
3089 cpl_frame_get_filename(cpl_frameset_get_position_const(pair_on, 0));
3090 skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
3094 pDETlist = cpl_propertylist_new();
3095 cpl_propertylist_copy_property_regexp(pDETlist, plist,
"DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
3098 irplib_table_create_column(gain_table, pDETlist);
3099 irplib_table_create_column(linear_table, pDETlist);
3102 if(opt_nir == NIR) {
3103 c_dit = detmon_pfits_get_dit(plist);
3104 c_ndit = irplib_pfits_get_ndit(plist);
3106 c_dit = irplib_pfits_get_exptime(plist);
3118 cpl_msg_info(cpl_func,
"Computing GAIN for EXPTIME value nb %d",
3122 if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
3124 cpl_table_erase_column(gain_table,
"MEAN_OFF1");
3125 cpl_table_erase_column(gain_table,
"MEAN_OFF2");
3126 cpl_table_erase_column(gain_table,
"SIG_OFF_DIF");
3127 cpl_table_erase_column(gain_table,
"GAIN");
3128 cpl_table_erase_column(gain_table,
"GAIN_CORR");
3129 cpl_table_new_column(gain_table,
"MEAN_OFF", CPL_TYPE_DOUBLE);
3133 skip_if(detmon_gain_table_fill_row(gain_table,
3136 diff_flats, ons, offs,
3137 detmon_lg_config.kappa,
3138 detmon_lg_config.niter,
3139 detmon_lg_config.llx,
3140 detmon_lg_config.lly,
3141 detmon_lg_config.urx,
3142 detmon_lg_config.ury,
3145 detmon_lg_config.gain_threshold,
3146 dit_nb, mode, rows_gain_affected));
3149 skip_if(detmon_check_saturation_on_pair(autocorr_images,
3151 detmon_lg_config.kappa,
3152 detmon_lg_config.niter,
3153 detmon_lg_config.llx,
3154 detmon_lg_config.lly,
3155 detmon_lg_config.urx,
3156 detmon_lg_config.ury,
3157 detmon_lg_config.saturation_limit,
3158 dit_nb, mode, rows_linear_affected));
3161 if (*rows_gain_affected)
3164 skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
3166 cpl_msg_info(cpl_func,
"Linearity reduction for nb %d",
3169 if (*rows_linear_affected) {
3170 skip_if(detmon_lin_table_fill_row(linear_table, c_dit,
3171 linearity_inputs, ons, offs,
3172 detmon_lg_config.llx,
3173 detmon_lg_config.lly,
3174 detmon_lg_config.urx,
3175 detmon_lg_config.ury,
3176 dit_nb, *dit_nskip, mode));
3178 skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
3190 if(opt_nir == OPT &&
3191 *rows_linear_affected != 0 ) {
3192 detmon_opt_contamination(ons, offs, mode, qclist);
3199 cpl_frameset_delete(pair_on);
3200 cpl_imagelist_delete(ons);
3202 if(!detmon_lg_config.collapse ) {
3203 cpl_imagelist_delete(offs);
3206 if(!detmon_lg_config.collapse) {
3207 cpl_frameset_delete(pair_off);
3210 cpl_propertylist_delete(plist);
3211 cpl_propertylist_delete(pDETlist);
3212 return cpl_error_get_code();
3222static cpl_error_code
3223detmon_add_adl_column(cpl_table * table,
3224 cpl_boolean opt_nir)
3226 cpl_error_code error;
3227 double mean_med_dit;
3230 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
3232 mean_med_dit = cpl_table_get_column_mean(table,
"MED_DIT");
3234 dits = cpl_table_get_data_double(table,
"EXPTIME");
3236 dits = cpl_table_get_data_double(table,
"DIT");
3238 error = cpl_table_copy_data_double(table,
"ADL", dits);
3239 cpl_ensure_code(!error, error);
3240 error = cpl_table_multiply_scalar(table,
"ADL", mean_med_dit);
3241 cpl_ensure_code(!error, error);
3243 return cpl_error_get_code();
3255static cpl_error_code
3256detmon_lg_reduce_init(cpl_table * gain_table,
3257 cpl_table * linear_table,
3258 cpl_imagelist ** linearity_inputs,
3259 const cpl_boolean opt_nir)
3261 skip_if(detmon_gain_table_create(gain_table, opt_nir));
3262 skip_if(detmon_lin_table_create(linear_table, opt_nir));
3264 if(detmon_lg_config.pix2pix) {
3265 *linearity_inputs = cpl_imagelist_new();
3266 skip_if(*linearity_inputs == NULL);
3271 return cpl_error_get_code();
3282detmon_pfits_get_dit(
const cpl_propertylist * plist)
3284 if (cpl_propertylist_has(plist,
"ESO DET DIT")) {
3286 return irplib_pfits_get_prop_double(plist,
"ESO DET DIT");
3289 return irplib_pfits_get_prop_double(plist,
"ESO DET SEQ1 DIT");
3291 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"FITS key "
3292 "ESO DET DIT or ESO DET DIT not found");
3304detmon_pfits_get_dit_opt(
const cpl_propertylist * plist)
3306 if (cpl_propertylist_has(plist,
"ESO DET WIN1 UIT1")) {
3308 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3309 }
else if (cpl_propertylist_has(plist,
"ESO DET UIT1")) {
3311 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3314 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"FITS key "
3315 "ESO DET WIN1 UIT1 or ESO DET UIT1 not found");
3325static cpl_propertylist*
3326detmon_load_pro_keys(
const char* NAME_O)
3328 cpl_propertylist* pro_keys=NULL;
3329 pro_keys=cpl_propertylist_load_regexp(NAME_O,0,
"^(ESO PRO)",0);
3334static double irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
3335 const char* prop_name)
3338 dit = cpl_propertylist_get_double(plist, prop_name);
3339 if(cpl_error_get_code() != CPL_ERROR_NONE)
3341 cpl_msg_error(cpl_func,
"Cannot read property '%s', err[%s]",
3342 prop_name, cpl_error_get_where());
3347static cpl_error_code
3348detmon_gain_compute_qc(
double kappa,
int nclip,
const int pos,
3349 const cpl_imagelist* offs,
unsigned mode,
3350 double avg_on1,
double avg_on2,
3351 double avg_off1,
double avg_off2,
3352 double sig_off_dif,
int c_ndit,
3353 double autocorr, cpl_image* on_dif,
3354 cpl_table* gain_table)
3359 double avg_on_dif, sig_on_dif;
3360 irplib_ksigma_clip(on_dif, 1, 1, cpl_image_get_size_x(on_dif),
3361 cpl_image_get_size_y(on_dif), kappa, nclip, 1e-5,
3362 &avg_on_dif, &sig_on_dif);
3364 cpl_table_set_double(gain_table,
"SIG_ON_DIF", pos,
3366 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3367 double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
3370 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
3373 = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
3377 const double gain = double_adu / (c_ndit * sigma);
3379 const double gain_corr = gain / (autocorr);
3381 skip_if(cpl_table_set_double(gain_table,
"GAIN", pos, gain));
3383 cpl_table_set_double(gain_table,
"GAIN_CORR", pos,
3387 skip_if(cpl_table_set_double(gain_table,
"AUTOCORR", pos, autocorr));
3388 skip_if(cpl_table_set_double(gain_table,
"ADU", pos, double_adu / 2));
3391 cpl_table_set_double(gain_table,
"Y_FIT", pos,
3392 c_ndit * sig_on_dif * sig_on_dif));
3394 cpl_table_set_double(gain_table,
"Y_FIT_CORR", pos,
3395 c_ndit * sig_on_dif * sig_on_dif));
3396 skip_if(cpl_table_set_double(gain_table,
"X_FIT", pos, double_adu));
3398 cpl_table_set_double(gain_table,
"X_FIT_CORR", pos,
3399 double_adu / autocorr));
3403 return cpl_error_get_code();
3407detmon_gain_prepare_autocorr(
unsigned mode,
const int pos,
3408 int m,
int n, cpl_imagelist* diff_flats,
3409 cpl_image* on_dif, cpl_imagelist* autocorr_images)
3411 double autocorr = 1.0;
3413 if (mode & IRPLIB_GAIN_WITH_AUTOCORR) {
3415 cpl_image * diff = cpl_image_duplicate(on_dif);
3416 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
3418 if (autocorr_images) {
3419 cpl_image * corr = NULL;
3420 autocorr = detmon_autocorr_factor(on_dif, &corr, m, n);
3422 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
3425 detmon_lg_add_empty_image(autocorr_images, pos);
3429 autocorr = detmon_autocorr_factor(on_dif, NULL, m, n);
3431 autocorr = isnan(autocorr) ? 1.0 : autocorr;
3439detmon_gain_prepare_table(
const cpl_imagelist* offs,
unsigned mode,
int llx,
3440 int lly,
int urx,
int ury,
double kappa,
int nclip,
3441 double std,
const int pos,
3442 cpl_table* gain_table,
double* avg_off2,
3443 double* sig_off_dif)
3445 double avg_off1 = 0.0;
3452 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3455 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3456 llx, lly, urx, ury, kappa, nclip, 1e-5,
3458 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF", pos, avg_off1));
3461 else if ((mode & IRPLIB_GAIN_NO_COLLAPSE)
3462 || (pos == 0 && mode & IRPLIB_GAIN_COLLAPSE)) {
3463 cpl_image * off_dif = NULL;
3466 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3467 llx, lly, urx, ury, kappa, nclip, 1e-5,
3469 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3471 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 1),
3472 llx, lly, urx, ury, kappa, nclip, 1e-5,
3474 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3475 off_dif = detmon_subtract_create_window(
3476 cpl_imagelist_get_const(offs, 0),
3477 cpl_imagelist_get_const(offs, 1), llx, lly, urx, ury);
3478 skip_if(off_dif == NULL);
3479 irplib_ksigma_clip(off_dif, 1, 1, cpl_image_get_size_x(off_dif),
3480 cpl_image_get_size_y(off_dif), kappa, nclip, 1e-5,
3481 &avg_off_dif, sig_off_dif);
3482 cpl_image_delete(off_dif);
3484 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3487 else if (pos > 0 && (mode & IRPLIB_GAIN_COLLAPSE)) {
3490 avg_off1 = cpl_table_get_double(gain_table,
"MEAN_OFF1", 0, &status);
3491 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3492 *avg_off2 = cpl_table_get_double(gain_table,
"MEAN_OFF2", 0, &status);
3493 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3494 *sig_off_dif = cpl_table_get_double(gain_table,
"SIG_OFF_DIF", 0,
3497 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3542static cpl_error_code
3543detmon_gain_table_fill_row(cpl_table * gain_table,
3544 double c_dit,
int c_ndit,
3545 cpl_imagelist * autocorr_images,
3546 cpl_imagelist * diff_flats,
3547 const cpl_imagelist * ons,
3548 const cpl_imagelist * offs,
3549 double kappa,
int nclip,
3550 int llx,
int lly,
int urx,
int ury,
3552 double gain_threshold,
3553 int pos,
unsigned mode,
int* rows_gain_affected)
3555 const cpl_image *image;
3556 cpl_image *on_dif = NULL;
3558 double avg_on1, avg_on2;
3559 double avg_off1, avg_off2;
3562 cpl_table_set(gain_table,
"FLAG", pos, 1);
3563 if (mode & IRPLIB_GAIN_NIR)
3565 cpl_table_set(gain_table,
"DIT", pos, c_dit);
3566 cpl_table_set(gain_table,
"NDIT", pos, c_ndit);
3567 }
else if (mode & IRPLIB_GAIN_OPT)
3569 cpl_table_set(gain_table,
"EXPTIME", pos, c_dit);
3572 cpl_msg_error(cpl_func,
"Mandatory mode (OPT or NIR) not provided");
3575 if(*rows_gain_affected == 0)
3577 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3578 cpl_table_set(gain_table,
"FLAG", pos, 0);
3579 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3584 detmon_lg_add_empty_image(diff_flats, pos);
3586 if (autocorr_images)
3588 detmon_lg_add_empty_image(autocorr_images, pos);
3591 return cpl_error_get_code();
3593 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3594 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3595 nclip, 1e-5, &avg_on1, &std));
3596 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3597 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3598 nclip, 1e-5, &avg_on2, &std));
3601 (avg_on1 > gain_threshold) ||
3602 (avg_on2 > gain_threshold)
3608 if ( (avg_on1 > gain_threshold) || (avg_on2 > gain_threshold) )
3610 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the gain_theshold parameter, "
3611 "the frames would not be taken into calculation");
3613 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3614 avg_on1, avg_on2, gain_threshold);
3617 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3618 cpl_table_set(gain_table,
"FLAG", pos, 0);
3619 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3624 detmon_lg_add_empty_image(diff_flats, pos);
3626 if (autocorr_images)
3628 detmon_lg_add_empty_image(autocorr_images, pos);
3631 *rows_gain_affected = 0;
3639 *rows_gain_affected = 1;
3640 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON1", pos, avg_on1));
3641 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON2", pos, avg_on2));
3644 detmon_subtract_create_window(cpl_imagelist_get_const(ons, 0),
3645 cpl_imagelist_get_const(ons, 1),
3646 llx, lly, urx, ury);
3647 skip_if(on_dif == NULL);
3649 autocorr = detmon_gain_prepare_autocorr(mode, pos, m, n,
3650 diff_flats, on_dif, autocorr_images);
3652 avg_off1 = detmon_gain_prepare_table(offs, mode, llx, lly, urx, ury,
3653 kappa, nclip, std, pos, gain_table, &avg_off2,
3656 detmon_gain_compute_qc(kappa, nclip, pos, offs, mode,
3657 avg_on1, avg_on2, avg_off1, avg_off2,
3658 sig_off_dif, c_ndit, autocorr, on_dif,
3663 cpl_image_delete(on_dif);
3665 return cpl_error_get_code();
3692static cpl_error_code
3693detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
3694 cpl_imagelist * diff_flats,
3695 const cpl_imagelist * ons,
3696 double kappa,
int nclip,
3697 int llx,
int lly,
int urx,
int ury,
3698 double saturation_limit,
3699 const int pos,
unsigned mode,
int* rows_linear_affected)
3701 const cpl_image *image;
3703 double avg_on1, avg_on2;
3706 if(*rows_linear_affected == 0)
3708 cpl_msg_info(cpl_func,
"For linearity skip the frame #%d", pos + 1);
3709 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3713 detmon_lg_add_empty_image(diff_flats, pos);
3715 if (autocorr_images)
3717 detmon_lg_add_empty_image(autocorr_images, pos);
3720 return cpl_error_get_code();
3722 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3723 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3724 nclip, 1e-5, &avg_on1, &std));
3725 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3726 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3727 nclip, 1e-5, &avg_on2, &std));
3730 (avg_on1 > saturation_limit) ||
3731 (avg_on2 > saturation_limit)
3737 if ( (avg_on1 > saturation_limit) || (avg_on2 > saturation_limit) )
3739 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the saturation_limit parameter, "
3740 "the frames would not be taken into calculation");
3742 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3743 avg_on1, avg_on2, saturation_limit);
3746 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3747 *rows_linear_affected = 0;
3754 return cpl_error_get_code();
3770detmon_bpixs(
const cpl_imagelist * coeffs,
3777 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
3784 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
3785 cpl_image_get_size_y(first));
3787 cpl_image *bpm = NULL;
3790 int size = cpl_imagelist_get_size(coeffs);
3793 bpm = cpl_image_new(cpl_image_get_size_x(first),
3794 cpl_image_get_size_y(first),
3799 for(
int i = 0; i < size; i++) {
3800 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
3802 cpl_stats* stats = cpl_stats_new_from_image(cur_coeff,
3803 CPL_STATS_MEAN | CPL_STATS_STDEV);
3804 double cur_mean = cpl_stats_get_mean(stats);
3805 double cur_stdev = cpl_stats_get_stdev(stats);
3807 double lo_cut = cur_mean - kappa * cur_stdev;
3808 double hi_cut = cur_mean + kappa * cur_stdev;
3810 cpl_mask* cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
3811 cpl_mask_not(cur_mask);
3814 cpl_image* cur_image = cpl_image_new_from_mask(cur_mask);
3815 double p = pow(2, i);
3816 cpl_image_power(cur_image, p);
3817 cpl_image_add(bpm, cur_image);
3818 cpl_image_delete(cur_image);
3821 cpl_mask_or(mask, cur_mask);
3823 cpl_mask_delete(cur_mask);
3824 cpl_stats_delete(stats);
3828 bpm = cpl_image_new_from_mask(mask);
3831 *nbpixs = cpl_mask_count(mask);
3833 cpl_mask_delete(mask);
3960detmon_autocorr_factor(
const cpl_image * image,
3961 cpl_image ** autocorr_image,
int m,
int n)
3963 cpl_image * mycorr_image = NULL;
3964 double autocorr = 0;
3967 mycorr_image = detmon_image_correlate(image, image, m, n);
3969 if (cpl_error_get_code() == CPL_ERROR_UNSUPPORTED_MODE)
3971 cpl_msg_warning(cpl_func,
"FFTW is not supported by CPL, autocorrelation "
3972 "would be computed using internal implementation");
3975 cpl_image_delete(mycorr_image);
3976 mycorr_image = detmon_autocorrelate(image, m, n);
3978 if(mycorr_image == NULL) {
3982 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
3984 autocorr = cpl_image_get_flux(mycorr_image);
3986 if (autocorr_image) *autocorr_image = mycorr_image;
3987 else cpl_image_delete(mycorr_image);
3992static cpl_propertylist*
3993detmon_lg_extract_qclist_4plane(cpl_propertylist* linc_qclist,
const int ip)
3996 cpl_propertylist* sub_set=NULL;
3999 sub_set=cpl_propertylist_new();
4000 qc_key=cpl_sprintf(
"QC LIN COEF%d",ip);
4001 cpl_propertylist_copy_property_regexp(sub_set,linc_qclist,qc_key,0);
4018static cpl_error_code
4019detmon_lg_extract_extention_header(cpl_frameset* frameset,
4020 cpl_propertylist* gaint_qclist,
4021 cpl_propertylist* lint_qclist,
4022 cpl_propertylist* linc_qclist,
4023 cpl_propertylist* bpm_qclist,
4027 cpl_propertylist * xplist = NULL;
4029 const char * filename =
4030 cpl_frame_get_filename(cpl_frameset_get_position(frameset, 0));
4032 xplist = cpl_propertylist_load_regexp(filename, whichext,
4033 "ESO DET|EXTNAME", 0);
4034 if (detmon_lg_config.exts >= 0)
4037 cpl_property* propExtname = NULL;
4038 propExtname = cpl_propertylist_get_property(xplist,
"EXTNAME");
4040 if (NULL != propExtname)
4042 propExtname = cpl_property_duplicate(propExtname);
4044 cpl_propertylist_delete(xplist);
4046 if (NULL != propExtname)
4048 xplist = cpl_propertylist_new();
4049 cpl_propertylist_append_property(xplist, propExtname);
4050 cpl_property_delete(propExtname);
4055 cpl_propertylist_append(gaint_qclist, xplist);
4056 cpl_propertylist_append(lint_qclist, xplist);
4057 cpl_propertylist_append(linc_qclist, xplist);
4058 cpl_propertylist_append(bpm_qclist, xplist);
4059 cpl_propertylist_delete(xplist);
4062 return cpl_error_get_code();
4079static cpl_error_code
4080detmon_lg_save_table_with_pro_keys(cpl_table* table,
4082 cpl_propertylist* xheader,
4083 unsigned CPL_IO_MODE)
4086 cpl_propertylist* pro_keys=NULL;
4088 pro_keys=detmon_load_pro_keys(name_o);
4089 cpl_propertylist_append(xheader,pro_keys);
4091 if(CPL_IO_MODE==CPL_IO_DEFAULT) {
4092 cpl_propertylist * pri_head=cpl_propertylist_load(name_o,0);
4093 cpl_table_save(table, pri_head,xheader,name_o,
4095 cpl_propertylist_delete(pri_head);
4098 cpl_table_save(table,NULL,xheader,name_o,
4101 cpl_propertylist_delete(pro_keys);
4103 return cpl_error_get_code();
4115static cpl_error_code
4116detmon_lg_save_image_with_pro_keys(cpl_image* image,
4118 cpl_propertylist* xheader)
4121 cpl_propertylist* pro_keys=NULL;
4122 pro_keys=detmon_load_pro_keys(name_o);
4123 cpl_propertylist_append(xheader,pro_keys);
4125 cpl_image_save(image,name_o, CPL_BPP_IEEE_FLOAT,
4126 xheader,CPL_IO_EXTEND);
4127 cpl_propertylist_delete(pro_keys);
4130 return cpl_error_get_code();
4142static cpl_error_code
4143detmon_lg_save_imagelist_with_pro_keys(cpl_imagelist* imagelist,
4145 cpl_propertylist* xheader)
4148 cpl_propertylist* pro_keys=NULL;
4149 pro_keys=detmon_load_pro_keys(name_o);
4150 cpl_propertylist_append(xheader,pro_keys);
4152 cpl_imagelist_save(imagelist,name_o, CPL_BPP_IEEE_FLOAT,
4153 xheader,CPL_IO_EXTEND);
4155 cpl_propertylist_delete(pro_keys);
4158 return cpl_error_get_code();
4178static cpl_error_code
4179detmon_lg_save_plane(
const cpl_parameterlist * parlist,
4180 cpl_frameset* frameset,
4181 const cpl_frameset * usedframes,
4183 const char* recipe_name,
4184 cpl_propertylist* mypro_coeffscube,
4185 cpl_propertylist* linc_plane_qclist,
4186 const char* package,
4190 if(detmon_lg_config.exts == 0) {
4191 cpl_propertylist* plist=NULL;
4192 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4194 CPL_BPP_IEEE_FLOAT, recipe_name,
4195 mypro_coeffscube, NULL,
4197 plist=cpl_propertylist_load(NAME_O,0);
4198 cpl_image_save(plane,NAME_O, CPL_BPP_IEEE_FLOAT,
4199 plist,CPL_IO_DEFAULT);
4200 cpl_propertylist_delete(plist);
4202 }
else if(detmon_lg_config.exts > 0) {
4203 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4205 CPL_BPP_IEEE_FLOAT, recipe_name,
4206 mypro_coeffscube, NULL,
4209 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4213 cpl_dfs_save_image(frameset, NULL, parlist,
4214 usedframes,NULL, NULL,
4215 CPL_BPP_IEEE_FLOAT, recipe_name,
4216 mypro_coeffscube, NULL,
4218 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4221 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4227 return cpl_error_get_code();
4250static cpl_error_code
4251detmon_lg_save_cube(
const cpl_parameterlist * parlist,
4252 cpl_frameset* frameset,
4253 const cpl_frameset * usedframes,
4255 const char* recipe_name,
4256 cpl_propertylist* mypro_coeffscube,
4257 cpl_propertylist* linc_qclist,
4258 const char* package,
4260 cpl_imagelist* coeffs)
4263 if(detmon_lg_config.exts == 0) {
4264 cpl_propertylist_append(mypro_coeffscube, linc_qclist);
4265 detmon_lg_dfs_save_imagelist
4266 (frameset, parlist, usedframes, coeffs,
4267 recipe_name, mypro_coeffscube, package,
4269 }
else if(detmon_lg_config.exts > 0) {
4270 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4272 CPL_BPP_IEEE_FLOAT, recipe_name,
4273 mypro_coeffscube, NULL,
4276 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4280 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4282 CPL_BPP_IEEE_FLOAT, recipe_name,
4283 mypro_coeffscube, NULL,
4286 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4288 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4291 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4293 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4297 return cpl_error_get_code();
4301detmon_lg_set_paf_name_and_header(cpl_frame* ref_frame,
4302 int flag_sets,
int which_set,
4304 const char* paf_suf,
4305 cpl_propertylist** plist)
4307 char * paf_name=NULL;
4309 if(detmon_lg_config.exts >= 0)
4311 *plist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4312 detmon_lg_config.exts);
4316 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4320 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4321 detmon_lg_config.pafname, paf_suf,which_set);
4326 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4332 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4333 detmon_lg_config.pafname, paf_suf,whichext);
4337 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4338 detmon_lg_config.pafname,paf_suf,
4339 which_set, whichext);
4348detmon_lg_set_paf_name_and_header_ext(cpl_frame* ref_frame,
4349 int flag_sets,
int which_set,
4351 const char* paf_suf,
4352 cpl_propertylist** plist)
4354 char* paf_name=NULL;
4356 if(detmon_lg_config.exts >= 0)
4358 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4359 detmon_lg_config.exts);
4363 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4366 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4367 detmon_lg_config.pafname, paf_suf,which_set);
4371 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4375 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4376 detmon_lg_config.pafname, paf_suf,whichext);
4379 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4380 detmon_lg_config.pafname,paf_suf,
4381 which_set, whichext);
4388static cpl_error_code
4389detmon_lg_save_paf_product(cpl_frame* ref_frame,
int flag_sets,
4390 int which_set,
int whichext,
4391 const char* pafregexp,
4392 const char* procatg,
4393 const char* pipeline_name,
4394 const char* recipe_name,
4395 const char* paf_suf,
4396 cpl_propertylist* qclist,
4401 char* paf_name=NULL;
4402 cpl_propertylist* plist=NULL;
4403 cpl_propertylist* paflist = NULL;
4404 cpl_propertylist* mainplist=NULL;
4406 mainplist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0);
4408 paf_name=detmon_lg_set_paf_name_and_header(ref_frame,flag_sets,
4412 paf_name=detmon_lg_set_paf_name_and_header_ext(ref_frame,flag_sets,
4418 paflist = cpl_propertylist_new();
4419 cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,procatg);
4422 cpl_propertylist_copy_property_regexp(paflist, plist,pafregexp, 0);
4423 cpl_propertylist_copy_property_regexp(paflist, mainplist,pafregexp, 0);
4424 cpl_propertylist_append(paflist,qclist);
4427 cpl_dfs_save_paf(pipeline_name, recipe_name,paflist,paf_name);
4430 cpl_propertylist_delete(mainplist);
4431 cpl_propertylist_delete(paflist);
4432 cpl_propertylist_delete(plist);
4435 return cpl_error_get_code();
4472static cpl_error_code
4473detmon_lg_save(
const cpl_parameterlist * parlist,
4474 cpl_frameset * frameset,
4475 const char *recipe_name,
4476 const char *pipeline_name,
4477 const char *pafregexp,
4478 const cpl_propertylist * pro_lintbl,
4479 const cpl_propertylist * pro_gaintbl,
4480 const cpl_propertylist * pro_coeffscube,
4481 const cpl_propertylist * pro_bpm,
4482 const cpl_propertylist * pro_corr,
4483 const cpl_propertylist * pro_diff,
4484 const char *package,
4485 cpl_imagelist * coeffs,
4486 cpl_table * gain_table,
4487 cpl_table * linear_table,
4489 cpl_imagelist * autocorr_images,
4490 cpl_imagelist * diff_flats,
4491 cpl_propertylist * gaint_qclist,
4492 cpl_propertylist * lint_qclist,
4493 cpl_propertylist * linc_qclist,
4494 cpl_propertylist * bpm_qclist,
4495 const int flag_sets,
4496 const int which_set,
4497 const cpl_frameset * usedframes,
4501 cpl_frame *ref_frame;
4502 cpl_propertylist *plist = NULL;
4503 cpl_propertylist *mainplist = NULL;
4509 cpl_propertylist * xplist = NULL;
4511 cpl_propertylist* linc_plane_qclist=NULL;
4512 cpl_image* plane=NULL;
4514 char* pcatg_plane=NULL;
4516 cpl_propertylist * mypro_lintbl =
4517 cpl_propertylist_duplicate(pro_lintbl);
4518 cpl_propertylist * mypro_gaintbl =
4519 cpl_propertylist_duplicate(pro_gaintbl);
4520 cpl_propertylist * mypro_coeffscube =
4521 cpl_propertylist_duplicate(pro_coeffscube);
4522 cpl_propertylist * mypro_bpm =
4523 cpl_propertylist_duplicate(pro_bpm);
4524 cpl_propertylist * mypro_corr =
4525 cpl_propertylist_duplicate(pro_corr);
4526 cpl_propertylist * mypro_diff =
4527 cpl_propertylist_duplicate(pro_diff);
4529 const char * procatg_lintbl =
4530 cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
4532 const char * procatg_gaintbl =
4533 cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
4535 const char * procatg_coeffscube =
4536 cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
4537 const char * procatg_bpm =
4538 cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
4542 detmon_lg_extract_extention_header(frameset,gaint_qclist,lint_qclist,
4543 linc_qclist,bpm_qclist,whichext);
4548 ref_frame = cpl_frameset_get_position(frameset, 0);
4550 skip_if((mainplist =
4551 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4557 cpl_msg_info(cpl_func,
"Write the LINEARITY TABLE");
4560 NAME_O=cpl_sprintf(
"%s_linearity_table.fits", recipe_name);
4562 NAME_O=cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name,
4566 if (detmon_lg_config.exts >= 0) {
4568 cpl_propertylist_append(mypro_lintbl, lint_qclist);
4569 skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,
4570 linear_table,NULL, recipe_name,
4571 mypro_lintbl, NULL, package, NAME_O));
4573 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4574 lint_qclist,CPL_IO_DEFAULT);
4579 skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL,
4580 linear_table,lint_qclist, recipe_name,
4581 mypro_lintbl,NULL, package, NAME_O));
4582 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4583 lint_qclist,CPL_IO_DEFAULT);
4590 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4591 lint_qclist,CPL_IO_EXTEND);
4594 irplib_free(&NAME_O);
4598 cpl_msg_info(cpl_func,
"Write the GAIN TABLE");
4601 NAME_O=cpl_sprintf(
"%s_gain_table.fits", recipe_name);
4603 NAME_O=cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name,
4607 if (detmon_lg_config.exts >= 0)
4611 cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
4612 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
4613 gain_table,NULL, recipe_name, mypro_gaintbl,
4614 NULL, package, NAME_O));
4615 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4616 gaint_qclist,CPL_IO_DEFAULT);
4624 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
4625 gaint_qclist, recipe_name, mypro_gaintbl,
4626 NULL, package, NAME_O));
4627 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4628 gaint_qclist,CPL_IO_DEFAULT);
4634 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4635 gaint_qclist,CPL_IO_EXTEND);
4639 if(detmon_lg_config.pix2pix)
4645 cpl_msg_info(cpl_func,
"Write the COEFFS FITS");
4646 irplib_free(&NAME_O);
4649 PREF_O=cpl_sprintf(
"%s_coeffs_cube", recipe_name);
4652 PREF_O=cpl_sprintf(
"%s_coeffs_cube_set%02d",
4653 recipe_name, which_set);
4655 if (detmon_lg_config.split_coeffs == 0) {
4656 NAME_O=cpl_sprintf(
"%s.fits", PREF_O);
4661 if(detmon_lg_config.split_coeffs != 0){
4664 nb_images = cpl_imagelist_get_size(coeffs);
4665 for(ip=0;ip<nb_images;ip++) {
4666 NAME_O=cpl_sprintf(
"%s_P%d.fits", PREF_O,ip);
4667 pcatg_plane=cpl_sprintf(
"COEFFS_CUBE_P%d",ip);
4668 cpl_propertylist_delete(mypro_coeffscube);
4669 mypro_coeffscube=cpl_propertylist_duplicate(pro_coeffscube);
4670 cpl_propertylist_set_string(mypro_coeffscube,CPL_DFS_PRO_CATG,
4672 linc_plane_qclist=detmon_lg_extract_qclist_4plane(linc_qclist,ip);
4673 cpl_propertylist_append(mypro_coeffscube, linc_plane_qclist);
4674 plane=cpl_imagelist_get(coeffs,ip);
4675 detmon_lg_save_plane(parlist,frameset,usedframes,whichext,
4676 recipe_name,mypro_coeffscube,
4677 linc_plane_qclist,package,NAME_O,plane);
4679 if(NULL!=linc_plane_qclist) {
4680 cpl_propertylist_delete(linc_plane_qclist);
4682 irplib_free(&NAME_O);
4687 detmon_lg_save_cube(parlist,frameset,usedframes,whichext,
4688 recipe_name,mypro_coeffscube,
4689 linc_qclist,package,NAME_O,coeffs);
4695 cpl_msg_info(cpl_func,
"Write the BAD PIXEL MAP");
4696 irplib_free(&NAME_O);
4700 NAME_O=cpl_sprintf(
"%s_bpm.fits", recipe_name);
4703 NAME_O=cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, which_set);
4708 if(detmon_lg_config.exts == 0) {
4709 cpl_propertylist_append(mypro_bpm, bpm_qclist);
4710 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
4711 CPL_BPP_IEEE_FLOAT, recipe_name,
4712 mypro_bpm, NULL, package,
4715 else if(detmon_lg_config.exts > 0)
4717 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4718 CPL_BPP_IEEE_FLOAT, recipe_name,
4719 mypro_bpm, NULL, package,
4721 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4727 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4728 CPL_BPP_IEEE_FLOAT, recipe_name,
4729 mypro_bpm, NULL, package,
4731 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4734 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4739 if(detmon_lg_config.intermediate)
4744 cpl_msg_info(cpl_func,
"Write the AUTOCORRS FITS");
4745 nb_images = cpl_imagelist_get_size(autocorr_images);
4746 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
4747 for(i = 0; i < nb_images; i++)
4749 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_corr);
4751 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4753 if(i < cpl_table_get_nrow(linear_table))
4755 ddit = cpl_table_get_double(linear_table,
4756 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4758 cpl_array_delete(pnames);
4761 irplib_free(&NAME_O);
4764 NAME_O=cpl_sprintf(
"%s_autocorr_%d.fits", recipe_name, i);
4765 assert(NAME_O != NULL);
4768 NAME_O=cpl_sprintf(
"%s_autocorr_%02d_set%02d.fits",
4769 recipe_name, i, which_set);
4770 assert(NAME_O != NULL);
4773 if(detmon_lg_config.exts > 0)
4775 cpl_propertylist* pextlist = cpl_propertylist_new();
4776 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4777 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4778 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4779 recipe_name, pplist, NULL,
4782 detmon_lg_save_image_with_pro_keys(
4783 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4785 cpl_propertylist_delete(pextlist);
4787 if(detmon_lg_config.exts == 0)
4789 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4790 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
4791 cpl_imagelist_get(autocorr_images, i),
4793 recipe_name, pplist, NULL, package,
4799 cpl_propertylist* pextlist = cpl_propertylist_new();
4800 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4803 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4804 usedframes, NULL,NULL,
4805 CPL_BPP_IEEE_FLOAT, recipe_name,
4809 detmon_lg_save_image_with_pro_keys(
4810 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4815 detmon_lg_save_image_with_pro_keys(
4816 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4818 cpl_propertylist_delete(pextlist);
4820 cpl_propertylist_delete (pplist);
4822 irplib_free(&NAME_O);
4831 cpl_msg_info(cpl_func,
"Write the DIFFS FITS");
4833 for(i = 0; i < nb_images; i++)
4835 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_diff);
4837 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4839 if(i < cpl_table_get_nrow(linear_table))
4841 ddit = cpl_table_get_double(linear_table,
4842 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4844 cpl_array_delete(pnames);
4849 NAME_O=cpl_sprintf(
"%s_diff_flat_%d.fits", recipe_name, i);
4852 NAME_O=cpl_sprintf(
"%s_diff_flat_%d_set%02d.fits",
4853 recipe_name, i, which_set);
4856 if(detmon_lg_config.exts > 0)
4858 cpl_propertylist* pextlist = cpl_propertylist_new();
4859 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4860 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT", ddit);
4861 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4862 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4864 mypro_diff, NULL,package, NAME_O));
4866 detmon_lg_save_image_with_pro_keys(
4867 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4869 cpl_propertylist_delete(pextlist);
4871 else if(detmon_lg_config.exts == 0)
4873 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4875 (frameset, NULL, parlist, usedframes, NULL,
4876 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
4877 recipe_name, pplist, NULL, package,
4882 cpl_propertylist* pextlist = cpl_propertylist_new();
4883 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4886 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT",ddit);
4888 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4889 usedframes, NULL,NULL,
4890 CPL_BPP_IEEE_FLOAT, recipe_name,
4891 mypro_diff, NULL,package, NAME_O));
4893 detmon_lg_save_image_with_pro_keys(
4894 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4899 detmon_lg_save_image_with_pro_keys(
4900 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4903 cpl_propertylist_delete(pextlist);
4905 cpl_propertylist_delete(pplist);
4906 irplib_free(&NAME_O);
4914 cpl_msg_info(cpl_func,
"Write the PAF file(s)");
4916 if(detmon_lg_config.pafgen) {
4918 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4919 pafregexp,procatg_gaintbl,
4920 pipeline_name,recipe_name,
4921 "qc01",gaint_qclist,0);
4923 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4924 pafregexp,procatg_lintbl,
4925 pipeline_name,recipe_name,
4926 "qc02",lint_qclist,0);
4928 if(detmon_lg_config.pix2pix)
4931 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4934 pipeline_name,recipe_name,
4935 "qc03",linc_qclist,1);
4937 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4938 whichext,pafregexp,procatg_bpm,
4939 pipeline_name,recipe_name,
4940 "qc04",bpm_qclist,1);
4945 cpl_msg_info(cpl_func,
"exit");
4947 cpl_propertylist_delete(xplist);
4949 cpl_propertylist_delete(plist);
4953 irplib_free(&NAME_O);
4955 cpl_free(pcatg_plane);
4956 cpl_propertylist_delete(mainplist);
4957 cpl_propertylist_delete(mypro_lintbl);
4958 cpl_propertylist_delete(mypro_gaintbl);
4959 cpl_propertylist_delete(mypro_coeffscube);
4960 cpl_propertylist_delete(mypro_bpm);
4961 cpl_propertylist_delete(mypro_corr);
4962 cpl_propertylist_delete(mypro_diff);
4964 return cpl_error_get_code();
4977static cpl_error_code
4978detmon_opt_contamination(
const cpl_imagelist * ons,
4979 const cpl_imagelist * offs,
4981 cpl_propertylist * qclist)
4989 struct rect rects[5] = {
4990 (
struct rect){ detmon_lg_config.llx1,
4991 detmon_lg_config.lly1,
4992 detmon_lg_config.urx1,
4993 detmon_lg_config.ury1},
4994 (
struct rect){ detmon_lg_config.llx2,
4995 detmon_lg_config.lly2,
4996 detmon_lg_config.urx2,
4997 detmon_lg_config.ury2},
4998 (
struct rect){ detmon_lg_config.llx3,
4999 detmon_lg_config.lly3,
5000 detmon_lg_config.urx3,
5001 detmon_lg_config.ury3},
5002 (
struct rect){ detmon_lg_config.llx4,
5003 detmon_lg_config.lly4,
5004 detmon_lg_config.urx4,
5005 detmon_lg_config.ury4},
5006 (
struct rect){ detmon_lg_config.llx5,
5007 detmon_lg_config.lly5,
5008 detmon_lg_config.urx5,
5009 detmon_lg_config.ury5},
5012 for (
size_t i = 0; i < 5; i++) {
5013 cpl_image * dif_avg;
5014 const cpl_image * off2;
5017 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
5018 off2 = cpl_imagelist_get_const(offs, 0);
5020 off2 = cpl_imagelist_get_const(offs, 1);
5022 dif_avg = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
5023 cpl_imagelist_get_const(offs, 0),
5024 cpl_imagelist_get_const(ons, 1),
5031 median = cpl_image_get_median(dif_avg);
5032 cpl_image_delete(dif_avg);
5035 sprintf(kname, DETMON_QC_CONTAM
"%zd", i + 1);
5037 if(cpl_propertylist_has(qclist,kname)){
5038 skip_if(cpl_propertylist_update_double(qclist,kname,median));
5040 skip_if(cpl_propertylist_append_double(qclist,kname,median));
5041 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
5047 return cpl_error_get_code();
5106detmon_lg_dfs_set_groups(cpl_frameset * set,
5107 const char *tag_on,
const char *tag_off)
5119 int nframes = cpl_frameset_get_size(set);
5122 for(
int i = 0; i < nframes; i++) {
5123 cpl_frame* cur_frame = cpl_frameset_get_position(set, i);
5124 const char* tag = cpl_frame_get_tag(cur_frame);
5127 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
5128 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
5148static cpl_error_code
5149detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist ** coeffs_ptr,
5150 cpl_image **bpms_ptr)
5166 cpl_image* dummy_bpm = cpl_image_new(detmon_lg_config.nx,
5167 detmon_lg_config.ny,
5169 cpl_imagelist* dummy_coeffs = cpl_imagelist_new();
5171 int* db_p = cpl_image_get_data_int(dummy_bpm);
5172 int* rb_p = cpl_image_get_data_int(*bpms_ptr);;
5173 float** dcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5174 float** rcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5175 int dlength = detmon_lg_config.nx;
5177 int rlength = detmon_lg_config.urx - detmon_lg_config.llx + 1;
5178 for (
int i = 0; i <= detmon_lg_config.order; i++)
5180 cpl_image* dummy_coeff = cpl_image_new(detmon_lg_config.nx,
5181 detmon_lg_config.ny,
5184 cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
5185 dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
5186 rcs_p[i] = cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
5189 for (
int i = detmon_lg_config.lly - 1; i < detmon_lg_config.ury; i++)
5191 for (
int j = detmon_lg_config.llx - 1; j < detmon_lg_config.urx; j++)
5193 shift_idx=(i - detmon_lg_config.lly + 1) * rlength +
5194 j - detmon_lg_config.llx + 1;
5195 *(db_p + i * dlength + j) = *(rb_p + shift_idx);
5196 for (
int k = 0; k <= detmon_lg_config.order; k++)
5198 *(dcs_p[k] + i * dlength + j) =
5199 *(rcs_p[k] + (i - detmon_lg_config.lly + 1) * rlength +
5200 j - detmon_lg_config.llx + 1);
5204 cpl_imagelist_delete(*coeffs_ptr);
5205 cpl_image_delete(*bpms_ptr);
5206 *coeffs_ptr = dummy_coeffs;
5207 *bpms_ptr = dummy_bpm;
5211 return cpl_error_get_code();
5248#ifdef DETMON_USE_DETECTOR_SHOTNOISE_MODEL
5271static cpl_error_code
5272detmon_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
5273 const double ron, cpl_image ** ima_errs)
5275 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
5276 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
5277 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
5278 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
5280 *ima_errs = cpl_image_duplicate(ima_data);
5282 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
5286 cpl_image_divide_scalar(*ima_errs, gain);
5287 cpl_image_add_scalar(*ima_errs, ron * ron);
5288 cpl_image_power(*ima_errs, 0.5);
5290 return cpl_error_get_code();
5295detmon_compute_badpixmap(cpl_boolean opt_nir,
const int nsets,
5296 const cpl_table* linear_table,
5297 const cpl_imagelist* linearity_inputs,
int nbpixs,
5298 cpl_vector* x, cpl_propertylist* gaint_qclist,
5299 cpl_image** bpms_ptr)
5305 if (opt_nir == NIR) {
5306 x = cpl_vector_wrap(nsets,
5307 (
double *) cpl_table_get_data_double_const(linear_table,
5311 x = cpl_vector_wrap(nsets,
5312 (
double *) cpl_table_get_data_double_const(linear_table,
5316 int sz = cpl_imagelist_get_size(linearity_inputs);
5317 double kappa = detmon_lg_config.kappa;
5318 int niter = detmon_lg_config.niter;
5319 int llx = detmon_lg_config.llx;
5320 int urx = detmon_lg_config.urx;
5321 int lly = detmon_lg_config.lly;
5322 int ury = detmon_lg_config.ury;
5324 const cpl_image *ima;
5328 cpl_imagelist* errors = cpl_imagelist_new();
5350 cpl_imagelist* linearity_scaled = cpl_imagelist_new();
5352 gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
5356 gain = (gain < 0) ? 1 : gain;
5362 for (
int i = 0; i < sz; i++) {
5363 ima = cpl_imagelist_get_const(linearity_inputs, i);
5371 irplib_ksigma_clip(ima, 1, 1, urx - llx + 1,
5372 ury - lly + 1, kappa, niter, 1e-5, &avg,
5377 if (avg < detmon_lg_config.saturation_limit) {
5385 cpl_image_get_mad(ima, &dmad);
5386 err = cpl_image_duplicate(ima);
5387 cpl_image_multiply_scalar(err, 0);
5388 cpl_image_add_scalar(err, dmad * CPL_MATH_STD_MAD);
5398 cpl_imagelist_set(errors, err, i);
5406 cpl_imagelist_set(linearity_scaled,
5407 cpl_image_duplicate(ima), i));
5415 cpl_imagelist_delete(errors);
5417 double pval = 0.001;
5452 nbpixs = cpl_image_get_flux(*bpms_ptr);
5455 cpl_imagelist_delete(linearity_scaled);
5456 cpl_vector_unwrap((cpl_vector*) x);
5473 skip_if(*bpms_ptr == NULL);
5491static cpl_image* detmon_lg_calc_noise_map(
const cpl_image *data,
5495 cpl_image *noiseImg = NULL;
5497 cpl_ensure(data, CPL_ERROR_NULL_INPUT, NULL);
5498 cpl_ensure(gain > 0.0, CPL_ERROR_ILLEGAL_INPUT, NULL);
5499 cpl_ensure(readnoise >= 0.0, CPL_ERROR_ILLEGAL_INPUT, NULL);
5501 noiseImg = cpl_image_duplicate(data);
5506 cpl_image_abs(noiseImg);
5507 cpl_image_multiply_scalar(noiseImg, gain);
5508 cpl_image_add_scalar(noiseImg, readnoise * readnoise);
5509 cpl_image_power(noiseImg, 0.5);
5515static cpl_mask* detmon_image_to_mask(cpl_image* bpm)
5517 cpl_ensure(bpm, CPL_ERROR_NULL_INPUT, NULL);
5519 cpl_size sx = cpl_image_get_size_x(bpm);
5520 cpl_size sy = cpl_image_get_size_y(bpm);
5522 cpl_mask* mask = cpl_mask_new(sx, sy);
5523 int* pbpm = cpl_image_get_data(bpm);
5524 cpl_binary* pmsk = cpl_mask_get_data(mask);
5525 for (cpl_size j = 0; j < sy; j++) {
5526 for (cpl_size i = 0; i < sx; i++) {
5527 if(pbpm[i+j*sx] != 0 ) {
5528 pmsk[i+j*sx] = CPL_BINARY_1;
5535static cpl_error_code
5536detmon_qc_lin_log(hdrl_imagelist* fit_coef, cpl_image* chi2,
5537 cpl_image* dof, cpl_mask* mask, cpl_propertylist* linc_qclist)
5542 cpl_image* image = NULL;
5543 cpl_image* error = NULL;
5547 for(cpl_size deg = 0; deg < planes; deg++)
5552 cpl_image_power(error, 2.);
5553 cpl_image_multiply(error, chi2);
5554 cpl_image_divide(error, dof);
5555 cpl_image_power(error, 0.5);
5557 bpm = cpl_image_set_bpm(image, mask);
5558 const double coeff = cpl_image_get_median(image);
5559 cpl_image_set_bpm(image, bpm);
5561 name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", (
int)deg);
5563 cpl_propertylist_append_double(linc_qclist, name_o1, coeff);
5564 cpl_propertylist_set_comment(linc_qclist, name_o1, DETMON_QC_LIN_COEF_C);
5569 name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", (
int)deg);
5571 bpm = cpl_image_set_bpm(error, mask);
5572 const double coeff_err = cpl_image_get_median(error);
5573 cpl_image_set_bpm(error, bpm);
5575 cpl_propertylist_append_double(linc_qclist, name_o2, coeff_err);
5576 cpl_propertylist_set_comment(linc_qclist, name_o2, DETMON_QC_LIN_COEF_ERR_C);
5583 return cpl_error_get_code();
5603static cpl_error_code
5604detmon_lg_reduce_all(
const cpl_table * linear_table,
5605 cpl_propertylist * gaint_qclist,
5606 cpl_propertylist * lint_qclist,
5607 cpl_propertylist * linc_qclist,
5608 cpl_propertylist * bpm_qclist,
5609 cpl_imagelist ** coeffs_ptr,
5610 cpl_image ** bpms_ptr,
5611 const cpl_imagelist * linearity_inputs,
5612 const cpl_table * gain_table,
5613 int which_ext, cpl_boolean opt_nir,
5618 const int linear_nsets = cpl_table_get_nrow(linear_table);
5619 const int gain_nsets = cpl_table_get_nrow(gain_table);
5621 cpl_polynomial *poly_linfit = NULL;
5622 cpl_image *fiterror = NULL;
5624 double * pcoeffs = NULL;
5625 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
5628 cpl_vector *x =NULL;
5629 const cpl_vector *y =NULL;
5632 const cpl_image * first = NULL;
5640 cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5641 cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5642 cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
5643 cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
5645 pcoeffs = cpl_malloc(
sizeof(
double)*(detmon_lg_config.order + 1));
5647 skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
5648 detmon_lg_config.method));
5649 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
5650 DETMON_QC_METHOD_C));
5653 if (!strcmp(detmon_lg_config.method,
"PTC")) {
5655 if (detmon_lg_config.exts >= 0) {
5656 cpl_msg_info(cpl_func,
5657 "Polynomial fitting for the GAIN (constant term method)");
5659 cpl_msg_info(cpl_func,
5660 "Polynomial fitting for the GAIN (constant term method)"
5661 " for extension nb %d", which_ext);
5663 skip_if(detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, gain_nsets));
5665 skip_if(detmon_lg_qc_med(gain_table, gaint_qclist, gain_nsets));
5670 if(detmon_lg_config.lamp_ok) {
5671 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
5672 detmon_lg_config.cr));
5673 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
5674 DETMON_QC_LAMP_FLUX_C));
5678 if(detmon_lg_config.autocorr == TRUE) {
5679 autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
5680 skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
5682 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
5683 DETMON_QC_AUTOCORR_C));
5685 if (detmon_lg_config.exts >= 0) {
5686 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix");
5688 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix"
5689 " for extension nb %d", which_ext);
5692 if(detmon_lg_config.pix2pix)
5696 nbpixs = detmon_compute_badpixmap(opt_nir, linear_nsets, linear_table,
5697 linearity_inputs, nbpixs, x,gaint_qclist, bpms_ptr);
5703 cpl_mask* mask = NULL;
5704 mask = detmon_image_to_mask(*bpms_ptr);
5706 if(!detmon_lg_config.pix2pix) {
5707 const int order=detmon_lg_config.order;
5715 y = cpl_vector_wrap(linear_nsets,
5716 (
double *)cpl_table_get_data_double_const(linear_table,
5719 if (opt_nir == NIR) {
5720 x = cpl_vector_wrap(linear_nsets,
5721 (
double *)cpl_table_get_data_double_const(linear_table,
5724 x = cpl_vector_wrap(linear_nsets,
5725 (
double *)cpl_table_get_data_double_const(linear_table,
5729 if(x == NULL || y == NULL) {
5730 cpl_vector_unwrap((cpl_vector *)x);
5731 cpl_vector_unwrap((cpl_vector *)y);
5741 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
5742 poly_linfit = irplib_polynomial_fit_1d_create(x, y,order,&mse);
5744 if(order == cpl_vector_get_size(x) - 1) {
5745 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5749 if(poly_linfit == NULL) {
5750 cpl_vector_unwrap((cpl_vector *)x);
5751 cpl_vector_unwrap((cpl_vector *)y);
5757 min_val=cpl_vector_get_min(y);
5758 max_val=cpl_vector_get_max(y);
5760 cpl_vector_unwrap((cpl_vector *)x);
5761 cpl_vector_unwrap((cpl_vector *)y);
5763 for(deg = 0; deg <= order; deg++) {
5764 const double coeff =
5765 cpl_polynomial_get_coeff(poly_linfit, °);
5767 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
5768 assert(name_o != NULL);
5769 skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
5770 skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
5771 DETMON_QC_LIN_COEF_C));
5774 pcoeffs[deg] = coeff;
5776 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
5777 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
5778 DETMON_QC_ERRFIT_MSE_C));
5782 const int order=detmon_lg_config.order;
5784 y = cpl_vector_wrap(linear_nsets,
5785 (
double *)cpl_table_get_data_double_const(linear_table,
5790 x = cpl_vector_wrap(linear_nsets,
5791 (
double *)cpl_table_get_data_double_const(linear_table,
5794 x = cpl_vector_wrap(linear_nsets,
5795 (
double *)cpl_table_get_data_double_const(linear_table,
5804 hdrl_imagelist* data = NULL;
5805 cpl_imagelist* linearity_errors = NULL;
5806 linearity_errors = cpl_imagelist_new();
5808 cpl_image* error = NULL;
5809 cpl_image* image = NULL;
5810 const double gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
5811 cpl_msg_info(cpl_func,
"Computed gain: %g", gain);
5814 cpl_imagelist* lin_inputs = (cpl_imagelist*) linearity_inputs;
5815 for(cpl_size i = 0; i < cpl_imagelist_get_size(linearity_inputs); i++) {
5817 image = cpl_imagelist_get(lin_inputs,i);
5821 error = detmon_lg_calc_noise_map(image,gain, ron);
5823 cpl_imagelist_set(linearity_errors, error, i);
5833 cpl_imagelist_delete(linearity_errors);
5836 cpl_image * out_chi2 = NULL, * out_dof = NULL;
5838 hdrl_imagelist * out_coef = NULL;
5843 detmon_qc_lin_log(out_coef, out_chi2, out_dof, mask, linc_qclist);
5845 cpl_image_delete(out_chi2);
5846 cpl_image_delete(out_dof);
5849 first = cpl_imagelist_get_const(linearity_inputs, 0);
5850 sizex = cpl_image_get_size_x(first);
5851 sizey = cpl_image_get_size_y(first);
5852 vsize = cpl_vector_get_size(x);
5853 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
5855 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,order, FALSE,
5856 CPL_TYPE_FLOAT, fiterror);
5857 min_val=cpl_vector_get_min(y);
5858 max_val=cpl_vector_get_max(y);
5859 cpl_vector_unwrap((cpl_vector*)x);
5860 cpl_vector_unwrap((cpl_vector*)y);
5862 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
5863 "Failed polynomial fit");
5900 if(order == vsize - 1)
5902 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5903 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5905 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5906 DETMON_QC_ERRFIT_C));
5909 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5910 cpl_image_get_median(fiterror)));
5911 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5912 DETMON_QC_ERRFIT_C));
5916 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
5918 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
5919 DETMON_QC_COUNTS_MIN_C));
5920 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
5922 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
5923 DETMON_QC_COUNTS_MAX_C));
5924 skip_if(detmon_lg_lineff(pcoeffs,lint_qclist,detmon_lg_config.ref_level,
5925 detmon_lg_config.order));
5927 if (detmon_lg_config.exts >= 0)
5929 cpl_msg_info(cpl_func,
"Bad pixel detection");
5932 cpl_msg_info(cpl_func,
"Bad pixel detection"
5933 " for extension nb %d", which_ext);
5939 skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
5940 skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
5941 DETMON_QC_NUM_BPM_C));
5942 cpl_msg_info(cpl_func,
"stability=%g",detmon_lg_config.lamp_stability);
5943 if(detmon_lg_config.lamp_stability != 0.0)
5945 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
5946 detmon_lg_config.lamp_stability));
5947 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
5948 DETMON_QC_LAMP_STAB_C));
5951 if (!detmon_lg_config.wholechip && detmon_lg_config.pix2pix)
5953 detmon_lg_fits_coeffs_and_bpm2chip(coeffs_ptr,bpms_ptr);
5959 cpl_mask_delete(mask);
5961 cpl_image_delete(fiterror);
5962 cpl_polynomial_delete(poly_linfit);
5966 return cpl_error_get_code();
5978static cpl_error_code
5979detmon_lg_lineff(
double * pcoeffs,
5980 cpl_propertylist * qclist,
5986 double residual, slope;
5989 cpl_polynomial * poly = cpl_polynomial_new(1);
6003 pcoeffs[0] -= ref_level;
6005 for (i = 2; i <= order; i++)
6008 for(j = 0; j < i; j++)
6010 pcoeffs[i] /= pcoeffs[1];
6016 for (deg = 0; deg <= order; deg++) {
6018 skip_if(cpl_polynomial_set_coeff(poly, °, pcoeffs[deg]));
6027 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
6029 if (slope <= 0.0 && residual >= 0.0) {
6030 cpl_msg_warning(cpl_func,
"Reference level (--ref_level) outside"
6031 " linearity range of the detector. Cannot compute"
6032 " linearity efficiency (QC.LINEFF).");
6037 cpl_error_code err = cpl_polynomial_solve_1d(poly, 0.0, &root, 1);
6042 if (err == CPL_ERROR_NONE)
6045 lineff = (root - ref_level) / ref_level;
6050 cpl_msg_warning(cpl_func,
6051 "Cannot compute linearity efficiency (QC.LINEFF)"
6052 "for the current combination "
6053 " of (--ref-level equal %d) and (--order equal %d) parameters. Try "
6054 "to decrease (--ref-level) value.", ref_level, order);
6057 cpl_msg_warning(cpl_func,
"DETMON_QC_LIN_EFF=%f",lineff );
6058 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
6060 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
6061 DETMON_QC_LIN_EFF_C));
6063 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
6065 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
6066 DETMON_QC_LIN_EFF_FLUX_C));
6070 cpl_polynomial_delete(poly);
6072 return cpl_error_get_code();
6083static cpl_error_code
6084detmon_lg_qc_ptc(
const cpl_table * gain_table,
6085 cpl_propertylist * qclist,
unsigned mode,
int rows_in_gain)
6088 cpl_polynomial *poly_fit = NULL;
6089 cpl_polynomial *poly_fit2 = NULL;
6091 const int nsets = rows_in_gain;
6093 cpl_vector *x = NULL;
6094 cpl_vector *y = NULL;
6096 cpl_errorstate prestate;
6098 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
6099 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
6101 x = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
6103 y = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
6105 skip_if(x == NULL || y == NULL);
6106 if (0 == detmon_lg_check_before_gain(x, y))
6110 cpl_vector_unwrap(x);
6114 cpl_vector_unwrap(y);
6116 return CPL_ERROR_NONE;
6119 poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
6120 skip_if(poly_fit == NULL);
6124 prestate = cpl_errorstate_get();
6125 coef = cpl_polynomial_get_coeff(poly_fit, &i);
6126 skip_if (!cpl_errorstate_is_equal(prestate) || coef==0);
6127 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
6128 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
6129 DETMON_QC_CONAD_C));
6132 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
6134 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
6150 if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
6151 const cpl_vector *x2 =
6152 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT_CORR"));
6153 const cpl_vector *y2 =
6154 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
6156 if(x2 == NULL || y2 == NULL) {
6157 cpl_vector_unwrap((cpl_vector *)x2);
6158 cpl_vector_unwrap((cpl_vector *)y2);
6169 poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
6170 if(poly_fit2 == NULL) {
6171 cpl_vector_unwrap((cpl_vector *)x2);
6172 cpl_vector_unwrap((cpl_vector *)y2);
6174 cpl_msg_error(cpl_func,
"Error during polynomial fit, err[%s]", cpl_error_get_where());
6178 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
6179 cpl_vector_unwrap((cpl_vector *)x2);
6180 cpl_vector_unwrap((cpl_vector *)y2);
6181 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
6184 prestate = cpl_errorstate_get();
6185 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
6186 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
6187 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
6189 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
6191 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
6192 DETMON_QC_CONAD_CORR_C));
6194 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
6196 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
6197 DETMON_QC_GAIN_CORR_C));
6203 cpl_vector_unwrap(x);
6204 cpl_vector_unwrap(y);
6205 cpl_polynomial_delete(poly_fit);
6206 cpl_polynomial_delete(poly_fit2);
6208 return cpl_error_get_code();
6217static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y)
6219 const double TOLERANCE = 1e-37;
6220 double xmin = cpl_vector_get_min(x);
6221 double xmax = cpl_vector_get_max(x);
6222 double ymin = cpl_vector_get_min(y);
6223 double ymax = cpl_vector_get_max(y);
6224 double ystdev = cpl_vector_get_stdev(y);
6225 double xstdev = cpl_vector_get_stdev(x);
6227 if (fabs(xmax-xmin) < TOLERANCE &&
6228 fabs(ymax - ymin) < TOLERANCE &&
6229 xstdev < TOLERANCE &&
6232 cpl_msg_warning(cpl_func,
"An empty frame has been detected, linearity, coeffs, gain, FPN values will not be computed.");
6247static cpl_error_code
6248detmon_lg_qc_med(
const cpl_table * gain_table,
6249 cpl_propertylist * qclist,
int rows_in_gain)
6253 cpl_vector *x = NULL;
6254 cpl_vector *y = NULL;
6255 int check_result = 0;
6257 if (rows_in_gain) {};
6259 x = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
6260 y = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
6261 check_result = detmon_lg_check_before_gain(x, y);
6264 cpl_vector_unwrap(x);
6268 cpl_vector_unwrap(y);
6270 if (0 == check_result)
6272 return CPL_ERROR_NONE;
6275 gain=cpl_table_get_column_median(gain_table,
"GAIN");
6277 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
6279 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
6282 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
6283 cpl_table_get_column_stdev
6284 (gain_table,
"GAIN")));
6285 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
6286 DETMON_QC_GAIN_MSE_C));
6288 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
6289 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
6290 DETMON_QC_CONAD_C));
6293 gain=cpl_table_get_column_median(gain_table,
"GAIN_CORR");
6295 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
6297 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
6298 DETMON_QC_GAIN_CORR_C));
6301 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
6302 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
6303 DETMON_QC_CONAD_CORR_C));
6308 return cpl_error_get_code();
6322static cpl_error_code
6323detmon_lg_rescale(cpl_imagelist * to_rescale)
6326 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 0),
6327 detmon_lg_config.llx,
6328 detmon_lg_config.lly,
6329 detmon_lg_config.urx,
6330 detmon_lg_config.ury);
6332 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 1),
6333 detmon_lg_config.llx,
6334 detmon_lg_config.lly,
6335 detmon_lg_config.urx,
6336 detmon_lg_config.ury);
6340 if(fabs(med1 / med2 - 1) > 0.001) {
6342 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
6345 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
6351 return cpl_error_get_code();
6354static cpl_error_code
6355detmon_pair_extract_next(
const cpl_frameset * set,
6359 cpl_frameset ** pair,
6363 double dit_next = -100;
6364 cpl_size* selection;
6365 int nsets_extracted = 0;
6366 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6367 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6368 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6369 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6371 nsets_extracted = cpl_frameset_get_size(set);
6372 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6373 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6376 dit = dit_array[*next_element ];
6378 if (*next_element < nsets_extracted - 1)
6380 dit_next = dit_array[*next_element + 1 ];
6384 selection[iindex[*next_element] ] = 1;
6385 if (fabs(dit - dit_next) < tolerance)
6388 selection[iindex[*next_element + 1] ] = 1;
6393 cpl_msg_warning(cpl_func,
"DIT for the second frame in the pair is above tolerance level - could not be taken, dit1[%f] dit2[%f] next_element: %d . Check input data set and tolerance value", dit, dit_next, *next_element);
6397 cpl_frameset_delete(*pair);
6398 *pair = cpl_frameset_extract(set, selection, 1);
6401 cpl_free(selection);
6402 return cpl_error_get_code();
6405static cpl_error_code
6406detmon_single_extract_next(
const cpl_frameset * set,
6410 cpl_frameset ** pair)
6412 cpl_size* selection;
6413 int nsets_extracted = 0;
6414 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6415 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6416 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6417 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6419 nsets_extracted = cpl_frameset_get_size(set);
6420 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6421 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6424 selection[iindex[*next_element] ] = 1;
6427 cpl_frameset_delete(*pair);
6428 *pair = cpl_frameset_extract(set, selection, 1);
6430 cpl_free(selection);
6431 return cpl_error_get_code();
6529detmon_gain(
const cpl_imagelist * imlist_on,
6530 const cpl_imagelist * imlist_off,
6531 const cpl_vector * exptimes,
6532 const cpl_vector * ndit,
6542 cpl_propertylist * qclist,
6544 cpl_imagelist ** diff_imlist,
6545 cpl_imagelist ** autocorr_imlist)
6547 cpl_table * gain_table = NULL;
6548 cpl_imagelist * difflist = NULL;
6549 cpl_imagelist * autocorrlist = NULL;
6550 cpl_imagelist * c_onlist = NULL;
6551 cpl_imagelist * c_offlist = NULL;
6552 cpl_vector * diffdits = NULL;
6553 cpl_vector * diffndits = NULL;
6554 int rows_in_gain = 0;
6555 int ndiffdits, ndits;
6557 cpl_boolean opt_nir = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
6558 const char * method = mode & IRPLIB_GAIN_PTC ?
"PTC" :
"MED";
6560 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6561 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6562 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6563 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6566 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6567 skip_if(detmon_gain_table_create(gain_table, opt_nir));
6571 skip_if(detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,
6573 ndiffdits = cpl_vector_get_size(diffdits);
6575 ndits = cpl_vector_get_size(exptimes);
6578 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
6579 difflist = cpl_imagelist_new();
6580 autocorrlist = cpl_imagelist_new();
6583 if (mode & IRPLIB_GAIN_COLLAPSE) {
6584 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6585 c_offlist = cpl_imagelist_duplicate(imlist_off);
6586 skip_if(detmon_lg_rescale(c_offlist));
6588 c_offlist = (cpl_imagelist *) imlist_off;
6593 for (i = 0; i < ndiffdits; i++) {
6600 c_dit=cpl_vector_get(diffdits, i);
6603 c_ndit=(int)cpl_vector_get(diffndits, i);
6606 c_onlist = cpl_imagelist_new();
6609 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6610 c_offlist = cpl_imagelist_new();
6615 for(j = 0; j < ndits; j++) {
6616 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6626 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6627 const cpl_image * im =
6628 cpl_imagelist_get_const(imlist_on, j);
6629 im_on = cpl_image_duplicate(im);
6631 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6633 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6640 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6642 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6643 const cpl_image * im =
6644 cpl_imagelist_get_const(imlist_off, j);
6645 im_off = cpl_image_duplicate(im);
6648 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6650 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6657 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6658 skip_if (c_nons != c_noffs);
6661 skip_if (c_nons == 0 || c_nons % 2 != 0);
6664 if(mode & IRPLIB_GAIN_WITH_RESCALE) {
6665 skip_if(detmon_lg_rescale(c_onlist));
6666 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6667 skip_if(detmon_lg_rescale(c_offlist));
6673 int rows_affected = 1;
6674 skip_if(detmon_gain_table_fill_row(gain_table,
6678 c_offlist, kappa, nclip,
6680 xshift, yshift, 1E10, i,
6681 mode, &rows_affected));
6686 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6687 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6688 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6689 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6690 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6691 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6694 cpl_imagelist_unset(c_onlist, 0);
6696 cpl_imagelist_unset(c_onlist, 0);
6698 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6699 cpl_imagelist_unset(c_offlist, 0);
6701 cpl_imagelist_unset(c_offlist, 0);
6709 cpl_imagelist_delete(c_onlist);
6710 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6711 cpl_imagelist_delete(c_offlist);
6715 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
6716 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
6717 DETMON_QC_METHOD_C));
6720 if (mode & IRPLIB_GAIN_PTC) {
6721 skip_if(detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
6723 skip_if(detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
6726 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
6727 double autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
6728 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
6730 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
6731 DETMON_QC_AUTOCORR_C));
6734 if (diff_imlist != NULL) *diff_imlist = difflist;
6735 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
6739 cpl_vector_delete(diffdits);
6740 cpl_vector_delete(diffndits);
6745static cpl_error_code
6746detmon_gain_table_create(cpl_table * gain_table,
6747 const cpl_boolean opt_nir)
6749 if (opt_nir == NIR) {
6750 skip_if(cpl_table_new_column(gain_table,
"DIT", CPL_TYPE_DOUBLE));
6751 skip_if(cpl_table_new_column(gain_table,
"NDIT", CPL_TYPE_INT));
6753 skip_if(cpl_table_new_column(gain_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6755 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON1", CPL_TYPE_DOUBLE));
6756 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON2", CPL_TYPE_DOUBLE));
6757 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF1", CPL_TYPE_DOUBLE));
6758 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF2", CPL_TYPE_DOUBLE));
6759 skip_if(cpl_table_new_column(gain_table,
"SIG_ON_DIF", CPL_TYPE_DOUBLE));
6760 skip_if(cpl_table_new_column(gain_table,
"SIG_OFF_DIF", CPL_TYPE_DOUBLE));
6761 skip_if(cpl_table_new_column(gain_table,
"GAIN", CPL_TYPE_DOUBLE));
6762 skip_if(cpl_table_new_column(gain_table,
"AUTOCORR", CPL_TYPE_DOUBLE));
6763 skip_if(cpl_table_new_column(gain_table,
"GAIN_CORR", CPL_TYPE_DOUBLE));
6764 skip_if(cpl_table_new_column(gain_table,
"ADU", CPL_TYPE_DOUBLE));
6765 skip_if(cpl_table_new_column(gain_table,
"X_FIT", CPL_TYPE_DOUBLE));
6766 skip_if(cpl_table_new_column(gain_table,
"X_FIT_CORR", CPL_TYPE_DOUBLE));
6767 skip_if(cpl_table_new_column(gain_table,
"Y_FIT", CPL_TYPE_DOUBLE));
6768 skip_if(cpl_table_new_column(gain_table,
"Y_FIT_CORR", CPL_TYPE_DOUBLE));
6769 skip_if(cpl_table_new_column(gain_table,
"FLAG", CPL_TYPE_INT));
6773 return cpl_error_get_code();
6776static cpl_error_code
6777detmon_lin_table_create(cpl_table * lin_table,
6778 const cpl_boolean opt_nir)
6780 if (opt_nir == NIR) {
6781 skip_if(cpl_table_new_column(lin_table,
"DIT", CPL_TYPE_DOUBLE));
6783 skip_if(cpl_table_new_column(lin_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6785 skip_if(cpl_table_new_column(lin_table,
"MED", CPL_TYPE_DOUBLE));
6786 skip_if(cpl_table_new_column(lin_table,
"MEAN", CPL_TYPE_DOUBLE));
6787 skip_if(cpl_table_new_column(lin_table,
"MED_DIT", CPL_TYPE_DOUBLE));
6788 skip_if(cpl_table_new_column(lin_table,
"MEAN_DIT", CPL_TYPE_DOUBLE));
6789 skip_if(cpl_table_new_column(lin_table,
"ADL", CPL_TYPE_DOUBLE));
6792 return cpl_error_get_code();
6796detmon_lg_find_dits(
const cpl_vector * exptimes,
6799 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6805 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
6809 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
6811 for (j = 0; j < ndits; j++) {
6812 if (fabs(cpl_vector_get(exptimes, i) -
6813 cpl_vector_get(dits, j)) > tolerance)
6816 if(ndiffs == ndits) {
6817 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
6822 cpl_vector_set_size(dits, ndits);
6830static cpl_error_code
6831detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
6832 const cpl_vector * vec_ndits,
6834 cpl_vector** diff_dits,
6835 cpl_vector** diff_ndits)
6843 * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6844 * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
6847 cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
6848 cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
6851 size=cpl_vector_get_size(exptimes);
6853 for(i = 1; i < size; i++) {
6855 for (j = 0; j < ndits; j++) {
6856 if (fabs(cpl_vector_get(exptimes, i) -
6857 cpl_vector_get(*diff_dits,j)) > tolerance)
6860 if(ndiffs == ndits) {
6861 cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
6862 cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
6867 cpl_vector_set_size(*diff_dits, ndits);
6868 cpl_vector_set_size(*diff_ndits, ndits);
6871 return cpl_error_get_code();
6961detmon_lin(
const cpl_imagelist * imlist_on,
6962 const cpl_imagelist * imlist_off,
6963 const cpl_vector * exptimes,
6973 cpl_propertylist * qclist,
6975 cpl_imagelist ** coeffs_cube,
6978 cpl_table * lin_table = NULL;
6979 cpl_imagelist * c_onlist = NULL;
6980 cpl_imagelist * c_offlist = NULL;
6981 cpl_vector * diffdits = NULL;
6982 cpl_imagelist * lin_inputs = NULL;
6983 cpl_polynomial * poly_linfit = NULL;
6984 cpl_image * fiterror = NULL;
6985 cpl_vector * vcoeffs = NULL;
6986 double * pcoeffs = NULL;
6987 int ndiffdits, ndits;
6989 cpl_boolean opt_nir = mode & IRPLIB_LIN_OPT ? OPT : NIR;
6990 const cpl_vector *x = NULL;
6991 const cpl_vector *y = NULL;
6993 const cpl_image * first = NULL;
7001 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
7002 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
7003 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
7004 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
7005 cpl_ensure(order > 0 , CPL_ERROR_ILLEGAL_INPUT, NULL);
7007 vcoeffs = cpl_vector_new(order + 1);
7008 pcoeffs = cpl_vector_get_data(vcoeffs);
7011 if (mode & IRPLIB_LIN_PIX2PIX) {
7012 cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
7013 cpl_ensure(bpm != NULL, CPL_ERROR_NULL_INPUT, NULL);
7014 lin_inputs = cpl_imagelist_new();
7018 lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
7019 skip_if(detmon_lin_table_create(lin_table, opt_nir));
7023 diffdits = detmon_lg_find_dits(exptimes, tolerance);
7024 ndiffdits = cpl_vector_get_size(diffdits);
7026 ndits = cpl_vector_get_size(exptimes);
7056 if (mode & IRPLIB_LIN_COLLAPSE) {
7061 cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
7062 skip_if(collapse == NULL);
7064 c_offlist = cpl_imagelist_new();
7065 skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
7069 for (i = 0; i < ndiffdits; i++) {
7073 double c_dit = cpl_vector_get(diffdits, i);
7075 c_onlist = cpl_imagelist_new();
7078 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7079 c_offlist = cpl_imagelist_new();
7083 for(j = 0; j < ndits; j++) {
7084 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
7094 if (mode & IRPLIB_LIN_WITH_RESCALE) {
7095 const cpl_image * im =
7096 cpl_imagelist_get_const(imlist_on, j);
7097 im_on = cpl_image_duplicate(im);
7099 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
7101 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
7108 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7110 if (mode & IRPLIB_LIN_WITH_RESCALE) {
7111 const cpl_image * im =
7112 cpl_imagelist_get_const(imlist_off, j);
7113 im_off = cpl_image_duplicate(im);
7116 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
7118 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
7125 if (mode & IRPLIB_LIN_NO_COLLAPSE)
7126 skip_if (c_nons != c_noffs);
7129 skip_if (c_nons == 0 || c_nons % 2 != 0);
7132 if(mode & IRPLIB_LIN_WITH_RESCALE) {
7133 skip_if(detmon_lg_rescale(c_onlist));
7134 if (mode & IRPLIB_LIN_NO_COLLAPSE)
7135 skip_if(detmon_lg_rescale(c_offlist));
7142 skip_if(detmon_lin_table_fill_row(lin_table, c_dit,
7144 c_onlist, c_offlist,
7148 if (mode & IRPLIB_LIN_WITH_RESCALE) {
7149 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
7150 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
7151 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7152 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
7153 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
7156 cpl_imagelist_unset(c_onlist, 0);
7158 cpl_imagelist_unset(c_onlist, 0);
7160 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7161 cpl_imagelist_unset(c_offlist, 0);
7163 cpl_imagelist_unset(c_offlist, 0);
7171 cpl_imagelist_delete(c_onlist);
7172 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7173 cpl_imagelist_delete(c_offlist);
7177 skip_if(detmon_add_adl_column(lin_table, opt_nir));
7179 if(!(mode & IRPLIB_LIN_PIX2PIX)) {
7182 y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7183 (
double *)cpl_table_get_data_double_const(lin_table,
7185 if (opt_nir == NIR) {
7186 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7187 (
double *)cpl_table_get_data_double_const(lin_table,
"DIT"));
7189 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7190 (
double *)cpl_table_get_data_double_const(lin_table,
"EXPTIME"));
7192 if(x == NULL || y == NULL) {
7193 cpl_vector_unwrap((cpl_vector *)x);
7194 cpl_vector_unwrap((cpl_vector *)y);
7204 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
7205 poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
7207 if(order == cpl_vector_get_size(x) - 1) {
7208 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7212 if(poly_linfit == NULL) {
7213 cpl_vector_unwrap((cpl_vector *)x);
7214 cpl_vector_unwrap((cpl_vector *)y);
7219 cpl_vector_unwrap((cpl_vector *)x);
7220 cpl_vector_unwrap((cpl_vector *)y);
7222 for(deg = 0; deg <= order; deg++) {
7223 const double coeff =
7224 cpl_polynomial_get_coeff(poly_linfit, °);
7226 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
7227 assert(name_o != NULL);
7228 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
7229 skip_if(cpl_propertylist_set_comment(qclist,name_o,
7230 DETMON_QC_LIN_COEF_C));
7232 pcoeffs[deg] = coeff;
7234 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
7235 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7236 DETMON_QC_ERRFIT_MSE_C));
7240 if (opt_nir == NIR) {
7241 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7242 (
double *)cpl_table_get_data_double_const(lin_table,
7245 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7246 (
double *)cpl_table_get_data_double_const(lin_table,
7251 first = cpl_imagelist_get_const(lin_inputs, 0);
7252 sizex = cpl_image_get_size_x(first);
7253 sizey = cpl_image_get_size_y(first);
7255 vsize = cpl_vector_get_size(x);
7257 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
7260 cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
7261 order, FALSE, CPL_TYPE_FLOAT,
7264 cpl_vector_unwrap((cpl_vector*)x);
7265 irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
7266 "Failed polynomial fit");
7268 for(i = 0; i <= order; i++) {
7269 cpl_image *image = cpl_imagelist_get(*coeffs_cube, i);
7270 const double coeff = cpl_image_get_median(image);
7271 char * name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", i);
7272 char * name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", i);
7274 assert(name_o1 != NULL);
7275 assert(name_o2 != NULL);
7276 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
7277 skip_if(cpl_propertylist_set_comment(qclist,name_o1,
7278 DETMON_QC_LIN_COEF_C));
7281 skip_if(cpl_propertylist_append_double(qclist, name_o2,
7282 cpl_image_get_stdev(image)));
7283 skip_if(cpl_propertylist_set_comment(qclist,name_o2,
7284 DETMON_QC_LIN_COEF_ERR_C));
7289 if(order == vsize - 1) {
7290 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7291 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7293 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7294 DETMON_QC_ERRFIT_C));
7298 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7299 cpl_image_get_median(fiterror)));
7300 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7301 DETMON_QC_ERRFIT_C));
7306 skip_if(detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
7308 if(mode & IRPLIB_LIN_PIX2PIX) {
7310 *bpm = detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
7311 skip_if(*bpm == NULL);
7312 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
7314 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
7315 DETMON_QC_NUM_BPM_C));
7320 cpl_vector_delete(diffdits);
7321 cpl_polynomial_delete(poly_linfit);
7322 cpl_imagelist_delete(lin_inputs);
7323 cpl_vector_delete(vcoeffs);
7324 cpl_image_delete(fiterror);
7354static cpl_error_code
7355detmon_lin_table_fill_row(cpl_table * lin_table,
double c_dit,
7356 cpl_imagelist * linearity_inputs,
7357 const cpl_imagelist * ons,
7358 const cpl_imagelist * offs,
7367 cpl_image * extracted=NULL;
7369 cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
7370 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
7371 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
7373 if (mode & IRPLIB_LIN_PIX2PIX) {
7374 cpl_msg_debug(cpl_func,
"checking linearity inputs");
7375 cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
7379 if (mode & IRPLIB_LIN_NIR) {
7380 cpl_table_set(lin_table,
"DIT", pos, c_dit);
7381 }
else if (mode & IRPLIB_LIN_OPT) {
7382 cpl_table_set(lin_table,
"EXPTIME", pos, c_dit);
7384 cpl_msg_error(cpl_func,
"Mandatory mode not given");
7388 const cpl_image * off2;
7389 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
7390 off2 = cpl_imagelist_get_const(offs, 0);
7392 off2 = cpl_imagelist_get_const(offs, 1);
7394 extracted = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
7395 cpl_imagelist_get_const(offs, 0),
7396 cpl_imagelist_get_const(ons, 1),
7398 llx, lly, urx, ury);
7399 cpl_ensure_code(extracted != NULL, cpl_error_get_code());
7403 double median = cpl_image_get_median(extracted);
7404 double mean= cpl_image_get_mean(extracted);
7405 cpl_table_set(lin_table,
"MED", pos, median);
7406 cpl_table_set(lin_table,
"MEAN", pos, mean);
7408 cpl_table_set(lin_table,
"MED_DIT", pos, median / c_dit);
7409 cpl_table_set(lin_table,
"MEAN_DIT", pos, mean / c_dit);
7413 if(mode & IRPLIB_LIN_PIX2PIX) {
7414 cpl_error_code error = cpl_imagelist_set(linearity_inputs, extracted,
7416 cpl_ensure_code(!error, error);
7418 cpl_image_delete(extracted);
7421 return cpl_error_get_code();
7424static double irplib_calculate_total_noise_smooth(
const cpl_image* pimage,
7425 int pattern_x,
int pattern_y)
7427 cpl_image * p_tmp_image = 0;
7428 cpl_image * psmooth_image = 0;
7430 cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
7432 p_tmp_image = cpl_image_duplicate(pimage);
7433 cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
7434 cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
7435 psmooth_image = cpl_image_divide_create(pimage,p_tmp_image);
7436 ret_noise = irplib_calculate_total_noise(psmooth_image);
7437 cpl_mask_delete(mask);
7438 cpl_image_delete(psmooth_image);
7439 cpl_image_delete(p_tmp_image);
7443static double irplib_calculate_total_noise(
const cpl_image* pimage)
7445 double total_noise = -1;
7446 unsigned long max_bin_size = 1E5;
7447 const double hstart = cpl_image_get_min(pimage);
7448 const double hrange = cpl_image_get_max(pimage) - hstart;
7449 const unsigned long nbins = max_bin_size;
7452 irplib_hist * phist = 0;
7453 phist = irplib_hist_new();
7456 irplib_hist_init(phist, nbins, hstart, hrange);
7457 err = irplib_hist_fill(phist, pimage);
7458 if (err == CPL_ERROR_NONE)
7466 unsigned long n_bins = irplib_hist_get_nbins(phist);
7467 double start = irplib_hist_get_start(phist);
7468 double bin_size = irplib_hist_get_bin_size(phist);
7469 cpl_vector* pdata_vector = cpl_vector_new(n_bins);
7470 cpl_vector* ppos_vector = cpl_vector_new(n_bins);
7471 cpl_table* ptable = cpl_table_new(n_bins);
7472 cpl_table_new_column(ptable,
"bin", CPL_TYPE_DOUBLE);
7473 cpl_table_new_column(ptable,
"value", CPL_TYPE_DOUBLE);
7474 for(i = 0; i < n_bins; i++)
7476 unsigned int value = irplib_hist_get_value(phist, i);
7477 double dvalue = (double)(value);
7478 cpl_vector_set(pdata_vector, i, dvalue);
7479 cpl_vector_set(ppos_vector, i, start + i * bin_size);
7481 cpl_table_set(ptable,
"bin", i, start + i * bin_size);
7482 cpl_table_set(ptable,
"value", i, dvalue);
7484 err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
7485 if (err == CPL_ERROR_NONE)
7487 cpl_msg_info(cpl_func,
"FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
7491 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed Gaussian Fit, err msg [%s]", cpl_error_get_message());
7494 cpl_table_delete(ptable);
7495 cpl_vector_delete(ppos_vector);
7496 cpl_vector_delete(pdata_vector);
7500 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
7503 irplib_hist_delete(phist);
7508static double irplib_compute_err(
double gain,
double ron,
double FA)
7510 double int_gain = (gain * gain - 1) / 12;
7515 return sqrt(ron * ron + FA / gain + int_gain);
7518static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain ,
7519 FPN_METHOD fpn_method,
int smooth_size,
double* mse)
7521 cpl_image* im_diff = 0;
7522 const cpl_image* im_f1 = f1;
7523 cpl_image* im_inrange1 = 0;
7532 cpl_msg_warning(cpl_func,
"gain[%f]<0", gain);
7533 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7540 im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
7541 im_f1 = im_inrange1;
7543 FA = cpl_image_get_median(im_f1);
7550 cpl_msg_info(cpl_func,
"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
7551 s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
7554 cpl_msg_info(cpl_func,
"HISTOGRAM method is used for FPN");
7555 s_tot = irplib_calculate_total_noise(im_f1);
7560 cpl_msg_warning(cpl_func,
"fpn_method is not defined");
7569 cpl_msg_warning(cpl_func,
"Median flux on sum of flats<0");
7570 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7575 if ((s_tot * s_tot - FA / gain) > 0)
7577 s_fpn = sqrt(s_tot * s_tot - FA / gain);
7578 sr_fpn = s_fpn / FA;
7579 *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
7583 cpl_msg_warning(cpl_func,
"s_tot * s_tot < FA / gain");
7584 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7593 cpl_image_delete(im_diff);
7596 cpl_image_delete(im_inrange1);
7602static cpl_imagelist * irplib_load_fset_wrp(
const cpl_frameset * pframeset,
7603 cpl_type type ,
int whichext)
7607 return detmon_load_frameset_window(pframeset, type, 0, whichext,
7608 detmon_lg_config.llx,
7609 detmon_lg_config.lly,
7610 detmon_lg_config.urx,
7611 detmon_lg_config.ury,
7612 detmon_lg_config.nx,
7613 detmon_lg_config.ny);
7616static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset * pframeset,
7617 cpl_type type ,
int whichext)
7620 cpl_imagelist* offs = cpl_imagelist_new();
7621 detmon_lg_config.load_fset(pframeset, type, offs);
7626static cpl_error_code irplib_table_create_column(cpl_table* ptable,
7627 cpl_propertylist* plist)
7629 if (ptable && plist)
7631 int size = cpl_propertylist_get_size(plist);
7633 for (i = 0; i < size; i++)
7635 cpl_property* pprop = cpl_propertylist_get(plist,i);
7638 const char* pname = cpl_property_get_name(pprop);
7641 cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
7642 if (cpl_error_get_code() != CPL_ERROR_NONE)
7644 cpl_msg_warning(cpl_func,
"cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
7651 return cpl_error_get_code();
7654static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
7655 cpl_propertylist* plist,
int row)
7657 cpl_error_code err = CPL_ERROR_NONE;
7658 if (ptable && plist)
7660 int size = cpl_propertylist_get_size(plist);
7662 for (i = 0; i < size; i++)
7664 cpl_property* pprop = cpl_propertylist_get(plist,i);
7667 const char* pname = cpl_property_get_name(pprop);
7668 double value = cpl_property_get_double(pprop);
7671 cpl_table_set_double(ptable, pname, row, value);
7672 if (cpl_error_get_code() != CPL_ERROR_NONE)
7674 cpl_msg_warning(cpl_func,
"cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
7685cpl_error_code detmon_check_order(
const double *exptime,
int sz,
7686 double tolerance,
int order)
7703 }
while(fabs(exptime[i-1] - exptime[i]) < tolerance);
7704 }
while(i < sz - 1);
7706 if ( !( fabs(exptime[i-1] - exptime[i]) < tolerance ) ) nsets++;
7709 cpl_error_set_message(cpl_func,CPL_ERROR_INCOMPATIBLE_INPUT,
7710 "Not enough frames for the polynomial"
7711 " fitting. nsets = %d <= %d order",
7714 return cpl_error_get_code();
7717static cpl_error_code
7718detmon_lg_dfs_save_imagelist(
7719 cpl_frameset * frameset,
7720 const cpl_parameterlist * parlist,
7721 const cpl_frameset *usedframes,
7722 const cpl_imagelist *coeffs,
7723 const char *recipe_name,
7724 const cpl_propertylist *mypro_coeffscube,
7725 const char * package,
7726 const char * name_o)
7728 return(cpl_dfs_save_imagelist
7729 (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
7730 recipe_name, mypro_coeffscube, NULL, package,
7734static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos)
7736 const cpl_image* first = cpl_imagelist_get(imlist, 0);
7739 int x = cpl_image_get_size_x(first);
7740 int y = cpl_image_get_size_y(first);
7741 cpl_type type = cpl_image_get_type(first);
7742 cpl_image * blank = cpl_image_new(x, y, type);
7743 cpl_imagelist_set(imlist, blank, pos);
7749detmon_lg_set_tag(cpl_frameset* set,
const char** tag_on,
const char** tag_off)
7754 ntag_old=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_OLD);
7755 ntag_new=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_NEW);
7757 *tag_on=DETMON_LG_ON_RAW_OLD;
7758 *tag_off=DETMON_LG_OFF_RAW_OLD;
7759 }
else if (ntag_new) {
7760 *tag_on=DETMON_LG_ON_RAW_NEW;
7761 *tag_off=DETMON_LG_OFF_RAW_NEW;
7763 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
7764 "Provide %s and %s (or %s and %s) input frames",
7765 DETMON_LG_ON_RAW_NEW,DETMON_LG_OFF_RAW_NEW,
7766 DETMON_LG_ON_RAW_OLD,DETMON_LG_OFF_RAW_OLD);
7770 return cpl_error_get_code();
hdrl_parameter * hdrl_bpm_fit_parameter_create_pval(int degree, double pval)
create bpm_fit parameter with p-value bpm treshold
cpl_error_code hdrl_bpm_fit_compute(const hdrl_parameter *par, const hdrl_imagelist *data, const cpl_vector *sample_pos, cpl_image **out_mask)
compute bad pixel map based on fitting a stack of images
cpl_error_code hdrl_fit_polynomial_imagelist(const hdrl_imagelist *list, const cpl_vector *samplepos, const int degree, hdrl_imagelist **coef, cpl_image **chi2, cpl_image **dof)
weighted least squares polynomial fit of each pixel of a imagelist
cpl_image * hdrl_image_get_error(hdrl_image *himg)
get error as cpl image
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
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.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
void hdrl_parameter_delete(hdrl_parameter *obj)
shallow delete of a parameter