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_default_mr(cpl_parameterlist * parlist,
1519 const char *recipe_name,
1520 const char *pipeline_name)
1522 char * group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1523 char * par_name = cpl_sprintf(
"%s.%s", group_name,
"regions-file");
1524 cpl_parameter * p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1525 "File containing regions, "
1526 "four comma separated points "
1529 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions-file");
1530 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1531 cpl_parameterlist_append(parlist, p);
1533 cpl_free(group_name);
1535 group_name = cpl_sprintf(
"%s.%s", pipeline_name, recipe_name);
1536 par_name = cpl_sprintf(
"%s.%s", group_name,
"regions");
1537 p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1538 "Colon separated list of regions, four "
1539 "points each, comma separated: "
1540 "llx,lly,urx,ury:llx,...",
1542 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"regions");
1543 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1544 cpl_parameterlist_append(parlist, p);
1546 cpl_free(group_name);
1548 return cpl_error_get_code();
1552 detmon_lg_fill_parlist_opt_default_mr(cpl_parameterlist * parlist,
1553 const char *recipe_name,
1554 const char *pipeline_name)
1556 detmon_lg_fill_parlist_opt_default(parlist, recipe_name, pipeline_name);
1557 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1561 detmon_lg_fill_parlist_nir_default_mr(cpl_parameterlist * parlist,
1562 const char *recipe_name,
1563 const char *pipeline_name)
1565 detmon_lg_fill_parlist_nir_default(parlist, recipe_name, pipeline_name);
1566 detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1568 return cpl_error_get_code();
1628 detmon_lg_fill_parlist(cpl_parameterlist * parlist,
1629 const char *recipe_name,
const char *pipeline_name,
1639 const char *intermediate,
1640 const char *autocorr,
1641 const char *collapse,
1642 const char *rescale,
1643 const char *pix2pix,
1650 const char * pafname,
1667 int llx5,
int lly5,
int urx5,
int ury5,
int exts,
1668 cpl_boolean opt_nir)
1670 const cpl_error_code error =
1671 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 25,
1673 "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
1674 "CPL_TYPE_STRING", method,
1677 "Polynomial order for the fit (Linearity)",
1678 "CPL_TYPE_INT", order,
1680 "Kappa value for the kappa-sigma clipping (Gain)",
1681 "CPL_TYPE_DOUBLE", kappa,
1683 "Number of iterations to compute rms (Gain)",
1684 "CPL_TYPE_INT", niter,
1686 "x coordinate of the lower-left "
1687 "point of the region of interest. If not modified, default value will be 1.",
1688 "CPL_TYPE_INT", llx,
1690 "y coordinate of the lower-left "
1691 "point of the region of interest. If not modified, default value will be 1.",
1692 "CPL_TYPE_INT", lly,
1694 "x coordinate of the upper-right "
1695 "point of the region of interest. If not modified, default value will be X dimension of the input image.",
1696 "CPL_TYPE_INT", urx,
1698 "y coordinate of the upper-right "
1699 "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
1700 "CPL_TYPE_INT", ury,
1702 "User reference level",
1703 "CPL_TYPE_INT", ref_level,
1705 "De-/Activate intermediate products",
1706 "CPL_TYPE_BOOL", intermediate,
1709 "De-/Activate the autocorr option",
1710 "CPL_TYPE_BOOL", autocorr,
1713 "De-/Activate the collapse option",
1714 "CPL_TYPE_BOOL", collapse,
1716 "De-/Activate the image rescale option",
1717 "CPL_TYPE_BOOL", rescale,
1719 "De-/Activate the computation with pixel to pixel accuracy",
1720 "CPL_TYPE_BOOL", pix2pix,
1722 "De-/Activate the binary bpm option",
1723 "CPL_TYPE_BOOL", bpmbin,
1725 "Maximum x-shift for the autocorr",
1728 "Upper limit of Median flux to be filtered",
1729 "CPL_TYPE_INT", filter,
1731 "Maximum y-shift for the autocorr",
1734 "Tolerance for pair discrimination",
1735 "CPL_TYPE_DOUBLE", tolerance,
1738 "Generate PAF file",
1739 "CPL_TYPE_BOOL", pafgen,
1741 "Specific name for PAF file",
1742 "CPL_TYPE_STRING", pafname,
1746 "Activate the multi-exts option. Choose -1 to process all extensions. Choose an extension number"
1747 " to process the appropriate extension.",
1748 "CPL_TYPE_INT", exts,
1751 "Method for computing Fixed Pattern Noise (SMOOTH or HISTOGRAM)",
1752 "CPL_TYPE_STRING",
"HISTOGRAM",
1755 "template size in pixels for smoothing during FPN computation (only for SMOOTH method)",
1759 "all frames with mean saturation above the limit would not be used in calculation",
1760 "CPL_TYPE_DOUBLE", 65535.0
1762 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 1,
1763 "coeffs_cube_split",
1764 "if TRUE, the recipe writes as many "
1765 "COEFFS_CUBE_Pi (i=0..order) as the value of "
1766 "the order parameter in a separate file",
1767 "CPL_TYPE_BOOL",
"CPL_FALSE");
1769 if(opt_nir == FALSE) {
1770 const cpl_error_code erroropt =
1771 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
1773 "x coord of the lower-left point of the first "
1774 "field used for contamination measurement. If not modified, default value will be 1.",
1775 "CPL_TYPE_INT", llx1,
1777 "y coord of the lower-left point of the first "
1778 "field used for contamination measurement. If not modified, default value will be 1.",
1779 "CPL_TYPE_INT", lly1,
1781 "x coord of the upper-right point of the first "
1782 "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
1783 "CPL_TYPE_INT", urx1,
1785 "y coord of the upper-right point of the first "
1786 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1787 "CPL_TYPE_INT", ury1,
1789 "x coord of the lower-left point of the second "
1790 "field used for contamination measurement. If not modified, default value will be 1.",
1791 "CPL_TYPE_INT", llx2,
1793 "y coord of the lower-left point of the second "
1794 "field used for contamination measurement. If not modified, default value will be 1.",
1795 "CPL_TYPE_INT", lly2,
1797 "x coord of the upper-right point of the second "
1798 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1799 "CPL_TYPE_INT", urx2,
1801 "y coord of the upper-right point of the second "
1802 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1803 "CPL_TYPE_INT", ury2,
1805 "x coord of the lower-left point of the third "
1806 "field used for contamination measurement. If not modified, default value will be 1.",
1807 "CPL_TYPE_INT", llx3,
1809 "y coord of the lower-left point of the third "
1810 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1811 "CPL_TYPE_INT", lly3,
1813 "x coord of the upper-right point of the third "
1814 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1815 "CPL_TYPE_INT", urx3,
1817 "y coord of the upper-right point of the third "
1818 "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
1819 "CPL_TYPE_INT", ury3,
1821 "x coord of the lower-left point of the fourth "
1822 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1823 "CPL_TYPE_INT", llx4,
1825 "y coord of the lower-left point of the fourth "
1826 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1827 "CPL_TYPE_INT", lly4,
1829 "x coord of the upper-right point of the fourth "
1830 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1831 "CPL_TYPE_INT", urx4,
1833 "y coord of the upper-right point of the fourth "
1834 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1835 "CPL_TYPE_INT", ury4,
1837 "x coord of the lower-left point of the fifth "
1838 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1839 "CPL_TYPE_INT", llx5,
1841 "y coord of the lower-left point of the fifth "
1842 "field used for contamination measurement. If not modified, default value will be 1.",
1843 "CPL_TYPE_INT", lly5,
1845 "x coord of the upper-right point of the fifth "
1846 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1847 "CPL_TYPE_INT", urx5,
1850 "y coord of the upper-right point of the fifth "
1851 "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
1852 "CPL_TYPE_INT", ury5);
1853 cpl_ensure_code(!erroropt, erroropt);
1856 cpl_ensure_code(!error, error);
1858 return cpl_error_get_code();
1871 static cpl_error_code
1872 detmon_lg_retrieve_parlist(
const char * pipeline_name,
1873 const char * recipe_name,
1874 const cpl_parameterlist * parlist,
1875 cpl_boolean opt_nir)
1879 cpl_parameter * par;
1882 par_name = cpl_sprintf(
"%s.%s.method", pipeline_name, recipe_name);
1883 assert(par_name != NULL);
1884 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1885 detmon_lg_config.method = cpl_parameter_get_string(par);
1889 detmon_lg_config.order =
1890 detmon_retrieve_par_int(
"order", pipeline_name, recipe_name,
1894 detmon_lg_config.kappa =
1895 detmon_retrieve_par_double(
"kappa", pipeline_name, recipe_name,
1899 detmon_lg_config.niter =
1900 detmon_retrieve_par_int(
"niter", pipeline_name, recipe_name,
1904 detmon_lg_config.llx =
1905 detmon_retrieve_par_int(
"llx", pipeline_name, recipe_name,
1909 detmon_lg_config.lly =
1910 detmon_retrieve_par_int(
"lly", pipeline_name, recipe_name,
1914 detmon_lg_config.urx =
1915 detmon_retrieve_par_int(
"urx", pipeline_name, recipe_name,
1919 detmon_lg_config.ury =
1920 detmon_retrieve_par_int(
"ury", pipeline_name, recipe_name,
1924 detmon_lg_config.ref_level =
1925 detmon_retrieve_par_int(
"ref_level", pipeline_name, recipe_name,
1930 cpl_sprintf(
"%s.%s.intermediate", pipeline_name, recipe_name);
1931 assert(par_name != NULL);
1932 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1933 detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
1937 par_name = cpl_sprintf(
"%s.%s.autocorr", pipeline_name, recipe_name);
1938 assert(par_name != NULL);
1939 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1940 detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
1944 par_name = cpl_sprintf(
"%s.%s.coeffs_cube_split", pipeline_name, recipe_name);
1945 assert(par_name != NULL);
1946 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1947 detmon_lg_config.split_coeffs = cpl_parameter_get_bool(par);
1951 par_name = cpl_sprintf(
"%s.%s.collapse", pipeline_name, recipe_name);
1952 assert(par_name != NULL);
1953 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1954 detmon_lg_config.collapse = cpl_parameter_get_bool(par);
1958 par_name = cpl_sprintf(
"%s.%s.rescale", pipeline_name, recipe_name);
1959 assert(par_name != NULL);
1960 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1961 detmon_lg_config.rescale = cpl_parameter_get_bool(par);
1965 par_name = cpl_sprintf(
"%s.%s.pix2pix", pipeline_name, recipe_name);
1966 assert(par_name != NULL);
1967 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1968 detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
1972 par_name = cpl_sprintf(
"%s.%s.bpmbin", pipeline_name, recipe_name);
1973 assert(par_name != NULL);
1974 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1975 detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
1979 detmon_lg_config.filter =
1980 detmon_retrieve_par_int(
"filter", pipeline_name,
1981 recipe_name, parlist);
1984 detmon_lg_config.m =
1985 detmon_retrieve_par_int(
"m", pipeline_name, recipe_name, parlist);
1988 detmon_lg_config.n =
1989 detmon_retrieve_par_int(
"n", pipeline_name, recipe_name, parlist);
1992 par_name = cpl_sprintf(
"%s.%s.tolerance", pipeline_name, recipe_name);
1993 assert(par_name != NULL);
1994 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1995 detmon_lg_config.tolerance = cpl_parameter_get_double(par);
2000 par_name = cpl_sprintf(
"%s.%s.pafgen", pipeline_name, recipe_name);
2001 assert(par_name != NULL);
2002 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2003 detmon_lg_config.pafgen = cpl_parameter_get_bool(par);
2007 par_name = cpl_sprintf(
"%s.%s.pafname", pipeline_name, recipe_name);
2008 assert(par_name != NULL);
2009 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2010 detmon_lg_config.pafname = cpl_parameter_get_string(par);
2013 if(opt_nir == OPT) {
2015 detmon_lg_config.llx1 =
2016 detmon_retrieve_par_int(
"llx1", pipeline_name, recipe_name,
2020 detmon_lg_config.lly1 =
2021 detmon_retrieve_par_int(
"lly1", pipeline_name, recipe_name,
2025 detmon_lg_config.urx1 =
2026 detmon_retrieve_par_int(
"urx1", pipeline_name, recipe_name,
2030 detmon_lg_config.ury1 =
2031 detmon_retrieve_par_int(
"ury1", pipeline_name, recipe_name,
2035 detmon_lg_config.llx2 =
2036 detmon_retrieve_par_int(
"llx2", pipeline_name, recipe_name,
2040 detmon_lg_config.lly2 =
2041 detmon_retrieve_par_int(
"lly2", pipeline_name, recipe_name,
2045 detmon_lg_config.urx2 =
2046 detmon_retrieve_par_int(
"urx2", pipeline_name, recipe_name,
2050 detmon_lg_config.ury2 =
2051 detmon_retrieve_par_int(
"ury2", pipeline_name, recipe_name,
2055 detmon_lg_config.llx3 =
2056 detmon_retrieve_par_int(
"llx3", pipeline_name, recipe_name,
2060 detmon_lg_config.lly3 =
2061 detmon_retrieve_par_int(
"lly3", pipeline_name, recipe_name,
2065 detmon_lg_config.urx3 =
2066 detmon_retrieve_par_int(
"urx3", pipeline_name, recipe_name,
2070 detmon_lg_config.ury3 =
2071 detmon_retrieve_par_int(
"ury3", pipeline_name, recipe_name,
2075 detmon_lg_config.llx4 =
2076 detmon_retrieve_par_int(
"llx4", pipeline_name, recipe_name,
2080 detmon_lg_config.lly4 =
2081 detmon_retrieve_par_int(
"lly4", pipeline_name, recipe_name,
2085 detmon_lg_config.urx4 =
2086 detmon_retrieve_par_int(
"urx4", pipeline_name, recipe_name,
2090 detmon_lg_config.ury4 =
2091 detmon_retrieve_par_int(
"ury4", pipeline_name, recipe_name,
2095 detmon_lg_config.llx5 =
2096 detmon_retrieve_par_int(
"llx5", pipeline_name, recipe_name,
2100 detmon_lg_config.lly5 =
2101 detmon_retrieve_par_int(
"lly5", pipeline_name, recipe_name,
2105 detmon_lg_config.urx5 =
2106 detmon_retrieve_par_int(
"urx5", pipeline_name, recipe_name,
2110 detmon_lg_config.ury5 =
2111 detmon_retrieve_par_int(
"ury5", pipeline_name, recipe_name,
2116 detmon_lg_config.exts =
2117 detmon_retrieve_par_int(
"exts", pipeline_name, recipe_name,
2121 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2123 cpl_sprintf(
"%s.%s.fpn_method", pipeline_name, recipe_name);
2124 assert(par_name != NULL);
2125 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2128 const char * str_method = cpl_parameter_get_string(par);
2129 if (strcmp(str_method,
"SMOOTH") == 0)
2131 detmon_lg_config.fpn_method = FPN_SMOOTH;
2133 else if (strcmp(str_method,
"HISTOGRAM") == 0)
2135 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
2141 detmon_lg_config.fpn_smooth =
2142 detmon_retrieve_par_int(
"fpn_smooth", pipeline_name, recipe_name,
2146 detmon_lg_config.saturation_limit = 65535;
2148 cpl_sprintf(
"%s.%s.saturation_limit", pipeline_name, recipe_name);
2149 assert(par_name != NULL);
2150 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2153 detmon_lg_config.saturation_limit = cpl_parameter_get_double(par);
2157 if(cpl_error_get_code())
2159 cpl_msg_error(cpl_func,
"Failed to retrieve the input parameters");
2160 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
2164 return cpl_error_get_code();
2174 static cpl_error_code
2175 detmon_lg_check_defaults(
const cpl_image * reference)
2177 const int nx = cpl_image_get_size_x(reference);
2178 const int ny = cpl_image_get_size_y(reference);
2180 detmon_lg_config.nx = nx;
2181 detmon_lg_config.ny = ny;
2183 detmon_lg_config.wholechip = CPL_FALSE;
2185 if(detmon_lg_config.llx == -1)
2186 detmon_lg_config.llx = 1;
2187 if(detmon_lg_config.lly == -1)
2188 detmon_lg_config.lly = 1;
2189 if(detmon_lg_config.urx == -1)
2190 detmon_lg_config.urx = nx;
2191 if(detmon_lg_config.ury == -1)
2192 detmon_lg_config.ury = ny;
2194 if (detmon_lg_config.llx == 1 &&
2195 detmon_lg_config.lly == 1 &&
2196 detmon_lg_config.urx == nx &&
2197 detmon_lg_config.ury == ny)
2198 detmon_lg_config.wholechip = CPL_TRUE;
2200 if(detmon_lg_config.llx1 == -1)
2201 detmon_lg_config.llx1 = 1;
2202 if(detmon_lg_config.lly1 == -1)
2203 detmon_lg_config.lly1 = 1;
2204 if(detmon_lg_config.urx1 == -1)
2205 detmon_lg_config.urx1 = nx;
2206 if(detmon_lg_config.ury1 == -1)
2207 detmon_lg_config.ury1 = ny;
2209 if(detmon_lg_config.llx2 == -1)
2210 detmon_lg_config.llx2 = 1;
2211 if(detmon_lg_config.lly2 == -1)
2212 detmon_lg_config.lly2 = 1;
2213 if(detmon_lg_config.urx2 == -1)
2214 detmon_lg_config.urx2 = nx / 2;
2215 if(detmon_lg_config.ury2 == -1)
2216 detmon_lg_config.ury2 = ny / 2;
2218 if(detmon_lg_config.llx3 == -1)
2219 detmon_lg_config.llx3 = 1;
2220 if(detmon_lg_config.lly3 == -1)
2221 detmon_lg_config.lly3 = ny / 2;
2222 if(detmon_lg_config.urx3 == -1)
2223 detmon_lg_config.urx3 = nx / 2;
2224 if(detmon_lg_config.ury3 == -1)
2225 detmon_lg_config.ury3 = ny;
2227 if(detmon_lg_config.llx4 == -1)
2228 detmon_lg_config.llx4 = nx / 2;
2229 if(detmon_lg_config.lly4 == -1)
2230 detmon_lg_config.lly4 = ny / 2;
2231 if(detmon_lg_config.urx4 == -1)
2232 detmon_lg_config.urx4 = nx;
2233 if(detmon_lg_config.ury4 == -1)
2234 detmon_lg_config.ury4 = ny;
2236 if(detmon_lg_config.llx5 == -1)
2237 detmon_lg_config.llx5 = nx / 2;
2238 if(detmon_lg_config.lly5 == -1)
2239 detmon_lg_config.lly5 = 1;
2240 if(detmon_lg_config.urx5 == -1)
2241 detmon_lg_config.urx5 = nx;
2242 if(detmon_lg_config.ury5 == -1)
2243 detmon_lg_config.ury5 = ny / 2;
2245 if(detmon_lg_config.intermediate == TRUE) {
2246 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.");
2247 detmon_lg_config.autocorr = TRUE;
2251 detmon_lg_config.lamp_stability = 0.0;
2253 detmon_lg_config.lamp_ok = FALSE;
2255 detmon_lg_config.cr = 0.0;
2257 return cpl_error_get_code();
2272 static cpl_error_code
2273 detmon_lg_split_onoff(
const cpl_frameset * cur_fset,
2274 cpl_frameset * cur_fset_on,
2275 cpl_frameset * cur_fset_off,
2277 const char *tag_off)
2282 cpl_frame * cur_frame_dup = NULL;
2285 const cpl_frame * first;
2286 const cpl_frame * second;
2287 const char * first_tag;
2288 const char * second_tag;
2289 skip_if((first = cpl_frameset_get_first_const(cur_fset)) == NULL);
2290 skip_if((second = cpl_frameset_get_next_const (cur_fset)) == NULL);
2292 skip_if((first_tag = cpl_frame_get_tag(first)) == NULL);
2293 skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
2294 if (opt_nir == OPT &&
2295 ((!strcmp(first_tag, tag_on ) && !strcmp(second_tag, tag_off)) ||
2296 (!strcmp(first_tag, tag_off) && !strcmp(second_tag, tag_on )))) {
2297 detmon_lg_config.lamp_ok = TRUE;
2301 nframes = cpl_frameset_get_size(cur_fset);
2302 for(i = detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
2303 const cpl_frame * cur_frame =
2304 cpl_frameset_get_position_const(cur_fset, i);
2308 cur_frame_dup = cpl_frame_duplicate(cur_frame);
2309 tag = (
char *) cpl_frame_get_tag(cur_frame_dup);
2312 if(!strcmp(tag, tag_on)) {
2313 skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
2314 }
else if(!strcmp(tag, tag_off)) {
2315 skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
2317 cpl_frame_delete(cur_frame_dup);
2318 cur_frame_dup = NULL;
2321 cur_frame_dup = NULL;
2325 cpl_frame_delete(cur_frame_dup);
2327 return cpl_error_get_code();
2354 static cpl_error_code
2355 detmon_lg_reduce(
const cpl_frameset * set_on,
2356 const cpl_frameset * set_off,
2357 int* index_on,
int* index_off,
2358 double* exptime_on,
double* exptime_off,
2359 int *next_index_on,
int* next_index_off,
2360 cpl_imagelist ** coeffs_ptr,
2361 cpl_table * gain_table,
2362 cpl_table * linear_table,
2363 cpl_image ** bpm_ptr,
2364 cpl_imagelist * autocorr_images,
2365 cpl_imagelist * diff_flats,
2366 cpl_propertylist * gaint_qclist,
2367 cpl_propertylist * lint_qclist,
2368 cpl_propertylist * linc_qclist,
2369 cpl_propertylist * bpm_qclist,
2370 int (* load_fset) (
const cpl_frameset *,
2373 const cpl_boolean opt_nir,
2376 cpl_errorstate prestate = cpl_errorstate_get();
2377 const double D_INVALID_VALUE = -999;
2379 cpl_imagelist * linearity_inputs = NULL;
2380 cpl_imagelist * opt_offs = NULL;
2382 cpl_propertylist * reflist = NULL;
2384 int rows_affected = 1;
2387 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2388 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2390 nsets = cpl_frameset_get_size(set_on) / 2;
2392 detmon_lg_config.load_fset = load_fset;
2393 if(detmon_lg_config.collapse) {
2400 const cpl_frame *first = cpl_frameset_get_first_const(set_off);
2401 cpl_frame *dup_first = cpl_frame_duplicate(first);
2403 const cpl_frame *second = cpl_frameset_get_next_const(set_off);
2404 cpl_frame *dup_second = cpl_frame_duplicate(second);
2406 cpl_frameset *raw_offs = cpl_frameset_new();
2408 skip_if(cpl_frameset_insert(raw_offs, dup_first));
2409 skip_if(cpl_frameset_insert(raw_offs, dup_second));
2411 opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
2414 cpl_frameset_delete(raw_offs);
2415 if (opt_offs == NULL) {
2416 cpl_errorstate_set(prestate);
2417 return CPL_ERROR_CONTINUE;
2421 skip_if(detmon_lg_reduce_init(gain_table,
2433 if(detmon_lg_lamp_stab(set_on, set_off,
2434 opt_nir, whichext)) {
2435 cpl_errorstate_set(prestate);
2438 if(!detmon_lg_config.collapse)
2442 skip_if(cpl_table_unselect_all(linear_table));
2443 skip_if(cpl_table_unselect_all(gain_table));
2447 for(i = 0; i < nsets ; i++)
2449 skip_if(detmon_lg_reduce_dit(set_on,
2450 index_on, exptime_on,
2454 index_off, exptime_off,
2455 next_index_on, next_index_off,
2457 gain_table, linearity_inputs,
2458 lint_qclist, opt_nir,
2459 autocorr_images, diff_flats,
2462 if (rows_affected == 0)
2464 cpl_msg_warning(cpl_func,
"The rest frames would not be taken "
2465 "into calculation, check the messages above");
2466 cpl_table_select_row(linear_table, i);
2467 cpl_table_select_row(gain_table, i);
2474 skip_if(detmon_add_adl_column(linear_table, opt_nir));
2480 skip_if(cpl_table_erase_selected(gain_table));
2481 skip_if(cpl_table_erase_selected(linear_table));
2483 reflist = cpl_propertylist_new();
2484 skip_if(cpl_propertylist_append_bool(reflist,
"ADU", FALSE));
2485 skip_if(cpl_table_sort(gain_table, reflist));
2491 skip_if(detmon_lg_reduce_all(linear_table,
2492 gaint_qclist, lint_qclist, linc_qclist,
2493 bpm_qclist, coeffs_ptr, bpm_ptr,
2495 gain_table, whichext, opt_nir));
2498 double gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
2501 cpl_error_code cplerr = cpl_error_get_code();
2502 if (cplerr != CPL_ERROR_NONE || (gain == 0.0))
2504 cpl_msg_warning(cpl_func,
"Cannot read gain from QC parameters - "
2505 "FPN will not be computed");
2510 detmon_fpn_compute(set_on, index_on, last_best, lint_qclist,
2511 detmon_lg_config.llx,
2512 detmon_lg_config.lly,
2513 detmon_lg_config.urx,
2514 detmon_lg_config.ury,
2517 detmon_lg_config.fpn_method,
2518 detmon_lg_config.fpn_smooth);
2523 detmon_table_fill_invalid(gain_table, D_INVALID_VALUE);
2525 cpl_imagelist_delete(linearity_inputs);
2526 cpl_imagelist_delete(opt_offs);
2527 cpl_propertylist_delete(reflist);
2529 return cpl_error_get_code();
2532 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable,
double code)
2534 int ncols = cpl_table_get_ncol(ptable);
2535 cpl_array* pnames = cpl_table_get_column_names(ptable);
2536 int nrows = cpl_table_get_nrow(ptable);
2538 for (i=0; i < ncols; i++)
2541 for (j = 0; j< nrows; j++)
2543 const char* colname = cpl_array_get_data_string_const(pnames)[i];
2545 cpl_type type = cpl_table_get_column_type(ptable, colname);
2546 cpl_table_get(ptable, colname, j, &isnull);
2549 if (type == CPL_TYPE_DOUBLE)
2551 cpl_table_set(ptable,colname,j, code);
2553 else if (type == CPL_TYPE_FLOAT)
2555 cpl_table_set_float(ptable,colname,j, (
float)code);
2560 cpl_array_delete(pnames);
2561 return cpl_error_get_code();
2564 static cpl_error_code
2565 detmon_fpn_compute(
const cpl_frameset *set_on,
2568 cpl_propertylist *lint_qclist,
2575 FPN_METHOD fpn_method,
2579 const cpl_image* im1 = 0;
2581 cpl_imagelist* ons = 0;
2582 cpl_frameset * pair_on = 0;
2583 int nsets_extracted = cpl_frameset_get_size(set_on);
2584 cpl_size * selection = NULL;
2593 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
2594 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
2596 selection[index_on[last_best*2 + 0] ] = 1;
2597 selection[index_on[last_best*2 + 1] ] = 1;
2598 pair_on = cpl_frameset_extract(set_on, selection, 1);
2599 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2601 skip_if(ons == NULL);
2602 skip_if((im1 = cpl_imagelist_get_const(ons, 0)) == NULL);
2604 fpn = irplib_fpn_lg(im1, range, gain, fpn_method, smooth_size, &mse);
2605 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_FPN,
2607 skip_if(cpl_propertylist_append_double(lint_qclist,
"ESO QC GAIN ERR",
2611 cpl_frameset_delete(pair_on);
2612 cpl_imagelist_delete(ons);
2613 cpl_free(selection);
2614 return cpl_error_get_code();
2626 static cpl_error_code
2627 detmon_lg_lamp_stab(
const cpl_frameset * lamps,
2628 const cpl_frameset * darks,
2629 cpl_boolean opt_nir,
2642 cpl_vector * selection = NULL;
2643 cpl_propertylist * plist;
2644 double dit_lamp, dit_dark;
2646 cpl_imagelist * lamps_data = NULL;
2647 cpl_imagelist * darks_data = NULL;
2648 double * stab_levels = NULL;
2650 double * ditvals = NULL;
2654 cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
2655 CPL_ERROR_ILLEGAL_INPUT);
2661 cpl_msg_info(__func__,
"Checking DIT consistency");
2662 selection = cpl_vector_new(nb_lamps);
2663 ditvals = cpl_malloc(nb_lamps *
sizeof(
double));
2665 for (i = 0; i < nb_lamps; i++) {
2666 const cpl_frame * c_lamp;
2667 const cpl_frame * c_dark;
2669 skip_if (cpl_error_get_code());
2672 c_lamp = cpl_frameset_get_position_const(lamps, i);
2673 plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
2675 dit_lamp = (double)irplib_pfits_get_dit(plist);
2677 dit_lamp = (double)irplib_pfits_get_dit_opt(plist);
2678 cpl_propertylist_delete(plist);
2679 skip_if (cpl_error_get_code());
2682 c_dark = cpl_frameset_get_position_const(darks, i);
2683 plist = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
2685 dit_dark = (double)irplib_pfits_get_dit(plist);
2687 dit_dark = (double)irplib_pfits_get_dit_opt(plist);
2688 cpl_propertylist_delete(plist);
2689 skip_if (cpl_error_get_code());
2692 if (fabs(dit_dark-dit_lamp) > 1e-3) {
2693 cpl_msg_error(__func__,
"DIT not consistent between LAMP and DARK, skip lamp stability computation");
2698 ditvals[i] = dit_lamp;
2701 cpl_vector_set(selection, i, -1.0);
2709 if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
2710 cpl_vector_set(selection, i, -1.0);
2714 cpl_vector_set(selection, i, 1.0);
2721 cpl_msg_info(__func__,
"Not enough frames for stability check");
2725 cpl_msg_info(__func__,
"Compute the differences lamp - dark");
2728 lamps_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2730 detmon_lg_config.llx,
2731 detmon_lg_config.lly,
2732 detmon_lg_config.urx,
2733 detmon_lg_config.ury,
2736 darks_data = detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2738 detmon_lg_config.llx,
2739 detmon_lg_config.lly,
2740 detmon_lg_config.urx,
2741 detmon_lg_config.ury,
2744 nb_darks=cpl_imagelist_get_size(darks_data);
2745 if(nb_darks==nb_lamps) {
2746 skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
2748 cpl_image* master_dark=cpl_imagelist_collapse_median_create(darks_data);
2749 cpl_imagelist_subtract_image(lamps_data,master_dark);
2750 cpl_image_delete(master_dark);
2753 cpl_msg_info(__func__,
"Check the lamp stability");
2754 stab_levels = cpl_malloc(dit_stab *
sizeof(
double));
2756 for (i=0; i<nb_lamps; i++) {
2757 if (cpl_vector_get(selection, i) < 0) {
2759 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
2765 for (i=1; i<dit_stab; i++) {
2766 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
2767 detmon_lg_config.lamp_stability)
2768 detmon_lg_config.lamp_stability =
2769 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
2774 if (detmon_lg_config.lamp_stability > 0.01) {
2775 cpl_msg_warning(__func__,
2776 "Lamp stability level %g difference too high - proceed anyway",detmon_lg_config.lamp_stability);
2783 cpl_vector_delete(selection);
2784 cpl_imagelist_delete(lamps_data);
2785 cpl_imagelist_delete(darks_data);
2786 cpl_free(stab_levels);
2788 return cpl_error_get_code();
2815 static cpl_error_code
2816 detmon_lg_reduce_dit(
const cpl_frameset * set_on,
2817 int* index_on,
double* exptime_on,
2820 const cpl_frameset * set_off,
2821 int * index_off,
double* exptime_off,
2822 int* next_on,
int* next_off,
2823 cpl_table * linear_table,
2824 cpl_table * gain_table,
2825 cpl_imagelist * linearity_inputs,
2826 cpl_propertylist * qclist,
2827 cpl_boolean opt_nir,
2828 cpl_imagelist * autocorr_images,
2829 cpl_imagelist * diff_flats,
2830 cpl_imagelist * opt_offs,
2834 cpl_frameset * pair_on = NULL;
2835 cpl_frameset * pair_off = NULL;
2836 cpl_imagelist * ons = NULL;
2837 cpl_imagelist * offs = NULL;
2838 cpl_boolean follow = CPL_TRUE;
2839 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
2843 double current_dit = 0;
2845 const char * filename;
2847 cpl_propertylist * plist = NULL;
2848 cpl_propertylist* pDETlist = NULL;
2850 mode = detmon_lg_config.collapse ?
2851 mode | IRPLIB_GAIN_COLLAPSE | IRPLIB_LIN_COLLAPSE:
2852 mode | IRPLIB_GAIN_NO_COLLAPSE | IRPLIB_LIN_NO_COLLAPSE;
2853 mode = detmon_lg_config.pix2pix ?
2854 mode | IRPLIB_LIN_PIX2PIX : mode;
2856 mode | IRPLIB_GAIN_NIR | IRPLIB_LIN_NIR :
2857 mode | IRPLIB_GAIN_OPT | IRPLIB_LIN_OPT ;
2861 skip_if(detmon_pair_extract_next(set_on, index_on, next_on, exptime_on, &pair_on, detmon_lg_config.tolerance));
2862 current_dit = exptime_on[*next_on - 1];
2865 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2866 skip_if(ons == NULL);
2867 cpl_msg_debug(cpl_func,
" Loaded ON images: %" CPL_SIZE_FORMAT
2868 ", exptime[%f]",cpl_imagelist_get_size(ons), current_dit );
2869 if(cpl_imagelist_get_size(ons) != 2)
2871 cpl_msg_error(cpl_func,
"cannot take ON pair, number of images[%"
2872 CPL_SIZE_FORMAT
"]", cpl_imagelist_get_size(ons));
2875 if(detmon_lg_config.filter > 0)
2878 cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
2879 detmon_lg_config.llx,
2880 detmon_lg_config.lly,
2881 detmon_lg_config.urx,
2882 detmon_lg_config.ury);
2884 cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
2885 detmon_lg_config.llx,
2886 detmon_lg_config.lly,
2887 detmon_lg_config.urx,
2888 detmon_lg_config.ury);
2889 if ( med1 > (
double)detmon_lg_config.filter ||
2890 med2 > (
double)detmon_lg_config.filter)
2893 cpl_table_select_row(gain_table, dit_nb);
2894 cpl_table_select_row(linear_table, dit_nb);
2896 cpl_msg_warning(cpl_func,
"Frames of EXPTIME nb %d "
2897 "will not be taken into account for computation "
2898 "as they are above --filter threshold", dit_nb);
2902 if (follow || detmon_lg_config.filter < 0)
2910 if(!detmon_lg_config.collapse)
2927 if (!strcmp(detmon_lg_config.method,
"MED") ||
2928 cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
2930 skip_if(detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off, detmon_lg_config.tolerance));
2934 skip_if(detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
2937 cpl_msg_debug(cpl_func,
" Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
2938 offs = detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
2940 skip_if(offs == NULL);
2941 skip_if(cpl_error_get_code());
2944 offs = (cpl_imagelist *) opt_offs;
2948 if(detmon_lg_config.rescale)
2950 skip_if(detmon_lg_rescale(ons));
2951 if (!detmon_lg_config.collapse &&
2952 !strcmp(detmon_lg_config.method,
"MED"))
2953 skip_if(detmon_lg_rescale(offs));
2958 cpl_frame_get_filename(cpl_frameset_get_first_const(pair_on));
2959 skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
2963 pDETlist = cpl_propertylist_new();
2964 cpl_propertylist_copy_property_regexp(pDETlist, plist,
"DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
2967 irplib_table_create_column(gain_table, pDETlist);
2968 irplib_table_create_column(linear_table, pDETlist);
2971 if(opt_nir == NIR) {
2972 c_dit = irplib_pfits_get_dit(plist);
2973 c_ndit = irplib_pfits_get_ndit(plist);
2975 c_dit = irplib_pfits_get_exptime(plist);
2987 cpl_msg_info(cpl_func,
"Computing GAIN for EXPTIME value nb %d",
2991 if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
2993 cpl_table_erase_column(gain_table,
"MEAN_OFF1");
2994 cpl_table_erase_column(gain_table,
"MEAN_OFF2");
2995 cpl_table_erase_column(gain_table,
"SIG_OFF_DIF");
2996 cpl_table_erase_column(gain_table,
"GAIN");
2997 cpl_table_erase_column(gain_table,
"GAIN_CORR");
2998 cpl_table_new_column(gain_table,
"MEAN_OFF", CPL_TYPE_DOUBLE);
3001 skip_if(detmon_gain_table_fill_row(gain_table,
3004 diff_flats, ons, offs,
3005 detmon_lg_config.kappa,
3006 detmon_lg_config.niter,
3007 detmon_lg_config.llx,
3008 detmon_lg_config.lly,
3009 detmon_lg_config.urx,
3010 detmon_lg_config.ury,
3013 detmon_lg_config.saturation_limit,
3014 dit_nb, mode, rows_affected));
3020 skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
3022 cpl_msg_info(cpl_func,
"Linearity reduction for nb %d",
3024 skip_if(detmon_lin_table_fill_row(linear_table, c_dit,
3025 linearity_inputs, ons, offs,
3026 detmon_lg_config.llx,
3027 detmon_lg_config.lly,
3028 detmon_lg_config.urx,
3029 detmon_lg_config.ury,
3030 dit_nb, *dit_nskip, mode));
3032 skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
3044 if(opt_nir == OPT &&
3045 *rows_affected != 0 ) {
3046 detmon_opt_contamination(ons, offs, mode, qclist);
3053 cpl_frameset_delete(pair_on);
3054 cpl_imagelist_delete(ons);
3056 if(!detmon_lg_config.collapse ) {
3057 cpl_imagelist_delete(offs);
3060 if(!detmon_lg_config.collapse) {
3061 cpl_frameset_delete(pair_off);
3064 cpl_propertylist_delete(plist);
3065 cpl_propertylist_delete(pDETlist);
3066 return cpl_error_get_code();
3076 static cpl_error_code
3077 detmon_add_adl_column(cpl_table * table,
3078 cpl_boolean opt_nir)
3080 cpl_error_code error;
3081 double mean_med_dit;
3084 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
3086 mean_med_dit = cpl_table_get_column_mean(table,
"MED_DIT");
3088 dits = cpl_table_get_data_double(table,
"EXPTIME");
3090 dits = cpl_table_get_data_double(table,
"DIT");
3092 error = cpl_table_copy_data_double(table,
"ADL", dits);
3093 cpl_ensure_code(!error, error);
3094 error = cpl_table_multiply_scalar(table,
"ADL", mean_med_dit);
3095 cpl_ensure_code(!error, error);
3097 return cpl_error_get_code();
3109 static cpl_error_code
3110 detmon_lg_reduce_init(cpl_table * gain_table,
3111 cpl_table * linear_table,
3112 cpl_imagelist ** linearity_inputs,
3113 const cpl_boolean opt_nir)
3115 skip_if(detmon_gain_table_create(gain_table, opt_nir));
3116 skip_if(detmon_lin_table_create(linear_table, opt_nir));
3118 if(detmon_lg_config.pix2pix) {
3119 *linearity_inputs = cpl_imagelist_new();
3120 skip_if(*linearity_inputs == NULL);
3125 return cpl_error_get_code();
3136 irplib_pfits_get_dit(
const cpl_propertylist * plist)
3138 return irplib_pfits_get_prop_double(plist,
"ESO DET DIT");
3149 irplib_pfits_get_dit_opt(
const cpl_propertylist * plist)
3151 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3160 static cpl_propertylist*
3161 detmon_load_pro_keys(
const char* NAME_O)
3163 cpl_propertylist* pro_keys=NULL;
3164 pro_keys=cpl_propertylist_load_regexp(NAME_O,0,
"^(ESO PRO)",0);
3169 static double irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
3170 const char* prop_name)
3173 dit = cpl_propertylist_get_double(plist, prop_name);
3174 if(cpl_error_get_code() != CPL_ERROR_NONE)
3176 cpl_msg_error(cpl_func,
"Cannot read property '%s', err[%s]",
3177 prop_name, cpl_error_get_where());
3215 static cpl_error_code
3216 detmon_gain_table_fill_row(cpl_table * gain_table,
3217 double c_dit,
int c_ndit,
3218 cpl_imagelist * autocorr_images,
3219 cpl_imagelist * diff_flats,
3220 const cpl_imagelist * ons,
3221 const cpl_imagelist * offs,
3222 double kappa,
int nclip,
3223 int llx,
int lly,
int urx,
int ury,
3225 double saturation_limit,
3226 const int pos,
unsigned mode,
int* rows_affected)
3228 const cpl_image *image;
3229 cpl_image *on_dif = NULL;
3231 double avg_on1, avg_on2;
3232 double avg_off1, avg_off2;
3233 double double_adu, autocorr, gain, gain_corr;
3236 cpl_table_set(gain_table,
"FLAG", pos, 1);
3237 if (mode & IRPLIB_GAIN_NIR)
3239 cpl_table_set(gain_table,
"DIT", pos, c_dit);
3240 cpl_table_set(gain_table,
"NDIT", pos, c_ndit);
3241 }
else if (mode & IRPLIB_GAIN_OPT)
3243 cpl_table_set(gain_table,
"EXPTIME", pos, c_dit);
3246 cpl_msg_error(cpl_func,
"Mandatory mode (OPT or NIR) not provided");
3249 if(*rows_affected == 0)
3251 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3252 cpl_table_set(gain_table,
"FLAG", pos, 0);
3253 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3258 detmon_lg_add_empty_image(diff_flats, pos);
3260 if (autocorr_images)
3262 detmon_lg_add_empty_image(autocorr_images, pos);
3265 return cpl_error_get_code();
3267 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3268 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3269 nclip, 1e-5, &avg_on1, &std));
3270 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3271 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3272 nclip, 1e-5, &avg_on2, &std));
3274 if ((avg_on1 > saturation_limit) || (avg_on2 > saturation_limit))
3276 cpl_msg_warning(cpl_func,
"Average saturation is above the limit, "
3277 "the frames would not be taken into calculation");
3278 cpl_msg_warning(cpl_func,
"saturation levels [%f ; %f], limit [%f]",
3279 avg_on1, avg_on2, saturation_limit);
3280 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3281 cpl_table_set(gain_table,
"FLAG", pos, 0);
3282 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3287 detmon_lg_add_empty_image(diff_flats, pos);
3289 if (autocorr_images)
3291 detmon_lg_add_empty_image(autocorr_images, pos);
3300 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON1", pos, avg_on1));
3301 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON2", pos, avg_on2));
3304 detmon_subtract_create_window(cpl_imagelist_get_const(ons, 0),
3305 cpl_imagelist_get_const(ons, 1),
3306 llx, lly, urx, ury);
3307 skip_if(on_dif == NULL);
3309 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3313 cpl_image * diff = cpl_image_duplicate(on_dif);
3314 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
3316 if (autocorr_images)
3318 cpl_image * corr = NULL;
3319 autocorr = detmon_autocorr_factor(on_dif, &corr, m, n);
3322 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
3326 detmon_lg_add_empty_image(autocorr_images, pos);
3330 autocorr = detmon_autocorr_factor(on_dif, NULL, m, n);
3332 autocorr = isnan(autocorr) ? 1.0 : autocorr;
3338 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE)
3341 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3342 llx, lly, urx, ury, kappa, nclip,
3343 1e-5, &avg_off1, &std));
3344 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF", pos, avg_off1));
3346 }
else if (mode & IRPLIB_GAIN_NO_COLLAPSE ||
3347 ( pos == 0 && mode & IRPLIB_GAIN_COLLAPSE )) {
3348 cpl_image * off_dif = NULL;
3350 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3351 llx, lly, urx, ury, kappa, nclip,
3352 1e-5, &avg_off1, &std));
3353 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3354 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 1),
3355 llx, lly, urx, ury, kappa, nclip,
3356 1e-5, &avg_off2, &std));
3357 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, avg_off2));
3359 detmon_subtract_create_window(cpl_imagelist_get_const(offs, 0),
3360 cpl_imagelist_get_const(offs, 1),
3361 llx, lly, urx, ury);
3362 skip_if(off_dif == NULL);
3363 irplib_ksigma_clip(off_dif, 1, 1,
3364 cpl_image_get_size_x(off_dif),
3365 cpl_image_get_size_y(off_dif),
3367 1e-5, &avg_off_dif, &sig_off_dif);
3368 cpl_image_delete(off_dif);
3369 skip_if(cpl_table_set_double(gain_table,
"SIG_OFF_DIF",
3371 }
else if (pos > 0 && mode & IRPLIB_GAIN_COLLAPSE)
3374 avg_off1 = cpl_table_get_double(gain_table,
"MEAN_OFF1", 0, &status);
3375 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3376 avg_off2 = cpl_table_get_double(gain_table,
"MEAN_OFF2", 0, &status);
3377 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, avg_off2));
3378 sig_off_dif = cpl_table_get_double(gain_table,
"SIG_OFF_DIF",
3380 skip_if(cpl_table_set_double(gain_table,
"SIG_OFF_DIF",
3385 double avg_on_dif, sig_on_dif;
3386 irplib_ksigma_clip(on_dif, 1, 1,
3387 cpl_image_get_size_x(on_dif),
3388 cpl_image_get_size_y(on_dif), kappa,
3389 nclip, 1e-5, &avg_on_dif, &sig_on_dif);
3390 skip_if(cpl_table_set_double(gain_table,
"SIG_ON_DIF", pos, sig_on_dif));
3392 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE)
3394 double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
3398 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
3400 sigma = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
3404 gain = double_adu / (c_ndit * sigma);
3406 gain_corr = gain / (autocorr);
3408 skip_if(cpl_table_set_double(gain_table,
"GAIN", pos, gain));
3409 skip_if(cpl_table_set_double(gain_table,
"GAIN_CORR", pos, gain_corr));
3412 skip_if(cpl_table_set_double(gain_table,
"AUTOCORR", pos, autocorr));
3413 skip_if(cpl_table_set_double(gain_table,
"ADU", pos, double_adu / 2));
3416 skip_if(cpl_table_set_double(gain_table,
"Y_FIT",
3418 c_ndit* sig_on_dif * sig_on_dif));
3419 skip_if(cpl_table_set_double(gain_table,
"Y_FIT_CORR",
3421 c_ndit * sig_on_dif * sig_on_dif));
3422 skip_if(cpl_table_set_double(gain_table,
"X_FIT", pos, double_adu));
3423 skip_if(cpl_table_set_double(gain_table,
"X_FIT_CORR",
3424 pos, double_adu / autocorr));
3429 cpl_image_delete(on_dif);
3431 return cpl_error_get_code();
3444 detmon_bpixs(
const cpl_imagelist * coeffs,
3451 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
3458 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
3459 cpl_image_get_size_y(first));
3460 cpl_image *cur_image = NULL;
3461 cpl_image *bpm = NULL;
3464 size = cpl_imagelist_get_size(coeffs);
3467 bpm = cpl_image_new(cpl_image_get_size_x(first),
3468 cpl_image_get_size_y(first),
3473 for(i = 0; i < size; i++) {
3474 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
3476 stats = cpl_stats_new_from_image(cur_coeff,
3477 CPL_STATS_MEAN | CPL_STATS_STDEV);
3478 cur_mean = cpl_stats_get_mean(stats);
3479 cur_stdev = cpl_stats_get_stdev(stats);
3481 lo_cut = cur_mean - kappa * cur_stdev;
3482 hi_cut = cur_mean + kappa * cur_stdev;
3484 cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
3485 cpl_mask_not(cur_mask);
3488 cur_image = cpl_image_new_from_mask(cur_mask);
3490 cpl_image_power(cur_image, p);
3491 cpl_image_add(bpm, cur_image);
3492 cpl_image_delete(cur_image);
3495 cpl_mask_or(mask, cur_mask);
3497 cpl_mask_delete(cur_mask);
3498 cpl_stats_delete(stats);
3502 bpm = cpl_image_new_from_mask(mask);
3505 *nbpixs += cpl_mask_count(mask);
3507 cpl_mask_delete(mask);
3634 detmon_autocorr_factor(
const cpl_image * image,
3635 cpl_image ** autocorr_image,
int m,
int n)
3637 cpl_image * mycorr_image = NULL;
3638 double autocorr = 0;
3639 cpl_error_code err = CPL_ERROR_NONE;
3641 mycorr_image = detmon_image_correlate(image, image, m, n);
3642 err=cpl_error_get_code();
3643 if (err == CPL_ERROR_UNSUPPORTED_MODE)
3645 cpl_msg_warning(cpl_func,
"FFTW is not supported by CPL, autocorrelation "
3646 "would be computed using internal implementation");
3649 cpl_image_delete(mycorr_image);
3650 mycorr_image = detmon_autocorrelate(image, m, n);
3652 if(mycorr_image == NULL) {
3656 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
3658 autocorr = cpl_image_get_flux(mycorr_image);
3660 if (autocorr_image) *autocorr_image = mycorr_image;
3661 else cpl_image_delete(mycorr_image);
3666 static cpl_propertylist*
3667 detmon_lg_extract_qclist_4plane(cpl_propertylist* linc_qclist,
const int ip)
3670 cpl_propertylist* sub_set=NULL;
3673 sub_set=cpl_propertylist_new();
3674 qc_key=cpl_sprintf(
"QC LIN COEF%d",ip);
3675 cpl_propertylist_copy_property_regexp(sub_set,linc_qclist,qc_key,0);
3692 static cpl_error_code
3693 detmon_lg_extract_extention_header(cpl_frameset* frameset,
3694 cpl_propertylist* gaint_qclist,
3695 cpl_propertylist* lint_qclist,
3696 cpl_propertylist* linc_qclist,
3697 cpl_propertylist* bpm_qclist,
3701 cpl_propertylist * xplist = NULL;
3703 const char * filename =
3704 cpl_frame_get_filename(cpl_frameset_get_first(frameset));
3706 xplist = cpl_propertylist_load_regexp(filename, whichext,
3707 "ESO DET|EXTNAME", 0);
3708 if (detmon_lg_config.exts >= 0)
3711 cpl_property* propExtname = NULL;
3712 propExtname = cpl_propertylist_get_property(xplist,
"EXTNAME");
3714 if (NULL != propExtname)
3716 propExtname = cpl_property_duplicate(propExtname);
3718 cpl_propertylist_delete(xplist);
3720 if (NULL != propExtname)
3722 xplist = cpl_propertylist_new();
3723 cpl_propertylist_append_property(xplist, propExtname);
3724 cpl_property_delete(propExtname);
3729 cpl_propertylist_append(gaint_qclist, xplist);
3730 cpl_propertylist_append(lint_qclist, xplist);
3731 cpl_propertylist_append(linc_qclist, xplist);
3732 cpl_propertylist_append(bpm_qclist, xplist);
3733 cpl_propertylist_delete(xplist);
3736 return cpl_error_get_code();
3753 static cpl_error_code
3754 detmon_lg_save_table_with_pro_keys(cpl_table* table,
3756 cpl_propertylist* xheader,
3757 unsigned CPL_IO_MODE)
3760 cpl_propertylist* pro_keys=NULL;
3762 pro_keys=detmon_load_pro_keys(name_o);
3763 cpl_propertylist_append(xheader,pro_keys);
3765 if(CPL_IO_MODE==CPL_IO_DEFAULT) {
3766 cpl_propertylist * pri_head=cpl_propertylist_load(name_o,0);
3767 cpl_table_save(table, pri_head,xheader,name_o,
3769 cpl_propertylist_delete(pri_head);
3772 cpl_table_save(table,NULL,xheader,name_o,
3775 cpl_propertylist_delete(pro_keys);
3777 return cpl_error_get_code();
3789 static cpl_error_code
3790 detmon_lg_save_image_with_pro_keys(cpl_image* image,
3792 cpl_propertylist* xheader)
3795 cpl_propertylist* pro_keys=NULL;
3796 pro_keys=detmon_load_pro_keys(name_o);
3797 cpl_propertylist_append(xheader,pro_keys);
3799 cpl_image_save(image,name_o, CPL_BPP_IEEE_FLOAT,
3800 xheader,CPL_IO_EXTEND);
3801 cpl_propertylist_delete(pro_keys);
3804 return cpl_error_get_code();
3816 static cpl_error_code
3817 detmon_lg_save_imagelist_with_pro_keys(cpl_imagelist* imagelist,
3819 cpl_propertylist* xheader)
3822 cpl_propertylist* pro_keys=NULL;
3823 pro_keys=detmon_load_pro_keys(name_o);
3824 cpl_propertylist_append(xheader,pro_keys);
3826 cpl_imagelist_save(imagelist,name_o, CPL_BPP_IEEE_FLOAT,
3827 xheader,CPL_IO_EXTEND);
3829 cpl_propertylist_delete(pro_keys);
3832 return cpl_error_get_code();
3852 static cpl_error_code
3853 detmon_lg_save_plane(
const cpl_parameterlist * parlist,
3854 cpl_frameset* frameset,
3855 const cpl_frameset * usedframes,
3857 const char* recipe_name,
3858 cpl_propertylist* mypro_coeffscube,
3859 cpl_propertylist* linc_plane_qclist,
3860 const char* package,
3864 if(detmon_lg_config.exts == 0) {
3865 cpl_propertylist* plist=NULL;
3866 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3868 CPL_BPP_IEEE_FLOAT, recipe_name,
3869 mypro_coeffscube, NULL,
3871 plist=cpl_propertylist_load(NAME_O,0);
3872 cpl_image_save(plane,NAME_O, CPL_BPP_IEEE_FLOAT,
3873 plist,CPL_IO_DEFAULT);
3874 cpl_propertylist_delete(plist);
3876 }
else if(detmon_lg_config.exts > 0) {
3877 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3879 CPL_BPP_IEEE_FLOAT, recipe_name,
3880 mypro_coeffscube, NULL,
3883 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
3887 cpl_dfs_save_image(frameset, NULL, parlist,
3888 usedframes,NULL, NULL,
3889 CPL_BPP_IEEE_FLOAT, recipe_name,
3890 mypro_coeffscube, NULL,
3892 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
3895 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
3901 return cpl_error_get_code();
3924 static cpl_error_code
3925 detmon_lg_save_cube(
const cpl_parameterlist * parlist,
3926 cpl_frameset* frameset,
3927 const cpl_frameset * usedframes,
3929 const char* recipe_name,
3930 cpl_propertylist* mypro_coeffscube,
3931 cpl_propertylist* linc_qclist,
3932 const char* package,
3934 cpl_imagelist* coeffs)
3937 if(detmon_lg_config.exts == 0) {
3938 cpl_propertylist_append(mypro_coeffscube, linc_qclist);
3939 detmon_lg_dfs_save_imagelist
3940 (frameset, parlist, usedframes, coeffs,
3941 recipe_name, mypro_coeffscube, package,
3943 }
else if(detmon_lg_config.exts > 0) {
3944 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3946 CPL_BPP_IEEE_FLOAT, recipe_name,
3947 mypro_coeffscube, NULL,
3950 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
3954 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3956 CPL_BPP_IEEE_FLOAT, recipe_name,
3957 mypro_coeffscube, NULL,
3960 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
3962 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
3965 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
3967 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
3971 return cpl_error_get_code();
3975 detmon_lg_set_paf_name_and_header(cpl_frame* ref_frame,
3976 int flag_sets,
int which_set,
3978 const char* paf_suf,
3979 cpl_propertylist** plist)
3981 char * paf_name=NULL;
3983 if(detmon_lg_config.exts >= 0)
3985 *plist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
3986 detmon_lg_config.exts);
3990 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
3994 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
3995 detmon_lg_config.pafname, paf_suf,which_set);
4000 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4006 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4007 detmon_lg_config.pafname, paf_suf,whichext);
4011 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4012 detmon_lg_config.pafname,paf_suf,
4013 which_set, whichext);
4022 detmon_lg_set_paf_name_and_header_ext(cpl_frame* ref_frame,
4023 int flag_sets,
int which_set,
4025 const char* paf_suf,
4026 cpl_propertylist** plist)
4028 char* paf_name=NULL;
4030 if(detmon_lg_config.exts >= 0)
4032 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4033 detmon_lg_config.exts);
4037 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4040 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4041 detmon_lg_config.pafname, paf_suf,which_set);
4045 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4049 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4050 detmon_lg_config.pafname, paf_suf,whichext);
4053 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4054 detmon_lg_config.pafname,paf_suf,
4055 which_set, whichext);
4062 static cpl_error_code
4063 detmon_lg_save_paf_product(cpl_frame* ref_frame,
int flag_sets,
4064 int which_set,
int whichext,
4065 const char* pafregexp,
4066 const char* procatg,
4067 const char* pipeline_name,
4068 const char* recipe_name,
4069 const char* paf_suf,
4070 cpl_propertylist* qclist,
4075 char* paf_name=NULL;
4076 cpl_propertylist* plist=NULL;
4077 cpl_propertylist* paflist = NULL;
4078 cpl_propertylist* mainplist=NULL;
4080 mainplist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0);
4082 paf_name=detmon_lg_set_paf_name_and_header(ref_frame,flag_sets,
4086 paf_name=detmon_lg_set_paf_name_and_header_ext(ref_frame,flag_sets,
4092 paflist = cpl_propertylist_new();
4093 cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,procatg);
4096 cpl_propertylist_copy_property_regexp(paflist, plist,pafregexp, 0);
4097 cpl_propertylist_copy_property_regexp(paflist, mainplist,pafregexp, 0);
4098 cpl_propertylist_append(paflist,qclist);
4101 cpl_dfs_save_paf(pipeline_name, recipe_name,paflist,paf_name);
4104 cpl_propertylist_delete(mainplist);
4105 cpl_propertylist_delete(paflist);
4106 cpl_propertylist_delete(plist);
4109 return cpl_error_get_code();
4146 static cpl_error_code
4147 detmon_lg_save(
const cpl_parameterlist * parlist,
4148 cpl_frameset * frameset,
4149 const char *recipe_name,
4150 const char *pipeline_name,
4151 const char *pafregexp,
4152 const cpl_propertylist * pro_lintbl,
4153 const cpl_propertylist * pro_gaintbl,
4154 const cpl_propertylist * pro_coeffscube,
4155 const cpl_propertylist * pro_bpm,
4156 const cpl_propertylist * pro_corr,
4157 const cpl_propertylist * pro_diff,
4158 const char *package,
4159 cpl_imagelist * coeffs,
4160 cpl_table * gain_table,
4161 cpl_table * linear_table,
4163 cpl_imagelist * autocorr_images,
4164 cpl_imagelist * diff_flats,
4165 cpl_propertylist * gaint_qclist,
4166 cpl_propertylist * lint_qclist,
4167 cpl_propertylist * linc_qclist,
4168 cpl_propertylist * bpm_qclist,
4169 const int flag_sets,
4170 const int which_set,
4171 const cpl_frameset * usedframes,
4175 cpl_frame *ref_frame;
4176 cpl_propertylist *plist = NULL;
4177 cpl_propertylist *mainplist = NULL;
4183 cpl_propertylist * xplist = NULL;
4185 cpl_propertylist* linc_plane_qclist=NULL;
4186 cpl_image* plane=NULL;
4188 char* pcatg_plane=NULL;
4190 cpl_propertylist * mypro_lintbl =
4191 cpl_propertylist_duplicate(pro_lintbl);
4192 cpl_propertylist * mypro_gaintbl =
4193 cpl_propertylist_duplicate(pro_gaintbl);
4194 cpl_propertylist * mypro_coeffscube =
4195 cpl_propertylist_duplicate(pro_coeffscube);
4196 cpl_propertylist * mypro_bpm =
4197 cpl_propertylist_duplicate(pro_bpm);
4198 cpl_propertylist * mypro_corr =
4199 cpl_propertylist_duplicate(pro_corr);
4200 cpl_propertylist * mypro_diff =
4201 cpl_propertylist_duplicate(pro_diff);
4203 const char * procatg_lintbl =
4204 cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
4206 const char * procatg_gaintbl =
4207 cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
4209 const char * procatg_coeffscube =
4210 cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
4211 const char * procatg_bpm =
4212 cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
4216 detmon_lg_extract_extention_header(frameset,gaint_qclist,lint_qclist,
4217 linc_qclist,bpm_qclist,whichext);
4222 ref_frame = cpl_frameset_get_first(frameset);
4224 skip_if((mainplist =
4225 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4231 cpl_msg_info(cpl_func,
"Write the LINEARITY TABLE");
4234 NAME_O=cpl_sprintf(
"%s_linearity_table.fits", recipe_name);
4236 NAME_O=cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name,
4240 if (detmon_lg_config.exts >= 0) {
4242 cpl_propertylist_append(mypro_lintbl, lint_qclist);
4243 skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,
4244 linear_table,NULL, recipe_name,
4245 mypro_lintbl, NULL, package, NAME_O));
4247 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4248 lint_qclist,CPL_IO_DEFAULT);
4253 skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL,
4254 linear_table,lint_qclist, recipe_name,
4255 mypro_lintbl,NULL, package, NAME_O));
4256 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4257 lint_qclist,CPL_IO_DEFAULT);
4264 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4265 lint_qclist,CPL_IO_EXTEND);
4268 irplib_free(&NAME_O);
4272 cpl_msg_info(cpl_func,
"Write the GAIN TABLE");
4275 NAME_O=cpl_sprintf(
"%s_gain_table.fits", recipe_name);
4277 NAME_O=cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name,
4281 if (detmon_lg_config.exts >= 0)
4285 cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
4286 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
4287 gain_table,NULL, recipe_name, mypro_gaintbl,
4288 NULL, package, NAME_O));
4289 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4290 gaint_qclist,CPL_IO_DEFAULT);
4298 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
4299 gaint_qclist, recipe_name, mypro_gaintbl,
4300 NULL, package, NAME_O));
4301 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4302 gaint_qclist,CPL_IO_DEFAULT);
4308 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4309 gaint_qclist,CPL_IO_EXTEND);
4313 if(detmon_lg_config.pix2pix)
4319 cpl_msg_info(cpl_func,
"Write the COEFFS FITS");
4320 irplib_free(&NAME_O);
4323 PREF_O=cpl_sprintf(
"%s_coeffs_cube", recipe_name);
4326 PREF_O=cpl_sprintf(
"%s_coeffs_cube_set%02d",
4327 recipe_name, which_set);
4329 if (detmon_lg_config.split_coeffs == 0) {
4330 NAME_O=cpl_sprintf(
"%s.fits", PREF_O);
4335 if(detmon_lg_config.split_coeffs != 0){
4338 nb_images = cpl_imagelist_get_size(coeffs);
4339 for(ip=0;ip<nb_images;ip++) {
4340 NAME_O=cpl_sprintf(
"%s_P%d.fits", PREF_O,ip);
4341 pcatg_plane=cpl_sprintf(
"COEFFS_CUBE_P%d",ip);
4342 cpl_propertylist_delete(mypro_coeffscube);
4343 mypro_coeffscube=cpl_propertylist_duplicate(pro_coeffscube);
4344 cpl_propertylist_set_string(mypro_coeffscube,CPL_DFS_PRO_CATG,
4346 linc_plane_qclist=detmon_lg_extract_qclist_4plane(linc_qclist,ip);
4347 cpl_propertylist_append(mypro_coeffscube, linc_plane_qclist);
4348 plane=cpl_imagelist_get(coeffs,ip);
4349 detmon_lg_save_plane(parlist,frameset,usedframes,whichext,
4350 recipe_name,mypro_coeffscube,
4351 linc_plane_qclist,package,NAME_O,plane);
4353 if(NULL!=linc_plane_qclist) {
4354 cpl_propertylist_delete(linc_plane_qclist);
4356 irplib_free(&NAME_O);
4361 detmon_lg_save_cube(parlist,frameset,usedframes,whichext,
4362 recipe_name,mypro_coeffscube,
4363 linc_qclist,package,NAME_O,coeffs);
4369 cpl_msg_info(cpl_func,
"Write the BAD PIXEL MAP");
4370 irplib_free(&NAME_O);
4374 NAME_O=cpl_sprintf(
"%s_bpm.fits", recipe_name);
4377 NAME_O=cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, which_set);
4382 if(detmon_lg_config.exts == 0) {
4383 cpl_propertylist_append(mypro_bpm, bpm_qclist);
4384 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
4385 CPL_BPP_IEEE_FLOAT, recipe_name,
4386 mypro_bpm, NULL, package,
4389 else if(detmon_lg_config.exts > 0)
4391 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4392 CPL_BPP_IEEE_FLOAT, recipe_name,
4393 mypro_bpm, NULL, package,
4395 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4401 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4402 CPL_BPP_IEEE_FLOAT, recipe_name,
4403 mypro_bpm, NULL, package,
4405 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4408 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4413 if(detmon_lg_config.intermediate)
4418 cpl_msg_info(cpl_func,
"Write the AUTOCORRS FITS");
4419 nb_images = cpl_imagelist_get_size(autocorr_images);
4420 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
4421 for(i = 0; i < nb_images; i++)
4423 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_corr);
4425 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4427 if(i < cpl_table_get_nrow(linear_table))
4429 ddit = cpl_table_get_double(linear_table,
4430 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4432 cpl_array_delete(pnames);
4435 irplib_free(&NAME_O);
4438 NAME_O=cpl_sprintf(
"%s_autocorr_%d.fits", recipe_name, i);
4439 assert(NAME_O != NULL);
4442 NAME_O=cpl_sprintf(
"%s_autocorr_%02d_set%02d.fits",
4443 recipe_name, i, which_set);
4444 assert(NAME_O != NULL);
4447 if(detmon_lg_config.exts > 0)
4449 cpl_propertylist* pextlist = cpl_propertylist_new();
4450 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4451 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4452 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4453 recipe_name, pplist, NULL,
4456 detmon_lg_save_image_with_pro_keys(
4457 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4459 cpl_propertylist_delete(pextlist);
4461 if(detmon_lg_config.exts == 0)
4463 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4464 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
4465 cpl_imagelist_get(autocorr_images, i),
4467 recipe_name, pplist, NULL, package,
4473 cpl_propertylist* pextlist = cpl_propertylist_new();
4474 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4477 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4478 usedframes, NULL,NULL,
4479 CPL_BPP_IEEE_FLOAT, recipe_name,
4483 detmon_lg_save_image_with_pro_keys(
4484 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4489 detmon_lg_save_image_with_pro_keys(
4490 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4492 cpl_propertylist_delete(pextlist);
4494 cpl_propertylist_delete (pplist);
4496 irplib_free(&NAME_O);
4505 cpl_msg_info(cpl_func,
"Write the DIFFS FITS");
4507 for(i = 0; i < nb_images; i++)
4509 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_diff);
4511 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4513 if(i < cpl_table_get_nrow(linear_table))
4515 ddit = cpl_table_get_double(linear_table,
4516 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4518 cpl_array_delete(pnames);
4523 NAME_O=cpl_sprintf(
"%s_diff_flat_%d.fits", recipe_name, i);
4526 NAME_O=cpl_sprintf(
"%s_diff_flat_%d_set%02d.fits",
4527 recipe_name, i, which_set);
4530 if(detmon_lg_config.exts > 0)
4532 cpl_propertylist* pextlist = cpl_propertylist_new();
4533 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4534 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT", ddit);
4535 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4536 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4538 mypro_diff, NULL,package, NAME_O));
4540 detmon_lg_save_image_with_pro_keys(
4541 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4543 cpl_propertylist_delete(pextlist);
4545 else if(detmon_lg_config.exts == 0)
4547 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4549 (frameset, NULL, parlist, usedframes, NULL,
4550 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
4551 recipe_name, pplist, NULL, package,
4556 cpl_propertylist* pextlist = cpl_propertylist_new();
4557 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4560 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT",ddit);
4562 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4563 usedframes, NULL,NULL,
4564 CPL_BPP_IEEE_FLOAT, recipe_name,
4565 mypro_diff, NULL,package, NAME_O));
4567 detmon_lg_save_image_with_pro_keys(
4568 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4573 detmon_lg_save_image_with_pro_keys(
4574 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4577 cpl_propertylist_delete(pextlist);
4579 cpl_propertylist_delete(pplist);
4580 irplib_free(&NAME_O);
4588 cpl_msg_info(cpl_func,
"Write the PAF file(s)");
4590 if(detmon_lg_config.pafgen) {
4592 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4593 pafregexp,procatg_gaintbl,
4594 pipeline_name,recipe_name,
4595 "qc01",gaint_qclist,0);
4597 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4598 pafregexp,procatg_lintbl,
4599 pipeline_name,recipe_name,
4600 "qc02",lint_qclist,0);
4602 if(detmon_lg_config.pix2pix)
4605 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4608 pipeline_name,recipe_name,
4609 "qc03",linc_qclist,1);
4611 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4612 whichext,pafregexp,procatg_bpm,
4613 pipeline_name,recipe_name,
4614 "qc04",bpm_qclist,1);
4619 cpl_msg_info(cpl_func,
"exit");
4621 cpl_propertylist_delete(xplist);
4623 cpl_propertylist_delete(plist);
4627 irplib_free(&NAME_O);
4629 cpl_free(pcatg_plane);
4630 cpl_propertylist_delete(mainplist);
4631 cpl_propertylist_delete(mypro_lintbl);
4632 cpl_propertylist_delete(mypro_gaintbl);
4633 cpl_propertylist_delete(mypro_coeffscube);
4634 cpl_propertylist_delete(mypro_bpm);
4635 cpl_propertylist_delete(mypro_corr);
4636 cpl_propertylist_delete(mypro_diff);
4638 return cpl_error_get_code();
4651 static cpl_error_code
4652 detmon_opt_contamination(
const cpl_imagelist * ons,
4653 const cpl_imagelist * offs,
4655 cpl_propertylist * qclist)
4663 struct rect rects[5] = {
4664 (
struct rect){ detmon_lg_config.llx1,
4665 detmon_lg_config.lly1,
4666 detmon_lg_config.urx1,
4667 detmon_lg_config.ury1},
4668 (
struct rect){ detmon_lg_config.llx2,
4669 detmon_lg_config.lly2,
4670 detmon_lg_config.urx2,
4671 detmon_lg_config.ury2},
4672 (
struct rect){ detmon_lg_config.llx3,
4673 detmon_lg_config.lly3,
4674 detmon_lg_config.urx3,
4675 detmon_lg_config.ury3},
4676 (
struct rect){ detmon_lg_config.llx4,
4677 detmon_lg_config.lly4,
4678 detmon_lg_config.urx4,
4679 detmon_lg_config.ury4},
4680 (
struct rect){ detmon_lg_config.llx5,
4681 detmon_lg_config.lly5,
4682 detmon_lg_config.urx5,
4683 detmon_lg_config.ury5},
4686 for (
size_t i = 0; i < 5; i++) {
4687 cpl_image * dif_avg;
4688 const cpl_image * off2;
4691 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
4692 off2 = cpl_imagelist_get_const(offs, 0);
4694 off2 = cpl_imagelist_get_const(offs, 1);
4696 dif_avg = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
4697 cpl_imagelist_get_const(offs, 0),
4698 cpl_imagelist_get_const(ons, 1),
4705 median = cpl_image_get_median(dif_avg);
4706 cpl_image_delete(dif_avg);
4709 sprintf(kname,
"%s%d", DETMON_QC_CONTAM, i + 1);
4711 if(cpl_propertylist_has(qclist,kname)){
4712 skip_if(cpl_propertylist_update_double(qclist,kname,median));
4714 skip_if(cpl_propertylist_append_double(qclist,kname,median));
4715 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
4721 return cpl_error_get_code();
4780 detmon_lg_dfs_set_groups(cpl_frameset *
set,
4781 const char *tag_on,
const char *tag_off)
4783 cpl_frame *cur_frame;
4793 nframes = cpl_frameset_get_size(
set);
4796 for(i = 0; i < nframes; i++) {
4797 cur_frame = cpl_frameset_get_position(
set, i);
4798 tag = cpl_frame_get_tag(cur_frame);
4801 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
4802 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
4822 static cpl_error_code
4823 detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist ** coeffs_ptr,
4824 cpl_image **bpms_ptr)
4826 cpl_image* dummy_bpm=NULL;
4827 cpl_image * dummy_coeff=NULL;
4828 cpl_imagelist * dummy_coeffs=NULL;
4840 dummy_bpm = cpl_image_new(detmon_lg_config.nx,
4841 detmon_lg_config.ny,
4843 dummy_coeffs = cpl_imagelist_new();
4845 db_p = cpl_image_get_data_int(dummy_bpm);
4846 rb_p = cpl_image_get_data_int(*bpms_ptr);;
4847 dcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
4848 rcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
4849 dlength = detmon_lg_config.nx;
4850 rlength = detmon_lg_config.urx - detmon_lg_config.llx + 1;
4851 for (i = 0; i <= detmon_lg_config.order; i++)
4853 dummy_coeff = cpl_image_new(detmon_lg_config.nx,
4854 detmon_lg_config.ny,
4857 cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
4858 dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
4859 rcs_p[i] = cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
4862 for (i = detmon_lg_config.lly - 1; i < detmon_lg_config.ury; i++)
4864 for (j = detmon_lg_config.llx - 1; j < detmon_lg_config.urx; j++)
4866 shift_idx=(i - detmon_lg_config.lly + 1) * rlength +
4867 j - detmon_lg_config.llx + 1;
4868 *(db_p + i * dlength + j) = *(rb_p + shift_idx);
4869 for (k = 0; k <= detmon_lg_config.order; k++)
4871 *(dcs_p[k] + i * dlength + j) =
4872 *(rcs_p[k] + (i - detmon_lg_config.lly + 1) * rlength +
4873 j - detmon_lg_config.llx + 1);
4877 cpl_imagelist_delete(*coeffs_ptr);
4878 cpl_image_delete(*bpms_ptr);
4879 *coeffs_ptr = dummy_coeffs;
4880 *bpms_ptr = dummy_bpm;
4884 return cpl_error_get_code();
4937 static cpl_error_code
4938 detmon_lg_reduce_all(
const cpl_table * linear_table,
4939 cpl_propertylist * gaint_qclist,
4940 cpl_propertylist * lint_qclist,
4941 cpl_propertylist * linc_qclist,
4942 cpl_propertylist * bpm_qclist,
4943 cpl_imagelist ** coeffs_ptr,
4944 cpl_image ** bpms_ptr,
4945 const cpl_imagelist * linearity_inputs,
4946 const cpl_table * gain_table,
4947 int which_ext, cpl_boolean opt_nir)
4951 const int nsets = cpl_table_get_nrow(linear_table);
4953 cpl_polynomial *poly_linfit = NULL;
4954 cpl_image *fiterror = NULL;
4955 char * name_o1 = NULL;
4956 char * name_o2 = NULL;
4957 double * pcoeffs = NULL;
4958 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
4961 cpl_vector *x =NULL;
4962 const cpl_vector *y =NULL;
4965 const cpl_image * first = NULL;
4973 cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
4974 cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
4975 cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
4976 cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
4978 pcoeffs = cpl_malloc(
sizeof(
double)*(detmon_lg_config.order + 1));
4980 skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
4981 detmon_lg_config.method));
4982 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
4983 DETMON_QC_METHOD_C));
4986 if (!strcmp(detmon_lg_config.method,
"PTC")) {
4988 if (detmon_lg_config.exts >= 0) {
4989 cpl_msg_info(cpl_func,
4990 "Polynomial fitting for the GAIN (constant term method)");
4992 cpl_msg_info(cpl_func,
4993 "Polynomial fitting for the GAIN (constant term method)"
4994 " for extension nb %d", which_ext);
4996 skip_if(detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, nsets));
4998 skip_if(detmon_lg_qc_med(gain_table, gaint_qclist, nsets));
5003 if(detmon_lg_config.lamp_ok) {
5004 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
5005 detmon_lg_config.cr));
5006 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
5007 DETMON_QC_LAMP_FLUX_C));
5011 if(detmon_lg_config.autocorr == TRUE) {
5012 autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
5013 skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
5015 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
5016 DETMON_QC_AUTOCORR_C));
5018 if (detmon_lg_config.exts >= 0) {
5019 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix");
5021 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix"
5022 " for extension nb %d", which_ext);
5025 if(!detmon_lg_config.pix2pix) {
5028 y = cpl_vector_wrap(nsets,
5029 (
double *)cpl_table_get_data_double_const(linear_table,
5032 if (opt_nir == NIR) {
5033 x = cpl_vector_wrap(nsets,
5034 (
double *)cpl_table_get_data_double_const(linear_table,
5037 x = cpl_vector_wrap(nsets,
5038 (
double *)cpl_table_get_data_double_const(linear_table,
5042 if(x == NULL || y == NULL) {
5043 cpl_vector_unwrap((cpl_vector *)x);
5044 cpl_vector_unwrap((cpl_vector *)y);
5054 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
5055 poly_linfit = irplib_polynomial_fit_1d_create(x, y,
5056 detmon_lg_config.order,
5059 if(detmon_lg_config.order == cpl_vector_get_size(x) - 1) {
5060 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5064 if(poly_linfit == NULL) {
5065 cpl_vector_unwrap((cpl_vector *)x);
5066 cpl_vector_unwrap((cpl_vector *)y);
5072 min_val=cpl_vector_get_min(y);
5073 max_val=cpl_vector_get_max(y);
5075 cpl_vector_unwrap((cpl_vector *)x);
5076 cpl_vector_unwrap((cpl_vector *)y);
5078 for(deg = 0; deg <= detmon_lg_config.order; deg++) {
5079 const double coeff =
5080 cpl_polynomial_get_coeff(poly_linfit, °);
5082 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
5083 assert(name_o != NULL);
5084 skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
5085 skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
5086 DETMON_QC_LIN_COEF_C));
5089 pcoeffs[deg] = coeff;
5091 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
5092 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
5093 DETMON_QC_ERRFIT_MSE_C));
5098 y = cpl_vector_wrap(nsets,
5099 (
double *)cpl_table_get_data_double_const(linear_table,
5104 x = cpl_vector_wrap(nsets,
5105 (
double *)cpl_table_get_data_double_const(linear_table,
5108 x = cpl_vector_wrap(nsets,
5109 (
double *)cpl_table_get_data_double_const(linear_table,
5114 first = cpl_imagelist_get_const(linearity_inputs, 0);
5115 sizex = cpl_image_get_size_x(first);
5116 sizey = cpl_image_get_size_y(first);
5117 vsize = cpl_vector_get_size(x);
5118 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
5120 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,
5121 detmon_lg_config.order, FALSE,
5122 CPL_TYPE_FLOAT, fiterror);
5123 min_val=cpl_vector_get_min(y);
5124 max_val=cpl_vector_get_max(y);
5125 cpl_vector_unwrap((cpl_vector*)x);
5126 cpl_vector_unwrap((cpl_vector*)y);
5128 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
5129 "Failed polynomial fit");
5132 for(deg = 0; deg <= detmon_lg_config.order; deg++)
5134 cpl_image *image = cpl_imagelist_get(*coeffs_ptr, deg);
5135 const double coeff = cpl_image_get_median(image);
5136 pcoeffs[deg] = coeff;
5137 name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", (
int)deg);
5138 name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", (
int)deg);
5139 assert(name_o1 != NULL);
5140 assert(name_o2 != NULL);
5141 skip_if(cpl_propertylist_append_double(linc_qclist, name_o1, coeff));
5142 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o1,
5143 DETMON_QC_LIN_COEF_C));
5146 skip_if(cpl_propertylist_append_double(linc_qclist, name_o2,
5147 cpl_image_get_stdev(image)));
5148 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o2,
5149 DETMON_QC_LIN_COEF_ERR_C));
5155 if(detmon_lg_config.order == vsize - 1)
5157 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5158 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5160 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5161 DETMON_QC_ERRFIT_C));
5164 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5165 cpl_image_get_median(fiterror)));
5166 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5167 DETMON_QC_ERRFIT_C));
5171 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
5173 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
5174 DETMON_QC_COUNTS_MIN_C));
5175 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
5177 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
5178 DETMON_QC_COUNTS_MAX_C));
5179 skip_if(detmon_lg_lineff(pcoeffs,lint_qclist,detmon_lg_config.ref_level,
5180 detmon_lg_config.order));
5182 if (detmon_lg_config.exts >= 0)
5184 cpl_msg_info(cpl_func,
"Bad pixel detection");
5187 cpl_msg_info(cpl_func,
"Bad pixel detection"
5188 " for extension nb %d", which_ext);
5190 if(detmon_lg_config.pix2pix)
5193 *bpms_ptr = detmon_bpixs(*coeffs_ptr, detmon_lg_config.bpmbin,
5194 detmon_lg_config.kappa, &nbpixs);
5204 skip_if(*bpms_ptr == NULL);
5209 skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
5210 skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
5211 DETMON_QC_NUM_BPM_C));
5212 if(detmon_lg_config.lamp_stability != 0.0)
5214 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
5215 detmon_lg_config.lamp_stability));
5216 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
5217 DETMON_QC_LAMP_STAB_C));
5220 if (!detmon_lg_config.wholechip && detmon_lg_config.pix2pix)
5222 detmon_lg_fits_coeffs_and_bpm2chip(coeffs_ptr,bpms_ptr);
5229 cpl_image_delete(fiterror);
5230 cpl_polynomial_delete(poly_linfit);
5234 return cpl_error_get_code();
5246 static cpl_error_code
5247 detmon_lg_lineff(
double * pcoeffs,
5248 cpl_propertylist * qclist,
5254 double residual, slope;
5257 cpl_polynomial * poly = cpl_polynomial_new(1);
5271 pcoeffs[0] -= ref_level;
5273 for (i = 2; i <= order; i++)
5276 for(j = 0; j < i; j++)
5278 pcoeffs[i] /= pcoeffs[1];
5284 for (deg = 0; deg <= order; deg++) {
5286 skip_if(cpl_polynomial_set_coeff(poly, °, pcoeffs[deg]));
5295 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
5297 if (slope <= 0.0 && residual >= 0.0) {
5298 cpl_msg_warning(cpl_func,
"Reference level (--ref_level) outside"
5299 " linearity range of the detector. Cannot compute"
5300 " linearity efficiency (QC.LINEFF).");
5305 cpl_error_code err = cpl_polynomial_solve_1d(poly, 0.0, &root, 1);
5310 if (err == CPL_ERROR_NONE)
5313 lineff = (root - ref_level) / ref_level;
5318 cpl_msg_warning(cpl_func,
5319 "Cannot compute linearity efficiency (QC.LINEFF)"
5320 "for the current combination "
5321 " of (--ref-level equal %d) and (--order equal %d) parameters. Try "
5322 "to decrease (--ref-level) value.", ref_level, order);
5325 cpl_msg_warning(cpl_func,
"DETMON_QC_LIN_EFF=%f",lineff );
5326 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
5328 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
5329 DETMON_QC_LIN_EFF_C));
5331 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
5333 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
5334 DETMON_QC_LIN_EFF_FLUX_C));
5338 cpl_polynomial_delete(poly);
5340 return cpl_error_get_code();
5351 static cpl_error_code
5352 detmon_lg_qc_ptc(
const cpl_table * gain_table,
5353 cpl_propertylist * qclist,
unsigned mode,
int rows_in_gain)
5356 cpl_polynomial *poly_fit = NULL;
5357 cpl_polynomial *poly_fit2 = NULL;
5359 const int nsets = rows_in_gain;
5361 cpl_vector *x = NULL;
5362 cpl_vector *y = NULL;
5364 cpl_errorstate prestate;
5366 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
5367 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
5369 x = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5371 y = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5373 skip_if(x == NULL || y == NULL);
5374 if (0 == detmon_lg_check_before_gain(x, y))
5378 cpl_vector_unwrap(x);
5382 cpl_vector_unwrap(y);
5384 return CPL_ERROR_NONE;
5387 poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
5388 skip_if(poly_fit == NULL);
5392 prestate = cpl_errorstate_get();
5393 coef = cpl_polynomial_get_coeff(poly_fit, &i);
5394 skip_if (!cpl_errorstate_is_equal(prestate) || coef==0);
5395 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
5396 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5397 DETMON_QC_CONAD_C));
5400 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
5402 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
5418 if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
5419 const cpl_vector *x2 =
5420 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT_CORR"));
5421 const cpl_vector *y2 =
5422 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5424 if(x2 == NULL || y2 == NULL) {
5425 cpl_vector_unwrap((cpl_vector *)x2);
5426 cpl_vector_unwrap((cpl_vector *)y2);
5437 poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
5438 if(poly_fit2 == NULL) {
5439 cpl_vector_unwrap((cpl_vector *)x2);
5440 cpl_vector_unwrap((cpl_vector *)y2);
5442 cpl_msg_error(cpl_func,
"Error during polynomial fit, err[%s]", cpl_error_get_where());
5446 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5447 cpl_vector_unwrap((cpl_vector *)x2);
5448 cpl_vector_unwrap((cpl_vector *)y2);
5449 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5452 prestate = cpl_errorstate_get();
5453 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
5454 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5455 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
5457 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
5459 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
5460 DETMON_QC_CONAD_CORR_C));
5462 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
5464 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
5465 DETMON_QC_GAIN_CORR_C));
5471 cpl_vector_unwrap(x);
5472 cpl_vector_unwrap(y);
5473 cpl_polynomial_delete(poly_fit);
5474 cpl_polynomial_delete(poly_fit2);
5476 return cpl_error_get_code();
5485 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y)
5487 const double TOLERANCE = 1e-37;
5488 double xmin = cpl_vector_get_min(x);
5489 double xmax = cpl_vector_get_max(x);
5490 double ymin = cpl_vector_get_min(y);
5491 double ymax = cpl_vector_get_max(y);
5492 double ystdev = cpl_vector_get_stdev(y);
5493 double xstdev = cpl_vector_get_stdev(x);
5495 if (fabs(xmax-xmin) < TOLERANCE &&
5496 fabs(ymax - ymin) < TOLERANCE &&
5497 xstdev < TOLERANCE &&
5500 cpl_msg_warning(cpl_func,
"An empty frame has been detected, linearity, coeffs, gain, FPN values will not be computed.");
5515 static cpl_error_code
5516 detmon_lg_qc_med(
const cpl_table * gain_table,
5517 cpl_propertylist * qclist,
int rows_in_gain)
5521 cpl_vector *x = NULL;
5522 cpl_vector *y = NULL;
5523 int check_result = 0;
5525 if (rows_in_gain) {};
5527 x = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5528 y = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5529 check_result = detmon_lg_check_before_gain(x, y);
5532 cpl_vector_unwrap(x);
5536 cpl_vector_unwrap(y);
5538 if (0 == check_result)
5540 return CPL_ERROR_NONE;
5543 gain=cpl_table_get_column_median(gain_table,
"GAIN");
5545 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
5547 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
5550 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
5551 cpl_table_get_column_stdev
5552 (gain_table,
"GAIN")));
5553 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
5554 DETMON_QC_GAIN_MSE_C));
5556 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
5557 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5558 DETMON_QC_CONAD_C));
5561 gain=cpl_table_get_column_median(gain_table,
"GAIN_CORR");
5563 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
5565 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
5566 DETMON_QC_GAIN_CORR_C));
5569 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
5570 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
5571 DETMON_QC_CONAD_CORR_C));
5576 return cpl_error_get_code();
5590 static cpl_error_code
5591 detmon_lg_rescale(cpl_imagelist * to_rescale)
5594 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 0),
5595 detmon_lg_config.llx,
5596 detmon_lg_config.lly,
5597 detmon_lg_config.urx,
5598 detmon_lg_config.ury);
5600 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 1),
5601 detmon_lg_config.llx,
5602 detmon_lg_config.lly,
5603 detmon_lg_config.urx,
5604 detmon_lg_config.ury);
5608 if(fabs(med1 / med2 - 1) > 0.001) {
5610 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
5613 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
5619 return cpl_error_get_code();
5622 static cpl_error_code
5623 detmon_pair_extract_next(
const cpl_frameset *
set,
5627 cpl_frameset ** pair,
5631 double dit_next = -100;
5632 cpl_size* selection;
5633 int nsets_extracted = 0;
5634 cpl_ensure_code(
set != NULL, CPL_ERROR_NULL_INPUT);
5635 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
5636 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
5637 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
5639 nsets_extracted = cpl_frameset_get_size(
set);
5640 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
5641 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
5644 dit = dit_array[*next_element ];
5646 if (*next_element < nsets_extracted - 1)
5648 dit_next = dit_array[*next_element + 1 ];
5652 selection[iindex[*next_element] ] = 1;
5653 if (fabs(dit - dit_next) < tolerance)
5656 selection[iindex[*next_element + 1] ] = 1;
5661 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);
5665 cpl_frameset_delete(*pair);
5666 *pair = cpl_frameset_extract(
set, selection, 1);
5669 cpl_free(selection);
5670 return cpl_error_get_code();
5673 static cpl_error_code
5674 detmon_single_extract_next(
const cpl_frameset *
set,
5678 cpl_frameset ** pair)
5680 cpl_size* selection;
5681 int nsets_extracted = 0;
5682 cpl_ensure_code(
set != NULL, CPL_ERROR_NULL_INPUT);
5683 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
5684 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
5685 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
5687 nsets_extracted = cpl_frameset_get_size(
set);
5688 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
5689 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
5692 selection[iindex[*next_element] ] = 1;
5695 cpl_frameset_delete(*pair);
5696 *pair = cpl_frameset_extract(
set, selection, 1);
5698 cpl_free(selection);
5699 return cpl_error_get_code();
5795 detmon_gain(
const cpl_imagelist * imlist_on,
5796 const cpl_imagelist * imlist_off,
5797 const cpl_vector * exptimes,
5798 const cpl_vector * ndit,
5808 cpl_propertylist * qclist,
5810 cpl_imagelist ** diff_imlist,
5811 cpl_imagelist ** autocorr_imlist)
5813 cpl_table * gain_table = NULL;
5814 cpl_imagelist * difflist = NULL;
5815 cpl_imagelist * autocorrlist = NULL;
5816 cpl_imagelist * c_onlist = NULL;
5817 cpl_imagelist * c_offlist = NULL;
5818 cpl_vector * diffdits = NULL;
5819 cpl_vector * diffndits = NULL;
5820 int rows_in_gain = 0;
5821 int ndiffdits, ndits;
5823 cpl_boolean opt_nir = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
5824 const char * method = mode & IRPLIB_GAIN_PTC ?
"PTC" :
"MED";
5826 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
5827 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
5828 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
5829 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
5832 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
5833 skip_if(detmon_gain_table_create(gain_table, opt_nir));
5837 skip_if(detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,
5839 ndiffdits = cpl_vector_get_size(diffdits);
5841 ndits = cpl_vector_get_size(exptimes);
5844 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
5845 difflist = cpl_imagelist_new();
5846 autocorrlist = cpl_imagelist_new();
5849 if (mode & IRPLIB_GAIN_COLLAPSE) {
5850 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
5851 c_offlist = cpl_imagelist_duplicate(imlist_off);
5852 skip_if(detmon_lg_rescale(c_offlist));
5854 c_offlist = (cpl_imagelist *) imlist_off;
5859 for (i = 0; i < ndiffdits; i++) {
5866 c_dit=cpl_vector_get(diffdits, i);
5869 c_ndit=(int)cpl_vector_get(diffndits, i);
5872 c_onlist = cpl_imagelist_new();
5875 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5876 c_offlist = cpl_imagelist_new();
5881 for(j = 0; j < ndits; j++) {
5882 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
5892 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
5893 const cpl_image * im =
5894 cpl_imagelist_get_const(imlist_on, j);
5895 im_on = cpl_image_duplicate(im);
5897 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
5899 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
5906 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5908 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
5909 const cpl_image * im =
5910 cpl_imagelist_get_const(imlist_off, j);
5911 im_off = cpl_image_duplicate(im);
5914 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
5916 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
5923 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
5924 skip_if (c_nons != c_noffs);
5927 skip_if (c_nons == 0 || c_nons % 2 != 0);
5930 if(mode & IRPLIB_GAIN_WITH_RESCALE) {
5931 skip_if(detmon_lg_rescale(c_onlist));
5932 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
5933 skip_if(detmon_lg_rescale(c_offlist));
5939 int rows_affected = 1;
5940 skip_if(detmon_gain_table_fill_row(gain_table,
5944 c_offlist, kappa, nclip,
5946 xshift, yshift,1E10, i,
5947 mode, &rows_affected));
5952 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
5953 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
5954 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
5955 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5956 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
5957 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
5960 cpl_imagelist_unset(c_onlist, 0);
5962 cpl_imagelist_unset(c_onlist, 0);
5964 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5965 cpl_imagelist_unset(c_offlist, 0);
5967 cpl_imagelist_unset(c_offlist, 0);
5975 cpl_imagelist_delete(c_onlist);
5976 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5977 cpl_imagelist_delete(c_offlist);
5981 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
5982 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
5983 DETMON_QC_METHOD_C));
5986 if (mode & IRPLIB_GAIN_PTC) {
5987 skip_if(detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
5989 skip_if(detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
5992 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
5993 double autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
5994 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
5996 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
5997 DETMON_QC_AUTOCORR_C));
6000 if (diff_imlist != NULL) *diff_imlist = difflist;
6001 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
6005 cpl_vector_delete(diffdits);
6006 cpl_vector_delete(diffndits);
6011 static cpl_error_code
6012 detmon_gain_table_create(cpl_table * gain_table,
6013 const cpl_boolean opt_nir)
6015 if (opt_nir == NIR) {
6016 skip_if(cpl_table_new_column(gain_table,
"DIT", CPL_TYPE_DOUBLE));
6017 skip_if(cpl_table_new_column(gain_table,
"NDIT", CPL_TYPE_INT));
6019 skip_if(cpl_table_new_column(gain_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6021 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON1", CPL_TYPE_DOUBLE));
6022 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON2", CPL_TYPE_DOUBLE));
6023 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF1", CPL_TYPE_DOUBLE));
6024 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF2", CPL_TYPE_DOUBLE));
6025 skip_if(cpl_table_new_column(gain_table,
"SIG_ON_DIF", CPL_TYPE_DOUBLE));
6026 skip_if(cpl_table_new_column(gain_table,
"SIG_OFF_DIF", CPL_TYPE_DOUBLE));
6027 skip_if(cpl_table_new_column(gain_table,
"GAIN", CPL_TYPE_DOUBLE));
6028 skip_if(cpl_table_new_column(gain_table,
"AUTOCORR", CPL_TYPE_DOUBLE));
6029 skip_if(cpl_table_new_column(gain_table,
"GAIN_CORR", CPL_TYPE_DOUBLE));
6030 skip_if(cpl_table_new_column(gain_table,
"ADU", CPL_TYPE_DOUBLE));
6031 skip_if(cpl_table_new_column(gain_table,
"X_FIT", CPL_TYPE_DOUBLE));
6032 skip_if(cpl_table_new_column(gain_table,
"X_FIT_CORR", CPL_TYPE_DOUBLE));
6033 skip_if(cpl_table_new_column(gain_table,
"Y_FIT", CPL_TYPE_DOUBLE));
6034 skip_if(cpl_table_new_column(gain_table,
"Y_FIT_CORR", CPL_TYPE_DOUBLE));
6035 skip_if(cpl_table_new_column(gain_table,
"FLAG", CPL_TYPE_INT));
6039 return cpl_error_get_code();
6042 static cpl_error_code
6043 detmon_lin_table_create(cpl_table * lin_table,
6044 const cpl_boolean opt_nir)
6046 if (opt_nir == NIR) {
6047 skip_if(cpl_table_new_column(lin_table,
"DIT", CPL_TYPE_DOUBLE));
6049 skip_if(cpl_table_new_column(lin_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6051 skip_if(cpl_table_new_column(lin_table,
"MED", CPL_TYPE_DOUBLE));
6052 skip_if(cpl_table_new_column(lin_table,
"MEAN", CPL_TYPE_DOUBLE));
6053 skip_if(cpl_table_new_column(lin_table,
"MED_DIT", CPL_TYPE_DOUBLE));
6054 skip_if(cpl_table_new_column(lin_table,
"MEAN_DIT", CPL_TYPE_DOUBLE));
6055 skip_if(cpl_table_new_column(lin_table,
"ADL", CPL_TYPE_DOUBLE));
6058 return cpl_error_get_code();
6062 detmon_lg_find_dits(
const cpl_vector * exptimes,
6065 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6071 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
6075 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
6077 for (j = 0; j < ndits; j++) {
6078 if (fabs(cpl_vector_get(exptimes, i) -
6079 cpl_vector_get(dits, j)) > tolerance)
6082 if(ndiffs == ndits) {
6083 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
6088 cpl_vector_set_size(dits, ndits);
6096 static cpl_error_code
6097 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
6098 const cpl_vector * vec_ndits,
6100 cpl_vector** diff_dits,
6101 cpl_vector** diff_ndits)
6109 * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6110 * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
6113 cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
6114 cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
6117 size=cpl_vector_get_size(exptimes);
6119 for(i = 1; i < size; i++) {
6121 for (j = 0; j < ndits; j++) {
6122 if (fabs(cpl_vector_get(exptimes, i) -
6123 cpl_vector_get(*diff_dits,j)) > tolerance)
6126 if(ndiffs == ndits) {
6127 cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
6128 cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
6133 cpl_vector_set_size(*diff_dits, ndits);
6134 cpl_vector_set_size(*diff_ndits, ndits);
6137 return cpl_error_get_code();
6225 detmon_lin(
const cpl_imagelist * imlist_on,
6226 const cpl_imagelist * imlist_off,
6227 const cpl_vector * exptimes,
6237 cpl_propertylist * qclist,
6239 cpl_imagelist ** coeffs_cube,
6242 cpl_table * lin_table = NULL;
6243 cpl_imagelist * c_onlist = NULL;
6244 cpl_imagelist * c_offlist = NULL;
6245 cpl_vector * diffdits = NULL;
6246 cpl_imagelist * lin_inputs = NULL;
6247 cpl_polynomial * poly_linfit = NULL;
6248 cpl_image * fiterror = NULL;
6249 cpl_vector * vcoeffs = NULL;
6250 double * pcoeffs = NULL;
6251 int ndiffdits, ndits;
6253 cpl_boolean opt_nir = mode & IRPLIB_LIN_OPT ? OPT : NIR;
6254 const cpl_vector *x = NULL;
6255 const cpl_vector *y = NULL;
6257 const cpl_image * first = NULL;
6265 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6266 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6267 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6268 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6269 cpl_ensure(order > 0 , CPL_ERROR_ILLEGAL_INPUT, NULL);
6271 vcoeffs = cpl_vector_new(order + 1);
6272 pcoeffs = cpl_vector_get_data(vcoeffs);
6275 if (mode & IRPLIB_LIN_PIX2PIX) {
6276 cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
6277 cpl_ensure(bpm != NULL, CPL_ERROR_NULL_INPUT, NULL);
6278 lin_inputs = cpl_imagelist_new();
6282 lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6283 skip_if(detmon_lin_table_create(lin_table, opt_nir));
6287 diffdits = detmon_lg_find_dits(exptimes, tolerance);
6288 ndiffdits = cpl_vector_get_size(diffdits);
6290 ndits = cpl_vector_get_size(exptimes);
6320 if (mode & IRPLIB_LIN_COLLAPSE) {
6325 cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
6326 skip_if(collapse == NULL);
6328 c_offlist = cpl_imagelist_new();
6329 skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
6333 for (i = 0; i < ndiffdits; i++) {
6337 double c_dit = cpl_vector_get(diffdits, i);
6339 c_onlist = cpl_imagelist_new();
6342 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6343 c_offlist = cpl_imagelist_new();
6347 for(j = 0; j < ndits; j++) {
6348 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6358 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6359 const cpl_image * im =
6360 cpl_imagelist_get_const(imlist_on, j);
6361 im_on = cpl_image_duplicate(im);
6363 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6365 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6372 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6374 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6375 const cpl_image * im =
6376 cpl_imagelist_get_const(imlist_off, j);
6377 im_off = cpl_image_duplicate(im);
6380 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6382 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6389 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6390 skip_if (c_nons != c_noffs);
6393 skip_if (c_nons == 0 || c_nons % 2 != 0);
6396 if(mode & IRPLIB_LIN_WITH_RESCALE) {
6397 skip_if(detmon_lg_rescale(c_onlist));
6398 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6399 skip_if(detmon_lg_rescale(c_offlist));
6406 skip_if(detmon_lin_table_fill_row(lin_table, c_dit,
6408 c_onlist, c_offlist,
6412 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6413 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6414 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6415 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6416 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6417 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6420 cpl_imagelist_unset(c_onlist, 0);
6422 cpl_imagelist_unset(c_onlist, 0);
6424 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6425 cpl_imagelist_unset(c_offlist, 0);
6427 cpl_imagelist_unset(c_offlist, 0);
6435 cpl_imagelist_delete(c_onlist);
6436 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6437 cpl_imagelist_delete(c_offlist);
6441 skip_if(detmon_add_adl_column(lin_table, opt_nir));
6443 if(!(mode & IRPLIB_LIN_PIX2PIX)) {
6446 y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6447 (
double *)cpl_table_get_data_double_const(lin_table,
6449 if (opt_nir == NIR) {
6450 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6451 (
double *)cpl_table_get_data_double_const(lin_table,
"DIT"));
6453 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6454 (
double *)cpl_table_get_data_double_const(lin_table,
"EXPTIME"));
6456 if(x == NULL || y == NULL) {
6457 cpl_vector_unwrap((cpl_vector *)x);
6458 cpl_vector_unwrap((cpl_vector *)y);
6468 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
6469 poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
6471 if(order == cpl_vector_get_size(x) - 1) {
6472 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
6476 if(poly_linfit == NULL) {
6477 cpl_vector_unwrap((cpl_vector *)x);
6478 cpl_vector_unwrap((cpl_vector *)y);
6483 cpl_vector_unwrap((cpl_vector *)x);
6484 cpl_vector_unwrap((cpl_vector *)y);
6486 for(deg = 0; deg <= order; deg++) {
6487 const double coeff =
6488 cpl_polynomial_get_coeff(poly_linfit, °);
6490 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
6491 assert(name_o != NULL);
6492 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
6493 skip_if(cpl_propertylist_set_comment(qclist,name_o,
6494 DETMON_QC_LIN_COEF_C));
6496 pcoeffs[deg] = coeff;
6498 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
6499 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
6500 DETMON_QC_ERRFIT_MSE_C));
6504 if (opt_nir == NIR) {
6505 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6506 (
double *)cpl_table_get_data_double_const(lin_table,
6509 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6510 (
double *)cpl_table_get_data_double_const(lin_table,
6515 first = cpl_imagelist_get_const(lin_inputs, 0);
6516 sizex = cpl_image_get_size_x(first);
6517 sizey = cpl_image_get_size_y(first);
6519 vsize = cpl_vector_get_size(x);
6521 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
6524 cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
6525 order, FALSE, CPL_TYPE_FLOAT,
6528 cpl_vector_unwrap((cpl_vector*)x);
6529 irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
6530 "Failed polynomial fit");
6532 for(i = 0; i <= order; i++) {
6533 cpl_image *image = cpl_imagelist_get(*coeffs_cube, i);
6534 const double coeff = cpl_image_get_median(image);
6535 char * name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", i);
6536 char * name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", i);
6538 assert(name_o1 != NULL);
6539 assert(name_o2 != NULL);
6540 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
6541 skip_if(cpl_propertylist_set_comment(qclist,name_o1,
6542 DETMON_QC_LIN_COEF_C));
6545 skip_if(cpl_propertylist_append_double(qclist, name_o2,
6546 cpl_image_get_stdev(image)));
6547 skip_if(cpl_propertylist_set_comment(qclist,name_o2,
6548 DETMON_QC_LIN_COEF_ERR_C));
6553 if(order == vsize - 1) {
6554 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
6555 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
6557 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
6558 DETMON_QC_ERRFIT_C));
6562 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
6563 cpl_image_get_median(fiterror)));
6564 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
6565 DETMON_QC_ERRFIT_C));
6570 skip_if(detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
6572 if(mode & IRPLIB_LIN_PIX2PIX) {
6574 *bpm = detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
6575 skip_if(*bpm == NULL);
6576 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
6578 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
6579 DETMON_QC_NUM_BPM_C));
6584 cpl_vector_delete(diffdits);
6585 cpl_polynomial_delete(poly_linfit);
6586 cpl_imagelist_delete(lin_inputs);
6587 cpl_vector_delete(vcoeffs);
6588 cpl_image_delete(fiterror);
6619 static cpl_error_code
6620 detmon_lin_table_fill_row(cpl_table * lin_table,
double c_dit,
6621 cpl_imagelist * linearity_inputs,
6622 const cpl_imagelist * ons,
6623 const cpl_imagelist * offs,
6632 cpl_image * extracted=NULL;
6634 cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
6635 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
6636 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
6638 if (mode & IRPLIB_LIN_PIX2PIX) {
6639 cpl_msg_debug(cpl_func,
"checking linearity inputs");
6640 cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
6644 if (mode & IRPLIB_LIN_NIR) {
6645 cpl_table_set(lin_table,
"DIT", pos, c_dit);
6646 }
else if (mode & IRPLIB_LIN_OPT) {
6647 cpl_table_set(lin_table,
"EXPTIME", pos, c_dit);
6649 cpl_msg_error(cpl_func,
"Mandatory mode not given");
6653 const cpl_image * off2;
6654 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
6655 off2 = cpl_imagelist_get_const(offs, 0);
6657 off2 = cpl_imagelist_get_const(offs, 1);
6659 extracted = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
6660 cpl_imagelist_get_const(offs, 0),
6661 cpl_imagelist_get_const(ons, 1),
6663 llx, lly, urx, ury);
6664 cpl_ensure_code(extracted != NULL, cpl_error_get_code());
6668 double median = cpl_image_get_median(extracted);
6669 double mean= cpl_image_get_mean(extracted);
6670 cpl_table_set(lin_table,
"MED", pos, median);
6671 cpl_table_set(lin_table,
"MEAN", pos, mean);
6673 cpl_table_set(lin_table,
"MED_DIT", pos, median / c_dit);
6674 cpl_table_set(lin_table,
"MEAN_DIT", pos, mean / c_dit);
6678 if(mode & IRPLIB_LIN_PIX2PIX) {
6679 cpl_error_code error = cpl_imagelist_set(linearity_inputs, extracted,
6681 cpl_ensure_code(!error, error);
6683 cpl_image_delete(extracted);
6686 return cpl_error_get_code();
6689 static double irplib_calculate_total_noise_smooth(
const cpl_image* pimage,
6690 int pattern_x,
int pattern_y)
6692 cpl_image * p_tmp_image = 0;
6693 cpl_image * psmooth_image = 0;
6695 cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
6697 p_tmp_image = cpl_image_duplicate(pimage);
6698 cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
6699 cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
6700 psmooth_image = cpl_image_divide_create(pimage,p_tmp_image);
6701 ret_noise = irplib_calculate_total_noise(psmooth_image);
6702 cpl_mask_delete(mask);
6703 cpl_image_delete(psmooth_image);
6704 cpl_image_delete(p_tmp_image);
6708 static double irplib_calculate_total_noise(
const cpl_image* pimage)
6710 double total_noise = -1;
6711 unsigned long max_bin_size = 1E5;
6712 const double hstart = cpl_image_get_min(pimage);
6713 const double hrange = cpl_image_get_max(pimage) - hstart;
6714 const unsigned long nbins = max_bin_size;
6715 cpl_error_code err = CPL_ERROR_NONE;
6717 irplib_hist * phist = 0;
6718 phist = irplib_hist_new();
6721 irplib_hist_init(phist, nbins, hstart, hrange);
6722 err = irplib_hist_fill(phist, pimage);
6723 if (err == CPL_ERROR_NONE)
6731 unsigned long n_bins = irplib_hist_get_nbins(phist);
6732 double start = irplib_hist_get_start(phist);
6733 double bin_size = irplib_hist_get_bin_size(phist);
6734 cpl_vector* pdata_vector = cpl_vector_new(n_bins);
6735 cpl_vector* ppos_vector = cpl_vector_new(n_bins);
6736 cpl_table* ptable = cpl_table_new(n_bins);
6737 cpl_table_new_column(ptable,
"bin", CPL_TYPE_DOUBLE);
6738 cpl_table_new_column(ptable,
"value", CPL_TYPE_DOUBLE);
6739 for(i = 0; i < n_bins; i++)
6741 unsigned int value = irplib_hist_get_value(phist, i);
6742 double dvalue = (double)(value);
6743 cpl_vector_set(pdata_vector, i, dvalue);
6744 cpl_vector_set(ppos_vector, i, start + i * bin_size);
6746 cpl_table_set(ptable,
"bin", i, start + i * bin_size);
6747 cpl_table_set(ptable,
"value", i, dvalue);
6749 err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
6750 if (err == CPL_ERROR_NONE)
6752 cpl_msg_info(cpl_func,
"FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
6756 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed Gaussian Fit, err msg [%s]", cpl_error_get_message());
6759 cpl_table_delete(ptable);
6760 cpl_vector_delete(ppos_vector);
6761 cpl_vector_delete(pdata_vector);
6765 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
6768 irplib_hist_delete(phist);
6773 static double irplib_compute_err(
double gain,
double ron,
double FA)
6775 double int_gain = (gain * gain - 1) / 12;
6780 return sqrt(ron * ron + FA / gain + int_gain);
6783 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain ,
6784 FPN_METHOD fpn_method,
int smooth_size,
double* mse)
6786 cpl_image* im_diff = 0;
6787 const cpl_image* im_f1 = f1;
6788 cpl_image* im_inrange1 = 0;
6797 cpl_msg_warning(cpl_func,
"gain[%f]<0", gain);
6798 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
6805 im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
6806 im_f1 = im_inrange1;
6808 FA = cpl_image_get_median(im_f1);
6815 cpl_msg_info(cpl_func,
"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
6816 s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
6819 cpl_msg_info(cpl_func,
"HISTOGRAM method is used for FPN");
6820 s_tot = irplib_calculate_total_noise(im_f1);
6825 cpl_msg_warning(cpl_func,
"fpn_method is not defined");
6834 cpl_msg_warning(cpl_func,
"Median flux on sum of flats<0");
6835 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
6840 if ((s_tot * s_tot - FA / gain) > 0)
6842 s_fpn = sqrt(s_tot * s_tot - FA / gain);
6843 sr_fpn = s_fpn / FA;
6844 *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
6848 cpl_msg_warning(cpl_func,
"s_tot * s_tot < FA / gain");
6849 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
6858 cpl_image_delete(im_diff);
6861 cpl_image_delete(im_inrange1);
6867 static cpl_imagelist * irplib_load_fset_wrp(
const cpl_frameset * pframeset,
6868 cpl_type type ,
int whichext)
6872 return detmon_load_frameset_window(pframeset, type, 0, whichext,
6873 detmon_lg_config.llx,
6874 detmon_lg_config.lly,
6875 detmon_lg_config.urx,
6876 detmon_lg_config.ury,
6877 detmon_lg_config.nx,
6878 detmon_lg_config.ny);
6881 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset * pframeset,
6882 cpl_type type ,
int whichext)
6885 cpl_imagelist* offs = cpl_imagelist_new();
6886 detmon_lg_config.load_fset(pframeset, type, offs);
6891 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
6892 cpl_propertylist* plist)
6894 if (ptable && plist)
6896 int size = cpl_propertylist_get_size(plist);
6898 for (i = 0; i < size; i++)
6900 cpl_property* pprop = cpl_propertylist_get(plist,i);
6903 const char* pname = cpl_property_get_name(pprop);
6906 cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
6907 if (cpl_error_get_code() != CPL_ERROR_NONE)
6909 cpl_msg_warning(cpl_func,
"cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
6916 return cpl_error_get_code();
6919 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
6920 cpl_propertylist* plist,
int row)
6922 cpl_error_code err = CPL_ERROR_NONE;
6923 if (ptable && plist)
6925 int size = cpl_propertylist_get_size(plist);
6927 for (i = 0; i < size; i++)
6929 cpl_property* pprop = cpl_propertylist_get(plist,i);
6932 const char* pname = cpl_property_get_name(pprop);
6933 double value = cpl_property_get_double(pprop);
6936 cpl_table_set_double(ptable, pname, row, value);
6937 if (cpl_error_get_code() != CPL_ERROR_NONE)
6939 cpl_msg_warning(cpl_func,
"cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
6950 cpl_error_code detmon_check_order(
const double *exptime,
int sz,
6951 double tolerance,
int order)
6968 }
while(fabs(exptime[i-1] - exptime[i]) < tolerance);
6969 }
while(i < sz - 1);
6971 if (!fabs(exptime[i-1] - exptime[i]) < tolerance) nsets++;
6974 cpl_error_set_message(cpl_func,CPL_ERROR_INCOMPATIBLE_INPUT,
6975 "Not enough frames for the polynomial"
6976 " fitting. nsets = %d <= %d order",
6979 return cpl_error_get_code();
6982 static cpl_error_code
6983 detmon_lg_dfs_save_imagelist(
6984 cpl_frameset * frameset,
6985 const cpl_parameterlist * parlist,
6986 const cpl_frameset *usedframes,
6987 const cpl_imagelist *coeffs,
6988 const char *recipe_name,
6989 const cpl_propertylist *mypro_coeffscube,
6990 const char * package,
6991 const char * name_o)
6993 return(cpl_dfs_save_imagelist
6994 (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
6995 recipe_name, mypro_coeffscube, NULL, package,
6999 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos)
7001 const cpl_image* first = cpl_imagelist_get(imlist, 0);
7004 int x = cpl_image_get_size_x(first);
7005 int y = cpl_image_get_size_y(first);
7006 cpl_type type = cpl_image_get_type(first);
7007 cpl_image * blank = cpl_image_new(x, y, type);
7008 cpl_imagelist_set(imlist, blank, pos);
7014 detmon_lg_set_tag(cpl_frameset*
set,
const char** tag_on,
const char** tag_off)
7019 ntag_old=cpl_frameset_count_tags(
set,DETMON_LG_ON_RAW_OLD);
7020 ntag_new=cpl_frameset_count_tags(
set,DETMON_LG_ON_RAW_NEW);
7022 *tag_on=DETMON_LG_ON_RAW_OLD;
7023 *tag_off=DETMON_LG_OFF_RAW_OLD;
7024 }
else if (ntag_new) {
7025 *tag_on=DETMON_LG_ON_RAW_NEW;
7026 *tag_off=DETMON_LG_OFF_RAW_NEW;
7028 cpl_msg_error(cpl_func,
"Provide %s and %s (or %s and %s) input frames",
7029 DETMON_LG_ON_RAW_NEW,DETMON_LG_OFF_RAW_NEW,
7030 DETMON_LG_ON_RAW_OLD,DETMON_LG_OFF_RAW_OLD);
7034 return cpl_error_get_code();