41 #include "detmon_lg.h"
44 #include "detmon_utils.h"
45 #include "detmon_lg_impl.h"
47 #include "irplib_ksigma_clip.h"
48 #include "irplib_utils.h"
49 #include "irplib_hist.h"
74 typedef enum _FPN_METHOD FPN_METHOD;
114 cpl_boolean wholechip;
115 cpl_boolean autocorr;
116 cpl_boolean intermediate;
117 cpl_boolean collapse;
124 const char * pafname;
129 double lamp_stability;
132 int (* load_fset) (
const cpl_frameset *, cpl_type, cpl_imagelist *);
133 cpl_imagelist * (* load_fset_wrp) (
const cpl_frameset *, cpl_type, int);
134 FPN_METHOD fpn_method;
136 double saturation_limit;
137 double gain_threshold;
138 cpl_boolean split_coeffs;
148 static cpl_error_code
149 detmon_lg_retrieve_parlist(
const char *,
150 const char *,
const cpl_parameterlist *,
154 static cpl_error_code
155 detmon_lg_split_onoff(
const cpl_frameset *,
158 const char *,
const char * );
160 static cpl_error_code
161 detmon_lg_reduce(
const cpl_frameset *,
162 const cpl_frameset *,
163 int* index_on,
int* index_off,
164 double* exptime_on,
double* exptime_off,
165 int *next_index_on,
int* next_index_off,
176 int (* load_fset) (
const cpl_frameset *,
179 const cpl_boolean,
int);
184 static cpl_error_code
185 detmon_lin_table_fill_row(cpl_table *,
double,
187 const cpl_imagelist *,
188 const cpl_imagelist *,
194 static cpl_error_code
195 detmon_gain_table_fill_row(cpl_table * gain_table,
196 double c_dit,
int c_ndit,
197 cpl_imagelist * autocorr_images,
198 cpl_imagelist * diff_flats,
199 const cpl_imagelist * ons,
200 const cpl_imagelist * offs,
201 double kappa,
int nclip,
202 int llx,
int lly,
int urx,
int ury,
204 double gain_threshold,
205 int pos,
unsigned mode,
int* rows_affected);
208 static cpl_error_code
209 detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
210 cpl_imagelist * diff_flats,
211 const cpl_imagelist * ons,
212 double kappa,
int nclip,
213 int llx,
int lly,
int urx,
int ury,
214 double saturation_limit,
215 const int pos,
unsigned mode,
216 int* rows_linear_affected);
218 static cpl_error_code
219 detmon_lg_save(
const cpl_parameterlist *,
224 const cpl_propertylist *,
225 const cpl_propertylist *,
226 const cpl_propertylist *,
227 const cpl_propertylist *,
228 const cpl_propertylist *,
229 const cpl_propertylist *,
241 const int,
const int,
const cpl_frameset *,
244 static cpl_error_code
245 detmon_lg_qc_ptc(
const cpl_table *,
246 cpl_propertylist *,
unsigned,
int);
248 static cpl_error_code
249 detmon_lg_qc_med(
const cpl_table *,
250 cpl_propertylist *,
int);
254 detmon_pfits_get_dit(
const cpl_propertylist *);
257 detmon_pfits_get_dit_opt(
const cpl_propertylist *);
259 irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
260 const char* prop_name);
262 static cpl_image * detmon_bpixs(
const cpl_imagelist *,
263 cpl_boolean,
const double,
int *);
266 detmon_autocorr_factor(
const cpl_image *,
267 cpl_image **,
int,
int);
271 static cpl_error_code
272 detmon_opt_contamination(
const cpl_imagelist *,
273 const cpl_imagelist *,
274 unsigned mode, cpl_propertylist *);
277 detmon_opt_lampcr(cpl_frameset *,
int);
281 detmon_lg_dfs_set_groups(cpl_frameset *,
const char *,
const char *);
283 static cpl_error_code
284 detmon_lg_reduce_all(
const cpl_table *,
291 const cpl_imagelist *,
292 const cpl_table *,
int, cpl_boolean);
294 static cpl_error_code
295 detmon_lg_check_defaults(
const cpl_image *);
297 static cpl_error_code
298 detmon_lg_rescale(cpl_imagelist *);
300 static cpl_error_code
301 detmon_lg_reduce_init(cpl_table *,
307 static cpl_error_code
308 detmon_add_adl_column(cpl_table *, cpl_boolean);
310 static cpl_error_code
311 detmon_lg_lamp_stab(
const cpl_frameset *,
312 const cpl_frameset *,
316 static cpl_error_code
317 detmon_lg_reduce_dit(
const cpl_frameset * set_on,
318 int* index_on,
double* exptime_on,
321 const cpl_frameset * set_off,
322 int * index_off,
double* exptime_off,
323 int* next_on,
int* next_off,
324 cpl_table * linear_table,
325 cpl_table * gain_table,
326 cpl_imagelist * linearity_inputs,
327 cpl_propertylist * qclist,
329 cpl_imagelist * autocorr_images,
330 cpl_imagelist * diff_flats,
331 cpl_imagelist * opt_offs,
333 int * rows_linear_affected,
334 int * rows_gain_affected);
336 static cpl_error_code
337 detmon_lg_core(cpl_frameset * cur_fset_on,
338 cpl_frameset * cur_fset_off,
342 double * exptime_off,
345 const char * recipe_name,
346 const char * pipeline_name,
347 const char * pafregexp,
348 const cpl_propertylist * pro_lintbl,
349 const cpl_propertylist * pro_gaintbl,
350 const cpl_propertylist * pro_coeffscube,
351 const cpl_propertylist * pro_bpm,
352 const cpl_propertylist * pro_corr,
353 const cpl_propertylist * pro_diff,
354 const char * package,
355 int (* load_fset) (
const cpl_frameset *,
358 int nsets, cpl_boolean opt_nir,
359 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
360 cpl_frameset * cur_fset);
362 static cpl_error_code
363 detmon_lg_lineff(
double *, cpl_propertylist *,
int,
int);
370 static cpl_error_code
371 detmon_gain_table_create(cpl_table *,
375 static cpl_error_code
376 detmon_lin_table_create(cpl_table *,
380 detmon_lg_find_dits(
const cpl_vector *,
383 static cpl_error_code
384 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
385 const cpl_vector * vec_ndits,
387 cpl_vector** diff_dits,
388 cpl_vector** diff_ndits);
390 static cpl_error_code
391 detmon_fpn_compute(
const cpl_frameset *set_on,
393 int last_linear_best,
394 cpl_propertylist *lint_qclist,
401 FPN_METHOD fpn_method,
403 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain,
404 FPN_METHOD fpn_method,
int,
double* mse);
405 static double irplib_calculate_total_noise(
const cpl_image* pimage);
407 static cpl_imagelist* irplib_load_fset_wrp(
const cpl_frameset *,
408 cpl_type,
int whichext);
409 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset *,
412 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
413 cpl_propertylist* plist);
414 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
415 cpl_propertylist* plist,
418 static cpl_error_code
419 detmon_pair_extract_next(
const cpl_frameset * set,
425 cpl_frameset ** pair,
427 static cpl_error_code
428 detmon_single_extract_next(
const cpl_frameset * set,
432 cpl_frameset ** pair);
439 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code);
440 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos);
441 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y);
450 static int irplib_pfits_get_ndit(
const cpl_propertylist * plist)
452 return cpl_propertylist_get_int(plist,
"ESO DET NDIT");
495 #ifdef DETMON_USE_DETECTOR_SHOTNOISE_MODEL
518 static cpl_error_code
519 hdrldemo_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
520 const double ron, cpl_image ** ima_errs)
522 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
523 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
524 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
525 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
527 *ima_errs = cpl_image_duplicate(ima_data);
529 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
533 cpl_image_divide_scalar(*ima_errs, gain);
534 cpl_image_add_scalar(*ima_errs, ron * ron);
535 cpl_image_power(*ima_errs, 0.5);
537 return cpl_error_get_code();
541 static cpl_error_code
542 detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
545 const char * tag_off,
546 const char * recipe_name,
547 const char * pipeline_name,
548 const char * pafregexp,
549 const cpl_propertylist * pro_lintbl,
550 const cpl_propertylist * pro_gaintbl,
551 const cpl_propertylist * pro_coeffscube,
552 const cpl_propertylist * pro_bpm,
553 const cpl_propertylist * pro_corr,
554 const cpl_propertylist * pro_diff,
555 const char * package,
557 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
558 const cpl_boolean opt_nir,
559 const cpl_parameterlist * parlist,
562 static double irplib_compute_err(
double gain,
double ron,
double photon_noise);
564 static cpl_error_code
565 detmon_lg_dfs_save_imagelist(cpl_frameset * frameset,
566 const cpl_parameterlist * parlist,
567 const cpl_frameset *usedframes,
568 const cpl_imagelist *coeffs,
569 const char *recipe_name,
570 const cpl_propertylist *mypro_coeffscube,
571 const char * package,
572 const char * name_o);
575 static void irplib_free(
char** pointer){
577 if(pointer && *pointer) {
583 static cpl_error_code
584 detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
int nsets,
586 const char * tag_off,
587 const char * recipe_name,
588 const char * pipeline_name,
589 const char * pafregexp,
590 const cpl_propertylist * pro_lintbl,
591 const cpl_propertylist * pro_gaintbl,
592 const cpl_propertylist * pro_coeffscube,
593 const cpl_propertylist * pro_bpm,
594 const cpl_propertylist * pro_corr,
595 const cpl_propertylist * pro_diff,
596 const char * package,
598 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
599 const cpl_boolean opt_nir,
600 const cpl_parameterlist * parlist,
605 int nexts = detmon_lg_config.nb_extensions;
607 double* exptime_on = 0;
608 double* exptime_off = 0;
611 cpl_frameset * cur_fset = NULL;
612 cpl_frameset* cur_fset_on = 0;
613 cpl_frameset* cur_fset_off = 0;
618 cpl_frameset_duplicate(frameset) : cpl_frameset_extract(frameset, selection, i);
621 skip_if(cur_fset == NULL);
624 cur_fset_on = cpl_frameset_new();
625 cur_fset_off = cpl_frameset_new();
626 cpl_msg_info(cpl_func,
"Splitting into ON and OFF sub-framesets");
627 skip_if (detmon_lg_split_onoff(cur_fset,
628 cur_fset_on, cur_fset_off,
630 if (cpl_frameset_get_size(cur_fset_on) == 0)
632 cpl_msg_error(cpl_func,
"No lamp frames in input");
636 if (cpl_frameset_get_size(cur_fset_off) == 0)
638 cpl_msg_error(cpl_func,
"No dark / bias frames in input");
641 cpl_msg_info(cpl_func,
"found on-frames[%" CPL_SIZE_FORMAT
"] off-frames[%" CPL_SIZE_FORMAT
"]",cpl_frameset_get_size(cur_fset_on), cpl_frameset_get_size(cur_fset_off));
649 exptime_on = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_on));
650 exptime_off = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_off));
652 index_on = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_on));
653 index_off = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_off));
654 irplib_frameset_sort(cur_fset_on, index_on, exptime_on);
655 irplib_frameset_sort(cur_fset_off, index_off, exptime_off);
668 skip_if(detmon_check_order(exptime_on, cpl_frameset_get_size(cur_fset_on), detmon_lg_config.tolerance, detmon_lg_config.order));
670 if(detmon_lg_config.exts >= 0)
678 if (detmon_lg_config.lamp_ok) {
679 skip_if(detmon_opt_lampcr(cur_fset, 0));
682 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
687 detmon_lg_config.exts,
689 recipe_name, pipeline_name, pafregexp,
690 pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff,
691 package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
693 for(j = 1; j <= nexts; j++) {
700 if (detmon_lg_config.lamp_ok) {
701 skip_if(detmon_opt_lampcr(cur_fset, j));
705 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
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();
845 detmon_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();
1055 static cpl_error_code
1056 detmon_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 detmon_lg_qc_params(
1131 linear_table, lint_qclist,
1132 gain_table, gaint_qclist,
1133 coeffs, linc_qclist,
1140 cpl_msg_info(cpl_func,
"Saving the products");
1143 detmon_lg_save(parlist, frameset, recipe_name,
1144 pipeline_name, pafregexp,
1145 pro_lintbl, pro_gaintbl,
1146 pro_coeffscube, pro_bpm,
1147 pro_corr, pro_diff, package,
1148 coeffs, gain_table, linear_table,
1149 bpm, autocorr_images, diff_flats,
1150 gaint_qclist, lint_qclist, linc_qclist,
1153 cur_fset, whichext));
1156 detmon_lg_save(parlist, frameset, recipe_name,
1157 pipeline_name, pafregexp,
1158 pro_lintbl, pro_gaintbl,
1159 pro_coeffscube, pro_bpm,
1160 pro_corr, pro_diff, package,
1161 coeffs, gain_table, linear_table,
1162 bpm, autocorr_images, diff_flats,
1163 gaint_qclist, lint_qclist, linc_qclist,
1166 cur_fset, whichext));
1173 cpl_table_delete(gain_table);
1174 cpl_table_delete(linear_table);
1175 cpl_imagelist_delete(coeffs);
1176 cpl_propertylist_delete(gaint_qclist);
1177 cpl_propertylist_delete(lint_qclist);
1178 cpl_propertylist_delete(linc_qclist);
1179 if(bpm_qclist != NULL) cpl_propertylist_delete(bpm_qclist);
1180 cpl_image_delete(bpm);
1181 cpl_imagelist_delete(autocorr_images);
1182 cpl_imagelist_delete(diff_flats);
1184 return cpl_error_get_code();
1209 detmon_image_correlate(
const cpl_image * image1,
1210 const cpl_image * image2,
1211 const int m,
const int n)
1213 cpl_image *image1_padded = NULL;
1214 cpl_image *image2_padded = NULL;
1218 cpl_image *corr_image_window = NULL;
1220 cpl_image* image_ri1 = NULL;
1221 cpl_image* image_ri2 = NULL;
1222 cpl_error_code err = CPL_ERROR_NONE;
1225 cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1226 cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1228 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1229 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1231 nx = cpl_image_get_size_x(image1);
1232 ny = cpl_image_get_size_y(image1);
1234 nx2 = cpl_image_get_size_x(image2);
1235 ny2 = cpl_image_get_size_y(image2);
1238 cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
1241 image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1242 cpl_image_copy(image1_padded, image1, m + 1, n + 1);
1244 image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1245 cpl_image_copy(image2_padded, image2, m + 1, n + 1);
1251 image_ri1 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
1252 image_ri2 = cpl_image_new(nx, ny , CPL_TYPE_FLOAT_COMPLEX);
1254 cpl_fft_image(image_ri1, image1_padded, CPL_FFT_FORWARD);
1255 cpl_fft_image(image_ri2, image2_padded, CPL_FFT_FORWARD);
1256 err = cpl_error_get_code();
1257 cpl_image_delete(image1_padded);
1258 image1_padded = NULL;
1259 cpl_image_delete(image2_padded);
1260 image2_padded = NULL;
1261 if (err == CPL_ERROR_NONE)
1264 cpl_image * corr_image = NULL;
1265 cpl_image * reorganised= NULL;
1266 cpl_image * image_ri_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1267 cpl_image * image_in_inv = cpl_image_new(nx, ny,
1268 CPL_TYPE_FLOAT_COMPLEX);
1271 for (i = 1; i <= nx; i++)
1273 for (j = 1; j <= ny; j++)
1276 double complex value1, value2, value;
1277 value1 = cpl_image_get_complex(image_ri1, i, j, &rej);
1278 value2 = cpl_image_get_complex(image_ri2, i, j, &rej);;
1279 value = conj(value1) * value2;
1280 cpl_image_set_complex(image_in_inv, i, j, value);
1283 cpl_image_delete(image_ri1);
1285 cpl_image_delete(image_ri2);
1288 err = cpl_error_get_code();
1289 if (err == CPL_ERROR_NONE)
1293 cpl_fft_image(image_ri_inv, image_in_inv,CPL_FFT_BACKWARD);
1294 cpl_image_delete(image_in_inv);
1297 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1298 for (i = 1; i <= nx; i++)
1300 for (j = 1; j <= ny; j++)
1304 value = cpl_image_get(image_ri_inv, i, j, &rej);
1305 cpl_image_set(corr_image, i, j, value);
1308 cpl_image_delete(image_ri_inv);
1309 err = cpl_error_get_code();
1310 if (err == CPL_ERROR_NONE)
1314 cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
1315 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1317 cpl_image_copy(reorganised, image, 1, 1);
1318 cpl_image_delete(image);
1319 image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
1320 cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
1321 cpl_image_delete(image);
1323 cpl_image_delete(corr_image);
1325 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1326 image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
1327 cpl_image_copy(corr_image, image, 1, 1);
1328 cpl_image_delete(image);
1330 image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
1331 cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
1332 cpl_image_delete(image);
1334 corr_image_window = cpl_image_extract(corr_image,
1337 nx / 2 + 1 + m, ny / 2 + 1 + n);
1342 cpl_image_delete(reorganised);
1343 cpl_image_delete(corr_image);
1345 if(cpl_image_divide_scalar(corr_image_window,
1346 cpl_image_get_max(corr_image_window))) {
1347 cpl_image_delete(corr_image_window);
1351 cpl_image_delete (image_ri1);
1352 cpl_image_delete (image_ri2);
1353 cpl_image_delete (image1_padded);
1354 cpl_image_delete (image2_padded);
1355 return corr_image_window;
1378 detmon_autocorrelate(
const cpl_image * input2,
const int m,
1381 cpl_image *im_re = NULL;
1382 cpl_image *im_im = NULL;
1384 cpl_image *ifft_re = NULL;
1385 cpl_image *ifft_im = NULL;
1386 cpl_image *autocorr = NULL;
1387 cpl_image *autocorr_norm_double = NULL;
1388 cpl_image *autocorr_norm = NULL;
1389 cpl_image *reorganised = NULL;
1390 cpl_image *image = NULL;
1392 cpl_error_code error;
1395 cpl_ensure(input2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1397 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1398 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1400 nx = cpl_image_get_size_x(input2) + 2 * m;
1401 ny = cpl_image_get_size_y(input2) + 2 * n;
1404 while(nx > p || ny > p) {
1408 input = cpl_image_cast(input2, CPL_TYPE_DOUBLE);
1410 im_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1411 error = cpl_image_copy(im_re, input, 1, 1);
1412 cpl_image_delete(input);
1414 cpl_ensure(!error, error, NULL);
1416 im_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1418 error = cpl_image_fft(im_re, im_im, CPL_FFT_DEFAULT);
1419 cpl_ensure(!error, error, NULL);
1421 ifft_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1422 error = cpl_image_power(im_re, 2);
1423 cpl_ensure(!error, error, NULL);
1425 error = cpl_image_add(ifft_re, im_re);
1426 cpl_ensure(!error, error, NULL);
1428 cpl_image_delete(im_re);
1430 error = cpl_image_power(im_im, 2);
1431 cpl_ensure(!error, error, NULL);
1433 error = cpl_image_add(ifft_re, im_im);
1434 cpl_ensure(!error, error, NULL);
1436 cpl_image_delete(im_im);
1438 ifft_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1440 error = cpl_image_fft(ifft_re, ifft_im, CPL_FFT_INVERSE);
1441 cpl_ensure(!error, error, NULL);
1443 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1445 error = cpl_image_power(ifft_re, 2);
1446 cpl_ensure(!error, error, NULL);
1448 error = cpl_image_add(autocorr, ifft_re);
1449 cpl_ensure(!error, error, NULL);
1451 cpl_image_delete(ifft_re);
1453 error = cpl_image_power(ifft_im, 2);
1454 cpl_ensure(!error, error, NULL);
1456 error = cpl_image_add(autocorr, ifft_im);
1457 cpl_ensure(!error, error, NULL);
1459 cpl_image_delete(ifft_im);
1462 reorganised = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1464 image = cpl_image_extract(autocorr, p / 2 + 1, 1, p, p);
1465 cpl_image_copy(reorganised, image, 1, 1);
1466 cpl_image_delete(image);
1468 image = cpl_image_extract(autocorr, 1, 1, p / 2, p);
1469 cpl_image_copy(reorganised, image, p / 2 + 1, 1);
1470 cpl_image_delete(image);
1472 cpl_image_delete(autocorr);
1474 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1476 image = cpl_image_extract(reorganised, 1, p / 2 + 1, p, p);
1477 cpl_image_copy(autocorr, image, 1, 1);
1478 cpl_image_delete(image);
1480 image = cpl_image_extract(reorganised, 1, 1, p, p / 2);
1481 cpl_image_copy(autocorr, image, 1, p / 2 + 1);
1482 cpl_image_delete(image);
1484 cpl_image_delete(reorganised);
1486 autocorr_norm_double =
1487 cpl_image_extract(autocorr, p / 2 + 1 - m, p / 2 + 1 - n,
1488 p / 2 + 1 + m, p / 2 + 1 + n);
1490 cpl_image_delete(autocorr);
1492 if(cpl_image_divide_scalar(autocorr_norm_double,
1493 cpl_image_get_max(autocorr_norm_double))) {
1494 cpl_image_delete(autocorr_norm_double);
1495 cpl_ensure(0, cpl_error_get_code(), NULL);
1499 autocorr_norm = cpl_image_cast(autocorr_norm_double, CPL_TYPE_FLOAT);
1500 cpl_image_delete(autocorr_norm_double);
1502 return autocorr_norm;
1518 detmon_lg_fill_parlist_nir_default(cpl_parameterlist * parlist,
1519 const char *recipe_name,
1520 const char *pipeline_name)
1522 const cpl_error_code error =
1523 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1569 cpl_ensure_code(!error, error);
1571 return cpl_error_get_code();
1587 detmon_lg_fill_parlist_opt_default(cpl_parameterlist * parlist,
1588 const char *recipe_name,
1589 const char *pipeline_name)
1591 const cpl_error_code error =
1592 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1637 cpl_ensure_code(!error, error);
1639 return cpl_error_get_code();
1642 static cpl_error_code
1643 detmon_lg_fill_parlist_default_mr(cpl_parameterlist * parlist,
1644 const char *recipe_name,
1645 const char *pipeline_name)
1647 char * group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1648 char * par_name = cpl_sprintf(
"%s.%s", group_name,
"regions-file");
1649 cpl_parameter * p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1650 "File containing regions, "
1651 "four comma separated points "
1654 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions-file");
1655 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1656 cpl_parameterlist_append(parlist, p);
1658 cpl_free(group_name);
1660 group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1661 par_name = cpl_sprintf(
"%s.%s", group_name,
"regions");
1662 p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1663 "Colon separated list of regions, four "
1664 "points each, comma separated: "
1665 "llx,lly,urx,ury:llx,...",
1667 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions");
1668 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1669 cpl_parameterlist_append(parlist, p);
1671 cpl_free(group_name);
1673 return cpl_error_get_code();
1677 detmon_lg_fill_parlist_opt_default_mr(cpl_parameterlist * parlist,
1678 const char *recipe_name,
1679 const char *pipeline_name)
1681 detmon_lg_fill_parlist_opt_default(parlist, recipe_name, pipeline_name);
1682 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1683 return cpl_error_get_code();
1687 detmon_lg_fill_parlist_nir_default_mr(cpl_parameterlist * parlist,
1688 const char *recipe_name,
1689 const char *pipeline_name)
1691 detmon_lg_fill_parlist_nir_default(parlist, recipe_name, pipeline_name);
1692 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1694 return cpl_error_get_code();
1754 detmon_lg_fill_parlist(cpl_parameterlist * parlist,
1755 const char *recipe_name,
const char *pipeline_name,
1765 const char *intermediate,
1766 const char *autocorr,
1767 const char *collapse,
1768 const char *rescale,
1769 const char *pix2pix,
1776 const char * pafname,
1793 int llx5,
int lly5,
int urx5,
int ury5,
int exts,
1794 cpl_boolean opt_nir)
1796 const cpl_error_code error =
1797 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 26,
1799 "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
1800 "CPL_TYPE_STRING", method,
1803 "Polynomial order for the fit (Linearity)",
1804 "CPL_TYPE_INT", order,
1806 "Kappa value for the kappa-sigma clipping (Gain)",
1807 "CPL_TYPE_DOUBLE", kappa,
1809 "Number of iterations to compute rms (Gain)",
1810 "CPL_TYPE_INT", niter,
1812 "x coordinate of the lower-left "
1813 "point of the region of interest. If not modified, default value will be 1.",
1814 "CPL_TYPE_INT", llx,
1816 "y coordinate of the lower-left "
1817 "point of the region of interest. If not modified, default value will be 1.",
1818 "CPL_TYPE_INT", lly,
1820 "x coordinate of the upper-right "
1821 "point of the region of interest. If not modified, default value will be X dimension of the input image.",
1822 "CPL_TYPE_INT", urx,
1824 "y coordinate of the upper-right "
1825 "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
1826 "CPL_TYPE_INT", ury,
1828 "User reference level",
1829 "CPL_TYPE_INT", ref_level,
1831 "De-/Activate intermediate products",
1832 "CPL_TYPE_BOOL", intermediate,
1835 "De-/Activate the autocorr option",
1836 "CPL_TYPE_BOOL", autocorr,
1839 "De-/Activate the collapse option",
1840 "CPL_TYPE_BOOL", collapse,
1842 "De-/Activate the image rescale option",
1843 "CPL_TYPE_BOOL", rescale,
1845 "De-/Activate the computation with pixel to pixel accuracy",
1846 "CPL_TYPE_BOOL", pix2pix,
1848 "De-/Activate the binary bpm option",
1849 "CPL_TYPE_BOOL", bpmbin,
1851 "Maximum x-shift for the autocorr",
1854 "Upper limit of Median flux to be filtered",
1855 "CPL_TYPE_INT", filter,
1857 "Maximum y-shift for the autocorr",
1860 "Tolerance for pair discrimination",
1861 "CPL_TYPE_DOUBLE", tolerance,
1864 "Generate PAF file",
1865 "CPL_TYPE_BOOL", pafgen,
1867 "Specific name for PAF file",
1868 "CPL_TYPE_STRING", pafname,
1872 "Activate the multi-exts option. Choose -1 to process all extensions. Choose an extension number"
1873 " to process the appropriate extension.",
1874 "CPL_TYPE_INT", exts,
1877 "Method for computing Fixed Pattern Noise (SMOOTH or HISTOGRAM)",
1878 "CPL_TYPE_STRING",
"HISTOGRAM",
1881 "template size in pixels for smoothing during FPN computation (only for SMOOTH method)",
1885 "all frames with mean saturation above the limit would not be used in linearity calculation",
1886 "CPL_TYPE_DOUBLE", 65535.0,
1889 "all frames with mean flux above the threshold would not be used in gain calculation",
1890 "CPL_TYPE_DOUBLE", 65535.0
1893 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 1,
1894 "coeffs_cube_split",
1895 "if TRUE, the recipe writes as many "
1896 "COEFFS_CUBE_Pi (i=0..order) as the value of "
1897 "the order parameter in a separate file",
1898 "CPL_TYPE_BOOL",
"CPL_FALSE");
1900 if(opt_nir == FALSE) {
1901 const cpl_error_code erroropt =
1902 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
1904 "x coord of the lower-left point of the first "
1905 "field used for contamination measurement. If not modified, default value will be 1.",
1906 "CPL_TYPE_INT", llx1,
1908 "y coord of the lower-left point of the first "
1909 "field used for contamination measurement. If not modified, default value will be 1.",
1910 "CPL_TYPE_INT", lly1,
1912 "x coord of the upper-right point of the first "
1913 "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
1914 "CPL_TYPE_INT", urx1,
1916 "y coord of the upper-right point of the first "
1917 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1918 "CPL_TYPE_INT", ury1,
1920 "x coord of the lower-left point of the second "
1921 "field used for contamination measurement. If not modified, default value will be 1.",
1922 "CPL_TYPE_INT", llx2,
1924 "y coord of the lower-left point of the second "
1925 "field used for contamination measurement. If not modified, default value will be 1.",
1926 "CPL_TYPE_INT", lly2,
1928 "x coord of the upper-right point of the second "
1929 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1930 "CPL_TYPE_INT", urx2,
1932 "y coord of the upper-right point of the second "
1933 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1934 "CPL_TYPE_INT", ury2,
1936 "x coord of the lower-left point of the third "
1937 "field used for contamination measurement. If not modified, default value will be 1.",
1938 "CPL_TYPE_INT", llx3,
1940 "y coord of the lower-left point of the third "
1941 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1942 "CPL_TYPE_INT", lly3,
1944 "x coord of the upper-right point of the third "
1945 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1946 "CPL_TYPE_INT", urx3,
1948 "y coord of the upper-right point of the third "
1949 "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
1950 "CPL_TYPE_INT", ury3,
1952 "x coord of the lower-left point of the fourth "
1953 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1954 "CPL_TYPE_INT", llx4,
1956 "y coord of the lower-left point of the fourth "
1957 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1958 "CPL_TYPE_INT", lly4,
1960 "x coord of the upper-right point of the fourth "
1961 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1962 "CPL_TYPE_INT", urx4,
1964 "y coord of the upper-right point of the fourth "
1965 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1966 "CPL_TYPE_INT", ury4,
1968 "x coord of the lower-left point of the fifth "
1969 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1970 "CPL_TYPE_INT", llx5,
1972 "y coord of the lower-left point of the fifth "
1973 "field used for contamination measurement. If not modified, default value will be 1.",
1974 "CPL_TYPE_INT", lly5,
1976 "x coord of the upper-right point of the fifth "
1977 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1978 "CPL_TYPE_INT", urx5,
1981 "y coord of the upper-right point of the fifth "
1982 "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
1983 "CPL_TYPE_INT", ury5);
1986 cpl_ensure_code(!erroropt, erroropt);
1989 cpl_ensure_code(!error, error);
1991 return cpl_error_get_code();
2004 static cpl_error_code
2005 detmon_lg_retrieve_parlist(
const char * pipeline_name,
2006 const char * recipe_name,
2007 const cpl_parameterlist * parlist,
2008 cpl_boolean opt_nir)
2012 const cpl_parameter * par;
2015 par_name = cpl_sprintf(
"%s.%s.method", pipeline_name, recipe_name);
2016 assert(par_name != NULL);
2017 par = cpl_parameterlist_find_const(parlist, par_name);
2018 detmon_lg_config.method = cpl_parameter_get_string(par);
2022 detmon_lg_config.order =
2023 detmon_retrieve_par_int(
"order", pipeline_name, recipe_name,
2027 detmon_lg_config.kappa =
2028 detmon_retrieve_par_double(
"kappa", pipeline_name, recipe_name,
2032 detmon_lg_config.niter =
2033 detmon_retrieve_par_int(
"niter", pipeline_name, recipe_name,
2037 detmon_lg_config.llx =
2038 detmon_retrieve_par_int(
"llx", pipeline_name, recipe_name,
2042 detmon_lg_config.lly =
2043 detmon_retrieve_par_int(
"lly", pipeline_name, recipe_name,
2047 detmon_lg_config.urx =
2048 detmon_retrieve_par_int(
"urx", pipeline_name, recipe_name,
2052 detmon_lg_config.ury =
2053 detmon_retrieve_par_int(
"ury", pipeline_name, recipe_name,
2057 detmon_lg_config.ref_level =
2058 detmon_retrieve_par_int(
"ref_level", pipeline_name, recipe_name,
2063 cpl_sprintf(
"%s.%s.intermediate", pipeline_name, recipe_name);
2064 assert(par_name != NULL);
2065 par = cpl_parameterlist_find_const(parlist, par_name);
2066 detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
2070 par_name = cpl_sprintf(
"%s.%s.autocorr", pipeline_name, recipe_name);
2071 assert(par_name != NULL);
2072 par = cpl_parameterlist_find_const(parlist, par_name);
2073 detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
2077 par_name = cpl_sprintf(
"%s.%s.coeffs_cube_split", pipeline_name, recipe_name);
2078 assert(par_name != NULL);
2079 par = cpl_parameterlist_find_const(parlist, par_name);
2080 detmon_lg_config.split_coeffs = cpl_parameter_get_bool(par);
2084 par_name = cpl_sprintf(
"%s.%s.collapse", pipeline_name, recipe_name);
2085 assert(par_name != NULL);
2086 par = cpl_parameterlist_find_const(parlist, par_name);
2087 detmon_lg_config.collapse = cpl_parameter_get_bool(par);
2091 par_name = cpl_sprintf(
"%s.%s.rescale", pipeline_name, recipe_name);
2092 assert(par_name != NULL);
2093 par = cpl_parameterlist_find_const(parlist, par_name);
2094 detmon_lg_config.rescale = cpl_parameter_get_bool(par);
2098 par_name = cpl_sprintf(
"%s.%s.pix2pix", pipeline_name, recipe_name);
2099 assert(par_name != NULL);
2100 par = cpl_parameterlist_find_const(parlist, par_name);
2101 detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
2105 par_name = cpl_sprintf(
"%s.%s.bpmbin", pipeline_name, recipe_name);
2106 assert(par_name != NULL);
2107 par = cpl_parameterlist_find_const(parlist, par_name);
2108 detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
2112 detmon_lg_config.filter =
2113 detmon_retrieve_par_int(
"filter", pipeline_name,
2114 recipe_name, parlist);
2117 detmon_lg_config.m =
2118 detmon_retrieve_par_int(
"m", pipeline_name, recipe_name, parlist);
2121 detmon_lg_config.n =
2122 detmon_retrieve_par_int(
"n", pipeline_name, recipe_name, parlist);
2125 par_name = cpl_sprintf(
"%s.%s.tolerance", pipeline_name, recipe_name);
2126 assert(par_name != NULL);
2127 par = cpl_parameterlist_find_const(parlist, par_name);
2128 detmon_lg_config.tolerance = cpl_parameter_get_double(par);
2133 par_name = cpl_sprintf(
"%s.%s.pafgen", pipeline_name, recipe_name);
2134 assert(par_name != NULL);
2135 par = cpl_parameterlist_find_const(parlist, par_name);
2136 detmon_lg_config.pafgen = cpl_parameter_get_bool(par);
2140 par_name = cpl_sprintf(
"%s.%s.pafname", pipeline_name, recipe_name);
2141 assert(par_name != NULL);
2142 par = cpl_parameterlist_find_const(parlist, par_name);
2143 detmon_lg_config.pafname = cpl_parameter_get_string(par);
2146 if(opt_nir == OPT) {
2148 detmon_lg_config.llx1 =
2149 detmon_retrieve_par_int(
"llx1", pipeline_name, recipe_name,
2153 detmon_lg_config.lly1 =
2154 detmon_retrieve_par_int(
"lly1", pipeline_name, recipe_name,
2158 detmon_lg_config.urx1 =
2159 detmon_retrieve_par_int(
"urx1", pipeline_name, recipe_name,
2163 detmon_lg_config.ury1 =
2164 detmon_retrieve_par_int(
"ury1", pipeline_name, recipe_name,
2168 detmon_lg_config.llx2 =
2169 detmon_retrieve_par_int(
"llx2", pipeline_name, recipe_name,
2173 detmon_lg_config.lly2 =
2174 detmon_retrieve_par_int(
"lly2", pipeline_name, recipe_name,
2178 detmon_lg_config.urx2 =
2179 detmon_retrieve_par_int(
"urx2", pipeline_name, recipe_name,
2183 detmon_lg_config.ury2 =
2184 detmon_retrieve_par_int(
"ury2", pipeline_name, recipe_name,
2188 detmon_lg_config.llx3 =
2189 detmon_retrieve_par_int(
"llx3", pipeline_name, recipe_name,
2193 detmon_lg_config.lly3 =
2194 detmon_retrieve_par_int(
"lly3", pipeline_name, recipe_name,
2198 detmon_lg_config.urx3 =
2199 detmon_retrieve_par_int(
"urx3", pipeline_name, recipe_name,
2203 detmon_lg_config.ury3 =
2204 detmon_retrieve_par_int(
"ury3", pipeline_name, recipe_name,
2208 detmon_lg_config.llx4 =
2209 detmon_retrieve_par_int(
"llx4", pipeline_name, recipe_name,
2213 detmon_lg_config.lly4 =
2214 detmon_retrieve_par_int(
"lly4", pipeline_name, recipe_name,
2218 detmon_lg_config.urx4 =
2219 detmon_retrieve_par_int(
"urx4", pipeline_name, recipe_name,
2223 detmon_lg_config.ury4 =
2224 detmon_retrieve_par_int(
"ury4", pipeline_name, recipe_name,
2228 detmon_lg_config.llx5 =
2229 detmon_retrieve_par_int(
"llx5", pipeline_name, recipe_name,
2233 detmon_lg_config.lly5 =
2234 detmon_retrieve_par_int(
"lly5", pipeline_name, recipe_name,
2238 detmon_lg_config.urx5 =
2239 detmon_retrieve_par_int(
"urx5", pipeline_name, recipe_name,
2243 detmon_lg_config.ury5 =
2244 detmon_retrieve_par_int(
"ury5", pipeline_name, recipe_name,
2249 detmon_lg_config.exts =
2250 detmon_retrieve_par_int(
"exts", pipeline_name, recipe_name,
2254 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2256 cpl_sprintf(
"%s.%s.fpn_method", pipeline_name, recipe_name);
2257 assert(par_name != NULL);
2258 par = cpl_parameterlist_find_const(parlist, par_name);
2261 const char * str_method = cpl_parameter_get_string(par);
2262 if (strcmp(str_method,
"SMOOTH") == 0)
2264 detmon_lg_config.fpn_method = FPN_SMOOTH;
2266 else if (strcmp(str_method,
"HISTOGRAM") == 0)
2268 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2274 detmon_lg_config.fpn_smooth =
2275 detmon_retrieve_par_int(
"fpn_smooth", pipeline_name, recipe_name,
2279 detmon_lg_config.saturation_limit = 65535;
2281 cpl_sprintf(
"%s.%s.saturation_limit", pipeline_name, recipe_name);
2282 assert(par_name != NULL);
2283 par = cpl_parameterlist_find_const(parlist, par_name);
2286 detmon_lg_config.saturation_limit = cpl_parameter_get_double(par);
2293 detmon_lg_config.gain_threshold = 0;
2295 cpl_sprintf(
"%s.%s.gain_threshold", pipeline_name, recipe_name);
2296 assert(par_name != NULL);
2297 par = cpl_parameterlist_find_const(parlist, par_name);
2300 detmon_lg_config.gain_threshold = cpl_parameter_get_double(par);
2305 if(cpl_error_get_code())
2307 cpl_msg_error(cpl_func,
"Failed to retrieve the input parameters");
2308 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
2312 return cpl_error_get_code();
2322 static cpl_error_code
2323 detmon_lg_check_defaults(
const cpl_image * reference)
2325 const int nx = cpl_image_get_size_x(reference);
2326 const int ny = cpl_image_get_size_y(reference);
2328 detmon_lg_config.nx = nx;
2329 detmon_lg_config.ny = ny;
2331 detmon_lg_config.wholechip = CPL_FALSE;
2333 if(detmon_lg_config.llx == -1)
2334 detmon_lg_config.llx = 1;
2335 if(detmon_lg_config.lly == -1)
2336 detmon_lg_config.lly = 1;
2337 if(detmon_lg_config.urx == -1)
2338 detmon_lg_config.urx = nx;
2339 if(detmon_lg_config.ury == -1)
2340 detmon_lg_config.ury = ny;
2342 if (detmon_lg_config.llx == 1 &&
2343 detmon_lg_config.lly == 1 &&
2344 detmon_lg_config.urx == nx &&
2345 detmon_lg_config.ury == ny)
2346 detmon_lg_config.wholechip = CPL_TRUE;
2348 if(detmon_lg_config.llx1 == -1)
2349 detmon_lg_config.llx1 = 1;
2350 if(detmon_lg_config.lly1 == -1)
2351 detmon_lg_config.lly1 = 1;
2352 if(detmon_lg_config.urx1 == -1)
2353 detmon_lg_config.urx1 = nx;
2354 if(detmon_lg_config.ury1 == -1)
2355 detmon_lg_config.ury1 = ny;
2357 if(detmon_lg_config.llx2 == -1)
2358 detmon_lg_config.llx2 = 1;
2359 if(detmon_lg_config.lly2 == -1)
2360 detmon_lg_config.lly2 = 1;
2361 if(detmon_lg_config.urx2 == -1)
2362 detmon_lg_config.urx2 = nx / 2;
2363 if(detmon_lg_config.ury2 == -1)
2364 detmon_lg_config.ury2 = ny / 2;
2366 if(detmon_lg_config.llx3 == -1)
2367 detmon_lg_config.llx3 = 1;
2368 if(detmon_lg_config.lly3 == -1)
2369 detmon_lg_config.lly3 = ny / 2;
2370 if(detmon_lg_config.urx3 == -1)
2371 detmon_lg_config.urx3 = nx / 2;
2372 if(detmon_lg_config.ury3 == -1)
2373 detmon_lg_config.ury3 = ny;
2375 if(detmon_lg_config.llx4 == -1)
2376 detmon_lg_config.llx4 = nx / 2;
2377 if(detmon_lg_config.lly4 == -1)
2378 detmon_lg_config.lly4 = ny / 2;
2379 if(detmon_lg_config.urx4 == -1)
2380 detmon_lg_config.urx4 = nx;
2381 if(detmon_lg_config.ury4 == -1)
2382 detmon_lg_config.ury4 = ny;
2384 if(detmon_lg_config.llx5 == -1)
2385 detmon_lg_config.llx5 = nx / 2;
2386 if(detmon_lg_config.lly5 == -1)
2387 detmon_lg_config.lly5 = 1;
2388 if(detmon_lg_config.urx5 == -1)
2389 detmon_lg_config.urx5 = nx;
2390 if(detmon_lg_config.ury5 == -1)
2391 detmon_lg_config.ury5 = ny / 2;
2393 if(detmon_lg_config.intermediate == TRUE) {
2394 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.");
2395 detmon_lg_config.autocorr = TRUE;
2399 detmon_lg_config.lamp_stability = 0.0;
2401 detmon_lg_config.lamp_ok = FALSE;
2403 detmon_lg_config.cr = 0.0;
2405 return cpl_error_get_code();
2420 static cpl_error_code
2421 detmon_lg_split_onoff(
const cpl_frameset * cur_fset,
2422 cpl_frameset * cur_fset_on,
2423 cpl_frameset * cur_fset_off,
2425 const char *tag_off)
2430 cpl_frame * cur_frame_dup = NULL;
2433 const cpl_frame * first;
2434 const cpl_frame * second;
2435 const char * first_tag;
2436 const char * second_tag;
2437 skip_if((first = cpl_frameset_get_position_const(cur_fset, 0)) == NULL);
2438 skip_if((second = cpl_frameset_get_position_const(cur_fset, 1)) == NULL);
2440 skip_if((first_tag = cpl_frame_get_tag(first)) == NULL);
2441 skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
2442 if (opt_nir == OPT &&
2443 ((!strcmp(first_tag, tag_on ) && !strcmp(second_tag, tag_off)) ||
2444 (!strcmp(first_tag, tag_off) && !strcmp(second_tag, tag_on )))) {
2445 detmon_lg_config.lamp_ok = TRUE;
2449 nframes = cpl_frameset_get_size(cur_fset);
2450 for(i = detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
2451 const cpl_frame * cur_frame =
2452 cpl_frameset_get_position_const(cur_fset, i);
2456 cur_frame_dup = cpl_frame_duplicate(cur_frame);
2457 tag = (
char *) cpl_frame_get_tag(cur_frame_dup);
2460 if(!strcmp(tag, tag_on)) {
2461 skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
2462 }
else if(!strcmp(tag, tag_off)) {
2463 skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
2465 cpl_frame_delete(cur_frame_dup);
2466 cur_frame_dup = NULL;
2469 cur_frame_dup = NULL;
2473 cpl_frame_delete(cur_frame_dup);
2475 return cpl_error_get_code();
2502 static cpl_error_code
2503 detmon_lg_reduce(
const cpl_frameset * set_on,
2504 const cpl_frameset * set_off,
2505 int* index_on,
int* index_off,
2506 double* exptime_on,
double* exptime_off,
2507 int *next_index_on,
int* next_index_off,
2508 cpl_imagelist ** coeffs_ptr,
2509 cpl_table * gain_table,
2510 cpl_table * linear_table,
2511 cpl_image ** bpm_ptr,
2512 cpl_imagelist * autocorr_images,
2513 cpl_imagelist * diff_flats,
2514 cpl_propertylist * gaint_qclist,
2515 cpl_propertylist * lint_qclist,
2516 cpl_propertylist * linc_qclist,
2517 cpl_propertylist * bpm_qclist,
2518 int (* load_fset) (
const cpl_frameset *,
2521 const cpl_boolean opt_nir,
2524 cpl_errorstate prestate = cpl_errorstate_get();
2525 const double D_INVALID_VALUE = -999;
2527 cpl_imagelist * linearity_inputs = NULL;
2528 cpl_imagelist * opt_offs = NULL;
2530 cpl_propertylist * reflist = NULL;
2532 int rows_linear_affected = 1;
2533 int rows_gain_affected = 1;
2534 int last_linear_best = 0;
2536 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2537 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2539 nsets = cpl_frameset_get_size(set_on) / 2;
2541 detmon_lg_config.load_fset = load_fset;
2542 if(detmon_lg_config.collapse) {
2549 const cpl_frame *first = cpl_frameset_get_position_const(set_off, 0);
2550 cpl_frame *dup_first = cpl_frame_duplicate(first);
2552 const cpl_frame *second = cpl_frameset_get_position_const(set_off, 1);
2553 cpl_frame *dup_second = cpl_frame_duplicate(second);
2555 cpl_frameset *raw_offs = cpl_frameset_new();
2557 skip_if(cpl_frameset_insert(raw_offs, dup_first));
2558 skip_if(cpl_frameset_insert(raw_offs, dup_second));
2560 opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
2563 cpl_frameset_delete(raw_offs);
2564 if (opt_offs == NULL) {
2565 cpl_errorstate_set(prestate);
2566 return CPL_ERROR_CONTINUE;
2570 skip_if(detmon_lg_reduce_init(gain_table,
2582 if(detmon_lg_lamp_stab(set_on, set_off,
2583 opt_nir, whichext)) {
2584 cpl_errorstate_set(prestate);
2587 if(!detmon_lg_config.collapse)
2591 skip_if(cpl_table_unselect_all(linear_table));
2592 skip_if(cpl_table_unselect_all(gain_table));
2596 for(i = 0; i < nsets ; i++)
2598 skip_if(detmon_lg_reduce_dit(set_on,
2599 index_on, exptime_on,
2603 index_off, exptime_off,
2604 next_index_on, next_index_off,
2606 gain_table, linearity_inputs,
2607 lint_qclist, opt_nir,
2608 autocorr_images, diff_flats,
2610 &rows_linear_affected,&rows_gain_affected));
2614 if (rows_linear_affected == 0)
2616 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2617 "into linear calculation, check the messages above");
2618 cpl_table_select_row(linear_table, i);
2622 last_linear_best = i;
2625 if (rows_gain_affected == 0)
2627 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2628 "into gain calculation, check the messages above");
2629 cpl_table_select_row(gain_table, i);
2636 skip_if(detmon_add_adl_column(linear_table, opt_nir));
2642 skip_if(cpl_table_erase_selected(gain_table));
2643 skip_if(cpl_table_erase_selected(linear_table));
2646 reflist = cpl_propertylist_new();
2647 skip_if(cpl_propertylist_append_bool(reflist,
"ADU", FALSE));
2648 skip_if(cpl_table_sort(gain_table, reflist));
2654 skip_if(detmon_lg_reduce_all(linear_table,
2655 gaint_qclist, lint_qclist, linc_qclist,
2656 bpm_qclist, coeffs_ptr, bpm_ptr,
2658 gain_table, whichext, opt_nir));
2661 double gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
2664 cpl_error_code cplerr = cpl_error_get_code();
2665 if (cplerr != CPL_ERROR_NONE || (gain == 0.0))
2667 cpl_msg_warning(cpl_func,
"Cannot read gain from QC parameters - "
2668 "FPN will not be computed");
2673 detmon_fpn_compute(set_on, index_on, last_linear_best, lint_qclist,
2674 detmon_lg_config.llx,
2675 detmon_lg_config.lly,
2676 detmon_lg_config.urx,
2677 detmon_lg_config.ury,
2680 detmon_lg_config.fpn_method,
2681 detmon_lg_config.fpn_smooth);
2686 detmon_table_fill_invalid(gain_table, D_INVALID_VALUE);
2688 cpl_imagelist_delete(linearity_inputs);
2689 cpl_imagelist_delete(opt_offs);
2690 cpl_propertylist_delete(reflist);
2692 return cpl_error_get_code();
2695 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code)
2697 int ncols = cpl_table_get_ncol(ptable);
2698 cpl_array* pnames = cpl_table_get_column_names(ptable);
2699 int nrows = cpl_table_get_nrow(ptable);
2701 for (i=0; i < ncols; i++)
2704 for (j = 0; j< nrows; j++)
2706 const char* colname = cpl_array_get_data_string_const(pnames)[i];
2708 cpl_type type = cpl_table_get_column_type(ptable, colname);
2709 cpl_table_get(ptable, colname, j, &isnull);
2712 if (type == CPL_TYPE_DOUBLE)
2714 cpl_table_set(ptable,colname,j, code);
2716 else if (type == CPL_TYPE_FLOAT)
2718 cpl_table_set_float(ptable,colname,j, (
float)code);
2723 cpl_array_delete(pnames);
2724 return cpl_error_get_code();
2727 static cpl_error_code
2728 detmon_fpn_compute(
const cpl_frameset *set_on,
2730 int last_linear_best,
2731 cpl_propertylist *lint_qclist,
2738 FPN_METHOD fpn_method,
2742 const cpl_image* im1 = 0;
2744 cpl_imagelist* ons = 0;
2745 cpl_frameset * pair_on = 0;
2746 int nsets_extracted = cpl_frameset_get_size(set_on);
2747 cpl_size * selection = NULL;
2756 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
2757 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
2759 selection[index_on[last_linear_best*2 + 0] ] = 1;
2760 selection[index_on[last_linear_best*2 + 1] ] = 1;
2761 pair_on = cpl_frameset_extract(set_on, selection, 1);
2762 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2764 skip_if(ons == NULL);
2765 skip_if((im1 = cpl_imagelist_get_const(ons, 0)) == NULL);
2767 fpn = irplib_fpn_lg(im1, range, gain, fpn_method, smooth_size, &mse);
2768 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_FPN,
2770 skip_if(cpl_propertylist_append_double(lint_qclist,
"ESO QC GAIN ERR",
2774 cpl_frameset_delete(pair_on);
2775 cpl_imagelist_delete(ons);
2776 cpl_free(selection);
2777 return cpl_error_get_code();
2789 static cpl_error_code
2790 detmon_lg_lamp_stab(
const cpl_frameset * lamps,
2791 const cpl_frameset * darks,
2792 cpl_boolean opt_nir,
2805 cpl_vector * selection = NULL;
2806 cpl_propertylist * plist;
2807 double dit_lamp, dit_dark;
2809 cpl_imagelist * lamps_data = NULL;
2810 cpl_imagelist * darks_data = NULL;
2811 double * stab_levels = NULL;
2813 double * ditvals = NULL;
2817 cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
2818 CPL_ERROR_ILLEGAL_INPUT);
2824 cpl_msg_info(__func__,
"Checking DIT consistency");
2825 selection = cpl_vector_new(nb_lamps);
2826 ditvals = cpl_malloc(nb_lamps *
sizeof(
double));
2828 for (i = 0; i < nb_lamps; i++) {
2829 const cpl_frame * c_lamp;
2830 const cpl_frame * c_dark;
2832 skip_if (cpl_error_get_code());
2835 c_lamp = cpl_frameset_get_position_const(lamps, i);
2836 plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
2838 dit_lamp = (double)detmon_pfits_get_dit(plist);
2840 dit_lamp = (double)detmon_pfits_get_dit_opt(plist);
2841 cpl_propertylist_delete(plist);
2842 skip_if (cpl_error_get_code());
2845 c_dark = cpl_frameset_get_position_const(darks, i);
2846 plist = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
2848 dit_dark = (double)detmon_pfits_get_dit(plist);
2850 dit_dark = (double)detmon_pfits_get_dit_opt(plist);
2851 cpl_propertylist_delete(plist);
2852 skip_if (cpl_error_get_code());
2855 if (fabs(dit_dark-dit_lamp) > 1e-3) {
2856 cpl_msg_error(__func__,
"DIT not consistent between LAMP and DARK, skip lamp stability computation");
2861 ditvals[i] = dit_lamp;
2864 cpl_vector_set(selection, i, -1.0);
2872 if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
2873 cpl_vector_set(selection, i, -1.0);
2877 cpl_vector_set(selection, i, 1.0);
2884 cpl_msg_info(__func__,
"Not enough frames for stability check");
2888 cpl_msg_info(__func__,
"Compute the differences lamp - dark");
2891 lamps_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2893 detmon_lg_config.llx,
2894 detmon_lg_config.lly,
2895 detmon_lg_config.urx,
2896 detmon_lg_config.ury,
2899 darks_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2901 detmon_lg_config.llx,
2902 detmon_lg_config.lly,
2903 detmon_lg_config.urx,
2904 detmon_lg_config.ury,
2907 nb_darks=cpl_imagelist_get_size(darks_data);
2908 if(nb_darks==nb_lamps) {
2909 skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
2911 cpl_image* master_dark=cpl_imagelist_collapse_median_create(darks_data);
2912 cpl_imagelist_subtract_image(lamps_data,master_dark);
2913 cpl_image_delete(master_dark);
2916 cpl_msg_info(__func__,
"Check the lamp stability");
2917 stab_levels = cpl_malloc(dit_stab *
sizeof(
double));
2919 for (i=0; i<nb_lamps; i++) {
2920 if (cpl_vector_get(selection, i) < 0) {
2922 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
2928 for (i=1; i<dit_stab; i++) {
2929 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
2930 detmon_lg_config.lamp_stability)
2931 detmon_lg_config.lamp_stability =
2932 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
2937 if (detmon_lg_config.lamp_stability > 0.01) {
2938 cpl_msg_warning(__func__,
2939 "Lamp stability level %g difference too high - proceed anyway",detmon_lg_config.lamp_stability);
2946 cpl_vector_delete(selection);
2947 cpl_imagelist_delete(lamps_data);
2948 cpl_imagelist_delete(darks_data);
2949 cpl_free(stab_levels);
2951 return cpl_error_get_code();
2978 static cpl_error_code
2979 detmon_lg_reduce_dit(
const cpl_frameset * set_on,
2980 int* index_on,
double* exptime_on,
2983 const cpl_frameset * set_off,
2984 int * index_off,
double* exptime_off,
2985 int* next_on,
int* next_off,
2986 cpl_table * linear_table,
2987 cpl_table * gain_table,
2988 cpl_imagelist * linearity_inputs,
2989 cpl_propertylist * qclist,
2990 cpl_boolean opt_nir,
2991 cpl_imagelist * autocorr_images,
2992 cpl_imagelist * diff_flats,
2993 cpl_imagelist * opt_offs,
2995 int* rows_linear_affected,
2996 int* rows_gain_affected)
2998 cpl_frameset * pair_on = NULL;
2999 cpl_frameset * pair_off = NULL;
3000 cpl_imagelist * ons = NULL;
3001 cpl_imagelist * offs = NULL;
3002 cpl_boolean follow = CPL_TRUE;
3003 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
3007 double current_dit = 0;
3009 const char * filename;
3011 cpl_propertylist * plist = NULL;
3012 cpl_propertylist* pDETlist = NULL;
3014 mode = detmon_lg_config.collapse ?
3015 mode | IRPLIB_GAIN_COLLAPSE | IRPLIB_LIN_COLLAPSE:
3016 mode | IRPLIB_GAIN_NO_COLLAPSE | IRPLIB_LIN_NO_COLLAPSE;
3017 mode = detmon_lg_config.pix2pix ?
3018 mode | IRPLIB_LIN_PIX2PIX : mode;
3020 mode | IRPLIB_GAIN_NIR | IRPLIB_LIN_NIR :
3021 mode | IRPLIB_GAIN_OPT | IRPLIB_LIN_OPT ;
3025 skip_if(detmon_pair_extract_next(set_on, index_on, next_on, exptime_on, &pair_on, detmon_lg_config.tolerance));
3026 current_dit = exptime_on[*next_on - 1];
3029 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
3030 skip_if(ons == NULL);
3031 cpl_msg_debug(cpl_func,
" Loaded ON images: %" CPL_SIZE_FORMAT
3032 ", exptime[%f]",cpl_imagelist_get_size(ons), current_dit );
3033 if(cpl_imagelist_get_size(ons) != 2)
3035 cpl_msg_error(cpl_func,
"cannot take ON pair, number of images[%"
3036 CPL_SIZE_FORMAT
"]", cpl_imagelist_get_size(ons));
3039 if(detmon_lg_config.filter > 0)
3042 cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
3043 detmon_lg_config.llx,
3044 detmon_lg_config.lly,
3045 detmon_lg_config.urx,
3046 detmon_lg_config.ury);
3048 cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
3049 detmon_lg_config.llx,
3050 detmon_lg_config.lly,
3051 detmon_lg_config.urx,
3052 detmon_lg_config.ury);
3056 if ( med1 > (
double)detmon_lg_config.filter ||
3057 med2 > (
double)detmon_lg_config.filter)
3060 cpl_table_select_row(gain_table, dit_nb);
3061 cpl_table_select_row(linear_table, dit_nb);
3063 cpl_msg_warning(cpl_func,
"Frames of EXPTIME nb %d "
3064 "will not be taken into account for computation "
3065 "as the median of the on frames computed on the "
3066 "user defined region [%d,%d,%d,%d] are above "
3067 "--filter threshold (%d)",
3069 detmon_lg_config.llx,
3070 detmon_lg_config.lly,
3071 detmon_lg_config.urx,
3072 detmon_lg_config.ury,
3073 detmon_lg_config.filter);
3077 if (follow || detmon_lg_config.filter < 0)
3085 if(!detmon_lg_config.collapse)
3102 if (!strcmp(detmon_lg_config.method,
"MED") ||
3103 cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
3105 skip_if(detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off, detmon_lg_config.tolerance));
3109 skip_if(detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
3112 cpl_msg_debug(cpl_func,
" Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
3113 offs = detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
3115 skip_if(offs == NULL);
3116 skip_if(cpl_error_get_code());
3119 offs = (cpl_imagelist *) opt_offs;
3123 if(detmon_lg_config.rescale)
3125 skip_if(detmon_lg_rescale(ons));
3126 if (!detmon_lg_config.collapse &&
3127 !strcmp(detmon_lg_config.method,
"MED"))
3128 skip_if(detmon_lg_rescale(offs));
3133 cpl_frame_get_filename(cpl_frameset_get_position_const(pair_on, 0));
3134 skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
3138 pDETlist = cpl_propertylist_new();
3139 cpl_propertylist_copy_property_regexp(pDETlist, plist,
"DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
3142 irplib_table_create_column(gain_table, pDETlist);
3143 irplib_table_create_column(linear_table, pDETlist);
3146 if(opt_nir == NIR) {
3147 c_dit = detmon_pfits_get_dit(plist);
3148 c_ndit = irplib_pfits_get_ndit(plist);
3150 c_dit = irplib_pfits_get_exptime(plist);
3162 cpl_msg_info(cpl_func,
"Computing GAIN for EXPTIME value nb %d",
3166 if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
3168 cpl_table_erase_column(gain_table,
"MEAN_OFF1");
3169 cpl_table_erase_column(gain_table,
"MEAN_OFF2");
3170 cpl_table_erase_column(gain_table,
"SIG_OFF_DIF");
3171 cpl_table_erase_column(gain_table,
"GAIN");
3172 cpl_table_erase_column(gain_table,
"GAIN_CORR");
3173 cpl_table_new_column(gain_table,
"MEAN_OFF", CPL_TYPE_DOUBLE);
3177 skip_if(detmon_gain_table_fill_row(gain_table,
3180 diff_flats, ons, offs,
3181 detmon_lg_config.kappa,
3182 detmon_lg_config.niter,
3183 detmon_lg_config.llx,
3184 detmon_lg_config.lly,
3185 detmon_lg_config.urx,
3186 detmon_lg_config.ury,
3189 detmon_lg_config.gain_threshold,
3190 dit_nb, mode, rows_gain_affected));
3193 skip_if(detmon_check_saturation_on_pair(autocorr_images,
3195 detmon_lg_config.kappa,
3196 detmon_lg_config.niter,
3197 detmon_lg_config.llx,
3198 detmon_lg_config.lly,
3199 detmon_lg_config.urx,
3200 detmon_lg_config.ury,
3201 detmon_lg_config.saturation_limit,
3202 dit_nb, mode, rows_linear_affected));
3205 if (*rows_gain_affected)
3208 skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
3210 cpl_msg_info(cpl_func,
"Linearity reduction for nb %d",
3213 if (*rows_linear_affected) {
3214 skip_if(detmon_lin_table_fill_row(linear_table, c_dit,
3215 linearity_inputs, ons, offs,
3216 detmon_lg_config.llx,
3217 detmon_lg_config.lly,
3218 detmon_lg_config.urx,
3219 detmon_lg_config.ury,
3220 dit_nb, *dit_nskip, mode));
3222 skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
3234 if(opt_nir == OPT &&
3235 *rows_linear_affected != 0 ) {
3236 detmon_opt_contamination(ons, offs, mode, qclist);
3243 cpl_frameset_delete(pair_on);
3244 cpl_imagelist_delete(ons);
3246 if(!detmon_lg_config.collapse ) {
3247 cpl_imagelist_delete(offs);
3250 if(!detmon_lg_config.collapse) {
3251 cpl_frameset_delete(pair_off);
3254 cpl_propertylist_delete(plist);
3255 cpl_propertylist_delete(pDETlist);
3256 return cpl_error_get_code();
3266 static cpl_error_code
3267 detmon_add_adl_column(cpl_table * table,
3268 cpl_boolean opt_nir)
3270 cpl_error_code error;
3271 double mean_med_dit;
3274 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
3276 mean_med_dit = cpl_table_get_column_mean(table,
"MED_DIT");
3278 dits = cpl_table_get_data_double(table,
"EXPTIME");
3280 dits = cpl_table_get_data_double(table,
"DIT");
3282 error = cpl_table_copy_data_double(table,
"ADL", dits);
3283 cpl_ensure_code(!error, error);
3284 error = cpl_table_multiply_scalar(table,
"ADL", mean_med_dit);
3285 cpl_ensure_code(!error, error);
3287 return cpl_error_get_code();
3299 static cpl_error_code
3300 detmon_lg_reduce_init(cpl_table * gain_table,
3301 cpl_table * linear_table,
3302 cpl_imagelist ** linearity_inputs,
3303 const cpl_boolean opt_nir)
3305 skip_if(detmon_gain_table_create(gain_table, opt_nir));
3306 skip_if(detmon_lin_table_create(linear_table, opt_nir));
3308 if(detmon_lg_config.pix2pix) {
3309 *linearity_inputs = cpl_imagelist_new();
3310 skip_if(*linearity_inputs == NULL);
3315 return cpl_error_get_code();
3326 detmon_pfits_get_dit(
const cpl_propertylist * plist)
3328 if (cpl_propertylist_has(plist,
"ESO DET DIT")) {
3330 return irplib_pfits_get_prop_double(plist,
"ESO DET DIT");
3333 return irplib_pfits_get_prop_double(plist,
"ESO DET SEQ1 DIT");
3335 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"FITS key "
3336 "ESO DET DIT or ESO DET DIT not found");
3348 detmon_pfits_get_dit_opt(
const cpl_propertylist * plist)
3350 if (cpl_propertylist_has(plist,
"ESO DET WIN1 UIT1")) {
3352 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3353 }
else if (cpl_propertylist_has(plist,
"ESO DET UIT1")) {
3355 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3358 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"FITS key "
3359 "ESO DET WIN1 UIT1 or ESO DET UIT1 not found");
3369 static cpl_propertylist*
3370 detmon_load_pro_keys(
const char* NAME_O)
3372 cpl_propertylist* pro_keys=NULL;
3373 pro_keys=cpl_propertylist_load_regexp(NAME_O,0,
"^(ESO PRO)",0);
3378 static double irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
3379 const char* prop_name)
3382 dit = cpl_propertylist_get_double(plist, prop_name);
3383 if(cpl_error_get_code() != CPL_ERROR_NONE)
3385 cpl_msg_error(cpl_func,
"Cannot read property '%s', err[%s]",
3386 prop_name, cpl_error_get_where());
3391 static cpl_error_code
3392 detmon_gain_compute_qc(
double kappa,
int nclip,
const int pos,
3393 const cpl_imagelist* offs,
unsigned mode,
3394 double avg_on1,
double avg_on2,
3395 double avg_off1,
double avg_off2,
3396 double sig_off_dif,
int c_ndit,
3397 double autocorr, cpl_image* on_dif,
3398 cpl_table* gain_table)
3403 double avg_on_dif, sig_on_dif;
3404 irplib_ksigma_clip(on_dif, 1, 1, cpl_image_get_size_x(on_dif),
3405 cpl_image_get_size_y(on_dif), kappa, nclip, 1e-5,
3406 &avg_on_dif, &sig_on_dif);
3408 cpl_table_set_double(gain_table,
"SIG_ON_DIF", pos,
3410 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3411 double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
3414 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
3417 = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
3421 const double gain = double_adu / (c_ndit * sigma);
3423 const double gain_corr = gain / (autocorr);
3425 skip_if(cpl_table_set_double(gain_table,
"GAIN", pos, gain));
3427 cpl_table_set_double(gain_table,
"GAIN_CORR", pos,
3431 skip_if(cpl_table_set_double(gain_table,
"AUTOCORR", pos, autocorr));
3432 skip_if(cpl_table_set_double(gain_table,
"ADU", pos, double_adu / 2));
3435 cpl_table_set_double(gain_table,
"Y_FIT", pos,
3436 c_ndit * sig_on_dif * sig_on_dif));
3438 cpl_table_set_double(gain_table,
"Y_FIT_CORR", pos,
3439 c_ndit * sig_on_dif * sig_on_dif));
3440 skip_if(cpl_table_set_double(gain_table,
"X_FIT", pos, double_adu));
3442 cpl_table_set_double(gain_table,
"X_FIT_CORR", pos,
3443 double_adu / autocorr));
3447 return cpl_error_get_code();
3451 detmon_gain_prepare_autocorr(
unsigned mode,
const int pos,
3452 int m,
int n, cpl_imagelist* diff_flats,
3453 cpl_image* on_dif, cpl_imagelist* autocorr_images)
3455 double autocorr = 1.0;
3457 if (mode & IRPLIB_GAIN_WITH_AUTOCORR) {
3459 cpl_image * diff = cpl_image_duplicate(on_dif);
3460 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
3462 if (autocorr_images) {
3463 cpl_image * corr = NULL;
3464 autocorr = detmon_autocorr_factor(on_dif, &corr, m, n);
3466 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
3469 detmon_lg_add_empty_image(autocorr_images, pos);
3473 autocorr = detmon_autocorr_factor(on_dif, NULL, m, n);
3475 autocorr = isnan(autocorr) ? 1.0 : autocorr;
3483 detmon_gain_prepare_table(
const cpl_imagelist* offs,
unsigned mode,
int llx,
3484 int lly,
int urx,
int ury,
double kappa,
int nclip,
3485 double std,
const int pos,
3486 cpl_table* gain_table,
double* avg_off2,
3487 double* sig_off_dif)
3489 double avg_off1 = 0.0;
3496 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3499 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3500 llx, lly, urx, ury, kappa, nclip, 1e-5,
3502 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF", pos, avg_off1));
3505 else if ((mode & IRPLIB_GAIN_NO_COLLAPSE)
3506 || (pos == 0 && mode & IRPLIB_GAIN_COLLAPSE)) {
3507 cpl_image * off_dif = NULL;
3510 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3511 llx, lly, urx, ury, kappa, nclip, 1e-5,
3513 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3515 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 1),
3516 llx, lly, urx, ury, kappa, nclip, 1e-5,
3518 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3519 off_dif = detmon_subtract_create_window(
3520 cpl_imagelist_get_const(offs, 0),
3521 cpl_imagelist_get_const(offs, 1), llx, lly, urx, ury);
3522 skip_if(off_dif == NULL);
3523 irplib_ksigma_clip(off_dif, 1, 1, cpl_image_get_size_x(off_dif),
3524 cpl_image_get_size_y(off_dif), kappa, nclip, 1e-5,
3525 &avg_off_dif, sig_off_dif);
3526 cpl_image_delete(off_dif);
3528 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3531 else if (pos > 0 && (mode & IRPLIB_GAIN_COLLAPSE)) {
3534 avg_off1 = cpl_table_get_double(gain_table,
"MEAN_OFF1", 0, &status);
3535 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3536 *avg_off2 = cpl_table_get_double(gain_table,
"MEAN_OFF2", 0, &status);
3537 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3538 *sig_off_dif = cpl_table_get_double(gain_table,
"SIG_OFF_DIF", 0,
3541 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3586 static cpl_error_code
3587 detmon_gain_table_fill_row(cpl_table * gain_table,
3588 double c_dit,
int c_ndit,
3589 cpl_imagelist * autocorr_images,
3590 cpl_imagelist * diff_flats,
3591 const cpl_imagelist * ons,
3592 const cpl_imagelist * offs,
3593 double kappa,
int nclip,
3594 int llx,
int lly,
int urx,
int ury,
3596 double gain_threshold,
3597 int pos,
unsigned mode,
int* rows_gain_affected)
3599 const cpl_image *image;
3600 cpl_image *on_dif = NULL;
3602 double avg_on1, avg_on2;
3603 double avg_off1, avg_off2;
3606 cpl_table_set(gain_table,
"FLAG", pos, 1);
3607 if (mode & IRPLIB_GAIN_NIR)
3609 cpl_table_set(gain_table,
"DIT", pos, c_dit);
3610 cpl_table_set(gain_table,
"NDIT", pos, c_ndit);
3611 }
else if (mode & IRPLIB_GAIN_OPT)
3613 cpl_table_set(gain_table,
"EXPTIME", pos, c_dit);
3616 cpl_msg_error(cpl_func,
"Mandatory mode (OPT or NIR) not provided");
3619 if(*rows_gain_affected == 0)
3621 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3622 cpl_table_set(gain_table,
"FLAG", pos, 0);
3623 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3628 detmon_lg_add_empty_image(diff_flats, pos);
3630 if (autocorr_images)
3632 detmon_lg_add_empty_image(autocorr_images, pos);
3635 return cpl_error_get_code();
3637 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3638 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3639 nclip, 1e-5, &avg_on1, &std));
3640 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3641 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3642 nclip, 1e-5, &avg_on2, &std));
3645 (avg_on1 > gain_threshold) ||
3646 (avg_on2 > gain_threshold)
3652 if ( (avg_on1 > gain_threshold) || (avg_on2 > gain_threshold) )
3654 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the gain_theshold parameter, "
3655 "the frames would not be taken into calculation");
3657 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3658 avg_on1, avg_on2, gain_threshold);
3661 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3662 cpl_table_set(gain_table,
"FLAG", pos, 0);
3663 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3668 detmon_lg_add_empty_image(diff_flats, pos);
3670 if (autocorr_images)
3672 detmon_lg_add_empty_image(autocorr_images, pos);
3675 *rows_gain_affected = 0;
3683 *rows_gain_affected = 1;
3684 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON1", pos, avg_on1));
3685 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON2", pos, avg_on2));
3688 detmon_subtract_create_window(cpl_imagelist_get_const(ons, 0),
3689 cpl_imagelist_get_const(ons, 1),
3690 llx, lly, urx, ury);
3691 skip_if(on_dif == NULL);
3693 autocorr = detmon_gain_prepare_autocorr(mode, pos, m, n,
3694 diff_flats, on_dif, autocorr_images);
3696 avg_off1 = detmon_gain_prepare_table(offs, mode, llx, lly, urx, ury,
3697 kappa, nclip, std, pos, gain_table, &avg_off2,
3700 detmon_gain_compute_qc(kappa, nclip, pos, offs, mode,
3701 avg_on1, avg_on2, avg_off1, avg_off2,
3702 sig_off_dif, c_ndit, autocorr, on_dif,
3707 cpl_image_delete(on_dif);
3709 return cpl_error_get_code();
3736 static cpl_error_code
3737 detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
3738 cpl_imagelist * diff_flats,
3739 const cpl_imagelist * ons,
3740 double kappa,
int nclip,
3741 int llx,
int lly,
int urx,
int ury,
3742 double saturation_limit,
3743 const int pos,
unsigned mode,
int* rows_linear_affected)
3745 const cpl_image *image;
3747 double avg_on1, avg_on2;
3750 if(*rows_linear_affected == 0)
3752 cpl_msg_info(cpl_func,
"For linearity skip the frame #%d", pos + 1);
3753 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3757 detmon_lg_add_empty_image(diff_flats, pos);
3759 if (autocorr_images)
3761 detmon_lg_add_empty_image(autocorr_images, pos);
3764 return cpl_error_get_code();
3766 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3767 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3768 nclip, 1e-5, &avg_on1, &std));
3769 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3770 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3771 nclip, 1e-5, &avg_on2, &std));
3774 (avg_on1 > saturation_limit) ||
3775 (avg_on2 > saturation_limit)
3781 if ( (avg_on1 > saturation_limit) || (avg_on2 > saturation_limit) )
3783 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the saturation_limit parameter, "
3784 "the frames would not be taken into calculation");
3786 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3787 avg_on1, avg_on2, saturation_limit);
3790 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3791 *rows_linear_affected = 0;
3798 return cpl_error_get_code();
3814 detmon_bpixs(
const cpl_imagelist * coeffs,
3821 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
3828 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
3829 cpl_image_get_size_y(first));
3831 cpl_image *bpm = NULL;
3834 int size = cpl_imagelist_get_size(coeffs);
3837 bpm = cpl_image_new(cpl_image_get_size_x(first),
3838 cpl_image_get_size_y(first),
3843 for(
int i = 0; i < size; i++) {
3844 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
3846 cpl_stats* stats = cpl_stats_new_from_image(cur_coeff,
3847 CPL_STATS_MEAN | CPL_STATS_STDEV);
3848 double cur_mean = cpl_stats_get_mean(stats);
3849 double cur_stdev = cpl_stats_get_stdev(stats);
3851 double lo_cut = cur_mean - kappa * cur_stdev;
3852 double hi_cut = cur_mean + kappa * cur_stdev;
3854 cpl_mask* cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
3855 cpl_mask_not(cur_mask);
3858 cpl_image* cur_image = cpl_image_new_from_mask(cur_mask);
3859 double p = pow(2, i);
3860 cpl_image_power(cur_image, p);
3861 cpl_image_add(bpm, cur_image);
3862 cpl_image_delete(cur_image);
3865 cpl_mask_or(mask, cur_mask);
3867 cpl_mask_delete(cur_mask);
3868 cpl_stats_delete(stats);
3872 bpm = cpl_image_new_from_mask(mask);
3875 *nbpixs = cpl_mask_count(mask);
3877 cpl_mask_delete(mask);
4004 detmon_autocorr_factor(
const cpl_image * image,
4005 cpl_image ** autocorr_image,
int m,
int n)
4007 cpl_image * mycorr_image = NULL;
4008 double autocorr = 0;
4011 mycorr_image = detmon_image_correlate(image, image, m, n);
4013 if (cpl_error_get_code() == CPL_ERROR_UNSUPPORTED_MODE)
4015 cpl_msg_warning(cpl_func,
"FFTW is not supported by CPL, autocorrelation "
4016 "would be computed using internal implementation");
4019 cpl_image_delete(mycorr_image);
4020 mycorr_image = detmon_autocorrelate(image, m, n);
4022 if(mycorr_image == NULL) {
4026 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
4028 autocorr = cpl_image_get_flux(mycorr_image);
4030 if (autocorr_image) *autocorr_image = mycorr_image;
4031 else cpl_image_delete(mycorr_image);
4036 static cpl_propertylist*
4037 detmon_lg_extract_qclist_4plane(cpl_propertylist* linc_qclist,
const int ip)
4040 cpl_propertylist* sub_set=NULL;
4043 sub_set=cpl_propertylist_new();
4044 qc_key=cpl_sprintf(
"QC LIN COEF%d",ip);
4045 cpl_propertylist_copy_property_regexp(sub_set,linc_qclist,qc_key,0);
4062 static cpl_error_code
4063 detmon_lg_extract_extention_header(cpl_frameset* frameset,
4064 cpl_propertylist* gaint_qclist,
4065 cpl_propertylist* lint_qclist,
4066 cpl_propertylist* linc_qclist,
4067 cpl_propertylist* bpm_qclist,
4071 cpl_propertylist * xplist = NULL;
4073 const char * filename =
4074 cpl_frame_get_filename(cpl_frameset_get_position(frameset, 0));
4076 xplist = cpl_propertylist_load_regexp(filename, whichext,
4077 "ESO DET|EXTNAME", 0);
4078 if (detmon_lg_config.exts >= 0)
4081 cpl_property* propExtname = NULL;
4082 propExtname = cpl_propertylist_get_property(xplist,
"EXTNAME");
4084 if (NULL != propExtname)
4086 propExtname = cpl_property_duplicate(propExtname);
4088 cpl_propertylist_delete(xplist);
4090 if (NULL != propExtname)
4092 xplist = cpl_propertylist_new();
4093 cpl_propertylist_append_property(xplist, propExtname);
4094 cpl_property_delete(propExtname);
4099 cpl_propertylist_append(gaint_qclist, xplist);
4100 cpl_propertylist_append(lint_qclist, xplist);
4101 cpl_propertylist_append(linc_qclist, xplist);
4102 cpl_propertylist_append(bpm_qclist, xplist);
4103 cpl_propertylist_delete(xplist);
4106 return cpl_error_get_code();
4123 static cpl_error_code
4124 detmon_lg_save_table_with_pro_keys(cpl_table* table,
4126 cpl_propertylist* xheader,
4127 unsigned CPL_IO_MODE)
4130 cpl_propertylist* pro_keys=NULL;
4132 pro_keys=detmon_load_pro_keys(name_o);
4133 cpl_propertylist_append(xheader,pro_keys);
4135 if(CPL_IO_MODE==CPL_IO_DEFAULT) {
4136 cpl_propertylist * pri_head=cpl_propertylist_load(name_o,0);
4137 cpl_table_save(table, pri_head,xheader,name_o,
4139 cpl_propertylist_delete(pri_head);
4142 cpl_table_save(table,NULL,xheader,name_o,
4145 cpl_propertylist_delete(pro_keys);
4147 return cpl_error_get_code();
4159 static cpl_error_code
4160 detmon_lg_save_image_with_pro_keys(cpl_image* image,
4162 cpl_propertylist* xheader)
4165 cpl_propertylist* pro_keys=NULL;
4166 pro_keys=detmon_load_pro_keys(name_o);
4167 cpl_propertylist_append(xheader,pro_keys);
4169 cpl_image_save(image,name_o, CPL_BPP_IEEE_FLOAT,
4170 xheader,CPL_IO_EXTEND);
4171 cpl_propertylist_delete(pro_keys);
4174 return cpl_error_get_code();
4186 static cpl_error_code
4187 detmon_lg_save_imagelist_with_pro_keys(cpl_imagelist* imagelist,
4189 cpl_propertylist* xheader)
4192 cpl_propertylist* pro_keys=NULL;
4193 pro_keys=detmon_load_pro_keys(name_o);
4194 cpl_propertylist_append(xheader,pro_keys);
4196 cpl_imagelist_save(imagelist,name_o, CPL_BPP_IEEE_FLOAT,
4197 xheader,CPL_IO_EXTEND);
4199 cpl_propertylist_delete(pro_keys);
4202 return cpl_error_get_code();
4222 static cpl_error_code
4223 detmon_lg_save_plane(
const cpl_parameterlist * parlist,
4224 cpl_frameset* frameset,
4225 const cpl_frameset * usedframes,
4227 const char* recipe_name,
4228 cpl_propertylist* mypro_coeffscube,
4229 cpl_propertylist* linc_plane_qclist,
4230 const char* package,
4234 if(detmon_lg_config.exts == 0) {
4235 cpl_propertylist* plist=NULL;
4236 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4238 CPL_BPP_IEEE_FLOAT, recipe_name,
4239 mypro_coeffscube, NULL,
4241 plist=cpl_propertylist_load(NAME_O,0);
4242 cpl_image_save(plane,NAME_O, CPL_BPP_IEEE_FLOAT,
4243 plist,CPL_IO_DEFAULT);
4244 cpl_propertylist_delete(plist);
4246 }
else if(detmon_lg_config.exts > 0) {
4247 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4249 CPL_BPP_IEEE_FLOAT, recipe_name,
4250 mypro_coeffscube, NULL,
4253 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4257 cpl_dfs_save_image(frameset, NULL, parlist,
4258 usedframes,NULL, NULL,
4259 CPL_BPP_IEEE_FLOAT, recipe_name,
4260 mypro_coeffscube, NULL,
4262 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4265 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4271 return cpl_error_get_code();
4294 static cpl_error_code
4295 detmon_lg_save_cube(
const cpl_parameterlist * parlist,
4296 cpl_frameset* frameset,
4297 const cpl_frameset * usedframes,
4299 const char* recipe_name,
4300 cpl_propertylist* mypro_coeffscube,
4301 cpl_propertylist* linc_qclist,
4302 const char* package,
4304 cpl_imagelist* coeffs)
4307 if(detmon_lg_config.exts == 0) {
4308 cpl_propertylist_append(mypro_coeffscube, linc_qclist);
4309 detmon_lg_dfs_save_imagelist
4310 (frameset, parlist, usedframes, coeffs,
4311 recipe_name, mypro_coeffscube, package,
4313 }
else if(detmon_lg_config.exts > 0) {
4314 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4316 CPL_BPP_IEEE_FLOAT, recipe_name,
4317 mypro_coeffscube, NULL,
4320 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4324 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4326 CPL_BPP_IEEE_FLOAT, recipe_name,
4327 mypro_coeffscube, NULL,
4330 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4332 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4335 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4337 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4341 return cpl_error_get_code();
4345 detmon_lg_set_paf_name_and_header(cpl_frame* ref_frame,
4346 int flag_sets,
int which_set,
4348 const char* paf_suf,
4349 cpl_propertylist** plist)
4351 char * paf_name=NULL;
4353 if(detmon_lg_config.exts >= 0)
4355 *plist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4356 detmon_lg_config.exts);
4360 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4364 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4365 detmon_lg_config.pafname, paf_suf,which_set);
4370 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4376 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4377 detmon_lg_config.pafname, paf_suf,whichext);
4381 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4382 detmon_lg_config.pafname,paf_suf,
4383 which_set, whichext);
4392 detmon_lg_set_paf_name_and_header_ext(cpl_frame* ref_frame,
4393 int flag_sets,
int which_set,
4395 const char* paf_suf,
4396 cpl_propertylist** plist)
4398 char* paf_name=NULL;
4400 if(detmon_lg_config.exts >= 0)
4402 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4403 detmon_lg_config.exts);
4407 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4410 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4411 detmon_lg_config.pafname, paf_suf,which_set);
4415 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4419 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4420 detmon_lg_config.pafname, paf_suf,whichext);
4423 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4424 detmon_lg_config.pafname,paf_suf,
4425 which_set, whichext);
4432 static cpl_error_code
4433 detmon_lg_save_paf_product(cpl_frame* ref_frame,
int flag_sets,
4434 int which_set,
int whichext,
4435 const char* pafregexp,
4436 const char* procatg,
4437 const char* pipeline_name,
4438 const char* recipe_name,
4439 const char* paf_suf,
4440 cpl_propertylist* qclist,
4445 char* paf_name=NULL;
4446 cpl_propertylist* plist=NULL;
4447 cpl_propertylist* paflist = NULL;
4448 cpl_propertylist* mainplist=NULL;
4450 mainplist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0);
4452 paf_name=detmon_lg_set_paf_name_and_header(ref_frame,flag_sets,
4456 paf_name=detmon_lg_set_paf_name_and_header_ext(ref_frame,flag_sets,
4462 paflist = cpl_propertylist_new();
4463 cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,procatg);
4466 cpl_propertylist_copy_property_regexp(paflist, plist,pafregexp, 0);
4467 cpl_propertylist_copy_property_regexp(paflist, mainplist,pafregexp, 0);
4468 cpl_propertylist_append(paflist,qclist);
4471 cpl_dfs_save_paf(pipeline_name, recipe_name,paflist,paf_name);
4474 cpl_propertylist_delete(mainplist);
4475 cpl_propertylist_delete(paflist);
4476 cpl_propertylist_delete(plist);
4479 return cpl_error_get_code();
4516 static cpl_error_code
4517 detmon_lg_save(
const cpl_parameterlist * parlist,
4518 cpl_frameset * frameset,
4519 const char *recipe_name,
4520 const char *pipeline_name,
4521 const char *pafregexp,
4522 const cpl_propertylist * pro_lintbl,
4523 const cpl_propertylist * pro_gaintbl,
4524 const cpl_propertylist * pro_coeffscube,
4525 const cpl_propertylist * pro_bpm,
4526 const cpl_propertylist * pro_corr,
4527 const cpl_propertylist * pro_diff,
4528 const char *package,
4529 cpl_imagelist * coeffs,
4530 cpl_table * gain_table,
4531 cpl_table * linear_table,
4533 cpl_imagelist * autocorr_images,
4534 cpl_imagelist * diff_flats,
4535 cpl_propertylist * gaint_qclist,
4536 cpl_propertylist * lint_qclist,
4537 cpl_propertylist * linc_qclist,
4538 cpl_propertylist * bpm_qclist,
4539 const int flag_sets,
4540 const int which_set,
4541 const cpl_frameset * usedframes,
4545 cpl_frame *ref_frame;
4546 cpl_propertylist *plist = NULL;
4547 cpl_propertylist *mainplist = NULL;
4553 cpl_propertylist * xplist = NULL;
4555 cpl_propertylist* linc_plane_qclist=NULL;
4556 cpl_image* plane=NULL;
4558 char* pcatg_plane=NULL;
4560 cpl_propertylist * mypro_lintbl =
4561 cpl_propertylist_duplicate(pro_lintbl);
4562 cpl_propertylist * mypro_gaintbl =
4563 cpl_propertylist_duplicate(pro_gaintbl);
4564 cpl_propertylist * mypro_coeffscube =
4565 cpl_propertylist_duplicate(pro_coeffscube);
4566 cpl_propertylist * mypro_bpm =
4567 cpl_propertylist_duplicate(pro_bpm);
4568 cpl_propertylist * mypro_corr =
4569 cpl_propertylist_duplicate(pro_corr);
4570 cpl_propertylist * mypro_diff =
4571 cpl_propertylist_duplicate(pro_diff);
4573 const char * procatg_lintbl =
4574 cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
4576 const char * procatg_gaintbl =
4577 cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
4579 const char * procatg_coeffscube =
4580 cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
4581 const char * procatg_bpm =
4582 cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
4586 detmon_lg_extract_extention_header(frameset,gaint_qclist,lint_qclist,
4587 linc_qclist,bpm_qclist,whichext);
4592 ref_frame = cpl_frameset_get_position(frameset, 0);
4594 skip_if((mainplist =
4595 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4601 cpl_msg_info(cpl_func,
"Write the LINEARITY TABLE");
4604 NAME_O=cpl_sprintf(
"%s_linearity_table.fits", recipe_name);
4606 NAME_O=cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name,
4610 if (detmon_lg_config.exts >= 0) {
4612 cpl_propertylist_append(mypro_lintbl, lint_qclist);
4613 skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,
4614 linear_table,NULL, recipe_name,
4615 mypro_lintbl, NULL, package, NAME_O));
4617 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4618 lint_qclist,CPL_IO_DEFAULT);
4623 skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL,
4624 linear_table,lint_qclist, recipe_name,
4625 mypro_lintbl,NULL, package, NAME_O));
4626 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4627 lint_qclist,CPL_IO_DEFAULT);
4634 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4635 lint_qclist,CPL_IO_EXTEND);
4638 irplib_free(&NAME_O);
4642 cpl_msg_info(cpl_func,
"Write the GAIN TABLE");
4645 NAME_O=cpl_sprintf(
"%s_gain_table.fits", recipe_name);
4647 NAME_O=cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name,
4651 if (detmon_lg_config.exts >= 0)
4655 cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
4656 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
4657 gain_table,NULL, recipe_name, mypro_gaintbl,
4658 NULL, package, NAME_O));
4659 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4660 gaint_qclist,CPL_IO_DEFAULT);
4668 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
4669 gaint_qclist, recipe_name, mypro_gaintbl,
4670 NULL, package, NAME_O));
4671 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4672 gaint_qclist,CPL_IO_DEFAULT);
4678 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4679 gaint_qclist,CPL_IO_EXTEND);
4683 if(detmon_lg_config.pix2pix)
4689 cpl_msg_info(cpl_func,
"Write the COEFFS FITS");
4690 irplib_free(&NAME_O);
4693 PREF_O=cpl_sprintf(
"%s_coeffs_cube", recipe_name);
4696 PREF_O=cpl_sprintf(
"%s_coeffs_cube_set%02d",
4697 recipe_name, which_set);
4699 if (detmon_lg_config.split_coeffs == 0) {
4700 NAME_O=cpl_sprintf(
"%s.fits", PREF_O);
4705 if(detmon_lg_config.split_coeffs != 0){
4708 nb_images = cpl_imagelist_get_size(coeffs);
4709 for(ip=0;ip<nb_images;ip++) {
4710 NAME_O=cpl_sprintf(
"%s_P%d.fits", PREF_O,ip);
4711 pcatg_plane=cpl_sprintf(
"COEFFS_CUBE_P%d",ip);
4712 cpl_propertylist_delete(mypro_coeffscube);
4713 mypro_coeffscube=cpl_propertylist_duplicate(pro_coeffscube);
4714 cpl_propertylist_set_string(mypro_coeffscube,CPL_DFS_PRO_CATG,
4716 linc_plane_qclist=detmon_lg_extract_qclist_4plane(linc_qclist,ip);
4717 cpl_propertylist_append(mypro_coeffscube, linc_plane_qclist);
4718 plane=cpl_imagelist_get(coeffs,ip);
4719 detmon_lg_save_plane(parlist,frameset,usedframes,whichext,
4720 recipe_name,mypro_coeffscube,
4721 linc_plane_qclist,package,NAME_O,plane);
4723 if(NULL!=linc_plane_qclist) {
4724 cpl_propertylist_delete(linc_plane_qclist);
4726 irplib_free(&NAME_O);
4731 detmon_lg_save_cube(parlist,frameset,usedframes,whichext,
4732 recipe_name,mypro_coeffscube,
4733 linc_qclist,package,NAME_O,coeffs);
4739 cpl_msg_info(cpl_func,
"Write the BAD PIXEL MAP");
4740 irplib_free(&NAME_O);
4744 NAME_O=cpl_sprintf(
"%s_bpm.fits", recipe_name);
4747 NAME_O=cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, which_set);
4752 if(detmon_lg_config.exts == 0) {
4753 cpl_propertylist_append(mypro_bpm, bpm_qclist);
4754 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
4755 CPL_BPP_IEEE_FLOAT, recipe_name,
4756 mypro_bpm, NULL, package,
4759 else if(detmon_lg_config.exts > 0)
4761 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4762 CPL_BPP_IEEE_FLOAT, recipe_name,
4763 mypro_bpm, NULL, package,
4765 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4771 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4772 CPL_BPP_IEEE_FLOAT, recipe_name,
4773 mypro_bpm, NULL, package,
4775 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4778 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4783 if(detmon_lg_config.intermediate)
4788 cpl_msg_info(cpl_func,
"Write the AUTOCORRS FITS");
4789 nb_images = cpl_imagelist_get_size(autocorr_images);
4790 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
4791 for(i = 0; i < nb_images; i++)
4793 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_corr);
4795 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4797 if(i < cpl_table_get_nrow(linear_table))
4799 ddit = cpl_table_get_double(linear_table,
4800 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4802 cpl_array_delete(pnames);
4805 irplib_free(&NAME_O);
4808 NAME_O=cpl_sprintf(
"%s_autocorr_%d.fits", recipe_name, i);
4809 assert(NAME_O != NULL);
4812 NAME_O=cpl_sprintf(
"%s_autocorr_%02d_set%02d.fits",
4813 recipe_name, i, which_set);
4814 assert(NAME_O != NULL);
4817 if(detmon_lg_config.exts > 0)
4819 cpl_propertylist* pextlist = cpl_propertylist_new();
4820 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4821 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4822 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4823 recipe_name, pplist, NULL,
4826 detmon_lg_save_image_with_pro_keys(
4827 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4829 cpl_propertylist_delete(pextlist);
4831 if(detmon_lg_config.exts == 0)
4833 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4834 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
4835 cpl_imagelist_get(autocorr_images, i),
4837 recipe_name, pplist, NULL, package,
4843 cpl_propertylist* pextlist = cpl_propertylist_new();
4844 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4847 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4848 usedframes, NULL,NULL,
4849 CPL_BPP_IEEE_FLOAT, recipe_name,
4853 detmon_lg_save_image_with_pro_keys(
4854 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4859 detmon_lg_save_image_with_pro_keys(
4860 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4862 cpl_propertylist_delete(pextlist);
4864 cpl_propertylist_delete (pplist);
4866 irplib_free(&NAME_O);
4875 cpl_msg_info(cpl_func,
"Write the DIFFS FITS");
4877 for(i = 0; i < nb_images; i++)
4879 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_diff);
4881 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4883 if(i < cpl_table_get_nrow(linear_table))
4885 ddit = cpl_table_get_double(linear_table,
4886 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4888 cpl_array_delete(pnames);
4893 NAME_O=cpl_sprintf(
"%s_diff_flat_%d.fits", recipe_name, i);
4896 NAME_O=cpl_sprintf(
"%s_diff_flat_%d_set%02d.fits",
4897 recipe_name, i, which_set);
4900 if(detmon_lg_config.exts > 0)
4902 cpl_propertylist* pextlist = cpl_propertylist_new();
4903 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4904 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT", ddit);
4905 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4906 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4908 mypro_diff, NULL,package, NAME_O));
4910 detmon_lg_save_image_with_pro_keys(
4911 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4913 cpl_propertylist_delete(pextlist);
4915 else if(detmon_lg_config.exts == 0)
4917 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4919 (frameset, NULL, parlist, usedframes, NULL,
4920 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
4921 recipe_name, pplist, NULL, package,
4926 cpl_propertylist* pextlist = cpl_propertylist_new();
4927 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4930 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT",ddit);
4932 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4933 usedframes, NULL,NULL,
4934 CPL_BPP_IEEE_FLOAT, recipe_name,
4935 mypro_diff, NULL,package, NAME_O));
4937 detmon_lg_save_image_with_pro_keys(
4938 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4943 detmon_lg_save_image_with_pro_keys(
4944 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4947 cpl_propertylist_delete(pextlist);
4949 cpl_propertylist_delete(pplist);
4950 irplib_free(&NAME_O);
4958 cpl_msg_info(cpl_func,
"Write the PAF file(s)");
4960 if(detmon_lg_config.pafgen) {
4962 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4963 pafregexp,procatg_gaintbl,
4964 pipeline_name,recipe_name,
4965 "qc01",gaint_qclist,0);
4967 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4968 pafregexp,procatg_lintbl,
4969 pipeline_name,recipe_name,
4970 "qc02",lint_qclist,0);
4972 if(detmon_lg_config.pix2pix)
4975 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4978 pipeline_name,recipe_name,
4979 "qc03",linc_qclist,1);
4981 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4982 whichext,pafregexp,procatg_bpm,
4983 pipeline_name,recipe_name,
4984 "qc04",bpm_qclist,1);
4989 cpl_msg_info(cpl_func,
"exit");
4991 cpl_propertylist_delete(xplist);
4993 cpl_propertylist_delete(plist);
4997 irplib_free(&NAME_O);
4999 cpl_free(pcatg_plane);
5000 cpl_propertylist_delete(mainplist);
5001 cpl_propertylist_delete(mypro_lintbl);
5002 cpl_propertylist_delete(mypro_gaintbl);
5003 cpl_propertylist_delete(mypro_coeffscube);
5004 cpl_propertylist_delete(mypro_bpm);
5005 cpl_propertylist_delete(mypro_corr);
5006 cpl_propertylist_delete(mypro_diff);
5008 return cpl_error_get_code();
5021 static cpl_error_code
5022 detmon_opt_contamination(
const cpl_imagelist * ons,
5023 const cpl_imagelist * offs,
5025 cpl_propertylist * qclist)
5033 struct rect rects[5] = {
5034 (
struct rect){ detmon_lg_config.llx1,
5035 detmon_lg_config.lly1,
5036 detmon_lg_config.urx1,
5037 detmon_lg_config.ury1},
5038 (
struct rect){ detmon_lg_config.llx2,
5039 detmon_lg_config.lly2,
5040 detmon_lg_config.urx2,
5041 detmon_lg_config.ury2},
5042 (
struct rect){ detmon_lg_config.llx3,
5043 detmon_lg_config.lly3,
5044 detmon_lg_config.urx3,
5045 detmon_lg_config.ury3},
5046 (
struct rect){ detmon_lg_config.llx4,
5047 detmon_lg_config.lly4,
5048 detmon_lg_config.urx4,
5049 detmon_lg_config.ury4},
5050 (
struct rect){ detmon_lg_config.llx5,
5051 detmon_lg_config.lly5,
5052 detmon_lg_config.urx5,
5053 detmon_lg_config.ury5},
5056 for (
size_t i = 0; i < 5; i++) {
5057 cpl_image * dif_avg;
5058 const cpl_image * off2;
5061 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
5062 off2 = cpl_imagelist_get_const(offs, 0);
5064 off2 = cpl_imagelist_get_const(offs, 1);
5066 dif_avg = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
5067 cpl_imagelist_get_const(offs, 0),
5068 cpl_imagelist_get_const(ons, 1),
5075 median = cpl_image_get_median(dif_avg);
5076 cpl_image_delete(dif_avg);
5079 sprintf(kname, DETMON_QC_CONTAM
"%zd", i + 1);
5081 if(cpl_propertylist_has(qclist,kname)){
5082 skip_if(cpl_propertylist_update_double(qclist,kname,median));
5084 skip_if(cpl_propertylist_append_double(qclist,kname,median));
5085 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
5091 return cpl_error_get_code();
5150 detmon_lg_dfs_set_groups(cpl_frameset * set,
5151 const char *tag_on,
const char *tag_off)
5163 int nframes = cpl_frameset_get_size(set);
5166 for(
int i = 0; i < nframes; i++) {
5167 cpl_frame* cur_frame = cpl_frameset_get_position(set, i);
5168 const char* tag = cpl_frame_get_tag(cur_frame);
5171 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
5172 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
5192 static cpl_error_code
5193 detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist ** coeffs_ptr,
5194 cpl_image **bpms_ptr)
5210 cpl_image* dummy_bpm = cpl_image_new(detmon_lg_config.nx,
5211 detmon_lg_config.ny,
5213 cpl_imagelist* dummy_coeffs = cpl_imagelist_new();
5215 int* db_p = cpl_image_get_data_int(dummy_bpm);
5216 int* rb_p = cpl_image_get_data_int(*bpms_ptr);;
5217 float** dcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5218 float** rcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5219 int dlength = detmon_lg_config.nx;
5221 int rlength = detmon_lg_config.urx - detmon_lg_config.llx + 1;
5222 for (
int i = 0; i <= detmon_lg_config.order; i++)
5224 cpl_image* dummy_coeff = cpl_image_new(detmon_lg_config.nx,
5225 detmon_lg_config.ny,
5228 cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
5229 dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
5230 rcs_p[i] = cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
5233 for (
int i = detmon_lg_config.lly - 1; i < detmon_lg_config.ury; i++)
5235 for (
int j = detmon_lg_config.llx - 1; j < detmon_lg_config.urx; j++)
5237 shift_idx=(i - detmon_lg_config.lly + 1) * rlength +
5238 j - detmon_lg_config.llx + 1;
5239 *(db_p + i * dlength + j) = *(rb_p + shift_idx);
5240 for (
int k = 0; k <= detmon_lg_config.order; k++)
5242 *(dcs_p[k] + i * dlength + j) =
5243 *(rcs_p[k] + (i - detmon_lg_config.lly + 1) * rlength +
5244 j - detmon_lg_config.llx + 1);
5248 cpl_imagelist_delete(*coeffs_ptr);
5249 cpl_image_delete(*bpms_ptr);
5250 *coeffs_ptr = dummy_coeffs;
5251 *bpms_ptr = dummy_bpm;
5255 return cpl_error_get_code();
5292 #ifdef DETMON_USE_DETECTOR_SHOTNOISE_MODEL
5315 static cpl_error_code
5316 detmon_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
5317 const double ron, cpl_image ** ima_errs)
5319 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
5320 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
5321 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
5322 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
5324 *ima_errs = cpl_image_duplicate(ima_data);
5326 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
5330 cpl_image_divide_scalar(*ima_errs, gain);
5331 cpl_image_add_scalar(*ima_errs, ron * ron);
5332 cpl_image_power(*ima_errs, 0.5);
5334 return cpl_error_get_code();
5339 detmon_compute_badpixmap(cpl_boolean opt_nir,
const int nsets,
5340 const cpl_table* linear_table,
5341 const cpl_imagelist* linearity_inputs,
int nbpixs,
5342 cpl_vector* x, cpl_propertylist* gaint_qclist,
5343 cpl_image** bpms_ptr)
5349 if (opt_nir == NIR) {
5350 x = cpl_vector_wrap(nsets,
5351 (
double *) cpl_table_get_data_double_const(linear_table,
5355 x = cpl_vector_wrap(nsets,
5356 (
double *) cpl_table_get_data_double_const(linear_table,
5360 int sz = cpl_imagelist_get_size(linearity_inputs);
5361 double kappa = detmon_lg_config.kappa;
5362 int niter = detmon_lg_config.niter;
5363 int llx = detmon_lg_config.llx;
5364 int urx = detmon_lg_config.urx;
5365 int lly = detmon_lg_config.lly;
5366 int ury = detmon_lg_config.ury;
5368 const cpl_image *ima;
5372 cpl_imagelist* errors = cpl_imagelist_new();
5394 cpl_imagelist* linearity_scaled = cpl_imagelist_new();
5396 gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
5400 gain = (gain < 0) ? 1 : gain;
5406 for (
int i = 0; i < sz; i++) {
5407 ima = cpl_imagelist_get_const(linearity_inputs, i);
5415 irplib_ksigma_clip(ima, 1, 1, urx - llx + 1,
5416 ury - lly + 1, kappa, niter, 1e-5, &avg,
5421 if (avg < detmon_lg_config.saturation_limit) {
5429 cpl_image_get_mad(ima, &dmad);
5430 err = cpl_image_duplicate(ima);
5431 cpl_image_multiply_scalar(err, 0);
5432 cpl_image_add_scalar(err, dmad * CPL_MATH_STD_MAD);
5442 cpl_imagelist_set(errors, err, i);
5450 cpl_imagelist_set(linearity_scaled,
5451 cpl_image_duplicate(ima), i));
5454 hdrl_imagelist* hil = hdrl_imagelist_create(linearity_scaled, errors);
5459 cpl_imagelist_delete(errors);
5461 double pval = 0.001;
5462 p = hdrl_bpm_fit_parameter_create_pval(1, pval);
5471 hdrl_bpm_fit_compute(p, hil, x, bpms_ptr);
5496 nbpixs = cpl_image_get_flux(*bpms_ptr);
5498 hdrl_imagelist_delete(hil);
5499 cpl_imagelist_delete(linearity_scaled);
5500 cpl_vector_unwrap((cpl_vector*) x);
5501 hdrl_parameter_delete(p);
5517 skip_if(*bpms_ptr == NULL);
5538 static cpl_error_code
5539 detmon_lg_reduce_all(
const cpl_table * linear_table,
5540 cpl_propertylist * gaint_qclist,
5541 cpl_propertylist * lint_qclist,
5542 cpl_propertylist * linc_qclist,
5543 cpl_propertylist * bpm_qclist,
5544 cpl_imagelist ** coeffs_ptr,
5545 cpl_image ** bpms_ptr,
5546 const cpl_imagelist * linearity_inputs,
5547 const cpl_table * gain_table,
5548 int which_ext, cpl_boolean opt_nir)
5552 const int linear_nsets = cpl_table_get_nrow(linear_table);
5553 const int gain_nsets = cpl_table_get_nrow(gain_table);
5555 cpl_polynomial *poly_linfit = NULL;
5556 cpl_image *fiterror = NULL;
5557 char * name_o1 = NULL;
5558 char * name_o2 = NULL;
5559 double * pcoeffs = NULL;
5560 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
5563 cpl_vector *x =NULL;
5564 const cpl_vector *y =NULL;
5567 const cpl_image * first = NULL;
5575 cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5576 cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5577 cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
5578 cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
5580 pcoeffs = cpl_malloc(
sizeof(
double)*(detmon_lg_config.order + 1));
5582 skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
5583 detmon_lg_config.method));
5584 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
5585 DETMON_QC_METHOD_C));
5588 if (!strcmp(detmon_lg_config.method,
"PTC")) {
5590 if (detmon_lg_config.exts >= 0) {
5591 cpl_msg_info(cpl_func,
5592 "Polynomial fitting for the GAIN (constant term method)");
5594 cpl_msg_info(cpl_func,
5595 "Polynomial fitting for the GAIN (constant term method)"
5596 " for extension nb %d", which_ext);
5598 skip_if(detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, gain_nsets));
5600 skip_if(detmon_lg_qc_med(gain_table, gaint_qclist, gain_nsets));
5605 if(detmon_lg_config.lamp_ok) {
5606 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
5607 detmon_lg_config.cr));
5608 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
5609 DETMON_QC_LAMP_FLUX_C));
5613 if(detmon_lg_config.autocorr == TRUE) {
5614 autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
5615 skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
5617 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
5618 DETMON_QC_AUTOCORR_C));
5620 if (detmon_lg_config.exts >= 0) {
5621 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix");
5623 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix"
5624 " for extension nb %d", which_ext);
5627 if(!detmon_lg_config.pix2pix) {
5628 const int order=detmon_lg_config.order;
5636 y = cpl_vector_wrap(linear_nsets,
5637 (
double *)cpl_table_get_data_double_const(linear_table,
5640 if (opt_nir == NIR) {
5641 x = cpl_vector_wrap(linear_nsets,
5642 (
double *)cpl_table_get_data_double_const(linear_table,
5645 x = cpl_vector_wrap(linear_nsets,
5646 (
double *)cpl_table_get_data_double_const(linear_table,
5650 if(x == NULL || y == NULL) {
5651 cpl_vector_unwrap((cpl_vector *)x);
5652 cpl_vector_unwrap((cpl_vector *)y);
5662 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
5663 poly_linfit = irplib_polynomial_fit_1d_create(x, y,order,&mse);
5665 if(order == cpl_vector_get_size(x) - 1) {
5666 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5670 if(poly_linfit == NULL) {
5671 cpl_vector_unwrap((cpl_vector *)x);
5672 cpl_vector_unwrap((cpl_vector *)y);
5678 min_val=cpl_vector_get_min(y);
5679 max_val=cpl_vector_get_max(y);
5681 cpl_vector_unwrap((cpl_vector *)x);
5682 cpl_vector_unwrap((cpl_vector *)y);
5684 for(deg = 0; deg <= order; deg++) {
5685 const double coeff =
5686 cpl_polynomial_get_coeff(poly_linfit, °);
5689 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
5690 assert(name_o != NULL);
5691 skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
5692 skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
5693 DETMON_QC_LIN_COEF_C));
5696 pcoeffs[deg] = coeff;
5698 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
5699 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
5700 DETMON_QC_ERRFIT_MSE_C));
5704 const int order=detmon_lg_config.order;
5706 y = cpl_vector_wrap(linear_nsets,
5707 (
double *)cpl_table_get_data_double_const(linear_table,
5712 x = cpl_vector_wrap(linear_nsets,
5713 (
double *)cpl_table_get_data_double_const(linear_table,
5716 x = cpl_vector_wrap(linear_nsets,
5717 (
double *)cpl_table_get_data_double_const(linear_table,
5722 first = cpl_imagelist_get_const(linearity_inputs, 0);
5723 sizex = cpl_image_get_size_x(first);
5724 sizey = cpl_image_get_size_y(first);
5725 vsize = cpl_vector_get_size(x);
5726 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
5728 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,order, FALSE,
5729 CPL_TYPE_FLOAT, fiterror);
5730 min_val=cpl_vector_get_min(y);
5731 max_val=cpl_vector_get_max(y);
5732 cpl_vector_unwrap((cpl_vector*)x);
5733 cpl_vector_unwrap((cpl_vector*)y);
5735 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
5736 "Failed polynomial fit");
5739 for(deg = 0; deg <= order; deg++)
5741 cpl_image *image = cpl_imagelist_get(*coeffs_ptr, deg);
5742 const double coeff = cpl_image_get_median(image);
5743 pcoeffs[deg] = coeff;
5745 name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", (
int)deg);
5746 name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", (
int)deg);
5747 assert(name_o1 != NULL);
5748 assert(name_o2 != NULL);
5749 skip_if(cpl_propertylist_append_double(linc_qclist, name_o1, coeff));
5750 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o1,
5751 DETMON_QC_LIN_COEF_C));
5754 skip_if(cpl_propertylist_append_double(linc_qclist, name_o2,
5755 cpl_image_get_stdev(image)));
5756 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o2,
5757 DETMON_QC_LIN_COEF_ERR_C));
5763 if(order == vsize - 1)
5765 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5766 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5768 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5769 DETMON_QC_ERRFIT_C));
5772 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5773 cpl_image_get_median(fiterror)));
5774 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5775 DETMON_QC_ERRFIT_C));
5779 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
5781 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
5782 DETMON_QC_COUNTS_MIN_C));
5783 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
5785 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
5786 DETMON_QC_COUNTS_MAX_C));
5787 skip_if(detmon_lg_lineff(pcoeffs,lint_qclist,detmon_lg_config.ref_level,
5788 detmon_lg_config.order));
5790 if (detmon_lg_config.exts >= 0)
5792 cpl_msg_info(cpl_func,
"Bad pixel detection");
5795 cpl_msg_info(cpl_func,
"Bad pixel detection"
5796 " for extension nb %d", which_ext);
5798 if(detmon_lg_config.pix2pix)
5802 nbpixs = detmon_compute_badpixmap(opt_nir, linear_nsets, linear_table,
5803 linearity_inputs, nbpixs, x,gaint_qclist, bpms_ptr);
5808 skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
5809 skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
5810 DETMON_QC_NUM_BPM_C));
5811 cpl_msg_info(cpl_func,
"stability=%g",detmon_lg_config.lamp_stability);
5812 if(detmon_lg_config.lamp_stability != 0.0)
5814 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
5815 detmon_lg_config.lamp_stability));
5816 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
5817 DETMON_QC_LAMP_STAB_C));
5820 if (!detmon_lg_config.wholechip && detmon_lg_config.pix2pix)
5822 detmon_lg_fits_coeffs_and_bpm2chip(coeffs_ptr,bpms_ptr);
5829 cpl_image_delete(fiterror);
5830 cpl_polynomial_delete(poly_linfit);
5834 return cpl_error_get_code();
5846 static cpl_error_code
5847 detmon_lg_lineff(
double * pcoeffs,
5848 cpl_propertylist * qclist,
5854 double residual, slope;
5857 cpl_polynomial * poly = cpl_polynomial_new(1);
5871 pcoeffs[0] -= ref_level;
5873 for (i = 2; i <= order; i++)
5876 for(j = 0; j < i; j++)
5878 pcoeffs[i] /= pcoeffs[1];
5884 for (deg = 0; deg <= order; deg++) {
5886 skip_if(cpl_polynomial_set_coeff(poly, °, pcoeffs[deg]));
5895 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
5897 if (slope <= 0.0 && residual >= 0.0) {
5898 cpl_msg_warning(cpl_func,
"Reference level (--ref_level) outside"
5899 " linearity range of the detector. Cannot compute"
5900 " linearity efficiency (QC.LINEFF).");
5905 cpl_error_code err = cpl_polynomial_solve_1d(poly, 0.0, &root, 1);
5910 if (err == CPL_ERROR_NONE)
5913 lineff = (root - ref_level) / ref_level;
5918 cpl_msg_warning(cpl_func,
5919 "Cannot compute linearity efficiency (QC.LINEFF)"
5920 "for the current combination "
5921 " of (--ref-level equal %d) and (--order equal %d) parameters. Try "
5922 "to decrease (--ref-level) value.", ref_level, order);
5925 cpl_msg_warning(cpl_func,
"DETMON_QC_LIN_EFF=%f",lineff );
5926 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
5928 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
5929 DETMON_QC_LIN_EFF_C));
5931 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
5933 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
5934 DETMON_QC_LIN_EFF_FLUX_C));
5938 cpl_polynomial_delete(poly);
5940 return cpl_error_get_code();
5951 static cpl_error_code
5952 detmon_lg_qc_ptc(
const cpl_table * gain_table,
5953 cpl_propertylist * qclist,
unsigned mode,
int rows_in_gain)
5956 cpl_polynomial *poly_fit = NULL;
5957 cpl_polynomial *poly_fit2 = NULL;
5959 const int nsets = rows_in_gain;
5961 cpl_vector *x = NULL;
5962 cpl_vector *y = NULL;
5964 cpl_errorstate prestate;
5966 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
5967 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
5969 x = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5971 y = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5973 skip_if(x == NULL || y == NULL);
5974 if (0 == detmon_lg_check_before_gain(x, y))
5978 cpl_vector_unwrap(x);
5982 cpl_vector_unwrap(y);
5984 return CPL_ERROR_NONE;
5987 poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
5988 skip_if(poly_fit == NULL);
5992 prestate = cpl_errorstate_get();
5993 coef = cpl_polynomial_get_coeff(poly_fit, &i);
5994 skip_if (!cpl_errorstate_is_equal(prestate) || coef==0);
5995 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
5996 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5997 DETMON_QC_CONAD_C));
6000 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
6002 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
6018 if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
6019 const cpl_vector *x2 =
6020 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT_CORR"));
6021 const cpl_vector *y2 =
6022 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
6024 if(x2 == NULL || y2 == NULL) {
6025 cpl_vector_unwrap((cpl_vector *)x2);
6026 cpl_vector_unwrap((cpl_vector *)y2);
6037 poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
6038 if(poly_fit2 == NULL) {
6039 cpl_vector_unwrap((cpl_vector *)x2);
6040 cpl_vector_unwrap((cpl_vector *)y2);
6042 cpl_msg_error(cpl_func,
"Error during polynomial fit, err[%s]", cpl_error_get_where());
6046 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
6047 cpl_vector_unwrap((cpl_vector *)x2);
6048 cpl_vector_unwrap((cpl_vector *)y2);
6049 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
6052 prestate = cpl_errorstate_get();
6053 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
6054 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
6055 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
6057 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
6059 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
6060 DETMON_QC_CONAD_CORR_C));
6062 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
6064 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
6065 DETMON_QC_GAIN_CORR_C));
6071 cpl_vector_unwrap(x);
6072 cpl_vector_unwrap(y);
6073 cpl_polynomial_delete(poly_fit);
6074 cpl_polynomial_delete(poly_fit2);
6076 return cpl_error_get_code();
6085 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y)
6087 const double TOLERANCE = 1e-37;
6088 double xmin = cpl_vector_get_min(x);
6089 double xmax = cpl_vector_get_max(x);
6090 double ymin = cpl_vector_get_min(y);
6091 double ymax = cpl_vector_get_max(y);
6092 double ystdev = cpl_vector_get_stdev(y);
6093 double xstdev = cpl_vector_get_stdev(x);
6095 if (fabs(xmax-xmin) < TOLERANCE &&
6096 fabs(ymax - ymin) < TOLERANCE &&
6097 xstdev < TOLERANCE &&
6100 cpl_msg_warning(cpl_func,
"An empty frame has been detected, linearity, coeffs, gain, FPN values will not be computed.");
6115 static cpl_error_code
6116 detmon_lg_qc_med(
const cpl_table * gain_table,
6117 cpl_propertylist * qclist,
int rows_in_gain)
6121 cpl_vector *x = NULL;
6122 cpl_vector *y = NULL;
6123 int check_result = 0;
6125 if (rows_in_gain) {};
6127 x = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
6128 y = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
6129 check_result = detmon_lg_check_before_gain(x, y);
6132 cpl_vector_unwrap(x);
6136 cpl_vector_unwrap(y);
6138 if (0 == check_result)
6140 return CPL_ERROR_NONE;
6143 gain=cpl_table_get_column_median(gain_table,
"GAIN");
6145 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
6147 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
6150 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
6151 cpl_table_get_column_stdev
6152 (gain_table,
"GAIN")));
6153 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
6154 DETMON_QC_GAIN_MSE_C));
6156 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
6157 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
6158 DETMON_QC_CONAD_C));
6161 gain=cpl_table_get_column_median(gain_table,
"GAIN_CORR");
6163 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
6165 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
6166 DETMON_QC_GAIN_CORR_C));
6169 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
6170 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
6171 DETMON_QC_CONAD_CORR_C));
6176 return cpl_error_get_code();
6190 static cpl_error_code
6191 detmon_lg_rescale(cpl_imagelist * to_rescale)
6194 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 0),
6195 detmon_lg_config.llx,
6196 detmon_lg_config.lly,
6197 detmon_lg_config.urx,
6198 detmon_lg_config.ury);
6200 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 1),
6201 detmon_lg_config.llx,
6202 detmon_lg_config.lly,
6203 detmon_lg_config.urx,
6204 detmon_lg_config.ury);
6208 if(fabs(med1 / med2 - 1) > 0.001) {
6210 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
6213 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
6219 return cpl_error_get_code();
6222 static cpl_error_code
6223 detmon_pair_extract_next(
const cpl_frameset * set,
6227 cpl_frameset ** pair,
6231 double dit_next = -100;
6232 cpl_size* selection;
6233 int nsets_extracted = 0;
6234 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6235 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6236 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6237 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6239 nsets_extracted = cpl_frameset_get_size(set);
6240 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6241 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6244 dit = dit_array[*next_element ];
6246 if (*next_element < nsets_extracted - 1)
6248 dit_next = dit_array[*next_element + 1 ];
6252 selection[iindex[*next_element] ] = 1;
6253 if (fabs(dit - dit_next) < tolerance)
6256 selection[iindex[*next_element + 1] ] = 1;
6261 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);
6265 cpl_frameset_delete(*pair);
6266 *pair = cpl_frameset_extract(set, selection, 1);
6269 cpl_free(selection);
6270 return cpl_error_get_code();
6273 static cpl_error_code
6274 detmon_single_extract_next(
const cpl_frameset * set,
6278 cpl_frameset ** pair)
6280 cpl_size* selection;
6281 int nsets_extracted = 0;
6282 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6283 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6284 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6285 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6287 nsets_extracted = cpl_frameset_get_size(set);
6288 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6289 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6292 selection[iindex[*next_element] ] = 1;
6295 cpl_frameset_delete(*pair);
6296 *pair = cpl_frameset_extract(set, selection, 1);
6298 cpl_free(selection);
6299 return cpl_error_get_code();
6397 detmon_gain(
const cpl_imagelist * imlist_on,
6398 const cpl_imagelist * imlist_off,
6399 const cpl_vector * exptimes,
6400 const cpl_vector * ndit,
6410 cpl_propertylist * qclist,
6412 cpl_imagelist ** diff_imlist,
6413 cpl_imagelist ** autocorr_imlist)
6415 cpl_table * gain_table = NULL;
6416 cpl_imagelist * difflist = NULL;
6417 cpl_imagelist * autocorrlist = NULL;
6418 cpl_imagelist * c_onlist = NULL;
6419 cpl_imagelist * c_offlist = NULL;
6420 cpl_vector * diffdits = NULL;
6421 cpl_vector * diffndits = NULL;
6422 int rows_in_gain = 0;
6423 int ndiffdits, ndits;
6425 cpl_boolean opt_nir = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
6426 const char * method = mode & IRPLIB_GAIN_PTC ?
"PTC" :
"MED";
6428 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6429 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6430 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6431 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6434 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6435 skip_if(detmon_gain_table_create(gain_table, opt_nir));
6439 skip_if(detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,
6441 ndiffdits = cpl_vector_get_size(diffdits);
6443 ndits = cpl_vector_get_size(exptimes);
6446 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
6447 difflist = cpl_imagelist_new();
6448 autocorrlist = cpl_imagelist_new();
6451 if (mode & IRPLIB_GAIN_COLLAPSE) {
6452 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6453 c_offlist = cpl_imagelist_duplicate(imlist_off);
6454 skip_if(detmon_lg_rescale(c_offlist));
6456 c_offlist = (cpl_imagelist *) imlist_off;
6461 for (i = 0; i < ndiffdits; i++) {
6468 c_dit=cpl_vector_get(diffdits, i);
6471 c_ndit=(int)cpl_vector_get(diffndits, i);
6474 c_onlist = cpl_imagelist_new();
6477 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6478 c_offlist = cpl_imagelist_new();
6483 for(j = 0; j < ndits; j++) {
6484 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6494 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6495 const cpl_image * im =
6496 cpl_imagelist_get_const(imlist_on, j);
6497 im_on = cpl_image_duplicate(im);
6499 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6501 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6508 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6510 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6511 const cpl_image * im =
6512 cpl_imagelist_get_const(imlist_off, j);
6513 im_off = cpl_image_duplicate(im);
6516 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6518 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6525 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6526 skip_if (c_nons != c_noffs);
6529 skip_if (c_nons == 0 || c_nons % 2 != 0);
6532 if(mode & IRPLIB_GAIN_WITH_RESCALE) {
6533 skip_if(detmon_lg_rescale(c_onlist));
6534 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6535 skip_if(detmon_lg_rescale(c_offlist));
6541 int rows_affected = 1;
6542 skip_if(detmon_gain_table_fill_row(gain_table,
6546 c_offlist, kappa, nclip,
6548 xshift, yshift, 1E10, i,
6549 mode, &rows_affected));
6554 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6555 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6556 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6557 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6558 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6559 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6562 cpl_imagelist_unset(c_onlist, 0);
6564 cpl_imagelist_unset(c_onlist, 0);
6566 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6567 cpl_imagelist_unset(c_offlist, 0);
6569 cpl_imagelist_unset(c_offlist, 0);
6577 cpl_imagelist_delete(c_onlist);
6578 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6579 cpl_imagelist_delete(c_offlist);
6583 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
6584 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
6585 DETMON_QC_METHOD_C));
6588 if (mode & IRPLIB_GAIN_PTC) {
6589 skip_if(detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
6591 skip_if(detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
6594 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
6595 double autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
6596 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
6598 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
6599 DETMON_QC_AUTOCORR_C));
6602 if (diff_imlist != NULL) *diff_imlist = difflist;
6603 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
6607 cpl_vector_delete(diffdits);
6608 cpl_vector_delete(diffndits);
6613 static cpl_error_code
6614 detmon_gain_table_create(cpl_table * gain_table,
6615 const cpl_boolean opt_nir)
6617 if (opt_nir == NIR) {
6618 skip_if(cpl_table_new_column(gain_table,
"DIT", CPL_TYPE_DOUBLE));
6619 skip_if(cpl_table_new_column(gain_table,
"NDIT", CPL_TYPE_INT));
6621 skip_if(cpl_table_new_column(gain_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6623 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON1", CPL_TYPE_DOUBLE));
6624 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON2", CPL_TYPE_DOUBLE));
6625 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF1", CPL_TYPE_DOUBLE));
6626 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF2", CPL_TYPE_DOUBLE));
6627 skip_if(cpl_table_new_column(gain_table,
"SIG_ON_DIF", CPL_TYPE_DOUBLE));
6628 skip_if(cpl_table_new_column(gain_table,
"SIG_OFF_DIF", CPL_TYPE_DOUBLE));
6629 skip_if(cpl_table_new_column(gain_table,
"GAIN", CPL_TYPE_DOUBLE));
6630 skip_if(cpl_table_new_column(gain_table,
"AUTOCORR", CPL_TYPE_DOUBLE));
6631 skip_if(cpl_table_new_column(gain_table,
"GAIN_CORR", CPL_TYPE_DOUBLE));
6632 skip_if(cpl_table_new_column(gain_table,
"ADU", CPL_TYPE_DOUBLE));
6633 skip_if(cpl_table_new_column(gain_table,
"X_FIT", CPL_TYPE_DOUBLE));
6634 skip_if(cpl_table_new_column(gain_table,
"X_FIT_CORR", CPL_TYPE_DOUBLE));
6635 skip_if(cpl_table_new_column(gain_table,
"Y_FIT", CPL_TYPE_DOUBLE));
6636 skip_if(cpl_table_new_column(gain_table,
"Y_FIT_CORR", CPL_TYPE_DOUBLE));
6637 skip_if(cpl_table_new_column(gain_table,
"FLAG", CPL_TYPE_INT));
6641 return cpl_error_get_code();
6644 static cpl_error_code
6645 detmon_lin_table_create(cpl_table * lin_table,
6646 const cpl_boolean opt_nir)
6648 if (opt_nir == NIR) {
6649 skip_if(cpl_table_new_column(lin_table,
"DIT", CPL_TYPE_DOUBLE));
6651 skip_if(cpl_table_new_column(lin_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6653 skip_if(cpl_table_new_column(lin_table,
"MED", CPL_TYPE_DOUBLE));
6654 skip_if(cpl_table_new_column(lin_table,
"MEAN", CPL_TYPE_DOUBLE));
6655 skip_if(cpl_table_new_column(lin_table,
"MED_DIT", CPL_TYPE_DOUBLE));
6656 skip_if(cpl_table_new_column(lin_table,
"MEAN_DIT", CPL_TYPE_DOUBLE));
6657 skip_if(cpl_table_new_column(lin_table,
"ADL", CPL_TYPE_DOUBLE));
6660 return cpl_error_get_code();
6664 detmon_lg_find_dits(
const cpl_vector * exptimes,
6667 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6673 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
6677 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
6679 for (j = 0; j < ndits; j++) {
6680 if (fabs(cpl_vector_get(exptimes, i) -
6681 cpl_vector_get(dits, j)) > tolerance)
6684 if(ndiffs == ndits) {
6685 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
6690 cpl_vector_set_size(dits, ndits);
6698 static cpl_error_code
6699 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
6700 const cpl_vector * vec_ndits,
6702 cpl_vector** diff_dits,
6703 cpl_vector** diff_ndits)
6711 * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6712 * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
6715 cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
6716 cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
6719 size=cpl_vector_get_size(exptimes);
6721 for(i = 1; i < size; i++) {
6723 for (j = 0; j < ndits; j++) {
6724 if (fabs(cpl_vector_get(exptimes, i) -
6725 cpl_vector_get(*diff_dits,j)) > tolerance)
6728 if(ndiffs == ndits) {
6729 cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
6730 cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
6735 cpl_vector_set_size(*diff_dits, ndits);
6736 cpl_vector_set_size(*diff_ndits, ndits);
6739 return cpl_error_get_code();
6829 detmon_lin(
const cpl_imagelist * imlist_on,
6830 const cpl_imagelist * imlist_off,
6831 const cpl_vector * exptimes,
6841 cpl_propertylist * qclist,
6843 cpl_imagelist ** coeffs_cube,
6846 cpl_table * lin_table = NULL;
6847 cpl_imagelist * c_onlist = NULL;
6848 cpl_imagelist * c_offlist = NULL;
6849 cpl_vector * diffdits = NULL;
6850 cpl_imagelist * lin_inputs = NULL;
6851 cpl_polynomial * poly_linfit = NULL;
6852 cpl_image * fiterror = NULL;
6853 cpl_vector * vcoeffs = NULL;
6854 double * pcoeffs = NULL;
6855 int ndiffdits, ndits;
6857 cpl_boolean opt_nir = mode & IRPLIB_LIN_OPT ? OPT : NIR;
6858 const cpl_vector *x = NULL;
6859 const cpl_vector *y = NULL;
6861 const cpl_image * first = NULL;
6869 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6870 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6871 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6872 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6873 cpl_ensure(order > 0 , CPL_ERROR_ILLEGAL_INPUT, NULL);
6875 vcoeffs = cpl_vector_new(order + 1);
6876 pcoeffs = cpl_vector_get_data(vcoeffs);
6879 if (mode & IRPLIB_LIN_PIX2PIX) {
6880 cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
6881 cpl_ensure(bpm != NULL, CPL_ERROR_NULL_INPUT, NULL);
6882 lin_inputs = cpl_imagelist_new();
6886 lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6887 skip_if(detmon_lin_table_create(lin_table, opt_nir));
6891 diffdits = detmon_lg_find_dits(exptimes, tolerance);
6892 ndiffdits = cpl_vector_get_size(diffdits);
6894 ndits = cpl_vector_get_size(exptimes);
6924 if (mode & IRPLIB_LIN_COLLAPSE) {
6929 cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
6930 skip_if(collapse == NULL);
6932 c_offlist = cpl_imagelist_new();
6933 skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
6937 for (i = 0; i < ndiffdits; i++) {
6941 double c_dit = cpl_vector_get(diffdits, i);
6943 c_onlist = cpl_imagelist_new();
6946 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6947 c_offlist = cpl_imagelist_new();
6951 for(j = 0; j < ndits; j++) {
6952 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6962 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6963 const cpl_image * im =
6964 cpl_imagelist_get_const(imlist_on, j);
6965 im_on = cpl_image_duplicate(im);
6967 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6969 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6976 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6978 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6979 const cpl_image * im =
6980 cpl_imagelist_get_const(imlist_off, j);
6981 im_off = cpl_image_duplicate(im);
6984 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6986 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6993 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6994 skip_if (c_nons != c_noffs);
6997 skip_if (c_nons == 0 || c_nons % 2 != 0);
7000 if(mode & IRPLIB_LIN_WITH_RESCALE) {
7001 skip_if(detmon_lg_rescale(c_onlist));
7002 if (mode & IRPLIB_LIN_NO_COLLAPSE)
7003 skip_if(detmon_lg_rescale(c_offlist));
7010 skip_if(detmon_lin_table_fill_row(lin_table, c_dit,
7012 c_onlist, c_offlist,
7016 if (mode & IRPLIB_LIN_WITH_RESCALE) {
7017 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
7018 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
7019 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7020 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
7021 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
7024 cpl_imagelist_unset(c_onlist, 0);
7026 cpl_imagelist_unset(c_onlist, 0);
7028 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7029 cpl_imagelist_unset(c_offlist, 0);
7031 cpl_imagelist_unset(c_offlist, 0);
7039 cpl_imagelist_delete(c_onlist);
7040 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7041 cpl_imagelist_delete(c_offlist);
7045 skip_if(detmon_add_adl_column(lin_table, opt_nir));
7047 if(!(mode & IRPLIB_LIN_PIX2PIX)) {
7050 y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7051 (
double *)cpl_table_get_data_double_const(lin_table,
7053 if (opt_nir == NIR) {
7054 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7055 (
double *)cpl_table_get_data_double_const(lin_table,
"DIT"));
7057 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7058 (
double *)cpl_table_get_data_double_const(lin_table,
"EXPTIME"));
7060 if(x == NULL || y == NULL) {
7061 cpl_vector_unwrap((cpl_vector *)x);
7062 cpl_vector_unwrap((cpl_vector *)y);
7072 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
7073 poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
7075 if(order == cpl_vector_get_size(x) - 1) {
7076 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7080 if(poly_linfit == NULL) {
7081 cpl_vector_unwrap((cpl_vector *)x);
7082 cpl_vector_unwrap((cpl_vector *)y);
7087 cpl_vector_unwrap((cpl_vector *)x);
7088 cpl_vector_unwrap((cpl_vector *)y);
7090 for(deg = 0; deg <= order; deg++) {
7091 const double coeff =
7092 cpl_polynomial_get_coeff(poly_linfit, °);
7094 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
7095 assert(name_o != NULL);
7096 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
7097 skip_if(cpl_propertylist_set_comment(qclist,name_o,
7098 DETMON_QC_LIN_COEF_C));
7100 pcoeffs[deg] = coeff;
7102 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
7103 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7104 DETMON_QC_ERRFIT_MSE_C));
7108 if (opt_nir == NIR) {
7109 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7110 (
double *)cpl_table_get_data_double_const(lin_table,
7113 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7114 (
double *)cpl_table_get_data_double_const(lin_table,
7119 first = cpl_imagelist_get_const(lin_inputs, 0);
7120 sizex = cpl_image_get_size_x(first);
7121 sizey = cpl_image_get_size_y(first);
7123 vsize = cpl_vector_get_size(x);
7125 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
7128 cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
7129 order, FALSE, CPL_TYPE_FLOAT,
7132 cpl_vector_unwrap((cpl_vector*)x);
7133 irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
7134 "Failed polynomial fit");
7136 for(i = 0; i <= order; i++) {
7137 cpl_image *image = cpl_imagelist_get(*coeffs_cube, i);
7138 const double coeff = cpl_image_get_median(image);
7139 char * name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", i);
7140 char * name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", i);
7142 assert(name_o1 != NULL);
7143 assert(name_o2 != NULL);
7144 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
7145 skip_if(cpl_propertylist_set_comment(qclist,name_o1,
7146 DETMON_QC_LIN_COEF_C));
7149 skip_if(cpl_propertylist_append_double(qclist, name_o2,
7150 cpl_image_get_stdev(image)));
7151 skip_if(cpl_propertylist_set_comment(qclist,name_o2,
7152 DETMON_QC_LIN_COEF_ERR_C));
7157 if(order == vsize - 1) {
7158 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7159 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7161 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7162 DETMON_QC_ERRFIT_C));
7166 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7167 cpl_image_get_median(fiterror)));
7168 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7169 DETMON_QC_ERRFIT_C));
7174 skip_if(detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
7176 if(mode & IRPLIB_LIN_PIX2PIX) {
7178 *bpm = detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
7179 skip_if(*bpm == NULL);
7180 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
7182 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
7183 DETMON_QC_NUM_BPM_C));
7188 cpl_vector_delete(diffdits);
7189 cpl_polynomial_delete(poly_linfit);
7190 cpl_imagelist_delete(lin_inputs);
7191 cpl_vector_delete(vcoeffs);
7192 cpl_image_delete(fiterror);
7222 static cpl_error_code
7223 detmon_lin_table_fill_row(cpl_table * lin_table,
double c_dit,
7224 cpl_imagelist * linearity_inputs,
7225 const cpl_imagelist * ons,
7226 const cpl_imagelist * offs,
7235 cpl_image * extracted=NULL;
7237 cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
7238 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
7239 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
7241 if (mode & IRPLIB_LIN_PIX2PIX) {
7242 cpl_msg_debug(cpl_func,
"checking linearity inputs");
7243 cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
7247 if (mode & IRPLIB_LIN_NIR) {
7248 cpl_table_set(lin_table,
"DIT", pos, c_dit);
7249 }
else if (mode & IRPLIB_LIN_OPT) {
7250 cpl_table_set(lin_table,
"EXPTIME", pos, c_dit);
7252 cpl_msg_error(cpl_func,
"Mandatory mode not given");
7256 const cpl_image * off2;
7257 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
7258 off2 = cpl_imagelist_get_const(offs, 0);
7260 off2 = cpl_imagelist_get_const(offs, 1);
7262 extracted = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
7263 cpl_imagelist_get_const(offs, 0),
7264 cpl_imagelist_get_const(ons, 1),
7266 llx, lly, urx, ury);
7267 cpl_ensure_code(extracted != NULL, cpl_error_get_code());
7271 double median = cpl_image_get_median(extracted);
7272 double mean= cpl_image_get_mean(extracted);
7273 cpl_table_set(lin_table,
"MED", pos, median);
7274 cpl_table_set(lin_table,
"MEAN", pos, mean);
7276 cpl_table_set(lin_table,
"MED_DIT", pos, median / c_dit);
7277 cpl_table_set(lin_table,
"MEAN_DIT", pos, mean / c_dit);
7281 if(mode & IRPLIB_LIN_PIX2PIX) {
7282 cpl_error_code error = cpl_imagelist_set(linearity_inputs, extracted,
7284 cpl_ensure_code(!error, error);
7286 cpl_image_delete(extracted);
7289 return cpl_error_get_code();
7292 static double irplib_calculate_total_noise_smooth(
const cpl_image* pimage,
7293 int pattern_x,
int pattern_y)
7295 cpl_image * p_tmp_image = 0;
7296 cpl_image * psmooth_image = 0;
7298 cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
7300 p_tmp_image = cpl_image_duplicate(pimage);
7301 cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
7302 cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
7303 psmooth_image = cpl_image_divide_create(pimage,p_tmp_image);
7304 ret_noise = irplib_calculate_total_noise(psmooth_image);
7305 cpl_mask_delete(mask);
7306 cpl_image_delete(psmooth_image);
7307 cpl_image_delete(p_tmp_image);
7311 static double irplib_calculate_total_noise(
const cpl_image* pimage)
7313 double total_noise = -1;
7314 unsigned long max_bin_size = 1E5;
7315 const double hstart = cpl_image_get_min(pimage);
7316 const double hrange = cpl_image_get_max(pimage) - hstart;
7317 const unsigned long nbins = max_bin_size;
7320 irplib_hist * phist = 0;
7321 phist = irplib_hist_new();
7324 irplib_hist_init(phist, nbins, hstart, hrange);
7325 err = irplib_hist_fill(phist, pimage);
7326 if (err == CPL_ERROR_NONE)
7334 unsigned long n_bins = irplib_hist_get_nbins(phist);
7335 double start = irplib_hist_get_start(phist);
7336 double bin_size = irplib_hist_get_bin_size(phist);
7337 cpl_vector* pdata_vector = cpl_vector_new(n_bins);
7338 cpl_vector* ppos_vector = cpl_vector_new(n_bins);
7339 cpl_table* ptable = cpl_table_new(n_bins);
7340 cpl_table_new_column(ptable,
"bin", CPL_TYPE_DOUBLE);
7341 cpl_table_new_column(ptable,
"value", CPL_TYPE_DOUBLE);
7342 for(i = 0; i < n_bins; i++)
7344 unsigned int value = irplib_hist_get_value(phist, i);
7345 double dvalue = (double)(value);
7346 cpl_vector_set(pdata_vector, i, dvalue);
7347 cpl_vector_set(ppos_vector, i, start + i * bin_size);
7349 cpl_table_set(ptable,
"bin", i, start + i * bin_size);
7350 cpl_table_set(ptable,
"value", i, dvalue);
7352 err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
7353 if (err == CPL_ERROR_NONE)
7355 cpl_msg_info(cpl_func,
"FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
7359 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed Gaussian Fit, err msg [%s]", cpl_error_get_message());
7362 cpl_table_delete(ptable);
7363 cpl_vector_delete(ppos_vector);
7364 cpl_vector_delete(pdata_vector);
7368 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
7371 irplib_hist_delete(phist);
7376 static double irplib_compute_err(
double gain,
double ron,
double FA)
7378 double int_gain = (gain * gain - 1) / 12;
7383 return sqrt(ron * ron + FA / gain + int_gain);
7386 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain ,
7387 FPN_METHOD fpn_method,
int smooth_size,
double* mse)
7389 cpl_image* im_diff = 0;
7390 const cpl_image* im_f1 = f1;
7391 cpl_image* im_inrange1 = 0;
7400 cpl_msg_warning(cpl_func,
"gain[%f]<0", gain);
7401 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7408 im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
7409 im_f1 = im_inrange1;
7411 FA = cpl_image_get_median(im_f1);
7418 cpl_msg_info(cpl_func,
"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
7419 s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
7422 cpl_msg_info(cpl_func,
"HISTOGRAM method is used for FPN");
7423 s_tot = irplib_calculate_total_noise(im_f1);
7428 cpl_msg_warning(cpl_func,
"fpn_method is not defined");
7437 cpl_msg_warning(cpl_func,
"Median flux on sum of flats<0");
7438 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7443 if ((s_tot * s_tot - FA / gain) > 0)
7445 s_fpn = sqrt(s_tot * s_tot - FA / gain);
7446 sr_fpn = s_fpn / FA;
7447 *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
7451 cpl_msg_warning(cpl_func,
"s_tot * s_tot < FA / gain");
7452 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7461 cpl_image_delete(im_diff);
7464 cpl_image_delete(im_inrange1);
7470 static cpl_imagelist * irplib_load_fset_wrp(
const cpl_frameset * pframeset,
7471 cpl_type type ,
int whichext)
7475 return detmon_load_frameset_window(pframeset, type, 0, whichext,
7476 detmon_lg_config.llx,
7477 detmon_lg_config.lly,
7478 detmon_lg_config.urx,
7479 detmon_lg_config.ury,
7480 detmon_lg_config.nx,
7481 detmon_lg_config.ny);
7484 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset * pframeset,
7485 cpl_type type ,
int whichext)
7488 cpl_imagelist* offs = cpl_imagelist_new();
7489 detmon_lg_config.load_fset(pframeset, type, offs);
7494 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
7495 cpl_propertylist* plist)
7497 if (ptable && plist)
7499 int size = cpl_propertylist_get_size(plist);
7501 for (i = 0; i < size; i++)
7503 cpl_property* pprop = cpl_propertylist_get(plist,i);
7506 const char* pname = cpl_property_get_name(pprop);
7509 cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
7510 if (cpl_error_get_code() != CPL_ERROR_NONE)
7512 cpl_msg_warning(cpl_func,
"cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
7519 return cpl_error_get_code();
7522 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
7523 cpl_propertylist* plist,
int row)
7525 cpl_error_code err = CPL_ERROR_NONE;
7526 if (ptable && plist)
7528 int size = cpl_propertylist_get_size(plist);
7530 for (i = 0; i < size; i++)
7532 cpl_property* pprop = cpl_propertylist_get(plist,i);
7535 const char* pname = cpl_property_get_name(pprop);
7536 double value = cpl_property_get_double(pprop);
7539 cpl_table_set_double(ptable, pname, row, value);
7540 if (cpl_error_get_code() != CPL_ERROR_NONE)
7542 cpl_msg_warning(cpl_func,
"cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
7553 cpl_error_code detmon_check_order(
const double *exptime,
int sz,
7554 double tolerance,
int order)
7571 }
while(fabs(exptime[i-1] - exptime[i]) < tolerance);
7572 }
while(i < sz - 1);
7574 if ( !( fabs(exptime[i-1] - exptime[i]) < tolerance ) ) nsets++;
7577 cpl_error_set_message(cpl_func,CPL_ERROR_INCOMPATIBLE_INPUT,
7578 "Not enough frames for the polynomial"
7579 " fitting. nsets = %d <= %d order",
7582 return cpl_error_get_code();
7585 static cpl_error_code
7586 detmon_lg_dfs_save_imagelist(
7587 cpl_frameset * frameset,
7588 const cpl_parameterlist * parlist,
7589 const cpl_frameset *usedframes,
7590 const cpl_imagelist *coeffs,
7591 const char *recipe_name,
7592 const cpl_propertylist *mypro_coeffscube,
7593 const char * package,
7594 const char * name_o)
7596 return(cpl_dfs_save_imagelist
7597 (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
7598 recipe_name, mypro_coeffscube, NULL, package,
7602 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos)
7604 const cpl_image* first = cpl_imagelist_get(imlist, 0);
7607 int x = cpl_image_get_size_x(first);
7608 int y = cpl_image_get_size_y(first);
7609 cpl_type type = cpl_image_get_type(first);
7610 cpl_image * blank = cpl_image_new(x, y, type);
7611 cpl_imagelist_set(imlist, blank, pos);
7616 static cpl_error_code
7617 detmon_lg_set_keyword_from_base_double(cpl_propertylist* pl,
7623 char* hkw = cpl_sprintf(
"%s %s", keyword_base, keyword_ext);
7624 char* hcm = cpl_sprintf(
"%s %s", comment_base, comment_ext);
7626 cpl_propertylist_append_double(pl, hkw, value);
7627 cpl_propertylist_set_comment(pl, hkw, hcm);
7632 return cpl_error_get_code();
7635 static cpl_error_code
7636 detmon_lg_set_keyword_from_insert_double(cpl_propertylist* pl,
7642 char* hkw = cpl_sprintf(keyword_base, keyword_ins);
7643 char* hcm = cpl_sprintf(comment_base, comment_ins);
7645 cpl_propertylist_append_double(pl, hkw, value);
7646 cpl_propertylist_set_comment(pl, hkw, hcm);
7651 return cpl_error_get_code();
7655 detmon_lg_set_tag(cpl_frameset* set,
const char** tag_on,
const char** tag_off)
7660 ntag_old=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_OLD);
7661 ntag_new=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_NEW);
7663 *tag_on=DETMON_LG_ON_RAW_OLD;
7664 *tag_off=DETMON_LG_OFF_RAW_OLD;
7665 }
else if (ntag_new) {
7666 *tag_on=DETMON_LG_ON_RAW_NEW;
7667 *tag_off=DETMON_LG_OFF_RAW_NEW;
7669 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
7670 "Provide %s and %s (or %s and %s) input frames",
7671 DETMON_LG_ON_RAW_NEW,DETMON_LG_OFF_RAW_NEW,
7672 DETMON_LG_ON_RAW_OLD,DETMON_LG_OFF_RAW_OLD);
7676 return cpl_error_get_code();
7680 detmon_lg_qc_params(cpl_table* linear_table, cpl_propertylist* lint_qclist,
7681 cpl_table* gain_table, cpl_propertylist* gaint_qclist,
7682 cpl_imagelist* coeffs, cpl_propertylist* linc_qclist,
7683 cpl_image* bpm, cpl_propertylist* bpm_qclist,
7684 const char * recipe_name) {
7686 char* qc_contam = NULL ;
7687 char* qc_contam_ref = cpl_sprintf(
"%s%01d", DETMON_QC_CONTAM, 5);
7689 cpl_msg_info(cpl_func,
"This is where I'll write the QC parameters");
7691 if (linear_table != NULL && lint_qclist != NULL) {
7693 if (cpl_propertylist_has(
7694 lint_qclist, qc_contam_ref)) {
7695 for (
int i=1; i<5; ++i) {
7696 qc_contam = cpl_sprintf(
"%s%01d", DETMON_QC_CONTAM, i);
7697 if (cpl_propertylist_has(lint_qclist, qc_contam_ref) &&
7698 cpl_propertylist_has(lint_qclist, qc_contam)) {
7699 cpl_propertylist_append_double(
7700 lint_qclist, cpl_sprintf(DETMON_QC_CONTAMi_NORM, i),
7701 cpl_propertylist_get_double(lint_qclist, qc_contam) /
7702 cpl_propertylist_get_double(lint_qclist, qc_contam_ref));
7703 cpl_propertylist_set_comment(
7704 lint_qclist, cpl_sprintf(DETMON_QC_CONTAMi_NORM, i),
7705 cpl_sprintf(DETMON_QC_CONTAMi_NORM_C, i)
7712 cpl_free(qc_contam);
7713 cpl_free(qc_contam_ref);
7714 return cpl_error_get_code();
7718 detmon_lg_qc_params_global_gain(
const char * recipe_name,
int nsets) {
7719 cpl_msg_info(cpl_func,
"Going to update gain table for recipe %s, nsets=%d",
7720 recipe_name, nsets);
7723 cpl_error_code err ;
7725 fn = cpl_sprintf(
"%s_gain_table.fits", recipe_name) ;
7726 cpl_msg_info(cpl_func,
"Will be modifying %s", fn) ;
7727 err = detmon_lg_qc_params_global_gain_update(fn, recipe_name);
7731 for (j=0; j<nsets; ++j) {
7732 fn = cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name, j);
7733 cpl_msg_info(cpl_func,
"Will be modifying %s", fn);
7734 err = detmon_lg_qc_params_global_gain_update(fn, recipe_name);
7744 detmon_lg_qc_params_global_gain_update(
const char * fn,
7745 const char * recipe_name) {
7746 cpl_msg_info(cpl_func,
"Now updating %s", fn);
7748 cpl_propertylist* phu = cpl_propertylist_load(fn, 0);
7749 cpl_propertylist** ehus = NULL;
7750 cpl_table** gain_tables = NULL;
7751 cpl_array* gains = NULL;
7752 cpl_array* conads = NULL ;
7753 cpl_frame* fr = cpl_frame_new();
7756 cpl_frame_set_filename(fr, fn);
7757 int nexts = cpl_frame_get_nextensions(fr);
7758 cpl_msg_info(cpl_func,
"Detected %d nexts", nexts);
7760 cpl_msg_warning(cpl_func,
"No extensions in %s, so no QC "
7761 "keywords to write", fn);
7762 cpl_msg_warning(cpl_func,
"Triggering goto cleanup");
7770 ehus = (cpl_propertylist**)cpl_malloc(nexts *
sizeof(cpl_propertylist*));
7771 gain_tables = (cpl_table**)cpl_malloc(nexts *
sizeof(cpl_table*));
7775 for (j=1; j <= nexts; j++) {
7776 cpl_msg_info(cpl_func,
"Loading EHU %d", j);
7777 ehus[j-1] = cpl_propertylist_load(fn, j);
7778 gain_tables[j-1] = cpl_table_load(fn, j, 1);
7783 cpl_msg_info(cpl_func,
"Populating data arrays");
7784 gains = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7785 conads = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7786 for (j=1; j <= nexts; j++) {
7787 cpl_msg_info(cpl_func,
" %d", j);
7788 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_GAIN)) {
7789 cpl_array_set(gains, j-1,
7790 cpl_propertylist_get_double(ehus[j-1],
7793 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_CONAD)) {
7794 cpl_array_set(conads, j-1,
7795 cpl_propertylist_get_double(ehus[j-1],
7799 cpl_msg_info(cpl_func,
"...populating complete!");
7801 cpl_propertylist_append_double(phu, DETMON_QC_GAIN_AVG,
7802 cpl_array_get_mean(gains));
7803 cpl_propertylist_set_comment(phu, DETMON_QC_GAIN_AVG,
7804 DETMON_QC_GAIN_AVG_C);
7806 cpl_propertylist_append_double(phu, DETMON_QC_GAIN_RMS,
7807 cpl_array_get_stdev(gains));
7808 cpl_propertylist_set_comment(phu, DETMON_QC_GAIN_RMS,
7809 DETMON_QC_GAIN_RMS_C);
7812 if (strcmp(recipe_name,
"detmon_opt_lg_mr") != 0) {
7815 cpl_propertylist_append_double(phu, DETMON_QC_CONAD_AVG,
7816 cpl_array_get_mean(conads));
7817 cpl_propertylist_set_comment(phu, DETMON_QC_CONAD_AVG,
7818 DETMON_QC_CONAD_AVG_C);
7820 cpl_propertylist_append_double(phu, DETMON_QC_CONAD_RMS,
7821 cpl_array_get_stdev(conads));
7822 cpl_propertylist_set_comment(phu, DETMON_QC_CONAD_RMS,
7823 DETMON_QC_CONAD_RMS_C);
7827 cpl_msg_info(cpl_func,
"Calculations complete!");
7830 cpl_propertylist_save(phu, fn, CPL_IO_CREATE);
7831 for (j=1; j<=nexts; ++j) {
7832 cpl_table_save(gain_tables[j-1], NULL,
7833 ehus[j-1], fn, CPL_IO_EXTEND);
7834 cpl_propertylist_delete(ehus[j-1]);
7835 cpl_table_delete(gain_tables[j-1]);
7850 cpl_msg_info(cpl_func,
"Cleaning up...");
7851 cpl_propertylist_delete(phu);
7855 cpl_free(gain_tables);
7857 cpl_frame_delete(fr);
7860 cpl_array_delete(conads);
7864 cpl_array_delete(gains);
7867 cpl_msg_info(cpl_func,
"...done!");
7869 return cpl_error_get_code();
7874 detmon_lg_qc_params_global_lin(
const char * recipe_name,
int nsets) {
7875 cpl_msg_info(cpl_func,
"Going to update linearity table for "
7876 "recipe %s, nsets=%d",
7877 recipe_name, nsets);
7881 fn = cpl_sprintf(
"%s_linearity_table.fits", recipe_name) ;
7882 cpl_msg_info(cpl_func,
"Will be modifying %s", fn, recipe_name) ;
7883 detmon_lg_qc_params_global_lin_update(fn, recipe_name);
7887 for (j=0; j<nsets; ++j) {
7888 fn = cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name, j);
7889 cpl_msg_info(cpl_func,
"Will be modifying %s", fn);
7890 detmon_lg_qc_params_global_lin_update(fn, recipe_name);
7895 return cpl_error_get_code();
7900 detmon_lg_qc_params_global_lin_update(
const char * fn,
7901 const char * recipe_name) {
7902 cpl_msg_info(cpl_func,
"Now updating %s", fn);
7904 cpl_propertylist* phu = cpl_propertylist_load(fn, 0);
7905 cpl_propertylist** ehus = NULL;
7906 cpl_table** lin_tables = NULL;
7907 cpl_array* gain_err = NULL;
7908 cpl_array* counts_min = NULL;
7909 cpl_array* counts_max = NULL;
7910 cpl_array* lin_eff = NULL;
7911 cpl_array* lin_eff_flux = NULL;
7913 cpl_array** contams = (cpl_array**)cpl_malloc(5 *
sizeof(cpl_array*));
7914 for (contam=0; contam < 5; ++contam) {
7915 contams[contam] = NULL;
7917 cpl_frame* fr = cpl_frame_new();
7918 char * coeff_kw = NULL ;
7919 char * coeff_comm = NULL ;
7930 cpl_frame_set_filename(fr, fn);
7931 int nexts = cpl_frame_get_nextensions(fr);
7933 cpl_msg_warning(cpl_func,
"No extensions in %s, so no QC "
7934 "keywords to write", fn);
7942 cpl_msg_info(cpl_func,
"Detected %d nexts", nexts);
7943 ehus = (cpl_propertylist**)cpl_malloc(nexts *
sizeof(cpl_propertylist*));
7944 lin_tables = (cpl_table**)cpl_malloc(nexts *
sizeof(cpl_table*));
7955 gain_err = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7956 counts_min = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7957 counts_max = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7958 lin_eff = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7959 lin_eff_flux = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7960 for (contam=0; contam < 5; ++contam) {
7961 contams[contam] = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7963 for (j=1; j <= nexts; ++j) {
7964 cpl_msg_info(cpl_func,
"Loading EHU %d", j);
7965 ehus[j-1] = cpl_propertylist_load(fn, j);
7966 lin_tables[j-1] = cpl_table_load(fn, j, 1);
7968 cpl_msg_info(cpl_func,
"Doing non-CONTAM values");
7970 if (cpl_propertylist_has(ehus[j-1],
"ESO QC GAIN ERR")) {
7971 cpl_array_set_double(gain_err, j-1,
7972 cpl_propertylist_get_double(
7973 ehus[j-1],
"ESO QC GAIN ERR"));
7975 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_COUNTS_MIN)) {
7976 cpl_array_set_double(counts_min, j-1,
7977 cpl_propertylist_get_double(
7978 ehus[j-1], DETMON_QC_COUNTS_MIN));
7980 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_COUNTS_MAX)) {
7981 cpl_array_set_double(counts_max, j-1,
7982 cpl_propertylist_get_double(
7983 ehus[j-1], DETMON_QC_COUNTS_MAX));
7985 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_LIN_EFF)) {
7986 cpl_array_set_double(lin_eff, j-1,
7987 cpl_propertylist_get_double(
7988 ehus[j-1], DETMON_QC_LIN_EFF));
7990 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_LIN_EFF_FLUX)) {
7991 cpl_array_set_double(lin_eff_flux, j-1,
7992 cpl_propertylist_get_double(
7993 ehus[j-1], DETMON_QC_LIN_EFF_FLUX));
7996 cpl_msg_info(cpl_func,
"Looping through contam values...");
7997 if (strcmp(recipe_name,
"detmon_opt_lg") == 0) {
7998 for (contam=0; contam<5 ; ++contam) {
8000 coeff_kw = cpl_sprintf(DETMON_QC_CONTAM
"%zd",
8002 if (cpl_propertylist_has(ehus[j-1],
8004 cpl_array_set_double(contams[contam], j-1,
8005 cpl_propertylist_get_double(
8022 cpl_msg_info(cpl_func,
"Computing & setting global values...");
8024 cpl_propertylist_append_double(phu, DETMON_QC_GAIN_ERR_AVG,
8025 cpl_array_get_mean(gain_err));
8026 cpl_propertylist_set_comment(phu, DETMON_QC_GAIN_ERR_AVG,
8027 DETMON_QC_GAIN_ERR_AVG_C);
8029 cpl_propertylist_append_double(phu, DETMON_QC_GAIN_ERR_RMS,
8030 cpl_array_get_stdev(gain_err));
8031 cpl_propertylist_set_comment(phu, DETMON_QC_GAIN_ERR_RMS,
8032 DETMON_QC_GAIN_ERR_RMS_C);
8034 cpl_propertylist_append_double(phu, DETMON_QC_COUNTS_MIN_AVG,
8035 cpl_array_get_mean(counts_min));
8036 cpl_propertylist_set_comment(phu, DETMON_QC_COUNTS_MIN_AVG,
8037 DETMON_QC_COUNTS_MIN_AVG_C);
8039 cpl_propertylist_append_double(phu, DETMON_QC_COUNTS_MIN_RMS,
8040 cpl_array_get_stdev(counts_min));
8041 cpl_propertylist_set_comment(phu, DETMON_QC_COUNTS_MIN_RMS,
8042 DETMON_QC_COUNTS_MIN_RMS_C);
8044 cpl_propertylist_append_double(phu, DETMON_QC_COUNTS_MAX_AVG,
8045 cpl_array_get_mean(counts_max));
8046 cpl_propertylist_set_comment(phu, DETMON_QC_COUNTS_MAX_AVG,
8047 DETMON_QC_COUNTS_MAX_AVG_C);
8049 cpl_propertylist_append_double(phu, DETMON_QC_COUNTS_MAX_RMS,
8050 cpl_array_get_stdev(counts_max));
8051 cpl_propertylist_set_comment(phu, DETMON_QC_COUNTS_MAX_RMS,
8052 DETMON_QC_COUNTS_MAX_RMS_C);
8054 cpl_propertylist_append_double(phu, DETMON_QC_LIN_EFF_AVG,
8055 cpl_array_get_mean(lin_eff));
8056 cpl_propertylist_set_comment(phu, DETMON_QC_LIN_EFF_AVG,
8057 DETMON_QC_LIN_EFF_AVG_C);
8059 cpl_propertylist_append_double(phu, DETMON_QC_LIN_EFF_RMS,
8060 cpl_array_get_stdev(lin_eff));
8061 cpl_propertylist_set_comment(phu, DETMON_QC_LIN_EFF_RMS,
8062 DETMON_QC_LIN_EFF_RMS_C);
8063 if (strcmp(recipe_name,
"detmon_opt_lg") == 0) {
8064 cpl_msg_info(cpl_func,
" Computing additional detmon_opt_lg values...");
8066 cpl_propertylist_append_double(phu, DETMON_QC_LIN_EFF_FLUX_AVG,
8067 cpl_array_get_mean(lin_eff_flux));
8068 cpl_propertylist_set_comment(phu, DETMON_QC_LIN_EFF_FLUX_AVG,
8069 DETMON_QC_LIN_EFF_FLUX_AVG_C);
8071 cpl_propertylist_append_double(phu, DETMON_QC_LIN_EFF_FLUX_RMS,
8072 cpl_array_get_stdev(lin_eff_flux));
8073 cpl_propertylist_set_comment(phu, DETMON_QC_LIN_EFF_FLUX_RMS,
8074 DETMON_QC_LIN_EFF_FLUX_RMS_C);
8077 for (contam=0 ; contam < 5; ++contam) {
8079 coeff_kw = cpl_sprintf(DETMON_QC_CONTAMi_AVG,
8081 coeff_comm = cpl_sprintf(DETMON_QC_CONTAMi_AVG_C,
8083 cpl_propertylist_append_double(phu,
8085 cpl_array_get_mean(contams[contam]));
8086 cpl_propertylist_set_comment(phu,
8090 cpl_free(coeff_comm);
8092 coeff_kw = cpl_sprintf(DETMON_QC_CONTAMi_RMS,
8094 coeff_comm = cpl_sprintf(DETMON_QC_CONTAMi_RMS_C,
8096 cpl_propertylist_append_double(phu,
8098 cpl_array_get_stdev(
8100 cpl_propertylist_set_comment(phu,
8104 cpl_free(coeff_comm);
8118 cpl_propertylist_save(phu, fn, CPL_IO_CREATE);
8119 for (j=1; j<=nexts; ++j) {
8120 cpl_table_save(lin_tables[j-1], NULL,
8121 ehus[j-1], fn, CPL_IO_EXTEND);
8122 cpl_propertylist_delete(ehus[j-1]);
8123 cpl_table_delete(lin_tables[j-1]);
8137 cpl_msg_info(cpl_func,
"Going into cleanup...");
8138 for (contam=0 ; contam<5 ; ++contam) {
8139 cpl_array_delete(contams[contam]);
8144 cpl_propertylist_delete(phu);
8146 cpl_free(lin_tables);
8150 cpl_array_delete(gain_err);
8152 cpl_array_delete(counts_min);
8154 cpl_array_delete(counts_max);
8156 cpl_array_delete(lin_eff);
8158 cpl_array_delete(lin_eff_flux);
8160 cpl_frame_delete(fr);
8162 cpl_msg_info(cpl_func,
"...done!");
8164 return cpl_error_get_code();
8168 detmon_lg_qc_params_global_bpm(
const char * recipe_name,
int nsets) {
8169 cpl_msg_info(cpl_func,
"Going to update BPM image for "
8170 "recipe %s, nsets=%d",
8171 recipe_name, nsets);
8176 fn = cpl_sprintf(
"%s_bpm.fits", recipe_name) ;
8177 cpl_msg_info(cpl_func,
"Will be modifying %s", fn) ;
8178 err = detmon_lg_qc_params_global_bpm_update(fn, recipe_name);
8182 for (j=0; j<nsets; ++j) {
8183 fn = cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, j);
8184 cpl_msg_info(cpl_func,
"Will be modifying %s", fn);
8185 err = detmon_lg_qc_params_global_bpm_update(fn, recipe_name);
8194 detmon_lg_qc_params_global_bpm_update(
const char * fn,
8195 const char * recipe_name) {
8196 cpl_msg_info(cpl_func,
"Now updating %s", fn);
8198 cpl_propertylist* phu = cpl_propertylist_load(fn, 0);
8199 cpl_propertylist** ehus = NULL ;
8200 cpl_image** bpm_imgs = NULL ;
8201 cpl_array* num_bpm = NULL;
8202 cpl_frame* fr = cpl_frame_new();
8208 if ((strcmp(recipe_name,
"detmon_opt_lg_mr") == 0 ) ||
8209 (strcmp(recipe_name,
"detmon_ir_lg_mr")) == 0) {
8214 cpl_frame_set_filename(fr, fn);
8215 int nexts = cpl_frame_get_nextensions(fr);
8217 cpl_msg_warning(cpl_func,
"No extensions in %s, so no QC "
8218 "keywords to write", fn);
8226 cpl_msg_info(cpl_func,
"Detected %d nexts", nexts);
8227 ehus = (cpl_propertylist**)cpl_malloc(nexts *
sizeof(cpl_propertylist*));
8228 bpm_imgs = (cpl_image**)cpl_malloc(nexts *
sizeof(cpl_image*));
8232 num_bpm = cpl_array_new(nexts, CPL_TYPE_INT);
8234 for (j=1; j<=nexts; ++j) {
8235 cpl_msg_info(cpl_func,
"Loading ext %d", j);
8236 ehus[j-1] = cpl_propertylist_load(fn, j);
8237 bpm_imgs[j-1] = cpl_image_load(fn, CPL_BPP_IEEE_FLOAT, 0, j);
8238 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_NUM_BPM)) {
8239 cpl_array_set_int(num_bpm, j-1,
8240 cpl_propertylist_get_int(ehus[j-1],
8241 DETMON_QC_NUM_BPM));
8247 cpl_propertylist_append_double(phu, DETMON_QC_NUM_BPM_AVG,
8248 cpl_array_get_mean(num_bpm));
8249 cpl_propertylist_set_comment(phu, DETMON_QC_NUM_BPM_AVG,
8250 DETMON_QC_NUM_BPM_AVG_C);
8253 cpl_propertylist_save(phu, fn, CPL_IO_CREATE);
8254 for (j=1; j<=nexts; ++j) {
8255 cpl_image_save(bpm_imgs[j-1], fn, CPL_BPP_IEEE_FLOAT, ehus[j-1],
8257 cpl_propertylist_delete(ehus[j-1]);
8258 cpl_image_delete(bpm_imgs[j-1]);
8272 cpl_msg_info(cpl_func,
"Doing cleanup");
8274 cpl_propertylist_delete(phu);
8278 cpl_array_delete(num_bpm);
8280 cpl_frame_delete(fr);
8282 cpl_msg_info(cpl_func,
"...done!");
8284 return cpl_error_get_code();
8289 detmon_lg_qc_params_global_coeffs(
const char * recipe_name,
int nsets) {
8290 cpl_msg_info(cpl_func,
"Going to update coeffs image for "
8291 "recipe %s, nsets=%d",
8292 recipe_name, nsets);
8294 cpl_error_code err = CPL_ERROR_NONE;
8297 fn = cpl_sprintf(
"%s_coeffs_cube.fits", recipe_name);
8298 cpl_msg_info(cpl_func,
"Will be modifying %s", fn) ;
8299 err = detmon_lg_qc_params_global_coeffs_update(fn, recipe_name);
8303 for (j=0; j<nsets; ++j) {
8304 fn = cpl_sprintf(
"%s_coeffs_cube_set%02d.fits",
8306 cpl_msg_info(cpl_func,
"Will be modifying %s", fn);
8307 err = detmon_lg_qc_params_global_coeffs_update(fn, recipe_name);
8316 detmon_lg_qc_params_global_coeffs_update(
const char * fn,
8317 const char * recipe_name) {
8318 cpl_msg_info(cpl_func,
"Now updating %s", fn);
8320 cpl_propertylist* phu = cpl_propertylist_load(fn, 0);
8321 cpl_propertylist** ehus = NULL;
8322 cpl_imagelist** coeff_cubes = NULL;
8323 cpl_frame* fr = NULL;
8324 cpl_array* lin_coeff = NULL;
8325 cpl_array* lin_coeff_err = NULL;
8326 cpl_array* errfit = NULL;
8327 char* coeff_kw = NULL ;
8328 char* coeff_kw_err = NULL ;
8329 char* coeff_str = NULL ;
8332 fr = cpl_frame_new();
8333 cpl_frame_set_filename(fr, fn);
8334 int nexts = cpl_frame_get_nextensions(fr);
8336 cpl_msg_warning(cpl_func,
"No extensions in %s, so no QC "
8337 "keywords to write", fn);
8346 if ((strcmp(recipe_name,
"detmon_opt_lg_mr") == 0 ) ||
8347 (strcmp(recipe_name,
"detmon_ir_lg_mr")) == 0) {
8348 cpl_msg_info(cpl_func,
"Skipping %s for recipe %s",
8349 cpl_func, recipe_name);
8353 cpl_msg_info(cpl_func,
"Detected %d nexts", nexts);
8354 ehus = (cpl_propertylist**)cpl_malloc(nexts *
sizeof(cpl_propertylist*));
8355 coeff_cubes = (cpl_imagelist**)cpl_malloc(nexts *
sizeof(cpl_imagelist*));
8356 cpl_msg_info(cpl_func,
"Malloc'd data structures for eventual re-write");
8359 int j, coeff, coeff_max ;
8361 for (j=1; j<=nexts; ++j) {
8362 ehus[j-1] = cpl_propertylist_load(fn, j);
8364 cpl_msg_info(__func__,
"Loaded extension headers");
8367 cpl_msg_info(__func__,
"Creating lin_coeff and errfit arrays...");
8368 lin_coeff = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
8369 lin_coeff_err = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
8370 errfit = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
8371 cpl_msg_info(__func__,
"...done!");
8373 if (strcmp(recipe_name,
"detmon_ir_lg") == 0) {
8376 cpl_msg_info(cpl_func,
"Populating errfit arrays");
8377 for (j=1; j<=nexts; ++j) {
8378 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_ERRFIT)) {
8379 cpl_array_set_double(
8381 cpl_propertylist_get_double(ehus[j-1],
8386 cpl_msg_info(cpl_func,
"Setting keywords with new funcs");
8387 detmon_lg_set_keyword_from_base_double(phu,
8388 DETMON_QC_ERRFIT,
"AVG",
8391 cpl_array_get_mean(errfit));
8393 detmon_lg_set_keyword_from_base_double(phu,
8394 DETMON_QC_ERRFIT,
"RMS",
8397 cpl_array_get_stdev(errfit));
8412 for (coeff = 0 ; coeff < coeff_max + 1 ; ++coeff) {
8413 cpl_msg_info(cpl_func,
"Forming coeff keyword %d", coeff);
8414 coeff_kw = cpl_sprintf(
"ESO QC LIN COEF%d", coeff);
8415 coeff_kw_err = cpl_sprintf(
"ESO QC LIN COEF%d ERR",
8417 coeff_str = cpl_sprintf(
"%d", coeff);
8420 cpl_msg_info(cpl_func,
"Reading in the coeff values");
8421 for (j=1; j<=nexts; ++j) {
8423 if (cpl_propertylist_has(ehus[j-1],
8425 cpl_array_set_double(
8428 cpl_propertylist_get_double(
8432 cpl_msg_info(cpl_func,
"Added value %f to lin_coeff in pos %d",
8433 cpl_propertylist_get_double(
8438 if (cpl_propertylist_has(ehus[j-1],
8440 cpl_array_set_double(
8442 cpl_propertylist_get_double(
8447 cpl_msg_info(__func__,
"Insertions complete! (%d)", coeff);
8460 cpl_msg_info(cpl_func,
"Writing back header keywords for %d", coeff);
8462 if (cpl_array_count_invalid(lin_coeff) < (cpl_size)nexts) {
8463 detmon_lg_set_keyword_from_insert_double(
8465 DETMON_QC_LIN_COEFF_AVG, coeff_str,
8466 DETMON_QC_LIN_COEFF_AVG_C, coeff_str,
8467 cpl_array_get_mean(lin_coeff)
8471 detmon_lg_set_keyword_from_insert_double(
8473 DETMON_QC_LIN_COEFF_RMS, coeff_str,
8474 DETMON_QC_LIN_COEFF_RMS_C, coeff_str,
8475 cpl_array_get_stdev(lin_coeff)
8479 if (cpl_array_count_invalid(lin_coeff_err) < (cpl_size)nexts) {
8481 detmon_lg_set_keyword_from_insert_double(
8483 DETMON_QC_LIN_COEFF_ERR_AVG, coeff_str,
8484 DETMON_QC_LIN_COEFF_ERR_AVG_C, coeff_str,
8485 cpl_array_get_mean(lin_coeff_err)
8489 detmon_lg_set_keyword_from_insert_double(
8491 DETMON_QC_LIN_COEFF_ERR_RMS, coeff_str,
8492 DETMON_QC_LIN_COEFF_ERR_RMS_C, coeff_str,
8493 cpl_array_get_stdev(lin_coeff)
8497 cpl_msg_info(__func__,
"Data write complete! (%d)", coeff);
8511 cpl_array_fill_window_invalid(lin_coeff, 0, nexts);
8512 cpl_array_fill_window_invalid(lin_coeff_err, 0, nexts);
8513 cpl_msg_info(__func__,
"Arrays reset! (%d)", coeff);
8524 cpl_msg_info(cpl_func,
"Purging the coeff keywords");
8526 cpl_free(coeff_kw_err);
8527 cpl_free(coeff_str);
8529 coeff_kw_err = NULL ;
8556 for (j=1; j<=nexts; ++j) {
8557 coeff_cubes[j-1] = cpl_imagelist_load(fn, CPL_BPP_IEEE_FLOAT, j);
8559 cpl_propertylist_save(phu, fn, CPL_IO_CREATE);
8560 for (j=1; j<=nexts; ++j) {
8561 cpl_imagelist_save(coeff_cubes[j-1], fn, CPL_BPP_IEEE_FLOAT, ehus[j-1],
8564 cpl_propertylist_delete(ehus[j-1]);
8565 cpl_imagelist_delete(coeff_cubes[j-1]);
8567 cpl_msg_info(__func__,
"Removed all file data in memory");
8580 cpl_msg_info(cpl_func,
"Doing cleanup...");
8583 cpl_propertylist_delete(phu);
8585 cpl_free(coeff_cubes);
8587 cpl_frame_delete(fr);
8589 cpl_array_delete(lin_coeff);
8591 cpl_array_delete(lin_coeff_err);
8593 cpl_array_delete(errfit);
8595 cpl_msg_info(cpl_func,
"...done!");
8596 return cpl_error_get_code();
8600 detmon_lg_qc_set_kw_from_table_column(cpl_table* table,
8601 const char * column,
8603 cpl_propertylist* header,
8605 const char * kw_comment) {
8607 if (strcmp(op,
"mean") == 0) {
8608 value = cpl_table_get_column_mean(table, column);
8609 }
else if (strcmp(op,
"stdev") == 0) {
8610 value = cpl_table_get_column_stdev(table, column);
8612 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
8613 return cpl_error_get_code();
8616 cpl_propertylist_append_double(header, kw, value);
8617 if (kw_comment != NULL) {
8618 cpl_propertylist_set_comment(header, kw, kw_comment);
8620 return cpl_error_get_code();