43 #include "detmon_utils.h"
44 #include "detmon_lg.h"
45 #include "detmon_lg_impl.h"
46 #include "detmon_dfs.h"
48 #include "irplib_ksigma_clip.h"
49 #include "irplib_utils.h"
50 #include "irplib_hist.h"
74 typedef enum _FPN_METHOD FPN_METHOD;
114 cpl_boolean wholechip;
115 cpl_boolean autocorr;
116 cpl_boolean intermediate;
117 cpl_boolean collapse;
124 const char * pafname;
129 double lamp_stability;
132 int (* load_fset) (
const cpl_frameset *, cpl_type, cpl_imagelist *);
133 cpl_imagelist * (* load_fset_wrp) (
const cpl_frameset *, cpl_type, int);
134 FPN_METHOD fpn_method;
136 double saturation_limit;
137 double gain_threshold;
138 cpl_boolean split_coeffs;
148 static cpl_error_code
149 detmon_lg_retrieve_parlist(
const char *,
150 const char *,
const cpl_parameterlist *,
154 static cpl_error_code
155 detmon_lg_split_onoff(
const cpl_frameset *,
158 const char *,
const char * );
160 static cpl_error_code
161 detmon_lg_reduce(
const cpl_frameset *,
162 const cpl_frameset *,
163 int* index_on,
int* index_off,
164 double* exptime_on,
double* exptime_off,
165 int *next_index_on,
int* next_index_off,
176 int (* load_fset) (
const cpl_frameset *,
179 const cpl_boolean,
int);
184 static cpl_error_code
185 detmon_lin_table_fill_row(cpl_table *,
double,
187 const cpl_imagelist *,
188 const cpl_imagelist *,
194 static cpl_error_code
195 detmon_gain_table_fill_row(cpl_table * gain_table,
196 double c_dit,
int c_ndit,
197 cpl_imagelist * autocorr_images,
198 cpl_imagelist * diff_flats,
199 const cpl_imagelist * ons,
200 const cpl_imagelist * offs,
201 double kappa,
int nclip,
202 int llx,
int lly,
int urx,
int ury,
204 double saturation_limit,
205 double gain_threshold,
206 const int pos,
unsigned mode,
int* rows_affected);
209 static cpl_error_code
210 detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
211 cpl_imagelist * diff_flats,
212 const cpl_imagelist * ons,
213 const cpl_imagelist * offs,
214 double kappa,
int nclip,
215 int llx,
int lly,
int urx,
int ury,
216 double saturation_limit,
217 const int pos,
unsigned mode,
218 int* rows_linear_affected);
220 static cpl_error_code
221 detmon_lg_save(
const cpl_parameterlist *,
226 const cpl_propertylist *,
227 const cpl_propertylist *,
228 const cpl_propertylist *,
229 const cpl_propertylist *,
230 const cpl_propertylist *,
231 const cpl_propertylist *,
243 const int,
const int,
const cpl_frameset *,
246 static cpl_error_code
247 detmon_lg_qc_ptc(
const cpl_table *,
248 cpl_propertylist *,
unsigned,
int);
250 static cpl_error_code
251 detmon_lg_qc_med(
const cpl_table *,
252 cpl_propertylist *,
int);
256 irplib_pfits_get_dit(
const cpl_propertylist *);
259 irplib_pfits_get_dit_opt(
const cpl_propertylist *);
261 irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
262 const char* prop_name);
264 static cpl_image * detmon_bpixs(
const cpl_imagelist *,
265 cpl_boolean,
const double,
int *);
268 detmon_autocorr_factor(
const cpl_image *,
269 cpl_image **,
int,
int);
273 static cpl_error_code
274 detmon_opt_contamination(
const cpl_imagelist *,
275 const cpl_imagelist *,
276 unsigned mode, cpl_propertylist *);
279 detmon_opt_lampcr(cpl_frameset *,
int);
283 detmon_lg_dfs_set_groups(cpl_frameset *,
const char *,
const char *);
285 static cpl_error_code
286 detmon_lg_reduce_all(
const cpl_table *,
293 const cpl_imagelist *,
294 const cpl_table *,
int, cpl_boolean);
296 static cpl_error_code
297 detmon_lg_check_defaults(
const cpl_image *);
299 static cpl_error_code
300 detmon_lg_rescale(cpl_imagelist *);
302 static cpl_error_code
303 detmon_lg_reduce_init(cpl_table *,
309 static cpl_error_code
310 detmon_add_adl_column(cpl_table *, cpl_boolean);
312 static cpl_error_code
313 detmon_lg_lamp_stab(
const cpl_frameset *,
314 const cpl_frameset *,
318 static cpl_error_code
319 detmon_lg_reduce_dit(
const cpl_frameset * set_on,
320 int* index_on,
double* exptime_on,
323 const cpl_frameset * set_off,
324 int * index_off,
double* exptime_off,
325 int* next_on,
int* next_off,
326 cpl_table * linear_table,
327 cpl_table * gain_table,
328 cpl_imagelist * linearity_inputs,
329 cpl_propertylist * qclist,
331 cpl_imagelist * autocorr_images,
332 cpl_imagelist * diff_flats,
333 cpl_imagelist * opt_offs,
335 int * rows_linear_affected,
336 int * rows_gain_affected);
338 static cpl_error_code
339 detmon_lg_core(cpl_frameset * cur_fset_on,
340 cpl_frameset * cur_fset_off,
344 double * exptime_off,
347 const char * recipe_name,
348 const char * pipeline_name,
349 const char * pafregexp,
350 const cpl_propertylist * pro_lintbl,
351 const cpl_propertylist * pro_gaintbl,
352 const cpl_propertylist * pro_coeffscube,
353 const cpl_propertylist * pro_bpm,
354 const cpl_propertylist * pro_corr,
355 const cpl_propertylist * pro_diff,
356 const char * package,
357 int (* load_fset) (
const cpl_frameset *,
360 int nsets, cpl_boolean opt_nir,
361 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
362 cpl_frameset * cur_fset);
364 static cpl_error_code
365 detmon_lg_lineff(
double *, cpl_propertylist *,
int,
int);
372 static cpl_error_code
373 detmon_gain_table_create(cpl_table *,
377 static cpl_error_code
378 detmon_lin_table_create(cpl_table *,
382 detmon_lg_find_dits(
const cpl_vector *,
385 static cpl_error_code
386 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
387 const cpl_vector * vec_ndits,
389 cpl_vector** diff_dits,
390 cpl_vector** diff_ndits);
392 static cpl_error_code
393 detmon_fpn_compute(
const cpl_frameset *set_on,
395 int last_linear_best,
396 cpl_propertylist *lint_qclist,
403 FPN_METHOD fpn_method,
405 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain,
406 FPN_METHOD fpn_method,
int,
double* mse);
407 static double irplib_calculate_total_noise(
const cpl_image* pimage);
409 static cpl_imagelist* irplib_load_fset_wrp(
const cpl_frameset *,
410 cpl_type,
int whichext);
411 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset *,
414 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
415 cpl_propertylist* plist);
416 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
417 cpl_propertylist* plist,
420 static cpl_error_code
421 detmon_pair_extract_next(
const cpl_frameset * set,
427 cpl_frameset ** pair,
429 static cpl_error_code
430 detmon_single_extract_next(
const cpl_frameset * set,
434 cpl_frameset ** pair);
441 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code);
442 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos);
443 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y);
452 static int irplib_pfits_get_ndit(
const cpl_propertylist * plist)
454 return cpl_propertylist_get_int(plist,
"ESO DET NDIT");
520 hdrldemo_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
521 const double ron, cpl_image ** ima_errs)
523 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
524 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
525 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
526 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
528 *ima_errs = cpl_image_duplicate(ima_data);
530 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
534 cpl_image_divide_scalar(*ima_errs, gain);
535 cpl_image_add_scalar(*ima_errs, ron * ron);
536 cpl_image_power(*ima_errs, 0.5);
538 return cpl_error_get_code();
543 static cpl_error_code
544 detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
547 const char * tag_off,
548 const char * recipe_name,
549 const char * pipeline_name,
550 const char * pafregexp,
551 const cpl_propertylist * pro_lintbl,
552 const cpl_propertylist * pro_gaintbl,
553 const cpl_propertylist * pro_coeffscube,
554 const cpl_propertylist * pro_bpm,
555 const cpl_propertylist * pro_corr,
556 const cpl_propertylist * pro_diff,
557 const char * package,
559 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
560 const cpl_boolean opt_nir,
561 const cpl_parameterlist * parlist,
564 static double irplib_compute_err(
double gain,
double ron,
double photon_noise);
566 static cpl_error_code
567 detmon_lg_dfs_save_imagelist(cpl_frameset * frameset,
568 const cpl_parameterlist * parlist,
569 const cpl_frameset *usedframes,
570 const cpl_imagelist *coeffs,
571 const char *recipe_name,
572 const cpl_propertylist *mypro_coeffscube,
573 const char * package,
574 const char * name_o);
577 static void irplib_free(
char** pointer){
579 if(pointer && *pointer) {
585 static cpl_error_code
586 detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
int nsets,
588 const char * tag_off,
589 const char * recipe_name,
590 const char * pipeline_name,
591 const char * pafregexp,
592 const cpl_propertylist * pro_lintbl,
593 const cpl_propertylist * pro_gaintbl,
594 const cpl_propertylist * pro_coeffscube,
595 const cpl_propertylist * pro_bpm,
596 const cpl_propertylist * pro_corr,
597 const cpl_propertylist * pro_diff,
598 const char * package,
600 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
601 const cpl_boolean opt_nir,
602 const cpl_parameterlist * parlist,
607 int nexts = detmon_lg_config.nb_extensions;
609 double* exptime_on = 0;
610 double* exptime_off = 0;
613 cpl_frameset * cur_fset = NULL;
614 cpl_frameset* cur_fset_on = 0;
615 cpl_frameset* cur_fset_off = 0;
620 cpl_frameset_duplicate(frameset) : cpl_frameset_extract(frameset, selection, i);
623 skip_if(cur_fset == NULL);
626 cur_fset_on = cpl_frameset_new();
627 cur_fset_off = cpl_frameset_new();
628 cpl_msg_info(cpl_func,
"Splitting into ON and OFF sub-framesets");
629 skip_if (detmon_lg_split_onoff(cur_fset,
630 cur_fset_on, cur_fset_off,
632 if (cpl_frameset_get_size(cur_fset_on) == 0)
634 cpl_msg_error(cpl_func,
"No lamp frames in input");
638 if (cpl_frameset_get_size(cur_fset_off) == 0)
640 cpl_msg_error(cpl_func,
"No dark / bias frames in input");
643 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));
651 exptime_on = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_on));
652 exptime_off = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_off));
654 index_on = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_on));
655 index_off = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_off));
656 irplib_frameset_sort(cur_fset_on, index_on, exptime_on);
657 irplib_frameset_sort(cur_fset_off, index_off, exptime_off);
670 skip_if(detmon_check_order(exptime_on, cpl_frameset_get_size(cur_fset_on), detmon_lg_config.tolerance, detmon_lg_config.order));
672 if(detmon_lg_config.exts >= 0)
680 if (detmon_lg_config.lamp_ok) {
681 skip_if(detmon_opt_lampcr(cur_fset, 0));
684 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
689 detmon_lg_config.exts,
691 recipe_name, pipeline_name, pafregexp,
692 pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff,
693 package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
695 for(j = 1; j <= nexts; j++) {
702 if (detmon_lg_config.lamp_ok) {
703 skip_if(detmon_opt_lampcr(cur_fset, j));
707 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
712 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));
717 cpl_frameset_delete(cur_fset);
718 cpl_frameset_delete(cur_fset_on);
719 cpl_frameset_delete(cur_fset_off);
722 cpl_free(exptime_on);
723 cpl_free(exptime_off);
724 return cpl_error_get_code();
802 detmon_lg(cpl_frameset * frameset,
803 const cpl_parameterlist * parlist,
805 const char * tag_off,
806 const char * recipe_name,
807 const char * pipeline_name,
808 const char * pafregexp,
809 const cpl_propertylist * pro_lintbl,
810 const cpl_propertylist * pro_gaintbl,
811 const cpl_propertylist * pro_coeffscube,
812 const cpl_propertylist * pro_bpm,
813 const cpl_propertylist * pro_corr,
814 const cpl_propertylist * pro_diff,
815 const char * package,
816 int (* compare) (
const cpl_frame *,
818 int (* load_fset) (
const cpl_frameset *,
821 const cpl_boolean opt_nir)
823 cpl_errorstate cleanstate = cpl_errorstate_get();
825 cpl_size * selection = NULL;
826 cpl_frame * first = NULL;
827 cpl_image * reference = NULL;
834 cpl_frameset * cur_fset = NULL;
835 cpl_frameset * cur_fset_on = NULL;
836 cpl_frameset * cur_fset_off = NULL;
839 cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
840 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
841 cpl_ensure_code(tag_on != NULL, CPL_ERROR_NULL_INPUT);
842 cpl_ensure_code(tag_off != NULL, CPL_ERROR_NULL_INPUT);
843 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
844 cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
845 cpl_ensure_code(pro_lintbl != NULL, CPL_ERROR_NULL_INPUT);
846 cpl_ensure_code(pro_gaintbl != NULL, CPL_ERROR_NULL_INPUT);
847 cpl_ensure_code(pro_coeffscube != NULL, CPL_ERROR_NULL_INPUT);
848 cpl_ensure_code(pro_bpm != NULL, CPL_ERROR_NULL_INPUT);
849 cpl_ensure_code(pro_corr != NULL, CPL_ERROR_NULL_INPUT);
850 cpl_ensure_code(pro_diff != NULL, CPL_ERROR_NULL_INPUT);
851 cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
853 cpl_msg_info(cpl_func,
"frameset size [%" CPL_SIZE_FORMAT
"]", cpl_frameset_get_size(frameset));
856 skip_if (detmon_lg_dfs_set_groups(frameset, tag_on, tag_off));
863 skip_if (detmon_lg_retrieve_parlist(pipeline_name, recipe_name,
871 first = cpl_frameset_get_first(frameset);
872 irplib_ensure (first != NULL, CPL_ERROR_ILLEGAL_INPUT,
"Empty data set! Provide %s and %s input frames",tag_on,tag_off);
874 detmon_lg_config.load_fset = load_fset;
875 detmon_lg_config.load_fset_wrp = load_fset ? irplib_load_fset_wrp_ext : irplib_load_fset_wrp;
878 detmon_lg_config.nb_extensions = 1;
879 if (detmon_lg_config.exts < 0) {
881 detmon_lg_config.nb_extensions = cpl_frame_get_nextensions(first);
882 while (reference == NULL && i <= detmon_lg_config.nb_extensions) {
883 reference = cpl_image_load(cpl_frame_get_filename(first),
884 CPL_TYPE_FLOAT, 0, i);
885 if (reference == NULL) {
886 cpl_msg_warning(cpl_func,
"Extension %d empty, skipping", i);
887 cpl_errorstate_set(cleanstate);
891 cpl_errorstate_set(cleanstate);
892 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
893 "No data found in any extension");
894 cpl_msg_info(cpl_func,
"Using extension %d as reference", i - 1);
896 if (load_fset != NULL) {
897 cpl_frameset *
new = cpl_frameset_new();
898 cpl_imagelist * p = cpl_imagelist_new();
899 cpl_frameset_insert(
new, cpl_frame_duplicate(first));
900 (*load_fset)(
new, CPL_TYPE_FLOAT, p);
901 reference = cpl_image_duplicate(cpl_imagelist_get(p, 0));
902 cpl_imagelist_delete(p);
903 cpl_frameset_delete(
new);
905 cpl_msg_info(cpl_func,
"name=%s",cpl_frame_get_filename(first));
906 reference = cpl_image_load(cpl_frame_get_filename(first),
907 CPL_TYPE_FLOAT, 0, detmon_lg_config.exts);
909 cpl_errorstate_set(cleanstate);
910 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
911 "No data found in requested extension %d",
912 detmon_lg_config.exts);
914 skip_if (reference == NULL);
916 skip_if (detmon_lg_check_defaults(reference));
925 if (compare == NULL) {
928 cpl_msg_info(cpl_func,
"Identifying different settings");
929 selection = cpl_frameset_labelise(frameset, compare, &nsets);
930 skip_if (selection == NULL);
934 for(
int i = 0; i < nsets; i++)
936 int fr_size = cpl_frameset_get_size(frameset);
938 cpl_msg_info(cpl_func,
"Reduce data set nb %d out of %" CPL_SIZE_FORMAT
"",
940 skip_if(detmon_lg_reduce_set(i, frameset, nsets, tag_on, tag_off,
955 fr_size_new = cpl_frameset_get_size(frameset);
961 if (fr_size_new > fr_size)
963 selection = cpl_realloc(selection, fr_size_new *
sizeof(selection[0]));
964 memset(selection + fr_size, -1, (fr_size_new - fr_size) *
sizeof(selection[0]));
970 cpl_frameset_delete(cur_fset);
971 cpl_frameset_delete(cur_fset_on);
972 cpl_frameset_delete(cur_fset_off);
974 cpl_image_delete(reference);
976 return cpl_error_get_code();
1012 static cpl_error_code
1013 detmon_lg_core(cpl_frameset * cur_fset_on,
1014 cpl_frameset * cur_fset_off,
1017 double * exptime_on,
1018 double * exptime_off,
1021 const char * recipe_name,
1022 const char * pipeline_name,
1023 const char * pafregexp,
1024 const cpl_propertylist * pro_lintbl,
1025 const cpl_propertylist * pro_gaintbl,
1026 const cpl_propertylist * pro_coeffscube,
1027 const cpl_propertylist * pro_bpm,
1028 const cpl_propertylist * pro_corr,
1029 const cpl_propertylist * pro_diff,
1030 const char * package,
1031 int (* load_fset) (
const cpl_frameset *,
1034 int nsets, cpl_boolean opt_nir,
1035 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
1036 cpl_frameset * cur_fset)
1038 cpl_table * gain_table = cpl_table_new(
1039 cpl_frameset_get_size(cur_fset_on) / 2);
1040 cpl_table * linear_table = cpl_table_new(
1041 cpl_frameset_get_size(cur_fset_on) / 2);
1042 cpl_imagelist * coeffs = NULL;
1043 cpl_image * bpm = NULL;
1044 cpl_imagelist * autocorr_images = NULL;
1045 cpl_imagelist * diff_flats = NULL;
1046 cpl_propertylist * gaint_qclist = NULL;
1047 cpl_propertylist * lint_qclist = NULL;
1048 cpl_propertylist * linc_qclist = NULL;
1049 cpl_propertylist * bpm_qclist = NULL;
1051 int next_index_on = 0;
1052 int next_index_off = 0;
1055 cpl_msg_info(cpl_func,
"Reduce extension nb %d ", whichext);
1059 if (detmon_lg_config.intermediate) {
1060 autocorr_images = cpl_imagelist_new();
1061 diff_flats = cpl_imagelist_new();
1064 gaint_qclist = cpl_propertylist_new();
1065 lint_qclist = cpl_propertylist_new();
1066 linc_qclist = cpl_propertylist_new();
1067 bpm_qclist = cpl_propertylist_new();
1070 cpl_msg_info(cpl_func,
"Starting data reduction");
1071 if (detmon_lg_reduce(cur_fset_on, cur_fset_off,
1072 index_on, index_off, exptime_on, exptime_off,
1073 &next_index_on, &next_index_off,
1074 &coeffs, gain_table,
1075 linear_table, &bpm, autocorr_images,
1076 diff_flats, gaint_qclist, lint_qclist,
1077 linc_qclist, bpm_qclist, load_fset,
1078 opt_nir, whichext) == CPL_ERROR_CONTINUE) {
1079 cpl_msg_info(cpl_func,
"Empty extension %d", whichext);
1083 cpl_msg_info(cpl_func,
"Saving the products");
1086 detmon_lg_save(parlist, frameset, recipe_name,
1087 pipeline_name, pafregexp,
1088 pro_lintbl, pro_gaintbl,
1089 pro_coeffscube, pro_bpm,
1090 pro_corr, pro_diff, package,
1091 coeffs, gain_table, linear_table,
1092 bpm, autocorr_images, diff_flats,
1093 gaint_qclist, lint_qclist, linc_qclist,
1094 bpm_qclist, 0, 0, cur_fset, whichext));
1097 detmon_lg_save(parlist, frameset, recipe_name,
1098 pipeline_name, pafregexp,
1099 pro_lintbl, pro_gaintbl,
1100 pro_coeffscube, pro_bpm,
1101 pro_corr, pro_diff, package,
1102 coeffs, gain_table, linear_table,
1103 bpm, autocorr_images, diff_flats,
1104 gaint_qclist, lint_qclist, linc_qclist,
1105 bpm_qclist, 1, whichset+ 1, cur_fset,
1113 cpl_table_delete(gain_table);
1114 cpl_table_delete(linear_table);
1115 cpl_imagelist_delete(coeffs);
1116 cpl_propertylist_delete(gaint_qclist);
1117 cpl_propertylist_delete(lint_qclist);
1118 cpl_propertylist_delete(linc_qclist);
1119 if(bpm_qclist != NULL) cpl_propertylist_delete(bpm_qclist);
1120 cpl_image_delete(bpm);
1121 cpl_imagelist_delete(autocorr_images);
1122 cpl_imagelist_delete(diff_flats);
1124 return cpl_error_get_code();
1149 detmon_image_correlate(
const cpl_image * image1,
1150 const cpl_image * image2,
1151 const int m,
const int n)
1153 cpl_image *image1_padded = NULL;
1154 cpl_image *image2_padded = NULL;
1158 cpl_image *corr_image_window = NULL;
1160 cpl_image* image_ri1 = NULL;
1161 cpl_image* image_ri2 = NULL;
1162 cpl_error_code err = CPL_ERROR_NONE;
1165 cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1166 cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1168 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1169 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1171 nx = cpl_image_get_size_x(image1);
1172 ny = cpl_image_get_size_y(image1);
1174 nx2 = cpl_image_get_size_x(image2);
1175 ny2 = cpl_image_get_size_y(image2);
1178 cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
1181 image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1182 cpl_image_copy(image1_padded, image1, m + 1, n + 1);
1184 image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1185 cpl_image_copy(image2_padded, image2, m + 1, n + 1);
1191 image_ri1 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
1192 image_ri2 = cpl_image_new(nx, ny , CPL_TYPE_FLOAT_COMPLEX);
1194 cpl_fft_image(image_ri1, image1_padded, CPL_FFT_FORWARD);
1195 cpl_fft_image(image_ri2, image2_padded, CPL_FFT_FORWARD);
1196 err = cpl_error_get_code();
1197 cpl_image_delete(image1_padded);
1198 image1_padded = NULL;
1199 cpl_image_delete(image2_padded);
1200 image2_padded = NULL;
1201 if (err == CPL_ERROR_NONE)
1204 cpl_image * corr_image = NULL;
1205 cpl_image * reorganised= NULL;
1206 cpl_image * image_ri_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1207 cpl_image * image_in_inv = cpl_image_new(nx, ny,
1208 CPL_TYPE_FLOAT_COMPLEX);
1211 for (i = 1; i <= nx; i++)
1213 for (j = 1; j <= ny; j++)
1216 double complex value1, value2, value;
1217 value1 = cpl_image_get_complex(image_ri1, i, j, &rej);
1218 value2 = cpl_image_get_complex(image_ri2, i, j, &rej);;
1219 value = conj(value1) * value2;
1220 cpl_image_set_complex(image_in_inv, i, j, value);
1223 cpl_image_delete(image_ri1);
1225 cpl_image_delete(image_ri2);
1228 err = cpl_error_get_code();
1229 if (err == CPL_ERROR_NONE)
1233 cpl_fft_image(image_ri_inv, image_in_inv,CPL_FFT_BACKWARD);
1234 cpl_image_delete(image_in_inv);
1237 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1238 for (i = 1; i <= nx; i++)
1240 for (j = 1; j <= ny; j++)
1244 value = cpl_image_get(image_ri_inv, i, j, &rej);
1245 cpl_image_set(corr_image, i, j, value);
1248 cpl_image_delete(image_ri_inv);
1249 err = cpl_error_get_code();
1250 if (err == CPL_ERROR_NONE)
1254 cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
1255 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1257 cpl_image_copy(reorganised, image, 1, 1);
1258 cpl_image_delete(image);
1259 image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
1260 cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
1261 cpl_image_delete(image);
1263 cpl_image_delete(corr_image);
1265 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1266 image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
1267 cpl_image_copy(corr_image, image, 1, 1);
1268 cpl_image_delete(image);
1270 image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
1271 cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
1272 cpl_image_delete(image);
1274 corr_image_window = cpl_image_extract(corr_image,
1277 nx / 2 + 1 + m, ny / 2 + 1 + n);
1282 cpl_image_delete(reorganised);
1283 cpl_image_delete(corr_image);
1285 if(cpl_image_divide_scalar(corr_image_window,
1286 cpl_image_get_max(corr_image_window))) {
1287 cpl_image_delete(corr_image_window);
1291 cpl_image_delete (image_ri1);
1292 cpl_image_delete (image_ri2);
1293 cpl_image_delete (image1_padded);
1294 cpl_image_delete (image2_padded);
1295 return corr_image_window;
1318 detmon_autocorrelate(
const cpl_image * input2,
const int m,
1321 cpl_image *im_re = NULL;
1322 cpl_image *im_im = NULL;
1324 cpl_image *ifft_re = NULL;
1325 cpl_image *ifft_im = NULL;
1326 cpl_image *autocorr = NULL;
1327 cpl_image *autocorr_norm_double = NULL;
1328 cpl_image *autocorr_norm = NULL;
1329 cpl_image *reorganised = NULL;
1330 cpl_image *image = NULL;
1332 cpl_error_code error;
1335 cpl_ensure(input2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1337 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1338 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1340 nx = cpl_image_get_size_x(input2) + 2 * m;
1341 ny = cpl_image_get_size_y(input2) + 2 * n;
1344 while(nx > p || ny > p) {
1348 input = cpl_image_cast(input2, CPL_TYPE_DOUBLE);
1350 im_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1351 error = cpl_image_copy(im_re, input, 1, 1);
1352 cpl_ensure(!error, error, NULL);
1354 im_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1356 error = cpl_image_fft(im_re, im_im, CPL_FFT_DEFAULT);
1357 cpl_ensure(!error, error, NULL);
1359 ifft_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1360 error = cpl_image_power(im_re, 2);
1361 cpl_ensure(!error, error, NULL);
1363 error = cpl_image_add(ifft_re, im_re);
1364 cpl_ensure(!error, error, NULL);
1366 cpl_image_delete(im_re);
1368 error = cpl_image_power(im_im, 2);
1369 cpl_ensure(!error, error, NULL);
1371 error = cpl_image_add(ifft_re, im_im);
1372 cpl_ensure(!error, error, NULL);
1374 cpl_image_delete(im_im);
1376 ifft_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1378 error = cpl_image_fft(ifft_re, ifft_im, CPL_FFT_INVERSE);
1379 cpl_ensure(!error, error, NULL);
1381 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1383 error = cpl_image_power(ifft_re, 2);
1384 cpl_ensure(!error, error, NULL);
1386 error = cpl_image_add(autocorr, ifft_re);
1387 cpl_ensure(!error, error, NULL);
1389 cpl_image_delete(ifft_re);
1391 error = cpl_image_power(ifft_im, 2);
1392 cpl_ensure(!error, error, NULL);
1394 error = cpl_image_add(autocorr, ifft_im);
1395 cpl_ensure(!error, error, NULL);
1397 cpl_image_delete(ifft_im);
1400 reorganised = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1402 image = cpl_image_extract(autocorr, p / 2 + 1, 1, p, p);
1403 cpl_image_copy(reorganised, image, 1, 1);
1404 cpl_image_delete(image);
1406 image = cpl_image_extract(autocorr, 1, 1, p / 2, p);
1407 cpl_image_copy(reorganised, image, p / 2 + 1, 1);
1408 cpl_image_delete(image);
1410 cpl_image_delete(autocorr);
1412 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1414 image = cpl_image_extract(reorganised, 1, p / 2 + 1, p, p);
1415 cpl_image_copy(autocorr, image, 1, 1);
1416 cpl_image_delete(image);
1418 image = cpl_image_extract(reorganised, 1, 1, p, p / 2);
1419 cpl_image_copy(autocorr, image, 1, p / 2 + 1);
1420 cpl_image_delete(image);
1422 cpl_image_delete(reorganised);
1424 autocorr_norm_double =
1425 cpl_image_extract(autocorr, p / 2 + 1 - m, p / 2 + 1 - n,
1426 p / 2 + 1 + m, p / 2 + 1 + n);
1428 cpl_image_delete(autocorr);
1430 if(cpl_image_divide_scalar(autocorr_norm_double,
1431 cpl_image_get_max(autocorr_norm_double))) {
1432 cpl_image_delete(autocorr_norm_double);
1433 cpl_ensure(0, cpl_error_get_code(), NULL);
1437 autocorr_norm = cpl_image_cast(autocorr_norm_double, CPL_TYPE_FLOAT);
1438 cpl_image_delete(autocorr_norm_double);
1440 cpl_image_delete(input);
1442 return autocorr_norm;
1458 detmon_lg_fill_parlist_nir_default(cpl_parameterlist * parlist,
1459 const char *recipe_name,
1460 const char *pipeline_name)
1462 const cpl_error_code error =
1463 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1509 cpl_ensure_code(!error, error);
1511 return cpl_error_get_code();
1527 detmon_lg_fill_parlist_opt_default(cpl_parameterlist * parlist,
1528 const char *recipe_name,
1529 const char *pipeline_name)
1531 const cpl_error_code error =
1532 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1577 cpl_ensure_code(!error, error);
1579 return cpl_error_get_code();
1583 detmon_lg_fill_parlist_default_mr(cpl_parameterlist * parlist,
1584 const char *recipe_name,
1585 const char *pipeline_name)
1587 char * group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1588 char * par_name = cpl_sprintf(
"%s.%s", group_name,
"regions-file");
1589 cpl_parameter * p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1590 "File containing regions, "
1591 "four comma separated points "
1594 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions-file");
1595 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1596 cpl_parameterlist_append(parlist, p);
1598 cpl_free(group_name);
1600 group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1601 par_name = cpl_sprintf(
"%s.%s", group_name,
"regions");
1602 p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1603 "Colon separated list of regions, four "
1604 "points each, comma separated: "
1605 "llx,lly,urx,ury:llx,...",
1607 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions");
1608 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1609 cpl_parameterlist_append(parlist, p);
1611 cpl_free(group_name);
1613 return cpl_error_get_code();
1617 detmon_lg_fill_parlist_opt_default_mr(cpl_parameterlist * parlist,
1618 const char *recipe_name,
1619 const char *pipeline_name)
1621 detmon_lg_fill_parlist_opt_default(parlist, recipe_name, pipeline_name);
1622 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1623 return cpl_error_get_code();
1627 detmon_lg_fill_parlist_nir_default_mr(cpl_parameterlist * parlist,
1628 const char *recipe_name,
1629 const char *pipeline_name)
1631 detmon_lg_fill_parlist_nir_default(parlist, recipe_name, pipeline_name);
1632 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1634 return cpl_error_get_code();
1694 detmon_lg_fill_parlist(cpl_parameterlist * parlist,
1695 const char *recipe_name,
const char *pipeline_name,
1705 const char *intermediate,
1706 const char *autocorr,
1707 const char *collapse,
1708 const char *rescale,
1709 const char *pix2pix,
1716 const char * pafname,
1733 int llx5,
int lly5,
int urx5,
int ury5,
int exts,
1734 cpl_boolean opt_nir)
1736 const cpl_error_code error =
1737 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 26,
1739 "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
1740 "CPL_TYPE_STRING", method,
1743 "Polynomial order for the fit (Linearity)",
1744 "CPL_TYPE_INT", order,
1746 "Kappa value for the kappa-sigma clipping (Gain)",
1747 "CPL_TYPE_DOUBLE", kappa,
1749 "Number of iterations to compute rms (Gain)",
1750 "CPL_TYPE_INT", niter,
1752 "x coordinate of the lower-left "
1753 "point of the region of interest. If not modified, default value will be 1.",
1754 "CPL_TYPE_INT", llx,
1756 "y coordinate of the lower-left "
1757 "point of the region of interest. If not modified, default value will be 1.",
1758 "CPL_TYPE_INT", lly,
1760 "x coordinate of the upper-right "
1761 "point of the region of interest. If not modified, default value will be X dimension of the input image.",
1762 "CPL_TYPE_INT", urx,
1764 "y coordinate of the upper-right "
1765 "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
1766 "CPL_TYPE_INT", ury,
1768 "User reference level",
1769 "CPL_TYPE_INT", ref_level,
1771 "De-/Activate intermediate products",
1772 "CPL_TYPE_BOOL", intermediate,
1775 "De-/Activate the autocorr option",
1776 "CPL_TYPE_BOOL", autocorr,
1779 "De-/Activate the collapse option",
1780 "CPL_TYPE_BOOL", collapse,
1782 "De-/Activate the image rescale option",
1783 "CPL_TYPE_BOOL", rescale,
1785 "De-/Activate the computation with pixel to pixel accuracy",
1786 "CPL_TYPE_BOOL", pix2pix,
1788 "De-/Activate the binary bpm option",
1789 "CPL_TYPE_BOOL", bpmbin,
1791 "Maximum x-shift for the autocorr",
1794 "Upper limit of Median flux to be filtered",
1795 "CPL_TYPE_INT", filter,
1797 "Maximum y-shift for the autocorr",
1800 "Tolerance for pair discrimination",
1801 "CPL_TYPE_DOUBLE", tolerance,
1804 "Generate PAF file",
1805 "CPL_TYPE_BOOL", pafgen,
1807 "Specific name for PAF file",
1808 "CPL_TYPE_STRING", pafname,
1812 "Activate the multi-exts option. Choose -1 to process all extensions. Choose an extension number"
1813 " to process the appropriate extension.",
1814 "CPL_TYPE_INT", exts,
1817 "Method for computing Fixed Pattern Noise (SMOOTH or HISTOGRAM)",
1818 "CPL_TYPE_STRING",
"HISTOGRAM",
1821 "template size in pixels for smoothing during FPN computation (only for SMOOTH method)",
1825 "all frames with mean saturation above the limit would not be used in linearity calculation",
1826 "CPL_TYPE_DOUBLE", 65535.0,
1829 "all frames with mean flux above the threshold would not be used in gain calculation",
1830 "CPL_TYPE_DOUBLE", 65535.0
1833 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 1,
1834 "coeffs_cube_split",
1835 "if TRUE, the recipe writes as many "
1836 "COEFFS_CUBE_Pi (i=0..order) as the value of "
1837 "the order parameter in a separate file",
1838 "CPL_TYPE_BOOL",
"CPL_FALSE");
1840 if(opt_nir == FALSE) {
1841 const cpl_error_code erroropt =
1842 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
1844 "x coord of the lower-left point of the first "
1845 "field used for contamination measurement. If not modified, default value will be 1.",
1846 "CPL_TYPE_INT", llx1,
1848 "y coord of the lower-left point of the first "
1849 "field used for contamination measurement. If not modified, default value will be 1.",
1850 "CPL_TYPE_INT", lly1,
1852 "x coord of the upper-right point of the first "
1853 "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
1854 "CPL_TYPE_INT", urx1,
1856 "y coord of the upper-right point of the first "
1857 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1858 "CPL_TYPE_INT", ury1,
1860 "x coord of the lower-left point of the second "
1861 "field used for contamination measurement. If not modified, default value will be 1.",
1862 "CPL_TYPE_INT", llx2,
1864 "y coord of the lower-left point of the second "
1865 "field used for contamination measurement. If not modified, default value will be 1.",
1866 "CPL_TYPE_INT", lly2,
1868 "x coord of the upper-right point of the second "
1869 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1870 "CPL_TYPE_INT", urx2,
1872 "y coord of the upper-right point of the second "
1873 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1874 "CPL_TYPE_INT", ury2,
1876 "x coord of the lower-left point of the third "
1877 "field used for contamination measurement. If not modified, default value will be 1.",
1878 "CPL_TYPE_INT", llx3,
1880 "y coord of the lower-left point of the third "
1881 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1882 "CPL_TYPE_INT", lly3,
1884 "x coord of the upper-right point of the third "
1885 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1886 "CPL_TYPE_INT", urx3,
1888 "y coord of the upper-right point of the third "
1889 "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
1890 "CPL_TYPE_INT", ury3,
1892 "x coord of the lower-left point of the fourth "
1893 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1894 "CPL_TYPE_INT", llx4,
1896 "y coord of the lower-left point of the fourth "
1897 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1898 "CPL_TYPE_INT", lly4,
1900 "x coord of the upper-right point of the fourth "
1901 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1902 "CPL_TYPE_INT", urx4,
1904 "y coord of the upper-right point of the fourth "
1905 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1906 "CPL_TYPE_INT", ury4,
1908 "x coord of the lower-left point of the fifth "
1909 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1910 "CPL_TYPE_INT", llx5,
1912 "y coord of the lower-left point of the fifth "
1913 "field used for contamination measurement. If not modified, default value will be 1.",
1914 "CPL_TYPE_INT", lly5,
1916 "x coord of the upper-right point of the fifth "
1917 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1918 "CPL_TYPE_INT", urx5,
1921 "y coord of the upper-right point of the fifth "
1922 "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
1923 "CPL_TYPE_INT", ury5);
1926 cpl_ensure_code(!erroropt, erroropt);
1929 cpl_ensure_code(!error, error);
1931 return cpl_error_get_code();
1944 static cpl_error_code
1945 detmon_lg_retrieve_parlist(
const char * pipeline_name,
1946 const char * recipe_name,
1947 const cpl_parameterlist * parlist,
1948 cpl_boolean opt_nir)
1952 cpl_parameter * par;
1955 par_name = cpl_sprintf(
"%s.%s.method", pipeline_name, recipe_name);
1956 assert(par_name != NULL);
1957 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1958 detmon_lg_config.method = cpl_parameter_get_string(par);
1962 detmon_lg_config.order =
1963 detmon_retrieve_par_int(
"order", pipeline_name, recipe_name,
1967 detmon_lg_config.kappa =
1968 detmon_retrieve_par_double(
"kappa", pipeline_name, recipe_name,
1972 detmon_lg_config.niter =
1973 detmon_retrieve_par_int(
"niter", pipeline_name, recipe_name,
1977 detmon_lg_config.llx =
1978 detmon_retrieve_par_int(
"llx", pipeline_name, recipe_name,
1982 detmon_lg_config.lly =
1983 detmon_retrieve_par_int(
"lly", pipeline_name, recipe_name,
1987 detmon_lg_config.urx =
1988 detmon_retrieve_par_int(
"urx", pipeline_name, recipe_name,
1992 detmon_lg_config.ury =
1993 detmon_retrieve_par_int(
"ury", pipeline_name, recipe_name,
1997 detmon_lg_config.ref_level =
1998 detmon_retrieve_par_int(
"ref_level", pipeline_name, recipe_name,
2003 cpl_sprintf(
"%s.%s.intermediate", pipeline_name, recipe_name);
2004 assert(par_name != NULL);
2005 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2006 detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
2010 par_name = cpl_sprintf(
"%s.%s.autocorr", pipeline_name, recipe_name);
2011 assert(par_name != NULL);
2012 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2013 detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
2017 par_name = cpl_sprintf(
"%s.%s.coeffs_cube_split", pipeline_name, recipe_name);
2018 assert(par_name != NULL);
2019 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2020 detmon_lg_config.split_coeffs = cpl_parameter_get_bool(par);
2024 par_name = cpl_sprintf(
"%s.%s.collapse", pipeline_name, recipe_name);
2025 assert(par_name != NULL);
2026 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2027 detmon_lg_config.collapse = cpl_parameter_get_bool(par);
2031 par_name = cpl_sprintf(
"%s.%s.rescale", pipeline_name, recipe_name);
2032 assert(par_name != NULL);
2033 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2034 detmon_lg_config.rescale = cpl_parameter_get_bool(par);
2038 par_name = cpl_sprintf(
"%s.%s.pix2pix", pipeline_name, recipe_name);
2039 assert(par_name != NULL);
2040 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2041 detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
2045 par_name = cpl_sprintf(
"%s.%s.bpmbin", pipeline_name, recipe_name);
2046 assert(par_name != NULL);
2047 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2048 detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
2052 detmon_lg_config.filter =
2053 detmon_retrieve_par_int(
"filter", pipeline_name,
2054 recipe_name, parlist);
2057 detmon_lg_config.m =
2058 detmon_retrieve_par_int(
"m", pipeline_name, recipe_name, parlist);
2061 detmon_lg_config.n =
2062 detmon_retrieve_par_int(
"n", pipeline_name, recipe_name, parlist);
2065 par_name = cpl_sprintf(
"%s.%s.tolerance", pipeline_name, recipe_name);
2066 assert(par_name != NULL);
2067 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2068 detmon_lg_config.tolerance = cpl_parameter_get_double(par);
2073 par_name = cpl_sprintf(
"%s.%s.pafgen", pipeline_name, recipe_name);
2074 assert(par_name != NULL);
2075 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2076 detmon_lg_config.pafgen = cpl_parameter_get_bool(par);
2080 par_name = cpl_sprintf(
"%s.%s.pafname", pipeline_name, recipe_name);
2081 assert(par_name != NULL);
2082 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2083 detmon_lg_config.pafname = cpl_parameter_get_string(par);
2086 if(opt_nir == OPT) {
2088 detmon_lg_config.llx1 =
2089 detmon_retrieve_par_int(
"llx1", pipeline_name, recipe_name,
2093 detmon_lg_config.lly1 =
2094 detmon_retrieve_par_int(
"lly1", pipeline_name, recipe_name,
2098 detmon_lg_config.urx1 =
2099 detmon_retrieve_par_int(
"urx1", pipeline_name, recipe_name,
2103 detmon_lg_config.ury1 =
2104 detmon_retrieve_par_int(
"ury1", pipeline_name, recipe_name,
2108 detmon_lg_config.llx2 =
2109 detmon_retrieve_par_int(
"llx2", pipeline_name, recipe_name,
2113 detmon_lg_config.lly2 =
2114 detmon_retrieve_par_int(
"lly2", pipeline_name, recipe_name,
2118 detmon_lg_config.urx2 =
2119 detmon_retrieve_par_int(
"urx2", pipeline_name, recipe_name,
2123 detmon_lg_config.ury2 =
2124 detmon_retrieve_par_int(
"ury2", pipeline_name, recipe_name,
2128 detmon_lg_config.llx3 =
2129 detmon_retrieve_par_int(
"llx3", pipeline_name, recipe_name,
2133 detmon_lg_config.lly3 =
2134 detmon_retrieve_par_int(
"lly3", pipeline_name, recipe_name,
2138 detmon_lg_config.urx3 =
2139 detmon_retrieve_par_int(
"urx3", pipeline_name, recipe_name,
2143 detmon_lg_config.ury3 =
2144 detmon_retrieve_par_int(
"ury3", pipeline_name, recipe_name,
2148 detmon_lg_config.llx4 =
2149 detmon_retrieve_par_int(
"llx4", pipeline_name, recipe_name,
2153 detmon_lg_config.lly4 =
2154 detmon_retrieve_par_int(
"lly4", pipeline_name, recipe_name,
2158 detmon_lg_config.urx4 =
2159 detmon_retrieve_par_int(
"urx4", pipeline_name, recipe_name,
2163 detmon_lg_config.ury4 =
2164 detmon_retrieve_par_int(
"ury4", pipeline_name, recipe_name,
2168 detmon_lg_config.llx5 =
2169 detmon_retrieve_par_int(
"llx5", pipeline_name, recipe_name,
2173 detmon_lg_config.lly5 =
2174 detmon_retrieve_par_int(
"lly5", pipeline_name, recipe_name,
2178 detmon_lg_config.urx5 =
2179 detmon_retrieve_par_int(
"urx5", pipeline_name, recipe_name,
2183 detmon_lg_config.ury5 =
2184 detmon_retrieve_par_int(
"ury5", pipeline_name, recipe_name,
2189 detmon_lg_config.exts =
2190 detmon_retrieve_par_int(
"exts", pipeline_name, recipe_name,
2194 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2196 cpl_sprintf(
"%s.%s.fpn_method", pipeline_name, recipe_name);
2197 assert(par_name != NULL);
2198 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2201 const char * str_method = cpl_parameter_get_string(par);
2202 if (strcmp(str_method,
"SMOOTH") == 0)
2204 detmon_lg_config.fpn_method = FPN_SMOOTH;
2206 else if (strcmp(str_method,
"HISTOGRAM") == 0)
2208 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2214 detmon_lg_config.fpn_smooth =
2215 detmon_retrieve_par_int(
"fpn_smooth", pipeline_name, recipe_name,
2219 detmon_lg_config.saturation_limit = 65535;
2221 cpl_sprintf(
"%s.%s.saturation_limit", pipeline_name, recipe_name);
2222 assert(par_name != NULL);
2223 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2226 detmon_lg_config.saturation_limit = cpl_parameter_get_double(par);
2233 detmon_lg_config.gain_threshold = 0;
2235 cpl_sprintf(
"%s.%s.gain_threshold", pipeline_name, recipe_name);
2236 assert(par_name != NULL);
2237 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2240 detmon_lg_config.gain_threshold = cpl_parameter_get_double(par);
2245 if(cpl_error_get_code())
2247 cpl_msg_error(cpl_func,
"Failed to retrieve the input parameters");
2248 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
2252 return cpl_error_get_code();
2262 static cpl_error_code
2263 detmon_lg_check_defaults(
const cpl_image * reference)
2265 const int nx = cpl_image_get_size_x(reference);
2266 const int ny = cpl_image_get_size_y(reference);
2268 detmon_lg_config.nx = nx;
2269 detmon_lg_config.ny = ny;
2271 detmon_lg_config.wholechip = CPL_FALSE;
2273 if(detmon_lg_config.llx == -1)
2274 detmon_lg_config.llx = 1;
2275 if(detmon_lg_config.lly == -1)
2276 detmon_lg_config.lly = 1;
2277 if(detmon_lg_config.urx == -1)
2278 detmon_lg_config.urx = nx;
2279 if(detmon_lg_config.ury == -1)
2280 detmon_lg_config.ury = ny;
2282 if (detmon_lg_config.llx == 1 &&
2283 detmon_lg_config.lly == 1 &&
2284 detmon_lg_config.urx == nx &&
2285 detmon_lg_config.ury == ny)
2286 detmon_lg_config.wholechip = CPL_TRUE;
2288 if(detmon_lg_config.llx1 == -1)
2289 detmon_lg_config.llx1 = 1;
2290 if(detmon_lg_config.lly1 == -1)
2291 detmon_lg_config.lly1 = 1;
2292 if(detmon_lg_config.urx1 == -1)
2293 detmon_lg_config.urx1 = nx;
2294 if(detmon_lg_config.ury1 == -1)
2295 detmon_lg_config.ury1 = ny;
2297 if(detmon_lg_config.llx2 == -1)
2298 detmon_lg_config.llx2 = 1;
2299 if(detmon_lg_config.lly2 == -1)
2300 detmon_lg_config.lly2 = 1;
2301 if(detmon_lg_config.urx2 == -1)
2302 detmon_lg_config.urx2 = nx / 2;
2303 if(detmon_lg_config.ury2 == -1)
2304 detmon_lg_config.ury2 = ny / 2;
2306 if(detmon_lg_config.llx3 == -1)
2307 detmon_lg_config.llx3 = 1;
2308 if(detmon_lg_config.lly3 == -1)
2309 detmon_lg_config.lly3 = ny / 2;
2310 if(detmon_lg_config.urx3 == -1)
2311 detmon_lg_config.urx3 = nx / 2;
2312 if(detmon_lg_config.ury3 == -1)
2313 detmon_lg_config.ury3 = ny;
2315 if(detmon_lg_config.llx4 == -1)
2316 detmon_lg_config.llx4 = nx / 2;
2317 if(detmon_lg_config.lly4 == -1)
2318 detmon_lg_config.lly4 = ny / 2;
2319 if(detmon_lg_config.urx4 == -1)
2320 detmon_lg_config.urx4 = nx;
2321 if(detmon_lg_config.ury4 == -1)
2322 detmon_lg_config.ury4 = ny;
2324 if(detmon_lg_config.llx5 == -1)
2325 detmon_lg_config.llx5 = nx / 2;
2326 if(detmon_lg_config.lly5 == -1)
2327 detmon_lg_config.lly5 = 1;
2328 if(detmon_lg_config.urx5 == -1)
2329 detmon_lg_config.urx5 = nx;
2330 if(detmon_lg_config.ury5 == -1)
2331 detmon_lg_config.ury5 = ny / 2;
2333 if(detmon_lg_config.intermediate == TRUE) {
2334 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.");
2335 detmon_lg_config.autocorr = TRUE;
2339 detmon_lg_config.lamp_stability = 0.0;
2341 detmon_lg_config.lamp_ok = FALSE;
2343 detmon_lg_config.cr = 0.0;
2345 return cpl_error_get_code();
2360 static cpl_error_code
2361 detmon_lg_split_onoff(
const cpl_frameset * cur_fset,
2362 cpl_frameset * cur_fset_on,
2363 cpl_frameset * cur_fset_off,
2365 const char *tag_off)
2370 cpl_frame * cur_frame_dup = NULL;
2373 const cpl_frame * first;
2374 const cpl_frame * second;
2375 const char * first_tag;
2376 const char * second_tag;
2377 skip_if((first = cpl_frameset_get_first_const(cur_fset)) == NULL);
2378 skip_if((second = cpl_frameset_get_next_const (cur_fset)) == NULL);
2380 skip_if((first_tag = cpl_frame_get_tag(first)) == NULL);
2381 skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
2382 if (opt_nir == OPT &&
2383 ((!strcmp(first_tag, tag_on ) && !strcmp(second_tag, tag_off)) ||
2384 (!strcmp(first_tag, tag_off) && !strcmp(second_tag, tag_on )))) {
2385 detmon_lg_config.lamp_ok = TRUE;
2389 nframes = cpl_frameset_get_size(cur_fset);
2390 for(i = detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
2391 const cpl_frame * cur_frame =
2392 cpl_frameset_get_position_const(cur_fset, i);
2396 cur_frame_dup = cpl_frame_duplicate(cur_frame);
2397 tag = (
char *) cpl_frame_get_tag(cur_frame_dup);
2400 if(!strcmp(tag, tag_on)) {
2401 skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
2402 }
else if(!strcmp(tag, tag_off)) {
2403 skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
2405 cpl_frame_delete(cur_frame_dup);
2406 cur_frame_dup = NULL;
2409 cur_frame_dup = NULL;
2413 cpl_frame_delete(cur_frame_dup);
2415 return cpl_error_get_code();
2442 static cpl_error_code
2443 detmon_lg_reduce(
const cpl_frameset * set_on,
2444 const cpl_frameset * set_off,
2445 int* index_on,
int* index_off,
2446 double* exptime_on,
double* exptime_off,
2447 int *next_index_on,
int* next_index_off,
2448 cpl_imagelist ** coeffs_ptr,
2449 cpl_table * gain_table,
2450 cpl_table * linear_table,
2451 cpl_image ** bpm_ptr,
2452 cpl_imagelist * autocorr_images,
2453 cpl_imagelist * diff_flats,
2454 cpl_propertylist * gaint_qclist,
2455 cpl_propertylist * lint_qclist,
2456 cpl_propertylist * linc_qclist,
2457 cpl_propertylist * bpm_qclist,
2458 int (* load_fset) (
const cpl_frameset *,
2461 const cpl_boolean opt_nir,
2464 cpl_errorstate prestate = cpl_errorstate_get();
2465 const double D_INVALID_VALUE = -999;
2467 cpl_imagelist * linearity_inputs = NULL;
2468 cpl_imagelist * opt_offs = NULL;
2470 cpl_propertylist * reflist = NULL;
2472 int rows_linear_affected = 1;
2473 int rows_gain_affected = 1;
2474 int last_linear_best = 0;
2475 int last_gain_best = 0;
2477 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2478 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2480 nsets = cpl_frameset_get_size(set_on) / 2;
2482 detmon_lg_config.load_fset = load_fset;
2483 if(detmon_lg_config.collapse) {
2490 const cpl_frame *first = cpl_frameset_get_first_const(set_off);
2491 cpl_frame *dup_first = cpl_frame_duplicate(first);
2493 const cpl_frame *second = cpl_frameset_get_next_const(set_off);
2494 cpl_frame *dup_second = cpl_frame_duplicate(second);
2496 cpl_frameset *raw_offs = cpl_frameset_new();
2498 skip_if(cpl_frameset_insert(raw_offs, dup_first));
2499 skip_if(cpl_frameset_insert(raw_offs, dup_second));
2501 opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
2504 cpl_frameset_delete(raw_offs);
2505 if (opt_offs == NULL) {
2506 cpl_errorstate_set(prestate);
2507 return CPL_ERROR_CONTINUE;
2511 skip_if(detmon_lg_reduce_init(gain_table,
2523 if(detmon_lg_lamp_stab(set_on, set_off,
2524 opt_nir, whichext)) {
2525 cpl_errorstate_set(prestate);
2528 if(!detmon_lg_config.collapse)
2532 skip_if(cpl_table_unselect_all(linear_table));
2533 skip_if(cpl_table_unselect_all(gain_table));
2537 for(i = 0; i < nsets ; i++)
2539 skip_if(detmon_lg_reduce_dit(set_on,
2540 index_on, exptime_on,
2544 index_off, exptime_off,
2545 next_index_on, next_index_off,
2547 gain_table, linearity_inputs,
2548 lint_qclist, opt_nir,
2549 autocorr_images, diff_flats,
2551 &rows_linear_affected,&rows_gain_affected));
2555 if (rows_linear_affected == 0)
2557 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2558 "into linear calculation, check the messages above");
2559 cpl_table_select_row(linear_table, i);
2563 last_linear_best = i;
2566 if (rows_gain_affected == 0)
2568 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2569 "into gain calculation, check the messages above");
2570 cpl_table_select_row(gain_table, i);
2581 skip_if(detmon_add_adl_column(linear_table, opt_nir));
2587 skip_if(cpl_table_erase_selected(gain_table));
2588 skip_if(cpl_table_erase_selected(linear_table));
2591 reflist = cpl_propertylist_new();
2592 skip_if(cpl_propertylist_append_bool(reflist,
"ADU", FALSE));
2593 skip_if(cpl_table_sort(gain_table, reflist));
2599 skip_if(detmon_lg_reduce_all(linear_table,
2600 gaint_qclist, lint_qclist, linc_qclist,
2601 bpm_qclist, coeffs_ptr, bpm_ptr,
2603 gain_table, whichext, opt_nir));
2606 double gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
2609 cpl_error_code cplerr = cpl_error_get_code();
2610 if (cplerr != CPL_ERROR_NONE || (gain == 0.0))
2612 cpl_msg_warning(cpl_func,
"Cannot read gain from QC parameters - "
2613 "FPN will not be computed");
2618 detmon_fpn_compute(set_on, index_on, last_linear_best, lint_qclist,
2619 detmon_lg_config.llx,
2620 detmon_lg_config.lly,
2621 detmon_lg_config.urx,
2622 detmon_lg_config.ury,
2625 detmon_lg_config.fpn_method,
2626 detmon_lg_config.fpn_smooth);
2631 detmon_table_fill_invalid(gain_table, D_INVALID_VALUE);
2633 cpl_imagelist_delete(linearity_inputs);
2634 cpl_imagelist_delete(opt_offs);
2635 cpl_propertylist_delete(reflist);
2637 return cpl_error_get_code();
2640 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code)
2642 int ncols = cpl_table_get_ncol(ptable);
2643 cpl_array* pnames = cpl_table_get_column_names(ptable);
2644 int nrows = cpl_table_get_nrow(ptable);
2646 for (i=0; i < ncols; i++)
2649 for (j = 0; j< nrows; j++)
2651 const char* colname = cpl_array_get_data_string_const(pnames)[i];
2653 cpl_type type = cpl_table_get_column_type(ptable, colname);
2654 cpl_table_get(ptable, colname, j, &isnull);
2657 if (type == CPL_TYPE_DOUBLE)
2659 cpl_table_set(ptable,colname,j, code);
2661 else if (type == CPL_TYPE_FLOAT)
2663 cpl_table_set_float(ptable,colname,j, (
float)code);
2668 cpl_array_delete(pnames);
2669 return cpl_error_get_code();
2672 static cpl_error_code
2673 detmon_fpn_compute(
const cpl_frameset *set_on,
2675 int last_linear_best,
2676 cpl_propertylist *lint_qclist,
2683 FPN_METHOD fpn_method,
2687 const cpl_image* im1 = 0;
2689 cpl_imagelist* ons = 0;
2690 cpl_frameset * pair_on = 0;
2691 int nsets_extracted = cpl_frameset_get_size(set_on);
2692 cpl_size * selection = NULL;
2701 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
2702 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
2704 selection[index_on[last_linear_best*2 + 0] ] = 1;
2705 selection[index_on[last_linear_best*2 + 1] ] = 1;
2706 pair_on = cpl_frameset_extract(set_on, selection, 1);
2707 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2709 skip_if(ons == NULL);
2710 skip_if((im1 = cpl_imagelist_get_const(ons, 0)) == NULL);
2712 fpn = irplib_fpn_lg(im1, range, gain, fpn_method, smooth_size, &mse);
2713 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_FPN,
2715 skip_if(cpl_propertylist_append_double(lint_qclist,
"ESO QC GAIN ERR",
2719 cpl_frameset_delete(pair_on);
2720 cpl_imagelist_delete(ons);
2721 cpl_free(selection);
2722 return cpl_error_get_code();
2734 static cpl_error_code
2735 detmon_lg_lamp_stab(
const cpl_frameset * lamps,
2736 const cpl_frameset * darks,
2737 cpl_boolean opt_nir,
2750 cpl_vector * selection = NULL;
2751 cpl_propertylist * plist;
2752 double dit_lamp, dit_dark;
2754 cpl_imagelist * lamps_data = NULL;
2755 cpl_imagelist * darks_data = NULL;
2756 double * stab_levels = NULL;
2758 double * ditvals = NULL;
2762 cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
2763 CPL_ERROR_ILLEGAL_INPUT);
2769 cpl_msg_info(__func__,
"Checking DIT consistency");
2770 selection = cpl_vector_new(nb_lamps);
2771 ditvals = cpl_malloc(nb_lamps *
sizeof(
double));
2773 for (i = 0; i < nb_lamps; i++) {
2774 const cpl_frame * c_lamp;
2775 const cpl_frame * c_dark;
2777 skip_if (cpl_error_get_code());
2780 c_lamp = cpl_frameset_get_position_const(lamps, i);
2781 plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
2783 dit_lamp = (double)irplib_pfits_get_dit(plist);
2785 dit_lamp = (double)irplib_pfits_get_dit_opt(plist);
2786 cpl_propertylist_delete(plist);
2787 skip_if (cpl_error_get_code());
2790 c_dark = cpl_frameset_get_position_const(darks, i);
2791 plist = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
2793 dit_dark = (double)irplib_pfits_get_dit(plist);
2795 dit_dark = (double)irplib_pfits_get_dit_opt(plist);
2796 cpl_propertylist_delete(plist);
2797 skip_if (cpl_error_get_code());
2800 if (fabs(dit_dark-dit_lamp) > 1e-3) {
2801 cpl_msg_error(__func__,
"DIT not consistent between LAMP and DARK, skip lamp stability computation");
2806 ditvals[i] = dit_lamp;
2809 cpl_vector_set(selection, i, -1.0);
2817 if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
2818 cpl_vector_set(selection, i, -1.0);
2822 cpl_vector_set(selection, i, 1.0);
2829 cpl_msg_info(__func__,
"Not enough frames for stability check");
2833 cpl_msg_info(__func__,
"Compute the differences lamp - dark");
2836 lamps_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2838 detmon_lg_config.llx,
2839 detmon_lg_config.lly,
2840 detmon_lg_config.urx,
2841 detmon_lg_config.ury,
2844 darks_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2846 detmon_lg_config.llx,
2847 detmon_lg_config.lly,
2848 detmon_lg_config.urx,
2849 detmon_lg_config.ury,
2852 nb_darks=cpl_imagelist_get_size(darks_data);
2853 if(nb_darks==nb_lamps) {
2854 skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
2856 cpl_image* master_dark=cpl_imagelist_collapse_median_create(darks_data);
2857 cpl_imagelist_subtract_image(lamps_data,master_dark);
2858 cpl_image_delete(master_dark);
2861 cpl_msg_info(__func__,
"Check the lamp stability");
2862 stab_levels = cpl_malloc(dit_stab *
sizeof(
double));
2864 for (i=0; i<nb_lamps; i++) {
2865 if (cpl_vector_get(selection, i) < 0) {
2867 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
2873 for (i=1; i<dit_stab; i++) {
2874 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
2875 detmon_lg_config.lamp_stability)
2876 detmon_lg_config.lamp_stability =
2877 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
2882 if (detmon_lg_config.lamp_stability > 0.01) {
2883 cpl_msg_warning(__func__,
2884 "Lamp stability level %g difference too high - proceed anyway",detmon_lg_config.lamp_stability);
2891 cpl_vector_delete(selection);
2892 cpl_imagelist_delete(lamps_data);
2893 cpl_imagelist_delete(darks_data);
2894 cpl_free(stab_levels);
2896 return cpl_error_get_code();
2923 static cpl_error_code
2924 detmon_lg_reduce_dit(
const cpl_frameset * set_on,
2925 int* index_on,
double* exptime_on,
2928 const cpl_frameset * set_off,
2929 int * index_off,
double* exptime_off,
2930 int* next_on,
int* next_off,
2931 cpl_table * linear_table,
2932 cpl_table * gain_table,
2933 cpl_imagelist * linearity_inputs,
2934 cpl_propertylist * qclist,
2935 cpl_boolean opt_nir,
2936 cpl_imagelist * autocorr_images,
2937 cpl_imagelist * diff_flats,
2938 cpl_imagelist * opt_offs,
2940 int* rows_linear_affected,
2941 int* rows_gain_affected)
2943 cpl_frameset * pair_on = NULL;
2944 cpl_frameset * pair_off = NULL;
2945 cpl_imagelist * ons = NULL;
2946 cpl_imagelist * offs = NULL;
2947 cpl_boolean follow = CPL_TRUE;
2948 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
2952 double current_dit = 0;
2954 const char * filename;
2956 cpl_propertylist * plist = NULL;
2957 cpl_propertylist* pDETlist = NULL;
2959 mode = detmon_lg_config.collapse ?
2960 mode | IRPLIB_GAIN_COLLAPSE | IRPLIB_LIN_COLLAPSE:
2961 mode | IRPLIB_GAIN_NO_COLLAPSE | IRPLIB_LIN_NO_COLLAPSE;
2962 mode = detmon_lg_config.pix2pix ?
2963 mode | IRPLIB_LIN_PIX2PIX : mode;
2965 mode | IRPLIB_GAIN_NIR | IRPLIB_LIN_NIR :
2966 mode | IRPLIB_GAIN_OPT | IRPLIB_LIN_OPT ;
2970 skip_if(detmon_pair_extract_next(set_on, index_on, next_on, exptime_on, &pair_on, detmon_lg_config.tolerance));
2971 current_dit = exptime_on[*next_on - 1];
2974 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2975 skip_if(ons == NULL);
2976 cpl_msg_debug(cpl_func,
" Loaded ON images: %" CPL_SIZE_FORMAT
2977 ", exptime[%f]",cpl_imagelist_get_size(ons), current_dit );
2978 if(cpl_imagelist_get_size(ons) != 2)
2980 cpl_msg_error(cpl_func,
"cannot take ON pair, number of images[%"
2981 CPL_SIZE_FORMAT
"]", cpl_imagelist_get_size(ons));
2984 if(detmon_lg_config.filter > 0)
2987 cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
2988 detmon_lg_config.llx,
2989 detmon_lg_config.lly,
2990 detmon_lg_config.urx,
2991 detmon_lg_config.ury);
2993 cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
2994 detmon_lg_config.llx,
2995 detmon_lg_config.lly,
2996 detmon_lg_config.urx,
2997 detmon_lg_config.ury);
3001 if ( med1 > (
double)detmon_lg_config.filter ||
3002 med2 > (
double)detmon_lg_config.filter)
3005 cpl_table_select_row(gain_table, dit_nb);
3006 cpl_table_select_row(linear_table, dit_nb);
3008 cpl_msg_warning(cpl_func,
"Frames of EXPTIME nb %d "
3009 "will not be taken into account for computation "
3010 "as the median of the on frames computed on the "
3011 "user defined region [%d,%d,%d,%d] are above "
3012 "--filter threshold (%d)",
3014 detmon_lg_config.llx,
3015 detmon_lg_config.lly,
3016 detmon_lg_config.urx,
3017 detmon_lg_config.ury,
3018 detmon_lg_config.filter);
3022 if (follow || detmon_lg_config.filter < 0)
3030 if(!detmon_lg_config.collapse)
3047 if (!strcmp(detmon_lg_config.method,
"MED") ||
3048 cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
3050 skip_if(detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off, detmon_lg_config.tolerance));
3054 skip_if(detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
3057 cpl_msg_debug(cpl_func,
" Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
3058 offs = detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
3060 skip_if(offs == NULL);
3061 skip_if(cpl_error_get_code());
3064 offs = (cpl_imagelist *) opt_offs;
3068 if(detmon_lg_config.rescale)
3070 skip_if(detmon_lg_rescale(ons));
3071 if (!detmon_lg_config.collapse &&
3072 !strcmp(detmon_lg_config.method,
"MED"))
3073 skip_if(detmon_lg_rescale(offs));
3078 cpl_frame_get_filename(cpl_frameset_get_first_const(pair_on));
3079 skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
3083 pDETlist = cpl_propertylist_new();
3084 cpl_propertylist_copy_property_regexp(pDETlist, plist,
"DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
3087 irplib_table_create_column(gain_table, pDETlist);
3088 irplib_table_create_column(linear_table, pDETlist);
3091 if(opt_nir == NIR) {
3092 c_dit = irplib_pfits_get_dit(plist);
3093 c_ndit = irplib_pfits_get_ndit(plist);
3095 c_dit = irplib_pfits_get_exptime(plist);
3107 cpl_msg_info(cpl_func,
"Computing GAIN for EXPTIME value nb %d",
3111 if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
3113 cpl_table_erase_column(gain_table,
"MEAN_OFF1");
3114 cpl_table_erase_column(gain_table,
"MEAN_OFF2");
3115 cpl_table_erase_column(gain_table,
"SIG_OFF_DIF");
3116 cpl_table_erase_column(gain_table,
"GAIN");
3117 cpl_table_erase_column(gain_table,
"GAIN_CORR");
3118 cpl_table_new_column(gain_table,
"MEAN_OFF", CPL_TYPE_DOUBLE);
3122 skip_if(detmon_gain_table_fill_row(gain_table,
3125 diff_flats, ons, offs,
3126 detmon_lg_config.kappa,
3127 detmon_lg_config.niter,
3128 detmon_lg_config.llx,
3129 detmon_lg_config.lly,
3130 detmon_lg_config.urx,
3131 detmon_lg_config.ury,
3134 detmon_lg_config.saturation_limit,
3135 detmon_lg_config.gain_threshold,
3136 dit_nb, mode, rows_gain_affected));
3139 skip_if(detmon_check_saturation_on_pair(autocorr_images,
3140 diff_flats,ons,offs,
3141 detmon_lg_config.kappa,
3142 detmon_lg_config.niter,
3143 detmon_lg_config.llx,
3144 detmon_lg_config.lly,
3145 detmon_lg_config.urx,
3146 detmon_lg_config.ury,
3147 detmon_lg_config.saturation_limit,
3148 dit_nb, mode, rows_linear_affected));
3151 if (*rows_gain_affected)
3154 skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
3156 cpl_msg_info(cpl_func,
"Linearity reduction for nb %d",
3159 if (*rows_linear_affected) {
3160 skip_if(detmon_lin_table_fill_row(linear_table, c_dit,
3161 linearity_inputs, ons, offs,
3162 detmon_lg_config.llx,
3163 detmon_lg_config.lly,
3164 detmon_lg_config.urx,
3165 detmon_lg_config.ury,
3166 dit_nb, *dit_nskip, mode));
3168 skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
3180 if(opt_nir == OPT &&
3181 *rows_linear_affected != 0 ) {
3182 detmon_opt_contamination(ons, offs, mode, qclist);
3189 cpl_frameset_delete(pair_on);
3190 cpl_imagelist_delete(ons);
3192 if(!detmon_lg_config.collapse ) {
3193 cpl_imagelist_delete(offs);
3196 if(!detmon_lg_config.collapse) {
3197 cpl_frameset_delete(pair_off);
3200 cpl_propertylist_delete(plist);
3201 cpl_propertylist_delete(pDETlist);
3202 return cpl_error_get_code();
3212 static cpl_error_code
3213 detmon_add_adl_column(cpl_table * table,
3214 cpl_boolean opt_nir)
3216 cpl_error_code error;
3217 double mean_med_dit;
3220 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
3222 mean_med_dit = cpl_table_get_column_mean(table,
"MED_DIT");
3224 dits = cpl_table_get_data_double(table,
"EXPTIME");
3226 dits = cpl_table_get_data_double(table,
"DIT");
3228 error = cpl_table_copy_data_double(table,
"ADL", dits);
3229 cpl_ensure_code(!error, error);
3230 error = cpl_table_multiply_scalar(table,
"ADL", mean_med_dit);
3231 cpl_ensure_code(!error, error);
3233 return cpl_error_get_code();
3245 static cpl_error_code
3246 detmon_lg_reduce_init(cpl_table * gain_table,
3247 cpl_table * linear_table,
3248 cpl_imagelist ** linearity_inputs,
3249 const cpl_boolean opt_nir)
3251 skip_if(detmon_gain_table_create(gain_table, opt_nir));
3252 skip_if(detmon_lin_table_create(linear_table, opt_nir));
3254 if(detmon_lg_config.pix2pix) {
3255 *linearity_inputs = cpl_imagelist_new();
3256 skip_if(*linearity_inputs == NULL);
3261 return cpl_error_get_code();
3272 irplib_pfits_get_dit(
const cpl_propertylist * plist)
3274 return irplib_pfits_get_prop_double(plist,
"ESO DET DIT");
3285 irplib_pfits_get_dit_opt(
const cpl_propertylist * plist)
3287 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3296 static cpl_propertylist*
3297 detmon_load_pro_keys(
const char* NAME_O)
3299 cpl_propertylist* pro_keys=NULL;
3300 pro_keys=cpl_propertylist_load_regexp(NAME_O,0,
"^(ESO PRO)",0);
3305 static double irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
3306 const char* prop_name)
3309 dit = cpl_propertylist_get_double(plist, prop_name);
3310 if(cpl_error_get_code() != CPL_ERROR_NONE)
3312 cpl_msg_error(cpl_func,
"Cannot read property '%s', err[%s]",
3313 prop_name, cpl_error_get_where());
3318 static cpl_error_code
3319 detmon_gain_compute_qc(
double kappa,
int nclip,
const int pos,
3320 const cpl_imagelist* offs,
unsigned mode,
3321 double double_adu,
double avg_on1,
double avg_on2,
3322 double avg_off1,
double avg_off2,
double sigma,
3323 double sig_off_dif,
double gain,
int c_ndit,
3324 double gain_corr,
double autocorr, cpl_image* on_dif,
3325 cpl_table* gain_table)
3329 double avg_on_dif, sig_on_dif;
3330 irplib_ksigma_clip(on_dif, 1, 1, cpl_image_get_size_x(on_dif),
3331 cpl_image_get_size_y(on_dif), kappa, nclip, 1e-5,
3332 &avg_on_dif, &sig_on_dif);
3334 cpl_table_set_double(gain_table,
"SIG_ON_DIF", pos,
3336 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3337 double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
3340 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
3342 sigma = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
3346 gain = double_adu / (c_ndit * sigma);
3348 gain_corr = gain / (autocorr);
3350 skip_if(cpl_table_set_double(gain_table,
"GAIN", pos, gain));
3352 cpl_table_set_double(gain_table,
"GAIN_CORR", pos,
3356 skip_if(cpl_table_set_double(gain_table,
"AUTOCORR", pos, autocorr));
3357 skip_if(cpl_table_set_double(gain_table,
"ADU", pos, double_adu / 2));
3360 cpl_table_set_double(gain_table,
"Y_FIT", pos,
3361 c_ndit * sig_on_dif * sig_on_dif));
3363 cpl_table_set_double(gain_table,
"Y_FIT_CORR", pos,
3364 c_ndit * sig_on_dif * sig_on_dif));
3365 skip_if(cpl_table_set_double(gain_table,
"X_FIT", pos, double_adu));
3367 cpl_table_set_double(gain_table,
"X_FIT_CORR", pos,
3368 double_adu / autocorr));
3372 return cpl_error_get_code();
3376 detmon_gain_prepare_autocorr(
unsigned mode,
const int pos,
double autocorr,
3377 int m,
int n, cpl_imagelist* diff_flats,
3378 cpl_image* on_dif, cpl_imagelist* autocorr_images)
3380 if (mode & IRPLIB_GAIN_WITH_AUTOCORR) {
3382 cpl_image * diff = cpl_image_duplicate(on_dif);
3383 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
3385 if (autocorr_images) {
3386 cpl_image * corr = NULL;
3387 autocorr = detmon_autocorr_factor(on_dif, &corr, m, n);
3389 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
3392 detmon_lg_add_empty_image(autocorr_images, pos);
3396 autocorr = detmon_autocorr_factor(on_dif, NULL, m, n);
3398 autocorr = isnan(autocorr) ? 1.0 : autocorr;
3409 detmon_gain_prepare_table(
const cpl_imagelist* offs,
unsigned mode,
int llx,
3410 int lly,
int urx,
int ury,
double kappa,
int nclip,
3411 double avg_off1,
double std,
const int pos,
3412 cpl_table* gain_table,
double* avg_off2,
3413 double* sig_off_dif)
3420 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3423 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3424 llx, lly, urx, ury, kappa, nclip, 1e-5,
3426 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF", pos, avg_off1));
3429 else if ((mode & IRPLIB_GAIN_NO_COLLAPSE)
3430 || (pos == 0 && mode & IRPLIB_GAIN_COLLAPSE)) {
3431 cpl_image * off_dif = NULL;
3434 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3435 llx, lly, urx, ury, kappa, nclip, 1e-5,
3437 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3439 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 1),
3440 llx, lly, urx, ury, kappa, nclip, 1e-5,
3442 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3443 off_dif = detmon_subtract_create_window(
3444 cpl_imagelist_get_const(offs, 0),
3445 cpl_imagelist_get_const(offs, 1), llx, lly, urx, ury);
3446 skip_if(off_dif == NULL);
3447 irplib_ksigma_clip(off_dif, 1, 1, cpl_image_get_size_x(off_dif),
3448 cpl_image_get_size_y(off_dif), kappa, nclip, 1e-5,
3449 &avg_off_dif, sig_off_dif);
3450 cpl_image_delete(off_dif);
3452 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3455 else if (pos > 0 && (mode & IRPLIB_GAIN_COLLAPSE)) {
3458 avg_off1 = cpl_table_get_double(gain_table,
"MEAN_OFF1", 0, &status);
3459 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3460 *avg_off2 = cpl_table_get_double(gain_table,
"MEAN_OFF2", 0, &status);
3461 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3462 *sig_off_dif = cpl_table_get_double(gain_table,
"SIG_OFF_DIF", 0,
3465 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3510 static cpl_error_code
3511 detmon_gain_table_fill_row(cpl_table * gain_table,
3512 double c_dit,
int c_ndit,
3513 cpl_imagelist * autocorr_images,
3514 cpl_imagelist * diff_flats,
3515 const cpl_imagelist * ons,
3516 const cpl_imagelist * offs,
3517 double kappa,
int nclip,
3518 int llx,
int lly,
int urx,
int ury,
3520 double saturation_limit,
3521 double gain_threshold,
3522 const int pos,
unsigned mode,
int* rows_gain_affected)
3524 const cpl_image *image;
3525 cpl_image *on_dif = NULL;
3527 double avg_on1, avg_on2;
3528 double avg_off1, avg_off2;
3529 double double_adu, autocorr, gain, gain_corr;
3532 cpl_table_set(gain_table,
"FLAG", pos, 1);
3533 if (mode & IRPLIB_GAIN_NIR)
3535 cpl_table_set(gain_table,
"DIT", pos, c_dit);
3536 cpl_table_set(gain_table,
"NDIT", pos, c_ndit);
3537 }
else if (mode & IRPLIB_GAIN_OPT)
3539 cpl_table_set(gain_table,
"EXPTIME", pos, c_dit);
3542 cpl_msg_error(cpl_func,
"Mandatory mode (OPT or NIR) not provided");
3545 if(*rows_gain_affected == 0)
3547 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3548 cpl_table_set(gain_table,
"FLAG", pos, 0);
3549 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3554 detmon_lg_add_empty_image(diff_flats, pos);
3556 if (autocorr_images)
3558 detmon_lg_add_empty_image(autocorr_images, pos);
3561 return cpl_error_get_code();
3563 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3564 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3565 nclip, 1e-5, &avg_on1, &std));
3566 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3567 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3568 nclip, 1e-5, &avg_on2, &std));
3571 (avg_on1 > gain_threshold) ||
3572 (avg_on2 > gain_threshold)
3578 if ( (avg_on1 > gain_threshold) || (avg_on2 > gain_threshold) )
3580 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the gain_theshold parameter, "
3581 "the frames would not be taken into calculation");
3583 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3584 avg_on1, avg_on2, gain_threshold);
3587 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3588 cpl_table_set(gain_table,
"FLAG", pos, 0);
3589 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3594 detmon_lg_add_empty_image(diff_flats, pos);
3596 if (autocorr_images)
3598 detmon_lg_add_empty_image(autocorr_images, pos);
3601 *rows_gain_affected = 0;
3609 *rows_gain_affected = 1;
3610 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON1", pos, avg_on1));
3611 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON2", pos, avg_on2));
3614 detmon_subtract_create_window(cpl_imagelist_get_const(ons, 0),
3615 cpl_imagelist_get_const(ons, 1),
3616 llx, lly, urx, ury);
3617 skip_if(on_dif == NULL);
3619 autocorr = detmon_gain_prepare_autocorr(mode, pos, autocorr, m, n,
3620 diff_flats, on_dif, autocorr_images);
3622 avg_off1 = detmon_gain_prepare_table(offs, mode, llx, lly, urx, ury,
3623 kappa, nclip, avg_off1, std, pos, gain_table, &avg_off2,
3626 detmon_gain_compute_qc(kappa, nclip, pos, offs, mode, double_adu,
3627 avg_on1, avg_on2, avg_off1, avg_off2, sigma,
3628 sig_off_dif, gain, c_ndit, gain_corr, autocorr, on_dif,
3633 cpl_image_delete(on_dif);
3635 return cpl_error_get_code();
3663 static cpl_error_code
3664 detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
3665 cpl_imagelist * diff_flats,
3666 const cpl_imagelist * ons,
3667 const cpl_imagelist * offs,
3668 double kappa,
int nclip,
3669 int llx,
int lly,
int urx,
int ury,
3670 double saturation_limit,
3671 const int pos,
unsigned mode,
int* rows_linear_affected)
3673 const cpl_image *image;
3675 double avg_on1, avg_on2;
3679 if(*rows_linear_affected == 0)
3681 cpl_msg_info(cpl_func,
"For linearity skip the frame #%d", pos + 1);
3682 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3686 detmon_lg_add_empty_image(diff_flats, pos);
3688 if (autocorr_images)
3690 detmon_lg_add_empty_image(autocorr_images, pos);
3693 return cpl_error_get_code();
3695 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3696 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3697 nclip, 1e-5, &avg_on1, &std));
3698 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3699 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3700 nclip, 1e-5, &avg_on2, &std));
3703 (avg_on1 > saturation_limit) ||
3704 (avg_on2 > saturation_limit)
3710 if ( (avg_on1 > saturation_limit) || (avg_on2 > saturation_limit) )
3712 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the saturation_limit parameter, "
3713 "the frames would not be taken into calculation");
3715 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3716 avg_on1, avg_on2, saturation_limit);
3719 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3720 *rows_linear_affected = 0;
3727 return cpl_error_get_code();
3743 detmon_bpixs(
const cpl_imagelist * coeffs,
3750 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
3757 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
3758 cpl_image_get_size_y(first));
3760 cpl_image *bpm = NULL;
3763 int size = cpl_imagelist_get_size(coeffs);
3766 bpm = cpl_image_new(cpl_image_get_size_x(first),
3767 cpl_image_get_size_y(first),
3772 for(
int i = 0; i < size; i++) {
3773 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
3775 cpl_stats* stats = cpl_stats_new_from_image(cur_coeff,
3776 CPL_STATS_MEAN | CPL_STATS_STDEV);
3777 double cur_mean = cpl_stats_get_mean(stats);
3778 double cur_stdev = cpl_stats_get_stdev(stats);
3780 double lo_cut = cur_mean - kappa * cur_stdev;
3781 double hi_cut = cur_mean + kappa * cur_stdev;
3783 cpl_mask* cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
3784 cpl_mask_not(cur_mask);
3787 cpl_image* cur_image = cpl_image_new_from_mask(cur_mask);
3788 double p = pow(2, i);
3789 cpl_image_power(cur_image, p);
3790 cpl_image_add(bpm, cur_image);
3791 cpl_image_delete(cur_image);
3794 cpl_mask_or(mask, cur_mask);
3796 cpl_mask_delete(cur_mask);
3797 cpl_stats_delete(stats);
3801 bpm = cpl_image_new_from_mask(mask);
3804 *nbpixs += cpl_mask_count(mask);
3806 cpl_mask_delete(mask);
3933 detmon_autocorr_factor(
const cpl_image * image,
3934 cpl_image ** autocorr_image,
int m,
int n)
3936 cpl_image * mycorr_image = NULL;
3937 double autocorr = 0;
3940 mycorr_image = detmon_image_correlate(image, image, m, n);
3942 if (cpl_error_get_code() == CPL_ERROR_UNSUPPORTED_MODE)
3944 cpl_msg_warning(cpl_func,
"FFTW is not supported by CPL, autocorrelation "
3945 "would be computed using internal implementation");
3948 cpl_image_delete(mycorr_image);
3949 mycorr_image = detmon_autocorrelate(image, m, n);
3951 if(mycorr_image == NULL) {
3955 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
3957 autocorr = cpl_image_get_flux(mycorr_image);
3959 if (autocorr_image) *autocorr_image = mycorr_image;
3960 else cpl_image_delete(mycorr_image);
3965 static cpl_propertylist*
3966 detmon_lg_extract_qclist_4plane(cpl_propertylist* linc_qclist,
const int ip)
3969 cpl_propertylist* sub_set=NULL;
3972 sub_set=cpl_propertylist_new();
3973 qc_key=cpl_sprintf(
"QC LIN COEF%d",ip);
3974 cpl_propertylist_copy_property_regexp(sub_set,linc_qclist,qc_key,0);
3991 static cpl_error_code
3992 detmon_lg_extract_extention_header(cpl_frameset* frameset,
3993 cpl_propertylist* gaint_qclist,
3994 cpl_propertylist* lint_qclist,
3995 cpl_propertylist* linc_qclist,
3996 cpl_propertylist* bpm_qclist,
4000 cpl_propertylist * xplist = NULL;
4002 const char * filename =
4003 cpl_frame_get_filename(cpl_frameset_get_first(frameset));
4005 xplist = cpl_propertylist_load_regexp(filename, whichext,
4006 "ESO DET|EXTNAME", 0);
4007 if (detmon_lg_config.exts >= 0)
4010 cpl_property* propExtname = NULL;
4011 propExtname = cpl_propertylist_get_property(xplist,
"EXTNAME");
4013 if (NULL != propExtname)
4015 propExtname = cpl_property_duplicate(propExtname);
4017 cpl_propertylist_delete(xplist);
4019 if (NULL != propExtname)
4021 xplist = cpl_propertylist_new();
4022 cpl_propertylist_append_property(xplist, propExtname);
4023 cpl_property_delete(propExtname);
4028 cpl_propertylist_append(gaint_qclist, xplist);
4029 cpl_propertylist_append(lint_qclist, xplist);
4030 cpl_propertylist_append(linc_qclist, xplist);
4031 cpl_propertylist_append(bpm_qclist, xplist);
4032 cpl_propertylist_delete(xplist);
4035 return cpl_error_get_code();
4052 static cpl_error_code
4053 detmon_lg_save_table_with_pro_keys(cpl_table* table,
4055 cpl_propertylist* xheader,
4056 unsigned CPL_IO_MODE)
4059 cpl_propertylist* pro_keys=NULL;
4061 pro_keys=detmon_load_pro_keys(name_o);
4062 cpl_propertylist_append(xheader,pro_keys);
4064 if(CPL_IO_MODE==CPL_IO_DEFAULT) {
4065 cpl_propertylist * pri_head=cpl_propertylist_load(name_o,0);
4066 cpl_table_save(table, pri_head,xheader,name_o,
4068 cpl_propertylist_delete(pri_head);
4071 cpl_table_save(table,NULL,xheader,name_o,
4074 cpl_propertylist_delete(pro_keys);
4076 return cpl_error_get_code();
4088 static cpl_error_code
4089 detmon_lg_save_image_with_pro_keys(cpl_image* image,
4091 cpl_propertylist* xheader)
4094 cpl_propertylist* pro_keys=NULL;
4095 pro_keys=detmon_load_pro_keys(name_o);
4096 cpl_propertylist_append(xheader,pro_keys);
4098 cpl_image_save(image,name_o, CPL_BPP_IEEE_FLOAT,
4099 xheader,CPL_IO_EXTEND);
4100 cpl_propertylist_delete(pro_keys);
4103 return cpl_error_get_code();
4115 static cpl_error_code
4116 detmon_lg_save_imagelist_with_pro_keys(cpl_imagelist* imagelist,
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_imagelist_save(imagelist,name_o, CPL_BPP_IEEE_FLOAT,
4126 xheader,CPL_IO_EXTEND);
4128 cpl_propertylist_delete(pro_keys);
4131 return cpl_error_get_code();
4151 static cpl_error_code
4152 detmon_lg_save_plane(
const cpl_parameterlist * parlist,
4153 cpl_frameset* frameset,
4154 const cpl_frameset * usedframes,
4156 const char* recipe_name,
4157 cpl_propertylist* mypro_coeffscube,
4158 cpl_propertylist* linc_plane_qclist,
4159 const char* package,
4163 if(detmon_lg_config.exts == 0) {
4164 cpl_propertylist* plist=NULL;
4165 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4167 CPL_BPP_IEEE_FLOAT, recipe_name,
4168 mypro_coeffscube, NULL,
4170 plist=cpl_propertylist_load(NAME_O,0);
4171 cpl_image_save(plane,NAME_O, CPL_BPP_IEEE_FLOAT,
4172 plist,CPL_IO_DEFAULT);
4173 cpl_propertylist_delete(plist);
4175 }
else if(detmon_lg_config.exts > 0) {
4176 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4178 CPL_BPP_IEEE_FLOAT, recipe_name,
4179 mypro_coeffscube, NULL,
4182 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4186 cpl_dfs_save_image(frameset, NULL, parlist,
4187 usedframes,NULL, NULL,
4188 CPL_BPP_IEEE_FLOAT, recipe_name,
4189 mypro_coeffscube, NULL,
4191 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4194 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4200 return cpl_error_get_code();
4223 static cpl_error_code
4224 detmon_lg_save_cube(
const cpl_parameterlist * parlist,
4225 cpl_frameset* frameset,
4226 const cpl_frameset * usedframes,
4228 const char* recipe_name,
4229 cpl_propertylist* mypro_coeffscube,
4230 cpl_propertylist* linc_qclist,
4231 const char* package,
4233 cpl_imagelist* coeffs)
4236 if(detmon_lg_config.exts == 0) {
4237 cpl_propertylist_append(mypro_coeffscube, linc_qclist);
4238 detmon_lg_dfs_save_imagelist
4239 (frameset, parlist, usedframes, coeffs,
4240 recipe_name, mypro_coeffscube, package,
4242 }
else if(detmon_lg_config.exts > 0) {
4243 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4245 CPL_BPP_IEEE_FLOAT, recipe_name,
4246 mypro_coeffscube, NULL,
4249 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4253 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4255 CPL_BPP_IEEE_FLOAT, recipe_name,
4256 mypro_coeffscube, NULL,
4259 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4261 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4264 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4266 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4270 return cpl_error_get_code();
4274 detmon_lg_set_paf_name_and_header(cpl_frame* ref_frame,
4275 int flag_sets,
int which_set,
4277 const char* paf_suf,
4278 cpl_propertylist** plist)
4280 char * paf_name=NULL;
4282 if(detmon_lg_config.exts >= 0)
4284 *plist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4285 detmon_lg_config.exts);
4289 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4293 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4294 detmon_lg_config.pafname, paf_suf,which_set);
4299 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4305 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4306 detmon_lg_config.pafname, paf_suf,whichext);
4310 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4311 detmon_lg_config.pafname,paf_suf,
4312 which_set, whichext);
4321 detmon_lg_set_paf_name_and_header_ext(cpl_frame* ref_frame,
4322 int flag_sets,
int which_set,
4324 const char* paf_suf,
4325 cpl_propertylist** plist)
4327 char* paf_name=NULL;
4329 if(detmon_lg_config.exts >= 0)
4331 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4332 detmon_lg_config.exts);
4336 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4339 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4340 detmon_lg_config.pafname, paf_suf,which_set);
4344 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4348 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4349 detmon_lg_config.pafname, paf_suf,whichext);
4352 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4353 detmon_lg_config.pafname,paf_suf,
4354 which_set, whichext);
4361 static cpl_error_code
4362 detmon_lg_save_paf_product(cpl_frame* ref_frame,
int flag_sets,
4363 int which_set,
int whichext,
4364 const char* pafregexp,
4365 const char* procatg,
4366 const char* pipeline_name,
4367 const char* recipe_name,
4368 const char* paf_suf,
4369 cpl_propertylist* qclist,
4374 char* paf_name=NULL;
4375 cpl_propertylist* plist=NULL;
4376 cpl_propertylist* paflist = NULL;
4377 cpl_propertylist* mainplist=NULL;
4379 mainplist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0);
4381 paf_name=detmon_lg_set_paf_name_and_header(ref_frame,flag_sets,
4385 paf_name=detmon_lg_set_paf_name_and_header_ext(ref_frame,flag_sets,
4391 paflist = cpl_propertylist_new();
4392 cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,procatg);
4395 cpl_propertylist_copy_property_regexp(paflist, plist,pafregexp, 0);
4396 cpl_propertylist_copy_property_regexp(paflist, mainplist,pafregexp, 0);
4397 cpl_propertylist_append(paflist,qclist);
4400 cpl_dfs_save_paf(pipeline_name, recipe_name,paflist,paf_name);
4403 cpl_propertylist_delete(mainplist);
4404 cpl_propertylist_delete(paflist);
4405 cpl_propertylist_delete(plist);
4408 return cpl_error_get_code();
4445 static cpl_error_code
4446 detmon_lg_save(
const cpl_parameterlist * parlist,
4447 cpl_frameset * frameset,
4448 const char *recipe_name,
4449 const char *pipeline_name,
4450 const char *pafregexp,
4451 const cpl_propertylist * pro_lintbl,
4452 const cpl_propertylist * pro_gaintbl,
4453 const cpl_propertylist * pro_coeffscube,
4454 const cpl_propertylist * pro_bpm,
4455 const cpl_propertylist * pro_corr,
4456 const cpl_propertylist * pro_diff,
4457 const char *package,
4458 cpl_imagelist * coeffs,
4459 cpl_table * gain_table,
4460 cpl_table * linear_table,
4462 cpl_imagelist * autocorr_images,
4463 cpl_imagelist * diff_flats,
4464 cpl_propertylist * gaint_qclist,
4465 cpl_propertylist * lint_qclist,
4466 cpl_propertylist * linc_qclist,
4467 cpl_propertylist * bpm_qclist,
4468 const int flag_sets,
4469 const int which_set,
4470 const cpl_frameset * usedframes,
4474 cpl_frame *ref_frame;
4475 cpl_propertylist *plist = NULL;
4476 cpl_propertylist *mainplist = NULL;
4482 cpl_propertylist * xplist = NULL;
4484 cpl_propertylist* linc_plane_qclist=NULL;
4485 cpl_image* plane=NULL;
4487 char* pcatg_plane=NULL;
4489 cpl_propertylist * mypro_lintbl =
4490 cpl_propertylist_duplicate(pro_lintbl);
4491 cpl_propertylist * mypro_gaintbl =
4492 cpl_propertylist_duplicate(pro_gaintbl);
4493 cpl_propertylist * mypro_coeffscube =
4494 cpl_propertylist_duplicate(pro_coeffscube);
4495 cpl_propertylist * mypro_bpm =
4496 cpl_propertylist_duplicate(pro_bpm);
4497 cpl_propertylist * mypro_corr =
4498 cpl_propertylist_duplicate(pro_corr);
4499 cpl_propertylist * mypro_diff =
4500 cpl_propertylist_duplicate(pro_diff);
4502 const char * procatg_lintbl =
4503 cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
4505 const char * procatg_gaintbl =
4506 cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
4508 const char * procatg_coeffscube =
4509 cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
4510 const char * procatg_bpm =
4511 cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
4515 detmon_lg_extract_extention_header(frameset,gaint_qclist,lint_qclist,
4516 linc_qclist,bpm_qclist,whichext);
4521 ref_frame = cpl_frameset_get_first(frameset);
4523 skip_if((mainplist =
4524 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4530 cpl_msg_info(cpl_func,
"Write the LINEARITY TABLE");
4533 NAME_O=cpl_sprintf(
"%s_linearity_table.fits", recipe_name);
4535 NAME_O=cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name,
4539 if (detmon_lg_config.exts >= 0) {
4541 cpl_propertylist_append(mypro_lintbl, lint_qclist);
4542 skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,
4543 linear_table,NULL, recipe_name,
4544 mypro_lintbl, NULL, package, NAME_O));
4546 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4547 lint_qclist,CPL_IO_DEFAULT);
4552 skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL,
4553 linear_table,lint_qclist, recipe_name,
4554 mypro_lintbl,NULL, package, NAME_O));
4555 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4556 lint_qclist,CPL_IO_DEFAULT);
4563 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4564 lint_qclist,CPL_IO_EXTEND);
4567 irplib_free(&NAME_O);
4571 cpl_msg_info(cpl_func,
"Write the GAIN TABLE");
4574 NAME_O=cpl_sprintf(
"%s_gain_table.fits", recipe_name);
4576 NAME_O=cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name,
4580 if (detmon_lg_config.exts >= 0)
4584 cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
4585 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
4586 gain_table,NULL, recipe_name, mypro_gaintbl,
4587 NULL, package, NAME_O));
4588 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4589 gaint_qclist,CPL_IO_DEFAULT);
4597 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
4598 gaint_qclist, recipe_name, mypro_gaintbl,
4599 NULL, package, NAME_O));
4600 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4601 gaint_qclist,CPL_IO_DEFAULT);
4607 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4608 gaint_qclist,CPL_IO_EXTEND);
4612 if(detmon_lg_config.pix2pix)
4618 cpl_msg_info(cpl_func,
"Write the COEFFS FITS");
4619 irplib_free(&NAME_O);
4622 PREF_O=cpl_sprintf(
"%s_coeffs_cube", recipe_name);
4625 PREF_O=cpl_sprintf(
"%s_coeffs_cube_set%02d",
4626 recipe_name, which_set);
4628 if (detmon_lg_config.split_coeffs == 0) {
4629 NAME_O=cpl_sprintf(
"%s.fits", PREF_O);
4634 if(detmon_lg_config.split_coeffs != 0){
4637 nb_images = cpl_imagelist_get_size(coeffs);
4638 for(ip=0;ip<nb_images;ip++) {
4639 NAME_O=cpl_sprintf(
"%s_P%d.fits", PREF_O,ip);
4640 pcatg_plane=cpl_sprintf(
"COEFFS_CUBE_P%d",ip);
4641 cpl_propertylist_delete(mypro_coeffscube);
4642 mypro_coeffscube=cpl_propertylist_duplicate(pro_coeffscube);
4643 cpl_propertylist_set_string(mypro_coeffscube,CPL_DFS_PRO_CATG,
4645 linc_plane_qclist=detmon_lg_extract_qclist_4plane(linc_qclist,ip);
4646 cpl_propertylist_append(mypro_coeffscube, linc_plane_qclist);
4647 plane=cpl_imagelist_get(coeffs,ip);
4648 detmon_lg_save_plane(parlist,frameset,usedframes,whichext,
4649 recipe_name,mypro_coeffscube,
4650 linc_plane_qclist,package,NAME_O,plane);
4652 if(NULL!=linc_plane_qclist) {
4653 cpl_propertylist_delete(linc_plane_qclist);
4655 irplib_free(&NAME_O);
4660 detmon_lg_save_cube(parlist,frameset,usedframes,whichext,
4661 recipe_name,mypro_coeffscube,
4662 linc_qclist,package,NAME_O,coeffs);
4668 cpl_msg_info(cpl_func,
"Write the BAD PIXEL MAP");
4669 irplib_free(&NAME_O);
4673 NAME_O=cpl_sprintf(
"%s_bpm.fits", recipe_name);
4676 NAME_O=cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, which_set);
4681 if(detmon_lg_config.exts == 0) {
4682 cpl_propertylist_append(mypro_bpm, bpm_qclist);
4683 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
4684 CPL_BPP_IEEE_FLOAT, recipe_name,
4685 mypro_bpm, NULL, package,
4688 else if(detmon_lg_config.exts > 0)
4690 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4691 CPL_BPP_IEEE_FLOAT, recipe_name,
4692 mypro_bpm, NULL, package,
4694 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4700 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4701 CPL_BPP_IEEE_FLOAT, recipe_name,
4702 mypro_bpm, NULL, package,
4704 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4707 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4712 if(detmon_lg_config.intermediate)
4717 cpl_msg_info(cpl_func,
"Write the AUTOCORRS FITS");
4718 nb_images = cpl_imagelist_get_size(autocorr_images);
4719 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
4720 for(i = 0; i < nb_images; i++)
4722 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_corr);
4724 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4726 if(i < cpl_table_get_nrow(linear_table))
4728 ddit = cpl_table_get_double(linear_table,
4729 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4731 cpl_array_delete(pnames);
4734 irplib_free(&NAME_O);
4737 NAME_O=cpl_sprintf(
"%s_autocorr_%d.fits", recipe_name, i);
4738 assert(NAME_O != NULL);
4741 NAME_O=cpl_sprintf(
"%s_autocorr_%02d_set%02d.fits",
4742 recipe_name, i, which_set);
4743 assert(NAME_O != NULL);
4746 if(detmon_lg_config.exts > 0)
4748 cpl_propertylist* pextlist = cpl_propertylist_new();
4749 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4750 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4751 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4752 recipe_name, pplist, NULL,
4755 detmon_lg_save_image_with_pro_keys(
4756 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4758 cpl_propertylist_delete(pextlist);
4760 if(detmon_lg_config.exts == 0)
4762 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4763 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
4764 cpl_imagelist_get(autocorr_images, i),
4766 recipe_name, pplist, NULL, package,
4772 cpl_propertylist* pextlist = cpl_propertylist_new();
4773 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4776 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4777 usedframes, NULL,NULL,
4778 CPL_BPP_IEEE_FLOAT, recipe_name,
4782 detmon_lg_save_image_with_pro_keys(
4783 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4788 detmon_lg_save_image_with_pro_keys(
4789 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4791 cpl_propertylist_delete(pextlist);
4793 cpl_propertylist_delete (pplist);
4795 irplib_free(&NAME_O);
4804 cpl_msg_info(cpl_func,
"Write the DIFFS FITS");
4806 for(i = 0; i < nb_images; i++)
4808 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_diff);
4810 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4812 if(i < cpl_table_get_nrow(linear_table))
4814 ddit = cpl_table_get_double(linear_table,
4815 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4817 cpl_array_delete(pnames);
4822 NAME_O=cpl_sprintf(
"%s_diff_flat_%d.fits", recipe_name, i);
4825 NAME_O=cpl_sprintf(
"%s_diff_flat_%d_set%02d.fits",
4826 recipe_name, i, which_set);
4829 if(detmon_lg_config.exts > 0)
4831 cpl_propertylist* pextlist = cpl_propertylist_new();
4832 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4833 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT", ddit);
4834 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4835 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4837 mypro_diff, NULL,package, NAME_O));
4839 detmon_lg_save_image_with_pro_keys(
4840 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4842 cpl_propertylist_delete(pextlist);
4844 else if(detmon_lg_config.exts == 0)
4846 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4848 (frameset, NULL, parlist, usedframes, NULL,
4849 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
4850 recipe_name, pplist, NULL, package,
4855 cpl_propertylist* pextlist = cpl_propertylist_new();
4856 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4859 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT",ddit);
4861 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4862 usedframes, NULL,NULL,
4863 CPL_BPP_IEEE_FLOAT, recipe_name,
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);
4872 detmon_lg_save_image_with_pro_keys(
4873 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4876 cpl_propertylist_delete(pextlist);
4878 cpl_propertylist_delete(pplist);
4879 irplib_free(&NAME_O);
4887 cpl_msg_info(cpl_func,
"Write the PAF file(s)");
4889 if(detmon_lg_config.pafgen) {
4891 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4892 pafregexp,procatg_gaintbl,
4893 pipeline_name,recipe_name,
4894 "qc01",gaint_qclist,0);
4896 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4897 pafregexp,procatg_lintbl,
4898 pipeline_name,recipe_name,
4899 "qc02",lint_qclist,0);
4901 if(detmon_lg_config.pix2pix)
4904 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4907 pipeline_name,recipe_name,
4908 "qc03",linc_qclist,1);
4910 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4911 whichext,pafregexp,procatg_bpm,
4912 pipeline_name,recipe_name,
4913 "qc04",bpm_qclist,1);
4918 cpl_msg_info(cpl_func,
"exit");
4920 cpl_propertylist_delete(xplist);
4922 cpl_propertylist_delete(plist);
4926 irplib_free(&NAME_O);
4928 cpl_free(pcatg_plane);
4929 cpl_propertylist_delete(mainplist);
4930 cpl_propertylist_delete(mypro_lintbl);
4931 cpl_propertylist_delete(mypro_gaintbl);
4932 cpl_propertylist_delete(mypro_coeffscube);
4933 cpl_propertylist_delete(mypro_bpm);
4934 cpl_propertylist_delete(mypro_corr);
4935 cpl_propertylist_delete(mypro_diff);
4937 return cpl_error_get_code();
4950 static cpl_error_code
4951 detmon_opt_contamination(
const cpl_imagelist * ons,
4952 const cpl_imagelist * offs,
4954 cpl_propertylist * qclist)
4962 struct rect rects[5] = {
4963 (
struct rect){ detmon_lg_config.llx1,
4964 detmon_lg_config.lly1,
4965 detmon_lg_config.urx1,
4966 detmon_lg_config.ury1},
4967 (
struct rect){ detmon_lg_config.llx2,
4968 detmon_lg_config.lly2,
4969 detmon_lg_config.urx2,
4970 detmon_lg_config.ury2},
4971 (
struct rect){ detmon_lg_config.llx3,
4972 detmon_lg_config.lly3,
4973 detmon_lg_config.urx3,
4974 detmon_lg_config.ury3},
4975 (
struct rect){ detmon_lg_config.llx4,
4976 detmon_lg_config.lly4,
4977 detmon_lg_config.urx4,
4978 detmon_lg_config.ury4},
4979 (
struct rect){ detmon_lg_config.llx5,
4980 detmon_lg_config.lly5,
4981 detmon_lg_config.urx5,
4982 detmon_lg_config.ury5},
4985 for (
size_t i = 0; i < 5; i++) {
4986 cpl_image * dif_avg;
4987 const cpl_image * off2;
4990 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
4991 off2 = cpl_imagelist_get_const(offs, 0);
4993 off2 = cpl_imagelist_get_const(offs, 1);
4995 dif_avg = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
4996 cpl_imagelist_get_const(offs, 0),
4997 cpl_imagelist_get_const(ons, 1),
5004 median = cpl_image_get_median(dif_avg);
5005 cpl_image_delete(dif_avg);
5008 sprintf(kname,
"%s%d", DETMON_QC_CONTAM, i + 1);
5010 if(cpl_propertylist_has(qclist,kname)){
5011 skip_if(cpl_propertylist_update_double(qclist,kname,median));
5013 skip_if(cpl_propertylist_append_double(qclist,kname,median));
5014 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
5020 return cpl_error_get_code();
5079 detmon_lg_dfs_set_groups(cpl_frameset * set,
5080 const char *tag_on,
const char *tag_off)
5092 int nframes = cpl_frameset_get_size(set);
5095 for(
int i = 0; i < nframes; i++) {
5096 cpl_frame* cur_frame = cpl_frameset_get_position(set, i);
5097 const char* tag = cpl_frame_get_tag(cur_frame);
5100 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
5101 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
5121 static cpl_error_code
5122 detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist ** coeffs_ptr,
5123 cpl_image **bpms_ptr)
5139 cpl_image* dummy_bpm = cpl_image_new(detmon_lg_config.nx,
5140 detmon_lg_config.ny,
5142 cpl_imagelist* dummy_coeffs = cpl_imagelist_new();
5144 int* db_p = cpl_image_get_data_int(dummy_bpm);
5145 int* rb_p = cpl_image_get_data_int(*bpms_ptr);;
5146 float** dcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5147 float** rcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5148 int dlength = detmon_lg_config.nx;
5150 int rlength = detmon_lg_config.urx - detmon_lg_config.llx + 1;
5151 for (
int i = 0; i <= detmon_lg_config.order; i++)
5153 cpl_image* dummy_coeff = cpl_image_new(detmon_lg_config.nx,
5154 detmon_lg_config.ny,
5157 cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
5158 dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
5159 rcs_p[i] = cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
5162 for (
int i = detmon_lg_config.lly - 1; i < detmon_lg_config.ury; i++)
5164 for (
int j = detmon_lg_config.llx - 1; j < detmon_lg_config.urx; j++)
5166 shift_idx=(i - detmon_lg_config.lly + 1) * rlength +
5167 j - detmon_lg_config.llx + 1;
5168 *(db_p + i * dlength + j) = *(rb_p + shift_idx);
5169 for (
int k = 0; k <= detmon_lg_config.order; k++)
5171 *(dcs_p[k] + i * dlength + j) =
5172 *(rcs_p[k] + (i - detmon_lg_config.lly + 1) * rlength +
5173 j - detmon_lg_config.llx + 1);
5177 cpl_imagelist_delete(*coeffs_ptr);
5178 cpl_image_delete(*bpms_ptr);
5179 *coeffs_ptr = dummy_coeffs;
5180 *bpms_ptr = dummy_bpm;
5184 return cpl_error_get_code();
5244 detmon_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
5245 const double ron, cpl_image ** ima_errs)
5247 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
5248 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
5249 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
5250 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
5252 *ima_errs = cpl_image_duplicate(ima_data);
5254 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
5258 cpl_image_divide_scalar(*ima_errs, gain);
5259 cpl_image_add_scalar(*ima_errs, ron * ron);
5260 cpl_image_power(*ima_errs, 0.5);
5262 return cpl_error_get_code();
5266 detmon_compute_badpixmap(cpl_boolean opt_nir,
const int nsets,
5267 const cpl_table* linear_table,
5268 const cpl_imagelist* linearity_inputs,
int nbpixs,
5269 cpl_vector* x, cpl_propertylist* gaint_qclist,
5270 cpl_image** bpms_ptr)
5276 if (opt_nir == NIR) {
5277 x = cpl_vector_wrap(nsets,
5278 (
double *) cpl_table_get_data_double_const(linear_table,
5282 x = cpl_vector_wrap(nsets,
5283 (
double *) cpl_table_get_data_double_const(linear_table,
5287 int sz = cpl_imagelist_get_size(linearity_inputs);
5288 int sx = cpl_image_get_size_x(cpl_imagelist_get_const(linearity_inputs, 0));
5289 int sy = cpl_image_get_size_y(cpl_imagelist_get_const(linearity_inputs, 0));
5290 double kappa = detmon_lg_config.kappa;
5291 int niter = detmon_lg_config.niter;
5292 int llx = detmon_lg_config.llx;
5293 int urx = detmon_lg_config.urx;
5294 int lly = detmon_lg_config.lly;
5295 int ury = detmon_lg_config.ury;
5298 cpl_image *ima, *err;
5301 cpl_imagelist* errors = cpl_imagelist_new();
5323 cpl_imagelist* linearity_scaled = cpl_imagelist_new();
5325 gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
5329 gain = (gain < 0) ? 1 : gain;
5330 double gain_eff = 2 * gain;
5342 for (
int i = 0; i < sz; i++) {
5343 ima = cpl_imagelist_get(linearity_inputs, i);
5351 irplib_ksigma_clip(ima, 1, 1, urx - llx + 1,
5352 ury - lly + 1, kappa, niter, 1e-5, &avg,
5357 if (avg < detmon_lg_config.saturation_limit) {
5365 cpl_image_get_mad(ima, &dmad);
5366 err = cpl_image_duplicate(ima);
5367 cpl_image_multiply_scalar(err, 0);
5368 cpl_image_add_scalar(err, dmad * CPL_MATH_STD_MAD);
5378 cpl_imagelist_set(errors, err, i);
5386 cpl_imagelist_set(linearity_scaled,
5387 cpl_image_duplicate(ima), i));
5390 hdrl_imagelist* hil = hdrl_imagelist_create(linearity_scaled, errors);
5395 cpl_imagelist_delete(errors);
5397 double pval = 0.001;
5398 p = hdrl_bpm_fit_parameter_create_pval(1, pval);
5407 hdrl_bpm_fit_compute(p, hil, x, bpms_ptr);
5432 nbpixs = cpl_image_get_flux(*bpms_ptr);
5434 hdrl_imagelist_delete(hil);
5435 cpl_imagelist_delete(linearity_scaled);
5436 cpl_vector_unwrap((cpl_vector*) x);
5437 hdrl_parameter_delete(p);
5453 skip_if(*bpms_ptr == NULL);
5474 static cpl_error_code
5475 detmon_lg_reduce_all(
const cpl_table * linear_table,
5476 cpl_propertylist * gaint_qclist,
5477 cpl_propertylist * lint_qclist,
5478 cpl_propertylist * linc_qclist,
5479 cpl_propertylist * bpm_qclist,
5480 cpl_imagelist ** coeffs_ptr,
5481 cpl_image ** bpms_ptr,
5482 const cpl_imagelist * linearity_inputs,
5483 const cpl_table * gain_table,
5484 int which_ext, cpl_boolean opt_nir)
5488 const int linear_nsets = cpl_table_get_nrow(linear_table);
5489 const int gain_nsets = cpl_table_get_nrow(gain_table);
5491 cpl_polynomial *poly_linfit = NULL;
5492 cpl_image *fiterror = NULL;
5493 char * name_o1 = NULL;
5494 char * name_o2 = NULL;
5495 double * pcoeffs = NULL;
5496 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
5499 cpl_vector *x =NULL;
5500 const cpl_vector *y =NULL;
5503 const cpl_image * first = NULL;
5511 cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5512 cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5513 cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
5514 cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
5516 pcoeffs = cpl_malloc(
sizeof(
double)*(detmon_lg_config.order + 1));
5518 skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
5519 detmon_lg_config.method));
5520 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
5521 DETMON_QC_METHOD_C));
5524 if (!strcmp(detmon_lg_config.method,
"PTC")) {
5526 if (detmon_lg_config.exts >= 0) {
5527 cpl_msg_info(cpl_func,
5528 "Polynomial fitting for the GAIN (constant term method)");
5530 cpl_msg_info(cpl_func,
5531 "Polynomial fitting for the GAIN (constant term method)"
5532 " for extension nb %d", which_ext);
5534 skip_if(detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, gain_nsets));
5536 skip_if(detmon_lg_qc_med(gain_table, gaint_qclist, gain_nsets));
5541 if(detmon_lg_config.lamp_ok) {
5542 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
5543 detmon_lg_config.cr));
5544 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
5545 DETMON_QC_LAMP_FLUX_C));
5549 if(detmon_lg_config.autocorr == TRUE) {
5550 autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
5551 skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
5553 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
5554 DETMON_QC_AUTOCORR_C));
5556 if (detmon_lg_config.exts >= 0) {
5557 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix");
5559 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix"
5560 " for extension nb %d", which_ext);
5563 if(!detmon_lg_config.pix2pix) {
5564 const int order=detmon_lg_config.order;
5572 y = cpl_vector_wrap(linear_nsets,
5573 (
double *)cpl_table_get_data_double_const(linear_table,
5576 if (opt_nir == NIR) {
5577 x = cpl_vector_wrap(linear_nsets,
5578 (
double *)cpl_table_get_data_double_const(linear_table,
5581 x = cpl_vector_wrap(linear_nsets,
5582 (
double *)cpl_table_get_data_double_const(linear_table,
5586 if(x == NULL || y == NULL) {
5587 cpl_vector_unwrap((cpl_vector *)x);
5588 cpl_vector_unwrap((cpl_vector *)y);
5598 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
5599 poly_linfit = irplib_polynomial_fit_1d_create(x, y,order,&mse);
5601 if(order == cpl_vector_get_size(x) - 1) {
5602 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5606 if(poly_linfit == NULL) {
5607 cpl_vector_unwrap((cpl_vector *)x);
5608 cpl_vector_unwrap((cpl_vector *)y);
5614 min_val=cpl_vector_get_min(y);
5615 max_val=cpl_vector_get_max(y);
5617 cpl_vector_unwrap((cpl_vector *)x);
5618 cpl_vector_unwrap((cpl_vector *)y);
5620 for(deg = 0; deg <= order; deg++) {
5621 const double coeff =
5622 cpl_polynomial_get_coeff(poly_linfit, °);
5624 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
5625 assert(name_o != NULL);
5626 skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
5627 skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
5628 DETMON_QC_LIN_COEF_C));
5631 pcoeffs[deg] = coeff;
5633 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
5634 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
5635 DETMON_QC_ERRFIT_MSE_C));
5639 const int order=detmon_lg_config.order;
5641 y = cpl_vector_wrap(linear_nsets,
5642 (
double *)cpl_table_get_data_double_const(linear_table,
5647 x = cpl_vector_wrap(linear_nsets,
5648 (
double *)cpl_table_get_data_double_const(linear_table,
5651 x = cpl_vector_wrap(linear_nsets,
5652 (
double *)cpl_table_get_data_double_const(linear_table,
5657 first = cpl_imagelist_get_const(linearity_inputs, 0);
5658 sizex = cpl_image_get_size_x(first);
5659 sizey = cpl_image_get_size_y(first);
5660 vsize = cpl_vector_get_size(x);
5661 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
5663 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,order, FALSE,
5664 CPL_TYPE_FLOAT, fiterror);
5665 min_val=cpl_vector_get_min(y);
5666 max_val=cpl_vector_get_max(y);
5667 cpl_vector_unwrap((cpl_vector*)x);
5668 cpl_vector_unwrap((cpl_vector*)y);
5670 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
5671 "Failed polynomial fit");
5674 for(deg = 0; deg <= order; deg++)
5676 cpl_image *image = cpl_imagelist_get(*coeffs_ptr, deg);
5677 const double coeff = cpl_image_get_median(image);
5678 pcoeffs[deg] = coeff;
5679 name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", (
int)deg);
5680 name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", (
int)deg);
5681 assert(name_o1 != NULL);
5682 assert(name_o2 != NULL);
5683 skip_if(cpl_propertylist_append_double(linc_qclist, name_o1, coeff));
5684 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o1,
5685 DETMON_QC_LIN_COEF_C));
5688 skip_if(cpl_propertylist_append_double(linc_qclist, name_o2,
5689 cpl_image_get_stdev(image)));
5690 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o2,
5691 DETMON_QC_LIN_COEF_ERR_C));
5697 if(order == vsize - 1)
5699 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5700 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5702 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5703 DETMON_QC_ERRFIT_C));
5706 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5707 cpl_image_get_median(fiterror)));
5708 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5709 DETMON_QC_ERRFIT_C));
5713 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
5715 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
5716 DETMON_QC_COUNTS_MIN_C));
5717 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
5719 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
5720 DETMON_QC_COUNTS_MAX_C));
5721 skip_if(detmon_lg_lineff(pcoeffs,lint_qclist,detmon_lg_config.ref_level,
5722 detmon_lg_config.order));
5724 if (detmon_lg_config.exts >= 0)
5726 cpl_msg_info(cpl_func,
"Bad pixel detection");
5729 cpl_msg_info(cpl_func,
"Bad pixel detection"
5730 " for extension nb %d", which_ext);
5732 if(detmon_lg_config.pix2pix)
5736 nbpixs = detmon_compute_badpixmap(opt_nir, linear_nsets, linear_table,
5737 linearity_inputs, nbpixs, x,gaint_qclist, bpms_ptr);
5742 skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
5743 skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
5744 DETMON_QC_NUM_BPM_C));
5745 cpl_msg_info(cpl_func,
"stability=%g",detmon_lg_config.lamp_stability);
5746 if(detmon_lg_config.lamp_stability != 0.0)
5748 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
5749 detmon_lg_config.lamp_stability));
5750 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
5751 DETMON_QC_LAMP_STAB_C));
5754 if (!detmon_lg_config.wholechip && detmon_lg_config.pix2pix)
5756 detmon_lg_fits_coeffs_and_bpm2chip(coeffs_ptr,bpms_ptr);
5763 cpl_image_delete(fiterror);
5764 cpl_polynomial_delete(poly_linfit);
5768 return cpl_error_get_code();
5780 static cpl_error_code
5781 detmon_lg_lineff(
double * pcoeffs,
5782 cpl_propertylist * qclist,
5788 double residual, slope;
5791 cpl_polynomial * poly = cpl_polynomial_new(1);
5805 pcoeffs[0] -= ref_level;
5807 for (i = 2; i <= order; i++)
5810 for(j = 0; j < i; j++)
5812 pcoeffs[i] /= pcoeffs[1];
5818 for (deg = 0; deg <= order; deg++) {
5820 skip_if(cpl_polynomial_set_coeff(poly, °, pcoeffs[deg]));
5829 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
5831 if (slope <= 0.0 && residual >= 0.0) {
5832 cpl_msg_warning(cpl_func,
"Reference level (--ref_level) outside"
5833 " linearity range of the detector. Cannot compute"
5834 " linearity efficiency (QC.LINEFF).");
5839 cpl_error_code err = cpl_polynomial_solve_1d(poly, 0.0, &root, 1);
5844 if (err == CPL_ERROR_NONE)
5847 lineff = (root - ref_level) / ref_level;
5852 cpl_msg_warning(cpl_func,
5853 "Cannot compute linearity efficiency (QC.LINEFF)"
5854 "for the current combination "
5855 " of (--ref-level equal %d) and (--order equal %d) parameters. Try "
5856 "to decrease (--ref-level) value.", ref_level, order);
5859 cpl_msg_warning(cpl_func,
"DETMON_QC_LIN_EFF=%f",lineff );
5860 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
5862 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
5863 DETMON_QC_LIN_EFF_C));
5865 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
5867 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
5868 DETMON_QC_LIN_EFF_FLUX_C));
5872 cpl_polynomial_delete(poly);
5874 return cpl_error_get_code();
5885 static cpl_error_code
5886 detmon_lg_qc_ptc(
const cpl_table * gain_table,
5887 cpl_propertylist * qclist,
unsigned mode,
int rows_in_gain)
5890 cpl_polynomial *poly_fit = NULL;
5891 cpl_polynomial *poly_fit2 = NULL;
5893 const int nsets = rows_in_gain;
5895 cpl_vector *x = NULL;
5896 cpl_vector *y = NULL;
5898 cpl_errorstate prestate;
5900 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
5901 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
5903 x = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5905 y = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5907 skip_if(x == NULL || y == NULL);
5908 if (0 == detmon_lg_check_before_gain(x, y))
5912 cpl_vector_unwrap(x);
5916 cpl_vector_unwrap(y);
5918 return CPL_ERROR_NONE;
5921 poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
5922 skip_if(poly_fit == NULL);
5926 prestate = cpl_errorstate_get();
5927 coef = cpl_polynomial_get_coeff(poly_fit, &i);
5928 skip_if (!cpl_errorstate_is_equal(prestate) || coef==0);
5929 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
5930 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5931 DETMON_QC_CONAD_C));
5934 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
5936 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
5952 if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
5953 const cpl_vector *x2 =
5954 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT_CORR"));
5955 const cpl_vector *y2 =
5956 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5958 if(x2 == NULL || y2 == NULL) {
5959 cpl_vector_unwrap((cpl_vector *)x2);
5960 cpl_vector_unwrap((cpl_vector *)y2);
5971 poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
5972 if(poly_fit2 == NULL) {
5973 cpl_vector_unwrap((cpl_vector *)x2);
5974 cpl_vector_unwrap((cpl_vector *)y2);
5976 cpl_msg_error(cpl_func,
"Error during polynomial fit, err[%s]", cpl_error_get_where());
5980 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5981 cpl_vector_unwrap((cpl_vector *)x2);
5982 cpl_vector_unwrap((cpl_vector *)y2);
5983 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5986 prestate = cpl_errorstate_get();
5987 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
5988 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5989 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
5991 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
5993 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
5994 DETMON_QC_CONAD_CORR_C));
5996 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
5998 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
5999 DETMON_QC_GAIN_CORR_C));
6005 cpl_vector_unwrap(x);
6006 cpl_vector_unwrap(y);
6007 cpl_polynomial_delete(poly_fit);
6008 cpl_polynomial_delete(poly_fit2);
6010 return cpl_error_get_code();
6019 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y)
6021 const double TOLERANCE = 1e-37;
6022 double xmin = cpl_vector_get_min(x);
6023 double xmax = cpl_vector_get_max(x);
6024 double ymin = cpl_vector_get_min(y);
6025 double ymax = cpl_vector_get_max(y);
6026 double ystdev = cpl_vector_get_stdev(y);
6027 double xstdev = cpl_vector_get_stdev(x);
6029 if (fabs(xmax-xmin) < TOLERANCE &&
6030 fabs(ymax - ymin) < TOLERANCE &&
6031 xstdev < TOLERANCE &&
6034 cpl_msg_warning(cpl_func,
"An empty frame has been detected, linearity, coeffs, gain, FPN values will not be computed.");
6049 static cpl_error_code
6050 detmon_lg_qc_med(
const cpl_table * gain_table,
6051 cpl_propertylist * qclist,
int rows_in_gain)
6055 cpl_vector *x = NULL;
6056 cpl_vector *y = NULL;
6057 int check_result = 0;
6059 if (rows_in_gain) {};
6061 x = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
6062 y = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
6063 check_result = detmon_lg_check_before_gain(x, y);
6066 cpl_vector_unwrap(x);
6070 cpl_vector_unwrap(y);
6072 if (0 == check_result)
6074 return CPL_ERROR_NONE;
6077 gain=cpl_table_get_column_median(gain_table,
"GAIN");
6079 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
6081 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
6084 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
6085 cpl_table_get_column_stdev
6086 (gain_table,
"GAIN")));
6087 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
6088 DETMON_QC_GAIN_MSE_C));
6090 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
6091 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
6092 DETMON_QC_CONAD_C));
6095 gain=cpl_table_get_column_median(gain_table,
"GAIN_CORR");
6097 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
6099 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
6100 DETMON_QC_GAIN_CORR_C));
6103 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
6104 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
6105 DETMON_QC_CONAD_CORR_C));
6110 return cpl_error_get_code();
6124 static cpl_error_code
6125 detmon_lg_rescale(cpl_imagelist * to_rescale)
6128 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 0),
6129 detmon_lg_config.llx,
6130 detmon_lg_config.lly,
6131 detmon_lg_config.urx,
6132 detmon_lg_config.ury);
6134 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 1),
6135 detmon_lg_config.llx,
6136 detmon_lg_config.lly,
6137 detmon_lg_config.urx,
6138 detmon_lg_config.ury);
6142 if(fabs(med1 / med2 - 1) > 0.001) {
6144 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
6147 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
6153 return cpl_error_get_code();
6156 static cpl_error_code
6157 detmon_pair_extract_next(
const cpl_frameset * set,
6161 cpl_frameset ** pair,
6165 double dit_next = -100;
6166 cpl_size* selection;
6167 int nsets_extracted = 0;
6168 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6169 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6170 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6171 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6173 nsets_extracted = cpl_frameset_get_size(set);
6174 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6175 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6178 dit = dit_array[*next_element ];
6180 if (*next_element < nsets_extracted - 1)
6182 dit_next = dit_array[*next_element + 1 ];
6186 selection[iindex[*next_element] ] = 1;
6187 if (fabs(dit - dit_next) < tolerance)
6190 selection[iindex[*next_element + 1] ] = 1;
6195 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);
6199 cpl_frameset_delete(*pair);
6200 *pair = cpl_frameset_extract(set, selection, 1);
6203 cpl_free(selection);
6204 return cpl_error_get_code();
6207 static cpl_error_code
6208 detmon_single_extract_next(
const cpl_frameset * set,
6212 cpl_frameset ** pair)
6214 cpl_size* selection;
6215 int nsets_extracted = 0;
6216 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6217 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6218 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6219 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6221 nsets_extracted = cpl_frameset_get_size(set);
6222 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6223 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6226 selection[iindex[*next_element] ] = 1;
6229 cpl_frameset_delete(*pair);
6230 *pair = cpl_frameset_extract(set, selection, 1);
6232 cpl_free(selection);
6233 return cpl_error_get_code();
6331 detmon_gain(
const cpl_imagelist * imlist_on,
6332 const cpl_imagelist * imlist_off,
6333 const cpl_vector * exptimes,
6334 const cpl_vector * ndit,
6344 cpl_propertylist * qclist,
6346 cpl_imagelist ** diff_imlist,
6347 cpl_imagelist ** autocorr_imlist)
6349 cpl_table * gain_table = NULL;
6350 cpl_imagelist * difflist = NULL;
6351 cpl_imagelist * autocorrlist = NULL;
6352 cpl_imagelist * c_onlist = NULL;
6353 cpl_imagelist * c_offlist = NULL;
6354 cpl_vector * diffdits = NULL;
6355 cpl_vector * diffndits = NULL;
6356 int rows_in_gain = 0;
6357 int ndiffdits, ndits;
6359 cpl_boolean opt_nir = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
6360 const char * method = mode & IRPLIB_GAIN_PTC ?
"PTC" :
"MED";
6362 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6363 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6364 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6365 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6368 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6369 skip_if(detmon_gain_table_create(gain_table, opt_nir));
6373 skip_if(detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,
6375 ndiffdits = cpl_vector_get_size(diffdits);
6377 ndits = cpl_vector_get_size(exptimes);
6380 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
6381 difflist = cpl_imagelist_new();
6382 autocorrlist = cpl_imagelist_new();
6385 if (mode & IRPLIB_GAIN_COLLAPSE) {
6386 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6387 c_offlist = cpl_imagelist_duplicate(imlist_off);
6388 skip_if(detmon_lg_rescale(c_offlist));
6390 c_offlist = (cpl_imagelist *) imlist_off;
6395 for (i = 0; i < ndiffdits; i++) {
6402 c_dit=cpl_vector_get(diffdits, i);
6405 c_ndit=(int)cpl_vector_get(diffndits, i);
6408 c_onlist = cpl_imagelist_new();
6411 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6412 c_offlist = cpl_imagelist_new();
6417 for(j = 0; j < ndits; j++) {
6418 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6428 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6429 const cpl_image * im =
6430 cpl_imagelist_get_const(imlist_on, j);
6431 im_on = cpl_image_duplicate(im);
6433 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6435 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6442 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6444 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6445 const cpl_image * im =
6446 cpl_imagelist_get_const(imlist_off, j);
6447 im_off = cpl_image_duplicate(im);
6450 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6452 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6459 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6460 skip_if (c_nons != c_noffs);
6463 skip_if (c_nons == 0 || c_nons % 2 != 0);
6466 if(mode & IRPLIB_GAIN_WITH_RESCALE) {
6467 skip_if(detmon_lg_rescale(c_onlist));
6468 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6469 skip_if(detmon_lg_rescale(c_offlist));
6475 int rows_affected = 1;
6476 skip_if(detmon_gain_table_fill_row(gain_table,
6480 c_offlist, kappa, nclip,
6482 xshift, yshift,1E10, 1E10, i,
6483 mode, &rows_affected));
6488 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6489 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6490 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6491 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6492 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6493 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6496 cpl_imagelist_unset(c_onlist, 0);
6498 cpl_imagelist_unset(c_onlist, 0);
6500 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6501 cpl_imagelist_unset(c_offlist, 0);
6503 cpl_imagelist_unset(c_offlist, 0);
6511 cpl_imagelist_delete(c_onlist);
6512 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6513 cpl_imagelist_delete(c_offlist);
6517 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
6518 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
6519 DETMON_QC_METHOD_C));
6522 if (mode & IRPLIB_GAIN_PTC) {
6523 skip_if(detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
6525 skip_if(detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
6528 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
6529 double autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
6530 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
6532 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
6533 DETMON_QC_AUTOCORR_C));
6536 if (diff_imlist != NULL) *diff_imlist = difflist;
6537 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
6541 cpl_vector_delete(diffdits);
6542 cpl_vector_delete(diffndits);
6547 static cpl_error_code
6548 detmon_gain_table_create(cpl_table * gain_table,
6549 const cpl_boolean opt_nir)
6551 if (opt_nir == NIR) {
6552 skip_if(cpl_table_new_column(gain_table,
"DIT", CPL_TYPE_DOUBLE));
6553 skip_if(cpl_table_new_column(gain_table,
"NDIT", CPL_TYPE_INT));
6555 skip_if(cpl_table_new_column(gain_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6557 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON1", CPL_TYPE_DOUBLE));
6558 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON2", CPL_TYPE_DOUBLE));
6559 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF1", CPL_TYPE_DOUBLE));
6560 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF2", CPL_TYPE_DOUBLE));
6561 skip_if(cpl_table_new_column(gain_table,
"SIG_ON_DIF", CPL_TYPE_DOUBLE));
6562 skip_if(cpl_table_new_column(gain_table,
"SIG_OFF_DIF", CPL_TYPE_DOUBLE));
6563 skip_if(cpl_table_new_column(gain_table,
"GAIN", CPL_TYPE_DOUBLE));
6564 skip_if(cpl_table_new_column(gain_table,
"AUTOCORR", CPL_TYPE_DOUBLE));
6565 skip_if(cpl_table_new_column(gain_table,
"GAIN_CORR", CPL_TYPE_DOUBLE));
6566 skip_if(cpl_table_new_column(gain_table,
"ADU", CPL_TYPE_DOUBLE));
6567 skip_if(cpl_table_new_column(gain_table,
"X_FIT", CPL_TYPE_DOUBLE));
6568 skip_if(cpl_table_new_column(gain_table,
"X_FIT_CORR", CPL_TYPE_DOUBLE));
6569 skip_if(cpl_table_new_column(gain_table,
"Y_FIT", CPL_TYPE_DOUBLE));
6570 skip_if(cpl_table_new_column(gain_table,
"Y_FIT_CORR", CPL_TYPE_DOUBLE));
6571 skip_if(cpl_table_new_column(gain_table,
"FLAG", CPL_TYPE_INT));
6575 return cpl_error_get_code();
6578 static cpl_error_code
6579 detmon_lin_table_create(cpl_table * lin_table,
6580 const cpl_boolean opt_nir)
6582 if (opt_nir == NIR) {
6583 skip_if(cpl_table_new_column(lin_table,
"DIT", CPL_TYPE_DOUBLE));
6585 skip_if(cpl_table_new_column(lin_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6587 skip_if(cpl_table_new_column(lin_table,
"MED", CPL_TYPE_DOUBLE));
6588 skip_if(cpl_table_new_column(lin_table,
"MEAN", CPL_TYPE_DOUBLE));
6589 skip_if(cpl_table_new_column(lin_table,
"MED_DIT", CPL_TYPE_DOUBLE));
6590 skip_if(cpl_table_new_column(lin_table,
"MEAN_DIT", CPL_TYPE_DOUBLE));
6591 skip_if(cpl_table_new_column(lin_table,
"ADL", CPL_TYPE_DOUBLE));
6594 return cpl_error_get_code();
6598 detmon_lg_find_dits(
const cpl_vector * exptimes,
6601 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6607 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
6611 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
6613 for (j = 0; j < ndits; j++) {
6614 if (fabs(cpl_vector_get(exptimes, i) -
6615 cpl_vector_get(dits, j)) > tolerance)
6618 if(ndiffs == ndits) {
6619 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
6624 cpl_vector_set_size(dits, ndits);
6632 static cpl_error_code
6633 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
6634 const cpl_vector * vec_ndits,
6636 cpl_vector** diff_dits,
6637 cpl_vector** diff_ndits)
6645 * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6646 * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
6649 cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
6650 cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
6653 size=cpl_vector_get_size(exptimes);
6655 for(i = 1; i < size; i++) {
6657 for (j = 0; j < ndits; j++) {
6658 if (fabs(cpl_vector_get(exptimes, i) -
6659 cpl_vector_get(*diff_dits,j)) > tolerance)
6662 if(ndiffs == ndits) {
6663 cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
6664 cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
6669 cpl_vector_set_size(*diff_dits, ndits);
6670 cpl_vector_set_size(*diff_ndits, ndits);
6673 return cpl_error_get_code();
6763 detmon_lin(
const cpl_imagelist * imlist_on,
6764 const cpl_imagelist * imlist_off,
6765 const cpl_vector * exptimes,
6775 cpl_propertylist * qclist,
6777 cpl_imagelist ** coeffs_cube,
6780 cpl_table * lin_table = NULL;
6781 cpl_imagelist * c_onlist = NULL;
6782 cpl_imagelist * c_offlist = NULL;
6783 cpl_vector * diffdits = NULL;
6784 cpl_imagelist * lin_inputs = NULL;
6785 cpl_polynomial * poly_linfit = NULL;
6786 cpl_image * fiterror = NULL;
6787 cpl_vector * vcoeffs = NULL;
6788 double * pcoeffs = NULL;
6789 int ndiffdits, ndits;
6791 cpl_boolean opt_nir = mode & IRPLIB_LIN_OPT ? OPT : NIR;
6792 const cpl_vector *x = NULL;
6793 const cpl_vector *y = NULL;
6795 const cpl_image * first = NULL;
6803 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6804 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6805 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6806 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6807 cpl_ensure(order > 0 , CPL_ERROR_ILLEGAL_INPUT, NULL);
6809 vcoeffs = cpl_vector_new(order + 1);
6810 pcoeffs = cpl_vector_get_data(vcoeffs);
6813 if (mode & IRPLIB_LIN_PIX2PIX) {
6814 cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
6815 cpl_ensure(bpm != NULL, CPL_ERROR_NULL_INPUT, NULL);
6816 lin_inputs = cpl_imagelist_new();
6820 lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6821 skip_if(detmon_lin_table_create(lin_table, opt_nir));
6825 diffdits = detmon_lg_find_dits(exptimes, tolerance);
6826 ndiffdits = cpl_vector_get_size(diffdits);
6828 ndits = cpl_vector_get_size(exptimes);
6858 if (mode & IRPLIB_LIN_COLLAPSE) {
6863 cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
6864 skip_if(collapse == NULL);
6866 c_offlist = cpl_imagelist_new();
6867 skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
6871 for (i = 0; i < ndiffdits; i++) {
6875 double c_dit = cpl_vector_get(diffdits, i);
6877 c_onlist = cpl_imagelist_new();
6880 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6881 c_offlist = cpl_imagelist_new();
6885 for(j = 0; j < ndits; j++) {
6886 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6896 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6897 const cpl_image * im =
6898 cpl_imagelist_get_const(imlist_on, j);
6899 im_on = cpl_image_duplicate(im);
6901 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6903 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6910 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6912 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6913 const cpl_image * im =
6914 cpl_imagelist_get_const(imlist_off, j);
6915 im_off = cpl_image_duplicate(im);
6918 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6920 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6927 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6928 skip_if (c_nons != c_noffs);
6931 skip_if (c_nons == 0 || c_nons % 2 != 0);
6934 if(mode & IRPLIB_LIN_WITH_RESCALE) {
6935 skip_if(detmon_lg_rescale(c_onlist));
6936 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6937 skip_if(detmon_lg_rescale(c_offlist));
6944 skip_if(detmon_lin_table_fill_row(lin_table, c_dit,
6946 c_onlist, c_offlist,
6950 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6951 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6952 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6953 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6954 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6955 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6958 cpl_imagelist_unset(c_onlist, 0);
6960 cpl_imagelist_unset(c_onlist, 0);
6962 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6963 cpl_imagelist_unset(c_offlist, 0);
6965 cpl_imagelist_unset(c_offlist, 0);
6973 cpl_imagelist_delete(c_onlist);
6974 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6975 cpl_imagelist_delete(c_offlist);
6979 skip_if(detmon_add_adl_column(lin_table, opt_nir));
6981 if(!(mode & IRPLIB_LIN_PIX2PIX)) {
6984 y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6985 (
double *)cpl_table_get_data_double_const(lin_table,
6987 if (opt_nir == NIR) {
6988 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6989 (
double *)cpl_table_get_data_double_const(lin_table,
"DIT"));
6991 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6992 (
double *)cpl_table_get_data_double_const(lin_table,
"EXPTIME"));
6994 if(x == NULL || y == NULL) {
6995 cpl_vector_unwrap((cpl_vector *)x);
6996 cpl_vector_unwrap((cpl_vector *)y);
7006 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
7007 poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
7009 if(order == cpl_vector_get_size(x) - 1) {
7010 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7014 if(poly_linfit == NULL) {
7015 cpl_vector_unwrap((cpl_vector *)x);
7016 cpl_vector_unwrap((cpl_vector *)y);
7021 cpl_vector_unwrap((cpl_vector *)x);
7022 cpl_vector_unwrap((cpl_vector *)y);
7024 for(deg = 0; deg <= order; deg++) {
7025 const double coeff =
7026 cpl_polynomial_get_coeff(poly_linfit, °);
7028 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
7029 assert(name_o != NULL);
7030 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
7031 skip_if(cpl_propertylist_set_comment(qclist,name_o,
7032 DETMON_QC_LIN_COEF_C));
7034 pcoeffs[deg] = coeff;
7036 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
7037 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7038 DETMON_QC_ERRFIT_MSE_C));
7042 if (opt_nir == NIR) {
7043 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7044 (
double *)cpl_table_get_data_double_const(lin_table,
7047 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7048 (
double *)cpl_table_get_data_double_const(lin_table,
7053 first = cpl_imagelist_get_const(lin_inputs, 0);
7054 sizex = cpl_image_get_size_x(first);
7055 sizey = cpl_image_get_size_y(first);
7057 vsize = cpl_vector_get_size(x);
7059 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
7062 cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
7063 order, FALSE, CPL_TYPE_FLOAT,
7066 cpl_vector_unwrap((cpl_vector*)x);
7067 irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
7068 "Failed polynomial fit");
7070 for(i = 0; i <= order; i++) {
7071 cpl_image *image = cpl_imagelist_get(*coeffs_cube, i);
7072 const double coeff = cpl_image_get_median(image);
7073 char * name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", i);
7074 char * name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", i);
7076 assert(name_o1 != NULL);
7077 assert(name_o2 != NULL);
7078 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
7079 skip_if(cpl_propertylist_set_comment(qclist,name_o1,
7080 DETMON_QC_LIN_COEF_C));
7083 skip_if(cpl_propertylist_append_double(qclist, name_o2,
7084 cpl_image_get_stdev(image)));
7085 skip_if(cpl_propertylist_set_comment(qclist,name_o2,
7086 DETMON_QC_LIN_COEF_ERR_C));
7091 if(order == vsize - 1) {
7092 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7093 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7095 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7096 DETMON_QC_ERRFIT_C));
7100 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7101 cpl_image_get_median(fiterror)));
7102 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7103 DETMON_QC_ERRFIT_C));
7108 skip_if(detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
7110 if(mode & IRPLIB_LIN_PIX2PIX) {
7112 *bpm = detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
7113 skip_if(*bpm == NULL);
7114 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
7116 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
7117 DETMON_QC_NUM_BPM_C));
7122 cpl_vector_delete(diffdits);
7123 cpl_polynomial_delete(poly_linfit);
7124 cpl_imagelist_delete(lin_inputs);
7125 cpl_vector_delete(vcoeffs);
7126 cpl_image_delete(fiterror);
7156 static cpl_error_code
7157 detmon_lin_table_fill_row(cpl_table * lin_table,
double c_dit,
7158 cpl_imagelist * linearity_inputs,
7159 const cpl_imagelist * ons,
7160 const cpl_imagelist * offs,
7169 cpl_image * extracted=NULL;
7171 cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
7172 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
7173 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
7175 if (mode & IRPLIB_LIN_PIX2PIX) {
7176 cpl_msg_debug(cpl_func,
"checking linearity inputs");
7177 cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
7181 if (mode & IRPLIB_LIN_NIR) {
7182 cpl_table_set(lin_table,
"DIT", pos, c_dit);
7183 }
else if (mode & IRPLIB_LIN_OPT) {
7184 cpl_table_set(lin_table,
"EXPTIME", pos, c_dit);
7186 cpl_msg_error(cpl_func,
"Mandatory mode not given");
7190 const cpl_image * off2;
7191 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
7192 off2 = cpl_imagelist_get_const(offs, 0);
7194 off2 = cpl_imagelist_get_const(offs, 1);
7196 extracted = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
7197 cpl_imagelist_get_const(offs, 0),
7198 cpl_imagelist_get_const(ons, 1),
7200 llx, lly, urx, ury);
7201 cpl_ensure_code(extracted != NULL, cpl_error_get_code());
7205 double median = cpl_image_get_median(extracted);
7206 double mean= cpl_image_get_mean(extracted);
7207 cpl_table_set(lin_table,
"MED", pos, median);
7208 cpl_table_set(lin_table,
"MEAN", pos, mean);
7210 cpl_table_set(lin_table,
"MED_DIT", pos, median / c_dit);
7211 cpl_table_set(lin_table,
"MEAN_DIT", pos, mean / c_dit);
7215 if(mode & IRPLIB_LIN_PIX2PIX) {
7216 cpl_error_code error = cpl_imagelist_set(linearity_inputs, extracted,
7218 cpl_ensure_code(!error, error);
7220 cpl_image_delete(extracted);
7223 return cpl_error_get_code();
7226 static double irplib_calculate_total_noise_smooth(
const cpl_image* pimage,
7227 int pattern_x,
int pattern_y)
7229 cpl_image * p_tmp_image = 0;
7230 cpl_image * psmooth_image = 0;
7232 cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
7234 p_tmp_image = cpl_image_duplicate(pimage);
7235 cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
7236 cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
7237 psmooth_image = cpl_image_divide_create(pimage,p_tmp_image);
7238 ret_noise = irplib_calculate_total_noise(psmooth_image);
7239 cpl_mask_delete(mask);
7240 cpl_image_delete(psmooth_image);
7241 cpl_image_delete(p_tmp_image);
7245 static double irplib_calculate_total_noise(
const cpl_image* pimage)
7247 double total_noise = -1;
7248 unsigned long max_bin_size = 1E5;
7249 const double hstart = cpl_image_get_min(pimage);
7250 const double hrange = cpl_image_get_max(pimage) - hstart;
7251 const unsigned long nbins = max_bin_size;
7254 irplib_hist * phist = 0;
7255 phist = irplib_hist_new();
7258 irplib_hist_init(phist, nbins, hstart, hrange);
7259 err = irplib_hist_fill(phist, pimage);
7260 if (err == CPL_ERROR_NONE)
7268 unsigned long n_bins = irplib_hist_get_nbins(phist);
7269 double start = irplib_hist_get_start(phist);
7270 double bin_size = irplib_hist_get_bin_size(phist);
7271 cpl_vector* pdata_vector = cpl_vector_new(n_bins);
7272 cpl_vector* ppos_vector = cpl_vector_new(n_bins);
7273 cpl_table* ptable = cpl_table_new(n_bins);
7274 cpl_table_new_column(ptable,
"bin", CPL_TYPE_DOUBLE);
7275 cpl_table_new_column(ptable,
"value", CPL_TYPE_DOUBLE);
7276 for(i = 0; i < n_bins; i++)
7278 unsigned int value = irplib_hist_get_value(phist, i);
7279 double dvalue = (double)(value);
7280 cpl_vector_set(pdata_vector, i, dvalue);
7281 cpl_vector_set(ppos_vector, i, start + i * bin_size);
7283 cpl_table_set(ptable,
"bin", i, start + i * bin_size);
7284 cpl_table_set(ptable,
"value", i, dvalue);
7286 err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
7287 if (err == CPL_ERROR_NONE)
7289 cpl_msg_info(cpl_func,
"FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
7293 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed Gaussian Fit, err msg [%s]", cpl_error_get_message());
7296 cpl_table_delete(ptable);
7297 cpl_vector_delete(ppos_vector);
7298 cpl_vector_delete(pdata_vector);
7302 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
7305 irplib_hist_delete(phist);
7310 static double irplib_compute_err(
double gain,
double ron,
double FA)
7312 double int_gain = (gain * gain - 1) / 12;
7317 return sqrt(ron * ron + FA / gain + int_gain);
7320 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain ,
7321 FPN_METHOD fpn_method,
int smooth_size,
double* mse)
7323 cpl_image* im_diff = 0;
7324 const cpl_image* im_f1 = f1;
7325 cpl_image* im_inrange1 = 0;
7334 cpl_msg_warning(cpl_func,
"gain[%f]<0", gain);
7335 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7342 im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
7343 im_f1 = im_inrange1;
7345 FA = cpl_image_get_median(im_f1);
7352 cpl_msg_info(cpl_func,
"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
7353 s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
7356 cpl_msg_info(cpl_func,
"HISTOGRAM method is used for FPN");
7357 s_tot = irplib_calculate_total_noise(im_f1);
7362 cpl_msg_warning(cpl_func,
"fpn_method is not defined");
7371 cpl_msg_warning(cpl_func,
"Median flux on sum of flats<0");
7372 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7377 if ((s_tot * s_tot - FA / gain) > 0)
7379 s_fpn = sqrt(s_tot * s_tot - FA / gain);
7380 sr_fpn = s_fpn / FA;
7381 *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
7385 cpl_msg_warning(cpl_func,
"s_tot * s_tot < FA / gain");
7386 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7395 cpl_image_delete(im_diff);
7398 cpl_image_delete(im_inrange1);
7404 static cpl_imagelist * irplib_load_fset_wrp(
const cpl_frameset * pframeset,
7405 cpl_type type ,
int whichext)
7409 return detmon_load_frameset_window(pframeset, type, 0, whichext,
7410 detmon_lg_config.llx,
7411 detmon_lg_config.lly,
7412 detmon_lg_config.urx,
7413 detmon_lg_config.ury,
7414 detmon_lg_config.nx,
7415 detmon_lg_config.ny);
7418 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset * pframeset,
7419 cpl_type type ,
int whichext)
7422 cpl_imagelist* offs = cpl_imagelist_new();
7423 detmon_lg_config.load_fset(pframeset, type, offs);
7428 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
7429 cpl_propertylist* plist)
7431 if (ptable && plist)
7433 int size = cpl_propertylist_get_size(plist);
7435 for (i = 0; i < size; i++)
7437 cpl_property* pprop = cpl_propertylist_get(plist,i);
7440 const char* pname = cpl_property_get_name(pprop);
7443 cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
7444 if (cpl_error_get_code() != CPL_ERROR_NONE)
7446 cpl_msg_warning(cpl_func,
"cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
7453 return cpl_error_get_code();
7456 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
7457 cpl_propertylist* plist,
int row)
7459 cpl_error_code err = CPL_ERROR_NONE;
7460 if (ptable && plist)
7462 int size = cpl_propertylist_get_size(plist);
7464 for (i = 0; i < size; i++)
7466 cpl_property* pprop = cpl_propertylist_get(plist,i);
7469 const char* pname = cpl_property_get_name(pprop);
7470 double value = cpl_property_get_double(pprop);
7473 cpl_table_set_double(ptable, pname, row, value);
7474 if (cpl_error_get_code() != CPL_ERROR_NONE)
7476 cpl_msg_warning(cpl_func,
"cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
7487 cpl_error_code detmon_check_order(
const double *exptime,
int sz,
7488 double tolerance,
int order)
7505 }
while(fabs(exptime[i-1] - exptime[i]) < tolerance);
7506 }
while(i < sz - 1);
7508 if ( !( fabs(exptime[i-1] - exptime[i]) < tolerance ) ) nsets++;
7511 cpl_error_set_message(cpl_func,CPL_ERROR_INCOMPATIBLE_INPUT,
7512 "Not enough frames for the polynomial"
7513 " fitting. nsets = %d <= %d order",
7516 return cpl_error_get_code();
7519 static cpl_error_code
7520 detmon_lg_dfs_save_imagelist(
7521 cpl_frameset * frameset,
7522 const cpl_parameterlist * parlist,
7523 const cpl_frameset *usedframes,
7524 const cpl_imagelist *coeffs,
7525 const char *recipe_name,
7526 const cpl_propertylist *mypro_coeffscube,
7527 const char * package,
7528 const char * name_o)
7530 return(cpl_dfs_save_imagelist
7531 (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
7532 recipe_name, mypro_coeffscube, NULL, package,
7536 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos)
7538 const cpl_image* first = cpl_imagelist_get(imlist, 0);
7541 int x = cpl_image_get_size_x(first);
7542 int y = cpl_image_get_size_y(first);
7543 cpl_type type = cpl_image_get_type(first);
7544 cpl_image * blank = cpl_image_new(x, y, type);
7545 cpl_imagelist_set(imlist, blank, pos);
7551 detmon_lg_set_tag(cpl_frameset* set,
const char** tag_on,
const char** tag_off)
7556 ntag_old=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_OLD);
7557 ntag_new=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_NEW);
7559 *tag_on=DETMON_LG_ON_RAW_OLD;
7560 *tag_off=DETMON_LG_OFF_RAW_OLD;
7561 }
else if (ntag_new) {
7562 *tag_on=DETMON_LG_ON_RAW_NEW;
7563 *tag_off=DETMON_LG_OFF_RAW_NEW;
7565 cpl_msg_error(cpl_func,
"Provide %s and %s (or %s and %s) input frames",
7566 DETMON_LG_ON_RAW_NEW,DETMON_LG_OFF_RAW_NEW,
7567 DETMON_LG_ON_RAW_OLD,DETMON_LG_OFF_RAW_OLD);
7571 return cpl_error_get_code();