44#include "detmon_utils.h"
45#include "detmon_lg_impl.h"
47#include "irplib_ksigma_clip.h"
48#include "irplib_utils.h"
49#include "irplib_hist.h"
74typedef enum _FPN_METHOD FPN_METHOD;
114 cpl_boolean wholechip;
115 cpl_boolean autocorr;
116 cpl_boolean intermediate;
117 cpl_boolean collapse;
124 const char * pafname;
129 double lamp_stability;
132 int (* load_fset) (
const cpl_frameset *, cpl_type, cpl_imagelist *);
133 cpl_imagelist * (* load_fset_wrp) (
const cpl_frameset *, cpl_type, int);
134 FPN_METHOD fpn_method;
136 double saturation_limit;
137 double gain_threshold;
138 cpl_boolean split_coeffs;
149detmon_lg_retrieve_parlist(
const char *,
150 const char *,
const cpl_parameterlist *,
155detmon_lg_split_onoff(
const cpl_frameset *,
158 const char *,
const char * );
161detmon_lg_reduce(
const cpl_frameset *,
162 const cpl_frameset *,
163 int* index_on,
int* index_off,
164 double* exptime_on,
double* exptime_off,
165 int *next_index_on,
int* next_index_off,
176 int (* load_fset) (
const cpl_frameset *,
179 const cpl_boolean,
int);
185detmon_lin_table_fill_row(cpl_table *,
double,
187 const cpl_imagelist *,
188 const cpl_imagelist *,
195detmon_gain_table_fill_row(cpl_table * gain_table,
196 double c_dit,
int c_ndit,
197 cpl_imagelist * autocorr_images,
198 cpl_imagelist * diff_flats,
199 const cpl_imagelist * ons,
200 const cpl_imagelist * offs,
201 double kappa,
int nclip,
202 int llx,
int lly,
int urx,
int ury,
204 double gain_threshold,
205 int pos,
unsigned mode,
int* rows_affected);
209detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
210 cpl_imagelist * diff_flats,
211 const cpl_imagelist * ons,
212 double kappa,
int nclip,
213 int llx,
int lly,
int urx,
int ury,
214 double saturation_limit,
215 const int pos,
unsigned mode,
216 int* rows_linear_affected);
219detmon_lg_save(
const cpl_parameterlist *,
224 const cpl_propertylist *,
225 const cpl_propertylist *,
226 const cpl_propertylist *,
227 const cpl_propertylist *,
228 const cpl_propertylist *,
229 const cpl_propertylist *,
241 const int,
const int,
const cpl_frameset *,
245detmon_lg_qc_ptc(
const cpl_table *,
246 cpl_propertylist *,
unsigned,
int);
249detmon_lg_qc_med(
const cpl_table *,
250 cpl_propertylist *,
int);
254detmon_pfits_get_dit(
const cpl_propertylist *);
257detmon_pfits_get_dit_opt(
const cpl_propertylist *);
259irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
260 const char* prop_name);
262static cpl_image * detmon_bpixs(
const cpl_imagelist *,
263 cpl_boolean,
const double,
int *);
266detmon_autocorr_factor(
const cpl_image *,
267 cpl_image **,
int,
int);
272detmon_opt_contamination(
const cpl_imagelist *,
273 const cpl_imagelist *,
274 unsigned mode, cpl_propertylist *);
277detmon_opt_lampcr(cpl_frameset *,
int);
281detmon_lg_dfs_set_groups(cpl_frameset *,
const char *,
const char *);
284detmon_lg_reduce_all(
const cpl_table *,
291 const cpl_imagelist *,
292 const cpl_table *,
int, cpl_boolean);
295detmon_lg_check_defaults(
const cpl_image *);
298detmon_lg_rescale(cpl_imagelist *);
301detmon_lg_reduce_init(cpl_table *,
308detmon_add_adl_column(cpl_table *, cpl_boolean);
311detmon_lg_lamp_stab(
const cpl_frameset *,
312 const cpl_frameset *,
317detmon_lg_reduce_dit(
const cpl_frameset * set_on,
318 int* index_on,
double* exptime_on,
321 const cpl_frameset * set_off,
322 int * index_off,
double* exptime_off,
323 int* next_on,
int* next_off,
324 cpl_table * linear_table,
325 cpl_table * gain_table,
326 cpl_imagelist * linearity_inputs,
327 cpl_propertylist * qclist,
329 cpl_imagelist * autocorr_images,
330 cpl_imagelist * diff_flats,
331 cpl_imagelist * opt_offs,
333 int * rows_linear_affected,
334 int * rows_gain_affected);
337detmon_lg_core(cpl_frameset * cur_fset_on,
338 cpl_frameset * cur_fset_off,
342 double * exptime_off,
345 const char * recipe_name,
346 const char * pipeline_name,
347 const char * pafregexp,
348 const cpl_propertylist * pro_lintbl,
349 const cpl_propertylist * pro_gaintbl,
350 const cpl_propertylist * pro_coeffscube,
351 const cpl_propertylist * pro_bpm,
352 const cpl_propertylist * pro_corr,
353 const cpl_propertylist * pro_diff,
354 const char * package,
355 int (* load_fset) (
const cpl_frameset *,
358 int nsets, cpl_boolean opt_nir,
359 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
360 cpl_frameset * cur_fset);
363detmon_lg_lineff(
double *, cpl_propertylist *,
int,
int);
371detmon_gain_table_create(cpl_table *,
376detmon_lin_table_create(cpl_table *,
380detmon_lg_find_dits(
const cpl_vector *,
384detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
385 const cpl_vector * vec_ndits,
387 cpl_vector** diff_dits,
388 cpl_vector** diff_ndits);
391detmon_fpn_compute(
const cpl_frameset *set_on,
393 int last_linear_best,
394 cpl_propertylist *lint_qclist,
401 FPN_METHOD fpn_method,
403static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain,
404 FPN_METHOD fpn_method,
int,
double* mse);
405static double irplib_calculate_total_noise(
const cpl_image* pimage);
407static cpl_imagelist* irplib_load_fset_wrp(
const cpl_frameset *,
408 cpl_type,
int whichext);
409static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset *,
412static cpl_error_code irplib_table_create_column(cpl_table* ptable,
413 cpl_propertylist* plist);
414static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
415 cpl_propertylist* plist,
419detmon_pair_extract_next(
const cpl_frameset * set,
425 cpl_frameset ** pair,
428detmon_single_extract_next(
const cpl_frameset * set,
432 cpl_frameset ** pair);
439static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code);
440static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos);
441static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y);
450static int irplib_pfits_get_ndit(
const cpl_propertylist * plist)
452 return cpl_propertylist_get_int(plist,
"ESO DET NDIT");
495#ifdef DETMON_USE_DETECTOR_SHOTNOISE_MODEL
519hdrldemo_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
520 const double ron, cpl_image ** ima_errs)
522 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
523 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
524 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
525 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
527 *ima_errs = cpl_image_duplicate(ima_data);
529 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
533 cpl_image_divide_scalar(*ima_errs, gain);
534 cpl_image_add_scalar(*ima_errs, ron * ron);
535 cpl_image_power(*ima_errs, 0.5);
537 return cpl_error_get_code();
542detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
545 const char * tag_off,
546 const char * recipe_name,
547 const char * pipeline_name,
548 const char * pafregexp,
549 const cpl_propertylist * pro_lintbl,
550 const cpl_propertylist * pro_gaintbl,
551 const cpl_propertylist * pro_coeffscube,
552 const cpl_propertylist * pro_bpm,
553 const cpl_propertylist * pro_corr,
554 const cpl_propertylist * pro_diff,
555 const char * package,
557 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
558 const cpl_boolean opt_nir,
559 const cpl_parameterlist * parlist,
562static double irplib_compute_err(
double gain,
double ron,
double photon_noise);
565detmon_lg_dfs_save_imagelist(cpl_frameset * frameset,
566 const cpl_parameterlist * parlist,
567 const cpl_frameset *usedframes,
568 const cpl_imagelist *coeffs,
569 const char *recipe_name,
570 const cpl_propertylist *mypro_coeffscube,
571 const char * package,
572 const char * name_o);
575static void irplib_free(
char** pointer){
577 if(pointer && *pointer) {
584detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
int nsets,
586 const char * tag_off,
587 const char * recipe_name,
588 const char * pipeline_name,
589 const char * pafregexp,
590 const cpl_propertylist * pro_lintbl,
591 const cpl_propertylist * pro_gaintbl,
592 const cpl_propertylist * pro_coeffscube,
593 const cpl_propertylist * pro_bpm,
594 const cpl_propertylist * pro_corr,
595 const cpl_propertylist * pro_diff,
596 const char * package,
598 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
599 const cpl_boolean opt_nir,
600 const cpl_parameterlist * parlist,
605 int nexts = detmon_lg_config.nb_extensions;
607 double* exptime_on = 0;
608 double* exptime_off = 0;
611 cpl_frameset * cur_fset = NULL;
612 cpl_frameset* cur_fset_on = 0;
613 cpl_frameset* cur_fset_off = 0;
618 cpl_frameset_duplicate(frameset) : cpl_frameset_extract(frameset, selection, i);
621 skip_if(cur_fset == NULL);
624 cur_fset_on = cpl_frameset_new();
625 cur_fset_off = cpl_frameset_new();
626 cpl_msg_info(cpl_func,
"Splitting into ON and OFF sub-framesets");
627 skip_if (detmon_lg_split_onoff(cur_fset,
628 cur_fset_on, cur_fset_off,
630 if (cpl_frameset_get_size(cur_fset_on) == 0)
632 cpl_msg_error(cpl_func,
"No lamp frames in input");
636 if (cpl_frameset_get_size(cur_fset_off) == 0)
638 cpl_msg_error(cpl_func,
"No dark / bias frames in input");
641 cpl_msg_info(cpl_func,
"found on-frames[%" CPL_SIZE_FORMAT
"] off-frames[%" CPL_SIZE_FORMAT
"]",cpl_frameset_get_size(cur_fset_on), cpl_frameset_get_size(cur_fset_off));
649 exptime_on = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_on));
650 exptime_off = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_off));
652 index_on = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_on));
653 index_off = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_off));
654 irplib_frameset_sort(cur_fset_on, index_on, exptime_on);
655 irplib_frameset_sort(cur_fset_off, index_off, exptime_off);
668 skip_if(detmon_check_order(exptime_on, cpl_frameset_get_size(cur_fset_on), detmon_lg_config.tolerance, detmon_lg_config.order));
670 if(detmon_lg_config.exts >= 0)
678 if (detmon_lg_config.lamp_ok) {
679 skip_if(detmon_opt_lampcr(cur_fset, 0));
682 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
687 detmon_lg_config.exts,
689 recipe_name, pipeline_name, pafregexp,
690 pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff,
691 package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
693 for(j = 1; j <= nexts; j++) {
700 if (detmon_lg_config.lamp_ok) {
701 skip_if(detmon_opt_lampcr(cur_fset, j));
705 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
711 pipeline_name, pafregexp,
712 pro_lintbl, pro_gaintbl,
714 pro_bpm, pro_corr, pro_diff,
715 package, load_fset, nsets, opt_nir,
716 frameset, parlist, cur_fset));
724 char* par_name = NULL ;
725 if (strcmp(recipe_name,
"detmon_opt_lg") == 0 ||
726 strcmp(recipe_name,
"detmon_ir_lg") == 0) {
727 cpl_msg_debug(cpl_func,
"This is where I want to write the 'super' QC kw");
728 cpl_msg_debug(cpl_func,
"Writing super QC kw for recipe %s", recipe_name);
730 if (cpl_error_get_code() != CPL_ERROR_NONE) {
731 cpl_msg_error(__func__,
"Error found in detmon_lg_reduce_set!");
732 cpl_msg_error(__func__,
"At: before computing for gain and lin global");
733 cpl_msg_error(__func__,
"In %s, L%u", cpl_error_get_file(),
734 cpl_error_get_line());
735 cpl_msg_error(__func__,
"%s", cpl_error_get_message());
737 detmon_lg_qc_params_global_gain(recipe_name, nsets);
738 detmon_lg_qc_params_global_lin(recipe_name, nsets);
739 par_name = cpl_sprintf(
"detmon.%s.pix2pix", recipe_name);
740 cpl_parameter* pix2pix = cpl_parameterlist_find(
743 if (pix2pix != NULL && cpl_parameter_get_bool(pix2pix)) {
744 if (cpl_error_get_code() != CPL_ERROR_NONE) {
745 cpl_msg_error(__func__,
"Error found in detmon_lg_reduce_set!");
746 cpl_msg_error(__func__,
"At: before computing for bpm and coeffs global");
747 cpl_msg_error(__func__,
"In %s, L%u", cpl_error_get_file(),
748 cpl_error_get_line());
749 cpl_msg_error(__func__,
"%s", cpl_error_get_message());
751 detmon_lg_qc_params_global_bpm(recipe_name, nsets);
752 detmon_lg_qc_params_global_coeffs(recipe_name, nsets);
757 cpl_frameset_delete(cur_fset);
758 cpl_frameset_delete(cur_fset_on);
759 cpl_frameset_delete(cur_fset_off);
762 cpl_free(exptime_on);
763 cpl_free(exptime_off);
764 return cpl_error_get_code();
842detmon_lg(cpl_frameset * frameset,
843 const cpl_parameterlist * parlist,
845 const char * tag_off,
846 const char * recipe_name,
847 const char * pipeline_name,
848 const char * pafregexp,
849 const cpl_propertylist * pro_lintbl,
850 const cpl_propertylist * pro_gaintbl,
851 const cpl_propertylist * pro_coeffscube,
852 const cpl_propertylist * pro_bpm,
853 const cpl_propertylist * pro_corr,
854 const cpl_propertylist * pro_diff,
855 const char * package,
856 int (* compare) (
const cpl_frame *,
858 int (* load_fset) (
const cpl_frameset *,
861 const cpl_boolean opt_nir)
863 cpl_errorstate cleanstate = cpl_errorstate_get();
865 cpl_size * selection = NULL;
866 cpl_frame * first = NULL;
867 cpl_image * reference = NULL;
874 cpl_frameset * cur_fset = NULL;
875 cpl_frameset * cur_fset_on = NULL;
876 cpl_frameset * cur_fset_off = NULL;
879 cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
880 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
881 cpl_ensure_code(tag_on != NULL, CPL_ERROR_NULL_INPUT);
882 cpl_ensure_code(tag_off != NULL, CPL_ERROR_NULL_INPUT);
883 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
884 cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
885 cpl_ensure_code(pro_lintbl != NULL, CPL_ERROR_NULL_INPUT);
886 cpl_ensure_code(pro_gaintbl != NULL, CPL_ERROR_NULL_INPUT);
887 cpl_ensure_code(pro_coeffscube != NULL, CPL_ERROR_NULL_INPUT);
888 cpl_ensure_code(pro_bpm != NULL, CPL_ERROR_NULL_INPUT);
889 cpl_ensure_code(pro_corr != NULL, CPL_ERROR_NULL_INPUT);
890 cpl_ensure_code(pro_diff != NULL, CPL_ERROR_NULL_INPUT);
891 cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
893 cpl_msg_info(cpl_func,
"frameset size [%" CPL_SIZE_FORMAT
"]", cpl_frameset_get_size(frameset));
896 skip_if (detmon_lg_dfs_set_groups(frameset, tag_on, tag_off));
903 skip_if (detmon_lg_retrieve_parlist(pipeline_name, recipe_name,
911 first = cpl_frameset_get_position(frameset, 0);
912 irplib_ensure (first != NULL, CPL_ERROR_ILLEGAL_INPUT,
"Empty data set! Provide %s and %s input frames",tag_on,tag_off);
914 detmon_lg_config.load_fset = load_fset;
915 detmon_lg_config.load_fset_wrp = load_fset ? irplib_load_fset_wrp_ext : irplib_load_fset_wrp;
918 detmon_lg_config.nb_extensions = 1;
919 if (detmon_lg_config.exts < 0) {
921 detmon_lg_config.nb_extensions = cpl_frame_get_nextensions(first);
922 while (reference == NULL && i <= detmon_lg_config.nb_extensions) {
923 reference = cpl_image_load(cpl_frame_get_filename(first),
924 CPL_TYPE_FLOAT, 0, i);
925 if (reference == NULL) {
926 cpl_msg_warning(cpl_func,
"Extension %d empty, skipping", i);
927 cpl_errorstate_set(cleanstate);
931 cpl_errorstate_set(cleanstate);
932 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
933 "No data found in any extension");
934 cpl_msg_info(cpl_func,
"Using extension %d as reference", i - 1);
936 if (load_fset != NULL) {
937 cpl_frameset *
new = cpl_frameset_new();
938 cpl_imagelist * p = cpl_imagelist_new();
939 cpl_frameset_insert(
new, cpl_frame_duplicate(first));
940 (*load_fset)(
new, CPL_TYPE_FLOAT, p);
941 reference = cpl_image_duplicate(cpl_imagelist_get(p, 0));
942 cpl_imagelist_delete(p);
943 cpl_frameset_delete(
new);
945 cpl_msg_info(cpl_func,
"name=%s",cpl_frame_get_filename(first));
946 reference = cpl_image_load(cpl_frame_get_filename(first),
947 CPL_TYPE_FLOAT, 0, detmon_lg_config.exts);
949 cpl_errorstate_set(cleanstate);
950 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
951 "No data found in requested extension %d",
952 detmon_lg_config.exts);
954 skip_if (reference == NULL);
956 skip_if (detmon_lg_check_defaults(reference));
965 if (compare == NULL) {
968 cpl_msg_info(cpl_func,
"Identifying different settings");
969 selection = cpl_frameset_labelise(frameset, compare, &nsets);
970 skip_if (selection == NULL);
974 for(
int i = 0; i < nsets; i++)
976 int fr_size = cpl_frameset_get_size(frameset);
978 cpl_msg_info(cpl_func,
"Reduce data set nb %d out of %" CPL_SIZE_FORMAT
"",
980 skip_if(detmon_lg_reduce_set(i, frameset, nsets, tag_on, tag_off,
995 fr_size_new = cpl_frameset_get_size(frameset);
1001 if (fr_size_new > fr_size)
1003 selection = cpl_realloc(selection, fr_size_new *
sizeof(selection[0]));
1004 memset(selection + fr_size, -1, (fr_size_new - fr_size) *
sizeof(selection[0]));
1010 cpl_frameset_delete(cur_fset);
1011 cpl_frameset_delete(cur_fset_on);
1012 cpl_frameset_delete(cur_fset_off);
1013 cpl_free(selection);
1014 cpl_image_delete(reference);
1016 return cpl_error_get_code();
1052static cpl_error_code
1053detmon_lg_core(cpl_frameset * cur_fset_on,
1054 cpl_frameset * cur_fset_off,
1057 double * exptime_on,
1058 double * exptime_off,
1061 const char * recipe_name,
1062 const char * pipeline_name,
1063 const char * pafregexp,
1064 const cpl_propertylist * pro_lintbl,
1065 const cpl_propertylist * pro_gaintbl,
1066 const cpl_propertylist * pro_coeffscube,
1067 const cpl_propertylist * pro_bpm,
1068 const cpl_propertylist * pro_corr,
1069 const cpl_propertylist * pro_diff,
1070 const char * package,
1071 int (* load_fset) (
const cpl_frameset *,
1074 int nsets, cpl_boolean opt_nir,
1075 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
1076 cpl_frameset * cur_fset)
1078 cpl_table * gain_table = cpl_table_new(
1079 cpl_frameset_get_size(cur_fset_on) / 2);
1080 cpl_table * linear_table = cpl_table_new(
1081 cpl_frameset_get_size(cur_fset_on) / 2);
1082 cpl_imagelist * coeffs = NULL;
1083 cpl_image * bpm = NULL;
1084 cpl_imagelist * autocorr_images = NULL;
1085 cpl_imagelist * diff_flats = NULL;
1086 cpl_propertylist * gaint_qclist = NULL;
1087 cpl_propertylist * lint_qclist = NULL;
1088 cpl_propertylist * linc_qclist = NULL;
1089 cpl_propertylist * bpm_qclist = NULL;
1091 int next_index_on = 0;
1092 int next_index_off = 0;
1095 cpl_msg_info(cpl_func,
"Reduce extension nb %d ", whichext);
1099 if (detmon_lg_config.intermediate) {
1100 autocorr_images = cpl_imagelist_new();
1101 diff_flats = cpl_imagelist_new();
1104 gaint_qclist = cpl_propertylist_new();
1105 lint_qclist = cpl_propertylist_new();
1106 linc_qclist = cpl_propertylist_new();
1107 bpm_qclist = cpl_propertylist_new();
1110 cpl_msg_info(cpl_func,
"Starting data reduction");
1111 if (detmon_lg_reduce(cur_fset_on, cur_fset_off,
1112 index_on, index_off, exptime_on, exptime_off,
1113 &next_index_on, &next_index_off,
1114 &coeffs, gain_table,
1115 linear_table, &bpm, autocorr_images,
1116 diff_flats, gaint_qclist, lint_qclist,
1117 linc_qclist, bpm_qclist, load_fset,
1118 opt_nir, whichext) == CPL_ERROR_CONTINUE) {
1119 cpl_msg_info(cpl_func,
"Empty extension %d", whichext);
1125 if (strcmp(recipe_name,
"detmon_opt_lg") == 0 ||
1126 strcmp(recipe_name,
"detmon_ir_lg") == 0) {
1127 cpl_msg_debug(cpl_func,
"Inserting per-extension QC params");
1128 detmon_lg_qc_params(
1129 linear_table, lint_qclist,
1130 gain_table, gaint_qclist,
1131 coeffs, linc_qclist,
1138 cpl_msg_info(cpl_func,
"Saving the products");
1141 detmon_lg_save(parlist, frameset, recipe_name,
1142 pipeline_name, pafregexp,
1143 pro_lintbl, pro_gaintbl,
1144 pro_coeffscube, pro_bpm,
1145 pro_corr, pro_diff, package,
1146 coeffs, gain_table, linear_table,
1147 bpm, autocorr_images, diff_flats,
1148 gaint_qclist, lint_qclist, linc_qclist,
1151 cur_fset, whichext));
1154 detmon_lg_save(parlist, frameset, recipe_name,
1155 pipeline_name, pafregexp,
1156 pro_lintbl, pro_gaintbl,
1157 pro_coeffscube, pro_bpm,
1158 pro_corr, pro_diff, package,
1159 coeffs, gain_table, linear_table,
1160 bpm, autocorr_images, diff_flats,
1161 gaint_qclist, lint_qclist, linc_qclist,
1164 cur_fset, whichext));
1171 cpl_table_delete(gain_table);
1172 cpl_table_delete(linear_table);
1173 cpl_imagelist_delete(coeffs);
1174 cpl_propertylist_delete(gaint_qclist);
1175 cpl_propertylist_delete(lint_qclist);
1176 cpl_propertylist_delete(linc_qclist);
1177 if(bpm_qclist != NULL) cpl_propertylist_delete(bpm_qclist);
1178 cpl_image_delete(bpm);
1179 cpl_imagelist_delete(autocorr_images);
1180 cpl_imagelist_delete(diff_flats);
1182 return cpl_error_get_code();
1207detmon_image_correlate(
const cpl_image * image1,
1208 const cpl_image * image2,
1209 const int m,
const int n)
1211 cpl_image *image1_padded = NULL;
1212 cpl_image *image2_padded = NULL;
1216 cpl_image *corr_image_window = NULL;
1218 cpl_image* image_ri1 = NULL;
1219 cpl_image* image_ri2 = NULL;
1220 cpl_error_code err = CPL_ERROR_NONE;
1223 cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1224 cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1226 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1227 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1229 nx = cpl_image_get_size_x(image1);
1230 ny = cpl_image_get_size_y(image1);
1232 nx2 = cpl_image_get_size_x(image2);
1233 ny2 = cpl_image_get_size_y(image2);
1236 cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
1239 image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1240 cpl_image_copy(image1_padded, image1, m + 1, n + 1);
1242 image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1243 cpl_image_copy(image2_padded, image2, m + 1, n + 1);
1249 image_ri1 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
1250 image_ri2 = cpl_image_new(nx, ny , CPL_TYPE_FLOAT_COMPLEX);
1252 cpl_fft_image(image_ri1, image1_padded, CPL_FFT_FORWARD);
1253 cpl_fft_image(image_ri2, image2_padded, CPL_FFT_FORWARD);
1254 err = cpl_error_get_code();
1255 cpl_image_delete(image1_padded);
1256 image1_padded = NULL;
1257 cpl_image_delete(image2_padded);
1258 image2_padded = NULL;
1259 if (err == CPL_ERROR_NONE)
1262 cpl_image * corr_image = NULL;
1263 cpl_image * reorganised= NULL;
1264 cpl_image * image_ri_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1265 cpl_image * image_in_inv = cpl_image_new(nx, ny,
1266 CPL_TYPE_FLOAT_COMPLEX);
1269 for (i = 1; i <= nx; i++)
1271 for (j = 1; j <= ny; j++)
1274 double complex value1, value2, value;
1275 value1 = cpl_image_get_complex(image_ri1, i, j, &rej);
1276 value2 = cpl_image_get_complex(image_ri2, i, j, &rej);;
1277 value = conj(value1) * value2;
1278 cpl_image_set_complex(image_in_inv, i, j, value);
1281 cpl_image_delete(image_ri1);
1283 cpl_image_delete(image_ri2);
1286 err = cpl_error_get_code();
1287 if (err == CPL_ERROR_NONE)
1291 cpl_fft_image(image_ri_inv, image_in_inv,CPL_FFT_BACKWARD);
1292 cpl_image_delete(image_in_inv);
1295 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1296 for (i = 1; i <= nx; i++)
1298 for (j = 1; j <= ny; j++)
1302 value = cpl_image_get(image_ri_inv, i, j, &rej);
1303 cpl_image_set(corr_image, i, j, value);
1306 cpl_image_delete(image_ri_inv);
1307 err = cpl_error_get_code();
1308 if (err == CPL_ERROR_NONE)
1312 cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
1313 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1315 cpl_image_copy(reorganised, image, 1, 1);
1316 cpl_image_delete(image);
1317 image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
1318 cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
1319 cpl_image_delete(image);
1321 cpl_image_delete(corr_image);
1323 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1324 image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
1325 cpl_image_copy(corr_image, image, 1, 1);
1326 cpl_image_delete(image);
1328 image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
1329 cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
1330 cpl_image_delete(image);
1332 corr_image_window = cpl_image_extract(corr_image,
1335 nx / 2 + 1 + m, ny / 2 + 1 + n);
1340 cpl_image_delete(reorganised);
1341 cpl_image_delete(corr_image);
1343 if(cpl_image_divide_scalar(corr_image_window,
1344 cpl_image_get_max(corr_image_window))) {
1345 cpl_image_delete(corr_image_window);
1349 cpl_image_delete (image_ri1);
1350 cpl_image_delete (image_ri2);
1351 cpl_image_delete (image1_padded);
1352 cpl_image_delete (image2_padded);
1353 return corr_image_window;
1376detmon_autocorrelate(
const cpl_image * input2,
const int m,
1379 cpl_image *im_re = NULL;
1380 cpl_image *im_im = NULL;
1382 cpl_image *ifft_re = NULL;
1383 cpl_image *ifft_im = NULL;
1384 cpl_image *autocorr = NULL;
1385 cpl_image *autocorr_norm_double = NULL;
1386 cpl_image *autocorr_norm = NULL;
1387 cpl_image *reorganised = NULL;
1388 cpl_image *image = NULL;
1390 cpl_error_code error;
1393 cpl_ensure(input2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1395 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1396 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1398 nx = cpl_image_get_size_x(input2) + 2 * m;
1399 ny = cpl_image_get_size_y(input2) + 2 * n;
1402 while(nx > p || ny > p) {
1406 input = cpl_image_cast(input2, CPL_TYPE_DOUBLE);
1408 im_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1409 error = cpl_image_copy(im_re, input, 1, 1);
1410 cpl_image_delete(input);
1412 cpl_ensure(!error, error, NULL);
1414 im_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1416 error = cpl_image_fft(im_re, im_im, CPL_FFT_DEFAULT);
1417 cpl_ensure(!error, error, NULL);
1419 ifft_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1420 error = cpl_image_power(im_re, 2);
1421 cpl_ensure(!error, error, NULL);
1423 error = cpl_image_add(ifft_re, im_re);
1424 cpl_ensure(!error, error, NULL);
1426 cpl_image_delete(im_re);
1428 error = cpl_image_power(im_im, 2);
1429 cpl_ensure(!error, error, NULL);
1431 error = cpl_image_add(ifft_re, im_im);
1432 cpl_ensure(!error, error, NULL);
1434 cpl_image_delete(im_im);
1436 ifft_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1438 error = cpl_image_fft(ifft_re, ifft_im, CPL_FFT_INVERSE);
1439 cpl_ensure(!error, error, NULL);
1441 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1443 error = cpl_image_power(ifft_re, 2);
1444 cpl_ensure(!error, error, NULL);
1446 error = cpl_image_add(autocorr, ifft_re);
1447 cpl_ensure(!error, error, NULL);
1449 cpl_image_delete(ifft_re);
1451 error = cpl_image_power(ifft_im, 2);
1452 cpl_ensure(!error, error, NULL);
1454 error = cpl_image_add(autocorr, ifft_im);
1455 cpl_ensure(!error, error, NULL);
1457 cpl_image_delete(ifft_im);
1460 reorganised = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1462 image = cpl_image_extract(autocorr, p / 2 + 1, 1, p, p);
1463 cpl_image_copy(reorganised, image, 1, 1);
1464 cpl_image_delete(image);
1466 image = cpl_image_extract(autocorr, 1, 1, p / 2, p);
1467 cpl_image_copy(reorganised, image, p / 2 + 1, 1);
1468 cpl_image_delete(image);
1470 cpl_image_delete(autocorr);
1472 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1474 image = cpl_image_extract(reorganised, 1, p / 2 + 1, p, p);
1475 cpl_image_copy(autocorr, image, 1, 1);
1476 cpl_image_delete(image);
1478 image = cpl_image_extract(reorganised, 1, 1, p, p / 2);
1479 cpl_image_copy(autocorr, image, 1, p / 2 + 1);
1480 cpl_image_delete(image);
1482 cpl_image_delete(reorganised);
1484 autocorr_norm_double =
1485 cpl_image_extract(autocorr, p / 2 + 1 - m, p / 2 + 1 - n,
1486 p / 2 + 1 + m, p / 2 + 1 + n);
1488 cpl_image_delete(autocorr);
1490 if(cpl_image_divide_scalar(autocorr_norm_double,
1491 cpl_image_get_max(autocorr_norm_double))) {
1492 cpl_image_delete(autocorr_norm_double);
1493 cpl_ensure(0, cpl_error_get_code(), NULL);
1497 autocorr_norm = cpl_image_cast(autocorr_norm_double, CPL_TYPE_FLOAT);
1498 cpl_image_delete(autocorr_norm_double);
1500 return autocorr_norm;
1516detmon_lg_fill_parlist_nir_default(cpl_parameterlist * parlist,
1517 const char *recipe_name,
1518 const char *pipeline_name)
1520 const cpl_error_code error =
1521 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1567 cpl_ensure_code(!error, error);
1569 return cpl_error_get_code();
1585detmon_lg_fill_parlist_opt_default(cpl_parameterlist * parlist,
1586 const char *recipe_name,
1587 const char *pipeline_name)
1589 const cpl_error_code error =
1590 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1635 cpl_ensure_code(!error, error);
1637 return cpl_error_get_code();
1640static cpl_error_code
1641detmon_lg_fill_parlist_default_mr(cpl_parameterlist * parlist,
1642 const char *recipe_name,
1643 const char *pipeline_name)
1645 char * group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1646 char * par_name = cpl_sprintf(
"%s.%s", group_name,
"regions-file");
1647 cpl_parameter * p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1648 "File containing regions, "
1649 "four comma separated points "
1652 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions-file");
1653 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1654 cpl_parameterlist_append(parlist, p);
1656 cpl_free(group_name);
1658 group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1659 par_name = cpl_sprintf(
"%s.%s", group_name,
"regions");
1660 p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1661 "Colon separated list of regions, four "
1662 "points each, comma separated: "
1663 "llx,lly,urx,ury:llx,...",
1665 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions");
1666 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1667 cpl_parameterlist_append(parlist, p);
1669 cpl_free(group_name);
1671 return cpl_error_get_code();
1675detmon_lg_fill_parlist_opt_default_mr(cpl_parameterlist * parlist,
1676 const char *recipe_name,
1677 const char *pipeline_name)
1679 detmon_lg_fill_parlist_opt_default(parlist, recipe_name, pipeline_name);
1680 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1681 return cpl_error_get_code();
1685detmon_lg_fill_parlist_nir_default_mr(cpl_parameterlist * parlist,
1686 const char *recipe_name,
1687 const char *pipeline_name)
1689 detmon_lg_fill_parlist_nir_default(parlist, recipe_name, pipeline_name);
1690 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1692 return cpl_error_get_code();
1752detmon_lg_fill_parlist(cpl_parameterlist * parlist,
1753 const char *recipe_name,
const char *pipeline_name,
1763 const char *intermediate,
1764 const char *autocorr,
1765 const char *collapse,
1766 const char *rescale,
1767 const char *pix2pix,
1774 const char * pafname,
1791 int llx5,
int lly5,
int urx5,
int ury5,
int exts,
1792 cpl_boolean opt_nir)
1794 const cpl_error_code error =
1795 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 26,
1797 "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
1798 "CPL_TYPE_STRING", method,
1801 "Polynomial order for the fit (Linearity)",
1802 "CPL_TYPE_INT", order,
1804 "Kappa value for the kappa-sigma clipping (Gain)",
1805 "CPL_TYPE_DOUBLE", kappa,
1807 "Number of iterations to compute rms (Gain)",
1808 "CPL_TYPE_INT", niter,
1810 "x coordinate of the lower-left "
1811 "point of the region of interest. If not modified, default value will be 1.",
1812 "CPL_TYPE_INT", llx,
1814 "y coordinate of the lower-left "
1815 "point of the region of interest. If not modified, default value will be 1.",
1816 "CPL_TYPE_INT", lly,
1818 "x coordinate of the upper-right "
1819 "point of the region of interest. If not modified, default value will be X dimension of the input image.",
1820 "CPL_TYPE_INT", urx,
1822 "y coordinate of the upper-right "
1823 "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
1824 "CPL_TYPE_INT", ury,
1826 "User reference level",
1827 "CPL_TYPE_INT", ref_level,
1829 "De-/Activate intermediate products",
1830 "CPL_TYPE_BOOL", intermediate,
1833 "De-/Activate the autocorr option",
1834 "CPL_TYPE_BOOL", autocorr,
1837 "De-/Activate the collapse option",
1838 "CPL_TYPE_BOOL", collapse,
1840 "De-/Activate the image rescale option",
1841 "CPL_TYPE_BOOL", rescale,
1843 "De-/Activate the computation with pixel to pixel accuracy",
1844 "CPL_TYPE_BOOL", pix2pix,
1846 "De-/Activate the binary bpm option",
1847 "CPL_TYPE_BOOL", bpmbin,
1849 "Maximum x-shift for the autocorr",
1852 "Upper limit of Median flux to be filtered",
1853 "CPL_TYPE_INT", filter,
1855 "Maximum y-shift for the autocorr",
1858 "Tolerance for pair discrimination",
1859 "CPL_TYPE_DOUBLE", tolerance,
1862 "Generate PAF file",
1863 "CPL_TYPE_BOOL", pafgen,
1865 "Specific name for PAF file",
1866 "CPL_TYPE_STRING", pafname,
1870 "Activate the multi-exts option. Choose -1 to process all extensions. Choose an extension number"
1871 " to process the appropriate extension.",
1872 "CPL_TYPE_INT", exts,
1875 "Method for computing Fixed Pattern Noise (SMOOTH or HISTOGRAM)",
1876 "CPL_TYPE_STRING",
"HISTOGRAM",
1879 "template size in pixels for smoothing during FPN computation (only for SMOOTH method)",
1883 "all frames with mean saturation above the limit would not be used in linearity calculation",
1884 "CPL_TYPE_DOUBLE", 65535.0,
1887 "all frames with mean flux above the threshold would not be used in gain calculation",
1888 "CPL_TYPE_DOUBLE", 65535.0
1891 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 1,
1892 "coeffs_cube_split",
1893 "if TRUE, the recipe writes as many "
1894 "COEFFS_CUBE_Pi (i=0..order) as the value of "
1895 "the order parameter in a separate file",
1896 "CPL_TYPE_BOOL",
"CPL_FALSE");
1898 if(opt_nir == FALSE) {
1899 const cpl_error_code erroropt =
1900 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
1902 "x coord of the lower-left point of the first "
1903 "field used for contamination measurement. If not modified, default value will be 1.",
1904 "CPL_TYPE_INT", llx1,
1906 "y coord of the lower-left point of the first "
1907 "field used for contamination measurement. If not modified, default value will be 1.",
1908 "CPL_TYPE_INT", lly1,
1910 "x coord of the upper-right point of the first "
1911 "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
1912 "CPL_TYPE_INT", urx1,
1914 "y coord of the upper-right point of the first "
1915 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1916 "CPL_TYPE_INT", ury1,
1918 "x coord of the lower-left point of the second "
1919 "field used for contamination measurement. If not modified, default value will be 1.",
1920 "CPL_TYPE_INT", llx2,
1922 "y coord of the lower-left point of the second "
1923 "field used for contamination measurement. If not modified, default value will be 1.",
1924 "CPL_TYPE_INT", lly2,
1926 "x coord of the upper-right point of the second "
1927 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1928 "CPL_TYPE_INT", urx2,
1930 "y coord of the upper-right point of the second "
1931 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1932 "CPL_TYPE_INT", ury2,
1934 "x coord of the lower-left point of the third "
1935 "field used for contamination measurement. If not modified, default value will be 1.",
1936 "CPL_TYPE_INT", llx3,
1938 "y coord of the lower-left point of the third "
1939 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1940 "CPL_TYPE_INT", lly3,
1942 "x coord of the upper-right point of the third "
1943 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1944 "CPL_TYPE_INT", urx3,
1946 "y coord of the upper-right point of the third "
1947 "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
1948 "CPL_TYPE_INT", ury3,
1950 "x coord of the lower-left point of the fourth "
1951 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1952 "CPL_TYPE_INT", llx4,
1954 "y coord of the lower-left point of the fourth "
1955 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1956 "CPL_TYPE_INT", lly4,
1958 "x coord of the upper-right point of the fourth "
1959 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1960 "CPL_TYPE_INT", urx4,
1962 "y coord of the upper-right point of the fourth "
1963 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1964 "CPL_TYPE_INT", ury4,
1966 "x coord of the lower-left point of the fifth "
1967 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1968 "CPL_TYPE_INT", llx5,
1970 "y coord of the lower-left point of the fifth "
1971 "field used for contamination measurement. If not modified, default value will be 1.",
1972 "CPL_TYPE_INT", lly5,
1974 "x coord of the upper-right point of the fifth "
1975 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1976 "CPL_TYPE_INT", urx5,
1979 "y coord of the upper-right point of the fifth "
1980 "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
1981 "CPL_TYPE_INT", ury5);
1984 cpl_ensure_code(!erroropt, erroropt);
1987 cpl_ensure_code(!error, error);
1989 return cpl_error_get_code();
2002static cpl_error_code
2003detmon_lg_retrieve_parlist(
const char * pipeline_name,
2004 const char * recipe_name,
2005 const cpl_parameterlist * parlist,
2006 cpl_boolean opt_nir)
2010 const cpl_parameter * par;
2013 par_name = cpl_sprintf(
"%s.%s.method", pipeline_name, recipe_name);
2014 assert(par_name != NULL);
2015 par = cpl_parameterlist_find_const(parlist, par_name);
2016 detmon_lg_config.method = cpl_parameter_get_string(par);
2020 detmon_lg_config.order =
2021 detmon_retrieve_par_int(
"order", pipeline_name, recipe_name,
2025 detmon_lg_config.kappa =
2026 detmon_retrieve_par_double(
"kappa", pipeline_name, recipe_name,
2030 detmon_lg_config.niter =
2031 detmon_retrieve_par_int(
"niter", pipeline_name, recipe_name,
2035 detmon_lg_config.llx =
2036 detmon_retrieve_par_int(
"llx", pipeline_name, recipe_name,
2040 detmon_lg_config.lly =
2041 detmon_retrieve_par_int(
"lly", pipeline_name, recipe_name,
2045 detmon_lg_config.urx =
2046 detmon_retrieve_par_int(
"urx", pipeline_name, recipe_name,
2050 detmon_lg_config.ury =
2051 detmon_retrieve_par_int(
"ury", pipeline_name, recipe_name,
2055 detmon_lg_config.ref_level =
2056 detmon_retrieve_par_int(
"ref_level", pipeline_name, recipe_name,
2061 cpl_sprintf(
"%s.%s.intermediate", pipeline_name, recipe_name);
2062 assert(par_name != NULL);
2063 par = cpl_parameterlist_find_const(parlist, par_name);
2064 detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
2068 par_name = cpl_sprintf(
"%s.%s.autocorr", pipeline_name, recipe_name);
2069 assert(par_name != NULL);
2070 par = cpl_parameterlist_find_const(parlist, par_name);
2071 detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
2075 par_name = cpl_sprintf(
"%s.%s.coeffs_cube_split", pipeline_name, recipe_name);
2076 assert(par_name != NULL);
2077 par = cpl_parameterlist_find_const(parlist, par_name);
2078 detmon_lg_config.split_coeffs = cpl_parameter_get_bool(par);
2082 par_name = cpl_sprintf(
"%s.%s.collapse", pipeline_name, recipe_name);
2083 assert(par_name != NULL);
2084 par = cpl_parameterlist_find_const(parlist, par_name);
2085 detmon_lg_config.collapse = cpl_parameter_get_bool(par);
2089 par_name = cpl_sprintf(
"%s.%s.rescale", pipeline_name, recipe_name);
2090 assert(par_name != NULL);
2091 par = cpl_parameterlist_find_const(parlist, par_name);
2092 detmon_lg_config.rescale = cpl_parameter_get_bool(par);
2096 par_name = cpl_sprintf(
"%s.%s.pix2pix", pipeline_name, recipe_name);
2097 assert(par_name != NULL);
2098 par = cpl_parameterlist_find_const(parlist, par_name);
2099 detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
2103 par_name = cpl_sprintf(
"%s.%s.bpmbin", pipeline_name, recipe_name);
2104 assert(par_name != NULL);
2105 par = cpl_parameterlist_find_const(parlist, par_name);
2106 detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
2110 detmon_lg_config.filter =
2111 detmon_retrieve_par_int(
"filter", pipeline_name,
2112 recipe_name, parlist);
2115 detmon_lg_config.m =
2116 detmon_retrieve_par_int(
"m", pipeline_name, recipe_name, parlist);
2119 detmon_lg_config.n =
2120 detmon_retrieve_par_int(
"n", pipeline_name, recipe_name, parlist);
2123 par_name = cpl_sprintf(
"%s.%s.tolerance", pipeline_name, recipe_name);
2124 assert(par_name != NULL);
2125 par = cpl_parameterlist_find_const(parlist, par_name);
2126 detmon_lg_config.tolerance = cpl_parameter_get_double(par);
2131 par_name = cpl_sprintf(
"%s.%s.pafgen", pipeline_name, recipe_name);
2132 assert(par_name != NULL);
2133 par = cpl_parameterlist_find_const(parlist, par_name);
2134 detmon_lg_config.pafgen = cpl_parameter_get_bool(par);
2138 par_name = cpl_sprintf(
"%s.%s.pafname", pipeline_name, recipe_name);
2139 assert(par_name != NULL);
2140 par = cpl_parameterlist_find_const(parlist, par_name);
2141 detmon_lg_config.pafname = cpl_parameter_get_string(par);
2144 if(opt_nir == OPT) {
2146 detmon_lg_config.llx1 =
2147 detmon_retrieve_par_int(
"llx1", pipeline_name, recipe_name,
2151 detmon_lg_config.lly1 =
2152 detmon_retrieve_par_int(
"lly1", pipeline_name, recipe_name,
2156 detmon_lg_config.urx1 =
2157 detmon_retrieve_par_int(
"urx1", pipeline_name, recipe_name,
2161 detmon_lg_config.ury1 =
2162 detmon_retrieve_par_int(
"ury1", pipeline_name, recipe_name,
2166 detmon_lg_config.llx2 =
2167 detmon_retrieve_par_int(
"llx2", pipeline_name, recipe_name,
2171 detmon_lg_config.lly2 =
2172 detmon_retrieve_par_int(
"lly2", pipeline_name, recipe_name,
2176 detmon_lg_config.urx2 =
2177 detmon_retrieve_par_int(
"urx2", pipeline_name, recipe_name,
2181 detmon_lg_config.ury2 =
2182 detmon_retrieve_par_int(
"ury2", pipeline_name, recipe_name,
2186 detmon_lg_config.llx3 =
2187 detmon_retrieve_par_int(
"llx3", pipeline_name, recipe_name,
2191 detmon_lg_config.lly3 =
2192 detmon_retrieve_par_int(
"lly3", pipeline_name, recipe_name,
2196 detmon_lg_config.urx3 =
2197 detmon_retrieve_par_int(
"urx3", pipeline_name, recipe_name,
2201 detmon_lg_config.ury3 =
2202 detmon_retrieve_par_int(
"ury3", pipeline_name, recipe_name,
2206 detmon_lg_config.llx4 =
2207 detmon_retrieve_par_int(
"llx4", pipeline_name, recipe_name,
2211 detmon_lg_config.lly4 =
2212 detmon_retrieve_par_int(
"lly4", pipeline_name, recipe_name,
2216 detmon_lg_config.urx4 =
2217 detmon_retrieve_par_int(
"urx4", pipeline_name, recipe_name,
2221 detmon_lg_config.ury4 =
2222 detmon_retrieve_par_int(
"ury4", pipeline_name, recipe_name,
2226 detmon_lg_config.llx5 =
2227 detmon_retrieve_par_int(
"llx5", pipeline_name, recipe_name,
2231 detmon_lg_config.lly5 =
2232 detmon_retrieve_par_int(
"lly5", pipeline_name, recipe_name,
2236 detmon_lg_config.urx5 =
2237 detmon_retrieve_par_int(
"urx5", pipeline_name, recipe_name,
2241 detmon_lg_config.ury5 =
2242 detmon_retrieve_par_int(
"ury5", pipeline_name, recipe_name,
2247 detmon_lg_config.exts =
2248 detmon_retrieve_par_int(
"exts", pipeline_name, recipe_name,
2252 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2254 cpl_sprintf(
"%s.%s.fpn_method", pipeline_name, recipe_name);
2255 assert(par_name != NULL);
2256 par = cpl_parameterlist_find_const(parlist, par_name);
2259 const char * str_method = cpl_parameter_get_string(par);
2260 if (strcmp(str_method,
"SMOOTH") == 0)
2262 detmon_lg_config.fpn_method = FPN_SMOOTH;
2264 else if (strcmp(str_method,
"HISTOGRAM") == 0)
2266 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2272 detmon_lg_config.fpn_smooth =
2273 detmon_retrieve_par_int(
"fpn_smooth", pipeline_name, recipe_name,
2277 detmon_lg_config.saturation_limit = 65535;
2279 cpl_sprintf(
"%s.%s.saturation_limit", pipeline_name, recipe_name);
2280 assert(par_name != NULL);
2281 par = cpl_parameterlist_find_const(parlist, par_name);
2284 detmon_lg_config.saturation_limit = cpl_parameter_get_double(par);
2291 detmon_lg_config.gain_threshold = 0;
2293 cpl_sprintf(
"%s.%s.gain_threshold", pipeline_name, recipe_name);
2294 assert(par_name != NULL);
2295 par = cpl_parameterlist_find_const(parlist, par_name);
2298 detmon_lg_config.gain_threshold = cpl_parameter_get_double(par);
2303 if(cpl_error_get_code())
2305 cpl_msg_error(cpl_func,
"Failed to retrieve the input parameters");
2306 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
2310 return cpl_error_get_code();
2320static cpl_error_code
2321detmon_lg_check_defaults(
const cpl_image * reference)
2323 const int nx = cpl_image_get_size_x(reference);
2324 const int ny = cpl_image_get_size_y(reference);
2326 detmon_lg_config.nx = nx;
2327 detmon_lg_config.ny = ny;
2329 detmon_lg_config.wholechip = CPL_FALSE;
2331 if(detmon_lg_config.llx == -1)
2332 detmon_lg_config.llx = 1;
2333 if(detmon_lg_config.lly == -1)
2334 detmon_lg_config.lly = 1;
2335 if(detmon_lg_config.urx == -1)
2336 detmon_lg_config.urx = nx;
2337 if(detmon_lg_config.ury == -1)
2338 detmon_lg_config.ury = ny;
2340 if (detmon_lg_config.llx == 1 &&
2341 detmon_lg_config.lly == 1 &&
2342 detmon_lg_config.urx == nx &&
2343 detmon_lg_config.ury == ny)
2344 detmon_lg_config.wholechip = CPL_TRUE;
2346 if(detmon_lg_config.llx1 == -1)
2347 detmon_lg_config.llx1 = 1;
2348 if(detmon_lg_config.lly1 == -1)
2349 detmon_lg_config.lly1 = 1;
2350 if(detmon_lg_config.urx1 == -1)
2351 detmon_lg_config.urx1 = nx;
2352 if(detmon_lg_config.ury1 == -1)
2353 detmon_lg_config.ury1 = ny;
2355 if(detmon_lg_config.llx2 == -1)
2356 detmon_lg_config.llx2 = 1;
2357 if(detmon_lg_config.lly2 == -1)
2358 detmon_lg_config.lly2 = 1;
2359 if(detmon_lg_config.urx2 == -1)
2360 detmon_lg_config.urx2 = nx / 2;
2361 if(detmon_lg_config.ury2 == -1)
2362 detmon_lg_config.ury2 = ny / 2;
2364 if(detmon_lg_config.llx3 == -1)
2365 detmon_lg_config.llx3 = 1;
2366 if(detmon_lg_config.lly3 == -1)
2367 detmon_lg_config.lly3 = ny / 2;
2368 if(detmon_lg_config.urx3 == -1)
2369 detmon_lg_config.urx3 = nx / 2;
2370 if(detmon_lg_config.ury3 == -1)
2371 detmon_lg_config.ury3 = ny;
2373 if(detmon_lg_config.llx4 == -1)
2374 detmon_lg_config.llx4 = nx / 2;
2375 if(detmon_lg_config.lly4 == -1)
2376 detmon_lg_config.lly4 = ny / 2;
2377 if(detmon_lg_config.urx4 == -1)
2378 detmon_lg_config.urx4 = nx;
2379 if(detmon_lg_config.ury4 == -1)
2380 detmon_lg_config.ury4 = ny;
2382 if(detmon_lg_config.llx5 == -1)
2383 detmon_lg_config.llx5 = nx / 2;
2384 if(detmon_lg_config.lly5 == -1)
2385 detmon_lg_config.lly5 = 1;
2386 if(detmon_lg_config.urx5 == -1)
2387 detmon_lg_config.urx5 = nx;
2388 if(detmon_lg_config.ury5 == -1)
2389 detmon_lg_config.ury5 = ny / 2;
2391 if(detmon_lg_config.intermediate == TRUE) {
2392 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.");
2393 detmon_lg_config.autocorr = TRUE;
2397 detmon_lg_config.lamp_stability = 0.0;
2399 detmon_lg_config.lamp_ok = FALSE;
2401 detmon_lg_config.cr = 0.0;
2403 return cpl_error_get_code();
2418static cpl_error_code
2419detmon_lg_split_onoff(
const cpl_frameset * cur_fset,
2420 cpl_frameset * cur_fset_on,
2421 cpl_frameset * cur_fset_off,
2423 const char *tag_off)
2428 cpl_frame * cur_frame_dup = NULL;
2431 const cpl_frame * first;
2432 const cpl_frame * second;
2433 const char * first_tag;
2434 const char * second_tag;
2435 skip_if((first = cpl_frameset_get_position_const(cur_fset, 0)) == NULL);
2436 skip_if((second = cpl_frameset_get_position_const(cur_fset, 1)) == NULL);
2438 skip_if((first_tag = cpl_frame_get_tag(first)) == NULL);
2439 skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
2440 if (opt_nir == OPT &&
2441 ((!strcmp(first_tag, tag_on ) && !strcmp(second_tag, tag_off)) ||
2442 (!strcmp(first_tag, tag_off) && !strcmp(second_tag, tag_on )))) {
2443 detmon_lg_config.lamp_ok = TRUE;
2447 nframes = cpl_frameset_get_size(cur_fset);
2448 for(i = detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
2449 const cpl_frame * cur_frame =
2450 cpl_frameset_get_position_const(cur_fset, i);
2454 cur_frame_dup = cpl_frame_duplicate(cur_frame);
2455 tag = (
char *) cpl_frame_get_tag(cur_frame_dup);
2458 if(!strcmp(tag, tag_on)) {
2459 skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
2460 }
else if(!strcmp(tag, tag_off)) {
2461 skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
2463 cpl_frame_delete(cur_frame_dup);
2464 cur_frame_dup = NULL;
2467 cur_frame_dup = NULL;
2471 cpl_frame_delete(cur_frame_dup);
2473 return cpl_error_get_code();
2500static cpl_error_code
2501detmon_lg_reduce(
const cpl_frameset * set_on,
2502 const cpl_frameset * set_off,
2503 int* index_on,
int* index_off,
2504 double* exptime_on,
double* exptime_off,
2505 int *next_index_on,
int* next_index_off,
2506 cpl_imagelist ** coeffs_ptr,
2507 cpl_table * gain_table,
2508 cpl_table * linear_table,
2509 cpl_image ** bpm_ptr,
2510 cpl_imagelist * autocorr_images,
2511 cpl_imagelist * diff_flats,
2512 cpl_propertylist * gaint_qclist,
2513 cpl_propertylist * lint_qclist,
2514 cpl_propertylist * linc_qclist,
2515 cpl_propertylist * bpm_qclist,
2516 int (* load_fset) (
const cpl_frameset *,
2519 const cpl_boolean opt_nir,
2522 cpl_errorstate prestate = cpl_errorstate_get();
2523 const double D_INVALID_VALUE = -999;
2525 cpl_imagelist * linearity_inputs = NULL;
2526 cpl_imagelist * opt_offs = NULL;
2528 cpl_propertylist * reflist = NULL;
2530 int rows_linear_affected = 1;
2531 int rows_gain_affected = 1;
2532 int last_linear_best = 0;
2534 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2535 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2537 nsets = cpl_frameset_get_size(set_on) / 2;
2539 detmon_lg_config.load_fset = load_fset;
2540 if(detmon_lg_config.collapse) {
2547 const cpl_frame *first = cpl_frameset_get_position_const(set_off, 0);
2548 cpl_frame *dup_first = cpl_frame_duplicate(first);
2550 const cpl_frame *second = cpl_frameset_get_position_const(set_off, 1);
2551 cpl_frame *dup_second = cpl_frame_duplicate(second);
2553 cpl_frameset *raw_offs = cpl_frameset_new();
2555 skip_if(cpl_frameset_insert(raw_offs, dup_first));
2556 skip_if(cpl_frameset_insert(raw_offs, dup_second));
2558 opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
2561 cpl_frameset_delete(raw_offs);
2562 if (opt_offs == NULL) {
2563 cpl_errorstate_set(prestate);
2564 return CPL_ERROR_CONTINUE;
2568 skip_if(detmon_lg_reduce_init(gain_table,
2580 if(detmon_lg_lamp_stab(set_on, set_off,
2581 opt_nir, whichext)) {
2582 cpl_errorstate_set(prestate);
2585 if(!detmon_lg_config.collapse)
2589 skip_if(cpl_table_unselect_all(linear_table));
2590 skip_if(cpl_table_unselect_all(gain_table));
2594 for(i = 0; i < nsets ; i++)
2596 skip_if(detmon_lg_reduce_dit(set_on,
2597 index_on, exptime_on,
2601 index_off, exptime_off,
2602 next_index_on, next_index_off,
2604 gain_table, linearity_inputs,
2605 lint_qclist, opt_nir,
2606 autocorr_images, diff_flats,
2608 &rows_linear_affected,&rows_gain_affected));
2612 if (rows_linear_affected == 0)
2614 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2615 "into linear calculation, check the messages above");
2616 cpl_table_select_row(linear_table, i);
2620 last_linear_best = i;
2623 if (rows_gain_affected == 0)
2625 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2626 "into gain calculation, check the messages above");
2627 cpl_table_select_row(gain_table, i);
2634 skip_if(detmon_add_adl_column(linear_table, opt_nir));
2640 skip_if(cpl_table_erase_selected(gain_table));
2641 skip_if(cpl_table_erase_selected(linear_table));
2644 reflist = cpl_propertylist_new();
2645 skip_if(cpl_propertylist_append_bool(reflist,
"ADU", FALSE));
2646 skip_if(cpl_table_sort(gain_table, reflist));
2652 skip_if(detmon_lg_reduce_all(linear_table,
2653 gaint_qclist, lint_qclist, linc_qclist,
2654 bpm_qclist, coeffs_ptr, bpm_ptr,
2656 gain_table, whichext, opt_nir));
2659 double gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
2662 cpl_error_code cplerr = cpl_error_get_code();
2663 if (cplerr != CPL_ERROR_NONE || (gain == 0.0))
2665 cpl_msg_warning(cpl_func,
"Cannot read gain from QC parameters - "
2666 "FPN will not be computed");
2671 detmon_fpn_compute(set_on, index_on, last_linear_best, lint_qclist,
2672 detmon_lg_config.llx,
2673 detmon_lg_config.lly,
2674 detmon_lg_config.urx,
2675 detmon_lg_config.ury,
2678 detmon_lg_config.fpn_method,
2679 detmon_lg_config.fpn_smooth);
2684 detmon_table_fill_invalid(gain_table, D_INVALID_VALUE);
2686 cpl_imagelist_delete(linearity_inputs);
2687 cpl_imagelist_delete(opt_offs);
2688 cpl_propertylist_delete(reflist);
2690 return cpl_error_get_code();
2693static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code)
2695 int ncols = cpl_table_get_ncol(ptable);
2696 cpl_array* pnames = cpl_table_get_column_names(ptable);
2697 int nrows = cpl_table_get_nrow(ptable);
2699 for (i=0; i < ncols; i++)
2702 for (j = 0; j< nrows; j++)
2704 const char* colname = cpl_array_get_data_string_const(pnames)[i];
2706 cpl_type type = cpl_table_get_column_type(ptable, colname);
2707 cpl_table_get(ptable, colname, j, &isnull);
2710 if (type == CPL_TYPE_DOUBLE)
2712 cpl_table_set(ptable,colname,j, code);
2714 else if (type == CPL_TYPE_FLOAT)
2716 cpl_table_set_float(ptable,colname,j, (
float)code);
2721 cpl_array_delete(pnames);
2722 return cpl_error_get_code();
2725static cpl_error_code
2726detmon_fpn_compute(
const cpl_frameset *set_on,
2728 int last_linear_best,
2729 cpl_propertylist *lint_qclist,
2736 FPN_METHOD fpn_method,
2740 const cpl_image* im1 = 0;
2742 cpl_imagelist* ons = 0;
2743 cpl_frameset * pair_on = 0;
2744 int nsets_extracted = cpl_frameset_get_size(set_on);
2745 cpl_size * selection = NULL;
2754 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
2755 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
2757 selection[index_on[last_linear_best*2 + 0] ] = 1;
2758 selection[index_on[last_linear_best*2 + 1] ] = 1;
2759 pair_on = cpl_frameset_extract(set_on, selection, 1);
2760 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2762 skip_if(ons == NULL);
2763 skip_if((im1 = cpl_imagelist_get_const(ons, 0)) == NULL);
2765 fpn = irplib_fpn_lg(im1, range, gain, fpn_method, smooth_size, &mse);
2766 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_FPN,
2768 skip_if(cpl_propertylist_append_double(lint_qclist,
"ESO QC GAIN ERR",
2772 cpl_frameset_delete(pair_on);
2773 cpl_imagelist_delete(ons);
2774 cpl_free(selection);
2775 return cpl_error_get_code();
2787static cpl_error_code
2788detmon_lg_lamp_stab(
const cpl_frameset * lamps,
2789 const cpl_frameset * darks,
2790 cpl_boolean opt_nir,
2803 cpl_vector * selection = NULL;
2804 cpl_propertylist * plist;
2805 double dit_lamp, dit_dark;
2807 cpl_imagelist * lamps_data = NULL;
2808 cpl_imagelist * darks_data = NULL;
2809 double * stab_levels = NULL;
2811 double * ditvals = NULL;
2815 cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
2816 CPL_ERROR_ILLEGAL_INPUT);
2822 cpl_msg_info(__func__,
"Checking DIT consistency");
2823 selection = cpl_vector_new(nb_lamps);
2824 ditvals = cpl_malloc(nb_lamps *
sizeof(
double));
2826 for (i = 0; i < nb_lamps; i++) {
2827 const cpl_frame * c_lamp;
2828 const cpl_frame * c_dark;
2830 skip_if (cpl_error_get_code());
2833 c_lamp = cpl_frameset_get_position_const(lamps, i);
2834 plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
2836 dit_lamp = (double)detmon_pfits_get_dit(plist);
2838 dit_lamp = (double)detmon_pfits_get_dit_opt(plist);
2839 cpl_propertylist_delete(plist);
2840 skip_if (cpl_error_get_code());
2843 c_dark = cpl_frameset_get_position_const(darks, i);
2844 plist = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
2846 dit_dark = (double)detmon_pfits_get_dit(plist);
2848 dit_dark = (double)detmon_pfits_get_dit_opt(plist);
2849 cpl_propertylist_delete(plist);
2850 skip_if (cpl_error_get_code());
2853 if (fabs(dit_dark-dit_lamp) > 1e-3) {
2854 cpl_msg_error(__func__,
"DIT not consistent between LAMP and DARK, skip lamp stability computation");
2859 ditvals[i] = dit_lamp;
2862 cpl_vector_set(selection, i, -1.0);
2870 if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
2871 cpl_vector_set(selection, i, -1.0);
2875 cpl_vector_set(selection, i, 1.0);
2882 cpl_msg_info(__func__,
"Not enough frames for stability check");
2886 cpl_msg_info(__func__,
"Compute the differences lamp - dark");
2889 lamps_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2891 detmon_lg_config.llx,
2892 detmon_lg_config.lly,
2893 detmon_lg_config.urx,
2894 detmon_lg_config.ury,
2897 darks_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2899 detmon_lg_config.llx,
2900 detmon_lg_config.lly,
2901 detmon_lg_config.urx,
2902 detmon_lg_config.ury,
2905 nb_darks=cpl_imagelist_get_size(darks_data);
2906 if(nb_darks==nb_lamps) {
2907 skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
2909 cpl_image* master_dark=cpl_imagelist_collapse_median_create(darks_data);
2910 cpl_imagelist_subtract_image(lamps_data,master_dark);
2911 cpl_image_delete(master_dark);
2914 cpl_msg_info(__func__,
"Check the lamp stability");
2915 stab_levels = cpl_malloc(dit_stab *
sizeof(
double));
2917 for (i=0; i<nb_lamps; i++) {
2918 if (cpl_vector_get(selection, i) < 0) {
2920 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
2926 for (i=1; i<dit_stab; i++) {
2927 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
2928 detmon_lg_config.lamp_stability)
2929 detmon_lg_config.lamp_stability =
2930 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
2935 if (detmon_lg_config.lamp_stability > 0.01) {
2936 cpl_msg_warning(__func__,
2937 "Lamp stability level %g difference too high - proceed anyway",detmon_lg_config.lamp_stability);
2944 cpl_vector_delete(selection);
2945 cpl_imagelist_delete(lamps_data);
2946 cpl_imagelist_delete(darks_data);
2947 cpl_free(stab_levels);
2949 return cpl_error_get_code();
2976static cpl_error_code
2977detmon_lg_reduce_dit(
const cpl_frameset * set_on,
2978 int* index_on,
double* exptime_on,
2981 const cpl_frameset * set_off,
2982 int * index_off,
double* exptime_off,
2983 int* next_on,
int* next_off,
2984 cpl_table * linear_table,
2985 cpl_table * gain_table,
2986 cpl_imagelist * linearity_inputs,
2987 cpl_propertylist * qclist,
2988 cpl_boolean opt_nir,
2989 cpl_imagelist * autocorr_images,
2990 cpl_imagelist * diff_flats,
2991 cpl_imagelist * opt_offs,
2993 int* rows_linear_affected,
2994 int* rows_gain_affected)
2996 cpl_frameset * pair_on = NULL;
2997 cpl_frameset * pair_off = NULL;
2998 cpl_imagelist * ons = NULL;
2999 cpl_imagelist * offs = NULL;
3000 cpl_boolean follow = CPL_TRUE;
3001 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
3005 double current_dit = 0;
3007 const char * filename;
3009 cpl_propertylist * plist = NULL;
3010 cpl_propertylist* pDETlist = NULL;
3012 mode = detmon_lg_config.collapse ?
3013 mode | IRPLIB_GAIN_COLLAPSE | IRPLIB_LIN_COLLAPSE:
3014 mode | IRPLIB_GAIN_NO_COLLAPSE | IRPLIB_LIN_NO_COLLAPSE;
3015 mode = detmon_lg_config.pix2pix ?
3016 mode | IRPLIB_LIN_PIX2PIX : mode;
3018 mode | IRPLIB_GAIN_NIR | IRPLIB_LIN_NIR :
3019 mode | IRPLIB_GAIN_OPT | IRPLIB_LIN_OPT ;
3023 skip_if(detmon_pair_extract_next(set_on, index_on, next_on, exptime_on, &pair_on, detmon_lg_config.tolerance));
3024 current_dit = exptime_on[*next_on - 1];
3027 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
3028 skip_if(ons == NULL);
3029 cpl_msg_debug(cpl_func,
" Loaded ON images: %" CPL_SIZE_FORMAT
3030 ", exptime[%f]",cpl_imagelist_get_size(ons), current_dit );
3031 if(cpl_imagelist_get_size(ons) != 2)
3033 cpl_msg_error(cpl_func,
"cannot take ON pair, number of images[%"
3034 CPL_SIZE_FORMAT
"]", cpl_imagelist_get_size(ons));
3037 if(detmon_lg_config.filter > 0)
3040 cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
3041 detmon_lg_config.llx,
3042 detmon_lg_config.lly,
3043 detmon_lg_config.urx,
3044 detmon_lg_config.ury);
3046 cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
3047 detmon_lg_config.llx,
3048 detmon_lg_config.lly,
3049 detmon_lg_config.urx,
3050 detmon_lg_config.ury);
3054 if ( med1 > (
double)detmon_lg_config.filter ||
3055 med2 > (
double)detmon_lg_config.filter)
3058 cpl_table_select_row(gain_table, dit_nb);
3059 cpl_table_select_row(linear_table, dit_nb);
3061 cpl_msg_warning(cpl_func,
"Frames of EXPTIME nb %d "
3062 "will not be taken into account for computation "
3063 "as the median of the on frames computed on the "
3064 "user defined region [%d,%d,%d,%d] are above "
3065 "--filter threshold (%d)",
3067 detmon_lg_config.llx,
3068 detmon_lg_config.lly,
3069 detmon_lg_config.urx,
3070 detmon_lg_config.ury,
3071 detmon_lg_config.filter);
3075 if (follow || detmon_lg_config.filter < 0)
3083 if(!detmon_lg_config.collapse)
3100 if (!strcmp(detmon_lg_config.method,
"MED") ||
3101 cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
3103 skip_if(detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off, detmon_lg_config.tolerance));
3107 skip_if(detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
3110 cpl_msg_debug(cpl_func,
" Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
3111 offs = detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
3113 skip_if(offs == NULL);
3114 skip_if(cpl_error_get_code());
3117 offs = (cpl_imagelist *) opt_offs;
3121 if(detmon_lg_config.rescale)
3123 skip_if(detmon_lg_rescale(ons));
3124 if (!detmon_lg_config.collapse &&
3125 !strcmp(detmon_lg_config.method,
"MED"))
3126 skip_if(detmon_lg_rescale(offs));
3131 cpl_frame_get_filename(cpl_frameset_get_position_const(pair_on, 0));
3132 skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
3136 pDETlist = cpl_propertylist_new();
3137 cpl_propertylist_copy_property_regexp(pDETlist, plist,
"DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
3140 irplib_table_create_column(gain_table, pDETlist);
3141 irplib_table_create_column(linear_table, pDETlist);
3144 if(opt_nir == NIR) {
3145 c_dit = detmon_pfits_get_dit(plist);
3146 c_ndit = irplib_pfits_get_ndit(plist);
3148 c_dit = irplib_pfits_get_exptime(plist);
3160 cpl_msg_info(cpl_func,
"Computing GAIN for EXPTIME value nb %d",
3164 if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
3166 cpl_table_erase_column(gain_table,
"MEAN_OFF1");
3167 cpl_table_erase_column(gain_table,
"MEAN_OFF2");
3168 cpl_table_erase_column(gain_table,
"SIG_OFF_DIF");
3169 cpl_table_erase_column(gain_table,
"GAIN");
3170 cpl_table_erase_column(gain_table,
"GAIN_CORR");
3171 cpl_table_new_column(gain_table,
"MEAN_OFF", CPL_TYPE_DOUBLE);
3175 skip_if(detmon_gain_table_fill_row(gain_table,
3178 diff_flats, ons, offs,
3179 detmon_lg_config.kappa,
3180 detmon_lg_config.niter,
3181 detmon_lg_config.llx,
3182 detmon_lg_config.lly,
3183 detmon_lg_config.urx,
3184 detmon_lg_config.ury,
3187 detmon_lg_config.gain_threshold,
3188 dit_nb, mode, rows_gain_affected));
3191 skip_if(detmon_check_saturation_on_pair(autocorr_images,
3193 detmon_lg_config.kappa,
3194 detmon_lg_config.niter,
3195 detmon_lg_config.llx,
3196 detmon_lg_config.lly,
3197 detmon_lg_config.urx,
3198 detmon_lg_config.ury,
3199 detmon_lg_config.saturation_limit,
3200 dit_nb, mode, rows_linear_affected));
3203 if (*rows_gain_affected)
3206 skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
3208 cpl_msg_info(cpl_func,
"Linearity reduction for nb %d",
3211 if (*rows_linear_affected) {
3212 skip_if(detmon_lin_table_fill_row(linear_table, c_dit,
3213 linearity_inputs, ons, offs,
3214 detmon_lg_config.llx,
3215 detmon_lg_config.lly,
3216 detmon_lg_config.urx,
3217 detmon_lg_config.ury,
3218 dit_nb, *dit_nskip, mode));
3220 skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
3232 if(opt_nir == OPT &&
3233 *rows_linear_affected != 0 ) {
3234 detmon_opt_contamination(ons, offs, mode, qclist);
3241 cpl_frameset_delete(pair_on);
3242 cpl_imagelist_delete(ons);
3244 if(!detmon_lg_config.collapse ) {
3245 cpl_imagelist_delete(offs);
3248 if(!detmon_lg_config.collapse) {
3249 cpl_frameset_delete(pair_off);
3252 cpl_propertylist_delete(plist);
3253 cpl_propertylist_delete(pDETlist);
3254 return cpl_error_get_code();
3264static cpl_error_code
3265detmon_add_adl_column(cpl_table * table,
3266 cpl_boolean opt_nir)
3268 cpl_error_code error;
3269 double mean_med_dit;
3272 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
3274 mean_med_dit = cpl_table_get_column_mean(table,
"MED_DIT");
3276 dits = cpl_table_get_data_double(table,
"EXPTIME");
3278 dits = cpl_table_get_data_double(table,
"DIT");
3280 error = cpl_table_copy_data_double(table,
"ADL", dits);
3281 cpl_ensure_code(!error, error);
3282 error = cpl_table_multiply_scalar(table,
"ADL", mean_med_dit);
3283 cpl_ensure_code(!error, error);
3285 return cpl_error_get_code();
3297static cpl_error_code
3298detmon_lg_reduce_init(cpl_table * gain_table,
3299 cpl_table * linear_table,
3300 cpl_imagelist ** linearity_inputs,
3301 const cpl_boolean opt_nir)
3303 skip_if(detmon_gain_table_create(gain_table, opt_nir));
3304 skip_if(detmon_lin_table_create(linear_table, opt_nir));
3306 if(detmon_lg_config.pix2pix) {
3307 *linearity_inputs = cpl_imagelist_new();
3308 skip_if(*linearity_inputs == NULL);
3313 return cpl_error_get_code();
3324detmon_pfits_get_dit(
const cpl_propertylist * plist)
3326 if (cpl_propertylist_has(plist,
"ESO DET DIT")) {
3328 return irplib_pfits_get_prop_double(plist,
"ESO DET DIT");
3331 return irplib_pfits_get_prop_double(plist,
"ESO DET SEQ1 DIT");
3333 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"FITS key "
3334 "ESO DET DIT or ESO DET DIT not found");
3346detmon_pfits_get_dit_opt(
const cpl_propertylist * plist)
3348 if (cpl_propertylist_has(plist,
"ESO DET WIN1 UIT1")) {
3350 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3351 }
else if (cpl_propertylist_has(plist,
"ESO DET UIT1")) {
3353 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3356 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
"FITS key "
3357 "ESO DET WIN1 UIT1 or ESO DET UIT1 not found");
3367static cpl_propertylist*
3368detmon_load_pro_keys(
const char* NAME_O)
3370 cpl_propertylist* pro_keys=NULL;
3371 pro_keys=cpl_propertylist_load_regexp(NAME_O,0,
"^(ESO PRO)",0);
3376static double irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
3377 const char* prop_name)
3380 dit = cpl_propertylist_get_double(plist, prop_name);
3381 if(cpl_error_get_code() != CPL_ERROR_NONE)
3383 cpl_msg_error(cpl_func,
"Cannot read property '%s', err[%s]",
3384 prop_name, cpl_error_get_where());
3389static cpl_error_code
3390detmon_gain_compute_qc(
double kappa,
int nclip,
const int pos,
3391 const cpl_imagelist* offs,
unsigned mode,
3392 double avg_on1,
double avg_on2,
3393 double avg_off1,
double avg_off2,
3394 double sig_off_dif,
int c_ndit,
3395 double autocorr, cpl_image* on_dif,
3396 cpl_table* gain_table)
3401 double avg_on_dif, sig_on_dif;
3402 irplib_ksigma_clip(on_dif, 1, 1, cpl_image_get_size_x(on_dif),
3403 cpl_image_get_size_y(on_dif), kappa, nclip, 1e-5,
3404 &avg_on_dif, &sig_on_dif);
3406 cpl_table_set_double(gain_table,
"SIG_ON_DIF", pos,
3408 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3409 double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
3412 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
3415 = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
3419 const double gain = double_adu / (c_ndit * sigma);
3421 const double gain_corr = gain / (autocorr);
3423 skip_if(cpl_table_set_double(gain_table,
"GAIN", pos, gain));
3425 cpl_table_set_double(gain_table,
"GAIN_CORR", pos,
3429 skip_if(cpl_table_set_double(gain_table,
"AUTOCORR", pos, autocorr));
3430 skip_if(cpl_table_set_double(gain_table,
"ADU", pos, double_adu / 2));
3433 cpl_table_set_double(gain_table,
"Y_FIT", pos,
3434 c_ndit * sig_on_dif * sig_on_dif));
3436 cpl_table_set_double(gain_table,
"Y_FIT_CORR", pos,
3437 c_ndit * sig_on_dif * sig_on_dif));
3438 skip_if(cpl_table_set_double(gain_table,
"X_FIT", pos, double_adu));
3440 cpl_table_set_double(gain_table,
"X_FIT_CORR", pos,
3441 double_adu / autocorr));
3445 return cpl_error_get_code();
3449detmon_gain_prepare_autocorr(
unsigned mode,
const int pos,
3450 int m,
int n, cpl_imagelist* diff_flats,
3451 cpl_image* on_dif, cpl_imagelist* autocorr_images)
3453 double autocorr = 1.0;
3455 if (mode & IRPLIB_GAIN_WITH_AUTOCORR) {
3457 cpl_image * diff = cpl_image_duplicate(on_dif);
3458 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
3460 if (autocorr_images) {
3461 cpl_image * corr = NULL;
3462 autocorr = detmon_autocorr_factor(on_dif, &corr, m, n);
3464 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
3467 detmon_lg_add_empty_image(autocorr_images, pos);
3471 autocorr = detmon_autocorr_factor(on_dif, NULL, m, n);
3473 autocorr = isnan(autocorr) ? 1.0 : autocorr;
3481detmon_gain_prepare_table(
const cpl_imagelist* offs,
unsigned mode,
int llx,
3482 int lly,
int urx,
int ury,
double kappa,
int nclip,
3483 double std,
const int pos,
3484 cpl_table* gain_table,
double* avg_off2,
3485 double* sig_off_dif)
3487 double avg_off1 = 0.0;
3494 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3497 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3498 llx, lly, urx, ury, kappa, nclip, 1e-5,
3500 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF", pos, avg_off1));
3503 else if ((mode & IRPLIB_GAIN_NO_COLLAPSE)
3504 || (pos == 0 && mode & IRPLIB_GAIN_COLLAPSE)) {
3505 cpl_image * off_dif = NULL;
3508 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3509 llx, lly, urx, ury, kappa, nclip, 1e-5,
3511 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3513 irplib_ksigma_clip(cpl_imagelist_get_const(offs, 1),
3514 llx, lly, urx, ury, kappa, nclip, 1e-5,
3516 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3517 off_dif = detmon_subtract_create_window(
3518 cpl_imagelist_get_const(offs, 0),
3519 cpl_imagelist_get_const(offs, 1), llx, lly, urx, ury);
3520 skip_if(off_dif == NULL);
3521 irplib_ksigma_clip(off_dif, 1, 1, cpl_image_get_size_x(off_dif),
3522 cpl_image_get_size_y(off_dif), kappa, nclip, 1e-5,
3523 &avg_off_dif, sig_off_dif);
3524 cpl_image_delete(off_dif);
3526 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3529 else if (pos > 0 && (mode & IRPLIB_GAIN_COLLAPSE)) {
3532 avg_off1 = cpl_table_get_double(gain_table,
"MEAN_OFF1", 0, &status);
3533 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3534 *avg_off2 = cpl_table_get_double(gain_table,
"MEAN_OFF2", 0, &status);
3535 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, *avg_off2));
3536 *sig_off_dif = cpl_table_get_double(gain_table,
"SIG_OFF_DIF", 0,
3539 cpl_table_set_double(gain_table,
"SIG_OFF_DIF", pos,
3584static cpl_error_code
3585detmon_gain_table_fill_row(cpl_table * gain_table,
3586 double c_dit,
int c_ndit,
3587 cpl_imagelist * autocorr_images,
3588 cpl_imagelist * diff_flats,
3589 const cpl_imagelist * ons,
3590 const cpl_imagelist * offs,
3591 double kappa,
int nclip,
3592 int llx,
int lly,
int urx,
int ury,
3594 double gain_threshold,
3595 int pos,
unsigned mode,
int* rows_gain_affected)
3597 const cpl_image *image;
3598 cpl_image *on_dif = NULL;
3600 double avg_on1, avg_on2;
3601 double avg_off1, avg_off2;
3604 cpl_table_set(gain_table,
"FLAG", pos, 1);
3605 if (mode & IRPLIB_GAIN_NIR)
3607 cpl_table_set(gain_table,
"DIT", pos, c_dit);
3608 cpl_table_set(gain_table,
"NDIT", pos, c_ndit);
3609 }
else if (mode & IRPLIB_GAIN_OPT)
3611 cpl_table_set(gain_table,
"EXPTIME", pos, c_dit);
3614 cpl_msg_error(cpl_func,
"Mandatory mode (OPT or NIR) not provided");
3617 if(*rows_gain_affected == 0)
3619 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3620 cpl_table_set(gain_table,
"FLAG", pos, 0);
3621 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3626 detmon_lg_add_empty_image(diff_flats, pos);
3628 if (autocorr_images)
3630 detmon_lg_add_empty_image(autocorr_images, pos);
3633 return cpl_error_get_code();
3635 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3636 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3637 nclip, 1e-5, &avg_on1, &std));
3638 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3639 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3640 nclip, 1e-5, &avg_on2, &std));
3643 (avg_on1 > gain_threshold) ||
3644 (avg_on2 > gain_threshold)
3650 if ( (avg_on1 > gain_threshold) || (avg_on2 > gain_threshold) )
3652 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the gain_theshold parameter, "
3653 "the frames would not be taken into calculation");
3655 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3656 avg_on1, avg_on2, gain_threshold);
3659 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3660 cpl_table_set(gain_table,
"FLAG", pos, 0);
3661 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3666 detmon_lg_add_empty_image(diff_flats, pos);
3668 if (autocorr_images)
3670 detmon_lg_add_empty_image(autocorr_images, pos);
3673 *rows_gain_affected = 0;
3681 *rows_gain_affected = 1;
3682 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON1", pos, avg_on1));
3683 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON2", pos, avg_on2));
3686 detmon_subtract_create_window(cpl_imagelist_get_const(ons, 0),
3687 cpl_imagelist_get_const(ons, 1),
3688 llx, lly, urx, ury);
3689 skip_if(on_dif == NULL);
3691 autocorr = detmon_gain_prepare_autocorr(mode, pos, m, n,
3692 diff_flats, on_dif, autocorr_images);
3694 avg_off1 = detmon_gain_prepare_table(offs, mode, llx, lly, urx, ury,
3695 kappa, nclip, std, pos, gain_table, &avg_off2,
3698 detmon_gain_compute_qc(kappa, nclip, pos, offs, mode,
3699 avg_on1, avg_on2, avg_off1, avg_off2,
3700 sig_off_dif, c_ndit, autocorr, on_dif,
3705 cpl_image_delete(on_dif);
3707 return cpl_error_get_code();
3734static cpl_error_code
3735detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
3736 cpl_imagelist * diff_flats,
3737 const cpl_imagelist * ons,
3738 double kappa,
int nclip,
3739 int llx,
int lly,
int urx,
int ury,
3740 double saturation_limit,
3741 const int pos,
unsigned mode,
int* rows_linear_affected)
3743 const cpl_image *image;
3745 double avg_on1, avg_on2;
3748 if(*rows_linear_affected == 0)
3750 cpl_msg_info(cpl_func,
"For linearity skip the frame #%d", pos + 1);
3751 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3755 detmon_lg_add_empty_image(diff_flats, pos);
3757 if (autocorr_images)
3759 detmon_lg_add_empty_image(autocorr_images, pos);
3762 return cpl_error_get_code();
3764 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3765 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3766 nclip, 1e-5, &avg_on1, &std));
3767 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3768 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3769 nclip, 1e-5, &avg_on2, &std));
3772 (avg_on1 > saturation_limit) ||
3773 (avg_on2 > saturation_limit)
3779 if ( (avg_on1 > saturation_limit) || (avg_on2 > saturation_limit) )
3781 cpl_msg_warning(cpl_func,
"Average level is above the limit set by the saturation_limit parameter, "
3782 "the frames would not be taken into calculation");
3784 cpl_msg_warning(cpl_func,
"Average levels [%f ; %f], limit [%f]",
3785 avg_on1, avg_on2, saturation_limit);
3788 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3789 *rows_linear_affected = 0;
3796 return cpl_error_get_code();
3812detmon_bpixs(
const cpl_imagelist * coeffs,
3819 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
3826 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
3827 cpl_image_get_size_y(first));
3829 cpl_image *bpm = NULL;
3832 int size = cpl_imagelist_get_size(coeffs);
3835 bpm = cpl_image_new(cpl_image_get_size_x(first),
3836 cpl_image_get_size_y(first),
3841 for(
int i = 0; i < size; i++) {
3842 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
3844 cpl_stats* stats = cpl_stats_new_from_image(cur_coeff,
3845 CPL_STATS_MEAN | CPL_STATS_STDEV);
3846 double cur_mean = cpl_stats_get_mean(stats);
3847 double cur_stdev = cpl_stats_get_stdev(stats);
3849 double lo_cut = cur_mean - kappa * cur_stdev;
3850 double hi_cut = cur_mean + kappa * cur_stdev;
3852 cpl_mask* cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
3853 cpl_mask_not(cur_mask);
3856 cpl_image* cur_image = cpl_image_new_from_mask(cur_mask);
3857 double p = pow(2, i);
3858 cpl_image_power(cur_image, p);
3859 cpl_image_add(bpm, cur_image);
3860 cpl_image_delete(cur_image);
3863 cpl_mask_or(mask, cur_mask);
3865 cpl_mask_delete(cur_mask);
3866 cpl_stats_delete(stats);
3870 bpm = cpl_image_new_from_mask(mask);
3873 *nbpixs = cpl_mask_count(mask);
3875 cpl_mask_delete(mask);
4002detmon_autocorr_factor(
const cpl_image * image,
4003 cpl_image ** autocorr_image,
int m,
int n)
4005 cpl_image * mycorr_image = NULL;
4006 double autocorr = 0;
4009 mycorr_image = detmon_image_correlate(image, image, m, n);
4011 if (cpl_error_get_code() == CPL_ERROR_UNSUPPORTED_MODE)
4013 cpl_msg_warning(cpl_func,
"FFTW is not supported by CPL, autocorrelation "
4014 "would be computed using internal implementation");
4017 cpl_image_delete(mycorr_image);
4018 mycorr_image = detmon_autocorrelate(image, m, n);
4020 if(mycorr_image == NULL) {
4024 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
4026 autocorr = cpl_image_get_flux(mycorr_image);
4028 if (autocorr_image) *autocorr_image = mycorr_image;
4029 else cpl_image_delete(mycorr_image);
4034static cpl_propertylist*
4035detmon_lg_extract_qclist_4plane(cpl_propertylist* linc_qclist,
const int ip)
4038 cpl_propertylist* sub_set=NULL;
4041 sub_set=cpl_propertylist_new();
4042 qc_key=cpl_sprintf(
"QC LIN COEF%d",ip);
4043 cpl_propertylist_copy_property_regexp(sub_set,linc_qclist,qc_key,0);
4060static cpl_error_code
4061detmon_lg_extract_extention_header(cpl_frameset* frameset,
4062 cpl_propertylist* gaint_qclist,
4063 cpl_propertylist* lint_qclist,
4064 cpl_propertylist* linc_qclist,
4065 cpl_propertylist* bpm_qclist,
4069 cpl_propertylist * xplist = NULL;
4071 const char * filename =
4072 cpl_frame_get_filename(cpl_frameset_get_position(frameset, 0));
4074 xplist = cpl_propertylist_load_regexp(filename, whichext,
4075 "ESO DET|EXTNAME", 0);
4076 if (detmon_lg_config.exts >= 0)
4079 cpl_property* propExtname = NULL;
4080 propExtname = cpl_propertylist_get_property(xplist,
"EXTNAME");
4082 if (NULL != propExtname)
4084 propExtname = cpl_property_duplicate(propExtname);
4086 cpl_propertylist_delete(xplist);
4088 if (NULL != propExtname)
4090 xplist = cpl_propertylist_new();
4091 cpl_propertylist_append_property(xplist, propExtname);
4092 cpl_property_delete(propExtname);
4097 cpl_propertylist_append(gaint_qclist, xplist);
4098 cpl_propertylist_append(lint_qclist, xplist);
4099 cpl_propertylist_append(linc_qclist, xplist);
4100 cpl_propertylist_append(bpm_qclist, xplist);
4101 cpl_propertylist_delete(xplist);
4104 return cpl_error_get_code();
4121static cpl_error_code
4122detmon_lg_save_table_with_pro_keys(cpl_table* table,
4124 cpl_propertylist* xheader,
4125 unsigned CPL_IO_MODE)
4128 cpl_propertylist* pro_keys=NULL;
4130 pro_keys=detmon_load_pro_keys(name_o);
4131 cpl_propertylist_append(xheader,pro_keys);
4133 if(CPL_IO_MODE==CPL_IO_DEFAULT) {
4134 cpl_propertylist * pri_head=cpl_propertylist_load(name_o,0);
4135 cpl_table_save(table, pri_head,xheader,name_o,
4137 cpl_propertylist_delete(pri_head);
4140 cpl_table_save(table,NULL,xheader,name_o,
4143 cpl_propertylist_delete(pro_keys);
4145 return cpl_error_get_code();
4157static cpl_error_code
4158detmon_lg_save_image_with_pro_keys(cpl_image* image,
4160 cpl_propertylist* xheader)
4163 cpl_propertylist* pro_keys=NULL;
4164 pro_keys=detmon_load_pro_keys(name_o);
4165 cpl_propertylist_append(xheader,pro_keys);
4167 cpl_image_save(image,name_o, CPL_BPP_IEEE_FLOAT,
4168 xheader,CPL_IO_EXTEND);
4169 cpl_propertylist_delete(pro_keys);
4172 return cpl_error_get_code();
4184static cpl_error_code
4185detmon_lg_save_imagelist_with_pro_keys(cpl_imagelist* imagelist,
4187 cpl_propertylist* xheader)
4190 cpl_propertylist* pro_keys=NULL;
4191 pro_keys=detmon_load_pro_keys(name_o);
4192 cpl_propertylist_append(xheader,pro_keys);
4194 cpl_imagelist_save(imagelist,name_o, CPL_BPP_IEEE_FLOAT,
4195 xheader,CPL_IO_EXTEND);
4197 cpl_propertylist_delete(pro_keys);
4200 return cpl_error_get_code();
4220static cpl_error_code
4221detmon_lg_save_plane(
const cpl_parameterlist * parlist,
4222 cpl_frameset* frameset,
4223 const cpl_frameset * usedframes,
4225 const char* recipe_name,
4226 cpl_propertylist* mypro_coeffscube,
4227 cpl_propertylist* linc_plane_qclist,
4228 const char* package,
4232 if(detmon_lg_config.exts == 0) {
4233 cpl_propertylist* plist=NULL;
4234 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4236 CPL_BPP_IEEE_FLOAT, recipe_name,
4237 mypro_coeffscube, NULL,
4239 plist=cpl_propertylist_load(NAME_O,0);
4240 cpl_image_save(plane,NAME_O, CPL_BPP_IEEE_FLOAT,
4241 plist,CPL_IO_DEFAULT);
4242 cpl_propertylist_delete(plist);
4244 }
else if(detmon_lg_config.exts > 0) {
4245 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4247 CPL_BPP_IEEE_FLOAT, recipe_name,
4248 mypro_coeffscube, NULL,
4251 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4255 cpl_dfs_save_image(frameset, NULL, parlist,
4256 usedframes,NULL, NULL,
4257 CPL_BPP_IEEE_FLOAT, recipe_name,
4258 mypro_coeffscube, NULL,
4260 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4263 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4269 return cpl_error_get_code();
4292static cpl_error_code
4293detmon_lg_save_cube(
const cpl_parameterlist * parlist,
4294 cpl_frameset* frameset,
4295 const cpl_frameset * usedframes,
4297 const char* recipe_name,
4298 cpl_propertylist* mypro_coeffscube,
4299 cpl_propertylist* linc_qclist,
4300 const char* package,
4302 cpl_imagelist* coeffs)
4305 if(detmon_lg_config.exts == 0) {
4306 cpl_propertylist_append(mypro_coeffscube, linc_qclist);
4307 detmon_lg_dfs_save_imagelist
4308 (frameset, parlist, usedframes, coeffs,
4309 recipe_name, mypro_coeffscube, package,
4311 }
else if(detmon_lg_config.exts > 0) {
4312 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4314 CPL_BPP_IEEE_FLOAT, recipe_name,
4315 mypro_coeffscube, NULL,
4318 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4322 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4324 CPL_BPP_IEEE_FLOAT, recipe_name,
4325 mypro_coeffscube, NULL,
4328 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4330 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4333 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4335 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4339 return cpl_error_get_code();
4343detmon_lg_set_paf_name_and_header(cpl_frame* ref_frame,
4344 int flag_sets,
int which_set,
4346 const char* paf_suf,
4347 cpl_propertylist** plist)
4349 char * paf_name=NULL;
4351 if(detmon_lg_config.exts >= 0)
4353 *plist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4354 detmon_lg_config.exts);
4358 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4362 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4363 detmon_lg_config.pafname, paf_suf,which_set);
4368 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4374 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4375 detmon_lg_config.pafname, paf_suf,whichext);
4379 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4380 detmon_lg_config.pafname,paf_suf,
4381 which_set, whichext);
4390detmon_lg_set_paf_name_and_header_ext(cpl_frame* ref_frame,
4391 int flag_sets,
int which_set,
4393 const char* paf_suf,
4394 cpl_propertylist** plist)
4396 char* paf_name=NULL;
4398 if(detmon_lg_config.exts >= 0)
4400 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4401 detmon_lg_config.exts);
4405 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4408 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4409 detmon_lg_config.pafname, paf_suf,which_set);
4413 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4417 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4418 detmon_lg_config.pafname, paf_suf,whichext);
4421 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4422 detmon_lg_config.pafname,paf_suf,
4423 which_set, whichext);
4430static cpl_error_code
4431detmon_lg_save_paf_product(cpl_frame* ref_frame,
int flag_sets,
4432 int which_set,
int whichext,
4433 const char* pafregexp,
4434 const char* procatg,
4435 const char* pipeline_name,
4436 const char* recipe_name,
4437 const char* paf_suf,
4438 cpl_propertylist* qclist,
4443 char* paf_name=NULL;
4444 cpl_propertylist* plist=NULL;
4445 cpl_propertylist* paflist = NULL;
4446 cpl_propertylist* mainplist=NULL;
4448 mainplist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0);
4450 paf_name=detmon_lg_set_paf_name_and_header(ref_frame,flag_sets,
4454 paf_name=detmon_lg_set_paf_name_and_header_ext(ref_frame,flag_sets,
4460 paflist = cpl_propertylist_new();
4461 cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,procatg);
4464 cpl_propertylist_copy_property_regexp(paflist, plist,pafregexp, 0);
4465 cpl_propertylist_copy_property_regexp(paflist, mainplist,pafregexp, 0);
4466 cpl_propertylist_append(paflist,qclist);
4469 cpl_dfs_save_paf(pipeline_name, recipe_name,paflist,paf_name);
4472 cpl_propertylist_delete(mainplist);
4473 cpl_propertylist_delete(paflist);
4474 cpl_propertylist_delete(plist);
4477 return cpl_error_get_code();
4514static cpl_error_code
4515detmon_lg_save(
const cpl_parameterlist * parlist,
4516 cpl_frameset * frameset,
4517 const char *recipe_name,
4518 const char *pipeline_name,
4519 const char *pafregexp,
4520 const cpl_propertylist * pro_lintbl,
4521 const cpl_propertylist * pro_gaintbl,
4522 const cpl_propertylist * pro_coeffscube,
4523 const cpl_propertylist * pro_bpm,
4524 const cpl_propertylist * pro_corr,
4525 const cpl_propertylist * pro_diff,
4526 const char *package,
4527 cpl_imagelist * coeffs,
4528 cpl_table * gain_table,
4529 cpl_table * linear_table,
4531 cpl_imagelist * autocorr_images,
4532 cpl_imagelist * diff_flats,
4533 cpl_propertylist * gaint_qclist,
4534 cpl_propertylist * lint_qclist,
4535 cpl_propertylist * linc_qclist,
4536 cpl_propertylist * bpm_qclist,
4537 const int flag_sets,
4538 const int which_set,
4539 const cpl_frameset * usedframes,
4543 cpl_frame *ref_frame;
4544 cpl_propertylist *plist = NULL;
4545 cpl_propertylist *mainplist = NULL;
4551 cpl_propertylist * xplist = NULL;
4553 cpl_propertylist* linc_plane_qclist=NULL;
4554 cpl_image* plane=NULL;
4556 char* pcatg_plane=NULL;
4558 cpl_propertylist * mypro_lintbl =
4559 cpl_propertylist_duplicate(pro_lintbl);
4560 cpl_propertylist * mypro_gaintbl =
4561 cpl_propertylist_duplicate(pro_gaintbl);
4562 cpl_propertylist * mypro_coeffscube =
4563 cpl_propertylist_duplicate(pro_coeffscube);
4564 cpl_propertylist * mypro_bpm =
4565 cpl_propertylist_duplicate(pro_bpm);
4566 cpl_propertylist * mypro_corr =
4567 cpl_propertylist_duplicate(pro_corr);
4568 cpl_propertylist * mypro_diff =
4569 cpl_propertylist_duplicate(pro_diff);
4571 const char * procatg_lintbl =
4572 cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
4574 const char * procatg_gaintbl =
4575 cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
4577 const char * procatg_coeffscube =
4578 cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
4579 const char * procatg_bpm =
4580 cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
4584 detmon_lg_extract_extention_header(frameset,gaint_qclist,lint_qclist,
4585 linc_qclist,bpm_qclist,whichext);
4590 ref_frame = cpl_frameset_get_position(frameset, 0);
4592 skip_if((mainplist =
4593 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4599 cpl_msg_info(cpl_func,
"Write the LINEARITY TABLE");
4602 NAME_O=cpl_sprintf(
"%s_linearity_table.fits", recipe_name);
4604 NAME_O=cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name,
4608 if (detmon_lg_config.exts >= 0) {
4610 cpl_propertylist_append(mypro_lintbl, lint_qclist);
4611 skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,
4612 linear_table,NULL, recipe_name,
4613 mypro_lintbl, NULL, package, NAME_O));
4615 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4616 lint_qclist,CPL_IO_DEFAULT);
4621 skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL,
4622 linear_table,lint_qclist, recipe_name,
4623 mypro_lintbl,NULL, package, NAME_O));
4624 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4625 lint_qclist,CPL_IO_DEFAULT);
4632 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4633 lint_qclist,CPL_IO_EXTEND);
4636 irplib_free(&NAME_O);
4640 cpl_msg_info(cpl_func,
"Write the GAIN TABLE");
4643 NAME_O=cpl_sprintf(
"%s_gain_table.fits", recipe_name);
4645 NAME_O=cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name,
4649 if (detmon_lg_config.exts >= 0)
4653 cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
4654 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
4655 gain_table,NULL, recipe_name, mypro_gaintbl,
4656 NULL, package, NAME_O));
4657 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4658 gaint_qclist,CPL_IO_DEFAULT);
4666 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
4667 gaint_qclist, recipe_name, mypro_gaintbl,
4668 NULL, package, NAME_O));
4669 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4670 gaint_qclist,CPL_IO_DEFAULT);
4676 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4677 gaint_qclist,CPL_IO_EXTEND);
4681 if(detmon_lg_config.pix2pix)
4687 cpl_msg_info(cpl_func,
"Write the COEFFS FITS");
4688 irplib_free(&NAME_O);
4691 PREF_O=cpl_sprintf(
"%s_coeffs_cube", recipe_name);
4694 PREF_O=cpl_sprintf(
"%s_coeffs_cube_set%02d",
4695 recipe_name, which_set);
4697 if (detmon_lg_config.split_coeffs == 0) {
4698 NAME_O=cpl_sprintf(
"%s.fits", PREF_O);
4703 if(detmon_lg_config.split_coeffs != 0){
4706 nb_images = cpl_imagelist_get_size(coeffs);
4707 for(ip=0;ip<nb_images;ip++) {
4708 NAME_O=cpl_sprintf(
"%s_P%d.fits", PREF_O,ip);
4709 pcatg_plane=cpl_sprintf(
"COEFFS_CUBE_P%d",ip);
4710 cpl_propertylist_delete(mypro_coeffscube);
4711 mypro_coeffscube=cpl_propertylist_duplicate(pro_coeffscube);
4712 cpl_propertylist_set_string(mypro_coeffscube,CPL_DFS_PRO_CATG,
4714 linc_plane_qclist=detmon_lg_extract_qclist_4plane(linc_qclist,ip);
4715 cpl_propertylist_append(mypro_coeffscube, linc_plane_qclist);
4716 plane=cpl_imagelist_get(coeffs,ip);
4717 detmon_lg_save_plane(parlist,frameset,usedframes,whichext,
4718 recipe_name,mypro_coeffscube,
4719 linc_plane_qclist,package,NAME_O,plane);
4721 if(NULL!=linc_plane_qclist) {
4722 cpl_propertylist_delete(linc_plane_qclist);
4724 irplib_free(&NAME_O);
4729 detmon_lg_save_cube(parlist,frameset,usedframes,whichext,
4730 recipe_name,mypro_coeffscube,
4731 linc_qclist,package,NAME_O,coeffs);
4737 cpl_msg_info(cpl_func,
"Write the BAD PIXEL MAP");
4738 irplib_free(&NAME_O);
4742 NAME_O=cpl_sprintf(
"%s_bpm.fits", recipe_name);
4745 NAME_O=cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, which_set);
4750 if(detmon_lg_config.exts == 0) {
4751 cpl_propertylist_append(mypro_bpm, bpm_qclist);
4752 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
4753 CPL_BPP_IEEE_FLOAT, recipe_name,
4754 mypro_bpm, NULL, package,
4757 else if(detmon_lg_config.exts > 0)
4759 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4760 CPL_BPP_IEEE_FLOAT, recipe_name,
4761 mypro_bpm, NULL, package,
4763 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4769 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4770 CPL_BPP_IEEE_FLOAT, recipe_name,
4771 mypro_bpm, NULL, package,
4773 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4776 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4781 if(detmon_lg_config.intermediate)
4786 cpl_msg_info(cpl_func,
"Write the AUTOCORRS FITS");
4787 nb_images = cpl_imagelist_get_size(autocorr_images);
4788 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
4789 for(i = 0; i < nb_images; i++)
4791 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_corr);
4793 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4795 if(i < cpl_table_get_nrow(linear_table))
4797 ddit = cpl_table_get_double(linear_table,
4798 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4800 cpl_array_delete(pnames);
4803 irplib_free(&NAME_O);
4806 NAME_O=cpl_sprintf(
"%s_autocorr_%d.fits", recipe_name, i);
4807 assert(NAME_O != NULL);
4810 NAME_O=cpl_sprintf(
"%s_autocorr_%02d_set%02d.fits",
4811 recipe_name, i, which_set);
4812 assert(NAME_O != NULL);
4815 if(detmon_lg_config.exts > 0)
4817 cpl_propertylist* pextlist = cpl_propertylist_new();
4818 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4819 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4820 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4821 recipe_name, pplist, NULL,
4824 detmon_lg_save_image_with_pro_keys(
4825 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4827 cpl_propertylist_delete(pextlist);
4829 if(detmon_lg_config.exts == 0)
4831 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4832 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
4833 cpl_imagelist_get(autocorr_images, i),
4835 recipe_name, pplist, NULL, package,
4841 cpl_propertylist* pextlist = cpl_propertylist_new();
4842 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4845 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4846 usedframes, NULL,NULL,
4847 CPL_BPP_IEEE_FLOAT, recipe_name,
4851 detmon_lg_save_image_with_pro_keys(
4852 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4857 detmon_lg_save_image_with_pro_keys(
4858 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4860 cpl_propertylist_delete(pextlist);
4862 cpl_propertylist_delete (pplist);
4864 irplib_free(&NAME_O);
4873 cpl_msg_info(cpl_func,
"Write the DIFFS FITS");
4875 for(i = 0; i < nb_images; i++)
4877 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_diff);
4879 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4881 if(i < cpl_table_get_nrow(linear_table))
4883 ddit = cpl_table_get_double(linear_table,
4884 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4886 cpl_array_delete(pnames);
4891 NAME_O=cpl_sprintf(
"%s_diff_flat_%d.fits", recipe_name, i);
4894 NAME_O=cpl_sprintf(
"%s_diff_flat_%d_set%02d.fits",
4895 recipe_name, i, which_set);
4898 if(detmon_lg_config.exts > 0)
4900 cpl_propertylist* pextlist = cpl_propertylist_new();
4901 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4902 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT", ddit);
4903 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4904 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4906 mypro_diff, NULL,package, NAME_O));
4908 detmon_lg_save_image_with_pro_keys(
4909 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4911 cpl_propertylist_delete(pextlist);
4913 else if(detmon_lg_config.exts == 0)
4915 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4917 (frameset, NULL, parlist, usedframes, NULL,
4918 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
4919 recipe_name, pplist, NULL, package,
4924 cpl_propertylist* pextlist = cpl_propertylist_new();
4925 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4928 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT",ddit);
4930 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4931 usedframes, NULL,NULL,
4932 CPL_BPP_IEEE_FLOAT, recipe_name,
4933 mypro_diff, NULL,package, NAME_O));
4935 detmon_lg_save_image_with_pro_keys(
4936 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4941 detmon_lg_save_image_with_pro_keys(
4942 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4945 cpl_propertylist_delete(pextlist);
4947 cpl_propertylist_delete(pplist);
4948 irplib_free(&NAME_O);
4956 cpl_msg_info(cpl_func,
"Write the PAF file(s)");
4958 if(detmon_lg_config.pafgen) {
4960 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4961 pafregexp,procatg_gaintbl,
4962 pipeline_name,recipe_name,
4963 "qc01",gaint_qclist,0);
4965 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4966 pafregexp,procatg_lintbl,
4967 pipeline_name,recipe_name,
4968 "qc02",lint_qclist,0);
4970 if(detmon_lg_config.pix2pix)
4973 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4976 pipeline_name,recipe_name,
4977 "qc03",linc_qclist,1);
4979 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4980 whichext,pafregexp,procatg_bpm,
4981 pipeline_name,recipe_name,
4982 "qc04",bpm_qclist,1);
4987 cpl_msg_info(cpl_func,
"exit");
4989 cpl_propertylist_delete(xplist);
4991 cpl_propertylist_delete(plist);
4995 irplib_free(&NAME_O);
4997 cpl_free(pcatg_plane);
4998 cpl_propertylist_delete(mainplist);
4999 cpl_propertylist_delete(mypro_lintbl);
5000 cpl_propertylist_delete(mypro_gaintbl);
5001 cpl_propertylist_delete(mypro_coeffscube);
5002 cpl_propertylist_delete(mypro_bpm);
5003 cpl_propertylist_delete(mypro_corr);
5004 cpl_propertylist_delete(mypro_diff);
5006 return cpl_error_get_code();
5019static cpl_error_code
5020detmon_opt_contamination(
const cpl_imagelist * ons,
5021 const cpl_imagelist * offs,
5023 cpl_propertylist * qclist)
5031 struct rect rects[5] = {
5032 (
struct rect){ detmon_lg_config.llx1,
5033 detmon_lg_config.lly1,
5034 detmon_lg_config.urx1,
5035 detmon_lg_config.ury1},
5036 (
struct rect){ detmon_lg_config.llx2,
5037 detmon_lg_config.lly2,
5038 detmon_lg_config.urx2,
5039 detmon_lg_config.ury2},
5040 (
struct rect){ detmon_lg_config.llx3,
5041 detmon_lg_config.lly3,
5042 detmon_lg_config.urx3,
5043 detmon_lg_config.ury3},
5044 (
struct rect){ detmon_lg_config.llx4,
5045 detmon_lg_config.lly4,
5046 detmon_lg_config.urx4,
5047 detmon_lg_config.ury4},
5048 (
struct rect){ detmon_lg_config.llx5,
5049 detmon_lg_config.lly5,
5050 detmon_lg_config.urx5,
5051 detmon_lg_config.ury5},
5054 for (
size_t i = 0; i < 5; i++) {
5055 cpl_image * dif_avg;
5056 const cpl_image * off2;
5059 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
5060 off2 = cpl_imagelist_get_const(offs, 0);
5062 off2 = cpl_imagelist_get_const(offs, 1);
5064 dif_avg = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
5065 cpl_imagelist_get_const(offs, 0),
5066 cpl_imagelist_get_const(ons, 1),
5073 median = cpl_image_get_median(dif_avg);
5074 cpl_image_delete(dif_avg);
5077 sprintf(kname, DETMON_QC_CONTAM
"%zd", i + 1);
5079 if(cpl_propertylist_has(qclist,kname)){
5080 skip_if(cpl_propertylist_update_double(qclist,kname,median));
5082 skip_if(cpl_propertylist_append_double(qclist,kname,median));
5083 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
5089 return cpl_error_get_code();
5148detmon_lg_dfs_set_groups(cpl_frameset * set,
5149 const char *tag_on,
const char *tag_off)
5161 int nframes = cpl_frameset_get_size(set);
5164 for(
int i = 0; i < nframes; i++) {
5165 cpl_frame* cur_frame = cpl_frameset_get_position(set, i);
5166 const char* tag = cpl_frame_get_tag(cur_frame);
5169 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
5170 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
5190static cpl_error_code
5191detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist ** coeffs_ptr,
5192 cpl_image **bpms_ptr)
5208 cpl_image* dummy_bpm = cpl_image_new(detmon_lg_config.nx,
5209 detmon_lg_config.ny,
5211 cpl_imagelist* dummy_coeffs = cpl_imagelist_new();
5213 int* db_p = cpl_image_get_data_int(dummy_bpm);
5214 int* rb_p = cpl_image_get_data_int(*bpms_ptr);;
5215 float** dcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5216 float** rcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
5217 int dlength = detmon_lg_config.nx;
5219 int rlength = detmon_lg_config.urx - detmon_lg_config.llx + 1;
5220 for (
int i = 0; i <= detmon_lg_config.order; i++)
5222 cpl_image* dummy_coeff = cpl_image_new(detmon_lg_config.nx,
5223 detmon_lg_config.ny,
5226 cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
5227 dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
5228 rcs_p[i] = cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
5231 for (
int i = detmon_lg_config.lly - 1; i < detmon_lg_config.ury; i++)
5233 for (
int j = detmon_lg_config.llx - 1; j < detmon_lg_config.urx; j++)
5235 shift_idx=(i - detmon_lg_config.lly + 1) * rlength +
5236 j - detmon_lg_config.llx + 1;
5237 *(db_p + i * dlength + j) = *(rb_p + shift_idx);
5238 for (
int k = 0; k <= detmon_lg_config.order; k++)
5240 *(dcs_p[k] + i * dlength + j) =
5241 *(rcs_p[k] + (i - detmon_lg_config.lly + 1) * rlength +
5242 j - detmon_lg_config.llx + 1);
5246 cpl_imagelist_delete(*coeffs_ptr);
5247 cpl_image_delete(*bpms_ptr);
5248 *coeffs_ptr = dummy_coeffs;
5249 *bpms_ptr = dummy_bpm;
5253 return cpl_error_get_code();
5290#ifdef DETMON_USE_DETECTOR_SHOTNOISE_MODEL
5313static cpl_error_code
5314detmon_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
5315 const double ron, cpl_image ** ima_errs)
5317 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
5318 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
5319 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
5320 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
5322 *ima_errs = cpl_image_duplicate(ima_data);
5324 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
5328 cpl_image_divide_scalar(*ima_errs, gain);
5329 cpl_image_add_scalar(*ima_errs, ron * ron);
5330 cpl_image_power(*ima_errs, 0.5);
5332 return cpl_error_get_code();
5337detmon_compute_badpixmap(cpl_boolean opt_nir,
const int nsets,
5338 const cpl_table* linear_table,
5339 const cpl_imagelist* linearity_inputs,
int nbpixs,
5340 cpl_vector* x, cpl_propertylist* gaint_qclist,
5341 cpl_image** bpms_ptr)
5347 if (opt_nir == NIR) {
5348 x = cpl_vector_wrap(nsets,
5349 (
double *) cpl_table_get_data_double_const(linear_table,
5353 x = cpl_vector_wrap(nsets,
5354 (
double *) cpl_table_get_data_double_const(linear_table,
5358 int sz = cpl_imagelist_get_size(linearity_inputs);
5359 double kappa = detmon_lg_config.kappa;
5360 int niter = detmon_lg_config.niter;
5361 int llx = detmon_lg_config.llx;
5362 int urx = detmon_lg_config.urx;
5363 int lly = detmon_lg_config.lly;
5364 int ury = detmon_lg_config.ury;
5366 const cpl_image *ima;
5370 cpl_imagelist* errors = cpl_imagelist_new();
5392 cpl_imagelist* linearity_scaled = cpl_imagelist_new();
5394 gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
5398 gain = (gain < 0) ? 1 : gain;
5404 for (
int i = 0; i < sz; i++) {
5405 ima = cpl_imagelist_get_const(linearity_inputs, i);
5413 irplib_ksigma_clip(ima, 1, 1, urx - llx + 1,
5414 ury - lly + 1, kappa, niter, 1e-5, &avg,
5419 if (avg < detmon_lg_config.saturation_limit) {
5427 cpl_image_get_mad(ima, &dmad);
5428 err = cpl_image_duplicate(ima);
5429 cpl_image_multiply_scalar(err, 0);
5430 cpl_image_add_scalar(err, dmad * CPL_MATH_STD_MAD);
5440 cpl_imagelist_set(errors, err, i);
5448 cpl_imagelist_set(linearity_scaled,
5449 cpl_image_duplicate(ima), i));
5452 hdrl_imagelist* hil = hdrl_imagelist_create(linearity_scaled, errors);
5457 cpl_imagelist_delete(errors);
5459 double pval = 0.001;
5460 p = hdrl_bpm_fit_parameter_create_pval(1, pval);
5469 hdrl_bpm_fit_compute(p, hil, x, bpms_ptr);
5494 nbpixs = cpl_image_get_flux(*bpms_ptr);
5496 hdrl_imagelist_delete(hil);
5497 cpl_imagelist_delete(linearity_scaled);
5498 cpl_vector_unwrap((cpl_vector*) x);
5499 hdrl_parameter_delete(p);
5515 skip_if(*bpms_ptr == NULL);
5536static cpl_error_code
5537detmon_lg_reduce_all(
const cpl_table * linear_table,
5538 cpl_propertylist * gaint_qclist,
5539 cpl_propertylist * lint_qclist,
5540 cpl_propertylist * linc_qclist,
5541 cpl_propertylist * bpm_qclist,
5542 cpl_imagelist ** coeffs_ptr,
5543 cpl_image ** bpms_ptr,
5544 const cpl_imagelist * linearity_inputs,
5545 const cpl_table * gain_table,
5546 int which_ext, cpl_boolean opt_nir)
5550 const int linear_nsets = cpl_table_get_nrow(linear_table);
5551 const int gain_nsets = cpl_table_get_nrow(gain_table);
5553 cpl_polynomial *poly_linfit = NULL;
5554 cpl_image *fiterror = NULL;
5555 char * name_o1 = NULL;
5556 char * name_o2 = NULL;
5557 double * pcoeffs = NULL;
5558 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
5561 cpl_vector *x =NULL;
5562 const cpl_vector *y =NULL;
5565 const cpl_image * first = NULL;
5573 cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5574 cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5575 cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
5576 cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
5578 pcoeffs = cpl_malloc(
sizeof(
double)*(detmon_lg_config.order + 1));
5580 skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
5581 detmon_lg_config.method));
5582 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
5583 DETMON_QC_METHOD_C));
5586 if (!strcmp(detmon_lg_config.method,
"PTC")) {
5588 if (detmon_lg_config.exts >= 0) {
5589 cpl_msg_info(cpl_func,
5590 "Polynomial fitting for the GAIN (constant term method)");
5592 cpl_msg_info(cpl_func,
5593 "Polynomial fitting for the GAIN (constant term method)"
5594 " for extension nb %d", which_ext);
5596 skip_if(detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, gain_nsets));
5598 skip_if(detmon_lg_qc_med(gain_table, gaint_qclist, gain_nsets));
5603 if(detmon_lg_config.lamp_ok) {
5604 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
5605 detmon_lg_config.cr));
5606 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
5607 DETMON_QC_LAMP_FLUX_C));
5611 if(detmon_lg_config.autocorr == TRUE) {
5612 autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
5613 skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
5615 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
5616 DETMON_QC_AUTOCORR_C));
5618 if (detmon_lg_config.exts >= 0) {
5619 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix");
5621 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix"
5622 " for extension nb %d", which_ext);
5625 if(!detmon_lg_config.pix2pix) {
5626 const int order=detmon_lg_config.order;
5634 y = cpl_vector_wrap(linear_nsets,
5635 (
double *)cpl_table_get_data_double_const(linear_table,
5638 if (opt_nir == NIR) {
5639 x = cpl_vector_wrap(linear_nsets,
5640 (
double *)cpl_table_get_data_double_const(linear_table,
5643 x = cpl_vector_wrap(linear_nsets,
5644 (
double *)cpl_table_get_data_double_const(linear_table,
5648 if(x == NULL || y == NULL) {
5649 cpl_vector_unwrap((cpl_vector *)x);
5650 cpl_vector_unwrap((cpl_vector *)y);
5660 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
5661 poly_linfit = irplib_polynomial_fit_1d_create(x, y,order,&mse);
5663 if(order == cpl_vector_get_size(x) - 1) {
5664 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5668 if(poly_linfit == NULL) {
5669 cpl_vector_unwrap((cpl_vector *)x);
5670 cpl_vector_unwrap((cpl_vector *)y);
5676 min_val=cpl_vector_get_min(y);
5677 max_val=cpl_vector_get_max(y);
5679 cpl_vector_unwrap((cpl_vector *)x);
5680 cpl_vector_unwrap((cpl_vector *)y);
5682 for(deg = 0; deg <= order; deg++) {
5683 const double coeff =
5684 cpl_polynomial_get_coeff(poly_linfit, °);
5687 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
5688 assert(name_o != NULL);
5689 skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
5690 skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
5691 DETMON_QC_LIN_COEF_C));
5694 pcoeffs[deg] = coeff;
5696 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
5697 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
5698 DETMON_QC_ERRFIT_MSE_C));
5702 const int order=detmon_lg_config.order;
5704 y = cpl_vector_wrap(linear_nsets,
5705 (
double *)cpl_table_get_data_double_const(linear_table,
5710 x = cpl_vector_wrap(linear_nsets,
5711 (
double *)cpl_table_get_data_double_const(linear_table,
5714 x = cpl_vector_wrap(linear_nsets,
5715 (
double *)cpl_table_get_data_double_const(linear_table,
5720 first = cpl_imagelist_get_const(linearity_inputs, 0);
5721 sizex = cpl_image_get_size_x(first);
5722 sizey = cpl_image_get_size_y(first);
5723 vsize = cpl_vector_get_size(x);
5724 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
5726 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,order, FALSE,
5727 CPL_TYPE_FLOAT, fiterror);
5728 min_val=cpl_vector_get_min(y);
5729 max_val=cpl_vector_get_max(y);
5730 cpl_vector_unwrap((cpl_vector*)x);
5731 cpl_vector_unwrap((cpl_vector*)y);
5733 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
5734 "Failed polynomial fit");
5737 for(deg = 0; deg <= order; deg++)
5739 cpl_image *image = cpl_imagelist_get(*coeffs_ptr, deg);
5740 const double coeff = cpl_image_get_median(image);
5741 pcoeffs[deg] = coeff;
5743 name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", (
int)deg);
5744 name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", (
int)deg);
5745 assert(name_o1 != NULL);
5746 assert(name_o2 != NULL);
5747 skip_if(cpl_propertylist_append_double(linc_qclist, name_o1, coeff));
5748 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o1,
5749 DETMON_QC_LIN_COEF_C));
5752 skip_if(cpl_propertylist_append_double(linc_qclist, name_o2,
5753 cpl_image_get_stdev(image)));
5754 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o2,
5755 DETMON_QC_LIN_COEF_ERR_C));
5761 if(order == vsize - 1)
5763 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5764 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5766 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5767 DETMON_QC_ERRFIT_C));
5770 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5771 cpl_image_get_median(fiterror)));
5772 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5773 DETMON_QC_ERRFIT_C));
5777 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
5779 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
5780 DETMON_QC_COUNTS_MIN_C));
5781 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
5783 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
5784 DETMON_QC_COUNTS_MAX_C));
5785 skip_if(detmon_lg_lineff(pcoeffs,lint_qclist,detmon_lg_config.ref_level,
5786 detmon_lg_config.order));
5788 if (detmon_lg_config.exts >= 0)
5790 cpl_msg_info(cpl_func,
"Bad pixel detection");
5793 cpl_msg_info(cpl_func,
"Bad pixel detection"
5794 " for extension nb %d", which_ext);
5796 if(detmon_lg_config.pix2pix)
5800 nbpixs = detmon_compute_badpixmap(opt_nir, linear_nsets, linear_table,
5801 linearity_inputs, nbpixs, x,gaint_qclist, bpms_ptr);
5806 skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
5807 skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
5808 DETMON_QC_NUM_BPM_C));
5809 cpl_msg_info(cpl_func,
"stability=%g",detmon_lg_config.lamp_stability);
5810 if(detmon_lg_config.lamp_stability != 0.0)
5812 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
5813 detmon_lg_config.lamp_stability));
5814 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
5815 DETMON_QC_LAMP_STAB_C));
5818 if (!detmon_lg_config.wholechip && detmon_lg_config.pix2pix)
5820 detmon_lg_fits_coeffs_and_bpm2chip(coeffs_ptr,bpms_ptr);
5827 cpl_image_delete(fiterror);
5828 cpl_polynomial_delete(poly_linfit);
5832 return cpl_error_get_code();
5844static cpl_error_code
5845detmon_lg_lineff(
double * pcoeffs,
5846 cpl_propertylist * qclist,
5852 double residual, slope;
5855 cpl_polynomial * poly = cpl_polynomial_new(1);
5869 pcoeffs[0] -= ref_level;
5871 for (i = 2; i <= order; i++)
5874 for(j = 0; j < i; j++)
5876 pcoeffs[i] /= pcoeffs[1];
5882 for (deg = 0; deg <= order; deg++) {
5884 skip_if(cpl_polynomial_set_coeff(poly, °, pcoeffs[deg]));
5893 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
5895 if (slope <= 0.0 && residual >= 0.0) {
5896 cpl_msg_warning(cpl_func,
"Reference level (--ref_level) outside"
5897 " linearity range of the detector. Cannot compute"
5898 " linearity efficiency (QC.LINEFF).");
5903 cpl_error_code err = cpl_polynomial_solve_1d(poly, 0.0, &root, 1);
5908 if (err == CPL_ERROR_NONE)
5911 lineff = (root - ref_level) / ref_level;
5916 cpl_msg_warning(cpl_func,
5917 "Cannot compute linearity efficiency (QC.LINEFF)"
5918 "for the current combination "
5919 " of (--ref-level equal %d) and (--order equal %d) parameters. Try "
5920 "to decrease (--ref-level) value.", ref_level, order);
5923 cpl_msg_warning(cpl_func,
"DETMON_QC_LIN_EFF=%f",lineff );
5924 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
5926 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
5927 DETMON_QC_LIN_EFF_C));
5929 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
5931 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
5932 DETMON_QC_LIN_EFF_FLUX_C));
5936 cpl_polynomial_delete(poly);
5938 return cpl_error_get_code();
5949static cpl_error_code
5950detmon_lg_qc_ptc(
const cpl_table * gain_table,
5951 cpl_propertylist * qclist,
unsigned mode,
int rows_in_gain)
5954 cpl_polynomial *poly_fit = NULL;
5955 cpl_polynomial *poly_fit2 = NULL;
5957 const int nsets = rows_in_gain;
5959 cpl_vector *x = NULL;
5960 cpl_vector *y = NULL;
5962 cpl_errorstate prestate;
5964 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
5965 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
5967 x = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5969 y = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5971 skip_if(x == NULL || y == NULL);
5972 if (0 == detmon_lg_check_before_gain(x, y))
5976 cpl_vector_unwrap(x);
5980 cpl_vector_unwrap(y);
5982 return CPL_ERROR_NONE;
5985 poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
5986 skip_if(poly_fit == NULL);
5990 prestate = cpl_errorstate_get();
5991 coef = cpl_polynomial_get_coeff(poly_fit, &i);
5992 skip_if (!cpl_errorstate_is_equal(prestate) || coef==0);
5993 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
5994 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5995 DETMON_QC_CONAD_C));
5998 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
6000 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
6016 if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
6017 const cpl_vector *x2 =
6018 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT_CORR"));
6019 const cpl_vector *y2 =
6020 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
6022 if(x2 == NULL || y2 == NULL) {
6023 cpl_vector_unwrap((cpl_vector *)x2);
6024 cpl_vector_unwrap((cpl_vector *)y2);
6035 poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
6036 if(poly_fit2 == NULL) {
6037 cpl_vector_unwrap((cpl_vector *)x2);
6038 cpl_vector_unwrap((cpl_vector *)y2);
6040 cpl_msg_error(cpl_func,
"Error during polynomial fit, err[%s]", cpl_error_get_where());
6044 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
6045 cpl_vector_unwrap((cpl_vector *)x2);
6046 cpl_vector_unwrap((cpl_vector *)y2);
6047 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
6050 prestate = cpl_errorstate_get();
6051 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
6052 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
6053 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
6055 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
6057 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
6058 DETMON_QC_CONAD_CORR_C));
6060 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
6062 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
6063 DETMON_QC_GAIN_CORR_C));
6069 cpl_vector_unwrap(x);
6070 cpl_vector_unwrap(y);
6071 cpl_polynomial_delete(poly_fit);
6072 cpl_polynomial_delete(poly_fit2);
6074 return cpl_error_get_code();
6083static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y)
6085 const double TOLERANCE = 1e-37;
6086 double xmin = cpl_vector_get_min(x);
6087 double xmax = cpl_vector_get_max(x);
6088 double ymin = cpl_vector_get_min(y);
6089 double ymax = cpl_vector_get_max(y);
6090 double ystdev = cpl_vector_get_stdev(y);
6091 double xstdev = cpl_vector_get_stdev(x);
6093 if (fabs(xmax-xmin) < TOLERANCE &&
6094 fabs(ymax - ymin) < TOLERANCE &&
6095 xstdev < TOLERANCE &&
6098 cpl_msg_warning(cpl_func,
"An empty frame has been detected, linearity, coeffs, gain, FPN values will not be computed.");
6113static cpl_error_code
6114detmon_lg_qc_med(
const cpl_table * gain_table,
6115 cpl_propertylist * qclist,
int rows_in_gain)
6119 cpl_vector *x = NULL;
6120 cpl_vector *y = NULL;
6121 int check_result = 0;
6123 if (rows_in_gain) {};
6125 x = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
6126 y = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
6127 check_result = detmon_lg_check_before_gain(x, y);
6130 cpl_vector_unwrap(x);
6134 cpl_vector_unwrap(y);
6136 if (0 == check_result)
6138 return CPL_ERROR_NONE;
6141 gain=cpl_table_get_column_median(gain_table,
"GAIN");
6143 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
6145 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
6148 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
6149 cpl_table_get_column_stdev
6150 (gain_table,
"GAIN")));
6151 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
6152 DETMON_QC_GAIN_MSE_C));
6154 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
6155 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
6156 DETMON_QC_CONAD_C));
6159 gain=cpl_table_get_column_median(gain_table,
"GAIN_CORR");
6161 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
6163 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
6164 DETMON_QC_GAIN_CORR_C));
6167 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
6168 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
6169 DETMON_QC_CONAD_CORR_C));
6174 return cpl_error_get_code();
6188static cpl_error_code
6189detmon_lg_rescale(cpl_imagelist * to_rescale)
6192 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 0),
6193 detmon_lg_config.llx,
6194 detmon_lg_config.lly,
6195 detmon_lg_config.urx,
6196 detmon_lg_config.ury);
6198 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 1),
6199 detmon_lg_config.llx,
6200 detmon_lg_config.lly,
6201 detmon_lg_config.urx,
6202 detmon_lg_config.ury);
6206 if(fabs(med1 / med2 - 1) > 0.001) {
6208 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
6211 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
6217 return cpl_error_get_code();
6220static cpl_error_code
6221detmon_pair_extract_next(
const cpl_frameset * set,
6225 cpl_frameset ** pair,
6229 double dit_next = -100;
6230 cpl_size* selection;
6231 int nsets_extracted = 0;
6232 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6233 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6234 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6235 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6237 nsets_extracted = cpl_frameset_get_size(set);
6238 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6239 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6242 dit = dit_array[*next_element ];
6244 if (*next_element < nsets_extracted - 1)
6246 dit_next = dit_array[*next_element + 1 ];
6250 selection[iindex[*next_element] ] = 1;
6251 if (fabs(dit - dit_next) < tolerance)
6254 selection[iindex[*next_element + 1] ] = 1;
6259 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);
6263 cpl_frameset_delete(*pair);
6264 *pair = cpl_frameset_extract(set, selection, 1);
6267 cpl_free(selection);
6268 return cpl_error_get_code();
6271static cpl_error_code
6272detmon_single_extract_next(
const cpl_frameset * set,
6276 cpl_frameset ** pair)
6278 cpl_size* selection;
6279 int nsets_extracted = 0;
6280 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6281 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6282 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6283 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6285 nsets_extracted = cpl_frameset_get_size(set);
6286 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
6287 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
6290 selection[iindex[*next_element] ] = 1;
6293 cpl_frameset_delete(*pair);
6294 *pair = cpl_frameset_extract(set, selection, 1);
6296 cpl_free(selection);
6297 return cpl_error_get_code();
6395detmon_gain(
const cpl_imagelist * imlist_on,
6396 const cpl_imagelist * imlist_off,
6397 const cpl_vector * exptimes,
6398 const cpl_vector * ndit,
6408 cpl_propertylist * qclist,
6410 cpl_imagelist ** diff_imlist,
6411 cpl_imagelist ** autocorr_imlist)
6413 cpl_table * gain_table = NULL;
6414 cpl_imagelist * difflist = NULL;
6415 cpl_imagelist * autocorrlist = NULL;
6416 cpl_imagelist * c_onlist = NULL;
6417 cpl_imagelist * c_offlist = NULL;
6418 cpl_vector * diffdits = NULL;
6419 cpl_vector * diffndits = NULL;
6420 int rows_in_gain = 0;
6421 int ndiffdits, ndits;
6423 cpl_boolean opt_nir = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
6424 const char * method = mode & IRPLIB_GAIN_PTC ?
"PTC" :
"MED";
6426 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6427 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6428 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6429 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6432 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6433 skip_if(detmon_gain_table_create(gain_table, opt_nir));
6437 skip_if(detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,
6439 ndiffdits = cpl_vector_get_size(diffdits);
6441 ndits = cpl_vector_get_size(exptimes);
6444 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
6445 difflist = cpl_imagelist_new();
6446 autocorrlist = cpl_imagelist_new();
6449 if (mode & IRPLIB_GAIN_COLLAPSE) {
6450 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6451 c_offlist = cpl_imagelist_duplicate(imlist_off);
6452 skip_if(detmon_lg_rescale(c_offlist));
6454 c_offlist = (cpl_imagelist *) imlist_off;
6459 for (i = 0; i < ndiffdits; i++) {
6466 c_dit=cpl_vector_get(diffdits, i);
6469 c_ndit=(int)cpl_vector_get(diffndits, i);
6472 c_onlist = cpl_imagelist_new();
6475 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6476 c_offlist = cpl_imagelist_new();
6481 for(j = 0; j < ndits; j++) {
6482 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6492 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6493 const cpl_image * im =
6494 cpl_imagelist_get_const(imlist_on, j);
6495 im_on = cpl_image_duplicate(im);
6497 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6499 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6506 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6508 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6509 const cpl_image * im =
6510 cpl_imagelist_get_const(imlist_off, j);
6511 im_off = cpl_image_duplicate(im);
6514 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6516 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6523 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6524 skip_if (c_nons != c_noffs);
6527 skip_if (c_nons == 0 || c_nons % 2 != 0);
6530 if(mode & IRPLIB_GAIN_WITH_RESCALE) {
6531 skip_if(detmon_lg_rescale(c_onlist));
6532 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
6533 skip_if(detmon_lg_rescale(c_offlist));
6539 int rows_affected = 1;
6540 skip_if(detmon_gain_table_fill_row(gain_table,
6544 c_offlist, kappa, nclip,
6546 xshift, yshift, 1E10, i,
6547 mode, &rows_affected));
6552 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
6553 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6554 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6555 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6556 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6557 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6560 cpl_imagelist_unset(c_onlist, 0);
6562 cpl_imagelist_unset(c_onlist, 0);
6564 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6565 cpl_imagelist_unset(c_offlist, 0);
6567 cpl_imagelist_unset(c_offlist, 0);
6575 cpl_imagelist_delete(c_onlist);
6576 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
6577 cpl_imagelist_delete(c_offlist);
6581 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
6582 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
6583 DETMON_QC_METHOD_C));
6586 if (mode & IRPLIB_GAIN_PTC) {
6587 skip_if(detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
6589 skip_if(detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
6592 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
6593 double autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
6594 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
6596 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
6597 DETMON_QC_AUTOCORR_C));
6600 if (diff_imlist != NULL) *diff_imlist = difflist;
6601 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
6605 cpl_vector_delete(diffdits);
6606 cpl_vector_delete(diffndits);
6611static cpl_error_code
6612detmon_gain_table_create(cpl_table * gain_table,
6613 const cpl_boolean opt_nir)
6615 if (opt_nir == NIR) {
6616 skip_if(cpl_table_new_column(gain_table,
"DIT", CPL_TYPE_DOUBLE));
6617 skip_if(cpl_table_new_column(gain_table,
"NDIT", CPL_TYPE_INT));
6619 skip_if(cpl_table_new_column(gain_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6621 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON1", CPL_TYPE_DOUBLE));
6622 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON2", CPL_TYPE_DOUBLE));
6623 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF1", CPL_TYPE_DOUBLE));
6624 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF2", CPL_TYPE_DOUBLE));
6625 skip_if(cpl_table_new_column(gain_table,
"SIG_ON_DIF", CPL_TYPE_DOUBLE));
6626 skip_if(cpl_table_new_column(gain_table,
"SIG_OFF_DIF", CPL_TYPE_DOUBLE));
6627 skip_if(cpl_table_new_column(gain_table,
"GAIN", CPL_TYPE_DOUBLE));
6628 skip_if(cpl_table_new_column(gain_table,
"AUTOCORR", CPL_TYPE_DOUBLE));
6629 skip_if(cpl_table_new_column(gain_table,
"GAIN_CORR", CPL_TYPE_DOUBLE));
6630 skip_if(cpl_table_new_column(gain_table,
"ADU", CPL_TYPE_DOUBLE));
6631 skip_if(cpl_table_new_column(gain_table,
"X_FIT", CPL_TYPE_DOUBLE));
6632 skip_if(cpl_table_new_column(gain_table,
"X_FIT_CORR", CPL_TYPE_DOUBLE));
6633 skip_if(cpl_table_new_column(gain_table,
"Y_FIT", CPL_TYPE_DOUBLE));
6634 skip_if(cpl_table_new_column(gain_table,
"Y_FIT_CORR", CPL_TYPE_DOUBLE));
6635 skip_if(cpl_table_new_column(gain_table,
"FLAG", CPL_TYPE_INT));
6639 return cpl_error_get_code();
6642static cpl_error_code
6643detmon_lin_table_create(cpl_table * lin_table,
6644 const cpl_boolean opt_nir)
6646 if (opt_nir == NIR) {
6647 skip_if(cpl_table_new_column(lin_table,
"DIT", CPL_TYPE_DOUBLE));
6649 skip_if(cpl_table_new_column(lin_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6651 skip_if(cpl_table_new_column(lin_table,
"MED", CPL_TYPE_DOUBLE));
6652 skip_if(cpl_table_new_column(lin_table,
"MEAN", CPL_TYPE_DOUBLE));
6653 skip_if(cpl_table_new_column(lin_table,
"MED_DIT", CPL_TYPE_DOUBLE));
6654 skip_if(cpl_table_new_column(lin_table,
"MEAN_DIT", CPL_TYPE_DOUBLE));
6655 skip_if(cpl_table_new_column(lin_table,
"ADL", CPL_TYPE_DOUBLE));
6658 return cpl_error_get_code();
6662detmon_lg_find_dits(
const cpl_vector * exptimes,
6665 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6671 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
6675 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
6677 for (j = 0; j < ndits; j++) {
6678 if (fabs(cpl_vector_get(exptimes, i) -
6679 cpl_vector_get(dits, j)) > tolerance)
6682 if(ndiffs == ndits) {
6683 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
6688 cpl_vector_set_size(dits, ndits);
6696static cpl_error_code
6697detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
6698 const cpl_vector * vec_ndits,
6700 cpl_vector** diff_dits,
6701 cpl_vector** diff_ndits)
6709 * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6710 * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
6713 cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
6714 cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
6717 size=cpl_vector_get_size(exptimes);
6719 for(i = 1; i < size; i++) {
6721 for (j = 0; j < ndits; j++) {
6722 if (fabs(cpl_vector_get(exptimes, i) -
6723 cpl_vector_get(*diff_dits,j)) > tolerance)
6726 if(ndiffs == ndits) {
6727 cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
6728 cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
6733 cpl_vector_set_size(*diff_dits, ndits);
6734 cpl_vector_set_size(*diff_ndits, ndits);
6737 return cpl_error_get_code();
6827detmon_lin(
const cpl_imagelist * imlist_on,
6828 const cpl_imagelist * imlist_off,
6829 const cpl_vector * exptimes,
6839 cpl_propertylist * qclist,
6841 cpl_imagelist ** coeffs_cube,
6844 cpl_table * lin_table = NULL;
6845 cpl_imagelist * c_onlist = NULL;
6846 cpl_imagelist * c_offlist = NULL;
6847 cpl_vector * diffdits = NULL;
6848 cpl_imagelist * lin_inputs = NULL;
6849 cpl_polynomial * poly_linfit = NULL;
6850 cpl_image * fiterror = NULL;
6851 cpl_vector * vcoeffs = NULL;
6852 double * pcoeffs = NULL;
6853 int ndiffdits, ndits;
6855 cpl_boolean opt_nir = mode & IRPLIB_LIN_OPT ? OPT : NIR;
6856 const cpl_vector *x = NULL;
6857 const cpl_vector *y = NULL;
6859 const cpl_image * first = NULL;
6867 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6868 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6869 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6870 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6871 cpl_ensure(order > 0 , CPL_ERROR_ILLEGAL_INPUT, NULL);
6873 vcoeffs = cpl_vector_new(order + 1);
6874 pcoeffs = cpl_vector_get_data(vcoeffs);
6877 if (mode & IRPLIB_LIN_PIX2PIX) {
6878 cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
6879 cpl_ensure(bpm != NULL, CPL_ERROR_NULL_INPUT, NULL);
6880 lin_inputs = cpl_imagelist_new();
6884 lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6885 skip_if(detmon_lin_table_create(lin_table, opt_nir));
6889 diffdits = detmon_lg_find_dits(exptimes, tolerance);
6890 ndiffdits = cpl_vector_get_size(diffdits);
6892 ndits = cpl_vector_get_size(exptimes);
6922 if (mode & IRPLIB_LIN_COLLAPSE) {
6927 cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
6928 skip_if(collapse == NULL);
6930 c_offlist = cpl_imagelist_new();
6931 skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
6935 for (i = 0; i < ndiffdits; i++) {
6939 double c_dit = cpl_vector_get(diffdits, i);
6941 c_onlist = cpl_imagelist_new();
6944 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6945 c_offlist = cpl_imagelist_new();
6949 for(j = 0; j < ndits; j++) {
6950 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6960 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6961 const cpl_image * im =
6962 cpl_imagelist_get_const(imlist_on, j);
6963 im_on = cpl_image_duplicate(im);
6965 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6967 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6974 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6976 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6977 const cpl_image * im =
6978 cpl_imagelist_get_const(imlist_off, j);
6979 im_off = cpl_image_duplicate(im);
6982 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6984 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6991 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6992 skip_if (c_nons != c_noffs);
6995 skip_if (c_nons == 0 || c_nons % 2 != 0);
6998 if(mode & IRPLIB_LIN_WITH_RESCALE) {
6999 skip_if(detmon_lg_rescale(c_onlist));
7000 if (mode & IRPLIB_LIN_NO_COLLAPSE)
7001 skip_if(detmon_lg_rescale(c_offlist));
7008 skip_if(detmon_lin_table_fill_row(lin_table, c_dit,
7010 c_onlist, c_offlist,
7014 if (mode & IRPLIB_LIN_WITH_RESCALE) {
7015 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
7016 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
7017 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7018 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
7019 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
7022 cpl_imagelist_unset(c_onlist, 0);
7024 cpl_imagelist_unset(c_onlist, 0);
7026 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7027 cpl_imagelist_unset(c_offlist, 0);
7029 cpl_imagelist_unset(c_offlist, 0);
7037 cpl_imagelist_delete(c_onlist);
7038 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
7039 cpl_imagelist_delete(c_offlist);
7043 skip_if(detmon_add_adl_column(lin_table, opt_nir));
7045 if(!(mode & IRPLIB_LIN_PIX2PIX)) {
7048 y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7049 (
double *)cpl_table_get_data_double_const(lin_table,
7051 if (opt_nir == NIR) {
7052 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7053 (
double *)cpl_table_get_data_double_const(lin_table,
"DIT"));
7055 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7056 (
double *)cpl_table_get_data_double_const(lin_table,
"EXPTIME"));
7058 if(x == NULL || y == NULL) {
7059 cpl_vector_unwrap((cpl_vector *)x);
7060 cpl_vector_unwrap((cpl_vector *)y);
7070 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
7071 poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
7073 if(order == cpl_vector_get_size(x) - 1) {
7074 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7078 if(poly_linfit == NULL) {
7079 cpl_vector_unwrap((cpl_vector *)x);
7080 cpl_vector_unwrap((cpl_vector *)y);
7085 cpl_vector_unwrap((cpl_vector *)x);
7086 cpl_vector_unwrap((cpl_vector *)y);
7088 for(deg = 0; deg <= order; deg++) {
7089 const double coeff =
7090 cpl_polynomial_get_coeff(poly_linfit, °);
7092 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
7093 assert(name_o != NULL);
7094 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
7095 skip_if(cpl_propertylist_set_comment(qclist,name_o,
7096 DETMON_QC_LIN_COEF_C));
7098 pcoeffs[deg] = coeff;
7100 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
7101 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7102 DETMON_QC_ERRFIT_MSE_C));
7106 if (opt_nir == NIR) {
7107 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7108 (
double *)cpl_table_get_data_double_const(lin_table,
7111 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
7112 (
double *)cpl_table_get_data_double_const(lin_table,
7117 first = cpl_imagelist_get_const(lin_inputs, 0);
7118 sizex = cpl_image_get_size_x(first);
7119 sizey = cpl_image_get_size_y(first);
7121 vsize = cpl_vector_get_size(x);
7123 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
7126 cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
7127 order, FALSE, CPL_TYPE_FLOAT,
7130 cpl_vector_unwrap((cpl_vector*)x);
7131 irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
7132 "Failed polynomial fit");
7134 for(i = 0; i <= order; i++) {
7135 cpl_image *image = cpl_imagelist_get(*coeffs_cube, i);
7136 const double coeff = cpl_image_get_median(image);
7137 char * name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", i);
7138 char * name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", i);
7140 assert(name_o1 != NULL);
7141 assert(name_o2 != NULL);
7142 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
7143 skip_if(cpl_propertylist_set_comment(qclist,name_o1,
7144 DETMON_QC_LIN_COEF_C));
7147 skip_if(cpl_propertylist_append_double(qclist, name_o2,
7148 cpl_image_get_stdev(image)));
7149 skip_if(cpl_propertylist_set_comment(qclist,name_o2,
7150 DETMON_QC_LIN_COEF_ERR_C));
7155 if(order == vsize - 1) {
7156 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
7157 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7159 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7160 DETMON_QC_ERRFIT_C));
7164 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7165 cpl_image_get_median(fiterror)));
7166 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7167 DETMON_QC_ERRFIT_C));
7172 skip_if(detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
7174 if(mode & IRPLIB_LIN_PIX2PIX) {
7176 *bpm = detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
7177 skip_if(*bpm == NULL);
7178 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
7180 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
7181 DETMON_QC_NUM_BPM_C));
7186 cpl_vector_delete(diffdits);
7187 cpl_polynomial_delete(poly_linfit);
7188 cpl_imagelist_delete(lin_inputs);
7189 cpl_vector_delete(vcoeffs);
7190 cpl_image_delete(fiterror);
7220static cpl_error_code
7221detmon_lin_table_fill_row(cpl_table * lin_table,
double c_dit,
7222 cpl_imagelist * linearity_inputs,
7223 const cpl_imagelist * ons,
7224 const cpl_imagelist * offs,
7233 cpl_image * extracted=NULL;
7235 cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
7236 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
7237 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
7239 if (mode & IRPLIB_LIN_PIX2PIX) {
7240 cpl_msg_debug(cpl_func,
"checking linearity inputs");
7241 cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
7245 if (mode & IRPLIB_LIN_NIR) {
7246 cpl_table_set(lin_table,
"DIT", pos, c_dit);
7247 }
else if (mode & IRPLIB_LIN_OPT) {
7248 cpl_table_set(lin_table,
"EXPTIME", pos, c_dit);
7250 cpl_msg_error(cpl_func,
"Mandatory mode not given");
7254 const cpl_image * off2;
7255 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
7256 off2 = cpl_imagelist_get_const(offs, 0);
7258 off2 = cpl_imagelist_get_const(offs, 1);
7260 extracted = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
7261 cpl_imagelist_get_const(offs, 0),
7262 cpl_imagelist_get_const(ons, 1),
7264 llx, lly, urx, ury);
7265 cpl_ensure_code(extracted != NULL, cpl_error_get_code());
7269 double median = cpl_image_get_median(extracted);
7270 double mean= cpl_image_get_mean(extracted);
7271 cpl_table_set(lin_table,
"MED", pos, median);
7272 cpl_table_set(lin_table,
"MEAN", pos, mean);
7274 cpl_table_set(lin_table,
"MED_DIT", pos, median / c_dit);
7275 cpl_table_set(lin_table,
"MEAN_DIT", pos, mean / c_dit);
7279 if(mode & IRPLIB_LIN_PIX2PIX) {
7280 cpl_error_code error = cpl_imagelist_set(linearity_inputs, extracted,
7282 cpl_ensure_code(!error, error);
7284 cpl_image_delete(extracted);
7287 return cpl_error_get_code();
7290static double irplib_calculate_total_noise_smooth(
const cpl_image* pimage,
7291 int pattern_x,
int pattern_y)
7293 cpl_image * p_tmp_image = 0;
7294 cpl_image * psmooth_image = 0;
7296 cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
7298 p_tmp_image = cpl_image_duplicate(pimage);
7299 cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
7300 cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
7301 psmooth_image = cpl_image_divide_create(pimage,p_tmp_image);
7302 ret_noise = irplib_calculate_total_noise(psmooth_image);
7303 cpl_mask_delete(mask);
7304 cpl_image_delete(psmooth_image);
7305 cpl_image_delete(p_tmp_image);
7309static double irplib_calculate_total_noise(
const cpl_image* pimage)
7311 double total_noise = -1;
7312 unsigned long max_bin_size = 1E5;
7313 const double hstart = cpl_image_get_min(pimage);
7314 const double hrange = cpl_image_get_max(pimage) - hstart;
7315 const unsigned long nbins = max_bin_size;
7318 irplib_hist * phist = 0;
7319 phist = irplib_hist_new();
7322 irplib_hist_init(phist, nbins, hstart, hrange);
7323 err = irplib_hist_fill(phist, pimage);
7324 if (err == CPL_ERROR_NONE)
7332 unsigned long n_bins = irplib_hist_get_nbins(phist);
7333 double start = irplib_hist_get_start(phist);
7334 double bin_size = irplib_hist_get_bin_size(phist);
7335 cpl_vector* pdata_vector = cpl_vector_new(n_bins);
7336 cpl_vector* ppos_vector = cpl_vector_new(n_bins);
7337 cpl_table* ptable = cpl_table_new(n_bins);
7338 cpl_table_new_column(ptable,
"bin", CPL_TYPE_DOUBLE);
7339 cpl_table_new_column(ptable,
"value", CPL_TYPE_DOUBLE);
7340 for(i = 0; i < n_bins; i++)
7342 unsigned int value = irplib_hist_get_value(phist, i);
7343 double dvalue = (double)(value);
7344 cpl_vector_set(pdata_vector, i, dvalue);
7345 cpl_vector_set(ppos_vector, i, start + i * bin_size);
7347 cpl_table_set(ptable,
"bin", i, start + i * bin_size);
7348 cpl_table_set(ptable,
"value", i, dvalue);
7350 err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
7351 if (err == CPL_ERROR_NONE)
7353 cpl_msg_info(cpl_func,
"FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
7357 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed Gaussian Fit, err msg [%s]", cpl_error_get_message());
7360 cpl_table_delete(ptable);
7361 cpl_vector_delete(ppos_vector);
7362 cpl_vector_delete(pdata_vector);
7366 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
7369 irplib_hist_delete(phist);
7374static double irplib_compute_err(
double gain,
double ron,
double FA)
7376 double int_gain = (gain * gain - 1) / 12;
7381 return sqrt(ron * ron + FA / gain + int_gain);
7384static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain ,
7385 FPN_METHOD fpn_method,
int smooth_size,
double* mse)
7387 cpl_image* im_diff = 0;
7388 const cpl_image* im_f1 = f1;
7389 cpl_image* im_inrange1 = 0;
7398 cpl_msg_warning(cpl_func,
"gain[%f]<0", gain);
7399 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7406 im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
7407 im_f1 = im_inrange1;
7409 FA = cpl_image_get_median(im_f1);
7416 cpl_msg_info(cpl_func,
"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
7417 s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
7420 cpl_msg_info(cpl_func,
"HISTOGRAM method is used for FPN");
7421 s_tot = irplib_calculate_total_noise(im_f1);
7426 cpl_msg_warning(cpl_func,
"fpn_method is not defined");
7435 cpl_msg_warning(cpl_func,
"Median flux on sum of flats<0");
7436 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7441 if ((s_tot * s_tot - FA / gain) > 0)
7443 s_fpn = sqrt(s_tot * s_tot - FA / gain);
7444 sr_fpn = s_fpn / FA;
7445 *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
7449 cpl_msg_warning(cpl_func,
"s_tot * s_tot < FA / gain");
7450 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
7459 cpl_image_delete(im_diff);
7462 cpl_image_delete(im_inrange1);
7468static cpl_imagelist * irplib_load_fset_wrp(
const cpl_frameset * pframeset,
7469 cpl_type type ,
int whichext)
7473 return detmon_load_frameset_window(pframeset, type, 0, whichext,
7474 detmon_lg_config.llx,
7475 detmon_lg_config.lly,
7476 detmon_lg_config.urx,
7477 detmon_lg_config.ury,
7478 detmon_lg_config.nx,
7479 detmon_lg_config.ny);
7482static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset * pframeset,
7483 cpl_type type ,
int whichext)
7486 cpl_imagelist* offs = cpl_imagelist_new();
7487 detmon_lg_config.load_fset(pframeset, type, offs);
7492static cpl_error_code irplib_table_create_column(cpl_table* ptable,
7493 cpl_propertylist* plist)
7495 if (ptable && plist)
7497 int size = cpl_propertylist_get_size(plist);
7499 for (i = 0; i < size; i++)
7501 cpl_property* pprop = cpl_propertylist_get(plist,i);
7504 const char* pname = cpl_property_get_name(pprop);
7507 cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
7508 if (cpl_error_get_code() != CPL_ERROR_NONE)
7510 cpl_msg_warning(cpl_func,
"cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
7517 return cpl_error_get_code();
7520static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
7521 cpl_propertylist* plist,
int row)
7523 cpl_error_code err = CPL_ERROR_NONE;
7524 if (ptable && plist)
7526 int size = cpl_propertylist_get_size(plist);
7528 for (i = 0; i < size; i++)
7530 cpl_property* pprop = cpl_propertylist_get(plist,i);
7533 const char* pname = cpl_property_get_name(pprop);
7534 double value = cpl_property_get_double(pprop);
7537 cpl_table_set_double(ptable, pname, row, value);
7538 if (cpl_error_get_code() != CPL_ERROR_NONE)
7540 cpl_msg_warning(cpl_func,
"cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
7551cpl_error_code detmon_check_order(
const double *exptime,
int sz,
7552 double tolerance,
int order)
7569 }
while(fabs(exptime[i-1] - exptime[i]) < tolerance);
7570 }
while(i < sz - 1);
7572 if ( !( fabs(exptime[i-1] - exptime[i]) < tolerance ) ) nsets++;
7575 cpl_error_set_message(cpl_func,CPL_ERROR_INCOMPATIBLE_INPUT,
7576 "Not enough frames for the polynomial"
7577 " fitting. nsets = %d <= %d order",
7580 return cpl_error_get_code();
7583static cpl_error_code
7584detmon_lg_dfs_save_imagelist(
7585 cpl_frameset * frameset,
7586 const cpl_parameterlist * parlist,
7587 const cpl_frameset *usedframes,
7588 const cpl_imagelist *coeffs,
7589 const char *recipe_name,
7590 const cpl_propertylist *mypro_coeffscube,
7591 const char * package,
7592 const char * name_o)
7594 return(cpl_dfs_save_imagelist
7595 (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
7596 recipe_name, mypro_coeffscube, NULL, package,
7600static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos)
7602 const cpl_image* first = cpl_imagelist_get(imlist, 0);
7605 int x = cpl_image_get_size_x(first);
7606 int y = cpl_image_get_size_y(first);
7607 cpl_type type = cpl_image_get_type(first);
7608 cpl_image * blank = cpl_image_new(x, y, type);
7609 cpl_imagelist_set(imlist, blank, pos);
7614static cpl_error_code
7615detmon_lg_set_keyword_from_base_double(cpl_propertylist* pl,
7621 char* hkw = cpl_sprintf(
"%s %s", keyword_base, keyword_ext);
7622 char* hcm = cpl_sprintf(
"%s %s", comment_base, comment_ext);
7624 cpl_propertylist_append_double(pl, hkw, value);
7625 cpl_propertylist_set_comment(pl, hkw, hcm);
7630 return cpl_error_get_code();
7633static cpl_error_code
7634detmon_lg_set_keyword_from_insert_double(cpl_propertylist* pl,
7640 char* hkw = cpl_sprintf(keyword_base, keyword_ins);
7641 char* hcm = cpl_sprintf(comment_base, comment_ins);
7643 cpl_propertylist_append_double(pl, hkw, value);
7644 cpl_propertylist_set_comment(pl, hkw, hcm);
7649 return cpl_error_get_code();
7653detmon_lg_set_tag(cpl_frameset* set,
const char** tag_on,
const char** tag_off)
7658 ntag_old=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_OLD);
7659 ntag_new=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_NEW);
7661 *tag_on=DETMON_LG_ON_RAW_OLD;
7662 *tag_off=DETMON_LG_OFF_RAW_OLD;
7663 }
else if (ntag_new) {
7664 *tag_on=DETMON_LG_ON_RAW_NEW;
7665 *tag_off=DETMON_LG_OFF_RAW_NEW;
7667 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
7668 "Provide %s and %s (or %s and %s) input frames",
7669 DETMON_LG_ON_RAW_NEW,DETMON_LG_OFF_RAW_NEW,
7670 DETMON_LG_ON_RAW_OLD,DETMON_LG_OFF_RAW_OLD);
7674 return cpl_error_get_code();
7678detmon_lg_qc_params(cpl_table* linear_table, cpl_propertylist* lint_qclist,
7679 cpl_table* gain_table, cpl_propertylist* gaint_qclist,
7680 cpl_imagelist* coeffs, cpl_propertylist* linc_qclist,
7681 cpl_image* bpm, cpl_propertylist* bpm_qclist,
7682 const char * recipe_name) {
7684 char* qc_contam = NULL ;
7685 char* qc_contam_ref = cpl_sprintf(
"%s%01d", DETMON_QC_CONTAM, 5);
7687 cpl_msg_debug(cpl_func,
"This is where I'll write the QC parameters");
7689 if (linear_table != NULL && lint_qclist != NULL) {
7691 if (cpl_propertylist_has(
7692 lint_qclist, qc_contam_ref)) {
7693 for (
int i=1; i<5; ++i) {
7694 qc_contam = cpl_sprintf(
"%s%01d", DETMON_QC_CONTAM, i);
7695 if (cpl_propertylist_has(lint_qclist, qc_contam_ref) &&
7696 cpl_propertylist_has(lint_qclist, qc_contam)) {
7697 cpl_propertylist_append_double(
7698 lint_qclist, cpl_sprintf(DETMON_QC_CONTAMi_NORM, i),
7699 cpl_propertylist_get_double(lint_qclist, qc_contam) /
7700 cpl_propertylist_get_double(lint_qclist, qc_contam_ref));
7701 cpl_propertylist_set_comment(
7702 lint_qclist, cpl_sprintf(DETMON_QC_CONTAMi_NORM, i),
7703 cpl_sprintf(DETMON_QC_CONTAMi_NORM_C, i)
7710 cpl_free(qc_contam);
7711 cpl_free(qc_contam_ref);
7712 return cpl_error_get_code();
7716detmon_lg_qc_params_global_gain(
const char * recipe_name,
int nsets) {
7717 cpl_msg_debug(cpl_func,
"Going to update gain table for recipe %s, nsets=%d",
7718 recipe_name, nsets);
7721 cpl_error_code err ;
7723 fn = cpl_sprintf(
"%s_gain_table.fits", recipe_name) ;
7724 cpl_msg_debug(cpl_func,
"Will be modifying %s", fn) ;
7725 err = detmon_lg_qc_params_global_gain_update(fn, recipe_name);
7729 for (j=0; j<nsets; ++j) {
7730 fn = cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name, j);
7731 cpl_msg_debug(cpl_func,
"Will be modifying %s", fn);
7732 err = detmon_lg_qc_params_global_gain_update(fn, recipe_name);
7742detmon_lg_qc_params_global_gain_update(
const char * fn,
7743 const char * recipe_name) {
7744 cpl_msg_debug(cpl_func,
"Now updating %s", fn);
7746 cpl_propertylist* phu = cpl_propertylist_load(fn, 0);
7747 cpl_propertylist** ehus = NULL;
7748 cpl_table** gain_tables = NULL;
7749 cpl_array* gains = NULL;
7750 cpl_array* conads = NULL ;
7751 cpl_frame* fr = cpl_frame_new();
7754 cpl_frame_set_filename(fr, fn);
7755 int nexts = cpl_frame_get_nextensions(fr);
7756 cpl_msg_debug(cpl_func,
"Detected %d nexts", nexts);
7758 cpl_msg_warning(cpl_func,
"No extensions in %s, so no QC "
7759 "keywords to write", fn);
7760 cpl_msg_warning(cpl_func,
"Triggering goto cleanup");
7768 ehus = (cpl_propertylist**)cpl_malloc(nexts *
sizeof(cpl_propertylist*));
7769 gain_tables = (cpl_table**)cpl_malloc(nexts *
sizeof(cpl_table*));
7773 for (j=1; j <= nexts; j++) {
7774 cpl_msg_debug(cpl_func,
"Loading EHU %d", j);
7775 ehus[j-1] = cpl_propertylist_load(fn, j);
7776 gain_tables[j-1] = cpl_table_load(fn, j, 1);
7780 cpl_msg_debug(cpl_func,
"Populating data arrays");
7781 gains = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7782 conads = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7783 for (j=1; j <= nexts; j++) {
7784 cpl_msg_debug(cpl_func,
" %d", j);
7785 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_GAIN)) {
7786 cpl_array_set(gains, j-1,
7787 cpl_propertylist_get_double(ehus[j-1],
7790 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_CONAD)) {
7791 cpl_array_set(conads, j-1,
7792 cpl_propertylist_get_double(ehus[j-1],
7796 cpl_msg_debug(cpl_func,
"...populating complete!");
7798 cpl_propertylist_append_double(phu, DETMON_QC_GAIN_AVG,
7799 cpl_array_get_mean(gains));
7800 cpl_propertylist_set_comment(phu, DETMON_QC_GAIN_AVG,
7801 DETMON_QC_GAIN_AVG_C);
7803 cpl_propertylist_append_double(phu, DETMON_QC_GAIN_RMS,
7804 cpl_array_get_stdev(gains));
7805 cpl_propertylist_set_comment(phu, DETMON_QC_GAIN_RMS,
7806 DETMON_QC_GAIN_RMS_C);
7809 if (strcmp(recipe_name,
"detmon_opt_lg_mr") != 0) {
7812 cpl_propertylist_append_double(phu, DETMON_QC_CONAD_AVG,
7813 cpl_array_get_mean(conads));
7814 cpl_propertylist_set_comment(phu, DETMON_QC_CONAD_AVG,
7815 DETMON_QC_CONAD_AVG_C);
7817 cpl_propertylist_append_double(phu, DETMON_QC_CONAD_RMS,
7818 cpl_array_get_stdev(conads));
7819 cpl_propertylist_set_comment(phu, DETMON_QC_CONAD_RMS,
7820 DETMON_QC_CONAD_RMS_C);
7822 cpl_msg_debug(cpl_func,
"Calculations complete!");
7825 for (j=1; j<=nexts; ++j) {
7827 cpl_table_save(gain_tables[j-1], phu,
7828 ehus[j-1], fn, CPL_IO_CREATE);
7830 cpl_table_save(gain_tables[j-1], NULL,
7831 ehus[j-1], fn, CPL_IO_EXTEND);
7833 cpl_propertylist_delete(ehus[j-1]);
7834 cpl_table_delete(gain_tables[j-1]);
7841 cpl_msg_debug(cpl_func,
"Cleaning up...");
7842 cpl_propertylist_delete(phu);
7843 cpl_msg_debug(cpl_func,
" PHU gone");
7845 cpl_msg_debug(cpl_func,
" ehus gone");
7846 cpl_free(gain_tables);
7847 cpl_msg_debug(cpl_func,
" gain_tables gone");
7848 cpl_frame_delete(fr);
7849 cpl_msg_debug(cpl_func,
" fr gone");
7850 cpl_array_delete(conads);
7851 cpl_msg_debug(cpl_func,
" conads gone");
7852 cpl_array_delete(gains);
7853 cpl_msg_debug(cpl_func,
" gains gone");
7854 cpl_msg_debug(cpl_func,
"...done!");
7856 return cpl_error_get_code();
7861detmon_lg_qc_params_global_lin(
const char * recipe_name,
int nsets) {
7862 cpl_msg_debug(cpl_func,
"Going to update linearity table for "
7863 "recipe %s, nsets=%d",
7864 recipe_name, nsets);
7868 fn = cpl_sprintf(
"%s_linearity_table.fits", recipe_name) ;
7869 cpl_msg_debug(cpl_func,
"Will be modifying %s", fn, recipe_name) ;
7870 detmon_lg_qc_params_global_lin_update(fn, recipe_name);
7874 for (j=0; j<nsets; ++j) {
7875 fn = cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name, j);
7876 cpl_msg_debug(cpl_func,
"Will be modifying %s", fn);
7877 detmon_lg_qc_params_global_lin_update(fn, recipe_name);
7882 return cpl_error_get_code();
7887detmon_lg_qc_params_global_lin_update(
const char * fn,
7888 const char * recipe_name) {
7889 cpl_msg_debug(cpl_func,
"Now updating %s", fn);
7891 cpl_propertylist* phu = cpl_propertylist_load(fn, 0);
7892 cpl_propertylist** ehus = NULL;
7893 cpl_table** lin_tables = NULL;
7894 cpl_array* gain_err = NULL;
7895 cpl_array* counts_min = NULL;
7896 cpl_array* counts_max = NULL;
7897 cpl_array* lin_eff = NULL;
7898 cpl_array* lin_eff_flux = NULL;
7900 cpl_array** contams = (cpl_array**)cpl_malloc(5 *
sizeof(cpl_array*));
7901 for (contam=0; contam < 5; ++contam) {
7902 contams[contam] = NULL;
7904 cpl_frame* fr = cpl_frame_new();
7905 char * coeff_kw = NULL ;
7906 char * coeff_comm = NULL ;
7909 cpl_frame_set_filename(fr, fn);
7910 int nexts = cpl_frame_get_nextensions(fr);
7912 cpl_msg_warning(cpl_func,
"No extensions in %s, so no QC "
7913 "keywords to write", fn);
7921 cpl_msg_debug(cpl_func,
"Detected %d nexts", nexts);
7922 ehus = (cpl_propertylist**)cpl_malloc(nexts *
sizeof(cpl_propertylist*));
7923 lin_tables = (cpl_table**)cpl_malloc(nexts *
sizeof(cpl_table*));
7926 gain_err = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7927 counts_min = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7928 counts_max = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7929 lin_eff = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7930 lin_eff_flux = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7931 for (contam=0; contam < 5; ++contam) {
7932 contams[contam] = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
7934 for (j=1; j <= nexts; ++j) {
7935 cpl_msg_debug(cpl_func,
"Loading EHU %d", j);
7936 ehus[j-1] = cpl_propertylist_load(fn, j);
7937 lin_tables[j-1] = cpl_table_load(fn, j, 1);
7939 cpl_msg_debug(cpl_func,
"Doing non-CONTAM values");
7941 if (cpl_propertylist_has(ehus[j-1],
"ESO QC GAIN ERR")) {
7942 cpl_array_set_double(gain_err, j-1,
7943 cpl_propertylist_get_double(
7944 ehus[j-1],
"ESO QC GAIN ERR"));
7946 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_COUNTS_MIN)) {
7947 cpl_array_set_double(counts_min, j-1,
7948 cpl_propertylist_get_double(
7949 ehus[j-1], DETMON_QC_COUNTS_MIN));
7951 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_COUNTS_MAX)) {
7952 cpl_array_set_double(counts_max, j-1,
7953 cpl_propertylist_get_double(
7954 ehus[j-1], DETMON_QC_COUNTS_MAX));
7956 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_LIN_EFF)) {
7957 cpl_array_set_double(lin_eff, j-1,
7958 cpl_propertylist_get_double(
7959 ehus[j-1], DETMON_QC_LIN_EFF));
7961 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_LIN_EFF_FLUX)) {
7962 cpl_array_set_double(lin_eff_flux, j-1,
7963 cpl_propertylist_get_double(
7964 ehus[j-1], DETMON_QC_LIN_EFF_FLUX));
7967 cpl_msg_debug(cpl_func,
"Looping through contam values...");
7968 if (strcmp(recipe_name,
"detmon_opt_lg") == 0) {
7969 for (contam=0; contam<5 ; ++contam) {
7970 coeff_kw = cpl_sprintf(DETMON_QC_CONTAM
"%zd",
7972 if (cpl_propertylist_has(ehus[j-1],
7974 cpl_array_set_double(contams[contam], j-1,
7975 cpl_propertylist_get_double(
7985 cpl_msg_debug(cpl_func,
"Computing & setting global values...");
7987 cpl_propertylist_append_double(phu, DETMON_QC_GAIN_ERR_AVG,
7988 cpl_array_get_mean(gain_err));
7989 cpl_propertylist_set_comment(phu, DETMON_QC_GAIN_ERR_AVG,
7990 DETMON_QC_GAIN_ERR_AVG_C);
7992 cpl_propertylist_append_double(phu, DETMON_QC_GAIN_ERR_RMS,
7993 cpl_array_get_stdev(gain_err));
7994 cpl_propertylist_set_comment(phu, DETMON_QC_GAIN_ERR_RMS,
7995 DETMON_QC_GAIN_ERR_RMS_C);
7997 cpl_propertylist_append_double(phu, DETMON_QC_COUNTS_MIN_AVG,
7998 cpl_array_get_mean(counts_min));
7999 cpl_propertylist_set_comment(phu, DETMON_QC_COUNTS_MIN_AVG,
8000 DETMON_QC_COUNTS_MIN_AVG_C);
8002 cpl_propertylist_append_double(phu, DETMON_QC_COUNTS_MIN_RMS,
8003 cpl_array_get_stdev(counts_min));
8004 cpl_propertylist_set_comment(phu, DETMON_QC_COUNTS_MIN_RMS,
8005 DETMON_QC_COUNTS_MIN_RMS_C);
8007 cpl_propertylist_append_double(phu, DETMON_QC_COUNTS_MAX_AVG,
8008 cpl_array_get_mean(counts_max));
8009 cpl_propertylist_set_comment(phu, DETMON_QC_COUNTS_MAX_AVG,
8010 DETMON_QC_COUNTS_MAX_AVG_C);
8012 cpl_propertylist_append_double(phu, DETMON_QC_COUNTS_MAX_RMS,
8013 cpl_array_get_stdev(counts_max));
8014 cpl_propertylist_set_comment(phu, DETMON_QC_COUNTS_MAX_RMS,
8015 DETMON_QC_COUNTS_MAX_RMS_C);
8017 cpl_propertylist_append_double(phu, DETMON_QC_LIN_EFF_AVG,
8018 cpl_array_get_mean(lin_eff));
8019 cpl_propertylist_set_comment(phu, DETMON_QC_LIN_EFF_AVG,
8020 DETMON_QC_LIN_EFF_AVG_C);
8022 cpl_propertylist_append_double(phu, DETMON_QC_LIN_EFF_RMS,
8023 cpl_array_get_stdev(lin_eff));
8024 cpl_propertylist_set_comment(phu, DETMON_QC_LIN_EFF_RMS,
8025 DETMON_QC_LIN_EFF_RMS_C);
8026 if (strcmp(recipe_name,
"detmon_opt_lg") == 0) {
8027 cpl_msg_debug(cpl_func,
" Computing additional detmon_opt_lg values...");
8029 cpl_propertylist_append_double(phu, DETMON_QC_LIN_EFF_FLUX_AVG,
8030 cpl_array_get_mean(lin_eff_flux));
8031 cpl_propertylist_set_comment(phu, DETMON_QC_LIN_EFF_FLUX_AVG,
8032 DETMON_QC_LIN_EFF_FLUX_AVG_C);
8034 cpl_propertylist_append_double(phu, DETMON_QC_LIN_EFF_FLUX_RMS,
8035 cpl_array_get_stdev(lin_eff_flux));
8036 cpl_propertylist_set_comment(phu, DETMON_QC_LIN_EFF_FLUX_RMS,
8037 DETMON_QC_LIN_EFF_FLUX_RMS_C);
8040 for (contam=0 ; contam < 5; ++contam) {
8041 coeff_kw = cpl_sprintf(DETMON_QC_CONTAMi_AVG,
8043 coeff_comm = cpl_sprintf(DETMON_QC_CONTAMi_AVG_C,
8045 cpl_propertylist_append_double(phu,
8047 cpl_array_get_mean(contams[contam]));
8048 cpl_propertylist_set_comment(phu,
8052 cpl_free(coeff_comm);
8054 coeff_kw = cpl_sprintf(DETMON_QC_CONTAMi_RMS,
8056 coeff_comm = cpl_sprintf(DETMON_QC_CONTAMi_RMS_C,
8058 cpl_propertylist_append_double(phu,
8060 cpl_array_get_stdev(
8062 cpl_propertylist_set_comment(phu,
8066 cpl_free(coeff_comm);
8072 cpl_propertylist_save(phu, fn, CPL_IO_CREATE);
8073 for (j=1; j<=nexts; ++j) {
8075 cpl_table_save(lin_tables[j-1], phu,
8076 ehus[j-1], fn, CPL_IO_CREATE);
8078 cpl_table_save(lin_tables[j-1], NULL,
8079 ehus[j-1], fn, CPL_IO_EXTEND);
8081 cpl_propertylist_delete(ehus[j-1]);
8082 cpl_table_delete(lin_tables[j-1]);
8088 cpl_msg_debug(cpl_func,
"Going into cleanup...");
8089 for (contam=0 ; contam<5 ; ++contam) {
8090 cpl_array_delete(contams[contam]);
8091 cpl_msg_debug(cpl_func,
" contams array %d gone", contam);
8093 cpl_msg_debug(cpl_func,
" contams arrays gone");
8095 cpl_propertylist_delete(phu);
8096 cpl_msg_debug(cpl_func,
" ehus gone");
8097 cpl_free(lin_tables);
8098 cpl_msg_debug(cpl_func,
" lin_tables gone");
8100 cpl_msg_debug(cpl_func,
" contams gone");
8101 cpl_array_delete(gain_err);
8102 cpl_msg_debug(cpl_func,
" gain_err gone");
8103 cpl_array_delete(counts_min);
8104 cpl_msg_debug(cpl_func,
" counts_min gone");
8105 cpl_array_delete(counts_max);
8106 cpl_msg_debug(cpl_func,
" counts_max gone");
8107 cpl_array_delete(lin_eff);
8108 cpl_msg_debug(cpl_func,
" lin_eff gone");
8109 cpl_array_delete(lin_eff_flux);
8110 cpl_msg_debug(cpl_func,
" lin_eff_flux gone");
8111 cpl_frame_delete(fr);
8112 cpl_msg_debug(cpl_func,
" fr gone");
8113 cpl_msg_debug(cpl_func,
"...done!");
8115 return cpl_error_get_code();
8119detmon_lg_qc_params_global_bpm(
const char * recipe_name,
int nsets) {
8120 cpl_msg_debug(cpl_func,
"Going to update BPM image for "
8121 "recipe %s, nsets=%d",
8122 recipe_name, nsets);
8127 fn = cpl_sprintf(
"%s_bpm.fits", recipe_name) ;
8128 cpl_msg_debug(cpl_func,
"Will be modifying %s", fn) ;
8129 err = detmon_lg_qc_params_global_bpm_update(fn, recipe_name);
8133 for (j=0; j<nsets; ++j) {
8134 fn = cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, j);
8135 cpl_msg_debug(cpl_func,
"Will be modifying %s", fn);
8136 err = detmon_lg_qc_params_global_bpm_update(fn, recipe_name);
8145detmon_lg_qc_params_global_bpm_update(
const char * fn,
8146 const char * recipe_name) {
8147 cpl_msg_debug(cpl_func,
"Now updating %s", fn);
8149 cpl_propertylist* phu = cpl_propertylist_load(fn, 0);
8150 cpl_propertylist** ehus = NULL ;
8151 cpl_image** bpm_imgs = NULL ;
8152 cpl_array* num_bpm = NULL;
8153 cpl_frame* fr = cpl_frame_new();
8159 if ((strcmp(recipe_name,
"detmon_opt_lg_mr") == 0 ) ||
8160 (strcmp(recipe_name,
"detmon_ir_lg_mr")) == 0) {
8165 cpl_frame_set_filename(fr, fn);
8166 int nexts = cpl_frame_get_nextensions(fr);
8168 cpl_msg_warning(cpl_func,
"No extensions in %s, so no QC "
8169 "keywords to write", fn);
8177 cpl_msg_debug(cpl_func,
"Detected %d nexts", nexts);
8178 ehus = (cpl_propertylist**)cpl_malloc(nexts *
sizeof(cpl_propertylist*));
8179 bpm_imgs = (cpl_image**)cpl_malloc(nexts *
sizeof(cpl_image*));
8183 num_bpm = cpl_array_new(nexts, CPL_TYPE_INT);
8185 for (j=1; j<=nexts; ++j) {
8186 cpl_msg_debug(cpl_func,
"Loading ext %d", j);
8187 ehus[j-1] = cpl_propertylist_load(fn, j);
8188 bpm_imgs[j-1] = cpl_image_load(fn, CPL_BPP_IEEE_FLOAT, 0, j);
8189 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_NUM_BPM)) {
8190 cpl_array_set_int(num_bpm, j-1,
8191 cpl_propertylist_get_int(ehus[j-1],
8192 DETMON_QC_NUM_BPM));
8198 cpl_propertylist_append_double(phu, DETMON_QC_NUM_BPM_AVG,
8199 cpl_array_get_mean(num_bpm));
8200 cpl_propertylist_set_comment(phu, DETMON_QC_NUM_BPM_AVG,
8201 DETMON_QC_NUM_BPM_AVG_C);
8204 cpl_propertylist_save(phu, fn, CPL_IO_CREATE);
8205 for (j=1; j<=nexts; ++j) {
8206 cpl_image_save(bpm_imgs[j-1], fn, CPL_BPP_IEEE_FLOAT, ehus[j-1],
8208 cpl_propertylist_delete(ehus[j-1]);
8209 cpl_image_delete(bpm_imgs[j-1]);
8215 cpl_msg_debug(cpl_func,
"Doing cleanup");
8217 cpl_propertylist_delete(phu);
8218 cpl_msg_debug(cpl_func,
" ehus gone");
8220 cpl_msg_debug(cpl_func,
" bpm_imgs gone");
8221 cpl_array_delete(num_bpm);
8222 cpl_msg_debug(cpl_func,
" num_bpm gone");
8223 cpl_frame_delete(fr);
8224 cpl_msg_debug(cpl_func,
" fr gone");
8225 cpl_msg_debug(cpl_func,
"...done!");
8227 return cpl_error_get_code();
8232detmon_lg_qc_params_global_coeffs(
const char * recipe_name,
int nsets) {
8233 cpl_msg_debug(cpl_func,
"Going to update coeffs image for "
8234 "recipe %s, nsets=%d",
8235 recipe_name, nsets);
8237 cpl_error_code err = CPL_ERROR_NONE;
8240 fn = cpl_sprintf(
"%s_coeffs_cube.fits", recipe_name);
8241 cpl_msg_debug(cpl_func,
"Will be modifying %s", fn) ;
8242 err = detmon_lg_qc_params_global_coeffs_update(fn, recipe_name);
8246 for (j=0; j<nsets; ++j) {
8247 fn = cpl_sprintf(
"%s_coeffs_cube_set%02d.fits",
8249 cpl_msg_debug(cpl_func,
"Will be modifying %s", fn);
8250 err = detmon_lg_qc_params_global_coeffs_update(fn, recipe_name);
8259detmon_lg_qc_params_global_coeffs_update(
const char * fn,
8260 const char * recipe_name) {
8261 cpl_msg_debug(cpl_func,
"Now updating %s", fn);
8263 cpl_propertylist* phu = cpl_propertylist_load(fn, 0);
8264 cpl_propertylist** ehus = NULL;
8265 cpl_imagelist** coeff_cubes = NULL;
8266 cpl_frame* fr = NULL;
8267 cpl_array* lin_coeff = NULL;
8268 cpl_array* lin_coeff_err = NULL;
8269 cpl_array* errfit = NULL;
8270 char* coeff_kw = NULL ;
8271 char* coeff_kw_err = NULL ;
8272 char* coeff_str = NULL ;
8275 fr = cpl_frame_new();
8276 cpl_frame_set_filename(fr, fn);
8277 int nexts = cpl_frame_get_nextensions(fr);
8279 cpl_msg_warning(cpl_func,
"No extensions in %s, so no QC "
8280 "keywords to write", fn);
8289 if ((strcmp(recipe_name,
"detmon_opt_lg_mr") == 0 ) ||
8290 (strcmp(recipe_name,
"detmon_ir_lg_mr")) == 0) {
8291 cpl_msg_debug(cpl_func,
"Skipping %s for recipe %s",
8292 cpl_func, recipe_name);
8296 cpl_msg_debug(cpl_func,
"Detected %d nexts", nexts);
8297 ehus = (cpl_propertylist**)cpl_malloc(nexts *
sizeof(cpl_propertylist*));
8298 coeff_cubes = (cpl_imagelist**)cpl_malloc(nexts *
sizeof(cpl_imagelist*));
8299 cpl_msg_debug(cpl_func,
"Malloc'd data structures for eventual re-write");
8302 int j, coeff, coeff_max ;
8304 for (j=1; j<=nexts; ++j) {
8305 ehus[j-1] = cpl_propertylist_load(fn, j);
8307 cpl_msg_debug(__func__,
"Loaded extension headers");
8310 cpl_msg_debug(__func__,
"Creating lin_coeff and errfit arrays...");
8311 lin_coeff = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
8312 lin_coeff_err = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
8313 errfit = cpl_array_new(nexts, CPL_TYPE_DOUBLE);
8314 cpl_msg_debug(__func__,
"...done!");
8316 if (strcmp(recipe_name,
"detmon_ir_lg") == 0) {
8319 cpl_msg_debug(cpl_func,
"Populating errfit arrays");
8320 for (j=1; j<=nexts; ++j) {
8321 if (cpl_propertylist_has(ehus[j-1], DETMON_QC_ERRFIT)) {
8322 cpl_array_set_double(
8324 cpl_propertylist_get_double(ehus[j-1],
8329 cpl_msg_debug(cpl_func,
"Setting keywords with new funcs");
8330 detmon_lg_set_keyword_from_base_double(phu,
8331 DETMON_QC_ERRFIT,
"AVG",
8334 cpl_array_get_mean(errfit));
8336 detmon_lg_set_keyword_from_base_double(phu,
8337 DETMON_QC_ERRFIT,
"RMS",
8340 cpl_array_get_stdev(errfit));
8346 for (coeff = 0 ; coeff < coeff_max + 1 ; ++coeff) {
8347 cpl_msg_debug(cpl_func,
"Forming coeff keyword %d", coeff);
8348 coeff_kw = cpl_sprintf(
"ESO QC LIN COEF%d", coeff);
8349 coeff_kw_err = cpl_sprintf(
"ESO QC LIN COEF%d ERR",
8351 coeff_str = cpl_sprintf(
"%d", coeff);
8354 cpl_msg_debug(cpl_func,
"Reading in the coeff values");
8355 for (j=1; j<=nexts; ++j) {
8357 if (cpl_propertylist_has(ehus[j-1],
8359 cpl_array_set_double(
8362 cpl_propertylist_get_double(
8366 cpl_msg_debug(cpl_func,
"Added value %f to lin_coeff in pos %d",
8367 cpl_propertylist_get_double(
8372 if (cpl_propertylist_has(ehus[j-1],
8374 cpl_array_set_double(
8376 cpl_propertylist_get_double(
8381 cpl_msg_debug(__func__,
"Insertions complete! (%d)", coeff);
8386 cpl_msg_debug(cpl_func,
"Writing back header keywords for %d", coeff);
8388 if (cpl_array_count_invalid(lin_coeff) < (cpl_size)nexts) {
8389 detmon_lg_set_keyword_from_insert_double(
8391 DETMON_QC_LIN_COEFF_AVG, coeff_str,
8392 DETMON_QC_LIN_COEFF_AVG_C, coeff_str,
8393 cpl_array_get_mean(lin_coeff)
8397 detmon_lg_set_keyword_from_insert_double(
8399 DETMON_QC_LIN_COEFF_RMS, coeff_str,
8400 DETMON_QC_LIN_COEFF_RMS_C, coeff_str,
8401 cpl_array_get_stdev(lin_coeff)
8405 if (cpl_array_count_invalid(lin_coeff_err) < (cpl_size)nexts) {
8407 detmon_lg_set_keyword_from_insert_double(
8409 DETMON_QC_LIN_COEFF_ERR_AVG, coeff_str,
8410 DETMON_QC_LIN_COEFF_ERR_AVG_C, coeff_str,
8411 cpl_array_get_mean(lin_coeff_err)
8415 detmon_lg_set_keyword_from_insert_double(
8417 DETMON_QC_LIN_COEFF_ERR_RMS, coeff_str,
8418 DETMON_QC_LIN_COEFF_ERR_RMS_C, coeff_str,
8419 cpl_array_get_stdev(lin_coeff_err)
8423 cpl_msg_debug(__func__,
"Data write complete! (%d)", coeff);
8426 cpl_array_fill_window_invalid(lin_coeff, 0, nexts);
8427 cpl_array_fill_window_invalid(lin_coeff_err, 0, nexts);
8428 cpl_msg_debug(__func__,
"Arrays reset! (%d)", coeff);
8431 cpl_msg_debug(cpl_func,
"Purging the coeff keywords");
8433 cpl_free(coeff_kw_err);
8434 cpl_free(coeff_str);
8436 coeff_kw_err = NULL ;
8443 for (j=1; j<=nexts; ++j) {
8444 coeff_cubes[j-1] = cpl_imagelist_load(fn, CPL_BPP_IEEE_FLOAT, j);
8446 cpl_propertylist_save(phu, fn, CPL_IO_CREATE);
8447 for (j=1; j<=nexts; ++j) {
8448 cpl_imagelist_save(coeff_cubes[j-1], fn, CPL_BPP_IEEE_FLOAT, ehus[j-1],
8451 cpl_propertylist_delete(ehus[j-1]);
8452 cpl_imagelist_delete(coeff_cubes[j-1]);
8454 cpl_msg_debug(__func__,
"Removed all file data in memory");
8458 cpl_msg_debug(cpl_func,
"Doing cleanup...");
8460 cpl_msg_debug(cpl_func,
" ehus gone");
8461 cpl_propertylist_delete(phu);
8462 cpl_msg_debug(cpl_func,
" phus gone");
8463 cpl_free(coeff_cubes);
8464 cpl_msg_debug(cpl_func,
" coeff_cubes gone");
8465 cpl_frame_delete(fr);
8466 cpl_msg_debug(cpl_func,
" fr gone");
8467 cpl_array_delete(lin_coeff);
8468 cpl_msg_debug(cpl_func,
" lin_coeff gone");
8469 cpl_array_delete(lin_coeff_err);
8470 cpl_msg_debug(cpl_func,
" lin_coeff_err gone");
8471 cpl_array_delete(errfit);
8472 cpl_msg_debug(cpl_func,
" errfit gone");
8473 cpl_msg_debug(cpl_func,
"...done!");
8474 return cpl_error_get_code();
8478detmon_lg_qc_set_kw_from_table_column(cpl_table* table,
8479 const char * column,
8481 cpl_propertylist* header,
8483 const char * kw_comment) {
8485 if (strcmp(op,
"mean") == 0) {
8486 value = cpl_table_get_column_mean(table, column);
8487 }
else if (strcmp(op,
"stdev") == 0) {
8488 value = cpl_table_get_column_stdev(table, column);
8490 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
8491 return cpl_error_get_code();
8494 cpl_propertylist_append_double(header, kw, value);
8495 if (kw_comment != NULL) {
8496 cpl_propertylist_set_comment(header, kw, kw_comment);
8498 return cpl_error_get_code();