43 #include "detmon_utils.h"
44 #include "detmon_lg.h"
45 #include "detmon_lg_impl.h"
46 #include "detmon_dfs.h"
48 #include "irplib_ksigma_clip.h"
49 #include "irplib_utils.h"
50 #include "irplib_hist.h"
74 typedef enum _FPN_METHOD FPN_METHOD;
114 cpl_boolean wholechip;
115 cpl_boolean autocorr;
116 cpl_boolean intermediate;
117 cpl_boolean collapse;
124 const char * pafname;
129 double lamp_stability;
132 int (* load_fset) (
const cpl_frameset *, cpl_type, cpl_imagelist *);
133 cpl_imagelist * (* load_fset_wrp) (
const cpl_frameset *, cpl_type, int);
134 FPN_METHOD fpn_method;
136 double saturation_limit;
137 double gain_threshold;
138 cpl_boolean split_coeffs;
148 static cpl_error_code
149 detmon_lg_retrieve_parlist(
const char *,
150 const char *,
const cpl_parameterlist *,
154 static cpl_error_code
155 detmon_lg_split_onoff(
const cpl_frameset *,
158 const char *,
const char * );
160 static cpl_error_code
161 detmon_lg_reduce(
const cpl_frameset *,
162 const cpl_frameset *,
163 int* index_on,
int* index_off,
164 double* exptime_on,
double* exptime_off,
165 int *next_index_on,
int* next_index_off,
176 int (* load_fset) (
const cpl_frameset *,
179 const cpl_boolean,
int);
184 static cpl_error_code
185 detmon_lin_table_fill_row(cpl_table *,
double,
187 const cpl_imagelist *,
188 const cpl_imagelist *,
194 static cpl_error_code
195 detmon_gain_table_fill_row(cpl_table * gain_table,
196 double c_dit,
int c_ndit,
197 cpl_imagelist * autocorr_images,
198 cpl_imagelist * diff_flats,
199 const cpl_imagelist * ons,
200 const cpl_imagelist * offs,
201 double kappa,
int nclip,
202 int llx,
int lly,
int urx,
int ury,
204 double saturation_limit,
205 double gain_threshold,
206 const int pos,
unsigned mode,
int* rows_affected);
209 static cpl_error_code
210 detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
211 cpl_imagelist * diff_flats,
212 const cpl_imagelist * ons,
213 const cpl_imagelist * offs,
214 double kappa,
int nclip,
215 int llx,
int lly,
int urx,
int ury,
216 double saturation_limit,
217 const int pos,
unsigned mode,
218 int* rows_linear_affected);
220 static cpl_error_code
221 detmon_lg_save(
const cpl_parameterlist *,
226 const cpl_propertylist *,
227 const cpl_propertylist *,
228 const cpl_propertylist *,
229 const cpl_propertylist *,
230 const cpl_propertylist *,
231 const cpl_propertylist *,
243 const int,
const int,
const cpl_frameset *,
246 static cpl_error_code
247 detmon_lg_qc_ptc(
const cpl_table *,
248 cpl_propertylist *,
unsigned,
int);
250 static cpl_error_code
251 detmon_lg_qc_med(
const cpl_table *,
252 cpl_propertylist *,
int);
256 irplib_pfits_get_dit(
const cpl_propertylist *);
259 irplib_pfits_get_dit_opt(
const cpl_propertylist *);
261 irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
262 const char* prop_name);
264 static cpl_image * detmon_bpixs(
const cpl_imagelist *,
265 cpl_boolean,
const double,
int *);
268 detmon_autocorr_factor(
const cpl_image *,
269 cpl_image **,
int,
int);
273 static cpl_error_code
274 detmon_opt_contamination(
const cpl_imagelist *,
275 const cpl_imagelist *,
276 unsigned mode, cpl_propertylist *);
279 detmon_opt_lampcr(cpl_frameset *,
int);
283 detmon_lg_dfs_set_groups(cpl_frameset *,
const char *,
const char *);
285 static cpl_error_code
286 detmon_lg_reduce_all(
const cpl_table *,
293 const cpl_imagelist *,
294 const cpl_table *,
int, cpl_boolean);
296 static cpl_error_code
297 detmon_lg_check_defaults(
const cpl_image *);
299 static cpl_error_code
300 detmon_lg_rescale(cpl_imagelist *);
302 static cpl_error_code
303 detmon_lg_reduce_init(cpl_table *,
309 static cpl_error_code
310 detmon_add_adl_column(cpl_table *, cpl_boolean);
312 static cpl_error_code
313 detmon_lg_lamp_stab(
const cpl_frameset *,
314 const cpl_frameset *,
318 static cpl_error_code
319 detmon_lg_reduce_dit(
const cpl_frameset * set_on,
320 int* index_on,
double* exptime_on,
323 const cpl_frameset * set_off,
324 int * index_off,
double* exptime_off,
325 int* next_on,
int* next_off,
326 cpl_table * linear_table,
327 cpl_table * gain_table,
328 cpl_imagelist * linearity_inputs,
329 cpl_propertylist * qclist,
331 cpl_imagelist * autocorr_images,
332 cpl_imagelist * diff_flats,
333 cpl_imagelist * opt_offs,
335 int * rows_linear_affected,
336 int * rows_gain_affected);
338 static cpl_error_code
339 detmon_lg_core(cpl_frameset * cur_fset_on,
340 cpl_frameset * cur_fset_off,
344 double * exptime_off,
347 const char * recipe_name,
348 const char * pipeline_name,
349 const char * pafregexp,
350 const cpl_propertylist * pro_lintbl,
351 const cpl_propertylist * pro_gaintbl,
352 const cpl_propertylist * pro_coeffscube,
353 const cpl_propertylist * pro_bpm,
354 const cpl_propertylist * pro_corr,
355 const cpl_propertylist * pro_diff,
356 const char * package,
357 int (* load_fset) (
const cpl_frameset *,
360 int nsets, cpl_boolean opt_nir,
361 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
362 cpl_frameset * cur_fset);
364 static cpl_error_code
365 detmon_lg_lineff(
double *, cpl_propertylist *,
int,
int);
372 static cpl_error_code
373 detmon_gain_table_create(cpl_table *,
377 static cpl_error_code
378 detmon_lin_table_create(cpl_table *,
382 detmon_lg_find_dits(
const cpl_vector *,
385 static cpl_error_code
386 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
387 const cpl_vector * vec_ndits,
389 cpl_vector** diff_dits,
390 cpl_vector** diff_ndits);
392 static cpl_error_code
393 detmon_fpn_compute(
const cpl_frameset *set_on,
395 int last_linear_best,
396 cpl_propertylist *lint_qclist,
403 FPN_METHOD fpn_method,
405 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain,
406 FPN_METHOD fpn_method,
int,
double* mse);
407 static double irplib_calculate_total_noise(
const cpl_image* pimage);
409 static cpl_imagelist* irplib_load_fset_wrp(
const cpl_frameset *,
410 cpl_type,
int whichext);
411 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset *,
414 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
415 cpl_propertylist* plist);
416 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
417 cpl_propertylist* plist,
420 static cpl_error_code
421 detmon_pair_extract_next(
const cpl_frameset * set,
427 cpl_frameset ** pair,
429 static cpl_error_code
430 detmon_single_extract_next(
const cpl_frameset * set,
434 cpl_frameset ** pair);
441 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code);
442 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos);
443 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y);
452 static int irplib_pfits_get_ndit(
const cpl_propertylist * plist)
454 return cpl_propertylist_get_int(plist,
"ESO DET NDIT");
520 hdrldemo_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
521 const double ron, cpl_image ** ima_errs)
523 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
524 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
525 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
526 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
528 *ima_errs = cpl_image_duplicate(ima_data);
530 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
534 cpl_image_divide_scalar(*ima_errs, gain);
535 cpl_image_add_scalar(*ima_errs, ron * ron);
536 cpl_image_power(*ima_errs, 0.5);
538 return cpl_error_get_code();
543 static cpl_error_code
544 detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
547 const char * tag_off,
548 const char * recipe_name,
549 const char * pipeline_name,
550 const char * pafregexp,
551 const cpl_propertylist * pro_lintbl,
552 const cpl_propertylist * pro_gaintbl,
553 const cpl_propertylist * pro_coeffscube,
554 const cpl_propertylist * pro_bpm,
555 const cpl_propertylist * pro_corr,
556 const cpl_propertylist * pro_diff,
557 const char * package,
559 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
560 const cpl_boolean opt_nir,
561 const cpl_parameterlist * parlist,
564 static double irplib_compute_err(
double gain,
double ron,
double photon_noise);
566 static cpl_error_code
567 detmon_lg_dfs_save_imagelist(cpl_frameset * frameset,
568 const cpl_parameterlist * parlist,
569 const cpl_frameset *usedframes,
570 const cpl_imagelist *coeffs,
571 const char *recipe_name,
572 const cpl_propertylist *mypro_coeffscube,
573 const char * package,
574 const char * name_o);
577 static void irplib_free(
char** pointer){
579 if(pointer && *pointer) {
585 static cpl_error_code
586 detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
int nsets,
588 const char * tag_off,
589 const char * recipe_name,
590 const char * pipeline_name,
591 const char * pafregexp,
592 const cpl_propertylist * pro_lintbl,
593 const cpl_propertylist * pro_gaintbl,
594 const cpl_propertylist * pro_coeffscube,
595 const cpl_propertylist * pro_bpm,
596 const cpl_propertylist * pro_corr,
597 const cpl_propertylist * pro_diff,
598 const char * package,
600 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
601 const cpl_boolean opt_nir,
602 const cpl_parameterlist * parlist,
607 int nexts = detmon_lg_config.nb_extensions;
609 double* exptime_on = 0;
610 double* exptime_off = 0;
613 cpl_frameset * cur_fset = NULL;
614 cpl_frameset* cur_fset_on = 0;
615 cpl_frameset* cur_fset_off = 0;
620 cpl_frameset_duplicate(frameset) : cpl_frameset_extract(frameset, selection, i);
623 skip_if(cur_fset == NULL);
626 cur_fset_on = cpl_frameset_new();
627 cur_fset_off = cpl_frameset_new();
628 cpl_msg_info(cpl_func,
"Splitting into ON and OFF sub-framesets");
629 skip_if (detmon_lg_split_onoff(cur_fset,
630 cur_fset_on, cur_fset_off,
632 if (cpl_frameset_get_size(cur_fset_on) == 0)
634 cpl_msg_error(cpl_func,
"No lamp frames in input");
638 if (cpl_frameset_get_size(cur_fset_off) == 0)
640 cpl_msg_error(cpl_func,
"No dark / bias frames in input");
643 cpl_msg_info(cpl_func,
"found on-frames[%" CPL_SIZE_FORMAT
"] off-frames[%" CPL_SIZE_FORMAT
"]",cpl_frameset_get_size(cur_fset_on), cpl_frameset_get_size(cur_fset_off));
651 exptime_on = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_on));
652 exptime_off = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_off));
654 index_on = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_on));
655 index_off = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_off));
656 irplib_frameset_sort(cur_fset_on, index_on, exptime_on);
657 irplib_frameset_sort(cur_fset_off, index_off, exptime_off);
670 skip_if(detmon_check_order(exptime_on, cpl_frameset_get_size(cur_fset_on), detmon_lg_config.tolerance, detmon_lg_config.order));
672 if(detmon_lg_config.exts >= 0)
680 if (detmon_lg_config.lamp_ok) {
681 skip_if(detmon_opt_lampcr(cur_fset, 0));
684 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
689 detmon_lg_config.exts,
691 recipe_name, pipeline_name, pafregexp,
692 pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff,
693 package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
695 for(j = 1; j <= nexts; j++) {
702 if (detmon_lg_config.lamp_ok) {
703 skip_if(detmon_opt_lampcr(cur_fset, j));
707 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
712 j, i, recipe_name, pipeline_name,pafregexp, pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff, package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
717 cpl_frameset_delete(cur_fset);
718 cpl_frameset_delete(cur_fset_on);
719 cpl_frameset_delete(cur_fset_off);
722 cpl_free(exptime_on);
723 cpl_free(exptime_off);
724 return cpl_error_get_code();
802 detmon_lg(cpl_frameset * frameset,
803 const cpl_parameterlist * parlist,
805 const char * tag_off,
806 const char * recipe_name,
807 const char * pipeline_name,
808 const char * pafregexp,
809 const cpl_propertylist * pro_lintbl,
810 const cpl_propertylist * pro_gaintbl,
811 const cpl_propertylist * pro_coeffscube,
812 const cpl_propertylist * pro_bpm,
813 const cpl_propertylist * pro_corr,
814 const cpl_propertylist * pro_diff,
815 const char * package,
816 int (* compare) (
const cpl_frame *,
818 int (* load_fset) (
const cpl_frameset *,
821 const cpl_boolean opt_nir)
823 cpl_errorstate cleanstate = cpl_errorstate_get();
825 cpl_size * selection = NULL;
826 cpl_frame * first = NULL;
827 cpl_image * reference = NULL;
834 cpl_frameset * cur_fset = NULL;
835 cpl_frameset * cur_fset_on = NULL;
836 cpl_frameset * cur_fset_off = NULL;
839 cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
840 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
841 cpl_ensure_code(tag_on != NULL, CPL_ERROR_NULL_INPUT);
842 cpl_ensure_code(tag_off != NULL, CPL_ERROR_NULL_INPUT);
843 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
844 cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
845 cpl_ensure_code(pro_lintbl != NULL, CPL_ERROR_NULL_INPUT);
846 cpl_ensure_code(pro_gaintbl != NULL, CPL_ERROR_NULL_INPUT);
847 cpl_ensure_code(pro_coeffscube != NULL, CPL_ERROR_NULL_INPUT);
848 cpl_ensure_code(pro_bpm != NULL, CPL_ERROR_NULL_INPUT);
849 cpl_ensure_code(pro_corr != NULL, CPL_ERROR_NULL_INPUT);
850 cpl_ensure_code(pro_diff != NULL, CPL_ERROR_NULL_INPUT);
851 cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
853 cpl_msg_info(cpl_func,
"frameset size [%" CPL_SIZE_FORMAT
"]", cpl_frameset_get_size(frameset));
856 skip_if (detmon_lg_dfs_set_groups(frameset, tag_on, tag_off));
863 skip_if (detmon_lg_retrieve_parlist(pipeline_name, recipe_name,
871 first = cpl_frameset_get_first(frameset);
872 irplib_ensure (first != NULL, CPL_ERROR_ILLEGAL_INPUT,
"Empty data set! Provide %s and %s input frames",tag_on,tag_off);
874 detmon_lg_config.load_fset = load_fset;
875 detmon_lg_config.load_fset_wrp = load_fset ? irplib_load_fset_wrp_ext : irplib_load_fset_wrp;
878 detmon_lg_config.nb_extensions = 1;
879 if (detmon_lg_config.exts < 0) {
881 detmon_lg_config.nb_extensions = cpl_frame_get_nextensions(first);
882 while (reference == NULL && i <= detmon_lg_config.nb_extensions) {
883 reference = cpl_image_load(cpl_frame_get_filename(first),
884 CPL_TYPE_FLOAT, 0, i);
885 if (reference == NULL) {
886 cpl_msg_warning(cpl_func,
"Extension %d empty, skipping", i);
887 cpl_errorstate_set(cleanstate);
891 cpl_errorstate_set(cleanstate);
892 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
893 "No data found in any extension");
894 cpl_msg_info(cpl_func,
"Using extension %d as reference", i - 1);
896 if (load_fset != NULL) {
897 cpl_frameset *
new = cpl_frameset_new();
898 cpl_imagelist * p = cpl_imagelist_new();
899 cpl_frameset_insert(
new, cpl_frame_duplicate(first));
900 (*load_fset)(
new, CPL_TYPE_FLOAT, p);
901 reference = cpl_image_duplicate(cpl_imagelist_get(p, 0));
902 cpl_imagelist_delete(p);
903 cpl_frameset_delete(
new);
905 cpl_msg_info(cpl_func,
"name=%s",cpl_frame_get_filename(first));
906 reference = cpl_image_load(cpl_frame_get_filename(first),
907 CPL_TYPE_FLOAT, 0, detmon_lg_config.exts);
909 cpl_errorstate_set(cleanstate);
910 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
911 "No data found in requested extension %d",
912 detmon_lg_config.exts);
914 skip_if (reference == NULL);
916 skip_if (detmon_lg_check_defaults(reference));
925 if (compare == NULL) {
928 cpl_msg_info(cpl_func,
"Identifying different settings");
929 selection = cpl_frameset_labelise(frameset, compare, &nsets);
930 skip_if (selection == NULL);
934 for(
int i = 0; i < nsets; i++)
936 int fr_size = cpl_frameset_get_size(frameset);
938 cpl_msg_info(cpl_func,
"Reduce data set nb %d out of %" CPL_SIZE_FORMAT
"",
940 skip_if(detmon_lg_reduce_set(i, frameset, nsets, tag_on, tag_off,
955 fr_size_new = cpl_frameset_get_size(frameset);
961 if (fr_size_new > fr_size)
963 selection = cpl_realloc(selection, fr_size_new *
sizeof(selection[0]));
964 memset(selection + fr_size, -1, (fr_size_new - fr_size) *
sizeof(selection[0]));
970 cpl_frameset_delete(cur_fset);
971 cpl_frameset_delete(cur_fset_on);
972 cpl_frameset_delete(cur_fset_off);
974 cpl_image_delete(reference);
976 return cpl_error_get_code();
1012 static cpl_error_code
1013 detmon_lg_core(cpl_frameset * cur_fset_on,
1014 cpl_frameset * cur_fset_off,
1017 double * exptime_on,
1018 double * exptime_off,
1021 const char * recipe_name,
1022 const char * pipeline_name,
1023 const char * pafregexp,
1024 const cpl_propertylist * pro_lintbl,
1025 const cpl_propertylist * pro_gaintbl,
1026 const cpl_propertylist * pro_coeffscube,
1027 const cpl_propertylist * pro_bpm,
1028 const cpl_propertylist * pro_corr,
1029 const cpl_propertylist * pro_diff,
1030 const char * package,
1031 int (* load_fset) (
const cpl_frameset *,
1034 int nsets, cpl_boolean opt_nir,
1035 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
1036 cpl_frameset * cur_fset)
1038 cpl_table * gain_table = cpl_table_new(
1039 cpl_frameset_get_size(cur_fset_on) / 2);
1040 cpl_table * linear_table = cpl_table_new(
1041 cpl_frameset_get_size(cur_fset_on) / 2);
1042 cpl_imagelist * coeffs = NULL;
1043 cpl_image * bpm = NULL;
1044 cpl_imagelist * autocorr_images = NULL;
1045 cpl_imagelist * diff_flats = NULL;
1046 cpl_propertylist * gaint_qclist = NULL;
1047 cpl_propertylist * lint_qclist = NULL;
1048 cpl_propertylist * linc_qclist = NULL;
1049 cpl_propertylist * bpm_qclist = NULL;
1051 int next_index_on = 0;
1052 int next_index_off = 0;
1055 cpl_msg_info(cpl_func,
"Reduce extension nb %d ", whichext);
1059 if (detmon_lg_config.intermediate) {
1060 autocorr_images = cpl_imagelist_new();
1061 diff_flats = cpl_imagelist_new();
1064 gaint_qclist = cpl_propertylist_new();
1065 lint_qclist = cpl_propertylist_new();
1066 linc_qclist = cpl_propertylist_new();
1067 bpm_qclist = cpl_propertylist_new();
1070 cpl_msg_info(cpl_func,
"Starting data reduction");
1071 if (detmon_lg_reduce(cur_fset_on, cur_fset_off,
1072 index_on, index_off, exptime_on, exptime_off,
1073 &next_index_on, &next_index_off,
1074 &coeffs, gain_table,
1075 linear_table, &bpm, autocorr_images,
1076 diff_flats, gaint_qclist, lint_qclist,
1077 linc_qclist, bpm_qclist, load_fset,
1078 opt_nir, whichext) == CPL_ERROR_CONTINUE) {
1079 cpl_msg_info(cpl_func,
"Empty extension %d", whichext);
1083 cpl_msg_info(cpl_func,
"Saving the products");
1086 detmon_lg_save(parlist, frameset, recipe_name,
1087 pipeline_name, pafregexp,
1088 pro_lintbl, pro_gaintbl,
1089 pro_coeffscube, pro_bpm,
1090 pro_corr, pro_diff, package,
1091 coeffs, gain_table, linear_table,
1092 bpm, autocorr_images, diff_flats,
1093 gaint_qclist, lint_qclist, linc_qclist,
1094 bpm_qclist, 0, 0, cur_fset, whichext));
1097 detmon_lg_save(parlist, frameset, recipe_name,
1098 pipeline_name, pafregexp,
1099 pro_lintbl, pro_gaintbl,
1100 pro_coeffscube, pro_bpm,
1101 pro_corr, pro_diff, package,
1102 coeffs, gain_table, linear_table,
1103 bpm, autocorr_images, diff_flats,
1104 gaint_qclist, lint_qclist, linc_qclist,
1105 bpm_qclist, 1, whichset+ 1, cur_fset,
1113 cpl_table_delete(gain_table);
1114 cpl_table_delete(linear_table);
1115 cpl_imagelist_delete(coeffs);
1116 cpl_propertylist_delete(gaint_qclist);
1117 cpl_propertylist_delete(lint_qclist);
1118 cpl_propertylist_delete(linc_qclist);
1119 if(bpm_qclist != NULL) cpl_propertylist_delete(bpm_qclist);
1120 cpl_image_delete(bpm);
1121 cpl_imagelist_delete(autocorr_images);
1122 cpl_imagelist_delete(diff_flats);
1124 return cpl_error_get_code();
1149 detmon_image_correlate(
const cpl_image * image1,
1150 const cpl_image * image2,
1151 const int m,
const int n)
1153 cpl_image *image1_padded = NULL;
1154 cpl_image *image2_padded = NULL;
1158 cpl_image *corr_image_window = NULL;
1160 cpl_image* image_ri1 = NULL;
1161 cpl_image* image_ri2 = NULL;
1162 cpl_error_code err = CPL_ERROR_NONE;
1165 cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1166 cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1168 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1169 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1171 nx = cpl_image_get_size_x(image1);
1172 ny = cpl_image_get_size_y(image1);
1174 nx2 = cpl_image_get_size_x(image2);
1175 ny2 = cpl_image_get_size_y(image2);
1178 cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
1181 image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1182 cpl_image_copy(image1_padded, image1, m + 1, n + 1);
1184 image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1185 cpl_image_copy(image2_padded, image2, m + 1, n + 1);
1191 image_ri1 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
1192 image_ri2 = cpl_image_new(nx, ny , CPL_TYPE_FLOAT_COMPLEX);
1194 cpl_fft_image(image_ri1, image1_padded, CPL_FFT_FORWARD);
1195 cpl_fft_image(image_ri2, image2_padded, CPL_FFT_FORWARD);
1196 err = cpl_error_get_code();
1197 cpl_image_delete(image1_padded);
1198 image1_padded = NULL;
1199 cpl_image_delete(image2_padded);
1200 image2_padded = NULL;
1201 if (err == CPL_ERROR_NONE)
1204 cpl_image * corr_image = NULL;
1205 cpl_image * reorganised= NULL;
1206 cpl_image * image_ri_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1207 cpl_image * image_in_inv = cpl_image_new(nx, ny,
1208 CPL_TYPE_FLOAT_COMPLEX);
1211 for (i = 1; i <= nx; i++)
1213 for (j = 1; j <= ny; j++)
1216 double complex value1, value2, value;
1217 value1 = cpl_image_get_complex(image_ri1, i, j, &rej);
1218 value2 = cpl_image_get_complex(image_ri2, i, j, &rej);;
1219 value = conj(value1) * value2;
1220 cpl_image_set_complex(image_in_inv, i, j, value);
1223 cpl_image_delete(image_ri1);
1225 cpl_image_delete(image_ri2);
1228 err = cpl_error_get_code();
1229 if (err == CPL_ERROR_NONE)
1233 cpl_fft_image(image_ri_inv, image_in_inv,CPL_FFT_BACKWARD);
1234 cpl_image_delete(image_in_inv);
1237 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1238 for (i = 1; i <= nx; i++)
1240 for (j = 1; j <= ny; j++)
1244 value = cpl_image_get(image_ri_inv, i, j, &rej);
1245 cpl_image_set(corr_image, i, j, value);
1248 cpl_image_delete(image_ri_inv);
1249 err = cpl_error_get_code();
1250 if (err == CPL_ERROR_NONE)
1254 cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
1255 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1257 cpl_image_copy(reorganised, image, 1, 1);
1258 cpl_image_delete(image);
1259 image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
1260 cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
1261 cpl_image_delete(image);
1263 cpl_image_delete(corr_image);
1265 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1266 image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
1267 cpl_image_copy(corr_image, image, 1, 1);
1268 cpl_image_delete(image);
1270 image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
1271 cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
1272 cpl_image_delete(image);
1274 corr_image_window = cpl_image_extract(corr_image,
1277 nx / 2 + 1 + m, ny / 2 + 1 + n);
1282 cpl_image_delete(reorganised);
1283 cpl_image_delete(corr_image);
1285 if(cpl_image_divide_scalar(corr_image_window,
1286 cpl_image_get_max(corr_image_window))) {
1287 cpl_image_delete(corr_image_window);
1291 cpl_image_delete (image_ri1);
1292 cpl_image_delete (image_ri2);
1293 cpl_image_delete (image1_padded);
1294 cpl_image_delete (image2_padded);
1295 return corr_image_window;
1318 detmon_autocorrelate(
const cpl_image * input2,
const int m,
1321 cpl_image *im_re = NULL;
1322 cpl_image *im_im = NULL;
1324 cpl_image *ifft_re = NULL;
1325 cpl_image *ifft_im = NULL;
1326 cpl_image *autocorr = NULL;
1327 cpl_image *autocorr_norm_double = NULL;
1328 cpl_image *autocorr_norm = NULL;
1329 cpl_image *reorganised = NULL;
1330 cpl_image *image = NULL;
1332 cpl_error_code error;
1335 cpl_ensure(input2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1337 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1338 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1340 nx = cpl_image_get_size_x(input2) + 2 * m;
1341 ny = cpl_image_get_size_y(input2) + 2 * n;
1344 while(nx > p || ny > p) {
1348 input = cpl_image_cast(input2, CPL_TYPE_DOUBLE);
1350 im_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1351 error = cpl_image_copy(im_re, input, 1, 1);
1352 cpl_ensure(!error, error, NULL);
1354 im_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1356 error = cpl_image_fft(im_re, im_im, CPL_FFT_DEFAULT);
1357 cpl_ensure(!error, error, NULL);
1359 ifft_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1360 error = cpl_image_power(im_re, 2);
1361 cpl_ensure(!error, error, NULL);
1363 error = cpl_image_add(ifft_re, im_re);
1364 cpl_ensure(!error, error, NULL);
1366 cpl_image_delete(im_re);
1368 error = cpl_image_power(im_im, 2);
1369 cpl_ensure(!error, error, NULL);
1371 error = cpl_image_add(ifft_re, im_im);
1372 cpl_ensure(!error, error, NULL);
1374 cpl_image_delete(im_im);
1376 ifft_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1378 error = cpl_image_fft(ifft_re, ifft_im, CPL_FFT_INVERSE);
1379 cpl_ensure(!error, error, NULL);
1381 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1383 error = cpl_image_power(ifft_re, 2);
1384 cpl_ensure(!error, error, NULL);
1386 error = cpl_image_add(autocorr, ifft_re);
1387 cpl_ensure(!error, error, NULL);
1389 cpl_image_delete(ifft_re);
1391 error = cpl_image_power(ifft_im, 2);
1392 cpl_ensure(!error, error, NULL);
1394 error = cpl_image_add(autocorr, ifft_im);
1395 cpl_ensure(!error, error, NULL);
1397 cpl_image_delete(ifft_im);
1400 reorganised = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1402 image = cpl_image_extract(autocorr, p / 2 + 1, 1, p, p);
1403 cpl_image_copy(reorganised, image, 1, 1);
1404 cpl_image_delete(image);
1406 image = cpl_image_extract(autocorr, 1, 1, p / 2, p);
1407 cpl_image_copy(reorganised, image, p / 2 + 1, 1);
1408 cpl_image_delete(image);
1410 cpl_image_delete(autocorr);
1412 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1414 image = cpl_image_extract(reorganised, 1, p / 2 + 1, p, p);
1415 cpl_image_copy(autocorr, image, 1, 1);
1416 cpl_image_delete(image);
1418 image = cpl_image_extract(reorganised, 1, 1, p, p / 2);
1419 cpl_image_copy(autocorr, image, 1, p / 2 + 1);
1420 cpl_image_delete(image);
1422 cpl_image_delete(reorganised);
1424 autocorr_norm_double =
1425 cpl_image_extract(autocorr, p / 2 + 1 - m, p / 2 + 1 - n,
1426 p / 2 + 1 + m, p / 2 + 1 + n);
1428 cpl_image_delete(autocorr);
1430 if(cpl_image_divide_scalar(autocorr_norm_double,
1431 cpl_image_get_max(autocorr_norm_double))) {
1432 cpl_image_delete(autocorr_norm_double);
1433 cpl_ensure(0, cpl_error_get_code(), NULL);
1437 autocorr_norm = cpl_image_cast(autocorr_norm_double, CPL_TYPE_FLOAT);
1438 cpl_image_delete(autocorr_norm_double);
1440 cpl_image_delete(input);
1442 return autocorr_norm;
1458 detmon_lg_fill_parlist_nir_default(cpl_parameterlist * parlist,
1459 const char *recipe_name,
1460 const char *pipeline_name)
1462 const cpl_error_code error =
1463 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1509 cpl_ensure_code(!error, error);
1511 return cpl_error_get_code();
1527 detmon_lg_fill_parlist_opt_default(cpl_parameterlist * parlist,
1528 const char *recipe_name,
1529 const char *pipeline_name)
1531 const cpl_error_code error =
1532 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1577 cpl_ensure_code(!error, error);
1579 return cpl_error_get_code();
1583 detmon_lg_fill_parlist_default_mr(cpl_parameterlist * parlist,
1584 const char *recipe_name,
1585 const char *pipeline_name)
1587 char * group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1588 char * par_name = cpl_sprintf(
"%s.%s", group_name,
"regions-file");
1589 cpl_parameter * p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1590 "File containing regions, "
1591 "four comma separated points "
1594 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions-file");
1595 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1596 cpl_parameterlist_append(parlist, p);
1598 cpl_free(group_name);
1600 group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1601 par_name = cpl_sprintf(
"%s.%s", group_name,
"regions");
1602 p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1603 "Colon separated list of regions, four "
1604 "points each, comma separated: "
1605 "llx,lly,urx,ury:llx,...",
1607 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions");
1608 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1609 cpl_parameterlist_append(parlist, p);
1611 cpl_free(group_name);
1613 return cpl_error_get_code();
1617 detmon_lg_fill_parlist_opt_default_mr(cpl_parameterlist * parlist,
1618 const char *recipe_name,
1619 const char *pipeline_name)
1621 detmon_lg_fill_parlist_opt_default(parlist, recipe_name, pipeline_name);
1622 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1623 return cpl_error_get_code();
1627 detmon_lg_fill_parlist_nir_default_mr(cpl_parameterlist * parlist,
1628 const char *recipe_name,
1629 const char *pipeline_name)
1631 detmon_lg_fill_parlist_nir_default(parlist, recipe_name, pipeline_name);
1632 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1634 return cpl_error_get_code();
1694 detmon_lg_fill_parlist(cpl_parameterlist * parlist,
1695 const char *recipe_name,
const char *pipeline_name,
1705 const char *intermediate,
1706 const char *autocorr,
1707 const char *collapse,
1708 const char *rescale,
1709 const char *pix2pix,
1716 const char * pafname,
1733 int llx5,
int lly5,
int urx5,
int ury5,
int exts,
1734 cpl_boolean opt_nir)
1736 const cpl_error_code error =
1737 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 26,
1739 "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
1740 "CPL_TYPE_STRING", method,
1743 "Polynomial order for the fit (Linearity)",
1744 "CPL_TYPE_INT", order,
1746 "Kappa value for the kappa-sigma clipping (Gain)",
1747 "CPL_TYPE_DOUBLE", kappa,
1749 "Number of iterations to compute rms (Gain)",
1750 "CPL_TYPE_INT", niter,
1752 "x coordinate of the lower-left "
1753 "point of the region of interest. If not modified, default value will be 1.",
1754 "CPL_TYPE_INT", llx,
1756 "y coordinate of the lower-left "
1757 "point of the region of interest. If not modified, default value will be 1.",
1758 "CPL_TYPE_INT", lly,
1760 "x coordinate of the upper-right "
1761 "point of the region of interest. If not modified, default value will be X dimension of the input image.",
1762 "CPL_TYPE_INT", urx,
1764 "y coordinate of the upper-right "
1765 "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
1766 "CPL_TYPE_INT", ury,
1768 "User reference level",
1769 "CPL_TYPE_INT", ref_level,
1771 "De-/Activate intermediate products",
1772 "CPL_TYPE_BOOL", intermediate,
1775 "De-/Activate the autocorr option",
1776 "CPL_TYPE_BOOL", autocorr,
1779 "De-/Activate the collapse option",
1780 "CPL_TYPE_BOOL", collapse,
1782 "De-/Activate the image rescale option",
1783 "CPL_TYPE_BOOL", rescale,
1785 "De-/Activate the computation with pixel to pixel accuracy",
1786 "CPL_TYPE_BOOL", pix2pix,
1788 "De-/Activate the binary bpm option",
1789 "CPL_TYPE_BOOL", bpmbin,
1791 "Maximum x-shift for the autocorr",
1794 "Upper limit of Median flux to be filtered",
1795 "CPL_TYPE_INT", filter,
1797 "Maximum y-shift for the autocorr",
1800 "Tolerance for pair discrimination",
1801 "CPL_TYPE_DOUBLE", tolerance,
1804 "Generate PAF file",
1805 "CPL_TYPE_BOOL", pafgen,
1807 "Specific name for PAF file",
1808 "CPL_TYPE_STRING", pafname,
1812 "Activate the multi-exts option. Choose -1 to process all extensions. Choose an extension number"
1813 " to process the appropriate extension.",
1814 "CPL_TYPE_INT", exts,
1817 "Method for computing Fixed Pattern Noise (SMOOTH or HISTOGRAM)",
1818 "CPL_TYPE_STRING",
"HISTOGRAM",
1821 "template size in pixels for smoothing during FPN computation (only for SMOOTH method)",
1825 "all frames with mean saturation above the limit would not be used in linearity calculation",
1826 "CPL_TYPE_DOUBLE", 65535.0,
1829 "all frames with mean flux above the threshold would not be used in gain calculation",
1830 "CPL_TYPE_DOUBLE", 65535.0
1833 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 1,
1834 "coeffs_cube_split",
1835 "if TRUE, the recipe writes as many "
1836 "COEFFS_CUBE_Pi (i=0..order) as the value of "
1837 "the order parameter in a separate file",
1838 "CPL_TYPE_BOOL",
"CPL_FALSE");
1840 if(opt_nir == FALSE) {
1841 const cpl_error_code erroropt =
1842 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
1844 "x coord of the lower-left point of the first "
1845 "field used for contamination measurement. If not modified, default value will be 1.",
1846 "CPL_TYPE_INT", llx1,
1848 "y coord of the lower-left point of the first "
1849 "field used for contamination measurement. If not modified, default value will be 1.",
1850 "CPL_TYPE_INT", lly1,
1852 "x coord of the upper-right point of the first "
1853 "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
1854 "CPL_TYPE_INT", urx1,
1856 "y coord of the upper-right point of the first "
1857 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1858 "CPL_TYPE_INT", ury1,
1860 "x coord of the lower-left point of the second "
1861 "field used for contamination measurement. If not modified, default value will be 1.",
1862 "CPL_TYPE_INT", llx2,
1864 "y coord of the lower-left point of the second "
1865 "field used for contamination measurement. If not modified, default value will be 1.",
1866 "CPL_TYPE_INT", lly2,
1868 "x coord of the upper-right point of the second "
1869 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1870 "CPL_TYPE_INT", urx2,
1872 "y coord of the upper-right point of the second "
1873 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1874 "CPL_TYPE_INT", ury2,
1876 "x coord of the lower-left point of the third "
1877 "field used for contamination measurement. If not modified, default value will be 1.",
1878 "CPL_TYPE_INT", llx3,
1880 "y coord of the lower-left point of the third "
1881 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1882 "CPL_TYPE_INT", lly3,
1884 "x coord of the upper-right point of the third "
1885 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1886 "CPL_TYPE_INT", urx3,
1888 "y coord of the upper-right point of the third "
1889 "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
1890 "CPL_TYPE_INT", ury3,
1892 "x coord of the lower-left point of the fourth "
1893 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1894 "CPL_TYPE_INT", llx4,
1896 "y coord of the lower-left point of the fourth "
1897 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1898 "CPL_TYPE_INT", lly4,
1900 "x coord of the upper-right point of the fourth "
1901 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1902 "CPL_TYPE_INT", urx4,
1904 "y coord of the upper-right point of the fourth "
1905 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1906 "CPL_TYPE_INT", ury4,
1908 "x coord of the lower-left point of the fifth "
1909 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1910 "CPL_TYPE_INT", llx5,
1912 "y coord of the lower-left point of the fifth "
1913 "field used for contamination measurement. If not modified, default value will be 1.",
1914 "CPL_TYPE_INT", lly5,
1916 "x coord of the upper-right point of the fifth "
1917 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1918 "CPL_TYPE_INT", urx5,
1921 "y coord of the upper-right point of the fifth "
1922 "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
1923 "CPL_TYPE_INT", ury5);
1926 cpl_ensure_code(!erroropt, erroropt);
1929 cpl_ensure_code(!error, error);
1931 return cpl_error_get_code();
1944 static cpl_error_code
1945 detmon_lg_retrieve_parlist(
const char * pipeline_name,
1946 const char * recipe_name,
1947 const cpl_parameterlist * parlist,
1948 cpl_boolean opt_nir)
1952 cpl_parameter * par;
1955 par_name = cpl_sprintf(
"%s.%s.method", pipeline_name, recipe_name);
1956 assert(par_name != NULL);
1957 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1958 detmon_lg_config.method = cpl_parameter_get_string(par);
1962 detmon_lg_config.order =
1963 detmon_retrieve_par_int(
"order", pipeline_name, recipe_name,
1967 detmon_lg_config.kappa =
1968 detmon_retrieve_par_double(
"kappa", pipeline_name, recipe_name,
1972 detmon_lg_config.niter =
1973 detmon_retrieve_par_int(
"niter", pipeline_name, recipe_name,
1977 detmon_lg_config.llx =
1978 detmon_retrieve_par_int(
"llx", pipeline_name, recipe_name,
1982 detmon_lg_config.lly =
1983 detmon_retrieve_par_int(
"lly", pipeline_name, recipe_name,
1987 detmon_lg_config.urx =
1988 detmon_retrieve_par_int(
"urx", pipeline_name, recipe_name,
1992 detmon_lg_config.ury =
1993 detmon_retrieve_par_int(
"ury", pipeline_name, recipe_name,
1997 detmon_lg_config.ref_level =
1998 detmon_retrieve_par_int(
"ref_level", pipeline_name, recipe_name,
2003 cpl_sprintf(
"%s.%s.intermediate", pipeline_name, recipe_name);
2004 assert(par_name != NULL);
2005 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2006 detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
2010 par_name = cpl_sprintf(
"%s.%s.autocorr", pipeline_name, recipe_name);
2011 assert(par_name != NULL);
2012 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2013 detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
2017 par_name = cpl_sprintf(
"%s.%s.coeffs_cube_split", pipeline_name, recipe_name);
2018 assert(par_name != NULL);
2019 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2020 detmon_lg_config.split_coeffs = cpl_parameter_get_bool(par);
2024 par_name = cpl_sprintf(
"%s.%s.collapse", pipeline_name, recipe_name);
2025 assert(par_name != NULL);
2026 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2027 detmon_lg_config.collapse = cpl_parameter_get_bool(par);
2031 par_name = cpl_sprintf(
"%s.%s.rescale", pipeline_name, recipe_name);
2032 assert(par_name != NULL);
2033 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2034 detmon_lg_config.rescale = cpl_parameter_get_bool(par);
2038 par_name = cpl_sprintf(
"%s.%s.pix2pix", pipeline_name, recipe_name);
2039 assert(par_name != NULL);
2040 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2041 detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
2045 par_name = cpl_sprintf(
"%s.%s.bpmbin", pipeline_name, recipe_name);
2046 assert(par_name != NULL);
2047 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2048 detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
2052 detmon_lg_config.filter =
2053 detmon_retrieve_par_int(
"filter", pipeline_name,
2054 recipe_name, parlist);
2057 detmon_lg_config.m =
2058 detmon_retrieve_par_int(
"m", pipeline_name, recipe_name, parlist);
2061 detmon_lg_config.n =
2062 detmon_retrieve_par_int(
"n", pipeline_name, recipe_name, parlist);
2065 par_name = cpl_sprintf(
"%s.%s.tolerance", pipeline_name, recipe_name);
2066 assert(par_name != NULL);
2067 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2068 detmon_lg_config.tolerance = cpl_parameter_get_double(par);
2073 par_name = cpl_sprintf(
"%s.%s.pafgen", pipeline_name, recipe_name);
2074 assert(par_name != NULL);
2075 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2076 detmon_lg_config.pafgen = cpl_parameter_get_bool(par);
2080 par_name = cpl_sprintf(
"%s.%s.pafname", pipeline_name, recipe_name);
2081 assert(par_name != NULL);
2082 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2083 detmon_lg_config.pafname = cpl_parameter_get_string(par);
2086 if(opt_nir == OPT) {
2088 detmon_lg_config.llx1 =
2089 detmon_retrieve_par_int(
"llx1", pipeline_name, recipe_name,
2093 detmon_lg_config.lly1 =
2094 detmon_retrieve_par_int(
"lly1", pipeline_name, recipe_name,
2098 detmon_lg_config.urx1 =
2099 detmon_retrieve_par_int(
"urx1", pipeline_name, recipe_name,
2103 detmon_lg_config.ury1 =
2104 detmon_retrieve_par_int(
"ury1", pipeline_name, recipe_name,
2108 detmon_lg_config.llx2 =
2109 detmon_retrieve_par_int(
"llx2", pipeline_name, recipe_name,
2113 detmon_lg_config.lly2 =
2114 detmon_retrieve_par_int(
"lly2", pipeline_name, recipe_name,
2118 detmon_lg_config.urx2 =
2119 detmon_retrieve_par_int(
"urx2", pipeline_name, recipe_name,
2123 detmon_lg_config.ury2 =
2124 detmon_retrieve_par_int(
"ury2", pipeline_name, recipe_name,
2128 detmon_lg_config.llx3 =
2129 detmon_retrieve_par_int(
"llx3", pipeline_name, recipe_name,
2133 detmon_lg_config.lly3 =
2134 detmon_retrieve_par_int(
"lly3", pipeline_name, recipe_name,
2138 detmon_lg_config.urx3 =
2139 detmon_retrieve_par_int(
"urx3", pipeline_name, recipe_name,
2143 detmon_lg_config.ury3 =
2144 detmon_retrieve_par_int(
"ury3", pipeline_name, recipe_name,
2148 detmon_lg_config.llx4 =
2149 detmon_retrieve_par_int(
"llx4", pipeline_name, recipe_name,
2153 detmon_lg_config.lly4 =
2154 detmon_retrieve_par_int(
"lly4", pipeline_name, recipe_name,
2158 detmon_lg_config.urx4 =
2159 detmon_retrieve_par_int(
"urx4", pipeline_name, recipe_name,
2163 detmon_lg_config.ury4 =
2164 detmon_retrieve_par_int(
"ury4", pipeline_name, recipe_name,
2168 detmon_lg_config.llx5 =
2169 detmon_retrieve_par_int(
"llx5", pipeline_name, recipe_name,
2173 detmon_lg_config.lly5 =
2174 detmon_retrieve_par_int(
"lly5", pipeline_name, recipe_name,
2178 detmon_lg_config.urx5 =
2179 detmon_retrieve_par_int(
"urx5", pipeline_name, recipe_name,
2183 detmon_lg_config.ury5 =
2184 detmon_retrieve_par_int(
"ury5", pipeline_name, recipe_name,
2189 detmon_lg_config.exts =
2190 detmon_retrieve_par_int(
"exts", pipeline_name, recipe_name,
2194 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2196 cpl_sprintf(
"%s.%s.fpn_method", pipeline_name, recipe_name);
2197 assert(par_name != NULL);
2198 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2201 const char * str_method = cpl_parameter_get_string(par);
2202 if (strcmp(str_method,
"SMOOTH") == 0)
2204 detmon_lg_config.fpn_method = FPN_SMOOTH;
2206 else if (strcmp(str_method,
"HISTOGRAM") == 0)
2208 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2214 detmon_lg_config.fpn_smooth =
2215 detmon_retrieve_par_int(
"fpn_smooth", pipeline_name, recipe_name,
2219 detmon_lg_config.saturation_limit = 65535;
2221 cpl_sprintf(
"%s.%s.saturation_limit", pipeline_name, recipe_name);
2222 assert(par_name != NULL);
2223 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2226 detmon_lg_config.saturation_limit = cpl_parameter_get_double(par);
2233 detmon_lg_config.gain_threshold = 0;
2235 cpl_sprintf(
"%s.%s.gain_threshold", pipeline_name, recipe_name);
2236 assert(par_name != NULL);
2237 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2240 detmon_lg_config.gain_threshold = cpl_parameter_get_double(par);
2245 if(cpl_error_get_code())
2247 cpl_msg_error(cpl_func,
"Failed to retrieve the input parameters");
2248 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
2252 return cpl_error_get_code();
2262 static cpl_error_code
2263 detmon_lg_check_defaults(
const cpl_image * reference)
2265 const int nx = cpl_image_get_size_x(reference);
2266 const int ny = cpl_image_get_size_y(reference);
2268 detmon_lg_config.nx = nx;
2269 detmon_lg_config.ny = ny;
2271 detmon_lg_config.wholechip = CPL_FALSE;
2273 if(detmon_lg_config.llx == -1)
2274 detmon_lg_config.llx = 1;
2275 if(detmon_lg_config.lly == -1)
2276 detmon_lg_config.lly = 1;
2277 if(detmon_lg_config.urx == -1)
2278 detmon_lg_config.urx = nx;
2279 if(detmon_lg_config.ury == -1)
2280 detmon_lg_config.ury = ny;
2282 if (detmon_lg_config.llx == 1 &&
2283 detmon_lg_config.lly == 1 &&
2284 detmon_lg_config.urx == nx &&
2285 detmon_lg_config.ury == ny)
2286 detmon_lg_config.wholechip = CPL_TRUE;
2288 if(detmon_lg_config.llx1 == -1)
2289 detmon_lg_config.llx1 = 1;
2290 if(detmon_lg_config.lly1 == -1)
2291 detmon_lg_config.lly1 = 1;
2292 if(detmon_lg_config.urx1 == -1)
2293 detmon_lg_config.urx1 = nx;
2294 if(detmon_lg_config.ury1 == -1)
2295 detmon_lg_config.ury1 = ny;
2297 if(detmon_lg_config.llx2 == -1)
2298 detmon_lg_config.llx2 = 1;
2299 if(detmon_lg_config.lly2 == -1)
2300 detmon_lg_config.lly2 = 1;
2301 if(detmon_lg_config.urx2 == -1)
2302 detmon_lg_config.urx2 = nx / 2;
2303 if(detmon_lg_config.ury2 == -1)
2304 detmon_lg_config.ury2 = ny / 2;
2306 if(detmon_lg_config.llx3 == -1)
2307 detmon_lg_config.llx3 = 1;
2308 if(detmon_lg_config.lly3 == -1)
2309 detmon_lg_config.lly3 = ny / 2;
2310 if(detmon_lg_config.urx3 == -1)
2311 detmon_lg_config.urx3 = nx / 2;
2312 if(detmon_lg_config.ury3 == -1)
2313 detmon_lg_config.ury3 = ny;
2315 if(detmon_lg_config.llx4 == -1)
2316 detmon_lg_config.llx4 = nx / 2;
2317 if(detmon_lg_config.lly4 == -1)
2318 detmon_lg_config.lly4 = ny / 2;
2319 if(detmon_lg_config.urx4 == -1)
2320 detmon_lg_config.urx4 = nx;
2321 if(detmon_lg_config.ury4 == -1)
2322 detmon_lg_config.ury4 = ny;
2324 if(detmon_lg_config.llx5 == -1)
2325 detmon_lg_config.llx5 = nx / 2;
2326 if(detmon_lg_config.lly5 == -1)
2327 detmon_lg_config.lly5 = 1;
2328 if(detmon_lg_config.urx5 == -1)
2329 detmon_lg_config.urx5 = nx;
2330 if(detmon_lg_config.ury5 == -1)
2331 detmon_lg_config.ury5 = ny / 2;
2333 if(detmon_lg_config.intermediate == TRUE) {
2334 cpl_msg_warning(cpl_func,
"PLEASE NOTE: The --intermediate option saves the difference and correlation images produced during autocorrelation computation. Therefore, --autocorr option has been automatically activated. If you didn't want to run this, please abort and rerun.");
2335 detmon_lg_config.autocorr = TRUE;
2339 detmon_lg_config.lamp_stability = 0.0;
2341 detmon_lg_config.lamp_ok = FALSE;
2343 detmon_lg_config.cr = 0.0;
2345 return cpl_error_get_code();
2360 static cpl_error_code
2361 detmon_lg_split_onoff(
const cpl_frameset * cur_fset,
2362 cpl_frameset * cur_fset_on,
2363 cpl_frameset * cur_fset_off,
2365 const char *tag_off)
2370 cpl_frame * cur_frame_dup = NULL;
2373 const cpl_frame * first;
2374 const cpl_frame * second;
2375 const char * first_tag;
2376 const char * second_tag;
2377 skip_if((first = cpl_frameset_get_first_const(cur_fset)) == NULL);
2378 skip_if((second = cpl_frameset_get_next_const (cur_fset)) == NULL);
2380 skip_if((first_tag = cpl_frame_get_tag(first)) == NULL);
2381 skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
2382 if (opt_nir == OPT &&
2383 ((!strcmp(first_tag, tag_on ) && !strcmp(second_tag, tag_off)) ||
2384 (!strcmp(first_tag, tag_off) && !strcmp(second_tag, tag_on )))) {
2385 detmon_lg_config.lamp_ok = TRUE;
2389 nframes = cpl_frameset_get_size(cur_fset);
2390 for(i = detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
2391 const cpl_frame * cur_frame =
2392 cpl_frameset_get_position_const(cur_fset, i);
2396 cur_frame_dup = cpl_frame_duplicate(cur_frame);
2397 tag = (
char *) cpl_frame_get_tag(cur_frame_dup);
2400 if(!strcmp(tag, tag_on)) {
2401 skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
2402 }
else if(!strcmp(tag, tag_off)) {
2403 skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
2405 cpl_frame_delete(cur_frame_dup);
2406 cur_frame_dup = NULL;
2409 cur_frame_dup = NULL;
2413 cpl_frame_delete(cur_frame_dup);
2415 return cpl_error_get_code();
2442 static cpl_error_code
2443 detmon_lg_reduce(
const cpl_frameset * set_on,
2444 const cpl_frameset * set_off,
2445 int* index_on,
int* index_off,
2446 double* exptime_on,
double* exptime_off,
2447 int *next_index_on,
int* next_index_off,
2448 cpl_imagelist ** coeffs_ptr,
2449 cpl_table * gain_table,
2450 cpl_table * linear_table,
2451 cpl_image ** bpm_ptr,
2452 cpl_imagelist * autocorr_images,
2453 cpl_imagelist * diff_flats,
2454 cpl_propertylist * gaint_qclist,
2455 cpl_propertylist * lint_qclist,
2456 cpl_propertylist * linc_qclist,
2457 cpl_propertylist * bpm_qclist,
2458 int (* load_fset) (
const cpl_frameset *,
2461 const cpl_boolean opt_nir,
2464 cpl_errorstate prestate = cpl_errorstate_get();
2465 const double D_INVALID_VALUE = -999;
2467 cpl_imagelist * linearity_inputs = NULL;
2468 cpl_imagelist * opt_offs = NULL;
2470 cpl_propertylist * reflist = NULL;
2472 int rows_linear_affected = 1;
2473 int rows_gain_affected = 1;
2474 int last_linear_best = 0;
2475 int last_gain_best = 0;
2477 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2478 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2480 nsets = cpl_frameset_get_size(set_on) / 2;
2482 detmon_lg_config.load_fset = load_fset;
2483 if(detmon_lg_config.collapse) {
2490 const cpl_frame *first = cpl_frameset_get_first_const(set_off);
2491 cpl_frame *dup_first = cpl_frame_duplicate(first);
2493 const cpl_frame *second = cpl_frameset_get_next_const(set_off);
2494 cpl_frame *dup_second = cpl_frame_duplicate(second);
2496 cpl_frameset *raw_offs = cpl_frameset_new();
2498 skip_if(cpl_frameset_insert(raw_offs, dup_first));
2499 skip_if(cpl_frameset_insert(raw_offs, dup_second));
2501 opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
2504 cpl_frameset_delete(raw_offs);
2505 if (opt_offs == NULL) {
2506 cpl_errorstate_set(prestate);
2507 return CPL_ERROR_CONTINUE;
2511 skip_if(detmon_lg_reduce_init(gain_table,
2523 if(detmon_lg_lamp_stab(set_on, set_off,
2524 opt_nir, whichext)) {
2525 cpl_errorstate_set(prestate);
2528 if(!detmon_lg_config.collapse)
2532 skip_if(cpl_table_unselect_all(linear_table));
2533 skip_if(cpl_table_unselect_all(gain_table));
2537 for(i = 0; i < nsets ; i++)
2539 skip_if(detmon_lg_reduce_dit(set_on,
2540 index_on, exptime_on,
2544 index_off, exptime_off,
2545 next_index_on, next_index_off,
2547 gain_table, linearity_inputs,
2548 lint_qclist, opt_nir,
2549 autocorr_images, diff_flats,
2551 &rows_linear_affected,&rows_gain_affected));
2555 if (rows_linear_affected == 0)
2557 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2558 "into linear calculation, check the messages above");
2559 cpl_table_select_row(linear_table, i);
2563 last_linear_best = i;
2566 if (rows_gain_affected == 0)
2568 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2569 "into gain calculation, check the messages above");
2570 cpl_table_select_row(gain_table, i);
2581 skip_if(detmon_add_adl_column(linear_table, opt_nir));
2587 skip_if(cpl_table_erase_selected(gain_table));
2588 skip_if(cpl_table_erase_selected(linear_table));
2591 reflist = cpl_propertylist_new();
2592 skip_if(cpl_propertylist_append_bool(reflist,
"ADU", FALSE));
2593 skip_if(cpl_table_sort(gain_table, reflist));
2599 skip_if(detmon_lg_reduce_all(linear_table,
2600 gaint_qclist, lint_qclist, linc_qclist,
2601 bpm_qclist, coeffs_ptr, bpm_ptr,
2603 gain_table, whichext, opt_nir));
2606 double gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
2609 cpl_error_code cplerr = cpl_error_get_code();
2610 if (cplerr != CPL_ERROR_NONE || (gain == 0.0))
2612 cpl_msg_warning(cpl_func,
"Cannot read gain from QC parameters - "
2613 "FPN will not be computed");
2618 detmon_fpn_compute(set_on, index_on, last_linear_best, lint_qclist,
2619 detmon_lg_config.llx,
2620 detmon_lg_config.lly,
2621 detmon_lg_config.urx,
2622 detmon_lg_config.ury,
2625 detmon_lg_config.fpn_method,
2626 detmon_lg_config.fpn_smooth);
2631 detmon_table_fill_invalid(gain_table, D_INVALID_VALUE);
2633 cpl_imagelist_delete(linearity_inputs);
2634 cpl_imagelist_delete(opt_offs);
2635 cpl_propertylist_delete(reflist);
2637 return cpl_error_get_code();
2640 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code)
2642 int ncols = cpl_table_get_ncol(ptable);
2643 cpl_array* pnames = cpl_table_get_column_names(ptable);
2644 int nrows = cpl_table_get_nrow(ptable);
2646 for (i=0; i < ncols; i++)
2649 for (j = 0; j< nrows; j++)
2651 const char* colname = cpl_array_get_data_string_const(pnames)[i];
2653 cpl_type type = cpl_table_get_column_type(ptable, colname);
2654 cpl_table_get(ptable, colname, j, &isnull);
2657 if (type == CPL_TYPE_DOUBLE)
2659 cpl_table_set(ptable,colname,j, code);
2661 else if (type == CPL_TYPE_FLOAT)
2663 cpl_table_set_float(ptable,colname,j, (
float)code);
2668 cpl_array_delete(pnames);
2669 return cpl_error_get_code();
2672 static cpl_error_code
2673 detmon_fpn_compute(
const cpl_frameset *set_on,
2675 int last_linear_best,
2676 cpl_propertylist *lint_qclist,
2683 FPN_METHOD fpn_method,
2687 const cpl_image* im1 = 0;
2689 cpl_imagelist* ons = 0;
2690 cpl_frameset * pair_on = 0;
2691 int nsets_extracted = cpl_frameset_get_size(set_on);
2692 cpl_size * selection = NULL;
2701 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
2702 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
2704 selection[index_on[last_linear_best*2 + 0] ] = 1;
2705 selection[index_on[last_linear_best*2 + 1] ] = 1;
2706 pair_on = cpl_frameset_extract(set_on, selection, 1);
2707 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2709 skip_if(ons == NULL);
2710 skip_if((im1 = cpl_imagelist_get_const(ons, 0)) == NULL);
2712 fpn = irplib_fpn_lg(im1, range, gain, fpn_method, smooth_size, &mse);
2713 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_FPN,
2715 skip_if(cpl_propertylist_append_double(lint_qclist,
"ESO QC GAIN ERR",
2719 cpl_frameset_delete(pair_on);
2720 cpl_imagelist_delete(ons);
2721 cpl_free(selection);
2722 return cpl_error_get_code();
2734 static cpl_error_code
2735 detmon_lg_lamp_stab(
const cpl_frameset * lamps,
2736 const cpl_frameset * darks,
2737 cpl_boolean opt_nir,
2750 cpl_vector * selection = NULL;
2751 cpl_propertylist * plist;
2752 double dit_lamp, dit_dark;
2754 cpl_imagelist * lamps_data = NULL;
2755 cpl_imagelist * darks_data = NULL;
2756 double * stab_levels = NULL;
2758 double * ditvals = NULL;
2762 cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
2763 CPL_ERROR_ILLEGAL_INPUT);
2769 cpl_msg_info(__func__,
"Checking DIT consistency");
2770 selection = cpl_vector_new(nb_lamps);
2771 ditvals = cpl_malloc(nb_lamps *
sizeof(
double));
2773 for (i = 0; i < nb_lamps; i++) {
2774 const cpl_frame * c_lamp;
2775 const cpl_frame * c_dark;
2777 skip_if (cpl_error_get_code());
2780 c_lamp = cpl_frameset_get_position_const(lamps, i);
2781 plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
2783 dit_lamp = (double)irplib_pfits_get_dit(plist);
2785 dit_lamp = (double)irplib_pfits_get_dit_opt(plist);
2786 cpl_propertylist_delete(plist);
2787 skip_if (cpl_error_get_code());
2790 c_dark = cpl_frameset_get_position_const(darks, i);
2791 plist = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
2793 dit_dark = (double)irplib_pfits_get_dit(plist);
2795 dit_dark = (double)irplib_pfits_get_dit_opt(plist);
2796 cpl_propertylist_delete(plist);
2797 skip_if (cpl_error_get_code());
2800 if (fabs(dit_dark-dit_lamp) > 1e-3) {
2801 cpl_msg_error(__func__,
"DIT not consistent between LAMP and DARK, skip lamp stability computation");
2806 ditvals[i] = dit_lamp;
2809 cpl_vector_set(selection, i, -1.0);
2817 if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
2818 cpl_vector_set(selection, i, -1.0);
2822 cpl_vector_set(selection, i, 1.0);
2829 cpl_msg_info(__func__,
"Not enough frames for stability check");
2833 cpl_msg_info(__func__,
"Compute the differences lamp - dark");
2836 lamps_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2838 detmon_lg_config.llx,
2839 detmon_lg_config.lly,
2840 detmon_lg_config.urx,
2841 detmon_lg_config.ury,
2844 darks_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2846 detmon_lg_config.llx,
2847 detmon_lg_config.lly,
2848 detmon_lg_config.urx,
2849 detmon_lg_config.ury,
2852 nb_darks=cpl_imagelist_get_size(darks_data);
2853 if(nb_darks==nb_lamps) {
2854 skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
2856 cpl_image* master_dark=cpl_imagelist_collapse_median_create(darks_data);
2857 cpl_imagelist_subtract_image(lamps_data,master_dark);
2858 cpl_image_delete(master_dark);
2861 cpl_msg_info(__func__,
"Check the lamp stability");
2862 stab_levels = cpl_malloc(dit_stab *
sizeof(
double));
2864 for (i=0; i<nb_lamps; i++) {
2865 if (cpl_vector_get(selection, i) < 0) {
2867 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
2873 for (i=1; i<dit_stab; i++) {
2874 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
2875 detmon_lg_config.lamp_stability)
2876 detmon_lg_config.lamp_stability =
2877 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
2882 if (detmon_lg_config.lamp_stability > 0.01) {
2883 cpl_msg_warning(__func__,
2884 "Lamp stability level %g difference too high - proceed anyway",detmon_lg_config.lamp_stability);
2891 cpl_vector_delete(selection);
2892 cpl_imagelist_delete(lamps_data);
2893 cpl_imagelist_delete(darks_data);
2894 cpl_free(stab_levels);
2896 return cpl_error_get_code();
2923 static cpl_error_code
2924 detmon_lg_reduce_dit(
const cpl_frameset * set_on,
2925 int* index_on,
double* exptime_on,
2928 const cpl_frameset * set_off,
2929 int * index_off,
double* exptime_off,
2930 int* next_on,
int* next_off,
2931 cpl_table * linear_table,
2932 cpl_table * gain_table,
2933 cpl_imagelist * linearity_inputs,
2934 cpl_propertylist * qclist,
2935 cpl_boolean opt_nir,
2936 cpl_imagelist * autocorr_images,
2937 cpl_imagelist * diff_flats,
2938 cpl_imagelist * opt_offs,
2940 int* rows_linear_affected,
2941 int* rows_gain_affected)
2943 cpl_frameset * pair_on = NULL;
2944 cpl_frameset * pair_off = NULL;
2945 cpl_imagelist * ons = NULL;
2946 cpl_imagelist * offs = NULL;
2947 cpl_boolean follow = CPL_TRUE;
2948 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
2952 double current_dit = 0;
2954 const char * filename;
2956 cpl_propertylist * plist = NULL;
2957 cpl_propertylist* pDETlist = NULL;
2959 mode = detmon_lg_config.collapse ?
2960 mode | IRPLIB_GAIN_COLLAPSE | IRPLIB_LIN_COLLAPSE:
2961 mode | IRPLIB_GAIN_NO_COLLAPSE | IRPLIB_LIN_NO_COLLAPSE;
2962 mode = detmon_lg_config.pix2pix ?
2963 mode | IRPLIB_LIN_PIX2PIX : mode;
2965 mode | IRPLIB_GAIN_NIR | IRPLIB_LIN_NIR :
2966 mode | IRPLIB_GAIN_OPT | IRPLIB_LIN_OPT ;
2970 skip_if(detmon_pair_extract_next(set_on, index_on, next_on, exptime_on, &pair_on, detmon_lg_config.tolerance));
2971 current_dit = exptime_on[*next_on - 1];
2974 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2975 skip_if(ons == NULL);
2976 cpl_msg_debug(cpl_func,
" Loaded ON images: %" CPL_SIZE_FORMAT
2977 ", exptime[%f]",cpl_imagelist_get_size(ons), current_dit );
2978 if(cpl_imagelist_get_size(ons) != 2)
2980 cpl_msg_error(cpl_func,
"cannot take ON pair, number of images[%"
2981 CPL_SIZE_FORMAT
"]", cpl_imagelist_get_size(ons));
2984 if(detmon_lg_config.filter > 0)
2987 cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
2988 detmon_lg_config.llx,
2989 detmon_lg_config.lly,
2990 detmon_lg_config.urx,
2991 detmon_lg_config.ury);
2993 cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
2994 detmon_lg_config.llx,
2995 detmon_lg_config.lly,
2996 detmon_lg_config.urx,
2997 detmon_lg_config.ury);
2998 if ( med1 > (
double)detmon_lg_config.filter ||
2999 med2 > (
double)detmon_lg_config.filter)
3002 cpl_table_select_row(gain_table, dit_nb);
3003 cpl_table_select_row(linear_table, dit_nb);
3005 cpl_msg_warning(cpl_func,
"Frames of EXPTIME nb %d "
3006 "will not be taken into account for computation "
3007 "as they are above --filter threshold", dit_nb);
3011 if (follow || detmon_lg_config.filter < 0)
3019 if(!detmon_lg_config.collapse)
3036 if (!strcmp(detmon_lg_config.method,
"MED") ||
3037 cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
3039 skip_if(detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off, detmon_lg_config.tolerance));
3043 skip_if(detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
3046 cpl_msg_debug(cpl_func,
" Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
3047 offs = detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
3049 skip_if(offs == NULL);
3050 skip_if(cpl_error_get_code());
3053 offs = (cpl_imagelist *) opt_offs;
3057 if(detmon_lg_config.rescale)
3059 skip_if(detmon_lg_rescale(ons));
3060 if (!detmon_lg_config.collapse &&
3061 !strcmp(detmon_lg_config.method,
"MED"))
3062 skip_if(detmon_lg_rescale(offs));
3067 cpl_frame_get_filename(cpl_frameset_get_first_const(pair_on));
3068 skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
3072 pDETlist = cpl_propertylist_new();
3073 cpl_propertylist_copy_property_regexp(pDETlist, plist,
"DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
3076 irplib_table_create_column(gain_table, pDETlist);
3077 irplib_table_create_column(linear_table, pDETlist);
3080 if(opt_nir == NIR) {
3081 c_dit = irplib_pfits_get_dit(plist);
3082 c_ndit = irplib_pfits_get_ndit(plist);
3084 c_dit = irplib_pfits_get_exptime(plist);
3096 cpl_msg_info(cpl_func,
"Computing GAIN for EXPTIME value nb %d",
3100 if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
3102 cpl_table_erase_column(gain_table,
"MEAN_OFF1");
3103 cpl_table_erase_column(gain_table,
"MEAN_OFF2");
3104 cpl_table_erase_column(gain_table,
"SIG_OFF_DIF");
3105 cpl_table_erase_column(gain_table,
"GAIN");
3106 cpl_table_erase_column(gain_table,
"GAIN_CORR");
3107 cpl_table_new_column(gain_table,
"MEAN_OFF", CPL_TYPE_DOUBLE);
3111 skip_if(detmon_gain_table_fill_row(gain_table,
3114 diff_flats, ons, offs,
3115 detmon_lg_config.kappa,
3116 detmon_lg_config.niter,
3117 detmon_lg_config.llx,
3118 detmon_lg_config.lly,
3119 detmon_lg_config.urx,
3120 detmon_lg_config.ury,
3123 detmon_lg_config.saturation_limit,
3124 detmon_lg_config.gain_threshold,
3125 dit_nb, mode, rows_gain_affected));
3128 skip_if(detmon_check_saturation_on_pair(autocorr_images,
3129 diff_flats,ons,offs,
3130 detmon_lg_config.kappa,
3131 detmon_lg_config.niter,
3132 detmon_lg_config.llx,
3133 detmon_lg_config.lly,
3134 detmon_lg_config.urx,
3135 detmon_lg_config.ury,
3136 detmon_lg_config.saturation_limit,
3137 dit_nb, mode, rows_linear_affected));
3140 if (*rows_gain_affected)
3143 skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
3145 cpl_msg_info(cpl_func,
"Linearity reduction for nb %d",
3148 if (*rows_linear_affected) {
3149 skip_if(detmon_lin_table_fill_row(linear_table, c_dit,
3150 linearity_inputs, ons, offs,
3151 detmon_lg_config.llx,
3152 detmon_lg_config.lly,
3153 detmon_lg_config.urx,
3154 detmon_lg_config.ury,
3155 dit_nb, *dit_nskip, mode));
3157 skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
3169 if(opt_nir == OPT &&
3170 *rows_linear_affected != 0 ) {
3171 detmon_opt_contamination(ons, offs, mode, qclist);
3178 cpl_frameset_delete(pair_on);
3179 cpl_imagelist_delete(ons);
3181 if(!detmon_lg_config.collapse ) {
3182 cpl_imagelist_delete(offs);
3185 if(!detmon_lg_config.collapse) {
3186 cpl_frameset_delete(pair_off);
3189 cpl_propertylist_delete(plist);
3190 cpl_propertylist_delete(pDETlist);
3191 return cpl_error_get_code();
3201 static cpl_error_code
3202 detmon_add_adl_column(cpl_table * table,
3203 cpl_boolean opt_nir)
3205 cpl_error_code error;
3206 double mean_med_dit;
3209 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
3211 mean_med_dit = cpl_table_get_column_mean(table,
"MED_DIT");
3213 dits = cpl_table_get_data_double(table,
"EXPTIME");
3215 dits = cpl_table_get_data_double(table,
"DIT");
3217 error = cpl_table_copy_data_double(table,
"ADL", dits);
3218 cpl_ensure_code(!error, error);
3219 error = cpl_table_multiply_scalar(table,
"ADL", mean_med_dit);
3220 cpl_ensure_code(!error, error);
3222 return cpl_error_get_code();
3234 static cpl_error_code
3235 detmon_lg_reduce_init(cpl_table * gain_table,
3236 cpl_table * linear_table,
3237 cpl_imagelist ** linearity_inputs,
3238 const cpl_boolean opt_nir)
3240 skip_if(detmon_gain_table_create(gain_table, opt_nir));
3241 skip_if(detmon_lin_table_create(linear_table, opt_nir));
3243 if(detmon_lg_config.pix2pix) {
3244 *linearity_inputs = cpl_imagelist_new();
3245 skip_if(*linearity_inputs == NULL);
3250 return cpl_error_get_code();
3261 irplib_pfits_get_dit(
const cpl_propertylist * plist)
3263 return irplib_pfits_get_prop_double(plist,
"ESO DET DIT");
3274 irplib_pfits_get_dit_opt(
const cpl_propertylist * plist)
3276 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3285 static cpl_propertylist*
3286 detmon_load_pro_keys(
const char* NAME_O)
3288 cpl_propertylist* pro_keys=NULL;
3289 pro_keys=cpl_propertylist_load_regexp(NAME_O,0,
"^(ESO PRO)",0);
3294 static double irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
3295 const char* prop_name)
3298 dit = cpl_propertylist_get_double(plist, prop_name);
3299 if(cpl_error_get_code() != CPL_ERROR_NONE)
3301 cpl_msg_error(cpl_func,
"Cannot read property '%s', err[%s]",
3302 prop_name, cpl_error_get_where());
3307 static cpl_error_code
3308 detmon_gain_compute_qc(
double kappa,
int nclip,
const int pos,
3309 const cpl_imagelist* offs,
unsigned mode,
3310 double double_adu,
double avg_on1,
double avg_on2,
3311 double avg_off1,
double avg_off2,
double sigma,
3312 double sig_off_dif,
double gain,
int c_ndit,
3313 double gain_corr,
double autocorr, cpl_image* on_dif,
3314 cpl_table* gain_table)
3318 double avg_on_dif, sig_on_dif;
3319 irplib_ksigma_clip(on_dif, 1, 1, cpl_image_get_size_x(on_dif),
3320 cpl_image_get_size_y(on_dif), kappa, nclip, 1e-5,
3321 &avg_on_dif, &sig_on_dif);
3323 cpl_table_set_double(gain_table,
"SIG_ON_DIF", pos,
3325 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3326 double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
3329 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
3331 sigma = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
3335 gain = double_adu / (c_ndit * sigma);
3337 gain_corr = gain / (autocorr);
3339 skip_if(cpl_table_set_double(gain_table,
"GAIN", pos, gain));
3341 cpl_table_set_double(gain_table,
"GAIN_CORR", pos,
3345 skip_if(cpl_table_set_double(gain_table,
"AUTOCORR", pos, autocorr));
3346 skip_if(cpl_table_set_double(gain_table,
"ADU", pos, double_adu / 2));
3349 cpl_table_set_double(gain_table,
"Y_FIT", pos,
3350 c_ndit * sig_on_dif * sig_on_dif));
3352 cpl_table_set_double(gain_table,
"Y_FIT_CORR", pos,
3353 c_ndit * sig_on_dif * sig_on_dif));
3354 skip_if(cpl_table_set_double(gain_table,
"X_FIT", pos, double_adu));
3356 cpl_table_set_double(gain_table,
"X_FIT_CORR", pos,
3357 double_adu / autocorr));
3361 return cpl_error_get_code();
3365 detmon_gain_prepare_autocorr(
unsigned mode,
const int pos,
double autocorr,
3366 int m,
int n, cpl_imagelist* diff_flats,
3367 cpl_image* on_dif, cpl_imagelist* autocorr_images)
3369 if (mode & IRPLIB_GAIN_WITH_AUTOCORR) {
3371 cpl_image * diff = cpl_image_duplicate(on_dif);
3372 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
3374 if (autocorr_images) {
3375 cpl_image * corr = NULL;
3376 autocorr = detmon_autocorr_factor(on_dif, &corr, m, n);
3378 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
3381 detmon_lg_add_empty_image(autocorr_images, pos);
3385 autocorr = detmon_autocorr_factor(on_dif, NULL, m, n);
3387 autocorr = isnan(autocorr) ? 1.0 : autocorr;
3398 detmon_gain_prepare_table(
const cpl_imagelist* offs,
unsigned mode,
int llx,
3399 int lly,
int urx,
int ury,
double kappa,
int nclip,
3400 double avg_off1,
double std,
const int pos,
3401 cpl_table* gain_table,
double* avg_off2,
3402 double* sig_off_dif)
3409 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3412 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3413 llx, lly, urx, ury, kappa, nclip, 1e-5,
3415 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF", pos, avg_off1));
3418 else if ((mode & IRPLIB_GAIN_NO_COLLAPSE)
3419 || (pos == 0 && mode & IRPLIB_GAIN_COLLAPSE)) {
3420 cpl_image * off_dif = NULL;
3423 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3424 llx, lly, urx, ury, kappa, nclip, 1e-5,
3426 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3428 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 1),
3429 llx, lly, urx, ury, kappa, nclip, 1e-5,
3431 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3432 off_dif = detmon_subtract_create_window(
3433 cpl_imagelist_get_const(offs, 0),
3434 cpl_imagelist_get_const(offs, 1), llx, lly, urx, ury);
3435 skip_if(off_dif == NULL);
3436 irplib_ksigma_clip(off_dif, 1, 1, cpl_image_get_size_x(off_dif),
3437 cpl_image_get_size_y(off_dif), kappa, nclip, 1e-5,
3438 &avg_off_dif, sig_off_dif);
3439 cpl_image_delete(off_dif);
3441 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3444 else if (pos > 0 && (mode & IRPLIB_GAIN_COLLAPSE)) {
3447 avg_off1 = cpl_table_get_double(gain_table,
"MEAN_OFF1", 0, &status);
3448 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3449 *avg_off2 = cpl_table_get_double(gain_table,
"MEAN_OFF2", 0, &status);
3450 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3451 *sig_off_dif = cpl_table_get_double(gain_table,
"SIG_OFF_DIF", 0,
3454 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3499 static cpl_error_code
3500 detmon_gain_table_fill_row(cpl_table * gain_table,
3501 double c_dit,
int c_ndit,
3502 cpl_imagelist * autocorr_images,
3503 cpl_imagelist * diff_flats,
3504 const cpl_imagelist * ons,
3505 const cpl_imagelist * offs,
3506 double kappa,
int nclip,
3507 int llx,
int lly,
int urx,
int ury,
3509 double saturation_limit,
3510 double gain_threshold,
3511 const int pos,
unsigned mode,
int* rows_gain_affected)
3513 const cpl_image *image;
3514 cpl_image *on_dif = NULL;
3516 double avg_on1, avg_on2;
3517 double avg_off1, avg_off2;
3518 double double_adu, autocorr, gain, gain_corr;
3521 cpl_table_set(gain_table,
"FLAG", pos, 1);
3522 if (mode & IRPLIB_GAIN_NIR)
3524 cpl_table_set(gain_table,
"DIT", pos, c_dit);
3525 cpl_table_set(gain_table,
"NDIT", pos, c_ndit);
3526 }
else if (mode & IRPLIB_GAIN_OPT)
3528 cpl_table_set(gain_table,
"EXPTIME", pos, c_dit);
3531 cpl_msg_error(cpl_func,
"Mandatory mode (OPT or NIR) not provided");
3534 if(*rows_gain_affected == 0)
3536 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3537 cpl_table_set(gain_table,
"FLAG", pos, 0);
3538 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3543 detmon_lg_add_empty_image(diff_flats, pos);
3545 if (autocorr_images)
3547 detmon_lg_add_empty_image(autocorr_images, pos);
3550 return cpl_error_get_code();
3552 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3553 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3554 nclip, 1e-5, &avg_on1, &std));
3555 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3556 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3557 nclip, 1e-5, &avg_on2, &std));
3560 (avg_on1 > gain_threshold) ||
3561 (avg_on2 > gain_threshold)
3567 if ( (avg_on1 > gain_threshold) || (avg_on2 > gain_threshold) )
3569 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the gain_theshold parameter, "
3570 "the frames would not be taken into calculation");
3572 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3573 avg_on1, avg_on2, gain_threshold);
3576 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3577 cpl_table_set(gain_table,
"FLAG", pos, 0);
3578 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3583 detmon_lg_add_empty_image(diff_flats, pos);
3585 if (autocorr_images)
3587 detmon_lg_add_empty_image(autocorr_images, pos);
3590 *rows_gain_affected = 0;
3598 *rows_gain_affected = 1;
3599 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON1", pos, avg_on1));
3600 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON2", pos, avg_on2));
3603 detmon_subtract_create_window(cpl_imagelist_get_const(ons, 0),
3604 cpl_imagelist_get_const(ons, 1),
3605 llx, lly, urx, ury);
3606 skip_if(on_dif == NULL);
3608 autocorr = detmon_gain_prepare_autocorr(mode, pos, autocorr, m, n,
3609 diff_flats, on_dif, autocorr_images);
3611 avg_off1 = detmon_gain_prepare_table(offs, mode, llx, lly, urx, ury,
3612 kappa, nclip, avg_off1, std, pos, gain_table, &avg_off2,
3615 detmon_gain_compute_qc(kappa, nclip, pos, offs, mode, double_adu,
3616 avg_on1, avg_on2, avg_off1, avg_off2, sigma,
3617 sig_off_dif, gain, c_ndit, gain_corr, autocorr, on_dif,
3622 cpl_image_delete(on_dif);
3624 return cpl_error_get_code();
3652 static cpl_error_code
3653 detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
3654 cpl_imagelist * diff_flats,
3655 const cpl_imagelist * ons,
3656 const cpl_imagelist * offs,
3657 double kappa,
int nclip,
3658 int llx,
int lly,
int urx,
int ury,
3659 double saturation_limit,
3660 const int pos,
unsigned mode,
int* rows_linear_affected)
3662 const cpl_image *image;
3664 double avg_on1, avg_on2;
3668 if(*rows_linear_affected == 0)
3670 cpl_msg_info(cpl_func,
"For linearity skip the frame #%d", pos + 1);
3671 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3675 detmon_lg_add_empty_image(diff_flats, pos);
3677 if (autocorr_images)
3679 detmon_lg_add_empty_image(autocorr_images, pos);
3682 return cpl_error_get_code();
3684 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3685 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3686 nclip, 1e-5, &avg_on1, &std));
3687 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3688 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3689 nclip, 1e-5, &avg_on2, &std));
3692 (avg_on1 > saturation_limit) ||
3693 (avg_on2 > saturation_limit)
3699 if ( (avg_on1 > saturation_limit) || (avg_on2 > saturation_limit) )
3701 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the saturation_limit parameter, "
3702 "the frames would not be taken into calculation");
3704 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3705 avg_on1, avg_on2, saturation_limit);
3708 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3709 *rows_linear_affected = 0;
3716 return cpl_error_get_code();
3732 detmon_bpixs(
const cpl_imagelist * coeffs,
3739 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
3746 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
3747 cpl_image_get_size_y(first));
3748 cpl_image *cur_image = NULL;
3749 cpl_image *bpm = NULL;
3752 size = cpl_imagelist_get_size(coeffs);
3755 bpm = cpl_image_new(cpl_image_get_size_x(first),
3756 cpl_image_get_size_y(first),
3761 for(i = 0; i < size; i++) {
3762 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
3764 stats = cpl_stats_new_from_image(cur_coeff,
3765 CPL_STATS_MEAN | CPL_STATS_STDEV);
3766 cur_mean = cpl_stats_get_mean(stats);
3767 cur_stdev = cpl_stats_get_stdev(stats);
3769 lo_cut = cur_mean - kappa * cur_stdev;
3770 hi_cut = cur_mean + kappa * cur_stdev;
3772 cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
3773 cpl_mask_not(cur_mask);
3776 cur_image = cpl_image_new_from_mask(cur_mask);
3778 cpl_image_power(cur_image, p);
3779 cpl_image_add(bpm, cur_image);
3780 cpl_image_delete(cur_image);
3783 cpl_mask_or(mask, cur_mask);
3785 cpl_mask_delete(cur_mask);
3786 cpl_stats_delete(stats);
3790 bpm = cpl_image_new_from_mask(mask);
3793 *nbpixs += cpl_mask_count(mask);
3795 cpl_mask_delete(mask);
3922 detmon_autocorr_factor(
const cpl_image * image,
3923 cpl_image ** autocorr_image,
int m,
int n)
3925 cpl_image * mycorr_image = NULL;
3926 double autocorr = 0;
3927 cpl_error_code err = CPL_ERROR_NONE;
3929 mycorr_image = detmon_image_correlate(image, image, m, n);
3930 err=cpl_error_get_code();
3931 if (err == CPL_ERROR_UNSUPPORTED_MODE)
3933 cpl_msg_warning(cpl_func,
"FFTW is not supported by CPL, autocorrelation "
3934 "would be computed using internal implementation");
3937 cpl_image_delete(mycorr_image);
3938 mycorr_image = detmon_autocorrelate(image, m, n);
3940 if(mycorr_image == NULL) {
3944 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
3946 autocorr = cpl_image_get_flux(mycorr_image);
3948 if (autocorr_image) *autocorr_image = mycorr_image;
3949 else cpl_image_delete(mycorr_image);
3954 static cpl_propertylist*
3955 detmon_lg_extract_qclist_4plane(cpl_propertylist* linc_qclist,
const int ip)
3958 cpl_propertylist* sub_set=NULL;
3961 sub_set=cpl_propertylist_new();
3962 qc_key=cpl_sprintf(
"QC LIN COEF%d",ip);
3963 cpl_propertylist_copy_property_regexp(sub_set,linc_qclist,qc_key,0);
3980 static cpl_error_code
3981 detmon_lg_extract_extention_header(cpl_frameset* frameset,
3982 cpl_propertylist* gaint_qclist,
3983 cpl_propertylist* lint_qclist,
3984 cpl_propertylist* linc_qclist,
3985 cpl_propertylist* bpm_qclist,
3989 cpl_propertylist * xplist = NULL;
3991 const char * filename =
3992 cpl_frame_get_filename(cpl_frameset_get_first(frameset));
3994 xplist = cpl_propertylist_load_regexp(filename, whichext,
3995 "ESO DET|EXTNAME", 0);
3996 if (detmon_lg_config.exts >= 0)
3999 cpl_property* propExtname = NULL;
4000 propExtname = cpl_propertylist_get_property(xplist,
"EXTNAME");
4002 if (NULL != propExtname)
4004 propExtname = cpl_property_duplicate(propExtname);
4006 cpl_propertylist_delete(xplist);
4008 if (NULL != propExtname)
4010 xplist = cpl_propertylist_new();
4011 cpl_propertylist_append_property(xplist, propExtname);
4012 cpl_property_delete(propExtname);
4017 cpl_propertylist_append(gaint_qclist, xplist);
4018 cpl_propertylist_append(lint_qclist, xplist);
4019 cpl_propertylist_append(linc_qclist, xplist);
4020 cpl_propertylist_append(bpm_qclist, xplist);
4021 cpl_propertylist_delete(xplist);
4024 return cpl_error_get_code();
4041 static cpl_error_code
4042 detmon_lg_save_table_with_pro_keys(cpl_table* table,
4044 cpl_propertylist* xheader,
4045 unsigned CPL_IO_MODE)
4048 cpl_propertylist* pro_keys=NULL;
4050 pro_keys=detmon_load_pro_keys(name_o);
4051 cpl_propertylist_append(xheader,pro_keys);
4053 if(CPL_IO_MODE==CPL_IO_DEFAULT) {
4054 cpl_propertylist * pri_head=cpl_propertylist_load(name_o,0);
4055 cpl_table_save(table, pri_head,xheader,name_o,
4057 cpl_propertylist_delete(pri_head);
4060 cpl_table_save(table,NULL,xheader,name_o,
4063 cpl_propertylist_delete(pro_keys);
4065 return cpl_error_get_code();
4077 static cpl_error_code
4078 detmon_lg_save_image_with_pro_keys(cpl_image* image,
4080 cpl_propertylist* xheader)
4083 cpl_propertylist* pro_keys=NULL;
4084 pro_keys=detmon_load_pro_keys(name_o);
4085 cpl_propertylist_append(xheader,pro_keys);
4087 cpl_image_save(image,name_o, CPL_BPP_IEEE_FLOAT,
4088 xheader,CPL_IO_EXTEND);
4089 cpl_propertylist_delete(pro_keys);
4092 return cpl_error_get_code();
4104 static cpl_error_code
4105 detmon_lg_save_imagelist_with_pro_keys(cpl_imagelist* imagelist,
4107 cpl_propertylist* xheader)
4110 cpl_propertylist* pro_keys=NULL;
4111 pro_keys=detmon_load_pro_keys(name_o);
4112 cpl_propertylist_append(xheader,pro_keys);
4114 cpl_imagelist_save(imagelist,name_o, CPL_BPP_IEEE_FLOAT,
4115 xheader,CPL_IO_EXTEND);
4117 cpl_propertylist_delete(pro_keys);
4120 return cpl_error_get_code();
4140 static cpl_error_code
4141 detmon_lg_save_plane(
const cpl_parameterlist * parlist,
4142 cpl_frameset* frameset,
4143 const cpl_frameset * usedframes,
4145 const char* recipe_name,
4146 cpl_propertylist* mypro_coeffscube,
4147 cpl_propertylist* linc_plane_qclist,
4148 const char* package,
4152 if(detmon_lg_config.exts == 0) {
4153 cpl_propertylist* plist=NULL;
4154 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4156 CPL_BPP_IEEE_FLOAT, recipe_name,
4157 mypro_coeffscube, NULL,
4159 plist=cpl_propertylist_load(NAME_O,0);
4160 cpl_image_save(plane,NAME_O, CPL_BPP_IEEE_FLOAT,
4161 plist,CPL_IO_DEFAULT);
4162 cpl_propertylist_delete(plist);
4164 }
else if(detmon_lg_config.exts > 0) {
4165 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4167 CPL_BPP_IEEE_FLOAT, recipe_name,
4168 mypro_coeffscube, NULL,
4171 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4175 cpl_dfs_save_image(frameset, NULL, parlist,
4176 usedframes,NULL, NULL,
4177 CPL_BPP_IEEE_FLOAT, recipe_name,
4178 mypro_coeffscube, NULL,
4180 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4183 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4189 return cpl_error_get_code();
4212 static cpl_error_code
4213 detmon_lg_save_cube(
const cpl_parameterlist * parlist,
4214 cpl_frameset* frameset,
4215 const cpl_frameset * usedframes,
4217 const char* recipe_name,
4218 cpl_propertylist* mypro_coeffscube,
4219 cpl_propertylist* linc_qclist,
4220 const char* package,
4222 cpl_imagelist* coeffs)
4225 if(detmon_lg_config.exts == 0) {
4226 cpl_propertylist_append(mypro_coeffscube, linc_qclist);
4227 detmon_lg_dfs_save_imagelist
4228 (frameset, parlist, usedframes, coeffs,
4229 recipe_name, mypro_coeffscube, package,
4231 }
else if(detmon_lg_config.exts > 0) {
4232 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4234 CPL_BPP_IEEE_FLOAT, recipe_name,
4235 mypro_coeffscube, NULL,
4238 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4242 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4244 CPL_BPP_IEEE_FLOAT, recipe_name,
4245 mypro_coeffscube, NULL,
4248 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4250 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4253 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4255 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4259 return cpl_error_get_code();
4263 detmon_lg_set_paf_name_and_header(cpl_frame* ref_frame,
4264 int flag_sets,
int which_set,
4266 const char* paf_suf,
4267 cpl_propertylist** plist)
4269 char * paf_name=NULL;
4271 if(detmon_lg_config.exts >= 0)
4273 *plist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4274 detmon_lg_config.exts);
4278 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4282 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4283 detmon_lg_config.pafname, paf_suf,which_set);
4288 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4294 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4295 detmon_lg_config.pafname, paf_suf,whichext);
4299 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4300 detmon_lg_config.pafname,paf_suf,
4301 which_set, whichext);
4310 detmon_lg_set_paf_name_and_header_ext(cpl_frame* ref_frame,
4311 int flag_sets,
int which_set,
4313 const char* paf_suf,
4314 cpl_propertylist** plist)
4316 char* paf_name=NULL;
4318 if(detmon_lg_config.exts >= 0)
4320 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4321 detmon_lg_config.exts);
4325 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4328 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4329 detmon_lg_config.pafname, paf_suf,which_set);
4333 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4337 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4338 detmon_lg_config.pafname, paf_suf,whichext);
4341 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4342 detmon_lg_config.pafname,paf_suf,
4343 which_set, whichext);
4350 static cpl_error_code
4351 detmon_lg_save_paf_product(cpl_frame* ref_frame,
int flag_sets,
4352 int which_set,
int whichext,
4353 const char* pafregexp,
4354 const char* procatg,
4355 const char* pipeline_name,
4356 const char* recipe_name,
4357 const char* paf_suf,
4358 cpl_propertylist* qclist,
4363 char* paf_name=NULL;
4364 cpl_propertylist* plist=NULL;
4365 cpl_propertylist* paflist = NULL;
4366 cpl_propertylist* mainplist=NULL;
4368 mainplist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0);
4370 paf_name=detmon_lg_set_paf_name_and_header(ref_frame,flag_sets,
4374 paf_name=detmon_lg_set_paf_name_and_header_ext(ref_frame,flag_sets,
4380 paflist = cpl_propertylist_new();
4381 cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,procatg);
4384 cpl_propertylist_copy_property_regexp(paflist, plist,pafregexp, 0);
4385 cpl_propertylist_copy_property_regexp(paflist, mainplist,pafregexp, 0);
4386 cpl_propertylist_append(paflist,qclist);
4389 cpl_dfs_save_paf(pipeline_name, recipe_name,paflist,paf_name);
4392 cpl_propertylist_delete(mainplist);
4393 cpl_propertylist_delete(paflist);
4394 cpl_propertylist_delete(plist);
4397 return cpl_error_get_code();
4434 static cpl_error_code
4435 detmon_lg_save(
const cpl_parameterlist * parlist,
4436 cpl_frameset * frameset,
4437 const char *recipe_name,
4438 const char *pipeline_name,
4439 const char *pafregexp,
4440 const cpl_propertylist * pro_lintbl,
4441 const cpl_propertylist * pro_gaintbl,
4442 const cpl_propertylist * pro_coeffscube,
4443 const cpl_propertylist * pro_bpm,
4444 const cpl_propertylist * pro_corr,
4445 const cpl_propertylist * pro_diff,
4446 const char *package,
4447 cpl_imagelist * coeffs,
4448 cpl_table * gain_table,
4449 cpl_table * linear_table,
4451 cpl_imagelist * autocorr_images,
4452 cpl_imagelist * diff_flats,
4453 cpl_propertylist * gaint_qclist,
4454 cpl_propertylist * lint_qclist,
4455 cpl_propertylist * linc_qclist,
4456 cpl_propertylist * bpm_qclist,
4457 const int flag_sets,
4458 const int which_set,
4459 const cpl_frameset * usedframes,
4463 cpl_frame *ref_frame;
4464 cpl_propertylist *plist = NULL;
4465 cpl_propertylist *mainplist = NULL;
4471 cpl_propertylist * xplist = NULL;
4473 cpl_propertylist* linc_plane_qclist=NULL;
4474 cpl_image* plane=NULL;
4476 char* pcatg_plane=NULL;
4478 cpl_propertylist * mypro_lintbl =
4479 cpl_propertylist_duplicate(pro_lintbl);
4480 cpl_propertylist * mypro_gaintbl =
4481 cpl_propertylist_duplicate(pro_gaintbl);
4482 cpl_propertylist * mypro_coeffscube =
4483 cpl_propertylist_duplicate(pro_coeffscube);
4484 cpl_propertylist * mypro_bpm =
4485 cpl_propertylist_duplicate(pro_bpm);
4486 cpl_propertylist * mypro_corr =
4487 cpl_propertylist_duplicate(pro_corr);
4488 cpl_propertylist * mypro_diff =
4489 cpl_propertylist_duplicate(pro_diff);
4491 const char * procatg_lintbl =
4492 cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
4494 const char * procatg_gaintbl =
4495 cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
4497 const char * procatg_coeffscube =
4498 cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
4499 const char * procatg_bpm =
4500 cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
4504 detmon_lg_extract_extention_header(frameset,gaint_qclist,lint_qclist,
4505 linc_qclist,bpm_qclist,whichext);
4510 ref_frame = cpl_frameset_get_first(frameset);
4512 skip_if((mainplist =
4513 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4519 cpl_msg_info(cpl_func,
"Write the LINEARITY TABLE");
4522 NAME_O=cpl_sprintf(
"%s_linearity_table.fits", recipe_name);
4524 NAME_O=cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name,
4528 if (detmon_lg_config.exts >= 0) {
4530 cpl_propertylist_append(mypro_lintbl, lint_qclist);
4531 skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,
4532 linear_table,NULL, recipe_name,
4533 mypro_lintbl, NULL, package, NAME_O));
4535 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4536 lint_qclist,CPL_IO_DEFAULT);
4541 skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL,
4542 linear_table,lint_qclist, recipe_name,
4543 mypro_lintbl,NULL, package, NAME_O));
4544 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4545 lint_qclist,CPL_IO_DEFAULT);
4552 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4553 lint_qclist,CPL_IO_EXTEND);
4556 irplib_free(&NAME_O);
4560 cpl_msg_info(cpl_func,
"Write the GAIN TABLE");
4563 NAME_O=cpl_sprintf(
"%s_gain_table.fits", recipe_name);
4565 NAME_O=cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name,
4569 if (detmon_lg_config.exts >= 0)
4573 cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
4574 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
4575 gain_table,NULL, recipe_name, mypro_gaintbl,
4576 NULL, package, NAME_O));
4577 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4578 gaint_qclist,CPL_IO_DEFAULT);
4586 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
4587 gaint_qclist, recipe_name, mypro_gaintbl,
4588 NULL, package, NAME_O));
4589 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4590 gaint_qclist,CPL_IO_DEFAULT);
4596 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4597 gaint_qclist,CPL_IO_EXTEND);
4601 if(detmon_lg_config.pix2pix)
4607 cpl_msg_info(cpl_func,
"Write the COEFFS FITS");
4608 irplib_free(&NAME_O);
4611 PREF_O=cpl_sprintf(
"%s_coeffs_cube", recipe_name);
4614 PREF_O=cpl_sprintf(
"%s_coeffs_cube_set%02d",
4615 recipe_name, which_set);
4617 if (detmon_lg_config.split_coeffs == 0) {
4618 NAME_O=cpl_sprintf(
"%s.fits", PREF_O);
4623 if(detmon_lg_config.split_coeffs != 0){
4626 nb_images = cpl_imagelist_get_size(coeffs);
4627 for(ip=0;ip<nb_images;ip++) {
4628 NAME_O=cpl_sprintf(
"%s_P%d.fits", PREF_O,ip);
4629 pcatg_plane=cpl_sprintf(
"COEFFS_CUBE_P%d",ip);
4630 cpl_propertylist_delete(mypro_coeffscube);
4631 mypro_coeffscube=cpl_propertylist_duplicate(pro_coeffscube);
4632 cpl_propertylist_set_string(mypro_coeffscube,CPL_DFS_PRO_CATG,
4634 linc_plane_qclist=detmon_lg_extract_qclist_4plane(linc_qclist,ip);
4635 cpl_propertylist_append(mypro_coeffscube, linc_plane_qclist);
4636 plane=cpl_imagelist_get(coeffs,ip);
4637 detmon_lg_save_plane(parlist,frameset,usedframes,whichext,
4638 recipe_name,mypro_coeffscube,
4639 linc_plane_qclist,package,NAME_O,plane);
4641 if(NULL!=linc_plane_qclist) {
4642 cpl_propertylist_delete(linc_plane_qclist);
4644 irplib_free(&NAME_O);
4649 detmon_lg_save_cube(parlist,frameset,usedframes,whichext,
4650 recipe_name,mypro_coeffscube,
4651 linc_qclist,package,NAME_O,coeffs);
4657 cpl_msg_info(cpl_func,
"Write the BAD PIXEL MAP");
4658 irplib_free(&NAME_O);
4662 NAME_O=cpl_sprintf(
"%s_bpm.fits", recipe_name);
4665 NAME_O=cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, which_set);
4670 if(detmon_lg_config.exts == 0) {
4671 cpl_propertylist_append(mypro_bpm, bpm_qclist);
4672 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
4673 CPL_BPP_IEEE_FLOAT, recipe_name,
4674 mypro_bpm, NULL, package,
4677 else if(detmon_lg_config.exts > 0)
4679 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4680 CPL_BPP_IEEE_FLOAT, recipe_name,
4681 mypro_bpm, NULL, package,
4683 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4689 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4690 CPL_BPP_IEEE_FLOAT, recipe_name,
4691 mypro_bpm, NULL, package,
4693 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4696 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4701 if(detmon_lg_config.intermediate)
4706 cpl_msg_info(cpl_func,
"Write the AUTOCORRS FITS");
4707 nb_images = cpl_imagelist_get_size(autocorr_images);
4708 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
4709 for(i = 0; i < nb_images; i++)
4711 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_corr);
4713 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4715 if(i < cpl_table_get_nrow(linear_table))
4717 ddit = cpl_table_get_double(linear_table,
4718 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4720 cpl_array_delete(pnames);
4723 irplib_free(&NAME_O);
4726 NAME_O=cpl_sprintf(
"%s_autocorr_%d.fits", recipe_name, i);
4727 assert(NAME_O != NULL);
4730 NAME_O=cpl_sprintf(
"%s_autocorr_%02d_set%02d.fits",
4731 recipe_name, i, which_set);
4732 assert(NAME_O != NULL);
4735 if(detmon_lg_config.exts > 0)
4737 cpl_propertylist* pextlist = cpl_propertylist_new();
4738 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4739 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4740 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4741 recipe_name, pplist, NULL,
4744 detmon_lg_save_image_with_pro_keys(
4745 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4747 cpl_propertylist_delete(pextlist);
4749 if(detmon_lg_config.exts == 0)
4751 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4752 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
4753 cpl_imagelist_get(autocorr_images, i),
4755 recipe_name, pplist, NULL, package,
4761 cpl_propertylist* pextlist = cpl_propertylist_new();
4762 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4765 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4766 usedframes, NULL,NULL,
4767 CPL_BPP_IEEE_FLOAT, recipe_name,
4771 detmon_lg_save_image_with_pro_keys(
4772 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4777 detmon_lg_save_image_with_pro_keys(
4778 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4780 cpl_propertylist_delete(pextlist);
4782 cpl_propertylist_delete (pplist);
4784 irplib_free(&NAME_O);
4793 cpl_msg_info(cpl_func,
"Write the DIFFS FITS");
4795 for(i = 0; i < nb_images; i++)
4797 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_diff);
4799 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4801 if(i < cpl_table_get_nrow(linear_table))
4803 ddit = cpl_table_get_double(linear_table,
4804 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4806 cpl_array_delete(pnames);
4811 NAME_O=cpl_sprintf(
"%s_diff_flat_%d.fits", recipe_name, i);
4814 NAME_O=cpl_sprintf(
"%s_diff_flat_%d_set%02d.fits",
4815 recipe_name, i, which_set);
4818 if(detmon_lg_config.exts > 0)
4820 cpl_propertylist* pextlist = cpl_propertylist_new();
4821 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4822 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT", ddit);
4823 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4824 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4826 mypro_diff, NULL,package, NAME_O));
4828 detmon_lg_save_image_with_pro_keys(
4829 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4831 cpl_propertylist_delete(pextlist);
4833 else if(detmon_lg_config.exts == 0)
4835 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4837 (frameset, NULL, parlist, usedframes, NULL,
4838 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
4839 recipe_name, pplist, NULL, package,
4844 cpl_propertylist* pextlist = cpl_propertylist_new();
4845 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4848 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT",ddit);
4850 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4851 usedframes, NULL,NULL,
4852 CPL_BPP_IEEE_FLOAT, recipe_name,
4853 mypro_diff, NULL,package, NAME_O));
4855 detmon_lg_save_image_with_pro_keys(
4856 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4861 detmon_lg_save_image_with_pro_keys(
4862 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4865 cpl_propertylist_delete(pextlist);
4867 cpl_propertylist_delete(pplist);
4868 irplib_free(&NAME_O);
4876 cpl_msg_info(cpl_func,
"Write the PAF file(s)");
4878 if(detmon_lg_config.pafgen) {
4880 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4881 pafregexp,procatg_gaintbl,
4882 pipeline_name,recipe_name,
4883 "qc01",gaint_qclist,0);
4885 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4886 pafregexp,procatg_lintbl,
4887 pipeline_name,recipe_name,
4888 "qc02",lint_qclist,0);
4890 if(detmon_lg_config.pix2pix)
4893 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4896 pipeline_name,recipe_name,
4897 "qc03",linc_qclist,1);
4899 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4900 whichext,pafregexp,procatg_bpm,
4901 pipeline_name,recipe_name,
4902 "qc04",bpm_qclist,1);
4907 cpl_msg_info(cpl_func,
"exit");
4909 cpl_propertylist_delete(xplist);
4911 cpl_propertylist_delete(plist);
4915 irplib_free(&NAME_O);
4917 cpl_free(pcatg_plane);
4918 cpl_propertylist_delete(mainplist);
4919 cpl_propertylist_delete(mypro_lintbl);
4920 cpl_propertylist_delete(mypro_gaintbl);
4921 cpl_propertylist_delete(mypro_coeffscube);
4922 cpl_propertylist_delete(mypro_bpm);
4923 cpl_propertylist_delete(mypro_corr);
4924 cpl_propertylist_delete(mypro_diff);
4926 return cpl_error_get_code();
4939 static cpl_error_code
4940 detmon_opt_contamination(
const cpl_imagelist * ons,
4941 const cpl_imagelist * offs,
4943 cpl_propertylist * qclist)
4951 struct rect rects[5] = {
4952 (
struct rect){ detmon_lg_config.llx1,
4953 detmon_lg_config.lly1,
4954 detmon_lg_config.urx1,
4955 detmon_lg_config.ury1},
4956 (
struct rect){ detmon_lg_config.llx2,
4957 detmon_lg_config.lly2,
4958 detmon_lg_config.urx2,
4959 detmon_lg_config.ury2},
4960 (
struct rect){ detmon_lg_config.llx3,
4961 detmon_lg_config.lly3,
4962 detmon_lg_config.urx3,
4963 detmon_lg_config.ury3},
4964 (
struct rect){ detmon_lg_config.llx4,
4965 detmon_lg_config.lly4,
4966 detmon_lg_config.urx4,
4967 detmon_lg_config.ury4},
4968 (
struct rect){ detmon_lg_config.llx5,
4969 detmon_lg_config.lly5,
4970 detmon_lg_config.urx5,
4971 detmon_lg_config.ury5},
4974 for (
size_t i = 0; i < 5; i++) {
4975 cpl_image * dif_avg;
4976 const cpl_image * off2;
4979 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
4980 off2 = cpl_imagelist_get_const(offs, 0);
4982 off2 = cpl_imagelist_get_const(offs, 1);
4984 dif_avg = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
4985 cpl_imagelist_get_const(offs, 0),
4986 cpl_imagelist_get_const(ons, 1),
4993 median = cpl_image_get_median(dif_avg);
4994 cpl_image_delete(dif_avg);
4997 sprintf(kname,
"%s%d", DETMON_QC_CONTAM, i + 1);
4999 if(cpl_propertylist_has(qclist,kname)){
5000 skip_if(cpl_propertylist_update_double(qclist,kname,median));
5002 skip_if(cpl_propertylist_append_double(qclist,kname,median));
5003 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
5009 return cpl_error_get_code();
5068 detmon_lg_dfs_set_groups(cpl_frameset * set,
5069 const char *tag_on,
const char *tag_off)
5071 cpl_frame *cur_frame;
5081 nframes = cpl_frameset_get_size(set);
5084 for(i = 0; i < nframes; i++) {
5085 cur_frame = cpl_frameset_get_position(set, i);
5086 tag = cpl_frame_get_tag(cur_frame);
5089 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
5090 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
5110 static cpl_error_code
5111 detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist ** coeffs_ptr,
5112 cpl_image **bpms_ptr)
5114 cpl_image* dummy_bpm=NULL;
5115 cpl_image * dummy_coeff=NULL;
5116 cpl_imagelist * dummy_coeffs=NULL;
5128 dummy_bpm = cpl_image_new(detmon_lg_config.nx,
5129 detmon_lg_config.ny,
5131 dummy_coeffs = cpl_imagelist_new();
5133 db_p = cpl_image_get_data_int(dummy_bpm);
5134 rb_p = cpl_image_get_data_int(*bpms_ptr);;
5135 dcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5136 rcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5137 dlength = detmon_lg_config.nx;
5138 rlength = detmon_lg_config.urx - detmon_lg_config.llx + 1;
5139 for (i = 0; i <= detmon_lg_config.order; i++)
5141 dummy_coeff = cpl_image_new(detmon_lg_config.nx,
5142 detmon_lg_config.ny,
5145 cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
5146 dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
5147 rcs_p[i] = cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
5150 for (i = detmon_lg_config.lly - 1; i < detmon_lg_config.ury; i++)
5152 for (j = detmon_lg_config.llx - 1; j < detmon_lg_config.urx; j++)
5154 shift_idx=(i - detmon_lg_config.lly + 1) * rlength +
5155 j - detmon_lg_config.llx + 1;
5156 *(db_p + i * dlength + j) = *(rb_p + shift_idx);
5157 for (k = 0; k <= detmon_lg_config.order; k++)
5159 *(dcs_p[k] + i * dlength + j) =
5160 *(rcs_p[k] + (i - detmon_lg_config.lly + 1) * rlength +
5161 j - detmon_lg_config.llx + 1);
5165 cpl_imagelist_delete(*coeffs_ptr);
5166 cpl_image_delete(*bpms_ptr);
5167 *coeffs_ptr = dummy_coeffs;
5168 *bpms_ptr = dummy_bpm;
5172 return cpl_error_get_code();
5232 detmon_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
5233 const double ron, cpl_image ** ima_errs)
5235 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
5236 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
5237 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
5238 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
5240 *ima_errs = cpl_image_duplicate(ima_data);
5242 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
5246 cpl_image_divide_scalar(*ima_errs, gain);
5247 cpl_image_add_scalar(*ima_errs, ron * ron);
5248 cpl_image_power(*ima_errs, 0.5);
5250 return cpl_error_get_code();
5254 detmon_compute_badpixmap(cpl_boolean opt_nir,
const int nsets,
5255 const cpl_table* linear_table,
5256 const cpl_imagelist* linearity_inputs,
int nbpixs,
5257 cpl_vector* x, cpl_propertylist* gaint_qclist,
5258 cpl_image** bpms_ptr)
5264 if (opt_nir == NIR) {
5265 x = cpl_vector_wrap(nsets,
5266 (
double *) cpl_table_get_data_double_const(linear_table,
5270 x = cpl_vector_wrap(nsets,
5271 (
double *) cpl_table_get_data_double_const(linear_table,
5275 int sz = cpl_imagelist_get_size(linearity_inputs);
5276 int sx = cpl_image_get_size_x(cpl_imagelist_get(linearity_inputs, 0));
5277 int sy = cpl_image_get_size_y(cpl_imagelist_get(linearity_inputs, 0));
5278 double kappa = detmon_lg_config.kappa;
5279 int niter = detmon_lg_config.niter;
5280 int llx = detmon_lg_config.llx;
5281 int urx = detmon_lg_config.urx;
5282 int lly = detmon_lg_config.lly;
5283 int ury = detmon_lg_config.ury;
5286 cpl_image *ima, *err;
5289 cpl_imagelist* errors = cpl_imagelist_new();
5311 cpl_imagelist* linearity_scaled = cpl_imagelist_new();
5313 gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
5317 gain = (gain < 0) ? 1 : gain;
5318 double gain_eff = 2 * gain;
5330 for (
int i = 0; i < sz; i++) {
5331 ima = cpl_imagelist_get(linearity_inputs, i);
5339 irplib_ksigma_clip(ima, 1, 1, urx - llx + 1,
5340 ury - lly + 1, kappa, niter, 1e-5, &avg,
5345 if (avg < detmon_lg_config.saturation_limit) {
5353 cpl_image_get_mad(ima, &dmad);
5354 err = cpl_image_duplicate(ima);
5355 cpl_image_multiply_scalar(err, 0);
5356 cpl_image_add_scalar(err, dmad * CPL_MATH_STD_MAD);
5366 cpl_imagelist_set(errors, err, i);
5374 cpl_imagelist_set(linearity_scaled,
5375 cpl_image_duplicate(ima), i));
5378 hdrl_imagelist* hil = hdrl_imagelist_create(linearity_scaled, errors);
5383 cpl_imagelist_delete(errors);
5385 double pval = 0.001;
5386 p = hdrl_bpm_fit_parameter_create_pval(1, pval);
5395 hdrl_bpm_fit_compute(p, hil, x, bpms_ptr);
5420 nbpixs = cpl_image_get_flux(*bpms_ptr);
5422 hdrl_imagelist_delete(hil);
5423 cpl_imagelist_delete(linearity_scaled);
5424 cpl_vector_unwrap((cpl_vector*) x);
5425 hdrl_parameter_delete(p);
5441 skip_if(*bpms_ptr == NULL);
5462 static cpl_error_code
5463 detmon_lg_reduce_all(
const cpl_table * linear_table,
5464 cpl_propertylist * gaint_qclist,
5465 cpl_propertylist * lint_qclist,
5466 cpl_propertylist * linc_qclist,
5467 cpl_propertylist * bpm_qclist,
5468 cpl_imagelist ** coeffs_ptr,
5469 cpl_image ** bpms_ptr,
5470 const cpl_imagelist * linearity_inputs,
5471 const cpl_table * gain_table,
5472 int which_ext, cpl_boolean opt_nir)
5476 const int linear_nsets = cpl_table_get_nrow(linear_table);
5477 const int gain_nsets = cpl_table_get_nrow(gain_table);
5479 cpl_polynomial *poly_linfit = NULL;
5480 cpl_image *fiterror = NULL;
5481 char * name_o1 = NULL;
5482 char * name_o2 = NULL;
5483 double * pcoeffs = NULL;
5484 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
5487 cpl_vector *x =NULL;
5488 const cpl_vector *y =NULL;
5491 const cpl_image * first = NULL;
5499 cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5500 cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5501 cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
5502 cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
5504 pcoeffs = cpl_malloc(
sizeof(
double)*(detmon_lg_config.order + 1));
5506 skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
5507 detmon_lg_config.method));
5508 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
5509 DETMON_QC_METHOD_C));
5512 if (!strcmp(detmon_lg_config.method,
"PTC")) {
5514 if (detmon_lg_config.exts >= 0) {
5515 cpl_msg_info(cpl_func,
5516 "Polynomial fitting for the GAIN (constant term method)");
5518 cpl_msg_info(cpl_func,
5519 "Polynomial fitting for the GAIN (constant term method)"
5520 " for extension nb %d", which_ext);
5522 skip_if(detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, gain_nsets));
5524 skip_if(detmon_lg_qc_med(gain_table, gaint_qclist, gain_nsets));
5529 if(detmon_lg_config.lamp_ok) {
5530 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
5531 detmon_lg_config.cr));
5532 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
5533 DETMON_QC_LAMP_FLUX_C));
5537 if(detmon_lg_config.autocorr == TRUE) {
5538 autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
5539 skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
5541 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
5542 DETMON_QC_AUTOCORR_C));
5544 if (detmon_lg_config.exts >= 0) {
5545 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix");
5547 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix"
5548 " for extension nb %d", which_ext);
5551 if(!detmon_lg_config.pix2pix) {
5552 const int order=detmon_lg_config.order;
5560 y = cpl_vector_wrap(linear_nsets,
5561 (
double *)cpl_table_get_data_double_const(linear_table,
5564 if (opt_nir == NIR) {
5565 x = cpl_vector_wrap(linear_nsets,
5566 (
double *)cpl_table_get_data_double_const(linear_table,
5569 x = cpl_vector_wrap(linear_nsets,
5570 (
double *)cpl_table_get_data_double_const(linear_table,
5574 if(x == NULL || y == NULL) {
5575 cpl_vector_unwrap((cpl_vector *)x);
5576 cpl_vector_unwrap((cpl_vector *)y);
5586 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
5587 poly_linfit = irplib_polynomial_fit_1d_create(x, y,order,&mse);
5589 if(order == cpl_vector_get_size(x) - 1) {
5590 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5594 if(poly_linfit == NULL) {
5595 cpl_vector_unwrap((cpl_vector *)x);
5596 cpl_vector_unwrap((cpl_vector *)y);
5602 min_val=cpl_vector_get_min(y);
5603 max_val=cpl_vector_get_max(y);
5605 cpl_vector_unwrap((cpl_vector *)x);
5606 cpl_vector_unwrap((cpl_vector *)y);
5608 for(deg = 0; deg <= order; deg++) {
5609 const double coeff =
5610 cpl_polynomial_get_coeff(poly_linfit, °);
5612 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
5613 assert(name_o != NULL);
5614 skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
5615 skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
5616 DETMON_QC_LIN_COEF_C));
5619 pcoeffs[deg] = coeff;
5621 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
5622 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
5623 DETMON_QC_ERRFIT_MSE_C));
5627 const int order=detmon_lg_config.order;
5629 y = cpl_vector_wrap(linear_nsets,
5630 (
double *)cpl_table_get_data_double_const(linear_table,
5635 x = cpl_vector_wrap(linear_nsets,
5636 (
double *)cpl_table_get_data_double_const(linear_table,
5639 x = cpl_vector_wrap(linear_nsets,
5640 (
double *)cpl_table_get_data_double_const(linear_table,
5645 first = cpl_imagelist_get_const(linearity_inputs, 0);
5646 sizex = cpl_image_get_size_x(first);
5647 sizey = cpl_image_get_size_y(first);
5648 vsize = cpl_vector_get_size(x);
5649 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
5651 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,order, FALSE,
5652 CPL_TYPE_FLOAT, fiterror);
5653 min_val=cpl_vector_get_min(y);
5654 max_val=cpl_vector_get_max(y);
5655 cpl_vector_unwrap((cpl_vector*)x);
5656 cpl_vector_unwrap((cpl_vector*)y);
5658 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
5659 "Failed polynomial fit");
5662 for(deg = 0; deg <= order; deg++)
5664 cpl_image *image = cpl_imagelist_get(*coeffs_ptr, deg);
5665 const double coeff = cpl_image_get_median(image);
5666 pcoeffs[deg] = coeff;
5667 name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", (
int)deg);
5668 name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", (
int)deg);
5669 assert(name_o1 != NULL);
5670 assert(name_o2 != NULL);
5671 skip_if(cpl_propertylist_append_double(linc_qclist, name_o1, coeff));
5672 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o1,
5673 DETMON_QC_LIN_COEF_C));
5676 skip_if(cpl_propertylist_append_double(linc_qclist, name_o2,
5677 cpl_image_get_stdev(image)));
5678 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o2,
5679 DETMON_QC_LIN_COEF_ERR_C));
5685 if(order == vsize - 1)
5687 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5688 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5690 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5691 DETMON_QC_ERRFIT_C));
5694 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5695 cpl_image_get_median(fiterror)));
5696 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5697 DETMON_QC_ERRFIT_C));
5701 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
5703 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
5704 DETMON_QC_COUNTS_MIN_C));
5705 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
5707 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
5708 DETMON_QC_COUNTS_MAX_C));
5709 skip_if(detmon_lg_lineff(pcoeffs,lint_qclist,detmon_lg_config.ref_level,
5710 detmon_lg_config.order));
5712 if (detmon_lg_config.exts >= 0)
5714 cpl_msg_info(cpl_func,
"Bad pixel detection");
5717 cpl_msg_info(cpl_func,
"Bad pixel detection"
5718 " for extension nb %d", which_ext);
5720 if(detmon_lg_config.pix2pix)
5724 nbpixs = detmon_compute_badpixmap(opt_nir, linear_nsets, linear_table,
5725 linearity_inputs, nbpixs, x,gaint_qclist, bpms_ptr);
5730 skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
5731 skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
5732 DETMON_QC_NUM_BPM_C));
5733 cpl_msg_info(cpl_func,
"stability=%g",detmon_lg_config.lamp_stability);
5734 if(detmon_lg_config.lamp_stability != 0.0)
5736 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
5737 detmon_lg_config.lamp_stability));
5738 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
5739 DETMON_QC_LAMP_STAB_C));
5742 if (!detmon_lg_config.wholechip && detmon_lg_config.pix2pix)
5744 detmon_lg_fits_coeffs_and_bpm2chip(coeffs_ptr,bpms_ptr);
5751 cpl_image_delete(fiterror);
5752 cpl_polynomial_delete(poly_linfit);
5756 return cpl_error_get_code();
5768 static cpl_error_code
5769 detmon_lg_lineff(
double * pcoeffs,
5770 cpl_propertylist * qclist,
5776 double residual, slope;
5779 cpl_polynomial * poly = cpl_polynomial_new(1);
5793 pcoeffs[0] -= ref_level;
5795 for (i = 2; i <= order; i++)
5798 for(j = 0; j < i; j++)
5800 pcoeffs[i] /= pcoeffs[1];
5806 for (deg = 0; deg <= order; deg++) {
5808 skip_if(cpl_polynomial_set_coeff(poly, °, pcoeffs[deg]));
5817 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
5819 if (slope <= 0.0 && residual >= 0.0) {
5820 cpl_msg_warning(cpl_func,
"Reference level (--ref_level) outside"
5821 " linearity range of the detector. Cannot compute"
5822 " linearity efficiency (QC.LINEFF).");
5827 cpl_error_code err = cpl_polynomial_solve_1d(poly, 0.0, &root, 1);
5832 if (err == CPL_ERROR_NONE)
5835 lineff = (root - ref_level) / ref_level;
5840 cpl_msg_warning(cpl_func,
5841 "Cannot compute linearity efficiency (QC.LINEFF)"
5842 "for the current combination "
5843 " of (--ref-level equal %d) and (--order equal %d) parameters. Try "
5844 "to decrease (--ref-level) value.", ref_level, order);
5847 cpl_msg_warning(cpl_func,
"DETMON_QC_LIN_EFF=%f",lineff );
5848 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
5850 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
5851 DETMON_QC_LIN_EFF_C));
5853 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
5855 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
5856 DETMON_QC_LIN_EFF_FLUX_C));
5860 cpl_polynomial_delete(poly);
5862 return cpl_error_get_code();
5873 static cpl_error_code
5874 detmon_lg_qc_ptc(
const cpl_table * gain_table,
5875 cpl_propertylist * qclist,
unsigned mode,
int rows_in_gain)
5878 cpl_polynomial *poly_fit = NULL;
5879 cpl_polynomial *poly_fit2 = NULL;
5881 const int nsets = rows_in_gain;
5883 cpl_vector *x = NULL;
5884 cpl_vector *y = NULL;
5886 cpl_errorstate prestate;
5888 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
5889 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
5891 x = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5893 y = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5895 skip_if(x == NULL || y == NULL);
5896 if (0 == detmon_lg_check_before_gain(x, y))
5900 cpl_vector_unwrap(x);
5904 cpl_vector_unwrap(y);
5906 return CPL_ERROR_NONE;
5909 poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
5910 skip_if(poly_fit == NULL);
5914 prestate = cpl_errorstate_get();
5915 coef = cpl_polynomial_get_coeff(poly_fit, &i);
5916 skip_if (!cpl_errorstate_is_equal(prestate) || coef==0);
5917 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
5918 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5919 DETMON_QC_CONAD_C));
5922 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
5924 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
5940 if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
5941 const cpl_vector *x2 =
5942 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT_CORR"));
5943 const cpl_vector *y2 =
5944 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5946 if(x2 == NULL || y2 == NULL) {
5947 cpl_vector_unwrap((cpl_vector *)x2);
5948 cpl_vector_unwrap((cpl_vector *)y2);
5959 poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
5960 if(poly_fit2 == NULL) {
5961 cpl_vector_unwrap((cpl_vector *)x2);
5962 cpl_vector_unwrap((cpl_vector *)y2);
5964 cpl_msg_error(cpl_func,
"Error during polynomial fit, err[%s]", cpl_error_get_where());
5968 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5969 cpl_vector_unwrap((cpl_vector *)x2);
5970 cpl_vector_unwrap((cpl_vector *)y2);
5971 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5974 prestate = cpl_errorstate_get();
5975 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
5976 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5977 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
5979 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
5981 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
5982 DETMON_QC_CONAD_CORR_C));
5984 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
5986 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
5987 DETMON_QC_GAIN_CORR_C));
5993 cpl_vector_unwrap(x);
5994 cpl_vector_unwrap(y);
5995 cpl_polynomial_delete(poly_fit);
5996 cpl_polynomial_delete(poly_fit2);
5998 return cpl_error_get_code();
6007 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y)
6009 const double TOLERANCE = 1e-37;
6010 double xmin = cpl_vector_get_min(x);
6011 double xmax = cpl_vector_get_max(x);
6012 double ymin = cpl_vector_get_min(y);
6013 double ymax = cpl_vector_get_max(y);
6014 double ystdev = cpl_vector_get_stdev(y);
6015 double xstdev = cpl_vector_get_stdev(x);
6017 if (fabs(xmax-xmin) < TOLERANCE &&
6018 fabs(ymax - ymin) < TOLERANCE &&
6019 xstdev < TOLERANCE &&
6022 cpl_msg_warning(cpl_func,
"An empty frame has been detected, linearity, coeffs, gain, FPN values will not be computed.");
6037 static cpl_error_code
6038 detmon_lg_qc_med(
const cpl_table * gain_table,
6039 cpl_propertylist * qclist,
int rows_in_gain)
6043 cpl_vector *x = NULL;
6044 cpl_vector *y = NULL;
6045 int check_result = 0;
6047 if (rows_in_gain) {};
6049 x = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
6050 y = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
6051 check_result = detmon_lg_check_before_gain(x, y);
6054 cpl_vector_unwrap(x);
6058 cpl_vector_unwrap(y);
6060 if (0 == check_result)
6062 return CPL_ERROR_NONE;
6065 gain=cpl_table_get_column_median(gain_table,
"GAIN");
6067 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
6069 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
6072 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
6073 cpl_table_get_column_stdev
6074 (gain_table,
"GAIN")));
6075 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
6076 DETMON_QC_GAIN_MSE_C));
6078 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
6079 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
6080 DETMON_QC_CONAD_C));
6083 gain=cpl_table_get_column_median(gain_table,
"GAIN_CORR");
6085 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
6087 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
6088 DETMON_QC_GAIN_CORR_C));
6091 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
6092 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
6093 DETMON_QC_CONAD_CORR_C));
6098 return cpl_error_get_code();
6112 static cpl_error_code
6113 detmon_lg_rescale(cpl_imagelist * to_rescale)
6116 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 0),
6117 detmon_lg_config.llx,
6118 detmon_lg_config.lly,
6119 detmon_lg_config.urx,
6120 detmon_lg_config.ury);
6122 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 1),
6123 detmon_lg_config.llx,
6124 detmon_lg_config.lly,
6125 detmon_lg_config.urx,
6126 detmon_lg_config.ury);
6130 if(fabs(med1 / med2 - 1) > 0.001) {
6132 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
6135 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
6141 return cpl_error_get_code();
6144 static cpl_error_code
6145 detmon_pair_extract_next(
const cpl_frameset * set,
6149 cpl_frameset ** pair,
6153 double dit_next = -100;
6154 cpl_size* selection;
6155 int nsets_extracted = 0;
6156 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6157 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6158 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6159 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6161 nsets_extracted = cpl_frameset_get_size(set);
6162 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6163 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6166 dit = dit_array[*next_element ];
6168 if (*next_element < nsets_extracted - 1)
6170 dit_next = dit_array[*next_element + 1 ];
6174 selection[iindex[*next_element] ] = 1;
6175 if (fabs(dit - dit_next) < tolerance)
6178 selection[iindex[*next_element + 1] ] = 1;
6183 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);
6187 cpl_frameset_delete(*pair);
6188 *pair = cpl_frameset_extract(set, selection, 1);
6191 cpl_free(selection);
6192 return cpl_error_get_code();
6195 static cpl_error_code
6196 detmon_single_extract_next(
const cpl_frameset * set,
6200 cpl_frameset ** pair)
6202 cpl_size* selection;
6203 int nsets_extracted = 0;
6204 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6205 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6206 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6207 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6209 nsets_extracted = cpl_frameset_get_size(set);
6210 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6211 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6214 selection[iindex[*next_element] ] = 1;
6217 cpl_frameset_delete(*pair);
6218 *pair = cpl_frameset_extract(set, selection, 1);
6220 cpl_free(selection);
6221 return cpl_error_get_code();
6319 detmon_gain(
const cpl_imagelist * imlist_on,
6320 const cpl_imagelist * imlist_off,
6321 const cpl_vector * exptimes,
6322 const cpl_vector * ndit,
6332 cpl_propertylist * qclist,
6334 cpl_imagelist ** diff_imlist,
6335 cpl_imagelist ** autocorr_imlist)
6337 cpl_table * gain_table = NULL;
6338 cpl_imagelist * difflist = NULL;
6339 cpl_imagelist * autocorrlist = NULL;
6340 cpl_imagelist * c_onlist = NULL;
6341 cpl_imagelist * c_offlist = NULL;
6342 cpl_vector * diffdits = NULL;
6343 cpl_vector * diffndits = NULL;
6344 int rows_in_gain = 0;
6345 int ndiffdits, ndits;
6347 cpl_boolean opt_nir = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
6348 const char * method = mode & IRPLIB_GAIN_PTC ?
"PTC" :
"MED";
6350 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6351 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6352 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6353 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6356 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6357 skip_if(detmon_gain_table_create(gain_table, opt_nir));
6361 skip_if(detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,
6363 ndiffdits = cpl_vector_get_size(diffdits);
6365 ndits = cpl_vector_get_size(exptimes);
6368 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
6369 difflist = cpl_imagelist_new();
6370 autocorrlist = cpl_imagelist_new();
6373 if (mode & IRPLIB_GAIN_COLLAPSE) {
6374 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6375 c_offlist = cpl_imagelist_duplicate(imlist_off);
6376 skip_if(detmon_lg_rescale(c_offlist));
6378 c_offlist = (cpl_imagelist *) imlist_off;
6383 for (i = 0; i < ndiffdits; i++) {
6390 c_dit=cpl_vector_get(diffdits, i);
6393 c_ndit=(int)cpl_vector_get(diffndits, i);
6396 c_onlist = cpl_imagelist_new();
6399 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6400 c_offlist = cpl_imagelist_new();
6405 for(j = 0; j < ndits; j++) {
6406 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6416 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6417 const cpl_image * im =
6418 cpl_imagelist_get_const(imlist_on, j);
6419 im_on = cpl_image_duplicate(im);
6421 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6423 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6430 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6432 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6433 const cpl_image * im =
6434 cpl_imagelist_get_const(imlist_off, j);
6435 im_off = cpl_image_duplicate(im);
6438 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6440 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6447 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6448 skip_if (c_nons != c_noffs);
6451 skip_if (c_nons == 0 || c_nons % 2 != 0);
6454 if(mode & IRPLIB_GAIN_WITH_RESCALE) {
6455 skip_if(detmon_lg_rescale(c_onlist));
6456 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6457 skip_if(detmon_lg_rescale(c_offlist));
6463 int rows_affected = 1;
6464 skip_if(detmon_gain_table_fill_row(gain_table,
6468 c_offlist, kappa, nclip,
6470 xshift, yshift,1E10, 1E10, i,
6471 mode, &rows_affected));
6476 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6477 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6478 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6479 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6480 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6481 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6484 cpl_imagelist_unset(c_onlist, 0);
6486 cpl_imagelist_unset(c_onlist, 0);
6488 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6489 cpl_imagelist_unset(c_offlist, 0);
6491 cpl_imagelist_unset(c_offlist, 0);
6499 cpl_imagelist_delete(c_onlist);
6500 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6501 cpl_imagelist_delete(c_offlist);
6505 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
6506 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
6507 DETMON_QC_METHOD_C));
6510 if (mode & IRPLIB_GAIN_PTC) {
6511 skip_if(detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
6513 skip_if(detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
6516 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
6517 double autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
6518 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
6520 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
6521 DETMON_QC_AUTOCORR_C));
6524 if (diff_imlist != NULL) *diff_imlist = difflist;
6525 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
6529 cpl_vector_delete(diffdits);
6530 cpl_vector_delete(diffndits);
6535 static cpl_error_code
6536 detmon_gain_table_create(cpl_table * gain_table,
6537 const cpl_boolean opt_nir)
6539 if (opt_nir == NIR) {
6540 skip_if(cpl_table_new_column(gain_table,
"DIT", CPL_TYPE_DOUBLE));
6541 skip_if(cpl_table_new_column(gain_table,
"NDIT", CPL_TYPE_INT));
6543 skip_if(cpl_table_new_column(gain_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6545 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON1", CPL_TYPE_DOUBLE));
6546 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON2", CPL_TYPE_DOUBLE));
6547 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF1", CPL_TYPE_DOUBLE));
6548 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF2", CPL_TYPE_DOUBLE));
6549 skip_if(cpl_table_new_column(gain_table,
"SIG_ON_DIF", CPL_TYPE_DOUBLE));
6550 skip_if(cpl_table_new_column(gain_table,
"SIG_OFF_DIF", CPL_TYPE_DOUBLE));
6551 skip_if(cpl_table_new_column(gain_table,
"GAIN", CPL_TYPE_DOUBLE));
6552 skip_if(cpl_table_new_column(gain_table,
"AUTOCORR", CPL_TYPE_DOUBLE));
6553 skip_if(cpl_table_new_column(gain_table,
"GAIN_CORR", CPL_TYPE_DOUBLE));
6554 skip_if(cpl_table_new_column(gain_table,
"ADU", CPL_TYPE_DOUBLE));
6555 skip_if(cpl_table_new_column(gain_table,
"X_FIT", CPL_TYPE_DOUBLE));
6556 skip_if(cpl_table_new_column(gain_table,
"X_FIT_CORR", CPL_TYPE_DOUBLE));
6557 skip_if(cpl_table_new_column(gain_table,
"Y_FIT", CPL_TYPE_DOUBLE));
6558 skip_if(cpl_table_new_column(gain_table,
"Y_FIT_CORR", CPL_TYPE_DOUBLE));
6559 skip_if(cpl_table_new_column(gain_table,
"FLAG", CPL_TYPE_INT));
6563 return cpl_error_get_code();
6566 static cpl_error_code
6567 detmon_lin_table_create(cpl_table * lin_table,
6568 const cpl_boolean opt_nir)
6570 if (opt_nir == NIR) {
6571 skip_if(cpl_table_new_column(lin_table,
"DIT", CPL_TYPE_DOUBLE));
6573 skip_if(cpl_table_new_column(lin_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6575 skip_if(cpl_table_new_column(lin_table,
"MED", CPL_TYPE_DOUBLE));
6576 skip_if(cpl_table_new_column(lin_table,
"MEAN", CPL_TYPE_DOUBLE));
6577 skip_if(cpl_table_new_column(lin_table,
"MED_DIT", CPL_TYPE_DOUBLE));
6578 skip_if(cpl_table_new_column(lin_table,
"MEAN_DIT", CPL_TYPE_DOUBLE));
6579 skip_if(cpl_table_new_column(lin_table,
"ADL", CPL_TYPE_DOUBLE));
6582 return cpl_error_get_code();
6586 detmon_lg_find_dits(
const cpl_vector * exptimes,
6589 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6595 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
6599 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
6601 for (j = 0; j < ndits; j++) {
6602 if (fabs(cpl_vector_get(exptimes, i) -
6603 cpl_vector_get(dits, j)) > tolerance)
6606 if(ndiffs == ndits) {
6607 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
6612 cpl_vector_set_size(dits, ndits);
6620 static cpl_error_code
6621 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
6622 const cpl_vector * vec_ndits,
6624 cpl_vector** diff_dits,
6625 cpl_vector** diff_ndits)
6633 * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6634 * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
6637 cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
6638 cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
6641 size=cpl_vector_get_size(exptimes);
6643 for(i = 1; i < size; i++) {
6645 for (j = 0; j < ndits; j++) {
6646 if (fabs(cpl_vector_get(exptimes, i) -
6647 cpl_vector_get(*diff_dits,j)) > tolerance)
6650 if(ndiffs == ndits) {
6651 cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
6652 cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
6657 cpl_vector_set_size(*diff_dits, ndits);
6658 cpl_vector_set_size(*diff_ndits, ndits);
6661 return cpl_error_get_code();
6751 detmon_lin(
const cpl_imagelist * imlist_on,
6752 const cpl_imagelist * imlist_off,
6753 const cpl_vector * exptimes,
6763 cpl_propertylist * qclist,
6765 cpl_imagelist ** coeffs_cube,
6768 cpl_table * lin_table = NULL;
6769 cpl_imagelist * c_onlist = NULL;
6770 cpl_imagelist * c_offlist = NULL;
6771 cpl_vector * diffdits = NULL;
6772 cpl_imagelist * lin_inputs = NULL;
6773 cpl_polynomial * poly_linfit = NULL;
6774 cpl_image * fiterror = NULL;
6775 cpl_vector * vcoeffs = NULL;
6776 double * pcoeffs = NULL;
6777 int ndiffdits, ndits;
6779 cpl_boolean opt_nir = mode & IRPLIB_LIN_OPT ? OPT : NIR;
6780 const cpl_vector *x = NULL;
6781 const cpl_vector *y = NULL;
6783 const cpl_image * first = NULL;
6791 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6792 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6793 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6794 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6795 cpl_ensure(order > 0 , CPL_ERROR_ILLEGAL_INPUT, NULL);
6797 vcoeffs = cpl_vector_new(order + 1);
6798 pcoeffs = cpl_vector_get_data(vcoeffs);
6801 if (mode & IRPLIB_LIN_PIX2PIX) {
6802 cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
6803 cpl_ensure(bpm != NULL, CPL_ERROR_NULL_INPUT, NULL);
6804 lin_inputs = cpl_imagelist_new();
6808 lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6809 skip_if(detmon_lin_table_create(lin_table, opt_nir));
6813 diffdits = detmon_lg_find_dits(exptimes, tolerance);
6814 ndiffdits = cpl_vector_get_size(diffdits);
6816 ndits = cpl_vector_get_size(exptimes);
6846 if (mode & IRPLIB_LIN_COLLAPSE) {
6851 cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
6852 skip_if(collapse == NULL);
6854 c_offlist = cpl_imagelist_new();
6855 skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
6859 for (i = 0; i < ndiffdits; i++) {
6863 double c_dit = cpl_vector_get(diffdits, i);
6865 c_onlist = cpl_imagelist_new();
6868 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6869 c_offlist = cpl_imagelist_new();
6873 for(j = 0; j < ndits; j++) {
6874 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6884 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6885 const cpl_image * im =
6886 cpl_imagelist_get_const(imlist_on, j);
6887 im_on = cpl_image_duplicate(im);
6889 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6891 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6898 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6900 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6901 const cpl_image * im =
6902 cpl_imagelist_get_const(imlist_off, j);
6903 im_off = cpl_image_duplicate(im);
6906 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6908 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6915 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6916 skip_if (c_nons != c_noffs);
6919 skip_if (c_nons == 0 || c_nons % 2 != 0);
6922 if(mode & IRPLIB_LIN_WITH_RESCALE) {
6923 skip_if(detmon_lg_rescale(c_onlist));
6924 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6925 skip_if(detmon_lg_rescale(c_offlist));
6932 skip_if(detmon_lin_table_fill_row(lin_table, c_dit,
6934 c_onlist, c_offlist,
6938 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6939 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6940 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6941 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6942 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6943 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6946 cpl_imagelist_unset(c_onlist, 0);
6948 cpl_imagelist_unset(c_onlist, 0);
6950 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6951 cpl_imagelist_unset(c_offlist, 0);
6953 cpl_imagelist_unset(c_offlist, 0);
6961 cpl_imagelist_delete(c_onlist);
6962 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6963 cpl_imagelist_delete(c_offlist);
6967 skip_if(detmon_add_adl_column(lin_table, opt_nir));
6969 if(!(mode & IRPLIB_LIN_PIX2PIX)) {
6972 y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6973 (
double *)cpl_table_get_data_double_const(lin_table,
6975 if (opt_nir == NIR) {
6976 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6977 (
double *)cpl_table_get_data_double_const(lin_table,
"DIT"));
6979 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6980 (
double *)cpl_table_get_data_double_const(lin_table,
"EXPTIME"));
6982 if(x == NULL || y == NULL) {
6983 cpl_vector_unwrap((cpl_vector *)x);
6984 cpl_vector_unwrap((cpl_vector *)y);
6994 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
6995 poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
6997 if(order == cpl_vector_get_size(x) - 1) {
6998 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7002 if(poly_linfit == NULL) {
7003 cpl_vector_unwrap((cpl_vector *)x);
7004 cpl_vector_unwrap((cpl_vector *)y);
7009 cpl_vector_unwrap((cpl_vector *)x);
7010 cpl_vector_unwrap((cpl_vector *)y);
7012 for(deg = 0; deg <= order; deg++) {
7013 const double coeff =
7014 cpl_polynomial_get_coeff(poly_linfit, °);
7016 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
7017 assert(name_o != NULL);
7018 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
7019 skip_if(cpl_propertylist_set_comment(qclist,name_o,
7020 DETMON_QC_LIN_COEF_C));
7022 pcoeffs[deg] = coeff;
7024 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
7025 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7026 DETMON_QC_ERRFIT_MSE_C));
7030 if (opt_nir == NIR) {
7031 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7032 (
double *)cpl_table_get_data_double_const(lin_table,
7035 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7036 (
double *)cpl_table_get_data_double_const(lin_table,
7041 first = cpl_imagelist_get_const(lin_inputs, 0);
7042 sizex = cpl_image_get_size_x(first);
7043 sizey = cpl_image_get_size_y(first);
7045 vsize = cpl_vector_get_size(x);
7047 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
7050 cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
7051 order, FALSE, CPL_TYPE_FLOAT,
7054 cpl_vector_unwrap((cpl_vector*)x);
7055 irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
7056 "Failed polynomial fit");
7058 for(i = 0; i <= order; i++) {
7059 cpl_image *image = cpl_imagelist_get(*coeffs_cube, i);
7060 const double coeff = cpl_image_get_median(image);
7061 char * name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", i);
7062 char * name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", i);
7064 assert(name_o1 != NULL);
7065 assert(name_o2 != NULL);
7066 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
7067 skip_if(cpl_propertylist_set_comment(qclist,name_o1,
7068 DETMON_QC_LIN_COEF_C));
7071 skip_if(cpl_propertylist_append_double(qclist, name_o2,
7072 cpl_image_get_stdev(image)));
7073 skip_if(cpl_propertylist_set_comment(qclist,name_o2,
7074 DETMON_QC_LIN_COEF_ERR_C));
7079 if(order == vsize - 1) {
7080 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7081 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7083 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7084 DETMON_QC_ERRFIT_C));
7088 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7089 cpl_image_get_median(fiterror)));
7090 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7091 DETMON_QC_ERRFIT_C));
7096 skip_if(detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
7098 if(mode & IRPLIB_LIN_PIX2PIX) {
7100 *bpm = detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
7101 skip_if(*bpm == NULL);
7102 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
7104 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
7105 DETMON_QC_NUM_BPM_C));
7110 cpl_vector_delete(diffdits);
7111 cpl_polynomial_delete(poly_linfit);
7112 cpl_imagelist_delete(lin_inputs);
7113 cpl_vector_delete(vcoeffs);
7114 cpl_image_delete(fiterror);
7145 static cpl_error_code
7146 detmon_lin_table_fill_row(cpl_table * lin_table,
double c_dit,
7147 cpl_imagelist * linearity_inputs,
7148 const cpl_imagelist * ons,
7149 const cpl_imagelist * offs,
7158 cpl_image * extracted=NULL;
7160 cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
7161 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
7162 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
7164 if (mode & IRPLIB_LIN_PIX2PIX) {
7165 cpl_msg_debug(cpl_func,
"checking linearity inputs");
7166 cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
7170 if (mode & IRPLIB_LIN_NIR) {
7171 cpl_table_set(lin_table,
"DIT", pos, c_dit);
7172 }
else if (mode & IRPLIB_LIN_OPT) {
7173 cpl_table_set(lin_table,
"EXPTIME", pos, c_dit);
7175 cpl_msg_error(cpl_func,
"Mandatory mode not given");
7179 const cpl_image * off2;
7180 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
7181 off2 = cpl_imagelist_get_const(offs, 0);
7183 off2 = cpl_imagelist_get_const(offs, 1);
7185 extracted = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
7186 cpl_imagelist_get_const(offs, 0),
7187 cpl_imagelist_get_const(ons, 1),
7189 llx, lly, urx, ury);
7190 cpl_ensure_code(extracted != NULL, cpl_error_get_code());
7194 double median = cpl_image_get_median(extracted);
7195 double mean= cpl_image_get_mean(extracted);
7196 cpl_table_set(lin_table,
"MED", pos, median);
7197 cpl_table_set(lin_table,
"MEAN", pos, mean);
7199 cpl_table_set(lin_table,
"MED_DIT", pos, median / c_dit);
7200 cpl_table_set(lin_table,
"MEAN_DIT", pos, mean / c_dit);
7204 if(mode & IRPLIB_LIN_PIX2PIX) {
7205 cpl_error_code error = cpl_imagelist_set(linearity_inputs, extracted,
7207 cpl_ensure_code(!error, error);
7209 cpl_image_delete(extracted);
7212 return cpl_error_get_code();
7215 static double irplib_calculate_total_noise_smooth(
const cpl_image* pimage,
7216 int pattern_x,
int pattern_y)
7218 cpl_image * p_tmp_image = 0;
7219 cpl_image * psmooth_image = 0;
7221 cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
7223 p_tmp_image = cpl_image_duplicate(pimage);
7224 cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
7225 cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
7226 psmooth_image = cpl_image_divide_create(pimage,p_tmp_image);
7227 ret_noise = irplib_calculate_total_noise(psmooth_image);
7228 cpl_mask_delete(mask);
7229 cpl_image_delete(psmooth_image);
7230 cpl_image_delete(p_tmp_image);
7234 static double irplib_calculate_total_noise(
const cpl_image* pimage)
7236 double total_noise = -1;
7237 unsigned long max_bin_size = 1E5;
7238 const double hstart = cpl_image_get_min(pimage);
7239 const double hrange = cpl_image_get_max(pimage) - hstart;
7240 const unsigned long nbins = max_bin_size;
7241 cpl_error_code err = CPL_ERROR_NONE;
7243 irplib_hist * phist = 0;
7244 phist = irplib_hist_new();
7247 irplib_hist_init(phist, nbins, hstart, hrange);
7248 err = irplib_hist_fill(phist, pimage);
7249 if (err == CPL_ERROR_NONE)
7257 unsigned long n_bins = irplib_hist_get_nbins(phist);
7258 double start = irplib_hist_get_start(phist);
7259 double bin_size = irplib_hist_get_bin_size(phist);
7260 cpl_vector* pdata_vector = cpl_vector_new(n_bins);
7261 cpl_vector* ppos_vector = cpl_vector_new(n_bins);
7262 cpl_table* ptable = cpl_table_new(n_bins);
7263 cpl_table_new_column(ptable,
"bin", CPL_TYPE_DOUBLE);
7264 cpl_table_new_column(ptable,
"value", CPL_TYPE_DOUBLE);
7265 for(i = 0; i < n_bins; i++)
7267 unsigned int value = irplib_hist_get_value(phist, i);
7268 double dvalue = (double)(value);
7269 cpl_vector_set(pdata_vector, i, dvalue);
7270 cpl_vector_set(ppos_vector, i, start + i * bin_size);
7272 cpl_table_set(ptable,
"bin", i, start + i * bin_size);
7273 cpl_table_set(ptable,
"value", i, dvalue);
7275 err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
7276 if (err == CPL_ERROR_NONE)
7278 cpl_msg_info(cpl_func,
"FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
7282 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed Gaussian Fit, err msg [%s]", cpl_error_get_message());
7285 cpl_table_delete(ptable);
7286 cpl_vector_delete(ppos_vector);
7287 cpl_vector_delete(pdata_vector);
7291 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
7294 irplib_hist_delete(phist);
7299 static double irplib_compute_err(
double gain,
double ron,
double FA)
7301 double int_gain = (gain * gain - 1) / 12;
7306 return sqrt(ron * ron + FA / gain + int_gain);
7309 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain ,
7310 FPN_METHOD fpn_method,
int smooth_size,
double* mse)
7312 cpl_image* im_diff = 0;
7313 const cpl_image* im_f1 = f1;
7314 cpl_image* im_inrange1 = 0;
7323 cpl_msg_warning(cpl_func,
"gain[%f]<0", gain);
7324 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7331 im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
7332 im_f1 = im_inrange1;
7334 FA = cpl_image_get_median(im_f1);
7341 cpl_msg_info(cpl_func,
"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
7342 s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
7345 cpl_msg_info(cpl_func,
"HISTOGRAM method is used for FPN");
7346 s_tot = irplib_calculate_total_noise(im_f1);
7351 cpl_msg_warning(cpl_func,
"fpn_method is not defined");
7360 cpl_msg_warning(cpl_func,
"Median flux on sum of flats<0");
7361 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7366 if ((s_tot * s_tot - FA / gain) > 0)
7368 s_fpn = sqrt(s_tot * s_tot - FA / gain);
7369 sr_fpn = s_fpn / FA;
7370 *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
7374 cpl_msg_warning(cpl_func,
"s_tot * s_tot < FA / gain");
7375 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7384 cpl_image_delete(im_diff);
7387 cpl_image_delete(im_inrange1);
7393 static cpl_imagelist * irplib_load_fset_wrp(
const cpl_frameset * pframeset,
7394 cpl_type type ,
int whichext)
7398 return detmon_load_frameset_window(pframeset, type, 0, whichext,
7399 detmon_lg_config.llx,
7400 detmon_lg_config.lly,
7401 detmon_lg_config.urx,
7402 detmon_lg_config.ury,
7403 detmon_lg_config.nx,
7404 detmon_lg_config.ny);
7407 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset * pframeset,
7408 cpl_type type ,
int whichext)
7411 cpl_imagelist* offs = cpl_imagelist_new();
7412 detmon_lg_config.load_fset(pframeset, type, offs);
7417 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
7418 cpl_propertylist* plist)
7420 if (ptable && plist)
7422 int size = cpl_propertylist_get_size(plist);
7424 for (i = 0; i < size; i++)
7426 cpl_property* pprop = cpl_propertylist_get(plist,i);
7429 const char* pname = cpl_property_get_name(pprop);
7432 cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
7433 if (cpl_error_get_code() != CPL_ERROR_NONE)
7435 cpl_msg_warning(cpl_func,
"cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
7442 return cpl_error_get_code();
7445 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
7446 cpl_propertylist* plist,
int row)
7448 cpl_error_code err = CPL_ERROR_NONE;
7449 if (ptable && plist)
7451 int size = cpl_propertylist_get_size(plist);
7453 for (i = 0; i < size; i++)
7455 cpl_property* pprop = cpl_propertylist_get(plist,i);
7458 const char* pname = cpl_property_get_name(pprop);
7459 double value = cpl_property_get_double(pprop);
7462 cpl_table_set_double(ptable, pname, row, value);
7463 if (cpl_error_get_code() != CPL_ERROR_NONE)
7465 cpl_msg_warning(cpl_func,
"cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
7476 cpl_error_code detmon_check_order(
const double *exptime,
int sz,
7477 double tolerance,
int order)
7494 }
while(fabs(exptime[i-1] - exptime[i]) < tolerance);
7495 }
while(i < sz - 1);
7497 if (!fabs(exptime[i-1] - exptime[i]) < tolerance) nsets++;
7500 cpl_error_set_message(cpl_func,CPL_ERROR_INCOMPATIBLE_INPUT,
7501 "Not enough frames for the polynomial"
7502 " fitting. nsets = %d <= %d order",
7505 return cpl_error_get_code();
7508 static cpl_error_code
7509 detmon_lg_dfs_save_imagelist(
7510 cpl_frameset * frameset,
7511 const cpl_parameterlist * parlist,
7512 const cpl_frameset *usedframes,
7513 const cpl_imagelist *coeffs,
7514 const char *recipe_name,
7515 const cpl_propertylist *mypro_coeffscube,
7516 const char * package,
7517 const char * name_o)
7519 return(cpl_dfs_save_imagelist
7520 (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
7521 recipe_name, mypro_coeffscube, NULL, package,
7525 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos)
7527 const cpl_image* first = cpl_imagelist_get(imlist, 0);
7530 int x = cpl_image_get_size_x(first);
7531 int y = cpl_image_get_size_y(first);
7532 cpl_type type = cpl_image_get_type(first);
7533 cpl_image * blank = cpl_image_new(x, y, type);
7534 cpl_imagelist_set(imlist, blank, pos);
7540 detmon_lg_set_tag(cpl_frameset* set,
const char** tag_on,
const char** tag_off)
7545 ntag_old=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_OLD);
7546 ntag_new=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_NEW);
7548 *tag_on=DETMON_LG_ON_RAW_OLD;
7549 *tag_off=DETMON_LG_OFF_RAW_OLD;
7550 }
else if (ntag_new) {
7551 *tag_on=DETMON_LG_ON_RAW_NEW;
7552 *tag_off=DETMON_LG_OFF_RAW_NEW;
7554 cpl_msg_error(cpl_func,
"Provide %s and %s (or %s and %s) input frames",
7555 DETMON_LG_ON_RAW_NEW,DETMON_LG_OFF_RAW_NEW,
7556 DETMON_LG_ON_RAW_OLD,DETMON_LG_OFF_RAW_OLD);
7560 return cpl_error_get_code();