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)
2912 if (cpl_frameset_get_size(set_off) % 2 != 0) {
2913 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
2914 "If collapse is FALSE the OFF frameset"
2915 " must be organized in pairs.");
2918 if (!strcmp(detmon_lg_config.method,
"MED") ||
2919 cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
2921 skip_if(detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off, detmon_lg_config.tolerance));
2925 skip_if(detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
2928 cpl_msg_debug(cpl_func,
" Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
2929 offs = detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
2931 skip_if(offs == NULL);
2932 skip_if(cpl_error_get_code());
2935 offs = (cpl_imagelist *) opt_offs;
2939 if(detmon_lg_config.rescale)
2941 skip_if(detmon_lg_rescale(ons));
2942 if (!detmon_lg_config.collapse &&
2943 !strcmp(detmon_lg_config.method,
"MED"))
2944 skip_if(detmon_lg_rescale(offs));
2949 cpl_frame_get_filename(cpl_frameset_get_first_const(pair_on));
2950 skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
2954 pDETlist = cpl_propertylist_new();
2955 cpl_propertylist_copy_property_regexp(pDETlist, plist,
"DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
2958 irplib_table_create_column(gain_table, pDETlist);
2959 irplib_table_create_column(linear_table, pDETlist);
2962 if(opt_nir == NIR) {
2963 c_dit = irplib_pfits_get_dit(plist);
2964 c_ndit = irplib_pfits_get_ndit(plist);
2966 c_dit = irplib_pfits_get_exptime(plist);
2978 cpl_msg_info(cpl_func,
"Computing GAIN for EXPTIME value nb %d",
2982 if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
2984 cpl_table_erase_column(gain_table,
"MEAN_OFF1");
2985 cpl_table_erase_column(gain_table,
"MEAN_OFF2");
2986 cpl_table_erase_column(gain_table,
"SIG_OFF_DIF");
2987 cpl_table_erase_column(gain_table,
"GAIN");
2988 cpl_table_erase_column(gain_table,
"GAIN_CORR");
2989 cpl_table_new_column(gain_table,
"MEAN_OFF", CPL_TYPE_DOUBLE);
2992 skip_if(detmon_gain_table_fill_row(gain_table,
2995 diff_flats, ons, offs,
2996 detmon_lg_config.kappa,
2997 detmon_lg_config.niter,
2998 detmon_lg_config.llx,
2999 detmon_lg_config.lly,
3000 detmon_lg_config.urx,
3001 detmon_lg_config.ury,
3004 detmon_lg_config.saturation_limit,
3005 dit_nb, mode, rows_affected));
3011 skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
3013 cpl_msg_info(cpl_func,
"Linearity reduction for nb %d",
3015 skip_if(detmon_lin_table_fill_row(linear_table, c_dit,
3016 linearity_inputs, ons, offs,
3017 detmon_lg_config.llx,
3018 detmon_lg_config.lly,
3019 detmon_lg_config.urx,
3020 detmon_lg_config.ury,
3021 dit_nb, *dit_nskip, mode));
3023 skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
3035 if(opt_nir == OPT &&
3036 *rows_affected != 0 ) {
3037 detmon_opt_contamination(ons, offs, mode, qclist);
3044 cpl_frameset_delete(pair_on);
3045 cpl_imagelist_delete(ons);
3047 if(!detmon_lg_config.collapse ) {
3048 cpl_imagelist_delete(offs);
3051 if(!detmon_lg_config.collapse) {
3052 cpl_frameset_delete(pair_off);
3055 cpl_propertylist_delete(plist);
3056 cpl_propertylist_delete(pDETlist);
3057 return cpl_error_get_code();
3067 static cpl_error_code
3068 detmon_add_adl_column(cpl_table * table,
3069 cpl_boolean opt_nir)
3071 cpl_error_code error;
3072 double mean_med_dit;
3075 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
3077 mean_med_dit = cpl_table_get_column_mean(table,
"MED_DIT");
3079 dits = cpl_table_get_data_double(table,
"EXPTIME");
3081 dits = cpl_table_get_data_double(table,
"DIT");
3083 error = cpl_table_copy_data_double(table,
"ADL", dits);
3084 cpl_ensure_code(!error, error);
3085 error = cpl_table_multiply_scalar(table,
"ADL", mean_med_dit);
3086 cpl_ensure_code(!error, error);
3088 return cpl_error_get_code();
3100 static cpl_error_code
3101 detmon_lg_reduce_init(cpl_table * gain_table,
3102 cpl_table * linear_table,
3103 cpl_imagelist ** linearity_inputs,
3104 const cpl_boolean opt_nir)
3106 skip_if(detmon_gain_table_create(gain_table, opt_nir));
3107 skip_if(detmon_lin_table_create(linear_table, opt_nir));
3109 if(detmon_lg_config.pix2pix) {
3110 *linearity_inputs = cpl_imagelist_new();
3111 skip_if(*linearity_inputs == NULL);
3116 return cpl_error_get_code();
3127 irplib_pfits_get_dit(
const cpl_propertylist * plist)
3129 return irplib_pfits_get_prop_double(plist,
"ESO DET DIT");
3140 irplib_pfits_get_dit_opt(
const cpl_propertylist * plist)
3142 return irplib_pfits_get_prop_double(plist,
"ESO DET WIN1 UIT1");
3151 static cpl_propertylist*
3152 detmon_load_pro_keys(
const char* NAME_O)
3154 cpl_propertylist* pro_keys=NULL;
3155 pro_keys=cpl_propertylist_load_regexp(NAME_O,0,
"^(ESO PRO)",0);
3160 static double irplib_pfits_get_prop_double(
const cpl_propertylist * plist,
3161 const char* prop_name)
3164 dit = cpl_propertylist_get_double(plist, prop_name);
3165 if(cpl_error_get_code() != CPL_ERROR_NONE)
3167 cpl_msg_error(cpl_func,
"Cannot read property '%s', err[%s]",
3168 prop_name, cpl_error_get_where());
3206 static cpl_error_code
3207 detmon_gain_table_fill_row(cpl_table * gain_table,
3208 double c_dit,
int c_ndit,
3209 cpl_imagelist * autocorr_images,
3210 cpl_imagelist * diff_flats,
3211 const cpl_imagelist * ons,
3212 const cpl_imagelist * offs,
3213 double kappa,
int nclip,
3214 int llx,
int lly,
int urx,
int ury,
3216 double saturation_limit,
3217 const int pos,
unsigned mode,
int* rows_affected)
3219 const cpl_image *image;
3220 cpl_image *on_dif = NULL;
3222 double avg_on1, avg_on2;
3223 double avg_off1, avg_off2;
3224 double double_adu, autocorr, gain, gain_corr;
3227 cpl_table_set(gain_table,
"FLAG", pos, 1);
3228 if (mode & IRPLIB_GAIN_NIR)
3230 cpl_table_set(gain_table,
"DIT", pos, c_dit);
3231 cpl_table_set(gain_table,
"NDIT", pos, c_ndit);
3232 }
else if (mode & IRPLIB_GAIN_OPT)
3234 cpl_table_set(gain_table,
"EXPTIME", pos, c_dit);
3237 cpl_msg_error(cpl_func,
"Mandatory mode (OPT or NIR) not provided");
3240 if(*rows_affected == 0)
3242 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3243 cpl_table_set(gain_table,
"FLAG", pos, 0);
3244 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3249 detmon_lg_add_empty_image(diff_flats, pos);
3251 if (autocorr_images)
3253 detmon_lg_add_empty_image(autocorr_images, pos);
3256 return cpl_error_get_code();
3258 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3259 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3260 nclip, 1e-5, &avg_on1, &std));
3261 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3262 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
3263 nclip, 1e-5, &avg_on2, &std));
3265 if ((avg_on1 > saturation_limit) || (avg_on2 > saturation_limit))
3267 cpl_msg_warning(cpl_func,
"Average saturation is above the limit, "
3268 "the frames would not be taken into calculation");
3269 cpl_msg_warning(cpl_func,
"saturation levels [%f ; %f], limit [%f]",
3270 avg_on1, avg_on2, saturation_limit);
3271 cpl_msg_info(cpl_func,
"skip the frame #%d", pos + 1);
3272 cpl_table_set(gain_table,
"FLAG", pos, 0);
3273 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3278 detmon_lg_add_empty_image(diff_flats, pos);
3280 if (autocorr_images)
3282 detmon_lg_add_empty_image(autocorr_images, pos);
3291 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON1", pos, avg_on1));
3292 skip_if(cpl_table_set_double(gain_table,
"MEAN_ON2", pos, avg_on2));
3295 detmon_subtract_create_window(cpl_imagelist_get_const(ons, 0),
3296 cpl_imagelist_get_const(ons, 1),
3297 llx, lly, urx, ury);
3298 skip_if(on_dif == NULL);
3300 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
3304 cpl_image * diff = cpl_image_duplicate(on_dif);
3305 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
3307 if (autocorr_images)
3309 cpl_image * corr = NULL;
3310 autocorr = detmon_autocorr_factor(on_dif, &corr, m, n);
3313 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
3317 detmon_lg_add_empty_image(autocorr_images, pos);
3321 autocorr = detmon_autocorr_factor(on_dif, NULL, m, n);
3323 autocorr = isnan(autocorr) ? 1.0 : autocorr;
3329 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE)
3332 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3333 llx, lly, urx, ury, kappa, nclip,
3334 1e-5, &avg_off1, &std));
3335 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF", pos, avg_off1));
3337 }
else if (mode & IRPLIB_GAIN_NO_COLLAPSE ||
3338 ( pos == 0 && mode & IRPLIB_GAIN_COLLAPSE )) {
3339 cpl_image * off_dif = NULL;
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_OFF1", pos, avg_off1));
3345 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 1),
3346 llx, lly, urx, ury, kappa, nclip,
3347 1e-5, &avg_off2, &std));
3348 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, avg_off2));
3350 detmon_subtract_create_window(cpl_imagelist_get_const(offs, 0),
3351 cpl_imagelist_get_const(offs, 1),
3352 llx, lly, urx, ury);
3353 skip_if(off_dif == NULL);
3354 irplib_ksigma_clip(off_dif, 1, 1,
3355 cpl_image_get_size_x(off_dif),
3356 cpl_image_get_size_y(off_dif),
3358 1e-5, &avg_off_dif, &sig_off_dif);
3359 cpl_image_delete(off_dif);
3360 skip_if(cpl_table_set_double(gain_table,
"SIG_OFF_DIF",
3362 }
else if (pos > 0 && mode & IRPLIB_GAIN_COLLAPSE)
3365 avg_off1 = cpl_table_get_double(gain_table,
"MEAN_OFF1", 0, &status);
3366 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF1", pos, avg_off1));
3367 avg_off2 = cpl_table_get_double(gain_table,
"MEAN_OFF2", 0, &status);
3368 skip_if(cpl_table_set_double(gain_table,
"MEAN_OFF2", pos, avg_off2));
3369 sig_off_dif = cpl_table_get_double(gain_table,
"SIG_OFF_DIF",
3371 skip_if(cpl_table_set_double(gain_table,
"SIG_OFF_DIF",
3376 double avg_on_dif, sig_on_dif;
3377 irplib_ksigma_clip(on_dif, 1, 1,
3378 cpl_image_get_size_x(on_dif),
3379 cpl_image_get_size_y(on_dif), kappa,
3380 nclip, 1e-5, &avg_on_dif, &sig_on_dif);
3381 skip_if(cpl_table_set_double(gain_table,
"SIG_ON_DIF", pos, sig_on_dif));
3383 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE)
3385 double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
3389 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
3391 sigma = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
3395 gain = double_adu / (c_ndit * sigma);
3397 gain_corr = gain / (autocorr);
3399 skip_if(cpl_table_set_double(gain_table,
"GAIN", pos, gain));
3400 skip_if(cpl_table_set_double(gain_table,
"GAIN_CORR", pos, gain_corr));
3403 skip_if(cpl_table_set_double(gain_table,
"AUTOCORR", pos, autocorr));
3404 skip_if(cpl_table_set_double(gain_table,
"ADU", pos, double_adu / 2));
3407 skip_if(cpl_table_set_double(gain_table,
"Y_FIT",
3409 c_ndit* sig_on_dif * sig_on_dif));
3410 skip_if(cpl_table_set_double(gain_table,
"Y_FIT_CORR",
3412 c_ndit * sig_on_dif * sig_on_dif));
3413 skip_if(cpl_table_set_double(gain_table,
"X_FIT", pos, double_adu));
3414 skip_if(cpl_table_set_double(gain_table,
"X_FIT_CORR",
3415 pos, double_adu / autocorr));
3420 cpl_image_delete(on_dif);
3422 return cpl_error_get_code();
3435 detmon_bpixs(
const cpl_imagelist * coeffs,
3442 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
3449 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
3450 cpl_image_get_size_y(first));
3451 cpl_image *cur_image = NULL;
3452 cpl_image *bpm = NULL;
3455 size = cpl_imagelist_get_size(coeffs);
3458 bpm = cpl_image_new(cpl_image_get_size_x(first),
3459 cpl_image_get_size_y(first),
3464 for(i = 0; i < size; i++) {
3465 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
3467 stats = cpl_stats_new_from_image(cur_coeff,
3468 CPL_STATS_MEAN | CPL_STATS_STDEV);
3469 cur_mean = cpl_stats_get_mean(stats);
3470 cur_stdev = cpl_stats_get_stdev(stats);
3472 lo_cut = cur_mean - kappa * cur_stdev;
3473 hi_cut = cur_mean + kappa * cur_stdev;
3475 cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
3476 cpl_mask_not(cur_mask);
3479 cur_image = cpl_image_new_from_mask(cur_mask);
3481 cpl_image_power(cur_image, p);
3482 cpl_image_add(bpm, cur_image);
3483 cpl_image_delete(cur_image);
3486 cpl_mask_or(mask, cur_mask);
3488 cpl_mask_delete(cur_mask);
3489 cpl_stats_delete(stats);
3493 bpm = cpl_image_new_from_mask(mask);
3496 *nbpixs += cpl_mask_count(mask);
3498 cpl_mask_delete(mask);
3625 detmon_autocorr_factor(
const cpl_image * image,
3626 cpl_image ** autocorr_image,
int m,
int n)
3628 cpl_image * mycorr_image = NULL;
3629 double autocorr = 0;
3630 cpl_error_code err = CPL_ERROR_NONE;
3632 mycorr_image = detmon_image_correlate(image, image, m, n);
3633 err=cpl_error_get_code();
3634 if (err == CPL_ERROR_UNSUPPORTED_MODE)
3636 cpl_msg_warning(cpl_func,
"FFTW is not supported by CPL, autocorrelation "
3637 "would be computed using internal implementation");
3640 cpl_image_delete(mycorr_image);
3641 mycorr_image = detmon_autocorrelate(image, m, n);
3643 if(mycorr_image == NULL) {
3647 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
3649 autocorr = cpl_image_get_flux(mycorr_image);
3651 if (autocorr_image) *autocorr_image = mycorr_image;
3652 else cpl_image_delete(mycorr_image);
3657 static cpl_propertylist*
3658 detmon_lg_extract_qclist_4plane(cpl_propertylist* linc_qclist,
const int ip)
3661 cpl_propertylist* sub_set=NULL;
3664 sub_set=cpl_propertylist_new();
3665 qc_key=cpl_sprintf(
"QC LIN COEF%d",ip);
3666 cpl_propertylist_copy_property_regexp(sub_set,linc_qclist,qc_key,0);
3683 static cpl_error_code
3684 detmon_lg_extract_extention_header(cpl_frameset* frameset,
3685 cpl_propertylist* gaint_qclist,
3686 cpl_propertylist* lint_qclist,
3687 cpl_propertylist* linc_qclist,
3688 cpl_propertylist* bpm_qclist,
3692 cpl_propertylist * xplist = NULL;
3694 const char * filename =
3695 cpl_frame_get_filename(cpl_frameset_get_first(frameset));
3697 xplist = cpl_propertylist_load_regexp(filename, whichext,
3698 "ESO DET|EXTNAME", 0);
3699 if (detmon_lg_config.exts >= 0)
3702 cpl_property* propExtname = NULL;
3703 propExtname = cpl_propertylist_get_property(xplist,
"EXTNAME");
3705 if (NULL != propExtname)
3707 propExtname = cpl_property_duplicate(propExtname);
3709 cpl_propertylist_delete(xplist);
3711 if (NULL != propExtname)
3713 xplist = cpl_propertylist_new();
3714 cpl_propertylist_append_property(xplist, propExtname);
3715 cpl_property_delete(propExtname);
3720 cpl_propertylist_append(gaint_qclist, xplist);
3721 cpl_propertylist_append(lint_qclist, xplist);
3722 cpl_propertylist_append(linc_qclist, xplist);
3723 cpl_propertylist_append(bpm_qclist, xplist);
3724 cpl_propertylist_delete(xplist);
3727 return cpl_error_get_code();
3744 static cpl_error_code
3745 detmon_lg_save_table_with_pro_keys(cpl_table* table,
3747 cpl_propertylist* xheader,
3748 unsigned CPL_IO_MODE)
3751 cpl_propertylist* pro_keys=NULL;
3753 pro_keys=detmon_load_pro_keys(name_o);
3754 cpl_propertylist_append(xheader,pro_keys);
3756 if(CPL_IO_MODE==CPL_IO_DEFAULT) {
3757 cpl_propertylist * pri_head=cpl_propertylist_load(name_o,0);
3758 cpl_table_save(table, pri_head,xheader,name_o,
3760 cpl_propertylist_delete(pri_head);
3763 cpl_table_save(table,NULL,xheader,name_o,
3766 cpl_propertylist_delete(pro_keys);
3768 return cpl_error_get_code();
3780 static cpl_error_code
3781 detmon_lg_save_image_with_pro_keys(cpl_image* image,
3783 cpl_propertylist* xheader)
3786 cpl_propertylist* pro_keys=NULL;
3787 pro_keys=detmon_load_pro_keys(name_o);
3788 cpl_propertylist_append(xheader,pro_keys);
3790 cpl_image_save(image,name_o, CPL_BPP_IEEE_FLOAT,
3791 xheader,CPL_IO_EXTEND);
3792 cpl_propertylist_delete(pro_keys);
3795 return cpl_error_get_code();
3807 static cpl_error_code
3808 detmon_lg_save_imagelist_with_pro_keys(cpl_imagelist* imagelist,
3810 cpl_propertylist* xheader)
3813 cpl_propertylist* pro_keys=NULL;
3814 pro_keys=detmon_load_pro_keys(name_o);
3815 cpl_propertylist_append(xheader,pro_keys);
3817 cpl_imagelist_save(imagelist,name_o, CPL_BPP_IEEE_FLOAT,
3818 xheader,CPL_IO_EXTEND);
3820 cpl_propertylist_delete(pro_keys);
3823 return cpl_error_get_code();
3843 static cpl_error_code
3844 detmon_lg_save_plane(
const cpl_parameterlist * parlist,
3845 cpl_frameset* frameset,
3846 const cpl_frameset * usedframes,
3848 const char* recipe_name,
3849 cpl_propertylist* mypro_coeffscube,
3850 cpl_propertylist* linc_plane_qclist,
3851 const char* package,
3855 if(detmon_lg_config.exts == 0) {
3856 cpl_propertylist* plist=NULL;
3857 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3859 CPL_BPP_IEEE_FLOAT, recipe_name,
3860 mypro_coeffscube, NULL,
3862 plist=cpl_propertylist_load(NAME_O,0);
3863 cpl_image_save(plane,NAME_O, CPL_BPP_IEEE_FLOAT,
3864 plist,CPL_IO_DEFAULT);
3865 cpl_propertylist_delete(plist);
3867 }
else if(detmon_lg_config.exts > 0) {
3868 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3870 CPL_BPP_IEEE_FLOAT, recipe_name,
3871 mypro_coeffscube, NULL,
3874 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
3878 cpl_dfs_save_image(frameset, NULL, parlist,
3879 usedframes,NULL, NULL,
3880 CPL_BPP_IEEE_FLOAT, recipe_name,
3881 mypro_coeffscube, NULL,
3883 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
3886 detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
3892 return cpl_error_get_code();
3915 static cpl_error_code
3916 detmon_lg_save_cube(
const cpl_parameterlist * parlist,
3917 cpl_frameset* frameset,
3918 const cpl_frameset * usedframes,
3920 const char* recipe_name,
3921 cpl_propertylist* mypro_coeffscube,
3922 cpl_propertylist* linc_qclist,
3923 const char* package,
3925 cpl_imagelist* coeffs)
3928 if(detmon_lg_config.exts == 0) {
3929 cpl_propertylist_append(mypro_coeffscube, linc_qclist);
3930 detmon_lg_dfs_save_imagelist
3931 (frameset, parlist, usedframes, coeffs,
3932 recipe_name, mypro_coeffscube, package,
3934 }
else if(detmon_lg_config.exts > 0) {
3935 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3937 CPL_BPP_IEEE_FLOAT, recipe_name,
3938 mypro_coeffscube, NULL,
3941 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
3945 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
3947 CPL_BPP_IEEE_FLOAT, recipe_name,
3948 mypro_coeffscube, NULL,
3951 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
3953 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
3956 detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
3958 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
3962 return cpl_error_get_code();
3966 detmon_lg_set_paf_name_and_header(cpl_frame* ref_frame,
3967 int flag_sets,
int which_set,
3969 const char* paf_suf,
3970 cpl_propertylist** plist)
3972 char * paf_name=NULL;
3974 if(detmon_lg_config.exts >= 0)
3976 *plist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
3977 detmon_lg_config.exts);
3981 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
3985 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
3986 detmon_lg_config.pafname, paf_suf,which_set);
3991 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
3997 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
3998 detmon_lg_config.pafname, paf_suf,whichext);
4002 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4003 detmon_lg_config.pafname,paf_suf,
4004 which_set, whichext);
4013 detmon_lg_set_paf_name_and_header_ext(cpl_frame* ref_frame,
4014 int flag_sets,
int which_set,
4016 const char* paf_suf,
4017 cpl_propertylist** plist)
4019 char* paf_name=NULL;
4021 if(detmon_lg_config.exts >= 0)
4023 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4024 detmon_lg_config.exts);
4028 paf_name=cpl_sprintf(
"%s_%s.paf", detmon_lg_config.pafname,paf_suf);
4031 paf_name=cpl_sprintf(
"%s_%s_set%02d.paf",
4032 detmon_lg_config.pafname, paf_suf,which_set);
4036 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4040 paf_name=cpl_sprintf(
"%s_%s_ext%02d.paf",
4041 detmon_lg_config.pafname, paf_suf,whichext);
4044 paf_name=cpl_sprintf(
"%s_%s_set%02d_ext%02d.paf",
4045 detmon_lg_config.pafname,paf_suf,
4046 which_set, whichext);
4053 static cpl_error_code
4054 detmon_lg_save_paf_product(cpl_frame* ref_frame,
int flag_sets,
4055 int which_set,
int whichext,
4056 const char* pafregexp,
4057 const char* procatg,
4058 const char* pipeline_name,
4059 const char* recipe_name,
4060 const char* paf_suf,
4061 cpl_propertylist* qclist,
4066 char* paf_name=NULL;
4067 cpl_propertylist* plist=NULL;
4068 cpl_propertylist* paflist = NULL;
4069 cpl_propertylist* mainplist=NULL;
4071 mainplist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0);
4073 paf_name=detmon_lg_set_paf_name_and_header(ref_frame,flag_sets,
4077 paf_name=detmon_lg_set_paf_name_and_header_ext(ref_frame,flag_sets,
4083 paflist = cpl_propertylist_new();
4084 cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,procatg);
4087 cpl_propertylist_copy_property_regexp(paflist, plist,pafregexp, 0);
4088 cpl_propertylist_copy_property_regexp(paflist, mainplist,pafregexp, 0);
4089 cpl_propertylist_append(paflist,qclist);
4092 cpl_dfs_save_paf(pipeline_name, recipe_name,paflist,paf_name);
4095 cpl_propertylist_delete(mainplist);
4096 cpl_propertylist_delete(paflist);
4097 cpl_propertylist_delete(plist);
4100 return cpl_error_get_code();
4137 static cpl_error_code
4138 detmon_lg_save(
const cpl_parameterlist * parlist,
4139 cpl_frameset * frameset,
4140 const char *recipe_name,
4141 const char *pipeline_name,
4142 const char *pafregexp,
4143 const cpl_propertylist * pro_lintbl,
4144 const cpl_propertylist * pro_gaintbl,
4145 const cpl_propertylist * pro_coeffscube,
4146 const cpl_propertylist * pro_bpm,
4147 const cpl_propertylist * pro_corr,
4148 const cpl_propertylist * pro_diff,
4149 const char *package,
4150 cpl_imagelist * coeffs,
4151 cpl_table * gain_table,
4152 cpl_table * linear_table,
4154 cpl_imagelist * autocorr_images,
4155 cpl_imagelist * diff_flats,
4156 cpl_propertylist * gaint_qclist,
4157 cpl_propertylist * lint_qclist,
4158 cpl_propertylist * linc_qclist,
4159 cpl_propertylist * bpm_qclist,
4160 const int flag_sets,
4161 const int which_set,
4162 const cpl_frameset * usedframes,
4166 cpl_frame *ref_frame;
4167 cpl_propertylist *plist = NULL;
4168 cpl_propertylist *mainplist = NULL;
4174 cpl_propertylist * xplist = NULL;
4176 cpl_propertylist* linc_plane_qclist=NULL;
4177 cpl_image* plane=NULL;
4179 char* pcatg_plane=NULL;
4181 cpl_propertylist * mypro_lintbl =
4182 cpl_propertylist_duplicate(pro_lintbl);
4183 cpl_propertylist * mypro_gaintbl =
4184 cpl_propertylist_duplicate(pro_gaintbl);
4185 cpl_propertylist * mypro_coeffscube =
4186 cpl_propertylist_duplicate(pro_coeffscube);
4187 cpl_propertylist * mypro_bpm =
4188 cpl_propertylist_duplicate(pro_bpm);
4189 cpl_propertylist * mypro_corr =
4190 cpl_propertylist_duplicate(pro_corr);
4191 cpl_propertylist * mypro_diff =
4192 cpl_propertylist_duplicate(pro_diff);
4194 const char * procatg_lintbl =
4195 cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
4197 const char * procatg_gaintbl =
4198 cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
4200 const char * procatg_coeffscube =
4201 cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
4202 const char * procatg_bpm =
4203 cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
4207 detmon_lg_extract_extention_header(frameset,gaint_qclist,lint_qclist,
4208 linc_qclist,bpm_qclist,whichext);
4213 ref_frame = cpl_frameset_get_first(frameset);
4215 skip_if((mainplist =
4216 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4222 cpl_msg_info(cpl_func,
"Write the LINEARITY TABLE");
4225 NAME_O=cpl_sprintf(
"%s_linearity_table.fits", recipe_name);
4227 NAME_O=cpl_sprintf(
"%s_linearity_table_set%02d.fits", recipe_name,
4231 if (detmon_lg_config.exts >= 0) {
4233 cpl_propertylist_append(mypro_lintbl, lint_qclist);
4234 skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,
4235 linear_table,NULL, recipe_name,
4236 mypro_lintbl, NULL, package, NAME_O));
4238 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4239 lint_qclist,CPL_IO_DEFAULT);
4244 skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL,
4245 linear_table,lint_qclist, recipe_name,
4246 mypro_lintbl,NULL, package, NAME_O));
4247 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4248 lint_qclist,CPL_IO_DEFAULT);
4255 detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4256 lint_qclist,CPL_IO_EXTEND);
4259 irplib_free(&NAME_O);
4263 cpl_msg_info(cpl_func,
"Write the GAIN TABLE");
4266 NAME_O=cpl_sprintf(
"%s_gain_table.fits", recipe_name);
4268 NAME_O=cpl_sprintf(
"%s_gain_table_set%02d.fits", recipe_name,
4272 if (detmon_lg_config.exts >= 0)
4276 cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
4277 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
4278 gain_table,NULL, recipe_name, mypro_gaintbl,
4279 NULL, package, NAME_O));
4280 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4281 gaint_qclist,CPL_IO_DEFAULT);
4289 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
4290 gaint_qclist, recipe_name, mypro_gaintbl,
4291 NULL, package, NAME_O));
4292 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4293 gaint_qclist,CPL_IO_DEFAULT);
4299 detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
4300 gaint_qclist,CPL_IO_EXTEND);
4304 if(detmon_lg_config.pix2pix)
4310 cpl_msg_info(cpl_func,
"Write the COEFFS FITS");
4311 irplib_free(&NAME_O);
4314 PREF_O=cpl_sprintf(
"%s_coeffs_cube", recipe_name);
4317 PREF_O=cpl_sprintf(
"%s_coeffs_cube_set%02d",
4318 recipe_name, which_set);
4320 if (detmon_lg_config.split_coeffs == 0) {
4321 NAME_O=cpl_sprintf(
"%s.fits", PREF_O);
4326 if(detmon_lg_config.split_coeffs != 0){
4329 nb_images = cpl_imagelist_get_size(coeffs);
4330 for(ip=0;ip<nb_images;ip++) {
4331 NAME_O=cpl_sprintf(
"%s_P%d.fits", PREF_O,ip);
4332 pcatg_plane=cpl_sprintf(
"COEFFS_CUBE_P%d",ip);
4333 cpl_propertylist_delete(mypro_coeffscube);
4334 mypro_coeffscube=cpl_propertylist_duplicate(pro_coeffscube);
4335 cpl_propertylist_set_string(mypro_coeffscube,CPL_DFS_PRO_CATG,
4337 linc_plane_qclist=detmon_lg_extract_qclist_4plane(linc_qclist,ip);
4338 cpl_propertylist_append(mypro_coeffscube, linc_plane_qclist);
4339 plane=cpl_imagelist_get(coeffs,ip);
4340 detmon_lg_save_plane(parlist,frameset,usedframes,whichext,
4341 recipe_name,mypro_coeffscube,
4342 linc_plane_qclist,package,NAME_O,plane);
4344 if(NULL!=linc_plane_qclist) {
4345 cpl_propertylist_delete(linc_plane_qclist);
4347 irplib_free(&NAME_O);
4352 detmon_lg_save_cube(parlist,frameset,usedframes,whichext,
4353 recipe_name,mypro_coeffscube,
4354 linc_qclist,package,NAME_O,coeffs);
4360 cpl_msg_info(cpl_func,
"Write the BAD PIXEL MAP");
4361 irplib_free(&NAME_O);
4365 NAME_O=cpl_sprintf(
"%s_bpm.fits", recipe_name);
4368 NAME_O=cpl_sprintf(
"%s_bpm_set%02d.fits", recipe_name, which_set);
4373 if(detmon_lg_config.exts == 0) {
4374 cpl_propertylist_append(mypro_bpm, bpm_qclist);
4375 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
4376 CPL_BPP_IEEE_FLOAT, recipe_name,
4377 mypro_bpm, NULL, package,
4380 else if(detmon_lg_config.exts > 0)
4382 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4383 CPL_BPP_IEEE_FLOAT, recipe_name,
4384 mypro_bpm, NULL, package,
4386 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4392 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4393 CPL_BPP_IEEE_FLOAT, recipe_name,
4394 mypro_bpm, NULL, package,
4396 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4399 detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4404 if(detmon_lg_config.intermediate)
4409 cpl_msg_info(cpl_func,
"Write the AUTOCORRS FITS");
4410 nb_images = cpl_imagelist_get_size(autocorr_images);
4411 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
4412 for(i = 0; i < nb_images; i++)
4414 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_corr);
4416 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4418 if(i < cpl_table_get_nrow(linear_table))
4420 ddit = cpl_table_get_double(linear_table,
4421 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4423 cpl_array_delete(pnames);
4426 irplib_free(&NAME_O);
4429 NAME_O=cpl_sprintf(
"%s_autocorr_%d.fits", recipe_name, i);
4430 assert(NAME_O != NULL);
4433 NAME_O=cpl_sprintf(
"%s_autocorr_%02d_set%02d.fits",
4434 recipe_name, i, which_set);
4435 assert(NAME_O != NULL);
4438 if(detmon_lg_config.exts > 0)
4440 cpl_propertylist* pextlist = cpl_propertylist_new();
4441 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4442 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4443 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4444 recipe_name, pplist, NULL,
4447 detmon_lg_save_image_with_pro_keys(
4448 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4450 cpl_propertylist_delete(pextlist);
4452 if(detmon_lg_config.exts == 0)
4454 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4455 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
4456 cpl_imagelist_get(autocorr_images, i),
4458 recipe_name, pplist, NULL, package,
4464 cpl_propertylist* pextlist = cpl_propertylist_new();
4465 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4468 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4469 usedframes, NULL,NULL,
4470 CPL_BPP_IEEE_FLOAT, recipe_name,
4474 detmon_lg_save_image_with_pro_keys(
4475 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4480 detmon_lg_save_image_with_pro_keys(
4481 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4483 cpl_propertylist_delete(pextlist);
4485 cpl_propertylist_delete (pplist);
4487 irplib_free(&NAME_O);
4496 cpl_msg_info(cpl_func,
"Write the DIFFS FITS");
4498 for(i = 0; i < nb_images; i++)
4500 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_diff);
4502 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4504 if(i < cpl_table_get_nrow(linear_table))
4506 ddit = cpl_table_get_double(linear_table,
4507 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4509 cpl_array_delete(pnames);
4514 NAME_O=cpl_sprintf(
"%s_diff_flat_%d.fits", recipe_name, i);
4517 NAME_O=cpl_sprintf(
"%s_diff_flat_%d_set%02d.fits",
4518 recipe_name, i, which_set);
4521 if(detmon_lg_config.exts > 0)
4523 cpl_propertylist* pextlist = cpl_propertylist_new();
4524 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4525 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT", ddit);
4526 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4527 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4529 mypro_diff, NULL,package, NAME_O));
4531 detmon_lg_save_image_with_pro_keys(
4532 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4534 cpl_propertylist_delete(pextlist);
4536 else if(detmon_lg_config.exts == 0)
4538 cpl_propertylist_append_double(pplist,
"ESO DET DIT", ddit);
4540 (frameset, NULL, parlist, usedframes, NULL,
4541 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
4542 recipe_name, pplist, NULL, package,
4547 cpl_propertylist* pextlist = cpl_propertylist_new();
4548 cpl_propertylist_append_double(pextlist,
"ESO DET DIT", ddit);
4551 cpl_propertylist_append_double(mypro_diff,
"ESO DET DIT",ddit);
4553 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4554 usedframes, NULL,NULL,
4555 CPL_BPP_IEEE_FLOAT, recipe_name,
4556 mypro_diff, NULL,package, NAME_O));
4558 detmon_lg_save_image_with_pro_keys(
4559 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4564 detmon_lg_save_image_with_pro_keys(
4565 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4568 cpl_propertylist_delete(pextlist);
4570 cpl_propertylist_delete(pplist);
4571 irplib_free(&NAME_O);
4579 cpl_msg_info(cpl_func,
"Write the PAF file(s)");
4581 if(detmon_lg_config.pafgen) {
4583 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4584 pafregexp,procatg_gaintbl,
4585 pipeline_name,recipe_name,
4586 "qc01",gaint_qclist,0);
4588 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4589 pafregexp,procatg_lintbl,
4590 pipeline_name,recipe_name,
4591 "qc02",lint_qclist,0);
4593 if(detmon_lg_config.pix2pix)
4596 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4599 pipeline_name,recipe_name,
4600 "qc03",linc_qclist,1);
4602 detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4603 whichext,pafregexp,procatg_bpm,
4604 pipeline_name,recipe_name,
4605 "qc04",bpm_qclist,1);
4610 cpl_msg_info(cpl_func,
"exit");
4612 cpl_propertylist_delete(xplist);
4614 cpl_propertylist_delete(plist);
4618 irplib_free(&NAME_O);
4620 cpl_free(pcatg_plane);
4621 cpl_propertylist_delete(mainplist);
4622 cpl_propertylist_delete(mypro_lintbl);
4623 cpl_propertylist_delete(mypro_gaintbl);
4624 cpl_propertylist_delete(mypro_coeffscube);
4625 cpl_propertylist_delete(mypro_bpm);
4626 cpl_propertylist_delete(mypro_corr);
4627 cpl_propertylist_delete(mypro_diff);
4629 return cpl_error_get_code();
4642 static cpl_error_code
4643 detmon_opt_contamination(
const cpl_imagelist * ons,
4644 const cpl_imagelist * offs,
4646 cpl_propertylist * qclist)
4654 struct rect rects[5] = {
4655 (
struct rect){ detmon_lg_config.llx1,
4656 detmon_lg_config.lly1,
4657 detmon_lg_config.urx1,
4658 detmon_lg_config.ury1},
4659 (
struct rect){ detmon_lg_config.llx2,
4660 detmon_lg_config.lly2,
4661 detmon_lg_config.urx2,
4662 detmon_lg_config.ury2},
4663 (
struct rect){ detmon_lg_config.llx3,
4664 detmon_lg_config.lly3,
4665 detmon_lg_config.urx3,
4666 detmon_lg_config.ury3},
4667 (
struct rect){ detmon_lg_config.llx4,
4668 detmon_lg_config.lly4,
4669 detmon_lg_config.urx4,
4670 detmon_lg_config.ury4},
4671 (
struct rect){ detmon_lg_config.llx5,
4672 detmon_lg_config.lly5,
4673 detmon_lg_config.urx5,
4674 detmon_lg_config.ury5},
4677 for (
size_t i = 0; i < 5; i++) {
4678 cpl_image * dif_avg;
4679 const cpl_image * off2;
4682 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
4683 off2 = cpl_imagelist_get_const(offs, 0);
4685 off2 = cpl_imagelist_get_const(offs, 1);
4687 dif_avg = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
4688 cpl_imagelist_get_const(offs, 0),
4689 cpl_imagelist_get_const(ons, 1),
4696 median = cpl_image_get_median(dif_avg);
4697 cpl_image_delete(dif_avg);
4700 sprintf(kname,
"%s%d", DETMON_QC_CONTAM, i + 1);
4702 if(cpl_propertylist_has(qclist,kname)){
4703 skip_if(cpl_propertylist_update_double(qclist,kname,median));
4705 skip_if(cpl_propertylist_append_double(qclist,kname,median));
4706 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
4712 return cpl_error_get_code();
4771 detmon_lg_dfs_set_groups(cpl_frameset *
set,
4772 const char *tag_on,
const char *tag_off)
4774 cpl_frame *cur_frame;
4784 nframes = cpl_frameset_get_size(
set);
4787 for(i = 0; i < nframes; i++) {
4788 cur_frame = cpl_frameset_get_position(
set, i);
4789 tag = cpl_frame_get_tag(cur_frame);
4792 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
4793 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
4813 static cpl_error_code
4814 detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist ** coeffs_ptr,
4815 cpl_image **bpms_ptr)
4817 cpl_image* dummy_bpm=NULL;
4818 cpl_image * dummy_coeff=NULL;
4819 cpl_imagelist * dummy_coeffs=NULL;
4831 dummy_bpm = cpl_image_new(detmon_lg_config.nx,
4832 detmon_lg_config.ny,
4834 dummy_coeffs = cpl_imagelist_new();
4836 db_p = cpl_image_get_data_int(dummy_bpm);
4837 rb_p = cpl_image_get_data_int(*bpms_ptr);;
4838 dcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
4839 rcs_p = cpl_malloc(
sizeof(
float *) * (detmon_lg_config.order + 1));
4840 dlength = detmon_lg_config.nx;
4841 rlength = detmon_lg_config.urx - detmon_lg_config.llx + 1;
4842 for (i = 0; i <= detmon_lg_config.order; i++)
4844 dummy_coeff = cpl_image_new(detmon_lg_config.nx,
4845 detmon_lg_config.ny,
4848 cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
4849 dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
4850 rcs_p[i] = cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
4853 for (i = detmon_lg_config.lly - 1; i < detmon_lg_config.ury; i++)
4855 for (j = detmon_lg_config.llx - 1; j < detmon_lg_config.urx; j++)
4857 shift_idx=(i - detmon_lg_config.lly + 1) * rlength +
4858 j - detmon_lg_config.llx + 1;
4859 *(db_p + i * dlength + j) = *(rb_p + shift_idx);
4860 for (k = 0; k <= detmon_lg_config.order; k++)
4862 *(dcs_p[k] + i * dlength + j) =
4863 *(rcs_p[k] + (i - detmon_lg_config.lly + 1) * rlength +
4864 j - detmon_lg_config.llx + 1);
4868 cpl_imagelist_delete(*coeffs_ptr);
4869 cpl_image_delete(*bpms_ptr);
4870 *coeffs_ptr = dummy_coeffs;
4871 *bpms_ptr = dummy_bpm;
4875 return cpl_error_get_code();
4928 static cpl_error_code
4929 detmon_lg_reduce_all(
const cpl_table * linear_table,
4930 cpl_propertylist * gaint_qclist,
4931 cpl_propertylist * lint_qclist,
4932 cpl_propertylist * linc_qclist,
4933 cpl_propertylist * bpm_qclist,
4934 cpl_imagelist ** coeffs_ptr,
4935 cpl_image ** bpms_ptr,
4936 const cpl_imagelist * linearity_inputs,
4937 const cpl_table * gain_table,
4938 int which_ext, cpl_boolean opt_nir)
4942 const int nsets = cpl_table_get_nrow(linear_table);
4944 cpl_polynomial *poly_linfit = NULL;
4945 cpl_image *fiterror = NULL;
4946 char * name_o1 = NULL;
4947 char * name_o2 = NULL;
4948 double * pcoeffs = NULL;
4949 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
4952 cpl_vector *x =NULL;
4953 const cpl_vector *y =NULL;
4956 const cpl_image * first = NULL;
4964 cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
4965 cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
4966 cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
4967 cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
4969 pcoeffs = cpl_malloc(
sizeof(
double)*(detmon_lg_config.order + 1));
4971 skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
4972 detmon_lg_config.method));
4973 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
4974 DETMON_QC_METHOD_C));
4977 if (!strcmp(detmon_lg_config.method,
"PTC")) {
4979 if (detmon_lg_config.exts >= 0) {
4980 cpl_msg_info(cpl_func,
4981 "Polynomial fitting for the GAIN (constant term method)");
4983 cpl_msg_info(cpl_func,
4984 "Polynomial fitting for the GAIN (constant term method)"
4985 " for extension nb %d", which_ext);
4987 skip_if(detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, nsets));
4989 skip_if(detmon_lg_qc_med(gain_table, gaint_qclist, nsets));
4994 if(detmon_lg_config.lamp_ok) {
4995 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
4996 detmon_lg_config.cr));
4997 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
4998 DETMON_QC_LAMP_FLUX_C));
5002 if(detmon_lg_config.autocorr == TRUE) {
5003 autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
5004 skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
5006 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
5007 DETMON_QC_AUTOCORR_C));
5009 if (detmon_lg_config.exts >= 0) {
5010 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix");
5012 cpl_msg_info(cpl_func,
"Polynomial fitting pix-to-pix"
5013 " for extension nb %d", which_ext);
5016 if(!detmon_lg_config.pix2pix) {
5019 y = cpl_vector_wrap(nsets,
5020 (
double *)cpl_table_get_data_double_const(linear_table,
5023 if (opt_nir == NIR) {
5024 x = cpl_vector_wrap(nsets,
5025 (
double *)cpl_table_get_data_double_const(linear_table,
5028 x = cpl_vector_wrap(nsets,
5029 (
double *)cpl_table_get_data_double_const(linear_table,
5033 if(x == NULL || y == NULL) {
5034 cpl_vector_unwrap((cpl_vector *)x);
5035 cpl_vector_unwrap((cpl_vector *)y);
5045 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
5046 poly_linfit = irplib_polynomial_fit_1d_create(x, y,
5047 detmon_lg_config.order,
5050 if(detmon_lg_config.order == cpl_vector_get_size(x) - 1) {
5051 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5055 if(poly_linfit == NULL) {
5056 cpl_vector_unwrap((cpl_vector *)x);
5057 cpl_vector_unwrap((cpl_vector *)y);
5063 min_val=cpl_vector_get_min(y);
5064 max_val=cpl_vector_get_max(y);
5066 cpl_vector_unwrap((cpl_vector *)x);
5067 cpl_vector_unwrap((cpl_vector *)y);
5069 for(deg = 0; deg <= detmon_lg_config.order; deg++) {
5070 const double coeff =
5071 cpl_polynomial_get_coeff(poly_linfit, °);
5073 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
5074 assert(name_o != NULL);
5075 skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
5076 skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
5077 DETMON_QC_LIN_COEF_C));
5080 pcoeffs[deg] = coeff;
5082 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
5083 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
5084 DETMON_QC_ERRFIT_MSE_C));
5089 y = cpl_vector_wrap(nsets,
5090 (
double *)cpl_table_get_data_double_const(linear_table,
5095 x = cpl_vector_wrap(nsets,
5096 (
double *)cpl_table_get_data_double_const(linear_table,
5099 x = cpl_vector_wrap(nsets,
5100 (
double *)cpl_table_get_data_double_const(linear_table,
5105 first = cpl_imagelist_get_const(linearity_inputs, 0);
5106 sizex = cpl_image_get_size_x(first);
5107 sizey = cpl_image_get_size_y(first);
5108 vsize = cpl_vector_get_size(x);
5109 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
5111 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,
5112 detmon_lg_config.order, FALSE,
5113 CPL_TYPE_FLOAT, fiterror);
5114 min_val=cpl_vector_get_min(y);
5115 max_val=cpl_vector_get_max(y);
5116 cpl_vector_unwrap((cpl_vector*)x);
5117 cpl_vector_unwrap((cpl_vector*)y);
5119 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
5120 "Failed polynomial fit");
5123 for(deg = 0; deg <= detmon_lg_config.order; deg++)
5125 cpl_image *image = cpl_imagelist_get(*coeffs_ptr, deg);
5126 const double coeff = cpl_image_get_median(image);
5127 pcoeffs[deg] = coeff;
5128 name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", (
int)deg);
5129 name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", (
int)deg);
5130 assert(name_o1 != NULL);
5131 assert(name_o2 != NULL);
5132 skip_if(cpl_propertylist_append_double(linc_qclist, name_o1, coeff));
5133 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o1,
5134 DETMON_QC_LIN_COEF_C));
5137 skip_if(cpl_propertylist_append_double(linc_qclist, name_o2,
5138 cpl_image_get_stdev(image)));
5139 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o2,
5140 DETMON_QC_LIN_COEF_ERR_C));
5146 if(detmon_lg_config.order == vsize - 1)
5148 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
5149 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5151 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5152 DETMON_QC_ERRFIT_C));
5155 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5156 cpl_image_get_median(fiterror)));
5157 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5158 DETMON_QC_ERRFIT_C));
5162 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
5164 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
5165 DETMON_QC_COUNTS_MIN_C));
5166 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
5168 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
5169 DETMON_QC_COUNTS_MAX_C));
5170 skip_if(detmon_lg_lineff(pcoeffs,lint_qclist,detmon_lg_config.ref_level,
5171 detmon_lg_config.order));
5173 if (detmon_lg_config.exts >= 0)
5175 cpl_msg_info(cpl_func,
"Bad pixel detection");
5178 cpl_msg_info(cpl_func,
"Bad pixel detection"
5179 " for extension nb %d", which_ext);
5181 if(detmon_lg_config.pix2pix)
5184 *bpms_ptr = detmon_bpixs(*coeffs_ptr, detmon_lg_config.bpmbin,
5185 detmon_lg_config.kappa, &nbpixs);
5195 skip_if(*bpms_ptr == NULL);
5200 skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
5201 skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
5202 DETMON_QC_NUM_BPM_C));
5203 if(detmon_lg_config.lamp_stability != 0.0)
5205 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
5206 detmon_lg_config.lamp_stability));
5207 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
5208 DETMON_QC_LAMP_STAB_C));
5211 if (!detmon_lg_config.wholechip && detmon_lg_config.pix2pix)
5213 detmon_lg_fits_coeffs_and_bpm2chip(coeffs_ptr,bpms_ptr);
5220 cpl_image_delete(fiterror);
5221 cpl_polynomial_delete(poly_linfit);
5225 return cpl_error_get_code();
5237 static cpl_error_code
5238 detmon_lg_lineff(
double * pcoeffs,
5239 cpl_propertylist * qclist,
5245 double residual, slope;
5248 cpl_polynomial * poly = cpl_polynomial_new(1);
5262 pcoeffs[0] -= ref_level;
5264 for (i = 2; i <= order; i++)
5267 for(j = 0; j < i; j++)
5269 pcoeffs[i] /= pcoeffs[1];
5275 for (deg = 0; deg <= order; deg++) {
5277 skip_if(cpl_polynomial_set_coeff(poly, °, pcoeffs[deg]));
5286 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
5288 if (slope <= 0.0 && residual >= 0.0) {
5289 cpl_msg_warning(cpl_func,
"Reference level (--ref_level) outside"
5290 " linearity range of the detector. Cannot compute"
5291 " linearity efficiency (QC.LINEFF).");
5296 cpl_error_code err = cpl_polynomial_solve_1d(poly, 0.0, &root, 1);
5301 if (err == CPL_ERROR_NONE)
5304 lineff = (root - ref_level) / ref_level;
5309 cpl_msg_warning(cpl_func,
5310 "Cannot compute linearity efficiency (QC.LINEFF)"
5311 "for the current combination "
5312 " of (--ref-level equal %d) and (--order equal %d) parameters. Try "
5313 "to decrease (--ref-level) value.", ref_level, order);
5316 cpl_msg_warning(cpl_func,
"DETMON_QC_LIN_EFF=%f",lineff );
5317 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
5319 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
5320 DETMON_QC_LIN_EFF_C));
5322 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
5324 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
5325 DETMON_QC_LIN_EFF_FLUX_C));
5329 cpl_polynomial_delete(poly);
5331 return cpl_error_get_code();
5342 static cpl_error_code
5343 detmon_lg_qc_ptc(
const cpl_table * gain_table,
5344 cpl_propertylist * qclist,
unsigned mode,
int rows_in_gain)
5347 cpl_polynomial *poly_fit = NULL;
5348 cpl_polynomial *poly_fit2 = NULL;
5350 const int nsets = rows_in_gain;
5352 cpl_vector *x = NULL;
5353 cpl_vector *y = NULL;
5355 cpl_errorstate prestate;
5357 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
5358 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
5360 x = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5362 y = cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5364 skip_if(x == NULL || y == NULL);
5365 if (0 == detmon_lg_check_before_gain(x, y))
5369 cpl_vector_unwrap(x);
5373 cpl_vector_unwrap(y);
5375 return CPL_ERROR_NONE;
5378 poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
5379 skip_if(poly_fit == NULL);
5383 prestate = cpl_errorstate_get();
5384 coef = cpl_polynomial_get_coeff(poly_fit, &i);
5385 skip_if (!cpl_errorstate_is_equal(prestate) || coef==0);
5386 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
5387 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5388 DETMON_QC_CONAD_C));
5391 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
5393 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
5409 if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
5410 const cpl_vector *x2 =
5411 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT_CORR"));
5412 const cpl_vector *y2 =
5413 cpl_vector_wrap(nsets, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5415 if(x2 == NULL || y2 == NULL) {
5416 cpl_vector_unwrap((cpl_vector *)x2);
5417 cpl_vector_unwrap((cpl_vector *)y2);
5428 poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
5429 if(poly_fit2 == NULL) {
5430 cpl_vector_unwrap((cpl_vector *)x2);
5431 cpl_vector_unwrap((cpl_vector *)y2);
5433 cpl_msg_error(cpl_func,
"Error during polynomial fit, err[%s]", cpl_error_get_where());
5437 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5438 cpl_vector_unwrap((cpl_vector *)x2);
5439 cpl_vector_unwrap((cpl_vector *)y2);
5440 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5443 prestate = cpl_errorstate_get();
5444 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
5445 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5446 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
5448 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
5450 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
5451 DETMON_QC_CONAD_CORR_C));
5453 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
5455 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
5456 DETMON_QC_GAIN_CORR_C));
5462 cpl_vector_unwrap(x);
5463 cpl_vector_unwrap(y);
5464 cpl_polynomial_delete(poly_fit);
5465 cpl_polynomial_delete(poly_fit2);
5467 return cpl_error_get_code();
5476 static int detmon_lg_check_before_gain(
const cpl_vector* x,
const cpl_vector* y)
5478 const double TOLERANCE = 1e-37;
5479 double xmin = cpl_vector_get_min(x);
5480 double xmax = cpl_vector_get_max(x);
5481 double ymin = cpl_vector_get_min(y);
5482 double ymax = cpl_vector_get_max(y);
5483 double ystdev = cpl_vector_get_stdev(y);
5484 double xstdev = cpl_vector_get_stdev(x);
5486 if (fabs(xmax-xmin) < TOLERANCE &&
5487 fabs(ymax - ymin) < TOLERANCE &&
5488 xstdev < TOLERANCE &&
5491 cpl_msg_warning(cpl_func,
"An empty frame has been detected, linearity, coeffs, gain, FPN values will not be computed.");
5506 static cpl_error_code
5507 detmon_lg_qc_med(
const cpl_table * gain_table,
5508 cpl_propertylist * qclist,
int rows_in_gain)
5512 cpl_vector *x = NULL;
5513 cpl_vector *y = NULL;
5514 int check_result = 0;
5516 if (rows_in_gain) {};
5518 x = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"X_FIT"));
5519 y = cpl_vector_wrap(rows_in_gain, (
double *)cpl_table_get_data_double_const(gain_table,
"Y_FIT"));
5520 check_result = detmon_lg_check_before_gain(x, y);
5523 cpl_vector_unwrap(x);
5527 cpl_vector_unwrap(y);
5529 if (0 == check_result)
5531 return CPL_ERROR_NONE;
5534 gain=cpl_table_get_column_median(gain_table,
"GAIN");
5536 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
5538 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
5541 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
5542 cpl_table_get_column_stdev
5543 (gain_table,
"GAIN")));
5544 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
5545 DETMON_QC_GAIN_MSE_C));
5547 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
5548 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5549 DETMON_QC_CONAD_C));
5552 gain=cpl_table_get_column_median(gain_table,
"GAIN_CORR");
5554 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
5556 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
5557 DETMON_QC_GAIN_CORR_C));
5560 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
5561 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
5562 DETMON_QC_CONAD_CORR_C));
5567 return cpl_error_get_code();
5581 static cpl_error_code
5582 detmon_lg_rescale(cpl_imagelist * to_rescale)
5585 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 0),
5586 detmon_lg_config.llx,
5587 detmon_lg_config.lly,
5588 detmon_lg_config.urx,
5589 detmon_lg_config.ury);
5591 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 1),
5592 detmon_lg_config.llx,
5593 detmon_lg_config.lly,
5594 detmon_lg_config.urx,
5595 detmon_lg_config.ury);
5599 if(fabs(med1 / med2 - 1) > 0.001) {
5601 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
5604 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
5610 return cpl_error_get_code();
5613 static cpl_error_code
5614 detmon_pair_extract_next(
const cpl_frameset *
set,
5618 cpl_frameset ** pair,
5622 double dit_next = -100;
5623 cpl_size* selection;
5624 int nsets_extracted = 0;
5625 cpl_ensure_code(
set != NULL, CPL_ERROR_NULL_INPUT);
5626 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
5627 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
5628 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
5630 nsets_extracted = cpl_frameset_get_size(
set);
5631 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
5632 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
5635 dit = dit_array[*next_element ];
5637 if (*next_element < nsets_extracted - 1)
5639 dit_next = dit_array[*next_element + 1 ];
5643 selection[iindex[*next_element] ] = 1;
5644 if (fabs(dit - dit_next) < tolerance)
5647 selection[iindex[*next_element + 1] ] = 1;
5652 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);
5656 cpl_frameset_delete(*pair);
5657 *pair = cpl_frameset_extract(
set, selection, 1);
5660 cpl_free(selection);
5661 return cpl_error_get_code();
5664 static cpl_error_code
5665 detmon_single_extract_next(
const cpl_frameset *
set,
5669 cpl_frameset ** pair)
5671 cpl_size* selection;
5672 int nsets_extracted = 0;
5673 cpl_ensure_code(
set != NULL, CPL_ERROR_NULL_INPUT);
5674 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
5675 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
5676 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
5678 nsets_extracted = cpl_frameset_get_size(
set);
5679 selection = cpl_malloc(
sizeof(cpl_size) * nsets_extracted);
5680 memset(&selection[0], 0,
sizeof(cpl_size) * nsets_extracted);
5683 selection[iindex[*next_element] ] = 1;
5686 cpl_frameset_delete(*pair);
5687 *pair = cpl_frameset_extract(
set, selection, 1);
5689 cpl_free(selection);
5690 return cpl_error_get_code();
5786 detmon_gain(
const cpl_imagelist * imlist_on,
5787 const cpl_imagelist * imlist_off,
5788 const cpl_vector * exptimes,
5789 const cpl_vector * ndit,
5799 cpl_propertylist * qclist,
5801 cpl_imagelist ** diff_imlist,
5802 cpl_imagelist ** autocorr_imlist)
5804 cpl_table * gain_table = NULL;
5805 cpl_imagelist * difflist = NULL;
5806 cpl_imagelist * autocorrlist = NULL;
5807 cpl_imagelist * c_onlist = NULL;
5808 cpl_imagelist * c_offlist = NULL;
5809 cpl_vector * diffdits = NULL;
5810 cpl_vector * diffndits = NULL;
5811 int rows_in_gain = 0;
5812 int ndiffdits, ndits;
5814 cpl_boolean opt_nir = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
5815 const char * method = mode & IRPLIB_GAIN_PTC ?
"PTC" :
"MED";
5817 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
5818 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
5819 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
5820 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
5823 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
5824 skip_if(detmon_gain_table_create(gain_table, opt_nir));
5828 skip_if(detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,
5830 ndiffdits = cpl_vector_get_size(diffdits);
5832 ndits = cpl_vector_get_size(exptimes);
5835 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
5836 difflist = cpl_imagelist_new();
5837 autocorrlist = cpl_imagelist_new();
5840 if (mode & IRPLIB_GAIN_COLLAPSE) {
5841 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
5842 c_offlist = cpl_imagelist_duplicate(imlist_off);
5843 skip_if(detmon_lg_rescale(c_offlist));
5845 c_offlist = (cpl_imagelist *) imlist_off;
5850 for (i = 0; i < ndiffdits; i++) {
5857 c_dit=cpl_vector_get(diffdits, i);
5860 c_ndit=(int)cpl_vector_get(diffndits, i);
5863 c_onlist = cpl_imagelist_new();
5866 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5867 c_offlist = cpl_imagelist_new();
5872 for(j = 0; j < ndits; j++) {
5873 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
5883 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
5884 const cpl_image * im =
5885 cpl_imagelist_get_const(imlist_on, j);
5886 im_on = cpl_image_duplicate(im);
5888 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
5890 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
5897 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5899 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
5900 const cpl_image * im =
5901 cpl_imagelist_get_const(imlist_off, j);
5902 im_off = cpl_image_duplicate(im);
5905 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
5907 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
5914 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
5915 skip_if (c_nons != c_noffs);
5918 skip_if (c_nons == 0 || c_nons % 2 != 0);
5921 if(mode & IRPLIB_GAIN_WITH_RESCALE) {
5922 skip_if(detmon_lg_rescale(c_onlist));
5923 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
5924 skip_if(detmon_lg_rescale(c_offlist));
5930 int rows_affected = 1;
5931 skip_if(detmon_gain_table_fill_row(gain_table,
5935 c_offlist, kappa, nclip,
5937 xshift, yshift,1E10, i,
5938 mode, &rows_affected));
5943 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
5944 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
5945 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
5946 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5947 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
5948 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
5951 cpl_imagelist_unset(c_onlist, 0);
5953 cpl_imagelist_unset(c_onlist, 0);
5955 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5956 cpl_imagelist_unset(c_offlist, 0);
5958 cpl_imagelist_unset(c_offlist, 0);
5966 cpl_imagelist_delete(c_onlist);
5967 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
5968 cpl_imagelist_delete(c_offlist);
5972 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
5973 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
5974 DETMON_QC_METHOD_C));
5977 if (mode & IRPLIB_GAIN_PTC) {
5978 skip_if(detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
5980 skip_if(detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
5983 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
5984 double autocorr = cpl_table_get_column_median(gain_table,
"AUTOCORR");
5985 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
5987 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
5988 DETMON_QC_AUTOCORR_C));
5991 if (diff_imlist != NULL) *diff_imlist = difflist;
5992 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
5996 cpl_vector_delete(diffdits);
5997 cpl_vector_delete(diffndits);
6002 static cpl_error_code
6003 detmon_gain_table_create(cpl_table * gain_table,
6004 const cpl_boolean opt_nir)
6006 if (opt_nir == NIR) {
6007 skip_if(cpl_table_new_column(gain_table,
"DIT", CPL_TYPE_DOUBLE));
6008 skip_if(cpl_table_new_column(gain_table,
"NDIT", CPL_TYPE_INT));
6010 skip_if(cpl_table_new_column(gain_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6012 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON1", CPL_TYPE_DOUBLE));
6013 skip_if(cpl_table_new_column(gain_table,
"MEAN_ON2", CPL_TYPE_DOUBLE));
6014 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF1", CPL_TYPE_DOUBLE));
6015 skip_if(cpl_table_new_column(gain_table,
"MEAN_OFF2", CPL_TYPE_DOUBLE));
6016 skip_if(cpl_table_new_column(gain_table,
"SIG_ON_DIF", CPL_TYPE_DOUBLE));
6017 skip_if(cpl_table_new_column(gain_table,
"SIG_OFF_DIF", CPL_TYPE_DOUBLE));
6018 skip_if(cpl_table_new_column(gain_table,
"GAIN", CPL_TYPE_DOUBLE));
6019 skip_if(cpl_table_new_column(gain_table,
"AUTOCORR", CPL_TYPE_DOUBLE));
6020 skip_if(cpl_table_new_column(gain_table,
"GAIN_CORR", CPL_TYPE_DOUBLE));
6021 skip_if(cpl_table_new_column(gain_table,
"ADU", CPL_TYPE_DOUBLE));
6022 skip_if(cpl_table_new_column(gain_table,
"X_FIT", CPL_TYPE_DOUBLE));
6023 skip_if(cpl_table_new_column(gain_table,
"X_FIT_CORR", CPL_TYPE_DOUBLE));
6024 skip_if(cpl_table_new_column(gain_table,
"Y_FIT", CPL_TYPE_DOUBLE));
6025 skip_if(cpl_table_new_column(gain_table,
"Y_FIT_CORR", CPL_TYPE_DOUBLE));
6026 skip_if(cpl_table_new_column(gain_table,
"FLAG", CPL_TYPE_INT));
6030 return cpl_error_get_code();
6033 static cpl_error_code
6034 detmon_lin_table_create(cpl_table * lin_table,
6035 const cpl_boolean opt_nir)
6037 if (opt_nir == NIR) {
6038 skip_if(cpl_table_new_column(lin_table,
"DIT", CPL_TYPE_DOUBLE));
6040 skip_if(cpl_table_new_column(lin_table,
"EXPTIME", CPL_TYPE_DOUBLE));
6042 skip_if(cpl_table_new_column(lin_table,
"MED", CPL_TYPE_DOUBLE));
6043 skip_if(cpl_table_new_column(lin_table,
"MEAN", CPL_TYPE_DOUBLE));
6044 skip_if(cpl_table_new_column(lin_table,
"MED_DIT", CPL_TYPE_DOUBLE));
6045 skip_if(cpl_table_new_column(lin_table,
"MEAN_DIT", CPL_TYPE_DOUBLE));
6046 skip_if(cpl_table_new_column(lin_table,
"ADL", CPL_TYPE_DOUBLE));
6049 return cpl_error_get_code();
6053 detmon_lg_find_dits(
const cpl_vector * exptimes,
6056 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6062 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
6066 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
6068 for (j = 0; j < ndits; j++) {
6069 if (fabs(cpl_vector_get(exptimes, i) -
6070 cpl_vector_get(dits, j)) > tolerance)
6073 if(ndiffs == ndits) {
6074 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
6079 cpl_vector_set_size(dits, ndits);
6087 static cpl_error_code
6088 detmon_lg_find_dits_ndits(
const cpl_vector * exptimes,
6089 const cpl_vector * vec_ndits,
6091 cpl_vector** diff_dits,
6092 cpl_vector** diff_ndits)
6100 * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6101 * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
6104 cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
6105 cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
6108 size=cpl_vector_get_size(exptimes);
6110 for(i = 1; i < size; i++) {
6112 for (j = 0; j < ndits; j++) {
6113 if (fabs(cpl_vector_get(exptimes, i) -
6114 cpl_vector_get(*diff_dits,j)) > tolerance)
6117 if(ndiffs == ndits) {
6118 cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
6119 cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
6124 cpl_vector_set_size(*diff_dits, ndits);
6125 cpl_vector_set_size(*diff_ndits, ndits);
6128 return cpl_error_get_code();
6216 detmon_lin(
const cpl_imagelist * imlist_on,
6217 const cpl_imagelist * imlist_off,
6218 const cpl_vector * exptimes,
6228 cpl_propertylist * qclist,
6230 cpl_imagelist ** coeffs_cube,
6233 cpl_table * lin_table = NULL;
6234 cpl_imagelist * c_onlist = NULL;
6235 cpl_imagelist * c_offlist = NULL;
6236 cpl_vector * diffdits = NULL;
6237 cpl_imagelist * lin_inputs = NULL;
6238 cpl_polynomial * poly_linfit = NULL;
6239 cpl_image * fiterror = NULL;
6240 cpl_vector * vcoeffs = NULL;
6241 double * pcoeffs = NULL;
6242 int ndiffdits, ndits;
6244 cpl_boolean opt_nir = mode & IRPLIB_LIN_OPT ? OPT : NIR;
6245 const cpl_vector *x = NULL;
6246 const cpl_vector *y = NULL;
6248 const cpl_image * first = NULL;
6256 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6257 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6258 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6259 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6260 cpl_ensure(order > 0 , CPL_ERROR_ILLEGAL_INPUT, NULL);
6262 vcoeffs = cpl_vector_new(order + 1);
6263 pcoeffs = cpl_vector_get_data(vcoeffs);
6266 if (mode & IRPLIB_LIN_PIX2PIX) {
6267 cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
6268 cpl_ensure(bpm != NULL, CPL_ERROR_NULL_INPUT, NULL);
6269 lin_inputs = cpl_imagelist_new();
6273 lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6274 skip_if(detmon_lin_table_create(lin_table, opt_nir));
6278 diffdits = detmon_lg_find_dits(exptimes, tolerance);
6279 ndiffdits = cpl_vector_get_size(diffdits);
6281 ndits = cpl_vector_get_size(exptimes);
6311 if (mode & IRPLIB_LIN_COLLAPSE) {
6316 cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
6317 skip_if(collapse == NULL);
6319 c_offlist = cpl_imagelist_new();
6320 skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
6324 for (i = 0; i < ndiffdits; i++) {
6328 double c_dit = cpl_vector_get(diffdits, i);
6330 c_onlist = cpl_imagelist_new();
6333 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6334 c_offlist = cpl_imagelist_new();
6338 for(j = 0; j < ndits; j++) {
6339 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6349 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6350 const cpl_image * im =
6351 cpl_imagelist_get_const(imlist_on, j);
6352 im_on = cpl_image_duplicate(im);
6354 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6356 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6363 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6365 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6366 const cpl_image * im =
6367 cpl_imagelist_get_const(imlist_off, j);
6368 im_off = cpl_image_duplicate(im);
6371 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6373 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6380 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6381 skip_if (c_nons != c_noffs);
6384 skip_if (c_nons == 0 || c_nons % 2 != 0);
6387 if(mode & IRPLIB_LIN_WITH_RESCALE) {
6388 skip_if(detmon_lg_rescale(c_onlist));
6389 if (mode & IRPLIB_LIN_NO_COLLAPSE)
6390 skip_if(detmon_lg_rescale(c_offlist));
6397 skip_if(detmon_lin_table_fill_row(lin_table, c_dit,
6399 c_onlist, c_offlist,
6403 if (mode & IRPLIB_LIN_WITH_RESCALE) {
6404 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6405 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6406 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6407 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6408 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6411 cpl_imagelist_unset(c_onlist, 0);
6413 cpl_imagelist_unset(c_onlist, 0);
6415 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6416 cpl_imagelist_unset(c_offlist, 0);
6418 cpl_imagelist_unset(c_offlist, 0);
6426 cpl_imagelist_delete(c_onlist);
6427 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
6428 cpl_imagelist_delete(c_offlist);
6432 skip_if(detmon_add_adl_column(lin_table, opt_nir));
6434 if(!(mode & IRPLIB_LIN_PIX2PIX)) {
6437 y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6438 (
double *)cpl_table_get_data_double_const(lin_table,
6440 if (opt_nir == NIR) {
6441 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6442 (
double *)cpl_table_get_data_double_const(lin_table,
"DIT"));
6444 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6445 (
double *)cpl_table_get_data_double_const(lin_table,
"EXPTIME"));
6447 if(x == NULL || y == NULL) {
6448 cpl_vector_unwrap((cpl_vector *)x);
6449 cpl_vector_unwrap((cpl_vector *)y);
6459 cpl_msg_info(cpl_func,
"Polynomial fitting for the LINEARITY");
6460 poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
6462 if(order == cpl_vector_get_size(x) - 1) {
6463 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
6467 if(poly_linfit == NULL) {
6468 cpl_vector_unwrap((cpl_vector *)x);
6469 cpl_vector_unwrap((cpl_vector *)y);
6474 cpl_vector_unwrap((cpl_vector *)x);
6475 cpl_vector_unwrap((cpl_vector *)y);
6477 for(deg = 0; deg <= order; deg++) {
6478 const double coeff =
6479 cpl_polynomial_get_coeff(poly_linfit, °);
6481 cpl_sprintf(
"ESO QC LIN COEF%" CPL_SIZE_FORMAT
"", deg);
6482 assert(name_o != NULL);
6483 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
6484 skip_if(cpl_propertylist_set_comment(qclist,name_o,
6485 DETMON_QC_LIN_COEF_C));
6487 pcoeffs[deg] = coeff;
6489 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
6490 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
6491 DETMON_QC_ERRFIT_MSE_C));
6495 if (opt_nir == NIR) {
6496 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6497 (
double *)cpl_table_get_data_double_const(lin_table,
6500 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6501 (
double *)cpl_table_get_data_double_const(lin_table,
6506 first = cpl_imagelist_get_const(lin_inputs, 0);
6507 sizex = cpl_image_get_size_x(first);
6508 sizey = cpl_image_get_size_y(first);
6510 vsize = cpl_vector_get_size(x);
6512 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
6515 cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
6516 order, FALSE, CPL_TYPE_FLOAT,
6519 cpl_vector_unwrap((cpl_vector*)x);
6520 irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
6521 "Failed polynomial fit");
6523 for(i = 0; i <= order; i++) {
6524 cpl_image *image = cpl_imagelist_get(*coeffs_cube, i);
6525 const double coeff = cpl_image_get_median(image);
6526 char * name_o1 = cpl_sprintf(
"ESO QC LIN COEF%d", i);
6527 char * name_o2 = cpl_sprintf(
"ESO QC LIN COEF%d ERR", i);
6529 assert(name_o1 != NULL);
6530 assert(name_o2 != NULL);
6531 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
6532 skip_if(cpl_propertylist_set_comment(qclist,name_o1,
6533 DETMON_QC_LIN_COEF_C));
6536 skip_if(cpl_propertylist_append_double(qclist, name_o2,
6537 cpl_image_get_stdev(image)));
6538 skip_if(cpl_propertylist_set_comment(qclist,name_o2,
6539 DETMON_QC_LIN_COEF_ERR_C));
6544 if(order == vsize - 1) {
6545 cpl_msg_warning(cpl_func,
"The fitting is not over-determined.");
6546 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
6548 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
6549 DETMON_QC_ERRFIT_C));
6553 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
6554 cpl_image_get_median(fiterror)));
6555 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
6556 DETMON_QC_ERRFIT_C));
6561 skip_if(detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
6563 if(mode & IRPLIB_LIN_PIX2PIX) {
6565 *bpm = detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
6566 skip_if(*bpm == NULL);
6567 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
6569 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
6570 DETMON_QC_NUM_BPM_C));
6575 cpl_vector_delete(diffdits);
6576 cpl_polynomial_delete(poly_linfit);
6577 cpl_imagelist_delete(lin_inputs);
6578 cpl_vector_delete(vcoeffs);
6579 cpl_image_delete(fiterror);
6610 static cpl_error_code
6611 detmon_lin_table_fill_row(cpl_table * lin_table,
double c_dit,
6612 cpl_imagelist * linearity_inputs,
6613 const cpl_imagelist * ons,
6614 const cpl_imagelist * offs,
6623 cpl_image * extracted=NULL;
6625 cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
6626 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
6627 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
6629 if (mode & IRPLIB_LIN_PIX2PIX) {
6630 cpl_msg_debug(cpl_func,
"checking linearity inputs");
6631 cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
6635 if (mode & IRPLIB_LIN_NIR) {
6636 cpl_table_set(lin_table,
"DIT", pos, c_dit);
6637 }
else if (mode & IRPLIB_LIN_OPT) {
6638 cpl_table_set(lin_table,
"EXPTIME", pos, c_dit);
6640 cpl_msg_error(cpl_func,
"Mandatory mode not given");
6644 const cpl_image * off2;
6645 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
6646 off2 = cpl_imagelist_get_const(offs, 0);
6648 off2 = cpl_imagelist_get_const(offs, 1);
6650 extracted = detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
6651 cpl_imagelist_get_const(offs, 0),
6652 cpl_imagelist_get_const(ons, 1),
6654 llx, lly, urx, ury);
6655 cpl_ensure_code(extracted != NULL, cpl_error_get_code());
6659 double median = cpl_image_get_median(extracted);
6660 double mean= cpl_image_get_mean(extracted);
6661 cpl_table_set(lin_table,
"MED", pos, median);
6662 cpl_table_set(lin_table,
"MEAN", pos, mean);
6664 cpl_table_set(lin_table,
"MED_DIT", pos, median / c_dit);
6665 cpl_table_set(lin_table,
"MEAN_DIT", pos, mean / c_dit);
6669 if(mode & IRPLIB_LIN_PIX2PIX) {
6670 cpl_error_code error = cpl_imagelist_set(linearity_inputs, extracted,
6672 cpl_ensure_code(!error, error);
6674 cpl_image_delete(extracted);
6677 return cpl_error_get_code();
6680 static double irplib_calculate_total_noise_smooth(
const cpl_image* pimage,
6681 int pattern_x,
int pattern_y)
6683 cpl_image * p_tmp_image = 0;
6684 cpl_image * psmooth_image = 0;
6686 cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
6688 p_tmp_image = cpl_image_duplicate(pimage);
6689 cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
6690 cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
6691 psmooth_image = cpl_image_divide_create(pimage,p_tmp_image);
6692 ret_noise = irplib_calculate_total_noise(psmooth_image);
6693 cpl_mask_delete(mask);
6694 cpl_image_delete(psmooth_image);
6695 cpl_image_delete(p_tmp_image);
6699 static double irplib_calculate_total_noise(
const cpl_image* pimage)
6701 double total_noise = -1;
6702 unsigned long max_bin_size = 1E5;
6703 const double hstart = cpl_image_get_min(pimage);
6704 const double hrange = cpl_image_get_max(pimage) - hstart;
6705 const unsigned long nbins = max_bin_size;
6706 cpl_error_code err = CPL_ERROR_NONE;
6708 irplib_hist * phist = 0;
6709 phist = irplib_hist_new();
6712 irplib_hist_init(phist, nbins, hstart, hrange);
6713 err = irplib_hist_fill(phist, pimage);
6714 if (err == CPL_ERROR_NONE)
6722 unsigned long n_bins = irplib_hist_get_nbins(phist);
6723 double start = irplib_hist_get_start(phist);
6724 double bin_size = irplib_hist_get_bin_size(phist);
6725 cpl_vector* pdata_vector = cpl_vector_new(n_bins);
6726 cpl_vector* ppos_vector = cpl_vector_new(n_bins);
6727 cpl_table* ptable = cpl_table_new(n_bins);
6728 cpl_table_new_column(ptable,
"bin", CPL_TYPE_DOUBLE);
6729 cpl_table_new_column(ptable,
"value", CPL_TYPE_DOUBLE);
6730 for(i = 0; i < n_bins; i++)
6732 unsigned int value = irplib_hist_get_value(phist, i);
6733 double dvalue = (double)(value);
6734 cpl_vector_set(pdata_vector, i, dvalue);
6735 cpl_vector_set(ppos_vector, i, start + i * bin_size);
6737 cpl_table_set(ptable,
"bin", i, start + i * bin_size);
6738 cpl_table_set(ptable,
"value", i, dvalue);
6740 err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
6741 if (err == CPL_ERROR_NONE)
6743 cpl_msg_info(cpl_func,
"FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
6747 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed Gaussian Fit, err msg [%s]", cpl_error_get_message());
6750 cpl_table_delete(ptable);
6751 cpl_vector_delete(ppos_vector);
6752 cpl_vector_delete(pdata_vector);
6756 cpl_msg_warning(cpl_func,
"FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
6759 irplib_hist_delete(phist);
6764 static double irplib_compute_err(
double gain,
double ron,
double FA)
6766 double int_gain = (gain * gain - 1) / 12;
6771 return sqrt(ron * ron + FA / gain + int_gain);
6774 static double irplib_fpn_lg(
const cpl_image* f1,
int* range,
double gain ,
6775 FPN_METHOD fpn_method,
int smooth_size,
double* mse)
6777 cpl_image* im_diff = 0;
6778 const cpl_image* im_f1 = f1;
6779 cpl_image* im_inrange1 = 0;
6788 cpl_msg_warning(cpl_func,
"gain[%f]<0", gain);
6789 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
6796 im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
6797 im_f1 = im_inrange1;
6799 FA = cpl_image_get_median(im_f1);
6806 cpl_msg_info(cpl_func,
"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
6807 s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
6810 cpl_msg_info(cpl_func,
"HISTOGRAM method is used for FPN");
6811 s_tot = irplib_calculate_total_noise(im_f1);
6816 cpl_msg_warning(cpl_func,
"fpn_method is not defined");
6825 cpl_msg_warning(cpl_func,
"Median flux on sum of flats<0");
6826 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
6831 if ((s_tot * s_tot - FA / gain) > 0)
6833 s_fpn = sqrt(s_tot * s_tot - FA / gain);
6834 sr_fpn = s_fpn / FA;
6835 *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
6839 cpl_msg_warning(cpl_func,
"s_tot * s_tot < FA / gain");
6840 cpl_msg_warning(cpl_func,
"We set dummy values for FPN");
6849 cpl_image_delete(im_diff);
6852 cpl_image_delete(im_inrange1);
6858 static cpl_imagelist * irplib_load_fset_wrp(
const cpl_frameset * pframeset,
6859 cpl_type type ,
int whichext)
6863 return detmon_load_frameset_window(pframeset, type, 0, whichext,
6864 detmon_lg_config.llx,
6865 detmon_lg_config.lly,
6866 detmon_lg_config.urx,
6867 detmon_lg_config.ury,
6868 detmon_lg_config.nx,
6869 detmon_lg_config.ny);
6872 static cpl_imagelist * irplib_load_fset_wrp_ext(
const cpl_frameset * pframeset,
6873 cpl_type type ,
int whichext)
6876 cpl_imagelist* offs = cpl_imagelist_new();
6877 detmon_lg_config.load_fset(pframeset, type, offs);
6882 static cpl_error_code irplib_table_create_column(cpl_table* ptable,
6883 cpl_propertylist* plist)
6885 if (ptable && plist)
6887 int size = cpl_propertylist_get_size(plist);
6889 for (i = 0; i < size; i++)
6891 cpl_property* pprop = cpl_propertylist_get(plist,i);
6894 const char* pname = cpl_property_get_name(pprop);
6897 cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
6898 if (cpl_error_get_code() != CPL_ERROR_NONE)
6900 cpl_msg_warning(cpl_func,
"cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
6907 return cpl_error_get_code();
6910 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
6911 cpl_propertylist* plist,
int row)
6913 cpl_error_code err = CPL_ERROR_NONE;
6914 if (ptable && plist)
6916 int size = cpl_propertylist_get_size(plist);
6918 for (i = 0; i < size; i++)
6920 cpl_property* pprop = cpl_propertylist_get(plist,i);
6923 const char* pname = cpl_property_get_name(pprop);
6924 double value = cpl_property_get_double(pprop);
6927 cpl_table_set_double(ptable, pname, row, value);
6928 if (cpl_error_get_code() != CPL_ERROR_NONE)
6930 cpl_msg_warning(cpl_func,
"cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
6941 cpl_error_code detmon_check_order(
const double *exptime,
int sz,
6942 double tolerance,
int order)
6959 }
while(fabs(exptime[i-1] - exptime[i]) < tolerance);
6960 }
while(i < sz - 1);
6962 if (!fabs(exptime[i-1] - exptime[i]) < tolerance) nsets++;
6965 cpl_error_set_message(cpl_func,CPL_ERROR_INCOMPATIBLE_INPUT,
6966 "Not enough frames for the polynomial"
6967 " fitting. nsets = %d <= %d order",
6970 return cpl_error_get_code();
6973 static cpl_error_code
6974 detmon_lg_dfs_save_imagelist(
6975 cpl_frameset * frameset,
6976 const cpl_parameterlist * parlist,
6977 const cpl_frameset *usedframes,
6978 const cpl_imagelist *coeffs,
6979 const char *recipe_name,
6980 const cpl_propertylist *mypro_coeffscube,
6981 const char * package,
6982 const char * name_o)
6984 return(cpl_dfs_save_imagelist
6985 (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
6986 recipe_name, mypro_coeffscube, NULL, package,
6990 static void detmon_lg_add_empty_image(cpl_imagelist* imlist,
int pos)
6992 const cpl_image* first = cpl_imagelist_get(imlist, 0);
6995 int x = cpl_image_get_size_x(first);
6996 int y = cpl_image_get_size_y(first);
6997 cpl_type type = cpl_image_get_type(first);
6998 cpl_image * blank = cpl_image_new(x, y, type);
6999 cpl_imagelist_set(imlist, blank, pos);
7005 detmon_lg_set_tag(cpl_frameset*
set,
const char** tag_on,
const char** tag_off)
7010 ntag_old=cpl_frameset_count_tags(
set,DETMON_LG_ON_RAW_OLD);
7011 ntag_new=cpl_frameset_count_tags(
set,DETMON_LG_ON_RAW_NEW);
7013 *tag_on=DETMON_LG_ON_RAW_OLD;
7014 *tag_off=DETMON_LG_OFF_RAW_OLD;
7015 }
else if (ntag_new) {
7016 *tag_on=DETMON_LG_ON_RAW_NEW;
7017 *tag_off=DETMON_LG_OFF_RAW_NEW;
7019 cpl_msg_error(cpl_func,
"Provide %s and %s (or %s and %s) input frames",
7020 DETMON_LG_ON_RAW_NEW,DETMON_LG_OFF_RAW_NEW,
7021 DETMON_LG_ON_RAW_OLD,DETMON_LG_OFF_RAW_OLD);
7025 return cpl_error_get_code();