30#include <eris_ifu_strehl.h>
31#include <eris_ifu_jitter_interface.h>
32#include <eris_ifu_wavecal_static.h>
33#include <eris_utils.h>
34#include <eris_pfits.h>
35#include <eris_ifu_utils.h>
42#define ERIS_IFU_RAW_BPM "RAW_BPM"
43#define ERIS_IFU_RAW_ERROR "RAW_ERROR"
54#define HDRL_PARAMETER_HEAD void * base
62} hdrl_rect_region_parameter;
76static cpl_error_code eris_ifu_propertylist_save(
78 const char * filename,
79 const cpl_propertylist * header,
80 const cpl_parameterlist * parlist,
81 cpl_frameset * frameset)
84 cpl_propertylist * applist = cpl_propertylist_new();
87 cpl_propertylist_update_string(applist, CPL_DFS_PRO_CATG, procatg);
89 cpl_dfs_save_propertylist(frameset, NULL, parlist, frameset, NULL,
90 "ERIS_IFU_STREHL", header, NULL, PACKAGE
"/" PACKAGE_VERSION,
92 cpl_propertylist_delete(applist);
94 return cpl_error_get_code();
112 hdrl_parameter * rect_region,
116 hdrl_rect_region_parameter * rr_loc =
117 (hdrl_rect_region_parameter *)rect_region ;
119 cpl_error_ensure(rect_region != 0, CPL_ERROR_NULL_INPUT,
120 return CPL_ERROR_NULL_INPUT,
"region input must not be NULL");
122 CPL_ERROR_ILLEGAL_INPUT,
return CPL_ERROR_ILLEGAL_INPUT,
123 "Expected Rect Region parameter") ;
125 if (nx > 0 && rr_loc->llx < 1) rr_loc->llx += nx;
126 if (ny > 0 && rr_loc->lly < 1) rr_loc->lly += ny;
127 if (nx > 0 && rr_loc->urx < 1) rr_loc->urx += nx;
128 if (ny > 0 && rr_loc->ury < 1) rr_loc->ury += ny;
156eris_ifu_detector_shotnoise_model(
const cpl_image* ima_data,
const double gain,
157 const double ron, cpl_image ** ima_errs)
159 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
160 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
161 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
162 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
164 *ima_errs = cpl_image_duplicate(ima_data);
166 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
170 cpl_image_divide_scalar(*ima_errs, gain);
171 cpl_image_add_scalar(*ima_errs, ron * ron);
172 cpl_image_power(*ima_errs, 0.5);
174 return cpl_error_get_code();
190eris_ifu_fix_neg_region(
const cpl_frame * frm, cpl_size extnum,
191 hdrl_parameter * par)
193 cpl_propertylist * plist =
194 cpl_propertylist_load(cpl_frame_get_filename(frm), extnum);
196 return cpl_error_get_code();
201 cpl_propertylist_delete(plist);
203 return cpl_error_get_code();
215static cpl_image * eris_ifu_image_mef_load_region(
218 hdrl_parameter * region_params)
220 cpl_image * out = NULL ;
222 if (region_params == NULL) {
223 out = cpl_image_load(cpl_frame_get_filename(frm),
224 CPL_TYPE_DOUBLE, 0, eidx);
226 eris_ifu_fix_neg_region(frm, eidx, region_params);
227 out = cpl_image_load_window(cpl_frame_get_filename(frm),
228 CPL_TYPE_DOUBLE, 0, eidx,
256static cpl_error_code eris_ifu_hdrl_image_load(
260 cpl_size ext_num_err,
262 cpl_size ext_num_bpm,
263 hdrl_parameter * region_params,
266 hdrl_image ** out_hdrl_ima)
271 cpl_ensure_code(in, CPL_ERROR_NULL_INPUT);
272 cpl_ensure_code(out_hdrl_ima, CPL_ERROR_NULL_INPUT);
275 img = eris_ifu_image_mef_load_region(in, ext_num, region_params);
276 if (img == NULL)
return CPL_ERROR_ILLEGAL_INPUT ;
279 if (in_bpm != NULL) {
280 cpl_image * bpm = eris_ifu_image_mef_load_region(in_bpm, ext_num_bpm, region_params);
281 cpl_mask * bpm_mask = cpl_mask_threshold_image_create(bpm,
283 cpl_image_delete(bpm) ;
284 cpl_mask_not(bpm_mask) ;
285 cpl_image_reject_from_mask(img, bpm_mask);
286 cpl_mask_delete(bpm_mask) ;
290 cpl_image * err =NULL;
291 if (in_err != NULL) {
292 err = eris_ifu_image_mef_load_region(in_err, ext_num_err, region_params);
293 }
else if (ron < 0. && gain < 0.) {
298 eris_ifu_detector_shotnoise_model(img, gain, ron, &err);
305 cpl_image_delete(img);
306 cpl_image_delete(err);
308 return cpl_error_get_code();
358eris_ifu_strehl_compute(cpl_frameset * frameset,
const cpl_parameterlist * parlist,
359 const char* recipe_name)
365 hdrl_strehl_result res;
368 cpl_frame * err_frm ;
369 cpl_frame * bpm_frm ;
371 hdrl_parameter * region_params = NULL;
373 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
374 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
375 cpl_ensure_code(recipe_name, CPL_ERROR_NULL_INPUT);
378 return cpl_error_get_code();
406 return cpl_error_set_message(cpl_func, CPL_ERROR_UNSPECIFIED,
407 "Parsing of the strehl parameters failed");
422 if ((in_frm = cpl_frameset_find(frameset, ERIS_IFU_PRO_JITTER_CUBE))==NULL) {
425 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
432 const char* fname = cpl_frame_get_filename(in_frm);
433 cpl_image* in_ima = cpl_image_load(fname,CPL_TYPE_FLOAT, 0, 0);
434 sx = cpl_image_get_size_x(in_ima);
435 sy = cpl_image_get_size_y(in_ima);
438 cpl_propertylist* plist = cpl_propertylist_load(fname,0);
439 double ron = cpl_propertylist_get_double(plist,
"ESO DET CHIP RON");
440 double gain = cpl_propertylist_get_double(plist,
"ESO DET CHIP GAIN");
441 cpl_propertylist_delete(plist);
442 cpl_image_delete(in_ima);
445 if (eris_ifu_hdrl_image_load(in_frm, extnum_raw, err_frm, extnum_err,
446 bpm_frm, extnum_bpm, region_params, ron, gain,
447 &hima) != CPL_ERROR_NONE) {
450 return cpl_error_set_message(cpl_func, CPL_ERROR_FILE_NOT_FOUND,
451 "Cannot load RAW image");
471 cpl_msg_info(cpl_func,
"Handles NANs");
476 cpl_msg_info(cpl_func,
"strehl=%g+-%g", res.strehl_value.data,
477 res.strehl_value.error);
479 cpl_msg_info(cpl_func,
"star peak at %g/%g: %g +- %g", res.star_x,
480 res.star_y, res.star_peak.data, res.star_peak.error);
481 cpl_msg_info(cpl_func,
"star flux %g+-%g", res.star_flux.data,
482 res.star_flux.error);
483 cpl_msg_info(cpl_func,
"median estimated background=%g+-%g "
484 "(computed error %g)",
485 res.star_background.data, res.star_background.error,
486 res.computed_background_error);
487 cpl_propertylist* header=cpl_propertylist_new();
488 cpl_propertylist_update_double(header,
"ESO QC STREHL",
489 res.strehl_value.data);
490 cpl_propertylist_update_double(header,
"ESO QC STREHL ERROR",
491 res.strehl_value.error);
492 cpl_propertylist_update_string(header, CPL_DFS_PRO_CATG,
"ERIS_IFU_STREHL");
494 eris_ifu_propertylist_save(
"ERIS_IFU_STREHL",
"eris_ifu_strehl.fits", header,
499 cpl_propertylist_delete(header);
503 return cpl_error_get_code();
518eris_ifu_stdstar_strehl_compute(cpl_frameset * frameset,
519 const cpl_parameterlist * parlist,
527 hdrl_strehl_result res;
529 cpl_frame * in_frm = NULL ;
530 cpl_frame * err_frm ;
531 cpl_frame * bpm_frm ;
533 hdrl_parameter * region_params = NULL;
534 char* param_name = NULL;
536 double wavelength = 0;
538 double pixel_scale_x = 0;
539 double pixel_scale_y = 0;
540 double flux_radius_pix = 1;
541 double bkg_radius_low = 1;
542 double bkg_radius_high = 1.5;
544 cpl_ensure_code(frameset,CPL_ERROR_NULL_INPUT);
545 cpl_ensure_code(parlist,CPL_ERROR_NULL_INPUT);
546 cpl_ensure_code(context,CPL_ERROR_NULL_INPUT);
548 param_name = cpl_sprintf(
"%s.strehl_flux_radius", context);
549 flux_radius_pix = cpl_parameter_get_double(
550 cpl_parameterlist_find_const(parlist, param_name));
551 cpl_free(param_name);
554 param_name = cpl_sprintf(
"%s.strehl_bkg-radius-low", context);
555 bkg_radius_low = cpl_parameter_get_double(
556 cpl_parameterlist_find_const(parlist, param_name));
557 cpl_free(param_name);
560 param_name = cpl_sprintf(
"%s.strehl_bkg-radius-high", context);
561 bkg_radius_high = cpl_parameter_get_double(
562 cpl_parameterlist_find_const(parlist, param_name));
563 cpl_free(param_name);
566 ifsBand band = UNDEFINED_BAND;
567 ifsPreopticsScale scale = UNDEFINED_SCALE;
568 ifsInstrument instrument = UNSET_INSTRUMENT;
569 eris_ifu_jitter_get_instrument_settings(frameset, &instrument, &band, &scale);
573 pixel_scale_x = 0.250;
577 pixel_scale_x = 0.100;
581 pixel_scale_x = 0.025;
584 case UNDEFINED_SCALE:
585 pixel_scale_x = 0.025;
589 pixel_scale_x = 0.100;
592 eris_ifu_get_central_lambda(band, &wavelength);
594 pixel_scale_y = pixel_scale_x;
595 cpl_msg_info(cpl_func,
"pixel_scale: %g [arcsec]",pixel_scale_x);
599 cpl_frame* std_flux_frm;
602 std_frm = cpl_frameset_find(frameset, ERIS_IFU_PRO_JITTER_STD_CUBE_COADD_MEDIAN);
603 std_flux_frm = cpl_frameset_find(frameset, ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD_MEDIAN);
604 psf_frm = cpl_frameset_find(frameset, ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD_MEDIAN);
605 if ( (std_frm == NULL) && (psf_frm == NULL) && (std_flux_frm == NULL)) {
606 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
607 "Missing ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD_MEDIAN file, Cannot compute Strehl,");
609 if(std_frm != NULL) {
611 }
else if(psf_frm != NULL) {
613 }
else if(std_flux_frm != NULL) {
614 in_frm = std_flux_frm;
618 cpl_propertylist* plist = cpl_propertylist_load(cpl_frame_get_filename(in_frm),0);
622 if(cpl_propertylist_has(plist,
"ESO QC FWHM MAJ")) {
623 fwhm_maj = cpl_propertylist_get_double(plist,
"ESO QC FWHM MAJ");
625 if(cpl_propertylist_has(plist,
"ESO QC FWHMX")) {
626 fwhm_maj = cpl_propertylist_get_double(plist,
"ESO QC FWHMX");
631 if(cpl_propertylist_has(plist,
"ESO QC FWHM MIN")) {
632 fwhm_min = cpl_propertylist_get_double(plist,
"ESO QC FWHM MIN");
634 if(cpl_propertylist_has(plist,
"ESO QC FWHMY")) {
635 fwhm_min = cpl_propertylist_get_double(plist,
"ESO QC FWHMY");
640 cpl_propertylist_delete(plist);
643 double fwhm_sup = (fwhm_maj > fwhm_min) ? fwhm_maj : fwhm_min;
644 if(flux_radius_pix == -1) {
645 cpl_msg_info(cpl_func,
"pipeline setting flux_radius_pix: 3 * PSF sigmas");
646 flux_radius_pix = 3. * fwhm_sup / CPL_MATH_FWHM_SIG;
648 cpl_msg_info(cpl_func,
"flux_radius_pix: %g",flux_radius_pix);
649 double flux_radius_arc = flux_radius_pix * pixel_scale_x;
651 if(bkg_radius_low == -1) {
652 cpl_msg_info(cpl_func,
"pipeline setting bkg_radius_low: 1.5 * flux_radius");
653 bkg_radius_low = 1.5 * flux_radius_arc;
655 bkg_radius_low *= pixel_scale_x;
658 if(bkg_radius_high == -1) {
659 cpl_msg_info(cpl_func,
"pipeline setting bkg_radius_high: 2.0 * flux_radius");
660 bkg_radius_high = 2.0 * flux_radius_arc;
662 bkg_radius_high *= pixel_scale_x;
665 cpl_msg_info(cpl_func,
"flux_radius: %g [arcsec] bkg_radius_low: %g [arcsec] bkg_radius_high: %g [arcsec]",
666 flux_radius_arc, bkg_radius_low,bkg_radius_high);
668 cpl_msg_info(cpl_func,
"flux_radius: %g [pix] bkg_radius_low: %g [pix] bkg_radius_high: %g [pix]",
669 flux_radius_arc / pixel_scale_x,bkg_radius_low / pixel_scale_x,bkg_radius_high / pixel_scale_x);
673 std_frm = cpl_frameset_find(frameset, ERIS_IFU_PRO_JITTER_STD_CUBE_MEAN);
674 psf_frm = cpl_frameset_find(frameset, ERIS_IFU_PRO_JITTER_PSF_CUBE_MEAN);
675 std_flux_frm = cpl_frameset_find(frameset, ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_MEAN);
676 if ( (std_frm == NULL) && (std_flux_frm == NULL) && (psf_frm == NULL) ) {
678 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
679 "Missing ERIS_IFU_PRO_JITTER_PSF_CUBE_MEAN file, Cannot compute Strehl,");
681 if(std_frm != NULL) {
683 }
else if(psf_frm != NULL) {
690 const char* fname = cpl_frame_get_filename(in_frm);
691 cpl_msg_info(cpl_func,
"strehl computed on: %s",fname);
692 cpl_image* in_ima = cpl_image_load(fname,CPL_TYPE_FLOAT, 0, 1);
694 sx = cpl_image_get_size_x(in_ima);
695 sy = cpl_image_get_size_y(in_ima);
699 plist = cpl_propertylist_load(fname,0);
700 double ron = cpl_propertylist_get_double(plist,
"ESO DET CHIP RON");
701 double gain = cpl_propertylist_get_double(plist,
"ESO DET CHIP GAIN");
704 cpl_image_delete(in_ima);
708 if (eris_ifu_hdrl_image_load(in_frm, extnum_raw, err_frm, extnum_err,
709 bpm_frm, extnum_bpm, region_params, ron, gain,
710 &hima) != CPL_ERROR_NONE) {
713 return cpl_error_set_message(cpl_func, CPL_ERROR_FILE_NOT_FOUND,
714 "Cannot load RAW image");
724 cpl_size margin_x = 4;
725 cpl_size margin_y = 4;
726 cpl_size llx = margin_x;
727 cpl_size lly = margin_y;
728 cpl_size urx = sx - margin_x;
729 cpl_size ury = sy - margin_y;
732 cpl_msg_info(cpl_func,
"Image max detected at cx: %lld, cy: %lld",cx, cy);
737 cpl_msg_info(cpl_func,
"check Strehl parameters");
742 res.strehl_value.data = 0;
743 res.strehl_value.error = 0;
745 cpl_msg_info(cpl_func,
"wavelength: %g M1: %g M2: %g",wavelength, M1_RADIUS,M2_RADIUS);
746 cpl_msg_info(cpl_func,
"flux_radius_pix: %g cx: %lld cy: %lld sx: %d sy:%d",flux_radius_pix, cx, cy, sx, sy);
747 if( (flux_radius_pix + cx) > (sx -2) ||
748 (flux_radius_pix + cy) > (sy -2) ||
749 (cx-flux_radius_pix) < 2 ||
750 (cy-flux_radius_pix) < 2){
752 cpl_msg_info(cpl_func,
"correct Strehl parameters");
753 flux_radius_pix = ( (flux_radius_pix + cx) > (sx -2) ) ? flux_radius_pix : sx -2;
754 flux_radius_pix = ( (flux_radius_pix + cy) > (sy -2) ) ? flux_radius_pix : sy -2;
755 flux_radius_pix = ( (cx - flux_radius_pix) < 2 ) ? cx -2 : flux_radius_pix;
756 flux_radius_pix = ( (cy - flux_radius_pix) < 2 ) ? cy -2 : flux_radius_pix;
758 flux_radius_arc = flux_radius_pix * pixel_scale_x;
759 bkg_radius_low = flux_radius_arc;
760 bkg_radius_high = (flux_radius_pix + 1) * pixel_scale_x;
761 cpl_msg_info(cpl_func,
"flux_radius: %g bkg_radius_low: %g bkg_radius_high: %g",
762 flux_radius_arc ,bkg_radius_low ,bkg_radius_high );
764 if(bkg_radius_low > 0) {
766 M1_RADIUS, M2_RADIUS, pixel_scale_x, pixel_scale_y,
767 flux_radius_arc, bkg_radius_low, bkg_radius_high) ;
772 cpl_msg_warning(cpl_func,
"bkg_radius_low: %g. Skip Strehl computation.", bkg_radius_low);
779 flux_radius_arc = flux_radius_pix * pixel_scale_x;
780 cpl_msg_info(cpl_func,
"flux_radius_pix: %g",flux_radius_pix);
781 if(bkg_radius_low > 0) {
783 M1_RADIUS, M2_RADIUS, pixel_scale_x, pixel_scale_y,
784 flux_radius_arc, bkg_radius_low, bkg_radius_high) ;
788 cpl_msg_info(cpl_func,
"strehl=%g+-%g", res.strehl_value.data,
789 res.strehl_value.error);
791 cpl_msg_warning(cpl_func,
"bkg_radius_low: %g. Skip Strehl computation.", bkg_radius_low);
799 if(cpl_error_get_code() != CPL_ERROR_NONE) {
800 cpl_msg_error(cpl_func,
"Error computing Strehl. Temporarily suppress it.");
801 cpl_error_set(cpl_func,CPL_ERROR_NONE);
803 return CPL_ERROR_NONE;
805 if (res.strehl_value.data > 0) {
807 cpl_msg_info(cpl_func,
"strehl=%g+-%g", res.strehl_value.data,
808 res.strehl_value.error);
810 cpl_msg_info(cpl_func,
"star peak at %g/%g: %g +- %g", res.star_x,
811 res.star_y, res.star_peak.data, res.star_peak.error);
812 cpl_msg_info(cpl_func,
"star flux %g+-%g", res.star_flux.data,
813 res.star_flux.error);
814 cpl_msg_info(cpl_func,
"median estimated background=%g+-%g "
815 "(computed error %g)",
816 res.star_background.data, res.star_background.error,
817 res.computed_background_error);
819 double qc_strehl = 0;
820 double qc_strehl_err = 0;
821 if(isnan(res.strehl_value.data)){
825 qc_strehl=res.strehl_value.data;
826 qc_strehl_err=res.strehl_value.error;
829 cpl_image* data = cpl_image_load(fname, CPL_TYPE_DOUBLE, 0, extnum_raw);
831 cpl_image* errs = cpl_image_load(fname, CPL_TYPE_DOUBLE, 0, extnum_err);
832 cpl_propertylist* eheader = cpl_propertylist_load(fname, extnum_err);
835 cpl_image* qual = cpl_image_load(fname, CPL_TYPE_INT, 0, extnum_bpm);
836 cpl_propertylist* qheader = cpl_propertylist_load(fname, extnum_bpm);
840 cpl_propertylist_append_double(plist,
"ESO QC STREHL", qc_strehl);
841 cpl_propertylist_append_double(plist,
"ESO QC STREHL ERROR", qc_strehl_err);
842 cpl_image_save(data, fname, CPL_TYPE_DOUBLE, plist, CPL_IO_DEFAULT);
850 cpl_image_save(errs, fname, CPL_TYPE_DOUBLE, eheader, CPL_IO_EXTEND);
851 cpl_image_save(qual, fname, CPL_TYPE_INT, qheader, CPL_IO_EXTEND);
852 cpl_image_delete(data);
853 cpl_image_delete(errs);
854 cpl_image_delete(qual);
856 cpl_propertylist_delete(eheader);
857 cpl_propertylist_delete(qheader);
861 cpl_propertylist_delete(plist);
867 return cpl_error_get_code();
cpl_error_code eris_ifu_dfs_set_groups(cpl_frameset *self)
Set the group as RAW or CALIB in a frameset.
cpl_error_code eris_ifu_mask_nans_in_hdrlimage(hdrl_image **hima)
Flag NANs in image.
int eris_pfits_get_naxis2(const cpl_propertylist *plist)
find out the character string associated to the NAXIS2 keyword
int eris_pfits_get_naxis1(const cpl_propertylist *plist)
find out the character string associated to the NAXIS1 keyword
cpl_error_code eris_check_error_code(const char *func_id)
handle CPL errors
hdrl_image * hdrl_image_create(const cpl_image *image, const cpl_image *error)
create a new hdrl_image from to existing images by copying them
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
void hdrl_parameter_delete(hdrl_parameter *obj)
shallow delete of a parameter
hdrl_strehl_result hdrl_strehl_compute(const hdrl_image *himg, hdrl_parameter *params)
This function computes the Strehl ratio.
hdrl_parameter * hdrl_strehl_parameter_create(double wavelength, double m1_radius, double m2_radius, double pixel_scale_x, double pixel_scale_y, double flux_radius, double bkg_radius_low, double bkg_radius_high)
Creates Strehl Parameters object.
hdrl_parameter * hdrl_strehl_parameter_parse_parlist(const cpl_parameterlist *parlist, const char *prefix)
Parse parameter list to create input parameters for the Strehl.
cpl_error_code hdrl_rect_region_parameter_verify(const hdrl_parameter *param, const cpl_size max_x, const cpl_size max_y)
Verify basic correctness of the parameters.
cpl_error_code hdrl_rect_region_fix_negatives(hdrl_parameter *rect_region, const cpl_size nx, const cpl_size ny)
wrap negative or zero coordinates around full image size
hdrl_parameter * hdrl_rect_region_parameter_create(cpl_size llx, cpl_size lly, cpl_size urx, cpl_size ury)
Creates Rect Region Parameters object.
cpl_size hdrl_rect_region_get_llx(const hdrl_parameter *p)
get lower left x coordinate of rectangual region
cpl_size hdrl_rect_region_get_urx(const hdrl_parameter *p)
get upper right x coordinate of rectangular region
cpl_size hdrl_rect_region_get_lly(const hdrl_parameter *p)
get lower left y coordinate of rectangual region
cpl_size hdrl_rect_region_get_ury(const hdrl_parameter *p)
get upper right y coordinate of rectangual region
cpl_boolean hdrl_rect_region_parameter_check(const hdrl_parameter *self)
Check that the parameter is hdrl_rect_region parameter.