35 #include "naco_recipe.h"
36 #include "naco_strehl.h"
44 #define STREHL_MINIMUM_FLUX 100000
45 #define STREHL_MAXIMUM_PEAK 4000
46 #define STREHL_DEF_LOCATE_SX 512
47 #define STREHL_DEF_LOCATE_SY 512
49 #define RECIPE_STRING "naco_img_strehl"
55 static cpl_image * naco_img_strehl_reduce(
const cpl_parameterlist *,
56 const irplib_framelist *);
58 static cpl_error_code naco_img_strehl_qc(cpl_propertylist *,
60 const irplib_framelist *);
62 static cpl_error_code naco_img_strehl_save(cpl_frameset *,
63 const cpl_parameterlist *,
64 const cpl_propertylist *,
65 const cpl_propertylist *,
67 const irplib_framelist *,
70 NACO_RECIPE_DEFINE(naco_img_strehl,
74 "Strehl computation recipe",
75 RECIPE_STRING
" -- NACO Strehl Ratio recipe.\n"
76 "This recipe estimates the strehl ratio and its error "
77 "bound.\nThe Set Of Frames (sof-file) must specify at "
78 "least one pair of files and they must be tagged either\n"
79 "NACO-raw-file.fits " NACO_IMG_STREHL_CAL
" or\n"
80 "NACO-raw-file.fits " NACO_IMG_STREHL_TECH
"\n");
102 } naco_img_strehl_config;
123 static int naco_img_strehl(cpl_frameset * framelist,
124 const cpl_parameterlist * parlist)
126 cpl_errorstate cleanstate = cpl_errorstate_get();
127 irplib_framelist * allframes = NULL;
128 irplib_framelist * rawframes = NULL;
129 irplib_framelist * framepair = NULL;
130 cpl_frame * frame1 = NULL;
131 cpl_frame * frame2 = NULL;
132 cpl_image * img = NULL;
133 cpl_propertylist * qclist = cpl_propertylist_new();
134 cpl_propertylist * paflist = cpl_propertylist_new();
141 "Could not group the input frames");
144 skip_if(allframes == NULL);
145 irplib_check(rawframes
147 "^(" NACO_IMG_STREHL_CAL
148 "|" NACO_IMG_STREHL_TECH
150 "Could not load the raw frames");
153 naco_img_strehl_config.mode = 0;
154 if (cpl_frameset_find(framelist, NACO_IMG_STREHL_CAL))
155 naco_img_strehl_config.mode = 1;
157 if (cpl_frameset_find(framelist, NACO_IMG_STREHL_TECH)) {
158 irplib_ensure(!naco_img_strehl_config.mode, CPL_ERROR_INCOMPATIBLE_INPUT,
159 "Mixing of DO categories " NACO_IMG_STREHL_CAL
" and "
160 NACO_IMG_STREHL_TECH
"is not supported");
161 naco_img_strehl_config.mode = 2;
166 skip_if_lt(nframes, 2,
"frames");
169 cpl_msg_warning(cpl_func,
"The SOF comprises an odd number (%d) of raw "
170 "frames, ignoring the last", nframes);
178 for (i=0; i < npairs; i++) {
179 cpl_error_code error;
182 cpl_msg_info(cpl_func,
"Reducing pair %d out of %d", i+1, npairs);
189 IRPLIB_PFITS_REGEXP_RECAL
"|"
190 NACO_PFITS_REGEXP_STREHL
"|"
191 NACO_PFITS_REGEXP_STREHL_PAF
199 NACO_PFITS_REGEXP_STREHL
202 img = naco_img_strehl_reduce(parlist, framepair);
206 irplib_error_recover(cleanstate,
"Could not reduce pair number "
210 skip_if(naco_img_strehl_qc(qclist, paflist, framepair));
213 bug_if (cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
214 naco_img_strehl_config.mode
215 == 1 ? NACO_IMG_STREHL_RESCAL
216 : NACO_IMG_STREHL_RESTECH));
218 irplib_ensure(!naco_img_strehl_save(framelist, parlist, qclist,
219 paflist, img, framepair, i+1),
221 "Could not save the products of pair %d", i+1);
223 cpl_image_delete(img);
225 cpl_propertylist_empty(qclist);
226 cpl_propertylist_empty(paflist);
240 irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
241 "None of the %d pairs of frames could be reduced", npairs);
245 cpl_image_delete(img);
249 cpl_propertylist_delete(qclist);
250 cpl_propertylist_delete(paflist);
252 return cpl_error_get_code();
263 static cpl_image * naco_img_strehl_reduce(
const cpl_parameterlist * parlist,
264 const irplib_framelist * framepair)
269 const cpl_propertylist * plist1
271 const cpl_propertylist * plist2
275 cpl_image * im1 = NULL;
276 cpl_image * im2 = NULL;
279 double psigmas[] = {5.0, 2.0, 1.0, 0.5};
280 const int nsigmas = (int)(
sizeof(psigmas)/
sizeof(double));
282 cpl_vector * sigmas = NULL;
283 cpl_apertures * apert = NULL;
291 bug_if(cpl_error_get_code());
293 naco_img_strehl_config.pscale = -1.0;
294 naco_img_strehl_config.pos_x = -1.0;
295 naco_img_strehl_config.pos_y = -1.0;
296 naco_img_strehl_config.strehl = -1.0;
297 naco_img_strehl_config.strehl_err = -1.0;
298 naco_img_strehl_config.star_bg = -1.0;
299 naco_img_strehl_config.star_peak = -1.0;
300 naco_img_strehl_config.star_flux = -1.0;
301 naco_img_strehl_config.psf_peak = -1.0;
302 naco_img_strehl_config.psf_flux = -1.0;
303 naco_img_strehl_config.bg_noise = -1.0;
310 "Could not load the filter names and Pixel-scales");
312 irplib_ensure(!strcmp(sval1, sval2), CPL_ERROR_INCOMPATIBLE_INPUT,
313 "The filters in the pair are different: %s <=> %s", sval1, sval2);
315 irplib_ensure(fabs(pixscale-dval) <= 1e-3, CPL_ERROR_INCOMPATIBLE_INPUT,
316 "The pixel-scales in the pair are different: %g <=> %g",
319 naco_img_strehl_config.pscale = pixscale;
320 naco_img_strehl_config.filter = sval1;
322 cpl_msg_info(cpl_func,
"Filter: [%s]", naco_img_strehl_config.filter);
323 cpl_msg_info(cpl_func,
"Pixel scale: [%g]", naco_img_strehl_config.pscale);
326 cpl_msg_info(cpl_func,
"---> Loading the pair of input images");
327 im1 = cpl_image_load(cpl_frame_get_filename(frame1), CPL_TYPE_FLOAT, 0, 0);
329 im2 = cpl_image_load(cpl_frame_get_filename(frame2), CPL_TYPE_FLOAT, 0, 0);
333 cpl_msg_info(cpl_func,
"---> Subtracting input images");
334 skip_if(cpl_image_subtract(im1, im2));
335 cpl_image_delete(im2);
340 "Cannot get filter infos [%s]", naco_img_strehl_config.filter);
342 cpl_msg_warning(cpl_func,
"LAM=%g, DLAM=%g", lam, dlam);
344 cpl_msg_info(cpl_func,
"---> Detecting a bright star using %d sigma-levels "
345 "ranging from %g down to %g", nsigmas, psigmas[0],
347 sigmas = cpl_vector_wrap(nsigmas, psigmas);
348 irplib_check(apert = cpl_apertures_extract_window(im1, sigmas,
349 (
int)(cpl_image_get_size_x(im1)-STREHL_DEF_LOCATE_SX)/2,
350 (
int)(cpl_image_get_size_y(im1)-STREHL_DEF_LOCATE_SY)/2,
351 (
int)(cpl_image_get_size_x(im1)+STREHL_DEF_LOCATE_SX)/2,
352 (
int)(cpl_image_get_size_y(im1)+STREHL_DEF_LOCATE_SY)/2,
354 "Could not detect the star");
358 naco_img_strehl_config.pos_x = cpl_apertures_get_centroid_x(apert, iflux);
359 naco_img_strehl_config.pos_y = cpl_apertures_get_centroid_y(apert, iflux);
360 cpl_apertures_delete(apert);
362 cpl_msg_info(cpl_func,
"Star detected at sigma=%g, at position %g %g",
364 naco_img_strehl_config.pos_x,
365 naco_img_strehl_config.pos_y);
370 "Cannot get filter infos [%s]", naco_img_strehl_config.filter);
373 cpl_msg_info(cpl_func,
"---> Computing the strehl ratio");
375 naco_img_strehl_config.pos_x,
376 naco_img_strehl_config.pos_y,
377 naco_img_strehl_config.pscale,
378 &(naco_img_strehl_config.strehl),
379 &(naco_img_strehl_config.strehl_err),
380 &(naco_img_strehl_config.star_bg),
381 &(naco_img_strehl_config.star_peak),
382 &(naco_img_strehl_config.star_flux),
383 &(naco_img_strehl_config.psf_peak),
384 &(naco_img_strehl_config.psf_flux),
385 &(naco_img_strehl_config.bg_noise)),
386 "Could not compute the Strehl ratio");
389 skip_if(cpl_error_get_code());
391 cpl_msg_info(cpl_func,
"Strehl: %g", naco_img_strehl_config.strehl);
392 cpl_msg_info(cpl_func,
"Strehl error: %g", naco_img_strehl_config.strehl_err);
393 cpl_msg_info(cpl_func,
"Star bg: %g", naco_img_strehl_config.star_bg);
394 cpl_msg_info(cpl_func,
"Star peak: %g", naco_img_strehl_config.star_peak);
395 cpl_msg_info(cpl_func,
"Star flux: %g", naco_img_strehl_config.star_flux);
396 cpl_msg_info(cpl_func,
"PSF peak: %g", naco_img_strehl_config.psf_peak);
397 cpl_msg_info(cpl_func,
"PSF flux: %g", naco_img_strehl_config.psf_flux);
398 cpl_msg_info(cpl_func,
"Bg noise: %g", naco_img_strehl_config.bg_noise);
400 if (ndit*naco_img_strehl_config.star_flux < STREHL_MINIMUM_FLUX)
401 cpl_msg_warning(cpl_func,
"The Strehl may be unreliable, due to a too "
402 "low star flux: %g < %g/%d",
403 naco_img_strehl_config.star_flux,
404 (
double)STREHL_MINIMUM_FLUX, ndit);
406 if (naco_img_strehl_config.star_peak > STREHL_MAXIMUM_PEAK)
407 cpl_msg_warning(cpl_func,
"The Strehl may be unreliable, due to a too "
408 "high star peak: %g > %g",
409 naco_img_strehl_config.star_peak,
410 (
double)STREHL_MAXIMUM_PEAK);
414 cpl_image_delete(im2);
415 cpl_apertures_delete(apert);
416 cpl_vector_unwrap(sigmas);
418 if (cpl_error_get_code()) {
419 cpl_image_delete(im1);
436 static cpl_error_code naco_img_strehl_qc(cpl_propertylist * qclist,
437 cpl_propertylist * paflist,
438 const irplib_framelist * framepair)
441 cpl_errorstate cleanstate = cpl_errorstate_get();
442 const cpl_propertylist * plist1
444 const cpl_propertylist * plist2
446 const char * optiname;
449 const double almost_zero = 1e-3;
456 skip_if (cpl_propertylist_copy_property_regexp(paflist, plist1,
"^("
457 NACO_PFITS_REGEXP_STREHL_PAF
464 if (cpl_error_get_code())
465 naco_error_reset(
"Could not get FITS key:");
467 if (fabs(dval1) <= almost_zero) mean = dval2;
468 else if (fabs(dval2) <= almost_zero) mean = dval1;
469 else mean = (dval1+dval2)/2.0;
471 skip_if(cpl_propertylist_append_double(paflist,
472 "ESO AOS RTC DET DST L0MEAN", mean));
478 if (cpl_error_get_code())
479 naco_error_reset(
"Could not get FITS key:");
481 if (fabs(dval1) <= almost_zero) mean = dval2;
482 else if (fabs(dval2) <= almost_zero) mean = dval1;
483 else mean = (dval1+dval2)/2.0;
485 skip_if(cpl_propertylist_append_double(paflist,
"ESO AOS RTC DET DST T0MEAN",
492 if (cpl_error_get_code())
493 naco_error_reset(
"Could not get FITS key:");
495 if (fabs(dval1) <= almost_zero) mean = dval2;
496 else if (fabs(dval2) <= almost_zero) mean = dval1;
497 else mean = (dval1+dval2)/2.0;
499 skip_if(cpl_propertylist_append_double(paflist,
"ESO AOS RTC DET DST R0MEAN",
506 if (cpl_error_get_code())
507 naco_error_reset(
"Could not get FITS key:");
509 if (fabs(dval1) <= almost_zero) mean = dval2;
510 else if (fabs(dval2) <= almost_zero) mean = dval1;
511 else mean = (dval1+dval2)/2.0;
513 skip_if(cpl_propertylist_append_double(paflist,
"ESO AOS RTC DET DST ECMEAN",
520 if (cpl_error_get_code())
521 naco_error_reset(
"Could not get FITS key:");
523 if (fabs(dval1) <= almost_zero) mean = dval2;
524 else if (fabs(dval2) <= almost_zero) mean = dval1;
525 else mean = (dval1+dval2)/2.0;
527 skip_if(cpl_propertylist_append_double(paflist,
"ESO AOS RTC DET DST FLUXMEAN",
531 skip_if(cpl_propertylist_append_string(qclist,
"ESO QC FILTER OBS",
532 naco_img_strehl_config.filter));
535 if (cpl_error_get_code())
536 naco_error_reset(
"Could not get FITS key:");
538 skip_if(cpl_propertylist_append_string(qclist,
"ESO QC FILTER NDENS",
541 if (cpl_error_get_code())
542 naco_error_reset(
"Could not get FITS key:");
544 skip_if(cpl_propertylist_append_string(qclist,
"ESO QC FILTER POL",
550 if (cpl_error_get_code()) {
552 naco_error_reset(
"Could not get FITS key:");
554 skip_if(cpl_propertylist_append_double(qclist,
"ESO QC AIRMASS", mean));
557 cpl_propertylist_append_double(qclist,
"ESO QC STREHL",
558 naco_img_strehl_config.strehl);
559 cpl_propertylist_append_double(qclist,
"ESO QC STREHL FLUX",
560 naco_img_strehl_config.star_flux);
561 cpl_propertylist_append_double(qclist,
"ESO QC STREHL PEAK",
562 naco_img_strehl_config.star_peak);
563 cpl_propertylist_append_double(qclist,
"ESO QC STREHL ERROR",
564 naco_img_strehl_config.strehl_err);
565 cpl_propertylist_append_double(qclist,
"ESO QC STREHL RMS",
566 naco_img_strehl_config.bg_noise);
567 cpl_propertylist_append_double(qclist,
"ESO QC STREHL POSX",
568 naco_img_strehl_config.pos_x);
569 cpl_propertylist_append_double(qclist,
"ESO QC STREHL POSY",
570 naco_img_strehl_config.pos_y);
574 bug_if (cpl_propertylist_append(paflist, qclist));
576 bug_if (cpl_propertylist_copy_property_regexp(qclist, plist1,
"^("
577 IRPLIB_PFITS_REGEXP_RECAL
584 return cpl_error_get_code();
600 static cpl_error_code naco_img_strehl_save(cpl_frameset * set_tot,
601 const cpl_parameterlist * parlist,
602 const cpl_propertylist * qclist,
603 const cpl_propertylist * paflist,
604 const cpl_image * ima,
605 const irplib_framelist * framepair,
609 char * filename = NULL;
615 filename = cpl_sprintf(RECIPE_STRING
"%02d" CPL_DFS_FITS, pair_id);
617 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
618 naco_img_strehl_config.mode == 1
619 ? NACO_IMG_STREHL_RESCAL
620 : NACO_IMG_STREHL_RESTECH, qclist, NULL,
621 naco_pipe_id, filename));
625 filename = cpl_sprintf(RECIPE_STRING
"%02d" CPL_DFS_PAF, pair_id);
626 skip_if (cpl_dfs_save_paf(
"NACO", RECIPE_STRING, paflist, filename));
631 cpl_frameset_delete(rawframes);
633 return cpl_error_get_code();
cpl_frameset * irplib_frameset_cast(const irplib_framelist *self)
Create a CPL frameset from an irplib_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
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.
double naco_pfits_get_t0mean(const cpl_propertylist *self)
find out the T0MEAN key
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.
cpl_error_code irplib_framelist_set(irplib_framelist *self, cpl_frame *frame, int pos)
Add a frame to a framelist.
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.
int naco_pfits_get_ndit(const cpl_propertylist *self)
find out the NDIT keyword
double naco_pfits_get_l0mean(const cpl_propertylist *self)
find out the L0MEAN
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.
cpl_frame * irplib_framelist_unset(irplib_framelist *self, int pos, cpl_propertylist **plist)
Erase a frame from a framelist and return it to the caller.
double naco_pfits_get_airmass_start(const cpl_propertylist *self)
find out airmass start
double naco_pfits_get_fluxmean(const cpl_propertylist *self)
find out the FLUXMEAN key
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.
double naco_pfits_get_airmass_end(const cpl_propertylist *self)
find out airmass end
double naco_pfits_get_r0mean(const cpl_propertylist *self)
find out the R0MEAN key
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.
irplib_framelist * irplib_framelist_new(void)
Create an empty framelist.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.
double naco_pfits_get_ecmean(const cpl_propertylist *self)
find out the ECMEAN key
cpl_error_code irplib_framelist_erase(irplib_framelist *self, int pos)
Erase a frame from a framelist and delete it and its propertylist.
const char * naco_pfits_get_filter(const cpl_propertylist *self)
find out the filter