44#include "detmon_utils.h"
45#include "detmon_lg_impl.h"
47#include "irplib_ksigma_clip.h"
48#include "irplib_utils.h"
49#include "irplib_hist.h"
74typedef 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;
149detmon_lg_retrieve_parlist(
const char *,
150 const char *,
const cpl_parameterlist *,
155detmon_lg_split_onoff(
const cpl_frameset *,
158 const char *,
const char * );
161detmon_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);
185detmon_lin_table_fill_row(cpl_table *,
double,
187 const cpl_imagelist *,
188 const cpl_imagelist *,
195detmon_gain_table_fill_row(cpl_table * gain_table,
196 double c_dit,
int c_ndit,
197 cpl_imagelist * autocorr_images,
198 cpl_imagelist * diff_flats,
199 const cpl_imagelist * ons,
200 const cpl_imagelist * offs,
201 double kappa,
int nclip,
202 int llx,
int lly,
int urx,
int ury,
204 double gain_threshold,
205 int pos,
unsigned mode,
int* rows_affected);
209detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
210 cpl_imagelist * diff_flats,
211 const cpl_imagelist * ons,
212 double kappa,
int nclip,
213 int llx,
int lly,
int urx,
int ury,
214 double saturation_limit,
215 const int pos,
unsigned mode,
216 int* rows_linear_affected);
219detmon_lg_save(
const cpl_parameterlist *,
224 const cpl_propertylist *,
225 const cpl_propertylist *,
226 const cpl_propertylist *,
227 const cpl_propertylist *,
228 const cpl_propertylist *,
229 const cpl_propertylist *,
241 const int,
const int,
const cpl_frameset *,
245detmon_lg_qc_ptc(
const cpl_table *,
246 cpl_propertylist *,
unsigned,
int);
249detmon_lg_qc_med(
const cpl_table *,
250 cpl_propertylist *,
int);
254detmon_pfits_get_dit(
const cpl_propertylist *);
257detmon_pfits_get_dit_opt(
const cpl_propertylist *);
259irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
260 const char* prop_name);
262static cpl_image * detmon_bpixs(
const cpl_imagelist *,
263 cpl_boolean,
const double,
int *);
266detmon_autocorr_factor(
const cpl_image *,
267 cpl_image **,
int,
int);
272detmon_opt_contamination(
const cpl_imagelist *,
273 const cpl_imagelist *,
274 unsigned mode, cpl_propertylist *);
277detmon_opt_lampcr(cpl_frameset *,
int);
281detmon_lg_dfs_set_groups(cpl_frameset *,
const char *,
const char *);
284detmon_lg_reduce_all(
const cpl_table *,
291 const cpl_imagelist *,
292 const cpl_table *,
int, cpl_boolean);
295detmon_lg_check_defaults(
const cpl_image *);
298detmon_lg_rescale(cpl_imagelist *);
301detmon_lg_reduce_init(cpl_table *,
308detmon_add_adl_column(cpl_table *, cpl_boolean);
311detmon_lg_lamp_stab(
const cpl_frameset *,
312 const cpl_frameset *,
317detmon_lg_reduce_dit(
const cpl_frameset * set_on,
318 int* index_on,
double* exptime_on,
321 const cpl_frameset * set_off,
322 int * index_off,
double* exptime_off,
323 int* next_on,
int* next_off,
324 cpl_table * linear_table,
325 cpl_table * gain_table,
326 cpl_imagelist * linearity_inputs,
327 cpl_propertylist * qclist,
329 cpl_imagelist * autocorr_images,
330 cpl_imagelist * diff_flats,
331 cpl_imagelist * opt_offs,
333 int * rows_linear_affected,
334 int * rows_gain_affected);
337detmon_lg_core(cpl_frameset * cur_fset_on,
338 cpl_frameset * cur_fset_off,
342 double * exptime_off,
345 const char * recipe_name,
346 const char * pipeline_name,
347 const char * pafregexp,
348 const cpl_propertylist * pro_lintbl,
349 const cpl_propertylist * pro_gaintbl,
350 const cpl_propertylist * pro_coeffscube,
351 const cpl_propertylist * pro_bpm,
352 const cpl_propertylist * pro_corr,
353 const cpl_propertylist * pro_diff,
354 const char * package,
355 int (* load_fset) (
const cpl_frameset *,
358 int nsets, cpl_boolean opt_nir,
359 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
360 cpl_frameset * cur_fset);
363detmon_lg_lineff(
double *, cpl_propertylist *,
int,
int);
371detmon_gain_table_create(cpl_table *,
376detmon_lin_table_create(cpl_table *,
380detmon_lg_find_dits(
const cpl_vector *,
384detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
385 const cpl_vector * vec_ndits,
387 cpl_vector** diff_dits,
388 cpl_vector** diff_ndits);
391detmon_fpn_compute(
const cpl_frameset *set_on,
393 int last_linear_best,
394 cpl_propertylist *lint_qclist,
401 FPN_METHOD fpn_method,
403static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain,
404 FPN_METHOD fpn_method,
int,
double* mse);
405static double irplib_calculate_total_noise(
const cpl_image* pimage);
407static cpl_imagelist* irplib_load_fset_wrp(
const cpl_frameset *,
408 cpl_type,
int whichext);
409static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset *,
412static cpl_error_code irplib_table_create_column(cpl_table* ptable,
413 cpl_propertylist* plist);
414static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
415 cpl_propertylist* plist,
419detmon_pair_extract_next(
const cpl_frameset * set,
425 cpl_frameset ** pair,
428detmon_single_extract_next(
const cpl_frameset * set,
432 cpl_frameset ** pair);
439static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code);
440static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos);
441static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y);
450static int irplib_pfits_get_ndit(
const cpl_propertylist * plist)
452 return cpl_propertylist_get_int(plist,
"ESO DET NDIT");
495#ifdef DETMON_USE_DETECTOR_SHOTNOISE_MODEL
519hdrldemo_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
520 const double ron, cpl_image ** ima_errs)
522 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
523 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
524 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
525 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
527 *ima_errs = cpl_image_duplicate(ima_data);
529 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
533 cpl_image_divide_scalar(*ima_errs, gain);
534 cpl_image_add_scalar(*ima_errs, ron * ron);
535 cpl_image_power(*ima_errs, 0.5);
537 return cpl_error_get_code();
542detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
545 const char * tag_off,
546 const char * recipe_name,
547 const char * pipeline_name,
548 const char * pafregexp,
549 const cpl_propertylist * pro_lintbl,
550 const cpl_propertylist * pro_gaintbl,
551 const cpl_propertylist * pro_coeffscube,
552 const cpl_propertylist * pro_bpm,
553 const cpl_propertylist * pro_corr,
554 const cpl_propertylist * pro_diff,
555 const char * package,
557 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
558 const cpl_boolean opt_nir,
559 const cpl_parameterlist * parlist,
562static double irplib_compute_err(
double gain,
double ron,
double photon_noise);
565detmon_lg_dfs_save_imagelist(cpl_frameset * frameset,
566 const cpl_parameterlist * parlist,
567 const cpl_frameset *usedframes,
568 const cpl_imagelist *coeffs,
569 const char *recipe_name,
570 const cpl_propertylist *mypro_coeffscube,
571 const char * package,
572 const char * name_o);
575static void irplib_free(
char** pointer){
577 if(pointer && *pointer) {
584detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
int nsets,
586 const char * tag_off,
587 const char * recipe_name,
588 const char * pipeline_name,
589 const char * pafregexp,
590 const cpl_propertylist * pro_lintbl,
591 const cpl_propertylist * pro_gaintbl,
592 const cpl_propertylist * pro_coeffscube,
593 const cpl_propertylist * pro_bpm,
594 const cpl_propertylist * pro_corr,
595 const cpl_propertylist * pro_diff,
596 const char * package,
598 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
599 const cpl_boolean opt_nir,
600 const cpl_parameterlist * parlist,
605 int nexts = detmon_lg_config.nb_extensions;
607 double* exptime_on = 0;
608 double* exptime_off = 0;
611 cpl_frameset * cur_fset = NULL;
612 cpl_frameset* cur_fset_on = 0;
613 cpl_frameset* cur_fset_off = 0;
618 cpl_frameset_duplicate(frameset) : cpl_frameset_extract(frameset, selection, i);
621 skip_if(cur_fset == NULL);
624 cur_fset_on = cpl_frameset_new();
625 cur_fset_off = cpl_frameset_new();
626 cpl_msg_info(cpl_func,
"Splitting into ON and OFF sub-framesets");
627 skip_if (detmon_lg_split_onoff(cur_fset,
628 cur_fset_on, cur_fset_off,
630 if (cpl_frameset_get_size(cur_fset_on) == 0)
632 cpl_msg_error(cpl_func,
"No lamp frames in input");
636 if (cpl_frameset_get_size(cur_fset_off) == 0)
638 cpl_msg_error(cpl_func,
"No dark / bias frames in input");
641 cpl_msg_info(cpl_func,
"found on-frames[%" CPL_SIZE_FORMAT
"] off-frames[%" CPL_SIZE_FORMAT
"]",cpl_frameset_get_size(cur_fset_on), cpl_frameset_get_size(cur_fset_off));
649 exptime_on = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_on));
650 exptime_off = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_off));
652 index_on = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_on));
653 index_off = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_off));
654 irplib_frameset_sort(cur_fset_on, index_on, exptime_on);
655 irplib_frameset_sort(cur_fset_off, index_off, exptime_off);
668 skip_if(detmon_check_order(exptime_on, cpl_frameset_get_size(cur_fset_on), detmon_lg_config.tolerance, detmon_lg_config.order));
670 if(detmon_lg_config.exts >= 0)
678 if (detmon_lg_config.lamp_ok) {
679 skip_if(detmon_opt_lampcr(cur_fset, 0));
682 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
687 detmon_lg_config.exts,
689 recipe_name, pipeline_name, pafregexp,
690 pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff,
691 package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
693 for(j = 1; j <= nexts; j++) {
700 if (detmon_lg_config.lamp_ok) {
701 skip_if(detmon_opt_lampcr(cur_fset, j));
705 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
711 pipeline_name, pafregexp,
712 pro_lintbl, pro_gaintbl,
714 pro_bpm, pro_corr, pro_diff,
715 package, load_fset, nsets, opt_nir,
716 frameset, parlist, cur_fset));
724 char* par_name = NULL ;
725 if (strcmp(recipe_name,
"detmon_opt_lg") == 0 ||
726 strcmp(recipe_name,
"detmon_ir_lg") == 0) {
727 cpl_msg_info(cpl_func,
"This is where I want to write the 'super' QC kw");
728 cpl_msg_info(cpl_func,
"Writing super QC kw for recipe %s", recipe_name);
738 detmon_lg_qc_params_global_gain(recipe_name, nsets);
739 detmon_lg_qc_params_global_lin(recipe_name, nsets);
741 par_name = cpl_sprintf(
"detmon.%s.pix2pix", recipe_name);
742 cpl_parameter* pix2pix = cpl_parameterlist_find(
745 if (pix2pix != NULL && cpl_parameter_get_bool(pix2pix)) {
754 detmon_lg_qc_params_global_bpm(recipe_name, nsets);
755 detmon_lg_qc_params_global_coeffs(recipe_name, nsets);
760 cpl_frameset_delete(cur_fset);
761 cpl_frameset_delete(cur_fset_on);
762 cpl_frameset_delete(cur_fset_off);
765 cpl_free(exptime_on);
766 cpl_free(exptime_off);
767 return cpl_error_get_code();
845detmon_lg(cpl_frameset * frameset,
846 const cpl_parameterlist * parlist,
848 const char * tag_off,
849 const char * recipe_name,
850 const char * pipeline_name,
851 const char * pafregexp,
852 const cpl_propertylist * pro_lintbl,
853 const cpl_propertylist * pro_gaintbl,
854 const cpl_propertylist * pro_coeffscube,
855 const cpl_propertylist * pro_bpm,
856 const cpl_propertylist * pro_corr,
857 const cpl_propertylist * pro_diff,
858 const char * package,
859 int (* compare) (
const cpl_frame *,
861 int (* load_fset) (
const cpl_frameset *,
864 const cpl_boolean opt_nir)
866 cpl_errorstate cleanstate = cpl_errorstate_get();
868 cpl_size * selection = NULL;
869 cpl_frame * first = NULL;
870 cpl_image * reference = NULL;
877 cpl_frameset * cur_fset = NULL;
878 cpl_frameset * cur_fset_on = NULL;
879 cpl_frameset * cur_fset_off = NULL;
882 cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
883 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
884 cpl_ensure_code(tag_on != NULL, CPL_ERROR_NULL_INPUT);
885 cpl_ensure_code(tag_off != NULL, CPL_ERROR_NULL_INPUT);
886 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
887 cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
888 cpl_ensure_code(pro_lintbl != NULL, CPL_ERROR_NULL_INPUT);
889 cpl_ensure_code(pro_gaintbl != NULL, CPL_ERROR_NULL_INPUT);
890 cpl_ensure_code(pro_coeffscube != NULL, CPL_ERROR_NULL_INPUT);
891 cpl_ensure_code(pro_bpm != NULL, CPL_ERROR_NULL_INPUT);
892 cpl_ensure_code(pro_corr != NULL, CPL_ERROR_NULL_INPUT);
893 cpl_ensure_code(pro_diff != NULL, CPL_ERROR_NULL_INPUT);
894 cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
896 cpl_msg_info(cpl_func,
"frameset size [%" CPL_SIZE_FORMAT
"]", cpl_frameset_get_size(frameset));
899 skip_if (detmon_lg_dfs_set_groups(frameset, tag_on, tag_off));
906 skip_if (detmon_lg_retrieve_parlist(pipeline_name, recipe_name,
914 first = cpl_frameset_get_position(frameset, 0);
915 irplib_ensure (first != NULL, CPL_ERROR_ILLEGAL_INPUT,
"Empty data set! Provide %s and %s input frames",tag_on,tag_off);
917 detmon_lg_config.load_fset = load_fset;
918 detmon_lg_config.load_fset_wrp = load_fset ? irplib_load_fset_wrp_ext : irplib_load_fset_wrp;
921 detmon_lg_config.nb_extensions = 1;
922 if (detmon_lg_config.exts < 0) {
924 detmon_lg_config.nb_extensions = cpl_frame_get_nextensions(first);
925 while (reference == NULL && i <= detmon_lg_config.nb_extensions) {
926 reference = cpl_image_load(cpl_frame_get_filename(first),
927 CPL_TYPE_FLOAT, 0, i);
928 if (reference == NULL) {
929 cpl_msg_warning(cpl_func,
"Extension %d empty, skipping", i);
930 cpl_errorstate_set(cleanstate);
934 cpl_errorstate_set(cleanstate);
935 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
936 "No data found in any extension");
937 cpl_msg_info(cpl_func,
"Using extension %d as reference", i - 1);
939 if (load_fset != NULL) {
940 cpl_frameset *
new = cpl_frameset_new();
941 cpl_imagelist * p = cpl_imagelist_new();
942 cpl_frameset_insert(
new, cpl_frame_duplicate(first));
943 (*load_fset)(
new, CPL_TYPE_FLOAT, p);
944 reference = cpl_image_duplicate(cpl_imagelist_get(p, 0));
945 cpl_imagelist_delete(p);
946 cpl_frameset_delete(
new);
948 cpl_msg_info(cpl_func,
"name=%s",cpl_frame_get_filename(first));
949 reference = cpl_image_load(cpl_frame_get_filename(first),
950 CPL_TYPE_FLOAT, 0, detmon_lg_config.exts);
952 cpl_errorstate_set(cleanstate);
953 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
954 "No data found in requested extension %d",
955 detmon_lg_config.exts);
957 skip_if (reference == NULL);
959 skip_if (detmon_lg_check_defaults(reference));
968 if (compare == NULL) {
971 cpl_msg_info(cpl_func,
"Identifying different settings");
972 selection = cpl_frameset_labelise(frameset, compare, &nsets);
973 skip_if (selection == NULL);
977 for(
int i = 0; i < nsets; i++)
979 int fr_size = cpl_frameset_get_size(frameset);
981 cpl_msg_info(cpl_func,
"Reduce data set nb %d out of %" CPL_SIZE_FORMAT
"",
983 skip_if(detmon_lg_reduce_set(i, frameset, nsets, tag_on, tag_off,
998 fr_size_new = cpl_frameset_get_size(frameset);
1004 if (fr_size_new > fr_size)
1006 selection = cpl_realloc(selection, fr_size_new *
sizeof(selection[0]));
1007 memset(selection + fr_size, -1, (fr_size_new - fr_size) *
sizeof(selection[0]));
1013 cpl_frameset_delete(cur_fset);
1014 cpl_frameset_delete(cur_fset_on);
1015 cpl_frameset_delete(cur_fset_off);
1016 cpl_free(selection);
1017 cpl_image_delete(reference);
1019 return cpl_error_get_code();
1055static cpl_error_code
1056detmon_lg_core(cpl_frameset * cur_fset_on,
1057 cpl_frameset * cur_fset_off,
1060 double * exptime_on,
1061 double * exptime_off,
1064 const char * recipe_name,
1065 const char * pipeline_name,
1066 const char * pafregexp,
1067 const cpl_propertylist * pro_lintbl,
1068 const cpl_propertylist * pro_gaintbl,
1069 const cpl_propertylist * pro_coeffscube,
1070 const cpl_propertylist * pro_bpm,
1071 const cpl_propertylist * pro_corr,
1072 const cpl_propertylist * pro_diff,
1073 const char * package,
1074 int (* load_fset) (
const cpl_frameset *,
1077 int nsets, cpl_boolean opt_nir,
1078 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
1079 cpl_frameset * cur_fset)
1081 cpl_table * gain_table = cpl_table_new(
1082 cpl_frameset_get_size(cur_fset_on) / 2);
1083 cpl_table * linear_table = cpl_table_new(
1084 cpl_frameset_get_size(cur_fset_on) / 2);
1085 cpl_imagelist * coeffs = NULL;
1086 cpl_image * bpm = NULL;
1087 cpl_imagelist * autocorr_images = NULL;
1088 cpl_imagelist * diff_flats = NULL;
1089 cpl_propertylist * gaint_qclist = NULL;
1090 cpl_propertylist * lint_qclist = NULL;
1091 cpl_propertylist * linc_qclist = NULL;
1092 cpl_propertylist * bpm_qclist = NULL;
1094 int next_index_on = 0;
1095 int next_index_off = 0;
1098 cpl_msg_info(cpl_func,
"Reduce extension nb %d ", whichext);
1102 if (detmon_lg_config.intermediate) {
1103 autocorr_images = cpl_imagelist_new();
1104 diff_flats = cpl_imagelist_new();
1107 gaint_qclist = cpl_propertylist_new();
1108 lint_qclist = cpl_propertylist_new();
1109 linc_qclist = cpl_propertylist_new();
1110 bpm_qclist = cpl_propertylist_new();
1113 cpl_msg_info(cpl_func,
"Starting data reduction");
1114 if (detmon_lg_reduce(cur_fset_on, cur_fset_off,
1115 index_on, index_off, exptime_on, exptime_off,
1116 &next_index_on, &next_index_off,
1117 &coeffs, gain_table,
1118 linear_table, &bpm, autocorr_images,
1119 diff_flats, gaint_qclist, lint_qclist,
1120 linc_qclist, bpm_qclist, load_fset,
1121 opt_nir, whichext) == CPL_ERROR_CONTINUE) {
1122 cpl_msg_info(cpl_func,
"Empty extension %d", whichext);
1128 if (strcmp(recipe_name,
"detmon_opt_lg") == 0 ||
1129 strcmp(recipe_name,
"detmon_ir_lg") == 0) {
1130 cpl_msg_info(cpl_func,
"Inserting per-extension QC params");
1131 detmon_lg_qc_params(
1132 linear_table, lint_qclist,
1133 gain_table, gaint_qclist,
1134 coeffs, linc_qclist,
1141 cpl_msg_info(cpl_func,
"Saving the products");
1144 detmon_lg_save(parlist, frameset, recipe_name,
1145 pipeline_name, pafregexp,
1146 pro_lintbl, pro_gaintbl,
1147 pro_coeffscube, pro_bpm,
1148 pro_corr, pro_diff, package,
1149 coeffs, gain_table, linear_table,
1150 bpm, autocorr_images, diff_flats,
1151 gaint_qclist, lint_qclist, linc_qclist,
1154 cur_fset, whichext));
1157 detmon_lg_save(parlist, frameset, recipe_name,
1158 pipeline_name, pafregexp,
1159 pro_lintbl, pro_gaintbl,
1160 pro_coeffscube, pro_bpm,
1161 pro_corr, pro_diff, package,
1162 coeffs, gain_table, linear_table,
1163 bpm, autocorr_images, diff_flats,
1164 gaint_qclist, lint_qclist, linc_qclist,
1167 cur_fset, whichext));
1174 cpl_table_delete(gain_table);
1175 cpl_table_delete(linear_table);
1176 cpl_imagelist_delete(coeffs);
1177 cpl_propertylist_delete(gaint_qclist);
1178 cpl_propertylist_delete(lint_qclist);
1179 cpl_propertylist_delete(linc_qclist);
1180 if(bpm_qclist != NULL) cpl_propertylist_delete(bpm_qclist);
1181 cpl_image_delete(bpm);
1182 cpl_imagelist_delete(autocorr_images);
1183 cpl_imagelist_delete(diff_flats);
1185 return cpl_error_get_code();
1210detmon_image_correlate(
const cpl_image * image1,
1211 const cpl_image * image2,
1212 const int m,
const int n)
1214 cpl_image *image1_padded = NULL;
1215 cpl_image *image2_padded = NULL;
1219 cpl_image *corr_image_window = NULL;
1221 cpl_image* image_ri1 = NULL;
1222 cpl_image* image_ri2 = NULL;
1223 cpl_error_code err = CPL_ERROR_NONE;
1226 cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1227 cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1229 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1230 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1232 nx = cpl_image_get_size_x(image1);
1233 ny = cpl_image_get_size_y(image1);
1235 nx2 = cpl_image_get_size_x(image2);
1236 ny2 = cpl_image_get_size_y(image2);
1239 cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
1242 image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1243 cpl_image_copy(image1_padded, image1, m + 1, n + 1);
1245 image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1246 cpl_image_copy(image2_padded, image2, m + 1, n + 1);
1252 image_ri1 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
1253 image_ri2 = cpl_image_new(nx, ny , CPL_TYPE_FLOAT_COMPLEX);
1255 cpl_fft_image(image_ri1, image1_padded, CPL_FFT_FORWARD);
1256 cpl_fft_image(image_ri2, image2_padded, CPL_FFT_FORWARD);
1257 err = cpl_error_get_code();
1258 cpl_image_delete(image1_padded);
1259 image1_padded = NULL;
1260 cpl_image_delete(image2_padded);
1261 image2_padded = NULL;
1262 if (err == CPL_ERROR_NONE)
1265 cpl_image * corr_image = NULL;
1266 cpl_image * reorganised= NULL;
1267 cpl_image * image_ri_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1268 cpl_image * image_in_inv = cpl_image_new(nx, ny,
1269 CPL_TYPE_FLOAT_COMPLEX);
1272 for (i = 1; i <= nx; i++)
1274 for (j = 1; j <= ny; j++)
1277 double complex value1, value2, value;
1278 value1 = cpl_image_get_complex(image_ri1, i, j, &rej);
1279 value2 = cpl_image_get_complex(image_ri2, i, j, &rej);;
1280 value = conj(value1) * value2;
1281 cpl_image_set_complex(image_in_inv, i, j, value);
1284 cpl_image_delete(image_ri1);
1286 cpl_image_delete(image_ri2);
1289 err = cpl_error_get_code();
1290 if (err == CPL_ERROR_NONE)
1294 cpl_fft_image(image_ri_inv, image_in_inv,CPL_FFT_BACKWARD);
1295 cpl_image_delete(image_in_inv);
1298 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1299 for (i = 1; i <= nx; i++)
1301 for (j = 1; j <= ny; j++)
1305 value = cpl_image_get(image_ri_inv, i, j, &rej);
1306 cpl_image_set(corr_image, i, j, value);
1309 cpl_image_delete(image_ri_inv);
1310 err = cpl_error_get_code();
1311 if (err == CPL_ERROR_NONE)
1315 cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
1316 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1318 cpl_image_copy(reorganised, image, 1, 1);
1319 cpl_image_delete(image);
1320 image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
1321 cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
1322 cpl_image_delete(image);
1324 cpl_image_delete(corr_image);
1326 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1327 image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
1328 cpl_image_copy(corr_image, image, 1, 1);
1329 cpl_image_delete(image);
1331 image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
1332 cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
1333 cpl_image_delete(image);
1335 corr_image_window = cpl_image_extract(corr_image,
1338 nx / 2 + 1 + m, ny / 2 + 1 + n);
1343 cpl_image_delete(reorganised);
1344 cpl_image_delete(corr_image);
1346 if(cpl_image_divide_scalar(corr_image_window,
1347 cpl_image_get_max(corr_image_window))) {
1348 cpl_image_delete(corr_image_window);
1352 cpl_image_delete (image_ri1);
1353 cpl_image_delete (image_ri2);
1354 cpl_image_delete (image1_padded);
1355 cpl_image_delete (image2_padded);
1356 return corr_image_window;
1379detmon_autocorrelate(
const cpl_image * input2,
const int m,
1382 cpl_image *im_re = NULL;
1383 cpl_image *im_im = NULL;
1385 cpl_image *ifft_re = NULL;
1386 cpl_image *ifft_im = NULL;
1387 cpl_image *autocorr = NULL;
1388 cpl_image *autocorr_norm_double = NULL;
1389 cpl_image *autocorr_norm = NULL;
1390 cpl_image *reorganised = NULL;
1391 cpl_image *image = NULL;
1393 cpl_error_code error;
1396 cpl_ensure(input2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1398 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1399 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1401 nx = cpl_image_get_size_x(input2) + 2 * m;
1402 ny = cpl_image_get_size_y(input2) + 2 * n;
1405 while(nx > p || ny > p) {
1409 input = cpl_image_cast(input2, CPL_TYPE_DOUBLE);
1411 im_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1412 error = cpl_image_copy(im_re, input, 1, 1);
1413 cpl_image_delete(input);
1415 cpl_ensure(!error, error, NULL);
1417 im_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1419 error = cpl_image_fft(im_re, im_im, CPL_FFT_DEFAULT);
1420 cpl_ensure(!error, error, NULL);
1422 ifft_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1423 error = cpl_image_power(im_re, 2);
1424 cpl_ensure(!error, error, NULL);
1426 error = cpl_image_add(ifft_re, im_re);
1427 cpl_ensure(!error, error, NULL);
1429 cpl_image_delete(im_re);
1431 error = cpl_image_power(im_im, 2);
1432 cpl_ensure(!error, error, NULL);
1434 error = cpl_image_add(ifft_re, im_im);
1435 cpl_ensure(!error, error, NULL);
1437 cpl_image_delete(im_im);
1439 ifft_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1441 error = cpl_image_fft(ifft_re, ifft_im, CPL_FFT_INVERSE);
1442 cpl_ensure(!error, error, NULL);
1444 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1446 error = cpl_image_power(ifft_re, 2);
1447 cpl_ensure(!error, error, NULL);
1449 error = cpl_image_add(autocorr, ifft_re);
1450 cpl_ensure(!error, error, NULL);
1452 cpl_image_delete(ifft_re);
1454 error = cpl_image_power(ifft_im, 2);
1455 cpl_ensure(!error, error, NULL);
1457 error = cpl_image_add(autocorr, ifft_im);
1458 cpl_ensure(!error, error, NULL);
1460 cpl_image_delete(ifft_im);
1463 reorganised = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1465 image = cpl_image_extract(autocorr, p / 2 + 1, 1, p, p);
1466 cpl_image_copy(reorganised, image, 1, 1);
1467 cpl_image_delete(image);
1469 image = cpl_image_extract(autocorr, 1, 1, p / 2, p);
1470 cpl_image_copy(reorganised, image, p / 2 + 1, 1);
1471 cpl_image_delete(image);
1473 cpl_image_delete(autocorr);
1475 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1477 image = cpl_image_extract(reorganised, 1, p / 2 + 1, p, p);
1478 cpl_image_copy(autocorr, image, 1, 1);
1479 cpl_image_delete(image);
1481 image = cpl_image_extract(reorganised, 1, 1, p, p / 2);
1482 cpl_image_copy(autocorr, image, 1, p / 2 + 1);
1483 cpl_image_delete(image);
1485 cpl_image_delete(reorganised);
1487 autocorr_norm_double =
1488 cpl_image_extract(autocorr, p / 2 + 1 - m, p / 2 + 1 - n,
1489 p / 2 + 1 + m, p / 2 + 1 + n);
1491 cpl_image_delete(autocorr);
1493 if(cpl_image_divide_scalar(autocorr_norm_double,
1494 cpl_image_get_max(autocorr_norm_double))) {
1495 cpl_image_delete(autocorr_norm_double);
1496 cpl_ensure(0, cpl_error_get_code(), NULL);
1500 autocorr_norm = cpl_image_cast(autocorr_norm_double, CPL_TYPE_FLOAT);
1501 cpl_image_delete(autocorr_norm_double);
1503 return autocorr_norm;
1519detmon_lg_fill_parlist_nir_default(cpl_parameterlist * parlist,
1520 const char *recipe_name,
1521 const char *pipeline_name)
1523 const cpl_error_code error =
1524 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1570 cpl_ensure_code(!error, error);
1572 return cpl_error_get_code();
1588detmon_lg_fill_parlist_opt_default(cpl_parameterlist * parlist,
1589 const char *recipe_name,
1590 const char *pipeline_name)
1592 const cpl_error_code error =
1593 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1638 cpl_ensure_code(!error, error);
1640 return cpl_error_get_code();
1643static cpl_error_code
1644detmon_lg_fill_parlist_default_mr(cpl_parameterlist * parlist,
1645 const char *recipe_name,
1646 const char *pipeline_name)
1648 char * group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1649 char * par_name = cpl_sprintf(
"%s.%s", group_name,
"regions-file");
1650 cpl_parameter * p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1651 "File containing regions, "
1652 "four comma separated points "
1655 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions-file");
1656 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1657 cpl_parameterlist_append(parlist, p);
1659 cpl_free(group_name);
1661 group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1662 par_name = cpl_sprintf(
"%s.%s", group_name,
"regions");
1663 p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1664 "Colon separated list of regions, four "
1665 "points each, comma separated: "
1666 "llx,lly,urx,ury:llx,...",
1668 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions");
1669 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1670 cpl_parameterlist_append(parlist, p);
1672 cpl_free(group_name);
1674 return cpl_error_get_code();
1678detmon_lg_fill_parlist_opt_default_mr(cpl_parameterlist * parlist,
1679 const char *recipe_name,
1680 const char *pipeline_name)
1682 detmon_lg_fill_parlist_opt_default(parlist, recipe_name, pipeline_name);
1683 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1684 return cpl_error_get_code();
1688detmon_lg_fill_parlist_nir_default_mr(cpl_parameterlist * parlist,
1689 const char *recipe_name,
1690 const char *pipeline_name)
1692 detmon_lg_fill_parlist_nir_default(parlist, recipe_name, pipeline_name);
1693 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1695 return cpl_error_get_code();
1755detmon_lg_fill_parlist(cpl_parameterlist * parlist,
1756 const char *recipe_name,
const char *pipeline_name,
1766 const char *intermediate,
1767 const char *autocorr,
1768 const char *collapse,
1769 const char *rescale,
1770 const char *pix2pix,
1777 const char * pafname,
1794 int llx5,
int lly5,
int urx5,
int ury5,
int exts,
1795 cpl_boolean opt_nir)
1797 const cpl_error_code error =
1798 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 26,
1800 "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
1801 "CPL_TYPE_STRING", method,
1804 "Polynomial order for the fit (Linearity)",
1805 "CPL_TYPE_INT", order,
1807 "Kappa value for the kappa-sigma clipping (Gain)",
1808 "CPL_TYPE_DOUBLE", kappa,
1810 "Number of iterations to compute rms (Gain)",
1811 "CPL_TYPE_INT", niter,
1813 "x coordinate of the lower-left "
1814 "point of the region of interest. If not modified, default value will be 1.",
1815 "CPL_TYPE_INT", llx,
1817 "y coordinate of the lower-left "
1818 "point of the region of interest. If not modified, default value will be 1.",
1819 "CPL_TYPE_INT", lly,
1821 "x coordinate of the upper-right "
1822 "point of the region of interest. If not modified, default value will be X dimension of the input image.",
1823 "CPL_TYPE_INT", urx,
1825 "y coordinate of the upper-right "
1826 "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
1827 "CPL_TYPE_INT", ury,
1829 "User reference level",
1830 "CPL_TYPE_INT", ref_level,
1832 "De-/Activate intermediate products",
1833 "CPL_TYPE_BOOL", intermediate,
1836 "De-/Activate the autocorr option",
1837 "CPL_TYPE_BOOL", autocorr,
1840 "De-/Activate the collapse option",
1841 "CPL_TYPE_BOOL", collapse,
1843 "De-/Activate the image rescale option",
1844 "CPL_TYPE_BOOL", rescale,
1846 "De-/Activate the computation with pixel to pixel accuracy",
1847 "CPL_TYPE_BOOL", pix2pix,
1849 "De-/Activate the binary bpm option",
1850 "CPL_TYPE_BOOL", bpmbin,
1852 "Maximum x-shift for the autocorr",
1855 "Upper limit of Median flux to be filtered",
1856 "CPL_TYPE_INT", filter,
1858 "Maximum y-shift for the autocorr",
1861 "Tolerance for pair discrimination",
1862 "CPL_TYPE_DOUBLE", tolerance,
1865 "Generate PAF file",
1866 "CPL_TYPE_BOOL", pafgen,
1868 "Specific name for PAF file",
1869 "CPL_TYPE_STRING", pafname,
1873 "Activate the multi-exts option. Choose -1 to process all extensions. Choose an extension number"
1874 " to process the appropriate extension.",
1875 "CPL_TYPE_INT", exts,
1878 "Method for computing Fixed Pattern Noise (SMOOTH or HISTOGRAM)",
1879 "CPL_TYPE_STRING",
"HISTOGRAM",
1882 "template size in pixels for smoothing during FPN computation (only for SMOOTH method)",
1886 "all frames with mean saturation above the limit would not be used in linearity calculation",
1887 "CPL_TYPE_DOUBLE", 65535.0,
1890 "all frames with mean flux above the threshold would not be used in gain calculation",
1891 "CPL_TYPE_DOUBLE", 65535.0
1894 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 1,
1895 "coeffs_cube_split",
1896 "if TRUE, the recipe writes as many "
1897 "COEFFS_CUBE_Pi (i=0..order) as the value of "
1898 "the order parameter in a separate file",
1899 "CPL_TYPE_BOOL",
"CPL_FALSE");
1901 if(opt_nir == FALSE) {
1902 const cpl_error_code erroropt =
1903 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
1905 "x coord of the lower-left point of the first "
1906 "field used for contamination measurement. If not modified, default value will be 1.",
1907 "CPL_TYPE_INT", llx1,
1909 "y coord of the lower-left point of the first "
1910 "field used for contamination measurement. If not modified, default value will be 1.",
1911 "CPL_TYPE_INT", lly1,
1913 "x coord of the upper-right point of the first "
1914 "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
1915 "CPL_TYPE_INT", urx1,
1917 "y coord of the upper-right point of the first "
1918 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1919 "CPL_TYPE_INT", ury1,
1921 "x coord of the lower-left point of the second "
1922 "field used for contamination measurement. If not modified, default value will be 1.",
1923 "CPL_TYPE_INT", llx2,
1925 "y coord of the lower-left point of the second "
1926 "field used for contamination measurement. If not modified, default value will be 1.",
1927 "CPL_TYPE_INT", lly2,
1929 "x coord of the upper-right point of the second "
1930 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1931 "CPL_TYPE_INT", urx2,
1933 "y coord of the upper-right point of the second "
1934 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1935 "CPL_TYPE_INT", ury2,
1937 "x coord of the lower-left point of the third "
1938 "field used for contamination measurement. If not modified, default value will be 1.",
1939 "CPL_TYPE_INT", llx3,
1941 "y coord of the lower-left point of the third "
1942 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1943 "CPL_TYPE_INT", lly3,
1945 "x coord of the upper-right point of the third "
1946 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1947 "CPL_TYPE_INT", urx3,
1949 "y coord of the upper-right point of the third "
1950 "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
1951 "CPL_TYPE_INT", ury3,
1953 "x coord of the lower-left point of the fourth "
1954 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1955 "CPL_TYPE_INT", llx4,
1957 "y coord of the lower-left point of the fourth "
1958 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1959 "CPL_TYPE_INT", lly4,
1961 "x coord of the upper-right point of the fourth "
1962 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1963 "CPL_TYPE_INT", urx4,
1965 "y coord of the upper-right point of the fourth "
1966 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1967 "CPL_TYPE_INT", ury4,
1969 "x coord of the lower-left point of the fifth "
1970 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1971 "CPL_TYPE_INT", llx5,
1973 "y coord of the lower-left point of the fifth "
1974 "field used for contamination measurement. If not modified, default value will be 1.",
1975 "CPL_TYPE_INT", lly5,
1977 "x coord of the upper-right point of the fifth "
1978 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1979 "CPL_TYPE_INT", urx5,
1982 "y coord of the upper-right point of the fifth "
1983 "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
1984 "CPL_TYPE_INT", ury5);
1987 cpl_ensure_code(!erroropt, erroropt);
1990 cpl_ensure_code(!error, error);
1992 return cpl_error_get_code();
2005static cpl_error_code
2006detmon_lg_retrieve_parlist(
const char * pipeline_name,
2007 const char * recipe_name,
2008 const cpl_parameterlist * parlist,
2009 cpl_boolean opt_nir)
2013 const cpl_parameter * par;
2016 par_name = cpl_sprintf(
"%s.%s.method", pipeline_name, recipe_name);
2017 assert(par_name != NULL);
2018 par = cpl_parameterlist_find_const(parlist, par_name);
2019 detmon_lg_config.method = cpl_parameter_get_string(par);
2023 detmon_lg_config.order =
2024 detmon_retrieve_par_int(
"order", pipeline_name, recipe_name,
2028 detmon_lg_config.kappa =
2029 detmon_retrieve_par_double(
"kappa", pipeline_name, recipe_name,
2033 detmon_lg_config.niter =
2034 detmon_retrieve_par_int(
"niter", pipeline_name, recipe_name,
2038 detmon_lg_config.llx =
2039 detmon_retrieve_par_int(
"llx", pipeline_name, recipe_name,
2043 detmon_lg_config.lly =
2044 detmon_retrieve_par_int(
"lly", pipeline_name, recipe_name,
2048 detmon_lg_config.urx =
2049 detmon_retrieve_par_int(
"urx", pipeline_name, recipe_name,
2053 detmon_lg_config.ury =
2054 detmon_retrieve_par_int(
"ury", pipeline_name, recipe_name,
2058 detmon_lg_config.ref_level =
2059 detmon_retrieve_par_int(
"ref_level", pipeline_name, recipe_name,
2064 cpl_sprintf(
"%s.%s.intermediate", pipeline_name, recipe_name);
2065 assert(par_name != NULL);
2066 par = cpl_parameterlist_find_const(parlist, par_name);
2067 detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
2071 par_name = cpl_sprintf(
"%s.%s.autocorr", pipeline_name, recipe_name);
2072 assert(par_name != NULL);
2073 par = cpl_parameterlist_find_const(parlist, par_name);
2074 detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
2078 par_name = cpl_sprintf(
"%s.%s.coeffs_cube_split", pipeline_name, recipe_name);
2079 assert(par_name != NULL);
2080 par = cpl_parameterlist_find_const(parlist, par_name);
2081 detmon_lg_config.split_coeffs = cpl_parameter_get_bool(par);
2085 par_name = cpl_sprintf(
"%s.%s.collapse", pipeline_name, recipe_name);
2086 assert(par_name != NULL);
2087 par = cpl_parameterlist_find_const(parlist, par_name);
2088 detmon_lg_config.collapse = cpl_parameter_get_bool(par);
2092 par_name = cpl_sprintf(
"%s.%s.rescale", pipeline_name, recipe_name);
2093 assert(par_name != NULL);
2094 par = cpl_parameterlist_find_const(parlist, par_name);
2095 detmon_lg_config.rescale = cpl_parameter_get_bool(par);
2099 par_name = cpl_sprintf(
"%s.%s.pix2pix", pipeline_name, recipe_name);
2100 assert(par_name != NULL);
2101 par = cpl_parameterlist_find_const(parlist, par_name);
2102 detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
2106 par_name = cpl_sprintf(
"%s.%s.bpmbin", pipeline_name, recipe_name);
2107 assert(par_name != NULL);
2108 par = cpl_parameterlist_find_const(parlist, par_name);
2109 detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
2113 detmon_lg_config.filter =
2114 detmon_retrieve_par_int(
"filter", pipeline_name,
2115 recipe_name, parlist);
2118 detmon_lg_config.m =
2119 detmon_retrieve_par_int(
"m", pipeline_name, recipe_name, parlist);
2122 detmon_lg_config.n =
2123 detmon_retrieve_par_int(
"n", pipeline_name, recipe_name, parlist);
2126 par_name = cpl_sprintf(
"%s.%s.tolerance", pipeline_name, recipe_name);
2127 assert(par_name != NULL);
2128 par = cpl_parameterlist_find_const(parlist, par_name);
2129 detmon_lg_config.tolerance = cpl_parameter_get_double(par);
2134 par_name = cpl_sprintf(
"%s.%s.pafgen", pipeline_name, recipe_name);
2135 assert(par_name != NULL);
2136 par = cpl_parameterlist_find_const(parlist, par_name);
2137 detmon_lg_config.pafgen = cpl_parameter_get_bool(par);
2141 par_name = cpl_sprintf(
"%s.%s.pafname", pipeline_name, recipe_name);
2142 assert(par_name != NULL);
2143 par = cpl_parameterlist_find_const(parlist, par_name);
2144 detmon_lg_config.pafname = cpl_parameter_get_string(par);
2147 if(opt_nir == OPT) {
2149 detmon_lg_config.llx1 =
2150 detmon_retrieve_par_int(
"llx1", pipeline_name, recipe_name,
2154 detmon_lg_config.lly1 =
2155 detmon_retrieve_par_int(
"lly1", pipeline_name, recipe_name,
2159 detmon_lg_config.urx1 =
2160 detmon_retrieve_par_int(
"urx1", pipeline_name, recipe_name,
2164 detmon_lg_config.ury1 =
2165 detmon_retrieve_par_int(
"ury1", pipeline_name, recipe_name,
2169 detmon_lg_config.llx2 =
2170 detmon_retrieve_par_int(
"llx2", pipeline_name, recipe_name,
2174 detmon_lg_config.lly2 =
2175 detmon_retrieve_par_int(
"lly2", pipeline_name, recipe_name,
2179 detmon_lg_config.urx2 =
2180 detmon_retrieve_par_int(
"urx2", pipeline_name, recipe_name,
2184 detmon_lg_config.ury2 =
2185 detmon_retrieve_par_int(
"ury2", pipeline_name, recipe_name,
2189 detmon_lg_config.llx3 =
2190 detmon_retrieve_par_int(
"llx3", pipeline_name, recipe_name,
2194 detmon_lg_config.lly3 =
2195 detmon_retrieve_par_int(
"lly3", pipeline_name, recipe_name,
2199 detmon_lg_config.urx3 =
2200 detmon_retrieve_par_int(
"urx3", pipeline_name, recipe_name,
2204 detmon_lg_config.ury3 =
2205 detmon_retrieve_par_int(
"ury3", pipeline_name, recipe_name,
2209 detmon_lg_config.llx4 =
2210 detmon_retrieve_par_int(
"llx4", pipeline_name, recipe_name,
2214 detmon_lg_config.lly4 =
2215 detmon_retrieve_par_int(
"lly4", pipeline_name, recipe_name,
2219 detmon_lg_config.urx4 =
2220 detmon_retrieve_par_int(
"urx4", pipeline_name, recipe_name,
2224 detmon_lg_config.ury4 =
2225 detmon_retrieve_par_int(
"ury4", pipeline_name, recipe_name,
2229 detmon_lg_config.llx5 =
2230 detmon_retrieve_par_int(
"llx5", pipeline_name, recipe_name,
2234 detmon_lg_config.lly5 =
2235 detmon_retrieve_par_int(
"lly5", pipeline_name, recipe_name,
2239 detmon_lg_config.urx5 =
2240 detmon_retrieve_par_int(
"urx5", pipeline_name, recipe_name,
2244 detmon_lg_config.ury5 =
2245 detmon_retrieve_par_int(
"ury5", pipeline_name, recipe_name,
2250 detmon_lg_config.exts =
2251 detmon_retrieve_par_int(
"exts", pipeline_name, recipe_name,
2255 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2257 cpl_sprintf(
"%s.%s.fpn_method", pipeline_name, recipe_name);
2258 assert(par_name != NULL);
2259 par = cpl_parameterlist_find_const(parlist, par_name);
2262 const char * str_method = cpl_parameter_get_string(par);
2263 if (strcmp(str_method,
"SMOOTH") == 0)
2265 detmon_lg_config.fpn_method = FPN_SMOOTH;
2267 else if (strcmp(str_method,
"HISTOGRAM") == 0)
2269 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2275 detmon_lg_config.fpn_smooth =
2276 detmon_retrieve_par_int(
"fpn_smooth", pipeline_name, recipe_name,
2280 detmon_lg_config.saturation_limit = 65535;
2282 cpl_sprintf(
"%s.%s.saturation_limit", pipeline_name, recipe_name);
2283 assert(par_name != NULL);
2284 par = cpl_parameterlist_find_const(parlist, par_name);
2287 detmon_lg_config.saturation_limit = cpl_parameter_get_double(par);
2294 detmon_lg_config.gain_threshold = 0;
2296 cpl_sprintf(
"%s.%s.gain_threshold", pipeline_name, recipe_name);
2297 assert(par_name != NULL);
2298 par = cpl_parameterlist_find_const(parlist, par_name);
2301 detmon_lg_config.gain_threshold = cpl_parameter_get_double(par);
2306 if(cpl_error_get_code())
2308 cpl_msg_error(cpl_func,
"Failed to retrieve the input parameters");
2309 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
2313 return cpl_error_get_code();
2323static cpl_error_code
2324detmon_lg_check_defaults(
const cpl_image * reference)
2326 const int nx = cpl_image_get_size_x(reference);
2327 const int ny = cpl_image_get_size_y(reference);
2329 detmon_lg_config.nx = nx;
2330 detmon_lg_config.ny = ny;
2332 detmon_lg_config.wholechip = CPL_FALSE;
2334 if(detmon_lg_config.llx == -1)
2335 detmon_lg_config.llx = 1;
2336 if(detmon_lg_config.lly == -1)
2337 detmon_lg_config.lly = 1;
2338 if(detmon_lg_config.urx == -1)
2339 detmon_lg_config.urx = nx;
2340 if(detmon_lg_config.ury == -1)
2341 detmon_lg_config.ury = ny;
2343 if (detmon_lg_config.llx == 1 &&
2344 detmon_lg_config.lly == 1 &&
2345 detmon_lg_config.urx == nx &&
2346 detmon_lg_config.ury == ny)
2347 detmon_lg_config.wholechip = CPL_TRUE;
2349 if(detmon_lg_config.llx1 == -1)
2350 detmon_lg_config.llx1 = 1;
2351 if(detmon_lg_config.lly1 == -1)
2352 detmon_lg_config.lly1 = 1;
2353 if(detmon_lg_config.urx1 == -1)
2354 detmon_lg_config.urx1 = nx;
2355 if(detmon_lg_config.ury1 == -1)
2356 detmon_lg_config.ury1 = ny;
2358 if(detmon_lg_config.llx2 == -1)
2359 detmon_lg_config.llx2 = 1;
2360 if(detmon_lg_config.lly2 == -1)
2361 detmon_lg_config.lly2 = 1;
2362 if(detmon_lg_config.urx2 == -1)
2363 detmon_lg_config.urx2 = nx / 2;
2364 if(detmon_lg_config.ury2 == -1)
2365 detmon_lg_config.ury2 = ny / 2;
2367 if(detmon_lg_config.llx3 == -1)
2368 detmon_lg_config.llx3 = 1;
2369 if(detmon_lg_config.lly3 == -1)
2370 detmon_lg_config.lly3 = ny / 2;
2371 if(detmon_lg_config.urx3 == -1)
2372 detmon_lg_config.urx3 = nx / 2;
2373 if(detmon_lg_config.ury3 == -1)
2374 detmon_lg_config.ury3 = ny;
2376 if(detmon_lg_config.llx4 == -1)
2377 detmon_lg_config.llx4 = nx / 2;
2378 if(detmon_lg_config.lly4 == -1)
2379 detmon_lg_config.lly4 = ny / 2;
2380 if(detmon_lg_config.urx4 == -1)
2381 detmon_lg_config.urx4 = nx;
2382 if(detmon_lg_config.ury4 == -1)
2383 detmon_lg_config.ury4 = ny;
2385 if(detmon_lg_config.llx5 == -1)
2386 detmon_lg_config.llx5 = nx / 2;
2387 if(detmon_lg_config.lly5 == -1)
2388 detmon_lg_config.lly5 = 1;
2389 if(detmon_lg_config.urx5 == -1)
2390 detmon_lg_config.urx5 = nx;
2391 if(detmon_lg_config.ury5 == -1)
2392 detmon_lg_config.ury5 = ny / 2;
2394 if(detmon_lg_config.intermediate == TRUE) {
2395 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.");
2396 detmon_lg_config.autocorr = TRUE;
2400 detmon_lg_config.lamp_stability = 0.0;
2402 detmon_lg_config.lamp_ok = FALSE;
2404 detmon_lg_config.cr = 0.0;
2406 return cpl_error_get_code();
2421static cpl_error_code
2422detmon_lg_split_onoff(
const cpl_frameset * cur_fset,
2423 cpl_frameset * cur_fset_on,
2424 cpl_frameset * cur_fset_off,
2426 const char *tag_off)
2431 cpl_frame * cur_frame_dup = NULL;
2434 const cpl_frame * first;
2435 const cpl_frame * second;
2436 const char * first_tag;
2437 const char * second_tag;
2438 skip_if((first = cpl_frameset_get_position_const(cur_fset, 0)) == NULL);
2439 skip_if((second = cpl_frameset_get_position_const(cur_fset, 1)) == NULL);
2441 skip_if((first_tag = cpl_frame_get_tag(first)) == NULL);
2442 skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
2443 if (opt_nir == OPT &&
2444 ((!strcmp(first_tag, tag_on ) && !strcmp(second_tag, tag_off)) ||
2445 (!strcmp(first_tag, tag_off) && !strcmp(second_tag, tag_on )))) {
2446 detmon_lg_config.lamp_ok = TRUE;
2450 nframes = cpl_frameset_get_size(cur_fset);
2451 for(i = detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
2452 const cpl_frame * cur_frame =
2453 cpl_frameset_get_position_const(cur_fset, i);
2457 cur_frame_dup = cpl_frame_duplicate(cur_frame);
2458 tag = (
char *) cpl_frame_get_tag(cur_frame_dup);
2461 if(!strcmp(tag, tag_on)) {
2462 skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
2463 }
else if(!strcmp(tag, tag_off)) {
2464 skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
2466 cpl_frame_delete(cur_frame_dup);
2467 cur_frame_dup = NULL;
2470 cur_frame_dup = NULL;
2474 cpl_frame_delete(cur_frame_dup);
2476 return cpl_error_get_code();
2503static cpl_error_code
2504detmon_lg_reduce(
const cpl_frameset * set_on,
2505 const cpl_frameset * set_off,
2506 int* index_on,
int* index_off,
2507 double* exptime_on,
double* exptime_off,
2508 int *next_index_on,
int* next_index_off,
2509 cpl_imagelist ** coeffs_ptr,
2510 cpl_table * gain_table,
2511 cpl_table * linear_table,
2512 cpl_image ** bpm_ptr,
2513 cpl_imagelist * autocorr_images,
2514 cpl_imagelist * diff_flats,
2515 cpl_propertylist * gaint_qclist,
2516 cpl_propertylist * lint_qclist,
2517 cpl_propertylist * linc_qclist,
2518 cpl_propertylist * bpm_qclist,
2519 int (* load_fset) (
const cpl_frameset *,
2522 const cpl_boolean opt_nir,
2525 cpl_errorstate prestate = cpl_errorstate_get();
2526 const double D_INVALID_VALUE = -999;
2528 cpl_imagelist * linearity_inputs = NULL;
2529 cpl_imagelist * opt_offs = NULL;
2531 cpl_propertylist * reflist = NULL;
2533 int rows_linear_affected = 1;
2534 int rows_gain_affected = 1;
2535 int last_linear_best = 0;
2537 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2538 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2540 nsets = cpl_frameset_get_size(set_on) / 2;
2542 detmon_lg_config.load_fset = load_fset;
2543 if(detmon_lg_config.collapse) {
2550 const cpl_frame *first = cpl_frameset_get_position_const(set_off, 0);
2551 cpl_frame *dup_first = cpl_frame_duplicate(first);
2553 const cpl_frame *second = cpl_frameset_get_position_const(set_off, 1);
2554 cpl_frame *dup_second = cpl_frame_duplicate(second);
2556 cpl_frameset *raw_offs = cpl_frameset_new();
2558 skip_if(cpl_frameset_insert(raw_offs, dup_first));
2559 skip_if(cpl_frameset_insert(raw_offs, dup_second));
2561 opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
2564 cpl_frameset_delete(raw_offs);
2565 if (opt_offs == NULL) {
2566 cpl_errorstate_set(prestate);
2567 return CPL_ERROR_CONTINUE;
2571 skip_if(detmon_lg_reduce_init(gain_table,
2583 if(detmon_lg_lamp_stab(set_on, set_off,
2584 opt_nir, whichext)) {
2585 cpl_errorstate_set(prestate);
2588 if(!detmon_lg_config.collapse)
2592 skip_if(cpl_table_unselect_all(linear_table));
2593 skip_if(cpl_table_unselect_all(gain_table));
2597 for(i = 0; i < nsets ; i++)
2599 skip_if(detmon_lg_reduce_dit(set_on,
2600 index_on, exptime_on,
2604 index_off, exptime_off,
2605 next_index_on, next_index_off,
2607 gain_table, linearity_inputs,
2608 lint_qclist, opt_nir,
2609 autocorr_images, diff_flats,
2611 &rows_linear_affected,&rows_gain_affected));
2615 if (rows_linear_affected == 0)
2617 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2618 "into linear calculation, check the messages above");
2619 cpl_table_select_row(linear_table, i);
2623 last_linear_best = i;
2626 if (rows_gain_affected == 0)
2628 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2629 "into gain calculation, check the messages above");
2630 cpl_table_select_row(gain_table, i);
2637 skip_if(detmon_add_adl_column(linear_table, opt_nir));
2643 skip_if(cpl_table_erase_selected(gain_table));
2644 skip_if(cpl_table_erase_selected(linear_table));
2647 reflist = cpl_propertylist_new();
2648 skip_if(cpl_propertylist_append_bool(reflist,
"ADU", FALSE));
2649 skip_if(cpl_table_sort(gain_table, reflist));
2655 skip_if(detmon_lg_reduce_all(linear_table,
2656 gaint_qclist, lint_qclist, linc_qclist,
2657 bpm_qclist, coeffs_ptr, bpm_ptr,
2659 gain_table, whichext, opt_nir));
2662 double gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
2665 cpl_error_code cplerr = cpl_error_get_code();
2666 if (cplerr != CPL_ERROR_NONE || (gain == 0.0))
2668 cpl_msg_warning(cpl_func,
"Cannot read gain from QC parameters - "
2669 "FPN will not be computed");
2674 detmon_fpn_compute(set_on, index_on, last_linear_best, lint_qclist,
2675 detmon_lg_config.llx,
2676 detmon_lg_config.lly,
2677 detmon_lg_config.urx,
2678 detmon_lg_config.ury,
2681 detmon_lg_config.fpn_method,
2682 detmon_lg_config.fpn_smooth);
2687 detmon_table_fill_invalid(gain_table, D_INVALID_VALUE);
2689 cpl_imagelist_delete(linearity_inputs);
2690 cpl_imagelist_delete(opt_offs);
2691 cpl_propertylist_delete(reflist);
2693 return cpl_error_get_code();
2696static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code)
2698 int ncols = cpl_table_get_ncol(ptable);
2699 cpl_array* pnames = cpl_table_get_column_names(ptable);
2700 int nrows = cpl_table_get_nrow(ptable);
2702 for (i=0; i < ncols; i++)
2705 for (j = 0; j< nrows; j++)
2707 const char* colname = cpl_array_get_data_string_const(pnames)[i];
2709 cpl_type type = cpl_table_get_column_type(ptable, colname);
2710 cpl_table_get(ptable, colname, j, &isnull);
2713 if (type == CPL_TYPE_DOUBLE)
2715 cpl_table_set(ptable,colname,j, code);
2717 else if (type == CPL_TYPE_FLOAT)
2719 cpl_table_set_float(ptable,colname,j, (
float)code);
2724 cpl_array_delete(pnames);
2725 return cpl_error_get_code();
2728static cpl_error_code
2729detmon_fpn_compute(
const cpl_frameset *set_on,
2731 int last_linear_best,
2732 cpl_propertylist *lint_qclist,
2739 FPN_METHOD fpn_method,
2743 const cpl_image* im1 = 0;
2745 cpl_imagelist* ons = 0;
2746 cpl_frameset * pair_on = 0;
2747 int nsets_extracted = cpl_frameset_get_size(set_on);
2748 cpl_size * selection = NULL;
2757 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
2758 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
2760 selection[index_on[last_linear_best*2 + 0] ] = 1;
2761 selection[index_on[last_linear_best*2 + 1] ] = 1;
2762 pair_on = cpl_frameset_extract(set_on, selection, 1);
2763 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2765 skip_if(ons == NULL);
2766 skip_if((im1 = cpl_imagelist_get_const(ons, 0)) == NULL);
2768 fpn = irplib_fpn_lg(im1, range, gain, fpn_method, smooth_size, &mse);
2769 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_FPN,
2771 skip_if(cpl_propertylist_append_double(lint_qclist,
"ESO QC GAIN ERR",
2775 cpl_frameset_delete(pair_on);
2776 cpl_imagelist_delete(ons);
2777 cpl_free(selection);
2778 return cpl_error_get_code();
2790static cpl_error_code
2791detmon_lg_lamp_stab(
const cpl_frameset * lamps,
2792 const cpl_frameset * darks,
2793 cpl_boolean opt_nir,
2806 cpl_vector * selection = NULL;
2807 cpl_propertylist * plist;
2808 double dit_lamp, dit_dark;
2810 cpl_imagelist * lamps_data = NULL;
2811 cpl_imagelist * darks_data = NULL;
2812 double * stab_levels = NULL;
2814 double * ditvals = NULL;
2818 cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
2819 CPL_ERROR_ILLEGAL_INPUT);
2825 cpl_msg_info(__func__,
"Checking DIT consistency");
2826 selection = cpl_vector_new(nb_lamps);
2827 ditvals = cpl_malloc(nb_lamps *
sizeof(
double));
2829 for (i = 0; i < nb_lamps; i++) {
2830 const cpl_frame * c_lamp;
2831 const cpl_frame * c_dark;
2833 skip_if (cpl_error_get_code());
2836 c_lamp = cpl_frameset_get_position_const(lamps, i);
2837 plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
2839 dit_lamp = (double)detmon_pfits_get_dit(plist);
2841 dit_lamp = (double)detmon_pfits_get_dit_opt(plist);
2842 cpl_propertylist_delete(plist);
2843 skip_if (cpl_error_get_code());
2846 c_dark = cpl_frameset_get_position_const(darks, i);
2847 plist = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
2849 dit_dark = (double)detmon_pfits_get_dit(plist);
2851 dit_dark = (double)detmon_pfits_get_dit_opt(plist);
2852 cpl_propertylist_delete(plist);
2853 skip_if (cpl_error_get_code());
2856 if (fabs(dit_dark-dit_lamp) > 1e-3) {
2857 cpl_msg_error(__func__,
"DIT not consistent between LAMP and DARK, skip lamp stability computation");
2862 ditvals[i] = dit_lamp;
2865 cpl_vector_set(selection, i, -1.0);
2873 if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
2874 cpl_vector_set(selection, i, -1.0);
2878 cpl_vector_set(selection, i, 1.0);
2885 cpl_msg_info(__func__,
"Not enough frames for stability check");
2889 cpl_msg_info(__func__,
"Compute the differences lamp - dark");
2892 lamps_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2894 detmon_lg_config.llx,
2895 detmon_lg_config.lly,
2896 detmon_lg_config.urx,
2897 detmon_lg_config.ury,
2900 darks_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2902 detmon_lg_config.llx,
2903 detmon_lg_config.lly,
2904 detmon_lg_config.urx,
2905 detmon_lg_config.ury,
2908 nb_darks=cpl_imagelist_get_size(darks_data);
2909 if(nb_darks==nb_lamps) {
2910 skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
2912 cpl_image* master_dark=cpl_imagelist_collapse_median_create(darks_data);
2913 cpl_imagelist_subtract_image(lamps_data,master_dark);
2914 cpl_image_delete(master_dark);
2917 cpl_msg_info(__func__,
"Check the lamp stability");
2918 stab_levels = cpl_malloc(dit_stab *
sizeof(
double));
2920 for (i=0; i<nb_lamps; i++) {
2921 if (cpl_vector_get(selection, i) < 0) {
2923 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
2929 for (i=1; i<dit_stab; i++) {
2930 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
2931 detmon_lg_config.lamp_stability)
2932 detmon_lg_config.lamp_stability =
2933 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
2938 if (detmon_lg_config.lamp_stability > 0.01) {
2939 cpl_msg_warning(__func__,
2940 "Lamp stability level %g difference too high - proceed anyway",detmon_lg_config.lamp_stability);
2947 cpl_vector_delete(selection);
2948 cpl_imagelist_delete(lamps_data);
2949 cpl_imagelist_delete(darks_data);
2950 cpl_free(stab_levels);
2952 return cpl_error_get_code();
2979static cpl_error_code
2980detmon_lg_reduce_dit(
const cpl_frameset * set_on,
2981 int* index_on,
double* exptime_on,
2984 const cpl_frameset * set_off,
2985 int * index_off,
double* exptime_off,
2986 int* next_on,
int* next_off,
2987 cpl_table * linear_table,
2988 cpl_table * gain_table,
2989 cpl_imagelist * linearity_inputs,
2990 cpl_propertylist * qclist,
2991 cpl_boolean opt_nir,
2992 cpl_imagelist * autocorr_images,
2993 cpl_imagelist * diff_flats,
2994 cpl_imagelist * opt_offs,
2996 int* rows_linear_affected,
2997 int* rows_gain_affected)
2999 cpl_frameset * pair_on = NULL;
3000 cpl_frameset * pair_off = NULL;
3001 cpl_imagelist * ons = NULL;
3002 cpl_imagelist * offs = NULL;
3003 cpl_boolean follow = CPL_TRUE;
3004 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
3008 double current_dit = 0;
3010 const char * filename;
3012 cpl_propertylist * plist = NULL;
3013 cpl_propertylist* pDETlist = NULL;
3015 mode = detmon_lg_config.collapse ?
3016 mode | IRPLIB_GAIN_COLLAPSE | IRPLIB_LIN_COLLAPSE:
3017 mode | IRPLIB_GAIN_NO_COLLAPSE | IRPLIB_LIN_NO_COLLAPSE;
3018 mode = detmon_lg_config.pix2pix ?
3019 mode | IRPLIB_LIN_PIX2PIX : mode;
3021 mode | IRPLIB_GAIN_NIR | IRPLIB_LIN_NIR :
3022 mode | IRPLIB_GAIN_OPT | IRPLIB_LIN_OPT ;
3026 skip_if(detmon_pair_extract_next(set_on, index_on, next_on, exptime_on, &pair_on, detmon_lg_config.tolerance));
3027 current_dit = exptime_on[*next_on - 1];
3030 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
3031 skip_if(ons == NULL);
3032 cpl_msg_debug(cpl_func,
" Loaded ON images: %" CPL_SIZE_FORMAT
3033 ", exptime[%f]",cpl_imagelist_get_size(ons), current_dit );
3034 if(cpl_imagelist_get_size(ons) != 2)
3036 cpl_msg_error(cpl_func,
"cannot take ON pair, number of images[%"
3037 CPL_SIZE_FORMAT
"]", cpl_imagelist_get_size(ons));
3040 if(detmon_lg_config.filter > 0)
3043 cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
3044 detmon_lg_config.llx,
3045 detmon_lg_config.lly,
3046 detmon_lg_config.urx,
3047 detmon_lg_config.ury);
3049 cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
3050 detmon_lg_config.llx,
3051 detmon_lg_config.lly,
3052 detmon_lg_config.urx,
3053 detmon_lg_config.ury);
3057 if ( med1 > (
double)detmon_lg_config.filter ||
3058 med2 > (
double)detmon_lg_config.filter)
3061 cpl_table_select_row(gain_table, dit_nb);
3062 cpl_table_select_row(linear_table, dit_nb);
3064 cpl_msg_warning(cpl_func,
"Frames of EXPTIME nb %d "
3065 "will not be taken into account for computation "
3066 "as the median of the on frames computed on the "
3067 "user defined region [%d,%d,%d,%d] are above "
3068 "--filter threshold (%d)",
3070 detmon_lg_config.llx,
3071 detmon_lg_config.lly,
3072 detmon_lg_config.urx,
3073 detmon_lg_config.ury,
3074 detmon_lg_config.filter);
3078 if (follow || detmon_lg_config.filter < 0)
3086 if(!detmon_lg_config.collapse)
3103 if (!strcmp(detmon_lg_config.method,
"MED") ||
3104 cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
3106 skip_if(detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off, detmon_lg_config.tolerance));
3110 skip_if(detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
3113 cpl_msg_debug(cpl_func,
" Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
3114 offs = detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
3116 skip_if(offs == NULL);
3117 skip_if(cpl_error_get_code());
3120 offs = (cpl_imagelist *) opt_offs;
3124 if(detmon_lg_config.rescale)
3126 skip_if(detmon_lg_rescale(ons));
3127 if (!detmon_lg_config.collapse &&
3128 !strcmp(detmon_lg_config.method,
"MED"))
3129 skip_if(detmon_lg_rescale(offs));
3134 cpl_frame_get_filename(cpl_frameset_get_position_const(pair_on, 0));
3135 skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
3139 pDETlist = cpl_propertylist_new();
3140 cpl_propertylist_copy_property_regexp(pDETlist, plist,
"DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
3143 irplib_table_create_column(gain_table, pDETlist);
3144 irplib_table_create_column(linear_table, pDETlist);
3147 if(opt_nir == NIR) {
3148 c_dit = detmon_pfits_get_dit(plist);
3149 c_ndit = irplib_pfits_get_ndit(plist);
3151 c_dit = irplib_pfits_get_exptime(plist);
3163 cpl_msg_info(cpl_func,
"Computing GAIN for EXPTIME value nb %d",
3167 if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
3169 cpl_table_erase_column(gain_table,
"MEAN_OFF1");
3170 cpl_table_erase_column(gain_table,
"MEAN_OFF2");
3171 cpl_table_erase_column(gain_table,
"SIG_OFF_DIF");
3172 cpl_table_erase_column(gain_table,
"GAIN");
3173 cpl_table_erase_column(gain_table,
"GAIN_CORR");
3174 cpl_table_new_column(gain_table,
"MEAN_OFF", CPL_TYPE_DOUBLE);
3178 skip_if(detmon_gain_table_fill_row(gain_table,
3181 diff_flats, ons, offs,
3182 detmon_lg_config.kappa,
3183 detmon_lg_config.niter,
3184 detmon_lg_config.llx,
3185 detmon_lg_config.lly,
3186 detmon_lg_config.urx,
3187 detmon_lg_config.ury,
3190 detmon_lg_config.gain_threshold,
3191 dit_nb, mode, rows_gain_affected));
3194 skip_if(detmon_check_saturation_on_pair(autocorr_images,
3196 detmon_lg_config.kappa,
3197 detmon_lg_config.niter,
3198 detmon_lg_config.llx,
3199 detmon_lg_config.lly,
3200 detmon_lg_config.urx,
3201 detmon_lg_config.ury,
3202 detmon_lg_config.saturation_limit,
3203 dit_nb, mode, rows_linear_affected));
3206 if (*rows_gain_affected)
3209 skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
3211 cpl_msg_info(cpl_func,
"Linearity reduction for nb %d",
3214 if (*rows_linear_affected) {
3215 skip_if(detmon_lin_table_fill_row(linear_table, c_dit,
3216 linearity_inputs, ons, offs,
3217 detmon_lg_config.llx,
3218 detmon_lg_config.lly,
3219 detmon_lg_config.urx,
3220 detmon_lg_config.ury,
3221 dit_nb, *dit_nskip, mode));
3223 skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
3235 if(opt_nir == OPT &&
3236 *rows_linear_affected != 0 ) {
3237 detmon_opt_contamination(ons, offs, mode, qclist);
3244 cpl_frameset_delete(pair_on);
3245 cpl_imagelist_delete(ons);
3247 if(!detmon_lg_config.collapse ) {
3248 cpl_imagelist_delete(offs);
3251 if(!detmon_lg_config.collapse) {
3252 cpl_frameset_delete(pair_off);
3255 cpl_propertylist_delete(plist);
3256 cpl_propertylist_delete(pDETlist);
3257 return cpl_error_get_code();
3267static cpl_error_code
3268detmon_add_adl_column(cpl_table * table,
3269 cpl_boolean opt_nir)
3271 cpl_error_code error;
3272 double mean_med_dit;
3275 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
3277 mean_med_dit = cpl_table_get_column_mean(table,
"MED_DIT");
3279 dits = cpl_table_get_data_double(table,
"EXPTIME");
3281 dits = cpl_table_get_data_double(table,
"DIT");
3283 error = cpl_table_copy_data_double(table,
"ADL", dits);
3284 cpl_ensure_code(!error, error);
3285 error = cpl_table_multiply_scalar(table,
"ADL", mean_med_dit);
3286 cpl_ensure_code(!error, error);
3288 return cpl_error_get_code();
3300static cpl_error_code
3301detmon_lg_reduce_init(cpl_table * gain_table,
3302 cpl_table * linear_table,
3303 cpl_imagelist ** linearity_inputs,
3304 const cpl_boolean opt_nir)
3306 skip_if(detmon_gain_table_create(gain_table, opt_nir));
3307 skip_if(detmon_lin_table_create(linear_table, opt_nir));
3309 if(detmon_lg_config.pix2pix) {
3310 *linearity_inputs = cpl_imagelist_new();
3311 skip_if(*linearity_inputs == NULL);
3316 return cpl_error_get_code();
3327detmon_pfits_get_dit(
const cpl_propertylist * plist)
3329 if (cpl_propertylist_has(plist,
"ESO DET DIT")) {
3331 return irplib_pfits_get_prop_double(plist,
"ESO DET DIT");
3334 return irplib_pfits_get_prop_double(plist,
"ESO DET SEQ1 DIT");
3336 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"FITS key "
3337 "ESO DET DIT or ESO DET DIT not found");
3349detmon_pfits_get_dit_opt(
const cpl_propertylist * plist)
3351 if (cpl_propertylist_has(plist,
"ESO DET WIN1 UIT1")) {
3353 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3354 }
else if (cpl_propertylist_has(plist,
"ESO DET UIT1")) {
3356 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3359 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"FITS key "
3360 "ESO DET WIN1 UIT1 or ESO DET UIT1 not found");
3370static cpl_propertylist*
3371detmon_load_pro_keys(
const char* NAME_O)
3373 cpl_propertylist* pro_keys=NULL;
3374 pro_keys=cpl_propertylist_load_regexp(NAME_O,0,
"^(ESO PRO)",0);
3379static double irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
3380 const char* prop_name)
3383 dit = cpl_propertylist_get_double(plist, prop_name);
3384 if(cpl_error_get_code() != CPL_ERROR_NONE)
3386 cpl_msg_error(cpl_func,
"Cannot read property '%s', err[%s]",
3387 prop_name, cpl_error_get_where());
3392static cpl_error_code
3393detmon_gain_compute_qc(
double kappa,
int nclip,
const int pos,
3394 const cpl_imagelist* offs,
unsigned mode,
3395 double avg_on1,
double avg_on2,
3396 double avg_off1,
double avg_off2,
3397 double sig_off_dif,
int c_ndit,
3398 double autocorr, cpl_image* on_dif,
3399 cpl_table* gain_table)
3404 double avg_on_dif, sig_on_dif;
3405 irplib_ksigma_clip(on_dif, 1, 1, cpl_image_get_size_x(on_dif),
3406 cpl_image_get_size_y(on_dif), kappa, nclip, 1e-5,
3407 &avg_on_dif, &sig_on_dif);
3409 cpl_table_set_double(gain_table,
"SIG_ON_DIF", pos,
3411 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3412 double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
3415 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
3418 = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
3422 const double gain = double_adu / (c_ndit * sigma);
3424 const double gain_corr = gain / (autocorr);
3426 skip_if(cpl_table_set_double(gain_table,
"GAIN", pos, gain));
3428 cpl_table_set_double(gain_table,
"GAIN_CORR", pos,
3432 skip_if(cpl_table_set_double(gain_table,
"AUTOCORR", pos, autocorr));
3433 skip_if(cpl_table_set_double(gain_table,
"ADU", pos, double_adu / 2));
3436 cpl_table_set_double(gain_table,
"Y_FIT", pos,
3437 c_ndit * sig_on_dif * sig_on_dif));
3439 cpl_table_set_double(gain_table,
"Y_FIT_CORR", pos,
3440 c_ndit * sig_on_dif * sig_on_dif));
3441 skip_if(cpl_table_set_double(gain_table,
"X_FIT", pos, double_adu));
3443 cpl_table_set_double(gain_table,
"X_FIT_CORR", pos,
3444 double_adu / autocorr));
3448 return cpl_error_get_code();
3452detmon_gain_prepare_autocorr(
unsigned mode,
const int pos,
3453 int m,
int n, cpl_imagelist* diff_flats,
3454 cpl_image* on_dif, cpl_imagelist* autocorr_images)
3456 double autocorr = 1.0;
3458 if (mode & IRPLIB_GAIN_WITH_AUTOCORR) {
3460 cpl_image * diff = cpl_image_duplicate(on_dif);
3461 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
3463 if (autocorr_images) {
3464 cpl_image * corr = NULL;
3465 autocorr = detmon_autocorr_factor(on_dif, &corr, m, n);
3467 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
3470 detmon_lg_add_empty_image(autocorr_images, pos);
3474 autocorr = detmon_autocorr_factor(on_dif, NULL, m, n);
3476 autocorr = isnan(autocorr) ? 1.0 : autocorr;
3484detmon_gain_prepare_table(
const cpl_imagelist* offs,
unsigned mode,
int llx,
3485 int lly,
int urx,
int ury,
double kappa,
int nclip,
3486 double std,
const int pos,
3487 cpl_table* gain_table,
double* avg_off2,
3488 double* sig_off_dif)
3490 double avg_off1 = 0.0;
3497 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3500 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3501 llx, lly, urx, ury, kappa, nclip, 1e-5,
3503 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF", pos, avg_off1));
3506 else if ((mode & IRPLIB_GAIN_NO_COLLAPSE)
3507 || (pos == 0 && mode & IRPLIB_GAIN_COLLAPSE)) {
3508 cpl_image * off_dif = NULL;
3511 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3512 llx, lly, urx, ury, kappa, nclip, 1e-5,
3514 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3516 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 1),
3517 llx, lly, urx, ury, kappa, nclip, 1e-5,
3519 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3520 off_dif = detmon_subtract_create_window(
3521 cpl_imagelist_get_const(offs, 0),
3522 cpl_imagelist_get_const(offs, 1), llx, lly, urx, ury);
3523 skip_if(off_dif == NULL);
3524 irplib_ksigma_clip(off_dif, 1, 1, cpl_image_get_size_x(off_dif),
3525 cpl_image_get_size_y(off_dif), kappa, nclip, 1e-5,
3526 &avg_off_dif, sig_off_dif);
3527 cpl_image_delete(off_dif);
3529 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3532 else if (pos > 0 && (mode & IRPLIB_GAIN_COLLAPSE)) {
3535 avg_off1 = cpl_table_get_double(gain_table,
"MEAN_OFF1", 0, &status);
3536 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3537 *avg_off2 = cpl_table_get_double(gain_table,
"MEAN_OFF2", 0, &status);
3538 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3539 *sig_off_dif = cpl_table_get_double(gain_table,
"SIG_OFF_DIF", 0,
3542 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3587static cpl_error_code
3588detmon_gain_table_fill_row(cpl_table * gain_table,
3589 double c_dit,
int c_ndit,
3590 cpl_imagelist * autocorr_images,
3591 cpl_imagelist * diff_flats,
3592 const cpl_imagelist * ons,
3593 const cpl_imagelist * offs,
3594 double kappa,
int nclip,
3595 int llx,
int lly,
int urx,
int ury,
3597 double gain_threshold,
3598 int pos,
unsigned mode,
int* rows_gain_affected)
3600 const cpl_image *image;
3601 cpl_image *on_dif = NULL;
3603 double avg_on1, avg_on2;
3604 double avg_off1, avg_off2;
3607 cpl_table_set(gain_table,
"FLAG", pos, 1);
3608 if (mode & IRPLIB_GAIN_NIR)
3610 cpl_table_set(gain_table,
"DIT", pos, c_dit);
3611 cpl_table_set(gain_table,
"NDIT", pos, c_ndit);
3612 }
else if (mode & IRPLIB_GAIN_OPT)
3614 cpl_table_set(gain_table,
"EXPTIME", pos, c_dit);
3617 cpl_msg_error(cpl_func,
"Mandatory mode (OPT or NIR) not provided");
3620 if(*rows_gain_affected == 0)
3622 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3623 cpl_table_set(gain_table,
"FLAG", pos, 0);
3624 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3629 detmon_lg_add_empty_image(diff_flats, pos);
3631 if (autocorr_images)
3633 detmon_lg_add_empty_image(autocorr_images, pos);
3636 return cpl_error_get_code();
3638 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3639 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3640 nclip, 1e-5, &avg_on1, &std));
3641 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3642 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3643 nclip, 1e-5, &avg_on2, &std));
3646 (avg_on1 > gain_threshold) ||
3647 (avg_on2 > gain_threshold)
3653 if ( (avg_on1 > gain_threshold) || (avg_on2 > gain_threshold) )
3655 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the gain_theshold parameter, "
3656 "the frames would not be taken into calculation");
3658 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3659 avg_on1, avg_on2, gain_threshold);
3662 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3663 cpl_table_set(gain_table,
"FLAG", pos, 0);
3664 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3669 detmon_lg_add_empty_image(diff_flats, pos);
3671 if (autocorr_images)
3673 detmon_lg_add_empty_image(autocorr_images, pos);
3676 *rows_gain_affected = 0;
3684 *rows_gain_affected = 1;
3685 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON1", pos, avg_on1));
3686 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON2", pos, avg_on2));
3689 detmon_subtract_create_window(cpl_imagelist_get_const(ons, 0),
3690 cpl_imagelist_get_const(ons, 1),
3691 llx, lly, urx, ury);
3692 skip_if(on_dif == NULL);
3694 autocorr = detmon_gain_prepare_autocorr(mode, pos, m, n,
3695 diff_flats, on_dif, autocorr_images);
3697 avg_off1 = detmon_gain_prepare_table(offs, mode, llx, lly, urx, ury,
3698 kappa, nclip, std, pos, gain_table, &avg_off2,
3701 detmon_gain_compute_qc(kappa, nclip, pos, offs, mode,
3702 avg_on1, avg_on2, avg_off1, avg_off2,
3703 sig_off_dif, c_ndit, autocorr, on_dif,
3708 cpl_image_delete(on_dif);
3710 return cpl_error_get_code();
3737static cpl_error_code
3738detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
3739 cpl_imagelist * diff_flats,
3740 const cpl_imagelist * ons,
3741 double kappa,
int nclip,
3742 int llx,
int lly,
int urx,
int ury,
3743 double saturation_limit,
3744 const int pos,
unsigned mode,
int* rows_linear_affected)
3746 const cpl_image *image;
3748 double avg_on1, avg_on2;
3751 if(*rows_linear_affected == 0)
3753 cpl_msg_info(cpl_func,
"For linearity skip the frame #%d", pos + 1);
3754 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3758 detmon_lg_add_empty_image(diff_flats, pos);
3760 if (autocorr_images)
3762 detmon_lg_add_empty_image(autocorr_images, pos);
3765 return cpl_error_get_code();
3767 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3768 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3769 nclip, 1e-5, &avg_on1, &std));
3770 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3771 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3772 nclip, 1e-5, &avg_on2, &std));
3775 (avg_on1 > saturation_limit) ||
3776 (avg_on2 > saturation_limit)
3782 if ( (avg_on1 > saturation_limit) || (avg_on2 > saturation_limit) )
3784 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the saturation_limit parameter, "
3785 "the frames would not be taken into calculation");
3787 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3788 avg_on1, avg_on2, saturation_limit);
3791 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3792 *rows_linear_affected = 0;
3799 return cpl_error_get_code();
3815detmon_bpixs(
const cpl_imagelist * coeffs,
3822 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
3829 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
3830 cpl_image_get_size_y(first));
3832 cpl_image *bpm = NULL;
3835 int size = cpl_imagelist_get_size(coeffs);
3838 bpm = cpl_image_new(cpl_image_get_size_x(first),
3839 cpl_image_get_size_y(first),
3844 for(
int i = 0; i < size; i++) {
3845 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
3847 cpl_stats* stats = cpl_stats_new_from_image(cur_coeff,
3848 CPL_STATS_MEAN | CPL_STATS_STDEV);
3849 double cur_mean = cpl_stats_get_mean(stats);
3850 double cur_stdev = cpl_stats_get_stdev(stats);
3852 double lo_cut = cur_mean - kappa * cur_stdev;
3853 double hi_cut = cur_mean + kappa * cur_stdev;
3855 cpl_mask* cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
3856 cpl_mask_not(cur_mask);
3859 cpl_image* cur_image = cpl_image_new_from_mask(cur_mask);
3860 double p = pow(2, i);
3861 cpl_image_power(cur_image, p);
3862 cpl_image_add(bpm, cur_image);
3863 cpl_image_delete(cur_image);
3866 cpl_mask_or(mask, cur_mask);
3868 cpl_mask_delete(cur_mask);
3869 cpl_stats_delete(stats);
3873 bpm = cpl_image_new_from_mask(mask);
3876 *nbpixs = cpl_mask_count(mask);
3878 cpl_mask_delete(mask);
4005detmon_autocorr_factor(
const cpl_image * image,
4006 cpl_image ** autocorr_image,
int m,
int n)
4008 cpl_image * mycorr_image = NULL;
4009 double autocorr = 0;
4012 mycorr_image = detmon_image_correlate(image, image, m, n);
4014 if (cpl_error_get_code() == CPL_ERROR_UNSUPPORTED_MODE)
4016 cpl_msg_warning(cpl_func,
"FFTW is not supported by CPL, autocorrelation "
4017 "would be computed using internal implementation");
4020 cpl_image_delete(mycorr_image);
4021 mycorr_image = detmon_autocorrelate(image, m, n);
4023 if(mycorr_image == NULL) {
4027 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
4029 autocorr = cpl_image_get_flux(mycorr_image);
4031 if (autocorr_image) *autocorr_image = mycorr_image;
4032 else cpl_image_delete(mycorr_image);
4037static cpl_propertylist*
4038detmon_lg_extract_qclist_4plane(cpl_propertylist* linc_qclist,
const int ip)
4041 cpl_propertylist* sub_set=NULL;
4044 sub_set=cpl_propertylist_new();
4045 qc_key=cpl_sprintf(
"QC LIN COEF%d",ip);
4046 cpl_propertylist_copy_property_regexp(sub_set,linc_qclist,qc_key,0);
4063static cpl_error_code
4064detmon_lg_extract_extention_header(cpl_frameset* frameset,
4065 cpl_propertylist* gaint_qclist,
4066 cpl_propertylist* lint_qclist,
4067 cpl_propertylist* linc_qclist,
4068 cpl_propertylist* bpm_qclist,
4072 cpl_propertylist * xplist = NULL;
4074 const char * filename =
4075 cpl_frame_get_filename(cpl_frameset_get_position(frameset, 0));
4077 xplist = cpl_propertylist_load_regexp(filename, whichext,
4078 "ESO DET|EXTNAME", 0);
4079 if (detmon_lg_config.exts >= 0)
4082 cpl_property* propExtname = NULL;
4083 propExtname = cpl_propertylist_get_property(xplist,
"EXTNAME");
4085 if (NULL != propExtname)
4087 propExtname = cpl_property_duplicate(propExtname);
4089 cpl_propertylist_delete(xplist);
4091 if (NULL != propExtname)
4093 xplist = cpl_propertylist_new();
4094 cpl_propertylist_append_property(xplist, propExtname);
4095 cpl_property_delete(propExtname);
4100 cpl_propertylist_append(gaint_qclist, xplist);
4101 cpl_propertylist_append(lint_qclist, xplist);
4102 cpl_propertylist_append(linc_qclist, xplist);
4103 cpl_propertylist_append(bpm_qclist, xplist);
4104 cpl_propertylist_delete(xplist);
4107 return cpl_error_get_code();
4124static cpl_error_code
4125detmon_lg_save_table_with_pro_keys(cpl_table* table,
4127 cpl_propertylist* xheader,
4128 unsigned CPL_IO_MODE)
4131 cpl_propertylist* pro_keys=NULL;
4133 pro_keys=detmon_load_pro_keys(name_o);
4134 cpl_propertylist_append(xheader,pro_keys);
4136 if(CPL_IO_MODE==CPL_IO_DEFAULT) {
4137 cpl_propertylist * pri_head=cpl_propertylist_load(name_o,0);
4138 cpl_table_save(table, pri_head,xheader,name_o,
4140 cpl_propertylist_delete(pri_head);
4143 cpl_table_save(table,NULL,xheader,name_o,
4146 cpl_propertylist_delete(pro_keys);
4148 return cpl_error_get_code();
4160static cpl_error_code
4161detmon_lg_save_image_with_pro_keys(cpl_image* image,
4163 cpl_propertylist* xheader)
4166 cpl_propertylist* pro_keys=NULL;
4167 pro_keys=detmon_load_pro_keys(name_o);
4168 cpl_propertylist_append(xheader,pro_keys);
4170 cpl_image_save(image,name_o, CPL_BPP_IEEE_FLOAT,
4171 xheader,CPL_IO_EXTEND);
4172 cpl_propertylist_delete(pro_keys);
4175 return cpl_error_get_code();
4187static cpl_error_code
4188detmon_lg_save_imagelist_with_pro_keys(cpl_imagelist* imagelist,
4190 cpl_propertylist* xheader)
4193 cpl_propertylist* pro_keys=NULL;
4194 pro_keys=detmon_load_pro_keys(name_o);
4195 cpl_propertylist_append(xheader,pro_keys);
4197 cpl_imagelist_save(imagelist,name_o, CPL_BPP_IEEE_FLOAT,
4198 xheader,CPL_IO_EXTEND);
4200 cpl_propertylist_delete(pro_keys);
4203 return cpl_error_get_code();
4223static cpl_error_code
4224detmon_lg_save_plane(
const cpl_parameterlist * parlist,
4225 cpl_frameset* frameset,
4226 const cpl_frameset * usedframes,
4228 const char* recipe_name,
4229 cpl_propertylist* mypro_coeffscube,
4230 cpl_propertylist* linc_plane_qclist,
4231 const char* package,
4235 if(detmon_lg_config.exts == 0) {
4236 cpl_propertylist* plist=NULL;
4237 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4239 CPL_BPP_IEEE_FLOAT, recipe_name,
4240 mypro_coeffscube, NULL,
4242 plist=cpl_propertylist_load(NAME_O,0);
4243 cpl_image_save(plane,NAME_O, CPL_BPP_IEEE_FLOAT,
4244 plist,CPL_IO_DEFAULT);
4245 cpl_propertylist_delete(plist);
4247 }
else if(detmon_lg_config.exts > 0) {
4248 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4250 CPL_BPP_IEEE_FLOAT, recipe_name,
4251 mypro_coeffscube, NULL,
4254 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4258 cpl_dfs_save_image(frameset, NULL, parlist,
4259 usedframes,NULL, NULL,
4260 CPL_BPP_IEEE_FLOAT, recipe_name,
4261 mypro_coeffscube, NULL,
4263 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4266 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4272 return cpl_error_get_code();
4295static cpl_error_code
4296detmon_lg_save_cube(
const cpl_parameterlist * parlist,
4297 cpl_frameset* frameset,
4298 const cpl_frameset * usedframes,
4300 const char* recipe_name,
4301 cpl_propertylist* mypro_coeffscube,
4302 cpl_propertylist* linc_qclist,
4303 const char* package,
4305 cpl_imagelist* coeffs)
4308 if(detmon_lg_config.exts == 0) {
4309 cpl_propertylist_append(mypro_coeffscube, linc_qclist);
4310 detmon_lg_dfs_save_imagelist
4311 (frameset, parlist, usedframes, coeffs,
4312 recipe_name, mypro_coeffscube, package,
4314 }
else if(detmon_lg_config.exts > 0) {
4315 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4317 CPL_BPP_IEEE_FLOAT, recipe_name,
4318 mypro_coeffscube, NULL,
4321 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4325 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4327 CPL_BPP_IEEE_FLOAT, recipe_name,
4328 mypro_coeffscube, NULL,
4331 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4333 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4336 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4338 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4342 return cpl_error_get_code();
4346detmon_lg_set_paf_name_and_header(cpl_frame* ref_frame,
4347 int flag_sets,
int which_set,
4349 const char* paf_suf,
4350 cpl_propertylist** plist)
4352 char * paf_name=NULL;
4354 if(detmon_lg_config.exts >= 0)
4356 *plist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4357 detmon_lg_config.exts);
4361 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4365 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4366 detmon_lg_config.pafname, paf_suf,which_set);
4371 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4377 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4378 detmon_lg_config.pafname, paf_suf,whichext);
4382 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4383 detmon_lg_config.pafname,paf_suf,
4384 which_set, whichext);
4393detmon_lg_set_paf_name_and_header_ext(cpl_frame* ref_frame,
4394 int flag_sets,
int which_set,
4396 const char* paf_suf,
4397 cpl_propertylist** plist)
4399 char* paf_name=NULL;
4401 if(detmon_lg_config.exts >= 0)
4403 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4404 detmon_lg_config.exts);
4408 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4411 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4412 detmon_lg_config.pafname, paf_suf,which_set);
4416 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4420 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4421 detmon_lg_config.pafname, paf_suf,whichext);
4424 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4425 detmon_lg_config.pafname,paf_suf,
4426 which_set, whichext);
4433static cpl_error_code
4434detmon_lg_save_paf_product(cpl_frame* ref_frame,
int flag_sets,
4435 int which_set,
int whichext,
4436 const char* pafregexp,
4437 const char* procatg,
4438 const char* pipeline_name,
4439 const char* recipe_name,
4440 const char* paf_suf,
4441 cpl_propertylist* qclist,
4446 char* paf_name=NULL;
4447 cpl_propertylist* plist=NULL;
4448 cpl_propertylist* paflist = NULL;
4449 cpl_propertylist* mainplist=NULL;
4451 mainplist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0);
4453 paf_name=detmon_lg_set_paf_name_and_header(ref_frame,flag_sets,
4457 paf_name=detmon_lg_set_paf_name_and_header_ext(ref_frame,flag_sets,
4463 paflist = cpl_propertylist_new();
4464 cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,procatg);
4467 cpl_propertylist_copy_property_regexp(paflist, plist,pafregexp, 0);
4468 cpl_propertylist_copy_property_regexp(paflist, mainplist,pafregexp, 0);
4469 cpl_propertylist_append(paflist,qclist);
4472 cpl_dfs_save_paf(pipeline_name, recipe_name,paflist,paf_name);
4475 cpl_propertylist_delete(mainplist);
4476 cpl_propertylist_delete(paflist);
4477 cpl_propertylist_delete(plist);
4480 return cpl_error_get_code();
4517static cpl_error_code
4518detmon_lg_save(
const cpl_parameterlist * parlist,
4519 cpl_frameset * frameset,
4520 const char *recipe_name,
4521 const char *pipeline_name,
4522 const char *pafregexp,
4523 const cpl_propertylist * pro_lintbl,
4524 const cpl_propertylist * pro_gaintbl,
4525 const cpl_propertylist * pro_coeffscube,
4526 const cpl_propertylist * pro_bpm,
4527 const cpl_propertylist * pro_corr,
4528 const cpl_propertylist * pro_diff,
4529 const char *package,
4530 cpl_imagelist * coeffs,
4531 cpl_table * gain_table,
4532 cpl_table * linear_table,
4534 cpl_imagelist * autocorr_images,
4535 cpl_imagelist * diff_flats,
4536 cpl_propertylist * gaint_qclist,
4537 cpl_propertylist * lint_qclist,
4538 cpl_propertylist * linc_qclist,
4539 cpl_propertylist * bpm_qclist,
4540 const int flag_sets,
4541 const int which_set,
4542 const cpl_frameset * usedframes,
4546 cpl_frame *ref_frame;
4547 cpl_propertylist *plist = NULL;
4548 cpl_propertylist *mainplist = NULL;
4554 cpl_propertylist * xplist = NULL;
4556 cpl_propertylist* linc_plane_qclist=NULL;
4557 cpl_image* plane=NULL;
4559 char* pcatg_plane=NULL;
4561 cpl_propertylist * mypro_lintbl =
4562 cpl_propertylist_duplicate(pro_lintbl);
4563 cpl_propertylist * mypro_gaintbl =
4564 cpl_propertylist_duplicate(pro_gaintbl);
4565 cpl_propertylist * mypro_coeffscube =
4566 cpl_propertylist_duplicate(pro_coeffscube);
4567 cpl_propertylist * mypro_bpm =
4568 cpl_propertylist_duplicate(pro_bpm);
4569 cpl_propertylist * mypro_corr =
4570 cpl_propertylist_duplicate(pro_corr);
4571 cpl_propertylist * mypro_diff =
4572 cpl_propertylist_duplicate(pro_diff);
4574 const char * procatg_lintbl =
4575 cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
4577 const char * procatg_gaintbl =
4578 cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
4580 const char * procatg_coeffscube =
4581 cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
4582 const char * procatg_bpm =
4583 cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
4587 detmon_lg_extract_extention_header(frameset,gaint_qclist,lint_qclist,
4588 linc_qclist,bpm_qclist,whichext);
4593 ref_frame = cpl_frameset_get_position(frameset, 0);
4595 skip_if((mainplist =
4596 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4602 cpl_msg_info(cpl_func,
"Write the LINEARITY TABLE");
4605 NAME_O=cpl_sprintf(
"%s_linearity_table.fits", recipe_name);
4607 NAME_O=cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name,
4611 if (detmon_lg_config.exts >= 0) {
4613 cpl_propertylist_append(mypro_lintbl, lint_qclist);
4614 skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,
4615 linear_table,NULL, recipe_name,
4616 mypro_lintbl, NULL, package, NAME_O));
4618 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4619 lint_qclist,CPL_IO_DEFAULT);
4624 skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL,
4625 linear_table,lint_qclist, recipe_name,
4626 mypro_lintbl,NULL, package, NAME_O));
4627 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4628 lint_qclist,CPL_IO_DEFAULT);
4635 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4636 lint_qclist,CPL_IO_EXTEND);
4639 irplib_free(&NAME_O);
4643 cpl_msg_info(cpl_func,
"Write the GAIN TABLE");
4646 NAME_O=cpl_sprintf(
"%s_gain_table.fits", recipe_name);
4648 NAME_O=cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name,
4652 if (detmon_lg_config.exts >= 0)
4656 cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
4657 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
4658 gain_table,NULL, recipe_name, mypro_gaintbl,
4659 NULL, package, NAME_O));
4660 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4661 gaint_qclist,CPL_IO_DEFAULT);
4669 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
4670 gaint_qclist, recipe_name, mypro_gaintbl,
4671 NULL, package, NAME_O));
4672 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4673 gaint_qclist,CPL_IO_DEFAULT);
4679 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4680 gaint_qclist,CPL_IO_EXTEND);
4684 if(detmon_lg_config.pix2pix)
4690 cpl_msg_info(cpl_func,
"Write the COEFFS FITS");
4691 irplib_free(&NAME_O);
4694 PREF_O=cpl_sprintf(
"%s_coeffs_cube", recipe_name);
4697 PREF_O=cpl_sprintf(
"%s_coeffs_cube_set%02d",
4698 recipe_name, which_set);
4700 if (detmon_lg_config.split_coeffs == 0) {
4701 NAME_O=cpl_sprintf(
"%s.fits", PREF_O);
4706 if(detmon_lg_config.split_coeffs != 0){
4709 nb_images = cpl_imagelist_get_size(coeffs);
4710 for(ip=0;ip<nb_images;ip++) {
4711 NAME_O=cpl_sprintf(
"%s_P%d.fits", PREF_O,ip);
4712 pcatg_plane=cpl_sprintf(
"COEFFS_CUBE_P%d",ip);
4713 cpl_propertylist_delete(mypro_coeffscube);
4714 mypro_coeffscube=cpl_propertylist_duplicate(pro_coeffscube);
4715 cpl_propertylist_set_string(mypro_coeffscube,CPL_DFS_PRO_CATG,
4717 linc_plane_qclist=detmon_lg_extract_qclist_4plane(linc_qclist,ip);
4718 cpl_propertylist_append(mypro_coeffscube, linc_plane_qclist);
4719 plane=cpl_imagelist_get(coeffs,ip);
4720 detmon_lg_save_plane(parlist,frameset,usedframes,whichext,
4721 recipe_name,mypro_coeffscube,
4722 linc_plane_qclist,package,NAME_O,plane);
4724 if(NULL!=linc_plane_qclist) {
4725 cpl_propertylist_delete(linc_plane_qclist);
4727 irplib_free(&NAME_O);
4732 detmon_lg_save_cube(parlist,frameset,usedframes,whichext,
4733 recipe_name,mypro_coeffscube,
4734 linc_qclist,package,NAME_O,coeffs);
4740 cpl_msg_info(cpl_func,
"Write the BAD PIXEL MAP");
4741 irplib_free(&NAME_O);
4745 NAME_O=cpl_sprintf(
"%s_bpm.fits", recipe_name);
4748 NAME_O=cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, which_set);
4753 if(detmon_lg_config.exts == 0) {
4754 cpl_propertylist_append(mypro_bpm, bpm_qclist);
4755 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
4756 CPL_BPP_IEEE_FLOAT, recipe_name,
4757 mypro_bpm, NULL, package,
4760 else if(detmon_lg_config.exts > 0)
4762 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4763 CPL_BPP_IEEE_FLOAT, recipe_name,
4764 mypro_bpm, NULL, package,
4766 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4772 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4773 CPL_BPP_IEEE_FLOAT, recipe_name,
4774 mypro_bpm, NULL, package,
4776 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4779 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4784 if(detmon_lg_config.intermediate)
4789 cpl_msg_info(cpl_func,
"Write the AUTOCORRS FITS");
4790 nb_images = cpl_imagelist_get_size(autocorr_images);
4791 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
4792 for(i = 0; i < nb_images; i++)
4794 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_corr);
4796 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4798 if(i < cpl_table_get_nrow(linear_table))
4800 ddit = cpl_table_get_double(linear_table,
4801 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4803 cpl_array_delete(pnames);
4806 irplib_free(&NAME_O);
4809 NAME_O=cpl_sprintf(
"%s_autocorr_%d.fits", recipe_name, i);
4810 assert(NAME_O != NULL);
4813 NAME_O=cpl_sprintf(
"%s_autocorr_%02d_set%02d.fits",
4814 recipe_name, i, which_set);
4815 assert(NAME_O != NULL);
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 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4823 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4824 recipe_name, pplist, NULL,
4827 detmon_lg_save_image_with_pro_keys(
4828 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4830 cpl_propertylist_delete(pextlist);
4832 if(detmon_lg_config.exts == 0)
4834 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4835 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
4836 cpl_imagelist_get(autocorr_images, i),
4838 recipe_name, pplist, NULL, package,
4844 cpl_propertylist* pextlist = cpl_propertylist_new();
4845 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4848 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4849 usedframes, NULL,NULL,
4850 CPL_BPP_IEEE_FLOAT, recipe_name,
4854 detmon_lg_save_image_with_pro_keys(
4855 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4860 detmon_lg_save_image_with_pro_keys(
4861 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4863 cpl_propertylist_delete(pextlist);
4865 cpl_propertylist_delete (pplist);
4867 irplib_free(&NAME_O);
4876 cpl_msg_info(cpl_func,
"Write the DIFFS FITS");
4878 for(i = 0; i < nb_images; i++)
4880 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_diff);
4882 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4884 if(i < cpl_table_get_nrow(linear_table))
4886 ddit = cpl_table_get_double(linear_table,
4887 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4889 cpl_array_delete(pnames);
4894 NAME_O=cpl_sprintf(
"%s_diff_flat_%d.fits", recipe_name, i);
4897 NAME_O=cpl_sprintf(
"%s_diff_flat_%d_set%02d.fits",
4898 recipe_name, i, which_set);
4901 if(detmon_lg_config.exts > 0)
4903 cpl_propertylist* pextlist = cpl_propertylist_new();
4904 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4905 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT", ddit);
4906 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4907 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4909 mypro_diff, NULL,package, NAME_O));
4911 detmon_lg_save_image_with_pro_keys(
4912 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4914 cpl_propertylist_delete(pextlist);
4916 else if(detmon_lg_config.exts == 0)
4918 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4920 (frameset, NULL, parlist, usedframes, NULL,
4921 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
4922 recipe_name, pplist, NULL, package,
4927 cpl_propertylist* pextlist = cpl_propertylist_new();
4928 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4931 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT",ddit);
4933 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4934 usedframes, NULL,NULL,
4935 CPL_BPP_IEEE_FLOAT, recipe_name,
4936 mypro_diff, NULL,package, NAME_O));
4938 detmon_lg_save_image_with_pro_keys(
4939 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4944 detmon_lg_save_image_with_pro_keys(
4945 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4948 cpl_propertylist_delete(pextlist);
4950 cpl_propertylist_delete(pplist);
4951 irplib_free(&NAME_O);
4959 cpl_msg_info(cpl_func,
"Write the PAF file(s)");
4961 if(detmon_lg_config.pafgen) {
4963 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4964 pafregexp,procatg_gaintbl,
4965 pipeline_name,recipe_name,
4966 "qc01",gaint_qclist,0);
4968 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4969 pafregexp,procatg_lintbl,
4970 pipeline_name,recipe_name,
4971 "qc02",lint_qclist,0);
4973 if(detmon_lg_config.pix2pix)
4976 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4979 pipeline_name,recipe_name,
4980 "qc03",linc_qclist,1);
4982 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4983 whichext,pafregexp,procatg_bpm,
4984 pipeline_name,recipe_name,
4985 "qc04",bpm_qclist,1);
4990 cpl_msg_info(cpl_func,
"exit");
4992 cpl_propertylist_delete(xplist);
4994 cpl_propertylist_delete(plist);
4998 irplib_free(&NAME_O);
5000 cpl_free(pcatg_plane);
5001 cpl_propertylist_delete(mainplist);
5002 cpl_propertylist_delete(mypro_lintbl);
5003 cpl_propertylist_delete(mypro_gaintbl);
5004 cpl_propertylist_delete(mypro_coeffscube);
5005 cpl_propertylist_delete(mypro_bpm);
5006 cpl_propertylist_delete(mypro_corr);
5007 cpl_propertylist_delete(mypro_diff);
5009 return cpl_error_get_code();
5022static cpl_error_code
5023detmon_opt_contamination(
const cpl_imagelist * ons,
5024 const cpl_imagelist * offs,
5026 cpl_propertylist * qclist)
5034 struct rect rects[5] = {
5035 (
struct rect){ detmon_lg_config.llx1,
5036 detmon_lg_config.lly1,
5037 detmon_lg_config.urx1,
5038 detmon_lg_config.ury1},
5039 (
struct rect){ detmon_lg_config.llx2,
5040 detmon_lg_config.lly2,
5041 detmon_lg_config.urx2,
5042 detmon_lg_config.ury2},
5043 (
struct rect){ detmon_lg_config.llx3,
5044 detmon_lg_config.lly3,
5045 detmon_lg_config.urx3,
5046 detmon_lg_config.ury3},
5047 (
struct rect){ detmon_lg_config.llx4,
5048 detmon_lg_config.lly4,
5049 detmon_lg_config.urx4,
5050 detmon_lg_config.ury4},
5051 (
struct rect){ detmon_lg_config.llx5,
5052 detmon_lg_config.lly5,
5053 detmon_lg_config.urx5,
5054 detmon_lg_config.ury5},
5057 for (
size_t i = 0; i < 5; i++) {
5058 cpl_image * dif_avg;
5059 const cpl_image * off2;
5062 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
5063 off2 = cpl_imagelist_get_const(offs, 0);
5065 off2 = cpl_imagelist_get_const(offs, 1);
5067 dif_avg = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
5068 cpl_imagelist_get_const(offs, 0),
5069 cpl_imagelist_get_const(ons, 1),
5076 median = cpl_image_get_median(dif_avg);
5077 cpl_image_delete(dif_avg);
5080 sprintf(kname, DETMON_QC_CONTAM
"%zd", i + 1);
5082 if(cpl_propertylist_has(qclist,kname)){
5083 skip_if(cpl_propertylist_update_double(qclist,kname,median));
5085 skip_if(cpl_propertylist_append_double(qclist,kname,median));
5086 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
5092 return cpl_error_get_code();
5151detmon_lg_dfs_set_groups(cpl_frameset * set,
5152 const char *tag_on,
const char *tag_off)
5164 int nframes = cpl_frameset_get_size(set);
5167 for(
int i = 0; i < nframes; i++) {
5168 cpl_frame* cur_frame = cpl_frameset_get_position(set, i);
5169 const char* tag = cpl_frame_get_tag(cur_frame);
5172 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
5173 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
5193static cpl_error_code
5194detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist ** coeffs_ptr,
5195 cpl_image **bpms_ptr)
5211 cpl_image* dummy_bpm = cpl_image_new(detmon_lg_config.nx,
5212 detmon_lg_config.ny,
5214 cpl_imagelist* dummy_coeffs = cpl_imagelist_new();
5216 int* db_p = cpl_image_get_data_int(dummy_bpm);
5217 int* rb_p = cpl_image_get_data_int(*bpms_ptr);;
5218 float** dcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5219 float** rcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5220 int dlength = detmon_lg_config.nx;
5222 int rlength = detmon_lg_config.urx - detmon_lg_config.llx + 1;
5223 for (
int i = 0; i <= detmon_lg_config.order; i++)
5225 cpl_image* dummy_coeff = cpl_image_new(detmon_lg_config.nx,
5226 detmon_lg_config.ny,
5229 cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
5230 dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
5231 rcs_p[i] = cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
5234 for (
int i = detmon_lg_config.lly - 1; i < detmon_lg_config.ury; i++)
5236 for (
int j = detmon_lg_config.llx - 1; j < detmon_lg_config.urx; j++)
5238 shift_idx=(i - detmon_lg_config.lly + 1) * rlength +
5239 j - detmon_lg_config.llx + 1;
5240 *(db_p + i * dlength + j) = *(rb_p + shift_idx);
5241 for (
int k = 0; k <= detmon_lg_config.order; k++)
5243 *(dcs_p[k] + i * dlength + j) =
5244 *(rcs_p[k] + (i - detmon_lg_config.lly + 1) * rlength +
5245 j - detmon_lg_config.llx + 1);
5249 cpl_imagelist_delete(*coeffs_ptr);
5250 cpl_image_delete(*bpms_ptr);
5251 *coeffs_ptr = dummy_coeffs;
5252 *bpms_ptr = dummy_bpm;
5256 return cpl_error_get_code();
5293#ifdef DETMON_USE_DETECTOR_SHOTNOISE_MODEL
5316static cpl_error_code
5317detmon_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
5318 const double ron, cpl_image ** ima_errs)
5320 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
5321 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
5322 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
5323 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
5325 *ima_errs = cpl_image_duplicate(ima_data);
5327 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
5331 cpl_image_divide_scalar(*ima_errs, gain);
5332 cpl_image_add_scalar(*ima_errs, ron * ron);
5333 cpl_image_power(*ima_errs, 0.5);
5335 return cpl_error_get_code();
5340detmon_compute_badpixmap(cpl_boolean opt_nir,
const int nsets,
5341 const cpl_table* linear_table,
5342 const cpl_imagelist* linearity_inputs,
int nbpixs,
5343 cpl_vector* x, cpl_propertylist* gaint_qclist,
5344 cpl_image** bpms_ptr)
5350 if (opt_nir == NIR) {
5351 x = cpl_vector_wrap(nsets,
5352 (
double *) cpl_table_get_data_double_const(linear_table,
5356 x = cpl_vector_wrap(nsets,
5357 (
double *) cpl_table_get_data_double_const(linear_table,
5361 int sz = cpl_imagelist_get_size(linearity_inputs);
5362 double kappa = detmon_lg_config.kappa;
5363 int niter = detmon_lg_config.niter;
5364 int llx = detmon_lg_config.llx;
5365 int urx = detmon_lg_config.urx;
5366 int lly = detmon_lg_config.lly;
5367 int ury = detmon_lg_config.ury;
5369 const cpl_image *ima;
5373 cpl_imagelist* errors = cpl_imagelist_new();
5395 cpl_imagelist* linearity_scaled = cpl_imagelist_new();
5397 gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
5401 gain = (gain < 0) ? 1 : gain;
5407 for (
int i = 0; i < sz; i++) {
5408 ima = cpl_imagelist_get_const(linearity_inputs, i);
5416 irplib_ksigma_clip(ima, 1, 1, urx - llx + 1,
5417 ury - lly + 1, kappa, niter, 1e-5, &avg,
5422 if (avg < detmon_lg_config.saturation_limit) {
5430 cpl_image_get_mad(ima, &dmad);
5431 err = cpl_image_duplicate(ima);
5432 cpl_image_multiply_scalar(err, 0);
5433 cpl_image_add_scalar(err, dmad * CPL_MATH_STD_MAD);
5443 cpl_imagelist_set(errors, err, i);
5451 cpl_imagelist_set(linearity_scaled,
5452 cpl_image_duplicate(ima), i));
5455 hdrl_imagelist* hil = hdrl_imagelist_create(linearity_scaled, errors);
5460 cpl_imagelist_delete(errors);
5462 double pval = 0.001;
5463 p = hdrl_bpm_fit_parameter_create_pval(1, pval);
5472 hdrl_bpm_fit_compute(p, hil, x, bpms_ptr);
5497 nbpixs = cpl_image_get_flux(*bpms_ptr);
5499 hdrl_imagelist_delete(hil);
5500 cpl_imagelist_delete(linearity_scaled);
5501 cpl_vector_unwrap((cpl_vector*) x);
5502 hdrl_parameter_delete(p);
5518 skip_if(*bpms_ptr == NULL);
5539static cpl_error_code
5540detmon_lg_reduce_all(
const cpl_table * linear_table,
5541 cpl_propertylist * gaint_qclist,
5542 cpl_propertylist * lint_qclist,
5543 cpl_propertylist * linc_qclist,
5544 cpl_propertylist * bpm_qclist,
5545 cpl_imagelist ** coeffs_ptr,
5546 cpl_image ** bpms_ptr,
5547 const cpl_imagelist * linearity_inputs,
5548 const cpl_table * gain_table,
5549 int which_ext, cpl_boolean opt_nir)
5553 const int linear_nsets = cpl_table_get_nrow(linear_table);
5554 const int gain_nsets = cpl_table_get_nrow(gain_table);
5556 cpl_polynomial *poly_linfit = NULL;
5557 cpl_image *fiterror = NULL;
5558 char * name_o1 = NULL;
5559 char * name_o2 = NULL;
5560 double * pcoeffs = NULL;
5561 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
5564 cpl_vector *x =NULL;
5565 const cpl_vector *y =NULL;
5568 const cpl_image * first = NULL;
5576 cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5577 cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5578 cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
5579 cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
5581 pcoeffs = cpl_malloc(
sizeof(
double)*(detmon_lg_config.order + 1));
5583 skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
5584 detmon_lg_config.method));
5585 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
5586 DETMON_QC_METHOD_C));
5589 if (!strcmp(detmon_lg_config.method,
"PTC")) {
5591 if (detmon_lg_config.exts >= 0) {
5592 cpl_msg_info(cpl_func,
5593 "Polynomial fitting for the GAIN (constant term method)");
5595 cpl_msg_info(cpl_func,
5596 "Polynomial fitting for the GAIN (constant term method)"
5597 " for extension nb %d", which_ext);
5599 skip_if(detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, gain_nsets));
5601 skip_if(detmon_lg_qc_med(gain_table, gaint_qclist, gain_nsets));
5606 if(detmon_lg_config.lamp_ok) {
5607 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
5608 detmon_lg_config.cr));
5609 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
5610 DETMON_QC_LAMP_FLUX_C));
5614 if(detmon_lg_config.autocorr == TRUE) {
5615 autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
5616 skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
5618 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
5619 DETMON_QC_AUTOCORR_C));
5621 if (detmon_lg_config.exts >= 0) {
5622 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix");
5624 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix"
5625 " for extension nb %d", which_ext);
5628 if(!detmon_lg_config.pix2pix) {
5629 const int order=detmon_lg_config.order;
5637 y = cpl_vector_wrap(linear_nsets,
5638 (
double *)cpl_table_get_data_double_const(linear_table,
5641 if (opt_nir == NIR) {
5642 x = cpl_vector_wrap(linear_nsets,
5643 (
double *)cpl_table_get_data_double_const(linear_table,
5646 x = cpl_vector_wrap(linear_nsets,
5647 (
double *)cpl_table_get_data_double_const(linear_table,
5651 if(x == NULL || y == NULL) {
5652 cpl_vector_unwrap((cpl_vector *)x);
5653 cpl_vector_unwrap((cpl_vector *)y);
5663 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
5664 poly_linfit = irplib_polynomial_fit_1d_create(x, y,order,&mse);
5666 if(order == cpl_vector_get_size(x) - 1) {
5667 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5671 if(poly_linfit == NULL) {
5672 cpl_vector_unwrap((cpl_vector *)x);
5673 cpl_vector_unwrap((cpl_vector *)y);
5679 min_val=cpl_vector_get_min(y);
5680 max_val=cpl_vector_get_max(y);
5682 cpl_vector_unwrap((cpl_vector *)x);
5683 cpl_vector_unwrap((cpl_vector *)y);
5685 for(deg = 0; deg <= order; deg++) {
5686 const double coeff =
5687 cpl_polynomial_get_coeff(poly_linfit, °);
5690 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
5691 assert(name_o != NULL);
5692 skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
5693 skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
5694 DETMON_QC_LIN_COEF_C));
5697 pcoeffs[deg] = coeff;
5699 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
5700 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
5701 DETMON_QC_ERRFIT_MSE_C));
5705 const int order=detmon_lg_config.order;
5707 y = cpl_vector_wrap(linear_nsets,
5708 (
double *)cpl_table_get_data_double_const(linear_table,
5713 x = cpl_vector_wrap(linear_nsets,
5714 (
double *)cpl_table_get_data_double_const(linear_table,
5717 x = cpl_vector_wrap(linear_nsets,
5718 (
double *)cpl_table_get_data_double_const(linear_table,
5723 first = cpl_imagelist_get_const(linearity_inputs, 0);
5724 sizex = cpl_image_get_size_x(first);
5725 sizey = cpl_image_get_size_y(first);
5726 vsize = cpl_vector_get_size(x);
5727 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
5729 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,order, FALSE,
5730 CPL_TYPE_FLOAT, fiterror);
5731 min_val=cpl_vector_get_min(y);
5732 max_val=cpl_vector_get_max(y);
5733 cpl_vector_unwrap((cpl_vector*)x);
5734 cpl_vector_unwrap((cpl_vector*)y);
5736 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
5737 "Failed polynomial fit");
5740 for(deg = 0; deg <= order; deg++)
5742 cpl_image *image = cpl_imagelist_get(*coeffs_ptr, deg);
5743 const double coeff = cpl_image_get_median(image);
5744 pcoeffs[deg] = coeff;
5746 name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", (
int)deg);
5747 name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", (
int)deg);
5748 assert(name_o1 != NULL);
5749 assert(name_o2 != NULL);
5750 skip_if(cpl_propertylist_append_double(linc_qclist, name_o1, coeff));
5751 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o1,
5752 DETMON_QC_LIN_COEF_C));
5755 skip_if(cpl_propertylist_append_double(linc_qclist, name_o2,
5756 cpl_image_get_stdev(image)));
5757 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o2,
5758 DETMON_QC_LIN_COEF_ERR_C));
5764 if(order == vsize - 1)
5766 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5767 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5769 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5770 DETMON_QC_ERRFIT_C));
5773 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5774 cpl_image_get_median(fiterror)));
5775 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5776 DETMON_QC_ERRFIT_C));
5780 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
5782 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
5783 DETMON_QC_COUNTS_MIN_C));
5784 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
5786 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
5787 DETMON_QC_COUNTS_MAX_C));
5788 skip_if(detmon_lg_lineff(pcoeffs,lint_qclist,detmon_lg_config.ref_level,
5789 detmon_lg_config.order));
5791 if (detmon_lg_config.exts >= 0)
5793 cpl_msg_info(cpl_func,
"Bad pixel detection");
5796 cpl_msg_info(cpl_func,
"Bad pixel detection"
5797 " for extension nb %d", which_ext);
5799 if(detmon_lg_config.pix2pix)
5803 nbpixs = detmon_compute_badpixmap(opt_nir, linear_nsets, linear_table,
5804 linearity_inputs, nbpixs, x,gaint_qclist, bpms_ptr);
5809 skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
5810 skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
5811 DETMON_QC_NUM_BPM_C));
5812 cpl_msg_info(cpl_func,
"stability=%g",detmon_lg_config.lamp_stability);
5813 if(detmon_lg_config.lamp_stability != 0.0)
5815 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
5816 detmon_lg_config.lamp_stability));
5817 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
5818 DETMON_QC_LAMP_STAB_C));
5821 if (!detmon_lg_config.wholechip && detmon_lg_config.pix2pix)
5823 detmon_lg_fits_coeffs_and_bpm2chip(coeffs_ptr,bpms_ptr);
5830 cpl_image_delete(fiterror);
5831 cpl_polynomial_delete(poly_linfit);
5835 return cpl_error_get_code();
5847static cpl_error_code
5848detmon_lg_lineff(
double * pcoeffs,
5849 cpl_propertylist * qclist,
5855 double residual, slope;
5858 cpl_polynomial * poly = cpl_polynomial_new(1);
5872 pcoeffs[0] -= ref_level;
5874 for (i = 2; i <= order; i++)
5877 for(j = 0; j < i; j++)
5879 pcoeffs[i] /= pcoeffs[1];
5885 for (deg = 0; deg <= order; deg++) {
5887 skip_if(cpl_polynomial_set_coeff(poly, °, pcoeffs[deg]));
5896 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
5898 if (slope <= 0.0 && residual >= 0.0) {
5899 cpl_msg_warning(cpl_func,
"Reference level (--ref_level) outside"
5900 " linearity range of the detector. Cannot compute"
5901 " linearity efficiency (QC.LINEFF).");
5906 cpl_error_code err = cpl_polynomial_solve_1d(poly, 0.0, &root, 1);
5911 if (err == CPL_ERROR_NONE)
5914 lineff = (root - ref_level) / ref_level;
5919 cpl_msg_warning(cpl_func,
5920 "Cannot compute linearity efficiency (QC.LINEFF)"
5921 "for the current combination "
5922 " of (--ref-level equal %d) and (--order equal %d) parameters. Try "
5923 "to decrease (--ref-level) value.", ref_level, order);
5926 cpl_msg_warning(cpl_func,
"DETMON_QC_LIN_EFF=%f",lineff );
5927 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
5929 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
5930 DETMON_QC_LIN_EFF_C));
5932 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
5934 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
5935 DETMON_QC_LIN_EFF_FLUX_C));
5939 cpl_polynomial_delete(poly);
5941 return cpl_error_get_code();
5952static cpl_error_code
5953detmon_lg_qc_ptc(
const cpl_table * gain_table,
5954 cpl_propertylist * qclist,
unsigned mode,
int rows_in_gain)
5957 cpl_polynomial *poly_fit = NULL;
5958 cpl_polynomial *poly_fit2 = NULL;
5960 const int nsets = rows_in_gain;
5962 cpl_vector *x = NULL;
5963 cpl_vector *y = NULL;
5965 cpl_errorstate prestate;
5967 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
5968 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
5970 x = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5972 y = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5974 skip_if(x == NULL || y == NULL);
5975 if (0 == detmon_lg_check_before_gain(x, y))
5979 cpl_vector_unwrap(x);
5983 cpl_vector_unwrap(y);
5985 return CPL_ERROR_NONE;
5988 poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
5989 skip_if(poly_fit == NULL);
5993 prestate = cpl_errorstate_get();
5994 coef = cpl_polynomial_get_coeff(poly_fit, &i);
5995 skip_if (!cpl_errorstate_is_equal(prestate) || coef==0);
5996 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
5997 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5998 DETMON_QC_CONAD_C));
6001 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
6003 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
6019 if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
6020 const cpl_vector *x2 =
6021 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT_CORR"));
6022 const cpl_vector *y2 =
6023 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
6025 if(x2 == NULL || y2 == NULL) {
6026 cpl_vector_unwrap((cpl_vector *)x2);
6027 cpl_vector_unwrap((cpl_vector *)y2);
6038 poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
6039 if(poly_fit2 == NULL) {
6040 cpl_vector_unwrap((cpl_vector *)x2);
6041 cpl_vector_unwrap((cpl_vector *)y2);
6043 cpl_msg_error(cpl_func,
"Error during polynomial fit, err[%s]", cpl_error_get_where());
6047 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
6048 cpl_vector_unwrap((cpl_vector *)x2);
6049 cpl_vector_unwrap((cpl_vector *)y2);
6050 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
6053 prestate = cpl_errorstate_get();
6054 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
6055 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
6056 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
6058 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
6060 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
6061 DETMON_QC_CONAD_CORR_C));
6063 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
6065 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
6066 DETMON_QC_GAIN_CORR_C));
6072 cpl_vector_unwrap(x);
6073 cpl_vector_unwrap(y);
6074 cpl_polynomial_delete(poly_fit);
6075 cpl_polynomial_delete(poly_fit2);
6077 return cpl_error_get_code();
6086static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y)
6088 const double TOLERANCE = 1e-37;
6089 double xmin = cpl_vector_get_min(x);
6090 double xmax = cpl_vector_get_max(x);
6091 double ymin = cpl_vector_get_min(y);
6092 double ymax = cpl_vector_get_max(y);
6093 double ystdev = cpl_vector_get_stdev(y);
6094 double xstdev = cpl_vector_get_stdev(x);
6096 if (fabs(xmax-xmin) < TOLERANCE &&
6097 fabs(ymax - ymin) < TOLERANCE &&
6098 xstdev < TOLERANCE &&
6101 cpl_msg_warning(cpl_func,
"An empty frame has been detected, linearity, coeffs, gain, FPN values will not be computed.");
6116static cpl_error_code
6117detmon_lg_qc_med(
const cpl_table * gain_table,
6118 cpl_propertylist * qclist,
int rows_in_gain)
6122 cpl_vector *x = NULL;
6123 cpl_vector *y = NULL;
6124 int check_result = 0;
6126 if (rows_in_gain) {};
6128 x = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
6129 y = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
6130 check_result = detmon_lg_check_before_gain(x, y);
6133 cpl_vector_unwrap(x);
6137 cpl_vector_unwrap(y);
6139 if (0 == check_result)
6141 return CPL_ERROR_NONE;
6144 gain=cpl_table_get_column_median(gain_table,
"GAIN");
6146 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
6148 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
6151 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
6152 cpl_table_get_column_stdev
6153 (gain_table,
"GAIN")));
6154 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
6155 DETMON_QC_GAIN_MSE_C));
6157 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
6158 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
6159 DETMON_QC_CONAD_C));
6162 gain=cpl_table_get_column_median(gain_table,
"GAIN_CORR");
6164 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
6166 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
6167 DETMON_QC_GAIN_CORR_C));
6170 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
6171 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
6172 DETMON_QC_CONAD_CORR_C));
6177 return cpl_error_get_code();
6191static cpl_error_code
6192detmon_lg_rescale(cpl_imagelist * to_rescale)
6195 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 0),
6196 detmon_lg_config.llx,
6197 detmon_lg_config.lly,
6198 detmon_lg_config.urx,
6199 detmon_lg_config.ury);
6201 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 1),
6202 detmon_lg_config.llx,
6203 detmon_lg_config.lly,
6204 detmon_lg_config.urx,
6205 detmon_lg_config.ury);
6209 if(fabs(med1 / med2 - 1) > 0.001) {
6211 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
6214 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
6220 return cpl_error_get_code();
6223static cpl_error_code
6224detmon_pair_extract_next(
const cpl_frameset * set,
6228 cpl_frameset ** pair,
6232 double dit_next = -100;
6233 cpl_size* selection;
6234 int nsets_extracted = 0;
6235 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6236 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6237 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6238 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6240 nsets_extracted = cpl_frameset_get_size(set);
6241 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6242 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6245 dit = dit_array[*next_element ];
6247 if (*next_element < nsets_extracted - 1)
6249 dit_next = dit_array[*next_element + 1 ];
6253 selection[iindex[*next_element] ] = 1;
6254 if (fabs(dit - dit_next) < tolerance)
6257 selection[iindex[*next_element + 1] ] = 1;
6262 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);
6266 cpl_frameset_delete(*pair);
6267 *pair = cpl_frameset_extract(set, selection, 1);
6270 cpl_free(selection);
6271 return cpl_error_get_code();
6274static cpl_error_code
6275detmon_single_extract_next(
const cpl_frameset * set,
6279 cpl_frameset ** pair)
6281 cpl_size* selection;
6282 int nsets_extracted = 0;
6283 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6284 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6285 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6286 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6288 nsets_extracted = cpl_frameset_get_size(set);
6289 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6290 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6293 selection[iindex[*next_element] ] = 1;
6296 cpl_frameset_delete(*pair);
6297 *pair = cpl_frameset_extract(set, selection, 1);
6299 cpl_free(selection);
6300 return cpl_error_get_code();
6398detmon_gain(
const cpl_imagelist * imlist_on,
6399 const cpl_imagelist * imlist_off,
6400 const cpl_vector * exptimes,
6401 const cpl_vector * ndit,
6411 cpl_propertylist * qclist,
6413 cpl_imagelist ** diff_imlist,
6414 cpl_imagelist ** autocorr_imlist)
6416 cpl_table * gain_table = NULL;
6417 cpl_imagelist * difflist = NULL;
6418 cpl_imagelist * autocorrlist = NULL;
6419 cpl_imagelist * c_onlist = NULL;
6420 cpl_imagelist * c_offlist = NULL;
6421 cpl_vector * diffdits = NULL;
6422 cpl_vector * diffndits = NULL;
6423 int rows_in_gain = 0;
6424 int ndiffdits, ndits;
6426 cpl_boolean opt_nir = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
6427 const char * method = mode & IRPLIB_GAIN_PTC ?
"PTC" :
"MED";
6429 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6430 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6431 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6432 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6435 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6436 skip_if(detmon_gain_table_create(gain_table, opt_nir));
6440 skip_if(detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,
6442 ndiffdits = cpl_vector_get_size(diffdits);
6444 ndits = cpl_vector_get_size(exptimes);
6447 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
6448 difflist = cpl_imagelist_new();
6449 autocorrlist = cpl_imagelist_new();
6452 if (mode & IRPLIB_GAIN_COLLAPSE) {
6453 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6454 c_offlist = cpl_imagelist_duplicate(imlist_off);
6455 skip_if(detmon_lg_rescale(c_offlist));
6457 c_offlist = (cpl_imagelist *) imlist_off;
6462 for (i = 0; i < ndiffdits; i++) {
6469 c_dit=cpl_vector_get(diffdits, i);
6472 c_ndit=(int)cpl_vector_get(diffndits, i);
6475 c_onlist = cpl_imagelist_new();
6478 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6479 c_offlist = cpl_imagelist_new();
6484 for(j = 0; j < ndits; j++) {
6485 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6495 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6496 const cpl_image * im =
6497 cpl_imagelist_get_const(imlist_on, j);
6498 im_on = cpl_image_duplicate(im);
6500 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6502 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6509 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6511 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6512 const cpl_image * im =
6513 cpl_imagelist_get_const(imlist_off, j);
6514 im_off = cpl_image_duplicate(im);
6517 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6519 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6526 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6527 skip_if (c_nons != c_noffs);
6530 skip_if (c_nons == 0 || c_nons % 2 != 0);
6533 if(mode & IRPLIB_GAIN_WITH_RESCALE) {
6534 skip_if(detmon_lg_rescale(c_onlist));
6535 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6536 skip_if(detmon_lg_rescale(c_offlist));
6542 int rows_affected = 1;
6543 skip_if(detmon_gain_table_fill_row(gain_table,
6547 c_offlist, kappa, nclip,
6549 xshift, yshift, 1E10, i,
6550 mode, &rows_affected));
6555 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6556 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6557 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6558 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6559 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6560 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6563 cpl_imagelist_unset(c_onlist, 0);
6565 cpl_imagelist_unset(c_onlist, 0);
6567 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6568 cpl_imagelist_unset(c_offlist, 0);
6570 cpl_imagelist_unset(c_offlist, 0);
6578 cpl_imagelist_delete(c_onlist);
6579 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6580 cpl_imagelist_delete(c_offlist);
6584 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
6585 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
6586 DETMON_QC_METHOD_C));
6589 if (mode & IRPLIB_GAIN_PTC) {
6590 skip_if(detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
6592 skip_if(detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
6595 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
6596 double autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
6597 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
6599 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
6600 DETMON_QC_AUTOCORR_C));
6603 if (diff_imlist != NULL) *diff_imlist = difflist;
6604 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
6608 cpl_vector_delete(diffdits);
6609 cpl_vector_delete(diffndits);
6614static cpl_error_code
6615detmon_gain_table_create(cpl_table * gain_table,
6616 const cpl_boolean opt_nir)
6618 if (opt_nir == NIR) {
6619 skip_if(cpl_table_new_column(gain_table,
"DIT", CPL_TYPE_DOUBLE));
6620 skip_if(cpl_table_new_column(gain_table,
"NDIT", CPL_TYPE_INT));
6622 skip_if(cpl_table_new_column(gain_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6624 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON1", CPL_TYPE_DOUBLE));
6625 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON2", CPL_TYPE_DOUBLE));
6626 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF1", CPL_TYPE_DOUBLE));
6627 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF2", CPL_TYPE_DOUBLE));
6628 skip_if(cpl_table_new_column(gain_table,
"SIG_ON_DIF", CPL_TYPE_DOUBLE));
6629 skip_if(cpl_table_new_column(gain_table,
"SIG_OFF_DIF", CPL_TYPE_DOUBLE));
6630 skip_if(cpl_table_new_column(gain_table,
"GAIN", CPL_TYPE_DOUBLE));
6631 skip_if(cpl_table_new_column(gain_table,
"AUTOCORR", CPL_TYPE_DOUBLE));
6632 skip_if(cpl_table_new_column(gain_table,
"GAIN_CORR", CPL_TYPE_DOUBLE));
6633 skip_if(cpl_table_new_column(gain_table,
"ADU", CPL_TYPE_DOUBLE));
6634 skip_if(cpl_table_new_column(gain_table,
"X_FIT", CPL_TYPE_DOUBLE));
6635 skip_if(cpl_table_new_column(gain_table,
"X_FIT_CORR", CPL_TYPE_DOUBLE));
6636 skip_if(cpl_table_new_column(gain_table,
"Y_FIT", CPL_TYPE_DOUBLE));
6637 skip_if(cpl_table_new_column(gain_table,
"Y_FIT_CORR", CPL_TYPE_DOUBLE));
6638 skip_if(cpl_table_new_column(gain_table,
"FLAG", CPL_TYPE_INT));
6642 return cpl_error_get_code();
6645static cpl_error_code
6646detmon_lin_table_create(cpl_table * lin_table,
6647 const cpl_boolean opt_nir)
6649 if (opt_nir == NIR) {
6650 skip_if(cpl_table_new_column(lin_table,
"DIT", CPL_TYPE_DOUBLE));
6652 skip_if(cpl_table_new_column(lin_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6654 skip_if(cpl_table_new_column(lin_table,
"MED", CPL_TYPE_DOUBLE));
6655 skip_if(cpl_table_new_column(lin_table,
"MEAN", CPL_TYPE_DOUBLE));
6656 skip_if(cpl_table_new_column(lin_table,
"MED_DIT", CPL_TYPE_DOUBLE));
6657 skip_if(cpl_table_new_column(lin_table,
"MEAN_DIT", CPL_TYPE_DOUBLE));
6658 skip_if(cpl_table_new_column(lin_table,
"ADL", CPL_TYPE_DOUBLE));
6661 return cpl_error_get_code();
6665detmon_lg_find_dits(
const cpl_vector * exptimes,
6668 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6674 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
6678 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
6680 for (j = 0; j < ndits; j++) {
6681 if (fabs(cpl_vector_get(exptimes, i) -
6682 cpl_vector_get(dits, j)) > tolerance)
6685 if(ndiffs == ndits) {
6686 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
6691 cpl_vector_set_size(dits, ndits);
6699static cpl_error_code
6700detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
6701 const cpl_vector * vec_ndits,
6703 cpl_vector** diff_dits,
6704 cpl_vector** diff_ndits)
6712 * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6713 * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
6716 cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
6717 cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
6720 size=cpl_vector_get_size(exptimes);
6722 for(i = 1; i < size; i++) {
6724 for (j = 0; j < ndits; j++) {
6725 if (fabs(cpl_vector_get(exptimes, i) -
6726 cpl_vector_get(*diff_dits,j)) > tolerance)
6729 if(ndiffs == ndits) {
6730 cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
6731 cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
6736 cpl_vector_set_size(*diff_dits, ndits);
6737 cpl_vector_set_size(*diff_ndits, ndits);
6740 return cpl_error_get_code();
6830detmon_lin(
const cpl_imagelist * imlist_on,
6831 const cpl_imagelist * imlist_off,
6832 const cpl_vector * exptimes,
6842 cpl_propertylist * qclist,
6844 cpl_imagelist ** coeffs_cube,
6847 cpl_table * lin_table = NULL;
6848 cpl_imagelist * c_onlist = NULL;
6849 cpl_imagelist * c_offlist = NULL;
6850 cpl_vector * diffdits = NULL;
6851 cpl_imagelist * lin_inputs = NULL;
6852 cpl_polynomial * poly_linfit = NULL;
6853 cpl_image * fiterror = NULL;
6854 cpl_vector * vcoeffs = NULL;
6855 double * pcoeffs = NULL;
6856 int ndiffdits, ndits;
6858 cpl_boolean opt_nir = mode & IRPLIB_LIN_OPT ? OPT : NIR;
6859 const cpl_vector *x = NULL;
6860 const cpl_vector *y = NULL;
6862 const cpl_image * first = NULL;
6870 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6871 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6872 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6873 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6874 cpl_ensure(order > 0 , CPL_ERROR_ILLEGAL_INPUT, NULL);
6876 vcoeffs = cpl_vector_new(order + 1);
6877 pcoeffs = cpl_vector_get_data(vcoeffs);
6880 if (mode & IRPLIB_LIN_PIX2PIX) {
6881 cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
6882 cpl_ensure(bpm != NULL, CPL_ERROR_NULL_INPUT, NULL);
6883 lin_inputs = cpl_imagelist_new();
6887 lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6888 skip_if(detmon_lin_table_create(lin_table, opt_nir));
6892 diffdits = detmon_lg_find_dits(exptimes, tolerance);
6893 ndiffdits = cpl_vector_get_size(diffdits);
6895 ndits = cpl_vector_get_size(exptimes);
6925 if (mode & IRPLIB_LIN_COLLAPSE) {
6930 cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
6931 skip_if(collapse == NULL);
6933 c_offlist = cpl_imagelist_new();
6934 skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
6938 for (i = 0; i < ndiffdits; i++) {
6942 double c_dit = cpl_vector_get(diffdits, i);
6944 c_onlist = cpl_imagelist_new();
6947 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6948 c_offlist = cpl_imagelist_new();
6952 for(j = 0; j < ndits; j++) {
6953 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6963 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6964 const cpl_image * im =
6965 cpl_imagelist_get_const(imlist_on, j);
6966 im_on = cpl_image_duplicate(im);
6968 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6970 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6977 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6979 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6980 const cpl_image * im =
6981 cpl_imagelist_get_const(imlist_off, j);
6982 im_off = cpl_image_duplicate(im);
6985 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6987 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6994 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6995 skip_if (c_nons != c_noffs);
6998 skip_if (c_nons == 0 || c_nons % 2 != 0);
7001 if(mode & IRPLIB_LIN_WITH_RESCALE) {
7002 skip_if(detmon_lg_rescale(c_onlist));
7003 if (mode & IRPLIB_LIN_NO_COLLAPSE)
7004 skip_if(detmon_lg_rescale(c_offlist));
7011 skip_if(detmon_lin_table_fill_row(lin_table, c_dit,
7013 c_onlist, c_offlist,
7017 if (mode & IRPLIB_LIN_WITH_RESCALE) {
7018 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
7019 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
7020 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7021 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
7022 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
7025 cpl_imagelist_unset(c_onlist, 0);
7027 cpl_imagelist_unset(c_onlist, 0);
7029 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7030 cpl_imagelist_unset(c_offlist, 0);
7032 cpl_imagelist_unset(c_offlist, 0);
7040 cpl_imagelist_delete(c_onlist);
7041 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7042 cpl_imagelist_delete(c_offlist);
7046 skip_if(detmon_add_adl_column(lin_table, opt_nir));
7048 if(!(mode & IRPLIB_LIN_PIX2PIX)) {
7051 y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7052 (
double *)cpl_table_get_data_double_const(lin_table,
7054 if (opt_nir == NIR) {
7055 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7056 (
double *)cpl_table_get_data_double_const(lin_table,
"DIT"));
7058 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7059 (
double *)cpl_table_get_data_double_const(lin_table,
"EXPTIME"));
7061 if(x == NULL || y == NULL) {
7062 cpl_vector_unwrap((cpl_vector *)x);
7063 cpl_vector_unwrap((cpl_vector *)y);
7073 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
7074 poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
7076 if(order == cpl_vector_get_size(x) - 1) {
7077 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7081 if(poly_linfit == NULL) {
7082 cpl_vector_unwrap((cpl_vector *)x);
7083 cpl_vector_unwrap((cpl_vector *)y);
7088 cpl_vector_unwrap((cpl_vector *)x);
7089 cpl_vector_unwrap((cpl_vector *)y);
7091 for(deg = 0; deg <= order; deg++) {
7092 const double coeff =
7093 cpl_polynomial_get_coeff(poly_linfit, °);
7095 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
7096 assert(name_o != NULL);
7097 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
7098 skip_if(cpl_propertylist_set_comment(qclist,name_o,
7099 DETMON_QC_LIN_COEF_C));
7101 pcoeffs[deg] = coeff;
7103 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
7104 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7105 DETMON_QC_ERRFIT_MSE_C));
7109 if (opt_nir == NIR) {
7110 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7111 (
double *)cpl_table_get_data_double_const(lin_table,
7114 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7115 (
double *)cpl_table_get_data_double_const(lin_table,
7120 first = cpl_imagelist_get_const(lin_inputs, 0);
7121 sizex = cpl_image_get_size_x(first);
7122 sizey = cpl_image_get_size_y(first);
7124 vsize = cpl_vector_get_size(x);
7126 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
7129 cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
7130 order, FALSE, CPL_TYPE_FLOAT,
7133 cpl_vector_unwrap((cpl_vector*)x);
7134 irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
7135 "Failed polynomial fit");
7137 for(i = 0; i <= order; i++) {
7138 cpl_image *image = cpl_imagelist_get(*coeffs_cube, i);
7139 const double coeff = cpl_image_get_median(image);
7140 char * name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", i);
7141 char * name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", i);
7143 assert(name_o1 != NULL);
7144 assert(name_o2 != NULL);
7145 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
7146 skip_if(cpl_propertylist_set_comment(qclist,name_o1,
7147 DETMON_QC_LIN_COEF_C));
7150 skip_if(cpl_propertylist_append_double(qclist, name_o2,
7151 cpl_image_get_stdev(image)));
7152 skip_if(cpl_propertylist_set_comment(qclist,name_o2,
7153 DETMON_QC_LIN_COEF_ERR_C));
7158 if(order == vsize - 1) {
7159 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7160 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7162 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7163 DETMON_QC_ERRFIT_C));
7167 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7168 cpl_image_get_median(fiterror)));
7169 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7170 DETMON_QC_ERRFIT_C));
7175 skip_if(detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
7177 if(mode & IRPLIB_LIN_PIX2PIX) {
7179 *bpm = detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
7180 skip_if(*bpm == NULL);
7181 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
7183 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
7184 DETMON_QC_NUM_BPM_C));
7189 cpl_vector_delete(diffdits);
7190 cpl_polynomial_delete(poly_linfit);
7191 cpl_imagelist_delete(lin_inputs);
7192 cpl_vector_delete(vcoeffs);
7193 cpl_image_delete(fiterror);
7223static cpl_error_code
7224detmon_lin_table_fill_row(cpl_table * lin_table,
double c_dit,
7225 cpl_imagelist * linearity_inputs,
7226 const cpl_imagelist * ons,
7227 const cpl_imagelist * offs,
7236 cpl_image * extracted=NULL;
7238 cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
7239 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
7240 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
7242 if (mode & IRPLIB_LIN_PIX2PIX) {
7243 cpl_msg_debug(cpl_func,
"checking linearity inputs");
7244 cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
7248 if (mode & IRPLIB_LIN_NIR) {
7249 cpl_table_set(lin_table,
"DIT", pos, c_dit);
7250 }
else if (mode & IRPLIB_LIN_OPT) {
7251 cpl_table_set(lin_table,
"EXPTIME", pos, c_dit);
7253 cpl_msg_error(cpl_func,
"Mandatory mode not given");
7257 const cpl_image * off2;
7258 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
7259 off2 = cpl_imagelist_get_const(offs, 0);
7261 off2 = cpl_imagelist_get_const(offs, 1);
7263 extracted = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
7264 cpl_imagelist_get_const(offs, 0),
7265 cpl_imagelist_get_const(ons, 1),
7267 llx, lly, urx, ury);
7268 cpl_ensure_code(extracted != NULL, cpl_error_get_code());
7272 double median = cpl_image_get_median(extracted);
7273 double mean= cpl_image_get_mean(extracted);
7274 cpl_table_set(lin_table,
"MED", pos, median);
7275 cpl_table_set(lin_table,
"MEAN", pos, mean);
7277 cpl_table_set(lin_table,
"MED_DIT", pos, median / c_dit);
7278 cpl_table_set(lin_table,
"MEAN_DIT", pos, mean / c_dit);
7282 if(mode & IRPLIB_LIN_PIX2PIX) {
7283 cpl_error_code error = cpl_imagelist_set(linearity_inputs, extracted,
7285 cpl_ensure_code(!error, error);
7287 cpl_image_delete(extracted);
7290 return cpl_error_get_code();
7293static double irplib_calculate_total_noise_smooth(
const cpl_image* pimage,
7294 int pattern_x,
int pattern_y)
7296 cpl_image * p_tmp_image = 0;
7297 cpl_image * psmooth_image = 0;
7299 cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
7301 p_tmp_image = cpl_image_duplicate(pimage);
7302 cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
7303 cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
7304 psmooth_image = cpl_image_divide_create(pimage,p_tmp_image);
7305 ret_noise = irplib_calculate_total_noise(psmooth_image);
7306 cpl_mask_delete(mask);
7307 cpl_image_delete(psmooth_image);
7308 cpl_image_delete(p_tmp_image);
7312static double irplib_calculate_total_noise(
const cpl_image* pimage)
7314 double total_noise = -1;
7315 unsigned long max_bin_size = 1E5;
7316 const double hstart = cpl_image_get_min(pimage);
7317 const double hrange = cpl_image_get_max(pimage) - hstart;
7318 const unsigned long nbins = max_bin_size;
7321 irplib_hist * phist = 0;
7322 phist = irplib_hist_new();
7325 irplib_hist_init(phist, nbins, hstart, hrange);
7326 err = irplib_hist_fill(phist, pimage);
7327 if (err == CPL_ERROR_NONE)
7335 unsigned long n_bins = irplib_hist_get_nbins(phist);
7336 double start = irplib_hist_get_start(phist);
7337 double bin_size = irplib_hist_get_bin_size(phist);
7338 cpl_vector* pdata_vector = cpl_vector_new(n_bins);
7339 cpl_vector* ppos_vector = cpl_vector_new(n_bins);
7340 cpl_table* ptable = cpl_table_new(n_bins);
7341 cpl_table_new_column(ptable,
"bin", CPL_TYPE_DOUBLE);
7342 cpl_table_new_column(ptable,
"value", CPL_TYPE_DOUBLE);
7343 for(i = 0; i < n_bins; i++)
7345 unsigned int value = irplib_hist_get_value(phist, i);
7346 double dvalue = (double)(value);
7347 cpl_vector_set(pdata_vector, i, dvalue);
7348 cpl_vector_set(ppos_vector, i, start + i * bin_size);
7350 cpl_table_set(ptable,
"bin", i, start + i * bin_size);
7351 cpl_table_set(ptable,
"value", i, dvalue);
7353 err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
7354 if (err == CPL_ERROR_NONE)
7356 cpl_msg_info(cpl_func,
"FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
7360 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed Gaussian Fit, err msg [%s]", cpl_error_get_message());
7363 cpl_table_delete(ptable);
7364 cpl_vector_delete(ppos_vector);
7365 cpl_vector_delete(pdata_vector);
7369 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
7372 irplib_hist_delete(phist);
7377static double irplib_compute_err(
double gain,
double ron,
double FA)
7379 double int_gain = (gain * gain - 1) / 12;
7384 return sqrt(ron * ron + FA / gain + int_gain);
7387static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain ,
7388 FPN_METHOD fpn_method,
int smooth_size,
double* mse)
7390 cpl_image* im_diff = 0;
7391 const cpl_image* im_f1 = f1;
7392 cpl_image* im_inrange1 = 0;
7401 cpl_msg_warning(cpl_func,
"gain[%f]<0", gain);
7402 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7409 im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
7410 im_f1 = im_inrange1;
7412 FA = cpl_image_get_median(im_f1);
7419 cpl_msg_info(cpl_func,
"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
7420 s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
7423 cpl_msg_info(cpl_func,
"HISTOGRAM method is used for FPN");
7424 s_tot = irplib_calculate_total_noise(im_f1);
7429 cpl_msg_warning(cpl_func,
"fpn_method is not defined");
7438 cpl_msg_warning(cpl_func,
"Median flux on sum of flats<0");
7439 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7444 if ((s_tot * s_tot - FA / gain) > 0)
7446 s_fpn = sqrt(s_tot * s_tot - FA / gain);
7447 sr_fpn = s_fpn / FA;
7448 *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
7452 cpl_msg_warning(cpl_func,
"s_tot * s_tot < FA / gain");
7453 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7462 cpl_image_delete(im_diff);
7465 cpl_image_delete(im_inrange1);
7471static cpl_imagelist * irplib_load_fset_wrp(
const cpl_frameset * pframeset,
7472 cpl_type type ,
int whichext)
7476 return detmon_load_frameset_window(pframeset, type, 0, whichext,
7477 detmon_lg_config.llx,
7478 detmon_lg_config.lly,
7479 detmon_lg_config.urx,
7480 detmon_lg_config.ury,
7481 detmon_lg_config.nx,
7482 detmon_lg_config.ny);
7485static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset * pframeset,
7486 cpl_type type ,
int whichext)
7489 cpl_imagelist* offs = cpl_imagelist_new();
7490 detmon_lg_config.load_fset(pframeset, type, offs);
7495static cpl_error_code irplib_table_create_column(cpl_table* ptable,
7496 cpl_propertylist* plist)
7498 if (ptable && plist)
7500 int size = cpl_propertylist_get_size(plist);
7502 for (i = 0; i < size; i++)
7504 cpl_property* pprop = cpl_propertylist_get(plist,i);
7507 const char* pname = cpl_property_get_name(pprop);
7510 cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
7511 if (cpl_error_get_code() != CPL_ERROR_NONE)
7513 cpl_msg_warning(cpl_func,
"cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
7520 return cpl_error_get_code();
7523static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
7524 cpl_propertylist* plist,
int row)
7526 cpl_error_code err = CPL_ERROR_NONE;
7527 if (ptable && plist)
7529 int size = cpl_propertylist_get_size(plist);
7531 for (i = 0; i < size; i++)
7533 cpl_property* pprop = cpl_propertylist_get(plist,i);
7536 const char* pname = cpl_property_get_name(pprop);
7537 double value = cpl_property_get_double(pprop);
7540 cpl_table_set_double(ptable, pname, row, value);
7541 if (cpl_error_get_code() != CPL_ERROR_NONE)
7543 cpl_msg_warning(cpl_func,
"cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
7554cpl_error_code detmon_check_order(
const double *exptime,
int sz,
7555 double tolerance,
int order)
7572 }
while(fabs(exptime[i-1] - exptime[i]) < tolerance);
7573 }
while(i < sz - 1);
7575 if ( !( fabs(exptime[i-1] - exptime[i]) < tolerance ) ) nsets++;
7578 cpl_error_set_message(cpl_func,CPL_ERROR_INCOMPATIBLE_INPUT,
7579 "Not enough frames for the polynomial"
7580 " fitting. nsets = %d <= %d order",
7583 return cpl_error_get_code();
7586static cpl_error_code
7587detmon_lg_dfs_save_imagelist(
7588 cpl_frameset * frameset,
7589 const cpl_parameterlist * parlist,
7590 const cpl_frameset *usedframes,
7591 const cpl_imagelist *coeffs,
7592 const char *recipe_name,
7593 const cpl_propertylist *mypro_coeffscube,
7594 const char * package,
7595 const char * name_o)
7597 return(cpl_dfs_save_imagelist
7598 (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
7599 recipe_name, mypro_coeffscube, NULL, package,
7603static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos)
7605 const cpl_image* first = cpl_imagelist_get(imlist, 0);
7608 int x = cpl_image_get_size_x(first);
7609 int y = cpl_image_get_size_y(first);
7610 cpl_type type = cpl_image_get_type(first);
7611 cpl_image * blank = cpl_image_new(x, y, type);
7612 cpl_imagelist_set(imlist, blank, pos);
7617static cpl_error_code
7618detmon_lg_set_keyword_from_base_double(cpl_propertylist* pl,
7624 char* hkw = cpl_sprintf(
"%s %s", keyword_base, keyword_ext);
7625 char* hcm = cpl_sprintf(
"%s %s", comment_base, comment_ext);
7627 cpl_propertylist_append_double(pl, hkw, value);
7628 cpl_propertylist_set_comment(pl, hkw, hcm);
7633 return cpl_error_get_code();
7636static cpl_error_code
7637detmon_lg_set_keyword_from_insert_double(cpl_propertylist* pl,
7643 char* hkw = cpl_sprintf(keyword_base, keyword_ins);
7644 char* hcm = cpl_sprintf(comment_base, comment_ins);
7646 cpl_propertylist_append_double(pl, hkw, value);
7647 cpl_propertylist_set_comment(pl, hkw, hcm);
7652 return cpl_error_get_code();
7656detmon_lg_set_tag(cpl_frameset* set,
const char** tag_on,
const char** tag_off)
7661 ntag_old=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_OLD);
7662 ntag_new=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_NEW);
7664 *tag_on=DETMON_LG_ON_RAW_OLD;
7665 *tag_off=DETMON_LG_OFF_RAW_OLD;
7666 }
else if (ntag_new) {
7667 *tag_on=DETMON_LG_ON_RAW_NEW;
7668 *tag_off=DETMON_LG_OFF_RAW_NEW;
7670 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
7671 "Provide %s and %s (or %s and %s) input frames",
7672 DETMON_LG_ON_RAW_NEW,DETMON_LG_OFF_RAW_NEW,
7673 DETMON_LG_ON_RAW_OLD,DETMON_LG_OFF_RAW_OLD);
7677 return cpl_error_get_code();
7681detmon_lg_qc_params(cpl_table* linear_table, cpl_propertylist* lint_qclist,
7682 cpl_table* gain_table, cpl_propertylist* gaint_qclist,
7683 cpl_imagelist* coeffs, cpl_propertylist* linc_qclist,
7684 cpl_image* bpm, cpl_propertylist* bpm_qclist,
7685 const char * recipe_name) {
7687 char* qc_contam = NULL ;
7688 char* qc_contam_ref = cpl_sprintf(
"%s%01d", DETMON_QC_CONTAM, 5);
7690 cpl_msg_info(cpl_func,
"This is where I'll write the QC parameters");
7692 if (linear_table != NULL && lint_qclist != NULL) {
7694 if (cpl_propertylist_has(
7695 lint_qclist, qc_contam_ref)) {
7696 for (
int i=1; i<5; ++i) {
7697 qc_contam = cpl_sprintf(
"%s%01d", DETMON_QC_CONTAM, i);
7698 if (cpl_propertylist_has(lint_qclist, qc_contam_ref) &&
7699 cpl_propertylist_has(lint_qclist, qc_contam)) {
7700 cpl_propertylist_append_double(
7701 lint_qclist, cpl_sprintf(DETMON_QC_CONTAMi_NORM, i),
7702 cpl_propertylist_get_double(lint_qclist, qc_contam) /
7703 cpl_propertylist_get_double(lint_qclist, qc_contam_ref));
7704 cpl_propertylist_set_comment(
7705 lint_qclist, cpl_sprintf(DETMON_QC_CONTAMi_NORM, i),
7706 cpl_sprintf(DETMON_QC_CONTAMi_NORM_C, i)
7713 cpl_free(qc_contam);
7714 cpl_free(qc_contam_ref);
7715 return cpl_error_get_code();
7719detmon_lg_qc_params_global_gain(
const char * recipe_name,
int nsets) {
7720 cpl_msg_info(cpl_func,
"Going to update gain table for recipe %s, nsets=%d",
7721 recipe_name, nsets);
7724 cpl_error_code err ;
7726 fn = cpl_sprintf(
"%s_gain_table.fits", recipe_name) ;
7727 cpl_msg_info(cpl_func,
"Will be modifying %s", fn) ;
7728 err = detmon_lg_qc_params_global_gain_update(fn, recipe_name);
7732 for (j=0; j<nsets; ++j) {
7733 fn = cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name, j);
7734 cpl_msg_info(cpl_func,
"Will be modifying %s", fn);
7735 err = detmon_lg_qc_params_global_gain_update(fn, recipe_name);
7745detmon_lg_qc_params_global_gain_update(
const char * fn,
7746 const char * recipe_name) {
7747 cpl_msg_info(cpl_func,
"Now updating %s", fn);
7749 cpl_propertylist* phu = cpl_propertylist_load(fn, 0);
7750 cpl_propertylist** ehus = NULL;
7751 cpl_table** gain_tables = NULL;
7752 cpl_array* gains = NULL;
7753 cpl_array* conads = NULL ;
7754 cpl_frame* fr = cpl_frame_new();
7757 cpl_frame_set_filename(fr, fn);
7758 int nexts = cpl_frame_get_nextensions(fr);
7759 cpl_msg_info(cpl_func,
"Detected %d nexts", nexts);
7761 cpl_msg_warning(cpl_func,
"No extensions in %s, so no QC "
7762 "keywords to write", fn);
7763 cpl_msg_warning(cpl_func,
"Triggering goto cleanup");
7771 ehus = (cpl_propertylist**)cpl_malloc(nexts *
sizeof(cpl_propertylist*));
7772 gain_tables = (cpl_table**)cpl_malloc(nexts *
sizeof(cpl_table*));
7776 for (j=1; j <= nexts; j++) {
7777 cpl_msg_info(cpl_func,
"Loading EHU %d", j);
7778 ehus[j-1] = cpl_propertylist_load(fn, j);
7779 gain_tables[j-1] = cpl_table_load(fn, j, 1);
7784 cpl_msg_info(cpl_func,
"Populating data arrays");
7785 gains = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7786 conads = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7787 for (j=1; j <= nexts; j++) {
7788 cpl_msg_info(cpl_func,
" %d", j);
7789 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_GAIN)) {
7790 cpl_array_set(gains, j-1,
7791 cpl_propertylist_get_double(ehus[j-1],
7794 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_CONAD)) {
7795 cpl_array_set(conads, j-1,
7796 cpl_propertylist_get_double(ehus[j-1],
7800 cpl_msg_info(cpl_func,
"...populating complete!");
7802 cpl_propertylist_append_double(phu, DETMON_QC_GAIN_AVG,
7803 cpl_array_get_mean(gains));
7804 cpl_propertylist_set_comment(phu, DETMON_QC_GAIN_AVG,
7805 DETMON_QC_GAIN_AVG_C);
7807 cpl_propertylist_append_double(phu, DETMON_QC_GAIN_RMS,
7808 cpl_array_get_stdev(gains));
7809 cpl_propertylist_set_comment(phu, DETMON_QC_GAIN_RMS,
7810 DETMON_QC_GAIN_RMS_C);
7813 if (strcmp(recipe_name,
"detmon_opt_lg_mr") != 0) {
7816 cpl_propertylist_append_double(phu, DETMON_QC_CONAD_AVG,
7817 cpl_array_get_mean(conads));
7818 cpl_propertylist_set_comment(phu, DETMON_QC_CONAD_AVG,
7819 DETMON_QC_CONAD_AVG_C);
7821 cpl_propertylist_append_double(phu, DETMON_QC_CONAD_RMS,
7822 cpl_array_get_stdev(conads));
7823 cpl_propertylist_set_comment(phu, DETMON_QC_CONAD_RMS,
7824 DETMON_QC_CONAD_RMS_C);
7828 cpl_msg_info(cpl_func,
"Calculations complete!");
7832for (j=1; j<=nexts; ++j) {
7834 cpl_table_save(gain_tables[j-1], phu,
7835 ehus[j-1], fn, CPL_IO_CREATE);
7837 cpl_table_save(gain_tables[j-1], NULL,
7838 ehus[j-1], fn, CPL_IO_EXTEND);
7840 cpl_propertylist_delete(ehus[j-1]);
7841 cpl_table_delete(gain_tables[j-1]);
7856 cpl_msg_info(cpl_func,
"Cleaning up...");
7857 cpl_propertylist_delete(phu);
7861 cpl_free(gain_tables);
7863 cpl_frame_delete(fr);
7866 cpl_array_delete(conads);
7870 cpl_array_delete(gains);
7873 cpl_msg_info(cpl_func,
"...done!");
7875 return cpl_error_get_code();
7880detmon_lg_qc_params_global_lin(
const char * recipe_name,
int nsets) {
7881 cpl_msg_info(cpl_func,
"Going to update linearity table for "
7882 "recipe %s, nsets=%d",
7883 recipe_name, nsets);
7887 fn = cpl_sprintf(
"%s_linearity_table.fits", recipe_name) ;
7888 cpl_msg_info(cpl_func,
"Will be modifying %s", fn, recipe_name) ;
7889 detmon_lg_qc_params_global_lin_update(fn, recipe_name);
7893 for (j=0; j<nsets; ++j) {
7894 fn = cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name, j);
7895 cpl_msg_info(cpl_func,
"Will be modifying %s", fn);
7896 detmon_lg_qc_params_global_lin_update(fn, recipe_name);
7901 return cpl_error_get_code();
7906detmon_lg_qc_params_global_lin_update(
const char * fn,
7907 const char * recipe_name) {
7908 cpl_msg_info(cpl_func,
"Now updating %s", fn);
7910 cpl_propertylist* phu = cpl_propertylist_load(fn, 0);
7911 cpl_propertylist** ehus = NULL;
7912 cpl_table** lin_tables = NULL;
7913 cpl_array* gain_err = NULL;
7914 cpl_array* counts_min = NULL;
7915 cpl_array* counts_max = NULL;
7916 cpl_array* lin_eff = NULL;
7917 cpl_array* lin_eff_flux = NULL;
7919 cpl_array** contams = (cpl_array**)cpl_malloc(5 *
sizeof(cpl_array*));
7920 for (contam=0; contam < 5; ++contam) {
7921 contams[contam] = NULL;
7923 cpl_frame* fr = cpl_frame_new();
7924 char * coeff_kw = NULL ;
7925 char * coeff_comm = NULL ;
7936 cpl_frame_set_filename(fr, fn);
7937 int nexts = cpl_frame_get_nextensions(fr);
7939 cpl_msg_warning(cpl_func,
"No extensions in %s, so no QC "
7940 "keywords to write", fn);
7948 cpl_msg_info(cpl_func,
"Detected %d nexts", nexts);
7949 ehus = (cpl_propertylist**)cpl_malloc(nexts *
sizeof(cpl_propertylist*));
7950 lin_tables = (cpl_table**)cpl_malloc(nexts *
sizeof(cpl_table*));
7961 gain_err = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7962 counts_min = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7963 counts_max = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7964 lin_eff = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7965 lin_eff_flux = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7966 for (contam=0; contam < 5; ++contam) {
7967 contams[contam] = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7969 for (j=1; j <= nexts; ++j) {
7970 cpl_msg_info(cpl_func,
"Loading EHU %d", j);
7971 ehus[j-1] = cpl_propertylist_load(fn, j);
7972 lin_tables[j-1] = cpl_table_load(fn, j, 1);
7974 cpl_msg_info(cpl_func,
"Doing non-CONTAM values");
7976 if (cpl_propertylist_has(ehus[j-1],
"ESO QC GAIN ERR")) {
7977 cpl_array_set_double(gain_err, j-1,
7978 cpl_propertylist_get_double(
7979 ehus[j-1],
"ESO QC GAIN ERR"));
7981 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_COUNTS_MIN)) {
7982 cpl_array_set_double(counts_min, j-1,
7983 cpl_propertylist_get_double(
7984 ehus[j-1], DETMON_QC_COUNTS_MIN));
7986 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_COUNTS_MAX)) {
7987 cpl_array_set_double(counts_max, j-1,
7988 cpl_propertylist_get_double(
7989 ehus[j-1], DETMON_QC_COUNTS_MAX));
7991 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_LIN_EFF)) {
7992 cpl_array_set_double(lin_eff, j-1,
7993 cpl_propertylist_get_double(
7994 ehus[j-1], DETMON_QC_LIN_EFF));
7996 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_LIN_EFF_FLUX)) {
7997 cpl_array_set_double(lin_eff_flux, j-1,
7998 cpl_propertylist_get_double(
7999 ehus[j-1], DETMON_QC_LIN_EFF_FLUX));
8002 cpl_msg_info(cpl_func,
"Looping through contam values...");
8003 if (strcmp(recipe_name,
"detmon_opt_lg") == 0) {
8004 for (contam=0; contam<5 ; ++contam) {
8006 coeff_kw = cpl_sprintf(DETMON_QC_CONTAM
"%zd",
8008 if (cpl_propertylist_has(ehus[j-1],
8010 cpl_array_set_double(contams[contam], j-1,
8011 cpl_propertylist_get_double(
8028 cpl_msg_info(cpl_func,
"Computing & setting global values...");
8030 cpl_propertylist_append_double(phu, DETMON_QC_GAIN_ERR_AVG,
8031 cpl_array_get_mean(gain_err));
8032 cpl_propertylist_set_comment(phu, DETMON_QC_GAIN_ERR_AVG,
8033 DETMON_QC_GAIN_ERR_AVG_C);
8035 cpl_propertylist_append_double(phu, DETMON_QC_GAIN_ERR_RMS,
8036 cpl_array_get_stdev(gain_err));
8037 cpl_propertylist_set_comment(phu, DETMON_QC_GAIN_ERR_RMS,
8038 DETMON_QC_GAIN_ERR_RMS_C);
8040 cpl_propertylist_append_double(phu, DETMON_QC_COUNTS_MIN_AVG,
8041 cpl_array_get_mean(counts_min));
8042 cpl_propertylist_set_comment(phu, DETMON_QC_COUNTS_MIN_AVG,
8043 DETMON_QC_COUNTS_MIN_AVG_C);
8045 cpl_propertylist_append_double(phu, DETMON_QC_COUNTS_MIN_RMS,
8046 cpl_array_get_stdev(counts_min));
8047 cpl_propertylist_set_comment(phu, DETMON_QC_COUNTS_MIN_RMS,
8048 DETMON_QC_COUNTS_MIN_RMS_C);
8050 cpl_propertylist_append_double(phu, DETMON_QC_COUNTS_MAX_AVG,
8051 cpl_array_get_mean(counts_max));
8052 cpl_propertylist_set_comment(phu, DETMON_QC_COUNTS_MAX_AVG,
8053 DETMON_QC_COUNTS_MAX_AVG_C);
8055 cpl_propertylist_append_double(phu, DETMON_QC_COUNTS_MAX_RMS,
8056 cpl_array_get_stdev(counts_max));
8057 cpl_propertylist_set_comment(phu, DETMON_QC_COUNTS_MAX_RMS,
8058 DETMON_QC_COUNTS_MAX_RMS_C);
8060 cpl_propertylist_append_double(phu, DETMON_QC_LIN_EFF_AVG,
8061 cpl_array_get_mean(lin_eff));
8062 cpl_propertylist_set_comment(phu, DETMON_QC_LIN_EFF_AVG,
8063 DETMON_QC_LIN_EFF_AVG_C);
8065 cpl_propertylist_append_double(phu, DETMON_QC_LIN_EFF_RMS,
8066 cpl_array_get_stdev(lin_eff));
8067 cpl_propertylist_set_comment(phu, DETMON_QC_LIN_EFF_RMS,
8068 DETMON_QC_LIN_EFF_RMS_C);
8069 if (strcmp(recipe_name,
"detmon_opt_lg") == 0) {
8070 cpl_msg_info(cpl_func,
" Computing additional detmon_opt_lg values...");
8072 cpl_propertylist_append_double(phu, DETMON_QC_LIN_EFF_FLUX_AVG,
8073 cpl_array_get_mean(lin_eff_flux));
8074 cpl_propertylist_set_comment(phu, DETMON_QC_LIN_EFF_FLUX_AVG,
8075 DETMON_QC_LIN_EFF_FLUX_AVG_C);
8077 cpl_propertylist_append_double(phu, DETMON_QC_LIN_EFF_FLUX_RMS,
8078 cpl_array_get_stdev(lin_eff_flux));
8079 cpl_propertylist_set_comment(phu, DETMON_QC_LIN_EFF_FLUX_RMS,
8080 DETMON_QC_LIN_EFF_FLUX_RMS_C);
8083 for (contam=0 ; contam < 5; ++contam) {
8085 coeff_kw = cpl_sprintf(DETMON_QC_CONTAMi_AVG,
8087 coeff_comm = cpl_sprintf(DETMON_QC_CONTAMi_AVG_C,
8089 cpl_propertylist_append_double(phu,
8091 cpl_array_get_mean(contams[contam]));
8092 cpl_propertylist_set_comment(phu,
8096 cpl_free(coeff_comm);
8098 coeff_kw = cpl_sprintf(DETMON_QC_CONTAMi_RMS,
8100 coeff_comm = cpl_sprintf(DETMON_QC_CONTAMi_RMS_C,
8102 cpl_propertylist_append_double(phu,
8104 cpl_array_get_stdev(
8106 cpl_propertylist_set_comment(phu,
8110 cpl_free(coeff_comm);
8124 cpl_propertylist_save(phu, fn, CPL_IO_CREATE);
8125 for (j=1; j<=nexts; ++j) {
8127 cpl_table_save(lin_tables[j-1], phu,
8128 ehus[j-1], fn, CPL_IO_CREATE);
8130 cpl_table_save(lin_tables[j-1], NULL,
8131 ehus[j-1], fn, CPL_IO_EXTEND);
8133 cpl_propertylist_delete(ehus[j-1]);
8134 cpl_table_delete(lin_tables[j-1]);
8148 cpl_msg_info(cpl_func,
"Going into cleanup...");
8149 for (contam=0 ; contam<5 ; ++contam) {
8150 cpl_array_delete(contams[contam]);
8155 cpl_propertylist_delete(phu);
8157 cpl_free(lin_tables);
8161 cpl_array_delete(gain_err);
8163 cpl_array_delete(counts_min);
8165 cpl_array_delete(counts_max);
8167 cpl_array_delete(lin_eff);
8169 cpl_array_delete(lin_eff_flux);
8171 cpl_frame_delete(fr);
8173 cpl_msg_info(cpl_func,
"...done!");
8175 return cpl_error_get_code();
8179detmon_lg_qc_params_global_bpm(
const char * recipe_name,
int nsets) {
8180 cpl_msg_info(cpl_func,
"Going to update BPM image for "
8181 "recipe %s, nsets=%d",
8182 recipe_name, nsets);
8187 fn = cpl_sprintf(
"%s_bpm.fits", recipe_name) ;
8188 cpl_msg_info(cpl_func,
"Will be modifying %s", fn) ;
8189 err = detmon_lg_qc_params_global_bpm_update(fn, recipe_name);
8193 for (j=0; j<nsets; ++j) {
8194 fn = cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, j);
8195 cpl_msg_info(cpl_func,
"Will be modifying %s", fn);
8196 err = detmon_lg_qc_params_global_bpm_update(fn, recipe_name);
8205detmon_lg_qc_params_global_bpm_update(
const char * fn,
8206 const char * recipe_name) {
8207 cpl_msg_info(cpl_func,
"Now updating %s", fn);
8209 cpl_propertylist* phu = cpl_propertylist_load(fn, 0);
8210 cpl_propertylist** ehus = NULL ;
8211 cpl_image** bpm_imgs = NULL ;
8212 cpl_array* num_bpm = NULL;
8213 cpl_frame* fr = cpl_frame_new();
8219 if ((strcmp(recipe_name,
"detmon_opt_lg_mr") == 0 ) ||
8220 (strcmp(recipe_name,
"detmon_ir_lg_mr")) == 0) {
8225 cpl_frame_set_filename(fr, fn);
8226 int nexts = cpl_frame_get_nextensions(fr);
8228 cpl_msg_warning(cpl_func,
"No extensions in %s, so no QC "
8229 "keywords to write", fn);
8237 cpl_msg_info(cpl_func,
"Detected %d nexts", nexts);
8238 ehus = (cpl_propertylist**)cpl_malloc(nexts *
sizeof(cpl_propertylist*));
8239 bpm_imgs = (cpl_image**)cpl_malloc(nexts *
sizeof(cpl_image*));
8243 num_bpm = cpl_array_new(nexts, CPL_TYPE_INT);
8245 for (j=1; j<=nexts; ++j) {
8246 cpl_msg_info(cpl_func,
"Loading ext %d", j);
8247 ehus[j-1] = cpl_propertylist_load(fn, j);
8248 bpm_imgs[j-1] = cpl_image_load(fn, CPL_BPP_IEEE_FLOAT, 0, j);
8249 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_NUM_BPM)) {
8250 cpl_array_set_int(num_bpm, j-1,
8251 cpl_propertylist_get_int(ehus[j-1],
8252 DETMON_QC_NUM_BPM));
8258 cpl_propertylist_append_double(phu, DETMON_QC_NUM_BPM_AVG,
8259 cpl_array_get_mean(num_bpm));
8260 cpl_propertylist_set_comment(phu, DETMON_QC_NUM_BPM_AVG,
8261 DETMON_QC_NUM_BPM_AVG_C);
8264 cpl_propertylist_save(phu, fn, CPL_IO_CREATE);
8265 for (j=1; j<=nexts; ++j) {
8266 cpl_image_save(bpm_imgs[j-1], fn, CPL_BPP_IEEE_FLOAT, ehus[j-1],
8268 cpl_propertylist_delete(ehus[j-1]);
8269 cpl_image_delete(bpm_imgs[j-1]);
8283 cpl_msg_info(cpl_func,
"Doing cleanup");
8285 cpl_propertylist_delete(phu);
8289 cpl_array_delete(num_bpm);
8291 cpl_frame_delete(fr);
8293 cpl_msg_info(cpl_func,
"...done!");
8295 return cpl_error_get_code();
8300detmon_lg_qc_params_global_coeffs(
const char * recipe_name,
int nsets) {
8301 cpl_msg_info(cpl_func,
"Going to update coeffs image for "
8302 "recipe %s, nsets=%d",
8303 recipe_name, nsets);
8305 cpl_error_code err = CPL_ERROR_NONE;
8308 fn = cpl_sprintf(
"%s_coeffs_cube.fits", recipe_name);
8309 cpl_msg_info(cpl_func,
"Will be modifying %s", fn) ;
8310 err = detmon_lg_qc_params_global_coeffs_update(fn, recipe_name);
8314 for (j=0; j<nsets; ++j) {
8315 fn = cpl_sprintf(
"%s_coeffs_cube_set%02d.fits",
8317 cpl_msg_info(cpl_func,
"Will be modifying %s", fn);
8318 err = detmon_lg_qc_params_global_coeffs_update(fn, recipe_name);
8327detmon_lg_qc_params_global_coeffs_update(
const char * fn,
8328 const char * recipe_name) {
8329 cpl_msg_info(cpl_func,
"Now updating %s", fn);
8331 cpl_propertylist* phu = cpl_propertylist_load(fn, 0);
8332 cpl_propertylist** ehus = NULL;
8333 cpl_imagelist** coeff_cubes = NULL;
8334 cpl_frame* fr = NULL;
8335 cpl_array* lin_coeff = NULL;
8336 cpl_array* lin_coeff_err = NULL;
8337 cpl_array* errfit = NULL;
8338 char* coeff_kw = NULL ;
8339 char* coeff_kw_err = NULL ;
8340 char* coeff_str = NULL ;
8343 fr = cpl_frame_new();
8344 cpl_frame_set_filename(fr, fn);
8345 int nexts = cpl_frame_get_nextensions(fr);
8347 cpl_msg_warning(cpl_func,
"No extensions in %s, so no QC "
8348 "keywords to write", fn);
8357 if ((strcmp(recipe_name,
"detmon_opt_lg_mr") == 0 ) ||
8358 (strcmp(recipe_name,
"detmon_ir_lg_mr")) == 0) {
8359 cpl_msg_info(cpl_func,
"Skipping %s for recipe %s",
8360 cpl_func, recipe_name);
8364 cpl_msg_info(cpl_func,
"Detected %d nexts", nexts);
8365 ehus = (cpl_propertylist**)cpl_malloc(nexts *
sizeof(cpl_propertylist*));
8366 coeff_cubes = (cpl_imagelist**)cpl_malloc(nexts *
sizeof(cpl_imagelist*));
8367 cpl_msg_info(cpl_func,
"Malloc'd data structures for eventual re-write");
8370 int j, coeff, coeff_max ;
8372 for (j=1; j<=nexts; ++j) {
8373 ehus[j-1] = cpl_propertylist_load(fn, j);
8375 cpl_msg_info(__func__,
"Loaded extension headers");
8378 cpl_msg_info(__func__,
"Creating lin_coeff and errfit arrays...");
8379 lin_coeff = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
8380 lin_coeff_err = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
8381 errfit = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
8382 cpl_msg_info(__func__,
"...done!");
8384 if (strcmp(recipe_name,
"detmon_ir_lg") == 0) {
8387 cpl_msg_info(cpl_func,
"Populating errfit arrays");
8388 for (j=1; j<=nexts; ++j) {
8389 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_ERRFIT)) {
8390 cpl_array_set_double(
8392 cpl_propertylist_get_double(ehus[j-1],
8397 cpl_msg_info(cpl_func,
"Setting keywords with new funcs");
8398 detmon_lg_set_keyword_from_base_double(phu,
8399 DETMON_QC_ERRFIT,
"AVG",
8402 cpl_array_get_mean(errfit));
8404 detmon_lg_set_keyword_from_base_double(phu,
8405 DETMON_QC_ERRFIT,
"RMS",
8408 cpl_array_get_stdev(errfit));
8423 for (coeff = 0 ; coeff < coeff_max + 1 ; ++coeff) {
8424 cpl_msg_info(cpl_func,
"Forming coeff keyword %d", coeff);
8425 coeff_kw = cpl_sprintf(
"ESO QC LIN COEF%d", coeff);
8426 coeff_kw_err = cpl_sprintf(
"ESO QC LIN COEF%d ERR",
8428 coeff_str = cpl_sprintf(
"%d", coeff);
8431 cpl_msg_info(cpl_func,
"Reading in the coeff values");
8432 for (j=1; j<=nexts; ++j) {
8434 if (cpl_propertylist_has(ehus[j-1],
8436 cpl_array_set_double(
8439 cpl_propertylist_get_double(
8443 cpl_msg_info(cpl_func,
"Added value %f to lin_coeff in pos %d",
8444 cpl_propertylist_get_double(
8449 if (cpl_propertylist_has(ehus[j-1],
8451 cpl_array_set_double(
8453 cpl_propertylist_get_double(
8458 cpl_msg_info(__func__,
"Insertions complete! (%d)", coeff);
8471 cpl_msg_info(cpl_func,
"Writing back header keywords for %d", coeff);
8473 if (cpl_array_count_invalid(lin_coeff) < (cpl_size)nexts) {
8474 detmon_lg_set_keyword_from_insert_double(
8476 DETMON_QC_LIN_COEFF_AVG, coeff_str,
8477 DETMON_QC_LIN_COEFF_AVG_C, coeff_str,
8478 cpl_array_get_mean(lin_coeff)
8482 detmon_lg_set_keyword_from_insert_double(
8484 DETMON_QC_LIN_COEFF_RMS, coeff_str,
8485 DETMON_QC_LIN_COEFF_RMS_C, coeff_str,
8486 cpl_array_get_stdev(lin_coeff)
8490 if (cpl_array_count_invalid(lin_coeff_err) < (cpl_size)nexts) {
8492 detmon_lg_set_keyword_from_insert_double(
8494 DETMON_QC_LIN_COEFF_ERR_AVG, coeff_str,
8495 DETMON_QC_LIN_COEFF_ERR_AVG_C, coeff_str,
8496 cpl_array_get_mean(lin_coeff_err)
8500 detmon_lg_set_keyword_from_insert_double(
8502 DETMON_QC_LIN_COEFF_ERR_RMS, coeff_str,
8503 DETMON_QC_LIN_COEFF_ERR_RMS_C, coeff_str,
8504 cpl_array_get_stdev(lin_coeff_err)
8508 cpl_msg_info(__func__,
"Data write complete! (%d)", coeff);
8522 cpl_array_fill_window_invalid(lin_coeff, 0, nexts);
8523 cpl_array_fill_window_invalid(lin_coeff_err, 0, nexts);
8524 cpl_msg_info(__func__,
"Arrays reset! (%d)", coeff);
8535 cpl_msg_info(cpl_func,
"Purging the coeff keywords");
8537 cpl_free(coeff_kw_err);
8538 cpl_free(coeff_str);
8540 coeff_kw_err = NULL ;
8567 for (j=1; j<=nexts; ++j) {
8568 coeff_cubes[j-1] = cpl_imagelist_load(fn, CPL_BPP_IEEE_FLOAT, j);
8570 cpl_propertylist_save(phu, fn, CPL_IO_CREATE);
8571 for (j=1; j<=nexts; ++j) {
8572 cpl_imagelist_save(coeff_cubes[j-1], fn, CPL_BPP_IEEE_FLOAT, ehus[j-1],
8575 cpl_propertylist_delete(ehus[j-1]);
8576 cpl_imagelist_delete(coeff_cubes[j-1]);
8578 cpl_msg_info(__func__,
"Removed all file data in memory");
8591 cpl_msg_info(cpl_func,
"Doing cleanup...");
8594 cpl_propertylist_delete(phu);
8596 cpl_free(coeff_cubes);
8598 cpl_frame_delete(fr);
8600 cpl_array_delete(lin_coeff);
8602 cpl_array_delete(lin_coeff_err);
8604 cpl_array_delete(errfit);
8606 cpl_msg_info(cpl_func,
"...done!");
8607 return cpl_error_get_code();
8611detmon_lg_qc_set_kw_from_table_column(cpl_table* table,
8612 const char * column,
8614 cpl_propertylist* header,
8616 const char * kw_comment) {
8618 if (strcmp(op,
"mean") == 0) {
8619 value = cpl_table_get_column_mean(table, column);
8620 }
else if (strcmp(op,
"stdev") == 0) {
8621 value = cpl_table_get_column_stdev(table, column);
8623 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
8624 return cpl_error_get_code();
8627 cpl_propertylist_append_double(header, kw, value);
8628 if (kw_comment != NULL) {
8629 cpl_propertylist_set_comment(header, kw, kw_comment);
8631 return cpl_error_get_code();