45 #include "detmon_ronbias.h"
46 #include "detmon_darkron.h"
48 #include "irplib_ksigma_clip.h"
49 #include "irplib_hist.h"
50 #include "irplib_utils.h"
54 #define pdist(x1,y1,x2,y2) (((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)))
56 #define cpl_drand() ((double)rand()/(double)RAND_MAX)
95 const char * ron_method;
96 const char * dsnu_method;
100 } detmon_dark_config;
110 static cpl_bivector *
111 irplib_bivector_gen_rect_poisson(
const int *r,
116 detmon_dark_dfs_set_groups(cpl_frameset *,
120 detmon_dark_dsnu(cpl_frameset *,
127 static cpl_error_code
128 detmon_dark_save(
const cpl_parameterlist *,
142 const cpl_frameset *);
146 static cpl_error_code
147 detmon_retrieve_dark_params(
const char *,
149 const cpl_parameterlist *);
152 detmon_dark_qc(cpl_propertylist *,
174 detmon_darkron_fill_parlist_default(cpl_parameterlist * parlist,
175 const char *recipe_name,
176 const char *pipeline_name)
178 const cpl_error_code error =
179 detmon_ronbias_fill_parlist(parlist, recipe_name, pipeline_name,
203 cpl_ensure_code(!error, error);
205 return cpl_error_get_code();
221 detmon_compare_dits(
const cpl_frame * frame1,
const cpl_frame * frame2)
224 cpl_propertylist *plist1;
225 cpl_propertylist *plist2;
229 if(frame1 == NULL || frame2 == NULL)
233 if((plist1 = cpl_propertylist_load(cpl_frame_get_filename(frame1),
235 cpl_msg_error(cpl_func,
"getting header from reference frame");
238 if((plist2 = cpl_propertylist_load(cpl_frame_get_filename(frame2),
240 cpl_msg_error(cpl_func,
"getting header from reference frame");
241 cpl_propertylist_delete(plist1);
246 if(cpl_error_get_code()) {
247 cpl_propertylist_delete(plist1);
248 cpl_propertylist_delete(plist2);
254 dval1 = irplib_pfits_get_exptime(plist1);
255 dval2 = irplib_pfits_get_exptime(plist2);
256 if(cpl_error_get_code()) {
257 cpl_msg_error(cpl_func,
"cannot get exposure time");
258 cpl_propertylist_delete(plist1);
259 cpl_propertylist_delete(plist2);
262 if(fabs(dval1 - dval2) > 1e-3)
266 cpl_propertylist_delete(plist1);
267 cpl_propertylist_delete(plist2);
284 static cpl_bivector *
285 irplib_bivector_gen_rect_poisson(
const int *r,
const int np,
const int homog)
291 double cand_x, cand_y;
294 int xmin, xmax, ymin, ymax;
297 const int homogc = 0 < homog && homog < np ? homog : np;
302 cpl_ensure(r, CPL_ERROR_NULL_INPUT, NULL);
303 cpl_ensure(np > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
305 list = cpl_bivector_new(np);
306 cpl_ensure(list, CPL_ERROR_NULL_INPUT, NULL);
307 px = cpl_bivector_get_x_data(list);
308 py = cpl_bivector_get_y_data(list);
316 CPL_MATH_SQRT1_2 * ((xmax - xmin) * (ymax - ymin) / (double) (homogc + 1));
322 while(gnp < homogc) {
324 cand_x = cpl_drand() * (xmax - xmin) + xmin;
325 cand_y = cpl_drand() * (ymax - ymin) + ymin;
329 for(i = 0; i < gnp; i++) {
330 if(pdist(cand_x, cand_y, px[i], py[i]) < min_dist) {
349 cand_x = cpl_drand() * (xmax - xmin) + xmin;
350 cand_y = cpl_drand() * (ymax - ymin) + ymin;
354 for(i = 0; i < homogc; i++) {
357 px[start_ndx + i], py[start_ndx + i]) < min_dist) {
376 cand_x = cpl_drand() * (xmax - xmin) + xmin;
377 cand_y = cpl_drand() * (ymax - ymin) + ymin;
381 for(i = 0; i < homogc; i++) {
384 px[start_ndx + i], py[start_ndx + i]) < min_dist) {
423 detmon_dark(cpl_frameset * frameset,
424 const cpl_parameterlist * parlist,
426 const char * recipe_name,
427 const char * pipeline_name,
428 const char * procatg_master,
429 const char * procatg_dsnu,
430 const char * procatg_tbl,
431 const char * package,
432 int (*compare)(
const cpl_frame *,
436 cpl_size *selection = NULL;
438 cpl_error_code error;
440 if(detmon_dark_dfs_set_groups(frameset, tag)) {
441 cpl_msg_error(cpl_func,
"Cannot identify RAW and CALIB frames");
449 error = detmon_retrieve_dark_params(pipeline_name,
450 recipe_name, parlist);
451 cpl_ensure_code(!error, error);
457 cpl_msg_info(cpl_func,
"Identify the different settings");
458 selection = cpl_frameset_labelise(frameset, compare, &nsets);
459 if(selection == NULL)
460 cpl_msg_error(cpl_func,
"Cannot labelise input frames");
463 detmon_dark_config.nb_extensions = 1;
464 if(detmon_dark_config.exts < 0) {
465 const cpl_frame *cur_frame =
466 cpl_frameset_get_first_const(frameset);
468 detmon_dark_config.nb_extensions =
469 cpl_frame_get_nextensions(cur_frame);
473 for(i = 0; i < nsets; i++) {
474 cpl_size *select_dits = NULL;
475 cpl_frameset *cur_fset =
476 nsets == 1 ? cpl_frameset_duplicate(frameset) :
477 cpl_frameset_extract(frameset, selection, i);
481 cpl_table ** dsnu_table = NULL;
482 cpl_imagelist ** dsnu = NULL;
484 cpl_propertylist ** qclist =
485 (cpl_propertylist **)
486 cpl_malloc(detmon_dark_config.nb_extensions *
487 sizeof(cpl_propertylist *));
490 cpl_imagelist ** masters =
492 cpl_malloc(detmon_dark_config.nb_extensions *
493 sizeof(cpl_imagelist *));
496 if(detmon_dark_config.opt_nir == OPT) {
498 (cpl_table **) cpl_malloc(detmon_dark_config.nb_extensions *
499 sizeof(cpl_table *));
502 cpl_malloc(detmon_dark_config.nb_extensions *
503 sizeof(cpl_imagelist *));
506 select_dits = cpl_frameset_labelise(cur_fset,
510 if(detmon_dark_config.exts >= 0) {
511 *masters = cpl_imagelist_new();
512 if(detmon_dark_config.opt_nir == OPT) {
513 *dsnu = cpl_imagelist_new();
514 *dsnu_table = cpl_table_new(ndits);
516 *qclist = cpl_propertylist_new();
517 cpl_table_new_column(*dsnu_table,
"DIT", CPL_TYPE_DOUBLE);
518 cpl_table_new_column(*dsnu_table,
"STDEV", CPL_TYPE_DOUBLE);
520 for ( j = 0; j < detmon_dark_config.nb_extensions; j ++) {
521 masters[j] = cpl_imagelist_new();
522 if(detmon_dark_config.opt_nir == OPT) {
523 dsnu[j] = cpl_imagelist_new();
524 dsnu_table[j] = cpl_table_new(ndits);
526 qclist[j] = cpl_propertylist_new();
527 cpl_table_new_column(dsnu_table[j],
"DIT", CPL_TYPE_DOUBLE);
528 cpl_table_new_column(dsnu_table[j],
"STDEV", CPL_TYPE_DOUBLE);
532 for(j = 0; j < ndits; j++) {
533 cpl_frameset * cur_fdit = cpl_frameset_extract(cur_fset,
535 cpl_imagelist ** raws =
537 cpl_malloc(detmon_dark_config.nb_extensions *
538 sizeof(cpl_imagelist *));
540 if(detmon_dark_config.exts >= 0) {
541 cpl_image * collapsed;
543 cpl_imagelist_load_frameset(cur_fdit, CPL_TYPE_FLOAT, 1,
544 detmon_dark_config.exts);
545 collapsed = cpl_imagelist_collapse_create(*raws);
546 cpl_imagelist_set(*masters, collapsed, j);
547 if(detmon_dark_config.opt_nir == OPT) {
548 detmon_dark_dsnu(cur_fdit, *dsnu, *dsnu_table,
551 detmon_dark_qc(*qclist, collapsed);
553 cpl_imagelist *raws_all_exts =
554 cpl_imagelist_load_frameset(cur_fdit, CPL_TYPE_FLOAT, 1,
556 for(k = 0; k < detmon_dark_config.nb_extensions; k++) {
557 int nframes = cpl_frameset_get_size(cur_fdit);
559 cpl_image * collapsed;
560 for(h = 0; h < nframes; h++) {
562 cpl_imagelist_unset(raws_all_exts,
564 nb_extensions - 1 - k) * h);
565 cpl_imagelist_set(raws[k], image, h);
567 collapsed = cpl_imagelist_collapse_create(raws[k]);
568 cpl_imagelist_set(masters[k],collapsed, j);
569 if(detmon_dark_config.opt_nir == OPT) {
570 detmon_dark_dsnu(cur_fdit, dsnu[k],
571 dsnu_table[j], collapsed, j);
573 detmon_dark_qc(qclist[k], collapsed);
577 cpl_frameset_delete(cur_fdit);
578 for(k = 0; k < detmon_dark_config.nb_extensions; k++) {
579 cpl_imagelist_delete(raws[k]);
584 cpl_frameset_delete(cur_fset);
586 detmon_dark_save(parlist, frameset, recipe_name, pipeline_name,
587 procatg_master, procatg_tbl, procatg_dsnu,
588 package, masters, dsnu_table, dsnu, qclist,
591 if(detmon_dark_config.opt_nir == OPT) {
592 for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
593 cpl_table_delete(dsnu_table[j]);
594 cpl_imagelist_delete(dsnu[j]);
596 cpl_free(dsnu_table);
600 for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
601 cpl_propertylist_delete(qclist[j]);
602 cpl_imagelist_delete(masters[j]);
606 cpl_free(select_dits);
612 return cpl_error_get_code();
628 detmon_dark_dfs_set_groups(cpl_frameset * set,
const char *tag)
638 int nframes = cpl_frameset_get_size(set);
641 for(
int i = 0; i < nframes; i++) {
642 cpl_frame* cur_frame = cpl_frameset_get_frame(set, i);
643 const char* cur_tag = cpl_frame_get_tag(cur_frame);
646 if(!strcmp(cur_tag, tag))
647 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
668 static cpl_error_code
669 detmon_retrieve_dark_params(
const char *pipeline_name,
670 const char *recipe_name,
671 const cpl_parameterlist * parlist)
677 par_name = cpl_sprintf(
"%s.%s.ron.method", pipeline_name, recipe_name);
678 assert(par_name != NULL);
679 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
680 detmon_dark_config.ron_method = cpl_parameter_get_string(par);
684 par_name = cpl_sprintf(
"%s.%s.dsnu.method", pipeline_name, recipe_name);
685 assert(par_name != NULL);
686 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
687 detmon_dark_config.dsnu_method = cpl_parameter_get_string(par);
691 par_name = cpl_sprintf(
"%s.%s.opt_nir", pipeline_name, recipe_name);
692 assert(par_name != NULL);
693 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
694 detmon_dark_config.opt_nir = cpl_parameter_get_bool(par);
698 detmon_dark_config.exts =
699 detmon_retrieve_par_int(
"exts", pipeline_name, recipe_name,
702 if(cpl_error_get_code()) {
703 cpl_msg_error(cpl_func,
"Failed to retrieve the input parameters");
704 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
708 return CPL_ERROR_NONE;
727 detmon_fill_dark_params(cpl_parameterlist * parlist,
728 const char *recipe_name,
729 const char *pipeline_name,
730 const char * ron_method,
731 const char * dsnu_method,
732 const char * opt_nir,
735 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 4,
738 "Method used to compute RON. Currently no "
739 "change is possible, RMS computed",
740 "CPL_TYPE_STRING", ron_method,
743 "Method used to compute DSNU map. Currently no "
744 "change is possible. Method used STDEV",
745 "CPL_TYPE_STRING", dsnu_method,
748 "Boolean, OPT (FALSE) or NIR(TRUE)",
749 "CPL_TYPE_BOOL", opt_nir,
752 "Activate the multi-exts option. Default 0"
753 "(primary unit), -1 (all exts)",
754 "CPL_TYPE_INT", exts);
756 return cpl_error_get_code();
770 detmon_fill_dark_params_default(cpl_parameterlist * parlist,
771 const char *recipe_name,
772 const char *pipeline_name)
774 detmon_fill_dark_params(parlist, recipe_name, pipeline_name,
779 return cpl_error_get_code();
796 detmon_dark_dsnu(cpl_frameset * cur_fdit,
797 cpl_imagelist * dsnu,
798 cpl_table * dsnu_table,
799 cpl_image * collapsed,
802 cpl_frame * first = cpl_frameset_get_first(cur_fdit);
803 cpl_propertylist * plist =
804 cpl_propertylist_load(cpl_frame_get_filename(first), 0);
805 double dit = irplib_pfits_get_exptime(plist);
806 double mean = cpl_image_get_mean(collapsed);
808 cpl_image * dsnu_map =
809 cpl_image_subtract_scalar_create(collapsed, mean);
811 cpl_image_divide_scalar(dsnu_map, mean);
812 stdev = cpl_image_get_stdev(dsnu_map);
814 cpl_imagelist_set(dsnu, dsnu_map, pos);
816 cpl_table_set(dsnu_table,
"DIT", pos, dit);
817 cpl_table_set(dsnu_table,
"STDEV", pos, stdev);
819 cpl_propertylist_delete(plist);
821 return cpl_error_get_code();
848 static cpl_error_code
849 detmon_dark_save(
const cpl_parameterlist * parlist,
850 cpl_frameset * frameset,
851 const char *recipe_name,
852 const char *pipeline_name,
853 const char *procatg_master,
854 const char *procatg_tbl,
855 const char *procatg_dsnu,
857 cpl_imagelist ** masters,
858 cpl_table ** dsnu_table,
859 cpl_imagelist ** dsnu,
860 cpl_propertylist ** qclist,
863 const cpl_frameset * usedframes)
866 cpl_frame *ref_frame;
867 cpl_propertylist *plist;
870 cpl_propertylist *paflist;
871 cpl_error_code error;
878 nb_images = cpl_imagelist_get_size(masters[0]);
879 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
882 for(i = 0; i < nb_images; i++) {
886 cpl_sprintf(
"%s_master_dit_%d.fits", recipe_name, i+1);
887 assert(name_o != NULL);
890 cpl_sprintf(
"%s_master_dit_%d_set%02d.fits",
891 recipe_name, i, which_set);
892 assert(name_o != NULL);
897 if(detmon_dark_config.exts >= 0) {
898 cpl_propertylist * pro_master = cpl_propertylist_new();
900 cpl_propertylist_append_string(pro_master,
901 CPL_DFS_PRO_CATG, procatg_master);
903 cpl_propertylist_append(pro_master, qclist[0]);
905 if(cpl_dfs_save_image
906 (frameset, NULL, parlist, usedframes, NULL,
907 cpl_imagelist_get(*masters, i), CPL_BPP_IEEE_FLOAT,
908 recipe_name, pro_master, NULL, package,
910 cpl_msg_error(cpl_func,
"Cannot save the product: %s",
913 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
917 cpl_propertylist_delete(pro_master);
919 cpl_propertylist * pro_master = cpl_propertylist_new();
921 cpl_propertylist_append_string(pro_master,
922 CPL_DFS_PRO_CATG, procatg_master);
924 cpl_propertylist_append(pro_master, qclist[0]);
926 if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
927 NULL, CPL_BPP_IEEE_FLOAT, recipe_name,
930 cpl_msg_error(cpl_func,
"Cannot save the product: %s",
933 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
936 cpl_propertylist_delete(pro_master);
937 for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
939 cpl_image_save(cpl_imagelist_get(masters[j], i),
940 name_o, CPL_BPP_IEEE_FLOAT, qclist[j],
942 cpl_ensure_code(!error, error);
948 if (detmon_dark_config.opt_nir == OPT) {
949 cpl_propertylist * pro_tbl = cpl_propertylist_new();
951 cpl_propertylist_append_string(pro_tbl,
952 CPL_DFS_PRO_CATG, procatg_tbl);
954 cpl_propertylist_append(pro_tbl, qclist[0]);
961 name_o = cpl_sprintf(
"%s_dsnu_table.fits", recipe_name);
962 assert(name_o != NULL);
965 cpl_sprintf(
"%s_dsnu_table_set%02d.fits", recipe_name,
967 assert(name_o != NULL);
970 if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
971 dsnu_table[0], NULL, recipe_name, pro_tbl, NULL,
973 cpl_msg_error(cpl_func,
"Cannot save the product: %s", name_o);
975 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
978 cpl_propertylist_delete(pro_tbl);
980 if(detmon_dark_config.exts < 0) {
982 for(i = 1; i < detmon_dark_config.nb_extensions; i++) {
984 cpl_table_save(dsnu_table[i], NULL, qclist[i], name_o,
986 cpl_ensure_code(!error, error);
997 for(i = 0; i < nb_images; i++) {
1001 cpl_sprintf(
"%s_dsnu_map_dit_%d.fits", recipe_name, i+1);
1002 assert(name_o != NULL);
1005 cpl_sprintf(
"%s_dsnu_map_dit_%d_set%02d.fits",
1006 recipe_name, i, which_set);
1007 assert(name_o != NULL);
1012 if(detmon_dark_config.exts >= 0) {
1013 cpl_propertylist * pro_dsnu = cpl_propertylist_new();
1015 cpl_propertylist_append_string(pro_dsnu,
1016 CPL_DFS_PRO_CATG, procatg_dsnu);
1018 cpl_propertylist_append(pro_dsnu, qclist[0]);
1020 if(cpl_dfs_save_image
1021 (frameset, NULL, parlist, usedframes, NULL,
1022 cpl_imagelist_get(*dsnu, i), CPL_BPP_IEEE_FLOAT,
1023 recipe_name, pro_dsnu, NULL, package,
1025 cpl_msg_error(cpl_func,
"Cannot save the product: %s",
1028 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
1032 cpl_propertylist_delete(pro_dsnu);
1034 cpl_propertylist * pro_dsnu = cpl_propertylist_new();
1036 cpl_propertylist_append_string(pro_dsnu,
1037 CPL_DFS_PRO_CATG, procatg_dsnu);
1039 cpl_propertylist_append(pro_dsnu, qclist[0]);
1041 if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
1043 CPL_BPP_IEEE_FLOAT, recipe_name,
1046 cpl_msg_error(cpl_func,
"Cannot save the product: %s",
1049 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
1052 cpl_propertylist_delete(pro_dsnu);
1053 for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
1055 cpl_image_save(cpl_imagelist_get(dsnu[j], i),
1056 name_o, CPL_BPP_IEEE_FLOAT, qclist[j],
1058 cpl_ensure_code(!error, error);
1073 ref_frame = cpl_frameset_get_first(frameset);
1074 if((plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
1076 cpl_msg_error(cpl_func,
"getting header from reference frame");
1077 cpl_ensure_code(0, cpl_error_get_code());
1081 paflist = cpl_propertylist_new();
1082 cpl_propertylist_copy_property_regexp(paflist, plist,
1083 "^(ARCFILE|MJD-OBS|ESO TPL ID|"
1084 "DATE-OBS|ESO DET DIT|ESO DET NDIT|"
1086 "ESO DET MODE NAME)$", 0);
1088 for(i = 0; i < detmon_dark_config.nb_extensions; i++) {
1089 cpl_propertylist * c_paflist = cpl_propertylist_duplicate(paflist);
1090 error = cpl_propertylist_append(c_paflist, qclist[i]);
1091 cpl_ensure_code(!error, error);
1094 if(detmon_dark_config.exts >= 0) {
1096 name_o = cpl_sprintf(
"%s.paf", recipe_name);
1097 assert(name_o != NULL);
1099 name_o = cpl_sprintf(
"%s_set%02d.paf", recipe_name, which_set);
1100 assert(name_o != NULL);
1104 name_o = cpl_sprintf(
"%s_ext%02d.paf", recipe_name, i+1);
1105 assert(name_o != NULL);
1107 name_o = cpl_sprintf(
"%s_set%02d_ext%02d.paf", recipe_name, which_set, i+1);
1108 assert(name_o != NULL);
1112 if(cpl_dfs_save_paf(pipeline_name, recipe_name, c_paflist, name_o)) {
1113 cpl_msg_error(cpl_func,
"Cannot save the product: %s", name_o);
1115 cpl_propertylist_delete(paflist);
1116 cpl_propertylist_delete(plist);
1118 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
1120 cpl_propertylist_delete(c_paflist);
1124 cpl_propertylist_delete(plist);
1125 cpl_propertylist_delete(paflist);
1127 return cpl_error_get_code();
1138 detmon_dark_qc(cpl_propertylist * qclist,
1139 cpl_image * collapsed)
1141 double mean = cpl_image_get_mean(collapsed);
1142 double stdev = cpl_image_get_stdev(collapsed);
1145 cpl_propertylist_append_double(qclist,DETMON_QC_DARK, mean);
1146 cpl_propertylist_set_comment(qclist,DETMON_QC_DARK,
1149 cpl_propertylist_append_double(qclist,DETMON_QC_DARK_STDEV, stdev);
1150 cpl_propertylist_set_comment(qclist,DETMON_QC_DARK_STDEV,
1151 DETMON_QC_DARK_STDEV_C);
1152 detmon_print_rec_status();
1154 return cpl_error_get_code();