naco_img_checkfocus.c

00001 /* $Id: naco_img_checkfocus.c,v 1.55 2009/02/19 15:15:38 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: 2009/02/19 15:15:38 $
00024  * $Revision: 1.55 $
00025  * $Name: naco-4_1_2 $
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(const cpl_propertylist *);
00063 
00064 NACO_RECIPE_DEFINE(naco_img_checkfocus,
00065     NACO_PARAM_PLOT    |                        
00066     NACO_PARAM_STAR_R  |                        
00067     NACO_PARAM_BG_RINT |                        
00068     NACO_PARAM_BG_REXT,
00069     "Focus check recipe",
00070     RECIPE_STRING " -- The focus checking recipe\n"        
00071     "The Set Of Frames (sof-file) must specify at least four "  
00072     "files and they must be tagged\n"                           
00073     "NACO-raw-file.fits "NACO_IMG_CHECKFOCUS_RAW"\n"            
00074     "The first of the files is used as a dark frame.\n");
00075 
00076 /*----------------------------------------------------------------------------*/
00080 /*----------------------------------------------------------------------------*/
00081 
00082 /*-----------------------------------------------------------------------------
00083                                 Functions code
00084  -----------------------------------------------------------------------------*/
00085 
00086 /*----------------------------------------------------------------------------*/
00093 /*----------------------------------------------------------------------------*/
00094 static int naco_img_checkfocus(cpl_frameset            * framelist,
00095                                const cpl_parameterlist * parlist)
00096 {
00097     cpl_errorstate cleanstate = cpl_errorstate_get();
00098     irplib_framelist * allframes = NULL;
00099     irplib_framelist * rawframes = NULL;
00100     cpl_propertylist * qclist = cpl_propertylist_new();
00101     cpl_image        * dark = NULL;
00102     cpl_vector       * strehl_vec = NULL;
00103     cpl_vector       * focus_vec = NULL;
00104     cpl_matrix       * focus_mat = NULL;
00105     cpl_vector       * focus_res = NULL;
00106     cpl_polynomial   * fit_poly = NULL;
00107     const char       * darkfile;
00108     int                nframes;
00109     int                nb_good;
00110     const int          degree1 = 1;
00111     const int          degree2 = 2;
00112     double             best_strehl = DBL_MAX; /* Avoid (false) uninit warning */
00113     double             c1, c2;
00114     double             optimal_focus, optimal_strehl, mse2, mse1;
00115     int                i;
00116 
00117     /* Identify the RAW and CALIB frames in the input frameset */
00118     skip_if (naco_dfs_set_groups(framelist));
00119 
00120     allframes = irplib_framelist_cast(framelist);
00121     skip_if(allframes == NULL);
00122 
00123     rawframes = irplib_framelist_extract(allframes, NACO_IMG_CHECKFOCUS_RAW);
00124     skip_if(rawframes == NULL);
00125     irplib_framelist_empty(allframes);
00126 
00127     nframes = irplib_framelist_get_size(rawframes);
00128     irplib_ensure(nframes >= 4, CPL_ERROR_DATA_NOT_FOUND,
00129                   "Must have at least 4 (not %d) frames to check the focus",
00130                    nframes);
00131    
00132     skip_if(irplib_framelist_load_propertylist(rawframes, 0, 0, "^("
00133                                                NACO_PFITS_REGEXP_CHECKFOCUS "|"
00134                                                NACO_PFITS_REGEXP_CHECKFOCUS_PAF
00135                                                ")$", CPL_FALSE));
00136 
00137     skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
00138                                                    NACO_PFITS_REGEXP_CHECKFOCUS
00139                                                    ")$", CPL_FALSE));
00140 
00141     /* The dark is the first frame */
00142     cpl_msg_info(cpl_func, "The first frame is used as a dark");
00143     darkfile = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, 0));
00144     skip_if (0);
00145 
00146     irplib_check(dark = cpl_image_load(darkfile, CPL_TYPE_FLOAT, 0, 0),
00147                  "Could not load the dark from %s", darkfile);
00148 
00149     /* Allocate vectors to store results */
00150     strehl_vec = cpl_vector_new(nframes-1);
00151     focus_vec  = cpl_vector_new(nframes-1);
00152     
00153     skip_if (naco_img_checkfocus_qc(qclist, rawframes));
00154 
00155     /* Reduce each frame */
00156     nb_good = 0;
00157     for (i=1 ; i < nframes ; i++) {
00158         double focus = DBL_MAX; /* Avoid (false) uninit warning */
00159         double energy = DBL_MAX; /* Avoid (false) uninit warning */
00160         double fwhm = DBL_MAX; /* Avoid (false) uninit warning */
00161         double strehl, strehl_err;
00162 
00163         cpl_msg_info(cpl_func, "Reducing frame %d of %d\n", i+1, nframes);
00164 
00165         /* Reduce frame nb i */
00166         if (naco_img_checkfocus_reduce(parlist, rawframes, i, dark,
00167                                       &fwhm, &strehl, &strehl_err,
00168                                        &energy, &focus)) {
00169             naco_error_reset("Could not compute focus for this frame:");
00170             continue;
00171         }
00172 
00173         /* Keep only the values where strehl_err < 10% */
00174         if (strehl_err >= 0.1) continue;
00175 
00176         /* Assign the results in the vectors */
00177         bug_if (cpl_vector_set(strehl_vec, nb_good, strehl));
00178         bug_if (cpl_vector_set(focus_vec,  nb_good, focus));
00179 
00180         nb_good++;
00181 
00182         if (nb_good > 1 && strehl <= best_strehl) continue;
00183 
00184         /* Found the best FOCUS */
00185         best_strehl = strehl;
00186 
00187         /* Add/Update QC parameters */
00188         bug_if(cpl_propertylist_update_double(qclist, "ESO QC STREHL", strehl));
00189         bug_if(cpl_propertylist_update_double(qclist, "ESO QC STREHL ERROR",
00190                                               strehl_err));
00191         bug_if(cpl_propertylist_update_double(qclist, "ESO QC FWHM PIX", fwhm));
00192         bug_if(cpl_propertylist_update_double(qclist, "ESO QC ENERGY", energy));
00193         bug_if(cpl_propertylist_update_double(qclist, "ESO QC FOCUS", focus));
00194 
00195 
00196     }
00197     cpl_image_delete(dark);
00198     dark = NULL;
00199     irplib_framelist_empty(rawframes);
00200 
00201     skip_if_lt (nb_good, 3, "frames with a Strehl error less than 0.1");
00202 
00203     bug_if (cpl_vector_set_size(strehl_vec, nb_good));
00204     bug_if (cpl_vector_set_size(focus_vec,  nb_good));
00205 
00206     /* Fit the optimal focus - and make sure it is well-defined */
00207 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE < CPL_VERSION(4, 8, 0)
00208     irplib_check(fit_poly = cpl_polynomial_fit_1d_create(focus_vec, strehl_vec,
00209                                                          degree1, &mse1),
00210                  "Cannot fit the strehl/focus");
00211 
00212     /* Fit the optimal focus */
00213     cpl_polynomial_delete(fit_poly);
00214     irplib_check(fit_poly = cpl_polynomial_fit_1d_create(focus_vec, strehl_vec,
00215                                                          degree2, &mse2),
00216                  "Cannot fit the strehl/focus");
00217 
00218 #else
00219     focus_res  = cpl_vector_new(nb_good);
00220     focus_mat  = cpl_matrix_wrap(1, nb_good, cpl_vector_get_data(focus_vec));
00221     fit_poly = cpl_polynomial_new(1);
00222     skip_if(cpl_polynomial_fit(fit_poly, focus_mat, NULL, strehl_vec, NULL,
00223                                CPL_FALSE, NULL, &degree1));
00224 
00225     bug_if(cpl_vector_fill_polynomial_fit_residual(focus_res, strehl_vec, NULL,
00226                                                    fit_poly, focus_mat, NULL));
00227     mse1 = cpl_vector_product(focus_res, focus_res) / nb_good;
00228 
00229     skip_if(cpl_polynomial_fit(fit_poly, focus_mat, NULL, strehl_vec, NULL,
00230                                CPL_FALSE, NULL, &degree2));
00231 
00232     bug_if(cpl_vector_fill_polynomial_fit_residual(focus_res, strehl_vec, NULL,
00233                                                    fit_poly, focus_mat, NULL));
00234     mse2 = cpl_vector_product(focus_res, focus_res) / nb_good;
00235 
00236     cpl_vector_delete(focus_res);
00237     focus_res = NULL;
00238     (void)cpl_matrix_unwrap(focus_mat);
00239     focus_mat = NULL;
00240 #endif
00241     cpl_vector_delete(strehl_vec);
00242     strehl_vec = NULL;
00243     cpl_vector_delete(focus_vec);
00244     focus_vec = NULL;
00245 
00246     i = 1;
00247     c1 = cpl_polynomial_get_coeff(fit_poly, &i);
00248     i = 2;
00249     c2 = cpl_polynomial_get_coeff(fit_poly, &i);
00250 
00251     irplib_ensure(mse2 < mse1, CPL_ERROR_DATA_NOT_FOUND,
00252                   "Ill-defined optimal focus, the strehl ratio "
00253                    "appears to be a linear function of the focus value: "
00254                    "mse(2)=%g >= mse(1)=%g (c1=%g, c2=%g)",
00255                    mse2, mse1, c1, c2);
00256 
00257     bug_if (c2 == 0.0);
00258 
00259     irplib_ensure(c2 < 0.0, CPL_ERROR_DATA_NOT_FOUND,
00260                   "Ill-defined optimal focus, the strehl ratio "
00261                    "does not have a single optimal value: mse(2)=%g, c1=%g, "
00262                    "c2=%g > 0", mse2, c1, c2);
00263 
00264     optimal_focus = -c1/(2.0*c2);
00265 
00266     /* Could compute derivate as well, to check that it is close to zero */
00267     optimal_strehl = cpl_polynomial_eval_1d(fit_poly, optimal_focus, NULL);
00268 
00269     cpl_polynomial_delete(fit_poly);
00270     fit_poly = NULL;
00271 
00272     cpl_msg_info(cpl_func, "Strehl ratio with optimal Focus(%g): %g "
00273                  "(mse(2)=%g < mse(1)=%g)", optimal_focus, optimal_strehl,
00274                  mse2, mse1);
00275 
00276     bug_if(cpl_propertylist_append_double(qclist, "ESO QC FOCUSOPT",
00277                                            optimal_focus));
00278 
00279     skip_if (naco_img_checkfocus_save(qclist));
00280 
00281     end_skip;
00282     
00283     cpl_propertylist_delete(qclist);
00284     irplib_framelist_delete(allframes);
00285     irplib_framelist_delete(rawframes);
00286     cpl_image_delete(dark);
00287 
00288     (void)cpl_matrix_unwrap(focus_mat);
00289     cpl_vector_delete(focus_res);
00290     cpl_vector_delete(strehl_vec);
00291     cpl_vector_delete(focus_vec);
00292 
00293     cpl_polynomial_delete(fit_poly);
00294 
00295     return cpl_error_get_code();
00296 }
00297 
00298 /*----------------------------------------------------------------------------*/
00312 /*----------------------------------------------------------------------------*/
00313 static cpl_error_code naco_img_checkfocus_reduce(const cpl_parameterlist * parlist,
00314                                                  const irplib_framelist  * rawframes,
00315                                                  int                       iframe,
00316                                                  const cpl_image *   dark,
00317                                                  double          *   fwhm,
00318                                                  double          *   strehl,
00319                                                  double          *   strehl_err,
00320                                                  double          *   energy,
00321                                                  double          *   focus)
00322 {
00323     const cpl_propertylist * plist;
00324     const char          *   filter;
00325     double                  pixscale;
00326     cpl_image           *   ima = NULL;
00327     cpl_vector          *   sigmas = NULL;
00328     cpl_apertures       *   apert = NULL;
00329     const char          *   file;
00330     double                  psigmas[] = {5, 2, 1, 0.5};
00331     const int               nsigmas = (int)(sizeof(psigmas)/sizeof(double));
00332     int                     isigma;
00333     double                  lam, dlam;
00334     double                  pos_x, pos_y;
00335     double                  star_bg, star_peak, star_flux, psf_peak, psf_flux, 
00336                             bg_noise;
00337     double                  fwhm_x, fwhm_y;
00338     int                     imax_flux;
00339 
00340 
00341     skip_if (0);
00342 
00343     bug_if (parlist == NULL);
00344     bug_if (rawframes == NULL);
00345     bug_if (dark == NULL);
00346     bug_if (fwhm == NULL);
00347     bug_if (strehl == NULL);
00348     bug_if (strehl_err == NULL);
00349     bug_if (energy == NULL);
00350     bug_if (focus == NULL);
00351 
00352     file = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, iframe));
00353 
00354     /* Print out the filter and the pixel scale */
00355     plist = irplib_framelist_get_propertylist_const(rawframes, iframe);
00356     bug_if (0);
00357 
00358     filter = naco_pfits_get_filter(plist);
00359     pixscale = naco_pfits_get_pixscale(plist);
00360     *focus = naco_pfits_get_focus(plist);
00361 
00362     skip_if (0);
00363 
00364     /* Get lam and dlam from the filter name for the Strehl computation */
00365     irplib_check(naco_get_filter_infos(filter, &lam, &dlam),
00366                  "Cannot get filter infos [%s]", filter);
00367 
00368     /* Load input images */
00369     cpl_msg_info(cpl_func, "---> Load input image and subtract the dark");
00370     ima = cpl_image_load(file, CPL_TYPE_FLOAT, 0, 0);
00371     skip_if (0);
00372     
00373     bug_if (cpl_image_subtract(ima, dark));
00374     
00375     /* Detect a bright star around the center */
00376     cpl_msg_info(cpl_func, "---> Detecting a bright star using "
00377                  "%d sigma-levels ranging from %g down to %g", nsigmas,
00378                  psigmas[0], psigmas[nsigmas-1]);
00379     sigmas = cpl_vector_wrap(nsigmas, psigmas);
00380     apert = cpl_apertures_extract_window(ima, sigmas, 
00381             (int)(cpl_image_get_size_x(ima)-STREHL_DEF_LOCATE_SX)/2,
00382             (int)(cpl_image_get_size_y(ima)-STREHL_DEF_LOCATE_SY)/2,
00383             (int)(cpl_image_get_size_x(ima)+STREHL_DEF_LOCATE_SX)/2,
00384             (int)(cpl_image_get_size_y(ima)+STREHL_DEF_LOCATE_SY)/2,
00385             &isigma);
00386     if (apert == NULL) {
00387         cpl_msg_error(cpl_func, "Cannot detect any object");
00388         skip_if(1);
00389     }
00390 
00391     /* Find position of aperture with largest flux */
00392     skip_if (irplib_apertures_find_max_flux(apert, &imax_flux, 1));
00393 
00394     pos_x = cpl_apertures_get_centroid_x(apert, imax_flux);
00395     skip_if (0);
00396     pos_y = cpl_apertures_get_centroid_y(apert, imax_flux);
00397     skip_if (0);
00398 
00399     cpl_apertures_delete(apert);
00400     apert = NULL;
00401 
00402     cpl_msg_info(cpl_func, "Star detected at sigma=%g, at position: %g %g",
00403                  psigmas[isigma], pos_x, pos_y);
00404    
00405     /* Compute the strehl */
00406     cpl_msg_info(cpl_func, "---> Compute the strehl");
00407     irplib_check(irplib_strehl_compute(ima, 
00408                                        STREHL_M1, STREHL_M2, lam, dlam,
00409                                        pixscale, STREHL_BOX_SIZE,
00410                                        pos_x, pos_y, 
00411                                        naco_parameterlist_get_double(parlist,
00412                                                                      RECIPE_STRING,
00413                                                              NACO_PARAM_STAR_R),
00414                                        naco_parameterlist_get_double(parlist,
00415                                                                      RECIPE_STRING,
00416                                                             NACO_PARAM_BG_RINT),
00417                                        naco_parameterlist_get_double(parlist,
00418                                                                      RECIPE_STRING,
00419                                                             NACO_PARAM_BG_REXT),
00420                                        -1, -1,
00421                                        strehl, strehl_err, &star_bg, &star_peak,
00422                                        &star_flux, &psf_peak,
00423                                        &psf_flux, &bg_noise),
00424                  "Cannot compute the strehl");
00425 
00426     /* Compute the energy */
00427     *energy = irplib_strehl_disk_flux(ima, pos_x, pos_y, ENERGY_RADIUS_PIX,
00428                                       0.0);
00429 
00430     skip_if (0);
00431     
00432     /* Compute the FHWM */
00433     skip_if (cpl_image_get_fwhm(ima, (int)pos_x, (int)pos_y, &fwhm_x, &fwhm_y));
00434 
00435     *fwhm = (fwhm_x+fwhm_y)/2.0;
00436 
00437     /* Display results */
00438     cpl_msg_info(cpl_func, "Strehl:                    %g", *strehl);
00439     cpl_msg_info(cpl_func, "Strehl error:              %g", *strehl_err);
00440     cpl_msg_info(cpl_func, "Energy:                    %g", *energy);
00441     cpl_msg_info(cpl_func, "FWHM:                      %g", *fwhm);
00442     cpl_msg_info(cpl_func, "Focus:                     %g", *focus);
00443 
00444     end_skip;
00445 
00446     cpl_image_delete(ima);
00447     cpl_vector_unwrap(sigmas);
00448     cpl_apertures_delete(apert);
00449 
00450     return cpl_error_get_code();
00451 }
00452 
00453 
00454 /*----------------------------------------------------------------------------*/
00461 /*----------------------------------------------------------------------------*/
00462 static cpl_error_code naco_img_checkfocus_qc(cpl_propertylist       * qclist,
00463                                              const irplib_framelist * rawframes)
00464 {
00465 
00466     const cpl_propertylist * reflist
00467         = irplib_framelist_get_propertylist_const(rawframes, 0);
00468 
00469 
00470     bug_if (0);
00471 
00472     /* Get the keywords for the paf file */
00473     bug_if(cpl_propertylist_copy_property_regexp(qclist, reflist,
00474                                                  "^(" IRPLIB_PFITS_REGEXP_PAF
00475                                                  ")$", 0));
00476   
00477     end_skip;
00478 
00479     return cpl_error_get_code();
00480 }
00481 
00482 /*----------------------------------------------------------------------------*/
00489 /*----------------------------------------------------------------------------*/
00490 static cpl_error_code naco_img_checkfocus_save(const cpl_propertylist * qclist)
00491 {
00492 
00493     skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, qclist,
00494                              RECIPE_STRING CPL_DFS_PAF));
00495 
00496     end_skip;
00497 
00498     return cpl_error_get_code();
00499 }

Generated on Fri Jul 3 11:23:58 2009 for NACO Pipeline Reference Manual by  doxygen 1.5.8