43 #include "detmon_utils.h"
44 #include "detmon_lg.h"
45 #include "detmon_lg_impl.h"
46 #include "detmon_dfs.h"
48 #include "irplib_ksigma_clip.h"
49 #include "irplib_utils.h"
50 #include "irplib_hist.h"
74 typedef enum _FPN_METHOD FPN_METHOD;
114 cpl_boolean wholechip;
115 cpl_boolean autocorr;
116 cpl_boolean intermediate;
117 cpl_boolean collapse;
124 const char * pafname;
129 double lamp_stability;
132 int (* load_fset) (
const cpl_frameset *, cpl_type, cpl_imagelist *);
133 cpl_imagelist * (* load_fset_wrp) (
const cpl_frameset *, cpl_type, int);
134 FPN_METHOD fpn_method;
136 double saturation_limit;
137 cpl_boolean split_coeffs;
147 static cpl_error_code
148 detmon_lg_retrieve_parlist(
const char *,
149 const char *,
const cpl_parameterlist *,
153 static cpl_error_code
154 detmon_lg_split_onoff(
const cpl_frameset *,
157 const char *,
const char * );
159 static cpl_error_code
160 detmon_lg_reduce(
const cpl_frameset *,
161 const cpl_frameset *,
162 int* index_on,
int* index_off,
163 double* exptime_on,
double* exptime_off,
164 int *next_index_on,
int* next_index_off,
175 int (* load_fset) (
const cpl_frameset *,
178 const cpl_boolean,
int);
180 static cpl_error_code
181 detmon_lin_table_fill_row(cpl_table *,
double,
183 const cpl_imagelist *,
184 const cpl_imagelist *,
190 static cpl_error_code
191 detmon_gain_table_fill_row(cpl_table * gain_table,
192 double c_dit,
int c_ndit,
193 cpl_imagelist * autocorr_images,
194 cpl_imagelist * diff_flats,
195 const cpl_imagelist * ons,
196 const cpl_imagelist * offs,
197 double kappa,
int nclip,
198 int llx,
int lly,
int urx,
int ury,
200 double saturation_limit,
201 const int pos,
unsigned mode,
int* rows_affected);
203 static cpl_error_code
204 detmon_lg_save(
const cpl_parameterlist *,
209 const cpl_propertylist *,
210 const cpl_propertylist *,
211 const cpl_propertylist *,
212 const cpl_propertylist *,
213 const cpl_propertylist *,
214 const cpl_propertylist *,
226 const int,
const int,
const cpl_frameset *,
229 static cpl_error_code
230 detmon_lg_qc_ptc(
const cpl_table *,
231 cpl_propertylist *,
unsigned,
int);
233 static cpl_error_code
234 detmon_lg_qc_med(
const cpl_table *,
235 cpl_propertylist *,
int);
239 irplib_pfits_get_dit(
const cpl_propertylist *);
242 irplib_pfits_get_dit_opt(
const cpl_propertylist *);
244 irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
245 const char* prop_name);
247 static cpl_image * detmon_bpixs(
const cpl_imagelist *,
248 cpl_boolean,
const double,
int *);
251 detmon_autocorr_factor(
const cpl_image *,
252 cpl_image **,
int,
int);
256 static cpl_error_code
257 detmon_opt_contamination(
const cpl_imagelist *,
258 const cpl_imagelist *,
259 unsigned mode, cpl_propertylist *);
262 detmon_opt_lampcr(cpl_frameset *,
int);
266 detmon_lg_dfs_set_groups(cpl_frameset *,
const char *,
const char *);
268 static cpl_error_code
269 detmon_lg_reduce_all(
const cpl_table *,
276 const cpl_imagelist *,
277 const cpl_table *,
int, cpl_boolean);
279 static cpl_error_code
280 detmon_lg_check_defaults(
const cpl_image *);
282 static cpl_error_code
283 detmon_lg_rescale(cpl_imagelist *);
285 static cpl_error_code
286 detmon_lg_reduce_init(cpl_table *,
292 static cpl_error_code
293 detmon_add_adl_column(cpl_table *, cpl_boolean);
295 static cpl_error_code
296 detmon_lg_lamp_stab(
const cpl_frameset *,
297 const cpl_frameset *,
301 static cpl_error_code
302 detmon_lg_reduce_dit(
const cpl_frameset * set_on,
303 int* index_on,
double* exptime_on,
306 const cpl_frameset * set_off,
307 int * index_off,
double* exptime_off,
308 int* next_on,
int* next_off,
309 cpl_table * linear_table,
310 cpl_table * gain_table,
311 cpl_imagelist * linearity_inputs,
312 cpl_propertylist * qclist,
314 cpl_imagelist * autocorr_images,
315 cpl_imagelist * diff_flats,
316 cpl_imagelist * opt_offs,
318 int * rows_affected);
320 static cpl_error_code
321 detmon_lg_core(cpl_frameset * cur_fset_on,
322 cpl_frameset * cur_fset_off,
326 double * exptime_off,
329 const char * recipe_name,
330 const char * pipeline_name,
331 const char * pafregexp,
332 const cpl_propertylist * pro_lintbl,
333 const cpl_propertylist * pro_gaintbl,
334 const cpl_propertylist * pro_coeffscube,
335 const cpl_propertylist * pro_bpm,
336 const cpl_propertylist * pro_corr,
337 const cpl_propertylist * pro_diff,
338 const char * package,
339 int (* load_fset) (
const cpl_frameset *,
342 int nsets, cpl_boolean opt_nir,
343 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
344 cpl_frameset * cur_fset);
346 static cpl_error_code
347 detmon_lg_lineff(
double *, cpl_propertylist *,
int,
int);
354 static cpl_error_code
355 detmon_gain_table_create(cpl_table *,
359 static cpl_error_code
360 detmon_lin_table_create(cpl_table *,
364 detmon_lg_find_dits(
const cpl_vector *,
367 static cpl_error_code
368 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
369 const cpl_vector * vec_ndits,
371 cpl_vector** diff_dits,
372 cpl_vector** diff_ndits);
374 static cpl_error_code
375 detmon_fpn_compute(
const cpl_frameset *set_on,
378 cpl_propertylist *lint_qclist,
385 FPN_METHOD fpn_method,
387 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain,
388 FPN_METHOD fpn_method,
int,
double* mse);
389 static double irplib_calculate_total_noise(
const cpl_image* pimage);
391 static cpl_imagelist* irplib_load_fset_wrp(
const cpl_frameset *,
392 cpl_type,
int whichext);
393 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset *,
396 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
397 cpl_propertylist* plist);
398 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
399 cpl_propertylist* plist,
402 static cpl_error_code
403 detmon_pair_extract_next(
const cpl_frameset * set,
409 cpl_frameset ** pair,
411 static cpl_error_code
412 detmon_single_extract_next(
const cpl_frameset * set,
416 cpl_frameset ** pair);
423 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code);
424 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos);
425 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y);
434 static int irplib_pfits_get_ndit(
const cpl_propertylist * plist)
436 return cpl_propertylist_get_int(plist,
"ESO DET NDIT");
502 hdrldemo_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
503 const double ron, cpl_image ** ima_errs)
505 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
506 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
507 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
508 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
510 *ima_errs = cpl_image_duplicate(ima_data);
512 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
516 cpl_image_divide_scalar(*ima_errs, gain);
517 cpl_image_add_scalar(*ima_errs, ron * ron);
518 cpl_image_power(*ima_errs, 0.5);
520 return cpl_error_get_code();
525 static cpl_error_code
526 detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
529 const char * tag_off,
530 const char * recipe_name,
531 const char * pipeline_name,
532 const char * pafregexp,
533 const cpl_propertylist * pro_lintbl,
534 const cpl_propertylist * pro_gaintbl,
535 const cpl_propertylist * pro_coeffscube,
536 const cpl_propertylist * pro_bpm,
537 const cpl_propertylist * pro_corr,
538 const cpl_propertylist * pro_diff,
539 const char * package,
541 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
542 const cpl_boolean opt_nir,
543 const cpl_parameterlist * parlist,
546 static double irplib_compute_err(
double gain,
double ron,
double photon_noise);
548 static cpl_error_code
549 detmon_lg_dfs_save_imagelist(cpl_frameset * frameset,
550 const cpl_parameterlist * parlist,
551 const cpl_frameset *usedframes,
552 const cpl_imagelist *coeffs,
553 const char *recipe_name,
554 const cpl_propertylist *mypro_coeffscube,
555 const char * package,
556 const char * name_o);
559 static void irplib_free(
char** pointer){
561 if(pointer && *pointer) {
567 static cpl_error_code
568 detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
int nsets,
570 const char * tag_off,
571 const char * recipe_name,
572 const char * pipeline_name,
573 const char * pafregexp,
574 const cpl_propertylist * pro_lintbl,
575 const cpl_propertylist * pro_gaintbl,
576 const cpl_propertylist * pro_coeffscube,
577 const cpl_propertylist * pro_bpm,
578 const cpl_propertylist * pro_corr,
579 const cpl_propertylist * pro_diff,
580 const char * package,
582 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
583 const cpl_boolean opt_nir,
584 const cpl_parameterlist * parlist,
589 int nexts = detmon_lg_config.nb_extensions;
591 double* exptime_on = 0;
592 double* exptime_off = 0;
595 cpl_frameset * cur_fset = NULL;
596 cpl_frameset* cur_fset_on = 0;
597 cpl_frameset* cur_fset_off = 0;
602 cpl_frameset_duplicate(frameset) : cpl_frameset_extract(frameset, selection, i);
605 skip_if(cur_fset == NULL);
608 cur_fset_on = cpl_frameset_new();
609 cur_fset_off = cpl_frameset_new();
610 cpl_msg_info(cpl_func,
"Splitting into ON and OFF sub-framesets");
611 skip_if (detmon_lg_split_onoff(cur_fset,
612 cur_fset_on, cur_fset_off,
614 if (cpl_frameset_get_size(cur_fset_on) == 0)
616 cpl_msg_error(cpl_func,
"No lamp frames in input");
620 if (cpl_frameset_get_size(cur_fset_off) == 0)
622 cpl_msg_error(cpl_func,
"No dark / bias frames in input");
625 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));
633 exptime_on = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_on));
634 exptime_off = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_off));
636 index_on = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_on));
637 index_off = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_off));
638 irplib_frameset_sort(cur_fset_on, index_on, exptime_on);
639 irplib_frameset_sort(cur_fset_off, index_off, exptime_off);
652 skip_if(detmon_check_order(exptime_on, cpl_frameset_get_size(cur_fset_on), detmon_lg_config.tolerance, detmon_lg_config.order));
654 if(detmon_lg_config.exts >= 0)
662 if (detmon_lg_config.lamp_ok) {
663 skip_if(detmon_opt_lampcr(cur_fset, 0));
666 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
671 detmon_lg_config.exts,
673 recipe_name, pipeline_name, pafregexp,
674 pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff,
675 package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
677 for(j = 1; j <= nexts; j++) {
684 if (detmon_lg_config.lamp_ok) {
685 skip_if(detmon_opt_lampcr(cur_fset, j));
689 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
694 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));
699 cpl_frameset_delete(cur_fset);
700 cpl_frameset_delete(cur_fset_on);
701 cpl_frameset_delete(cur_fset_off);
704 cpl_free(exptime_on);
705 cpl_free(exptime_off);
706 return cpl_error_get_code();
784 detmon_lg(cpl_frameset * frameset,
785 const cpl_parameterlist * parlist,
787 const char * tag_off,
788 const char * recipe_name,
789 const char * pipeline_name,
790 const char * pafregexp,
791 const cpl_propertylist * pro_lintbl,
792 const cpl_propertylist * pro_gaintbl,
793 const cpl_propertylist * pro_coeffscube,
794 const cpl_propertylist * pro_bpm,
795 const cpl_propertylist * pro_corr,
796 const cpl_propertylist * pro_diff,
797 const char * package,
798 int (* compare) (
const cpl_frame *,
800 int (* load_fset) (
const cpl_frameset *,
803 const cpl_boolean opt_nir)
805 cpl_errorstate cleanstate = cpl_errorstate_get();
807 cpl_size * selection = NULL;
808 cpl_frame * first = NULL;
809 cpl_image * reference = NULL;
816 cpl_frameset * cur_fset = NULL;
817 cpl_frameset * cur_fset_on = NULL;
818 cpl_frameset * cur_fset_off = NULL;
821 cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
822 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
823 cpl_ensure_code(tag_on != NULL, CPL_ERROR_NULL_INPUT);
824 cpl_ensure_code(tag_off != NULL, CPL_ERROR_NULL_INPUT);
825 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
826 cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
827 cpl_ensure_code(pro_lintbl != NULL, CPL_ERROR_NULL_INPUT);
828 cpl_ensure_code(pro_gaintbl != NULL, CPL_ERROR_NULL_INPUT);
829 cpl_ensure_code(pro_coeffscube != NULL, CPL_ERROR_NULL_INPUT);
830 cpl_ensure_code(pro_bpm != NULL, CPL_ERROR_NULL_INPUT);
831 cpl_ensure_code(pro_corr != NULL, CPL_ERROR_NULL_INPUT);
832 cpl_ensure_code(pro_diff != NULL, CPL_ERROR_NULL_INPUT);
833 cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
835 cpl_msg_info(cpl_func,
"frameset size [%" CPL_SIZE_FORMAT
"]", cpl_frameset_get_size(frameset));
838 skip_if (detmon_lg_dfs_set_groups(frameset, tag_on, tag_off));
845 skip_if (detmon_lg_retrieve_parlist(pipeline_name, recipe_name,
853 first = cpl_frameset_get_first(frameset);
854 irplib_ensure (first != NULL, CPL_ERROR_ILLEGAL_INPUT,
"Empty data set! Provide %s and %s input frames",tag_on,tag_off);
856 detmon_lg_config.load_fset = load_fset;
857 detmon_lg_config.load_fset_wrp = load_fset ? irplib_load_fset_wrp_ext : irplib_load_fset_wrp;
860 detmon_lg_config.nb_extensions = 1;
861 if (detmon_lg_config.exts < 0) {
863 detmon_lg_config.nb_extensions = cpl_frame_get_nextensions(first);
864 while (reference == NULL && i <= detmon_lg_config.nb_extensions) {
865 reference = cpl_image_load(cpl_frame_get_filename(first),
866 CPL_TYPE_FLOAT, 0, i);
867 if (reference == NULL) {
868 cpl_msg_warning(cpl_func,
"Extension %d empty, skipping", i);
869 cpl_errorstate_set(cleanstate);
873 cpl_errorstate_set(cleanstate);
874 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
875 "No data found in any extension");
876 cpl_msg_info(cpl_func,
"Using extension %d as reference", i - 1);
878 if (load_fset != NULL) {
879 cpl_frameset *
new = cpl_frameset_new();
880 cpl_imagelist * p = cpl_imagelist_new();
881 cpl_frameset_insert(
new, cpl_frame_duplicate(first));
882 (*load_fset)(
new, CPL_TYPE_FLOAT, p);
883 reference = cpl_image_duplicate(cpl_imagelist_get(p, 0));
884 cpl_imagelist_delete(p);
885 cpl_frameset_delete(
new);
887 cpl_msg_info(cpl_func,
"name=%s",cpl_frame_get_filename(first));
888 reference = cpl_image_load(cpl_frame_get_filename(first),
889 CPL_TYPE_FLOAT, 0, detmon_lg_config.exts);
891 cpl_errorstate_set(cleanstate);
892 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
893 "No data found in requested extension %d",
894 detmon_lg_config.exts);
896 skip_if (reference == NULL);
898 skip_if (detmon_lg_check_defaults(reference));
907 if (compare == NULL) {
910 cpl_msg_info(cpl_func,
"Identifying different settings");
911 selection = cpl_frameset_labelise(frameset, compare, &nsets);
912 skip_if (selection == NULL);
916 for(
int i = 0; i < nsets; i++)
918 int fr_size = cpl_frameset_get_size(frameset);
920 cpl_msg_info(cpl_func,
"Reduce data set nb %d out of %" CPL_SIZE_FORMAT
"",
922 skip_if(detmon_lg_reduce_set(i, frameset, nsets, tag_on, tag_off,
937 fr_size_new = cpl_frameset_get_size(frameset);
943 if (fr_size_new > fr_size)
945 selection = cpl_realloc(selection, fr_size_new *
sizeof(selection[0]));
946 memset(selection + fr_size, -1, (fr_size_new - fr_size) *
sizeof(selection[0]));
952 cpl_frameset_delete(cur_fset);
953 cpl_frameset_delete(cur_fset_on);
954 cpl_frameset_delete(cur_fset_off);
956 cpl_image_delete(reference);
958 return cpl_error_get_code();
994 static cpl_error_code
995 detmon_lg_core(cpl_frameset * cur_fset_on,
996 cpl_frameset * cur_fset_off,
1000 double * exptime_off,
1003 const char * recipe_name,
1004 const char * pipeline_name,
1005 const char * pafregexp,
1006 const cpl_propertylist * pro_lintbl,
1007 const cpl_propertylist * pro_gaintbl,
1008 const cpl_propertylist * pro_coeffscube,
1009 const cpl_propertylist * pro_bpm,
1010 const cpl_propertylist * pro_corr,
1011 const cpl_propertylist * pro_diff,
1012 const char * package,
1013 int (* load_fset) (
const cpl_frameset *,
1016 int nsets, cpl_boolean opt_nir,
1017 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
1018 cpl_frameset * cur_fset)
1020 cpl_table * gain_table = cpl_table_new(
1021 cpl_frameset_get_size(cur_fset_on) / 2);
1022 cpl_table * linear_table = cpl_table_new(
1023 cpl_frameset_get_size(cur_fset_on) / 2);
1024 cpl_imagelist * coeffs = NULL;
1025 cpl_image * bpm = NULL;
1026 cpl_imagelist * autocorr_images = NULL;
1027 cpl_imagelist * diff_flats = NULL;
1028 cpl_propertylist * gaint_qclist = NULL;
1029 cpl_propertylist * lint_qclist = NULL;
1030 cpl_propertylist * linc_qclist = NULL;
1031 cpl_propertylist * bpm_qclist = NULL;
1033 int next_index_on = 0;
1034 int next_index_off = 0;
1037 cpl_msg_info(cpl_func,
"Reduce extension nb %d ", whichext);
1041 if (detmon_lg_config.intermediate) {
1042 autocorr_images = cpl_imagelist_new();
1043 diff_flats = cpl_imagelist_new();
1046 gaint_qclist = cpl_propertylist_new();
1047 lint_qclist = cpl_propertylist_new();
1048 linc_qclist = cpl_propertylist_new();
1049 bpm_qclist = cpl_propertylist_new();
1052 cpl_msg_info(cpl_func,
"Starting data reduction");
1053 if (detmon_lg_reduce(cur_fset_on, cur_fset_off,
1054 index_on, index_off, exptime_on, exptime_off,
1055 &next_index_on, &next_index_off,
1056 &coeffs, gain_table,
1057 linear_table, &bpm, autocorr_images,
1058 diff_flats, gaint_qclist, lint_qclist,
1059 linc_qclist, bpm_qclist, load_fset,
1060 opt_nir, whichext) == CPL_ERROR_CONTINUE) {
1061 cpl_msg_info(cpl_func,
"Empty extension %d", whichext);
1065 cpl_msg_info(cpl_func,
"Saving the products");
1068 detmon_lg_save(parlist, frameset, recipe_name,
1069 pipeline_name, pafregexp,
1070 pro_lintbl, pro_gaintbl,
1071 pro_coeffscube, pro_bpm,
1072 pro_corr, pro_diff, package,
1073 coeffs, gain_table, linear_table,
1074 bpm, autocorr_images, diff_flats,
1075 gaint_qclist, lint_qclist, linc_qclist,
1076 bpm_qclist, 0, 0, cur_fset, whichext));
1079 detmon_lg_save(parlist, frameset, recipe_name,
1080 pipeline_name, pafregexp,
1081 pro_lintbl, pro_gaintbl,
1082 pro_coeffscube, pro_bpm,
1083 pro_corr, pro_diff, package,
1084 coeffs, gain_table, linear_table,
1085 bpm, autocorr_images, diff_flats,
1086 gaint_qclist, lint_qclist, linc_qclist,
1087 bpm_qclist, 1, whichset+ 1, cur_fset,
1095 cpl_table_delete(gain_table);
1096 cpl_table_delete(linear_table);
1097 cpl_imagelist_delete(coeffs);
1098 cpl_propertylist_delete(gaint_qclist);
1099 cpl_propertylist_delete(lint_qclist);
1100 cpl_propertylist_delete(linc_qclist);
1101 if(bpm_qclist != NULL) cpl_propertylist_delete(bpm_qclist);
1102 cpl_image_delete(bpm);
1103 cpl_imagelist_delete(autocorr_images);
1104 cpl_imagelist_delete(diff_flats);
1106 return cpl_error_get_code();
1131 detmon_image_correlate(
const cpl_image * image1,
1132 const cpl_image * image2,
1133 const int m,
const int n)
1135 cpl_image *image1_padded = NULL;
1136 cpl_image *image2_padded = NULL;
1140 cpl_image *corr_image_window = NULL;
1142 cpl_image* image_ri1 = NULL;
1143 cpl_image* image_ri2 = NULL;
1144 cpl_error_code err = CPL_ERROR_NONE;
1147 cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1148 cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1150 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1151 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1153 nx = cpl_image_get_size_x(image1);
1154 ny = cpl_image_get_size_y(image1);
1156 nx2 = cpl_image_get_size_x(image2);
1157 ny2 = cpl_image_get_size_y(image2);
1160 cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
1163 image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1164 cpl_image_copy(image1_padded, image1, m + 1, n + 1);
1166 image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1167 cpl_image_copy(image2_padded, image2, m + 1, n + 1);
1173 image_ri1 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
1174 image_ri2 = cpl_image_new(nx, ny , CPL_TYPE_FLOAT_COMPLEX);
1176 cpl_fft_image(image_ri1, image1_padded, CPL_FFT_FORWARD);
1177 cpl_fft_image(image_ri2, image2_padded, CPL_FFT_FORWARD);
1178 err = cpl_error_get_code();
1179 cpl_image_delete(image1_padded);
1180 image1_padded = NULL;
1181 cpl_image_delete(image2_padded);
1182 image2_padded = NULL;
1183 if (err == CPL_ERROR_NONE)
1186 cpl_image * corr_image = NULL;
1187 cpl_image * reorganised= NULL;
1188 cpl_image * image_ri_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1189 cpl_image * image_in_inv = cpl_image_new(nx, ny,
1190 CPL_TYPE_FLOAT_COMPLEX);
1193 for (i = 1; i <= nx; i++)
1195 for (j = 1; j <= ny; j++)
1198 double complex value1, value2, value;
1199 value1 = cpl_image_get_complex(image_ri1, i, j, &rej);
1200 value2 = cpl_image_get_complex(image_ri2, i, j, &rej);;
1201 value = conj(value1) * value2;
1202 cpl_image_set_complex(image_in_inv, i, j, value);
1205 cpl_image_delete(image_ri1);
1207 cpl_image_delete(image_ri2);
1210 err = cpl_error_get_code();
1211 if (err == CPL_ERROR_NONE)
1215 cpl_fft_image(image_ri_inv, image_in_inv,CPL_FFT_BACKWARD);
1216 cpl_image_delete(image_in_inv);
1219 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1220 for (i = 1; i <= nx; i++)
1222 for (j = 1; j <= ny; j++)
1226 value = cpl_image_get(image_ri_inv, i, j, &rej);
1227 cpl_image_set(corr_image, i, j, value);
1230 cpl_image_delete(image_ri_inv);
1231 err = cpl_error_get_code();
1232 if (err == CPL_ERROR_NONE)
1236 cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
1237 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1239 cpl_image_copy(reorganised, image, 1, 1);
1240 cpl_image_delete(image);
1241 image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
1242 cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
1243 cpl_image_delete(image);
1245 cpl_image_delete(corr_image);
1247 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1248 image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
1249 cpl_image_copy(corr_image, image, 1, 1);
1250 cpl_image_delete(image);
1252 image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
1253 cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
1254 cpl_image_delete(image);
1256 corr_image_window = cpl_image_extract(corr_image,
1259 nx / 2 + 1 + m, ny / 2 + 1 + n);
1264 cpl_image_delete(reorganised);
1265 cpl_image_delete(corr_image);
1267 if(cpl_image_divide_scalar(corr_image_window,
1268 cpl_image_get_max(corr_image_window))) {
1269 cpl_image_delete(corr_image_window);
1273 cpl_image_delete (image_ri1);
1274 cpl_image_delete (image_ri2);
1275 cpl_image_delete (image1_padded);
1276 cpl_image_delete (image2_padded);
1277 return corr_image_window;
1300 detmon_autocorrelate(
const cpl_image * input2,
const int m,
1303 cpl_image *im_re = NULL;
1304 cpl_image *im_im = NULL;
1306 cpl_image *ifft_re = NULL;
1307 cpl_image *ifft_im = NULL;
1308 cpl_image *autocorr = NULL;
1309 cpl_image *autocorr_norm_double = NULL;
1310 cpl_image *autocorr_norm = NULL;
1311 cpl_image *reorganised = NULL;
1312 cpl_image *image = NULL;
1314 cpl_error_code error;
1317 cpl_ensure(input2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1319 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1320 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1322 nx = cpl_image_get_size_x(input2) + 2 * m;
1323 ny = cpl_image_get_size_y(input2) + 2 * n;
1326 while(nx > p || ny > p) {
1330 input = cpl_image_cast(input2, CPL_TYPE_DOUBLE);
1332 im_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1333 error = cpl_image_copy(im_re, input, 1, 1);
1334 cpl_ensure(!error, error, NULL);
1336 im_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1338 error = cpl_image_fft(im_re, im_im, CPL_FFT_DEFAULT);
1339 cpl_ensure(!error, error, NULL);
1341 ifft_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1342 error = cpl_image_power(im_re, 2);
1343 cpl_ensure(!error, error, NULL);
1345 error = cpl_image_add(ifft_re, im_re);
1346 cpl_ensure(!error, error, NULL);
1348 cpl_image_delete(im_re);
1350 error = cpl_image_power(im_im, 2);
1351 cpl_ensure(!error, error, NULL);
1353 error = cpl_image_add(ifft_re, im_im);
1354 cpl_ensure(!error, error, NULL);
1356 cpl_image_delete(im_im);
1358 ifft_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1360 error = cpl_image_fft(ifft_re, ifft_im, CPL_FFT_INVERSE);
1361 cpl_ensure(!error, error, NULL);
1363 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1365 error = cpl_image_power(ifft_re, 2);
1366 cpl_ensure(!error, error, NULL);
1368 error = cpl_image_add(autocorr, ifft_re);
1369 cpl_ensure(!error, error, NULL);
1371 cpl_image_delete(ifft_re);
1373 error = cpl_image_power(ifft_im, 2);
1374 cpl_ensure(!error, error, NULL);
1376 error = cpl_image_add(autocorr, ifft_im);
1377 cpl_ensure(!error, error, NULL);
1379 cpl_image_delete(ifft_im);
1382 reorganised = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1384 image = cpl_image_extract(autocorr, p / 2 + 1, 1, p, p);
1385 cpl_image_copy(reorganised, image, 1, 1);
1386 cpl_image_delete(image);
1388 image = cpl_image_extract(autocorr, 1, 1, p / 2, p);
1389 cpl_image_copy(reorganised, image, p / 2 + 1, 1);
1390 cpl_image_delete(image);
1392 cpl_image_delete(autocorr);
1394 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1396 image = cpl_image_extract(reorganised, 1, p / 2 + 1, p, p);
1397 cpl_image_copy(autocorr, image, 1, 1);
1398 cpl_image_delete(image);
1400 image = cpl_image_extract(reorganised, 1, 1, p, p / 2);
1401 cpl_image_copy(autocorr, image, 1, p / 2 + 1);
1402 cpl_image_delete(image);
1404 cpl_image_delete(reorganised);
1406 autocorr_norm_double =
1407 cpl_image_extract(autocorr, p / 2 + 1 - m, p / 2 + 1 - n,
1408 p / 2 + 1 + m, p / 2 + 1 + n);
1410 cpl_image_delete(autocorr);
1412 if(cpl_image_divide_scalar(autocorr_norm_double,
1413 cpl_image_get_max(autocorr_norm_double))) {
1414 cpl_image_delete(autocorr_norm_double);
1415 cpl_ensure(0, cpl_error_get_code(), NULL);
1419 autocorr_norm = cpl_image_cast(autocorr_norm_double, CPL_TYPE_FLOAT);
1420 cpl_image_delete(autocorr_norm_double);
1422 cpl_image_delete(input);
1424 return autocorr_norm;
1440 detmon_lg_fill_parlist_nir_default(cpl_parameterlist * parlist,
1441 const char *recipe_name,
1442 const char *pipeline_name)
1444 const cpl_error_code error =
1445 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1491 cpl_ensure_code(!error, error);
1493 return cpl_error_get_code();
1509 detmon_lg_fill_parlist_opt_default(cpl_parameterlist * parlist,
1510 const char *recipe_name,
1511 const char *pipeline_name)
1513 const cpl_error_code error =
1514 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1559 cpl_ensure_code(!error, error);
1561 return cpl_error_get_code();
1565 detmon_lg_fill_parlist_default_mr(cpl_parameterlist * parlist,
1566 const char *recipe_name,
1567 const char *pipeline_name)
1569 char * group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1570 char * par_name = cpl_sprintf(
"%s.%s", group_name,
"regions-file");
1571 cpl_parameter * p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1572 "File containing regions, "
1573 "four comma separated points "
1576 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions-file");
1577 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1578 cpl_parameterlist_append(parlist, p);
1580 cpl_free(group_name);
1582 group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1583 par_name = cpl_sprintf(
"%s.%s", group_name,
"regions");
1584 p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1585 "Colon separated list of regions, four "
1586 "points each, comma separated: "
1587 "llx,lly,urx,ury:llx,...",
1589 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions");
1590 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1591 cpl_parameterlist_append(parlist, p);
1593 cpl_free(group_name);
1595 return cpl_error_get_code();
1599 detmon_lg_fill_parlist_opt_default_mr(cpl_parameterlist * parlist,
1600 const char *recipe_name,
1601 const char *pipeline_name)
1603 detmon_lg_fill_parlist_opt_default(parlist, recipe_name, pipeline_name);
1604 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1605 return cpl_error_get_code();
1609 detmon_lg_fill_parlist_nir_default_mr(cpl_parameterlist * parlist,
1610 const char *recipe_name,
1611 const char *pipeline_name)
1613 detmon_lg_fill_parlist_nir_default(parlist, recipe_name, pipeline_name);
1614 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1616 return cpl_error_get_code();
1676 detmon_lg_fill_parlist(cpl_parameterlist * parlist,
1677 const char *recipe_name,
const char *pipeline_name,
1687 const char *intermediate,
1688 const char *autocorr,
1689 const char *collapse,
1690 const char *rescale,
1691 const char *pix2pix,
1698 const char * pafname,
1715 int llx5,
int lly5,
int urx5,
int ury5,
int exts,
1716 cpl_boolean opt_nir)
1718 const cpl_error_code error =
1719 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 25,
1721 "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
1722 "CPL_TYPE_STRING", method,
1725 "Polynomial order for the fit (Linearity)",
1726 "CPL_TYPE_INT", order,
1728 "Kappa value for the kappa-sigma clipping (Gain)",
1729 "CPL_TYPE_DOUBLE", kappa,
1731 "Number of iterations to compute rms (Gain)",
1732 "CPL_TYPE_INT", niter,
1734 "x coordinate of the lower-left "
1735 "point of the region of interest. If not modified, default value will be 1.",
1736 "CPL_TYPE_INT", llx,
1738 "y coordinate of the lower-left "
1739 "point of the region of interest. If not modified, default value will be 1.",
1740 "CPL_TYPE_INT", lly,
1742 "x coordinate of the upper-right "
1743 "point of the region of interest. If not modified, default value will be X dimension of the input image.",
1744 "CPL_TYPE_INT", urx,
1746 "y coordinate of the upper-right "
1747 "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
1748 "CPL_TYPE_INT", ury,
1750 "User reference level",
1751 "CPL_TYPE_INT", ref_level,
1753 "De-/Activate intermediate products",
1754 "CPL_TYPE_BOOL", intermediate,
1757 "De-/Activate the autocorr option",
1758 "CPL_TYPE_BOOL", autocorr,
1761 "De-/Activate the collapse option",
1762 "CPL_TYPE_BOOL", collapse,
1764 "De-/Activate the image rescale option",
1765 "CPL_TYPE_BOOL", rescale,
1767 "De-/Activate the computation with pixel to pixel accuracy",
1768 "CPL_TYPE_BOOL", pix2pix,
1770 "De-/Activate the binary bpm option",
1771 "CPL_TYPE_BOOL", bpmbin,
1773 "Maximum x-shift for the autocorr",
1776 "Upper limit of Median flux to be filtered",
1777 "CPL_TYPE_INT", filter,
1779 "Maximum y-shift for the autocorr",
1782 "Tolerance for pair discrimination",
1783 "CPL_TYPE_DOUBLE", tolerance,
1786 "Generate PAF file",
1787 "CPL_TYPE_BOOL", pafgen,
1789 "Specific name for PAF file",
1790 "CPL_TYPE_STRING", pafname,
1794 "Activate the multi-exts option. Choose -1 to process all extensions. Choose an extension number"
1795 " to process the appropriate extension.",
1796 "CPL_TYPE_INT", exts,
1799 "Method for computing Fixed Pattern Noise (SMOOTH or HISTOGRAM)",
1800 "CPL_TYPE_STRING",
"HISTOGRAM",
1803 "template size in pixels for smoothing during FPN computation (only for SMOOTH method)",
1807 "all frames with mean saturation above the limit would not be used in calculation",
1808 "CPL_TYPE_DOUBLE", 65535.0
1811 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 1,
1812 "coeffs_cube_split",
1813 "if TRUE, the recipe writes as many "
1814 "COEFFS_CUBE_Pi (i=0..order) as the value of "
1815 "the order parameter in a separate file",
1816 "CPL_TYPE_BOOL",
"CPL_FALSE");
1818 if(opt_nir == FALSE) {
1819 const cpl_error_code erroropt =
1820 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
1822 "x coord of the lower-left point of the first "
1823 "field used for contamination measurement. If not modified, default value will be 1.",
1824 "CPL_TYPE_INT", llx1,
1826 "y coord of the lower-left point of the first "
1827 "field used for contamination measurement. If not modified, default value will be 1.",
1828 "CPL_TYPE_INT", lly1,
1830 "x coord of the upper-right point of the first "
1831 "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
1832 "CPL_TYPE_INT", urx1,
1834 "y coord of the upper-right point of the first "
1835 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1836 "CPL_TYPE_INT", ury1,
1838 "x coord of the lower-left point of the second "
1839 "field used for contamination measurement. If not modified, default value will be 1.",
1840 "CPL_TYPE_INT", llx2,
1842 "y coord of the lower-left point of the second "
1843 "field used for contamination measurement. If not modified, default value will be 1.",
1844 "CPL_TYPE_INT", lly2,
1846 "x coord of the upper-right point of the second "
1847 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1848 "CPL_TYPE_INT", urx2,
1850 "y coord of the upper-right point of the second "
1851 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1852 "CPL_TYPE_INT", ury2,
1854 "x coord of the lower-left point of the third "
1855 "field used for contamination measurement. If not modified, default value will be 1.",
1856 "CPL_TYPE_INT", llx3,
1858 "y coord of the lower-left point of the third "
1859 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1860 "CPL_TYPE_INT", lly3,
1862 "x coord of the upper-right point of the third "
1863 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1864 "CPL_TYPE_INT", urx3,
1866 "y coord of the upper-right point of the third "
1867 "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
1868 "CPL_TYPE_INT", ury3,
1870 "x coord of the lower-left point of the fourth "
1871 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1872 "CPL_TYPE_INT", llx4,
1874 "y coord of the lower-left point of the fourth "
1875 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1876 "CPL_TYPE_INT", lly4,
1878 "x coord of the upper-right point of the fourth "
1879 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1880 "CPL_TYPE_INT", urx4,
1882 "y coord of the upper-right point of the fourth "
1883 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1884 "CPL_TYPE_INT", ury4,
1886 "x coord of the lower-left point of the fifth "
1887 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1888 "CPL_TYPE_INT", llx5,
1890 "y coord of the lower-left point of the fifth "
1891 "field used for contamination measurement. If not modified, default value will be 1.",
1892 "CPL_TYPE_INT", lly5,
1894 "x coord of the upper-right point of the fifth "
1895 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1896 "CPL_TYPE_INT", urx5,
1899 "y coord of the upper-right point of the fifth "
1900 "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
1901 "CPL_TYPE_INT", ury5);
1904 cpl_ensure_code(!erroropt, erroropt);
1907 cpl_ensure_code(!error, error);
1909 return cpl_error_get_code();
1922 static cpl_error_code
1923 detmon_lg_retrieve_parlist(
const char * pipeline_name,
1924 const char * recipe_name,
1925 const cpl_parameterlist * parlist,
1926 cpl_boolean opt_nir)
1930 cpl_parameter * par;
1933 par_name = cpl_sprintf(
"%s.%s.method", pipeline_name, recipe_name);
1934 assert(par_name != NULL);
1935 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1936 detmon_lg_config.method = cpl_parameter_get_string(par);
1940 detmon_lg_config.order =
1941 detmon_retrieve_par_int(
"order", pipeline_name, recipe_name,
1945 detmon_lg_config.kappa =
1946 detmon_retrieve_par_double(
"kappa", pipeline_name, recipe_name,
1950 detmon_lg_config.niter =
1951 detmon_retrieve_par_int(
"niter", pipeline_name, recipe_name,
1955 detmon_lg_config.llx =
1956 detmon_retrieve_par_int(
"llx", pipeline_name, recipe_name,
1960 detmon_lg_config.lly =
1961 detmon_retrieve_par_int(
"lly", pipeline_name, recipe_name,
1965 detmon_lg_config.urx =
1966 detmon_retrieve_par_int(
"urx", pipeline_name, recipe_name,
1970 detmon_lg_config.ury =
1971 detmon_retrieve_par_int(
"ury", pipeline_name, recipe_name,
1975 detmon_lg_config.ref_level =
1976 detmon_retrieve_par_int(
"ref_level", pipeline_name, recipe_name,
1981 cpl_sprintf(
"%s.%s.intermediate", pipeline_name, recipe_name);
1982 assert(par_name != NULL);
1983 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1984 detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
1988 par_name = cpl_sprintf(
"%s.%s.autocorr", pipeline_name, recipe_name);
1989 assert(par_name != NULL);
1990 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1991 detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
1995 par_name = cpl_sprintf(
"%s.%s.coeffs_cube_split", pipeline_name, recipe_name);
1996 assert(par_name != NULL);
1997 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1998 detmon_lg_config.split_coeffs = cpl_parameter_get_bool(par);
2002 par_name = cpl_sprintf(
"%s.%s.collapse", pipeline_name, recipe_name);
2003 assert(par_name != NULL);
2004 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2005 detmon_lg_config.collapse = cpl_parameter_get_bool(par);
2009 par_name = cpl_sprintf(
"%s.%s.rescale", pipeline_name, recipe_name);
2010 assert(par_name != NULL);
2011 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2012 detmon_lg_config.rescale = cpl_parameter_get_bool(par);
2016 par_name = cpl_sprintf(
"%s.%s.pix2pix", pipeline_name, recipe_name);
2017 assert(par_name != NULL);
2018 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2019 detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
2023 par_name = cpl_sprintf(
"%s.%s.bpmbin", pipeline_name, recipe_name);
2024 assert(par_name != NULL);
2025 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2026 detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
2030 detmon_lg_config.filter =
2031 detmon_retrieve_par_int(
"filter", pipeline_name,
2032 recipe_name, parlist);
2035 detmon_lg_config.m =
2036 detmon_retrieve_par_int(
"m", pipeline_name, recipe_name, parlist);
2039 detmon_lg_config.n =
2040 detmon_retrieve_par_int(
"n", pipeline_name, recipe_name, parlist);
2043 par_name = cpl_sprintf(
"%s.%s.tolerance", pipeline_name, recipe_name);
2044 assert(par_name != NULL);
2045 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2046 detmon_lg_config.tolerance = cpl_parameter_get_double(par);
2051 par_name = cpl_sprintf(
"%s.%s.pafgen", pipeline_name, recipe_name);
2052 assert(par_name != NULL);
2053 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2054 detmon_lg_config.pafgen = cpl_parameter_get_bool(par);
2058 par_name = cpl_sprintf(
"%s.%s.pafname", pipeline_name, recipe_name);
2059 assert(par_name != NULL);
2060 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2061 detmon_lg_config.pafname = cpl_parameter_get_string(par);
2064 if(opt_nir == OPT) {
2066 detmon_lg_config.llx1 =
2067 detmon_retrieve_par_int(
"llx1", pipeline_name, recipe_name,
2071 detmon_lg_config.lly1 =
2072 detmon_retrieve_par_int(
"lly1", pipeline_name, recipe_name,
2076 detmon_lg_config.urx1 =
2077 detmon_retrieve_par_int(
"urx1", pipeline_name, recipe_name,
2081 detmon_lg_config.ury1 =
2082 detmon_retrieve_par_int(
"ury1", pipeline_name, recipe_name,
2086 detmon_lg_config.llx2 =
2087 detmon_retrieve_par_int(
"llx2", pipeline_name, recipe_name,
2091 detmon_lg_config.lly2 =
2092 detmon_retrieve_par_int(
"lly2", pipeline_name, recipe_name,
2096 detmon_lg_config.urx2 =
2097 detmon_retrieve_par_int(
"urx2", pipeline_name, recipe_name,
2101 detmon_lg_config.ury2 =
2102 detmon_retrieve_par_int(
"ury2", pipeline_name, recipe_name,
2106 detmon_lg_config.llx3 =
2107 detmon_retrieve_par_int(
"llx3", pipeline_name, recipe_name,
2111 detmon_lg_config.lly3 =
2112 detmon_retrieve_par_int(
"lly3", pipeline_name, recipe_name,
2116 detmon_lg_config.urx3 =
2117 detmon_retrieve_par_int(
"urx3", pipeline_name, recipe_name,
2121 detmon_lg_config.ury3 =
2122 detmon_retrieve_par_int(
"ury3", pipeline_name, recipe_name,
2126 detmon_lg_config.llx4 =
2127 detmon_retrieve_par_int(
"llx4", pipeline_name, recipe_name,
2131 detmon_lg_config.lly4 =
2132 detmon_retrieve_par_int(
"lly4", pipeline_name, recipe_name,
2136 detmon_lg_config.urx4 =
2137 detmon_retrieve_par_int(
"urx4", pipeline_name, recipe_name,
2141 detmon_lg_config.ury4 =
2142 detmon_retrieve_par_int(
"ury4", pipeline_name, recipe_name,
2146 detmon_lg_config.llx5 =
2147 detmon_retrieve_par_int(
"llx5", pipeline_name, recipe_name,
2151 detmon_lg_config.lly5 =
2152 detmon_retrieve_par_int(
"lly5", pipeline_name, recipe_name,
2156 detmon_lg_config.urx5 =
2157 detmon_retrieve_par_int(
"urx5", pipeline_name, recipe_name,
2161 detmon_lg_config.ury5 =
2162 detmon_retrieve_par_int(
"ury5", pipeline_name, recipe_name,
2167 detmon_lg_config.exts =
2168 detmon_retrieve_par_int(
"exts", pipeline_name, recipe_name,
2172 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2174 cpl_sprintf(
"%s.%s.fpn_method", pipeline_name, recipe_name);
2175 assert(par_name != NULL);
2176 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2179 const char * str_method = cpl_parameter_get_string(par);
2180 if (strcmp(str_method,
"SMOOTH") == 0)
2182 detmon_lg_config.fpn_method = FPN_SMOOTH;
2184 else if (strcmp(str_method,
"HISTOGRAM") == 0)
2186 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2192 detmon_lg_config.fpn_smooth =
2193 detmon_retrieve_par_int(
"fpn_smooth", pipeline_name, recipe_name,
2197 detmon_lg_config.saturation_limit = 65535;
2199 cpl_sprintf(
"%s.%s.saturation_limit", pipeline_name, recipe_name);
2200 assert(par_name != NULL);
2201 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2204 detmon_lg_config.saturation_limit = cpl_parameter_get_double(par);
2210 if(cpl_error_get_code())
2212 cpl_msg_error(cpl_func,
"Failed to retrieve the input parameters");
2213 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
2217 return cpl_error_get_code();
2227 static cpl_error_code
2228 detmon_lg_check_defaults(
const cpl_image * reference)
2230 const int nx = cpl_image_get_size_x(reference);
2231 const int ny = cpl_image_get_size_y(reference);
2233 detmon_lg_config.nx = nx;
2234 detmon_lg_config.ny = ny;
2236 detmon_lg_config.wholechip = CPL_FALSE;
2238 if(detmon_lg_config.llx == -1)
2239 detmon_lg_config.llx = 1;
2240 if(detmon_lg_config.lly == -1)
2241 detmon_lg_config.lly = 1;
2242 if(detmon_lg_config.urx == -1)
2243 detmon_lg_config.urx = nx;
2244 if(detmon_lg_config.ury == -1)
2245 detmon_lg_config.ury = ny;
2247 if (detmon_lg_config.llx == 1 &&
2248 detmon_lg_config.lly == 1 &&
2249 detmon_lg_config.urx == nx &&
2250 detmon_lg_config.ury == ny)
2251 detmon_lg_config.wholechip = CPL_TRUE;
2253 if(detmon_lg_config.llx1 == -1)
2254 detmon_lg_config.llx1 = 1;
2255 if(detmon_lg_config.lly1 == -1)
2256 detmon_lg_config.lly1 = 1;
2257 if(detmon_lg_config.urx1 == -1)
2258 detmon_lg_config.urx1 = nx;
2259 if(detmon_lg_config.ury1 == -1)
2260 detmon_lg_config.ury1 = ny;
2262 if(detmon_lg_config.llx2 == -1)
2263 detmon_lg_config.llx2 = 1;
2264 if(detmon_lg_config.lly2 == -1)
2265 detmon_lg_config.lly2 = 1;
2266 if(detmon_lg_config.urx2 == -1)
2267 detmon_lg_config.urx2 = nx / 2;
2268 if(detmon_lg_config.ury2 == -1)
2269 detmon_lg_config.ury2 = ny / 2;
2271 if(detmon_lg_config.llx3 == -1)
2272 detmon_lg_config.llx3 = 1;
2273 if(detmon_lg_config.lly3 == -1)
2274 detmon_lg_config.lly3 = ny / 2;
2275 if(detmon_lg_config.urx3 == -1)
2276 detmon_lg_config.urx3 = nx / 2;
2277 if(detmon_lg_config.ury3 == -1)
2278 detmon_lg_config.ury3 = ny;
2280 if(detmon_lg_config.llx4 == -1)
2281 detmon_lg_config.llx4 = nx / 2;
2282 if(detmon_lg_config.lly4 == -1)
2283 detmon_lg_config.lly4 = ny / 2;
2284 if(detmon_lg_config.urx4 == -1)
2285 detmon_lg_config.urx4 = nx;
2286 if(detmon_lg_config.ury4 == -1)
2287 detmon_lg_config.ury4 = ny;
2289 if(detmon_lg_config.llx5 == -1)
2290 detmon_lg_config.llx5 = nx / 2;
2291 if(detmon_lg_config.lly5 == -1)
2292 detmon_lg_config.lly5 = 1;
2293 if(detmon_lg_config.urx5 == -1)
2294 detmon_lg_config.urx5 = nx;
2295 if(detmon_lg_config.ury5 == -1)
2296 detmon_lg_config.ury5 = ny / 2;
2298 if(detmon_lg_config.intermediate == TRUE) {
2299 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.");
2300 detmon_lg_config.autocorr = TRUE;
2304 detmon_lg_config.lamp_stability = 0.0;
2306 detmon_lg_config.lamp_ok = FALSE;
2308 detmon_lg_config.cr = 0.0;
2310 return cpl_error_get_code();
2325 static cpl_error_code
2326 detmon_lg_split_onoff(
const cpl_frameset * cur_fset,
2327 cpl_frameset * cur_fset_on,
2328 cpl_frameset * cur_fset_off,
2330 const char *tag_off)
2335 cpl_frame * cur_frame_dup = NULL;
2338 const cpl_frame * first;
2339 const cpl_frame * second;
2340 const char * first_tag;
2341 const char * second_tag;
2342 skip_if((first = cpl_frameset_get_first_const(cur_fset)) == NULL);
2343 skip_if((second = cpl_frameset_get_next_const (cur_fset)) == NULL);
2345 skip_if((first_tag = cpl_frame_get_tag(first)) == NULL);
2346 skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
2347 if (opt_nir == OPT &&
2348 ((!strcmp(first_tag, tag_on ) && !strcmp(second_tag, tag_off)) ||
2349 (!strcmp(first_tag, tag_off) && !strcmp(second_tag, tag_on )))) {
2350 detmon_lg_config.lamp_ok = TRUE;
2354 nframes = cpl_frameset_get_size(cur_fset);
2355 for(i = detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
2356 const cpl_frame * cur_frame =
2357 cpl_frameset_get_position_const(cur_fset, i);
2361 cur_frame_dup = cpl_frame_duplicate(cur_frame);
2362 tag = (
char *) cpl_frame_get_tag(cur_frame_dup);
2365 if(!strcmp(tag, tag_on)) {
2366 skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
2367 }
else if(!strcmp(tag, tag_off)) {
2368 skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
2370 cpl_frame_delete(cur_frame_dup);
2371 cur_frame_dup = NULL;
2374 cur_frame_dup = NULL;
2378 cpl_frame_delete(cur_frame_dup);
2380 return cpl_error_get_code();
2407 static cpl_error_code
2408 detmon_lg_reduce(
const cpl_frameset * set_on,
2409 const cpl_frameset * set_off,
2410 int* index_on,
int* index_off,
2411 double* exptime_on,
double* exptime_off,
2412 int *next_index_on,
int* next_index_off,
2413 cpl_imagelist ** coeffs_ptr,
2414 cpl_table * gain_table,
2415 cpl_table * linear_table,
2416 cpl_image ** bpm_ptr,
2417 cpl_imagelist * autocorr_images,
2418 cpl_imagelist * diff_flats,
2419 cpl_propertylist * gaint_qclist,
2420 cpl_propertylist * lint_qclist,
2421 cpl_propertylist * linc_qclist,
2422 cpl_propertylist * bpm_qclist,
2423 int (* load_fset) (
const cpl_frameset *,
2426 const cpl_boolean opt_nir,
2429 cpl_errorstate prestate = cpl_errorstate_get();
2430 const double D_INVALID_VALUE = -999;
2432 cpl_imagelist * linearity_inputs = NULL;
2433 cpl_imagelist * opt_offs = NULL;
2435 cpl_propertylist * reflist = NULL;
2437 int rows_affected = 1;
2440 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2441 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2443 nsets = cpl_frameset_get_size(set_on) / 2;
2445 detmon_lg_config.load_fset = load_fset;
2446 if(detmon_lg_config.collapse) {
2453 const cpl_frame *first = cpl_frameset_get_first_const(set_off);
2454 cpl_frame *dup_first = cpl_frame_duplicate(first);
2456 const cpl_frame *second = cpl_frameset_get_next_const(set_off);
2457 cpl_frame *dup_second = cpl_frame_duplicate(second);
2459 cpl_frameset *raw_offs = cpl_frameset_new();
2461 skip_if(cpl_frameset_insert(raw_offs, dup_first));
2462 skip_if(cpl_frameset_insert(raw_offs, dup_second));
2464 opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
2467 cpl_frameset_delete(raw_offs);
2468 if (opt_offs == NULL) {
2469 cpl_errorstate_set(prestate);
2470 return CPL_ERROR_CONTINUE;
2474 skip_if(detmon_lg_reduce_init(gain_table,
2486 if(detmon_lg_lamp_stab(set_on, set_off,
2487 opt_nir, whichext)) {
2488 cpl_errorstate_set(prestate);
2491 if(!detmon_lg_config.collapse)
2495 skip_if(cpl_table_unselect_all(linear_table));
2496 skip_if(cpl_table_unselect_all(gain_table));
2500 for(i = 0; i < nsets ; i++)
2502 skip_if(detmon_lg_reduce_dit(set_on,
2503 index_on, exptime_on,
2507 index_off, exptime_off,
2508 next_index_on, next_index_off,
2510 gain_table, linearity_inputs,
2511 lint_qclist, opt_nir,
2512 autocorr_images, diff_flats,
2515 if (rows_affected == 0)
2517 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2518 "into calculation, check the messages above");
2519 cpl_table_select_row(linear_table, i);
2520 cpl_table_select_row(gain_table, i);
2527 skip_if(detmon_add_adl_column(linear_table, opt_nir));
2533 skip_if(cpl_table_erase_selected(gain_table));
2534 skip_if(cpl_table_erase_selected(linear_table));
2536 reflist = cpl_propertylist_new();
2537 skip_if(cpl_propertylist_append_bool(reflist,
"ADU", FALSE));
2538 skip_if(cpl_table_sort(gain_table, reflist));
2544 skip_if(detmon_lg_reduce_all(linear_table,
2545 gaint_qclist, lint_qclist, linc_qclist,
2546 bpm_qclist, coeffs_ptr, bpm_ptr,
2548 gain_table, whichext, opt_nir));
2551 double gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
2554 cpl_error_code cplerr = cpl_error_get_code();
2555 if (cplerr != CPL_ERROR_NONE || (gain == 0.0))
2557 cpl_msg_warning(cpl_func,
"Cannot read gain from QC parameters - "
2558 "FPN will not be computed");
2563 detmon_fpn_compute(set_on, index_on, last_best, lint_qclist,
2564 detmon_lg_config.llx,
2565 detmon_lg_config.lly,
2566 detmon_lg_config.urx,
2567 detmon_lg_config.ury,
2570 detmon_lg_config.fpn_method,
2571 detmon_lg_config.fpn_smooth);
2576 detmon_table_fill_invalid(gain_table, D_INVALID_VALUE);
2578 cpl_imagelist_delete(linearity_inputs);
2579 cpl_imagelist_delete(opt_offs);
2580 cpl_propertylist_delete(reflist);
2582 return cpl_error_get_code();
2585 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code)
2587 int ncols = cpl_table_get_ncol(ptable);
2588 cpl_array* pnames = cpl_table_get_column_names(ptable);
2589 int nrows = cpl_table_get_nrow(ptable);
2591 for (i=0; i < ncols; i++)
2594 for (j = 0; j< nrows; j++)
2596 const char* colname = cpl_array_get_data_string_const(pnames)[i];
2598 cpl_type type = cpl_table_get_column_type(ptable, colname);
2599 cpl_table_get(ptable, colname, j, &isnull);
2602 if (type == CPL_TYPE_DOUBLE)
2604 cpl_table_set(ptable,colname,j, code);
2606 else if (type == CPL_TYPE_FLOAT)
2608 cpl_table_set_float(ptable,colname,j, (
float)code);
2613 cpl_array_delete(pnames);
2614 return cpl_error_get_code();
2617 static cpl_error_code
2618 detmon_fpn_compute(
const cpl_frameset *set_on,
2621 cpl_propertylist *lint_qclist,
2628 FPN_METHOD fpn_method,
2632 const cpl_image* im1 = 0;
2634 cpl_imagelist* ons = 0;
2635 cpl_frameset * pair_on = 0;
2636 int nsets_extracted = cpl_frameset_get_size(set_on);
2637 cpl_size * selection = NULL;
2646 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
2647 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
2649 selection[index_on[last_best*2 + 0] ] = 1;
2650 selection[index_on[last_best*2 + 1] ] = 1;
2651 pair_on = cpl_frameset_extract(set_on, selection, 1);
2652 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2654 skip_if(ons == NULL);
2655 skip_if((im1 = cpl_imagelist_get_const(ons, 0)) == NULL);
2657 fpn = irplib_fpn_lg(im1, range, gain, fpn_method, smooth_size, &mse);
2658 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_FPN,
2660 skip_if(cpl_propertylist_append_double(lint_qclist,
"ESO QC GAIN ERR",
2664 cpl_frameset_delete(pair_on);
2665 cpl_imagelist_delete(ons);
2666 cpl_free(selection);
2667 return cpl_error_get_code();
2679 static cpl_error_code
2680 detmon_lg_lamp_stab(
const cpl_frameset * lamps,
2681 const cpl_frameset * darks,
2682 cpl_boolean opt_nir,
2695 cpl_vector * selection = NULL;
2696 cpl_propertylist * plist;
2697 double dit_lamp, dit_dark;
2699 cpl_imagelist * lamps_data = NULL;
2700 cpl_imagelist * darks_data = NULL;
2701 double * stab_levels = NULL;
2703 double * ditvals = NULL;
2707 cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
2708 CPL_ERROR_ILLEGAL_INPUT);
2714 cpl_msg_info(__func__,
"Checking DIT consistency");
2715 selection = cpl_vector_new(nb_lamps);
2716 ditvals = cpl_malloc(nb_lamps *
sizeof(
double));
2718 for (i = 0; i < nb_lamps; i++) {
2719 const cpl_frame * c_lamp;
2720 const cpl_frame * c_dark;
2722 skip_if (cpl_error_get_code());
2725 c_lamp = cpl_frameset_get_position_const(lamps, i);
2726 plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
2728 dit_lamp = (double)irplib_pfits_get_dit(plist);
2730 dit_lamp = (double)irplib_pfits_get_dit_opt(plist);
2731 cpl_propertylist_delete(plist);
2732 skip_if (cpl_error_get_code());
2735 c_dark = cpl_frameset_get_position_const(darks, i);
2736 plist = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
2738 dit_dark = (double)irplib_pfits_get_dit(plist);
2740 dit_dark = (double)irplib_pfits_get_dit_opt(plist);
2741 cpl_propertylist_delete(plist);
2742 skip_if (cpl_error_get_code());
2745 if (fabs(dit_dark-dit_lamp) > 1e-3) {
2746 cpl_msg_error(__func__,
"DIT not consistent between LAMP and DARK, skip lamp stability computation");
2751 ditvals[i] = dit_lamp;
2754 cpl_vector_set(selection, i, -1.0);
2762 if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
2763 cpl_vector_set(selection, i, -1.0);
2767 cpl_vector_set(selection, i, 1.0);
2774 cpl_msg_info(__func__,
"Not enough frames for stability check");
2778 cpl_msg_info(__func__,
"Compute the differences lamp - dark");
2781 lamps_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2783 detmon_lg_config.llx,
2784 detmon_lg_config.lly,
2785 detmon_lg_config.urx,
2786 detmon_lg_config.ury,
2789 darks_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2791 detmon_lg_config.llx,
2792 detmon_lg_config.lly,
2793 detmon_lg_config.urx,
2794 detmon_lg_config.ury,
2797 nb_darks=cpl_imagelist_get_size(darks_data);
2798 if(nb_darks==nb_lamps) {
2799 skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
2801 cpl_image* master_dark=cpl_imagelist_collapse_median_create(darks_data);
2802 cpl_imagelist_subtract_image(lamps_data,master_dark);
2803 cpl_image_delete(master_dark);
2806 cpl_msg_info(__func__,
"Check the lamp stability");
2807 stab_levels = cpl_malloc(dit_stab *
sizeof(
double));
2809 for (i=0; i<nb_lamps; i++) {
2810 if (cpl_vector_get(selection, i) < 0) {
2812 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
2818 for (i=1; i<dit_stab; i++) {
2819 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
2820 detmon_lg_config.lamp_stability)
2821 detmon_lg_config.lamp_stability =
2822 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
2827 if (detmon_lg_config.lamp_stability > 0.01) {
2828 cpl_msg_warning(__func__,
2829 "Lamp stability level %g difference too high - proceed anyway",detmon_lg_config.lamp_stability);
2836 cpl_vector_delete(selection);
2837 cpl_imagelist_delete(lamps_data);
2838 cpl_imagelist_delete(darks_data);
2839 cpl_free(stab_levels);
2841 return cpl_error_get_code();
2868 static cpl_error_code
2869 detmon_lg_reduce_dit(
const cpl_frameset * set_on,
2870 int* index_on,
double* exptime_on,
2873 const cpl_frameset * set_off,
2874 int * index_off,
double* exptime_off,
2875 int* next_on,
int* next_off,
2876 cpl_table * linear_table,
2877 cpl_table * gain_table,
2878 cpl_imagelist * linearity_inputs,
2879 cpl_propertylist * qclist,
2880 cpl_boolean opt_nir,
2881 cpl_imagelist * autocorr_images,
2882 cpl_imagelist * diff_flats,
2883 cpl_imagelist * opt_offs,
2887 cpl_frameset * pair_on = NULL;
2888 cpl_frameset * pair_off = NULL;
2889 cpl_imagelist * ons = NULL;
2890 cpl_imagelist * offs = NULL;
2891 cpl_boolean follow = CPL_TRUE;
2892 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
2896 double current_dit = 0;
2898 const char * filename;
2900 cpl_propertylist * plist = NULL;
2901 cpl_propertylist* pDETlist = NULL;
2903 mode = detmon_lg_config.collapse ?
2904 mode | IRPLIB_GAIN_COLLAPSE | IRPLIB_LIN_COLLAPSE:
2905 mode | IRPLIB_GAIN_NO_COLLAPSE | IRPLIB_LIN_NO_COLLAPSE;
2906 mode = detmon_lg_config.pix2pix ?
2907 mode | IRPLIB_LIN_PIX2PIX : mode;
2909 mode | IRPLIB_GAIN_NIR | IRPLIB_LIN_NIR :
2910 mode | IRPLIB_GAIN_OPT | IRPLIB_LIN_OPT ;
2914 skip_if(detmon_pair_extract_next(set_on, index_on, next_on, exptime_on, &pair_on, detmon_lg_config.tolerance));
2915 current_dit = exptime_on[*next_on - 1];
2918 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2919 skip_if(ons == NULL);
2920 cpl_msg_debug(cpl_func,
" Loaded ON images: %" CPL_SIZE_FORMAT
2921 ", exptime[%f]",cpl_imagelist_get_size(ons), current_dit );
2922 if(cpl_imagelist_get_size(ons) != 2)
2924 cpl_msg_error(cpl_func,
"cannot take ON pair, number of images[%"
2925 CPL_SIZE_FORMAT
"]", cpl_imagelist_get_size(ons));
2928 if(detmon_lg_config.filter > 0)
2931 cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
2932 detmon_lg_config.llx,
2933 detmon_lg_config.lly,
2934 detmon_lg_config.urx,
2935 detmon_lg_config.ury);
2937 cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
2938 detmon_lg_config.llx,
2939 detmon_lg_config.lly,
2940 detmon_lg_config.urx,
2941 detmon_lg_config.ury);
2942 if ( med1 > (
double)detmon_lg_config.filter ||
2943 med2 > (
double)detmon_lg_config.filter)
2946 cpl_table_select_row(gain_table, dit_nb);
2947 cpl_table_select_row(linear_table, dit_nb);
2949 cpl_msg_warning(cpl_func,
"Frames of EXPTIME nb %d "
2950 "will not be taken into account for computation "
2951 "as they are above --filter threshold", dit_nb);
2955 if (follow || detmon_lg_config.filter < 0)
2963 if(!detmon_lg_config.collapse)
2980 if (!strcmp(detmon_lg_config.method,
"MED") ||
2981 cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
2983 skip_if(detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off, detmon_lg_config.tolerance));
2987 skip_if(detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
2990 cpl_msg_debug(cpl_func,
" Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
2991 offs = detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
2993 skip_if(offs == NULL);
2994 skip_if(cpl_error_get_code());
2997 offs = (cpl_imagelist *) opt_offs;
3001 if(detmon_lg_config.rescale)
3003 skip_if(detmon_lg_rescale(ons));
3004 if (!detmon_lg_config.collapse &&
3005 !strcmp(detmon_lg_config.method,
"MED"))
3006 skip_if(detmon_lg_rescale(offs));
3011 cpl_frame_get_filename(cpl_frameset_get_first_const(pair_on));
3012 skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
3016 pDETlist = cpl_propertylist_new();
3017 cpl_propertylist_copy_property_regexp(pDETlist, plist,
"DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
3020 irplib_table_create_column(gain_table, pDETlist);
3021 irplib_table_create_column(linear_table, pDETlist);
3024 if(opt_nir == NIR) {
3025 c_dit = irplib_pfits_get_dit(plist);
3026 c_ndit = irplib_pfits_get_ndit(plist);
3028 c_dit = irplib_pfits_get_exptime(plist);
3040 cpl_msg_info(cpl_func,
"Computing GAIN for EXPTIME value nb %d",
3044 if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
3046 cpl_table_erase_column(gain_table,
"MEAN_OFF1");
3047 cpl_table_erase_column(gain_table,
"MEAN_OFF2");
3048 cpl_table_erase_column(gain_table,
"SIG_OFF_DIF");
3049 cpl_table_erase_column(gain_table,
"GAIN");
3050 cpl_table_erase_column(gain_table,
"GAIN_CORR");
3051 cpl_table_new_column(gain_table,
"MEAN_OFF", CPL_TYPE_DOUBLE);
3054 skip_if(detmon_gain_table_fill_row(gain_table,
3057 diff_flats, ons, offs,
3058 detmon_lg_config.kappa,
3059 detmon_lg_config.niter,
3060 detmon_lg_config.llx,
3061 detmon_lg_config.lly,
3062 detmon_lg_config.urx,
3063 detmon_lg_config.ury,
3066 detmon_lg_config.saturation_limit,
3067 dit_nb, mode, rows_affected));
3073 skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
3075 cpl_msg_info(cpl_func,
"Linearity reduction for nb %d",
3077 skip_if(detmon_lin_table_fill_row(linear_table, c_dit,
3078 linearity_inputs, ons, offs,
3079 detmon_lg_config.llx,
3080 detmon_lg_config.lly,
3081 detmon_lg_config.urx,
3082 detmon_lg_config.ury,
3083 dit_nb, *dit_nskip, mode));
3085 skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
3097 if(opt_nir == OPT &&
3098 *rows_affected != 0 ) {
3099 detmon_opt_contamination(ons, offs, mode, qclist);
3106 cpl_frameset_delete(pair_on);
3107 cpl_imagelist_delete(ons);
3109 if(!detmon_lg_config.collapse ) {
3110 cpl_imagelist_delete(offs);
3113 if(!detmon_lg_config.collapse) {
3114 cpl_frameset_delete(pair_off);
3117 cpl_propertylist_delete(plist);
3118 cpl_propertylist_delete(pDETlist);
3119 return cpl_error_get_code();
3129 static cpl_error_code
3130 detmon_add_adl_column(cpl_table * table,
3131 cpl_boolean opt_nir)
3133 cpl_error_code error;
3134 double mean_med_dit;
3137 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
3139 mean_med_dit = cpl_table_get_column_mean(table,
"MED_DIT");
3141 dits = cpl_table_get_data_double(table,
"EXPTIME");
3143 dits = cpl_table_get_data_double(table,
"DIT");
3145 error = cpl_table_copy_data_double(table,
"ADL", dits);
3146 cpl_ensure_code(!error, error);
3147 error = cpl_table_multiply_scalar(table,
"ADL", mean_med_dit);
3148 cpl_ensure_code(!error, error);
3150 return cpl_error_get_code();
3162 static cpl_error_code
3163 detmon_lg_reduce_init(cpl_table * gain_table,
3164 cpl_table * linear_table,
3165 cpl_imagelist ** linearity_inputs,
3166 const cpl_boolean opt_nir)
3168 skip_if(detmon_gain_table_create(gain_table, opt_nir));
3169 skip_if(detmon_lin_table_create(linear_table, opt_nir));
3171 if(detmon_lg_config.pix2pix) {
3172 *linearity_inputs = cpl_imagelist_new();
3173 skip_if(*linearity_inputs == NULL);
3178 return cpl_error_get_code();
3189 irplib_pfits_get_dit(
const cpl_propertylist * plist)
3191 return irplib_pfits_get_prop_double(plist,
"ESO DET DIT");
3202 irplib_pfits_get_dit_opt(
const cpl_propertylist * plist)
3204 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3213 static cpl_propertylist*
3214 detmon_load_pro_keys(
const char* NAME_O)
3216 cpl_propertylist* pro_keys=NULL;
3217 pro_keys=cpl_propertylist_load_regexp(NAME_O,0,
"^(ESO PRO)",0);
3222 static double irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
3223 const char* prop_name)
3226 dit = cpl_propertylist_get_double(plist, prop_name);
3227 if(cpl_error_get_code() != CPL_ERROR_NONE)
3229 cpl_msg_error(cpl_func,
"Cannot read property '%s', err[%s]",
3230 prop_name, cpl_error_get_where());
3268 static cpl_error_code
3269 detmon_gain_table_fill_row(cpl_table * gain_table,
3270 double c_dit,
int c_ndit,
3271 cpl_imagelist * autocorr_images,
3272 cpl_imagelist * diff_flats,
3273 const cpl_imagelist * ons,
3274 const cpl_imagelist * offs,
3275 double kappa,
int nclip,
3276 int llx,
int lly,
int urx,
int ury,
3278 double saturation_limit,
3279 const int pos,
unsigned mode,
int* rows_affected)
3281 const cpl_image *image;
3282 cpl_image *on_dif = NULL;
3284 double avg_on1, avg_on2;
3285 double avg_off1, avg_off2;
3286 double double_adu, autocorr, gain, gain_corr;
3289 cpl_table_set(gain_table,
"FLAG", pos, 1);
3290 if (mode & IRPLIB_GAIN_NIR)
3292 cpl_table_set(gain_table,
"DIT", pos, c_dit);
3293 cpl_table_set(gain_table,
"NDIT", pos, c_ndit);
3294 }
else if (mode & IRPLIB_GAIN_OPT)
3296 cpl_table_set(gain_table,
"EXPTIME", pos, c_dit);
3299 cpl_msg_error(cpl_func,
"Mandatory mode (OPT or NIR) not provided");
3302 if(*rows_affected == 0)
3304 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3305 cpl_table_set(gain_table,
"FLAG", pos, 0);
3306 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3311 detmon_lg_add_empty_image(diff_flats, pos);
3313 if (autocorr_images)
3315 detmon_lg_add_empty_image(autocorr_images, pos);
3318 return cpl_error_get_code();
3320 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3321 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3322 nclip, 1e-5, &avg_on1, &std));
3323 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3324 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3325 nclip, 1e-5, &avg_on2, &std));
3327 if ((avg_on1 > saturation_limit) || (avg_on2 > saturation_limit))
3329 cpl_msg_warning(cpl_func,
"Average saturation is above the limit, "
3330 "the frames would not be taken into calculation");
3331 cpl_msg_warning(cpl_func,
"saturation levels [%f ; %f], limit [%f]",
3332 avg_on1, avg_on2, saturation_limit);
3333 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3334 cpl_table_set(gain_table,
"FLAG", pos, 0);
3335 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3340 detmon_lg_add_empty_image(diff_flats, pos);
3342 if (autocorr_images)
3344 detmon_lg_add_empty_image(autocorr_images, pos);
3353 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON1", pos, avg_on1));
3354 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON2", pos, avg_on2));
3357 detmon_subtract_create_window(cpl_imagelist_get_const(ons, 0),
3358 cpl_imagelist_get_const(ons, 1),
3359 llx, lly, urx, ury);
3360 skip_if(on_dif == NULL);
3362 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3366 cpl_image * diff = cpl_image_duplicate(on_dif);
3367 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
3369 if (autocorr_images)
3371 cpl_image * corr = NULL;
3372 autocorr = detmon_autocorr_factor(on_dif, &corr, m, n);
3375 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
3379 detmon_lg_add_empty_image(autocorr_images, pos);
3383 autocorr = detmon_autocorr_factor(on_dif, NULL, m, n);
3385 autocorr = isnan(autocorr) ? 1.0 : autocorr;
3391 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE)
3394 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3395 llx, lly, urx, ury, kappa, nclip,
3396 1e-5, &avg_off1, &std));
3397 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF", pos, avg_off1));
3399 }
else if (mode & IRPLIB_GAIN_NO_COLLAPSE ||
3400 ( pos == 0 && mode & IRPLIB_GAIN_COLLAPSE )) {
3401 cpl_image * off_dif = NULL;
3403 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3404 llx, lly, urx, ury, kappa, nclip,
3405 1e-5, &avg_off1, &std));
3406 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3407 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 1),
3408 llx, lly, urx, ury, kappa, nclip,
3409 1e-5, &avg_off2, &std));
3410 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, avg_off2));
3412 detmon_subtract_create_window(cpl_imagelist_get_const(offs, 0),
3413 cpl_imagelist_get_const(offs, 1),
3414 llx, lly, urx, ury);
3415 skip_if(off_dif == NULL);
3416 irplib_ksigma_clip(off_dif, 1, 1,
3417 cpl_image_get_size_x(off_dif),
3418 cpl_image_get_size_y(off_dif),
3420 1e-5, &avg_off_dif, &sig_off_dif);
3421 cpl_image_delete(off_dif);
3422 skip_if(cpl_table_set_double(gain_table,
"SIG_OFF_DIF",
3424 }
else if (pos > 0 && mode & IRPLIB_GAIN_COLLAPSE)
3427 avg_off1 = cpl_table_get_double(gain_table,
"MEAN_OFF1", 0, &status);
3428 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3429 avg_off2 = cpl_table_get_double(gain_table,
"MEAN_OFF2", 0, &status);
3430 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, avg_off2));
3431 sig_off_dif = cpl_table_get_double(gain_table,
"SIG_OFF_DIF",
3433 skip_if(cpl_table_set_double(gain_table,
"SIG_OFF_DIF",
3438 double avg_on_dif, sig_on_dif;
3439 irplib_ksigma_clip(on_dif, 1, 1,
3440 cpl_image_get_size_x(on_dif),
3441 cpl_image_get_size_y(on_dif), kappa,
3442 nclip, 1e-5, &avg_on_dif, &sig_on_dif);
3443 skip_if(cpl_table_set_double(gain_table,
"SIG_ON_DIF", pos, sig_on_dif));
3445 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE)
3447 double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
3451 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
3453 sigma = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
3457 gain = double_adu / (c_ndit * sigma);
3459 gain_corr = gain / (autocorr);
3461 skip_if(cpl_table_set_double(gain_table,
"GAIN", pos, gain));
3462 skip_if(cpl_table_set_double(gain_table,
"GAIN_CORR", pos, gain_corr));
3465 skip_if(cpl_table_set_double(gain_table,
"AUTOCORR", pos, autocorr));
3466 skip_if(cpl_table_set_double(gain_table,
"ADU", pos, double_adu / 2));
3469 skip_if(cpl_table_set_double(gain_table,
"Y_FIT",
3471 c_ndit* sig_on_dif * sig_on_dif));
3472 skip_if(cpl_table_set_double(gain_table,
"Y_FIT_CORR",
3474 c_ndit * sig_on_dif * sig_on_dif));
3475 skip_if(cpl_table_set_double(gain_table,
"X_FIT", pos, double_adu));
3476 skip_if(cpl_table_set_double(gain_table,
"X_FIT_CORR",
3477 pos, double_adu / autocorr));
3482 cpl_image_delete(on_dif);
3484 return cpl_error_get_code();
3497 detmon_bpixs(
const cpl_imagelist * coeffs,
3504 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
3511 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
3512 cpl_image_get_size_y(first));
3513 cpl_image *cur_image = NULL;
3514 cpl_image *bpm = NULL;
3517 size = cpl_imagelist_get_size(coeffs);
3520 bpm = cpl_image_new(cpl_image_get_size_x(first),
3521 cpl_image_get_size_y(first),
3526 for(i = 0; i < size; i++) {
3527 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
3529 stats = cpl_stats_new_from_image(cur_coeff,
3530 CPL_STATS_MEAN | CPL_STATS_STDEV);
3531 cur_mean = cpl_stats_get_mean(stats);
3532 cur_stdev = cpl_stats_get_stdev(stats);
3534 lo_cut = cur_mean - kappa * cur_stdev;
3535 hi_cut = cur_mean + kappa * cur_stdev;
3537 cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
3538 cpl_mask_not(cur_mask);
3541 cur_image = cpl_image_new_from_mask(cur_mask);
3543 cpl_image_power(cur_image, p);
3544 cpl_image_add(bpm, cur_image);
3545 cpl_image_delete(cur_image);
3548 cpl_mask_or(mask, cur_mask);
3550 cpl_mask_delete(cur_mask);
3551 cpl_stats_delete(stats);
3555 bpm = cpl_image_new_from_mask(mask);
3558 *nbpixs += cpl_mask_count(mask);
3560 cpl_mask_delete(mask);
3687 detmon_autocorr_factor(
const cpl_image * image,
3688 cpl_image ** autocorr_image,
int m,
int n)
3690 cpl_image * mycorr_image = NULL;
3691 double autocorr = 0;
3692 cpl_error_code err = CPL_ERROR_NONE;
3694 mycorr_image = detmon_image_correlate(image, image, m, n);
3695 err=cpl_error_get_code();
3696 if (err == CPL_ERROR_UNSUPPORTED_MODE)
3698 cpl_msg_warning(cpl_func,
"FFTW is not supported by CPL, autocorrelation "
3699 "would be computed using internal implementation");
3702 cpl_image_delete(mycorr_image);
3703 mycorr_image = detmon_autocorrelate(image, m, n);
3705 if(mycorr_image == NULL) {
3709 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
3711 autocorr = cpl_image_get_flux(mycorr_image);
3713 if (autocorr_image) *autocorr_image = mycorr_image;
3714 else cpl_image_delete(mycorr_image);
3719 static cpl_propertylist*
3720 detmon_lg_extract_qclist_4plane(cpl_propertylist* linc_qclist,
const int ip)
3723 cpl_propertylist* sub_set=NULL;
3726 sub_set=cpl_propertylist_new();
3727 qc_key=cpl_sprintf(
"QC LIN COEF%d",ip);
3728 cpl_propertylist_copy_property_regexp(sub_set,linc_qclist,qc_key,0);
3745 static cpl_error_code
3746 detmon_lg_extract_extention_header(cpl_frameset* frameset,
3747 cpl_propertylist* gaint_qclist,
3748 cpl_propertylist* lint_qclist,
3749 cpl_propertylist* linc_qclist,
3750 cpl_propertylist* bpm_qclist,
3754 cpl_propertylist * xplist = NULL;
3756 const char * filename =
3757 cpl_frame_get_filename(cpl_frameset_get_first(frameset));
3759 xplist = cpl_propertylist_load_regexp(filename, whichext,
3760 "ESO DET|EXTNAME", 0);
3761 if (detmon_lg_config.exts >= 0)
3764 cpl_property* propExtname = NULL;
3765 propExtname = cpl_propertylist_get_property(xplist,
"EXTNAME");
3767 if (NULL != propExtname)
3769 propExtname = cpl_property_duplicate(propExtname);
3771 cpl_propertylist_delete(xplist);
3773 if (NULL != propExtname)
3775 xplist = cpl_propertylist_new();
3776 cpl_propertylist_append_property(xplist, propExtname);
3777 cpl_property_delete(propExtname);
3782 cpl_propertylist_append(gaint_qclist, xplist);
3783 cpl_propertylist_append(lint_qclist, xplist);
3784 cpl_propertylist_append(linc_qclist, xplist);
3785 cpl_propertylist_append(bpm_qclist, xplist);
3786 cpl_propertylist_delete(xplist);
3789 return cpl_error_get_code();
3806 static cpl_error_code
3807 detmon_lg_save_table_with_pro_keys(cpl_table* table,
3809 cpl_propertylist* xheader,
3810 unsigned CPL_IO_MODE)
3813 cpl_propertylist* pro_keys=NULL;
3815 pro_keys=detmon_load_pro_keys(name_o);
3816 cpl_propertylist_append(xheader,pro_keys);
3818 if(CPL_IO_MODE==CPL_IO_DEFAULT) {
3819 cpl_propertylist * pri_head=cpl_propertylist_load(name_o,0);
3820 cpl_table_save(table, pri_head,xheader,name_o,
3822 cpl_propertylist_delete(pri_head);
3825 cpl_table_save(table,NULL,xheader,name_o,
3828 cpl_propertylist_delete(pro_keys);
3830 return cpl_error_get_code();
3842 static cpl_error_code
3843 detmon_lg_save_image_with_pro_keys(cpl_image* image,
3845 cpl_propertylist* xheader)
3848 cpl_propertylist* pro_keys=NULL;
3849 pro_keys=detmon_load_pro_keys(name_o);
3850 cpl_propertylist_append(xheader,pro_keys);
3852 cpl_image_save(image,name_o, CPL_BPP_IEEE_FLOAT,
3853 xheader,CPL_IO_EXTEND);
3854 cpl_propertylist_delete(pro_keys);
3857 return cpl_error_get_code();
3869 static cpl_error_code
3870 detmon_lg_save_imagelist_with_pro_keys(cpl_imagelist* imagelist,
3872 cpl_propertylist* xheader)
3875 cpl_propertylist* pro_keys=NULL;
3876 pro_keys=detmon_load_pro_keys(name_o);
3877 cpl_propertylist_append(xheader,pro_keys);
3879 cpl_imagelist_save(imagelist,name_o, CPL_BPP_IEEE_FLOAT,
3880 xheader,CPL_IO_EXTEND);
3882 cpl_propertylist_delete(pro_keys);
3885 return cpl_error_get_code();
3905 static cpl_error_code
3906 detmon_lg_save_plane(
const cpl_parameterlist * parlist,
3907 cpl_frameset* frameset,
3908 const cpl_frameset * usedframes,
3910 const char* recipe_name,
3911 cpl_propertylist* mypro_coeffscube,
3912 cpl_propertylist* linc_plane_qclist,
3913 const char* package,
3917 if(detmon_lg_config.exts == 0) {
3918 cpl_propertylist* plist=NULL;
3919 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3921 CPL_BPP_IEEE_FLOAT, recipe_name,
3922 mypro_coeffscube, NULL,
3924 plist=cpl_propertylist_load(NAME_O,0);
3925 cpl_image_save(plane,NAME_O, CPL_BPP_IEEE_FLOAT,
3926 plist,CPL_IO_DEFAULT);
3927 cpl_propertylist_delete(plist);
3929 }
else if(detmon_lg_config.exts > 0) {
3930 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3932 CPL_BPP_IEEE_FLOAT, recipe_name,
3933 mypro_coeffscube, NULL,
3936 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
3940 cpl_dfs_save_image(frameset, NULL, parlist,
3941 usedframes,NULL, NULL,
3942 CPL_BPP_IEEE_FLOAT, recipe_name,
3943 mypro_coeffscube, NULL,
3945 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
3948 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
3954 return cpl_error_get_code();
3977 static cpl_error_code
3978 detmon_lg_save_cube(
const cpl_parameterlist * parlist,
3979 cpl_frameset* frameset,
3980 const cpl_frameset * usedframes,
3982 const char* recipe_name,
3983 cpl_propertylist* mypro_coeffscube,
3984 cpl_propertylist* linc_qclist,
3985 const char* package,
3987 cpl_imagelist* coeffs)
3990 if(detmon_lg_config.exts == 0) {
3991 cpl_propertylist_append(mypro_coeffscube, linc_qclist);
3992 detmon_lg_dfs_save_imagelist
3993 (frameset, parlist, usedframes, coeffs,
3994 recipe_name, mypro_coeffscube, package,
3996 }
else if(detmon_lg_config.exts > 0) {
3997 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3999 CPL_BPP_IEEE_FLOAT, recipe_name,
4000 mypro_coeffscube, NULL,
4003 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4007 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4009 CPL_BPP_IEEE_FLOAT, recipe_name,
4010 mypro_coeffscube, NULL,
4013 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4015 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4018 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4020 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4024 return cpl_error_get_code();
4028 detmon_lg_set_paf_name_and_header(cpl_frame* ref_frame,
4029 int flag_sets,
int which_set,
4031 const char* paf_suf,
4032 cpl_propertylist** plist)
4034 char * paf_name=NULL;
4036 if(detmon_lg_config.exts >= 0)
4038 *plist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4039 detmon_lg_config.exts);
4043 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4047 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4048 detmon_lg_config.pafname, paf_suf,which_set);
4053 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4059 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4060 detmon_lg_config.pafname, paf_suf,whichext);
4064 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4065 detmon_lg_config.pafname,paf_suf,
4066 which_set, whichext);
4075 detmon_lg_set_paf_name_and_header_ext(cpl_frame* ref_frame,
4076 int flag_sets,
int which_set,
4078 const char* paf_suf,
4079 cpl_propertylist** plist)
4081 char* paf_name=NULL;
4083 if(detmon_lg_config.exts >= 0)
4085 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4086 detmon_lg_config.exts);
4090 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4093 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4094 detmon_lg_config.pafname, paf_suf,which_set);
4098 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4102 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4103 detmon_lg_config.pafname, paf_suf,whichext);
4106 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4107 detmon_lg_config.pafname,paf_suf,
4108 which_set, whichext);
4115 static cpl_error_code
4116 detmon_lg_save_paf_product(cpl_frame* ref_frame,
int flag_sets,
4117 int which_set,
int whichext,
4118 const char* pafregexp,
4119 const char* procatg,
4120 const char* pipeline_name,
4121 const char* recipe_name,
4122 const char* paf_suf,
4123 cpl_propertylist* qclist,
4128 char* paf_name=NULL;
4129 cpl_propertylist* plist=NULL;
4130 cpl_propertylist* paflist = NULL;
4131 cpl_propertylist* mainplist=NULL;
4133 mainplist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0);
4135 paf_name=detmon_lg_set_paf_name_and_header(ref_frame,flag_sets,
4139 paf_name=detmon_lg_set_paf_name_and_header_ext(ref_frame,flag_sets,
4145 paflist = cpl_propertylist_new();
4146 cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,procatg);
4149 cpl_propertylist_copy_property_regexp(paflist, plist,pafregexp, 0);
4150 cpl_propertylist_copy_property_regexp(paflist, mainplist,pafregexp, 0);
4151 cpl_propertylist_append(paflist,qclist);
4154 cpl_dfs_save_paf(pipeline_name, recipe_name,paflist,paf_name);
4157 cpl_propertylist_delete(mainplist);
4158 cpl_propertylist_delete(paflist);
4159 cpl_propertylist_delete(plist);
4162 return cpl_error_get_code();
4199 static cpl_error_code
4200 detmon_lg_save(
const cpl_parameterlist * parlist,
4201 cpl_frameset * frameset,
4202 const char *recipe_name,
4203 const char *pipeline_name,
4204 const char *pafregexp,
4205 const cpl_propertylist * pro_lintbl,
4206 const cpl_propertylist * pro_gaintbl,
4207 const cpl_propertylist * pro_coeffscube,
4208 const cpl_propertylist * pro_bpm,
4209 const cpl_propertylist * pro_corr,
4210 const cpl_propertylist * pro_diff,
4211 const char *package,
4212 cpl_imagelist * coeffs,
4213 cpl_table * gain_table,
4214 cpl_table * linear_table,
4216 cpl_imagelist * autocorr_images,
4217 cpl_imagelist * diff_flats,
4218 cpl_propertylist * gaint_qclist,
4219 cpl_propertylist * lint_qclist,
4220 cpl_propertylist * linc_qclist,
4221 cpl_propertylist * bpm_qclist,
4222 const int flag_sets,
4223 const int which_set,
4224 const cpl_frameset * usedframes,
4228 cpl_frame *ref_frame;
4229 cpl_propertylist *plist = NULL;
4230 cpl_propertylist *mainplist = NULL;
4236 cpl_propertylist * xplist = NULL;
4238 cpl_propertylist* linc_plane_qclist=NULL;
4239 cpl_image* plane=NULL;
4241 char* pcatg_plane=NULL;
4243 cpl_propertylist * mypro_lintbl =
4244 cpl_propertylist_duplicate(pro_lintbl);
4245 cpl_propertylist * mypro_gaintbl =
4246 cpl_propertylist_duplicate(pro_gaintbl);
4247 cpl_propertylist * mypro_coeffscube =
4248 cpl_propertylist_duplicate(pro_coeffscube);
4249 cpl_propertylist * mypro_bpm =
4250 cpl_propertylist_duplicate(pro_bpm);
4251 cpl_propertylist * mypro_corr =
4252 cpl_propertylist_duplicate(pro_corr);
4253 cpl_propertylist * mypro_diff =
4254 cpl_propertylist_duplicate(pro_diff);
4256 const char * procatg_lintbl =
4257 cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
4259 const char * procatg_gaintbl =
4260 cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
4262 const char * procatg_coeffscube =
4263 cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
4264 const char * procatg_bpm =
4265 cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
4269 detmon_lg_extract_extention_header(frameset,gaint_qclist,lint_qclist,
4270 linc_qclist,bpm_qclist,whichext);
4275 ref_frame = cpl_frameset_get_first(frameset);
4277 skip_if((mainplist =
4278 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4284 cpl_msg_info(cpl_func,
"Write the LINEARITY TABLE");
4287 NAME_O=cpl_sprintf(
"%s_linearity_table.fits", recipe_name);
4289 NAME_O=cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name,
4293 if (detmon_lg_config.exts >= 0) {
4295 cpl_propertylist_append(mypro_lintbl, lint_qclist);
4296 skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,
4297 linear_table,NULL, recipe_name,
4298 mypro_lintbl, NULL, package, NAME_O));
4300 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4301 lint_qclist,CPL_IO_DEFAULT);
4306 skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL,
4307 linear_table,lint_qclist, recipe_name,
4308 mypro_lintbl,NULL, package, NAME_O));
4309 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4310 lint_qclist,CPL_IO_DEFAULT);
4317 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4318 lint_qclist,CPL_IO_EXTEND);
4321 irplib_free(&NAME_O);
4325 cpl_msg_info(cpl_func,
"Write the GAIN TABLE");
4328 NAME_O=cpl_sprintf(
"%s_gain_table.fits", recipe_name);
4330 NAME_O=cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name,
4334 if (detmon_lg_config.exts >= 0)
4338 cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
4339 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
4340 gain_table,NULL, recipe_name, mypro_gaintbl,
4341 NULL, package, NAME_O));
4342 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4343 gaint_qclist,CPL_IO_DEFAULT);
4351 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
4352 gaint_qclist, recipe_name, mypro_gaintbl,
4353 NULL, package, NAME_O));
4354 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4355 gaint_qclist,CPL_IO_DEFAULT);
4361 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4362 gaint_qclist,CPL_IO_EXTEND);
4366 if(detmon_lg_config.pix2pix)
4372 cpl_msg_info(cpl_func,
"Write the COEFFS FITS");
4373 irplib_free(&NAME_O);
4376 PREF_O=cpl_sprintf(
"%s_coeffs_cube", recipe_name);
4379 PREF_O=cpl_sprintf(
"%s_coeffs_cube_set%02d",
4380 recipe_name, which_set);
4382 if (detmon_lg_config.split_coeffs == 0) {
4383 NAME_O=cpl_sprintf(
"%s.fits", PREF_O);
4388 if(detmon_lg_config.split_coeffs != 0){
4391 nb_images = cpl_imagelist_get_size(coeffs);
4392 for(ip=0;ip<nb_images;ip++) {
4393 NAME_O=cpl_sprintf(
"%s_P%d.fits", PREF_O,ip);
4394 pcatg_plane=cpl_sprintf(
"COEFFS_CUBE_P%d",ip);
4395 cpl_propertylist_delete(mypro_coeffscube);
4396 mypro_coeffscube=cpl_propertylist_duplicate(pro_coeffscube);
4397 cpl_propertylist_set_string(mypro_coeffscube,CPL_DFS_PRO_CATG,
4399 linc_plane_qclist=detmon_lg_extract_qclist_4plane(linc_qclist,ip);
4400 cpl_propertylist_append(mypro_coeffscube, linc_plane_qclist);
4401 plane=cpl_imagelist_get(coeffs,ip);
4402 detmon_lg_save_plane(parlist,frameset,usedframes,whichext,
4403 recipe_name,mypro_coeffscube,
4404 linc_plane_qclist,package,NAME_O,plane);
4406 if(NULL!=linc_plane_qclist) {
4407 cpl_propertylist_delete(linc_plane_qclist);
4409 irplib_free(&NAME_O);
4414 detmon_lg_save_cube(parlist,frameset,usedframes,whichext,
4415 recipe_name,mypro_coeffscube,
4416 linc_qclist,package,NAME_O,coeffs);
4422 cpl_msg_info(cpl_func,
"Write the BAD PIXEL MAP");
4423 irplib_free(&NAME_O);
4427 NAME_O=cpl_sprintf(
"%s_bpm.fits", recipe_name);
4430 NAME_O=cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, which_set);
4435 if(detmon_lg_config.exts == 0) {
4436 cpl_propertylist_append(mypro_bpm, bpm_qclist);
4437 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
4438 CPL_BPP_IEEE_FLOAT, recipe_name,
4439 mypro_bpm, NULL, package,
4442 else if(detmon_lg_config.exts > 0)
4444 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4445 CPL_BPP_IEEE_FLOAT, recipe_name,
4446 mypro_bpm, NULL, package,
4448 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4454 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4455 CPL_BPP_IEEE_FLOAT, recipe_name,
4456 mypro_bpm, NULL, package,
4458 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4461 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4466 if(detmon_lg_config.intermediate)
4471 cpl_msg_info(cpl_func,
"Write the AUTOCORRS FITS");
4472 nb_images = cpl_imagelist_get_size(autocorr_images);
4473 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
4474 for(i = 0; i < nb_images; i++)
4476 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_corr);
4478 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4480 if(i < cpl_table_get_nrow(linear_table))
4482 ddit = cpl_table_get_double(linear_table,
4483 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4485 cpl_array_delete(pnames);
4488 irplib_free(&NAME_O);
4491 NAME_O=cpl_sprintf(
"%s_autocorr_%d.fits", recipe_name, i);
4492 assert(NAME_O != NULL);
4495 NAME_O=cpl_sprintf(
"%s_autocorr_%02d_set%02d.fits",
4496 recipe_name, i, which_set);
4497 assert(NAME_O != NULL);
4500 if(detmon_lg_config.exts > 0)
4502 cpl_propertylist* pextlist = cpl_propertylist_new();
4503 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4504 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4505 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4506 recipe_name, pplist, NULL,
4509 detmon_lg_save_image_with_pro_keys(
4510 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4512 cpl_propertylist_delete(pextlist);
4514 if(detmon_lg_config.exts == 0)
4516 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4517 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
4518 cpl_imagelist_get(autocorr_images, i),
4520 recipe_name, pplist, NULL, package,
4526 cpl_propertylist* pextlist = cpl_propertylist_new();
4527 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4530 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4531 usedframes, NULL,NULL,
4532 CPL_BPP_IEEE_FLOAT, recipe_name,
4536 detmon_lg_save_image_with_pro_keys(
4537 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4542 detmon_lg_save_image_with_pro_keys(
4543 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4545 cpl_propertylist_delete(pextlist);
4547 cpl_propertylist_delete (pplist);
4549 irplib_free(&NAME_O);
4558 cpl_msg_info(cpl_func,
"Write the DIFFS FITS");
4560 for(i = 0; i < nb_images; i++)
4562 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_diff);
4564 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4566 if(i < cpl_table_get_nrow(linear_table))
4568 ddit = cpl_table_get_double(linear_table,
4569 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4571 cpl_array_delete(pnames);
4576 NAME_O=cpl_sprintf(
"%s_diff_flat_%d.fits", recipe_name, i);
4579 NAME_O=cpl_sprintf(
"%s_diff_flat_%d_set%02d.fits",
4580 recipe_name, i, which_set);
4583 if(detmon_lg_config.exts > 0)
4585 cpl_propertylist* pextlist = cpl_propertylist_new();
4586 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4587 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT", ddit);
4588 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4589 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4591 mypro_diff, NULL,package, NAME_O));
4593 detmon_lg_save_image_with_pro_keys(
4594 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4596 cpl_propertylist_delete(pextlist);
4598 else if(detmon_lg_config.exts == 0)
4600 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4602 (frameset, NULL, parlist, usedframes, NULL,
4603 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
4604 recipe_name, pplist, NULL, package,
4609 cpl_propertylist* pextlist = cpl_propertylist_new();
4610 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4613 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT",ddit);
4615 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4616 usedframes, NULL,NULL,
4617 CPL_BPP_IEEE_FLOAT, recipe_name,
4618 mypro_diff, NULL,package, NAME_O));
4620 detmon_lg_save_image_with_pro_keys(
4621 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4626 detmon_lg_save_image_with_pro_keys(
4627 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4630 cpl_propertylist_delete(pextlist);
4632 cpl_propertylist_delete(pplist);
4633 irplib_free(&NAME_O);
4641 cpl_msg_info(cpl_func,
"Write the PAF file(s)");
4643 if(detmon_lg_config.pafgen) {
4645 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4646 pafregexp,procatg_gaintbl,
4647 pipeline_name,recipe_name,
4648 "qc01",gaint_qclist,0);
4650 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4651 pafregexp,procatg_lintbl,
4652 pipeline_name,recipe_name,
4653 "qc02",lint_qclist,0);
4655 if(detmon_lg_config.pix2pix)
4658 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4661 pipeline_name,recipe_name,
4662 "qc03",linc_qclist,1);
4664 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4665 whichext,pafregexp,procatg_bpm,
4666 pipeline_name,recipe_name,
4667 "qc04",bpm_qclist,1);
4672 cpl_msg_info(cpl_func,
"exit");
4674 cpl_propertylist_delete(xplist);
4676 cpl_propertylist_delete(plist);
4680 irplib_free(&NAME_O);
4682 cpl_free(pcatg_plane);
4683 cpl_propertylist_delete(mainplist);
4684 cpl_propertylist_delete(mypro_lintbl);
4685 cpl_propertylist_delete(mypro_gaintbl);
4686 cpl_propertylist_delete(mypro_coeffscube);
4687 cpl_propertylist_delete(mypro_bpm);
4688 cpl_propertylist_delete(mypro_corr);
4689 cpl_propertylist_delete(mypro_diff);
4691 return cpl_error_get_code();
4704 static cpl_error_code
4705 detmon_opt_contamination(
const cpl_imagelist * ons,
4706 const cpl_imagelist * offs,
4708 cpl_propertylist * qclist)
4716 struct rect rects[5] = {
4717 (
struct rect){ detmon_lg_config.llx1,
4718 detmon_lg_config.lly1,
4719 detmon_lg_config.urx1,
4720 detmon_lg_config.ury1},
4721 (
struct rect){ detmon_lg_config.llx2,
4722 detmon_lg_config.lly2,
4723 detmon_lg_config.urx2,
4724 detmon_lg_config.ury2},
4725 (
struct rect){ detmon_lg_config.llx3,
4726 detmon_lg_config.lly3,
4727 detmon_lg_config.urx3,
4728 detmon_lg_config.ury3},
4729 (
struct rect){ detmon_lg_config.llx4,
4730 detmon_lg_config.lly4,
4731 detmon_lg_config.urx4,
4732 detmon_lg_config.ury4},
4733 (
struct rect){ detmon_lg_config.llx5,
4734 detmon_lg_config.lly5,
4735 detmon_lg_config.urx5,
4736 detmon_lg_config.ury5},
4739 for (
size_t i = 0; i < 5; i++) {
4740 cpl_image * dif_avg;
4741 const cpl_image * off2;
4744 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
4745 off2 = cpl_imagelist_get_const(offs, 0);
4747 off2 = cpl_imagelist_get_const(offs, 1);
4749 dif_avg = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
4750 cpl_imagelist_get_const(offs, 0),
4751 cpl_imagelist_get_const(ons, 1),
4758 median = cpl_image_get_median(dif_avg);
4759 cpl_image_delete(dif_avg);
4762 sprintf(kname,
"%s%d", DETMON_QC_CONTAM, i + 1);
4764 if(cpl_propertylist_has(qclist,kname)){
4765 skip_if(cpl_propertylist_update_double(qclist,kname,median));
4767 skip_if(cpl_propertylist_append_double(qclist,kname,median));
4768 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
4774 return cpl_error_get_code();
4833 detmon_lg_dfs_set_groups(cpl_frameset * set,
4834 const char *tag_on,
const char *tag_off)
4836 cpl_frame *cur_frame;
4846 nframes = cpl_frameset_get_size(set);
4849 for(i = 0; i < nframes; i++) {
4850 cur_frame = cpl_frameset_get_position(set, i);
4851 tag = cpl_frame_get_tag(cur_frame);
4854 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
4855 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
4875 static cpl_error_code
4876 detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist ** coeffs_ptr,
4877 cpl_image **bpms_ptr)
4879 cpl_image* dummy_bpm=NULL;
4880 cpl_image * dummy_coeff=NULL;
4881 cpl_imagelist * dummy_coeffs=NULL;
4893 dummy_bpm = cpl_image_new(detmon_lg_config.nx,
4894 detmon_lg_config.ny,
4896 dummy_coeffs = cpl_imagelist_new();
4898 db_p = cpl_image_get_data_int(dummy_bpm);
4899 rb_p = cpl_image_get_data_int(*bpms_ptr);;
4900 dcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
4901 rcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
4902 dlength = detmon_lg_config.nx;
4903 rlength = detmon_lg_config.urx - detmon_lg_config.llx + 1;
4904 for (i = 0; i <= detmon_lg_config.order; i++)
4906 dummy_coeff = cpl_image_new(detmon_lg_config.nx,
4907 detmon_lg_config.ny,
4910 cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
4911 dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
4912 rcs_p[i] = cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
4915 for (i = detmon_lg_config.lly - 1; i < detmon_lg_config.ury; i++)
4917 for (j = detmon_lg_config.llx - 1; j < detmon_lg_config.urx; j++)
4919 shift_idx=(i - detmon_lg_config.lly + 1) * rlength +
4920 j - detmon_lg_config.llx + 1;
4921 *(db_p + i * dlength + j) = *(rb_p + shift_idx);
4922 for (k = 0; k <= detmon_lg_config.order; k++)
4924 *(dcs_p[k] + i * dlength + j) =
4925 *(rcs_p[k] + (i - detmon_lg_config.lly + 1) * rlength +
4926 j - detmon_lg_config.llx + 1);
4930 cpl_imagelist_delete(*coeffs_ptr);
4931 cpl_image_delete(*bpms_ptr);
4932 *coeffs_ptr = dummy_coeffs;
4933 *bpms_ptr = dummy_bpm;
4937 return cpl_error_get_code();
4997 detmon_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
4998 const double ron, cpl_image ** ima_errs)
5000 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
5001 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
5002 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
5003 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
5005 *ima_errs = cpl_image_duplicate(ima_data);
5007 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
5011 cpl_image_divide_scalar(*ima_errs, gain);
5012 cpl_image_add_scalar(*ima_errs, ron * ron);
5013 cpl_image_power(*ima_errs, 0.5);
5015 return cpl_error_get_code();
5033 static cpl_error_code
5034 detmon_lg_reduce_all(
const cpl_table * linear_table,
5035 cpl_propertylist * gaint_qclist,
5036 cpl_propertylist * lint_qclist,
5037 cpl_propertylist * linc_qclist,
5038 cpl_propertylist * bpm_qclist,
5039 cpl_imagelist ** coeffs_ptr,
5040 cpl_image ** bpms_ptr,
5041 const cpl_imagelist * linearity_inputs,
5042 const cpl_table * gain_table,
5043 int which_ext, cpl_boolean opt_nir)
5047 const int nsets = cpl_table_get_nrow(linear_table);
5049 cpl_polynomial *poly_linfit = NULL;
5050 cpl_image *fiterror = NULL;
5051 char * name_o1 = NULL;
5052 char * name_o2 = NULL;
5053 double * pcoeffs = NULL;
5054 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
5057 cpl_vector *x =NULL;
5058 const cpl_vector *y =NULL;
5061 const cpl_image * first = NULL;
5069 cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5070 cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5071 cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
5072 cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
5074 pcoeffs = cpl_malloc(
sizeof(
double)*(detmon_lg_config.order + 1));
5076 skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
5077 detmon_lg_config.method));
5078 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
5079 DETMON_QC_METHOD_C));
5082 if (!strcmp(detmon_lg_config.method,
"PTC")) {
5084 if (detmon_lg_config.exts >= 0) {
5085 cpl_msg_info(cpl_func,
5086 "Polynomial fitting for the GAIN (constant term method)");
5088 cpl_msg_info(cpl_func,
5089 "Polynomial fitting for the GAIN (constant term method)"
5090 " for extension nb %d", which_ext);
5092 skip_if(detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, nsets));
5094 skip_if(detmon_lg_qc_med(gain_table, gaint_qclist, nsets));
5099 if(detmon_lg_config.lamp_ok) {
5100 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
5101 detmon_lg_config.cr));
5102 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
5103 DETMON_QC_LAMP_FLUX_C));
5107 if(detmon_lg_config.autocorr == TRUE) {
5108 autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
5109 skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
5111 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
5112 DETMON_QC_AUTOCORR_C));
5114 if (detmon_lg_config.exts >= 0) {
5115 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix");
5117 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix"
5118 " for extension nb %d", which_ext);
5121 if(!detmon_lg_config.pix2pix) {
5124 y = cpl_vector_wrap(nsets,
5125 (
double *)cpl_table_get_data_double_const(linear_table,
5128 if (opt_nir == NIR) {
5129 x = cpl_vector_wrap(nsets,
5130 (
double *)cpl_table_get_data_double_const(linear_table,
5133 x = cpl_vector_wrap(nsets,
5134 (
double *)cpl_table_get_data_double_const(linear_table,
5138 if(x == NULL || y == NULL) {
5139 cpl_vector_unwrap((cpl_vector *)x);
5140 cpl_vector_unwrap((cpl_vector *)y);
5150 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
5151 poly_linfit = irplib_polynomial_fit_1d_create(x, y,
5152 detmon_lg_config.order,
5155 if(detmon_lg_config.order == cpl_vector_get_size(x) - 1) {
5156 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5160 if(poly_linfit == NULL) {
5161 cpl_vector_unwrap((cpl_vector *)x);
5162 cpl_vector_unwrap((cpl_vector *)y);
5168 min_val=cpl_vector_get_min(y);
5169 max_val=cpl_vector_get_max(y);
5171 cpl_vector_unwrap((cpl_vector *)x);
5172 cpl_vector_unwrap((cpl_vector *)y);
5174 for(deg = 0; deg <= detmon_lg_config.order; deg++) {
5175 const double coeff =
5176 cpl_polynomial_get_coeff(poly_linfit, °);
5178 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
5179 assert(name_o != NULL);
5180 skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
5181 skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
5182 DETMON_QC_LIN_COEF_C));
5185 pcoeffs[deg] = coeff;
5187 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
5188 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
5189 DETMON_QC_ERRFIT_MSE_C));
5194 y = cpl_vector_wrap(nsets,
5195 (
double *)cpl_table_get_data_double_const(linear_table,
5200 x = cpl_vector_wrap(nsets,
5201 (
double *)cpl_table_get_data_double_const(linear_table,
5204 x = cpl_vector_wrap(nsets,
5205 (
double *)cpl_table_get_data_double_const(linear_table,
5210 first = cpl_imagelist_get_const(linearity_inputs, 0);
5211 sizex = cpl_image_get_size_x(first);
5212 sizey = cpl_image_get_size_y(first);
5213 vsize = cpl_vector_get_size(x);
5214 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
5216 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,
5217 detmon_lg_config.order, FALSE,
5218 CPL_TYPE_FLOAT, fiterror);
5219 min_val=cpl_vector_get_min(y);
5220 max_val=cpl_vector_get_max(y);
5221 cpl_vector_unwrap((cpl_vector*)x);
5222 cpl_vector_unwrap((cpl_vector*)y);
5224 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
5225 "Failed polynomial fit");
5228 for(deg = 0; deg <= detmon_lg_config.order; deg++)
5230 cpl_image *image = cpl_imagelist_get(*coeffs_ptr, deg);
5231 const double coeff = cpl_image_get_median(image);
5232 pcoeffs[deg] = coeff;
5233 name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", (
int)deg);
5234 name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", (
int)deg);
5235 assert(name_o1 != NULL);
5236 assert(name_o2 != NULL);
5237 skip_if(cpl_propertylist_append_double(linc_qclist, name_o1, coeff));
5238 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o1,
5239 DETMON_QC_LIN_COEF_C));
5242 skip_if(cpl_propertylist_append_double(linc_qclist, name_o2,
5243 cpl_image_get_stdev(image)));
5244 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o2,
5245 DETMON_QC_LIN_COEF_ERR_C));
5251 if(detmon_lg_config.order == vsize - 1)
5253 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5254 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5256 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5257 DETMON_QC_ERRFIT_C));
5260 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5261 cpl_image_get_median(fiterror)));
5262 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5263 DETMON_QC_ERRFIT_C));
5267 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
5269 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
5270 DETMON_QC_COUNTS_MIN_C));
5271 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
5273 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
5274 DETMON_QC_COUNTS_MAX_C));
5275 skip_if(detmon_lg_lineff(pcoeffs,lint_qclist,detmon_lg_config.ref_level,
5276 detmon_lg_config.order));
5278 if (detmon_lg_config.exts >= 0)
5280 cpl_msg_info(cpl_func,
"Bad pixel detection");
5283 cpl_msg_info(cpl_func,
"Bad pixel detection"
5284 " for extension nb %d", which_ext);
5286 if(detmon_lg_config.pix2pix)
5294 x = cpl_vector_wrap(nsets,
5295 (
double *)cpl_table_get_data_double_const(linear_table,
5298 x = cpl_vector_wrap(nsets,
5299 (
double *)cpl_table_get_data_double_const(linear_table,
5305 int sz = cpl_imagelist_get_size(linearity_inputs);
5306 int sx=cpl_image_get_size_x(cpl_imagelist_get(linearity_inputs,0));
5307 int sy=cpl_image_get_size_y(cpl_imagelist_get(linearity_inputs,0));
5309 double kappa= detmon_lg_config.kappa;
5310 int niter=detmon_lg_config.niter;
5312 int llx=detmon_lg_config.llx;
5313 int urx=detmon_lg_config.urx;
5315 int lly=detmon_lg_config.lly;
5316 int ury=detmon_lg_config.ury;
5320 cpl_image* ima, *err;
5324 cpl_imagelist* errors=cpl_imagelist_new();
5350 cpl_imagelist* linearity_scaled=cpl_imagelist_new();
5352 gain=cpl_propertylist_get_double(gaint_qclist,DETMON_QC_GAIN);
5357 gain = (gain<0) ? 1: gain;
5358 double gain_eff=2*gain;
5370 for(
int i=0;i<sz;i++) {
5371 ima=cpl_imagelist_get(linearity_inputs,i);
5372 sprintf(fname,
"pippo%d.fits",i);
5373 cpl_image_save(ima, fname,CPL_BPP_IEEE_FLOAT,NULL, CPL_IO_DEFAULT);
5381 skip_if(irplib_ksigma_clip(ima, 1, 1, urx-llx+1, ury-lly+1, kappa,
5382 niter, 1e-5, &avg, &rms));
5387 if(avg < detmon_lg_config.saturation_limit) {
5395 cpl_image_get_mad(ima,&dmad);
5396 err=cpl_image_duplicate(ima);
5397 cpl_image_multiply_scalar(err,0);
5398 cpl_image_add_scalar(err,dmad*CPL_MATH_STD_MAD);
5408 cpl_imagelist_set(errors,err,i);
5415 skip_if(cpl_imagelist_set(linearity_scaled,cpl_image_duplicate(ima),i));
5419 hdrl_imagelist* hil= hdrl_imagelist_create(linearity_scaled,errors);
5424 cpl_imagelist_delete(errors);
5427 p = hdrl_bpm_fit_parameter_create_pval(1, pval);
5440 hdrl_bpm_fit_compute(p, hil, x, bpms_ptr);
5466 nbpixs=cpl_image_get_flux(*bpms_ptr);
5473 hdrl_imagelist_delete(hil);
5475 cpl_imagelist_delete(linearity_scaled);
5476 cpl_vector_unwrap((cpl_vector*)x);
5477 hdrl_parameter_delete(p);
5494 skip_if(*bpms_ptr == NULL);
5500 skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
5501 skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
5502 DETMON_QC_NUM_BPM_C));
5503 cpl_msg_info(cpl_func,
"stability=%g",detmon_lg_config.lamp_stability);
5504 if(detmon_lg_config.lamp_stability != 0.0)
5506 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
5507 detmon_lg_config.lamp_stability));
5508 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
5509 DETMON_QC_LAMP_STAB_C));
5512 if (!detmon_lg_config.wholechip && detmon_lg_config.pix2pix)
5514 detmon_lg_fits_coeffs_and_bpm2chip(coeffs_ptr,bpms_ptr);
5521 cpl_image_delete(fiterror);
5522 cpl_polynomial_delete(poly_linfit);
5526 return cpl_error_get_code();
5538 static cpl_error_code
5539 detmon_lg_lineff(
double * pcoeffs,
5540 cpl_propertylist * qclist,
5546 double residual, slope;
5549 cpl_polynomial * poly = cpl_polynomial_new(1);
5563 pcoeffs[0] -= ref_level;
5565 for (i = 2; i <= order; i++)
5568 for(j = 0; j < i; j++)
5570 pcoeffs[i] /= pcoeffs[1];
5576 for (deg = 0; deg <= order; deg++) {
5578 skip_if(cpl_polynomial_set_coeff(poly, °, pcoeffs[deg]));
5587 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
5589 if (slope <= 0.0 && residual >= 0.0) {
5590 cpl_msg_warning(cpl_func,
"Reference level (--ref_level) outside"
5591 " linearity range of the detector. Cannot compute"
5592 " linearity efficiency (QC.LINEFF).");
5597 cpl_error_code err = cpl_polynomial_solve_1d(poly, 0.0, &root, 1);
5602 if (err == CPL_ERROR_NONE)
5605 lineff = (root - ref_level) / ref_level;
5610 cpl_msg_warning(cpl_func,
5611 "Cannot compute linearity efficiency (QC.LINEFF)"
5612 "for the current combination "
5613 " of (--ref-level equal %d) and (--order equal %d) parameters. Try "
5614 "to decrease (--ref-level) value.", ref_level, order);
5617 cpl_msg_warning(cpl_func,
"DETMON_QC_LIN_EFF=%f",lineff );
5618 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
5620 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
5621 DETMON_QC_LIN_EFF_C));
5623 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
5625 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
5626 DETMON_QC_LIN_EFF_FLUX_C));
5630 cpl_polynomial_delete(poly);
5632 return cpl_error_get_code();
5643 static cpl_error_code
5644 detmon_lg_qc_ptc(
const cpl_table * gain_table,
5645 cpl_propertylist * qclist,
unsigned mode,
int rows_in_gain)
5648 cpl_polynomial *poly_fit = NULL;
5649 cpl_polynomial *poly_fit2 = NULL;
5651 const int nsets = rows_in_gain;
5653 cpl_vector *x = NULL;
5654 cpl_vector *y = NULL;
5656 cpl_errorstate prestate;
5658 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
5659 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
5661 x = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5663 y = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5665 skip_if(x == NULL || y == NULL);
5666 if (0 == detmon_lg_check_before_gain(x, y))
5670 cpl_vector_unwrap(x);
5674 cpl_vector_unwrap(y);
5676 return CPL_ERROR_NONE;
5679 poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
5680 skip_if(poly_fit == NULL);
5684 prestate = cpl_errorstate_get();
5685 coef = cpl_polynomial_get_coeff(poly_fit, &i);
5686 skip_if (!cpl_errorstate_is_equal(prestate) || coef==0);
5687 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
5688 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5689 DETMON_QC_CONAD_C));
5692 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
5694 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
5710 if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
5711 const cpl_vector *x2 =
5712 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT_CORR"));
5713 const cpl_vector *y2 =
5714 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5716 if(x2 == NULL || y2 == NULL) {
5717 cpl_vector_unwrap((cpl_vector *)x2);
5718 cpl_vector_unwrap((cpl_vector *)y2);
5729 poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
5730 if(poly_fit2 == NULL) {
5731 cpl_vector_unwrap((cpl_vector *)x2);
5732 cpl_vector_unwrap((cpl_vector *)y2);
5734 cpl_msg_error(cpl_func,
"Error during polynomial fit, err[%s]", cpl_error_get_where());
5738 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5739 cpl_vector_unwrap((cpl_vector *)x2);
5740 cpl_vector_unwrap((cpl_vector *)y2);
5741 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5744 prestate = cpl_errorstate_get();
5745 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
5746 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5747 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
5749 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
5751 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
5752 DETMON_QC_CONAD_CORR_C));
5754 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
5756 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
5757 DETMON_QC_GAIN_CORR_C));
5763 cpl_vector_unwrap(x);
5764 cpl_vector_unwrap(y);
5765 cpl_polynomial_delete(poly_fit);
5766 cpl_polynomial_delete(poly_fit2);
5768 return cpl_error_get_code();
5777 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y)
5779 const double TOLERANCE = 1e-37;
5780 double xmin = cpl_vector_get_min(x);
5781 double xmax = cpl_vector_get_max(x);
5782 double ymin = cpl_vector_get_min(y);
5783 double ymax = cpl_vector_get_max(y);
5784 double ystdev = cpl_vector_get_stdev(y);
5785 double xstdev = cpl_vector_get_stdev(x);
5787 if (fabs(xmax-xmin) < TOLERANCE &&
5788 fabs(ymax - ymin) < TOLERANCE &&
5789 xstdev < TOLERANCE &&
5792 cpl_msg_warning(cpl_func,
"An empty frame has been detected, linearity, coeffs, gain, FPN values will not be computed.");
5807 static cpl_error_code
5808 detmon_lg_qc_med(
const cpl_table * gain_table,
5809 cpl_propertylist * qclist,
int rows_in_gain)
5813 cpl_vector *x = NULL;
5814 cpl_vector *y = NULL;
5815 int check_result = 0;
5817 if (rows_in_gain) {};
5819 x = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5820 y = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5821 check_result = detmon_lg_check_before_gain(x, y);
5824 cpl_vector_unwrap(x);
5828 cpl_vector_unwrap(y);
5830 if (0 == check_result)
5832 return CPL_ERROR_NONE;
5835 gain=cpl_table_get_column_median(gain_table,
"GAIN");
5837 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
5839 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
5842 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
5843 cpl_table_get_column_stdev
5844 (gain_table,
"GAIN")));
5845 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
5846 DETMON_QC_GAIN_MSE_C));
5848 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
5849 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5850 DETMON_QC_CONAD_C));
5853 gain=cpl_table_get_column_median(gain_table,
"GAIN_CORR");
5855 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
5857 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
5858 DETMON_QC_GAIN_CORR_C));
5861 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
5862 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
5863 DETMON_QC_CONAD_CORR_C));
5868 return cpl_error_get_code();
5882 static cpl_error_code
5883 detmon_lg_rescale(cpl_imagelist * to_rescale)
5886 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 0),
5887 detmon_lg_config.llx,
5888 detmon_lg_config.lly,
5889 detmon_lg_config.urx,
5890 detmon_lg_config.ury);
5892 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 1),
5893 detmon_lg_config.llx,
5894 detmon_lg_config.lly,
5895 detmon_lg_config.urx,
5896 detmon_lg_config.ury);
5900 if(fabs(med1 / med2 - 1) > 0.001) {
5902 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
5905 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
5911 return cpl_error_get_code();
5914 static cpl_error_code
5915 detmon_pair_extract_next(
const cpl_frameset * set,
5919 cpl_frameset ** pair,
5923 double dit_next = -100;
5924 cpl_size* selection;
5925 int nsets_extracted = 0;
5926 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
5927 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
5928 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
5929 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
5931 nsets_extracted = cpl_frameset_get_size(set);
5932 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
5933 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
5936 dit = dit_array[*next_element ];
5938 if (*next_element < nsets_extracted - 1)
5940 dit_next = dit_array[*next_element + 1 ];
5944 selection[iindex[*next_element] ] = 1;
5945 if (fabs(dit - dit_next) < tolerance)
5948 selection[iindex[*next_element + 1] ] = 1;
5953 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);
5957 cpl_frameset_delete(*pair);
5958 *pair = cpl_frameset_extract(set, selection, 1);
5961 cpl_free(selection);
5962 return cpl_error_get_code();
5965 static cpl_error_code
5966 detmon_single_extract_next(
const cpl_frameset * set,
5970 cpl_frameset ** pair)
5972 cpl_size* selection;
5973 int nsets_extracted = 0;
5974 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
5975 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
5976 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
5977 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
5979 nsets_extracted = cpl_frameset_get_size(set);
5980 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
5981 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
5984 selection[iindex[*next_element] ] = 1;
5987 cpl_frameset_delete(*pair);
5988 *pair = cpl_frameset_extract(set, selection, 1);
5990 cpl_free(selection);
5991 return cpl_error_get_code();
6087 detmon_gain(
const cpl_imagelist * imlist_on,
6088 const cpl_imagelist * imlist_off,
6089 const cpl_vector * exptimes,
6090 const cpl_vector * ndit,
6100 cpl_propertylist * qclist,
6102 cpl_imagelist ** diff_imlist,
6103 cpl_imagelist ** autocorr_imlist)
6105 cpl_table * gain_table = NULL;
6106 cpl_imagelist * difflist = NULL;
6107 cpl_imagelist * autocorrlist = NULL;
6108 cpl_imagelist * c_onlist = NULL;
6109 cpl_imagelist * c_offlist = NULL;
6110 cpl_vector * diffdits = NULL;
6111 cpl_vector * diffndits = NULL;
6112 int rows_in_gain = 0;
6113 int ndiffdits, ndits;
6115 cpl_boolean opt_nir = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
6116 const char * method = mode & IRPLIB_GAIN_PTC ?
"PTC" :
"MED";
6118 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6119 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6120 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6121 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6124 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6125 skip_if(detmon_gain_table_create(gain_table, opt_nir));
6129 skip_if(detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,
6131 ndiffdits = cpl_vector_get_size(diffdits);
6133 ndits = cpl_vector_get_size(exptimes);
6136 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
6137 difflist = cpl_imagelist_new();
6138 autocorrlist = cpl_imagelist_new();
6141 if (mode & IRPLIB_GAIN_COLLAPSE) {
6142 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6143 c_offlist = cpl_imagelist_duplicate(imlist_off);
6144 skip_if(detmon_lg_rescale(c_offlist));
6146 c_offlist = (cpl_imagelist *) imlist_off;
6151 for (i = 0; i < ndiffdits; i++) {
6158 c_dit=cpl_vector_get(diffdits, i);
6161 c_ndit=(int)cpl_vector_get(diffndits, i);
6164 c_onlist = cpl_imagelist_new();
6167 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6168 c_offlist = cpl_imagelist_new();
6173 for(j = 0; j < ndits; j++) {
6174 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6184 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6185 const cpl_image * im =
6186 cpl_imagelist_get_const(imlist_on, j);
6187 im_on = cpl_image_duplicate(im);
6189 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6191 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6198 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6200 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6201 const cpl_image * im =
6202 cpl_imagelist_get_const(imlist_off, j);
6203 im_off = cpl_image_duplicate(im);
6206 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6208 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6215 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6216 skip_if (c_nons != c_noffs);
6219 skip_if (c_nons == 0 || c_nons % 2 != 0);
6222 if(mode & IRPLIB_GAIN_WITH_RESCALE) {
6223 skip_if(detmon_lg_rescale(c_onlist));
6224 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6225 skip_if(detmon_lg_rescale(c_offlist));
6231 int rows_affected = 1;
6232 skip_if(detmon_gain_table_fill_row(gain_table,
6236 c_offlist, kappa, nclip,
6238 xshift, yshift,1E10, i,
6239 mode, &rows_affected));
6244 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6245 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6246 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6247 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6248 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6249 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6252 cpl_imagelist_unset(c_onlist, 0);
6254 cpl_imagelist_unset(c_onlist, 0);
6256 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6257 cpl_imagelist_unset(c_offlist, 0);
6259 cpl_imagelist_unset(c_offlist, 0);
6267 cpl_imagelist_delete(c_onlist);
6268 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6269 cpl_imagelist_delete(c_offlist);
6273 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
6274 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
6275 DETMON_QC_METHOD_C));
6278 if (mode & IRPLIB_GAIN_PTC) {
6279 skip_if(detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
6281 skip_if(detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
6284 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
6285 double autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
6286 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
6288 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
6289 DETMON_QC_AUTOCORR_C));
6292 if (diff_imlist != NULL) *diff_imlist = difflist;
6293 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
6297 cpl_vector_delete(diffdits);
6298 cpl_vector_delete(diffndits);
6303 static cpl_error_code
6304 detmon_gain_table_create(cpl_table * gain_table,
6305 const cpl_boolean opt_nir)
6307 if (opt_nir == NIR) {
6308 skip_if(cpl_table_new_column(gain_table,
"DIT", CPL_TYPE_DOUBLE));
6309 skip_if(cpl_table_new_column(gain_table,
"NDIT", CPL_TYPE_INT));
6311 skip_if(cpl_table_new_column(gain_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6313 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON1", CPL_TYPE_DOUBLE));
6314 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON2", CPL_TYPE_DOUBLE));
6315 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF1", CPL_TYPE_DOUBLE));
6316 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF2", CPL_TYPE_DOUBLE));
6317 skip_if(cpl_table_new_column(gain_table,
"SIG_ON_DIF", CPL_TYPE_DOUBLE));
6318 skip_if(cpl_table_new_column(gain_table,
"SIG_OFF_DIF", CPL_TYPE_DOUBLE));
6319 skip_if(cpl_table_new_column(gain_table,
"GAIN", CPL_TYPE_DOUBLE));
6320 skip_if(cpl_table_new_column(gain_table,
"AUTOCORR", CPL_TYPE_DOUBLE));
6321 skip_if(cpl_table_new_column(gain_table,
"GAIN_CORR", CPL_TYPE_DOUBLE));
6322 skip_if(cpl_table_new_column(gain_table,
"ADU", CPL_TYPE_DOUBLE));
6323 skip_if(cpl_table_new_column(gain_table,
"X_FIT", CPL_TYPE_DOUBLE));
6324 skip_if(cpl_table_new_column(gain_table,
"X_FIT_CORR", CPL_TYPE_DOUBLE));
6325 skip_if(cpl_table_new_column(gain_table,
"Y_FIT", CPL_TYPE_DOUBLE));
6326 skip_if(cpl_table_new_column(gain_table,
"Y_FIT_CORR", CPL_TYPE_DOUBLE));
6327 skip_if(cpl_table_new_column(gain_table,
"FLAG", CPL_TYPE_INT));
6331 return cpl_error_get_code();
6334 static cpl_error_code
6335 detmon_lin_table_create(cpl_table * lin_table,
6336 const cpl_boolean opt_nir)
6338 if (opt_nir == NIR) {
6339 skip_if(cpl_table_new_column(lin_table,
"DIT", CPL_TYPE_DOUBLE));
6341 skip_if(cpl_table_new_column(lin_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6343 skip_if(cpl_table_new_column(lin_table,
"MED", CPL_TYPE_DOUBLE));
6344 skip_if(cpl_table_new_column(lin_table,
"MEAN", CPL_TYPE_DOUBLE));
6345 skip_if(cpl_table_new_column(lin_table,
"MED_DIT", CPL_TYPE_DOUBLE));
6346 skip_if(cpl_table_new_column(lin_table,
"MEAN_DIT", CPL_TYPE_DOUBLE));
6347 skip_if(cpl_table_new_column(lin_table,
"ADL", CPL_TYPE_DOUBLE));
6350 return cpl_error_get_code();
6354 detmon_lg_find_dits(
const cpl_vector * exptimes,
6357 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6363 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
6367 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
6369 for (j = 0; j < ndits; j++) {
6370 if (fabs(cpl_vector_get(exptimes, i) -
6371 cpl_vector_get(dits, j)) > tolerance)
6374 if(ndiffs == ndits) {
6375 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
6380 cpl_vector_set_size(dits, ndits);
6388 static cpl_error_code
6389 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
6390 const cpl_vector * vec_ndits,
6392 cpl_vector** diff_dits,
6393 cpl_vector** diff_ndits)
6401 * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6402 * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
6405 cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
6406 cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
6409 size=cpl_vector_get_size(exptimes);
6411 for(i = 1; i < size; i++) {
6413 for (j = 0; j < ndits; j++) {
6414 if (fabs(cpl_vector_get(exptimes, i) -
6415 cpl_vector_get(*diff_dits,j)) > tolerance)
6418 if(ndiffs == ndits) {
6419 cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
6420 cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
6425 cpl_vector_set_size(*diff_dits, ndits);
6426 cpl_vector_set_size(*diff_ndits, ndits);
6429 return cpl_error_get_code();
6517 detmon_lin(
const cpl_imagelist * imlist_on,
6518 const cpl_imagelist * imlist_off,
6519 const cpl_vector * exptimes,
6529 cpl_propertylist * qclist,
6531 cpl_imagelist ** coeffs_cube,
6534 cpl_table * lin_table = NULL;
6535 cpl_imagelist * c_onlist = NULL;
6536 cpl_imagelist * c_offlist = NULL;
6537 cpl_vector * diffdits = NULL;
6538 cpl_imagelist * lin_inputs = NULL;
6539 cpl_polynomial * poly_linfit = NULL;
6540 cpl_image * fiterror = NULL;
6541 cpl_vector * vcoeffs = NULL;
6542 double * pcoeffs = NULL;
6543 int ndiffdits, ndits;
6545 cpl_boolean opt_nir = mode & IRPLIB_LIN_OPT ? OPT : NIR;
6546 const cpl_vector *x = NULL;
6547 const cpl_vector *y = NULL;
6549 const cpl_image * first = NULL;
6557 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6558 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6559 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6560 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6561 cpl_ensure(order > 0 , CPL_ERROR_ILLEGAL_INPUT, NULL);
6563 vcoeffs = cpl_vector_new(order + 1);
6564 pcoeffs = cpl_vector_get_data(vcoeffs);
6567 if (mode & IRPLIB_LIN_PIX2PIX) {
6568 cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
6569 cpl_ensure(bpm != NULL, CPL_ERROR_NULL_INPUT, NULL);
6570 lin_inputs = cpl_imagelist_new();
6574 lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6575 skip_if(detmon_lin_table_create(lin_table, opt_nir));
6579 diffdits = detmon_lg_find_dits(exptimes, tolerance);
6580 ndiffdits = cpl_vector_get_size(diffdits);
6582 ndits = cpl_vector_get_size(exptimes);
6612 if (mode & IRPLIB_LIN_COLLAPSE) {
6617 cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
6618 skip_if(collapse == NULL);
6620 c_offlist = cpl_imagelist_new();
6621 skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
6625 for (i = 0; i < ndiffdits; i++) {
6629 double c_dit = cpl_vector_get(diffdits, i);
6631 c_onlist = cpl_imagelist_new();
6634 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6635 c_offlist = cpl_imagelist_new();
6639 for(j = 0; j < ndits; j++) {
6640 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6650 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6651 const cpl_image * im =
6652 cpl_imagelist_get_const(imlist_on, j);
6653 im_on = cpl_image_duplicate(im);
6655 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6657 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6664 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6666 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6667 const cpl_image * im =
6668 cpl_imagelist_get_const(imlist_off, j);
6669 im_off = cpl_image_duplicate(im);
6672 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6674 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6681 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6682 skip_if (c_nons != c_noffs);
6685 skip_if (c_nons == 0 || c_nons % 2 != 0);
6688 if(mode & IRPLIB_LIN_WITH_RESCALE) {
6689 skip_if(detmon_lg_rescale(c_onlist));
6690 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6691 skip_if(detmon_lg_rescale(c_offlist));
6698 skip_if(detmon_lin_table_fill_row(lin_table, c_dit,
6700 c_onlist, c_offlist,
6704 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6705 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6706 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6707 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6708 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6709 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6712 cpl_imagelist_unset(c_onlist, 0);
6714 cpl_imagelist_unset(c_onlist, 0);
6716 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6717 cpl_imagelist_unset(c_offlist, 0);
6719 cpl_imagelist_unset(c_offlist, 0);
6727 cpl_imagelist_delete(c_onlist);
6728 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6729 cpl_imagelist_delete(c_offlist);
6733 skip_if(detmon_add_adl_column(lin_table, opt_nir));
6735 if(!(mode & IRPLIB_LIN_PIX2PIX)) {
6738 y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6739 (
double *)cpl_table_get_data_double_const(lin_table,
6741 if (opt_nir == NIR) {
6742 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6743 (
double *)cpl_table_get_data_double_const(lin_table,
"DIT"));
6745 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6746 (
double *)cpl_table_get_data_double_const(lin_table,
"EXPTIME"));
6748 if(x == NULL || y == NULL) {
6749 cpl_vector_unwrap((cpl_vector *)x);
6750 cpl_vector_unwrap((cpl_vector *)y);
6760 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
6761 poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
6763 if(order == cpl_vector_get_size(x) - 1) {
6764 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
6768 if(poly_linfit == NULL) {
6769 cpl_vector_unwrap((cpl_vector *)x);
6770 cpl_vector_unwrap((cpl_vector *)y);
6775 cpl_vector_unwrap((cpl_vector *)x);
6776 cpl_vector_unwrap((cpl_vector *)y);
6778 for(deg = 0; deg <= order; deg++) {
6779 const double coeff =
6780 cpl_polynomial_get_coeff(poly_linfit, °);
6782 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
6783 assert(name_o != NULL);
6784 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
6785 skip_if(cpl_propertylist_set_comment(qclist,name_o,
6786 DETMON_QC_LIN_COEF_C));
6788 pcoeffs[deg] = coeff;
6790 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
6791 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
6792 DETMON_QC_ERRFIT_MSE_C));
6796 if (opt_nir == NIR) {
6797 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6798 (
double *)cpl_table_get_data_double_const(lin_table,
6801 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6802 (
double *)cpl_table_get_data_double_const(lin_table,
6807 first = cpl_imagelist_get_const(lin_inputs, 0);
6808 sizex = cpl_image_get_size_x(first);
6809 sizey = cpl_image_get_size_y(first);
6811 vsize = cpl_vector_get_size(x);
6813 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
6816 cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
6817 order, FALSE, CPL_TYPE_FLOAT,
6820 cpl_vector_unwrap((cpl_vector*)x);
6821 irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
6822 "Failed polynomial fit");
6824 for(i = 0; i <= order; i++) {
6825 cpl_image *image = cpl_imagelist_get(*coeffs_cube, i);
6826 const double coeff = cpl_image_get_median(image);
6827 char * name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", i);
6828 char * name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", i);
6830 assert(name_o1 != NULL);
6831 assert(name_o2 != NULL);
6832 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
6833 skip_if(cpl_propertylist_set_comment(qclist,name_o1,
6834 DETMON_QC_LIN_COEF_C));
6837 skip_if(cpl_propertylist_append_double(qclist, name_o2,
6838 cpl_image_get_stdev(image)));
6839 skip_if(cpl_propertylist_set_comment(qclist,name_o2,
6840 DETMON_QC_LIN_COEF_ERR_C));
6845 if(order == vsize - 1) {
6846 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
6847 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
6849 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
6850 DETMON_QC_ERRFIT_C));
6854 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
6855 cpl_image_get_median(fiterror)));
6856 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
6857 DETMON_QC_ERRFIT_C));
6862 skip_if(detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
6864 if(mode & IRPLIB_LIN_PIX2PIX) {
6866 *bpm = detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
6867 skip_if(*bpm == NULL);
6868 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
6870 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
6871 DETMON_QC_NUM_BPM_C));
6876 cpl_vector_delete(diffdits);
6877 cpl_polynomial_delete(poly_linfit);
6878 cpl_imagelist_delete(lin_inputs);
6879 cpl_vector_delete(vcoeffs);
6880 cpl_image_delete(fiterror);
6911 static cpl_error_code
6912 detmon_lin_table_fill_row(cpl_table * lin_table,
double c_dit,
6913 cpl_imagelist * linearity_inputs,
6914 const cpl_imagelist * ons,
6915 const cpl_imagelist * offs,
6924 cpl_image * extracted=NULL;
6926 cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
6927 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
6928 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
6930 if (mode & IRPLIB_LIN_PIX2PIX) {
6931 cpl_msg_debug(cpl_func,
"checking linearity inputs");
6932 cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
6936 if (mode & IRPLIB_LIN_NIR) {
6937 cpl_table_set(lin_table,
"DIT", pos, c_dit);
6938 }
else if (mode & IRPLIB_LIN_OPT) {
6939 cpl_table_set(lin_table,
"EXPTIME", pos, c_dit);
6941 cpl_msg_error(cpl_func,
"Mandatory mode not given");
6945 const cpl_image * off2;
6946 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
6947 off2 = cpl_imagelist_get_const(offs, 0);
6949 off2 = cpl_imagelist_get_const(offs, 1);
6951 extracted = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
6952 cpl_imagelist_get_const(offs, 0),
6953 cpl_imagelist_get_const(ons, 1),
6955 llx, lly, urx, ury);
6956 cpl_ensure_code(extracted != NULL, cpl_error_get_code());
6960 double median = cpl_image_get_median(extracted);
6961 double mean= cpl_image_get_mean(extracted);
6962 cpl_table_set(lin_table,
"MED", pos, median);
6963 cpl_table_set(lin_table,
"MEAN", pos, mean);
6965 cpl_table_set(lin_table,
"MED_DIT", pos, median / c_dit);
6966 cpl_table_set(lin_table,
"MEAN_DIT", pos, mean / c_dit);
6970 if(mode & IRPLIB_LIN_PIX2PIX) {
6971 cpl_error_code error = cpl_imagelist_set(linearity_inputs, extracted,
6973 cpl_ensure_code(!error, error);
6975 cpl_image_delete(extracted);
6978 return cpl_error_get_code();
6981 static double irplib_calculate_total_noise_smooth(
const cpl_image* pimage,
6982 int pattern_x,
int pattern_y)
6984 cpl_image * p_tmp_image = 0;
6985 cpl_image * psmooth_image = 0;
6987 cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
6989 p_tmp_image = cpl_image_duplicate(pimage);
6990 cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
6991 cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
6992 psmooth_image = cpl_image_divide_create(pimage,p_tmp_image);
6993 ret_noise = irplib_calculate_total_noise(psmooth_image);
6994 cpl_mask_delete(mask);
6995 cpl_image_delete(psmooth_image);
6996 cpl_image_delete(p_tmp_image);
7000 static double irplib_calculate_total_noise(
const cpl_image* pimage)
7002 double total_noise = -1;
7003 unsigned long max_bin_size = 1E5;
7004 const double hstart = cpl_image_get_min(pimage);
7005 const double hrange = cpl_image_get_max(pimage) - hstart;
7006 const unsigned long nbins = max_bin_size;
7007 cpl_error_code err = CPL_ERROR_NONE;
7009 irplib_hist * phist = 0;
7010 phist = irplib_hist_new();
7013 irplib_hist_init(phist, nbins, hstart, hrange);
7014 err = irplib_hist_fill(phist, pimage);
7015 if (err == CPL_ERROR_NONE)
7023 unsigned long n_bins = irplib_hist_get_nbins(phist);
7024 double start = irplib_hist_get_start(phist);
7025 double bin_size = irplib_hist_get_bin_size(phist);
7026 cpl_vector* pdata_vector = cpl_vector_new(n_bins);
7027 cpl_vector* ppos_vector = cpl_vector_new(n_bins);
7028 cpl_table* ptable = cpl_table_new(n_bins);
7029 cpl_table_new_column(ptable,
"bin", CPL_TYPE_DOUBLE);
7030 cpl_table_new_column(ptable,
"value", CPL_TYPE_DOUBLE);
7031 for(i = 0; i < n_bins; i++)
7033 unsigned int value = irplib_hist_get_value(phist, i);
7034 double dvalue = (double)(value);
7035 cpl_vector_set(pdata_vector, i, dvalue);
7036 cpl_vector_set(ppos_vector, i, start + i * bin_size);
7038 cpl_table_set(ptable,
"bin", i, start + i * bin_size);
7039 cpl_table_set(ptable,
"value", i, dvalue);
7041 err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
7042 if (err == CPL_ERROR_NONE)
7044 cpl_msg_info(cpl_func,
"FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
7048 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed Gaussian Fit, err msg [%s]", cpl_error_get_message());
7051 cpl_table_delete(ptable);
7052 cpl_vector_delete(ppos_vector);
7053 cpl_vector_delete(pdata_vector);
7057 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
7060 irplib_hist_delete(phist);
7065 static double irplib_compute_err(
double gain,
double ron,
double FA)
7067 double int_gain = (gain * gain - 1) / 12;
7072 return sqrt(ron * ron + FA / gain + int_gain);
7075 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain ,
7076 FPN_METHOD fpn_method,
int smooth_size,
double* mse)
7078 cpl_image* im_diff = 0;
7079 const cpl_image* im_f1 = f1;
7080 cpl_image* im_inrange1 = 0;
7089 cpl_msg_warning(cpl_func,
"gain[%f]<0", gain);
7090 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7097 im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
7098 im_f1 = im_inrange1;
7100 FA = cpl_image_get_median(im_f1);
7107 cpl_msg_info(cpl_func,
"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
7108 s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
7111 cpl_msg_info(cpl_func,
"HISTOGRAM method is used for FPN");
7112 s_tot = irplib_calculate_total_noise(im_f1);
7117 cpl_msg_warning(cpl_func,
"fpn_method is not defined");
7126 cpl_msg_warning(cpl_func,
"Median flux on sum of flats<0");
7127 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7132 if ((s_tot * s_tot - FA / gain) > 0)
7134 s_fpn = sqrt(s_tot * s_tot - FA / gain);
7135 sr_fpn = s_fpn / FA;
7136 *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
7140 cpl_msg_warning(cpl_func,
"s_tot * s_tot < FA / gain");
7141 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7150 cpl_image_delete(im_diff);
7153 cpl_image_delete(im_inrange1);
7159 static cpl_imagelist * irplib_load_fset_wrp(
const cpl_frameset * pframeset,
7160 cpl_type type ,
int whichext)
7164 return detmon_load_frameset_window(pframeset, type, 0, whichext,
7165 detmon_lg_config.llx,
7166 detmon_lg_config.lly,
7167 detmon_lg_config.urx,
7168 detmon_lg_config.ury,
7169 detmon_lg_config.nx,
7170 detmon_lg_config.ny);
7173 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset * pframeset,
7174 cpl_type type ,
int whichext)
7177 cpl_imagelist* offs = cpl_imagelist_new();
7178 detmon_lg_config.load_fset(pframeset, type, offs);
7183 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
7184 cpl_propertylist* plist)
7186 if (ptable && plist)
7188 int size = cpl_propertylist_get_size(plist);
7190 for (i = 0; i < size; i++)
7192 cpl_property* pprop = cpl_propertylist_get(plist,i);
7195 const char* pname = cpl_property_get_name(pprop);
7198 cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
7199 if (cpl_error_get_code() != CPL_ERROR_NONE)
7201 cpl_msg_warning(cpl_func,
"cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
7208 return cpl_error_get_code();
7211 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
7212 cpl_propertylist* plist,
int row)
7214 cpl_error_code err = CPL_ERROR_NONE;
7215 if (ptable && plist)
7217 int size = cpl_propertylist_get_size(plist);
7219 for (i = 0; i < size; i++)
7221 cpl_property* pprop = cpl_propertylist_get(plist,i);
7224 const char* pname = cpl_property_get_name(pprop);
7225 double value = cpl_property_get_double(pprop);
7228 cpl_table_set_double(ptable, pname, row, value);
7229 if (cpl_error_get_code() != CPL_ERROR_NONE)
7231 cpl_msg_warning(cpl_func,
"cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
7242 cpl_error_code detmon_check_order(
const double *exptime,
int sz,
7243 double tolerance,
int order)
7260 }
while(fabs(exptime[i-1] - exptime[i]) < tolerance);
7261 }
while(i < sz - 1);
7263 if (!fabs(exptime[i-1] - exptime[i]) < tolerance) nsets++;
7266 cpl_error_set_message(cpl_func,CPL_ERROR_INCOMPATIBLE_INPUT,
7267 "Not enough frames for the polynomial"
7268 " fitting. nsets = %d <= %d order",
7271 return cpl_error_get_code();
7274 static cpl_error_code
7275 detmon_lg_dfs_save_imagelist(
7276 cpl_frameset * frameset,
7277 const cpl_parameterlist * parlist,
7278 const cpl_frameset *usedframes,
7279 const cpl_imagelist *coeffs,
7280 const char *recipe_name,
7281 const cpl_propertylist *mypro_coeffscube,
7282 const char * package,
7283 const char * name_o)
7285 return(cpl_dfs_save_imagelist
7286 (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
7287 recipe_name, mypro_coeffscube, NULL, package,
7291 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos)
7293 const cpl_image* first = cpl_imagelist_get(imlist, 0);
7296 int x = cpl_image_get_size_x(first);
7297 int y = cpl_image_get_size_y(first);
7298 cpl_type type = cpl_image_get_type(first);
7299 cpl_image * blank = cpl_image_new(x, y, type);
7300 cpl_imagelist_set(imlist, blank, pos);
7306 detmon_lg_set_tag(cpl_frameset* set,
const char** tag_on,
const char** tag_off)
7311 ntag_old=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_OLD);
7312 ntag_new=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_NEW);
7314 *tag_on=DETMON_LG_ON_RAW_OLD;
7315 *tag_off=DETMON_LG_OFF_RAW_OLD;
7316 }
else if (ntag_new) {
7317 *tag_on=DETMON_LG_ON_RAW_NEW;
7318 *tag_off=DETMON_LG_OFF_RAW_NEW;
7320 cpl_msg_error(cpl_func,
"Provide %s and %s (or %s and %s) input frames",
7321 DETMON_LG_ON_RAW_NEW,DETMON_LG_OFF_RAW_NEW,
7322 DETMON_LG_ON_RAW_OLD,DETMON_LG_OFF_RAW_OLD);
7326 return cpl_error_get_code();