42 #include "detmon_utils.h"
43 #include "detmon_lg.h"
44 #include "detmon_lg_impl.h"
45 #include "detmon_dfs.h"
47 #include "irplib_ksigma_clip.h"
48 #include "irplib_utils.h"
49 #include "irplib_hist.h"
73 typedef enum _FPN_METHOD FPN_METHOD;
113 cpl_boolean wholechip;
114 cpl_boolean autocorr;
115 cpl_boolean intermediate;
116 cpl_boolean collapse;
123 const char * pafname;
128 double lamp_stability;
131 int (* load_fset) (
const cpl_frameset *, cpl_type, cpl_imagelist *);
132 cpl_imagelist * (* load_fset_wrp) (
const cpl_frameset *, cpl_type, int);
133 FPN_METHOD fpn_method;
135 double saturation_limit;
136 cpl_boolean split_coeffs;
146 static cpl_error_code
147 detmon_lg_retrieve_parlist(
const char *,
148 const char *,
const cpl_parameterlist *,
152 static cpl_error_code
153 detmon_lg_split_onoff(
const cpl_frameset *,
156 const char *,
const char * );
158 static cpl_error_code
159 detmon_lg_reduce(
const cpl_frameset *,
160 const cpl_frameset *,
161 int* index_on,
int* index_off,
162 double* exptime_on,
double* exptime_off,
163 int *next_index_on,
int* next_index_off,
174 int (* load_fset) (
const cpl_frameset *,
177 const cpl_boolean,
int);
179 static cpl_error_code
180 detmon_lin_table_fill_row(cpl_table *,
double,
182 const cpl_imagelist *,
183 const cpl_imagelist *,
189 static cpl_error_code
190 detmon_gain_table_fill_row(cpl_table * gain_table,
191 double c_dit,
int c_ndit,
192 cpl_imagelist * autocorr_images,
193 cpl_imagelist * diff_flats,
194 const cpl_imagelist * ons,
195 const cpl_imagelist * offs,
196 double kappa,
int nclip,
197 int llx,
int lly,
int urx,
int ury,
199 double saturation_limit,
200 const int pos,
unsigned mode,
int* rows_affected);
202 static cpl_error_code
203 detmon_lg_save(
const cpl_parameterlist *,
208 const cpl_propertylist *,
209 const cpl_propertylist *,
210 const cpl_propertylist *,
211 const cpl_propertylist *,
212 const cpl_propertylist *,
213 const cpl_propertylist *,
225 const int,
const int,
const cpl_frameset *,
228 static cpl_error_code
229 detmon_lg_qc_ptc(
const cpl_table *,
230 cpl_propertylist *,
unsigned,
int);
232 static cpl_error_code
233 detmon_lg_qc_med(
const cpl_table *,
234 cpl_propertylist *,
int);
238 irplib_pfits_get_dit(
const cpl_propertylist *);
241 irplib_pfits_get_dit_opt(
const cpl_propertylist *);
243 irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
244 const char* prop_name);
246 static cpl_image * detmon_bpixs(
const cpl_imagelist *,
247 cpl_boolean,
const double,
int *);
250 detmon_autocorr_factor(
const cpl_image *,
251 cpl_image **,
int,
int);
255 static cpl_error_code
256 detmon_opt_contamination(
const cpl_imagelist *,
257 const cpl_imagelist *,
258 unsigned mode, cpl_propertylist *);
261 detmon_opt_lampcr(cpl_frameset *,
int);
265 detmon_lg_dfs_set_groups(cpl_frameset *,
const char *,
const char *);
267 static cpl_error_code
268 detmon_lg_reduce_all(
const cpl_table *,
275 const cpl_imagelist *,
276 const cpl_table *,
int, cpl_boolean);
278 static cpl_error_code
279 detmon_lg_check_defaults(
const cpl_image *);
281 static cpl_error_code
282 detmon_lg_rescale(cpl_imagelist *);
284 static cpl_error_code
285 detmon_lg_reduce_init(cpl_table *,
291 static cpl_error_code
292 detmon_add_adl_column(cpl_table *, cpl_boolean);
294 static cpl_error_code
295 detmon_lg_lamp_stab(
const cpl_frameset *,
296 const cpl_frameset *,
300 static cpl_error_code
301 detmon_lg_reduce_dit(
const cpl_frameset * set_on,
302 int* index_on,
double* exptime_on,
305 const cpl_frameset * set_off,
306 int * index_off,
double* exptime_off,
307 int* next_on,
int* next_off,
308 cpl_table * linear_table,
309 cpl_table * gain_table,
310 cpl_imagelist * linearity_inputs,
311 cpl_propertylist * qclist,
313 cpl_imagelist * autocorr_images,
314 cpl_imagelist * diff_flats,
315 cpl_imagelist * opt_offs,
317 int * rows_affected);
319 static cpl_error_code
320 detmon_lg_core(cpl_frameset * cur_fset_on,
321 cpl_frameset * cur_fset_off,
325 double * exptime_off,
328 const char * recipe_name,
329 const char * pipeline_name,
330 const char * pafregexp,
331 const cpl_propertylist * pro_lintbl,
332 const cpl_propertylist * pro_gaintbl,
333 const cpl_propertylist * pro_coeffscube,
334 const cpl_propertylist * pro_bpm,
335 const cpl_propertylist * pro_corr,
336 const cpl_propertylist * pro_diff,
337 const char * package,
338 int (* load_fset) (
const cpl_frameset *,
341 int nsets, cpl_boolean opt_nir,
342 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
343 cpl_frameset * cur_fset);
345 static cpl_error_code
346 detmon_lg_lineff(
double *, cpl_propertylist *,
int,
int);
353 static cpl_error_code
354 detmon_gain_table_create(cpl_table *,
358 static cpl_error_code
359 detmon_lin_table_create(cpl_table *,
363 detmon_lg_find_dits(
const cpl_vector *,
366 static cpl_error_code
367 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
368 const cpl_vector * vec_ndits,
370 cpl_vector** diff_dits,
371 cpl_vector** diff_ndits);
373 static cpl_error_code
374 detmon_fpn_compute(
const cpl_frameset *set_on,
377 cpl_propertylist *lint_qclist,
384 FPN_METHOD fpn_method,
386 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain,
387 FPN_METHOD fpn_method,
int,
double* mse);
388 static double irplib_calculate_total_noise(
const cpl_image* pimage);
390 static cpl_imagelist* irplib_load_fset_wrp(
const cpl_frameset *,
391 cpl_type,
int whichext);
392 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset *,
395 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
396 cpl_propertylist* plist);
397 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
398 cpl_propertylist* plist,
401 static cpl_error_code
402 detmon_pair_extract_next(
const cpl_frameset *
set,
408 cpl_frameset ** pair,
410 static cpl_error_code
411 detmon_single_extract_next(
const cpl_frameset *
set,
415 cpl_frameset ** pair);
422 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code);
423 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos);
424 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y);
433 static int irplib_pfits_get_ndit(
const cpl_propertylist * plist)
435 return cpl_propertylist_get_int(plist,
"ESO DET NDIT");
478 static cpl_error_code
479 detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
482 const char * tag_off,
483 const char * recipe_name,
484 const char * pipeline_name,
485 const char * pafregexp,
486 const cpl_propertylist * pro_lintbl,
487 const cpl_propertylist * pro_gaintbl,
488 const cpl_propertylist * pro_coeffscube,
489 const cpl_propertylist * pro_bpm,
490 const cpl_propertylist * pro_corr,
491 const cpl_propertylist * pro_diff,
492 const char * package,
494 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
495 const cpl_boolean opt_nir,
496 const cpl_parameterlist * parlist,
499 static double irplib_compute_err(
double gain,
double ron,
double photon_noise);
501 static cpl_error_code
502 detmon_lg_dfs_save_imagelist(cpl_frameset * frameset,
503 const cpl_parameterlist * parlist,
504 const cpl_frameset *usedframes,
505 const cpl_imagelist *coeffs,
506 const char *recipe_name,
507 const cpl_propertylist *mypro_coeffscube,
508 const char * package,
509 const char * name_o);
512 static void irplib_free(
char** pointer){
514 if(pointer && *pointer) {
520 static cpl_error_code
521 detmon_lg_reduce_set(
int i, cpl_frameset * frameset,
int nsets,
523 const char * tag_off,
524 const char * recipe_name,
525 const char * pipeline_name,
526 const char * pafregexp,
527 const cpl_propertylist * pro_lintbl,
528 const cpl_propertylist * pro_gaintbl,
529 const cpl_propertylist * pro_coeffscube,
530 const cpl_propertylist * pro_bpm,
531 const cpl_propertylist * pro_corr,
532 const cpl_propertylist * pro_diff,
533 const char * package,
535 (
const cpl_frameset *, cpl_type, cpl_imagelist *),
536 const cpl_boolean opt_nir,
537 const cpl_parameterlist * parlist,
542 int nexts = detmon_lg_config.nb_extensions;
544 double* exptime_on = 0;
545 double* exptime_off = 0;
548 cpl_frameset * cur_fset = NULL;
549 cpl_frameset* cur_fset_on = 0;
550 cpl_frameset* cur_fset_off = 0;
555 cpl_frameset_duplicate(frameset) : cpl_frameset_extract(frameset, selection, i);
558 skip_if(cur_fset == NULL);
561 cur_fset_on = cpl_frameset_new();
562 cur_fset_off = cpl_frameset_new();
563 cpl_msg_info(cpl_func,
"Splitting into ON and OFF sub-framesets");
564 skip_if (detmon_lg_split_onoff(cur_fset,
565 cur_fset_on, cur_fset_off,
567 if (cpl_frameset_get_size(cur_fset_on) == 0)
569 cpl_msg_error(cpl_func,
"No lamp frames in input");
573 if (cpl_frameset_get_size(cur_fset_off) == 0)
575 cpl_msg_error(cpl_func,
"No dark / bias frames in input");
578 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));
586 exptime_on = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_on));
587 exptime_off = cpl_malloc(
sizeof(
double)*cpl_frameset_get_size(cur_fset_off));
589 index_on = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_on));
590 index_off = cpl_malloc(
sizeof(
int)*cpl_frameset_get_size(cur_fset_off));
591 irplib_frameset_sort(cur_fset_on, index_on, exptime_on);
592 irplib_frameset_sort(cur_fset_off, index_off, exptime_off);
605 skip_if(detmon_check_order(exptime_on, cpl_frameset_get_size(cur_fset_on), detmon_lg_config.tolerance, detmon_lg_config.order));
607 if(detmon_lg_config.exts >= 0)
615 if (detmon_lg_config.lamp_ok) {
616 skip_if(detmon_opt_lampcr(cur_fset, 0));
619 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
624 detmon_lg_config.exts,
626 recipe_name, pipeline_name, pafregexp,
627 pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff,
628 package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
630 for(j = 1; j <= nexts; j++) {
637 if (detmon_lg_config.lamp_ok) {
638 skip_if(detmon_opt_lampcr(cur_fset, j));
642 skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
647 j, i, recipe_name, pipeline_name,pafregexp, pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff, package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
652 cpl_frameset_delete(cur_fset);
653 cpl_frameset_delete(cur_fset_on);
654 cpl_frameset_delete(cur_fset_off);
657 cpl_free(exptime_on);
658 cpl_free(exptime_off);
659 return cpl_error_get_code();
737 detmon_lg(cpl_frameset * frameset,
738 const cpl_parameterlist * parlist,
740 const char * tag_off,
741 const char * recipe_name,
742 const char * pipeline_name,
743 const char * pafregexp,
744 const cpl_propertylist * pro_lintbl,
745 const cpl_propertylist * pro_gaintbl,
746 const cpl_propertylist * pro_coeffscube,
747 const cpl_propertylist * pro_bpm,
748 const cpl_propertylist * pro_corr,
749 const cpl_propertylist * pro_diff,
750 const char * package,
751 int (* compare) (
const cpl_frame *,
753 int (* load_fset) (
const cpl_frameset *,
756 const cpl_boolean opt_nir)
758 cpl_errorstate cleanstate = cpl_errorstate_get();
760 cpl_size * selection = NULL;
761 cpl_frame * first = NULL;
762 cpl_image * reference = NULL;
769 cpl_frameset * cur_fset = NULL;
770 cpl_frameset * cur_fset_on = NULL;
771 cpl_frameset * cur_fset_off = NULL;
774 cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
775 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
776 cpl_ensure_code(tag_on != NULL, CPL_ERROR_NULL_INPUT);
777 cpl_ensure_code(tag_off != NULL, CPL_ERROR_NULL_INPUT);
778 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
779 cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
780 cpl_ensure_code(pro_lintbl != NULL, CPL_ERROR_NULL_INPUT);
781 cpl_ensure_code(pro_gaintbl != NULL, CPL_ERROR_NULL_INPUT);
782 cpl_ensure_code(pro_coeffscube != NULL, CPL_ERROR_NULL_INPUT);
783 cpl_ensure_code(pro_bpm != NULL, CPL_ERROR_NULL_INPUT);
784 cpl_ensure_code(pro_corr != NULL, CPL_ERROR_NULL_INPUT);
785 cpl_ensure_code(pro_diff != NULL, CPL_ERROR_NULL_INPUT);
786 cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
788 cpl_msg_info(cpl_func,
"frameset size [%" CPL_SIZE_FORMAT
"]", cpl_frameset_get_size(frameset));
791 skip_if (detmon_lg_dfs_set_groups(frameset, tag_on, tag_off));
798 skip_if (detmon_lg_retrieve_parlist(pipeline_name, recipe_name,
806 first = cpl_frameset_get_first(frameset);
807 irplib_ensure (first != NULL, CPL_ERROR_ILLEGAL_INPUT,
"Empty data set! Provide %s and %s input frames",tag_on,tag_off);
809 detmon_lg_config.load_fset = load_fset;
810 detmon_lg_config.load_fset_wrp = load_fset ? irplib_load_fset_wrp_ext : irplib_load_fset_wrp;
813 detmon_lg_config.nb_extensions = 1;
814 if (detmon_lg_config.exts < 0) {
816 detmon_lg_config.nb_extensions = cpl_frame_get_nextensions(first);
817 while (reference == NULL && i <= detmon_lg_config.nb_extensions) {
818 reference = cpl_image_load(cpl_frame_get_filename(first),
819 CPL_TYPE_FLOAT, 0, i);
820 if (reference == NULL) {
821 cpl_msg_warning(cpl_func,
"Extension %d empty, skipping", i);
822 cpl_errorstate_set(cleanstate);
826 cpl_errorstate_set(cleanstate);
827 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
828 "No data found in any extension");
829 cpl_msg_info(cpl_func,
"Using extension %d as reference", i - 1);
831 if (load_fset != NULL) {
832 cpl_frameset *
new = cpl_frameset_new();
833 cpl_imagelist * p = cpl_imagelist_new();
834 cpl_frameset_insert(
new, cpl_frame_duplicate(first));
835 (*load_fset)(
new, CPL_TYPE_FLOAT, p);
836 reference = cpl_image_duplicate(cpl_imagelist_get(p, 0));
837 cpl_imagelist_delete(p);
838 cpl_frameset_delete(
new);
840 cpl_msg_info(cpl_func,
"name=%s",cpl_frame_get_filename(first));
841 reference = cpl_image_load(cpl_frame_get_filename(first),
842 CPL_TYPE_FLOAT, 0, detmon_lg_config.exts);
844 cpl_errorstate_set(cleanstate);
845 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
846 "No data found in requested extension %d",
847 detmon_lg_config.exts);
849 skip_if (reference == NULL);
851 skip_if (detmon_lg_check_defaults(reference));
860 if (compare == NULL) {
863 cpl_msg_info(cpl_func,
"Identifying different settings");
864 selection = cpl_frameset_labelise(frameset, compare, &nsets);
865 skip_if (selection == NULL);
869 for(
int i = 0; i < nsets; i++)
871 int fr_size = cpl_frameset_get_size(frameset);
873 cpl_msg_info(cpl_func,
"Reduce data set nb %d out of %" CPL_SIZE_FORMAT
"",
875 skip_if(detmon_lg_reduce_set(i, frameset, nsets, tag_on, tag_off,
890 fr_size_new = cpl_frameset_get_size(frameset);
896 if (fr_size_new > fr_size)
898 selection = cpl_realloc(selection, fr_size_new *
sizeof(selection[0]));
899 memset(selection + fr_size, -1, (fr_size_new - fr_size) *
sizeof(selection[0]));
905 cpl_frameset_delete(cur_fset);
906 cpl_frameset_delete(cur_fset_on);
907 cpl_frameset_delete(cur_fset_off);
909 cpl_image_delete(reference);
911 return cpl_error_get_code();
947 static cpl_error_code
948 detmon_lg_core(cpl_frameset * cur_fset_on,
949 cpl_frameset * cur_fset_off,
953 double * exptime_off,
956 const char * recipe_name,
957 const char * pipeline_name,
958 const char * pafregexp,
959 const cpl_propertylist * pro_lintbl,
960 const cpl_propertylist * pro_gaintbl,
961 const cpl_propertylist * pro_coeffscube,
962 const cpl_propertylist * pro_bpm,
963 const cpl_propertylist * pro_corr,
964 const cpl_propertylist * pro_diff,
965 const char * package,
966 int (* load_fset) (
const cpl_frameset *,
969 int nsets, cpl_boolean opt_nir,
970 cpl_frameset * frameset,
const cpl_parameterlist * parlist,
971 cpl_frameset * cur_fset)
973 cpl_table * gain_table = cpl_table_new(
974 cpl_frameset_get_size(cur_fset_on) / 2);
975 cpl_table * linear_table = cpl_table_new(
976 cpl_frameset_get_size(cur_fset_on) / 2);
977 cpl_imagelist * coeffs = NULL;
978 cpl_image * bpm = NULL;
979 cpl_imagelist * autocorr_images = NULL;
980 cpl_imagelist * diff_flats = NULL;
981 cpl_propertylist * gaint_qclist = NULL;
982 cpl_propertylist * lint_qclist = NULL;
983 cpl_propertylist * linc_qclist = NULL;
984 cpl_propertylist * bpm_qclist = NULL;
986 int next_index_on = 0;
987 int next_index_off = 0;
990 cpl_msg_info(cpl_func,
"Reduce extension nb %d ", whichext);
994 if (detmon_lg_config.intermediate) {
995 autocorr_images = cpl_imagelist_new();
996 diff_flats = cpl_imagelist_new();
999 gaint_qclist = cpl_propertylist_new();
1000 lint_qclist = cpl_propertylist_new();
1001 linc_qclist = cpl_propertylist_new();
1002 bpm_qclist = cpl_propertylist_new();
1005 cpl_msg_info(cpl_func,
"Starting data reduction");
1006 if (detmon_lg_reduce(cur_fset_on, cur_fset_off,
1007 index_on, index_off, exptime_on, exptime_off,
1008 &next_index_on, &next_index_off,
1009 &coeffs, gain_table,
1010 linear_table, &bpm, autocorr_images,
1011 diff_flats, gaint_qclist, lint_qclist,
1012 linc_qclist, bpm_qclist, load_fset,
1013 opt_nir, whichext) == CPL_ERROR_CONTINUE) {
1014 cpl_msg_info(cpl_func,
"Empty extension %d", whichext);
1018 cpl_msg_info(cpl_func,
"Saving the products");
1021 detmon_lg_save(parlist, frameset, recipe_name,
1022 pipeline_name, pafregexp,
1023 pro_lintbl, pro_gaintbl,
1024 pro_coeffscube, pro_bpm,
1025 pro_corr, pro_diff, package,
1026 coeffs, gain_table, linear_table,
1027 bpm, autocorr_images, diff_flats,
1028 gaint_qclist, lint_qclist, linc_qclist,
1029 bpm_qclist, 0, 0, cur_fset, whichext));
1032 detmon_lg_save(parlist, frameset, recipe_name,
1033 pipeline_name, pafregexp,
1034 pro_lintbl, pro_gaintbl,
1035 pro_coeffscube, pro_bpm,
1036 pro_corr, pro_diff, package,
1037 coeffs, gain_table, linear_table,
1038 bpm, autocorr_images, diff_flats,
1039 gaint_qclist, lint_qclist, linc_qclist,
1040 bpm_qclist, 1, whichset+ 1, cur_fset,
1048 cpl_table_delete(gain_table);
1049 cpl_table_delete(linear_table);
1050 cpl_imagelist_delete(coeffs);
1051 cpl_propertylist_delete(gaint_qclist);
1052 cpl_propertylist_delete(lint_qclist);
1053 cpl_propertylist_delete(linc_qclist);
1054 if(bpm_qclist != NULL) cpl_propertylist_delete(bpm_qclist);
1055 cpl_image_delete(bpm);
1056 cpl_imagelist_delete(autocorr_images);
1057 cpl_imagelist_delete(diff_flats);
1059 return cpl_error_get_code();
1084 detmon_image_correlate(
const cpl_image * image1,
1085 const cpl_image * image2,
1086 const int m,
const int n)
1088 cpl_image *image1_padded = NULL;
1089 cpl_image *image2_padded = NULL;
1093 cpl_image *corr_image_window = NULL;
1095 cpl_image* image_ri1 = NULL;
1096 cpl_image* image_ri2 = NULL;
1097 cpl_error_code err = CPL_ERROR_NONE;
1100 cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1101 cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1103 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1104 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1106 nx = cpl_image_get_size_x(image1);
1107 ny = cpl_image_get_size_y(image1);
1109 nx2 = cpl_image_get_size_x(image2);
1110 ny2 = cpl_image_get_size_y(image2);
1113 cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
1116 image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1117 cpl_image_copy(image1_padded, image1, m + 1, n + 1);
1119 image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1120 cpl_image_copy(image2_padded, image2, m + 1, n + 1);
1126 image_ri1 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
1127 image_ri2 = cpl_image_new(nx, ny , CPL_TYPE_FLOAT_COMPLEX);
1129 cpl_fft_image(image_ri1, image1_padded, CPL_FFT_FORWARD);
1130 cpl_fft_image(image_ri2, image2_padded, CPL_FFT_FORWARD);
1131 err = cpl_error_get_code();
1132 cpl_image_delete(image1_padded);
1133 image1_padded = NULL;
1134 cpl_image_delete(image2_padded);
1135 image2_padded = NULL;
1136 if (err == CPL_ERROR_NONE)
1139 cpl_image * corr_image = NULL;
1140 cpl_image * reorganised= NULL;
1141 cpl_image * image_ri_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1142 cpl_image * image_in_inv = cpl_image_new(nx, ny,
1143 CPL_TYPE_FLOAT_COMPLEX);
1146 for (i = 1; i <= nx; i++)
1148 for (j = 1; j <= ny; j++)
1151 double complex value1, value2, value;
1152 value1 = cpl_image_get_complex(image_ri1, i, j, &rej);
1153 value2 = cpl_image_get_complex(image_ri2, i, j, &rej);;
1154 value = conj(value1) * value2;
1155 cpl_image_set_complex(image_in_inv, i, j, value);
1158 cpl_image_delete(image_ri1);
1160 cpl_image_delete(image_ri2);
1163 err = cpl_error_get_code();
1164 if (err == CPL_ERROR_NONE)
1168 cpl_fft_image(image_ri_inv, image_in_inv,CPL_FFT_BACKWARD);
1169 cpl_image_delete(image_in_inv);
1172 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1173 for (i = 1; i <= nx; i++)
1175 for (j = 1; j <= ny; j++)
1179 value = cpl_image_get(image_ri_inv, i, j, &rej);
1180 cpl_image_set(corr_image, i, j, value);
1183 cpl_image_delete(image_ri_inv);
1184 err = cpl_error_get_code();
1185 if (err == CPL_ERROR_NONE)
1189 cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
1190 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1192 cpl_image_copy(reorganised, image, 1, 1);
1193 cpl_image_delete(image);
1194 image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
1195 cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
1196 cpl_image_delete(image);
1198 cpl_image_delete(corr_image);
1200 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1201 image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
1202 cpl_image_copy(corr_image, image, 1, 1);
1203 cpl_image_delete(image);
1205 image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
1206 cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
1207 cpl_image_delete(image);
1209 corr_image_window = cpl_image_extract(corr_image,
1212 nx / 2 + 1 + m, ny / 2 + 1 + n);
1217 cpl_image_delete(reorganised);
1218 cpl_image_delete(corr_image);
1220 if(cpl_image_divide_scalar(corr_image_window,
1221 cpl_image_get_max(corr_image_window))) {
1222 cpl_image_delete(corr_image_window);
1226 cpl_image_delete (image_ri1);
1227 cpl_image_delete (image_ri2);
1228 cpl_image_delete (image1_padded);
1229 cpl_image_delete (image2_padded);
1230 return corr_image_window;
1253 detmon_autocorrelate(
const cpl_image * input2,
const int m,
1256 cpl_image *im_re = NULL;
1257 cpl_image *im_im = NULL;
1259 cpl_image *ifft_re = NULL;
1260 cpl_image *ifft_im = NULL;
1261 cpl_image *autocorr = NULL;
1262 cpl_image *autocorr_norm_double = NULL;
1263 cpl_image *autocorr_norm = NULL;
1264 cpl_image *reorganised = NULL;
1265 cpl_image *image = NULL;
1267 cpl_error_code error;
1270 cpl_ensure(input2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1272 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1273 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1275 nx = cpl_image_get_size_x(input2) + 2 * m;
1276 ny = cpl_image_get_size_y(input2) + 2 * n;
1279 while(nx > p || ny > p) {
1283 input = cpl_image_cast(input2, CPL_TYPE_DOUBLE);
1285 im_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1286 error = cpl_image_copy(im_re, input, 1, 1);
1287 cpl_ensure(!error, error, NULL);
1289 im_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1291 error = cpl_image_fft(im_re, im_im, CPL_FFT_DEFAULT);
1292 cpl_ensure(!error, error, NULL);
1294 ifft_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1295 error = cpl_image_power(im_re, 2);
1296 cpl_ensure(!error, error, NULL);
1298 error = cpl_image_add(ifft_re, im_re);
1299 cpl_ensure(!error, error, NULL);
1301 cpl_image_delete(im_re);
1303 error = cpl_image_power(im_im, 2);
1304 cpl_ensure(!error, error, NULL);
1306 error = cpl_image_add(ifft_re, im_im);
1307 cpl_ensure(!error, error, NULL);
1309 cpl_image_delete(im_im);
1311 ifft_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1313 error = cpl_image_fft(ifft_re, ifft_im, CPL_FFT_INVERSE);
1314 cpl_ensure(!error, error, NULL);
1316 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1318 error = cpl_image_power(ifft_re, 2);
1319 cpl_ensure(!error, error, NULL);
1321 error = cpl_image_add(autocorr, ifft_re);
1322 cpl_ensure(!error, error, NULL);
1324 cpl_image_delete(ifft_re);
1326 error = cpl_image_power(ifft_im, 2);
1327 cpl_ensure(!error, error, NULL);
1329 error = cpl_image_add(autocorr, ifft_im);
1330 cpl_ensure(!error, error, NULL);
1332 cpl_image_delete(ifft_im);
1335 reorganised = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1337 image = cpl_image_extract(autocorr, p / 2 + 1, 1, p, p);
1338 cpl_image_copy(reorganised, image, 1, 1);
1339 cpl_image_delete(image);
1341 image = cpl_image_extract(autocorr, 1, 1, p / 2, p);
1342 cpl_image_copy(reorganised, image, p / 2 + 1, 1);
1343 cpl_image_delete(image);
1345 cpl_image_delete(autocorr);
1347 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1349 image = cpl_image_extract(reorganised, 1, p / 2 + 1, p, p);
1350 cpl_image_copy(autocorr, image, 1, 1);
1351 cpl_image_delete(image);
1353 image = cpl_image_extract(reorganised, 1, 1, p, p / 2);
1354 cpl_image_copy(autocorr, image, 1, p / 2 + 1);
1355 cpl_image_delete(image);
1357 cpl_image_delete(reorganised);
1359 autocorr_norm_double =
1360 cpl_image_extract(autocorr, p / 2 + 1 - m, p / 2 + 1 - n,
1361 p / 2 + 1 + m, p / 2 + 1 + n);
1363 cpl_image_delete(autocorr);
1365 if(cpl_image_divide_scalar(autocorr_norm_double,
1366 cpl_image_get_max(autocorr_norm_double))) {
1367 cpl_image_delete(autocorr_norm_double);
1368 cpl_ensure(0, cpl_error_get_code(), NULL);
1372 autocorr_norm = cpl_image_cast(autocorr_norm_double, CPL_TYPE_FLOAT);
1373 cpl_image_delete(autocorr_norm_double);
1375 cpl_image_delete(input);
1377 return autocorr_norm;
1393 detmon_lg_fill_parlist_nir_default(cpl_parameterlist * parlist,
1394 const char *recipe_name,
1395 const char *pipeline_name)
1397 const cpl_error_code error =
1398 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1444 cpl_ensure_code(!error, error);
1446 return cpl_error_get_code();
1462 detmon_lg_fill_parlist_opt_default(cpl_parameterlist * parlist,
1463 const char *recipe_name,
1464 const char *pipeline_name)
1466 const cpl_error_code error =
1467 detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1512 cpl_ensure_code(!error, error);
1514 return cpl_error_get_code();
1518 detmon_lg_fill_parlist_opt_default_mr(cpl_parameterlist * parlist,
1519 const char *recipe_name,
1520 const char *pipeline_name)
1522 detmon_lg_fill_parlist_opt_default(parlist,
1527 char * group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1528 char * par_name = cpl_sprintf(
"%s.%s", group_name,
"regions-file");
1529 cpl_parameter * p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1530 "File containing regions, "
1531 "four comma separated points "
1534 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions-file");
1535 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1536 cpl_parameterlist_append(parlist, p);
1538 cpl_free(group_name);
1540 group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1541 par_name = cpl_sprintf(
"%s.%s", group_name,
"regions");
1542 p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1543 "Colon separated list of regions, four "
1544 "points each, comma separated: "
1545 "llx,lly,urx,ury:llx,...",
1547 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions");
1548 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1549 cpl_parameterlist_append(parlist, p);
1551 cpl_free(group_name);
1553 return cpl_error_get_code();
1613 detmon_lg_fill_parlist(cpl_parameterlist * parlist,
1614 const char *recipe_name,
const char *pipeline_name,
1624 const char *intermediate,
1625 const char *autocorr,
1626 const char *collapse,
1627 const char *rescale,
1628 const char *pix2pix,
1635 const char * pafname,
1652 int llx5,
int lly5,
int urx5,
int ury5,
int exts,
1653 cpl_boolean opt_nir)
1655 const cpl_error_code error =
1656 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 25,
1658 "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
1659 "CPL_TYPE_STRING", method,
1662 "Polynomial order for the fit (Linearity)",
1663 "CPL_TYPE_INT", order,
1665 "Kappa value for the kappa-sigma clipping (Gain)",
1666 "CPL_TYPE_DOUBLE", kappa,
1668 "Number of iterations to compute rms (Gain)",
1669 "CPL_TYPE_INT", niter,
1671 "x coordinate of the lower-left "
1672 "point of the region of interest. If not modified, default value will be 1.",
1673 "CPL_TYPE_INT", llx,
1675 "y coordinate of the lower-left "
1676 "point of the region of interest. If not modified, default value will be 1.",
1677 "CPL_TYPE_INT", lly,
1679 "x coordinate of the upper-right "
1680 "point of the region of interest. If not modified, default value will be X dimension of the input image.",
1681 "CPL_TYPE_INT", urx,
1683 "y coordinate of the upper-right "
1684 "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
1685 "CPL_TYPE_INT", ury,
1687 "User reference level",
1688 "CPL_TYPE_INT", ref_level,
1690 "De-/Activate intermediate products",
1691 "CPL_TYPE_BOOL", intermediate,
1694 "De-/Activate the autocorr option",
1695 "CPL_TYPE_BOOL", autocorr,
1698 "De-/Activate the collapse option",
1699 "CPL_TYPE_BOOL", collapse,
1701 "De-/Activate the image rescale option",
1702 "CPL_TYPE_BOOL", rescale,
1704 "De-/Activate the computation with pixel to pixel accuracy",
1705 "CPL_TYPE_BOOL", pix2pix,
1707 "De-/Activate the binary bpm option",
1708 "CPL_TYPE_BOOL", bpmbin,
1710 "Maximum x-shift for the autocorr",
1713 "Upper limit of Median flux to be filtered",
1714 "CPL_TYPE_INT", filter,
1716 "Maximum y-shift for the autocorr",
1719 "Tolerance for pair discrimination",
1720 "CPL_TYPE_DOUBLE", tolerance,
1723 "Generate PAF file",
1724 "CPL_TYPE_BOOL", pafgen,
1726 "Specific name for PAF file",
1727 "CPL_TYPE_STRING", pafname,
1731 "Activate the multi-exts option. Choose -1 to process all extensions. Choose an extension number"
1732 " to process the appropriate extension.",
1733 "CPL_TYPE_INT", exts,
1736 "Method for computing Fixed Pattern Noise (SMOOTH or HISTOGRAM)",
1737 "CPL_TYPE_STRING",
"HISTOGRAM",
1740 "template size in pixels for smoothing during FPN computation (only for SMOOTH method)",
1744 "all frames with mean saturation above the limit would not be used in calculation",
1745 "CPL_TYPE_DOUBLE", 65535.0
1747 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 1,
1748 "coeffs_cube_split",
1749 "if TRUE, the recipe writes as many "
1750 "COEFFS_CUBE_Pi (i=0..order) as the value of "
1751 "the order parameter in a separate file",
1752 "CPL_TYPE_BOOL",
"CPL_FALSE");
1754 if(opt_nir == FALSE) {
1755 const cpl_error_code erroropt =
1756 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
1758 "x coord of the lower-left point of the first "
1759 "field used for contamination measurement. If not modified, default value will be 1.",
1760 "CPL_TYPE_INT", llx1,
1762 "y coord of the lower-left point of the first "
1763 "field used for contamination measurement. If not modified, default value will be 1.",
1764 "CPL_TYPE_INT", lly1,
1766 "x coord of the upper-right point of the first "
1767 "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
1768 "CPL_TYPE_INT", urx1,
1770 "y coord of the upper-right point of the first "
1771 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1772 "CPL_TYPE_INT", ury1,
1774 "x coord of the lower-left point of the second "
1775 "field used for contamination measurement. If not modified, default value will be 1.",
1776 "CPL_TYPE_INT", llx2,
1778 "y coord of the lower-left point of the second "
1779 "field used for contamination measurement. If not modified, default value will be 1.",
1780 "CPL_TYPE_INT", lly2,
1782 "x coord of the upper-right point of the second "
1783 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1784 "CPL_TYPE_INT", urx2,
1786 "y coord of the upper-right point of the second "
1787 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1788 "CPL_TYPE_INT", ury2,
1790 "x coord of the lower-left point of the third "
1791 "field used for contamination measurement. If not modified, default value will be 1.",
1792 "CPL_TYPE_INT", llx3,
1794 "y coord of the lower-left point of the third "
1795 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1796 "CPL_TYPE_INT", lly3,
1798 "x coord of the upper-right point of the third "
1799 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1800 "CPL_TYPE_INT", urx3,
1802 "y coord of the upper-right point of the third "
1803 "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
1804 "CPL_TYPE_INT", ury3,
1806 "x coord of the lower-left point of the fourth "
1807 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1808 "CPL_TYPE_INT", llx4,
1810 "y coord of the lower-left point of the fourth "
1811 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1812 "CPL_TYPE_INT", lly4,
1814 "x coord of the upper-right point of the fourth "
1815 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1816 "CPL_TYPE_INT", urx4,
1818 "y coord of the upper-right point of the fourth "
1819 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1820 "CPL_TYPE_INT", ury4,
1822 "x coord of the lower-left point of the fifth "
1823 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1824 "CPL_TYPE_INT", llx5,
1826 "y coord of the lower-left point of the fifth "
1827 "field used for contamination measurement. If not modified, default value will be 1.",
1828 "CPL_TYPE_INT", lly5,
1830 "x coord of the upper-right point of the fifth "
1831 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1832 "CPL_TYPE_INT", urx5,
1835 "y coord of the upper-right point of the fifth "
1836 "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
1837 "CPL_TYPE_INT", ury5);
1838 cpl_ensure_code(!erroropt, erroropt);
1841 cpl_ensure_code(!error, error);
1843 return cpl_error_get_code();
1856 static cpl_error_code
1857 detmon_lg_retrieve_parlist(
const char * pipeline_name,
1858 const char * recipe_name,
1859 const cpl_parameterlist * parlist,
1860 cpl_boolean opt_nir)
1864 cpl_parameter * par;
1867 par_name = cpl_sprintf(
"%s.%s.method", pipeline_name, recipe_name);
1868 assert(par_name != NULL);
1869 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1870 detmon_lg_config.method = cpl_parameter_get_string(par);
1874 detmon_lg_config.order =
1875 detmon_retrieve_par_int(
"order", pipeline_name, recipe_name,
1879 detmon_lg_config.kappa =
1880 detmon_retrieve_par_double(
"kappa", pipeline_name, recipe_name,
1884 detmon_lg_config.niter =
1885 detmon_retrieve_par_int(
"niter", pipeline_name, recipe_name,
1889 detmon_lg_config.llx =
1890 detmon_retrieve_par_int(
"llx", pipeline_name, recipe_name,
1894 detmon_lg_config.lly =
1895 detmon_retrieve_par_int(
"lly", pipeline_name, recipe_name,
1899 detmon_lg_config.urx =
1900 detmon_retrieve_par_int(
"urx", pipeline_name, recipe_name,
1904 detmon_lg_config.ury =
1905 detmon_retrieve_par_int(
"ury", pipeline_name, recipe_name,
1909 detmon_lg_config.ref_level =
1910 detmon_retrieve_par_int(
"ref_level", pipeline_name, recipe_name,
1915 cpl_sprintf(
"%s.%s.intermediate", pipeline_name, recipe_name);
1916 assert(par_name != NULL);
1917 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1918 detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
1922 par_name = cpl_sprintf(
"%s.%s.autocorr", pipeline_name, recipe_name);
1923 assert(par_name != NULL);
1924 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1925 detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
1929 par_name = cpl_sprintf(
"%s.%s.coeffs_cube_split", pipeline_name, recipe_name);
1930 assert(par_name != NULL);
1931 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1932 detmon_lg_config.split_coeffs = cpl_parameter_get_bool(par);
1936 par_name = cpl_sprintf(
"%s.%s.collapse", pipeline_name, recipe_name);
1937 assert(par_name != NULL);
1938 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1939 detmon_lg_config.collapse = cpl_parameter_get_bool(par);
1943 par_name = cpl_sprintf(
"%s.%s.rescale", pipeline_name, recipe_name);
1944 assert(par_name != NULL);
1945 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1946 detmon_lg_config.rescale = cpl_parameter_get_bool(par);
1950 par_name = cpl_sprintf(
"%s.%s.pix2pix", pipeline_name, recipe_name);
1951 assert(par_name != NULL);
1952 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1953 detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
1957 par_name = cpl_sprintf(
"%s.%s.bpmbin", pipeline_name, recipe_name);
1958 assert(par_name != NULL);
1959 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1960 detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
1964 detmon_lg_config.filter =
1965 detmon_retrieve_par_int(
"filter", pipeline_name,
1966 recipe_name, parlist);
1969 detmon_lg_config.m =
1970 detmon_retrieve_par_int(
"m", pipeline_name, recipe_name, parlist);
1973 detmon_lg_config.n =
1974 detmon_retrieve_par_int(
"n", pipeline_name, recipe_name, parlist);
1977 par_name = cpl_sprintf(
"%s.%s.tolerance", pipeline_name, recipe_name);
1978 assert(par_name != NULL);
1979 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1980 detmon_lg_config.tolerance = cpl_parameter_get_double(par);
1985 par_name = cpl_sprintf(
"%s.%s.pafgen", pipeline_name, recipe_name);
1986 assert(par_name != NULL);
1987 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1988 detmon_lg_config.pafgen = cpl_parameter_get_bool(par);
1992 par_name = cpl_sprintf(
"%s.%s.pafname", pipeline_name, recipe_name);
1993 assert(par_name != NULL);
1994 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1995 detmon_lg_config.pafname = cpl_parameter_get_string(par);
1998 if(opt_nir == OPT) {
2000 detmon_lg_config.llx1 =
2001 detmon_retrieve_par_int(
"llx1", pipeline_name, recipe_name,
2005 detmon_lg_config.lly1 =
2006 detmon_retrieve_par_int(
"lly1", pipeline_name, recipe_name,
2010 detmon_lg_config.urx1 =
2011 detmon_retrieve_par_int(
"urx1", pipeline_name, recipe_name,
2015 detmon_lg_config.ury1 =
2016 detmon_retrieve_par_int(
"ury1", pipeline_name, recipe_name,
2020 detmon_lg_config.llx2 =
2021 detmon_retrieve_par_int(
"llx2", pipeline_name, recipe_name,
2025 detmon_lg_config.lly2 =
2026 detmon_retrieve_par_int(
"lly2", pipeline_name, recipe_name,
2030 detmon_lg_config.urx2 =
2031 detmon_retrieve_par_int(
"urx2", pipeline_name, recipe_name,
2035 detmon_lg_config.ury2 =
2036 detmon_retrieve_par_int(
"ury2", pipeline_name, recipe_name,
2040 detmon_lg_config.llx3 =
2041 detmon_retrieve_par_int(
"llx3", pipeline_name, recipe_name,
2045 detmon_lg_config.lly3 =
2046 detmon_retrieve_par_int(
"lly3", pipeline_name, recipe_name,
2050 detmon_lg_config.urx3 =
2051 detmon_retrieve_par_int(
"urx3", pipeline_name, recipe_name,
2055 detmon_lg_config.ury3 =
2056 detmon_retrieve_par_int(
"ury3", pipeline_name, recipe_name,
2060 detmon_lg_config.llx4 =
2061 detmon_retrieve_par_int(
"llx4", pipeline_name, recipe_name,
2065 detmon_lg_config.lly4 =
2066 detmon_retrieve_par_int(
"lly4", pipeline_name, recipe_name,
2070 detmon_lg_config.urx4 =
2071 detmon_retrieve_par_int(
"urx4", pipeline_name, recipe_name,
2075 detmon_lg_config.ury4 =
2076 detmon_retrieve_par_int(
"ury4", pipeline_name, recipe_name,
2080 detmon_lg_config.llx5 =
2081 detmon_retrieve_par_int(
"llx5", pipeline_name, recipe_name,
2085 detmon_lg_config.lly5 =
2086 detmon_retrieve_par_int(
"lly5", pipeline_name, recipe_name,
2090 detmon_lg_config.urx5 =
2091 detmon_retrieve_par_int(
"urx5", pipeline_name, recipe_name,
2095 detmon_lg_config.ury5 =
2096 detmon_retrieve_par_int(
"ury5", pipeline_name, recipe_name,
2101 detmon_lg_config.exts =
2102 detmon_retrieve_par_int(
"exts", pipeline_name, recipe_name,
2106 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2108 cpl_sprintf(
"%s.%s.fpn_method", pipeline_name, recipe_name);
2109 assert(par_name != NULL);
2110 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2113 const char * str_method = cpl_parameter_get_string(par);
2114 if (strcmp(str_method,
"SMOOTH") == 0)
2116 detmon_lg_config.fpn_method = FPN_SMOOTH;
2118 else if (strcmp(str_method,
"HISTOGRAM") == 0)
2120 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2126 detmon_lg_config.fpn_smooth =
2127 detmon_retrieve_par_int(
"fpn_smooth", pipeline_name, recipe_name,
2131 detmon_lg_config.saturation_limit = 65535;
2133 cpl_sprintf(
"%s.%s.saturation_limit", pipeline_name, recipe_name);
2134 assert(par_name != NULL);
2135 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2138 detmon_lg_config.saturation_limit = cpl_parameter_get_double(par);
2142 if(cpl_error_get_code())
2144 cpl_msg_error(cpl_func,
"Failed to retrieve the input parameters");
2145 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
2149 return cpl_error_get_code();
2159 static cpl_error_code
2160 detmon_lg_check_defaults(
const cpl_image * reference)
2162 const int nx = cpl_image_get_size_x(reference);
2163 const int ny = cpl_image_get_size_y(reference);
2165 detmon_lg_config.nx = nx;
2166 detmon_lg_config.ny = ny;
2168 detmon_lg_config.wholechip = CPL_FALSE;
2170 if(detmon_lg_config.llx == -1)
2171 detmon_lg_config.llx = 1;
2172 if(detmon_lg_config.lly == -1)
2173 detmon_lg_config.lly = 1;
2174 if(detmon_lg_config.urx == -1)
2175 detmon_lg_config.urx = nx;
2176 if(detmon_lg_config.ury == -1)
2177 detmon_lg_config.ury = ny;
2179 if (detmon_lg_config.llx == 1 &&
2180 detmon_lg_config.lly == 1 &&
2181 detmon_lg_config.urx == nx &&
2182 detmon_lg_config.ury == ny)
2183 detmon_lg_config.wholechip = CPL_TRUE;
2185 if(detmon_lg_config.llx1 == -1)
2186 detmon_lg_config.llx1 = 1;
2187 if(detmon_lg_config.lly1 == -1)
2188 detmon_lg_config.lly1 = 1;
2189 if(detmon_lg_config.urx1 == -1)
2190 detmon_lg_config.urx1 = nx;
2191 if(detmon_lg_config.ury1 == -1)
2192 detmon_lg_config.ury1 = ny;
2194 if(detmon_lg_config.llx2 == -1)
2195 detmon_lg_config.llx2 = 1;
2196 if(detmon_lg_config.lly2 == -1)
2197 detmon_lg_config.lly2 = 1;
2198 if(detmon_lg_config.urx2 == -1)
2199 detmon_lg_config.urx2 = nx / 2;
2200 if(detmon_lg_config.ury2 == -1)
2201 detmon_lg_config.ury2 = ny / 2;
2203 if(detmon_lg_config.llx3 == -1)
2204 detmon_lg_config.llx3 = 1;
2205 if(detmon_lg_config.lly3 == -1)
2206 detmon_lg_config.lly3 = ny / 2;
2207 if(detmon_lg_config.urx3 == -1)
2208 detmon_lg_config.urx3 = nx / 2;
2209 if(detmon_lg_config.ury3 == -1)
2210 detmon_lg_config.ury3 = ny;
2212 if(detmon_lg_config.llx4 == -1)
2213 detmon_lg_config.llx4 = nx / 2;
2214 if(detmon_lg_config.lly4 == -1)
2215 detmon_lg_config.lly4 = ny / 2;
2216 if(detmon_lg_config.urx4 == -1)
2217 detmon_lg_config.urx4 = nx;
2218 if(detmon_lg_config.ury4 == -1)
2219 detmon_lg_config.ury4 = ny;
2221 if(detmon_lg_config.llx5 == -1)
2222 detmon_lg_config.llx5 = nx / 2;
2223 if(detmon_lg_config.lly5 == -1)
2224 detmon_lg_config.lly5 = 1;
2225 if(detmon_lg_config.urx5 == -1)
2226 detmon_lg_config.urx5 = nx;
2227 if(detmon_lg_config.ury5 == -1)
2228 detmon_lg_config.ury5 = ny / 2;
2230 if(detmon_lg_config.intermediate == TRUE) {
2231 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.");
2232 detmon_lg_config.autocorr = TRUE;
2236 detmon_lg_config.lamp_stability = 0.0;
2238 detmon_lg_config.lamp_ok = FALSE;
2240 detmon_lg_config.cr = 0.0;
2242 return cpl_error_get_code();
2257 static cpl_error_code
2258 detmon_lg_split_onoff(
const cpl_frameset * cur_fset,
2259 cpl_frameset * cur_fset_on,
2260 cpl_frameset * cur_fset_off,
2262 const char *tag_off)
2267 cpl_frame * cur_frame_dup = NULL;
2270 const cpl_frame * first;
2271 const cpl_frame * second;
2272 const char * first_tag;
2273 const char * second_tag;
2274 skip_if((first = cpl_frameset_get_first_const(cur_fset)) == NULL);
2275 skip_if((second = cpl_frameset_get_next_const (cur_fset)) == NULL);
2277 skip_if((first_tag = cpl_frame_get_tag(first)) == NULL);
2278 skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
2279 if (opt_nir == OPT &&
2280 ((!strcmp(first_tag, tag_on ) && !strcmp(second_tag, tag_off)) ||
2281 (!strcmp(first_tag, tag_off) && !strcmp(second_tag, tag_on )))) {
2282 detmon_lg_config.lamp_ok = TRUE;
2286 nframes = cpl_frameset_get_size(cur_fset);
2287 for(i = detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
2288 const cpl_frame * cur_frame =
2289 cpl_frameset_get_position_const(cur_fset, i);
2293 cur_frame_dup = cpl_frame_duplicate(cur_frame);
2294 tag = (
char *) cpl_frame_get_tag(cur_frame_dup);
2297 if(!strcmp(tag, tag_on)) {
2298 skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
2299 }
else if(!strcmp(tag, tag_off)) {
2300 skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
2302 cpl_frame_delete(cur_frame_dup);
2303 cur_frame_dup = NULL;
2306 cur_frame_dup = NULL;
2310 cpl_frame_delete(cur_frame_dup);
2312 return cpl_error_get_code();
2339 static cpl_error_code
2340 detmon_lg_reduce(
const cpl_frameset * set_on,
2341 const cpl_frameset * set_off,
2342 int* index_on,
int* index_off,
2343 double* exptime_on,
double* exptime_off,
2344 int *next_index_on,
int* next_index_off,
2345 cpl_imagelist ** coeffs_ptr,
2346 cpl_table * gain_table,
2347 cpl_table * linear_table,
2348 cpl_image ** bpm_ptr,
2349 cpl_imagelist * autocorr_images,
2350 cpl_imagelist * diff_flats,
2351 cpl_propertylist * gaint_qclist,
2352 cpl_propertylist * lint_qclist,
2353 cpl_propertylist * linc_qclist,
2354 cpl_propertylist * bpm_qclist,
2355 int (* load_fset) (
const cpl_frameset *,
2358 const cpl_boolean opt_nir,
2361 cpl_errorstate prestate = cpl_errorstate_get();
2362 const double D_INVALID_VALUE = -999;
2364 cpl_imagelist * linearity_inputs = NULL;
2365 cpl_imagelist * opt_offs = NULL;
2367 cpl_propertylist * reflist = NULL;
2369 int rows_affected = 1;
2372 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2373 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2375 nsets = cpl_frameset_get_size(set_on) / 2;
2377 detmon_lg_config.load_fset = load_fset;
2378 if(detmon_lg_config.collapse) {
2385 const cpl_frame *first = cpl_frameset_get_first_const(set_off);
2386 cpl_frame *dup_first = cpl_frame_duplicate(first);
2388 const cpl_frame *second = cpl_frameset_get_next_const(set_off);
2389 cpl_frame *dup_second = cpl_frame_duplicate(second);
2391 cpl_frameset *raw_offs = cpl_frameset_new();
2393 skip_if(cpl_frameset_insert(raw_offs, dup_first));
2394 skip_if(cpl_frameset_insert(raw_offs, dup_second));
2396 opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
2399 cpl_frameset_delete(raw_offs);
2400 if (opt_offs == NULL) {
2401 cpl_errorstate_set(prestate);
2402 return CPL_ERROR_CONTINUE;
2406 skip_if(detmon_lg_reduce_init(gain_table,
2418 if(detmon_lg_lamp_stab(set_on, set_off,
2419 opt_nir, whichext)) {
2420 cpl_errorstate_set(prestate);
2423 if(!detmon_lg_config.collapse)
2427 skip_if(cpl_table_unselect_all(linear_table));
2428 skip_if(cpl_table_unselect_all(gain_table));
2432 for(i = 0; i < nsets ; i++)
2434 skip_if(detmon_lg_reduce_dit(set_on,
2435 index_on, exptime_on,
2439 index_off, exptime_off,
2440 next_index_on, next_index_off,
2442 gain_table, linearity_inputs,
2443 lint_qclist, opt_nir,
2444 autocorr_images, diff_flats,
2447 if (rows_affected == 0)
2449 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2450 "into calculation, check the messages above");
2451 cpl_table_select_row(linear_table, i);
2452 cpl_table_select_row(gain_table, i);
2459 skip_if(detmon_add_adl_column(linear_table, opt_nir));
2465 skip_if(cpl_table_erase_selected(gain_table));
2466 skip_if(cpl_table_erase_selected(linear_table));
2468 reflist = cpl_propertylist_new();
2469 skip_if(cpl_propertylist_append_bool(reflist,
"ADU", FALSE));
2470 skip_if(cpl_table_sort(gain_table, reflist));
2476 skip_if(detmon_lg_reduce_all(linear_table,
2477 gaint_qclist, lint_qclist, linc_qclist,
2478 bpm_qclist, coeffs_ptr, bpm_ptr,
2480 gain_table, whichext, opt_nir));
2483 double gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
2486 cpl_error_code cplerr = cpl_error_get_code();
2487 if (cplerr != CPL_ERROR_NONE || (gain == 0.0))
2489 cpl_msg_warning(cpl_func,
"Cannot read gain from QC parameters - "
2490 "FPN will not be computed");
2495 detmon_fpn_compute(set_on, index_on, last_best, lint_qclist,
2496 detmon_lg_config.llx,
2497 detmon_lg_config.lly,
2498 detmon_lg_config.urx,
2499 detmon_lg_config.ury,
2502 detmon_lg_config.fpn_method,
2503 detmon_lg_config.fpn_smooth);
2508 detmon_table_fill_invalid(gain_table, D_INVALID_VALUE);
2510 cpl_imagelist_delete(linearity_inputs);
2511 cpl_imagelist_delete(opt_offs);
2512 cpl_propertylist_delete(reflist);
2514 return cpl_error_get_code();
2517 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code)
2519 int ncols = cpl_table_get_ncol(ptable);
2520 cpl_array* pnames = cpl_table_get_column_names(ptable);
2521 int nrows = cpl_table_get_nrow(ptable);
2523 for (i=0; i < ncols; i++)
2526 for (j = 0; j< nrows; j++)
2528 const char* colname = cpl_array_get_data_string_const(pnames)[i];
2530 cpl_type type = cpl_table_get_column_type(ptable, colname);
2531 cpl_table_get(ptable, colname, j, &isnull);
2534 if (type == CPL_TYPE_DOUBLE)
2536 cpl_table_set(ptable,colname,j, code);
2538 else if (type == CPL_TYPE_FLOAT)
2540 cpl_table_set_float(ptable,colname,j, (
float)code);
2545 cpl_array_delete(pnames);
2546 return cpl_error_get_code();
2549 static cpl_error_code
2550 detmon_fpn_compute(
const cpl_frameset *set_on,
2553 cpl_propertylist *lint_qclist,
2560 FPN_METHOD fpn_method,
2564 const cpl_image* im1 = 0;
2566 cpl_imagelist* ons = 0;
2567 cpl_frameset * pair_on = 0;
2568 int nsets_extracted = cpl_frameset_get_size(set_on);
2569 cpl_size * selection = NULL;
2578 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
2579 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
2581 selection[index_on[last_best*2 + 0] ] = 1;
2582 selection[index_on[last_best*2 + 1] ] = 1;
2583 pair_on = cpl_frameset_extract(set_on, selection, 1);
2584 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2586 skip_if(ons == NULL);
2587 skip_if((im1 = cpl_imagelist_get_const(ons, 0)) == NULL);
2589 fpn = irplib_fpn_lg(im1, range, gain, fpn_method, smooth_size, &mse);
2590 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_FPN,
2592 skip_if(cpl_propertylist_append_double(lint_qclist,
"ESO QC GAIN ERR",
2596 cpl_frameset_delete(pair_on);
2597 cpl_imagelist_delete(ons);
2598 cpl_free(selection);
2599 return cpl_error_get_code();
2611 static cpl_error_code
2612 detmon_lg_lamp_stab(
const cpl_frameset * lamps,
2613 const cpl_frameset * darks,
2614 cpl_boolean opt_nir,
2627 cpl_vector * selection = NULL;
2628 cpl_propertylist * plist;
2629 double dit_lamp, dit_dark;
2631 cpl_imagelist * lamps_data = NULL;
2632 cpl_imagelist * darks_data = NULL;
2633 double * stab_levels = NULL;
2635 double * ditvals = NULL;
2639 cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
2640 CPL_ERROR_ILLEGAL_INPUT);
2646 cpl_msg_info(__func__,
"Checking DIT consistency");
2647 selection = cpl_vector_new(nb_lamps);
2648 ditvals = cpl_malloc(nb_lamps *
sizeof(
double));
2650 for (i = 0; i < nb_lamps; i++) {
2651 const cpl_frame * c_lamp;
2652 const cpl_frame * c_dark;
2654 skip_if (cpl_error_get_code());
2657 c_lamp = cpl_frameset_get_position_const(lamps, i);
2658 plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
2660 dit_lamp = (double)irplib_pfits_get_dit(plist);
2662 dit_lamp = (double)irplib_pfits_get_dit_opt(plist);
2663 cpl_propertylist_delete(plist);
2664 skip_if (cpl_error_get_code());
2667 c_dark = cpl_frameset_get_position_const(darks, i);
2668 plist = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
2670 dit_dark = (double)irplib_pfits_get_dit(plist);
2672 dit_dark = (double)irplib_pfits_get_dit_opt(plist);
2673 cpl_propertylist_delete(plist);
2674 skip_if (cpl_error_get_code());
2677 if (fabs(dit_dark-dit_lamp) > 1e-3) {
2678 cpl_msg_error(__func__,
"DIT not consistent between LAMP and DARK, skip lamp stability computation");
2683 ditvals[i] = dit_lamp;
2686 cpl_vector_set(selection, i, -1.0);
2694 if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
2695 cpl_vector_set(selection, i, -1.0);
2699 cpl_vector_set(selection, i, 1.0);
2706 cpl_msg_info(__func__,
"Not enough frames for stability check");
2710 cpl_msg_info(__func__,
"Compute the differences lamp - dark");
2713 lamps_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2715 detmon_lg_config.llx,
2716 detmon_lg_config.lly,
2717 detmon_lg_config.urx,
2718 detmon_lg_config.ury,
2721 darks_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2723 detmon_lg_config.llx,
2724 detmon_lg_config.lly,
2725 detmon_lg_config.urx,
2726 detmon_lg_config.ury,
2729 nb_darks=cpl_imagelist_get_size(darks_data);
2730 if(nb_darks==nb_lamps) {
2731 skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
2733 cpl_image* master_dark=cpl_imagelist_collapse_median_create(darks_data);
2734 cpl_imagelist_subtract_image(lamps_data,master_dark);
2735 cpl_image_delete(master_dark);
2738 cpl_msg_info(__func__,
"Check the lamp stability");
2739 stab_levels = cpl_malloc(dit_stab *
sizeof(
double));
2741 for (i=0; i<nb_lamps; i++) {
2742 if (cpl_vector_get(selection, i) < 0) {
2744 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
2750 for (i=1; i<dit_stab; i++) {
2751 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
2752 detmon_lg_config.lamp_stability)
2753 detmon_lg_config.lamp_stability =
2754 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
2759 if (detmon_lg_config.lamp_stability > 0.01) {
2760 cpl_msg_warning(__func__,
2761 "Lamp stability level %g difference too high - proceed anyway",detmon_lg_config.lamp_stability);
2768 cpl_vector_delete(selection);
2769 cpl_imagelist_delete(lamps_data);
2770 cpl_imagelist_delete(darks_data);
2771 cpl_free(stab_levels);
2773 return cpl_error_get_code();
2800 static cpl_error_code
2801 detmon_lg_reduce_dit(
const cpl_frameset * set_on,
2802 int* index_on,
double* exptime_on,
2805 const cpl_frameset * set_off,
2806 int * index_off,
double* exptime_off,
2807 int* next_on,
int* next_off,
2808 cpl_table * linear_table,
2809 cpl_table * gain_table,
2810 cpl_imagelist * linearity_inputs,
2811 cpl_propertylist * qclist,
2812 cpl_boolean opt_nir,
2813 cpl_imagelist * autocorr_images,
2814 cpl_imagelist * diff_flats,
2815 cpl_imagelist * opt_offs,
2819 cpl_frameset * pair_on = NULL;
2820 cpl_frameset * pair_off = NULL;
2821 cpl_imagelist * ons = NULL;
2822 cpl_imagelist * offs = NULL;
2823 cpl_boolean follow = CPL_TRUE;
2824 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
2828 double current_dit = 0;
2830 const char * filename;
2832 cpl_propertylist * plist = NULL;
2833 cpl_propertylist* pDETlist = NULL;
2835 mode = detmon_lg_config.collapse ?
2836 mode | IRPLIB_GAIN_COLLAPSE | IRPLIB_LIN_COLLAPSE:
2837 mode | IRPLIB_GAIN_NO_COLLAPSE | IRPLIB_LIN_NO_COLLAPSE;
2838 mode = detmon_lg_config.pix2pix ?
2839 mode | IRPLIB_LIN_PIX2PIX : mode;
2841 mode | IRPLIB_GAIN_NIR | IRPLIB_LIN_NIR :
2842 mode | IRPLIB_GAIN_OPT | IRPLIB_LIN_OPT ;
2846 skip_if(detmon_pair_extract_next(set_on, index_on, next_on, exptime_on, &pair_on, detmon_lg_config.tolerance));
2847 current_dit = exptime_on[*next_on - 1];
2850 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2851 skip_if(ons == NULL);
2852 cpl_msg_debug(cpl_func,
" Loaded ON images: %" CPL_SIZE_FORMAT
2853 ", exptime[%f]",cpl_imagelist_get_size(ons), current_dit );
2854 if(cpl_imagelist_get_size(ons) != 2)
2856 cpl_msg_error(cpl_func,
"cannot take ON pair, number of images[%"
2857 CPL_SIZE_FORMAT
"]", cpl_imagelist_get_size(ons));
2860 if(detmon_lg_config.filter > 0)
2863 cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
2864 detmon_lg_config.llx,
2865 detmon_lg_config.lly,
2866 detmon_lg_config.urx,
2867 detmon_lg_config.ury);
2869 cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
2870 detmon_lg_config.llx,
2871 detmon_lg_config.lly,
2872 detmon_lg_config.urx,
2873 detmon_lg_config.ury);
2874 if ( med1 > (
double)detmon_lg_config.filter ||
2875 med2 > (
double)detmon_lg_config.filter)
2878 cpl_table_select_row(gain_table, dit_nb);
2879 cpl_table_select_row(linear_table, dit_nb);
2881 cpl_msg_warning(cpl_func,
"Frames of EXPTIME nb %d "
2882 "will not be taken into account for computation "
2883 "as they are above --filter threshold", dit_nb);
2887 if (follow || detmon_lg_config.filter < 0)
2895 if(!detmon_lg_config.collapse)
2897 if (!strcmp(detmon_lg_config.method,
"MED") ||
2898 cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
2900 skip_if(detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off, detmon_lg_config.tolerance));
2904 skip_if(detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
2907 cpl_msg_debug(cpl_func,
" Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
2908 offs = detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
2910 skip_if(offs == NULL);
2911 skip_if(cpl_error_get_code());
2914 offs = (cpl_imagelist *) opt_offs;
2918 if(detmon_lg_config.rescale)
2920 skip_if(detmon_lg_rescale(ons));
2921 if (!detmon_lg_config.collapse &&
2922 !strcmp(detmon_lg_config.method,
"MED"))
2923 skip_if(detmon_lg_rescale(offs));
2928 cpl_frame_get_filename(cpl_frameset_get_first_const(pair_on));
2929 skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
2933 pDETlist = cpl_propertylist_new();
2934 cpl_propertylist_copy_property_regexp(pDETlist, plist,
"DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
2937 irplib_table_create_column(gain_table, pDETlist);
2938 irplib_table_create_column(linear_table, pDETlist);
2941 if(opt_nir == NIR) {
2942 c_dit = irplib_pfits_get_dit(plist);
2943 c_ndit = irplib_pfits_get_ndit(plist);
2945 c_dit = irplib_pfits_get_exptime(plist);
2957 cpl_msg_info(cpl_func,
"Computing GAIN for EXPTIME value nb %d",
2961 if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
2963 cpl_table_erase_column(gain_table,
"MEAN_OFF1");
2964 cpl_table_erase_column(gain_table,
"MEAN_OFF2");
2965 cpl_table_erase_column(gain_table,
"SIG_OFF_DIF");
2966 cpl_table_erase_column(gain_table,
"GAIN");
2967 cpl_table_erase_column(gain_table,
"GAIN_CORR");
2968 cpl_table_new_column(gain_table,
"MEAN_OFF", CPL_TYPE_DOUBLE);
2971 skip_if(detmon_gain_table_fill_row(gain_table,
2974 diff_flats, ons, offs,
2975 detmon_lg_config.kappa,
2976 detmon_lg_config.niter,
2977 detmon_lg_config.llx,
2978 detmon_lg_config.lly,
2979 detmon_lg_config.urx,
2980 detmon_lg_config.ury,
2983 detmon_lg_config.saturation_limit,
2984 dit_nb, mode, rows_affected));
2990 skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
2992 cpl_msg_info(cpl_func,
"Linearity reduction for nb %d",
2994 skip_if(detmon_lin_table_fill_row(linear_table, c_dit,
2995 linearity_inputs, ons, offs,
2996 detmon_lg_config.llx,
2997 detmon_lg_config.lly,
2998 detmon_lg_config.urx,
2999 detmon_lg_config.ury,
3000 dit_nb, *dit_nskip, mode));
3002 skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
3014 if(opt_nir == OPT &&
3015 *rows_affected != 0 ) {
3016 detmon_opt_contamination(ons, offs, mode, qclist);
3023 cpl_frameset_delete(pair_on);
3024 cpl_imagelist_delete(ons);
3026 if(!detmon_lg_config.collapse ) {
3027 cpl_imagelist_delete(offs);
3030 if(!detmon_lg_config.collapse) {
3031 cpl_frameset_delete(pair_off);
3034 cpl_propertylist_delete(plist);
3035 cpl_propertylist_delete(pDETlist);
3036 return cpl_error_get_code();
3046 static cpl_error_code
3047 detmon_add_adl_column(cpl_table * table,
3048 cpl_boolean opt_nir)
3050 cpl_error_code error;
3051 double mean_med_dit;
3054 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
3056 mean_med_dit = cpl_table_get_column_mean(table,
"MED_DIT");
3058 dits = cpl_table_get_data_double(table,
"EXPTIME");
3060 dits = cpl_table_get_data_double(table,
"DIT");
3062 error = cpl_table_copy_data_double(table,
"ADL", dits);
3063 cpl_ensure_code(!error, error);
3064 error = cpl_table_multiply_scalar(table,
"ADL", mean_med_dit);
3065 cpl_ensure_code(!error, error);
3067 return cpl_error_get_code();
3079 static cpl_error_code
3080 detmon_lg_reduce_init(cpl_table * gain_table,
3081 cpl_table * linear_table,
3082 cpl_imagelist ** linearity_inputs,
3083 const cpl_boolean opt_nir)
3085 skip_if(detmon_gain_table_create(gain_table, opt_nir));
3086 skip_if(detmon_lin_table_create(linear_table, opt_nir));
3088 if(detmon_lg_config.pix2pix) {
3089 *linearity_inputs = cpl_imagelist_new();
3090 skip_if(*linearity_inputs == NULL);
3095 return cpl_error_get_code();
3106 irplib_pfits_get_dit(
const cpl_propertylist * plist)
3108 return irplib_pfits_get_prop_double(plist,
"ESO DET DIT");
3119 irplib_pfits_get_dit_opt(
const cpl_propertylist * plist)
3121 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3130 static cpl_propertylist*
3131 detmon_load_pro_keys(
const char* NAME_O)
3133 cpl_propertylist* pro_keys=NULL;
3134 pro_keys=cpl_propertylist_load_regexp(NAME_O,0,
"^(ESO PRO)",0);
3139 static double irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
3140 const char* prop_name)
3143 dit = cpl_propertylist_get_double(plist, prop_name);
3144 if(cpl_error_get_code() != CPL_ERROR_NONE)
3146 cpl_msg_error(cpl_func,
"Cannot read property '%s', err[%s]",
3147 prop_name, cpl_error_get_where());
3185 static cpl_error_code
3186 detmon_gain_table_fill_row(cpl_table * gain_table,
3187 double c_dit,
int c_ndit,
3188 cpl_imagelist * autocorr_images,
3189 cpl_imagelist * diff_flats,
3190 const cpl_imagelist * ons,
3191 const cpl_imagelist * offs,
3192 double kappa,
int nclip,
3193 int llx,
int lly,
int urx,
int ury,
3195 double saturation_limit,
3196 const int pos,
unsigned mode,
int* rows_affected)
3198 const cpl_image *image;
3199 cpl_image *on_dif = NULL;
3201 double avg_on1, avg_on2;
3202 double avg_off1, avg_off2;
3203 double double_adu, autocorr, gain, gain_corr;
3206 cpl_table_set(gain_table,
"FLAG", pos, 1);
3207 if (mode & IRPLIB_GAIN_NIR)
3209 cpl_table_set(gain_table,
"DIT", pos, c_dit);
3210 cpl_table_set(gain_table,
"NDIT", pos, c_ndit);
3211 }
else if (mode & IRPLIB_GAIN_OPT)
3213 cpl_table_set(gain_table,
"EXPTIME", pos, c_dit);
3216 cpl_msg_error(cpl_func,
"Mandatory mode (OPT or NIR) not provided");
3219 if(*rows_affected == 0)
3221 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3222 cpl_table_set(gain_table,
"FLAG", pos, 0);
3223 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3228 detmon_lg_add_empty_image(diff_flats, pos);
3230 if (autocorr_images)
3232 detmon_lg_add_empty_image(autocorr_images, pos);
3235 return cpl_error_get_code();
3237 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3238 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3239 nclip, 1e-5, &avg_on1, &std));
3240 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3241 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3242 nclip, 1e-5, &avg_on2, &std));
3244 if ((avg_on1 > saturation_limit) || (avg_on2 > saturation_limit))
3246 cpl_msg_warning(cpl_func,
"Average saturation is above the limit, "
3247 "the frames would not be taken into calculation");
3248 cpl_msg_warning(cpl_func,
"saturation levels [%f ; %f], limit [%f]",
3249 avg_on1, avg_on2, saturation_limit);
3250 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3251 cpl_table_set(gain_table,
"FLAG", pos, 0);
3252 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3257 detmon_lg_add_empty_image(diff_flats, pos);
3259 if (autocorr_images)
3261 detmon_lg_add_empty_image(autocorr_images, pos);
3270 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON1", pos, avg_on1));
3271 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON2", pos, avg_on2));
3274 detmon_subtract_create_window(cpl_imagelist_get_const(ons, 0),
3275 cpl_imagelist_get_const(ons, 1),
3276 llx, lly, urx, ury);
3277 skip_if(on_dif == NULL);
3279 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3283 cpl_image * diff = cpl_image_duplicate(on_dif);
3284 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
3286 if (autocorr_images)
3288 cpl_image * corr = NULL;
3289 autocorr = detmon_autocorr_factor(on_dif, &corr, m, n);
3292 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
3296 detmon_lg_add_empty_image(autocorr_images, pos);
3300 autocorr = detmon_autocorr_factor(on_dif, NULL, m, n);
3302 autocorr = isnan(autocorr) ? 1.0 : autocorr;
3308 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE)
3311 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3312 llx, lly, urx, ury, kappa, nclip,
3313 1e-5, &avg_off1, &std));
3314 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF", pos, avg_off1));
3316 }
else if (mode & IRPLIB_GAIN_NO_COLLAPSE ||
3317 ( pos == 0 && mode & IRPLIB_GAIN_COLLAPSE )) {
3318 cpl_image * off_dif = NULL;
3320 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3321 llx, lly, urx, ury, kappa, nclip,
3322 1e-5, &avg_off1, &std));
3323 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3324 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 1),
3325 llx, lly, urx, ury, kappa, nclip,
3326 1e-5, &avg_off2, &std));
3327 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, avg_off2));
3329 detmon_subtract_create_window(cpl_imagelist_get_const(offs, 0),
3330 cpl_imagelist_get_const(offs, 1),
3331 llx, lly, urx, ury);
3332 skip_if(off_dif == NULL);
3333 irplib_ksigma_clip(off_dif, 1, 1,
3334 cpl_image_get_size_x(off_dif),
3335 cpl_image_get_size_y(off_dif),
3337 1e-5, &avg_off_dif, &sig_off_dif);
3338 cpl_image_delete(off_dif);
3339 skip_if(cpl_table_set_double(gain_table,
"SIG_OFF_DIF",
3341 }
else if (pos > 0 && mode & IRPLIB_GAIN_COLLAPSE)
3344 avg_off1 = cpl_table_get_double(gain_table,
"MEAN_OFF1", 0, &status);
3345 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3346 avg_off2 = cpl_table_get_double(gain_table,
"MEAN_OFF2", 0, &status);
3347 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, avg_off2));
3348 sig_off_dif = cpl_table_get_double(gain_table,
"SIG_OFF_DIF",
3350 skip_if(cpl_table_set_double(gain_table,
"SIG_OFF_DIF",
3355 double avg_on_dif, sig_on_dif;
3356 irplib_ksigma_clip(on_dif, 1, 1,
3357 cpl_image_get_size_x(on_dif),
3358 cpl_image_get_size_y(on_dif), kappa,
3359 nclip, 1e-5, &avg_on_dif, &sig_on_dif);
3360 skip_if(cpl_table_set_double(gain_table,
"SIG_ON_DIF", pos, sig_on_dif));
3362 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE)
3364 double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
3368 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
3370 sigma = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
3374 gain = double_adu / (c_ndit * sigma);
3376 gain_corr = gain / (autocorr);
3378 skip_if(cpl_table_set_double(gain_table,
"GAIN", pos, gain));
3379 skip_if(cpl_table_set_double(gain_table,
"GAIN_CORR", pos, gain_corr));
3382 skip_if(cpl_table_set_double(gain_table,
"AUTOCORR", pos, autocorr));
3383 skip_if(cpl_table_set_double(gain_table,
"ADU", pos, double_adu / 2));
3386 skip_if(cpl_table_set_double(gain_table,
"Y_FIT",
3388 c_ndit* sig_on_dif * sig_on_dif));
3389 skip_if(cpl_table_set_double(gain_table,
"Y_FIT_CORR",
3391 c_ndit * sig_on_dif * sig_on_dif));
3392 skip_if(cpl_table_set_double(gain_table,
"X_FIT", pos, double_adu));
3393 skip_if(cpl_table_set_double(gain_table,
"X_FIT_CORR",
3394 pos, double_adu / autocorr));
3399 cpl_image_delete(on_dif);
3401 return cpl_error_get_code();
3414 detmon_bpixs(
const cpl_imagelist * coeffs,
3421 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
3428 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
3429 cpl_image_get_size_y(first));
3430 cpl_image *cur_image = NULL;
3431 cpl_image *bpm = NULL;
3434 size = cpl_imagelist_get_size(coeffs);
3437 bpm = cpl_image_new(cpl_image_get_size_x(first),
3438 cpl_image_get_size_y(first),
3443 for(i = 0; i < size; i++) {
3444 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
3446 stats = cpl_stats_new_from_image(cur_coeff,
3447 CPL_STATS_MEAN | CPL_STATS_STDEV);
3448 cur_mean = cpl_stats_get_mean(stats);
3449 cur_stdev = cpl_stats_get_stdev(stats);
3451 lo_cut = cur_mean - kappa * cur_stdev;
3452 hi_cut = cur_mean + kappa * cur_stdev;
3454 cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
3455 cpl_mask_not(cur_mask);
3458 cur_image = cpl_image_new_from_mask(cur_mask);
3460 cpl_image_power(cur_image, p);
3461 cpl_image_add(bpm, cur_image);
3462 cpl_image_delete(cur_image);
3465 cpl_mask_or(mask, cur_mask);
3467 cpl_mask_delete(cur_mask);
3468 cpl_stats_delete(stats);
3472 bpm = cpl_image_new_from_mask(mask);
3475 *nbpixs += cpl_mask_count(mask);
3477 cpl_mask_delete(mask);
3604 detmon_autocorr_factor(
const cpl_image * image,
3605 cpl_image ** autocorr_image,
int m,
int n)
3607 cpl_image * mycorr_image = NULL;
3608 double autocorr = 0;
3609 cpl_error_code err = CPL_ERROR_NONE;
3611 mycorr_image = detmon_image_correlate(image, image, m, n);
3612 err=cpl_error_get_code();
3613 if (err == CPL_ERROR_UNSUPPORTED_MODE)
3615 cpl_msg_warning(cpl_func,
"FFTW is not supported by CPL, autocorrelation "
3616 "would be computed using internal implementation");
3619 cpl_image_delete(mycorr_image);
3620 mycorr_image = detmon_autocorrelate(image, m, n);
3622 if(mycorr_image == NULL) {
3626 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
3628 autocorr = cpl_image_get_flux(mycorr_image);
3630 if (autocorr_image) *autocorr_image = mycorr_image;
3631 else cpl_image_delete(mycorr_image);
3636 static cpl_propertylist*
3637 detmon_lg_extract_qclist_4plane(cpl_propertylist* linc_qclist,
const int ip)
3640 cpl_propertylist* sub_set=NULL;
3643 sub_set=cpl_propertylist_new();
3644 qc_key=cpl_sprintf(
"QC LIN COEF%d",ip);
3645 cpl_propertylist_copy_property_regexp(sub_set,linc_qclist,qc_key,0);
3662 static cpl_error_code
3663 detmon_lg_extract_extention_header(cpl_frameset* frameset,
3664 cpl_propertylist* gaint_qclist,
3665 cpl_propertylist* lint_qclist,
3666 cpl_propertylist* linc_qclist,
3667 cpl_propertylist* bpm_qclist,
3671 cpl_propertylist * xplist = NULL;
3673 const char * filename =
3674 cpl_frame_get_filename(cpl_frameset_get_first(frameset));
3676 xplist = cpl_propertylist_load_regexp(filename, whichext,
3677 "ESO DET|EXTNAME", 0);
3678 if (detmon_lg_config.exts >= 0)
3681 cpl_property* propExtname = NULL;
3682 propExtname = cpl_propertylist_get_property(xplist,
"EXTNAME");
3684 if (NULL != propExtname)
3686 propExtname = cpl_property_duplicate(propExtname);
3688 cpl_propertylist_delete(xplist);
3690 if (NULL != propExtname)
3692 xplist = cpl_propertylist_new();
3693 cpl_propertylist_append_property(xplist, propExtname);
3694 cpl_property_delete(propExtname);
3699 cpl_propertylist_append(gaint_qclist, xplist);
3700 cpl_propertylist_append(lint_qclist, xplist);
3701 cpl_propertylist_append(linc_qclist, xplist);
3702 cpl_propertylist_append(bpm_qclist, xplist);
3703 cpl_propertylist_delete(xplist);
3706 return cpl_error_get_code();
3723 static cpl_error_code
3724 detmon_lg_save_table_with_pro_keys(cpl_table* table,
3726 cpl_propertylist* xheader,
3727 unsigned CPL_IO_MODE)
3730 cpl_propertylist* pro_keys=NULL;
3732 pro_keys=detmon_load_pro_keys(name_o);
3733 cpl_propertylist_append(xheader,pro_keys);
3735 if(CPL_IO_MODE==CPL_IO_DEFAULT) {
3736 cpl_propertylist * pri_head=cpl_propertylist_load(name_o,0);
3737 cpl_table_save(table, pri_head,xheader,name_o,
3739 cpl_propertylist_delete(pri_head);
3742 cpl_table_save(table,NULL,xheader,name_o,
3745 cpl_propertylist_delete(pro_keys);
3747 return cpl_error_get_code();
3759 static cpl_error_code
3760 detmon_lg_save_image_with_pro_keys(cpl_image* image,
3762 cpl_propertylist* xheader)
3765 cpl_propertylist* pro_keys=NULL;
3766 pro_keys=detmon_load_pro_keys(name_o);
3767 cpl_propertylist_append(xheader,pro_keys);
3769 cpl_image_save(image,name_o, CPL_BPP_IEEE_FLOAT,
3770 xheader,CPL_IO_EXTEND);
3771 cpl_propertylist_delete(pro_keys);
3774 return cpl_error_get_code();
3786 static cpl_error_code
3787 detmon_lg_save_imagelist_with_pro_keys(cpl_imagelist* imagelist,
3789 cpl_propertylist* xheader)
3792 cpl_propertylist* pro_keys=NULL;
3793 pro_keys=detmon_load_pro_keys(name_o);
3794 cpl_propertylist_append(xheader,pro_keys);
3796 cpl_imagelist_save(imagelist,name_o, CPL_BPP_IEEE_FLOAT,
3797 xheader,CPL_IO_EXTEND);
3799 cpl_propertylist_delete(pro_keys);
3802 return cpl_error_get_code();
3822 static cpl_error_code
3823 detmon_lg_save_plane(
const cpl_parameterlist * parlist,
3824 cpl_frameset* frameset,
3825 const cpl_frameset * usedframes,
3827 const char* recipe_name,
3828 cpl_propertylist* mypro_coeffscube,
3829 cpl_propertylist* linc_plane_qclist,
3830 const char* package,
3834 if(detmon_lg_config.exts == 0) {
3835 cpl_propertylist* plist=NULL;
3836 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3838 CPL_BPP_IEEE_FLOAT, recipe_name,
3839 mypro_coeffscube, NULL,
3841 plist=cpl_propertylist_load(NAME_O,0);
3842 cpl_image_save(plane,NAME_O, CPL_BPP_IEEE_FLOAT,
3843 plist,CPL_IO_DEFAULT);
3844 cpl_propertylist_delete(plist);
3846 }
else if(detmon_lg_config.exts > 0) {
3847 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3849 CPL_BPP_IEEE_FLOAT, recipe_name,
3850 mypro_coeffscube, NULL,
3853 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
3857 cpl_dfs_save_image(frameset, NULL, parlist,
3858 usedframes,NULL, NULL,
3859 CPL_BPP_IEEE_FLOAT, recipe_name,
3860 mypro_coeffscube, NULL,
3862 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
3865 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
3871 return cpl_error_get_code();
3894 static cpl_error_code
3895 detmon_lg_save_cube(
const cpl_parameterlist * parlist,
3896 cpl_frameset* frameset,
3897 const cpl_frameset * usedframes,
3899 const char* recipe_name,
3900 cpl_propertylist* mypro_coeffscube,
3901 cpl_propertylist* linc_qclist,
3902 const char* package,
3904 cpl_imagelist* coeffs)
3907 if(detmon_lg_config.exts == 0) {
3908 cpl_propertylist_append(mypro_coeffscube, linc_qclist);
3909 detmon_lg_dfs_save_imagelist
3910 (frameset, parlist, usedframes, coeffs,
3911 recipe_name, mypro_coeffscube, package,
3913 }
else if(detmon_lg_config.exts > 0) {
3914 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3916 CPL_BPP_IEEE_FLOAT, recipe_name,
3917 mypro_coeffscube, NULL,
3920 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
3924 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3926 CPL_BPP_IEEE_FLOAT, recipe_name,
3927 mypro_coeffscube, NULL,
3930 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
3932 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
3935 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
3937 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
3941 return cpl_error_get_code();
3945 detmon_lg_set_paf_name_and_header(cpl_frame* ref_frame,
3946 int flag_sets,
int which_set,
3948 const char* paf_suf,
3949 cpl_propertylist** plist)
3951 char * paf_name=NULL;
3953 if(detmon_lg_config.exts >= 0)
3955 *plist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
3956 detmon_lg_config.exts);
3960 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
3964 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
3965 detmon_lg_config.pafname, paf_suf,which_set);
3970 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
3976 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
3977 detmon_lg_config.pafname, paf_suf,whichext);
3981 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
3982 detmon_lg_config.pafname,paf_suf,
3983 which_set, whichext);
3992 detmon_lg_set_paf_name_and_header_ext(cpl_frame* ref_frame,
3993 int flag_sets,
int which_set,
3995 const char* paf_suf,
3996 cpl_propertylist** plist)
3998 char* paf_name=NULL;
4000 if(detmon_lg_config.exts >= 0)
4002 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4003 detmon_lg_config.exts);
4007 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4010 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4011 detmon_lg_config.pafname, paf_suf,which_set);
4015 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4019 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4020 detmon_lg_config.pafname, paf_suf,whichext);
4023 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4024 detmon_lg_config.pafname,paf_suf,
4025 which_set, whichext);
4032 static cpl_error_code
4033 detmon_lg_save_paf_product(cpl_frame* ref_frame,
int flag_sets,
4034 int which_set,
int whichext,
4035 const char* pafregexp,
4036 const char* procatg,
4037 const char* pipeline_name,
4038 const char* recipe_name,
4039 const char* paf_suf,
4040 cpl_propertylist* qclist,
4045 char* paf_name=NULL;
4046 cpl_propertylist* plist=NULL;
4047 cpl_propertylist* paflist = NULL;
4048 cpl_propertylist* mainplist=NULL;
4050 mainplist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0);
4052 paf_name=detmon_lg_set_paf_name_and_header(ref_frame,flag_sets,
4056 paf_name=detmon_lg_set_paf_name_and_header_ext(ref_frame,flag_sets,
4062 paflist = cpl_propertylist_new();
4063 cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,procatg);
4066 cpl_propertylist_copy_property_regexp(paflist, plist,pafregexp, 0);
4067 cpl_propertylist_copy_property_regexp(paflist, mainplist,pafregexp, 0);
4068 cpl_propertylist_append(paflist,qclist);
4071 cpl_dfs_save_paf(pipeline_name, recipe_name,paflist,paf_name);
4074 cpl_propertylist_delete(mainplist);
4075 cpl_propertylist_delete(paflist);
4076 cpl_propertylist_delete(plist);
4079 return cpl_error_get_code();
4116 static cpl_error_code
4117 detmon_lg_save(
const cpl_parameterlist * parlist,
4118 cpl_frameset * frameset,
4119 const char *recipe_name,
4120 const char *pipeline_name,
4121 const char *pafregexp,
4122 const cpl_propertylist * pro_lintbl,
4123 const cpl_propertylist * pro_gaintbl,
4124 const cpl_propertylist * pro_coeffscube,
4125 const cpl_propertylist * pro_bpm,
4126 const cpl_propertylist * pro_corr,
4127 const cpl_propertylist * pro_diff,
4128 const char *package,
4129 cpl_imagelist * coeffs,
4130 cpl_table * gain_table,
4131 cpl_table * linear_table,
4133 cpl_imagelist * autocorr_images,
4134 cpl_imagelist * diff_flats,
4135 cpl_propertylist * gaint_qclist,
4136 cpl_propertylist * lint_qclist,
4137 cpl_propertylist * linc_qclist,
4138 cpl_propertylist * bpm_qclist,
4139 const int flag_sets,
4140 const int which_set,
4141 const cpl_frameset * usedframes,
4145 cpl_frame *ref_frame;
4146 cpl_propertylist *plist = NULL;
4147 cpl_propertylist *mainplist = NULL;
4153 cpl_propertylist * xplist = NULL;
4155 cpl_propertylist* linc_plane_qclist=NULL;
4156 cpl_image* plane=NULL;
4158 char* pcatg_plane=NULL;
4160 cpl_propertylist * mypro_lintbl =
4161 cpl_propertylist_duplicate(pro_lintbl);
4162 cpl_propertylist * mypro_gaintbl =
4163 cpl_propertylist_duplicate(pro_gaintbl);
4164 cpl_propertylist * mypro_coeffscube =
4165 cpl_propertylist_duplicate(pro_coeffscube);
4166 cpl_propertylist * mypro_bpm =
4167 cpl_propertylist_duplicate(pro_bpm);
4168 cpl_propertylist * mypro_corr =
4169 cpl_propertylist_duplicate(pro_corr);
4170 cpl_propertylist * mypro_diff =
4171 cpl_propertylist_duplicate(pro_diff);
4173 const char * procatg_lintbl =
4174 cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
4176 const char * procatg_gaintbl =
4177 cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
4179 const char * procatg_coeffscube =
4180 cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
4181 const char * procatg_bpm =
4182 cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
4186 detmon_lg_extract_extention_header(frameset,gaint_qclist,lint_qclist,
4187 linc_qclist,bpm_qclist,whichext);
4192 ref_frame = cpl_frameset_get_first(frameset);
4194 skip_if((mainplist =
4195 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4201 cpl_msg_info(cpl_func,
"Write the LINEARITY TABLE");
4204 NAME_O=cpl_sprintf(
"%s_linearity_table.fits", recipe_name);
4206 NAME_O=cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name,
4210 if (detmon_lg_config.exts >= 0) {
4212 cpl_propertylist_append(mypro_lintbl, lint_qclist);
4213 skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,
4214 linear_table,NULL, recipe_name,
4215 mypro_lintbl, NULL, package, NAME_O));
4217 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4218 lint_qclist,CPL_IO_DEFAULT);
4223 skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL,
4224 linear_table,lint_qclist, recipe_name,
4225 mypro_lintbl,NULL, package, NAME_O));
4226 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4227 lint_qclist,CPL_IO_DEFAULT);
4234 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4235 lint_qclist,CPL_IO_EXTEND);
4238 irplib_free(&NAME_O);
4242 cpl_msg_info(cpl_func,
"Write the GAIN TABLE");
4245 NAME_O=cpl_sprintf(
"%s_gain_table.fits", recipe_name);
4247 NAME_O=cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name,
4251 if (detmon_lg_config.exts >= 0)
4255 cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
4256 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
4257 gain_table,NULL, recipe_name, mypro_gaintbl,
4258 NULL, package, NAME_O));
4259 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4260 gaint_qclist,CPL_IO_DEFAULT);
4268 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
4269 gaint_qclist, recipe_name, mypro_gaintbl,
4270 NULL, package, NAME_O));
4271 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4272 gaint_qclist,CPL_IO_DEFAULT);
4278 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4279 gaint_qclist,CPL_IO_EXTEND);
4283 if(detmon_lg_config.pix2pix)
4289 cpl_msg_info(cpl_func,
"Write the COEFFS FITS");
4290 irplib_free(&NAME_O);
4293 PREF_O=cpl_sprintf(
"%s_coeffs_cube", recipe_name);
4296 PREF_O=cpl_sprintf(
"%s_coeffs_cube_set%02d",
4297 recipe_name, which_set);
4299 if (detmon_lg_config.split_coeffs == 0) {
4300 NAME_O=cpl_sprintf(
"%s.fits", PREF_O);
4305 if(detmon_lg_config.split_coeffs != 0){
4308 nb_images = cpl_imagelist_get_size(coeffs);
4309 for(ip=0;ip<nb_images;ip++) {
4310 NAME_O=cpl_sprintf(
"%s_P%d.fits", PREF_O,ip);
4311 pcatg_plane=cpl_sprintf(
"COEFFS_CUBE_P%d",ip);
4312 cpl_propertylist_delete(mypro_coeffscube);
4313 mypro_coeffscube=cpl_propertylist_duplicate(pro_coeffscube);
4314 cpl_propertylist_set_string(mypro_coeffscube,CPL_DFS_PRO_CATG,
4316 linc_plane_qclist=detmon_lg_extract_qclist_4plane(linc_qclist,ip);
4317 cpl_propertylist_append(mypro_coeffscube, linc_plane_qclist);
4318 plane=cpl_imagelist_get(coeffs,ip);
4319 detmon_lg_save_plane(parlist,frameset,usedframes,whichext,
4320 recipe_name,mypro_coeffscube,
4321 linc_plane_qclist,package,NAME_O,plane);
4323 if(NULL!=linc_plane_qclist) {
4324 cpl_propertylist_delete(linc_plane_qclist);
4326 irplib_free(&NAME_O);
4331 detmon_lg_save_cube(parlist,frameset,usedframes,whichext,
4332 recipe_name,mypro_coeffscube,
4333 linc_qclist,package,NAME_O,coeffs);
4339 cpl_msg_info(cpl_func,
"Write the BAD PIXEL MAP");
4340 irplib_free(&NAME_O);
4344 NAME_O=cpl_sprintf(
"%s_bpm.fits", recipe_name);
4347 NAME_O=cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, which_set);
4352 if(detmon_lg_config.exts == 0) {
4353 cpl_propertylist_append(mypro_bpm, bpm_qclist);
4354 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
4355 CPL_BPP_IEEE_FLOAT, recipe_name,
4356 mypro_bpm, NULL, package,
4359 else if(detmon_lg_config.exts > 0)
4361 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4362 CPL_BPP_IEEE_FLOAT, recipe_name,
4363 mypro_bpm, NULL, package,
4365 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4371 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4372 CPL_BPP_IEEE_FLOAT, recipe_name,
4373 mypro_bpm, NULL, package,
4375 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4378 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4383 if(detmon_lg_config.intermediate)
4388 cpl_msg_info(cpl_func,
"Write the AUTOCORRS FITS");
4389 nb_images = cpl_imagelist_get_size(autocorr_images);
4390 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
4391 for(i = 0; i < nb_images; i++)
4393 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_corr);
4395 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4397 if(i < cpl_table_get_nrow(linear_table))
4399 ddit = cpl_table_get_double(linear_table,
4400 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4402 cpl_array_delete(pnames);
4405 irplib_free(&NAME_O);
4408 NAME_O=cpl_sprintf(
"%s_autocorr_%d.fits", recipe_name, i);
4409 assert(NAME_O != NULL);
4412 NAME_O=cpl_sprintf(
"%s_autocorr_%02d_set%02d.fits",
4413 recipe_name, i, which_set);
4414 assert(NAME_O != NULL);
4417 if(detmon_lg_config.exts > 0)
4419 cpl_propertylist* pextlist = cpl_propertylist_new();
4420 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4421 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4422 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4423 recipe_name, pplist, NULL,
4426 detmon_lg_save_image_with_pro_keys(
4427 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4429 cpl_propertylist_delete(pextlist);
4431 if(detmon_lg_config.exts == 0)
4433 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4434 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
4435 cpl_imagelist_get(autocorr_images, i),
4437 recipe_name, pplist, NULL, package,
4443 cpl_propertylist* pextlist = cpl_propertylist_new();
4444 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4447 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4448 usedframes, NULL,NULL,
4449 CPL_BPP_IEEE_FLOAT, recipe_name,
4453 detmon_lg_save_image_with_pro_keys(
4454 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4459 detmon_lg_save_image_with_pro_keys(
4460 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4462 cpl_propertylist_delete(pextlist);
4464 cpl_propertylist_delete (pplist);
4466 irplib_free(&NAME_O);
4475 cpl_msg_info(cpl_func,
"Write the DIFFS FITS");
4477 for(i = 0; i < nb_images; i++)
4479 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_diff);
4481 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4483 if(i < cpl_table_get_nrow(linear_table))
4485 ddit = cpl_table_get_double(linear_table,
4486 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4488 cpl_array_delete(pnames);
4493 NAME_O=cpl_sprintf(
"%s_diff_flat_%d.fits", recipe_name, i);
4496 NAME_O=cpl_sprintf(
"%s_diff_flat_%d_set%02d.fits",
4497 recipe_name, i, which_set);
4500 if(detmon_lg_config.exts > 0)
4502 cpl_propertylist* pextlist = cpl_propertylist_new();
4503 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4504 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT", ddit);
4505 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4506 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4508 mypro_diff, NULL,package, NAME_O));
4510 detmon_lg_save_image_with_pro_keys(
4511 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4513 cpl_propertylist_delete(pextlist);
4515 else if(detmon_lg_config.exts == 0)
4517 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4519 (frameset, NULL, parlist, usedframes, NULL,
4520 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
4521 recipe_name, pplist, NULL, package,
4526 cpl_propertylist* pextlist = cpl_propertylist_new();
4527 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4530 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT",ddit);
4532 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4533 usedframes, NULL,NULL,
4534 CPL_BPP_IEEE_FLOAT, recipe_name,
4535 mypro_diff, NULL,package, NAME_O));
4537 detmon_lg_save_image_with_pro_keys(
4538 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4543 detmon_lg_save_image_with_pro_keys(
4544 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4547 cpl_propertylist_delete(pextlist);
4549 cpl_propertylist_delete(pplist);
4550 irplib_free(&NAME_O);
4558 cpl_msg_info(cpl_func,
"Write the PAF file(s)");
4560 if(detmon_lg_config.pafgen) {
4562 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4563 pafregexp,procatg_gaintbl,
4564 pipeline_name,recipe_name,
4565 "qc01",gaint_qclist,0);
4567 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4568 pafregexp,procatg_lintbl,
4569 pipeline_name,recipe_name,
4570 "qc02",lint_qclist,0);
4572 if(detmon_lg_config.pix2pix)
4575 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4578 pipeline_name,recipe_name,
4579 "qc03",linc_qclist,1);
4581 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4582 whichext,pafregexp,procatg_bpm,
4583 pipeline_name,recipe_name,
4584 "qc04",bpm_qclist,1);
4589 cpl_msg_info(cpl_func,
"exit");
4591 cpl_propertylist_delete(xplist);
4593 cpl_propertylist_delete(plist);
4597 irplib_free(&NAME_O);
4599 cpl_free(pcatg_plane);
4600 cpl_propertylist_delete(mainplist);
4601 cpl_propertylist_delete(mypro_lintbl);
4602 cpl_propertylist_delete(mypro_gaintbl);
4603 cpl_propertylist_delete(mypro_coeffscube);
4604 cpl_propertylist_delete(mypro_bpm);
4605 cpl_propertylist_delete(mypro_corr);
4606 cpl_propertylist_delete(mypro_diff);
4608 return cpl_error_get_code();
4621 static cpl_error_code
4622 detmon_opt_contamination(
const cpl_imagelist * ons,
4623 const cpl_imagelist * offs,
4625 cpl_propertylist * qclist)
4633 struct rect rects[5] = {
4634 (
struct rect){ detmon_lg_config.llx1,
4635 detmon_lg_config.lly1,
4636 detmon_lg_config.urx1,
4637 detmon_lg_config.ury1},
4638 (
struct rect){ detmon_lg_config.llx2,
4639 detmon_lg_config.lly2,
4640 detmon_lg_config.urx2,
4641 detmon_lg_config.ury2},
4642 (
struct rect){ detmon_lg_config.llx3,
4643 detmon_lg_config.lly3,
4644 detmon_lg_config.urx3,
4645 detmon_lg_config.ury3},
4646 (
struct rect){ detmon_lg_config.llx4,
4647 detmon_lg_config.lly4,
4648 detmon_lg_config.urx4,
4649 detmon_lg_config.ury4},
4650 (
struct rect){ detmon_lg_config.llx5,
4651 detmon_lg_config.lly5,
4652 detmon_lg_config.urx5,
4653 detmon_lg_config.ury5},
4656 for (
size_t i = 0; i < 5; i++) {
4657 cpl_image * dif_avg;
4658 const cpl_image * off2;
4661 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
4662 off2 = cpl_imagelist_get_const(offs, 0);
4664 off2 = cpl_imagelist_get_const(offs, 1);
4666 dif_avg = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
4667 cpl_imagelist_get_const(offs, 0),
4668 cpl_imagelist_get_const(ons, 1),
4675 median = cpl_image_get_median(dif_avg);
4676 cpl_image_delete(dif_avg);
4679 sprintf(kname,
"%s%d", DETMON_QC_CONTAM, i + 1);
4681 if(cpl_propertylist_has(qclist,kname)){
4682 skip_if(cpl_propertylist_update_double(qclist,kname,median));
4684 skip_if(cpl_propertylist_append_double(qclist,kname,median));
4685 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
4691 return cpl_error_get_code();
4750 detmon_lg_dfs_set_groups(cpl_frameset *
set,
4751 const char *tag_on,
const char *tag_off)
4753 cpl_frame *cur_frame;
4763 nframes = cpl_frameset_get_size(
set);
4766 for(i = 0; i < nframes; i++) {
4767 cur_frame = cpl_frameset_get_position(
set, i);
4768 tag = cpl_frame_get_tag(cur_frame);
4771 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
4772 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
4792 static cpl_error_code
4793 detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist ** coeffs_ptr,
4794 cpl_image **bpms_ptr)
4796 cpl_image* dummy_bpm=NULL;
4797 cpl_image * dummy_coeff=NULL;
4798 cpl_imagelist * dummy_coeffs=NULL;
4810 dummy_bpm = cpl_image_new(detmon_lg_config.nx,
4811 detmon_lg_config.ny,
4813 dummy_coeffs = cpl_imagelist_new();
4815 db_p = cpl_image_get_data_int(dummy_bpm);
4816 rb_p = cpl_image_get_data_int(*bpms_ptr);;
4817 dcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
4818 rcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
4819 dlength = detmon_lg_config.nx;
4820 rlength = detmon_lg_config.urx - detmon_lg_config.llx + 1;
4821 for (i = 0; i <= detmon_lg_config.order; i++)
4823 dummy_coeff = cpl_image_new(detmon_lg_config.nx,
4824 detmon_lg_config.ny,
4827 cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
4828 dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
4829 rcs_p[i] = cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
4832 for (i = detmon_lg_config.lly - 1; i < detmon_lg_config.ury; i++)
4834 for (j = detmon_lg_config.llx - 1; j < detmon_lg_config.urx; j++)
4836 shift_idx=(i - detmon_lg_config.lly + 1) * rlength +
4837 j - detmon_lg_config.llx + 1;
4838 *(db_p + i * dlength + j) = *(rb_p + shift_idx);
4839 for (k = 0; k <= detmon_lg_config.order; k++)
4841 *(dcs_p[k] + i * dlength + j) =
4842 *(rcs_p[k] + (i - detmon_lg_config.lly + 1) * rlength +
4843 j - detmon_lg_config.llx + 1);
4847 cpl_imagelist_delete(*coeffs_ptr);
4848 cpl_image_delete(*bpms_ptr);
4849 *coeffs_ptr = dummy_coeffs;
4850 *bpms_ptr = dummy_bpm;
4854 return cpl_error_get_code();
4907 static cpl_error_code
4908 detmon_lg_reduce_all(
const cpl_table * linear_table,
4909 cpl_propertylist * gaint_qclist,
4910 cpl_propertylist * lint_qclist,
4911 cpl_propertylist * linc_qclist,
4912 cpl_propertylist * bpm_qclist,
4913 cpl_imagelist ** coeffs_ptr,
4914 cpl_image ** bpms_ptr,
4915 const cpl_imagelist * linearity_inputs,
4916 const cpl_table * gain_table,
4917 int which_ext, cpl_boolean opt_nir)
4921 const int nsets = cpl_table_get_nrow(linear_table);
4923 cpl_polynomial *poly_linfit = NULL;
4924 cpl_image *fiterror = NULL;
4925 char * name_o1 = NULL;
4926 char * name_o2 = NULL;
4927 double * pcoeffs = NULL;
4928 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
4931 cpl_vector *x =NULL;
4932 const cpl_vector *y =NULL;
4935 const cpl_image * first = NULL;
4943 cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
4944 cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
4945 cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
4946 cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
4948 pcoeffs = cpl_malloc(
sizeof(
double)*(detmon_lg_config.order + 1));
4950 skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
4951 detmon_lg_config.method));
4952 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
4953 DETMON_QC_METHOD_C));
4956 if (!strcmp(detmon_lg_config.method,
"PTC")) {
4958 if (detmon_lg_config.exts >= 0) {
4959 cpl_msg_info(cpl_func,
4960 "Polynomial fitting for the GAIN (constant term method)");
4962 cpl_msg_info(cpl_func,
4963 "Polynomial fitting for the GAIN (constant term method)"
4964 " for extension nb %d", which_ext);
4966 skip_if(detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, nsets));
4968 skip_if(detmon_lg_qc_med(gain_table, gaint_qclist, nsets));
4973 if(detmon_lg_config.lamp_ok) {
4974 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
4975 detmon_lg_config.cr));
4976 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
4977 DETMON_QC_LAMP_FLUX_C));
4981 if(detmon_lg_config.autocorr == TRUE) {
4982 autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
4983 skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
4985 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
4986 DETMON_QC_AUTOCORR_C));
4988 if (detmon_lg_config.exts >= 0) {
4989 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix");
4991 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix"
4992 " for extension nb %d", which_ext);
4995 if(!detmon_lg_config.pix2pix) {
4998 y = cpl_vector_wrap(nsets,
4999 (
double *)cpl_table_get_data_double_const(linear_table,
5002 if (opt_nir == NIR) {
5003 x = cpl_vector_wrap(nsets,
5004 (
double *)cpl_table_get_data_double_const(linear_table,
5007 x = cpl_vector_wrap(nsets,
5008 (
double *)cpl_table_get_data_double_const(linear_table,
5012 if(x == NULL || y == NULL) {
5013 cpl_vector_unwrap((cpl_vector *)x);
5014 cpl_vector_unwrap((cpl_vector *)y);
5024 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
5025 poly_linfit = irplib_polynomial_fit_1d_create(x, y,
5026 detmon_lg_config.order,
5029 if(detmon_lg_config.order == cpl_vector_get_size(x) - 1) {
5030 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5034 if(poly_linfit == NULL) {
5035 cpl_vector_unwrap((cpl_vector *)x);
5036 cpl_vector_unwrap((cpl_vector *)y);
5042 min_val=cpl_vector_get_min(y);
5043 max_val=cpl_vector_get_max(y);
5045 cpl_vector_unwrap((cpl_vector *)x);
5046 cpl_vector_unwrap((cpl_vector *)y);
5048 for(deg = 0; deg <= detmon_lg_config.order; deg++) {
5049 const double coeff =
5050 cpl_polynomial_get_coeff(poly_linfit, °);
5052 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
5053 assert(name_o != NULL);
5054 skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
5055 skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
5056 DETMON_QC_LIN_COEF_C));
5059 pcoeffs[deg] = coeff;
5061 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
5062 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
5063 DETMON_QC_ERRFIT_MSE_C));
5068 y = cpl_vector_wrap(nsets,
5069 (
double *)cpl_table_get_data_double_const(linear_table,
5074 x = cpl_vector_wrap(nsets,
5075 (
double *)cpl_table_get_data_double_const(linear_table,
5078 x = cpl_vector_wrap(nsets,
5079 (
double *)cpl_table_get_data_double_const(linear_table,
5084 first = cpl_imagelist_get_const(linearity_inputs, 0);
5085 sizex = cpl_image_get_size_x(first);
5086 sizey = cpl_image_get_size_y(first);
5087 vsize = cpl_vector_get_size(x);
5088 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
5090 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,
5091 detmon_lg_config.order, FALSE,
5092 CPL_TYPE_FLOAT, fiterror);
5093 min_val=cpl_vector_get_min(y);
5094 max_val=cpl_vector_get_max(y);
5095 cpl_vector_unwrap((cpl_vector*)x);
5096 cpl_vector_unwrap((cpl_vector*)y);
5098 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
5099 "Failed polynomial fit");
5102 for(deg = 0; deg <= detmon_lg_config.order; deg++)
5104 cpl_image *image = cpl_imagelist_get(*coeffs_ptr, deg);
5105 const double coeff = cpl_image_get_median(image);
5106 pcoeffs[deg] = coeff;
5107 name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", (
int)deg);
5108 name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", (
int)deg);
5109 assert(name_o1 != NULL);
5110 assert(name_o2 != NULL);
5111 skip_if(cpl_propertylist_append_double(linc_qclist, name_o1, coeff));
5112 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o1,
5113 DETMON_QC_LIN_COEF_C));
5116 skip_if(cpl_propertylist_append_double(linc_qclist, name_o2,
5117 cpl_image_get_stdev(image)));
5118 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o2,
5119 DETMON_QC_LIN_COEF_ERR_C));
5125 if(detmon_lg_config.order == vsize - 1)
5127 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5128 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5130 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5131 DETMON_QC_ERRFIT_C));
5134 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5135 cpl_image_get_median(fiterror)));
5136 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5137 DETMON_QC_ERRFIT_C));
5141 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
5143 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
5144 DETMON_QC_COUNTS_MIN_C));
5145 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
5147 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
5148 DETMON_QC_COUNTS_MAX_C));
5149 skip_if(detmon_lg_lineff(pcoeffs,lint_qclist,detmon_lg_config.ref_level,
5150 detmon_lg_config.order));
5152 if (detmon_lg_config.exts >= 0)
5154 cpl_msg_info(cpl_func,
"Bad pixel detection");
5157 cpl_msg_info(cpl_func,
"Bad pixel detection"
5158 " for extension nb %d", which_ext);
5160 if(detmon_lg_config.pix2pix)
5163 *bpms_ptr = detmon_bpixs(*coeffs_ptr, detmon_lg_config.bpmbin,
5164 detmon_lg_config.kappa, &nbpixs);
5174 skip_if(*bpms_ptr == NULL);
5179 skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
5180 skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
5181 DETMON_QC_NUM_BPM_C));
5182 if(detmon_lg_config.lamp_stability != 0.0)
5184 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
5185 detmon_lg_config.lamp_stability));
5186 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
5187 DETMON_QC_LAMP_STAB_C));
5190 if (!detmon_lg_config.wholechip && detmon_lg_config.pix2pix)
5192 detmon_lg_fits_coeffs_and_bpm2chip(coeffs_ptr,bpms_ptr);
5199 cpl_image_delete(fiterror);
5200 cpl_polynomial_delete(poly_linfit);
5204 return cpl_error_get_code();
5216 static cpl_error_code
5217 detmon_lg_lineff(
double * pcoeffs,
5218 cpl_propertylist * qclist,
5224 double residual, slope;
5227 cpl_polynomial * poly = cpl_polynomial_new(1);
5241 pcoeffs[0] -= ref_level;
5243 for (i = 2; i <= order; i++)
5246 for(j = 0; j < i; j++)
5248 pcoeffs[i] /= pcoeffs[1];
5254 for (deg = 0; deg <= order; deg++) {
5256 skip_if(cpl_polynomial_set_coeff(poly, °, pcoeffs[deg]));
5265 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
5267 if (slope <= 0.0 && residual >= 0.0) {
5268 cpl_msg_warning(cpl_func,
"Reference level (--ref_level) outside"
5269 " linearity range of the detector. Cannot compute"
5270 " linearity efficiency (QC.LINEFF).");
5275 cpl_error_code err = cpl_polynomial_solve_1d(poly, 0.0, &root, 1);
5280 if (err == CPL_ERROR_NONE)
5283 lineff = (root - ref_level) / ref_level;
5288 cpl_msg_warning(cpl_func,
5289 "Cannot compute linearity efficiency (QC.LINEFF)"
5290 "for the current combination "
5291 " of (--ref-level equal %d) and (--order equal %d) parameters. Try "
5292 "to decrease (--ref-level) value.", ref_level, order);
5295 cpl_msg_warning(cpl_func,
"DETMON_QC_LIN_EFF=%f",lineff );
5296 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
5298 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
5299 DETMON_QC_LIN_EFF_C));
5301 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
5303 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
5304 DETMON_QC_LIN_EFF_FLUX_C));
5308 cpl_polynomial_delete(poly);
5310 return cpl_error_get_code();
5321 static cpl_error_code
5322 detmon_lg_qc_ptc(
const cpl_table * gain_table,
5323 cpl_propertylist * qclist,
unsigned mode,
int rows_in_gain)
5326 cpl_polynomial *poly_fit = NULL;
5327 cpl_polynomial *poly_fit2 = NULL;
5329 const int nsets = rows_in_gain;
5331 cpl_vector *x = NULL;
5332 cpl_vector *y = NULL;
5334 cpl_errorstate prestate;
5336 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
5337 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
5339 x = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5341 y = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5343 skip_if(x == NULL || y == NULL);
5344 if (0 == detmon_lg_check_before_gain(x, y))
5348 cpl_vector_unwrap(x);
5352 cpl_vector_unwrap(y);
5354 return CPL_ERROR_NONE;
5357 poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
5358 skip_if(poly_fit == NULL);
5362 prestate = cpl_errorstate_get();
5363 coef = cpl_polynomial_get_coeff(poly_fit, &i);
5364 skip_if (!cpl_errorstate_is_equal(prestate) || coef==0);
5365 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
5366 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5367 DETMON_QC_CONAD_C));
5370 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
5372 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
5388 if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
5389 const cpl_vector *x2 =
5390 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT_CORR"));
5391 const cpl_vector *y2 =
5392 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5394 if(x2 == NULL || y2 == NULL) {
5395 cpl_vector_unwrap((cpl_vector *)x2);
5396 cpl_vector_unwrap((cpl_vector *)y2);
5407 poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
5408 if(poly_fit2 == NULL) {
5409 cpl_vector_unwrap((cpl_vector *)x2);
5410 cpl_vector_unwrap((cpl_vector *)y2);
5412 cpl_msg_error(cpl_func,
"Error during polynomial fit, err[%s]", cpl_error_get_where());
5416 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5417 cpl_vector_unwrap((cpl_vector *)x2);
5418 cpl_vector_unwrap((cpl_vector *)y2);
5419 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5422 prestate = cpl_errorstate_get();
5423 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
5424 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5425 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
5427 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
5429 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
5430 DETMON_QC_CONAD_CORR_C));
5432 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
5434 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
5435 DETMON_QC_GAIN_CORR_C));
5441 cpl_vector_unwrap(x);
5442 cpl_vector_unwrap(y);
5443 cpl_polynomial_delete(poly_fit);
5444 cpl_polynomial_delete(poly_fit2);
5446 return cpl_error_get_code();
5455 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y)
5457 const double TOLERANCE = 1e-37;
5458 double xmin = cpl_vector_get_min(x);
5459 double xmax = cpl_vector_get_max(x);
5460 double ymin = cpl_vector_get_min(y);
5461 double ymax = cpl_vector_get_max(y);
5462 double ystdev = cpl_vector_get_stdev(y);
5463 double xstdev = cpl_vector_get_stdev(x);
5465 if (fabs(xmax-xmin) < TOLERANCE &&
5466 fabs(ymax - ymin) < TOLERANCE &&
5467 xstdev < TOLERANCE &&
5470 cpl_msg_warning(cpl_func,
"An empty frame has been detected, linearity, coeffs, gain, FPN values will not be computed.");
5485 static cpl_error_code
5486 detmon_lg_qc_med(
const cpl_table * gain_table,
5487 cpl_propertylist * qclist,
int rows_in_gain)
5491 cpl_vector *x = NULL;
5492 cpl_vector *y = NULL;
5493 int check_result = 0;
5495 if (rows_in_gain) {};
5497 x = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5498 y = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5499 check_result = detmon_lg_check_before_gain(x, y);
5502 cpl_vector_unwrap(x);
5506 cpl_vector_unwrap(y);
5508 if (0 == check_result)
5510 return CPL_ERROR_NONE;
5513 gain=cpl_table_get_column_median(gain_table,
"GAIN");
5515 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
5517 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
5520 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
5521 cpl_table_get_column_stdev
5522 (gain_table,
"GAIN")));
5523 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
5524 DETMON_QC_GAIN_MSE_C));
5526 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
5527 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5528 DETMON_QC_CONAD_C));
5531 gain=cpl_table_get_column_median(gain_table,
"GAIN_CORR");
5533 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
5535 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
5536 DETMON_QC_GAIN_CORR_C));
5539 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
5540 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
5541 DETMON_QC_CONAD_CORR_C));
5546 return cpl_error_get_code();
5560 static cpl_error_code
5561 detmon_lg_rescale(cpl_imagelist * to_rescale)
5564 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 0),
5565 detmon_lg_config.llx,
5566 detmon_lg_config.lly,
5567 detmon_lg_config.urx,
5568 detmon_lg_config.ury);
5570 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 1),
5571 detmon_lg_config.llx,
5572 detmon_lg_config.lly,
5573 detmon_lg_config.urx,
5574 detmon_lg_config.ury);
5578 if(fabs(med1 / med2 - 1) > 0.001) {
5580 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
5583 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
5589 return cpl_error_get_code();
5592 static cpl_error_code
5593 detmon_pair_extract_next(
const cpl_frameset *
set,
5597 cpl_frameset ** pair,
5601 double dit_next = -100;
5602 cpl_size* selection;
5603 int nsets_extracted = 0;
5604 cpl_ensure_code(
set != NULL, CPL_ERROR_NULL_INPUT);
5605 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
5606 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
5607 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
5609 nsets_extracted = cpl_frameset_get_size(
set);
5610 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
5611 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
5614 dit = dit_array[*next_element ];
5616 if (*next_element < nsets_extracted - 1)
5618 dit_next = dit_array[*next_element + 1 ];
5622 selection[iindex[*next_element] ] = 1;
5623 if (fabs(dit - dit_next) < tolerance)
5626 selection[iindex[*next_element + 1] ] = 1;
5631 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);
5635 cpl_frameset_delete(*pair);
5636 *pair = cpl_frameset_extract(
set, selection, 1);
5639 cpl_free(selection);
5640 return cpl_error_get_code();
5643 static cpl_error_code
5644 detmon_single_extract_next(
const cpl_frameset *
set,
5648 cpl_frameset ** pair)
5650 cpl_size* selection;
5651 int nsets_extracted = 0;
5652 cpl_ensure_code(
set != NULL, CPL_ERROR_NULL_INPUT);
5653 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
5654 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
5655 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
5657 nsets_extracted = cpl_frameset_get_size(
set);
5658 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
5659 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
5662 selection[iindex[*next_element] ] = 1;
5665 cpl_frameset_delete(*pair);
5666 *pair = cpl_frameset_extract(
set, selection, 1);
5668 cpl_free(selection);
5669 return cpl_error_get_code();
5765 detmon_gain(
const cpl_imagelist * imlist_on,
5766 const cpl_imagelist * imlist_off,
5767 const cpl_vector * exptimes,
5768 const cpl_vector * ndit,
5778 cpl_propertylist * qclist,
5780 cpl_imagelist ** diff_imlist,
5781 cpl_imagelist ** autocorr_imlist)
5783 cpl_table * gain_table = NULL;
5784 cpl_imagelist * difflist = NULL;
5785 cpl_imagelist * autocorrlist = NULL;
5786 cpl_imagelist * c_onlist = NULL;
5787 cpl_imagelist * c_offlist = NULL;
5788 cpl_vector * diffdits = NULL;
5789 cpl_vector * diffndits = NULL;
5790 int rows_in_gain = 0;
5791 int ndiffdits, ndits;
5793 cpl_boolean opt_nir = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
5794 const char * method = mode & IRPLIB_GAIN_PTC ?
"PTC" :
"MED";
5796 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
5797 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
5798 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
5799 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
5802 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
5803 skip_if(detmon_gain_table_create(gain_table, opt_nir));
5807 skip_if(detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,
5809 ndiffdits = cpl_vector_get_size(diffdits);
5811 ndits = cpl_vector_get_size(exptimes);
5814 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
5815 difflist = cpl_imagelist_new();
5816 autocorrlist = cpl_imagelist_new();
5819 if (mode & IRPLIB_GAIN_COLLAPSE) {
5820 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
5821 c_offlist = cpl_imagelist_duplicate(imlist_off);
5822 skip_if(detmon_lg_rescale(c_offlist));
5824 c_offlist = (cpl_imagelist *) imlist_off;
5829 for (i = 0; i < ndiffdits; i++) {
5836 c_dit=cpl_vector_get(diffdits, i);
5839 c_ndit=(int)cpl_vector_get(diffndits, i);
5842 c_onlist = cpl_imagelist_new();
5845 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5846 c_offlist = cpl_imagelist_new();
5851 for(j = 0; j < ndits; j++) {
5852 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
5862 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
5863 const cpl_image * im =
5864 cpl_imagelist_get_const(imlist_on, j);
5865 im_on = cpl_image_duplicate(im);
5867 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
5869 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
5876 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5878 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
5879 const cpl_image * im =
5880 cpl_imagelist_get_const(imlist_off, j);
5881 im_off = cpl_image_duplicate(im);
5884 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
5886 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
5893 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
5894 skip_if (c_nons != c_noffs);
5897 skip_if (c_nons == 0 || c_nons % 2 != 0);
5900 if(mode & IRPLIB_GAIN_WITH_RESCALE) {
5901 skip_if(detmon_lg_rescale(c_onlist));
5902 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
5903 skip_if(detmon_lg_rescale(c_offlist));
5909 int rows_affected = 1;
5910 skip_if(detmon_gain_table_fill_row(gain_table,
5914 c_offlist, kappa, nclip,
5916 xshift, yshift,1E10, i,
5917 mode, &rows_affected));
5922 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
5923 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
5924 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
5925 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5926 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
5927 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
5930 cpl_imagelist_unset(c_onlist, 0);
5932 cpl_imagelist_unset(c_onlist, 0);
5934 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5935 cpl_imagelist_unset(c_offlist, 0);
5937 cpl_imagelist_unset(c_offlist, 0);
5945 cpl_imagelist_delete(c_onlist);
5946 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5947 cpl_imagelist_delete(c_offlist);
5951 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
5952 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
5953 DETMON_QC_METHOD_C));
5956 if (mode & IRPLIB_GAIN_PTC) {
5957 skip_if(detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
5959 skip_if(detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
5962 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
5963 double autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
5964 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
5966 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
5967 DETMON_QC_AUTOCORR_C));
5970 if (diff_imlist != NULL) *diff_imlist = difflist;
5971 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
5975 cpl_vector_delete(diffdits);
5976 cpl_vector_delete(diffndits);
5981 static cpl_error_code
5982 detmon_gain_table_create(cpl_table * gain_table,
5983 const cpl_boolean opt_nir)
5985 if (opt_nir == NIR) {
5986 skip_if(cpl_table_new_column(gain_table,
"DIT", CPL_TYPE_DOUBLE));
5987 skip_if(cpl_table_new_column(gain_table,
"NDIT", CPL_TYPE_INT));
5989 skip_if(cpl_table_new_column(gain_table,
"EXPTIME", CPL_TYPE_DOUBLE));
5991 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON1", CPL_TYPE_DOUBLE));
5992 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON2", CPL_TYPE_DOUBLE));
5993 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF1", CPL_TYPE_DOUBLE));
5994 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF2", CPL_TYPE_DOUBLE));
5995 skip_if(cpl_table_new_column(gain_table,
"SIG_ON_DIF", CPL_TYPE_DOUBLE));
5996 skip_if(cpl_table_new_column(gain_table,
"SIG_OFF_DIF", CPL_TYPE_DOUBLE));
5997 skip_if(cpl_table_new_column(gain_table,
"GAIN", CPL_TYPE_DOUBLE));
5998 skip_if(cpl_table_new_column(gain_table,
"AUTOCORR", CPL_TYPE_DOUBLE));
5999 skip_if(cpl_table_new_column(gain_table,
"GAIN_CORR", CPL_TYPE_DOUBLE));
6000 skip_if(cpl_table_new_column(gain_table,
"ADU", CPL_TYPE_DOUBLE));
6001 skip_if(cpl_table_new_column(gain_table,
"X_FIT", CPL_TYPE_DOUBLE));
6002 skip_if(cpl_table_new_column(gain_table,
"X_FIT_CORR", CPL_TYPE_DOUBLE));
6003 skip_if(cpl_table_new_column(gain_table,
"Y_FIT", CPL_TYPE_DOUBLE));
6004 skip_if(cpl_table_new_column(gain_table,
"Y_FIT_CORR", CPL_TYPE_DOUBLE));
6005 skip_if(cpl_table_new_column(gain_table,
"FLAG", CPL_TYPE_INT));
6009 return cpl_error_get_code();
6012 static cpl_error_code
6013 detmon_lin_table_create(cpl_table * lin_table,
6014 const cpl_boolean opt_nir)
6016 if (opt_nir == NIR) {
6017 skip_if(cpl_table_new_column(lin_table,
"DIT", CPL_TYPE_DOUBLE));
6019 skip_if(cpl_table_new_column(lin_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6021 skip_if(cpl_table_new_column(lin_table,
"MED", CPL_TYPE_DOUBLE));
6022 skip_if(cpl_table_new_column(lin_table,
"MEAN", CPL_TYPE_DOUBLE));
6023 skip_if(cpl_table_new_column(lin_table,
"MED_DIT", CPL_TYPE_DOUBLE));
6024 skip_if(cpl_table_new_column(lin_table,
"MEAN_DIT", CPL_TYPE_DOUBLE));
6025 skip_if(cpl_table_new_column(lin_table,
"ADL", CPL_TYPE_DOUBLE));
6028 return cpl_error_get_code();
6032 detmon_lg_find_dits(
const cpl_vector * exptimes,
6035 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6041 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
6045 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
6047 for (j = 0; j < ndits; j++) {
6048 if (fabs(cpl_vector_get(exptimes, i) -
6049 cpl_vector_get(dits, j)) > tolerance)
6052 if(ndiffs == ndits) {
6053 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
6058 cpl_vector_set_size(dits, ndits);
6066 static cpl_error_code
6067 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
6068 const cpl_vector * vec_ndits,
6070 cpl_vector** diff_dits,
6071 cpl_vector** diff_ndits)
6079 * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6080 * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
6083 cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
6084 cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
6087 size=cpl_vector_get_size(exptimes);
6089 for(i = 1; i < size; i++) {
6091 for (j = 0; j < ndits; j++) {
6092 if (fabs(cpl_vector_get(exptimes, i) -
6093 cpl_vector_get(*diff_dits,j)) > tolerance)
6096 if(ndiffs == ndits) {
6097 cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
6098 cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
6103 cpl_vector_set_size(*diff_dits, ndits);
6104 cpl_vector_set_size(*diff_ndits, ndits);
6107 return cpl_error_get_code();
6195 detmon_lin(
const cpl_imagelist * imlist_on,
6196 const cpl_imagelist * imlist_off,
6197 const cpl_vector * exptimes,
6207 cpl_propertylist * qclist,
6209 cpl_imagelist ** coeffs_cube,
6212 cpl_table * lin_table = NULL;
6213 cpl_imagelist * c_onlist = NULL;
6214 cpl_imagelist * c_offlist = NULL;
6215 cpl_vector * diffdits = NULL;
6216 cpl_imagelist * lin_inputs = NULL;
6217 cpl_polynomial * poly_linfit = NULL;
6218 cpl_image * fiterror = NULL;
6219 cpl_vector * vcoeffs = NULL;
6220 double * pcoeffs = NULL;
6221 int ndiffdits, ndits;
6223 cpl_boolean opt_nir = mode & IRPLIB_LIN_OPT ? OPT : NIR;
6224 const cpl_vector *x = NULL;
6225 const cpl_vector *y = NULL;
6227 const cpl_image * first = NULL;
6235 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6236 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6237 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6238 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6239 cpl_ensure(order > 0 , CPL_ERROR_ILLEGAL_INPUT, NULL);
6241 vcoeffs = cpl_vector_new(order + 1);
6242 pcoeffs = cpl_vector_get_data(vcoeffs);
6245 if (mode & IRPLIB_LIN_PIX2PIX) {
6246 cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
6247 cpl_ensure(bpm != NULL, CPL_ERROR_NULL_INPUT, NULL);
6248 lin_inputs = cpl_imagelist_new();
6252 lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6253 skip_if(detmon_lin_table_create(lin_table, opt_nir));
6257 diffdits = detmon_lg_find_dits(exptimes, tolerance);
6258 ndiffdits = cpl_vector_get_size(diffdits);
6260 ndits = cpl_vector_get_size(exptimes);
6290 if (mode & IRPLIB_LIN_COLLAPSE) {
6295 cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
6296 skip_if(collapse == NULL);
6298 c_offlist = cpl_imagelist_new();
6299 skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
6303 for (i = 0; i < ndiffdits; i++) {
6307 double c_dit = cpl_vector_get(diffdits, i);
6309 c_onlist = cpl_imagelist_new();
6312 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6313 c_offlist = cpl_imagelist_new();
6317 for(j = 0; j < ndits; j++) {
6318 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6328 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6329 const cpl_image * im =
6330 cpl_imagelist_get_const(imlist_on, j);
6331 im_on = cpl_image_duplicate(im);
6333 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6335 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6342 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6344 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6345 const cpl_image * im =
6346 cpl_imagelist_get_const(imlist_off, j);
6347 im_off = cpl_image_duplicate(im);
6350 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6352 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6359 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6360 skip_if (c_nons != c_noffs);
6363 skip_if (c_nons == 0 || c_nons % 2 != 0);
6366 if(mode & IRPLIB_LIN_WITH_RESCALE) {
6367 skip_if(detmon_lg_rescale(c_onlist));
6368 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6369 skip_if(detmon_lg_rescale(c_offlist));
6376 skip_if(detmon_lin_table_fill_row(lin_table, c_dit,
6378 c_onlist, c_offlist,
6382 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6383 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6384 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6385 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6386 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6387 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6390 cpl_imagelist_unset(c_onlist, 0);
6392 cpl_imagelist_unset(c_onlist, 0);
6394 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6395 cpl_imagelist_unset(c_offlist, 0);
6397 cpl_imagelist_unset(c_offlist, 0);
6405 cpl_imagelist_delete(c_onlist);
6406 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6407 cpl_imagelist_delete(c_offlist);
6411 skip_if(detmon_add_adl_column(lin_table, opt_nir));
6413 if(!(mode & IRPLIB_LIN_PIX2PIX)) {
6416 y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6417 (
double *)cpl_table_get_data_double_const(lin_table,
6419 if (opt_nir == NIR) {
6420 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6421 (
double *)cpl_table_get_data_double_const(lin_table,
"DIT"));
6423 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6424 (
double *)cpl_table_get_data_double_const(lin_table,
"EXPTIME"));
6426 if(x == NULL || y == NULL) {
6427 cpl_vector_unwrap((cpl_vector *)x);
6428 cpl_vector_unwrap((cpl_vector *)y);
6438 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
6439 poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
6441 if(order == cpl_vector_get_size(x) - 1) {
6442 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
6446 if(poly_linfit == NULL) {
6447 cpl_vector_unwrap((cpl_vector *)x);
6448 cpl_vector_unwrap((cpl_vector *)y);
6453 cpl_vector_unwrap((cpl_vector *)x);
6454 cpl_vector_unwrap((cpl_vector *)y);
6456 for(deg = 0; deg <= order; deg++) {
6457 const double coeff =
6458 cpl_polynomial_get_coeff(poly_linfit, °);
6460 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
6461 assert(name_o != NULL);
6462 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
6463 skip_if(cpl_propertylist_set_comment(qclist,name_o,
6464 DETMON_QC_LIN_COEF_C));
6466 pcoeffs[deg] = coeff;
6468 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
6469 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
6470 DETMON_QC_ERRFIT_MSE_C));
6474 if (opt_nir == NIR) {
6475 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6476 (
double *)cpl_table_get_data_double_const(lin_table,
6479 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6480 (
double *)cpl_table_get_data_double_const(lin_table,
6485 first = cpl_imagelist_get_const(lin_inputs, 0);
6486 sizex = cpl_image_get_size_x(first);
6487 sizey = cpl_image_get_size_y(first);
6489 vsize = cpl_vector_get_size(x);
6491 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
6494 cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
6495 order, FALSE, CPL_TYPE_FLOAT,
6498 cpl_vector_unwrap((cpl_vector*)x);
6499 irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
6500 "Failed polynomial fit");
6502 for(i = 0; i <= order; i++) {
6503 cpl_image *image = cpl_imagelist_get(*coeffs_cube, i);
6504 const double coeff = cpl_image_get_median(image);
6505 char * name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", i);
6506 char * name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", i);
6508 assert(name_o1 != NULL);
6509 assert(name_o2 != NULL);
6510 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
6511 skip_if(cpl_propertylist_set_comment(qclist,name_o1,
6512 DETMON_QC_LIN_COEF_C));
6515 skip_if(cpl_propertylist_append_double(qclist, name_o2,
6516 cpl_image_get_stdev(image)));
6517 skip_if(cpl_propertylist_set_comment(qclist,name_o2,
6518 DETMON_QC_LIN_COEF_ERR_C));
6523 if(order == vsize - 1) {
6524 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
6525 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
6527 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
6528 DETMON_QC_ERRFIT_C));
6532 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
6533 cpl_image_get_median(fiterror)));
6534 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
6535 DETMON_QC_ERRFIT_C));
6540 skip_if(detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
6542 if(mode & IRPLIB_LIN_PIX2PIX) {
6544 *bpm = detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
6545 skip_if(*bpm == NULL);
6546 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
6548 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
6549 DETMON_QC_NUM_BPM_C));
6554 cpl_vector_delete(diffdits);
6555 cpl_polynomial_delete(poly_linfit);
6556 cpl_imagelist_delete(lin_inputs);
6557 cpl_vector_delete(vcoeffs);
6558 cpl_image_delete(fiterror);
6589 static cpl_error_code
6590 detmon_lin_table_fill_row(cpl_table * lin_table,
double c_dit,
6591 cpl_imagelist * linearity_inputs,
6592 const cpl_imagelist * ons,
6593 const cpl_imagelist * offs,
6602 cpl_image * extracted=NULL;
6604 cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
6605 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
6606 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
6608 if (mode & IRPLIB_LIN_PIX2PIX) {
6609 cpl_msg_debug(cpl_func,
"checking linearity inputs");
6610 cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
6614 if (mode & IRPLIB_LIN_NIR) {
6615 cpl_table_set(lin_table,
"DIT", pos, c_dit);
6616 }
else if (mode & IRPLIB_LIN_OPT) {
6617 cpl_table_set(lin_table,
"EXPTIME", pos, c_dit);
6619 cpl_msg_error(cpl_func,
"Mandatory mode not given");
6623 const cpl_image * off2;
6624 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
6625 off2 = cpl_imagelist_get_const(offs, 0);
6627 off2 = cpl_imagelist_get_const(offs, 1);
6629 extracted = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
6630 cpl_imagelist_get_const(offs, 0),
6631 cpl_imagelist_get_const(ons, 1),
6633 llx, lly, urx, ury);
6634 cpl_ensure_code(extracted != NULL, cpl_error_get_code());
6638 double median = cpl_image_get_median(extracted);
6639 double mean= cpl_image_get_mean(extracted);
6640 cpl_table_set(lin_table,
"MED", pos, median);
6641 cpl_table_set(lin_table,
"MEAN", pos, mean);
6643 cpl_table_set(lin_table,
"MED_DIT", pos, median / c_dit);
6644 cpl_table_set(lin_table,
"MEAN_DIT", pos, mean / c_dit);
6648 if(mode & IRPLIB_LIN_PIX2PIX) {
6649 cpl_error_code error = cpl_imagelist_set(linearity_inputs, extracted,
6651 cpl_ensure_code(!error, error);
6653 cpl_image_delete(extracted);
6656 return cpl_error_get_code();
6659 static double irplib_calculate_total_noise_smooth(
const cpl_image* pimage,
6660 int pattern_x,
int pattern_y)
6662 cpl_image * p_tmp_image = 0;
6663 cpl_image * psmooth_image = 0;
6665 cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
6667 p_tmp_image = cpl_image_duplicate(pimage);
6668 cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
6669 cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
6670 psmooth_image = cpl_image_divide_create(pimage,p_tmp_image);
6671 ret_noise = irplib_calculate_total_noise(psmooth_image);
6672 cpl_mask_delete(mask);
6673 cpl_image_delete(psmooth_image);
6674 cpl_image_delete(p_tmp_image);
6678 static double irplib_calculate_total_noise(
const cpl_image* pimage)
6680 double total_noise = -1;
6681 unsigned long max_bin_size = 1E5;
6682 const double hstart = cpl_image_get_min(pimage);
6683 const double hrange = cpl_image_get_max(pimage) - hstart;
6684 const unsigned long nbins = max_bin_size;
6685 cpl_error_code err = CPL_ERROR_NONE;
6687 irplib_hist * phist = 0;
6688 phist = irplib_hist_new();
6691 irplib_hist_init(phist, nbins, hstart, hrange);
6692 err = irplib_hist_fill(phist, pimage);
6693 if (err == CPL_ERROR_NONE)
6701 unsigned long n_bins = irplib_hist_get_nbins(phist);
6702 double start = irplib_hist_get_start(phist);
6703 double bin_size = irplib_hist_get_bin_size(phist);
6704 cpl_vector* pdata_vector = cpl_vector_new(n_bins);
6705 cpl_vector* ppos_vector = cpl_vector_new(n_bins);
6706 cpl_table* ptable = cpl_table_new(n_bins);
6707 cpl_table_new_column(ptable,
"bin", CPL_TYPE_DOUBLE);
6708 cpl_table_new_column(ptable,
"value", CPL_TYPE_DOUBLE);
6709 for(i = 0; i < n_bins; i++)
6711 unsigned int value = irplib_hist_get_value(phist, i);
6712 double dvalue = (double)(value);
6713 cpl_vector_set(pdata_vector, i, dvalue);
6714 cpl_vector_set(ppos_vector, i, start + i * bin_size);
6716 cpl_table_set(ptable,
"bin", i, start + i * bin_size);
6717 cpl_table_set(ptable,
"value", i, dvalue);
6719 err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
6720 if (err == CPL_ERROR_NONE)
6722 cpl_msg_info(cpl_func,
"FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
6726 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed Gaussian Fit, err msg [%s]", cpl_error_get_message());
6729 cpl_table_delete(ptable);
6730 cpl_vector_delete(ppos_vector);
6731 cpl_vector_delete(pdata_vector);
6735 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
6738 irplib_hist_delete(phist);
6743 static double irplib_compute_err(
double gain,
double ron,
double FA)
6745 double int_gain = (gain * gain - 1) / 12;
6750 return sqrt(ron * ron + FA / gain + int_gain);
6753 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain ,
6754 FPN_METHOD fpn_method,
int smooth_size,
double* mse)
6756 cpl_image* im_diff = 0;
6757 const cpl_image* im_f1 = f1;
6758 cpl_image* im_inrange1 = 0;
6767 cpl_msg_warning(cpl_func,
"gain[%f]<0", gain);
6768 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
6775 im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
6776 im_f1 = im_inrange1;
6778 FA = cpl_image_get_median(im_f1);
6785 cpl_msg_info(cpl_func,
"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
6786 s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
6789 cpl_msg_info(cpl_func,
"HISTOGRAM method is used for FPN");
6790 s_tot = irplib_calculate_total_noise(im_f1);
6795 cpl_msg_warning(cpl_func,
"fpn_method is not defined");
6804 cpl_msg_warning(cpl_func,
"Median flux on sum of flats<0");
6805 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
6810 if ((s_tot * s_tot - FA / gain) > 0)
6812 s_fpn = sqrt(s_tot * s_tot - FA / gain);
6813 sr_fpn = s_fpn / FA;
6814 *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
6818 cpl_msg_warning(cpl_func,
"s_tot * s_tot < FA / gain");
6819 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
6828 cpl_image_delete(im_diff);
6831 cpl_image_delete(im_inrange1);
6837 static cpl_imagelist * irplib_load_fset_wrp(
const cpl_frameset * pframeset,
6838 cpl_type type ,
int whichext)
6842 return detmon_load_frameset_window(pframeset, type, 0, whichext,
6843 detmon_lg_config.llx,
6844 detmon_lg_config.lly,
6845 detmon_lg_config.urx,
6846 detmon_lg_config.ury,
6847 detmon_lg_config.nx,
6848 detmon_lg_config.ny);
6851 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset * pframeset,
6852 cpl_type type ,
int whichext)
6855 cpl_imagelist* offs = cpl_imagelist_new();
6856 detmon_lg_config.load_fset(pframeset, type, offs);
6861 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
6862 cpl_propertylist* plist)
6864 if (ptable && plist)
6866 int size = cpl_propertylist_get_size(plist);
6868 for (i = 0; i < size; i++)
6870 cpl_property* pprop = cpl_propertylist_get(plist,i);
6873 const char* pname = cpl_property_get_name(pprop);
6876 cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
6877 if (cpl_error_get_code() != CPL_ERROR_NONE)
6879 cpl_msg_warning(cpl_func,
"cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
6886 return cpl_error_get_code();
6889 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
6890 cpl_propertylist* plist,
int row)
6892 cpl_error_code err = CPL_ERROR_NONE;
6893 if (ptable && plist)
6895 int size = cpl_propertylist_get_size(plist);
6897 for (i = 0; i < size; i++)
6899 cpl_property* pprop = cpl_propertylist_get(plist,i);
6902 const char* pname = cpl_property_get_name(pprop);
6903 double value = cpl_property_get_double(pprop);
6906 cpl_table_set_double(ptable, pname, row, value);
6907 if (cpl_error_get_code() != CPL_ERROR_NONE)
6909 cpl_msg_warning(cpl_func,
"cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
6920 cpl_error_code detmon_check_order(
const double *exptime,
int sz,
6921 double tolerance,
int order)
6938 }
while(fabs(exptime[i-1] - exptime[i]) < tolerance);
6939 }
while(i < sz - 1);
6941 if (!fabs(exptime[i-1] - exptime[i]) < tolerance) nsets++;
6944 cpl_error_set_message(cpl_func,CPL_ERROR_INCOMPATIBLE_INPUT,
6945 "Not enough frames for the polynomial"
6946 " fitting. nsets = %d <= %d order",
6949 return cpl_error_get_code();
6952 static cpl_error_code
6953 detmon_lg_dfs_save_imagelist(
6954 cpl_frameset * frameset,
6955 const cpl_parameterlist * parlist,
6956 const cpl_frameset *usedframes,
6957 const cpl_imagelist *coeffs,
6958 const char *recipe_name,
6959 const cpl_propertylist *mypro_coeffscube,
6960 const char * package,
6961 const char * name_o)
6963 return(cpl_dfs_save_imagelist
6964 (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
6965 recipe_name, mypro_coeffscube, NULL, package,
6969 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos)
6971 const cpl_image* first = cpl_imagelist_get(imlist, 0);
6974 int x = cpl_image_get_size_x(first);
6975 int y = cpl_image_get_size_y(first);
6976 cpl_type type = cpl_image_get_type(first);
6977 cpl_image * blank = cpl_image_new(x, y, type);
6978 cpl_imagelist_set(imlist, blank, pos);
6984 detmon_lg_set_tag(cpl_frameset*
set,
const char** tag_on,
const char** tag_off)
6989 ntag_old=cpl_frameset_count_tags(
set,DETMON_LG_ON_RAW_OLD);
6990 ntag_new=cpl_frameset_count_tags(
set,DETMON_LG_ON_RAW_NEW);
6992 *tag_on=DETMON_LG_ON_RAW_OLD;
6993 *tag_off=DETMON_LG_OFF_RAW_OLD;
6994 }
else if (ntag_new) {
6995 *tag_on=DETMON_LG_ON_RAW_NEW;
6996 *tag_off=DETMON_LG_OFF_RAW_NEW;
6998 cpl_msg_error(cpl_func,
"Provide %s and %s (or %s and %s) input frames",
6999 DETMON_LG_ON_RAW_NEW,DETMON_LG_OFF_RAW_NEW,
7000 DETMON_LG_ON_RAW_OLD,DETMON_LG_OFF_RAW_OLD);
7004 return cpl_error_get_code();