naco_img_checkfocus.c

00001 /* $Id: naco_img_checkfocus.c,v 1.58 2010/03/04 15:57:20 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: 2010/03/04 15:57:20 $
00024  * $Revision: 1.58 $
00025  * $Name: HEAD $
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 int          degree1 = 1;
00112     const int          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     i = 1;
00232     c1 = cpl_polynomial_get_coeff(fit_poly, &i);
00233     i = 2;
00234     c2 = cpl_polynomial_get_coeff(fit_poly, &i);
00235 
00236     irplib_ensure(mse2 < mse1, CPL_ERROR_DATA_NOT_FOUND,
00237                   "Ill-defined optimal focus, the strehl ratio "
00238                    "appears to be a linear function of the focus value: "
00239                    "mse(2)=%g >= mse(1)=%g (c1=%g, c2=%g)",
00240                    mse2, mse1, c1, c2);
00241 
00242     bug_if (c2 == 0.0);
00243 
00244     irplib_ensure(c2 < 0.0, CPL_ERROR_DATA_NOT_FOUND,
00245                   "Ill-defined optimal focus, the strehl ratio "
00246                    "does not have a single optimal value: mse(2)=%g, c1=%g, "
00247                    "c2=%g > 0", mse2, c1, c2);
00248 
00249     optimal_focus = -c1/(2.0*c2);
00250 
00251     /* Could compute derivate as well, to check that it is close to zero */
00252     optimal_strehl = cpl_polynomial_eval_1d(fit_poly, optimal_focus, NULL);
00253 
00254     cpl_polynomial_delete(fit_poly);
00255     fit_poly = NULL;
00256 
00257     cpl_msg_info(cpl_func, "Strehl ratio with optimal Focus(%g): %g "
00258                  "(mse(2)=%g < mse(1)=%g)", optimal_focus, optimal_strehl,
00259                  mse2, mse1);
00260 
00261     bug_if(cpl_propertylist_append_double(qclist, "ESO QC FOCUSOPT",
00262                                            optimal_focus));
00263 
00264     /* PRO.CATG */
00265     bug_if(cpl_propertylist_append_string(qclist, CPL_DFS_PRO_CATG,
00266                                           NACO_IMG_CHECKFOCUS));
00267 
00268     skip_if (naco_img_checkfocus_save(framelist, parlist, qclist));
00269 
00270     end_skip;
00271     
00272     cpl_propertylist_delete(qclist);
00273     irplib_framelist_delete(allframes);
00274     irplib_framelist_delete(rawframes);
00275     cpl_image_delete(dark);
00276 
00277     cpl_vector_delete(focus_res);
00278     cpl_vector_delete(strehl_vec);
00279     cpl_matrix_delete(focus_mat);
00280 
00281     cpl_polynomial_delete(fit_poly);
00282 
00283     return cpl_error_get_code();
00284 }
00285 
00286 /*----------------------------------------------------------------------------*/
00300 /*----------------------------------------------------------------------------*/
00301 static cpl_error_code naco_img_checkfocus_reduce(const cpl_parameterlist * parlist,
00302                                                  const irplib_framelist  * rawframes,
00303                                                  int                       iframe,
00304                                                  const cpl_image *   dark,
00305                                                  double          *   fwhm,
00306                                                  double          *   strehl,
00307                                                  double          *   strehl_err,
00308                                                  double          *   energy,
00309                                                  double          *   focus)
00310 {
00311     const cpl_propertylist * plist;
00312     const char          *   filter;
00313     double                  pixscale;
00314     cpl_image           *   ima = NULL;
00315     cpl_vector          *   sigmas = NULL;
00316     cpl_apertures       *   apert = NULL;
00317     const char          *   file;
00318     double                  psigmas[] = {5, 2, 1, 0.5};
00319     const int               nsigmas = (int)(sizeof(psigmas)/sizeof(double));
00320     int                     isigma;
00321     double                  lam, dlam;
00322     double                  pos_x, pos_y;
00323     double                  star_bg, star_peak, star_flux, psf_peak, psf_flux, 
00324                             bg_noise;
00325     double                  fwhm_x, fwhm_y;
00326     int                     imax_flux;
00327 
00328 
00329     skip_if (0);
00330 
00331     bug_if (parlist == NULL);
00332     bug_if (rawframes == NULL);
00333     bug_if (dark == NULL);
00334     bug_if (fwhm == NULL);
00335     bug_if (strehl == NULL);
00336     bug_if (strehl_err == NULL);
00337     bug_if (energy == NULL);
00338     bug_if (focus == NULL);
00339 
00340     file = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, iframe));
00341 
00342     /* Print out the filter and the pixel scale */
00343     plist = irplib_framelist_get_propertylist_const(rawframes, iframe);
00344     bug_if (0);
00345 
00346     filter = naco_pfits_get_filter(plist);
00347     pixscale = naco_pfits_get_pixscale(plist);
00348     *focus = naco_pfits_get_focus(plist);
00349 
00350     skip_if (0);
00351 
00352     /* Get lam and dlam from the filter name for the Strehl computation */
00353     irplib_check(naco_get_filter_infos(filter, &lam, &dlam),
00354                  "Cannot get filter infos [%s]", filter);
00355 
00356     /* Load input images */
00357     cpl_msg_info(cpl_func, "---> Load input image and subtract the dark");
00358     ima = cpl_image_load(file, CPL_TYPE_FLOAT, 0, 0);
00359     skip_if (0);
00360     
00361     bug_if (cpl_image_subtract(ima, dark));
00362     
00363     /* Detect a bright star around the center */
00364     cpl_msg_info(cpl_func, "---> Detecting a bright star using "
00365                  "%d sigma-levels ranging from %g down to %g", nsigmas,
00366                  psigmas[0], psigmas[nsigmas-1]);
00367     sigmas = cpl_vector_wrap(nsigmas, psigmas);
00368     apert = cpl_apertures_extract_window(ima, sigmas, 
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             (int)(cpl_image_get_size_x(ima)+STREHL_DEF_LOCATE_SX)/2,
00372             (int)(cpl_image_get_size_y(ima)+STREHL_DEF_LOCATE_SY)/2,
00373             &isigma);
00374     if (apert == NULL) {
00375         cpl_msg_error(cpl_func, "Cannot detect any object");
00376         skip_if(1);
00377     }
00378 
00379     /* Find position of aperture with largest flux */
00380     skip_if (irplib_apertures_find_max_flux(apert, &imax_flux, 1));
00381 
00382     pos_x = cpl_apertures_get_centroid_x(apert, imax_flux);
00383     skip_if (0);
00384     pos_y = cpl_apertures_get_centroid_y(apert, imax_flux);
00385     skip_if (0);
00386 
00387     cpl_apertures_delete(apert);
00388     apert = NULL;
00389 
00390     cpl_msg_info(cpl_func, "Star detected at sigma=%g, at position: %g %g",
00391                  psigmas[isigma], pos_x, pos_y);
00392    
00393     /* Compute the strehl */
00394     cpl_msg_info(cpl_func, "---> Compute the strehl");
00395     irplib_check(irplib_strehl_compute(ima, 
00396                                        STREHL_M1, STREHL_M2, lam, dlam,
00397                                        pixscale, STREHL_BOX_SIZE,
00398                                        pos_x, pos_y, 
00399                                        naco_parameterlist_get_double(parlist,
00400                                                                      RECIPE_STRING,
00401                                                              NACO_PARAM_STAR_R),
00402                                        naco_parameterlist_get_double(parlist,
00403                                                                      RECIPE_STRING,
00404                                                             NACO_PARAM_BG_RINT),
00405                                        naco_parameterlist_get_double(parlist,
00406                                                                      RECIPE_STRING,
00407                                                             NACO_PARAM_BG_REXT),
00408                                        -1, -1,
00409                                        strehl, strehl_err, &star_bg, &star_peak,
00410                                        &star_flux, &psf_peak,
00411                                        &psf_flux, &bg_noise),
00412                  "Cannot compute the strehl");
00413 
00414     /* Compute the energy */
00415     *energy = irplib_strehl_disk_flux(ima, pos_x, pos_y, ENERGY_RADIUS_PIX,
00416                                       0.0);
00417 
00418     skip_if (0);
00419     
00420     /* Compute the FHWM */
00421     skip_if (cpl_image_get_fwhm(ima, (int)pos_x, (int)pos_y, &fwhm_x, &fwhm_y));
00422 
00423     *fwhm = (fwhm_x+fwhm_y)/2.0;
00424 
00425     /* Display results */
00426     cpl_msg_info(cpl_func, "Strehl:                    %g", *strehl);
00427     cpl_msg_info(cpl_func, "Strehl error:              %g", *strehl_err);
00428     cpl_msg_info(cpl_func, "Energy:                    %g", *energy);
00429     cpl_msg_info(cpl_func, "FWHM:                      %g", *fwhm);
00430     cpl_msg_info(cpl_func, "Focus:                     %g", *focus);
00431 
00432     end_skip;
00433 
00434     cpl_image_delete(ima);
00435     cpl_vector_unwrap(sigmas);
00436     cpl_apertures_delete(apert);
00437 
00438     return cpl_error_get_code();
00439 }
00440 
00441 
00442 /*----------------------------------------------------------------------------*/
00449 /*----------------------------------------------------------------------------*/
00450 static cpl_error_code naco_img_checkfocus_qc(cpl_propertylist       * qclist,
00451                                              const irplib_framelist * rawframes)
00452 {
00453 
00454     const cpl_propertylist * reflist
00455         = irplib_framelist_get_propertylist_const(rawframes, 0);
00456 
00457 
00458     bug_if (0);
00459 
00460     /* Get the keywords for the paf file */
00461     bug_if(cpl_propertylist_copy_property_regexp(qclist, reflist,
00462                                                  "^(" IRPLIB_PFITS_REGEXP_PAF
00463                                                  ")$", 0));
00464   
00465     end_skip;
00466 
00467     return cpl_error_get_code();
00468 }
00469 
00470 /*----------------------------------------------------------------------------*/
00478 /*----------------------------------------------------------------------------*/
00479 static
00480 cpl_error_code naco_img_checkfocus_save(cpl_frameset * self,
00481                                         const cpl_parameterlist * parlist,
00482                                         const cpl_propertylist * qclist)
00483 {
00484 
00485 
00486     skip_if(cpl_dfs_save_propertylist(self, NULL, parlist, self, NULL,
00487                                       RECIPE_STRING, qclist, NULL, naco_pipe_id,
00488                                       RECIPE_STRING CPL_DFS_FITS));
00489 
00490 #ifdef NACO_SAVE_PAF
00491     skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, qclist,
00492                              RECIPE_STRING CPL_DFS_PAF));
00493 #endif
00494 
00495     end_skip;
00496 
00497     return cpl_error_get_code();
00498 }

Generated on Wed Mar 9 15:46:17 2011 for NACO Pipeline Reference Manual by  doxygen 1.5.8