41 #include "detmon_lg.h"
44 #include "detmon_utils.h"
45 #include "detmon_lg_impl.h"
47 #include "irplib_ksigma_clip.h"
48 #include "irplib_utils.h"
49 #include "irplib_hist.h"
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 gain_threshold,
205 int pos,
unsigned mode,
int* rows_affected);
208 static cpl_error_code
209 detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
210 cpl_imagelist * diff_flats,
211 const cpl_imagelist * ons,
212 double kappa,
int nclip,
213 int llx,
int lly,
int urx,
int ury,
214 double saturation_limit,
215 const int pos,
unsigned mode,
216 int* rows_linear_affected);
218 static cpl_error_code
219 detmon_lg_save(
const cpl_parameterlist *,
224 const cpl_propertylist *,
225 const cpl_propertylist *,
226 const cpl_propertylist *,
227 const cpl_propertylist *,
228 const cpl_propertylist *,
229 const cpl_propertylist *,
241 const int,
const int,
const cpl_frameset *,
244 static cpl_error_code
245 detmon_lg_qc_ptc(
const cpl_table *,
246 cpl_propertylist *,
unsigned,
int);
248 static cpl_error_code
249 detmon_lg_qc_med(
const cpl_table *,
250 cpl_propertylist *,
int);
254 detmon_pfits_get_dit(
const cpl_propertylist *);
257 detmon_pfits_get_dit_opt(
const cpl_propertylist *);
259 irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
260 const char* prop_name);
262 static cpl_image * detmon_bpixs(
const cpl_imagelist *,
263 cpl_boolean,
const double,
int *);
266 detmon_autocorr_factor(
const cpl_image *,
267 cpl_image **,
int,
int);
271 static cpl_error_code
272 detmon_opt_contamination(
const cpl_imagelist *,
273 const cpl_imagelist *,
274 unsigned mode, cpl_propertylist *);
277 detmon_opt_lampcr(cpl_frameset *,
int);
281 detmon_lg_dfs_set_groups(cpl_frameset *,
const char *,
const char *);
283 static cpl_error_code
284 detmon_lg_reduce_all(
const cpl_table *,
291 const cpl_imagelist *,
292 const cpl_table *,
int, cpl_boolean);
294 static cpl_error_code
295 detmon_lg_check_defaults(
const cpl_image *);
297 static cpl_error_code
298 detmon_lg_rescale(cpl_imagelist *);
300 static cpl_error_code
301 detmon_lg_reduce_init(cpl_table *,
307 static cpl_error_code
308 detmon_add_adl_column(cpl_table *, cpl_boolean);
310 static cpl_error_code
311 detmon_lg_lamp_stab(
const cpl_frameset *,
312 const cpl_frameset *,
316 static cpl_error_code
317 detmon_lg_reduce_dit(
const cpl_frameset * set_on,
318 int* index_on,
double* exptime_on,
321 const cpl_frameset * set_off,
322 int * index_off,
double* exptime_off,
323 int* next_on,
int* next_off,
324 cpl_table * linear_table,
325 cpl_table * gain_table,
326 cpl_imagelist * linearity_inputs,
327 cpl_propertylist * qclist,
329 cpl_imagelist * autocorr_images,
330 cpl_imagelist * diff_flats,
331 cpl_imagelist * opt_offs,
333 int * rows_linear_affected,
334 int * rows_gain_affected);
336 static cpl_error_code
337 detmon_lg_core(cpl_frameset * cur_fset_on,
338 cpl_frameset * cur_fset_off,
342 double * exptime_off,
345 const char * recipe_name,
346 const char * pipeline_name,
347 const char * pafregexp,
348 const cpl_propertylist * pro_lintbl,
349 const cpl_propertylist * pro_gaintbl,
350 const cpl_propertylist * pro_coeffscube,
351 const cpl_propertylist * pro_bpm,
352 const cpl_propertylist * pro_corr,
353 const cpl_propertylist * pro_diff,
354 const char * package,
355 int (* load_fset) (
const cpl_frameset *,
358 int nsets, cpl_boolean opt_nir,
359 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
360 cpl_frameset * cur_fset);
362 static cpl_error_code
363 detmon_lg_lineff(
double *, cpl_propertylist *,
int,
int);
370 static cpl_error_code
371 detmon_gain_table_create(cpl_table *,
375 static cpl_error_code
376 detmon_lin_table_create(cpl_table *,
380 detmon_lg_find_dits(
const cpl_vector *,
383 static cpl_error_code
384 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
385 const cpl_vector * vec_ndits,
387 cpl_vector** diff_dits,
388 cpl_vector** diff_ndits);
390 static cpl_error_code
391 detmon_fpn_compute(
const cpl_frameset *set_on,
393 int last_linear_best,
394 cpl_propertylist *lint_qclist,
401 FPN_METHOD fpn_method,
403 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain,
404 FPN_METHOD fpn_method,
int,
double* mse);
405 static double irplib_calculate_total_noise(
const cpl_image* pimage);
407 static cpl_imagelist* irplib_load_fset_wrp(
const cpl_frameset *,
408 cpl_type,
int whichext);
409 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset *,
412 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
413 cpl_propertylist* plist);
414 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
415 cpl_propertylist* plist,
418 static cpl_error_code
419 detmon_pair_extract_next(
const cpl_frameset * set,
425 cpl_frameset ** pair,
427 static cpl_error_code
428 detmon_single_extract_next(
const cpl_frameset * set,
432 cpl_frameset ** pair);
439 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code);
440 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos);
441 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y);
450 static int irplib_pfits_get_ndit(
const cpl_propertylist * plist)
452 return cpl_propertylist_get_int(plist,
"ESO DET NDIT");
495 #ifdef DETMON_USE_DETECTOR_SHOTNOISE_MODEL
518 static cpl_error_code
519 hdrldemo_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
520 const double ron, cpl_image ** ima_errs)
522 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
523 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
524 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
525 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
527 *ima_errs = cpl_image_duplicate(ima_data);
529 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
533 cpl_image_divide_scalar(*ima_errs, gain);
534 cpl_image_add_scalar(*ima_errs, ron * ron);
535 cpl_image_power(*ima_errs, 0.5);
537 return cpl_error_get_code();
541 static cpl_error_code
542 detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
545 const char * tag_off,
546 const char * recipe_name,
547 const char * pipeline_name,
548 const char * pafregexp,
549 const cpl_propertylist * pro_lintbl,
550 const cpl_propertylist * pro_gaintbl,
551 const cpl_propertylist * pro_coeffscube,
552 const cpl_propertylist * pro_bpm,
553 const cpl_propertylist * pro_corr,
554 const cpl_propertylist * pro_diff,
555 const char * package,
557 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
558 const cpl_boolean opt_nir,
559 const cpl_parameterlist * parlist,
562 static double irplib_compute_err(
double gain,
double ron,
double photon_noise);
564 static cpl_error_code
565 detmon_lg_dfs_save_imagelist(cpl_frameset * frameset,
566 const cpl_parameterlist * parlist,
567 const cpl_frameset *usedframes,
568 const cpl_imagelist *coeffs,
569 const char *recipe_name,
570 const cpl_propertylist *mypro_coeffscube,
571 const char * package,
572 const char * name_o);
575 static void irplib_free(
char** pointer){
577 if(pointer && *pointer) {
583 static cpl_error_code
584 detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
int nsets,
586 const char * tag_off,
587 const char * recipe_name,
588 const char * pipeline_name,
589 const char * pafregexp,
590 const cpl_propertylist * pro_lintbl,
591 const cpl_propertylist * pro_gaintbl,
592 const cpl_propertylist * pro_coeffscube,
593 const cpl_propertylist * pro_bpm,
594 const cpl_propertylist * pro_corr,
595 const cpl_propertylist * pro_diff,
596 const char * package,
598 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
599 const cpl_boolean opt_nir,
600 const cpl_parameterlist * parlist,
605 int nexts = detmon_lg_config.nb_extensions;
607 double* exptime_on = 0;
608 double* exptime_off = 0;
611 cpl_frameset * cur_fset = NULL;
612 cpl_frameset* cur_fset_on = 0;
613 cpl_frameset* cur_fset_off = 0;
618 cpl_frameset_duplicate(frameset) : cpl_frameset_extract(frameset, selection, i);
621 skip_if(cur_fset == NULL);
624 cur_fset_on = cpl_frameset_new();
625 cur_fset_off = cpl_frameset_new();
626 cpl_msg_info(cpl_func,
"Splitting into ON and OFF sub-framesets");
627 skip_if (detmon_lg_split_onoff(cur_fset,
628 cur_fset_on, cur_fset_off,
630 if (cpl_frameset_get_size(cur_fset_on) == 0)
632 cpl_msg_error(cpl_func,
"No lamp frames in input");
636 if (cpl_frameset_get_size(cur_fset_off) == 0)
638 cpl_msg_error(cpl_func,
"No dark / bias frames in input");
641 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));
649 exptime_on = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_on));
650 exptime_off = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_off));
652 index_on = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_on));
653 index_off = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_off));
654 irplib_frameset_sort(cur_fset_on, index_on, exptime_on);
655 irplib_frameset_sort(cur_fset_off, index_off, exptime_off);
668 skip_if(detmon_check_order(exptime_on, cpl_frameset_get_size(cur_fset_on), detmon_lg_config.tolerance, detmon_lg_config.order));
670 if(detmon_lg_config.exts >= 0)
678 if (detmon_lg_config.lamp_ok) {
679 skip_if(detmon_opt_lampcr(cur_fset, 0));
682 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
687 detmon_lg_config.exts,
689 recipe_name, pipeline_name, pafregexp,
690 pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff,
691 package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
693 for(j = 1; j <= nexts; j++) {
700 if (detmon_lg_config.lamp_ok) {
701 skip_if(detmon_opt_lampcr(cur_fset, j));
705 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
710 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));
715 cpl_frameset_delete(cur_fset);
716 cpl_frameset_delete(cur_fset_on);
717 cpl_frameset_delete(cur_fset_off);
720 cpl_free(exptime_on);
721 cpl_free(exptime_off);
722 return cpl_error_get_code();
800 detmon_lg(cpl_frameset * frameset,
801 const cpl_parameterlist * parlist,
803 const char * tag_off,
804 const char * recipe_name,
805 const char * pipeline_name,
806 const char * pafregexp,
807 const cpl_propertylist * pro_lintbl,
808 const cpl_propertylist * pro_gaintbl,
809 const cpl_propertylist * pro_coeffscube,
810 const cpl_propertylist * pro_bpm,
811 const cpl_propertylist * pro_corr,
812 const cpl_propertylist * pro_diff,
813 const char * package,
814 int (* compare) (
const cpl_frame *,
816 int (* load_fset) (
const cpl_frameset *,
819 const cpl_boolean opt_nir)
821 cpl_errorstate cleanstate = cpl_errorstate_get();
823 cpl_size * selection = NULL;
824 cpl_frame * first = NULL;
825 cpl_image * reference = NULL;
832 cpl_frameset * cur_fset = NULL;
833 cpl_frameset * cur_fset_on = NULL;
834 cpl_frameset * cur_fset_off = NULL;
837 cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
838 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
839 cpl_ensure_code(tag_on != NULL, CPL_ERROR_NULL_INPUT);
840 cpl_ensure_code(tag_off != NULL, CPL_ERROR_NULL_INPUT);
841 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
842 cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
843 cpl_ensure_code(pro_lintbl != NULL, CPL_ERROR_NULL_INPUT);
844 cpl_ensure_code(pro_gaintbl != NULL, CPL_ERROR_NULL_INPUT);
845 cpl_ensure_code(pro_coeffscube != NULL, CPL_ERROR_NULL_INPUT);
846 cpl_ensure_code(pro_bpm != NULL, CPL_ERROR_NULL_INPUT);
847 cpl_ensure_code(pro_corr != NULL, CPL_ERROR_NULL_INPUT);
848 cpl_ensure_code(pro_diff != NULL, CPL_ERROR_NULL_INPUT);
849 cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
851 cpl_msg_info(cpl_func,
"frameset size [%" CPL_SIZE_FORMAT
"]", cpl_frameset_get_size(frameset));
854 skip_if (detmon_lg_dfs_set_groups(frameset, tag_on, tag_off));
861 skip_if (detmon_lg_retrieve_parlist(pipeline_name, recipe_name,
869 first = cpl_frameset_get_position(frameset, 0);
870 irplib_ensure (first != NULL, CPL_ERROR_ILLEGAL_INPUT,
"Empty data set! Provide %s and %s input frames",tag_on,tag_off);
872 detmon_lg_config.load_fset = load_fset;
873 detmon_lg_config.load_fset_wrp = load_fset ? irplib_load_fset_wrp_ext : irplib_load_fset_wrp;
876 detmon_lg_config.nb_extensions = 1;
877 if (detmon_lg_config.exts < 0) {
879 detmon_lg_config.nb_extensions = cpl_frame_get_nextensions(first);
880 while (reference == NULL && i <= detmon_lg_config.nb_extensions) {
881 reference = cpl_image_load(cpl_frame_get_filename(first),
882 CPL_TYPE_FLOAT, 0, i);
883 if (reference == NULL) {
884 cpl_msg_warning(cpl_func,
"Extension %d empty, skipping", i);
885 cpl_errorstate_set(cleanstate);
889 cpl_errorstate_set(cleanstate);
890 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
891 "No data found in any extension");
892 cpl_msg_info(cpl_func,
"Using extension %d as reference", i - 1);
894 if (load_fset != NULL) {
895 cpl_frameset *
new = cpl_frameset_new();
896 cpl_imagelist * p = cpl_imagelist_new();
897 cpl_frameset_insert(
new, cpl_frame_duplicate(first));
898 (*load_fset)(
new, CPL_TYPE_FLOAT, p);
899 reference = cpl_image_duplicate(cpl_imagelist_get(p, 0));
900 cpl_imagelist_delete(p);
901 cpl_frameset_delete(
new);
903 cpl_msg_info(cpl_func,
"name=%s",cpl_frame_get_filename(first));
904 reference = cpl_image_load(cpl_frame_get_filename(first),
905 CPL_TYPE_FLOAT, 0, detmon_lg_config.exts);
907 cpl_errorstate_set(cleanstate);
908 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
909 "No data found in requested extension %d",
910 detmon_lg_config.exts);
912 skip_if (reference == NULL);
914 skip_if (detmon_lg_check_defaults(reference));
923 if (compare == NULL) {
926 cpl_msg_info(cpl_func,
"Identifying different settings");
927 selection = cpl_frameset_labelise(frameset, compare, &nsets);
928 skip_if (selection == NULL);
932 for(
int i = 0; i < nsets; i++)
934 int fr_size = cpl_frameset_get_size(frameset);
936 cpl_msg_info(cpl_func,
"Reduce data set nb %d out of %" CPL_SIZE_FORMAT
"",
938 skip_if(detmon_lg_reduce_set(i, frameset, nsets, tag_on, tag_off,
953 fr_size_new = cpl_frameset_get_size(frameset);
959 if (fr_size_new > fr_size)
961 selection = cpl_realloc(selection, fr_size_new *
sizeof(selection[0]));
962 memset(selection + fr_size, -1, (fr_size_new - fr_size) *
sizeof(selection[0]));
968 cpl_frameset_delete(cur_fset);
969 cpl_frameset_delete(cur_fset_on);
970 cpl_frameset_delete(cur_fset_off);
972 cpl_image_delete(reference);
974 return cpl_error_get_code();
1010 static cpl_error_code
1011 detmon_lg_core(cpl_frameset * cur_fset_on,
1012 cpl_frameset * cur_fset_off,
1015 double * exptime_on,
1016 double * exptime_off,
1019 const char * recipe_name,
1020 const char * pipeline_name,
1021 const char * pafregexp,
1022 const cpl_propertylist * pro_lintbl,
1023 const cpl_propertylist * pro_gaintbl,
1024 const cpl_propertylist * pro_coeffscube,
1025 const cpl_propertylist * pro_bpm,
1026 const cpl_propertylist * pro_corr,
1027 const cpl_propertylist * pro_diff,
1028 const char * package,
1029 int (* load_fset) (
const cpl_frameset *,
1032 int nsets, cpl_boolean opt_nir,
1033 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
1034 cpl_frameset * cur_fset)
1036 cpl_table * gain_table = cpl_table_new(
1037 cpl_frameset_get_size(cur_fset_on) / 2);
1038 cpl_table * linear_table = cpl_table_new(
1039 cpl_frameset_get_size(cur_fset_on) / 2);
1040 cpl_imagelist * coeffs = NULL;
1041 cpl_image * bpm = NULL;
1042 cpl_imagelist * autocorr_images = NULL;
1043 cpl_imagelist * diff_flats = NULL;
1044 cpl_propertylist * gaint_qclist = NULL;
1045 cpl_propertylist * lint_qclist = NULL;
1046 cpl_propertylist * linc_qclist = NULL;
1047 cpl_propertylist * bpm_qclist = NULL;
1049 int next_index_on = 0;
1050 int next_index_off = 0;
1053 cpl_msg_info(cpl_func,
"Reduce extension nb %d ", whichext);
1057 if (detmon_lg_config.intermediate) {
1058 autocorr_images = cpl_imagelist_new();
1059 diff_flats = cpl_imagelist_new();
1062 gaint_qclist = cpl_propertylist_new();
1063 lint_qclist = cpl_propertylist_new();
1064 linc_qclist = cpl_propertylist_new();
1065 bpm_qclist = cpl_propertylist_new();
1068 cpl_msg_info(cpl_func,
"Starting data reduction");
1069 if (detmon_lg_reduce(cur_fset_on, cur_fset_off,
1070 index_on, index_off, exptime_on, exptime_off,
1071 &next_index_on, &next_index_off,
1072 &coeffs, gain_table,
1073 linear_table, &bpm, autocorr_images,
1074 diff_flats, gaint_qclist, lint_qclist,
1075 linc_qclist, bpm_qclist, load_fset,
1076 opt_nir, whichext) == CPL_ERROR_CONTINUE) {
1077 cpl_msg_info(cpl_func,
"Empty extension %d", whichext);
1081 cpl_msg_info(cpl_func,
"Saving the products");
1084 detmon_lg_save(parlist, frameset, recipe_name,
1085 pipeline_name, pafregexp,
1086 pro_lintbl, pro_gaintbl,
1087 pro_coeffscube, pro_bpm,
1088 pro_corr, pro_diff, package,
1089 coeffs, gain_table, linear_table,
1090 bpm, autocorr_images, diff_flats,
1091 gaint_qclist, lint_qclist, linc_qclist,
1092 bpm_qclist, 0, 0, cur_fset, whichext));
1095 detmon_lg_save(parlist, frameset, recipe_name,
1096 pipeline_name, pafregexp,
1097 pro_lintbl, pro_gaintbl,
1098 pro_coeffscube, pro_bpm,
1099 pro_corr, pro_diff, package,
1100 coeffs, gain_table, linear_table,
1101 bpm, autocorr_images, diff_flats,
1102 gaint_qclist, lint_qclist, linc_qclist,
1103 bpm_qclist, 1, whichset+ 1, cur_fset,
1111 cpl_table_delete(gain_table);
1112 cpl_table_delete(linear_table);
1113 cpl_imagelist_delete(coeffs);
1114 cpl_propertylist_delete(gaint_qclist);
1115 cpl_propertylist_delete(lint_qclist);
1116 cpl_propertylist_delete(linc_qclist);
1117 if(bpm_qclist != NULL) cpl_propertylist_delete(bpm_qclist);
1118 cpl_image_delete(bpm);
1119 cpl_imagelist_delete(autocorr_images);
1120 cpl_imagelist_delete(diff_flats);
1122 return cpl_error_get_code();
1147 detmon_image_correlate(
const cpl_image * image1,
1148 const cpl_image * image2,
1149 const int m,
const int n)
1151 cpl_image *image1_padded = NULL;
1152 cpl_image *image2_padded = NULL;
1156 cpl_image *corr_image_window = NULL;
1158 cpl_image* image_ri1 = NULL;
1159 cpl_image* image_ri2 = NULL;
1160 cpl_error_code err = CPL_ERROR_NONE;
1163 cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1164 cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1166 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1167 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1169 nx = cpl_image_get_size_x(image1);
1170 ny = cpl_image_get_size_y(image1);
1172 nx2 = cpl_image_get_size_x(image2);
1173 ny2 = cpl_image_get_size_y(image2);
1176 cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
1179 image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1180 cpl_image_copy(image1_padded, image1, m + 1, n + 1);
1182 image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1183 cpl_image_copy(image2_padded, image2, m + 1, n + 1);
1189 image_ri1 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
1190 image_ri2 = cpl_image_new(nx, ny , CPL_TYPE_FLOAT_COMPLEX);
1192 cpl_fft_image(image_ri1, image1_padded, CPL_FFT_FORWARD);
1193 cpl_fft_image(image_ri2, image2_padded, CPL_FFT_FORWARD);
1194 err = cpl_error_get_code();
1195 cpl_image_delete(image1_padded);
1196 image1_padded = NULL;
1197 cpl_image_delete(image2_padded);
1198 image2_padded = NULL;
1199 if (err == CPL_ERROR_NONE)
1202 cpl_image * corr_image = NULL;
1203 cpl_image * reorganised= NULL;
1204 cpl_image * image_ri_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1205 cpl_image * image_in_inv = cpl_image_new(nx, ny,
1206 CPL_TYPE_FLOAT_COMPLEX);
1209 for (i = 1; i <= nx; i++)
1211 for (j = 1; j <= ny; j++)
1214 double complex value1, value2, value;
1215 value1 = cpl_image_get_complex(image_ri1, i, j, &rej);
1216 value2 = cpl_image_get_complex(image_ri2, i, j, &rej);;
1217 value = conj(value1) * value2;
1218 cpl_image_set_complex(image_in_inv, i, j, value);
1221 cpl_image_delete(image_ri1);
1223 cpl_image_delete(image_ri2);
1226 err = cpl_error_get_code();
1227 if (err == CPL_ERROR_NONE)
1231 cpl_fft_image(image_ri_inv, image_in_inv,CPL_FFT_BACKWARD);
1232 cpl_image_delete(image_in_inv);
1235 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1236 for (i = 1; i <= nx; i++)
1238 for (j = 1; j <= ny; j++)
1242 value = cpl_image_get(image_ri_inv, i, j, &rej);
1243 cpl_image_set(corr_image, i, j, value);
1246 cpl_image_delete(image_ri_inv);
1247 err = cpl_error_get_code();
1248 if (err == CPL_ERROR_NONE)
1252 cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
1253 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1255 cpl_image_copy(reorganised, image, 1, 1);
1256 cpl_image_delete(image);
1257 image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
1258 cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
1259 cpl_image_delete(image);
1261 cpl_image_delete(corr_image);
1263 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1264 image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
1265 cpl_image_copy(corr_image, image, 1, 1);
1266 cpl_image_delete(image);
1268 image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
1269 cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
1270 cpl_image_delete(image);
1272 corr_image_window = cpl_image_extract(corr_image,
1275 nx / 2 + 1 + m, ny / 2 + 1 + n);
1280 cpl_image_delete(reorganised);
1281 cpl_image_delete(corr_image);
1283 if(cpl_image_divide_scalar(corr_image_window,
1284 cpl_image_get_max(corr_image_window))) {
1285 cpl_image_delete(corr_image_window);
1289 cpl_image_delete (image_ri1);
1290 cpl_image_delete (image_ri2);
1291 cpl_image_delete (image1_padded);
1292 cpl_image_delete (image2_padded);
1293 return corr_image_window;
1316 detmon_autocorrelate(
const cpl_image * input2,
const int m,
1319 cpl_image *im_re = NULL;
1320 cpl_image *im_im = NULL;
1322 cpl_image *ifft_re = NULL;
1323 cpl_image *ifft_im = NULL;
1324 cpl_image *autocorr = NULL;
1325 cpl_image *autocorr_norm_double = NULL;
1326 cpl_image *autocorr_norm = NULL;
1327 cpl_image *reorganised = NULL;
1328 cpl_image *image = NULL;
1330 cpl_error_code error;
1333 cpl_ensure(input2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1335 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1336 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1338 nx = cpl_image_get_size_x(input2) + 2 * m;
1339 ny = cpl_image_get_size_y(input2) + 2 * n;
1342 while(nx > p || ny > p) {
1346 input = cpl_image_cast(input2, CPL_TYPE_DOUBLE);
1348 im_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1349 error = cpl_image_copy(im_re, input, 1, 1);
1350 cpl_image_delete(input);
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 return autocorr_norm;
1456 detmon_lg_fill_parlist_nir_default(cpl_parameterlist * parlist,
1457 const char *recipe_name,
1458 const char *pipeline_name)
1460 const cpl_error_code error =
1461 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1507 cpl_ensure_code(!error, error);
1509 return cpl_error_get_code();
1525 detmon_lg_fill_parlist_opt_default(cpl_parameterlist * parlist,
1526 const char *recipe_name,
1527 const char *pipeline_name)
1529 const cpl_error_code error =
1530 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1575 cpl_ensure_code(!error, error);
1577 return cpl_error_get_code();
1580 static cpl_error_code
1581 detmon_lg_fill_parlist_default_mr(cpl_parameterlist * parlist,
1582 const char *recipe_name,
1583 const char *pipeline_name)
1585 char * group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1586 char * par_name = cpl_sprintf(
"%s.%s", group_name,
"regions-file");
1587 cpl_parameter * p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1588 "File containing regions, "
1589 "four comma separated points "
1592 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions-file");
1593 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1594 cpl_parameterlist_append(parlist, p);
1596 cpl_free(group_name);
1598 group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1599 par_name = cpl_sprintf(
"%s.%s", group_name,
"regions");
1600 p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1601 "Colon separated list of regions, four "
1602 "points each, comma separated: "
1603 "llx,lly,urx,ury:llx,...",
1605 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions");
1606 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1607 cpl_parameterlist_append(parlist, p);
1609 cpl_free(group_name);
1611 return cpl_error_get_code();
1615 detmon_lg_fill_parlist_opt_default_mr(cpl_parameterlist * parlist,
1616 const char *recipe_name,
1617 const char *pipeline_name)
1619 detmon_lg_fill_parlist_opt_default(parlist, recipe_name, pipeline_name);
1620 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1621 return cpl_error_get_code();
1625 detmon_lg_fill_parlist_nir_default_mr(cpl_parameterlist * parlist,
1626 const char *recipe_name,
1627 const char *pipeline_name)
1629 detmon_lg_fill_parlist_nir_default(parlist, recipe_name, pipeline_name);
1630 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1632 return cpl_error_get_code();
1692 detmon_lg_fill_parlist(cpl_parameterlist * parlist,
1693 const char *recipe_name,
const char *pipeline_name,
1703 const char *intermediate,
1704 const char *autocorr,
1705 const char *collapse,
1706 const char *rescale,
1707 const char *pix2pix,
1714 const char * pafname,
1731 int llx5,
int lly5,
int urx5,
int ury5,
int exts,
1732 cpl_boolean opt_nir)
1734 const cpl_error_code error =
1735 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 26,
1737 "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
1738 "CPL_TYPE_STRING", method,
1741 "Polynomial order for the fit (Linearity)",
1742 "CPL_TYPE_INT", order,
1744 "Kappa value for the kappa-sigma clipping (Gain)",
1745 "CPL_TYPE_DOUBLE", kappa,
1747 "Number of iterations to compute rms (Gain)",
1748 "CPL_TYPE_INT", niter,
1750 "x coordinate of the lower-left "
1751 "point of the region of interest. If not modified, default value will be 1.",
1752 "CPL_TYPE_INT", llx,
1754 "y coordinate of the lower-left "
1755 "point of the region of interest. If not modified, default value will be 1.",
1756 "CPL_TYPE_INT", lly,
1758 "x coordinate of the upper-right "
1759 "point of the region of interest. If not modified, default value will be X dimension of the input image.",
1760 "CPL_TYPE_INT", urx,
1762 "y coordinate of the upper-right "
1763 "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
1764 "CPL_TYPE_INT", ury,
1766 "User reference level",
1767 "CPL_TYPE_INT", ref_level,
1769 "De-/Activate intermediate products",
1770 "CPL_TYPE_BOOL", intermediate,
1773 "De-/Activate the autocorr option",
1774 "CPL_TYPE_BOOL", autocorr,
1777 "De-/Activate the collapse option",
1778 "CPL_TYPE_BOOL", collapse,
1780 "De-/Activate the image rescale option",
1781 "CPL_TYPE_BOOL", rescale,
1783 "De-/Activate the computation with pixel to pixel accuracy",
1784 "CPL_TYPE_BOOL", pix2pix,
1786 "De-/Activate the binary bpm option",
1787 "CPL_TYPE_BOOL", bpmbin,
1789 "Maximum x-shift for the autocorr",
1792 "Upper limit of Median flux to be filtered",
1793 "CPL_TYPE_INT", filter,
1795 "Maximum y-shift for the autocorr",
1798 "Tolerance for pair discrimination",
1799 "CPL_TYPE_DOUBLE", tolerance,
1802 "Generate PAF file",
1803 "CPL_TYPE_BOOL", pafgen,
1805 "Specific name for PAF file",
1806 "CPL_TYPE_STRING", pafname,
1810 "Activate the multi-exts option. Choose -1 to process all extensions. Choose an extension number"
1811 " to process the appropriate extension.",
1812 "CPL_TYPE_INT", exts,
1815 "Method for computing Fixed Pattern Noise (SMOOTH or HISTOGRAM)",
1816 "CPL_TYPE_STRING",
"HISTOGRAM",
1819 "template size in pixels for smoothing during FPN computation (only for SMOOTH method)",
1823 "all frames with mean saturation above the limit would not be used in linearity calculation",
1824 "CPL_TYPE_DOUBLE", 65535.0,
1827 "all frames with mean flux above the threshold would not be used in gain calculation",
1828 "CPL_TYPE_DOUBLE", 65535.0
1831 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 1,
1832 "coeffs_cube_split",
1833 "if TRUE, the recipe writes as many "
1834 "COEFFS_CUBE_Pi (i=0..order) as the value of "
1835 "the order parameter in a separate file",
1836 "CPL_TYPE_BOOL",
"CPL_FALSE");
1838 if(opt_nir == FALSE) {
1839 const cpl_error_code erroropt =
1840 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
1842 "x coord of the lower-left point of the first "
1843 "field used for contamination measurement. If not modified, default value will be 1.",
1844 "CPL_TYPE_INT", llx1,
1846 "y coord of the lower-left point of the first "
1847 "field used for contamination measurement. If not modified, default value will be 1.",
1848 "CPL_TYPE_INT", lly1,
1850 "x coord of the upper-right point of the first "
1851 "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
1852 "CPL_TYPE_INT", urx1,
1854 "y coord of the upper-right point of the first "
1855 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1856 "CPL_TYPE_INT", ury1,
1858 "x coord of the lower-left point of the second "
1859 "field used for contamination measurement. If not modified, default value will be 1.",
1860 "CPL_TYPE_INT", llx2,
1862 "y coord of the lower-left point of the second "
1863 "field used for contamination measurement. If not modified, default value will be 1.",
1864 "CPL_TYPE_INT", lly2,
1866 "x coord of the upper-right point of the second "
1867 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1868 "CPL_TYPE_INT", urx2,
1870 "y coord of the upper-right point of the second "
1871 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1872 "CPL_TYPE_INT", ury2,
1874 "x coord of the lower-left point of the third "
1875 "field used for contamination measurement. If not modified, default value will be 1.",
1876 "CPL_TYPE_INT", llx3,
1878 "y coord of the lower-left point of the third "
1879 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1880 "CPL_TYPE_INT", lly3,
1882 "x coord of the upper-right point of the third "
1883 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1884 "CPL_TYPE_INT", urx3,
1886 "y coord of the upper-right point of the third "
1887 "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
1888 "CPL_TYPE_INT", ury3,
1890 "x coord of the lower-left point of the fourth "
1891 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1892 "CPL_TYPE_INT", llx4,
1894 "y coord of the lower-left point of the fourth "
1895 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1896 "CPL_TYPE_INT", lly4,
1898 "x coord of the upper-right point of the fourth "
1899 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1900 "CPL_TYPE_INT", urx4,
1902 "y coord of the upper-right point of the fourth "
1903 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1904 "CPL_TYPE_INT", ury4,
1906 "x coord of the lower-left point of the fifth "
1907 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1908 "CPL_TYPE_INT", llx5,
1910 "y coord of the lower-left point of the fifth "
1911 "field used for contamination measurement. If not modified, default value will be 1.",
1912 "CPL_TYPE_INT", lly5,
1914 "x coord of the upper-right point of the fifth "
1915 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1916 "CPL_TYPE_INT", urx5,
1919 "y coord of the upper-right point of the fifth "
1920 "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
1921 "CPL_TYPE_INT", ury5);
1924 cpl_ensure_code(!erroropt, erroropt);
1927 cpl_ensure_code(!error, error);
1929 return cpl_error_get_code();
1942 static cpl_error_code
1943 detmon_lg_retrieve_parlist(
const char * pipeline_name,
1944 const char * recipe_name,
1945 const cpl_parameterlist * parlist,
1946 cpl_boolean opt_nir)
1950 const cpl_parameter * par;
1953 par_name = cpl_sprintf(
"%s.%s.method", pipeline_name, recipe_name);
1954 assert(par_name != NULL);
1955 par = cpl_parameterlist_find_const(parlist, par_name);
1956 detmon_lg_config.method = cpl_parameter_get_string(par);
1960 detmon_lg_config.order =
1961 detmon_retrieve_par_int(
"order", pipeline_name, recipe_name,
1965 detmon_lg_config.kappa =
1966 detmon_retrieve_par_double(
"kappa", pipeline_name, recipe_name,
1970 detmon_lg_config.niter =
1971 detmon_retrieve_par_int(
"niter", pipeline_name, recipe_name,
1975 detmon_lg_config.llx =
1976 detmon_retrieve_par_int(
"llx", pipeline_name, recipe_name,
1980 detmon_lg_config.lly =
1981 detmon_retrieve_par_int(
"lly", pipeline_name, recipe_name,
1985 detmon_lg_config.urx =
1986 detmon_retrieve_par_int(
"urx", pipeline_name, recipe_name,
1990 detmon_lg_config.ury =
1991 detmon_retrieve_par_int(
"ury", pipeline_name, recipe_name,
1995 detmon_lg_config.ref_level =
1996 detmon_retrieve_par_int(
"ref_level", pipeline_name, recipe_name,
2001 cpl_sprintf(
"%s.%s.intermediate", pipeline_name, recipe_name);
2002 assert(par_name != NULL);
2003 par = cpl_parameterlist_find_const(parlist, par_name);
2004 detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
2008 par_name = cpl_sprintf(
"%s.%s.autocorr", pipeline_name, recipe_name);
2009 assert(par_name != NULL);
2010 par = cpl_parameterlist_find_const(parlist, par_name);
2011 detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
2015 par_name = cpl_sprintf(
"%s.%s.coeffs_cube_split", pipeline_name, recipe_name);
2016 assert(par_name != NULL);
2017 par = cpl_parameterlist_find_const(parlist, par_name);
2018 detmon_lg_config.split_coeffs = cpl_parameter_get_bool(par);
2022 par_name = cpl_sprintf(
"%s.%s.collapse", pipeline_name, recipe_name);
2023 assert(par_name != NULL);
2024 par = cpl_parameterlist_find_const(parlist, par_name);
2025 detmon_lg_config.collapse = cpl_parameter_get_bool(par);
2029 par_name = cpl_sprintf(
"%s.%s.rescale", pipeline_name, recipe_name);
2030 assert(par_name != NULL);
2031 par = cpl_parameterlist_find_const(parlist, par_name);
2032 detmon_lg_config.rescale = cpl_parameter_get_bool(par);
2036 par_name = cpl_sprintf(
"%s.%s.pix2pix", pipeline_name, recipe_name);
2037 assert(par_name != NULL);
2038 par = cpl_parameterlist_find_const(parlist, par_name);
2039 detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
2043 par_name = cpl_sprintf(
"%s.%s.bpmbin", pipeline_name, recipe_name);
2044 assert(par_name != NULL);
2045 par = cpl_parameterlist_find_const(parlist, par_name);
2046 detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
2050 detmon_lg_config.filter =
2051 detmon_retrieve_par_int(
"filter", pipeline_name,
2052 recipe_name, parlist);
2055 detmon_lg_config.m =
2056 detmon_retrieve_par_int(
"m", pipeline_name, recipe_name, parlist);
2059 detmon_lg_config.n =
2060 detmon_retrieve_par_int(
"n", pipeline_name, recipe_name, parlist);
2063 par_name = cpl_sprintf(
"%s.%s.tolerance", pipeline_name, recipe_name);
2064 assert(par_name != NULL);
2065 par = cpl_parameterlist_find_const(parlist, par_name);
2066 detmon_lg_config.tolerance = cpl_parameter_get_double(par);
2071 par_name = cpl_sprintf(
"%s.%s.pafgen", pipeline_name, recipe_name);
2072 assert(par_name != NULL);
2073 par = cpl_parameterlist_find_const(parlist, par_name);
2074 detmon_lg_config.pafgen = cpl_parameter_get_bool(par);
2078 par_name = cpl_sprintf(
"%s.%s.pafname", pipeline_name, recipe_name);
2079 assert(par_name != NULL);
2080 par = cpl_parameterlist_find_const(parlist, par_name);
2081 detmon_lg_config.pafname = cpl_parameter_get_string(par);
2084 if(opt_nir == OPT) {
2086 detmon_lg_config.llx1 =
2087 detmon_retrieve_par_int(
"llx1", pipeline_name, recipe_name,
2091 detmon_lg_config.lly1 =
2092 detmon_retrieve_par_int(
"lly1", pipeline_name, recipe_name,
2096 detmon_lg_config.urx1 =
2097 detmon_retrieve_par_int(
"urx1", pipeline_name, recipe_name,
2101 detmon_lg_config.ury1 =
2102 detmon_retrieve_par_int(
"ury1", pipeline_name, recipe_name,
2106 detmon_lg_config.llx2 =
2107 detmon_retrieve_par_int(
"llx2", pipeline_name, recipe_name,
2111 detmon_lg_config.lly2 =
2112 detmon_retrieve_par_int(
"lly2", pipeline_name, recipe_name,
2116 detmon_lg_config.urx2 =
2117 detmon_retrieve_par_int(
"urx2", pipeline_name, recipe_name,
2121 detmon_lg_config.ury2 =
2122 detmon_retrieve_par_int(
"ury2", pipeline_name, recipe_name,
2126 detmon_lg_config.llx3 =
2127 detmon_retrieve_par_int(
"llx3", pipeline_name, recipe_name,
2131 detmon_lg_config.lly3 =
2132 detmon_retrieve_par_int(
"lly3", pipeline_name, recipe_name,
2136 detmon_lg_config.urx3 =
2137 detmon_retrieve_par_int(
"urx3", pipeline_name, recipe_name,
2141 detmon_lg_config.ury3 =
2142 detmon_retrieve_par_int(
"ury3", pipeline_name, recipe_name,
2146 detmon_lg_config.llx4 =
2147 detmon_retrieve_par_int(
"llx4", pipeline_name, recipe_name,
2151 detmon_lg_config.lly4 =
2152 detmon_retrieve_par_int(
"lly4", pipeline_name, recipe_name,
2156 detmon_lg_config.urx4 =
2157 detmon_retrieve_par_int(
"urx4", pipeline_name, recipe_name,
2161 detmon_lg_config.ury4 =
2162 detmon_retrieve_par_int(
"ury4", pipeline_name, recipe_name,
2166 detmon_lg_config.llx5 =
2167 detmon_retrieve_par_int(
"llx5", pipeline_name, recipe_name,
2171 detmon_lg_config.lly5 =
2172 detmon_retrieve_par_int(
"lly5", pipeline_name, recipe_name,
2176 detmon_lg_config.urx5 =
2177 detmon_retrieve_par_int(
"urx5", pipeline_name, recipe_name,
2181 detmon_lg_config.ury5 =
2182 detmon_retrieve_par_int(
"ury5", pipeline_name, recipe_name,
2187 detmon_lg_config.exts =
2188 detmon_retrieve_par_int(
"exts", pipeline_name, recipe_name,
2192 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2194 cpl_sprintf(
"%s.%s.fpn_method", pipeline_name, recipe_name);
2195 assert(par_name != NULL);
2196 par = cpl_parameterlist_find_const(parlist, par_name);
2199 const char * str_method = cpl_parameter_get_string(par);
2200 if (strcmp(str_method,
"SMOOTH") == 0)
2202 detmon_lg_config.fpn_method = FPN_SMOOTH;
2204 else if (strcmp(str_method,
"HISTOGRAM") == 0)
2206 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2212 detmon_lg_config.fpn_smooth =
2213 detmon_retrieve_par_int(
"fpn_smooth", pipeline_name, recipe_name,
2217 detmon_lg_config.saturation_limit = 65535;
2219 cpl_sprintf(
"%s.%s.saturation_limit", pipeline_name, recipe_name);
2220 assert(par_name != NULL);
2221 par = cpl_parameterlist_find_const(parlist, par_name);
2224 detmon_lg_config.saturation_limit = cpl_parameter_get_double(par);
2231 detmon_lg_config.gain_threshold = 0;
2233 cpl_sprintf(
"%s.%s.gain_threshold", pipeline_name, recipe_name);
2234 assert(par_name != NULL);
2235 par = cpl_parameterlist_find_const(parlist, par_name);
2238 detmon_lg_config.gain_threshold = cpl_parameter_get_double(par);
2243 if(cpl_error_get_code())
2245 cpl_msg_error(cpl_func,
"Failed to retrieve the input parameters");
2246 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
2250 return cpl_error_get_code();
2260 static cpl_error_code
2261 detmon_lg_check_defaults(
const cpl_image * reference)
2263 const int nx = cpl_image_get_size_x(reference);
2264 const int ny = cpl_image_get_size_y(reference);
2266 detmon_lg_config.nx = nx;
2267 detmon_lg_config.ny = ny;
2269 detmon_lg_config.wholechip = CPL_FALSE;
2271 if(detmon_lg_config.llx == -1)
2272 detmon_lg_config.llx = 1;
2273 if(detmon_lg_config.lly == -1)
2274 detmon_lg_config.lly = 1;
2275 if(detmon_lg_config.urx == -1)
2276 detmon_lg_config.urx = nx;
2277 if(detmon_lg_config.ury == -1)
2278 detmon_lg_config.ury = ny;
2280 if (detmon_lg_config.llx == 1 &&
2281 detmon_lg_config.lly == 1 &&
2282 detmon_lg_config.urx == nx &&
2283 detmon_lg_config.ury == ny)
2284 detmon_lg_config.wholechip = CPL_TRUE;
2286 if(detmon_lg_config.llx1 == -1)
2287 detmon_lg_config.llx1 = 1;
2288 if(detmon_lg_config.lly1 == -1)
2289 detmon_lg_config.lly1 = 1;
2290 if(detmon_lg_config.urx1 == -1)
2291 detmon_lg_config.urx1 = nx;
2292 if(detmon_lg_config.ury1 == -1)
2293 detmon_lg_config.ury1 = ny;
2295 if(detmon_lg_config.llx2 == -1)
2296 detmon_lg_config.llx2 = 1;
2297 if(detmon_lg_config.lly2 == -1)
2298 detmon_lg_config.lly2 = 1;
2299 if(detmon_lg_config.urx2 == -1)
2300 detmon_lg_config.urx2 = nx / 2;
2301 if(detmon_lg_config.ury2 == -1)
2302 detmon_lg_config.ury2 = ny / 2;
2304 if(detmon_lg_config.llx3 == -1)
2305 detmon_lg_config.llx3 = 1;
2306 if(detmon_lg_config.lly3 == -1)
2307 detmon_lg_config.lly3 = ny / 2;
2308 if(detmon_lg_config.urx3 == -1)
2309 detmon_lg_config.urx3 = nx / 2;
2310 if(detmon_lg_config.ury3 == -1)
2311 detmon_lg_config.ury3 = ny;
2313 if(detmon_lg_config.llx4 == -1)
2314 detmon_lg_config.llx4 = nx / 2;
2315 if(detmon_lg_config.lly4 == -1)
2316 detmon_lg_config.lly4 = ny / 2;
2317 if(detmon_lg_config.urx4 == -1)
2318 detmon_lg_config.urx4 = nx;
2319 if(detmon_lg_config.ury4 == -1)
2320 detmon_lg_config.ury4 = ny;
2322 if(detmon_lg_config.llx5 == -1)
2323 detmon_lg_config.llx5 = nx / 2;
2324 if(detmon_lg_config.lly5 == -1)
2325 detmon_lg_config.lly5 = 1;
2326 if(detmon_lg_config.urx5 == -1)
2327 detmon_lg_config.urx5 = nx;
2328 if(detmon_lg_config.ury5 == -1)
2329 detmon_lg_config.ury5 = ny / 2;
2331 if(detmon_lg_config.intermediate == TRUE) {
2332 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.");
2333 detmon_lg_config.autocorr = TRUE;
2337 detmon_lg_config.lamp_stability = 0.0;
2339 detmon_lg_config.lamp_ok = FALSE;
2341 detmon_lg_config.cr = 0.0;
2343 return cpl_error_get_code();
2358 static cpl_error_code
2359 detmon_lg_split_onoff(
const cpl_frameset * cur_fset,
2360 cpl_frameset * cur_fset_on,
2361 cpl_frameset * cur_fset_off,
2363 const char *tag_off)
2368 cpl_frame * cur_frame_dup = NULL;
2371 const cpl_frame * first;
2372 const cpl_frame * second;
2373 const char * first_tag;
2374 const char * second_tag;
2375 skip_if((first = cpl_frameset_get_position_const(cur_fset, 0)) == NULL);
2376 skip_if((second = cpl_frameset_get_position_const(cur_fset, 1)) == NULL);
2378 skip_if((first_tag = cpl_frame_get_tag(first)) == NULL);
2379 skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
2380 if (opt_nir == OPT &&
2381 ((!strcmp(first_tag, tag_on ) && !strcmp(second_tag, tag_off)) ||
2382 (!strcmp(first_tag, tag_off) && !strcmp(second_tag, tag_on )))) {
2383 detmon_lg_config.lamp_ok = TRUE;
2387 nframes = cpl_frameset_get_size(cur_fset);
2388 for(i = detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
2389 const cpl_frame * cur_frame =
2390 cpl_frameset_get_position_const(cur_fset, i);
2394 cur_frame_dup = cpl_frame_duplicate(cur_frame);
2395 tag = (
char *) cpl_frame_get_tag(cur_frame_dup);
2398 if(!strcmp(tag, tag_on)) {
2399 skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
2400 }
else if(!strcmp(tag, tag_off)) {
2401 skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
2403 cpl_frame_delete(cur_frame_dup);
2404 cur_frame_dup = NULL;
2407 cur_frame_dup = NULL;
2411 cpl_frame_delete(cur_frame_dup);
2413 return cpl_error_get_code();
2440 static cpl_error_code
2441 detmon_lg_reduce(
const cpl_frameset * set_on,
2442 const cpl_frameset * set_off,
2443 int* index_on,
int* index_off,
2444 double* exptime_on,
double* exptime_off,
2445 int *next_index_on,
int* next_index_off,
2446 cpl_imagelist ** coeffs_ptr,
2447 cpl_table * gain_table,
2448 cpl_table * linear_table,
2449 cpl_image ** bpm_ptr,
2450 cpl_imagelist * autocorr_images,
2451 cpl_imagelist * diff_flats,
2452 cpl_propertylist * gaint_qclist,
2453 cpl_propertylist * lint_qclist,
2454 cpl_propertylist * linc_qclist,
2455 cpl_propertylist * bpm_qclist,
2456 int (* load_fset) (
const cpl_frameset *,
2459 const cpl_boolean opt_nir,
2462 cpl_errorstate prestate = cpl_errorstate_get();
2463 const double D_INVALID_VALUE = -999;
2465 cpl_imagelist * linearity_inputs = NULL;
2466 cpl_imagelist * opt_offs = NULL;
2468 cpl_propertylist * reflist = NULL;
2470 int rows_linear_affected = 1;
2471 int rows_gain_affected = 1;
2472 int last_linear_best = 0;
2474 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2475 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2477 nsets = cpl_frameset_get_size(set_on) / 2;
2479 detmon_lg_config.load_fset = load_fset;
2480 if(detmon_lg_config.collapse) {
2487 const cpl_frame *first = cpl_frameset_get_position_const(set_off, 0);
2488 cpl_frame *dup_first = cpl_frame_duplicate(first);
2490 const cpl_frame *second = cpl_frameset_get_position_const(set_off, 1);
2491 cpl_frame *dup_second = cpl_frame_duplicate(second);
2493 cpl_frameset *raw_offs = cpl_frameset_new();
2495 skip_if(cpl_frameset_insert(raw_offs, dup_first));
2496 skip_if(cpl_frameset_insert(raw_offs, dup_second));
2498 opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
2501 cpl_frameset_delete(raw_offs);
2502 if (opt_offs == NULL) {
2503 cpl_errorstate_set(prestate);
2504 return CPL_ERROR_CONTINUE;
2508 skip_if(detmon_lg_reduce_init(gain_table,
2520 if(detmon_lg_lamp_stab(set_on, set_off,
2521 opt_nir, whichext)) {
2522 cpl_errorstate_set(prestate);
2525 if(!detmon_lg_config.collapse)
2529 skip_if(cpl_table_unselect_all(linear_table));
2530 skip_if(cpl_table_unselect_all(gain_table));
2534 for(i = 0; i < nsets ; i++)
2536 skip_if(detmon_lg_reduce_dit(set_on,
2537 index_on, exptime_on,
2541 index_off, exptime_off,
2542 next_index_on, next_index_off,
2544 gain_table, linearity_inputs,
2545 lint_qclist, opt_nir,
2546 autocorr_images, diff_flats,
2548 &rows_linear_affected,&rows_gain_affected));
2552 if (rows_linear_affected == 0)
2554 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2555 "into linear calculation, check the messages above");
2556 cpl_table_select_row(linear_table, i);
2560 last_linear_best = i;
2563 if (rows_gain_affected == 0)
2565 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2566 "into gain calculation, check the messages above");
2567 cpl_table_select_row(gain_table, i);
2574 skip_if(detmon_add_adl_column(linear_table, opt_nir));
2580 skip_if(cpl_table_erase_selected(gain_table));
2581 skip_if(cpl_table_erase_selected(linear_table));
2584 reflist = cpl_propertylist_new();
2585 skip_if(cpl_propertylist_append_bool(reflist,
"ADU", FALSE));
2586 skip_if(cpl_table_sort(gain_table, reflist));
2592 skip_if(detmon_lg_reduce_all(linear_table,
2593 gaint_qclist, lint_qclist, linc_qclist,
2594 bpm_qclist, coeffs_ptr, bpm_ptr,
2596 gain_table, whichext, opt_nir));
2599 double gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
2602 cpl_error_code cplerr = cpl_error_get_code();
2603 if (cplerr != CPL_ERROR_NONE || (gain == 0.0))
2605 cpl_msg_warning(cpl_func,
"Cannot read gain from QC parameters - "
2606 "FPN will not be computed");
2611 detmon_fpn_compute(set_on, index_on, last_linear_best, lint_qclist,
2612 detmon_lg_config.llx,
2613 detmon_lg_config.lly,
2614 detmon_lg_config.urx,
2615 detmon_lg_config.ury,
2618 detmon_lg_config.fpn_method,
2619 detmon_lg_config.fpn_smooth);
2624 detmon_table_fill_invalid(gain_table, D_INVALID_VALUE);
2626 cpl_imagelist_delete(linearity_inputs);
2627 cpl_imagelist_delete(opt_offs);
2628 cpl_propertylist_delete(reflist);
2630 return cpl_error_get_code();
2633 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code)
2635 int ncols = cpl_table_get_ncol(ptable);
2636 cpl_array* pnames = cpl_table_get_column_names(ptable);
2637 int nrows = cpl_table_get_nrow(ptable);
2639 for (i=0; i < ncols; i++)
2642 for (j = 0; j< nrows; j++)
2644 const char* colname = cpl_array_get_data_string_const(pnames)[i];
2646 cpl_type type = cpl_table_get_column_type(ptable, colname);
2647 cpl_table_get(ptable, colname, j, &isnull);
2650 if (type == CPL_TYPE_DOUBLE)
2652 cpl_table_set(ptable,colname,j, code);
2654 else if (type == CPL_TYPE_FLOAT)
2656 cpl_table_set_float(ptable,colname,j, (
float)code);
2661 cpl_array_delete(pnames);
2662 return cpl_error_get_code();
2665 static cpl_error_code
2666 detmon_fpn_compute(
const cpl_frameset *set_on,
2668 int last_linear_best,
2669 cpl_propertylist *lint_qclist,
2676 FPN_METHOD fpn_method,
2680 const cpl_image* im1 = 0;
2682 cpl_imagelist* ons = 0;
2683 cpl_frameset * pair_on = 0;
2684 int nsets_extracted = cpl_frameset_get_size(set_on);
2685 cpl_size * selection = NULL;
2694 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
2695 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
2697 selection[index_on[last_linear_best*2 + 0] ] = 1;
2698 selection[index_on[last_linear_best*2 + 1] ] = 1;
2699 pair_on = cpl_frameset_extract(set_on, selection, 1);
2700 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2702 skip_if(ons == NULL);
2703 skip_if((im1 = cpl_imagelist_get_const(ons, 0)) == NULL);
2705 fpn = irplib_fpn_lg(im1, range, gain, fpn_method, smooth_size, &mse);
2706 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_FPN,
2708 skip_if(cpl_propertylist_append_double(lint_qclist,
"ESO QC GAIN ERR",
2712 cpl_frameset_delete(pair_on);
2713 cpl_imagelist_delete(ons);
2714 cpl_free(selection);
2715 return cpl_error_get_code();
2727 static cpl_error_code
2728 detmon_lg_lamp_stab(
const cpl_frameset * lamps,
2729 const cpl_frameset * darks,
2730 cpl_boolean opt_nir,
2743 cpl_vector * selection = NULL;
2744 cpl_propertylist * plist;
2745 double dit_lamp, dit_dark;
2747 cpl_imagelist * lamps_data = NULL;
2748 cpl_imagelist * darks_data = NULL;
2749 double * stab_levels = NULL;
2751 double * ditvals = NULL;
2755 cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
2756 CPL_ERROR_ILLEGAL_INPUT);
2762 cpl_msg_info(__func__,
"Checking DIT consistency");
2763 selection = cpl_vector_new(nb_lamps);
2764 ditvals = cpl_malloc(nb_lamps *
sizeof(
double));
2766 for (i = 0; i < nb_lamps; i++) {
2767 const cpl_frame * c_lamp;
2768 const cpl_frame * c_dark;
2770 skip_if (cpl_error_get_code());
2773 c_lamp = cpl_frameset_get_position_const(lamps, i);
2774 plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
2776 dit_lamp = (double)detmon_pfits_get_dit(plist);
2778 dit_lamp = (double)detmon_pfits_get_dit_opt(plist);
2779 cpl_propertylist_delete(plist);
2780 skip_if (cpl_error_get_code());
2783 c_dark = cpl_frameset_get_position_const(darks, i);
2784 plist = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
2786 dit_dark = (double)detmon_pfits_get_dit(plist);
2788 dit_dark = (double)detmon_pfits_get_dit_opt(plist);
2789 cpl_propertylist_delete(plist);
2790 skip_if (cpl_error_get_code());
2793 if (fabs(dit_dark-dit_lamp) > 1e-3) {
2794 cpl_msg_error(__func__,
"DIT not consistent between LAMP and DARK, skip lamp stability computation");
2799 ditvals[i] = dit_lamp;
2802 cpl_vector_set(selection, i, -1.0);
2810 if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
2811 cpl_vector_set(selection, i, -1.0);
2815 cpl_vector_set(selection, i, 1.0);
2822 cpl_msg_info(__func__,
"Not enough frames for stability check");
2826 cpl_msg_info(__func__,
"Compute the differences lamp - dark");
2829 lamps_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2831 detmon_lg_config.llx,
2832 detmon_lg_config.lly,
2833 detmon_lg_config.urx,
2834 detmon_lg_config.ury,
2837 darks_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2839 detmon_lg_config.llx,
2840 detmon_lg_config.lly,
2841 detmon_lg_config.urx,
2842 detmon_lg_config.ury,
2845 nb_darks=cpl_imagelist_get_size(darks_data);
2846 if(nb_darks==nb_lamps) {
2847 skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
2849 cpl_image* master_dark=cpl_imagelist_collapse_median_create(darks_data);
2850 cpl_imagelist_subtract_image(lamps_data,master_dark);
2851 cpl_image_delete(master_dark);
2854 cpl_msg_info(__func__,
"Check the lamp stability");
2855 stab_levels = cpl_malloc(dit_stab *
sizeof(
double));
2857 for (i=0; i<nb_lamps; i++) {
2858 if (cpl_vector_get(selection, i) < 0) {
2860 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
2866 for (i=1; i<dit_stab; i++) {
2867 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
2868 detmon_lg_config.lamp_stability)
2869 detmon_lg_config.lamp_stability =
2870 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
2875 if (detmon_lg_config.lamp_stability > 0.01) {
2876 cpl_msg_warning(__func__,
2877 "Lamp stability level %g difference too high - proceed anyway",detmon_lg_config.lamp_stability);
2884 cpl_vector_delete(selection);
2885 cpl_imagelist_delete(lamps_data);
2886 cpl_imagelist_delete(darks_data);
2887 cpl_free(stab_levels);
2889 return cpl_error_get_code();
2916 static cpl_error_code
2917 detmon_lg_reduce_dit(
const cpl_frameset * set_on,
2918 int* index_on,
double* exptime_on,
2921 const cpl_frameset * set_off,
2922 int * index_off,
double* exptime_off,
2923 int* next_on,
int* next_off,
2924 cpl_table * linear_table,
2925 cpl_table * gain_table,
2926 cpl_imagelist * linearity_inputs,
2927 cpl_propertylist * qclist,
2928 cpl_boolean opt_nir,
2929 cpl_imagelist * autocorr_images,
2930 cpl_imagelist * diff_flats,
2931 cpl_imagelist * opt_offs,
2933 int* rows_linear_affected,
2934 int* rows_gain_affected)
2936 cpl_frameset * pair_on = NULL;
2937 cpl_frameset * pair_off = NULL;
2938 cpl_imagelist * ons = NULL;
2939 cpl_imagelist * offs = NULL;
2940 cpl_boolean follow = CPL_TRUE;
2941 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
2945 double current_dit = 0;
2947 const char * filename;
2949 cpl_propertylist * plist = NULL;
2950 cpl_propertylist* pDETlist = NULL;
2952 mode = detmon_lg_config.collapse ?
2953 mode | IRPLIB_GAIN_COLLAPSE | IRPLIB_LIN_COLLAPSE:
2954 mode | IRPLIB_GAIN_NO_COLLAPSE | IRPLIB_LIN_NO_COLLAPSE;
2955 mode = detmon_lg_config.pix2pix ?
2956 mode | IRPLIB_LIN_PIX2PIX : mode;
2958 mode | IRPLIB_GAIN_NIR | IRPLIB_LIN_NIR :
2959 mode | IRPLIB_GAIN_OPT | IRPLIB_LIN_OPT ;
2963 skip_if(detmon_pair_extract_next(set_on, index_on, next_on, exptime_on, &pair_on, detmon_lg_config.tolerance));
2964 current_dit = exptime_on[*next_on - 1];
2967 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2968 skip_if(ons == NULL);
2969 cpl_msg_debug(cpl_func,
" Loaded ON images: %" CPL_SIZE_FORMAT
2970 ", exptime[%f]",cpl_imagelist_get_size(ons), current_dit );
2971 if(cpl_imagelist_get_size(ons) != 2)
2973 cpl_msg_error(cpl_func,
"cannot take ON pair, number of images[%"
2974 CPL_SIZE_FORMAT
"]", cpl_imagelist_get_size(ons));
2977 if(detmon_lg_config.filter > 0)
2980 cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
2981 detmon_lg_config.llx,
2982 detmon_lg_config.lly,
2983 detmon_lg_config.urx,
2984 detmon_lg_config.ury);
2986 cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
2987 detmon_lg_config.llx,
2988 detmon_lg_config.lly,
2989 detmon_lg_config.urx,
2990 detmon_lg_config.ury);
2994 if ( med1 > (
double)detmon_lg_config.filter ||
2995 med2 > (
double)detmon_lg_config.filter)
2998 cpl_table_select_row(gain_table, dit_nb);
2999 cpl_table_select_row(linear_table, dit_nb);
3001 cpl_msg_warning(cpl_func,
"Frames of EXPTIME nb %d "
3002 "will not be taken into account for computation "
3003 "as the median of the on frames computed on the "
3004 "user defined region [%d,%d,%d,%d] are above "
3005 "--filter threshold (%d)",
3007 detmon_lg_config.llx,
3008 detmon_lg_config.lly,
3009 detmon_lg_config.urx,
3010 detmon_lg_config.ury,
3011 detmon_lg_config.filter);
3015 if (follow || detmon_lg_config.filter < 0)
3023 if(!detmon_lg_config.collapse)
3040 if (!strcmp(detmon_lg_config.method,
"MED") ||
3041 cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
3043 skip_if(detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off, detmon_lg_config.tolerance));
3047 skip_if(detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
3050 cpl_msg_debug(cpl_func,
" Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
3051 offs = detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
3053 skip_if(offs == NULL);
3054 skip_if(cpl_error_get_code());
3057 offs = (cpl_imagelist *) opt_offs;
3061 if(detmon_lg_config.rescale)
3063 skip_if(detmon_lg_rescale(ons));
3064 if (!detmon_lg_config.collapse &&
3065 !strcmp(detmon_lg_config.method,
"MED"))
3066 skip_if(detmon_lg_rescale(offs));
3071 cpl_frame_get_filename(cpl_frameset_get_position_const(pair_on, 0));
3072 skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
3076 pDETlist = cpl_propertylist_new();
3077 cpl_propertylist_copy_property_regexp(pDETlist, plist,
"DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
3080 irplib_table_create_column(gain_table, pDETlist);
3081 irplib_table_create_column(linear_table, pDETlist);
3084 if(opt_nir == NIR) {
3085 c_dit = detmon_pfits_get_dit(plist);
3086 c_ndit = irplib_pfits_get_ndit(plist);
3088 c_dit = irplib_pfits_get_exptime(plist);
3100 cpl_msg_info(cpl_func,
"Computing GAIN for EXPTIME value nb %d",
3104 if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
3106 cpl_table_erase_column(gain_table,
"MEAN_OFF1");
3107 cpl_table_erase_column(gain_table,
"MEAN_OFF2");
3108 cpl_table_erase_column(gain_table,
"SIG_OFF_DIF");
3109 cpl_table_erase_column(gain_table,
"GAIN");
3110 cpl_table_erase_column(gain_table,
"GAIN_CORR");
3111 cpl_table_new_column(gain_table,
"MEAN_OFF", CPL_TYPE_DOUBLE);
3115 skip_if(detmon_gain_table_fill_row(gain_table,
3118 diff_flats, ons, offs,
3119 detmon_lg_config.kappa,
3120 detmon_lg_config.niter,
3121 detmon_lg_config.llx,
3122 detmon_lg_config.lly,
3123 detmon_lg_config.urx,
3124 detmon_lg_config.ury,
3127 detmon_lg_config.gain_threshold,
3128 dit_nb, mode, rows_gain_affected));
3131 skip_if(detmon_check_saturation_on_pair(autocorr_images,
3133 detmon_lg_config.kappa,
3134 detmon_lg_config.niter,
3135 detmon_lg_config.llx,
3136 detmon_lg_config.lly,
3137 detmon_lg_config.urx,
3138 detmon_lg_config.ury,
3139 detmon_lg_config.saturation_limit,
3140 dit_nb, mode, rows_linear_affected));
3143 if (*rows_gain_affected)
3146 skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
3148 cpl_msg_info(cpl_func,
"Linearity reduction for nb %d",
3151 if (*rows_linear_affected) {
3152 skip_if(detmon_lin_table_fill_row(linear_table, c_dit,
3153 linearity_inputs, ons, offs,
3154 detmon_lg_config.llx,
3155 detmon_lg_config.lly,
3156 detmon_lg_config.urx,
3157 detmon_lg_config.ury,
3158 dit_nb, *dit_nskip, mode));
3160 skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
3172 if(opt_nir == OPT &&
3173 *rows_linear_affected != 0 ) {
3174 detmon_opt_contamination(ons, offs, mode, qclist);
3181 cpl_frameset_delete(pair_on);
3182 cpl_imagelist_delete(ons);
3184 if(!detmon_lg_config.collapse ) {
3185 cpl_imagelist_delete(offs);
3188 if(!detmon_lg_config.collapse) {
3189 cpl_frameset_delete(pair_off);
3192 cpl_propertylist_delete(plist);
3193 cpl_propertylist_delete(pDETlist);
3194 return cpl_error_get_code();
3204 static cpl_error_code
3205 detmon_add_adl_column(cpl_table * table,
3206 cpl_boolean opt_nir)
3208 cpl_error_code error;
3209 double mean_med_dit;
3212 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
3214 mean_med_dit = cpl_table_get_column_mean(table,
"MED_DIT");
3216 dits = cpl_table_get_data_double(table,
"EXPTIME");
3218 dits = cpl_table_get_data_double(table,
"DIT");
3220 error = cpl_table_copy_data_double(table,
"ADL", dits);
3221 cpl_ensure_code(!error, error);
3222 error = cpl_table_multiply_scalar(table,
"ADL", mean_med_dit);
3223 cpl_ensure_code(!error, error);
3225 return cpl_error_get_code();
3237 static cpl_error_code
3238 detmon_lg_reduce_init(cpl_table * gain_table,
3239 cpl_table * linear_table,
3240 cpl_imagelist ** linearity_inputs,
3241 const cpl_boolean opt_nir)
3243 skip_if(detmon_gain_table_create(gain_table, opt_nir));
3244 skip_if(detmon_lin_table_create(linear_table, opt_nir));
3246 if(detmon_lg_config.pix2pix) {
3247 *linearity_inputs = cpl_imagelist_new();
3248 skip_if(*linearity_inputs == NULL);
3253 return cpl_error_get_code();
3264 detmon_pfits_get_dit(
const cpl_propertylist * plist)
3266 if (cpl_propertylist_has(plist,
"ESO DET DIT")) {
3268 return irplib_pfits_get_prop_double(plist,
"ESO DET DIT");
3271 return irplib_pfits_get_prop_double(plist,
"ESO DET SEQ1 DIT");
3273 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"FITS key "
3274 "ESO DET DIT or ESO DET DIT not found");
3286 detmon_pfits_get_dit_opt(
const cpl_propertylist * plist)
3288 if (cpl_propertylist_has(plist,
"ESO DET WIN1 UIT1")) {
3290 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3291 }
else if (cpl_propertylist_has(plist,
"ESO DET UIT1")) {
3293 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3296 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"FITS key "
3297 "ESO DET WIN1 UIT1 or ESO DET UIT1 not found");
3307 static cpl_propertylist*
3308 detmon_load_pro_keys(
const char* NAME_O)
3310 cpl_propertylist* pro_keys=NULL;
3311 pro_keys=cpl_propertylist_load_regexp(NAME_O,0,
"^(ESO PRO)",0);
3316 static double irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
3317 const char* prop_name)
3320 dit = cpl_propertylist_get_double(plist, prop_name);
3321 if(cpl_error_get_code() != CPL_ERROR_NONE)
3323 cpl_msg_error(cpl_func,
"Cannot read property '%s', err[%s]",
3324 prop_name, cpl_error_get_where());
3329 static cpl_error_code
3330 detmon_gain_compute_qc(
double kappa,
int nclip,
const int pos,
3331 const cpl_imagelist* offs,
unsigned mode,
3332 double avg_on1,
double avg_on2,
3333 double avg_off1,
double avg_off2,
3334 double sig_off_dif,
int c_ndit,
3335 double autocorr, cpl_image* on_dif,
3336 cpl_table* gain_table)
3341 double avg_on_dif, sig_on_dif;
3342 irplib_ksigma_clip(on_dif, 1, 1, cpl_image_get_size_x(on_dif),
3343 cpl_image_get_size_y(on_dif), kappa, nclip, 1e-5,
3344 &avg_on_dif, &sig_on_dif);
3346 cpl_table_set_double(gain_table,
"SIG_ON_DIF", pos,
3348 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3349 double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
3352 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
3355 = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
3359 const double gain = double_adu / (c_ndit * sigma);
3361 const double gain_corr = gain / (autocorr);
3363 skip_if(cpl_table_set_double(gain_table,
"GAIN", pos, gain));
3365 cpl_table_set_double(gain_table,
"GAIN_CORR", pos,
3369 skip_if(cpl_table_set_double(gain_table,
"AUTOCORR", pos, autocorr));
3370 skip_if(cpl_table_set_double(gain_table,
"ADU", pos, double_adu / 2));
3373 cpl_table_set_double(gain_table,
"Y_FIT", pos,
3374 c_ndit * sig_on_dif * sig_on_dif));
3376 cpl_table_set_double(gain_table,
"Y_FIT_CORR", pos,
3377 c_ndit * sig_on_dif * sig_on_dif));
3378 skip_if(cpl_table_set_double(gain_table,
"X_FIT", pos, double_adu));
3380 cpl_table_set_double(gain_table,
"X_FIT_CORR", pos,
3381 double_adu / autocorr));
3385 return cpl_error_get_code();
3389 detmon_gain_prepare_autocorr(
unsigned mode,
const int pos,
3390 int m,
int n, cpl_imagelist* diff_flats,
3391 cpl_image* on_dif, cpl_imagelist* autocorr_images)
3393 double autocorr = 1.0;
3395 if (mode & IRPLIB_GAIN_WITH_AUTOCORR) {
3397 cpl_image * diff = cpl_image_duplicate(on_dif);
3398 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
3400 if (autocorr_images) {
3401 cpl_image * corr = NULL;
3402 autocorr = detmon_autocorr_factor(on_dif, &corr, m, n);
3404 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
3407 detmon_lg_add_empty_image(autocorr_images, pos);
3411 autocorr = detmon_autocorr_factor(on_dif, NULL, m, n);
3413 autocorr = isnan(autocorr) ? 1.0 : autocorr;
3421 detmon_gain_prepare_table(
const cpl_imagelist* offs,
unsigned mode,
int llx,
3422 int lly,
int urx,
int ury,
double kappa,
int nclip,
3423 double std,
const int pos,
3424 cpl_table* gain_table,
double* avg_off2,
3425 double* sig_off_dif)
3427 double avg_off1 = 0.0;
3434 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3437 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3438 llx, lly, urx, ury, kappa, nclip, 1e-5,
3440 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF", pos, avg_off1));
3443 else if ((mode & IRPLIB_GAIN_NO_COLLAPSE)
3444 || (pos == 0 && mode & IRPLIB_GAIN_COLLAPSE)) {
3445 cpl_image * off_dif = NULL;
3448 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3449 llx, lly, urx, ury, kappa, nclip, 1e-5,
3451 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3453 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 1),
3454 llx, lly, urx, ury, kappa, nclip, 1e-5,
3456 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3457 off_dif = detmon_subtract_create_window(
3458 cpl_imagelist_get_const(offs, 0),
3459 cpl_imagelist_get_const(offs, 1), llx, lly, urx, ury);
3460 skip_if(off_dif == NULL);
3461 irplib_ksigma_clip(off_dif, 1, 1, cpl_image_get_size_x(off_dif),
3462 cpl_image_get_size_y(off_dif), kappa, nclip, 1e-5,
3463 &avg_off_dif, sig_off_dif);
3464 cpl_image_delete(off_dif);
3466 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3469 else if (pos > 0 && (mode & IRPLIB_GAIN_COLLAPSE)) {
3472 avg_off1 = cpl_table_get_double(gain_table,
"MEAN_OFF1", 0, &status);
3473 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3474 *avg_off2 = cpl_table_get_double(gain_table,
"MEAN_OFF2", 0, &status);
3475 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3476 *sig_off_dif = cpl_table_get_double(gain_table,
"SIG_OFF_DIF", 0,
3479 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3524 static cpl_error_code
3525 detmon_gain_table_fill_row(cpl_table * gain_table,
3526 double c_dit,
int c_ndit,
3527 cpl_imagelist * autocorr_images,
3528 cpl_imagelist * diff_flats,
3529 const cpl_imagelist * ons,
3530 const cpl_imagelist * offs,
3531 double kappa,
int nclip,
3532 int llx,
int lly,
int urx,
int ury,
3534 double gain_threshold,
3535 int pos,
unsigned mode,
int* rows_gain_affected)
3537 const cpl_image *image;
3538 cpl_image *on_dif = NULL;
3540 double avg_on1, avg_on2;
3541 double avg_off1, avg_off2;
3544 cpl_table_set(gain_table,
"FLAG", pos, 1);
3545 if (mode & IRPLIB_GAIN_NIR)
3547 cpl_table_set(gain_table,
"DIT", pos, c_dit);
3548 cpl_table_set(gain_table,
"NDIT", pos, c_ndit);
3549 }
else if (mode & IRPLIB_GAIN_OPT)
3551 cpl_table_set(gain_table,
"EXPTIME", pos, c_dit);
3554 cpl_msg_error(cpl_func,
"Mandatory mode (OPT or NIR) not provided");
3557 if(*rows_gain_affected == 0)
3559 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3560 cpl_table_set(gain_table,
"FLAG", pos, 0);
3561 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3566 detmon_lg_add_empty_image(diff_flats, pos);
3568 if (autocorr_images)
3570 detmon_lg_add_empty_image(autocorr_images, pos);
3573 return cpl_error_get_code();
3575 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3576 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3577 nclip, 1e-5, &avg_on1, &std));
3578 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3579 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3580 nclip, 1e-5, &avg_on2, &std));
3583 (avg_on1 > gain_threshold) ||
3584 (avg_on2 > gain_threshold)
3590 if ( (avg_on1 > gain_threshold) || (avg_on2 > gain_threshold) )
3592 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the gain_theshold parameter, "
3593 "the frames would not be taken into calculation");
3595 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3596 avg_on1, avg_on2, gain_threshold);
3599 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3600 cpl_table_set(gain_table,
"FLAG", pos, 0);
3601 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3606 detmon_lg_add_empty_image(diff_flats, pos);
3608 if (autocorr_images)
3610 detmon_lg_add_empty_image(autocorr_images, pos);
3613 *rows_gain_affected = 0;
3621 *rows_gain_affected = 1;
3622 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON1", pos, avg_on1));
3623 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON2", pos, avg_on2));
3626 detmon_subtract_create_window(cpl_imagelist_get_const(ons, 0),
3627 cpl_imagelist_get_const(ons, 1),
3628 llx, lly, urx, ury);
3629 skip_if(on_dif == NULL);
3631 autocorr = detmon_gain_prepare_autocorr(mode, pos, m, n,
3632 diff_flats, on_dif, autocorr_images);
3634 avg_off1 = detmon_gain_prepare_table(offs, mode, llx, lly, urx, ury,
3635 kappa, nclip, std, pos, gain_table, &avg_off2,
3638 detmon_gain_compute_qc(kappa, nclip, pos, offs, mode,
3639 avg_on1, avg_on2, avg_off1, avg_off2,
3640 sig_off_dif, c_ndit, autocorr, on_dif,
3645 cpl_image_delete(on_dif);
3647 return cpl_error_get_code();
3674 static cpl_error_code
3675 detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
3676 cpl_imagelist * diff_flats,
3677 const cpl_imagelist * ons,
3678 double kappa,
int nclip,
3679 int llx,
int lly,
int urx,
int ury,
3680 double saturation_limit,
3681 const int pos,
unsigned mode,
int* rows_linear_affected)
3683 const cpl_image *image;
3685 double avg_on1, avg_on2;
3688 if(*rows_linear_affected == 0)
3690 cpl_msg_info(cpl_func,
"For linearity skip the frame #%d", pos + 1);
3691 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3695 detmon_lg_add_empty_image(diff_flats, pos);
3697 if (autocorr_images)
3699 detmon_lg_add_empty_image(autocorr_images, pos);
3702 return cpl_error_get_code();
3704 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3705 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3706 nclip, 1e-5, &avg_on1, &std));
3707 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3708 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3709 nclip, 1e-5, &avg_on2, &std));
3712 (avg_on1 > saturation_limit) ||
3713 (avg_on2 > saturation_limit)
3719 if ( (avg_on1 > saturation_limit) || (avg_on2 > saturation_limit) )
3721 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the saturation_limit parameter, "
3722 "the frames would not be taken into calculation");
3724 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3725 avg_on1, avg_on2, saturation_limit);
3728 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3729 *rows_linear_affected = 0;
3736 return cpl_error_get_code();
3752 detmon_bpixs(
const cpl_imagelist * coeffs,
3759 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
3766 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
3767 cpl_image_get_size_y(first));
3769 cpl_image *bpm = NULL;
3772 int size = cpl_imagelist_get_size(coeffs);
3775 bpm = cpl_image_new(cpl_image_get_size_x(first),
3776 cpl_image_get_size_y(first),
3781 for(
int i = 0; i < size; i++) {
3782 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
3784 cpl_stats* stats = cpl_stats_new_from_image(cur_coeff,
3785 CPL_STATS_MEAN | CPL_STATS_STDEV);
3786 double cur_mean = cpl_stats_get_mean(stats);
3787 double cur_stdev = cpl_stats_get_stdev(stats);
3789 double lo_cut = cur_mean - kappa * cur_stdev;
3790 double hi_cut = cur_mean + kappa * cur_stdev;
3792 cpl_mask* cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
3793 cpl_mask_not(cur_mask);
3796 cpl_image* cur_image = cpl_image_new_from_mask(cur_mask);
3797 double p = pow(2, i);
3798 cpl_image_power(cur_image, p);
3799 cpl_image_add(bpm, cur_image);
3800 cpl_image_delete(cur_image);
3803 cpl_mask_or(mask, cur_mask);
3805 cpl_mask_delete(cur_mask);
3806 cpl_stats_delete(stats);
3810 bpm = cpl_image_new_from_mask(mask);
3813 *nbpixs = cpl_mask_count(mask);
3815 cpl_mask_delete(mask);
3942 detmon_autocorr_factor(
const cpl_image * image,
3943 cpl_image ** autocorr_image,
int m,
int n)
3945 cpl_image * mycorr_image = NULL;
3946 double autocorr = 0;
3949 mycorr_image = detmon_image_correlate(image, image, m, n);
3951 if (cpl_error_get_code() == CPL_ERROR_UNSUPPORTED_MODE)
3953 cpl_msg_warning(cpl_func,
"FFTW is not supported by CPL, autocorrelation "
3954 "would be computed using internal implementation");
3957 cpl_image_delete(mycorr_image);
3958 mycorr_image = detmon_autocorrelate(image, m, n);
3960 if(mycorr_image == NULL) {
3964 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
3966 autocorr = cpl_image_get_flux(mycorr_image);
3968 if (autocorr_image) *autocorr_image = mycorr_image;
3969 else cpl_image_delete(mycorr_image);
3974 static cpl_propertylist*
3975 detmon_lg_extract_qclist_4plane(cpl_propertylist* linc_qclist,
const int ip)
3978 cpl_propertylist* sub_set=NULL;
3981 sub_set=cpl_propertylist_new();
3982 qc_key=cpl_sprintf(
"QC LIN COEF%d",ip);
3983 cpl_propertylist_copy_property_regexp(sub_set,linc_qclist,qc_key,0);
4000 static cpl_error_code
4001 detmon_lg_extract_extention_header(cpl_frameset* frameset,
4002 cpl_propertylist* gaint_qclist,
4003 cpl_propertylist* lint_qclist,
4004 cpl_propertylist* linc_qclist,
4005 cpl_propertylist* bpm_qclist,
4009 cpl_propertylist * xplist = NULL;
4011 const char * filename =
4012 cpl_frame_get_filename(cpl_frameset_get_position(frameset, 0));
4014 xplist = cpl_propertylist_load_regexp(filename, whichext,
4015 "ESO DET|EXTNAME", 0);
4016 if (detmon_lg_config.exts >= 0)
4019 cpl_property* propExtname = NULL;
4020 propExtname = cpl_propertylist_get_property(xplist,
"EXTNAME");
4022 if (NULL != propExtname)
4024 propExtname = cpl_property_duplicate(propExtname);
4026 cpl_propertylist_delete(xplist);
4028 if (NULL != propExtname)
4030 xplist = cpl_propertylist_new();
4031 cpl_propertylist_append_property(xplist, propExtname);
4032 cpl_property_delete(propExtname);
4037 cpl_propertylist_append(gaint_qclist, xplist);
4038 cpl_propertylist_append(lint_qclist, xplist);
4039 cpl_propertylist_append(linc_qclist, xplist);
4040 cpl_propertylist_append(bpm_qclist, xplist);
4041 cpl_propertylist_delete(xplist);
4044 return cpl_error_get_code();
4061 static cpl_error_code
4062 detmon_lg_save_table_with_pro_keys(cpl_table* table,
4064 cpl_propertylist* xheader,
4065 unsigned CPL_IO_MODE)
4068 cpl_propertylist* pro_keys=NULL;
4070 pro_keys=detmon_load_pro_keys(name_o);
4071 cpl_propertylist_append(xheader,pro_keys);
4073 if(CPL_IO_MODE==CPL_IO_DEFAULT) {
4074 cpl_propertylist * pri_head=cpl_propertylist_load(name_o,0);
4075 cpl_table_save(table, pri_head,xheader,name_o,
4077 cpl_propertylist_delete(pri_head);
4080 cpl_table_save(table,NULL,xheader,name_o,
4083 cpl_propertylist_delete(pro_keys);
4085 return cpl_error_get_code();
4097 static cpl_error_code
4098 detmon_lg_save_image_with_pro_keys(cpl_image* image,
4100 cpl_propertylist* xheader)
4103 cpl_propertylist* pro_keys=NULL;
4104 pro_keys=detmon_load_pro_keys(name_o);
4105 cpl_propertylist_append(xheader,pro_keys);
4107 cpl_image_save(image,name_o, CPL_BPP_IEEE_FLOAT,
4108 xheader,CPL_IO_EXTEND);
4109 cpl_propertylist_delete(pro_keys);
4112 return cpl_error_get_code();
4124 static cpl_error_code
4125 detmon_lg_save_imagelist_with_pro_keys(cpl_imagelist* imagelist,
4127 cpl_propertylist* xheader)
4130 cpl_propertylist* pro_keys=NULL;
4131 pro_keys=detmon_load_pro_keys(name_o);
4132 cpl_propertylist_append(xheader,pro_keys);
4134 cpl_imagelist_save(imagelist,name_o, CPL_BPP_IEEE_FLOAT,
4135 xheader,CPL_IO_EXTEND);
4137 cpl_propertylist_delete(pro_keys);
4140 return cpl_error_get_code();
4160 static cpl_error_code
4161 detmon_lg_save_plane(
const cpl_parameterlist * parlist,
4162 cpl_frameset* frameset,
4163 const cpl_frameset * usedframes,
4165 const char* recipe_name,
4166 cpl_propertylist* mypro_coeffscube,
4167 cpl_propertylist* linc_plane_qclist,
4168 const char* package,
4172 if(detmon_lg_config.exts == 0) {
4173 cpl_propertylist* plist=NULL;
4174 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4176 CPL_BPP_IEEE_FLOAT, recipe_name,
4177 mypro_coeffscube, NULL,
4179 plist=cpl_propertylist_load(NAME_O,0);
4180 cpl_image_save(plane,NAME_O, CPL_BPP_IEEE_FLOAT,
4181 plist,CPL_IO_DEFAULT);
4182 cpl_propertylist_delete(plist);
4184 }
else if(detmon_lg_config.exts > 0) {
4185 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4187 CPL_BPP_IEEE_FLOAT, recipe_name,
4188 mypro_coeffscube, NULL,
4191 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4195 cpl_dfs_save_image(frameset, NULL, parlist,
4196 usedframes,NULL, NULL,
4197 CPL_BPP_IEEE_FLOAT, recipe_name,
4198 mypro_coeffscube, NULL,
4200 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4203 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4209 return cpl_error_get_code();
4232 static cpl_error_code
4233 detmon_lg_save_cube(
const cpl_parameterlist * parlist,
4234 cpl_frameset* frameset,
4235 const cpl_frameset * usedframes,
4237 const char* recipe_name,
4238 cpl_propertylist* mypro_coeffscube,
4239 cpl_propertylist* linc_qclist,
4240 const char* package,
4242 cpl_imagelist* coeffs)
4245 if(detmon_lg_config.exts == 0) {
4246 cpl_propertylist_append(mypro_coeffscube, linc_qclist);
4247 detmon_lg_dfs_save_imagelist
4248 (frameset, parlist, usedframes, coeffs,
4249 recipe_name, mypro_coeffscube, package,
4251 }
else if(detmon_lg_config.exts > 0) {
4252 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4254 CPL_BPP_IEEE_FLOAT, recipe_name,
4255 mypro_coeffscube, NULL,
4258 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4262 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4264 CPL_BPP_IEEE_FLOAT, recipe_name,
4265 mypro_coeffscube, NULL,
4268 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4270 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4273 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4275 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4279 return cpl_error_get_code();
4283 detmon_lg_set_paf_name_and_header(cpl_frame* ref_frame,
4284 int flag_sets,
int which_set,
4286 const char* paf_suf,
4287 cpl_propertylist** plist)
4289 char * paf_name=NULL;
4291 if(detmon_lg_config.exts >= 0)
4293 *plist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4294 detmon_lg_config.exts);
4298 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4302 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4303 detmon_lg_config.pafname, paf_suf,which_set);
4308 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4314 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4315 detmon_lg_config.pafname, paf_suf,whichext);
4319 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4320 detmon_lg_config.pafname,paf_suf,
4321 which_set, whichext);
4330 detmon_lg_set_paf_name_and_header_ext(cpl_frame* ref_frame,
4331 int flag_sets,
int which_set,
4333 const char* paf_suf,
4334 cpl_propertylist** plist)
4336 char* paf_name=NULL;
4338 if(detmon_lg_config.exts >= 0)
4340 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4341 detmon_lg_config.exts);
4345 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4348 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4349 detmon_lg_config.pafname, paf_suf,which_set);
4353 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4357 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4358 detmon_lg_config.pafname, paf_suf,whichext);
4361 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4362 detmon_lg_config.pafname,paf_suf,
4363 which_set, whichext);
4370 static cpl_error_code
4371 detmon_lg_save_paf_product(cpl_frame* ref_frame,
int flag_sets,
4372 int which_set,
int whichext,
4373 const char* pafregexp,
4374 const char* procatg,
4375 const char* pipeline_name,
4376 const char* recipe_name,
4377 const char* paf_suf,
4378 cpl_propertylist* qclist,
4383 char* paf_name=NULL;
4384 cpl_propertylist* plist=NULL;
4385 cpl_propertylist* paflist = NULL;
4386 cpl_propertylist* mainplist=NULL;
4388 mainplist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0);
4390 paf_name=detmon_lg_set_paf_name_and_header(ref_frame,flag_sets,
4394 paf_name=detmon_lg_set_paf_name_and_header_ext(ref_frame,flag_sets,
4400 paflist = cpl_propertylist_new();
4401 cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,procatg);
4404 cpl_propertylist_copy_property_regexp(paflist, plist,pafregexp, 0);
4405 cpl_propertylist_copy_property_regexp(paflist, mainplist,pafregexp, 0);
4406 cpl_propertylist_append(paflist,qclist);
4409 cpl_dfs_save_paf(pipeline_name, recipe_name,paflist,paf_name);
4412 cpl_propertylist_delete(mainplist);
4413 cpl_propertylist_delete(paflist);
4414 cpl_propertylist_delete(plist);
4417 return cpl_error_get_code();
4454 static cpl_error_code
4455 detmon_lg_save(
const cpl_parameterlist * parlist,
4456 cpl_frameset * frameset,
4457 const char *recipe_name,
4458 const char *pipeline_name,
4459 const char *pafregexp,
4460 const cpl_propertylist * pro_lintbl,
4461 const cpl_propertylist * pro_gaintbl,
4462 const cpl_propertylist * pro_coeffscube,
4463 const cpl_propertylist * pro_bpm,
4464 const cpl_propertylist * pro_corr,
4465 const cpl_propertylist * pro_diff,
4466 const char *package,
4467 cpl_imagelist * coeffs,
4468 cpl_table * gain_table,
4469 cpl_table * linear_table,
4471 cpl_imagelist * autocorr_images,
4472 cpl_imagelist * diff_flats,
4473 cpl_propertylist * gaint_qclist,
4474 cpl_propertylist * lint_qclist,
4475 cpl_propertylist * linc_qclist,
4476 cpl_propertylist * bpm_qclist,
4477 const int flag_sets,
4478 const int which_set,
4479 const cpl_frameset * usedframes,
4483 cpl_frame *ref_frame;
4484 cpl_propertylist *plist = NULL;
4485 cpl_propertylist *mainplist = NULL;
4491 cpl_propertylist * xplist = NULL;
4493 cpl_propertylist* linc_plane_qclist=NULL;
4494 cpl_image* plane=NULL;
4496 char* pcatg_plane=NULL;
4498 cpl_propertylist * mypro_lintbl =
4499 cpl_propertylist_duplicate(pro_lintbl);
4500 cpl_propertylist * mypro_gaintbl =
4501 cpl_propertylist_duplicate(pro_gaintbl);
4502 cpl_propertylist * mypro_coeffscube =
4503 cpl_propertylist_duplicate(pro_coeffscube);
4504 cpl_propertylist * mypro_bpm =
4505 cpl_propertylist_duplicate(pro_bpm);
4506 cpl_propertylist * mypro_corr =
4507 cpl_propertylist_duplicate(pro_corr);
4508 cpl_propertylist * mypro_diff =
4509 cpl_propertylist_duplicate(pro_diff);
4511 const char * procatg_lintbl =
4512 cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
4514 const char * procatg_gaintbl =
4515 cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
4517 const char * procatg_coeffscube =
4518 cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
4519 const char * procatg_bpm =
4520 cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
4524 detmon_lg_extract_extention_header(frameset,gaint_qclist,lint_qclist,
4525 linc_qclist,bpm_qclist,whichext);
4530 ref_frame = cpl_frameset_get_position(frameset, 0);
4532 skip_if((mainplist =
4533 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4539 cpl_msg_info(cpl_func,
"Write the LINEARITY TABLE");
4542 NAME_O=cpl_sprintf(
"%s_linearity_table.fits", recipe_name);
4544 NAME_O=cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name,
4548 if (detmon_lg_config.exts >= 0) {
4550 cpl_propertylist_append(mypro_lintbl, lint_qclist);
4551 skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,
4552 linear_table,NULL, recipe_name,
4553 mypro_lintbl, NULL, package, NAME_O));
4555 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4556 lint_qclist,CPL_IO_DEFAULT);
4561 skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL,
4562 linear_table,lint_qclist, recipe_name,
4563 mypro_lintbl,NULL, package, NAME_O));
4564 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4565 lint_qclist,CPL_IO_DEFAULT);
4572 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4573 lint_qclist,CPL_IO_EXTEND);
4576 irplib_free(&NAME_O);
4580 cpl_msg_info(cpl_func,
"Write the GAIN TABLE");
4583 NAME_O=cpl_sprintf(
"%s_gain_table.fits", recipe_name);
4585 NAME_O=cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name,
4589 if (detmon_lg_config.exts >= 0)
4593 cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
4594 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
4595 gain_table,NULL, recipe_name, mypro_gaintbl,
4596 NULL, package, NAME_O));
4597 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4598 gaint_qclist,CPL_IO_DEFAULT);
4606 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
4607 gaint_qclist, recipe_name, mypro_gaintbl,
4608 NULL, package, NAME_O));
4609 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4610 gaint_qclist,CPL_IO_DEFAULT);
4616 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4617 gaint_qclist,CPL_IO_EXTEND);
4621 if(detmon_lg_config.pix2pix)
4627 cpl_msg_info(cpl_func,
"Write the COEFFS FITS");
4628 irplib_free(&NAME_O);
4631 PREF_O=cpl_sprintf(
"%s_coeffs_cube", recipe_name);
4634 PREF_O=cpl_sprintf(
"%s_coeffs_cube_set%02d",
4635 recipe_name, which_set);
4637 if (detmon_lg_config.split_coeffs == 0) {
4638 NAME_O=cpl_sprintf(
"%s.fits", PREF_O);
4643 if(detmon_lg_config.split_coeffs != 0){
4646 nb_images = cpl_imagelist_get_size(coeffs);
4647 for(ip=0;ip<nb_images;ip++) {
4648 NAME_O=cpl_sprintf(
"%s_P%d.fits", PREF_O,ip);
4649 pcatg_plane=cpl_sprintf(
"COEFFS_CUBE_P%d",ip);
4650 cpl_propertylist_delete(mypro_coeffscube);
4651 mypro_coeffscube=cpl_propertylist_duplicate(pro_coeffscube);
4652 cpl_propertylist_set_string(mypro_coeffscube,CPL_DFS_PRO_CATG,
4654 linc_plane_qclist=detmon_lg_extract_qclist_4plane(linc_qclist,ip);
4655 cpl_propertylist_append(mypro_coeffscube, linc_plane_qclist);
4656 plane=cpl_imagelist_get(coeffs,ip);
4657 detmon_lg_save_plane(parlist,frameset,usedframes,whichext,
4658 recipe_name,mypro_coeffscube,
4659 linc_plane_qclist,package,NAME_O,plane);
4661 if(NULL!=linc_plane_qclist) {
4662 cpl_propertylist_delete(linc_plane_qclist);
4664 irplib_free(&NAME_O);
4669 detmon_lg_save_cube(parlist,frameset,usedframes,whichext,
4670 recipe_name,mypro_coeffscube,
4671 linc_qclist,package,NAME_O,coeffs);
4677 cpl_msg_info(cpl_func,
"Write the BAD PIXEL MAP");
4678 irplib_free(&NAME_O);
4682 NAME_O=cpl_sprintf(
"%s_bpm.fits", recipe_name);
4685 NAME_O=cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, which_set);
4690 if(detmon_lg_config.exts == 0) {
4691 cpl_propertylist_append(mypro_bpm, bpm_qclist);
4692 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
4693 CPL_BPP_IEEE_FLOAT, recipe_name,
4694 mypro_bpm, NULL, package,
4697 else if(detmon_lg_config.exts > 0)
4699 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4700 CPL_BPP_IEEE_FLOAT, recipe_name,
4701 mypro_bpm, NULL, package,
4703 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4709 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4710 CPL_BPP_IEEE_FLOAT, recipe_name,
4711 mypro_bpm, NULL, package,
4713 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4716 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4721 if(detmon_lg_config.intermediate)
4726 cpl_msg_info(cpl_func,
"Write the AUTOCORRS FITS");
4727 nb_images = cpl_imagelist_get_size(autocorr_images);
4728 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
4729 for(i = 0; i < nb_images; i++)
4731 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_corr);
4733 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4735 if(i < cpl_table_get_nrow(linear_table))
4737 ddit = cpl_table_get_double(linear_table,
4738 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4740 cpl_array_delete(pnames);
4743 irplib_free(&NAME_O);
4746 NAME_O=cpl_sprintf(
"%s_autocorr_%d.fits", recipe_name, i);
4747 assert(NAME_O != NULL);
4750 NAME_O=cpl_sprintf(
"%s_autocorr_%02d_set%02d.fits",
4751 recipe_name, i, which_set);
4752 assert(NAME_O != NULL);
4755 if(detmon_lg_config.exts > 0)
4757 cpl_propertylist* pextlist = cpl_propertylist_new();
4758 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4759 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4760 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4761 recipe_name, pplist, NULL,
4764 detmon_lg_save_image_with_pro_keys(
4765 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4767 cpl_propertylist_delete(pextlist);
4769 if(detmon_lg_config.exts == 0)
4771 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4772 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
4773 cpl_imagelist_get(autocorr_images, i),
4775 recipe_name, pplist, NULL, package,
4781 cpl_propertylist* pextlist = cpl_propertylist_new();
4782 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4785 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4786 usedframes, NULL,NULL,
4787 CPL_BPP_IEEE_FLOAT, recipe_name,
4791 detmon_lg_save_image_with_pro_keys(
4792 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4797 detmon_lg_save_image_with_pro_keys(
4798 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4800 cpl_propertylist_delete(pextlist);
4802 cpl_propertylist_delete (pplist);
4804 irplib_free(&NAME_O);
4813 cpl_msg_info(cpl_func,
"Write the DIFFS FITS");
4815 for(i = 0; i < nb_images; i++)
4817 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_diff);
4819 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4821 if(i < cpl_table_get_nrow(linear_table))
4823 ddit = cpl_table_get_double(linear_table,
4824 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4826 cpl_array_delete(pnames);
4831 NAME_O=cpl_sprintf(
"%s_diff_flat_%d.fits", recipe_name, i);
4834 NAME_O=cpl_sprintf(
"%s_diff_flat_%d_set%02d.fits",
4835 recipe_name, i, which_set);
4838 if(detmon_lg_config.exts > 0)
4840 cpl_propertylist* pextlist = cpl_propertylist_new();
4841 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4842 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT", ddit);
4843 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4844 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4846 mypro_diff, NULL,package, NAME_O));
4848 detmon_lg_save_image_with_pro_keys(
4849 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4851 cpl_propertylist_delete(pextlist);
4853 else if(detmon_lg_config.exts == 0)
4855 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4857 (frameset, NULL, parlist, usedframes, NULL,
4858 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
4859 recipe_name, pplist, NULL, package,
4864 cpl_propertylist* pextlist = cpl_propertylist_new();
4865 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4868 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT",ddit);
4870 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4871 usedframes, NULL,NULL,
4872 CPL_BPP_IEEE_FLOAT, recipe_name,
4873 mypro_diff, NULL,package, NAME_O));
4875 detmon_lg_save_image_with_pro_keys(
4876 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4881 detmon_lg_save_image_with_pro_keys(
4882 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4885 cpl_propertylist_delete(pextlist);
4887 cpl_propertylist_delete(pplist);
4888 irplib_free(&NAME_O);
4896 cpl_msg_info(cpl_func,
"Write the PAF file(s)");
4898 if(detmon_lg_config.pafgen) {
4900 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4901 pafregexp,procatg_gaintbl,
4902 pipeline_name,recipe_name,
4903 "qc01",gaint_qclist,0);
4905 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4906 pafregexp,procatg_lintbl,
4907 pipeline_name,recipe_name,
4908 "qc02",lint_qclist,0);
4910 if(detmon_lg_config.pix2pix)
4913 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4916 pipeline_name,recipe_name,
4917 "qc03",linc_qclist,1);
4919 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4920 whichext,pafregexp,procatg_bpm,
4921 pipeline_name,recipe_name,
4922 "qc04",bpm_qclist,1);
4927 cpl_msg_info(cpl_func,
"exit");
4929 cpl_propertylist_delete(xplist);
4931 cpl_propertylist_delete(plist);
4935 irplib_free(&NAME_O);
4937 cpl_free(pcatg_plane);
4938 cpl_propertylist_delete(mainplist);
4939 cpl_propertylist_delete(mypro_lintbl);
4940 cpl_propertylist_delete(mypro_gaintbl);
4941 cpl_propertylist_delete(mypro_coeffscube);
4942 cpl_propertylist_delete(mypro_bpm);
4943 cpl_propertylist_delete(mypro_corr);
4944 cpl_propertylist_delete(mypro_diff);
4946 return cpl_error_get_code();
4959 static cpl_error_code
4960 detmon_opt_contamination(
const cpl_imagelist * ons,
4961 const cpl_imagelist * offs,
4963 cpl_propertylist * qclist)
4971 struct rect rects[5] = {
4972 (
struct rect){ detmon_lg_config.llx1,
4973 detmon_lg_config.lly1,
4974 detmon_lg_config.urx1,
4975 detmon_lg_config.ury1},
4976 (
struct rect){ detmon_lg_config.llx2,
4977 detmon_lg_config.lly2,
4978 detmon_lg_config.urx2,
4979 detmon_lg_config.ury2},
4980 (
struct rect){ detmon_lg_config.llx3,
4981 detmon_lg_config.lly3,
4982 detmon_lg_config.urx3,
4983 detmon_lg_config.ury3},
4984 (
struct rect){ detmon_lg_config.llx4,
4985 detmon_lg_config.lly4,
4986 detmon_lg_config.urx4,
4987 detmon_lg_config.ury4},
4988 (
struct rect){ detmon_lg_config.llx5,
4989 detmon_lg_config.lly5,
4990 detmon_lg_config.urx5,
4991 detmon_lg_config.ury5},
4994 for (
size_t i = 0; i < 5; i++) {
4995 cpl_image * dif_avg;
4996 const cpl_image * off2;
4999 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
5000 off2 = cpl_imagelist_get_const(offs, 0);
5002 off2 = cpl_imagelist_get_const(offs, 1);
5004 dif_avg = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
5005 cpl_imagelist_get_const(offs, 0),
5006 cpl_imagelist_get_const(ons, 1),
5013 median = cpl_image_get_median(dif_avg);
5014 cpl_image_delete(dif_avg);
5017 sprintf(kname, DETMON_QC_CONTAM
"%zd", i + 1);
5019 if(cpl_propertylist_has(qclist,kname)){
5020 skip_if(cpl_propertylist_update_double(qclist,kname,median));
5022 skip_if(cpl_propertylist_append_double(qclist,kname,median));
5023 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
5029 return cpl_error_get_code();
5088 detmon_lg_dfs_set_groups(cpl_frameset * set,
5089 const char *tag_on,
const char *tag_off)
5101 int nframes = cpl_frameset_get_size(set);
5104 for(
int i = 0; i < nframes; i++) {
5105 cpl_frame* cur_frame = cpl_frameset_get_position(set, i);
5106 const char* tag = cpl_frame_get_tag(cur_frame);
5109 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
5110 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
5130 static cpl_error_code
5131 detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist ** coeffs_ptr,
5132 cpl_image **bpms_ptr)
5148 cpl_image* dummy_bpm = cpl_image_new(detmon_lg_config.nx,
5149 detmon_lg_config.ny,
5151 cpl_imagelist* dummy_coeffs = cpl_imagelist_new();
5153 int* db_p = cpl_image_get_data_int(dummy_bpm);
5154 int* rb_p = cpl_image_get_data_int(*bpms_ptr);;
5155 float** dcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5156 float** rcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5157 int dlength = detmon_lg_config.nx;
5159 int rlength = detmon_lg_config.urx - detmon_lg_config.llx + 1;
5160 for (
int i = 0; i <= detmon_lg_config.order; i++)
5162 cpl_image* dummy_coeff = cpl_image_new(detmon_lg_config.nx,
5163 detmon_lg_config.ny,
5166 cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
5167 dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
5168 rcs_p[i] = cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
5171 for (
int i = detmon_lg_config.lly - 1; i < detmon_lg_config.ury; i++)
5173 for (
int j = detmon_lg_config.llx - 1; j < detmon_lg_config.urx; j++)
5175 shift_idx=(i - detmon_lg_config.lly + 1) * rlength +
5176 j - detmon_lg_config.llx + 1;
5177 *(db_p + i * dlength + j) = *(rb_p + shift_idx);
5178 for (
int k = 0; k <= detmon_lg_config.order; k++)
5180 *(dcs_p[k] + i * dlength + j) =
5181 *(rcs_p[k] + (i - detmon_lg_config.lly + 1) * rlength +
5182 j - detmon_lg_config.llx + 1);
5186 cpl_imagelist_delete(*coeffs_ptr);
5187 cpl_image_delete(*bpms_ptr);
5188 *coeffs_ptr = dummy_coeffs;
5189 *bpms_ptr = dummy_bpm;
5193 return cpl_error_get_code();
5230 #ifdef DETMON_USE_DETECTOR_SHOTNOISE_MODEL
5253 static cpl_error_code
5254 detmon_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
5255 const double ron, cpl_image ** ima_errs)
5257 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
5258 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
5259 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
5260 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
5262 *ima_errs = cpl_image_duplicate(ima_data);
5264 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
5268 cpl_image_divide_scalar(*ima_errs, gain);
5269 cpl_image_add_scalar(*ima_errs, ron * ron);
5270 cpl_image_power(*ima_errs, 0.5);
5272 return cpl_error_get_code();
5277 detmon_compute_badpixmap(cpl_boolean opt_nir,
const int nsets,
5278 const cpl_table* linear_table,
5279 const cpl_imagelist* linearity_inputs,
int nbpixs,
5280 cpl_vector* x, cpl_propertylist* gaint_qclist,
5281 cpl_image** bpms_ptr)
5287 if (opt_nir == NIR) {
5288 x = cpl_vector_wrap(nsets,
5289 (
double *) cpl_table_get_data_double_const(linear_table,
5293 x = cpl_vector_wrap(nsets,
5294 (
double *) cpl_table_get_data_double_const(linear_table,
5298 int sz = cpl_imagelist_get_size(linearity_inputs);
5299 double kappa = detmon_lg_config.kappa;
5300 int niter = detmon_lg_config.niter;
5301 int llx = detmon_lg_config.llx;
5302 int urx = detmon_lg_config.urx;
5303 int lly = detmon_lg_config.lly;
5304 int ury = detmon_lg_config.ury;
5306 const cpl_image *ima;
5310 cpl_imagelist* errors = cpl_imagelist_new();
5332 cpl_imagelist* linearity_scaled = cpl_imagelist_new();
5334 gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
5338 gain = (gain < 0) ? 1 : gain;
5344 for (
int i = 0; i < sz; i++) {
5345 ima = cpl_imagelist_get_const(linearity_inputs, i);
5353 irplib_ksigma_clip(ima, 1, 1, urx - llx + 1,
5354 ury - lly + 1, kappa, niter, 1e-5, &avg,
5359 if (avg < detmon_lg_config.saturation_limit) {
5367 cpl_image_get_mad(ima, &dmad);
5368 err = cpl_image_duplicate(ima);
5369 cpl_image_multiply_scalar(err, 0);
5370 cpl_image_add_scalar(err, dmad * CPL_MATH_STD_MAD);
5380 cpl_imagelist_set(errors, err, i);
5388 cpl_imagelist_set(linearity_scaled,
5389 cpl_image_duplicate(ima), i));
5392 hdrl_imagelist* hil = hdrl_imagelist_create(linearity_scaled, errors);
5397 cpl_imagelist_delete(errors);
5399 double pval = 0.001;
5400 p = hdrl_bpm_fit_parameter_create_pval(1, pval);
5409 hdrl_bpm_fit_compute(p, hil, x, bpms_ptr);
5434 nbpixs = cpl_image_get_flux(*bpms_ptr);
5436 hdrl_imagelist_delete(hil);
5437 cpl_imagelist_delete(linearity_scaled);
5438 cpl_vector_unwrap((cpl_vector*) x);
5439 hdrl_parameter_delete(p);
5455 skip_if(*bpms_ptr == NULL);
5476 static cpl_error_code
5477 detmon_lg_reduce_all(
const cpl_table * linear_table,
5478 cpl_propertylist * gaint_qclist,
5479 cpl_propertylist * lint_qclist,
5480 cpl_propertylist * linc_qclist,
5481 cpl_propertylist * bpm_qclist,
5482 cpl_imagelist ** coeffs_ptr,
5483 cpl_image ** bpms_ptr,
5484 const cpl_imagelist * linearity_inputs,
5485 const cpl_table * gain_table,
5486 int which_ext, cpl_boolean opt_nir)
5490 const int linear_nsets = cpl_table_get_nrow(linear_table);
5491 const int gain_nsets = cpl_table_get_nrow(gain_table);
5493 cpl_polynomial *poly_linfit = NULL;
5494 cpl_image *fiterror = NULL;
5495 char * name_o1 = NULL;
5496 char * name_o2 = NULL;
5497 double * pcoeffs = NULL;
5498 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
5501 cpl_vector *x =NULL;
5502 const cpl_vector *y =NULL;
5505 const cpl_image * first = NULL;
5513 cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5514 cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5515 cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
5516 cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
5518 pcoeffs = cpl_malloc(
sizeof(
double)*(detmon_lg_config.order + 1));
5520 skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
5521 detmon_lg_config.method));
5522 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
5523 DETMON_QC_METHOD_C));
5526 if (!strcmp(detmon_lg_config.method,
"PTC")) {
5528 if (detmon_lg_config.exts >= 0) {
5529 cpl_msg_info(cpl_func,
5530 "Polynomial fitting for the GAIN (constant term method)");
5532 cpl_msg_info(cpl_func,
5533 "Polynomial fitting for the GAIN (constant term method)"
5534 " for extension nb %d", which_ext);
5536 skip_if(detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, gain_nsets));
5538 skip_if(detmon_lg_qc_med(gain_table, gaint_qclist, gain_nsets));
5543 if(detmon_lg_config.lamp_ok) {
5544 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
5545 detmon_lg_config.cr));
5546 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
5547 DETMON_QC_LAMP_FLUX_C));
5551 if(detmon_lg_config.autocorr == TRUE) {
5552 autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
5553 skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
5555 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
5556 DETMON_QC_AUTOCORR_C));
5558 if (detmon_lg_config.exts >= 0) {
5559 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix");
5561 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix"
5562 " for extension nb %d", which_ext);
5565 if(!detmon_lg_config.pix2pix) {
5566 const int order=detmon_lg_config.order;
5574 y = cpl_vector_wrap(linear_nsets,
5575 (
double *)cpl_table_get_data_double_const(linear_table,
5578 if (opt_nir == NIR) {
5579 x = cpl_vector_wrap(linear_nsets,
5580 (
double *)cpl_table_get_data_double_const(linear_table,
5583 x = cpl_vector_wrap(linear_nsets,
5584 (
double *)cpl_table_get_data_double_const(linear_table,
5588 if(x == NULL || y == NULL) {
5589 cpl_vector_unwrap((cpl_vector *)x);
5590 cpl_vector_unwrap((cpl_vector *)y);
5600 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
5601 poly_linfit = irplib_polynomial_fit_1d_create(x, y,order,&mse);
5603 if(order == cpl_vector_get_size(x) - 1) {
5604 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5608 if(poly_linfit == NULL) {
5609 cpl_vector_unwrap((cpl_vector *)x);
5610 cpl_vector_unwrap((cpl_vector *)y);
5616 min_val=cpl_vector_get_min(y);
5617 max_val=cpl_vector_get_max(y);
5619 cpl_vector_unwrap((cpl_vector *)x);
5620 cpl_vector_unwrap((cpl_vector *)y);
5622 for(deg = 0; deg <= order; deg++) {
5623 const double coeff =
5624 cpl_polynomial_get_coeff(poly_linfit, °);
5626 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
5627 assert(name_o != NULL);
5628 skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
5629 skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
5630 DETMON_QC_LIN_COEF_C));
5633 pcoeffs[deg] = coeff;
5635 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
5636 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
5637 DETMON_QC_ERRFIT_MSE_C));
5641 const int order=detmon_lg_config.order;
5643 y = cpl_vector_wrap(linear_nsets,
5644 (
double *)cpl_table_get_data_double_const(linear_table,
5649 x = cpl_vector_wrap(linear_nsets,
5650 (
double *)cpl_table_get_data_double_const(linear_table,
5653 x = cpl_vector_wrap(linear_nsets,
5654 (
double *)cpl_table_get_data_double_const(linear_table,
5659 first = cpl_imagelist_get_const(linearity_inputs, 0);
5660 sizex = cpl_image_get_size_x(first);
5661 sizey = cpl_image_get_size_y(first);
5662 vsize = cpl_vector_get_size(x);
5663 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
5665 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,order, FALSE,
5666 CPL_TYPE_FLOAT, fiterror);
5667 min_val=cpl_vector_get_min(y);
5668 max_val=cpl_vector_get_max(y);
5669 cpl_vector_unwrap((cpl_vector*)x);
5670 cpl_vector_unwrap((cpl_vector*)y);
5672 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
5673 "Failed polynomial fit");
5676 for(deg = 0; deg <= order; deg++)
5678 cpl_image *image = cpl_imagelist_get(*coeffs_ptr, deg);
5679 const double coeff = cpl_image_get_median(image);
5680 pcoeffs[deg] = coeff;
5681 name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", (
int)deg);
5682 name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", (
int)deg);
5683 assert(name_o1 != NULL);
5684 assert(name_o2 != NULL);
5685 skip_if(cpl_propertylist_append_double(linc_qclist, name_o1, coeff));
5686 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o1,
5687 DETMON_QC_LIN_COEF_C));
5690 skip_if(cpl_propertylist_append_double(linc_qclist, name_o2,
5691 cpl_image_get_stdev(image)));
5692 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o2,
5693 DETMON_QC_LIN_COEF_ERR_C));
5699 if(order == vsize - 1)
5701 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5702 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5704 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5705 DETMON_QC_ERRFIT_C));
5708 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5709 cpl_image_get_median(fiterror)));
5710 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5711 DETMON_QC_ERRFIT_C));
5715 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
5717 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
5718 DETMON_QC_COUNTS_MIN_C));
5719 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
5721 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
5722 DETMON_QC_COUNTS_MAX_C));
5723 skip_if(detmon_lg_lineff(pcoeffs,lint_qclist,detmon_lg_config.ref_level,
5724 detmon_lg_config.order));
5726 if (detmon_lg_config.exts >= 0)
5728 cpl_msg_info(cpl_func,
"Bad pixel detection");
5731 cpl_msg_info(cpl_func,
"Bad pixel detection"
5732 " for extension nb %d", which_ext);
5734 if(detmon_lg_config.pix2pix)
5738 nbpixs = detmon_compute_badpixmap(opt_nir, linear_nsets, linear_table,
5739 linearity_inputs, nbpixs, x,gaint_qclist, bpms_ptr);
5744 skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
5745 skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
5746 DETMON_QC_NUM_BPM_C));
5747 cpl_msg_info(cpl_func,
"stability=%g",detmon_lg_config.lamp_stability);
5748 if(detmon_lg_config.lamp_stability != 0.0)
5750 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
5751 detmon_lg_config.lamp_stability));
5752 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
5753 DETMON_QC_LAMP_STAB_C));
5756 if (!detmon_lg_config.wholechip && detmon_lg_config.pix2pix)
5758 detmon_lg_fits_coeffs_and_bpm2chip(coeffs_ptr,bpms_ptr);
5765 cpl_image_delete(fiterror);
5766 cpl_polynomial_delete(poly_linfit);
5770 return cpl_error_get_code();
5782 static cpl_error_code
5783 detmon_lg_lineff(
double * pcoeffs,
5784 cpl_propertylist * qclist,
5790 double residual, slope;
5793 cpl_polynomial * poly = cpl_polynomial_new(1);
5807 pcoeffs[0] -= ref_level;
5809 for (i = 2; i <= order; i++)
5812 for(j = 0; j < i; j++)
5814 pcoeffs[i] /= pcoeffs[1];
5820 for (deg = 0; deg <= order; deg++) {
5822 skip_if(cpl_polynomial_set_coeff(poly, °, pcoeffs[deg]));
5831 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
5833 if (slope <= 0.0 && residual >= 0.0) {
5834 cpl_msg_warning(cpl_func,
"Reference level (--ref_level) outside"
5835 " linearity range of the detector. Cannot compute"
5836 " linearity efficiency (QC.LINEFF).");
5841 cpl_error_code err = cpl_polynomial_solve_1d(poly, 0.0, &root, 1);
5846 if (err == CPL_ERROR_NONE)
5849 lineff = (root - ref_level) / ref_level;
5854 cpl_msg_warning(cpl_func,
5855 "Cannot compute linearity efficiency (QC.LINEFF)"
5856 "for the current combination "
5857 " of (--ref-level equal %d) and (--order equal %d) parameters. Try "
5858 "to decrease (--ref-level) value.", ref_level, order);
5861 cpl_msg_warning(cpl_func,
"DETMON_QC_LIN_EFF=%f",lineff );
5862 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
5864 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
5865 DETMON_QC_LIN_EFF_C));
5867 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
5869 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
5870 DETMON_QC_LIN_EFF_FLUX_C));
5874 cpl_polynomial_delete(poly);
5876 return cpl_error_get_code();
5887 static cpl_error_code
5888 detmon_lg_qc_ptc(
const cpl_table * gain_table,
5889 cpl_propertylist * qclist,
unsigned mode,
int rows_in_gain)
5892 cpl_polynomial *poly_fit = NULL;
5893 cpl_polynomial *poly_fit2 = NULL;
5895 const int nsets = rows_in_gain;
5897 cpl_vector *x = NULL;
5898 cpl_vector *y = NULL;
5900 cpl_errorstate prestate;
5902 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
5903 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
5905 x = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5907 y = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5909 skip_if(x == NULL || y == NULL);
5910 if (0 == detmon_lg_check_before_gain(x, y))
5914 cpl_vector_unwrap(x);
5918 cpl_vector_unwrap(y);
5920 return CPL_ERROR_NONE;
5923 poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
5924 skip_if(poly_fit == NULL);
5928 prestate = cpl_errorstate_get();
5929 coef = cpl_polynomial_get_coeff(poly_fit, &i);
5930 skip_if (!cpl_errorstate_is_equal(prestate) || coef==0);
5931 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
5932 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5933 DETMON_QC_CONAD_C));
5936 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
5938 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
5954 if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
5955 const cpl_vector *x2 =
5956 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT_CORR"));
5957 const cpl_vector *y2 =
5958 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5960 if(x2 == NULL || y2 == NULL) {
5961 cpl_vector_unwrap((cpl_vector *)x2);
5962 cpl_vector_unwrap((cpl_vector *)y2);
5973 poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
5974 if(poly_fit2 == NULL) {
5975 cpl_vector_unwrap((cpl_vector *)x2);
5976 cpl_vector_unwrap((cpl_vector *)y2);
5978 cpl_msg_error(cpl_func,
"Error during polynomial fit, err[%s]", cpl_error_get_where());
5982 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5983 cpl_vector_unwrap((cpl_vector *)x2);
5984 cpl_vector_unwrap((cpl_vector *)y2);
5985 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5988 prestate = cpl_errorstate_get();
5989 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
5990 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5991 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
5993 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
5995 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
5996 DETMON_QC_CONAD_CORR_C));
5998 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
6000 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
6001 DETMON_QC_GAIN_CORR_C));
6007 cpl_vector_unwrap(x);
6008 cpl_vector_unwrap(y);
6009 cpl_polynomial_delete(poly_fit);
6010 cpl_polynomial_delete(poly_fit2);
6012 return cpl_error_get_code();
6021 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y)
6023 const double TOLERANCE = 1e-37;
6024 double xmin = cpl_vector_get_min(x);
6025 double xmax = cpl_vector_get_max(x);
6026 double ymin = cpl_vector_get_min(y);
6027 double ymax = cpl_vector_get_max(y);
6028 double ystdev = cpl_vector_get_stdev(y);
6029 double xstdev = cpl_vector_get_stdev(x);
6031 if (fabs(xmax-xmin) < TOLERANCE &&
6032 fabs(ymax - ymin) < TOLERANCE &&
6033 xstdev < TOLERANCE &&
6036 cpl_msg_warning(cpl_func,
"An empty frame has been detected, linearity, coeffs, gain, FPN values will not be computed.");
6051 static cpl_error_code
6052 detmon_lg_qc_med(
const cpl_table * gain_table,
6053 cpl_propertylist * qclist,
int rows_in_gain)
6057 cpl_vector *x = NULL;
6058 cpl_vector *y = NULL;
6059 int check_result = 0;
6061 if (rows_in_gain) {};
6063 x = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
6064 y = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
6065 check_result = detmon_lg_check_before_gain(x, y);
6068 cpl_vector_unwrap(x);
6072 cpl_vector_unwrap(y);
6074 if (0 == check_result)
6076 return CPL_ERROR_NONE;
6079 gain=cpl_table_get_column_median(gain_table,
"GAIN");
6081 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
6083 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
6086 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
6087 cpl_table_get_column_stdev
6088 (gain_table,
"GAIN")));
6089 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
6090 DETMON_QC_GAIN_MSE_C));
6092 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
6093 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
6094 DETMON_QC_CONAD_C));
6097 gain=cpl_table_get_column_median(gain_table,
"GAIN_CORR");
6099 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
6101 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
6102 DETMON_QC_GAIN_CORR_C));
6105 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
6106 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
6107 DETMON_QC_CONAD_CORR_C));
6112 return cpl_error_get_code();
6126 static cpl_error_code
6127 detmon_lg_rescale(cpl_imagelist * to_rescale)
6130 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 0),
6131 detmon_lg_config.llx,
6132 detmon_lg_config.lly,
6133 detmon_lg_config.urx,
6134 detmon_lg_config.ury);
6136 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 1),
6137 detmon_lg_config.llx,
6138 detmon_lg_config.lly,
6139 detmon_lg_config.urx,
6140 detmon_lg_config.ury);
6144 if(fabs(med1 / med2 - 1) > 0.001) {
6146 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
6149 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
6155 return cpl_error_get_code();
6158 static cpl_error_code
6159 detmon_pair_extract_next(
const cpl_frameset * set,
6163 cpl_frameset ** pair,
6167 double dit_next = -100;
6168 cpl_size* selection;
6169 int nsets_extracted = 0;
6170 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6171 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6172 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6173 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6175 nsets_extracted = cpl_frameset_get_size(set);
6176 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6177 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6180 dit = dit_array[*next_element ];
6182 if (*next_element < nsets_extracted - 1)
6184 dit_next = dit_array[*next_element + 1 ];
6188 selection[iindex[*next_element] ] = 1;
6189 if (fabs(dit - dit_next) < tolerance)
6192 selection[iindex[*next_element + 1] ] = 1;
6197 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);
6201 cpl_frameset_delete(*pair);
6202 *pair = cpl_frameset_extract(set, selection, 1);
6205 cpl_free(selection);
6206 return cpl_error_get_code();
6209 static cpl_error_code
6210 detmon_single_extract_next(
const cpl_frameset * set,
6214 cpl_frameset ** pair)
6216 cpl_size* selection;
6217 int nsets_extracted = 0;
6218 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6219 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6220 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6221 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6223 nsets_extracted = cpl_frameset_get_size(set);
6224 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6225 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6228 selection[iindex[*next_element] ] = 1;
6231 cpl_frameset_delete(*pair);
6232 *pair = cpl_frameset_extract(set, selection, 1);
6234 cpl_free(selection);
6235 return cpl_error_get_code();
6333 detmon_gain(
const cpl_imagelist * imlist_on,
6334 const cpl_imagelist * imlist_off,
6335 const cpl_vector * exptimes,
6336 const cpl_vector * ndit,
6346 cpl_propertylist * qclist,
6348 cpl_imagelist ** diff_imlist,
6349 cpl_imagelist ** autocorr_imlist)
6351 cpl_table * gain_table = NULL;
6352 cpl_imagelist * difflist = NULL;
6353 cpl_imagelist * autocorrlist = NULL;
6354 cpl_imagelist * c_onlist = NULL;
6355 cpl_imagelist * c_offlist = NULL;
6356 cpl_vector * diffdits = NULL;
6357 cpl_vector * diffndits = NULL;
6358 int rows_in_gain = 0;
6359 int ndiffdits, ndits;
6361 cpl_boolean opt_nir = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
6362 const char * method = mode & IRPLIB_GAIN_PTC ?
"PTC" :
"MED";
6364 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6365 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6366 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6367 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6370 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6371 skip_if(detmon_gain_table_create(gain_table, opt_nir));
6375 skip_if(detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,
6377 ndiffdits = cpl_vector_get_size(diffdits);
6379 ndits = cpl_vector_get_size(exptimes);
6382 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
6383 difflist = cpl_imagelist_new();
6384 autocorrlist = cpl_imagelist_new();
6387 if (mode & IRPLIB_GAIN_COLLAPSE) {
6388 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6389 c_offlist = cpl_imagelist_duplicate(imlist_off);
6390 skip_if(detmon_lg_rescale(c_offlist));
6392 c_offlist = (cpl_imagelist *) imlist_off;
6397 for (i = 0; i < ndiffdits; i++) {
6404 c_dit=cpl_vector_get(diffdits, i);
6407 c_ndit=(int)cpl_vector_get(diffndits, i);
6410 c_onlist = cpl_imagelist_new();
6413 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6414 c_offlist = cpl_imagelist_new();
6419 for(j = 0; j < ndits; j++) {
6420 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6430 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6431 const cpl_image * im =
6432 cpl_imagelist_get_const(imlist_on, j);
6433 im_on = cpl_image_duplicate(im);
6435 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6437 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6444 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6446 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6447 const cpl_image * im =
6448 cpl_imagelist_get_const(imlist_off, j);
6449 im_off = cpl_image_duplicate(im);
6452 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6454 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6461 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6462 skip_if (c_nons != c_noffs);
6465 skip_if (c_nons == 0 || c_nons % 2 != 0);
6468 if(mode & IRPLIB_GAIN_WITH_RESCALE) {
6469 skip_if(detmon_lg_rescale(c_onlist));
6470 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6471 skip_if(detmon_lg_rescale(c_offlist));
6477 int rows_affected = 1;
6478 skip_if(detmon_gain_table_fill_row(gain_table,
6482 c_offlist, kappa, nclip,
6484 xshift, yshift, 1E10, i,
6485 mode, &rows_affected));
6490 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6491 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6492 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6493 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6494 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6495 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6498 cpl_imagelist_unset(c_onlist, 0);
6500 cpl_imagelist_unset(c_onlist, 0);
6502 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6503 cpl_imagelist_unset(c_offlist, 0);
6505 cpl_imagelist_unset(c_offlist, 0);
6513 cpl_imagelist_delete(c_onlist);
6514 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6515 cpl_imagelist_delete(c_offlist);
6519 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
6520 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
6521 DETMON_QC_METHOD_C));
6524 if (mode & IRPLIB_GAIN_PTC) {
6525 skip_if(detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
6527 skip_if(detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
6530 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
6531 double autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
6532 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
6534 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
6535 DETMON_QC_AUTOCORR_C));
6538 if (diff_imlist != NULL) *diff_imlist = difflist;
6539 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
6543 cpl_vector_delete(diffdits);
6544 cpl_vector_delete(diffndits);
6549 static cpl_error_code
6550 detmon_gain_table_create(cpl_table * gain_table,
6551 const cpl_boolean opt_nir)
6553 if (opt_nir == NIR) {
6554 skip_if(cpl_table_new_column(gain_table,
"DIT", CPL_TYPE_DOUBLE));
6555 skip_if(cpl_table_new_column(gain_table,
"NDIT", CPL_TYPE_INT));
6557 skip_if(cpl_table_new_column(gain_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6559 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON1", CPL_TYPE_DOUBLE));
6560 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON2", CPL_TYPE_DOUBLE));
6561 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF1", CPL_TYPE_DOUBLE));
6562 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF2", CPL_TYPE_DOUBLE));
6563 skip_if(cpl_table_new_column(gain_table,
"SIG_ON_DIF", CPL_TYPE_DOUBLE));
6564 skip_if(cpl_table_new_column(gain_table,
"SIG_OFF_DIF", CPL_TYPE_DOUBLE));
6565 skip_if(cpl_table_new_column(gain_table,
"GAIN", CPL_TYPE_DOUBLE));
6566 skip_if(cpl_table_new_column(gain_table,
"AUTOCORR", CPL_TYPE_DOUBLE));
6567 skip_if(cpl_table_new_column(gain_table,
"GAIN_CORR", CPL_TYPE_DOUBLE));
6568 skip_if(cpl_table_new_column(gain_table,
"ADU", CPL_TYPE_DOUBLE));
6569 skip_if(cpl_table_new_column(gain_table,
"X_FIT", CPL_TYPE_DOUBLE));
6570 skip_if(cpl_table_new_column(gain_table,
"X_FIT_CORR", CPL_TYPE_DOUBLE));
6571 skip_if(cpl_table_new_column(gain_table,
"Y_FIT", CPL_TYPE_DOUBLE));
6572 skip_if(cpl_table_new_column(gain_table,
"Y_FIT_CORR", CPL_TYPE_DOUBLE));
6573 skip_if(cpl_table_new_column(gain_table,
"FLAG", CPL_TYPE_INT));
6577 return cpl_error_get_code();
6580 static cpl_error_code
6581 detmon_lin_table_create(cpl_table * lin_table,
6582 const cpl_boolean opt_nir)
6584 if (opt_nir == NIR) {
6585 skip_if(cpl_table_new_column(lin_table,
"DIT", CPL_TYPE_DOUBLE));
6587 skip_if(cpl_table_new_column(lin_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6589 skip_if(cpl_table_new_column(lin_table,
"MED", CPL_TYPE_DOUBLE));
6590 skip_if(cpl_table_new_column(lin_table,
"MEAN", CPL_TYPE_DOUBLE));
6591 skip_if(cpl_table_new_column(lin_table,
"MED_DIT", CPL_TYPE_DOUBLE));
6592 skip_if(cpl_table_new_column(lin_table,
"MEAN_DIT", CPL_TYPE_DOUBLE));
6593 skip_if(cpl_table_new_column(lin_table,
"ADL", CPL_TYPE_DOUBLE));
6596 return cpl_error_get_code();
6600 detmon_lg_find_dits(
const cpl_vector * exptimes,
6603 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6609 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
6613 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
6615 for (j = 0; j < ndits; j++) {
6616 if (fabs(cpl_vector_get(exptimes, i) -
6617 cpl_vector_get(dits, j)) > tolerance)
6620 if(ndiffs == ndits) {
6621 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
6626 cpl_vector_set_size(dits, ndits);
6634 static cpl_error_code
6635 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
6636 const cpl_vector * vec_ndits,
6638 cpl_vector** diff_dits,
6639 cpl_vector** diff_ndits)
6647 * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6648 * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
6651 cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
6652 cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
6655 size=cpl_vector_get_size(exptimes);
6657 for(i = 1; i < size; i++) {
6659 for (j = 0; j < ndits; j++) {
6660 if (fabs(cpl_vector_get(exptimes, i) -
6661 cpl_vector_get(*diff_dits,j)) > tolerance)
6664 if(ndiffs == ndits) {
6665 cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
6666 cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
6671 cpl_vector_set_size(*diff_dits, ndits);
6672 cpl_vector_set_size(*diff_ndits, ndits);
6675 return cpl_error_get_code();
6765 detmon_lin(
const cpl_imagelist * imlist_on,
6766 const cpl_imagelist * imlist_off,
6767 const cpl_vector * exptimes,
6777 cpl_propertylist * qclist,
6779 cpl_imagelist ** coeffs_cube,
6782 cpl_table * lin_table = NULL;
6783 cpl_imagelist * c_onlist = NULL;
6784 cpl_imagelist * c_offlist = NULL;
6785 cpl_vector * diffdits = NULL;
6786 cpl_imagelist * lin_inputs = NULL;
6787 cpl_polynomial * poly_linfit = NULL;
6788 cpl_image * fiterror = NULL;
6789 cpl_vector * vcoeffs = NULL;
6790 double * pcoeffs = NULL;
6791 int ndiffdits, ndits;
6793 cpl_boolean opt_nir = mode & IRPLIB_LIN_OPT ? OPT : NIR;
6794 const cpl_vector *x = NULL;
6795 const cpl_vector *y = NULL;
6797 const cpl_image * first = NULL;
6805 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6806 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6807 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6808 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6809 cpl_ensure(order > 0 , CPL_ERROR_ILLEGAL_INPUT, NULL);
6811 vcoeffs = cpl_vector_new(order + 1);
6812 pcoeffs = cpl_vector_get_data(vcoeffs);
6815 if (mode & IRPLIB_LIN_PIX2PIX) {
6816 cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
6817 cpl_ensure(bpm != NULL, CPL_ERROR_NULL_INPUT, NULL);
6818 lin_inputs = cpl_imagelist_new();
6822 lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6823 skip_if(detmon_lin_table_create(lin_table, opt_nir));
6827 diffdits = detmon_lg_find_dits(exptimes, tolerance);
6828 ndiffdits = cpl_vector_get_size(diffdits);
6830 ndits = cpl_vector_get_size(exptimes);
6860 if (mode & IRPLIB_LIN_COLLAPSE) {
6865 cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
6866 skip_if(collapse == NULL);
6868 c_offlist = cpl_imagelist_new();
6869 skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
6873 for (i = 0; i < ndiffdits; i++) {
6877 double c_dit = cpl_vector_get(diffdits, i);
6879 c_onlist = cpl_imagelist_new();
6882 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6883 c_offlist = cpl_imagelist_new();
6887 for(j = 0; j < ndits; j++) {
6888 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6898 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6899 const cpl_image * im =
6900 cpl_imagelist_get_const(imlist_on, j);
6901 im_on = cpl_image_duplicate(im);
6903 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6905 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6912 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6914 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6915 const cpl_image * im =
6916 cpl_imagelist_get_const(imlist_off, j);
6917 im_off = cpl_image_duplicate(im);
6920 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6922 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6929 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6930 skip_if (c_nons != c_noffs);
6933 skip_if (c_nons == 0 || c_nons % 2 != 0);
6936 if(mode & IRPLIB_LIN_WITH_RESCALE) {
6937 skip_if(detmon_lg_rescale(c_onlist));
6938 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6939 skip_if(detmon_lg_rescale(c_offlist));
6946 skip_if(detmon_lin_table_fill_row(lin_table, c_dit,
6948 c_onlist, c_offlist,
6952 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6953 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6954 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6955 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6956 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6957 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6960 cpl_imagelist_unset(c_onlist, 0);
6962 cpl_imagelist_unset(c_onlist, 0);
6964 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6965 cpl_imagelist_unset(c_offlist, 0);
6967 cpl_imagelist_unset(c_offlist, 0);
6975 cpl_imagelist_delete(c_onlist);
6976 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6977 cpl_imagelist_delete(c_offlist);
6981 skip_if(detmon_add_adl_column(lin_table, opt_nir));
6983 if(!(mode & IRPLIB_LIN_PIX2PIX)) {
6986 y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6987 (
double *)cpl_table_get_data_double_const(lin_table,
6989 if (opt_nir == NIR) {
6990 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6991 (
double *)cpl_table_get_data_double_const(lin_table,
"DIT"));
6993 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6994 (
double *)cpl_table_get_data_double_const(lin_table,
"EXPTIME"));
6996 if(x == NULL || y == NULL) {
6997 cpl_vector_unwrap((cpl_vector *)x);
6998 cpl_vector_unwrap((cpl_vector *)y);
7008 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
7009 poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
7011 if(order == cpl_vector_get_size(x) - 1) {
7012 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7016 if(poly_linfit == NULL) {
7017 cpl_vector_unwrap((cpl_vector *)x);
7018 cpl_vector_unwrap((cpl_vector *)y);
7023 cpl_vector_unwrap((cpl_vector *)x);
7024 cpl_vector_unwrap((cpl_vector *)y);
7026 for(deg = 0; deg <= order; deg++) {
7027 const double coeff =
7028 cpl_polynomial_get_coeff(poly_linfit, °);
7030 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
7031 assert(name_o != NULL);
7032 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
7033 skip_if(cpl_propertylist_set_comment(qclist,name_o,
7034 DETMON_QC_LIN_COEF_C));
7036 pcoeffs[deg] = coeff;
7038 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
7039 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7040 DETMON_QC_ERRFIT_MSE_C));
7044 if (opt_nir == NIR) {
7045 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7046 (
double *)cpl_table_get_data_double_const(lin_table,
7049 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7050 (
double *)cpl_table_get_data_double_const(lin_table,
7055 first = cpl_imagelist_get_const(lin_inputs, 0);
7056 sizex = cpl_image_get_size_x(first);
7057 sizey = cpl_image_get_size_y(first);
7059 vsize = cpl_vector_get_size(x);
7061 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
7064 cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
7065 order, FALSE, CPL_TYPE_FLOAT,
7068 cpl_vector_unwrap((cpl_vector*)x);
7069 irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
7070 "Failed polynomial fit");
7072 for(i = 0; i <= order; i++) {
7073 cpl_image *image = cpl_imagelist_get(*coeffs_cube, i);
7074 const double coeff = cpl_image_get_median(image);
7075 char * name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", i);
7076 char * name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", i);
7078 assert(name_o1 != NULL);
7079 assert(name_o2 != NULL);
7080 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
7081 skip_if(cpl_propertylist_set_comment(qclist,name_o1,
7082 DETMON_QC_LIN_COEF_C));
7085 skip_if(cpl_propertylist_append_double(qclist, name_o2,
7086 cpl_image_get_stdev(image)));
7087 skip_if(cpl_propertylist_set_comment(qclist,name_o2,
7088 DETMON_QC_LIN_COEF_ERR_C));
7093 if(order == vsize - 1) {
7094 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7095 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7097 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7098 DETMON_QC_ERRFIT_C));
7102 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7103 cpl_image_get_median(fiterror)));
7104 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7105 DETMON_QC_ERRFIT_C));
7110 skip_if(detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
7112 if(mode & IRPLIB_LIN_PIX2PIX) {
7114 *bpm = detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
7115 skip_if(*bpm == NULL);
7116 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
7118 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
7119 DETMON_QC_NUM_BPM_C));
7124 cpl_vector_delete(diffdits);
7125 cpl_polynomial_delete(poly_linfit);
7126 cpl_imagelist_delete(lin_inputs);
7127 cpl_vector_delete(vcoeffs);
7128 cpl_image_delete(fiterror);
7158 static cpl_error_code
7159 detmon_lin_table_fill_row(cpl_table * lin_table,
double c_dit,
7160 cpl_imagelist * linearity_inputs,
7161 const cpl_imagelist * ons,
7162 const cpl_imagelist * offs,
7171 cpl_image * extracted=NULL;
7173 cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
7174 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
7175 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
7177 if (mode & IRPLIB_LIN_PIX2PIX) {
7178 cpl_msg_debug(cpl_func,
"checking linearity inputs");
7179 cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
7183 if (mode & IRPLIB_LIN_NIR) {
7184 cpl_table_set(lin_table,
"DIT", pos, c_dit);
7185 }
else if (mode & IRPLIB_LIN_OPT) {
7186 cpl_table_set(lin_table,
"EXPTIME", pos, c_dit);
7188 cpl_msg_error(cpl_func,
"Mandatory mode not given");
7192 const cpl_image * off2;
7193 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
7194 off2 = cpl_imagelist_get_const(offs, 0);
7196 off2 = cpl_imagelist_get_const(offs, 1);
7198 extracted = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
7199 cpl_imagelist_get_const(offs, 0),
7200 cpl_imagelist_get_const(ons, 1),
7202 llx, lly, urx, ury);
7203 cpl_ensure_code(extracted != NULL, cpl_error_get_code());
7207 double median = cpl_image_get_median(extracted);
7208 double mean= cpl_image_get_mean(extracted);
7209 cpl_table_set(lin_table,
"MED", pos, median);
7210 cpl_table_set(lin_table,
"MEAN", pos, mean);
7212 cpl_table_set(lin_table,
"MED_DIT", pos, median / c_dit);
7213 cpl_table_set(lin_table,
"MEAN_DIT", pos, mean / c_dit);
7217 if(mode & IRPLIB_LIN_PIX2PIX) {
7218 cpl_error_code error = cpl_imagelist_set(linearity_inputs, extracted,
7220 cpl_ensure_code(!error, error);
7222 cpl_image_delete(extracted);
7225 return cpl_error_get_code();
7228 static double irplib_calculate_total_noise_smooth(
const cpl_image* pimage,
7229 int pattern_x,
int pattern_y)
7231 cpl_image * p_tmp_image = 0;
7232 cpl_image * psmooth_image = 0;
7234 cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
7236 p_tmp_image = cpl_image_duplicate(pimage);
7237 cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
7238 cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
7239 psmooth_image = cpl_image_divide_create(pimage,p_tmp_image);
7240 ret_noise = irplib_calculate_total_noise(psmooth_image);
7241 cpl_mask_delete(mask);
7242 cpl_image_delete(psmooth_image);
7243 cpl_image_delete(p_tmp_image);
7247 static double irplib_calculate_total_noise(
const cpl_image* pimage)
7249 double total_noise = -1;
7250 unsigned long max_bin_size = 1E5;
7251 const double hstart = cpl_image_get_min(pimage);
7252 const double hrange = cpl_image_get_max(pimage) - hstart;
7253 const unsigned long nbins = max_bin_size;
7256 irplib_hist * phist = 0;
7257 phist = irplib_hist_new();
7260 irplib_hist_init(phist, nbins, hstart, hrange);
7261 err = irplib_hist_fill(phist, pimage);
7262 if (err == CPL_ERROR_NONE)
7270 unsigned long n_bins = irplib_hist_get_nbins(phist);
7271 double start = irplib_hist_get_start(phist);
7272 double bin_size = irplib_hist_get_bin_size(phist);
7273 cpl_vector* pdata_vector = cpl_vector_new(n_bins);
7274 cpl_vector* ppos_vector = cpl_vector_new(n_bins);
7275 cpl_table* ptable = cpl_table_new(n_bins);
7276 cpl_table_new_column(ptable,
"bin", CPL_TYPE_DOUBLE);
7277 cpl_table_new_column(ptable,
"value", CPL_TYPE_DOUBLE);
7278 for(i = 0; i < n_bins; i++)
7280 unsigned int value = irplib_hist_get_value(phist, i);
7281 double dvalue = (double)(value);
7282 cpl_vector_set(pdata_vector, i, dvalue);
7283 cpl_vector_set(ppos_vector, i, start + i * bin_size);
7285 cpl_table_set(ptable,
"bin", i, start + i * bin_size);
7286 cpl_table_set(ptable,
"value", i, dvalue);
7288 err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
7289 if (err == CPL_ERROR_NONE)
7291 cpl_msg_info(cpl_func,
"FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
7295 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed Gaussian Fit, err msg [%s]", cpl_error_get_message());
7298 cpl_table_delete(ptable);
7299 cpl_vector_delete(ppos_vector);
7300 cpl_vector_delete(pdata_vector);
7304 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
7307 irplib_hist_delete(phist);
7312 static double irplib_compute_err(
double gain,
double ron,
double FA)
7314 double int_gain = (gain * gain - 1) / 12;
7319 return sqrt(ron * ron + FA / gain + int_gain);
7322 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain ,
7323 FPN_METHOD fpn_method,
int smooth_size,
double* mse)
7325 cpl_image* im_diff = 0;
7326 const cpl_image* im_f1 = f1;
7327 cpl_image* im_inrange1 = 0;
7336 cpl_msg_warning(cpl_func,
"gain[%f]<0", gain);
7337 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7344 im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
7345 im_f1 = im_inrange1;
7347 FA = cpl_image_get_median(im_f1);
7354 cpl_msg_info(cpl_func,
"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
7355 s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
7358 cpl_msg_info(cpl_func,
"HISTOGRAM method is used for FPN");
7359 s_tot = irplib_calculate_total_noise(im_f1);
7364 cpl_msg_warning(cpl_func,
"fpn_method is not defined");
7373 cpl_msg_warning(cpl_func,
"Median flux on sum of flats<0");
7374 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7379 if ((s_tot * s_tot - FA / gain) > 0)
7381 s_fpn = sqrt(s_tot * s_tot - FA / gain);
7382 sr_fpn = s_fpn / FA;
7383 *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
7387 cpl_msg_warning(cpl_func,
"s_tot * s_tot < FA / gain");
7388 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7397 cpl_image_delete(im_diff);
7400 cpl_image_delete(im_inrange1);
7406 static cpl_imagelist * irplib_load_fset_wrp(
const cpl_frameset * pframeset,
7407 cpl_type type ,
int whichext)
7411 return detmon_load_frameset_window(pframeset, type, 0, whichext,
7412 detmon_lg_config.llx,
7413 detmon_lg_config.lly,
7414 detmon_lg_config.urx,
7415 detmon_lg_config.ury,
7416 detmon_lg_config.nx,
7417 detmon_lg_config.ny);
7420 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset * pframeset,
7421 cpl_type type ,
int whichext)
7424 cpl_imagelist* offs = cpl_imagelist_new();
7425 detmon_lg_config.load_fset(pframeset, type, offs);
7430 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
7431 cpl_propertylist* plist)
7433 if (ptable && plist)
7435 int size = cpl_propertylist_get_size(plist);
7437 for (i = 0; i < size; i++)
7439 cpl_property* pprop = cpl_propertylist_get(plist,i);
7442 const char* pname = cpl_property_get_name(pprop);
7445 cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
7446 if (cpl_error_get_code() != CPL_ERROR_NONE)
7448 cpl_msg_warning(cpl_func,
"cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
7455 return cpl_error_get_code();
7458 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
7459 cpl_propertylist* plist,
int row)
7461 cpl_error_code err = CPL_ERROR_NONE;
7462 if (ptable && plist)
7464 int size = cpl_propertylist_get_size(plist);
7466 for (i = 0; i < size; i++)
7468 cpl_property* pprop = cpl_propertylist_get(plist,i);
7471 const char* pname = cpl_property_get_name(pprop);
7472 double value = cpl_property_get_double(pprop);
7475 cpl_table_set_double(ptable, pname, row, value);
7476 if (cpl_error_get_code() != CPL_ERROR_NONE)
7478 cpl_msg_warning(cpl_func,
"cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
7489 cpl_error_code detmon_check_order(
const double *exptime,
int sz,
7490 double tolerance,
int order)
7507 }
while(fabs(exptime[i-1] - exptime[i]) < tolerance);
7508 }
while(i < sz - 1);
7510 if ( !( fabs(exptime[i-1] - exptime[i]) < tolerance ) ) nsets++;
7513 cpl_error_set_message(cpl_func,CPL_ERROR_INCOMPATIBLE_INPUT,
7514 "Not enough frames for the polynomial"
7515 " fitting. nsets = %d <= %d order",
7518 return cpl_error_get_code();
7521 static cpl_error_code
7522 detmon_lg_dfs_save_imagelist(
7523 cpl_frameset * frameset,
7524 const cpl_parameterlist * parlist,
7525 const cpl_frameset *usedframes,
7526 const cpl_imagelist *coeffs,
7527 const char *recipe_name,
7528 const cpl_propertylist *mypro_coeffscube,
7529 const char * package,
7530 const char * name_o)
7532 return(cpl_dfs_save_imagelist
7533 (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
7534 recipe_name, mypro_coeffscube, NULL, package,
7538 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos)
7540 const cpl_image* first = cpl_imagelist_get(imlist, 0);
7543 int x = cpl_image_get_size_x(first);
7544 int y = cpl_image_get_size_y(first);
7545 cpl_type type = cpl_image_get_type(first);
7546 cpl_image * blank = cpl_image_new(x, y, type);
7547 cpl_imagelist_set(imlist, blank, pos);
7553 detmon_lg_set_tag(cpl_frameset* set,
const char** tag_on,
const char** tag_off)
7558 ntag_old=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_OLD);
7559 ntag_new=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_NEW);
7561 *tag_on=DETMON_LG_ON_RAW_OLD;
7562 *tag_off=DETMON_LG_OFF_RAW_OLD;
7563 }
else if (ntag_new) {
7564 *tag_on=DETMON_LG_ON_RAW_NEW;
7565 *tag_off=DETMON_LG_OFF_RAW_NEW;
7567 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
7568 "Provide %s and %s (or %s and %s) input frames",
7569 DETMON_LG_ON_RAW_NEW,DETMON_LG_OFF_RAW_NEW,
7570 DETMON_LG_ON_RAW_OLD,DETMON_LG_OFF_RAW_OLD);
7574 return cpl_error_get_code();