visir_img_phot.c

00001 /* $Id: visir_img_phot.c,v 1.163 2010/09/30 06:49:14 llundin Exp $
00002  *
00003  * This file is part of the VISIR 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/09/30 06:49:14 $
00024  * $Revision: 1.163 $
00025  * $Name: HEAD $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 
00033 /*-----------------------------------------------------------------------------
00034                                 Includes
00035  -----------------------------------------------------------------------------*/
00036 
00037 #include <string.h>
00038 #include <float.h>
00039 
00040 #include "visir_recipe.h"
00041 #include "irplib_strehl.h"
00042 
00043 /*-----------------------------------------------------------------------------
00044                                 Define   
00045  -----------------------------------------------------------------------------*/
00046 
00047 #define VISIR_IMG_PHOT_POS_WARN         10.0
00048 #define VISIR_IMG_PHOT_POS_ERROR        25.0
00049 #define VISIR_IMG_PHOT_POS_UNCERTAINTY  10.0
00050 #define STREHL_M1                       8.0
00051 #define STREHL_M2                       1.1
00052 #define STREHL_BOX_SIZE                 64
00053 #define STREHL_STAR_RADIUS              2.0
00054 #define STREHL_BG_R1                    2.0
00055 #define STREHL_BG_R2                    3.0
00056 
00057 #define RECIPE_STRING "visir_img_phot"
00058 
00059 
00060 /* FITS keys to be loaded for all raw files */
00061 #define RECIPE_KEYS_REGEXP_ALL \
00062         VISIR_PFITS_REGEXP_IMG_RECOMBINE \
00063     "|" VISIR_PFITS_REGEXP_IMG_SENSIT
00064 
00065 /* FITS keys to be loaded for first raw file */
00066 #define RECIPE_KEYS_REGEXP               \
00067         RECIPE_KEYS_REGEXP_ALL           \
00068     "|" VISIR_PFITS_IMG_PHOT_COPY        \
00069     "|" VISIR_PFITS_REGEXP_IMG_PHOT_PAF
00070 
00071 /* FITS keys to be loaded for first raw file, in case WCS is used */
00072 #define RECIPE_KEYS_REGEXP_WCS \
00073         RECIPE_KEYS_REGEXP \
00074     "|" IRPLIB_PFITS_WCS_REGEXP
00075 
00076 
00077 /*-----------------------------------------------------------------------------
00078                             Private Functions prototypes
00079  -----------------------------------------------------------------------------*/
00080 
00081 static double visir_img_phot_eccent_four(const cpl_apertures *, int, int,
00082                                          const cpl_apertures *, int, int);
00083 
00084 #ifdef VISIR_IMG_PHOT_USE_ECCENT_THREE
00085 static double visir_img_phot_eccent_three(const cpl_apertures *, int,
00086                                           const cpl_apertures *, int, int);
00087 #endif
00088 
00089 static double visir_img_phot_jy_from_cat(const char *, const char *, double,
00090                                          double, const char *);
00091 static int visir_img_phot_sensit(const cpl_image *, const irplib_framelist *,
00092                                  const char *);
00093 static int visir_img_phot_flux_three(const cpl_image *);
00094 static int visir_img_phot_flux_four(const cpl_image *);
00095 static int visir_img_phot_flux(const cpl_image *, double, double, int, int, int,
00096                                double *, double *, double *, double *, double*);
00097 
00098 static cpl_error_code visir_get_filter_infos(const char *, double *, double *);
00099 
00100 static cpl_error_code visir_img_phot_qc(cpl_propertylist *,
00101                                         cpl_boolean,
00102                                         const irplib_framelist *);
00103 
00104 static cpl_error_code visir_img_phot_save(cpl_frameset *,
00105                                           const cpl_parameterlist *,
00106                                           const cpl_propertylist *,
00107                                           const cpl_image *,
00108                                           const cpl_image *,
00109                                           const cpl_image *,
00110                                           const cpl_image *);
00111 
00112 VISIR_RECIPE_DEFINE(visir_img_phot,
00113                     VISIR_PARAM_RADII | VISIR_PARAM_JYVAL |
00114                     VISIR_PARAM_REFINE | VISIR_PARAM_XCORR |
00115                     VISIR_PARAM_OFFSETS | VISIR_PARAM_OBJECTS |
00116                     VISIR_PARAM_NODPOS |  VISIR_PARAM_AUTOBPM |
00117                     VISIR_PARAM_GLITCH | VISIR_PARAM_PURGE |
00118                     VISIR_PARAM_UNION  | VISIR_PARAM_REJECT |
00119                     VISIR_PARAM_COMBINE | VISIR_PARAM_ECCMAX |
00120                     VISIR_PARAM_STRIPITE | VISIR_PARAM_STRIPMOR |
00121                     VISIR_PARAM_PLOT,
00122                     "Sensitivity computation",
00123                     "This recipe computes the conversion factor and the "
00124                     "sentitivity of a\n"
00125                     "standard star. It requires a standard star catalog.\n"
00126                     "The files listed in the Set Of Frames (sof-file) "
00127                     "must be tagged:\n"
00128                     "VISIR-std-star-observation.fits " VISIR_IMG_PHOT_RAW
00129                     "\n"
00130                     "VISIR-Imaging-Standard-Star-Catalog.fits "
00131                     VISIR_IMA_STD_CAT_PROCATG "\n"
00132                     "\n"
00133                     "The primary product will have a FITS card\n"
00134                     "'HIERARCH " CPL_DFS_PRO_CATG "' with a string value of\n"
00135                     "'" VISIR_IMG_PHOT_COMBINED_PROCATG "'\n"
00136                     " and the corresponding beam-collapsed product will "
00137                     "have a FITS card\n"
00138                     "'HIERARCH " CPL_DFS_PRO_CATG "' with a value of\n"
00139                     VISIR_IMG_PHOT_ONEBEAM_PROCATG
00140                     "\n"
00141                     MAN_VISIR_CALIB_BPM_IMG);
00142 
00143 /*-----------------------------------------------------------------------------
00144                             Static variables
00145  -----------------------------------------------------------------------------*/
00146 
00147 static const int fits_strlen = IRPLIB_FITS_STRLEN;
00148 
00149 static struct {
00150     /* Inputs */
00151     double      jy_val;
00152     int         r0_max;
00153     int         r1;
00154     int         r2;
00155 
00156     /* Outputs */
00157     double      exptime;
00158     double      pscale;
00159     char        star_name[IRPLIB_FITS_STRLEN+1];
00160     char        filter[IRPLIB_FITS_STRLEN+1];
00161     double      bg_sigma;
00162     double      flux_snr;
00163     double      flux_snr_noise;
00164     double      flux_tot;
00165     double      fwhm_x;
00166     double      fwhm_y;
00167     double      fwhm_x_pos1;
00168     double      fwhm_y_pos1;
00169     double      fwhm_x_pos2;
00170     double      fwhm_y_pos2;
00171     double      fwhm_x_neg1;
00172     double      fwhm_y_neg1;
00173     double      fwhm_x_neg2;
00174     double      fwhm_y_neg2;
00175     double      sensitivity;
00176     double      conversion;
00177     double      strehl;
00178     double      strehl_err;
00179 } visir_img_phot_config;
00180 
00181 
00182 /*----------------------------------------------------------------------------*/
00186 /*----------------------------------------------------------------------------*/
00187 
00188 /*-----------------------------------------------------------------------------
00189                                 Functions code
00190  -----------------------------------------------------------------------------*/
00191 
00192 /*----------------------------------------------------------------------------*/
00199 /*----------------------------------------------------------------------------*/
00200 static int visir_img_phot(cpl_frameset            * framelist,
00201                           const cpl_parameterlist * parlist)
00202 {
00203     cpl_errorstate cleanstate = cpl_errorstate_get();
00204     irplib_framelist * allframes = NULL;
00205     irplib_framelist * rawframes = NULL;
00206     cpl_propertylist * qclist    = cpl_propertylist_new();
00207     const char      *  badpix;
00208     const char      *  star_cat;
00209     const char      *  flat;
00210     cpl_image       ** combined = NULL;
00211     cpl_image       ** beam1    = NULL;
00212     const char      *  sval;
00213     cpl_boolean        drop_wcs;
00214     const char       * keys_regexp =  "^(" RECIPE_KEYS_REGEXP_WCS ")$";
00215     const char * combine_string;
00216     cpl_geom_combine combine_mode;
00217 
00218 
00219 
00220     visir_img_phot_config.exptime = -1.0;
00221     visir_img_phot_config.pscale = -1.0;
00222     visir_img_phot_config.star_name[0] = (char)0;
00223     visir_img_phot_config.filter[0] = (char)0;
00224     visir_img_phot_config.bg_sigma = -1.0;
00225     visir_img_phot_config.flux_snr = -1.0;
00226     visir_img_phot_config.flux_snr_noise = -1.0;
00227     visir_img_phot_config.flux_tot = -1.0;
00228     visir_img_phot_config.fwhm_x = -1.0;
00229     visir_img_phot_config.fwhm_y = -1.0;
00230     visir_img_phot_config.fwhm_x_pos1 = -1.0;
00231     visir_img_phot_config.fwhm_y_pos1 = -1.0;
00232     visir_img_phot_config.fwhm_x_pos2 = -1.0;
00233     visir_img_phot_config.fwhm_y_pos2 = -1.0;
00234     visir_img_phot_config.fwhm_x_neg1 = -1.0;
00235     visir_img_phot_config.fwhm_y_neg1 = -1.0;
00236     visir_img_phot_config.fwhm_x_neg2 = -1.0;
00237     visir_img_phot_config.fwhm_y_neg2 = -1.0;
00238     visir_img_phot_config.sensitivity = -1.0;
00239     visir_img_phot_config.conversion = -1.0;
00240     visir_img_phot_config.strehl = -1.0;
00241     visir_img_phot_config.strehl_err = -1.0;
00242 
00243     /* Retrieve input parameters */
00244     combine_string = visir_parameterlist_get_string(parlist, RECIPE_STRING,
00245                                                     VISIR_PARAM_COMBINE);
00246 
00247     bug_if (combine_string == NULL);
00248 
00249     if (combine_string[0] == 'u')
00250         combine_mode = CPL_GEOM_UNION;
00251     else if (combine_string[0] == 'f')
00252         combine_mode = CPL_GEOM_FIRST;
00253     else if (combine_string[0] == 'i')
00254         combine_mode = CPL_GEOM_INTERSECT;
00255     else
00256         skip_if(1);
00257 
00258 
00259     visir_img_phot_config.jy_val = 
00260         visir_parameterlist_get_double(parlist, RECIPE_STRING, VISIR_PARAM_JYVAL);
00261     skip_if (0);
00262 
00263     sval = visir_parameterlist_get_string(parlist, RECIPE_STRING, VISIR_PARAM_RADII);
00264     skip_if (sval == NULL);
00265 
00266     skip_if (sscanf(sval, "%d %d %d",
00267                     &visir_img_phot_config.r0_max,
00268                     &visir_img_phot_config.r1,
00269                     &visir_img_phot_config.r2) != 3);
00270 
00271     /* Identify the RAW and CALIB frames in the input frameset */
00272     skip_if (visir_dfs_set_groups(framelist));
00273 
00274     /* Objects observation */
00275     allframes = irplib_framelist_cast(framelist);
00276     skip_if(allframes == NULL);
00277     rawframes = irplib_framelist_extract(allframes, VISIR_IMG_PHOT_RAW);
00278 
00279     skip_if (rawframes == NULL);
00280 
00281     irplib_framelist_empty(allframes);
00282 
00283     skip_if(irplib_framelist_load_propertylist(rawframes, 0, 0, keys_regexp,
00284                                                CPL_FALSE));
00285 
00286     skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
00287                                                    RECIPE_KEYS_REGEXP_ALL
00288                                                    ")$", CPL_FALSE));
00289 
00290     skip_if(visir_dfs_check_framelist_tag(rawframes));
00291     
00292     /* Standard star catalog */
00293     star_cat = irplib_frameset_find_file(framelist, VISIR_CALIB_STDSTAR_IMG);
00294     if (star_cat == NULL) {
00295          cpl_msg_error(cpl_func, "The input files has no star catalog tagged "
00296                        "%s", VISIR_CALIB_STDSTAR_IMG);
00297          visir_error_set(CPL_ERROR_DATA_NOT_FOUND);
00298          skip_if(1);
00299     }
00300 
00301     /* Bad pixels calibration file */
00302     badpix = irplib_frameset_find_file(framelist, VISIR_CALIB_BPM);
00303 
00304     /* Flatfield calibration file */
00305     flat = irplib_frameset_find_file(framelist, VISIR_CALIB_FLAT);
00306 
00307 
00308     /* DIT must be present every where */  
00309     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DIT,
00310                                       CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00311     if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DIT,
00312                                  CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5)) {
00313         /* Allow 0.1 ms difference - or warn */
00314         /* FIXME: The recipe does not properly handle non-uniform DITSs */  
00315         visir_error_reset("DIT differs by more than %g", 1e-5);
00316     }
00317 
00318     /* FIXME: Verify the angular distance */
00319     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_RA,
00320                                       CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00321 
00322     /* FIXME: Allow 1 degree difference */
00323     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DEC,
00324                                       CPL_TYPE_DOUBLE, CPL_TRUE, 1.0));
00325 
00326     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_CHOP_NCYCLES,
00327                                       CPL_TYPE_INT, CPL_TRUE, 0.0));
00328 
00329     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NDIT,
00330                                       CPL_TYPE_INT, CPL_TRUE, 0.0));
00331 
00332     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_STARNAME,
00333                                       CPL_TYPE_STRING, CPL_TRUE, 0.0));
00334 
00335     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_INSMODE,
00336                                       CPL_TYPE_STRING, CPL_TRUE, 0.0));
00337 
00338     if (strncmp("IMG", visir_pfits_get_insmode(
00339                     irplib_framelist_get_propertylist_const(rawframes, 0)),
00340                 6) == 0) {
00341         skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_FILTER1,
00342                                           CPL_TYPE_STRING, CPL_TRUE, 0.0));
00343     } else {
00344         skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_FILTER2,
00345                                           CPL_TYPE_STRING, CPL_TRUE, 0.0));
00346     }
00347 
00348     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_PIXSCALE,
00349                                       CPL_TYPE_STRING, CPL_TRUE, 0.0));
00350 
00351     /* Combine the frames */
00352     cpl_msg_info(cpl_func, "Combining the images");
00353     combined = visir_img_recombine(RECIPE_STRING, parlist, rawframes, badpix,
00354                                    flat, combine_mode, &drop_wcs,
00355                                    CPL_FALSE, 0.0, 0);
00356 
00357     if (combined == NULL) {
00358         cpl_msg_error(cpl_func, "Could not combine the input frames");
00359         skip_if(1);
00360     }
00361 
00362     beam1 = visir_img_collapse_beam(qclist, combined[0], parlist, RECIPE_STRING,
00363                                     VISIR_CHOPNOD_AUTO,
00364                                     irplib_framelist_get_propertylist_const
00365                                     (rawframes, 0));
00366 
00367     if (beam1 == NULL) {
00368         irplib_error_recover(cleanstate, "Could not collapse the beams of "
00369                              "the combined image");
00370     }
00371 
00372 
00373     
00374     /* Compute the background values of the HCYCLE frames */
00375     skip_if(visir_qc_append_background(qclist, rawframes, 0, 0));
00376 
00377     /* Compute here the sensitivity */
00378     cpl_msg_info(cpl_func, "Computing the sensitivity");
00379     if (visir_img_phot_sensit(combined[0], rawframes, star_cat)) {
00380         cpl_msg_error(cpl_func, "Could not compute sensitivity: '%s' in %s",
00381                         cpl_error_get_message(), cpl_error_get_where());
00382         skip_if(1);
00383     }
00384 
00385     skip_if (visir_img_phot_qc(qclist, drop_wcs, rawframes));
00386     irplib_framelist_empty(rawframes);
00387 
00388     /* Save the combined image and contribution map */
00389     if (beam1 == NULL) {
00390     cpl_msg_info(cpl_func, "Saving the combined image with its contribution "
00391                  "map");
00392         skip_if (visir_img_phot_save(framelist, parlist, qclist, combined[0],
00393                                      combined[1], NULL, NULL));
00394     } else {
00395         cpl_msg_info(cpl_func, "Saving the combined and the beam-combined "
00396                      "images with their contribution maps");
00397         skip_if (visir_img_phot_save(framelist, parlist, qclist, combined[0],
00398                                      combined[1], beam1[0], beam1[1]));
00399     }
00400 
00401     end_skip;
00402 
00403     cpl_propertylist_delete(qclist);
00404     irplib_framelist_delete(allframes);
00405     irplib_framelist_delete(rawframes);
00406 
00407     if (combined) {
00408         cpl_image_delete(combined[0]);
00409         cpl_image_delete(combined[1]);
00410         cpl_free(combined);
00411     }
00412 
00413     if (beam1) {
00414         cpl_image_delete(beam1[0]);
00415         cpl_image_delete(beam1[1]);
00416         cpl_free(beam1);
00417     }
00418 
00419     return cpl_error_get_code();
00420 
00421 }
00422  
00423 /*----------------------------------------------------------------------------*/
00444 /*----------------------------------------------------------------------------*/
00445 static int visir_img_phot_sensit(const cpl_image * combined,
00446                                  const irplib_framelist * rawframes,
00447                                  const char * star_cat)
00448 {
00449     cpl_errorstate cleanstate = cpl_errorstate_get();
00450     const cpl_propertylist * plist = NULL;
00451     double             exptime;
00452     double             dit;
00453     int                ndit;
00454     int                ncycles, nnod;
00455     double             ra, dec;
00456     const char       * sval;
00457     double             f2;
00458 
00459 
00460     skip_if (0);
00461  
00462     plist = irplib_framelist_get_propertylist_const(rawframes, 0);
00463     skip_if (0);
00464 
00465     /* Get the total exposure time */
00466     /* DIT */
00467     dit = visir_pfits_get_dit(plist);
00468     /* NDIT */
00469     ndit = visir_pfits_get_ndit(plist);
00470     /* NNOD */
00471     nnod = irplib_framelist_get_size(rawframes);
00472     /* Number of chopping cycles */
00473     ncycles = visir_pfits_get_chop_ncycles(plist);
00474 
00475     /* Exptime * 2 because of chopping */
00476     exptime = 2 * dit * ndit * nnod * ncycles;
00477     visir_img_phot_config.exptime = exptime;
00478 
00479     if (exptime <= 0 || cpl_error_get_code()) {
00480         cpl_msg_error(cpl_func, "Illegal exposure time "
00481                       "(dit=%g:ndit=%d:ncycles=%d:nnod=%d): %g",
00482                       dit, ndit, ncycles, nnod, exptime);
00483         skip_if(1);
00484     }
00485 
00486     /* Copy the standard star name */
00487     skip_if ((sval = visir_pfits_get_starname(plist)) == NULL);
00488     (void) strncpy(visir_img_phot_config.star_name, sval, fits_strlen);
00489 
00490     /* Copy the filter name */
00491     skip_if ((sval = visir_pfits_get_filter(plist)) == NULL);
00492     (void)strncpy(visir_img_phot_config.filter, sval, fits_strlen);
00493    
00494     /* Get RA / DEC */
00495     ra  = visir_pfits_get_ra(plist);
00496     skip_if (0);
00497     dec = visir_pfits_get_dec(plist);
00498     skip_if (0);
00499 
00500     /* Get the pixel scale */
00501     sval = visir_pfits_get_pixscale(plist);
00502     skip_if (0);
00503 
00504     visir_img_phot_config.pscale = atof(sval);
00505     
00506     /* Get the JY value from the catalog if not user provided */
00507     if (visir_img_phot_config.jy_val < -998) {
00508         visir_img_phot_config.jy_val =
00509             visir_img_phot_jy_from_cat(star_cat, visir_img_phot_config.filter,
00510                                        ra,dec, visir_img_phot_config.star_name);
00511         skip_if (visir_img_phot_config.jy_val < -998);
00512     }
00513     
00514     /* Display the result */
00515     cpl_msg_info(cpl_func, "Star %s with filter %s : %g Jy",
00516             visir_img_phot_config.star_name,
00517             visir_img_phot_config.filter,
00518             visir_img_phot_config.jy_val);
00519    
00520     /* Compute the background signa */
00521     visir_img_phot_config.bg_sigma = visir_img_phot_sigma_clip(combined);
00522     skip_if (0);
00523     
00524     /* Get the flux and flux noise and fwhm */
00525     cpl_msg_info(cpl_func, "Compute the star flux");
00526     sval = visir_pfits_get_chopnod_dir(plist);
00527 #if 1
00528     if (sval != NULL && !strcmp(sval, "PERPENDICULAR")) {
00529         /* 4 sources */
00530         skip_if (visir_img_phot_flux_four(combined));
00531     } else if (sval != NULL && !strcmp(sval, "PARALLEL")) {
00532         /* 3 sources */
00533         skip_if (visir_img_phot_flux_three(combined));
00534     } else {
00535         if (sval == NULL) {
00536             visir_error_reset("Could not get FITS key");
00537         } else {
00538             cpl_msg_warning(cpl_func, "Unknown chopping direction: %s", sval);
00539         }
00540         cpl_msg_warning(cpl_func, "Proceeding as if FITS card %s had value %s",
00541                         "ESO SEQ CHOPNOD DIR", "PERPENDICULAR");
00542         if (visir_img_phot_flux_four(combined)) {
00543             visir_error_reset("Proceeding as if FITS card %s had value %s",
00544                               "ESO SEQ CHOPNOD DIR", "PARALLEL");
00545             skip_if (visir_img_phot_flux_three(combined));
00546         }        
00547     }
00548 #else
00549     if (sval == NULL) {
00550         visir_error_reset("Could not get chopping direction");
00551         if (visir_img_phot_flux_three(combined)) {
00552             cpl_msg_error(cpl_func, "Could not compute the flux");
00553             skip_if(1);
00554         }
00555     } else if (!strcmp(sval, "PARALLEL")) {
00556         /* 3 sources */
00557         if (visir_img_phot_flux_three(combined)) {
00558             cpl_msg_error(cpl_func, "Could not compute the flux");
00559             skip_if(1);
00560         }
00561     } else {
00562         /* Default is 4 sources */
00563         if (strcmp(sval, "PERPENDICULAR"))
00564             cpl_msg_warning(cpl_func, "Unknown chopping direction: %s", sval);
00565         if (visir_img_phot_flux_four(combined)) {
00566             cpl_msg_error(cpl_func, "Could not compute the flux");
00567             skip_if(1);
00568         }
00569     }
00570 #endif
00571 
00572     /* Compute the sensitivity and the conversion factor */
00573 
00574     skip_if ( visir_img_phot_config.flux_snr == 0 );
00575     skip_if ( visir_img_phot_config.flux_snr_noise == 0 );
00576     skip_if ( visir_img_phot_config.jy_val == 0 );
00577 
00578     f2  = visir_img_phot_config.flux_snr / visir_img_phot_config.flux_snr_noise;
00579     f2 *= sqrt(3600/visir_img_phot_config.exptime);
00580     visir_img_phot_config.sensitivity = visir_img_phot_config.jy_val*1000*10/f2;
00581     visir_img_phot_config.conversion = visir_img_phot_config.flux_tot /
00582         visir_img_phot_config.jy_val;
00583 
00584     end_skip;
00585 
00586     cpl_msg_info(cpl_func, "Sensitivity : %g", visir_img_phot_config.sensitivity);
00587     cpl_msg_info(cpl_func, "Conversion  : %g", visir_img_phot_config.conversion);
00588     cpl_msg_info(cpl_func, "Strehl      : %g", visir_img_phot_config.strehl);
00589     cpl_msg_info(cpl_func, "Strehl error: %g", visir_img_phot_config.strehl_err);
00590 
00591     return cpl_error_get_code();
00592 }
00593  
00594 /*----------------------------------------------------------------------------*/
00604 /*----------------------------------------------------------------------------*/
00605 static double visir_img_phot_jy_from_cat(
00606         const char * star_cat,
00607         const char * filter,
00608         double       ra,
00609         double       dec,
00610         const char * star_name) 
00611 {
00612     cpl_table    * tab = NULL;
00613     cpl_vector   * v_ra = NULL;
00614     cpl_vector   * v_dec = NULL;
00615     const char   * stdstar; 
00616     int            nb_stars;
00617     const double   max_radius = VISIR_STAR_MAX_RADIUS;
00618     double         value = -999;
00619     double         jy;
00620     double         dist;
00621     int            min_dist_ind;
00622 
00623 
00624     skip_if( 0 );
00625     skip_if( star_cat  == NULL );
00626     skip_if( star_name == NULL );
00627     skip_if( filter    == NULL );
00628   
00629     /* Open the star catalog */
00630     if ((tab = cpl_table_load(star_cat, 1, 1)) == NULL) {
00631         cpl_msg_error(cpl_func, "Could not load the star catalog: %s",
00632                       star_cat);
00633         skip_if(1);
00634     }
00635 
00636     /* Check that the filter is in the table */
00637     if (!cpl_table_has_column(tab, filter)) {
00638         cpl_msg_error(cpl_func, "Catalog %s has no column for filter: %s",
00639                       star_cat, filter);
00640         visir_error_set(CPL_ERROR_DATA_NOT_FOUND);
00641         skip_if(1);
00642     }
00643 
00644     if (!cpl_table_has_column(tab, "STARS")) {
00645         cpl_msg_error(cpl_func, "Catalog %s does not have a column labeled %s",
00646                       star_cat, "STARS");
00647         visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
00648         skip_if(1);
00649     }
00650 
00651     nb_stars = cpl_table_get_nrow(tab);
00652     skip_if (nb_stars < 1);
00653 
00654     /* Get the RA and DEC columns */
00655     v_ra = cpl_vector_wrap(nb_stars, cpl_table_get_data_double(tab, "RA"));
00656     skip_if( v_ra == NULL);
00657 
00658     v_dec = cpl_vector_wrap(nb_stars, cpl_table_get_data_double(tab, "DEC"));
00659     skip_if( v_dec == NULL);
00660 
00661     min_dist_ind = visir_star_find(v_ra, v_dec, ra, dec, max_radius, &dist);
00662 
00663     if (min_dist_ind < 0) {
00664         cpl_msg_error(cpl_func, "Observation target '%s' was not found among "
00665                       "the %d entries in the standard star catalog %s",
00666                       star_name, nb_stars, star_cat);
00667         skip_if(1);
00668     }
00669 
00670     stdstar = cpl_table_get_string(tab, "STARS", min_dist_ind);
00671     skip_if ( stdstar == NULL );
00672 
00673     jy = cpl_table_get(tab, filter, min_dist_ind, NULL);
00674     skip_if( 0 );
00675 
00676     value = jy;
00677 
00678     if (strcmp(stdstar, star_name) != 0 && dist > 0.0) {
00679         /* The names do not match, nor does the location (exactly) */
00680         cpl_msg_warning(cpl_func, "The standard star '%s' at (RA,DEC)=(%g,%g) "
00681                         "in the FITS header is closest to the catalog star "
00682                         "'%s' at (RA,DEC)=(%g,%g) at distance %g degrees",
00683                         star_name, ra, dec, stdstar,
00684                         cpl_vector_get(v_ra,  min_dist_ind),
00685                         cpl_vector_get(v_dec, min_dist_ind), dist);
00686     } else if (dist > 0.0) {
00687         /* The names match, but the location does not (exactly) */
00688         cpl_msg_warning(cpl_func, "The location of the standard star '%s' in "
00689                         "the FITS header (RA,DEC)=(%g,%g) and the catalog "
00690                         "(RA,DEC)=(%g,%g) differ by %g degrees", stdstar, ra,
00691                         dec, cpl_vector_get(v_ra,  min_dist_ind),
00692                         cpl_vector_get(v_dec, min_dist_ind), dist);
00693     } else if (strcmp(stdstar, star_name) != 0) {
00694         /* The names do not match, but the location does */
00695         cpl_msg_warning(cpl_func, "The name of the standard star at (RA,DEC)="
00696                         "(%g,%g) in the FITS header '%s' and the catalog '%s' "
00697                         "are different", ra, dec, star_name, stdstar);
00698     } else {
00699         cpl_msg_info(cpl_func, "Standard star is '%s' at (RA, DEC)=(%g,%g)",
00700                      stdstar, ra, dec);
00701  
00702         if (cpl_msg_get_level() <= CPL_MSG_DEBUG)
00703             cpl_table_dump(tab, min_dist_ind, 1, stdout);
00704     }
00705 
00706     cpl_msg_info(cpl_func, "The standard star '%s' has %g Jy through filter %s",
00707                  stdstar, value, filter);
00708  
00709     end_skip;
00710 
00711     cpl_table_delete(tab);
00712     cpl_vector_unwrap(v_ra);
00713     cpl_vector_unwrap(v_dec);
00714 
00715     return value;
00716 }
00717 
00718 /*----------------------------------------------------------------------------*/
00727 /*----------------------------------------------------------------------------*/
00728 static int visir_img_phot_flux_three(const cpl_image * combined)
00729 {
00730     cpl_errorstate cleanstate = cpl_errorstate_get();
00731     cpl_image       *   min_combined = NULL;
00732     cpl_apertures   *   appos = NULL;
00733     cpl_apertures   *   apneg = NULL;
00734     cpl_vector      *   sigmas = NULL;
00735     double              psigmas[] = {5, 2, 1, 0.5};
00736     double              x[3];
00737     double              y[3];
00738     double              flux_snr[3];
00739     double              flux_snr_noise[3];
00740     double              flux_tot[3];
00741     double              fwhm_x[3];
00742     double              fwhm_y[3];
00743     double              dist1, dist2;
00744     int                 ngood_fwhm;
00745     double              lam, dlam;
00746     double              star_bg,star_peak,star_flux,psf_peak,psf_flux,bg_noise;
00747     double              eccmin = DBL_MAX;
00748     const int           nsigmas = sizeof(psigmas)/sizeof(double);
00749     int                 isigma;
00750 #ifdef VISIR_IMG_PHOT_USE_ECCENT_THREE
00751     int                 ipos, ineg1, ineg2;
00752 #endif
00753     int                 iappos, iapneg2[2];
00754     int                 i;
00755 
00756 
00757     if (cpl_error_get_code()) return cpl_error_get_code();
00758 
00759     cpl_ensure_code(combined != NULL, CPL_ERROR_NULL_INPUT);
00760 
00761     cpl_msg_info(cpl_func, "Detecting the 3-source star using %d sigma-levels "
00762                  "ranging from %g down to %g", nsigmas, psigmas[0],
00763                  psigmas[nsigmas-1]);
00764 
00765     sigmas = cpl_vector_new(1);
00766     min_combined = cpl_image_multiply_scalar_create(combined, -1.0);
00767     bug_if(0);
00768     for (isigma = 0; isigma < nsigmas; isigma++) {
00769 
00770         /* FIXME: Why ?! */
00771         irplib_error_recover(cleanstate, "Resetting error (why?)");
00772 
00773         bug_if(cpl_vector_set(sigmas, 0, psigmas[isigma]));
00774 
00775         /* Detect where the POSITIVE star is */
00776         cpl_apertures_delete(appos);
00777         appos = cpl_apertures_extract(combined, sigmas, NULL);
00778         if (appos == NULL) {
00779             cpl_msg_warning(cpl_func, "Found no positive star at sigma=%g",
00780                             psigmas[isigma]);
00781             continue;
00782         }
00783 
00784         /* Detect where the NEGATIVE stars are */
00785         cpl_apertures_delete(apneg);
00786         apneg = cpl_apertures_extract(min_combined, sigmas, NULL);
00787         if (apneg == NULL) {
00788             cpl_msg_warning(cpl_func, "Found no negative stars at sigma=%g",
00789                             psigmas[isigma]);
00790             continue;
00791         }
00792         if (cpl_apertures_get_size(apneg) < 2) {
00793             cpl_msg_warning(cpl_func, "Found just 1 negative star at sigma=%g, "
00794                             "need two", psigmas[isigma]);
00795             continue;
00796         }
00797 
00798         cpl_msg_info(cpl_func, "Found positive and negative stars at sigma=%g",
00799                      psigmas[isigma]);
00800         break;
00801     }
00802 
00803     skip_if(appos == NULL);
00804     skip_if(apneg == NULL);
00805     skip_if (cpl_apertures_get_size(apneg) < 2);
00806 
00807     if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
00808         cpl_apertures_dump(appos, stdout);
00809         cpl_apertures_dump(apneg, stdout);
00810     }
00811 
00812 #ifndef VISIR_IMG_PHOT_USE_ECCENT_THREE
00813     bug_if(irplib_apertures_find_max_flux(appos, &iappos, 1));
00814     bug_if(irplib_apertures_find_max_flux(apneg, iapneg2, 2));
00815 #else
00816     if (cpl_apertures_get_size(appos) > 1 || cpl_apertures_get_size(apneg) > 2)
00817         cpl_msg_info(cpl_func, "Selecting from %d positive and %d negative "
00818                      "stars 3 stars on a vertical line",
00819                      cpl_apertures_get_size(appos),
00820                      cpl_apertures_get_size(apneg));
00821 
00822     for (ipos = 1; ipos <= cpl_apertures_get_size(appos); ipos++) {
00823         for (ineg1 = 2; ineg1 <= cpl_apertures_get_size(apneg); ineg1++) {
00824             for (ineg2 = 1; ineg2 < ineg1; ineg2++) {
00825                 const double ecc = visir_img_phot_eccent_three(appos, ipos,
00826                                                                apneg,
00827                                                                ineg1, ineg2);
00828                 if (ecc < eccmin) {
00829                     if (eccmin < DBL_MAX)
00830                         cpl_msg_debug(cpl_func, "Found star positions with "
00831                                       "reduced mis-alignment [pixel]: "
00832                                       "%g < %g", ecc, eccmin);
00833                     eccmin = ecc;
00834                     iappos = ipos;
00835                     iapneg2[0] = ineg1;
00836                     iapneg2[1] = ineg2;
00837                 }
00838             }
00839         }
00840     }
00841 
00842     /* Star 1 should have largest flux */
00843     if (cpl_apertures_get_flux(apneg, iapneg2[0]) <
00844         cpl_apertures_get_flux(apneg, iapneg2[1])) {
00845         const int tmp = iapneg2[0];
00846         iapneg2[0] = iapneg2[1];
00847         iapneg2[1] = tmp;
00848     }
00849 
00850 #endif
00851 
00852     x[0] = cpl_apertures_get_centroid_x(appos, iappos);
00853     y[0] = cpl_apertures_get_centroid_y(appos, iappos);
00854 
00855     x[1] = cpl_apertures_get_centroid_x(apneg, iapneg2[0]);
00856     y[1] = cpl_apertures_get_centroid_y(apneg, iapneg2[0]);
00857     x[2] = cpl_apertures_get_centroid_x(apneg, iapneg2[1]);
00858     y[2] = cpl_apertures_get_centroid_y(apneg, iapneg2[1]);
00859 
00860     cpl_apertures_delete(appos);
00861     cpl_apertures_delete(apneg);
00862     appos = NULL;
00863     apneg = NULL;
00864 
00865     cpl_msg_info(cpl_func, "Positive star at position %g %g", x[0], y[0]);
00866     cpl_msg_info(cpl_func, "Negative star 1 at position %g %g", x[1], y[1]);
00867     cpl_msg_info(cpl_func, "Negative star 2 at position %g %g", x[2], y[2]);
00868 
00869     dist1 = sqrt((x[1]-x[0])*(x[1]-x[0])+(y[1]-y[0])*(y[1]-y[0]));
00870     dist2 = sqrt((x[2]-x[0])*(x[2]-x[0])+(y[2]-y[0])*(y[2]-y[0]));
00871     cpl_msg_info(cpl_func, "Star 1 Pos/Neg Distance: %g", dist1);
00872     cpl_msg_info(cpl_func, "Star 2 Pos/Neg Distance: %g", dist2);
00873 
00874 
00875     if (eccmin < DBL_MAX) {
00876         cpl_msg_info(cpl_func, "The deviation from a vertical line by "
00877                      "the three stars [pixel]: %g", eccmin);
00878         if (eccmin > VISIR_IMG_PHOT_POS_WARN) {
00879             if (eccmin > VISIR_IMG_PHOT_POS_ERROR) {
00880                 cpl_msg_error(cpl_func, "The deviation from a vertical line"
00881                               " by the three stars exceed %g, the detected "
00882                               "objects are wrong", VISIR_IMG_PHOT_POS_ERROR);
00883                 skip_if(1);
00884             }
00885             cpl_msg_warning(cpl_func, "The deviation from a vertical line "
00886                             "by the three stars exceed %g, the detected "
00887                             "objects may be wrong", VISIR_IMG_PHOT_POS_WARN);
00888         }
00889     }
00890 
00891     /* FIXME: Pick other object instead, and lower sigma if needed */
00892     if ((int)x[0]-IRPLIB_STREHL_BORDER <= 0 ||
00893         (int)y[0]-IRPLIB_STREHL_BORDER <= 0 ||
00894         (int)x[0]+IRPLIB_STREHL_BORDER > cpl_image_get_size_x(combined) || 
00895         (int)y[0]+IRPLIB_STREHL_BORDER > cpl_image_get_size_y(combined)) {
00896         cpl_msg_error(cpl_func, "Positive star at (%g,%g) is less than %d "
00897                       "pixels from the image border", x[0], y[0],
00898                       1+IRPLIB_STREHL_BORDER);
00899         skip_if(1);
00900     }
00901 
00902     /* FIXME: Useful ? */
00903     /* Verify the stars positions */
00904     if (fabs(dist1-dist2) > VISIR_IMG_PHOT_POS_UNCERTAINTY) {
00905         cpl_msg_error(cpl_func, "Too large Pos/Neg Distance between the two "
00906                       "stars: %g > %g", fabs(dist1-dist2),
00907                       VISIR_IMG_PHOT_POS_UNCERTAINTY);
00908         skip_if(1);
00909     }
00910 
00911     /* Photometry on positive stars */
00912     skip_if (visir_img_phot_flux(combined,
00913             x[0], y[0],
00914             visir_img_phot_config.r0_max,
00915             visir_img_phot_config.r1,
00916             visir_img_phot_config.r2,
00917             &(flux_snr[0]),
00918             &(flux_snr_noise[0]),
00919             &(flux_tot[0]),
00920             &(fwhm_x[0]),
00921             &(fwhm_y[0])));
00922 
00923     /* Photometry on negative stars */
00924     for (i=1 ; i<3 ; i++)
00925         skip_if (visir_img_phot_flux(min_combined,
00926                 x[i], y[i],
00927                 visir_img_phot_config.r0_max,
00928                 visir_img_phot_config.r1,
00929                 visir_img_phot_config.r2,
00930                 &(flux_snr[i]),
00931                 &(flux_snr_noise[i]),
00932                 &(flux_tot[i]),
00933                 &(fwhm_x[i]),
00934                 &(fwhm_y[i])));
00935 
00936     cpl_image_delete(min_combined);
00937     min_combined = NULL;
00938     
00939     /* Compute the results */
00940     /* Flux */
00941     visir_img_phot_config.flux_snr = 0.0;
00942     for (i=0 ; i<3 ; i++) visir_img_phot_config.flux_snr += flux_snr[i];
00943 
00944     /* Flux noise */
00945     visir_img_phot_config.flux_snr_noise = 0.0;
00946     for (i=0 ; i<3 ; i++) visir_img_phot_config.flux_snr_noise +=
00947         flux_snr_noise[i]*flux_snr_noise[i];
00948     visir_img_phot_config.flux_snr_noise = 
00949         sqrt(visir_img_phot_config.flux_snr_noise);
00950 
00951     /* Total flux */
00952     visir_img_phot_config.flux_tot = 0.0;
00953     for (i=0 ; i<3 ; i++) visir_img_phot_config.flux_tot += flux_tot[i];
00954     
00955     /* FWHM */
00956     ngood_fwhm = 0;
00957     visir_img_phot_config.fwhm_x = 0.0;
00958     for (i=0 ; i<3 ; i++) {
00959         if (fwhm_x[i] > 0.0) {
00960             visir_img_phot_config.fwhm_x += fwhm_x[i];
00961             ngood_fwhm ++;
00962         }
00963     }
00964     if (ngood_fwhm > 0) visir_img_phot_config.fwhm_x /= ngood_fwhm;
00965     else visir_img_phot_config.fwhm_x = -1.0;
00966     ngood_fwhm = 0;
00967     visir_img_phot_config.fwhm_y = 0.0;
00968     for (i=0 ; i<3 ; i++) {
00969         if (fwhm_y[i] > 0.0) {
00970             visir_img_phot_config.fwhm_y += fwhm_y[i];
00971             ngood_fwhm ++;
00972         }
00973     }
00974     if (ngood_fwhm > 0) visir_img_phot_config.fwhm_y /= ngood_fwhm;
00975     else visir_img_phot_config.fwhm_y = -1.0;
00976     visir_img_phot_config.fwhm_x_pos1 = fwhm_x[0];
00977     visir_img_phot_config.fwhm_y_pos1 = fwhm_y[0];
00978     visir_img_phot_config.fwhm_x_neg1 = fwhm_x[1];
00979     visir_img_phot_config.fwhm_y_neg1 = fwhm_y[1];
00980     visir_img_phot_config.fwhm_x_neg2 = fwhm_x[2];
00981     visir_img_phot_config.fwhm_y_neg2 = fwhm_y[2];
00982 
00983     /* Get lam and dlam from the filter name for the Strehl computation */
00984     if (visir_get_filter_infos(visir_img_phot_config.filter, &lam, &dlam)) {
00985         cpl_msg_error(cpl_func, "Could not get info for filter: %s",
00986                 visir_img_phot_config.filter);
00987         skip_if(1);
00988     }
00989     
00990     /* Strehl computation */
00991     if (irplib_strehl_compute(combined, STREHL_M1, STREHL_M2, lam, dlam, 
00992                 visir_img_phot_config.pscale,
00993                 STREHL_BOX_SIZE, x[0], y[0], STREHL_STAR_RADIUS,
00994                 STREHL_BG_R1, STREHL_BG_R2, -1, -1, 
00995                 &(visir_img_phot_config.strehl), 
00996                 &(visir_img_phot_config.strehl_err),
00997                 &star_bg, &star_peak, &star_flux, &psf_peak, &psf_flux,
00998                 &bg_noise)) {
00999         cpl_msg_error(cpl_func, "Could not compute the strehl: '%s' in %s",
01000                         cpl_error_get_message(), cpl_error_get_where());
01001         skip_if(1);
01002     }
01003 
01004 
01005     end_skip;
01006 
01007     cpl_apertures_delete(appos);
01008     cpl_apertures_delete(apneg);
01009     cpl_vector_delete(sigmas);
01010     cpl_image_delete(min_combined);
01011     
01012     return cpl_error_get_code();
01013 }
01014 
01015 /*----------------------------------------------------------------------------*/
01024 /*----------------------------------------------------------------------------*/
01025 static int visir_img_phot_flux_four(const cpl_image * combined)
01026 {
01027     cpl_errorstate cleanstate = cpl_errorstate_get();
01028     cpl_image       *   min_combined = NULL;
01029     cpl_apertures   *   appos = NULL;
01030     cpl_apertures   *   apneg = NULL;
01031     cpl_vector      *   sigmas = NULL;
01032     double              psigmas[] = {5, 2, 1, 0.5};
01033     double              x[4];
01034     double              y[4];
01035     double              flux_snr[4];
01036     double              flux_snr_noise[4];
01037     double              flux_tot[4];
01038     double              fwhm_x[4];
01039     double              fwhm_y[4];
01040     double              dist1, dist2;
01041     int                 ngood_fwhm;
01042     double              lam, dlam;
01043     double              star_bg,star_peak,star_flux,psf_peak,psf_flux,bg_noise;
01044     double              eccmin = DBL_MAX;
01045     const int           nsigmas = sizeof(psigmas)/sizeof(double);
01046     int                 isigma;
01047     int                 ipos1, ipos2, ineg1, ineg2;
01048     int                 i;
01049     int                 iappos2[] = {0, 0}; /* Avoid (false) uninit warning */
01050     int                 iapneg2[] = {0, 0}; /* Avoid (false) uninit warning */
01051 
01052 
01053     if (cpl_error_get_code()) return cpl_error_get_code();
01054 
01055     cpl_ensure_code(combined != NULL, CPL_ERROR_NULL_INPUT);
01056 
01057     cpl_msg_info(cpl_func, "Detecting the 4-source star using %d sigma-levels "
01058                  "ranging from %g down to %g", nsigmas, psigmas[0],
01059                  psigmas[nsigmas-1]);
01060 
01061     sigmas = cpl_vector_new(1);
01062     min_combined = cpl_image_multiply_scalar_create(combined, -1.0);
01063     bug_if(0);
01064     for (isigma = 0; isigma < nsigmas; isigma++) {
01065 
01066         /* FIXME: Why ?! */
01067         irplib_error_recover(cleanstate, "Resetting error (why?)");
01068 
01069         bug_if(cpl_vector_set(sigmas, 0, psigmas[isigma]));
01070 
01071         /* Detect where the POSITIVE stars are */
01072         cpl_apertures_delete(appos);
01073         appos = cpl_apertures_extract(combined, sigmas, NULL);
01074         if (appos == NULL) {
01075             cpl_msg_warning(cpl_func, "Found no positive stars at sigma=%g",
01076                             psigmas[isigma]);
01077             continue;
01078         }
01079         if (cpl_apertures_get_size(appos) < 2) {
01080             cpl_msg_warning(cpl_func, "Found just 1 positive star at sigma=%g, "
01081                             "need two", psigmas[isigma]);
01082             continue;
01083         }
01084 
01085         /* Detect where the NEGATIVE stars are */
01086         cpl_apertures_delete(apneg);
01087         apneg = cpl_apertures_extract(min_combined, sigmas, NULL);
01088         if (apneg == NULL) {
01089             cpl_msg_warning(cpl_func, "Found no negative stars at sigma=%g",
01090                             psigmas[isigma]);
01091             continue;
01092         }
01093         if (cpl_apertures_get_size(apneg) < 2) {
01094             cpl_msg_warning(cpl_func, "Found just 1 negative star at sigma=%g, "
01095                             "need two", psigmas[isigma]);
01096             continue;
01097         }
01098 
01099         cpl_msg_info(cpl_func, "Found positive and negative stars at sigma=%g",
01100                      psigmas[isigma]);
01101         break;
01102     }
01103 
01104     skip_if(appos == NULL);
01105     skip_if(apneg == NULL);
01106     skip_if (cpl_apertures_get_size(appos) < 2);
01107     skip_if (cpl_apertures_get_size(apneg) < 2);
01108 
01109     if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
01110         cpl_apertures_dump(appos, stdout);
01111         cpl_apertures_dump(apneg, stdout);
01112     }
01113 
01114     if (cpl_apertures_get_size(appos) > 2 || cpl_apertures_get_size(apneg) > 2)
01115         cpl_msg_info(cpl_func, "Selecting from %d positive and %d negative "
01116                      "stars two pairs that outline a square",
01117                      cpl_apertures_get_size(appos),
01118                      cpl_apertures_get_size(apneg));
01119 
01120     for (ipos1 = 2; ipos1 <= cpl_apertures_get_size(appos); ipos1++) {
01121         for (ipos2 = 1; ipos2 < ipos1; ipos2++) {
01122             for (ineg1 = 2; ineg1 <= cpl_apertures_get_size(apneg); ineg1++) {
01123                 for (ineg2 = 1; ineg2 < ineg1; ineg2++) {
01124                     const double ecc = visir_img_phot_eccent_four(appos, ipos1,
01125                                                                   ipos2, apneg,
01126                                                                   ineg1, ineg2);
01127 
01128                     if (ecc < eccmin) {
01129                         if (eccmin < DBL_MAX)
01130                             cpl_msg_debug(cpl_func, "Found star positions with "
01131                                          "reduced non-square-ness [pixel]: "
01132                                          "%g < %g", ecc, eccmin);
01133                         eccmin = ecc;
01134                         iappos2[0] = ipos1;
01135                         iappos2[1] = ipos2;
01136                         iapneg2[0] = ineg1;
01137                         iapneg2[1] = ineg2;
01138                     }
01139                 }
01140             }
01141         }
01142     }
01143 
01144     /* Star 1 should have largest flux */
01145     if (cpl_apertures_get_flux(appos, iappos2[0]) <
01146         cpl_apertures_get_flux(appos, iappos2[1])) {
01147         const int tmp = iappos2[0];
01148         iappos2[0] = iappos2[1];
01149         iappos2[1] = tmp;
01150     }
01151     if (cpl_apertures_get_flux(apneg, iapneg2[0]) <
01152         cpl_apertures_get_flux(apneg, iapneg2[1])) {
01153         const int tmp = iapneg2[0];
01154         iapneg2[0] = iapneg2[1];
01155         iapneg2[1] = tmp;
01156     }
01157 
01158 
01159     x[0] = cpl_apertures_get_centroid_x(appos, iappos2[0]);
01160     y[0] = cpl_apertures_get_centroid_y(appos, iappos2[0]);
01161     x[1] = cpl_apertures_get_centroid_x(appos, iappos2[1]);
01162     y[1] = cpl_apertures_get_centroid_y(appos, iappos2[1]);
01163 
01164     x[2] = cpl_apertures_get_centroid_x(apneg, iapneg2[0]);
01165     y[2] = cpl_apertures_get_centroid_y(apneg, iapneg2[0]);
01166     x[3] = cpl_apertures_get_centroid_x(apneg, iapneg2[1]);
01167     y[3] = cpl_apertures_get_centroid_y(apneg, iapneg2[1]);
01168 
01169     cpl_apertures_delete(appos);
01170     cpl_apertures_delete(apneg);
01171     appos = NULL;
01172     apneg = NULL;
01173 
01174     cpl_msg_info(cpl_func, "Positive star 1 at position %g %g", x[0], y[0]);
01175     cpl_msg_info(cpl_func, "Positive star 2 at position %g %g", x[1], y[1]);
01176 
01177     cpl_msg_info(cpl_func, "Negative star 1 at position %g %g", x[2], y[2]);
01178     cpl_msg_info(cpl_func, "Negative star 2 at position %g %g", x[3], y[3]);
01179 
01180     /* FIXME: Useful ?  - change to 1D-distances  - and move into sigma loop */
01181     dist1 = sqrt((x[2]-x[0])*(x[2]-x[0])+(y[2]-y[0])*(y[2]-y[0]));
01182     dist2 = sqrt((x[3]-x[1])*(x[3]-x[1])+(y[3]-y[1])*(y[3]-y[1]));
01183     cpl_msg_info(cpl_func, "Star 1 Pos/Neg Distance: %g", dist1);
01184     cpl_msg_info(cpl_func, "Star 2 Pos/Neg Distance: %g", dist2);
01185 
01186     if (eccmin < DBL_MAX) {
01187         cpl_msg_info(cpl_func, "The deviation from a horizontal square by "
01188                      "the two star pairs [pixel]: %g", eccmin);
01189         if (eccmin > VISIR_IMG_PHOT_POS_WARN) {
01190             if (eccmin > VISIR_IMG_PHOT_POS_ERROR) {
01191                 cpl_msg_error(cpl_func, "The deviation from a horizontal square"
01192                               " by the two star pairs exceed %g, the detected "
01193                               "objects are wrong", VISIR_IMG_PHOT_POS_ERROR);
01194                 skip_if(1);
01195             }
01196             cpl_msg_warning(cpl_func, "The deviation from a horizontal square "
01197                             "by the two star pairs exceed %g, the detected "
01198                             "objects may be wrong", VISIR_IMG_PHOT_POS_WARN);
01199         }
01200     }
01201 
01202     if ((int)x[0]-IRPLIB_STREHL_BORDER <= 0 ||
01203         (int)y[0]-IRPLIB_STREHL_BORDER <= 0 ||
01204         (int)x[0]+IRPLIB_STREHL_BORDER > cpl_image_get_size_x(combined) || 
01205         (int)y[0]+IRPLIB_STREHL_BORDER > cpl_image_get_size_y(combined)) {
01206         cpl_msg_error(cpl_func, "Positive star 1 at (%g,%g) is less than %d "
01207                       "pixels from the image border", x[0], y[0],
01208                       1+IRPLIB_STREHL_BORDER);
01209         skip_if(1);
01210     }
01211 
01212     /* Verify the stars positions */
01213     if (fabs(dist1-dist2) > VISIR_IMG_PHOT_POS_UNCERTAINTY) {
01214         cpl_msg_error(cpl_func, "Too large Pos/Neg Distance between the two "
01215                       "stars: %g > %g", fabs(dist1-dist2),
01216                       VISIR_IMG_PHOT_POS_UNCERTAINTY);
01217         skip_if(1);
01218     }
01219 
01220     /* Photometry on positive stars */
01221     for (i=0 ; i<2 ; i++)
01222         skip_if (visir_img_phot_flux(combined,
01223                 x[i], y[i],
01224                 visir_img_phot_config.r0_max,
01225                 visir_img_phot_config.r1,
01226                 visir_img_phot_config.r2,
01227                 &(flux_snr[i]),
01228                 &(flux_snr_noise[i]),
01229                 &(flux_tot[i]),
01230                 &(fwhm_x[i]),
01231                 &(fwhm_y[i])));
01232 
01233     /* Photometry on negative stars */
01234     for (i=2 ; i<4 ; i++)
01235         skip_if (visir_img_phot_flux(min_combined,
01236                 x[i], y[i],
01237                 visir_img_phot_config.r0_max,
01238                 visir_img_phot_config.r1,
01239                 visir_img_phot_config.r2,
01240                 &(flux_snr[i]),
01241                 &(flux_snr_noise[i]),
01242                 &(flux_tot[i]),
01243                 &(fwhm_x[i]),
01244                 &(fwhm_y[i])));
01245 
01246     cpl_image_delete(min_combined);
01247     min_combined = NULL;
01248     
01249     /* Compute the results */
01250     /* Flux */
01251     visir_img_phot_config.flux_snr = 0.0;
01252     for (i=0 ; i<4 ; i++) visir_img_phot_config.flux_snr += flux_snr[i];
01253 
01254     /* Flux noise */
01255     visir_img_phot_config.flux_snr_noise = 0.0;
01256     for (i=0 ; i<4 ; i++) visir_img_phot_config.flux_snr_noise +=
01257         flux_snr_noise[i]*flux_snr_noise[i];
01258     visir_img_phot_config.flux_snr_noise = 
01259         sqrt(visir_img_phot_config.flux_snr_noise);
01260 
01261     /* Total flux */
01262     visir_img_phot_config.flux_tot = 0.0;
01263     for (i=0 ; i<4 ; i++) visir_img_phot_config.flux_tot += flux_tot[i];
01264     
01265     /* FWHM */
01266     ngood_fwhm = 0;
01267     visir_img_phot_config.fwhm_x = 0.0;
01268     for (i=0 ; i<4 ; i++) {
01269         if (fwhm_x[i] > 0.0) {
01270             visir_img_phot_config.fwhm_x += fwhm_x[i];
01271             ngood_fwhm ++;
01272         }
01273     }
01274     if (ngood_fwhm > 0) visir_img_phot_config.fwhm_x /= ngood_fwhm;
01275     else visir_img_phot_config.fwhm_x = -1.0;
01276     ngood_fwhm = 0;
01277     visir_img_phot_config.fwhm_y = 0.0;
01278     for (i=0 ; i<4 ; i++) {
01279         if (fwhm_y[i] > 0.0) {
01280             visir_img_phot_config.fwhm_y += fwhm_y[i];
01281             ngood_fwhm ++;
01282         }
01283     }
01284     if (ngood_fwhm > 0) visir_img_phot_config.fwhm_y /= ngood_fwhm;
01285     else visir_img_phot_config.fwhm_y = -1.0;
01286     visir_img_phot_config.fwhm_x_pos1 = fwhm_x[0];
01287     visir_img_phot_config.fwhm_y_pos1 = fwhm_y[0];
01288     visir_img_phot_config.fwhm_x_pos2 = fwhm_x[1];
01289     visir_img_phot_config.fwhm_y_pos2 = fwhm_y[1];
01290     visir_img_phot_config.fwhm_x_neg1 = fwhm_x[2];
01291     visir_img_phot_config.fwhm_y_neg1 = fwhm_y[2];
01292     visir_img_phot_config.fwhm_x_neg2 = fwhm_x[3];
01293     visir_img_phot_config.fwhm_y_neg2 = fwhm_y[3];
01294 
01295     /* Get lam and dlam from the filter name for the Strehl computation */
01296     if (visir_get_filter_infos(visir_img_phot_config.filter, &lam, &dlam)) {
01297         cpl_msg_error(cpl_func, "Central wavelength and width is missing for "
01298                       "filter: %s", visir_img_phot_config.filter);
01299         skip_if(1);
01300     }
01301     
01302     /* Strehl computation */
01303     if (irplib_strehl_compute(combined, STREHL_M1, STREHL_M2, lam, dlam, 
01304                 visir_img_phot_config.pscale,
01305                 STREHL_BOX_SIZE, x[0], y[0], STREHL_STAR_RADIUS,
01306                 STREHL_BG_R1, STREHL_BG_R2, -1, -1, 
01307                 &(visir_img_phot_config.strehl), 
01308                 &(visir_img_phot_config.strehl_err),
01309                 &star_bg, &star_peak, &star_flux, &psf_peak, &psf_flux,
01310                 &bg_noise)) {
01311         cpl_msg_error(cpl_func, "Could not compute the strehl: '%s' in %s",
01312                         cpl_error_get_message(), cpl_error_get_where());
01313         skip_if(1);
01314     }
01315     
01316 
01317     end_skip;
01318 
01319     cpl_apertures_delete(appos);
01320     cpl_apertures_delete(apneg);
01321     cpl_vector_delete(sigmas);
01322     cpl_image_delete(min_combined);
01323     
01324     return cpl_error_get_code();
01325 
01326 }
01327 
01328 
01329 /*----------------------------------------------------------------------------*/
01345 /*----------------------------------------------------------------------------*/
01346 static double visir_img_phot_eccent_four(const cpl_apertures * appos,
01347                                          int ipos1, int ipos2,
01348                                          const cpl_apertures * apneg,
01349                                          int ineg1, int ineg2)
01350 {
01351 
01352     /* NB: Lower left pixel is (1, 1) */
01353 
01354     /* The two positive points */
01355     const double xp1 = cpl_apertures_get_centroid_x(appos, ipos1);
01356     const double xp2 = cpl_apertures_get_centroid_x(appos, ipos2);
01357     const double yp1 = cpl_apertures_get_centroid_y(appos, ipos1);
01358     const double yp2 = cpl_apertures_get_centroid_y(appos, ipos2);
01359 
01360     /* The leftmost positive point */
01361     const double xpl = xp1 < xp2 ? xp1 : xp2;
01362     const double ypl = xp1 < xp2 ? yp1 : yp2;
01363 
01364     /* The rightmost positive point */
01365     const double xpr = xp1 < xp2 ? xp2 : xp1;
01366     const double ypr = xp1 < xp2 ? yp2 : yp1;
01367 
01368     /* The two negative points */
01369     const double xn1 = cpl_apertures_get_centroid_x(apneg, ineg1);
01370     const double yn1 = cpl_apertures_get_centroid_y(apneg, ineg1);
01371     const double xn2 = cpl_apertures_get_centroid_x(apneg, ineg2);
01372     const double yn2 = cpl_apertures_get_centroid_y(apneg, ineg2);
01373 
01374     /* The leftmost negative point */
01375     const double xln = xn1 < xn2 ? xn1 : xn2;
01376     const double yln = xn1 < xn2 ? yn1 : yn2;
01377 
01378     /* The rightmost engative point */
01379     const double xrn = xn1 < xn2 ? xn2 : xn1;
01380     const double yrn = xn1 < xn2 ? yn2 : yn1;
01381 
01382     const double lx1 = xrn - xpl; /* The length of the top x-side */
01383     const double lx2 = xpr - xln; /* The length of the bottom x-side */
01384     const double ly1 = ypl - yln; /* The length of the left y-side */
01385     const double ly2 = yrn - ypr; /* The length of the right y-side */
01386 
01387     const double lmean = 0.25 * ( lx1 + lx2 + ly1 + ly2);
01388 
01389     const double dx1 = lx1 - lmean;
01390     const double dx2 = lx2 - lmean;
01391     const double dy1 = ly1 - lmean;
01392     const double dy2 = ly2 - lmean;
01393 
01394     const double ey1 = yrn - ypl; /* The displacement in the top x-side */
01395     const double ey2 = ypr - yln; /* The displacement in the bottom x-side */
01396     const double ex1 = xpl - xln; /* The displacement in the left y-side */
01397     const double ex2 = xpr - xrn; /* The displacement in the right y-side */
01398 
01399     const double result = sqrt(dx1 * dx1 + dx2 * dx2 + dy1 * dy1 + dy2 * dy2 +
01400                                ex1 * ex1 + ex2 * ex2 + ey1 * ey1 + ey2 * ey2);
01401 
01402 
01403     bug_if(0);
01404 
01405     bug_if(appos == apneg);
01406     bug_if(ipos1 == ipos2);
01407     bug_if(ineg1 == ineg2);
01408 
01409     end_skip;    
01410 
01411     return result;
01412   
01413 
01414 }
01415 
01416 #ifdef VISIR_IMG_PHOT_USE_ECCENT_THREE
01417 /*----------------------------------------------------------------------------*/
01432 /*----------------------------------------------------------------------------*/
01433 static double visir_img_phot_eccent_three(const cpl_apertures * appos,
01434                                           int ipos,
01435                                           const cpl_apertures * apneg,
01436                                           int ineg1, int ineg2)
01437 {
01438 
01439     /* NB: Lower left pixel is (1, 1) */
01440 
01441     /* The positive point */
01442     const double xp = cpl_apertures_get_centroid_x(appos, ipos);
01443     const double yp = cpl_apertures_get_centroid_y(appos, ipos);
01444 
01445     /* The two negative points */
01446     const double xn1 = cpl_apertures_get_centroid_x(apneg, ineg1);
01447     const double yn1 = cpl_apertures_get_centroid_y(apneg, ineg1);
01448     const double xn2 = cpl_apertures_get_centroid_x(apneg, ineg2);
01449     const double yn2 = cpl_apertures_get_centroid_y(apneg, ineg2);
01450 
01451     /* The bottom negative point */
01452     const double xnb = xn1 < xn2 ? xn1 : xn2;
01453     const double ynb = xn1 < xn2 ? yn1 : yn2;
01454 
01455     /* The top engative point */
01456     const double xnt = xn1 < xn2 ? xn2 : xn1;
01457     const double ynt = xn1 < xn2 ? yn2 : yn1;
01458 
01459     const double l1  = ynt - yp;  /* The length of the top line */
01460     const double l2  = yp  - ynb; /* The length of the bottom line */
01461     const double ln  = ynt - ynb; /* The length of the top to bottom line */
01462 
01463     const double lmean = 0.25 * ( l1 + l2 + ln);
01464 
01465     const double d1 = l1 - lmean;
01466     const double d2 = l2 - lmean;
01467     const double dn = 0.5 * ln - lmean;
01468 
01469     const double e1 = xp - xnt; /* The displacement in the top line */
01470     const double e2 = xp - xnb; /* The displacement in the bottom line */
01471 
01472     const double result = sqrt(d1 * d1 + d2 * d2 + dn * dn + e1 * e1 + e2 * e2);
01473 
01474 
01475     bug_if(0);
01476 
01477     bug_if(appos == apneg);
01478     bug_if(ineg1 == ineg2);
01479 
01480     end_skip;    
01481 
01482     return result;
01483   
01484 
01485 }
01486 
01487 #endif
01488  
01489 /*----------------------------------------------------------------------------*/
01508 /*----------------------------------------------------------------------------*/
01509 static int visir_img_phot_flux(
01510         const cpl_image * combined,
01511         double          x_pos,
01512         double          y_pos,
01513         int             r0_max,
01514         int             r1,
01515         int             r2,
01516         double      *   flux_snr,
01517         double      *   flux_snr_noise,
01518         double      *   flux_tot,
01519         double      *   fwhm_x,
01520         double      *   fwhm_y)
01521 {
01522     cpl_apertures   *   apert = NULL;
01523     cpl_image       *   labels;
01524     cpl_image       *   bg_subtracted = NULL;
01525     cpl_vector      *   r0 = NULL;
01526     cpl_vector      *   fl = NULL;
01527     cpl_vector      *   fl_noise = NULL;
01528     cpl_vector      *   snr = NULL;
01529     double              bg, fl_val;
01530     double              max_val = 0.0; /* Avoid (false) uninit warning */
01531     int                 max_ind = 0;   /* Avoid (false) uninit warning */
01532     int                 i;
01533     int                 nx, ny;
01534 
01535 
01536     if (cpl_error_get_code()) return cpl_error_get_code();
01537 
01538     cpl_ensure_code(combined != NULL, CPL_ERROR_NULL_INPUT);
01539     cpl_ensure_code(r0_max > 0,       CPL_ERROR_ILLEGAL_INPUT);
01540 
01541     nx = cpl_image_get_size_x(combined);
01542     ny = cpl_image_get_size_y(combined);
01543 
01544     /* Create the label image defining the background ring */
01545     if ((labels = visir_create_ring_intimage(nx, ny, 
01546             (int)x_pos, (int)y_pos, r1, r2)) == NULL) {
01547         cpl_msg_error(cpl_func, "Could not create a ring image");
01548         skip_if(1);
01549     }
01550     /* Compute the background */
01551     apert = cpl_apertures_new_from_image(combined, labels);
01552     cpl_image_delete(labels);
01553     labels = NULL;
01554     bg = cpl_apertures_get_median(apert, 1);
01555     cpl_apertures_delete(apert);
01556     apert = NULL;
01557     cpl_msg_info(cpl_func, "Background : %g", bg);
01558    
01559     /* Create the label image defining the total star disk */
01560     if ((labels = visir_create_disk_intimage(nx, ny, 
01561             (int)x_pos, (int)y_pos, r0_max)) == NULL) {
01562         cpl_msg_error(cpl_func, "Could not create a disk image");
01563         skip_if(1);
01564     }
01565 
01566     /* Compute the total flux and the associated error */
01567 
01568     bg_subtracted = cpl_image_subtract_scalar_create(combined, bg);
01569 
01570     apert = cpl_apertures_new_from_image(bg_subtracted, labels);
01571     cpl_image_delete(labels);
01572     labels = NULL;
01573     *flux_tot = cpl_apertures_get_flux(apert, 1);
01574     cpl_apertures_delete(apert);
01575     apert = NULL;
01576     cpl_msg_info(cpl_func, "Star total flux (error): %g", *flux_tot);
01577     
01578     /* Create and fill r0 */
01579     r0 = cpl_vector_new(r0_max);
01580     for (i=0 ; i<r0_max ; i++) cpl_vector_set(r0, i, i+1);
01581 
01582     /* Create fl, fl_noise */
01583     fl = cpl_vector_new(r0_max);
01584     fl_noise = cpl_vector_new(r0_max);
01585     
01586     /* For each radius, compute fl and fl_noise */
01587     for (i=0 ; i<r0_max ; i++) {
01588         /* Create the label image defining the current star disk */
01589         if ((labels = visir_create_disk_intimage(nx, ny, 
01590                 (int)x_pos, (int)y_pos, (int)cpl_vector_get(r0, i))) == NULL) {
01591             cpl_msg_error(cpl_func, "Could not create a disk image: %d", i);
01592             break;
01593         }
01594         /* Compute the statistics on the zone defined by the labels */
01595         apert = cpl_apertures_new_from_image(bg_subtracted, labels);
01596         /* FIXME: apert == NULL ? */
01597         cpl_image_delete(labels);
01598         labels = NULL;
01599         fl_val = cpl_apertures_get_flux(apert, 1);
01600         cpl_vector_set(fl, i, fl_val);
01601         cpl_vector_set(fl_noise, i, visir_img_phot_config.bg_sigma * 
01602                 sqrt((double)cpl_apertures_get_npix(apert, 1)));
01603         cpl_apertures_delete(apert);
01604         apert = NULL;
01605     }
01606     skip_if( 0 );
01607 
01608     /* Compute the flux (and error) for the best signal to noise */
01609     snr = cpl_vector_duplicate(fl);
01610     cpl_vector_divide(snr, fl_noise);
01611     for (i=0 ; i<r0_max ; i++) {
01612         if (i == 0 || max_val < cpl_vector_get(snr, i)) {
01613             max_val = cpl_vector_get(snr, i);
01614             max_ind = i;
01615         }
01616     }
01617     *flux_snr = cpl_vector_get(fl, max_ind);
01618     *flux_snr_noise = cpl_vector_get(fl_noise, max_ind);
01619     cpl_msg_info(cpl_func, "Best SNR star flux : %g for radius %g",
01620             *flux_snr, cpl_vector_get(r0, max_ind));
01621     
01622     /* Compute the FWHM */
01623     skip_if (cpl_image_get_fwhm(bg_subtracted, (int)x_pos, (int)y_pos, fwhm_x,
01624                                 fwhm_y));
01625 
01626     cpl_msg_info(cpl_func, "FWHM : %g in x ; %g in y ", *fwhm_x, *fwhm_y);
01627 
01628     skip_if ( *fwhm_x <= 0.0 );
01629     skip_if ( *fwhm_y <= 0.0 );
01630 
01631     end_skip;
01632 
01633     cpl_apertures_delete(apert);
01634     cpl_image_delete(labels);
01635     cpl_image_delete(bg_subtracted);
01636 
01637     cpl_vector_delete(r0);
01638     cpl_vector_delete(fl);
01639     cpl_vector_delete(snr);
01640     cpl_vector_delete(fl_noise);
01641 
01642     return cpl_error_get_code();
01643 }
01644 
01645 
01646 /*----------------------------------------------------------------------------*/
01657 /*----------------------------------------------------------------------------*/
01658 static cpl_error_code visir_get_filter_infos(
01659         const char  *   f,
01660         double      *   pcwlen,
01661         double      *   pdwlen)
01662 {
01663 
01664     double cwlen = -1;
01665     double dwlen = -1;
01666 
01667 
01668     skip_if (f      == NULL);
01669     skip_if (pcwlen == NULL);
01670     skip_if (pdwlen == NULL);
01671 
01672     skip_if (!strcmp(f, "MV"));
01673 
01674     if (!strcmp(f, "N-BAND")) { cwlen = 10.56;dwlen = 5.37;}
01675     else if (!strcmp(f, "SIC"))    { cwlen = 11.848;dwlen = 2.34;}
01676     else if (!strcmp(f, "PAH1_1")) { cwlen = 8.19;dwlen = 0.15;}
01677     else if (!strcmp(f, "PAH1"))   { cwlen = 8.586;dwlen = 0.421;}
01678     else if (!strcmp(f, "ARIII"))  { cwlen = 8.992;dwlen = 0.138;}
01679     else if (!strcmp(f, "SIV_1"))  { cwlen = 10.02;dwlen = 0.18;}
01680     else if (!strcmp(f, "SIV"))    { cwlen = 10.485;dwlen = 0.159;}
01681     else if (!strcmp(f, "PAH2_1")) { cwlen = 10.76;dwlen = 0.69;}
01682     else if (!strcmp(f, "SIV_2"))  { cwlen = 11.1;dwlen = 0.19;}
01683     else if (!strcmp(f, "PAH2"))   { cwlen = 11.254;dwlen = 0.594;}
01684     else if (!strcmp(f, "PAH2_2")) { cwlen = 12.13;dwlen = 0.37;}
01685     else if (!strcmp(f, "NEII_1")) { cwlen = 12.51;dwlen = 0.18;}
01686     else if (!strcmp(f, "NEII"))   { cwlen = 12.805;dwlen = 0.21;}
01687     else if (!strcmp(f, "NEII_2")) { cwlen = 13.036;dwlen = 0.219;}
01688     else if (!strcmp(f, "Q0"))     { cwlen = 16.554;dwlen = 0.398;}
01689     else if (!strcmp(f, "QH2"))    { cwlen = 17.11;dwlen = 0.398;}
01690     else if (!strcmp(f, "Q1"))     { cwlen = 17.653;dwlen = 0.83;}
01691     else if (!strcmp(f, "Q2"))     { cwlen = 18.718;dwlen = 0.878;}
01692     else if (!strcmp(f, "Q3"))     { cwlen = 19.5;dwlen = 0.4;}
01693     else if (!strcmp(f, "Q4"))     { cwlen = 20.5;dwlen = 1.0;}
01694     else if (!strcmp(f, "Q7"))     { cwlen = 23.1;dwlen = 0.8;}
01695     else if (!strcmp(f, "Q8"))     { cwlen = 24.5;dwlen = 0.8;}
01696     else if (!strcmp(f, "N-SW-spec"))   { cwlen = 8.85;dwlen = 2.7;}
01697     else if (!strcmp(f, "H2S4-spec"))   { cwlen = 8.12;dwlen = 0.3;}
01698     else if (!strcmp(f, "ARIII-spec"))  { cwlen = 8.44;dwlen = 0.78;}
01699     else if (!strcmp(f, "NEII_2-spec")) { cwlen = 12.805;dwlen = 0.2;}
01700     else if (!strcmp(f, "H2S3-spec"))   { cwlen = 9.62;dwlen = 0.2;}
01701     else if (!strcmp(f, "H2S1-spec"))   { cwlen = 17.0;dwlen = 0.4;}
01702 
01703     /* The width of each new, below filter is the Full Width at Half Maximum */
01704 
01705     else if (!strcmp(f, "J7.9"))   { cwlen =  (7.483 +  8.035)/2.0;
01706     dwlen =  8.035 -  7.483;}
01707     else if (!strcmp(f, "J8.9"))   { cwlen =  (8.338 +  9.068)/2.0;
01708     dwlen =  9.068 -  8.338;}
01709     else if (!strcmp(f, "J9.8"))   { cwlen =  (9.123 + 10.059)/2.0;
01710     dwlen = 10.059 -  9.123;}
01711     else if (!strcmp(f, "J12.2"))  { cwlen = (11.700 + 12.216)/2.0;
01712     dwlen = 12.216 - 11.700;}
01713     else if (!strcmp(f, "B8.7"))   { cwlen =  (8.436 +  9.410)/2.0;
01714     dwlen =  9.410 -  8.436;}
01715     else if (!strcmp(f, "B9.7"))   { cwlen =  (9.402 + 10.242)/2.0;
01716     dwlen = 10.242 -  9.402;}
01717     else if (!strcmp(f, "B10.7"))  { cwlen =  (9.970 + 11.338)/2.0;
01718     dwlen = 11.338 -  9.970;}
01719     else if (!strcmp(f, "B11.7"))  { cwlen = (11.098 + 11.950)/2.0;
01720     dwlen = 11.950 - 11.098;}
01721     else if (!strcmp(f, "B12.4"))  { cwlen = (11.971 + 12.961)/2.0;
01722     dwlen = 12.961 - 11.971;}
01723 
01724     *pcwlen = cwlen;
01725     *pdwlen = dwlen;
01726 
01727     skip_if (cwlen <= 0);
01728     skip_if (dwlen <= 0);
01729 
01730     end_skip;
01731 
01732     return cpl_error_get_code();
01733 }
01734 
01735 /*----------------------------------------------------------------------------*/
01743 /*----------------------------------------------------------------------------*/
01744 static cpl_error_code visir_img_phot_qc(cpl_propertylist       * qclist,
01745                                         cpl_boolean              drop_wcs,
01746                                         const irplib_framelist * rawframes)
01747 {
01748 
01749     const cpl_propertylist * reflist
01750         = irplib_framelist_get_propertylist_const(rawframes, 0);
01751 
01752 
01753     /* QC.EXPTIME */
01754     bug_if (cpl_propertylist_append_double(qclist, "ESO QC EXPTIME", 
01755             visir_img_phot_config.exptime));
01756     /* QC.JYVAL */
01757     bug_if (cpl_propertylist_append_double(qclist, "ESO QC JYVAL", 
01758             visir_img_phot_config.jy_val));
01759     /* QC.STARNAME */
01760     bug_if (cpl_propertylist_append_string(qclist, "ESO QC STARNAME",
01761             visir_img_phot_config.star_name));
01762     /* QC.FILTER */
01763     bug_if (cpl_propertylist_append_string(qclist, "ESO QC FILTER",
01764             visir_img_phot_config.filter));
01765 
01766     /* QC.BACKGD.SIGMA */
01767     bug_if (cpl_propertylist_append_double(qclist, "ESO QC BACKGD SIGMA",
01768             visir_img_phot_config.bg_sigma));
01769     /* QC.FLUXTOT */
01770     bug_if (cpl_propertylist_append_double(qclist, "ESO QC FLUXTOT",
01771             visir_img_phot_config.flux_tot));
01772     /* QC.FLUXSNR */
01773     bug_if (cpl_propertylist_append_double(qclist, "ESO QC FLUXSNR",
01774             visir_img_phot_config.flux_snr));
01775     /* QC.FLUXSNR.NOISE */
01776     bug_if (cpl_propertylist_append_double(qclist, "ESO QC FLUXSNR NOISE",
01777             visir_img_phot_config.flux_snr_noise));
01778     /* QC.FWHMX */
01779     bug_if (cpl_propertylist_append_double(qclist, "ESO QC FWHMX",
01780             visir_img_phot_config.fwhm_x));
01781     /* QC.FWHMY */
01782     bug_if (cpl_propertylist_append_double(qclist, "ESO QC FWHMY",
01783             visir_img_phot_config.fwhm_y));
01784     /* QC.FWHMX.POS1 */
01785     bug_if (cpl_propertylist_append_double(qclist, "ESO QC FWHMX POS1",
01786             visir_img_phot_config.fwhm_x_pos1));
01787     /* QC.FWHMY.POS1 */
01788     bug_if (cpl_propertylist_append_double(qclist, "ESO QC FWHMY POS1",
01789             visir_img_phot_config.fwhm_y_pos1));
01790     /* QC.FWHMX.POS2 */
01791     bug_if (cpl_propertylist_append_double(qclist, "ESO QC FWHMX POS2",
01792             visir_img_phot_config.fwhm_x_pos2));
01793     /* QC.FWHMY.POS2 */
01794     bug_if (cpl_propertylist_append_double(qclist, "ESO QC FWHMY POS2",
01795             visir_img_phot_config.fwhm_y_pos2));
01796     /* QC.FWHMX.NEG1 */
01797     bug_if (cpl_propertylist_append_double(qclist, "ESO QC FWHMX NEG1",
01798             visir_img_phot_config.fwhm_x_neg1));
01799     /* QC.FWHMY.NEG1 */
01800     bug_if (cpl_propertylist_append_double(qclist, "ESO QC FWHMY NEG1",
01801             visir_img_phot_config.fwhm_y_neg1));
01802     /* QC.FWHMX.NEG2 */
01803     bug_if (cpl_propertylist_append_double(qclist, "ESO QC FWHMX NEG2",
01804             visir_img_phot_config.fwhm_x_neg2));
01805     /* QC.FWHMY.NEG2 */
01806     bug_if (cpl_propertylist_append_double(qclist, "ESO QC FWHMY NEG2",
01807             visir_img_phot_config.fwhm_y_neg2));
01808     /* QC.SENSIT */
01809     bug_if (cpl_propertylist_append_double(qclist, "ESO QC SENSIT",
01810             visir_img_phot_config.sensitivity));
01811     /* QC.CONVER */
01812     bug_if (cpl_propertylist_append_double(qclist, "ESO QC CONVER",
01813             visir_img_phot_config.conversion));
01814     /* QC.STREHL */
01815     bug_if (cpl_propertylist_append_double(qclist, "ESO QC STREHL",
01816             visir_img_phot_config.strehl));
01817     /* QC.STREHL.ERROR */
01818     bug_if (cpl_propertylist_append_double(qclist, "ESO QC STREHL ERROR",
01819             visir_img_phot_config.strehl_err));
01820 
01821     /* QC.CAPA */
01822     skip_if (visir_qc_append_capa(qclist, rawframes));
01823 
01824     if (drop_wcs) {
01825         cpl_propertylist * pcopy = cpl_propertylist_new();
01826         const cpl_error_code error
01827             = cpl_propertylist_copy_property_regexp(pcopy, reflist, "^("
01828                                                     IRPLIB_PFITS_WCS_REGEXP
01829                                                     ")$", 0);
01830         if (!error && cpl_propertylist_get_size(pcopy) > 0) {
01831             cpl_msg_warning(cpl_func, "Combined image will have no WCS "
01832                             "coordinates");
01833         }
01834         cpl_propertylist_delete(pcopy);
01835         bug_if(0);
01836 
01837         bug_if(cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
01838                                                      VISIR_PFITS_IMG_PHOT_COPY
01839                                                      ")$", 0));
01840     } else {
01841         bug_if(cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
01842                                                      VISIR_PFITS_IMG_PHOT_COPY
01843                                                      "|" IRPLIB_PFITS_WCS_REGEXP
01844                                                      ")$", 0));
01845     }
01846 
01847     bug_if (irplib_pfits_set_airmass(qclist, rawframes));
01848 
01849     end_skip;
01850     
01851     return cpl_error_get_code();
01852 
01853 }
01854  
01855 /*----------------------------------------------------------------------------*/
01867 /*----------------------------------------------------------------------------*/
01868 static cpl_error_code visir_img_phot_save(cpl_frameset            * self,
01869                                           const cpl_parameterlist * parlist,
01870                                           const cpl_propertylist  * qclist,
01871                                           const cpl_image         * combined,
01872                                           const cpl_image         * contrib,
01873                                           const cpl_image         * beam1,
01874                                           const cpl_image         * beam1i)
01875 {
01876 
01877     cpl_propertylist * xtlist = cpl_propertylist_new();
01878 
01879     bug_if (0);
01880 
01881     /* SAVE THE COMBINED IMAGE */
01882     skip_if (irplib_dfs_save_image(self, parlist, self, combined,
01883                                    CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
01884                                    VISIR_IMG_PHOT_COMBINED_PROCATG,
01885                                    qclist, NULL, visir_pipe_id,
01886                                    RECIPE_STRING CPL_DFS_FITS));
01887 
01888     /* THE CONTRIBUTION MAP */
01889     bug_if(cpl_propertylist_append_string(xtlist, "EXTNAME",
01890                                           "Contribution Map"));
01891     skip_if (cpl_image_save(contrib, RECIPE_STRING CPL_DFS_FITS,
01892                             CPL_BPP_16_UNSIGNED, xtlist, CPL_IO_EXTEND));
01893 
01894     if (beam1 != NULL) {
01895         /* THE BEAM COLLAPSED IMAGE */
01896         skip_if (irplib_dfs_save_image(self, parlist, self, beam1,
01897                                        CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
01898                                        VISIR_IMG_PHOT_ONEBEAM_PROCATG, qclist,
01899                                        NULL, visir_pipe_id,
01900                                        RECIPE_STRING "_onebeam" CPL_DFS_FITS));
01901 
01902         /* THE BEAM COLLAPSED CONTRIBUTION MAP */
01903         skip_if (cpl_image_save(beam1i, RECIPE_STRING "_onebeam" CPL_DFS_FITS,
01904                                 CPL_BPP_8_UNSIGNED, xtlist, CPL_IO_EXTEND));
01905     }
01906 
01907     end_skip;
01908 
01909     cpl_propertylist_delete(xtlist);
01910 
01911     return cpl_error_get_code();
01912 
01913 }

Generated on Thu Mar 24 11:59:39 2011 for VISIR Pipeline Reference Manual by  doxygen 1.5.8