36 #include "naco_recipe.h"
37 #include "naco_strehl.h"
39 #include "irplib_strehl.h"
40 #include "irplib_calib.h"
49 #define RECIPE_STRING "naco_img_jitter"
53 #define NACO_MIN(A,B) ((A) < (B) ? (A) : (B))
54 #define NACO_MAX(A,B) ((A) > (B) ? (A) : (B))
60 #ifndef NACO_IMG_JITTER_KEEP_SKY_OBJECTS
61 static cpl_error_code naco_img_jitter_reject_objects(cpl_image *,
double,
65 static cpl_error_code naco_img_jitter_find_strehl(
const cpl_imagelist *,
66 const cpl_parameterlist *,
67 const irplib_framelist *);
69 static cpl_image * naco_img_jitter_saa_center(
const cpl_imagelist *,
72 static cpl_image * naco_img_jitter_saa_lucky(
const cpl_imagelist *,
74 const cpl_bivector *,
double);
76 static cpl_image * naco_img_jitter_find_sky_cube(
int,
int,
const cpl_array *,
77 const irplib_framelist *);
79 static cpl_error_code naco_img_jitter_imagelist_wrap_nocube(cpl_imagelist *,
84 static cpl_image * naco_img_jitter_combine_cube(cpl_table *,
const cpl_imagelist *,
85 const cpl_propertylist *,
86 const cpl_parameterlist *,
int);
88 static cpl_error_code naco_img_jitter_check_cube(
const cpl_imagelist *,
91 static cpl_error_code naco_img_jitter_do_cube(cpl_imagelist *, cpl_table *,
94 const irplib_framelist *,
95 const cpl_parameterlist *);
98 cpl_error_code naco_img_jitter_load_objimages(cpl_imagelist *, cpl_array *,
99 const irplib_framelist *,
100 const cpl_parameterlist *);
102 static cpl_image ** naco_img_jitter_reduce(cpl_imagelist *, cpl_table *,
104 const irplib_framelist *,
105 const irplib_framelist *,
106 const cpl_parameterlist *,
112 static cpl_image * naco_img_jitter_find_sky(cpl_propertylist *,
113 const cpl_imagelist *,
114 const cpl_imagelist *);
115 static cpl_image ** naco_img_jitter_saa(cpl_imagelist *,
116 const irplib_framelist *,
117 const cpl_parameterlist *);
118 static cpl_error_code naco_img_jitter_qc(cpl_propertylist *, cpl_propertylist *,
119 const irplib_framelist *,
120 const cpl_image *, cpl_boolean);
121 static cpl_error_code naco_img_jitter_qc_apertures(cpl_propertylist *,
122 const irplib_framelist *,
124 static cpl_error_code naco_img_jitter_save(cpl_frameset *,
125 const cpl_parameterlist *,
126 const cpl_propertylist *,
127 const cpl_propertylist *,
128 const cpl_imagelist *,
133 NACO_RECIPE_DEFINE(naco_img_jitter,
146 RECIPE_STRING
" -- NACO imaging jitter recipe.\n"
147 "The files listed in the Set Of Frames (sof-file) "
149 "NACO-raw-file.fits "NACO_IMG_JITTER_OBJ
" or\n"
150 "NACO-raw-file.fits "NACO_IMG_JITTER_SKY
" or\n"
151 "NACO-raw-file.fits "NACO_IMG_JITTER_OBJ_POL
" or\n"
152 "NACO-raw-file.fits "NACO_IMG_JITTER_SKY_POL
" or\n"
153 "NACO-flat-file.fits "NACO_CALIB_FLAT
" or\n"
154 "NACO-bpm-file.fits "NACO_CALIB_BPM
" or\n"
155 "NACO-dark-file.fits "NACO_CALIB_DARK
"\n");
175 static int naco_img_jitter(cpl_frameset * framelist,
176 const cpl_parameterlist * parlist)
178 cpl_errorstate cleanstate = cpl_errorstate_get();
179 irplib_framelist * allframes = NULL;
180 irplib_framelist * objframes = NULL;
181 irplib_framelist * skyframes = NULL;
182 cpl_propertylist * qclist = cpl_propertylist_new();
183 cpl_propertylist * paflist = cpl_propertylist_new();
184 cpl_imagelist * objimages = cpl_imagelist_new();
185 cpl_image ** combined = NULL;
186 cpl_table * cubetable = cpl_table_new(1);
190 cpl_boolean drop_wcs = CPL_FALSE;
197 skip_if(allframes == NULL);
200 "^(" NACO_IMG_JITTER_OBJ
"|"
201 NACO_IMG_JITTER_OBJ_POL
")$",
203 skip_if(objframes == NULL);
206 "^(" NACO_IMG_JITTER_SKY
"|"
207 NACO_IMG_JITTER_SKY_POL
")$",
210 if (skyframes == NULL) {
211 naco_error_reset(
"The set of frames has no sky frames:");
224 NACO_PFITS_REGEXP_JITTER_FIRST
228 NACO_PFITS_REGEXP_JITTER_ALL
232 cpl_msg_info(cpl_func,
"Apply the data recombination");
233 combined = naco_img_jitter_reduce(objimages, cubetable, qclist, objframes,
234 skyframes, parlist, dark, flat, badpix,
237 skip_if (combined == NULL);
242 cpl_msg_info(cpl_func,
"Compute QC parameters from the combined image");
243 skip_if (naco_img_jitter_qc(qclist, paflist, objframes, combined[0], drop_wcs));
248 cpl_msg_info(cpl_func,
"Save the products");
251 bug_if (cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
252 cpl_table_get_ncol(cubetable) > 0 ?
253 NACO_IMG_JITTER_CUBE :
254 NACO_IMG_JITTER_COMB));
256 skip_if (naco_img_jitter_save(framelist, parlist, qclist, paflist,
258 combined[0], combined[1], cubetable));
262 if (combined != NULL) {
263 cpl_image_delete(combined[0]);
264 cpl_image_delete(combined[1]);
267 cpl_imagelist_delete(objimages);
271 cpl_propertylist_delete(qclist);
272 cpl_propertylist_delete(paflist);
273 cpl_table_delete(cubetable);
275 return cpl_error_get_code();
294 static cpl_image ** naco_img_jitter_reduce(cpl_imagelist * objimages,
295 cpl_table * cubetable,
296 cpl_propertylist * qclist,
297 const irplib_framelist * obj,
298 const irplib_framelist * sky,
299 const cpl_parameterlist * parlist,
303 cpl_boolean * pdid_resize)
305 cpl_errorstate prestate = cpl_errorstate_get();
307 cpl_imagelist * nocubeimgs = NULL;
308 cpl_imagelist * skyimages = NULL;
309 cpl_image * skyimage = NULL;
310 cpl_image ** combined = NULL;
311 cpl_array * iscube = NULL;
312 cpl_boolean has_cube = CPL_FALSE;
314 (parlist, RECIPE_STRING, NACO_PARAM_CUBEMODE);
318 bug_if(pdid_resize == NULL);
319 bug_if(scubemode == NULL);
322 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
325 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
328 cpl_msg_info(cpl_func,
"Loading the %d object and %d sky images",
332 iscube = cpl_array_new(nobj, CPL_TYPE_INT);
334 (void)naco_img_jitter_load_objimages(objimages, iscube, obj, parlist);
336 any_if(
"Could not load the %d object images", nobj);
338 cpl_msg_info(cpl_func,
"Loaded %d object images", nobj);
340 skip_if(cpl_imagelist_get_size(objimages) != nobj);
344 cpl_msg_info(cpl_func,
"Sky estimation and correction");
346 if (scubemode[0] ==
'a') {
348 const int mcube = nobj - cpl_array_count_invalid(iscube);
351 cpl_msg_info(cpl_func,
"Collapsing %d cube(s) with no shifting",
353 cpl_array_delete(iscube);
354 iscube = cpl_array_new(nobj, CPL_TYPE_INT);
358 if (cpl_array_has_valid(iscube)) {
361 skip_if(naco_img_jitter_do_cube(objimages, cubetable, qclist,
362 iscube, obj, parlist));
364 #ifdef NACO_IMG_JITTER_DEVELOPMENT
365 skip_if(cpl_imagelist_save(objimages,
"Collapsed.fits", CPL_BPP_IEEE_FLOAT,
366 NULL, CPL_IO_CREATE));
370 if (cpl_array_has_invalid(iscube)) {
372 nocubeimgs = has_cube ? cpl_imagelist_new() : objimages;
374 skip_if(naco_img_jitter_imagelist_wrap_nocube(nocubeimgs, iscube,
376 inocube = cpl_imagelist_get_size(nocubeimgs);
382 any_if(
"Could not load sky images");
386 skyimage = naco_img_jitter_find_sky(qclist, nocubeimgs, skyimages);
387 any_if(
"Could not estimate sky");
389 cpl_imagelist_delete(skyimages);
393 skip_if (cpl_imagelist_subtract_image(nocubeimgs, skyimage));
397 if(naco_img_jitter_find_strehl(objimages, parlist, obj)) {
398 irplib_error_recover(prestate,
"Could not compute Strehl-ratio "
399 "for %d frame(s)", nobj);
403 cpl_msg_info(cpl_func,
"Shift and add");
404 combined = naco_img_jitter_saa(objimages, obj, parlist);
405 skip_if (combined == NULL);
407 *pdid_resize = (cpl_boolean)
408 (cpl_image_get_size_x(combined[0])
409 != cpl_image_get_size_x(cpl_imagelist_get_const(objimages, 0)) ||
410 cpl_image_get_size_y(combined[0])
411 != cpl_image_get_size_y(cpl_imagelist_get_const(objimages, 0)));
416 for (;inocube > 0;) {
417 (void)cpl_imagelist_unset(nocubeimgs, --inocube);
420 if (nocubeimgs != objimages) cpl_imagelist_delete(nocubeimgs);
421 cpl_imagelist_delete(skyimages);
422 cpl_image_delete(skyimage);
423 cpl_array_delete(iscube);
437 static cpl_image * naco_img_jitter_find_sky(cpl_propertylist * qclist,
438 const cpl_imagelist * objs,
439 const cpl_imagelist * skys)
441 cpl_image *
self = NULL;
445 self = cpl_imagelist_collapse_median_create(skys);
446 any_if(
"Could not compute the median of %d sky images",
447 (
int)cpl_imagelist_get_size(skys));
451 self = cpl_imagelist_collapse_median_create(objs);
452 any_if(
"Could not compute the median of %d object images",
453 (
int)cpl_imagelist_get_size(objs));
457 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC BACKGD",
458 cpl_image_get_median(
self)));
459 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC BACKGD STDEV",
460 cpl_image_get_stdev(
self)));
476 static cpl_image ** naco_img_jitter_saa(cpl_imagelist * imlist,
477 const irplib_framelist * objframes,
478 const cpl_parameterlist * parlist)
481 cpl_bivector * offsets_est = NULL;
482 cpl_bivector * objs = NULL;
483 cpl_image ** combined = NULL;
484 cpl_vector * sigmas = NULL;
485 double psigmas[] = {5.0, 2.0, 1.0, 0.5};
486 const char * offsets;
487 const char * objects;
488 #ifdef NACO_USE_ODDEVEN
489 cpl_boolean oddeven_flag;
491 const int nsigmas = (int)(
sizeof(psigmas)/
sizeof(double));
492 const int nfiles = cpl_imagelist_get_size(imlist);
494 int rej_low, rej_high;
495 const char * combine_string;
496 cpl_geom_combine combine_mode;
510 #ifdef NACO_USE_ODDEVEN
519 bug_if (sval == NULL);
521 skip_if (sscanf(sval,
"%d %d %d %d", &sx, &sy, &mx, &my) != 4);
526 bug_if (combine_string == NULL);
528 if (combine_string[0] ==
'u')
529 combine_mode = CPL_GEOM_UNION;
530 else if (combine_string[0] ==
'f')
531 combine_mode = CPL_GEOM_FIRST;
532 else if (combine_string[0] ==
'i')
533 combine_mode = CPL_GEOM_INTERSECT;
539 NACO_PARAM_REJ_HILO);
540 bug_if (sval == NULL);
542 skip_if (sscanf(sval,
"%d %d", &rej_low, &rej_high) != 2);
546 cpl_msg_info(cpl_func,
"Get the offsets estimation");
549 offsets[0] != (
char)0) {
551 offsets_est = cpl_bivector_read(offsets);
552 if (offsets_est == NULL ||
553 cpl_bivector_get_size(offsets_est) != nfiles) {
554 cpl_msg_error(cpl_func,
"Cannot get offsets from %s",
559 double * offsets_est_x;
560 double * offsets_est_y;
561 double offx0 = DBL_MAX;
562 double offy0 = DBL_MAX;
566 offsets_est = cpl_bivector_new(nfiles);
567 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
568 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
569 for (i=0 ; i < nfiles ; i++) {
570 const cpl_propertylist * plist
589 objects[0] != (
char)0) {
590 cpl_msg_info(cpl_func,
"Get the user provided correlation objects");
592 objs = cpl_bivector_read(objects);
594 cpl_msg_error(cpl_func,
"Cannot get objects from %s",
601 sigmas = cpl_vector_wrap(nsigmas, psigmas);
604 cpl_msg_info(cpl_func,
"Recombine the images set");
605 combined = cpl_geom_img_offset_combine(imlist, offsets_est, 1, objs,
606 sigmas, NULL, sx, sy, mx, my,
607 rej_low, rej_high, combine_mode);
609 skip_if (combined == NULL);
613 cpl_bivector_delete(offsets_est);
614 cpl_bivector_delete(objs);
615 cpl_vector_unwrap(sigmas);
631 static cpl_error_code naco_img_jitter_qc(cpl_propertylist * qclist,
632 cpl_propertylist * paflist,
633 const irplib_framelist * objframes,
634 const cpl_image * combined,
635 cpl_boolean drop_wcs)
637 cpl_errorstate cleanstate = cpl_errorstate_get();
638 const cpl_propertylist * reflist
643 bug_if(combined == NULL);
645 bug_if(cpl_propertylist_copy_property_regexp(paflist, reflist,
"^("
646 NACO_PFITS_REGEXP_JITTER_PAF
649 if (naco_img_jitter_qc_apertures(qclist, objframes, combined)) {
650 naco_error_reset(
"Could not compute all QC parameters");
654 if (cpl_error_get_code()) {
655 naco_error_reset(
"Could not get FITS key:");
657 cpl_propertylist_append_string(qclist,
"ESO QC FILTER OBS", sval);
660 if (cpl_error_get_code()) {
661 naco_error_reset(
"Could not get FITS key:");
663 cpl_propertylist_append_string(qclist,
"ESO QC FILTER NDENS", sval);
666 if (cpl_error_get_code()) {
667 naco_error_reset(
"Could not get FITS key:");
669 cpl_propertylist_append_string(qclist,
"ESO QC FILTER POL", sval);
674 bug_if (cpl_propertylist_append(paflist, qclist));
677 cpl_propertylist * pcopy = cpl_propertylist_new();
678 const cpl_error_code error
679 = cpl_propertylist_copy_property_regexp(pcopy, reflist,
"^("
680 IRPLIB_PFITS_WCS_REGEXP
682 if (!error && cpl_propertylist_get_size(pcopy) > 0) {
683 cpl_msg_warning(cpl_func,
"Combined image will have no WCS "
686 cpl_propertylist_delete(pcopy);
688 bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist,
"^("
689 NACO_PFITS_REGEXP_JITTER_COPY
692 bug_if(cpl_propertylist_copy_property_regexp(qclist, reflist,
"^("
693 IRPLIB_PFITS_WCS_REGEXP
"|"
694 NACO_PFITS_REGEXP_JITTER_COPY
698 if (cpl_propertylist_has(qclist,
"AIRMASS"))
703 return cpl_error_get_code();
715 static cpl_error_code naco_img_jitter_qc_apertures(cpl_propertylist * qclist,
716 const irplib_framelist *
718 const cpl_image * combined)
720 const cpl_propertylist * reflist
723 cpl_apertures * aperts = NULL;
724 cpl_bivector * fwhms = NULL;
725 cpl_vector * fwhms_sum = NULL;
726 cpl_vector * sigmas = NULL;
729 double * fwhms_sum_data;
732 double psigmas[] = {5.0, 2.0, 1.0, 0.5};
733 const int nsigmas = (int)(
sizeof(psigmas)/
sizeof(double));
739 const double seeing_min_arcsec = 0.1;
740 const double seeing_max_arcsec = 5.0;
741 const double seeing_fwhm_var = 0.2;
743 double iq, fwhm_pix, fwhm_arcsec;
747 cpl_msg_info(cpl_func,
"Detecting apertures using %d sigma-levels "
748 "ranging from %g down to %g", nsigmas, psigmas[0],
752 skip_if( pixscale <= 0.0 );
753 bug_if( seeing_min_arcsec < 0.0);
756 sigmas = cpl_vector_wrap(nsigmas, psigmas);
758 aperts = cpl_apertures_extract(combined, sigmas, &isigma);
759 if (aperts == NULL) {
760 cpl_msg_warning(cpl_func,
"Could not detect any apertures in combined "
767 fwhms = cpl_apertures_get_fwhm(combined, aperts);
769 cpl_msg_warning(cpl_func,
"Could not compute any FWHMs of the "
770 "apertures in the combined image");
774 cpl_apertures_delete(aperts);
778 nb_val = cpl_bivector_get_size(fwhms);
779 fwhms_x = cpl_bivector_get_x_data(fwhms);
780 fwhms_y = cpl_bivector_get_y_data(fwhms);
784 for (i=0 ; i < nb_val ; i++) {
785 if (fwhms_x[i] <= 0.0 || fwhms_y[i] <= 0.0)
continue;
786 fwhms_x[nb_good] = fwhms_x[i];
787 fwhms_y[nb_good] = fwhms_y[i];
791 cpl_msg_info(cpl_func,
"Detected %d (%d) apertures at sigma=%g",
792 nb_good, nb_val, psigmas[isigma]);
794 skip_if_lt (nb_good, 1,
"aperture with a FWHM");
798 bug_if(cpl_vector_set_size(cpl_bivector_get_x(fwhms), nb_val));
799 bug_if(cpl_vector_set_size(cpl_bivector_get_y(fwhms), nb_val));
800 fwhms_x = cpl_bivector_get_x_data(fwhms);
801 fwhms_y = cpl_bivector_get_y_data(fwhms);
804 fwhms_sum = cpl_vector_new(nb_good);
805 fwhms_sum_data = cpl_vector_get_data(fwhms_sum);
806 for (i=0; i < nb_good; i++) {
807 fwhms_sum_data[i] = fwhms_x[i] + fwhms_y[i];
810 fwhm_pix = 0.5 * cpl_vector_get_median(fwhms_sum);
812 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC FWHM PIX", fwhm_pix));
814 fwhm_arcsec = fwhm_pix * pixscale;
816 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC FWHM ARCSEC",
823 f_min = seeing_min_arcsec / pixscale;
824 f_max = seeing_max_arcsec / pixscale;
828 for (i=0 ; i < nb_val ; i++) {
829 const double fx = fwhms_x[i];
830 const double fy = fwhms_y[i];
832 if (fx <= f_min || f_max <= fx || fy <= f_min || f_max <= fy)
continue;
833 if (fabs(fx-fy) >= 0.5 * (fx + fy) * seeing_fwhm_var)
continue;
835 fwhms_sum_data[nb_good] = fx + fy;
839 cpl_msg_info(cpl_func,
"%d of the apertures have FWHMs within the range "
840 "%g to %g and eccentricity within %g", nb_good, f_min, f_max,
843 skip_if_lt (nb_good, 1,
"aperture with a good FWHM");
845 bug_if(cpl_vector_set_size(fwhms_sum, nb_good));
848 iq = pixscale * 0.5 * cpl_vector_get_median(fwhms_sum);
850 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC IQ", iq));
854 cpl_vector_delete(fwhms_sum);
855 cpl_bivector_delete(fwhms);
856 cpl_vector_unwrap(sigmas);
857 cpl_apertures_delete(aperts);
859 return cpl_error_get_code();
876 static cpl_error_code naco_img_jitter_save(cpl_frameset * set,
877 const cpl_parameterlist * parlist,
878 const cpl_propertylist * qclist,
879 const cpl_propertylist * paflist,
880 const cpl_imagelist * objimages,
881 const cpl_image * combined,
882 const cpl_image * contrib,
883 const cpl_table * cubetable)
886 const cpl_boolean is_cube = cpl_table_get_ncol(cubetable) > 0
887 ? CPL_TRUE : CPL_FALSE;
888 const char * procatg = is_cube ? NACO_IMG_JITTER_CUBE
889 : NACO_IMG_JITTER_COMB;
890 cpl_propertylist * xtlist = cpl_propertylist_new();
891 const cpl_boolean save_cube =
893 NACO_PARAM_SAVECUBE);
896 bug_if (contrib == NULL);
900 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
901 procatg, qclist, NULL,
902 naco_pipe_id, RECIPE_STRING CPL_DFS_FITS));
904 bug_if(cpl_propertylist_append_string(xtlist,
"EXTNAME",
905 "Contribution Map"));
906 skip_if (cpl_image_save(contrib, RECIPE_STRING CPL_DFS_FITS,
907 CPL_BPP_16_SIGNED, xtlist, CPL_IO_EXTEND));
911 bug_if(cpl_propertylist_update_string(xtlist,
"EXTNAME",
912 "Plane Properties"));
913 skip_if (cpl_table_save(cubetable, NULL, xtlist,
914 RECIPE_STRING CPL_DFS_FITS, CPL_IO_EXTEND));
918 bug_if(cpl_propertylist_update_string(xtlist,
"EXTNAME",
919 "Corrected object images"));
920 skip_if (cpl_imagelist_save(objimages, RECIPE_STRING CPL_DFS_FITS,
921 CPL_BPP_IEEE_FLOAT, xtlist, CPL_IO_EXTEND));
925 skip_if (cpl_dfs_save_paf(
"NACO", RECIPE_STRING, paflist,
926 RECIPE_STRING CPL_DFS_PAF));
928 bug_if(paflist == NULL);
933 cpl_propertylist_delete(xtlist);
935 return cpl_error_get_code();
953 cpl_error_code naco_img_jitter_load_objimages(cpl_imagelist * objlist,
955 const irplib_framelist *
self,
956 const cpl_parameterlist * parlist)
959 cpl_image * image = NULL;
962 bug_if(objlist == NULL);
963 bug_if(
self == NULL);
964 bug_if(iscube == NULL);
965 bug_if(parlist == NULL);
967 for (i=0; i < nframes; i++, image = NULL) {
968 const char * filename
970 const cpl_propertylist * plist
972 const int naxis3 = cpl_propertylist_has(plist,
"NAXIS3") ?
973 cpl_propertylist_get_int(plist,
"NAXIS3") : 1;
978 bug_if(cpl_array_set_int(iscube, i, 1));
986 image = cpl_image_load(filename, CPL_TYPE_FLOAT, naxis3-1, EXT0);
988 any_if(
"Could not load %d-cube-sum from frame %d/%d, file=%s",
989 naxis3-1, i+1, nframes, filename);
992 image = cpl_image_load(filename, CPL_TYPE_FLOAT, 0, EXT0);
994 any_if(
"Could not load FITS-image from extension %d in frame "
995 "%d/%d, file=%s", EXT0, i+1, nframes, filename);
998 bug_if(cpl_imagelist_set(objlist, image, i));
1003 cpl_image_delete(image);
1005 return cpl_error_get_code();
1018 static cpl_error_code naco_img_jitter_check_cube(
const cpl_imagelist *
self,
1019 const cpl_image * sum)
1021 cpl_image * accu = cpl_imagelist_collapse_create(
self);
1024 cpl_image_subtract(accu, sum);
1026 err = cpl_image_get_absflux(accu);
1029 err /= cpl_image_get_size_x(sum) * cpl_image_get_size_y(sum);
1031 cpl_msg_info(cpl_func,
"Average per-pixel error in final sum frame "
1032 "in %d-cube: %g", (
int)cpl_imagelist_get_size(
self), err);
1035 cpl_image_delete(accu);
1037 return cpl_error_get_code();
1054 static cpl_error_code naco_img_jitter_do_cube(cpl_imagelist *
self,
1055 cpl_table * cubetable,
1056 cpl_propertylist * qclist,
1057 const cpl_array * iscube,
1058 const irplib_framelist * obj,
1059 const cpl_parameterlist * parlist)
1063 cpl_imagelist * onelist = NULL;
1064 cpl_image * sum = NULL;
1065 cpl_image * onesky = NULL;
1068 NACO_PARAM_SKYPLANE);
1069 cpl_vector * skymedians = cpl_vector_new(nframes);
1073 bug_if(
self == NULL);
1074 bug_if(cubetable == NULL);
1075 bug_if(qclist == NULL);
1076 bug_if(obj == NULL);
1077 bug_if(parlist == NULL);
1078 bug_if(nframes != cpl_array_get_size(iscube));
1079 bug_if(nframes != cpl_imagelist_get_size(
self));
1082 for (i=0; i < nframes; i++) {
1085 (void)cpl_array_get_int(iscube, i, &is_invalid);
1088 const char * filename
1090 const cpl_propertylist * plist
1096 cpl_image_delete(onesky);
1097 onesky = naco_img_jitter_find_sky_cube(i, nskyplane, iscube, obj);
1098 any_if(
"Could not estimate sky for frame %d/%d, file=%s",
1099 i+1, nframes, filename);
1101 skymedian = cpl_image_get_median(onesky);
1102 #ifdef NACO_IMG_JITTER_DEVELOPMENT
1103 if (onelist == NULL) {
1107 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC BACKGD",
1110 cpl_image_save(onesky,
"Sky.fits", CPL_BPP_IEEE_FLOAT, NULL,
1113 cpl_image_save(onesky,
"Sky.fits", CPL_BPP_IEEE_FLOAT, NULL,
1117 cpl_imagelist_delete(onelist);
1118 onelist = cpl_imagelist_load(filename, CPL_TYPE_FLOAT, EXT0);
1120 any_if(
"Could not load cube from frame %d/%d, file=%s",
1121 i+1, nframes, filename);
1123 naxis3 = cpl_imagelist_get_size(onelist);
1125 cpl_msg_info(cpl_func,
"Processing %d-cube from frame %d/%d, "
1126 "file=%s. Median of sky-estimate: %g",
1127 naxis3-1, i+1, nframes, filename, skymedian);
1128 cpl_vector_set(skymedians, nsky++, skymedian);
1132 sum = cpl_imagelist_unset(onelist, naxis3-1);
1134 bug_if(naco_img_jitter_check_cube(onelist, sum));
1136 skip_if(cpl_imagelist_subtract_image(onelist, onesky));
1138 cpl_image_delete(sum);
1139 sum = naco_img_jitter_combine_cube(cubetable, onelist, plist,
1141 any_if(
"Could not combine %d images from frame %d/%d, file=%s",
1142 naxis3-1, i+1, nframes, filename);
1144 bug_if(cpl_imagelist_set(
self, sum, i));
1150 double skystdev, skymean;
1152 bug_if(cpl_vector_set_size(skymedians, nsky));
1154 skymean = cpl_vector_get_mean(skymedians);
1155 skystdev = cpl_vector_get_stdev(skymedians);
1157 cpl_msg_info(cpl_func,
"Mean and stdev of %d medians of sky estimates: "
1158 "%g %g", nsky, skymean, skystdev);
1160 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC SKY STDEV",
1166 cpl_imagelist_delete(onelist);
1167 cpl_image_delete(sum);
1168 cpl_image_delete(onesky);
1169 cpl_vector_delete(skymedians);
1171 return cpl_error_get_code();
1189 cpl_image * naco_img_jitter_combine_cube(cpl_table * cubetable,
1190 const cpl_imagelist * cube,
1191 const cpl_propertylist * plist,
1192 const cpl_parameterlist * parlist,
1196 cpl_errorstate prestate = cpl_errorstate_get();
1197 cpl_image *
self = NULL;
1198 const int ncube = cpl_imagelist_get_size(cube);
1199 cpl_image ** combined = NULL;
1200 cpl_apertures * apert = NULL;
1201 cpl_bivector * offs = cpl_bivector_new(ncube);
1202 cpl_vector * offsx = cpl_bivector_get_x(offs);
1203 cpl_vector * offsy = cpl_bivector_get_y(offs);
1204 cpl_vector * sigmas = NULL;
1205 cpl_vector * vstrehl = cpl_vector_new(ncube);
1206 double psigmas[] = {5.0, 2.0, 1.0, 0.5};
1207 const int nsigmas = (int)(
sizeof(psigmas)/
sizeof(double));
1216 NACO_PARAM_LUCK_STR);
1218 double lam = DBL_MAX;
1219 double dlam = DBL_MAX;
1220 cpl_size isigma = 0;
1221 const int ncubetable = cpl_table_get_nrow(cubetable);
1226 skip_if(rbgext <= rbgint);
1227 skip_if(pixscale <= 0.0);
1230 "Frame has no info for filter %s", filter);
1232 cpl_msg_debug(cpl_func,
"Frame %d has pixelscale [Arcsecond/pixel]=%g, "
1233 "Central wavelength [micron]=%g, Filter bandwidth "
1234 "[micron]=%g", 1+idx, pixscale, lam, dlam);
1235 cpl_msg_debug(cpl_func,
"Frame %d assumes Rstar [pixel]=%g, Rint "
1236 "[pixel]=%g, Rext [pixel]=%g", 1+idx, rstar/pixscale,
1237 rbgint/pixscale, rbgext/pixscale);
1239 if (cpl_table_get_ncol(cubetable) == 0) {
1240 cpl_table_new_column(cubetable,
"Frame", CPL_TYPE_INT);
1241 cpl_table_new_column(cubetable,
"Plane", CPL_TYPE_INT);
1242 cpl_table_new_column(cubetable,
"XCentroid", CPL_TYPE_DOUBLE);
1243 cpl_table_new_column(cubetable,
"YCentroid", CPL_TYPE_DOUBLE);
1244 cpl_table_set_column_unit(cubetable,
"XCentroid",
"pixel");
1245 cpl_table_set_column_unit(cubetable,
"YCentroid",
"pixel");
1246 cpl_table_new_column(cubetable,
"Strehl", CPL_TYPE_DOUBLE);
1247 cpl_table_new_column(cubetable,
"Strehl_Error", CPL_TYPE_DOUBLE);
1248 cpl_table_new_column(cubetable,
"Star_Background", CPL_TYPE_DOUBLE);
1249 cpl_table_new_column(cubetable,
"Star_Peak", CPL_TYPE_DOUBLE);
1250 cpl_table_new_column(cubetable,
"Star_Flux", CPL_TYPE_DOUBLE);
1251 cpl_table_new_column(cubetable,
"PSF_Peak_per_Flux", CPL_TYPE_DOUBLE);
1252 cpl_table_set_column_unit(cubetable,
"PSF_Peak_per_Flux",
"unitless");
1253 cpl_table_new_column(cubetable,
"Background_Noise", CPL_TYPE_DOUBLE);
1254 cpl_table_set_size(cubetable, ncube);
1257 cpl_table_set_size(cubetable, ncubetable + ncube);
1258 icubetable = ncubetable;
1262 sigmas = cpl_vector_wrap(nsigmas, psigmas);
1263 for (i = 0; i < ncube; i++) {
1264 const cpl_image * one = cpl_imagelist_get_const(cube, i);
1265 double cent_x, cent_y;
1266 double strehl, strehl_err, star_bg,star_peak, star_flux;
1267 double psf_peak, psf_flux, bg_noise;
1271 cpl_apertures_delete(apert);
1272 apert = cpl_apertures_extract(one, sigmas, &isigma);
1274 any_if(
"No object found in image %d/%d in frame %d", i+1, ncube, 1+idx);
1278 cent_x = cpl_apertures_get_centroid_x(apert, iflux);
1279 cent_y = cpl_apertures_get_centroid_y(apert, iflux);
1280 cpl_vector_set(offsx, i, cent_x);
1281 cpl_vector_set(offsy, i, cent_y);
1283 cpl_msg_debug(cpl_func,
"Detected %d/%d sigma=%g-aperture(s) (x,y)"
1284 "=(%g,%g) (%d/%d) in %d/%d-image in frame %d", iflux,
1285 (
int)cpl_apertures_get_size(apert), psigmas[isigma],
1286 cent_x, cent_y, 1+(
int)isigma, nsigmas, 1+i, ncube,
1289 cpl_table_set_int(cubetable,
"Frame", i+icubetable, 1+idx);
1290 cpl_table_set_int(cubetable,
"Plane", i+icubetable, 1+i);
1291 cpl_table_set_double(cubetable,
"XCentroid", i+icubetable, cent_x);
1292 cpl_table_set_double(cubetable,
"YCentroid", i+icubetable, cent_y);
1296 cent_x, cent_y, pixscale,
1297 &strehl, &strehl_err,
1298 &star_bg, &star_peak, &star_flux,
1299 &psf_peak, &psf_flux,
1301 cpl_msg_info(cpl_func,
"Could not compute strehl for "
1302 "image %d in frame %d", 1+i, 1+idx);
1303 cpl_errorstate_dump(prestate, CPL_FALSE,
1305 cpl_errorstate_set(prestate);
1307 cpl_table_set_invalid(cubetable,
"Strehl", i+icubetable);
1308 cpl_table_set_invalid(cubetable,
"Strehl_Error", i+icubetable);
1309 cpl_table_set_invalid(cubetable,
"Star_Background", i+icubetable);
1310 cpl_table_set_invalid(cubetable,
"Star_Peak", i+icubetable);
1311 cpl_table_set_invalid(cubetable,
"Star_Flux", i+icubetable);
1312 cpl_table_set_invalid(cubetable,
"PSF_Peak_per_Flux", i+icubetable);
1313 cpl_table_set_invalid(cubetable,
"Background_Noise", i+icubetable);
1314 cpl_vector_set(vstrehl, i, 0.0);
1317 cpl_vector_set(vstrehl, i, strehl);
1318 cpl_table_set_double(cubetable,
"Strehl", i+icubetable, strehl);
1319 cpl_table_set_double(cubetable,
"Strehl_Error", i+icubetable,
1321 cpl_table_set_double(cubetable,
"Star_Background", i+icubetable,
1323 cpl_table_set_double(cubetable,
"Star_Peak", i+icubetable,
1325 cpl_table_set_double(cubetable,
"Star_Flux", i+icubetable,
1327 cpl_table_set_double(cubetable,
"PSF_Peak_per_Flux", i+icubetable,
1329 cpl_table_set_double(cubetable,
"Background_Noise", i+icubetable,
1334 self = naco_img_jitter_saa_lucky(cube, vstrehl, offs, lucky);
1338 if (combined != NULL) {
1339 cpl_image_delete(combined[0]);
1343 cpl_bivector_delete(offs);
1344 (void)cpl_vector_unwrap(sigmas);
1345 cpl_apertures_delete(apert);
1346 cpl_vector_delete(vstrehl);
1348 cpl_ensure(
self != NULL, cpl_error_get_code(), NULL);
1366 static cpl_image * naco_img_jitter_find_sky_cube(
int isky,
int nskyplane,
1367 const cpl_array * iscube,
1368 const irplib_framelist * obj)
1371 cpl_image *
self = NULL;
1373 cpl_imagelist * belowcube = NULL;
1374 cpl_imagelist * abovecube = NULL;
1375 cpl_imagelist * skycube = NULL;
1376 cpl_imagelist * mycube = NULL;
1377 cpl_image * mysky = NULL;
1378 cpl_mask * fillbpm = NULL;
1384 bug_if(isky >= nframes);
1385 bug_if(nframes != cpl_array_get_size(iscube));
1386 if (nskyplane > 0) skip_if_lt(nskyplane, 3,
"sky planes for median");
1389 (void)cpl_array_get_int(iscube, isky, &is_invalid);
1394 for (i = isky - 1; i >= 0; i++) {
1396 (void)cpl_array_get_int(iscube, i, &is_invalid);
1398 if (!is_invalid)
break;
1404 for (i = isky + 1; i < nframes; i++) {
1406 (void)cpl_array_get_int(iscube, i, &is_invalid);
1408 if (!is_invalid)
break;
1413 cpl_msg_info(cpl_func,
"Estimating sky for cube %d/%d via cubes %d and %d",
1414 1+isky, nframes, 1+ibelow, 1+iabove);
1418 const char * filename
1421 if (nskyplane > 0) {
1423 const cpl_propertylist * plist
1426 const int istop = irplib_pfits_get_int(plist,
"NAXIS3") - 2;
1427 const int istart = NACO_MAX(0, istop - nskyplane + 1);
1429 skip_if_lt(istop - istart, 2,
"sky planes for median");
1431 belowcube = cpl_imagelist_new();
1433 for (i = istart; i <= istop; i++) {
1434 self = cpl_image_load(filename, CPL_TYPE_FLOAT, i, EXT0);
1436 any_if(
"Could not load plane %d from frame %d/%d, file=%s",
1437 1+i, 1+ibelow, nframes, filename);
1439 bug_if(cpl_imagelist_set(belowcube,
self, i - istart));
1445 belowcube = cpl_imagelist_load(filename, CPL_TYPE_FLOAT, EXT0);
1447 any_if(
"Could not load cube from frame %d/%d, file=%s",
1448 1+ibelow, nframes, filename);
1450 naxis3 = cpl_imagelist_get_size(belowcube);
1454 cpl_image_delete(cpl_imagelist_unset(belowcube, naxis3-1));
1460 if (iabove < nframes) {
1461 const char * filename
1464 if (nskyplane > 0) {
1466 const cpl_propertylist * plist
1468 const int istart = 0;
1470 const int istop = NACO_MIN(nskyplane-1, irplib_pfits_get_int
1471 (plist,
"NAXIS3") - 2);
1473 skip_if_lt(istop - istart, 2,
"sky planes for median");
1475 abovecube = cpl_imagelist_new();
1477 for (i = istart; i <= istop; i++) {
1478 self = cpl_image_load(filename, CPL_TYPE_FLOAT, i, EXT0);
1480 any_if(
"Could not load plane %d from frame %d/%d, file=%s",
1481 1+i, 1+iabove, nframes, filename);
1483 bug_if(cpl_imagelist_set(abovecube,
self, i - istart));
1490 abovecube = cpl_imagelist_load(filename, CPL_TYPE_FLOAT, EXT0);
1492 any_if(
"Could not load cube from frame %d/%d, file=%s",
1493 1+iabove, nframes, filename);
1495 naxis3 = cpl_imagelist_get_size(abovecube);
1499 cpl_image_delete(cpl_imagelist_unset(abovecube, naxis3-1));
1504 error_if(belowcube == NULL && abovecube == NULL, CPL_ERROR_DATA_NOT_FOUND,
1505 "No cube(s) available for sky estimation among %d object frames",
1508 if (belowcube == NULL) {
1509 skycube = abovecube;
1510 }
else if (abovecube == NULL) {
1511 skycube = belowcube;
1515 const int nbelow = cpl_imagelist_get_size(belowcube);
1516 const int nabove = cpl_imagelist_get_size(abovecube);
1519 skycube = cpl_imagelist_new();
1521 for (i = 0; i < nbelow; i++) {
1522 skip_if(cpl_imagelist_set(skycube, cpl_imagelist_get(belowcube, i),
1525 for (i = 0; i < nabove; i++) {
1526 skip_if(cpl_imagelist_set(skycube, cpl_imagelist_get(abovecube, i),
1529 skip_if(cpl_imagelist_get_size(skycube) != nwrap);
1530 skip_if(nbelow + nabove != nwrap);
1533 self = cpl_imagelist_collapse_median_create(skycube);
1535 #ifndef NACO_IMG_JITTER_KEEP_SKY_OBJECTS
1536 if (belowcube == NULL || abovecube == NULL) {
1538 const cpl_mask * fill2bpm;
1539 const cpl_mask * selfbpm = NULL;
1540 const double lo_skysigma = 0.2;
1541 const double hi_skysigma = 5.0;
1543 skip_if(naco_img_jitter_reject_objects(
self, lo_skysigma, hi_skysigma));
1545 selfbpm = cpl_image_get_bpm_const(
self);
1547 if (selfbpm != NULL) {
1548 const cpl_mask * mybpm;
1552 const char * filename
1556 mycube = cpl_imagelist_load(filename, CPL_TYPE_FLOAT, EXT0);
1558 any_if(
"Could not load cube from frame %d/%d, file=%s",
1559 1+isky, nframes, filename);
1561 naxis3 = cpl_imagelist_get_size(mycube);
1565 cpl_image_delete(cpl_imagelist_unset(mycube, naxis3-1));
1567 mysky = cpl_imagelist_collapse_median_create(mycube);
1569 skip_if(naco_img_jitter_reject_objects(mysky, lo_skysigma,
1575 mybpm = cpl_image_get_bpm_const(mysky);
1577 if (mybpm == NULL) {
1583 fillbpm = cpl_mask_duplicate(mybpm);
1584 bug_if(cpl_mask_not(fillbpm));
1585 bug_if(cpl_mask_and(fillbpm, selfbpm));
1590 cpl_msg_info(cpl_func,
"Filling %d object-pixels in sky image "
1591 "with %d sky-pixels from object image",
1592 (
int)cpl_mask_count(selfbpm),
1593 (
int)cpl_mask_count(fill2bpm));
1594 if (fill2bpm != selfbpm) {
1596 bug_if(cpl_image_reject_from_mask(
self, fill2bpm));
1599 if (fillbpm == NULL) {
1600 fillbpm = cpl_mask_duplicate(fill2bpm);
1601 }
else if (fillbpm != fill2bpm) {
1602 bug_if(cpl_mask_copy(fillbpm, fill2bpm, 1, 1));
1605 bug_if(cpl_image_fill_rejected(
self, 0.0));
1606 bug_if(cpl_image_accept_all(
self));
1608 bug_if(cpl_mask_not(fillbpm));
1609 bug_if(cpl_image_reject_from_mask(mysky, fillbpm));
1610 bug_if(cpl_image_fill_rejected(mysky, 0.0));
1611 bug_if(cpl_image_accept_all(mysky));
1612 bug_if(cpl_image_add(
self, mysky));
1619 if (cpl_error_get_code()) {
1620 cpl_image_delete(
self);
1625 if (skycube != belowcube && skycube != abovecube) {
1626 int nwrap = cpl_imagelist_get_size(skycube);
1630 (void)cpl_imagelist_unset(skycube, --nwrap);
1633 cpl_imagelist_delete(skycube);
1636 cpl_mask_delete(fillbpm);
1637 cpl_image_delete(mysky);
1638 cpl_imagelist_delete(mycube);
1639 cpl_imagelist_delete(belowcube);
1640 cpl_imagelist_delete(abovecube);
1659 cpl_error_code naco_img_jitter_imagelist_wrap_nocube(cpl_imagelist *
self,
1660 const cpl_array * iscube,
1661 cpl_imagelist * other)
1664 const int ncube = cpl_imagelist_get_size(other);
1665 int nwrap = cpl_imagelist_get_size(
self);
1668 bug_if(
self == NULL);
1669 bug_if(iscube == NULL);
1670 bug_if(other == NULL);
1672 bug_if(cpl_array_get_size(iscube) != ncube);
1674 for (i = 0; i < ncube; i++) {
1677 (void)cpl_array_get_int(iscube, i, &is_invalid);
1680 cpl_imagelist_set(
self, cpl_imagelist_get(other, i), nwrap);
1685 bug_if(cpl_imagelist_get_size(
self) != nwrap);
1689 return cpl_error_get_code();
1693 #ifndef NACO_IMG_JITTER_KEEP_SKY_OBJECTS
1707 static cpl_error_code naco_img_jitter_reject_objects(cpl_image *
self,
1712 double med_dist = DBL_MAX;
1713 double hi_threshold;
1714 cpl_mask * hi_objects = NULL;
1715 cpl_mask * lo_objects = NULL;
1716 cpl_mask * rejects = NULL;
1717 cpl_image * hi_label = NULL;
1718 cpl_image * lo_label = NULL;
1719 cpl_apertures * hi_apert = NULL;
1720 cpl_mask * kernel = NULL;
1723 bug_if(
self == NULL);
1724 bug_if(lo_sigma <= 0.0);
1725 bug_if(hi_sigma < lo_sigma);
1728 median = cpl_image_get_median_dev(
self, &med_dist);
1729 hi_threshold = median + hi_sigma * med_dist;
1732 hi_objects = cpl_mask_threshold_image_create(
self, hi_threshold, DBL_MAX);
1733 bug_if(hi_objects == NULL);
1737 kernel = cpl_mask_new(3, 3);
1738 bug_if(cpl_mask_not(kernel));
1739 bug_if(cpl_mask_filter(hi_objects, hi_objects, kernel, CPL_FILTER_OPENING,
1742 if (!cpl_mask_is_empty(hi_objects)) {
1746 const double lo_threshold = median + lo_sigma * med_dist;
1747 cpl_size hi_ilabel, hi_nlabel, lo_nlabel;
1750 lo_objects = cpl_mask_threshold_image_create(
self, lo_threshold, DBL_MAX);
1751 bug_if(lo_objects == NULL);
1752 bug_if(cpl_mask_filter(lo_objects, lo_objects, kernel,
1753 CPL_FILTER_OPENING, CPL_BORDER_ZERO));
1755 hi_label = cpl_image_labelise_mask_create(hi_objects, &hi_nlabel);
1756 lo_label = cpl_image_labelise_mask_create(lo_objects, &lo_nlabel);
1758 hi_apert = cpl_apertures_new_from_image(
self, hi_label);
1759 bug_if(hi_apert == NULL);
1761 for (hi_ilabel = 1; hi_ilabel <= hi_nlabel; hi_ilabel++) {
1763 const int pos_x = cpl_apertures_get_top_x(hi_apert, hi_ilabel);
1764 const int pos_y = cpl_apertures_get_top(hi_apert, hi_ilabel);
1767 const int lo_ilabel = (int)cpl_image_get(lo_label, pos_x, pos_y,
1771 cpl_mask_delete(rejects);
1772 rejects = cpl_mask_threshold_image_create(lo_label,
1773 (
double)lo_ilabel - 0.5,
1774 (
double)lo_ilabel + 0.5);
1777 cpl_mask_or(hi_objects, rejects);
1781 cpl_msg_info(cpl_func,
"Found %d object(s) of %d pixel(s) "
1782 "in sky image using sigmas %g and %g", (
int)hi_nlabel,
1783 (
int)cpl_mask_count(hi_objects), lo_sigma, hi_sigma);
1784 bug_if(cpl_image_reject_from_mask(
self, hi_objects));
1790 cpl_apertures_delete(hi_apert);
1791 cpl_image_delete(hi_label);
1792 cpl_image_delete(lo_label);
1793 cpl_mask_delete(kernel);
1794 cpl_mask_delete(hi_objects);
1795 cpl_mask_delete(lo_objects);
1796 cpl_mask_delete(rejects);
1798 return cpl_error_get_code();
1815 static cpl_image * naco_img_jitter_saa_lucky(
const cpl_imagelist * cube,
1816 const cpl_vector * strehl,
1817 const cpl_bivector * offs,
1821 cpl_image *
self = NULL;
1822 const int ncube = cpl_imagelist_get_size(cube);
1823 const int mcube = NACO_MAX(NACO_MIN(ncube, (
int)(0.5 + fraction * ncube)),
1825 cpl_imagelist * lcube = NULL;
1826 const cpl_imagelist * ucube;
1827 cpl_vector * lstrehl = mcube == ncube ? (cpl_vector*)strehl
1828 : cpl_vector_duplicate(strehl);
1831 cpl_bivector * loffs = cpl_bivector_duplicate(offs);
1832 cpl_vector * loffsx = cpl_bivector_get_x(loffs);
1833 cpl_vector * loffsy = cpl_bivector_get_y(loffs);
1834 cpl_table * tsort = NULL;
1835 cpl_propertylist * psort = NULL;
1839 bug_if(cpl_vector_get_size(strehl) != ncube);
1840 bug_if(cpl_bivector_get_size(offs) != ncube);
1841 bug_if(fraction <= 0.0);
1842 bug_if(fraction > 1.0);
1844 if (mcube < ncube) {
1848 tsort = cpl_table_new(ncube);
1849 psort = cpl_propertylist_new();
1852 bug_if(cpl_propertylist_append_bool(psort,
"LSTREHL", CPL_TRUE));
1854 bug_if(cpl_table_wrap_double(tsort, cpl_vector_get_data(lstrehl),
1856 bug_if(cpl_table_wrap_double(tsort, cpl_vector_get_data(loffsx),
1858 bug_if(cpl_table_wrap_double(tsort, cpl_vector_get_data(loffsy),
1860 bug_if(cpl_table_new_column(tsort,
"INDEX", CPL_TYPE_INT));
1863 pindex = cpl_table_get_data_int(tsort,
"INDEX");
1864 for (i = 0; i < ncube; i++) {
1868 bug_if(cpl_table_sort(tsort, psort));
1871 lcube = cpl_imagelist_new();
1874 for (i = 0; i < mcube; i++) {
1875 const int j = pindex[i];
1876 const cpl_image * image = cpl_imagelist_get_const(cube, j);
1878 cpl_imagelist_set(lcube, (cpl_image*)image, i);
1883 bug_if(cpl_vector_set_size(loffsx, mcube));
1884 bug_if(cpl_vector_set_size(loffsy, mcube));
1886 strehlmin = cpl_vector_get(lstrehl, mcube - 1);
1887 cpl_vector_delete(lstrehl);
1890 cpl_msg_info(cpl_func,
"%g%% (%d/%d) lucky mode at Strehl=%g",
1891 100.0*fraction, mcube, ncube, strehlmin);
1893 ucube = lcube ? lcube : cube;
1895 self = naco_img_jitter_saa_center(ucube, loffs);
1896 any_if(
"Could not center and saa %d-cube", ncube);
1900 if (lcube != NULL) {
1902 for (i = cpl_imagelist_get_size(lcube); i > 0;) {
1903 (void)cpl_imagelist_unset(lcube, --i);
1906 cpl_imagelist_delete(lcube);
1909 if (lstrehl != strehl)
1910 cpl_vector_delete(lstrehl);
1912 cpl_bivector_delete(loffs);
1914 if (tsort != NULL) {
1915 if (cpl_table_has_column(tsort,
"LSTREHL"))
1916 (void)cpl_table_unwrap(tsort,
"LSTREHL");
1917 if (cpl_table_has_column(tsort,
"LOFFSX"))
1918 (
void)cpl_table_unwrap(tsort,
"LOFFSX");
1919 if (cpl_table_has_column(tsort,
"LOFFSY"))
1920 (void)cpl_table_unwrap(tsort,
"LOFFSY");
1921 cpl_table_delete(tsort);
1923 cpl_propertylist_delete(psort);
1939 cpl_error_code naco_img_jitter_find_strehl(
const cpl_imagelist *
self,
1940 const cpl_parameterlist * parlist,
1941 const irplib_framelist * objframes)
1945 cpl_apertures * apert = NULL;
1946 cpl_vector * sigmas = NULL;
1947 double psigmas[] = {5.0, 2.0, 1.0, 0.5};
1948 const int nsigmas = (int)(
sizeof(psigmas)/
sizeof(double));
1954 cpl_size isigma = 0;
1958 skip_if(rbgext <= rbgint);
1960 bug_if(cpl_imagelist_get_size(
self) != nobj);
1963 sigmas = cpl_vector_wrap(nsigmas, psigmas);
1965 for (i = 0; i < nobj; i++) {
1966 const cpl_propertylist * plist
1968 const cpl_image * oimage = cpl_imagelist_get_const(
self, i);
1972 double lam = DBL_MAX;
1973 double dlam = DBL_MAX;
1975 double cent_x, cent_y;
1976 double strehl = 0, strehl_err, star_bg,star_peak, star_flux;
1977 double psf_peak, psf_flux, bg_noise;
1981 skip_if(pixscale <= 0.0);
1984 "Frame %d has no info for filter %s", 1+i, filter);
1986 cpl_apertures_delete(apert);
1987 apert = cpl_apertures_extract(oimage, sigmas, &isigma);
1989 any_if(
"No object found in combined image of frame %d", 1+i);
1993 cent_x = cpl_apertures_get_centroid_x(apert, iflux);
1994 cent_y = cpl_apertures_get_centroid_y(apert, iflux);
1997 cent_x, cent_y, pixscale,
1998 &strehl, &strehl_err,
1999 &star_bg, &star_peak, &star_flux,
2000 &psf_peak, &psf_flux,
2002 cpl_msg_info(cpl_func,
"Image of frame %d/%d has strehl=%g at (x,y)"
2003 "=(%g,%g)", 1+i, nobj, strehl, cent_x, cent_y);
2008 (void)cpl_vector_unwrap(sigmas);
2009 cpl_apertures_delete(apert);
2011 return cpl_error_get_code();
2025 static cpl_image * naco_img_jitter_saa_center(
const cpl_imagelist * cube,
2026 cpl_bivector * offs)
2029 const int ncube = cpl_imagelist_get_size(cube);
2030 cpl_image *
self = NULL;
2031 const cpl_image * image;
2032 cpl_image ** combined = NULL;
2033 cpl_imagelist * ccube = NULL;
2034 const cpl_imagelist * ucube;
2035 cpl_vector * offsx = cpl_bivector_get_x(offs);
2036 cpl_vector * offsy = cpl_bivector_get_y(offs);
2037 double * doffsx = cpl_vector_get_data(offsx);
2038 double * doffsy = cpl_vector_get_data(offsy);
2039 const double med_x = cpl_vector_get_median_const(offsx);
2040 const double med_y = cpl_vector_get_median_const(offsy);
2041 double pos_x, pos_y;
2042 double minsqdist = DBL_MAX;
2047 bug_if(cpl_bivector_get_size(offs) != ncube);
2050 for (i = 0; i < ncube; i++) {
2051 const double x = cpl_vector_get(offsx, i);
2052 const double y = cpl_vector_get(offsy, i);
2054 = (x - med_x) * (x - med_x) + (y - med_y) * (y - med_y);
2056 if (sqdist < minsqdist) {
2062 cpl_msg_info(cpl_func,
"Plane %d/%d has minimal object distance %g "
2063 "from median (x,y)=(%g,%g)", 1+imin, ncube,
2064 sqrt(minsqdist), med_x, med_y);
2070 ccube = cpl_imagelist_new();
2072 image = cpl_imagelist_get_const(cube, imin);
2073 bug_if(cpl_imagelist_set(ccube, (cpl_image*)image, 0));
2075 for (i = 0; i < imin; i++) {
2076 image = cpl_imagelist_get_const(cube, i);
2077 bug_if(cpl_imagelist_set(ccube, (cpl_image*)image, 1+i));
2079 for (i = 1+imin; i < ncube; i++) {
2080 image = cpl_imagelist_get_const(cube, i);
2081 bug_if(cpl_imagelist_set(ccube, (cpl_image*)image, i));
2084 bug_if(cpl_imagelist_get_size(ccube) != ncube);
2087 pos_x = cpl_vector_get(offsx, imin);
2088 pos_y = cpl_vector_get(offsy, imin);
2091 memmove(doffsx + 1, doffsx, (
size_t)imin *
sizeof(*doffsx));
2092 memmove(doffsy + 1, doffsy, (
size_t)imin *
sizeof(*doffsy));
2095 cpl_vector_set(offsx, 0, pos_x);
2096 cpl_vector_set(offsy, 0, pos_y);
2098 ucube = ccube ? ccube : cube;
2101 cpl_vector_subtract_scalar(offsx, cpl_vector_get(offsx, 0));
2102 cpl_vector_subtract_scalar(offsy, cpl_vector_get(offsy, 0));
2103 cpl_vector_multiply_scalar(offsx, -1.0);
2104 cpl_vector_multiply_scalar(offsy, -1.0);
2106 combined = cpl_geom_img_offset_saa(ucube, offs, CPL_KERNEL_DEFAULT,
2107 0, 0, CPL_GEOM_FIRST, &pos_x, &pos_y);
2109 any_if(
"Could not shift and add %d-cube", ncube);
2111 cpl_msg_info(cpl_func,
"Shift-and-added %d-cube, 1st pos=(%g,%g)",
2112 ncube, pos_x, pos_y);
2115 cpl_image_delete(combined[1]);
2121 if (combined != NULL) {
2122 cpl_image_delete(combined[0]);
2123 cpl_image_delete(combined[1]);
2127 if (ccube != NULL) {
2129 for (i = cpl_imagelist_get_size(ccube); i > 0;) {
2130 (void)cpl_imagelist_unset(ccube, --i);
2133 cpl_imagelist_delete(ccube);
cpl_imagelist * irplib_imagelist_load_framelist(const irplib_framelist *self, cpl_type pixeltype, int planenum, int extnum)
Load an imagelist from a framelist.
cpl_error_code naco_strehl_compute(const cpl_image *self, const cpl_parameterlist *parlist, const char *recipename, double lam, double dlam, double pos_x, double pos_y, double pixscale, double *pstrehl, double *pstrehl_err, double *pstar_bg, double *pstar_peak, double *pstar_flux, double *ppsf_peak, double *ppsf_flux, double *pbg_noise)
Compute the strehl ratio in an image.
double naco_pfits_get_pixscale(const cpl_propertylist *self)
find out the pixel scale
double naco_pfits_get_cumoffsety(const cpl_propertylist *self)
find out the cumulative offset in Y
const char * naco_pfits_get_opti4_name(const cpl_propertylist *self)
find out the OPTI4.NAME key
cpl_error_code naco_get_filter_infos(const char *f, double *lam, double *dlam)
Get the infos of one of the filters.
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
cpl_error_code irplib_apertures_find_max_flux(const cpl_apertures *self, int *ind, int nfind)
Find the aperture(s) with the greatest flux.
#define IRPLIB_STREHL_STAR_RADIUS
The radius of the star, [Arcseconds].
double naco_pfits_get_cumoffsetx(const cpl_propertylist *self)
find out the cumulative offset in X
cpl_error_code irplib_pfits_set_airmass(cpl_propertylist *self, const irplib_framelist *rawframes)
Update/Set the AIRMASS property.
irplib_framelist * irplib_framelist_extract_regexp(const irplib_framelist *self, const char *regexp, cpl_boolean invert)
Extract the frames with the given tag from a framelist.
void irplib_errorstate_dump_debug(unsigned self, unsigned first, unsigned last)
Dump a single CPL error at the CPL debug level.
int naco_parameterlist_get_int(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO integer parameter.
const cpl_propertylist * irplib_framelist_get_propertylist_const(const irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
void irplib_framelist_empty(irplib_framelist *self)
Erase all frames from a framelist.
cpl_error_code irplib_dfs_save_image(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_image *image, cpl_type_bpp bpp, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save an image as a DFS-compliant pipeline product.
cpl_error_code irplib_framelist_load_propertylist_all(irplib_framelist *self, int ind, const char *regexp, cpl_boolean invert)
Load the propertylists of all frames in the framelist.
double naco_parameterlist_get_double(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO parameter of type double.
cpl_boolean naco_parameterlist_get_bool(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO boolean parameter.
#define IRPLIB_STREHL_BACKGROUND_R2
The outer radius of the noise-estimation region, [Arcseconds].
const cpl_frame * irplib_framelist_get_const(const irplib_framelist *self, int pos)
Get the specified frame from the framelist.
const char * naco_pfits_get_opti3_name(const cpl_propertylist *self)
find out the OPTI3.NAME key
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
cpl_error_code irplib_framelist_contains(const irplib_framelist *self, const char *key, cpl_type type, cpl_boolean is_equal, double fp_tol)
Verify that a property is present for all frames.
const char * irplib_frameset_find_file(const cpl_frameset *self, const char *tag)
Find the filename with the given tag in a frame set.
#define IRPLIB_STREHL_BACKGROUND_R1
The inner radius of the noise-estimation region, [Arcseconds].
cpl_error_code irplib_framelist_load_propertylist(irplib_framelist *self, int pos, int ind, const char *regexp, cpl_boolean invert)
Load the propertylist of the specified frame in the framelist.
irplib_framelist * irplib_framelist_cast(const cpl_frameset *frameset)
Create an irplib_framelist from a cpl_framelist.
const char * naco_parameterlist_get_string(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO string parameter.
int irplib_flat_dark_bpm_calib(cpl_imagelist *ilist, const char *flat, const char *dark, const char *bpm)
Apply the calibration to the frames.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.
const char * naco_pfits_get_filter(const cpl_propertylist *self)
find out the filter