naco_img_checkfocus.c

00001 /* $Id: naco_img_checkfocus.c,v 1.59 2011-12-22 11:09:36 llundin Exp $
00002  *
00003  * This file is part of the NACO Pipeline
00004  * Copyright (C) 2002,2003 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: llundin $
00023  * $Date: 2011-12-22 11:09:36 $
00024  * $Revision: 1.59 $
00025  * $Name: not supported by cvs2svn $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include "naco_recipe.h"
00037 #include "irplib_strehl.h"
00038 
00039 /*-----------------------------------------------------------------------------
00040                                 Define
00041  -----------------------------------------------------------------------------*/
00042 
00043 #define STREHL_DEF_LOCATE_SX            512
00044 #define STREHL_DEF_LOCATE_SY            512
00045 #define ENERGY_RADIUS_PIX               11
00046 
00047 #define RECIPE_STRING "naco_img_checkfocus"
00048 
00049 /*-----------------------------------------------------------------------------
00050                             Private Functions prototypes
00051  -----------------------------------------------------------------------------*/
00052 
00053 static cpl_error_code naco_img_checkfocus_reduce(const cpl_parameterlist *,
00054                                                  const irplib_framelist *, int,
00055                                                  const cpl_image *, double *,
00056                                                  double *, double *, double *,
00057                                                  double *);
00058 
00059 static cpl_error_code naco_img_checkfocus_qc(cpl_propertylist *,
00060                                              const irplib_framelist *);
00061 
00062 static cpl_error_code naco_img_checkfocus_save(cpl_frameset *,
00063                                                const cpl_parameterlist *,
00064                                                const cpl_propertylist *);
00065 
00066 NACO_RECIPE_DEFINE(naco_img_checkfocus,
00067     NACO_PARAM_PLOT    |                        
00068     NACO_PARAM_STAR_R  |                        
00069     NACO_PARAM_BG_RINT |                        
00070     NACO_PARAM_BG_REXT,
00071     "Focus check recipe",
00072     RECIPE_STRING " -- The focus checking recipe\n"        
00073     "The Set Of Frames (sof-file) must specify at least four "  
00074     "files and they must be tagged\n"                           
00075     "NACO-raw-file.fits "NACO_IMG_CHECKFOCUS_RAW"\n"            
00076     "The first of the files is used as a dark frame.\n");
00077 
00078 /*----------------------------------------------------------------------------*/
00082 /*----------------------------------------------------------------------------*/
00083 
00084 /*-----------------------------------------------------------------------------
00085                                 Functions code
00086  -----------------------------------------------------------------------------*/
00087 
00088 /*----------------------------------------------------------------------------*/
00095 /*----------------------------------------------------------------------------*/
00096 static int naco_img_checkfocus(cpl_frameset            * framelist,
00097                                const cpl_parameterlist * parlist)
00098 {
00099     cpl_errorstate cleanstate = cpl_errorstate_get();
00100     irplib_framelist * allframes = NULL;
00101     irplib_framelist * rawframes = NULL;
00102     cpl_propertylist * qclist = cpl_propertylist_new();
00103     cpl_image        * dark = NULL;
00104     cpl_vector       * strehl_vec = NULL;
00105     cpl_matrix       * focus_mat = NULL;
00106     cpl_vector       * focus_res = NULL;
00107     cpl_polynomial   * fit_poly = NULL;
00108     const char       * darkfile;
00109     int                nframes;
00110     int                nb_good;
00111     const cpl_size     degree1 = 1;
00112     const cpl_size     degree2 = 2;
00113     double             best_strehl = DBL_MAX; /* Avoid (false) uninit warning */
00114     double             c1, c2;
00115     double             optimal_focus, optimal_strehl, mse2, mse1;
00116     int                i;
00117 
00118     /* Identify the RAW and CALIB frames in the input frameset */
00119     skip_if (naco_dfs_set_groups(framelist));
00120 
00121     allframes = irplib_framelist_cast(framelist);
00122     skip_if(allframes == NULL);
00123 
00124     rawframes = irplib_framelist_extract(allframes, NACO_IMG_CHECKFOCUS_RAW);
00125     skip_if(rawframes == NULL);
00126     irplib_framelist_empty(allframes);
00127 
00128     nframes = irplib_framelist_get_size(rawframes);
00129     irplib_ensure(nframes >= 4, CPL_ERROR_DATA_NOT_FOUND,
00130                   "Must have at least 4 (not %d) frames to check the focus",
00131                    nframes);
00132    
00133     skip_if(irplib_framelist_load_propertylist(rawframes, 0, 0, "^("
00134                                                NACO_PFITS_REGEXP_CHECKFOCUS "|"
00135                                                NACO_PFITS_REGEXP_CHECKFOCUS_PAF
00136                                                ")$", CPL_FALSE));
00137 
00138     skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
00139                                                    NACO_PFITS_REGEXP_CHECKFOCUS
00140                                                    ")$", CPL_FALSE));
00141 
00142     /* The dark is the first frame */
00143     cpl_msg_info(cpl_func, "The first frame is used as a dark");
00144     darkfile = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, 0));
00145     skip_if (0);
00146 
00147     irplib_check(dark = cpl_image_load(darkfile, CPL_TYPE_FLOAT, 0, 0),
00148                  "Could not load the dark from %s", darkfile);
00149 
00150     /* Allocate vectors to store results */
00151     strehl_vec = cpl_vector_new(nframes-1);
00152     focus_mat  = cpl_matrix_new(1, nframes-1);
00153     
00154     skip_if (naco_img_checkfocus_qc(qclist, rawframes));
00155 
00156     /* Reduce each frame */
00157     nb_good = 0;
00158     for (i=1 ; i < nframes ; i++) {
00159         double focus = DBL_MAX; /* Avoid (false) uninit warning */
00160         double energy = DBL_MAX; /* Avoid (false) uninit warning */
00161         double fwhm = DBL_MAX; /* Avoid (false) uninit warning */
00162         double strehl, strehl_err;
00163 
00164         cpl_msg_info(cpl_func, "Reducing frame %d of %d\n", i+1, nframes);
00165 
00166         /* Reduce frame nb i */
00167         if (naco_img_checkfocus_reduce(parlist, rawframes, i, dark,
00168                                       &fwhm, &strehl, &strehl_err,
00169                                        &energy, &focus)) {
00170             naco_error_reset("Could not compute focus for this frame:");
00171             continue;
00172         }
00173 
00174         /* Keep only the values where strehl_err < 10% */
00175         if (strehl_err >= 0.1) continue;
00176 
00177         /* Assign the results in the vectors */
00178         bug_if (cpl_vector_set(strehl_vec,   nb_good, strehl));
00179         bug_if (cpl_matrix_set(focus_mat, 0, nb_good, focus));
00180 
00181         nb_good++;
00182 
00183         if (nb_good > 1 && strehl <= best_strehl) continue;
00184 
00185         /* Found the best FOCUS */
00186         best_strehl = strehl;
00187 
00188         /* Add/Update QC parameters */
00189         bug_if(cpl_propertylist_update_double(qclist, "ESO QC STREHL", strehl));
00190         bug_if(cpl_propertylist_update_double(qclist, "ESO QC STREHL ERROR",
00191                                               strehl_err));
00192         bug_if(cpl_propertylist_update_double(qclist, "ESO QC FWHM PIX", fwhm));
00193         bug_if(cpl_propertylist_update_double(qclist, "ESO QC ENERGY", energy));
00194         bug_if(cpl_propertylist_update_double(qclist, "ESO QC FOCUS", focus));
00195 
00196 
00197     }
00198     cpl_image_delete(dark);
00199     dark = NULL;
00200     irplib_framelist_empty(rawframes);
00201 
00202     skip_if_lt (nb_good, 3, "frames with a Strehl error less than 0.1");
00203 
00204     bug_if (cpl_vector_set_size(strehl_vec,   nb_good));
00205     bug_if (cpl_matrix_set_size(focus_mat, 1, nb_good));
00206 
00207     /* Fit the optimal focus - and make sure it is well-defined */
00208     focus_res  = cpl_vector_new(nb_good);
00209     fit_poly = cpl_polynomial_new(1);
00210     skip_if(cpl_polynomial_fit(fit_poly, focus_mat, NULL, strehl_vec, NULL,
00211                                CPL_FALSE, NULL, &degree1));
00212 
00213     bug_if(cpl_vector_fill_polynomial_fit_residual(focus_res, strehl_vec, NULL,
00214                                                    fit_poly, focus_mat, NULL));
00215     mse1 = cpl_vector_product(focus_res, focus_res) / nb_good;
00216 
00217     skip_if(cpl_polynomial_fit(fit_poly, focus_mat, NULL, strehl_vec, NULL,
00218                                CPL_FALSE, NULL, &degree2));
00219 
00220     bug_if(cpl_vector_fill_polynomial_fit_residual(focus_res, strehl_vec, NULL,
00221                                                    fit_poly, focus_mat, NULL));
00222     mse2 = cpl_vector_product(focus_res, focus_res) / nb_good;
00223 
00224     cpl_vector_delete(focus_res);
00225     focus_res = NULL;
00226     cpl_vector_delete(strehl_vec);
00227     strehl_vec = NULL;
00228     cpl_matrix_delete(focus_mat);
00229     focus_mat = NULL;
00230 
00231     c1 = cpl_polynomial_get_coeff(fit_poly, &degree1);
00232     c2 = cpl_polynomial_get_coeff(fit_poly, &degree2);
00233 
00234     irplib_ensure(mse2 < mse1, CPL_ERROR_DATA_NOT_FOUND,
00235                   "Ill-defined optimal focus, the strehl ratio "
00236                    "appears to be a linear function of the focus value: "
00237                    "mse(2)=%g >= mse(1)=%g (c1=%g, c2=%g)",
00238                    mse2, mse1, c1, c2);
00239 
00240     bug_if (c2 == 0.0);
00241 
00242     irplib_ensure(c2 < 0.0, CPL_ERROR_DATA_NOT_FOUND,
00243                   "Ill-defined optimal focus, the strehl ratio "
00244                    "does not have a single optimal value: mse(2)=%g, c1=%g, "
00245                    "c2=%g > 0", mse2, c1, c2);
00246 
00247     optimal_focus = -c1/(2.0*c2);
00248 
00249     /* Could compute derivate as well, to check that it is close to zero */
00250     optimal_strehl = cpl_polynomial_eval_1d(fit_poly, optimal_focus, NULL);
00251 
00252     cpl_polynomial_delete(fit_poly);
00253     fit_poly = NULL;
00254 
00255     cpl_msg_info(cpl_func, "Strehl ratio with optimal Focus(%g): %g "
00256                  "(mse(2)=%g < mse(1)=%g)", optimal_focus, optimal_strehl,
00257                  mse2, mse1);
00258 
00259     bug_if(cpl_propertylist_append_double(qclist, "ESO QC FOCUSOPT",
00260                                            optimal_focus));
00261 
00262     /* PRO.CATG */
00263     bug_if(cpl_propertylist_append_string(qclist, CPL_DFS_PRO_CATG,
00264                                           NACO_IMG_CHECKFOCUS));
00265 
00266     skip_if (naco_img_checkfocus_save(framelist, parlist, qclist));
00267 
00268     end_skip;
00269     
00270     cpl_propertylist_delete(qclist);
00271     irplib_framelist_delete(allframes);
00272     irplib_framelist_delete(rawframes);
00273     cpl_image_delete(dark);
00274 
00275     cpl_vector_delete(focus_res);
00276     cpl_vector_delete(strehl_vec);
00277     cpl_matrix_delete(focus_mat);
00278 
00279     cpl_polynomial_delete(fit_poly);
00280 
00281     return cpl_error_get_code();
00282 }
00283 
00284 /*----------------------------------------------------------------------------*/
00298 /*----------------------------------------------------------------------------*/
00299 static cpl_error_code naco_img_checkfocus_reduce(const cpl_parameterlist * parlist,
00300                                                  const irplib_framelist  * rawframes,
00301                                                  int                       iframe,
00302                                                  const cpl_image *   dark,
00303                                                  double          *   fwhm,
00304                                                  double          *   strehl,
00305                                                  double          *   strehl_err,
00306                                                  double          *   energy,
00307                                                  double          *   focus)
00308 {
00309     const cpl_propertylist * plist;
00310     const char          *   filter;
00311     double                  pixscale;
00312     cpl_image           *   ima = NULL;
00313     cpl_vector          *   sigmas = NULL;
00314     cpl_apertures       *   apert = NULL;
00315     const char          *   file;
00316     double                  psigmas[] = {5, 2, 1, 0.5};
00317     const int               nsigmas = (int)(sizeof(psigmas)/sizeof(double));
00318     cpl_size                isigma;
00319     double                  lam, dlam;
00320     double                  pos_x, pos_y;
00321     double                  star_bg, star_peak, star_flux, psf_peak, psf_flux, 
00322                             bg_noise;
00323     double                  fwhm_x, fwhm_y;
00324     int                     imax_flux;
00325 
00326 
00327     skip_if (0);
00328 
00329     bug_if (parlist == NULL);
00330     bug_if (rawframes == NULL);
00331     bug_if (dark == NULL);
00332     bug_if (fwhm == NULL);
00333     bug_if (strehl == NULL);
00334     bug_if (strehl_err == NULL);
00335     bug_if (energy == NULL);
00336     bug_if (focus == NULL);
00337 
00338     file = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, iframe));
00339 
00340     /* Print out the filter and the pixel scale */
00341     plist = irplib_framelist_get_propertylist_const(rawframes, iframe);
00342     bug_if (0);
00343 
00344     filter = naco_pfits_get_filter(plist);
00345     pixscale = naco_pfits_get_pixscale(plist);
00346     *focus = naco_pfits_get_focus(plist);
00347 
00348     skip_if (0);
00349 
00350     /* Get lam and dlam from the filter name for the Strehl computation */
00351     irplib_check(naco_get_filter_infos(filter, &lam, &dlam),
00352                  "Cannot get filter infos [%s]", filter);
00353 
00354     /* Load input images */
00355     cpl_msg_info(cpl_func, "---> Load input image and subtract the dark");
00356     ima = cpl_image_load(file, CPL_TYPE_FLOAT, 0, 0);
00357     skip_if (0);
00358     
00359     bug_if (cpl_image_subtract(ima, dark));
00360     
00361     /* Detect a bright star around the center */
00362     cpl_msg_info(cpl_func, "---> Detecting a bright star using "
00363                  "%d sigma-levels ranging from %g down to %g", nsigmas,
00364                  psigmas[0], psigmas[nsigmas-1]);
00365     sigmas = cpl_vector_wrap(nsigmas, psigmas);
00366     apert = cpl_apertures_extract_window(ima, sigmas, 
00367             (int)(cpl_image_get_size_x(ima)-STREHL_DEF_LOCATE_SX)/2,
00368             (int)(cpl_image_get_size_y(ima)-STREHL_DEF_LOCATE_SY)/2,
00369             (int)(cpl_image_get_size_x(ima)+STREHL_DEF_LOCATE_SX)/2,
00370             (int)(cpl_image_get_size_y(ima)+STREHL_DEF_LOCATE_SY)/2,
00371             &isigma);
00372     if (apert == NULL) {
00373         cpl_msg_error(cpl_func, "Cannot detect any object");
00374         skip_if(1);
00375     }
00376 
00377     /* Find position of aperture with largest flux */
00378     skip_if (irplib_apertures_find_max_flux(apert, &imax_flux, 1));
00379 
00380     pos_x = cpl_apertures_get_centroid_x(apert, imax_flux);
00381     skip_if (0);
00382     pos_y = cpl_apertures_get_centroid_y(apert, imax_flux);
00383     skip_if (0);
00384 
00385     cpl_apertures_delete(apert);
00386     apert = NULL;
00387 
00388     cpl_msg_info(cpl_func, "Star detected at sigma=%g, at position: %g %g",
00389                  psigmas[isigma], pos_x, pos_y);
00390    
00391     /* Compute the strehl */
00392     cpl_msg_info(cpl_func, "---> Compute the strehl");
00393     irplib_check(irplib_strehl_compute(ima, 
00394                                        IRPLIB_STREHL_M1, IRPLIB_STREHL_M2, lam, dlam,
00395                                        pixscale, IRPLIB_STREHL_BOX_SIZE,
00396                                        pos_x, pos_y, 
00397                                        naco_parameterlist_get_double(parlist,
00398                                                                      RECIPE_STRING,
00399                                                              NACO_PARAM_STAR_R),
00400                                        naco_parameterlist_get_double(parlist,
00401                                                                      RECIPE_STRING,
00402                                                             NACO_PARAM_BG_RINT),
00403                                        naco_parameterlist_get_double(parlist,
00404                                                                      RECIPE_STRING,
00405                                                             NACO_PARAM_BG_REXT),
00406                                        -1, -1,
00407                                        strehl, strehl_err, &star_bg, &star_peak,
00408                                        &star_flux, &psf_peak,
00409                                        &psf_flux, &bg_noise),
00410                  "Cannot compute the strehl");
00411 
00412     /* Compute the energy */
00413     *energy = irplib_strehl_disk_flux(ima, pos_x, pos_y, ENERGY_RADIUS_PIX,
00414                                       0.0);
00415 
00416     skip_if (0);
00417     
00418     /* Compute the FHWM */
00419     skip_if (cpl_image_get_fwhm(ima, (int)pos_x, (int)pos_y, &fwhm_x, &fwhm_y));
00420 
00421     *fwhm = (fwhm_x+fwhm_y)/2.0;
00422 
00423     /* Display results */
00424     cpl_msg_info(cpl_func, "Strehl:                    %g", *strehl);
00425     cpl_msg_info(cpl_func, "Strehl error:              %g", *strehl_err);
00426     cpl_msg_info(cpl_func, "Energy:                    %g", *energy);
00427     cpl_msg_info(cpl_func, "FWHM:                      %g", *fwhm);
00428     cpl_msg_info(cpl_func, "Focus:                     %g", *focus);
00429 
00430     end_skip;
00431 
00432     cpl_image_delete(ima);
00433     cpl_vector_unwrap(sigmas);
00434     cpl_apertures_delete(apert);
00435 
00436     return cpl_error_get_code();
00437 }
00438 
00439 
00440 /*----------------------------------------------------------------------------*/
00447 /*----------------------------------------------------------------------------*/
00448 static cpl_error_code naco_img_checkfocus_qc(cpl_propertylist       * qclist,
00449                                              const irplib_framelist * rawframes)
00450 {
00451 
00452     const cpl_propertylist * reflist
00453         = irplib_framelist_get_propertylist_const(rawframes, 0);
00454 
00455 
00456     bug_if (0);
00457 
00458     /* Get the keywords for the paf file */
00459     bug_if(cpl_propertylist_copy_property_regexp(qclist, reflist,
00460                                                  "^(" IRPLIB_PFITS_REGEXP_PAF
00461                                                  ")$", 0));
00462   
00463     end_skip;
00464 
00465     return cpl_error_get_code();
00466 }
00467 
00468 /*----------------------------------------------------------------------------*/
00476 /*----------------------------------------------------------------------------*/
00477 static
00478 cpl_error_code naco_img_checkfocus_save(cpl_frameset * self,
00479                                         const cpl_parameterlist * parlist,
00480                                         const cpl_propertylist * qclist)
00481 {
00482 
00483 
00484     skip_if(cpl_dfs_save_propertylist(self, NULL, parlist, self, NULL,
00485                                       RECIPE_STRING, qclist, NULL, naco_pipe_id,
00486                                       RECIPE_STRING CPL_DFS_FITS));
00487 
00488 #ifdef NACO_SAVE_PAF
00489     skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, qclist,
00490                              RECIPE_STRING CPL_DFS_PAF));
00491 #endif
00492 
00493     end_skip;
00494 
00495     return cpl_error_get_code();
00496 }
Generated on Mon Feb 17 15:01:44 2014 for NACO Pipeline Reference Manual by  doxygen 1.6.3