visir_img_phot.c

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

Generated on Mon Feb 6 15:23:49 2012 for VISIR Pipeline Reference Manual by  doxygen 1.5.8